summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:11:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:12:43 +0000
commitcf94bdc0742c13e2a0cac864c478b8626b266e1b (patch)
tree044670aa50cc5e2b4229aa0b6b3df6676730c0a6
parentAdding debian version 1.65.0+dfsg1-2. (diff)
downloadrustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.tar.xz
rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.zip
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--COPYRIGHT432
-rw-r--r--Cargo.lock344
-rw-r--r--RELEASES.md96
-rw-r--r--compiler/rustc/src/main.rs4
-rw-r--r--compiler/rustc_ast/Cargo.toml1
-rw-r--r--compiler/rustc_ast/src/ast.rs43
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs17
-rw-r--r--compiler/rustc_ast/src/token.rs49
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs150
-rw-r--r--compiler/rustc_ast/src/util/parser.rs4
-rw-r--r--compiler/rustc_ast/src/visit.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs23
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs236
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs87
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs22
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs99
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs158
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs10
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs127
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs127
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs291
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml1
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs14
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs2
-rw-r--r--compiler/rustc_attr/Cargo.toml1
-rw-r--r--compiler/rustc_attr/src/lib.rs1
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs161
-rw-r--r--compiler/rustc_borrowck/Cargo.toml1
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs12
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs9
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs152
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs148
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs156
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs16
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs12
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs109
-rw-r--r--compiler/rustc_borrowck/src/lib.rs22
-rw-r--r--compiler/rustc_borrowck/src/nll.rs14
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs13
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs1
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs41
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs374
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs32
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs71
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs17
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs17
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs39
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs156
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs19
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs24
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs10
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs73
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs20
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs13
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs16
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs1949
-rw-r--r--compiler/rustc_builtin_macros/src/format/ast.rs240
-rw-r--r--compiler/rustc_builtin_macros/src/format/expand.rs353
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs39
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs15
-rw-r--r--compiler/rustc_codegen_cranelift/.github/workflows/main.yml99
-rw-r--r--compiler/rustc_codegen_cranelift/.vscode/settings.json6
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.lock62
-rw-r--r--compiler/rustc_codegen_cranelift/Cargo.toml14
-rw-r--r--compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock38
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs52
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/abi_checker.rs60
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_backend.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs13
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/config.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/mod.rs21
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/prepare.rs186
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/rustc_info.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/tests.rs179
-rw-r--r--compiler/rustc_codegen_cranelift/build_system/utils.rs46
-rwxr-xr-xcompiler/rustc_codegen_cranelift/clean_all.sh6
-rw-r--r--compiler/rustc_codegen_cranelift/config.txt2
-rw-r--r--compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs6
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/std_example.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch29
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch36
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0001-portable-simd-Disable-unsupported-tests.patch96
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch47
-rw-r--r--compiler/rustc_codegen_cranelift/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh6
-rwxr-xr-xcompiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh8
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs53
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/allocator.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/archive.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs26
-rw-r--r--compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs17
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs112
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs51
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs7
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs62
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs128
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs14
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/num.rs61
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs40
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs56
-rw-r--r--compiler/rustc_codegen_cranelift/src/vtable.rs26
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/archive.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs5
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs37
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs24
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs242
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs19
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs204
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs17
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/asm.rs9
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int.rs2
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/back/archive.rs67
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs99
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs261
-rw-r--r--compiler/rustc_codegen_llvm/src/base.rs13
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs56
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs26
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs52
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs110
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs36
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs241
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs151
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs63
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs112
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs356
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs104
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs20
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs28
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs208
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/abi.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/misc.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs7
-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/src/const_eval/error.rs78
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs52
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs16
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs8
-rw-r--r--compiler/rustc_const_eval/src/const_eval/valtrees.rs4
-rw-r--r--compiler/rustc_const_eval/src/errors.rs104
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs108
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs75
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs25
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs9
-rw-r--r--compiler/rustc_const_eval/src/lib.rs10
-rw-r--r--compiler/rustc_const_eval/src/might_permit_raw_init.rs44
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs81
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs20
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs12
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs64
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/resolver.rs6
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs9
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs45
-rw-r--r--compiler/rustc_const_eval/src/util/might_permit_raw_init.rs151
-rw-r--r--compiler/rustc_const_eval/src/util/mod.rs2
-rw-r--r--compiler/rustc_data_structures/Cargo.toml1
-rw-r--r--compiler/rustc_data_structures/src/flock/linux.rs7
-rw-r--r--compiler/rustc_data_structures/src/graph/vec_graph/mod.rs4
-rw-r--r--compiler/rustc_data_structures/src/lib.rs3
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs37
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/tests.rs8
-rw-r--r--compiler/rustc_data_structures/src/profiling.rs64
-rw-r--r--compiler/rustc_data_structures/src/sorted_map.rs17
-rw-r--r--compiler/rustc_data_structures/src/sso/set.rs2
-rw-r--r--compiler/rustc_data_structures/src/transitive_relation.rs12
-rw-r--r--compiler/rustc_data_structures/src/unord.rs382
-rw-r--r--compiler/rustc_driver/Cargo.toml2
-rw-r--r--compiler/rustc_driver/src/lib.rs61
-rw-r--r--compiler/rustc_driver/src/pretty.rs4
-rw-r--r--compiler/rustc_driver/src/session_diagnostics.rs30
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0045.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0092.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0094.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0161.md7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0210.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0211.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0311.md42
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0579.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0591.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0622.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0732.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0743.md2
-rw-r--r--compiler/rustc_error_messages/Cargo.toml1
-rw-r--r--compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl4
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl68
-rw-r--r--compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl121
-rw-r--r--compiler/rustc_error_messages/locales/en-US/compiletest.ftl5
-rw-r--r--compiler/rustc_error_messages/locales/en-US/errors.ftl13
-rw-r--r--compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl (renamed from compiler/rustc_error_messages/locales/en-US/typeck.ftl)83
-rw-r--r--compiler/rustc_error_messages/locales/en-US/infer.ftl4
-rw-r--r--compiler/rustc_error_messages/locales/en-US/lint.ftl7
-rw-r--r--compiler/rustc_error_messages/locales/en-US/metadata.ftl2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/middle.ftl12
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parser.ftl217
-rw-r--r--compiler/rustc_error_messages/locales/en-US/passes.ftl563
-rw-r--r--compiler/rustc_error_messages/locales/en-US/privacy.ftl2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/query_system.ftl5
-rw-r--r--compiler/rustc_error_messages/locales/en-US/session.ftl20
-rw-r--r--compiler/rustc_error_messages/src/lib.rs77
-rw-r--r--compiler/rustc_errors/Cargo.toml3
-rw-r--r--compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs4
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs262
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs99
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs222
-rw-r--r--compiler/rustc_errors/src/emitter.rs4
-rw-r--r--compiler/rustc_errors/src/json.rs4
-rw-r--r--compiler/rustc_errors/src/lib.rs81
-rw-r--r--compiler/rustc_errors/src/translation.rs34
-rw-r--r--compiler/rustc_expand/src/base.rs59
-rw-r--r--compiler/rustc_expand/src/build.rs4
-rw-r--r--compiler/rustc_expand/src/config.rs10
-rw-r--r--compiler/rustc_expand/src/errors.rs26
-rw-r--r--compiler/rustc_expand/src/expand.rs72
-rw-r--r--compiler/rustc_expand/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs26
-rw-r--r--compiler/rustc_expand/src/placeholders.rs8
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs146
-rw-r--r--compiler/rustc_expand/src/tokenstream/tests.rs18
-rw-r--r--compiler/rustc_feature/Cargo.toml1
-rw-r--r--compiler/rustc_feature/src/accepted.rs6
-rw-r--r--compiler/rustc_feature/src/active.rs10
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs43
-rw-r--r--compiler/rustc_hir/Cargo.toml1
-rw-r--r--compiler/rustc_hir/src/def.rs125
-rw-r--r--compiler/rustc_hir/src/hir.rs97
-rw-r--r--compiler/rustc_hir/src/hir_id.rs60
-rw-r--r--compiler/rustc_hir/src/intravisit.rs20
-rw-r--r--compiler/rustc_hir/src/lib.rs3
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs10
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml (renamed from compiler/rustc_typeck/Cargo.toml)3
-rw-r--r--compiler/rustc_hir_analysis/README.md (renamed from compiler/rustc_typeck/README.md)0
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs (renamed from compiler/rustc_typeck/src/astconv/errors.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/generics.rs (renamed from compiler/rustc_typeck/src/astconv/generics.rs)15
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs (renamed from compiler/rustc_typeck/src/astconv/mod.rs)214
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs (renamed from compiler/rustc_typeck/src/bounds.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs (renamed from compiler/rustc_typeck/src/check/check.rs)588
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_method.rs (renamed from compiler/rustc_typeck/src/check/compare_method.rs)1099
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs (renamed from compiler/rustc_typeck/src/check/dropck.rs)12
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs (renamed from compiler/rustc_typeck/src/check/intrinsic.rs)32
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs (renamed from compiler/rustc_typeck/src/check/intrinsicck.rs)112
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs (renamed from compiler/rustc_typeck/src/check/mod.rs)504
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs (renamed from compiler/rustc_typeck/src/check/region.rs)8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs (renamed from compiler/rustc_typeck/src/check/wfcheck.rs)195
-rw-r--r--compiler/rustc_hir_analysis/src/check_unused.rs (renamed from compiler/rustc_typeck/src/check_unused.rs)31
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs572
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs (renamed from compiler/rustc_typeck/src/coherence/inherent_impls.rs)18
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs (renamed from compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs)58
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs (renamed from compiler/rustc_typeck/src/coherence/mod.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs (renamed from compiler/rustc_typeck/src/coherence/orphan.rs)38
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/unsafety.rs (renamed from compiler/rustc_typeck/src/coherence/unsafety.rs)32
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs (renamed from compiler/rustc_typeck/src/collect.rs)1302
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs481
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs (renamed from compiler/rustc_typeck/src/collect/item_bounds.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/collect/lifetimes.rs (renamed from compiler/rustc_resolve/src/late/lifetimes.rs)139
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs707
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs (renamed from compiler/rustc_typeck/src/collect/type_of.rs)128
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs (renamed from compiler/rustc_typeck/src/constrained_generic_params.rs)10
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs (renamed from compiler/rustc_typeck/src/errors.rs)233
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs (renamed from compiler/rustc_typeck/src/hir_wf_check.rs)58
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs (renamed from compiler/rustc_typeck/src/impl_wf_check.rs)43
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs (renamed from compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs)98
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs (renamed from compiler/rustc_typeck/src/lib.rs)81
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs (renamed from compiler/rustc_typeck/src/outlives/explicit.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs (renamed from compiler/rustc_typeck/src/outlives/implicit_infer.rs)4
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs (renamed from compiler/rustc_typeck/src/outlives/mod.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/test.rs (renamed from compiler/rustc_typeck/src/outlives/test.rs)6
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/utils.rs (renamed from compiler/rustc_typeck/src/outlives/utils.rs)17
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors.rs (renamed from compiler/rustc_typeck/src/structured_errors.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs (renamed from compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs (renamed from compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs (renamed from compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs (renamed from compiler/rustc_typeck/src/variance/constraints.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs (renamed from compiler/rustc_typeck/src/variance/mod.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/variance/solve.rs (renamed from compiler/rustc_typeck/src/variance/solve.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/variance/terms.rs (renamed from compiler/rustc_typeck/src/variance/terms.rs)0
-rw-r--r--compiler/rustc_hir_analysis/src/variance/test.rs (renamed from compiler/rustc_typeck/src/variance/test.rs)7
-rw-r--r--compiler/rustc_hir_analysis/src/variance/xform.rs (renamed from compiler/rustc_typeck/src/variance/xform.rs)0
-rw-r--r--compiler/rustc_hir_pretty/Cargo.toml1
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs8
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml28
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs (renamed from compiler/rustc_typeck/src/check/_match.rs)19
-rw-r--r--compiler/rustc_hir_typeck/src/autoderef.rs (renamed from compiler/rustc_typeck/src/check/autoderef.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs (renamed from compiler/rustc_typeck/src/check/callee.rs)401
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs (renamed from compiler/rustc_typeck/src/check/cast.rs)174
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs324
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs (renamed from compiler/rustc_typeck/src/check/closure.rs)37
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs (renamed from compiler/rustc_typeck/src/check/coercion.rs)83
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs (renamed from compiler/rustc_typeck/src/check/demand.rs)135
-rw-r--r--compiler/rustc_hir_typeck/src/diverges.rs (renamed from compiler/rustc_typeck/src/check/diverges.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs126
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs (renamed from compiler/rustc_typeck/src/check/expectation.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs (renamed from compiler/rustc_typeck/src/check/expr.rs)118
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs (renamed from compiler/rustc_typeck/src/expr_use_visitor.rs)15
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs (renamed from compiler/rustc_typeck/src/check/fallback.rs)4
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs (renamed from compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs)116
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs (renamed from compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs (renamed from compiler/rustc_typeck/src/check/fn_ctxt/checks.rs)72
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs (renamed from compiler/rustc_typeck/src/check/fn_ctxt/mod.rs)26
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs (renamed from compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs)199
-rw-r--r--compiler/rustc_hir_typeck/src/gather_locals.rs (renamed from compiler/rustc_typeck/src/check/gather_locals.rs)3
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs (renamed from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs)2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs (renamed from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs (renamed from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs (renamed from compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs)2
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs (renamed from compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs)15
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs (renamed from compiler/rustc_typeck/src/check/generator_interior.rs)49
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs (renamed from compiler/rustc_typeck/src/check/inherited.rs)38
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs108
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs507
-rw-r--r--compiler/rustc_hir_typeck/src/mem_categorization.rs (renamed from compiler/rustc_typeck/src/mem_categorization.rs)24
-rw-r--r--compiler/rustc_hir_typeck/src/method/confirm.rs (renamed from compiler/rustc_typeck/src/check/method/confirm.rs)6
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs (renamed from compiler/rustc_typeck/src/check/method/mod.rs)5
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs (renamed from compiler/rustc_typeck/src/check/method/prelude2021.rs)121
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs (renamed from compiler/rustc_typeck/src/check/method/probe.rs)163
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs (renamed from compiler/rustc_typeck/src/check/method/suggest.rs)388
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs (renamed from compiler/rustc_typeck/src/check/op.rs)15
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs (renamed from compiler/rustc_typeck/src/check/pat.rs)10
-rw-r--r--compiler/rustc_hir_typeck/src/place_op.rs (renamed from compiler/rustc_typeck/src/check/place_op.rs)4
-rw-r--r--compiler/rustc_hir_typeck/src/rvalue_scopes.rs (renamed from compiler/rustc_typeck/src/check/rvalue_scopes.rs)0
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs (renamed from compiler/rustc_typeck/src/check/upvar.rs)28
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs (renamed from compiler/rustc_typeck/src/check/writeback.rs)79
-rw-r--r--compiler/rustc_incremental/Cargo.toml1
-rw-r--r--compiler/rustc_incremental/src/lib.rs1
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs10
-rw-r--r--compiler/rustc_index/Cargo.toml1
-rw-r--r--compiler/rustc_index/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs178
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs15
-rw-r--r--compiler/rustc_infer/src/infer/at.rs7
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs6
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs20
-rw-r--r--compiler/rustc_infer/src/infer/combine.rs57
-rw-r--r--compiler/rustc_infer/src/infer/equate.rs19
-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.rs88
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs18
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs18
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs31
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs7
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs31
-rw-r--r--compiler/rustc_infer/src/infer/freshen.rs4
-rw-r--r--compiler/rustc_infer/src/infer/fudge.rs4
-rw-r--r--compiler/rustc_infer/src/infer/glb.rs2
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs4
-rw-r--r--compiler/rustc_infer/src/infer/lattice.rs2
-rw-r--r--compiler/rustc_infer/src/infer/lub.rs2
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs300
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs27
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs53
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs17
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs12
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs150
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs111
-rw-r--r--compiler/rustc_infer/src/infer/projection.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/resolve.rs25
-rw-r--r--compiler/rustc_infer/src/infer/sub.rs61
-rw-r--r--compiler/rustc_infer/src/lib.rs5
-rw-r--r--compiler/rustc_infer/src/traits/engine.rs15
-rw-r--r--compiler/rustc_infer/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs10
-rw-r--r--compiler/rustc_infer/src/traits/structural_impls.rs1
-rw-r--r--compiler/rustc_infer/src/traits/util.rs12
-rw-r--r--compiler/rustc_interface/Cargo.toml4
-rw-r--r--compiler/rustc_interface/src/errors.rs58
-rw-r--r--compiler/rustc_interface/src/interface.rs109
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/passes.rs23
-rw-r--r--compiler/rustc_interface/src/proc_macro_decls.rs5
-rw-r--r--compiler/rustc_interface/src/queries.rs4
-rw-r--r--compiler/rustc_interface/src/tests.rs43
-rw-r--r--compiler/rustc_interface/src/util.rs122
-rw-r--r--compiler/rustc_lexer/Cargo.toml1
-rw-r--r--compiler/rustc_lexer/src/cursor.rs16
-rw-r--r--compiler/rustc_lexer/src/lib.rs76
-rw-r--r--compiler/rustc_lexer/src/unescape.rs27
-rw-r--r--compiler/rustc_lint/Cargo.toml2
-rw-r--r--compiler/rustc_lint/src/array_into_iter.rs62
-rw-r--r--compiler/rustc_lint/src/builtin.rs896
-rw-r--r--compiler/rustc_lint/src/context.rs91
-rw-r--r--compiler/rustc_lint/src/early.rs8
-rw-r--r--compiler/rustc_lint/src/enum_intrinsics_non_enums.rs26
-rw-r--r--compiler/rustc_lint/src/errors.rs90
-rw-r--r--compiler/rustc_lint/src/expect.rs14
-rw-r--r--compiler/rustc_lint/src/for_loops_over_fallibles.rs183
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs94
-rw-r--r--compiler/rustc_lint/src/internal.rs215
-rw-r--r--compiler/rustc_lint/src/late.rs25
-rw-r--r--compiler/rustc_lint/src/let_underscore.rs67
-rw-r--r--compiler/rustc_lint/src/levels.rs957
-rw-r--r--compiler/rustc_lint/src/lib.rs15
-rw-r--r--compiler/rustc_lint/src/methods.rs19
-rw-r--r--compiler/rustc_lint/src/non_ascii_idents.rs68
-rw-r--r--compiler/rustc_lint/src/non_fmt_panic.rs113
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs111
-rw-r--r--compiler/rustc_lint/src/noop_method_call.rs27
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs163
-rw-r--r--compiler/rustc_lint/src/pass_by_value.rs18
-rw-r--r--compiler/rustc_lint/src/redundant_semicolon.rs19
-rw-r--r--compiler/rustc_lint/src/traits.rs36
-rw-r--r--compiler/rustc_lint/src/types.rs389
-rw-r--r--compiler/rustc_lint/src/unused.rs169
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs37
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs34
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp260
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp47
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs197
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs743
-rw-r--r--compiler/rustc_macros/src/diagnostics/fluent.rs65
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs36
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs492
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs421
-rw-r--r--compiler/rustc_macros/src/lib.rs5
-rw-r--r--compiler/rustc_macros/src/query.rs52
-rw-r--r--compiler/rustc_metadata/Cargo.toml1
-rw-r--r--compiler/rustc_metadata/src/errors.rs384
-rw-r--r--compiler/rustc_metadata/src/foreign_modules.rs6
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs41
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs79
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs27
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs518
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs10
-rw-r--r--compiler/rustc_middle/Cargo.toml2
-rw-r--r--compiler/rustc_middle/benches/lib.rs54
-rw-r--r--compiler/rustc_middle/src/arena.rs5
-rw-r--r--compiler/rustc_middle/src/dep_graph/dep_node.rs152
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs52
-rw-r--r--compiler/rustc_middle/src/error.rs27
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs129
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs36
-rw-r--r--compiler/rustc_middle/src/infer/unify_key.rs2
-rw-r--r--compiler/rustc_middle/src/lib.rs6
-rw-r--r--compiler/rustc_middle/src/lint.rs329
-rw-r--r--compiler/rustc_middle/src/macros.rs13
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs2
-rw-r--r--compiler/rustc_middle/src/middle/privacy.rs214
-rw-r--r--compiler/rustc_middle/src/middle/resolve_lifetime.rs15
-rw-r--r--compiler/rustc_middle/src/middle/stability.rs11
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs19
-rw-r--r--compiler/rustc_middle/src/mir/interpret/pointer.rs2
-rw-r--r--compiler/rustc_middle/src/mir/interpret/queries.rs42
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs114
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs6
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs3
-rw-r--r--compiler/rustc_middle/src/mir/query.rs9
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs26
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs5
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs28
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs19
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs7
-rw-r--r--compiler/rustc_middle/src/query/mod.rs302
-rw-r--r--compiler/rustc_middle/src/thir.rs9
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs16
-rw-r--r--compiler/rustc_middle/src/traits/query.rs4
-rw-r--r--compiler/rustc_middle/src/traits/select.rs12
-rw-r--r--compiler/rustc_middle/src/traits/structural_impls.rs2
-rw-r--r--compiler/rustc_middle/src/ty/abstract_const.rs12
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs3
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs27
-rw-r--r--compiler/rustc_middle/src/ty/cast.rs28
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs1
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs52
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs52
-rw-r--r--compiler/rustc_middle/src/ty/context.rs176
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/erase_regions.rs5
-rw-r--r--compiler/rustc_middle/src/ty/error.rs8
-rw-r--r--compiler/rustc_middle/src/ty/fast_reject.rs11
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs18
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs40
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs3
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs145
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs204
-rw-r--r--compiler/rustc_middle/src/ty/inhabitedness/mod.rs258
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs6
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2375
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs141
-rw-r--r--compiler/rustc_middle/src/ty/normalize_erasing_regions.rs24
-rw-r--r--compiler/rustc_middle/src/ty/opaque_types.rs218
-rw-r--r--compiler/rustc_middle/src/ty/parameterized.rs7
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs13
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs230
-rw-r--r--compiler/rustc_middle/src/ty/query.rs24
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs14
-rw-r--r--compiler/rustc_middle/src/ty/rvalue_scopes.rs2
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs55
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs150
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs134
-rw-r--r--compiler/rustc_middle/src/ty/util.rs41
-rw-r--r--compiler/rustc_middle/src/ty/visit.rs32
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs16
-rw-r--r--compiler/rustc_middle/src/values.rs180
-rw-r--r--compiler/rustc_mir_build/Cargo.toml1
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs37
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs7
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_operand.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_place.rs76
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs24
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_temp.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs96
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs35
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs25
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs51
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs132
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs4
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs30
-rw-r--r--compiler/rustc_mir_build/src/lib.rs2
-rw-r--r--compiler/rustc_mir_build/src/lints.rs24
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs117
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs57
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs20
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs8
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs19
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml1
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs5
-rw-r--r--compiler/rustc_mir_dataflow/src/errors.rs42
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs1
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/check_const_item_mutation.rs18
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs40
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs24
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs6
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs47
-rw-r--r--compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml1
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs248
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs14
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs22
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs3
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs47
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs24
-rw-r--r--compiler/rustc_mir_transform/src/marker.rs20
-rw-r--r--compiler/rustc_mir_transform/src/pass_manager.rs89
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml1
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs34
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs37
-rw-r--r--compiler/rustc_monomorphize/src/lib.rs1
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/default.rs6
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs53
-rw-r--r--compiler/rustc_parse/Cargo.toml1
-rw-r--r--compiler/rustc_parse/src/errors.rs1237
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs397
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs428
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs19
-rw-r--r--compiler/rustc_parse/src/lib.rs6
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs159
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs33
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs946
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs509
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs36
-rw-r--r--compiler/rustc_parse/src/parser/item.rs163
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs151
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs26
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs169
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs11
-rw-r--r--compiler/rustc_parse_format/src/lib.rs30
-rw-r--r--compiler/rustc_parse_format/src/tests.rs15
-rw-r--r--compiler/rustc_passes/src/check_attr.rs277
-rw-r--r--compiler/rustc_passes/src/check_const.rs17
-rw-r--r--compiler/rustc_passes/src/dead.rs136
-rw-r--r--compiler/rustc_passes/src/debugger_visualizer.rs15
-rw-r--r--compiler/rustc_passes/src/diagnostic_items.rs45
-rw-r--r--compiler/rustc_passes/src/entry.rs157
-rw-r--r--compiler/rustc_passes/src/errors.rs1095
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs23
-rw-r--r--compiler/rustc_passes/src/hir_stats.rs4
-rw-r--r--compiler/rustc_passes/src/lang_items.rs211
-rw-r--r--compiler/rustc_passes/src/layout_test.rs77
-rw-r--r--compiler/rustc_passes/src/lib.rs3
-rw-r--r--compiler/rustc_passes/src/lib_features.rs34
-rw-r--r--compiler/rustc_passes/src/liveness.rs65
-rw-r--r--compiler/rustc_passes/src/loops.rs161
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs88
-rw-r--r--compiler/rustc_passes/src/reachable.rs53
-rw-r--r--compiler/rustc_passes/src/stability.rs230
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs31
-rw-r--r--compiler/rustc_plugin_impl/Cargo.toml1
-rw-r--r--compiler/rustc_plugin_impl/src/errors.rs10
-rw-r--r--compiler/rustc_privacy/Cargo.toml2
-rw-r--r--compiler/rustc_privacy/src/errors.rs42
-rw-r--r--compiler/rustc_privacy/src/lib.rs342
-rw-r--r--compiler/rustc_query_impl/src/keys.rs42
-rw-r--r--compiler/rustc_query_impl/src/lib.rs13
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs13
-rw-r--r--compiler/rustc_query_impl/src/plumbing.rs188
-rw-r--r--compiler/rustc_query_impl/src/profiling_support.rs25
-rw-r--r--compiler/rustc_query_system/Cargo.toml1
-rw-r--r--compiler/rustc_query_system/src/dep_graph/dep_node.rs73
-rw-r--r--compiler/rustc_query_system/src/dep_graph/mod.rs45
-rw-r--r--compiler/rustc_query_system/src/error.rs73
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs11
-rw-r--r--compiler/rustc_query_system/src/lib.rs5
-rw-r--r--compiler/rustc_query_system/src/query/config.rs2
-rw-r--r--compiler/rustc_query_system/src/query/job.rs33
-rw-r--r--compiler/rustc_query_system/src/query/mod.rs15
-rw-r--r--compiler/rustc_query_system/src/query/plumbing.rs11
-rw-r--r--compiler/rustc_query_system/src/values.rs5
-rw-r--r--compiler/rustc_resolve/Cargo.toml1
-rw-r--r--compiler/rustc_resolve/src/access_levels.rs185
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs7
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs2
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs27
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs139
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs188
-rw-r--r--compiler/rustc_resolve/src/ident.rs22
-rw-r--r--compiler/rustc_resolve/src/imports.rs32
-rw-r--r--compiler/rustc_resolve/src/late.rs366
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs859
-rw-r--r--compiler/rustc_resolve/src/lib.rs82
-rw-r--r--compiler/rustc_resolve/src/macros.rs25
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs83
-rw-r--r--compiler/rustc_save_analysis/src/errors.rs6
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs32
-rw-r--r--compiler/rustc_save_analysis/src/sig.rs12
-rw-r--r--compiler/rustc_serialize/src/lib.rs1
-rw-r--r--compiler/rustc_serialize/src/opaque.rs4
-rw-r--r--compiler/rustc_session/src/config.rs6
-rw-r--r--compiler/rustc_session/src/config/sigpipe.rs13
-rw-r--r--compiler/rustc_session/src/errors.rs198
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/options.rs123
-rw-r--r--compiler/rustc_session/src/parse.rs46
-rw-r--r--compiler/rustc_session/src/session.rs191
-rw-r--r--compiler/rustc_session/src/utils.rs11
-rw-r--r--compiler/rustc_span/Cargo.toml1
-rw-r--r--compiler/rustc_span/src/def_id.rs20
-rw-r--r--compiler/rustc_span/src/lib.rs14
-rw-r--r--compiler/rustc_span/src/source_map.rs44
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs45
-rw-r--r--compiler/rustc_span/src/span_encoding.rs42
-rw-r--r--compiler/rustc_span/src/symbol.rs35
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml1
-rw-r--r--compiler/rustc_symbol_mangling/src/errors.rs6
-rw-r--r--compiler/rustc_symbol_mangling/src/test.rs8
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs4
-rw-r--r--compiler/rustc_target/Cargo.toml3
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs5
-rw-r--r--compiler/rustc_target/src/abi/mod.rs70
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs4
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs4
-rw-r--r--compiler/rustc_target/src/spec/abi.rs138
-rw-r--r--compiler/rustc_target/src/spec/android_base.rs4
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs22
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabi.rs5
-rw-r--r--compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs5
-rw-r--r--compiler/rustc_target/src/spec/armv4t_none_eabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv5te_none_eabi.rs41
-rw-r--r--compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs5
-rw-r--r--compiler/rustc_target/src/spec/armv7_linux_androideabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv7a_none_eabihf.rs4
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabi.rs5
-rw-r--r--compiler/rustc_target/src/spec/armv7r_none_eabihf.rs5
-rw-r--r--compiler/rustc_target/src/spec/avr_gnu_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/fuchsia_base.rs6
-rw-r--r--compiler/rustc_target/src/spec/hermit_base.rs6
-rw-r--r--compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs4
-rw-r--r--compiler/rustc_target/src/spec/i386_apple_ios.rs3
-rw-r--r--compiler/rustc_target/src/spec/i686_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_linux_android.rs3
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs4
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_haiku.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs8
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/i686_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/illumos_base.rs6
-rw-r--r--compiler/rustc_target/src/spec/l4re_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/linux_kernel_base.rs3
-rw-r--r--compiler/rustc_target/src/spec/mipsel_sony_psp.rs10
-rw-r--r--compiler/rustc_target/src/spec/mipsel_unknown_none.rs5
-rw-r--r--compiler/rustc_target/src/spec/mod.rs244
-rw-r--r--compiler/rustc_target/src/spec/msp430_none_elf.rs4
-rw-r--r--compiler/rustc_target/src/spec/msvc_base.rs8
-rw-r--r--compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs1
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs8
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs5
-rw-r--r--compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs4
-rw-r--r--compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs5
-rw-r--r--compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs6
-rw-r--r--compiler/rustc_target/src/spec/riscv64imac_unknown_none_elf.rs6
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs11
-rw-r--r--compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs11
-rw-r--r--compiler/rustc_target/src/spec/solaris_base.rs4
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs4
-rw-r--r--compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs4
-rw-r--r--compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs4
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs85
-rw-r--r--compiler/rustc_target/src/spec/thumb_base.rs5
-rw-r--r--compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs41
-rw-r--r--compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs4
-rw-r--r--compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/uefi_msvc_base.rs7
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs8
-rw-r--r--compiler/rustc_target/src/spec/wasm32_wasi.rs6
-rw-r--r--compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs8
-rw-r--r--compiler/rustc_target/src/spec/wasm_base.rs9
-rw-r--r--compiler/rustc_target/src/spec/windows_gnu_base.rs28
-rw-r--r--compiler/rustc_target/src/spec/windows_gnullvm_base.rs10
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs7
-rw-r--r--compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_darwin.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_tvos.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs8
-rw-r--r--compiler/rustc_target/src/spec/x86_64_fuchsia.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_linux_android.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_solaris.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_sun_solaris.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs3
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_redox.rs7
-rw-r--r--compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs9
-rw-r--r--compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/autoderef.rs4
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs46
-rw-r--r--compiler/rustc_trait_selection/src/infer.rs26
-rw-r--r--compiler/rustc_trait_selection/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs234
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/codegen.rs89
-rw-r--r--compiler/rustc_trait_selection/src/traits/coherence.rs102
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs63
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs721
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs370
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs84
-rw-r--r--compiler/rustc_trait_selection/src/traits/misc.rs111
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs175
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs176
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs142
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs54
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/relationships.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs29
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs72
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs149
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/mod.rs83
-rw-r--r--compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs46
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs220
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs20
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs7
-rw-r--r--compiler/rustc_traits/src/lib.rs1
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs46
-rw-r--r--compiler/rustc_traits/src/type_op.rs10
-rw-r--r--compiler/rustc_transmute/src/layout/tree.rs22
-rw-r--r--compiler/rustc_transmute/src/lib.rs19
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs551
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs18
-rw-r--r--compiler/rustc_ty_utils/src/common_traits.rs11
-rw-r--r--compiler/rustc_ty_utils/src/consts.rs15
-rw-r--r--compiler/rustc_ty_utils/src/errors.rs56
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs75
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs1803
-rw-r--r--compiler/rustc_ty_utils/src/layout_sanity_check.rs (renamed from compiler/rustc_middle/src/ty/layout_sanity_check.rs)2
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs10
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs5
-rw-r--r--compiler/rustc_ty_utils/src/representability.rs451
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs20
-rw-r--r--compiler/rustc_type_ir/Cargo.toml1
-rw-r--r--compiler/rustc_type_ir/src/lib.rs6
-rw-r--r--compiler/rustc_type_ir/src/sty.rs4
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs594
-rw-r--r--config.toml.example15
-rw-r--r--git-commit-hash2
-rw-r--r--git-commit-info3
-rw-r--r--library/alloc/benches/lib.rs1
-rw-r--r--library/alloc/src/alloc.rs12
-rw-r--r--library/alloc/src/borrow.rs1
-rw-r--r--library/alloc/src/boxed.rs68
-rw-r--r--library/alloc/src/boxed/thin.rs2
-rw-r--r--library/alloc/src/collections/btree/map.rs41
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs1
-rw-r--r--library/alloc/src/collections/btree/node.rs6
-rw-r--r--library/alloc/src/collections/btree/set.rs26
-rw-r--r--library/alloc/src/collections/linked_list.rs2
-rw-r--r--library/alloc/src/collections/mod.rs1
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs14
-rw-r--r--library/alloc/src/ffi/c_str.rs3
-rw-r--r--library/alloc/src/fmt.rs2
-rw-r--r--library/alloc/src/lib.rs22
-rw-r--r--library/alloc/src/raw_vec.rs12
-rw-r--r--library/alloc/src/rc.rs12
-rw-r--r--library/alloc/src/slice.rs8
-rw-r--r--library/alloc/src/string.rs34
-rw-r--r--library/alloc/src/sync.rs61
-rw-r--r--library/alloc/src/task.rs6
-rw-r--r--library/alloc/src/vec/drain.rs4
-rw-r--r--library/alloc/src/vec/in_place_collect.rs18
-rw-r--r--library/alloc/src/vec/in_place_drop.rs15
-rw-r--r--library/alloc/src/vec/into_iter.rs27
-rw-r--r--library/alloc/src/vec/is_zero.rs22
-rw-r--r--library/alloc/src/vec/mod.rs144
-rw-r--r--library/alloc/tests/autotraits.rs293
-rw-r--r--library/alloc/tests/lib.rs7
-rw-r--r--library/alloc/tests/vec.rs65
-rw-r--r--library/core/benches/iter.rs27
-rw-r--r--library/core/benches/lib.rs1
-rw-r--r--library/core/src/alloc/layout.rs5
-rw-r--r--library/core/src/alloc/mod.rs3
-rw-r--r--library/core/src/array/iter.rs59
-rw-r--r--library/core/src/array/mod.rs59
-rw-r--r--library/core/src/bool.rs23
-rw-r--r--library/core/src/borrow.rs2
-rw-r--r--library/core/src/cell.rs74
-rw-r--r--library/core/src/char/decode.rs2
-rw-r--r--library/core/src/char/methods.rs37
-rw-r--r--library/core/src/char/mod.rs2
-rw-r--r--library/core/src/cmp.rs91
-rw-r--r--library/core/src/const_closure.rs77
-rw-r--r--library/core/src/convert/mod.rs217
-rw-r--r--library/core/src/default.rs1
-rw-r--r--library/core/src/error.rs4
-rw-r--r--library/core/src/ffi/c_str.rs76
-rw-r--r--library/core/src/fmt/mod.rs9
-rw-r--r--library/core/src/fmt/num.rs92
-rw-r--r--library/core/src/future/ready.rs24
-rw-r--r--library/core/src/hint.rs7
-rw-r--r--library/core/src/intrinsics.rs146
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs18
-rw-r--r--library/core/src/iter/adapters/by_ref_sized.rs19
-rw-r--r--library/core/src/iter/adapters/copied.rs74
-rw-r--r--library/core/src/iter/adapters/map_while.rs14
-rw-r--r--library/core/src/iter/adapters/mod.rs10
-rw-r--r--library/core/src/iter/adapters/scan.rs14
-rw-r--r--library/core/src/iter/adapters/skip.rs12
-rw-r--r--library/core/src/iter/adapters/take.rs14
-rw-r--r--library/core/src/iter/adapters/take_while.rs14
-rw-r--r--library/core/src/iter/mod.rs23
-rw-r--r--library/core/src/iter/range.rs28
-rw-r--r--library/core/src/iter/traits/collect.rs3
-rw-r--r--library/core/src/iter/traits/iterator.rs170
-rw-r--r--library/core/src/lazy.rs1
-rw-r--r--library/core/src/lib.rs17
-rw-r--r--library/core/src/marker.rs125
-rw-r--r--library/core/src/mem/maybe_uninit.rs44
-rw-r--r--library/core/src/mem/mod.rs85
-rw-r--r--library/core/src/mem/transmutability.rs4
-rw-r--r--library/core/src/num/dec2flt/lemire.rs4
-rw-r--r--library/core/src/num/error.rs3
-rw-r--r--library/core/src/num/flt2dec/strategy/grisu.rs4
-rw-r--r--library/core/src/num/int_log10.rs2
-rw-r--r--library/core/src/num/int_macros.rs102
-rw-r--r--library/core/src/num/mod.rs66
-rw-r--r--library/core/src/num/nonzero.rs159
-rw-r--r--library/core/src/num/uint_macros.rs153
-rw-r--r--library/core/src/ops/arith.rs50
-rw-r--r--library/core/src/ops/bit.rs11
-rw-r--r--library/core/src/ops/control_flow.rs9
-rw-r--r--library/core/src/ops/deref.rs2
-rw-r--r--library/core/src/ops/drop.rs1
-rw-r--r--library/core/src/ops/function.rs3
-rw-r--r--library/core/src/ops/generator.rs1
-rw-r--r--library/core/src/ops/index.rs2
-rw-r--r--library/core/src/ops/index_range.rs171
-rw-r--r--library/core/src/ops/mod.rs3
-rw-r--r--library/core/src/ops/try_trait.rs106
-rw-r--r--library/core/src/option.rs46
-rw-r--r--library/core/src/panic/location.rs9
-rw-r--r--library/core/src/panicking.rs126
-rw-r--r--library/core/src/primitive_docs.rs23
-rw-r--r--library/core/src/ptr/alignment.rs (renamed from library/core/src/mem/valid_align.rs)175
-rw-r--r--library/core/src/ptr/const_ptr.rs10
-rw-r--r--library/core/src/ptr/metadata.rs14
-rw-r--r--library/core/src/ptr/mod.rs122
-rw-r--r--library/core/src/ptr/mut_ptr.rs11
-rw-r--r--library/core/src/ptr/non_null.rs6
-rw-r--r--library/core/src/result.rs34
-rw-r--r--library/core/src/slice/index.rs104
-rw-r--r--library/core/src/slice/iter.rs21
-rw-r--r--library/core/src/slice/iter/macros.rs8
-rw-r--r--library/core/src/slice/memchr.rs4
-rw-r--r--library/core/src/slice/mod.rs132
-rw-r--r--library/core/src/slice/raw.rs42
-rw-r--r--library/core/src/slice/rotate.rs4
-rw-r--r--library/core/src/slice/sort.rs6
-rw-r--r--library/core/src/str/error.rs3
-rw-r--r--library/core/src/str/mod.rs1
-rw-r--r--library/core/src/str/pattern.rs2
-rw-r--r--library/core/src/str/traits.rs18
-rw-r--r--library/core/src/sync/atomic.rs54
-rw-r--r--library/core/src/sync/exclusive.rs9
-rw-r--r--library/core/src/task/wake.rs9
-rw-r--r--library/core/src/time.rs176
-rw-r--r--library/core/src/tuple.rs3
-rw-r--r--library/core/src/unicode/printable.rs131
-rw-r--r--library/core/src/unicode/unicode_data.rs232
-rw-r--r--library/core/tests/ascii.rs18
-rw-r--r--library/core/tests/lib.rs9
-rw-r--r--library/core/tests/mem.rs12
-rw-r--r--library/core/tests/num/int_log.rs30
-rw-r--r--library/core/tests/num/mod.rs2
-rw-r--r--library/core/tests/num/wrapping.rs2
-rw-r--r--library/core/tests/option.rs1
-rw-r--r--library/core/tests/panic.rs1
-rw-r--r--library/core/tests/panic/location.rs31
-rw-r--r--library/core/tests/slice.rs1
-rw-r--r--library/core/tests/task.rs17
-rw-r--r--library/core/tests/time.rs32
-rw-r--r--library/panic_unwind/src/emcc.rs40
-rw-r--r--library/panic_unwind/src/gcc.rs30
-rw-r--r--library/panic_unwind/src/lib.rs3
-rw-r--r--library/panic_unwind/src/seh.rs20
-rw-r--r--library/proc_macro/src/bridge/client.rs4
-rw-r--r--library/proc_macro/src/lib.rs4
-rw-r--r--library/std/Cargo.toml4
-rw-r--r--library/std/src/backtrace.rs12
-rw-r--r--library/std/src/collections/hash/map.rs7
-rw-r--r--library/std/src/collections/hash/map/tests.rs6
-rw-r--r--library/std/src/collections/hash/set.rs5
-rw-r--r--library/std/src/collections/hash/set/tests.rs6
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/error.rs1023
-rw-r--r--library/std/src/fs.rs67
-rw-r--r--library/std/src/io/error.rs7
-rw-r--r--library/std/src/io/error/tests.rs2
-rw-r--r--library/std/src/io/mod.rs7
-rw-r--r--library/std/src/io/readbuf.rs9
-rw-r--r--library/std/src/io/stdio.rs57
-rw-r--r--library/std/src/keyword_docs.rs151
-rw-r--r--library/std/src/lazy.rs1
-rw-r--r--library/std/src/lib.rs24
-rw-r--r--library/std/src/os/fd/mod.rs13
-rw-r--r--library/std/src/os/fd/owned.rs75
-rw-r--r--library/std/src/os/fd/raw.rs18
-rw-r--r--library/std/src/os/mod.rs4
-rw-r--r--library/std/src/os/unix/io/fd.rs8
-rw-r--r--library/std/src/os/unix/io/mod.rs11
-rw-r--r--library/std/src/os/unix/io/raw.rs6
-rw-r--r--library/std/src/os/unix/io/tests.rs (renamed from library/std/src/os/unix/io/fd/tests.rs)0
-rw-r--r--library/std/src/os/unix/mod.rs2
-rw-r--r--library/std/src/os/wasi/io/fd.rs3
-rw-r--r--library/std/src/os/wasi/io/mod.rs12
-rw-r--r--library/std/src/os/wasi/io/raw.rs18
-rw-r--r--library/std/src/os/watchos/fs.rs142
-rw-r--r--library/std/src/os/watchos/mod.rs6
-rw-r--r--library/std/src/os/watchos/raw.rs83
-rw-r--r--library/std/src/os/windows/io/handle.rs17
-rw-r--r--library/std/src/panicking.rs160
-rw-r--r--library/std/src/path.rs4
-rw-r--r--library/std/src/personality/dwarf/eh.rs5
-rw-r--r--library/std/src/primitive_docs.rs23
-rw-r--r--library/std/src/process.rs18
-rw-r--r--library/std/src/rt.rs7
-rw-r--r--library/std/src/sync/mpsc/stream.rs2
-rw-r--r--library/std/src/sync/once.rs312
-rw-r--r--library/std/src/sync/rwlock.rs64
-rw-r--r--library/std/src/sys/common/mod.rs4
-rw-r--r--library/std/src/sys/common/small_c_string.rs58
-rw-r--r--library/std/src/sys/common/tests.rs66
-rw-r--r--library/std/src/sys/hermit/args.rs74
-rw-r--r--library/std/src/sys/hermit/fs.rs13
-rw-r--r--library/std/src/sys/hermit/mod.rs4
-rw-r--r--library/std/src/sys/mod.rs2
-rw-r--r--library/std/src/sys/sgx/abi/tls/mod.rs1
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs28
-rw-r--r--library/std/src/sys/sgx/thread_local_key.rs5
-rw-r--r--library/std/src/sys/solid/fs.rs20
-rw-r--r--library/std/src/sys/solid/os.rs44
-rw-r--r--library/std/src/sys/solid/thread_local_key.rs5
-rw-r--r--library/std/src/sys/unix/fs.rs483
-rw-r--r--library/std/src/sys/unix/io.rs6
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs2
-rw-r--r--library/std/src/sys/unix/locks/mod.rs6
-rw-r--r--library/std/src/sys/unix/mod.rs42
-rw-r--r--library/std/src/sys/unix/os.rs59
-rw-r--r--library/std/src/sys/unix/process/process_common.rs2
-rw-r--r--library/std/src/sys/unix/process/process_common/tests.rs79
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs2
-rw-r--r--library/std/src/sys/unix/process/process_unix.rs76
-rw-r--r--library/std/src/sys/unix/stdio.rs50
-rw-r--r--library/std/src/sys/unix/thread.rs29
-rw-r--r--library/std/src/sys/unix/thread_local_dtor.rs1
-rw-r--r--library/std/src/sys/unix/thread_local_key.rs5
-rw-r--r--library/std/src/sys/unix/thread_parker/darwin.rs131
-rw-r--r--library/std/src/sys/unix/thread_parker/mod.rs13
-rw-r--r--library/std/src/sys/unix/time.rs34
-rw-r--r--library/std/src/sys/unsupported/io.rs4
-rw-r--r--library/std/src/sys/unsupported/locks/condvar.rs1
-rw-r--r--library/std/src/sys/unsupported/locks/mod.rs2
-rw-r--r--library/std/src/sys/unsupported/locks/mutex.rs1
-rw-r--r--library/std/src/sys/unsupported/locks/rwlock.rs1
-rw-r--r--library/std/src/sys/unsupported/thread_local_dtor.rs1
-rw-r--r--library/std/src/sys/unsupported/thread_local_key.rs5
-rw-r--r--library/std/src/sys/wasi/fs.rs105
-rw-r--r--library/std/src/sys/wasi/io.rs6
-rw-r--r--library/std/src/sys/wasi/mod.rs3
-rw-r--r--library/std/src/sys/wasi/os.rs81
-rw-r--r--library/std/src/sys/wasi/stdio.rs23
-rw-r--r--library/std/src/sys/wasi/time.rs4
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/c.rs34
-rw-r--r--library/std/src/sys/windows/fs.rs41
-rw-r--r--library/std/src/sys/windows/io.rs76
-rw-r--r--library/std/src/sys/windows/locks/mod.rs2
-rw-r--r--library/std/src/sys/windows/process.rs6
-rw-r--r--library/std/src/sys/windows/rand.rs76
-rw-r--r--library/std/src/sys/windows/thread_local_key.rs196
-rw-r--r--library/std/src/sys/windows/thread_local_key/tests.rs53
-rw-r--r--library/std/src/sys_common/backtrace.rs9
-rw-r--r--library/std/src/sys_common/condvar.rs1
-rw-r--r--library/std/src/sys_common/condvar/check.rs1
-rw-r--r--library/std/src/sys_common/mod.rs10
-rw-r--r--library/std/src/sys_common/mutex.rs45
-rw-r--r--library/std/src/sys_common/net.rs20
-rw-r--r--library/std/src/sys_common/once/futex.rs134
-rw-r--r--library/std/src/sys_common/once/generic.rs282
-rw-r--r--library/std/src/sys_common/once/mod.rs43
-rw-r--r--library/std/src/sys_common/rwlock.rs61
-rw-r--r--library/std/src/sys_common/thread_local_key.rs24
-rw-r--r--library/std/src/thread/local.rs8
-rw-r--r--library/std/src/thread/mod.rs114
-rw-r--r--library/std/src/thread/tests.rs22
-rw-r--r--library/std/src/time.rs6
-rw-r--r--library/std/tests/run-time-detect.rs86
-rw-r--r--library/stdarch/ci/android-install-sdk.sh4
-rw-r--r--library/stdarch/ci/docker/aarch64-linux-android/Dockerfile11
-rw-r--r--library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile11
-rw-r--r--library/stdarch/ci/docker/x86_64-linux-android/Dockerfile4
-rw-r--r--library/stdarch/crates/core_arch/src/arm_shared/neon/mod.rs24
-rw-r--r--library/stdarch/crates/core_arch/src/lib.rs5
-rw-r--r--library/stdarch/crates/core_arch/src/macros.rs24
-rw-r--r--library/stdarch/crates/core_arch/src/mod.rs7
-rw-r--r--library/stdarch/crates/core_arch/src/riscv_shared/mod.rs83
-rw-r--r--library/stdarch/crates/core_arch/src/riscv_shared/p.rs1061
-rw-r--r--library/stdarch/crates/core_arch/src/simd_llvm.rs8
-rw-r--r--library/stdarch/crates/core_arch/src/x86/avx2.rs4
-rw-r--r--library/stdarch/crates/core_arch/src/x86/cpuid.rs28
-rw-r--r--library/stdarch/crates/core_arch/src/x86/mod.rs4
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse2.rs4
-rw-r--r--library/stdarch/crates/core_arch/src/x86/sse3.rs6
-rw-r--r--library/stdarch/crates/std_detect/Cargo.toml2
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs227
-rw-r--r--library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs61
-rw-r--r--library/stdarch/crates/std_detect/src/detect/test_data/linux-artificial-aarch64.auxvbin0 -> 336 bytes
-rw-r--r--library/stdarch/crates/std_detect/src/detect/test_data/linux-empty-hwcap2-aarch64.auxvbin0 -> 336 bytes
-rw-r--r--library/stdarch/crates/std_detect/src/detect/test_data/linux-hwcap2-aarch64.auxvbin0 -> 336 bytes
-rw-r--r--library/stdarch/crates/std_detect/src/detect/test_data/linux-no-hwcap2-aarch64.auxvbin0 -> 320 bytes
-rw-r--r--library/stdarch/crates/std_detect/src/detect/test_data/linux-x64-i7-6850k.auxvbin304 -> 0 bytes
-rw-r--r--library/stdarch/crates/stdarch-test/Cargo.toml2
-rw-r--r--library/stdarch/crates/stdarch-test/src/lib.rs1
-rw-r--r--library/test/src/bench.rs21
-rw-r--r--library/test/src/cli.rs4
-rw-r--r--library/test/src/console.rs2
-rw-r--r--library/test/src/helpers/isatty.rs32
-rw-r--r--library/test/src/helpers/mod.rs1
-rw-r--r--library/test/src/lib.rs105
-rw-r--r--library/test/src/term.rs2
-rw-r--r--library/test/src/term/win.rs7
-rw-r--r--library/test/src/tests.rs117
-rw-r--r--library/test/src/types.rs15
-rw-r--r--src/README.md2
-rw-r--r--src/bootstrap/CHANGELOG.md2
-rw-r--r--src/bootstrap/Cargo.lock8
-rw-r--r--src/bootstrap/README.md64
-rw-r--r--src/bootstrap/bin/rustc.rs2
-rw-r--r--src/bootstrap/bolt.rs71
-rw-r--r--src/bootstrap/bootstrap.py18
-rw-r--r--src/bootstrap/build.rs36
-rw-r--r--src/bootstrap/builder.rs24
-rw-r--r--src/bootstrap/builder/tests.rs4
-rw-r--r--src/bootstrap/channel.rs68
-rw-r--r--src/bootstrap/check.rs2
-rw-r--r--src/bootstrap/compile.rs67
-rw-r--r--src/bootstrap/config.rs153
-rw-r--r--src/bootstrap/dist.rs200
-rw-r--r--src/bootstrap/doc.rs285
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/flags.rs26
-rw-r--r--src/bootstrap/install.rs11
-rw-r--r--src/bootstrap/lib.rs66
-rw-r--r--src/bootstrap/native.rs116
-rw-r--r--src/bootstrap/sanity.rs2
-rw-r--r--src/bootstrap/tarball.rs6
-rw-r--r--src/bootstrap/test.rs237
-rw-r--r--src/bootstrap/tool.rs42
-rw-r--r--src/bootstrap/toolstate.rs1
-rw-r--r--src/ci/docker/README.md106
-rw-r--r--src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile35
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config726
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile43
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch44
-rw-r--r--src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch63
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile44
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile43
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config741
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile44
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh26
-rw-r--r--src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config740
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile5
-rwxr-xr-xsrc/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version2
-rwxr-xr-xsrc/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh11
-rw-r--r--src/ci/github-actions/ci.yml39
-rwxr-xr-xsrc/ci/pgo.sh39
-rwxr-xr-xsrc/ci/run.sh5
-rwxr-xr-xsrc/ci/scripts/select-xcode.sh13
-rwxr-xr-xsrc/ci/scripts/should-skip-this.sh8
-rw-r--r--src/doc/book/ADMIN_TASKS.md7
-rw-r--r--src/doc/book/TODO.md17
-rw-r--r--src/doc/book/ci/dictionary.txt1
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock40
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/output.txt2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs2
-rw-r--r--src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch08-common-collections/listing-08-04/src/main.rs4
-rw-r--r--src/doc/book/listings/ch08-common-collections/listing-08-06/src/main.rs2
-rw-r--r--src/doc/book/listings/ch08-common-collections/listing-08-07/src/main.rs2
-rw-r--r--src/doc/book/listings/ch08-common-collections/listing-08-16/src/main.rs2
-rw-r--r--src/doc/book/listings/ch08-common-collections/no-listing-02-format/src/main.rs2
-rw-r--r--src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs2
-rw-r--r--src/doc/book/listings/ch09-error-handling/listing-09-07/src/main.rs3
-rw-r--r--src/doc/book/listings/ch09-error-handling/listing-09-08/src/main.rs3
-rw-r--r--src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock3
-rw-r--r--src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock16
-rw-r--r--src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml2
-rw-r--r--src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs8
-rw-r--r--src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs12
-rw-r--r--src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs10
-rw-r--r--src/doc/book/nostarch/acknowledgments.md2
-rw-r--r--src/doc/book/nostarch/appendix.md452
-rw-r--r--src/doc/book/nostarch/appendix_a.md142
-rw-r--r--src/doc/book/nostarch/appendix_b.md241
-rw-r--r--src/doc/book/nostarch/appendix_c.md184
-rw-r--r--src/doc/book/nostarch/appendix_d.md175
-rw-r--r--src/doc/book/nostarch/appendix_e.md66
-rw-r--r--src/doc/book/nostarch/bio.md7
-rw-r--r--src/doc/book/nostarch/chapter01.md161
-rw-r--r--src/doc/book/nostarch/chapter02.md509
-rw-r--r--src/doc/book/nostarch/chapter03.md528
-rw-r--r--src/doc/book/nostarch/chapter04.md520
-rw-r--r--src/doc/book/nostarch/chapter05.md486
-rw-r--r--src/doc/book/nostarch/chapter06.md362
-rw-r--r--src/doc/book/nostarch/chapter07.md595
-rw-r--r--src/doc/book/nostarch/chapter08.md497
-rw-r--r--src/doc/book/nostarch/chapter09.md646
-rw-r--r--src/doc/book/nostarch/chapter10.md577
-rw-r--r--src/doc/book/nostarch/chapter11.md476
-rw-r--r--src/doc/book/nostarch/chapter12.md454
-rw-r--r--src/doc/book/nostarch/chapter13.md404
-rw-r--r--src/doc/book/nostarch/chapter14.md343
-rw-r--r--src/doc/book/nostarch/chapter15.md675
-rw-r--r--src/doc/book/nostarch/chapter16.md436
-rw-r--r--src/doc/book/nostarch/chapter17.md407
-rw-r--r--src/doc/book/nostarch/chapter18.md366
-rw-r--r--src/doc/book/nostarch/chapter19.md684
-rw-r--r--src/doc/book/nostarch/chapter20.md731
-rw-r--r--src/doc/book/nostarch/frontmatter.md292
-rw-r--r--src/doc/book/nostarch/introduction.md13
-rw-r--r--src/doc/book/nostarch/preface.md24
-rw-r--r--src/doc/book/src/appendix-04-useful-development-tools.md15
-rw-r--r--src/doc/book/src/appendix-06-translation.md1
-rw-r--r--src/doc/book/src/ch00-00-introduction.md47
-rw-r--r--src/doc/book/src/ch01-01-installation.md58
-rw-r--r--src/doc/book/src/ch01-02-hello-world.md20
-rw-r--r--src/doc/book/src/ch01-03-hello-cargo.md24
-rw-r--r--src/doc/book/src/ch02-00-guessing-game-tutorial.md246
-rw-r--r--src/doc/book/src/ch03-00-common-programming-concepts.md6
-rw-r--r--src/doc/book/src/ch03-01-variables-and-mutability.md55
-rw-r--r--src/doc/book/src/ch03-02-data-types.md82
-rw-r--r--src/doc/book/src/ch03-03-how-functions-work.md22
-rw-r--r--src/doc/book/src/ch03-04-comments.md5
-rw-r--r--src/doc/book/src/ch03-05-control-flow.md84
-rw-r--r--src/doc/book/src/ch04-01-what-is-ownership.md88
-rw-r--r--src/doc/book/src/ch04-02-references-and-borrowing.md36
-rw-r--r--src/doc/book/src/ch04-03-slices.md50
-rw-r--r--src/doc/book/src/ch05-02-example-structs.md2
-rw-r--r--src/doc/book/src/ch08-02-strings.md4
-rw-r--r--src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md18
-rw-r--r--src/doc/book/src/ch09-02-recoverable-errors-with-result.md8
-rw-r--r--src/doc/book/src/ch13-02-iterators.md2
-rw-r--r--src/doc/book/src/ch14-02-publishing-to-crates-io.md9
-rw-r--r--src/doc/book/src/ch14-03-cargo-workspaces.md13
-rw-r--r--src/doc/book/src/ch14-04-installing-binaries.md8
-rw-r--r--src/doc/book/src/ch15-00-smart-pointers.md6
-rw-r--r--src/doc/book/src/ch15-01-box.md6
-rw-r--r--src/doc/book/src/ch15-02-deref.md11
-rw-r--r--src/doc/book/src/ch15-03-drop.md2
-rw-r--r--src/doc/book/src/ch15-05-interior-mutability.md8
-rw-r--r--src/doc/book/src/ch15-06-reference-cycles.md2
-rw-r--r--src/doc/book/src/ch16-01-threads.md4
-rw-r--r--src/doc/book/src/ch16-03-shared-state.md6
-rwxr-xr-xsrc/doc/book/tools/doc-to-md.sh13
-rw-r--r--src/doc/book/tools/docx-to-md.xsl262
-rw-r--r--src/doc/embedded-book/CITATION.bib7
-rw-r--r--src/doc/embedded-book/src/start/registers.md2
-rw-r--r--src/doc/index.md6
-rw-r--r--src/doc/nomicon/src/subtyping.md2
-rw-r--r--src/doc/nomicon/src/transmutes.md2
-rw-r--r--src/doc/reference/book.toml2
-rw-r--r--src/doc/reference/src/SUMMARY.md3
-rw-r--r--src/doc/reference/src/attributes.md3
-rw-r--r--src/doc/reference/src/attributes/codegen.md2
-rw-r--r--src/doc/reference/src/attributes/derive.md4
-rw-r--r--src/doc/reference/src/attributes/diagnostics.md2
-rw-r--r--src/doc/reference/src/conditional-compilation.md19
-rw-r--r--src/doc/reference/src/destructors.md2
-rw-r--r--src/doc/reference/src/expressions.md139
-rw-r--r--src/doc/reference/src/expressions/block-expr.md9
-rw-r--r--src/doc/reference/src/expressions/closure-expr.md2
-rw-r--r--src/doc/reference/src/expressions/grouped-expr.md4
-rw-r--r--src/doc/reference/src/expressions/loop-expr.md34
-rw-r--r--src/doc/reference/src/identifiers.md6
-rw-r--r--src/doc/reference/src/inline-assembly.md7
-rw-r--r--src/doc/reference/src/items/associated-items.md145
-rw-r--r--src/doc/reference/src/items/external-blocks.md58
-rw-r--r--src/doc/reference/src/items/functions.md4
-rw-r--r--src/doc/reference/src/items/traits.md1
-rw-r--r--src/doc/reference/src/items/type-aliases.md18
-rw-r--r--src/doc/reference/src/patterns.md324
-rw-r--r--src/doc/reference/src/statements-and-expressions.md12
-rw-r--r--src/doc/reference/src/statements.md86
-rw-r--r--src/doc/reference/src/tokens.md2
-rw-r--r--src/doc/reference/src/type-layout.md30
-rw-r--r--src/doc/reference/src/types/function-pointer.md2
-rw-r--r--src/doc/reference/src/types/pointer.md6
-rw-r--r--src/doc/reference/src/unsafe-blocks.md22
-rw-r--r--src/doc/reference/src/unsafe-functions.md5
-rw-r--r--src/doc/reference/src/unsafe-keyword.md58
-rw-r--r--src/doc/rust-by-example/src/cargo/conventions.md6
-rw-r--r--src/doc/rust-by-example/src/cargo/deps.md21
-rw-r--r--src/doc/rust-by-example/src/conversion/from_into.md2
-rw-r--r--src/doc/rust-by-example/src/error/iter_result.md2
-rw-r--r--src/doc/rust-by-example/src/error/option_unwrap/defaults.md6
-rw-r--r--src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md2
-rw-r--r--src/doc/rust-by-example/src/flow_control/match/guard.md6
-rw-r--r--src/doc/rust-by-example/src/macros.md2
-rw-r--r--src/doc/rust-by-example/src/mod/struct_visibility.md3
-rw-r--r--src/doc/rust-by-example/src/primitives/array.md2
-rw-r--r--src/doc/rust-by-example/src/std/box.md6
-rw-r--r--src/doc/rust-by-example/src/std/str.md2
-rw-r--r--src/doc/rust-by-example/src/std_misc/path.md6
-rw-r--r--src/doc/rust-by-example/src/testing/doc_testing.md11
-rw-r--r--src/doc/rust-by-example/src/types/cast.md20
-rw-r--r--src/doc/rust-by-example/src/unsafe/asm.md4
-rw-r--r--src/doc/rustc-dev-guide/.github/workflows/ci.yml21
-rw-r--r--src/doc/rustc-dev-guide/.github/workflows/date-check.yml2
-rw-r--r--src/doc/rustc-dev-guide/book.toml1
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md2
-rw-r--r--src/doc/rustc-dev-guide/src/about-this-guide.md4
-rw-r--r--src/doc/rustc-dev-guide/src/appendix/glossary.md3
-rw-r--r--src/doc/rustc-dev-guide/src/backend/codegen.md2
-rw-r--r--src/doc/rustc-dev-guide/src/backend/debugging.md2
-rw-r--r--src/doc/rustc-dev-guide/src/building/bootstrapping.md86
-rw-r--r--src/doc/rustc-dev-guide/src/building/how-to-build-and-run.md14
-rw-r--r--src/doc/rustc-dev-guide/src/building/new-target.md8
-rw-r--r--src/doc/rustc-dev-guide/src/building/prerequisites.md7
-rw-r--r--src/doc/rustc-dev-guide/src/building/suggested.md4
-rw-r--r--src/doc/rustc-dev-guide/src/closure.md16
-rw-r--r--src/doc/rustc-dev-guide/src/const-eval.md62
-rw-r--r--src/doc/rustc-dev-guide/src/const-eval/interpret.md (renamed from src/doc/rustc-dev-guide/src/miri.md)31
-rw-r--r--src/doc/rustc-dev-guide/src/contributing.md115
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics.md12
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md147
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/translation.md22
-rw-r--r--src/doc/rustc-dev-guide/src/feature-gates.md4
-rw-r--r--src/doc/rustc-dev-guide/src/generics.md4
-rw-r--r--src/doc/rustc-dev-guide/src/git.md29
-rw-r--r--src/doc/rustc-dev-guide/src/img/rustc_stages.svg3
-rw-r--r--src/doc/rustc-dev-guide/src/implementing_new_features.md12
-rw-r--r--src/doc/rustc-dev-guide/src/method-lookup.md4
-rw-r--r--src/doc/rustc-dev-guide/src/name-resolution.md2
-rw-r--r--src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md6
-rw-r--r--src/doc/rustc-dev-guide/src/overview.md4
-rw-r--r--src/doc/rustc-dev-guide/src/panic-implementation.md2
-rw-r--r--src/doc/rustc-dev-guide/src/rustc-driver.md2
-rw-r--r--src/doc/rustc-dev-guide/src/rustdoc.md2
-rw-r--r--src/doc/rustc-dev-guide/src/stability.md6
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ci.md3
-rw-r--r--src/doc/rustc-dev-guide/src/tests/intro.md2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md12
-rw-r--r--src/doc/rustc-dev-guide/src/traits/resolution.md117
-rw-r--r--src/doc/rustc-dev-guide/src/ty.md2
-rw-r--r--src/doc/rustc/src/SUMMARY.md3
-rw-r--r--src/doc/rustc/src/command-line-arguments.md15
-rw-r--r--src/doc/rustc/src/platform-support.md18
-rw-r--r--src/doc/rustc/src/platform-support/android.md45
-rw-r--r--src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md2
-rw-r--r--src/doc/rustc/src/platform-support/armv5te-none-eabi.md66
-rw-r--r--src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md72
-rw-r--r--src/doc/rustdoc/book.toml4
-rw-r--r--src/doc/rustdoc/src/unstable-features.md39
-rw-r--r--src/doc/style-guide/book.toml8
-rw-r--r--src/doc/style-guide/src/README.md190
-rw-r--r--src/doc/style-guide/src/SUMMARY.md11
-rw-r--r--src/doc/style-guide/src/advice.md34
-rw-r--r--src/doc/style-guide/src/cargo.md78
-rw-r--r--src/doc/style-guide/src/expressions.md850
-rw-r--r--src/doc/style-guide/src/items.md565
-rw-r--r--src/doc/style-guide/src/principles.md51
-rw-r--r--src/doc/style-guide/src/statements.md150
-rw-r--r--src/doc/style-guide/src/types.md58
-rw-r--r--src/doc/unstable-book/src/compiler-flags/dylib-lto.md4
-rw-r--r--src/doc/unstable-book/src/compiler-flags/self-profile-events.md2
-rw-r--r--src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md37
-rw-r--r--src/doc/unstable-book/src/language-features/asm-sym.md13
-rw-r--r--src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md30
-rw-r--r--src/doc/unstable-book/src/language-features/half-open-range-patterns.md27
-rw-r--r--src/doc/unstable-book/src/language-features/unix-sigpipe.md10
-rwxr-xr-xsrc/etc/cat-and-grep.sh10
-rw-r--r--src/etc/natvis/libcore.natvis4
-rwxr-xr-xsrc/etc/rust-gdbgui3
-rw-r--r--src/librustdoc/clean/auto_trait.rs15
-rw-r--r--src/librustdoc/clean/blanket_impl.rs209
-rw-r--r--src/librustdoc/clean/inline.rs53
-rw-r--r--src/librustdoc/clean/mod.rs339
-rw-r--r--src/librustdoc/clean/simplify.rs60
-rw-r--r--src/librustdoc/clean/types.rs56
-rw-r--r--src/librustdoc/clean/utils.rs19
-rw-r--r--src/librustdoc/config.rs80
-rw-r--r--src/librustdoc/core.rs48
-rw-r--r--src/librustdoc/doctest.rs18
-rw-r--r--src/librustdoc/fold.rs2
-rw-r--r--src/librustdoc/formats/cache.rs29
-rw-r--r--src/librustdoc/formats/renderer.rs4
-rw-r--r--src/librustdoc/html/format.rs33
-rw-r--r--src/librustdoc/html/highlight.rs13
-rw-r--r--src/librustdoc/html/markdown.rs34
-rw-r--r--src/librustdoc/html/markdown/tests.rs48
-rw-r--r--src/librustdoc/html/render/context.rs65
-rw-r--r--src/librustdoc/html/render/mod.rs210
-rw-r--r--src/librustdoc/html/render/print_item.rs46
-rw-r--r--src/librustdoc/html/render/write_shared.rs6
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/css/noscript.css6
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css683
-rw-r--r--src/librustdoc/html/static/css/settings.css22
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css117
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css116
-rw-r--r--src/librustdoc/html/static/css/themes/light.css109
-rw-r--r--src/librustdoc/html/static/js/main.js264
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js2
-rw-r--r--src/librustdoc/html/static/js/settings.js11
-rw-r--r--src/librustdoc/html/static/js/source-script.js37
-rw-r--r--src/librustdoc/html/static/js/storage.js4
-rw-r--r--src/librustdoc/html/templates/page.html54
-rw-r--r--src/librustdoc/html/templates/print_item.html24
-rw-r--r--src/librustdoc/json/conversions.rs12
-rw-r--r--src/librustdoc/json/mod.rs8
-rw-r--r--src/librustdoc/lib.rs87
-rw-r--r--src/librustdoc/lint.rs2
-rw-r--r--src/librustdoc/markdown.rs7
-rw-r--r--src/librustdoc/passes/bare_urls.rs6
-rw-r--r--src/librustdoc/passes/check_code_block_syntax.rs95
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs14
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs28
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links/early.rs44
-rw-r--r--src/librustdoc/passes/html_tags.rs72
-rw-r--r--src/librustdoc/passes/propagate_doc_cfg.rs2
-rw-r--r--src/librustdoc/passes/strip_private.rs2
-rw-r--r--src/librustdoc/passes/stripper.rs44
-rw-r--r--src/librustdoc/scrape_examples.rs11
-rw-r--r--src/librustdoc/visit.rs2
-rw-r--r--src/librustdoc/visit_ast.rs20
-rw-r--r--src/librustdoc/visit_lib.rs32
-rw-r--r--src/rustdoc-json-types/lib.rs15
-rw-r--r--src/stage0.json568
-rw-r--r--src/test/assembly/asm/aarch64-types.rs2
-rw-r--r--src/test/assembly/asm/arm-types.rs2
-rw-r--r--src/test/assembly/asm/avr-types.rs2
-rw-r--r--src/test/assembly/asm/bpf-types.rs2
-rw-r--r--src/test/assembly/asm/global_asm.rs6
-rw-r--r--src/test/assembly/asm/hexagon-types.rs2
-rw-r--r--src/test/assembly/asm/mips-types.rs2
-rw-r--r--src/test/assembly/asm/msp430-types.rs2
-rw-r--r--src/test/assembly/asm/nvptx-types.rs2
-rw-r--r--src/test/assembly/asm/powerpc-types.rs2
-rw-r--r--src/test/assembly/asm/riscv-types.rs2
-rw-r--r--src/test/assembly/asm/s390x-types.rs2
-rw-r--r--src/test/assembly/asm/wasm-types.rs2
-rw-r--r--src/test/assembly/asm/x86-types.rs2
-rw-r--r--src/test/assembly/x86-stack-probes.rs42
-rw-r--r--src/test/codegen-units/item-collection/asm-sym.rs20
-rw-r--r--src/test/codegen-units/item-collection/generic-impl.rs6
-rw-r--r--src/test/codegen/abi-main-signature-32bit-c-int.rs2
-rw-r--r--src/test/codegen/binary-search-index-no-bound-check.rs20
-rw-r--r--src/test/codegen/deduced-param-attrs.rs60
-rw-r--r--src/test/codegen/function-arguments.rs2
-rw-r--r--src/test/codegen/mem-replace-direct-memcpy.rs1
-rw-r--r--src/test/codegen/sanitizer_scs_attr_check.rs6
-rw-r--r--src/test/codegen/slice-iter-len-eq-zero.rs14
-rw-r--r--src/test/codegen/slice_as_from_ptr_range.rs23
-rw-r--r--src/test/codegen/stack-probes-call.rs24
-rw-r--r--src/test/codegen/stack-probes-inline.rs32
-rw-r--r--src/test/codegen/stack-probes.rs22
-rw-r--r--src/test/codegen/vec-calloc.rs19
-rw-r--r--src/test/codegen/vec-in-place.rs2
-rw-r--r--src/test/incremental/hashes/function_interfaces.rs2
-rw-r--r--src/test/incremental/issue-61323.rs3
-rw-r--r--src/test/incremental/spans_significant_w_panic.rs1
-rw-r--r--src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff6
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/cast.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/indirect.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff2
-rw-r--r--src/test/mir-opt/derefer_complex_case.main.Derefer.diff12
-rw-r--r--src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff4
-rw-r--r--src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff6
-rw-r--r--src/test/mir-opt/enum_cast.bar.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/enum_cast.boo.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/enum_cast.droppy.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/enum_cast.foo.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff24
-rw-r--r--src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/inline/asm-unwind.rs22
-rw-r--r--src/test/mir-opt/inline/asm_unwind.main.Inline.diff45
-rw-r--r--src/test/mir-opt/inline/cycle.f.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff6
-rw-r--r--src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff4
-rw-r--r--src/test/mir-opt/inline/inline_diverging.g.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_generator.main.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir6
-rw-r--r--src/test/mir-opt/inline/inline_shims.clone.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir2
-rw-r--r--src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir2
-rw-r--r--src/test/mir-opt/inline/issue_78442.bar.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff4
-rw-r--r--src/test/mir-opt/issue-101867.rs2
-rw-r--r--src/test/mir-opt/issue_101867.main.mir_map.0.mir4
-rw-r--r--src/test/mir-opt/issue_101973.inner.ConstProp.diff4
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff4
-rw-r--r--src/test/mir-opt/issue_91633.bar.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/issue_91633.foo.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/issue_91633.hey.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/issue_99325.main.mir_map.0.mir18
-rw-r--r--src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff8
-rw-r--r--src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff4
-rw-r--r--src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff2
-rw-r--r--src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir2
-rw-r--r--src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff4
-rw-r--r--src/test/mir-opt/remove-never-const.rs1
-rw-r--r--src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff2
-rw-r--r--src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir4
-rw-r--r--src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir2
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir10
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir2
-rw-r--r--src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir2
-rw-r--r--src/test/pretty/issue-4264.pp8
-rw-r--r--src/test/pretty/issue-85089.pp20
-rw-r--r--src/test/pretty/issue-85089.rs16
-rw-r--r--src/test/pretty/raw-str-nonexpr.rs1
-rw-r--r--src/test/pretty/tests-are-sorted.pp69
-rw-r--r--src/test/pretty/tests-are-sorted.rs13
-rw-r--r--src/test/run-make-fulldeps/alloc-no-rc/Makefile4
-rw-r--r--src/test/run-make-fulldeps/alloc-no-sync/Makefile4
-rw-r--r--src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile11
-rw-r--r--src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs7
-rw-r--r--src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs13
-rw-r--r--src/test/run-make-fulldeps/intrinsic-unreachable/Makefile1
-rw-r--r--src/test/run-make-fulldeps/issue-19371/foo.rs2
-rw-r--r--src/test/run-make-fulldeps/obtain-borrowck/driver.rs12
-rw-r--r--src/test/run-make-fulldeps/print-calling-conventions/Makefile4
-rw-r--r--src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs8
-rw-r--r--src/test/run-make/coverage-reports/Makefile11
-rw-r--r--src/test/run-make/issue-36710/Makefile6
-rw-r--r--src/test/run-make/macos-fat-archive/Makefile10
-rw-r--r--src/test/run-make/macos-fat-archive/lib.rs3
-rw-r--r--src/test/run-make/macos-fat-archive/native-library.c1
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/Makefile15
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs4
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-linker/main.rs9
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/Makefile12
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs9
-rw-r--r--src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs4
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile22
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs5
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs4
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs11
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/Makefile34
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/main.rs4
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c1
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c1
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c1
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs13
-rw-r--r--src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs13
-rw-r--r--src/test/rustdoc-gui/anchor-navigable.goml4
-rw-r--r--src/test/rustdoc-gui/anchors.goml247
-rw-r--r--src/test/rustdoc-gui/auto-hide-trait-implementations.goml2
-rw-r--r--src/test/rustdoc-gui/basic-code.goml4
-rw-r--r--src/test/rustdoc-gui/basic.goml4
-rw-r--r--src/test/rustdoc-gui/check-code-blocks-margin.goml6
-rw-r--r--src/test/rustdoc-gui/check-stab-in-docblock.goml27
-rw-r--r--src/test/rustdoc-gui/check_info_sign_position.goml4
-rw-r--r--src/test/rustdoc-gui/code-blocks-overflow.goml4
-rw-r--r--src/test/rustdoc-gui/code-color.goml38
-rw-r--r--src/test/rustdoc-gui/code-sidebar-toggle.goml2
-rw-r--r--src/test/rustdoc-gui/code-tags.goml10
-rw-r--r--src/test/rustdoc-gui/codeblock-tooltip.goml170
-rw-r--r--src/test/rustdoc-gui/default-settings.goml2
-rw-r--r--src/test/rustdoc-gui/docblock-big-code-mobile.goml2
-rw-r--r--src/test/rustdoc-gui/docblock-code-block-line-number.goml27
-rw-r--r--src/test/rustdoc-gui/docblock-details.goml15
-rw-r--r--src/test/rustdoc-gui/docblock-table-overflow.goml6
-rw-r--r--src/test/rustdoc-gui/docblock-table.goml2
-rw-r--r--src/test/rustdoc-gui/duplicate-macro-reexport.goml2
-rw-r--r--src/test/rustdoc-gui/escape-key.goml2
-rw-r--r--src/test/rustdoc-gui/font-weight.goml20
-rw-r--r--src/test/rustdoc-gui/hash-item-expansion.goml2
-rw-r--r--src/test/rustdoc-gui/headers-color.goml173
-rw-r--r--src/test/rustdoc-gui/headings.goml198
-rw-r--r--src/test/rustdoc-gui/help-page.goml24
-rw-r--r--src/test/rustdoc-gui/highlight-colors.goml94
-rw-r--r--src/test/rustdoc-gui/huge-collection-of-constants.goml2
-rw-r--r--src/test/rustdoc-gui/impl-default-expansion.goml2
-rw-r--r--src/test/rustdoc-gui/implementors.goml16
-rw-r--r--src/test/rustdoc-gui/item-decl-colors.goml74
-rw-r--r--src/test/rustdoc-gui/item-info-alignment.goml2
-rw-r--r--src/test/rustdoc-gui/item-info-overflow.goml10
-rw-r--r--src/test/rustdoc-gui/item-info.goml8
-rw-r--r--src/test/rustdoc-gui/item-summary-table.goml2
-rw-r--r--src/test/rustdoc-gui/javascript-disabled.goml2
-rw-r--r--src/test/rustdoc-gui/jump-to-def-background.goml57
-rw-r--r--src/test/rustdoc-gui/label-next-to-symbol.goml2
-rw-r--r--src/test/rustdoc-gui/links-color.goml2
-rw-r--r--src/test/rustdoc-gui/list_code_block.goml4
-rw-r--r--src/test/rustdoc-gui/mobile.goml6
-rw-r--r--src/test/rustdoc-gui/module-items-font.goml2
-rw-r--r--src/test/rustdoc-gui/no-docblock.goml8
-rw-r--r--src/test/rustdoc-gui/notable-trait.goml128
-rw-r--r--src/test/rustdoc-gui/overflow-tooltip-information.goml2
-rw-r--r--src/test/rustdoc-gui/pocket-menu.goml2
-rw-r--r--src/test/rustdoc-gui/run-on-hover.goml2
-rw-r--r--src/test/rustdoc-gui/rust-logo.goml100
-rw-r--r--src/test/rustdoc-gui/search-filter.goml4
-rw-r--r--src/test/rustdoc-gui/search-form-elements.goml44
-rw-r--r--src/test/rustdoc-gui/search-input-mobile.goml2
-rw-r--r--src/test/rustdoc-gui/search-reexport.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-color.goml410
-rw-r--r--src/test/rustdoc-gui/search-result-description.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-display.goml4
-rw-r--r--src/test/rustdoc-gui/search-result-go-to-first.goml12
-rw-r--r--src/test/rustdoc-gui/search-result-keyword.goml2
-rw-r--r--src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml10
-rw-r--r--src/test/rustdoc-gui/settings.goml15
-rw-r--r--src/test/rustdoc-gui/shortcuts.goml20
-rw-r--r--src/test/rustdoc-gui/sidebar-links-color.goml233
-rw-r--r--src/test/rustdoc-gui/sidebar-macro-reexport.goml4
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile-scroll.goml10
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml18
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code-display.goml25
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml6
-rw-r--r--src/test/rustdoc-gui/sidebar.goml73
-rw-r--r--src/test/rustdoc-gui/source-anchor-scroll.goml4
-rw-r--r--src/test/rustdoc-gui/source-code-page.goml90
-rw-r--r--src/test/rustdoc-gui/src-font-size.goml10
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs91
-rw-r--r--src/test/rustdoc-gui/theme-change.goml4
-rw-r--r--src/test/rustdoc-gui/theme-in-history.goml4
-rw-r--r--src/test/rustdoc-gui/toggle-click-deadspace.goml4
-rw-r--r--src/test/rustdoc-gui/toggle-docs-mobile.goml2
-rw-r--r--src/test/rustdoc-gui/toggle-docs.goml4
-rw-r--r--src/test/rustdoc-gui/toggle-implementors.goml2
-rw-r--r--src/test/rustdoc-gui/toggled-open-implementations.goml2
-rw-r--r--src/test/rustdoc-gui/trait-sidebar-item-order.goml2
-rw-r--r--src/test/rustdoc-gui/type-declation-overflow.goml20
-rw-r--r--src/test/rustdoc-gui/unsafe-fn.goml28
-rw-r--r--src/test/rustdoc-gui/where-whitespace.goml4
-rw-r--r--src/test/rustdoc-js-std/asrawfd.js6
-rw-r--r--src/test/rustdoc-json/primitives/primitive_impls.rs34
-rw-r--r--src/test/rustdoc-json/primitives/primitive_overloading.rs (renamed from src/test/rustdoc-json/primitive_overloading.rs)0
-rw-r--r--src/test/rustdoc-json/primitives/primitive_type.rs (renamed from src/test/rustdoc-json/primitives.rs)0
-rw-r--r--src/test/rustdoc-json/primitives/use_primitive.rs (renamed from src/test/rustdoc-json/primitive.rs)2
-rw-r--r--src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs28
-rw-r--r--src/test/rustdoc-ui/bare-urls.stderr2
-rw-r--r--src/test/rustdoc-ui/check-attr-test.stderr2
-rw-r--r--src/test/rustdoc-ui/check-attr.stderr2
-rw-r--r--src/test/rustdoc-ui/check-cfg-test.stderr2
-rw-r--r--src/test/rustdoc-ui/check-fail.stderr2
-rw-r--r--src/test/rustdoc-ui/check.stderr4
-rw-r--r--src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr2
-rw-r--r--src/test/rustdoc-ui/diagnostic-width.rs2
-rw-r--r--src/test/rustdoc-ui/diagnostic-width.stderr2
-rw-r--r--src/test/rustdoc-ui/doc-attr.stderr4
-rw-r--r--src/test/rustdoc-ui/doc-include-suggestion.stderr2
-rw-r--r--src/test/rustdoc-ui/doc-spotlight.stderr8
-rw-r--r--src/test/rustdoc-ui/doc-test-attr.stderr4
-rw-r--r--src/test/rustdoc-ui/doc_cfg_hide.rs11
-rw-r--r--src/test/rustdoc-ui/doc_cfg_hide.stderr40
-rw-r--r--src/test/rustdoc-ui/doctest-edition.stderr2
-rw-r--r--src/test/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr6
-rw-r--r--src/test/rustdoc-ui/ignore-block-help.stderr2
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs3
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr17
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs4
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr17
-rw-r--r--src/test/rustdoc-ui/infinite-recursive-type.stderr4
-rw-r--r--src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/malformed-generics.rs9
-rw-r--r--src/test/rustdoc-ui/intra-doc/malformed-generics.stderr82
-rw-r--r--src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/private.private.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/private.public.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr12
-rw-r--r--src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr2
-rw-r--r--src/test/rustdoc-ui/intra-doc/warning-crlf.stderr2
-rw-r--r--src/test/rustdoc-ui/invalid-doc-attr.stderr6
-rw-r--r--src/test/rustdoc-ui/invalid-html-self-closing-tag.rs70
-rw-r--r--src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr80
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.rs6
-rw-r--r--src/test/rustdoc-ui/invalid-syntax.stderr19
-rw-r--r--src/test/rustdoc-ui/issue-102986.rs4
-rw-r--r--src/test/rustdoc-ui/issue-102986.stderr14
-rw-r--r--src/test/rustdoc-ui/issue-74134.private.stderr2
-rw-r--r--src/test/rustdoc-ui/issue-74134.public.stderr2
-rw-r--r--src/test/rustdoc-ui/lint-group.stderr2
-rw-r--r--src/test/rustdoc-ui/macro-docs.stderr2
-rw-r--r--src/test/rustdoc-ui/no-crate-level-doc-lint.stderr4
-rw-r--r--src/test/rustdoc-ui/normalize-cycle.rs1
-rw-r--r--src/test/rustdoc-ui/normalize-overflow.rs2
-rw-r--r--src/test/rustdoc-ui/pub-export-lint.stderr2
-rw-r--r--src/test/rustdoc-ui/reference-link-reports-error-once.stderr2
-rw-r--r--src/test/rustdoc-ui/renamed-lint-still-applies.stderr4
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.fixed10
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.rs10
-rw-r--r--src/test/rustdoc-ui/suggestions/html-as-generics.stderr24
-rw-r--r--src/test/rustdoc-ui/z-help.stdout47
-rw-r--r--src/test/rustdoc/anchors.no_const_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_trait_method_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_tymethod_anchor.html2
-rw-r--r--src/test/rustdoc/anchors.no_type_anchor.html2
-rw-r--r--src/test/rustdoc/anonymous-lifetime.rs2
-rw-r--r--src/test/rustdoc/array-links.link_box_generic.html1
-rw-r--r--src/test/rustdoc/array-links.link_box_u32.html1
-rw-r--r--src/test/rustdoc/array-links.link_slice_generic.html1
-rw-r--r--src/test/rustdoc/array-links.link_slice_u32.html1
-rw-r--r--src/test/rustdoc/array-links.rs28
-rw-r--r--src/test/rustdoc/assoc-consts.rs4
-rw-r--r--src/test/rustdoc/associated-consts.rs8
-rw-r--r--src/test/rustdoc/async-trait.rs16
-rw-r--r--src/test/rustdoc/attribute-rendering.rs2
-rw-r--r--src/test/rustdoc/attributes.rs2
-rw-r--r--src/test/rustdoc/auxiliary/async-trait-dep.rs9
-rw-r--r--src/test/rustdoc/auxiliary/reexport-doc-aux.rs5
-rw-r--r--src/test/rustdoc/blanket-reexport-item.rs2
-rw-r--r--src/test/rustdoc/const-generics/add-impl.rs2
-rw-r--r--src/test/rustdoc/const-generics/const-generics-docs.rs12
-rw-r--r--src/test/rustdoc/const-generics/const-impl.rs10
-rw-r--r--src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs2
-rw-r--r--src/test/rustdoc/const-value-display.rs4
-rw-r--r--src/test/rustdoc/decl-trailing-whitespace.rs2
-rw-r--r--src/test/rustdoc/deref-recursive-pathbuf.rs4
-rw-r--r--src/test/rustdoc/deref-recursive.rs4
-rw-r--r--src/test/rustdoc/deref-typedef.rs2
-rw-r--r--src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs38
-rw-r--r--src/test/rustdoc/duplicate_impls/issue-33054.rs6
-rw-r--r--src/test/rustdoc/empty-impl-block.rs2
-rw-r--r--src/test/rustdoc/escape-deref-methods.rs2
-rw-r--r--src/test/rustdoc/extern-impl.rs6
-rw-r--r--src/test/rustdoc/fn-bound.rs2
-rw-r--r--src/test/rustdoc/generic-impl.rs2
-rw-r--r--src/test/rustdoc/higher-ranked-trait-bounds.rs2
-rw-r--r--src/test/rustdoc/impl-disambiguation.rs10
-rw-r--r--src/test/rustdoc/impl-parts.rs4
-rw-r--r--src/test/rustdoc/index-page.rs6
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html1
-rw-r--r--src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs40
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs46
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs13
-rw-r--r--src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs14
-rw-r--r--src/test/rustdoc/inline_cross/impl_trait.rs7
-rw-r--r--src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html1
-rw-r--r--src/test/rustdoc/inline_cross/issue-24183.rs18
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948-1.rs20
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948-2.rs12
-rw-r--r--src/test/rustdoc/inline_cross/issue-31948.rs20
-rw-r--r--src/test/rustdoc/inline_cross/issue-32881.rs4
-rw-r--r--src/test/rustdoc/inline_cross/issue-33113.rs4
-rw-r--r--src/test/rustdoc/inline_cross/trait-vis.rs2
-rw-r--r--src/test/rustdoc/inline_local/trait-vis.rs4
-rw-r--r--src/test/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs4
-rw-r--r--src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs2
-rw-r--r--src/test/rustdoc/intra-doc/issue-103463.rs8
-rw-r--r--src/test/rustdoc/intra-doc/issue-104145.rs14
-rw-r--r--src/test/rustdoc/intra-doc/no-doc-primitive.rs15
-rw-r--r--src/test/rustdoc/issue-100241.rs12
-rw-r--r--src/test/rustdoc/issue-29503.rs2
-rw-r--r--src/test/rustdoc/issue-33592.rs4
-rw-r--r--src/test/rustdoc/issue-46727.rs2
-rw-r--r--src/test/rustdoc/issue-50159.rs4
-rw-r--r--src/test/rustdoc/issue-51236.rs2
-rw-r--r--src/test/rustdoc/issue-54705.rs4
-rw-r--r--src/test/rustdoc/issue-55321.rs8
-rw-r--r--src/test/rustdoc/issue-56822.rs2
-rw-r--r--src/test/rustdoc/issue-60726.rs4
-rw-r--r--src/test/rustdoc/issue-75588.rs4
-rw-r--r--src/test/rustdoc/issue-80233-normalize-auto-trait.rs2
-rw-r--r--src/test/rustdoc/issue-82465-asref-for-and-of-local.rs4
-rw-r--r--src/test/rustdoc/issue-98697.rs4
-rw-r--r--src/test/rustdoc/keyword.rs2
-rw-r--r--src/test/rustdoc/logo-class-default.rs2
-rw-r--r--src/test/rustdoc/logo-class.rs4
-rw-r--r--src/test/rustdoc/macro-higher-kinded-function.rs4
-rw-r--r--src/test/rustdoc/negative-impl-sidebar.rs2
-rw-r--r--src/test/rustdoc/negative-impl.rs4
-rw-r--r--src/test/rustdoc/normalize-assoc-item.rs13
-rw-r--r--src/test/rustdoc/not-wf-ambiguous-normalization.rs24
-rw-r--r--src/test/rustdoc/primitive-reference.rs4
-rw-r--r--src/test/rustdoc/primitive-slice-auto-trait.rs2
-rw-r--r--src/test/rustdoc/primitive-tuple-auto-trait.rs2
-rw-r--r--src/test/rustdoc/primitive-unit-auto-trait.rs2
-rw-r--r--src/test/rustdoc/primitive.rs2
-rw-r--r--src/test/rustdoc/primitive/primitive-generic-impl.rs2
-rw-r--r--src/test/rustdoc/recursive-deref.rs18
-rw-r--r--src/test/rustdoc/reexport-dep-foreign-fn.rs2
-rw-r--r--src/test/rustdoc/reexport-doc.rs8
-rw-r--r--src/test/rustdoc/reexports-priv.rs32
-rw-r--r--src/test/rustdoc/reexports.rs16
-rw-r--r--src/test/rustdoc/rfc-2632-const-trait-impl.rs16
-rw-r--r--src/test/rustdoc/safe-intrinsic.rs2
-rw-r--r--src/test/rustdoc/sidebar-all-page.rs35
-rw-r--r--src/test/rustdoc/sidebar-items.rs18
-rw-r--r--src/test/rustdoc/sidebar-links-to-foreign-impl.rs6
-rw-r--r--src/test/rustdoc/sized_trait.rs2
-rw-r--r--src/test/rustdoc/src-links-auto-impls.rs6
-rw-r--r--src/test/rustdoc/strip-enum-variant.no-not-shown.html2
-rw-r--r--src/test/rustdoc/strip-enum-variant.rs2
-rw-r--r--src/test/rustdoc/synthetic_auto/basic.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/complex.rs2
-rw-r--r--src/test/rustdoc/synthetic_auto/crate-local.rs6
-rw-r--r--src/test/rustdoc/synthetic_auto/lifetimes.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/manual.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/negative.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/nested.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/no-redundancy.rs2
-rw-r--r--src/test/rustdoc/synthetic_auto/overflow.rs2
-rw-r--r--src/test/rustdoc/synthetic_auto/project.rs4
-rw-r--r--src/test/rustdoc/synthetic_auto/self-referential.rs2
-rw-r--r--src/test/rustdoc/synthetic_auto/static-region.rs2
-rw-r--r--src/test/rustdoc/toggle-item-contents.rs2
-rw-r--r--src/test/rustdoc/toggle-trait-fn.rs12
-rw-r--r--src/test/rustdoc/trait_alias.rs6
-rw-r--r--src/test/rustdoc/traits-in-bodies.rs6
-rw-r--r--src/test/rustdoc/tuple-struct-fields-doc.rs2
-rw-r--r--src/test/rustdoc/typedef.rs4
-rw-r--r--src/test/rustdoc/where.SWhere_Simd_item-decl.html2
-rw-r--r--src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html2
-rw-r--r--src/test/rustdoc/where.rs14
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.enum.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.enum2.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.rs16
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.struct.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.struct2.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.trait.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.trait2.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.union.html4
-rw-r--r--src/test/rustdoc/whitespace-after-where-clause.union2.html4
-rw-r--r--src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs10
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs8
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs10
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs4
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-tool-test.rs8
-rw-r--r--src/test/ui-fulldeps/fluent-messages/test.rs5
-rw-r--r--src/test/ui-fulldeps/fluent-messages/test.stderr29
-rw-r--r--src/test/ui-fulldeps/internal-lints/default_hash_types.stderr2
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs52
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.stderr14
-rw-r--r--src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr2
-rw-r--r--src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr2
-rw-r--r--src/test/ui-fulldeps/internal-lints/query_stability.stderr2
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs4
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs605
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr552
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs321
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr256
-rw-r--r--src/test/ui/abi/abi-sysv64-register-usage.rs26
-rw-r--r--src/test/ui/abi/abi-typo-unstable.rs6
-rw-r--r--src/test/ui/abi/abi-typo-unstable.stderr11
-rw-r--r--src/test/ui/abi/segfault-no-out-of-stack.rs1
-rw-r--r--src/test/ui/abi/stack-probes-lto.rs3
-rw-r--r--src/test/ui/abi/stack-probes.rs30
-rw-r--r--src/test/ui/abi/unsupported.aarch64.stderr2
-rw-r--r--src/test/ui/abi/unsupported.arm.stderr2
-rw-r--r--src/test/ui/abi/unsupported.x64.stderr2
-rw-r--r--src/test/ui/abi/x86stdcall.rs26
-rw-r--r--src/test/ui/abi/x86stdcall2.rs12
-rw-r--r--src/test/ui/alloc-error/default-alloc-error-hook.rs11
-rw-r--r--src/test/ui/anon-params/anon-params-deprecated.stderr4
-rw-r--r--src/test/ui/anonymous-higher-ranked-lifetime.stderr20
-rw-r--r--src/test/ui/array-slice-vec/array_const_index-0.rs3
-rw-r--r--src/test/ui/array-slice-vec/array_const_index-0.stderr20
-rw-r--r--src/test/ui/array-slice-vec/array_const_index-1.rs3
-rw-r--r--src/test/ui/array-slice-vec/array_const_index-1.stderr20
-rw-r--r--src/test/ui/asm/aarch64/bad-reg.rs2
-rw-r--r--src/test/ui/asm/aarch64/may_unwind.rs2
-rw-r--r--src/test/ui/asm/aarch64/sym.rs2
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.rs2
-rw-r--r--src/test/ui/asm/aarch64/type-check-2-2.stderr10
-rw-r--r--src/test/ui/asm/aarch64/type-check-2.rs2
-rw-r--r--src/test/ui/asm/aarch64/type-check-3.stderr2
-rw-r--r--src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr2
-rw-r--r--src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr2
-rw-r--r--src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr2
-rw-r--r--src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr2
-rw-r--r--src/test/ui/asm/generic-const.rs2
-rw-r--r--src/test/ui/asm/naked-functions-ffi.stderr2
-rw-r--r--src/test/ui/asm/naked-functions.rs2
-rw-r--r--src/test/ui/asm/named-asm-labels.stderr6
-rw-r--r--src/test/ui/asm/type-check-1.rs2
-rw-r--r--src/test/ui/asm/unpretty-expanded.rs1
-rw-r--r--src/test/ui/asm/unpretty-expanded.stdout1
-rw-r--r--src/test/ui/asm/x86_64/bad-reg.rs2
-rw-r--r--src/test/ui/asm/x86_64/issue-96797.rs2
-rw-r--r--src/test/ui/asm/x86_64/may_unwind.rs2
-rw-r--r--src/test/ui/asm/x86_64/multiple-clobber-abi.rs2
-rw-r--r--src/test/ui/asm/x86_64/sym.rs2
-rw-r--r--src/test/ui/asm/x86_64/type-check-2.rs2
-rw-r--r--src/test/ui/asm/x86_64/type-check-3.stderr2
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.rs5
-rw-r--r--src/test/ui/asm/x86_64/type-check-4.stderr6
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.rs2
-rw-r--r--src/test/ui/asm/x86_64/type-check-5.stderr10
-rw-r--r--src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr2
-rw-r--r--src/test/ui/associated-consts/defaults-not-assumed-fail.rs4
-rw-r--r--src/test/ui/associated-consts/defaults-not-assumed-fail.stderr39
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_1.rs18
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_2.rs11
-rw-r--r--src/test/ui/associated-consts/mismatched_impl_ty_3.rs11
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-2.stderr8
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-3.rs1
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names-3.stderr18
-rw-r--r--src/test/ui/associated-item/associated-item-duplicate-names.stderr14
-rw-r--r--src/test/ui/associated-item/impl-duplicate-methods.rs (renamed from src/test/ui/impl-duplicate-methods.rs)2
-rw-r--r--src/test/ui/associated-item/impl-duplicate-methods.stderr11
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.rs4
-rw-r--r--src/test/ui/associated-type-bounds/inside-adt.stderr10
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr10
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.rs2
-rw-r--r--src/test/ui/associated-types/defaults-specialization.stderr2
-rw-r--r--src/test/ui/associated-types/issue-85103.rs2
-rw-r--r--src/test/ui/associated-types/issue-85103.stderr2
-rw-r--r--src/test/ui/associated-types/issue-87261.rs6
-rw-r--r--src/test/ui/associated-types/issue-87261.stderr18
-rw-r--r--src/test/ui/async-await/async-fn-nonsend.stderr2
-rw-r--r--src/test/ui/async-await/async-fn-size-moved-locals.rs2
-rw-r--r--src/test/ui/async-await/async-fn-size-uninit-locals.rs5
-rw-r--r--src/test/ui/async-await/async-trait-fn.rs3
-rw-r--r--src/test/ui/async-await/async-trait-fn.stderr62
-rw-r--r--src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr4
-rw-r--r--src/test/ui/async-await/await-keyword/2015-edition-warning.stderr4
-rw-r--r--src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr4
-rw-r--r--src/test/ui/async-await/edition-deny-async-fns-2015.rs1
-rw-r--r--src/test/ui/async-await/edition-deny-async-fns-2015.stderr28
-rw-r--r--src/test/ui/async-await/feature-gate-async_fn_in_trait.rs25
-rw-r--r--src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr42
-rw-r--r--src/test/ui/async-await/in-trait/async-associated-types.rs24
-rw-r--r--src/test/ui/async-await/in-trait/async-associated-types.stderr57
-rw-r--r--src/test/ui/async-await/in-trait/async-associated-types2.rs30
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs21
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr17
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs24
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs21
-rw-r--r--src/test/ui/async-await/in-trait/async-example-desugared.rs23
-rw-r--r--src/test/ui/async-await/in-trait/async-example.rs32
-rw-r--r--src/test/ui/async-await/in-trait/async-generics-and-bounds.rs21
-rw-r--r--src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr37
-rw-r--r--src/test/ui/async-await/in-trait/async-generics.rs18
-rw-r--r--src/test/ui/async-await/in-trait/async-generics.stderr37
-rw-r--r--src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs20
-rw-r--r--src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr23
-rw-r--r--src/test/ui/async-await/in-trait/async-lifetimes.rs18
-rw-r--r--src/test/ui/async-await/in-trait/async-lifetimes.stderr23
-rw-r--r--src/test/ui/async-await/in-trait/async-recursive-generic.rs21
-rw-r--r--src/test/ui/async-await/in-trait/async-recursive-generic.stderr12
-rw-r--r--src/test/ui/async-await/in-trait/async-recursive.rs21
-rw-r--r--src/test/ui/async-await/in-trait/async-recursive.stderr12
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.rs17
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err.stderr17
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err2.rs21
-rw-r--r--src/test/ui/async-await/in-trait/fn-not-async-err2.stderr12
-rw-r--r--src/test/ui/async-await/in-trait/issue-102138.rs46
-rw-r--r--src/test/ui/async-await/in-trait/issue-102219.rs10
-rw-r--r--src/test/ui/async-await/in-trait/issue-102310.rs15
-rw-r--r--src/test/ui/async-await/issue-64130-1-sync.rs2
-rw-r--r--src/test/ui/async-await/issue-64130-2-send.rs2
-rw-r--r--src/test/ui/async-await/issue-64130-3-other.rs2
-rw-r--r--src/test/ui/async-await/issue-66387-if-without-else.stderr2
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issue-73541-3.rs (renamed from src/test/ui/issues/issue-73541-3.rs)0
-rw-r--r--src/test/ui/async-await/issue-73541-3.stderr (renamed from src/test/ui/issues/issue-73541-3.stderr)0
-rw-r--r--src/test/ui/async-await/issue-73541.rs (renamed from src/test/ui/issues/issue-73541.rs)0
-rw-r--r--src/test/ui/async-await/issue-73541.stderr (renamed from src/test/ui/issues/issue-73541.stderr)0
-rw-r--r--src/test/ui/async-await/issue-98634.rs50
-rw-r--r--src/test/ui/async-await/issue-98634.stderr60
-rw-r--r--src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs1
-rw-r--r--src/test/ui/async-await/issues/issue-95307.stderr2
-rw-r--r--src/test/ui/async-await/large_moves.attribute.stderr2
-rw-r--r--src/test/ui/async-await/large_moves.option.stderr2
-rw-r--r--src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr2
-rw-r--r--src/test/ui/async-await/no-const-async.stderr2
-rw-r--r--src/test/ui/attr-from-macro.rs20
-rw-r--r--src/test/ui/attributes/doc-attr.stderr4
-rw-r--r--src/test/ui/attributes/invalid-doc-attr.stderr6
-rw-r--r--src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs6
-rw-r--r--src/test/ui/auto-traits/suspicious-impls-lint.stderr10
-rw-r--r--src/test/ui/auxiliary/attr-from-macro.rs15
-rw-r--r--src/test/ui/backtrace.rs1
-rw-r--r--src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs1
-rw-r--r--src/test/ui/binding/issue-53114-safety-checks.stderr10
-rw-r--r--src/test/ui/binop/issue-77910-1.rs2
-rw-r--r--src/test/ui/binop/issue-77910-1.stderr12
-rw-r--r--src/test/ui/binop/issue-77910-2.stderr4
-rw-r--r--src/test/ui/block-result/consider-removing-last-semi.stderr6
-rw-r--r--src/test/ui/block-result/issue-11714.stderr2
-rw-r--r--src/test/ui/block-result/issue-13428.stderr2
-rw-r--r--src/test/ui/borrowck/anonymous-region-in-apit.rs12
-rw-r--r--src/test/ui/borrowck/anonymous-region-in-apit.stderr16
-rw-r--r--src/test/ui/borrowck/borrowck-block-unint.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-break-uninit-2.stderr4
-rw-r--r--src/test/ui/borrowck/borrowck-break-uninit.stderr4
-rw-r--r--src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-init-in-fru.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-init-op-equal.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-init-plus-equal.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-return.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-storage-dead.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-uninit-after-item.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-uninit-field-access.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr50
-rw-r--r--src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr15
-rw-r--r--src/test/ui/borrowck/borrowck-uninit.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr10
-rw-r--r--src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr5
-rw-r--r--src/test/ui/borrowck/borrowck-while-cond.stderr5
-rw-r--r--src/test/ui/borrowck/issue-102209.rs28
-rw-r--r--src/test/ui/borrowck/issue-102209.stderr22
-rw-r--r--src/test/ui/borrowck/issue-103250.rs37
-rw-r--r--src/test/ui/borrowck/issue-103250.stderr17
-rw-r--r--src/test/ui/borrowck/issue-103624.rs31
-rw-r--r--src/test/ui/borrowck/issue-103624.stderr35
-rw-r--r--src/test/ui/borrowck/issue-17718-static-move.rs (renamed from src/test/ui/issues/issue-17718-static-move.rs)0
-rw-r--r--src/test/ui/borrowck/issue-17718-static-move.stderr (renamed from src/test/ui/issues/issue-17718-static-move.stderr)0
-rw-r--r--src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs (renamed from src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs)0
-rw-r--r--src/test/ui/borrowck/issue-24267-flow-exit.stderr8
-rw-r--r--src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr5
-rw-r--r--src/test/ui/borrowck/issue-81899.rs3
-rw-r--r--src/test/ui/borrowck/issue-81899.stderr23
-rw-r--r--src/test/ui/borrowck/issue-88434-minimal-example.rs3
-rw-r--r--src/test/ui/borrowck/issue-88434-minimal-example.stderr23
-rw-r--r--src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs3
-rw-r--r--src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr23
-rw-r--r--src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs26
-rw-r--r--src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr24
-rw-r--r--src/test/ui/borrowck/suggest-assign-rvalue.rs57
-rw-r--r--src/test/ui/borrowck/suggest-assign-rvalue.stderr138
-rw-r--r--src/test/ui/borrowck/two-phase-across-loop.stderr5
-rw-r--r--src/test/ui/box/issue-95036.rs2
-rw-r--r--src/test/ui/builtin-clone-unwind.rs1
-rw-r--r--src/test/ui/cast/cast-rfc0401.rs6
-rw-r--r--src/test/ui/cast/issue-88621.rs2
-rw-r--r--src/test/ui/cast/issue-88621.stderr2
-rw-r--r--src/test/ui/catch-unwind-bang.rs1
-rw-r--r--src/test/ui/cenum_impl_drop_cast.stderr8
-rw-r--r--src/test/ui/cfg/cfg-method-receiver-ok.rs14
-rw-r--r--src/test/ui/cfg/cfg-method-receiver.rs11
-rw-r--r--src/test/ui/cfg/cfg-method-receiver.stderr24
-rw-r--r--src/test/ui/cfg/cfg-panic.rs3
-rw-r--r--src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr2
-rw-r--r--src/test/ui/check-cfg/compact-values.stderr2
-rw-r--r--src/test/ui/check-cfg/empty-values.stderr2
-rw-r--r--src/test/ui/check-cfg/invalid-cfg-value.stderr2
-rw-r--r--src/test/ui/check-cfg/no-values.stderr2
-rw-r--r--src/test/ui/check-cfg/well-known-values.stderr2
-rw-r--r--src/test/ui/check-static-values-constraints.rs2
-rw-r--r--src/test/ui/check-static-values-constraints.stderr4
-rw-r--r--src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr6
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/issue-90465.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr5
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed1
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs1
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr4
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr2
-rw-r--r--src/test/ui/closures/closure-bounds-subtype.stderr4
-rw-r--r--src/test/ui/closures/closure-reform-bad.stderr2
-rw-r--r--src/test/ui/closures/closure-return-type-must-be-sized.rs74
-rw-r--r--src/test/ui/closures/closure-return-type-must-be-sized.stderr99
-rw-r--r--src/test/ui/closures/closure_promotion.rs2
-rw-r--r--src/test/ui/closures/issue-101696.rs36
-rw-r--r--src/test/ui/closures/issue-102089-multiple-opaque-cast.rs17
-rw-r--r--src/test/ui/closures/issue-97607.rs12
-rw-r--r--src/test/ui/closures/multiple-fn-bounds.rs15
-rw-r--r--src/test/ui/closures/multiple-fn-bounds.stderr24
-rw-r--r--src/test/ui/closures/old-closure-expression-remove-semicolon.fixed2
-rw-r--r--src/test/ui/closures/old-closure-expression-remove-semicolon.rs2
-rw-r--r--src/test/ui/closures/old-closure-expression-remove-semicolon.stderr2
-rw-r--r--src/test/ui/codemap_tests/unicode.normal.stderr2
-rw-r--r--src/test/ui/coercion/coercion-missing-tail-expected-type.stderr4
-rw-r--r--src/test/ui/coercion/issue-36007.rs20
-rw-r--r--src/test/ui/coherence/coherence-default-trait-impl.stderr12
-rw-r--r--src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr4
-rw-r--r--src/test/ui/coherence/coherence-fn-implied-bounds.stderr6
-rw-r--r--src/test/ui/coherence/coherence-free-vs-bound-region.stderr6
-rw-r--r--src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr2
-rw-r--r--src/test/ui/coherence/coherence-negative-impls-copy-bad.rs11
-rw-r--r--src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr36
-rw-r--r--src/test/ui/coherence/coherence-negative-impls-copy.rs29
-rw-r--r--src/test/ui/coherence/coherence-subtyping.stderr2
-rw-r--r--src/test/ui/coherence/coherence-wasm-bindgen.stderr8
-rw-r--r--src/test/ui/coherence/deep-bad-copy-reason.stderr4
-rw-r--r--src/test/ui/command/command-current-dir.rs1
-rw-r--r--src/test/ui/command/command-exec.rs1
-rw-r--r--src/test/ui/command/command-pre-exec.rs1
-rw-r--r--src/test/ui/command/command-uid-gid.rs1
-rw-r--r--src/test/ui/compare-method/issue-90444.stderr6
-rw-r--r--src/test/ui/conflicting-repr-hints.stderr2
-rw-r--r--src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr5
-rw-r--r--src/test/ui/const-generics/const_trait_fn-issue-88433.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/closures.stderr4
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr10
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/function-call.rs1
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/function-call.stderr4
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-102074.rs23
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-102768.rs14
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr33
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr10
-rw-r--r--src/test/ui/const-generics/invariant.stderr2
-rw-r--r--src/test/ui/const-generics/issue-102124.rs20
-rw-r--r--src/test/ui/const-generics/issue-103243.rs37
-rw-r--r--src/test/ui/const-generics/issue-80471.stderr2
-rw-r--r--src/test/ui/const-generics/issue-93647.rs2
-rw-r--r--src/test/ui/const-generics/issues/issue-83466.stderr2
-rw-r--r--src/test/ui/const-generics/issues/issue-83765.stderr8
-rw-r--r--src/test/ui/const-generics/issues/issue-88119.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-98629.rs1
-rw-r--r--src/test/ui/const-generics/issues/issue-98629.stderr2
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.rs1
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.stderr18
-rw-r--r--src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs1
-rw-r--r--src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr8
-rw-r--r--src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr2
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-2.rs2
-rw-r--r--src/test/ui/const-generics/occurs-check/unused-substs-3.rs2
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.32bit.stderr16
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.64bit.stderr16
-rw-r--r--src/test/ui/const_prop/issue-102553.rs24
-rw-r--r--src/test/ui/consts/array-literal-index-oob.rs2
-rw-r--r--src/test/ui/consts/array-literal-index-oob.stderr6
-rw-r--r--src/test/ui/consts/assert-type-intrinsics.rs7
-rw-r--r--src/test/ui/consts/assert-type-intrinsics.stderr70
-rw-r--r--src/test/ui/consts/assoc_const_generic_impl.rs7
-rw-r--r--src/test/ui/consts/assoc_const_generic_impl.stderr40
-rw-r--r--src/test/ui/consts/cast-discriminant-zst-enum.rs1
-rw-r--r--src/test/ui/consts/const-err-early.rs17
-rw-r--r--src/test/ui/consts/const-err-early.stderr126
-rw-r--r--src/test/ui/consts/const-err-late.rs22
-rw-r--r--src/test/ui/consts/const-err-late.stderr27
-rw-r--r--src/test/ui/consts/const-err-multi.rs14
-rw-r--r--src/test/ui/consts/const-err-multi.stderr102
-rw-r--r--src/test/ui/consts/const-err-rpass.rs2
-rw-r--r--src/test/ui/consts/const-err.rs19
-rw-r--r--src/test/ui/consts/const-err.stderr44
-rw-r--r--src/test/ui/consts/const-eval/conditional_array_execution.rs10
-rw-r--r--src/test/ui/consts/const-eval/conditional_array_execution.stderr63
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-2.rs4
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-2.stderr24
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr4
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr4
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2.rs26
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2.stderr226
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2b.rs26
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2b.stderr226
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2c.rs26
-rw-r--r--src/test/ui/consts/const-eval/const-eval-overflow2c.stderr226
-rw-r--r--src/test/ui/consts/const-eval/const-eval-query-stack.rs10
-rw-r--r--src/test/ui/consts/const-eval/const-eval-query-stack.stderr64
-rw-r--r--src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr570
-rw-r--r--src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs81
-rw-r--r--src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs7
-rw-r--r--src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr92
-rw-r--r--src/test/ui/consts/const-eval/const_let.rs8
-rw-r--r--src/test/ui/consts/const-eval/const_let.stderr16
-rw-r--r--src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr2
-rw-r--r--src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr20
-rw-r--r--src/test/ui/consts/const-eval/erroneous-const.rs6
-rw-r--r--src/test/ui/consts/const-eval/erroneous-const.stderr45
-rw-r--r--src/test/ui/consts/const-eval/erroneous-const2.rs6
-rw-r--r--src/test/ui/consts/const-eval/erroneous-const2.stderr41
-rw-r--r--src/test/ui/consts/const-eval/format.rs4
-rw-r--r--src/test/ui/consts/const-eval/format.stderr78
-rw-r--r--src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs6
-rw-r--r--src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr38
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.rs2
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.stderr6
-rw-r--r--src/test/ui/consts/const-eval/issue-100878.rs8
-rw-r--r--src/test/ui/consts/const-eval/issue-43197.rs16
-rw-r--r--src/test/ui/consts/const-eval/issue-43197.stderr119
-rw-r--r--src/test/ui/consts/const-eval/issue-44578.rs5
-rw-r--r--src/test/ui/consts/const-eval/issue-44578.stderr43
-rw-r--r--src/test/ui/consts/const-eval/issue-50814-2.rs3
-rw-r--r--src/test/ui/consts/const-eval/issue-50814-2.stderr23
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.rs3
-rw-r--r--src/test/ui/consts/const-eval/issue-50814.stderr23
-rw-r--r--src/test/ui/consts/const-eval/issue-65394.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-65394.stderr4
-rw-r--r--src/test/ui/consts/const-eval/livedrop.rs2
-rw-r--r--src/test/ui/consts/const-eval/livedrop.stderr4
-rw-r--r--src/test/ui/consts/const-eval/panic-assoc-never-type.rs1
-rw-r--r--src/test/ui/consts/const-eval/panic-assoc-never-type.stderr6
-rw-r--r--src/test/ui/consts/const-eval/panic-never-type.rs1
-rw-r--r--src/test/ui/consts/const-eval/panic-never-type.stderr4
-rw-r--r--src/test/ui/consts/const-eval/partial_ptr_overwrite.rs3
-rw-r--r--src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr25
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail.rs2
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr2
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs2
-rw-r--r--src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr2
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.noopt.stderr93
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.opt.stderr95
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr93
-rw-r--r--src/test/ui/consts/const-eval/promoted_errors.rs25
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err.rs10
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err.stderr31
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err_bin.rs10
-rw-r--r--src/test/ui/consts/const-eval/pub_const_err_bin.stderr31
-rw-r--r--src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr21
-rw-r--r--src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr21
-rw-r--r--src/test/ui/consts/const-eval/ref_to_int_match.rs3
-rw-r--r--src/test/ui/consts/const-eval/ub-enum.32bit.stderr110
-rw-r--r--src/test/ui/consts/const-eval/ub-enum.64bit.stderr110
-rw-r--r--src/test/ui/consts/const-eval/ub-enum.rs16
-rw-r--r--src/test/ui/consts/const-eval/ub-int-array.32bit.stderr6
-rw-r--r--src/test/ui/consts/const-eval/ub-int-array.64bit.stderr6
-rw-r--r--src/test/ui/consts/const-eval/ub-int-array.rs1
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr12
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr12
-rw-r--r--src/test/ui/consts/const-eval/ub-nonnull.rs3
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr114
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr114
-rw-r--r--src/test/ui/consts/const-eval/ub-ref-ptr.rs15
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr6
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr6
-rw-r--r--src/test/ui/consts/const-eval/ub-uninhabit.rs1
-rw-r--r--src/test/ui/consts/const-eval/ub-upvars.rs2
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr187
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr187
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs24
-rw-r--r--src/test/ui/consts/const-eval/union-ub.32bit.stderr4
-rw-r--r--src/test/ui/consts/const-eval/union-ub.64bit.stderr4
-rw-r--r--src/test/ui/consts/const-eval/union-ub.rs1
-rw-r--r--src/test/ui/consts/const-eval/union_promotion.rs2
-rw-r--r--src/test/ui/consts/const-eval/union_promotion.stderr2
-rw-r--r--src/test/ui/consts/const-eval/unused-broken-const.rs3
-rw-r--r--src/test/ui/consts/const-eval/unused-broken-const.stderr20
-rw-r--r--src/test/ui/consts/const-eval/valid-const.rs1
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr16
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr16
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs2
-rw-r--r--src/test/ui/consts/const-external-macro-const-err.rs3
-rw-r--r--src/test/ui/consts/const-external-macro-const-err.stderr18
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.rs24
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.stderr199
-rw-r--r--src/test/ui/consts/const-fn-error.rs6
-rw-r--r--src/test/ui/consts/const-fn-error.stderr4
-rw-r--r--src/test/ui/consts/const-for.rs4
-rw-r--r--src/test/ui/consts/const-for.stderr4
-rw-r--r--src/test/ui/consts/const-int-arithmetic-overflow.rs1
-rw-r--r--src/test/ui/consts/const-len-underflow-separate-spans.rs3
-rw-r--r--src/test/ui/consts/const-len-underflow-separate-spans.stderr21
-rw-r--r--src/test/ui/consts/const-negation.rs2
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.rs3
-rw-r--r--src/test/ui/consts/const-prop-read-static-in-const.stderr20
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs6
-rw-r--r--src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr40
-rw-r--r--src/test/ui/consts/const-slice-oob.rs5
-rw-r--r--src/test/ui/consts/const-slice-oob.stderr22
-rw-r--r--src/test/ui/consts/const_discriminant.rs1
-rw-r--r--src/test/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr2
-rw-r--r--src/test/ui/consts/const_in_pattern/incomplete-slice.stderr2
-rw-r--r--src/test/ui/consts/const_in_pattern/issue-44333.stderr4
-rw-r--r--src/test/ui/consts/const_in_pattern/reject_non_structural.stderr4
-rw-r--r--src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr2
-rw-r--r--src/test/ui/consts/const_limit/const_eval_limit_reached.rs3
-rw-r--r--src/test/ui/consts/const_limit/const_eval_limit_reached.stderr24
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable_ub.stderr10
-rw-r--r--src/test/ui/consts/constifconst-call-in-const-position.rs22
-rw-r--r--src/test/ui/consts/constifconst-call-in-const-position.stderr18
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.precise.stderr8
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.rs8
-rw-r--r--src/test/ui/consts/control-flow/drop-fail.stock.stderr16
-rw-r--r--src/test/ui/consts/control-flow/issue-50577.stderr2
-rw-r--r--src/test/ui/consts/dangling-alloc-id-ice.rs1
-rw-r--r--src/test/ui/consts/dangling-alloc-id-ice.stderr2
-rw-r--r--src/test/ui/consts/drop_box.rs2
-rw-r--r--src/test/ui/consts/drop_box.stderr4
-rw-r--r--src/test/ui/consts/drop_zst.stderr4
-rw-r--r--src/test/ui/consts/extra-const-ub/detect-extra-ub.rs9
-rw-r--r--src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr75
-rw-r--r--src/test/ui/consts/invalid-union.32bit.stderr17
-rw-r--r--src/test/ui/consts/invalid-union.64bit.stderr17
-rw-r--r--src/test/ui/consts/invalid-union.rs1
-rw-r--r--src/test/ui/consts/issue-102117.rs30
-rw-r--r--src/test/ui/consts/issue-102117.stderr37
-rw-r--r--src/test/ui/consts/issue-104155.rs5
-rw-r--r--src/test/ui/consts/issue-17718-constants-not-static.rs (renamed from src/test/ui/issues/issue-17718-constants-not-static.rs)0
-rw-r--r--src/test/ui/consts/issue-17718-constants-not-static.stderr (renamed from src/test/ui/issues/issue-17718-constants-not-static.stderr)0
-rw-r--r--src/test/ui/consts/issue-25826.stderr4
-rw-r--r--src/test/ui/consts/issue-46553.rs1
-rw-r--r--src/test/ui/consts/issue-56164.rs5
-rw-r--r--src/test/ui/consts/issue-56164.stderr22
-rw-r--r--src/test/ui/consts/issue-66693.rs3
-rw-r--r--src/test/ui/consts/issue-66693.stderr18
-rw-r--r--src/test/ui/consts/issue-78655.stderr5
-rw-r--r--src/test/ui/consts/issue-88071.rs2
-rw-r--r--src/test/ui/consts/issue-94675.rs5
-rw-r--r--src/test/ui/consts/issue-94675.stderr31
-rw-r--r--src/test/ui/consts/issue-miri-1910.stderr42
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.rs6
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr20
-rw-r--r--src/test/ui/consts/miri_unleashed/abi-mismatch.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/abi-mismatch.stderr8
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.stderr46
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const_2.rs4
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const_2.stderr25
-rw-r--r--src/test/ui/consts/miri_unleashed/box.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/box.stderr10
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr81
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr81
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.rs34
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr100
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr38
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr38
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs24
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr104
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr104
-rw-r--r--src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs14
-rw-r--r--src/test/ui/consts/miri_unleashed/drop.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/drop.stderr6
-rw-r--r--src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs4
-rw-r--r--src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr6
-rw-r--r--src/test/ui/consts/miri_unleashed/inline_asm.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/inline_asm.stderr4
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_references.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_references.stderr12
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr12
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr12
-rw-r--r--src/test/ui/consts/miri_unleashed/mutable_references_err.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/mutating_global.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/mutating_global.stderr2
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/non_const_fn.stderr4
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.stderr6
-rw-r--r--src/test/ui/consts/miri_unleashed/raw_mutable_const.rs2
-rw-r--r--src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr4
-rw-r--r--src/test/ui/consts/miri_unleashed/tls.rs1
-rw-r--r--src/test/ui/consts/miri_unleashed/tls.stderr8
-rw-r--r--src/test/ui/consts/promote-not.rs2
-rw-r--r--src/test/ui/consts/ptr_comparisons.rs6
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr41
-rw-r--r--src/test/ui/consts/qualif-indirect-mutation-fail.rs18
-rw-r--r--src/test/ui/consts/qualif-indirect-mutation-fail.stderr36
-rw-r--r--src/test/ui/consts/raw-ptr-const.rs2
-rw-r--r--src/test/ui/consts/raw-ptr-const.stderr2
-rw-r--r--src/test/ui/consts/recursive.rs3
-rw-r--r--src/test/ui/consts/recursive.stderr31
-rw-r--r--src/test/ui/consts/refs_check_const_eq-issue-88384.stderr2
-rw-r--r--src/test/ui/consts/stable-precise-live-drops-in-libcore.rs2
-rw-r--r--src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr4
-rw-r--r--src/test/ui/consts/trait_specialization.stderr2
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.rs3
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.stderr285
-rw-r--r--src/test/ui/consts/unstable-const-fn-in-libcore.rs10
-rw-r--r--src/test/ui/consts/unstable-const-fn-in-libcore.stderr33
-rw-r--r--src/test/ui/consts/write_to_static_via_mut_ref.rs1
-rw-r--r--src/test/ui/consts/write_to_static_via_mut_ref.stderr4
-rw-r--r--src/test/ui/deprecation/deprecation-lint.rs2
-rw-r--r--src/test/ui/derive-uninhabited-enum-38885.stderr2
-rw-r--r--src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr2
-rw-r--r--src/test/ui/derives/deriving-with-repr-packed.stderr20
-rw-r--r--src/test/ui/deriving/deriving-all-codegen.stdout72
-rw-r--r--src/test/ui/deriving/deriving-default-enum.rs10
-rw-r--r--src/test/ui/deriving/deriving-hash.rs20
-rw-r--r--src/test/ui/destructuring-assignment/warn-unused-duplication.stderr2
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-ty.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-31424.stderr2
-rw-r--r--src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed5
-rw-r--r--src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs5
-rw-r--r--src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr34
-rw-r--r--src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr16
-rw-r--r--src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr10
-rw-r--r--src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr4
-rw-r--r--src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr16
-rw-r--r--src/test/ui/did_you_mean/issue-54109-without-witness.stderr16
-rw-r--r--src/test/ui/drop/drop_order.rs64
-rw-r--r--src/test/ui/drop/dropck_legal_cycles.rs14
-rw-r--r--src/test/ui/drop/dynamic-drop-async.rs1
-rw-r--r--src/test/ui/drop/dynamic-drop.rs1
-rw-r--r--src/test/ui/drop/issue-100276.rs12
-rw-r--r--src/test/ui/drop/issue-17718-const-destructors.rs (renamed from src/test/ui/issues/issue-17718-const-destructors.rs)0
-rw-r--r--src/test/ui/drop/issue-23338-ensure-param-drop-order.rs (renamed from src/test/ui/issues/issue-23338-ensure-param-drop-order.rs)0
-rw-r--r--src/test/ui/drop/issue-48962.rs (renamed from src/test/ui/issues/issue-48962.rs)0
-rw-r--r--src/test/ui/drop/repeat-drop-2.rs2
-rw-r--r--src/test/ui/drop/repeat-drop-2.stderr9
-rw-r--r--src/test/ui/drop/repeat-drop.rs3
-rw-r--r--src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr12
-rw-r--r--src/test/ui/dropck/issue-24805-dropck-itemless.rs (renamed from src/test/ui/issues/issue-24805-dropck-itemless.rs)0
-rw-r--r--src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr4
-rw-r--r--src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr4
-rw-r--r--src/test/ui/dyn-keyword/dyn-angle-brackets.stderr4
-rw-r--r--src/test/ui/dyn-star/auxiliary/dyn-star-foreign.rs10
-rw-r--r--src/test/ui/dyn-star/box.rs17
-rw-r--r--src/test/ui/dyn-star/const.rs2
-rw-r--r--src/test/ui/dyn-star/drop.rs2
-rw-r--r--src/test/ui/dyn-star/error.rs2
-rw-r--r--src/test/ui/dyn-star/error.stderr2
-rw-r--r--src/test/ui/dyn-star/make-dyn-star.rs5
-rw-r--r--src/test/ui/dyn-star/method.rs3
-rw-r--r--src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs13
-rw-r--r--src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr28
-rw-r--r--src/test/ui/dyn-star/no-explicit-dyn-star.rs8
-rw-r--r--src/test/ui/dyn-star/no-explicit-dyn-star.stderr9
-rw-r--r--src/test/ui/dyn-star/no-implicit-dyn-star.rs8
-rw-r--r--src/test/ui/dyn-star/no-implicit-dyn-star.stderr19
-rw-r--r--src/test/ui/dyn-star/upcast.rs33
-rw-r--r--src/test/ui/editions/edition-raw-pointer-method-2015.stderr4
-rw-r--r--src/test/ui/empty/empty-attributes.stderr2
-rw-r--r--src/test/ui/empty/empty-struct-braces-expr.stderr46
-rw-r--r--src/test/ui/empty_global_asm.rs15
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs1
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr2
-rw-r--r--src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs2
-rw-r--r--src/test/ui/enum-discriminant/discriminant_size.stderr2
-rw-r--r--src/test/ui/enum-discriminant/discriminant_value.rs2
-rw-r--r--src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs10
-rw-r--r--src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr36
-rw-r--r--src/test/ui/enum-discriminant/issue-43398.stderr2
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.rs2
-rw-r--r--src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr4
-rw-r--r--src/test/ui/enum-discriminant/repr128.stderr2
-rw-r--r--src/test/ui/enum/enum-discrim-too-small2.stderr4
-rw-r--r--src/test/ui/error-codes/E0017.stderr2
-rw-r--r--src/test/ui/error-codes/E0094.rs2
-rw-r--r--src/test/ui/error-codes/E0094.stderr2
-rw-r--r--src/test/ui/error-codes/E0199.stderr6
-rw-r--r--src/test/ui/error-codes/E0200.stderr6
-rw-r--r--src/test/ui/error-codes/E0201.rs2
-rw-r--r--src/test/ui/error-codes/E0201.stderr33
-rw-r--r--src/test/ui/error-codes/E0283.stderr4
-rw-r--r--src/test/ui/error-codes/E0308.rs2
-rw-r--r--src/test/ui/error-codes/E0308.stderr2
-rw-r--r--src/test/ui/error-codes/E0311.rs9
-rw-r--r--src/test/ui/error-codes/E0311.stderr24
-rw-r--r--src/test/ui/error-codes/E0388.stderr2
-rw-r--r--src/test/ui/error-codes/E0423.stderr22
-rw-r--r--src/test/ui/error-codes/E0520.stderr2
-rw-r--r--src/test/ui/error-codes/E0585.stderr2
-rw-r--r--src/test/ui/error-codes/E0771.stderr2
-rw-r--r--src/test/ui/error-codes/E0790.stderr20
-rw-r--r--src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr2
-rw-r--r--src/test/ui/explain.stdout4
-rw-r--r--src/test/ui/expr/if/bad-if-let-suggestion.stderr5
-rw-r--r--src/test/ui/expr/if/if-let.stderr2
-rw-r--r--src/test/ui/expr/if/if-without-else-result.rs2
-rw-r--r--src/test/ui/expr/if/if-without-else-result.stderr2
-rw-r--r--src/test/ui/expr/if/issue-4201.rs2
-rw-r--r--src/test/ui/expr/if/issue-4201.stderr2
-rw-r--r--src/test/ui/expr/malformed_closure/ruby_style_closure.stderr2
-rw-r--r--src/test/ui/extenv/issue-55897.rs2
-rw-r--r--src/test/ui/extenv/issue-55897.stderr7
-rw-r--r--src/test/ui/extern-flag/empty-extern-arg.rs2
-rw-r--r--src/test/ui/extern/extern-no-mangle.stderr2
-rw-r--r--src/test/ui/extern/extern-with-type-bounds.rs2
-rw-r--r--src/test/ui/extern/extern-with-type-bounds.stderr2
-rw-r--r--src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs1
-rw-r--r--src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs1
-rw-r--r--src/test/ui/feature-gates/bench.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_sym.rs19
-rw-r--r--src/test/ui/feature-gates/feature-gate-asm_sym.stderr21
-rw-r--r--src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-repr-simd.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs13
-rw-r--r--src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr22
-rw-r--r--src/test/ui/feature-gates/feature-gate-strict_provenance.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-test_unstable_lint.stderr2
-rw-r--r--src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr2
-rw-r--r--src/test/ui/fmt/auxiliary/format-string-proc-macro.rs28
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-102057.rs19
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-102057.stderr45
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-93378.rs4
-rw-r--r--src/test/ui/fmt/format-args-capture-issue-93378.stderr17
-rw-r--r--src/test/ui/fmt/format-args-capture-macro-hygiene.rs18
-rw-r--r--src/test/ui/fmt/format-args-capture-macro-hygiene.stderr37
-rw-r--r--src/test/ui/fmt/format-concat-span.stderr11
-rw-r--r--src/test/ui/fmt/format-expanded-string.rs (renamed from src/test/ui/fmt/format-concat-span.rs)9
-rw-r--r--src/test/ui/fmt/format-expanded-string.stderr19
-rw-r--r--src/test/ui/fmt/ifmt-bad-arg.rs8
-rw-r--r--src/test/ui/fmt/ifmt-bad-arg.stderr98
-rw-r--r--src/test/ui/for-loop-while/while-let-2.stderr2
-rw-r--r--src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr12
-rw-r--r--src/test/ui/function-pointer/issue-102289.rs54
-rw-r--r--src/test/ui/function-pointer/sized-ret-with-binder.rs15
-rw-r--r--src/test/ui/function-pointer/unsized-ret.rs14
-rw-r--r--src/test/ui/function-pointer/unsized-ret.stderr35
-rw-r--r--src/test/ui/future-incompatible-lint-group.stderr8
-rw-r--r--src/test/ui/generator/issue-102645.rs23
-rw-r--r--src/test/ui/generator/issue-102645.stderr19
-rw-r--r--src/test/ui/generator/issue-52398.stderr2
-rw-r--r--src/test/ui/generator/issue-57084.stderr2
-rw-r--r--src/test/ui/generator/match-bindings.stderr2
-rw-r--r--src/test/ui/generator/panic-drops-resume.rs2
-rw-r--r--src/test/ui/generator/panic-drops.rs1
-rw-r--r--src/test/ui/generator/panic-safe.rs1
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-1.stderr8
-rw-r--r--src/test/ui/generator/reborrow-mut-upvar.stderr2
-rw-r--r--src/test/ui/generator/resume-after-return.rs1
-rw-r--r--src/test/ui/generator/size-moved-locals.rs1
-rw-r--r--src/test/ui/generator/too-live-local-in-immovable-gen.stderr2
-rw-r--r--src/test/ui/generator/yield-in-args-rev.stderr2
-rw-r--r--src/test/ui/generator/yield-in-box.stderr2
-rw-r--r--src/test/ui/generator/yield-in-initializer.stderr2
-rw-r--r--src/test/ui/generator/yield-subtype.stderr2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-86218.stderr23
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88382.stderr4
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-89008.stderr19
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-91762.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-102114.rs16
-rw-r--r--src/test/ui/generic-associated-types/issue-102114.stderr12
-rw-r--r--src/test/ui/generic-associated-types/issue-86218-2.rs23
-rw-r--r--src/test/ui/generic-associated-types/issue-86218.rs (renamed from src/test/ui/generic-associated-types/bugs/issue-86218.rs)8
-rw-r--r--src/test/ui/generic-associated-types/issue-87258_a.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-87429-specialization.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-89008.rs (renamed from src/test/ui/generic-associated-types/bugs/issue-89008.rs)28
-rw-r--r--src/test/ui/generics/issue-94923.rs49
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr6
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs7
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr12
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs18
-rw-r--r--src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr53
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr6
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr136
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr10
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr12
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr16
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr52
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-4.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-5.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/pat-tuple-5.stderr2
-rw-r--r--src/test/ui/half-open-range-patterns/range_pat_interactions0.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/range_pat_interactions3.rs3
-rw-r--r--src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr11
-rw-r--r--src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs2
-rw-r--r--src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs1
-rw-r--r--src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr13
-rw-r--r--src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-100689.rs29
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-102899.rs32
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-30786.stderr10
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-46989.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-95034.rs20
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-95034.stderr1
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr16
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr6
-rw-r--r--src/test/ui/hygiene/globs.stderr18
-rw-r--r--src/test/ui/hygiene/impl_items-2.rs26
-rw-r--r--src/test/ui/hygiene/impl_items-2.stderr15
-rw-r--r--src/test/ui/hygiene/impl_items.rs2
-rw-r--r--src/test/ui/hygiene/impl_items.stderr2
-rw-r--r--src/test/ui/hygiene/rustc-macro-transparency.stderr8
-rw-r--r--src/test/ui/impl-duplicate-methods.stderr11
-rw-r--r--src/test/ui/impl-trait/auto-trait-leak.stderr8
-rw-r--r--src/test/ui/impl-trait/equality-rpass.stderr2
-rw-r--r--src/test/ui/impl-trait/equality.stderr2
-rw-r--r--src/test/ui/impl-trait/equality2.stderr2
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr4
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr4
-rw-r--r--src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs2
-rw-r--r--src/test/ui/impl-trait/hidden-lifetimes.stderr8
-rw-r--r--src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs11
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs13
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr11
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err.rs13
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-type-err.stderr12
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs21
-rw-r--r--src/test/ui/impl-trait/in-trait/default-body.rs21
-rw-r--r--src/test/ui/impl-trait/in-trait/early.rs23
-rw-r--r--src/test/ui/impl-trait/in-trait/foreign.rs9
-rw-r--r--src/test/ui/impl-trait/in-trait/issue-102140.rs30
-rw-r--r--src/test/ui/impl-trait/in-trait/issue-102140.stderr29
-rw-r--r--src/test/ui/impl-trait/in-trait/issue-102301.rs18
-rw-r--r--src/test/ui/impl-trait/in-trait/issue-102571.rs24
-rw-r--r--src/test/ui/impl-trait/in-trait/issue-102571.stderr14
-rw-r--r--src/test/ui/impl-trait/in-trait/signature-mismatch.rs21
-rw-r--r--src/test/ui/impl-trait/in-trait/signature-mismatch.stderr16
-rw-r--r--src/test/ui/impl-trait/issue-100075-2.stderr2
-rw-r--r--src/test/ui/impl-trait/issue-102605.rs15
-rw-r--r--src/test/ui/impl-trait/issue-102605.stderr41
-rw-r--r--src/test/ui/impl-trait/issue-103181-1.rs85
-rw-r--r--src/test/ui/impl-trait/issue-103181-1.stderr12
-rw-r--r--src/test/ui/impl-trait/issue-103181-2.rs29
-rw-r--r--src/test/ui/impl-trait/issue-103181-2.stderr9
-rw-r--r--src/test/ui/impl-trait/issue-103599.stderr2
-rw-r--r--src/test/ui/impl-trait/issue-86465.rs6
-rw-r--r--src/test/ui/impl-trait/issue-86465.stderr2
-rw-r--r--src/test/ui/impl-trait/issue-87450.stderr2
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.rs2
-rw-r--r--src/test/ui/impl-trait/issues/issue-78722.stderr4
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.stderr15
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr2
-rw-r--r--src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr2
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr14
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.stderr17
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.stderr17
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait.stderr17
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait2.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait2.stderr17
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait3.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type3-tait3.stderr17
-rw-r--r--src/test/ui/impl-trait/nested-return-type3.rs1
-rw-r--r--src/test/ui/impl-trait/nested-return-type3.stderr17
-rw-r--r--src/test/ui/impl-trait/normalize-tait-in-const.rs39
-rw-r--r--src/test/ui/impl-trait/normalize-tait-in-const.stderr8
-rw-r--r--src/test/ui/impl-trait/region-escape-via-bound.stderr2
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr8
-rw-r--r--src/test/ui/impl-trait/unactionable_diagnostic.fixed25
-rw-r--r--src/test/ui/impl-trait/unactionable_diagnostic.rs25
-rw-r--r--src/test/ui/impl-trait/unactionable_diagnostic.stderr14
-rw-r--r--src/test/ui/impl-trait/where-allowed.stderr2
-rw-r--r--src/test/ui/imports/issue-56125.stderr12
-rw-r--r--src/test/ui/imports/issue-57015.stderr5
-rw-r--r--src/test/ui/imports/local-modularized-tricky-fail-2.stderr2
-rw-r--r--src/test/ui/inference/char-as-str-single.fixed1
-rw-r--r--src/test/ui/inference/char-as-str-single.rs1
-rw-r--r--src/test/ui/inference/char-as-str-single.stderr15
-rw-r--r--src/test/ui/inference/inference-variable-behind-raw-pointer.stderr2
-rw-r--r--src/test/ui/inference/inference_unstable.stderr2
-rw-r--r--src/test/ui/inference/issue-36053.rs (renamed from src/test/ui/issues/issue-36053.rs)0
-rw-r--r--src/test/ui/inference/need_type_info/concrete-impl.stderr9
-rw-r--r--src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs11
-rw-r--r--src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr9
-rw-r--r--src/test/ui/inference/need_type_info/issue-103053.rs18
-rw-r--r--src/test/ui/inference/need_type_info/issue-103053.stderr14
-rw-r--r--src/test/ui/inference/str-as-char.fixed4
-rw-r--r--src/test/ui/inference/str-as-char.rs4
-rw-r--r--src/test/ui/inference/str-as-char.stderr24
-rw-r--r--src/test/ui/infinite/infinite-struct.rs7
-rw-r--r--src/test/ui/infinite/infinite-struct.stderr19
-rw-r--r--src/test/ui/infinite/infinite-tag-type-recursion.stderr4
-rw-r--r--src/test/ui/inline-const/const-match-pat-range.rs3
-rw-r--r--src/test/ui/intrinsics/const-eval-select-backtrace-std.rs1
-rw-r--r--src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr2
-rw-r--r--src/test/ui/intrinsics/const-eval-select-backtrace.rs1
-rw-r--r--src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr2
-rw-r--r--src/test/ui/intrinsics/intrinsic-alignment.rs1
-rw-r--r--src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs1
-rw-r--r--src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr2
-rw-r--r--src/test/ui/intrinsics/intrinsic-raw_eq-const.rs1
-rw-r--r--src/test/ui/intrinsics/intrinsics-integer.rs6
-rw-r--r--src/test/ui/intrinsics/panic-uninitialized-zeroed.rs253
-rw-r--r--src/test/ui/intrinsics/safe-intrinsic-mismatch.rs11
-rw-r--r--src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr14
-rw-r--r--src/test/ui/invalid/invalid-inline.rs9
-rw-r--r--src/test/ui/invalid/invalid-inline.stderr15
-rw-r--r--src/test/ui/invalid/invalid-llvm-passes.rs2
-rw-r--r--src/test/ui/issues/issue-102964.rs10
-rw-r--r--src/test/ui/issues/issue-102964.stderr19
-rw-r--r--src/test/ui/issues/issue-11958.stderr4
-rw-r--r--src/test/ui/issues/issue-1460.stderr2
-rw-r--r--src/test/ui/issues/issue-14875.rs1
-rw-r--r--src/test/ui/issues/issue-16250.stderr12
-rw-r--r--src/test/ui/issues/issue-16256.stderr2
-rw-r--r--src/test/ui/issues/issue-17431-1.stderr10
-rw-r--r--src/test/ui/issues/issue-17431-2.rs3
-rw-r--r--src/test/ui/issues/issue-17431-2.stderr31
-rw-r--r--src/test/ui/issues/issue-17431-3.stderr10
-rw-r--r--src/test/ui/issues/issue-17431-4.stderr10
-rw-r--r--src/test/ui/issues/issue-17431-5.stderr4
-rw-r--r--src/test/ui/issues/issue-17431-6.stderr10
-rw-r--r--src/test/ui/issues/issue-17431-7.stderr10
-rw-r--r--src/test/ui/issues/issue-18919.stderr4
-rw-r--r--src/test/ui/issues/issue-19991.rs2
-rw-r--r--src/test/ui/issues/issue-19991.stderr2
-rw-r--r--src/test/ui/issues/issue-21174.stderr4
-rw-r--r--src/test/ui/issues/issue-22644.rs2
-rw-r--r--src/test/ui/issues/issue-22644.stderr2
-rw-r--r--src/test/ui/issues/issue-23122-2.rs1
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr9
-rw-r--r--src/test/ui/issues/issue-24013.stderr5
-rw-r--r--src/test/ui/issues/issue-24322.stderr4
-rw-r--r--src/test/ui/issues/issue-25901.rs2
-rw-r--r--src/test/ui/issues/issue-25901.stderr22
-rw-r--r--src/test/ui/issues/issue-28344.stderr2
-rw-r--r--src/test/ui/issues/issue-29746.rs2
-rw-r--r--src/test/ui/issues/issue-29948.rs1
-rw-r--r--src/test/ui/issues/issue-3008-1.stderr4
-rw-r--r--src/test/ui/issues/issue-3008-2.stderr4
-rw-r--r--src/test/ui/issues/issue-3008-3.stderr4
-rw-r--r--src/test/ui/issues/issue-30371.rs1
-rw-r--r--src/test/ui/issues/issue-30490.rs1
-rw-r--r--src/test/ui/issues/issue-32326.stderr12
-rw-r--r--src/test/ui/issues/issue-35241.stderr2
-rw-r--r--src/test/ui/issues/issue-3563-2.rs14
-rw-r--r--src/test/ui/issues/issue-3779.stderr6
-rw-r--r--src/test/ui/issues/issue-40000.stderr4
-rw-r--r--src/test/ui/issues/issue-4265.stderr8
-rw-r--r--src/test/ui/issues/issue-43853.rs1
-rw-r--r--src/test/ui/issues/issue-46519.rs1
-rw-r--r--src/test/ui/issues/issue-47094.stderr2
-rw-r--r--src/test/ui/issues/issue-47486.stderr5
-rw-r--r--src/test/ui/issues/issue-47725.stderr2
-rw-r--r--src/test/ui/issues/issue-50582.stderr4
-rw-r--r--src/test/ui/issues/issue-50781.stderr10
-rw-r--r--src/test/ui/issues/issue-54044.stderr2
-rw-r--r--src/test/ui/issues/issue-55380.stderr2
-rw-r--r--src/test/ui/issues/issue-57271.rs4
-rw-r--r--src/test/ui/issues/issue-57271.stderr28
-rw-r--r--src/test/ui/issues/issue-57362-2.stderr6
-rw-r--r--src/test/ui/issues/issue-58022.stderr12
-rw-r--r--src/test/ui/issues/issue-58734.stderr2
-rw-r--r--src/test/ui/issues/issue-59488.stderr4
-rw-r--r--src/test/ui/issues/issue-60622.stderr4
-rw-r--r--src/test/ui/issues/issue-6458-3.stderr6
-rw-r--r--src/test/ui/issues/issue-6458-4.stderr2
-rw-r--r--src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr2
-rw-r--r--src/test/ui/issues/issue-72278.stderr2
-rw-r--r--src/test/ui/issues/issue-72554.rs1
-rw-r--r--src/test/ui/issues/issue-72554.stderr24
-rw-r--r--src/test/ui/issues/issue-75307.rs2
-rw-r--r--src/test/ui/issues/issue-75307.stderr8
-rw-r--r--src/test/ui/issues/issue-75907.rs2
-rw-r--r--src/test/ui/issues/issue-75907_b.rs2
-rw-r--r--src/test/ui/issues/issue-77993-1.rs12
-rw-r--r--src/test/ui/issues/issue-77993-1.stderr16
-rw-r--r--src/test/ui/issues/issue-78957.stderr2
-rw-r--r--src/test/ui/issues/issue-86756.stderr2
-rw-r--r--src/test/ui/issues/issue-8727.stderr2
-rw-r--r--src/test/ui/issues/issue-87707.rs1
-rw-r--r--src/test/ui/issues/issue-87707.run.stderr4
-rw-r--r--src/test/ui/issues/issue-99838.rs2
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-2018.stderr2
-rw-r--r--src/test/ui/iterators/into-iter-on-arrays-lint.stderr2
-rw-r--r--src/test/ui/iterators/iter-count-overflow-debug.rs1
-rw-r--r--src/test/ui/iterators/iter-position-overflow-debug.rs1
-rw-r--r--src/test/ui/iterators/iter-step-overflow-debug.rs1
-rw-r--r--src/test/ui/iterators/iter-sum-overflow-debug.rs1
-rw-r--r--src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs1
-rw-r--r--src/test/ui/keyword/keyword-self-as-type-param.stderr4
-rw-r--r--src/test/ui/lang-items/issue-83471.stderr14
-rw-r--r--src/test/ui/let-else/const-fn.rs1
-rw-r--r--src/test/ui/let-else/let-else-brace-before-else.stderr8
-rw-r--r--src/test/ui/let-else/let-else-irrefutable.stderr2
-rw-r--r--src/test/ui/let-else/let-else-non-diverging.rs11
-rw-r--r--src/test/ui/let-else/let-else-non-diverging.stderr13
-rw-r--r--src/test/ui/let-else/let-else-then-diverge.rs4
-rw-r--r--src/test/ui/let-else/let-else-then-diverge.stderr4
-rw-r--r--src/test/ui/lexer/lex-emoji-identifiers.rs17
-rw-r--r--src/test/ui/lexer/lex-emoji-identifiers.stderr52
-rw-r--r--src/test/ui/lexical-scopes.stderr2
-rw-r--r--src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs11
-rw-r--r--src/test/ui/lifetimes/issue-79187-2.stderr2
-rw-r--r--src/test/ui/lifetimes/issue-79187.stderr2
-rw-r--r--src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr2
-rw-r--r--src/test/ui/lifetimes/nested-binder-print.rs10
-rw-r--r--src/test/ui/lifetimes/nested-binder-print.stderr14
-rw-r--r--src/test/ui/lifetimes/re-empty-in-error.stderr2
-rw-r--r--src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr1
-rw-r--r--src/test/ui/lifetimes/unusual-rib-combinations.rs28
-rw-r--r--src/test/ui/lifetimes/unusual-rib-combinations.stderr61
-rw-r--r--src/test/ui/limits/issue-55878.stderr17
-rw-r--r--src/test/ui/linkage-attr/link-attr-validation-early.stderr2
-rw-r--r--src/test/ui/lint/auxiliary/trivial-cast-ice.rs7
-rw-r--r--src/test/ui/lint/bare-trait-objects-path.stderr2
-rw-r--r--src/test/ui/lint/clashing-extern-fn.stderr6
-rw-r--r--src/test/ui/lint/cli-lint-override.forbid_warn.stderr2
-rw-r--r--src/test/ui/lint/cli-lint-override.force_warn_deny.stderr2
-rw-r--r--src/test/ui/lint/cli-lint-override.warn_deny.stderr2
-rw-r--r--src/test/ui/lint/dead-code/issue-85071-2.stderr10
-rw-r--r--src/test/ui/lint/dead-code/issue-85071.stderr10
-rw-r--r--src/test/ui/lint/dead-code/unused-variant.stderr2
-rw-r--r--src/test/ui/lint/deny-overflowing-literals.stderr2
-rw-r--r--src/test/ui/lint/expansion-time.stderr8
-rw-r--r--src/test/ui/lint/fn_must_use.stderr2
-rw-r--r--src/test/ui/lint/for_loop_over_fallibles.rs43
-rw-r--r--src/test/ui/lint/for_loop_over_fallibles.stderr101
-rw-r--r--src/test/ui/lint/forbid-group-group-2.stderr4
-rw-r--r--src/test/ui/lint/forbid-group-member.stderr2
-rw-r--r--src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs12
-rw-r--r--src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr23
-rw-r--r--src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs14
-rw-r--r--src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr23
-rw-r--r--src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr2
-rw-r--r--src/test/ui/lint/force-warn/cap-lints-allow.stderr2
-rw-r--r--src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr2
-rw-r--r--src/test/ui/lint/force-warn/deny-by-default-lint.rs12
-rw-r--r--src/test/ui/lint/force-warn/deny-by-default-lint.stderr23
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-lint-group.stderr2
-rw-r--r--src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr2
-rw-r--r--src/test/ui/lint/inclusive-range-pattern-syntax.stderr4
-rw-r--r--src/test/ui/lint/inert-attr-macro.stderr10
-rw-r--r--src/test/ui/lint/inline-trait-and-foreign-items.stderr6
-rw-r--r--src/test/ui/lint/invalid_value.rs (renamed from src/test/ui/lint/uninitialized-zeroed.rs)40
-rw-r--r--src/test/ui/lint/invalid_value.stderr (renamed from src/test/ui/lint/uninitialized-zeroed.stderr)242
-rw-r--r--src/test/ui/lint/issue-102705.rs22
-rw-r--r--src/test/ui/lint/issue-14309.stderr10
-rw-r--r--src/test/ui/lint/issue-1866.stderr4
-rw-r--r--src/test/ui/lint/issue-63364.stderr2
-rw-r--r--src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr4
-rw-r--r--src/test/ui/lint/issue-79744.stderr2
-rw-r--r--src/test/ui/lint/issue-80988.stderr2
-rw-r--r--src/test/ui/lint/issue-83477.stderr2
-rw-r--r--src/test/ui/lint/issue-86600-lint-twice.stderr2
-rw-r--r--src/test/ui/lint/lint-attr-everywhere-early.stderr4
-rw-r--r--src/test/ui/lint/lint-attr-everywhere-late.stderr120
-rw-r--r--src/test/ui/lint/lint-const-item-mutation.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-2.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-3.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73249-5.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-1.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-73251-2.stderr2
-rw-r--r--src/test/ui/lint/lint-ctypes-enum.stderr10
-rw-r--r--src/test/ui/lint/lint-ctypes-fn.stderr4
-rw-r--r--src/test/ui/lint/lint-ctypes.stderr10
-rw-r--r--src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr2
-rw-r--r--src/test/ui/lint/lint-exceeding-bitshifts.rs2
-rw-r--r--src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr44
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-bool.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-fence.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-int.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-ptr.stderr2
-rw-r--r--src/test/ui/lint/lint-invalid-atomic-ordering-uint.stderr2
-rw-r--r--src/test/ui/lint/lint-non-snake-case-crate-2.stderr2
-rw-r--r--src/test/ui/lint/lint-output-format.rs1
-rw-r--r--src/test/ui/lint/lint-output-format.stderr12
-rw-r--r--src/test/ui/lint/lint-pre-expansion-extern-module.stderr2
-rw-r--r--src/test/ui/lint/lint-stability-deprecated.rs2
-rw-r--r--src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr2
-rw-r--r--src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr2
-rw-r--r--src/test/ui/lint/lint-temporary-cstring-as-param.stderr4
-rw-r--r--src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr4
-rw-r--r--src/test/ui/lint/lint-type-limits2.stderr4
-rw-r--r--src/test/ui/lint/lint-type-limits3.stderr4
-rw-r--r--src/test/ui/lint/lint-type-overflow.stderr2
-rw-r--r--src/test/ui/lint/lint-type-overflow2.rs1
-rw-r--r--src/test/ui/lint/lint-type-overflow2.stderr14
-rw-r--r--src/test/ui/lint/lint-unconditional-recursion.stderr2
-rw-r--r--src/test/ui/lint/lint-unsafe-code.stderr2
-rw-r--r--src/test/ui/lint/must_not_suspend/boxed.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/dedup.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/gated.stderr2
-rw-r--r--src/test/ui/lint/must_not_suspend/mutex.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/trait.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/unit.stderr10
-rw-r--r--src/test/ui/lint/must_not_suspend/warn.stderr10
-rw-r--r--src/test/ui/lint/no-coverage.stderr2
-rw-r--r--src/test/ui/lint/noop-method-call.rs1
-rw-r--r--src/test/ui/lint/noop-method-call.stderr14
-rw-r--r--src/test/ui/lint/opaque-ty-ffi-unsafe.stderr2
-rw-r--r--src/test/ui/lint/outer-forbid.stderr4
-rw-r--r--src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr2
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr2
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr2
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr2
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr16
-rw-r--r--src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr2
-rw-r--r--src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr4
-rw-r--r--src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr8
-rw-r--r--src/test/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr2
-rw-r--r--src/test/ui/lint/trivial-cast-ice.rs12
-rw-r--r--src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr4
-rw-r--r--src/test/ui/lint/trivial-casts.stderr4
-rw-r--r--src/test/ui/lint/trivial_casts.stderr4
-rw-r--r--src/test/ui/lint/type-overflow.stderr4
-rw-r--r--src/test/ui/lint/unaligned_references.stderr80
-rw-r--r--src/test/ui/lint/unaligned_references_external_macro.stderr16
-rw-r--r--src/test/ui/lint/unreachable_pub.stderr2
-rw-r--r--src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr2
-rw-r--r--src/test/ui/lint/unused/must-use-box-from-raw.stderr2
-rw-r--r--src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr2
-rw-r--r--src/test/ui/lint/unused/must_use-tuple.stderr2
-rw-r--r--src/test/ui/lint/unused/unused-attr-duplicate.stderr10
-rw-r--r--src/test/ui/lint/unused/unused-closure.stderr2
-rw-r--r--src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr2
-rw-r--r--src/test/ui/lint/unused/unused-doc-comments-for-macros.stderr2
-rw-r--r--src/test/ui/lint/unused/unused-supertrait.rs11
-rw-r--r--src/test/ui/lint/unused/unused-supertrait.stderr15
-rw-r--r--src/test/ui/lint/unused/unused_attributes-must_use.stderr10
-rw-r--r--src/test/ui/lint/unused/useless-comment.stderr2
-rw-r--r--src/test/ui/liveness/liveness-asm.stderr2
-rw-r--r--src/test/ui/liveness/liveness-consts.stderr4
-rw-r--r--src/test/ui/liveness/liveness-dead.stderr2
-rw-r--r--src/test/ui/liveness/liveness-return-last-stmt-semi.rs1
-rw-r--r--src/test/ui/liveness/liveness-return-last-stmt-semi.stderr10
-rw-r--r--src/test/ui/liveness/liveness-unused.stderr2
-rw-r--r--src/test/ui/liveness/liveness-upvars.stderr4
-rw-r--r--src/test/ui/loops/loop-proper-liveness.stderr4
-rw-r--r--src/test/ui/macros/format-parse-errors.stderr2
-rw-r--r--src/test/ui/macros/issue-102878.rs10
-rw-r--r--src/test/ui/macros/issue-102878.stderr60
-rw-r--r--src/test/ui/macros/issue-39404.stderr2
-rw-r--r--src/test/ui/macros/issue-84195-lint-anon-const.stderr4
-rw-r--r--src/test/ui/macros/issue-99265.stderr278
-rw-r--r--src/test/ui/macros/issue-99907.stderr4
-rw-r--r--src/test/ui/macros/lint-trailing-macro-call.stderr2
-rw-r--r--src/test/ui/macros/macro-comma-behavior-rpass.rs1
-rw-r--r--src/test/ui/macros/macro-context.stderr4
-rw-r--r--src/test/ui/macros/macro-in-expression-context.stderr2
-rw-r--r--src/test/ui/macros/macro-match-nonterminal.stderr2
-rw-r--r--src/test/ui/macros/macro-missing-fragment-deduplication.stderr2
-rw-r--r--src/test/ui/macros/macro-missing-fragment.stderr4
-rw-r--r--src/test/ui/macros/macro-or-patterns-back-compat.stderr4
-rw-r--r--src/test/ui/macros/macro-use-all-and-none.stderr2
-rw-r--r--src/test/ui/macros/macro_rules-unmatchable-literals.rs14
-rw-r--r--src/test/ui/macros/macro_rules-unmatchable-literals.stderr14
-rw-r--r--src/test/ui/macros/macros-nonfatal-errors.rs23
-rw-r--r--src/test/ui/macros/macros-nonfatal-errors.stderr12
-rw-r--r--src/test/ui/macros/must-use-in-macro-55516.stderr2
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs1
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs1
-rw-r--r--src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs1
-rw-r--r--src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr44
-rw-r--r--src/test/ui/macros/stringify.rs1
-rw-r--r--src/test/ui/macros/syntax-error-recovery.rs18
-rw-r--r--src/test/ui/macros/syntax-error-recovery.stderr30
-rw-r--r--src/test/ui/malformed/malformed-regressions.stderr2
-rw-r--r--src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr2
-rw-r--r--src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs10
-rw-r--r--src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs9
-rw-r--r--src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr31
-rw-r--r--src/test/ui/marker_trait_attr/overlap-marker-trait.rs3
-rw-r--r--src/test/ui/marker_trait_attr/overlap-marker-trait.stderr4
-rw-r--r--src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs3
-rw-r--r--src/test/ui/match/expr_before_ident_pat.rs2
-rw-r--r--src/test/ui/match/expr_before_ident_pat.stderr4
-rw-r--r--src/test/ui/match/issue-41255.rs1
-rw-r--r--src/test/ui/match/issue-41255.stderr30
-rw-r--r--src/test/ui/match/issue-92100.rs2
-rw-r--r--src/test/ui/methods/issues/issue-90315.rs79
-rw-r--r--src/test/ui/methods/issues/issue-90315.stderr198
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr4
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-lint.stderr4
-rw-r--r--src/test/ui/methods/method-call-lifetime-args-unresolved.stderr2
-rw-r--r--src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr2
-rw-r--r--src/test/ui/methods/method-macro-backtrace.stderr8
-rw-r--r--src/test/ui/mir/drop-elaboration-after-borrowck-error.rs8
-rw-r--r--src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr21
-rw-r--r--src/test/ui/mir/mir_calls_to_shims.rs1
-rw-r--r--src/test/ui/mir/mir_codegen_calls_diverging_drops.rs1
-rw-r--r--src/test/ui/mir/mir_drop_order.rs1
-rw-r--r--src/test/ui/mir/mir_drop_panics.rs1
-rw-r--r--src/test/ui/mir/mir_let_chains_drop_order.rs9
-rw-r--r--src/test/ui/mir/thir-constparam-temp.stderr2
-rw-r--r--src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr2
-rw-r--r--src/test/ui/mismatched_types/closure-mismatch.stderr2
-rw-r--r--src/test/ui/mismatched_types/fn-variance-1.stderr4
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr4
-rw-r--r--src/test/ui/mismatched_types/show_module.rs18
-rw-r--r--src/test/ui/mismatched_types/show_module.stderr23
-rw-r--r--src/test/ui/mismatched_types/similar_paths.rs11
-rw-r--r--src/test/ui/mismatched_types/similar_paths.stderr23
-rw-r--r--src/test/ui/mismatched_types/similar_paths_primitive.rs10
-rw-r--r--src/test/ui/mismatched_types/similar_paths_primitive.stderr24
-rw-r--r--src/test/ui/modules/special_module_name.stderr2
-rw-r--r--src/test/ui/moves/issue-72649-uninit-in-loop.stderr10
-rw-r--r--src/test/ui/moves/move-into-dead-array-1.stderr5
-rw-r--r--src/test/ui/moves/move-of-addr-of-mut.stderr4
-rw-r--r--src/test/ui/moves/move-out-of-slice-2.stderr2
-rw-r--r--src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr24
-rw-r--r--src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr24
-rw-r--r--src/test/ui/native-library-link-flags/suggest-libname-only-1.rs9
-rw-r--r--src/test/ui/native-library-link-flags/suggest-libname-only-1.stderr6
-rw-r--r--src/test/ui/native-library-link-flags/suggest-libname-only-2.rs9
-rw-r--r--src/test/ui/native-library-link-flags/suggest-libname-only-2.stderr6
-rw-r--r--src/test/ui/never_type/issue-52443.rs4
-rw-r--r--src/test/ui/never_type/issue-52443.stderr4
-rw-r--r--src/test/ui/never_type/issue-5500-1.rs (renamed from src/test/ui/issues/issue-5500-1.rs)0
-rw-r--r--src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs31
-rw-r--r--src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr104
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument-callee.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr4
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr2
-rw-r--r--src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr2
-rw-r--r--src/test/ui/nll/closures-in-loops.stderr16
-rw-r--r--src/test/ui/nll/issue-48623-generator.stderr2
-rw-r--r--src/test/ui/nll/issue-51191.stderr2
-rw-r--r--src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr10
-rw-r--r--src/test/ui/nll/issue-97997.stderr4
-rw-r--r--src/test/ui/nll/match-cfg-fake-edges.stderr5
-rw-r--r--src/test/ui/nll/match-on-borrowed.stderr5
-rw-r--r--src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr6
-rw-r--r--src/test/ui/nll/relate_tys/universe-violation.stderr2
-rw-r--r--src/test/ui/nll/trait-associated-constant.stderr2
-rw-r--r--src/test/ui/nll/ty-outlives/impl-trait-captures.stderr8
-rw-r--r--src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr4
-rw-r--r--src/test/ui/no-patterns-in-args-2.stderr4
-rw-r--r--src/test/ui/non-fmt-panic.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr48
-rw-r--r--src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr48
-rw-r--r--src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr48
-rw-r--r--src/test/ui/numbers-arithmetic/issue-8460-const.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs1
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs2
-rw-r--r--src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr2
-rw-r--r--src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs1
-rw-r--r--src/test/ui/object-safety/issue-102762.rs26
-rw-r--r--src/test/ui/object-safety/issue-102762.stderr20
-rw-r--r--src/test/ui/object-safety/issue-102933.rs25
-rw-r--r--src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.rs15
-rw-r--r--src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr43
-rw-r--r--src/test/ui/oom_unwind.rs2
-rw-r--r--src/test/ui/opt-in-copy.stderr8
-rw-r--r--src/test/ui/packed/issue-27060-rpass.stderr32
-rw-r--r--src/test/ui/packed/issue-27060.stderr10
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element-64bit.stderr16
-rw-r--r--src/test/ui/packed/packed-struct-borrow-element.stderr24
-rw-r--r--src/test/ui/panic-handler/weak-lang-item.rs2
-rw-r--r--src/test/ui/panic-runtime/need-abort-got-unwind.rs1
-rw-r--r--src/test/ui/panic-runtime/transitive-link-a-bunch.rs1
-rw-r--r--src/test/ui/panic-runtime/want-unwind-got-abort.rs1
-rw-r--r--src/test/ui/panic-runtime/want-unwind-got-abort2.rs1
-rw-r--r--src/test/ui/panic-while-printing.rs1
-rw-r--r--src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr2
-rw-r--r--src/test/ui/panics/issue-47429-short-backtraces.rs1
-rw-r--r--src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr2
-rw-r--r--src/test/ui/panics/runtime-switch.legacy.run.stderr2
-rw-r--r--src/test/ui/panics/runtime-switch.rs1
-rw-r--r--src/test/ui/panics/runtime-switch.v0.run.stderr2
-rw-r--r--src/test/ui/parser/assoc-static-semantic-fail.stderr2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.rs2
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr106
-rw-r--r--src/test/ui/parser/bad-let-as-field.rs6
-rw-r--r--src/test/ui/parser/bad-let-as-field.stderr15
-rw-r--r--src/test/ui/parser/bad-lit-suffixes.rs16
-rw-r--r--src/test/ui/parser/bad-lit-suffixes.stderr16
-rw-r--r--src/test/ui/parser/bad-pointer-type.rs2
-rw-r--r--src/test/ui/parser/bad-pointer-type.stderr11
-rw-r--r--src/test/ui/parser/default.stderr2
-rw-r--r--src/test/ui/parser/doc-after-struct-field.rs4
-rw-r--r--src/test/ui/parser/doc-after-struct-field.stderr4
-rw-r--r--src/test/ui/parser/doc-before-extern-rbrace.stderr2
-rw-r--r--src/test/ui/parser/doc-before-fn-rbrace.rs2
-rw-r--r--src/test/ui/parser/doc-before-fn-rbrace.stderr2
-rw-r--r--src/test/ui/parser/doc-before-rbrace.rs2
-rw-r--r--src/test/ui/parser/doc-before-rbrace.stderr2
-rw-r--r--src/test/ui/parser/doc-before-semi.rs2
-rw-r--r--src/test/ui/parser/doc-before-semi.stderr2
-rw-r--r--src/test/ui/parser/doc-before-struct-rbrace-1.rs2
-rw-r--r--src/test/ui/parser/doc-before-struct-rbrace-1.stderr5
-rw-r--r--src/test/ui/parser/doc-before-struct-rbrace-2.rs2
-rw-r--r--src/test/ui/parser/doc-before-struct-rbrace-2.stderr2
-rw-r--r--src/test/ui/parser/doc-inside-trait-item.stderr2
-rw-r--r--src/test/ui/parser/double-pointer.rs7
-rw-r--r--src/test/ui/parser/double-pointer.stderr15
-rw-r--r--src/test/ui/parser/emoji-identifiers.stderr18
-rw-r--r--src/test/ui/parser/empty-impl-semicolon.rs5
-rw-r--r--src/test/ui/parser/empty-impl-semicolon.stderr8
-rw-r--r--src/test/ui/parser/expr-as-stmt-2.stderr5
-rw-r--r--src/test/ui/parser/expr-as-stmt.stderr9
-rw-r--r--src/test/ui/parser/fn-field-parse-error-ice.rs2
-rw-r--r--src/test/ui/parser/fn-field-parse-error-ice.stderr12
-rw-r--r--src/test/ui/parser/fn-header-semantic-fail.stderr14
-rw-r--r--src/test/ui/parser/inner-attr-after-doc-comment.stderr2
-rw-r--r--src/test/ui/parser/issue-103143.rs5
-rw-r--r--src/test/ui/parser/issue-103143.stderr20
-rw-r--r--src/test/ui/parser/issue-103425.rs15
-rw-r--r--src/test/ui/parser/issue-103425.stderr29
-rw-r--r--src/test/ui/parser/issue-17718-parse-const.rs (renamed from src/test/ui/issues/issue-17718-parse-const.rs)0
-rw-r--r--src/test/ui/parser/issues/issue-101540.rs7
-rw-r--r--src/test/ui/parser/issues/issue-101540.stderr12
-rw-r--r--src/test/ui/parser/issues/issue-102182-impl-trait-recover.rs3
-rw-r--r--src/test/ui/parser/issues/issue-102182-impl-trait-recover.stderr14
-rw-r--r--src/test/ui/parser/issues/issue-17383.rs7
-rw-r--r--src/test/ui/parser/issues/issue-17383.stderr15
-rw-r--r--src/test/ui/parser/issues/issue-34222-1.stderr2
-rw-r--r--src/test/ui/parser/issues/issue-48636.stderr4
-rw-r--r--src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs1
-rw-r--r--src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr2
-rw-r--r--src/test/ui/parser/issues/issue-8537.stderr2
-rw-r--r--src/test/ui/parser/issues/issue-93282.rs1
-rw-r--r--src/test/ui/parser/issues/issue-93282.stderr27
-rw-r--r--src/test/ui/parser/item-needs-block.rs10
-rw-r--r--src/test/ui/parser/item-needs-block.stderr26
-rw-r--r--src/test/ui/parser/label-after-block-like.rs43
-rw-r--r--src/test/ui/parser/label-after-block-like.stderr176
-rw-r--r--src/test/ui/parser/label-is-actually-char.rs16
-rw-r--r--src/test/ui/parser/label-is-actually-char.stderr46
-rw-r--r--src/test/ui/parser/macro/issue-33569.stderr2
-rw-r--r--src/test/ui/parser/macro/issue-37113.stderr2
-rw-r--r--src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr3
-rw-r--r--src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr3
-rw-r--r--src/test/ui/parser/numeric-lifetime.stderr16
-rw-r--r--src/test/ui/parser/parser-recovery-1.stderr12
-rw-r--r--src/test/ui/parser/parser-recovery-2.stderr12
-rw-r--r--src/test/ui/parser/recover-enum2.stderr2
-rw-r--r--src/test/ui/parser/recover-field-semi.stderr8
-rw-r--r--src/test/ui/parser/recover-range-pats.rs1
-rw-r--r--src/test/ui/parser/recover-range-pats.stderr126
-rw-r--r--src/test/ui/parser/recover-struct.stderr2
-rw-r--r--src/test/ui/parser/recovered-struct-variant.stderr4
-rw-r--r--src/test/ui/parser/removed-syntax-enum-newtype.stderr4
-rw-r--r--src/test/ui/parser/removed-syntax-field-let-2.rs12
-rw-r--r--src/test/ui/parser/removed-syntax-field-let-2.stderr33
-rw-r--r--src/test/ui/parser/removed-syntax-field-let.stderr8
-rw-r--r--src/test/ui/parser/removed-syntax-field-semicolon.stderr2
-rw-r--r--src/test/ui/parser/require-parens-for-chained-comparison.rs2
-rw-r--r--src/test/ui/parser/require-parens-for-chained-comparison.stderr16
-rw-r--r--src/test/ui/parser/semi-after-closure-in-macro.rs14
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.rs12
-rw-r--r--src/test/ui/parser/tag-variant-disr-non-nullary.stderr25
-rw-r--r--src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr2
-rw-r--r--src/test/ui/parser/trait-object-trait-parens.stderr2
-rw-r--r--src/test/ui/parser/type-alias-where-fixable.stderr2
-rw-r--r--src/test/ui/parser/unicode-control-codepoints.stderr4
-rw-r--r--src/test/ui/parser/unmatched-langle-1.stderr12
-rw-r--r--src/test/ui/pattern/issue-17718-patterns.rs (renamed from src/test/ui/issues/issue-17718-patterns.rs)0
-rw-r--r--src/test/ui/pattern/issue-17718-patterns.stderr (renamed from src/test/ui/issues/issue-17718-patterns.stderr)0
-rw-r--r--src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/consts-opaque.stderr2
-rw-r--r--src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr4
-rw-r--r--src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr2
-rw-r--r--src/test/ui/polymorphization/const_parameters/closures.stderr2
-rw-r--r--src/test/ui/polymorphization/const_parameters/functions.stderr2
-rw-r--r--src/test/ui/polymorphization/generators.stderr2
-rw-r--r--src/test/ui/polymorphization/predicates.stderr2
-rw-r--r--src/test/ui/polymorphization/promoted-function-2.stderr2
-rw-r--r--src/test/ui/privacy/access_levels.rs49
-rw-r--r--src/test/ui/privacy/access_levels.stderr125
-rw-r--r--src/test/ui/privacy/associated-item-privacy-inherent.rs6
-rw-r--r--src/test/ui/privacy/associated-item-privacy-inherent.stderr6
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.rs6
-rw-r--r--src/test/ui/privacy/associated-item-privacy-trait.stderr6
-rw-r--r--src/test/ui/privacy/auxiliary/issue-17718-const-privacy.rs (renamed from src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs)0
-rw-r--r--src/test/ui/privacy/effective_visibilities.rs75
-rw-r--r--src/test/ui/privacy/effective_visibilities.stderr134
-rw-r--r--src/test/ui/privacy/issue-17718-const-privacy.rs (renamed from src/test/ui/issues/issue-17718-const-privacy.rs)0
-rw-r--r--src/test/ui/privacy/issue-17718-const-privacy.stderr (renamed from src/test/ui/issues/issue-17718-const-privacy.stderr)0
-rw-r--r--src/test/ui/privacy/issue-30079.stderr2
-rw-r--r--src/test/ui/privacy/private-in-public-assoc-ty.stderr2
-rw-r--r--src/test/ui/privacy/private-in-public-non-principal.stderr2
-rw-r--r--src/test/ui/privacy/private-in-public-warn.stderr4
-rw-r--r--src/test/ui/privacy/private-inferred-type-3.rs2
-rw-r--r--src/test/ui/privacy/private-inferred-type-3.stderr2
-rw-r--r--src/test/ui/privacy/private-inferred-type.rs2
-rw-r--r--src/test/ui/privacy/private-inferred-type.stderr2
-rw-r--r--src/test/ui/privacy/reachable-unnameable-items.rs1
-rw-r--r--src/test/ui/privacy/where-priv-type.stderr2
-rw-r--r--src/test/ui/proc-macro/attr-complex-fn.stdout4
-rw-r--r--src/test/ui/proc-macro/call-deprecated.rs2
-rw-r--r--src/test/ui/proc-macro/capture-macro-rules-invoke.stdout12
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug-span-debug.rs7
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr127
-rw-r--r--src/test/ui/proc-macro/debug/dump-debug.stderr6
-rw-r--r--src/test/ui/proc-macro/derive-bad.stderr5
-rw-r--r--src/test/ui/proc-macro/derive-helper-shadowing.stderr2
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout8
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-62325.stdout8
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout24
-rw-r--r--src/test/ui/proc-macro/expand-with-a-macro.rs1
-rw-r--r--src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr4
-rw-r--r--src/test/ui/proc-macro/generate-mod.stderr18
-rw-r--r--src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr2
-rw-r--r--src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr2
-rw-r--r--src/test/ui/proc-macro/inner-attrs.stdout4
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs9
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr91
-rw-r--r--src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout11
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.stderr2
-rw-r--r--src/test/ui/proc-macro/issue-75930-derive-cfg.stdout20
-rw-r--r--src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout4
-rw-r--r--src/test/ui/proc-macro/keep-expr-tokens.stderr12
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.rs4
-rw-r--r--src/test/ui/proc-macro/meta-macro-hygiene.stdout6
-rw-r--r--src/test/ui/proc-macro/mixed-site-span.stderr4
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack-hide.rs12
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack-hide.stdout21
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack-show.rs17
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack-show.stderr179
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack-show.stdout44
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs14
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs14
-rw-r--r--src/test/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs14
-rw-r--r--src/test/ui/proc-macro/proc-macro-attributes.stderr2
-rw-r--r--src/test/ui/proc-macro/proc-macro-gates.stderr2
-rw-r--r--src/test/ui/proc-macro/three-equals.stderr6
-rw-r--r--src/test/ui/process/process-panic-after-fork.rs45
-rw-r--r--src/test/ui/process/process-spawn-nonexistent.rs1
-rw-r--r--src/test/ui/process/process-spawn-with-unicode-params.rs1
-rw-r--r--src/test/ui/process/signal-exit-status.rs1
-rw-r--r--src/test/ui/pub/pub-reexport-priv-extern-crate.stderr2
-rw-r--r--src/test/ui/pub/pub-restricted-error.stderr2
-rw-r--r--src/test/ui/query-system/query_depth.rs31
-rw-r--r--src/test/ui/query-system/query_depth.stderr11
-rw-r--r--src/test/ui/query-visibility.rs9
-rw-r--r--src/test/ui/range/range-inclusive-pattern-precedence.stderr4
-rw-r--r--src/test/ui/range/range-inclusive-pattern-precedence2.stderr4
-rw-r--r--src/test/ui/recursion/issue-83150.stderr6
-rw-r--r--src/test/ui/recursion/issue-95134.rs4
-rw-r--r--src/test/ui/recursion/issue-95134.stderr7
-rw-r--r--src/test/ui/recursion/recursive-enum.stderr4
-rw-r--r--src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr4
-rw-r--r--src/test/ui/regions/issue-101280.rs10
-rw-r--r--src/test/ui/regions/issue-101280.stderr14
-rw-r--r--src/test/ui/regions/issue-102374.rs20
-rw-r--r--src/test/ui/regions/issue-102374.stderr14
-rw-r--r--src/test/ui/regions/issue-102392.rs6
-rw-r--r--src/test/ui/regions/issue-102392.stderr14
-rw-r--r--src/test/ui/regions/region-bound-on-closure-outlives-call.stderr2
-rw-r--r--src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr4
-rw-r--r--src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr4
-rw-r--r--src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr2
-rw-r--r--src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr4
-rw-r--r--src/test/ui/repr/repr-transparent-issue-87496.stderr2
-rw-r--r--src/test/ui/repr/repr-transparent-non-exhaustive.rs24
-rw-r--r--src/test/ui/repr/repr-transparent-non-exhaustive.stderr30
-rw-r--r--src/test/ui/resolve/bad-env-capture.stderr12
-rw-r--r--src/test/ui/resolve/bad-env-capture2.stderr12
-rw-r--r--src/test/ui/resolve/bad-env-capture3.stderr12
-rw-r--r--src/test/ui/resolve/bad-expr-path.stderr12
-rw-r--r--src/test/ui/resolve/bad-expr-path2.stderr12
-rw-r--r--src/test/ui/resolve/issue-102946.rs7
-rw-r--r--src/test/ui/resolve/issue-102946.stderr26
-rw-r--r--src/test/ui/resolve/issue-103202.rs7
-rw-r--r--src/test/ui/resolve/issue-103202.stderr9
-rw-r--r--src/test/ui/resolve/issue-14254.stderr127
-rw-r--r--src/test/ui/resolve/issue-23305.rs2
-rw-r--r--src/test/ui/resolve/issue-23305.stderr16
-rw-r--r--src/test/ui/resolve/issue-2356.stderr90
-rw-r--r--src/test/ui/resolve/issue-42944.stderr24
-rw-r--r--src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr4
-rw-r--r--src/test/ui/resolve/issue-73427.stderr40
-rw-r--r--src/test/ui/resolve/levenshtein.stderr18
-rw-r--r--src/test/ui/resolve/name-collision-in-trait-fn-sig.rs11
-rw-r--r--src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr13
-rw-r--r--src/test/ui/resolve/privacy-enum-ctor.stderr6
-rw-r--r--src/test/ui/resolve/resolve-assoc-suggestions.stderr2
-rw-r--r--src/test/ui/resolve/resolve-hint-macro.stderr22
-rw-r--r--src/test/ui/resolve/resolve-self-in-impl.rs9
-rw-r--r--src/test/ui/resolve/resolve-self-in-impl.stderr74
-rw-r--r--src/test/ui/resolve/resolve-speculative-adjustment.stderr12
-rw-r--r--src/test/ui/resolve/tuple-struct-alias.stderr16
-rw-r--r--src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr38
-rw-r--r--src/test/ui/return/issue-64620.rs (renamed from src/test/ui/issues/issue-64620.rs)0
-rw-r--r--src/test/ui/return/issue-64620.stderr (renamed from src/test/ui/issues/issue-64620.stderr)0
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr4
-rw-r--r--src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr2
-rw-r--r--src/test/ui/rfc-1937-termination-trait/issue-103052-1.rs11
-rw-r--r--src/test/ui/rfc-1937-termination-trait/issue-103052-1.stderr17
-rw-r--r--src/test/ui/rfc-1937-termination-trait/issue-103052-2.rs18
-rw-r--r--src/test/ui/rfc-1937-termination-trait/issue-103052-2.stderr15
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs1
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr7
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr2
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr48
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr8
-rw-r--r--src/test/ui/rfc-2008-non-exhaustive/struct.stderr12
-rw-r--r--src/test/ui/rfc-2091-track-caller/std-panic-locations.rs1
-rw-r--r--src/test/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr7
-rw-r--r--src/test/ui/rfc-2294-if-let-guard/warns.stderr4
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr4
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr26
-rw-r--r--src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr77
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr77
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop.rs3
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr4
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr13
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs15
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr41
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs5
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs31
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs26
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs18
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs9
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr24
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr21
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs20
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/super-traits.rs3
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs34
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr14
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs7
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr36
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs17
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs31
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr35
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs1
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs19
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr56
-rw-r--r--src/test/ui/rfc1623-2.stderr2
-rw-r--r--src/test/ui/rfcs/rfc1857-drop-order.rs1
-rw-r--r--src/test/ui/runtime/backtrace-debuginfo.rs1
-rw-r--r--src/test/ui/runtime/out-of-stack.rs1
-rw-r--r--src/test/ui/runtime/rt-explody-panic-payloads.rs14
-rw-r--r--src/test/ui/rust-2018/async-ident-allowed.stderr4
-rw-r--r--src/test/ui/rust-2018/async-ident.stderr4
-rw-r--r--src/test/ui/rust-2018/dyn-keyword.stderr4
-rw-r--r--src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr4
-rw-r--r--src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr4
-rw-r--r--src/test/ui/rust-2018/edition-lint-nested-paths.stderr4
-rw-r--r--src/test/ui/rust-2018/edition-lint-paths.stderr4
-rw-r--r--src/test/ui/rust-2018/extern-crate-rename.stderr4
-rw-r--r--src/test/ui/rust-2018/extern-crate-submod.stderr4
-rw-r--r--src/test/ui/rust-2018/try-ident.stderr4
-rw-r--r--src/test/ui/rust-2018/try-macro.stderr4
-rw-r--r--src/test/ui/rust-2021/array-into-iter-ambiguous.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-generic.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-imported.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-macros.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr4
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision.stderr4
-rw-r--r--src/test/ui/rust-2021/generic-type-collision.stderr4
-rw-r--r--src/test/ui/rust-2021/inherent-dyn-collision.stderr4
-rw-r--r--src/test/ui/rust-2021/reserved-prefixes-migration.stderr4
-rw-r--r--src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr4
-rw-r--r--src/test/ui/rustdoc/doc-test-attr.stderr4
-rw-r--r--src/test/ui/rustdoc/feature-gate-doc_primitive.stderr2
-rw-r--r--src/test/ui/sanitize/address.rs4
-rw-r--r--src/test/ui/sanitize/hwaddress.rs2
-rw-r--r--src/test/ui/sanitize/inline-always.stderr2
-rw-r--r--src/test/ui/sanitize/leak.rs2
-rw-r--r--src/test/ui/sanitize/memory-eager.rs1
-rw-r--r--src/test/ui/sanitize/memory.rs1
-rw-r--r--src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs2
-rw-r--r--src/test/ui/save-analysis/issue-68621.stderr2
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr2
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr2
-rw-r--r--src/test/ui/simd/portable-intrinsics-arent-exposed.stderr5
-rw-r--r--src/test/ui/simd/target-feature-mixup.rs1
-rw-r--r--src/test/ui/single-use-lifetime/derive-eq.rs11
-rw-r--r--src/test/ui/sized-cycle-note.rs11
-rw-r--r--src/test/ui/sized-cycle-note.stderr32
-rw-r--r--src/test/ui/span/E0072.stderr6
-rw-r--r--src/test/ui/span/E0204.stderr8
-rw-r--r--src/test/ui/span/E0493.rs2
-rw-r--r--src/test/ui/span/E0493.stderr4
-rw-r--r--src/test/ui/span/E0535.stderr2
-rw-r--r--src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs1
-rw-r--r--src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr38
-rw-r--r--src/test/ui/span/issue-7575.rs75
-rw-r--r--src/test/ui/span/issue-7575.stderr82
-rw-r--r--src/test/ui/span/multiline-span-E0072.stderr6
-rw-r--r--src/test/ui/span/recursive-type-field.rs4
-rw-r--r--src/test/ui/span/recursive-type-field.stderr38
-rw-r--r--src/test/ui/specialization/assoc-ty-graph-cycle.stderr2
-rw-r--r--src/test/ui/specialization/const_trait_impl.rs55
-rw-r--r--src/test/ui/specialization/cross-crate-defaults.stderr2
-rw-r--r--src/test/ui/specialization/default-associated-type-bound-1.stderr2
-rw-r--r--src/test/ui/specialization/default-associated-type-bound-2.stderr2
-rw-r--r--src/test/ui/specialization/default-generic-associated-type-bound.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/out-of-order.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/overlap-projection.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/projection.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-no-default.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr2
-rw-r--r--src/test/ui/specialization/defaultimpl/validation.stderr2
-rw-r--r--src/test/ui/specialization/issue-35376.stderr2
-rw-r--r--src/test/ui/specialization/issue-36804.stderr2
-rw-r--r--src/test/ui/specialization/issue-38091-2.stderr4
-rw-r--r--src/test/ui/specialization/issue-38091.stderr2
-rw-r--r--src/test/ui/specialization/issue-39448.stderr2
-rw-r--r--src/test/ui/specialization/issue-39618.stderr2
-rw-r--r--src/test/ui/specialization/issue-50452-fail.stderr2
-rw-r--r--src/test/ui/specialization/issue-50452.stderr2
-rw-r--r--src/test/ui/specialization/issue-52050.stderr2
-rw-r--r--src/test/ui/specialization/issue-63716-parse-async.stderr2
-rw-r--r--src/test/ui/specialization/issue-70442.stderr2
-rw-r--r--src/test/ui/specialization/non-defaulted-item-fail.stderr2
-rw-r--r--src/test/ui/specialization/specialization-allowed-cross-crate.stderr2
-rw-r--r--src/test/ui/specialization/specialization-assoc-fns.stderr2
-rw-r--r--src/test/ui/specialization/specialization-basics.stderr2
-rw-r--r--src/test/ui/specialization/specialization-cross-crate.stderr2
-rw-r--r--src/test/ui/specialization/specialization-default-methods.stderr2
-rw-r--r--src/test/ui/specialization/specialization-default-projection.stderr2
-rw-r--r--src/test/ui/specialization/specialization-default-types.stderr2
-rw-r--r--src/test/ui/specialization/specialization-no-default.stderr2
-rw-r--r--src/test/ui/specialization/specialization-on-projection.stderr2
-rw-r--r--src/test/ui/specialization/specialization-out-of-order.stderr2
-rw-r--r--src/test/ui/specialization/specialization-overlap-negative.stderr2
-rw-r--r--src/test/ui/specialization/specialization-overlap-projection.stderr2
-rw-r--r--src/test/ui/specialization/specialization-overlap.stderr2
-rw-r--r--src/test/ui/specialization/specialization-polarity.stderr2
-rw-r--r--src/test/ui/specialization/specialization-projection-alias.stderr2
-rw-r--r--src/test/ui/specialization/specialization-projection.stderr2
-rw-r--r--src/test/ui/specialization/specialization-supertraits.stderr2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections-with-params.stderr2
-rw-r--r--src/test/ui/specialization/specialization-translate-projections.stderr2
-rw-r--r--src/test/ui/specialization/transmute-specialization.stderr2
-rw-r--r--src/test/ui/stability-attribute/missing-const-stability.rs1
-rw-r--r--src/test/ui/stability-attribute/missing-const-stability.stderr2
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-trait-impl.rs16
-rw-r--r--src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr16
-rw-r--r--src/test/ui/stability-attribute/stable-in-unstable.rs8
-rw-r--r--src/test/ui/stability-attribute/stable-in-unstable.stderr20
-rw-r--r--src/test/ui/static/static-drop-scope.rs16
-rw-r--r--src/test/ui/static/static-drop-scope.stderr32
-rw-r--r--src/test/ui/statics/issue-17718-static-sync.rs (renamed from src/test/ui/issues/issue-17718-static-sync.rs)0
-rw-r--r--src/test/ui/statics/issue-17718-static-sync.stderr (renamed from src/test/ui/issues/issue-17718-static-sync.stderr)0
-rw-r--r--src/test/ui/statics/issue-17718-static-unsafe-interior.rs (renamed from src/test/ui/issues/issue-17718-static-unsafe-interior.rs)0
-rw-r--r--src/test/ui/statics/uninhabited-static.stderr18
-rw-r--r--src/test/ui/stats/hir-stats.rs1
-rw-r--r--src/test/ui/stats/hir-stats.stderr96
-rw-r--r--src/test/ui/std-backtrace.rs1
-rw-r--r--src/test/ui/structs-enums/issue-2718-a.rs (renamed from src/test/ui/issues/issue-2718-a.rs)0
-rw-r--r--src/test/ui/structs-enums/issue-2718-a.stderr (renamed from src/test/ui/issues/issue-2718-a.stderr)4
-rw-r--r--src/test/ui/structs-enums/rec-align-u32.rs1
-rw-r--r--src/test/ui/structs-enums/rec-align-u64.rs1
-rw-r--r--src/test/ui/structs-enums/struct-rec/issue-74224.stderr4
-rw-r--r--src/test/ui/structs-enums/struct-rec/issue-84611.stderr4
-rw-r--r--src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.rs6
-rw-r--r--src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr62
-rw-r--r--src/test/ui/structs/incomplete-fn-in-struct-definition.rs5
-rw-r--r--src/test/ui/structs/incomplete-fn-in-struct-definition.stderr15
-rw-r--r--src/test/ui/structs/struct-fn-in-definition.stderr9
-rw-r--r--src/test/ui/structs/struct-path-associated-type.rs4
-rw-r--r--src/test/ui/structs/struct-path-associated-type.stderr30
-rw-r--r--src/test/ui/suggestions/abi-typo.fixed6
-rw-r--r--src/test/ui/suggestions/abi-typo.rs6
-rw-r--r--src/test/ui/suggestions/abi-typo.stderr14
-rw-r--r--src/test/ui/suggestions/assoc_fn_without_self.stderr12
-rw-r--r--src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr9
-rw-r--r--src/test/ui/suggestions/boxed-variant-field.rs1
-rw-r--r--src/test/ui/suggestions/boxed-variant-field.stderr4
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.rs17
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.stderr21
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs15
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr21
-rw-r--r--src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr9
-rw-r--r--src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr14
-rw-r--r--src/test/ui/suggestions/fn-to-method.rs19
-rw-r--r--src/test/ui/suggestions/fn-to-method.stderr38
-rw-r--r--src/test/ui/suggestions/format-borrow.stderr16
-rw-r--r--src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr12
-rw-r--r--src/test/ui/suggestions/inner_type.fixed40
-rw-r--r--src/test/ui/suggestions/inner_type.rs40
-rw-r--r--src/test/ui/suggestions/inner_type.stderr83
-rw-r--r--src/test/ui/suggestions/inner_type2.rs26
-rw-r--r--src/test/ui/suggestions/inner_type2.stderr29
-rw-r--r--src/test/ui/suggestions/into-convert.rs26
-rw-r--r--src/test/ui/suggestions/into-convert.stderr44
-rw-r--r--src/test/ui/suggestions/issue-101065.fixed14
-rw-r--r--src/test/ui/suggestions/issue-101065.rs14
-rw-r--r--src/test/ui/suggestions/issue-101065.stderr23
-rw-r--r--src/test/ui/suggestions/issue-101623.rs25
-rw-r--r--src/test/ui/suggestions/issue-101623.stderr14
-rw-r--r--src/test/ui/suggestions/issue-101984.stderr4
-rw-r--r--src/test/ui/suggestions/issue-102354.rs10
-rw-r--r--src/test/ui/suggestions/issue-102354.stderr24
-rw-r--r--src/test/ui/suggestions/issue-102892.rs25
-rw-r--r--src/test/ui/suggestions/issue-102892.stderr57
-rw-r--r--src/test/ui/suggestions/issue-103112.rs4
-rw-r--r--src/test/ui/suggestions/issue-103112.stderr15
-rw-r--r--src/test/ui/suggestions/issue-61963.stderr4
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr1
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr4
-rw-r--r--src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr4
-rw-r--r--src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr2
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr4
-rw-r--r--src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr4
-rw-r--r--src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs2
-rw-r--r--src/test/ui/suggestions/return-closures.stderr2
-rw-r--r--src/test/ui/suggestions/struct-field-type-including-single-colon.stderr4
-rw-r--r--src/test/ui/suggestions/sugg-else-for-closure.fixed8
-rw-r--r--src/test/ui/suggestions/sugg-else-for-closure.rs8
-rw-r--r--src/test/ui/suggestions/sugg-else-for-closure.stderr23
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.fixed17
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.rs17
-rw-r--r--src/test/ui/suggestions/suggest-let-for-assignment.stderr60
-rw-r--r--src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr2
-rw-r--r--src/test/ui/symbol-names/impl1.legacy.stderr2
-rw-r--r--src/test/ui/symbol-names/impl1.rs4
-rw-r--r--src/test/ui/symbol-names/impl1.v0.stderr2
-rw-r--r--src/test/ui/test-attrs/inaccessible-test-modules.stderr14
-rw-r--r--src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs1
-rw-r--r--src/test/ui/test-attrs/test-on-not-fn.stderr24
-rw-r--r--src/test/ui/test-attrs/test-panic-while-printing.rs1
-rw-r--r--src/test/ui/test-attrs/test-should-fail-good-message.rs1
-rw-r--r--src/test/ui/test-attrs/test-thread-capture.rs1
-rw-r--r--src/test/ui/test-attrs/test-thread-capture.run.stdout2
-rw-r--r--src/test/ui/test-attrs/test-thread-nocapture.rs1
-rw-r--r--src/test/ui/test-attrs/test-thread-nocapture.run.stderr2
-rw-r--r--src/test/ui/thir-tree.stdout4
-rw-r--r--src/test/ui/threads-sendsync/issue-43733-2.rs2
-rw-r--r--src/test/ui/threads-sendsync/issue-43733.rs2
-rw-r--r--src/test/ui/threads-sendsync/sync-send-in-std.rs1
-rw-r--r--src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr2
-rw-r--r--src/test/ui/traits/bound/not-on-bare-trait.stderr2
-rw-r--r--src/test/ui/traits/copy-impl-cannot-normalize.stderr4
-rw-r--r--src/test/ui/traits/issue-102989.rs16
-rw-r--r--src/test/ui/traits/issue-102989.stderr59
-rw-r--r--src/test/ui/traits/issue-33140-hack-boundaries.stderr17
-rw-r--r--src/test/ui/traits/issue-43784-supertrait.rs (renamed from src/test/ui/issues/issue-43784-supertrait.rs)0
-rw-r--r--src/test/ui/traits/issue-43784-supertrait.stderr (renamed from src/test/ui/issues/issue-43784-supertrait.stderr)0
-rw-r--r--src/test/ui/traits/issue-8153.stderr7
-rw-r--r--src/test/ui/traits/issue-91949-hangs-on-recursion.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/negative-default-impls.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-negative.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/negative-specializes-positive.stderr2
-rw-r--r--src/test/ui/traits/negative-impls/positive-specializes-negative.stderr2
-rw-r--r--src/test/ui/traits/object/issue-33140-traitobject-crate.stderr57
-rw-r--r--src/test/ui/traits/safety-trait-impl-cc.stderr6
-rw-r--r--src/test/ui/traits/safety-trait-impl.stderr12
-rw-r--r--src/test/ui/traits/static-method-generic-inference.stderr4
-rw-r--r--src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr4
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs (renamed from src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs)0
-rw-r--r--src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr (renamed from src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr)2
-rw-r--r--src/test/ui/traits/unspecified-self-in-trait-ref.stderr2
-rw-r--r--src/test/ui/transmutability/enums/should_order_correctly.rs1
-rw-r--r--src/test/ui/transmutability/enums/should_respect_endianness.rs1
-rw-r--r--src/test/ui/transmutability/enums/should_respect_endianness.stderr4
-rw-r--r--src/test/ui/transmutability/issue-101739-1.rs21
-rw-r--r--src/test/ui/transmutability/issue-101739-1.stderr16
-rw-r--r--src/test/ui/transmutability/issue-101739-2.rs37
-rw-r--r--src/test/ui/transmutability/issue-101739-2.stderr20
-rw-r--r--src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs4
-rw-r--r--src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr37
-rw-r--r--src/test/ui/transmute-equal-assoc-types.rs4
-rw-r--r--src/test/ui/transmute-equal-assoc-types.stderr11
-rw-r--r--src/test/ui/transmute/lifetimes.rs23
-rw-r--r--src/test/ui/transmute/main.rs2
-rw-r--r--src/test/ui/transmute/main.stderr10
-rw-r--r--src/test/ui/treat-err-as-bug/delay_span_bug.rs2
-rw-r--r--src/test/ui/treat-err-as-bug/delay_span_bug.stderr2
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr2
-rw-r--r--src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/closure_parent_substs.rs65
-rw-r--r--src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs65
-rw-r--r--src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr64
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr10
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs4
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr12
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs5
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds.rs51
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds2.rs10
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds3.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs31
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr11
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs51
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr16
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs27
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs43
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr58
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs11
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr14
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-101750.rs37
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr3
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs20
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-89686.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-89686.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs10
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr15
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs92
-rw-r--r--src/test/ui/type-alias-impl-trait/missing_lifetime_bound.rs7
-rw-r--r--src/test/ui/type-alias-impl-trait/missing_lifetime_bound.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs6
-rw-r--r--src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs14
-rw-r--r--src/test/ui/type/issue-101866.rs15
-rw-r--r--src/test/ui/type/issue-101866.stderr18
-rw-r--r--src/test/ui/type/issue-94187-verbose-type-name.rs13
-rw-r--r--src/test/ui/type/type-check/assignment-expected-bool.stderr22
-rw-r--r--src/test/ui/type/type-check/assignment-in-if.rs19
-rw-r--r--src/test/ui/type/type-check/assignment-in-if.stderr71
-rw-r--r--src/test/ui/type/type-mismatch-same-crate-name.stderr11
-rw-r--r--src/test/ui/type/type-recursive-box-shadowed.stderr4
-rw-r--r--src/test/ui/type/type-recursive.stderr42
-rw-r--r--src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr4
-rw-r--r--src/test/ui/typeck/issue-87181/empty-tuple-method.stderr2
-rw-r--r--src/test/ui/typeck/issue-87181/enum-variant.stderr2
-rw-r--r--src/test/ui/typeck/issue-87181/tuple-field.stderr2
-rw-r--r--src/test/ui/typeck/slow-lhs-suggestion.rs26
-rw-r--r--src/test/ui/typeck/slow-lhs-suggestion.stderr187
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr2
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr12
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr18
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr6
-rw-r--r--src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr5
-rw-r--r--src/test/ui/union/union-copy.stderr4
-rw-r--r--src/test/ui/union/union-nonrepresentable.stderr10
-rw-r--r--src/test/ui/union/union-repr-c.stderr10
-rw-r--r--src/test/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr2
-rw-r--r--src/test/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr4
-rw-r--r--src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr2
-rw-r--r--src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr4
-rw-r--r--src/test/ui/unresolved/unresolved-candidates.rs13
-rw-r--r--src/test/ui/unresolved/unresolved-candidates.stderr26
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr4
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr4
-rw-r--r--src/test/ui/unsized-locals/borrow-after-move.stderr2
-rw-r--r--src/test/ui/unsized-locals/by-value-trait-object-safety.stderr2
-rw-r--r--src/test/ui/unsized-locals/double-move.stderr2
-rw-r--r--src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr2
-rw-r--r--src/test/ui/unsized-locals/issue-50940-with-feature.stderr2
-rw-r--r--src/test/ui/unwind-abis/feature-gate-c-unwind.stderr2
-rw-r--r--src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs1
-rw-r--r--src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr6
-rw-r--r--src/test/ui/unwind-no-uwtable.rs1
-rw-r--r--src/test/ui/variance/variance-regions-unused-indirect.rs1
-rw-r--r--src/test/ui/variance/variance-regions-unused-indirect.stderr30
-rw-r--r--src/test/ui/wf/issue-103573.rs22
-rw-r--r--src/test/ui/wf/issue-103573.stderr14
-rw-r--r--src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr18
-rw-r--r--src/test/ui/where-clauses/higher-ranked-fn-type.rs25
-rw-r--r--src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr18
-rw-r--r--src/tools/build-manifest/src/main.rs55
-rw-r--r--src/tools/build-manifest/src/versions.rs19
-rw-r--r--src/tools/cargotest/main.rs6
-rw-r--r--src/tools/clippy/.github/workflows/clippy.yml1
-rw-r--r--src/tools/clippy/.github/workflows/clippy_bors.yml1
-rw-r--r--src/tools/clippy/.github/workflows/clippy_dev.yml2
-rw-r--r--src/tools/clippy/CHANGELOG.md166
-rw-r--r--src/tools/clippy/CONTRIBUTING.md27
-rw-r--r--src/tools/clippy/Cargo.toml8
-rw-r--r--src/tools/clippy/README.md46
-rw-r--r--src/tools/clippy/book/src/development/adding_lints.md24
-rw-r--r--src/tools/clippy/book/src/development/basics.md7
-rw-r--r--src/tools/clippy/book/src/development/common_tools_writing_lints.md15
-rw-r--r--src/tools/clippy/clippy_dev/src/fmt.rs6
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/main.rs2
-rw-r--r--src/tools/clippy/clippy_dev/src/new_lint.rs166
-rw-r--r--src/tools/clippy/clippy_dev/src/serve.rs6
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/git_hook.rs7
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/intellij.rs42
-rw-r--r--src/tools/clippy/clippy_dev/src/setup/vscode.rs19
-rw-r--r--src/tools/clippy/clippy_dev/src/update_lints.rs111
-rw-r--r--src/tools/clippy/clippy_lints/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/approx_const.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/asm_syntax.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_constants.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/attrs.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/await_holding_invalid.rs42
-rw-r--r--src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs68
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/booleans.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/box_default.rs129
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/feature_name.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/mod.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ptr_alignment.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs57
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs78
-rw-r--r--src/tools/clippy/clippy_lints/src/checked_conversions.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs64
-rw-r--r--src/tools/clippy/clippy_lints/src/comparison_chain.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/copy_iterator.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs69
-rw-r--r--src/tools/clippy/clippy_lints/src/default_union_representation.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/dereference.rs203
-rw-r--r--src/tools/clippy/clippy_lints/src/derivable_impls.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_macros.rs151
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_methods.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/disallowed_types.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/doc.rs102
-rw-r--r--src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/double_parens.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/drop_forget_ref.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/empty_enum.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/enum_variants.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/equatable_if_let.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/eta_reduction.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/exhaustive_items.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/exit.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/explicit_write.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/fallible_impl_from.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/float_literal.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/format.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/format_args.rs302
-rw-r--r--src/tools/clippy/clippy_lints/src/format_impl.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/formatting.rs25
-rw-r--r--src/tools/clippy/clippy_lints/src/from_over_into.rs176
-rw-r--r--src/tools/clippy/clippy_lints/src/from_str_radix_10.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/must_use.rs116
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/not_unsafe_ptr_arg_deref.rs95
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/result.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/future_not_send.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_hasher.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_return.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs114
-rw-r--r--src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/index_refutable_slice.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/indexing_slicing.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/infinite_iter.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/inherent_to_string.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/int_plus_one.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_not_returning_iterator.rs9
-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.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/large_stack_arrays.rs50
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/let_if_seq.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/let_underscore.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_all.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_complexity.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_correctness.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_internal.rs32
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_lints.rs48
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_nursery.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_perf.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_restriction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_style.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs98
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/literal_representation.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_find.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mod.rs59
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_assert.rs31
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_async_fn.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_clamp.rs717
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/map_unit_fn.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/match_result_ok.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_filter.rs153
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_map.rs318
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_utils.rs277
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/mod.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/needless_match.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs65
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/single_match.rs17
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/try_err.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/mem_replace.rs72
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs13
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/err_expect.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/expect_fun_call.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_next.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_first.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_count.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs87
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_nth.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_ok_or.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_clone.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_flatten.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_identity.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/mod.rs152
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/ok_expect.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs29
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/search_is_some.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/stable_sort_primitive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/str_splitn.rs24
-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_splitn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/suspicious_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs73
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/useless_asref.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/minmax.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/misc.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/mod.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_doc.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_trait_methods.rs98
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/module_style.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_key.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/mut_reference.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/mutex_atomic.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_continue.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_for_each.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_late_init.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs21
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_question_mark.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/neg_multiply.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/new_without_default.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/non_copy_const.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/non_expressive_names.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs83
-rw-r--r--src/tools/clippy/clippy_lints/src/octal_escapes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/only_used_in_recursion.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs127
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs83
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/bit_mask.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs28
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/eq_op.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/mod.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/op_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/self_assignment.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/option_env_unwrap.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/option_if_let_else.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/panic_in_result_fn.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/partial_pub_fields.rs81
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/partialeq_to_none.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/precedence.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs66
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/question_mark.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/ranges.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs45
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs454
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_slicing.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ref_option_ref.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/regex.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/return_self_not_must_use.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/returns.rs212
-rw-r--r--src/tools/clippy/clippy_lints/src/same_name_method.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/self_named_constructors.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/shadow.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs16
-rw-r--r--src/tools/clippy/clippy_lints/src/std_instead_of_core.rs22
-rw-r--r--src/tools/clippy/clippy_lints/src/strings.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/swap.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/to_digit_is_some.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/trailing_empty_array.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/trait_bounds.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs18
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_ref_to_ref.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmute_undefined_repr.rs178
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs41
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/utils.rs11
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/borrowed_box.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/types/box_collection.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/types/mod.rs20
-rw-r--r--src/tools/clippy/clippy_lints/src/types/rc_buffer.rs27
-rw-r--r--src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs55
-rw-r--r--src/tools/clippy/clippy_lints/src/types/vec_box.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/uninit_vec.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_io_amount.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs36
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_rounding.rs9
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_self.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap.rs7
-rw-r--r--src/tools/clippy/clippy_lints/src/unwrap_in_result.rs72
-rw-r--r--src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/use_self.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs19
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs121
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/conf.rs43
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints.rs1447
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/clippy_lints_internal.rs49
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs245
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs77
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs164
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs239
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs108
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs342
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs105
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs63
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs62
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs37
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs343
-rw-r--r--src/tools/clippy/clippy_lints/src/wildcard_imports.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/write.rs780
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_div_zero.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/zero_sized_map_values.rs7
-rw-r--r--src/tools/clippy/clippy_utils/Cargo.toml2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/attrs.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/check_proc_macro.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/consts.rs56
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs51
-rw-r--r--src/tools/clippy/clippy_utils/src/eager_or_lazy.rs12
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs297
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs400
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs52
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs164
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs241
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/possible_origin.rs59
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs29
-rw-r--r--src/tools/clippy/clippy_utils/src/msrvs.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/numeric_literal.rs7
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs39
-rw-r--r--src/tools/clippy/clippy_utils/src/ptr.rs37
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs36
-rw-r--r--src/tools/clippy/clippy_utils/src/source.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/sugg.rs120
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs77
-rw-r--r--src/tools/clippy/clippy_utils/src/usage.rs77
-rw-r--r--src/tools/clippy/clippy_utils/src/visitors.rs164
-rw-r--r--src/tools/clippy/lintcheck/Cargo.toml2
-rw-r--r--src/tools/clippy/lintcheck/README.md20
-rw-r--r--src/tools/clippy/lintcheck/lintcheck_crates.toml8
-rw-r--r--src/tools/clippy/lintcheck/src/config.rs15
-rw-r--r--src/tools/clippy/lintcheck/src/driver.rs67
-rw-r--r--src/tools/clippy/lintcheck/src/main.rs320
-rw-r--r--src/tools/clippy/lintcheck/src/recursive.rs123
-rw-r--r--src/tools/clippy/rust-toolchain2
-rw-r--r--src/tools/clippy/rustc_tools_util/Cargo.toml2
-rw-r--r--src/tools/clippy/rustc_tools_util/README.md8
-rw-r--r--src/tools/clippy/rustc_tools_util/src/lib.rs12
-rw-r--r--src/tools/clippy/src/docs.rs14
-rw-r--r--src/tools/clippy/src/docs/arithmetic_side_effects.txt2
-rw-r--r--src/tools/clippy/src/docs/as_ptr_cast_mut.txt19
-rw-r--r--src/tools/clippy/src/docs/box_default.txt17
-rw-r--r--src/tools/clippy/src/docs/cast_nan_to_int.txt15
-rw-r--r--src/tools/clippy/src/docs/disallowed_macros.txt36
-rw-r--r--src/tools/clippy/src/docs/for_loops_over_fallibles.txt32
-rw-r--r--src/tools/clippy/src/docs/implicit_saturating_add.txt20
-rw-r--r--src/tools/clippy/src/docs/iter_kv_map.txt22
-rw-r--r--src/tools/clippy/src/docs/manual_clamp.txt46
-rw-r--r--src/tools/clippy/src/docs/manual_filter.txt21
-rw-r--r--src/tools/clippy/src/docs/missing_trait_methods.txt40
-rw-r--r--src/tools/clippy/src/docs/needless_borrowed_reference.txt18
-rw-r--r--src/tools/clippy/src/docs/partial_pub_fields.txt27
-rw-r--r--src/tools/clippy/src/docs/positional_named_format_parameters.txt15
-rw-r--r--src/tools/clippy/src/docs/print_literal.txt4
-rw-r--r--src/tools/clippy/src/docs/print_stderr.txt8
-rw-r--r--src/tools/clippy/src/docs/print_stdout.txt8
-rw-r--r--src/tools/clippy/src/docs/similar_names.txt4
-rw-r--r--src/tools/clippy/src/docs/uninlined_format_args.txt36
-rw-r--r--src/tools/clippy/src/docs/unused_format_specs.txt24
-rw-r--r--src/tools/clippy/src/docs/write_literal.txt4
-rw-r--r--src/tools/clippy/src/driver.rs6
-rw-r--r--src/tools/clippy/src/main.rs6
-rw-r--r--src/tools/clippy/tests/compile-test.rs25
-rw-r--r--src/tools/clippy/tests/dogfood.rs9
-rw-r--r--src/tools/clippy/tests/integration.rs23
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs2
-rw-r--r--src/tools/clippy/tests/missing-test-files.rs2
-rw-r--r--src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr2
-rw-r--r--src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr4
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr2
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml9
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad/inner.rs1
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs7
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr11
-rw-r--r--src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr2
-rw-r--r--src/tools/clippy/tests/ui-internal/auxiliary/paths.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr4
-rw-r--r--src/tools/clippy/tests/ui-internal/custom_ice_message.stderr2
-rw-r--r--src/tools/clippy/tests/ui-internal/if_chain_style.stderr2
-rw-r--r--src/tools/clippy/tests/ui-internal/invalid_paths.rs2
-rw-r--r--src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs39
-rw-r--r--src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr27
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed62
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs62
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr101
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs16
-rw-r--r--src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr27
-rw-r--r--src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr4
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/auxiliary/macros.rs32
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/clippy.toml11
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs39
-rw-r--r--src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr84
-rw-r--r--src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed62
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs2
-rw-r--r--src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr77
-rw-r--r--src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr2
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml1
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs6
-rw-r--r--src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr24
-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.stderr2
-rw-r--r--src/tools/clippy/tests/ui/absurd-extreme-comparisons.stderr2
-rw-r--r--src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr2
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_letter_range.fixed13
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_letter_range.rs13
-rw-r--r--src/tools/clippy/tests/ui/almost_complete_letter_range.stderr39
-rw-r--r--src/tools/clippy/tests/ui/approx_const.stderr2
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.rs191
-rw-r--r--src/tools/clippy/tests/ui/arithmetic_side_effects.stderr356
-rw-r--r--src/tools/clippy/tests/ui/as_conversions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/as_ptr_cast_mut.rs37
-rw-r--r--src/tools/clippy/tests/ui/as_ptr_cast_mut.stderr16
-rw-r--r--src/tools/clippy/tests/ui/asm_syntax.stderr4
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_constants.stderr2
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.fixed6
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.rs6
-rw-r--r--src/tools/clippy/tests/ui/assertions_on_result_states.stderr8
-rw-r--r--src/tools/clippy/tests/ui/assign_ops2.rs2
-rw-r--r--src/tools/clippy/tests/ui/assign_ops2.stderr20
-rw-r--r--src/tools/clippy/tests/ui/author.stdout24
-rw-r--r--src/tools/clippy/tests/ui/author/blocks.stdout116
-rw-r--r--src/tools/clippy/tests/ui/author/call.stdout28
-rw-r--r--src/tools/clippy/tests/ui/author/if.stdout92
-rw-r--r--src/tools/clippy/tests/ui/author/issue_3849.stdout24
-rw-r--r--src/tools/clippy/tests/ui/author/loop.stdout202
-rw-r--r--src/tools/clippy/tests/ui/author/matches.stdout72
-rw-r--r--src/tools/clippy/tests/ui/author/repeat.stdout20
-rw-r--r--src/tools/clippy/tests/ui/author/struct.stdout112
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/macro_rules.rs7
-rw-r--r--src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs2
-rw-r--r--src/tools/clippy/tests/ui/await_holding_lock.stderr2
-rw-r--r--src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr2
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map.fixed1
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map.rs1
-rw-r--r--src/tools/clippy/tests/ui/bind_instead_of_map.stderr6
-rw-r--r--src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr2
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.fixed8
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.rs14
-rw-r--r--src/tools/clippy/tests/ui/bool_to_int_with_if.stderr43
-rw-r--r--src/tools/clippy/tests/ui/borrow_box.rs5
-rw-r--r--src/tools/clippy/tests/ui/borrow_box.stderr20
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr2
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr2
-rw-r--r--src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr2
-rw-r--r--src/tools/clippy/tests/ui/box_collection.rs4
-rw-r--r--src/tools/clippy/tests/ui/box_collection.stderr2
-rw-r--r--src/tools/clippy/tests/ui/box_default.fixed57
-rw-r--r--src/tools/clippy/tests/ui/box_default.rs57
-rw-r--r--src/tools/clippy/tests/ui/box_default.stderr88
-rw-r--r--src/tools/clippy/tests/ui/box_default_no_std.rs33
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs3
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr22
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs5
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr32
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs3
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr30
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs5
-rw-r--r--src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr30
-rw-r--r--src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr2
-rw-r--r--src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed17
-rw-r--r--src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs17
-rw-r--r--src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr42
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.fixed13
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.rs13
-rw-r--r--src/tools/clippy/tests/ui/cast_lossless_bool.stderr34
-rw-r--r--src/tools/clippy/tests/ui/cast_nan_to_int.rs18
-rw-r--r--src/tools/clippy/tests/ui/cast_nan_to_int.stderr51
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed16
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs16
-rw-r--r--src/tools/clippy/tests/ui/cfg_attr_rustfmt.stderr8
-rw-r--r--src/tools/clippy/tests/ui/char_lit_as_u8.stderr2
-rw-r--r--src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/checked_conversions.fixed16
-rw-r--r--src/tools/clippy/tests/ui/checked_conversions.rs16
-rw-r--r--src/tools/clippy/tests/ui/checked_conversions.stderr40
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr2
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed24
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.rs24
-rw-r--r--src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr30
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity.stderr2
-rw-r--r--src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr2
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.fixed3
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.rs5
-rw-r--r--src/tools/clippy/tests/ui/collapsible_if.stderr10
-rw-r--r--src/tools/clippy/tests/ui/collapsible_match.rs24
-rw-r--r--src/tools/clippy/tests/ui/collapsible_match.stderr76
-rw-r--r--src/tools/clippy/tests/ui/collapsible_match2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/comparison_chain.stderr2
-rw-r--r--src/tools/clippy/tests/ui/copy_iterator.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-360.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-4775.rs2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-6254.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7126.rs6
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7868.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-7869.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9445.rs3
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9459.rs5
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9463.rs5
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9463.stderr29
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-9625.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/regressions.rs2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr2
-rw-r--r--src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr2
-rw-r--r--src/tools/clippy/tests/ui/def_id_nocore.stderr2
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed9
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs9
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr34
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed10
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs10
-rw-r--r--src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr34
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.fixed4
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.rs4
-rw-r--r--src/tools/clippy/tests/ui/default_trait_access.stderr2
-rw-r--r--src/tools/clippy/tests/ui/default_union_representation.stderr2
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.fixed213
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.rs4
-rw-r--r--src/tools/clippy/tests/ui/derivable_impls.stderr56
-rw-r--r--src/tools/clippy/tests/ui/derive.stderr2
-rw-r--r--src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr2
-rw-r--r--src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr2
-rw-r--r--src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr2
-rw-r--r--src/tools/clippy/tests/ui/doc_link_with_quotes.rs7
-rw-r--r--src/tools/clippy/tests/ui/doc_link_with_quotes.stderr6
-rw-r--r--src/tools/clippy/tests/ui/double_must_use.stderr2
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.rs20
-rw-r--r--src/tools/clippy/tests/ui/drop_forget_copy.stderr42
-rw-r--r--src/tools/clippy/tests/ui/drop_non_drop.stderr2
-rw-r--r--src/tools/clippy/tests/ui/drop_ref.stderr2
-rw-r--r--src/tools/clippy/tests/ui/else_if_without_else.stderr2
-rw-r--r--src/tools/clippy/tests/ui/empty_enum.stderr2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop.stderr2
-rw-r--r--src/tools/clippy/tests/ui/empty_loop_no_std.stderr2
-rw-r--r--src/tools/clippy/tests/ui/entry.fixed1
-rw-r--r--src/tools/clippy/tests/ui/entry.rs1
-rw-r--r--src/tools/clippy/tests/ui/entry.stderr20
-rw-r--r--src/tools/clippy/tests/ui/eprint_with_newline.rs10
-rw-r--r--src/tools/clippy/tests/ui/eprint_with_newline.stderr18
-rw-r--r--src/tools/clippy/tests/ui/err_expect.fixed17
-rw-r--r--src/tools/clippy/tests/ui/err_expect.rs17
-rw-r--r--src/tools/clippy/tests/ui/err_expect.stderr10
-rw-r--r--src/tools/clippy/tests/ui/eta.fixed25
-rw-r--r--src/tools/clippy/tests/ui/eta.rs25
-rw-r--r--src/tools/clippy/tests/ui/eta.stderr20
-rw-r--r--src/tools/clippy/tests/ui/expect.stderr2
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.fixed9
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.rs9
-rw-r--r--src/tools/clippy/tests/ui/expect_fun_call.stderr40
-rw-r--r--src/tools/clippy/tests/ui/explicit_counter_loop.rs1
-rw-r--r--src/tools/clippy/tests/ui/explicit_counter_loop.stderr18
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.fixed10
-rw-r--r--src/tools/clippy/tests/ui/explicit_deref_methods.rs10
-rw-r--r--src/tools/clippy/tests/ui/explicit_write.fixed5
-rw-r--r--src/tools/clippy/tests/ui/explicit_write.rs5
-rw-r--r--src/tools/clippy/tests/ui/explicit_write.stderr32
-rw-r--r--src/tools/clippy/tests/ui/fallible_impl_from.rs1
-rw-r--r--src/tools/clippy/tests/ui/fallible_impl_from.stderr26
-rw-r--r--src/tools/clippy/tests/ui/field_reassign_with_default.stderr2
-rw-r--r--src/tools/clippy/tests/ui/filetype_is_file.stderr2
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.fixed16
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.rs16
-rw-r--r--src/tools/clippy/tests/ui/filter_map_next_fixable.stderr10
-rw-r--r--src/tools/clippy/tests/ui/float_cmp.stderr2
-rw-r--r--src/tools/clippy/tests/ui/float_cmp_const.stderr2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_exp.fixed1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_exp.rs1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_exp.stderr10
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_log.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_logbase.fixed1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_logbase.rs1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_logbase.stderr10
-rw-r--r--src/tools/clippy/tests/ui/floating_point_mul_add.fixed2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_mul_add.rs2
-rw-r--r--src/tools/clippy/tests/ui/floating_point_mul_add.stderr30
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.fixed1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.rs1
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powf.stderr62
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.fixed3
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.rs3
-rw-r--r--src/tools/clippy/tests/ui/floating_point_powi.stderr24
-rw-r--r--src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr2
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/for_loop_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/for_loop_unfixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/for_loop_unfixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/for_loops_over_fallibles.rs72
-rw-r--r--src/tools/clippy/tests/ui/for_loops_over_fallibles.stderr95
-rw-r--r--src/tools/clippy/tests/ui/forget_non_drop.stderr2
-rw-r--r--src/tools/clippy/tests/ui/forget_ref.stderr2
-rw-r--r--src/tools/clippy/tests/ui/format.fixed10
-rw-r--r--src/tools/clippy/tests/ui/format.rs10
-rw-r--r--src/tools/clippy/tests/ui/format.stderr44
-rw-r--r--src/tools/clippy/tests/ui/format_args.fixed15
-rw-r--r--src/tools/clippy/tests/ui/format_args.rs15
-rw-r--r--src/tools/clippy/tests/ui/format_args.stderr60
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.rs6
-rw-r--r--src/tools/clippy/tests/ui/format_args_unfixable.stderr38
-rw-r--r--src/tools/clippy/tests/ui/format_push_string.stderr2
-rw-r--r--src/tools/clippy/tests/ui/formatting.stderr4
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.fixed87
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.rs66
-rw-r--r--src/tools/clippy/tests/ui/from_over_into.stderr70
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.rs35
-rw-r--r--src/tools/clippy/tests/ui/from_over_into_unfixable.stderr29
-rw-r--r--src/tools/clippy/tests/ui/functions.rs4
-rw-r--r--src/tools/clippy/tests/ui/future_not_send.stderr2
-rw-r--r--src/tools/clippy/tests/ui/get_unwrap.stderr2
-rw-r--r--src/tools/clippy/tests/ui/identity_op.fixed4
-rw-r--r--src/tools/clippy/tests/ui/identity_op.rs4
-rw-r--r--src/tools/clippy/tests/ui/if_let_mutex.stderr2
-rw-r--r--src/tools/clippy/tests/ui/if_not_else.stderr2
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else.stderr2
-rw-r--r--src/tools/clippy/tests/ui/if_same_then_else2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/if_then_some_else_none.stderr2
-rw-r--r--src/tools/clippy/tests/ui/ifs_same_cond.stderr2
-rw-r--r--src/tools/clippy/tests/ui/impl.stderr2
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_add.fixed106
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_add.rs154
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_add.stderr197
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.fixed50
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.rs50
-rw-r--r--src/tools/clippy/tests/ui/implicit_saturating_sub.stderr46
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs1
-rw-r--r--src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr20
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.rs2
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_index.stderr10
-rw-r--r--src/tools/clippy/tests/ui/indexing_slicing_slice.stderr2
-rw-r--r--src/tools/clippy/tests/ui/inefficient_to_string.stderr10
-rw-r--r--src/tools/clippy/tests/ui/infinite_iter.rs2
-rw-r--r--src/tools/clippy/tests/ui/infinite_iter.stderr32
-rw-r--r--src/tools/clippy/tests/ui/infinite_loop.stderr2
-rw-r--r--src/tools/clippy/tests/ui/inherent_to_string.stderr4
-rw-r--r--src/tools/clippy/tests/ui/inspect_for_each.stderr2
-rw-r--r--src/tools/clippy/tests/ui/integer_division.stderr2
-rw-r--r--src/tools/clippy/tests/ui/issue_2356.fixed1
-rw-r--r--src/tools/clippy/tests/ui/issue_2356.rs1
-rw-r--r--src/tools/clippy/tests/ui/issue_2356.stderr2
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.rs1
-rw-r--r--src/tools/clippy/tests/ui/issue_4266.stderr8
-rw-r--r--src/tools/clippy/tests/ui/item_after_statement.rs1
-rw-r--r--src/tools/clippy/tests/ui/item_after_statement.stderr6
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.fixed64
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.rs64
-rw-r--r--src/tools/clippy/tests/ui/iter_kv_map.stderr136
-rw-r--r--src/tools/clippy/tests/ui/iter_nth.stderr2
-rw-r--r--src/tools/clippy/tests/ui/iter_skip_next_unfixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.rs4
-rw-r--r--src/tools/clippy/tests/ui/large_enum_variant.stderr16
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.rs6
-rw-r--r--src/tools/clippy/tests/ui/large_stack_arrays.stderr10
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.rs2
-rw-r--r--src/tools/clippy/tests/ui/len_without_is_empty.stderr2
-rw-r--r--src/tools/clippy/tests/ui/let_if_seq.stderr2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_drop.stderr2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_lock.stderr2
-rw-r--r--src/tools/clippy/tests/ui/let_underscore_must_use.stderr2
-rw-r--r--src/tools/clippy/tests/ui/linkedlist.stderr2
-rw-r--r--src/tools/clippy/tests/ui/literals.rs7
-rw-r--r--src/tools/clippy/tests/ui/literals.stderr35
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.fixed43
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2018.stderr58
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.fixed18
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.edition2021.stderr51
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.fixed45
-rw-r--r--src/tools/clippy/tests/ui/manual_assert.rs19
-rw-r--r--src/tools/clippy/tests/ui/manual_bits.fixed3
-rw-r--r--src/tools/clippy/tests/ui/manual_bits.rs3
-rw-r--r--src/tools/clippy/tests/ui/manual_bits.stderr58
-rw-r--r--src/tools/clippy/tests/ui/manual_clamp.rs331
-rw-r--r--src/tools/clippy/tests/ui/manual_clamp.stderr390
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.fixed119
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.rs243
-rw-r--r--src/tools/clippy/tests/ui/manual_filter.stderr191
-rw-r--r--src/tools/clippy/tests/ui/manual_find.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.fixed4
-rw-r--r--src/tools/clippy/tests/ui/manual_find_fixable.rs4
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_flatten.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.fixed2
-rw-r--r--src/tools/clippy/tests/ui/manual_map_option.rs2
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr2
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.fixed30
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.rs30
-rw-r--r--src/tools/clippy/tests/ui/manual_rem_euclid.stderr30
-rw-r--r--src/tools/clippy/tests/ui/manual_strip.rs19
-rw-r--r--src/tools/clippy/tests/ui/manual_strip.stderr49
-rw-r--r--src/tools/clippy/tests/ui/map_err.stderr2
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or.rs18
-rw-r--r--src/tools/clippy/tests/ui/map_unwrap_or.stderr30
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed16
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs19
-rw-r--r--src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr38
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.rs1
-rw-r--r--src/tools/clippy/tests/ui/match_overlapping_arm.stderr34
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.fixed3
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.rs3
-rw-r--r--src/tools/clippy/tests/ui/match_ref_pats.stderr10
-rw-r--r--src/tools/clippy/tests/ui/match_result_ok.fixed3
-rw-r--r--src/tools/clippy/tests/ui/match_result_ok.rs3
-rw-r--r--src/tools/clippy/tests/ui/match_result_ok.stderr6
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms.stderr2
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.rs6
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms2.stderr48
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.fixed13
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.rs12
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding.stderr19
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.fixed2
-rw-r--r--src/tools/clippy/tests/ui/match_single_binding2.rs2
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr35
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.rs3
-rw-r--r--src/tools/clippy/tests/ui/match_wild_err_arm.stderr (renamed from src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr)10
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.fixed18
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.rs18
-rw-r--r--src/tools/clippy/tests/ui/mem_replace.stderr46
-rw-r--r--src/tools/clippy/tests/ui/min_max.rs1
-rw-r--r--src/tools/clippy/tests/ui/min_max.stderr26
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.rs227
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_attr.stderr46
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs14
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr44
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs11
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr38
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_no_patch.rs14
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs4
-rw-r--r--src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr8
-rw-r--r--src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr2
-rw-r--r--src/tools/clippy/tests/ui/mismatching_type_param_order.stderr2
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs12
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr12
-rw-r--r--src/tools/clippy/tests/ui/missing_doc.rs1
-rw-r--r--src/tools/clippy/tests/ui/missing_doc.stderr48
-rw-r--r--src/tools/clippy/tests/ui/missing_panics_doc.stderr2
-rw-r--r--src/tools/clippy/tests/ui/missing_trait_methods.rs50
-rw-r--r--src/tools/clippy/tests/ui/missing_trait_methods.stderr27
-rw-r--r--src/tools/clippy/tests/ui/mixed_read_write_in_expression.stderr2
-rw-r--r--src/tools/clippy/tests/ui/modulo_arithmetic_float.stderr2
-rw-r--r--src/tools/clippy/tests/ui/modulo_arithmetic_integral.stderr2
-rw-r--r--src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr2
-rw-r--r--src/tools/clippy/tests/ui/mut_from_ref.stderr2
-rw-r--r--src/tools/clippy/tests/ui/mut_mut.rs4
-rw-r--r--src/tools/clippy/tests/ui/mut_range_bound.stderr2
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.fixed93
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.rs91
-rw-r--r--src/tools/clippy/tests/ui/needless_borrow.stderr96
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.fixed41
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.rs41
-rw-r--r--src/tools/clippy/tests/ui/needless_borrowed_ref.stderr121
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_collect_indirect.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_continue.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_continue.stderr18
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.fixed7
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.rs7
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_fixable.stderr16
-rw-r--r--src/tools/clippy/tests/ui/needless_for_each_unfixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.fixed5
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.rs5
-rw-r--r--src/tools/clippy/tests/ui/needless_late_init.stderr32
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_value.rs9
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_value.stderr52
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.rs1
-rw-r--r--src/tools/clippy/tests/ui/needless_range_loop.stderr28
-rw-r--r--src/tools/clippy/tests/ui/needless_return.fixed37
-rw-r--r--src/tools/clippy/tests/ui/needless_return.rs37
-rw-r--r--src/tools/clippy/tests/ui/needless_return.stderr205
-rw-r--r--src/tools/clippy/tests/ui/never_loop.rs26
-rw-r--r--src/tools/clippy/tests/ui/never_loop.stderr15
-rw-r--r--src/tools/clippy/tests/ui/no_effect.rs6
-rw-r--r--src/tools/clippy/tests/ui/no_effect.stderr60
-rw-r--r--src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr2
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.rs6
-rw-r--r--src/tools/clippy/tests/ui/nonminimal_bool.stderr8
-rw-r--r--src/tools/clippy/tests/ui/octal_escapes.stderr2
-rw-r--r--src/tools/clippy/tests/ui/ok_expect.stderr2
-rw-r--r--src/tools/clippy/tests/ui/only_used_in_recursion.stderr2
-rw-r--r--src/tools/clippy/tests/ui/only_used_in_recursion2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.fixed17
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.rs17
-rw-r--r--src/tools/clippy/tests/ui/option_as_ref_deref.stderr42
-rw-r--r--src/tools/clippy/tests/ui/option_env_unwrap.stderr2
-rw-r--r--src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed3
-rw-r--r--src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs3
-rw-r--r--src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr38
-rw-r--r--src/tools/clippy/tests/ui/option_take_on_temporary.fixed15
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.fixed14
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.rs14
-rw-r--r--src/tools/clippy/tests/ui/or_fun_call.stderr52
-rw-r--r--src/tools/clippy/tests/ui/out_of_bounds_indexing/issue-3102.rs2
-rw-r--r--src/tools/clippy/tests/ui/out_of_bounds_indexing/simple.rs2
-rw-r--r--src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr2
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn.stderr2
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn_assertions.rs2
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs2
-rw-r--r--src/tools/clippy/tests/ui/partial_pub_fields.rs40
-rw-r--r--src/tools/clippy/tests/ui/partial_pub_fields.stderr35
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.stderr2
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr2
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr2
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr2
-rw-r--r--src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr2
-rw-r--r--src/tools/clippy/tests/ui/patterns.fixed3
-rw-r--r--src/tools/clippy/tests/ui/patterns.rs3
-rw-r--r--src/tools/clippy/tests/ui/patterns.stderr6
-rw-r--r--src/tools/clippy/tests/ui/positional_named_format_parameters.fixed56
-rw-r--r--src/tools/clippy/tests/ui/positional_named_format_parameters.rs56
-rw-r--r--src/tools/clippy/tests/ui/positional_named_format_parameters.stderr418
-rw-r--r--src/tools/clippy/tests/ui/print_literal.rs3
-rw-r--r--src/tools/clippy/tests/ui/print_literal.stderr56
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.rs10
-rw-r--r--src/tools/clippy/tests/ui/print_with_newline.stderr18
-rw-r--r--src/tools/clippy/tests/ui/println_empty_string.stderr24
-rw-r--r--src/tools/clippy/tests/ui/proc_macro.stderr2
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.rs30
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr20
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed1
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.rs1
-rw-r--r--src/tools/clippy/tests/ui/ptr_offset_with_cast.stderr4
-rw-r--r--src/tools/clippy/tests/ui/pub_use.stderr2
-rw-r--r--src/tools/clippy/tests/ui/question_mark.fixed9
-rw-r--r--src/tools/clippy/tests/ui/question_mark.rs9
-rw-r--r--src/tools/clippy/tests/ui/range_contains.fixed26
-rw-r--r--src/tools/clippy/tests/ui/range_contains.rs26
-rw-r--r--src/tools/clippy/tests/ui/range_contains.stderr48
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr2
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr2
-rw-r--r--src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr2
-rw-r--r--src/tools/clippy/tests/ui/rc_mutex.stderr2
-rw-r--r--src/tools/clippy/tests/ui/recursive_format_impl.rs5
-rw-r--r--src/tools/clippy/tests/ui/recursive_format_impl.stderr20
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation.stderr2
-rw-r--r--src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.fixed4
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.rs4
-rw-r--r--src/tools/clippy/tests/ui/redundant_clone.stderr2
-rw-r--r--src/tools/clippy/tests/ui/redundant_else.stderr2
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.fixed16
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.rs16
-rw-r--r--src/tools/clippy/tests/ui/redundant_field_names.stderr22
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr2
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed11
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs11
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr36
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed11
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs11
-rw-r--r--src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr44
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed13
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.rs13
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr40
-rw-r--r--src/tools/clippy/tests/ui/ref_option_ref.rs5
-rw-r--r--src/tools/clippy/tests/ui/regex.stderr2
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed9
-rw-r--r--src/tools/clippy/tests/ui/rename.rs5
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr96
-rw-r--r--src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr2
-rw-r--r--src/tools/clippy/tests/ui/result_large_err.stderr2
-rw-r--r--src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed2
-rw-r--r--src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs2
-rw-r--r--src/tools/clippy/tests/ui/result_unit_error.stderr2
-rw-r--r--src/tools/clippy/tests/ui/return_self_not_must_use.stderr2
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.stderr8
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed1
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.stderr12
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.rs1
-rw-r--r--src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.stderr4
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.rs12
-rw-r--r--src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr26
-rw-r--r--src/tools/clippy/tests/ui/same_item_push.stderr2
-rw-r--r--src/tools/clippy/tests/ui/same_name_method.stderr2
-rw-r--r--src/tools/clippy/tests/ui/search_is_some.stderr2
-rw-r--r--src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs2
-rw-r--r--src/tools/clippy/tests/ui/shadow.stderr6
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr14
-rw-r--r--src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs7
-rw-r--r--src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr54
-rw-r--r--src/tools/clippy/tests/ui/similar_names.stderr2
-rw-r--r--src/tools/clippy/tests/ui/single_char_lifetime_names.stderr2
-rw-r--r--src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr2
-rw-r--r--src/tools/clippy/tests/ui/single_match.rs1
-rw-r--r--src/tools/clippy/tests/ui/single_match.stderr32
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.rs4
-rw-r--r--src/tools/clippy/tests/ui/single_match_else.stderr10
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr2
-rw-r--r--src/tools/clippy/tests/ui/skip_while_next.stderr2
-rw-r--r--src/tools/clippy/tests/ui/stable_sort_primitive.stderr2
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.rs6
-rw-r--r--src/tools/clippy/tests/ui/std_instead_of_core.stderr22
-rw-r--r--src/tools/clippy/tests/ui/str_to_string.stderr2
-rw-r--r--src/tools/clippy/tests/ui/string_to_string.stderr2
-rw-r--r--src/tools/clippy/tests/ui/struct_excessive_bools.stderr2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_else_formatting.stderr2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_map.stderr2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_splitn.stderr2
-rw-r--r--src/tools/clippy/tests/ui/suspicious_to_owned.stderr8
-rw-r--r--src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr2
-rw-r--r--src/tools/clippy/tests/ui/swap.stderr4
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.fixed2
-rw-r--r--src/tools/clippy/tests/ui/toplevel_ref_arg.rs2
-rw-r--r--src/tools/clippy/tests/ui/trailing_empty_array.stderr2
-rw-r--r--src/tools/clippy/tests/ui/trait_duplication_in_bounds_unfixable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr4
-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/trivially_copy_pass_by_ref.rs7
-rw-r--r--src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr38
-rw-r--r--src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr2
-rw-r--r--src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr2
-rw-r--r--src/tools/clippy/tests/ui/undropped_manually_drops.stderr2
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.rs6
-rw-r--r--src/tools/clippy/tests/ui/uninit_vec.stderr2
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.fixed182
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.rs182
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args.stderr879
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed29
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr15
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed29
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr51
-rw-r--r--src/tools/clippy/tests/ui/uninlined_format_args_panic.rs29
-rw-r--r--src/tools/clippy/tests/ui/unit_arg.rs15
-rw-r--r--src/tools/clippy/tests/ui/unit_arg.stderr20
-rw-r--r--src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed3
-rw-r--r--src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs3
-rw-r--r--src/tools/clippy/tests/ui/unit_arg_empty_blocks.stderr8
-rw-r--r--src/tools/clippy/tests/ui/unit_hash.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.fixed18
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.rs18
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_cast.stderr20
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_clone.rs4
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.fixed2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_join.rs2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed21
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs21
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr68
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_self_imports.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.fixed11
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.rs11
-rw-r--r--src/tools/clippy/tests/ui/unnecessary_to_owned.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unneeded_field_pattern.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.fixed16
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.rs16
-rw-r--r--src/tools/clippy/tests/ui/unnested_or_patterns.stderr13
-rw-r--r--src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unsafe_removed_from_name.rs3
-rw-r--r--src/tools/clippy/tests/ui/unused_async.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.fixed18
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.rs18
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs.stderr54
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs_unfixable.rs30
-rw-r--r--src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr69
-rw-r--r--src/tools/clippy/tests/ui/unused_io_amount.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unused_peekable.rs33
-rw-r--r--src/tools/clippy/tests/ui/unused_peekable.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unused_self.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unwrap.stderr2
-rw-r--r--src/tools/clippy/tests/ui/unwrap_expect_used.stderr4
-rw-r--r--src/tools/clippy/tests/ui/unwrap_in_result.stderr2
-rw-r--r--src/tools/clippy/tests/ui/upper_case_acronyms.rs9
-rw-r--r--src/tools/clippy/tests/ui/upper_case_acronyms.stderr14
-rw-r--r--src/tools/clippy/tests/ui/use_self.fixed42
-rw-r--r--src/tools/clippy/tests/ui/use_self.rs42
-rw-r--r--src/tools/clippy/tests/ui/use_self.stderr90
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.rs3
-rw-r--r--src/tools/clippy/tests/ui/used_underscore_binding.stderr12
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.fixed3
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.rs3
-rw-r--r--src/tools/clippy/tests/ui/useless_asref.stderr24
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr2
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion_try.stderr2
-rw-r--r--src/tools/clippy/tests/ui/vec.fixed2
-rw-r--r--src/tools/clippy/tests/ui/vec.rs2
-rw-r--r--src/tools/clippy/tests/ui/vec_resize_to_zero.stderr2
-rw-r--r--src/tools/clippy/tests/ui/verbose_file_reads.stderr2
-rw-r--r--src/tools/clippy/tests/ui/vtable_address_comparisons.stderr2
-rw-r--r--src/tools/clippy/tests/ui/while_let_loop.rs1
-rw-r--r--src/tools/clippy/tests/ui/while_let_loop.stderr10
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.fixed10
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.rs10
-rw-r--r--src/tools/clippy/tests/ui/while_let_on_iterator.stderr52
-rw-r--r--src/tools/clippy/tests/ui/wild_in_or_pats.stderr2
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed10
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs10
-rw-r--r--src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr14
-rw-r--r--src/tools/clippy/tests/ui/write_literal.rs4
-rw-r--r--src/tools/clippy/tests/ui/write_literal.stderr56
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.rs9
-rw-r--r--src/tools/clippy/tests/ui/write_literal_2.stderr80
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.rs8
-rw-r--r--src/tools/clippy/tests/ui/write_with_newline.stderr38
-rw-r--r--src/tools/clippy/tests/ui/writeln_empty_string.stderr12
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention.stderr2
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_convention2.stderr2
-rw-r--r--src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr2
-rw-r--r--src/tools/clippy/tests/ui/zero_div_zero.stderr2
-rw-r--r--src/tools/clippy/tests/ui/zero_sized_btreemap_values.stderr2
-rw-r--r--src/tools/clippy/tests/ui/zero_sized_hashmap_values.stderr2
-rw-r--r--src/tools/clippy/tests/versioncheck.rs8
-rw-r--r--src/tools/compiletest/src/common.rs28
-rw-r--r--src/tools/compiletest/src/header.rs20
-rw-r--r--src/tools/compiletest/src/main.rs29
-rw-r--r--src/tools/compiletest/src/runtest.rs35
-rw-r--r--src/tools/compiletest/src/util.rs6
-rw-r--r--src/tools/error_index_generator/error-index.css3
-rw-r--r--src/tools/jsondoclint/src/item_kind.rs3
-rw-r--r--src/tools/jsondoclint/src/validator.rs10
-rw-r--r--src/tools/linkchecker/main.rs1
-rwxr-xr-xsrc/tools/publish_toolstate.py17
-rw-r--r--src/tools/rust-analyzer/Cargo.lock205
-rw-r--r--src/tools/rust-analyzer/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/fixture.rs8
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs22
-rw-r--r--src/tools/rust-analyzer/crates/cfg/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs103
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/adt.rs244
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/child_by_source.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expr.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs362
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs86
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/name.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs217
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs75
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs108
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs43
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs64
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs44
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs114
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs78
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs102
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs235
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs110
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs22
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/method_resolution.rs34
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs159
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs101
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml6
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/from_id.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs158
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs46
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs822
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs35
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_new.rs61
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs52
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs39
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs141
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_getter.rs325
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs296
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs3
-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_qualified_name_with_use.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs159
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs91
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs88
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs150
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs51
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs247
-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.rs45
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs1939
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs46
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs267
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml6
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs31
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/json_is_not_rust.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/annotations.rs307
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs (renamed from src/tools/rust-analyzer/crates/ide/src/fn_references.rs)37
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs63
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs136
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs83
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/parent_module.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/status.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html8
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs30
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander.rs3
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs91
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs57
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs41
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml2
-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/mod.rs11
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs9
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs11
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs12
-rw-r--r--src/tools/rust-analyzer/crates/profile/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs374
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs184
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs22
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs3
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs17
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs74
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs66
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs197
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs11
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs84
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs31
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs28
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs110
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs211
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/from_proto.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs53
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs33
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp_utils.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs188
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs143
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/to_proto.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs12
-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.rs1
-rw-r--r--src/tools/rust-analyzer/crates/sourcegen/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs61
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs23
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs30
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs53
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs94
-rw-r--r--src/tools/rust-analyzer/crates/text-edit/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/docs/dev/README.md2
-rw-r--r--src/tools/rust-analyzer/docs/dev/guide.md9
-rw-r--r--src/tools/rust-analyzer/docs/dev/syntax.md6
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc74
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc17
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/Cargo.toml10
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/msg.rs10
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs7
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/xtask/src/flags.rs19
-rw-r--r--src/tools/rust-analyzer/xtask/src/main.rs7
-rw-r--r--src/tools/rustdoc/main.rs3
-rw-r--r--src/tools/rustfmt/src/chains.rs10
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs2
-rw-r--r--src/tools/rustfmt/src/items.rs12
-rw-r--r--src/tools/rustfmt/src/visitor.rs2
-rw-r--r--src/tools/tidy/src/alphabetical.rs111
-rw-r--r--src/tools/tidy/src/bins.rs5
-rw-r--r--src/tools/tidy/src/debug_artifacts.rs3
-rw-r--r--src/tools/tidy/src/deps.rs45
-rw-r--r--src/tools/tidy/src/edition.rs5
-rw-r--r--src/tools/tidy/src/error_codes_check.rs3
-rw-r--r--src/tools/tidy/src/errors.rs5
-rw-r--r--src/tools/tidy/src/features.rs276
-rw-r--r--src/tools/tidy/src/lib.rs3
-rw-r--r--src/tools/tidy/src/main.rs4
-rw-r--r--src/tools/tidy/src/pal.rs3
-rw-r--r--src/tools/tidy/src/style.rs5
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs6
-rw-r--r--src/tools/tidy/src/unit_tests.rs5
-rw-r--r--src/tools/tidy/src/walk.rs6
-rw-r--r--src/version2
-rw-r--r--vendor/clap-3.2.20/.cargo-checksum.json (renamed from vendor/clap/.cargo-checksum.json)0
-rw-r--r--vendor/clap-3.2.20/Cargo.lock (renamed from vendor/clap/Cargo.lock)0
-rw-r--r--vendor/clap-3.2.20/Cargo.toml (renamed from vendor/clap/Cargo.toml)0
-rw-r--r--vendor/clap-3.2.20/LICENSE-APACHE (renamed from vendor/clap/LICENSE-APACHE)0
-rw-r--r--vendor/clap-3.2.20/LICENSE-MIT (renamed from vendor/clap/LICENSE-MIT)0
-rw-r--r--vendor/clap-3.2.20/README.md (renamed from vendor/clap/README.md)0
-rw-r--r--vendor/clap-3.2.20/examples/cargo-example-derive.md (renamed from vendor/clap/examples/cargo-example-derive.md)0
-rw-r--r--vendor/clap-3.2.20/examples/cargo-example-derive.rs (renamed from vendor/clap/examples/cargo-example-derive.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/cargo-example.md (renamed from vendor/clap/examples/cargo-example.md)0
-rw-r--r--vendor/clap-3.2.20/examples/cargo-example.rs (renamed from vendor/clap/examples/cargo-example.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/demo.md (renamed from vendor/clap/examples/demo.md)0
-rw-r--r--vendor/clap-3.2.20/examples/demo.rs (renamed from vendor/clap/examples/demo.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/augment_args.rs (renamed from vendor/clap/examples/derive_ref/augment_args.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/augment_subcommands.rs (renamed from vendor/clap/examples/derive_ref/augment_subcommands.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/custom-bool.md (renamed from vendor/clap/examples/derive_ref/custom-bool.md)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/custom-bool.rs (renamed from vendor/clap/examples/derive_ref/custom-bool.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/flatten_hand_args.rs (renamed from vendor/clap/examples/derive_ref/flatten_hand_args.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/hand_subcommand.rs (renamed from vendor/clap/examples/derive_ref/hand_subcommand.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/derive_ref/interop_tests.md (renamed from vendor/clap/examples/derive_ref/interop_tests.md)0
-rw-r--r--vendor/clap-3.2.20/examples/escaped-positional-derive.md (renamed from vendor/clap/examples/escaped-positional-derive.md)0
-rw-r--r--vendor/clap-3.2.20/examples/escaped-positional-derive.rs (renamed from vendor/clap/examples/escaped-positional-derive.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/escaped-positional.md (renamed from vendor/clap/examples/escaped-positional.md)0
-rw-r--r--vendor/clap-3.2.20/examples/escaped-positional.rs (renamed from vendor/clap/examples/escaped-positional.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/git-derive.md (renamed from vendor/clap/examples/git-derive.md)0
-rw-r--r--vendor/clap-3.2.20/examples/git-derive.rs (renamed from vendor/clap/examples/git-derive.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/git.md (renamed from vendor/clap/examples/git.md)0
-rw-r--r--vendor/clap-3.2.20/examples/git.rs (renamed from vendor/clap/examples/git.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/multicall-busybox.md (renamed from vendor/clap/examples/multicall-busybox.md)0
-rw-r--r--vendor/clap-3.2.20/examples/multicall-busybox.rs (renamed from vendor/clap/examples/multicall-busybox.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/multicall-hostname.md (renamed from vendor/clap/examples/multicall-hostname.md)0
-rw-r--r--vendor/clap-3.2.20/examples/multicall-hostname.rs (renamed from vendor/clap/examples/multicall-hostname.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/pacman.md (renamed from vendor/clap/examples/pacman.md)0
-rw-r--r--vendor/clap-3.2.20/examples/pacman.rs (renamed from vendor/clap/examples/pacman.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/repl.rs (renamed from vendor/clap/examples/repl.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/01_quick.md (renamed from vendor/clap/examples/tutorial_builder/01_quick.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/01_quick.rs (renamed from vendor/clap/examples/tutorial_builder/01_quick.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.md (renamed from vendor/clap/examples/tutorial_builder/02_app_settings.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.rs (renamed from vendor/clap/examples/tutorial_builder/02_app_settings.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_apps.md (renamed from vendor/clap/examples/tutorial_builder/02_apps.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_apps.rs (renamed from vendor/clap/examples/tutorial_builder/02_apps.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_crate.md (renamed from vendor/clap/examples/tutorial_builder/02_crate.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/02_crate.rs (renamed from vendor/clap/examples/tutorial_builder/02_crate.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.md (renamed from vendor/clap/examples/tutorial_builder/03_01_flag_bool.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.rs (renamed from vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.md (renamed from vendor/clap/examples/tutorial_builder/03_01_flag_count.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.rs (renamed from vendor/clap/examples/tutorial_builder/03_01_flag_count.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.md (renamed from vendor/clap/examples/tutorial_builder/03_02_option.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.rs (renamed from vendor/clap/examples/tutorial_builder/03_02_option.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.md (renamed from vendor/clap/examples/tutorial_builder/03_03_positional.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.rs (renamed from vendor/clap/examples/tutorial_builder/03_03_positional.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.md (renamed from vendor/clap/examples/tutorial_builder/03_04_subcommands.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.rs (renamed from vendor/clap/examples/tutorial_builder/03_04_subcommands.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.md (renamed from vendor/clap/examples/tutorial_builder/03_05_default_values.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.rs (renamed from vendor/clap/examples/tutorial_builder/03_05_default_values.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.md (renamed from vendor/clap/examples/tutorial_builder/04_01_enum.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.rs (renamed from vendor/clap/examples/tutorial_builder/04_01_enum.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.md (renamed from vendor/clap/examples/tutorial_builder/04_01_possible.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.rs (renamed from vendor/clap/examples/tutorial_builder/04_01_possible.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.md (renamed from vendor/clap/examples/tutorial_builder/04_02_parse.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.rs (renamed from vendor/clap/examples/tutorial_builder/04_02_parse.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.md (renamed from vendor/clap/examples/tutorial_builder/04_02_validate.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.rs (renamed from vendor/clap/examples/tutorial_builder/04_02_validate.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.md (renamed from vendor/clap/examples/tutorial_builder/04_03_relations.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.rs (renamed from vendor/clap/examples/tutorial_builder/04_03_relations.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.md (renamed from vendor/clap/examples/tutorial_builder/04_04_custom.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.rs (renamed from vendor/clap/examples/tutorial_builder/04_04_custom.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_builder/05_01_assert.rs (renamed from vendor/clap/examples/tutorial_builder/05_01_assert.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/01_quick.md (renamed from vendor/clap/examples/tutorial_derive/01_quick.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/01_quick.rs (renamed from vendor/clap/examples/tutorial_derive/01_quick.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.md (renamed from vendor/clap/examples/tutorial_derive/02_app_settings.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.rs (renamed from vendor/clap/examples/tutorial_derive/02_app_settings.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_apps.md (renamed from vendor/clap/examples/tutorial_derive/02_apps.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_apps.rs (renamed from vendor/clap/examples/tutorial_derive/02_apps.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_crate.md (renamed from vendor/clap/examples/tutorial_derive/02_crate.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/02_crate.rs (renamed from vendor/clap/examples/tutorial_derive/02_crate.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.md (renamed from vendor/clap/examples/tutorial_derive/03_01_flag_bool.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.rs (renamed from vendor/clap/examples/tutorial_derive/03_01_flag_bool.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.md (renamed from vendor/clap/examples/tutorial_derive/03_01_flag_count.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.rs (renamed from vendor/clap/examples/tutorial_derive/03_01_flag_count.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.md (renamed from vendor/clap/examples/tutorial_derive/03_02_option.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.rs (renamed from vendor/clap/examples/tutorial_derive/03_02_option.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.md (renamed from vendor/clap/examples/tutorial_derive/03_03_positional.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.rs (renamed from vendor/clap/examples/tutorial_derive/03_03_positional.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.md (renamed from vendor/clap/examples/tutorial_derive/03_04_subcommands.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.rs (renamed from vendor/clap/examples/tutorial_derive/03_04_subcommands.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands_alt.rs (renamed from vendor/clap/examples/tutorial_derive/03_04_subcommands_alt.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.md (renamed from vendor/clap/examples/tutorial_derive/03_05_default_values.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.rs (renamed from vendor/clap/examples/tutorial_derive/03_05_default_values.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.md (renamed from vendor/clap/examples/tutorial_derive/04_01_enum.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.rs (renamed from vendor/clap/examples/tutorial_derive/04_01_enum.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.md (renamed from vendor/clap/examples/tutorial_derive/04_02_parse.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.rs (renamed from vendor/clap/examples/tutorial_derive/04_02_parse.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.md (renamed from vendor/clap/examples/tutorial_derive/04_02_validate.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.rs (renamed from vendor/clap/examples/tutorial_derive/04_02_validate.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.md (renamed from vendor/clap/examples/tutorial_derive/04_03_relations.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.rs (renamed from vendor/clap/examples/tutorial_derive/04_03_relations.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.md (renamed from vendor/clap/examples/tutorial_derive/04_04_custom.md)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.rs (renamed from vendor/clap/examples/tutorial_derive/04_04_custom.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/tutorial_derive/05_01_assert.rs (renamed from vendor/clap/examples/tutorial_derive/05_01_assert.rs)0
-rw-r--r--vendor/clap-3.2.20/examples/typed-derive.md (renamed from vendor/clap/examples/typed-derive.md)0
-rw-r--r--vendor/clap-3.2.20/examples/typed-derive.rs (renamed from vendor/clap/examples/typed-derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/cargo_example.rs (renamed from vendor/clap/src/_cookbook/cargo_example.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/cargo_example_derive (renamed from vendor/clap/src/_cookbook/cargo_example_derive)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/cargo_example_derive.rs (renamed from vendor/clap/src/_cookbook/cargo_example_derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/escaped_positional.rs (renamed from vendor/clap/src/_cookbook/escaped_positional.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/escaped_positional_derive.rs (renamed from vendor/clap/src/_cookbook/escaped_positional_derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/git.rs (renamed from vendor/clap/src/_cookbook/git.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/git_derive.rs (renamed from vendor/clap/src/_cookbook/git_derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/mod.rs (renamed from vendor/clap/src/_cookbook/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/multicall_busybox.rs (renamed from vendor/clap/src/_cookbook/multicall_busybox.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/multicall_hostname.rs (renamed from vendor/clap/src/_cookbook/multicall_hostname.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/pacman.rs (renamed from vendor/clap/src/_cookbook/pacman.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/repl.rs (renamed from vendor/clap/src/_cookbook/repl.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_cookbook/typed_derive.rs (renamed from vendor/clap/src/_cookbook/typed_derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_derive/_tutorial.rs (renamed from vendor/clap/src/_derive/_tutorial.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_derive/mod.rs (renamed from vendor/clap/src/_derive/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_faq.rs (renamed from vendor/clap/src/_faq.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_features.rs (renamed from vendor/clap/src/_features.rs)0
-rw-r--r--vendor/clap-3.2.20/src/_tutorial.rs (renamed from vendor/clap/src/_tutorial.rs)0
-rw-r--r--vendor/clap-3.2.20/src/bin/stdio-fixture.rs (renamed from vendor/clap/src/bin/stdio-fixture.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/action.rs (renamed from vendor/clap/src/builder/action.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/app_settings.rs (renamed from vendor/clap/src/builder/app_settings.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/arg.rs (renamed from vendor/clap/src/builder/arg.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/arg_group.rs (renamed from vendor/clap/src/builder/arg_group.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/arg_predicate.rs (renamed from vendor/clap/src/builder/arg_predicate.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/arg_settings.rs (renamed from vendor/clap/src/builder/arg_settings.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/command.rs (renamed from vendor/clap/src/builder/command.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/debug_asserts.rs (renamed from vendor/clap/src/builder/debug_asserts.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/macros.rs (renamed from vendor/clap/src/builder/macros.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/mod.rs (renamed from vendor/clap/src/builder/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/possible_value.rs (renamed from vendor/clap/src/builder/possible_value.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/regex.rs (renamed from vendor/clap/src/builder/regex.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/tests.rs (renamed from vendor/clap/src/builder/tests.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/usage_parser.rs (renamed from vendor/clap/src/builder/usage_parser.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/value_hint.rs (renamed from vendor/clap/src/builder/value_hint.rs)0
-rw-r--r--vendor/clap-3.2.20/src/builder/value_parser.rs (renamed from vendor/clap/src/builder/value_parser.rs)0
-rw-r--r--vendor/clap-3.2.20/src/derive.rs (renamed from vendor/clap/src/derive.rs)0
-rw-r--r--vendor/clap-3.2.20/src/error/context.rs (renamed from vendor/clap/src/error/context.rs)0
-rw-r--r--vendor/clap-3.2.20/src/error/kind.rs (renamed from vendor/clap/src/error/kind.rs)0
-rw-r--r--vendor/clap-3.2.20/src/error/mod.rs (renamed from vendor/clap/src/error/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/lib.rs (renamed from vendor/clap/src/lib.rs)0
-rw-r--r--vendor/clap-3.2.20/src/macros.rs (renamed from vendor/clap/src/macros.rs)0
-rw-r--r--vendor/clap-3.2.20/src/mkeymap.rs (renamed from vendor/clap/src/mkeymap.rs)0
-rw-r--r--vendor/clap-3.2.20/src/output/fmt.rs (renamed from vendor/clap/src/output/fmt.rs)0
-rw-r--r--vendor/clap-3.2.20/src/output/help.rs (renamed from vendor/clap/src/output/help.rs)0
-rw-r--r--vendor/clap-3.2.20/src/output/mod.rs (renamed from vendor/clap/src/output/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/output/usage.rs (renamed from vendor/clap/src/output/usage.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/arg_matcher.rs (renamed from vendor/clap/src/parser/arg_matcher.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/error.rs (renamed from vendor/clap/src/parser/error.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/features/mod.rs (renamed from vendor/clap/src/parser/features/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/features/suggestions.rs (renamed from vendor/clap/src/parser/features/suggestions.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/matches/any_value.rs (renamed from vendor/clap/src/parser/matches/any_value.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/matches/arg_matches.rs (renamed from vendor/clap/src/parser/matches/arg_matches.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/matches/matched_arg.rs (renamed from vendor/clap/src/parser/matches/matched_arg.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/matches/mod.rs (renamed from vendor/clap/src/parser/matches/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/matches/value_source.rs (renamed from vendor/clap/src/parser/matches/value_source.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/mod.rs (renamed from vendor/clap/src/parser/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/parser.rs (renamed from vendor/clap/src/parser/parser.rs)0
-rw-r--r--vendor/clap-3.2.20/src/parser/validator.rs (renamed from vendor/clap/src/parser/validator.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/color.rs (renamed from vendor/clap/src/util/color.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/fnv.rs (renamed from vendor/clap/src/util/fnv.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/graph.rs (renamed from vendor/clap/src/util/graph.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/id.rs (renamed from vendor/clap/src/util/id.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/mod.rs (renamed from vendor/clap/src/util/mod.rs)0
-rw-r--r--vendor/clap-3.2.20/src/util/str_to_bool.rs (renamed from vendor/clap/src/util/str_to_bool.rs)0
-rw-r--r--vendor/clap_lex-0.2.2/.cargo-checksum.json (renamed from vendor/clap_lex/.cargo-checksum.json)0
-rw-r--r--vendor/clap_lex-0.2.2/Cargo.toml (renamed from vendor/clap_lex/Cargo.toml)0
-rw-r--r--vendor/clap_lex-0.2.2/LICENSE-APACHE (renamed from vendor/clap_lex/LICENSE-APACHE)0
-rw-r--r--vendor/clap_lex-0.2.2/LICENSE-MIT (renamed from vendor/clap_lex/LICENSE-MIT)0
-rw-r--r--vendor/clap_lex-0.2.2/README.md (renamed from vendor/clap_lex/README.md)0
-rw-r--r--vendor/clap_lex-0.2.2/src/lib.rs (renamed from vendor/clap_lex/src/lib.rs)0
-rw-r--r--vendor/compiler_builtins/.cargo-checksum.json2
-rw-r--r--vendor/compiler_builtins/Cargo.lock2
-rw-r--r--vendor/compiler_builtins/Cargo.toml3
-rw-r--r--vendor/compiler_builtins/LICENSE.txt91
-rw-r--r--vendor/compiler_builtins/src/float/conv.rs6
-rw-r--r--vendor/compiler_builtins/src/float/div.rs6
-rw-r--r--vendor/compiler_builtins/src/int/specialized_div_rem/mod.rs5
-rw-r--r--vendor/compiler_builtins/src/macros.rs1
-rw-r--r--vendor/compiler_builtins/src/math.rs7
-rw-r--r--vendor/compiletest_rs/.cargo-checksum.json2
-rw-r--r--vendor/compiletest_rs/Cargo.toml2
-rw-r--r--vendor/compiletest_rs/README.md4
-rw-r--r--vendor/compiletest_rs/src/runtest.rs47
-rw-r--r--vendor/crossbeam-epoch/.cargo-checksum.json2
-rw-r--r--vendor/crossbeam-epoch/CHANGELOG.md5
-rw-r--r--vendor/crossbeam-epoch/Cargo.lock48
-rw-r--r--vendor/crossbeam-epoch/Cargo.toml7
-rw-r--r--vendor/crossbeam-epoch/no_atomic.rs6
-rw-r--r--vendor/crossbeam-epoch/src/default.rs34
-rw-r--r--vendor/crossbeam-epoch/src/lib.rs2
-rw-r--r--vendor/crossbeam-epoch/src/sync/mod.rs3
-rw-r--r--vendor/crossbeam-epoch/src/sync/once_lock.rs103
-rw-r--r--vendor/crossbeam-utils/.cargo-checksum.json2
-rw-r--r--vendor/crossbeam-utils/CHANGELOG.md5
-rw-r--r--vendor/crossbeam-utils/Cargo.toml8
-rw-r--r--vendor/crossbeam-utils/no_atomic.rs6
-rw-r--r--vendor/crossbeam-utils/src/cache_padded.rs6
-rw-r--r--vendor/crossbeam-utils/src/sync/mod.rs2
-rw-r--r--vendor/crossbeam-utils/src/sync/once_lock.rs103
-rw-r--r--vendor/crossbeam-utils/src/sync/sharded_lock.rs24
-rw-r--r--vendor/crossbeam-utils/src/sync/wait_group.rs5
-rw-r--r--vendor/dashmap/.cargo-checksum.json2
-rw-r--r--vendor/dashmap/Cargo.toml13
-rw-r--r--vendor/dashmap/src/lib.rs59
-rw-r--r--vendor/dashmap/src/rayon/map.rs4
-rw-r--r--vendor/dashmap/src/rayon/read_only.rs96
-rw-r--r--vendor/dashmap/src/read_only.rs2
-rw-r--r--vendor/dashmap/src/table.rs81
-rw-r--r--vendor/form_urlencoded/.cargo-checksum.json2
-rw-r--r--vendor/form_urlencoded/Cargo.toml18
-rw-r--r--vendor/form_urlencoded/src/lib.rs6
-rw-r--r--vendor/home/.cargo-checksum.json2
-rw-r--r--vendor/home/Cargo.toml26
-rw-r--r--vendor/home/src/env.rs106
-rw-r--r--vendor/home/src/lib.rs48
-rw-r--r--vendor/idna/.cargo-checksum.json2
-rw-r--r--vendor/idna/Cargo.toml23
-rw-r--r--vendor/idna/LICENSE-MIT2
-rw-r--r--vendor/idna/src/lib.rs3
-rw-r--r--vendor/idna/src/uts46.rs76
-rw-r--r--vendor/idna/tests/punycode.rs4
-rw-r--r--vendor/idna/tests/tests.rs12
-rw-r--r--vendor/idna/tests/uts46.rs13
-rw-r--r--vendor/itertools/.cargo-checksum.json2
-rw-r--r--vendor/itertools/CHANGELOG.md7
-rw-r--r--vendor/itertools/Cargo.lock726
-rw-r--r--vendor/itertools/Cargo.toml4
-rw-r--r--vendor/itertools/README.md2
-rw-r--r--vendor/itertools/benches/extra/zipslices.rs2
-rw-r--r--vendor/itertools/clippy.toml1
-rw-r--r--vendor/itertools/src/adaptors/coalesce.rs4
-rw-r--r--vendor/itertools/src/adaptors/mod.rs14
-rw-r--r--vendor/itertools/src/adaptors/multi_product.rs4
-rw-r--r--vendor/itertools/src/combinations_with_replacement.rs4
-rw-r--r--vendor/itertools/src/concat_impl.rs3
-rw-r--r--vendor/itertools/src/duplicates_impl.rs1
-rw-r--r--vendor/itertools/src/either_or_both.rs49
-rw-r--r--vendor/itertools/src/exactly_one_err.rs4
-rw-r--r--vendor/itertools/src/extrema_set.rs48
-rw-r--r--vendor/itertools/src/flatten_ok.rs33
-rw-r--r--vendor/itertools/src/free.rs26
-rw-r--r--vendor/itertools/src/groupbylazy.rs12
-rw-r--r--vendor/itertools/src/grouping_map.rs7
-rw-r--r--vendor/itertools/src/impl_macros.rs1
-rw-r--r--vendor/itertools/src/intersperse.rs5
-rw-r--r--vendor/itertools/src/kmerge_impl.rs8
-rw-r--r--vendor/itertools/src/lazy_buffer.rs20
-rw-r--r--vendor/itertools/src/lib.rs230
-rw-r--r--vendor/itertools/src/merge_join.rs4
-rw-r--r--vendor/itertools/src/multipeek_impl.rs10
-rw-r--r--vendor/itertools/src/pad_tail.rs2
-rw-r--r--vendor/itertools/src/peeking_take_while.rs2
-rw-r--r--vendor/itertools/src/permutations.rs7
-rw-r--r--vendor/itertools/src/rciter_impl.rs1
-rw-r--r--vendor/itertools/src/size_hint.rs16
-rw-r--r--vendor/itertools/src/tuple_impl.rs2
-rw-r--r--vendor/itertools/src/unique_impl.rs7
-rw-r--r--vendor/itertools/src/unziptuple.rs8
-rw-r--r--vendor/itertools/src/ziptuple.rs1
-rw-r--r--vendor/itertools/tests/adaptors_no_collect.rs11
-rw-r--r--vendor/itertools/tests/quick.rs116
-rw-r--r--vendor/itertools/tests/specializations.rs4
-rw-r--r--vendor/itertools/tests/test_core.rs15
-rw-r--r--vendor/itertools/tests/test_std.rs80
-rw-r--r--vendor/itertools/tests/zip.rs8
-rw-r--r--vendor/itoa/.cargo-checksum.json2
-rw-r--r--vendor/itoa/Cargo.toml6
-rw-r--r--vendor/itoa/src/lib.rs8
-rw-r--r--vendor/itoa/src/udiv128.rs5
-rw-r--r--vendor/libc/.cargo-checksum.json2
-rw-r--r--vendor/libc/Cargo.toml2
-rw-r--r--vendor/libc/src/fuchsia/mod.rs27
-rw-r--r--vendor/libc/src/unix/bsd/apple/mod.rs345
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs11
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs8
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs13
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs13
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs13
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs80
-rw-r--r--vendor/libc/src/unix/bsd/freebsdlike/mod.rs13
-rw-r--r--vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs37
-rw-r--r--vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs16
-rw-r--r--vendor/libc/src/unix/linux_like/android/mod.rs26
-rw-r--r--vendor/libc/src/unix/linux_like/emscripten/mod.rs4
-rw-r--r--vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs7
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/gnu/mod.rs22
-rw-r--r--vendor/libc/src/unix/linux_like/linux/mod.rs314
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs8
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs9
-rw-r--r--vendor/libc/src/unix/linux_like/linux/musl/mod.rs3
-rw-r--r--vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs1
-rw-r--r--vendor/libc/src/unix/linux_like/mod.rs2
-rw-r--r--vendor/libc/src/unix/newlib/mod.rs2
-rw-r--r--vendor/libc/src/unix/solarish/illumos.rs5
-rw-r--r--vendor/libc/src/unix/solarish/mod.rs16
-rw-r--r--vendor/libc/src/unix/solarish/solaris.rs11
-rw-r--r--vendor/libc/src/unix/solarish/x86_64.rs31
-rw-r--r--vendor/lock_api/.cargo-checksum.json2
-rw-r--r--vendor/lock_api/Cargo.toml2
-rw-r--r--vendor/lock_api/src/mutex.rs29
-rw-r--r--vendor/lock_api/src/remutex.rs8
-rw-r--r--vendor/lock_api/src/rwlock.rs10
-rw-r--r--vendor/matches/.cargo-checksum.json1
-rw-r--r--vendor/matches/Cargo.toml24
-rw-r--r--vendor/matches/lib.rs128
-rw-r--r--vendor/matches/tests/macro_use_one.rs11
-rw-r--r--vendor/matches/tests/use_star.rs10
-rw-r--r--vendor/miniz_oxide/.cargo-checksum.json2
-rw-r--r--vendor/miniz_oxide/Cargo.toml27
-rw-r--r--vendor/miniz_oxide/src/inflate/mod.rs12
-rw-r--r--vendor/once_cell/.cargo-checksum.json2
-rw-r--r--vendor/once_cell/CHANGELOG.md12
-rw-r--r--vendor/once_cell/Cargo.lock62
-rw-r--r--vendor/once_cell/Cargo.toml6
-rw-r--r--vendor/once_cell/examples/lazy_static.rs2
-rw-r--r--vendor/once_cell/src/lib.rs80
-rw-r--r--vendor/once_cell/tests/it.rs35
-rw-r--r--vendor/percent-encoding/.cargo-checksum.json2
-rw-r--r--vendor/percent-encoding/Cargo.toml21
-rw-r--r--vendor/percent-encoding/LICENSE-MIT2
-rw-r--r--vendor/percent-encoding/src/lib.rs (renamed from vendor/percent-encoding/lib.rs)74
-rw-r--r--vendor/proc-macro2/.cargo-checksum.json2
-rw-r--r--vendor/proc-macro2/Cargo.toml2
-rw-r--r--vendor/proc-macro2/build.rs5
-rw-r--r--vendor/proc-macro2/src/fallback.rs28
-rw-r--r--vendor/proc-macro2/src/lib.rs25
-rw-r--r--vendor/proc-macro2/src/parse.rs13
-rw-r--r--vendor/proc-macro2/src/wrapper.rs16
-rw-r--r--vendor/proc-macro2/tests/test.rs13
-rw-r--r--vendor/rowan/.cargo-checksum.json2
-rw-r--r--vendor/rowan/Cargo.lock10
-rw-r--r--vendor/rowan/Cargo.toml3
-rw-r--r--vendor/rowan/src/cursor.rs2
-rw-r--r--vendor/rustc_tools_util/.cargo-checksum.json1
-rw-r--r--vendor/rustc_tools_util/Cargo.toml32
-rw-r--r--vendor/rustc_tools_util/LICENSE-APACHE (renamed from vendor/xflags/LICENSE-APACHE)2
-rw-r--r--vendor/rustc_tools_util/LICENSE-MIT (renamed from vendor/matches/LICENSE)4
-rw-r--r--vendor/rustc_tools_util/README.md62
-rw-r--r--vendor/rustc_tools_util/src/lib.rs162
-rw-r--r--vendor/semver/.cargo-checksum.json2
-rw-r--r--vendor/semver/Cargo.toml2
-rw-r--r--vendor/semver/src/backport.rs9
-rw-r--r--vendor/semver/src/identifier.rs8
-rw-r--r--vendor/semver/src/lib.rs2
-rw-r--r--vendor/serde/.cargo-checksum.json2
-rw-r--r--vendor/serde/Cargo.toml5
-rw-r--r--vendor/serde/src/de/ignored_any.rs2
-rw-r--r--vendor/serde/src/de/impls.rs8
-rw-r--r--vendor/serde/src/de/mod.rs10
-rw-r--r--vendor/serde/src/de/value.rs37
-rw-r--r--vendor/serde/src/lib.rs17
-rw-r--r--vendor/serde/src/private/de.rs11
-rw-r--r--vendor/serde/src/private/ser.rs6
-rw-r--r--vendor/serde/src/ser/impls.rs15
-rw-r--r--vendor/serde_derive/.cargo-checksum.json2
-rw-r--r--vendor/serde_derive/Cargo.toml3
-rw-r--r--vendor/serde_derive/src/lib.rs2
-rw-r--r--vendor/serde_json/.cargo-checksum.json2
-rw-r--r--vendor/serde_json/Cargo.toml2
-rw-r--r--vendor/serde_json/src/lib.rs2
-rw-r--r--vendor/serde_json/src/number.rs13
-rw-r--r--vendor/serde_json/src/value/ser.rs10
-rw-r--r--vendor/serde_json/tests/test.rs6
-rw-r--r--vendor/smallvec/.cargo-checksum.json2
-rw-r--r--vendor/smallvec/Cargo.toml31
-rw-r--r--vendor/smallvec/debug_metadata/README.md111
-rw-r--r--vendor/smallvec/debug_metadata/smallvec.natvis35
-rw-r--r--vendor/smallvec/scripts/run_miri.sh3
-rw-r--r--vendor/smallvec/src/lib.rs7
-rw-r--r--vendor/smallvec/tests/debugger_visualizer.rs68
-rw-r--r--vendor/syn/.cargo-checksum.json2
-rw-r--r--vendor/syn/Cargo.toml4
-rw-r--r--vendor/syn/benches/file.rs2
-rw-r--r--vendor/syn/benches/rust.rs11
-rw-r--r--vendor/syn/src/buffer.rs215
-rw-r--r--vendor/syn/src/expr.rs21
-rw-r--r--vendor/syn/src/gen/clone.rs2
-rw-r--r--vendor/syn/src/gen/debug.rs10
-rw-r--r--vendor/syn/src/gen/eq.rs6
-rw-r--r--vendor/syn/src/gen/fold.rs6
-rw-r--r--vendor/syn/src/gen/hash.rs6
-rw-r--r--vendor/syn/src/gen/visit.rs6
-rw-r--r--vendor/syn/src/gen/visit_mut.rs6
-rw-r--r--vendor/syn/src/item.rs14
-rw-r--r--vendor/syn/src/lib.rs11
-rw-r--r--vendor/syn/src/lit.rs2
-rw-r--r--vendor/syn/src/parse_macro_input.rs4
-rw-r--r--vendor/syn/src/pat.rs35
-rw-r--r--vendor/syn/src/path.rs46
-rw-r--r--vendor/syn/src/stmt.rs6
-rw-r--r--vendor/syn/src/ty.rs53
-rw-r--r--vendor/syn/tests/.gitignore1
-rw-r--r--vendor/syn/tests/common/eq.rs64
-rw-r--r--vendor/syn/tests/debug/gen.rs12
-rw-r--r--vendor/syn/tests/regression/issue1108.rs2
-rw-r--r--vendor/syn/tests/repo/mod.rs77
-rw-r--r--vendor/syn/tests/test_parse_stream.rs8
-rw-r--r--vendor/syn/tests/test_precedence.rs19
-rw-r--r--vendor/syn/tests/test_size.rs8
-rw-r--r--vendor/thiserror-impl/.cargo-checksum.json2
-rw-r--r--vendor/thiserror-impl/Cargo.toml2
-rw-r--r--vendor/thiserror-impl/src/expand.rs18
-rw-r--r--vendor/thiserror/.cargo-checksum.json2
-rw-r--r--vendor/thiserror/Cargo.toml6
-rw-r--r--vendor/thiserror/README.md30
-rw-r--r--vendor/thiserror/build.rs66
-rw-r--r--vendor/thiserror/src/aserror.rs9
-rw-r--r--vendor/thiserror/src/lib.rs39
-rw-r--r--vendor/thiserror/src/provide.rs15
-rw-r--r--vendor/thiserror/tests/test_backtrace.rs46
-rw-r--r--vendor/thiserror/tests/test_deprecated.rs10
-rw-r--r--vendor/thiserror/tests/ui/source-enum-not-error.stderr6
-rw-r--r--vendor/thiserror/tests/ui/source-struct-not-error.stderr4
-rw-r--r--vendor/tracing-attributes/.cargo-checksum.json2
-rw-r--r--vendor/tracing-attributes/CHANGELOG.md21
-rw-r--r--vendor/tracing-attributes/Cargo.toml18
-rw-r--r--vendor/tracing-attributes/README.md4
-rw-r--r--vendor/tracing-attributes/src/expand.rs118
-rw-r--r--vendor/tracing-attributes/src/lib.rs60
-rw-r--r--vendor/tracing-attributes/tests/async_fn.rs13
-rw-r--r--vendor/tracing-attributes/tests/instrument.rs9
-rw-r--r--vendor/tracing-attributes/tests/ui.rs7
-rw-r--r--vendor/tracing-attributes/tests/ui/async_instrument.rs46
-rw-r--r--vendor/tracing-attributes/tests/ui/async_instrument.stderr98
-rw-r--r--vendor/tracing-core/.cargo-checksum.json2
-rw-r--r--vendor/tracing-core/CHANGELOG.md18
-rw-r--r--vendor/tracing-core/Cargo.toml2
-rw-r--r--vendor/tracing-core/README.md26
-rw-r--r--vendor/tracing-core/src/callsite.rs1
-rw-r--r--vendor/tracing-core/src/dispatcher.rs113
-rw-r--r--vendor/tracing-core/src/subscriber.rs27
-rw-r--r--vendor/tracing-subscriber-0.3.3/.cargo-checksum.json1
-rw-r--r--vendor/tracing-subscriber-0.3.3/CHANGELOG.md (renamed from vendor/tracing-subscriber/CHANGELOG.md)323
-rw-r--r--vendor/tracing-subscriber-0.3.3/Cargo.toml (renamed from vendor/tracing-subscriber/Cargo.toml)138
-rw-r--r--vendor/tracing-subscriber-0.3.3/LICENSE (renamed from vendor/tracing-subscriber/LICENSE)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/README.md (renamed from vendor/tracing-subscriber/README.md)6
-rw-r--r--vendor/tracing-subscriber-0.3.3/benches/enter.rs (renamed from vendor/tracing-subscriber/benches/enter.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/benches/filter.rs (renamed from vendor/tracing-subscriber/benches/filter.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/benches/filter_log.rs (renamed from vendor/tracing-subscriber/benches/filter_log.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/benches/fmt.rs (renamed from vendor/tracing-subscriber/benches/fmt.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/benches/support/mod.rs (renamed from vendor/tracing-subscriber/benches/support/mod.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/field/debug.rs (renamed from vendor/tracing-subscriber/src/field/debug.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/field/delimited.rs (renamed from vendor/tracing-subscriber/src/field/delimited.rs)4
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/field/display.rs (renamed from vendor/tracing-subscriber/src/field/display.rs)2
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/field/mod.rs (renamed from vendor/tracing-subscriber/src/field/mod.rs)14
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/directive.rs (renamed from vendor/tracing-subscriber/src/filter/directive.rs)34
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs (renamed from vendor/tracing-subscriber/src/filter/env/directive.rs)160
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs (renamed from vendor/tracing-subscriber/src/filter/env/field.rs)250
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs (renamed from vendor/tracing-subscriber/src/filter/env/mod.rs)677
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs (renamed from vendor/tracing-subscriber/src/filter/filter_fn.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs (renamed from vendor/tracing-subscriber/src/filter/layer_filters/mod.rs)367
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/level.rs (renamed from vendor/tracing-subscriber/src/filter/level.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/mod.rs (renamed from vendor/tracing-subscriber/src/filter/mod.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/filter/targets.rs (renamed from vendor/tracing-subscriber/src/filter/targets.rs)33
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs (renamed from vendor/tracing-subscriber/src/fmt/fmt_layer.rs)215
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs (renamed from vendor/tracing-subscriber/src/fmt/format/json.rs)175
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs (renamed from vendor/tracing-subscriber/src/fmt/format/mod.rs)443
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs (renamed from vendor/tracing-subscriber/src/fmt/format/pretty.rs)156
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs (renamed from vendor/tracing-subscriber/src/fmt/mod.rs)359
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs (renamed from vendor/tracing-subscriber/src/fmt/time/datetime.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs (renamed from vendor/tracing-subscriber/src/fmt/time/mod.rs)8
-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/fmt/writer.rs (renamed from vendor/tracing-subscriber/src/fmt/writer.rs)28
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/layer/context.rs (renamed from vendor/tracing-subscriber/src/layer/context.rs)22
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/layer/layered.rs (renamed from vendor/tracing-subscriber/src/layer/layered.rs)57
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/layer/mod.rs (renamed from vendor/tracing-subscriber/src/layer/mod.rs)725
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/layer/tests.rs (renamed from vendor/tracing-subscriber/src/layer/tests.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/lib.rs (renamed from vendor/tracing-subscriber/src/lib.rs)54
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/macros.rs (renamed from vendor/tracing-subscriber/src/macros.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/prelude.rs (renamed from vendor/tracing-subscriber/src/prelude.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs (renamed from vendor/tracing-subscriber/src/registry/extensions.rs)2
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/registry/mod.rs (renamed from vendor/tracing-subscriber/src/registry/mod.rs)20
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs (renamed from vendor/tracing-subscriber/src/registry/sharded.rs)27
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/registry/stack.rs (renamed from vendor/tracing-subscriber/src/registry/stack.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/reload.rs (renamed from vendor/tracing-subscriber/src/reload.rs)171
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/sync.rs (renamed from vendor/tracing-subscriber/src/sync.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/src/util.rs (renamed from vendor/tracing-subscriber/src/util.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs (renamed from vendor/tracing-subscriber/tests/duplicate_spans.rs)1
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/field_filter.rs (renamed from vendor/tracing-subscriber/tests/field_filter.rs)4
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/filter.rs187
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/filter_log.rs (renamed from vendor/tracing-subscriber/tests/filter_log.rs)4
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs (renamed from vendor/tracing-subscriber/tests/fmt_max_level_hint.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs (renamed from vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/boxed.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/main.rs)3
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/targets.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs (renamed from vendor/tracing-subscriber/tests/layer_filters/trees.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs (renamed from vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs (renamed from vendor/tracing-subscriber/tests/registry_max_level_hint.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs (renamed from vendor/tracing-subscriber/tests/registry_with_subscriber.rs)2
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/reload.rs81
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs (renamed from vendor/tracing-subscriber/tests/same_len_filters.rs)4
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/support.rs (renamed from vendor/tracing-subscriber/tests/support.rs)19
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs (renamed from vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs)0
-rw-r--r--vendor/tracing-subscriber-0.3.3/tests/utils.rs (renamed from vendor/tracing-subscriber/tests/utils.rs)4
-rw-r--r--vendor/tracing-subscriber/.cargo-checksum.json1
-rw-r--r--vendor/tracing-subscriber/src/filter/env/builder.rs324
-rw-r--r--vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs469
-rw-r--r--vendor/tracing-subscriber/src/fmt/time/time_crate.rs470
-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/layer_filters/combinators.rs42
-rw-r--r--vendor/tracing-subscriber/tests/layer_filters/vec.rs120
-rw-r--r--vendor/tracing-subscriber/tests/option.rs41
-rw-r--r--vendor/tracing-subscriber/tests/reload.rs155
-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/.cargo-checksum.json2
-rw-r--r--vendor/tracing/CHANGELOG.md52
-rw-r--r--vendor/tracing/Cargo.toml6
-rw-r--r--vendor/tracing/README.md4
-rw-r--r--vendor/tracing/src/dispatcher.rs2
-rw-r--r--vendor/tracing/src/lib.rs10
-rw-r--r--vendor/tracing/src/macros.rs38
-rw-r--r--vendor/unicode-ident/.cargo-checksum.json2
-rw-r--r--vendor/unicode-ident/Cargo.toml18
-rw-r--r--vendor/unicode-ident/LICENSE-UNICODE46
-rw-r--r--vendor/unicode-ident/README.md30
-rw-r--r--vendor/unicode-ident/src/tables.rs111
-rw-r--r--vendor/unicode-ident/tests/fst/xid_continue.fstbin70255 -> 72750 bytes
-rw-r--r--vendor/unicode-ident/tests/fst/xid_start.fstbin62642 -> 64999 bytes
-rw-r--r--vendor/unicode-ident/tests/static_size.rs8
-rw-r--r--vendor/unicode-ident/tests/trie/trie.rs222
-rw-r--r--vendor/unicode-normalization/.cargo-checksum.json2
-rw-r--r--vendor/unicode-normalization/Cargo.toml2
-rw-r--r--vendor/unicode-normalization/README.md2
-rw-r--r--vendor/unicode-normalization/scripts/unicode.py2
-rw-r--r--vendor/unicode-normalization/src/tables.rs16653
-rw-r--r--vendor/unicode-script/.cargo-checksum.json2
-rw-r--r--vendor/unicode-script/Cargo.toml36
-rw-r--r--vendor/unicode-script/LICENSE-APACHE201
-rw-r--r--vendor/unicode-script/LICENSE-MIT (renamed from vendor/xflags/LICENSE-MIT)50
-rw-r--r--vendor/unicode-script/README.md4
-rw-r--r--vendor/unicode-script/scripts/unicode.py4
-rw-r--r--vendor/unicode-script/src/lib.rs10
-rw-r--r--vendor/unicode-script/src/tables.rs2275
-rw-r--r--vendor/unicode-security/.cargo-checksum.json2
-rw-r--r--vendor/unicode-security/Cargo.toml39
-rw-r--r--vendor/unicode-security/README.md4
-rw-r--r--vendor/unicode-security/scripts/unicode.py6
-rw-r--r--vendor/unicode-security/src/restriction_level.rs2
-rw-r--r--vendor/unicode-security/src/tables.rs2118
-rw-r--r--vendor/unicode-segmentation/.cargo-checksum.json2
-rw-r--r--vendor/unicode-segmentation/Cargo.toml29
-rwxr-xr-xvendor/unicode-segmentation/scripts/unicode.py2
-rw-r--r--vendor/unicode-segmentation/src/tables.rs2372
-rw-r--r--vendor/unicode-segmentation/src/testdata.rs6
-rw-r--r--vendor/unicode-width/.cargo-checksum.json2
-rw-r--r--vendor/unicode-width/Cargo.toml30
-rwxr-xr-xvendor/unicode-width/scripts/unicode.py748
-rw-r--r--vendor/unicode-width/src/tables.rs775
-rw-r--r--vendor/unicode-width/src/tests.rs20
-rw-r--r--vendor/unicode-xid/.cargo-checksum.json2
-rw-r--r--vendor/unicode-xid/Cargo.toml2
-rw-r--r--vendor/unicode-xid/README.md9
-rw-r--r--vendor/unicode-xid/src/tables.rs45
-rw-r--r--vendor/url/.cargo-checksum.json2
-rw-r--r--vendor/url/Cargo.toml63
-rw-r--r--vendor/url/LICENSE-MIT2
-rw-r--r--vendor/url/README.md14
-rw-r--r--vendor/url/src/host.rs86
-rw-r--r--vendor/url/src/lib.rs82
-rw-r--r--vendor/url/src/origin.rs3
-rw-r--r--vendor/url/src/parser.rs37
-rw-r--r--vendor/url/src/quirks.rs59
-rw-r--r--vendor/url/tests/data.rs79
-rw-r--r--vendor/url/tests/debugger_visualizer.rs102
-rw-r--r--vendor/url/tests/unit.rs54
-rw-r--r--vendor/url/tests/urltestdata.json1625
-rw-r--r--vendor/xflags-macros/.cargo-checksum.json2
-rw-r--r--vendor/xflags-macros/Cargo.toml6
-rw-r--r--vendor/xflags-macros/src/ast.rs13
-rw-r--r--vendor/xflags-macros/src/emit.rs350
-rw-r--r--vendor/xflags-macros/src/lib.rs26
-rw-r--r--vendor/xflags-macros/src/parse.rs166
-rw-r--r--vendor/xflags-macros/src/update.rs3
-rw-r--r--vendor/xflags-macros/tests/data/help.rs (renamed from vendor/xflags-macros/tests/it/src/help.rs)5
-rw-r--r--vendor/xflags-macros/tests/data/repeated_pos.rs (renamed from vendor/xflags-macros/tests/it/src/repeated_pos.rs)3
-rw-r--r--vendor/xflags-macros/tests/data/smoke.rs (renamed from vendor/xflags-macros/tests/it/src/smoke.rs)3
-rw-r--r--vendor/xflags-macros/tests/data/subcommands.rs (renamed from vendor/xflags-macros/tests/it/src/subcommands.rs)3
-rw-r--r--vendor/xflags-macros/tests/it/help.rs84
-rw-r--r--vendor/xflags-macros/tests/it/main.rs36
-rw-r--r--vendor/xflags-macros/tests/it/repeated_pos.rs64
-rw-r--r--vendor/xflags-macros/tests/it/smoke.rs61
-rw-r--r--vendor/xflags-macros/tests/it/subcommands.rs174
-rw-r--r--vendor/xflags/.cargo-checksum.json2
-rw-r--r--vendor/xflags/Cargo.lock6
-rw-r--r--vendor/xflags/Cargo.toml9
-rw-r--r--vendor/xflags/README.md49
-rw-r--r--vendor/xflags/examples/hello-generated.rs13
-rw-r--r--vendor/xflags/examples/hello.rs3
-rw-r--r--vendor/xflags/examples/immediate-mode.rs16
-rw-r--r--vendor/xflags/examples/longer.rs7
-rw-r--r--vendor/xflags/examples/non-utf8.rs3
-rw-r--r--vendor/xflags/src/lib.rs172
-rw-r--r--vendor/xflags/src/rt.rs14
-rw-r--r--version2
5777 files changed, 132160 insertions, 90593 deletions
diff --git a/COPYRIGHT b/COPYRIGHT
index dc9abf84b..11335879b 100644
--- a/COPYRIGHT
+++ b/COPYRIGHT
@@ -23,65 +23,251 @@ The Rust Project includes packages written by third parties.
The following third party packages are included, and carry
their own copyright notices and license terms:
-* LLVM. Code for this package is found in src/llvm-project.
-
- Copyright (c) 2003-2013 University of Illinois at
- Urbana-Champaign. All rights reserved.
-
- Developed by:
-
- LLVM Team
-
- University of Illinois at Urbana-Champaign
-
- http://llvm.org
-
- Permission is hereby granted, free of charge, to any
- person obtaining a copy of this software and associated
- documentation files (the "Software"), to deal with 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:
-
- * Redistributions of source code must retain the
- above copyright notice, this list of conditions
- and the following disclaimers.
-
- * Redistributions in binary form must reproduce the
- above copyright notice, this list of conditions
- and the following disclaimers in the documentation
- and/or other materials provided with the
- distribution.
-
- * Neither the names of the LLVM Team, University of
- Illinois at Urbana-Champaign, nor the names of its
- contributors may be used to endorse or promote
- products derived from this Software without
- specific prior written permission.
-
- 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
-
-* Additional libraries included in LLVM carry separate
- BSD-compatible licenses. See src/llvm-project/llvm/LICENSE.TXT
- for details.
-
-* compiler-rt, in src/compiler-rt is dual licensed under
- LLVM's license and MIT:
-
- Copyright (c) 2009-2014 by the contributors listed in
- CREDITS.TXT
-
+* LLVM, located in src/llvm-project, is licensed under the following
+ terms.
+
+ ==============================================================================
+ The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+ ==============================================================================
+
+ 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.
+
+
+ ---- LLVM Exceptions to the Apache 2.0 License ----
+
+ As an exception, if, as a result of your compiling your source code, portions
+ of this Software are embedded into an Object form of such source code, you
+ may redistribute such embedded portions in such Object form without complying
+ with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+ In addition, if you combine or link compiled forms of this Software with
+ software that is licensed under the GPLv2 ("Combined Software") and if a
+ court of competent jurisdiction determines that the patent provision (Section
+ 3), the indemnity provision (Section 9) or other Section of the License
+ conflicts with the conditions of the GPLv2, you may retroactively and
+ prospectively choose to deem waived or otherwise exclude such Section(s) of
+ the License, but only in their entirety and only with respect to the Combined
+ Software.
+
+ ==============================================================================
+ Software from third parties included in the LLVM Project:
+ ==============================================================================
+ The LLVM Project contains third party software which is under different license
+ terms. All such code will be identified clearly using at least one of two
+ mechanisms:
+ 1) It will be in a separate directory tree with its own `LICENSE.txt` or
+ `LICENSE` file at the top containing the specific license and restrictions
+ which apply to that software, or
+ 2) It will contain specific license and restriction terms at the top of every
+ file.
+
+ ==============================================================================
+ Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
+ ==============================================================================
+ University of Illinois/NCSA
+ Open Source License
+
+ Copyright (c) 2003-2019 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
@@ -92,70 +278,32 @@ their own copyright notices and license terms:
http://llvm.org
- Permission is hereby granted, free of charge, to any
- person obtaining a copy of this software and associated
- documentation files (the "Software"), to deal with 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:
-
- * Redistributions of source code must retain the
- above copyright notice, this list of conditions
- and the following disclaimers.
-
- * Redistributions in binary form must reproduce the
- above copyright notice, this list of conditions
- and the following disclaimers in the documentation
- and/or other materials provided with the
- distribution.
-
- * Neither the names of the LLVM Team, University of
- Illinois at Urbana-Champaign, nor the names of its
- contributors may be used to endorse or promote
- products derived from this Software without
- specific prior written permission.
-
- 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 CONTRIBUTORS 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 WITH THE SOFTWARE.
-
- ========================================================
-
- Copyright (c) 2009-2014 by the contributors listed in
- CREDITS.TXT
-
- 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.
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the "Software"), to deal with
+ 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:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+ 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
+ CONTRIBUTORS 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 WITH THE
+ SOFTWARE.
* Portions of the FFI code for interacting with the native ABI
is derived from the Clay programming language, which carries
@@ -191,41 +339,3 @@ their own copyright notices and license terms:
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
-
-* libbacktrace, under src/libbacktrace:
-
- Copyright (C) 2012-2014 Free Software Foundation, Inc.
- Written by Ian Lance Taylor, Google.
-
- Redistribution and use in source and binary forms, with
- or without modification, are permitted provided that the
- following conditions are met:
-
- (1) Redistributions of source code must retain the
- above copyright notice, this list of conditions and
- the following disclaimer.
-
- (2) Redistributions in binary form must reproduce
- the above copyright notice, this list of conditions
- and the following disclaimer in the documentation
- and/or other materials provided with the
- distribution.
-
- (3) The name of the author may not be used to
- endorse or promote products derived from this
- software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- OF SUCH DAMAGE. */
diff --git a/Cargo.lock b/Cargo.lock
index fda523611..dab693419 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -288,7 +288,7 @@ dependencies = [
[[package]]
name = "cargo"
-version = "0.66.0"
+version = "0.67.0"
dependencies = [
"anyhow",
"atty",
@@ -297,7 +297,7 @@ dependencies = [
"cargo-test-macro",
"cargo-test-support",
"cargo-util",
- "clap",
+ "clap 4.0.15",
"crates-io",
"curl",
"curl-sys",
@@ -330,8 +330,10 @@ dependencies = [
"pretty_env_logger",
"rustc-workspace-hack",
"rustfix",
+ "same-file",
"semver",
"serde",
+ "serde-value",
"serde_ignored",
"serde_json",
"shell-escape",
@@ -383,11 +385,12 @@ version = "0.1.0"
dependencies = [
"cargo_metadata 0.15.0",
"directories",
+ "rustc-build-sysroot",
"rustc-workspace-hack",
+ "rustc_tools_util",
"rustc_version",
"serde",
"serde_json",
- "vergen",
]
[[package]]
@@ -417,6 +420,7 @@ dependencies = [
"anyhow",
"cargo-test-macro",
"cargo-util",
+ "crates-io",
"filetime",
"flate2",
"git2",
@@ -507,6 +511,10 @@ name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-core",
+]
[[package]]
name = "chalk-derive"
@@ -584,7 +592,7 @@ dependencies = [
"atty",
"bitflags",
"clap_derive",
- "clap_lex",
+ "clap_lex 0.2.2",
"indexmap",
"once_cell",
"strsim",
@@ -593,12 +601,25 @@ dependencies = [
]
[[package]]
+name = "clap"
+version = "4.0.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f"
+dependencies = [
+ "atty",
+ "bitflags",
+ "clap_lex 0.3.0",
+ "strsim",
+ "termcolor",
+]
+
+[[package]]
name = "clap_complete"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df6f3613c0a3cddfd78b41b10203eb322cb29b600cbdf808a7d3db95691b8e25"
dependencies = [
- "clap",
+ "clap 3.2.20",
]
[[package]]
@@ -624,8 +645,17 @@ dependencies = [
]
[[package]]
+name = "clap_lex"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
+dependencies = [
+ "os_str_bytes",
+]
+
+[[package]]
name = "clippy"
-version = "0.1.65"
+version = "0.1.66"
dependencies = [
"clippy_lints",
"clippy_utils",
@@ -657,7 +687,7 @@ name = "clippy_dev"
version = "0.0.1"
dependencies = [
"aho-corasick",
- "clap",
+ "clap 3.2.20",
"indoc",
"itertools",
"opener",
@@ -668,7 +698,7 @@ dependencies = [
[[package]]
name = "clippy_lints"
-version = "0.1.65"
+version = "0.1.66"
dependencies = [
"cargo_metadata 0.14.0",
"clippy_utils",
@@ -690,7 +720,7 @@ dependencies = [
[[package]]
name = "clippy_utils"
-version = "0.1.65"
+version = "0.1.66"
dependencies = [
"arrayvec",
"if_chain",
@@ -766,9 +796,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
-version = "0.1.79"
+version = "0.1.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"
+checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
dependencies = [
"cc",
"rustc-std-workspace-core",
@@ -799,9 +829,9 @@ dependencies = [
[[package]]
name = "compiletest_rs"
-version = "0.8.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "262134ef87408da1ddfe45e33daa0ca43b75286d6b1076446e602d264cf9847e"
+checksum = "70489bbb718aea4f92e5f48f2e3b5be670c2051de30e57cb6e5377b4aa08b372"
dependencies = [
"diff",
"filetime",
@@ -1075,9 +1105,9 @@ dependencies = [
[[package]]
name = "directories"
-version = "3.0.2"
+version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7"
+checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
dependencies = [
"dirs-sys",
]
@@ -1168,26 +1198,6 @@ dependencies = [
]
[[package]]
-name = "enum-iterator"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
-dependencies = [
- "enum-iterator-derive",
-]
-
-[[package]]
-name = "enum-iterator-derive"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1525,18 +1535,6 @@ dependencies = [
]
[[package]]
-name = "getset"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
-dependencies = [
- "proc-macro-error",
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "gimli"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1802,7 +1800,7 @@ name = "installer"
version = "0.0.0"
dependencies = [
"anyhow",
- "clap",
+ "clap 3.2.20",
"flate2",
"lazy_static",
"num_cpus",
@@ -1845,9 +1843,9 @@ dependencies = [
[[package]]
name = "itertools"
-version = "0.10.1"
+version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
@@ -1937,9 +1935,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.131"
+version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
dependencies = [
"rustc-std-workspace-core",
]
@@ -2145,7 +2143,7 @@ dependencies = [
"ammonia",
"anyhow",
"chrono",
- "clap",
+ "clap 3.2.20",
"clap_complete",
"elasticlunr-rs",
"env_logger 0.9.0",
@@ -2264,6 +2262,7 @@ dependencies = [
"rand 0.8.5",
"regex",
"rustc-workspace-hack",
+ "rustc_version",
"shell-escape",
"smallvec",
"ui_test",
@@ -2415,6 +2414,15 @@ dependencies = [
]
[[package]]
+name = "ordered-float"
+version = "2.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
name = "os_info"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2645,9 +2653,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.18"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
+checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "polonius-engine"
@@ -2714,11 +2722,11 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
-version = "1.0.37"
+version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
+checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
- "unicode-xid",
+ "unicode-ident",
]
[[package]]
@@ -3008,12 +3016,23 @@ dependencies = [
name = "rustbook"
version = "0.1.0"
dependencies = [
- "clap",
+ "clap 3.2.20",
"env_logger 0.7.1",
"mdbook",
]
[[package]]
+name = "rustc-build-sysroot"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92"
+dependencies = [
+ "anyhow",
+ "rustc_version",
+ "tempfile",
+]
+
+[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3095,7 +3114,7 @@ name = "rustc-workspace-hack"
version = "1.0.0"
dependencies = [
"bstr",
- "clap",
+ "clap 3.2.20",
"libz-sys",
"regex",
"serde_json",
@@ -3259,7 +3278,6 @@ dependencies = [
"bitflags",
"cstr",
"libc",
- "libloading",
"measureme",
"object 0.29.0",
"rustc-demangle",
@@ -3282,6 +3300,7 @@ dependencies = [
"rustc_symbol_mangling",
"rustc_target",
"smallvec",
+ "tempfile",
"tracing",
]
@@ -3391,6 +3410,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_hir",
+ "rustc_hir_analysis",
"rustc_hir_pretty",
"rustc_interface",
"rustc_lint",
@@ -3404,7 +3424,6 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
- "rustc_typeck",
"serde_json",
"tracing",
"winapi",
@@ -3435,6 +3454,8 @@ version = "0.0.0"
dependencies = [
"annotate-snippets",
"atty",
+ "rustc_ast",
+ "rustc_ast_pretty",
"rustc_data_structures",
"rustc_error_messages",
"rustc_hir",
@@ -3510,6 +3531,34 @@ dependencies = [
]
[[package]]
+name = "rustc_hir_analysis"
+version = "0.0.0"
+dependencies = [
+ "rustc_arena",
+ "rustc_ast",
+ "rustc_attr",
+ "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",
+ "tracing",
+]
+
+[[package]]
name = "rustc_hir_pretty"
version = "0.0.0"
dependencies = [
@@ -3521,6 +3570,32 @@ dependencies = [
]
[[package]]
+name = "rustc_hir_typeck"
+version = "0.1.0"
+dependencies = [
+ "rustc_ast",
+ "rustc_data_structures",
+ "rustc_errors",
+ "rustc_graphviz",
+ "rustc_hir",
+ "rustc_hir_analysis",
+ "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",
+ "tracing",
+]
+
+[[package]]
name = "rustc_incremental"
version = "0.0.0"
dependencies = [
@@ -3588,6 +3663,8 @@ dependencies = [
"rustc_errors",
"rustc_expand",
"rustc_hir",
+ "rustc_hir_analysis",
+ "rustc_hir_typeck",
"rustc_incremental",
"rustc_lint",
"rustc_macros",
@@ -3610,7 +3687,6 @@ dependencies = [
"rustc_trait_selection",
"rustc_traits",
"rustc_ty_utils",
- "rustc_typeck",
"smallvec",
"tracing",
"winapi",
@@ -3735,8 +3811,6 @@ dependencies = [
"either",
"gsgdt",
"polonius-engine",
- "rand 0.8.5",
- "rand_xoshiro",
"rustc-rayon",
"rustc-rayon-core",
"rustc_apfloat",
@@ -3920,12 +3994,12 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
+ "rustc_hir_analysis",
"rustc_macros",
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_trait_selection",
- "rustc_typeck",
"tracing",
]
@@ -4106,6 +4180,7 @@ version = "0.0.0"
dependencies = [
"bitflags",
"rustc_data_structures",
+ "rustc_feature",
"rustc_index",
"rustc_macros",
"rustc_serialize",
@@ -4116,7 +4191,9 @@ dependencies = [
[[package]]
name = "rustc_tools_util"
-version = "0.2.0"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"
[[package]]
name = "rustc_trait_selection"
@@ -4181,6 +4258,8 @@ dependencies = [
name = "rustc_ty_utils"
version = "0.0.0"
dependencies = [
+ "rand 0.8.5",
+ "rand_xoshiro",
"rustc_data_structures",
"rustc_errors",
"rustc_hir",
@@ -4209,35 +4288,6 @@ dependencies = [
]
[[package]]
-name = "rustc_typeck"
-version = "0.0.0"
-dependencies = [
- "rustc_arena",
- "rustc_ast",
- "rustc_attr",
- "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_ty_utils",
- "rustc_type_ir",
- "smallvec",
- "tracing",
-]
-
-[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4320,7 +4370,7 @@ dependencies = [
"anyhow",
"bytecount",
"cargo_metadata 0.14.0",
- "clap",
+ "clap 3.2.20",
"derive-new",
"diff",
"dirs",
@@ -4426,18 +4476,28 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.143"
+version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
dependencies = [
"serde_derive",
]
[[package]]
+name = "serde-value"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
+dependencies = [
+ "ordered-float",
+ "serde",
+]
+
+[[package]]
name = "serde_derive"
-version = "1.0.143"
+version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
+checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
dependencies = [
"proc-macro2",
"quote",
@@ -4613,7 +4673,7 @@ version = "0.0.0"
dependencies = [
"addr2line 0.16.0",
"alloc",
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"compiler_builtins",
"core",
"dlmalloc",
@@ -4637,7 +4697,7 @@ dependencies = [
name = "std_detect"
version = "0.1.5"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
"compiler_builtins",
"libc",
"rustc-std-workspace-alloc",
@@ -4687,13 +4747,13 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
-version = "1.0.91"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
- "unicode-xid",
+ "unicode-ident",
]
[[package]]
@@ -4886,9 +4946,18 @@ checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
[[package]]
name = "tinyvec"
-version = "0.3.4"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
@@ -4912,16 +4981,26 @@ dependencies = [
]
[[package]]
+name = "toml_datetime"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808b51e57d0ef8f71115d8f3a01e7d3750d01c79cac4b3eda910f4389fdf92fd"
+dependencies = [
+ "serde",
+]
+
+[[package]]
name = "toml_edit"
-version = "0.14.3"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba98375fd631b83696f87c64e4ed8e29e6a1f3404d6aed95fa95163bad38e705"
+checksum = "b1541ba70885967e662f69d31ab3aeca7b1aaecfcd58679590b893e9239c3646"
dependencies = [
"combine",
"indexmap",
"itertools",
"kstring",
"serde",
+ "toml_datetime",
]
[[package]]
@@ -5175,25 +5254,31 @@ dependencies = [
]
[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
name = "unicode-normalization"
-version = "0.1.13"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-script"
-version = "0.5.3"
+version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9"
+checksum = "7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc"
[[package]]
name = "unicode-security"
-version = "0.0.5"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d87c28edc5b263377e448d6cdcb935c06b95413d8013ba6fae470558ccab18f"
+checksum = "9ef5756b3097992b934b06608c69f48448a0fbe804bb1e72b982f6d7983e9e63"
dependencies = [
"unicode-normalization",
"unicode-script",
@@ -5201,15 +5286,15 @@ dependencies = [
[[package]]
name = "unicode-segmentation"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]]
name = "unicode-width"
-version = "0.1.8"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@@ -5218,9 +5303,9 @@ dependencies = [
[[package]]
name = "unicode-xid"
-version = "0.2.2"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "unicode_categories"
@@ -5294,21 +5379,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c"
[[package]]
-name = "vergen"
-version = "5.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbc87f9a7a9d61b15d51d1d3547284f67b6b4f1494ce3fc5814c101f35a5183"
-dependencies = [
- "anyhow",
- "chrono",
- "enum-iterator",
- "getset",
- "git2",
- "rustversion",
- "thiserror",
-]
-
-[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/RELEASES.md b/RELEASES.md
index a3df56f1d..5b4d6ccd9 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,94 @@
+Version 1.66.0 (2022-12-15)
+==========================
+
+Language
+--------
+- [Permit specifying explicit discriminants on all `repr(Int)` enums](https://github.com/rust-lang/rust/pull/95710/)
+ ```rust
+ #[repr(u8)]
+ enum Foo {
+ A(u8) = 0,
+ B(i8) = 1,
+ C(bool) = 42,
+ }
+ ```
+- [Allow transmutes between the same type differing only in lifetimes](https://github.com/rust-lang/rust/pull/101520/)
+- [Change constant evaluation errors from a deny-by-default lint to a hard error](https://github.com/rust-lang/rust/pull/102091/)
+- [Trigger `must_use` on `impl Trait` for supertraits](https://github.com/rust-lang/rust/pull/102287/)
+ This makes `impl ExactSizeIterator` respect the existing `#[must_use]` annotation on `Iterator`.
+- [Allow `..X` and `..=X` in patterns](https://github.com/rust-lang/rust/pull/102275/)
+- [Uplift `clippy::for_loops_over_fallibles` lint into rustc](https://github.com/rust-lang/rust/pull/99696/)
+- [Stabilize `sym` operands in inline assembly](https://github.com/rust-lang/rust/pull/103168/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101912/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+ This is a soundness fix which may break code that was erroneously relying on this behavior.
+
+Compiler
+--------
+- [Add armv5te-none-eabi and thumbv5te-none-eabi tier 3 targets](https://github.com/rust-lang/rust/pull/101329/)
+ - Refer to Rust's [platform support page][platform-support-doc] for more
+ information on Rust's tiered platform support.
+- [Add support for linking against macOS universal libraries](https://github.com/rust-lang/rust/pull/98736)
+
+Libraries
+---------
+- [Fix `#[derive(Default)]` on a generic `#[default]` enum adding unnecessary `Default` bounds](https://github.com/rust-lang/rust/pull/101040/)
+- [Update to Unicode 15](https://github.com/rust-lang/rust/pull/101821/)
+
+Stabilized APIs
+---------------
+
+- [`proc_macro::Span::source_text`](https://doc.rust-lang.org/stable/proc_macro/struct.Span.html#method.source_text)
+- [`uX::{checked_add_signed, overflowing_add_signed, saturating_add_signed, wrapping_add_signed}`](https://doc.rust-lang.org/stable/std/primitive.u8.html#method.checked_add_signed)
+- [`iX::{checked_add_unsigned, overflowing_add_unsigned, saturating_add_unsigned, wrapping_add_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_add_unsigned)
+- [`iX::{checked_sub_unsigned, overflowing_sub_unsigned, saturating_sub_unsigned, wrapping_sub_unsigned}`](https://doc.rust-lang.org/stable/std/primitive.i8.html#method.checked_sub_unsigned)
+- [`BTreeSet::{first, last, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeSet.html#method.first)
+- [`BTreeMap::{first_key_value, last_key_value, first_entry, last_entry, pop_first, pop_last}`](https://doc.rust-lang.org/stable/std/collections/struct.BTreeMap.html#method.first_key_value)
+- [Add `AsFd` implementations for stdio lock types on WASI.](https://github.com/rust-lang/rust/pull/101768/)
+- [`impl TryFrom<Vec<T>> for Box<[T; N]>`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#impl-TryFrom%3CVec%3CT%2C%20Global%3E%3E-for-Box%3C%5BT%3B%20N%5D%2C%20Global%3E)
+- [`core::hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
+- [`Duration::try_from_secs_{f32,f64}`](https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.try_from_secs_f32)
+- [`Option::unzip`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.unzip)
+- [`std::os::fd`](https://doc.rust-lang.org/stable/std/os/fd/index.html)
+
+
+Rustdoc
+-------
+
+- [Add Rustdoc warning for invalid HTML tags in the documentation](https://github.com/rust-lang/rust/pull/101720/)
+
+Cargo
+-----
+
+- [Added `cargo remove` to remove dependencies from Cargo.toml](https://doc.rust-lang.org/nightly/cargo/commands/cargo-remove.html)
+- [`cargo publish` now waits for the new version to be downloadable before exiting](https://github.com/rust-lang/cargo/pull/11062)
+
+See [detailed release notes](https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md#cargo-166-2022-12-15) for more.
+
+Compatibility Notes
+-------------------
+
+- [Only apply `ProceduralMasquerade` hack to older versions of `rental`](https://github.com/rust-lang/rust/pull/94063/)
+- [Don't export `__heap_base` and `__data_end` on wasm32-wasi.](https://github.com/rust-lang/rust/pull/102385/)
+- [Don't export `__wasm_init_memory` on WebAssembly.](https://github.com/rust-lang/rust/pull/102426/)
+- [Only export `__tls_*` on wasm32-unknown-unknown.](https://github.com/rust-lang/rust/pull/102440/)
+- [Don't link to `libresolv` in libstd on Darwin](https://github.com/rust-lang/rust/pull/102766/)
+- [Update libstd's libc to 0.2.135 (to make `libstd` no longer pull in `libiconv.dylib` on Darwin)](https://github.com/rust-lang/rust/pull/103277/)
+- [Opaque types no longer imply lifetime bounds](https://github.com/rust-lang/rust/pull/95474/)
+ This is a soundness fix which may break code that was erroneously relying on this behavior.
+- [Make `order_dependent_trait_objects` show up in future-breakage reports](https://github.com/rust-lang/rust/pull/102635/)
+- [Change std::process::Command spawning to default to inheriting the parent's signal mask](https://github.com/rust-lang/rust/pull/101077/)
+
+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.
+
+- [Enable BOLT for LLVM compilation](https://github.com/rust-lang/rust/pull/94381/)
+- [Enable LTO for rustc_driver.so](https://github.com/rust-lang/rust/pull/101403/)
+
Version 1.65.0 (2022-11-03)
==========================
@@ -6,7 +97,7 @@ Language
- [Error on `as` casts of enums with `#[non_exhaustive]` variants](https://github.com/rust-lang/rust/pull/92744/)
- [Stabilize `let else`](https://github.com/rust-lang/rust/pull/93628/)
- [Stabilize generic associated types (GATs)](https://github.com/rust-lang/rust/pull/96709/)
-- [Add lints `let_underscore_drop`, `let_underscore_lock`, and `let_underscore_must_use` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
+- [Add lints `let_underscore_drop` and `let_underscore_lock` from Clippy](https://github.com/rust-lang/rust/pull/97739/)
- [Stabilize `break`ing from arbitrary labeled blocks ("label-break-value")](https://github.com/rust-lang/rust/pull/99332/)
- [Uninitialized integers, floats, and raw pointers are now considered immediate UB](https://github.com/rust-lang/rust/pull/98919/).
Usage of `MaybeUninit` is the correct way to work with uninitialized memory.
@@ -87,6 +178,9 @@ Compatibility Notes
This strengthens the forward compatibility lint deprecated_cfg_attr_crate_type_name to deny.
- [`llvm-has-rust-patches` allows setting the build system to treat the LLVM as having Rust-specific patches](https://github.com/rust-lang/rust/pull/101072)
This option may need to be set for distributions that are building Rust with a patched LLVM via `llvm-config`, not the built-in LLVM.
+- Combining three or more languages (e.g. Objective C, C++ and Rust) into one binary may hit linker limitations when using `lld`. For more information, see [issue 102754][102754].
+
+[102754]: https://github.com/rust-lang/rust/issues/102754
Internal Changes
----------------
diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs
index 0de1a7819..e21c9b660 100644
--- a/compiler/rustc/src/main.rs
+++ b/compiler/rustc/src/main.rs
@@ -1,3 +1,5 @@
+#![feature(unix_sigpipe)]
+
// A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]`
// mechanism. However, for complicated reasons (see
@@ -23,6 +25,7 @@
// libraries. So we must reference jemalloc symbols one way or another, because
// this file is the only object code in the rustc executable.
+#[unix_sigpipe = "sig_dfl"]
fn main() {
// See the comment at the top of this file for an explanation of this.
#[cfg(feature = "jemalloc-sys")]
@@ -58,6 +61,5 @@ fn main() {
}
}
- rustc_driver::set_sigpipe_handler();
rustc_driver::main()
}
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index c24180bac..fcbf96818 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.2.1"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index d86db8f8b..4ef43735a 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1112,24 +1112,6 @@ pub struct Expr {
}
impl Expr {
- /// Returns `true` if this expression would be valid somewhere that expects a value;
- /// for example, an `if` condition.
- pub fn returns(&self) -> bool {
- if let ExprKind::Block(ref block, _) = self.kind {
- match block.stmts.last().map(|last_stmt| &last_stmt.kind) {
- // Implicit return
- Some(StmtKind::Expr(_)) => true,
- // Last statement is an explicit return?
- Some(StmtKind::Semi(expr)) => matches!(expr.kind, ExprKind::Ret(_)),
- // This is a block that doesn't end in either an implicit or explicit return.
- _ => false,
- }
- } else {
- // This is not a block, it is a value.
- true
- }
- }
-
/// Is this expr either `N`, or `{ N }`.
///
/// If this is not the case, name resolution does not resolve `N` when using
@@ -1338,14 +1320,13 @@ pub enum ExprKind {
///
/// The `PathSegment` represents the method name and its generic arguments
/// (within the angle brackets).
- /// The first element of the vector of an `Expr` is the expression that evaluates
- /// to the object on which the method is being called on (the receiver),
- /// and the remaining elements are the rest of the arguments.
- /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
- /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, [x, a, b, c, d])`.
+ /// The standalone `Expr` is the receiver expression.
+ /// The vector of `Expr` is the arguments.
+ /// `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
+ /// `ExprKind::MethodCall(PathSegment { foo, [Bar, Baz] }, x, [a, b, c, d])`.
/// This `Span` is the span of the function, without the dot and receiver
/// (e.g. `foo(a, b)` in `x.foo(a, b)`
- MethodCall(PathSegment, Vec<P<Expr>>, Span),
+ MethodCall(PathSegment, P<Expr>, Vec<P<Expr>>, Span),
/// A tuple (e.g., `(a, b, c, d)`).
Tup(Vec<P<Expr>>),
/// A binary operation (e.g., `a + b`, `a * b`).
@@ -2957,7 +2938,7 @@ pub enum AssocItemKind {
/// An associated function.
Fn(Box<Fn>),
/// An associated type.
- TyAlias(Box<TyAlias>),
+ Type(Box<TyAlias>),
/// A macro expanding to associated items.
MacCall(P<MacCall>),
}
@@ -2967,7 +2948,7 @@ impl AssocItemKind {
match *self {
Self::Const(defaultness, ..)
| Self::Fn(box Fn { defaultness, .. })
- | Self::TyAlias(box TyAlias { defaultness, .. }) => defaultness,
+ | Self::Type(box TyAlias { defaultness, .. }) => defaultness,
Self::MacCall(..) => Defaultness::Final,
}
}
@@ -2978,7 +2959,7 @@ impl From<AssocItemKind> for ItemKind {
match assoc_item_kind {
AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c),
AssocItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
- AssocItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
+ AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
}
}
@@ -2991,7 +2972,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
Ok(match item_kind {
ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c),
ItemKind::Fn(fn_kind) => AssocItemKind::Fn(fn_kind),
- ItemKind::TyAlias(ty_alias_kind) => AssocItemKind::TyAlias(ty_alias_kind),
+ ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind),
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
_ => return Err(item_kind),
})
@@ -3043,14 +3024,13 @@ pub type ForeignItem = Item<ForeignItemKind>;
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(AssocItem, 104);
static_assert_size!(AssocItemKind, 32);
static_assert_size!(Attribute, 32);
static_assert_size!(Block, 48);
static_assert_size!(Expr, 104);
static_assert_size!(ExprKind, 72);
- #[cfg(not(bootstrap))]
static_assert_size!(Fn, 184);
static_assert_size!(ForeignItem, 96);
static_assert_size!(ForeignItemKind, 24);
@@ -3065,11 +3045,12 @@ mod size_asserts {
static_assert_size!(Local, 72);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 120);
- static_assert_size!(PatKind, 96);
static_assert_size!(Path, 40);
static_assert_size!(PathSegment, 24);
+ static_assert_size!(PatKind, 96);
static_assert_size!(Stmt, 32);
static_assert_size!(StmtKind, 16);
static_assert_size!(Ty, 96);
static_assert_size!(TyKind, 72);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index bd7a85b07..eeb7e56e2 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -13,9 +13,7 @@
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(if_let_guard)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(slice_internals)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 9fd0b63c4..b970e57e0 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -152,6 +152,12 @@ pub trait MutVisitor: Sized {
noop_visit_expr(e, self);
}
+ /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
+ /// It can be removed once that feature is stabilized.
+ fn visit_method_receiver_expr(&mut self, ex: &mut P<Expr>) {
+ self.visit_expr(ex)
+ }
+
fn filter_map_expr(&mut self, e: P<Expr>) -> Option<P<Expr>> {
noop_filter_map_expr(e, self)
}
@@ -1106,7 +1112,7 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
visit_fn_sig(sig, visitor);
visit_opt(body, |body| visitor.visit_block(body));
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
defaultness,
generics,
where_clauses,
@@ -1297,10 +1303,11 @@ pub fn noop_visit_expr<T: MutVisitor>(
vis.visit_expr(f);
visit_exprs(args, vis);
}
- ExprKind::MethodCall(PathSegment { ident, id, args }, exprs, span) => {
+ ExprKind::MethodCall(PathSegment { ident, id, args }, receiver, exprs, span) => {
vis.visit_ident(ident);
vis.visit_id(id);
visit_opt(args, |args| vis.visit_generic_args(args));
+ vis.visit_method_receiver_expr(receiver);
visit_exprs(exprs, vis);
vis.visit_span(span);
}
@@ -1588,3 +1595,9 @@ impl DummyAstNode for Crate {
}
}
}
+
+impl<N: DummyAstNode, T: DummyAstNode> DummyAstNode for crate::ast_traits::AstNodeWrapper<N, T> {
+ fn dummy() -> Self {
+ crate::ast_traits::AstNodeWrapper::new(N::dummy(), T::dummy())
+ }
+}
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index 97dfb7837..83b10d906 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -13,7 +13,7 @@ use rustc_span::symbol::{kw, sym};
use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
use std::borrow::Cow;
-use std::{fmt, mem};
+use std::fmt;
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind {
@@ -256,10 +256,6 @@ pub enum TokenKind {
Eof,
}
-// `TokenKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenKind, 16);
-
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
@@ -335,11 +331,6 @@ impl Token {
Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span)
}
- /// Return this token by value and leave a dummy token in its place.
- pub fn take(&mut self) -> Self {
- mem::replace(self, Token::dummy())
- }
-
/// For interpolated tokens, returns a span of the fragment to which the interpolated
/// token refers. For all other tokens this is just a regular span.
/// It is particularly important to use this for identifiers and lifetimes
@@ -354,17 +345,14 @@ impl Token {
}
pub fn is_op(&self) -> bool {
- !matches!(
- self.kind,
- OpenDelim(..)
- | CloseDelim(..)
- | Literal(..)
- | DocComment(..)
- | Ident(..)
- | Lifetime(..)
- | Interpolated(..)
- | Eof
- )
+ match self.kind {
+ Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | BinOp(_)
+ | BinOpEq(_) | At | Dot | DotDot | DotDotDot | DotDotEq | Comma | Semi | Colon
+ | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar | Question | SingleQuote => true,
+
+ OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..)
+ | Lifetime(..) | Interpolated(..) | Eof => false,
+ }
}
pub fn is_like_plus(&self) -> bool {
@@ -733,6 +721,7 @@ impl Token {
}
impl PartialEq<TokenKind> for Token {
+ #[inline]
fn eq(&self, rhs: &TokenKind) -> bool {
self.kind == *rhs
}
@@ -756,10 +745,6 @@ pub enum Nonterminal {
NtVis(P<ast::Visibility>),
}
-// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Nonterminal, 16);
-
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind {
Item,
@@ -898,3 +883,17 @@ where
panic!("interpolated tokens should not be present in the HIR")
}
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(Lit, 12);
+ static_assert_size!(LitKind, 2);
+ static_assert_size!(Nonterminal, 16);
+ static_assert_size!(Token, 24);
+ static_assert_size!(TokenKind, 16);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 875cd620d..015f5c1ee 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -47,10 +47,6 @@ pub enum TokenTree {
Delimited(DelimSpan, Delimiter, TokenStream),
}
-// This type is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenTree, 32);
-
// Ensure all fields of `TokenTree` is `Send` and `Sync`.
#[cfg(parallel_compiler)]
fn _dummy()
@@ -249,12 +245,12 @@ impl AttrTokenStream {
// properly implemented - we always synthesize fake tokens,
// so we never reach this code.
- let mut builder = TokenStreamBuilder::new();
+ let mut stream = TokenStream::default();
for inner_attr in inner_attrs {
- builder.push(inner_attr.tokens());
+ stream.push_stream(inner_attr.tokens());
}
- builder.push(delim_tokens.clone());
- *tree = TokenTree::Delimited(*span, *delim, builder.build());
+ stream.push_stream(delim_tokens.clone());
+ *tree = TokenTree::Delimited(*span, *delim, stream);
found = true;
break;
}
@@ -308,13 +304,20 @@ pub struct AttributesData {
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
-// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(TokenStream, 8);
-
+/// Similar to `proc_macro::Spacing`, but for tokens.
+///
+/// Note that all `ast::TokenTree::Token` instances have a `Spacing`, but when
+/// we convert to `proc_macro::TokenTree` for proc macros only `Punct`
+/// `TokenTree`s have a `proc_macro::Spacing`.
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum Spacing {
+ /// The token is not immediately followed by an operator token (as
+ /// determined by `Token::is_op`). E.g. a `+` token is `Alone` in `+ =`,
+ /// `+/*foo*/=`, `+ident`, and `+()`.
Alone,
+
+ /// The token is immediately followed by an operator token. E.g. a `+`
+ /// token is `Joint` in `+=` and `++`.
Joint,
}
@@ -502,76 +505,49 @@ impl TokenStream {
self.trees().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
}
-}
-// 99.5%+ of the time we have 1 or 2 elements in this vector.
-#[derive(Clone)]
-pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>);
-
-impl TokenStreamBuilder {
- pub fn new() -> TokenStreamBuilder {
- TokenStreamBuilder(SmallVec::new())
- }
-
- pub fn push(&mut self, stream: TokenStream) {
- self.0.push(stream);
- }
-
- pub fn build(self) -> TokenStream {
- let mut streams = self.0;
- match streams.len() {
- 0 => TokenStream::default(),
- 1 => streams.pop().unwrap(),
- _ => {
- // We will extend the first stream in `streams` with the
- // elements from the subsequent streams. This requires using
- // `make_mut()` on the first stream, and in practice this
- // doesn't cause cloning 99.9% of the time.
- //
- // One very common use case is when `streams` has two elements,
- // where the first stream has any number of elements within
- // (often 1, but sometimes many more) and the second stream has
- // a single element within.
-
- // Determine how much the first stream will be extended.
- // Needed to avoid quadratic blow up from on-the-fly
- // reallocations (#57735).
- let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
-
- // Get the first stream, which will become the result stream.
- // If it's `None`, create an empty stream.
- let mut iter = streams.into_iter();
- let mut res_stream_lrc = iter.next().unwrap().0;
-
- // Append the subsequent elements to the result stream, after
- // reserving space for them.
- let res_vec_mut = Lrc::make_mut(&mut res_stream_lrc);
- res_vec_mut.reserve(num_appends);
- for stream in iter {
- let stream_iter = stream.0.iter().cloned();
-
- // If (a) `res_mut_vec` is not empty and the last tree
- // within it is a token tree marked with `Joint`, and (b)
- // `stream` is not empty and the first tree within it is a
- // token tree, and (c) the two tokens can be glued
- // together...
- if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = res_vec_mut.last()
- && let Some(TokenTree::Token(tok, spacing)) = stream.0.first()
- && let Some(glued_tok) = last_tok.glue(&tok)
- {
- // ...then overwrite the last token tree in
- // `res_vec_mut` with the glued token, and skip the
- // first token tree from `stream`.
- *res_vec_mut.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
- res_vec_mut.extend(stream_iter.skip(1));
- } else {
- // Append all of `stream`.
- res_vec_mut.extend(stream_iter);
- }
- }
+ // If `vec` is not empty, try to glue `tt` onto its last token. The return
+ // value indicates if gluing took place.
+ fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
+ if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last()
+ && let TokenTree::Token(tok, spacing) = tt
+ && let Some(glued_tok) = last_tok.glue(&tok)
+ {
+ // ...then overwrite the last token tree in `vec` with the
+ // glued token, and skip the first token tree from `stream`.
+ *vec.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
+ true
+ } else {
+ false
+ }
+ }
- TokenStream(res_stream_lrc)
- }
+ // Push `tt` onto the end of the stream, possibly gluing it to the last
+ // token. Uses `make_mut` to maximize efficiency.
+ pub fn push_tree(&mut self, tt: TokenTree) {
+ let vec_mut = Lrc::make_mut(&mut self.0);
+
+ if Self::try_glue_to_last(vec_mut, &tt) {
+ // nothing else to do
+ } else {
+ vec_mut.push(tt);
+ }
+ }
+
+ // Push `stream` onto the end of the stream, possibly gluing the first
+ // token tree to the last token. (No other token trees will be glued.)
+ // Uses `make_mut` to maximize efficiency.
+ pub fn push_stream(&mut self, stream: TokenStream) {
+ let vec_mut = Lrc::make_mut(&mut self.0);
+
+ let stream_iter = stream.0.iter().cloned();
+
+ if let Some(first) = stream.0.first() && Self::try_glue_to_last(vec_mut, first) {
+ // Now skip the first token tree from `stream`.
+ vec_mut.extend(stream_iter.skip(1));
+ } else {
+ // Append all of `stream`.
+ vec_mut.extend(stream_iter);
}
}
}
@@ -664,3 +640,17 @@ impl DelimSpan {
self.open.with_hi(self.close.hi())
}
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(AttrTokenStream, 8);
+ static_assert_size!(AttrTokenTree, 32);
+ static_assert_size!(LazyAttrTokenStream, 8);
+ static_assert_size!(TokenStream, 8);
+ static_assert_size!(TokenTree, 32);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs
index 6c5c7f66f..b40ad6f70 100644
--- a/compiler/rustc_ast/src/util/parser.rs
+++ b/compiler/rustc_ast/src/util/parser.rs
@@ -396,9 +396,9 @@ pub fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
contains_exterior_struct_lit(&x)
}
- ast::ExprKind::MethodCall(.., ref exprs, _) => {
+ ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
// X { y: 1 }.bar(...)
- contains_exterior_struct_lit(&exprs[0])
+ contains_exterior_struct_lit(&receiver)
}
_ => false,
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 1d0de5a4b..6f56c1ef0 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -140,6 +140,11 @@ pub trait Visitor<'ast>: Sized {
fn visit_expr(&mut self, ex: &'ast Expr) {
walk_expr(self, ex)
}
+ /// This method is a hack to workaround unstable of `stmt_expr_attributes`.
+ /// It can be removed once that feature is stabilized.
+ fn visit_method_receiver_expr(&mut self, ex: &'ast Expr) {
+ self.visit_expr(ex)
+ }
fn visit_expr_post(&mut self, _ex: &'ast Expr) {}
fn visit_ty(&mut self, t: &'ast Ty) {
walk_ty(self, t)
@@ -244,14 +249,12 @@ pub trait Visitor<'ast>: Sized {
#[macro_export]
macro_rules! walk_list {
- ($visitor: expr, $method: ident, $list: expr) => {
- for elem in $list {
- $visitor.$method(elem)
- }
- };
- ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
- for elem in $list {
- $visitor.$method(elem, $($extra_args,)*)
+ ($visitor: expr, $method: ident, $list: expr $(, $($extra_args: expr),* )?) => {
+ {
+ #[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))]
+ for elem in $list {
+ $visitor.$method(elem $(, $($extra_args,)* )?)
+ }
}
}
}
@@ -685,7 +688,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, generics, body.as_deref());
visitor.visit_fn(kind, span, id);
}
- AssocItemKind::TyAlias(box TyAlias { generics, bounds, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
visitor.visit_generics(generics);
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
walk_list!(visitor, visit_ty, ty);
@@ -795,8 +798,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
visitor.visit_expr(callee_expression);
walk_list!(visitor, visit_expr, arguments);
}
- ExprKind::MethodCall(ref segment, ref arguments, _span) => {
+ ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _span) => {
visitor.visit_path_segment(segment);
+ visitor.visit_expr(receiver);
walk_list!(visitor, visit_expr, arguments);
}
ExprKind::Binary(_, ref left_expression, ref right_expression) => {
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 24672efc6..450cdf246 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -192,26 +192,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
InlineAsmOperand::Sym { ref sym } => {
- if !self.tcx.features().asm_sym {
- feature_err(
- &sess.parse_sess,
- sym::asm_sym,
- *op_sp,
- "sym operands for inline assembly are unstable",
- )
- .emit();
- }
-
let static_def_id = self
.resolver
.get_partial_res(sym.id)
- .filter(|res| res.unresolved_segments() == 0)
- .and_then(|res| {
- if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
- Some(def_id)
- } else {
- None
- }
+ .and_then(|res| res.full_res())
+ .and_then(|res| match res {
+ Res::Def(DefKind::Static(_), def_id) => Some(def_id),
+ _ => None,
});
if let Some(def_id) = static_def_id {
@@ -237,7 +224,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Wrap the expression in an AnonConst.
let parent_def_id = self.current_hir_id_owner;
let node_id = self.next_node_id();
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: P(expr) };
hir::InlineAsmOperand::SymFn {
anon_const: self.lower_anon_const(&anon_const),
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index c87d0ca96..157f46501 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic, DiagnosticArgFromDisplay};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::DiagnosticArgFromDisplay;
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{symbol::Ident, Span, Symbol};
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::generic_type_with_parentheses, code = "E0214")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_generic_type_with_parentheses, code = "E0214")]
pub struct GenericTypeWithParentheses {
#[primary_span]
#[label]
@@ -12,35 +12,42 @@ pub struct GenericTypeWithParentheses {
pub sub: Option<UseAngleBrackets>,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
+#[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
pub struct UseAngleBrackets {
+ #[suggestion_part(code = "<")]
pub open_param: Span,
+ #[suggestion_part(code = ">")]
pub close_param: Span,
}
-impl AddSubdiagnostic for UseAngleBrackets {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
- diag.multipart_suggestion(
- fluent::ast_lowering::use_angle_brackets,
- vec![(self.open_param, String::from("<")), (self.close_param, String::from(">"))],
- Applicability::MaybeIncorrect,
- );
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[help]
-#[diag(ast_lowering::invalid_abi, code = "E0703")]
+#[derive(Diagnostic)]
+#[diag(ast_lowering_invalid_abi, code = "E0703")]
+#[note]
pub struct InvalidAbi {
#[primary_span]
#[label]
pub span: Span,
pub abi: Symbol,
- pub valid_abis: String,
+ pub command: String,
+ #[subdiagnostic]
+ pub suggestion: Option<InvalidAbiSuggestion>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+ ast_lowering_invalid_abi_suggestion,
+ code = "{suggestion}",
+ applicability = "maybe-incorrect"
+)]
+pub struct InvalidAbiSuggestion {
+ #[primary_span]
+ pub span: Span,
+ pub suggestion: String,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::assoc_ty_parentheses)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_assoc_ty_parentheses)]
pub struct AssocTyParentheses {
#[primary_span]
pub span: Span,
@@ -48,123 +55,116 @@ pub struct AssocTyParentheses {
pub sub: AssocTyParenthesesSub,
}
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
pub enum AssocTyParenthesesSub {
- Empty { parentheses_span: Span },
- NotEmpty { open_param: Span, close_param: Span },
-}
-
-impl AddSubdiagnostic for AssocTyParenthesesSub {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
- match self {
- Self::Empty { parentheses_span } => diag.multipart_suggestion(
- fluent::ast_lowering::remove_parentheses,
- vec![(parentheses_span, String::new())],
- Applicability::MaybeIncorrect,
- ),
- Self::NotEmpty { open_param, close_param } => diag.multipart_suggestion(
- fluent::ast_lowering::use_angle_brackets,
- vec![(open_param, String::from("<")), (close_param, String::from(">"))],
- Applicability::MaybeIncorrect,
- ),
- };
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(ast_lowering::misplaced_impl_trait, code = "E0562")]
+ #[multipart_suggestion(ast_lowering_remove_parentheses)]
+ Empty {
+ #[suggestion_part(code = "")]
+ parentheses_span: Span,
+ },
+ #[multipart_suggestion(ast_lowering_use_angle_brackets)]
+ NotEmpty {
+ #[suggestion_part(code = "<")]
+ open_param: Span,
+ #[suggestion_part(code = ">")]
+ close_param: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(ast_lowering_misplaced_impl_trait, code = "E0562")]
pub struct MisplacedImplTrait<'a> {
#[primary_span]
pub span: Span,
pub position: DiagnosticArgFromDisplay<'a>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::rustc_box_attribute_error)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_rustc_box_attribute_error)]
pub struct RustcBoxAttributeError {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::underscore_expr_lhs_assign)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_underscore_expr_lhs_assign)]
pub struct UnderscoreExprLhsAssign {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::base_expression_double_dot)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_base_expression_double_dot)]
pub struct BaseExpressionDoubleDot {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::await_only_in_async_fn_and_blocks, code = "E0728")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = "E0728")]
pub struct AwaitOnlyInAsyncFnAndBlocks {
#[primary_span]
#[label]
pub dot_await_span: Span,
- #[label(ast_lowering::this_not_async)]
+ #[label(ast_lowering_this_not_async)]
pub item_span: Option<Span>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::generator_too_many_parameters, code = "E0628")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_generator_too_many_parameters, code = "E0628")]
pub struct GeneratorTooManyParameters {
#[primary_span]
pub fn_decl_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::closure_cannot_be_static, code = "E0697")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_closure_cannot_be_static, code = "E0697")]
pub struct ClosureCannotBeStatic {
#[primary_span]
pub fn_decl_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
+#[derive(Diagnostic, Clone, Copy)]
#[help]
-#[diag(ast_lowering::async_non_move_closure_not_supported, code = "E0708")]
+#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
pub struct AsyncNonMoveClosureNotSupported {
#[primary_span]
pub fn_decl_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::functional_record_update_destructuring_assignment)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
pub struct FunctionalRecordUpdateDestructuringAssignemnt {
#[primary_span]
#[suggestion(code = "", applicability = "machine-applicable")]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::async_generators_not_supported, code = "E0727")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_async_generators_not_supported, code = "E0727")]
pub struct AsyncGeneratorsNotSupported {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::inline_asm_unsupported_target, code = "E0472")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_inline_asm_unsupported_target, code = "E0472")]
pub struct InlineAsmUnsupportedTarget {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::att_syntax_only_x86)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_att_syntax_only_x86)]
pub struct AttSyntaxOnlyX86 {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::abi_specified_multiple_times)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_abi_specified_multiple_times)]
pub struct AbiSpecifiedMultipleTimes {
#[primary_span]
pub abi_span: Span,
@@ -175,24 +175,24 @@ pub struct AbiSpecifiedMultipleTimes {
pub equivalent: Option<()>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::clobber_abi_not_supported)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_clobber_abi_not_supported)]
pub struct ClobberAbiNotSupported {
#[primary_span]
pub abi_span: Span,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[note]
-#[diag(ast_lowering::invalid_abi_clobber_abi)]
+#[diag(ast_lowering_invalid_abi_clobber_abi)]
pub struct InvalidAbiClobberAbi {
#[primary_span]
pub abi_span: Span,
pub supported_abis: String,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_register)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_register)]
pub struct InvalidRegister<'a> {
#[primary_span]
pub op_span: Span,
@@ -200,8 +200,8 @@ pub struct InvalidRegister<'a> {
pub error: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_register_class)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_register_class)]
pub struct InvalidRegisterClass<'a> {
#[primary_span]
pub op_span: Span,
@@ -209,61 +209,61 @@ pub struct InvalidRegisterClass<'a> {
pub error: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_lowering::invalid_asm_template_modifier_reg_class)]
+#[derive(Diagnostic)]
+#[diag(ast_lowering_invalid_asm_template_modifier_reg_class)]
pub struct InvalidAsmTemplateModifierRegClass {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
#[subdiagnostic]
pub sub: InvalidAsmTemplateModifierRegClassSub,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum InvalidAsmTemplateModifierRegClassSub {
- #[note(ast_lowering::support_modifiers)]
+ #[note(ast_lowering_support_modifiers)]
SupportModifier { class_name: Symbol, modifiers: String },
- #[note(ast_lowering::does_not_support_modifiers)]
+ #[note(ast_lowering_does_not_support_modifiers)]
DoesNotSupportModifier { class_name: Symbol },
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_const)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_asm_template_modifier_const)]
pub struct InvalidAsmTemplateModifierConst {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::invalid_asm_template_modifier_sym)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_invalid_asm_template_modifier_sym)]
pub struct InvalidAsmTemplateModifierSym {
#[primary_span]
- #[label(ast_lowering::template_modifier)]
+ #[label(ast_lowering_template_modifier)]
pub placeholder_span: Span,
- #[label(ast_lowering::argument)]
+ #[label(ast_lowering_argument)]
pub op_span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::register_class_only_clobber)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_register_class_only_clobber)]
pub struct RegisterClassOnlyClobber {
#[primary_span]
pub op_span: Span,
pub reg_class_name: Symbol,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::register_conflict)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_register_conflict)]
pub struct RegisterConflict<'a> {
#[primary_span]
- #[label(ast_lowering::register1)]
+ #[label(ast_lowering_register1)]
pub op_span1: Span,
- #[label(ast_lowering::register2)]
+ #[label(ast_lowering_register2)]
pub op_span2: Span,
pub reg1_name: &'a str,
pub reg2_name: &'a str,
@@ -271,14 +271,14 @@ pub struct RegisterConflict<'a> {
pub in_out: Option<Span>,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
+#[derive(Diagnostic, Clone, Copy)]
#[help]
-#[diag(ast_lowering::sub_tuple_binding)]
+#[diag(ast_lowering_sub_tuple_binding)]
pub struct SubTupleBinding<'a> {
#[primary_span]
#[label]
#[suggestion_verbose(
- ast_lowering::sub_tuple_binding_suggestion,
+ ast_lowering_sub_tuple_binding_suggestion,
code = "..",
applicability = "maybe-incorrect"
)]
@@ -288,57 +288,57 @@ pub struct SubTupleBinding<'a> {
pub ctx: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::extra_double_dot)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_extra_double_dot)]
pub struct ExtraDoubleDot<'a> {
#[primary_span]
#[label]
pub span: Span,
- #[label(ast_lowering::previously_used_here)]
+ #[label(ast_lowering_previously_used_here)]
pub prev_span: Span,
pub ctx: &'a str,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
+#[derive(Diagnostic, Clone, Copy)]
#[note]
-#[diag(ast_lowering::misplaced_double_dot)]
+#[diag(ast_lowering_misplaced_double_dot)]
pub struct MisplacedDoubleDot {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::misplaced_relax_trait_bound)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_misplaced_relax_trait_bound)]
pub struct MisplacedRelaxTraitBound {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::not_supported_for_lifetime_binder_async_closure)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_not_supported_for_lifetime_binder_async_closure)]
pub struct NotSupportedForLifetimeBinderAsyncClosure {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::arbitrary_expression_in_pattern)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_arbitrary_expression_in_pattern)]
pub struct ArbitraryExpressionInPattern {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::inclusive_range_with_no_end)]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_inclusive_range_with_no_end)]
pub struct InclusiveRangeWithNoEnd {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic, Clone, Copy)]
-#[diag(ast_lowering::trait_fn_async, code = "E0706")]
+#[derive(Diagnostic, Clone, Copy)]
+#[diag(ast_lowering_trait_fn_async, code = "E0706")]
#[note]
-#[note(ast_lowering::note2)]
+#[note(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 7b8070d3c..ec9c39350 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -60,7 +60,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Call(f, self.lower_exprs(args))
}
}
- ExprKind::MethodCall(ref seg, ref args, span) => {
+ ExprKind::MethodCall(ref seg, ref receiver, ref args, span) => {
let hir_seg = self.arena.alloc(self.lower_path_segment(
e.span,
seg,
@@ -68,9 +68,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
ParenthesizedGenericArgs::Err,
&ImplTraitContext::Disallowed(ImplTraitPosition::Path),
));
- let receiver = self.lower_expr(&args[0]);
+ let receiver = self.lower_expr(receiver);
let args =
- self.arena.alloc_from_iter(args[1..].iter().map(|x| self.lower_expr_mut(x)));
+ self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x)));
hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(span))
}
ExprKind::Binary(binop, ref lhs, ref rhs) => {
@@ -359,7 +359,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let node_id = self.next_node_id();
// Add a definition for the in-band const def.
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst);
let anon_const = AnonConst { id: node_id, value: arg };
generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const)));
@@ -387,32 +387,58 @@ impl<'hir> LoweringContext<'_, 'hir> {
then: &Block,
else_opt: Option<&Expr>,
) -> hir::ExprKind<'hir> {
- let lowered_cond = self.lower_expr(cond);
- let new_cond = self.manage_let_cond(lowered_cond);
+ let lowered_cond = self.lower_cond(cond);
let then_expr = self.lower_block_expr(then);
if let Some(rslt) = else_opt {
- hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
+ hir::ExprKind::If(
+ lowered_cond,
+ self.arena.alloc(then_expr),
+ Some(self.lower_expr(rslt)),
+ )
} else {
- hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
+ hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None)
}
}
- // If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
- // in a temporary block.
- fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
- fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
- match expr.kind {
- hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
- hir::ExprKind::Let(..) => true,
+ // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope
+ // so that temporaries created in the condition don't live beyond it.
+ fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> {
+ fn has_let_expr(expr: &Expr) -> bool {
+ match &expr.kind {
+ ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
+ ExprKind::Let(..) => true,
_ => false,
}
}
- if has_let_expr(cond) {
- cond
- } else {
- let reason = DesugaringKind::CondTemporary;
- let span_block = self.mark_span_with_reason(reason, cond.span, None);
- self.expr_drop_temps(span_block, cond, AttrVec::new())
+
+ // We have to take special care for `let` exprs in the condition, e.g. in
+ // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
+ // condition in this case.
+ //
+ // In order to mantain the drop behavior for the non `let` parts of the condition,
+ // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
+ // gets transformed into `if { let _t = foo; _t } && let pat = val`
+ match &cond.kind {
+ ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs)
+ if has_let_expr(cond) =>
+ {
+ let op = self.lower_binop(*op);
+ let lhs = self.lower_cond(lhs);
+ let rhs = self.lower_cond(rhs);
+
+ self.arena.alloc(self.expr(
+ cond.span,
+ hir::ExprKind::Binary(op, lhs, rhs),
+ AttrVec::new(),
+ ))
+ }
+ ExprKind::Let(..) => self.lower_expr(cond),
+ _ => {
+ let cond = self.lower_expr(cond);
+ let reason = DesugaringKind::CondTemporary;
+ let span_block = self.mark_span_with_reason(reason, cond.span, None);
+ self.expr_drop_temps(span_block, cond, AttrVec::new())
+ }
}
}
@@ -439,14 +465,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Block,
opt_label: Option<Label>,
) -> hir::ExprKind<'hir> {
- let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
- let new_cond = self.manage_let_cond(lowered_cond);
+ let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond));
let then = self.lower_block_expr(body);
let expr_break = self.expr_break(span, AttrVec::new());
let stmt_break = self.stmt_expr(span, expr_break);
let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
- let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
+ let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr));
let if_expr = self.expr(span, if_kind, AttrVec::new());
let block = self.block_expr(self.arena.alloc(if_expr));
let span = self.lower_span(span.with_hi(cond.span.hi()));
@@ -1044,9 +1069,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a tuple struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
- if partial_res.unresolved_segments() == 0
- && !partial_res.base_res().expected_in_tuple_struct_pat()
- {
+ if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() {
return None;
}
}
@@ -1066,9 +1089,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
if let ExprKind::Path(qself, path) = &expr.kind {
// Does the path resolve to something disallowed in a unit struct/variant pattern?
if let Some(partial_res) = self.resolver.get_partial_res(expr.id) {
- if partial_res.unresolved_segments() == 0
- && !partial_res.base_res().expected_in_unit_struct_pat()
- {
+ if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() {
return None;
}
}
@@ -1609,11 +1630,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
/// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into:
- /// ```rust
+ /// ```ignore(illustrative)
/// // If there is an enclosing `try {...}`:
- /// break 'catch_target FromResidual::from_residual(Yeet(residual)),
+ /// break 'catch_target FromResidual::from_residual(Yeet(residual));
/// // Otherwise:
- /// return FromResidual::from_residual(Yeet(residual)),
+ /// return FromResidual::from_residual(Yeet(residual));
/// ```
/// But to simplify this, there's a `from_yeet` lang item function which
/// handles the combined `FromResidual::from_residual(Yeet(residual))`.
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 85846b567..f1851d7b4 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -24,7 +24,7 @@ pub(super) struct NodeCollector<'a, 'hir> {
/// The parent of this node
parent_node: hir::ItemLocalId,
- owner: LocalDefId,
+ owner: OwnerId,
definitions: &'a definitions::Definitions,
}
@@ -81,9 +81,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
self.source_map.span_to_diagnostic_string(span),
node,
- self.definitions.def_path(self.owner).to_string_no_crate_verbose(),
+ self.definitions.def_path(self.owner.def_id).to_string_no_crate_verbose(),
self.owner,
- self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
+ self.definitions.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
hir_id.owner,
)
}
@@ -112,19 +112,19 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
- self.insert_nested(item.def_id);
+ self.insert_nested(item.owner_id.def_id);
}
fn visit_nested_trait_item(&mut self, item_id: TraitItemId) {
- self.insert_nested(item_id.def_id);
+ self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
- self.insert_nested(item_id.def_id);
+ self.insert_nested(item_id.owner_id.def_id);
}
fn visit_nested_foreign_item(&mut self, foreign_id: ForeignItemId) {
- self.insert_nested(foreign_id.def_id);
+ self.insert_nested(foreign_id.owner_id.def_id);
}
fn visit_nested_body(&mut self, id: BodyId) {
@@ -143,7 +143,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_item(&mut self, i: &'hir Item<'hir>) {
- debug_assert_eq!(i.def_id, self.owner);
+ debug_assert_eq!(i.owner_id, self.owner);
self.with_parent(i.hir_id(), |this| {
if let ItemKind::Struct(ref struct_def, _) = i.kind {
// If this is a tuple or unit-like struct, register the constructor.
@@ -157,7 +157,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_foreign_item(&mut self, fi: &'hir ForeignItem<'hir>) {
- debug_assert_eq!(fi.def_id, self.owner);
+ debug_assert_eq!(fi.owner_id, self.owner);
self.with_parent(fi.hir_id(), |this| {
intravisit::walk_foreign_item(this, fi);
});
@@ -176,7 +176,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) {
- debug_assert_eq!(ti.def_id, self.owner);
+ debug_assert_eq!(ti.owner_id, self.owner);
self.with_parent(ti.hir_id(), |this| {
intravisit::walk_trait_item(this, ti);
});
@@ -184,7 +184,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
#[instrument(level = "debug", skip(self))]
fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) {
- debug_assert_eq!(ii.def_id, self.owner);
+ debug_assert_eq!(ii.owner_id, self.owner);
self.with_parent(ii.hir_id(), |this| {
intravisit::walk_impl_item(this, ii);
});
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 550833275..76316a574 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -1,4 +1,4 @@
-use super::errors::{InvalidAbi, MisplacedRelaxTraitBound};
+use super::errors::{InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound};
use super::ResolverAstLoweringExt;
use super::{Arena, AstOwner, ImplTraitContext, ImplTraitPosition};
use super::{FnDeclKind, LoweringContext, ParamMode};
@@ -14,9 +14,10 @@ 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::source_map::DesugaringKind;
use rustc_span::symbol::{kw, sym, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
use rustc_target::spec::abi;
use smallvec::{smallvec, SmallVec};
@@ -67,7 +68,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
bodies: Vec::new(),
attrs: SortedMap::default(),
children: FxHashMap::default(),
- current_hir_id_owner: CRATE_DEF_ID,
+ 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(),
@@ -176,7 +177,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
pub(super) fn lower_item_ref(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
- let mut node_ids = smallvec![hir::ItemId { def_id: self.local_def_id(i.id) }];
+ let mut node_ids =
+ smallvec![hir::ItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }];
if let ItemKind::Use(ref use_tree) = &i.kind {
self.lower_item_id_use_tree(use_tree, i.id, &mut node_ids);
}
@@ -192,7 +194,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match tree.kind {
UseTreeKind::Nested(ref nested_vec) => {
for &(ref nested, id) in nested_vec {
- vec.push(hir::ItemId { def_id: self.local_def_id(id) });
+ vec.push(hir::ItemId {
+ owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
+ });
self.lower_item_id_use_tree(nested, id, vec);
}
}
@@ -201,7 +205,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
for (_, &id) in
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
{
- vec.push(hir::ItemId { def_id: self.local_def_id(id) });
+ vec.push(hir::ItemId {
+ owner_id: hir::OwnerId { def_id: self.local_def_id(id) },
+ });
}
}
}
@@ -214,7 +220,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let attrs = self.lower_attrs(hir_id, &i.attrs);
let kind = self.lower_item_kind(i.span, i.id, hir_id, &mut ident, attrs, vis_span, &i.kind);
let item = hir::Item {
- def_id: hir_id.expect_owner(),
+ owner_id: hir_id.expect_owner(),
ident: self.lower_ident(ident),
kind,
vis_span,
@@ -539,7 +545,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
let ident = *ident;
let mut path = path.clone();
for seg in &mut path.segments {
- seg.id = self.next_node_id();
+ // Give the cloned segment the same resolution information
+ // as the old one (this is needed for stability checking).
+ let new_id = self.next_node_id();
+ self.resolver.clone_res(seg.id, new_id);
+ seg.id = new_id;
}
let span = path.span;
@@ -552,7 +562,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
- def_id: new_id,
+ owner_id: hir::OwnerId { def_id: new_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@@ -608,7 +618,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
// Give the segments new node-ids since they are being cloned.
for seg in &mut prefix.segments {
- seg.id = self.next_node_id();
+ // Give the cloned segment the same resolution information
+ // as the old one (this is needed for stability checking).
+ let new_id = self.next_node_id();
+ self.resolver.clone_res(seg.id, new_id);
+ seg.id = new_id;
}
// Each `use` import is an item and thus are owners of the
@@ -626,7 +640,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
let item = hir::Item {
- def_id: new_hir_id,
+ owner_id: hir::OwnerId { def_id: new_hir_id },
ident: this.lower_ident(ident),
kind,
vis_span,
@@ -646,10 +660,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> {
let hir_id = self.lower_node_id(i.id);
- let def_id = hir_id.expect_owner();
+ let owner_id = hir_id.expect_owner();
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ForeignItem {
- def_id,
+ owner_id,
ident: self.lower_ident(i.ident),
kind: match i.kind {
ForeignItemKind::Fn(box Fn { ref sig, ref generics, .. }) => {
@@ -688,7 +702,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef {
hir::ForeignItemRef {
- id: hir::ForeignItemId { def_id: self.local_def_id(i.id) },
+ id: hir::ForeignItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
}
@@ -798,7 +812,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
);
(generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
ref generics,
where_clauses,
ref bounds,
@@ -831,7 +845,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_attrs(hir_id, &i.attrs);
let item = hir::TraitItem {
- def_id: trait_item_def_id,
+ owner_id: trait_item_def_id,
ident: self.lower_ident(i.ident),
generics,
kind,
@@ -844,13 +858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
let kind = match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
- AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+ AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
};
- let id = hir::TraitItemId { def_id: self.local_def_id(i.id) };
+ let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } };
hir::TraitItemRef {
id,
ident: self.lower_ident(i.ident),
@@ -892,7 +906,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(generics, hir::ImplItemKind::Fn(sig, body_id))
}
- AssocItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
+ AssocItemKind::Type(box TyAlias { generics, where_clauses, ty, .. }) => {
let mut generics = generics.clone();
add_ty_alias_where_clause(&mut generics, *where_clauses, false);
self.lower_generics(
@@ -902,11 +916,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|this| match ty {
None => {
let ty = this.arena.alloc(this.ty(i.span, hir::TyKind::Err));
- hir::ImplItemKind::TyAlias(ty)
+ hir::ImplItemKind::Type(ty)
}
Some(ty) => {
let ty = this.lower_ty(ty, &ImplTraitContext::TypeAliasesOpaqueTy);
- hir::ImplItemKind::TyAlias(ty)
+ hir::ImplItemKind::Type(ty)
}
},
)
@@ -917,7 +931,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let hir_id = self.lower_node_id(i.id);
self.lower_attrs(hir_id, &i.attrs);
let item = hir::ImplItem {
- def_id: hir_id.expect_owner(),
+ owner_id: hir_id.expect_owner(),
ident: self.lower_ident(i.ident),
generics,
kind,
@@ -930,18 +944,21 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn lower_impl_item_ref(&mut self, i: &AssocItem) -> hir::ImplItemRef {
hir::ImplItemRef {
- id: hir::ImplItemId { def_id: self.local_def_id(i.id) },
+ id: hir::ImplItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } },
ident: self.lower_ident(i.ident),
span: self.lower_span(i.span),
kind: match &i.kind {
AssocItemKind::Const(..) => hir::AssocItemKind::Const,
- AssocItemKind::TyAlias(..) => hir::AssocItemKind::Type,
+ AssocItemKind::Type(..) => hir::AssocItemKind::Type,
AssocItemKind::Fn(box Fn { sig, .. }) => {
hir::AssocItemKind::Fn { has_self: sig.decl.has_self() }
}
AssocItemKind::MacCall(..) => unimplemented!(),
},
- trait_item_def_id: self.resolver.get_partial_res(i.id).map(|r| r.base_res().def_id()),
+ trait_item_def_id: self
+ .resolver
+ .get_partial_res(i.id)
+ .map(|r| r.expect_full_res().def_id()),
}
}
@@ -1049,9 +1066,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
asyncness: Async,
body: Option<&Block>,
) -> hir::BodyId {
- let closure_id = match asyncness {
- Async::Yes { closure_id, .. } => closure_id,
- Async::No => return self.lower_fn_body_block(span, decl, body),
+ let (closure_id, body) = match (asyncness, body) {
+ (Async::Yes { closure_id, .. }, Some(body)) => (closure_id, body),
+ _ => return self.lower_fn_body_block(span, decl, body),
};
self.lower_body(|this| {
@@ -1193,16 +1210,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
parameters.push(new_parameter);
}
- let body_span = body.map_or(span, |b| b.span);
let async_expr = this.make_async_expr(
CaptureBy::Value,
closure_id,
None,
- body_span,
+ body.span,
hir::AsyncGeneratorKind::Fn,
|this| {
// Create a block from the user's function body:
- let user_body = this.lower_block_expr_opt(body_span, body);
+ let user_body = this.lower_block_expr(body);
// Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span =
@@ -1234,7 +1250,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
(
this.arena.alloc_from_iter(parameters),
- this.expr(body_span, async_expr, AttrVec::new()),
+ this.expr(body.span, async_expr, AttrVec::new()),
)
})
}
@@ -1280,10 +1296,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
fn error_on_invalid_abi(&self, abi: StrLit) {
+ let abi_names = abi::enabled_names(self.tcx.features(), abi.span)
+ .iter()
+ .map(|s| Symbol::intern(s))
+ .collect::<Vec<_>>();
+ let suggested_name = find_best_match_for_name(&abi_names, abi.symbol_unescaped, None);
self.tcx.sess.emit_err(InvalidAbi {
+ abi: abi.symbol_unescaped,
span: abi.span,
- abi: abi.symbol,
- valid_abis: abi::all_names().join(", "),
+ suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
+ span: abi.span,
+ suggestion: format!("\"{suggested_name}\""),
+ }),
+ command: "rustc --print=calling-conventions".to_string(),
});
}
@@ -1335,9 +1360,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
match self
.resolver
.get_partial_res(bound_pred.bounded_ty.id)
- .map(|d| (d.base_res(), d.unresolved_segments()))
+ .and_then(|r| r.full_res())
{
- Some((Res::Def(DefKind::TyParam, def_id), 0))
+ Some(Res::Def(DefKind::TyParam, def_id))
if bound_pred.bound_generic_params.is_empty() =>
{
generics
@@ -1464,6 +1489,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
let bounded_ty =
self.ty_path(ty_id, param_span, hir::QPath::Resolved(None, ty_path));
Some(hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ hir_id: self.next_id(),
bounded_ty: self.arena.alloc(bounded_ty),
bounds,
span,
@@ -1494,6 +1520,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ref bounds,
span,
}) => hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ hir_id: self.next_id(),
bound_generic_params: self.lower_generic_params(bound_generic_params),
bounded_ty: self
.lower_ty(bounded_ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Type)),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 9012aa704..ff29d15f1 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -32,7 +32,6 @@
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
@@ -62,8 +61,8 @@ 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_middle::{bug, span_bug};
use rustc_session::parse::feature_err;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DesugaringKind;
@@ -126,7 +125,7 @@ struct LoweringContext<'a, 'hir> {
is_in_trait_impl: bool,
is_in_dyn_type: bool,
- current_hir_id_owner: LocalDefId,
+ 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]>>,
@@ -161,6 +160,10 @@ trait ResolverAstLoweringExt {
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>;
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>;
fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>;
+ // Clones the resolution (if any) on 'source' and applies it
+ // to 'target'. Used when desugaring a `UseTreeKind::Nested` to
+ // multiple `UseTreeKind::Simple`s
+ fn clone_res(&mut self, source: NodeId, target: NodeId);
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
@@ -176,12 +179,7 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
return None;
}
- let partial_res = self.partial_res_map.get(&expr.id)?;
- if partial_res.unresolved_segments() != 0 {
- return None;
- }
-
- if let Res::Def(DefKind::Fn, def_id) = partial_res.base_res() {
+ if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_res()? {
// We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new
// const generics style.
@@ -198,6 +196,12 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
None
}
+ fn clone_res(&mut self, source: NodeId, target: NodeId) {
+ if let Some(res) = self.partial_res_map.get(&source) {
+ self.partial_res_map.insert(target, *res);
+ }
+ }
+
/// Obtains resolution for a `NodeId` with a single resolution.
fn get_partial_res(&self, id: NodeId) -> Option<PartialRes> {
self.partial_res_map.get(&id).copied()
@@ -324,17 +328,20 @@ enum FnDeclKind {
}
impl FnDeclKind {
- fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+ fn impl_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
+ FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
_ => false,
}
}
- fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
+ fn async_fn_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
- FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
+ FnDeclKind::Fn | FnDeclKind::Inherent => true,
+ FnDeclKind::Impl if tcx.features().async_fn_in_trait => true,
+ FnDeclKind::Trait if tcx.features().async_fn_in_trait => true,
_ => false,
}
}
@@ -572,7 +579,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
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, def_id);
+ let current_owner =
+ std::mem::replace(&mut self.current_hir_id_owner, hir::OwnerId { def_id });
let current_local_counter =
std::mem::replace(&mut self.item_local_id_counter, hir::ItemLocalId::new(1));
let current_impl_trait_defs = std::mem::take(&mut self.impl_trait_defs);
@@ -587,7 +595,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug_assert_eq!(_old, None);
let item = f(self);
- debug_assert_eq!(def_id, item.def_id());
+ debug_assert_eq!(def_id, item.def_id().def_id);
// `f` should have consumed all the elements in these vectors when constructing `item`.
debug_assert!(self.impl_trait_defs.is_empty());
debug_assert!(self.impl_trait_bounds.is_empty());
@@ -753,12 +761,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
fn expect_full_res(&mut self, id: NodeId) -> Res<NodeId> {
- self.resolver.get_partial_res(id).map_or(Res::Err, |pr| {
- if pr.unresolved_segments() != 0 {
- panic!("path not fully resolved: {:?}", pr);
- }
- pr.base_res()
- })
+ self.resolver.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res())
}
fn expect_full_res_from_use(&mut self, id: NodeId) -> impl Iterator<Item = Res<NodeId>> {
@@ -786,7 +789,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
/// Mark a span as relative to the current owning item.
fn lower_span(&self, span: Span) -> Span {
if self.tcx.sess.opts.unstable_opts.incremental_relative_spans {
- span.with_parent(Some(self.current_hir_id_owner))
+ span.with_parent(Some(self.current_hir_id_owner.def_id))
} else {
// Do not make spans relative when not using incremental compilation.
span
@@ -812,7 +815,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
LifetimeRes::Fresh { param, .. } => {
// Late resolution delegates to us the creation of the `LocalDefId`.
let _def_id = self.create_def(
- self.current_hir_id_owner,
+ self.current_hir_id_owner.def_id,
param,
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
);
@@ -1060,9 +1063,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
// constructing the HIR for `impl bounds...` and then lowering that.
- let parent_def_id = self.current_hir_id_owner;
let impl_trait_node_id = self.next_node_id();
- self.create_def(parent_def_id, impl_trait_node_id, DefPathData::ImplTrait);
self.with_dyn_type_scope(false, |this| {
let node_id = this.next_node_id();
@@ -1140,8 +1141,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// type and value namespaces. If we resolved the path in the value namespace, we
// transform it into a generic const argument.
TyKind::Path(ref qself, ref path) => {
- if let Some(partial_res) = self.resolver.get_partial_res(ty.id) {
- let res = partial_res.base_res();
+ if let Some(res) = self
+ .resolver
+ .get_partial_res(ty.id)
+ .and_then(|partial_res| partial_res.full_res())
+ {
if !res.matches_ns(Namespace::TypeNS) {
debug!(
"lower_generic_arg: Lowering type argument as const argument: {:?}",
@@ -1154,7 +1158,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let node_id = self.next_node_id();
// Add a definition for the in-band const def.
- self.create_def(parent_def_id, node_id, DefPathData::AnonConst);
+ self.create_def(
+ parent_def_id.def_id,
+ node_id,
+ DefPathData::AnonConst,
+ );
let span = self.lower_span(ty.span);
let path_expr = Expr {
@@ -1204,8 +1212,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// by `ty_path`.
if qself.is_none()
&& let Some(partial_res) = self.resolver.get_partial_res(t.id)
- && partial_res.unresolved_segments() == 0
- && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
+ && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{
let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| {
let poly_trait_ref = this.ast_arena.ptr.alloc(PolyTraitRef {
@@ -1349,9 +1356,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
def_node_id,
bounds,
false,
- &ImplTraitContext::TypeAliasesOpaqueTy,
+ itctx,
),
ImplTraitContext::Universal => {
+ self.create_def(
+ self.current_hir_id_owner.def_id,
+ def_node_id,
+ DefPathData::ImplTrait,
+ );
let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
let (param, bounds, path) =
@@ -1445,7 +1457,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// frequently opened issues show.
let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None);
- let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
+ let opaque_ty_def_id = match origin {
+ hir::OpaqueTyOrigin::TyAlias => self.create_def(
+ self.current_hir_id_owner.def_id,
+ opaque_ty_node_id,
+ DefPathData::ImplTrait,
+ ),
+ hir::OpaqueTyOrigin::FnReturn(fn_def_id) => {
+ self.create_def(fn_def_id, opaque_ty_node_id, DefPathData::ImplTrait)
+ }
+ hir::OpaqueTyOrigin::AsyncFn(..) => bug!("unreachable"),
+ };
debug!(?opaque_ty_def_id);
// Contains the new lifetime definitions created for the TAIT (if any).
@@ -1551,7 +1573,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
debug!(?lifetimes);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
- hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait)
+ hir::TyKind::OpaqueDef(
+ hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
+ lifetimes,
+ in_trait,
+ )
}
/// Registers a new opaque type with the proper `NodeId`s and
@@ -1567,7 +1593,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Generate an `type Foo = impl Trait;` declaration.
trace!("registering opaque type with id {:#?}", opaque_ty_id);
let opaque_ty_item = hir::Item {
- def_id: opaque_ty_id,
+ owner_id: hir::OwnerId { def_id: opaque_ty_id },
ident: Ident::empty(),
kind: opaque_ty_item_kind,
vis_span: self.lower_span(span.shrink_to_lo()),
@@ -1701,62 +1727,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}));
let output = if let Some((ret_id, span)) = make_ret_async {
- match kind {
- FnDeclKind::Trait => {
- if !kind.impl_trait_in_trait_allowed(self.tcx) {
+ if !kind.async_fn_allowed(self.tcx) {
+ match kind {
+ FnDeclKind::Trait | FnDeclKind::Impl => {
self.tcx
.sess
.create_feature_err(
TraitFnAsync { fn_span, span },
- sym::return_position_impl_trait_in_trait,
+ sym::async_fn_in_trait,
)
.emit();
}
- self.lower_async_fn_ret_ty(
- &decl.output,
- fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
- ret_id,
- true,
- )
- }
- _ => {
- if !kind.impl_trait_return_allowed(self.tcx) {
- if kind == FnDeclKind::Impl {
- self.tcx
- .sess
- .create_feature_err(
- TraitFnAsync { fn_span, span },
- sym::return_position_impl_trait_in_trait,
- )
- .emit();
- } else {
- self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
- }
+ _ => {
+ self.tcx.sess.emit_err(TraitFnAsync { fn_span, span });
}
- self.lower_async_fn_ret_ty(
- &decl.output,
- fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
- ret_id,
- false,
- )
}
}
+
+ self.lower_async_fn_ret_ty(
+ &decl.output,
+ fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+ ret_id,
+ matches!(kind, FnDeclKind::Trait),
+ )
} else {
match decl.output {
FnRetTy::Ty(ref ty) => {
let mut context = match fn_node_id {
- Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => {
- let fn_def_id = self.local_def_id(fn_node_id);
- ImplTraitContext::ReturnPositionOpaqueTy {
- origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
- in_trait: false,
- }
- }
- Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => {
+ Some(fn_node_id) if kind.impl_trait_allowed(self.tcx) => {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
- in_trait: true,
+ in_trait: matches!(kind, FnDeclKind::Trait),
}
}
_ => ImplTraitContext::Disallowed(match kind {
@@ -1950,9 +1952,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let future_bound = this.lower_async_fn_output_type_to_future_bound(
output,
span,
- ImplTraitContext::ReturnPositionOpaqueTy {
- origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
- in_trait,
+ if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
+ ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+ } else {
+ ImplTraitContext::ReturnPositionOpaqueTy {
+ origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+ in_trait,
+ }
},
);
@@ -2038,7 +2044,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
let opaque_ty_ref = hir::TyKind::OpaqueDef(
- hir::ItemId { def_id: opaque_ty_def_id },
+ hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
generic_args,
in_trait,
);
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index 1ea76fdbf..1af1633b5 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -239,7 +239,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ident: Ident,
lower_sub: impl FnOnce(&mut Self) -> Option<&'hir hir::Pat<'hir>>,
) -> hir::PatKind<'hir> {
- match self.resolver.get_partial_res(p.id).map(|d| d.base_res()) {
+ match self.resolver.get_partial_res(p.id).map(|d| d.expect_full_res()) {
// `None` can occur in body-less function signatures
res @ (None | Some(Res::Local(_))) => {
let canonical_id = match res {
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 6bb1bb9ea..888776ccc 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -29,11 +29,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
+ let base_res = partial_res.base_res();
+ let unresolved_segments = partial_res.unresolved_segments();
let path_span_lo = p.span.shrink_to_lo();
- let proj_start = p.segments.len() - partial_res.unresolved_segments();
+ let proj_start = p.segments.len() - unresolved_segments;
let path = self.arena.alloc(hir::Path {
- res: self.lower_res(partial_res.base_res()),
+ res: self.lower_res(base_res),
segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
|(i, segment)| {
let param_mode = match (qself_position, param_mode) {
@@ -46,7 +48,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
_ => param_mode,
};
- let parenthesized_generic_args = match partial_res.base_res() {
+ let parenthesized_generic_args = match base_res {
// `a::b::Trait(Args)`
Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
ParenthesizedGenericArgs::Ok
@@ -83,7 +85,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// Simple case, either no projections, or only fully-qualified.
// E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
- if partial_res.unresolved_segments() == 0 {
+ if unresolved_segments == 0 {
return hir::QPath::Resolved(qself, path);
}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index b1d10e07a..036643244 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -14,6 +14,7 @@ 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::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -38,6 +39,13 @@ enum SelfSemantic {
No,
}
+/// What is the context that prevents using `~const`?
+enum DisallowTildeConstContext<'a> {
+ TraitObject,
+ ImplTrait,
+ Fn(FnKind<'a>),
+}
+
struct AstValidator<'a> {
session: &'a Session,
@@ -56,7 +64,7 @@ struct AstValidator<'a> {
/// e.g., `impl Iterator<Item = impl Debug>`.
outer_impl_trait: Option<Span>,
- is_tilde_const_allowed: bool,
+ disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
/// or `Foo::Bar<impl Trait>`
@@ -93,18 +101,26 @@ impl<'a> AstValidator<'a> {
self.is_impl_trait_banned = old;
}
- fn with_tilde_const(&mut self, allowed: bool, f: impl FnOnce(&mut Self)) {
- let old = mem::replace(&mut self.is_tilde_const_allowed, allowed);
+ fn with_tilde_const(
+ &mut self,
+ disallowed: Option<DisallowTildeConstContext<'a>>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
f(self);
- self.is_tilde_const_allowed = old;
+ self.disallow_tilde_const = old;
}
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(true, f)
+ self.with_tilde_const(None, f)
}
- fn with_banned_tilde_const(&mut self, f: impl FnOnce(&mut Self)) {
- self.with_tilde_const(false, f)
+ fn with_banned_tilde_const(
+ &mut self,
+ ctx: DisallowTildeConstContext<'a>,
+ f: impl FnOnce(&mut Self),
+ ) {
+ self.with_tilde_const(Some(ctx), f)
}
fn with_let_management(
@@ -154,7 +170,7 @@ impl<'a> AstValidator<'a> {
DEPRECATED_WHERE_CLAUSE_LOCATION,
id,
where_clauses.0.1,
- fluent::ast_passes::deprecated_where_clause_location,
+ fluent::ast_passes_deprecated_where_clause_location,
BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
where_clauses.1.1.shrink_to_hi(),
suggestion,
@@ -172,7 +188,7 @@ impl<'a> AstValidator<'a> {
fn with_impl_trait(&mut self, outer: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.outer_impl_trait, outer);
if outer.is_some() {
- self.with_banned_tilde_const(f);
+ self.with_banned_tilde_const(DisallowTildeConstContext::ImplTrait, f);
} else {
f(self);
}
@@ -197,7 +213,10 @@ impl<'a> AstValidator<'a> {
TyKind::ImplTrait(..) => {
self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t))
}
- TyKind::TraitObject(..) => self.with_banned_tilde_const(|this| visit::walk_ty(this, t)),
+ TyKind::TraitObject(..) => self
+ .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| {
+ visit::walk_ty(this, t)
+ }),
TyKind::Path(ref qself, ref path) => {
// We allow these:
// - `Option<impl Trait>`
@@ -233,20 +252,6 @@ impl<'a> AstValidator<'a> {
}
}
- fn visit_struct_field_def(&mut self, field: &'a FieldDef) {
- if let Some(ident) = field.ident {
- if ident.name == kw::Underscore {
- self.visit_vis(&field.vis);
- self.visit_ident(ident);
- self.visit_ty_common(&field.ty);
- self.walk_ty(&field.ty);
- walk_list!(self, visit_attribute, &field.attrs);
- return;
- }
- }
- self.visit_field_def(field);
- }
-
fn err_handler(&self) -> &rustc_errors::Handler {
&self.session.diagnostic()
}
@@ -987,8 +992,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
visit::walk_lifetime(self, lifetime);
}
- fn visit_field_def(&mut self, s: &'a FieldDef) {
- visit::walk_field_def(self, s)
+ fn visit_field_def(&mut self, field: &'a FieldDef) {
+ visit::walk_field_def(self, field)
}
fn visit_item(&mut self, item: &'a Item) {
@@ -1176,42 +1181,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
self.check_mod_file_item_asciionly(item.ident);
}
}
- ItemKind::Struct(ref vdata, ref generics) => match vdata {
- // Duplicating the `Visitor` logic allows catching all cases
- // of `Anonymous(Struct, Union)` outside of a field struct or union.
- //
- // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
- // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
- // it uses `visit_ty_common`, which doesn't contain that specific check.
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- },
- ItemKind::Union(ref vdata, ref generics) => {
+ ItemKind::Union(ref vdata, ..) => {
if vdata.fields().is_empty() {
self.err_handler().span_err(item.span, "unions cannot have zero fields");
}
- match vdata {
- VariantData::Struct(ref fields, ..) => {
- self.visit_vis(&item.vis);
- self.visit_ident(item.ident);
- self.visit_generics(generics);
- self.with_banned_assoc_ty_bound(|this| {
- walk_list!(this, visit_struct_field_def, fields);
- });
- walk_list!(self, visit_attribute, &item.attrs);
- return;
- }
- _ => {}
- }
}
ItemKind::Const(def, .., None) => {
self.check_defaultness(item.span, def);
@@ -1411,13 +1384,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
err.emit();
}
- (_, TraitBoundModifier::MaybeConst) => {
- if !self.is_tilde_const_allowed {
- self.err_handler()
- .struct_span_err(bound.span(), "`~const` is not allowed here")
- .note("only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions")
- .emit();
- }
+ (_, 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::ImplTrait => err.note("`impl Trait`s 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"),
+ };
+ err.emit();
}
(_, TraitBoundModifier::MaybeConstMaybe) => {
self.err_handler()
@@ -1524,10 +1499,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
let tilde_const_allowed =
- matches!(fk.header(), Some(FnHeader { constness: Const::Yes(_), .. }))
+ matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
- self.with_tilde_const(tilde_const_allowed, |this| visit::walk_fn(this, fk));
+ let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
+
+ self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
}
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
@@ -1557,7 +1534,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
});
}
}
- AssocItemKind::TyAlias(box TyAlias {
+ AssocItemKind::Type(box TyAlias {
generics,
where_clauses,
where_predicates_split,
@@ -1596,7 +1573,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}
match item.kind {
- AssocItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. })
+ AssocItemKind::Type(box TyAlias { ref generics, ref bounds, ref ty, .. })
if ctxt == AssocCtxt::Trait =>
{
self.visit_vis(&item.vis);
@@ -1771,7 +1748,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
in_const_trait_impl: false,
has_proc_macro_decls: false,
outer_impl_trait: None,
- is_tilde_const_allowed: false,
+ disallow_tilde_const: None,
is_impl_trait_banned: false,
is_assoc_ty_bound_banned: false,
forbidden_let_reason: Some(ForbiddenLetReason::GenericForbidden),
@@ -1783,15 +1760,17 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
}
/// Used to forbid `let` expressions in certain syntactic locations.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Subdiagnostic)]
pub(crate) enum ForbiddenLetReason {
/// `let` is not valid and the source environment is not important
GenericForbidden,
/// A let chain with the `||` operator
- NotSupportedOr(Span),
+ #[note(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
- NotSupportedParentheses(Span),
+ #[note(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 4f3b09c58..59f582f10 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -1,13 +1,13 @@
//! Errors emitted by ast_passes.
-use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::{fluent, AddToDiagnostic, Applicability, Diagnostic, SubdiagnosticMessage};
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
use crate::ast_validation::ForbiddenLetReason;
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_let)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let)]
#[note]
pub struct ForbiddenLet {
#[primary_span]
@@ -16,130 +16,116 @@ pub struct ForbiddenLet {
pub(crate) reason: ForbiddenLetReason,
}
-impl AddSubdiagnostic for ForbiddenLetReason {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
- match self {
- Self::GenericForbidden => {}
- Self::NotSupportedOr(span) => {
- diag.span_note(span, fluent::ast_passes::not_supported_or);
- }
- Self::NotSupportedParentheses(span) => {
- diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
- }
- }
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_let_stable)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_let_stable)]
#[note]
pub struct ForbiddenLetStable {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_assoc_constraint)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_assoc_constraint)]
pub struct ForbiddenAssocConstraint {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::keyword_lifetime)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_keyword_lifetime)]
pub struct KeywordLifetime {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::invalid_label)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_invalid_label)]
pub struct InvalidLabel {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::invalid_visibility, code = "E0449")]
+#[derive(Diagnostic)]
+#[diag(ast_passes_invalid_visibility, code = "E0449")]
pub struct InvalidVisibility {
#[primary_span]
pub span: Span,
- #[label(ast_passes::implied)]
+ #[label(implied)]
pub implied: Option<Span>,
#[subdiagnostic]
pub note: Option<InvalidVisibilityNote>,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum InvalidVisibilityNote {
- #[note(ast_passes::individual_impl_items)]
+ #[note(individual_impl_items)]
IndividualImplItems,
- #[note(ast_passes::individual_foreign_items)]
+ #[note(individual_foreign_items)]
IndividualForeignItems,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::trait_fn_const, code = "E0379")]
+#[derive(Diagnostic)]
+#[diag(ast_passes_trait_fn_const, code = "E0379")]
pub struct TraitFnConst {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_lifetime_bound)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_lifetime_bound)]
pub struct ForbiddenLifetimeBound {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_non_lifetime_param)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_non_lifetime_param)]
pub struct ForbiddenNonLifetimeParam {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_too_many)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_too_many)]
pub struct FnParamTooMany {
#[primary_span]
pub span: Span,
pub max_num_args: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_only)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_c_var_args_only)]
pub struct FnParamCVarArgsOnly {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_c_var_args_not_last)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_c_var_args_not_last)]
pub struct FnParamCVarArgsNotLast {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_doc_comment)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_doc_comment)]
pub struct FnParamDocComment {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_forbidden_attr)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_attr)]
pub struct FnParamForbiddenAttr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_param_forbidden_self)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_param_forbidden_self)]
#[note]
pub struct FnParamForbiddenSelf {
#[primary_span]
@@ -147,8 +133,8 @@ pub struct FnParamForbiddenSelf {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::forbidden_default)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_forbidden_default)]
pub struct ForbiddenDefault {
#[primary_span]
pub span: Span,
@@ -156,8 +142,8 @@ pub struct ForbiddenDefault {
pub def_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_const_without_body)]
pub struct AssocConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -165,8 +151,8 @@ pub struct AssocConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_fn_without_body)]
pub struct AssocFnWithoutBody {
#[primary_span]
pub span: Span,
@@ -174,8 +160,8 @@ pub struct AssocFnWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::assoc_type_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_assoc_type_without_body)]
pub struct AssocTypeWithoutBody {
#[primary_span]
pub span: Span,
@@ -183,8 +169,8 @@ pub struct AssocTypeWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::const_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_const_without_body)]
pub struct ConstWithoutBody {
#[primary_span]
pub span: Span,
@@ -192,8 +178,8 @@ pub struct ConstWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::static_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_static_without_body)]
pub struct StaticWithoutBody {
#[primary_span]
pub span: Span,
@@ -201,8 +187,8 @@ pub struct StaticWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::ty_alias_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_ty_alias_without_body)]
pub struct TyAliasWithoutBody {
#[primary_span]
pub span: Span,
@@ -210,8 +196,8 @@ pub struct TyAliasWithoutBody {
pub replace_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(ast_passes::fn_without_body)]
+#[derive(Diagnostic)]
+#[diag(ast_passes_fn_without_body)]
pub struct FnWithoutBody {
#[primary_span]
pub span: Span,
@@ -227,8 +213,11 @@ pub struct ExternBlockSuggestion {
pub abi: Option<Symbol>,
}
-impl AddSubdiagnostic for ExternBlockSuggestion {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+impl AddToDiagnostic for ExternBlockSuggestion {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
let start_suggestion = if let Some(abi) = self.abi {
format!("extern \"{}\" {{", abi)
} else {
@@ -237,7 +226,7 @@ impl AddSubdiagnostic for ExternBlockSuggestion {
let end_suggestion = " }".to_owned();
diag.multipart_suggestion(
- fluent::ast_passes::extern_block_suggestion,
+ fluent::extern_block_suggestion,
vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
Applicability::MaybeIncorrect,
);
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index aeff73c5b..546010135 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,15 +1,15 @@
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, VariantData};
+use rustc_ast::{PatKind, RangeEnd};
use rustc_errors::{struct_span_err, Applicability, StashKey};
-use rustc_feature::Features;
-use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-use rustc_session::parse::{feature_err, feature_warn};
+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;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
+use rustc_target::spec::abi;
macro_rules! gate_feature_fn {
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
@@ -84,210 +84,26 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- match symbol_unescaped.as_str() {
- // Stable
- "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
- | "system" => {}
- "rust-intrinsic" => {
- gate_feature_post!(&self, intrinsics, span, "intrinsics are subject to change");
- }
- "platform-intrinsic" => {
- gate_feature_post!(
- &self,
- platform_intrinsics,
- span,
- "platform intrinsics are experimental and possibly buggy"
- );
- }
- "vectorcall" => {
- gate_feature_post!(
- &self,
- abi_vectorcall,
- span,
- "vectorcall is experimental and subject to change"
- );
- }
- "thiscall" => {
- gate_feature_post!(
- &self,
- abi_thiscall,
- span,
- "thiscall is experimental and subject to change"
- );
- }
- "rust-call" => {
- gate_feature_post!(
- &self,
- unboxed_closures,
- span,
- "rust-call ABI is subject to change"
- );
- }
- "rust-cold" => {
- gate_feature_post!(
- &self,
- rust_cold_cc,
- span,
- "rust-cold is experimental and subject to change"
- );
- }
- "ptx-kernel" => {
- gate_feature_post!(
- &self,
- abi_ptx,
- span,
- "PTX ABIs are experimental and subject to change"
- );
- }
- "unadjusted" => {
- gate_feature_post!(
- &self,
- abi_unadjusted,
- span,
- "unadjusted ABI is an implementation detail and perma-unstable"
- );
- }
- "msp430-interrupt" => {
- gate_feature_post!(
- &self,
- abi_msp430_interrupt,
- span,
- "msp430-interrupt ABI is experimental and subject to change"
- );
- }
- "x86-interrupt" => {
- gate_feature_post!(
- &self,
- abi_x86_interrupt,
- span,
- "x86-interrupt ABI is experimental and subject to change"
- );
- }
- "amdgpu-kernel" => {
- gate_feature_post!(
- &self,
- abi_amdgpu_kernel,
- span,
- "amdgpu-kernel ABI is experimental and subject to change"
- );
- }
- "avr-interrupt" | "avr-non-blocking-interrupt" => {
- gate_feature_post!(
- &self,
- abi_avr_interrupt,
- span,
- "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change"
- );
- }
- "efiapi" => {
- gate_feature_post!(
- &self,
- abi_efiapi,
- span,
- "efiapi ABI is experimental and subject to change"
- );
- }
- "C-cmse-nonsecure-call" => {
- gate_feature_post!(
- &self,
- abi_c_cmse_nonsecure_call,
+ match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) {
+ Ok(()) => (),
+ Err(abi::AbiDisabled::Unstable { feature, explain }) => {
+ feature_err_issue(
+ &self.sess.parse_sess,
+ feature,
span,
- "C-cmse-nonsecure-call ABI is experimental and subject to change"
- );
- }
- "C-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "C-unwind ABI is experimental and subject to change"
- );
- }
- "stdcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "stdcall-unwind ABI is experimental and subject to change"
- );
- }
- "system-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "system-unwind ABI is experimental and subject to change"
- );
- }
- "thiscall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "thiscall-unwind ABI is experimental and subject to change"
- );
- }
- "cdecl-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "cdecl-unwind ABI is experimental and subject to change"
- );
- }
- "fastcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "fastcall-unwind ABI is experimental and subject to change"
- );
- }
- "vectorcall-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "vectorcall-unwind ABI is experimental and subject to change"
- );
- }
- "aapcs-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "aapcs-unwind ABI is experimental and subject to change"
- );
- }
- "win64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "win64-unwind ABI is experimental and subject to change"
- );
- }
- "sysv64-unwind" => {
- gate_feature_post!(
- &self,
- c_unwind,
- span,
- "sysv64-unwind ABI is experimental and subject to change"
- );
- }
- "wasm" => {
- gate_feature_post!(
- &self,
- wasm_abi,
- span,
- "wasm ABI is experimental and subject to change"
- );
+ GateIssue::Language,
+ explain,
+ )
+ .emit();
}
- abi => {
+ Err(abi::AbiDisabled::Unrecognized) => {
if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) {
self.sess.parse_sess.span_diagnostic.delay_span_bug(
span,
- &format!("unrecognized ABI not caught in lowering: {}", abi),
+ &format!(
+ "unrecognized ABI not caught in lowering: {}",
+ symbol_unescaped.as_str()
+ ),
);
}
}
@@ -300,46 +116,6 @@ impl<'a> PostExpansionVisitor<'a> {
}
}
- fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) {
- let has_fields = variants.iter().any(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => true,
- VariantData::Unit(..) => false,
- });
-
- let discriminant_spans = variants
- .iter()
- .filter(|variant| match variant.data {
- VariantData::Tuple(..) | VariantData::Struct(..) => false,
- VariantData::Unit(..) => true,
- })
- .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span))
- .collect::<Vec<_>>();
-
- if !discriminant_spans.is_empty() && has_fields {
- let mut err = feature_err(
- &self.sess.parse_sess,
- sym::arbitrary_enum_discriminant,
- discriminant_spans.clone(),
- "custom discriminant values are not allowed in enums with tuple or struct variants",
- );
- for sp in discriminant_spans {
- err.span_label(sp, "disallowed custom discriminant");
- }
- for variant in variants.iter() {
- match &variant.data {
- VariantData::Struct(..) => {
- err.span_label(variant.span, "struct variant defined here");
- }
- VariantData::Tuple(..) => {
- err.span_label(variant.span, "tuple variant defined here");
- }
- VariantData::Unit(..) => {}
- }
- }
- err.emit();
- }
- }
-
/// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
fn check_impl_trait(&self, ty: &ast::Ty) {
struct ImplTraitVisitor<'a> {
@@ -457,26 +233,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
- ast::ItemKind::Enum(ast::EnumDef { ref variants, .. }, ..) => {
- for variant in variants {
- match (&variant.data, &variant.disr_expr) {
- (ast::VariantData::Unit(..), _) => {}
- (_, Some(disr_expr)) => gate_feature_post!(
- &self,
- arbitrary_enum_discriminant,
- disr_expr.value.span,
- "discriminants on non-unit variants are experimental"
- ),
- _ => {}
- }
- }
-
- let has_feature = self.features.arbitrary_enum_discriminant;
- if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) {
- self.maybe_report_invalid_custom_discriminants(&variants);
- }
- }
-
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, ref of_trait, .. }) => {
if let ast::ImplPolarity::Negative(span) = polarity {
gate_feature_post!(
@@ -645,7 +401,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
gate_feature_post!(
&self,
- half_open_range_patterns,
+ half_open_range_patterns_in_slices,
pat.span,
"`X..` patterns in slices are experimental"
);
@@ -701,7 +457,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
let is_fn = match i.kind {
ast::AssocItemKind::Fn(_) => true,
- ast::AssocItemKind::TyAlias(box ast::TyAlias { ref ty, .. }) => {
+ ast::AssocItemKind::Type(box ast::TyAlias { ref ty, .. }) => {
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
gate_feature_post!(
&self,
@@ -773,7 +529,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
gate_all!(generators, "yield syntax is experimental");
gate_all!(raw_ref_op, "raw address of syntax is experimental");
gate_all!(const_trait_impl, "const trait impls are experimental");
- gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
+ gate_all!(
+ half_open_range_patterns_in_slices,
+ "half-open range patterns in slices are unstable"
+ );
gate_all!(inline_const, "inline-const is experimental");
gate_all!(inline_const_pat, "inline-const in pattern position is experimental");
gate_all!(associated_const_equality, "associated const equality is incomplete");
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 8aa9d57f0..f58fffc91 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -9,7 +9,6 @@
#![feature(if_let_guard)]
#![feature(iter_is_partitioned)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#[macro_use]
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index 5ad8714e9..a3e3e823b 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index ead38caee..bcefa8ce0 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -193,9 +193,13 @@ impl<'a> State<'a> {
self.print_call_post(args)
}
- fn print_expr_method_call(&mut self, segment: &ast::PathSegment, args: &[P<ast::Expr>]) {
- let base_args = &args[1..];
- self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX);
+ fn print_expr_method_call(
+ &mut self,
+ segment: &ast::PathSegment,
+ receiver: &ast::Expr,
+ base_args: &[P<ast::Expr>],
+ ) {
+ self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
self.word(".");
self.print_ident(segment.ident);
if let Some(ref args) = segment.args {
@@ -303,8 +307,8 @@ impl<'a> State<'a> {
ast::ExprKind::Call(ref func, ref args) => {
self.print_expr_call(func, &args);
}
- ast::ExprKind::MethodCall(ref segment, ref args, _) => {
- self.print_expr_method_call(segment, &args);
+ ast::ExprKind::MethodCall(ref segment, ref receiver, ref args, _) => {
+ self.print_expr_method_call(segment, &receiver, &args);
}
ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
self.print_expr_binary(op, lhs, rhs);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index 54bac29a6..159853c9e 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -516,7 +516,7 @@ impl<'a> State<'a> {
ast::AssocItemKind::Const(def, ty, body) => {
self.print_item_const(ident, None, ty, body.as_deref(), vis, *def);
}
- ast::AssocItemKind::TyAlias(box ast::TyAlias {
+ ast::AssocItemKind::Type(box ast::TyAlias {
defaultness,
generics,
where_clauses,
diff --git a/compiler/rustc_attr/Cargo.toml b/compiler/rustc_attr/Cargo.toml
index ba310a686..6349ddf31 100644
--- a/compiler/rustc_attr/Cargo.toml
+++ b/compiler/rustc_attr/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_attr/src/lib.rs b/compiler/rustc_attr/src/lib.rs
index 52e65a9c7..4580ffcc6 100644
--- a/compiler/rustc_attr/src/lib.rs
+++ b/compiler/rustc_attr/src/lib.rs
@@ -5,7 +5,6 @@
//! to this crate.
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 085175d4b..edccfa1c8 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -2,23 +2,22 @@ use std::num::IntErrorKind;
use rustc_ast as ast;
use rustc_errors::{
- error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler,
+ error_code, fluent, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
};
-use rustc_macros::SessionDiagnostic;
-use rustc_session::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use crate::UnsupportedLiteralReason;
-#[derive(SessionDiagnostic)]
-#[diag(attr::expected_one_cfg_pattern, code = "E0536")]
+#[derive(Diagnostic)]
+#[diag(attr_expected_one_cfg_pattern, code = "E0536")]
pub(crate) struct ExpectedOneCfgPattern {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_predicate, code = "E0537")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_predicate, code = "E0537")]
pub(crate) struct InvalidPredicate {
#[primary_span]
pub span: Span,
@@ -26,8 +25,8 @@ pub(crate) struct InvalidPredicate {
pub predicate: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::multiple_item, code = "E0538")]
+#[derive(Diagnostic)]
+#[diag(attr_multiple_item, code = "E0538")]
pub(crate) struct MultipleItem {
#[primary_span]
pub span: Span,
@@ -35,8 +34,8 @@ pub(crate) struct MultipleItem {
pub item: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::incorrect_meta_item, code = "E0539")]
+#[derive(Diagnostic)]
+#[diag(attr_incorrect_meta_item, code = "E0539")]
pub(crate) struct IncorrectMetaItem {
#[primary_span]
pub span: Span,
@@ -50,44 +49,44 @@ pub(crate) struct UnknownMetaItem<'a> {
}
// Manual implementation to be able to format `expected` items correctly.
-impl<'a> SessionDiagnostic<'a> for UnknownMetaItem<'_> {
+impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::<Vec<_>>();
let mut diag = handler.struct_span_err_with_code(
self.span,
- fluent::attr::unknown_meta_item,
+ fluent::attr_unknown_meta_item,
error_code!(E0541),
);
diag.set_arg("item", self.item);
diag.set_arg("expected", expected.join(", "));
- diag.span_label(self.span, fluent::attr::label);
+ diag.span_label(self.span, fluent::label);
diag
}
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::missing_since, code = "E0542")]
+#[derive(Diagnostic)]
+#[diag(attr_missing_since, code = "E0542")]
pub(crate) struct MissingSince {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::missing_note, code = "E0543")]
+#[derive(Diagnostic)]
+#[diag(attr_missing_note, code = "E0543")]
pub(crate) struct MissingNote {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::multiple_stability_levels, code = "E0544")]
+#[derive(Diagnostic)]
+#[diag(attr_multiple_stability_levels, code = "E0544")]
pub(crate) struct MultipleStabilityLevels {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_issue_string, code = "E0545")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_issue_string, code = "E0545")]
pub(crate) struct InvalidIssueString {
#[primary_span]
pub span: Span,
@@ -98,33 +97,33 @@ pub(crate) struct InvalidIssueString {
// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be
// translatable.
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum InvalidIssueStringCause {
- #[label(attr::must_not_be_zero)]
+ #[label(must_not_be_zero)]
MustNotBeZero {
#[primary_span]
span: Span,
},
- #[label(attr::empty)]
+ #[label(empty)]
Empty {
#[primary_span]
span: Span,
},
- #[label(attr::invalid_digit)]
+ #[label(invalid_digit)]
InvalidDigit {
#[primary_span]
span: Span,
},
- #[label(attr::pos_overflow)]
+ #[label(pos_overflow)]
PosOverflow {
#[primary_span]
span: Span,
},
- #[label(attr::neg_overflow)]
+ #[label(neg_overflow)]
NegOverflow {
#[primary_span]
span: Span,
@@ -144,22 +143,22 @@ impl InvalidIssueStringCause {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::missing_feature, code = "E0546")]
+#[derive(Diagnostic)]
+#[diag(attr_missing_feature, code = "E0546")]
pub(crate) struct MissingFeature {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::non_ident_feature, code = "E0546")]
+#[derive(Diagnostic)]
+#[diag(attr_non_ident_feature, code = "E0546")]
pub(crate) struct NonIdentFeature {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::missing_issue, code = "E0547")]
+#[derive(Diagnostic)]
+#[diag(attr_missing_issue, code = "E0547")]
pub(crate) struct MissingIssue {
#[primary_span]
pub span: Span,
@@ -167,8 +166,8 @@ pub(crate) struct MissingIssue {
// FIXME: This diagnostic is identical to `IncorrectMetaItem`, barring the error code. Consider
// changing this to `IncorrectMetaItem`. See #51489.
-#[derive(SessionDiagnostic)]
-#[diag(attr::incorrect_meta_item, code = "E0551")]
+#[derive(Diagnostic)]
+#[diag(attr_incorrect_meta_item, code = "E0551")]
pub(crate) struct IncorrectMetaItem2 {
#[primary_span]
pub span: Span,
@@ -176,15 +175,15 @@ pub(crate) struct IncorrectMetaItem2 {
// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
// It is more similar to `IncorrectReprFormatGeneric`.
-#[derive(SessionDiagnostic)]
-#[diag(attr::incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
+#[derive(Diagnostic)]
+#[diag(attr_incorrect_repr_format_packed_one_or_zero_arg, code = "E0552")]
pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_repr_hint_no_paren, code = "E0552")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_repr_hint_no_paren, code = "E0552")]
pub(crate) struct InvalidReprHintNoParen {
#[primary_span]
pub span: Span,
@@ -192,8 +191,8 @@ pub(crate) struct InvalidReprHintNoParen {
pub name: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_repr_hint_no_value, code = "E0552")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_repr_hint_no_value, code = "E0552")]
pub(crate) struct InvalidReprHintNoValue {
#[primary_span]
pub span: Span,
@@ -209,18 +208,18 @@ pub(crate) struct UnsupportedLiteral {
pub start_point_span: Span,
}
-impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
+impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut diag = handler.struct_span_err_with_code(
self.span,
match self.reason {
- UnsupportedLiteralReason::Generic => fluent::attr::unsupported_literal_generic,
- UnsupportedLiteralReason::CfgString => fluent::attr::unsupported_literal_cfg_string,
+ UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic,
+ UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string,
UnsupportedLiteralReason::DeprecatedString => {
- fluent::attr::unsupported_literal_deprecated_string
+ fluent::attr_unsupported_literal_deprecated_string
}
UnsupportedLiteralReason::DeprecatedKvPair => {
- fluent::attr::unsupported_literal_deprecated_kv_pair
+ fluent::attr_unsupported_literal_deprecated_kv_pair
}
},
error_code!(E0565),
@@ -228,7 +227,7 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
if self.is_bytestr {
diag.span_suggestion(
self.start_point_span,
- fluent::attr::unsupported_literal_suggestion,
+ fluent::attr_unsupported_literal_suggestion,
"",
Applicability::MaybeIncorrect,
);
@@ -237,16 +236,16 @@ impl<'a> SessionDiagnostic<'a> for UnsupportedLiteral {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_repr_align_need_arg, code = "E0589")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_repr_align_need_arg, code = "E0589")]
pub(crate) struct InvalidReprAlignNeedArg {
#[primary_span]
#[suggestion(code = "align(...)", applicability = "has-placeholders")]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::invalid_repr_generic, code = "E0589")]
+#[derive(Diagnostic)]
+#[diag(attr_invalid_repr_generic, code = "E0589")]
pub(crate) struct InvalidReprGeneric<'a> {
#[primary_span]
pub span: Span,
@@ -255,15 +254,15 @@ pub(crate) struct InvalidReprGeneric<'a> {
pub error_part: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::incorrect_repr_format_align_one_arg, code = "E0693")]
+#[derive(Diagnostic)]
+#[diag(attr_incorrect_repr_format_align_one_arg, code = "E0693")]
pub(crate) struct IncorrectReprFormatAlignOneArg {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::incorrect_repr_format_generic, code = "E0693")]
+#[derive(Diagnostic)]
+#[diag(attr_incorrect_repr_format_generic, code = "E0693")]
pub(crate) struct IncorrectReprFormatGeneric<'a> {
#[primary_span]
pub span: Span,
@@ -274,9 +273,9 @@ pub(crate) struct IncorrectReprFormatGeneric<'a> {
pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum IncorrectReprFormatGenericCause<'a> {
- #[suggestion(attr::suggestion, code = "{name}({int})", applicability = "machine-applicable")]
+ #[suggestion(suggestion, code = "{name}({int})", applicability = "machine-applicable")]
Int {
#[primary_span]
span: Span,
@@ -288,11 +287,7 @@ pub(crate) enum IncorrectReprFormatGenericCause<'a> {
int: u128,
},
- #[suggestion(
- attr::suggestion,
- code = "{name}({symbol})",
- applicability = "machine-applicable"
- )]
+ #[suggestion(suggestion, code = "{name}({symbol})", applicability = "machine-applicable")]
Symbol {
#[primary_span]
span: Span,
@@ -317,29 +312,29 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::rustc_promotable_pairing, code = "E0717")]
+#[derive(Diagnostic)]
+#[diag(attr_rustc_promotable_pairing, code = "E0717")]
pub(crate) struct RustcPromotablePairing {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::rustc_allowed_unstable_pairing, code = "E0789")]
+#[derive(Diagnostic)]
+#[diag(attr_rustc_allowed_unstable_pairing, code = "E0789")]
pub(crate) struct RustcAllowedUnstablePairing {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::cfg_predicate_identifier)]
+#[derive(Diagnostic)]
+#[diag(attr_cfg_predicate_identifier)]
pub(crate) struct CfgPredicateIdentifier {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::deprecated_item_suggestion)]
+#[derive(Diagnostic)]
+#[diag(attr_deprecated_item_suggestion)]
pub(crate) struct DeprecatedItemSuggestion {
#[primary_span]
pub span: Span,
@@ -351,22 +346,22 @@ pub(crate) struct DeprecatedItemSuggestion {
pub details: (),
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::expected_single_version_literal)]
+#[derive(Diagnostic)]
+#[diag(attr_expected_single_version_literal)]
pub(crate) struct ExpectedSingleVersionLiteral {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::expected_version_literal)]
+#[derive(Diagnostic)]
+#[diag(attr_expected_version_literal)]
pub(crate) struct ExpectedVersionLiteral {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::expects_feature_list)]
+#[derive(Diagnostic)]
+#[diag(attr_expects_feature_list)]
pub(crate) struct ExpectsFeatureList {
#[primary_span]
pub span: Span,
@@ -374,8 +369,8 @@ pub(crate) struct ExpectsFeatureList {
pub name: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::expects_features)]
+#[derive(Diagnostic)]
+#[diag(attr_expects_features)]
pub(crate) struct ExpectsFeatures {
#[primary_span]
pub span: Span,
@@ -383,15 +378,15 @@ pub(crate) struct ExpectsFeatures {
pub name: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::soft_no_args)]
+#[derive(Diagnostic)]
+#[diag(attr_soft_no_args)]
pub(crate) struct SoftNoArgs {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(attr::unknown_version_literal)]
+#[derive(Diagnostic)]
+#[diag(attr_unknown_version_literal)]
pub(crate) struct UnknownVersionLiteral {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index fbf628e86..87c113f3e 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
either = "1.5.0"
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index 144fd15fc..f185e402f 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -14,8 +14,8 @@ use crate::{
places_conflict, region_infer::values::LivenessValues,
};
-pub(super) fn generate_constraints<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+pub(super) fn generate_constraints<'tcx>(
+ infcx: &InferCtxt<'tcx>,
liveness_constraints: &mut LivenessValues<RegionVid>,
all_facts: &mut Option<AllFacts>,
location_table: &LocationTable,
@@ -37,8 +37,8 @@ pub(super) fn generate_constraints<'cx, 'tcx>(
}
/// 'cg = the duration of the constraint generation process itself.
-struct ConstraintGeneration<'cg, 'cx, 'tcx> {
- infcx: &'cg InferCtxt<'cx, 'tcx>,
+struct ConstraintGeneration<'cg, 'tcx> {
+ infcx: &'cg InferCtxt<'tcx>,
all_facts: &'cg mut Option<AllFacts>,
location_table: &'cg LocationTable,
liveness_constraints: &'cg mut LivenessValues<RegionVid>,
@@ -46,7 +46,7 @@ struct ConstraintGeneration<'cg, 'cx, 'tcx> {
body: &'cg Body<'tcx>,
}
-impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
+impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> {
fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
self.super_basic_block_data(bb, data);
}
@@ -156,7 +156,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
}
}
-impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
+impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
/// Some variable with type `live_ty` is "regular live" at
/// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index efc17a173..b162095f8 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -31,9 +31,8 @@ pub fn get_body_with_borrowck_facts<'tcx>(
def: ty::WithOptConstParam<LocalDefId>,
) -> BodyWithBorrowckFacts<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
- tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).enter(|infcx| {
- let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexVec<_, _> = &promoted.borrow();
- *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
- })
+ let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def.did)).build();
+ let input_body: &Body<'_> = &input_body.borrow();
+ let promoted: &IndexVec<_, _> = &promoted.borrow();
+ *super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index b1def1892..02071ed6b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -56,7 +56,7 @@ impl<'tcx> UniverseInfo<'tcx> {
) {
match self.0 {
UniverseInfoInner::RelateTys { expected, found } => {
- let err = mbcx.infcx.report_mismatched_types(
+ let err = mbcx.infcx.err_ctxt().report_mismatched_types(
&cause,
expected,
found,
@@ -238,20 +238,11 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -288,37 +279,24 @@ where
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
- let mut selcx = SelectionContext::new(infcx);
-
- // FIXME(lqd): Unify and de-duplicate the following with the actual
- // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
- // `ObligationCause`. The normalization results are currently different between
- // `AtExt::normalize` used in the query and `normalize` called below: the former fails
- // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
- // after #85499 lands to see if its fixes have erased this difference.
- let (param_env, value) = key.into_parts();
- let Normalized { value: _, obligations } = rustc_trait_selection::traits::normalize(
- &mut selcx,
- param_env,
- cause,
- value.value,
- );
- fulfill_cx.register_predicate_obligations(infcx, obligations);
-
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+
+ let mut selcx = SelectionContext::new(infcx);
+
+ // FIXME(lqd): Unify and de-duplicate the following with the actual
+ // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
+ // `ObligationCause`. The normalization results are currently different between
+ // `AtExt::normalize` used in the query and `normalize` called below: the former fails
+ // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
+ // after #85499 lands to see if its fixes have erased this difference.
+ let (param_env, value) = key.into_parts();
+ let Normalized { value: _, obligations } =
+ rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value);
+ fulfill_cx.register_predicate_obligations(infcx, obligations);
+
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -349,21 +327,11 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- mbcx.infcx.tcx.infer_ctxt().enter_with_canonical(
- cause.span,
- &self.canonical_query,
- |ref infcx, key, _| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span))
- .ok()?;
- try_extract_error_from_fulfill_cx(
- fulfill_cx,
- infcx,
- placeholder_region,
- error_region,
- )
- },
- )
+ let (ref infcx, key, _) =
+ mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?;
+ try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
}
}
@@ -407,7 +375,7 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
#[instrument(skip(fulfill_cx, infcx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>(
mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
@@ -427,7 +395,7 @@ fn try_extract_error_from_fulfill_cx<'tcx>(
}
fn try_extract_error_from_region_constraints<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
region_constraints: &RegionConstraintData<'tcx>,
@@ -449,42 +417,38 @@ fn try_extract_error_from_region_constraints<'tcx>(
})?;
debug!(?sub_region, "cause = {:#?}", cause);
- let nice_error = match (error_region, *sub_region) {
- (Some(error_region), ty::ReVar(vid)) => NiceRegionError::new(
- infcx,
- RegionResolutionError::SubSupConflict(
- vid,
- region_var_origin(vid),
- cause.clone(),
- error_region,
- cause.clone(),
- placeholder_region,
- vec![],
- ),
- ),
- (Some(error_region), _) => NiceRegionError::new(
- infcx,
- RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region),
+ let error = match (error_region, *sub_region) {
+ (Some(error_region), ty::ReVar(vid)) => RegionResolutionError::SubSupConflict(
+ vid,
+ region_var_origin(vid),
+ cause.clone(),
+ error_region,
+ cause.clone(),
+ placeholder_region,
+ vec![],
),
+ (Some(error_region), _) => {
+ RegionResolutionError::ConcreteFailure(cause.clone(), error_region, placeholder_region)
+ }
// Note universe here is wrong...
- (None, ty::ReVar(vid)) => NiceRegionError::new(
- infcx,
- RegionResolutionError::UpperBoundUniverseConflict(
- vid,
- region_var_origin(vid),
- universe_of_region(vid),
- cause.clone(),
- placeholder_region,
- ),
- ),
- (None, _) => NiceRegionError::new(
- infcx,
- RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region),
+ (None, ty::ReVar(vid)) => RegionResolutionError::UpperBoundUniverseConflict(
+ vid,
+ region_var_origin(vid),
+ universe_of_region(vid),
+ cause.clone(),
+ placeholder_region,
),
+ (None, _) => {
+ RegionResolutionError::ConcreteFailure(cause.clone(), sub_region, placeholder_region)
+ }
};
- nice_error.try_report_from_nll().or_else(|| {
+ NiceRegionError::new(&infcx.err_ctxt(), error).try_report_from_nll().or_else(|| {
if let SubregionOrigin::Subtype(trace) = cause {
- Some(infcx.report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch))
+ Some(
+ infcx
+ .err_ctxt()
+ .report_and_explain_type_error(*trace, TypeError::RegionsPlaceholderMismatch),
+ )
} else {
None
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index f2204c242..583bc2e28 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
-use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
@@ -198,7 +198,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span,
move_spans,
*moved_place,
- Some(used_place),
partially_str,
loop_message,
move_msg,
@@ -369,6 +368,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut visitor = ConditionVisitor { spans: &spans, name: &name, errors: vec![] };
visitor.visit_body(&body);
+ let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action
{
@@ -396,6 +396,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.count()
== 0
{
+ show_assign_sugg = true;
"isn't initialized"
} else {
"is possibly-uninitialized"
@@ -446,10 +447,84 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
}
+
err.span_label(decl_span, "binding declared here but left uninitialized");
+ if show_assign_sugg {
+ struct LetVisitor {
+ decl_span: Span,
+ sugg_span: Option<Span>,
+ }
+
+ impl<'v> Visitor<'v> for LetVisitor {
+ fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+ if self.sugg_span.is_some() {
+ return;
+ }
+ if let hir::StmtKind::Local(hir::Local {
+ span, ty, init: None, ..
+ }) = &ex.kind && span.contains(self.decl_span) {
+ self.sugg_span = ty.map_or(Some(self.decl_span), |ty| Some(ty.span));
+ }
+ hir::intravisit::walk_stmt(self, ex);
+ }
+ }
+
+ let mut visitor = LetVisitor { decl_span, sugg_span: None };
+ visitor.visit_body(&body);
+ if let Some(span) = visitor.sugg_span {
+ self.suggest_assign_value(&mut err, moved_place, span);
+ }
+ }
err
}
+ fn suggest_assign_value(
+ &self,
+ err: &mut Diagnostic,
+ moved_place: PlaceRef<'tcx>,
+ sugg_span: Span,
+ ) {
+ let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
+ debug!("ty: {:?}, kind: {:?}", ty, ty.kind());
+
+ let tcx = self.infcx.tcx;
+ let implements_default = |ty, param_env| {
+ let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
+ return false;
+ };
+ // Regions are already solved, so we must use a fresh InferCtxt,
+ // but the type has region variables, so erase those.
+ tcx.infer_ctxt()
+ .build()
+ .type_implements_trait(
+ default_trait,
+ tcx.erase_regions(ty),
+ ty::List::empty(),
+ param_env,
+ )
+ .must_apply_modulo_regions()
+ };
+
+ let assign_value = match ty.kind() {
+ ty::Bool => "false",
+ ty::Float(_) => "0.0",
+ ty::Int(_) | ty::Uint(_) => "0",
+ ty::Never | ty::Error(_) => "",
+ ty::Adt(def, _) if Some(def.did()) == tcx.get_diagnostic_item(sym::Vec) => "vec![]",
+ ty::Adt(_, _) if implements_default(ty, self.param_env) => "Default::default()",
+ _ => "todo!()",
+ };
+
+ if !assign_value.is_empty() {
+ err.span_suggestion_verbose(
+ sugg_span.shrink_to_hi(),
+ format!("consider assigning a value"),
+ format!(" = {}", assign_value),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+
fn suggest_borrow_fn_like(
&self,
err: &mut Diagnostic,
@@ -537,41 +612,40 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.and_then(|def_id| tcx.hir().get_generics(def_id))
else { return; };
// Try to find predicates on *generic params* that would allow copying `ty`
- let predicates: Result<Vec<_>, _> = tcx.infer_ctxt().enter(|infcx| {
- let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
+ let infcx = tcx.infer_ctxt().build();
+ let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
- let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
- let cause = ObligationCause::new(
- span,
- self.mir_hir_id(),
- rustc_infer::traits::ObligationCauseCode::MiscObligation,
- );
- fulfill_cx.register_bound(
- &infcx,
- self.param_env,
- // Erase any region vids from the type, which may not be resolved
- infcx.tcx.erase_regions(ty),
- copy_did,
- cause,
- );
- // Select all, including ambiguous predicates
- let errors = fulfill_cx.select_all_or_error(&infcx);
-
- // Only emit suggestion if all required predicates are on generic
- errors
- .into_iter()
- .map(|err| match err.obligation.predicate.kind().skip_binder() {
- PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
- ty::Param(param_ty) => Ok((
- generics.type_param(param_ty, tcx),
- predicate.trait_ref.print_only_trait_path().to_string(),
- )),
- _ => Err(()),
- },
+ let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+ let cause = ObligationCause::new(
+ span,
+ self.mir_hir_id(),
+ rustc_infer::traits::ObligationCauseCode::MiscObligation,
+ );
+ fulfill_cx.register_bound(
+ &infcx,
+ self.param_env,
+ // Erase any region vids from the type, which may not be resolved
+ infcx.tcx.erase_regions(ty),
+ copy_did,
+ cause,
+ );
+ // Select all, including ambiguous predicates
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+
+ // Only emit suggestion if all required predicates are on generic
+ let predicates: Result<Vec<_>, _> = errors
+ .into_iter()
+ .map(|err| match err.obligation.predicate.kind().skip_binder() {
+ PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
+ ty::Param(param_ty) => Ok((
+ generics.type_param(param_ty, tcx),
+ predicate.trait_ref.print_only_trait_path().to_string(),
+ )),
_ => Err(()),
- })
- .collect()
- });
+ },
+ _ => Err(()),
+ })
+ .collect();
if let Ok(predicates) = predicates {
suggest_constraining_type_params(
@@ -2146,7 +2220,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
StorageDeadOrDrop::Destructor(_) => kind,
},
- ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => {
+ ProjectionElem::OpaqueCast { .. }
+ | ProjectionElem::Field(..)
+ | ProjectionElem::Downcast(..) => {
match place_ty.ty.kind() {
ty::Adt(def, _) if def.has_dtor(tcx) => {
// Report the outermost adt with a destructor
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 1c01e78ab..582d683dd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -1,8 +1,5 @@
//! Print diagnostics to explain why values are borrowed.
-use std::collections::VecDeque;
-
-use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic};
use rustc_index::vec::IndexVec;
use rustc_infer::infer::NllRegionVariableOrigin;
@@ -359,19 +356,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let borrow_region_vid = borrow.region;
debug!(?borrow_region_vid);
- let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
+ let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
debug!(?region_sub);
- match find_use::find(body, regioncx, tcx, region_sub, location) {
+ let mut use_location = location;
+ let mut use_in_later_iteration_of_loop = false;
+
+ if region_sub == borrow_region_vid {
+ // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow is
+ // issued is the same location that invalidates the reference), this is likely a loop iteration
+ // - in this case, try using the loop terminator location in `find_sub_region_live_at`.
+ if let Some(loop_terminator_location) =
+ regioncx.find_loop_terminator_location(borrow.region, body)
+ {
+ region_sub = self
+ .regioncx
+ .find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
+ debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
+ use_location = loop_terminator_location;
+ use_in_later_iteration_of_loop = true;
+ }
+ }
+
+ match find_use::find(body, regioncx, tcx, region_sub, use_location) {
Some(Cause::LiveVar(local, location)) => {
let span = body.source_info(location).span;
let spans = self
.move_spans(Place::from(local).as_ref(), location)
.or_else(|| self.borrow_spans(span, location));
- let borrow_location = location;
- if self.is_use_in_later_iteration_of_loop(borrow_location, location) {
- let later_use = self.later_use_kind(borrow, spans, location);
+ if use_in_later_iteration_of_loop {
+ let later_use = self.later_use_kind(borrow, spans, use_location);
BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2)
} else {
// Check if the location represents a `FakeRead`, and adapt the error
@@ -425,131 +440,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- /// true if `borrow_location` can reach `use_location` by going through a loop and
- /// `use_location` is also inside of that loop
- fn is_use_in_later_iteration_of_loop(
- &self,
- borrow_location: Location,
- use_location: Location,
- ) -> bool {
- let back_edge = self.reach_through_backedge(borrow_location, use_location);
- back_edge.map_or(false, |back_edge| self.can_reach_head_of_loop(use_location, back_edge))
- }
-
- /// Returns the outmost back edge if `from` location can reach `to` location passing through
- /// that back edge
- fn reach_through_backedge(&self, from: Location, to: Location) -> Option<Location> {
- let mut visited_locations = FxHashSet::default();
- let mut pending_locations = VecDeque::new();
- visited_locations.insert(from);
- pending_locations.push_back(from);
- debug!("reach_through_backedge: from={:?} to={:?}", from, to,);
-
- let mut outmost_back_edge = None;
- while let Some(location) = pending_locations.pop_front() {
- debug!(
- "reach_through_backedge: location={:?} outmost_back_edge={:?}
- pending_locations={:?} visited_locations={:?}",
- location, outmost_back_edge, pending_locations, visited_locations
- );
-
- if location == to && outmost_back_edge.is_some() {
- // We've managed to reach the use location
- debug!("reach_through_backedge: found!");
- return outmost_back_edge;
- }
-
- let block = &self.body.basic_blocks[location.block];
-
- if location.statement_index < block.statements.len() {
- let successor = location.successor_within_block();
- if visited_locations.insert(successor) {
- pending_locations.push_back(successor);
- }
- } else {
- pending_locations.extend(
- block
- .terminator()
- .successors()
- .map(|bb| Location { statement_index: 0, block: bb })
- .filter(|s| visited_locations.insert(*s))
- .map(|s| {
- if self.is_back_edge(location, s) {
- match outmost_back_edge {
- None => {
- outmost_back_edge = Some(location);
- }
-
- Some(back_edge)
- if location.dominates(back_edge, &self.dominators) =>
- {
- outmost_back_edge = Some(location);
- }
-
- Some(_) => {}
- }
- }
-
- s
- }),
- );
- }
- }
-
- None
- }
-
- /// true if `from` location can reach `loop_head` location and `loop_head` dominates all the
- /// intermediate nodes
- fn can_reach_head_of_loop(&self, from: Location, loop_head: Location) -> bool {
- self.find_loop_head_dfs(from, loop_head, &mut FxHashSet::default())
- }
-
- fn find_loop_head_dfs(
- &self,
- from: Location,
- loop_head: Location,
- visited_locations: &mut FxHashSet<Location>,
- ) -> bool {
- visited_locations.insert(from);
-
- if from == loop_head {
- return true;
- }
-
- if loop_head.dominates(from, &self.dominators) {
- let block = &self.body.basic_blocks[from.block];
-
- if from.statement_index < block.statements.len() {
- let successor = from.successor_within_block();
-
- if !visited_locations.contains(&successor)
- && self.find_loop_head_dfs(successor, loop_head, visited_locations)
- {
- return true;
- }
- } else {
- for bb in block.terminator().successors() {
- let successor = Location { statement_index: 0, block: bb };
-
- if !visited_locations.contains(&successor)
- && self.find_loop_head_dfs(successor, loop_head, visited_locations)
- {
- return true;
- }
- }
- }
- }
-
- false
- }
-
- /// True if an edge `source -> target` is a backedge -- in other words, if the target
- /// dominates the source.
- fn is_back_edge(&self, source: Location, target: Location) -> bool {
- target.dominates(source, &self.dominators)
- }
-
/// Determine how the borrow was later used.
/// First span returned points to the location of the conflicting use
/// Second span if `Some` is returned in the case of closures and points
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 683084cf0..534d9ecae 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -237,6 +237,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::Downcast(..) if opt.including_downcast => return None,
ProjectionElem::Downcast(..) => (),
+ ProjectionElem::OpaqueCast(..) => (),
ProjectionElem::Field(field, _ty) => {
// FIXME(project-rfc_2229#36): print capture precisely here.
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
@@ -317,6 +318,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
PlaceRef { local, projection: proj_base }.ty(self.body, self.infcx.tcx)
}
ProjectionElem::Downcast(..) => place.ty(self.body, self.infcx.tcx),
+ ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(*ty),
ProjectionElem::Field(_, field_type) => PlaceTy::from_ty(*field_type),
},
};
@@ -970,7 +972,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
move_span: Span,
move_spans: UseSpans<'tcx>,
moved_place: Place<'tcx>,
- used_place: Option<PlaceRef<'tcx>>,
partially_str: &str,
loop_message: &str,
move_msg: &str,
@@ -1024,7 +1025,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, self.infcx.tcx).ty;
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
- Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+ Some(def_id) => {
+ let infcx = self.infcx.tcx.infer_ctxt().build();
type_known_to_meet_bound_modulo_regions(
&infcx,
self.param_env,
@@ -1035,7 +1037,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
def_id,
DUMMY_SP,
)
- }),
+ }
_ => false,
};
if suggest {
@@ -1058,9 +1060,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place_name, partially_str, loop_message
),
);
- // If we have a `&mut` ref, we need to reborrow.
- if let Some(ty::Ref(_, _, hir::Mutability::Mut)) = used_place
- .map(|used_place| used_place.ty(self.body, self.infcx.tcx).ty.kind())
+ // If the moved place was a `&mut` ref, then we can
+ // suggest to reborrow it where it was moved, so it
+ // will still be valid by the time we get to the usage.
+ if let ty::Ref(_, _, hir::Mutability::Mut) =
+ moved_place.ty(self.body, self.infcx.tcx).ty.kind()
{
// If we are in a loop this will be suggested later.
if !is_loop_move {
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 8d4c38d3a..5a47f4567 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
if let Some(use_spans) = use_spans {
self.explain_captures(
- &mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
+ &mut err, span, span, use_spans, move_place, "", "", "", false, true,
);
}
err
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 6b5014fa9..8ad40c0aa 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -169,6 +169,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
..,
ProjectionElem::Index(_)
| ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
],
@@ -931,7 +932,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let opt_suggestions = self
.infcx
.tcx
- .typeck(path_segment.hir_id.owner)
+ .typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(*hir_id)
.and_then(|def_id| self.infcx.tcx.impl_of_method(def_id))
.map(|def_id| self.infcx.tcx.associated_items(def_id))
@@ -1031,7 +1032,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if look_at_return && hir.get_return_block(closure_id).is_some() {
// ...otherwise we are probably in the tail expression of the function, point at the
// return type.
- match hir.get_by_def_id(hir.get_parent_item(fn_call_id)) {
+ match hir.get_by_def_id(hir.get_parent_item(fn_call_id).def_id) {
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem {
ident,
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 34be2874f..15230718d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -186,7 +186,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
let origin = RelateParamBound(type_test_span, generic_ty, None);
- self.buffer_error(self.infcx.construct_generic_bound_failure(
+ self.buffer_error(self.infcx.err_ctxt().construct_generic_bound_failure(
self.body.source.def_id().expect_local(),
type_test_span,
Some(origin),
@@ -281,7 +281,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let tcx = self.infcx.tcx;
match tcx.hir().get_if_local(def_id) {
Some(Node::ImplItem(impl_item)) => {
- match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) {
+ match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
+ {
Some(Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
..
@@ -291,7 +292,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
Some(Node::TraitItem(trait_item)) => {
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
- match tcx.hir().find_by_def_id(trait_did) {
+ match tcx.hir().find_by_def_id(trait_did.def_id) {
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
// The method being called is defined in the `trait`, but the `'static`
// obligation comes from the `impl`. Find that `impl` so that we can point
@@ -340,7 +341,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
/// Report an error because the universal region `fr` was required to outlive
/// `outlived_fr` but it is not known to do so. For example:
///
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
///
@@ -364,7 +365,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Check if we can use one of the "nice region errors".
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
- let nice = NiceRegionError::new_from_span(self.infcx, cause.span, o, f);
+ let infer_err = self.infcx.err_ctxt();
+ let nice = NiceRegionError::new_from_span(&infer_err, cause.span, o, f);
if let Some(diag) = nice.try_report_from_nll() {
self.buffer_error(diag);
return;
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 6c1eaa809..c044dbaba 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -251,7 +251,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr))
- .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr));
+ .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
+ .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
if let Some(ref value) = value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
@@ -707,7 +708,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
hir::AsyncGeneratorKind::Block => " of async block",
hir::AsyncGeneratorKind::Closure => " of async closure",
hir::AsyncGeneratorKind::Fn => {
- let parent_item = hir.get_by_def_id(hir.get_parent_item(mir_hir_id));
+ let parent_item =
+ hir.get_by_def_id(hir.get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("generator lowered from async fn should be in fn")
@@ -863,20 +865,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
};
let tcx = self.infcx.tcx;
- let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?;
- if tcx.parent(region.def_id) != body_parent_did
- || tcx.def_kind(body_parent_did) != DefKind::Impl
- {
+ let region_parent = tcx.parent(region.def_id);
+ if tcx.def_kind(region_parent) != DefKind::Impl {
return None;
}
- let mut found = false;
- tcx.fold_regions(tcx.type_of(body_parent_did), |r: ty::Region<'tcx>, _| {
- if *r == ty::ReEarlyBound(region) {
- found = true;
- }
- r
- });
+ let found = tcx
+ .any_free_region_meets(&tcx.type_of(region_parent), |r| *r == ty::ReEarlyBound(region));
Some(RegionName {
name: self.synthesize_region_name(),
@@ -889,4 +884,92 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
),
})
}
+
+ fn give_name_if_anonymous_region_appears_in_arg_position_impl_trait(
+ &self,
+ fr: RegionVid,
+ ) -> Option<RegionName> {
+ let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else {
+ return None;
+ };
+ if region.has_name() {
+ return None;
+ };
+
+ let predicates = self
+ .infcx
+ .tcx
+ .predicates_of(self.body.source.def_id())
+ .instantiate_identity(self.infcx.tcx)
+ .predicates;
+
+ if let Some(upvar_index) = self
+ .regioncx
+ .universal_regions()
+ .defining_ty
+ .upvar_tys()
+ .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region))
+ {
+ let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
+ self.infcx.tcx,
+ &self.upvars,
+ upvar_index,
+ );
+ let region_name = self.synthesize_region_name();
+
+ Some(RegionName {
+ name: region_name,
+ source: RegionNameSource::AnonRegionFromUpvar(upvar_span, upvar_name),
+ })
+ } else if let Some(arg_index) = self
+ .regioncx
+ .universal_regions()
+ .unnormalized_input_tys
+ .iter()
+ .position(|ty| self.any_param_predicate_mentions(&predicates, *ty, region))
+ {
+ let (arg_name, arg_span) = self.regioncx.get_argument_name_and_span_for_region(
+ self.body,
+ &self.local_names,
+ arg_index,
+ );
+ let region_name = self.synthesize_region_name();
+
+ Some(RegionName {
+ name: region_name,
+ source: RegionNameSource::AnonRegionFromArgument(
+ RegionNameHighlight::CannotMatchHirTy(arg_span, arg_name?.to_string()),
+ ),
+ })
+ } else {
+ None
+ }
+ }
+
+ fn any_param_predicate_mentions(
+ &self,
+ predicates: &[ty::Predicate<'tcx>],
+ ty: Ty<'tcx>,
+ region: ty::EarlyBoundRegion,
+ ) -> bool {
+ let tcx = self.infcx.tcx;
+ ty.walk().any(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Param(_) = ty.kind()
+ {
+ predicates.iter().any(|pred| {
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
+ ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
+ _ => return false,
+ }
+ tcx.any_free_region_meets(pred, |r| {
+ *r == ty::ReEarlyBound(region)
+ })
+ })
+ } else {
+ false
+ }
+ })
+ }
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 86da87d06..abfe253d4 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -3,7 +3,6 @@
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
@@ -132,14 +131,11 @@ fn mir_borrowck<'tcx>(
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
- let opt_closure_req = tcx
- .infer_ctxt()
- .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner))
- .enter(|infcx| {
- let input_body: &Body<'_> = &input_body.borrow();
- let promoted: &IndexVec<_, _> = &promoted.borrow();
- do_mir_borrowck(&infcx, input_body, promoted, false).0
- });
+ let infcx =
+ tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
+ let input_body: &Body<'_> = &input_body.borrow();
+ let promoted: &IndexVec<_, _> = &promoted.borrow();
+ let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
debug!("mir_borrowck done");
tcx.arena.alloc(opt_closure_req)
@@ -151,8 +147,8 @@ fn mir_borrowck<'tcx>(
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.with_opt_param().as_local().unwrap()), level = "debug")]
-fn do_mir_borrowck<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+fn do_mir_borrowck<'tcx>(
+ infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexVec<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
@@ -475,7 +471,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
}
struct MirBorrowckCtxt<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &'cx Body<'tcx>,
move_data: &'cx MoveData<'tcx>,
@@ -1781,6 +1777,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
for (place_base, elem) in place.iter_projections().rev() {
match elem {
ProjectionElem::Index(_/*operand*/) |
+ ProjectionElem::OpaqueCast(_) |
ProjectionElem::ConstantIndex { .. } |
// assigning to P[i] requires P to be valid.
ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) =>
@@ -2172,6 +2169,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Downcast(..) => {
let upvar_field_projection = self.is_upvar_field_projection(place);
if let Some(field) = upvar_field_projection {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 12b2481cc..08fdd28eb 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -55,8 +55,8 @@ pub(crate) struct NllOutput<'tcx> {
/// regions (e.g., region parameters) declared on the function. That set will need to be given to
/// `compute_regions`.
#[instrument(skip(infcx, param_env, body, promoted), level = "debug")]
-pub(crate) fn replace_regions_in_mir<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+pub(crate) fn replace_regions_in_mir<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
@@ -155,7 +155,7 @@ fn populate_polonius_move_facts(
///
/// This may result in errors being reported.
pub(crate) fn compute_regions<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
universal_regions: UniversalRegions<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -318,8 +318,8 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
}
}
-pub(super) fn dump_mir_results<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub(super) fn dump_mir_results<'tcx>(
+ infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
@@ -368,8 +368,8 @@ pub(super) fn dump_mir_results<'a, 'tcx>(
};
}
-pub(super) fn dump_annotation<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub(super) fn dump_annotation<'tcx>(
+ infcx: &InferCtxt<'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
closure_region_requirements: &Option<ClosureRegionRequirements<'_>>,
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 6e5a96bee..0e71efd6f 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -250,6 +250,7 @@ fn place_components_conflict<'tcx>(
| (ProjectionElem::Index { .. }, _, _)
| (ProjectionElem::ConstantIndex { .. }, _, _)
| (ProjectionElem::Subslice { .. }, _, _)
+ | (ProjectionElem::OpaqueCast { .. }, _, _)
| (ProjectionElem::Downcast { .. }, _, _) => {
// Recursive case. This can still be disjoint on a
// further iteration if this a shallow access and
@@ -317,6 +318,17 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
Overlap::EqualOrDisjoint
}
+ (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
+ if v1 == v2 {
+ // same type - recur.
+ debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
+ Overlap::EqualOrDisjoint
+ } else {
+ // Different types. Disjoint!
+ debug!("place_element_conflict: DISJOINT-OPAQUE");
+ Overlap::Disjoint
+ }
+ }
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
if f1 == f2 {
// same field (e.g., `a.y` vs. `a.y`) - recur.
@@ -520,6 +532,7 @@ fn place_projection_conflict<'tcx>(
| ProjectionElem::Field(..)
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(..),
_,
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index bdf2becb7..2b50cbac9 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -81,6 +81,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
}
ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
+ | ProjectionElem::OpaqueCast { .. }
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Index(_) => {
cursor = cursor_base;
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 244e6e342..8b63294fb 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -15,7 +15,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, ReturnConstraint,
+ ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
@@ -565,7 +565,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(skip(self, infcx, body, polonius_output), level = "debug")]
pub(super) fn solve(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
polonius_output: Option<Rc<PoloniusOutput>>,
@@ -835,7 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// 'a`. See `TypeTest` for more details.
fn check_type_tests(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'tcx>>>,
@@ -923,7 +923,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))]
fn try_promote_type_test(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
type_test: &TypeTest<'tcx>,
@@ -1036,7 +1036,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx))]
fn try_promote_type_test_subject(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
ty: Ty<'tcx>,
) -> Option<ClosureOutlivesSubject<'tcx>> {
let tcx = infcx.tcx;
@@ -1212,7 +1212,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// `point`.
fn eval_verify_bound(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
generic_ty: Ty<'tcx>,
@@ -1262,7 +1262,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn eval_if_eq(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_ty: Ty<'tcx>,
lower_bound: RegionVid,
@@ -1398,7 +1398,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// whether any of the constraints were too strong. In particular,
/// we want to check for a case where a universally quantified
/// region exceeded its bounds. Consider:
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
/// In this case, returning `x` requires `&'a u32 <: &'b u32`
@@ -1451,7 +1451,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// <https://smallcultfollowing.com/babysteps/blog/2019/01/17/polonius-and-region-errors/>
///
/// In the canonical example
- /// ```compile_fail,E0312
+ /// ```compile_fail
/// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x }
/// ```
/// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a
@@ -1718,7 +1718,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
fn check_member_constraints(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
errors_buffer: &mut RegionErrors<'tcx>,
) {
let member_constraints = self.member_constraints.clone();
@@ -2236,6 +2236,27 @@ impl<'tcx> RegionInferenceContext<'tcx> {
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
self.universe_causes[&universe].clone()
}
+
+ /// Tries to find the terminator of the loop in which the region 'r' resides.
+ /// Returns the location of the terminator if found.
+ pub(crate) fn find_loop_terminator_location(
+ &self,
+ r: RegionVid,
+ body: &Body<'_>,
+ ) -> Option<Location> {
+ let scc = self.constraint_sccs.scc(r.to_region_vid());
+ let locations = self.scc_values.locations_outlived_by(scc);
+ for location in locations {
+ let bb = &body[location.block];
+ if let Some(terminator) = &bb.terminator {
+ // terminator of a loop should be TerminatorKind::FalseUnwind
+ if let TerminatorKind::FalseUnwind { .. } = terminator.kind {
+ return Some(location);
+ }
+ }
+ }
+ None
+ }
}
impl<'tcx> RegionDefinition<'tcx> {
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 9d088642f..465f353aa 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -2,22 +2,18 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
-use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
-use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
+use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
};
use rustc_span::Span;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::TraitEngineExt as _;
-use crate::session_diagnostics::ConstNotUsedTraitAlias;
-
use super::RegionInferenceContext;
impl<'tcx> RegionInferenceContext<'tcx> {
@@ -63,7 +59,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx), ret)]
pub(crate) fn infer_opaque_types(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
@@ -194,7 +190,7 @@ pub trait InferCtxtExt<'tcx> {
) -> Ty<'tcx>;
}
-impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Given the fully resolved, instantiated type for an opaque
/// type, i.e., the value of an inference variable like C1 or C2
/// (*), computes the "definition type" for an opaque type
@@ -229,31 +225,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return self.tcx.ty_error();
}
- let OpaqueTypeKey { def_id, substs } = opaque_type_key;
-
- // Use substs to build up a reverse map from regions to their
- // identity mappings. This is necessary because of `impl
- // Trait` lifetimes are computed by replacing existing
- // lifetimes with 'static and remapping only those used in the
- // `impl Trait` return type, resulting in the parameters
- // shifting.
- let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
- debug!(?id_substs);
- let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
- substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
- debug!("map = {:#?}", map);
-
- // Convert the type from the function into a type valid outside
- // the function, by replacing invalid regions with 'static,
- // after producing an error for each of them.
- let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
- self.tcx,
- opaque_type_key,
- map,
- instantiated_ty.ty,
- instantiated_ty.span,
- ));
- debug!(?definition_ty);
+ let definition_ty = instantiated_ty
+ .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false, origin)
+ .ty;
if !check_opaque_type_parameter_valid(
self.tcx,
@@ -266,72 +240,70 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Only check this for TAIT. RPIT already supports `src/test/ui/impl-trait/nested-return-type2.rs`
// on stable and we'd break that.
- if let OpaqueTyOrigin::TyAlias = origin {
- // 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
- self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter(
- move |infcx| {
- // Require the hidden type to be well-formed with only the generics of the opaque type.
- // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
- // hidden type is well formed even without those bounds.
- let predicate =
- ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
- .to_predicate(infcx.tcx);
- let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
+ let OpaqueTyOrigin::TyAlias = origin else {
+ return definition_ty;
+ };
+ let def_id = opaque_type_key.def_id;
+ // 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
+ let infcx =
+ self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
+ // Require the hidden type to be well-formed with only the generics of the opaque type.
+ // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+ // hidden type is well formed even without those bounds.
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
+ .to_predicate(infcx.tcx);
+ let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
- // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
- // the bounds that the function supplies.
- match infcx.register_hidden_type(
- OpaqueTypeKey { def_id, substs: id_substs },
- ObligationCause::misc(instantiated_ty.span, body_id),
- param_env,
+ let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
+
+ // Require that the hidden type actually fulfills all the bounds of the opaque type, even without
+ // the bounds that the function supplies.
+ let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
+ match infcx
+ .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
+ .eq(opaque_ty, definition_ty)
+ {
+ Ok(infer_ok) => {
+ for obligation in infer_ok.obligations {
+ fulfillment_cx.register_predicate_obligation(&infcx, obligation);
+ }
+ }
+ Err(err) => {
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(
+ &ObligationCause::misc(instantiated_ty.span, body_id),
+ opaque_ty,
definition_ty,
- origin,
- ) {
- Ok(infer_ok) => {
- for obligation in infer_ok.obligations {
- fulfillment_cx.register_predicate_obligation(&infcx, obligation);
- }
- }
- Err(err) => {
- infcx
- .report_mismatched_types(
- &ObligationCause::misc(instantiated_ty.span, body_id),
- self.tcx.mk_opaque(def_id.to_def_id(), id_substs),
- definition_ty,
- err,
- )
- .emit();
- }
- }
+ err,
+ )
+ .emit();
+ }
+ }
- fulfillment_cx.register_predicate_obligation(
- &infcx,
- Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
- );
+ fulfillment_cx.register_predicate_obligation(
+ &infcx,
+ Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
+ );
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = fulfillment_cx.select_all_or_error(&infcx);
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = fulfillment_cx.select_all_or_error(&infcx);
- // This is still required for many(half of the tests in ui/type-alias-impl-trait)
- // tests to pass
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+ // This is still required for many(half of the tests in ui/type-alias-impl-trait)
+ // tests to pass
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- if errors.is_empty() {
- definition_ty
- } else {
- infcx.report_fulfillment_errors(&errors, None, false);
- self.tcx.ty_error()
- }
- },
- )
- } else {
+ if errors.is_empty() {
definition_ty
+ } else {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ self.tcx.ty_error()
}
}
}
@@ -427,221 +399,3 @@ fn check_opaque_type_parameter_valid(
}
true
}
-
-struct ReverseMapper<'tcx> {
- tcx: TyCtxt<'tcx>,
-
- key: ty::OpaqueTypeKey<'tcx>,
- map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
- do_not_error: bool,
-
- /// initially `Some`, set to `None` once error has been reported
- hidden_ty: Option<Ty<'tcx>>,
-
- /// Span of function being checked.
- span: Span,
-}
-
-impl<'tcx> ReverseMapper<'tcx> {
- fn new(
- tcx: TyCtxt<'tcx>,
- key: ty::OpaqueTypeKey<'tcx>,
- map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
- hidden_ty: Ty<'tcx>,
- span: Span,
- ) -> Self {
- Self { tcx, key, map, do_not_error: false, hidden_ty: Some(hidden_ty), span }
- }
-
- fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
- assert!(!self.do_not_error);
- self.do_not_error = true;
- let kind = kind.fold_with(self);
- self.do_not_error = false;
- kind
- }
-
- fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
- assert!(!self.do_not_error);
- kind.fold_with(self)
- }
-}
-
-impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- #[instrument(skip(self), level = "debug")]
- fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
- match *r {
- // Ignore bound regions and `'static` regions that appear in the
- // type, we only need to remap regions that reference lifetimes
- // from the function declaration.
- // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
- ty::ReLateBound(..) | ty::ReStatic => return r,
-
- // If regions have been erased (by writeback), don't try to unerase
- // them.
- ty::ReErased => return r,
-
- // The regions that we expect from borrow checking.
- ty::ReEarlyBound(_) | ty::ReFree(_) => {}
-
- ty::RePlaceholder(_) | ty::ReVar(_) => {
- // All of the regions in the type should either have been
- // erased by writeback, or mapped back to named regions by
- // borrow checking.
- bug!("unexpected region kind in opaque type: {:?}", r);
- }
- }
-
- let generics = self.tcx().generics_of(self.key.def_id);
- match self.map.get(&r.into()).map(|k| k.unpack()) {
- Some(GenericArgKind::Lifetime(r1)) => r1,
- Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
- None if self.do_not_error => self.tcx.lifetimes.re_static,
- None if generics.parent.is_some() => {
- if let Some(hidden_ty) = self.hidden_ty.take() {
- unexpected_hidden_region_diagnostic(
- self.tcx,
- self.tcx.def_span(self.key.def_id),
- hidden_ty,
- r,
- self.key,
- )
- .emit();
- }
- self.tcx.lifetimes.re_static
- }
- None => {
- 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",
- r
- ),
- )
- .emit();
-
- self.tcx().lifetimes.re_static
- }
- }
- }
-
- 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)
- }
- }));
-
- 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)
- }
- }));
-
- self.tcx.mk_generator(def_id, substs, movability)
- }
-
- ty::Param(param) => {
- // Look it up in the substitution list.
- match self.map.get(&ty.into()).map(|k| k.unpack()) {
- // Found it in the substitution list; replace with the parameter from the
- // opaque type.
- Some(GenericArgKind::Type(t1)) => t1,
- Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
- None => {
- debug!(?param, ?self.map);
- self.tcx
- .sess
- .struct_span_err(
- self.span,
- &format!(
- "type parameter `{}` is part of concrete type but not \
- used in parameter list for the `impl Trait` type alias",
- ty
- ),
- )
- .emit();
-
- self.tcx().ty_error()
- }
- }
- }
-
- _ => ty.super_fold_with(self),
- }
- }
-
- fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
- trace!("checking const {:?}", ct);
- // Find a const parameter
- match ct.kind() {
- ty::ConstKind::Param(..) => {
- // Look it up in the substitution list.
- match self.map.get(&ct.into()).map(|k| k.unpack()) {
- // Found it in the substitution list, replace with the parameter from the
- // opaque type.
- Some(GenericArgKind::Const(c1)) => c1,
- Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
- None => {
- self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
- ct: ct.to_string(),
- span: self.span,
- });
-
- self.tcx().const_error(ct.ty())
- }
- }
- }
-
- _ => ct,
- }
- }
-}
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index 63b2088f7..f30237690 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -1,8 +1,8 @@
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext};
+use rustc_middle::mir::Constant;
use rustc_middle::mir::{Body, Location, Promoted};
-use rustc_middle::mir::{Constant, ConstantKind};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
/// inference variables, returning the number of variables created.
#[instrument(skip(infcx, body, promoted), level = "debug")]
pub fn renumber_mir<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
body: &mut Body<'tcx>,
promoted: &mut IndexVec<Promoted, Body<'tcx>>,
) {
@@ -28,7 +28,7 @@ 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
+pub fn renumber_regions<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> T
where
T: TypeFoldable<'tcx>,
{
@@ -38,23 +38,8 @@ where
})
}
-// FIXME(valtrees): This function is necessary because `fold_regions`
-// panics for mir constants in the visitor.
-//
-// Once `visit_mir_constant` is removed we can also remove this function
-// and just use `renumber_regions`.
-fn renumber_regions_in_mir_constant<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
- value: ConstantKind<'tcx>,
-) -> ConstantKind<'tcx> {
- infcx.tcx.super_fold_regions(value, |_region, _depth| {
- let origin = NllRegionVariableOrigin::Existential { from_forall: false };
- infcx.next_nll_region_var(origin)
- })
-}
-
struct NllVisitor<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
@@ -64,13 +49,6 @@ impl<'a, 'tcx> NllVisitor<'a, 'tcx> {
{
renumber_regions(self.infcx, value)
}
-
- fn renumber_regions_in_mir_constant(
- &mut self,
- value: ConstantKind<'tcx>,
- ) -> ConstantKind<'tcx> {
- renumber_regions_in_mir_constant(self.infcx, value)
- }
}
impl<'a, 'tcx> MutVisitor<'tcx> for NllVisitor<'a, 'tcx> {
@@ -103,7 +81,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_in_mir_constant(literal);
+ constant.literal = self.renumber_regions(literal);
debug!("constant: {:#?}", constant);
}
}
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 5d750c6ca..cff3089c3 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -1,12 +1,12 @@
use rustc_errors::{IntoDiagnosticArg, MultiSpan};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
use crate::diagnostics::RegionName;
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::move_unsized, code = "E0161")]
+#[derive(Diagnostic)]
+#[diag(borrowck_move_unsized, code = "E0161")]
pub(crate) struct MoveUnsized<'tcx> {
pub ty: Ty<'tcx>,
#[primary_span]
@@ -14,8 +14,8 @@ pub(crate) struct MoveUnsized<'tcx> {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::higher_ranked_lifetime_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_higher_ranked_lifetime_error)]
pub(crate) struct HigherRankedLifetimeError {
#[subdiagnostic]
pub cause: Option<HigherRankedErrorCause>,
@@ -23,23 +23,23 @@ pub(crate) struct HigherRankedLifetimeError {
pub span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum HigherRankedErrorCause {
- #[note(borrowck::could_not_prove)]
+ #[note(borrowck_could_not_prove)]
CouldNotProve { predicate: String },
- #[note(borrowck::could_not_normalize)]
+ #[note(borrowck_could_not_normalize)]
CouldNotNormalize { value: String },
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::higher_ranked_subtype_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_higher_ranked_subtype_error)]
pub(crate) struct HigherRankedSubtypeError {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::generic_does_not_live_long_enough)]
+#[derive(Diagnostic)]
+#[diag(borrowck_generic_does_not_live_long_enough)]
pub(crate) struct GenericDoesNotLiveLongEnough {
pub kind: String,
#[primary_span]
@@ -47,24 +47,15 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
}
#[derive(LintDiagnostic)]
-#[diag(borrowck::var_does_not_need_mut)]
+#[diag(borrowck_var_does_not_need_mut)]
pub(crate) struct VarNeedNotMut {
#[suggestion_short(applicability = "machine-applicable", code = "")]
pub span: Span,
}
-
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::const_not_used_in_type_alias)]
-pub(crate) struct ConstNotUsedTraitAlias {
- pub ct: String,
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::var_cannot_escape_closure)]
+#[derive(Diagnostic)]
+#[diag(borrowck_var_cannot_escape_closure)]
#[note]
-#[note(borrowck::cannot_escape)]
+#[note(cannot_escape)]
pub(crate) struct FnMutError {
#[primary_span]
pub span: Span,
@@ -72,54 +63,54 @@ pub(crate) struct FnMutError {
pub ty_err: FnMutReturnTypeErr,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum VarHereDenote {
- #[label(borrowck::var_here_captured)]
+ #[label(borrowck_var_here_captured)]
Captured {
#[primary_span]
span: Span,
},
- #[label(borrowck::var_here_defined)]
+ #[label(borrowck_var_here_defined)]
Defined {
#[primary_span]
span: Span,
},
- #[label(borrowck::closure_inferred_mut)]
+ #[label(borrowck_closure_inferred_mut)]
FnMutInferred {
#[primary_span]
span: Span,
},
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum FnMutReturnTypeErr {
- #[label(borrowck::returned_closure_escaped)]
+ #[label(borrowck_returned_closure_escaped)]
ReturnClosure {
#[primary_span]
span: Span,
},
- #[label(borrowck::returned_async_block_escaped)]
+ #[label(borrowck_returned_async_block_escaped)]
ReturnAsyncBlock {
#[primary_span]
span: Span,
},
- #[label(borrowck::returned_ref_escaped)]
+ #[label(borrowck_returned_ref_escaped)]
ReturnRef {
#[primary_span]
span: Span,
},
}
-#[derive(SessionDiagnostic)]
-#[diag(borrowck::lifetime_constraints_error)]
+#[derive(Diagnostic)]
+#[diag(borrowck_lifetime_constraints_error)]
pub(crate) struct LifetimeOutliveErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum LifetimeReturnCategoryErr<'a> {
- #[label(borrowck::returned_lifetime_wrong)]
+ #[label(borrowck_returned_lifetime_wrong)]
WrongReturn {
#[primary_span]
span: Span,
@@ -127,7 +118,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> {
outlived_fr_name: RegionName,
fr_name: &'a RegionName,
},
- #[label(borrowck::returned_lifetime_short)]
+ #[label(borrowck_returned_lifetime_short)]
ShortReturn {
#[primary_span]
span: Span,
@@ -149,9 +140,9 @@ impl IntoDiagnosticArg for RegionName {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub(crate) enum RequireStaticErr {
- #[note(borrowck::used_impl_require_static)]
+ #[note(borrowck_used_impl_require_static)]
UsedImpl {
#[primary_span]
multi_span: MultiSpan,
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 9271a2f4d..a581726a1 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -52,11 +52,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(error_info) => error_info.to_universe_info(old_universe),
None => UniverseInfo::other(),
};
- for u in old_universe..universe {
- self.borrowck_context
- .constraints
- .universe_causes
- .insert(u + 1, universe_info.clone());
+ for u in (old_universe + 1)..=universe {
+ self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
}
}
@@ -71,15 +68,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
where
T: TypeFoldable<'tcx>,
{
+ let old_universe = self.infcx.universe();
+
let (instantiated, _) =
self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
- for u in 0..canonical.max_universe.as_u32() {
- let info = UniverseInfo::other();
- self.borrowck_context
- .constraints
- .universe_causes
- .insert(ty::UniverseIndex::from_u32(u), info);
+ for u in (old_universe + 1)..=self.infcx.universe() {
+ self.borrowck_context.constraints.universe_causes.insert(u, UniverseInfo::other());
}
instantiated
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 71eae0583..d5bfc2f52 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -19,7 +19,7 @@ use crate::{
};
pub(crate) struct ConstraintConversion<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
/// Each RBP `GK: 'a` is assumed to be true. These encode
@@ -43,7 +43,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
pub(crate) fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
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 f1b1c33a1..029095926 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -8,7 +8,6 @@ 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::DUMMY_SP;
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc;
use type_op::TypeOpOutput;
@@ -48,7 +47,7 @@ pub(crate) struct CreateResult<'tcx> {
}
pub(crate) fn create<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
universal_regions: &Rc<UniversalRegions<'tcx>>,
@@ -197,7 +196,7 @@ impl UniversalRegionRelations<'_> {
}
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
- infcx: &'this InferCtxt<'this, 'tcx>,
+ infcx: &'this InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
universal_regions: Rc<UniversalRegions<'tcx>>,
implicit_region_bound: ty::Region<'tcx>,
@@ -219,6 +218,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
}
pub(crate) fn create(mut self) -> CreateResult<'tcx> {
+ let span = self.infcx.tcx.def_span(self.universal_regions.defining_ty.def_id());
let unnormalized_input_output_tys = self
.universal_regions
.unnormalized_input_tys
@@ -250,7 +250,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.infcx
.tcx
.sess
- .delay_span_bug(DUMMY_SP, &format!("failed to normalize {:?}", ty));
+ .delay_span_bug(span, &format!("failed to normalize {:?}", ty));
TypeOpOutput {
output: self.infcx.tcx.ty_error(),
constraints: None,
@@ -301,8 +301,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
&self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
- Locations::All(DUMMY_SP),
- DUMMY_SP,
+ Locations::All(span),
+ span,
ConstraintCategory::Internal,
&mut self.constraints,
)
@@ -362,6 +362,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
}
+
+ OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
+ self.region_bound_pairs
+ .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
+ }
}
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 4431a2e8e..a66ddd27d 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -7,16 +7,11 @@
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).
-use crate::type_check::constraint_conversion::ConstraintConversion;
use rustc_index::vec::Idx;
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;
use rustc_span::Span;
-use rustc_span::DUMMY_SP;
-use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
-use rustc_trait_selection::traits::query::Fallible;
-use type_op::TypeOpOutput;
use crate::universal_regions::UniversalRegions;
@@ -185,7 +180,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
- #[instrument(skip(self, span), level = "debug")]
+ #[instrument(skip(self), level = "debug")]
fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
if let Err(_) =
self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
@@ -194,13 +189,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `rustc_traits::normalize_after_erasing_regions`. Ideally, we'd
// like to normalize *before* inserting into `local_decls`, but
// doing so ends up causing some other trouble.
- let b = match self.normalize_and_add_constraints(b) {
- Ok(n) => n,
- Err(_) => {
- debug!("equate_inputs_and_outputs: NoSolution");
- b
- }
- };
+ let b = self.normalize(b, Locations::All(span));
// Note: if we have to introduce new placeholders during normalization above, then we won't have
// added those universes to the universe info, which we would want in `relate_tys`.
@@ -218,28 +207,4 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}
-
- pub(crate) fn normalize_and_add_constraints(&mut self, t: Ty<'tcx>) -> Fallible<Ty<'tcx>> {
- let TypeOpOutput { output: norm_ty, constraints, .. } =
- self.param_env.and(type_op::normalize::Normalize::new(t)).fully_perform(self.infcx)?;
-
- debug!("{:?} normalized to {:?}", t, norm_ty);
-
- for data in constraints {
- ConstraintConversion::new(
- self.infcx,
- &self.borrowck_context.universal_regions,
- &self.region_bound_pairs,
- self.implicit_region_bound,
- self.param_env,
- Locations::All(DUMMY_SP),
- DUMMY_SP,
- ConstraintCategory::Internal,
- &mut self.borrowck_context.constraints,
- )
- .convert_all(&*data);
- }
-
- Ok(norm_ty)
- }
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3713ec3f5..3c1c3ab45 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -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: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body: &Body<'tcx>,
promoted: &IndexVec<Promoted, Body<'tcx>>,
@@ -138,8 +138,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
use_polonius: bool,
) -> MirTypeckResults<'tcx> {
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
- let mut universe_causes = FxHashMap::default();
- universe_causes.insert(ty::UniverseIndex::from_u32(0), UniverseInfo::other());
let mut constraints = MirTypeckRegionConstraints {
placeholder_indices: PlaceholderIndices::default(),
placeholder_index_to_region: IndexVec::default(),
@@ -148,7 +146,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
member_constraints: MemberConstraintSet::default(),
closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
- universe_causes,
+ universe_causes: FxHashMap::default(),
};
let CreateResult {
@@ -165,9 +163,8 @@ pub(crate) fn type_check<'mir, 'tcx>(
debug!(?normalized_inputs_and_output);
- for u in ty::UniverseIndex::ROOT..infcx.universe() {
- let info = UniverseInfo::other();
- constraints.universe_causes.insert(u, info);
+ for u in ty::UniverseIndex::ROOT..=infcx.universe() {
+ constraints.universe_causes.insert(u, UniverseInfo::other());
}
let mut borrowck_context = BorrowCheckContext {
@@ -236,7 +233,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
- if hidden_type.has_infer_types_or_consts() {
+ if hidden_type.has_non_region_infer() {
infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
@@ -428,12 +425,18 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() {
+ // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed.
+ // this is because the well-formedness of the function does not need to be proved to have `const`
+ // impls for trait bounds.
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
+ let prev = self.cx.param_env;
+ self.cx.param_env = prev.without_const();
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
locations,
);
+ self.cx.param_env = prev;
}
}
}
@@ -581,6 +584,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// modify their locations.
let all_facts = &mut None;
let mut constraints = Default::default();
+ let mut type_tests = Default::default();
let mut closure_bounds = Default::default();
let mut liveness_constraints =
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
@@ -592,6 +596,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
&mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints,
);
+ mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
mem::swap(
&mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
&mut closure_bounds,
@@ -616,6 +621,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
swap_constraints(self);
let locations = location.to_locations();
+
+ // Use location of promoted const in collected constraints
+ for type_test in type_tests.iter() {
+ let mut type_test = type_test.clone();
+ type_test.locations = locations;
+ self.cx.borrowck_context.constraints.type_tests.push(type_test)
+ }
for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone();
constraint.locations = locations;
@@ -764,6 +776,19 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
}
PlaceTy::from_ty(fty)
}
+ ProjectionElem::OpaqueCast(ty) => {
+ let ty = self.sanitize_type(place, ty);
+ let ty = self.cx.normalize(ty, location);
+ self.cx
+ .eq_types(
+ base.ty,
+ ty,
+ location.to_locations(),
+ ConstraintCategory::TypeAnnotation,
+ )
+ .unwrap();
+ PlaceTy::from_ty(ty)
+ }
}
}
@@ -857,7 +882,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<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
last_span: Span,
body: &'a Body<'tcx>,
@@ -927,7 +952,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
impl<'tcx> MirTypeckRegionConstraints<'tcx> {
fn placeholder_region(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
placeholder: ty::PlaceholderRegion,
) -> ty::Region<'tcx> {
let placeholder_index = self.placeholder_indices.insert(placeholder);
@@ -1011,7 +1036,7 @@ impl Locations {
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -1170,10 +1195,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
tcx,
self.param_env,
proj,
- |this, field, ()| {
+ |this, field, _| {
let ty = this.field_ty(tcx, field);
self.normalize(ty, locations)
},
+ |_, _| unreachable!(),
);
curr_projected_ty = projected_ty;
}
@@ -1604,7 +1630,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let op_arg_ty = self.normalize(op_arg_ty, term_location);
let category = if from_hir_call {
- ConstraintCategory::CallArgument(func_ty)
+ ConstraintCategory::CallArgument(self.infcx.tcx.erase_regions(func_ty))
} else {
ConstraintCategory::Boring
};
@@ -1757,7 +1783,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// `Sized` bound in no way depends on precise regions, so this
// shouldn't affect `is_sized`.
let erased_ty = tcx.erase_regions(ty);
- if !erased_ty.is_sized(tcx.at(span), self.param_env) {
+ if !erased_ty.is_sized(tcx, self.param_env) {
// in current MIR construction, all non-control-flow rvalue
// expressions evaluate through `as_temp` or `into` a return
// slot or local, so to find all unsized rvalues it is enough
@@ -2189,25 +2215,104 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}
-
- CastKind::Misc => {
+ CastKind::IntToInt => {
let ty_from = op.ty(body, tcx);
let cast_ty_from = CastTy::from_ty(ty_from);
let cast_ty_to = CastTy::from_ty(*ty);
- // Misc casts are either between floats and ints, or one ptr type to another.
match (cast_ty_from, cast_ty_to) {
- (
- Some(CastTy::Int(_) | CastTy::Float),
- Some(CastTy::Int(_) | CastTy::Float),
- )
- | (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
+ (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
_ => {
span_mirbug!(
self,
rvalue,
- "Invalid Misc cast {:?} -> {:?}",
+ "Invalid IntToInt cast {:?} -> {:?}",
ty_from,
- ty,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::IntToFloat => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid IntToFloat cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FloatToInt => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Float), Some(CastTy::Int(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FloatToInt cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FloatToFloat => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Float), Some(CastTy::Float)) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FloatToFloat cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::FnPtrToPtr => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid FnPtrToPtr cast {:?} -> {:?}",
+ ty_from,
+ ty
+ )
+ }
+ }
+ }
+ CastKind::PtrToPtr => {
+ let ty_from = op.ty(body, tcx);
+ let cast_ty_from = CastTy::from_ty(ty_from);
+ let cast_ty_to = CastTy::from_ty(*ty);
+ match (cast_ty_from, cast_ty_to) {
+ (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
+ _ => {
+ span_mirbug!(
+ self,
+ rvalue,
+ "Invalid PtrToPtr cast {:?} -> {:?}",
+ ty_from,
+ ty
)
}
}
@@ -2503,6 +2608,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
ProjectionElem::Field(..)
| ProjectionElem::Downcast(..)
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
@@ -2723,7 +2829,7 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
/// constraints in our `InferCtxt`
type ErrorInfo = InstantiateOpaqueType<'tcx>;
- fn fully_perform(mut self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
Ok(InferOk { value: (), obligations: self.obligations.clone() })
})?;
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index c97a6a1a6..4f2dc263b 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -1,6 +1,6 @@
use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin;
-use rustc_infer::traits::ObligationCause;
+use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation;
@@ -155,27 +155,16 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true
}
- fn register_opaque_type(
+ fn register_opaque_type_obligations(
&mut self,
- a: Ty<'tcx>,
- b: Ty<'tcx>,
- a_is_expected: bool,
+ obligations: PredicateObligations<'tcx>,
) -> Result<(), TypeError<'tcx>> {
- let param_env = self.param_env();
- let span = self.span();
- let def_id = self.type_checker.body.source.def_id().expect_local();
- let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id);
- let cause = ObligationCause::misc(span, body_id);
self.type_checker
.fully_perform_op(
self.locations,
self.category,
InstantiateOpaqueType {
- obligations: self
- .type_checker
- .infcx
- .handle_opaque_type(a, b, a_is_expected, &cause, param_env)?
- .obligations,
+ obligations,
// These fields are filled in during execution of the operation
base_universe: None,
region_constraints: None,
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 8cf9ed53d..2beb5e0ab 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,8 +22,8 @@ use rustc_hir::{BodyOwnerKind, HirId};
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use std::iter;
use crate::nll::ToRegionVid;
@@ -219,7 +219,7 @@ impl<'tcx> UniversalRegions<'tcx> {
/// signature. This will also compute the relationships that are
/// known between those regions.
pub fn new(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
@@ -382,7 +382,7 @@ impl<'tcx> UniversalRegions<'tcx> {
}
struct UniversalRegionsBuilder<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
mir_def: ty::WithOptConstParam<LocalDefId>,
mir_hir_id: HirId,
param_env: ty::ParamEnv<'tcx>,
@@ -414,7 +414,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
- // If this is is a 'root' body (not a closure/generator/inline const), then
+ // If this is a 'root' body (not a closure/generator/inline const), then
// there are no extern regions, so the local regions start at the same
// position as the (empty) sub-list of extern regions
let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id {
@@ -699,7 +699,7 @@ trait InferCtxtExt<'tcx> {
);
}
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn replace_free_regions_with_nll_infer_vars<T>(
&self,
origin: NllRegionVariableOrigin,
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index f80215a3c..bb6839360 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -58,6 +58,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
/// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to:
///
/// ```rust
+ /// #![feature(generic_assert_internals)]
/// let elem = 1;
/// {
/// #[allow(unused_imports)]
@@ -70,7 +71,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
/// __local_bind0
/// } == 1
/// ) {
- /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {}", __capture0)
+ /// panic!("Assertion failed: elem == 1\nWith captures:\n elem = {:?}", __capture0)
/// }
/// }
/// ```
@@ -241,8 +242,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
- ExprKind::MethodCall(_, ref mut local_exprs, _) => {
- for local_expr in local_exprs.iter_mut().skip(1) {
+ ExprKind::MethodCall(_, _,ref mut local_exprs, _) => {
+ for local_expr in local_exprs.iter_mut() {
self.manage_cond_expr(local_expr);
}
}
@@ -378,14 +379,12 @@ impl<'cx, 'a> Context<'cx, 'a> {
id: DUMMY_NODE_ID,
ident: Ident::new(sym::try_capture, self.span),
},
- vec![
- expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
- expr_addr_of_mut(
- self.cx,
- self.span,
- self.cx.expr_path(Path::from_ident(capture)),
- ),
- ],
+ expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)),
+ vec![expr_addr_of_mut(
+ self.cx,
+ self.span,
+ self.cx.expr_path(Path::from_ident(capture)),
+ )],
self.span,
))
.add_trailing_semicolon();
@@ -443,10 +442,11 @@ fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
fn expr_method_call(
cx: &ExtCtxt<'_>,
path: PathSegment,
+ receiver: P<Expr>,
args: Vec<P<Expr>>,
span: Span,
) -> P<Expr> {
- cx.expr(span, ExprKind::MethodCall(path, args, span))
+ cx.expr(span, ExprKind::MethodCall(path, receiver, args, span))
}
fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: P<Expr>) -> P<Expr> {
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 9046bf130..5638c2f61 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -8,7 +8,7 @@ use rustc_ast::tokenstream::TokenStream;
use rustc_attr as attr;
use rustc_errors::PResult;
use rustc_expand::base::{self, *};
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::Span;
pub fn expand_cfg(
@@ -35,16 +35,16 @@ pub fn expand_cfg(
}
}
-#[derive(SessionDiagnostic)]
-#[diag(builtin_macros::requires_cfg_pattern)]
+#[derive(Diagnostic)]
+#[diag(builtin_macros_requires_cfg_pattern)]
struct RequiresCfgPattern {
#[primary_span]
#[label]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(builtin_macros::expected_one_cfg_pattern)]
+#[derive(Diagnostic)]
+#[diag(builtin_macros_expected_one_cfg_pattern)]
struct OneCfgPattern {
#[primary_span]
span: Span,
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index e673dff0d..750f1fe12 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -7,6 +7,7 @@ use rustc_ast::visit::Visitor;
use rustc_ast::NodeId;
use rustc_ast::{mut_visit, visit};
use rustc_ast::{Attribute, HasAttrs, HasTokens};
+use rustc_errors::PResult;
use rustc_expand::base::{Annotatable, ExtCtxt};
use rustc_expand::config::StripUnconfigured;
use rustc_expand::configure;
@@ -144,33 +145,34 @@ impl CfgEval<'_, '_> {
// the location of `#[cfg]` and `#[cfg_attr]` in the token stream. The tokenization
// process is lossless, so this process is invisible to proc-macros.
- let parse_annotatable_with: fn(&mut Parser<'_>) -> _ = match annotatable {
- Annotatable::Item(_) => {
- |parser| Annotatable::Item(parser.parse_item(ForceCollect::Yes).unwrap().unwrap())
- }
- Annotatable::TraitItem(_) => |parser| {
- Annotatable::TraitItem(
- parser.parse_trait_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
- )
- },
- Annotatable::ImplItem(_) => |parser| {
- Annotatable::ImplItem(
- parser.parse_impl_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
- )
- },
- Annotatable::ForeignItem(_) => |parser| {
- Annotatable::ForeignItem(
- parser.parse_foreign_item(ForceCollect::Yes).unwrap().unwrap().unwrap(),
- )
- },
- Annotatable::Stmt(_) => |parser| {
- Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes).unwrap().unwrap()))
- },
- Annotatable::Expr(_) => {
- |parser| Annotatable::Expr(parser.parse_expr_force_collect().unwrap())
- }
- _ => unreachable!(),
- };
+ let parse_annotatable_with: for<'a> fn(&mut Parser<'a>) -> PResult<'a, _> =
+ match annotatable {
+ Annotatable::Item(_) => {
+ |parser| Ok(Annotatable::Item(parser.parse_item(ForceCollect::Yes)?.unwrap()))
+ }
+ Annotatable::TraitItem(_) => |parser| {
+ Ok(Annotatable::TraitItem(
+ parser.parse_trait_item(ForceCollect::Yes)?.unwrap().unwrap(),
+ ))
+ },
+ Annotatable::ImplItem(_) => |parser| {
+ Ok(Annotatable::ImplItem(
+ parser.parse_impl_item(ForceCollect::Yes)?.unwrap().unwrap(),
+ ))
+ },
+ Annotatable::ForeignItem(_) => |parser| {
+ Ok(Annotatable::ForeignItem(
+ parser.parse_foreign_item(ForceCollect::Yes)?.unwrap().unwrap(),
+ ))
+ },
+ Annotatable::Stmt(_) => |parser| {
+ Ok(Annotatable::Stmt(P(parser.parse_stmt(ForceCollect::Yes)?.unwrap())))
+ },
+ Annotatable::Expr(_) => {
+ |parser| Ok(Annotatable::Expr(parser.parse_expr_force_collect()?))
+ }
+ _ => unreachable!(),
+ };
// 'Flatten' all nonterminals (i.e. `TokenKind::Interpolated`)
// to `None`-delimited groups containing the corresponding tokens. This
@@ -193,7 +195,13 @@ impl CfgEval<'_, '_> {
let mut parser =
rustc_parse::stream_to_parser(&self.cfg.sess.parse_sess, orig_tokens, None);
parser.capture_cfg = true;
- annotatable = parse_annotatable_with(&mut parser);
+ match parse_annotatable_with(&mut parser) {
+ Ok(a) => annotatable = a,
+ Err(mut err) => {
+ err.emit();
+ return Some(annotatable);
+ }
+ }
// Now that we have our re-parsed `AttrTokenStream`, recursively configuring
// our attribute target will correctly the tokens as well.
@@ -202,8 +210,15 @@ impl CfgEval<'_, '_> {
}
impl MutVisitor for CfgEval<'_, '_> {
+ #[instrument(level = "trace", skip(self))]
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
- self.cfg.configure_expr(expr);
+ self.cfg.configure_expr(expr, false);
+ mut_visit::noop_visit_expr(expr, self);
+ }
+
+ #[instrument(level = "trace", skip(self))]
+ fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
+ self.cfg.configure_expr(expr, true);
mut_visit::noop_visit_expr(expr, self);
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 77e0b6c55..7bd344467 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -16,6 +16,7 @@ pub fn expand_deriving_copy(
let trait_def = TraitDef {
span,
path: path_std!(marker::Copy),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: true,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index c7f2d95e7..fa8685f5f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -72,6 +72,7 @@ pub fn expand_deriving_clone(
let trait_def = TraitDef {
span,
path: path_std!(clone::Clone),
+ skip_path_as_bound: false,
additional_bounds: bounds,
generics: Bounds::empty(),
supports_unions: true,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index 5b556c5c9..eab67b0d3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -25,6 +25,7 @@ pub fn expand_deriving_eq(
let trait_def = TraitDef {
span,
path: path_std!(cmp::Eq),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: true,
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 726258695..7f117981a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -19,6 +19,7 @@ pub fn expand_deriving_ord(
let trait_def = TraitDef {
span,
path: path_std!(cmp::Ord),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
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 42ee65b57..236cbccaf 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -83,6 +83,7 @@ pub fn expand_deriving_partial_eq(
let trait_def = TraitDef {
span,
path: path_std!(cmp::PartialEq),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
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 516892aed..4173403a1 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -37,6 +37,7 @@ pub fn expand_deriving_partial_ord(
let trait_def = TraitDef {
span,
path: path_std!(cmp::PartialOrd),
+ skip_path_as_bound: false,
additional_bounds: vec![],
generics: Bounds::empty(),
supports_unions: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 4af7fd816..2cf614ed9 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -20,6 +20,7 @@ pub fn expand_deriving_debug(
let trait_def = TraitDef {
span,
path: path_std!(fmt::Debug),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index 7174dbbe7..d669f6168 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -23,6 +23,7 @@ pub fn expand_deriving_rustc_decodable(
let trait_def = TraitDef {
span,
path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index a94c8a996..17df9fb27 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -24,6 +24,7 @@ pub fn expand_deriving_default(
let trait_def = TraitDef {
span,
path: Path::new(vec![kw::Default, sym::Default]),
+ skip_path_as_bound: has_a_default_variant(item),
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
@@ -262,3 +263,22 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for DetectNonVariantDefaultAttr<'a, '
}
}
}
+
+fn has_a_default_variant(item: &Annotatable) -> bool {
+ struct HasDefaultAttrOnVariant {
+ found: bool,
+ }
+
+ impl<'ast> rustc_ast::visit::Visitor<'ast> for HasDefaultAttrOnVariant {
+ fn visit_variant(&mut self, v: &'ast rustc_ast::Variant) {
+ if v.attrs.iter().any(|attr| attr.has_name(kw::Default)) {
+ self.found = true;
+ }
+ // no need to subrecurse.
+ }
+ }
+
+ let mut visitor = HasDefaultAttrOnVariant { found: false };
+ item.visit_with(&mut visitor);
+ visitor.found
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index b220e5423..f83f58b97 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -107,6 +107,7 @@ pub fn expand_deriving_rustc_encodable(
let trait_def = TraitDef {
span,
path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 3cc160adb..16ee3aa89 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -174,6 +174,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
use std::cell::RefCell;
use std::iter;
+use std::ops::Not;
use std::vec;
use thin_vec::thin_vec;
use ty::{Bounds, Path, Ref, Self_, Ty};
@@ -187,6 +188,9 @@ pub struct TraitDef<'a> {
/// Path of the trait, including any type parameters
pub path: Path,
+ /// Whether to skip adding the current trait as a bound to the type parameters of the type.
+ pub skip_path_as_bound: bool,
+
/// Additional bounds required of any type parameters of the type,
/// other than the current trait
pub additional_bounds: Vec<Ty>,
@@ -562,7 +566,7 @@ impl<'a> TraitDef<'a> {
tokens: None,
},
attrs: ast::AttrVec::new(),
- kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
+ kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias {
defaultness: ast::Defaultness::Final,
generics: Generics::default(),
where_clauses: (
@@ -596,7 +600,7 @@ impl<'a> TraitDef<'a> {
cx.trait_bound(p.to_path(cx, self.span, type_ident, generics))
}).chain(
// require the current trait
- iter::once(cx.trait_bound(trait_path.clone()))
+ 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()
@@ -1110,6 +1114,11 @@ impl<'a> MethodDef<'a> {
/// ```
/// is equivalent to:
/// ```
+ /// #![feature(core_intrinsics)]
+ /// enum A {
+ /// A1,
+ /// A2(i32)
+ /// }
/// impl ::core::cmp::PartialEq for A {
/// #[inline]
/// fn eq(&self, other: &A) -> bool {
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index f1f02e7ce..6e9d5f08b 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -22,6 +22,7 @@ pub fn expand_deriving_hash(
let hash_trait_def = TraitDef {
span,
path,
+ skip_path_as_bound: false,
additional_bounds: Vec::new(),
generics: Bounds::empty(),
supports_unions: false,
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index a65d0bad6..ee346047a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -131,6 +131,8 @@ fn inject_impl_of_structural_trait(
// Create generics param list for where clauses and impl headers
let mut generics = generics.clone();
+ let ctxt = span.ctxt();
+
// Create the type of `self`.
//
// in addition, remove defaults from generic params (impls cannot have them).
@@ -138,16 +140,18 @@ fn inject_impl_of_structural_trait(
.params
.iter_mut()
.map(|param| match &mut param.kind {
- ast::GenericParamKind::Lifetime => {
- ast::GenericArg::Lifetime(cx.lifetime(span, param.ident))
- }
+ ast::GenericParamKind::Lifetime => ast::GenericArg::Lifetime(
+ cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident),
+ ),
ast::GenericParamKind::Type { default } => {
*default = None;
- ast::GenericArg::Type(cx.ty_ident(span, param.ident))
+ ast::GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident))
}
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
*default = None;
- ast::GenericArg::Const(cx.const_ident(span, param.ident))
+ ast::GenericArg::Const(
+ cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident),
+ )
}
})
.collect();
@@ -174,6 +178,8 @@ fn inject_impl_of_structural_trait(
})
.cloned(),
);
+ // Mark as `automatically_derived` to avoid some silly lints.
+ attrs.push(cx.attribute(cx.meta_word(span, sym::automatically_derived)));
let newitem = cx.item(
span,
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 210048710..8b07c1106 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,271 +1,42 @@
-use ArgumentType::*;
-use Position::*;
-
-use rustc_ast as ast;
use rustc_ast::ptr::P;
+use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{token, BlockCheckMode, UnsafeSource};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_ast::Expr;
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, Applicability, MultiSpan, PResult};
use rustc_expand::base::{self, *};
use rustc_parse_format as parse;
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::symbol::{Ident, Symbol};
use rustc_span::{BytePos, InnerSpan, Span};
-use smallvec::SmallVec;
use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY;
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId};
-use rustc_parse_format::Count;
-use std::borrow::Cow;
-use std::collections::hash_map::Entry;
-
-#[derive(PartialEq)]
-enum ArgumentType {
- Placeholder(&'static str),
- Count,
-}
-
-enum Position {
- Exact(usize),
- Capture(usize),
- Named(Symbol, InnerSpan),
-}
-
-/// Indicates how positional named argument (i.e. an named argument which is used by position
-/// instead of by name) is used in format string
-/// * `Arg` is the actual argument to print
-/// * `Width` is width format argument
-/// * `Precision` is precion format argument
-/// Example: `{Arg:Width$.Precision$}
-#[derive(Debug, Eq, PartialEq)]
-enum PositionalNamedArgType {
- Arg,
- Width,
- Precision,
-}
-
-/// Contains information necessary to create a lint for a positional named argument
-#[derive(Debug)]
-struct PositionalNamedArg {
- ty: PositionalNamedArgType,
- /// The piece of the using this argument (multiple pieces can use the same argument)
- cur_piece: usize,
- /// The InnerSpan for in the string to be replaced with the named argument
- /// This will be None when the position is implicit
- inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
- /// The name to use instead of the position
- replacement: Symbol,
- /// The span for the positional named argument (so the lint can point a message to it)
- positional_named_arg_span: Span,
- has_formatting: bool,
-}
-
-impl PositionalNamedArg {
- /// Determines:
- /// 1) span to be replaced with the name of the named argument and
- /// 2) span to be underlined for error messages
- fn get_positional_arg_spans(&self, cx: &Context<'_, '_>) -> (Option<Span>, Option<Span>) {
- if let Some(inner_span) = &self.inner_span_to_replace {
- let span =
- cx.fmtsp.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end });
- (Some(span), Some(span))
- } else if self.ty == PositionalNamedArgType::Arg {
- // In the case of a named argument whose position is implicit, if the argument *has*
- // formatting, there will not be a span to replace. Instead, we insert the name after
- // the `{`, which will be the first character of arg_span. If the argument does *not*
- // have formatting, there may or may not be a span to replace. This is because
- // whitespace is allowed in arguments without formatting (such as `format!("{ }", 1);`)
- // but is not allowed in arguments with formatting (an error will be generated in cases
- // like `format!("{ :1.1}", 1.0f32);`.
- // For the message span, if there is formatting, we want to use the opening `{` and the
- // next character, which will the `:` indicating the start of formatting. If there is
- // not any formatting, we want to underline the entire span.
- cx.arg_spans.get(self.cur_piece).map_or((None, None), |arg_span| {
- if self.has_formatting {
- (
- Some(arg_span.with_lo(arg_span.lo() + BytePos(1)).shrink_to_lo()),
- Some(arg_span.with_hi(arg_span.lo() + BytePos(2))),
- )
- } else {
- let replace_start = arg_span.lo() + BytePos(1);
- let replace_end = arg_span.hi() - BytePos(1);
- let to_replace = arg_span.with_lo(replace_start).with_hi(replace_end);
- (Some(to_replace), Some(*arg_span))
- }
- })
- } else {
- (None, None)
- }
- }
-}
-
-/// Encapsulates all the named arguments that have been used positionally
-#[derive(Debug)]
-struct PositionalNamedArgsLint {
- positional_named_args: Vec<PositionalNamedArg>,
-}
-
-impl PositionalNamedArgsLint {
- /// For a given positional argument, check if the index is for a named argument.
- ///
- /// Since positional arguments are required to come before named arguments, if the positional
- /// index is greater than or equal to the start of named arguments, we know it's a named
- /// argument used positionally.
- ///
- /// Example:
- /// println!("{} {} {2}", 0, a=1, b=2);
- ///
- /// In this case, the first piece (`{}`) would be ArgumentImplicitlyIs with an index of 0. The
- /// total number of arguments is 3 and the number of named arguments is 2, so the start of named
- /// arguments is index 1. Therefore, the index of 0 is okay.
- ///
- /// The second piece (`{}`) would be ArgumentImplicitlyIs with an index of 1, which is the start
- /// of named arguments, and so we should add a lint to use the named argument `a`.
- ///
- /// The third piece (`{2}`) would be ArgumentIs with an index of 2, which is greater than the
- /// start of named arguments, and so we should add a lint to use the named argument `b`.
- ///
- /// This same check also works for width and precision formatting when either or both are
- /// CountIsParam, which contains an index into the arguments.
- fn maybe_add_positional_named_arg(
- &mut self,
- arg: Option<&FormatArg>,
- ty: PositionalNamedArgType,
- cur_piece: usize,
- inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
- has_formatting: bool,
- ) {
- if let Some(arg) = arg {
- if let Some(name) = arg.name {
- self.push(name, ty, cur_piece, inner_span_to_replace, has_formatting)
- }
- }
- }
- /// Construct a PositionalNamedArg struct and push it into the vec of positional
- /// named arguments.
- fn push(
- &mut self,
- arg_name: Ident,
- ty: PositionalNamedArgType,
- cur_piece: usize,
- inner_span_to_replace: Option<rustc_parse_format::InnerSpan>,
- has_formatting: bool,
- ) {
- // In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in
- // the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is
- // `Precision`.
- let inner_span_to_replace = if ty == PositionalNamedArgType::Precision {
- inner_span_to_replace
- .map(|is| rustc_parse_format::InnerSpan { start: is.start + 1, end: is.end })
- } else {
- inner_span_to_replace
- };
- self.positional_named_args.push(PositionalNamedArg {
- ty,
- cur_piece,
- inner_span_to_replace,
- replacement: arg_name.name,
- positional_named_arg_span: arg_name.span,
- has_formatting,
- });
- }
-}
-
-struct Context<'a, 'b> {
- ecx: &'a mut ExtCtxt<'b>,
- /// The macro's call site. References to unstable formatting internals must
- /// use this span to pass the stability checker.
- macsp: Span,
- /// The span of the format string literal.
- fmtsp: Span,
-
- /// List of parsed argument expressions.
- /// Named expressions are resolved early, and are appended to the end of
- /// argument expressions.
- ///
- /// Example showing the various data structures in motion:
- ///
- /// * Original: `"{foo:o} {:o} {foo:x} {0:x} {1:o} {:x} {1:x} {0:o}"`
- /// * Implicit argument resolution: `"{foo:o} {0:o} {foo:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
- /// * Name resolution: `"{2:o} {0:o} {2:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
- /// * `arg_types` (in JSON): `[[0, 1, 0], [0, 1, 1], [0, 1]]`
- /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
- /// * `names` (in JSON): `{"foo": 2}`
- args: Vec<FormatArg>,
- /// The number of arguments that were added by implicit capturing.
- num_captured_args: usize,
- /// Placeholder slot numbers indexed by argument.
- arg_types: Vec<Vec<usize>>,
- /// Unique format specs seen for each argument.
- arg_unique_types: Vec<Vec<ArgumentType>>,
- /// Map from named arguments to their resolved indices.
- names: FxHashMap<Symbol, usize>,
-
- /// The latest consecutive literal strings, or empty if there weren't any.
- literal: String,
+mod ast;
+use ast::*;
- /// Collection of the compiled `rt::Argument` structures
- pieces: Vec<P<ast::Expr>>,
- /// Collection of string literals
- str_pieces: Vec<P<ast::Expr>>,
- /// Stays `true` if all formatting parameters are default (as in "{}{}").
- all_pieces_simple: bool,
+mod expand;
+use expand::expand_parsed_format_args;
- /// Mapping between positional argument references and indices into the
- /// final generated static argument array. We record the starting indices
- /// corresponding to each positional argument, and number of references
- /// consumed so far for each argument, to facilitate correct `Position`
- /// mapping in `build_piece`. In effect this can be seen as a "flattened"
- /// version of `arg_unique_types`.
- ///
- /// Again with the example described above in docstring for `args`:
- ///
- /// * `arg_index_map` (in JSON): `[[0, 1, 0], [2, 3, 3], [4, 5]]`
- arg_index_map: Vec<Vec<usize>>,
+// 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.
- /// Starting offset of count argument slots.
- count_args_index_offset: usize,
+// See format/ast.rs for the FormatArgs structure and glossary.
- /// Count argument slots and tracking data structures.
- /// Count arguments are separately tracked for de-duplication in case
- /// multiple references are made to one argument. For example, in this
- /// format string:
- ///
- /// * Original: `"{:.*} {:.foo$} {1:.*} {:.0$}"`
- /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
- /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
- /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
- /// * `count_args`: `vec![0, 5, 3]`
- count_args: Vec<usize>,
- /// Relative slot numbers for count arguments.
- count_positions: FxHashMap<usize, usize>,
- /// Number of count slots assigned.
- count_positions_count: usize,
-
- /// Current position of the implicit positional arg pointer, as if it
- /// still existed in this phase of processing.
- /// Used only for `all_pieces_simple` tracking in `build_piece`.
- curarg: usize,
- /// Current piece being evaluated, used for error reporting.
- curpiece: usize,
- /// Keep track of invalid references to positional arguments.
- invalid_refs: Vec<(usize, usize)>,
- /// Spans of all the formatting arguments, in order.
- arg_spans: Vec<Span>,
- /// All the formatting arguments that have formatting flags set, in order for diagnostics.
- arg_with_formatting: Vec<parse::FormatSpec<'a>>,
-
- /// Whether this format string came from a string literal, as opposed to a macro.
- is_literal: bool,
- unused_names_lint: PositionalNamedArgsLint,
-}
-
-pub struct FormatArg {
- expr: P<ast::Expr>,
- name: Option<Ident>,
+// Only used in parse_args and report_invalid_references,
+// to indicate how a referred argument was used.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum PositionUsedAs {
+ Placeholder(Option<Span>),
+ Precision,
+ Width,
}
+use PositionUsedAs::*;
/// Parses the arguments from the given list of tokens, returning the diagnostic
/// if there's a parse error so we can continue parsing other format!
@@ -274,15 +45,14 @@ pub struct FormatArg {
/// If parsing succeeds, the return value is:
///
/// ```text
-/// Some((fmtstr, parsed arguments, index map for named arguments))
+/// Ok((fmtstr, parsed arguments))
/// ```
fn parse_args<'a>(
ecx: &mut ExtCtxt<'a>,
sp: Span,
tts: TokenStream,
-) -> PResult<'a, (P<ast::Expr>, Vec<FormatArg>, FxHashMap<Symbol, usize>)> {
- let mut args = Vec::<FormatArg>::new();
- let mut names = FxHashMap::<Symbol, usize>::default();
+) -> PResult<'a, (P<Expr>, FormatArguments)> {
+ let mut args = FormatArguments::new();
let mut p = ecx.new_parser_from_tts(tts);
@@ -311,7 +81,6 @@ fn parse_args<'a>(
};
let mut first = true;
- let mut named = false;
while p.token != token::Eof {
if !p.eat(&token::Comma) {
@@ -343,879 +112,54 @@ fn parse_args<'a>(
} // accept trailing commas
match p.token.ident() {
Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => {
- named = true;
p.bump();
p.expect(&token::Eq)?;
- let e = p.parse_expr()?;
- if let Some(&prev) = names.get(&ident.name) {
- ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident))
- .span_label(args[prev].expr.span, "previously here")
- .span_label(e.span, "duplicate argument")
- .emit();
+ let expr = p.parse_expr()?;
+ if let Some((_, prev)) = args.by_name(ident.name) {
+ ecx.struct_span_err(
+ ident.span,
+ &format!("duplicate argument named `{}`", ident),
+ )
+ .span_label(prev.kind.ident().unwrap().span, "previously here")
+ .span_label(ident.span, "duplicate argument")
+ .emit();
continue;
}
-
- // Resolve names into slots early.
- // Since all the positional args are already seen at this point
- // if the input is valid, we can simply append to the positional
- // args. And remember the names.
- let slot = args.len();
- names.insert(ident.name, slot);
- args.push(FormatArg { expr: e, name: Some(ident) });
+ args.add(FormatArgument { kind: FormatArgumentKind::Named(ident), expr });
}
_ => {
- let e = p.parse_expr()?;
- if named {
+ let expr = p.parse_expr()?;
+ if !args.named_args().is_empty() {
let mut err = ecx.struct_span_err(
- e.span,
+ expr.span,
"positional arguments cannot follow named arguments",
);
- err.span_label(e.span, "positional arguments must be before named arguments");
- for &pos in names.values() {
- err.span_label(args[pos].expr.span, "named argument");
+ err.span_label(
+ expr.span,
+ "positional arguments must be before named arguments",
+ );
+ for arg in args.named_args() {
+ if let Some(name) = arg.kind.ident() {
+ err.span_label(name.span.to(arg.expr.span), "named argument");
+ }
}
err.emit();
}
- args.push(FormatArg { expr: e, name: None });
+ args.add(FormatArgument { kind: FormatArgumentKind::Normal, expr });
}
}
}
- Ok((fmtstr, args, names))
+ Ok((fmtstr, args))
}
-impl<'a, 'b> Context<'a, 'b> {
- /// The number of arguments that were explicitly given.
- fn num_args(&self) -> usize {
- self.args.len() - self.num_captured_args
- }
-
- fn resolve_name_inplace(&mut self, p: &mut parse::Piece<'_>) {
- // NOTE: the `unwrap_or` branch is needed in case of invalid format
- // arguments, e.g., `format_args!("{foo}")`.
- let lookup = |s: &str| self.names.get(&Symbol::intern(s)).copied().unwrap_or(0);
-
- match *p {
- parse::String(_) => {}
- parse::NextArgument(ref mut arg) => {
- if let parse::ArgumentNamed(s) = arg.position {
- arg.position = parse::ArgumentIs(lookup(s));
- }
- if let parse::CountIsName(s, _) = arg.format.width {
- arg.format.width = parse::CountIsParam(lookup(s));
- }
- if let parse::CountIsName(s, _) = arg.format.precision {
- arg.format.precision = parse::CountIsParam(lookup(s));
- }
- }
- }
- }
-
- /// Verifies one piece of a parse string, and remembers it if valid.
- /// All errors are not emitted as fatal so we can continue giving errors
- /// about this and possibly other format strings.
- fn verify_piece(&mut self, p: &parse::Piece<'a>) {
- match *p {
- parse::String(..) => {}
- parse::NextArgument(ref arg) => {
- // width/precision first, if they have implicit positional
- // parameters it makes more sense to consume them first.
- self.verify_count(
- arg.format.width,
- &arg.format.width_span,
- PositionalNamedArgType::Width,
- );
- self.verify_count(
- arg.format.precision,
- &arg.format.precision_span,
- PositionalNamedArgType::Precision,
- );
-
- let has_precision = arg.format.precision != Count::CountImplied;
- let has_width = arg.format.width != Count::CountImplied;
-
- if has_precision || has_width {
- // push before named params are resolved to aid diagnostics
- self.arg_with_formatting.push(arg.format);
- }
-
- // argument second, if it's an implicit positional parameter
- // it's written second, so it should come after width/precision.
- let pos = match arg.position {
- parse::ArgumentIs(i) => {
- self.unused_names_lint.maybe_add_positional_named_arg(
- self.args.get(i),
- PositionalNamedArgType::Arg,
- self.curpiece,
- Some(arg.position_span),
- has_precision || has_width,
- );
-
- Exact(i)
- }
- parse::ArgumentImplicitlyIs(i) => {
- self.unused_names_lint.maybe_add_positional_named_arg(
- self.args.get(i),
- PositionalNamedArgType::Arg,
- self.curpiece,
- None,
- has_precision || has_width,
- );
- Exact(i)
- }
- parse::ArgumentNamed(s) => {
- let symbol = Symbol::intern(s);
- let span = arg.position_span;
- Named(symbol, InnerSpan::new(span.start, span.end))
- }
- };
-
- let ty = Placeholder(match arg.format.ty {
- "" => "Display",
- "?" => "Debug",
- "e" => "LowerExp",
- "E" => "UpperExp",
- "o" => "Octal",
- "p" => "Pointer",
- "b" => "Binary",
- "x" => "LowerHex",
- "X" => "UpperHex",
- _ => {
- let fmtsp = self.fmtsp;
- let sp = arg
- .format
- .ty_span
- .map(|sp| fmtsp.from_inner(InnerSpan::new(sp.start, sp.end)));
- let mut err = self.ecx.struct_span_err(
- sp.unwrap_or(fmtsp),
- &format!("unknown format trait `{}`", arg.format.ty),
- );
- err.note(
- "the only appropriate formatting traits are:\n\
- - ``, which uses the `Display` trait\n\
- - `?`, which uses the `Debug` trait\n\
- - `e`, which uses the `LowerExp` trait\n\
- - `E`, which uses the `UpperExp` trait\n\
- - `o`, which uses the `Octal` trait\n\
- - `p`, which uses the `Pointer` trait\n\
- - `b`, which uses the `Binary` trait\n\
- - `x`, which uses the `LowerHex` trait\n\
- - `X`, which uses the `UpperHex` trait",
- );
- if let Some(sp) = sp {
- for (fmt, name) in &[
- ("", "Display"),
- ("?", "Debug"),
- ("e", "LowerExp"),
- ("E", "UpperExp"),
- ("o", "Octal"),
- ("p", "Pointer"),
- ("b", "Binary"),
- ("x", "LowerHex"),
- ("X", "UpperHex"),
- ] {
- // FIXME: rustfix (`run-rustfix`) fails to apply suggestions.
- // > "Cannot replace slice of data that was already replaced"
- err.tool_only_span_suggestion(
- sp,
- &format!("use the `{}` trait", name),
- *fmt,
- Applicability::MaybeIncorrect,
- );
- }
- }
- err.emit();
- "<invalid>"
- }
- });
- self.verify_arg_type(pos, ty);
- self.curpiece += 1;
- }
- }
- }
-
- fn verify_count(
- &mut self,
- c: parse::Count<'_>,
- inner_span: &Option<rustc_parse_format::InnerSpan>,
- named_arg_type: PositionalNamedArgType,
- ) {
- match c {
- parse::CountImplied | parse::CountIs(..) => {}
- parse::CountIsParam(i) | parse::CountIsStar(i) => {
- self.unused_names_lint.maybe_add_positional_named_arg(
- self.args.get(i),
- named_arg_type,
- self.curpiece,
- *inner_span,
- true,
- );
- self.verify_arg_type(Exact(i), Count);
- }
- parse::CountIsName(s, span) => {
- self.verify_arg_type(
- Named(Symbol::intern(s), InnerSpan::new(span.start, span.end)),
- Count,
- );
- }
- }
- }
-
- fn describe_num_args(&self) -> Cow<'_, str> {
- match self.num_args() {
- 0 => "no arguments were given".into(),
- 1 => "there is 1 argument".into(),
- x => format!("there are {} arguments", x).into(),
- }
- }
-
- /// Handle invalid references to positional arguments. Output different
- /// errors for the case where all arguments are positional and for when
- /// there are named arguments or numbered positional arguments in the
- /// format string.
- fn report_invalid_references(&self, numbered_position_args: bool) {
- let mut e;
- let sp = if !self.arg_spans.is_empty() {
- // Point at the formatting arguments.
- MultiSpan::from_spans(self.arg_spans.clone())
- } else {
- MultiSpan::from_span(self.fmtsp)
- };
- let refs =
- self.invalid_refs.iter().map(|(r, pos)| (r.to_string(), self.arg_spans.get(*pos)));
-
- let mut zero_based_note = false;
-
- let count = self.pieces.len()
- + self
- .arg_with_formatting
- .iter()
- .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
- .count();
- if self.names.is_empty() && !numbered_position_args && count != self.num_args() {
- e = self.ecx.struct_span_err(
- sp,
- &format!(
- "{} positional argument{} in format string, but {}",
- count,
- pluralize!(count),
- self.describe_num_args(),
- ),
- );
- for arg in &self.args {
- // Point at the arguments that will be formatted.
- e.span_label(arg.expr.span, "");
- }
- } else {
- let (mut refs, spans): (Vec<_>, Vec<_>) = refs.unzip();
- // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
- // for `println!("{7:7$}", 1);`
- refs.sort();
- refs.dedup();
- let spans: Vec<_> = spans.into_iter().filter_map(|sp| sp.copied()).collect();
- let sp = if self.arg_spans.is_empty() || spans.is_empty() {
- MultiSpan::from_span(self.fmtsp)
- } else {
- MultiSpan::from_spans(spans)
- };
- let arg_list = if refs.len() == 1 {
- format!("argument {}", refs[0])
- } else {
- let reg = refs.pop().unwrap();
- format!("arguments {head} and {tail}", head = refs.join(", "), tail = reg)
- };
-
- e = self.ecx.struct_span_err(
- sp,
- &format!(
- "invalid reference to positional {} ({})",
- arg_list,
- self.describe_num_args()
- ),
- );
- zero_based_note = true;
- };
-
- for fmt in &self.arg_with_formatting {
- if let Some(span) = fmt.precision_span {
- let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
- match fmt.precision {
- parse::CountIsParam(pos) if pos >= self.num_args() => {
- e.span_label(
- span,
- &format!(
- "this precision flag expects an `usize` argument at position {}, \
- but {}",
- pos,
- self.describe_num_args(),
- ),
- );
- zero_based_note = true;
- }
- parse::CountIsStar(pos) => {
- let count = self.pieces.len()
- + self
- .arg_with_formatting
- .iter()
- .filter(|fmt| matches!(fmt.precision, parse::CountIsStar(_)))
- .count();
- e.span_label(
- span,
- &format!(
- "this precision flag adds an extra required argument at position {}, \
- which is why there {} expected",
- pos,
- if count == 1 {
- "is 1 argument".to_string()
- } else {
- format!("are {} arguments", count)
- },
- ),
- );
- if let Some(arg) = self.args.get(pos) {
- e.span_label(
- arg.expr.span,
- "this parameter corresponds to the precision flag",
- );
- }
- zero_based_note = true;
- }
- _ => {}
- }
- }
- if let Some(span) = fmt.width_span {
- let span = self.fmtsp.from_inner(InnerSpan::new(span.start, span.end));
- match fmt.width {
- parse::CountIsParam(pos) if pos >= self.num_args() => {
- e.span_label(
- span,
- &format!(
- "this width flag expects an `usize` argument at position {}, \
- but {}",
- pos,
- self.describe_num_args(),
- ),
- );
- zero_based_note = true;
- }
- _ => {}
- }
- }
- }
- if zero_based_note {
- e.note("positional arguments are zero-based");
- }
- if !self.arg_with_formatting.is_empty() {
- e.note(
- "for information about formatting flags, visit \
- https://doc.rust-lang.org/std/fmt/index.html",
- );
- }
-
- e.emit();
- }
-
- /// Actually verifies and tracks a given format placeholder
- /// (a.k.a. argument).
- fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
- if let Exact(arg) = arg {
- if arg >= self.num_args() {
- self.invalid_refs.push((arg, self.curpiece));
- return;
- }
- }
-
- match arg {
- Exact(arg) | Capture(arg) => {
- match ty {
- Placeholder(_) => {
- // record every (position, type) combination only once
- let seen_ty = &mut self.arg_unique_types[arg];
- let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| {
- let i = seen_ty.len();
- seen_ty.push(ty);
- i
- });
- self.arg_types[arg].push(i);
- }
- Count => {
- if let Entry::Vacant(e) = self.count_positions.entry(arg) {
- let i = self.count_positions_count;
- e.insert(i);
- self.count_args.push(arg);
- self.count_positions_count += 1;
- }
- }
- }
- }
-
- Named(name, span) => {
- match self.names.get(&name) {
- Some(&idx) => {
- // Treat as positional arg.
- self.verify_arg_type(Capture(idx), ty)
- }
- None => {
- // For the moment capturing variables from format strings expanded from macros is
- // disabled (see RFC #2795)
- if self.is_literal {
- // Treat this name as a variable to capture from the surrounding scope
- let idx = self.args.len();
- self.arg_types.push(Vec::new());
- self.arg_unique_types.push(Vec::new());
- let span = if self.is_literal {
- self.fmtsp.from_inner(span)
- } else {
- self.fmtsp
- };
- self.num_captured_args += 1;
- self.args.push(FormatArg {
- expr: self.ecx.expr_ident(span, Ident::new(name, span)),
- name: Some(Ident::new(name, span)),
- });
- self.names.insert(name, idx);
- self.verify_arg_type(Capture(idx), ty)
- } else {
- let msg = format!("there is no argument named `{}`", name);
- let sp = if self.is_literal {
- self.fmtsp.from_inner(span)
- } else {
- self.fmtsp
- };
- let mut err = self.ecx.struct_span_err(sp, &msg);
-
- err.note(&format!(
- "did you intend to capture a variable `{}` from \
- the surrounding scope?",
- name
- ));
- err.note(
- "to avoid ambiguity, `format_args!` cannot capture variables \
- when the format string is expanded from a macro",
- );
-
- err.emit();
- }
- }
- }
- }
- }
- }
-
- /// Builds the mapping between format placeholders and argument objects.
- fn build_index_map(&mut self) {
- // NOTE: Keep the ordering the same as `into_expr`'s expansion would do!
- let args_len = self.args.len();
- self.arg_index_map.reserve(args_len);
-
- let mut sofar = 0usize;
-
- // Map the arguments
- for i in 0..args_len {
- let arg_types = &self.arg_types[i];
- let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::<Vec<_>>();
- self.arg_index_map.push(arg_offsets);
- sofar += self.arg_unique_types[i].len();
- }
-
- // Record starting index for counts, which appear just after arguments
- self.count_args_index_offset = sofar;
- }
-
- fn rtpath(ecx: &ExtCtxt<'_>, s: Symbol) -> Vec<Ident> {
- ecx.std_path(&[sym::fmt, sym::rt, sym::v1, s])
- }
-
- fn build_count(&self, c: parse::Count<'_>) -> P<ast::Expr> {
- let sp = self.macsp;
- let count = |c, arg| {
- let mut path = Context::rtpath(self.ecx, sym::Count);
- path.push(Ident::new(c, sp));
- match arg {
- Some(arg) => self.ecx.expr_call_global(sp, path, vec![arg]),
- None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
- }
- };
- match c {
- parse::CountIs(i) => count(sym::Is, Some(self.ecx.expr_usize(sp, i))),
- parse::CountIsParam(i) | parse::CountIsStar(i) => {
- // This needs mapping too, as `i` is referring to a macro
- // argument. If `i` is not found in `count_positions` then
- // the error had already been emitted elsewhere.
- let i = self.count_positions.get(&i).cloned().unwrap_or(0)
- + self.count_args_index_offset;
- count(sym::Param, Some(self.ecx.expr_usize(sp, i)))
- }
- parse::CountImplied => count(sym::Implied, None),
- // should never be the case, names are already resolved
- parse::CountIsName(..) => panic!("should never happen"),
- }
- }
-
- /// Build a literal expression from the accumulated string literals
- fn build_literal_string(&mut self) -> P<ast::Expr> {
- let sp = self.fmtsp;
- let s = Symbol::intern(&self.literal);
- self.literal.clear();
- self.ecx.expr_str(sp, s)
- }
-
- /// Builds a static `rt::Argument` from a `parse::Piece` or append
- /// to the `literal` string.
- fn build_piece(
- &mut self,
- piece: &parse::Piece<'a>,
- arg_index_consumed: &mut Vec<usize>,
- ) -> Option<P<ast::Expr>> {
- let sp = self.macsp;
- match *piece {
- parse::String(s) => {
- self.literal.push_str(s);
- None
- }
- parse::NextArgument(ref arg) => {
- // Build the position
- let pos = {
- match arg.position {
- parse::ArgumentIs(i, ..) | parse::ArgumentImplicitlyIs(i) => {
- // Map to index in final generated argument array
- // in case of multiple types specified
- let arg_idx = match arg_index_consumed.get_mut(i) {
- None => 0, // error already emitted elsewhere
- Some(offset) => {
- let idx_map = &self.arg_index_map[i];
- // unwrap_or branch: error already emitted elsewhere
- let arg_idx = *idx_map.get(*offset).unwrap_or(&0);
- *offset += 1;
- arg_idx
- }
- };
- self.ecx.expr_usize(sp, arg_idx)
- }
-
- // should never be the case, because names are already
- // resolved.
- parse::ArgumentNamed(..) => panic!("should never happen"),
- }
- };
-
- let simple_arg = parse::Argument {
- position: {
- // We don't have ArgumentNext any more, so we have to
- // track the current argument ourselves.
- let i = self.curarg;
- self.curarg += 1;
- parse::ArgumentIs(i)
- },
- position_span: arg.position_span,
- format: parse::FormatSpec {
- fill: None,
- align: parse::AlignUnknown,
- flags: 0,
- precision: parse::CountImplied,
- precision_span: arg.format.precision_span,
- width: parse::CountImplied,
- width_span: arg.format.width_span,
- ty: arg.format.ty,
- ty_span: arg.format.ty_span,
- },
- };
-
- let fill = arg.format.fill.unwrap_or(' ');
- let pos_simple = arg.position.index() == simple_arg.position.index();
-
- if !pos_simple || arg.format != simple_arg.format {
- self.all_pieces_simple = false;
- }
-
- // Build the format
- let fill = self.ecx.expr_char(sp, fill);
- let align = |name| {
- let mut p = Context::rtpath(self.ecx, sym::Alignment);
- p.push(Ident::new(name, sp));
- self.ecx.path_global(sp, p)
- };
- let align = match arg.format.align {
- parse::AlignLeft => align(sym::Left),
- parse::AlignRight => align(sym::Right),
- parse::AlignCenter => align(sym::Center),
- parse::AlignUnknown => align(sym::Unknown),
- };
- let align = self.ecx.expr_path(align);
- let flags = self.ecx.expr_u32(sp, arg.format.flags);
- let prec = self.build_count(arg.format.precision);
- let width = self.build_count(arg.format.width);
- let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::FormatSpec));
- let fmt = self.ecx.expr_struct(
- sp,
- path,
- vec![
- self.ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
- self.ecx.field_imm(sp, Ident::new(sym::align, sp), align),
- self.ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
- self.ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
- self.ecx.field_imm(sp, Ident::new(sym::width, sp), width),
- ],
- );
-
- let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, sym::Argument));
- Some(self.ecx.expr_struct(
- sp,
- path,
- vec![
- self.ecx.field_imm(sp, Ident::new(sym::position, sp), pos),
- self.ecx.field_imm(sp, Ident::new(sym::format, sp), fmt),
- ],
- ))
- }
- }
- }
-
- /// Actually builds the expression which the format_args! block will be
- /// expanded to.
- fn into_expr(self) -> P<ast::Expr> {
- let mut original_args = self.args;
- let mut fmt_args = Vec::with_capacity(
- self.arg_unique_types.iter().map(|v| v.len()).sum::<usize>() + self.count_args.len(),
- );
-
- // First, build up the static array which will become our precompiled
- // format "string"
- let pieces = self.ecx.expr_array_ref(self.fmtsp, self.str_pieces);
-
- // We need to construct a &[ArgumentV1] to pass into the fmt::Arguments
- // constructor. In general the expressions in this slice might be
- // permuted from their order in original_args (such as in the case of
- // "{1} {0}"), or may have multiple entries referring to the same
- // element of original_args ("{0} {0}").
- //
- // The following vector has one item per element of our output slice,
- // identifying the index of which element of original_args it's passing,
- // and that argument's type.
- let mut fmt_arg_index_and_ty = SmallVec::<[(usize, &ArgumentType); 8]>::new();
- for (i, unique_types) in self.arg_unique_types.iter().enumerate() {
- fmt_arg_index_and_ty.extend(unique_types.iter().map(|ty| (i, ty)));
- }
- fmt_arg_index_and_ty.extend(self.count_args.iter().map(|&i| (i, &Count)));
-
- // Figure out whether there are permuted or repeated elements. If not,
- // we can generate simpler code.
- //
- // The sequence has no indices out of order or repeated if: for every
- // adjacent pair of elements, the first one's index is less than the
- // second one's index.
- let nicely_ordered =
- fmt_arg_index_and_ty.array_windows().all(|[(i, _i_ty), (j, _j_ty)]| i < j);
-
- // We want to emit:
- //
- // [ArgumentV1::new(&$arg0, …), ArgumentV1::new(&$arg1, …), …]
- //
- // However, it's only legal to do so if $arg0, $arg1, … were written in
- // exactly that order by the programmer. When arguments are permuted, we
- // want them evaluated in the order written by the programmer, not in
- // the order provided to fmt::Arguments. When arguments are repeated, we
- // want the expression evaluated only once.
- //
- // Further, if any arg _after the first one_ contains a yield point such
- // as `await` or `yield`, the above short form is inconvenient for the
- // caller because it would keep a temporary of type ArgumentV1 alive
- // across the yield point. ArgumentV1 can't implement Send since it
- // holds a type-erased arbitrary type.
- //
- // Thus in the not nicely ordered case, and in the yielding case, we
- // emit the following instead:
- //
- // match (&$arg0, &$arg1, …) {
- // args => [ArgumentV1::new(args.$i, …), ArgumentV1::new(args.$j, …), …]
- // }
- //
- // for the sequence of indices $i, $j, … governed by fmt_arg_index_and_ty.
- // This more verbose representation ensures that all arguments are
- // evaluated a single time each, in the order written by the programmer,
- // and that the surrounding future/generator (if any) is Send whenever
- // possible.
- let no_need_for_match = nicely_ordered
- && !original_args.iter().skip(1).any(|arg| may_contain_yield_point(&arg.expr));
-
- for (arg_index, arg_ty) in fmt_arg_index_and_ty {
- let e = &mut original_args[arg_index].expr;
- let span = e.span;
- let arg = if no_need_for_match {
- let expansion_span = e.span.with_ctxt(self.macsp.ctxt());
- // The indices are strictly ordered so e has not been taken yet.
- self.ecx.expr_addr_of(expansion_span, P(e.take()))
- } else {
- let def_site = self.ecx.with_def_site_ctxt(span);
- let args_tuple = self.ecx.expr_ident(def_site, Ident::new(sym::args, def_site));
- let member = Ident::new(sym::integer(arg_index), def_site);
- self.ecx.expr(def_site, ast::ExprKind::Field(args_tuple, member))
- };
- fmt_args.push(Context::format_arg(self.ecx, self.macsp, span, arg_ty, arg));
- }
-
- let args_array = self.ecx.expr_array(self.macsp, fmt_args);
- let args_slice = self.ecx.expr_addr_of(
- self.macsp,
- if no_need_for_match {
- args_array
- } else {
- // In the !no_need_for_match case, none of the exprs were moved
- // away in the previous loop.
- //
- // This uses the arg span for `&arg` so that borrowck errors
- // point to the specific expression passed to the macro (the
- // span is otherwise unavailable in the MIR used by borrowck).
- let heads = original_args
- .into_iter()
- .map(|arg| {
- self.ecx.expr_addr_of(arg.expr.span.with_ctxt(self.macsp.ctxt()), arg.expr)
- })
- .collect();
-
- let pat = self.ecx.pat_ident(self.macsp, Ident::new(sym::args, self.macsp));
- let arm = self.ecx.arm(self.macsp, pat, args_array);
- let head = self.ecx.expr(self.macsp, ast::ExprKind::Tup(heads));
- self.ecx.expr_match(self.macsp, head, vec![arm])
- },
- );
-
- // Now create the fmt::Arguments struct with all our locals we created.
- let (fn_name, fn_args) = if self.all_pieces_simple {
- ("new_v1", vec![pieces, args_slice])
- } else {
- // Build up the static array which will store our precompiled
- // nonstandard placeholders, if there are any.
- let fmt = self.ecx.expr_array_ref(self.macsp, self.pieces);
-
- let path = self.ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]);
- let unsafe_arg = self.ecx.expr_call_global(self.macsp, path, Vec::new());
- let unsafe_expr = self.ecx.expr_block(P(ast::Block {
- stmts: vec![self.ecx.stmt_expr(unsafe_arg)],
- id: ast::DUMMY_NODE_ID,
- rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
- span: self.macsp,
- tokens: None,
- could_be_bare_literal: false,
- }));
-
- ("new_v1_formatted", vec![pieces, args_slice, fmt, unsafe_expr])
- };
-
- let path = self.ecx.std_path(&[sym::fmt, sym::Arguments, Symbol::intern(fn_name)]);
- self.ecx.expr_call_global(self.macsp, path, fn_args)
- }
-
- fn format_arg(
- ecx: &ExtCtxt<'_>,
- macsp: Span,
- mut sp: Span,
- ty: &ArgumentType,
- arg: P<ast::Expr>,
- ) -> P<ast::Expr> {
- sp = ecx.with_def_site_ctxt(sp);
- let trait_ = match *ty {
- Placeholder(trait_) if trait_ == "<invalid>" => return DummyResult::raw_expr(sp, true),
- Placeholder(trait_) => trait_,
- Count => {
- let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, sym::from_usize]);
- return ecx.expr_call_global(macsp, path, vec![arg]);
- }
- };
- let new_fn_name = match trait_ {
- "Display" => "new_display",
- "Debug" => "new_debug",
- "LowerExp" => "new_lower_exp",
- "UpperExp" => "new_upper_exp",
- "Octal" => "new_octal",
- "Pointer" => "new_pointer",
- "Binary" => "new_binary",
- "LowerHex" => "new_lower_hex",
- "UpperHex" => "new_upper_hex",
- _ => unreachable!(),
- };
-
- let path = ecx.std_path(&[sym::fmt, sym::ArgumentV1, Symbol::intern(new_fn_name)]);
- ecx.expr_call_global(sp, path, vec![arg])
- }
-}
-
-fn expand_format_args_impl<'cx>(
- ecx: &'cx mut ExtCtxt<'_>,
- mut sp: Span,
- tts: TokenStream,
- nl: bool,
-) -> Box<dyn base::MacResult + 'cx> {
- sp = ecx.with_def_site_ctxt(sp);
- match parse_args(ecx, sp, tts) {
- Ok((efmt, args, names)) => {
- MacEager::expr(expand_preparsed_format_args(ecx, sp, efmt, args, names, nl))
- }
- Err(mut err) => {
- err.emit();
- DummyResult::any(sp)
- }
- }
-}
-
-pub fn expand_format_args<'cx>(
- ecx: &'cx mut ExtCtxt<'_>,
- sp: Span,
- tts: TokenStream,
-) -> Box<dyn base::MacResult + 'cx> {
- expand_format_args_impl(ecx, sp, tts, false)
-}
-
-pub fn expand_format_args_nl<'cx>(
- ecx: &'cx mut ExtCtxt<'_>,
- sp: Span,
- tts: TokenStream,
-) -> Box<dyn base::MacResult + 'cx> {
- expand_format_args_impl(ecx, sp, tts, true)
-}
-
-fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>) {
- for named_arg in &cx.unused_names_lint.positional_named_args {
- let (position_sp_to_replace, position_sp_for_msg) = named_arg.get_positional_arg_spans(cx);
-
- let msg = format!("named argument `{}` is not used by name", named_arg.replacement);
-
- cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
- span: MultiSpan::from_span(named_arg.positional_named_arg_span),
- msg: msg.into(),
- node_id: ast::CRATE_NODE_ID,
- lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
- diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
- position_sp_to_replace,
- position_sp_for_msg,
- named_arg_sp: named_arg.positional_named_arg_span,
- named_arg_name: named_arg.replacement.to_string(),
- is_formatting_arg: named_arg.ty != PositionalNamedArgType::Arg,
- },
- });
- }
-}
-
-/// Take the various parts of `format_args!(efmt, args..., name=names...)`
-/// and construct the appropriate formatting expression.
-pub fn expand_preparsed_format_args(
+pub fn make_format_args(
ecx: &mut ExtCtxt<'_>,
- sp: Span,
- efmt: P<ast::Expr>,
- args: Vec<FormatArg>,
- names: FxHashMap<Symbol, usize>,
+ efmt: P<Expr>,
+ mut args: FormatArguments,
append_newline: bool,
-) -> P<ast::Expr> {
- // NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
- // `ArgumentType` does not derive `Clone`.
- let arg_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
- let arg_unique_types: Vec<_> = (0..args.len()).map(|_| Vec::new()).collect();
-
- let mut macsp = ecx.call_site();
- macsp = ecx.with_def_site_ctxt(macsp);
-
+) -> Result<FormatArgs, ()> {
let msg = "format argument must be a string literal";
- let fmt_sp = efmt.span;
- let efmt_kind_is_lit: bool = matches!(efmt.kind, ast::ExprKind::Lit(_));
+ let unexpanded_fmt_span = efmt.span;
let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
Ok(mut fmt) if append_newline => {
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
@@ -1224,13 +168,13 @@ pub fn expand_preparsed_format_args(
Ok(fmt) => fmt,
Err(err) => {
if let Some((mut err, suggested)) = err {
- let sugg_fmt = match args.len() {
+ let sugg_fmt = match args.explicit_args().len() {
0 => "{}".to_string(),
- _ => format!("{}{{}}", "{} ".repeat(args.len())),
+ _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
};
if !suggested {
err.span_suggestion(
- fmt_sp.shrink_to_lo(),
+ unexpanded_fmt_span.shrink_to_lo(),
"you might be missing a string literal to format with",
format!("\"{}\", ", sugg_fmt),
Applicability::MaybeIncorrect,
@@ -1238,17 +182,17 @@ pub fn expand_preparsed_format_args(
}
err.emit();
}
- return DummyResult::raw_expr(sp, true);
+ return Err(());
}
};
let str_style = match fmt_style {
- ast::StrStyle::Cooked => None,
- ast::StrStyle::Raw(raw) => Some(raw as usize),
+ rustc_ast::StrStyle::Cooked => None,
+ rustc_ast::StrStyle::Raw(raw) => Some(raw as usize),
};
let fmt_str = fmt_str.as_str(); // for the suggestions below
- let fmt_snippet = ecx.source_map().span_to_snippet(fmt_sp).ok();
+ let fmt_snippet = ecx.source_map().span_to_snippet(unexpanded_fmt_span).ok();
let mut parser = parse::Parser::new(
fmt_str,
str_style,
@@ -1257,18 +201,20 @@ pub fn expand_preparsed_format_args(
parse::ParseMode::Format,
);
- let mut unverified_pieces = Vec::new();
+ let mut pieces = Vec::new();
while let Some(piece) = parser.next() {
if !parser.errors.is_empty() {
break;
} else {
- unverified_pieces.push(piece);
+ pieces.push(piece);
}
}
+ let is_literal = parser.is_literal;
+
if !parser.errors.is_empty() {
let err = parser.errors.remove(0);
- let sp = if efmt_kind_is_lit {
+ let sp = if is_literal {
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end))
} else {
// The format string could be another macro invocation, e.g.:
@@ -1286,25 +232,21 @@ pub fn expand_preparsed_format_args(
if let Some(note) = err.note {
e.note(&note);
}
- if let Some((label, span)) = err.secondary_label {
- if efmt_kind_is_lit {
- e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
- }
+ if let Some((label, span)) = err.secondary_label && is_literal {
+ e.span_label(fmt_span.from_inner(InnerSpan::new(span.start, span.end)), label);
}
if err.should_be_replaced_with_positional_argument {
let captured_arg_span =
fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end));
- let n_positional_args =
- args.iter().rposition(|arg| arg.name.is_none()).map_or(0, |i| i + 1);
if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) {
- let span = match args[..n_positional_args].last() {
+ let span = match args.unnamed_args().last() {
Some(arg) => arg.expr.span,
- None => fmt_sp,
+ None => fmt_span,
};
e.multipart_suggestion_verbose(
"consider using a positional formatting argument instead",
vec![
- (captured_arg_span, n_positional_args.to_string()),
+ (captured_arg_span, args.unnamed_args().len().to_string()),
(span.shrink_to_hi(), format!(", {}", arg)),
],
Applicability::MachineApplicable,
@@ -1312,241 +254,626 @@ pub fn expand_preparsed_format_args(
}
}
e.emit();
- return DummyResult::raw_expr(sp, true);
+ return Err(());
}
- let arg_spans = parser
- .arg_places
- .iter()
- .map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
- .collect();
+ let to_span = |inner_span: rustc_parse_format::InnerSpan| {
+ is_literal.then(|| {
+ fmt_span.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end })
+ })
+ };
+
+ let mut used = vec![false; args.explicit_args().len()];
+ let mut invalid_refs = Vec::new();
+ let mut numeric_refences_to_named_arg = Vec::new();
- let mut cx = Context {
- ecx,
- args,
- num_captured_args: 0,
- arg_types,
- arg_unique_types,
- names,
- curarg: 0,
- curpiece: 0,
- arg_index_map: Vec::new(),
- count_args: Vec::new(),
- count_positions: FxHashMap::default(),
- count_positions_count: 0,
- count_args_index_offset: 0,
- literal: String::new(),
- pieces: Vec::with_capacity(unverified_pieces.len()),
- str_pieces: Vec::with_capacity(unverified_pieces.len()),
- all_pieces_simple: true,
- macsp,
- fmtsp: fmt_span,
- invalid_refs: Vec::new(),
- arg_spans,
- arg_with_formatting: Vec::new(),
- is_literal: parser.is_literal,
- unused_names_lint: PositionalNamedArgsLint { positional_named_args: vec![] },
+ enum ArgRef<'a> {
+ Index(usize),
+ Name(&'a str, Option<Span>),
+ }
+ use ArgRef::*;
+
+ let mut lookup_arg = |arg: ArgRef<'_>,
+ span: Option<Span>,
+ used_as: PositionUsedAs,
+ kind: FormatArgPositionKind|
+ -> FormatArgPosition {
+ let index = match arg {
+ Index(index) => {
+ if let Some(arg) = args.by_index(index) {
+ used[index] = true;
+ if arg.kind.ident().is_some() {
+ // This was a named argument, but it was used as a positional argument.
+ numeric_refences_to_named_arg.push((index, span, used_as));
+ }
+ Ok(index)
+ } else {
+ // Doesn't exist as an explicit argument.
+ invalid_refs.push((index, span, used_as, kind));
+ Err(index)
+ }
+ }
+ Name(name, span) => {
+ let name = Symbol::intern(name);
+ if let Some((index, _)) = args.by_name(name) {
+ // Name found in `args`, so we resolve it to its index.
+ if index < args.explicit_args().len() {
+ // Mark it as used, if it was an explicit argument.
+ used[index] = true;
+ }
+ Ok(index)
+ } else {
+ // Name not found in `args`, so we add it as an implicitly captured argument.
+ let span = span.unwrap_or(fmt_span);
+ let ident = Ident::new(name, span);
+ let expr = if is_literal {
+ ecx.expr_ident(span, ident)
+ } else {
+ // For the moment capturing variables from format strings expanded from macros is
+ // disabled (see RFC #2795)
+ ecx.struct_span_err(span, &format!("there is no argument named `{name}`"))
+ .note(format!("did you intend to capture a variable `{name}` from the surrounding scope?"))
+ .note("to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro")
+ .emit();
+ DummyResult::raw_expr(span, true)
+ };
+ Ok(args.add(FormatArgument { kind: FormatArgumentKind::Captured(ident), expr }))
+ }
+ }
+ };
+ FormatArgPosition { index, kind, span }
};
- // This needs to happen *after* the Parser has consumed all pieces to create all the spans
- let pieces = unverified_pieces
- .into_iter()
- .map(|mut piece| {
- cx.verify_piece(&piece);
- cx.resolve_name_inplace(&mut piece);
- piece
- })
- .collect::<Vec<_>>();
+ let mut template = Vec::new();
+ let mut unfinished_literal = String::new();
+ let mut placeholder_index = 0;
- let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| match *arg {
- parse::String(_) => false,
- parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(..)),
- });
+ for piece in pieces {
+ match piece {
+ parse::Piece::String(s) => {
+ unfinished_literal.push_str(s);
+ }
+ parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => {
+ if !unfinished_literal.is_empty() {
+ template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
+ unfinished_literal.clear();
+ }
- cx.build_index_map();
+ let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s));
+ placeholder_index += 1;
+
+ let position_span = to_span(position_span);
+ let argument = match position {
+ parse::ArgumentImplicitlyIs(i) => lookup_arg(
+ Index(i),
+ position_span,
+ Placeholder(span),
+ FormatArgPositionKind::Implicit,
+ ),
+ parse::ArgumentIs(i) => lookup_arg(
+ Index(i),
+ position_span,
+ Placeholder(span),
+ FormatArgPositionKind::Number,
+ ),
+ parse::ArgumentNamed(name) => lookup_arg(
+ Name(name, position_span),
+ position_span,
+ Placeholder(span),
+ FormatArgPositionKind::Named,
+ ),
+ };
- let mut arg_index_consumed = vec![0usize; cx.arg_index_map.len()];
+ let alignment = match format.align {
+ parse::AlignUnknown => None,
+ parse::AlignLeft => Some(FormatAlignment::Left),
+ parse::AlignRight => Some(FormatAlignment::Right),
+ parse::AlignCenter => Some(FormatAlignment::Center),
+ };
- for piece in pieces {
- if let Some(piece) = cx.build_piece(&piece, &mut arg_index_consumed) {
- let s = cx.build_literal_string();
- cx.str_pieces.push(s);
- cx.pieces.push(piece);
+ let format_trait = match format.ty {
+ "" => FormatTrait::Display,
+ "?" => FormatTrait::Debug,
+ "e" => FormatTrait::LowerExp,
+ "E" => FormatTrait::UpperExp,
+ "o" => FormatTrait::Octal,
+ "p" => FormatTrait::Pointer,
+ "b" => FormatTrait::Binary,
+ "x" => FormatTrait::LowerHex,
+ "X" => FormatTrait::UpperHex,
+ _ => {
+ invalid_placeholder_type_error(ecx, format.ty, format.ty_span, fmt_span);
+ FormatTrait::Display
+ }
+ };
+
+ let precision_span = format.precision_span.and_then(to_span);
+ let precision = match format.precision {
+ parse::CountIs(n) => Some(FormatCount::Literal(n)),
+ parse::CountIsName(name, name_span) => Some(FormatCount::Argument(lookup_arg(
+ Name(name, to_span(name_span)),
+ precision_span,
+ Precision,
+ FormatArgPositionKind::Named,
+ ))),
+ parse::CountIsParam(i) => Some(FormatCount::Argument(lookup_arg(
+ Index(i),
+ precision_span,
+ Precision,
+ FormatArgPositionKind::Number,
+ ))),
+ parse::CountIsStar(i) => Some(FormatCount::Argument(lookup_arg(
+ Index(i),
+ precision_span,
+ Precision,
+ FormatArgPositionKind::Implicit,
+ ))),
+ parse::CountImplied => None,
+ };
+
+ let width_span = format.width_span.and_then(to_span);
+ let width = match format.width {
+ parse::CountIs(n) => Some(FormatCount::Literal(n)),
+ parse::CountIsName(name, name_span) => Some(FormatCount::Argument(lookup_arg(
+ Name(name, to_span(name_span)),
+ width_span,
+ Width,
+ FormatArgPositionKind::Named,
+ ))),
+ parse::CountIsParam(i) => Some(FormatCount::Argument(lookup_arg(
+ Index(i),
+ width_span,
+ Width,
+ FormatArgPositionKind::Number,
+ ))),
+ parse::CountIsStar(_) => unreachable!(),
+ parse::CountImplied => None,
+ };
+
+ template.push(FormatArgsPiece::Placeholder(FormatPlaceholder {
+ argument,
+ span,
+ format_trait,
+ format_options: FormatOptions {
+ fill: format.fill,
+ alignment,
+ flags: format.flags,
+ precision,
+ width,
+ },
+ }));
+ }
}
}
- if !cx.literal.is_empty() {
- let s = cx.build_literal_string();
- cx.str_pieces.push(s);
+ if !unfinished_literal.is_empty() {
+ template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
}
- if !cx.invalid_refs.is_empty() {
- cx.report_invalid_references(numbered_position_args);
+ if !invalid_refs.is_empty() {
+ report_invalid_references(ecx, &invalid_refs, &template, fmt_span, &args, parser);
}
- // Make sure that all arguments were used and all arguments have types.
- let errs = cx
- .arg_types
+ let unused = used
.iter()
.enumerate()
- .filter(|(i, ty)| ty.is_empty() && !cx.count_positions.contains_key(&i))
+ .filter(|&(_, used)| !used)
.map(|(i, _)| {
- let msg = if cx.args[i].name.is_some() {
+ let msg = if let FormatArgumentKind::Named(_) = args.explicit_args()[i].kind {
"named argument never used"
} else {
"argument never used"
};
- (cx.args[i].expr.span, msg)
+ (args.explicit_args()[i].expr.span, msg)
})
.collect::<Vec<_>>();
- let errs_len = errs.len();
- if !errs.is_empty() {
- let args_used = cx.arg_types.len() - errs_len;
- let args_unused = errs_len;
+ if !unused.is_empty() {
+ // If there's a lot of unused arguments,
+ // let's check if this format arguments looks like another syntax (printf / shell).
+ let detect_foreign_fmt = unused.len() > args.explicit_args().len() / 2;
+ report_missing_placeholders(ecx, unused, detect_foreign_fmt, str_style, fmt_str, fmt_span);
+ }
- let mut diag = {
- if let [(sp, msg)] = &errs[..] {
- let mut diag = cx.ecx.struct_span_err(*sp, *msg);
- diag.span_label(*sp, *msg);
- diag
- } else {
- let mut diag = cx.ecx.struct_span_err(
- errs.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
- "multiple unused formatting arguments",
- );
- diag.span_label(cx.fmtsp, "multiple missing formatting specifiers");
- for (sp, msg) in errs {
- diag.span_label(sp, msg);
+ // Only check for unused named argument names if there are no other errors to avoid causing
+ // too much noise in output errors, such as when a named argument is entirely unused.
+ if invalid_refs.is_empty() && ecx.sess.err_count() == 0 {
+ for &(index, span, used_as) in &numeric_refences_to_named_arg {
+ let (position_sp_to_replace, position_sp_for_msg) = match used_as {
+ Placeholder(pspan) => (span, pspan),
+ Precision => {
+ // Strip the leading `.` for precision.
+ let span = span.map(|span| span.with_lo(span.lo() + BytePos(1)));
+ (span, span)
}
- diag
- }
- };
+ Width => (span, span),
+ };
+ let arg_name = args.explicit_args()[index].kind.ident().unwrap();
+ ecx.buffered_early_lint.push(BufferedEarlyLint {
+ span: arg_name.span.into(),
+ msg: format!("named argument `{}` is not used by name", arg_name.name).into(),
+ node_id: rustc_ast::CRATE_NODE_ID,
+ lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
+ diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
+ position_sp_to_replace,
+ position_sp_for_msg,
+ named_arg_sp: arg_name.span,
+ named_arg_name: arg_name.name.to_string(),
+ is_formatting_arg: matches!(used_as, Width | Precision),
+ },
+ });
+ }
+ }
- // Used to ensure we only report translations for *one* kind of foreign format.
- let mut found_foreign = false;
- // Decide if we want to look for foreign formatting directives.
- if args_used < args_unused {
- use super::format_foreign as foreign;
+ Ok(FormatArgs { span: fmt_span, template, arguments: args })
+}
- // The set of foreign substitutions we've explained. This prevents spamming the user
- // with `%d should be written as {}` over and over again.
- let mut explained = FxHashSet::default();
+fn invalid_placeholder_type_error(
+ ecx: &ExtCtxt<'_>,
+ ty: &str,
+ ty_span: Option<rustc_parse_format::InnerSpan>,
+ fmt_span: Span,
+) {
+ let sp = ty_span.map(|sp| fmt_span.from_inner(InnerSpan::new(sp.start, sp.end)));
+ let mut err =
+ ecx.struct_span_err(sp.unwrap_or(fmt_span), &format!("unknown format trait `{}`", ty));
+ err.note(
+ "the only appropriate formatting traits are:\n\
+ - ``, which uses the `Display` trait\n\
+ - `?`, which uses the `Debug` trait\n\
+ - `e`, which uses the `LowerExp` trait\n\
+ - `E`, which uses the `UpperExp` trait\n\
+ - `o`, which uses the `Octal` trait\n\
+ - `p`, which uses the `Pointer` trait\n\
+ - `b`, which uses the `Binary` trait\n\
+ - `x`, which uses the `LowerHex` trait\n\
+ - `X`, which uses the `UpperHex` trait",
+ );
+ if let Some(sp) = sp {
+ for (fmt, name) in &[
+ ("", "Display"),
+ ("?", "Debug"),
+ ("e", "LowerExp"),
+ ("E", "UpperExp"),
+ ("o", "Octal"),
+ ("p", "Pointer"),
+ ("b", "Binary"),
+ ("x", "LowerHex"),
+ ("X", "UpperHex"),
+ ] {
+ err.tool_only_span_suggestion(
+ sp,
+ &format!("use the `{}` trait", name),
+ *fmt,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ err.emit();
+}
- macro_rules! check_foreign {
- ($kind:ident) => {{
- let mut show_doc_note = false;
+fn report_missing_placeholders(
+ ecx: &mut ExtCtxt<'_>,
+ unused: Vec<(Span, &str)>,
+ detect_foreign_fmt: bool,
+ str_style: Option<usize>,
+ fmt_str: &str,
+ fmt_span: Span,
+) {
+ let mut diag = if let &[(span, msg)] = &unused[..] {
+ let mut diag = ecx.struct_span_err(span, msg);
+ diag.span_label(span, msg);
+ diag
+ } else {
+ let mut diag = ecx.struct_span_err(
+ unused.iter().map(|&(sp, _)| sp).collect::<Vec<Span>>(),
+ "multiple unused formatting arguments",
+ );
+ diag.span_label(fmt_span, "multiple missing formatting specifiers");
+ for &(span, msg) in &unused {
+ diag.span_label(span, msg);
+ }
+ diag
+ };
- let mut suggestions = vec![];
- // account for `"` and account for raw strings `r#`
- let padding = str_style.map(|i| i + 2).unwrap_or(1);
- for sub in foreign::$kind::iter_subs(fmt_str, padding) {
- let (trn, success) = match sub.translate() {
- Ok(trn) => (trn, true),
- Err(Some(msg)) => (msg, false),
+ // Used to ensure we only report translations for *one* kind of foreign format.
+ let mut found_foreign = false;
+
+ // Decide if we want to look for foreign formatting directives.
+ if detect_foreign_fmt {
+ use super::format_foreign as foreign;
+
+ // The set of foreign substitutions we've explained. This prevents spamming the user
+ // with `%d should be written as {}` over and over again.
+ let mut explained = FxHashSet::default();
+
+ macro_rules! check_foreign {
+ ($kind:ident) => {{
+ let mut show_doc_note = false;
+
+ let mut suggestions = vec![];
+ // account for `"` and account for raw strings `r#`
+ let padding = str_style.map(|i| i + 2).unwrap_or(1);
+ for sub in foreign::$kind::iter_subs(fmt_str, padding) {
+ let (trn, success) = match sub.translate() {
+ Ok(trn) => (trn, true),
+ Err(Some(msg)) => (msg, false),
+
+ // If it has no translation, don't call it out specifically.
+ _ => continue,
+ };
+
+ let pos = sub.position();
+ let sub = String::from(sub.as_str());
+ if explained.contains(&sub) {
+ continue;
+ }
+ explained.insert(sub.clone());
- // If it has no translation, don't call it out specifically.
- _ => continue,
- };
+ if !found_foreign {
+ found_foreign = true;
+ show_doc_note = true;
+ }
- let pos = sub.position();
- let sub = String::from(sub.as_str());
- if explained.contains(&sub) {
- continue;
- }
- explained.insert(sub.clone());
+ if let Some(inner_sp) = pos {
+ let sp = fmt_span.from_inner(inner_sp);
- if !found_foreign {
- found_foreign = true;
- show_doc_note = true;
+ if success {
+ suggestions.push((sp, trn));
+ } else {
+ diag.span_note(
+ sp,
+ &format!("format specifiers use curly braces, and {}", trn),
+ );
}
-
- if let Some(inner_sp) = pos {
- let sp = fmt_sp.from_inner(inner_sp);
-
- if success {
- suggestions.push((sp, trn));
- } else {
- diag.span_note(
- sp,
- &format!("format specifiers use curly braces, and {}", trn),
- );
- }
+ } else {
+ if success {
+ diag.help(&format!("`{}` should be written as `{}`", sub, trn));
} else {
- if success {
- diag.help(&format!("`{}` should be written as `{}`", sub, trn));
- } else {
- diag.note(&format!(
- "`{}` should use curly braces, and {}",
- sub, trn
- ));
- }
+ diag.note(&format!("`{}` should use curly braces, and {}", sub, trn));
}
}
+ }
- if show_doc_note {
- diag.note(concat!(
- stringify!($kind),
- " formatting not supported; see the documentation for `std::fmt`",
- ));
- }
- if suggestions.len() > 0 {
- diag.multipart_suggestion(
- "format specifiers use curly braces",
- suggestions,
- Applicability::MachineApplicable,
- );
- }
- }};
- }
-
- check_foreign!(printf);
- if !found_foreign {
- check_foreign!(shell);
- }
- }
- if !found_foreign && errs_len == 1 {
- diag.span_label(cx.fmtsp, "formatting specifier missing");
+ if show_doc_note {
+ diag.note(concat!(
+ stringify!($kind),
+ " formatting not supported; see the documentation for `std::fmt`",
+ ));
+ }
+ if suggestions.len() > 0 {
+ diag.multipart_suggestion(
+ "format specifiers use curly braces",
+ suggestions,
+ Applicability::MachineApplicable,
+ );
+ }
+ }};
}
- diag.emit();
- } else if cx.invalid_refs.is_empty() && cx.ecx.sess.err_count() == 0 {
- // Only check for unused named argument names if there are no other errors to avoid causing
- // too much noise in output errors, such as when a named argument is entirely unused.
- create_lints_for_named_arguments_used_positionally(&mut cx);
+ check_foreign!(printf);
+ if !found_foreign {
+ check_foreign!(shell);
+ }
+ }
+ if !found_foreign && unused.len() == 1 {
+ diag.span_label(fmt_span, "formatting specifier missing");
}
- cx.into_expr()
+ diag.emit();
}
-fn may_contain_yield_point(e: &ast::Expr) -> bool {
- struct MayContainYieldPoint(bool);
+/// Handle invalid references to positional arguments. Output different
+/// errors for the case where all arguments are positional and for when
+/// there are named arguments or numbered positional arguments in the
+/// format string.
+fn report_invalid_references(
+ ecx: &mut ExtCtxt<'_>,
+ invalid_refs: &[(usize, Option<Span>, PositionUsedAs, FormatArgPositionKind)],
+ template: &[FormatArgsPiece],
+ fmt_span: Span,
+ args: &FormatArguments,
+ parser: parse::Parser<'_>,
+) {
+ let num_args_desc = match args.explicit_args().len() {
+ 0 => "no arguments were given".to_string(),
+ 1 => "there is 1 argument".to_string(),
+ n => format!("there are {} arguments", n),
+ };
+
+ let mut e;
- 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);
+ if template.iter().all(|piece| match piece {
+ FormatArgsPiece::Placeholder(FormatPlaceholder {
+ argument: FormatArgPosition { kind: FormatArgPositionKind::Number, .. },
+ ..
+ }) => false,
+ FormatArgsPiece::Placeholder(FormatPlaceholder {
+ format_options:
+ FormatOptions {
+ precision:
+ Some(FormatCount::Argument(FormatArgPosition {
+ kind: FormatArgPositionKind::Number,
+ ..
+ })),
+ ..
+ }
+ | FormatOptions {
+ width:
+ Some(FormatCount::Argument(FormatArgPosition {
+ kind: FormatArgPositionKind::Number,
+ ..
+ })),
+ ..
+ },
+ ..
+ }) => false,
+ _ => true,
+ }) {
+ // There are no numeric positions.
+ // Collect all the implicit positions:
+ let mut spans = Vec::new();
+ let mut num_placeholders = 0;
+ for piece in template {
+ let mut placeholder = None;
+ // `{arg:.*}`
+ if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+ format_options:
+ FormatOptions {
+ precision:
+ Some(FormatCount::Argument(FormatArgPosition {
+ span,
+ kind: FormatArgPositionKind::Implicit,
+ ..
+ })),
+ ..
+ },
+ ..
+ }) = piece
+ {
+ placeholder = *span;
+ num_placeholders += 1;
}
+ // `{}`
+ if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+ argument: FormatArgPosition { kind: FormatArgPositionKind::Implicit, .. },
+ span,
+ ..
+ }) = piece
+ {
+ placeholder = *span;
+ num_placeholders += 1;
+ }
+ // For `{:.*}`, we only push one span.
+ spans.extend(placeholder);
}
-
- fn visit_mac_call(&mut self, _: &ast::MacCall) {
- self.0 = true;
+ let span = if spans.is_empty() {
+ MultiSpan::from_span(fmt_span)
+ } else {
+ MultiSpan::from_spans(spans)
+ };
+ e = ecx.struct_span_err(
+ span,
+ &format!(
+ "{} positional argument{} in format string, but {}",
+ num_placeholders,
+ pluralize!(num_placeholders),
+ num_args_desc,
+ ),
+ );
+ for arg in args.explicit_args() {
+ e.span_label(arg.expr.span, "");
+ }
+ // Point out `{:.*}` placeholders: those take an extra argument.
+ let mut has_precision_star = false;
+ for piece in template {
+ if let FormatArgsPiece::Placeholder(FormatPlaceholder {
+ format_options:
+ FormatOptions {
+ precision:
+ Some(FormatCount::Argument(FormatArgPosition {
+ index,
+ span: Some(span),
+ kind: FormatArgPositionKind::Implicit,
+ ..
+ })),
+ ..
+ },
+ ..
+ }) = piece
+ {
+ let (Ok(index) | Err(index)) = index;
+ has_precision_star = true;
+ e.span_label(
+ *span,
+ &format!(
+ "this precision flag adds an extra required argument at position {}, which is why there {} expected",
+ index,
+ if num_placeholders == 1 {
+ "is 1 argument".to_string()
+ } else {
+ format!("are {} arguments", num_placeholders)
+ },
+ ),
+ );
+ }
+ }
+ if has_precision_star {
+ e.note("positional arguments are zero-based");
}
+ } else {
+ let mut indexes: Vec<_> = invalid_refs.iter().map(|&(index, _, _, _)| index).collect();
+ // Avoid `invalid reference to positional arguments 7 and 7 (there is 1 argument)`
+ // for `println!("{7:7$}", 1);`
+ indexes.sort();
+ indexes.dedup();
+ let span: MultiSpan = if !parser.is_literal || parser.arg_places.is_empty() {
+ MultiSpan::from_span(fmt_span)
+ } else {
+ MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect())
+ };
+ let arg_list = if let &[index] = &indexes[..] {
+ format!("argument {index}")
+ } else {
+ let tail = indexes.pop().unwrap();
+ format!(
+ "arguments {head} and {tail}",
+ head = indexes.into_iter().map(|i| i.to_string()).collect::<Vec<_>>().join(", ")
+ )
+ };
+ e = ecx.struct_span_err(
+ span,
+ &format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+ );
+ e.note("positional arguments are zero-based");
+ }
- fn visit_attribute(&mut self, _: &ast::Attribute) {
- // Conservatively assume this may be a proc macro attribute in
- // expression position.
- self.0 = true;
+ if template.iter().any(|piece| match piece {
+ FormatArgsPiece::Placeholder(FormatPlaceholder { format_options: f, .. }) => {
+ *f != FormatOptions::default()
}
+ _ => false,
+ }) {
+ e.note("for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html");
+ }
+
+ e.emit();
+}
- fn visit_item(&mut self, _: &ast::Item) {
- // Do not recurse into nested items.
+fn expand_format_args_impl<'cx>(
+ ecx: &'cx mut ExtCtxt<'_>,
+ mut sp: Span,
+ tts: TokenStream,
+ nl: bool,
+) -> Box<dyn base::MacResult + 'cx> {
+ sp = ecx.with_def_site_ctxt(sp);
+ 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))
+ } else {
+ MacEager::expr(DummyResult::raw_expr(sp, true))
+ }
+ }
+ Err(mut err) => {
+ err.emit();
+ DummyResult::any(sp)
}
}
+}
+
+pub fn expand_format_args<'cx>(
+ ecx: &'cx mut ExtCtxt<'_>,
+ sp: Span,
+ tts: TokenStream,
+) -> Box<dyn base::MacResult + 'cx> {
+ expand_format_args_impl(ecx, sp, tts, false)
+}
- let mut visitor = MayContainYieldPoint(false);
- visitor.visit_expr(e);
- visitor.0
+pub fn expand_format_args_nl<'cx>(
+ ecx: &'cx mut ExtCtxt<'_>,
+ sp: Span,
+ tts: TokenStream,
+) -> Box<dyn base::MacResult + 'cx> {
+ expand_format_args_impl(ecx, sp, tts, true)
}
diff --git a/compiler/rustc_builtin_macros/src/format/ast.rs b/compiler/rustc_builtin_macros/src/format/ast.rs
new file mode 100644
index 000000000..01dbffa21
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/format/ast.rs
@@ -0,0 +1,240 @@
+use rustc_ast::ptr::P;
+use rustc_ast::Expr;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
+
+// Definitions:
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └──────────────────────────────────────────────┘
+// FormatArgs
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └─────────┘
+// argument
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └───────────────────┘
+// template
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └────┘└─────────┘└┘
+// pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └────┘ └┘
+// literal pieces
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └─────────┘
+// placeholder
+//
+// format_args!("hello {abc:.xyz$}!!", abc="world");
+// └─┘ └─┘
+// positions (could be names, numbers, empty, or `*`)
+
+/// (Parsed) format args.
+///
+/// Basically the "AST" for a complete `format_args!()`.
+///
+/// E.g., `format_args!("hello {name}");`.
+#[derive(Clone, Debug)]
+pub struct FormatArgs {
+ pub span: Span,
+ pub template: Vec<FormatArgsPiece>,
+ pub arguments: FormatArguments,
+}
+
+/// A piece of a format template string.
+///
+/// E.g. "hello" or "{name}".
+#[derive(Clone, Debug)]
+pub enum FormatArgsPiece {
+ Literal(Symbol),
+ Placeholder(FormatPlaceholder),
+}
+
+/// The arguments to format_args!().
+///
+/// E.g. `1, 2, name="ferris", n=3`,
+/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
+#[derive(Clone, Debug)]
+pub struct FormatArguments {
+ arguments: Vec<FormatArgument>,
+ num_unnamed_args: usize,
+ num_explicit_args: usize,
+ names: FxHashMap<Symbol, usize>,
+}
+
+impl FormatArguments {
+ pub fn new() -> Self {
+ Self {
+ arguments: Vec::new(),
+ names: FxHashMap::default(),
+ num_unnamed_args: 0,
+ num_explicit_args: 0,
+ }
+ }
+
+ pub fn add(&mut self, arg: FormatArgument) -> usize {
+ let index = self.arguments.len();
+ if let Some(name) = arg.kind.ident() {
+ self.names.insert(name.name, index);
+ } else if self.names.is_empty() {
+ // Only count the unnamed args before the first named arg.
+ // (Any later ones are errors.)
+ self.num_unnamed_args += 1;
+ }
+ if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
+ // This is an explicit argument.
+ // Make sure that all arguments so far are explcit.
+ assert_eq!(
+ self.num_explicit_args,
+ self.arguments.len(),
+ "captured arguments must be added last"
+ );
+ self.num_explicit_args += 1;
+ }
+ self.arguments.push(arg);
+ index
+ }
+
+ pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
+ let i = *self.names.get(&name)?;
+ Some((i, &self.arguments[i]))
+ }
+
+ pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
+ (i < self.num_explicit_args).then(|| &self.arguments[i])
+ }
+
+ pub fn unnamed_args(&self) -> &[FormatArgument] {
+ &self.arguments[..self.num_unnamed_args]
+ }
+
+ pub fn named_args(&self) -> &[FormatArgument] {
+ &self.arguments[self.num_unnamed_args..self.num_explicit_args]
+ }
+
+ pub fn explicit_args(&self) -> &[FormatArgument] {
+ &self.arguments[..self.num_explicit_args]
+ }
+
+ pub fn into_vec(self) -> Vec<FormatArgument> {
+ self.arguments
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct FormatArgument {
+ pub kind: FormatArgumentKind,
+ pub expr: P<Expr>,
+}
+
+#[derive(Clone, Debug)]
+pub enum FormatArgumentKind {
+ /// `format_args(…, arg)`
+ Normal,
+ /// `format_args(…, arg = 1)`
+ Named(Ident),
+ /// `format_args("… {arg} …")`
+ Captured(Ident),
+}
+
+impl FormatArgumentKind {
+ pub fn ident(&self) -> Option<Ident> {
+ match self {
+ &Self::Normal => None,
+ &Self::Named(id) => Some(id),
+ &Self::Captured(id) => Some(id),
+ }
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatPlaceholder {
+ /// Index into [`FormatArgs::arguments`].
+ pub argument: FormatArgPosition,
+ /// The span inside the format string for the full `{…}` placeholder.
+ pub span: Option<Span>,
+ /// `{}`, `{:?}`, or `{:x}`, etc.
+ pub format_trait: FormatTrait,
+ /// `{}` or `{:.5}` or `{:-^20}`, etc.
+ pub format_options: FormatOptions,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct FormatArgPosition {
+ /// Which argument this position refers to (Ok),
+ /// or would've referred to if it existed (Err).
+ pub index: Result<usize, usize>,
+ /// What kind of position this is. See [`FormatArgPositionKind`].
+ pub kind: FormatArgPositionKind,
+ /// The span of the name or number.
+ pub span: Option<Span>,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum FormatArgPositionKind {
+ /// `{}` or `{:.*}`
+ Implicit,
+ /// `{1}` or `{:1$}` or `{:.1$}`
+ Number,
+ /// `{a}` or `{:a$}` or `{:.a$}`
+ Named,
+}
+
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
+pub enum FormatTrait {
+ /// `{}`
+ Display,
+ /// `{:?}`
+ Debug,
+ /// `{:e}`
+ LowerExp,
+ /// `{:E}`
+ UpperExp,
+ /// `{:o}`
+ Octal,
+ /// `{:p}`
+ Pointer,
+ /// `{:b}`
+ Binary,
+ /// `{:x}`
+ LowerHex,
+ /// `{:X}`
+ UpperHex,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct FormatOptions {
+ /// The width. E.g. `{:5}` or `{:width$}`.
+ pub width: Option<FormatCount>,
+ /// The precision. E.g. `{:.5}` or `{:.precision$}`.
+ pub precision: Option<FormatCount>,
+ /// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
+ 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,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatAlignment {
+ /// `{:<}`
+ Left,
+ /// `{:>}`
+ Right,
+ /// `{:^}`
+ Center,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum FormatCount {
+ /// `{:5}` or `{:.5}`
+ Literal(usize),
+ /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
+ Argument(FormatArgPosition),
+}
diff --git a/compiler/rustc_builtin_macros/src/format/expand.rs b/compiler/rustc_builtin_macros/src/format/expand.rs
new file mode 100644
index 000000000..9dde5efcb
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/format/expand.rs
@@ -0,0 +1,353 @@
+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/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 8aeb3b82a..c7ea7de8f 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -7,9 +7,9 @@
#![feature(box_patterns)]
#![feature(decl_macro)]
#![feature(if_let_guard)]
+#![feature(is_some_and)]
#![feature(is_sorted)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(proc_macro_internals)]
#![feature(proc_macro_quote)]
#![recursion_limit = "256"]
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 7efb6cc61..fee5d04cd 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -36,13 +36,22 @@ pub fn expand_test_case(
let sp = ecx.with_def_site_ctxt(attr_sp);
let mut item = anno_item.expect_item();
item = item.map(|mut item| {
+ let test_path_symbol = Symbol::intern(&item_path(
+ // skip the name of the root module
+ &ecx.current_expansion.module.mod_path[1..],
+ &item.ident,
+ ));
item.vis = ast::Visibility {
span: item.vis.span,
kind: ast::VisibilityKind::Public,
tokens: None,
};
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
- item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)));
+ item.attrs.push(ecx.attribute(attr::mk_name_value_item_str(
+ Ident::new(sym::rustc_test_marker, sp),
+ test_path_symbol,
+ sp,
+ )));
item
});
@@ -115,7 +124,7 @@ pub fn expand_test_or_bench(
// reworked in the future to not need it, it'd be nice.
_ => diag.struct_span_err(attr_sp, msg).forget_guarantee(),
};
- err.span_label(attr_sp, "the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
+ err.span_label(attr_sp, "the `#[test]` macro causes a function to be run on a test and has no effect on non-functions")
.span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
.span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect)
.emit();
@@ -215,6 +224,12 @@ pub fn expand_test_or_bench(
)
};
+ let test_path_symbol = Symbol::intern(&item_path(
+ // skip the name of the root module
+ &cx.current_expansion.module.mod_path[1..],
+ &item.ident,
+ ));
+
let mut test_const = cx.item(
sp,
Ident::new(item.ident.name, sp),
@@ -224,9 +239,14 @@ pub fn expand_test_or_bench(
Ident::new(sym::cfg, attr_sp),
vec![attr::mk_nested_word_item(Ident::new(sym::test, attr_sp))],
)),
- // #[rustc_test_marker]
- cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
- ],
+ // #[rustc_test_marker = "test_case_sort_key"]
+ cx.attribute(attr::mk_name_value_item_str(
+ Ident::new(sym::rustc_test_marker, attr_sp),
+ test_path_symbol,
+ attr_sp,
+ )),
+ ]
+ .into(),
// const $ident: test::TestDescAndFn =
ast::ItemKind::Const(
ast::Defaultness::Final,
@@ -250,14 +270,7 @@ pub fn expand_test_or_bench(
cx.expr_call(
sp,
cx.expr_path(test_path("StaticTestName")),
- vec![cx.expr_str(
- sp,
- Symbol::intern(&item_path(
- // skip the name of the root module
- &cx.current_expansion.module.mod_path[1..],
- &item.ident,
- )),
- )],
+ vec![cx.expr_str(sp, test_path_symbol)],
),
),
// ignore: true | false
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 561ca00c7..b8b8351a3 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -18,9 +18,11 @@ use thin_vec::thin_vec;
use std::{iter, mem};
+#[derive(Clone)]
struct Test {
span: Span,
ident: Ident,
+ name: Symbol,
}
struct TestCtxt<'a> {
@@ -120,10 +122,10 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
fn flat_map_item(&mut self, i: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
let mut item = i.into_inner();
- if is_test_case(&self.cx.ext_cx.sess, &item) {
+ if let Some(name) = get_test_name(&self.cx.ext_cx.sess, &item) {
debug!("this is a test item");
- let test = Test { span: item.span, ident: item.ident };
+ let test = Test { span: item.span, ident: item.ident, name };
self.tests.push(test);
}
@@ -357,9 +359,12 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
debug!("building test vector from {} tests", cx.test_cases.len());
let ecx = &cx.ext_cx;
+ let mut tests = cx.test_cases.clone();
+ tests.sort_by(|a, b| a.name.as_str().cmp(&b.name.as_str()));
+
ecx.expr_array_ref(
sp,
- cx.test_cases
+ tests
.iter()
.map(|test| {
ecx.expr_addr_of(test.span, ecx.expr_path(ecx.path(test.span, vec![test.ident])))
@@ -368,8 +373,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P<ast::Expr> {
)
}
-fn is_test_case(sess: &Session, i: &ast::Item) -> bool {
- sess.contains_name(&i.attrs, sym::rustc_test_marker)
+fn get_test_name(sess: &Session, i: &ast::Item) -> Option<Symbol> {
+ sess.first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker)
}
fn get_test_runner(
diff --git a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
index e8897e9ae..5061010c8 100644
--- a/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
+++ b/compiler/rustc_codegen_cranelift/.github/workflows/main.yml
@@ -29,7 +29,11 @@ jobs:
matrix:
include:
- os: ubuntu-latest
+ 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:
@@ -112,7 +116,7 @@ jobs:
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v2
with:
- name: cg_clif-${{ runner.os }}
+ name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar.xz
- name: Upload prebuilt cg_clif (cross compile)
@@ -122,56 +126,89 @@ jobs:
name: cg_clif-${{ runner.os }}-cross-x86_64-mingw
path: cg_clif.tar.xz
- build_windows:
- runs-on: windows-latest
+ windows:
+ runs-on: ${{ matrix.os }}
timeout-minutes: 60
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ # Native Windows build with MSVC
+ - 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
+
steps:
- uses: actions/checkout@v3
- #- name: Cache cargo installed crates
- # uses: actions/cache@v2
- # with:
- # path: ~/.cargo/bin
- # key: ${{ runner.os }}-cargo-installed-crates
-
- #- name: Cache cargo registry and index
- # uses: actions/cache@v2
- # with:
- # path: |
- # ~/.cargo/registry
- # ~/.cargo/git
- # key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
-
- #- name: Cache cargo target dir
- # uses: actions/cache@v2
- # with:
- # path: target
- # key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+ - name: Cache cargo installed crates
+ uses: actions/cache@v2
+ with:
+ path: ~/.cargo/bin
+ key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-installed-crates
+
+ - name: Cache cargo registry and index
+ uses: actions/cache@v2
+ 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@v2
+ with:
+ path: target
+ key: ${{ runner.os }}-${{ matrix.env.TARGET_TRIPLE }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
+
+ - name: Set MinGW as the default toolchain
+ if: matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
+ run: rustup set default-host x86_64-pc-windows-gnu
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
git config --global core.autocrlf false
- rustup set default-host x86_64-pc-windows-gnu
rustc y.rs -o y.exe -g
./y.exe prepare
+ - name: Build 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: Build
- #name: Test
+ run: ./y.rs build --sysroot none
+
+ - name: Test
run: |
# Enable backtraces for easier debugging
- #$Env:RUST_BACKTRACE=1
+ $Env:RUST_BACKTRACE=1
# Reduce amount of benchmark runs as they are slow
- #$Env:COMPILE_RUNS=2
- #$Env:RUN_RUNS=2
+ $Env:COMPILE_RUNS=2
+ $Env:RUN_RUNS=2
# Enable extra checks
- #$Env:CG_CLIF_ENABLE_VERIFIER=1
-
- ./y.exe build
+ $Env:CG_CLIF_ENABLE_VERIFIER=1
+
+ # WIP Disable some tests
+
+ # 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
+
+ ./y.exe test
- name: Package prebuilt cg_clif
# don't use compression as xzip isn't supported by tar on windows and bzip2 hangs
@@ -180,5 +217,5 @@ jobs:
- name: Upload prebuilt cg_clif
uses: actions/upload-artifact@v2
with:
- name: cg_clif-${{ runner.os }}
+ name: cg_clif-${{ matrix.env.TARGET_TRIPLE }}
path: cg_clif.tar
diff --git a/compiler/rustc_codegen_cranelift/.vscode/settings.json b/compiler/rustc_codegen_cranelift/.vscode/settings.json
index d88309e41..13301bf20 100644
--- a/compiler/rustc_codegen_cranelift/.vscode/settings.json
+++ b/compiler/rustc_codegen_cranelift/.vscode/settings.json
@@ -7,7 +7,7 @@
"rust-analyzer.cargo.features": ["unstable-features"],
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
- //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",
+ //"./build_sysroot/sysroot_src/library/std/Cargo.toml",
{
"roots": [
"./example/mini_core.rs",
@@ -36,10 +36,10 @@
]
},
{
- "roots": ["./scripts/filter_profile.rs"],
+ "roots": ["./example/std_example.rs"],
"crates": [
{
- "root_module": "./scripts/filter_profile.rs",
+ "root_module": "./example/std_example.rs",
"edition": "2018",
"deps": [{ "crate": 1, "name": "std" }],
"cfg": [],
diff --git a/compiler/rustc_codegen_cranelift/Cargo.lock b/compiler/rustc_codegen_cranelift/Cargo.lock
index edae7e471..3fa9d56cd 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/Cargo.lock
@@ -25,6 +25,12 @@ version = "0.8.0"
source = "git+https://github.com/bjorn3/rust-ar.git?branch=do_not_remove_cg_clif_ranlib#de9ab0e56bf3a208381d342aa5b60f9ff2891648"
[[package]]
+name = "arrayvec"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
+
+[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -37,6 +43,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[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"
@@ -50,19 +62,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93945adbccc8d731503d3038814a51e8317497c9e205411820348132fa01a358"
+checksum = "44409ccf2d0f663920cab563d2b79fcd6b2e9a2bcc6e929fef76c8f82ad6c17a"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b482acc9d0d0d1ad3288a90a8150ee648be3dce8dc8c8669ff026f72debdc31"
+checksum = "98de2018ad96eb97f621f7d6b900a0cc661aec8d02ea4a50e56ecb48e5a2fcaf"
dependencies = [
+ "arrayvec",
+ "bumpalo",
"cranelift-bforest",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
@@ -77,30 +91,30 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9ec188d71e663192ef9048f204e410a7283b609942efc9fcc77da6d496edbb8"
+checksum = "5287ce36e6c4758fbaf298bd1a8697ad97a4f2375a3d1b61142ea538db4877e5"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ad794b1b1c2c7bd9f7b76cfe0f084eaf7753e55d56191c3f7d89e8fa4978b99"
+checksum = "2855c24219e2f08827f3f4ffb2da92e134ae8d8ecc185b11ec8f9878cf5f588e"
[[package]]
name = "cranelift-entity"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "342da0d5056f4119d3c311c4aab2460ceb6ee6e127bb395b76dd2279a09ea7a5"
+checksum = "0b65673279d75d34bf11af9660ae2dbd1c22e6d28f163f5c72f4e1dc56d56103"
[[package]]
name = "cranelift-frontend"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfff792f775b07d4d9cfe9f1c767ce755c6cbadda1bbd6db18a1c75ff9f7376a"
+checksum = "3ed2b3d7a4751163f6c4a349205ab1b7d9c00eecf19dcea48592ef1f7688eefc"
dependencies = [
"cranelift-codegen",
"log",
@@ -110,15 +124,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d51089478849f2ac8ef60a8a2d5346c8d4abfec0e45ac5b24530ef9f9499e1e"
+checksum = "3be64cecea9d90105fc6a2ba2d003e98c867c1d6c4c86cc878f97ad9fb916293"
[[package]]
name = "cranelift-jit"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "095936e41720f86004b4c57ce88e6a13af28646bb3a6fb4afbebd5ae90c50029"
+checksum = "f98ed42a70a0c9c388e34ec9477f57fc7300f541b1e5136a0e2ea02b1fac6015"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -134,9 +148,9 @@ dependencies = [
[[package]]
name = "cranelift-module"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "704a1aea4723d97eafe0fb7af110f6f6868b1ac95f5380bbc9adb2a3b8cf97e8"
+checksum = "d658ac7f156708bfccb647216cc8b9387469f50d352ba4ad80150541e4ae2d49"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -144,9 +158,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "885debe62f2078638d6585f54c9f05f5c2008f22ce5a2a9100ada785fc065dbd"
+checksum = "c4a03a6ac1b063e416ca4b93f6247978c991475e8271465340caa6f92f3c16a4"
dependencies = [
"cranelift-codegen",
"libc",
@@ -155,9 +169,9 @@ dependencies = [
[[package]]
name = "cranelift-object"
-version = "0.87.0"
+version = "0.88.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aac1310cf1081ae8eca916c92cd163b977c77cab6e831fa812273c26ff921816"
+checksum = "eef0b4119b645b870a43a036d76c0ada3a076b1f82e8b8487659304c8b09049b"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -232,9 +246,9 @@ checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
[[package]]
name = "libloading"
-version = "0.6.7"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883"
+checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd"
dependencies = [
"cfg-if",
"winapi",
diff --git a/compiler/rustc_codegen_cranelift/Cargo.toml b/compiler/rustc_codegen_cranelift/Cargo.toml
index e7c342748..09cf5b4a1 100644
--- a/compiler/rustc_codegen_cranelift/Cargo.toml
+++ b/compiler/rustc_codegen_cranelift/Cargo.toml
@@ -8,19 +8,19 @@ crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
-cranelift-codegen = { version = "0.87.0", features = ["unwind", "all-arch"] }
-cranelift-frontend = "0.87.0"
-cranelift-module = "0.87.0"
-cranelift-native = "0.87.0"
-cranelift-jit = { version = "0.87.0", optional = true }
-cranelift-object = "0.87.0"
+cranelift-codegen = { version = "0.88.1", features = ["unwind", "all-arch"] }
+cranelift-frontend = "0.88.1"
+cranelift-module = "0.88.1"
+cranelift-native = "0.88.1"
+cranelift-jit = { version = "0.88.1", optional = true }
+cranelift-object = "0.88.1"
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"] }
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.9.1"
-libloading = { version = "0.6.0", optional = true }
+libloading = { version = "0.7.3", optional = true }
once_cell = "1.10.0"
smallvec = "1.8.1"
diff --git a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
index 6c5043bb6..f6a9cb672 100644
--- a/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
+++ b/compiler/rustc_codegen_cranelift/build_sysroot/Cargo.lock
@@ -55,10 +55,20 @@ dependencies = [
]
[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-core",
+]
+
+[[package]]
name = "compiler_builtins"
-version = "0.1.79"
+version = "0.1.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"
+checksum = "18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"
dependencies = [
"rustc-std-workspace-core",
]
@@ -123,9 +133,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
-version = "0.2.5"
+version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "897cd85af6387be149f55acf168e41be176a02de7872403aaab184afc2f327e6"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"compiler_builtins",
"libc",
@@ -135,9 +145,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.132"
+version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
dependencies = [
"rustc-std-workspace-core",
]
@@ -182,7 +192,7 @@ name = "panic_abort"
version = "0.0.0"
dependencies = [
"alloc",
- "cfg-if",
+ "cfg-if 0.1.10",
"compiler_builtins",
"core",
"libc",
@@ -193,7 +203,7 @@ name = "panic_unwind"
version = "0.0.0"
dependencies = [
"alloc",
- "cfg-if",
+ "cfg-if 0.1.10",
"compiler_builtins",
"core",
"libc",
@@ -245,7 +255,7 @@ version = "0.0.0"
dependencies = [
"addr2line",
"alloc",
- "cfg-if",
+ "cfg-if 1.0.0",
"compiler_builtins",
"core",
"dlmalloc",
@@ -267,7 +277,7 @@ dependencies = [
name = "std_detect"
version = "0.1.5"
dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
"compiler_builtins",
"libc",
"rustc-std-workspace-alloc",
@@ -289,7 +299,7 @@ dependencies = [
name = "test"
version = "0.0.0"
dependencies = [
- "cfg-if",
+ "cfg-if 0.1.10",
"core",
"getopts",
"libc",
@@ -301,9 +311,9 @@ dependencies = [
[[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"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-core",
@@ -315,7 +325,7 @@ name = "unwind"
version = "0.0.0"
dependencies = [
"cc",
- "cfg-if",
+ "cfg-if 0.1.10",
"compiler_builtins",
"core",
"libc",
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
new file mode 100644
index 000000000..fae5b2716
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/build_system/abi_cafe.rs
@@ -0,0 +1,52 @@
+use std::env;
+use std::path::Path;
+
+use super::build_sysroot;
+use super::config;
+use super::prepare;
+use super::utils::{cargo_command, spawn_and_wait};
+use super::SysrootKind;
+
+pub(crate) fn run(
+ channel: &str,
+ sysroot_kind: SysrootKind,
+ target_dir: &Path,
+ cg_clif_dylib: &Path,
+ host_triple: &str,
+ target_triple: &str,
+) {
+ 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;
+ }
+
+ eprintln!("Building sysroot for abi-cafe");
+ build_sysroot::build_sysroot(
+ channel,
+ sysroot_kind,
+ target_dir,
+ cg_clif_dylib,
+ host_triple,
+ target_triple,
+ );
+
+ eprintln!("Running abi-cafe");
+ let abi_cafe_path = prepare::ABI_CAFE.source_dir();
+ env::set_current_dir(abi_cafe_path.clone()).unwrap();
+
+ let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
+
+ let mut cmd = cargo_command("cargo", "run", Some(target_triple), &abi_cafe_path);
+ cmd.arg("--");
+ cmd.arg("--pairs");
+ cmd.args(pairs);
+ cmd.arg("--add-rustc-codegen-backend");
+ cmd.arg(format!("cgclif:{}", cg_clif_dylib.display()));
+
+ spawn_and_wait(cmd);
+}
diff --git a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs b/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs
deleted file mode 100644
index 67dbd0a38..000000000
--- a/compiler/rustc_codegen_cranelift/build_system/abi_checker.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use super::build_sysroot;
-use super::config;
-use super::utils::spawn_and_wait;
-use build_system::SysrootKind;
-use std::env;
-use std::path::Path;
-use std::process::Command;
-
-pub(crate) fn run(
- channel: &str,
- sysroot_kind: SysrootKind,
- target_dir: &Path,
- cg_clif_build_dir: &Path,
- host_triple: &str,
- target_triple: &str,
-) {
- if !config::get_bool("testsuite.abi-checker") {
- eprintln!("[SKIP] abi-checker");
- return;
- }
-
- if host_triple != target_triple {
- eprintln!("[SKIP] abi-checker (cross-compilation not supported)");
- return;
- }
-
- eprintln!("Building sysroot for abi-checker");
- build_sysroot::build_sysroot(
- channel,
- sysroot_kind,
- target_dir,
- cg_clif_build_dir,
- host_triple,
- target_triple,
- );
-
- eprintln!("Running abi-checker");
- let mut abi_checker_path = env::current_dir().unwrap();
- abi_checker_path.push("abi-checker");
- env::set_current_dir(abi_checker_path.clone()).unwrap();
-
- let build_dir = abi_checker_path.parent().unwrap().join("build");
- let cg_clif_dylib_path = build_dir.join(if cfg!(windows) { "bin" } else { "lib" }).join(
- env::consts::DLL_PREFIX.to_string() + "rustc_codegen_cranelift" + env::consts::DLL_SUFFIX,
- );
-
- let pairs = ["rustc_calls_cgclif", "cgclif_calls_rustc", "cgclif_calls_cc", "cc_calls_cgclif"];
-
- let mut cmd = Command::new("cargo");
- cmd.arg("run");
- cmd.arg("--target");
- cmd.arg(target_triple);
- cmd.arg("--");
- cmd.arg("--pairs");
- cmd.args(pairs);
- cmd.arg("--add-rustc-codegen-backend");
- cmd.arg(format!("cgclif:{}", cg_clif_dylib_path.display()));
-
- spawn_and_wait(cmd);
-}
diff --git a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
index 9e59b8199..cda468bcf 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_backend.rs
@@ -1,16 +1,16 @@
use std::env;
-use std::path::{Path, PathBuf};
-use std::process::Command;
+use std::path::PathBuf;
-use super::utils::is_ci;
+use super::rustc_info::get_file_name;
+use super::utils::{cargo_command, is_ci};
pub(crate) fn build_backend(
channel: &str,
host_triple: &str,
use_unstable_features: bool,
) -> PathBuf {
- let mut cmd = Command::new("cargo");
- cmd.arg("build").arg("--target").arg(host_triple);
+ let source_dir = std::env::current_dir().unwrap();
+ let mut cmd = cargo_command("cargo", "build", Some(host_triple), &source_dir);
cmd.env("CARGO_BUILD_INCREMENTAL", "true"); // Force incr comp even in release mode
@@ -41,5 +41,9 @@ pub(crate) fn build_backend(
eprintln!("[BUILD] rustc_codegen_cranelift");
super::utils::spawn_and_wait(cmd);
- Path::new("target").join(host_triple).join(channel)
+ source_dir
+ .join("target")
+ .join(host_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 7e205b0fd..856aecc49 100644
--- a/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/build_sysroot.rs
@@ -3,14 +3,14 @@ use std::path::{Path, PathBuf};
use std::process::{self, Command};
use super::rustc_info::{get_file_name, get_rustc_version, get_wrapper_file_name};
-use super::utils::{spawn_and_wait, try_hard_link};
+use super::utils::{cargo_command, spawn_and_wait, try_hard_link};
use super::SysrootKind;
pub(crate) fn build_sysroot(
channel: &str,
sysroot_kind: SysrootKind,
target_dir: &Path,
- cg_clif_build_dir: &Path,
+ cg_clif_dylib_src: &Path,
host_triple: &str,
target_triple: &str,
) {
@@ -23,7 +23,6 @@ pub(crate) fn build_sysroot(
fs::create_dir_all(target_dir.join("lib")).unwrap();
// Copy the backend
- let cg_clif_dylib = get_file_name("rustc_codegen_cranelift", "dylib");
let cg_clif_dylib_path = target_dir
.join(if cfg!(windows) {
// Windows doesn't have rpath support, so the cg_clif dylib needs to be next to the
@@ -32,8 +31,8 @@ pub(crate) fn build_sysroot(
} else {
"lib"
})
- .join(&cg_clif_dylib);
- try_hard_link(cg_clif_build_dir.join(cg_clif_dylib), &cg_clif_dylib_path);
+ .join(get_file_name("rustc_codegen_cranelift", "dylib"));
+ try_hard_link(cg_clif_dylib_src, &cg_clif_dylib_path);
// Build and copy rustc and cargo wrappers
for wrapper in ["rustc-clif", "cargo-clif"] {
@@ -186,10 +185,10 @@ fn build_clif_sysroot_for_triple(
}
// Build sysroot
- let mut build_cmd = Command::new("cargo");
- build_cmd.arg("build").arg("--target").arg(triple).current_dir("build_sysroot");
+ let mut build_cmd = cargo_command("cargo", "build", Some(triple), Path::new("build_sysroot"));
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={}", target_dir.to_str().unwrap()));
if channel == "release" {
build_cmd.arg("--release");
rustflags.push_str(" -Zmir-opt-level=3");
diff --git a/compiler/rustc_codegen_cranelift/build_system/config.rs b/compiler/rustc_codegen_cranelift/build_system/config.rs
index ef540cf1f..c31784e10 100644
--- a/compiler/rustc_codegen_cranelift/build_system/config.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/config.rs
@@ -1,4 +1,5 @@
-use std::{fs, process};
+use std::fs;
+use std::process;
fn load_config_file() -> Vec<(String, Option<String>)> {
fs::read_to_string("config.txt")
diff --git a/compiler/rustc_codegen_cranelift/build_system/mod.rs b/compiler/rustc_codegen_cranelift/build_system/mod.rs
index c3706dc6f..b25270d83 100644
--- a/compiler/rustc_codegen_cranelift/build_system/mod.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/mod.rs
@@ -4,7 +4,7 @@ use std::process;
use self::utils::is_ci;
-mod abi_checker;
+mod abi_cafe;
mod build_backend;
mod build_sysroot;
mod config;
@@ -122,32 +122,23 @@ pub fn main() {
host_triple.clone()
};
- if target_triple.ends_with("-msvc") {
- eprintln!("The MSVC toolchain is not yet supported by rustc_codegen_cranelift.");
- eprintln!("Switch to the MinGW toolchain for Windows support.");
- eprintln!("Hint: You can use `rustup set default-host x86_64-pc-windows-gnu` to");
- eprintln!("set the global default target to MinGW");
- process::exit(1);
- }
-
- let cg_clif_build_dir =
- build_backend::build_backend(channel, &host_triple, use_unstable_features);
+ let cg_clif_dylib = build_backend::build_backend(channel, &host_triple, use_unstable_features);
match command {
Command::Test => {
tests::run_tests(
channel,
sysroot_kind,
&target_dir,
- &cg_clif_build_dir,
+ &cg_clif_dylib,
&host_triple,
&target_triple,
);
- abi_checker::run(
+ abi_cafe::run(
channel,
sysroot_kind,
&target_dir,
- &cg_clif_build_dir,
+ &cg_clif_dylib,
&host_triple,
&target_triple,
);
@@ -157,7 +148,7 @@ pub fn main() {
channel,
sysroot_kind,
&target_dir,
- &cg_clif_build_dir,
+ &cg_clif_dylib,
&host_triple,
&target_triple,
);
diff --git a/compiler/rustc_codegen_cranelift/build_system/prepare.rs b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
index d23b7f00d..3111f62f6 100644
--- a/compiler/rustc_codegen_cranelift/build_system/prepare.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/prepare.rs
@@ -1,64 +1,63 @@
use std::env;
use std::ffi::OsStr;
-use std::ffi::OsString;
use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::process::Command;
use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
-use super::utils::{copy_dir_recursively, spawn_and_wait};
+use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
+
+pub(crate) const ABI_CAFE: GitRepo =
+ GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
+
+pub(crate) const RAND: GitRepo =
+ GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
+
+pub(crate) const REGEX: GitRepo =
+ GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
+
+pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
+ "rust-lang",
+ "portable-simd",
+ "d5cd4a8112d958bd3a252327e0d069a6363249bd",
+ "portable-simd",
+);
+
+pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
+ "ebobby",
+ "simple-raytracer",
+ "804a7a21b9e673a482797aa289a18ed480e4d813",
+ "<none>",
+);
pub(crate) fn prepare() {
+ if Path::new("download").exists() {
+ std::fs::remove_dir_all(Path::new("download")).unwrap();
+ }
+ std::fs::create_dir_all(Path::new("download")).unwrap();
+
prepare_sysroot();
+ // FIXME maybe install this only locally?
eprintln!("[INSTALL] hyperfine");
Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
- clone_repo_shallow_github(
- "abi-checker",
- "Gankra",
- "abi-checker",
- "a2232d45f202846f5c02203c9f27355360f9a2ff",
- );
- apply_patches("abi-checker", Path::new("abi-checker"));
-
- clone_repo_shallow_github(
- "rand",
- "rust-random",
- "rand",
- "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
- );
- apply_patches("rand", Path::new("rand"));
-
- clone_repo_shallow_github(
- "regex",
- "rust-lang",
- "regex",
- "341f207c1071f7290e3f228c710817c280c8dca1",
- );
-
- clone_repo_shallow_github(
- "portable-simd",
- "rust-lang",
- "portable-simd",
- "b8d6b6844602f80af79cd96401339ec594d472d8",
- );
- apply_patches("portable-simd", Path::new("portable-simd"));
-
- clone_repo_shallow_github(
- "simple-raytracer",
- "ebobby",
- "simple-raytracer",
- "804a7a21b9e673a482797aa289a18ed480e4d813",
- );
+ ABI_CAFE.fetch();
+ RAND.fetch();
+ REGEX.fetch();
+ PORTABLE_SIMD.fetch();
+ SIMPLE_RAYTRACER.fetch();
eprintln!("[LLVM BUILD] simple-raytracer");
- let mut build_cmd = Command::new("cargo");
- build_cmd.arg("build").env_remove("CARGO_TARGET_DIR").current_dir("simple-raytracer");
+ let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
spawn_and_wait(build_cmd);
fs::copy(
- Path::new("simple-raytracer/target/debug").join(get_file_name("main", "bin")),
- Path::new("simple-raytracer").join(get_file_name("raytracer_cg_llvm", "bin")),
+ SIMPLE_RAYTRACER
+ .source_dir()
+ .join("target")
+ .join("debug")
+ .join(get_file_name("main", "bin")),
+ SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
)
.unwrap();
}
@@ -90,38 +89,78 @@ fn prepare_sysroot() {
apply_patches("sysroot", &sysroot_src);
}
+pub(crate) struct GitRepo {
+ url: GitRepoUrl,
+ rev: &'static str,
+ patch_name: &'static str,
+}
+
+enum GitRepoUrl {
+ Github { user: &'static str, repo: &'static str },
+}
+
+impl GitRepo {
+ const fn github(
+ user: &'static str,
+ repo: &'static str,
+ rev: &'static str,
+ patch_name: &'static str,
+ ) -> GitRepo {
+ GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
+ }
+
+ pub(crate) fn source_dir(&self) -> PathBuf {
+ match self.url {
+ GitRepoUrl::Github { user: _, repo } => {
+ std::env::current_dir().unwrap().join("download").join(repo)
+ }
+ }
+ }
+
+ fn fetch(&self) {
+ match self.url {
+ GitRepoUrl::Github { user, repo } => {
+ clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
+ }
+ }
+ apply_patches(self.patch_name, &self.source_dir());
+ }
+}
+
#[allow(dead_code)]
-fn clone_repo(target_dir: &str, repo: &str, rev: &str) {
+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(target_dir).spawn().unwrap().wait().unwrap();
+ Command::new("git").arg("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(target_dir);
+ clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
spawn_and_wait(clean_cmd);
let mut checkout_cmd = Command::new("git");
- checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(target_dir);
+ checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
spawn_and_wait(checkout_cmd);
}
-fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev: &str) {
+fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
if cfg!(windows) {
// Older windows doesn't have tar or curl by default. Fall back to using git.
- clone_repo(target_dir, &format!("https://github.com/{}/{}.git", username, repo), rev);
+ clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
return;
}
- let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", username, repo, rev);
- let archive_file = format!("{}.tar.gz", rev);
- let archive_dir = format!("{}-{}", repo, rev);
+ let downloads_dir = std::env::current_dir().unwrap().join("download");
+
+ let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
+ let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
+ let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
- eprintln!("[DOWNLOAD] {}/{} from {}", username, repo, archive_url);
+ eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
// Remove previous results if they exists
let _ = std::fs::remove_file(&archive_file);
let _ = std::fs::remove_dir_all(&archive_dir);
- let _ = std::fs::remove_dir_all(target_dir);
+ let _ = std::fs::remove_dir_all(&download_dir);
// Download zip archive
let mut download_cmd = Command::new("curl");
@@ -130,13 +169,13 @@ fn clone_repo_shallow_github(target_dir: &str, username: &str, repo: &str, rev:
// Unpack tar archive
let mut unpack_cmd = Command::new("tar");
- unpack_cmd.arg("xf").arg(&archive_file);
+ unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
spawn_and_wait(unpack_cmd);
// Rename unpacked dir to the expected name
- std::fs::rename(archive_dir, target_dir).unwrap();
+ std::fs::rename(archive_dir, &download_dir).unwrap();
- init_git_repo(Path::new(target_dir));
+ init_git_repo(&download_dir);
// Cleanup
std::fs::remove_file(archive_file).unwrap();
@@ -156,14 +195,20 @@ fn init_git_repo(repo_dir: &Path) {
spawn_and_wait(git_commit_cmd);
}
-fn get_patches(crate_name: &str) -> Vec<OsString> {
- let mut patches: Vec<_> = fs::read_dir("patches")
+fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
+ let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
.unwrap()
.map(|entry| entry.unwrap().path())
.filter(|path| path.extension() == Some(OsStr::new("patch")))
- .map(|path| path.file_name().unwrap().to_owned())
- .filter(|file_name| {
- file_name.to_str().unwrap().split_once("-").unwrap().1.starts_with(crate_name)
+ .filter(|path| {
+ path.file_name()
+ .unwrap()
+ .to_str()
+ .unwrap()
+ .split_once("-")
+ .unwrap()
+ .1
+ .starts_with(crate_name)
})
.collect();
patches.sort();
@@ -171,11 +216,18 @@ fn get_patches(crate_name: &str) -> Vec<OsString> {
}
fn apply_patches(crate_name: &str, target_dir: &Path) {
- for patch in get_patches(crate_name) {
- eprintln!("[PATCH] {:?} <- {:?}", target_dir.file_name().unwrap(), patch);
- let patch_arg = env::current_dir().unwrap().join("patches").join(patch);
+ if crate_name == "<none>" {
+ return;
+ }
+
+ for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
+ eprintln!(
+ "[PATCH] {:?} <- {:?}",
+ target_dir.file_name().unwrap(),
+ patch.file_name().unwrap()
+ );
let mut apply_patch_cmd = Command::new("git");
- apply_patch_cmd.arg("am").arg(patch_arg).arg("-q").current_dir(target_dir);
+ apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
spawn_and_wait(apply_patch_cmd);
}
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
index 913b589af..3c08b6fa3 100644
--- a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs
@@ -65,7 +65,7 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String {
}
/// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to
-/// underscores (`_`). This is specially made for the the rustc and cargo wrappers
+/// 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('-', "_");
diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs
index e21397cec..a414b60f4 100644
--- a/compiler/rustc_codegen_cranelift/build_system/tests.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs
@@ -1,7 +1,8 @@
use super::build_sysroot;
use super::config;
+use super::prepare;
use super::rustc_info::get_wrapper_file_name;
-use super::utils::{spawn_and_wait, spawn_and_wait_with_input};
+use super::utils::{cargo_command, hyperfine_command, spawn_and_wait, spawn_and_wait_with_input};
use build_system::SysrootKind;
use std::env;
use std::ffi::OsStr;
@@ -217,103 +218,95 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
TestCase::new("test.rust-random/rand", &|runner| {
- runner.in_dir(["rand"], |runner| {
- runner.run_cargo(["clean"]);
+ runner.in_dir(prepare::RAND.source_dir(), |runner| {
+ runner.run_cargo("clean", []);
if runner.host_triple == runner.target_triple {
eprintln!("[TEST] rust-random/rand");
- runner.run_cargo(["test", "--workspace"]);
+ runner.run_cargo("test", ["--workspace"]);
} else {
eprintln!("[AOT] rust-random/rand");
- runner.run_cargo([
- "build",
- "--workspace",
- "--target",
- &runner.target_triple,
- "--tests",
- ]);
+ runner.run_cargo("build", ["--workspace", "--tests"]);
}
});
}),
TestCase::new("bench.simple-raytracer", &|runner| {
- runner.in_dir(["simple-raytracer"], |runner| {
- let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string());
+ runner.in_dir(prepare::SIMPLE_RAYTRACER.source_dir(), |runner| {
+ let run_runs = env::var("RUN_RUNS").unwrap_or("10".to_string()).parse().unwrap();
if runner.host_triple == runner.target_triple {
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer");
- let mut bench_compile = Command::new("hyperfine");
- bench_compile.arg("--runs");
- bench_compile.arg(&run_runs);
- bench_compile.arg("--warmup");
- bench_compile.arg("1");
- bench_compile.arg("--prepare");
- bench_compile.arg(format!("{:?}", runner.cargo_command(["clean"])));
-
- if cfg!(windows) {
- bench_compile.arg("cmd /C \"set RUSTFLAGS= && cargo build\"");
- } else {
- bench_compile.arg("RUSTFLAGS='' cargo build");
- }
+ let prepare = runner.cargo_command("clean", []);
+
+ let llvm_build_cmd = cargo_command("cargo", "build", None, Path::new("."));
+
+ let cargo_clif = runner
+ .root_dir
+ .clone()
+ .join("build")
+ .join(get_wrapper_file_name("cargo-clif", "bin"));
+ let clif_build_cmd = cargo_command(cargo_clif, "build", None, Path::new("."));
+
+ let bench_compile =
+ hyperfine_command(1, run_runs, Some(prepare), llvm_build_cmd, clif_build_cmd);
- bench_compile.arg(format!("{:?}", runner.cargo_command(["build"])));
spawn_and_wait(bench_compile);
eprintln!("[BENCH RUN] ebobby/simple-raytracer");
fs::copy(PathBuf::from("./target/debug/main"), PathBuf::from("raytracer_cg_clif"))
.unwrap();
- let mut bench_run = Command::new("hyperfine");
- bench_run.arg("--runs");
- bench_run.arg(&run_runs);
- bench_run.arg(PathBuf::from("./raytracer_cg_llvm"));
- bench_run.arg(PathBuf::from("./raytracer_cg_clif"));
+ let bench_run = hyperfine_command(
+ 0,
+ run_runs,
+ None,
+ Command::new("./raytracer_cg_llvm"),
+ Command::new("./raytracer_cg_clif"),
+ );
spawn_and_wait(bench_run);
} else {
- runner.run_cargo(["clean"]);
+ runner.run_cargo("clean", []);
eprintln!("[BENCH COMPILE] ebobby/simple-raytracer (skipped)");
eprintln!("[COMPILE] ebobby/simple-raytracer");
- runner.run_cargo(["build", "--target", &runner.target_triple]);
+ runner.run_cargo("build", []);
eprintln!("[BENCH RUN] ebobby/simple-raytracer (skipped)");
}
});
}),
TestCase::new("test.libcore", &|runner| {
- runner.in_dir(["build_sysroot", "sysroot_src", "library", "core", "tests"], |runner| {
- runner.run_cargo(["clean"]);
-
- if runner.host_triple == runner.target_triple {
- runner.run_cargo(["test"]);
- } else {
- eprintln!("Cross-Compiling: Not running tests");
- runner.run_cargo(["build", "--target", &runner.target_triple, "--tests"]);
- }
- });
+ runner.in_dir(
+ std::env::current_dir()
+ .unwrap()
+ .join("build_sysroot")
+ .join("sysroot_src")
+ .join("library")
+ .join("core")
+ .join("tests"),
+ |runner| {
+ runner.run_cargo("clean", []);
+
+ if runner.host_triple == runner.target_triple {
+ runner.run_cargo("test", []);
+ } else {
+ eprintln!("Cross-Compiling: Not running tests");
+ runner.run_cargo("build", ["--tests"]);
+ }
+ },
+ );
}),
TestCase::new("test.regex-shootout-regex-dna", &|runner| {
- runner.in_dir(["regex"], |runner| {
- runner.run_cargo(["clean"]);
+ runner.in_dir(prepare::REGEX.source_dir(), |runner| {
+ runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
- let mut build_cmd = runner.cargo_command([
- "build",
- "--example",
- "shootout-regex-dna",
- "--target",
- &runner.target_triple,
- ]);
+ let mut build_cmd = runner.cargo_command("build", ["--example", "shootout-regex-dna"]);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
spawn_and_wait(build_cmd);
if runner.host_triple == runner.target_triple {
- let mut run_cmd = runner.cargo_command([
- "run",
- "--example",
- "shootout-regex-dna",
- "--target",
- &runner.target_triple,
- ]);
+ let mut run_cmd = runner.cargo_command("run", ["--example", "shootout-regex-dna"]);
run_cmd.env("RUSTFLAGS", lint_rust_flags);
let input =
@@ -353,41 +346,43 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[
});
}),
TestCase::new("test.regex", &|runner| {
- runner.in_dir(["regex"], |runner| {
- runner.run_cargo(["clean"]);
+ runner.in_dir(prepare::REGEX.source_dir(), |runner| {
+ runner.run_cargo("clean", []);
// newer aho_corasick versions throw a deprecation warning
let lint_rust_flags = format!("{} --cap-lints warn", runner.rust_flags);
if runner.host_triple == runner.target_triple {
- let mut run_cmd = runner.cargo_command([
+ let mut run_cmd = runner.cargo_command(
"test",
- "--tests",
- "--",
- "--exclude-should-panic",
- "--test-threads",
- "1",
- "-Zunstable-options",
- "-q",
- ]);
+ [
+ "--tests",
+ "--",
+ "--exclude-should-panic",
+ "--test-threads",
+ "1",
+ "-Zunstable-options",
+ "-q",
+ ],
+ );
run_cmd.env("RUSTFLAGS", lint_rust_flags);
spawn_and_wait(run_cmd);
} else {
eprintln!("Cross-Compiling: Not running tests");
let mut build_cmd =
- runner.cargo_command(["build", "--tests", "--target", &runner.target_triple]);
+ runner.cargo_command("build", ["--tests", "--target", &runner.target_triple]);
build_cmd.env("RUSTFLAGS", lint_rust_flags.clone());
spawn_and_wait(build_cmd);
}
});
}),
TestCase::new("test.portable-simd", &|runner| {
- runner.in_dir(["portable-simd"], |runner| {
- runner.run_cargo(["clean"]);
- runner.run_cargo(["build", "--all-targets", "--target", &runner.target_triple]);
+ runner.in_dir(prepare::PORTABLE_SIMD.source_dir(), |runner| {
+ runner.run_cargo("clean", []);
+ runner.run_cargo("build", ["--all-targets", "--target", &runner.target_triple]);
if runner.host_triple == runner.target_triple {
- runner.run_cargo(["test", "-q"]);
+ runner.run_cargo("test", ["-q"]);
}
});
}),
@@ -397,7 +392,7 @@ pub(crate) fn run_tests(
channel: &str,
sysroot_kind: SysrootKind,
target_dir: &Path,
- cg_clif_build_dir: &Path,
+ cg_clif_dylib: &Path,
host_triple: &str,
target_triple: &str,
) {
@@ -408,7 +403,7 @@ pub(crate) fn run_tests(
channel,
SysrootKind::None,
&target_dir,
- cg_clif_build_dir,
+ cg_clif_dylib,
&host_triple,
&target_triple,
);
@@ -427,7 +422,7 @@ pub(crate) fn run_tests(
channel,
sysroot_kind,
&target_dir,
- cg_clif_build_dir,
+ cg_clif_dylib,
&host_triple,
&target_triple,
);
@@ -521,16 +516,8 @@ impl TestRunner {
}
}
- fn in_dir<'a, I, F>(&self, dir: I, callback: F)
- where
- I: IntoIterator<Item = &'a str>,
- F: FnOnce(&TestRunner),
- {
+ fn in_dir(&self, new: impl AsRef<Path>, callback: impl FnOnce(&TestRunner)) {
let current = env::current_dir().unwrap();
- let mut new = current.clone();
- for d in dir {
- new.push(d);
- }
env::set_current_dir(new).unwrap();
callback(self);
@@ -595,25 +582,29 @@ impl TestRunner {
spawn_and_wait(cmd);
}
- fn cargo_command<I, S>(&self, args: I) -> Command
+ fn cargo_command<'a, I>(&self, subcommand: &str, args: I) -> Command
where
- I: IntoIterator<Item = S>,
- S: AsRef<OsStr>,
+ I: IntoIterator<Item = &'a str>,
{
let mut cargo_clif = self.root_dir.clone();
cargo_clif.push("build");
cargo_clif.push(get_wrapper_file_name("cargo-clif", "bin"));
- let mut cmd = Command::new(cargo_clif);
+ let mut cmd = cargo_command(
+ cargo_clif,
+ subcommand,
+ if subcommand == "clean" { None } else { Some(&self.target_triple) },
+ Path::new("."),
+ );
cmd.args(args);
cmd.env("RUSTFLAGS", &self.rust_flags);
cmd
}
- fn run_cargo<'a, I>(&self, args: I)
+ fn run_cargo<'a, I>(&self, subcommand: &str, args: I)
where
I: IntoIterator<Item = &'a str>,
{
- spawn_and_wait(self.cargo_command(args));
+ spawn_and_wait(self.cargo_command(subcommand, args));
}
}
diff --git a/compiler/rustc_codegen_cranelift/build_system/utils.rs b/compiler/rustc_codegen_cranelift/build_system/utils.rs
index bdf8f8ecd..48da64906 100644
--- a/compiler/rustc_codegen_cranelift/build_system/utils.rs
+++ b/compiler/rustc_codegen_cranelift/build_system/utils.rs
@@ -4,6 +4,52 @@ use std::io::Write;
use std::path::Path;
use std::process::{self, Command, Stdio};
+pub(crate) fn cargo_command(
+ cargo: impl AsRef<Path>,
+ subcommand: &str,
+ triple: Option<&str>,
+ source_dir: &Path,
+) -> Command {
+ let mut cmd = Command::new(cargo.as_ref());
+ cmd.arg(subcommand)
+ .arg("--manifest-path")
+ .arg(source_dir.join("Cargo.toml"))
+ .arg("--target-dir")
+ .arg(source_dir.join("target"));
+
+ if let Some(triple) = triple {
+ cmd.arg("--target").arg(triple);
+ }
+
+ cmd
+}
+
+pub(crate) fn hyperfine_command(
+ warmup: u64,
+ runs: u64,
+ prepare: Option<Command>,
+ a: Command,
+ b: Command,
+) -> Command {
+ let mut bench = Command::new("hyperfine");
+
+ if warmup != 0 {
+ bench.arg("--warmup").arg(warmup.to_string());
+ }
+
+ if runs != 0 {
+ bench.arg("--runs").arg(runs.to_string());
+ }
+
+ if let Some(prepare) = prepare {
+ bench.arg("--prepare").arg(format!("{:?}", prepare));
+ }
+
+ bench.arg(format!("{:?}", a)).arg(format!("{:?}", b));
+
+ bench
+}
+
#[track_caller]
pub(crate) fn try_hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) {
let src = src.as_ref();
diff --git a/compiler/rustc_codegen_cranelift/clean_all.sh b/compiler/rustc_codegen_cranelift/clean_all.sh
index 62e52bd19..fedab2433 100755
--- a/compiler/rustc_codegen_cranelift/clean_all.sh
+++ b/compiler/rustc_codegen_cranelift/clean_all.sh
@@ -3,4 +3,8 @@ set -e
rm -rf build_sysroot/{sysroot_src/,target/,compiler-builtins/,rustc_version}
rm -rf target/ build/ perf.data{,.old} y.bin
-rm -rf rand/ regex/ simple-raytracer/ portable-simd/ abi-checker/
+rm -rf download/
+
+# 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/
diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt
index 2264d301d..0d539191b 100644
--- a/compiler/rustc_codegen_cranelift/config.txt
+++ b/compiler/rustc_codegen_cranelift/config.txt
@@ -49,4 +49,4 @@ test.regex-shootout-regex-dna
test.regex
test.portable-simd
-testsuite.abi-checker
+testsuite.abi-cafe
diff --git a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
index 2ecc8b823..039100696 100644
--- a/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
+++ b/compiler/rustc_codegen_cranelift/example/issue-91827-extern-types.rs
@@ -5,7 +5,6 @@
// Test that we can handle unsized types with an extern type tail part.
// Regression test for issue #91827.
-#![feature(const_ptr_offset_from)]
#![feature(extern_types)]
use std::ptr::addr_of;
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 42f8aa50b..7f85b52f0 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -559,16 +559,22 @@ pub union MaybeUninit<T> {
pub mod intrinsics {
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
pub fn abort() -> !;
+ #[rustc_safe_intrinsic]
pub fn size_of<T>() -> usize;
pub fn size_of_val<T: ?::Sized>(val: *const T) -> usize;
+ #[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
pub fn min_align_of_val<T: ?::Sized>(val: *const T) -> usize;
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
pub fn transmute<T, U>(e: T) -> U;
pub fn ctlz_nonzero<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn needs_drop<T: ?::Sized>() -> bool;
+ #[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
}
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index e83be3a3d..215d3556a 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -93,6 +93,7 @@ fn start<T: Termination + 'static>(
main: fn() -> T,
argc: isize,
argv: *const *const u8,
+ _sigpipe: u8,
) -> isize {
if argc == 3 {
unsafe { puts(*argv as *const i8); }
diff --git a/compiler/rustc_codegen_cranelift/example/std_example.rs b/compiler/rustc_codegen_cranelift/example/std_example.rs
index 0b5b6cd55..ad108c349 100644
--- a/compiler/rustc_codegen_cranelift/example/std_example.rs
+++ b/compiler/rustc_codegen_cranelift/example/std_example.rs
@@ -1,4 +1,4 @@
-#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
+#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
new file mode 100644
index 000000000..0e5e7cdfc
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0001-abi-cafe-Disable-some-test-on-x86_64-pc-windows-gnu.patch
@@ -0,0 +1,29 @@
+From 2b15fee2bb5fd14e34c7e17e44d99cb34f4c555d Mon Sep 17 00:00:00 2001
+From: Afonso Bordado <afonsobordado@az8.co>
+Date: Tue, 27 Sep 2022 07:55:17 +0100
+Subject: [PATCH] Disable some test on x86_64-pc-windows-gnu
+
+---
+ src/report.rs | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/report.rs b/src/report.rs
+index eeec614..f582867 100644
+--- a/src/report.rs
++++ b/src/report.rs
+@@ -48,6 +48,12 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
+ //
+ // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
+
++ // x86_64-pc-windows-gnu has some broken i128 tests that aren't disabled by default
++ if cfg!(all(target_os = "windows", target_env = "gnu")) && test.test_name == "ui128" {
++ result.run = Link;
++ result.check = Pass(Link);
++ }
++
+ // END OF VENDOR RESERVED AREA
+ //
+ //
+--
+2.30.1.windows.1
+
diff --git a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch b/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch
deleted file mode 100644
index 526366a75..000000000
--- a/compiler/rustc_codegen_cranelift/patches/0001-abi-checker-Disable-failing-tests.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From 1a315ba225577dbbd1f449d9609f16f984f68708 Mon Sep 17 00:00:00 2001
-From: Afonso Bordado <afonso360@users.noreply.github.com>
-Date: Fri, 12 Aug 2022 22:51:58 +0000
-Subject: [PATCH] Disable abi-checker tests
-
----
- src/report.rs | 14 ++++++++++++++
- 1 file changed, 14 insertions(+)
-
-diff --git a/src/report.rs b/src/report.rs
-index 7346f5e..8347762 100644
---- a/src/report.rs
-+++ b/src/report.rs
-@@ -45,6 +45,20 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn AbiImpl, callee: &dyn AbiImpl
- //
- // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES
-
-+ // Currently MSVC has some broken ABI issues. Furthermore, they cause
-+ // a STATUS_ACCESS_VIOLATION, so we can't even run them. Ensure that they compile and link.
-+ if cfg!(windows) && (test.test_name == "bool" || test.test_name == "ui128") {
-+ result.run = Link;
-+ result.check = Pass(Link);
-+ }
-+
-+ // structs is broken in the current release of cranelift for aarch64.
-+ // It has been fixed for cranelift 0.88: https://github.com/bytecodealliance/wasmtime/pull/4634
-+ if cfg!(target_arch = "aarch64") && test.test_name == "structs" {
-+ result.run = Link;
-+ result.check = Pass(Link);
-+ }
-+
- // END OF VENDOR RESERVED AREA
- //
- //
---
-2.34.1
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
index 54e13b090..89e2b61c1 100644
--- 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
@@ -1,80 +1,29 @@
-From 97c473937382a5b5858d9cce3c947855d23b2dc5 Mon Sep 17 00:00:00 2001
+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/math.rs | 6 ++++++
- crates/core_simd/src/vector.rs | 2 ++
- crates/core_simd/tests/masks.rs | 2 ++
- crates/core_simd/tests/ops_macros.rs | 4 ++++
- 4 files changed, 14 insertions(+)
+ 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/math.rs b/crates/core_simd/src/math.rs
-index 2bae414..2f87499 100644
---- a/crates/core_simd/src/math.rs
-+++ b/crates/core_simd/src/math.rs
-@@ -5,6 +5,7 @@ macro_rules! impl_uint_arith {
- ($($ty:ty),+) => {
- $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
-
-+ /*
- /// Lanewise saturating add.
- ///
- /// # Examples
-@@ -43,6 +44,7 @@ macro_rules! impl_uint_arith {
- pub fn saturating_sub(self, second: Self) -> Self {
- unsafe { simd_saturating_sub(self, second) }
- }
-+ */
- })+
- }
- }
-@@ -51,6 +53,7 @@ macro_rules! impl_int_arith {
- ($($ty:ty),+) => {
- $( impl<const LANES: usize> Simd<$ty, LANES> where LaneCount<LANES>: SupportedLaneCount {
-
-+ /*
- /// Lanewise saturating add.
- ///
- /// # Examples
-@@ -89,6 +92,7 @@ macro_rules! impl_int_arith {
- pub fn saturating_sub(self, second: Self) -> Self {
- unsafe { simd_saturating_sub(self, second) }
- }
-+ */
-
- /// Lanewise absolute value, implemented in Rust.
- /// Every lane becomes its absolute value.
-@@ -109,6 +113,7 @@ macro_rules! impl_int_arith {
- (self^m) - m
- }
-
-+ /*
- /// Lanewise saturating absolute value, implemented in Rust.
- /// As abs(), except the MIN value becomes MAX instead of itself.
- ///
-@@ -151,6 +156,7 @@ macro_rules! impl_int_arith {
- pub fn saturating_neg(self) -> Self {
- Self::splat(0).saturating_sub(self)
- }
-+ */
- })+
- }
- }
diff --git a/crates/core_simd/src/vector.rs b/crates/core_simd/src/vector.rs
-index 7c5ec2b..c8631e8 100644
+index e8e8f68..7173c24 100644
--- a/crates/core_simd/src/vector.rs
+++ b/crates/core_simd/src/vector.rs
-@@ -75,6 +75,7 @@ where
- Self(array)
+@@ -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.
///
-@@ -297,6 +298,7 @@ where
+@@ -473,6 +474,7 @@ where
// Cleared ☢️ *mut T Zone
}
}
@@ -82,26 +31,5 @@ index 7c5ec2b..c8631e8 100644
}
impl<T, const LANES: usize> Copy for Simd<T, LANES>
-diff --git a/crates/core_simd/tests/masks.rs b/crates/core_simd/tests/masks.rs
-index 6a8ecd3..68fcb49 100644
---- a/crates/core_simd/tests/masks.rs
-+++ b/crates/core_simd/tests/masks.rs
-@@ -68,6 +68,7 @@ macro_rules! test_mask_api {
- assert_eq!(core_simd::Mask::<$type, 8>::from_int(int), mask);
- }
-
-+ /*
- #[cfg(feature = "generic_const_exprs")]
- #[test]
- fn roundtrip_bitmask_conversion() {
-@@ -80,6 +81,7 @@ macro_rules! test_mask_api {
- assert_eq!(bitmask, [0b01001001, 0b10000011]);
- assert_eq!(core_simd::Mask::<$type, 16>::from_bitmask(bitmask), mask);
- }
-+ */
- }
- }
- }
--
-2.26.2.7.g19db9cfb68
-
+2.25.1
diff --git a/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch
new file mode 100644
index 000000000..d8775e2d0
--- /dev/null
+++ b/compiler/rustc_codegen_cranelift/patches/0003-rand-Disable-rand-tests-on-mingw.patch
@@ -0,0 +1,47 @@
+From eec874c889b8d24e5ad50faded24288150f057b1 Mon Sep 17 00:00:00 2001
+From: Afonso Bordado <afonsobordado@az8.co>
+Date: Tue, 27 Sep 2022 08:13:58 +0100
+Subject: [PATCH] Disable rand tests on mingw
+
+---
+ rand_distr/src/pareto.rs | 2 ++
+ rand_distr/tests/value_stability.rs | 4 ++++
+ 2 files changed, 6 insertions(+)
+
+diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs
+index 217899e..9cedeb7 100644
+--- a/rand_distr/src/pareto.rs
++++ b/rand_distr/src/pareto.rs
+@@ -107,6 +107,8 @@ mod tests {
+ }
+
+ #[test]
++ // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation
++ #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+ fn value_stability() {
+ fn test_samples<F: Float + core::fmt::Debug, D: Distribution<F>>(
+ distr: D, zero: F, expected: &[F],
+diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs
+index 192ba74..0101ace 100644
+--- a/rand_distr/tests/value_stability.rs
++++ b/rand_distr/tests/value_stability.rs
+@@ -72,6 +72,8 @@ fn unit_disc_stability() {
+ }
+
+ #[test]
++// This is broken on x86_64-pc-windows-gnu
++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+ fn pareto_stability() {
+ test_samples(213, Pareto::new(1.0, 1.0).unwrap(), &[
+ 1.0423688f32, 2.1235929, 4.132709, 1.4679428,
+@@ -143,6 +145,8 @@ fn inverse_gaussian_stability() {
+ }
+
+ #[test]
++// This is broken on x86_64-pc-windows-gnu
++#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)]
+ fn gamma_stability() {
+ // Gamma has 3 cases: shape == 1, shape < 1, shape > 1
+ test_samples(223, Gamma::new(1.0, 5.0).unwrap(), &[
+--
+2.25.1
diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain b/compiler/rustc_codegen_cranelift/rust-toolchain
index 14f2746ec..c0a2e7a78 100644
--- a/compiler/rustc_codegen_cranelift/rust-toolchain
+++ b/compiler/rustc_codegen_cranelift/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-08-24"
+channel = "nightly-2022-10-23"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
index 091bfa1e9..d6a377895 100644
--- a/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
@@ -10,6 +10,8 @@ git fetch
git checkout -- .
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
+git am ../patches/*-sysroot-*.patch
+
git apply - <<EOF
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index d95b5b7f17f..00b6f0e3635 100644
@@ -66,3 +68,7 @@ popd
# FIXME remove once inline asm is fully supported
export RUSTFLAGS="$RUSTFLAGS --cfg=rustix_use_libc"
+
+# Allow the testsuite to use llvm tools
+host_triple=$(rustc -vV | grep host | cut -d: -f2 | tr -d " ")
+export LLVM_BIN_DIR="$(rustc --print sysroot)/lib/rustlib/$host_triple/bin"
diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
index 944787612..9b5db3cf8 100755
--- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
+++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
@@ -29,10 +29,6 @@ rm src/test/incremental/change_crate_dep_kind.rs
rm src/test/incremental/issue-80691-bad-eval-cache.rs # -Cpanic=abort causes abort instead of exit(101)
# requires compiling with -Cpanic=unwind
-rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
-rm src/test/ui/async-await/async-fn-size-moved-locals.rs # -Cpanic=abort shrinks some generator by one byte
-rm src/test/ui/async-await/async-fn-size-uninit-locals.rs # same
-rm src/test/ui/generator/size-moved-locals.rs # same
rm -r src/test/ui/macros/rfc-2011-nicer-assert-messages/
# vendor intrinsics
@@ -67,6 +63,7 @@ rm src/test/ui/target-feature/missing-plusminus.rs # error not implemented
rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
rm -r src/test/run-make/emit-named-files # requires full --emit support
rm src/test/ui/abi/stack-probes.rs # stack probes not yet implemented
+rm src/test/ui/simd/intrinsic/ptr-cast.rs # simd_expose_addr intrinsic unimplemented
# optimization tests
# ==================
@@ -110,12 +107,13 @@ rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unorde
# bugs in the test suite
# ======================
rm src/test/ui/backtrace.rs # TODO warning
-rm src/test/ui/empty_global_asm.rs # TODO add needs-asm-support
rm src/test/ui/simple_global_asm.rs # TODO add needs-asm-support
rm src/test/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 src/test/run-make/native-link-modifier-bundle
+rm src/test/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
+
echo "[TEST] rustc test suite"
RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui,incremental}
popd
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 0497c2570..99059e788 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -465,7 +465,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = fx.bcx.import_signature(sig);
- (CallTarget::Indirect(sig, method), Some(ptr))
+ (CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
}
// Normal call
@@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>(
// we don't actually need to drop anything
} else {
match ty.kind() {
- ty::Dynamic(..) => {
+ 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 (ptr, vtable) = drop_place.to_ptr_maybe_unsized();
let ptr = ptr.get_addr(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
@@ -578,6 +590,43 @@ pub(crate) fn codegen_drop<'tcx>(
let sig = fx.bcx.import_signature(sig);
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
}
+ 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 (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
+ let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
+
+ let virtual_drop = Instance {
+ def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
+ substs: drop_instance.substs,
+ };
+ let fn_abi =
+ RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
+
+ let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
+ let sig = fx.bcx.import_signature(sig);
+ fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
+ }
_ => {
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
index 96e25d3a8..e5ad31eb9 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs
@@ -193,7 +193,7 @@ pub(super) fn from_casted_value<'tcx>(
kind: StackSlotKind::ExplicitSlot,
// FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
// specify stack slot alignment.
- // Stack slot size may be bigger for for example `[u8; 3]` which is packed into an `i32`.
+ // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`.
// It may also be smaller for example when the type is a wrapper around an integer with a
// larger alignment than the integer.
size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16,
diff --git a/compiler/rustc_codegen_cranelift/src/allocator.rs b/compiler/rustc_codegen_cranelift/src/allocator.rs
index 6d321c7b2..bad8a87b9 100644
--- a/compiler/rustc_codegen_cranelift/src/allocator.rs
+++ b/compiler/rustc_codegen_cranelift/src/allocator.rs
@@ -78,7 +78,7 @@ fn codegen_inner(
let callee_func_id = module.declare_function(&callee_name, Linkage::Import, &sig).unwrap();
let mut ctx = Context::new();
- ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig.clone());
+ ctx.func.signature = sig.clone();
{
let mut func_ctx = FunctionBuilderContext::new();
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
@@ -116,7 +116,7 @@ fn codegen_inner(
let callee_func_id = module.declare_function(callee_name, Linkage::Import, &sig).unwrap();
let mut ctx = Context::new();
- ctx.func = Function::with_name_signature(ExternalName::user(0, 0), sig);
+ ctx.func.signature = sig;
{
let mut func_ctx = FunctionBuilderContext::new();
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
diff --git a/compiler/rustc_codegen_cranelift/src/archive.rs b/compiler/rustc_codegen_cranelift/src/archive.rs
index fb5313f17..f2e3bf16e 100644
--- a/compiler/rustc_codegen_cranelift/src/archive.rs
+++ b/compiler/rustc_codegen_cranelift/src/archive.rs
@@ -160,6 +160,8 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
let err = err.to_string();
if err == "Unknown file magic" {
// Not an object file; skip it.
+ } else if object::read::archive::ArchiveFile::parse(&*data).is_ok() {
+ // Nested archive file; skip it.
} else {
sess.fatal(&format!(
"error parsing `{}` during archive creation: {}",
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 399474d79..1db445027 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -6,6 +6,8 @@ use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
+use cranelift_codegen::ir::UserFuncName;
+
use crate::constant::ConstantCx;
use crate::debuginfo::FunctionDebugContext;
use crate::prelude::*;
@@ -64,7 +66,7 @@ pub(crate) fn codegen_fn<'tcx>(
let mut func_ctx = FunctionBuilderContext::new();
let mut func = cached_func;
func.clear();
- func.name = ExternalName::user(0, func_id.as_u32());
+ func.name = UserFuncName::user(0, func_id.as_u32());
func.signature = sig;
func.collect_debug_info();
@@ -633,7 +635,12 @@ fn codegen_stmt<'tcx>(
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
}
Rvalue::Cast(
- CastKind::Misc
+ CastKind::IntToInt
+ | CastKind::FloatToFloat
+ | CastKind::FloatToInt
+ | CastKind::IntToFloat
+ | CastKind::FnPtrToPtr
+ | CastKind::PtrToPtr
| CastKind::PointerExposeAddress
| CastKind::PointerFromExposedAddress,
ref operand,
@@ -701,9 +708,9 @@ fn codegen_stmt<'tcx>(
let operand = codegen_operand(fx, operand);
operand.unsize_value(fx, lval);
}
- Rvalue::Cast(CastKind::DynStar, _, _) => {
- // FIXME(dyn-star)
- unimplemented!()
+ Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
+ let operand = codegen_operand(fx, operand);
+ operand.coerce_dyn_star(fx, lval);
}
Rvalue::Discriminant(place) => {
let place = codegen_place(fx, place);
@@ -763,11 +770,7 @@ fn codegen_stmt<'tcx>(
lval.write_cvalue(fx, CValue::by_val(operand, box_layout));
}
Rvalue::NullaryOp(null_op, ty) => {
- assert!(
- lval.layout()
- .ty
- .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
- );
+ assert!(lval.layout().ty.is_sized(fx.tcx, ParamEnv::reveal_all()));
let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
@@ -850,6 +853,7 @@ pub(crate) fn codegen_place<'tcx>(
PlaceElem::Deref => {
cplace = cplace.place_deref(fx);
}
+ PlaceElem::OpaqueCast(ty) => cplace = cplace.place_opaque_cast(fx, ty),
PlaceElem::Field(field, _ty) => {
cplace = cplace.place_field(fx, field);
}
@@ -916,7 +920,7 @@ pub(crate) fn codegen_operand<'tcx>(
let cplace = codegen_place(fx, *place);
cplace.to_cvalue(fx)
}
- Operand::Constant(const_) => crate::constant::codegen_constant(fx, const_),
+ Operand::Constant(const_) => crate::constant::codegen_constant_operand(fx, const_),
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
index dfde97920..f855e20e0 100644
--- a/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
+++ b/compiler/rustc_codegen_cranelift/src/concurrency_limiter.rs
@@ -10,6 +10,7 @@ pub(super) struct ConcurrencyLimiter {
helper_thread: Option<HelperThread>,
state: Arc<Mutex<state::ConcurrencyLimiterState>>,
available_token_condvar: Arc<Condvar>,
+ finished: bool,
}
impl ConcurrencyLimiter {
@@ -32,6 +33,7 @@ impl ConcurrencyLimiter {
helper_thread: Some(helper_thread),
state,
available_token_condvar: Arc::new(Condvar::new()),
+ finished: false,
}
}
@@ -56,16 +58,23 @@ impl ConcurrencyLimiter {
let mut state = self.state.lock().unwrap();
state.job_already_done();
}
-}
-impl Drop for ConcurrencyLimiter {
- fn drop(&mut self) {
- //
+ pub(crate) fn finished(mut self) {
self.helper_thread.take();
// Assert that all jobs have finished
let state = Mutex::get_mut(Arc::get_mut(&mut self.state).unwrap()).unwrap();
state.assert_done();
+
+ self.finished = true;
+ }
+}
+
+impl Drop for ConcurrencyLimiter {
+ fn drop(&mut self) {
+ if !self.finished && !std::thread::panicking() {
+ panic!("Forgot to call finished() on ConcurrencyLimiter");
+ }
}
}
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 6b4ed9b9d..148b66d95 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -5,10 +5,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
};
-use rustc_middle::ty::ConstKind;
-use rustc_span::DUMMY_SP;
-use cranelift_codegen::ir::GlobalValueData;
use cranelift_module::*;
use crate::prelude::*;
@@ -42,15 +39,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
let mut all_constants_ok = true;
for constant in &fx.mir.required_consts {
let unevaluated = match fx.monomorphize(constant.literal) {
- ConstantKind::Ty(ct) => match ct.kind() {
- ConstKind::Unevaluated(uv) => uv.expand(),
- ConstKind::Value(_) => continue,
- ConstKind::Param(_)
- | ConstKind::Infer(_)
- | ConstKind::Bound(_, _)
- | ConstKind::Placeholder(_)
- | ConstKind::Error(_) => unreachable!("{:?}", ct),
- },
+ ConstantKind::Ty(_) => unreachable!(),
ConstantKind::Unevaluated(uv, _) => uv,
ConstantKind::Val(..) => continue,
};
@@ -90,53 +79,46 @@ pub(crate) fn codegen_tls_ref<'tcx>(
CValue::by_val(tls_ptr, layout)
}
-fn codegen_static_ref<'tcx>(
- fx: &mut FunctionCx<'_, '_, 'tcx>,
- def_id: DefId,
- layout: TyAndLayout<'tcx>,
-) -> CPlace<'tcx> {
- let data_id = data_id_for_static(fx.tcx, fx.module, def_id, false);
- let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
- if fx.clif_comments.enabled() {
- fx.add_comment(local_data_id, format!("{:?}", def_id));
- }
- let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
- assert!(!layout.is_unsized(), "unsized statics aren't supported");
- assert!(
- matches!(
- fx.bcx.func.global_values[local_data_id],
- GlobalValueData::Symbol { tls: false, .. }
- ),
- "tls static referenced without Rvalue::ThreadLocalRef"
- );
- CPlace::for_ptr(crate::pointer::Pointer::new(global_ptr), layout)
-}
-
-pub(crate) fn codegen_constant<'tcx>(
+pub(crate) fn eval_mir_constant<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
constant: &Constant<'tcx>,
-) -> CValue<'tcx> {
- let (const_val, ty) = match fx.monomorphize(constant.literal) {
- ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
- ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty)
+) -> (ConstValue<'tcx>, Ty<'tcx>) {
+ let constant_kind = fx.monomorphize(constant.literal);
+ let uv = match constant_kind {
+ ConstantKind::Ty(const_) => match const_.kind() {
+ ty::ConstKind::Unevaluated(uv) => uv.expand(),
+ ty::ConstKind::Value(val) => {
+ return (fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty());
+ }
+ err => span_bug!(
+ constant.span,
+ "encountered bad ConstKind after monomorphizing: {:?}",
+ err
+ ),
+ },
+ ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
if fx.tcx.is_static(def.did) =>
{
- assert!(substs.is_empty());
- assert!(promoted.is_none());
-
- return codegen_static_ref(fx, def.did, fx.layout_of(ty)).to_cvalue(fx);
- }
- ConstantKind::Unevaluated(unevaluated, ty) => {
- match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
- Ok(const_val) => (const_val, ty),
- Err(_) => {
- span_bug!(constant.span, "erroneous constant not captured by required_consts");
- }
- }
+ span_bug!(constant.span, "MIR constant refers to static");
}
- ConstantKind::Val(val, ty) => (val, ty),
+ ConstantKind::Unevaluated(uv, _) => uv,
+ ConstantKind::Val(val, _) => return (val, constant_kind.ty()),
};
+ (
+ fx.tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).unwrap_or_else(|_err| {
+ span_bug!(constant.span, "erroneous constant not captured by required_consts");
+ }),
+ constant_kind.ty(),
+ )
+}
+
+pub(crate) fn codegen_constant_operand<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ constant: &Constant<'tcx>,
+) -> CValue<'tcx> {
+ let (const_val, ty) = eval_mir_constant(fx, constant);
+
codegen_const_value(fx, const_val, ty)
}
@@ -253,7 +235,7 @@ pub(crate) fn codegen_const_value<'tcx>(
}
}
-pub(crate) fn pointer_for_allocation<'tcx>(
+fn pointer_for_allocation<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
alloc: ConstAllocation<'tcx>,
) -> crate::pointer::Pointer {
@@ -308,7 +290,7 @@ fn data_id_for_static(
let is_mutable = if tcx.is_mutable_static(def_id) {
true
} else {
- !ty.is_freeze(tcx.at(DUMMY_SP), ParamEnv::reveal_all())
+ !ty.is_freeze(tcx, ParamEnv::reveal_all())
};
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
@@ -476,14 +458,13 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
operand: &Operand<'tcx>,
) -> Option<ConstValue<'tcx>> {
match operand {
- Operand::Constant(const_) => match const_.literal {
- ConstantKind::Ty(const_) => fx
- .monomorphize(const_)
- .eval_for_mir(fx.tcx, ParamEnv::reveal_all())
- .try_to_value(fx.tcx),
+ Operand::Constant(const_) => match fx.monomorphize(const_.literal) {
+ ConstantKind::Ty(const_) => Some(
+ const_.eval_for_mir(fx.tcx, ParamEnv::reveal_all()).try_to_value(fx.tcx).unwrap(),
+ ),
ConstantKind::Val(val, _) => Some(val),
ConstantKind::Unevaluated(uv, _) => {
- fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).ok()
+ Some(fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), uv, None).unwrap())
}
},
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
@@ -499,7 +480,16 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
match &stmt.kind {
StatementKind::Assign(local_and_rvalue) if &local_and_rvalue.0 == place => {
match &local_and_rvalue.1 {
- Rvalue::Cast(CastKind::Misc, operand, ty) => {
+ Rvalue::Cast(
+ CastKind::IntToInt
+ | CastKind::FloatToFloat
+ | CastKind::FloatToInt
+ | CastKind::IntToFloat
+ | CastKind::FnPtrToPtr
+ | CastKind::PtrToPtr,
+ operand,
+ ty,
+ ) => {
if computed_const_val.is_some() {
return None; // local assigned twice
}
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 8eabe1cbc..f873561c1 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -106,7 +106,7 @@ impl OngoingCodegen {
}
}
- drop(self.concurrency_limiter);
+ self.concurrency_limiter.finished();
(
CodegenResults {
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 0e77e4004..6a430b521 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -67,13 +67,12 @@ fn create_jit_module(
hotswap: bool,
) -> (JITModule, CodegenCx) {
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
- let imported_symbols = load_imported_symbols_for_jit(tcx.sess, crate_info);
let isa = crate::build_isa(tcx.sess, backend_config);
let mut jit_builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
jit_builder.hotswap(hotswap);
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
- jit_builder.symbols(imported_symbols);
+ jit_builder.symbol_lookup_fn(dep_symbol_lookup_fn(tcx.sess, crate_info));
jit_builder.symbol("__clif_jit_fn", clif_jit_fn as *const u8);
let mut jit_module = JITModule::new(jit_builder);
@@ -286,10 +285,10 @@ fn jit_fn(instance_ptr: *const Instance<'static>, trampoline_ptr: *const u8) ->
})
}
-fn load_imported_symbols_for_jit(
+fn dep_symbol_lookup_fn(
sess: &Session,
crate_info: CrateInfo,
-) -> Vec<(String, *const u8)> {
+) -> Box<dyn Fn(&str) -> Option<*const u8>> {
use rustc_middle::middle::dependency_format::Linkage;
let mut dylib_paths = Vec::new();
@@ -316,39 +315,23 @@ fn load_imported_symbols_for_jit(
}
}
- let mut imported_symbols = Vec::new();
- for path in dylib_paths {
- use object::{Object, ObjectSymbol};
- let lib = libloading::Library::new(&path).unwrap();
- let obj = std::fs::read(path).unwrap();
- let obj = object::File::parse(&*obj).unwrap();
- imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
- let name = symbol.name().unwrap().to_string();
- if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
- return None;
- }
- if name.starts_with("rust_metadata_") {
- // The metadata is part of a section that is not loaded by the dynamic linker in
- // case of cg_llvm.
- return None;
- }
- let dlsym_name = if cfg!(target_os = "macos") {
- // On macOS `dlsym` expects the name without leading `_`.
- assert!(name.starts_with('_'), "{:?}", name);
- &name[1..]
- } else {
- &name
- };
- let symbol: libloading::Symbol<'_, *const u8> =
- unsafe { lib.get(dlsym_name.as_bytes()) }.unwrap();
- Some((name, *symbol))
- }));
- std::mem::forget(lib)
- }
+ let imported_dylibs = Box::leak(
+ dylib_paths
+ .into_iter()
+ .map(|path| unsafe { libloading::Library::new(&path).unwrap() })
+ .collect::<Box<[_]>>(),
+ );
sess.abort_if_errors();
- imported_symbols
+ Box::new(move |sym_name| {
+ for dylib in &*imported_dylibs {
+ if let Ok(sym) = unsafe { dylib.get::<*const u8>(sym_name.as_bytes()) } {
+ return Some(*sym);
+ }
+ }
+ None
+ })
}
fn codegen_shim<'tcx>(
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 8b3d475cb..3fcc84d39 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -27,7 +27,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
}
// Used by stdarch
- if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
+ if template[0] == InlineAsmTemplatePiece::String("mov ".to_string())
&& matches!(
template[1],
InlineAsmTemplatePiece::Placeholder {
@@ -36,24 +36,26 @@ pub(crate) fn codegen_inline_asm<'tcx>(
span: _
}
)
- && template[2] == InlineAsmTemplatePiece::String("\n".to_string())
- && template[3] == InlineAsmTemplatePiece::String("cpuid".to_string())
- && template[4] == InlineAsmTemplatePiece::String("\n".to_string())
- && template[5] == InlineAsmTemplatePiece::String("xchgq %rbx, ".to_string())
+ && template[2] == InlineAsmTemplatePiece::String(", rbx".to_string())
+ && template[3] == InlineAsmTemplatePiece::String("\n".to_string())
+ && template[4] == InlineAsmTemplatePiece::String("cpuid".to_string())
+ && template[5] == InlineAsmTemplatePiece::String("\n".to_string())
+ && template[6] == InlineAsmTemplatePiece::String("xchg ".to_string())
&& matches!(
- template[6],
+ template[7],
InlineAsmTemplatePiece::Placeholder {
operand_idx: 0,
modifier: Some('r'),
span: _
}
)
+ && template[8] == InlineAsmTemplatePiece::String(", rbx".to_string())
{
assert_eq!(operands.len(), 4);
let (leaf, eax_place) = match operands[1] {
InlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::ax)),
- late: true,
+ late: _,
ref in_value,
out_place: Some(out_place),
} => (
@@ -68,7 +70,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
X86InlineAsmRegClass::reg,
)),
- late: true,
+ late: _,
place: Some(place),
} => crate::base::codegen_place(fx, place),
_ => unreachable!(),
@@ -76,7 +78,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
let (sub_leaf, ecx_place) = match operands[2] {
InlineAsmOperand::InOut {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::cx)),
- late: true,
+ late: _,
ref in_value,
out_place: Some(out_place),
} => (
@@ -88,7 +90,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
let edx_place = match operands[3] {
InlineAsmOperand::Out {
reg: InlineAsmRegOrRegClass::Reg(InlineAsmReg::X86(X86InlineAsmReg::dx)),
- late: true,
+ late: _,
place: Some(place),
} => crate::base::codegen_place(fx, place),
_ => unreachable!(),
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index a799dca93..783d426c3 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -14,6 +14,10 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
target: Option<BasicBlock>,
) {
match intrinsic {
+ "llvm.x86.sse2.pause" | "llvm.aarch64.isb" => {
+ // Spin loop hint
+ }
+
// Used by `_mm_movemask_epi8` and `_mm256_movemask_epi8`
"llvm.x86.sse2.pmovmskb.128" | "llvm.x86.avx2.pmovmskb" | "llvm.x86.sse2.movmsk.pd" => {
intrinsic_args!(fx, args => (a); intrinsic);
@@ -25,8 +29,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
let mut res = fx.bcx.ins().iconst(types::I32, 0);
for lane in (0..lane_count).rev() {
- let a_lane =
- a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx);
+ let a_lane = a.value_lane(fx, lane).load_scalar(fx);
// cast float to int
let a_lane = match lane_ty {
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 2e4ca594f..0302b843a 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -84,6 +84,30 @@ fn simd_for_each_lane<'tcx>(
}
}
+fn simd_pair_for_each_lane_typed<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ x: CValue<'tcx>,
+ y: CValue<'tcx>,
+ ret: CPlace<'tcx>,
+ f: &dyn Fn(&mut FunctionCx<'_, '_, 'tcx>, CValue<'tcx>, CValue<'tcx>) -> CValue<'tcx>,
+) {
+ assert_eq!(x.layout(), y.layout());
+ let layout = x.layout();
+
+ let (lane_count, _lane_ty) = 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!(lane_count, ret_lane_count);
+
+ for lane_idx in 0..lane_count {
+ let x_lane = x.value_lane(fx, lane_idx);
+ let y_lane = y.value_lane(fx, lane_idx);
+
+ let res_lane = f(fx, x_lane, y_lane);
+
+ ret.place_lane(fx, lane_idx).write_cvalue(fx, res_lane);
+ }
+}
+
fn simd_pair_for_each_lane<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
x: CValue<'tcx>,
@@ -504,37 +528,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
_ => unreachable!(),
};
- let signed = type_sign(lhs.layout().ty);
-
- let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
-
- let (val, has_overflow) = checked_res.load_scalar_pair(fx);
- let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
-
- let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
-
- let val = match (intrinsic, signed) {
- (sym::saturating_add, false) => fx.bcx.ins().select(has_overflow, max, val),
- (sym::saturating_sub, false) => fx.bcx.ins().select(has_overflow, min, val),
- (sym::saturating_add, true) => {
- let rhs = rhs.load_scalar(fx);
- let rhs_ge_zero =
- fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
- let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
- fx.bcx.ins().select(has_overflow, sat_val, val)
- }
- (sym::saturating_sub, true) => {
- let rhs = rhs.load_scalar(fx);
- let rhs_ge_zero =
- fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
- let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
- fx.bcx.ins().select(has_overflow, sat_val, val)
- }
- _ => unreachable!(),
- };
-
- let res = CValue::by_val(val, lhs.layout());
-
+ let res = crate::num::codegen_saturating_int_binop(fx, bin_op, lhs, rhs);
ret.write_cvalue(fx, res);
}
sym::rotate_left => {
@@ -819,8 +813,8 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::ptr_guaranteed_cmp => {
intrinsic_args!(fx, args => (a, b); intrinsic);
- let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b);
- ret.write_cvalue(fx, val);
+ let val = crate::num::codegen_ptr_binop(fx, BinOp::Eq, a, b).load_scalar(fx);
+ ret.write_cvalue(fx, CValue::by_val(val, fx.layout_of(fx.tcx.types.u8)));
}
sym::caller_location => {
@@ -1206,7 +1200,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
// FIXME once unwinding is supported, change this to actually catch panics
let f_sig = fx.bcx.func.import_signature(Signature {
call_conv: fx.target_config.default_call_conv,
- params: vec![AbiParam::new(fx.bcx.func.dfg.value_type(data))],
+ params: vec![AbiParam::new(pointer_ty(fx.tcx))],
returns: vec![],
});
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 1f358b1bb..51fce8c85 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -2,6 +2,7 @@
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::Symbol;
+use rustc_target::abi::Endian;
use super::*;
use crate::prelude::*;
@@ -26,7 +27,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
span: Span,
) {
match intrinsic {
- sym::simd_cast => {
+ sym::simd_as | sym::simd_cast => {
intrinsic_args!(fx, args => (a); intrinsic);
if !a.layout().ty.is_simd() {
@@ -162,6 +163,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
}
}
} else {
+ // FIXME remove this case
intrinsic.as_str()["simd_shuffle".len()..].parse().unwrap()
};
@@ -650,8 +652,128 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
}
}
- // simd_saturating_*
- // simd_bitmask
+ sym::simd_select_bitmask => {
+ intrinsic_args!(fx, args => (m, a, b); intrinsic);
+
+ if !a.layout().ty.is_simd() {
+ report_simd_type_validation_error(fx, intrinsic, span, a.layout().ty);
+ return;
+ }
+ assert_eq!(a.layout(), b.layout());
+
+ let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+ let lane_layout = fx.layout_of(lane_ty);
+
+ let m = m.load_scalar(fx);
+
+ for lane in 0..lane_count {
+ let m_lane = fx.bcx.ins().ushr_imm(m, u64::from(lane) as i64);
+ let m_lane = fx.bcx.ins().band_imm(m_lane, 1);
+ let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+ let b_lane = b.value_lane(fx, lane).load_scalar(fx);
+
+ let m_lane = fx.bcx.ins().icmp_imm(IntCC::Equal, m_lane, 0);
+ let res_lane =
+ CValue::by_val(fx.bcx.ins().select(m_lane, b_lane, a_lane), lane_layout);
+
+ ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
+ }
+ }
+
+ sym::simd_bitmask => {
+ intrinsic_args!(fx, args => (a); intrinsic);
+
+ let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx);
+ let lane_clif_ty = fx.clif_type(lane_ty).unwrap();
+
+ // The `fn simd_bitmask(vector) -> unsigned integer` intrinsic takes a
+ // vector mask and returns the most significant bit (MSB) of each lane in the form
+ // of either:
+ // * an unsigned integer
+ // * an array of `u8`
+ // If the vector has less than 8 lanes, a u8 is returned with zeroed trailing bits.
+ //
+ // The bit order of the result depends on the byte endianness, LSB-first for little
+ // endian and MSB-first for big endian.
+ let expected_int_bits = lane_count.max(8);
+ let expected_bytes = expected_int_bits / 8 + ((expected_int_bits % 8 > 0) as u64);
+
+ match lane_ty.kind() {
+ ty::Int(_) | ty::Uint(_) => {}
+ _ => {
+ fx.tcx.sess.span_fatal(
+ span,
+ &format!(
+ "invalid monomorphization of `simd_bitmask` intrinsic: \
+ vector argument `{}`'s element type `{}`, expected integer element \
+ type",
+ a.layout().ty,
+ lane_ty
+ ),
+ );
+ }
+ }
+
+ let res_type =
+ Type::int_with_byte_size(u16::try_from(expected_bytes).unwrap()).unwrap();
+ let mut res = fx.bcx.ins().iconst(res_type, 0);
+
+ let lanes = match fx.tcx.sess.target.endian {
+ Endian::Big => Box::new(0..lane_count) as Box<dyn Iterator<Item = u64>>,
+ Endian::Little => Box::new((0..lane_count).rev()) as Box<dyn Iterator<Item = u64>>,
+ };
+ for lane in lanes {
+ let a_lane = a.value_lane(fx, lane).load_scalar(fx);
+
+ // extract sign bit of an int
+ let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, i64::from(lane_clif_ty.bits() - 1));
+
+ // shift sign bit into result
+ let a_lane_sign = clif_intcast(fx, a_lane_sign, res_type, false);
+ res = fx.bcx.ins().ishl_imm(res, 1);
+ res = fx.bcx.ins().bor(res, a_lane_sign);
+ }
+
+ match ret.layout().ty.kind() {
+ 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())
+ == Some(expected_bytes) => {}
+ _ => {
+ fx.tcx.sess.span_fatal(
+ span,
+ &format!(
+ "invalid monomorphization of `simd_bitmask` intrinsic: \
+ cannot return `{}`, expected `u{}` or `[u8; {}]`",
+ ret.layout().ty,
+ expected_int_bits,
+ expected_bytes
+ ),
+ );
+ }
+ }
+
+ let res = CValue::by_val(res, ret.layout());
+ ret.write_cvalue(fx, res);
+ }
+
+ sym::simd_saturating_add | sym::simd_saturating_sub => {
+ intrinsic_args!(fx, args => (x, y); intrinsic);
+
+ let bin_op = match intrinsic {
+ sym::simd_saturating_add => BinOp::Add,
+ sym::simd_saturating_sub => BinOp::Sub,
+ _ => unreachable!(),
+ };
+
+ // FIXME use vector instructions when possible
+ simd_pair_for_each_lane_typed(fx, x, y, ret, &|fx, x_lane, y_lane| {
+ crate::num::codegen_saturating_int_binop(fx, bin_op, x_lane, y_lane)
+ });
+ }
+
+ // simd_arith_offset
// simd_scatter
// simd_gather
_ => {
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index 913414e76..629d79d50 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -96,8 +96,8 @@ mod prelude {
pub(crate) use cranelift_codegen::ir::function::Function;
pub(crate) use cranelift_codegen::ir::types;
pub(crate) use cranelift_codegen::ir::{
- AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
- StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
+ AbiParam, Block, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot,
+ StackSlotData, StackSlotKind, TrapCode, Type, Value,
};
pub(crate) use cranelift_codegen::isa::{self, CallConv};
pub(crate) use cranelift_codegen::Context;
@@ -251,7 +251,6 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap();
- flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
flags_builder.set("enable_verifier", enable_verifier).unwrap();
flags_builder.set("regalloc_checker", enable_verifier).unwrap();
@@ -279,6 +278,15 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
}
}
+ if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+ // 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
+ flags_builder.set("enable_probestack", "false").unwrap();
+ }
+
let flags = settings::Flags::new(flags_builder);
let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 3c024a84d..cae6312a6 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -75,7 +75,7 @@ pub(crate) fn maybe_create_entry_wrapper(
let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();
let mut ctx = Context::new();
- ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig);
+ ctx.func.signature = cmain_sig;
{
let mut func_ctx = FunctionBuilderContext::new();
let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
diff --git a/compiler/rustc_codegen_cranelift/src/num.rs b/compiler/rustc_codegen_cranelift/src/num.rs
index 4ce8adb18..ecbab408d 100644
--- a/compiler/rustc_codegen_cranelift/src/num.rs
+++ b/compiler/rustc_codegen_cranelift/src/num.rs
@@ -150,18 +150,12 @@ pub(crate) fn codegen_int_binop<'tcx>(
BinOp::BitXor => b.bxor(lhs, rhs),
BinOp::BitAnd => b.band(lhs, rhs),
BinOp::BitOr => b.bor(lhs, rhs),
- BinOp::Shl => {
- let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
- let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
- fx.bcx.ins().ishl(lhs, actual_shift)
- }
+ BinOp::Shl => b.ishl(lhs, rhs),
BinOp::Shr => {
- let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
- let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
if signed {
- fx.bcx.ins().sshr(lhs, actual_shift)
+ b.sshr(lhs, rhs)
} else {
- fx.bcx.ins().ushr(lhs, actual_shift)
+ b.ushr(lhs, rhs)
}
}
// Compare binops handles by `codegen_binop`.
@@ -279,22 +273,15 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
}
}
BinOp::Shl => {
- let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
- let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
- let val = fx.bcx.ins().ishl(lhs, masked_shift);
+ let val = fx.bcx.ins().ishl(lhs, rhs);
let ty = fx.bcx.func.dfg.value_type(val);
let max_shift = i64::from(ty.bits()) - 1;
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
(val, has_overflow)
}
BinOp::Shr => {
- let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
- let masked_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
- let val = if !signed {
- fx.bcx.ins().ushr(lhs, masked_shift)
- } else {
- fx.bcx.ins().sshr(lhs, masked_shift)
- };
+ let val =
+ if !signed { fx.bcx.ins().ushr(lhs, rhs) } else { fx.bcx.ins().sshr(lhs, rhs) };
let ty = fx.bcx.func.dfg.value_type(val);
let max_shift = i64::from(ty.bits()) - 1;
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, rhs, max_shift);
@@ -309,6 +296,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
CValue::by_val_pair(res, has_overflow, out_layout)
}
+pub(crate) fn codegen_saturating_int_binop<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ bin_op: BinOp,
+ lhs: CValue<'tcx>,
+ rhs: CValue<'tcx>,
+) -> CValue<'tcx> {
+ assert_eq!(lhs.layout().ty, rhs.layout().ty);
+
+ let signed = type_sign(lhs.layout().ty);
+ let clif_ty = fx.clif_type(lhs.layout().ty).unwrap();
+ let (min, max) = type_min_max_value(&mut fx.bcx, clif_ty, signed);
+
+ let checked_res = crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs);
+ let (val, has_overflow) = checked_res.load_scalar_pair(fx);
+
+ let val = match (bin_op, signed) {
+ (BinOp::Add, false) => fx.bcx.ins().select(has_overflow, max, val),
+ (BinOp::Sub, false) => fx.bcx.ins().select(has_overflow, min, val),
+ (BinOp::Add, true) => {
+ let rhs = rhs.load_scalar(fx);
+ let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+ let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min);
+ fx.bcx.ins().select(has_overflow, sat_val, val)
+ }
+ (BinOp::Sub, true) => {
+ let rhs = rhs.load_scalar(fx);
+ let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, rhs, 0);
+ let sat_val = fx.bcx.ins().select(rhs_ge_zero, min, max);
+ fx.bcx.ins().select(has_overflow, sat_val, val)
+ }
+ _ => unreachable!(),
+ };
+
+ CValue::by_val(val, lhs.layout())
+}
+
pub(crate) fn codegen_float_binop<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
bin_op: BinOp,
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index dd9d891dd..9c88f7dbc 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -25,7 +25,12 @@ pub(crate) fn unsized_info<'tcx>(
.bcx
.ins()
.iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
- (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+ (
+ &ty::Dynamic(ref data_a, _, src_dyn_kind),
+ &ty::Dynamic(ref data_b, _, target_dyn_kind),
+ ) => {
+ assert_eq!(src_dyn_kind, target_dyn_kind);
+
let old_info =
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
if data_a.principal_def_id() == data_b.principal_def_id() {
@@ -101,6 +106,21 @@ fn unsize_ptr<'tcx>(
}
}
+/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
+pub(crate) fn cast_to_dyn_star<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ src: Value,
+ src_ty_and_layout: TyAndLayout<'tcx>,
+ dst_ty: Ty<'tcx>,
+ old_info: Option<Value>,
+) -> (Value, Value) {
+ assert!(
+ matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
+ "destination type must be a dyn*"
+ );
+ (src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
+}
+
/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub(crate) fn coerce_unsized_into<'tcx>(
@@ -147,6 +167,24 @@ pub(crate) fn coerce_unsized_into<'tcx>(
}
}
+pub(crate) fn coerce_dyn_star<'tcx>(
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ src: CValue<'tcx>,
+ dst: CPlace<'tcx>,
+) {
+ let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
+ let (data, vtable) = src.load_scalar_pair(fx);
+ (data, Some(vtable))
+ } else {
+ let data = src.load_scalar(fx);
+ (data, None)
+ };
+
+ let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);
+
+ dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
+}
+
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
pub(crate) fn size_and_align_of_dst<'tcx>(
diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index cfaadca94..c3dfbd372 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -107,6 +107,50 @@ impl<'tcx> CValue<'tcx> {
}
}
+ // FIXME remove
+ // Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
+ // vtable pointer.
+ pub(crate) fn dyn_star_force_data_on_stack(
+ self,
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ ) -> (Value, Value) {
+ assert!(self.1.ty.is_dyn_star());
+
+ match self.0 {
+ CValueInner::ByRef(ptr, None) => {
+ let (a_scalar, b_scalar) = match self.1.abi {
+ Abi::ScalarPair(a, b) => (a, b),
+ _ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
+ };
+ let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
+ let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
+ let mut flags = MemFlags::new();
+ flags.set_notrap();
+ let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
+ (ptr.get_addr(fx), vtable)
+ }
+ CValueInner::ByValPair(data, vtable) => {
+ let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData {
+ kind: StackSlotKind::ExplicitSlot,
+ // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to
+ // specify stack slot alignment.
+ size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15)
+ / 16
+ * 16,
+ });
+ let data_ptr = Pointer::stack_slot(stack_slot);
+ let mut flags = MemFlags::new();
+ flags.set_notrap();
+ data_ptr.store(fx, data, flags);
+
+ (data_ptr.get_addr(fx), vtable)
+ }
+ CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
+ unreachable!("dyn_star_force_data_on_stack({:?})", self)
+ }
+ }
+ }
+
pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
match self.0 {
CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),
@@ -236,6 +280,10 @@ impl<'tcx> CValue<'tcx> {
crate::unsize::coerce_unsized_into(fx, self, dest);
}
+ pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) {
+ crate::unsize::coerce_dyn_star(fx, self, dest);
+ }
+
/// If `ty` is signed, `const_val` must already be sign extended.
pub(crate) fn const_val(
fx: &mut FunctionCx<'_, '_, 'tcx>,
@@ -621,6 +669,14 @@ impl<'tcx> CPlace<'tcx> {
}
}
+ pub(crate) fn place_opaque_cast(
+ self,
+ fx: &mut FunctionCx<'_, '_, 'tcx>,
+ ty: Ty<'tcx>,
+ ) -> CPlace<'tcx> {
+ CPlace { inner: self.inner, layout: fx.layout_of(ty) }
+ }
+
pub(crate) fn place_field(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,
diff --git a/compiler/rustc_codegen_cranelift/src/vtable.rs b/compiler/rustc_codegen_cranelift/src/vtable.rs
index 36b3725ef..f04fb82de 100644
--- a/compiler/rustc_codegen_cranelift/src/vtable.rs
+++ b/compiler/rustc_codegen_cranelift/src/vtable.rs
@@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
arg: CValue<'tcx>,
idx: usize,
-) -> (Value, Value) {
- let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
- arg.load_scalar_pair(fx)
- } else {
- let (ptr, vtable) = arg.try_to_ptr().unwrap();
- (ptr.get_addr(fx), vtable.unwrap())
+) -> (Pointer, Value) {
+ let (ptr, vtable) = 'block: {
+ if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
+ if ty.is_dyn_star() {
+ let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
+ let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
+ let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
+ let vtable =
+ dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
+ break 'block (ptr, vtable);
+ }
+ }
+
+ if let Abi::ScalarPair(_, _) = arg.layout().abi {
+ let (ptr, vtable) = arg.load_scalar_pair(fx);
+ (Pointer::new(ptr), vtable)
+ } else {
+ let (ptr, vtable) = arg.try_to_ptr().unwrap();
+ (ptr, vtable.unwrap())
+ }
};
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 848c34211..6fb1cbfad 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -11,10 +11,6 @@ use crate::intrinsic::ArgAbiExt;
use crate::type_of::LayoutGccExt;
impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
- fn apply_attrs_callsite(&mut self, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _callsite: Self::Value) {
- // TODO(antoyo)
- }
-
fn get_param(&mut self, index: usize) -> Self::Value {
let func = self.current_func();
let param = func.get_param(index as i32);
diff --git a/compiler/rustc_codegen_gcc/src/archive.rs b/compiler/rustc_codegen_gcc/src/archive.rs
index 96c773101..f18ae7ea5 100644
--- a/compiler/rustc_codegen_gcc/src/archive.rs
+++ b/compiler/rustc_codegen_gcc/src/archive.rs
@@ -1,6 +1,8 @@
use std::fs::File;
use std::path::{Path, PathBuf};
+use crate::errors::RanlibFailure;
+
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use rustc_session::Session;
@@ -182,7 +184,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
std::process::Command::new("ranlib").arg(output).status().expect("Couldn't run ranlib");
if !status.success() {
- self.config.sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
+ self.config.sess.emit_fatal(RanlibFailure::new(status.code()));
}
any_members
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 52fd66af0..c346dbd63 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -12,6 +12,7 @@ use std::borrow::Cow;
use crate::builder::Builder;
use crate::context::CodegenCx;
+use crate::errors::UnwindingInlineAsm;
use crate::type_of::LayoutGccExt;
use crate::callee::get_fn;
@@ -109,7 +110,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], _instance: Instance<'_>, _dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>) {
if options.contains(InlineAsmOptions::MAY_UNWIND) {
self.sess()
- .struct_span_err(span[0], "GCC backend does not support unwinding from inline asm")
+ .create_err(UnwindingInlineAsm { span: span[0] })
.emit();
return;
}
@@ -497,7 +498,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
if options.contains(InlineAsmOptions::NORETURN) {
let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) };
- self.call(self.type_void(), builtin_unreachable, &[], None);
+ self.call(self.type_void(), None, builtin_unreachable, &[], None);
}
// Write results to outputs.
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 6994eeb00..a314b7cc2 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -444,11 +444,23 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.block.end_with_switch(None, value, default_block, &gcc_cases);
}
- fn invoke(&mut self, typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+ fn invoke(
+ &mut self,
+ typ: Type<'gcc>,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
+ func: RValue<'gcc>,
+ args: &[RValue<'gcc>],
+ then: Block<'gcc>,
+ catch: Block<'gcc>,
+ _funclet: Option<&Funclet>,
+ ) -> RValue<'gcc> {
// TODO(bjorn3): Properly implement unwinding.
- let call_site = self.call(typ, func, args, None);
+ let call_site = self.call(typ, None, func, args, None);
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
self.llbb().end_with_conditional(None, condition, then, catch);
+ if let Some(_fn_abi) = fn_abi {
+ // TODO(bjorn3): Apply function attributes
+ }
call_site
}
@@ -643,11 +655,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
}
- fn dynamic_alloca(&mut self, _ty: Type<'gcc>, _align: Align) -> RValue<'gcc> {
- unimplemented!();
- }
-
- fn array_alloca(&mut self, _ty: Type<'gcc>, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
+ fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
unimplemented!();
}
@@ -1227,16 +1235,27 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
// TODO(antoyo)
}
- fn call(&mut self, _typ: Type<'gcc>, func: RValue<'gcc>, args: &[RValue<'gcc>], funclet: Option<&Funclet>) -> RValue<'gcc> {
+ fn call(
+ &mut self,
+ _typ: Type<'gcc>,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
+ func: RValue<'gcc>,
+ args: &[RValue<'gcc>],
+ funclet: Option<&Funclet>,
+ ) -> RValue<'gcc> {
// FIXME(antoyo): remove when having a proper API.
let gcc_func = unsafe { std::mem::transmute(func) };
- if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
+ let call = if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() {
self.function_call(func, args, funclet)
}
else {
// If it's a not function that was defined, it's a function pointer.
self.function_ptr_call(func, args, funclet)
+ };
+ if let Some(_fn_abi) = fn_abi {
+ // TODO(bjorn3): Apply function attributes
}
+ call
}
fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 356c03ee3..81f533288 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -14,6 +14,7 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan
use crate::base;
use crate::context::CodegenCx;
+use crate::errors::LinkageConstOrMutType;
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -368,10 +369,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
cx.layout_of(mt.ty).gcc_type(cx, true)
}
else {
- cx.sess().span_fatal(
- span,
- "must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
- )
+ cx.sess().emit_fatal(LinkageConstOrMutType { span: span })
};
// Declare a symbol `foo` with the desired linkage.
let global1 = cx.declare_global_with_linkage(&sym, llty2, base::global_linkage_to_gcc(linkage));
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 478f6d893..62a61eb85 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
use rustc_session::Session;
-use rustc_span::Span;
+use rustc_span::{Span, source_map::respan};
use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
@@ -293,7 +293,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type)
}
- pub fn sess(&self) -> &Session {
+ pub fn sess(&self) -> &'tcx Session {
&self.tcx.sess
}
@@ -416,10 +416,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.codegen_unit
}
- fn used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> {
- unimplemented!();
- }
-
fn set_frame_pointer_type(&self, _llfn: RValue<'gcc>) {
// TODO(antoyo)
}
@@ -428,10 +424,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
// TODO(antoyo)
}
- fn create_used_variable(&self) {
- unimplemented!();
- }
-
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
if self.get_declared_value("main").is_none() {
Some(self.declare_cfn("main", fn_type))
@@ -443,14 +435,6 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
None
}
}
-
- fn compiler_used_statics(&self) -> &RefCell<Vec<RValue<'gcc>>> {
- unimplemented!()
- }
-
- fn create_compiler_used_variable(&self) {
- unimplemented!()
- }
}
impl<'gcc, 'tcx> HasTyCtxt<'tcx> for CodegenCx<'gcc, 'tcx> {
@@ -477,7 +461,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
if let LayoutError::SizeOverflow(_) = err {
- self.sess().span_fatal(span, &err.to_string())
+ self.sess().emit_fatal(respan(span, err))
} else {
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
}
@@ -495,7 +479,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
fn_abi_request: FnAbiRequest<'tcx>,
) -> ! {
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
- self.sess().span_fatal(span, &err.to_string())
+ self.sess().emit_fatal(respan(span, err))
} else {
match fn_abi_request {
FnAbiRequest::OfFnPtr { sig, extra_args } => {
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
new file mode 100644
index 000000000..15ad90f90
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -0,0 +1,242 @@
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
+use rustc_macros::Diagnostic;
+use rustc_middle::ty::Ty;
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
+
+struct ExitCode(Option<i32>);
+
+impl IntoDiagnosticArg for ExitCode {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ let ExitCode(exit_code) = self;
+ match exit_code {
+ Some(t) => t.into_diagnostic_arg(),
+ None => DiagnosticArgValue::Str(Cow::Borrowed("<signal>")),
+ }
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_ranlib_failure)]
+pub(crate) struct RanlibFailure {
+ exit_code: ExitCode,
+}
+
+impl RanlibFailure {
+ pub fn new(exit_code: Option<i32>) -> Self {
+ RanlibFailure { exit_code: ExitCode(exit_code) }
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_basic_integer, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_invalid_float_vector, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub elem_ty: &'a str,
+ pub vec_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_not_float, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_unrecognized, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnrecognized {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub elem_ty: Ty<'a>,
+ pub vec_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_element, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_ty: Ty<'a>,
+ pub elem_ty: Ty<'a>,
+ pub ret_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_invalid_bitmask, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ty: Ty<'a>,
+ pub expected_int_bits: u64,
+ pub expected_bytes: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_simd_shuffle, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_expected_simd, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub position: &'a str,
+ pub found_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_mask_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationMaskType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_return_length, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_len: u64,
+ pub ret_ty: Ty<'a>,
+ pub out_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_return_length_input_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_len: u64,
+ pub in_ty: Ty<'a>,
+ pub ret_ty: Ty<'a>,
+ pub out_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_return_element, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_elem: Ty<'a>,
+ pub in_ty: Ty<'a>,
+ pub ret_ty: Ty<'a>,
+ pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_return_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_elem: Ty<'a>,
+ pub in_ty: Ty<'a>,
+ pub ret_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_inserted_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_elem: Ty<'a>,
+ pub in_ty: Ty<'a>,
+ pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_return_integer_type, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub ret_ty: Ty<'a>,
+ pub out_ty: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_mismatched_lengths, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationMismatchedLengths {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub m_len: u64,
+ pub v_len: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_cast, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_ty: Ty<'a>,
+ pub in_elem: Ty<'a>,
+ pub ret_ty: Ty<'a>,
+ pub out_elem: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_invalid_monomorphization_unsupported_operation, code = "E0511")]
+pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+ pub in_ty: Ty<'a>,
+ pub in_elem: Ty<'a>,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_linkage_const_or_mut_type)]
+pub(crate) struct LinkageConstOrMutType {
+ #[primary_span]
+ pub span: Span
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_lto_not_supported)]
+pub(crate) struct LTONotSupported;
+
+#[derive(Diagnostic)]
+#[diag(codegen_gcc_unwinding_inline_asm)]
+pub(crate) struct UnwindingInlineAsm {
+ #[primary_span]
+ pub span: Span
+}
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 02cedd464..49be6c649 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -4,7 +4,7 @@ mod simd;
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh;
-use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error};
+use rustc_codegen_ssa::common::IntPredicate;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
@@ -20,6 +20,7 @@ use crate::abi::GccType;
use crate::builder::Builder;
use crate::common::{SignType, TypeReflection};
use crate::context::CodegenCx;
+use crate::errors::InvalidMonomorphizationBasicInteger;
use crate::type_of::LayoutGccExt;
use crate::intrinsic::simd::generic_simd_intrinsic;
@@ -99,7 +100,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
_ if simple.is_some() => {
// FIXME(antoyo): remove this cast when the API supports function.
let func = unsafe { std::mem::transmute(simple.expect("simple")) };
- self.call(self.type_void(), func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
+ self.call(self.type_void(), None, func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
},
sym::likely => {
self.expect(args[0].immediate(), true)
@@ -242,15 +243,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
_ => bug!(),
},
None => {
- span_invalid_monomorphization_error(
- tcx.sess,
- span,
- &format!(
- "invalid monomorphization of `{}` intrinsic: \
- expected basic integer type, found `{}`",
- name, ty
- ),
- );
+ tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty });
return;
}
}
@@ -348,7 +341,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
fn abort(&mut self) {
let func = self.context.get_builtin_function("abort");
let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
- self.call(self.type_void(), func, &[], None);
+ self.call(self.type_void(), None, func, &[], None);
}
fn assume(&mut self, value: Self::Value) {
@@ -1131,7 +1124,7 @@ fn try_intrinsic<'gcc, 'tcx>(bx: &mut Builder<'_, 'gcc, 'tcx>, try_func: RValue<
// NOTE: the `|| true` here is to use the panic=abort strategy with panic=unwind too
if bx.sess().panic_strategy() == PanicStrategy::Abort || true {
// TODO(bjorn3): Properly implement unwinding and remove the `|| true` once this is done.
- bx.call(bx.type_void(), try_func, &[data], None);
+ bx.call(bx.type_void(), None, try_func, &[data], None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
let ret_align = bx.tcx.data_layout.i32_align.abi;
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 2401f3350..12e416f62 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -2,7 +2,7 @@ use std::cmp::Ordering;
use gccjit::{BinaryOp, RValue, Type, ToRValue};
use rustc_codegen_ssa::base::compare_simd_types;
-use rustc_codegen_ssa::common::{TypeKind, span_invalid_monomorphization_error};
+use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
@@ -14,43 +14,48 @@ use rustc_span::{Span, Symbol, sym};
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
+};
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>, ()> {
// macros for error handling:
- #[allow(unused_macro_rules)]
- macro_rules! emit_error {
- ($msg: tt) => {
- emit_error!($msg, )
- };
- ($msg: tt, $($fmt: tt)*) => {
- span_invalid_monomorphization_error(
- bx.sess(), span,
- &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
- name, $($fmt)*));
- }
- }
-
macro_rules! return_error {
- ($($fmt: tt)*) => {
+ ($err:expr) => {
{
- emit_error!($($fmt)*);
+ bx.sess().emit_err($err);
return Err(());
}
}
}
-
macro_rules! require {
- ($cond: expr, $($fmt: tt)*) => {
+ ($cond:expr, $err:expr) => {
if !$cond {
- return_error!($($fmt)*);
+ return_error!($err);
}
- };
+ }
}
-
macro_rules! require_simd {
($ty: expr, $position: expr) => {
- require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty)
+ require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty })
};
}
@@ -82,10 +87,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
bx.load(int_ty, ptr, Align::ONE)
}
_ => return_error!(
- "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`",
- mask_ty,
- expected_int_bits,
- expected_bytes
+ InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes }
),
};
@@ -127,18 +129,11 @@ 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,
- "expected return type with length {} (same as input type `{}`), \
- found `{}` with length {}",
- 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,
- "expected return type with integer elements, found `{}` with non-integer `{}`",
- ret_ty,
- out_ty
+ InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty}
);
return Ok(compare_simd_types(
@@ -163,8 +158,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})
}
_ => return_error!(
- "simd_shuffle index must be an array of `u32`, got `{}`",
- args[2].layout.ty
+ InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty }
),
}
}
@@ -179,19 +173,11 @@ 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!(
out_len == n,
- "expected return type of length {}, found `{}` with length {}",
- n,
- ret_ty,
- out_len
+ InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len }
);
require!(
in_elem == out_ty,
- "expected return element type `{}` (element of input `{}`), \
- found `{}` with element type `{}`",
- in_elem,
- in_ty,
- ret_ty,
- out_ty
+ InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
);
let vector = args[2].immediate();
@@ -207,10 +193,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::simd_insert {
require!(
in_elem == arg_tys[2],
- "expected inserted type `{}` (element of input `{}`), found `{}`",
- in_elem,
- in_ty,
- arg_tys[2]
+ InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
);
let vector = args[0].immediate();
let index = args[1].immediate();
@@ -263,10 +246,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::simd_extract {
require!(
ret_ty == in_elem,
- "expected return type `{}` (element of input `{}`), found `{}`",
- in_elem,
- in_ty,
- ret_ty
+ InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
let vector = args[0].immediate();
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
@@ -279,13 +259,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
require!(
m_len == v_len,
- "mismatched lengths: mask length `{}` != other vector length `{}`",
- m_len,
- v_len
+ InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len }
);
match m_elem_ty.kind() {
ty::Int(_) => {}
- _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty),
+ _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }),
}
return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
}
@@ -295,12 +273,7 @@ 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,
- "expected return type with length {} (same as input type `{}`), \
- found `{}` with length {}",
- 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 {
@@ -412,13 +385,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}
_ => { /* Unsupported. Fallthrough. */ }
}
- require!(
- false,
- "unsupported cast from `{}` with element `{}` to `{}` with element `{}`",
- in_ty,
- in_elem,
- ret_ty,
- out_elem
+ return_error!(
+ InvalidMonomorphizationUnsupportedCast { span, name, in_ty, in_elem, ret_ty, out_elem }
);
}
@@ -431,10 +399,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})*
_ => {},
}
- require!(false,
- "unsupported operation on `{}` with element `{}`",
- in_ty,
- in_elem)
+ return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
})*
}
}
@@ -448,23 +413,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
span: Span,
args: &[OperandRef<'tcx, RValue<'gcc>>],
) -> Result<RValue<'gcc>, ()> {
- macro_rules! emit_error {
- ($msg: tt, $($fmt: tt)*) => {
- span_invalid_monomorphization_error(
- bx.sess(), span,
- &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
- name, $($fmt)*));
- }
- }
macro_rules! return_error {
- ($($fmt: tt)*) => {
+ ($err:expr) => {
{
- emit_error!($($fmt)*);
+ 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);
@@ -472,16 +428,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
32 => ("f32", elem_ty),
64 => ("f64", elem_ty),
_ => {
- return_error!(
- "unsupported element type `{}` of floating-point vector `{}`",
- f.name_str(),
- in_ty
- );
+ return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
}
}
}
else {
- return_error!("`{}` is not a floating-point type", in_ty);
+ return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
};
let vec_ty = bx.cx.type_vector(elem_ty, in_len);
@@ -504,12 +456,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)),
sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)),
- _ => return_error!("unrecognized intrinsic `{}`", name),
+ _ => 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, 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)
}
@@ -557,10 +509,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})*
_ => {},
}
- require!(false,
- "unsupported operation on `{}` with element `{}`",
- in_ty,
- in_elem)
+ return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
})*
}
}
@@ -579,12 +528,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)),
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)),
_ => {
- return_error!(
- "expected element type `{}` of vector type `{}` \
- to be a signed or unsigned integer type",
- arg_tys[0].simd_size_and_type(bx.tcx()).1,
- arg_tys[0]
- );
+ return_error!(InvalidMonomorphizationExpectedSignedUnsigned {
+ span,
+ name,
+ elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1,
+ vec_ty: arg_tys[0],
+ });
}
};
let builtin_name =
@@ -617,10 +566,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name {
require!(
ret_ty == in_elem,
- "expected return type `{}` (element of input `{}`), found `{}`",
- in_elem,
- in_ty,
- ret_ty
+ InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {
@@ -644,13 +590,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
}
}
- _ => return_error!(
- "unsupported {} from `{}` with element `{}` to `{}`",
- sym::$name,
- in_ty,
- in_elem,
- ret_ty
- ),
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
};
}
};
@@ -676,20 +616,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name {
require!(
ret_ty == in_elem,
- "expected return type `{}` (element of input `{}`), found `{}`",
- in_elem,
- in_ty,
- ret_ty
+ 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!(
- "unsupported {} from `{}` with element `{}` to `{}`",
- sym::$name,
- in_ty,
- in_elem,
- ret_ty
- ),
+ _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
};
}
};
@@ -704,22 +635,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let input = if !$boolean {
require!(
ret_ty == in_elem,
- "expected return type `{}` (element of input `{}`), found `{}`",
- in_elem,
- in_ty,
- ret_ty
+ InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
);
args[0].immediate()
} else {
match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {}
- _ => return_error!(
- "unsupported {} from `{}` with element `{}` to `{}`",
- sym::$name,
- in_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:
@@ -733,11 +655,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) })
}
_ => return_error!(
- "unsupported {} from `{}` with element `{}` to `{}`",
- sym::$name,
- in_ty,
- in_elem,
- ret_ty
+ 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 223466fb9..accd02ab0 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -18,6 +18,8 @@
#![recursion_limit="256"]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
extern crate rustc_apfloat;
extern crate rustc_ast;
@@ -25,6 +27,7 @@ extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_hir;
+extern crate rustc_macros;
extern crate rustc_metadata;
extern crate rustc_middle;
extern crate rustc_session;
@@ -50,6 +53,7 @@ mod context;
mod coverageinfo;
mod debuginfo;
mod declare;
+mod errors;
mod int;
mod intrinsic;
mod mono_item;
@@ -59,6 +63,7 @@ mod type_of;
use std::any::Any;
use std::sync::{Arc, Mutex};
+use crate::errors::LTONotSupported;
use gccjit::{Context, OptimizationLevel, CType};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
@@ -97,7 +102,7 @@ pub struct GccCodegenBackend {
impl CodegenBackend for GccCodegenBackend {
fn init(&self, sess: &Session) {
if sess.lto() != Lto::No {
- sess.warn("LTO is not supported. You may get a linker error.");
+ sess.emit_warning(LTONotSupported {});
}
let temp_dir = TempDir::new().expect("cannot create temporary directory");
@@ -166,15 +171,6 @@ impl ExtraBackendMethods for GccCodegenBackend {
Ok(())
})
}
-
- fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str {
- unimplemented!();
- }
-
- fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> {
- None
- // TODO(antoyo)
- }
}
pub struct ModuleBuffer;
@@ -205,7 +201,6 @@ impl WriteBackendMethods for GccCodegenBackend {
type Module = GccContext;
type TargetMachine = ();
type ModuleBuffer = ModuleBuffer;
- type Context = ();
type ThinData = ();
type ThinBuffer = ThinBuffer;
diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs
index 46abbb553..38c1eac7a 100644
--- a/compiler/rustc_codegen_gcc/tests/run/asm.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs
@@ -3,11 +3,12 @@
// Run-time:
// status: 0
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::{asm, global_asm};
-global_asm!("
+global_asm!(
+ "
.global add_asm
add_asm:
mov rax, rdi
@@ -132,7 +133,9 @@ fn main() {
assert_eq!(x, 43);
// check sym fn
- extern "C" fn foo() -> u64 { 42 }
+ extern "C" fn foo() -> u64 {
+ 42
+ }
let x: u64;
unsafe {
asm!("call {}", sym foo, lateout("rax") x);
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index 2b90e4ae8..75779622b 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -3,7 +3,7 @@
// Run-time:
// status: 0
-#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
+#![feature(const_black_box, core_intrinsics, start)]
#![no_std]
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 74115353a..0ad39c240 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -5,13 +5,11 @@ edition = "2021"
[lib]
test = false
-doctest = false
[dependencies]
bitflags = "1.0"
cstr = "0.2"
libc = "0.2"
-libloading = "0.7.1"
measureme = "10.0.0"
object = { version = "0.29.0", default-features = false, features = ["std", "read_core", "archive", "coff", "elf", "macho", "pe"] }
tracing = "0.1"
@@ -35,3 +33,4 @@ 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"
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 26f5225f6..d478efc86 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -592,10 +592,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
- fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value) {
- fn_abi.apply_attrs_callsite(self, callsite)
- }
-
fn get_param(&mut self, index: usize) -> Self::Value {
llvm::get_param(self.llfn(), index as c_uint)
}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 5202ac697..017513721 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -430,9 +430,9 @@ pub(crate) fn inline_asm_call<'ll>(
);
let call = if let Some((dest, catch, funclet)) = dest_catch_funclet {
- bx.invoke(fty, v, inputs, dest, catch, funclet)
+ bx.invoke(fty, None, v, inputs, dest, catch, funclet)
} else {
- bx.call(fty, v, inputs, None)
+ bx.call(fty, None, v, inputs, None)
};
// Store mark in a metadata node so we can map LLVM errors
@@ -551,6 +551,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
format!("{{{}}}", reg.name())
}
}
+ // The constraints can be retrieved from
+ // https://llvm.org/docs/LangRef.html#supported-constraint-code-list
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
@@ -624,6 +626,8 @@ fn modifier_to_llvm(
reg: InlineAsmRegClass,
modifier: Option<char>,
) -> Option<char> {
+ // The modifiers can be retrieved from
+ // https://llvm.org/docs/LangRef.html#asm-template-argument-modifiers
match reg {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs
index ed96355a0..082665bba 100644
--- a/compiler/rustc_codegen_llvm/src/back/archive.rs
+++ b/compiler/rustc_codegen_llvm/src/back/archive.rs
@@ -2,16 +2,20 @@
use std::env;
use std::ffi::{CStr, CString, OsString};
-use std::io;
+use std::fs;
+use std::io::{self, Write};
use std::mem;
use std::path::{Path, PathBuf};
use std::ptr;
use std::str;
+use object::read::macho::FatArch;
+
use crate::common;
use crate::llvm::archive_ro::{ArchiveRO, Child};
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
+use rustc_data_structures::memmap::Mmap;
use rustc_session::cstore::DllImport;
use rustc_session::Session;
@@ -53,13 +57,70 @@ fn llvm_machine_type(cpu: &str) -> LLVMMachineType {
}
}
+fn try_filter_fat_archs(
+ archs: object::read::Result<&[impl FatArch]>,
+ target_arch: object::Architecture,
+ archive_path: &Path,
+ archive_map_data: &[u8],
+) -> io::Result<Option<PathBuf>> {
+ let archs = archs.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
+
+ let desired = match archs.iter().filter(|a| a.architecture() == target_arch).next() {
+ Some(a) => a,
+ None => return Ok(None),
+ };
+
+ let (mut new_f, extracted_path) = tempfile::Builder::new()
+ .suffix(archive_path.file_name().unwrap())
+ .tempfile()?
+ .keep()
+ .unwrap();
+
+ new_f.write_all(
+ desired.data(archive_map_data).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?,
+ )?;
+
+ Ok(Some(extracted_path))
+}
+
+fn try_extract_macho_fat_archive(
+ sess: &Session,
+ archive_path: &Path,
+) -> io::Result<Option<PathBuf>> {
+ let archive_map = unsafe { Mmap::map(fs::File::open(&archive_path)?)? };
+ let target_arch = match sess.target.arch.as_ref() {
+ "aarch64" => object::Architecture::Aarch64,
+ "x86_64" => object::Architecture::X86_64,
+ _ => return Ok(None),
+ };
+
+ match object::macho::FatHeader::parse(&*archive_map) {
+ Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC => {
+ let archs = object::macho::FatHeader::parse_arch32(&*archive_map);
+ try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ }
+ Ok(h) if h.magic.get(object::endian::BigEndian) == object::macho::FAT_MAGIC_64 => {
+ let archs = object::macho::FatHeader::parse_arch64(&*archive_map);
+ try_filter_fat_archs(archs, target_arch, archive_path, &*archive_map)
+ }
+ // Not a FatHeader at all, just return None.
+ _ => Ok(None),
+ }
+}
+
impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
fn add_archive(
&mut self,
archive: &Path,
skip: Box<dyn FnMut(&str) -> bool + 'static>,
) -> io::Result<()> {
- let archive_ro = match ArchiveRO::open(archive) {
+ let mut archive = archive.to_path_buf();
+ if self.sess.target.llvm_target.contains("-apple-macosx") {
+ if let Some(new_archive) = try_extract_macho_fat_archive(&self.sess, &archive)? {
+ archive = new_archive
+ }
+ }
+ let archive_ro = match ArchiveRO::open(&archive) {
Ok(ar) => ar,
Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)),
};
@@ -67,7 +128,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
return Ok(());
}
self.additions.push(Addition::Archive {
- path: archive.to_path_buf(),
+ path: archive,
archive: archive_ro,
skip: Box::new(skip),
});
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index a89df00e2..a49cc7f8d 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -1,8 +1,6 @@
-use crate::back::write::{
- self, save_temp_bitcode, to_llvm_opt_settings, with_llvm_pmb, DiagnosticHandlers,
-};
-use crate::llvm::{self, build_string, False, True};
-use crate::{llvm_util, LlvmCodegenBackend, ModuleLlvm};
+use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
+use crate::llvm::{self, build_string};
+use crate::{LlvmCodegenBackend, ModuleLlvm};
use object::read::archive::ArchiveFile;
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
use rustc_codegen_ssa::back::symbol_export;
@@ -34,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin";
pub fn crate_type_allows_lto(crate_type: CrateType) -> bool {
match crate_type {
- CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true,
- CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false,
+ CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true,
+ CrateType::Rlib | CrateType::ProcMacro => false,
}
}
@@ -75,17 +73,6 @@ fn prepare_lto(
// with either fat or thin LTO
let mut upstream_modules = Vec::new();
if cgcx.lto != Lto::ThinLocal {
- if cgcx.opts.cg.prefer_dynamic {
- diag_handler
- .struct_err("cannot prefer dynamic linking when performing LTO")
- .note(
- "only 'staticlib', 'bin', and 'cdylib' outputs are \
- supported with LTO",
- )
- .emit();
- return Err(FatalError);
- }
-
// Make sure we actually can run LTO
for crate_type in cgcx.crate_types.iter() {
if !crate_type_allows_lto(*crate_type) {
@@ -94,9 +81,25 @@ fn prepare_lto(
static library outputs",
);
return Err(e);
+ } 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`"));
+ }
}
}
+ if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
+ diag_handler
+ .struct_err("cannot prefer dynamic linking when performing LTO")
+ .note(
+ "only 'staticlib', 'bin', and 'cdylib' outputs are \
+ supported with LTO",
+ )
+ .emit();
+ return Err(FatalError);
+ }
+
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
let exported_symbols =
cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
@@ -575,7 +578,7 @@ pub(crate) fn run_pass_manager(
module: &mut ModuleCodegen<ModuleLlvm>,
thin: bool,
) -> Result<(), FatalError> {
- let _timer = cgcx.prof.extra_verbose_generic_activity("LLVM_lto_optimize", &*module.name);
+ let _timer = cgcx.prof.verbose_generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
let config = cgcx.config(module.kind);
// Now we have one massive module inside of llmod. Time to run the
@@ -597,61 +600,9 @@ pub(crate) fn run_pass_manager(
1,
);
}
- if llvm_util::should_use_new_llvm_pass_manager(
- &config.new_llvm_pass_manager,
- &cgcx.target_arch,
- ) {
- let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
- let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
- write::optimize_with_new_llvm_pass_manager(
- cgcx,
- diag_handler,
- module,
- config,
- opt_level,
- opt_stage,
- )?;
- debug!("lto done");
- return Ok(());
- }
-
- let pm = llvm::LLVMCreatePassManager();
- llvm::LLVMAddAnalysisPasses(module.module_llvm.tm, pm);
-
- if config.verify_llvm_ir {
- let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- let opt_level = config
- .opt_level
- .map(|x| to_llvm_opt_settings(x).0)
- .unwrap_or(llvm::CodeGenOptLevel::None);
- with_llvm_pmb(module.module_llvm.llmod(), config, opt_level, false, &mut |b| {
- if thin {
- llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
- } else {
- llvm::LLVMRustPassManagerBuilderPopulateLTOPassManager(
- b, pm, /* Internalize = */ False, /* RunInliner = */ True,
- );
- }
- });
-
- // We always generate bitcode through ThinLTOBuffers,
- // which do not support anonymous globals
- if config.bitcode_needed() {
- let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- if config.verify_llvm_ir {
- let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast());
- llvm::LLVMRustAddPass(pm, pass.unwrap());
- }
-
- llvm::LLVMRunPassManager(pm, module.module_llvm.llmod());
-
- llvm::LLVMDisposePassManager(pm);
+ let opt_stage = if thin { llvm::OptStage::ThinLTO } else { llvm::OptStage::FatLTO };
+ let opt_level = config.opt_level.unwrap_or(config::OptLevel::No);
+ write::llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage)?;
}
debug!("lto done");
Ok(())
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index a695df840..11053a8f6 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -21,7 +21,6 @@ use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_errors::{FatalError, Handler, Level};
use rustc_fs_util::{link_or_copy, path_to_c_string};
-use rustc_middle::bug;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath};
use rustc_session::Session;
@@ -417,7 +416,7 @@ fn get_instr_profile_output_path(config: &ModuleConfig) -> Option<CString> {
}
}
-pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
+pub(crate) unsafe fn llvm_optimize(
cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler: &Handler,
module: &ModuleCodegen<ModuleLlvm>,
@@ -465,7 +464,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager(
// FIXME: NewPM doesn't provide a facility to pass custom InlineParams.
// We would have to add upstream support for this first, before we can support
// config.inline_threshold and our more aggressive default thresholds.
- let result = llvm::LLVMRustOptimizeWithNewPassManager(
+ let result = llvm::LLVMRustOptimize(
module.module_llvm.llmod(),
&*module.module_llvm.tm,
to_pass_builder_opt_level(opt_level),
@@ -509,18 +508,11 @@ pub(crate) unsafe fn optimize(
let llmod = module.module_llvm.llmod();
let llcx = &*module.module_llvm.llcx;
- let tm = &*module.module_llvm.tm;
let _handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
let module_name = module.name.clone();
let module_name = Some(&module_name[..]);
- if let Some(false) = config.new_llvm_pass_manager && llvm_util::get_version() >= (15, 0, 0) {
- diag_handler.warn(
- "ignoring `-Z new-llvm-pass-manager=no`, which is no longer supported with LLVM 15",
- );
- }
-
if config.emit_no_opt_bc {
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
let out = path_to_c_string(&out);
@@ -528,191 +520,24 @@ pub(crate) unsafe fn optimize(
}
if let Some(opt_level) = config.opt_level {
- if llvm_util::should_use_new_llvm_pass_manager(
- &config.new_llvm_pass_manager,
- &cgcx.target_arch,
- ) {
- let opt_stage = match cgcx.lto {
- Lto::Fat => llvm::OptStage::PreLinkFatLTO,
- Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
- _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
- _ => llvm::OptStage::PreLinkNoLTO,
- };
- return optimize_with_new_llvm_pass_manager(
- cgcx,
- diag_handler,
- module,
- config,
- opt_level,
- opt_stage,
- );
- }
-
- if cgcx.prof.llvm_recording_enabled() {
- diag_handler
- .warn("`-Z self-profile-events = llvm` requires `-Z new-llvm-pass-manager`");
- }
-
- // Create the two optimizing pass managers. These mirror what clang
- // does, and are by populated by LLVM's default PassManagerBuilder.
- // Each manager has a different set of passes, but they also share
- // some common passes.
- let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod);
- let mpm = llvm::LLVMCreatePassManager();
-
- {
- let find_pass = |pass_name: &str| {
- let pass_name = SmallCStr::new(pass_name);
- llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr())
- };
-
- if config.verify_llvm_ir {
- // Verification should run as the very first pass.
- llvm::LLVMRustAddPass(fpm, find_pass("verify").unwrap());
- }
-
- let mut extra_passes = Vec::new();
- let mut have_name_anon_globals_pass = false;
-
- for pass_name in &config.passes {
- if pass_name == "lint" {
- // Linting should also be performed early, directly on the generated IR.
- llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap());
- continue;
- }
-
- if let Some(pass) = find_pass(pass_name) {
- extra_passes.push(pass);
- } else {
- diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass_name));
- }
-
- if pass_name == "name-anon-globals" {
- have_name_anon_globals_pass = true;
- }
- }
-
- // Instrumentation must be inserted before optimization,
- // otherwise LLVM may optimize some functions away which
- // breaks llvm-cov.
- //
- // This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp.
- if config.instrument_gcov {
- llvm::LLVMRustAddPass(mpm, find_pass("insert-gcov-profiling").unwrap());
- }
- if config.instrument_coverage {
- llvm::LLVMRustAddPass(mpm, find_pass("instrprof").unwrap());
- }
- if config.debug_info_for_profiling {
- llvm::LLVMRustAddPass(mpm, find_pass("add-discriminators").unwrap());
- }
-
- add_sanitizer_passes(config, &mut extra_passes);
-
- // Some options cause LLVM bitcode to be emitted, which uses ThinLTOBuffers, so we need
- // to make sure we run LLVM's NameAnonGlobals pass when emitting bitcode; otherwise
- // we'll get errors in LLVM.
- let using_thin_buffers = config.bitcode_needed();
- if !config.no_prepopulate_passes {
- llvm::LLVMAddAnalysisPasses(tm, fpm);
- llvm::LLVMAddAnalysisPasses(tm, mpm);
- let opt_level = to_llvm_opt_settings(opt_level).0;
- let prepare_for_thin_lto = cgcx.lto == Lto::Thin
- || cgcx.lto == Lto::ThinLocal
- || (cgcx.lto != Lto::Fat && cgcx.opts.cg.linker_plugin_lto.enabled());
- with_llvm_pmb(llmod, config, opt_level, prepare_for_thin_lto, &mut |b| {
- llvm::LLVMRustAddLastExtensionPasses(
- b,
- extra_passes.as_ptr(),
- extra_passes.len() as size_t,
- );
- llvm::LLVMRustPassManagerBuilderPopulateFunctionPassManager(b, fpm);
- llvm::LLVMRustPassManagerBuilderPopulateModulePassManager(b, mpm);
- });
-
- have_name_anon_globals_pass = have_name_anon_globals_pass || prepare_for_thin_lto;
- if using_thin_buffers && !prepare_for_thin_lto {
- llvm::LLVMRustAddPass(mpm, find_pass("name-anon-globals").unwrap());
- have_name_anon_globals_pass = true;
- }
- } else {
- // If we don't use the standard pipeline, directly populate the MPM
- // with the extra passes.
- for pass in extra_passes {
- llvm::LLVMRustAddPass(mpm, pass);
- }
- }
-
- if using_thin_buffers && !have_name_anon_globals_pass {
- // As described above, this will probably cause an error in LLVM
- if config.no_prepopulate_passes {
- diag_handler.err(
- "The current compilation is going to use thin LTO buffers \
- without running LLVM's NameAnonGlobals pass. \
- This will likely cause errors in LLVM. Consider adding \
- -C passes=name-anon-globals to the compiler command line.",
- );
- } else {
- bug!(
- "We are using thin LTO buffers without running the NameAnonGlobals pass. \
- This will likely cause errors in LLVM and should never happen."
- );
- }
- }
- }
-
- diag_handler.abort_if_errors();
-
- // Finally, run the actual optimization passes
- {
- let _timer = cgcx.prof.extra_verbose_generic_activity(
- "LLVM_module_optimize_function_passes",
- &*module.name,
- );
- llvm::LLVMRustRunFunctionPassManager(fpm, llmod);
- }
- {
- let _timer = cgcx.prof.extra_verbose_generic_activity(
- "LLVM_module_optimize_module_passes",
- &*module.name,
- );
- llvm::LLVMRunPassManager(mpm, llmod);
- }
-
- // Deallocate managers that we're now done with
- llvm::LLVMDisposePassManager(fpm);
- llvm::LLVMDisposePassManager(mpm);
+ let opt_stage = match cgcx.lto {
+ Lto::Fat => llvm::OptStage::PreLinkFatLTO,
+ Lto::Thin | Lto::ThinLocal => llvm::OptStage::PreLinkThinLTO,
+ _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
+ _ => llvm::OptStage::PreLinkNoLTO,
+ };
+ return llvm_optimize(cgcx, diag_handler, module, config, opt_level, opt_stage);
}
Ok(())
}
-unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static mut llvm::Pass>) {
- if config.sanitizer.contains(SanitizerSet::ADDRESS) {
- let recover = config.sanitizer_recover.contains(SanitizerSet::ADDRESS);
- passes.push(llvm::LLVMRustCreateAddressSanitizerFunctionPass(recover));
- passes.push(llvm::LLVMRustCreateModuleAddressSanitizerPass(recover));
- }
- if config.sanitizer.contains(SanitizerSet::MEMORY) {
- let track_origins = config.sanitizer_memory_track_origins as c_int;
- let recover = config.sanitizer_recover.contains(SanitizerSet::MEMORY);
- passes.push(llvm::LLVMRustCreateMemorySanitizerPass(track_origins, recover));
- }
- if config.sanitizer.contains(SanitizerSet::THREAD) {
- passes.push(llvm::LLVMRustCreateThreadSanitizerPass());
- }
- if config.sanitizer.contains(SanitizerSet::HWADDRESS) {
- let recover = config.sanitizer_recover.contains(SanitizerSet::HWADDRESS);
- passes.push(llvm::LLVMRustCreateHWAddressSanitizerPass(recover));
- }
-}
-
pub(crate) fn link(
cgcx: &CodegenContext<LlvmCodegenBackend>,
diag_handler: &Handler,
mut modules: Vec<ModuleCodegen<ModuleLlvm>>,
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
use super::lto::{Linker, ModuleBuffer};
- // Sort the modules by name to ensure to ensure deterministic behavior.
+ // Sort the modules by name to ensure deterministic behavior.
modules.sort_by(|a, b| a.name.cmp(&b.name));
let (first, elements) =
modules.split_first().expect("Bug! modules must contain at least one module.");
@@ -1072,72 +897,6 @@ unsafe fn embed_bitcode(
}
}
-pub unsafe fn with_llvm_pmb(
- llmod: &llvm::Module,
- config: &ModuleConfig,
- opt_level: llvm::CodeGenOptLevel,
- prepare_for_thin_lto: bool,
- f: &mut dyn FnMut(&llvm::PassManagerBuilder),
-) {
- use std::ptr;
-
- // Create the PassManagerBuilder for LLVM. We configure it with
- // reasonable defaults and prepare it to actually populate the pass
- // manager.
- let builder = llvm::LLVMRustPassManagerBuilderCreate();
- let opt_size = config.opt_size.map_or(llvm::CodeGenOptSizeNone, |x| to_llvm_opt_settings(x).1);
- let inline_threshold = config.inline_threshold;
- let pgo_gen_path = get_pgo_gen_path(config);
- let pgo_use_path = get_pgo_use_path(config);
- let pgo_sample_use_path = get_pgo_sample_use_path(config);
-
- llvm::LLVMRustConfigurePassManagerBuilder(
- builder,
- opt_level,
- config.merge_functions,
- config.vectorize_slp,
- config.vectorize_loop,
- prepare_for_thin_lto,
- pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
- pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
- pgo_sample_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
- opt_size as c_int,
- );
-
- llvm::LLVMRustAddBuilderLibraryInfo(builder, llmod, config.no_builtins);
-
- // Here we match what clang does (kinda). For O0 we only inline
- // always-inline functions (but don't add lifetime intrinsics), at O1 we
- // inline with lifetime intrinsics, and O2+ we add an inliner with a
- // thresholds copied from clang.
- match (opt_level, opt_size, inline_threshold) {
- (.., Some(t)) => {
- llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, t);
- }
- (llvm::CodeGenOptLevel::Aggressive, ..) => {
- llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 275);
- }
- (_, llvm::CodeGenOptSizeDefault, _) => {
- llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 75);
- }
- (_, llvm::CodeGenOptSizeAggressive, _) => {
- llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 25);
- }
- (llvm::CodeGenOptLevel::None, ..) => {
- llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
- }
- (llvm::CodeGenOptLevel::Less, ..) => {
- llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers);
- }
- (llvm::CodeGenOptLevel::Default, ..) => {
- llvm::LLVMRustPassManagerBuilderUseInlinerWithThreshold(builder, 225);
- }
- }
-
- f(builder);
- llvm::LLVMRustPassManagerBuilderDispose(builder);
-}
-
// Create a `__imp_<symbol> = &symbol` global for every public static `symbol`.
// This is required to satisfy `dllimport` references to static data in .rlibs
// when using MSVC linker. We do this only for data, as linker can fix up
diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs
index 86f92dc02..5b2bbdb4b 100644
--- a/compiler/rustc_codegen_llvm/src/base.rs
+++ b/compiler/rustc_codegen_llvm/src/base.rs
@@ -19,6 +19,8 @@ use crate::context::CodegenCx;
use crate::llvm;
use crate::value::Value;
+use cstr::cstr;
+
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::*;
@@ -107,11 +109,14 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
}
// Create the llvm.used and llvm.compiler.used variables.
- if !cx.used_statics().borrow().is_empty() {
- cx.create_used_variable()
+ if !cx.used_statics.borrow().is_empty() {
+ cx.create_used_variable_impl(cstr!("llvm.used"), &*cx.used_statics.borrow());
}
- if !cx.compiler_used_statics().borrow().is_empty() {
- cx.create_compiler_used_variable()
+ if !cx.compiler_used_statics.borrow().is_empty() {
+ cx.create_used_variable_impl(
+ cstr!("llvm.compiler.used"),
+ &*cx.compiler_used_statics.borrow(),
+ );
}
// Run replace-all-uses-with for statics that need it. This must
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 63b63c6a1..fca43a0d8 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1,14 +1,14 @@
+use crate::abi::FnAbiLlvmExt;
use crate::attributes;
use crate::common::Funclet;
use crate::context::CodegenCx;
-use crate::llvm::{self, BasicBlock, False};
-use crate::llvm::{AtomicOrdering, AtomicRmwBinOp, SynchronizationScope};
+use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use cstr::cstr;
use libc::{c_char, c_uint};
-use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, TypeKind};
+use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*;
@@ -215,6 +215,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn invoke(
&mut self,
llty: &'ll Type,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: &'ll Value,
args: &[&'ll Value],
then: &'ll BasicBlock,
@@ -227,7 +228,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.as_ref().map(|b| &*b.raw);
- unsafe {
+ let invoke = unsafe {
llvm::LLVMRustBuildInvoke(
self.llbuilder,
llty,
@@ -239,7 +240,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
bundle,
UNNAMED,
)
+ };
+ if let Some(fn_abi) = fn_abi {
+ fn_abi.apply_attrs_callsite(self, invoke);
}
+ invoke
}
fn unreachable(&mut self) {
@@ -406,20 +411,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
let mut bx = Builder::with_cx(self.cx);
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
- bx.dynamic_alloca(ty, align)
- }
-
- fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
unsafe {
- let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED);
+ let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
alloca
}
}
- fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, align: Align) -> &'ll Value {
+ fn byte_array_alloca(&mut self, len: &'ll Value, align: Align) -> &'ll Value {
unsafe {
- let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED);
+ let alloca =
+ llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, UNNAMED);
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
alloca
}
@@ -1042,15 +1044,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
) -> &'ll Value {
let weak = if weak { llvm::True } else { llvm::False };
unsafe {
- llvm::LLVMRustBuildAtomicCmpXchg(
+ let value = llvm::LLVMBuildAtomicCmpXchg(
self.llbuilder,
dst,
cmp,
src,
AtomicOrdering::from_generic(order),
AtomicOrdering::from_generic(failure_order),
- weak,
- )
+ llvm::False, // SingleThreaded
+ );
+ llvm::LLVMSetWeak(value, weak);
+ value
}
}
fn atomic_rmw(
@@ -1067,7 +1071,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
dst,
src,
AtomicOrdering::from_generic(order),
- False,
+ llvm::False, // SingleThreaded
)
}
}
@@ -1075,13 +1079,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn atomic_fence(
&mut self,
order: rustc_codegen_ssa::common::AtomicOrdering,
- scope: rustc_codegen_ssa::common::SynchronizationScope,
+ scope: SynchronizationScope,
) {
+ let single_threaded = match scope {
+ SynchronizationScope::SingleThread => llvm::True,
+ SynchronizationScope::CrossThread => llvm::False,
+ };
unsafe {
- llvm::LLVMRustBuildAtomicFence(
+ llvm::LLVMBuildFence(
self.llbuilder,
AtomicOrdering::from_generic(order),
- SynchronizationScope::from_generic(scope),
+ single_threaded,
+ UNNAMED,
);
}
}
@@ -1139,6 +1148,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn call(
&mut self,
llty: &'ll Type,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: &'ll Value,
args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>,
@@ -1149,7 +1159,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
let bundle = funclet.map(|funclet| funclet.bundle());
let bundle = bundle.as_ref().map(|b| &*b.raw);
- unsafe {
+ let call = unsafe {
llvm::LLVMRustBuildCall(
self.llbuilder,
llty,
@@ -1158,7 +1168,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
args.len() as c_uint,
bundle,
)
+ };
+ if let Some(fn_abi) = fn_abi {
+ fn_abi.apply_attrs_callsite(self, call);
}
+ call
}
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
@@ -1391,7 +1405,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
pub(crate) fn call_intrinsic(&mut self, intrinsic: &str, args: &[&'ll Value]) -> &'ll Value {
let (ty, f) = self.cx.get_intrinsic(intrinsic);
- self.call(ty, f, args, None)
+ self.call(ty, None, f, args, None)
}
fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
@@ -1453,7 +1467,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width)
};
let f = self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
- self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None)
+ self.call(self.type_func(&[src_ty], dest_ty), None, f, &[val], None)
}
pub(crate) fn landing_pad(
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index b83c1e8f0..6f0d1b7ce 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -179,7 +179,8 @@ pub fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) ->
// MinGW: For backward compatibility we rely on the linker to decide whether it
// should use dllimport for functions.
if cx.use_dll_storage_attrs
- && tcx.is_dllimport_foreign_item(instance_def_id)
+ && let Some(library) = tcx.native_library(instance_def_id)
+ && library.kind.is_dllimport()
&& !matches!(tcx.sess.target.env.as_ref(), "gnu" | "uclibc")
{
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index a559f7f3d..dd3c43ba5 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -332,7 +332,10 @@ impl<'ll> CodegenCx<'ll, '_> {
}
}
- if self.use_dll_storage_attrs && self.tcx.is_dllimport_foreign_item(def_id) {
+ if self.use_dll_storage_attrs
+ && let Some(library) = self.tcx.native_library(def_id)
+ && library.kind.is_dllimport()
+ {
// For foreign (native) libs we know the exact storage type to use.
unsafe {
llvm::LLVMSetDLLStorageClass(g, llvm::DLLStorageClass::DllImport);
@@ -552,7 +555,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
// `#[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,
- // that check happens when assigning the `CodegenFnAttrFlags` in `rustc_typeck`,
+ // 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 67ffc7cb9..79ddfd884 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -154,6 +154,11 @@ pub unsafe fn create_module<'ll>(
target_data_layout = target_data_layout.replace("-p10:8:8-p20:8:8", "");
}
}
+ if llvm_version < (16, 0, 0) {
+ if sess.target.arch == "s390x" {
+ target_data_layout = target_data_layout.replace("-v128:64", "");
+ }
+ }
// Ensure the data-layout values hardcoded remain the defaults.
if sess.target.is_builtin {
@@ -453,7 +458,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
self.coverage_cx.as_ref()
}
- fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
+ pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) {
let section = cstr!("llvm.metadata");
let array = self.const_array(self.type_ptr_to(self.type_i8()), values);
@@ -551,14 +556,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
self.codegen_unit
}
- fn used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
- &self.used_statics
- }
-
- fn compiler_used_statics(&self) -> &RefCell<Vec<&'ll Value>> {
- &self.compiler_used_statics
- }
-
fn set_frame_pointer_type(&self, llfn: &'ll Value) {
if let Some(attr) = attributes::frame_pointer_type_attr(self) {
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &[attr]);
@@ -572,17 +569,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &attrs);
}
- fn create_used_variable(&self) {
- self.create_used_variable_impl(cstr!("llvm.used"), &*self.used_statics.borrow());
- }
-
- fn create_compiler_used_variable(&self) {
- self.create_used_variable_impl(
- cstr!("llvm.compiler.used"),
- &*self.compiler_used_statics.borrow(),
- );
- }
-
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
if self.get_declared_value("main").is_none() {
Some(self.declare_cfn("main", llvm::UnnamedAddr::Global, fn_type))
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index 0d1df6fb1..433f04320 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -129,7 +129,7 @@ impl CoverageMapGenerator {
// 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 the relative paths
+ // compilation directory can be combined with the relative paths
// to get absolute paths, if needed.
let working_dir = tcx
.sess
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index 0f663a267..f79ef1172 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -32,6 +32,7 @@ fn declare_raw_fn<'ll>(
name: &str,
callconv: llvm::CallConv,
unnamed: llvm::UnnamedAddr,
+ visibility: llvm::Visibility,
ty: &'ll Type,
) -> &'ll Value {
debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
@@ -41,6 +42,7 @@ fn declare_raw_fn<'ll>(
llvm::SetFunctionCallConv(llfn, callconv);
llvm::SetUnnamedAddress(llfn, unnamed);
+ llvm::set_visibility(llfn, visibility);
let mut attrs = SmallVec::<[_; 4]>::new();
@@ -78,7 +80,14 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
unnamed: llvm::UnnamedAddr,
fn_type: &'ll Type,
) -> &'ll Value {
- declare_raw_fn(self, name, llvm::CCallConv, unnamed, fn_type)
+ // Declare C ABI functions with the visibility used by C by default.
+ let visibility = if self.tcx.sess.target.default_hidden_visibility {
+ llvm::Visibility::Hidden
+ } else {
+ llvm::Visibility::Default
+ };
+
+ declare_raw_fn(self, name, llvm::CCallConv, unnamed, visibility, fn_type)
}
/// Declare a Rust function.
@@ -95,6 +104,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
name,
fn_abi.llvm_cconv(),
llvm::UnnamedAddr::Global,
+ llvm::Visibility::Default,
fn_abi.llvm_type(self),
);
fn_abi.apply_attrs_llfn(self, llfn);
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index a640de42a..825011941 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -108,6 +108,7 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
let (simple_ty, simple_fn) = simple.unwrap();
self.call(
simple_ty,
+ None,
simple_fn,
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
None,
@@ -435,7 +436,7 @@ fn try_intrinsic<'ll>(
) {
if bx.sess().panic_strategy() == PanicStrategy::Abort {
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
- bx.call(try_func_ty, try_func, &[data], None);
+ bx.call(try_func_ty, None, try_func, &[data], None);
// Return 0 unconditionally from the intrinsic call;
// we can never unwind.
let ret_align = bx.tcx().data_layout.i32_align.abi;
@@ -534,7 +535,7 @@ fn codegen_msvc_try<'ll>(
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
let slot = bx.alloca(bx.type_i8p(), ptr_align);
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
- bx.invoke(try_func_ty, try_func, &[data], normal, catchswitch, None);
+ bx.invoke(try_func_ty, None, try_func, &[data], normal, catchswitch, None);
bx.switch_to_block(normal);
bx.ret(bx.const_i32(0));
@@ -578,7 +579,7 @@ fn codegen_msvc_try<'ll>(
let funclet = bx.catch_pad(cs, &[tydesc, flags, slot]);
let ptr = bx.load(bx.type_i8p(), slot, ptr_align);
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
- bx.call(catch_ty, catch_func, &[data, ptr], Some(&funclet));
+ bx.call(catch_ty, None, catch_func, &[data, ptr], Some(&funclet));
bx.catch_ret(&funclet, caught);
// The flag value of 64 indicates a "catch-all".
@@ -586,7 +587,7 @@ fn codegen_msvc_try<'ll>(
let flags = bx.const_i32(64);
let null = bx.const_null(bx.type_i8p());
let funclet = bx.catch_pad(cs, &[null, flags, null]);
- bx.call(catch_ty, catch_func, &[data, null], Some(&funclet));
+ bx.call(catch_ty, None, catch_func, &[data, null], Some(&funclet));
bx.catch_ret(&funclet, caught);
bx.switch_to_block(caught);
@@ -595,7 +596,7 @@ fn codegen_msvc_try<'ll>(
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
- let ret = bx.call(llty, llfn, &[try_func, data, catch_func], None);
+ let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@@ -638,7 +639,7 @@ fn codegen_gnu_try<'ll>(
let data = llvm::get_param(bx.llfn(), 1);
let catch_func = llvm::get_param(bx.llfn(), 2);
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
- bx.invoke(try_func_ty, try_func, &[data], then, catch, None);
+ bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
bx.switch_to_block(then);
bx.ret(bx.const_i32(0));
@@ -656,13 +657,13 @@ fn codegen_gnu_try<'ll>(
bx.add_clause(vals, tydesc);
let ptr = bx.extract_value(vals, 0);
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
- bx.call(catch_ty, catch_func, &[data, ptr], None);
+ bx.call(catch_ty, None, catch_func, &[data, ptr], None);
bx.ret(bx.const_i32(1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
- let ret = bx.call(llty, llfn, &[try_func, data, catch_func], None);
+ let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@@ -702,7 +703,7 @@ fn codegen_emcc_try<'ll>(
let data = llvm::get_param(bx.llfn(), 1);
let catch_func = llvm::get_param(bx.llfn(), 2);
let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
- bx.invoke(try_func_ty, try_func, &[data], then, catch, None);
+ bx.invoke(try_func_ty, None, try_func, &[data], then, catch, None);
bx.switch_to_block(then);
bx.ret(bx.const_i32(0));
@@ -741,13 +742,13 @@ fn codegen_emcc_try<'ll>(
let catch_data = bx.bitcast(catch_data, bx.type_i8p());
let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void());
- bx.call(catch_ty, catch_func, &[data, catch_data], None);
+ bx.call(catch_ty, None, catch_func, &[data, catch_data], None);
bx.ret(bx.const_i32(1));
});
// Note that no invoke is used here because by definition this function
// can't panic (that's what it's catching).
- let ret = bx.call(llty, llfn, &[try_func, data, catch_func], None);
+ let ret = bx.call(llty, None, llfn, &[try_func, data, catch_func], None);
let i32_align = bx.tcx().data_layout.i32_align.abi;
bx.store(ret, dest, i32_align);
}
@@ -1217,8 +1218,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
};
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str);
let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty);
- let c =
- bx.call(fn_ty, f, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None);
+ let c = bx.call(
+ fn_ty,
+ None,
+ f,
+ &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
+ None,
+ );
Ok(c)
}
@@ -1417,8 +1423,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
llvm_elem_vec_ty,
);
let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
- let v =
- bx.call(fn_ty, f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None);
+ let v = bx.call(
+ fn_ty,
+ None,
+ f,
+ &[args[1].immediate(), alignment, mask, args[0].immediate()],
+ None,
+ );
return Ok(v);
}
@@ -1543,8 +1554,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
let fn_ty =
bx.type_func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t);
let f = bx.declare_cfn(&llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
- let v =
- bx.call(fn_ty, f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None);
+ let v = bx.call(
+ fn_ty,
+ None,
+ f,
+ &[args[0].immediate(), args[1].immediate(), alignment, mask],
+ None,
+ );
return Ok(v);
}
@@ -1992,7 +2008,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
let fn_ty = bx.type_func(&[vec_ty, vec_ty], vec_ty);
let f = bx.declare_cfn(llvm_intrinsic, llvm::UnnamedAddr::No, fn_ty);
- let v = bx.call(fn_ty, f, &[lhs, rhs], None);
+ let v = bx.call(fn_ty, None, f, &[lhs, rhs], None);
return Ok(v);
}
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 42c65e04e..89c7e51d0 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -7,7 +7,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(hash_raw_entry)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(extern_types)]
#![feature(once_cell)]
#![feature(iter_intersperse)]
@@ -132,12 +131,6 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
) -> TargetMachineFactoryFn<Self> {
back::write::target_machine_factory(sess, optlvl, target_features)
}
- fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
- llvm_util::target_cpu(sess)
- }
- fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> {
- llvm_util::tune_cpu(sess)
- }
fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T>
where
@@ -171,7 +164,6 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
impl WriteBackendMethods for LlvmCodegenBackend {
type Module = ModuleLlvm;
type ModuleBuffer = back::lto::ModuleBuffer;
- type Context = llvm::Context;
type TargetMachine = &'static mut llvm::TargetMachine;
type ThinData = back::lto::ThinData;
type ThinBuffer = back::lto::ThinBuffer;
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index ce27dc5a5..42cb694c0 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -400,27 +400,6 @@ impl AtomicOrdering {
}
}
-/// LLVMRustSynchronizationScope
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum SynchronizationScope {
- SingleThread,
- CrossThread,
-}
-
-impl SynchronizationScope {
- pub fn from_generic(sc: rustc_codegen_ssa::common::SynchronizationScope) -> Self {
- match sc {
- rustc_codegen_ssa::common::SynchronizationScope::SingleThread => {
- SynchronizationScope::SingleThread
- }
- rustc_codegen_ssa::common::SynchronizationScope::CrossThread => {
- SynchronizationScope::CrossThread
- }
- }
- }
-}
-
/// LLVMRustFileType
#[derive(Copy, Clone)]
#[repr(C)]
@@ -1782,16 +1761,18 @@ extern "C" {
Order: AtomicOrdering,
) -> &'a Value;
- pub fn LLVMRustBuildAtomicCmpXchg<'a>(
+ pub fn LLVMBuildAtomicCmpXchg<'a>(
B: &Builder<'a>,
LHS: &'a Value,
CMP: &'a Value,
RHS: &'a Value,
Order: AtomicOrdering,
FailureOrder: AtomicOrdering,
- Weak: Bool,
+ SingleThreaded: Bool,
) -> &'a Value;
+ pub fn LLVMSetWeak(CmpXchgInst: &Value, IsWeak: Bool);
+
pub fn LLVMBuildAtomicRMW<'a>(
B: &Builder<'a>,
Op: AtomicRmwBinOp,
@@ -1801,27 +1782,19 @@ extern "C" {
SingleThreaded: Bool,
) -> &'a Value;
- pub fn LLVMRustBuildAtomicFence(
- B: &Builder<'_>,
+ pub fn LLVMBuildFence<'a>(
+ B: &Builder<'a>,
Order: AtomicOrdering,
- Scope: SynchronizationScope,
- );
+ SingleThreaded: Bool,
+ Name: *const c_char,
+ ) -> &'a Value;
/// Writes a module to the specified path. Returns 0 on success.
pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int;
- /// Creates a pass manager.
+ /// Creates a legacy pass manager -- only used for final codegen.
pub fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>;
- /// Creates a function-by-function pass manager
- pub fn LLVMCreateFunctionPassManagerForModule(M: &Module) -> &mut PassManager<'_>;
-
- /// Disposes a pass manager.
- pub fn LLVMDisposePassManager<'a>(PM: &'a mut PassManager<'a>);
-
- /// Runs a pass manager on a module.
- pub fn LLVMRunPassManager<'a>(PM: &PassManager<'a>, M: &'a Module) -> Bool;
-
pub fn LLVMInitializePasses();
pub fn LLVMTimeTraceProfilerInitialize();
@@ -1832,32 +1805,6 @@ extern "C" {
pub fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>);
- pub fn LLVMRustPassManagerBuilderCreate() -> &'static mut PassManagerBuilder;
- pub fn LLVMRustPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder);
- pub fn LLVMRustPassManagerBuilderUseInlinerWithThreshold(
- PMB: &PassManagerBuilder,
- threshold: c_uint,
- );
- pub fn LLVMRustPassManagerBuilderPopulateModulePassManager(
- PMB: &PassManagerBuilder,
- PM: &PassManager<'_>,
- );
-
- pub fn LLVMRustPassManagerBuilderPopulateFunctionPassManager(
- PMB: &PassManagerBuilder,
- PM: &PassManager<'_>,
- );
- pub fn LLVMRustPassManagerBuilderPopulateLTOPassManager(
- PMB: &PassManagerBuilder,
- PM: &PassManager<'_>,
- Internalize: Bool,
- RunInliner: Bool,
- );
- pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
- PMB: &PassManagerBuilder,
- PM: &PassManager<'_>,
- );
-
pub fn LLVMGetHostCPUFeatures() -> *mut c_char;
pub fn LLVMDisposeMessage(message: *mut c_char);
@@ -2262,22 +2209,6 @@ extern "C" {
pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>;
- pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>;
- pub fn LLVMRustCreateAddressSanitizerFunctionPass(Recover: bool) -> &'static mut Pass;
- pub fn LLVMRustCreateModuleAddressSanitizerPass(Recover: bool) -> &'static mut Pass;
- pub fn LLVMRustCreateMemorySanitizerPass(
- TrackOrigins: c_int,
- Recover: bool,
- ) -> &'static mut Pass;
- pub fn LLVMRustCreateThreadSanitizerPass() -> &'static mut Pass;
- pub fn LLVMRustCreateHWAddressSanitizerPass(Recover: bool) -> &'static mut Pass;
- pub fn LLVMRustAddPass(PM: &PassManager<'_>, Pass: &'static mut Pass);
- pub fn LLVMRustAddLastExtensionPasses(
- PMB: &PassManagerBuilder,
- Passes: *const &'static mut Pass,
- NumPasses: size_t,
- );
-
pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool;
pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine);
@@ -2311,29 +2242,11 @@ extern "C" {
SplitDwarfFile: *const c_char,
) -> Option<&'static mut TargetMachine>;
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
- pub fn LLVMRustAddBuilderLibraryInfo<'a>(
- PMB: &'a PassManagerBuilder,
- M: &'a Module,
- DisableSimplifyLibCalls: bool,
- );
- pub fn LLVMRustConfigurePassManagerBuilder(
- PMB: &PassManagerBuilder,
- OptLevel: CodeGenOptLevel,
- MergeFunctions: bool,
- SLPVectorize: bool,
- LoopVectorize: bool,
- PrepareForThinLTO: bool,
- PGOGenPath: *const c_char,
- PGOUsePath: *const c_char,
- PGOSampleUsePath: *const c_char,
- SizeLevel: c_int,
- );
pub fn LLVMRustAddLibraryInfo<'a>(
PM: &PassManager<'a>,
M: &'a Module,
DisableSimplifyLibCalls: bool,
);
- pub fn LLVMRustRunFunctionPassManager<'a>(PM: &PassManager<'a>, M: &'a Module);
pub fn LLVMRustWriteOutputFile<'a>(
T: &'a TargetMachine,
PM: &PassManager<'a>,
@@ -2342,7 +2255,7 @@ extern "C" {
DwoOutput: *const c_char,
FileType: FileType,
) -> LLVMRustResult;
- pub fn LLVMRustOptimizeWithNewPassManager<'a>(
+ pub fn LLVMRustOptimize<'a>(
M: &'a Module,
TM: &'a TargetMachine,
OptLevel: PassBuilderOptLevel,
@@ -2380,7 +2293,6 @@ extern "C" {
pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char);
pub fn LLVMRustPrintPasses();
pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char);
- pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool);
pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t);
pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 60707a1c3..2fd58567c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -1,7 +1,6 @@
use crate::back::write::create_informational_target_machine;
-use crate::{llvm, llvm_util};
+use crate::llvm;
use libc::c_int;
-use libloading::Library;
use rustc_codegen_ssa::target_features::{
supported_target_features, tied_target_features, RUSTC_SPECIFIC_FEATURES,
};
@@ -16,7 +15,6 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy};
use smallvec::{smallvec, SmallVec};
use std::ffi::{CStr, CString};
-use std::mem;
use std::path::Path;
use std::ptr;
use std::slice;
@@ -120,22 +118,6 @@ unsafe fn configure_llvm(sess: &Session) {
llvm::LLVMInitializePasses();
- // Use the legacy plugin registration if we don't use the new pass manager
- if !should_use_new_llvm_pass_manager(
- &sess.opts.unstable_opts.new_llvm_pass_manager,
- &sess.target.arch,
- ) {
- // Register LLVM plugins by loading them into the compiler process.
- for plugin in &sess.opts.unstable_opts.llvm_plugins {
- let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e));
- debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin);
-
- // Intentionally leak the dynamic library. We can't ever unload it
- // since the library can make things that will live arbitrarily long.
- mem::forget(lib);
- }
- }
-
rustc_llvm::initialize_available_targets();
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
@@ -539,19 +521,3 @@ pub fn tune_cpu(sess: &Session) -> Option<&str> {
let name = sess.opts.unstable_opts.tune_cpu.as_ref()?;
Some(handle_native(name))
}
-
-pub(crate) fn should_use_new_llvm_pass_manager(user_opt: &Option<bool>, target_arch: &str) -> bool {
- // The new pass manager is enabled by default for LLVM >= 13.
- // This matches Clang, which also enables it since Clang 13.
-
- // Since LLVM 15, the legacy pass manager is no longer supported.
- if llvm_util::get_version() >= (15, 0, 0) {
- return true;
- }
-
- // There are some perf issues with the new pass manager when targeting
- // s390x with LLVM 13, so enable the new pass manager only with LLVM 14.
- // See https://github.com/rust-lang/rust/issues/89609.
- let min_version = if target_arch == "s390x" { 14 } else { 13 };
- user_opt.unwrap_or_else(|| llvm_util::get_version() >= (min_version, 0, 0))
-}
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 6cce95427..0dc0dee86 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library;
use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
-use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
+use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
use rustc_session::cstore::DllImport;
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
@@ -23,20 +23,23 @@ use rustc_session::{filesearch, Session};
use rustc_span::symbol::Symbol;
use rustc_span::DebuggerVisualizerFile;
use rustc_target::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
-use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
-use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
+use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy};
+use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo, Target};
use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
use super::command::Command;
use super::linker::{self, Linker};
use super::metadata::{create_rmeta_file, MetadataPosition};
use super::rpath::{self, RPathConfig};
-use crate::{looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib};
+use crate::{
+ errors, looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
+};
use cc::windows_registry;
use regex::Regex;
use tempfile::Builder as TempFileBuilder;
+use itertools::Itertools;
use std::borrow::Borrow;
use std::cell::OnceCell;
use std::collections::BTreeSet;
@@ -93,7 +96,7 @@ pub fn link_binary<'a>(
let tmpdir = TempFileBuilder::new()
.prefix("rustc")
.tempdir()
- .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
+ .unwrap_or_else(|error| sess.emit_fatal(errors::CreateTempDir { error }));
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
let out_filename = out_filename(
sess,
@@ -206,11 +209,29 @@ pub fn link_binary<'a>(
}
pub fn each_linked_rlib(
+ sess: &Session,
info: &CrateInfo,
f: &mut dyn FnMut(CrateNum, &Path),
-) -> Result<(), String> {
+) -> Result<(), errors::LinkRlibError> {
let crates = info.used_crates.iter();
let mut fmts = None;
+
+ let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin);
+ if lto_active {
+ for combination in info.dependency_formats.iter().combinations(2) {
+ let (ty1, list1) = &combination[0];
+ let (ty2, list2) = &combination[1];
+ if list1 != list2 {
+ return Err(errors::LinkRlibError::IncompatibleDependencyFormats {
+ ty1: format!("{ty1:?}"),
+ ty2: format!("{ty2:?}"),
+ list1: format!("{list1:?}"),
+ list2: format!("{list2:?}"),
+ });
+ }
+ }
+ }
+
for (ty, list) in info.dependency_formats.iter() {
match ty {
CrateType::Executable
@@ -220,30 +241,31 @@ pub fn each_linked_rlib(
fmts = Some(list);
break;
}
+ CrateType::Dylib if lto_active => {
+ fmts = Some(list);
+ break;
+ }
_ => {}
}
}
let Some(fmts) = fmts else {
- return Err("could not find formats for rlibs".to_string());
+ return Err(errors::LinkRlibError::MissingFormat);
};
for &cnum in crates {
match fmts.get(cnum.as_usize() - 1) {
Some(&Linkage::NotLinked | &Linkage::IncludedFromDylib) => continue,
Some(_) => {}
- None => return Err("could not find formats for rlibs".to_string()),
+ None => return Err(errors::LinkRlibError::MissingFormat),
}
- let name = info.crate_name[&cnum];
+ let crate_name = info.crate_name[&cnum];
let used_crate_source = &info.used_crate_source[&cnum];
if let Some((path, _)) = &used_crate_source.rlib {
f(cnum, &path);
} else {
if used_crate_source.rmeta.is_some() {
- return Err(format!(
- "could not find rlib for: `{}`, found rmeta (metadata) file",
- name
- ));
+ return Err(errors::LinkRlibError::OnlyRmetaFound { crate_name });
} else {
- return Err(format!("could not find rlib for: `{}`", name));
+ return Err(errors::LinkRlibError::NotFound { crate_name });
}
}
}
@@ -340,10 +362,7 @@ fn link_rlib<'a>(
// -whole-archive and it isn't clear how we can currently handle such a
// situation correctly.
// See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897
- sess.err(
- "the linking modifiers `+bundle` and `+whole-archive` are not compatible \
- with each other when generating rlibs",
- );
+ sess.emit_err(errors::IncompatibleLinkingModifiers);
}
NativeLibKind::Static { bundle: None | Some(true), .. } => {}
NativeLibKind::Static { bundle: Some(false), .. }
@@ -365,12 +384,8 @@ fn link_rlib<'a>(
));
continue;
}
- ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|e| {
- sess.fatal(&format!(
- "failed to add native library {}: {}",
- location.to_string_lossy(),
- e
- ));
+ ab.add_archive(&location, Box::new(|_| false)).unwrap_or_else(|error| {
+ sess.emit_fatal(errors::AddNativeLibrary { library_path: location, error });
});
}
}
@@ -386,8 +401,8 @@ fn link_rlib<'a>(
true,
);
- ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|e| {
- sess.fatal(&format!("failed to add native library {}: {}", output_path.display(), e));
+ ab.add_archive(&output_path, Box::new(|_| false)).unwrap_or_else(|error| {
+ sess.emit_fatal(errors::AddNativeLibrary { library_path: output_path, error });
});
}
@@ -452,14 +467,11 @@ fn collate_raw_dylibs<'a, 'b>(
// FIXME: when we add support for ordinals, figure out if we need to do anything
// if we have two DllImport values with the same name but different ordinals.
if import.calling_convention != old_import.calling_convention {
- sess.span_err(
- import.span,
- &format!(
- "multiple declarations of external function `{}` from \
- library `{}` have different calling conventions",
- import.name, name,
- ),
- );
+ sess.emit_err(errors::MultipleExternalFuncDecl {
+ span: import.span,
+ function: import.name,
+ library_name: &name,
+ });
}
}
}
@@ -502,7 +514,7 @@ fn link_staticlib<'a>(
)?;
let mut all_native_libs = vec![];
- let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| {
+ let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| {
let name = codegen_results.crate_info.crate_name[&cnum];
let native_libs = &codegen_results.crate_info.native_libraries[&cnum];
@@ -561,7 +573,7 @@ fn link_staticlib<'a>(
all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned());
});
if let Err(e) = res {
- sess.fatal(&e);
+ sess.emit_fatal(e);
}
ab.build(out_filename);
@@ -674,9 +686,7 @@ fn link_dwarf_object<'a>(
}) {
Ok(()) => {}
Err(e) => {
- sess.struct_err("linking dwarf objects with thorin failed")
- .note(&format!("{:?}", e))
- .emit();
+ sess.emit_err(errors::ThorinErrorWrapper(e));
sess.abort_if_errors();
}
}
@@ -749,8 +759,7 @@ fn link_natively<'a>(
// then it should not default to linking executables as pie. Different
// versions of gcc seem to use different quotes in the error message so
// don't check for them.
- if sess.target.linker_is_gnu
- && flavor != LinkerFlavor::Ld
+ if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
&& unknown_arg_regex.is_match(&out)
&& out.contains("-no-pie")
&& cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie")
@@ -768,8 +777,7 @@ fn link_natively<'a>(
// Detect '-static-pie' used with an older version of gcc or clang not supporting it.
// Fallback from '-static-pie' to '-static' in that case.
- if sess.target.linker_is_gnu
- && flavor != LinkerFlavor::Ld
+ if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
&& unknown_arg_regex.is_match(&out)
&& (out.contains("-static-pie") || out.contains("--no-dynamic-linker"))
&& cmd.get_args().iter().any(|e| e.to_string_lossy() == "-static-pie")
@@ -882,29 +890,20 @@ fn link_natively<'a>(
let mut output = prog.stderr.clone();
output.extend_from_slice(&prog.stdout);
let escaped_output = escape_string(&output);
- let mut err = sess.struct_err(&format!(
- "linking with `{}` failed: {}",
- linker_path.display(),
- prog.status
- ));
- err.note(&format!("{:?}", &cmd)).note(&escaped_output);
- if escaped_output.contains("undefined reference to") {
- err.help(
- "some `extern` functions couldn't be found; some native libraries may \
- need to be installed or have their path specified",
- );
- err.note("use the `-l` flag to specify native libraries to link");
- err.note("use the `cargo:rustc-link-lib` directive to specify the native \
- libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)");
- }
- err.emit();
-
+ // FIXME: Add UI tests for this error.
+ let err = errors::LinkingFailed {
+ linker_path: &linker_path,
+ exit_status: prog.status,
+ command: &cmd,
+ escaped_output: &escaped_output,
+ };
+ sess.diagnostic().emit_err(err);
// If MSVC's `link.exe` was expected but the return code
// is not a Microsoft LNK error then suggest a way to fix or
// install the Visual Studio build tools.
if let Some(code) = prog.status.code() {
if sess.target.is_like_msvc
- && flavor == LinkerFlavor::Msvc
+ && flavor == LinkerFlavor::Msvc(Lld::No)
// Respect the command line override
&& sess.opts.cg.linker.is_none()
// Match exactly "link.exe"
@@ -980,9 +979,10 @@ fn link_natively<'a>(
but `link.exe` was not found",
);
sess.note_without_error(
- "please ensure that VS 2013, VS 2015, VS 2017, VS 2019 or VS 2022 \
- was installed with the Visual C++ option",
+ "please ensure that Visual Studio 2017 or later, or Build Tools \
+ for Visual Studio were installed with the Visual C++ option.",
);
+ sess.note_without_error("VS Code is a different product, and is not sufficient.");
}
sess.abort_if_errors();
}
@@ -1035,16 +1035,36 @@ fn link_natively<'a>(
if sess.target.is_like_osx {
match (strip, crate_type) {
- (Strip::Debuginfo, _) => strip_symbols_in_osx(sess, &out_filename, Some("-S")),
+ (Strip::Debuginfo, _) => {
+ strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-S"))
+ }
// Per the manpage, `-x` is the maximum safe strip level for dynamic libraries. (#93988)
(Strip::Symbols, CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro) => {
- strip_symbols_in_osx(sess, &out_filename, Some("-x"))
+ strip_symbols_with_external_utility(sess, "strip", &out_filename, Some("-x"))
+ }
+ (Strip::Symbols, _) => {
+ strip_symbols_with_external_utility(sess, "strip", &out_filename, None)
}
- (Strip::Symbols, _) => strip_symbols_in_osx(sess, &out_filename, None),
(Strip::None, _) => {}
}
}
+ if sess.target.os == "illumos" {
+ // Many illumos systems will have both the native 'strip' utility and
+ // the GNU one. Use the native version explicitly and do not rely on
+ // what's in the path.
+ let stripcmd = "/usr/bin/strip";
+ match strip {
+ // Always preserve the symbol table (-x).
+ Strip::Debuginfo => {
+ strip_symbols_with_external_utility(sess, stripcmd, &out_filename, Some("-x"))
+ }
+ // Strip::Symbols is handled via the --strip-all linker option.
+ Strip::Symbols => {}
+ Strip::None => {}
+ }
+ }
+
Ok(())
}
@@ -1056,8 +1076,13 @@ fn strip_value(sess: &Session) -> Strip {
}
}
-fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Option<&str>) {
- let mut cmd = Command::new("strip");
+fn strip_symbols_with_external_utility<'a>(
+ sess: &'a Session,
+ util: &str,
+ out_filename: &Path,
+ option: Option<&str>,
+) {
+ let mut cmd = Command::new(util);
if let Some(option) = option {
cmd.arg(option);
}
@@ -1068,14 +1093,14 @@ fn strip_symbols_in_osx<'a>(sess: &'a Session, out_filename: &Path, option: Opti
let mut output = prog.stderr.clone();
output.extend_from_slice(&prog.stdout);
sess.struct_warn(&format!(
- "stripping debug info with `strip` failed: {}",
- prog.status
+ "stripping debug info with `{}` failed: {}",
+ util, prog.status
))
.note(&escape_string(&output))
.emit();
}
}
- Err(e) => sess.fatal(&format!("unable to run `strip`: {}", e)),
+ Err(e) => sess.fatal(&format!("unable to run `{}`: {}", util, e)),
}
}
@@ -1091,11 +1116,12 @@ fn add_sanitizer_libraries(sess: &Session, crate_type: CrateType, linker: &mut d
// both executables and dynamic shared objects. Everywhere else the runtimes
// are currently distributed as static libraries which should be linked to
// executables only.
- let needs_runtime = match crate_type {
- CrateType::Executable => true,
- CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx,
- CrateType::Rlib | CrateType::Staticlib => false,
- };
+ let needs_runtime = !sess.target.is_like_android
+ && match crate_type {
+ CrateType::Executable => true,
+ CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => sess.target.is_like_osx,
+ CrateType::Rlib | CrateType::Staticlib => false,
+ };
if !needs_runtime {
return;
@@ -1187,7 +1213,10 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
// only the linker flavor is known; use the default linker for the selected flavor
(None, Some(flavor)) => Some((
PathBuf::from(match flavor {
- LinkerFlavor::Gcc => {
+ LinkerFlavor::Gnu(Cc::Yes, _)
+ | LinkerFlavor::Darwin(Cc::Yes, _)
+ | LinkerFlavor::WasmLld(Cc::Yes)
+ | LinkerFlavor::Unix(Cc::Yes) => {
if cfg!(any(target_os = "solaris", target_os = "illumos")) {
// On historical Solaris systems, "cc" may have
// been Sun Studio, which is not flag-compatible
@@ -1200,9 +1229,14 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
"cc"
}
}
- LinkerFlavor::Ld => "ld",
- LinkerFlavor::Lld(_) => "lld",
- LinkerFlavor::Msvc => "link.exe",
+ LinkerFlavor::Gnu(_, Lld::Yes)
+ | LinkerFlavor::Darwin(_, Lld::Yes)
+ | LinkerFlavor::WasmLld(..)
+ | LinkerFlavor::Msvc(Lld::Yes) => "lld",
+ LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
+ "ld"
+ }
+ LinkerFlavor::Msvc(..) => "link.exe",
LinkerFlavor::EmCc => {
if cfg!(windows) {
"emcc.bat"
@@ -1227,15 +1261,20 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
|| stem == "clang"
|| stem.ends_with("-clang")
{
- LinkerFlavor::Gcc
+ LinkerFlavor::from_cli(LinkerFlavorCli::Gcc, &sess.target)
} else if stem == "wasm-ld" || stem.ends_with("-wasm-ld") {
- LinkerFlavor::Lld(LldFlavor::Wasm)
- } else if stem == "ld" || stem == "ld.lld" || stem.ends_with("-ld") {
- LinkerFlavor::Ld
- } else if stem == "link" || stem == "lld-link" {
- LinkerFlavor::Msvc
+ LinkerFlavor::WasmLld(Cc::No)
+ } else if stem == "ld" || stem.ends_with("-ld") {
+ LinkerFlavor::from_cli(LinkerFlavorCli::Ld, &sess.target)
+ } else if stem == "ld.lld" {
+ LinkerFlavor::Gnu(Cc::No, Lld::Yes)
+ } else if stem == "link" {
+ LinkerFlavor::Msvc(Lld::No)
+ } else if stem == "lld-link" {
+ LinkerFlavor::Msvc(Lld::Yes)
} else if stem == "lld" || stem == "rust-lld" {
- LinkerFlavor::Lld(sess.target.lld_flavor)
+ let lld_flavor = sess.target.linker_flavor.lld_flavor();
+ LinkerFlavor::from_cli(LinkerFlavorCli::Lld(lld_flavor), &sess.target)
} else {
// fall back to the value in the target spec
sess.target.linker_flavor
@@ -1249,7 +1288,8 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
// linker and linker flavor specified via command line have precedence over what the target
// specification specifies
- let linker_flavor = sess.opts.cg.linker_flavor.map(LinkerFlavor::from_cli);
+ let linker_flavor =
+ sess.opts.cg.linker_flavor.map(|flavor| LinkerFlavor::from_cli(flavor, &sess.target));
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
return ret;
}
@@ -1320,7 +1360,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
let verbatim = lib.verbatim.unwrap_or(false);
if sess.target.is_like_msvc {
Some(format!("{}{}", name, if verbatim { "" } else { ".lib" }))
- } else if sess.target.linker_is_gnu {
+ } else if sess.target.linker_flavor.is_gnu() {
Some(format!("-l{}{}", if verbatim { ":" } else { "" }, name))
} else {
Some(format!("-l{}", name))
@@ -1607,7 +1647,7 @@ fn add_pre_link_objects(
let empty = Default::default();
let objects = if self_contained {
&opts.pre_link_objects_self_contained
- } else if !(sess.target.os == "fuchsia" && flavor == LinkerFlavor::Gcc) {
+ } else if !(sess.target.os == "fuchsia" && matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))) {
&opts.pre_link_objects
} else {
&empty
@@ -1647,7 +1687,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor)
fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
match (crate_type, &sess.target.link_script) {
(CrateType::Cdylib | CrateType::Executable, Some(script)) => {
- if !sess.target.linker_is_gnu {
+ if !sess.target.linker_flavor.is_gnu() {
sess.fatal("can only use link script when linking with GNU-like linker");
}
@@ -1890,7 +1930,7 @@ fn add_rpath_args(
out_filename: out_filename.to_path_buf(),
has_rpath: sess.target.has_rpath,
is_like_osx: sess.target.is_like_osx,
- linker_is_gnu: sess.target.linker_is_gnu,
+ linker_is_gnu: sess.target.linker_flavor.is_gnu(),
};
cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
}
@@ -2134,7 +2174,7 @@ fn add_order_independent_options(
if sess.target.os == "fuchsia"
&& crate_type == CrateType::Executable
- && flavor != LinkerFlavor::Gcc
+ && !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _))
{
let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) {
"asan/"
@@ -2747,12 +2787,12 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
let llvm_target = &sess.target.llvm_target;
if sess.target.vendor != "apple"
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "macos")
- || (flavor != LinkerFlavor::Gcc && flavor != LinkerFlavor::Lld(LldFlavor::Ld64))
+ || !matches!(flavor, LinkerFlavor::Darwin(..))
{
return;
}
- if os == "macos" && flavor != LinkerFlavor::Lld(LldFlavor::Ld64) {
+ if os == "macos" && !matches!(flavor, LinkerFlavor::Darwin(Cc::No, _)) {
return;
}
@@ -2786,10 +2826,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
};
match flavor {
- LinkerFlavor::Gcc => {
+ LinkerFlavor::Darwin(Cc::Yes, _) => {
cmd.args(&["-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
}
- LinkerFlavor::Lld(LldFlavor::Ld64) => {
+ LinkerFlavor::Darwin(Cc::No, _) => {
cmd.args(&["-syslibroot", &sdk_root]);
}
_ => unreachable!(),
@@ -2852,7 +2892,10 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
if let Some(ld_impl) = sess.opts.unstable_opts.gcc_ld {
- if let LinkerFlavor::Gcc = flavor {
+ if let LinkerFlavor::Gnu(Cc::Yes, _)
+ | LinkerFlavor::Darwin(Cc::Yes, _)
+ | LinkerFlavor::WasmLld(Cc::Yes) = flavor
+ {
match ld_impl {
LdImpl::Lld => {
// Implement the "self-contained" part of -Zgcc-ld
@@ -2867,7 +2910,7 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
// Implement the "linker flavor" part of -Zgcc-ld
// by asking cc to use some kind of lld.
cmd.arg("-fuse-ld=lld");
- if sess.target.lld_flavor != LldFlavor::Ld {
+ if !flavor.is_gnu() {
// Tell clang to use a non-default LLD flavor.
// Gcc doesn't understand the target option, but we currently assume
// that gcc is not used for Apple and Wasm targets (#97402).
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e505543b2..c49b19bdf 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -1,5 +1,6 @@
use super::command::Command;
use super::symbol_export;
+use crate::errors;
use rustc_span::symbol::sym;
use std::ffi::{OsStr, OsString};
@@ -16,7 +17,7 @@ use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, S
use rustc_middle::ty::TyCtxt;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
use rustc_session::Session;
-use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
+use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
use cc::windows_registry;
@@ -56,8 +57,13 @@ pub fn get_linker<'a>(
let mut cmd = match linker.to_str() {
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
_ => match flavor {
- LinkerFlavor::Lld(f) => Command::lld(linker, f),
- LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
+ LinkerFlavor::Gnu(Cc::No, Lld::Yes)
+ | LinkerFlavor::Darwin(Cc::No, Lld::Yes)
+ | LinkerFlavor::WasmLld(Cc::No)
+ | LinkerFlavor::Msvc(Lld::Yes) => Command::lld(linker, flavor.lld_flavor()),
+ LinkerFlavor::Msvc(Lld::No)
+ if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() =>
+ {
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
}
_ => Command::new(linker),
@@ -68,9 +74,7 @@ pub fn get_linker<'a>(
// To comply with the Windows App Certification Kit,
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
let t = &sess.target;
- if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
- && t.vendor == "uwp"
- {
+ if matches!(flavor, LinkerFlavor::Msvc(..)) && t.vendor == "uwp" {
if let Some(ref tool) = msvc_tool {
let original_path = tool.path();
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
@@ -126,23 +130,22 @@ pub fn get_linker<'a>(
// to the linker args construction.
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
match flavor {
- LinkerFlavor::Gcc => {
- Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
- as Box<dyn Linker>
- }
- LinkerFlavor::Ld if sess.target.os == "l4re" => {
+ LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => {
Box::new(L4Bender::new(cmd, sess)) as Box<dyn Linker>
}
- LinkerFlavor::Lld(LldFlavor::Ld)
- | LinkerFlavor::Lld(LldFlavor::Ld64)
- | LinkerFlavor::Ld => {
- Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
- as Box<dyn Linker>
- }
- LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
- Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
- }
- LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
+ LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
+ LinkerFlavor::Gnu(cc, _)
+ | LinkerFlavor::Darwin(cc, _)
+ | LinkerFlavor::WasmLld(cc)
+ | LinkerFlavor::Unix(cc) => Box::new(GccLinker {
+ cmd,
+ sess,
+ target_cpu,
+ hinted_static: false,
+ is_ld: cc == Cc::No,
+ is_gnu: flavor.is_gnu(),
+ }) as Box<dyn Linker>,
+ LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
@@ -211,6 +214,7 @@ pub struct GccLinker<'a> {
hinted_static: bool, // Keeps track of the current hinting mode.
// Link as ld
is_ld: bool,
+ is_gnu: bool,
}
impl<'a> GccLinker<'a> {
@@ -359,7 +363,7 @@ impl<'a> Linker for GccLinker<'a> {
fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
match output_kind {
LinkOutputKind::DynamicNoPicExe => {
- if !self.is_ld && self.sess.target.linker_is_gnu {
+ if !self.is_ld && self.is_gnu {
self.cmd.arg("-no-pie");
}
}
@@ -373,7 +377,7 @@ impl<'a> Linker for GccLinker<'a> {
LinkOutputKind::StaticNoPicExe => {
// `-static` works for both gcc wrapper and ld.
self.cmd.arg("-static");
- if !self.is_ld && self.sess.target.linker_is_gnu {
+ if !self.is_ld && self.is_gnu {
self.cmd.arg("-no-pie");
}
}
@@ -431,26 +435,26 @@ impl<'a> Linker for GccLinker<'a> {
// FIXME(81490): ld64 doesn't support these flags but macOS 11
// has -needed-l{} / -needed_library {}
// but we have no way to detect that here.
- self.sess.warn("`as-needed` modifier not implemented yet for ld64");
- } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
+ self.sess.emit_warning(errors::Ld64UnimplementedModifier);
+ } else if self.is_gnu && !self.sess.target.is_like_windows {
self.linker_arg("--no-as-needed");
} else {
- self.sess.warn("`as-needed` modifier not supported for current linker");
+ self.sess.emit_warning(errors::LinkerUnsupportedModifier);
}
}
self.hint_dynamic();
- self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib));
+ self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
if !as_needed {
if self.sess.target.is_like_osx {
// See above FIXME comment
- } else if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
+ } else if self.is_gnu && !self.sess.target.is_like_windows {
self.linker_arg("--as-needed");
}
}
}
fn link_staticlib(&mut self, lib: &str, verbatim: bool) {
self.hint_static();
- self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib));
+ self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
}
fn link_rlib(&mut self, lib: &Path) {
self.hint_static();
@@ -489,7 +493,7 @@ impl<'a> Linker for GccLinker<'a> {
// FIXME(81490): ld64 as of macOS 11 supports the -needed_framework
// flag but we have no way to detect that here.
// self.cmd.arg("-needed_framework").arg(framework);
- self.sess.warn("`as-needed` modifier not implemented yet for ld64");
+ self.sess.emit_warning(errors::Ld64UnimplementedModifier);
}
self.cmd.arg("-framework").arg(framework);
}
@@ -504,11 +508,8 @@ impl<'a> Linker for GccLinker<'a> {
self.hint_static();
let target = &self.sess.target;
if !target.is_like_osx {
- self.linker_arg("--whole-archive").cmd.arg(format!(
- "-l{}{}",
- if verbatim { ":" } else { "" },
- lib
- ));
+ self.linker_arg("--whole-archive");
+ self.cmd.arg(format!("-l{}{lib}", if verbatim && self.is_gnu { ":" } else { "" },));
self.linker_arg("--no-whole-archive");
} else {
// -force_load is the macOS equivalent of --whole-archive, but it
@@ -553,21 +554,19 @@ impl<'a> Linker for GccLinker<'a> {
// eliminate the metadata. If we're building an executable, however,
// --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
// reduction.
- } else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm)
- && !keep_metadata
- {
+ } else if (self.is_gnu || self.sess.target.is_like_wasm) && !keep_metadata {
self.linker_arg("--gc-sections");
}
}
fn no_gc_sections(&mut self) {
- if self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm {
+ if self.is_gnu || self.sess.target.is_like_wasm {
self.linker_arg("--no-gc-sections");
}
}
fn optimize(&mut self) {
- if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm {
+ if !self.is_gnu && !self.sess.target.is_like_wasm {
return;
}
@@ -581,7 +580,7 @@ impl<'a> Linker for GccLinker<'a> {
}
fn pgo_gen(&mut self) {
- if !self.sess.target.linker_is_gnu {
+ if !self.is_gnu {
return;
}
@@ -611,7 +610,13 @@ impl<'a> Linker for GccLinker<'a> {
match strip {
Strip::None => {}
Strip::Debuginfo => {
- self.linker_arg("--strip-debug");
+ // The illumos linker does not support --strip-debug although
+ // it does support --strip-all as a compatibility alias for -s.
+ // The --strip-debug case is handled by running an external
+ // `strip` utility as a separate step after linking.
+ if self.sess.target.os != "illumos" {
+ self.linker_arg("--strip-debug");
+ }
}
Strip::Symbols => {
self.linker_arg("--strip-all");
@@ -667,8 +672,8 @@ impl<'a> Linker for GccLinker<'a> {
writeln!(f, "_{}", sym)?;
}
};
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write lib.def file: {}", e));
+ if let Err(error) = res {
+ self.sess.emit_fatal(errors::LibDefWriteFailure { error });
}
} else if is_windows {
let res: io::Result<()> = try {
@@ -682,8 +687,8 @@ impl<'a> Linker for GccLinker<'a> {
writeln!(f, " {}", symbol)?;
}
};
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write list.def file: {}", e));
+ if let Err(error) = res {
+ self.sess.emit_fatal(errors::LibDefWriteFailure { error });
}
} else {
// Write an LD version script
@@ -699,8 +704,8 @@ impl<'a> Linker for GccLinker<'a> {
}
writeln!(f, "\n local:\n *;\n}};")?;
};
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write version script: {}", e));
+ if let Err(error) = res {
+ self.sess.emit_fatal(errors::VersionScriptWriteFailure { error });
}
}
@@ -752,13 +757,13 @@ impl<'a> Linker for GccLinker<'a> {
fn add_no_exec(&mut self) {
if self.sess.target.is_like_windows {
self.linker_arg("--nxcompat");
- } else if self.sess.target.linker_is_gnu {
+ } else if self.is_gnu {
self.linker_arg("-znoexecstack");
}
}
fn add_as_needed(&mut self) {
- if self.sess.target.linker_is_gnu && !self.sess.target.is_like_windows {
+ if self.is_gnu && !self.sess.target.is_like_windows {
self.linker_arg("--as-needed");
} else if self.sess.target.is_like_solaris {
// -z ignore is the Solaris equivalent to the GNU ld --as-needed option
@@ -917,9 +922,8 @@ impl<'a> Linker for MsvcLinker<'a> {
self.cmd.arg(arg);
}
}
- Err(err) => {
- self.sess
- .warn(&format!("error enumerating natvis directory: {}", err));
+ Err(error) => {
+ self.sess.emit_warning(errors::NoNatvisDirectory { error });
}
}
}
@@ -973,8 +977,8 @@ impl<'a> Linker for MsvcLinker<'a> {
writeln!(f, " {}", symbol)?;
}
};
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write lib.def file: {}", e));
+ if let Err(error) = res {
+ self.sess.emit_fatal(errors::LibDefWriteFailure { error });
}
let mut arg = OsString::from("/DEF:");
arg.push(path);
@@ -1174,22 +1178,19 @@ impl<'a> WasmLd<'a> {
// sharing memory and instantiating the module multiple times. As a
// result if it were exported then we'd just have no sharing.
//
- // * `--export=__wasm_init_memory` - when using `--passive-segments` the
- // linker will synthesize this function, and so we need to make sure
- // that our usage of `--export` below won't accidentally cause this
- // function to get deleted.
- //
- // * `--export=*tls*` - when `#[thread_local]` symbols are used these
- // symbols are how the TLS segments are initialized and configured.
+ // On wasm32-unknown-unknown, we also export symbols for glue code to use:
+ // * `--export=*tls*` - when `#[thread_local]` symbols are used these
+ // symbols are how the TLS segments are initialized and configured.
if sess.target_features.contains(&sym::atomics) {
cmd.arg("--shared-memory");
cmd.arg("--max-memory=1073741824");
cmd.arg("--import-memory");
- cmd.arg("--export=__wasm_init_memory");
- cmd.arg("--export=__wasm_init_tls");
- cmd.arg("--export=__tls_size");
- cmd.arg("--export=__tls_align");
- cmd.arg("--export=__tls_base");
+ if sess.target.os == "unknown" {
+ cmd.arg("--export=__wasm_init_tls");
+ cmd.arg("--export=__tls_size");
+ cmd.arg("--export=__tls_align");
+ cmd.arg("--export=__tls_base");
+ }
}
WasmLd { cmd, sess }
}
@@ -1314,10 +1315,12 @@ impl<'a> Linker for WasmLd<'a> {
// LLD will hide these otherwise-internal symbols since it only exports
// symbols explicitly passed via the `--export` flags above and hides all
- // others. Various bits and pieces of tooling use this, so be sure these
- // symbols make their way out of the linker as well.
- self.cmd.arg("--export=__heap_base");
- self.cmd.arg("--export=__data_end");
+ // others. Various bits and pieces of wasm32-unknown-unknown tooling use
+ // this, so be sure these symbols make their way out of the linker as well.
+ if self.sess.target.os == "unknown" {
+ self.cmd.arg("--export=__heap_base");
+ self.cmd.arg("--export=__data_end");
+ }
}
fn subsystem(&mut self, _subsystem: &str) {}
@@ -1438,7 +1441,7 @@ impl<'a> Linker for L4Bender<'a> {
fn export_symbols(&mut self, _: &Path, _: CrateType, _: &[String]) {
// ToDo, not implemented, copy from GCC
- self.sess.warn("exporting symbols not implemented yet for L4Bender");
+ self.sess.emit_warning(errors::L4BenderExportingSymbolsUnimplemented);
return;
}
@@ -1730,8 +1733,8 @@ impl<'a> Linker for BpfLinker<'a> {
writeln!(f, "{}", sym)?;
}
};
- if let Err(e) = res {
- self.sess.fatal(&format!("failed to write symbols file: {}", e));
+ if let Err(error) = res {
+ self.sess.emit_fatal(errors::SymbolFileWriteFailure { error });
} else {
self.cmd.arg("--export-symbols").arg(&path);
}
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 8d7e2c5cf..c2ecc4160 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -13,7 +13,7 @@ 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_session::config::CrateType;
+use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::spec::SanitizerSet;
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
@@ -76,7 +76,7 @@ fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<
// let it through if it's included statically.
match tcx.hir().get_by_def_id(def_id) {
Node::ForeignItem(..) => {
- tcx.is_statically_included_foreign_item(def_id).then_some(def_id)
+ tcx.native_library(def_id).map_or(false, |library| library.kind.is_statically_included()).then_some(def_id)
}
// Only consider nodes that actually have exported symbols.
@@ -206,6 +206,15 @@ fn exported_symbols_provider_local<'tcx>(
},
));
}
+
+ symbols.push((
+ ExportedSymbol::NoDefId(SymbolName::new(tcx, OomStrategy::SYMBOL)),
+ SymbolExportInfo {
+ level: SymbolExportLevel::Rust,
+ kind: SymbolExportKind::Text,
+ used: false,
+ },
+ ));
}
if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 68f3b19b7..d0ac016b0 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -2,11 +2,11 @@ use super::link::{self, ensure_removed};
use super::lto::{self, SerializedModule};
use super::symbol_export::symbol_name_for_instance_in_crate;
+use crate::errors;
+use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind,
};
-
-use crate::traits::*;
use jobserver::{Acquired, Client};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::memmap::Mmap;
@@ -15,7 +15,10 @@ use rustc_data_structures::profiling::TimingGuard;
use rustc_data_structures::profiling::VerboseTimingGuard;
use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::Emitter;
-use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
+use rustc_errors::{
+ translation::{to_fluent_args, Translate},
+ DiagnosticId, FatalError, Handler, Level,
+};
use rustc_fs_util::link_or_copy;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_incremental::{
@@ -113,7 +116,6 @@ pub struct ModuleConfig {
pub vectorize_slp: bool,
pub merge_functions: bool,
pub inline_threshold: Option<u32>,
- pub new_llvm_pass_manager: Option<bool>,
pub emit_lifetime_markers: bool,
pub llvm_plugins: Vec<String>,
}
@@ -265,7 +267,6 @@ impl ModuleConfig {
},
inline_threshold: sess.opts.cg.inline_threshold,
- new_llvm_pass_manager: sess.opts.unstable_opts.new_llvm_pass_manager,
emit_lifetime_markers: sess.emit_lifetime_markers(),
llvm_plugins: if_regular!(sess.opts.unstable_opts.llvm_plugins.clone(), vec![]),
}
@@ -532,7 +533,7 @@ fn produce_final_output_artifacts(
// Produce final compile outputs.
let copy_gracefully = |from: &Path, to: &Path| {
if let Err(e) = fs::copy(from, to) {
- sess.err(&format!("could not copy {:?} to {:?}: {}", from, to, e));
+ sess.emit_err(errors::CopyPath::new(from, to, e));
}
};
@@ -548,7 +549,7 @@ fn produce_final_output_artifacts(
ensure_removed(sess.diagnostic(), &path);
}
} else {
- let ext = crate_output
+ let extension = crate_output
.temp_path(output_type, None)
.extension()
.unwrap()
@@ -559,19 +560,11 @@ fn produce_final_output_artifacts(
if crate_output.outputs.contains_key(&output_type) {
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
// no good solution for this case, so warn the user.
- sess.warn(&format!(
- "ignoring emit path because multiple .{} files \
- were produced",
- ext
- ));
+ sess.emit_warning(errors::IgnoringEmitPath { extension });
} else if crate_output.single_output_file.is_some() {
// 3) Multiple codegen units, with `-o some_name`. We have
// no good solution for this case, so warn the user.
- sess.warn(&format!(
- "ignoring -o because multiple .{} files \
- were produced",
- ext
- ));
+ sess.emit_warning(errors::IgnoringOutput { extension });
} else {
// 4) Multiple codegen units, but no explicit name. We
// just leave the `foo.0.x` files in place.
@@ -882,14 +875,12 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
);
match link_or_copy(&source_file, &output_path) {
Ok(_) => Some(output_path),
- Err(err) => {
- let diag_handler = cgcx.create_diag_handler();
- diag_handler.err(&format!(
- "unable to copy {} to {}: {}",
- source_file.display(),
- output_path.display(),
- err
- ));
+ Err(error) => {
+ cgcx.create_diag_handler().emit_err(errors::CopyPathBuf {
+ source_file,
+ output_path,
+ error,
+ });
None
}
}
@@ -1008,6 +999,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
let coordinator_send = tx_to_llvm_workers;
let sess = tcx.sess;
+ let mut each_linked_rlib_for_lto = Vec::new();
+ drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| {
+ if link::ignored_for_lto(sess, crate_info, cnum) {
+ return;
+ }
+ each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
+ }));
+
// Compute the set of symbols we need to retain when doing LTO (if we need to)
let exported_symbols = {
let mut exported_symbols = FxHashMap::default();
@@ -1029,7 +1028,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
}
Lto::Fat | Lto::Thin => {
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
- for &cnum in tcx.crates(()).iter() {
+ for &(cnum, ref _path) in &each_linked_rlib_for_lto {
exported_symbols.insert(cnum, copy_symbols(cnum));
}
Some(Arc::new(exported_symbols))
@@ -1049,14 +1048,6 @@ fn start_executing_work<B: ExtraBackendMethods>(
})
.expect("failed to spawn helper thread");
- let mut each_linked_rlib_for_lto = Vec::new();
- drop(link::each_linked_rlib(crate_info, &mut |cnum, path| {
- if link::ignored_for_lto(sess, crate_info, cnum) {
- return;
- }
- each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
- }));
-
let ol =
if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
// If we know that we won’t be doing codegen, create target machines without optimisation.
@@ -1639,7 +1630,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
llvm_start_time: &mut Option<VerboseTimingGuard<'a>>,
) {
if config.time_module && llvm_start_time.is_none() {
- *llvm_start_time = Some(prof.extra_verbose_generic_activity("LLVM_passes", "crate"));
+ *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes"));
}
}
}
@@ -1752,7 +1743,7 @@ impl Translate for SharedEmitter {
impl Emitter for SharedEmitter {
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
- let fluent_args = self.to_fluent_args(diag.args());
+ let fluent_args = to_fluent_args(diag.args());
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
code: diag.code.clone(),
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index b98ff4957..84b89cd71 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, VariantIdx};
+use rustc_target::abi::{Align, Size, VariantIdx};
use std::collections::BTreeSet;
use std::convert::TryFrom;
@@ -151,7 +151,12 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
(&ty::Array(_, len), &ty::Slice(_)) => {
cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
}
- (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
+ (
+ &ty::Dynamic(ref data_a, _, src_dyn_kind),
+ &ty::Dynamic(ref data_b, _, target_dyn_kind),
+ ) => {
+ assert_eq!(src_dyn_kind, target_dyn_kind);
+
let old_info =
old_info.expect("unsized_info: missing old info for trait upcasting coercion");
if data_a.principal_def_id() == data_b.principal_def_id() {
@@ -167,11 +172,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
if let Some(entry_idx) = vptr_entry_idx {
let ptr_ty = cx.type_i8p();
let ptr_align = cx.tcx().data_layout.pointer_align.abi;
- let vtable_ptr_ty = cx.scalar_pair_element_backend_type(
- cx.layout_of(cx.tcx().mk_mut_ptr(target)),
- 1,
- true,
- );
+ let vtable_ptr_ty = vtable_ptr_ty(cx, target, target_dyn_kind);
let llvtable = bx.pointercast(old_info, bx.type_ptr_to(ptr_ty));
let gep = bx.inbounds_gep(
ptr_ty,
@@ -187,18 +188,32 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
old_info
}
}
- (_, &ty::Dynamic(ref data, ..)) => {
- let vtable_ptr_ty = cx.scalar_pair_element_backend_type(
- cx.layout_of(cx.tcx().mk_mut_ptr(target)),
- 1,
- true,
- );
+ (_, &ty::Dynamic(ref data, _, target_dyn_kind)) => {
+ let vtable_ptr_ty = vtable_ptr_ty(cx, target, target_dyn_kind);
cx.const_ptrcast(meth::get_vtable(cx, source, data.principal()), vtable_ptr_ty)
}
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
}
}
+// Returns the vtable pointer type of a `dyn` or `dyn*` type
+fn vtable_ptr_ty<'tcx, Cx: CodegenMethods<'tcx>>(
+ cx: &Cx,
+ target: Ty<'tcx>,
+ kind: ty::DynKind,
+) -> <Cx as BackendTypes>::Type {
+ cx.scalar_pair_element_backend_type(
+ cx.layout_of(match kind {
+ // vtable is the second field of `*mut dyn Trait`
+ ty::Dyn => cx.tcx().mk_mut_ptr(target),
+ // vtable is the second field of `dyn* Trait`
+ ty::DynStar => target,
+ }),
+ 1,
+ true,
+ )
+}
+
/// Coerces `src` to `dst_ty`. `src_ty` must be a pointer.
pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
@@ -248,6 +263,29 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
}
}
+/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
+pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
+ bx: &mut Bx,
+ src: Bx::Value,
+ src_ty_and_layout: TyAndLayout<'tcx>,
+ dst_ty: Ty<'tcx>,
+ old_info: Option<Bx::Value>,
+) -> (Bx::Value, Bx::Value) {
+ debug!("cast_to_dyn_star: {:?} => {:?}", src_ty_and_layout.ty, dst_ty);
+ assert!(
+ 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()),
+ };
+ (src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info))
+}
+
/// Coerces `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty`, and stores the result in `dst`.
pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
@@ -299,40 +337,26 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
- op: hir::BinOpKind,
- lhs: Bx::Value,
- rhs: Bx::Value,
-) -> Bx::Value {
- cast_shift_rhs(bx, op, lhs, rhs)
-}
-
-fn cast_shift_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
- bx: &mut Bx,
- op: hir::BinOpKind,
lhs: Bx::Value,
rhs: Bx::Value,
) -> Bx::Value {
// Shifts may have any size int on the rhs
- if op.is_shift() {
- let mut rhs_llty = bx.cx().val_ty(rhs);
- let mut lhs_llty = bx.cx().val_ty(lhs);
- if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
- rhs_llty = bx.cx().element_type(rhs_llty)
- }
- if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
- lhs_llty = bx.cx().element_type(lhs_llty)
- }
- let rhs_sz = bx.cx().int_width(rhs_llty);
- let lhs_sz = bx.cx().int_width(lhs_llty);
- if lhs_sz < rhs_sz {
- bx.trunc(rhs, lhs_llty)
- } else if lhs_sz > rhs_sz {
- // FIXME (#1877: If in the future shifting by negative
- // values is no longer undefined then this is wrong.
- bx.zext(rhs, lhs_llty)
- } else {
- rhs
- }
+ let mut rhs_llty = bx.cx().val_ty(rhs);
+ let mut lhs_llty = bx.cx().val_ty(lhs);
+ if bx.cx().type_kind(rhs_llty) == TypeKind::Vector {
+ rhs_llty = bx.cx().element_type(rhs_llty)
+ }
+ if bx.cx().type_kind(lhs_llty) == TypeKind::Vector {
+ lhs_llty = bx.cx().element_type(lhs_llty)
+ }
+ let rhs_sz = bx.cx().int_width(rhs_llty);
+ let lhs_sz = bx.cx().int_width(lhs_llty);
+ if lhs_sz < rhs_sz {
+ bx.trunc(rhs, lhs_llty)
+ } else if lhs_sz > rhs_sz {
+ // FIXME (#1877: If in the future shifting by negative
+ // values is no longer undefined then this is wrong.
+ bx.zext(rhs, lhs_llty)
} else {
rhs
}
@@ -475,7 +499,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
(rust_main, start_ty, vec![arg_argc, arg_argv])
};
- let result = bx.call(start_ty, start_fn, &args, None);
+ let result = bx.call(start_ty, None, start_fn, &args, None);
let cast = bx.intcast(result, cx.type_int(), true);
bx.ret(cast);
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index 8ca1a6084..71f9179d0 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -1,7 +1,6 @@
#![allow(non_camel_case_types)]
use rustc_errors::struct_span_err;
-use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_middle::mir::interpret::ConstValue;
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
@@ -140,7 +139,7 @@ pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
lhs: Bx::Value,
rhs: Bx::Value,
) -> Bx::Value {
- let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
+ let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
bx.shl(lhs, rhs)
@@ -152,7 +151,7 @@ pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
lhs: Bx::Value,
rhs: Bx::Value,
) -> Bx::Value {
- let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
+ let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
// #1877, #10183: Ensure that input is always valid
let rhs = shift_mask_rhs(bx, rhs);
let is_signed = lhs_t.is_signed();
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 135ed680d..e05646e1e 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -666,10 +666,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
hcx.while_hashing_spans(false, |hcx| {
ct.to_valtree().hash_stable(hcx, &mut hasher)
});
- // Note: Don't use `StableHashResult` impl of `u64` here directly, since that
- // would lead to endianness problems.
- let hash: u128 = hasher.finish();
- (hash.to_le() as u64).to_le()
+ let hash: u64 = hasher.finish();
+ hash
});
if cpp_like_debuginfo(tcx) {
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
new file mode 100644
index 000000000..ebb531f1c
--- /dev/null
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -0,0 +1,356 @@
+//! Errors emitted by codegen_ssa
+
+use crate::back::command::Command;
+use rustc_errors::{
+ fluent, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
+ IntoDiagnosticArg,
+};
+use rustc_macros::Diagnostic;
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
+use std::io::Error;
+use std::path::{Path, PathBuf};
+use std::process::ExitStatus;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_lib_def_write_failure)]
+pub struct LibDefWriteFailure {
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_version_script_write_failure)]
+pub struct VersionScriptWriteFailure {
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_symbol_file_write_failure)]
+pub struct SymbolFileWriteFailure {
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_ld64_unimplemented_modifier)]
+pub struct Ld64UnimplementedModifier;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_linker_unsupported_modifier)]
+pub struct LinkerUnsupportedModifier;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_L4Bender_exporting_symbols_unimplemented)]
+pub struct L4BenderExportingSymbolsUnimplemented;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_no_natvis_directory)]
+pub struct NoNatvisDirectory {
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_copy_path_buf)]
+pub struct CopyPathBuf {
+ pub source_file: PathBuf,
+ pub output_path: PathBuf,
+ pub error: Error,
+}
+
+// Reports Paths using `Debug` implementation rather than Path's `Display` implementation.
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_copy_path)]
+pub struct CopyPath<'a> {
+ from: DebugArgPath<'a>,
+ to: DebugArgPath<'a>,
+ error: Error,
+}
+
+impl<'a> CopyPath<'a> {
+ pub fn new(from: &'a Path, to: &'a Path, error: Error) -> CopyPath<'a> {
+ CopyPath { from: DebugArgPath(from), to: DebugArgPath(to), error }
+ }
+}
+
+struct DebugArgPath<'a>(pub &'a Path);
+
+impl IntoDiagnosticArg for DebugArgPath<'_> {
+ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self.0)))
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_ignoring_emit_path)]
+pub struct IgnoringEmitPath {
+ pub extension: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_ignoring_output)]
+pub struct IgnoringOutput {
+ pub extension: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_create_temp_dir)]
+pub struct CreateTempDir {
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_incompatible_linking_modifiers)]
+pub struct IncompatibleLinkingModifiers;
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_add_native_library)]
+pub struct AddNativeLibrary {
+ pub library_path: PathBuf,
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_multiple_external_func_decl)]
+pub struct MultipleExternalFuncDecl<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub function: Symbol,
+ pub library_name: &'a str,
+}
+
+#[derive(Diagnostic)]
+pub enum LinkRlibError {
+ #[diag(codegen_ssa_rlib_missing_format)]
+ MissingFormat,
+
+ #[diag(codegen_ssa_rlib_only_rmeta_found)]
+ OnlyRmetaFound { crate_name: Symbol },
+
+ #[diag(codegen_ssa_rlib_not_found)]
+ NotFound { crate_name: Symbol },
+
+ #[diag(codegen_ssa_rlib_incompatible_dependency_formats)]
+ IncompatibleDependencyFormats { ty1: String, ty2: String, list1: String, list2: String },
+}
+
+pub struct ThorinErrorWrapper(pub thorin::Error);
+
+impl IntoDiagnostic<'_> for ThorinErrorWrapper {
+ fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag;
+ match self.0 {
+ thorin::Error::ReadInput(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_read_input_failure);
+ diag
+ }
+ thorin::Error::ParseFileKind(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind);
+ diag
+ }
+ thorin::Error::ParseObjectFile(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file);
+ diag
+ }
+ thorin::Error::ParseArchiveFile(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file);
+ diag
+ }
+ thorin::Error::ParseArchiveMember(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_archive_member);
+ diag
+ }
+ thorin::Error::InvalidInputKind => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind);
+ diag
+ }
+ thorin::Error::DecompressData(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_decompress_data);
+ diag
+ }
+ thorin::Error::NamelessSection(_, offset) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_section_without_name);
+ diag.set_arg("offset", format!("0x{:08x}", offset));
+ diag
+ }
+ thorin::Error::RelocationWithInvalidSymbol(section, offset) => {
+ diag =
+ handler.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol);
+ diag.set_arg("section", section);
+ diag.set_arg("offset", format!("0x{:08x}", offset));
+ diag
+ }
+ thorin::Error::MultipleRelocations(section, offset) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_relocations);
+ diag.set_arg("section", section);
+ diag.set_arg("offset", format!("0x{:08x}", offset));
+ diag
+ }
+ thorin::Error::UnsupportedRelocation(section, offset) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation);
+ diag.set_arg("section", section);
+ diag.set_arg("offset", format!("0x{:08x}", offset));
+ diag
+ }
+ thorin::Error::MissingDwoName(id) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name);
+ diag.set_arg("id", format!("0x{:08x}", id));
+ diag
+ }
+ thorin::Error::NoCompilationUnits => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_no_compilation_units);
+ diag
+ }
+ thorin::Error::NoDie => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_no_die);
+ diag
+ }
+ thorin::Error::TopLevelDieNotUnit => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit);
+ diag
+ }
+ thorin::Error::MissingRequiredSection(section) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_required_section);
+ diag.set_arg("section", section);
+ diag
+ }
+ thorin::Error::ParseUnitAbbreviations(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations);
+ diag
+ }
+ thorin::Error::ParseUnitAttribute(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute);
+ diag
+ }
+ thorin::Error::ParseUnitHeader(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit_header);
+ diag
+ }
+ thorin::Error::ParseUnit(_) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_unit);
+ diag
+ }
+ thorin::Error::IncompatibleIndexVersion(section, format, actual) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version);
+ diag.set_arg("section", section);
+ diag.set_arg("actual", actual);
+ diag.set_arg("format", format);
+ diag
+ }
+ thorin::Error::OffsetAtIndex(_, index) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_offset_at_index);
+ diag.set_arg("index", index);
+ diag
+ }
+ thorin::Error::StrAtOffset(_, offset) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_str_at_offset);
+ diag.set_arg("offset", format!("0x{:08x}", offset));
+ diag
+ }
+ thorin::Error::ParseIndex(_, section) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_parse_index);
+ diag.set_arg("section", section);
+ diag
+ }
+ thorin::Error::UnitNotInIndex(unit) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index);
+ diag.set_arg("unit", format!("0x{:08x}", unit));
+ diag
+ }
+ thorin::Error::RowNotInIndex(_, row) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_row_not_in_index);
+ diag.set_arg("row", row);
+ diag
+ }
+ thorin::Error::SectionNotInRow => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_section_not_in_row);
+ diag
+ }
+ thorin::Error::EmptyUnit(unit) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_empty_unit);
+ diag.set_arg("unit", format!("0x{:08x}", unit));
+ diag
+ }
+ thorin::Error::MultipleDebugInfoSection => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section);
+ diag
+ }
+ thorin::Error::MultipleDebugTypesSection => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section);
+ diag
+ }
+ thorin::Error::NotSplitUnit => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_not_split_unit);
+ diag
+ }
+ thorin::Error::DuplicateUnit(unit) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_duplicate_unit);
+ diag.set_arg("unit", format!("0x{:08x}", unit));
+ diag
+ }
+ thorin::Error::MissingReferencedUnit(unit) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit);
+ diag.set_arg("unit", format!("0x{:08x}", unit));
+ diag
+ }
+ thorin::Error::NoOutputObjectCreated => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_not_output_object_created);
+ diag
+ }
+ thorin::Error::MixedInputEncodings => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings);
+ diag
+ }
+ thorin::Error::Io(e) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_io);
+ diag.set_arg("error", format!("{e}"));
+ diag
+ }
+ thorin::Error::ObjectRead(e) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_object_read);
+ diag.set_arg("error", format!("{e}"));
+ diag
+ }
+ thorin::Error::ObjectWrite(e) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_object_write);
+ diag.set_arg("error", format!("{e}"));
+ diag
+ }
+ thorin::Error::GimliRead(e) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_read);
+ diag.set_arg("error", format!("{e}"));
+ diag
+ }
+ thorin::Error::GimliWrite(e) => {
+ diag = handler.struct_err(fluent::codegen_ssa_thorin_gimli_write);
+ diag.set_arg("error", format!("{e}"));
+ diag
+ }
+ _ => unimplemented!("Untranslated thorin error"),
+ }
+ }
+}
+
+pub struct LinkingFailed<'a> {
+ pub linker_path: &'a PathBuf,
+ pub exit_status: ExitStatus,
+ pub command: &'a Command,
+ pub escaped_output: &'a str,
+}
+
+impl IntoDiagnostic<'_> for LinkingFailed<'_> {
+ fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_err(fluent::codegen_ssa_linking_failed);
+ diag.set_arg("linker_path", format!("{}", self.linker_path.display()));
+ diag.set_arg("exit_status", format!("{}", self.exit_status));
+
+ diag.note(format!("{:?}", self.command)).note(self.escaped_output);
+
+ // Trying to match an error from OS linkers
+ // which by now we have no way to translate.
+ if self.escaped_output.contains("undefined reference to") {
+ diag.note(fluent::codegen_ssa_extern_funcs_not_found)
+ .note(fluent::codegen_ssa_specify_libraries_to_link)
+ .note(fluent::codegen_ssa_use_cargo_directive);
+ }
+ diag
+ }
+}
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index e736b2aba..ceebe4d41 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -1,12 +1,12 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)]
#![feature(try_blocks)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(once_cell)]
#![feature(associated_type_bounds)]
#![feature(strict_provenance)]
#![feature(int_roundings)]
#![feature(if_let_guard)]
+#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
@@ -44,6 +44,7 @@ pub mod base;
pub mod common;
pub mod coverageinfo;
pub mod debuginfo;
+pub mod errors;
pub mod glue;
pub mod meth;
pub mod mir;
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index a6b226ef7..29b7c9b0a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -63,7 +63,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
}
}
- fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
+ /// Get a basic block (creating it if necessary), possibly with a landing
+ /// pad next to it.
+ fn llbb_with_landing_pad<Bx: BuilderMethods<'a, 'tcx>>(
&self,
fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock,
@@ -73,32 +75,36 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
let target_funclet = fx.cleanup_kinds[target].funclet_bb(target);
match (self.funclet_bb, target_funclet) {
(None, None) => (lltarget, false),
- (Some(f), Some(t_f)) if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) => {
- (lltarget, false)
- }
// jump *into* cleanup - need a landing pad if GNU, cleanup pad if MSVC
(None, Some(_)) => (fx.landing_pad_for(target), false),
(Some(_), None) => span_bug!(span, "{:?} - jump out of cleanup?", self.terminator),
- (Some(_), Some(_)) => (fx.landing_pad_for(target), true),
+ (Some(f), Some(t_f)) => {
+ if f == t_f || !base::wants_msvc_seh(fx.cx.tcx().sess) {
+ (lltarget, false)
+ } else {
+ (fx.landing_pad_for(target), true)
+ }
+ }
}
}
- /// Create a basic block.
- fn llblock<Bx: BuilderMethods<'a, 'tcx>>(
+ /// Get a basic block (creating it if necessary), possibly with cleanup
+ /// stuff in it or next to it.
+ fn llbb_with_cleanup<Bx: BuilderMethods<'a, 'tcx>>(
&self,
fx: &mut FunctionCx<'a, 'tcx, Bx>,
target: mir::BasicBlock,
) -> Bx::BasicBlock {
- let (lltarget, is_cleanupret) = self.lltarget(fx, target);
+ let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target);
if is_cleanupret {
// MSVC cross-funclet jump - need a trampoline
-
- debug!("llblock: creating cleanup trampoline for {:?}", target);
+ debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
+ debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
- let trampoline = Bx::append_block(fx.cx, fx.llfn, name);
- let mut trampoline_bx = Bx::build(fx.cx, trampoline);
+ let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
+ let mut trampoline_bx = Bx::build(fx.cx, trampoline_llbb);
trampoline_bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
- trampoline
+ trampoline_llbb
} else {
lltarget
}
@@ -110,10 +116,11 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
bx: &mut Bx,
target: mir::BasicBlock,
) {
- let (lltarget, is_cleanupret) = self.lltarget(fx, target);
+ let (lltarget, is_cleanupret) = self.llbb_with_landing_pad(fx, target);
if is_cleanupret {
- // micro-optimization: generate a `ret` rather than a jump
+ // MSVC micro-optimization: generate a `ret` rather than a jump
// to a trampoline.
+ debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget));
} else {
bx.br(lltarget);
@@ -138,7 +145,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
- Some(self.llblock(fx, cleanup))
+ Some(self.llbb_with_cleanup(fx, cleanup))
} else if fx.mir[self.bb].is_cleanup
&& fn_abi.can_unwind
&& !base::wants_msvc_seh(fx.cx.tcx().sess)
@@ -162,9 +169,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
} else {
fx.unreachable_block()
};
- let invokeret =
- bx.invoke(fn_ty, fn_ptr, &llargs, ret_llbb, unwind_block, self.funclet(fx));
- bx.apply_attrs_callsite(&fn_abi, invokeret);
+ let invokeret = bx.invoke(
+ fn_ty,
+ Some(&fn_abi),
+ fn_ptr,
+ &llargs,
+ ret_llbb,
+ unwind_block,
+ self.funclet(fx),
+ );
if fx.mir[self.bb].is_cleanup {
bx.do_not_inline(invokeret);
}
@@ -178,8 +191,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret);
}
} else {
- let llret = bx.call(fn_ty, fn_ptr, &llargs, self.funclet(fx));
- bx.apply_attrs_callsite(&fn_abi, llret);
+ let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &llargs, self.funclet(fx));
if fx.mir[self.bb].is_cleanup {
// Cleanup is always the cold path. Don't inline
// drop glue. Also, when there is a deeply-nested
@@ -226,7 +238,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
options,
line_spans,
instance,
- Some((ret_llbb, self.llblock(fx, cleanup), self.funclet(fx))),
+ Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))),
);
} else {
bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None);
@@ -276,8 +288,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if target_iter.len() == 1 {
// If there are two targets (one conditional, one fallback), emit br instead of switch
let (test_value, target) = target_iter.next().unwrap();
- let lltrue = helper.llblock(self, target);
- let llfalse = helper.llblock(self, targets.otherwise());
+ let lltrue = helper.llbb_with_cleanup(self, target);
+ let llfalse = helper.llbb_with_cleanup(self, targets.otherwise());
if switch_ty == bx.tcx().types.bool {
// Don't generate trivial icmps when switching on bool
match test_value {
@@ -294,8 +306,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} else {
bx.switch(
discr.immediate(),
- helper.llblock(self, targets.otherwise()),
- target_iter.map(|(value, target)| (value, helper.llblock(self, target))),
+ helper.llbb_with_cleanup(self, targets.otherwise()),
+ target_iter.map(|(value, target)| (value, helper.llbb_with_cleanup(self, target))),
);
}
}
@@ -525,7 +537,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let cond = bx.expect(cond, expected);
// Create the failure block and the conditional branch to it.
- let lltarget = helper.llblock(self, target);
+ let lltarget = helper.llbb_with_cleanup(self, target);
let panic_block = bx.append_sibling_block("panic");
if expected {
bx.cond_br(cond, lltarget, panic_block);
@@ -1454,20 +1466,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// bar();
// }
Some(&mir::TerminatorKind::Abort) => {
- let cs_bb =
+ let cs_llbb =
Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb));
- let cp_bb =
+ let cp_llbb =
Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb));
- ret_llbb = cs_bb;
+ ret_llbb = cs_llbb;
- let mut cs_bx = Bx::build(self.cx, cs_bb);
- let cs = cs_bx.catch_switch(None, None, &[cp_bb]);
+ let mut cs_bx = Bx::build(self.cx, cs_llbb);
+ let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
// The "null" here is actually a RTTI type descriptor for the
// C++ personality function, but `catch (...)` has no type so
// it's null. The 64 here is actually a bitfield which
// represents that this is a catch-all block.
- let mut cp_bx = Bx::build(self.cx, cp_bb);
+ let mut cp_bx = Bx::build(self.cx, cp_llbb);
let null = cp_bx.const_null(
cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space),
);
@@ -1476,10 +1488,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
cp_bx.br(llbb);
}
_ => {
- let cleanup_bb =
+ let cleanup_llbb =
Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
- ret_llbb = cleanup_bb;
- let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
+ ret_llbb = cleanup_llbb;
+ let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
funclet = cleanup_bx.cleanup_pad(None, &[]);
cleanup_bx.br(llbb);
}
@@ -1487,19 +1499,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.funclets[bb] = Some(funclet);
ret_llbb
} else {
- let bb = Bx::append_block(self.cx, self.llfn, "cleanup");
- let mut bx = Bx::build(self.cx, bb);
+ let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup");
+ let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
let llpersonality = self.cx.eh_personality();
let llretty = self.landing_pad_type();
- let lp = bx.cleanup_landing_pad(llretty, llpersonality);
+ let lp = cleanup_bx.cleanup_landing_pad(llretty, llpersonality);
- let slot = self.get_personality_slot(&mut bx);
- slot.storage_live(&mut bx);
- Pair(bx.extract_value(lp, 0), bx.extract_value(lp, 1)).store(&mut bx, slot);
+ let slot = self.get_personality_slot(&mut cleanup_bx);
+ slot.storage_live(&mut cleanup_bx);
+ Pair(cleanup_bx.extract_value(lp, 0), cleanup_bx.extract_value(lp, 1))
+ .store(&mut cleanup_bx, slot);
- bx.br(llbb);
- bx.llbb()
+ cleanup_bx.br(llbb);
+ cleanup_llbb
}
}
@@ -1533,8 +1546,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicNoUnwind);
let fn_ty = bx.fn_decl_backend_type(&fn_abi);
- let llret = bx.call(fn_ty, fn_ptr, &[], None);
- bx.apply_attrs_callsite(&fn_abi, llret);
+ let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None);
bx.do_not_inline(llret);
bx.unreachable();
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 2b931bfc9..da9aaf00e 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -148,10 +148,10 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let debug_context = cx.create_function_debug_context(instance, &fn_abi, llfn, &mir);
let start_llbb = Bx::append_block(cx, llfn, "start");
- let mut bx = Bx::build(cx, start_llbb);
+ let mut start_bx = Bx::build(cx, start_llbb);
if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) {
- bx.set_personality_fn(cx.eh_personality());
+ start_bx.set_personality_fn(cx.eh_personality());
}
let cleanup_kinds = analyze::cleanup_kinds(&mir);
@@ -180,7 +180,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
caller_location: None,
};
- fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx);
+ fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
// Evaluate all required consts; codegen later assumes that CTFE will never fail.
let mut all_consts_ok = true;
@@ -206,29 +206,29 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// Allocate variable and temp allocas
fx.locals = {
- let args = arg_local_refs(&mut bx, &mut fx, &memory_locals);
+ let args = arg_local_refs(&mut start_bx, &mut fx, &memory_locals);
let mut allocate_local = |local| {
let decl = &mir.local_decls[local];
- let layout = bx.layout_of(fx.monomorphize(decl.ty));
+ let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
assert!(!layout.ty.has_erasable_regions());
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
debug!("alloc: {:?} (return place) -> place", local);
- let llretptr = bx.get_param(0);
+ let llretptr = start_bx.get_param(0);
return LocalRef::Place(PlaceRef::new_sized(llretptr, layout));
}
if memory_locals.contains(local) {
debug!("alloc: {:?} -> place", local);
if layout.is_unsized() {
- LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut bx, layout))
+ LocalRef::UnsizedPlace(PlaceRef::alloca_unsized_indirect(&mut start_bx, layout))
} else {
- LocalRef::Place(PlaceRef::alloca(&mut bx, layout))
+ LocalRef::Place(PlaceRef::alloca(&mut start_bx, layout))
}
} else {
debug!("alloc: {:?} -> operand", local);
- LocalRef::new_operand(&mut bx, layout)
+ LocalRef::new_operand(&mut start_bx, layout)
}
};
@@ -240,7 +240,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
};
// Apply debuginfo to the newly allocated locals.
- fx.debug_introduce_locals(&mut bx);
+ fx.debug_introduce_locals(&mut start_bx);
// Codegen the body of each block using reverse postorder
for (bb, _) in traversal::reverse_postorder(&mir) {
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 37b1e0362..e6ba642a7 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -352,7 +352,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
// Allocate an appropriate region on the stack, and copy the value into it
let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
- let lldst = bx.array_alloca(bx.cx().type_i8(), llsize, max_align);
+ let lldst = bx.byte_array_alloca(llsize, max_align);
bx.memcpy(lldst, max_align, llptr, min_align, llsize, flags);
// Store the allocated region and the extra to the indirect place.
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 13d8f6edd..9c18df564 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -400,6 +400,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
downcast
}
+ pub fn project_type<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+ &self,
+ bx: &mut Bx,
+ ty: Ty<'tcx>,
+ ) -> Self {
+ let mut downcast = *self;
+ downcast.layout = bx.cx().layout_of(ty);
+
+ // Cast to the appropriate type.
+ let variant_ty = bx.cx().backend_type(downcast.layout);
+ downcast.llval = bx.pointercast(downcast.llval, bx.cx().type_ptr_to(variant_ty));
+
+ downcast
+ }
+
pub fn storage_live<Bx: BuilderMethods<'a, 'tcx, Value = V>>(&self, bx: &mut Bx) {
bx.lifetime_start(self.llval, self.layout.size);
}
@@ -442,6 +457,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::ProjectionElem::Field(ref field, _) => {
cg_base.project_field(bx, field.index())
}
+ mir::ProjectionElem::OpaqueCast(ty) => cg_base.project_type(bx, ty),
mir::ProjectionElem::Index(index) => {
let index = &mir::Operand::Copy(mir::Place::from(index));
let index = self.codegen_operand(bx, index);
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 56852b0fc..4aab31fbf 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -4,7 +4,6 @@ use super::{FunctionCx, LocalRef};
use crate::base;
use crate::common::{self, IntPredicate};
-use crate::meth::get_vtable;
use crate::traits::*;
use crate::MemFlags;
@@ -250,7 +249,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandValue::Pair(lldata, llextra)
}
mir::CastKind::Pointer(PointerCast::MutToConstPointer)
- | mir::CastKind::Misc
+ | mir::CastKind::PtrToPtr
if bx.cx().is_backend_scalar_pair(operand.layout) =>
{
if let OperandValue::Pair(data_ptr, meta) = operand.val {
@@ -273,24 +272,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}
}
mir::CastKind::DynStar => {
- let data = match operand.val {
+ let (lldata, llextra) = match operand.val {
OperandValue::Ref(_, _, _) => todo!(),
- OperandValue::Immediate(v) => v,
- OperandValue::Pair(_, _) => todo!(),
+ OperandValue::Immediate(v) => (v, None),
+ OperandValue::Pair(v, l) => (v, Some(l)),
};
- let trait_ref =
- if let ty::Dynamic(data, _, ty::DynStar) = cast.ty.kind() {
- data.principal()
- } else {
- bug!("Only valid to do a DynStar cast into a DynStar type")
- };
- let vtable = get_vtable(bx.cx(), source.ty(self.mir, bx.tcx()), trait_ref);
- OperandValue::Pair(data, vtable)
+ let (lldata, llextra) =
+ base::cast_to_dyn_star(&mut bx, lldata, operand.layout, cast.ty, llextra);
+ OperandValue::Pair(lldata, llextra)
}
mir::CastKind::Pointer(
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
)
- | mir::CastKind::Misc
+ | mir::CastKind::IntToInt
+ | mir::CastKind::FloatToInt
+ | mir::CastKind::FloatToFloat
+ | mir::CastKind::IntToFloat
+ | mir::CastKind::PtrToPtr
+ | mir::CastKind::FnPtrToPtr
+
// Since int2ptr can have arbitrary integer types as input (so we have to do
// sign extension and all that), it is currently best handled in the same code
// path as the other integer-to-X casts.
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 0e259bcd1..83407ee8f 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -13,17 +13,25 @@ pub const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
// if it doesn't, to_llvm_feature in llvm_util in rustc_codegen_llvm needs to be adapted
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+ // tidy-alphabetical-start
("aclass", Some(sym::arm_target_feature)),
- ("mclass", Some(sym::arm_target_feature)),
- ("rclass", Some(sym::arm_target_feature)),
- ("dsp", Some(sym::arm_target_feature)),
- ("neon", Some(sym::arm_target_feature)),
+ ("aes", Some(sym::arm_target_feature)),
("crc", Some(sym::arm_target_feature)),
("crypto", Some(sym::arm_target_feature)),
- ("aes", Some(sym::arm_target_feature)),
- ("sha2", Some(sym::arm_target_feature)),
- ("i8mm", Some(sym::arm_target_feature)),
+ ("d32", Some(sym::arm_target_feature)),
("dotprod", Some(sym::arm_target_feature)),
+ ("dsp", Some(sym::arm_target_feature)),
+ ("fp-armv8", Some(sym::arm_target_feature)),
+ ("i8mm", Some(sym::arm_target_feature)),
+ ("mclass", Some(sym::arm_target_feature)),
+ ("neon", Some(sym::arm_target_feature)),
+ ("rclass", Some(sym::arm_target_feature)),
+ ("sha2", Some(sym::arm_target_feature)),
+ // This is needed for inline assembly, but shouldn't be stabilized as-is
+ // since it should be enabled per-function using #[instruction_set], not
+ // #[target_feature].
+ ("thumb-mode", Some(sym::arm_target_feature)),
+ ("thumb2", Some(sym::arm_target_feature)),
("v5te", Some(sym::arm_target_feature)),
("v6", Some(sym::arm_target_feature)),
("v6k", Some(sym::arm_target_feature)),
@@ -33,104 +41,97 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("vfp2", Some(sym::arm_target_feature)),
("vfp3", Some(sym::arm_target_feature)),
("vfp4", Some(sym::arm_target_feature)),
- ("fp-armv8", Some(sym::arm_target_feature)),
- // This is needed for inline assembly, but shouldn't be stabilized as-is
- // since it should be enabled per-function using #[instruction_set], not
- // #[target_feature].
- ("thumb-mode", Some(sym::arm_target_feature)),
- ("thumb2", Some(sym::arm_target_feature)),
- ("d32", Some(sym::arm_target_feature)),
+ // tidy-alphabetical-end
];
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
- // FEAT_AdvSimd & FEAT_FP
- ("neon", None),
- // FEAT_FP16
- ("fp16", None),
- // FEAT_SVE
- ("sve", None),
+ // tidy-alphabetical-start
+ // FEAT_AES
+ ("aes", None),
+ // FEAT_BF16
+ ("bf16", None),
+ // FEAT_BTI
+ ("bti", None),
// FEAT_CRC
("crc", None),
- // FEAT_RAS
- ("ras", None),
- // FEAT_LSE
- ("lse", None),
- // FEAT_RDM
- ("rdm", None),
- // FEAT_RCPC
- ("rcpc", None),
- // FEAT_RCPC2
- ("rcpc2", None),
- // FEAT_DotProd
- ("dotprod", None),
- // FEAT_TME
- ("tme", None),
- // FEAT_FHM
- ("fhm", None),
// FEAT_DIT
("dit", None),
- // FEAT_FLAGM
- ("flagm", None),
- // FEAT_SSBS
- ("ssbs", None),
- // FEAT_SB
- ("sb", None),
- // FEAT_PAUTH (address authentication)
- ("paca", None),
- // FEAT_PAUTH (generic authentication)
- ("pacg", None),
+ // FEAT_DotProd
+ ("dotprod", None),
// FEAT_DPB
("dpb", None),
// FEAT_DPB2
("dpb2", None),
- // FEAT_SVE2
- ("sve2", None),
- // FEAT_SVE2_AES
- ("sve2-aes", None),
- // FEAT_SVE2_SM4
- ("sve2-sm4", None),
- // FEAT_SVE2_SHA3
- ("sve2-sha3", None),
- // FEAT_SVE2_BitPerm
- ("sve2-bitperm", None),
- // FEAT_FRINTTS
- ("frintts", None),
- // FEAT_I8MM
- ("i8mm", None),
// FEAT_F32MM
("f32mm", None),
// FEAT_F64MM
("f64mm", None),
- // FEAT_BF16
- ("bf16", None),
- // FEAT_RAND
- ("rand", None),
- // FEAT_BTI
- ("bti", None),
- // FEAT_MTE
- ("mte", None),
- // FEAT_JSCVT
- ("jsconv", None),
// FEAT_FCMA
("fcma", None),
- // FEAT_AES
- ("aes", None),
+ // FEAT_FHM
+ ("fhm", None),
+ // FEAT_FLAGM
+ ("flagm", None),
+ // FEAT_FP16
+ ("fp16", None),
+ // FEAT_FRINTTS
+ ("frintts", None),
+ // FEAT_I8MM
+ ("i8mm", None),
+ // FEAT_JSCVT
+ ("jsconv", None),
+ // FEAT_LOR
+ ("lor", None),
+ // FEAT_LSE
+ ("lse", None),
+ // FEAT_MTE
+ ("mte", None),
+ // FEAT_AdvSimd & FEAT_FP
+ ("neon", None),
+ // FEAT_PAUTH (address authentication)
+ ("paca", None),
+ // FEAT_PAUTH (generic authentication)
+ ("pacg", None),
+ // FEAT_PAN
+ ("pan", None),
+ // FEAT_PMUv3
+ ("pmuv3", None),
+ // FEAT_RAND
+ ("rand", None),
+ // FEAT_RAS
+ ("ras", None),
+ // FEAT_RCPC
+ ("rcpc", None),
+ // FEAT_RCPC2
+ ("rcpc2", None),
+ // FEAT_RDM
+ ("rdm", None),
+ // FEAT_SB
+ ("sb", None),
// FEAT_SHA1 & FEAT_SHA256
("sha2", None),
// FEAT_SHA512 & FEAT_SHA3
("sha3", None),
// FEAT_SM3 & FEAT_SM4
("sm4", None),
- // FEAT_PAN
- ("pan", None),
- // FEAT_LOR
- ("lor", None),
- // FEAT_VHE
- ("vh", None),
- // FEAT_PMUv3
- ("pmuv3", None),
// FEAT_SPE
("spe", None),
+ // FEAT_SSBS
+ ("ssbs", None),
+ // FEAT_SVE
+ ("sve", None),
+ // FEAT_SVE2
+ ("sve2", None),
+ // FEAT_SVE2_AES
+ ("sve2-aes", None),
+ // FEAT_SVE2_BitPerm
+ ("sve2-bitperm", None),
+ // FEAT_SVE2_SHA3
+ ("sve2-sha3", None),
+ // FEAT_SVE2_SM4
+ ("sve2-sm4", None),
+ // FEAT_TME
+ ("tme", None),
("v8.1a", Some(sym::aarch64_ver_target_feature)),
("v8.2a", Some(sym::aarch64_ver_target_feature)),
("v8.3a", Some(sym::aarch64_ver_target_feature)),
@@ -138,6 +139,9 @@ const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("v8.5a", Some(sym::aarch64_ver_target_feature)),
("v8.6a", Some(sym::aarch64_ver_target_feature)),
("v8.7a", Some(sym::aarch64_ver_target_feature)),
+ // FEAT_VHE
+ ("vh", None),
+ // tidy-alphabetical-end
];
const AARCH64_TIED_FEATURES: &[&[&str]] = &[
@@ -145,6 +149,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
];
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+ // tidy-alphabetical-start
("adx", None),
("aes", None),
("avx", None),
@@ -194,69 +199,80 @@ const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("xsavec", None),
("xsaveopt", None),
("xsaves", None),
+ // tidy-alphabetical-end
];
const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+ // tidy-alphabetical-start
("hvx", Some(sym::hexagon_target_feature)),
("hvx-length128b", Some(sym::hexagon_target_feature)),
+ // tidy-alphabetical-end
];
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+ // tidy-alphabetical-start
("altivec", Some(sym::powerpc_target_feature)),
("power8-altivec", Some(sym::powerpc_target_feature)),
- ("power9-altivec", Some(sym::powerpc_target_feature)),
("power8-vector", Some(sym::powerpc_target_feature)),
+ ("power9-altivec", Some(sym::powerpc_target_feature)),
("power9-vector", Some(sym::powerpc_target_feature)),
("vsx", Some(sym::powerpc_target_feature)),
+ // tidy-alphabetical-end
];
const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
+ // tidy-alphabetical-start
("fp64", Some(sym::mips_target_feature)),
("msa", Some(sym::mips_target_feature)),
("virt", Some(sym::mips_target_feature)),
+ // tidy-alphabetical-end
];
const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
- ("m", Some(sym::riscv_target_feature)),
+ // tidy-alphabetical-start
("a", Some(sym::riscv_target_feature)),
("c", Some(sym::riscv_target_feature)),
- ("f", Some(sym::riscv_target_feature)),
("d", Some(sym::riscv_target_feature)),
("e", Some(sym::riscv_target_feature)),
+ ("f", Some(sym::riscv_target_feature)),
+ ("m", Some(sym::riscv_target_feature)),
("v", Some(sym::riscv_target_feature)),
- ("zfinx", Some(sym::riscv_target_feature)),
- ("zdinx", Some(sym::riscv_target_feature)),
- ("zhinx", Some(sym::riscv_target_feature)),
- ("zhinxmin", Some(sym::riscv_target_feature)),
- ("zfh", Some(sym::riscv_target_feature)),
- ("zfhmin", Some(sym::riscv_target_feature)),
("zba", Some(sym::riscv_target_feature)),
("zbb", Some(sym::riscv_target_feature)),
("zbc", Some(sym::riscv_target_feature)),
- ("zbs", Some(sym::riscv_target_feature)),
("zbkb", Some(sym::riscv_target_feature)),
("zbkc", Some(sym::riscv_target_feature)),
("zbkx", Some(sym::riscv_target_feature)),
+ ("zbs", Some(sym::riscv_target_feature)),
+ ("zdinx", Some(sym::riscv_target_feature)),
+ ("zfh", Some(sym::riscv_target_feature)),
+ ("zfhmin", Some(sym::riscv_target_feature)),
+ ("zfinx", Some(sym::riscv_target_feature)),
+ ("zhinx", Some(sym::riscv_target_feature)),
+ ("zhinxmin", Some(sym::riscv_target_feature)),
+ ("zk", Some(sym::riscv_target_feature)),
+ ("zkn", Some(sym::riscv_target_feature)),
("zknd", Some(sym::riscv_target_feature)),
("zkne", Some(sym::riscv_target_feature)),
("zknh", Some(sym::riscv_target_feature)),
- ("zksed", Some(sym::riscv_target_feature)),
- ("zksh", Some(sym::riscv_target_feature)),
("zkr", Some(sym::riscv_target_feature)),
- ("zkn", Some(sym::riscv_target_feature)),
("zks", Some(sym::riscv_target_feature)),
- ("zk", Some(sym::riscv_target_feature)),
+ ("zksed", Some(sym::riscv_target_feature)),
+ ("zksh", Some(sym::riscv_target_feature)),
("zkt", Some(sym::riscv_target_feature)),
+ // tidy-alphabetical-end
];
const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
- ("simd128", None),
+ // tidy-alphabetical-start
("atomics", Some(sym::wasm_target_feature)),
- ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
("bulk-memory", Some(sym::wasm_target_feature)),
("mutable-globals", Some(sym::wasm_target_feature)),
+ ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
("reference-types", Some(sym::wasm_target_feature)),
("sign-ext", Some(sym::wasm_target_feature)),
+ ("simd128", None),
+ // tidy-alphabetical-end
];
const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
diff --git a/compiler/rustc_codegen_ssa/src/traits/abi.rs b/compiler/rustc_codegen_ssa/src/traits/abi.rs
index a00d78daf..60d8f2a9e 100644
--- a/compiler/rustc_codegen_ssa/src/traits/abi.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/abi.rs
@@ -1,8 +1,5 @@
use super::BackendTypes;
-use rustc_middle::ty::Ty;
-use rustc_target::abi::call::FnAbi;
pub trait AbiBuilderMethods<'tcx>: BackendTypes {
- fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value);
fn get_param(&mut self, index: usize) -> Self::Value;
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 779bd3ea2..87e347c61 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -134,8 +134,6 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
opt_level: config::OptLevel,
target_features: &[String],
) -> TargetMachineFactoryFn<Self>;
- fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str;
- fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str>;
fn spawn_thread<F, T>(_time_trace: bool, f: F) -> std::thread::JoinHandle<T>
where
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 10cf8948b..01408f39f 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -17,6 +17,7 @@ use crate::MemFlags;
use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
use rustc_middle::ty::Ty;
use rustc_span::Span;
+use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
use rustc_target::spec::HasTargetSpec;
@@ -71,6 +72,7 @@ pub trait BuilderMethods<'a, 'tcx>:
fn invoke(
&mut self,
llty: Self::Type,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: Self::Value,
args: &[Self::Value],
then: Self::BasicBlock,
@@ -133,8 +135,7 @@ pub trait BuilderMethods<'a, 'tcx>:
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
- fn dynamic_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
- fn array_alloca(&mut self, ty: Self::Type, len: Self::Value, align: Align) -> Self::Value;
+ fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value;
fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;
@@ -320,6 +321,7 @@ pub trait BuilderMethods<'a, 'tcx>:
fn call(
&mut self,
llty: Self::Type,
+ fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: Self::Value,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 7755e6793..450672fb9 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -5,7 +5,7 @@ use rustc_span::Span;
use rustc_target::abi::call::FnAbi;
pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
- /// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`,
+ /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
/// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
/// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
fn codegen_intrinsic_call(
diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs
index 4266e42ec..04e2b8796 100644
--- a/compiler/rustc_codegen_ssa/src/traits/misc.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs
@@ -15,12 +15,8 @@ pub trait MiscMethods<'tcx>: BackendTypes {
fn eh_personality(&self) -> Self::Value;
fn sess(&self) -> &Session;
fn codegen_unit(&self) -> &'tcx CodegenUnit<'tcx>;
- fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
- fn compiler_used_statics(&self) -> &RefCell<Vec<Self::Value>>;
fn set_frame_pointer_type(&self, llfn: Self::Function);
fn apply_target_cpu_attr(&self, llfn: Self::Function);
- fn create_used_variable(&self);
- fn create_compiler_used_variable(&self);
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>;
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 8158e8dd0..bdc6a91cf 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -5,7 +5,6 @@ use crate::common::TypeKind;
use crate::mir::place::PlaceRef;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{self, Ty};
-use rustc_span::DUMMY_SP;
use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
use rustc_target::abi::{AddressSpace, Integer};
@@ -75,16 +74,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
}
fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
- ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
+ ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all())
}
fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
- ty.is_freeze(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
+ ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all())
}
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
let param_env = ty::ParamEnv::reveal_all();
- if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) {
+ if ty.is_sized(self.tcx(), param_env) {
return false;
}
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index e54ec34f1..e0e8ffa89 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -9,7 +9,6 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
type Module: Send + Sync;
type TargetMachine;
type ModuleBuffer: ModuleBufferMethods;
- type Context: ?Sized;
type ThinData: Send + Sync;
type ThinBuffer: ThinBufferMethods;
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 32e8233a0..e09a6d1d6 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
tracing = "0.1"
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index 09d53331b..4977a5d6b 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -2,7 +2,6 @@ use std::error::Error;
use std::fmt;
use rustc_errors::Diagnostic;
-use rustc_hir as hir;
use rustc_middle::mir::AssertKind;
use rustc_middle::ty::{layout::LayoutError, query::TyCtxtAt, ConstInt};
use rustc_span::{Span, Symbol};
@@ -23,11 +22,7 @@ pub enum ConstEvalErrKind {
Abort(String),
}
-impl MachineStopType for ConstEvalErrKind {
- fn is_hard_err(&self) -> bool {
- matches!(self, Self::Panic { .. })
- }
-}
+impl MachineStopType for ConstEvalErrKind {}
// The errors become `MachineStop` with plain strings when being raised.
// `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to
@@ -69,7 +64,7 @@ pub struct ConstEvalErr<'tcx> {
impl<'tcx> ConstEvalErr<'tcx> {
/// Turn an interpreter error into something to report to the user.
/// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
- /// Should be called only if the error is actually going to to be reported!
+ /// Should be called only if the error is actually going to be reported!
pub fn new<'mir, M: Machine<'mir, 'tcx>>(
ecx: &InterpCx<'mir, 'tcx, M>,
error: InterpErrorInfo<'tcx>,
@@ -87,48 +82,10 @@ impl<'tcx> ConstEvalErr<'tcx> {
ConstEvalErr { error: error.into_kind(), stacktrace, span }
}
- pub fn struct_error(
- &self,
- tcx: TyCtxtAt<'tcx>,
- message: &str,
- decorate: impl FnOnce(&mut Diagnostic),
- ) -> ErrorHandled {
- self.struct_generic(tcx, message, decorate, None)
- }
-
pub fn report_as_error(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
self.struct_error(tcx, message, |_| {})
}
- pub fn report_as_lint(
- &self,
- tcx: TyCtxtAt<'tcx>,
- message: &str,
- lint_root: hir::HirId,
- span: Option<Span>,
- ) -> ErrorHandled {
- self.struct_generic(
- tcx,
- message,
- |lint: &mut Diagnostic| {
- // Apply the span.
- if let Some(span) = span {
- let primary_spans = lint.span.primary_spans().to_vec();
- // point at the actual error as the primary span
- lint.replace_span_with(span);
- // point to the `const` statement as a secondary span
- // they don't have any label
- for sp in primary_spans {
- if sp != span {
- lint.span_label(sp, "");
- }
- }
- }
- },
- Some(lint_root),
- )
- }
-
/// Create a diagnostic for this const eval error.
///
/// Sets the message passed in via `message` and adds span labels with detailed error
@@ -137,13 +94,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
///
/// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
/// (Except that for some errors, we ignore all that -- see `must_error` below.)
- #[instrument(skip(self, tcx, decorate, lint_root), level = "debug")]
- fn struct_generic(
+ #[instrument(skip(self, tcx, decorate), level = "debug")]
+ pub fn struct_error(
&self,
tcx: TyCtxtAt<'tcx>,
message: &str,
decorate: impl FnOnce(&mut Diagnostic),
- lint_root: Option<hir::HirId>,
) -> ErrorHandled {
let finish = |err: &mut Diagnostic, span_msg: Option<String>| {
trace!("reporting const eval failure at {:?}", self.span);
@@ -224,27 +180,9 @@ impl<'tcx> ConstEvalErr<'tcx> {
let err_msg = self.error.to_string();
- // Regular case - emit a lint.
- if let Some(lint_root) = lint_root {
- // Report as lint.
- let hir_id =
- self.stacktrace.iter().rev().find_map(|frame| frame.lint_root).unwrap_or(lint_root);
- tcx.struct_span_lint_hir(
- rustc_session::lint::builtin::CONST_ERR,
- hir_id,
- tcx.span,
- |lint| {
- let mut lint = lint.build(message);
- finish(&mut lint, Some(err_msg));
- lint.emit();
- },
- );
- ErrorHandled::Linted
- } else {
- // Report as hard error.
- let mut err = struct_error(tcx, message);
- finish(&mut err, Some(err_msg));
- ErrorHandled::Reported(err.emit())
- }
+ // Report as hard error.
+ let mut err = struct_error(tcx, message);
+ finish(&mut err, Some(err_msg));
+ ErrorHandled::Reported(err.emit())
}
}
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 a2f14e753..1b1052fdf 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -13,7 +13,7 @@ use rustc_middle::mir::pretty::display_allocation;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, subst::Subst, TyCtxt};
+use rustc_middle::ty::{self, TyCtxt};
use rustc_span::source_map::Span;
use rustc_target::abi::{self, Abi};
use std::borrow::Cow;
@@ -317,45 +317,23 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
Err(error) => {
let err = ConstEvalErr::new(&ecx, error, None);
- // Some CTFE errors raise just a lint, not a hard error; see
- // <https://github.com/rust-lang/rust/issues/71800>.
- let is_hard_err = if let Some(def) = def.as_local() {
- // (Associated) consts only emit a lint, since they might be unused.
- !matches!(tcx.def_kind(def.did.to_def_id()), DefKind::Const | DefKind::AssocConst)
- // check if the inner InterpError is hard
- || err.error.is_hard_err()
+ let msg = if is_static {
+ Cow::from("could not evaluate static initializer")
} else {
- // use of broken constant from other crate: always an error
- true
- };
-
- if is_hard_err {
- let msg = if is_static {
- Cow::from("could not evaluate static initializer")
+ // If the current item has generics, we'd like to enrich the message with the
+ // instance and its substs: to show the actual compile-time values, in addition to
+ // the expression, leading to the const eval error.
+ let instance = &key.value.instance;
+ if !instance.substs.is_empty() {
+ let instance = with_no_trimmed_paths!(instance.to_string());
+ let msg = format!("evaluation of `{}` failed", instance);
+ Cow::from(msg)
} else {
- // If the current item has generics, we'd like to enrich the message with the
- // instance and its substs: to show the actual compile-time values, in addition to
- // the expression, leading to the const eval error.
- let instance = &key.value.instance;
- if !instance.substs.is_empty() {
- let instance = with_no_trimmed_paths!(instance.to_string());
- let msg = format!("evaluation of `{}` failed", instance);
- Cow::from(msg)
- } else {
- Cow::from("evaluation of constant value failed")
- }
- };
+ Cow::from("evaluation of constant value failed")
+ }
+ };
- Err(err.report_as_error(ecx.tcx.at(err.span), &msg))
- } else {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def.as_local().unwrap().did);
- Err(err.report_as_lint(
- tcx.at(tcx.def_span(def.did)),
- "any use of this value will cause an error",
- hir_id,
- Some(err.span),
- ))
- }
+ Err(err.report_as_error(ecx.tcx.at(err.span), &msg))
}
Ok(mplace) => {
// Since evaluation had no errors, validate the resulting constant.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index e5acacd91..35d58d2f6 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -2,10 +2,10 @@ use rustc_hir::def::DefKind;
use rustc_middle::mir;
use rustc_middle::ty::{self, Ty, TyCtxt};
use std::borrow::Borrow;
-use std::collections::hash_map::Entry;
use std::hash::Hash;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::IndexEntry;
use std::fmt;
use rustc_ast::Mutability;
@@ -107,18 +107,18 @@ impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
}
}
-impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
+impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {
#[inline(always)]
fn contains_key<Q: ?Sized + Hash + Eq>(&mut self, k: &Q) -> bool
where
K: Borrow<Q>,
{
- FxHashMap::contains_key(self, k)
+ FxIndexMap::contains_key(self, k)
}
#[inline(always)]
fn insert(&mut self, k: K, v: V) -> Option<V> {
- FxHashMap::insert(self, k, v)
+ FxIndexMap::insert(self, k, v)
}
#[inline(always)]
@@ -126,7 +126,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
where
K: Borrow<Q>,
{
- FxHashMap::remove(self, k)
+ FxIndexMap::remove(self, k)
}
#[inline(always)]
@@ -148,8 +148,8 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
#[inline(always)]
fn get_mut_or<E>(&mut self, k: K, vacant: impl FnOnce() -> Result<V, E>) -> Result<&mut V, E> {
match self.entry(k) {
- Entry::Occupied(e) => Ok(e.into_mut()),
- Entry::Vacant(e) => {
+ IndexEntry::Occupied(e) => Ok(e.into_mut()),
+ IndexEntry::Vacant(e) => {
let v = vacant()?;
Ok(e.insert(v))
}
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index d9c4ae4d5..1c33e7845 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -100,10 +100,10 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
val: mir::ConstantKind<'tcx>,
-) -> InterpResult<'tcx, mir::DestructuredMirConstant<'tcx>> {
+) -> InterpResult<'tcx, mir::DestructuredConstant<'tcx>> {
trace!("destructure_mir_constant: {:?}", val);
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
- let op = ecx.mir_const_to_op(&val, None)?;
+ let op = ecx.const_to_op(&val, None)?;
// We go to `usize` as we cannot allocate anything bigger anyway.
let (field_count, variant, down) = match val.ty().kind() {
@@ -129,7 +129,7 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
.collect::<InterpResult<'tcx, Vec<_>>>()?;
let fields = tcx.arena.alloc_from_iter(fields_iter);
- Ok(mir::DestructuredMirConstant { variant, fields })
+ Ok(mir::DestructuredConstant { variant, fields })
}
#[instrument(skip(tcx), level = "debug")]
@@ -139,7 +139,7 @@ pub(crate) fn deref_mir_constant<'tcx>(
val: mir::ConstantKind<'tcx>,
) -> mir::ConstantKind<'tcx> {
let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
- let op = ecx.mir_const_to_op(&val, None).unwrap();
+ let op = ecx.const_to_op(&val, None).unwrap();
let mplace = ecx.deref_operand(&op).unwrap();
if let Some(alloc_id) = mplace.ptr.provenance {
assert_eq!(
diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
index a964fe846..f4da11883 100644
--- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs
+++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs
@@ -212,7 +212,7 @@ fn create_pointee_place<'tcx>(
) -> MPlaceTy<'tcx> {
let tcx = ecx.tcx.tcx;
- if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty()) {
+ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty()) {
// We need to create `Allocation`s for custom DSTs
let (unsized_inner_ty, num_elems) = get_info_on_unsized_field(ty, valtree, tcx);
@@ -398,7 +398,7 @@ fn valtree_into_mplace<'tcx>(
let mut place_inner = match ty.kind() {
ty::Str | ty::Slice(_) => ecx.mplace_index(&place, i as u64).unwrap(),
- _ if !ty.is_sized(ecx.tcx, ty::ParamEnv::empty())
+ _ if !ty.is_sized(*ecx.tcx, ty::ParamEnv::empty())
&& i == branches.len() - 1 =>
{
// Note: For custom DSTs we need to manually process the last unsized field.
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index c3547cb3a..4b0550767 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,146 +1,146 @@
use rustc_hir::ConstContext;
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unstable_in_stable)]
+#[derive(Diagnostic)]
+#[diag(const_eval_unstable_in_stable)]
pub(crate) struct UnstableInStable {
pub gate: String,
#[primary_span]
pub span: Span,
#[suggestion(
- const_eval::unstable_sugg,
+ unstable_sugg,
code = "#[rustc_const_unstable(feature = \"...\", issue = \"...\")]\n",
applicability = "has-placeholders"
)]
#[suggestion(
- const_eval::bypass_sugg,
+ bypass_sugg,
code = "#[rustc_allow_const_fn_unstable({gate})]\n",
applicability = "has-placeholders"
)]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::thread_local_access, code = "E0625")]
+#[derive(Diagnostic)]
+#[diag(const_eval_thread_local_access, code = "E0625")]
pub(crate) struct NonConstOpErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::static_access, code = "E0013")]
+#[derive(Diagnostic)]
+#[diag(const_eval_static_access, code = "E0013")]
#[help]
pub(crate) struct StaticAccessErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(const_eval::teach_note)]
- #[help(const_eval::teach_help)]
+ #[note(teach_note)]
+ #[help(teach_help)]
pub teach: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::raw_ptr_to_int)]
+#[derive(Diagnostic)]
+#[diag(const_eval_raw_ptr_to_int)]
#[note]
-#[note(const_eval::note2)]
+#[note(note2)]
pub(crate) struct RawPtrToIntErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::raw_ptr_comparison)]
+#[derive(Diagnostic)]
+#[diag(const_eval_raw_ptr_comparison)]
#[note]
pub(crate) struct RawPtrComparisonErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::panic_non_str)]
+#[derive(Diagnostic)]
+#[diag(const_eval_panic_non_str)]
pub(crate) struct PanicNonStrErr {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::mut_deref, code = "E0658")]
+#[derive(Diagnostic)]
+#[diag(const_eval_mut_deref, code = "E0658")]
pub(crate) struct MutDerefErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::transient_mut_borrow, code = "E0658")]
+#[derive(Diagnostic)]
+#[diag(const_eval_transient_mut_borrow, code = "E0658")]
pub(crate) struct TransientMutBorrowErr {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::transient_mut_borrow_raw, code = "E0658")]
+#[derive(Diagnostic)]
+#[diag(const_eval_transient_mut_borrow_raw, code = "E0658")]
pub(crate) struct TransientMutBorrowErrRaw {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::max_num_nodes_in_const)]
+#[derive(Diagnostic)]
+#[diag(const_eval_max_num_nodes_in_const)]
pub(crate) struct MaxNumNodesInConstErr {
#[primary_span]
pub span: Span,
pub global_const_id: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_fn_pointer_call)]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_fn_pointer_call)]
pub(crate) struct UnallowedFnPointerCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unstable_const_fn)]
+#[derive(Diagnostic)]
+#[diag(const_eval_unstable_const_fn)]
pub(crate) struct UnstableConstFn {
#[primary_span]
pub span: Span,
pub def_path: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_mutable_refs, code = "E0764")]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_mutable_refs, code = "E0764")]
pub(crate) struct UnallowedMutableRefs {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(const_eval::teach_note)]
+ #[note(teach_note)]
pub teach: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_mutable_refs_raw, code = "E0764")]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_mutable_refs_raw, code = "E0764")]
pub(crate) struct UnallowedMutableRefsRaw {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
- #[note(const_eval::teach_note)]
+ #[note(teach_note)]
pub teach: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::non_const_fmt_macro_call, code = "E0015")]
+#[derive(Diagnostic)]
+#[diag(const_eval_non_const_fmt_macro_call, code = "E0015")]
pub(crate) struct NonConstFmtMacroCall {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::non_const_fn_call, code = "E0015")]
+#[derive(Diagnostic)]
+#[diag(const_eval_non_const_fn_call, code = "E0015")]
pub(crate) struct NonConstFnCall {
#[primary_span]
pub span: Span,
@@ -148,35 +148,35 @@ pub(crate) struct NonConstFnCall {
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_op_in_const_context)]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_op_in_const_context)]
pub(crate) struct UnallowedOpInConstContext {
#[primary_span]
pub span: Span,
pub msg: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_heap_allocations, code = "E0010")]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_heap_allocations, code = "E0010")]
pub(crate) struct UnallowedHeapAllocations {
#[primary_span]
#[label]
pub span: Span,
pub kind: ConstContext,
- #[note(const_eval::teach_note)]
+ #[note(teach_note)]
pub teach: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::unallowed_inline_asm, code = "E0015")]
+#[derive(Diagnostic)]
+#[diag(const_eval_unallowed_inline_asm, code = "E0015")]
pub(crate) struct UnallowedInlineAsm {
#[primary_span]
pub span: Span,
pub kind: ConstContext,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::interior_mutable_data_refer, code = "E0492")]
+#[derive(Diagnostic)]
+#[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
pub(crate) struct InteriorMutableDataRefer {
#[primary_span]
#[label]
@@ -184,12 +184,12 @@ pub(crate) struct InteriorMutableDataRefer {
#[help]
pub opt_help: Option<()>,
pub kind: ConstContext,
- #[note(const_eval::teach_note)]
+ #[note(teach_note)]
pub teach: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(const_eval::interior_mutability_borrow)]
+#[derive(Diagnostic)]
+#[diag(const_eval_interior_mutability_borrow)]
pub(crate) struct InteriorMutabilityBorrow {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index cbe985480..269ae15d4 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -43,9 +43,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_immediate(res, dest)?;
}
- Misc => {
+ IntToInt | IntToFloat => {
let src = self.read_immediate(src)?;
- let res = self.misc_cast(&src, cast_ty)?;
+ let res = self.int_to_int_or_float(&src, cast_ty)?;
+ self.write_immediate(res, dest)?;
+ }
+
+ FloatToFloat | FloatToInt => {
+ let src = self.read_immediate(src)?;
+ let res = self.float_to_float_or_int(&src, cast_ty)?;
+ self.write_immediate(res, dest)?;
+ }
+
+ FnPtrToPtr | PtrToPtr => {
+ let src = self.read_immediate(&src)?;
+ let res = self.ptr_to_ptr(&src, cast_ty)?;
self.write_immediate(res, dest)?;
}
@@ -126,13 +138,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(())
}
- pub fn misc_cast(
- &mut self,
+ /// Handles 'IntToInt' and 'IntToFloat' casts.
+ pub fn int_to_int_or_float(
+ &self,
+ src: &ImmTy<'tcx, M::Provenance>,
+ cast_ty: Ty<'tcx>,
+ ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
+ assert!(src.layout.ty.is_integral() || src.layout.ty.is_char() || src.layout.ty.is_bool());
+ assert!(cast_ty.is_floating_point() || cast_ty.is_integral() || cast_ty.is_char());
+
+ Ok(self.cast_from_int_like(src.to_scalar(), src.layout, cast_ty)?.into())
+ }
+
+ /// Handles 'FloatToFloat' and 'FloatToInt' casts.
+ pub fn float_to_float_or_int(
+ &self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
use rustc_type_ir::sty::TyKind::*;
- trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, cast_ty);
match src.layout.ty.kind() {
// Floating point
@@ -142,47 +166,42 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Float(FloatTy::F64) => {
return Ok(self.cast_from_float(src.to_scalar().to_f64()?, cast_ty).into());
}
- // The rest is integer/pointer-"like", including fn ptr casts
- _ => assert!(
- src.layout.ty.is_bool()
- || src.layout.ty.is_char()
- || src.layout.ty.is_integral()
- || src.layout.ty.is_any_ptr(),
- "Unexpected cast from type {:?}",
- src.layout.ty
- ),
+ _ => {
+ bug!("Can't cast 'Float' type into {:?}", cast_ty);
+ }
}
+ }
- // # First handle non-scalar source values.
-
+ /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
+ pub fn ptr_to_ptr(
+ &self,
+ src: &ImmTy<'tcx, M::Provenance>,
+ cast_ty: Ty<'tcx>,
+ ) -> InterpResult<'tcx, Immediate<M::Provenance>> {
+ assert!(src.layout.ty.is_any_ptr());
+ assert!(cast_ty.is_unsafe_ptr());
// Handle casting any ptr to raw ptr (might be a fat ptr).
- if src.layout.ty.is_any_ptr() && cast_ty.is_unsafe_ptr() {
- let dest_layout = self.layout_of(cast_ty)?;
- if dest_layout.size == src.layout.size {
- // Thin or fat pointer that just hast the ptr kind of target type changed.
- return Ok(**src);
- } else {
- // Casting the metadata away from a fat ptr.
- assert_eq!(src.layout.size, 2 * self.pointer_size());
- assert_eq!(dest_layout.size, self.pointer_size());
- assert!(src.layout.ty.is_unsafe_ptr());
- return match **src {
- Immediate::ScalarPair(data, _) => Ok(data.into()),
- Immediate::Scalar(..) => span_bug!(
- self.cur_span(),
- "{:?} input to a fat-to-thin cast ({:?} -> {:?})",
- *src,
- src.layout.ty,
- cast_ty
- ),
- Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
- };
- }
+ let dest_layout = self.layout_of(cast_ty)?;
+ if dest_layout.size == src.layout.size {
+ // Thin or fat pointer that just hast the ptr kind of target type changed.
+ return Ok(**src);
+ } else {
+ // Casting the metadata away from a fat ptr.
+ assert_eq!(src.layout.size, 2 * self.pointer_size());
+ assert_eq!(dest_layout.size, self.pointer_size());
+ assert!(src.layout.ty.is_unsafe_ptr());
+ return match **src {
+ Immediate::ScalarPair(data, _) => Ok(data.into()),
+ Immediate::Scalar(..) => span_bug!(
+ self.cur_span(),
+ "{:?} input to a fat-to-thin cast ({:?} -> {:?})",
+ *src,
+ src.layout.ty,
+ cast_ty
+ ),
+ Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
+ };
}
-
- // # The remaining source values are scalar and "int-like".
- let scalar = src.to_scalar();
- Ok(self.cast_from_int_like(scalar, src.layout, cast_ty)?.into())
}
pub fn pointer_expose_address_cast(
@@ -203,7 +222,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
pub fn pointer_from_exposed_address_cast(
- &mut self,
+ &self,
src: &ImmTy<'tcx, M::Provenance>,
cast_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Immediate<M::Provenance>> {
@@ -220,6 +239,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Ok(Scalar::from_maybe_pointer(ptr, self).into())
}
+ /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input
+ /// type (basically everything with a scalar layout) to int/float/char types.
pub fn cast_from_int_like(
&self,
scalar: Scalar<M::Provenance>, // input value (there is no ScalarTy so we separate data+layout)
@@ -259,6 +280,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
})
}
+ /// Low-level cast helper function. Converts an apfloat `f` into int or float types.
fn cast_from_float<F>(&self, f: F, dest_ty: Ty<'tcx>) -> Scalar<M::Provenance>
where
F: Float + Into<Scalar<M::Provenance>> + FloatConvert<Single> + FloatConvert<Double>,
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index d37eaeed0..a9063ad31 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -258,6 +258,9 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
{
write!(f, "inside closure")?;
} else {
+ // Note: this triggers a `good_path_bug` state, which means that if we ever get here
+ // we must emit a diagnostic. We should never display a `FrameInfo` unless we
+ // actually want to emit a warning or error to the user.
write!(f, "inside `{}`", self.instance)?;
}
if !self.span.is_dummy() {
@@ -465,7 +468,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
#[inline]
pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
- ty.is_freeze(self.tcx, self.param_env)
+ ty.is_freeze(*self.tcx, self.param_env)
}
pub fn load_mir(
@@ -683,11 +686,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.stack_mut().push(frame);
// Make sure all the constants required by this frame evaluate successfully (post-monomorphization check).
- for const_ in &body.required_consts {
- let span = const_.span;
- let const_ =
- self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?;
- self.mir_const_to_op(&const_, None).map_err(|err| {
+ for ct in &body.required_consts {
+ let span = ct.span;
+ let ct = self.subst_from_current_frame_and_normalize_erasing_regions(ct.literal)?;
+ self.const_to_op(&ct, None).map_err(|err| {
// If there was an error, set the span of the current frame to this constant.
// Avoiding doing this when evaluation succeeds.
self.frame_mut().loc = Err(span);
@@ -929,11 +931,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
#[must_use]
- pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
+ pub fn generate_stacktrace_from_stack(
+ stack: &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>],
+ ) -> Vec<FrameInfo<'tcx>> {
let mut frames = Vec::new();
// This deliberately does *not* honor `requires_caller_location` since it is used for much
// more than just panics.
- for frame in self.stack().iter().rev() {
+ for frame in stack.iter().rev() {
let lint_root = frame.current_source_info().and_then(|source_info| {
match &frame.body.source_scopes[source_info.scope].local_data {
mir::ClearCrossCrate::Set(data) => Some(data.lint_root),
@@ -947,6 +951,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
trace!("generate stacktrace: {:#?}", frames);
frames
}
+
+ #[must_use]
+ pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
+ Self::generate_stacktrace_from_stack(self.stack())
+ }
}
#[doc(hidden)]
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 24dbc7695..6809a42dc 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -15,7 +15,7 @@
//! that contains allocations whose mutability we cannot identify.)
use super::validity::RefTracking;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_middle::mir::interpret::InterpResult;
@@ -37,7 +37,7 @@ pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
ExtraFnVal = !,
FrameExtra = (),
AllocExtra = (),
- MemoryMap = FxHashMap<AllocId, (MemoryKind<T>, Allocation)>,
+ MemoryMap = FxIndexMap<AllocId, (MemoryKind<T>, Allocation)>,
>;
struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>> {
@@ -47,7 +47,7 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_ev
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>,
/// A list of all encountered allocations. After type-based interning, we traverse this list to
/// also intern allocations that are only referenced by a raw pointer or inside a union.
- leftover_allocations: &'rt mut FxHashSet<AllocId>,
+ leftover_allocations: &'rt mut FxIndexSet<AllocId>,
/// The root kind of the value that we're looking at. This field is never mutated for a
/// particular allocation. It is primarily used to make as many allocations as possible
/// read-only so LLVM can place them in const memory.
@@ -79,7 +79,7 @@ struct IsStaticOrFn;
/// to account for (e.g. for vtables).
fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval::MemoryKind>>(
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
- leftover_allocations: &'rt mut FxHashSet<AllocId>,
+ leftover_allocations: &'rt mut FxIndexSet<AllocId>,
alloc_id: AllocId,
mode: InternMode,
ty: Option<Ty<'tcx>>,
@@ -114,7 +114,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
if let InternMode::Static(mutability) = mode {
// For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
// no interior mutability.
- let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env));
+ let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env));
// For statics, allocation mutability is the combination of place mutability and
// type mutability.
// The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@@ -332,8 +332,6 @@ pub enum InternKind {
///
/// This *cannot raise an interpreter error*. Doing so is left to validation, which
/// tracks where in the value we are and thus can show much better error messages.
-/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures
-/// are hard errors.
#[instrument(level = "debug", skip(ecx))]
pub fn intern_const_alloc_recursive<
'mir,
@@ -357,7 +355,7 @@ pub fn intern_const_alloc_recursive<
// `leftover_allocations` collects *all* allocations we see, because some might not
// be available in a typed way. They get interned at the end.
let mut ref_tracking = RefTracking::empty();
- let leftover_allocations = &mut FxHashSet::default();
+ let leftover_allocations = &mut FxIndexSet::default();
// start with the outermost allocation
intern_shallow(
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 91f4f0425..0e3867557 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs
@@ -4,7 +4,6 @@ use rustc_ast::Mutability;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::ty::subst::Subst;
use rustc_span::{Span, Symbol};
use crate::interpret::{
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
index 7e4c5fcb0..ffdb8de5b 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics/type_name.rs
@@ -4,7 +4,7 @@ use rustc_hir::definitions::DisambiguatedDefPathData;
use rustc_middle::mir::interpret::{Allocation, ConstAllocation};
use rustc_middle::ty::{
self,
- print::{PrettyPrinter, Print, Printer},
+ print::{with_no_verbose_constants, PrettyPrinter, Print, Printer},
subst::{GenericArg, GenericArgKind},
Ty, TyCtxt,
};
@@ -190,7 +190,9 @@ impl Write for AbsolutePathPrinter<'_> {
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
- let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
+ let path = with_no_verbose_constants!(
+ AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path
+ );
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
tcx.intern_const_alloc(alloc)
}
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 530e252b7..351152eba 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -426,7 +426,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
type ExtraFnVal = !;
type MemoryMap =
- rustc_data_structures::fx::FxHashMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
+ rustc_data_structures::fx::FxIndexMap<AllocId, (MemoryKind<Self::MemoryKind>, Allocation)>;
const GLOBAL_KIND: Option<Self::MemoryKind> = None; // no copying of globals from `tcx` to machine memory
type AllocExtra = ();
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index ed155fbfe..e5e015c1e 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -794,7 +794,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
todo.extend(static_roots);
while let Some(id) = todo.pop() {
if reachable.insert(id) {
- // This is a new allocation, add the allocation it points to to `todo`.
+ // This is a new allocation, add the allocation it points to `todo`.
if let Some((_, alloc)) = self.memory.alloc_map.get(id) {
todo.extend(
alloc.provenance().values().filter_map(|prov| prov.get_alloc_id()),
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 0e3959b61..0c212cf59 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// * During ConstProp, with `TooGeneric` or since the `required_consts` were not all
// checked yet.
// * During CTFE, since promoteds in `const`/`static` initializer bodies can fail.
- self.mir_const_to_op(&val, layout)?
+ self.const_to_op(&val, layout)?
}
};
trace!("{:?}: {:?}", mir_op, *op);
@@ -549,45 +549,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
ops.iter().map(|op| self.eval_operand(op, None)).collect()
}
- // Used when the miri-engine runs into a constant and for extracting information from constants
- // in patterns via the `const_eval` module
- /// The `val` and `layout` are assumed to already be in our interpreter
- /// "universe" (param_env).
pub fn const_to_op(
&self,
- c: ty::Const<'tcx>,
- layout: Option<TyAndLayout<'tcx>>,
- ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
- match c.kind() {
- ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => throw_inval!(TooGeneric),
- ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
- throw_inval!(AlreadyReported(reported))
- }
- ty::ConstKind::Unevaluated(uv) => {
- // NOTE: We evaluate to a `ValTree` here as a check to ensure
- // we're working with valid constants, even though we never need it.
- let instance = self.resolve(uv.def, uv.substs)?;
- let cid = GlobalId { instance, promoted: None };
- let _valtree = self
- .tcx
- .eval_to_valtree(self.param_env.and(cid))?
- .unwrap_or_else(|| bug!("unable to create ValTree for {:?}", uv));
-
- Ok(self.eval_to_allocation(cid)?.into())
- }
- ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
- span_bug!(self.cur_span(), "const_to_op: Unexpected ConstKind {:?}", c)
- }
- ty::ConstKind::Value(valtree) => {
- let ty = c.ty();
- let const_val = self.tcx.valtree_to_const_val((ty, valtree));
- self.const_val_to_op(const_val, ty, layout)
- }
- }
- }
-
- pub fn mir_const_to_op(
- &self,
val: &mir::ConstantKind<'tcx>,
layout: Option<TyAndLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
@@ -599,7 +562,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// manually normalized.
let val = self.tcx.normalize_erasing_regions(self.param_env, *val);
match val {
- mir::ConstantKind::Ty(ct) => self.const_to_op(ct, layout),
+ mir::ConstantKind::Ty(ct) => {
+ match ct.kind() {
+ ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(..) => {
+ throw_inval!(TooGeneric)
+ }
+ ty::ConstKind::Error(DelaySpanBugEmitted { reported, .. }) => {
+ throw_inval!(AlreadyReported(reported))
+ }
+ ty::ConstKind::Unevaluated(uv) => {
+ // NOTE: We evaluate to a `ValTree` here as a check to ensure
+ // we're working with valid constants, even though we never need it.
+ let instance = self.resolve(uv.def, uv.substs)?;
+ let cid = GlobalId { instance, promoted: None };
+ let _valtree = self
+ .tcx
+ .eval_to_valtree(self.param_env.and(cid))?
+ .unwrap_or_else(|| bug!("unable to create ValTree for {uv:?}"));
+
+ Ok(self.eval_to_allocation(cid)?.into())
+ }
+ ty::ConstKind::Bound(..) | ty::ConstKind::Infer(..) => {
+ span_bug!(self.cur_span(), "unexpected ConstKind in ctfe: {ct:?}")
+ }
+ ty::ConstKind::Value(valtree) => {
+ let ty = ct.ty();
+ let const_val = self.tcx.valtree_to_const_val((ty, valtree));
+ self.const_val_to_op(const_val, ty, layout)
+ }
+ }
+ }
mir::ConstantKind::Val(val, ty) => self.const_val_to_op(val, ty, layout),
mir::ConstantKind::Unevaluated(uv, _) => {
let instance = self.resolve(uv.def, uv.substs)?;
@@ -799,13 +791,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
// Some nodes are used a lot. Make sure they don't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(Immediate, 48);
static_assert_size!(ImmTy<'_>, 64);
static_assert_size!(Operand, 56);
static_assert_size!(OpTy<'_>, 80);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index b32889290..b0625b5f4 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -280,7 +280,7 @@ 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> {
+ pub fn assert_mem_place(&self) -> MPlaceTy<'tcx, Prov> {
self.try_as_mplace().unwrap()
}
}
@@ -640,11 +640,17 @@ where
// avoid force_allocation.
let src = match self.read_immediate_raw(src)? {
Ok(src_val) => {
- assert!(!src.layout.is_unsized(), "cannot copy unsized immediates");
- assert!(
- !dest.layout.is_unsized(),
- "the src is sized, so the dest must also be sized"
- );
+ // FIXME(const_prop): Const-prop can possibly evaluate an
+ // unsized copy operation when it thinks that the type is
+ // actually sized, due to a trivially false where-clause
+ // predicate like `where Self: Sized` with `Self = dyn Trait`.
+ // See #102553 for an example of such a predicate.
+ if src.layout.is_unsized() {
+ throw_inval!(SizeOfUnsizedType(src.layout.ty));
+ }
+ if dest.layout.is_unsized() {
+ throw_inval!(SizeOfUnsizedType(dest.layout.ty));
+ }
assert_eq!(src.layout.size, dest.layout.size);
// Yay, we got a value that we can write directly.
return if layout_compat {
@@ -886,12 +892,11 @@ where
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
- static_assert_size!(MemPlaceMeta, 24);
+ // tidy-alphabetical-start
static_assert_size!(MemPlace, 40);
+ static_assert_size!(MemPlaceMeta, 24);
static_assert_size!(MPlaceTy<'_>, 64);
- #[cfg(not(bootstrap))]
static_assert_size!(Place, 40);
- #[cfg(not(bootstrap))]
static_assert_size!(PlaceTy<'_>, 64);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index 77da8f104..6b2e2bb8a 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -350,6 +350,11 @@ where
) -> InterpResult<'tcx, PlaceTy<'tcx, M::Provenance>> {
use rustc_middle::mir::ProjectionElem::*;
Ok(match proj_elem {
+ OpaqueCast(ty) => {
+ let mut place = base.clone();
+ place.layout = self.layout_of(ty)?;
+ place
+ }
Field(field, _) => self.place_field(base, field.index())?,
Downcast(_, variant) => self.place_downcast(base, variant)?,
Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
@@ -374,6 +379,11 @@ where
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
use rustc_middle::mir::ProjectionElem::*;
Ok(match proj_elem {
+ OpaqueCast(ty) => {
+ let mut op = base.clone();
+ op.layout = self.layout_of(ty)?;
+ op
+ }
Field(field, _) => self.operand_field(base, field.index())?,
Downcast(_, variant) => self.operand_downcast(base, variant)?,
Deref => self.deref_operand(base)?.into(),
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 50a82aa0e..57e40e168 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -35,7 +35,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
assert_eq!(discr.layout.ty, switch_ty);
// Branch to the `otherwise` case by default, if no match is found.
- assert!(!targets.iter().is_empty());
let mut target_block = targets.otherwise();
for (const_int, target) in targets.iter() {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 14aaee6ac..8aa56c275 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -15,7 +15,6 @@ use rustc_middle::mir::interpret::InterpError;
use rustc_middle::ty;
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
use rustc_span::symbol::{sym, Symbol};
-use rustc_span::DUMMY_SP;
use rustc_target::abi::{Abi, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange};
use std::hash::Hash;
@@ -56,7 +55,7 @@ macro_rules! throw_validation_failure {
/// This lets you use the patterns as a kind of validation list, asserting which errors
/// can possibly happen:
///
-/// ```
+/// ```ignore(illustrative)
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "some failure" },
/// });
@@ -65,7 +64,7 @@ macro_rules! throw_validation_failure {
/// The patterns must be of type `UndefinedBehaviorInfo`.
/// An additional expected parameter can also be added to the failure message:
///
-/// ```
+/// ```ignore(illustrative)
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "some failure" } expected { "something that wasn't a failure" },
/// });
@@ -74,7 +73,7 @@ macro_rules! throw_validation_failure {
/// An additional nicety is that both parameters actually take format args, so you can just write
/// the format string in directly:
///
-/// ```
+/// ```ignore(illustrative)
/// let v = try_validation!(some_fn(), some_path, {
/// Foo | Bar | Baz => { "{:?}", some_failure } expected { "{}", expected_value },
/// });
@@ -726,7 +725,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
) -> InterpResult<'tcx> {
// Special check preventing `UnsafeCell` inside unions in the inner part of constants.
if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) {
- if !op.layout.ty.is_freeze(self.ecx.tcx.at(DUMMY_SP), self.ecx.param_env) {
+ if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
}
}
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 9f47d302a..443c01fdb 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -10,7 +10,6 @@ Rust MIR: a lowered representation of Rust.
#![feature(decl_macro)]
#![feature(exact_size_is_empty)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(slice_ptr_get)]
@@ -21,9 +20,8 @@ Rust MIR: a lowered representation of Rust.
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
-#![feature(is_some_with)]
+#![feature(is_some_and)]
#![recursion_limit = "256"]
-#![allow(rustc::potential_query_instability)]
#[macro_use]
extern crate tracing;
@@ -33,7 +31,6 @@ extern crate rustc_middle;
pub mod const_eval;
mod errors;
pub mod interpret;
-mod might_permit_raw_init;
pub mod transform;
pub mod util;
@@ -62,7 +59,6 @@ pub fn provide(providers: &mut Providers) {
const_eval::deref_mir_constant(tcx, param_env, value)
};
providers.permits_uninit_init =
- |tcx, ty| might_permit_raw_init::might_permit_raw_init(tcx, ty, InitKind::Uninit);
- providers.permits_zero_init =
- |tcx, ty| might_permit_raw_init::might_permit_raw_init(tcx, ty, InitKind::Zero);
+ |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);
}
diff --git a/compiler/rustc_const_eval/src/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/might_permit_raw_init.rs
deleted file mode 100644
index 37ffa19cc..000000000
--- a/compiler/rustc_const_eval/src/might_permit_raw_init.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::const_eval::CompileTimeInterpreter;
-use crate::interpret::{InterpCx, MemoryKind, OpTy};
-use rustc_middle::ty::layout::LayoutCx;
-use rustc_middle::ty::{layout::TyAndLayout, ParamEnv, TyCtxt};
-use rustc_session::Limit;
-use rustc_target::abi::InitKind;
-
-pub fn might_permit_raw_init<'tcx>(
- tcx: TyCtxt<'tcx>,
- ty: TyAndLayout<'tcx>,
- kind: InitKind,
-) -> bool {
- let strict = tcx.sess.opts.unstable_opts.strict_init_checks;
-
- if strict {
- let machine = CompileTimeInterpreter::new(
- Limit::new(0),
- /*can_access_statics:*/ false,
- /*check_alignment:*/ true,
- );
-
- let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
-
- let allocated = cx
- .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
- .expect("OOM: failed to allocate for uninit check");
-
- if kind == InitKind::Zero {
- cx.write_bytes_ptr(
- allocated.ptr,
- std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
- )
- .expect("failed to write bytes for zero valid check");
- }
-
- let ot: OpTy<'_, _> = allocated.into();
-
- // Assume that if it failed, it's a validation failure.
- cx.validate_operand(&ot).is_ok()
- } else {
- let layout_cx = LayoutCx { tcx, param_env: ParamEnv::reveal_all() };
- ty.might_permit_raw_init(&layout_cx, kind)
- }
-}
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 7e15858c8..22a61774e 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -13,8 +13,11 @@ use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty,
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::SelectionContext;
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
+use rustc_trait_selection::traits::{
+ self, ObligationCauseCode, SelectionContext, TraitEngine, TraitEngineExt,
+};
use std::mem;
use std::ops::Deref;
@@ -550,7 +553,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
unimplemented!()
}
- Rvalue::Cast(CastKind::Misc, _, _) => {}
+ Rvalue::Cast(_, _, _) => {}
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::ShallowInitBox(_, _) => {}
@@ -656,6 +659,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Downcast(..)
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::Field(..)
| ProjectionElem::Index(_) => {}
@@ -733,10 +737,49 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
let obligation =
Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred);
- let implsrc = tcx.infer_ctxt().enter(|infcx| {
+ let implsrc = {
+ let infcx = tcx.infer_ctxt().build();
let mut selcx = SelectionContext::new(&infcx);
selcx.select(&obligation)
- });
+ };
+
+ // do a well-formedness check on the trait method being called. This is because typeck only does a
+ // "non-const" check. This is required for correctness here.
+ {
+ let infcx = tcx.infer_ctxt().build();
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ 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,
+ ObligationCauseCode::ItemObligation(callee),
+ )
+ };
+ let normalized = infcx.partially_normalize_associated_types_in(
+ cause(),
+ param_env,
+ predicates,
+ );
+
+ for p in normalized.obligations {
+ fulfill_cx.register_predicate_obligation(&infcx, p);
+ }
+ for obligation in traits::predicates_for_generics(
+ |_, _| cause(),
+ self.param_env,
+ normalized.value,
+ ) {
+ fulfill_cx.register_predicate_obligation(&infcx, obligation);
+ }
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ }
+ }
match implsrc {
Ok(Some(ImplSource::Param(_, ty::BoundConstness::ConstIfConst))) => {
@@ -794,16 +837,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// improve diagnostics by showing what failed. Our requirements are stricter this time
// as we are going to error again anyways.
- tcx.infer_ctxt().enter(|infcx| {
- if let Err(e) = implsrc {
- infcx.report_selection_error(
- obligation.clone(),
- &obligation,
- &e,
- false,
- );
- }
- });
+ let infcx = tcx.infer_ctxt().build();
+ if let Err(e) = implsrc {
+ infcx.err_ctxt().report_selection_error(
+ obligation.clone(),
+ &obligation,
+ &e,
+ false,
+ );
+ }
self.check_op(ops::FnCallNonConst {
caller,
@@ -867,8 +909,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}
- let is_intrinsic = tcx.is_intrinsic(callee);
-
if !tcx.is_const_fn_raw(callee) {
if !tcx.is_const_default_method(callee) {
// To get to here we must have already found a const impl for the
@@ -928,7 +968,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// We do not use `const` modifiers for intrinsic "functions", as intrinsics are
// `extern` functions, and these have no way to get marked `const`. So instead we
// use `rustc_const_(un)stable` attributes to mean that the intrinsic is `const`
- if self.ccx.is_const_stable_const_fn() || is_intrinsic {
+ if self.ccx.is_const_stable_const_fn() || tcx.is_intrinsic(callee) {
self.check_op(ops::FnCallUnstable(callee, None));
return;
}
@@ -968,7 +1008,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
if needs_non_const_drop {
self.check_op_spanned(
- ops::LiveDrop { dropped_at: Some(terminator.source_info.span) },
+ ops::LiveDrop {
+ dropped_at: Some(terminator.source_info.span),
+ dropped_ty: ty_of_dropped_place,
+ },
err_span,
);
}
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 5fb4bf638..b28d70194 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -156,10 +156,9 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
}),
);
- let implsrc = tcx.infer_ctxt().enter(|infcx| {
- let mut selcx = SelectionContext::new(&infcx);
- selcx.select(&obligation)
- });
+ let infcx = tcx.infer_ctxt().build();
+ let mut selcx = SelectionContext::new(&infcx);
+ let implsrc = selcx.select(&obligation);
if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
let span = tcx.def_span(data.impl_def_id);
@@ -422,10 +421,11 @@ impl<'tcx> NonConstOp<'tcx> for InlineAsm {
}
#[derive(Debug)]
-pub struct LiveDrop {
+pub struct LiveDrop<'tcx> {
pub dropped_at: Option<Span>,
+ pub dropped_ty: Ty<'tcx>,
}
-impl<'tcx> NonConstOp<'tcx> for LiveDrop {
+impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
fn build_error(
&self,
ccx: &ConstCx<'_, 'tcx>,
@@ -435,9 +435,13 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop {
ccx.tcx.sess,
span,
E0493,
- "destructors cannot be evaluated at compile-time"
+ "destructor of `{}` cannot be evaluated at compile-time",
+ self.dropped_ty,
+ );
+ err.span_label(
+ span,
+ format!("the destructor for this type cannot be evaluated in {}s", ccx.const_kind()),
);
- err.span_label(span, format!("{}s cannot evaluate destructors", ccx.const_kind()));
if let Some(span) = self.dropped_at {
err.span_label(span, "value is dropped here");
}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index 4e210f663..d4570c598 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -1,6 +1,6 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Location};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
use rustc_span::{symbol::sym, Span};
use super::check::Qualifs;
@@ -58,9 +58,9 @@ impl<'mir, 'tcx> std::ops::Deref for CheckLiveDrops<'mir, 'tcx> {
}
}
-impl CheckLiveDrops<'_, '_> {
- fn check_live_drop(&self, span: Span) {
- ops::LiveDrop { dropped_at: None }.build_error(self.ccx, span).emit();
+impl<'tcx> CheckLiveDrops<'_, 'tcx> {
+ fn check_live_drop(&self, span: Span, dropped_ty: Ty<'tcx>) {
+ ops::LiveDrop { dropped_at: None, dropped_ty }.build_error(self.ccx, span).emit();
}
}
@@ -90,7 +90,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
}
if dropped_place.is_indirect() {
- self.check_live_drop(terminator.source_info.span);
+ self.check_live_drop(terminator.source_info.span, dropped_ty);
return;
}
@@ -101,7 +101,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
if self.qualifs.needs_non_const_drop(self.ccx, dropped_place.local, location) {
// Use the span where the dropped local was declared for the error.
let span = self.body.local_decls[dropped_place.local].source_info.span;
- self.check_live_drop(span);
+ self.check_live_drop(span, dropped_ty);
}
}
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 6c73ef5a8..335992342 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -5,9 +5,9 @@
use rustc_errors::ErrorGuaranteed;
use rustc_hir::LangItem;
use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::mir;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
-use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::{
self, ImplSource, Obligation, ObligationCause, SelectionContext,
};
@@ -91,7 +91,7 @@ impl Qualif for HasMutInterior {
}
fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
- !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
+ !ty.is_freeze(cx.tcx, cx.param_env)
}
fn in_adt_inherently<'tcx>(
@@ -167,30 +167,28 @@ impl Qualif for NeedsNonConstDrop {
}),
);
- cx.tcx.infer_ctxt().enter(|infcx| {
- let mut selcx = SelectionContext::new(&infcx);
- let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
- // If we couldn't select a const destruct candidate, then it's bad
- return true;
- };
-
- if !matches!(
- impl_src,
- ImplSource::ConstDestruct(_)
- | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
- ) {
- // If our const destruct candidate is not ConstDestruct or implied by the param env,
- // then it's bad
- return true;
- }
+ let infcx = cx.tcx.infer_ctxt().build();
+ let mut selcx = SelectionContext::new(&infcx);
+ let Some(impl_src) = selcx.select(&obligation).ok().flatten() else {
+ // If we couldn't select a const destruct candidate, then it's bad
+ return true;
+ };
+
+ if !matches!(
+ impl_src,
+ ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst)
+ ) {
+ // If our const destruct candidate is not ConstDestruct or implied by the param env,
+ // then it's bad
+ return true;
+ }
- if impl_src.borrow_nested_obligations().is_empty() {
- return false;
- }
+ if impl_src.borrow_nested_obligations().is_empty() {
+ return false;
+ }
- // If we had any errors, then it's bad
- !traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty()
- })
+ // If we had any errors, then it's bad
+ !traits::fully_solve_obligations(&infcx, impl_src.nested_obligations()).is_empty()
}
fn in_adt_inherently<'tcx>(
@@ -308,6 +306,7 @@ where
ProjectionElem::Deref
| ProjectionElem::Field(_, _)
+ | ProjectionElem::OpaqueCast(_)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. }
| ProjectionElem::Downcast(_, _)
@@ -349,17 +348,13 @@ where
// FIXME(valtrees): check whether const qualifs should behave the same
// way for type and mir constants.
let uneval = match constant.literal {
- ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => {
- let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() };
-
- Some(uv.expand())
- }
- ConstantKind::Ty(_) => None,
+ ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
+ ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
ConstantKind::Unevaluated(uv, _) => Some(uv),
ConstantKind::Val(..) => None,
};
- if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval {
+ if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval {
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
// check performed after the promotion. Verify that with an assertion.
@@ -367,11 +362,8 @@ where
// Don't peek inside trait associated constants.
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
- let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
- cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
- } else {
- cx.tcx.at(constant.span).mir_const_qualif(def.did)
- };
+ assert_eq!(def.const_param_did, None, "expected associated const: {def:?}");
+ let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
if !Q::in_qualifs(&qualifs) {
return false;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index 60c1e4950..805e6096b 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -8,7 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementK
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::JoinSemiLattice;
use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
-use rustc_span::DUMMY_SP;
use std::fmt;
use std::marker::PhantomData;
@@ -120,10 +119,7 @@ where
///
/// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134
fn shared_borrow_allows_mutation(&self, place: mir::Place<'tcx>) -> bool {
- !place
- .ty(self.ccx.body, self.ccx.tcx)
- .ty
- .is_freeze(self.ccx.tcx.at(DUMMY_SP), self.ccx.param_env)
+ !place.ty(self.ccx.body, self.ccx.tcx).ty.is_freeze(self.ccx.tcx, self.ccx.param_env)
}
}
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index f7a7cc88a..f3ae16da4 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -13,6 +13,7 @@
//! move analysis runs after promotion on broken MIR.
use rustc_hir as hir;
+use rustc_middle::mir;
use rustc_middle::mir::traversal::ReversePostorderIter;
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
@@ -40,10 +41,6 @@ pub struct PromoteTemps<'tcx> {
}
impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> {
- fn phase_change(&self) -> Option<MirPhase> {
- Some(MirPhase::Analysis(AnalysisPhase::Initial))
- }
-
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// There's not really any point in promoting errorful MIR.
//
@@ -361,7 +358,7 @@ impl<'tcx> Validator<'_, 'tcx> {
return Err(Unpromotable);
}
}
- ProjectionElem::Downcast(..) => {
+ ProjectionElem::OpaqueCast(..) | ProjectionElem::Downcast(..) => {
return Err(Unpromotable);
}
@@ -840,7 +837,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
promoted.span = span;
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
- let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
+ let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
Operand::Constant(Box::new(Constant {
span,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 4aa98cb13..81b82a21f 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -13,7 +13,6 @@ use rustc_middle::mir::{
TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_storage_live_locals;
@@ -106,7 +105,7 @@ pub fn equal_up_to_regions<'tcx>(
},
)
};
- tcx.infer_ctxt().enter(|infcx| infcx.can_eq(param_env, normalize(src), normalize(dest)).is_ok())
+ tcx.infer_ctxt().build().can_eq(param_env, normalize(src), normalize(dest)).is_ok()
}
struct TypeChecker<'a, 'tcx> {
@@ -236,9 +235,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// `Operand::Copy` is only supposed to be used with `Copy` types.
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
- let span = self.body.source_info(location).span;
- if !ty.is_copy_modulo_regions(self.tcx.at(span), self.param_env) {
+ if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
self.fail(location, format!("`Operand::Copy` with non-`Copy` type {}", ty));
}
}
@@ -285,7 +283,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
this.fail(
location,
format!(
- "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is {:?}",
+ "Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
parent, f, ty, f_ty
)
)
@@ -557,25 +555,40 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
check_kinds!(a, "Cannot shallow init type {:?}", ty::RawPtr(..));
}
Rvalue::Cast(kind, operand, target_type) => {
+ let op_ty = operand.ty(self.body, self.tcx);
match kind {
- CastKind::Misc => {
- let op_ty = operand.ty(self.body, self.tcx);
- if op_ty.is_enum() {
+ CastKind::DynStar => {
+ // FIXME(dyn-star): make sure nothing needs to be done here.
+ }
+ // FIXME: Add Checks for these
+ CastKind::PointerFromExposedAddress
+ | CastKind::PointerExposeAddress
+ | CastKind::Pointer(_) => {}
+ CastKind::IntToInt | CastKind::IntToFloat => {
+ let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
+ let target_valid = target_type.is_numeric() || target_type.is_char();
+ if !input_valid || !target_valid {
+ self.fail(
+ location,
+ format!("Wrong cast kind {kind:?} for the type {op_ty}",),
+ );
+ }
+ }
+ CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
+ if !(op_ty.is_any_ptr() && target_type.is_unsafe_ptr()) {
+ self.fail(location, "Can't cast {op_ty} into 'Ptr'");
+ }
+ }
+ CastKind::FloatToFloat | CastKind::FloatToInt => {
+ if !op_ty.is_floating_point() || !target_type.is_numeric() {
self.fail(
location,
format!(
- "enum -> int casts should go through `Rvalue::Discriminant`: {operand:?}:{op_ty} as {target_type}",
+ "Trying to cast non 'Float' as {kind:?} into {target_type:?}"
),
);
}
}
- CastKind::DynStar => {
- // FIXME(dyn-star): make sure nothing needs to be done here.
- }
- // Nothing to check here
- CastKind::PointerFromExposedAddress
- | CastKind::PointerExposeAddress
- | CastKind::Pointer(_) => {}
}
}
Rvalue::Repeat(_, _)
diff --git a/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
new file mode 100644
index 000000000..6ca712233
--- /dev/null
+++ b/compiler/rustc_const_eval/src/util/might_permit_raw_init.rs
@@ -0,0 +1,151 @@
+use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout};
+use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_session::Limit;
+use rustc_target::abi::{Abi, FieldsShape, InitKind, Scalar, Variants};
+
+use crate::const_eval::CompileTimeInterpreter;
+use crate::interpret::{InterpCx, MemoryKind, OpTy};
+
+/// Determines if this type permits "raw" initialization by just transmuting some memory into an
+/// instance of `T`.
+///
+/// `init_kind` indicates if the memory is zero-initialized or left uninitialized. We assume
+/// uninitialized memory is mitigated by filling it with 0x01, which reduces the chance of causing
+/// LLVM UB.
+///
+/// By default we check whether that operation would cause *LLVM UB*, i.e., whether the LLVM IR we
+/// generate has UB or not. This is a mitigation strategy, which is why we are okay with accepting
+/// 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>(
+ 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)
+ } else {
+ let layout_cx = LayoutCx { tcx, param_env: ParamEnv::reveal_all() };
+ might_permit_raw_init_lax(ty, &layout_cx, kind)
+ }
+}
+
+/// Implements the 'strict' version of the `might_permit_raw_init` checks; see that function for
+/// details.
+fn might_permit_raw_init_strict<'tcx>(
+ ty: TyAndLayout<'tcx>,
+ tcx: TyCtxt<'tcx>,
+ kind: InitKind,
+) -> bool {
+ let machine = CompileTimeInterpreter::new(
+ Limit::new(0),
+ /*can_access_statics:*/ false,
+ /*check_alignment:*/ true,
+ );
+
+ let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
+
+ let allocated = cx
+ .allocate(ty, MemoryKind::Machine(crate::const_eval::MemoryKind::Heap))
+ .expect("OOM: failed to allocate for uninit check");
+
+ if kind == InitKind::Zero {
+ cx.write_bytes_ptr(
+ allocated.ptr,
+ std::iter::repeat(0_u8).take(ty.layout.size().bytes_usize()),
+ )
+ .expect("failed to write bytes for zero valid check");
+ }
+
+ let ot: OpTy<'_, _> = allocated.into();
+
+ // Assume that if it failed, it's a validation failure.
+ // 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()
+}
+
+/// Implements the 'lax' (default) version of the `might_permit_raw_init` checks; see that function for
+/// details.
+fn might_permit_raw_init_lax<'tcx>(
+ this: TyAndLayout<'tcx>,
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ init_kind: InitKind,
+) -> bool {
+ let scalar_allows_raw_init = move |s: Scalar| -> bool {
+ match init_kind {
+ InitKind::Zero => {
+ // The range must contain 0.
+ s.valid_range(cx).contains(0)
+ }
+ InitKind::UninitMitigated0x01Fill => {
+ // The range must include an 0x01-filled buffer.
+ let mut val: u128 = 0x01;
+ for _ in 1..s.size(cx).bytes() {
+ // For sizes >1, repeat the 0x01.
+ val = (val << 8) | 0x01;
+ }
+ s.valid_range(cx).contains(val)
+ }
+ }
+ };
+
+ // Check the ABI.
+ let valid = match this.abi {
+ Abi::Uninhabited => false, // definitely UB
+ Abi::Scalar(s) => scalar_allows_raw_init(s),
+ Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
+ Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
+ Abi::Aggregate { .. } => true, // Fields are checked below.
+ };
+ if !valid {
+ // This is definitely not okay.
+ return 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");
+ // 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;
+ }
+ if pointee.size.bytes() > 0 {
+ // A 'fake' integer pointer is not sufficiently dereferenceable.
+ return false;
+ }
+ }
+
+ // If we have not found an error yet, we need to recursively descend into fields.
+ match &this.fields {
+ FieldsShape::Primitive | FieldsShape::Union { .. } => {}
+ FieldsShape::Array { .. } => {
+ // Arrays never have scalar layout in LLVM, so if the array is not actually
+ // accessed, there is no LLVM UB -- therefore we can skip this.
+ }
+ FieldsShape::Arbitrary { offsets, .. } => {
+ for idx in 0..offsets.len() {
+ 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;
+ }
+ }
+ }
+ }
+
+ match &this.variants {
+ Variants::Single { .. } => {
+ // All fields of this single variant have already been checked above, there is nothing
+ // else to do.
+ }
+ Variants::Multiple { .. } => {
+ // We cannot tell LLVM anything about the details of this multi-variant layout, so
+ // invalid values "hidden" inside the variant cannot cause LLVM trouble.
+ }
+ }
+
+ true
+}
diff --git a/compiler/rustc_const_eval/src/util/mod.rs b/compiler/rustc_const_eval/src/util/mod.rs
index a1876bed8..7a05cfd23 100644
--- a/compiler/rustc_const_eval/src/util/mod.rs
+++ b/compiler/rustc_const_eval/src/util/mod.rs
@@ -3,8 +3,10 @@ mod alignment;
mod call_kind;
pub mod collect_writes;
mod find_self_call;
+mod might_permit_raw_init;
pub use self::aggregate::expand_aggregate;
pub use self::alignment::is_disaligned;
pub use self::call_kind::{call_kind, CallDesugaringKind, CallKind};
pub use self::find_self_call::find_self_call;
+pub use self::might_permit_raw_init::might_permit_raw_init;
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 2d8658db5..9daa21ef6 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
arrayvec = { version = "0.7", default-features = false }
diff --git a/compiler/rustc_data_structures/src/flock/linux.rs b/compiler/rustc_data_structures/src/flock/linux.rs
index bb3ecfbc3..9ed26e490 100644
--- a/compiler/rustc_data_structures/src/flock/linux.rs
+++ b/compiler/rustc_data_structures/src/flock/linux.rs
@@ -14,12 +14,7 @@ pub struct Lock {
impl Lock {
pub fn new(p: &Path, wait: bool, create: bool, exclusive: bool) -> io::Result<Lock> {
- let file = OpenOptions::new()
- .read(true)
- .write(true)
- .create(create)
- .mode(libc::S_IRWXU as u32)
- .open(p)?;
+ let file = OpenOptions::new().read(true).write(true).create(create).mode(0o600).open(p)?;
let mut operation = if exclusive { libc::LOCK_EX } else { libc::LOCK_SH };
if !wait {
diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
index 3d91bcade..e8efbd09a 100644
--- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
+++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs
@@ -29,8 +29,8 @@ impl<N: Idx + Ord> VecGraph<N> {
// Store the *target* of each edge into `edge_targets`.
let edge_targets: Vec<N> = edge_pairs.iter().map(|&(_, target)| target).collect();
- // Create the *edge starts* array. We are iterating over over
- // the (sorted) edge pairs. We maintain the invariant that the
+ // Create the *edge starts* array. We are iterating over the
+ // (sorted) edge pairs. We maintain the invariant that the
// length of the `node_starts` array is enough to store the
// current source node -- so when we see that the source node
// for an edge is greater than the current length, we grow the
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 56f7823ef..3a2000233 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -13,7 +13,6 @@
#![feature(cell_leak)]
#![feature(control_flow_enum)]
#![feature(extend_one)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(hash_raw_entry)]
#![feature(hasher_prefixfree_extras)]
#![feature(maybe_uninit_uninit_array)]
@@ -23,6 +22,7 @@
#![feature(new_uninit)]
#![feature(once_cell)]
#![feature(rustc_attrs)]
+#![feature(negative_impls)]
#![feature(test)]
#![feature(thread_id_value)]
#![feature(vec_into_raw_parts)]
@@ -87,6 +87,7 @@ pub mod steal;
pub mod tagged_ptr;
pub mod temp_dir;
pub mod unhash;
+pub mod unord;
pub use ena::undo_log;
pub use ena::unify;
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index e351b650a..10e673cd9 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -95,6 +95,10 @@ 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>,
+ >;
fn needs_process_obligation(&self, obligation: &Self::Obligation) -> bool;
@@ -111,7 +115,11 @@ pub trait ObligationProcessor {
/// In other words, if we had O1 which required O2 which required
/// O3 which required O1, we would give an iterator yielding O1,
/// O2, O3 (O1 is not yielded twice).
- fn process_backedge<'c, I>(&mut self, cycle: I, _marker: PhantomData<&'c Self::Obligation>)
+ fn process_backedge<'c, I>(
+ &mut self,
+ cycle: I,
+ _marker: PhantomData<&'c Self::Obligation>,
+ ) -> Result<(), Self::Error>
where
I: Clone + Iterator<Item = &'c Self::Obligation>;
}
@@ -402,12 +410,11 @@ impl<O: ForestObligation> ObligationForest<O> {
/// Performs a fixpoint computation over the obligation list.
#[inline(never)]
- pub fn process_obligations<P, OUT>(&mut self, processor: &mut P) -> OUT
+ pub fn process_obligations<P>(&mut self, processor: &mut P) -> P::OUT
where
P: ObligationProcessor<Obligation = O>,
- OUT: OutcomeTrait<Obligation = O, Error = Error<O, P::Error>>,
{
- let mut outcome = OUT::new();
+ let mut outcome = P::OUT::new();
// Fixpoint computation: we repeat until the inner loop stalls.
loop {
@@ -473,7 +480,7 @@ impl<O: ForestObligation> ObligationForest<O> {
}
self.mark_successes();
- self.process_cycles(processor);
+ self.process_cycles(processor, &mut outcome);
self.compress(|obl| outcome.record_completed(obl));
}
@@ -558,7 +565,7 @@ impl<O: ForestObligation> ObligationForest<O> {
/// Report cycles between all `Success` nodes, and convert all `Success`
/// nodes to `Done`. This must be called after `mark_successes`.
- fn process_cycles<P>(&mut self, processor: &mut P)
+ fn process_cycles<P>(&mut self, processor: &mut P, outcome: &mut P::OUT)
where
P: ObligationProcessor<Obligation = O>,
{
@@ -568,7 +575,7 @@ impl<O: ForestObligation> ObligationForest<O> {
// to handle the no-op cases immediately to avoid the cost of the
// function call.
if node.state.get() == NodeState::Success {
- self.find_cycles_from_node(&mut stack, processor, index);
+ self.find_cycles_from_node(&mut stack, processor, index, outcome);
}
}
@@ -576,8 +583,13 @@ impl<O: ForestObligation> ObligationForest<O> {
self.reused_node_vec = stack;
}
- fn find_cycles_from_node<P>(&self, stack: &mut Vec<usize>, processor: &mut P, index: usize)
- where
+ fn find_cycles_from_node<P>(
+ &self,
+ stack: &mut Vec<usize>,
+ processor: &mut P,
+ index: usize,
+ outcome: &mut P::OUT,
+ ) where
P: ObligationProcessor<Obligation = O>,
{
let node = &self.nodes[index];
@@ -586,17 +598,20 @@ impl<O: ForestObligation> ObligationForest<O> {
None => {
stack.push(index);
for &dep_index in node.dependents.iter() {
- self.find_cycles_from_node(stack, processor, dep_index);
+ self.find_cycles_from_node(stack, processor, dep_index, outcome);
}
stack.pop();
node.state.set(NodeState::Done);
}
Some(rpos) => {
// Cycle detected.
- processor.process_backedge(
+ let result = processor.process_backedge(
stack[rpos..].iter().map(|&i| &self.nodes[i].obligation),
PhantomData,
);
+ if let Err(err) = result {
+ outcome.record_error(Error { error: err, backtrace: self.error_at(index) });
+ }
}
}
}
diff --git a/compiler/rustc_data_structures/src/obligation_forest/tests.rs b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
index e2991aae1..bc252f772 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/tests.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
@@ -64,6 +64,7 @@ where
{
type Obligation = O;
type Error = E;
+ type OUT = TestOutcome<O, E>;
fn needs_process_obligation(&self, _obligation: &Self::Obligation) -> bool {
true
@@ -76,10 +77,15 @@ where
(self.process_obligation)(obligation)
}
- fn process_backedge<'c, I>(&mut self, _cycle: I, _marker: PhantomData<&'c Self::Obligation>)
+ fn process_backedge<'c, I>(
+ &mut self,
+ _cycle: I,
+ _marker: PhantomData<&'c Self::Obligation>,
+ ) -> Result<(), Self::Error>
where
I: Clone + Iterator<Item = &'c Self::Obligation>,
{
+ Ok(())
}
}
diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs
index d8b26f984..ba1960805 100644
--- a/compiler/rustc_data_structures/src/profiling.rs
+++ b/compiler/rustc_data_structures/src/profiling.rs
@@ -158,30 +158,21 @@ pub struct SelfProfilerRef {
// actually enabled.
event_filter_mask: EventFilter,
- // Print verbose generic activities to stdout
+ // Print verbose generic activities to stderr?
print_verbose_generic_activities: bool,
-
- // Print extra verbose generic activities to stdout
- print_extra_verbose_generic_activities: bool,
}
impl SelfProfilerRef {
pub fn new(
profiler: Option<Arc<SelfProfiler>>,
print_verbose_generic_activities: bool,
- print_extra_verbose_generic_activities: bool,
) -> SelfProfilerRef {
// If there is no SelfProfiler then the filter mask is set to NONE,
// ensuring that nothing ever tries to actually access it.
let event_filter_mask =
profiler.as_ref().map_or(EventFilter::empty(), |p| p.event_filter_mask);
- SelfProfilerRef {
- profiler,
- event_filter_mask,
- print_verbose_generic_activities,
- print_extra_verbose_generic_activities,
- }
+ SelfProfilerRef { profiler, event_filter_mask, print_verbose_generic_activities }
}
/// This shim makes sure that calls only get executed if the filter mask
@@ -214,7 +205,7 @@ impl SelfProfilerRef {
/// Start profiling a verbose generic activity. Profiling continues until the
/// VerboseTimingGuard returned from this call is dropped. In addition to recording
/// a measureme event, "verbose" generic activities also print a timing entry to
- /// stdout if the compiler is invoked with -Ztime or -Ztime-passes.
+ /// stderr if the compiler is invoked with -Ztime-passes.
pub fn verbose_generic_activity<'a>(
&'a self,
event_label: &'static str,
@@ -225,11 +216,8 @@ impl SelfProfilerRef {
VerboseTimingGuard::start(message, self.generic_activity(event_label))
}
- /// Start profiling an extra verbose generic activity. Profiling continues until the
- /// VerboseTimingGuard returned from this call is dropped. In addition to recording
- /// a measureme event, "extra verbose" generic activities also print a timing entry to
- /// stdout if the compiler is invoked with -Ztime-passes.
- pub fn extra_verbose_generic_activity<'a, A>(
+ /// Like `verbose_generic_activity`, but with an extra arg.
+ pub fn verbose_generic_activity_with_arg<'a, A>(
&'a self,
event_label: &'static str,
event_arg: A,
@@ -237,7 +225,7 @@ impl SelfProfilerRef {
where
A: Borrow<str> + Into<String>,
{
- let message = if self.print_extra_verbose_generic_activities {
+ let message = if self.print_verbose_generic_activities {
Some(format!("{}({})", event_label, event_arg.borrow()))
} else {
None
@@ -745,27 +733,9 @@ impl Drop for VerboseTimingGuard<'_> {
if let Some((start_time, start_rss, ref message)) = self.start_and_message {
let end_rss = get_resident_set_size();
let dur = start_time.elapsed();
-
- if should_print_passes(dur, start_rss, end_rss) {
- print_time_passes_entry(&message, dur, start_rss, end_rss);
- }
- }
- }
-}
-
-fn should_print_passes(dur: Duration, start_rss: Option<usize>, end_rss: Option<usize>) -> bool {
- if dur.as_millis() > 5 {
- return true;
- }
-
- if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) {
- let change_rss = end_rss.abs_diff(start_rss);
- if change_rss > 0 {
- return true;
+ print_time_passes_entry(&message, dur, start_rss, end_rss);
}
}
-
- false
}
pub fn print_time_passes_entry(
@@ -774,6 +744,26 @@ pub fn print_time_passes_entry(
start_rss: Option<usize>,
end_rss: Option<usize>,
) {
+ // Print the pass if its duration is greater than 5 ms, or it changed the
+ // measured RSS.
+ let is_notable = || {
+ if dur.as_millis() > 5 {
+ return true;
+ }
+
+ if let (Some(start_rss), Some(end_rss)) = (start_rss, end_rss) {
+ let change_rss = end_rss.abs_diff(start_rss);
+ if change_rss > 0 {
+ return true;
+ }
+ }
+
+ false
+ };
+ if !is_notable() {
+ return;
+ }
+
let rss_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as usize;
let rss_change_to_mb = |rss| (rss as f64 / 1_000_000.0).round() as i128;
diff --git a/compiler/rustc_data_structures/src/sorted_map.rs b/compiler/rustc_data_structures/src/sorted_map.rs
index 937cb6715..fe257e102 100644
--- a/compiler/rustc_data_structures/src/sorted_map.rs
+++ b/compiler/rustc_data_structures/src/sorted_map.rs
@@ -96,6 +96,23 @@ impl<K: Ord, V> SortedMap<K, V> {
}
}
+ /// Gets a mutable reference to the value in the entry, or insert a new one.
+ #[inline]
+ pub fn get_mut_or_insert_default(&mut self, key: K) -> &mut V
+ where
+ K: Eq,
+ V: Default,
+ {
+ let index = match self.lookup_index_for(&key) {
+ Ok(index) => index,
+ Err(index) => {
+ self.data.insert(index, (key, V::default()));
+ index
+ }
+ };
+ unsafe { &mut self.data.get_unchecked_mut(index).1 }
+ }
+
#[inline]
pub fn clear(&mut self) {
self.data.clear();
diff --git a/compiler/rustc_data_structures/src/sso/set.rs b/compiler/rustc_data_structures/src/sso/set.rs
index 4fda3adb7..406f0270d 100644
--- a/compiler/rustc_data_structures/src/sso/set.rs
+++ b/compiler/rustc_data_structures/src/sso/set.rs
@@ -27,7 +27,7 @@ pub struct SsoHashSet<T> {
map: SsoHashMap<T, ()>,
}
-/// Adapter function used ot return
+/// Adapter function used to return
/// result if SsoHashMap functions into
/// result SsoHashSet should return.
#[inline(always)]
diff --git a/compiler/rustc_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs
index f016c391f..cf6162038 100644
--- a/compiler/rustc_data_structures/src/transitive_relation.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation.rs
@@ -1,5 +1,5 @@
use crate::frozen::Frozen;
-use crate::fx::FxIndexSet;
+use crate::fx::{FxHashSet, FxIndexSet};
use rustc_index::bit_set::BitMatrix;
use std::fmt::Debug;
use std::hash::Hash;
@@ -16,7 +16,7 @@ pub struct TransitiveRelationBuilder<T> {
// List of base edges in the graph. Require to compute transitive
// closure.
- edges: Vec<Edge>,
+ edges: FxHashSet<Edge>,
}
#[derive(Debug)]
@@ -52,10 +52,10 @@ impl<T: Eq + Hash> Default for TransitiveRelationBuilder<T> {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug, Hash)]
struct Index(usize);
-#[derive(Clone, PartialEq, Eq, Debug)]
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
struct Edge {
source: Index,
target: Index,
@@ -99,9 +99,7 @@ impl<T: Eq + Hash + Copy> TransitiveRelationBuilder<T> {
let a = self.add_index(a);
let b = self.add_index(b);
let edge = Edge { source: a, target: b };
- if !self.edges.contains(&edge) {
- self.edges.push(edge);
- }
+ self.edges.insert(edge);
}
/// Compute the transitive closure derived from the edges, and converted to
diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs
new file mode 100644
index 000000000..c015f1232
--- /dev/null
+++ b/compiler/rustc_data_structures/src/unord.rs
@@ -0,0 +1,382 @@
+//! This module contains collection types that don't expose their internal
+//! ordering. This is a useful property for deterministic computations, such
+//! as required by the query system.
+
+use rustc_hash::{FxHashMap, FxHashSet};
+use smallvec::SmallVec;
+use std::{
+ borrow::Borrow,
+ hash::Hash,
+ iter::{Product, Sum},
+};
+
+use crate::{
+ fingerprint::Fingerprint,
+ stable_hasher::{HashStable, StableHasher, ToStableHashKey},
+};
+
+/// `UnordItems` is the order-less version of `Iterator`. It only contains methods
+/// that don't (easily) expose an ordering of the underlying items.
+///
+/// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This
+/// is to reduce the risk of accidentally leaking the internal order via the closure
+/// environment. Otherwise one could easily do something like
+///
+/// ```rust,ignore (pseudo code)
+/// let mut ordered = vec![];
+/// unordered_items.all(|x| ordered.push(x));
+/// ```
+///
+/// It's still possible to do the same thing with an `Fn` by using interior mutability,
+/// but the chance of doing it accidentally is reduced.
+pub struct UnordItems<T, I: Iterator<Item = T>>(I);
+
+impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
+ #[inline]
+ pub fn map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>> {
+ UnordItems(self.0.map(f))
+ }
+
+ #[inline]
+ pub fn all<U, F: Fn(T) -> bool>(mut self, f: F) -> bool {
+ self.0.all(f)
+ }
+
+ #[inline]
+ pub fn any<U, F: Fn(T) -> bool>(mut self, f: F) -> bool {
+ self.0.any(f)
+ }
+
+ #[inline]
+ pub fn filter<U, F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>> {
+ UnordItems(self.0.filter(f))
+ }
+
+ #[inline]
+ pub fn filter_map<U, F: Fn(T) -> Option<U>>(
+ self,
+ f: F,
+ ) -> UnordItems<U, impl Iterator<Item = U>> {
+ UnordItems(self.0.filter_map(f))
+ }
+
+ #[inline]
+ pub fn max(self) -> Option<T>
+ where
+ T: Ord,
+ {
+ self.0.max()
+ }
+
+ #[inline]
+ pub fn min(self) -> Option<T>
+ where
+ T: Ord,
+ {
+ self.0.min()
+ }
+
+ #[inline]
+ pub fn sum<S>(self) -> S
+ where
+ S: Sum<T>,
+ {
+ self.0.sum()
+ }
+
+ #[inline]
+ pub fn product<S>(self) -> S
+ where
+ S: Product<T>,
+ {
+ self.0.product()
+ }
+
+ #[inline]
+ pub fn count(self) -> usize {
+ self.0.count()
+ }
+}
+
+impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
+ #[inline]
+ pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> {
+ UnordItems(self.0.cloned())
+ }
+}
+
+impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
+ #[inline]
+ pub fn copied(self) -> UnordItems<T, impl Iterator<Item = T>> {
+ UnordItems(self.0.copied())
+ }
+}
+
+impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
+ pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T>
+ where
+ T: ToStableHashKey<HCX>,
+ {
+ let mut items: Vec<T> = self.0.collect();
+ items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
+ items
+ }
+
+ pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]>
+ where
+ T: ToStableHashKey<HCX>,
+ {
+ let mut items: SmallVec<[T; LEN]> = self.0.collect();
+ items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
+ items
+ }
+}
+
+/// This is a set collection type that tries very hard to not expose
+/// any internal iteration. This is a useful property when trying to
+/// uphold the determinism invariants imposed by the query system.
+///
+/// This collection type is a good choice for set-like collections the
+/// keys of which don't have a semantic ordering.
+///
+/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
+/// for more information.
+#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
+pub struct UnordSet<V: Eq + Hash> {
+ inner: FxHashSet<V>,
+}
+
+impl<V: Eq + Hash> Default for UnordSet<V> {
+ fn default() -> Self {
+ Self { inner: FxHashSet::default() }
+ }
+}
+
+impl<V: Eq + Hash> UnordSet<V> {
+ #[inline]
+ pub fn new() -> Self {
+ Self { inner: Default::default() }
+ }
+
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ #[inline]
+ pub fn insert(&mut self, v: V) -> bool {
+ self.inner.insert(v)
+ }
+
+ #[inline]
+ pub fn contains<Q: ?Sized>(&self, v: &Q) -> bool
+ where
+ V: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.inner.contains(v)
+ }
+
+ #[inline]
+ pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
+ UnordItems(self.inner.iter())
+ }
+
+ #[inline]
+ pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
+ UnordItems(self.inner.into_iter())
+ }
+
+ // We can safely extend this UnordSet from a set of unordered values because that
+ // won't expose the internal ordering anywhere.
+ #[inline]
+ pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
+ self.inner.extend(items.0)
+ }
+}
+
+impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
+ fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
+ self.inner.extend(iter)
+ }
+}
+
+impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
+ #[inline]
+ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+ hash_iter_order_independent(self.inner.iter(), hcx, hasher);
+ }
+}
+
+/// This is a map collection type that tries very hard to not expose
+/// any internal iteration. This is a useful property when trying to
+/// uphold the determinism invariants imposed by the query system.
+///
+/// This collection type is a good choice for map-like collections the
+/// keys of which don't have a semantic ordering.
+///
+/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
+/// for more information.
+#[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
+pub struct UnordMap<K: Eq + Hash, V> {
+ inner: FxHashMap<K, V>,
+}
+
+impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
+ fn default() -> Self {
+ Self { inner: FxHashMap::default() }
+ }
+}
+
+impl<K: Hash + Eq, V> Extend<(K, V)> for UnordMap<K, V> {
+ fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
+ self.inner.extend(iter)
+ }
+}
+
+impl<K: Eq + Hash, V> UnordMap<K, V> {
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ #[inline]
+ pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+ self.inner.insert(k, v)
+ }
+
+ #[inline]
+ pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
+ where
+ K: Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.inner.contains_key(k)
+ }
+
+ #[inline]
+ pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator<Item = (&'a K, &'a V)>> {
+ UnordItems(self.inner.iter())
+ }
+
+ #[inline]
+ pub fn into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>> {
+ UnordItems(self.inner.into_iter())
+ }
+
+ // We can safely extend this UnordMap from a set of unordered values because that
+ // won't expose the internal ordering anywhere.
+ #[inline]
+ pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
+ self.inner.extend(items.0)
+ }
+}
+
+impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> for UnordMap<K, V> {
+ #[inline]
+ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+ hash_iter_order_independent(self.inner.iter(), hcx, hasher);
+ }
+}
+
+/// This is a collection type that tries very hard to not expose
+/// any internal iteration. This is a useful property when trying to
+/// uphold the determinism invariants imposed by the query system.
+///
+/// This collection type is a good choice for collections the
+/// keys of which don't have a semantic ordering and don't implement
+/// `Hash` or `Eq`.
+///
+/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
+/// for more information.
+#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
+pub struct UnordBag<V> {
+ inner: Vec<V>,
+}
+
+impl<V> UnordBag<V> {
+ #[inline]
+ pub fn new() -> Self {
+ Self { inner: Default::default() }
+ }
+
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.inner.len()
+ }
+
+ #[inline]
+ pub fn push(&mut self, v: V) {
+ self.inner.push(v);
+ }
+
+ #[inline]
+ pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator<Item = &'a V>> {
+ UnordItems(self.inner.iter())
+ }
+
+ #[inline]
+ pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
+ UnordItems(self.inner.into_iter())
+ }
+
+ // We can safely extend this UnordSet from a set of unordered values because that
+ // won't expose the internal ordering anywhere.
+ #[inline]
+ pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
+ self.inner.extend(items.0)
+ }
+}
+
+impl<T> Extend<T> for UnordBag<T> {
+ fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
+ self.inner.extend(iter)
+ }
+}
+
+impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordBag<V> {
+ #[inline]
+ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+ hash_iter_order_independent(self.inner.iter(), hcx, hasher);
+ }
+}
+
+fn hash_iter_order_independent<
+ HCX,
+ T: HashStable<HCX>,
+ I: Iterator<Item = T> + ExactSizeIterator,
+>(
+ mut it: I,
+ hcx: &mut HCX,
+ hasher: &mut StableHasher,
+) {
+ let len = it.len();
+ len.hash_stable(hcx, hasher);
+
+ match len {
+ 0 => {
+ // We're done
+ }
+ 1 => {
+ // No need to instantiate a hasher
+ it.next().unwrap().hash_stable(hcx, hasher);
+ }
+ _ => {
+ let mut accumulator = Fingerprint::ZERO;
+ for item in it {
+ let mut item_hasher = StableHasher::new();
+ item.hash_stable(hcx, &mut item_hasher);
+ let item_fingerprint: Fingerprint = item_hasher.finish();
+ accumulator = accumulator.combine_commutative(item_fingerprint);
+ }
+ accumulator.hash_stable(hcx, hasher);
+ }
+ }
+}
+
+// Do not implement IntoIterator for the collections in this module.
+// They only exist to hide iteration order in the first place.
+impl<T> !IntoIterator for UnordBag<T> {}
+impl<V> !IntoIterator for UnordSet<V> {}
+impl<K, V> !IntoIterator for UnordMap<K, V> {}
+impl<T, I> !IntoIterator for UnordItems<T, I> {}
diff --git a/compiler/rustc_driver/Cargo.toml b/compiler/rustc_driver/Cargo.toml
index d1d02ed73..59e937777 100644
--- a/compiler/rustc_driver/Cargo.toml
+++ b/compiler/rustc_driver/Cargo.toml
@@ -30,7 +30,7 @@ rustc_error_codes = { path = "../rustc_error_codes" }
rustc_interface = { path = "../rustc_interface" }
rustc_ast = { path = "../rustc_ast" }
rustc_span = { path = "../rustc_span" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
[target.'cfg(unix)'.dependencies]
libc = "0.2"
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 8fb950819..cfa734c7d 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -5,7 +5,6 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(once_cell)]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
@@ -36,7 +35,7 @@ use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest, Tr
use rustc_session::cstore::MetadataLoader;
use rustc_session::getopts;
use rustc_session::lint::{Lint, LintId};
-use rustc_session::{config, DiagnosticOutput, Session};
+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;
@@ -128,10 +127,13 @@ pub struct TimePassesCallbacks {
}
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 --prints=... option has been given, we don't print the "total"
- // time because it will mess up the --prints output. See #64339.
- self.time_passes = config.opts.prints.is_empty() && config.opts.time_passes();
+ // 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;
}
}
@@ -145,19 +147,21 @@ pub struct RunCompiler<'a, 'b> {
at_args: &'a [String],
callbacks: &'b mut (dyn Callbacks + Send),
file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- emitter: Option<Box<dyn Write + Send>>,
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, emitter: None, make_codegen_backend: None }
+ Self { at_args, callbacks, file_loader: None, make_codegen_backend: None }
}
/// Set a custom codegen backend.
///
- /// Used by cg_clif.
+ /// 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<
@@ -168,17 +172,11 @@ impl<'a, 'b> RunCompiler<'a, 'b> {
self
}
- /// Emit diagnostics to the specified location.
- ///
- /// Used by RLS.
- pub fn set_emitter(&mut self, emitter: Option<Box<dyn Write + Send>>) -> &mut Self {
- self.emitter = emitter;
- self
- }
-
/// Load files from sources other than the file system.
///
- /// Used by RLS.
+ /// 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>>,
@@ -189,27 +187,20 @@ impl<'a, 'b> RunCompiler<'a, 'b> {
/// Parse args and run the compiler.
pub fn run(self) -> interface::Result<()> {
- run_compiler(
- self.at_args,
- self.callbacks,
- self.file_loader,
- self.emitter,
- self.make_codegen_backend,
- )
+ 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>>,
- emitter: Option<Box<dyn Write + Send>>,
make_codegen_backend: Option<
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
) -> interface::Result<()> {
let args = args::arg_expand_all(at_args);
- let diagnostic_output = emitter.map_or(DiagnosticOutput::Default, DiagnosticOutput::Raw);
let Some(matches) = handle_options(&args) else { return Ok(()) };
let sopts = config::build_session_options(&matches);
@@ -231,7 +222,6 @@ fn run_compiler(
output_file: ofile,
output_dir: odir,
file_loader,
- diagnostic_output,
lint_caps: Default::default(),
parse_sess_created: None,
register_lints: None,
@@ -437,18 +427,6 @@ fn run_compiler(
})
}
-#[cfg(unix)]
-pub fn set_sigpipe_handler() {
- unsafe {
- // Set the SIGPIPE signal handler, so that an EPIPE
- // will cause rustc to terminate, as expected.
- assert_ne!(libc::signal(libc::SIGPIPE, libc::SIG_DFL), libc::SIG_ERR);
- }
-}
-
-#[cfg(windows)]
-pub fn set_sigpipe_handler() {}
-
// 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));
@@ -742,6 +720,11 @@ fn print_crate_info(
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
diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs
index 2874fa0ca..f9b1316d2 100644
--- a/compiler/rustc_driver/src/pretty.rs
+++ b/compiler/rustc_driver/src/pretty.rs
@@ -329,7 +329,7 @@ impl<'tcx> pprust_hir::PpAnn for TypedAnnotation<'tcx> {
let typeck_results = self.maybe_typeck_results.get().or_else(|| {
self.tcx
.hir()
- .maybe_body_owned_by(expr.hir_id.owner)
+ .maybe_body_owned_by(expr.hir_id.owner.def_id)
.map(|body_id| self.tcx.typeck_body(body_id))
});
@@ -502,7 +502,7 @@ fn print_with_analysis(
ThirTree => {
let mut out = String::new();
- abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess);
+ abort_on_err(rustc_hir_analysis::check_crate(tcx), tcx.sess);
debug!("pretty printing THIR tree");
for did in tcx.hir().body_owners() {
let _ = writeln!(
diff --git a/compiler/rustc_driver/src/session_diagnostics.rs b/compiler/rustc_driver/src/session_diagnostics.rs
index e9696792d..c1bc10891 100644
--- a/compiler/rustc_driver/src/session_diagnostics.rs
+++ b/compiler/rustc_driver/src/session_diagnostics.rs
@@ -1,39 +1,39 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_unable_to_read)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_unable_to_read)]
pub(crate) struct RlinkUnableToRead {
pub err: std::io::Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_wrong_file_type)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_wrong_file_type)]
pub(crate) struct RLinkWrongFileType;
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_empty_version_number)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_empty_version_number)]
pub(crate) struct RLinkEmptyVersionNumber;
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_encoding_version_mismatch)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_encoding_version_mismatch)]
pub(crate) struct RLinkEncodingVersionMismatch {
pub version_array: String,
pub rlink_version: u32,
}
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_rustc_version_mismatch)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_rustc_version_mismatch)]
pub(crate) struct RLinkRustcVersionMismatch<'a> {
pub rustc_version: String,
pub current_version: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(driver::rlink_no_a_file)]
+#[derive(Diagnostic)]
+#[diag(driver_rlink_no_a_file)]
pub(crate) struct RlinkNotAFile;
-#[derive(SessionDiagnostic)]
-#[diag(driver::unpretty_dump_fail)]
+#[derive(Diagnostic)]
+#[diag(driver_unpretty_dump_fail)]
pub(crate) struct UnprettyDumpFail {
pub path: String,
pub err: String,
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 854625579..1e86d1596 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"),
E0308: include_str!("./error_codes/E0308.md"),
E0309: include_str!("./error_codes/E0309.md"),
E0310: include_str!("./error_codes/E0310.md"),
+E0311: include_str!("./error_codes/E0311.md"),
E0312: include_str!("./error_codes/E0312.md"),
E0316: include_str!("./error_codes/E0316.md"),
E0317: include_str!("./error_codes/E0317.md"),
@@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"),
// E0300, // unexpanded macro
// E0304, // expected signed integer constant
// E0305, // expected constant
- E0311, // thing may not live long enough
E0313, // lifetime of borrowed pointer outlives lifetime of captured
// variable
// E0314, // closure outlives stack frame
diff --git a/compiler/rustc_error_codes/src/error_codes/E0045.md b/compiler/rustc_error_codes/src/error_codes/E0045.md
index 143c693bf..1cb214531 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0045.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0045.md
@@ -3,9 +3,7 @@ Variadic parameters have been used on a non-C ABI function.
Erroneous code example:
```compile_fail,E0045
-#![feature(unboxed_closures)]
-
-extern "rust-call" {
+extern "Rust" {
fn foo(x: u8, ...); // error!
}
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0092.md b/compiler/rustc_error_codes/src/error_codes/E0092.md
index 496174b28..5cbe2a188 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0092.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0092.md
@@ -19,6 +19,6 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in
#![feature(intrinsics)]
extern "rust-intrinsic" {
- fn atomic_fence(); // ok!
+ fn atomic_fence_seqcst(); // ok!
}
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md
index ec86ec44e..cc546bdbb 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0094.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0094.md
@@ -6,6 +6,7 @@ Erroneous code example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; // error: intrinsic has wrong number
// of type parameters
}
@@ -19,6 +20,7 @@ Example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
}
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0161.md b/compiler/rustc_error_codes/src/error_codes/E0161.md
index ebd2c9769..643990ef1 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0161.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0161.md
@@ -3,7 +3,6 @@ A value was moved whose size was not known at compile time.
Erroneous code example:
```compile_fail,E0161
-#![feature(box_syntax)]
trait Bar {
fn f(self);
}
@@ -13,7 +12,7 @@ impl Bar for i32 {
}
fn main() {
- let b: Box<dyn Bar> = box (0 as i32);
+ let b: Box<dyn Bar> = Box::new(0i32);
b.f();
// error: cannot move a value of type dyn Bar: the size of dyn Bar cannot
// be statically determined
@@ -27,8 +26,6 @@ either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move
it around as usual. Example:
```
-#![feature(box_syntax)]
-
trait Bar {
fn f(&self);
}
@@ -38,7 +35,7 @@ impl Bar for i32 {
}
fn main() {
- let b: Box<dyn Bar> = box (0 as i32);
+ let b: Box<dyn Bar> = Box::new(0i32);
b.f();
// ok!
}
diff --git a/compiler/rustc_error_codes/src/error_codes/E0210.md b/compiler/rustc_error_codes/src/error_codes/E0210.md
index dc2fd9b0c..41263e5e3 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0210.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0210.md
@@ -76,7 +76,5 @@ Let `Ti` be the first such type.
For information on the design of the orphan rules,
see [RFC 2451] and [RFC 1023].
-For information on the design of the orphan rules, see [RFC 1023].
-
[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html
[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md
index 77289f019..8c2462ebd 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0211.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0211.md
@@ -7,6 +7,7 @@ used. Erroneous code examples:
#![feature(intrinsics)]
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T>(); // error: intrinsic has wrong type
}
@@ -42,6 +43,7 @@ For the first code example, please check the function definition. Example:
#![feature(intrinsics)]
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T>() -> usize; // ok!
}
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0311.md b/compiler/rustc_error_codes/src/error_codes/E0311.md
new file mode 100644
index 000000000..08159d3f4
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0311.md
@@ -0,0 +1,42 @@
+This error occurs when there is an unsatisfied outlives bound involving an
+elided region and a generic type parameter or associated type.
+
+Erroneous code example:
+
+```compile_fail,E0311
+fn no_restriction<T>(x: &()) -> &() {
+ with_restriction::<T>(x)
+}
+
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ x
+}
+```
+
+Why doesn't this code compile? It helps to look at the lifetime bounds that are
+automatically added by the compiler. For more details see the documentation for
+[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).
+
+The compiler elides the lifetime of `x` and the return type to some arbitrary
+lifetime `'anon` in `no_restriction()`. The only information available to the
+compiler is that `'anon` is valid for the duration of the function. When
+calling `with_restriction()`, the compiler requires the completely unrelated
+type parameter `T` to outlive `'anon` because of the `T: 'a` bound in
+`with_restriction()`. This causes an error because `T` is not required to
+outlive `'anon` in `no_restriction()`.
+
+If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
+compiler would have added an implied bound, causing this to compile.
+
+This error can be resolved by explicitly naming the elided lifetime for `x` and
+then explicily requiring that the generic parameter `T` outlives that lifetime:
+
+```
+fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ with_restriction::<T>(x)
+}
+
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ x
+}
+```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0579.md b/compiler/rustc_error_codes/src/error_codes/E0579.md
index f554242a3..e7e6fb682 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0579.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0579.md
@@ -8,9 +8,9 @@ Erroneous code example:
fn main() {
match 5u32 {
// This range is ok, albeit pointless.
- 1 .. 2 => {}
+ 1..2 => {}
// This range is empty, and the compiler can tell.
- 5 .. 5 => {} // error!
+ 5..5 => {} // error!
}
}
```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0591.md b/compiler/rustc_error_codes/src/error_codes/E0591.md
index f49805d9b..6ed8370e8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0591.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0591.md
@@ -53,8 +53,8 @@ unsafe {
```
Here, transmute is being used to convert the types of the fn arguments.
-This pattern is incorrect because, because the type of `foo` is a function
-**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
+This pattern is incorrect because the type of `foo` is a function **item**
+(`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
is a function pointer, which is not zero-sized.
This pattern should be rewritten. There are a few possible ways to do this:
diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md
index 990a25494..3ba3ed10e 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0622.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0622.md
@@ -5,7 +5,7 @@ Erroneous code example:
```compile_fail,E0622
#![feature(intrinsics)]
extern "rust-intrinsic" {
- pub static breakpoint : fn(); // error: intrinsic must be a function
+ pub static breakpoint: fn(); // error: intrinsic must be a function
}
fn main() { unsafe { breakpoint(); } }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0732.md b/compiler/rustc_error_codes/src/error_codes/E0732.md
index 7347e6654..9536fdbf0 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0732.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0732.md
@@ -3,8 +3,6 @@ An `enum` with a discriminant must specify a `#[repr(inttype)]`.
Erroneous code example:
```compile_fail,E0732
-#![feature(arbitrary_enum_discriminant)]
-
enum Enum { // error!
Unit = 1,
Tuple() = 2,
@@ -20,8 +18,6 @@ is a well-defined way to extract a variant's discriminant from a value;
for instance:
```
-#![feature(arbitrary_enum_discriminant)]
-
#[repr(u8)]
enum Enum {
Unit = 3,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0743.md b/compiler/rustc_error_codes/src/error_codes/E0743.md
index ddd3136df..a19d3ef96 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0743.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0743.md
@@ -3,8 +3,6 @@ The C-variadic type `...` has been nested inside another type.
Erroneous code example:
```compile_fail,E0743
-#![feature(c_variadic)]
-
fn foo2(x: u8, y: &...) {} // error!
```
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index fc84c7c86..9945f3379 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
fluent-bundle = "0.15.2"
diff --git a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
index c45e045b4..03c88c6c0 100644
--- a/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/ast_lowering.ftl
@@ -7,7 +7,9 @@ ast_lowering_use_angle_brackets = use angle brackets instead
ast_lowering_invalid_abi =
invalid ABI: found `{$abi}`
.label = invalid ABI
- .help = valid ABIs: {$valid_abis}
+ .note = invoke `{$command}` for a full list of supported calling conventions.
+
+ast_lowering_invalid_abi_suggestion = did you mean
ast_lowering_assoc_ty_parentheses =
parenthesized generic arguments cannot be used in associated type constraints
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
new file mode 100644
index 000000000..178e1a67c
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_gcc.ftl
@@ -0,0 +1,68 @@
+codegen_gcc_ranlib_failure =
+ Ranlib exited with code {$exit_code}
+
+codegen_gcc_linkage_const_or_mut_type =
+ must have type `*const T` or `*mut T` due to `#[linkage]` attribute
+
+codegen_gcc_unwinding_inline_asm =
+ GCC backend does not support unwinding from inline asm
+
+codegen_gcc_lto_not_supported =
+ LTO is not supported. You may get a linker error.
+
+codegen_gcc_invalid_monomorphization_basic_integer =
+ invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
+
+codegen_gcc_invalid_monomorphization_invalid_float_vector =
+ invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$elem_ty}` of floating-point vector `{$vec_ty}`
+
+codegen_gcc_invalid_monomorphization_not_float =
+ invalid monomorphization of `{$name}` intrinsic: `{$ty}` is not a floating-point type
+
+codegen_gcc_invalid_monomorphization_unrecognized =
+ invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}`
+
+codegen_gcc_invalid_monomorphization_expected_signed_unsigned =
+ invalid monomorphization of `{$name}` intrinsic: expected element type `{$elem_ty}` of vector type `{$vec_ty}` to be a signed or unsigned integer type
+
+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}]`
+
+codegen_gcc_invalid_monomorphization_simd_shuffle =
+ invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}`
+
+codegen_gcc_invalid_monomorphization_expected_simd =
+ invalid monomorphization of `{$name}` intrinsic: expected SIMD {$expected_ty} type, found non-SIMD `{$found_ty}`
+
+codegen_gcc_invalid_monomorphization_mask_type =
+ invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_`
+
+codegen_gcc_invalid_monomorphization_return_length =
+ invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len}
+
+codegen_gcc_invalid_monomorphization_return_length_input_type =
+ invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len}
+
+codegen_gcc_invalid_monomorphization_return_element =
+ invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_type =
+ invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}`
+
+codegen_gcc_invalid_monomorphization_inserted_type =
+ invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_return_integer_type =
+ invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}`
+
+codegen_gcc_invalid_monomorphization_mismatched_lengths =
+ invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}`
+
+codegen_gcc_invalid_monomorphization_unsupported_cast =
+ invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}`
+
+codegen_gcc_invalid_monomorphization_unsupported_operation =
+ invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
new file mode 100644
index 000000000..966a421bc
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl
@@ -0,0 +1,121 @@
+codegen_ssa_lib_def_write_failure = failed to write lib.def file: {$error}
+
+codegen_ssa_version_script_write_failure = failed to write version script: {$error}
+
+codegen_ssa_symbol_file_write_failure = failed to write symbols file: {$error}
+
+codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
+
+codegen_ssa_linker_unsupported_modifier = `as-needed` modifier not supported for current linker
+
+codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not implemented yet for L4Bender
+
+codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
+
+codegen_ssa_copy_path = could not copy {$from} to {$to}: {$error}
+
+codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$error}
+
+codegen_ssa_ignoring_emit_path = ignoring emit path because multiple .{$extension} files were produced
+
+codegen_ssa_ignoring_output = ignoring -o because multiple .{$extension} files were produced
+
+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_add_native_library = failed to add native library {$library_path}: {$error}
+
+codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
+
+codegen_ssa_rlib_missing_format = could not find formats for rlibs
+
+codegen_ssa_rlib_only_rmeta_found = could not find rlib for: `{$crate_name}`, found rmeta (metadata) file
+
+codegen_ssa_rlib_not_found = could not find rlib for: `{$crate_name}`
+
+codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
+
+codegen_ssa_linking_failed = linking with `{$linker_path}` failed: {$exit_status}
+
+codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
+
+codegen_ssa_specify_libraries_to_link = use the `-l` flag to specify native libraries to link
+
+codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
+
+codegen_ssa_thorin_read_input_failure = failed to read input file
+
+codegen_ssa_thorin_parse_input_file_kind = failed to parse input file kind
+
+codegen_ssa_thorin_parse_input_object_file = failed to parse input object file
+
+codegen_ssa_thorin_parse_input_archive_file = failed to parse input archive file
+
+codegen_ssa_thorin_parse_archive_member = failed to parse archive member
+
+codegen_ssa_thorin_invalid_input_kind = input is not an archive or elf object
+
+codegen_ssa_thorin_decompress_data = failed to decompress compressed section
+
+codegen_ssa_thorin_section_without_name = section without name at offset {$offset}
+
+codegen_ssa_thorin_relocation_with_invalid_symbol = relocation with invalid symbol for section `{$section}` at offset {$offset}
+
+codegen_ssa_thorin_multiple_relocations = multiple relocations for section `{$section}` at offset {$offset}
+
+codegen_ssa_thorin_unsupported_relocation = unsupported relocation for section {$section} at offset {$offset}
+
+codegen_ssa_thorin_missing_dwo_name = missing path attribute to DWARF object ({$id})
+
+codegen_ssa_thorin_no_compilation_units = input object has no compilation units
+
+codegen_ssa_thorin_no_die = no top-level debugging information entry in compilation/type unit
+
+codegen_ssa_thorin_top_level_die_not_unit = top-level debugging information entry is not a compilation/type unit
+
+codegen_ssa_thorin_missing_required_section = input object missing required section `{$section}`
+
+codegen_ssa_thorin_parse_unit_abbreviations = failed to parse unit abbreviations
+
+codegen_ssa_thorin_parse_unit_attribute = failed to parse unit attribute
+
+codegen_ssa_thorin_parse_unit_header = failed to parse unit header
+
+codegen_ssa_thorin_parse_unit = failed to parse unit
+
+codegen_ssa_thorin_incompatible_index_version = incompatible `{$section}` index version: found version {$actual}, expected version {$format}
+
+codegen_ssa_thorin_offset_at_index = read offset at index {$index} of `.debug_str_offsets.dwo` section
+
+codegen_ssa_thorin_str_at_offset = read string at offset {$offset} of `.debug_str.dwo` section
+
+codegen_ssa_thorin_parse_index = failed to parse `{$section}` index section
+
+codegen_ssa_thorin_unit_not_in_index = unit {$unit} from input package is not in its index
+
+codegen_ssa_thorin_row_not_in_index = row {$row} found in index's hash table not present in index
+
+codegen_ssa_thorin_section_not_in_row = section not found in unit's row in index
+
+codegen_ssa_thorin_empty_unit = unit {$unit} in input DWARF object with no data
+
+codegen_ssa_thorin_multiple_debug_info_section = multiple `.debug_info.dwo` sections
+
+codegen_ssa_thorin_multiple_debug_types_section = multiple `.debug_types.dwo` sections in a package
+
+codegen_ssa_thorin_not_split_unit = regular compilation unit in object (missing dwo identifier)
+
+codegen_ssa_thorin_duplicate_unit = duplicate split compilation unit ({$unit})
+
+codegen_ssa_thorin_missing_referenced_unit = unit {$unit} referenced by executable was not found
+
+codegen_ssa_thorin_not_output_object_created = no output object was created from inputs
+
+codegen_ssa_thorin_mixed_input_encodings = input objects haved mixed encodings
+
+codegen_ssa_thorin_io = {$error}
+codegen_ssa_thorin_object_read = {$error}
+codegen_ssa_thorin_object_write = {$error}
+codegen_ssa_thorin_gimli_read = {$error}
+codegen_ssa_thorin_gimli_write = {$error}
diff --git a/compiler/rustc_error_messages/locales/en-US/compiletest.ftl b/compiler/rustc_error_messages/locales/en-US/compiletest.ftl
new file mode 100644
index 000000000..55061fbce
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/compiletest.ftl
@@ -0,0 +1,5 @@
+compiletest_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/compiler/rustc_error_messages/locales/en-US/errors.ftl b/compiler/rustc_error_messages/locales/en-US/errors.ftl
new file mode 100644
index 000000000..429bdd277
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/errors.ftl
@@ -0,0 +1,13 @@
+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/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
index 272731d99..74088f4df 100644
--- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/hir_analysis.ftl
@@ -1,101 +1,101 @@
-typeck_field_multiply_specified_in_initializer =
+hir_analysis_field_multiply_specified_in_initializer =
field `{$ident}` specified more than once
.label = used more than once
.previous_use_label = first use of `{$ident}`
-typeck_unrecognized_atomic_operation =
+hir_analysis_unrecognized_atomic_operation =
unrecognized atomic operation function: `{$op}`
.label = unrecognized atomic operation
-typeck_wrong_number_of_generic_arguments_to_intrinsic =
+hir_analysis_wrong_number_of_generic_arguments_to_intrinsic =
intrinsic has wrong number of {$descr} parameters: found {$found}, expected {$expected}
.label = expected {$expected} {$descr} {$expected ->
[one] parameter
*[other] parameters
}
-typeck_unrecognized_intrinsic_function =
+hir_analysis_unrecognized_intrinsic_function =
unrecognized intrinsic function: `{$name}`
.label = unrecognized intrinsic
-typeck_lifetimes_or_bounds_mismatch_on_trait =
+hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
.label = lifetimes do not match {$item_kind} in trait
.generics_label = lifetimes in impl do not match this {$item_kind} in trait
-typeck_drop_impl_on_wrong_item =
+hir_analysis_drop_impl_on_wrong_item =
the `Drop` trait may only be implemented for local structs, enums, and unions
.label = must be a struct, enum, or union in the current crate
-typeck_field_already_declared =
+hir_analysis_field_already_declared =
field `{$field_name}` is already declared
.label = field already declared
.previous_decl_label = `{$field_name}` first declared here
-typeck_copy_impl_on_type_with_dtor =
+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
-typeck_multiple_relaxed_default_bounds =
+hir_analysis_multiple_relaxed_default_bounds =
type parameter has more than one relaxed default bound, only one is supported
-typeck_copy_impl_on_non_adt =
+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
-typeck_trait_object_declared_with_no_traits =
+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
-typeck_ambiguous_lifetime_bound =
+hir_analysis_ambiguous_lifetime_bound =
ambiguous lifetime bound, explicit lifetime bound required
-typeck_assoc_type_binding_not_allowed =
+hir_analysis_assoc_type_binding_not_allowed =
associated type bindings are not allowed here
.label = associated type not allowed here
-typeck_functional_record_update_on_non_struct =
+hir_analysis_functional_record_update_on_non_struct =
functional record update syntax requires a struct
-typeck_typeof_reserved_keyword_used =
+hir_analysis_typeof_reserved_keyword_used =
`typeof` is a reserved keyword but unimplemented
.suggestion = consider replacing `typeof(...)` with an actual type
.label = reserved keyword
-typeck_return_stmt_outside_of_fn_body =
+hir_analysis_return_stmt_outside_of_fn_body =
return statement outside of function body
.encl_body_label = the return is part of this body...
.encl_fn_label = ...not the enclosing function body
-typeck_yield_expr_outside_of_generator =
+hir_analysis_yield_expr_outside_of_generator =
yield expression outside of generator literal
-typeck_struct_expr_non_exhaustive =
+hir_analysis_struct_expr_non_exhaustive =
cannot create non-exhaustive {$what} using struct expression
-typeck_method_call_on_unknown_type =
+hir_analysis_method_call_on_unknown_type =
the type of this value must be known to call a method on a raw pointer on it
-typeck_value_of_associated_struct_already_specified =
+hir_analysis_value_of_associated_struct_already_specified =
the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
.label = re-bound here
.previous_bound_label = `{$item_name}` bound here first
-typeck_address_of_temporary_taken = cannot take address of a temporary
+hir_analysis_address_of_temporary_taken = cannot take address of a temporary
.label = temporary value
-typeck_add_return_type_add = try adding a return type
+hir_analysis_add_return_type_add = try adding a return type
-typeck_add_return_type_missing_here = a return type might be missing here
+hir_analysis_add_return_type_missing_here = a return type might be missing here
-typeck_expected_default_return_type = expected `()` because of default return type
+hir_analysis_expected_default_return_type = expected `()` because of default return type
-typeck_expected_return_type = expected `{$expected}` because of return type
+hir_analysis_expected_return_type = expected `{$expected}` because of return type
-typeck_unconstrained_opaque_type = unconstrained opaque type
- .note = `{$name}` must be used in combination with a concrete type within the same module
+hir_analysis_unconstrained_opaque_type = unconstrained opaque type
+ .note = `{$name}` must be used in combination with a concrete type within the same {$what}
-typeck_missing_type_params =
+hir_analysis_missing_type_params =
the type {$parameterCount ->
[one] parameter
*[other] parameters
@@ -117,19 +117,36 @@ typeck_missing_type_params =
} to {$parameters}
.note = because of the default `Self` reference, type parameters must be specified on object types
-typeck_manual_implementation =
+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
-typeck_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
-typeck_unused_extern_crate =
+hir_analysis_unused_extern_crate =
unused extern crate
.suggestion = remove it
-typeck_extern_crate_not_idiomatic =
+hir_analysis_extern_crate_not_idiomatic =
`extern crate` is not idiomatic in the new edition
.suggestion = convert it to a `{$msg_code}`
-typeck_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
+
+hir_analysis_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
+
+hir_analysis_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
+
+hir_analysis_const_impl_for_non_const_trait =
+ const `impl` for trait `{$trait_name}` which is not marked with `#[const_trait]`
+ .suggestion = mark `{$trait_name}` as const
+ .note = marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ .adding = adding a non-const method body in the future would be a breaking change
+
+hir_analysis_const_bound_for_non_const_trait =
+ ~const can only be applied to `#[const_trait]` traits
+
+hir_analysis_self_in_impl_self =
+ `Self` is not valid in the self type of an impl block
+ .note = replace `Self` with a different type
diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl
index 65371a285..18b3408b0 100644
--- a/compiler/rustc_error_messages/locales/en-US/infer.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl
@@ -164,7 +164,9 @@ infer_region_explanation = {$pref_kind ->
}
infer_mismatched_static_lifetime = incompatible lifetime on type
-infer_msl_impl_note = ...does not necessarily outlive the static lifetime introduced by the compatible `impl`
+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
+infer_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement
infer_msl_introduces_static = introduces a `'static` lifetime requirement
infer_msl_unmet_req = because this has an unmet lifetime requirement
infer_msl_trait_note = this has an implicit `'static` lifetime requirement
diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl
index 7f9918e4f..7e28f22c0 100644
--- a/compiler/rustc_error_messages/locales/en-US/lint.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl
@@ -51,7 +51,7 @@ lint_non_existant_doc_keyword = found non-existing keyword `{$keyword}` used in
.help = only existing keywords are allowed in core/std
lint_diag_out_of_impl =
- diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+ diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
lint_untranslatable_diag = diagnostics should be created using translatable messages
@@ -433,3 +433,8 @@ lint_check_name_unknown_tool = unknown lint tool: `{$tool_name}`
lint_check_name_warning = {$msg}
lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
+
+lint_opaque_hidden_inferred_bound = opaque type `{$ty}` does not satisfy its associated type bounds
+ .specifically = this associated type bound is unsatisfied for `{$proj_ty}`
+
+lint_opaque_hidden_inferred_bound_sugg = add this bound
diff --git a/compiler/rustc_error_messages/locales/en-US/metadata.ftl b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
index d27100c56..08e553d9f 100644
--- a/compiler/rustc_error_messages/locales/en-US/metadata.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/metadata.ftl
@@ -165,6 +165,8 @@ metadata_failed_write_error =
metadata_missing_native_library =
could not find native static library `{$libname}`, perhaps an -L flag is missing?
+metadata_only_provide_library_name = only provide the library name `{$suggested_name}`, not the full filename
+
metadata_failed_create_tempdir =
couldn't create a temp dir: {$err}
diff --git a/compiler/rustc_error_messages/locales/en-US/middle.ftl b/compiler/rustc_error_messages/locales/en-US/middle.ftl
index ed8348864..b9e4499d4 100644
--- a/compiler/rustc_error_messages/locales/en-US/middle.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/middle.ftl
@@ -15,3 +15,15 @@ middle_previous_use_here =
middle_limit_invalid =
`limit` must be a non-negative integer
.label = {$error_str}
+
+middle_const_eval_non_int =
+ constant evaluation of enum discriminant resulted in non-integer
+
+middle_unknown_layout =
+ the type `{$ty}` has an unknown layout
+
+middle_values_too_big =
+ values of the type `{$ty}` are too big for the current architecture
+
+middle_cannot_be_normalized =
+ unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized
diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl
index f74df3d97..13c368d1c 100644
--- a/compiler/rustc_error_messages/locales/en-US/parser.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl
@@ -47,7 +47,7 @@ parser_invalid_comparison_operator = invalid comparison operator `{$invalid}`
.spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
parser_invalid_logical_operator = `{$incorrect}` is not a logical operator
- .note = unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ .note = unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
.use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
.use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
@@ -55,7 +55,9 @@ parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
.suggestion = use `!` to perform bitwise not
parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier
- .suggestion = use `!` to perform logical negation
+parser_unexpected_token_after_not_bitwise = use `!` to perform bitwise not
+parser_unexpected_token_after_not_logical = use `!` to perform logical negation
+parser_unexpected_token_after_not_default = use `!` to perform logical negation or bitwise not
parser_malformed_loop_label = malformed loop label
.suggestion = use the correct loop label format
@@ -69,6 +71,8 @@ parser_field_expression_with_generic = field expressions cannot have generic arg
parser_macro_invocation_with_qualified_path = macros cannot use qualified paths
parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
+ .suggestion_remove_label = consider removing the label
+ .suggestion_enclose_in_block = consider enclosing expression in a block
parser_require_colon_after_labeled_expression = labeled expression must be followed by `:`
.note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
@@ -156,3 +160,212 @@ parser_remove_let = expected pattern, found `let`
parser_use_eq_instead = unexpected `==`
.suggestion = try using `=` instead
+
+parser_use_empty_block_not_semi = expected { "`{}`" }, found `;`
+ .suggestion = try using { "`{}`" } instead
+
+parser_comparison_interpreted_as_generic =
+ `<` is interpreted as a start of generic arguments for `{$type}`, not a comparison
+ .label_args = interpreted as generic arguments
+ .label_comparison = not interpreted as comparison
+ .suggestion = try comparing the cast value
+
+parser_shift_interpreted_as_generic =
+ `<<` is interpreted as a start of generic arguments for `{$type}`, not a shift
+ .label_args = interpreted as generic arguments
+ .label_comparison = not interpreted as shift
+ .suggestion = try shifting the cast value
+
+parser_found_expr_would_be_stmt = expected expression, found `{$token}`
+ .label = expected expression
+
+parser_leading_plus_not_supported = leading `+` is not supported
+ .label = unexpected `+`
+ .suggestion_remove_plus = try removing the `+`
+
+parser_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call arguments
+ .suggestion_braces_for_struct = if `{$type}` is a struct, use braces as delimiters
+ .suggestion_no_fields_for_fn = if `{$type}` is a function, use the arguments directly
+
+parser_labeled_loop_in_break = parentheses are required around this expression to avoid confusion with a labeled break expression
+
+parser_sugg_wrap_expression_in_parentheses = wrap the expression in parentheses
+
+parser_array_brackets_instead_of_braces = this is a block expression, not an array
+ .suggestion = to make an array, use square brackets instead of curly braces
+
+parser_match_arm_body_without_braces = `match` arm body without braces
+ .label_statements = {$num_statements ->
+ [one] this statement is not surrounded by a body
+ *[other] these statements are not surrounded by a body
+ }
+ .label_arrow = while parsing the `match` arm starting here
+ .suggestion_add_braces = surround the {$num_statements ->
+ [one] statement
+ *[other] statements
+ } with a body
+ .suggestion_use_comma_not_semicolon = use a comma to end a `match` arm expression
+
+parser_struct_literal_not_allowed_here = struct literals are not allowed here
+ .suggestion = surround the struct literal with parentheses
+
+parser_invalid_interpolated_expression = invalid interpolated expression
+
+parser_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+parser_octal_float_literal_not_supported = octal float literal is not supported
+parser_binary_float_literal_not_supported = binary float literal is not supported
+parser_not_supported = not supported
+
+parser_invalid_literal_suffix = suffixes on {$kind} literals are invalid
+ .label = invalid suffix `{$suffix}`
+
+parser_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
+ .tuple_exception_line_2 = on proc macros, you'll want to use `syn::Index::from` or `proc_macro::Literal::*_unsuffixed` for code that will desugar to tuple field access
+ .tuple_exception_line_3 = see issue #60210 <https://github.com/rust-lang/rust/issues/60210> for more information
+
+parser_non_string_abi_literal = non-string ABI literal
+ .suggestion = specify the ABI with a string literal
+
+parser_mismatched_closing_delimiter = mismatched closing delimiter: `{$delimiter}`
+ .label_unmatched = mismatched closing delimiter
+ .label_opening_candidate = closing delimiter possibly meant for this
+ .label_unclosed = unclosed delimiter
+
+parser_incorrect_visibility_restriction = incorrect visibility restriction
+ .help = some possible visibility restrictions are:
+ `pub(crate)`: visible only on the current crate
+ `pub(super)`: visible only in the current module's parent
+ `pub(in path::to::module)`: visible only on the specified path
+ .suggestion = make this visible only to module `{$inner_str}` with `in`
+
+parser_assignment_else_not_allowed = <assignment> ... else {"{"} ... {"}"} is not allowed
+
+parser_expected_statement_after_outer_attr = expected statement after outer attribute
+
+parser_doc_comment_does_not_document_anything = found a documentation comment that doesn't document anything
+ .help = doc comments must come before what they document, if a comment was intended use `//`
+ .suggestion = missing comma here
+
+parser_const_let_mutually_exclusive = `const` and `let` are mutually exclusive
+ .suggestion = remove `let`
+
+parser_invalid_expression_in_let_else = a `{$operator}` expression cannot be directly assigned in `let...else`
+parser_invalid_curly_in_let_else = right curly brace `{"}"}` before `else` in a `let...else` statement not allowed
+
+parser_compound_assignment_expression_in_let = can't reassign to an uninitialized variable
+ .suggestion = initialize the variable
+ .help = if you meant to overwrite, remove the `let` binding
+
+parser_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
+ .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+parser_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}`
+
+parser_label_inner_attr_does_not_annotate_this = the inner attribute doesn't annotate this {$item}
+parser_sugg_change_inner_attr_to_outer = to annotate the {$item}, change the attribute from inner to outer style
+
+parser_inner_attr_not_permitted_after_outer_doc_comment = an inner attribute is not permitted following an outer doc comment
+ .label_attr = not permitted following an outer doc comment
+ .label_prev_doc_comment = previous doc comment
+ .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer}
+
+parser_inner_attr_not_permitted_after_outer_attr = an inner attribute is not permitted following an outer attribute
+ .label_attr = not permitted following an outer attribute
+ .label_prev_attr = previous outer attribute
+ .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer}
+
+parser_inner_attr_not_permitted = an inner attribute is not permitted in this context
+ .label_does_not_annotate_this = {parser_label_inner_attr_does_not_annotate_this}
+ .sugg_change_inner_to_outer = {parser_sugg_change_inner_attr_to_outer}
+
+parser_inner_attr_explanation = inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files
+parser_outer_attr_explanation = outer attributes, like `#[test]`, annotate the item following them
+
+parser_inner_doc_comment_not_permitted = expected outer doc comment
+ .note = inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
+ .suggestion = you might have meant to write a regular comment
+ .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
+ .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
+
+parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token}`
+parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token}`
+parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token}`
+parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token}`
+parser_expected_identifier_found_str = expected identifier, found `{$token}`
+
+parser_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
+parser_expected_identifier_found_keyword = expected identifier, found keyword
+parser_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
+parser_expected_identifier_found_doc_comment = expected identifier, found doc comment
+parser_expected_identifier = expected identifier
+
+parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier
+
+parser_sugg_remove_comma = remove this comma
+
+parser_expected_semi_found_reserved_identifier_str = expected `;`, found reserved identifier `{$token}`
+parser_expected_semi_found_keyword_str = expected `;`, found keyword `{$token}`
+parser_expected_semi_found_reserved_keyword_str = expected `;`, found reserved keyword `{$token}`
+parser_expected_semi_found_doc_comment_str = expected `;`, found doc comment `{$token}`
+parser_expected_semi_found_str = expected `;`, found `{$token}`
+
+parser_sugg_change_this_to_semi = change this to `;`
+parser_sugg_add_semi = add `;` here
+parser_label_unexpected_token = unexpected token
+
+parser_unmatched_angle_brackets = {$num_extra_brackets ->
+ [one] unmatched angle bracket
+ *[other] unmatched angle brackets
+ }
+ .suggestion = {$num_extra_brackets ->
+ [one] remove extra angle bracket
+ *[other] remove extra angle brackets
+ }
+
+parser_generic_parameters_without_angle_brackets = generic parameters without surrounding angle brackets
+ .suggestion = surround the type parameters with angle brackets
+
+parser_comparison_operators_cannot_be_chained = comparison operators cannot be chained
+ .sugg_parentheses_for_function_args = or use `(...)` if you meant to specify fn arguments
+ .sugg_split_comparison = split the comparison into two
+ .sugg_parenthesize = parenthesize the comparison
+parser_sugg_turbofish_syntax = use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+
+parser_question_mark_in_type = invalid `?` in type
+ .label = `?` is only allowed on expressions, not types
+ .suggestion = if you meant to express that the type might not contain a value, use the `Option` wrapper type
+
+parser_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head
+ .suggestion = remove parentheses in `for` loop
+
+parser_doc_comment_on_param_type = documentation comments cannot be applied to a function parameter's type
+ .label = doc comments are not allowed here
+
+parser_attribute_on_param_type = attributes cannot be applied to a function parameter's type
+ .label = attributes are not allowed here
+
+parser_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
+ .suggestion = give this argument a name or use an underscore to ignore it
+
+parser_self_param_not_first = unexpected `self` parameter in function
+ .label = must be the first parameter of an associated function
+
+parser_const_generic_without_braces = expressions must be enclosed in braces to be used as const generic arguments
+ .suggestion = enclose the `const` expression in braces
+
+parser_unexpected_const_param_declaration = unexpected `const` parameter declaration
+ .label = expected a `const` expression, not a parameter declaration
+ .suggestion = `const` parameters must be declared for the `impl`
+
+parser_unexpected_const_in_generic_param = expected lifetime, type, or constant, found keyword `const`
+ .suggestion = the `const` keyword is only needed in the definition of the type
+
+parser_async_move_order_incorrect = the order of `move` and `async` is incorrect
+ .suggestion = try switching the order
+
+parser_double_colon_in_bound = expected `:` followed by trait or lifetime
+ .suggestion = use single colon
diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl
index 556a6452f..4bc6bd9fb 100644
--- a/compiler/rustc_error_messages/locales/en-US/passes.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl
@@ -10,88 +10,119 @@ passes_outer_crate_level_attr =
passes_inner_crate_level_attr =
crate-level attribute should be in the root module
-passes_ignored_attr_with_macro = `#[{$sym}]` is ignored on struct fields, match arms and macro defs
+passes_ignored_attr_with_macro =
+ `#[{$sym}]` is ignored on struct fields, match arms and macro defs
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "80564")}
-passes_ignored_attr = `#[{$sym}]` is ignored on struct fields and match arms
+passes_ignored_attr =
+ `#[{$sym}]` is ignored on struct fields and match arms
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "80564")}
-passes_inline_ignored_function_prototype = `#[inline]` is ignored on function prototypes
+passes_inline_ignored_function_prototype =
+ `#[inline]` is ignored on function prototypes
-passes_inline_ignored_constants = `#[inline]` is ignored on constants
+passes_inline_ignored_constants =
+ `#[inline]` is ignored on constants
.warn = {-passes_previously_accepted}
.note = {-passes_see_issue(issue: "65833")}
-passes_inline_not_fn_or_closure = attribute should be applied to function or closure
+passes_inline_not_fn_or_closure =
+ attribute should be applied to function or closure
.label = not a function or closure
-passes_no_coverage_ignored_function_prototype = `#[no_coverage]` is ignored on function prototypes
+passes_no_coverage_ignored_function_prototype =
+ `#[no_coverage]` is ignored on function prototypes
passes_no_coverage_propagate =
`#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
-passes_no_coverage_fn_defn = `#[no_coverage]` may only be applied to function definitions
+passes_no_coverage_fn_defn =
+ `#[no_coverage]` may only be applied to function definitions
-passes_no_coverage_not_coverable = `#[no_coverage]` must be applied to coverable code
+passes_no_coverage_not_coverable =
+ `#[no_coverage]` must be applied to coverable code
.label = not coverable code
-passes_should_be_applied_to_fn = attribute should be applied to a function definition
+passes_should_be_applied_to_fn =
+ attribute should be applied to a function definition
.label = not a function definition
-passes_naked_tracked_caller = cannot use `#[track_caller]` with `#[naked]`
+passes_naked_tracked_caller =
+ cannot use `#[track_caller]` with `#[naked]`
-passes_should_be_applied_to_struct_enum = attribute should be applied to a struct or enum
+passes_should_be_applied_to_struct_enum =
+ attribute should be applied to a struct or enum
.label = not a struct or enum
-passes_should_be_applied_to_trait = attribute should be applied to a trait
+passes_should_be_applied_to_trait =
+ attribute should be applied to a trait
.label = not a trait
-passes_target_feature_on_statement = {passes_should_be_applied_to_fn}
+passes_target_feature_on_statement =
+ {passes_should_be_applied_to_fn}
.warn = {-passes_previously_accepted}
.label = {passes_should_be_applied_to_fn.label}
-passes_should_be_applied_to_static = attribute should be applied to a static
+passes_should_be_applied_to_static =
+ attribute should be applied to a static
.label = not a static
-passes_doc_expect_str = doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
+passes_doc_expect_str =
+ doc {$attr_name} attribute expects a string: #[doc({$attr_name} = "a")]
-passes_doc_alias_empty = {$attr_str} attribute cannot have empty value
+passes_doc_alias_empty =
+ {$attr_str} attribute cannot have empty value
-passes_doc_alias_bad_char = {$char_} character isn't allowed in {$attr_str}
+passes_doc_alias_bad_char =
+ {$char_} character isn't allowed in {$attr_str}
-passes_doc_alias_start_end = {$attr_str} cannot start or end with ' '
+passes_doc_alias_start_end =
+ {$attr_str} cannot start or end with ' '
-passes_doc_alias_bad_location = {$attr_str} isn't allowed on {$location}
+passes_doc_alias_bad_location =
+ {$attr_str} isn't allowed on {$location}
-passes_doc_alias_not_an_alias = {$attr_str} is the same as the item's name
+passes_doc_alias_not_an_alias =
+ {$attr_str} is the same as the item's name
passes_doc_alias_duplicated = doc alias is duplicated
.label = first defined here
-passes_doc_alias_not_string_literal = `#[doc(alias("a"))]` expects string literals
+passes_doc_alias_not_string_literal =
+ `#[doc(alias("a"))]` expects string literals
passes_doc_alias_malformed =
doc alias attribute expects a string `#[doc(alias = "a")]` or a list of strings `#[doc(alias("a", "b"))]`
-passes_doc_keyword_empty_mod = `#[doc(keyword = "...")]` should be used on empty modules
+passes_doc_keyword_empty_mod =
+ `#[doc(keyword = "...")]` should be used on empty modules
-passes_doc_keyword_not_mod = `#[doc(keyword = "...")]` should be used on modules
+passes_doc_keyword_not_mod =
+ `#[doc(keyword = "...")]` should be used on modules
-passes_doc_keyword_invalid_ident = `{$doc_keyword}` is not a valid identifier
+passes_doc_keyword_invalid_ident =
+ `{$doc_keyword}` is not a valid identifier
passes_doc_fake_variadic_not_valid =
`#[doc(fake_variadic)]` must be used on the first of a set of tuple or fn pointer trait impls with varying arity
-passes_doc_keyword_only_impl = `#[doc(keyword = "...")]` should be used on impl blocks
+passes_doc_keyword_only_impl =
+ `#[doc(keyword = "...")]` should be used on impl blocks
-passes_doc_inline_conflict_first = this attribute...
-passes_doc_inline_conflict_second = ...conflicts with this attribute
-passes_doc_inline_conflict = conflicting doc inlining attributes
+passes_doc_inline_conflict_first =
+ this attribute...
+
+passes_doc_inline_conflict_second =
+ {"."}..conflicts with this attribute
+
+passes_doc_inline_conflict =
+ conflicting doc inlining attributes
.help = remove one of the conflicting attributes
-passes_doc_inline_only_use = this attribute can only be applied to a `use` item
+passes_doc_inline_only_use =
+ this attribute can only be applied to a `use` item
.label = only applicable on `use` items
.not_a_use_item_label = not a `use` item
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#inline-and-no_inline> for more information
@@ -99,30 +130,42 @@ passes_doc_inline_only_use = this attribute can only be applied to a `use` item
passes_doc_attr_not_crate_level =
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute
-passes_attr_crate_level = this attribute can only be applied at the crate level
+passes_attr_crate_level =
+ this attribute can only be applied at the crate level
.suggestion = to apply to the crate, use an inner attribute
.help = to apply to the crate, use an inner attribute
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
-passes_doc_test_unknown = unknown `doc(test)` attribute `{$path}`
+passes_doc_test_unknown =
+ unknown `doc(test)` attribute `{$path}`
+
+passes_doc_test_takes_list =
+ `#[doc(test(...)]` takes a list of attributes
-passes_doc_test_takes_list = `#[doc(test(...)]` takes a list of attributes
+passes_doc_primitive =
+ `doc(primitive)` should never have been stable
-passes_doc_primitive = `doc(primitive)` should never have been stable
+passes_doc_cfg_hide_takes_list =
+ `#[doc(cfg_hide(...)]` takes a list of attributes
-passes_doc_test_unknown_any = unknown `doc` attribute `{$path}`
+passes_doc_test_unknown_any =
+ unknown `doc` attribute `{$path}`
-passes_doc_test_unknown_spotlight = unknown `doc` attribute `{$path}`
+passes_doc_test_unknown_spotlight =
+ unknown `doc` attribute `{$path}`
.note = `doc(spotlight)` was renamed to `doc(notable_trait)`
.suggestion = use `notable_trait` instead
.no_op_note = `doc(spotlight)` is now a no-op
-passes_doc_test_unknown_include = unknown `doc` attribute `{$path}`
+passes_doc_test_unknown_include =
+ unknown `doc` attribute `{$path}`
.suggestion = use `doc = include_str!` instead
-passes_doc_invalid = invalid `doc` attribute
+passes_doc_invalid =
+ invalid `doc` attribute
-passes_pass_by_value = `pass_by_value` attribute should be applied to a struct, enum or type alias
+passes_pass_by_value =
+ `pass_by_value` attribute should be applied to a struct, enum or type alias
.label = is not a struct, enum or type alias
passes_allow_incoherent_impl =
@@ -137,42 +180,54 @@ 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`
-passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target}
+passes_must_use_no_effect =
+ `#[must_use]` has no effect when applied to {$article} {$target}
-passes_must_not_suspend = `must_not_suspend` attribute should be applied to a struct, enum, or trait
+passes_must_not_suspend =
+ `must_not_suspend` attribute should be applied to a struct, enum, or trait
.label = is not a struct, enum, or trait
-passes_cold = {passes_should_be_applied_to_fn}
+passes_cold =
+ {passes_should_be_applied_to_fn}
.warn = {-passes_previously_accepted}
.label = {passes_should_be_applied_to_fn.label}
-passes_link = attribute should be applied to an `extern` block with non-Rust ABI
+passes_link =
+ attribute should be applied to an `extern` block with non-Rust ABI
.warn = {-passes_previously_accepted}
.label = not an `extern` block
-passes_link_name = attribute should be applied to a foreign function or static
+passes_link_name =
+ attribute should be applied to a foreign function or static
.warn = {-passes_previously_accepted}
.label = not a foreign function or static
.help = try `#[link(name = "{$value}")]` instead
-passes_no_link = attribute should be applied to an `extern crate` item
+passes_no_link =
+ attribute should be applied to an `extern crate` item
.label = not an `extern crate` item
-passes_export_name = attribute should be applied to a free function, impl method or static
+passes_export_name =
+ attribute should be applied to a free function, impl method or static
.label = not a free function, impl method or static
-passes_rustc_layout_scalar_valid_range_not_struct = attribute should be applied to a struct
+passes_rustc_layout_scalar_valid_range_not_struct =
+ attribute should be applied to a struct
.label = not a struct
-passes_rustc_layout_scalar_valid_range_arg = expected exactly one integer literal argument
+passes_rustc_layout_scalar_valid_range_arg =
+ expected exactly one integer literal argument
-passes_rustc_legacy_const_generics_only = #[rustc_legacy_const_generics] functions must only have const generics
+passes_rustc_legacy_const_generics_only =
+ #[rustc_legacy_const_generics] functions must only have const generics
.label = non-const generic parameter
-passes_rustc_legacy_const_generics_index = #[rustc_legacy_const_generics] must have one index for each generic parameter
+passes_rustc_legacy_const_generics_index =
+ #[rustc_legacy_const_generics] must have one index for each generic parameter
.label = generic parameters
-passes_rustc_legacy_const_generics_index_exceed = index exceeds number of arguments
+passes_rustc_legacy_const_generics_index_exceed =
+ index exceeds number of arguments
.label = there {$arg_count ->
[one] is
*[other] are
@@ -181,90 +236,438 @@ passes_rustc_legacy_const_generics_index_exceed = index exceeds number of argume
*[other] arguments
}
-passes_rustc_legacy_const_generics_index_negative = arguments should be non-negative integers
+passes_rustc_legacy_const_generics_index_negative =
+ arguments should be non-negative integers
-passes_rustc_dirty_clean = attribute requires -Z query-dep-graph to be enabled
+passes_rustc_dirty_clean =
+ attribute requires -Z query-dep-graph to be enabled
-passes_link_section = attribute should be applied to a function or static
+passes_link_section =
+ attribute should be applied to a function or static
.warn = {-passes_previously_accepted}
.label = not a function or static
-passes_no_mangle_foreign = `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
+passes_no_mangle_foreign =
+ `#[no_mangle]` has no effect on a foreign {$foreign_item_kind}
.warn = {-passes_previously_accepted}
.label = foreign {$foreign_item_kind}
.note = symbol names in extern blocks are not mangled
.suggestion = remove this attribute
-passes_no_mangle = attribute should be applied to a free function, impl method or static
+passes_no_mangle =
+ attribute should be applied to a free function, impl method or static
.warn = {-passes_previously_accepted}
.label = not a free function, impl method or static
-passes_repr_ident = meta item in `repr` must be an identifier
+passes_repr_ident =
+ meta item in `repr` must be an identifier
-passes_repr_conflicting = conflicting representation hints
+passes_repr_conflicting =
+ conflicting representation hints
-passes_used_static = attribute must be applied to a `static` variable
+passes_used_static =
+ attribute must be applied to a `static` variable
-passes_used_compiler_linker = `used(compiler)` and `used(linker)` can't be used together
+passes_used_compiler_linker =
+ `used(compiler)` and `used(linker)` can't be used together
-passes_allow_internal_unstable = attribute should be applied to a macro
+passes_allow_internal_unstable =
+ attribute should be applied to a macro
.label = not a macro
-passes_debug_visualizer_placement = attribute should be applied to a module
+passes_debug_visualizer_placement =
+ attribute should be applied to a module
-passes_debug_visualizer_invalid = invalid argument
+passes_debug_visualizer_invalid =
+ invalid argument
.note_1 = expected: `natvis_file = "..."`
.note_2 = OR
.note_3 = expected: `gdb_script_file = "..."`
-passes_rustc_allow_const_fn_unstable = attribute should be applied to `const fn`
+passes_debug_visualizer_unreadable =
+ couldn't read {$file}: {$error}
+
+passes_rustc_allow_const_fn_unstable =
+ attribute should be applied to `const fn`
.label = not a `const fn`
-passes_rustc_std_internal_symbol = attribute should be applied to functions or statics
+passes_rustc_std_internal_symbol =
+ attribute should be applied to functions or statics
.label = not a function or static
-passes_const_trait = attribute should be applied to a trait
+passes_const_trait =
+ attribute should be applied to a trait
-passes_stability_promotable = attribute cannot be applied to an expression
+passes_stability_promotable =
+ attribute cannot be applied to an expression
-passes_deprecated = attribute is ignored here
+passes_deprecated =
+ attribute is ignored here
-passes_macro_use = `#[{$name}]` only has an effect on `extern crate` and modules
+passes_macro_use =
+ `#[{$name}]` only has an effect on `extern crate` and modules
-passes_macro_export = `#[macro_export]` only has an effect on macro definitions
+passes_macro_export =
+ `#[macro_export]` only has an effect on macro definitions
-passes_plugin_registrar = `#[plugin_registrar]` only has an effect on functions
+passes_plugin_registrar =
+ `#[plugin_registrar]` only has an effect on functions
-passes_unused_empty_lints_note = attribute `{$name}` with an empty list has no effect
+passes_unused_empty_lints_note =
+ attribute `{$name}` with an empty list has no effect
-passes_unused_no_lints_note = attribute `{$name}` without any lints has no effect
+passes_unused_no_lints_note =
+ attribute `{$name}` without any lints has no effect
passes_unused_default_method_body_const_note =
`default_method_body_is_const` has been replaced with `#[const_trait]` on traits
-passes_unused = unused attribute
+passes_unused =
+ unused attribute
.suggestion = remove this attribute
-passes_non_exported_macro_invalid_attrs = attribute should be applied to function or closure
+passes_non_exported_macro_invalid_attrs =
+ attribute should be applied to function or closure
.label = not a function or closure
-passes_unused_duplicate = unused attribute
+passes_unused_duplicate =
+ unused attribute
.suggestion = remove this attribute
.note = attribute also specified here
.warn = {-passes_previously_accepted}
-passes_unused_multiple = multiple `{$name}` attributes
+passes_unused_multiple =
+ multiple `{$name}` attributes
.suggestion = remove this attribute
.note = attribute also specified here
-passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct
+passes_rustc_lint_opt_ty =
+ `#[rustc_lint_opt_ty]` should be applied to a struct
.label = not a struct
-passes_rustc_lint_opt_deny_field_access = `#[rustc_lint_opt_deny_field_access]` should be applied to a field
+passes_rustc_lint_opt_deny_field_access =
+ `#[rustc_lint_opt_deny_field_access]` should be applied to a field
.label = not a field
-passes_link_ordinal = attribute should be applied to a foreign function or static
+passes_link_ordinal =
+ attribute should be applied to a foreign function or static
.label = not a foreign function or static
-passes_collapse_debuginfo = `collapse_debuginfo` attribute should be applied to macro definitions
+passes_collapse_debuginfo =
+ `collapse_debuginfo` attribute should be applied to macro definitions
.label = not a macro definition
+
+passes_deprecated_annotation_has_no_effect =
+ this `#[deprecated]` annotation has no effect
+ .suggestion = remove the unnecessary deprecation attribute
+
+passes_unknown_external_lang_item =
+ unknown external lang item: `{$lang_item}`
+
+passes_missing_panic_handler =
+ `#[panic_handler]` function required, but not found
+
+passes_alloc_func_required =
+ `#[alloc_error_handler]` function required, but not found
+
+passes_missing_alloc_error_handler =
+ use `#![feature(default_alloc_error_handler)]` for a default error handler
+
+passes_missing_lang_item =
+ language item required, but not found: `{$name}`
+ .note = this can occur when a binary crate with `#![no_std]` is compiled for a target where `{$name}` is defined in the standard library
+ .help = you may be able to compile for a target that doesn't need `{$name}`, specify a target with `--target` or in `.cargo/config`
+
+passes_lang_item_on_incorrect_target =
+ `{$name}` language item must be applied to a {$expected_target}
+ .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
+
+passes_unknown_lang_item =
+ definition of an unknown language item: `{$name}`
+ .label = definition of unknown language item `{$name}`
+
+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}`.
+
+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}
+
+passes_align =
+ align: {$align}
+
+passes_size =
+ size: {$size}
+
+passes_homogeneous_aggregate =
+ homogeneous_aggregate: {$homogeneous_aggregate}
+
+passes_layout_of =
+ layout_of({$normalized_ty}) = {$ty_layout}
+
+passes_unrecognized_field =
+ unrecognized field name `{$name}`
+
+passes_layout =
+ layout error: {$layout_error}
+
+passes_feature_stable_twice =
+ feature `{$feature}` is declared stable since {$since}, but was previously declared stable since {$prev_since}
+
+passes_feature_previously_declared =
+ feature `{$feature}` is declared {$declared}, but was previously declared {$prev_declared}
+
+passes_expr_not_allowed_in_context =
+ {$expr} is not allowed in a `{$context}`
+
+passes_const_impl_const_trait =
+ const `impl`s must be for traits marked with `#[const_trait]`
+ .note = this trait must be annotated with `#[const_trait]`
+
+passes_break_non_loop =
+ `break` with value from a `{$kind}` loop
+ .label = can only break with a value inside `loop` or breakable block
+ .label2 = you can't `break` with a value in a `{$kind}` loop
+ .suggestion = use `break` on its own without a value inside this `{$kind}` loop
+ .break_expr_suggestion = alternatively, you might have meant to use the available loop label
+
+passes_continue_labeled_block =
+ `continue` pointing to a labeled block
+ .label = labeled blocks cannot be `continue`'d
+ .block_label = labeled block the `continue` points to
+
+passes_break_inside_closure =
+ `{$name}` inside of a closure
+ .label = cannot `{$name}` inside of a closure
+ .closure_label = enclosing closure
+
+passes_break_inside_async_block =
+ `{$name}` inside of an `async` block
+ .label = cannot `{$name}` inside of an `async` block
+ .async_block_label = enclosing `async` block
+
+passes_outside_loop =
+ `{$name}` outside of a loop
+ .label = cannot `{$name}` outside of a loop
+
+passes_unlabeled_in_labeled_block =
+ unlabeled `{$cf_type}` inside of a labeled block
+ .label = `{$cf_type}` statements that would diverge to or through a labeled block need to bear a label
+
+passes_unlabeled_cf_in_while_condition =
+ `break` or `continue` with no label in the condition of a `while` loop
+ .label = unlabeled `{$cf_type}` in the condition of a `while` loop
+
+passes_cannot_inline_naked_function =
+ naked functions cannot be inlined
+
+passes_undefined_naked_function_abi =
+ Rust ABI is unsupported in naked functions
+
+passes_no_patterns =
+ patterns not allowed in naked function parameters
+
+passes_params_not_allowed =
+ referencing function parameters is not allowed in naked functions
+ .help = follow the calling convention in asm block to use parameters
+
+passes_naked_functions_asm_block =
+ naked functions must contain a single asm block
+ .label_multiple_asm = multiple asm blocks are unsupported in naked functions
+ .label_non_asm = non-asm is unsupported in naked functions
+
+passes_naked_functions_operands =
+ only `const` and `sym` operands are supported in naked functions
+
+passes_naked_functions_asm_options =
+ asm options unsupported in naked functions: {$unsupported_options}
+
+passes_naked_functions_must_use_noreturn =
+ asm in naked functions must use `noreturn` option
+ .suggestion = consider specifying that the asm block is responsible for returning from the function
+
+passes_attr_only_on_main =
+ `{$attr}` attribute can only be used on `fn main()`
+
+passes_attr_only_on_root_main =
+ `{$attr}` attribute can only be used on root `fn main()`
+
+passes_attr_only_in_functions =
+ `{$attr}` attribute can only be used on functions
+
+passes_multiple_rustc_main =
+ multiple functions with a `#[rustc_main]` attribute
+ .first = first `#[rustc_main]` function
+ .additional = additional `#[rustc_main]` function
+
+passes_multiple_start_functions =
+ multiple `start` functions
+ .label = multiple `start` functions
+ .previous = previous `#[start]` function here
+
+passes_extern_main =
+ the `main` function cannot be declared in an `extern` block
+
+passes_unix_sigpipe_values =
+ valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+
+passes_no_main_function =
+ `main` function not found in crate `{$crate_name}`
+ .here_is_main = here is a function named `main`
+ .one_or_more_possible_main = you have one or more functions named `main` not defined at the crate level
+ .consider_moving_main = consider moving the `main` function definitions
+ .main_must_be_defined_at_crate = the main function must be defined at the crate level{$has_filename ->
+ [true] {" "}(in `{$filename}`)
+ *[false] {""}
+ }
+ .consider_adding_main_to_file = consider adding a `main` function to `{$filename}`
+ .consider_adding_main_at_crate = consider adding a `main` function at the crate level
+ .teach_note = If you don't know the basics of Rust, you can go look to the Rust Book to get started: https://doc.rust-lang.org/book/
+ .non_function_main = non-function item at `crate::main` is found
+
+passes_duplicate_lang_item =
+ found duplicate lang item `{$lang_item_name}`
+ .first_defined_span = the lang item is first defined here
+ .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+ .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+ .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+ .second_definition_local = second definition in the local crate (`{$crate_name}`)
+ .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+ .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+
+passes_duplicate_lang_item_crate =
+ duplicate lang item in crate `{$crate_name}`: `{$lang_item_name}`.
+ .first_defined_span = the lang item is first defined here
+ .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+ .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+ .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+ .second_definition_local = second definition in the local crate (`{$crate_name}`)
+ .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+ .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+
+passes_duplicate_lang_item_crate_depends =
+ duplicate lang item in crate `{$crate_name}` (which `{$dependency_of}` depends on): `{$lang_item_name}`.
+ .first_defined_span = the lang item is first defined here
+ .first_defined_crate_depends = the lang item is first defined in crate `{$orig_crate_name}` (which `{$orig_dependency_of}` depends on)
+ .first_defined_crate = the lang item is first defined in crate `{$orig_crate_name}`.
+ .first_definition_local = first definition in the local crate (`{$orig_crate_name}`)
+ .second_definition_local = second definition in the local crate (`{$crate_name}`)
+ .first_definition_path = first definition in `{$orig_crate_name}` loaded from {$orig_path}
+ .second_definition_path = second definition in `{$crate_name}` loaded from {$path}
+
+passes_incorrect_target =
+ `{$name}` language item must be applied to a {$kind} with {$at_least ->
+ [true] at least {$num}
+ *[false] {$num}
+ } generic {$num ->
+ [one] argument
+ *[other] arguments
+ }
+ .label = this {$kind} has {$actual_num} generic {$actual_num ->
+ [one] argument
+ *[other] arguments
+ }
+
+passes_useless_assignment =
+ useless assignment of {$is_field_assign ->
+ [true] field
+ *[false] variable
+ } of type `{$ty}` to itself
+
+passes_only_has_effect_on =
+ `#[{$attr_name}]` only has an effect on {$target_name ->
+ [function] functions
+ [module] modules
+ [implementation_block] implementation blocks
+ *[unspecified] (unspecified--this is a compiler bug)
+ }
+
+passes_object_lifetime_err =
+ {$repr}
+
+passes_unrecognized_repr_hint =
+ unrecognized representation hint
+ .help = valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`
+
+passes_attr_application_enum =
+ attribute should be applied to an enum
+ .label = not an enum
+
+passes_attr_application_struct =
+ attribute should be applied to a struct
+ .label = not a struct
+
+passes_attr_application_struct_union =
+ attribute should be applied to a struct or union
+ .label = not a struct or union
+
+passes_attr_application_struct_enum_union =
+ attribute should be applied to a struct, enum, or union
+ .label = not a struct, enum, or union
+
+passes_attr_application_struct_enum_function_union =
+ attribute should be applied to a struct, enum, function, or union
+ .label = not a struct, enum, function, or union
+
+passes_transparent_incompatible =
+ transparent {$target} cannot have other repr hints
+
+passes_deprecated_attribute =
+ deprecated attribute must be paired with either stable or unstable attribute
+
+passes_useless_stability =
+ this stability annotation is useless
+ .label = useless stability annotation
+ .item = the stability attribute annotates this item
+
+passes_invalid_stability =
+ invalid stability version found
+ .label = invalid stability version
+ .item = the stability attribute annotates this item
+
+passes_cannot_stabilize_deprecated =
+ an API can't be stabilized after it is deprecated
+ .label = invalid version
+ .item = the stability attribute annotates this item
+
+passes_invalid_deprecation_version =
+ invalid deprecation version found
+ .label = invalid deprecation version
+ .item = the stability attribute annotates this item
+
+passes_missing_stability_attr =
+ {$descr} has missing stability attribute
+
+passes_missing_const_stab_attr =
+ {$descr} has missing const stability attribute
+
+passes_trait_impl_const_stable =
+ trait implementations cannot be const stable yet
+ .note = see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+
+passes_feature_only_on_nightly =
+ `#![feature]` may not be used on the {$release_channel} release channel
+
+passes_unknown_feature =
+ unknown feature `{$feature}`
+
+passes_implied_feature_not_exist =
+ feature `{$implied_by}` implying `{$feature}` does not exist
+
+passes_duplicate_feature_err =
+ the feature `{$feature}` has already been declared
+
+passes_missing_const_err =
+ attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
+ .help = make the function or method const
+ .label = attribute specified here
diff --git a/compiler/rustc_error_messages/locales/en-US/privacy.ftl b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
index da987152f..a26d1b2b3 100644
--- a/compiler/rustc_error_messages/locales/en-US/privacy.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/privacy.ftl
@@ -11,7 +11,7 @@ privacy_in_public_interface = {$vis_descr} {$kind} `{$descr}` in public interfac
.label = can't leak {$vis_descr} {$kind}
.visibility_label = `{$descr}` declared as {$vis_descr}
-privacy_report_access_level = {$descr}
+privacy_report_effective_visibility = {$descr}
privacy_from_private_dep_in_public_interface =
{$kind} `{$descr}` from private dependency '{$krate}' in public interface
diff --git a/compiler/rustc_error_messages/locales/en-US/query_system.ftl b/compiler/rustc_error_messages/locales/en-US/query_system.ftl
index 167704e46..870e82403 100644
--- a/compiler/rustc_error_messages/locales/en-US/query_system.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/query_system.ftl
@@ -12,6 +12,8 @@ query_system_cycle_usage = cycle used when {$usage}
query_system_cycle_stack_single = ...which immediately requires {$stack_bottom} again
+query_system_cycle_stack_middle = ...which requires {$desc}...
+
query_system_cycle_stack_multiple = ...which again requires {$stack_bottom}, completing the cycle
query_system_cycle_recursive_ty_alias = type aliases cannot be recursive
@@ -23,3 +25,6 @@ query_system_cycle_recursive_trait_alias = trait aliases cannot be recursive
query_system_cycle_which_requires = ...which requires {$desc}...
query_system_query_overflow = queries overflow the depth limit!
+ .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+query_system_layout_of_depth = query depth increased by {$depth} when {$desc}
diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl
index 76cae3c81..e22779230 100644
--- a/compiler/rustc_error_messages/locales/en-US/session.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/session.ftl
@@ -39,20 +39,6 @@ session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination`
session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5
-session_target_invalid_address_space = invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
-
-session_target_invalid_bits = invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
-
-session_target_missing_alignment = missing alignment for `{$cause}` in "data-layout"
-
-session_target_invalid_alignment = invalid alignment for `{$cause}` in "data-layout": {$err}
-
-session_target_inconsistent_architecture = inconsistent target specification: "data-layout" claims architecture is {$dl}-endian, while "target-endian" is `{$target}`
-
-session_target_inconsistent_pointer_width = inconsistent target specification: "data-layout" claims pointers are {$pointer_size}-bit, while "target-pointer-width" is `{$target}`
-
-session_target_invalid_bits_size = {$err}
-
session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
session_split_debuginfo_unstable_platform = `-Csplit-debuginfo={$debuginfo}` is unstable on this platform
@@ -66,3 +52,9 @@ session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has
session_crate_name_empty = crate name must not be empty
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
+
+session_expr_parentheses_needed = parentheses are required to parse this as an expression
+
+session_skipping_const_checks = skipping const checks
+session_unleashed_feature_help_named = skipping check for `{$gate}` feature
+session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index b6e0f3faa..9465051dd 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -35,32 +35,38 @@ 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_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",
- session => "../locales/en-US/session.ftl",
- interface => "../locales/en-US/interface.ftl",
+ hir_analysis => "../locales/en-US/hir_analysis.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_dataflow => "../locales/en-US/mir_dataflow.ftl",
monomorphize => "../locales/en-US/monomorphize.ftl",
- metadata => "../locales/en-US/metadata.ftl",
parser => "../locales/en-US/parser.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",
- trait_selection => "../locales/en-US/trait_selection.ftl",
save_analysis => "../locales/en-US/save_analysis.ftl",
- ty_utils => "../locales/en-US/ty_utils.ftl",
- typeck => "../locales/en-US/typeck.ftl",
- mir_dataflow => "../locales/en-US/mir_dataflow.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};
@@ -268,14 +274,26 @@ type FluentId = Cow<'static, str>;
/// Translatable messages for subdiagnostics are typically attributes attached to a larger Fluent
/// message so messages of this type must be combined with a `DiagnosticMessage` (using
/// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from
-/// the `SessionSubdiagnostic` derive refer to Fluent identifiers directly.
+/// the `Subdiagnostic` derive refer to Fluent identifiers directly.
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
pub enum SubdiagnosticMessage {
/// Non-translatable diagnostic message.
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
Str(String),
+ /// Translatable message which has already been translated eagerly.
+ ///
+ /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
+ /// be instantiated multiple times with different values. As translation normally happens
+ /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
+ /// the setting of diagnostic arguments in the derived code will overwrite previous variable
+ /// values and only the final value will be set when translation occurs - resulting in
+ /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
+ /// happening immediately after the subdiagnostic derive's logic has been run. This variant
+ /// stores messages which have been translated eagerly.
+ // FIXME(#100717): can a `Cow<'static, str>` be used here?
+ Eager(String),
/// Identifier of a Fluent message. Instances of this variant are generated by the
- /// `SessionSubdiagnostic` derive.
+ /// `Subdiagnostic` derive.
FluentIdentifier(FluentId),
/// Attribute of a Fluent message. Needs to be combined with a Fluent identifier to produce an
/// actual translated message. Instances of this variant are generated by the `fluent_messages`
@@ -301,8 +319,20 @@ impl<S: Into<String>> From<S> for SubdiagnosticMessage {
#[rustc_diagnostic_item = "DiagnosticMessage"]
pub enum DiagnosticMessage {
/// Non-translatable diagnostic message.
- // FIXME(davidtwco): can a `Cow<'static, str>` be used here?
+ // FIXME(#100717): can a `Cow<'static, str>` be used here?
Str(String),
+ /// Translatable message which has already been translated eagerly.
+ ///
+ /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
+ /// be instantiated multiple times with different values. As translation normally happens
+ /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
+ /// the setting of diagnostic arguments in the derived code will overwrite previous variable
+ /// values and only the final value will be set when translation occurs - resulting in
+ /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
+ /// happening immediately after the subdiagnostic derive's logic has been run. This variant
+ /// stores messages which have been translated eagerly.
+ // FIXME(#100717): can a `Cow<'static, str>` be used here?
+ Eager(String),
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
/// message.
///
@@ -321,6 +351,7 @@ impl DiagnosticMessage {
pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
let attr = match sub {
SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
+ SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s),
SubdiagnosticMessage::FluentIdentifier(id) => {
return DiagnosticMessage::FluentIdentifier(id, None);
}
@@ -329,24 +360,12 @@ impl DiagnosticMessage {
match self {
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
+ DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()),
DiagnosticMessage::FluentIdentifier(id, _) => {
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
}
}
}
-
- /// Returns the `String` contained within the `DiagnosticMessage::Str` variant, assuming that
- /// this diagnostic message is of the legacy, non-translatable variety. Panics if this
- /// assumption does not hold.
- ///
- /// Don't use this - it exists to support some places that do comparison with diagnostic
- /// strings.
- pub fn expect_str(&self) -> &str {
- match self {
- DiagnosticMessage::Str(s) => s,
- _ => panic!("expected non-translatable diagnostic message"),
- }
- }
}
/// `From` impl that enables existing diagnostic calls to functions which now take
@@ -357,6 +376,17 @@ impl<S: Into<String>> From<S> for DiagnosticMessage {
}
}
+/// A workaround for "good path" ICEs when formatting types in disables lints.
+///
+/// Delays formatting until `.into(): DiagnosticMessage` is used.
+pub struct DelayDm<F>(pub F);
+
+impl<F: FnOnce() -> String> From<DelayDm<F>> for DiagnosticMessage {
+ fn from(DelayDm(f): DelayDm<F>) -> Self {
+ DiagnosticMessage::from(f())
+ }
+}
+
/// Translating *into* a subdiagnostic message from a diagnostic message is a little strange - but
/// the subdiagnostic functions (e.g. `span_label`) take a `SubdiagnosticMessage` and the
/// subdiagnostic derive refers to typed identifiers that are `DiagnosticMessage`s, so need to be
@@ -366,6 +396,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage {
fn into(self) -> SubdiagnosticMessage {
match self {
DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
+ DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s),
DiagnosticMessage::FluentIdentifier(id, None) => {
SubdiagnosticMessage::FluentIdentifier(id)
}
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index c36ca11fa..7803a0792 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -4,10 +4,11 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_error_messages = { path = "../rustc_error_messages" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
index b32fc3c71..f14b8ee32 100644
--- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
+++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs
@@ -7,7 +7,7 @@
use crate::emitter::FileWithAnnotatedLines;
use crate::snippet::Line;
-use crate::translation::Translate;
+use crate::translation::{to_fluent_args, Translate};
use crate::{
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, Emitter, FluentBundle,
LazyFallbackBundle, Level, MultiSpan, Style, SubDiagnostic,
@@ -46,7 +46,7 @@ impl Translate for AnnotateSnippetEmitterWriter {
impl Emitter for AnnotateSnippetEmitterWriter {
/// The entry point for the diagnostics generation
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
- let fluent_args = self.to_fluent_args(diag.args());
+ let fluent_args = to_fluent_args(diag.args());
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index a774b52c8..23f29a24f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1,21 +1,17 @@
use crate::snippet::Style;
use crate::{
- CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan,
+ CodeSuggestion, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Level, MultiSpan,
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_error_messages::FluentValue;
-use rustc_hir as hir;
use rustc_lint_defs::{Applicability, LintExpectationId};
use rustc_span::edition::LATEST_STABLE_EDITION;
-use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
-use rustc_span::{edition::Edition, Span, DUMMY_SP};
-use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
+use rustc_span::symbol::Symbol;
+use rustc_span::{Span, DUMMY_SP};
use std::borrow::Cow;
use std::fmt;
use std::hash::{Hash, Hasher};
-use std::num::ParseIntError;
-use std::path::{Path, PathBuf};
/// Error type for `Diagnostic`'s `suggestions` field, indicating that
/// `.disable_suggestions()` was called on the `Diagnostic`.
@@ -25,7 +21,11 @@ pub struct SuggestionsDisabled;
/// Simplified version of `FluentArg` that can implement `Encodable` and `Decodable`. Collection of
/// `DiagnosticArg` are converted to `FluentArgs` (consuming the collection) at the start of
/// diagnostic emission.
-pub type DiagnosticArg<'source> = (Cow<'source, str>, DiagnosticArgValue<'source>);
+pub type DiagnosticArg<'iter, 'source> =
+ (&'iter DiagnosticArgName<'source>, &'iter DiagnosticArgValue<'source>);
+
+/// Name of a diagnostic argument.
+pub type DiagnosticArgName<'source> = Cow<'source, str>;
/// Simplified version of `FluentValue` that can implement `Encodable` and `Decodable`. Converted
/// to a `FluentValue` by the emitter to be used in diagnostic translation.
@@ -35,7 +35,7 @@ pub enum DiagnosticArgValue<'source> {
Number(usize),
}
-/// Converts a value of a type into a `DiagnosticArg` (typically a field of a `SessionDiagnostic`
+/// Converts a value of a type into a `DiagnosticArg` (typically a field of an `IntoDiagnostic`
/// struct). Implemented as a custom trait rather than `From` so that it is implemented on the type
/// being converted rather than on `DiagnosticArgValue`, which enables types from other `rustc_*`
/// crates to implement this.
@@ -43,119 +43,6 @@ pub trait IntoDiagnosticArg {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
}
-pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display);
-
-impl IntoDiagnosticArg for DiagnosticArgFromDisplay<'_> {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.0.to_string().into_diagnostic_arg()
- }
-}
-
-impl<'a> From<&'a dyn fmt::Display> for DiagnosticArgFromDisplay<'a> {
- fn from(t: &'a dyn fmt::Display) -> Self {
- DiagnosticArgFromDisplay(t)
- }
-}
-
-impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> {
- fn from(t: &'a T) -> Self {
- DiagnosticArgFromDisplay(t)
- }
-}
-
-macro_rules! into_diagnostic_arg_using_display {
- ($( $ty:ty ),+ $(,)?) => {
- $(
- impl IntoDiagnosticArg for $ty {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.to_string().into_diagnostic_arg()
- }
- }
- )+
- }
-}
-
-into_diagnostic_arg_using_display!(
- i8,
- u8,
- i16,
- u16,
- i32,
- u32,
- i64,
- u64,
- i128,
- u128,
- std::io::Error,
- std::num::NonZeroU32,
- hir::Target,
- Edition,
- Ident,
- MacroRulesNormalizedIdent,
- ParseIntError,
- StackProtector,
- &TargetTriple,
- SplitDebuginfo
-);
-
-impl IntoDiagnosticArg for bool {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- if self {
- DiagnosticArgValue::Str(Cow::Borrowed("true"))
- } else {
- DiagnosticArgValue::Str(Cow::Borrowed("false"))
- }
- }
-}
-
-impl IntoDiagnosticArg for char {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
- }
-}
-
-impl IntoDiagnosticArg for Symbol {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.to_ident_string().into_diagnostic_arg()
- }
-}
-
-impl<'a> IntoDiagnosticArg for &'a str {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- self.to_string().into_diagnostic_arg()
- }
-}
-
-impl IntoDiagnosticArg for String {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(self))
- }
-}
-
-impl<'a> IntoDiagnosticArg for &'a Path {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
- }
-}
-
-impl IntoDiagnosticArg for PathBuf {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
- }
-}
-
-impl IntoDiagnosticArg for usize {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Number(self)
- }
-}
-
-impl IntoDiagnosticArg for PanicStrategy {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
- }
-}
-
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
fn into(self) -> FluentValue<'source> {
match self {
@@ -165,22 +52,24 @@ impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
}
}
-impl IntoDiagnosticArg for hir::ConstContext {
- fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
- DiagnosticArgValue::Str(Cow::Borrowed(match self {
- hir::ConstContext::ConstFn => "constant function",
- hir::ConstContext::Static(_) => "static",
- hir::ConstContext::Const => "constant",
- }))
- }
-}
-
/// Trait implemented by error types. This should not be implemented manually. Instead, use
-/// `#[derive(SessionSubdiagnostic)]` -- see [rustc_macros::SessionSubdiagnostic].
-#[rustc_diagnostic_item = "AddSubdiagnostic"]
-pub trait AddSubdiagnostic {
+/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
+#[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")]
+#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "AddToDiagnostic")]
+pub trait AddToDiagnostic
+where
+ Self: Sized,
+{
/// Add a subdiagnostic to an existing diagnostic.
- fn add_to_diagnostic(self, diag: &mut Diagnostic);
+ fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+ self.add_to_diagnostic_with(diag, |_, m| m);
+ }
+
+ /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
+ /// (to optionally perform eager translation).
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, f: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage;
}
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
@@ -188,7 +77,12 @@ pub trait AddSubdiagnostic {
#[rustc_diagnostic_item = "DecorateLint"]
pub trait DecorateLint<'a, G: EmissionGuarantee> {
/// Decorate and emit a lint.
- fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>);
+ fn decorate_lint<'b>(
+ self,
+ diag: &'b mut DiagnosticBuilder<'a, G>,
+ ) -> &'b mut DiagnosticBuilder<'a, G>;
+
+ fn msg(&self) -> DiagnosticMessage;
}
#[must_use]
@@ -203,7 +97,7 @@ pub struct Diagnostic {
pub span: MultiSpan,
pub children: Vec<SubDiagnostic>,
pub suggestions: Result<Vec<CodeSuggestion>, SuggestionsDisabled>,
- args: Vec<DiagnosticArg<'static>>,
+ args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
/// This is not used for highlighting or rendering any error message. Rather, it can be used
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
@@ -295,7 +189,7 @@ impl Diagnostic {
span: MultiSpan::new(),
children: vec![],
suggestions: Ok(vec![]),
- args: vec![],
+ args: Default::default(),
sort_span: DUMMY_SP,
is_lint: false,
}
@@ -338,9 +232,10 @@ impl Diagnostic {
// The lint index inside the attribute is manually transferred here.
let lint_index = expectation_id.get_lint_index();
expectation_id.set_lint_index(None);
- let mut stable_id = *unstable_to_stable
+ let mut stable_id = unstable_to_stable
.get(&expectation_id)
- .expect("each unstable `LintExpectationId` must have a matching stable id");
+ .expect("each unstable `LintExpectationId` must have a matching stable id")
+ .normalize();
stable_id.set_lint_index(lint_index);
*expectation_id = stable_id;
@@ -672,6 +567,11 @@ impl Diagnostic {
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"
+ );
+
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: suggestion
@@ -749,6 +649,10 @@ impl Diagnostic {
applicability: Applicability,
style: SuggestionStyle,
) -> &mut Self {
+ debug_assert!(
+ !(sp.is_empty() && suggestion.to_string().is_empty()),
+ "Span must not be empty and have no suggestion"
+ );
self.push_suggestion(CodeSuggestion {
substitutions: vec![Substitution {
parts: vec![SubstitutionPart { snippet: suggestion.to_string(), span: sp }],
@@ -787,8 +691,32 @@ impl Diagnostic {
suggestions: impl Iterator<Item = String>,
applicability: Applicability,
) -> &mut Self {
+ self.span_suggestions_with_style(
+ sp,
+ msg,
+ suggestions,
+ applicability,
+ SuggestionStyle::ShowCode,
+ )
+ }
+
+ /// [`Diagnostic::span_suggestions()`] but you can set the [`SuggestionStyle`].
+ pub fn span_suggestions_with_style(
+ &mut self,
+ sp: Span,
+ msg: impl Into<SubdiagnosticMessage>,
+ suggestions: impl Iterator<Item = String>,
+ applicability: Applicability,
+ style: SuggestionStyle,
+ ) -> &mut Self {
let mut suggestions: Vec<_> = suggestions.collect();
suggestions.sort();
+
+ debug_assert!(
+ !(sp.is_empty() && suggestions.iter().any(|suggestion| suggestion.is_empty())),
+ "Span must not be empty and have no suggestion"
+ );
+
let substitutions = suggestions
.into_iter()
.map(|snippet| Substitution { parts: vec![SubstitutionPart { snippet, span: sp }] })
@@ -796,22 +724,33 @@ impl Diagnostic {
self.push_suggestion(CodeSuggestion {
substitutions,
msg: self.subdiagnostic_message_to_diagnostic_message(msg),
- style: SuggestionStyle::ShowCode,
+ style,
applicability,
});
self
}
- /// Prints out a message with multiple suggested edits of the code.
- /// See also [`Diagnostic::span_suggestion()`].
+ /// Prints out a message with multiple suggested edits of the code, where each edit consists of
+ /// multiple parts.
+ /// See also [`Diagnostic::multipart_suggestion()`].
pub fn multipart_suggestions(
&mut self,
msg: impl Into<SubdiagnosticMessage>,
suggestions: impl Iterator<Item = Vec<(Span, String)>>,
applicability: Applicability,
) -> &mut Self {
+ let suggestions: Vec<_> = suggestions.collect();
+ debug_assert!(
+ !(suggestions
+ .iter()
+ .flat_map(|suggs| suggs)
+ .any(|(sp, suggestion)| sp.is_empty() && suggestion.is_empty())),
+ "Span must not be empty and have no suggestion"
+ );
+
self.push_suggestion(CodeSuggestion {
substitutions: suggestions
+ .into_iter()
.map(|sugg| Substitution {
parts: sugg
.into_iter()
@@ -825,6 +764,7 @@ impl Diagnostic {
});
self
}
+
/// Prints out a message with a suggested edit of the code. If the suggestion is presented
/// inline, it will only show the message and not the suggestion.
///
@@ -890,13 +830,30 @@ impl Diagnostic {
self
}
- /// Add a subdiagnostic from a type that implements `SessionSubdiagnostic` - see
- /// [rustc_macros::SessionSubdiagnostic].
- pub fn subdiagnostic(&mut self, subdiagnostic: impl AddSubdiagnostic) -> &mut Self {
+ /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
+ /// [rustc_macros::Subdiagnostic]).
+ pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
subdiagnostic.add_to_diagnostic(self);
self
}
+ /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
+ /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
+ /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
+ /// interpolated variables).
+ pub fn eager_subdiagnostic(
+ &mut self,
+ handler: &crate::Handler,
+ subdiagnostic: impl AddToDiagnostic,
+ ) -> &mut Self {
+ subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
+ let args = diag.args();
+ let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
+ handler.eagerly_translate(msg, args)
+ });
+ self
+ }
+
pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self {
self.span = sp.into();
if let Some(span) = self.span.primary_span() {
@@ -929,8 +886,11 @@ impl Diagnostic {
self
}
- pub fn args(&self) -> &[DiagnosticArg<'static>] {
- &self.args
+ // Exact iteration order of diagnostic arguments shouldn't make a difference to output because
+ // they're only used in interpolation.
+ #[allow(rustc::potential_query_instability)]
+ pub fn args<'a>(&'a self) -> impl Iterator<Item = DiagnosticArg<'a, 'static>> {
+ self.args.iter()
}
pub fn set_arg(
@@ -938,7 +898,7 @@ impl Diagnostic {
name: impl Into<Cow<'static, str>>,
arg: impl IntoDiagnosticArg,
) -> &mut Self {
- self.args.push((name.into(), arg.into_diagnostic_arg()));
+ self.args.insert(name.into(), arg.into_diagnostic_arg());
self
}
@@ -949,7 +909,7 @@ impl Diagnostic {
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
/// combining it with the primary message of the diagnostic (if translatable, otherwise it just
/// passes the user's string along).
- fn subdiagnostic_message_to_diagnostic_message(
+ pub(crate) fn subdiagnostic_message_to_diagnostic_message(
&self,
attr: impl Into<SubdiagnosticMessage>,
) -> DiagnosticMessage {
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 7e29dc207..9b41234dc 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -5,6 +5,7 @@ use crate::{
};
use crate::{Handler, Level, MultiSpan, StashKey};
use rustc_lint_defs::Applicability;
+use rustc_span::source_map::Spanned;
use rustc_span::Span;
use std::borrow::Cow;
@@ -13,6 +14,28 @@ use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::thread::panicking;
+/// Trait implemented by error types. This should not be implemented manually. Instead, use
+/// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic].
+#[cfg_attr(bootstrap, rustc_diagnostic_item = "SessionDiagnostic")]
+#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "IntoDiagnostic")]
+pub trait IntoDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
+ /// Write out as a diagnostic out of `Handler`.
+ #[must_use]
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>;
+}
+
+impl<'a, T, E> IntoDiagnostic<'a, E> for Spanned<T>
+where
+ T: IntoDiagnostic<'a, E>,
+ E: EmissionGuarantee,
+{
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, E> {
+ let mut diag = self.node.into_diagnostic(handler);
+ diag.set_span(self.span);
+ diag
+ }
+}
+
/// Used for emitting structured error messages and other diagnostic information.
///
/// If there is some state in a downstream crate you would like to
@@ -232,6 +255,56 @@ impl EmissionGuarantee for () {
}
}
+/// Marker type which enables implementation of `create_note` and `emit_note` functions for
+/// note-without-error struct diagnostics.
+#[derive(Copy, Clone)]
+pub struct Noted;
+
+impl<'a> DiagnosticBuilder<'a, Noted> {
+ /// Convenience function for internal use, clients should use one of the
+ /// `struct_*` methods on [`Handler`].
+ pub(crate) fn new_note(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
+ let diagnostic = Diagnostic::new_with_code(Level::Note, None, message);
+ Self::new_diagnostic_note(handler, diagnostic)
+ }
+
+ /// Creates a new `DiagnosticBuilder` with an already constructed
+ /// diagnostic.
+ pub(crate) fn new_diagnostic_note(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 Noted {
+ 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 => {}
+ }
+
+ Noted
+ }
+
+ fn make_diagnostic_builder(
+ handler: &Handler,
+ msg: impl Into<DiagnosticMessage>,
+ ) -> DiagnosticBuilder<'_, Self> {
+ DiagnosticBuilder::new_note(handler, msg)
+ }
+}
+
impl<'a> DiagnosticBuilder<'a, !> {
/// Convenience function for internal use, clients should use one of the
/// `struct_*` methods on [`Handler`].
@@ -570,7 +643,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!(pub fn subdiagnostic(
&mut self,
- subdiagnostic: impl crate::AddSubdiagnostic
+ subdiagnostic: impl crate::AddToDiagnostic
) -> &mut Self);
}
@@ -619,27 +692,3 @@ macro_rules! struct_span_err {
macro_rules! error_code {
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
}
-
-/// Wrapper around a `DiagnosticBuilder` for creating lints.
-pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
-
-impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
- #[rustc_lint_diagnostics]
- /// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
- pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> {
- self.0.set_primary_message(msg);
- self.0.set_is_lint();
- self.0
- }
-
- /// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
- pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
- LintDiagnosticBuilder(err)
- }
-}
-
-impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
- pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
- LintDiagnosticBuilder(self.0.forget_guarantee())
- }
-}
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
new file mode 100644
index 000000000..7640b2919
--- /dev/null
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -0,0 +1,222 @@
+use crate::{
+ fluent, DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
+};
+use rustc_ast as ast;
+use rustc_ast_pretty::pprust;
+use rustc_hir as hir;
+use rustc_lint_defs::Level;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
+use rustc_target::abi::TargetDataLayoutErrors;
+use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple};
+use std::borrow::Cow;
+use std::fmt;
+use std::num::ParseIntError;
+use std::path::{Path, PathBuf};
+
+pub struct DiagnosticArgFromDisplay<'a>(pub &'a dyn fmt::Display);
+
+impl IntoDiagnosticArg for DiagnosticArgFromDisplay<'_> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.0.to_string().into_diagnostic_arg()
+ }
+}
+
+impl<'a> From<&'a dyn fmt::Display> for DiagnosticArgFromDisplay<'a> {
+ fn from(t: &'a dyn fmt::Display) -> Self {
+ DiagnosticArgFromDisplay(t)
+ }
+}
+
+impl<'a, T: fmt::Display> From<&'a T> for DiagnosticArgFromDisplay<'a> {
+ fn from(t: &'a T) -> Self {
+ DiagnosticArgFromDisplay(t)
+ }
+}
+
+macro_rules! into_diagnostic_arg_using_display {
+ ($( $ty:ty ),+ $(,)?) => {
+ $(
+ impl IntoDiagnosticArg for $ty {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+ }
+ )+
+ }
+}
+
+into_diagnostic_arg_using_display!(
+ i8,
+ u8,
+ i16,
+ u16,
+ i32,
+ u32,
+ i64,
+ u64,
+ i128,
+ u128,
+ std::io::Error,
+ std::num::NonZeroU32,
+ hir::Target,
+ Edition,
+ Ident,
+ MacroRulesNormalizedIdent,
+ ParseIntError,
+ StackProtector,
+ &TargetTriple,
+ SplitDebuginfo
+);
+
+impl IntoDiagnosticArg for bool {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ if self {
+ DiagnosticArgValue::Str(Cow::Borrowed("true"))
+ } else {
+ DiagnosticArgValue::Str(Cow::Borrowed("false"))
+ }
+ }
+}
+
+impl IntoDiagnosticArg for char {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(format!("{:?}", self)))
+ }
+}
+
+impl IntoDiagnosticArg for Symbol {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_ident_string().into_diagnostic_arg()
+ }
+}
+
+impl<'a> IntoDiagnosticArg for &'a str {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
+impl IntoDiagnosticArg for String {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self))
+ }
+}
+
+impl<'a> IntoDiagnosticArg for &'a Path {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
+ }
+}
+
+impl IntoDiagnosticArg for PathBuf {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
+ }
+}
+
+impl IntoDiagnosticArg for usize {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Number(self)
+ }
+}
+
+impl IntoDiagnosticArg for PanicStrategy {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string()))
+ }
+}
+
+impl IntoDiagnosticArg for hir::ConstContext {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Borrowed(match self {
+ hir::ConstContext::ConstFn => "constant function",
+ hir::ConstContext::Static(_) => "static",
+ hir::ConstContext::Const => "constant",
+ }))
+ }
+}
+
+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))
+ }
+}
+
+impl IntoDiagnosticArg for ast::token::TokenKind {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(pprust::token_kind_to_string(&self))
+ }
+}
+
+impl IntoDiagnosticArg for Level {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::Str(Cow::Borrowed(match self {
+ Level::Allow => "-A",
+ Level::Warn => "-W",
+ Level::ForceWarn(_) => "--force-warn",
+ Level::Deny => "-D",
+ Level::Forbid => "-F",
+ Level::Expect(_) => {
+ unreachable!("lints with the level of `expect` should not run this code");
+ }
+ }))
+ }
+}
+
+impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
+ fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
+ let mut diag;
+ match self {
+ TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
+ diag = handler.struct_fatal(fluent::errors_target_invalid_address_space);
+ diag.set_arg("addr_space", addr_space);
+ diag.set_arg("cause", cause);
+ diag.set_arg("err", err);
+ diag
+ }
+ TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
+ diag = handler.struct_fatal(fluent::errors_target_invalid_bits);
+ diag.set_arg("kind", kind);
+ diag.set_arg("bit", bit);
+ diag.set_arg("cause", cause);
+ diag.set_arg("err", err);
+ diag
+ }
+ TargetDataLayoutErrors::MissingAlignment { cause } => {
+ diag = handler.struct_fatal(fluent::errors_target_missing_alignment);
+ diag.set_arg("cause", cause);
+ diag
+ }
+ TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
+ diag = handler.struct_fatal(fluent::errors_target_invalid_alignment);
+ diag.set_arg("cause", cause);
+ diag.set_arg("err", err);
+ diag
+ }
+ TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
+ diag = handler.struct_fatal(fluent::errors_target_inconsistent_architecture);
+ diag.set_arg("dl", dl);
+ diag.set_arg("target", target);
+ diag
+ }
+ TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
+ diag = handler.struct_fatal(fluent::errors_target_inconsistent_pointer_width);
+ diag.set_arg("pointer_size", pointer_size);
+ diag.set_arg("target", target);
+ diag
+ }
+ TargetDataLayoutErrors::InvalidBitsSize { err } => {
+ diag = handler.struct_fatal(fluent::errors_target_invalid_bits_size);
+ diag.set_arg("err", err);
+ diag
+ }
+ }
+ }
+}
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 66fbb8f12..cd6413bc3 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -14,7 +14,7 @@ use rustc_span::{FileLines, SourceFile, Span};
use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, Style, StyledString};
use crate::styled_buffer::StyledBuffer;
-use crate::translation::Translate;
+use crate::translation::{to_fluent_args, Translate};
use crate::{
CodeSuggestion, Diagnostic, DiagnosticId, DiagnosticMessage, FluentBundle, Handler,
LazyFallbackBundle, Level, MultiSpan, SubDiagnostic, SubstitutionHighlight, SuggestionStyle,
@@ -535,7 +535,7 @@ impl Emitter for EmitterWriter {
}
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
- let fluent_args = self.to_fluent_args(diag.args());
+ let fluent_args = to_fluent_args(diag.args());
let mut children = diag.children.clone();
let (mut primary_span, suggestions) = self.primary_span_formatted(&diag, &fluent_args);
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index 1680c6acc..4cc7be47f 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -13,7 +13,7 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
use crate::emitter::{Emitter, HumanReadableErrorType};
use crate::registry::Registry;
-use crate::translation::Translate;
+use crate::translation::{to_fluent_args, Translate};
use crate::DiagnosticId;
use crate::{
CodeSuggestion, FluentBundle, LazyFallbackBundle, MultiSpan, SpanLabel, SubDiagnostic,
@@ -312,7 +312,7 @@ struct UnusedExterns<'a, 'b, 'c> {
impl Diagnostic {
fn from_errors_diagnostic(diag: &crate::Diagnostic, je: &JsonEmitter) -> Diagnostic {
- let args = je.to_fluent_args(diag.args());
+ let args = to_fluent_args(diag.args());
let sugg = diag.suggestions.iter().flatten().map(|sugg| {
let translated_message = je.translate_message(&sugg.msg, &args);
Diagnostic {
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index a7b01feeb..0963ea71f 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -7,7 +7,6 @@
#![feature(if_let_guard)]
#![feature(adt_const_params)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![feature(result_option_inspect)]
#![feature(rustc_attrs)]
@@ -31,7 +30,7 @@ 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, DiagnosticMessage, FluentBundle,
+ fallback_fluent_bundle, fluent, fluent_bundle, DelayDm, DiagnosticMessage, FluentBundle,
LanguageIdentifier, LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagnosticMessage,
DEFAULT_LOCALE_RESOURCES,
};
@@ -52,6 +51,7 @@ use termcolor::{Color, ColorSpec};
pub mod annotate_snippet_emitter_writer;
mod diagnostic;
mod diagnostic_builder;
+mod diagnostic_impls;
pub mod emitter;
pub mod json;
mod lock;
@@ -60,15 +60,17 @@ mod snippet;
mod styled_buffer;
pub mod translation;
+pub use diagnostic_builder::IntoDiagnostic;
pub use snippet::Style;
-pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a, ErrorGuaranteed>>;
+pub type PErr<'a> = DiagnosticBuilder<'a, ErrorGuaranteed>;
+pub type PResult<'a, T> = Result<T, PErr<'a>>;
// `PResult` is used a lot. Make sure it doesn't unintentionally get bigger.
-// (See also the comment on `DiagnosticBuilder`'s `diagnostic` field.)
+// (See also the comment on `DiagnosticBuilderInner`'s `diagnostic` field.)
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(PResult<'_, ()>, 16);
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64", not(bootstrap)))]
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(PResult<'_, bool>, 16);
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Encodable, Decodable)]
@@ -370,10 +372,11 @@ impl fmt::Display for ExplicitBug {
impl error::Error for ExplicitBug {}
pub use diagnostic::{
- AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgFromDisplay,
- DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
+ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
+ DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
};
-pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder};
+pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted};
+pub use diagnostic_impls::DiagnosticArgFromDisplay;
use std::backtrace::Backtrace;
/// A handler deals with errors and other compiler output.
@@ -410,7 +413,7 @@ struct HandlerInner {
/// would be unnecessary repetition.
taught_diagnostics: FxHashSet<DiagnosticId>,
- /// Used to suggest rustc --explain <error code>
+ /// Used to suggest rustc --explain `<error code>`
emitted_diagnostic_codes: FxIndexSet<DiagnosticId>,
/// This set contains a hash of every diagnostic that has been emitted by
@@ -436,11 +439,11 @@ struct HandlerInner {
/// have been converted.
check_unstable_expect_diagnostics: bool,
- /// Expected [`Diagnostic`]s store a [`LintExpectationId`] as part of
+ /// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
/// the lint level. [`LintExpectationId`]s created early during the compilation
/// (before `HirId`s have been defined) are not stable and can therefore not be
/// stored on disk. This buffer stores these diagnostics until the ID has been
- /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`]s are the
+ /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
/// submitted for storage and added to the list of fulfilled expectations.
unstable_expect_diagnostics: Vec<Diagnostic>,
@@ -459,6 +462,10 @@ pub enum StashKey {
ItemNoType,
UnderscoreForArrayLengths,
EarlySyntaxWarning,
+ CallIntoMethod,
+ /// When an invalid lifetime e.g. `'2` should be reinterpreted
+ /// as a char literal in the parser
+ LifetimeIsChar,
}
fn default_track_diagnostic(_: &Diagnostic) {}
@@ -596,6 +603,17 @@ impl Handler {
}
}
+ /// Translate `message` eagerly with `args`.
+ pub fn eagerly_translate<'a>(
+ &self,
+ message: DiagnosticMessage,
+ args: impl Iterator<Item = DiagnosticArg<'a, 'static>>,
+ ) -> SubdiagnosticMessage {
+ let inner = self.inner.borrow();
+ let args = crate::translation::to_fluent_args(args);
+ SubdiagnosticMessage::Eager(inner.emitter.translate_message(&message, &args).to_string())
+ }
+
// This is here to not allow mutation of flags;
// as of this writing it's only used in tests in librustc_middle.
pub fn can_emit_warnings(&self) -> bool {
@@ -1028,6 +1046,39 @@ impl Handler {
self.inner.borrow_mut().emit_diagnostic(diagnostic)
}
+ pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
+ self.create_err(err).emit()
+ }
+
+ pub fn create_err<'a>(
+ &'a self,
+ err: impl IntoDiagnostic<'a>,
+ ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+ err.into_diagnostic(self)
+ }
+
+ pub fn create_warning<'a>(
+ &'a self,
+ warning: impl IntoDiagnostic<'a, ()>,
+ ) -> DiagnosticBuilder<'a, ()> {
+ warning.into_diagnostic(self)
+ }
+
+ pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
+ self.create_warning(warning).emit()
+ }
+
+ pub fn create_fatal<'a>(
+ &'a self,
+ fatal: impl IntoDiagnostic<'a, !>,
+ ) -> DiagnosticBuilder<'a, !> {
+ fatal.into_diagnostic(self)
+ }
+
+ pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
+ self.create_fatal(fatal).emit()
+ }
+
fn emit_diag_at_span(
&self,
mut diag: Diagnostic,
@@ -1100,6 +1151,12 @@ impl Handler {
);
std::mem::take(&mut self.inner.borrow_mut().fulfilled_expectations)
}
+
+ pub fn flush_delayed(&self) {
+ let mut inner = self.inner.lock();
+ let bugs = std::mem::replace(&mut inner.delayed_span_bugs, Vec::new());
+ inner.flush_delayed(bugs, "no errors encountered even though `delay_span_bug` issued");
+ }
}
impl HandlerInner {
@@ -1171,7 +1228,7 @@ impl HandlerInner {
if let Some(expectation_id) = diagnostic.level.get_expectation_id() {
self.suppressed_expected_diag = true;
- self.fulfilled_expectations.insert(expectation_id);
+ self.fulfilled_expectations.insert(expectation_id.normalize());
}
if matches!(diagnostic.level, Warning(_))
diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs
index 4f407badb..a7737b467 100644
--- a/compiler/rustc_errors/src/translation.rs
+++ b/compiler/rustc_errors/src/translation.rs
@@ -4,6 +4,27 @@ use rustc_data_structures::sync::Lrc;
use rustc_error_messages::FluentArgs;
use std::borrow::Cow;
+/// Convert diagnostic arguments (a rustc internal type that exists to implement
+/// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
+///
+/// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
+/// passed around as a reference thereafter.
+pub fn to_fluent_args<'iter, 'arg: 'iter>(
+ iter: impl Iterator<Item = DiagnosticArg<'iter, 'arg>>,
+) -> FluentArgs<'arg> {
+ let mut args = if let Some(size) = iter.size_hint().1 {
+ FluentArgs::with_capacity(size)
+ } else {
+ FluentArgs::new()
+ };
+
+ for (k, v) in iter {
+ args.set(k.clone(), v.clone());
+ }
+
+ args
+}
+
pub trait Translate {
/// Return `FluentBundle` with localized diagnostics for the locale requested by the user. If no
/// language was requested by the user then this will be `None` and `fallback_fluent_bundle`
@@ -15,15 +36,6 @@ pub trait Translate {
/// unavailable for the requested locale.
fn fallback_fluent_bundle(&self) -> &FluentBundle;
- /// Convert diagnostic arguments (a rustc internal type that exists to implement
- /// `Encodable`/`Decodable`) into `FluentArgs` which is necessary to perform translation.
- ///
- /// Typically performed once for each diagnostic at the start of `emit_diagnostic` and then
- /// passed around as a reference thereafter.
- fn to_fluent_args<'arg>(&self, args: &[DiagnosticArg<'arg>]) -> FluentArgs<'arg> {
- FromIterator::from_iter(args.iter().cloned())
- }
-
/// Convert `DiagnosticMessage`s to a string, performing translation if necessary.
fn translate_messages(
&self,
@@ -43,7 +55,9 @@ pub trait Translate {
) -> Cow<'_, str> {
trace!(?message, ?args);
let (identifier, attr) = match message {
- DiagnosticMessage::Str(msg) => return Cow::Borrowed(&msg),
+ DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
+ return Cow::Borrowed(&msg);
+ }
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
};
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index e1da3ecde..c8de60ccb 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -10,17 +10,19 @@ use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind
use rustc_attr::{self as attr, Deprecation, Stability};
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::sync::{self, Lrc};
-use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, PResult};
+use rustc_errors::{
+ Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, PResult,
+};
use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics};
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
-use rustc_session::{parse::ParseSess, Limit, Session, SessionDiagnostic};
+use rustc_session::{parse::ParseSess, Limit, Session};
use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId};
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{FileName, Span, DUMMY_SP};
+use rustc_span::{BytePos, FileName, RealFileName, Span, DUMMY_SP};
use smallvec::{smallvec, SmallVec};
use std::default::Default;
@@ -1109,12 +1111,12 @@ impl<'a> ExtCtxt<'a> {
pub fn create_err(
&self,
- err: impl SessionDiagnostic<'a>,
+ err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
self.sess.create_err(err)
}
- pub fn emit_err(&self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
+ pub fn emit_err(&self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.sess.emit_err(err)
}
@@ -1226,8 +1228,9 @@ pub fn expr_to_spanned_string<'a>(
ast::LitKind::Str(s, style) => return Ok((s, style, expr.span)),
ast::LitKind::ByteStr(_) => {
let mut err = cx.struct_span_err(l.span, err_msg);
+ let span = expr.span.shrink_to_lo();
err.span_suggestion(
- expr.span.shrink_to_lo(),
+ span.with_hi(span.lo() + BytePos(1)),
"consider removing the leading `b`",
"",
Applicability::MaybeIncorrect,
@@ -1420,16 +1423,40 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &ParseSess) -> bool {
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
if let [variant] = &*enum_def.variants {
if variant.ident.name == sym::Input {
- sess.buffer_lint_with_diagnostic(
- &PROC_MACRO_BACK_COMPAT,
- item.ident.span,
- ast::CRATE_NODE_ID,
- "using `procedural-masquerade` crate",
- BuiltinLintDiagnostics::ProcMacroBackCompat(
- "The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. \
- Versions of this crate below 0.1.7 will eventually stop compiling.".to_string())
- );
- return true;
+ let filename = sess.source_map().span_to_filename(item.ident.span);
+ if let FileName::Real(RealFileName::LocalPath(path)) = filename {
+ if let Some(c) = path
+ .components()
+ .flat_map(|c| c.as_os_str().to_str())
+ .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental"))
+ {
+ let crate_matches = if c.starts_with("allsorts-rental") {
+ true
+ } else {
+ let mut version = c.trim_start_matches("rental-").split(".");
+ version.next() == Some("0")
+ && version.next() == Some("5")
+ && version
+ .next()
+ .and_then(|c| c.parse::<u32>().ok())
+ .map_or(false, |v| v < 6)
+ };
+
+ if crate_matches {
+ sess.buffer_lint_with_diagnostic(
+ &PROC_MACRO_BACK_COMPAT,
+ item.ident.span,
+ ast::CRATE_NODE_ID,
+ "using an old version of `rental`",
+ BuiltinLintDiagnostics::ProcMacroBackCompat(
+ "older versions of the `rental` crate will stop compiling in future versions of Rust; \
+ please update to `rental` v0.5.6, or switch to one of the `rental` alternatives".to_string()
+ )
+ );
+ return true;
+ }
+ }
+ }
}
}
}
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 50d2be3ce..0952e65cf 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -252,6 +252,10 @@ impl<'a> ExtCtxt<'a> {
self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
}
+ pub fn expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr> {
+ self.expr(span, ast::ExprKind::Field(expr, field))
+ }
+
pub fn expr_binary(
&self,
sp: Span,
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 8d4e36407..1d2b1298a 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -469,6 +469,7 @@ impl<'a> StripUnconfigured<'a> {
}
/// If attributes are not allowed on expressions, emit an error for `attr`
+ #[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
if !self.features.map_or(true, |features| features.stmt_expr_attributes) {
let mut err = feature_err(
@@ -486,9 +487,12 @@ impl<'a> StripUnconfigured<'a> {
}
}
- pub fn configure_expr(&self, expr: &mut P<ast::Expr>) {
- for attr in expr.attrs.iter() {
- self.maybe_emit_expr_attr_err(attr);
+ #[instrument(level = "trace", skip(self))]
+ pub fn configure_expr(&self, expr: &mut P<ast::Expr>, method_receiver: bool) {
+ if !method_receiver {
+ for attr in expr.attrs.iter() {
+ self.maybe_emit_expr_attr_err(attr);
+ }
}
// If an expr is valid to cfg away it will have been removed by the
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 0feae0deb..d383f4832 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,46 +1,46 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::symbol::MacroRulesNormalizedIdent;
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(expand::expr_repeat_no_syntax_vars)]
+#[derive(Diagnostic)]
+#[diag(expand_expr_repeat_no_syntax_vars)]
pub(crate) struct NoSyntaxVarsExprRepeat {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(expand::must_repeat_once)]
+#[derive(Diagnostic)]
+#[diag(expand_must_repeat_once)]
pub(crate) struct MustRepeatOnce {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(expand::count_repetition_misplaced)]
+#[derive(Diagnostic)]
+#[diag(expand_count_repetition_misplaced)]
pub(crate) struct CountRepetitionMisplaced {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(expand::meta_var_expr_unrecognized_var)]
+#[derive(Diagnostic)]
+#[diag(expand_meta_var_expr_unrecognized_var)]
pub(crate) struct MetaVarExprUnrecognizedVar {
#[primary_span]
pub span: Span,
pub key: MacroRulesNormalizedIdent,
}
-#[derive(SessionDiagnostic)]
-#[diag(expand::var_still_repeating)]
+#[derive(Diagnostic)]
+#[diag(expand_var_still_repeating)]
pub(crate) struct VarStillRepeating {
#[primary_span]
pub span: Span,
pub ident: MacroRulesNormalizedIdent,
}
-#[derive(SessionDiagnostic)]
-#[diag(expand::meta_var_dif_seq_matchers)]
+#[derive(Diagnostic)]
+#[diag(expand_meta_var_dif_seq_matchers)]
pub(crate) struct MetaVarsDifSeqMatchers {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index c2add852a..57713fb3c 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -50,6 +50,7 @@ macro_rules! ast_fragments {
/// Can also serve as an input and intermediate result for macro expansion operations.
pub enum AstFragment {
OptExpr(Option<P<ast::Expr>>),
+ MethodReceiverExpr(P<ast::Expr>),
$($Kind($AstTy),)*
}
@@ -57,6 +58,7 @@ macro_rules! ast_fragments {
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AstFragmentKind {
OptExpr,
+ MethodReceiverExpr,
$($Kind,)*
}
@@ -64,6 +66,7 @@ macro_rules! ast_fragments {
pub fn name(self) -> &'static str {
match self {
AstFragmentKind::OptExpr => "expression",
+ AstFragmentKind::MethodReceiverExpr => "expression",
$(AstFragmentKind::$Kind => $kind_name,)*
}
}
@@ -72,6 +75,8 @@ macro_rules! ast_fragments {
match self {
AstFragmentKind::OptExpr =>
result.make_expr().map(Some).map(AstFragment::OptExpr),
+ AstFragmentKind::MethodReceiverExpr =>
+ result.make_expr().map(AstFragment::MethodReceiverExpr),
$(AstFragmentKind::$Kind => result.$make_ast().map(AstFragment::$Kind),)*
}
}
@@ -98,6 +103,13 @@ macro_rules! ast_fragments {
}
}
+ pub fn make_method_receiver_expr(self) -> P<ast::Expr> {
+ match self {
+ AstFragment::MethodReceiverExpr(expr) => expr,
+ _ => panic!("AstFragment::make_* called on the wrong kind of fragment"),
+ }
+ }
+
$(pub fn $make_ast(self) -> $AstTy {
match self {
AstFragment::$Kind(ast) => ast,
@@ -120,6 +132,7 @@ macro_rules! ast_fragments {
}
});
}
+ AstFragment::MethodReceiverExpr(expr) => vis.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ast) => vis.$mut_visit_ast(ast),)?)*
$($(AstFragment::$Kind(ast) =>
ast.flat_map_in_place(|ast| vis.$flat_map_ast_elt(ast)),)?)*
@@ -130,6 +143,7 @@ macro_rules! ast_fragments {
match *self {
AstFragment::OptExpr(Some(ref expr)) => visitor.visit_expr(expr),
AstFragment::OptExpr(None) => {}
+ AstFragment::MethodReceiverExpr(ref expr) => visitor.visit_method_receiver_expr(expr),
$($(AstFragment::$Kind(ref ast) => visitor.$visit_ast(ast),)?)*
$($(AstFragment::$Kind(ref ast) => for ast_elt in &ast[..] {
visitor.$visit_ast_elt(ast_elt, $($args)*);
@@ -222,6 +236,7 @@ impl AstFragmentKind {
match self {
AstFragmentKind::OptExpr
| AstFragmentKind::Expr
+ | AstFragmentKind::MethodReceiverExpr
| AstFragmentKind::Stmts
| AstFragmentKind::Ty
| AstFragmentKind::Pat => SupportsMacroExpansion::Yes { supports_inner_attrs: false },
@@ -285,6 +300,9 @@ impl AstFragmentKind {
AstFragmentKind::Expr => AstFragment::Expr(
items.next().expect("expected exactly one expression").expect_expr(),
),
+ AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(
+ items.next().expect("expected exactly one expression").expect_expr(),
+ ),
AstFragmentKind::OptExpr => {
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr))
}
@@ -327,7 +345,7 @@ impl InvocationKind {
fn placeholder_visibility(&self) -> Option<ast::Visibility> {
// HACK: For unnamed fields placeholders should have the same visibility as the actual
// fields because for tuple structs/variants resolve determines visibilities of their
- // constructor using these field visibilities before attributes on them are are expanded.
+ // constructor using these field visibilities before attributes on them are expanded.
// The assumption is that the attribute expansion cannot change field visibilities,
// and it holds because only inert attributes are supported in this position.
match self {
@@ -893,6 +911,7 @@ pub fn parse_ast_fragment<'a>(
AstFragment::Stmts(stmts)
}
AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?),
+ AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(this.parse_expr()?),
AstFragmentKind::OptExpr => {
if this.token != token::Eof {
AstFragment::OptExpr(Some(this.parse_expr()?))
@@ -937,13 +956,12 @@ pub fn ensure_complete_parse<'a>(
kind_name,
);
err.note(&msg);
- let semi_span = this.sess.source_map().next_point(span);
- let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span));
- match this.sess.source_map().span_to_snippet(semi_full_span) {
+ let semi_span = this.sess.source_map().next_point(span);
+ match this.sess.source_map().span_to_snippet(semi_span) {
Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
err.span_suggestion(
- semi_span,
+ span.shrink_to_hi(),
"you might be missing a semicolon here",
";",
Applicability::MaybeIncorrect,
@@ -1478,6 +1496,42 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
}
}
+/// This struct is a hack to workaround unstable of `stmt_expr_attributes`.
+/// It can be removed once that feature is stabilized.
+struct MethodReceiverTag;
+impl DummyAstNode for MethodReceiverTag {
+ fn dummy() -> MethodReceiverTag {
+ MethodReceiverTag
+ }
+}
+impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, MethodReceiverTag> {
+ type OutputTy = Self;
+ type AttrsTy = ast::AttrVec;
+ const KIND: AstFragmentKind = AstFragmentKind::MethodReceiverExpr;
+ fn descr() -> &'static str {
+ "an expression"
+ }
+ fn to_annotatable(self) -> Annotatable {
+ Annotatable::Expr(self.wrapped)
+ }
+ fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy {
+ AstNodeWrapper::new(fragment.make_method_receiver_expr(), MethodReceiverTag)
+ }
+ fn noop_visit<V: MutVisitor>(&mut self, visitor: &mut V) {
+ noop_visit_expr(&mut self.wrapped, visitor)
+ }
+ fn is_mac_call(&self) -> bool {
+ matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
+ }
+ fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
+ let node = self.wrapped.into_inner();
+ match node.kind {
+ ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
+ _ => unreachable!(),
+ }
+ }
+}
+
struct InvocationCollector<'a, 'b> {
cx: &'a mut ExtCtxt<'b>,
invocations: Vec<(Invocation, Option<Lrc<SyntaxExtension>>)>,
@@ -1841,6 +1895,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
self.visit_node(node)
}
+ fn visit_method_receiver_expr(&mut self, node: &mut P<ast::Expr>) {
+ visit_clobber(node, |node| {
+ let mut wrapper = AstNodeWrapper::new(node, MethodReceiverTag);
+ self.visit_node(&mut wrapper);
+ wrapper.wrapped
+ })
+ }
+
fn filter_map_expr(&mut self, node: P<ast::Expr>) -> Option<P<ast::Expr>> {
self.flat_map_node(AstNodeWrapper::new(node, OptExprTag))
}
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index ffc9abe64..b34de94fb 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -3,7 +3,6 @@
#![feature(associated_type_defaults)]
#![feature(if_let_guard)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(macro_metavar_expr)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_internals)]
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 7764ffd24..f6fe38174 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -14,7 +14,7 @@ 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, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
use rustc_feature::Features;
use rustc_lint_defs::builtin::{
RUST_2021_INCOMPATIBLE_OR_PATTERNS, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS,
@@ -68,19 +68,22 @@ fn emit_frag_parse_err(
kind: AstFragmentKind,
) {
// FIXME(davidtwco): avoid depending on the error message text
- if parser.token == token::Eof && e.message[0].0.expect_str().ends_with(", found `<eof>`") {
- if !e.span.is_dummy() {
- // early end of macro arm (#52866)
- e.replace_span_with(parser.sess.source_map().next_point(parser.token.span));
- }
+ if parser.token == token::Eof
+ && let DiagnosticMessage::Str(message) = &e.message[0].0
+ && message.ends_with(", found `<eof>`")
+ {
let msg = &e.message[0];
e.message[0] = (
- rustc_errors::DiagnosticMessage::Str(format!(
+ DiagnosticMessage::Str(format!(
"macro expansion ends with an incomplete expression: {}",
- msg.0.expect_str().replace(", found `<eof>`", ""),
+ message.replace(", found `<eof>`", ""),
)),
msg.1,
);
+ if !e.span.is_dummy() {
+ // early end of macro arm (#52866)
+ e.replace_span_with(parser.token.span.shrink_to_hi());
+ }
}
if e.span.is_dummy() {
// Get around lack of span in error (#30128)
@@ -247,6 +250,7 @@ fn expand_macro<'cx>(
// hacky, but speeds up the `html5ever` benchmark significantly. (Issue
// 68836 suggests a more comprehensive but more complex change to deal with
// this situation.)
+ // FIXME(Nilstrieb): Stop recovery from happening on this parser and retry later with recovery if the macro failed to match.
let parser = parser_from_cx(sess, arg.clone());
// Try each arm's matchers.
@@ -593,14 +597,14 @@ pub fn compile_declarative_macro(
(mk_syn_ext(expander), rule_spans)
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum ExplainDocComment {
- #[label(expand::explain_doc_comment_inner)]
+ #[label(expand_explain_doc_comment_inner)]
Inner {
#[primary_span]
span: Span,
},
- #[label(expand::explain_doc_comment_outer)]
+ #[label(expand_explain_doc_comment_outer)]
Outer {
#[primary_span]
span: Span,
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 3b0d5ddb9..faaf3b3fe 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -55,6 +55,7 @@ pub fn placeholder(
}),
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
+ AstFragmentKind::MethodReceiverExpr => AstFragment::MethodReceiverExpr(expr_placeholder()),
AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
id,
span,
@@ -296,6 +297,13 @@ impl MutVisitor for PlaceholderExpander {
}
}
+ fn visit_method_receiver_expr(&mut self, expr: &mut P<ast::Expr>) {
+ match expr.kind {
+ ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_method_receiver_expr(),
+ _ => noop_visit_expr(expr, self),
+ }
+ }
+
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
match expr.kind {
ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index 59a7b668a..cc2858d3f 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -1,5 +1,8 @@
use crate::base::ExtCtxt;
-
+use pm::bridge::{
+ server, DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree,
+};
+use pm::{Delimiter, Level, LineColumn};
use rustc_ast as ast;
use rustc_ast::token;
use rustc_ast::tokenstream::{self, Spacing::*, TokenStream};
@@ -13,11 +16,7 @@ use rustc_session::parse::ParseSess;
use rustc_span::def_id::CrateNum;
use rustc_span::symbol::{self, sym, Symbol};
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span};
-
-use pm::bridge::{
- server, DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree,
-};
-use pm::{Delimiter, Level, LineColumn};
+use smallvec::{smallvec, SmallVec};
use std::ops::Bound;
trait FromInternal<T> {
@@ -110,10 +109,26 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
tokenstream::TokenTree::Token(token, spacing) => (token, spacing == Joint),
};
+ // Split the operator into one or more `Punct`s, one per character.
+ // The final one inherits the jointness of the original token. Any
+ // before that get `joint = true`.
let mut op = |s: &str| {
assert!(s.is_ascii());
- trees.extend(s.as_bytes().iter().enumerate().map(|(idx, &ch)| {
- TokenTree::Punct(Punct { ch, joint: joint || idx != s.len() - 1, span })
+ trees.extend(s.bytes().enumerate().map(|(i, ch)| {
+ let is_final = i == s.len() - 1;
+ // Split the token span into single chars. Unless the span
+ // is an unusual one, e.g. due to proc macro expansion. We
+ // determine this by assuming any span with a length that
+ // matches the operator length is a normal one, and any
+ // span with a different length is an unusual one.
+ let span = if (span.hi() - span.lo()).to_usize() == s.len() {
+ let lo = span.lo() + BytePos::from_usize(i);
+ let hi = lo + BytePos::from_usize(1);
+ span.with_lo(lo).with_hi(hi)
+ } else {
+ span
+ };
+ TokenTree::Punct(Punct { ch, joint: if is_final { joint } else { true }, span })
}));
};
@@ -237,23 +252,57 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
}
}
-impl ToInternal<TokenStream> for (TokenTree<TokenStream, Span, Symbol>, &mut Rustc<'_, '_>) {
- fn to_internal(self) -> TokenStream {
+// We use a `SmallVec` because the output size is always one or two `TokenTree`s.
+impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
+ for (TokenTree<TokenStream, Span, Symbol>, &mut Rustc<'_, '_>)
+{
+ fn to_internal(self) -> SmallVec<[tokenstream::TokenTree; 2]> {
use rustc_ast::token::*;
let (tree, rustc) = self;
- let (ch, joint, span) = match tree {
- TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span),
+ match tree {
+ TokenTree::Punct(Punct { ch, joint, span }) => {
+ let kind = match ch {
+ b'=' => Eq,
+ b'<' => Lt,
+ b'>' => Gt,
+ b'!' => Not,
+ b'~' => Tilde,
+ b'+' => BinOp(Plus),
+ b'-' => BinOp(Minus),
+ b'*' => BinOp(Star),
+ b'/' => BinOp(Slash),
+ b'%' => BinOp(Percent),
+ b'^' => BinOp(Caret),
+ b'&' => BinOp(And),
+ b'|' => BinOp(Or),
+ b'@' => At,
+ b'.' => Dot,
+ b',' => Comma,
+ b';' => Semi,
+ b':' => Colon,
+ b'#' => Pound,
+ b'$' => Dollar,
+ b'?' => Question,
+ b'\'' => SingleQuote,
+ _ => unreachable!(),
+ };
+ smallvec![if joint {
+ tokenstream::TokenTree::token_joint(kind, span)
+ } else {
+ tokenstream::TokenTree::token_alone(kind, span)
+ }]
+ }
TokenTree::Group(Group { delimiter, stream, span: DelimSpan { open, close, .. } }) => {
- return tokenstream::TokenStream::delimited(
+ smallvec![tokenstream::TokenTree::Delimited(
tokenstream::DelimSpan { open, close },
delimiter.to_internal(),
stream.unwrap_or_default(),
- );
+ )]
}
TokenTree::Ident(self::Ident { sym, is_raw, span }) => {
rustc.sess().symbol_gallery.insert(sym, span);
- return tokenstream::TokenStream::token_alone(Ident(sym, is_raw), span);
+ smallvec![tokenstream::TokenTree::token_alone(Ident(sym, is_raw), span)]
}
TokenTree::Literal(self::Literal {
kind: self::LitKind::Integer,
@@ -266,7 +315,7 @@ impl ToInternal<TokenStream> for (TokenTree<TokenStream, Span, Symbol>, &mut Rus
let integer = TokenKind::lit(token::Integer, symbol, suffix);
let a = tokenstream::TokenTree::token_alone(minus, span);
let b = tokenstream::TokenTree::token_alone(integer, span);
- return [a, b].into_iter().collect();
+ smallvec![a, b]
}
TokenTree::Literal(self::Literal {
kind: self::LitKind::Float,
@@ -279,46 +328,14 @@ impl ToInternal<TokenStream> for (TokenTree<TokenStream, Span, Symbol>, &mut Rus
let float = TokenKind::lit(token::Float, symbol, suffix);
let a = tokenstream::TokenTree::token_alone(minus, span);
let b = tokenstream::TokenTree::token_alone(float, span);
- return [a, b].into_iter().collect();
+ smallvec![a, b]
}
TokenTree::Literal(self::Literal { kind, symbol, suffix, span }) => {
- return tokenstream::TokenStream::token_alone(
+ smallvec![tokenstream::TokenTree::token_alone(
TokenKind::lit(kind.to_internal(), symbol, suffix),
span,
- );
+ )]
}
- };
-
- let kind = match ch {
- b'=' => Eq,
- b'<' => Lt,
- b'>' => Gt,
- b'!' => Not,
- b'~' => Tilde,
- b'+' => BinOp(Plus),
- b'-' => BinOp(Minus),
- b'*' => BinOp(Star),
- b'/' => BinOp(Slash),
- b'%' => BinOp(Percent),
- b'^' => BinOp(Caret),
- b'&' => BinOp(And),
- b'|' => BinOp(Or),
- b'@' => At,
- b'.' => Dot,
- b',' => Comma,
- b';' => Semi,
- b':' => Colon,
- b'#' => Pound,
- b'$' => Dollar,
- b'?' => Question,
- b'\'' => SingleQuote,
- _ => unreachable!(),
- };
-
- if joint {
- tokenstream::TokenStream::token_joint(kind, span)
- } else {
- tokenstream::TokenStream::token_alone(kind, span)
}
}
}
@@ -533,7 +550,7 @@ impl server::TokenStream for Rustc<'_, '_> {
&mut self,
tree: TokenTree<Self::TokenStream, Self::Span, Self::Symbol>,
) -> Self::TokenStream {
- (tree, &mut *self).to_internal()
+ Self::TokenStream::new((tree, &mut *self).to_internal().into_iter().collect::<Vec<_>>())
}
fn concat_trees(
@@ -541,14 +558,14 @@ impl server::TokenStream for Rustc<'_, '_> {
base: Option<Self::TokenStream>,
trees: Vec<TokenTree<Self::TokenStream, Self::Span, Self::Symbol>>,
) -> Self::TokenStream {
- let mut builder = tokenstream::TokenStreamBuilder::new();
- if let Some(base) = base {
- builder.push(base);
- }
+ let mut stream =
+ if let Some(base) = base { base } else { tokenstream::TokenStream::default() };
for tree in trees {
- builder.push((tree, &mut *self).to_internal());
+ for tt in (tree, &mut *self).to_internal() {
+ stream.push_tree(tt);
+ }
}
- builder.build()
+ stream
}
fn concat_streams(
@@ -556,14 +573,12 @@ impl server::TokenStream for Rustc<'_, '_> {
base: Option<Self::TokenStream>,
streams: Vec<Self::TokenStream>,
) -> Self::TokenStream {
- let mut builder = tokenstream::TokenStreamBuilder::new();
- if let Some(base) = base {
- builder.push(base);
+ let mut stream =
+ if let Some(base) = base { base } else { tokenstream::TokenStream::default() };
+ for s in streams {
+ stream.push_stream(s);
}
- for stream in streams {
- builder.push(stream);
- }
- builder.build()
+ stream
}
fn into_trees(
@@ -689,6 +704,7 @@ impl server::Span for Rustc<'_, '_> {
fn source_text(&mut self, span: Self::Span) -> Option<String> {
self.sess().source_map().span_to_snippet(span).ok()
}
+
/// Saves the provided span into the metadata of
/// *the crate we are currently compiling*, which must
/// be a proc-macro crate. This id can be passed to
diff --git a/compiler/rustc_expand/src/tokenstream/tests.rs b/compiler/rustc_expand/src/tokenstream/tests.rs
index eed696810..91c4dd732 100644
--- a/compiler/rustc_expand/src/tokenstream/tests.rs
+++ b/compiler/rustc_expand/src/tokenstream/tests.rs
@@ -1,7 +1,7 @@
use crate::tests::string_to_stream;
use rustc_ast::token;
-use rustc_ast::tokenstream::{TokenStream, TokenStreamBuilder};
+use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_span::create_default_session_globals_then;
use rustc_span::{BytePos, Span, Symbol};
@@ -19,10 +19,9 @@ fn test_concat() {
let test_res = string_to_ts("foo::bar::baz");
let test_fst = string_to_ts("foo::bar");
let test_snd = string_to_ts("::baz");
- let mut builder = TokenStreamBuilder::new();
- builder.push(test_fst);
- builder.push(test_snd);
- let eq_res = builder.build();
+ let mut eq_res = TokenStream::default();
+ eq_res.push_stream(test_fst);
+ eq_res.push_stream(test_snd);
assert_eq!(test_res.trees().count(), 5);
assert_eq!(eq_res.trees().count(), 5);
assert_eq!(test_res.eq_unspanned(&eq_res), true);
@@ -99,11 +98,10 @@ fn test_is_empty() {
#[test]
fn test_dotdotdot() {
create_default_session_globals_then(|| {
- let mut builder = TokenStreamBuilder::new();
- builder.push(TokenStream::token_joint(token::Dot, sp(0, 1)));
- builder.push(TokenStream::token_joint(token::Dot, sp(1, 2)));
- builder.push(TokenStream::token_alone(token::Dot, sp(2, 3)));
- let stream = builder.build();
+ let mut stream = TokenStream::default();
+ stream.push_tree(TokenTree::token_joint(token::Dot, sp(0, 1)));
+ stream.push_tree(TokenTree::token_joint(token::Dot, sp(1, 2)));
+ stream.push_tree(TokenTree::token_alone(token::Dot, sp(2, 3)));
assert!(stream.eq_unspanned(&string_to_ts("...")));
assert_eq!(stream.trees().count(), 1);
})
diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml
index 3d8d0db20..6f6468646 100644
--- a/compiler/rustc_feature/Cargo.toml
+++ b/compiler/rustc_feature/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 8efb7ccc1..80448605c 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -53,6 +53,10 @@ declare_features! (
(accepted, abi_sysv64, "1.24.0", Some(36167), None),
/// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
(accepted, adx_target_feature, "1.61.0", Some(44839), None),
+ /// Allows explicit discriminants on non-unit enum variants.
+ (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553), None),
+ /// Allows using `sym` operands in inline assembly.
+ (accepted, asm_sym, "1.66.0", Some(93333), None),
/// Allows the definition of associated constants in `trait` or `impl` blocks.
(accepted, associated_consts, "1.20.0", Some(29646), None),
/// Allows using associated `type`s in `trait`s.
@@ -169,6 +173,8 @@ declare_features! (
(accepted, global_allocator, "1.28.0", Some(27389), None),
// FIXME: explain `globs`.
(accepted, globs, "1.0.0", None, None),
+ /// Allows using `..=X` as a pattern.
+ (accepted, half_open_range_patterns, "1.66.0", Some(67264), None),
/// Allows using the `u128` and `i128` types.
(accepted, i128_type, "1.26.0", Some(35118), None),
/// Allows the use of `if let` expressions.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 3aecfba5f..647ccdec7 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -292,16 +292,12 @@ declare_features! (
(incomplete, adt_const_params, "1.56.0", Some(95174), None),
/// Allows defining an `#[alloc_error_handler]`.
(active, alloc_error_handler, "1.29.0", Some(51540), None),
- /// Allows explicit discriminants on non-unit enum variants.
- (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
/// Allows trait methods with arbitrary self types.
(active, arbitrary_self_types, "1.23.0", Some(44874), None),
/// Allows using `const` operands in inline assembly.
(active, asm_const, "1.58.0", Some(93332), None),
/// Enables experimental inline assembly support for additional architectures.
(active, asm_experimental_arch, "1.58.0", Some(93335), None),
- /// Allows using `sym` operands in inline assembly.
- (active, asm_sym, "1.58.0", Some(93333), None),
/// Allows the `may_unwind` option in inline assembly.
(active, asm_unwind, "1.58.0", Some(93334), None),
/// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
@@ -312,6 +308,8 @@ declare_features! (
(active, associated_type_defaults, "1.2.0", Some(29661), None),
/// Allows `async || body` closures.
(active, async_closure, "1.37.0", Some(62290), None),
+ /// Alows async functions to be declared, implemented, and used in traits.
+ (incomplete, async_fn_in_trait, "1.66.0", Some(91611), None),
/// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries.
(active, c_unwind, "1.52.0", Some(74990), None),
/// Allows using C-variadics.
@@ -410,8 +408,8 @@ declare_features! (
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
- /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
- (active, half_open_range_patterns, "1.41.0", Some(67264), None),
+ /// Allows using `..=X` as a patterns in slices.
+ (active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
/// Allows `if let` guard in match arms.
(active, if_let_guard, "1.47.0", Some(51114), None),
/// Allows using imported `main` function
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index b50c972e6..2ead3c2c8 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -296,20 +296,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Lints:
ungated!(
- warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+ DuplicatesOk, @only_local: true,
),
ungated!(
- allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+ DuplicatesOk, @only_local: true,
),
gated!(
expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk,
lint_reasons, experimental!(expect)
),
ungated!(
- forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+ DuplicatesOk, @only_local: true,
),
ungated!(
- deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
+ DuplicatesOk, @only_local: true,
),
ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
gated!(
@@ -340,7 +344,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
),
ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(no_link, Normal, template!(Word), WarnFollowing),
- ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
+ ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, @only_local: true),
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
@@ -382,7 +386,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true),
ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true),
ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
- ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
+ ungated!(
+ target_feature, Normal, template!(List: r#"enable = "name""#),
+ DuplicatesOk, @only_local: true,
+ ),
ungated!(track_caller, Normal, template!(Word), WarnFollowing),
gated!(
no_sanitize, Normal,
@@ -468,7 +475,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// RFC 2632
gated!(
const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl,
- "`const` is a temporary placeholder for marking a trait that is suitable for `const` \
+ "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \
`impls` and all default bodies as `const`, which may be removed or renamed in the \
future."
),
@@ -488,17 +495,24 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Internal attributes: Stability, deprecation, and unsafe:
// ==========================================================================
- ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
+ ungated!(
+ feature, CrateLevel,
+ template!(List: "name1, name2, ..."), DuplicatesOk, @only_local: true,
+ ),
// DuplicatesOk since it has its own validation
ungated!(
- stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
+ stable, Normal,
+ template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, @only_local: true,
),
ungated!(
unstable, Normal,
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
),
ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
- ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
+ ungated!(
+ rustc_const_stable, Normal,
+ template!(List: r#"feature = "name""#), DuplicatesOk, @only_local: true,
+ ),
ungated!(
rustc_default_body_unstable, Normal,
template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk
@@ -516,6 +530,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
"allow_internal_unsafe side-steps the unsafe_code lint",
),
+ ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk),
rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing,
"rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
through unstable paths"),
@@ -535,7 +550,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// ==========================================================================
rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
- rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
@@ -731,7 +746,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
for reserving for `for<T> From<!> for T` impl"
),
rustc_attr!(
- rustc_test_marker, Normal, template!(Word), WarnFollowing,
+ rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
"the `#[rustc_test_marker]` attribute is used internally to track tests",
),
rustc_attr!(
@@ -762,7 +777,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Internal attributes, Testing:
// ==========================================================================
- rustc_attr!(TEST, rustc_access_level, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
@@ -822,6 +837,8 @@ pub fn is_builtin_attr_name(name: Symbol) -> bool {
BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
}
+/// Whether this builtin attribute is only used in the local crate.
+/// If so, it is not encoded in the crate metadata.
pub fn is_builtin_only_local(name: Symbol) -> bool {
BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
}
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 69ad623b7..129f8d235 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_arena = { path = "../rustc_arena" }
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index e7c26bd72..4ef4aad90 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -314,74 +314,75 @@ pub enum Res<Id = hir::HirId> {
/// **Belongs to the type namespace.**
PrimTy(hir::PrimTy),
- /// The `Self` type, optionally with the [`DefId`] of the trait it belongs to and
- /// optionally with the [`DefId`] of the item introducing the `Self` type alias.
+ /// The `Self` type, as used within a trait.
+ ///
+ /// **Belongs to the type namespace.**
+ ///
+ /// See the examples on [`Res::SelfTyAlias`] for details.
+ SelfTyParam {
+ /// The trait this `Self` is a generic parameter for.
+ trait_: DefId,
+ },
+
+ /// The `Self` type, as used somewhere other than within a trait.
///
/// **Belongs to the type namespace.**
///
/// Examples:
/// ```
- /// struct Bar(Box<Self>);
- /// // `Res::SelfTy { trait_: None, alias_of: Some(Bar) }`
+ /// struct Bar(Box<Self>); // SelfTyAlias
///
/// trait Foo {
- /// fn foo() -> Box<Self>;
- /// // `Res::SelfTy { trait_: Some(Foo), alias_of: None }`
+ /// fn foo() -> Box<Self>; // SelfTyParam
/// }
///
/// impl Bar {
/// fn blah() {
- /// let _: Self;
- /// // `Res::SelfTy { trait_: None, alias_of: Some(::{impl#0}) }`
+ /// let _: Self; // SelfTyAlias
/// }
/// }
///
/// impl Foo for Bar {
- /// fn foo() -> Box<Self> {
- /// // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
- /// let _: Self;
- /// // `Res::SelfTy { trait_: Some(Foo), alias_of: Some(::{impl#1}) }`
+ /// fn foo() -> Box<Self> { // SelfTyAlias
+ /// let _: Self; // SelfTyAlias
///
/// todo!()
/// }
/// }
/// ```
- ///
/// *See also [`Res::SelfCtor`].*
///
- /// -----
- ///
- /// HACK(min_const_generics): self types also have an optional requirement to **not** mention
- /// any generic parameters to allow the following with `min_const_generics`:
- /// ```
- /// # struct Foo;
- /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
- ///
- /// struct Bar([u8; baz::<Self>()]);
- /// const fn baz<T>() -> usize { 10 }
- /// ```
- /// We do however allow `Self` in repeat expression even if it is generic to not break code
- /// which already works on stable while causing the `const_evaluatable_unchecked` future compat
- /// lint:
- /// ```
- /// fn foo<T>() {
- /// let _bar = [1_u8; std::mem::size_of::<*mut T>()];
- /// }
- /// ```
- // FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
- SelfTy {
- /// The trait this `Self` is a generic arg for.
- trait_: Option<DefId>,
+ SelfTyAlias {
/// The item introducing the `Self` type alias. Can be used in the `type_of` query
- /// to get the underlying type. Additionally whether the `Self` type is disallowed
- /// from mentioning generics (i.e. when used in an anonymous constant).
- alias_to: Option<(DefId, bool)>,
- },
+ /// to get the underlying type.
+ alias_to: DefId,
- /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
- ///
- /// **Belongs to the type namespace.**
- ToolMod,
+ /// Whether the `Self` type is disallowed from mentioning generics (i.e. when used in an
+ /// anonymous constant).
+ ///
+ /// HACK(min_const_generics): self types also have an optional requirement to **not**
+ /// mention any generic parameters to allow the following with `min_const_generics`:
+ /// ```
+ /// # struct Foo;
+ /// impl Foo { fn test() -> [u8; std::mem::size_of::<Self>()] { todo!() } }
+ ///
+ /// struct Bar([u8; baz::<Self>()]);
+ /// const fn baz<T>() -> usize { 10 }
+ /// ```
+ /// We do however allow `Self` in repeat expression even if it is generic to not break code
+ /// which already works on stable while causing the `const_evaluatable_unchecked` future
+ /// compat lint:
+ /// ```
+ /// fn foo<T>() {
+ /// let _bar = [1_u8; std::mem::size_of::<*mut T>()];
+ /// }
+ /// ```
+ // FIXME(generic_const_exprs): Remove this bodge once that feature is stable.
+ forbid_generic: bool,
+
+ /// Is this within an `impl Foo for bar`?
+ is_trait_impl: bool,
+ },
// Value namespace
/// The `Self` constructor, along with the [`DefId`]
@@ -389,7 +390,7 @@ pub enum Res<Id = hir::HirId> {
///
/// **Belongs to the value namespace.**
///
- /// *See also [`Res::SelfTy`].*
+ /// *See also [`Res::SelfTyParam`] and [`Res::SelfTyAlias`].*
SelfCtor(DefId),
/// A local variable or function parameter.
@@ -397,6 +398,11 @@ pub enum Res<Id = hir::HirId> {
/// **Belongs to the value namespace.**
Local(Id),
+ /// A tool attribute module; e.g., the `rustfmt` in `#[rustfmt::skip]`.
+ ///
+ /// **Belongs to the type namespace.**
+ ToolMod,
+
// Macro namespace
/// An attribute that is *not* implemented via macro.
/// E.g., `#[inline]` and `#[rustfmt::skip]`, which are essentially directives,
@@ -458,6 +464,16 @@ impl PartialRes {
pub fn unresolved_segments(&self) -> usize {
self.unresolved_segments
}
+
+ #[inline]
+ pub fn full_res(&self) -> Option<Res<NodeId>> {
+ (self.unresolved_segments == 0).then_some(self.base_res)
+ }
+
+ #[inline]
+ pub fn expect_full_res(&self) -> Res<NodeId> {
+ self.full_res().expect("unexpected unresolved segments")
+ }
}
/// Different kinds of symbols can coexist even if they share the same textual name.
@@ -606,7 +622,8 @@ impl<Id> Res<Id> {
Res::Local(..)
| Res::PrimTy(..)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::SelfCtor(..)
| Res::ToolMod
| Res::NonMacroAttr(..)
@@ -629,7 +646,7 @@ impl<Id> Res<Id> {
Res::SelfCtor(..) => "self constructor",
Res::PrimTy(..) => "builtin type",
Res::Local(..) => "local variable",
- Res::SelfTy { .. } => "self type",
+ Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => "self type",
Res::ToolMod => "tool module",
Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
Res::Err => "unresolved item",
@@ -652,7 +669,10 @@ impl<Id> Res<Id> {
Res::SelfCtor(id) => Res::SelfCtor(id),
Res::PrimTy(id) => Res::PrimTy(id),
Res::Local(id) => Res::Local(map(id)),
- Res::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+ Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
+ Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
+ Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
+ }
Res::ToolMod => Res::ToolMod,
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
@@ -665,7 +685,10 @@ impl<Id> Res<Id> {
Res::SelfCtor(id) => Res::SelfCtor(id),
Res::PrimTy(id) => Res::PrimTy(id),
Res::Local(id) => Res::Local(map(id)?),
- Res::SelfTy { trait_, alias_to } => Res::SelfTy { trait_, alias_to },
+ Res::SelfTyParam { trait_ } => Res::SelfTyParam { trait_ },
+ Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl } => {
+ Res::SelfTyAlias { alias_to, forbid_generic, is_trait_impl }
+ }
Res::ToolMod => Res::ToolMod,
Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
Res::Err => Res::Err,
@@ -692,7 +715,9 @@ impl<Id> Res<Id> {
pub fn ns(&self) -> Option<Namespace> {
match self {
Res::Def(kind, ..) => kind.ns(),
- Res::PrimTy(..) | Res::SelfTy { .. } | Res::ToolMod => Some(Namespace::TypeNS),
+ Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::ToolMod => {
+ Some(Namespace::TypeNS)
+ }
Res::SelfCtor(..) | Res::Local(..) => Some(Namespace::ValueNS),
Res::NonMacroAttr(..) => Some(Namespace::MacroNS),
Res::Err => None,
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index a8436ea64..ef00c1ffc 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1,6 +1,6 @@
use crate::def::{CtorKind, DefKind, Res};
use crate::def_id::DefId;
-pub(crate) use crate::hir_id::{HirId, ItemLocalId};
+pub(crate) use crate::hir_id::{HirId, ItemLocalId, OwnerId};
use crate::intravisit::FnKind;
use crate::LangItem;
@@ -731,6 +731,7 @@ pub enum PredicateOrigin {
/// A type bound (e.g., `for<'c> Foo: Send + Clone + 'c`).
#[derive(Debug, HashStable_Generic)]
pub struct WhereBoundPredicate<'hir> {
+ pub hir_id: HirId,
pub span: Span,
/// Origin of the predicate.
pub origin: PredicateOrigin,
@@ -2206,14 +2207,14 @@ pub struct FnSig<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct TraitItemId {
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
}
impl TraitItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
}
@@ -2224,7 +2225,7 @@ impl TraitItemId {
#[derive(Debug, HashStable_Generic)]
pub struct TraitItem<'hir> {
pub ident: Ident,
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: TraitItemKind<'hir>,
pub span: Span,
@@ -2235,11 +2236,11 @@ impl TraitItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
pub fn trait_item_id(&self) -> TraitItemId {
- TraitItemId { def_id: self.def_id }
+ TraitItemId { owner_id: self.owner_id }
}
}
@@ -2270,14 +2271,14 @@ pub enum TraitItemKind<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct ImplItemId {
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
}
impl ImplItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
}
@@ -2285,7 +2286,7 @@ impl ImplItemId {
#[derive(Debug, HashStable_Generic)]
pub struct ImplItem<'hir> {
pub ident: Ident,
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
pub generics: &'hir Generics<'hir>,
pub kind: ImplItemKind<'hir>,
pub defaultness: Defaultness,
@@ -2297,11 +2298,11 @@ impl ImplItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
pub fn impl_item_id(&self) -> ImplItemId {
- ImplItemId { def_id: self.def_id }
+ ImplItemId { owner_id: self.owner_id }
}
}
@@ -2314,7 +2315,7 @@ pub enum ImplItemKind<'hir> {
/// An associated function implementation with the given signature and body.
Fn(FnSig<'hir>, BodyId),
/// An associated type.
- TyAlias(&'hir Ty<'hir>),
+ Type(&'hir Ty<'hir>),
}
// The name of the associated type for `Fn` return types.
@@ -2403,8 +2404,9 @@ impl<'hir> Ty<'hir> {
return None;
};
match path.res {
- Res::Def(DefKind::TyParam, def_id)
- | Res::SelfTy { trait_: Some(def_id), alias_to: None } => Some((def_id, segment.ident)),
+ Res::Def(DefKind::TyParam, def_id) | Res::SelfTyParam { trait_: def_id } => {
+ Some((def_id, segment.ident))
+ }
_ => None,
}
}
@@ -2416,6 +2418,30 @@ impl<'hir> Ty<'hir> {
}
final_ty
}
+
+ pub fn find_self_aliases(&self) -> Vec<Span> {
+ use crate::intravisit::Visitor;
+ struct MyVisitor(Vec<Span>);
+ impl<'v> Visitor<'v> for MyVisitor {
+ fn visit_ty(&mut self, t: &'v Ty<'v>) {
+ if matches!(
+ &t.kind,
+ TyKind::Path(QPath::Resolved(
+ _,
+ Path { res: crate::def::Res::SelfTyAlias { .. }, .. },
+ ))
+ ) {
+ self.0.push(t.span);
+ return;
+ }
+ crate::intravisit::walk_ty(self, t);
+ }
+ }
+
+ let mut my_visitor = MyVisitor(vec![]);
+ my_visitor.visit_ty(self);
+ my_visitor.0
+ }
}
/// Not represented directly in the AST; referred to by name through a `ty_path`.
@@ -2888,14 +2914,14 @@ impl<'hir> VariantData<'hir> {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, Hash, HashStable_Generic)]
pub struct ItemId {
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
}
impl ItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
}
@@ -2905,7 +2931,7 @@ impl ItemId {
#[derive(Debug, HashStable_Generic)]
pub struct Item<'hir> {
pub ident: Ident,
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
pub kind: ItemKind<'hir>,
pub span: Span,
pub vis_span: Span,
@@ -2915,11 +2941,11 @@ impl Item<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
pub fn item_id(&self) -> ItemId {
- ItemId { def_id: self.def_id }
+ ItemId { owner_id: self.owner_id }
}
}
@@ -3132,14 +3158,14 @@ pub enum AssocItemKind {
// so it can fetched later.
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct ForeignItemId {
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
}
impl ForeignItemId {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
}
@@ -3160,7 +3186,7 @@ pub struct ForeignItemRef {
pub struct ForeignItem<'hir> {
pub ident: Ident,
pub kind: ForeignItemKind<'hir>,
- pub def_id: LocalDefId,
+ pub owner_id: OwnerId,
pub span: Span,
pub vis_span: Span,
}
@@ -3169,11 +3195,11 @@ impl ForeignItem<'_> {
#[inline]
pub fn hir_id(&self) -> HirId {
// Items are always HIR owners.
- HirId::make_owner(self.def_id)
+ HirId::make_owner(self.owner_id.def_id)
}
pub fn foreign_item_id(&self) -> ForeignItemId {
- ForeignItemId { def_id: self.def_id }
+ ForeignItemId { owner_id: self.owner_id }
}
}
@@ -3263,12 +3289,12 @@ impl<'hir> OwnerNode<'hir> {
Node::generics(self.into())
}
- pub fn def_id(self) -> LocalDefId {
+ pub fn def_id(self) -> OwnerId {
match self {
- OwnerNode::Item(Item { def_id, .. })
- | OwnerNode::TraitItem(TraitItem { def_id, .. })
- | OwnerNode::ImplItem(ImplItem { def_id, .. })
- | OwnerNode::ForeignItem(ForeignItem { def_id, .. }) => *def_id,
+ OwnerNode::Item(Item { owner_id, .. })
+ | OwnerNode::TraitItem(TraitItem { owner_id, .. })
+ | OwnerNode::ImplItem(ImplItem { owner_id, .. })
+ | OwnerNode::ForeignItem(ForeignItem { owner_id, .. }) => *owner_id,
OwnerNode::Crate(..) => crate::CRATE_HIR_ID.owner,
}
}
@@ -3512,7 +3538,7 @@ impl<'hir> Node<'hir> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(Block<'_>, 48);
static_assert_size!(Body<'_>, 32);
static_assert_size!(Expr<'_>, 64);
@@ -3520,30 +3546,27 @@ mod size_asserts {
static_assert_size!(FnDecl<'_>, 40);
static_assert_size!(ForeignItem<'_>, 72);
static_assert_size!(ForeignItemKind<'_>, 40);
- #[cfg(not(bootstrap))]
static_assert_size!(GenericArg<'_>, 24);
static_assert_size!(GenericBound<'_>, 48);
static_assert_size!(Generics<'_>, 56);
static_assert_size!(Impl<'_>, 80);
- #[cfg(not(bootstrap))]
static_assert_size!(ImplItem<'_>, 80);
- #[cfg(not(bootstrap))]
static_assert_size!(ImplItemKind<'_>, 32);
static_assert_size!(Item<'_>, 80);
static_assert_size!(ItemKind<'_>, 48);
static_assert_size!(Local<'_>, 64);
static_assert_size!(Param<'_>, 32);
static_assert_size!(Pat<'_>, 72);
+ static_assert_size!(Path<'_>, 40);
+ static_assert_size!(PathSegment<'_>, 48);
static_assert_size!(PatKind<'_>, 48);
- static_assert_size!(Path<'_>, 48);
- static_assert_size!(PathSegment<'_>, 56);
static_assert_size!(QPath<'_>, 24);
+ static_assert_size!(Res, 12);
static_assert_size!(Stmt<'_>, 32);
static_assert_size!(StmtKind<'_>, 16);
- #[cfg(not(bootstrap))]
static_assert_size!(TraitItem<'_>, 88);
- #[cfg(not(bootstrap))]
static_assert_size!(TraitItemKind<'_>, 48);
static_assert_size!(Ty<'_>, 48);
static_assert_size!(TyKind<'_>, 32);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs
index 84b0740c7..752f760ea 100644
--- a/compiler/rustc_hir/src/hir_id.rs
+++ b/compiler/rustc_hir/src/hir_id.rs
@@ -1,6 +1,43 @@
-use crate::def_id::{LocalDefId, CRATE_DEF_ID};
+use crate::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
+use rustc_span::{def_id::DefPathHash, HashStableContext};
use std::fmt;
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Encodable, Decodable)]
+pub struct OwnerId {
+ pub def_id: LocalDefId,
+}
+
+impl From<OwnerId> for HirId {
+ fn from(owner: OwnerId) -> HirId {
+ HirId { owner, local_id: ItemLocalId::from_u32(0) }
+ }
+}
+
+impl OwnerId {
+ #[inline]
+ pub fn to_def_id(self) -> DefId {
+ self.def_id.to_def_id()
+ }
+}
+
+impl<CTX: HashStableContext> HashStable<CTX> for OwnerId {
+ #[inline]
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ self.to_stable_hash_key(hcx).hash_stable(hcx, hasher);
+ }
+}
+
+impl<CTX: HashStableContext> ToStableHashKey<CTX> for OwnerId {
+ type KeyType = DefPathHash;
+
+ #[inline]
+ fn to_stable_hash_key(&self, hcx: &CTX) -> DefPathHash {
+ hcx.def_path_hash(self.to_def_id())
+ }
+}
+
/// Uniquely identifies a node in the HIR of the current crate. It is
/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing
/// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"),
@@ -15,22 +52,23 @@ use std::fmt;
#[derive(Encodable, Decodable, HashStable_Generic)]
#[rustc_pass_by_value]
pub struct HirId {
- pub owner: LocalDefId,
+ pub owner: OwnerId,
pub local_id: ItemLocalId,
}
impl HirId {
/// Signal local id which should never be used.
- pub const INVALID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::INVALID };
+ pub const INVALID: HirId =
+ HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::INVALID };
#[inline]
- pub fn expect_owner(self) -> LocalDefId {
+ pub fn expect_owner(self) -> OwnerId {
assert_eq!(self.local_id.index(), 0);
self.owner
}
#[inline]
- pub fn as_owner(self) -> Option<LocalDefId> {
+ pub fn as_owner(self) -> Option<OwnerId> {
if self.local_id.index() == 0 { Some(self.owner) } else { None }
}
@@ -41,11 +79,14 @@ impl HirId {
#[inline]
pub fn make_owner(owner: LocalDefId) -> Self {
- Self { owner, local_id: ItemLocalId::from_u32(0) }
+ Self { owner: OwnerId { def_id: owner }, local_id: ItemLocalId::from_u32(0) }
}
pub fn index(self) -> (usize, usize) {
- (rustc_index::vec::Idx::index(self.owner), rustc_index::vec::Idx::index(self.local_id))
+ (
+ rustc_index::vec::Idx::index(self.owner.def_id),
+ rustc_index::vec::Idx::index(self.local_id),
+ )
}
}
@@ -94,4 +135,7 @@ impl ItemLocalId {
}
/// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_ID`.
-pub const CRATE_HIR_ID: HirId = HirId { owner: CRATE_DEF_ID, local_id: ItemLocalId::from_u32(0) };
+pub const CRATE_HIR_ID: HirId =
+ HirId { owner: OwnerId { def_id: CRATE_DEF_ID }, local_id: ItemLocalId::from_u32(0) };
+
+pub const CRATE_OWNER_ID: OwnerId = OwnerId { def_id: CRATE_DEF_ID };
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 8f5f314ec..be77e6fd3 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -847,20 +847,28 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>(
) {
match *predicate {
WherePredicate::BoundPredicate(WhereBoundPredicate {
+ hir_id,
ref bounded_ty,
bounds,
bound_generic_params,
- ..
+ origin: _,
+ span: _,
}) => {
+ visitor.visit_id(hir_id);
visitor.visit_ty(bounded_ty);
walk_list!(visitor, visit_param_bound, bounds);
walk_list!(visitor, visit_generic_param, bound_generic_params);
}
- WherePredicate::RegionPredicate(WhereRegionPredicate { ref lifetime, bounds, .. }) => {
+ WherePredicate::RegionPredicate(WhereRegionPredicate {
+ ref lifetime,
+ bounds,
+ span: _,
+ in_where_clause: _,
+ }) => {
visitor.visit_lifetime(lifetime);
walk_list!(visitor, visit_param_bound, bounds);
}
- WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, .. }) => {
+ WherePredicate::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty, span: _ }) => {
visitor.visit_ty(lhs_ty);
visitor.visit_ty(rhs_ty);
}
@@ -904,7 +912,7 @@ pub fn walk_fn<'v, V: Visitor<'v>>(
pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
- let TraitItem { ident, generics, ref defaultness, ref kind, span, def_id: _ } = *trait_item;
+ 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);
@@ -944,7 +952,7 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem<'v>) {
// N.B., deliberately force a compilation error if/when new fields are added.
let ImplItem {
- def_id: _,
+ owner_id: _,
ident,
ref generics,
ref kind,
@@ -971,7 +979,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
impl_item.hir_id(),
);
}
- ImplItemKind::TyAlias(ref ty) => {
+ ImplItemKind::Type(ref ty) => {
visitor.visit_id(impl_item.hir_id());
visitor.visit_ty(ty);
}
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 946da9265..1c4aa420c 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -4,8 +4,7 @@
#![feature(associated_type_defaults)]
#![feature(closure_track_caller)]
-#![feature(const_btree_new)]
-#![cfg_attr(bootstrap, feature(let_else))]
+#![feature(const_btree_len)]
#![feature(once_cell)]
#![feature(min_specialization)]
#![feature(never_type)]
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 5b9c42686..23423e8f3 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -20,7 +20,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for HirId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) {
- let def_path_hash = self.owner.to_stable_hash_key(hcx);
+ let def_path_hash = self.owner.def_id.to_stable_hash_key(hcx);
(def_path_hash, self.local_id)
}
}
@@ -49,7 +49,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
- self.def_id.to_stable_hash_key(hcx)
+ self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@@ -58,7 +58,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for TraitItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
- self.def_id.to_stable_hash_key(hcx)
+ self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@@ -67,7 +67,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ImplItemId {
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
- self.def_id.to_stable_hash_key(hcx)
+ self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
@@ -76,7 +76,7 @@ impl<HirCtx: crate::HashStableContext> ToStableHashKey<HirCtx> for ForeignItemId
#[inline]
fn to_stable_hash_key(&self, hcx: &HirCtx) -> DefPathHash {
- self.def_id.to_stable_hash_key(hcx)
+ self.owner_id.def_id.to_stable_hash_key(hcx)
}
}
diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index cae29c1d3..0761d8cdb 100644
--- a/compiler/rustc_typeck/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -1,5 +1,5 @@
[package]
-name = "rustc_typeck"
+name = "rustc_hir_analysis"
version = "0.0.0"
edition = "2021"
@@ -26,7 +26,6 @@ rustc_span = { path = "../rustc_span" }
rustc_index = { path = "../rustc_index" }
rustc_infer = { path = "../rustc_infer" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_ty_utils = { path = "../rustc_ty_utils" }
rustc_lint = { path = "../rustc_lint" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_type_ir = { path = "../rustc_type_ir" }
diff --git a/compiler/rustc_typeck/README.md b/compiler/rustc_hir_analysis/README.md
index b61dbd8c9..b61dbd8c9 100644
--- a/compiler/rustc_typeck/README.md
+++ b/compiler/rustc_hir_analysis/README.md
diff --git a/compiler/rustc_typeck/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index a9152bdc5..a9152bdc5 100644
--- a/compiler/rustc_typeck/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index afac75de2..47915b4bd 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -83,9 +83,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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.infer_ctxt().enter(|infcx| {
- infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id))
- });
+ let infcx = tcx.infer_ctxt().build();
+ let param_type =
+ infcx.resolve_numeric_literals_with_default(tcx.type_of(param.def_id));
if param_type.is_suggestable(tcx, false) {
err.span_suggestion(
tcx.def_span(src_def_id),
@@ -448,8 +448,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let infer_lifetimes =
(gen_pos != GenericArgPosition::Type || infer_args) && !gen_args.has_lifetime_params();
- if gen_pos != GenericArgPosition::Type && !gen_args.bindings.is_empty() {
- Self::prohibit_assoc_ty_binding(tcx, gen_args.bindings[0].span);
+ if gen_pos != GenericArgPosition::Type && let Some(b) = gen_args.bindings.first() {
+ Self::prohibit_assoc_ty_binding(tcx, b.span);
}
let explicit_late_bound =
@@ -649,9 +649,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].hir_id(),
multispan,
- |lint| {
- lint.build(msg).emit();
- },
+ msg,
+ |lint| lint,
);
}
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 4bf9562e2..38f195dab 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -26,7 +26,7 @@ use rustc_hir::intravisit::{walk_generics, Visitor as _};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
use rustc_middle::middle::stability::AllowUnstable;
-use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::DynKind;
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{
@@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
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::Span;
+use rustc_span::{sym, Span};
use rustc_target::spec::abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::astconv_object_safety_violations;
@@ -275,10 +275,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment.args(),
item_segment.infer_args,
None,
+ None,
);
- let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
-
- if let Some(b) = assoc_bindings.first() {
+ if let Some(b) = item_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
}
@@ -326,6 +325,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generic_args: &'a hir::GenericArgs<'_>,
infer_args: bool,
self_ty: Option<Ty<'tcx>>,
+ constness: Option<ty::BoundConstness>,
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
// If the type is parameterized by this region, then replace this
// region with the current anon region binding (in other words,
@@ -365,7 +365,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(&[]), arg_count);
+ return (tcx.intern_substs(parent_substs), arg_count);
}
struct SubstsForAstPathCtxt<'a, 'tcx> {
@@ -536,6 +536,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&mut substs_ctx,
);
+ if let Some(ty::BoundConstness::ConstIfConst) = constness
+ && generics.has_self && !tcx.has_attr(def_id, sym::const_trait)
+ {
+ tcx.sess.emit_err(crate::errors::ConstBoundForNonConstTrait { span } );
+ }
+
(substs, arg_count)
}
@@ -584,9 +590,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
assoc_bindings
}
- pub(crate) fn create_substs_for_associated_item(
+ pub fn create_substs_for_associated_item(
&self,
- tcx: TyCtxt<'tcx>,
span: Span,
item_def_id: DefId,
item_segment: &hir::PathSegment<'_>,
@@ -596,28 +601,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
span, item_def_id, item_segment
);
- if tcx.generics_of(item_def_id).params.is_empty() {
- self.prohibit_generics(slice::from_ref(item_segment).iter(), |_| {});
-
- parent_substs
- } else {
- let (args, _) = self.create_substs_for_ast_path(
- span,
- item_def_id,
- parent_substs,
- item_segment,
- item_segment.args(),
- item_segment.infer_args,
- None,
- );
-
- let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
- if let Some(b) = assoc_bindings.first() {
- Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
- }
+ let (args, _) = self.create_substs_for_ast_path(
+ span,
+ item_def_id,
+ parent_substs,
+ item_segment,
+ item_segment.args(),
+ item_segment.infer_args,
+ None,
+ None,
+ );
- args
+ if let Some(b) = item_segment.args().bindings.first() {
+ Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
}
+
+ args
}
/// Instantiates the path for the given trait reference, assuming that it's
@@ -630,6 +629,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&self,
trait_ref: &hir::TraitRef<'_>,
self_ty: Ty<'tcx>,
+ constness: ty::BoundConstness,
) -> ty::TraitRef<'tcx> {
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {});
@@ -639,6 +639,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_ref.path.segments.last().unwrap(),
true,
+ Some(constness),
)
}
@@ -665,6 +666,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
args,
infer_args,
Some(self_ty),
+ Some(constness),
);
let tcx = self.tcx();
@@ -690,6 +692,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
speculative,
&mut dup_bindings,
binding_span.unwrap_or(binding.span),
+ constness,
);
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
}
@@ -793,6 +796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &hir::PathSegment<'_>,
is_impl: bool,
+ constness: Option<ty::BoundConstness>,
) -> ty::TraitRef<'tcx> {
let (substs, _) = self.create_substs_for_ast_trait_ref(
span,
@@ -800,9 +804,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty,
trait_segment,
is_impl,
+ constness,
);
- let assoc_bindings = self.create_assoc_bindings_for_generic_args(trait_segment.args());
- if let Some(b) = assoc_bindings.first() {
+ if let Some(b) = trait_segment.args().bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
}
ty::TraitRef::new(trait_def_id, substs)
@@ -816,6 +820,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self_ty: Ty<'tcx>,
trait_segment: &'a hir::PathSegment<'a>,
is_impl: bool,
+ constness: Option<ty::BoundConstness>,
) -> (SubstsRef<'tcx>, GenericArgCountResult) {
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, is_impl);
@@ -827,6 +832,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_segment.args(),
trait_segment.infer_args,
Some(self_ty),
+ constness,
)
}
@@ -1038,6 +1044,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
speculative: bool,
dup_bindings: &mut FxHashMap<DefId, Span>,
path_span: Span,
+ constness: ty::BoundConstness,
) -> Result<(), ErrorGuaranteed> {
// Given something like `U: SomeTrait<T = X>`, we want to produce a
// predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -1127,17 +1134,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
};
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
- tcx,
path_span,
assoc_item.def_id,
&item_segment,
trait_ref.substs,
);
- debug!(
- "add_predicates_for_ast_type_binding: substs for trait-ref and assoc_item: {:?}",
- substs_trait_ref_and_assoc_item
- );
+ debug!(?substs_trait_ref_and_assoc_item);
ty::ProjectionTy {
item_def_id: assoc_item.def_id,
@@ -1158,8 +1161,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.collect_constrained_late_bound_regions(&projection_ty);
let late_bound_in_ty =
tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty));
- debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref);
- debug!("late_bound_in_ty = {:?}", late_bound_in_ty);
+ debug!(?late_bound_in_trait_ref);
+ debug!(?late_bound_in_ty);
// FIXME: point at the type params that don't have appropriate lifetimes:
// struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F);
@@ -1660,6 +1663,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Checks that `bounds` contains exactly one element and reports appropriate
// errors otherwise.
+ #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)]
fn one_bound_for_assoc_type<I>(
&self,
all_candidates: impl Fn() -> I,
@@ -1689,10 +1693,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return Err(reported);
}
};
- debug!("one_bound_for_assoc_type: bound = {:?}", bound);
+ debug!(?bound);
if let Some(bound2) = next_cand {
- debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
+ debug!(?bound2);
let is_equality = is_equality();
let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates);
@@ -1788,6 +1792,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// parameter or `Self`.
// NOTE: When this function starts resolving `Trait::AssocTy` successfully
// it should also start reporting the `BARE_TRAIT_OBJECTS` lint.
+ #[instrument(level = "debug", skip(self, hir_ref_id, span, qself, assoc_segment), fields(assoc_ident=?assoc_segment.ident), ret)]
pub fn associated_path_to_ty(
&self,
hir_ref_id: hir::HirId,
@@ -1805,8 +1810,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Err
};
- debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
-
// Check if we have an enum variant.
let mut variant_resolution = None;
if let ty::Adt(adt_def, _) = qself_ty.kind() {
@@ -1910,7 +1913,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
// Find the type of the associated item, and the trait where the associated
// item is declared.
let bound = match (&qself_ty.kind(), qself_res) {
- (_, Res::SelfTy { trait_: Some(_), alias_to: Some((impl_def_id, _)) }) => {
+ (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
// `Self` in an impl of a trait -- we have a concrete self type and a
// trait reference.
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
@@ -1929,8 +1932,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
(
&ty::Param(_),
- Res::SelfTy { trait_: Some(param_did), alias_to: None }
- | Res::Def(DefKind::TyParam, param_did),
+ Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
) => self.find_bound_for_assoc_item(param_did.expect_local(), assoc_ident, span)?,
_ => {
let reported = if variant_resolution.is_some() {
@@ -2023,30 +2025,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx.check_stability(item.def_id, Some(hir_ref_id), span, None);
if let Some(variant_def_id) = variant_resolution {
- tcx.struct_span_lint_hir(AMBIGUOUS_ASSOCIATED_ITEMS, hir_ref_id, span, |lint| {
- let mut err = lint.build("ambiguous associated item");
- let mut could_refer_to = |kind: DefKind, def_id, also| {
- let note_msg = format!(
- "`{}` could{} refer to the {} defined here",
- assoc_ident,
- also,
- kind.descr(def_id)
- );
- err.span_note(tcx.def_span(def_id), &note_msg);
- };
+ tcx.struct_span_lint_hir(
+ AMBIGUOUS_ASSOCIATED_ITEMS,
+ hir_ref_id,
+ span,
+ "ambiguous associated item",
+ |lint| {
+ let mut could_refer_to = |kind: DefKind, def_id, also| {
+ let note_msg = format!(
+ "`{}` could{} refer to the {} defined here",
+ assoc_ident,
+ also,
+ kind.descr(def_id)
+ );
+ lint.span_note(tcx.def_span(def_id), &note_msg);
+ };
- could_refer_to(DefKind::Variant, variant_def_id, "");
- could_refer_to(kind, item.def_id, " also");
+ could_refer_to(DefKind::Variant, variant_def_id, "");
+ could_refer_to(kind, item.def_id, " also");
- err.span_suggestion(
- span,
- "use fully-qualified syntax",
- format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
- Applicability::MachineApplicable,
- );
+ lint.span_suggestion(
+ span,
+ "use fully-qualified syntax",
+ format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident),
+ Applicability::MachineApplicable,
+ );
- err.emit();
- });
+ lint
+ },
+ );
}
Ok((ty, kind, item.def_id))
}
@@ -2058,6 +2065,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_def_id: DefId,
trait_segment: &hir::PathSegment<'_>,
item_segment: &hir::PathSegment<'_>,
+ constness: ty::BoundConstness,
) -> Ty<'tcx> {
let tcx = self.tcx();
@@ -2102,11 +2110,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
debug!("qpath_to_ty: self_type={:?}", self_ty);
- let trait_ref =
- self.ast_path_to_mono_trait_ref(span, trait_def_id, self_ty, trait_segment, false);
+ let trait_ref = self.ast_path_to_mono_trait_ref(
+ span,
+ trait_def_id,
+ self_ty,
+ trait_segment,
+ false,
+ Some(constness),
+ );
let item_substs = self.create_substs_for_associated_item(
- tcx,
span,
item_def_id,
item_segment,
@@ -2217,8 +2230,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
for segment in segments {
// Only emit the first error to avoid overloading the user with error messages.
- if let [binding, ..] = segment.args().bindings {
- Self::prohibit_assoc_ty_binding(self.tcx(), binding.span);
+ if let Some(b) = segment.args().bindings.first() {
+ Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
return true;
}
}
@@ -2426,7 +2439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
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))
}
- Res::SelfTy { trait_: Some(_), alias_to: None } => {
+ Res::SelfTyParam { .. } => {
// `Self` in trait or type alias.
assert_eq!(opt_self_ty, None);
self.prohibit_generics(path.segments.iter(), |err| {
@@ -2441,7 +2454,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
});
tcx.types.self_param
}
- Res::SelfTy { trait_: _, alias_to: Some((def_id, forbid_generic)) } => {
+ Res::SelfTyAlias { alias_to: def_id, forbid_generic, .. } => {
// `Self` in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
// Try to evaluate any array length constants.
@@ -2543,12 +2556,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
Res::Def(DefKind::AssocTy, def_id) => {
debug_assert!(path.segments.len() >= 2);
self.prohibit_generics(path.segments[..path.segments.len() - 2].iter(), |_| {});
+ // HACK: until we support `<Type as ~const Trait>`, assume all of them are.
+ let constness = if tcx.has_attr(tcx.parent(def_id), sym::const_trait) {
+ ty::BoundConstness::ConstIfConst
+ } else {
+ ty::BoundConstness::NotConst
+ };
self.qpath_to_ty(
span,
opt_self_ty,
def_id,
&path.segments[path.segments.len() - 2],
path.segments.last().unwrap(),
+ constness,
)
}
Res::PrimTy(prim_ty) => {
@@ -2641,7 +2661,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
hir::TyKind::OpaqueDef(item_id, lifetimes, in_trait) => {
let opaque_ty = tcx.hir().item(item_id);
- let def_id = item_id.def_id.to_def_id();
+ let def_id = item_id.owner_id.to_def_id();
match opaque_ty.kind {
hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
@@ -2667,6 +2687,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
&GenericArgs::none(),
true,
None,
+ None,
);
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
.subst(tcx, substs)
@@ -2775,6 +2796,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}
+ #[instrument(level = "debug", skip(self, hir_id, unsafety, abi, decl, generics, hir_ty), ret)]
pub fn ty_of_fn(
&self,
hir_id: hir::HirId,
@@ -2784,8 +2806,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
generics: Option<&hir::Generics<'_>>,
hir_ty: Option<&hir::Ty<'_>>,
) -> ty::PolyFnSig<'tcx> {
- debug!("ty_of_fn");
-
let tcx = self.tcx();
let bound_vars = tcx.late_bound_vars(hir_id);
debug!(?bound_vars);
@@ -2835,7 +2855,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(),
};
- debug!("ty_of_fn: output_ty={:?}", output_ty);
+ debug!(?output_ty);
let fn_ty = tcx.mk_fn_sig(input_tys.into_iter(), output_ty, decl.c_variadic, unsafety, abi);
let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars);
@@ -2912,8 +2932,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) =
hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") };
- let trait_ref =
- self.instantiate_mono_trait_ref(i.of_trait.as_ref()?, self.ast_ty_to_ty(i.self_ty));
+ let trait_ref = self.instantiate_mono_trait_ref(
+ i.of_trait.as_ref()?,
+ self.ast_ty_to_ty(i.self_ty),
+ ty::BoundConstness::NotConst,
+ );
let assoc = tcx.associated_items(trait_ref.def_id).find_by_name_and_kind(
tcx,
@@ -3009,7 +3032,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
/// Make sure that we are in the condition to suggest the blanket implementation.
fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) {
let tcx = self.tcx();
- let parent_id = tcx.hir().get_parent_item(self_ty.hir_id);
+ let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id;
if let hir::Node::Item(hir::Item {
kind:
hir::ItemKind::Impl(hir::Impl {
@@ -3060,24 +3083,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.map_or(false, |s| s.trim_end().ends_with('<'));
let is_global = poly_trait_ref.trait_ref.path.is_global();
- let sugg = Vec::from_iter([
- (
- self_ty.span.shrink_to_lo(),
- format!(
- "{}dyn {}",
- if needs_bracket { "<" } else { "" },
- if is_global { "(" } else { "" },
- ),
+
+ let mut sugg = Vec::from_iter([(
+ self_ty.span.shrink_to_lo(),
+ format!(
+ "{}dyn {}",
+ if needs_bracket { "<" } else { "" },
+ if is_global { "(" } else { "" },
),
- (
+ )]);
+
+ if is_global || needs_bracket {
+ sugg.push((
self_ty.span.shrink_to_hi(),
format!(
"{}{}",
if is_global { ")" } else { "" },
if needs_bracket { ">" } else { "" },
),
- ),
- ]);
+ ));
+ }
+
if self_ty.span.edition() >= Edition::Edition2021 {
let msg = "trait objects must include the `dyn` keyword";
let label = "add `dyn` keyword before this trait";
@@ -3093,15 +3119,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
BARE_TRAIT_OBJECTS,
self_ty.hir_id,
self_ty.span,
+ msg,
|lint| {
- let mut diag = lint.build(msg);
- diag.multipart_suggestion_verbose(
+ lint.multipart_suggestion_verbose(
"use `dyn`",
sugg,
Applicability::MachineApplicable,
);
- self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag);
- diag.emit();
+ self.maybe_lint_blanket_trait_impl(&self_ty, lint);
+ lint
},
);
}
diff --git a/compiler/rustc_typeck/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 6a28bb16a..6a28bb16a 100644
--- a/compiler/rustc_typeck/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index d6fa74c87..b70ac0205 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,8 +1,7 @@
use crate::check::intrinsicck::InlineAsmCtxt;
-use super::coercion::CoerceMany;
use super::compare_method::check_type_bounds;
-use super::compare_method::{compare_const_impl, compare_impl_method, compare_ty_impl};
+use super::compare_method::{compare_impl_method, compare_ty_impl};
use super::*;
use rustc_attr as attr;
use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan};
@@ -10,10 +9,8 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
-use rustc_hir::lang_items::LangItem;
use rustc_hir::{ItemKind, Node, PathSegment};
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{DefiningAnchor, RegionVariableOrigin, TyCtxtInferExt};
use rustc_infer::traits::Obligation;
use rustc_lint::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
@@ -29,13 +26,12 @@ use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVE
use rustc_span::symbol::sym;
use rustc_span::{self, Span};
use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCtxt};
-use rustc_ty_utils::representability::{self, Representability};
use std::ops::ControlFlow;
-pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
+pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
match tcx.sess.target.is_abi_supported(abi) {
Some(true) => (),
Some(false) => {
@@ -48,9 +44,13 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
.emit();
}
None => {
- tcx.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
- lint.build("use of calling convention not supported on this target").emit();
- });
+ tcx.struct_span_lint_hir(
+ UNSUPPORTED_CALLING_CONVENTIONS,
+ hir_id,
+ span,
+ "use of calling convention not supported on this target",
+ |lint| lint,
+ );
}
}
@@ -66,318 +66,10 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ab
}
}
-/// Helper used for fns and closures. Does the grungy work of checking a function
-/// body and returns the function context used for that purpose, since in the case of a fn item
-/// there is still a bit more to do.
-///
-/// * ...
-/// * inherited: other fields inherited from the enclosing fn (if any)
-#[instrument(skip(inherited, body), level = "debug")]
-pub(super) fn check_fn<'a, 'tcx>(
- inherited: &'a Inherited<'a, 'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- fn_sig: ty::FnSig<'tcx>,
- decl: &'tcx hir::FnDecl<'tcx>,
- fn_id: hir::HirId,
- body: &'tcx hir::Body<'tcx>,
- can_be_generator: Option<hir::Movability>,
- return_type_pre_known: bool,
-) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
- // Create the function context. This is either derived from scratch or,
- // in the case of closures, based on the outer context.
- let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
- fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
- fcx.return_type_pre_known = return_type_pre_known;
-
- let tcx = fcx.tcx;
- let hir = tcx.hir();
-
- let declared_ret_ty = fn_sig.output();
-
- let ret_ty =
- fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
- declared_ret_ty,
- body.value.hir_id,
- decl.output.span(),
- param_env,
- ));
- // If we replaced declared_ret_ty with infer vars, then we must be inferring
- // an opaque type, so set a flag so we can improve diagnostics.
- fcx.return_type_has_opaque = ret_ty != declared_ret_ty;
-
- fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
-
- let span = body.value.span;
-
- fn_maybe_err(tcx, span, fn_sig.abi);
-
- if fn_sig.abi == Abi::RustCall {
- let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
-
- let err = || {
- let item = match tcx.hir().get(fn_id) {
- Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
- Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::Fn(header, ..), ..
- }) => Some(header),
- Node::TraitItem(hir::TraitItem {
- kind: hir::TraitItemKind::Fn(header, ..),
- ..
- }) => Some(header),
- // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
- Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
- node => bug!("Item being checked wasn't a function/closure: {:?}", node),
- };
-
- if let Some(header) = item {
- tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
- }
- };
-
- if fn_sig.inputs().len() != expected_args {
- err()
- } else {
- // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
- // This will probably require wide-scale changes to support a TupleKind obligation
- // We can't resolve this without knowing the type of the param
- if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
- err()
- }
- }
- }
-
- if body.generator_kind.is_some() && can_be_generator.is_some() {
- let yield_ty = fcx
- .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
- fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
-
- // Resume type defaults to `()` if the generator has no argument.
- let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
-
- fcx.resume_yield_tys = Some((resume_ty, yield_ty));
- }
-
- GatherLocalsVisitor::new(&fcx).visit_body(body);
-
- // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
- // (as it's created inside the body itself, not passed in from outside).
- let maybe_va_list = if fn_sig.c_variadic {
- 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
- };
-
- // Add formal parameters.
- let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
- let inputs_fn = fn_sig.inputs().iter().copied();
- 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);
-
- // Check that argument is Sized.
- // The check for a non-trivial pattern is a hack to avoid duplicate warnings
- // for simple cases like `fn foo(x: Trait)`,
- // where we would error once on the parameter as a whole, and once on the binding `x`.
- if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
- fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
- }
-
- fcx.write_ty(param.hir_id, param_ty);
- }
-
- inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
-
- fcx.in_tail_expr = true;
- if let ty::Dynamic(..) = declared_ret_ty.kind() {
- // FIXME: We need to verify that the return type is `Sized` after the return expression has
- // been evaluated so that we have types available for all the nodes being returned, but that
- // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
- // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
- // while keeping the current ordering we will ignore the tail expression's type because we
- // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
- // because we will trigger "unreachable expression" lints unconditionally.
- // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
- // case that a newcomer might make, returning a bare trait, and in that case we populate
- // the tail expression's type so that the suggestion will be correct, but ignore all other
- // possible cases.
- fcx.check_expr(&body.value);
- fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
- } else {
- fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
- fcx.check_return_expr(&body.value, false);
- }
- fcx.in_tail_expr = false;
-
- // We insert the deferred_generator_interiors entry after visiting the body.
- // This ensures that all nested generators appear before the entry of this generator.
- // resolve_generator_interiors relies on this property.
- 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));
-
- let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
- Some(GeneratorTypes {
- resume_ty,
- yield_ty,
- interior,
- movability: can_be_generator.unwrap(),
- })
- } else {
- None
- };
-
- // Finalize the return check by taking the LUB of the return types
- // we saw and assigning it to the expected return type. This isn't
- // really expected to fail, since the coercions would have failed
- // earlier when trying to find a LUB.
- let coercion = fcx.ret_coercion.take().unwrap().into_inner();
- let mut actual_return_ty = coercion.complete(&fcx);
- debug!("actual_return_ty = {:?}", actual_return_ty);
- if let ty::Dynamic(..) = declared_ret_ty.kind() {
- // We have special-cased the case where the function is declared
- // `-> dyn Foo` and we don't actually relate it to the
- // `fcx.ret_coercion`, so just substitute a type variable.
- actual_return_ty =
- fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
- debug!("actual_return_ty replaced with {:?}", actual_return_ty);
- }
-
- // HACK(oli-obk, compiler-errors): We should be comparing this against
- // `declared_ret_ty`, but then anything uninferred would be inferred to
- // the opaque type itself. That again would cause writeback to assume
- // we have a recursive call site and do the sadly stabilized fallback to `()`.
- fcx.demand_suptype(span, ret_ty, actual_return_ty);
-
- // 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()
- {
- check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
- }
-
- // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
- if let Some(alloc_error_handler_did) = tcx.lang_items().oom()
- && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id()
- {
- check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty);
- }
-
- (fcx, gen_ty)
-}
-
-fn check_panic_info_fn(
- tcx: TyCtxt<'_>,
- fn_id: LocalDefId,
- fn_sig: ty::FnSig<'_>,
- decl: &hir::FnDecl<'_>,
- declared_ret_ty: Ty<'_>,
-) {
- let Some(panic_info_did) = tcx.lang_items().panic_info() else {
- tcx.sess.err("language item required, but not found: `panic_info`");
- return;
- };
-
- if *declared_ret_ty.kind() != ty::Never {
- tcx.sess.span_err(decl.output.span(), "return type should be `!`");
- }
-
- let inputs = fn_sig.inputs();
- if inputs.len() != 1 {
- tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
- return;
- }
-
- let arg_is_panic_info = match *inputs[0].kind() {
- ty::Ref(region, ty, mutbl) => match *ty.kind() {
- ty::Adt(ref adt, _) => {
- adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static()
- }
- _ => false,
- },
- _ => false,
- };
-
- if !arg_is_panic_info {
- tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
- }
-
- let DefKind::Fn = tcx.def_kind(fn_id) else {
- let span = tcx.def_span(fn_id);
- tcx.sess.span_err(span, "should be a function");
- return;
- };
-
- let generic_counts = tcx.generics_of(fn_id).own_counts();
- if generic_counts.types != 0 {
- let span = tcx.def_span(fn_id);
- tcx.sess.span_err(span, "should have no type parameters");
- }
- if generic_counts.consts != 0 {
- let span = tcx.def_span(fn_id);
- tcx.sess.span_err(span, "should have no const parameters");
- }
-}
-
-fn check_alloc_error_fn(
- tcx: TyCtxt<'_>,
- fn_id: LocalDefId,
- fn_sig: ty::FnSig<'_>,
- decl: &hir::FnDecl<'_>,
- declared_ret_ty: Ty<'_>,
-) {
- let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else {
- tcx.sess.err("language item required, but not found: `alloc_layout`");
- return;
- };
-
- if *declared_ret_ty.kind() != ty::Never {
- tcx.sess.span_err(decl.output.span(), "return type should be `!`");
- }
-
- let inputs = fn_sig.inputs();
- if inputs.len() != 1 {
- tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
- return;
- }
-
- let arg_is_alloc_layout = match inputs[0].kind() {
- ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
- _ => false,
- };
-
- if !arg_is_alloc_layout {
- tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
- }
-
- let DefKind::Fn = tcx.def_kind(fn_id) else {
- let span = tcx.def_span(fn_id);
- tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function");
- return;
- };
-
- let generic_counts = tcx.generics_of(fn_id).own_counts();
- if generic_counts.types != 0 {
- let span = tcx.def_span(fn_id);
- tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters");
- }
- if generic_counts.consts != 0 {
- let span = tcx.def_span(fn_id);
- tcx.sess
- .span_err(span, "`#[alloc_error_handler]` function should have no const parameters");
- }
-}
-
fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let def = tcx.adt_def(def_id);
let span = tcx.def_span(def_id);
def.destructor(tcx); // force the destructor to be evaluated
- check_representable(tcx, span, def_id);
if def.repr().simd() {
check_simd(tcx, span, def_id);
@@ -391,7 +83,6 @@ fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let def = tcx.adt_def(def_id);
let span = tcx.def_span(def_id);
def.destructor(tcx); // force the destructor to be evaluated
- check_representable(tcx, span, def_id);
check_transparent(tcx, span, def);
check_union_fields(tcx, span, def_id);
check_packed(tcx, span, def);
@@ -423,7 +114,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b
_ => {
// Fallback case: allow `ManuallyDrop` and things that are `Copy`.
ty.ty_adt_def().is_some_and(|adt_def| adt_def.is_manually_drop())
- || ty.is_copy_modulo_regions(tcx.at(span), param_env)
+ || ty.is_copy_modulo_regions(tcx, param_env)
}
}
}
@@ -510,10 +201,10 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
UNINHABITED_STATIC,
tcx.hir().local_def_id_to_hir_id(def_id),
span,
+ "static of uninhabited type",
|lint| {
- lint.build("static of uninhabited type")
+ lint
.note("uninhabited statics cannot be initialized, and any access would be an immediate error")
- .emit();
},
);
}
@@ -521,23 +212,33 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
/// projections that would result in "inheriting lifetimes".
-pub(super) fn check_opaque<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: LocalDefId,
- substs: SubstsRef<'tcx>,
- origin: &hir::OpaqueTyOrigin,
-) {
- let span = tcx.def_span(def_id);
- check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
- if tcx.type_of(def_id).references_error() {
+fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, 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");
+ return;
+ };
+
+ // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
+ // `async-std` (and `pub async fn` in general).
+ // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
+ // See https://github.com/rust-lang/rust/issues/75100
+ if tcx.sess.opts.actually_rustdoc {
+ return;
+ }
+
+ let substs = InternalSubsts::identity_for_item(tcx, item.owner_id.to_def_id());
+ let span = tcx.def_span(item.owner_id.def_id);
+
+ check_opaque_for_inheriting_lifetimes(tcx, item.owner_id.def_id, span);
+ if tcx.type_of(item.owner_id.def_id).references_error() {
return;
}
- if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
+ if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
return;
}
- check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
+ check_opaque_meets_bounds(tcx, item.owner_id.def_id, substs, span, &origin);
}
-
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
/// in "inheriting lifetimes".
#[instrument(level = "debug", skip(tcx, span))]
@@ -609,9 +310,12 @@ pub(super) fn check_opaque_for_inheriting_lifetimes<'tcx>(
fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
match arg.kind {
hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
- [PathSegment { res: Res::SelfTy { trait_: _, alias_to: impl_ref }, .. }] => {
- let impl_ty_name =
- impl_ref.map(|(def_id, _)| self.tcx.def_path_str(def_id));
+ [PathSegment { res: Res::SelfTyParam { .. }, .. }] => {
+ let impl_ty_name = None;
+ self.selftys.push((path.span, impl_ty_name));
+ }
+ [PathSegment { res: Res::SelfTyAlias { alias_to: def_id, .. }, .. }] => {
+ let impl_ty_name = Some(self.tcx.def_path_str(*def_id));
self.selftys.push((path.span, impl_ty_name));
}
_ => {}
@@ -701,10 +405,12 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
/// check those cases in the `param_env` of that function, which may have
/// bounds not on this opaque type:
///
-/// type X<T> = impl Clone
+/// ```ignore (illustrative)
+/// type X<T> = impl Clone;
/// fn f<T: Clone>(t: T) -> X<T> {
/// t
/// }
+/// ```
///
/// Without this check the above code is incorrectly accepted: we would ICE if
/// some tried, for example, to clone an `Option<X<&mut ()>>`.
@@ -716,8 +422,6 @@ fn check_opaque_meets_bounds<'tcx>(
span: Span,
origin: &hir::OpaqueTyOrigin,
) {
- let hidden_type = tcx.bound_type_of(def_id.to_def_id()).subst(tcx, substs);
-
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,
@@ -725,76 +429,88 @@ fn check_opaque_meets_bounds<'tcx>(
};
let param_env = tcx.param_env(defining_use_anchor);
- tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor)).enter(
- move |infcx| {
- let ocx = ObligationCtxt::new(&infcx);
- let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+ let infcx = tcx
+ .infer_ctxt()
+ .with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
+ .build();
+ let ocx = ObligationCtxt::new(&infcx);
+ let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+
+ // `ReErased` regions appear in the "parent_substs" of closures/generators.
+ // We're ignoring them here and replacing them with fresh region variables.
+ // See tests in ui/type-alias-impl-trait/closure_{parent_substs,wf_outlives}.rs.
+ //
+ // 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.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, hir_id);
- match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
- Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
- Err(ty_err) => {
- tcx.sess.delay_span_bug(
- span,
- &format!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
- );
- }
- }
+ match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_ty) {
+ Ok(infer_ok) => ocx.register_infer_ok_obligations(infer_ok),
+ Err(ty_err) => {
+ tcx.sess.delay_span_bug(
+ span,
+ &format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
+ );
+ }
+ }
- // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
- // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
- // hidden type is well formed even without those bounds.
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_type.into()))
- .to_predicate(tcx);
- ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
-
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- }
- match origin {
- // Checked when type checking the function containing them.
- hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
- // Can have different predicates to their defining use
- hir::OpaqueTyOrigin::TyAlias => {
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx.check_region_obligations_and_report_errors(
- defining_use_anchor,
- &outlives_environment,
- );
- }
- }
- // Clean up after ourselves
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- },
- );
+ // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
+ // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
+ // hidden type is well formed even without those bounds.
+ let predicate =
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())).to_predicate(tcx);
+ ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate));
+
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ }
+ match origin {
+ // Checked when type checking the function containing them.
+ hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
+ // Can have different predicates to their defining use
+ hir::OpaqueTyOrigin::TyAlias => {
+ let outlives_environment = OutlivesEnvironment::new(param_env);
+ infcx.check_region_obligations_and_report_errors(
+ defining_use_anchor,
+ &outlives_environment,
+ );
+ }
+ }
+ // Clean up after ourselves
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
}
fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
debug!(
"check_item_type(it.def_id={:?}, it.name={})",
- id.def_id,
- tcx.def_path_str(id.def_id.to_def_id())
+ id.owner_id,
+ tcx.def_path_str(id.owner_id.to_def_id())
);
let _indenter = indenter();
- match tcx.def_kind(id.def_id) {
+ match tcx.def_kind(id.owner_id) {
DefKind::Static(..) => {
- tcx.ensure().typeck(id.def_id);
- maybe_check_static_with_link_section(tcx, id.def_id);
- check_static_inhabited(tcx, id.def_id);
+ tcx.ensure().typeck(id.owner_id.def_id);
+ maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
+ check_static_inhabited(tcx, id.owner_id.def_id);
}
DefKind::Const => {
- tcx.ensure().typeck(id.def_id);
+ tcx.ensure().typeck(id.owner_id.def_id);
}
DefKind::Enum => {
let item = tcx.hir().item(id);
let hir::ItemKind::Enum(ref enum_definition, _) = item.kind else {
return;
};
- check_enum(tcx, &enum_definition.variants, item.def_id);
+ check_enum(tcx, &enum_definition.variants, item.owner_id.def_id);
}
DefKind::Fn => {} // entirely within check_item_body
DefKind::Impl => {
@@ -802,12 +518,12 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
let hir::ItemKind::Impl(ref impl_) = it.kind else {
return;
};
- debug!("ItemKind::Impl {} with id {:?}", it.ident, it.def_id);
- if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.def_id) {
+ debug!("ItemKind::Impl {} with id {:?}", it.ident, it.owner_id);
+ if let Some(impl_trait_ref) = tcx.impl_trait_ref(it.owner_id) {
check_impl_items_against_trait(
tcx,
it.span,
- it.def_id,
+ it.owner_id.def_id,
impl_trait_ref,
&impl_.items,
);
@@ -829,15 +545,15 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
fn_maybe_err(tcx, item.ident.span, abi);
}
hir::TraitItemKind::Type(.., Some(default)) => {
- let assoc_item = tcx.associated_item(item.def_id);
+ let assoc_item = tcx.associated_item(item.owner_id);
let trait_substs =
- InternalSubsts::identity_for_item(tcx, it.def_id.to_def_id());
+ InternalSubsts::identity_for_item(tcx, it.owner_id.to_def_id());
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
tcx,
assoc_item,
assoc_item,
default.span,
- ty::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs },
+ ty::TraitRef { def_id: it.owner_id.to_def_id(), substs: trait_substs },
);
}
_ => {}
@@ -845,28 +561,28 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
}
}
DefKind::Struct => {
- check_struct(tcx, id.def_id);
+ check_struct(tcx, id.owner_id.def_id);
}
DefKind::Union => {
- check_union(tcx, id.def_id);
+ check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
- let item = tcx.hir().item(id);
- let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
- return;
- };
- // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
- // `async-std` (and `pub async fn` in general).
- // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
- // See https://github.com/rust-lang/rust/issues/75100
- if !tcx.sess.opts.actually_rustdoc {
- let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
- check_opaque(tcx, item.def_id, substs, &origin);
+ check_opaque(tcx, id);
+ }
+ DefKind::ImplTraitPlaceholder => {
+ let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+ // Only check the validity of this opaque type if the function has a default body
+ if let hir::Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
+ ..
+ }) = tcx.hir().get_by_def_id(parent.expect_local())
+ {
+ check_opaque(tcx, id);
}
}
DefKind::TyAlias => {
- let pty_ty = tcx.type_of(id.def_id);
- let generics = tcx.generics_of(id.def_id);
+ let pty_ty = tcx.type_of(id.owner_id);
+ let generics = tcx.generics_of(id.owner_id);
check_type_params_are_used(tcx, &generics, pty_ty);
}
DefKind::ForeignMod => {
@@ -888,7 +604,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
}
} else {
for item in items {
- let def_id = item.id.def_id;
+ 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 {
@@ -943,7 +659,7 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
// an error would be reported if this fails.
- let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id());
+ let _ = traits::OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
}
pub(super) fn check_specialization_validity<'tcx>(
@@ -1030,7 +746,7 @@ 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.def_id);
+ let ty_impl_item = tcx.associated_item(impl_item.id.owner_id);
let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
tcx.associated_item(trait_item_id)
} else {
@@ -1041,14 +757,10 @@ fn check_impl_items_against_trait<'tcx>(
let impl_item_full = tcx.hir().impl_item(impl_item.id);
match impl_item_full.kind {
hir::ImplItemKind::Const(..) => {
- // Find associated const definition.
- compare_const_impl(
- tcx,
- &ty_impl_item,
- impl_item.span,
- &ty_trait_item,
- impl_trait_ref,
- );
+ let _ = tcx.compare_assoc_const_impl_item_with_trait_item((
+ impl_item.id.owner_id.def_id,
+ 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);
@@ -1060,7 +772,7 @@ fn check_impl_items_against_trait<'tcx>(
opt_trait_span,
);
}
- hir::ImplItemKind::TyAlias(impl_ty) => {
+ hir::ImplItemKind::Type(impl_ty) => {
let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
compare_ty_impl(
tcx,
@@ -1148,27 +860,6 @@ fn check_impl_items_against_trait<'tcx>(
}
}
-/// Checks whether a type can be represented in memory. In particular, it
-/// identifies types that contain themselves without indirection through a
-/// pointer, which would mean their size is unbounded.
-pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bool {
- let rty = tcx.type_of(item_def_id);
-
- // Check that it is possible to represent this type. This call identifies
- // (1) types that contain themselves and (2) types that contain a different
- // recursive type. It is only necessary to throw an error on those that
- // contain themselves. For case 2, there must be an inner type that will be
- // caught by case 1.
- match representability::ty_is_representable(tcx, rty, sp, None) {
- Representability::SelfRecursive(spans) => {
- recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
- return false;
- }
- Representability::Representable | Representability::ContainsRecursive => (),
- }
- true
-}
-
pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
let t = tcx.type_of(def_id);
if let ty::Adt(def, substs) = t.kind()
@@ -1434,6 +1125,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()),
span,
+ "zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types",
|lint| {
let note = if non_exhaustive {
"is marked with `#[non_exhaustive]`"
@@ -1441,10 +1133,9 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtD
"contains private fields"
};
let field_ty = tcx.def_path_str_with_substs(def_id, substs);
- lint.build("zero-sized fields in repr(transparent) cannot contain external non-exhaustive types")
+ lint
.note(format!("this {descr} contains `{field_ty}`, which {note}, \
and makes it not a breaking change to become non-zero-sized in the future."))
- .emit();
},
)
}
@@ -1489,7 +1180,7 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
}
}
- if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant {
+ if tcx.adt_def(def_id).repr().int.is_none() {
let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
@@ -1506,7 +1197,6 @@ fn check_enum<'tcx>(tcx: TyCtxt<'tcx>, vs: &'tcx [hir::Variant<'tcx>], def_id: L
detect_discriminant_duplicate(tcx, def.discriminants(tcx).collect(), vs, sp);
- check_representable(tcx, sp, def_id);
check_transparent(tcx, sp, def);
}
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs
index 59d591acd..32f66b06f 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs
@@ -1,6 +1,6 @@
use super::potentially_plural_count;
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
-use hir::def_id::DefId;
+use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
use rustc_hir as hir;
@@ -12,14 +12,14 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
use rustc_infer::infer::{self, TyCtxtInferExt};
use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::util::ExplicitSelf;
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{
self, AssocItem, DefIdTree, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
use rustc_span::Span;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
@@ -215,224 +215,220 @@ fn compare_predicate_entailment<'tcx>(
);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
- tcx.infer_ctxt().enter(|ref infcx| {
- let ocx = ObligationCtxt::new(infcx);
+ let infcx = &tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(infcx);
- debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
+ debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds());
- let mut selcx = traits::SelectionContext::new(&infcx);
- let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
- for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
- let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
- let traits::Normalized { value: predicate, obligations } =
- traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
+ for (predicate, span) in iter::zip(impl_m_own_bounds.predicates, impl_m_own_bounds.spans) {
+ let normalize_cause = traits::ObligationCause::misc(span, impl_m_hir_id);
+ let traits::Normalized { value: predicate, obligations } =
+ traits::normalize(&mut selcx, param_env, normalize_cause, predicate);
- ocx.register_obligations(obligations);
- let cause = ObligationCause::new(
- span,
- impl_m_hir_id,
- ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_m.def_id.expect_local(),
- trait_item_def_id: trait_m.def_id,
- kind: impl_m.kind,
- },
- );
- ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
- }
-
- // We now need to check that the signature of the impl method is
- // compatible with that of the trait method. We do this by
- // checking that `impl_fty <: trait_fty`.
- //
- // FIXME. Unfortunately, this doesn't quite work right now because
- // associated type normalization is not integrated into subtype
- // checks. For the comparison to be valid, we need to
- // normalize the associated types in the impl/trait methods
- // first. However, because function types bind regions, just
- // calling `normalize_associated_types_in` would have no effect on
- // any associated types appearing in the fn arguments or return
- // type.
-
- // Compute placeholder form of impl and trait method tys.
- let tcx = infcx.tcx;
-
- let mut wf_tys = FxHashSet::default();
-
- let impl_sig = infcx.replace_bound_vars_with_fresh_vars(
- impl_m_span,
- infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id),
+ ocx.register_obligations(obligations);
+ let cause = ObligationCause::new(
+ span,
+ impl_m_hir_id,
+ ObligationCauseCode::CompareImplItemObligation {
+ impl_item_def_id: impl_m.def_id.expect_local(),
+ trait_item_def_id: trait_m.def_id,
+ kind: impl_m.kind,
+ },
);
+ ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+ }
- let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
- let impl_sig = ocx.normalize(norm_cause.clone(), param_env, impl_sig);
- let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
- debug!("compare_impl_method: impl_fty={:?}", impl_fty);
-
- let trait_sig = tcx.bound_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,
- // we have to do this before normalization, since the normalized ty may
- // not contain the input parameters. See issue #87748.
- wf_tys.extend(trait_sig.inputs_and_output.iter());
- let trait_sig = ocx.normalize(norm_cause, param_env, trait_sig);
- // We also have to add the normalized trait signature
- // as we don't normalize during implied bounds computation.
- wf_tys.extend(trait_sig.inputs_and_output.iter());
- let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
-
- debug!("compare_impl_method: trait_fty={:?}", trait_fty);
-
- // FIXME: We'd want to keep more accurate spans than "the method signature" when
- // processing the comparison between the trait and impl fn, but we sadly lose them
- // and point at the whole signature when a trait bound or specific input or output
- // type would be more appropriate. In other places we have a `Vec<Span>`
- // corresponding to their `Vec<Predicate>`, but we don't have that here.
- // Fixing this would improve the output of test `issue-83765.rs`.
- let mut result = infcx
- .at(&cause, param_env)
- .sup(trait_fty, impl_fty)
- .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
-
- // HACK(RPITIT): #101614. When we are trying to infer the hidden types for
- // RPITITs, we need to equate the output tys instead of just subtyping. If
- // we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
- // us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
- // fixed up to `ReEmpty`, and which is certainly not what we want.
- if trait_fty.has_infer_types() {
- result = result.and_then(|()| {
- infcx
- .at(&cause, param_env)
- .eq(trait_sig.output(), impl_sig.output())
- .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok))
- });
- }
+ // We now need to check that the signature of the impl method is
+ // compatible with that of the trait method. We do this by
+ // checking that `impl_fty <: trait_fty`.
+ //
+ // FIXME. Unfortunately, this doesn't quite work right now because
+ // associated type normalization is not integrated into subtype
+ // checks. For the comparison to be valid, we need to
+ // normalize the associated types in the impl/trait methods
+ // first. However, because function types bind regions, just
+ // calling `normalize_associated_types_in` would have no effect on
+ // any associated types appearing in the fn arguments or return
+ // type.
+
+ // Compute placeholder form of impl and trait method tys.
+ let tcx = infcx.tcx;
- if let Err(terr) = result {
- debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
+ let mut wf_tys = FxHashSet::default();
- let (impl_err_span, trait_err_span) =
- extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
+ let impl_sig = infcx.replace_bound_vars_with_fresh_vars(
+ impl_m_span,
+ infer::HigherRankedType,
+ tcx.fn_sig(impl_m.def_id),
+ );
- cause.span = impl_err_span;
+ let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id);
+ let impl_sig = ocx.normalize(norm_cause.clone(), param_env, impl_sig);
+ let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
+ debug!("compare_impl_method: impl_fty={:?}", impl_fty);
+
+ let trait_sig = tcx.bound_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,
+ // we have to do this before normalization, since the normalized ty may
+ // not contain the input parameters. See issue #87748.
+ wf_tys.extend(trait_sig.inputs_and_output.iter());
+ let trait_sig = ocx.normalize(norm_cause, param_env, trait_sig);
+ // We also have to add the normalized trait signature
+ // as we don't normalize during implied bounds computation.
+ wf_tys.extend(trait_sig.inputs_and_output.iter());
+ let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
+
+ debug!("compare_impl_method: trait_fty={:?}", trait_fty);
+
+ // FIXME: We'd want to keep more accurate spans than "the method signature" when
+ // processing the comparison between the trait and impl fn, but we sadly lose them
+ // and point at the whole signature when a trait bound or specific input or output
+ // type would be more appropriate. In other places we have a `Vec<Span>`
+ // corresponding to their `Vec<Predicate>`, but we don't have that here.
+ // Fixing this would improve the output of test `issue-83765.rs`.
+ let mut result = infcx
+ .at(&cause, param_env)
+ .sup(trait_fty, impl_fty)
+ .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok));
+
+ // HACK(RPITIT): #101614. When we are trying to infer the hidden types for
+ // RPITITs, we need to equate the output tys instead of just subtyping. If
+ // we just use `sup` above, we'll end up `&'static str <: _#1t`, which causes
+ // us to infer `_#1t = #'_#2r str`, where `'_#2r` is unconstrained, which gets
+ // fixed up to `ReEmpty`, and which is certainly not what we want.
+ if trait_fty.has_infer_types() {
+ result = result.and_then(|()| {
+ infcx
+ .at(&cause, param_env)
+ .eq(trait_sig.output(), impl_sig.output())
+ .map(|infer_ok| ocx.register_infer_ok_obligations(infer_ok))
+ });
+ }
- let mut diag = struct_span_err!(
- tcx.sess,
- cause.span(),
- E0053,
- "method `{}` has an incompatible type for trait",
- trait_m.name
- );
- match &terr {
- TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
- if trait_m.fn_has_self_parameter =>
- {
- let ty = trait_sig.inputs()[0];
- let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty())
- {
- ExplicitSelf::ByValue => "self".to_owned(),
- ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
- ExplicitSelf::ByReference(_, hir::Mutability::Mut) => {
- "&mut self".to_owned()
- }
- _ => format!("self: {ty}"),
- };
+ if let Err(terr) = result {
+ debug!("sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty);
- // 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 span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
- ImplItemKind::Fn(ref sig, body) => tcx
- .hir()
- .body_param_names(body)
- .zip(sig.decl.inputs.iter())
- .map(|(param, ty)| param.span.to(ty.span))
- .next()
- .unwrap_or(impl_err_span),
- _ => bug!("{:?} is not a method", impl_m),
- };
+ let (impl_err_span, trait_err_span) =
+ extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m);
+ cause.span = impl_err_span;
+
+ let mut diag = struct_span_err!(
+ tcx.sess,
+ cause.span(),
+ E0053,
+ "method `{}` has an incompatible type for trait",
+ trait_m.name
+ );
+ match &terr {
+ TypeError::ArgumentMutability(0) | TypeError::ArgumentSorts(_, 0)
+ if trait_m.fn_has_self_parameter =>
+ {
+ let ty = trait_sig.inputs()[0];
+ let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
+ ExplicitSelf::ByValue => "self".to_owned(),
+ ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
+ ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
+ _ => format!("self: {ty}"),
+ };
+
+ // When the `impl` receiver is an arbitrary self type, like `self: Box<Self>`, the
+ // span points only at the type `Box<Self`>, but we want to cover the whole
+ // argument pattern and type.
+ let span = match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
+ ImplItemKind::Fn(ref sig, body) => tcx
+ .hir()
+ .body_param_names(body)
+ .zip(sig.decl.inputs.iter())
+ .map(|(param, ty)| param.span.to(ty.span))
+ .next()
+ .unwrap_or(impl_err_span),
+ _ => bug!("{:?} is not a method", impl_m),
+ };
+
+ diag.span_suggestion(
+ span,
+ "change the self-receiver type to match the trait",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ }
+ TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
+ if trait_sig.inputs().len() == *i {
+ // Suggestion to change output type. We do not suggest in `async` functions
+ // to avoid complex logic or incorrect output.
+ match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
+ ImplItemKind::Fn(ref sig, _)
+ if sig.header.asyncness == hir::IsAsync::NotAsync =>
+ {
+ let msg = "change the output type to match the trait";
+ let ap = Applicability::MachineApplicable;
+ match sig.decl.output {
+ hir::FnRetTy::DefaultReturn(sp) => {
+ let sugg = format!("-> {} ", trait_sig.output());
+ diag.span_suggestion_verbose(sp, msg, sugg, ap);
+ }
+ hir::FnRetTy::Return(hir_ty) => {
+ let sugg = trait_sig.output();
+ diag.span_suggestion(hir_ty.span, msg, sugg, ap);
+ }
+ };
+ }
+ _ => {}
+ };
+ } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
diag.span_suggestion(
- span,
- "change the self-receiver type to match the trait",
- sugg,
+ impl_err_span,
+ "change the parameter type to match the trait",
+ trait_ty,
Applicability::MachineApplicable,
);
}
- TypeError::ArgumentMutability(i) | TypeError::ArgumentSorts(_, i) => {
- if trait_sig.inputs().len() == *i {
- // Suggestion to change output type. We do not suggest in `async` functions
- // to avoid complex logic or incorrect output.
- match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind {
- ImplItemKind::Fn(ref sig, _)
- if sig.header.asyncness == hir::IsAsync::NotAsync =>
- {
- let msg = "change the output type to match the trait";
- let ap = Applicability::MachineApplicable;
- match sig.decl.output {
- hir::FnRetTy::DefaultReturn(sp) => {
- let sugg = format!("-> {} ", trait_sig.output());
- diag.span_suggestion_verbose(sp, msg, sugg, ap);
- }
- hir::FnRetTy::Return(hir_ty) => {
- let sugg = trait_sig.output();
- diag.span_suggestion(hir_ty.span, msg, sugg, ap);
- }
- };
- }
- _ => {}
- };
- } else if let Some(trait_ty) = trait_sig.inputs().get(*i) {
- diag.span_suggestion(
- impl_err_span,
- "change the parameter type to match the trait",
- trait_ty,
- Applicability::MachineApplicable,
- );
- }
- }
- _ => {}
}
+ _ => {}
+ }
- infcx.note_type_err(
- &mut diag,
- &cause,
- trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
- Some(infer::ValuePairs::Terms(ExpectedFound {
- expected: trait_fty.into(),
- found: impl_fty.into(),
- })),
- terr,
- false,
- false,
- );
+ infcx.err_ctxt().note_type_err(
+ &mut diag,
+ &cause,
+ trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
+ Some(infer::ValuePairs::Terms(ExpectedFound {
+ expected: trait_fty.into(),
+ found: impl_fty.into(),
+ })),
+ terr,
+ false,
+ false,
+ );
- return Err(diag.emit());
- }
+ return Err(diag.emit());
+ }
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- let reported = infcx.report_fulfillment_errors(&errors, None, false);
- return Err(reported);
- }
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return Err(reported);
+ }
- // Finally, resolve all regions. This catches wily misuses of
- // lifetime parameters.
- let outlives_environment = OutlivesEnvironment::with_bounds(
- param_env,
- Some(infcx),
- infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
- );
- infcx.check_region_obligations_and_report_errors(
- impl_m.def_id.expect_local(),
- &outlives_environment,
- );
+ // Finally, resolve all regions. This catches wily misuses of
+ // lifetime parameters.
+ let outlives_environment = OutlivesEnvironment::with_bounds(
+ param_env,
+ Some(infcx),
+ infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+ );
+ infcx.check_region_obligations_and_report_errors(
+ impl_m.def_id.expect_local(),
+ &outlives_environment,
+ );
- Ok(())
- })
+ Ok(())
}
pub fn collect_trait_impl_trait_tys<'tcx>(
@@ -465,125 +461,173 @@ pub fn collect_trait_impl_trait_tys<'tcx>(
let trait_to_placeholder_substs =
impl_to_placeholder_substs.rebase_onto(tcx, impl_m.container_id(tcx), trait_to_impl_substs);
- tcx.infer_ctxt().enter(|ref infcx| {
- let ocx = ObligationCtxt::new(infcx);
+ let infcx = &tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(infcx);
- let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
- let impl_return_ty = ocx.normalize(
- norm_cause.clone(),
- param_env,
- infcx
- .replace_bound_vars_with_fresh_vars(
- return_span,
- infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id),
- )
- .output(),
- );
+ let norm_cause = ObligationCause::misc(return_span, impl_m_hir_id);
+ let impl_sig = ocx.normalize(
+ norm_cause.clone(),
+ param_env,
+ infcx.replace_bound_vars_with_fresh_vars(
+ return_span,
+ infer::HigherRankedType,
+ tcx.fn_sig(impl_m.def_id),
+ ),
+ );
+ let impl_return_ty = impl_sig.output();
- let mut collector =
- ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_id);
- let unnormalized_trait_return_ty = tcx
- .liberate_late_bound_regions(
- impl_m.def_id,
- tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
- )
- .output()
- .fold_with(&mut collector);
- let trait_return_ty =
- ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_return_ty);
+ let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_hir_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),
+ )
+ .fold_with(&mut collector);
+ let trait_sig = ocx.normalize(norm_cause.clone(), param_env, unnormalized_trait_sig);
+ let trait_return_ty = trait_sig.output();
- let wf_tys = FxHashSet::from_iter([unnormalized_trait_return_ty, trait_return_ty]);
+ let wf_tys = FxHashSet::from_iter(
+ unnormalized_trait_sig.inputs_and_output.iter().chain(trait_sig.inputs_and_output.iter()),
+ );
- match infcx.at(&cause, param_env).eq(trait_return_ty, impl_return_ty) {
- Ok(infer::InferOk { value: (), obligations }) => {
- ocx.register_obligations(obligations);
- }
- Err(terr) => {
- let mut diag = struct_span_err!(
- tcx.sess,
- cause.span(),
- E0053,
- "method `{}` has an incompatible return type for trait",
- trait_m.name
- );
- let hir = tcx.hir();
- infcx.note_type_err(
- &mut diag,
- &cause,
- hir.get_if_local(impl_m.def_id)
- .and_then(|node| node.fn_decl())
- .map(|decl| (decl.output.span(), "return type in trait".to_owned())),
- Some(infer::ValuePairs::Terms(ExpectedFound {
- expected: trait_return_ty.into(),
- found: impl_return_ty.into(),
- })),
- terr,
- false,
- false,
- );
- return Err(diag.emit());
- }
+ match infcx.at(&cause, param_env).eq(trait_return_ty, impl_return_ty) {
+ Ok(infer::InferOk { value: (), obligations }) => {
+ ocx.register_obligations(obligations);
}
+ Err(terr) => {
+ let mut diag = struct_span_err!(
+ tcx.sess,
+ cause.span(),
+ E0053,
+ "method `{}` has an incompatible return type for trait",
+ trait_m.name
+ );
+ let hir = tcx.hir();
+ infcx.err_ctxt().note_type_err(
+ &mut diag,
+ &cause,
+ hir.get_if_local(impl_m.def_id)
+ .and_then(|node| node.fn_decl())
+ .map(|decl| (decl.output.span(), "return type in trait".to_owned())),
+ Some(infer::ValuePairs::Terms(ExpectedFound {
+ expected: trait_return_ty.into(),
+ found: impl_return_ty.into(),
+ })),
+ terr,
+ false,
+ false,
+ );
+ return Err(diag.emit());
+ }
+ }
- // Check that all obligations are satisfied by the implementation's
- // RPITs.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- let reported = infcx.report_fulfillment_errors(&errors, None, false);
- return Err(reported);
+ // Unify the whole function signature. We need to do this to fully infer
+ // the lifetimes of the return type, but do this after unifying just the
+ // return types, since we want to avoid duplicating errors from
+ // `compare_predicate_entailment`.
+ match infcx
+ .at(&cause, param_env)
+ .eq(tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)), tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)))
+ {
+ Ok(infer::InferOk { value: (), obligations }) => {
+ ocx.register_obligations(obligations);
}
+ Err(terr) => {
+ let guar = tcx.sess.delay_span_bug(
+ return_span,
+ format!("could not unify `{trait_sig}` and `{impl_sig}`: {terr:?}"),
+ );
+ return Err(guar);
+ }
+ }
- // Finally, resolve all regions. This catches wily misuses of
- // lifetime parameters.
- let outlives_environment = OutlivesEnvironment::with_bounds(
- param_env,
- Some(infcx),
- infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
- );
- infcx.check_region_obligations_and_report_errors(
- impl_m.def_id.expect_local(),
- &outlives_environment,
- );
+ // Check that all obligations are satisfied by the implementation's
+ // RPITs.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return Err(reported);
+ }
- let mut collected_tys = FxHashMap::default();
- for (def_id, (ty, substs)) in collector.types {
- match infcx.fully_resolve(ty) {
- Ok(ty) => {
- // `ty` contains free regions that we created earlier while liberating the
- // trait fn signature. However, projection normalization expects `ty` to
- // contains `def_id`'s early-bound regions.
- let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
- debug!(?id_substs, ?substs);
- let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> = substs
- .iter()
- .enumerate()
- .map(|(index, arg)| (arg, id_substs[index]))
- .collect();
- debug!(?map);
-
- let ty = tcx.fold_regions(ty, |region, _| {
- if let ty::ReFree(_) = region.kind() {
- map[&region.into()].expect_region()
- } else {
- region
- }
- });
- debug!(%ty);
- collected_tys.insert(def_id, ty);
- }
- Err(err) => {
- tcx.sess.delay_span_bug(
- return_span,
- format!("could not fully resolve: {ty} => {err:?}"),
- );
- collected_tys.insert(def_id, tcx.ty_error());
- }
+ // Finally, resolve all regions. This catches wily misuses of
+ // lifetime parameters.
+ let outlives_environment = OutlivesEnvironment::with_bounds(
+ param_env,
+ Some(infcx),
+ infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+ );
+ infcx.check_region_obligations_and_report_errors(
+ impl_m.def_id.expect_local(),
+ &outlives_environment,
+ );
+
+ let mut collected_tys = FxHashMap::default();
+ for (def_id, (ty, substs)) in collector.types {
+ match infcx.fully_resolve(ty) {
+ Ok(ty) => {
+ // `ty` contains free regions that we created earlier while liberating the
+ // trait fn signature. However, projection normalization expects `ty` to
+ // contains `def_id`'s early-bound regions.
+ let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ debug!(?id_substs, ?substs);
+ let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> =
+ std::iter::zip(substs, id_substs).collect();
+ debug!(?map);
+
+ // NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
+ // region substs that are synthesized during AST lowering. These are substs
+ // that are appended to the parent substs (trait and trait method). However,
+ // we're trying to infer the unsubstituted type value of the RPITIT inside
+ // the *impl*, so we can later use the impl's method substs to normalize
+ // an RPITIT to a concrete type (`confirm_impl_trait_in_trait_candidate`).
+ //
+ // Due to the design of RPITITs, during AST lowering, we have no idea that
+ // an impl method corresponds to a trait method with RPITITs in it. Therefore,
+ // we don't have a list of early-bound region substs for the RPITIT in the impl.
+ // Since early region parameters are index-based, we can't just rebase these
+ // (trait method) early-bound region substs onto the impl, and there's no
+ // guarantee that the indices from the trait substs and impl substs line up.
+ // So to fix this, we subtract the number of trait substs and add the number of
+ // impl substs to *renumber* these early-bound regions to their corresponding
+ // indices in the impl's substitutions list.
+ //
+ // Also, we only need to account for a difference in trait and impl substs,
+ // since we previously enforce that the trait method and impl method have the
+ // same generics.
+ let num_trait_substs = trait_to_impl_substs.len();
+ let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
+ let ty = tcx.fold_regions(ty, |region, _| {
+ let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; };
+ 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;
+ };
+ tcx.mk_region(ty::ReEarlyBound(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);
+ }
+ Err(err) => {
+ tcx.sess.delay_span_bug(
+ return_span,
+ format!("could not fully resolve: {ty} => {err:?}"),
+ );
+ collected_tys.insert(def_id, tcx.ty_error());
}
}
+ }
- Ok(&*tcx.arena.alloc(collected_tys))
- })
+ Ok(&*tcx.arena.alloc(collected_tys))
}
struct ImplTraitInTraitCollector<'a, 'tcx> {
@@ -628,10 +672,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> {
});
self.types.insert(proj.item_def_id, (infer_ty, proj.substs));
// Recurse into bounds
- for pred in self.tcx().bound_explicit_item_bounds(proj.item_def_id).transpose_iter() {
- let pred_span = pred.0.1;
-
- let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx(), proj.substs);
+ for (pred, pred_span) in self.tcx().bound_explicit_item_bounds(proj.item_def_id).subst_iter_copied(self.tcx(), proj.substs) {
let pred = pred.fold_with(self);
let pred = self.ocx.normalize(
ObligationCause::misc(self.span, self.body_id),
@@ -712,8 +753,8 @@ fn check_region_bounds_on_impl_item<'tcx>(
}
#[instrument(level = "debug", skip(infcx))]
-fn extract_spans_for_error_reporting<'a, 'tcx>(
- infcx: &infer::InferCtxt<'a, 'tcx>,
+fn extract_spans_for_error_reporting<'tcx>(
+ infcx: &infer::InferCtxt<'tcx>,
terr: TypeError<'_>,
cause: &ObligationCause<'tcx>,
impl_m: &ty::AssocItem,
@@ -768,16 +809,15 @@ fn compare_self_type<'tcx>(
let self_arg_ty = tcx.fn_sig(method.def_id).input(0);
let param_env = ty::ParamEnv::reveal_all();
- tcx.infer_ctxt().enter(|infcx| {
- 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();
- match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
- ExplicitSelf::ByValue => "self".to_owned(),
- ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
- ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
- _ => format!("self: {self_arg_ty}"),
- }
- })
+ 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();
+ match ExplicitSelf::determine(self_arg_ty, can_eq_self) {
+ ExplicitSelf::ByValue => "self".to_owned(),
+ ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
+ ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
+ _ => format!("self: {self_arg_ty}"),
+ }
};
match (trait_m.fn_has_self_parameter, impl_m.fn_has_self_parameter) {
@@ -1300,114 +1340,114 @@ fn compare_generic_param_kinds<'tcx>(
Ok(())
}
-pub(crate) fn compare_const_impl<'tcx>(
+/// Use `tcx.compare_assoc_const_impl_item_with_trait_item` instead
+pub(crate) fn raw_compare_const_impl<'tcx>(
tcx: TyCtxt<'tcx>,
- impl_c: &ty::AssocItem,
- impl_c_span: Span,
- trait_c: &ty::AssocItem,
- impl_trait_ref: ty::TraitRef<'tcx>,
-) {
+ (impl_const_item_def, trait_const_item_def): (LocalDefId, DefId),
+) -> Result<(), ErrorGuaranteed> {
+ let impl_const_item = tcx.associated_item(impl_const_item_def);
+ let trait_const_item = tcx.associated_item(trait_const_item_def);
+ let impl_trait_ref = tcx.impl_trait_ref(impl_const_item.container_id(tcx)).unwrap();
debug!("compare_const_impl(impl_trait_ref={:?})", impl_trait_ref);
- tcx.infer_ctxt().enter(|infcx| {
- let param_env = tcx.param_env(impl_c.def_id);
- let ocx = ObligationCtxt::new(&infcx);
-
- // The below is for the most part highly similar to the procedure
- // for methods above. It is simpler in many respects, especially
- // because we shouldn't really have to deal with lifetimes or
- // predicates. In fact some of this should probably be put into
- // shared functions because of DRY violations...
- let trait_to_impl_substs = impl_trait_ref.substs;
-
- // Create a parameter environment that represents the implementation's
- // method.
- let impl_c_hir_id = tcx.hir().local_def_id_to_hir_id(impl_c.def_id.expect_local());
-
- // Compute placeholder form of impl and trait const tys.
- let impl_ty = tcx.type_of(impl_c.def_id);
- let trait_ty = tcx.bound_type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
- let mut cause = ObligationCause::new(
- impl_c_span,
- impl_c_hir_id,
- ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_c.def_id.expect_local(),
- trait_item_def_id: trait_c.def_id,
- kind: impl_c.kind,
- },
- );
+ let impl_c_span = tcx.def_span(impl_const_item_def.to_def_id());
- // There is no "body" here, so just pass dummy id.
- let impl_ty = ocx.normalize(cause.clone(), param_env, impl_ty);
+ let infcx = tcx.infer_ctxt().build();
+ let param_env = tcx.param_env(impl_const_item_def.to_def_id());
+ let ocx = ObligationCtxt::new(&infcx);
- debug!("compare_const_impl: impl_ty={:?}", impl_ty);
+ // The below is for the most part highly similar to the procedure
+ // for methods above. It is simpler in many respects, especially
+ // because we shouldn't really have to deal with lifetimes or
+ // predicates. In fact some of this should probably be put into
+ // shared functions because of DRY violations...
+ let trait_to_impl_substs = impl_trait_ref.substs;
- let trait_ty = ocx.normalize(cause.clone(), param_env, trait_ty);
+ // 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);
- debug!("compare_const_impl: trait_ty={:?}", trait_ty);
+ // 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 mut cause = ObligationCause::new(
+ impl_c_span,
+ impl_c_hir_id,
+ ObligationCauseCode::CompareImplItemObligation {
+ impl_item_def_id: impl_const_item_def,
+ trait_item_def_id: trait_const_item_def,
+ kind: impl_const_item.kind,
+ },
+ );
- let err = infcx
- .at(&cause, param_env)
- .sup(trait_ty, impl_ty)
- .map(|ok| ocx.register_infer_ok_obligations(ok));
+ // There is no "body" here, so just pass dummy id.
+ let impl_ty = ocx.normalize(cause.clone(), param_env, impl_ty);
- if let Err(terr) = err {
- debug!(
- "checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
- impl_ty, trait_ty
- );
+ debug!("compare_const_impl: impl_ty={:?}", impl_ty);
- // Locate the Span containing just the type of the offending impl
- match tcx.hir().expect_impl_item(impl_c.def_id.expect_local()).kind {
- ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
- _ => bug!("{:?} is not a impl const", impl_c),
- }
+ let trait_ty = ocx.normalize(cause.clone(), param_env, trait_ty);
- let mut diag = struct_span_err!(
- tcx.sess,
- cause.span,
- E0326,
- "implemented const `{}` has an incompatible type for trait",
- trait_c.name
- );
+ debug!("compare_const_impl: trait_ty={:?}", trait_ty);
- let trait_c_span = trait_c.def_id.as_local().map(|trait_c_def_id| {
- // Add a label to the Span containing just the type of the const
- match tcx.hir().expect_trait_item(trait_c_def_id).kind {
- TraitItemKind::Const(ref ty, _) => ty.span,
- _ => bug!("{:?} is not a trait const", trait_c),
- }
- });
+ let err = infcx
+ .at(&cause, param_env)
+ .sup(trait_ty, impl_ty)
+ .map(|ok| ocx.register_infer_ok_obligations(ok));
- infcx.note_type_err(
- &mut diag,
- &cause,
- trait_c_span.map(|span| (span, "type in trait".to_owned())),
- Some(infer::ValuePairs::Terms(ExpectedFound {
- expected: trait_ty.into(),
- found: impl_ty.into(),
- })),
- terr,
- false,
- false,
- );
- diag.emit();
- }
+ if let Err(terr) = err {
+ debug!(
+ "checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
+ impl_ty, trait_ty
+ );
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- return;
+ // Locate the Span containing just the type of the offending impl
+ match tcx.hir().expect_impl_item(impl_const_item_def).kind {
+ ImplItemKind::Const(ref ty, _) => cause.span = ty.span,
+ _ => bug!("{:?} is not a impl const", impl_const_item),
}
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx.check_region_obligations_and_report_errors(
- impl_c.def_id.expect_local(),
- &outlives_environment,
+ let mut diag = struct_span_err!(
+ tcx.sess,
+ cause.span,
+ E0326,
+ "implemented const `{}` has an incompatible type for trait",
+ trait_const_item.name
);
- });
+
+ 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
+ match tcx.hir().expect_trait_item(trait_c_def_id).kind {
+ TraitItemKind::Const(ref ty, _) => ty.span,
+ _ => bug!("{:?} is not a trait const", trait_const_item),
+ }
+ });
+
+ infcx.err_ctxt().note_type_err(
+ &mut diag,
+ &cause,
+ trait_c_span.map(|span| (span, "type in trait".to_owned())),
+ Some(infer::ValuePairs::Terms(ExpectedFound {
+ expected: trait_ty.into(),
+ found: impl_ty.into(),
+ })),
+ terr,
+ false,
+ false,
+ );
+ return Err(diag.emit());
+ };
+
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ return Err(infcx.err_ctxt().report_fulfillment_errors(&errors, None, false));
+ }
+
+ // FIXME return `ErrorReported` if region obligations error?
+ let outlives_environment = OutlivesEnvironment::new(param_env);
+ infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment);
+ Ok(())
}
pub(crate) fn compare_ty_impl<'tcx>(
@@ -1488,52 +1528,50 @@ fn compare_type_predicate_entailment<'tcx>(
hir::Constness::NotConst,
);
let param_env = traits::normalize_param_env_or_error(tcx, param_env, normalize_cause);
- tcx.infer_ctxt().enter(|infcx| {
- let ocx = ObligationCtxt::new(&infcx);
+ let infcx = tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(&infcx);
- debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
+ debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds());
- let mut selcx = traits::SelectionContext::new(&infcx);
-
- assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
- for (span, predicate) in
- std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
- {
- let cause = ObligationCause::misc(span, impl_ty_hir_id);
- let traits::Normalized { value: predicate, obligations } =
- traits::normalize(&mut selcx, param_env, cause, predicate);
-
- let cause = ObligationCause::new(
- span,
- impl_ty_hir_id,
- ObligationCauseCode::CompareImplItemObligation {
- impl_item_def_id: impl_ty.def_id.expect_local(),
- trait_item_def_id: trait_ty.def_id,
- kind: impl_ty.kind,
- },
- );
- ocx.register_obligations(obligations);
- ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
- }
+ let mut selcx = traits::SelectionContext::new(&infcx);
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- let reported = infcx.report_fulfillment_errors(&errors, None, false);
- return Err(reported);
- }
+ assert_eq!(impl_ty_own_bounds.predicates.len(), impl_ty_own_bounds.spans.len());
+ for (span, predicate) in std::iter::zip(impl_ty_own_bounds.spans, impl_ty_own_bounds.predicates)
+ {
+ let cause = ObligationCause::misc(span, impl_ty_hir_id);
+ let traits::Normalized { value: predicate, obligations } =
+ traits::normalize(&mut selcx, param_env, cause, predicate);
- // Finally, resolve all regions. This catches wily misuses of
- // lifetime parameters.
- let outlives_environment = OutlivesEnvironment::new(param_env);
- infcx.check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
+ let cause = ObligationCause::new(
+ span,
+ impl_ty_hir_id,
+ ObligationCauseCode::CompareImplItemObligation {
+ impl_item_def_id: impl_ty.def_id.expect_local(),
+ trait_item_def_id: trait_ty.def_id,
+ kind: impl_ty.kind,
+ },
);
+ ocx.register_obligations(obligations);
+ ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate));
+ }
+
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return Err(reported);
+ }
+
+ // Finally, resolve all regions. This catches wily misuses of
+ // lifetime parameters.
+ let outlives_environment = OutlivesEnvironment::new(param_env);
+ infcx.check_region_obligations_and_report_errors(
+ impl_ty.def_id.expect_local(),
+ &outlives_environment,
+ );
- Ok(())
- })
+ Ok(())
}
/// Validate that `ProjectionCandidate`s created for this associated type will
@@ -1693,94 +1731,89 @@ pub fn check_type_bounds<'tcx>(
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);
- tcx.infer_ctxt().enter(move |infcx| {
- let ocx = ObligationCtxt::new(&infcx);
+ 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 assumed_wf_types =
+ ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
- let mut selcx = traits::SelectionContext::new(&infcx);
- let normalize_cause = ObligationCause::new(
- impl_ty_span,
- impl_ty_hir_id,
- ObligationCauseCode::CheckAssociatedTypeBounds {
- impl_item_def_id: impl_ty.def_id.expect_local(),
- trait_item_def_id: trait_ty.def_id,
- },
- );
- let mk_cause = |span: Span| {
- let code = if span.is_dummy() {
- traits::ItemObligation(trait_ty.def_id)
- } else {
- traits::BindingObligation(trait_ty.def_id, span)
- };
- ObligationCause::new(impl_ty_span, impl_ty_hir_id, code)
+ let mut selcx = traits::SelectionContext::new(&infcx);
+ let normalize_cause = ObligationCause::new(
+ impl_ty_span,
+ impl_ty_hir_id,
+ ObligationCauseCode::CheckAssociatedTypeBounds {
+ impl_item_def_id: impl_ty.def_id.expect_local(),
+ trait_item_def_id: trait_ty.def_id,
+ },
+ );
+ let mk_cause = |span: Span| {
+ let code = if span.is_dummy() {
+ traits::ItemObligation(trait_ty.def_id)
+ } else {
+ traits::BindingObligation(trait_ty.def_id, span)
};
+ ObligationCause::new(impl_ty_span, impl_ty_hir_id, code)
+ };
- let obligations = tcx
- .bound_explicit_item_bounds(trait_ty.def_id)
- .transpose_iter()
- .map(|e| e.map_bound(|e| *e).transpose_tuple2())
- .map(|(bound, span)| {
- debug!(?bound);
- // this is where opaque type is found
- let concrete_ty_bound = bound.subst(tcx, rebased_substs);
- debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
-
- traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
- })
- .collect();
- debug!("check_type_bounds: item_bounds={:?}", obligations);
-
- for mut obligation in util::elaborate_obligations(tcx, obligations) {
- let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
- &mut selcx,
- normalize_param_env,
- normalize_cause.clone(),
- obligation.predicate,
- );
- debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
- obligation.predicate = normalized_predicate;
+ let obligations = tcx
+ .bound_explicit_item_bounds(trait_ty.def_id)
+ .subst_iter_copied(tcx, rebased_substs)
+ .map(|(concrete_ty_bound, span)| {
+ debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
+ traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
+ })
+ .collect();
+ debug!("check_type_bounds: item_bounds={:?}", obligations);
+
+ for mut obligation in util::elaborate_obligations(tcx, obligations) {
+ let traits::Normalized { value: normalized_predicate, obligations } = traits::normalize(
+ &mut selcx,
+ normalize_param_env,
+ normalize_cause.clone(),
+ obligation.predicate,
+ );
+ debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate);
+ obligation.predicate = normalized_predicate;
- ocx.register_obligations(obligations);
- ocx.register_obligation(obligation);
- }
- // Check that all obligations are satisfied by the implementation's
- // version.
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- let reported = infcx.report_fulfillment_errors(&errors, None, false);
- return Err(reported);
- }
+ ocx.register_obligations(obligations);
+ ocx.register_obligation(obligation);
+ }
+ // Check that all obligations are satisfied by the implementation's
+ // version.
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return Err(reported);
+ }
- // 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 outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
+ // 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 outlives_environment =
+ OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
- infcx.check_region_obligations_and_report_errors(
- impl_ty.def_id.expect_local(),
- &outlives_environment,
- );
+ infcx.check_region_obligations_and_report_errors(
+ impl_ty.def_id.expect_local(),
+ &outlives_environment,
+ );
- let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- for (key, value) in constraints {
- infcx
- .report_mismatched_types(
- &ObligationCause::misc(
- value.hidden_type.span,
- tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()),
- ),
- tcx.mk_opaque(key.def_id.to_def_id(), key.substs),
- value.hidden_type.ty,
- TypeError::Mismatch,
- )
- .emit();
- }
+ let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+ for (key, value) in constraints {
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(
+ &ObligationCause::misc(
+ value.hidden_type.span,
+ tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()),
+ ),
+ tcx.mk_opaque(key.def_id.to_def_id(), key.substs),
+ value.hidden_type.ty,
+ TypeError::Mismatch,
+ )
+ .emit();
+ }
- Ok(())
- })
+ Ok(())
}
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
diff --git a/compiler/rustc_typeck/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index ab143c059..a74016e22 100644
--- a/compiler/rustc_typeck/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -1,4 +1,4 @@
-// FIXME(@lcnr): Move this module out of `rustc_typeck`.
+// FIXME(@lcnr): Move this module out of `rustc_hir_analysis`.
//
// We don't do any drop checking during hir typeck.
use crate::hir::def_id::{DefId, LocalDefId};
@@ -184,13 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
let p = p.kind();
match (predicate.skip_binder(), p.skip_binder()) {
(ty::PredicateKind::Trait(a), ty::PredicateKind::Trait(b)) => {
- // Since struct predicates cannot have ~const, project the impl predicate
- // onto one that ignores the constness. This is equivalent to saying that
- // we match a `Trait` bound on the struct with a `Trait` or `~const Trait`
- // in the impl.
- let non_const_a =
- ty::TraitPredicate { constness: ty::BoundConstness::NotConst, ..a };
- relator.relate(predicate.rebind(non_const_a), p.rebind(b)).is_ok()
+ relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
}
(ty::PredicateKind::Projection(a), ty::PredicateKind::Projection(b)) => {
relator.relate(predicate.rebind(a), p.rebind(b)).is_ok()
@@ -198,7 +192,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
(
ty::PredicateKind::ConstEvaluatable(a),
ty::PredicateKind::ConstEvaluatable(b),
- ) => tcx.try_unify_abstract_consts(self_param_env.and((a, b))),
+ ) => relator.relate(predicate.rebind(a), predicate.rebind(b)).is_ok(),
(
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, lt_a)),
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_b, lt_b)),
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index c7425ff78..609095c9c 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -7,10 +7,10 @@ use crate::errors::{
};
use crate::require_same_types;
-use rustc_errors::struct_span_err;
+use hir::def_id::DefId;
+use rustc_errors::{struct_span_err, DiagnosticMessage};
use rustc_hir as hir;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::spec::abi::Abi;
@@ -26,7 +26,7 @@ fn equate_intrinsic_type<'tcx>(
) {
let (own_counts, span) = match &it.kind {
hir::ForeignItemKind::Fn(.., generics) => {
- let own_counts = tcx.generics_of(it.def_id.to_def_id()).own_counts();
+ let own_counts = tcx.generics_of(it.owner_id.to_def_id()).own_counts();
(own_counts, generics.span)
}
_ => {
@@ -57,13 +57,17 @@ fn equate_intrinsic_type<'tcx>(
{
let fty = tcx.mk_fn_ptr(sig);
let cause = ObligationCause::new(it.span, it.hir_id(), ObligationCauseCode::IntrinsicType);
- require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.def_id)), fty);
+ require_same_types(tcx, &cause, tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id)), fty);
}
}
/// Returns the unsafety of the given intrinsic.
-pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
- match intrinsic {
+pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir::Unsafety {
+ let has_safe_attr = match tcx.has_attr(intrinsic_id, sym::rustc_safe_intrinsic) {
+ true => hir::Unsafety::Normal,
+ false => hir::Unsafety::Unsafe,
+ };
+ let is_in_list = match tcx.item_name(intrinsic_id) {
// When adding a new intrinsic to this list,
// it's usually worth updating that intrinsic's documentation
// to note that it's safe to call, since
@@ -107,14 +111,26 @@ pub fn intrinsic_operation_unsafety(intrinsic: Symbol) -> hir::Unsafety {
| sym::variant_count
| sym::ptr_mask => hir::Unsafety::Normal,
_ => hir::Unsafety::Unsafe,
+ };
+
+ if has_safe_attr != is_in_list {
+ tcx.sess.struct_span_err(
+ tcx.def_span(intrinsic_id),
+ DiagnosticMessage::Str(format!(
+ "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
+ tcx.item_name(intrinsic_id)
+ ))).emit();
}
+
+ is_in_list
}
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
- let intrinsic_name = tcx.item_name(it.def_id.to_def_id());
+ let intrinsic_id = it.owner_id.to_def_id();
+ let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
let bound_vars = tcx.mk_bound_variable_kinds(
@@ -161,7 +177,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
};
(n_tps, 0, inputs, output, hir::Unsafety::Unsafe)
} else {
- let unsafety = intrinsic_operation_unsafety(intrinsic_name);
+ let unsafety = intrinsic_operation_unsafety(tcx, intrinsic_id);
let (n_tps, inputs, output) = match intrinsic_name {
sym::abort => (0, Vec::new(), tcx.types.never),
sym::unreachable => (0, Vec::new(), tcx.types.never),
diff --git a/compiler/rustc_typeck/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index d8fe63dbf..17c4d0d48 100644
--- a/compiler/rustc_typeck/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -1,104 +1,11 @@
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxHashSet;
-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, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy};
use rustc_session::lint;
-use rustc_span::{Span, Symbol, DUMMY_SP};
-use rustc_target::abi::{Pointer, VariantIdx};
+use rustc_span::{Symbol, DUMMY_SP};
use rustc_target::asm::{InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmType};
-use super::FnCtxt;
-
-/// If the type is `Option<T>`, it will return `T`, otherwise
-/// the type itself. Works on most `Option`-like types.
-fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
- let ty::Adt(def, substs) = *ty.kind() else { return ty };
-
- if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
- let data_idx;
-
- let one = VariantIdx::new(1);
- let zero = VariantIdx::new(0);
-
- if def.variant(zero).fields.is_empty() {
- data_idx = one;
- } else if def.variant(one).fields.is_empty() {
- data_idx = zero;
- } else {
- return ty;
- }
-
- if def.variant(data_idx).fields.len() == 1 {
- return def.variant(data_idx).fields[0].ty(tcx, substs);
- }
- }
-
- ty
-}
-
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
- pub fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
- let convert = |ty: Ty<'tcx>| {
- let ty = self.resolve_vars_if_possible(ty);
- let ty = self.tcx.normalize_erasing_regions(self.param_env, ty);
- (SizeSkeleton::compute(ty, self.tcx, self.param_env), ty)
- };
- let (sk_from, from) = convert(from);
- let (sk_to, to) = convert(to);
-
- // Check for same size using the skeletons.
- if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
- if sk_from.same_size(sk_to) {
- return;
- }
-
- // Special-case transmuting from `typeof(function)` and
- // `Option<typeof(function)>` to present a clearer error.
- let from = unpack_option_like(self.tcx, from);
- if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (from.kind(), sk_to) && size_to == Pointer.size(&self.tcx) {
- struct_span_err!(self.tcx.sess, span, E0591, "can't transmute zero-sized type")
- .note(&format!("source type: {from}"))
- .note(&format!("target type: {to}"))
- .help("cast with `as` to a pointer instead")
- .emit();
- return;
- }
- }
-
- // Try to display a sensible error with as much information as possible.
- let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
- Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()),
- Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
- Err(LayoutError::Unknown(bad)) => {
- if bad == ty {
- "this type does not have a fixed size".to_owned()
- } else {
- format!("size can vary because of {bad}")
- }
- }
- Err(err) => err.to_string(),
- };
-
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0512,
- "cannot transmute between types of different sizes, \
- or dependently-sized types"
- );
- if from == to {
- err.note(&format!("`{from}` does not have a fixed size"));
- } else {
- err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
- .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
- }
- err.emit();
- }
-}
-
pub struct InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -126,7 +33,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying.
- if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) {
+ if ty.is_sized(self.tcx, self.param_env) {
return true;
}
if let ty::Foreign(..) = ty.kind() {
@@ -146,7 +53,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
target_features: &FxHashSet<Symbol>,
) -> Option<InlineAsmType> {
let ty = (self.get_operand_ty)(expr);
- if ty.has_infer_types_or_consts() {
+ if ty.has_non_region_infer() {
bug!("inference variable in asm operand ty: {:?} {:?}", expr, ty);
}
let asm_ty_isize = match self.tcx.sess.target.pointer_width {
@@ -221,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)].
- if !ty.is_copy_modulo_regions(self.tcx.at(expr.span), self.param_env) {
+ if !ty.is_copy_modulo_regions(self.tcx, self.param_env) {
let msg = "arguments for inline assembly must be copyable";
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
err.note(&format!("`{ty}` does not implement the Copy trait"));
@@ -328,17 +235,16 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
lint::builtin::ASM_SUB_REGISTER,
expr.hir_id,
spans,
+ "formatting may not be suitable for sub-register argument",
|lint| {
- let msg = "formatting may not be suitable for sub-register argument";
- let mut err = lint.build(msg);
- err.span_label(expr.span, "for this argument");
- err.help(&format!(
+ lint.span_label(expr.span, "for this argument");
+ lint.help(&format!(
"use `{{{idx}:{suggested_modifier}}}` to have the register formatted as `{suggested_result}`",
));
- err.help(&format!(
+ lint.help(&format!(
"or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`",
));
- err.emit();
+ lint
},
);
}
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index cfae63e4a..2e7b10257 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -62,195 +62,49 @@ a type parameter).
*/
-pub mod _match;
-mod autoderef;
-mod callee;
-pub mod cast;
mod check;
-mod closure;
-pub mod coercion;
mod compare_method;
-pub mod demand;
-mod diverges;
pub mod dropck;
-mod expectation;
-mod expr;
-mod fallback;
-mod fn_ctxt;
-mod gather_locals;
-mod generator_interior;
-mod inherited;
pub mod intrinsic;
-mod intrinsicck;
-pub mod method;
-mod op;
-mod pat;
-mod place_op;
+pub mod intrinsicck;
mod region;
-pub mod rvalue_scopes;
-mod upvar;
pub mod wfcheck;
-pub mod writeback;
-use check::{check_abi, check_fn, check_mod_item_types};
-pub use diverges::Diverges;
-pub use expectation::Expectation;
-pub use fn_ctxt::*;
-pub use inherited::{Inherited, InheritedBuilder};
+pub use check::check_abi;
-use crate::astconv::AstConv;
-use crate::check::gather_locals::GatherLocalsVisitor;
+use check::check_mod_item_types;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::{
- pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, MultiSpan,
-};
+use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
-use rustc_hir::def::Res;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
-use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
use rustc_index::bit_set::BitSet;
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
-use rustc_session::config;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_session::parse::feature_err;
-use rustc_session::Session;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, BytePos, Span, Symbol};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits;
-use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
-use std::cell::RefCell;
use std::num::NonZeroU32;
use crate::require_c_abi_if_c_variadic;
use crate::util::common::indenter;
-use self::coercion::DynamicCoerceMany;
use self::compare_method::collect_trait_impl_trait_tys;
use self::region::region_scope_tree;
-pub use self::Expectation::*;
-
-#[macro_export]
-macro_rules! type_error_struct {
- ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
- let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
-
- if $typ.references_error() {
- err.downgrade_to_delayed_bug();
- }
-
- err
- })
-}
-
-/// The type of a local binding, including the revealed type for anon types.
-#[derive(Copy, Clone, Debug)]
-pub struct LocalTy<'tcx> {
- decl_ty: Ty<'tcx>,
- revealed_ty: Ty<'tcx>,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum Needs {
- MutPlace,
- None,
-}
-
-impl Needs {
- fn maybe_mut_place(m: hir::Mutability) -> Self {
- match m {
- hir::Mutability::Mut => Needs::MutPlace,
- hir::Mutability::Not => Needs::None,
- }
- }
-}
-
-#[derive(Copy, Clone)]
-pub struct UnsafetyState {
- pub def: hir::HirId,
- pub unsafety: hir::Unsafety,
- from_fn: bool,
-}
-
-impl UnsafetyState {
- pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
- UnsafetyState { def, unsafety, from_fn: true }
- }
-
- pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
- use hir::BlockCheckMode;
- match self.unsafety {
- // If this unsafe, then if the outer function was already marked as
- // unsafe we shouldn't attribute the unsafe'ness to the block. This
- // way the block can be warned about instead of ignoring this
- // extraneous block (functions are never warned about).
- hir::Unsafety::Unsafe if self.from_fn => self,
-
- unsafety => {
- let (unsafety, def) = match blk.rules {
- BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
- BlockCheckMode::DefaultBlock => (unsafety, self.def),
- };
- UnsafetyState { def, unsafety, from_fn: false }
- }
- }
- }
-}
-
-#[derive(Debug, Copy, Clone)]
-pub enum PlaceOp {
- Deref,
- Index,
-}
-
-pub struct BreakableCtxt<'tcx> {
- may_break: bool,
-
- // this is `null` for loops where break with a value is illegal,
- // such as `while`, `for`, and `while let`
- coerce: Option<DynamicCoerceMany<'tcx>>,
-}
-
-pub struct EnclosingBreakables<'tcx> {
- stack: Vec<BreakableCtxt<'tcx>>,
- by_id: HirIdMap<usize>,
-}
-
-impl<'tcx> EnclosingBreakables<'tcx> {
- fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
- self.opt_find_breakable(target_id).unwrap_or_else(|| {
- bug!("could not find enclosing breakable with id {}", target_id);
- })
- }
-
- fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
- match self.by_id.get(&target_id) {
- Some(ix) => Some(&mut self.stack[*ix]),
- None => None,
- }
- }
-}
pub fn provide(providers: &mut Providers) {
- method::provide(providers);
wfcheck::provide(providers);
*providers = Providers {
- typeck_item_bodies,
- typeck_const_arg,
- typeck,
- diagnostic_only_typeck,
- has_typeck_results,
adt_destructor,
- used_trait_imports,
check_mod_item_types,
region_scope_tree,
collect_trait_impl_trait_tys,
+ compare_assoc_const_impl_item_with_trait_item: compare_method::raw_compare_const_impl,
..*providers
};
}
@@ -259,255 +113,6 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
tcx.calculate_dtor(def_id, dropck::check_drop_impl)
}
-/// If this `DefId` is a "primary tables entry", returns
-/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
-///
-/// If this function returns `Some`, then `typeck_results(def_id)` will
-/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
-/// may not succeed. In some cases where this function returns `None`
-/// (notably closures), `typeck_results(def_id)` would wind up
-/// redirecting to the owning function.
-fn primary_body_of(
- tcx: TyCtxt<'_>,
- id: hir::HirId,
-) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
- match tcx.hir().get(id) {
- Node::Item(item) => match item.kind {
- hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
- Some((body, Some(ty), None))
- }
- hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
- _ => None,
- },
- Node::TraitItem(item) => match item.kind {
- hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
- hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
- Some((body, None, Some(sig)))
- }
- _ => None,
- },
- Node::ImplItem(item) => match item.kind {
- hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
- hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
- _ => None,
- },
- Node::AnonConst(constant) => Some((constant.body, None, None)),
- _ => None,
- }
-}
-
-fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
- // Closures' typeck results come from their outermost function,
- // as they are part of the same "inference environment".
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
- if typeck_root_def_id != def_id {
- return tcx.has_typeck_results(typeck_root_def_id);
- }
-
- if let Some(def_id) = def_id.as_local() {
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- primary_body_of(tcx, id).is_some()
- } else {
- false
- }
-}
-
-fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
- &*tcx.typeck(def_id).used_trait_imports
-}
-
-fn typeck_const_arg<'tcx>(
- tcx: TyCtxt<'tcx>,
- (did, param_did): (LocalDefId, DefId),
-) -> &ty::TypeckResults<'tcx> {
- let fallback = move || tcx.type_of(param_did);
- typeck_with_fallback(tcx, did, fallback)
-}
-
-fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
- 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());
- typeck_with_fallback(tcx, def_id, fallback)
- }
-}
-
-/// Used only to get `TypeckResults` for type inference during error recovery.
-/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
-fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
- let fallback = move || {
- let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
- tcx.ty_error_with_message(span, "diagnostic only typeck table used")
- };
- typeck_with_fallback(tcx, def_id, fallback)
-}
-
-fn typeck_with_fallback<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: LocalDefId,
- fallback: impl Fn() -> Ty<'tcx> + 'tcx,
-) -> &'tcx ty::TypeckResults<'tcx> {
- // Closures' typeck results come from their outermost function,
- // as they are part of the same "inference environment".
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
- if typeck_root_def_id != def_id {
- return tcx.typeck(typeck_root_def_id);
- }
-
- let id = tcx.hir().local_def_id_to_hir_id(def_id);
- let span = tcx.hir().span(id);
-
- // Figure out what primary body this item has.
- let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
- span_bug!(span, "can't type-check body of {:?}", def_id);
- });
- let body = tcx.hir().body(body_id);
-
- let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
- let param_env = tcx.param_env(def_id);
- let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig {
- let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() {
- let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
- <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
- } else {
- tcx.fn_sig(def_id)
- };
-
- check_abi(tcx, id, span, fn_sig.abi());
-
- // Compute the function signature from point of view of inside the fn.
- let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
- let fn_sig = inh.normalize_associated_types_in(
- body.value.span,
- body_id.hir_id,
- param_env,
- fn_sig,
- );
- check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
- } else {
- let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
- let expected_type = body_ty
- .and_then(|ty| match ty.kind {
- hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
- _ => None,
- })
- .unwrap_or_else(|| match tcx.hir().get(id) {
- Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
- Node::Expr(&hir::Expr {
- kind: hir::ExprKind::ConstBlock(ref anon_const),
- ..
- }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span,
- }),
- Node::Ty(&hir::Ty {
- kind: hir::TyKind::Typeof(ref anon_const), ..
- }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::TypeInference,
- span,
- }),
- Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
- | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
- let operand_ty = asm
- .operands
- .iter()
- .filter_map(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const }
- if anon_const.hir_id == id =>
- {
- // Inline assembly constants must be integers.
- Some(fcx.next_int_var())
- }
- hir::InlineAsmOperand::SymFn { anon_const }
- if anon_const.hir_id == id =>
- {
- Some(fcx.next_ty_var(TypeVariableOrigin {
- kind: TypeVariableOriginKind::MiscVariable,
- span,
- }))
- }
- _ => None,
- })
- .next();
- operand_ty.unwrap_or_else(fallback)
- }
- _ => fallback(),
- },
- _ => fallback(),
- });
-
- let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
- fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
-
- // Gather locals in statics (because of block expressions).
- GatherLocalsVisitor::new(&fcx).visit_body(body);
-
- fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
-
- fcx.write_ty(id, expected_type);
-
- fcx
- };
-
- let fallback_has_occurred = fcx.type_inference_fallback();
-
- // Even though coercion casts provide type hints, we check casts after fallback for
- // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
- fcx.check_casts();
- fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
-
- // Closure and generator analysis may run after fallback
- // because they don't constrain other type variables.
- fcx.closure_analyze(body);
- assert!(fcx.deferred_call_resolutions.borrow().is_empty());
- // 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_ty(span, ty);
- fcx.require_type_is_sized(ty, span, code);
- }
-
- fcx.select_all_obligations_or_error();
-
- if !fcx.infcx.is_tainted_by_errors() {
- fcx.check_transmutes();
- }
-
- fcx.check_asms();
-
- fcx.infcx.skip_region_resolution();
-
- fcx.resolve_type_vars_in_body(body)
- });
-
- // Consistency check our TypeckResults instance can hold all ItemLocalIds
- // it will need to hold.
- assert_eq!(typeck_results.hir_owner, id.owner);
-
- typeck_results
-}
-
-/// When `check_fn` is invoked on a generator (i.e., a body that
-/// includes yield), it returns back some information about the yield
-/// points.
-struct GeneratorTypes<'tcx> {
- /// Type of generator argument / values returned by `yield`.
- resume_ty: Ty<'tcx>,
-
- /// Type of value that is yielded.
- yield_ty: Ty<'tcx>,
-
- /// Types that are captured (see `GeneratorInterior` for more).
- interior: Ty<'tcx>,
-
- /// Indicates if the generator is movable or static (immovable).
- movability: hir::Movability,
-}
-
/// Given a `DefId` for an opaque type in return position, find its parent item's return
/// expressions.
fn get_owner_return_paths<'tcx>(
@@ -515,7 +120,7 @@ fn get_owner_return_paths<'tcx>(
def_id: LocalDefId,
) -> Option<(LocalDefId, ReturnsVisitor<'tcx>)> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let parent_id = tcx.hir().get_parent_item(hir_id);
+ let parent_id = tcx.hir().get_parent_item(hir_id).def_id;
tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| {
let body = tcx.hir().body(body_id);
let mut visitor = ReturnsVisitor::default();
@@ -524,9 +129,10 @@ fn get_owner_return_paths<'tcx>(
})
}
-// Forbid defining intrinsics in Rust code,
-// as they must always be defined by the compiler.
-fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
+/// Forbid defining intrinsics in Rust code,
+/// as they must always be defined by the compiler.
+// FIXME: Move this to a more appropriate place.
+pub fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi {
tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block");
}
@@ -820,6 +426,17 @@ fn fn_sig_suggestion<'tcx>(
format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
}
+pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
+ Some(match ty.kind() {
+ ty::Bool => "true",
+ ty::Char => "'a'",
+ ty::Int(_) | ty::Uint(_) => "42",
+ ty::Float(_) => "3.14159",
+ ty::Error(_) | ty::Never => return None,
+ _ => "value",
+ })
+}
+
/// 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.
@@ -841,7 +458,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 val = expr::ty_kind_suggestion(ty).unwrap_or("value");
+ let val = ty_kind_suggestion(ty).unwrap_or("value");
format!("const {}: {} = {};", assoc.name, ty, val)
}
}
@@ -892,76 +509,7 @@ fn bad_non_zero_sized_fields<'tcx>(
err.emit();
}
-fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
- struct_span_err!(
- tcx.sess,
- span,
- E0533,
- "expected unit struct, unit variant or constant, found {} `{}`",
- res.descr(),
- rustc_hir_pretty::qpath_to_string(qpath),
- )
- .emit();
-}
-
-/// Controls whether the arguments are tupled. This is used for the call
-/// operator.
-///
-/// Tupling means that all call-side arguments are packed into a tuple and
-/// passed as a single parameter. For example, if tupling is enabled, this
-/// function:
-/// ```
-/// fn f(x: (isize, isize)) {}
-/// ```
-/// Can be called as:
-/// ```ignore UNSOLVED (can this be done in user code?)
-/// # fn f(x: (isize, isize)) {}
-/// f(1, 2);
-/// ```
-/// Instead of:
-/// ```
-/// # fn f(x: (isize, isize)) {}
-/// f((1, 2));
-/// ```
-#[derive(Clone, Eq, PartialEq)]
-enum TupleArgumentsFlag {
- DontTupleArguments,
- TupleArguments,
-}
-
-fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
- tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
-}
-
-fn fatally_break_rust(sess: &Session) {
- let handler = sess.diagnostic();
- handler.span_bug_no_panic(
- MultiSpan::new(),
- "It looks like you're trying to break rust; would you like some ICE?",
- );
- handler.note_without_error("the compiler expectedly panicked. this is a feature.");
- handler.note_without_error(
- "we would appreciate a joke overview: \
- https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
- );
- handler.note_without_error(&format!(
- "rustc {} running on {}",
- option_env!("CFG_VERSION").unwrap_or("unknown_version"),
- config::host_triple(),
- ));
-}
-
-fn potentially_plural_count(count: usize, word: &str) -> String {
+// FIXME: Consider moving this method to a more fitting place.
+pub fn potentially_plural_count(count: usize, word: &str) -> String {
format!("{} {}{}", count, word, pluralize!(count))
}
-
-fn has_expected_num_generic_args<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_did: Option<DefId>,
- expected: usize,
-) -> bool {
- trait_did.map_or(true, |trait_did| {
- let generics = tcx.generics_of(trait_did);
- generics.count() == expected + if generics.has_self { 1 } else { 0 }
- })
-}
diff --git a/compiler/rustc_typeck/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index b89db79be..ff32329e4 100644
--- a/compiler/rustc_typeck/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -252,9 +252,13 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
) => {
// For shortcircuiting operators, mark the RHS as a terminating
// scope since it only executes conditionally.
- terminating(r.hir_id.local_id);
- }
+ // `Let` expressions (in a let-chain) shouldn't be terminating, as their temporaries
+ // should live beyond the immediate expression
+ if !matches!(r.kind, hir::ExprKind::Let(_)) {
+ terminating(r.hir_id.local_id);
+ }
+ }
hir::ExprKind::If(_, ref then, Some(ref otherwise)) => {
terminating(then.hir_id.local_id);
terminating(otherwise.hir_id.local_id);
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 27b3da8ab..a23575004 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -12,17 +12,17 @@ use rustc_infer::infer::outlives::obligations::TypeOutlives;
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
+use rustc_middle::ty::{GenericArgKind, InternalSubsts};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::autoderef::Autoderef;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
@@ -91,32 +91,31 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
{
let param_env = tcx.param_env(body_def_id);
let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
- tcx.infer_ctxt().enter(|ref infcx| {
- let ocx = ObligationCtxt::new(infcx);
+ let infcx = &tcx.infer_ctxt().build();
+ let ocx = ObligationCtxt::new(infcx);
- let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
+ let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
- let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
+ let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
- if !tcx.features().trivial_bounds {
- wfcx.check_false_global_bounds()
- }
- f(&mut wfcx);
- let errors = wfcx.select_all_or_error();
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- return;
- }
+ if !tcx.features().trivial_bounds {
+ wfcx.check_false_global_bounds()
+ }
+ f(&mut wfcx);
+ let errors = wfcx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return;
+ }
- let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
- let outlives_environment =
- OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+ let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+ let outlives_environment =
+ OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
- infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
- })
+ infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
}
-fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
let node = tcx.hir().expect_owner(def_id);
match node {
hir::OwnerNode::Crate(_) => {}
@@ -148,10 +147,10 @@ fn check_well_formed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
/// the types first.
#[instrument(skip(tcx), level = "debug")]
fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
- let def_id = item.def_id;
+ let def_id = item.owner_id.def_id;
debug!(
- ?item.def_id,
+ ?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
@@ -175,7 +174,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
// for `T`
hir::ItemKind::Impl(ref impl_) => {
let is_auto = tcx
- .impl_trait_ref(item.def_id)
+ .impl_trait_ref(def_id)
.map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id));
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
@@ -211,13 +210,13 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
}
hir::ItemKind::Fn(ref sig, ..) => {
- check_item_fn(tcx, item.def_id, item.ident, item.span, sig.decl);
+ check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
}
hir::ItemKind::Static(ty, ..) => {
- check_item_type(tcx, item.def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, false);
}
hir::ItemKind::Const(ty, ..) => {
- check_item_type(tcx, item.def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, false);
}
hir::ItemKind::Struct(ref struct_def, ref ast_generics) => {
check_type_defn(tcx, item, false, |wfcx| vec![wfcx.non_enum_variant(struct_def)]);
@@ -247,24 +246,24 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
- let def_id = item.def_id;
+ let def_id = item.owner_id.def_id;
debug!(
- ?item.def_id,
+ ?item.owner_id,
item.name = ? tcx.def_path_str(def_id.to_def_id())
);
match item.kind {
hir::ForeignItemKind::Fn(decl, ..) => {
- check_item_fn(tcx, item.def_id, item.ident, item.span, decl)
+ check_item_fn(tcx, def_id, item.ident, item.span, decl)
}
- hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, item.def_id, ty.span, true),
+ hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
hir::ForeignItemKind::Type => (),
}
}
fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
- let def_id = trait_item.def_id;
+ let def_id = trait_item.owner_id.def_id;
let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
@@ -272,11 +271,11 @@ fn check_trait_item(tcx: TyCtxt<'_>, trait_item: &hir::TraitItem<'_>) {
_ => (None, trait_item.span),
};
check_object_unsafe_self_trait_by_name(tcx, trait_item);
- check_associated_item(tcx, trait_item.def_id, span, method_sig);
+ 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.def_id.to_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() {
@@ -349,7 +348,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
loop {
let mut should_continue = false;
for gat_item in associated_items {
- let gat_def_id = gat_item.id.def_id;
+ let gat_def_id = gat_item.id.owner_id;
let gat_item = tcx.associated_item(gat_def_id);
// If this item is not an assoc ty, or has no substs, then it's not a GAT
if gat_item.kind != ty::AssocKind::Type {
@@ -366,7 +365,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// constrains the GAT with individually.
let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
for item in associated_items {
- let item_def_id = item.id.def_id;
+ let item_def_id = item.id.owner_id;
// Skip our own GAT, since it does not constrain itself at all.
if item_def_id == gat_def_id {
continue;
@@ -393,7 +392,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// We also assume that all of the function signature's parameter types
// are well formed.
&sig.inputs().iter().copied().collect(),
- gat_def_id,
+ gat_def_id.def_id,
gat_generics,
)
}
@@ -416,7 +415,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
.copied()
.collect::<Vec<_>>(),
&FxHashSet::default(),
- gat_def_id,
+ gat_def_id.def_id,
gat_generics,
)
}
@@ -456,7 +455,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
}
for (gat_def_id, required_bounds) in required_bounds_by_item {
- let gat_item_hir = tcx.hir().expect_trait_item(gat_def_id);
+ 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();
@@ -699,29 +698,32 @@ fn resolve_regions_with_wf_tys<'tcx>(
id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
wf_tys: &FxHashSet<Ty<'tcx>>,
- add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'a, 'tcx>, &'a RegionBoundPairs<'tcx>),
+ add_constraints: impl for<'a> FnOnce(&'a InferCtxt<'tcx>, &'a RegionBoundPairs<'tcx>),
) -> bool {
// Unfortunately, we have to use a new `InferCtxt` each call, because
// region constraints get added and solved there and we need to test each
// call individually.
- tcx.infer_ctxt().enter(|infcx| {
- let outlives_environment = OutlivesEnvironment::with_bounds(
- param_env,
- Some(&infcx),
- infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
- );
- let region_bound_pairs = outlives_environment.region_bound_pairs();
+ let infcx = tcx.infer_ctxt().build();
+ let outlives_environment = OutlivesEnvironment::with_bounds(
+ param_env,
+ Some(&infcx),
+ infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
+ );
+ let region_bound_pairs = outlives_environment.region_bound_pairs();
- add_constraints(&infcx, region_bound_pairs);
+ add_constraints(&infcx, region_bound_pairs);
- let errors = infcx.resolve_regions(&outlives_environment);
+ infcx.process_registered_region_obligations(
+ outlives_environment.region_bound_pairs(),
+ param_env,
+ );
+ let errors = infcx.resolve_regions(&outlives_environment);
- debug!(?errors, "errors");
+ debug!(?errors, "errors");
- // If we were able to prove that the type outlives the region without
- // an error, it must be because of the implied or explicit bounds...
- errors.is_empty()
- })
+ // If we were able to prove that the type outlives the region without
+ // an error, it must be because of the implied or explicit bounds...
+ errors.is_empty()
}
/// TypeVisitor that looks for uses of GATs like
@@ -786,9 +788,9 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
/// When this is done, suggest using `Self` instead.
fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) {
let (trait_name, trait_def_id) =
- match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id())) {
+ match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) {
hir::Node::Item(item) => match item.kind {
- hir::ItemKind::Trait(..) => (item.ident, item.def_id),
+ hir::ItemKind::Trait(..) => (item.ident, item.owner_id),
_ => return,
},
_ => return,
@@ -796,18 +798,18 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
let mut trait_should_be_self = vec![];
match &item.kind {
hir::TraitItemKind::Const(ty, _) | hir::TraitItemKind::Type(_, Some(ty))
- if could_be_self(trait_def_id, ty) =>
+ if could_be_self(trait_def_id.def_id, ty) =>
{
trait_should_be_self.push(ty.span)
}
hir::TraitItemKind::Fn(sig, _) => {
for ty in sig.decl.inputs {
- if could_be_self(trait_def_id, ty) {
+ if could_be_self(trait_def_id.def_id, ty) {
trait_should_be_self.push(ty.span);
}
}
match sig.decl.output {
- hir::FnRetTy::Return(ty) if could_be_self(trait_def_id, ty) => {
+ hir::FnRetTy::Return(ty) if could_be_self(trait_def_id.def_id, ty) => {
trait_should_be_self.push(ty.span);
}
_ => {}
@@ -836,16 +838,14 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
}
fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) {
- let def_id = impl_item.def_id;
-
let (method_sig, span) = match impl_item.kind {
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
- hir::ImplItemKind::TyAlias(ty) if ty.span != DUMMY_SP => (None, ty.span),
+ hir::ImplItemKind::Type(ty) if ty.span != DUMMY_SP => (None, ty.span),
_ => (None, impl_item.span),
};
- check_associated_item(tcx, def_id, span, method_sig);
+ check_associated_item(tcx, impl_item.owner_id.def_id, span, method_sig);
}
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
@@ -1045,9 +1045,11 @@ fn check_type_defn<'tcx, F>(
) where
F: FnMut(&WfCheckingCtxt<'_, 'tcx>) -> Vec<AdtVariant<'tcx>>,
{
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
+ let _ = tcx.representability(item.owner_id.def_id);
+
+ enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
let variants = lookup_fields(wfcx);
- let packed = tcx.adt_def(item.def_id).repr().packed();
+ let packed = tcx.adt_def(item.owner_id).repr().packed();
for variant in &variants {
// All field types must be well-formed.
@@ -1071,7 +1073,7 @@ fn check_type_defn<'tcx, F>(
// Just treat unresolved type expression as if it needs drop.
true
} else {
- ty.needs_drop(tcx, tcx.param_env(item.def_id))
+ ty.needs_drop(tcx, tcx.param_env(item.owner_id))
}
}
};
@@ -1103,8 +1105,6 @@ fn check_type_defn<'tcx, F>(
// Explicit `enum` discriminant values must const-evaluate successfully.
if let Some(discr_def_id) = variant.explicit_discr {
- let discr_substs = InternalSubsts::identity_for_item(tcx, discr_def_id.to_def_id());
-
let cause = traits::ObligationCause::new(
tcx.def_span(discr_def_id),
wfcx.body_id,
@@ -1113,28 +1113,28 @@ fn check_type_defn<'tcx, F>(
wfcx.register_obligation(traits::Obligation::new(
cause,
wfcx.param_env,
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ty::Unevaluated::new(
- ty::WithOptConstParam::unknown(discr_def_id.to_def_id()),
- discr_substs,
- )))
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
+ ty::Const::from_anon_const(tcx, discr_def_id),
+ ))
.to_predicate(tcx),
));
}
}
- check_where_clauses(wfcx, item.span, item.def_id);
+ check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
#[instrument(skip(tcx, item))]
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
- debug!(?item.def_id);
+ debug!(?item.owner_id);
- let trait_def = tcx.trait_def(item.def_id);
+ let def_id = item.owner_id.def_id;
+ let trait_def = tcx.trait_def(def_id);
if trait_def.is_marker
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)
{
- for associated_def_id in &*tcx.associated_item_def_ids(item.def_id) {
+ for associated_def_id in &*tcx.associated_item_def_ids(def_id) {
struct_span_err!(
tcx.sess,
tcx.def_span(*associated_def_id),
@@ -1145,8 +1145,8 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
}
}
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
- check_where_clauses(wfcx, item.span, item.def_id)
+ enter_wf_checking_ctxt(tcx, item.span, def_id, |wfcx| {
+ check_where_clauses(wfcx, item.span, def_id)
});
// Only check traits, don't check trait aliases
@@ -1240,13 +1240,13 @@ fn check_impl<'tcx>(
ast_trait_ref: &Option<hir::TraitRef<'_>>,
constness: hir::Constness,
) {
- enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
+ enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| {
match *ast_trait_ref {
Some(ref ast_trait_ref) => {
// `#[rustc_reservation_impl]` impls are not real impls and
// therefore don't need to be WF (the trait's `Self: Trait` predicate
// won't hold).
- let trait_ref = tcx.impl_trait_ref(item.def_id).unwrap();
+ let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap();
let trait_ref = wfcx.normalize(ast_trait_ref.path.span, None, trait_ref);
let trait_pred = ty::TraitPredicate {
trait_ref,
@@ -1268,21 +1268,21 @@ fn check_impl<'tcx>(
wfcx.register_obligations(obligations);
}
None => {
- let self_ty = tcx.type_of(item.def_id);
+ let self_ty = tcx.type_of(item.owner_id);
let self_ty = wfcx.normalize(
item.span,
- Some(WellFormedLoc::Ty(item.hir_id().expect_owner())),
+ Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
self_ty,
);
wfcx.register_wf_obligation(
ast_self_ty.span,
- Some(WellFormedLoc::Ty(item.hir_id().expect_owner())),
+ Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
self_ty.into(),
);
}
}
- check_where_clauses(wfcx, item.span, item.def_id);
+ check_where_clauses(wfcx, item.span, item.owner_id.def_id);
});
}
@@ -1427,9 +1427,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let substituted_pred = predicates.rebind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
- if substituted_pred.has_param_types_or_consts()
- || param_count.params.len() > 1
- || has_region
+ if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
{
None
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
@@ -1678,7 +1676,7 @@ fn receiver_is_valid<'tcx>(
// `self: Self` is always valid.
if can_eq_self(receiver_ty) {
if let Err(err) = wfcx.equate_types(&cause, wfcx.param_env, self_ty, receiver_ty) {
- infcx.report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
+ infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
}
return true;
}
@@ -1710,7 +1708,10 @@ fn receiver_is_valid<'tcx>(
if let Err(err) =
wfcx.equate_types(&cause, wfcx.param_env, self_ty, potential_self_ty)
{
- infcx.report_mismatched_types(&cause, self_ty, potential_self_ty, err).emit();
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(&cause, self_ty, potential_self_ty, err)
+ .emit();
}
break;
@@ -1777,14 +1778,14 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let ty = tcx.type_of(item.def_id);
+ let ty = tcx.type_of(item.owner_id);
if tcx.has_error_field(ty) {
return;
}
- let ty_predicates = tcx.predicates_of(item.def_id);
+ let ty_predicates = tcx.predicates_of(item.owner_id);
assert_eq!(ty_predicates.parent, None);
- let variances = tcx.variances_of(item.def_id);
+ let variances = tcx.variances_of(item.owner_id);
let mut constrained_parameters: FxHashSet<_> = variances
.iter()
@@ -1797,7 +1798,7 @@ fn check_variances_for_type_defn<'tcx>(
// Lazily calculated because it is only needed in case of an error.
let explicitly_bounded_params = LazyCell::new(|| {
- let icx = crate::collect::ItemCtxt::new(tcx, item.def_id.to_def_id());
+ let icx = crate::collect::ItemCtxt::new(tcx, item.owner_id.to_def_id());
hir_generics
.predicates
.iter()
@@ -1918,10 +1919,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalDefId) {
let items = tcx.hir_module_items(module);
- items.par_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_impl_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_trait_items(|item| tcx.ensure().check_well_formed(item.def_id));
- items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.def_id));
+ items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id));
+ items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id));
}
///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 1d23ed929..d0c317334 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -1,5 +1,6 @@
use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+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};
@@ -8,12 +9,12 @@ use rustc_session::lint;
use rustc_span::{Span, Symbol};
pub fn check_crate(tcx: TyCtxt<'_>) {
- let mut used_trait_imports: FxHashSet<LocalDefId> = FxHashSet::default();
+ let mut used_trait_imports: UnordSet<LocalDefId> = Default::default();
for item_def_id in tcx.hir().body_owners() {
let imports = tcx.used_trait_imports(item_def_id);
debug!("GatherVisitor: item_def_id={:?} with imports {:#?}", item_def_id, imports);
- used_trait_imports.extend(imports.iter());
+ used_trait_imports.extend(imports.items().copied());
}
for &id in tcx.maybe_unused_trait_imports(()) {
@@ -29,14 +30,18 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
continue;
}
let hir::ItemKind::Use(path, _) = item.kind else { unreachable!() };
- tcx.struct_span_lint_hir(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, |lint| {
- let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
- format!("unused import: `{}`", snippet)
- } else {
- "unused import".to_owned()
- };
- lint.build(&msg).emit();
- });
+ let msg = if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(path.span) {
+ format!("unused import: `{}`", snippet)
+ } else {
+ "unused import".to_owned()
+ };
+ tcx.struct_span_lint_hir(
+ lint::builtin::UNUSED_IMPORTS,
+ item.hir_id(),
+ path.span,
+ msg,
+ |lint| lint,
+ );
}
unused_crates_lint(tcx);
@@ -85,11 +90,11 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
let mut crates_to_lint = vec![];
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::ExternCrate) {
+ 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.def_id.to_def_id(),
+ def_id: item.owner_id.to_def_id(),
span: item.span,
orig_name,
warn_if_unused: !item.ident.as_str().starts_with('_'),
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
new file mode 100644
index 000000000..b6c91d425
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -0,0 +1,572 @@
+//! Check properties that are required by built-in traits and set
+//! up data structures required by type-checking/codegen.
+
+use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
+use rustc_errors::{struct_span_err, MultiSpan};
+use rustc_hir as hir;
+use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::lang_items::LangItem;
+use rustc_hir::ItemKind;
+use rustc_infer::infer;
+use rustc_infer::infer::outlives::env::OutlivesEnvironment;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
+use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitable};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
+use rustc_trait_selection::traits::predicate_for_trait_def;
+use rustc_trait_selection::traits::{self, ObligationCause};
+use std::collections::BTreeMap;
+
+pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
+ let lang_items = tcx.lang_items();
+ Checker { tcx, trait_def_id }
+ .check(lang_items.drop_trait(), visit_implementation_of_drop)
+ .check(lang_items.copy_trait(), visit_implementation_of_copy)
+ .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
+ .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
+}
+
+struct Checker<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ trait_def_id: DefId,
+}
+
+impl<'tcx> Checker<'tcx> {
+ fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
+ where
+ F: FnMut(TyCtxt<'tcx>, LocalDefId),
+ {
+ if Some(self.trait_def_id) == trait_def_id {
+ for &impl_def_id in self.tcx.hir().trait_impls(self.trait_def_id) {
+ f(self.tcx, impl_def_id);
+ }
+ }
+ self
+ }
+}
+
+fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
+ // Destructors only work on local ADT types.
+ match tcx.type_of(impl_did).kind() {
+ ty::Adt(def, _) if def.did().is_local() => return,
+ ty::Error(_) => return,
+ _ => {}
+ }
+
+ let sp = match tcx.hir().expect_item(impl_did).kind {
+ ItemKind::Impl(ref impl_) => impl_.self_ty.span,
+ _ => bug!("expected Drop impl item"),
+ };
+
+ tcx.sess.emit_err(DropImplOnWrongItem { span: sp });
+}
+
+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);
+ debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
+
+ let param_env = tcx.param_env(impl_did);
+ assert!(!self_type.has_escaping_bound_vars());
+
+ debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
+
+ let span = match tcx.hir().expect_item(impl_did).kind {
+ ItemKind::Impl(hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. }) => return,
+ ItemKind::Impl(impl_) => impl_.self_ty.span,
+ _ => bug!("expected Copy impl item"),
+ };
+
+ let cause = traits::ObligationCause::misc(span, impl_hir_id);
+ match can_type_implement_copy(tcx, param_env, self_type, cause) {
+ Ok(()) => {}
+ Err(CopyImplementationError::InfrigingFields(fields)) => {
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0204,
+ "the trait `Copy` may not be implemented for this type"
+ );
+
+ // We'll try to suggest constraining type parameters to fulfill the requirements of
+ // their `Copy` implementation.
+ let mut errors: BTreeMap<_, Vec<_>> = Default::default();
+ let mut bounds = vec![];
+
+ for (field, ty) in fields {
+ let field_span = tcx.def_span(field.did);
+ let field_ty_span = match tcx.hir().get_if_local(field.did) {
+ Some(hir::Node::Field(field_def)) => field_def.ty.span,
+ _ => field_span,
+ };
+ err.span_label(field_span, "this field does not implement `Copy`");
+ // Spin up a new FulfillmentContext, so we can get the _precise_ reason
+ // why this field does not implement Copy. This is useful because sometimes
+ // it is not immediately clear why Copy is not implemented for a field, since
+ // all we point at is the field itself.
+ let infcx = tcx.infer_ctxt().ignoring_regions().build();
+ for error in traits::fully_solve_bound(
+ &infcx,
+ traits::ObligationCause::dummy_with_span(field_ty_span),
+ param_env,
+ ty,
+ tcx.lang_items().copy_trait().unwrap(),
+ ) {
+ let error_predicate = error.obligation.predicate;
+ // Only note if it's not the root obligation, otherwise it's trivial and
+ // should be self-explanatory (i.e. a field literally doesn't implement Copy).
+
+ // FIXME: This error could be more descriptive, especially if the error_predicate
+ // contains a foreign type or if it's a deeply nested type...
+ if error_predicate != error.root_obligation.predicate {
+ errors
+ .entry((ty.to_string(), error_predicate.to_string()))
+ .or_default()
+ .push(error.obligation.cause.span);
+ }
+ if let ty::PredicateKind::Trait(ty::TraitPredicate {
+ trait_ref,
+ polarity: ty::ImplPolarity::Positive,
+ ..
+ }) = error_predicate.kind().skip_binder()
+ {
+ let ty = trait_ref.self_ty();
+ if let ty::Param(_) = ty.kind() {
+ bounds.push((
+ format!("{ty}"),
+ trait_ref.print_only_trait_path().to_string(),
+ Some(trait_ref.def_id),
+ ));
+ }
+ }
+ }
+ }
+ for ((ty, error_predicate), spans) in errors {
+ let span: MultiSpan = spans.into();
+ err.span_note(
+ span,
+ &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
+ );
+ }
+ suggest_constraining_type_params(
+ tcx,
+ tcx.hir().get_generics(impl_did).expect("impls always have generics"),
+ &mut err,
+ bounds.iter().map(|(param, constraint, def_id)| {
+ (param.as_str(), constraint.as_str(), *def_id)
+ }),
+ );
+ err.emit();
+ }
+ Err(CopyImplementationError::NotAnAdt) => {
+ tcx.sess.emit_err(CopyImplOnNonAdt { span });
+ }
+ Err(CopyImplementationError::HasDestructor) => {
+ tcx.sess.emit_err(CopyImplOnTypeWithDtor { span });
+ }
+ }
+}
+
+fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) {
+ debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
+
+ // Just compute this for the side-effects, in particular reporting
+ // errors; other parts of the code may demand it for the info of
+ // course.
+ let span = tcx.def_span(impl_did);
+ tcx.at(span).coerce_unsized_info(impl_did);
+}
+
+fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, 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 dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
+
+ let source = tcx.type_of(impl_did);
+ assert!(!source.has_escaping_bound_vars());
+ let target = {
+ let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+ assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
+
+ trait_ref.substs.type_at(1)
+ };
+
+ debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
+
+ let param_env = tcx.param_env(impl_did);
+
+ 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);
+
+ use rustc_type_ir::sty::TyKind::*;
+ match (source.kind(), target.kind()) {
+ (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
+ if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {}
+ (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
+ (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
+ if def_a.is_struct() && def_b.is_struct() =>
+ {
+ if def_a != def_b {
+ let source_path = tcx.def_path_str(def_a.did());
+ let target_path = tcx.def_path_str(def_b.did());
+
+ create_err(&format!(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with the same \
+ definition; expected `{}`, found `{}`",
+ source_path, target_path,
+ ))
+ .emit();
+
+ return;
+ }
+
+ if def_a.repr().c() || def_a.repr().packed() {
+ create_err(
+ "structs implementing `DispatchFromDyn` may not have \
+ `#[repr(packed)]` or `#[repr(C)]`",
+ )
+ .emit();
+ }
+
+ let fields = &def_a.non_enum_variant().fields;
+
+ let coerced_fields = fields
+ .iter()
+ .filter(|field| {
+ let ty_a = field.ty(tcx, substs_a);
+ let ty_b = field.ty(tcx, substs_b);
+
+ if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
+ if layout.is_zst() && layout.align.abi.bytes() == 1 {
+ // ignore ZST fields with alignment of 1 byte
+ return false;
+ }
+ }
+
+ if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
+ if ok.obligations.is_empty() {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for structs containing the field being coerced, \
+ ZST fields with 1 byte alignment, and nothing else",
+ )
+ .note(&format!(
+ "extra field `{}` of type `{}` is not allowed",
+ field.name, ty_a,
+ ))
+ .emit();
+
+ return false;
+ }
+ }
+
+ return true;
+ })
+ .collect::<Vec<_>>();
+
+ if coerced_fields.is_empty() {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with a single field \
+ being coerced, none found",
+ )
+ .emit();
+ } else if coerced_fields.len() > 1 {
+ create_err("implementing the `DispatchFromDyn` trait requires multiple coercions")
+ .note(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures with a single field \
+ being coerced",
+ )
+ .note(&format!(
+ "currently, {} fields need coercions: {}",
+ coerced_fields.len(),
+ coerced_fields
+ .iter()
+ .map(|field| {
+ format!(
+ "`{}` (`{}` to `{}`)",
+ field.name,
+ field.ty(tcx, substs_a),
+ field.ty(tcx, substs_b),
+ )
+ })
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))
+ .emit();
+ } else {
+ let errors = traits::fully_solve_obligations(
+ &infcx,
+ coerced_fields.into_iter().map(|field| {
+ predicate_for_trait_def(
+ tcx,
+ param_env,
+ cause.clone(),
+ dispatch_from_dyn_trait,
+ 0,
+ field.ty(tcx, substs_a),
+ &[field.ty(tcx, substs_b).into()],
+ )
+ }),
+ );
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ }
+
+ // Finally, resolve all regions.
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
+ }
+ }
+ _ => {
+ create_err(
+ "the trait `DispatchFromDyn` may only be implemented \
+ for a coercion between structures",
+ )
+ .emit();
+ }
+ }
+}
+
+pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
+ debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
+
+ // this provider should only get invoked for local def-ids
+ let impl_did = impl_did.expect_local();
+ let span = tcx.def_span(impl_did);
+
+ let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
+
+ let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
+ tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
+ });
+
+ let source = tcx.type_of(impl_did);
+ let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+ assert_eq!(trait_ref.def_id, coerce_unsized_trait);
+ let target = trait_ref.substs.type_at(1);
+ debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
+
+ let param_env = tcx.param_env(impl_did);
+ assert!(!source.has_escaping_bound_vars());
+
+ let err_info = CoerceUnsizedInfo { custom_kind: None };
+
+ 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 check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
+ mt_b: ty::TypeAndMut<'tcx>,
+ mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
+ if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(
+ &cause,
+ mk_ptr(mt_b.ty),
+ target,
+ ty::error::TypeError::Mutability,
+ )
+ .emit();
+ }
+ (mt_a.ty, mt_b.ty, unsize_trait, None)
+ };
+ let (source, target, trait_def_id, kind) = match (source.kind(), target.kind()) {
+ (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
+ infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
+ let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
+ let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
+ check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
+ }
+
+ (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
+ let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
+ check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
+ }
+
+ (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)),
+
+ (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
+ if def_a.is_struct() && def_b.is_struct() =>
+ {
+ if def_a != def_b {
+ let source_path = tcx.def_path_str(def_a.did());
+ let target_path = tcx.def_path_str(def_b.did());
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0377,
+ "the trait `CoerceUnsized` may only be implemented \
+ for a coercion between structures with the same \
+ definition; expected `{}`, found `{}`",
+ source_path,
+ target_path
+ )
+ .emit();
+ return err_info;
+ }
+
+ // 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>`,
+ // which acts like a pointer to `U`, but carries along some extra data of type `T`:
+ //
+ // struct Foo<T, U> {
+ // extra: T,
+ // ptr: *mut U,
+ // }
+ //
+ // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
+ // to `Foo<T, [i32]>`. That impl would look like:
+ //
+ // impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
+ //
+ // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
+ // when this coercion occurs, we would be changing the
+ // field `ptr` from a thin pointer of type `*mut [i32;
+ // 3]` to a fat pointer of type `*mut [i32]` (with
+ // extra data `3`). **The purpose of this check is to
+ // make sure that we know how to do this conversion.**
+ //
+ // To check if this impl is legal, we would walk down
+ // the fields of `Foo` and consider their types with
+ // both substitutes. We are looking to find that
+ // exactly one (non-phantom) field has changed its
+ // type, which we will expect to be the pointer that
+ // is becoming fat (we could probably generalize this
+ // to multiple thin pointers of the same type becoming
+ // fat, but we don't). In this case:
+ //
+ // - `extra` has type `T` before and type `T` after
+ // - `ptr` has type `*mut U` before and type `*mut V` after
+ //
+ // Since just one field changed, we would then check
+ // that `*mut U: CoerceUnsized<*mut V>` is implemented
+ // (in other words, that we know how to do this
+ // conversion). This will work out because `U:
+ // Unsize<V>`, and we have a builtin rule that `*mut
+ // U` can be coerced to `*mut V` if `U: Unsize<V>`.
+ let fields = &def_a.non_enum_variant().fields;
+ let diff_fields = fields
+ .iter()
+ .enumerate()
+ .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() {
+ // Ignore PhantomData fields
+ return None;
+ }
+
+ // Ignore fields that aren't changed; it may
+ // be that we could get away with subtyping or
+ // something more accepting, but we use
+ // equality because we want to be able to
+ // perform this check without computing
+ // variance where possible. (This is because
+ // we may have to evaluate constraint
+ // expressions in the course of execution.)
+ // See e.g., #41936.
+ if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
+ if ok.obligations.is_empty() {
+ return None;
+ }
+ }
+
+ // Collect up all fields that were significantly changed
+ // i.e., those that contain T in coerce_unsized T -> U
+ Some((i, a, b))
+ })
+ .collect::<Vec<_>>();
+
+ if diff_fields.is_empty() {
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0374,
+ "the trait `CoerceUnsized` may only be implemented \
+ for a coercion between structures with one field \
+ being coerced, none found"
+ )
+ .emit();
+ return err_info;
+ } else if diff_fields.len() > 1 {
+ let item = tcx.hir().expect_item(impl_did);
+ let span =
+ if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) = item.kind {
+ t.path.span
+ } else {
+ tcx.def_span(impl_did)
+ };
+
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0375,
+ "implementing the trait \
+ `CoerceUnsized` requires multiple \
+ coercions"
+ )
+ .note(
+ "`CoerceUnsized` may only be implemented for \
+ a coercion between structures with one field being coerced",
+ )
+ .note(&format!(
+ "currently, {} fields need coercions: {}",
+ diff_fields.len(),
+ diff_fields
+ .iter()
+ .map(|&(i, a, b)| { format!("`{}` (`{}` to `{}`)", fields[i].name, a, b) })
+ .collect::<Vec<_>>()
+ .join(", ")
+ ))
+ .span_label(span, "requires multiple coercions")
+ .emit();
+ return err_info;
+ }
+
+ let (i, a, b) = diff_fields[0];
+ let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
+ (a, b, coerce_unsized_trait, Some(kind))
+ }
+
+ _ => {
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0376,
+ "the trait `CoerceUnsized` may only be implemented \
+ for a coercion between structures"
+ )
+ .emit();
+ return err_info;
+ }
+ };
+
+ // Register an obligation for `A: Trait<B>`.
+ let cause = traits::ObligationCause::misc(span, impl_hir_id);
+ let predicate =
+ predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]);
+ let errors = traits::fully_solve_obligation(&infcx, predicate);
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ }
+
+ // Finally, resolve all regions.
+ let outlives_env = OutlivesEnvironment::new(param_env);
+ infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
+
+ CoerceUnsizedInfo { custom_kind: kind }
+}
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
index 52aad636f..2890c149b 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
@@ -58,7 +58,7 @@ const ADD_ATTR: &str =
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.def_id;
+ let impl_def_id = item.owner_id;
if let Some(def_id) = 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
@@ -89,7 +89,7 @@ impl<'tcx> InherentCollect<'tcx> {
for impl_item in items {
if !self
.tcx
- .has_attr(impl_item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl)
+ .has_attr(impl_item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
struct_span_err!(
self.tcx.sess,
@@ -105,7 +105,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
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);
+ self.impls_map.incoherent_impls.entry(simp).or_default().push(impl_def_id.def_id);
} else {
bug!("unexpected self type: {:?}", self_ty);
}
@@ -135,7 +135,7 @@ impl<'tcx> InherentCollect<'tcx> {
for item in items {
if !self
.tcx
- .has_attr(item.id.def_id.to_def_id(), sym::rustc_allow_incoherent_impl)
+ .has_attr(item.id.owner_id.to_def_id(), sym::rustc_allow_incoherent_impl)
{
struct_span_err!(
self.tcx.sess,
@@ -177,7 +177,7 @@ impl<'tcx> InherentCollect<'tcx> {
}
fn check_item(&mut self, id: hir::ItemId) {
- if !matches!(self.tcx.def_kind(id.def_id), DefKind::Impl) {
+ if !matches!(self.tcx.def_kind(id.owner_id), DefKind::Impl) {
return;
}
@@ -186,7 +186,7 @@ impl<'tcx> InherentCollect<'tcx> {
return;
};
- let self_ty = self.tcx.type_of(item.def_id);
+ let self_ty = self.tcx.type_of(item.owner_id);
match *self_ty.kind() {
ty::Adt(def, _) => {
self.check_def_id(item, self_ty, def.did());
@@ -220,7 +220,9 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Ref(..)
| ty::Never
| ty::FnPtr(_)
- | ty::Tuple(..) => self.check_primitive_impl(item.def_id, self_ty, items, ty.span),
+ | ty::Tuple(..) => {
+ self.check_primitive_impl(item.owner_id.def_id, self_ty, items, ty.span)
+ }
ty::Projection(..) | ty::Opaque(..) | ty::Param(_) => {
let mut err = struct_span_err!(
self.tcx.sess,
@@ -241,7 +243,7 @@ impl<'tcx> InherentCollect<'tcx> {
| ty::Bound(..)
| ty::Placeholder(_)
| ty::Infer(_) => {
- bug!("unexpected impl self type of impl: {:?} {:?}", item.def_id, self_ty);
+ bug!("unexpected impl self type of impl: {:?} {:?}", item.owner_id, self_ty);
}
ty::Error(_) => {}
}
diff --git a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
index 03e076bf5..972769eb1 100644
--- a/compiler/rustc_typeck/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -58,6 +58,37 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
== item2.ident(self.tcx).normalize_to_macros_2_0()
}
+ fn check_for_duplicate_items_in_impl(&self, impl_: DefId) {
+ let impl_items = self.tcx.associated_items(impl_);
+
+ let mut seen_items = FxHashMap::default();
+ for impl_item in impl_items.in_definition_order() {
+ let span = self.tcx.def_span(impl_item.def_id);
+ let ident = impl_item.ident(self.tcx);
+
+ let norm_ident = ident.normalize_to_macros_2_0();
+ match seen_items.entry(norm_ident) {
+ Entry::Occupied(entry) => {
+ let former = entry.get();
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0592,
+ "duplicate definitions with name `{}`",
+ ident,
+ );
+ err.span_label(span, format!("duplicate definitions for `{}`", ident));
+ err.span_label(*former, format!("other definition for `{}`", ident));
+
+ err.emit();
+ }
+ Entry::Vacant(entry) => {
+ entry.insert(span);
+ }
+ }
+ }
+ }
+
fn check_for_common_items_in_impls(
&self,
impl1: DefId,
@@ -117,29 +148,22 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
// inherent impls without warning.
SkipLeakCheck::Yes,
overlap_mode,
- |overlap| {
- self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
- false
- },
- || true,
- );
+ )
+ .map_or(true, |overlap| {
+ self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
+ false
+ });
}
fn check_item(&mut self, id: hir::ItemId) {
- let def_kind = self.tcx.def_kind(id.def_id);
+ let def_kind = self.tcx.def_kind(id.owner_id);
if !matches!(def_kind, DefKind::Enum | DefKind::Struct | DefKind::Trait | DefKind::Union) {
return;
}
- let impls = self.tcx.inherent_impls(id.def_id);
+ let impls = self.tcx.inherent_impls(id.owner_id);
- // If there is only one inherent impl block,
- // there is nothing to overlap check it with
- if impls.len() <= 1 {
- return;
- }
-
- let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id());
+ let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());
let impls_items = impls
.iter()
@@ -152,6 +176,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
const ALLOCATING_ALGO_THRESHOLD: usize = 500;
if impls.len() < ALLOCATING_ALGO_THRESHOLD {
for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() {
+ self.check_for_duplicate_items_in_impl(impl1_def_id);
+
for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] {
if self.impls_have_common_items(impl_items1, impl_items2) {
self.check_for_overlapping_inherent_impls(
@@ -290,6 +316,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
impl_blocks.sort_unstable();
for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() {
let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx];
+ self.check_for_duplicate_items_in_impl(impl1_def_id);
+
for &impl2_items_idx in impl_blocks[(i + 1)..].iter() {
let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx];
if self.impls_have_common_items(impl_items1, impl_items2) {
diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index ae9ebe590..ae9ebe590 100644
--- a/compiler/rustc_typeck/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
diff --git a/compiler/rustc_typeck/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 1608550aa..bb45c3823 100644
--- a/compiler/rustc_typeck/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -2,10 +2,9 @@
//! crate or pertains to a type defined in this crate.
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, DelayDm};
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IgnoreRegions;
@@ -43,7 +42,7 @@ fn do_orphan_check_impl<'tcx>(
) -> Result<(), ErrorGuaranteed> {
let trait_def_id = trait_ref.def_id;
- let item = tcx.hir().item(hir::ItemId { def_id });
+ let item = tcx.hir().expect_item(def_id);
let hir::ItemKind::Impl(ref impl_) = item.kind else {
bug!("{:?} is not an impl: {:?}", def_id, item);
};
@@ -102,7 +101,7 @@ fn do_orphan_check_impl<'tcx>(
span_bug!(sp, "opaque type not found, but `has_opaque_types` is set")
}
- match traits::orphan_check(tcx, item.def_id.to_def_id()) {
+ match traits::orphan_check(tcx, item.owner_id.to_def_id()) {
Ok(()) => {}
Err(err) => emit_orphan_check_error(
tcx,
@@ -229,12 +228,8 @@ fn emit_orphan_check_error<'tcx>(
"only traits defined in the current crate {msg}"
);
err.span_label(sp, "impl doesn't use only types from inside the current crate");
- for (ty, is_target_ty) in &tys {
- let mut ty = *ty;
- tcx.infer_ctxt().enter(|infcx| {
- // Remove the lifetimes unnecessary for this error.
- ty = infcx.freshen(ty);
- });
+ for &(mut ty, is_target_ty) in &tys {
+ ty = tcx.erase_regions(ty);
ty = match ty.kind() {
// Remove the type arguments from the output, as they are not relevant.
// You can think of this as the reverse of `resolve_vars_if_possible`.
@@ -264,7 +259,7 @@ fn emit_orphan_check_error<'tcx>(
};
let msg = format!("{} is not defined in the current crate{}", ty, postfix);
- if *is_target_ty {
+ if is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
err.span_label(self_ty_span, &msg);
} else {
@@ -417,30 +412,31 @@ fn lint_auto_trait_impl<'tcx>(
lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
tcx.hir().local_def_id_to_hir_id(impl_def_id),
tcx.def_span(impl_def_id),
- |err| {
- let item_span = tcx.def_span(self_type_did);
- let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
- let mut err = err.build(&format!(
+ DelayDm(|| {
+ format!(
"cross-crate traits with a default impl, like `{}`, \
should not be specialized",
tcx.def_path_str(trait_ref.def_id),
- ));
+ )
+ }),
+ |lint| {
+ let item_span = tcx.def_span(self_type_did);
+ let self_descr = tcx.def_kind(self_type_did).descr(self_type_did);
match arg {
ty::util::NotUniqueParam::DuplicateParam(arg) => {
- err.note(&format!("`{}` is mentioned multiple times", arg));
+ lint.note(&format!("`{}` is mentioned multiple times", arg));
}
ty::util::NotUniqueParam::NotParam(arg) => {
- err.note(&format!("`{}` is not a generic parameter", arg));
+ lint.note(&format!("`{}` is not a generic parameter", arg));
}
}
- err.span_note(
+ lint.span_note(
item_span,
&format!(
"try using the same sequence of generic parameters as the {} definition",
self_descr,
),
- );
- err.emit();
+ )
},
);
}
diff --git a/compiler/rustc_typeck/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
index e45fb5fe4..a34815b45 100644
--- a/compiler/rustc_typeck/src/coherence/unsafety.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs
@@ -13,7 +13,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let item = tcx.hir().expect_item(def_id);
let hir::ItemKind::Impl(ref impl_) = item.kind else { bug!() };
- if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
let trait_def = tcx.trait_def(trait_ref.def_id);
let unsafe_attr =
impl_.generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle");
@@ -26,6 +26,12 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"implementing the trait `{}` is not unsafe",
trait_ref.print_only_trait_path()
)
+ .span_suggestion_verbose(
+ item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)),
+ "remove `unsafe` from this trait implementation",
+ "",
+ rustc_errors::Applicability::MachineApplicable,
+ )
.emit();
}
@@ -37,6 +43,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"the trait `{}` requires an `unsafe impl` declaration",
trait_ref.print_only_trait_path()
)
+ .note(format!(
+ "the trait `{}` enforces invariants that the compiler can't check. \
+ Review the trait documentation and make sure this implementation \
+ upholds those invariants before adding the `unsafe` keyword",
+ trait_ref.print_only_trait_path()
+ ))
+ .span_suggestion_verbose(
+ item.span.shrink_to_lo(),
+ "add `unsafe` to this trait implementation",
+ "unsafe ",
+ rustc_errors::Applicability::MaybeIncorrect,
+ )
.emit();
}
@@ -48,6 +66,18 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
"requires an `unsafe impl` declaration due to `#[{}]` attribute",
attr_name
)
+ .note(format!(
+ "the trait `{}` enforces invariants that the compiler can't check. \
+ Review the trait documentation and make sure this implementation \
+ upholds those invariants before adding the `unsafe` keyword",
+ trait_ref.print_only_trait_path()
+ ))
+ .span_suggestion_verbose(
+ item.span.shrink_to_lo(),
+ "add `unsafe` to this trait implementation",
+ "unsafe ",
+ rustc_errors::Applicability::MaybeIncorrect,
+ )
.emit();
}
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 45a5eca70..346d2e2fc 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -15,46 +15,41 @@
//! crate as a kind of pass. This should eventually be factored away.
use crate::astconv::AstConv;
-use crate::bounds::Bounds;
use crate::check::intrinsic::intrinsic_operation_unsafety;
-use crate::constrained_generic_params as cgp;
use crate::errors;
-use crate::middle::resolve_lifetime as rl;
use rustc_ast as ast;
use rustc_ast::{MetaItemKind, NestedMetaItem};
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind};
-use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::weak_lang_items;
-use rustc_hir::{GenericParamKind, HirId, Node};
+use rustc_hir::{GenericParamKind, Node};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::util::Discr;
-use rustc_middle::ty::util::IntTypeExt;
+use rustc_middle::ty::util::{Discr, IntTypeExt};
+use rustc_middle::ty::ReprOptions;
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
-use rustc_middle::ty::{ReprOptions, ToPredicate};
use rustc_session::lint;
use rustc_session::parse::feature_err;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
use rustc_target::spec::{abi, SanitizerSet};
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
use std::iter;
+mod generics_of;
mod item_bounds;
+mod lifetimes;
+mod predicates_of;
mod type_of;
-#[derive(Debug)]
-struct OnlySelfBounds(bool);
-
///////////////////////////////////////////////////////////////////////////
// Main entry point
@@ -63,19 +58,21 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
}
pub fn provide(providers: &mut Providers) {
+ lifetimes::provide(providers);
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
- generics_of,
- predicates_of,
+ generics_of: generics_of::generics_of,
+ predicates_of: predicates_of::predicates_of,
predicates_defined_on,
- explicit_predicates_of,
- super_predicates_of,
- super_predicates_that_define_assoc_type,
- trait_explicit_predicates_and_bounds,
- type_param_predicates,
+ explicit_predicates_of: predicates_of::explicit_predicates_of,
+ super_predicates_of: predicates_of::super_predicates_of,
+ super_predicates_that_define_assoc_type:
+ predicates_of::super_predicates_that_define_assoc_type,
+ trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
+ type_param_predicates: predicates_of::type_param_predicates,
trait_def,
adt_def,
fn_sig,
@@ -103,13 +100,12 @@ pub fn provide(providers: &mut Providers) {
/// It's also used for the bodies of items like structs where the body (the fields)
/// are just signatures.
///
-/// This is in contrast to [`FnCtxt`], which is used to type-check bodies of
+/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
///
/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
/// while `FnCtxt` does do inference.
///
-/// [`FnCtxt`]: crate::check::FnCtxt
/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
///
/// # Trait predicates
@@ -430,7 +426,6 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
self,
- self.tcx,
span,
item_def_id,
item_segment,
@@ -449,8 +444,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
match self.node() {
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
- let item =
- self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id()));
+ let item = self
+ .tcx
+ .hir()
+ .expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
match &item.kind {
hir::ItemKind::Enum(_, generics)
| hir::ItemKind::Struct(_, generics)
@@ -571,164 +568,10 @@ fn get_new_lifetime_name<'tcx>(
(1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
}
-/// Returns the predicates defined on `item_def_id` of the form
-/// `X: Foo` where `X` is the type parameter `def_id`.
-#[instrument(level = "trace", skip(tcx))]
-fn type_param_predicates(
- tcx: TyCtxt<'_>,
- (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
-) -> ty::GenericPredicates<'_> {
- use rustc_hir::*;
-
- // In the AST, bounds can derive from two places. Either
- // written inline like `<T: Foo>` or in a where-clause like
- // `where T: Foo`.
-
- let param_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let param_owner = tcx.hir().ty_param_owner(def_id);
- let generics = tcx.generics_of(param_owner);
- let index = generics.param_def_id_to_index[&def_id.to_def_id()];
- let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
-
- // Don't look for bounds where the type parameter isn't in scope.
- let parent = if item_def_id == param_owner.to_def_id() {
- None
- } else {
- tcx.generics_of(item_def_id).parent
- };
-
- let mut result = parent
- .map(|parent| {
- let icx = ItemCtxt::new(tcx, parent);
- icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
- })
- .unwrap_or_default();
- let mut extend = None;
-
- let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
- let ast_generics = match tcx.hir().get(item_hir_id) {
- Node::TraitItem(item) => &item.generics,
-
- Node::ImplItem(item) => &item.generics,
-
- Node::Item(item) => {
- match item.kind {
- ItemKind::Fn(.., ref generics, _)
- | ItemKind::Impl(hir::Impl { ref generics, .. })
- | ItemKind::TyAlias(_, ref generics)
- | ItemKind::OpaqueTy(OpaqueTy {
- ref generics,
- origin: hir::OpaqueTyOrigin::TyAlias,
- ..
- })
- | ItemKind::Enum(_, ref generics)
- | ItemKind::Struct(_, ref generics)
- | ItemKind::Union(_, ref generics) => generics,
- ItemKind::Trait(_, _, ref generics, ..) => {
- // Implied `Self: Trait` and supertrait bounds.
- if param_id == item_hir_id {
- let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
- extend =
- Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
- }
- generics
- }
- _ => return result,
- }
- }
-
- Node::ForeignItem(item) => match item.kind {
- ForeignItemKind::Fn(_, _, ref generics) => generics,
- _ => return result,
- },
-
- _ => return result,
- };
-
- let icx = ItemCtxt::new(tcx, item_def_id);
- let extra_predicates = extend.into_iter().chain(
- icx.type_parameter_bounds_in_generics(
- ast_generics,
- param_id,
- ty,
- OnlySelfBounds(true),
- Some(assoc_name),
- )
- .into_iter()
- .filter(|(predicate, _)| match predicate.kind().skip_binder() {
- ty::PredicateKind::Trait(data) => data.self_ty().is_param(index),
- _ => false,
- }),
- );
- result.predicates =
- tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
- result
-}
-
-impl<'tcx> ItemCtxt<'tcx> {
- /// Finds bounds from `hir::Generics`. This requires scanning through the
- /// AST. We do this to avoid having to convert *all* the bounds, which
- /// would create artificial cycles. Instead, we can only convert the
- /// bounds for a type parameter `X` if `X::Foo` is used.
- #[instrument(level = "trace", skip(self, ast_generics))]
- fn type_parameter_bounds_in_generics(
- &self,
- ast_generics: &'tcx hir::Generics<'tcx>,
- param_id: hir::HirId,
- ty: Ty<'tcx>,
- only_self_bounds: OnlySelfBounds,
- assoc_name: Option<Ident>,
- ) -> Vec<(ty::Predicate<'tcx>, Span)> {
- let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
- trace!(?param_def_id);
- ast_generics
- .predicates
- .iter()
- .filter_map(|wp| match *wp {
- hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
- _ => None,
- })
- .flat_map(|bp| {
- let bt = if bp.is_param_bound(param_def_id) {
- Some(ty)
- } else if !only_self_bounds.0 {
- Some(self.to_ty(bp.bounded_ty))
- } else {
- None
- };
- let bvars = self.tcx.late_bound_vars(bp.bounded_ty.hir_id);
-
- bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
- |(_, b, _)| match assoc_name {
- Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
- None => true,
- },
- )
- })
- .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
- .collect()
- }
-
- #[instrument(level = "trace", skip(self))]
- fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
- match b {
- hir::GenericBound::Trait(poly_trait_ref, _) => {
- let trait_ref = &poly_trait_ref.trait_ref;
- if let Some(trait_did) = trait_ref.trait_def_id() {
- self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
- } else {
- false
- }
- }
- _ => false,
- }
- }
-}
-
fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
let it = tcx.hir().item(item_id);
debug!("convert: item {} with id {}", it.ident, it.hir_id());
- let def_id = item_id.def_id;
+ let def_id = item_id.owner_id.def_id;
match it.kind {
// These don't define types.
@@ -740,11 +583,11 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
hir::ItemKind::ForeignMod { items, .. } => {
for item in items {
let item = tcx.hir().foreign_item(item.id);
- tcx.ensure().generics_of(item.def_id);
- tcx.ensure().type_of(item.def_id);
- tcx.ensure().predicates_of(item.def_id);
+ tcx.ensure().generics_of(item.owner_id);
+ tcx.ensure().type_of(item.owner_id);
+ tcx.ensure().predicates_of(item.owner_id);
match item.kind {
- hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.def_id),
+ hir::ForeignItemKind::Fn(..) => tcx.ensure().fn_sig(item.owner_id),
hir::ForeignItemKind::Static(..) => {
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_foreign_item(item);
@@ -840,20 +683,21 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
let trait_item = tcx.hir().trait_item(trait_item_id);
- tcx.ensure().generics_of(trait_item_id.def_id);
+ let def_id = trait_item_id.owner_id;
+ tcx.ensure().generics_of(def_id);
match trait_item.kind {
hir::TraitItemKind::Fn(..) => {
- tcx.ensure().type_of(trait_item_id.def_id);
- tcx.ensure().fn_sig(trait_item_id.def_id);
+ tcx.ensure().type_of(def_id);
+ tcx.ensure().fn_sig(def_id);
}
hir::TraitItemKind::Const(.., Some(_)) => {
- tcx.ensure().type_of(trait_item_id.def_id);
+ tcx.ensure().type_of(def_id);
}
hir::TraitItemKind::Const(hir_ty, _) => {
- tcx.ensure().type_of(trait_item_id.def_id);
+ tcx.ensure().type_of(def_id);
// Account for `const C: _;`.
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
@@ -863,8 +707,8 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
}
hir::TraitItemKind::Type(_, Some(_)) => {
- tcx.ensure().item_bounds(trait_item_id.def_id);
- tcx.ensure().type_of(trait_item_id.def_id);
+ tcx.ensure().item_bounds(def_id);
+ tcx.ensure().type_of(def_id);
// Account for `type T = _;`.
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_trait_item(trait_item);
@@ -872,7 +716,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
}
hir::TraitItemKind::Type(_, None) => {
- tcx.ensure().item_bounds(trait_item_id.def_id);
+ tcx.ensure().item_bounds(def_id);
// #74612: Visit and try to find bad placeholders
// even if there is no concrete type.
let mut visitor = HirPlaceholderCollector::default();
@@ -882,11 +726,11 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
}
};
- tcx.ensure().predicates_of(trait_item_id.def_id);
+ tcx.ensure().predicates_of(def_id);
}
fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
- let def_id = impl_item_id.def_id;
+ let def_id = impl_item_id.owner_id;
tcx.ensure().generics_of(def_id);
tcx.ensure().type_of(def_id);
tcx.ensure().predicates_of(def_id);
@@ -895,7 +739,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
hir::ImplItemKind::Fn(..) => {
tcx.ensure().fn_sig(def_id);
}
- hir::ImplItemKind::TyAlias(_) => {
+ hir::ImplItemKind::Type(_) => {
// Account for `type T = _;`
let mut visitor = HirPlaceholderCollector::default();
visitor.visit_impl_item(impl_item);
@@ -1095,96 +939,6 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
tcx.alloc_adt_def(def_id.to_def_id(), kind, variants, repr)
}
-/// Ensures that the super-predicates of the trait with a `DefId`
-/// of `trait_def_id` are converted and stored. This also ensures that
-/// the transitive super-predicates are converted.
-fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredicates<'_> {
- debug!("super_predicates(trait_def_id={:?})", trait_def_id);
- tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
-}
-
-/// Ensures that the super-predicates of the trait with a `DefId`
-/// of `trait_def_id` are converted and stored. This also ensures that
-/// the transitive super-predicates are converted.
-fn super_predicates_that_define_assoc_type(
- tcx: TyCtxt<'_>,
- (trait_def_id, assoc_name): (DefId, Option<Ident>),
-) -> ty::GenericPredicates<'_> {
- debug!(
- "super_predicates_that_define_assoc_type(trait_def_id={:?}, assoc_name={:?})",
- trait_def_id, assoc_name
- );
- if trait_def_id.is_local() {
- debug!("super_predicates_that_define_assoc_type: local trait_def_id={:?}", trait_def_id);
- let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
-
- let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
- bug!("trait_node_id {} is not an item", trait_hir_id);
- };
-
- let (generics, bounds) = match item.kind {
- hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
- hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
- _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
- };
-
- let icx = ItemCtxt::new(tcx, trait_def_id);
-
- // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
- let self_param_ty = tcx.types.self_param;
- let superbounds1 = if let Some(assoc_name) = assoc_name {
- <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type(
- &icx,
- self_param_ty,
- bounds,
- assoc_name,
- )
- } else {
- <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
- };
-
- let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
-
- // Convert any explicit superbounds in the where-clause,
- // e.g., `trait Foo where Self: Bar`.
- // In the case of trait aliases, however, we include all bounds in the where-clause,
- // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
- // as one of its "superpredicates".
- let is_trait_alias = tcx.is_trait_alias(trait_def_id);
- let superbounds2 = icx.type_parameter_bounds_in_generics(
- generics,
- item.hir_id(),
- self_param_ty,
- OnlySelfBounds(!is_trait_alias),
- assoc_name,
- );
-
- // Combine the two lists to form the complete set of superbounds:
- let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
- debug!(?superbounds);
-
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
- if assoc_name.is_none() {
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
- for &(pred, span) in superbounds {
- debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Trait(bound) = pred.kind().skip_binder() {
- tcx.at(span).super_predicates_of(bound.def_id());
- }
- }
- }
-
- ty::GenericPredicates { parent: None, predicates: superbounds }
- } else {
- // if `assoc_name` is None, then the query should've been redirected to an
- // external provider
- assert!(assoc_name.is_some());
- tcx.super_predicates_of(trait_def_id)
- }
-}
-
fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
let item = tcx.hir().expect_item(def_id.expect_local());
@@ -1256,7 +1010,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
match item {
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
- if !tcx.impl_defaultness(item.id.def_id).has_value() {
+ if !tcx.impl_defaultness(item.id.owner_id).has_value() {
tcx.sess
.struct_span_err(
item.span,
@@ -1326,475 +1080,6 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
)
}
-fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
- struct LateBoundRegionsDetector<'tcx> {
- tcx: TyCtxt<'tcx>,
- outer_index: ty::DebruijnIndex,
- has_late_bound_regions: Option<Span>,
- }
-
- impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
- fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
- if self.has_late_bound_regions.is_some() {
- return;
- }
- match ty.kind {
- hir::TyKind::BareFn(..) => {
- self.outer_index.shift_in(1);
- intravisit::walk_ty(self, ty);
- self.outer_index.shift_out(1);
- }
- _ => intravisit::walk_ty(self, ty),
- }
- }
-
- fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) {
- if self.has_late_bound_regions.is_some() {
- return;
- }
- self.outer_index.shift_in(1);
- intravisit::walk_poly_trait_ref(self, tr);
- self.outer_index.shift_out(1);
- }
-
- fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
- if self.has_late_bound_regions.is_some() {
- 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 => {
- self.has_late_bound_regions = Some(lt.span);
- }
- }
- }
- }
-
- fn has_late_bound_regions<'tcx>(
- tcx: TyCtxt<'tcx>,
- generics: &'tcx hir::Generics<'tcx>,
- decl: &'tcx hir::FnDecl<'tcx>,
- ) -> Option<Span> {
- let mut visitor = LateBoundRegionsDetector {
- tcx,
- outer_index: ty::INNERMOST,
- has_late_bound_regions: None,
- };
- for param in generics.params {
- if let GenericParamKind::Lifetime { .. } = param.kind {
- if tcx.is_late_bound(param.hir_id) {
- return Some(param.span);
- }
- }
- }
- visitor.visit_fn_decl(decl);
- visitor.has_late_bound_regions
- }
-
- match node {
- Node::TraitItem(item) => match item.kind {
- hir::TraitItemKind::Fn(ref sig, _) => {
- has_late_bound_regions(tcx, &item.generics, sig.decl)
- }
- _ => None,
- },
- Node::ImplItem(item) => match item.kind {
- hir::ImplItemKind::Fn(ref sig, _) => {
- has_late_bound_regions(tcx, &item.generics, sig.decl)
- }
- _ => None,
- },
- Node::ForeignItem(item) => match item.kind {
- hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
- has_late_bound_regions(tcx, generics, fn_decl)
- }
- _ => None,
- },
- Node::Item(item) => match item.kind {
- hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
- has_late_bound_regions(tcx, generics, sig.decl)
- }
- _ => None,
- },
- _ => None,
- }
-}
-
-struct AnonConstInParamTyDetector {
- in_param_ty: bool,
- found_anon_const_in_param_ty: bool,
- ct: HirId,
-}
-
-impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
- fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
- if let GenericParamKind::Const { ty, default: _ } = p.kind {
- let prev = self.in_param_ty;
- self.in_param_ty = true;
- self.visit_ty(ty);
- self.in_param_ty = prev;
- }
- }
-
- fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
- if self.in_param_ty && self.ct == c.hir_id {
- self.found_anon_const_in_param_ty = true;
- } else {
- intravisit::walk_anon_const(self, c)
- }
- }
-}
-
-fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
- use rustc_hir::*;
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
-
- let node = tcx.hir().get(hir_id);
- let parent_def_id = match node {
- Node::ImplItem(_)
- | Node::TraitItem(_)
- | Node::Variant(_)
- | Node::Ctor(..)
- | Node::Field(_) => {
- let parent_id = tcx.hir().get_parent_item(hir_id);
- Some(parent_id.to_def_id())
- }
- // FIXME(#43408) always enable this once `lazy_normalization` is
- // stable enough and does not need a feature gate anymore.
- Node::AnonConst(_) => {
- let parent_def_id = tcx.hir().get_parent_item(hir_id);
-
- let mut in_param_ty = false;
- for (_parent, node) in tcx.hir().parent_iter(hir_id) {
- if let Some(generics) = node.generics() {
- let mut visitor = AnonConstInParamTyDetector {
- in_param_ty: false,
- found_anon_const_in_param_ty: false,
- ct: hir_id,
- };
-
- visitor.visit_generics(generics);
- in_param_ty = visitor.found_anon_const_in_param_ty;
- break;
- }
- }
-
- if in_param_ty {
- // We do not allow generic parameters in anon consts if we are inside
- // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
- None
- } else if tcx.lazy_normalization() {
- if let Some(param_id) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) {
- // If the def_id we are calling generics_of on is an anon ct default i.e:
- //
- // struct Foo<const N: usize = { .. }>;
- // ^^^ ^ ^^^^^^ def id of this anon const
- // ^ ^ param_id
- // ^ parent_def_id
- //
- // then we only want to return generics for params to the left of `N`. If we don't do that we
- // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
- //
- // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
- // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
- // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
- //
- // We fix this by having this function return the parent's generics ourselves and truncating the
- // generics to only include non-forward declared params (with the exception of the `Self` ty)
- //
- // For the above code example that means we want `substs: []`
- // For the following struct def we want `substs: [N#0]` when generics_of is called on
- // the def id of the `{ N + 1 }` anon const
- // struct Foo<const N: usize, const M: usize = { N + 1 }>;
- //
- // This has some implications for how we get the predicates available to the anon const
- // see `explicit_predicates_of` for more information on this
- let generics = tcx.generics_of(parent_def_id.to_def_id());
- let param_def = tcx.hir().local_def_id(param_id).to_def_id();
- let param_def_idx = generics.param_def_id_to_index[&param_def];
- // In the above example this would be .params[..N#0]
- let params = generics.params[..param_def_idx as usize].to_owned();
- let param_def_id_to_index =
- params.iter().map(|param| (param.def_id, param.index)).collect();
-
- return ty::Generics {
- // we set the parent of these generics to be our parent's parent so that we
- // dont end up with substs: [N, M, N] for the const default on a struct like this:
- // struct Foo<const N: usize, const M: usize = { ... }>;
- parent: generics.parent,
- parent_count: generics.parent_count,
- params,
- param_def_id_to_index,
- has_self: generics.has_self,
- has_late_bound_regions: generics.has_late_bound_regions,
- };
- }
-
- // HACK(eddyb) this provides the correct generics when
- // `feature(generic_const_expressions)` is enabled, so that const expressions
- // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
- //
- // Note that we do not supply the parent generics when using
- // `min_const_generics`.
- Some(parent_def_id.to_def_id())
- } else {
- let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
- match parent_node {
- // HACK(eddyb) this provides the correct generics for repeat
- // expressions' count (i.e. `N` in `[x; N]`), and explicit
- // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
- // as they shouldn't be able to cause query cycle errors.
- Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
- if constant.hir_id() == hir_id =>
- {
- Some(parent_def_id.to_def_id())
- }
- Node::Variant(Variant { disr_expr: Some(ref constant), .. })
- if constant.hir_id == hir_id =>
- {
- Some(parent_def_id.to_def_id())
- }
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
- Some(tcx.typeck_root_def_id(def_id))
- }
- // Exclude `GlobalAsm` here which cannot have generics.
- Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
- if asm.operands.iter().any(|(op, _op_sp)| match op {
- hir::InlineAsmOperand::Const { anon_const }
- | hir::InlineAsmOperand::SymFn { anon_const } => {
- anon_const.hir_id == hir_id
- }
- _ => false,
- }) =>
- {
- Some(parent_def_id.to_def_id())
- }
- _ => None,
- }
- }
- }
- Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
- Some(tcx.typeck_root_def_id(def_id))
- }
- Node::Item(item) => match item.kind {
- ItemKind::OpaqueTy(hir::OpaqueTy {
- origin:
- hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
- in_trait,
- ..
- }) => {
- if in_trait {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
- } else {
- assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
- }
- Some(fn_def_id.to_def_id())
- }
- ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
- let parent_id = tcx.hir().get_parent_item(hir_id);
- assert_ne!(parent_id, CRATE_DEF_ID);
- debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
- // Opaque types are always nested within another item, and
- // inherit the generics of the item.
- Some(parent_id.to_def_id())
- }
- _ => None,
- },
- _ => None,
- };
-
- enum Defaults {
- Allowed,
- // See #36887
- FutureCompatDisallowed,
- Deny,
- }
-
- let no_generics = hir::Generics::empty();
- let ast_generics = node.generics().unwrap_or(&no_generics);
- let (opt_self, allow_defaults) = match node {
- Node::Item(item) => {
- match item.kind {
- ItemKind::Trait(..) | ItemKind::TraitAlias(..) => {
- // Add in the self type parameter.
- //
- // Something of a hack: use the node id for the trait, also as
- // the node id for the Self type parameter.
- let opt_self = Some(ty::GenericParamDef {
- index: 0,
- name: kw::SelfUpper,
- def_id,
- pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type {
- has_default: false,
- synthetic: false,
- },
- });
-
- (opt_self, Defaults::Allowed)
- }
- ItemKind::TyAlias(..)
- | ItemKind::Enum(..)
- | ItemKind::Struct(..)
- | ItemKind::OpaqueTy(..)
- | ItemKind::Union(..) => (None, Defaults::Allowed),
- _ => (None, Defaults::FutureCompatDisallowed),
- }
- }
-
- // GATs
- Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
- (None, Defaults::Deny)
- }
- Node::ImplItem(item) if matches!(item.kind, ImplItemKind::TyAlias(..)) => {
- (None, Defaults::Deny)
- }
-
- _ => (None, Defaults::FutureCompatDisallowed),
- };
-
- let has_self = opt_self.is_some();
- let mut parent_has_self = false;
- let mut own_start = has_self as u32;
- let parent_count = parent_def_id.map_or(0, |def_id| {
- let generics = tcx.generics_of(def_id);
- assert!(!has_self);
- parent_has_self = generics.has_self;
- own_start = generics.count() as u32;
- generics.parent_count + generics.params.len()
- });
-
- let mut params: Vec<_> = Vec::with_capacity(ast_generics.params.len() + has_self as usize);
-
- if let Some(opt_self) = opt_self {
- params.push(opt_self);
- }
-
- let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
- params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
- name: param.name.ident().name,
- index: own_start + i as u32,
- def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
- pure_wrt_drop: param.pure_wrt_drop,
- kind: ty::GenericParamDefKind::Lifetime,
- }));
-
- // Now create the real type and const parameters.
- let type_start = own_start - has_self as u32 + params.len() as u32;
- let mut i = 0;
-
- const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
- `struct`, `enum`, `type`, or `trait` definitions";
-
- params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
- GenericParamKind::Lifetime { .. } => None,
- GenericParamKind::Type { ref default, synthetic, .. } => {
- if default.is_some() {
- match allow_defaults {
- Defaults::Allowed => {}
- Defaults::FutureCompatDisallowed
- if tcx.features().default_type_parameter_fallback => {}
- Defaults::FutureCompatDisallowed => {
- tcx.struct_span_lint_hir(
- lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
- param.hir_id,
- param.span,
- |lint| {
- lint.build(TYPE_DEFAULT_NOT_ALLOWED).emit();
- },
- );
- }
- Defaults::Deny => {
- tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
- }
- }
- }
-
- let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
-
- let param_def = ty::GenericParamDef {
- index: type_start + i as u32,
- name: param.name.ident().name,
- def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
- pure_wrt_drop: param.pure_wrt_drop,
- kind,
- };
- i += 1;
- Some(param_def)
- }
- GenericParamKind::Const { default, .. } => {
- if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
- tcx.sess.span_err(
- param.span,
- "defaults for const parameters are only allowed in \
- `struct`, `enum`, `type`, or `trait` definitions",
- );
- }
-
- let param_def = ty::GenericParamDef {
- index: type_start + i as u32,
- name: param.name.ident().name,
- def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
- pure_wrt_drop: param.pure_wrt_drop,
- kind: ty::GenericParamDefKind::Const { has_default: default.is_some() },
- };
- i += 1;
- Some(param_def)
- }
- }));
-
- // provide junk type parameter defs - the only place that
- // cares about anything but the length is instantiation,
- // and we don't do that for closures.
- if let Node::Expr(&hir::Expr {
- kind: hir::ExprKind::Closure(hir::Closure { movability: gen, .. }),
- ..
- }) = node
- {
- let dummy_args = if gen.is_some() {
- &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
- } else {
- &["<closure_kind>", "<closure_signature>", "<upvars>"][..]
- };
-
- params.extend(dummy_args.iter().enumerate().map(|(i, &arg)| ty::GenericParamDef {
- index: type_start + i as u32,
- name: Symbol::intern(arg),
- def_id,
- pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
- }));
- }
-
- // provide junk type parameter defs for const blocks.
- if let Node::AnonConst(_) = node {
- let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
- if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
- params.push(ty::GenericParamDef {
- index: type_start,
- name: Symbol::intern("<const_ty>"),
- def_id,
- pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
- });
- }
- }
-
- let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
-
- ty::Generics {
- parent: parent_def_id,
- parent_count,
- params,
- param_def_id_to_index,
- has_self: has_self || parent_has_self,
- has_late_bound_regions: has_late_bound_regions(tcx, node),
- }
-}
-
fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
generic_args.iter().any(|arg| match arg {
hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
@@ -1858,7 +1143,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
}
ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
- // Do not try to inference the return type for a impl method coming from a trait
+ // Do not try to infer the return type for a impl method coming from a trait
if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
tcx.hir().get(tcx.hir().get_parent_node(hir_id))
&& i.of_trait.is_some()
@@ -2001,15 +1286,46 @@ fn infer_return_ty_for_fn_sig<'tcx>(
fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> {
let icx = ItemCtxt::new(tcx, def_id);
- match tcx.hir().expect_item(def_id.expect_local()).kind {
+ let item = tcx.hir().expect_item(def_id.expect_local());
+ match item.kind {
hir::ItemKind::Impl(ref impl_) => impl_.of_trait.as_ref().map(|ast_trait_ref| {
let selfty = tcx.type_of(def_id);
- <dyn AstConv<'_>>::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty)
+ <dyn AstConv<'_>>::instantiate_mono_trait_ref(
+ &icx,
+ ast_trait_ref,
+ selfty,
+ check_impl_constness(tcx, impl_.constness, ast_trait_ref),
+ )
}),
_ => bug!(),
}
}
+fn check_impl_constness(
+ tcx: TyCtxt<'_>,
+ constness: hir::Constness,
+ ast_trait_ref: &hir::TraitRef<'_>,
+) -> ty::BoundConstness {
+ match constness {
+ hir::Constness::Const => {
+ if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
+ let trait_name = tcx.item_name(trait_def_id).to_string();
+ tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
+ trait_ref_span: ast_trait_ref.path.span,
+ trait_name,
+ local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
+ marking: (),
+ adding: (),
+ });
+ ty::BoundConstness::NotConst
+ } else {
+ ty::BoundConstness::ConstIfConst
+ }
+ },
+ hir::Constness::NotConst => ty::BoundConstness::NotConst,
+ }
+}
+
fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity {
let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
let item = tcx.hir().expect_item(def_id.expect_local());
@@ -2091,451 +1407,6 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate
result
}
-/// Returns a list of all type predicates (explicit and implicit) for the definition with
-/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
-/// `Self: Trait` predicates for traits.
-fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
- let mut result = tcx.predicates_defined_on(def_id);
-
- if tcx.is_trait(def_id) {
- // For traits, add `Self: Trait` predicate. This is
- // not part of the predicates that a user writes, but it
- // is something that one must prove in order to invoke a
- // method or project an associated type.
- //
- // In the chalk setup, this predicate is not part of the
- // "predicates" for a trait item. But it is useful in
- // rustc because if you directly (e.g.) invoke a trait
- // method like `Trait::method(...)`, you must naturally
- // prove that the trait applies to the types that were
- // used, and adding the predicate into this list ensures
- // that this is done.
- //
- // We use a DUMMY_SP here as a way to signal trait bounds that come
- // from the trait itself that *shouldn't* be shown as the source of
- // an obligation and instead be skipped. Otherwise we'd use
- // `tcx.def_span(def_id);`
-
- let constness = if tcx.has_attr(def_id, sym::const_trait) {
- ty::BoundConstness::ConstIfConst
- } else {
- ty::BoundConstness::NotConst
- };
-
- let span = rustc_span::DUMMY_SP;
- result.predicates =
- tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
- ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
- span,
- ))));
- }
- debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
- result
-}
-
-/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
-/// N.B., this does not include any implied/inferred constraints.
-#[instrument(level = "trace", skip(tcx), ret)]
-fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
- use rustc_hir::*;
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- let node = tcx.hir().get(hir_id);
-
- let mut is_trait = None;
- let mut is_default_impl_trait = None;
-
- let icx = ItemCtxt::new(tcx, def_id);
-
- const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
-
- // We use an `IndexSet` to preserves order of insertion.
- // Preserving the order of insertion is important here so as not to break UI tests.
- let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
-
- let ast_generics = match node {
- Node::TraitItem(item) => item.generics,
-
- Node::ImplItem(item) => item.generics,
-
- Node::Item(item) => {
- match item.kind {
- ItemKind::Impl(ref impl_) => {
- if impl_.defaultness.is_default() {
- is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy);
- }
- &impl_.generics
- }
- ItemKind::Fn(.., ref generics, _)
- | ItemKind::TyAlias(_, ref generics)
- | ItemKind::Enum(_, ref generics)
- | ItemKind::Struct(_, ref generics)
- | ItemKind::Union(_, ref generics) => *generics,
-
- ItemKind::Trait(_, _, ref generics, ..) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
- *generics
- }
- ItemKind::TraitAlias(ref generics, _) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
- *generics
- }
- ItemKind::OpaqueTy(OpaqueTy {
- origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
- ..
- }) => {
- // return-position impl trait
- //
- // We don't inherit predicates from the parent here:
- // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
- // then the return type is `f::<'static, T>::{{opaque}}`.
- //
- // If we inherited the predicates of `f` then we would
- // require that `T: 'static` to show that the return
- // type is well-formed.
- //
- // The only way to have something with this opaque type
- // is from the return type of the containing function,
- // which will ensure that the function's predicates
- // hold.
- return ty::GenericPredicates { parent: None, predicates: &[] };
- }
- ItemKind::OpaqueTy(OpaqueTy {
- ref generics,
- origin: hir::OpaqueTyOrigin::TyAlias,
- ..
- }) => {
- // type-alias impl trait
- generics
- }
-
- _ => NO_GENERICS,
- }
- }
-
- Node::ForeignItem(item) => match item.kind {
- ForeignItemKind::Static(..) => NO_GENERICS,
- ForeignItemKind::Fn(_, _, ref generics) => *generics,
- ForeignItemKind::Type => NO_GENERICS,
- },
-
- _ => NO_GENERICS,
- };
-
- let generics = tcx.generics_of(def_id);
- let parent_count = generics.parent_count as u32;
- let has_own_self = generics.has_self && parent_count == 0;
-
- // Below we'll consider the bounds on the type parameters (including `Self`)
- // and the explicit where-clauses, but to get the full set of predicates
- // on a trait we need to add in the supertrait bounds and bounds found on
- // associated types.
- if let Some(_trait_ref) = is_trait {
- predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
- }
-
- // In default impls, we can assume that the self type implements
- // the trait. So in:
- //
- // default impl Foo for Bar { .. }
- //
- // we add a default where clause `Foo: Bar`. We do a similar thing for traits
- // (see below). Recall that a default impl is not itself an impl, but rather a
- // set of defaults that can be incorporated into another impl.
- if let Some(trait_ref) = is_default_impl_trait {
- predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id)));
- }
-
- // Collect the region predicates that were declared inline as
- // well. In the case of parameters declared on a fn or method, we
- // have to be careful to only iterate over early-bound regions.
- let mut index = parent_count
- + has_own_self as u32
- + early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
-
- trace!(?predicates);
- trace!(?ast_generics);
-
- // Collect the predicates that were written inline by the user on each
- // type parameter (e.g., `<T: Foo>`).
- for param in ast_generics.params {
- match param.kind {
- // We already dealt with early bound lifetimes above.
- GenericParamKind::Lifetime { .. } => (),
- GenericParamKind::Type { .. } => {
- let name = param.name.ident().name;
- let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
- index += 1;
-
- let mut bounds = Bounds::default();
- // Params are implicitly sized unless a `?Sized` bound is found
- <dyn AstConv<'_>>::add_implicitly_sized(
- &icx,
- &mut bounds,
- &[],
- Some((param.hir_id, ast_generics.predicates)),
- param.span,
- );
- trace!(?bounds);
- predicates.extend(bounds.predicates(tcx, param_ty));
- trace!(?predicates);
- }
- GenericParamKind::Const { .. } => {
- // Bounds on const parameters are currently not possible.
- index += 1;
- }
- }
- }
-
- trace!(?predicates);
- // Add in the bounds that appear in the where-clause.
- for predicate in ast_generics.predicates {
- match predicate {
- hir::WherePredicate::BoundPredicate(bound_pred) => {
- let ty = icx.to_ty(bound_pred.bounded_ty);
- let bound_vars = icx.tcx.late_bound_vars(bound_pred.bounded_ty.hir_id);
-
- // Keep the type around in a dummy predicate, in case of no bounds.
- // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
- // is still checked for WF.
- if bound_pred.bounds.is_empty() {
- if let ty::Param(_) = ty.kind() {
- // This is a `where T:`, which can be in the HIR from the
- // transformation that moves `?Sized` to `T`'s declaration.
- // We can skip the predicate because type parameters are
- // trivially WF, but also we *should*, to avoid exposing
- // users who never wrote `where Type:,` themselves, to
- // compiler/tooling bugs from not handling WF predicates.
- } else {
- let span = bound_pred.bounded_ty.span;
- let predicate = ty::Binder::bind_with_vars(
- ty::PredicateKind::WellFormed(ty.into()),
- bound_vars,
- );
- predicates.insert((predicate.to_predicate(tcx), span));
- }
- }
-
- let mut bounds = Bounds::default();
- <dyn AstConv<'_>>::add_bounds(
- &icx,
- ty,
- bound_pred.bounds.iter(),
- &mut bounds,
- bound_vars,
- );
- predicates.extend(bounds.predicates(tcx, ty));
- }
-
- hir::WherePredicate::RegionPredicate(region_pred) => {
- let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, &region_pred.lifetime, None);
- predicates.extend(region_pred.bounds.iter().map(|bound| {
- let (r2, span) = match bound {
- hir::GenericBound::Outlives(lt) => {
- (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span)
- }
- _ => bug!(),
- };
- let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives(
- ty::OutlivesPredicate(r1, r2),
- ))
- .to_predicate(icx.tcx);
-
- (pred, span)
- }))
- }
-
- hir::WherePredicate::EqPredicate(..) => {
- // FIXME(#20041)
- }
- }
- }
-
- if tcx.features().generic_const_exprs {
- predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
- }
-
- let mut predicates: Vec<_> = predicates.into_iter().collect();
-
- // Subtle: before we store the predicates into the tcx, we
- // sort them so that predicates like `T: Foo<Item=U>` come
- // before uses of `U`. This avoids false ambiguity errors
- // 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 trait_ref = tcx.impl_trait_ref(def_id);
- cgp::setup_constraining_predicates(
- tcx,
- &mut predicates,
- trait_ref,
- &mut cgp::parameters_for_impl(self_ty, trait_ref),
- );
- }
-
- ty::GenericPredicates {
- parent: generics.parent,
- predicates: tcx.arena.alloc_from_iter(predicates),
- }
-}
-
-fn const_evaluatable_predicates_of<'tcx>(
- tcx: TyCtxt<'tcx>,
- def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> {
- struct ConstCollector<'tcx> {
- tcx: TyCtxt<'tcx>,
- preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
- }
-
- impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
- fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
- let def_id = self.tcx.hir().local_def_id(c.hir_id);
- let ct = ty::Const::from_anon_const(self.tcx, def_id);
- if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
- assert_eq!(uv.promoted, ());
- let span = self.tcx.hir().span(c.hir_id);
- self.preds.insert((
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
- .to_predicate(self.tcx),
- span,
- ));
- }
- }
-
- fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
- // Do not look into const param defaults,
- // these get checked when they are actually instantiated.
- //
- // We do not want the following to error:
- //
- // struct Foo<const N: usize, const M: usize = { N + 1 }>;
- // struct Bar<const N: usize>(Foo<N, 3>);
- }
- }
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- let node = tcx.hir().get(hir_id);
-
- let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
- if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind {
- if let Some(of_trait) = &impl_.of_trait {
- debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
- collector.visit_trait_ref(of_trait);
- }
-
- debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
- collector.visit_ty(impl_.self_ty);
- }
-
- if let Some(generics) = node.generics() {
- debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
- collector.visit_generics(generics);
- }
-
- if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
- debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
- collector.visit_fn_decl(fn_sig.decl);
- }
- debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
-
- collector.preds
-}
-
-fn trait_explicit_predicates_and_bounds(
- tcx: TyCtxt<'_>,
- def_id: LocalDefId,
-) -> ty::GenericPredicates<'_> {
- assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
- gather_explicit_predicates_of(tcx, def_id.to_def_id())
-}
-
-fn explicit_predicates_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericPredicates<'tcx> {
- let def_kind = tcx.def_kind(def_id);
- if let DefKind::Trait = def_kind {
- // Remove bounds on associated types from the predicates, they will be
- // returned by `explicit_item_bounds`.
- let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
- let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
-
- let is_assoc_item_ty = |ty: Ty<'tcx>| {
- // For a predicate from a where clause to become a bound on an
- // associated type:
- // * It must use the identity substs of the item.
- // * Since any generic parameters on the item are not in scope,
- // this means that the item is not a GAT, and its identity
- // substs are the same as the trait's.
- // * It must be an associated type for this trait (*not* a
- // supertrait).
- if let ty::Projection(projection) = ty.kind() {
- projection.substs == trait_identity_substs
- && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
- } else {
- false
- }
- };
-
- let predicates: Vec<_> = predicates_and_bounds
- .predicates
- .iter()
- .copied()
- .filter(|(pred, _)| match pred.kind().skip_binder() {
- ty::PredicateKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
- ty::PredicateKind::Projection(proj) => {
- !is_assoc_item_ty(proj.projection_ty.self_ty())
- }
- ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
- _ => true,
- })
- .collect();
- if predicates.len() == predicates_and_bounds.predicates.len() {
- predicates_and_bounds
- } else {
- ty::GenericPredicates {
- parent: predicates_and_bounds.parent,
- predicates: tcx.arena.alloc_slice(&predicates),
- }
- }
- } else {
- if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
- if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() {
- // In `generics_of` we set the generics' parent to be our parent's parent which means that
- // we lose out on the predicates of our actual parent if we dont return those predicates here.
- // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
- //
- // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
- // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
- // ^^^ explicit_predicates_of on
- // parent item we dont have set as the
- // parent of generics returned by `generics_of`
- //
- // In the above code we want the anon const to have predicates in its param env for `T: Trait`
- let item_def_id = tcx.hir().get_parent_item(hir_id);
- // In the above code example we would be calling `explicit_predicates_of(Foo)` here
- return tcx.explicit_predicates_of(item_def_id);
- }
- }
- gather_explicit_predicates_of(tcx, def_id)
- }
-}
-
-/// Converts a specific `GenericBound` from the AST into a set of
-/// predicates that apply to the self type. A vector is returned
-/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
-/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
-/// and `<T as Bar>::X == i32`).
-fn predicates_from_bound<'tcx>(
- astconv: &dyn AstConv<'tcx>,
- param_ty: Ty<'tcx>,
- bound: &'tcx hir::GenericBound<'tcx>,
- bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
-) -> Vec<(ty::Predicate<'tcx>, Span)> {
- let mut bounds = Bounds::default();
- astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
- bounds.predicates(astconv.tcx(), param_ty).collect()
-}
-
fn compute_sig_of_foreign_fn_decl<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
@@ -2543,7 +1414,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
abi: abi::Abi,
) -> ty::PolyFnSig<'tcx> {
let unsafety = if abi == abi::Abi::RustIntrinsic {
- intrinsic_operation_unsafety(tcx.item_name(def_id))
+ intrinsic_operation_unsafety(tcx, def_id)
} else {
hir::Unsafety::Unsafe
};
@@ -2741,13 +1612,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
}
- // The panic_no_unwind function called by TerminatorKind::Abort will never
- // unwind. If the panic handler that it invokes unwind then it will simply
- // call the panic handler again.
- if Some(did.to_def_id()) == tcx.lang_items().panic_no_unwind() {
- codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
- }
-
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
let mut inline_span = None;
@@ -2808,7 +1672,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
)
.emit();
}
- } else if attr.has_name(sym::rustc_allocator_nounwind) {
+ } else if attr.has_name(sym::rustc_nounwind) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
} else if attr.has_name(sym::rustc_reallocator) {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR;
@@ -3154,6 +2018,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
E0535,
"invalid argument"
)
+ .help("valid inline arguments are `always` and `never`")
.emit();
InlineAttr::None
@@ -3227,11 +2092,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
lint::builtin::INLINE_NO_SANITIZE,
hir_id,
no_sanitize_span,
- |lint| {
- lint.build("`no_sanitize` will have no effect after inlining")
- .span_note(inline_span, "inlining requested here")
- .emit();
- },
+ "`no_sanitize` will have no effect after inlining",
+ |lint| lint.span_note(inline_span, "inlining requested here"),
)
}
}
@@ -3386,7 +2248,7 @@ fn check_target_feature_trait_unsafe(tcx: TyCtxt<'_>, id: LocalDefId, attr_span:
let node = tcx.hir().get(hir_id);
if let 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);
+ let parent_item = tcx.hir().expect_item(parent_id.def_id);
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = parent_item.kind {
tcx.sess
.struct_span_err(
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
new file mode 100644
index 000000000..c7777a946
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -0,0 +1,481 @@
+use crate::middle::resolve_lifetime as rl;
+use hir::{
+ intravisit::{self, Visitor},
+ GenericParamKind, HirId, Node,
+};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_session::lint;
+use rustc_span::symbol::{kw, Symbol};
+use rustc_span::Span;
+
+pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
+ use rustc_hir::*;
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+
+ let node = tcx.hir().get(hir_id);
+ let parent_def_id = match node {
+ Node::ImplItem(_)
+ | Node::TraitItem(_)
+ | Node::Variant(_)
+ | Node::Ctor(..)
+ | Node::Field(_) => {
+ let parent_id = tcx.hir().get_parent_item(hir_id);
+ Some(parent_id.to_def_id())
+ }
+ // FIXME(#43408) always enable this once `lazy_normalization` is
+ // stable enough and does not need a feature gate anymore.
+ Node::AnonConst(_) => {
+ let parent_def_id = tcx.hir().get_parent_item(hir_id);
+
+ let mut in_param_ty = false;
+ for (_parent, node) in tcx.hir().parent_iter(hir_id) {
+ if let Some(generics) = node.generics() {
+ let mut visitor = AnonConstInParamTyDetector {
+ in_param_ty: false,
+ found_anon_const_in_param_ty: false,
+ ct: hir_id,
+ };
+
+ visitor.visit_generics(generics);
+ in_param_ty = visitor.found_anon_const_in_param_ty;
+ break;
+ }
+ }
+
+ if in_param_ty {
+ // We do not allow generic parameters in anon consts if we are inside
+ // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
+ None
+ } else if tcx.lazy_normalization() {
+ if let Some(param_id) = tcx.hir().opt_const_param_default_param_hir_id(hir_id) {
+ // If the def_id we are calling generics_of on is an anon ct default i.e:
+ //
+ // struct Foo<const N: usize = { .. }>;
+ // ^^^ ^ ^^^^^^ def id of this anon const
+ // ^ ^ param_id
+ // ^ parent_def_id
+ //
+ // then we only want to return generics for params to the left of `N`. If we don't do that we
+ // end up with that const looking like: `ty::ConstKind::Unevaluated(def_id, substs: [N#0])`.
+ //
+ // This causes ICEs (#86580) when building the substs for Foo in `fn foo() -> Foo { .. }` as
+ // we substitute the defaults with the partially built substs when we build the substs. Subst'ing
+ // the `N#0` on the unevaluated const indexes into the empty substs we're in the process of building.
+ //
+ // We fix this by having this function return the parent's generics ourselves and truncating the
+ // generics to only include non-forward declared params (with the exception of the `Self` ty)
+ //
+ // For the above code example that means we want `substs: []`
+ // For the following struct def we want `substs: [N#0]` when generics_of is called on
+ // the def id of the `{ N + 1 }` anon const
+ // struct Foo<const N: usize, const M: usize = { N + 1 }>;
+ //
+ // This has some implications for how we get the predicates available to the anon const
+ // see `explicit_predicates_of` for more information on this
+ let generics = tcx.generics_of(parent_def_id.to_def_id());
+ let param_def = tcx.hir().local_def_id(param_id).to_def_id();
+ let param_def_idx = generics.param_def_id_to_index[&param_def];
+ // In the above example this would be .params[..N#0]
+ let params = generics.params[..param_def_idx as usize].to_owned();
+ let param_def_id_to_index =
+ params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ return ty::Generics {
+ // we set the parent of these generics to be our parent's parent so that we
+ // dont end up with substs: [N, M, N] for the const default on a struct like this:
+ // struct Foo<const N: usize, const M: usize = { ... }>;
+ parent: generics.parent,
+ parent_count: generics.parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: generics.has_self,
+ has_late_bound_regions: generics.has_late_bound_regions,
+ };
+ }
+
+ // HACK(eddyb) this provides the correct generics when
+ // `feature(generic_const_expressions)` is enabled, so that const expressions
+ // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
+ //
+ // Note that we do not supply the parent generics when using
+ // `min_const_generics`.
+ Some(parent_def_id.to_def_id())
+ } else {
+ let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+ match parent_node {
+ // HACK(eddyb) this provides the correct generics for repeat
+ // expressions' count (i.e. `N` in `[x; N]`), and explicit
+ // `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
+ // as they shouldn't be able to cause query cycle errors.
+ Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
+ if constant.hir_id() == hir_id =>
+ {
+ Some(parent_def_id.to_def_id())
+ }
+ Node::Variant(Variant { disr_expr: Some(ref constant), .. })
+ if constant.hir_id == hir_id =>
+ {
+ Some(parent_def_id.to_def_id())
+ }
+ Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
+ Some(tcx.typeck_root_def_id(def_id))
+ }
+ // Exclude `GlobalAsm` here which cannot have generics.
+ Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
+ if asm.operands.iter().any(|(op, _op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const }
+ | hir::InlineAsmOperand::SymFn { anon_const } => {
+ anon_const.hir_id == hir_id
+ }
+ _ => false,
+ }) =>
+ {
+ Some(parent_def_id.to_def_id())
+ }
+ _ => None,
+ }
+ }
+ }
+ Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
+ Some(tcx.typeck_root_def_id(def_id))
+ }
+ Node::Item(item) => match item.kind {
+ ItemKind::OpaqueTy(hir::OpaqueTy {
+ origin:
+ hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+ in_trait,
+ ..
+ }) => {
+ if in_trait {
+ assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
+ } else {
+ assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
+ }
+ Some(fn_def_id.to_def_id())
+ }
+ ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+ let parent_id = tcx.hir().get_parent_item(hir_id);
+ assert_ne!(parent_id, hir::CRATE_OWNER_ID);
+ debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
+ // Opaque types are always nested within another item, and
+ // inherit the generics of the item.
+ Some(parent_id.to_def_id())
+ }
+ _ => None,
+ },
+ _ => None,
+ };
+
+ enum Defaults {
+ Allowed,
+ // See #36887
+ FutureCompatDisallowed,
+ Deny,
+ }
+
+ let no_generics = hir::Generics::empty();
+ let ast_generics = node.generics().unwrap_or(&no_generics);
+ let (opt_self, allow_defaults) = match node {
+ Node::Item(item) => {
+ match item.kind {
+ ItemKind::Trait(..) | ItemKind::TraitAlias(..) => {
+ // Add in the self type parameter.
+ //
+ // Something of a hack: use the node id for the trait, also as
+ // the node id for the Self type parameter.
+ let opt_self = Some(ty::GenericParamDef {
+ index: 0,
+ name: kw::SelfUpper,
+ def_id,
+ pure_wrt_drop: false,
+ kind: ty::GenericParamDefKind::Type {
+ has_default: false,
+ synthetic: false,
+ },
+ });
+
+ (opt_self, Defaults::Allowed)
+ }
+ ItemKind::TyAlias(..)
+ | ItemKind::Enum(..)
+ | ItemKind::Struct(..)
+ | ItemKind::OpaqueTy(..)
+ | ItemKind::Union(..) => (None, Defaults::Allowed),
+ _ => (None, Defaults::FutureCompatDisallowed),
+ }
+ }
+
+ // GATs
+ Node::TraitItem(item) if matches!(item.kind, TraitItemKind::Type(..)) => {
+ (None, Defaults::Deny)
+ }
+ Node::ImplItem(item) if matches!(item.kind, ImplItemKind::Type(..)) => {
+ (None, Defaults::Deny)
+ }
+
+ _ => (None, Defaults::FutureCompatDisallowed),
+ };
+
+ let has_self = opt_self.is_some();
+ let mut parent_has_self = false;
+ let mut own_start = has_self as u32;
+ let parent_count = parent_def_id.map_or(0, |def_id| {
+ let generics = tcx.generics_of(def_id);
+ assert!(!has_self);
+ parent_has_self = generics.has_self;
+ own_start = generics.count() as u32;
+ generics.parent_count + generics.params.len()
+ });
+
+ let mut params: Vec<_> = Vec::with_capacity(ast_generics.params.len() + has_self as usize);
+
+ if let Some(opt_self) = opt_self {
+ params.push(opt_self);
+ }
+
+ let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, ast_generics);
+ params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
+ name: param.name.ident().name,
+ index: own_start + i as u32,
+ def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
+ pure_wrt_drop: param.pure_wrt_drop,
+ kind: ty::GenericParamDefKind::Lifetime,
+ }));
+
+ // Now create the real type and const parameters.
+ let type_start = own_start - has_self as u32 + params.len() as u32;
+ let mut i = 0;
+ let mut next_index = || {
+ let prev = i;
+ i += 1;
+ prev as u32 + type_start
+ };
+
+ const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
+ `struct`, `enum`, `type`, or `trait` definitions";
+
+ params.extend(ast_generics.params.iter().filter_map(|param| match param.kind {
+ GenericParamKind::Lifetime { .. } => None,
+ GenericParamKind::Type { ref default, synthetic, .. } => {
+ if default.is_some() {
+ match allow_defaults {
+ Defaults::Allowed => {}
+ Defaults::FutureCompatDisallowed
+ if tcx.features().default_type_parameter_fallback => {}
+ Defaults::FutureCompatDisallowed => {
+ tcx.struct_span_lint_hir(
+ lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+ param.hir_id,
+ param.span,
+ TYPE_DEFAULT_NOT_ALLOWED,
+ |lint| lint,
+ );
+ }
+ Defaults::Deny => {
+ tcx.sess.span_err(param.span, TYPE_DEFAULT_NOT_ALLOWED);
+ }
+ }
+ }
+
+ let kind = ty::GenericParamDefKind::Type { has_default: default.is_some(), synthetic };
+
+ Some(ty::GenericParamDef {
+ index: next_index(),
+ name: param.name.ident().name,
+ def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
+ pure_wrt_drop: param.pure_wrt_drop,
+ kind,
+ })
+ }
+ GenericParamKind::Const { default, .. } => {
+ if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
+ tcx.sess.span_err(
+ param.span,
+ "defaults for const parameters are only allowed in \
+ `struct`, `enum`, `type`, or `trait` definitions",
+ );
+ }
+
+ Some(ty::GenericParamDef {
+ index: next_index(),
+ name: param.name.ident().name,
+ def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(),
+ pure_wrt_drop: param.pure_wrt_drop,
+ kind: ty::GenericParamDefKind::Const { has_default: default.is_some() },
+ })
+ }
+ }));
+
+ // provide junk type parameter defs - the only place that
+ // cares about anything but the length is instantiation,
+ // and we don't do that for closures.
+ if let Node::Expr(&hir::Expr {
+ kind: hir::ExprKind::Closure(hir::Closure { movability: gen, .. }),
+ ..
+ }) = node
+ {
+ let dummy_args = if gen.is_some() {
+ &["<resume_ty>", "<yield_ty>", "<return_ty>", "<witness>", "<upvars>"][..]
+ } else {
+ &["<closure_kind>", "<closure_signature>", "<upvars>"][..]
+ };
+
+ params.extend(dummy_args.iter().map(|&arg| ty::GenericParamDef {
+ index: next_index(),
+ name: Symbol::intern(arg),
+ def_id,
+ pure_wrt_drop: false,
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
+ }));
+ }
+
+ // provide junk type parameter defs for const blocks.
+ if let Node::AnonConst(_) = node {
+ let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
+ if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
+ params.push(ty::GenericParamDef {
+ index: next_index(),
+ name: Symbol::intern("<const_ty>"),
+ def_id,
+ pure_wrt_drop: false,
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
+ });
+ }
+ }
+
+ let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ ty::Generics {
+ parent: parent_def_id,
+ parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: has_self || parent_has_self,
+ has_late_bound_regions: has_late_bound_regions(tcx, node),
+ }
+}
+
+fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
+ struct LateBoundRegionsDetector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ outer_index: ty::DebruijnIndex,
+ has_late_bound_regions: Option<Span>,
+ }
+
+ impl<'tcx> Visitor<'tcx> for LateBoundRegionsDetector<'tcx> {
+ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+ if self.has_late_bound_regions.is_some() {
+ return;
+ }
+ match ty.kind {
+ hir::TyKind::BareFn(..) => {
+ self.outer_index.shift_in(1);
+ intravisit::walk_ty(self, ty);
+ self.outer_index.shift_out(1);
+ }
+ _ => intravisit::walk_ty(self, ty),
+ }
+ }
+
+ fn visit_poly_trait_ref(&mut self, tr: &'tcx hir::PolyTraitRef<'tcx>) {
+ if self.has_late_bound_regions.is_some() {
+ return;
+ }
+ self.outer_index.shift_in(1);
+ intravisit::walk_poly_trait_ref(self, tr);
+ self.outer_index.shift_out(1);
+ }
+
+ fn visit_lifetime(&mut self, lt: &'tcx hir::Lifetime) {
+ if self.has_late_bound_regions.is_some() {
+ 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 => {
+ self.has_late_bound_regions = Some(lt.span);
+ }
+ }
+ }
+ }
+
+ fn has_late_bound_regions<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ generics: &'tcx hir::Generics<'tcx>,
+ decl: &'tcx hir::FnDecl<'tcx>,
+ ) -> Option<Span> {
+ let mut visitor = LateBoundRegionsDetector {
+ tcx,
+ outer_index: ty::INNERMOST,
+ has_late_bound_regions: None,
+ };
+ for param in generics.params {
+ if let GenericParamKind::Lifetime { .. } = param.kind {
+ if tcx.is_late_bound(param.hir_id) {
+ return Some(param.span);
+ }
+ }
+ }
+ visitor.visit_fn_decl(decl);
+ visitor.has_late_bound_regions
+ }
+
+ match node {
+ Node::TraitItem(item) => match item.kind {
+ hir::TraitItemKind::Fn(ref sig, _) => {
+ has_late_bound_regions(tcx, &item.generics, sig.decl)
+ }
+ _ => None,
+ },
+ Node::ImplItem(item) => match item.kind {
+ hir::ImplItemKind::Fn(ref sig, _) => {
+ has_late_bound_regions(tcx, &item.generics, sig.decl)
+ }
+ _ => None,
+ },
+ Node::ForeignItem(item) => match item.kind {
+ hir::ForeignItemKind::Fn(fn_decl, _, ref generics) => {
+ has_late_bound_regions(tcx, generics, fn_decl)
+ }
+ _ => None,
+ },
+ Node::Item(item) => match item.kind {
+ hir::ItemKind::Fn(ref sig, .., ref generics, _) => {
+ has_late_bound_regions(tcx, generics, sig.decl)
+ }
+ _ => None,
+ },
+ _ => None,
+ }
+}
+
+struct AnonConstInParamTyDetector {
+ in_param_ty: bool,
+ found_anon_const_in_param_ty: bool,
+ ct: HirId,
+}
+
+impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
+ fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
+ if let GenericParamKind::Const { ty, default: _ } = p.kind {
+ let prev = self.in_param_ty;
+ self.in_param_ty = true;
+ self.visit_ty(ty);
+ self.in_param_ty = prev;
+ }
+ }
+
+ fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
+ if self.in_param_ty && self.ct == c.hir_id {
+ self.found_anon_const_in_param_ty = true;
+ } else {
+ intravisit::walk_anon_const(self, c)
+ }
+ }
+}
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 0d34a8bfe..0d34a8bfe 100644
--- a/compiler/rustc_typeck/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
index 4d9704617..3f263a6de 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs
@@ -32,8 +32,6 @@ trait RegionExt {
fn id(&self) -> Option<DefId>;
fn shifted(self, amount: u32) -> Region;
-
- fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region;
}
impl RegionExt for Region {
@@ -69,15 +67,6 @@ impl RegionExt for Region {
_ => self,
}
}
-
- fn shifted_out_to_binder(self, binder: ty::DebruijnIndex) -> Region {
- match self {
- Region::LateBound(debruijn, index, id) => {
- Region::LateBound(debruijn.shifted_out_to_binder(binder), index, id)
- }
- _ => self,
- }
- }
}
/// Maps the id of each lifetime reference to the lifetime decl
@@ -101,8 +90,8 @@ struct NamedRegionMap {
late_bound_vars: HirIdMap<Vec<ty::BoundVariableKind>>,
}
-pub(crate) struct LifetimeContext<'a, 'tcx> {
- pub(crate) tcx: TyCtxt<'tcx>,
+struct LifetimeContext<'a, 'tcx> {
+ tcx: TyCtxt<'tcx>,
map: &'a mut NamedRegionMap,
scope: ScopeRef<'a>,
@@ -234,7 +223,7 @@ type ScopeRef<'a> = &'a Scope<'a>;
const ROOT_SCOPE: ScopeRef<'static> = &Scope::Root;
-pub fn provide(providers: &mut ty::query::Providers) {
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
resolve_lifetimes_trait_definition,
resolve_lifetimes,
@@ -326,6 +315,7 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
}
debug!(?rl.defs);
+ debug!(?rl.late_bound_vars);
rl
}
@@ -339,24 +329,25 @@ fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetime
/// This allows us to avoid cycles. Importantly, if we ask for lifetimes for lifetimes that have an owner
/// other than the trait itself (like the trait methods or associated types), then we just use the regular
/// `resolve_lifetimes`.
-fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx ResolveLifetimes {
- let item_id = item_for(tcx, def_id);
- if item_id == def_id {
- let item = tcx.hir().item(hir::ItemId { def_id: item_id });
+fn resolve_lifetimes_for<'tcx>(tcx: TyCtxt<'tcx>, def_id: hir::OwnerId) -> &'tcx ResolveLifetimes {
+ let item_id = item_for(tcx, def_id.def_id);
+ let local_def_id = item_id.owner_id.def_id;
+ if item_id.owner_id == def_id {
+ let item = tcx.hir().item(item_id);
match item.kind {
- hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(item_id),
- _ => tcx.resolve_lifetimes(item_id),
+ hir::ItemKind::Trait(..) => tcx.resolve_lifetimes_trait_definition(local_def_id),
+ _ => tcx.resolve_lifetimes(local_def_id),
}
} else {
- tcx.resolve_lifetimes(item_id)
+ tcx.resolve_lifetimes(local_def_id)
}
}
/// Finds the `Item` that contains the given `LocalDefId`
-fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
+fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> hir::ItemId {
match tcx.hir().find_by_def_id(local_def_id) {
Some(Node::Item(item)) => {
- return item.def_id;
+ return item.item_id();
}
_ => {}
}
@@ -366,7 +357,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
loop {
let node = parent_iter.next().map(|n| n.1);
match node {
- Some(hir::Node::Item(item)) => break item.def_id,
+ Some(hir::Node::Item(item)) => break item.item_id(),
Some(hir::Node::Crate(_)) | None => bug!("Called `item_for` on an Item."),
_ => {}
}
@@ -506,7 +497,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
})
.unzip();
- self.map.late_bound_vars.insert(e.hir_id, binders);
+ self.record_late_bound_vars(e.hir_id, binders);
let scope = Scope::Binder {
hir_id: e.hir_id,
lifetimes,
@@ -530,7 +521,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
match &item.kind {
hir::ItemKind::Impl(hir::Impl { of_trait, .. }) => {
if let Some(of_trait) = of_trait {
- self.map.late_bound_vars.insert(of_trait.hir_ref_id, Vec::default());
+ self.record_late_bound_vars(of_trait.hir_ref_id, Vec::default());
}
}
_ => {}
@@ -566,13 +557,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// their owner, we can keep going until we find the Item that owns that. We then
// conservatively add all resolved lifetimes. Otherwise we run into problems in
// cases like `type Foo<'a> = impl Bar<As = impl Baz + 'a>`.
- for (_hir_id, node) in
- self.tcx.hir().parent_iter(self.tcx.hir().local_def_id_to_hir_id(item.def_id))
- {
+ for (_hir_id, node) in self.tcx.hir().parent_iter(item.owner_id.into()) {
match node {
hir::Node::Item(parent_item) => {
- let resolved_lifetimes: &ResolveLifetimes =
- self.tcx.resolve_lifetimes(item_for(self.tcx, parent_item.def_id));
+ let resolved_lifetimes: &ResolveLifetimes = self.tcx.resolve_lifetimes(
+ item_for(self.tcx, parent_item.owner_id.def_id).owner_id.def_id,
+ );
// We need to add *all* deps, since opaque tys may want them from *us*
for (&owner, defs) in resolved_lifetimes.defs.iter() {
defs.iter().for_each(|(&local_id, region)| {
@@ -583,7 +573,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
resolved_lifetimes.late_bound_vars.iter()
{
late_bound_vars.iter().for_each(|(&local_id, late_bound_vars)| {
- self.map.late_bound_vars.insert(
+ self.record_late_bound_vars(
hir::HirId { owner, local_id },
late_bound_vars.clone(),
);
@@ -614,7 +604,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
- self.map.late_bound_vars.insert(item.hir_id(), vec![]);
+ self.record_late_bound_vars(item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: item.hir_id(),
lifetimes,
@@ -663,7 +653,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
(pair, r)
})
.unzip();
- self.map.late_bound_vars.insert(ty.hir_id, binders);
+ self.record_late_bound_vars(ty.hir_id, binders);
let scope = Scope::Binder {
hir_id: ty.hir_id,
lifetimes,
@@ -817,7 +807,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {}
}
}
- self.map.late_bound_vars.insert(ty.hir_id, vec![]);
+ self.record_late_bound_vars(ty.hir_id, vec![]);
let scope = Scope::Binder {
hir_id: ty.hir_id,
@@ -861,7 +851,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => None,
})
.collect();
- self.map.late_bound_vars.insert(trait_item.hir_id(), vec![]);
+ self.record_late_bound_vars(trait_item.hir_id(), vec![]);
let scope = Scope::Binder {
hir_id: trait_item.hir_id(),
lifetimes,
@@ -897,7 +887,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
Fn(..) => self.visit_early_late(impl_item.hir_id(), &impl_item.generics, |this| {
intravisit::walk_impl_item(this, impl_item)
}),
- TyAlias(ref ty) => {
+ Type(ref ty) => {
let generics = &impl_item.generics;
let lifetimes: FxIndexMap<LocalDefId, Region> = generics
.params
@@ -909,9 +899,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
GenericParamKind::Const { .. } | GenericParamKind::Type { .. } => None,
})
.collect();
- self.map.late_bound_vars.insert(ty.hir_id, vec![]);
+ self.record_late_bound_vars(impl_item.hir_id(), vec![]);
let scope = Scope::Binder {
- hir_id: ty.hir_id,
+ hir_id: impl_item.hir_id(),
lifetimes,
s: self.scope,
scope_type: BinderScopeType::Normal,
@@ -995,13 +985,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
for predicate in generics.predicates {
match predicate {
&hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
+ hir_id,
ref bounded_ty,
bounds,
ref bound_generic_params,
origin,
..
}) => {
- let (lifetimes, binders): (FxIndexMap<LocalDefId, Region>, Vec<_>) =
+ let lifetimes: FxIndexMap<LocalDefId, Region> =
bound_generic_params
.iter()
.filter(|param| {
@@ -1009,19 +1000,23 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
})
.enumerate()
.map(|(late_bound_idx, param)| {
- let pair =
- Region::late(late_bound_idx as u32, this.tcx.hir(), param);
- let r = late_region_as_bound_region(this.tcx, &pair.1);
- (pair, r)
+ Region::late(late_bound_idx as u32, this.tcx.hir(), param)
+ })
+ .collect();
+ let binders: Vec<_> =
+ lifetimes
+ .iter()
+ .map(|(_, region)| {
+ late_region_as_bound_region(this.tcx, region)
})
- .unzip();
- this.map.late_bound_vars.insert(bounded_ty.hir_id, binders.clone());
+ .collect();
+ 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
// will be `Concatenating` anyways, so we don't have to worry about the depth
// being wrong.
let scope = Scope::Binder {
- hir_id: bounded_ty.hir_id,
+ hir_id,
lifetimes,
s: this.scope,
scope_type: BinderScopeType::Normal,
@@ -1089,7 +1084,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
// imagine there's a better way to go about this.
let (binders, scope_type) = self.poly_trait_ref_binder_info();
- self.map.late_bound_vars.insert(*hir_id, binders);
+ self.record_late_bound_vars(*hir_id, binders);
let scope = Scope::Binder {
hir_id: *hir_id,
lifetimes: FxIndexMap::default(),
@@ -1127,7 +1122,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
binders.extend(binders_iter);
debug!(?binders);
- self.map.late_bound_vars.insert(trait_ref.trait_ref.hir_ref_id, 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
@@ -1211,6 +1206,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
}
}
+ fn record_late_bound_vars(&mut self, hir_id: hir::HirId, binder: Vec<ty::BoundVariableKind>) {
+ if let Some(old) = self.map.late_bound_vars.insert(hir_id, binder) {
+ bug!(
+ "overwrote bound vars for {hir_id:?}:\nold={old:?}\nnew={:?}",
+ self.map.late_bound_vars[&hir_id]
+ )
+ }
+ }
+
/// Visits self by adding a scope and handling recursive walk over the contents with `walk`.
///
/// Handles visiting fns and methods. These are a bit complicated because we must distinguish
@@ -1268,7 +1272,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
late_region_as_bound_region(self.tcx, &pair.1)
})
.collect();
- self.map.late_bound_vars.insert(hir_id, binders);
+ self.record_late_bound_vars(hir_id, binders);
let scope = Scope::Binder {
hir_id,
lifetimes,
@@ -1315,15 +1319,44 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// regular fns.
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
&& let hir::LifetimeName::Param(_, hir::ParamName::Fresh) = lifetime_ref.name
- && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner)
+ && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
- rustc_session::parse::feature_err(
+ let mut diag = rustc_session::parse::feature_err(
&self.tcx.sess.parse_sess,
sym::anonymous_lifetime_in_impl_trait,
lifetime_ref.span,
"anonymous lifetimes in `impl Trait` are unstable",
- ).emit();
+ );
+
+ match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) {
+ Some(generics) => {
+
+ let new_param_sugg_tuple;
+
+ new_param_sugg_tuple = match generics.span_for_param_suggestion() {
+ Some(_) => {
+ Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()))
+ },
+ None => Some((generics.span, "<'a>".to_owned()))
+ };
+
+ let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())];
+
+ if let Some(new_tuple) = new_param_sugg_tuple{
+ multi_sugg_vec.push(new_tuple);
+ }
+
+ diag.span_label(lifetime_ref.span, "expected named lifetime parameter");
+ diag.multipart_suggestion("consider introducing a named lifetime parameter",
+ multi_sugg_vec,
+ rustc_errors::Applicability::MaybeIncorrect);
+
+ },
+ None => { }
+ }
+
+ diag.emit();
return;
}
scope = s;
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
new file mode 100644
index 000000000..2e84e1d01
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -0,0 +1,707 @@
+use crate::astconv::AstConv;
+use crate::bounds::Bounds;
+use crate::collect::ItemCtxt;
+use crate::constrained_generic_params as cgp;
+use hir::{HirId, Node};
+use rustc_data_structures::fx::FxIndexSet;
+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_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::ToPredicate;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::symbol::{sym, Ident};
+use rustc_span::{Span, DUMMY_SP};
+
+#[derive(Debug)]
+struct OnlySelfBounds(bool);
+
+/// Returns a list of all type predicates (explicit and implicit) for the definition with
+/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
+/// `Self: Trait` predicates for traits.
+pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+ let mut result = tcx.predicates_defined_on(def_id);
+
+ if tcx.is_trait(def_id) {
+ // For traits, add `Self: Trait` predicate. This is
+ // not part of the predicates that a user writes, but it
+ // is something that one must prove in order to invoke a
+ // method or project an associated type.
+ //
+ // In the chalk setup, this predicate is not part of the
+ // "predicates" for a trait item. But it is useful in
+ // rustc because if you directly (e.g.) invoke a trait
+ // method like `Trait::method(...)`, you must naturally
+ // prove that the trait applies to the types that were
+ // used, and adding the predicate into this list ensures
+ // that this is done.
+ //
+ // We use a DUMMY_SP here as a way to signal trait bounds that come
+ // from the trait itself that *shouldn't* be shown as the source of
+ // an obligation and instead be skipped. Otherwise we'd use
+ // `tcx.def_span(def_id);`
+
+ let constness = if tcx.has_attr(def_id, sym::const_trait) {
+ ty::BoundConstness::ConstIfConst
+ } else {
+ ty::BoundConstness::NotConst
+ };
+
+ let span = rustc_span::DUMMY_SP;
+ result.predicates =
+ tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
+ ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
+ span,
+ ))));
+ }
+ debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
+ result
+}
+
+/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
+/// N.B., this does not include any implied/inferred constraints.
+#[instrument(level = "trace", skip(tcx), ret)]
+fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+ use rustc_hir::*;
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let node = tcx.hir().get(hir_id);
+
+ let mut is_trait = None;
+ let mut is_default_impl_trait = None;
+
+ let icx = ItemCtxt::new(tcx, def_id);
+
+ const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
+
+ // We use an `IndexSet` to preserves order of insertion.
+ // Preserving the order of insertion is important here so as not to break UI tests.
+ let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
+
+ let ast_generics = match node {
+ Node::TraitItem(item) => item.generics,
+
+ Node::ImplItem(item) => item.generics,
+
+ Node::Item(item) => {
+ match item.kind {
+ ItemKind::Impl(ref impl_) => {
+ if impl_.defaultness.is_default() {
+ is_default_impl_trait = tcx.impl_trait_ref(def_id).map(ty::Binder::dummy);
+ }
+ &impl_.generics
+ }
+ ItemKind::Fn(.., ref generics, _)
+ | ItemKind::TyAlias(_, ref generics)
+ | ItemKind::Enum(_, ref generics)
+ | ItemKind::Struct(_, ref generics)
+ | ItemKind::Union(_, ref generics) => *generics,
+
+ ItemKind::Trait(_, _, ref generics, ..) => {
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id));
+ *generics
+ }
+ ItemKind::TraitAlias(ref generics, _) => {
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id));
+ *generics
+ }
+ ItemKind::OpaqueTy(OpaqueTy {
+ origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
+ ..
+ }) => {
+ // return-position impl trait
+ //
+ // We don't inherit predicates from the parent here:
+ // If we have, say `fn f<'a, T: 'a>() -> impl Sized {}`
+ // then the return type is `f::<'static, T>::{{opaque}}`.
+ //
+ // If we inherited the predicates of `f` then we would
+ // require that `T: 'static` to show that the return
+ // type is well-formed.
+ //
+ // The only way to have something with this opaque type
+ // is from the return type of the containing function,
+ // which will ensure that the function's predicates
+ // hold.
+ return ty::GenericPredicates { parent: None, predicates: &[] };
+ }
+ ItemKind::OpaqueTy(OpaqueTy {
+ ref generics,
+ origin: hir::OpaqueTyOrigin::TyAlias,
+ ..
+ }) => {
+ // type-alias impl trait
+ generics
+ }
+
+ _ => NO_GENERICS,
+ }
+ }
+
+ Node::ForeignItem(item) => match item.kind {
+ ForeignItemKind::Static(..) => NO_GENERICS,
+ ForeignItemKind::Fn(_, _, ref generics) => *generics,
+ ForeignItemKind::Type => NO_GENERICS,
+ },
+
+ _ => NO_GENERICS,
+ };
+
+ let generics = tcx.generics_of(def_id);
+ let parent_count = generics.parent_count as u32;
+ let has_own_self = generics.has_self && parent_count == 0;
+
+ // Below we'll consider the bounds on the type parameters (including `Self`)
+ // and the explicit where-clauses, but to get the full set of predicates
+ // on a trait we need to add in the supertrait bounds and bounds found on
+ // associated types.
+ if let Some(_trait_ref) = is_trait {
+ predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
+ }
+
+ // In default impls, we can assume that the self type implements
+ // the trait. So in:
+ //
+ // default impl Foo for Bar { .. }
+ //
+ // we add a default where clause `Foo: Bar`. We do a similar thing for traits
+ // (see below). Recall that a default impl is not itself an impl, but rather a
+ // set of defaults that can be incorporated into another impl.
+ if let Some(trait_ref) = is_default_impl_trait {
+ predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id)));
+ }
+
+ // Collect the region predicates that were declared inline as
+ // well. In the case of parameters declared on a fn or method, we
+ // have to be careful to only iterate over early-bound regions.
+ let mut index = parent_count
+ + has_own_self as u32
+ + super::early_bound_lifetimes_from_generics(tcx, ast_generics).count() as u32;
+
+ trace!(?predicates);
+ trace!(?ast_generics);
+
+ // Collect the predicates that were written inline by the user on each
+ // type parameter (e.g., `<T: Foo>`).
+ for param in ast_generics.params {
+ match param.kind {
+ // We already dealt with early bound lifetimes above.
+ GenericParamKind::Lifetime { .. } => (),
+ GenericParamKind::Type { .. } => {
+ let name = param.name.ident().name;
+ let param_ty = ty::ParamTy::new(index, name).to_ty(tcx);
+ index += 1;
+
+ let mut bounds = Bounds::default();
+ // Params are implicitly sized unless a `?Sized` bound is found
+ <dyn AstConv<'_>>::add_implicitly_sized(
+ &icx,
+ &mut bounds,
+ &[],
+ Some((param.hir_id, ast_generics.predicates)),
+ param.span,
+ );
+ trace!(?bounds);
+ predicates.extend(bounds.predicates(tcx, param_ty));
+ trace!(?predicates);
+ }
+ GenericParamKind::Const { .. } => {
+ // Bounds on const parameters are currently not possible.
+ index += 1;
+ }
+ }
+ }
+
+ trace!(?predicates);
+ // Add in the bounds that appear in the where-clause.
+ for predicate in ast_generics.predicates {
+ match predicate {
+ hir::WherePredicate::BoundPredicate(bound_pred) => {
+ let ty = icx.to_ty(bound_pred.bounded_ty);
+ let bound_vars = icx.tcx.late_bound_vars(bound_pred.hir_id);
+
+ // Keep the type around in a dummy predicate, in case of no bounds.
+ // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
+ // is still checked for WF.
+ if bound_pred.bounds.is_empty() {
+ if let ty::Param(_) = ty.kind() {
+ // This is a `where T:`, which can be in the HIR from the
+ // transformation that moves `?Sized` to `T`'s declaration.
+ // We can skip the predicate because type parameters are
+ // trivially WF, but also we *should*, to avoid exposing
+ // users who never wrote `where Type:,` themselves, to
+ // compiler/tooling bugs from not handling WF predicates.
+ } else {
+ let span = bound_pred.bounded_ty.span;
+ let predicate = ty::Binder::bind_with_vars(
+ ty::PredicateKind::WellFormed(ty.into()),
+ bound_vars,
+ );
+ predicates.insert((predicate.to_predicate(tcx), span));
+ }
+ }
+
+ let mut bounds = Bounds::default();
+ <dyn AstConv<'_>>::add_bounds(
+ &icx,
+ ty,
+ bound_pred.bounds.iter(),
+ &mut bounds,
+ bound_vars,
+ );
+ predicates.extend(bounds.predicates(tcx, ty));
+ }
+
+ hir::WherePredicate::RegionPredicate(region_pred) => {
+ let r1 = <dyn AstConv<'_>>::ast_region_to_region(&icx, &region_pred.lifetime, None);
+ predicates.extend(region_pred.bounds.iter().map(|bound| {
+ let (r2, span) = match bound {
+ hir::GenericBound::Outlives(lt) => {
+ (<dyn AstConv<'_>>::ast_region_to_region(&icx, lt, None), lt.span)
+ }
+ _ => bug!(),
+ };
+ let pred = ty::Binder::dummy(ty::PredicateKind::RegionOutlives(
+ ty::OutlivesPredicate(r1, r2),
+ ))
+ .to_predicate(icx.tcx);
+
+ (pred, span)
+ }))
+ }
+
+ hir::WherePredicate::EqPredicate(..) => {
+ // FIXME(#20041)
+ }
+ }
+ }
+
+ if tcx.features().generic_const_exprs {
+ predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
+ }
+
+ let mut predicates: Vec<_> = predicates.into_iter().collect();
+
+ // Subtle: before we store the predicates into the tcx, we
+ // sort them so that predicates like `T: Foo<Item=U>` come
+ // before uses of `U`. This avoids false ambiguity errors
+ // 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 trait_ref = tcx.impl_trait_ref(def_id);
+ cgp::setup_constraining_predicates(
+ tcx,
+ &mut predicates,
+ trait_ref,
+ &mut cgp::parameters_for_impl(self_ty, trait_ref),
+ );
+ }
+
+ ty::GenericPredicates {
+ parent: generics.parent,
+ predicates: tcx.arena.alloc_from_iter(predicates),
+ }
+}
+
+fn const_evaluatable_predicates_of<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+) -> FxIndexSet<(ty::Predicate<'tcx>, Span)> {
+ struct ConstCollector<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+ }
+
+ impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
+ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) {
+ let def_id = self.tcx.hir().local_def_id(c.hir_id);
+ let ct = ty::Const::from_anon_const(self.tcx, def_id);
+ if let ty::ConstKind::Unevaluated(_) = ct.kind() {
+ let span = self.tcx.hir().span(c.hir_id);
+ self.preds.insert((
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
+ .to_predicate(self.tcx),
+ span,
+ ));
+ }
+ }
+
+ fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::AnonConst) {
+ // Do not look into const param defaults,
+ // these get checked when they are actually instantiated.
+ //
+ // We do not want the following to error:
+ //
+ // struct Foo<const N: usize, const M: usize = { N + 1 }>;
+ // struct Bar<const N: usize>(Foo<N, 3>);
+ }
+ }
+
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let node = tcx.hir().get(hir_id);
+
+ let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
+ if let hir::Node::Item(item) = node && let hir::ItemKind::Impl(ref impl_) = item.kind {
+ if let Some(of_trait) = &impl_.of_trait {
+ debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id);
+ collector.visit_trait_ref(of_trait);
+ }
+
+ debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id);
+ collector.visit_ty(impl_.self_ty);
+ }
+
+ if let Some(generics) = node.generics() {
+ debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id);
+ collector.visit_generics(generics);
+ }
+
+ if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) {
+ debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id);
+ collector.visit_fn_decl(fn_sig.decl);
+ }
+ debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds);
+
+ collector.preds
+}
+
+pub(super) fn trait_explicit_predicates_and_bounds(
+ tcx: TyCtxt<'_>,
+ def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+ assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
+ gather_explicit_predicates_of(tcx, def_id.to_def_id())
+}
+
+pub(super) fn explicit_predicates_of<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: DefId,
+) -> ty::GenericPredicates<'tcx> {
+ let def_kind = tcx.def_kind(def_id);
+ if let DefKind::Trait = def_kind {
+ // Remove bounds on associated types from the predicates, they will be
+ // returned by `explicit_item_bounds`.
+ let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
+ let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+
+ let is_assoc_item_ty = |ty: Ty<'tcx>| {
+ // For a predicate from a where clause to become a bound on an
+ // associated type:
+ // * It must use the identity substs of the item.
+ // * Since any generic parameters on the item are not in scope,
+ // this means that the item is not a GAT, and its identity
+ // substs are the same as the trait's.
+ // * It must be an associated type for this trait (*not* a
+ // supertrait).
+ if let ty::Projection(projection) = ty.kind() {
+ projection.substs == trait_identity_substs
+ && tcx.associated_item(projection.item_def_id).container_id(tcx) == def_id
+ } else {
+ false
+ }
+ };
+
+ let predicates: Vec<_> = predicates_and_bounds
+ .predicates
+ .iter()
+ .copied()
+ .filter(|(pred, _)| match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
+ ty::PredicateKind::Projection(proj) => {
+ !is_assoc_item_ty(proj.projection_ty.self_ty())
+ }
+ ty::PredicateKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
+ _ => true,
+ })
+ .collect();
+ if predicates.len() == predicates_and_bounds.predicates.len() {
+ predicates_and_bounds
+ } else {
+ ty::GenericPredicates {
+ parent: predicates_and_bounds.parent,
+ predicates: tcx.arena.alloc_slice(&predicates),
+ }
+ }
+ } else {
+ if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ if tcx.hir().opt_const_param_default_param_hir_id(hir_id).is_some() {
+ // In `generics_of` we set the generics' parent to be our parent's parent which means that
+ // we lose out on the predicates of our actual parent if we dont return those predicates here.
+ // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
+ //
+ // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
+ // ^^^ ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
+ // ^^^ explicit_predicates_of on
+ // parent item we dont have set as the
+ // parent of generics returned by `generics_of`
+ //
+ // In the above code we want the anon const to have predicates in its param env for `T: Trait`
+ let item_def_id = tcx.hir().get_parent_item(hir_id);
+ // In the above code example we would be calling `explicit_predicates_of(Foo)` here
+ return tcx.explicit_predicates_of(item_def_id);
+ }
+ }
+ gather_explicit_predicates_of(tcx, def_id)
+ }
+}
+
+/// Ensures that the super-predicates of the trait with a `DefId`
+/// of `trait_def_id` are converted and stored. This also ensures that
+/// the transitive super-predicates are converted.
+pub(super) fn super_predicates_of(
+ tcx: TyCtxt<'_>,
+ trait_def_id: DefId,
+) -> ty::GenericPredicates<'_> {
+ tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
+}
+
+/// Ensures that the super-predicates of the trait with a `DefId`
+/// of `trait_def_id` are converted and stored. This also ensures that
+/// the transitive super-predicates are converted.
+pub(super) fn super_predicates_that_define_assoc_type(
+ tcx: TyCtxt<'_>,
+ (trait_def_id, assoc_name): (DefId, Option<Ident>),
+) -> ty::GenericPredicates<'_> {
+ if trait_def_id.is_local() {
+ debug!("local trait");
+ let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
+
+ let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
+ bug!("trait_node_id {} is not an item", trait_hir_id);
+ };
+
+ let (generics, bounds) = match item.kind {
+ hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => (generics, supertraits),
+ hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits),
+ _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
+ };
+
+ let icx = ItemCtxt::new(tcx, trait_def_id);
+
+ // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
+ let self_param_ty = tcx.types.self_param;
+ let superbounds1 = if let Some(assoc_name) = assoc_name {
+ <dyn AstConv<'_>>::compute_bounds_that_match_assoc_type(
+ &icx,
+ self_param_ty,
+ bounds,
+ assoc_name,
+ )
+ } else {
+ <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds)
+ };
+
+ let superbounds1 = superbounds1.predicates(tcx, self_param_ty);
+
+ // Convert any explicit superbounds in the where-clause,
+ // e.g., `trait Foo where Self: Bar`.
+ // In the case of trait aliases, however, we include all bounds in the where-clause,
+ // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
+ // as one of its "superpredicates".
+ let is_trait_alias = tcx.is_trait_alias(trait_def_id);
+ let superbounds2 = icx.type_parameter_bounds_in_generics(
+ generics,
+ item.hir_id(),
+ self_param_ty,
+ OnlySelfBounds(!is_trait_alias),
+ assoc_name,
+ );
+
+ // Combine the two lists to form the complete set of superbounds:
+ let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
+ debug!(?superbounds);
+
+ // Now require that immediate supertraits are converted,
+ // which will, in turn, reach indirect supertraits.
+ if assoc_name.is_none() {
+ // Now require that immediate supertraits are converted,
+ // which will, in turn, reach indirect supertraits.
+ for &(pred, span) in superbounds {
+ debug!("superbound: {:?}", pred);
+ if let ty::PredicateKind::Trait(bound) = pred.kind().skip_binder() {
+ tcx.at(span).super_predicates_of(bound.def_id());
+ }
+ }
+ }
+
+ ty::GenericPredicates { parent: None, predicates: superbounds }
+ } else {
+ // if `assoc_name` is None, then the query should've been redirected to an
+ // external provider
+ assert!(assoc_name.is_some());
+ tcx.super_predicates_of(trait_def_id)
+ }
+}
+
+/// Returns the predicates defined on `item_def_id` of the form
+/// `X: Foo` where `X` is the type parameter `def_id`.
+#[instrument(level = "trace", skip(tcx))]
+pub(super) fn type_param_predicates(
+ tcx: TyCtxt<'_>,
+ (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
+) -> ty::GenericPredicates<'_> {
+ use rustc_hir::*;
+
+ // In the AST, bounds can derive from two places. Either
+ // written inline like `<T: Foo>` or in a where-clause like
+ // `where T: Foo`.
+
+ let param_id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let param_owner = tcx.hir().ty_param_owner(def_id);
+ let generics = tcx.generics_of(param_owner);
+ let index = generics.param_def_id_to_index[&def_id.to_def_id()];
+ let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
+
+ // Don't look for bounds where the type parameter isn't in scope.
+ let parent = if item_def_id == param_owner.to_def_id() {
+ None
+ } else {
+ tcx.generics_of(item_def_id).parent
+ };
+
+ let mut result = parent
+ .map(|parent| {
+ let icx = ItemCtxt::new(tcx, parent);
+ icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
+ })
+ .unwrap_or_default();
+ let mut extend = None;
+
+ let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
+ let ast_generics = match tcx.hir().get(item_hir_id) {
+ Node::TraitItem(item) => &item.generics,
+
+ Node::ImplItem(item) => &item.generics,
+
+ Node::Item(item) => {
+ match item.kind {
+ ItemKind::Fn(.., ref generics, _)
+ | ItemKind::Impl(hir::Impl { ref generics, .. })
+ | ItemKind::TyAlias(_, ref generics)
+ | ItemKind::OpaqueTy(OpaqueTy {
+ ref generics,
+ origin: hir::OpaqueTyOrigin::TyAlias,
+ ..
+ })
+ | ItemKind::Enum(_, ref generics)
+ | ItemKind::Struct(_, ref generics)
+ | ItemKind::Union(_, ref generics) => generics,
+ ItemKind::Trait(_, _, ref generics, ..) => {
+ // Implied `Self: Trait` and supertrait bounds.
+ if param_id == item_hir_id {
+ let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
+ extend =
+ Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
+ }
+ generics
+ }
+ _ => return result,
+ }
+ }
+
+ Node::ForeignItem(item) => match item.kind {
+ ForeignItemKind::Fn(_, _, ref generics) => generics,
+ _ => return result,
+ },
+
+ _ => return result,
+ };
+
+ let icx = ItemCtxt::new(tcx, item_def_id);
+ let extra_predicates = extend.into_iter().chain(
+ icx.type_parameter_bounds_in_generics(
+ ast_generics,
+ param_id,
+ ty,
+ OnlySelfBounds(true),
+ Some(assoc_name),
+ )
+ .into_iter()
+ .filter(|(predicate, _)| match predicate.kind().skip_binder() {
+ ty::PredicateKind::Trait(data) => data.self_ty().is_param(index),
+ _ => false,
+ }),
+ );
+ result.predicates =
+ tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(extra_predicates));
+ result
+}
+
+impl<'tcx> ItemCtxt<'tcx> {
+ /// Finds bounds from `hir::Generics`. This requires scanning through the
+ /// AST. We do this to avoid having to convert *all* the bounds, which
+ /// would create artificial cycles. Instead, we can only convert the
+ /// bounds for a type parameter `X` if `X::Foo` is used.
+ #[instrument(level = "trace", skip(self, ast_generics))]
+ fn type_parameter_bounds_in_generics(
+ &self,
+ ast_generics: &'tcx hir::Generics<'tcx>,
+ param_id: hir::HirId,
+ ty: Ty<'tcx>,
+ only_self_bounds: OnlySelfBounds,
+ assoc_name: Option<Ident>,
+ ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+ let param_def_id = self.tcx.hir().local_def_id(param_id).to_def_id();
+ trace!(?param_def_id);
+ ast_generics
+ .predicates
+ .iter()
+ .filter_map(|wp| match *wp {
+ hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+ _ => None,
+ })
+ .flat_map(|bp| {
+ let bt = if bp.is_param_bound(param_def_id) {
+ Some(ty)
+ } else if !only_self_bounds.0 {
+ Some(self.to_ty(bp.bounded_ty))
+ } else {
+ None
+ };
+ let bvars = self.tcx.late_bound_vars(bp.hir_id);
+
+ bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter(
+ |(_, b, _)| match assoc_name {
+ Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name),
+ None => true,
+ },
+ )
+ })
+ .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars))
+ .collect()
+ }
+
+ #[instrument(level = "trace", skip(self))]
+ fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
+ match b {
+ hir::GenericBound::Trait(poly_trait_ref, _) => {
+ let trait_ref = &poly_trait_ref.trait_ref;
+ if let Some(trait_did) = trait_ref.trait_def_id() {
+ self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
+ } else {
+ false
+ }
+ }
+ _ => false,
+ }
+ }
+}
+
+/// Converts a specific `GenericBound` from the AST into a set of
+/// predicates that apply to the self type. A vector is returned
+/// because this can be anywhere from zero predicates (`T: ?Sized` adds no
+/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar`
+/// and `<T as Bar>::X == i32`).
+fn predicates_from_bound<'tcx>(
+ astconv: &dyn AstConv<'tcx>,
+ param_ty: Ty<'tcx>,
+ bound: &'tcx hir::GenericBound<'tcx>,
+ bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+) -> Vec<(ty::Predicate<'tcx>, Span)> {
+ let mut bounds = Bounds::default();
+ astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars);
+ bounds.predicates(astconv.tcx(), param_ty).collect()
+}
diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index a1d1f125f..c29a645eb 100644
--- a/compiler/rustc_typeck/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -284,7 +284,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
icx.to_ty(ty)
}
}
- ImplItemKind::TyAlias(ty) => {
+ ImplItemKind::Type(ty) => {
if tcx.impl_trait_ref(tcx.hir().get_parent_item(hir_id)).is_none() {
check_feature_inherent_assoc_ty(tcx, item.span);
}
@@ -319,7 +319,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
}
ItemKind::TyAlias(self_ty, _) => icx.to_ty(self_ty),
- ItemKind::Impl(hir::Impl { self_ty, .. }) => icx.to_ty(*self_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()
+ },
+ _ => icx.to_ty(*self_ty),
+ }
+ },
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
tcx.mk_fn_def(def_id.to_def_id(), substs)
@@ -340,10 +348,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
..
}) => {
if in_trait {
- span_bug!(item.span, "impl-trait in trait has no default")
- } else {
- find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+ assert!(tcx.impl_defaultness(owner).has_value());
}
+ find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
}
ItemKind::Trait(..)
| ItemKind::TraitAlias(..)
@@ -493,8 +500,10 @@ 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(tcx.generics_of(assoc_item.def_id).params[idx].def_id)
+ 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)
} else {
// FIXME(associated_const_equality): add a useful error message here.
tcx.ty_error_with_message(
@@ -564,6 +573,11 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
/// checked against it (we also carry the span of that first
/// type).
found: Option<ty::OpaqueHiddenType<'tcx>>,
+
+ /// In the presence of dead code, typeck may figure out a hidden type
+ /// while borrowck will now. We collect these cases here and check at
+ /// the end that we actually found a type that matches (modulo regions).
+ typeck_types: Vec<ty::OpaqueHiddenType<'tcx>>,
}
impl ConstraintLocator<'_> {
@@ -590,18 +604,23 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error() });
return;
}
- if !tables.concrete_opaque_types.contains_key(&self.def_id) {
+ let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
debug!("no constraints in typeck results");
return;
+ };
+ if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
+ self.typeck_types.push(typeck_hidden_ty);
}
+
// Use borrowck to get the type with unerased regions.
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
debug!(?concrete_opaque_types);
if let Some(&concrete_type) = concrete_opaque_types.get(&self.def_id) {
debug!(?concrete_type, "found constraint");
- if let Some(prev) = self.found {
- if concrete_type.ty != prev.ty && !(concrete_type, prev).references_error() {
+ 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();
}
} else {
self.found = Some(concrete_type);
@@ -624,31 +643,31 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
intravisit::walk_expr(self, ex);
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.def_id);
+ trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
- if it.def_id != self.def_id {
- self.check(it.def_id);
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
intravisit::walk_item(self, it);
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.def_id);
+ trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
- if it.def_id != self.def_id {
- self.check(it.def_id);
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
intravisit::walk_impl_item(self, it);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.def_id);
- self.check(it.def_id);
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
intravisit::walk_trait_item(self, it);
}
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let scope = tcx.hir().get_defining_scope(hir_id);
- let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None };
+ let mut locator = ConstraintLocator { def_id: def_id, tcx, found: None, typeck_types: vec![] };
debug!(?scope);
@@ -678,16 +697,32 @@ fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> T
}
}
- match locator.found {
- Some(hidden) => hidden.ty,
- None => {
- tcx.sess.emit_err(UnconstrainedOpaqueType {
- span: tcx.def_span(def_id),
- name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
- });
- tcx.ty_error()
+ let Some(hidden) = locator.found else {
+ tcx.sess.emit_err(UnconstrainedOpaqueType {
+ span: tcx.def_span(def_id),
+ name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
+ what: match tcx.hir().get(scope) {
+ _ if scope == hir::CRATE_HIR_ID => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
+ Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
+ _ => "item",
+ },
+ });
+ return tcx.ty_error();
+ };
+
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if tcx.erase_regions(concrete_type.ty) != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, tcx);
+ }
}
}
+
+ hidden.ty
}
fn find_opaque_ty_constraints_for_rpit(
@@ -743,24 +778,24 @@ fn find_opaque_ty_constraints_for_rpit(
intravisit::walk_expr(self, ex);
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
- trace!(?it.def_id);
+ trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
- if it.def_id != self.def_id {
- self.check(it.def_id);
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
intravisit::walk_item(self, it);
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
- trace!(?it.def_id);
+ trace!(?it.owner_id);
// The opaque type itself or its children are not within its reveal scope.
- if it.def_id != self.def_id {
- self.check(it.def_id);
+ if it.owner_id.def_id != self.def_id {
+ self.check(it.owner_id.def_id);
intravisit::walk_impl_item(self, it);
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
- trace!(?it.def_id);
- self.check(it.def_id);
+ trace!(?it.owner_id);
+ self.check(it.owner_id.def_id);
intravisit::walk_trait_item(self, it);
}
}
@@ -788,20 +823,15 @@ fn find_opaque_ty_constraints_for_rpit(
// the `concrete_opaque_types` table.
tcx.ty_error()
} else {
- table
- .concrete_opaque_types
- .get(&def_id)
- .copied()
- .unwrap_or_else(|| {
- // We failed to resolve the opaque type or it
- // resolves to itself. We interpret this as the
- // no values of the hidden type ever being constructed,
- // so we can just make the hidden type be `!`.
- // For backwards compatibility reasons, we fall back to
- // `()` until we the diverging default is changed.
- Some(tcx.mk_diverging_default())
- })
- .expect("RPIT always have a hidden type from typeck")
+ table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // We failed to resolve the opaque type or it
+ // resolves to itself. We interpret this as the
+ // no values of the hidden type ever being constructed,
+ // so we can just make the hidden type be `!`.
+ // For backwards compatibility reasons, we fall back to
+ // `()` until we the diverging default is changed.
+ tcx.mk_diverging_default()
+ })
}
})
}
diff --git a/compiler/rustc_typeck/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 8428e4664..213b89fc7 100644
--- a/compiler/rustc_typeck/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -114,9 +114,9 @@ pub fn identify_constrained_generic_params<'tcx>(
/// ```
/// The impl's predicates are collected from left to right. Ignoring
/// the implicit `Sized` bounds, these are
-/// * T: Debug
-/// * U: Iterator
-/// * <U as Iterator>::Item = T -- a desugared ProjectionPredicate
+/// * `T: Debug`
+/// * `U: Iterator`
+/// * `<U as Iterator>::Item = T` -- a desugared ProjectionPredicate
///
/// When we, for example, try to go over the trait-reference
/// `IntoIter<u32> as Trait`, we substitute the impl parameters with fresh
@@ -132,12 +132,16 @@ pub fn identify_constrained_generic_params<'tcx>(
///
/// We *do* have to be somewhat careful when projection targets contain
/// projections themselves, for example in
+///
+/// ```ignore (illustrative)
/// impl<S,U,V,W> Trait for U where
/// /* 0 */ S: Iterator<Item = U>,
/// /* - */ U: Iterator,
/// /* 1 */ <U as Iterator>::Item: ToOwned<Owned=(W,<V as Iterator>::Item)>
/// /* 2 */ W: Iterator<Item = V>
/// /* 3 */ V: Debug
+/// ```
+///
/// we have to evaluate the projections in the order I wrote them:
/// `V: Debug` requires `V` to be evaluated. The only projection that
/// *determines* `V` is 2 (1 contains it, but *does not determine it*,
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 0d2e66745..d5b1a7ce1 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1,23 +1,13 @@
-//! Errors emitted by typeck.
+//! Errors emitted by `rustc_hir_analysis`.
+
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
+use rustc_errors::{IntoDiagnostic, MultiSpan};
+use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_middle::ty::Ty;
-use rustc_session::SessionDiagnostic;
use rustc_span::{symbol::Ident, Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(typeck::field_multiply_specified_in_initializer, code = "E0062")]
-pub struct FieldMultiplySpecifiedInInitializer {
- #[primary_span]
- #[label]
- pub span: Span,
- #[label(typeck::previous_use_label)]
- pub prev_span: Span,
- pub ident: Ident,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::unrecognized_atomic_operation, code = "E0092")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")]
pub struct UnrecognizedAtomicOperation<'a> {
#[primary_span]
#[label]
@@ -25,8 +15,8 @@ pub struct UnrecognizedAtomicOperation<'a> {
pub op: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
#[primary_span]
#[label]
@@ -36,8 +26,8 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
pub descr: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::unrecognized_intrinsic_function, code = "E0093")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_unrecognized_intrinsic_function, code = "E0093")]
pub struct UnrecognizedIntrinsicFunction {
#[primary_span]
#[label]
@@ -45,93 +35,86 @@ pub struct UnrecognizedIntrinsicFunction {
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
pub struct LifetimesOrBoundsMismatchOnTrait {
#[primary_span]
#[label]
pub span: Span,
- #[label(typeck::generics_label)]
+ #[label(generics_label)]
pub generics_span: Option<Span>,
pub item_kind: &'static str,
pub ident: Ident,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::drop_impl_on_wrong_item, code = "E0120")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_drop_impl_on_wrong_item, code = "E0120")]
pub struct DropImplOnWrongItem {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::field_already_declared, code = "E0124")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_field_already_declared, code = "E0124")]
pub struct FieldAlreadyDeclared {
pub field_name: Ident,
#[primary_span]
#[label]
pub span: Span,
- #[label(typeck::previous_decl_label)]
+ #[label(previous_decl_label)]
pub prev_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_copy_impl_on_type_with_dtor, code = "E0184")]
pub struct CopyImplOnTypeWithDtor {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::multiple_relaxed_default_bounds, code = "E0203")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_multiple_relaxed_default_bounds, code = "E0203")]
pub struct MultipleRelaxedDefaultBounds {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::copy_impl_on_non_adt, code = "E0206")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_copy_impl_on_non_adt, code = "E0206")]
pub struct CopyImplOnNonAdt {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::trait_object_declared_with_no_traits, code = "E0224")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")]
pub struct TraitObjectDeclaredWithNoTraits {
#[primary_span]
pub span: Span,
- #[label(typeck::alias_span)]
+ #[label(alias_span)]
pub trait_alias_span: Option<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0227")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_ambiguous_lifetime_bound, code = "E0227")]
pub struct AmbiguousLifetimeBound {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::assoc_type_binding_not_allowed, code = "E0229")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_assoc_type_binding_not_allowed, code = "E0229")]
pub struct AssocTypeBindingNotAllowed {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::functional_record_update_on_non_struct, code = "E0436")]
-pub struct FunctionalRecordUpdateOnNonStruct {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::typeof_reserved_keyword_used, code = "E0516")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_typeof_reserved_keyword_used, code = "E0516")]
pub struct TypeofReservedKeywordUsed<'tcx> {
pub ty: Ty<'tcx>,
#[primary_span]
@@ -141,104 +124,26 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
pub opt_sugg: Option<(Span, Applicability)>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
-pub struct ReturnStmtOutsideOfFnBody {
- #[primary_span]
- pub span: Span,
- #[label(typeck::encl_body_label)]
- pub encl_body_span: Option<Span>,
- #[label(typeck::encl_fn_label)]
- pub encl_fn_span: Option<Span>,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::yield_expr_outside_of_generator, code = "E0627")]
-pub struct YieldExprOutsideOfGenerator {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::struct_expr_non_exhaustive, code = "E0639")]
-pub struct StructExprNonExhaustive {
- #[primary_span]
- pub span: Span,
- pub what: &'static str,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::method_call_on_unknown_type, code = "E0699")]
-pub struct MethodCallOnUnknownType {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::value_of_associated_struct_already_specified, code = "E0719")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_value_of_associated_struct_already_specified, code = "E0719")]
pub struct ValueOfAssociatedStructAlreadySpecified {
#[primary_span]
#[label]
pub span: Span,
- #[label(typeck::previous_bound_label)]
+ #[label(previous_bound_label)]
pub prev_span: Span,
pub item_name: Ident,
pub def_path: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::address_of_temporary_taken, code = "E0745")]
-pub struct AddressOfTemporaryTaken {
- #[primary_span]
- #[label]
- pub span: Span,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub enum AddReturnTypeSuggestion {
- #[suggestion(
- typeck::add_return_type_add,
- code = "-> {found} ",
- applicability = "machine-applicable"
- )]
- Add {
- #[primary_span]
- span: Span,
- found: String,
- },
- #[suggestion(
- typeck::add_return_type_missing_here,
- code = "-> _ ",
- applicability = "has-placeholders"
- )]
- MissingHere {
- #[primary_span]
- span: Span,
- },
-}
-
-#[derive(SessionSubdiagnostic)]
-pub enum ExpectedReturnTypeLabel<'tcx> {
- #[label(typeck::expected_default_return_type)]
- Unit {
- #[primary_span]
- span: Span,
- },
- #[label(typeck::expected_return_type)]
- Other {
- #[primary_span]
- span: Span,
- expected: Ty<'tcx>,
- },
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(typeck::unconstrained_opaque_type)]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_unconstrained_opaque_type)]
#[note]
pub struct UnconstrainedOpaqueType {
#[primary_span]
pub span: Span,
pub name: Symbol,
+ pub what: &'static str,
}
pub struct MissingTypeParams {
@@ -249,12 +154,12 @@ pub struct MissingTypeParams {
pub empty_generic_args: bool,
}
-// Manual implementation of `SessionDiagnostic` to be able to call `span_to_snippet`.
-impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
+// Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`.
+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::typeck::missing_type_params,
+ rustc_errors::fluent::hir_analysis_missing_type_params,
error_code!(E0393),
);
err.set_arg("parameterCount", self.missing_type_params.len());
@@ -267,7 +172,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
.join(", "),
);
- err.span_label(self.def_span, rustc_errors::fluent::typeck::label);
+ err.span_label(self.def_span, rustc_errors::fluent::label);
let mut suggested = false;
// Don't suggest setting the type params if there are some already: the order is
@@ -282,7 +187,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
// least we can clue them to the correct syntax `Iterator<Type>`.
err.span_suggestion(
self.span,
- rustc_errors::fluent::typeck::suggestion,
+ rustc_errors::fluent::suggestion,
format!(
"{}<{}>",
snippet,
@@ -298,16 +203,16 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
}
}
if !suggested {
- err.span_label(self.span, rustc_errors::fluent::typeck::no_suggestion_label);
+ err.span_label(self.span, rustc_errors::fluent::no_suggestion_label);
}
- err.note(rustc_errors::fluent::typeck::note);
+ err.note(rustc_errors::fluent::note);
err
}
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::manual_implementation, code = "E0183")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_manual_implementation, code = "E0183")]
#[help]
pub struct ManualImplementation {
#[primary_span]
@@ -316,22 +221,22 @@ pub struct ManualImplementation {
pub trait_name: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::substs_on_overridden_impl)]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_substs_on_overridden_impl)]
pub struct SubstsOnOverriddenImpl {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(typeck::unused_extern_crate)]
+#[diag(hir_analysis_unused_extern_crate)]
pub struct UnusedExternCrate {
#[suggestion(applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(typeck::extern_crate_not_idiomatic)]
+#[diag(hir_analysis_extern_crate_not_idiomatic)]
pub struct ExternCrateNotIdiomatic {
#[suggestion_short(applicability = "machine-applicable", code = "{suggestion_code}")]
pub span: Span,
@@ -339,9 +244,39 @@ pub struct ExternCrateNotIdiomatic {
pub suggestion_code: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::expected_used_symbol)]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_expected_used_symbol)]
pub struct ExpectedUsedSymbol {
#[primary_span]
pub span: Span,
}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_const_impl_for_non_const_trait)]
+pub struct ConstImplForNonConstTrait {
+ #[primary_span]
+ pub trait_ref_span: Span,
+ pub trait_name: String,
+ #[suggestion(applicability = "machine-applicable", code = "#[const_trait]")]
+ pub local_trait_span: Option<Span>,
+ #[note]
+ pub marking: (),
+ #[note(adding)]
+ pub adding: (),
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_const_bound_for_non_const_trait)]
+pub struct ConstBoundForNonConstTrait {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_self_in_impl_self)]
+pub struct SelfInImplSelf {
+ #[primary_span]
+ pub span: MultiSpan,
+ #[note]
+ pub note: (),
+}
diff --git a/compiler/rustc_typeck/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index 7b080dc29..b0fdfcf38 100644
--- a/compiler/rustc_typeck/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -64,38 +64,36 @@ fn diagnostic_hir_wf_check<'tcx>(
impl<'tcx> Visitor<'tcx> for HirWfCheck<'tcx> {
fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
- self.tcx.infer_ctxt().enter(|infcx| {
- let tcx_ty =
- self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
- let cause = traits::ObligationCause::new(
- ty.span,
- self.hir_id,
- traits::ObligationCauseCode::WellFormed(None),
- );
- let errors = traits::fully_solve_obligation(
- &infcx,
- traits::Obligation::new(
- cause,
- self.param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
- .to_predicate(self.tcx),
- ),
- );
- if !errors.is_empty() {
- debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
- for error in errors {
- if error.obligation.predicate == self.predicate {
- // Save the cause from the greatest depth - this corresponds
- // to picking more-specific types (e.g. `MyStruct<u8>`)
- // over less-specific types (e.g. `Option<MyStruct<u8>>`)
- if self.depth >= self.cause_depth {
- self.cause = Some(error.obligation.cause);
- self.cause_depth = self.depth
- }
+ let infcx = self.tcx.infer_ctxt().build();
+ let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx });
+ let cause = traits::ObligationCause::new(
+ ty.span,
+ self.hir_id,
+ traits::ObligationCauseCode::WellFormed(None),
+ );
+ let errors = traits::fully_solve_obligation(
+ &infcx,
+ traits::Obligation::new(
+ cause,
+ self.param_env,
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into()))
+ .to_predicate(self.tcx),
+ ),
+ );
+ if !errors.is_empty() {
+ debug!("Wf-check got errors for {:?}: {:?}", ty, errors);
+ for error in errors {
+ if error.obligation.predicate == self.predicate {
+ // Save the cause from the greatest depth - this corresponds
+ // to picking more-specific types (e.g. `MyStruct<u8>`)
+ // over less-specific types (e.g. `Option<MyStruct<u8>>`)
+ if self.depth >= self.cause_depth {
+ self.cause = Some(error.obligation.cause);
+ self.cause_depth = self.depth
}
}
}
- });
+ }
self.depth += 1;
intravisit::walk_ty(self, ty);
self.depth -= 1;
@@ -119,7 +117,7 @@ fn diagnostic_hir_wf_check<'tcx>(
let ty = match loc {
WellFormedLoc::Ty(_) => match hir.get(hir_id) {
hir::Node::ImplItem(item) => match item.kind {
- hir::ImplItemKind::TyAlias(ty) => Some(ty),
+ hir::ImplItemKind::Type(ty) => Some(ty),
hir::ImplItemKind::Const(ty, _) => Some(ty),
ref item => bug!("Unexpected ImplItem {:?}", item),
},
diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 9fee1eaae..136f61999 100644
--- a/compiler/rustc_typeck/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -11,7 +11,7 @@
use crate::constrained_generic_params as cgp;
use min_specialization::check_min_specialization;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -19,8 +19,6 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::{Span, Symbol};
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-
mod min_specialization;
/// Checks that all the type/lifetime parameters on an impl also
@@ -57,11 +55,10 @@ 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.def_id), DefKind::Impl) {
- enforce_impl_params_are_constrained(tcx, id.def_id);
- enforce_impl_items_are_distinct(tcx, id.def_id);
+ 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.def_id);
+ check_min_specialization(tcx, id.owner_id.def_id);
}
}
}
@@ -194,35 +191,3 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol
}
err.emit();
}
-
-/// Enforce that we do not have two items in an impl with the same name.
-fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
- let mut seen_type_items = FxHashMap::default();
- let mut seen_value_items = FxHashMap::default();
- for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) {
- let impl_item = tcx.associated_item(impl_item_ref);
- let seen_items = match impl_item.kind {
- ty::AssocKind::Type => &mut seen_type_items,
- _ => &mut seen_value_items,
- };
- let span = tcx.def_span(impl_item_ref);
- let ident = impl_item.ident(tcx);
- match seen_items.entry(ident.normalize_to_macros_2_0()) {
- Occupied(entry) => {
- let mut err = struct_span_err!(
- tcx.sess,
- span,
- E0201,
- "duplicate definitions with name `{}`:",
- ident
- );
- err.span_label(*entry.get(), format!("previous definition of `{}` here", ident));
- err.span_label(span, "duplicate definition");
- err.emit();
- }
- Vacant(entry) => {
- entry.insert(span);
- }
- }
- }
-}
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index 2741d9f77..e806e9487 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -77,7 +77,7 @@ use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::Span;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
@@ -130,8 +130,10 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
///
/// Example
///
+/// ```ignore (illustrative)
/// impl<A, B> Foo<A> for B { /* impl2 */ }
/// impl<C> Foo<Vec<C>> for C { /* impl1 */ }
+/// ```
///
/// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
fn get_impl_substs<'tcx>(
@@ -139,34 +141,33 @@ fn get_impl_substs<'tcx>(
impl1_def_id: LocalDefId,
impl2_node: Node,
) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
- tcx.infer_ctxt().enter(|ref infcx| {
- 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 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);
+ let assumed_wf_types =
+ ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
- let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
- let impl2_substs =
- translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+ let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+ let impl2_substs =
+ translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- ocx.infcx.report_fulfillment_errors(&errors, None, false);
- return None;
- }
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ ocx.infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return None;
+ }
- let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
- let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
- infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
- let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
- let span = tcx.def_span(impl1_def_id);
- tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
- return None;
- };
- Some((impl1_substs, impl2_substs))
- })
+ let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
+ let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+ infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+ let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+ let span = tcx.def_span(impl1_def_id);
+ tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
+ return None;
+ };
+ Some((impl1_substs, impl2_substs))
}
/// Returns a list of all of the unconstrained subst of the given impl.
@@ -226,13 +227,17 @@ fn unconstrained_parent_impl_substs<'tcx>(
///
/// For example forbid the following:
///
+/// ```ignore (illustrative)
/// impl<A> Tr for A { }
/// impl<B> Tr for (B, B) { }
+/// ```
///
/// Note that only consider the unconstrained parameters of the base impl:
///
+/// ```ignore (illustrative)
/// impl<S, I: IntoIterator<Item = S>> Tr<S> for I { }
/// impl<T> Tr<T> for Vec<T> { }
+/// ```
///
/// The substs for the parent impl here are `[T, Vec<T>]`, which repeats `T`,
/// but `S` is constrained in the parent impl, so `parent_substs` is only
@@ -257,8 +262,10 @@ fn check_duplicate_params<'tcx>(
///
/// For example forbid the following:
///
+/// ```ignore (illustrative)
/// impl<A> Tr for A { }
/// impl Tr for &'static i32 { }
+/// ```
fn check_static_lifetimes<'tcx>(
tcx: TyCtxt<'tcx>,
parent_substs: &Vec<GenericArg<'tcx>>,
@@ -344,23 +351,21 @@ 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().substs {
- tcx.infer_ctxt().enter(|ref infcx| {
- 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 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();
- assert!(!obligations.needs_infer());
- impl2_predicates.extend(
- traits::elaborate_obligations(tcx, obligations)
- .map(|obligation| obligation.predicate),
- )
- })
+ assert!(!obligations.needs_infer());
+ impl2_predicates.extend(
+ traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate),
+ )
}
impl2_predicates.extend(
traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
@@ -423,13 +428,10 @@ fn trait_predicate_kind<'tcx>(
predicate: ty::Predicate<'tcx>,
) -> Option<TraitSpecializationKind> {
match predicate.kind().skip_binder() {
- ty::PredicateKind::Trait(ty::TraitPredicate {
- trait_ref,
- constness: ty::BoundConstness::NotConst,
- polarity: _,
- }) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
- ty::PredicateKind::Trait(_)
- | ty::PredicateKind::RegionOutlives(_)
+ ty::PredicateKind::Trait(ty::TraitPredicate { trait_ref, constness: _, polarity: _ }) => {
+ Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
+ }
+ ty::PredicateKind::RegionOutlives(_)
| ty::PredicateKind::TypeOutlives(_)
| ty::PredicateKind::Projection(_)
| ty::PredicateKind::WellFormed(_)
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index b1ce972e1..525cd2419 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -64,15 +64,13 @@ This API is completely unstable and subject to change.
#![feature(if_let_guard)]
#![feature(is_sorted)]
#![feature(iter_intersperse)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(slice_partition_dedup)]
#![feature(try_blocks)]
-#![feature(is_some_with)]
+#![feature(is_some_and)]
#![feature(type_alias_impl_trait)]
#![recursion_limit = "256"]
@@ -84,20 +82,19 @@ extern crate rustc_middle;
// These are used by Clippy.
pub mod check;
-pub mod expr_use_visitor;
-mod astconv;
+pub mod astconv;
mod bounds;
mod check_unused;
mod coherence;
-mod collect;
+// FIXME: This module shouldn't be public.
+pub mod collect;
mod constrained_generic_params;
mod errors;
pub mod hir_wf_check;
mod impl_wf_check;
-mod mem_categorization;
mod outlives;
-mod structured_errors;
+pub mod structured_errors;
mod variance;
use rustc_errors::{struct_span_err, ErrorGuaranteed};
@@ -112,7 +109,7 @@ use rustc_middle::util;
use rustc_session::config::EntryFnType;
use rustc_span::{symbol::sym, Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
use std::iter;
@@ -143,24 +140,23 @@ fn require_same_types<'tcx>(
expected: Ty<'tcx>,
actual: Ty<'tcx>,
) -> bool {
- tcx.infer_ctxt().enter(|ref infcx| {
- let param_env = ty::ParamEnv::empty();
- let errors = match infcx.at(cause, param_env).eq(expected, actual) {
- Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
- Err(err) => {
- infcx.report_mismatched_types(cause, expected, actual, err).emit();
- return false;
- }
- };
+ let infcx = &tcx.infer_ctxt().build();
+ let param_env = ty::ParamEnv::empty();
+ let errors = match infcx.at(cause, param_env).eq(expected, actual) {
+ Ok(InferOk { obligations, .. }) => traits::fully_solve_obligations(infcx, obligations),
+ Err(err) => {
+ infcx.err_ctxt().report_mismatched_types(cause, expected, actual, err).emit();
+ return false;
+ }
+ };
- match &errors[..] {
- [] => true,
- errors => {
- infcx.report_fulfillment_errors(errors, None, false);
- false
- }
+ match &errors[..] {
+ [] => true,
+ errors => {
+ infcx.err_ctxt().report_fulfillment_errors(errors, None, false);
+ false
}
- })
+ }
}
fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
@@ -307,23 +303,22 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
error = true;
}
let return_ty = return_ty.skip_binder();
- tcx.infer_ctxt().enter(|infcx| {
- // Main should have no WC, so empty param env is OK here.
- let param_env = ty::ParamEnv::empty();
- let cause = traits::ObligationCause::new(
- return_ty_span,
- main_diagnostics_hir_id,
- ObligationCauseCode::MainFunctionType,
- );
- let ocx = traits::ObligationCtxt::new(&infcx);
- let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
- ocx.register_bound(cause, param_env, norm_return_ty, term_did);
- let errors = ocx.select_all_or_error();
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- error = true;
- }
- });
+ let infcx = tcx.infer_ctxt().build();
+ // Main should have no WC, so empty param env is OK here.
+ let param_env = ty::ParamEnv::empty();
+ let cause = traits::ObligationCause::new(
+ return_ty_span,
+ main_diagnostics_hir_id,
+ ObligationCauseCode::MainFunctionType,
+ );
+ let ocx = traits::ObligationCtxt::new(&infcx);
+ let norm_return_ty = ocx.normalize(cause.clone(), param_env, return_ty);
+ ocx.register_bound(cause, param_env, norm_return_ty, term_did);
+ let errors = ocx.select_all_or_error();
+ if !errors.is_empty() {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ error = true;
+ }
// now we can take the return type of the given main function
expected_return_type = main_fnsig.output();
} else {
@@ -386,7 +381,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
error = true;
}
if let hir::IsAsync::Async = sig.header.asyncness {
- let span = tcx.def_span(it.def_id);
+ let span = tcx.def_span(it.owner_id);
struct_span_err!(
tcx.sess,
span,
diff --git a/compiler/rustc_typeck/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 7534482cc..7534482cc 100644
--- a/compiler/rustc_typeck/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
diff --git a/compiler/rustc_typeck/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 3b779280e..90c6edb65 100644
--- a/compiler/rustc_typeck/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -1,8 +1,8 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::Span;
use super::explicit::ExplicitPredicatesMap;
@@ -29,7 +29,7 @@ pub(super) fn infer_predicates<'tcx>(
// Visit all the crates and infer predicates
for id in tcx.hir().items() {
- let item_did = id.def_id;
+ let item_did = id.owner_id;
debug!("InferVisitor::visit_item(item={:?})", item_did);
diff --git a/compiler/rustc_typeck/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index e50c26765..e50c26765 100644
--- a/compiler/rustc_typeck/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
diff --git a/compiler/rustc_typeck/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
index eb0e12034..fa2ac5659 100644
--- a/compiler/rustc_typeck/src/outlives/test.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/test.rs
@@ -6,11 +6,11 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
for id in tcx.hir().items() {
// For unit testing: check for a special "rustc_outlives"
// attribute and report an error with various results if found.
- if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_outlives) {
- let inferred_outlives_of = tcx.inferred_outlives_of(id.def_id);
+ if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_outlives) {
+ let inferred_outlives_of = tcx.inferred_outlives_of(id.owner_id);
struct_span_err!(
tcx.sess,
- tcx.def_span(id.def_id),
+ tcx.def_span(id.owner_id),
E0640,
"{:?}",
inferred_outlives_of
diff --git a/compiler/rustc_typeck/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs
index 3e8d023fb..0409c7081 100644
--- a/compiler/rustc_typeck/src/outlives/utils.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs
@@ -96,6 +96,23 @@ pub(crate) fn insert_outlives_predicate<'tcx>(
.or_insert(span);
}
+ Component::Opaque(def_id, substs) => {
+ // This would arise from something like:
+ //
+ // ```rust
+ // type Opaque<T> = impl Sized;
+ // fn defining<T>() -> Opaque<T> {}
+ // struct Ss<'a, T>(&'a Opaque<T>);
+ // ```
+ //
+ // Here we want to have an implied bound `Opaque<T>: 'a`
+
+ let ty = tcx.mk_opaque(def_id, substs);
+ required_predicates
+ .entry(ty::OutlivesPredicate(ty.into(), outlived_region))
+ .or_insert(span);
+ }
+
Component::EscapingProjection(_) => {
// As above, but the projection involves
// late-bound regions. Therefore, the WF
diff --git a/compiler/rustc_typeck/src/structured_errors.rs b/compiler/rustc_hir_analysis/src/structured_errors.rs
index 0b46fce17..0b46fce17 100644
--- a/compiler/rustc_typeck/src/structured_errors.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors.rs
diff --git a/compiler/rustc_typeck/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..324df313e 100644
--- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/missing_cast_for_variadic_arg.rs
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
index bb6088054..bb6088054 100644
--- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/sized_unsized_cast.rs
diff --git a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 435912464..435912464 100644
--- a/compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
diff --git a/compiler/rustc_typeck/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index eaf0310d5..eaf0310d5 100644
--- a/compiler/rustc_typeck/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
diff --git a/compiler/rustc_typeck/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 82103c5a0..82103c5a0 100644
--- a/compiler/rustc_typeck/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs
index 97aca621a..97aca621a 100644
--- a/compiler/rustc_typeck/src/variance/solve.rs
+++ b/compiler/rustc_hir_analysis/src/variance/solve.rs
diff --git a/compiler/rustc_typeck/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs
index 1f763011e..1f763011e 100644
--- a/compiler/rustc_typeck/src/variance/terms.rs
+++ b/compiler/rustc_hir_analysis/src/variance/terms.rs
diff --git a/compiler/rustc_typeck/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
index 2ba87db88..83ed3e44b 100644
--- a/compiler/rustc_typeck/src/variance/test.rs
+++ b/compiler/rustc_hir_analysis/src/variance/test.rs
@@ -6,9 +6,10 @@ pub fn test_variance(tcx: TyCtxt<'_>) {
// For unit testing: check for a special "rustc_variance"
// attribute and report an error with various results if found.
for id in tcx.hir().items() {
- if tcx.has_attr(id.def_id.to_def_id(), sym::rustc_variance) {
- let variances_of = tcx.variances_of(id.def_id);
- struct_span_err!(tcx.sess, tcx.def_span(id.def_id), E0208, "{:?}", variances_of).emit();
+ if tcx.has_attr(id.owner_id.to_def_id(), sym::rustc_variance) {
+ let variances_of = tcx.variances_of(id.owner_id);
+ struct_span_err!(tcx.sess, tcx.def_span(id.owner_id), E0208, "{:?}", variances_of)
+ .emit();
}
}
}
diff --git a/compiler/rustc_typeck/src/variance/xform.rs b/compiler/rustc_hir_analysis/src/variance/xform.rs
index 027f0859f..027f0859f 100644
--- a/compiler/rustc_typeck/src/variance/xform.rs
+++ b/compiler/rustc_hir_analysis/src/variance/xform.rs
diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml
index 46a8e7dee..1ea7be1ae 100644
--- a/compiler/rustc_hir_pretty/Cargo.toml
+++ b/compiler/rustc_hir_pretty/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 35a58296e..da27554a2 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -887,7 +887,7 @@ impl<'a> State<'a> {
self.end(); // need to close a box
self.ann.nested(self, Nested::Body(body));
}
- hir::ImplItemKind::TyAlias(ty) => {
+ hir::ImplItemKind::Type(ty) => {
self.print_associated_type(ii.ident, ii.generics, None, Some(ty));
}
}
@@ -1687,7 +1687,11 @@ impl<'a> State<'a> {
let mut nonelided_generic_args: bool = false;
let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
- GenericArg::Lifetime(lt) => lt.is_elided(),
+ GenericArg::Lifetime(lt) if lt.is_elided() => true,
+ GenericArg::Lifetime(_) => {
+ nonelided_generic_args = true;
+ false
+ }
_ => {
nonelided_generic_args = true;
true
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
new file mode 100644
index 000000000..093f9bb84
--- /dev/null
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -0,0 +1,28 @@
+[package]
+name = "rustc_hir_typeck"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+tracing = "0.1"
+rustc_ast = { path = "../rustc_ast" }
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_errors = { path = "../rustc_errors" }
+rustc_graphviz = { path = "../rustc_graphviz" }
+rustc_index = { path = "../rustc_index" }
+rustc_infer = { path = "../rustc_infer" }
+rustc_hir = { path = "../rustc_hir" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
+rustc_lint = { path = "../rustc_lint" }
+rustc_middle = { path = "../rustc_middle" }
+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" }
+rustc_trait_selection = { path = "../rustc_trait_selection" }
+rustc_type_ir = { path = "../rustc_type_ir" }
diff --git a/compiler/rustc_typeck/src/check/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 20332e75c..2b15d4dcd 100644
--- a/compiler/rustc_typeck/src/check/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -1,10 +1,10 @@
-use crate::check::coercion::{AsCoercionSite, CoerceMany};
-use crate::check::{Diverges, Expectation, FnCtxt, Needs};
+use crate::coercion::{AsCoercionSite, CoerceMany};
+use crate::{Diverges, Expectation, FnCtxt, Needs};
use rustc_errors::{Applicability, MultiSpan};
use rustc_hir::{self as hir, ExprKind};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::traits::Obligation;
-use rustc_middle::ty::{self, Subst, ToPredicate, Ty};
+use rustc_middle::ty::{self, ToPredicate, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some(ret) = self
.tcx
.hir()
- .find_by_def_id(self.body_id.owner)
+ .find_by_def_id(self.body_id.owner.def_id)
.and_then(|owner| owner.fn_decl())
.map(|decl| decl.output.span())
else { return; };
@@ -259,7 +259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help("consider adding an `else` block that evaluates to the expected type");
error = true;
},
- ret_reason.is_none(),
+ false,
);
error
}
@@ -495,7 +495,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.typeck_results
.borrow()
.liberated_fn_sigs()
- .get(hir::HirId::make_owner(self.body_id.owner))?;
+ .get(hir::HirId::make_owner(self.body_id.owner.def_id))?;
let substs = sig.output().walk().find_map(|arg| {
if let ty::GenericArgKind::Type(ty) = arg.unpack()
@@ -514,8 +514,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
for ty in [first_ty, second_ty] {
- for pred in self.tcx.bound_explicit_item_bounds(rpit_def_id).transpose_iter() {
- let pred = pred.map_bound(|(pred, _)| *pred).subst(self.tcx, substs);
+ for (pred, _) in self
+ .tcx
+ .bound_explicit_item_bounds(rpit_def_id)
+ .subst_iter_copied(self.tcx, substs)
+ {
let pred = match pred.kind().skip_binder() {
ty::PredicateKind::Trait(mut trait_pred) => {
assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty);
diff --git a/compiler/rustc_typeck/src/check/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs
index 59c366ad7..59c366ad7 100644
--- a/compiler/rustc_typeck/src/check/autoderef.rs
+++ b/compiler/rustc_hir_typeck/src/autoderef.rs
diff --git a/compiler/rustc_typeck/src/check/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 0d35c2479..1b33f2f02 100644
--- a/compiler/rustc_typeck/src/check/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -1,8 +1,10 @@
+use super::method::probe::{IsSuggestion, Mode, ProbeScope};
use super::method::MethodCallee;
-use super::{DefIdOrName, Expectation, FnCtxt, TupleArgumentsFlag};
-use crate::type_error_struct;
+use super::{Expectation, FnCtxt, TupleArgumentsFlag};
-use rustc_errors::{struct_span_err, Applicability, Diagnostic};
+use crate::type_error_struct;
+use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_errors::{struct_span_err, Applicability, Diagnostic, StashKey};
use rustc_hir as hir;
use rustc_hir::def::{self, Namespace, Res};
use rustc_hir::def_id::DefId;
@@ -17,7 +19,7 @@ use rustc_infer::{
use rustc_middle::ty::adjustment::{
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
};
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
use rustc_span::def_id::LocalDefId;
use rustc_span::symbol::{sym, Ident};
@@ -25,6 +27,7 @@ use rustc_span::Span;
use rustc_target::spec::abi;
use rustc_trait_selection::autoderef::Autoderef;
use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use std::iter;
@@ -60,6 +63,7 @@ pub fn check_legal_trait_for_method_call(
}
}
+#[derive(Debug)]
enum CallStep<'tcx> {
Builtin(Ty<'tcx>),
DeferredClosure(LocalDefId, ty::FnSig<'tcx>),
@@ -188,6 +192,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return None;
}
+ ty::Error(_) => {
+ return None;
+ }
+
_ => {}
}
@@ -394,140 +402,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
ty::FnPtr(sig) => (sig, None),
_ => {
- let mut unit_variant = None;
- if let hir::ExprKind::Path(qpath) = &callee_expr.kind
- && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
- = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
- // Only suggest removing parens if there are no arguments
- && arg_exprs.is_empty()
+ if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &callee_expr.kind
+ && let [segment] = path.segments
+ && let Some(mut diag) = self
+ .tcx
+ .sess
+ .diagnostic()
+ .steal_diagnostic(segment.ident.span, StashKey::CallIntoMethod)
{
- let descr = match kind {
- def::CtorOf::Struct => "struct",
- def::CtorOf::Variant => "enum variant",
- };
- let removal_span =
- callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
- unit_variant =
- Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
- }
-
- let callee_ty = self.resolve_vars_if_possible(callee_ty);
- let mut err = type_error_struct!(
- self.tcx.sess,
- callee_expr.span,
- callee_ty,
- E0618,
- "expected function, found {}",
- match &unit_variant {
- Some((_, kind, path)) => format!("{kind} `{path}`"),
- None => format!("`{callee_ty}`"),
- }
- );
-
- self.identify_bad_closure_def_and_call(
- &mut err,
- call_expr.hir_id,
- &callee_expr.kind,
- callee_expr.span,
- );
-
- if let Some((removal_span, kind, path)) = &unit_variant {
- err.span_suggestion_verbose(
- *removal_span,
- &format!(
- "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
- ),
- "",
- Applicability::MachineApplicable,
- );
- }
-
- let mut inner_callee_path = None;
- let def = match callee_expr.kind {
- hir::ExprKind::Path(ref qpath) => {
- self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
- }
- hir::ExprKind::Call(ref inner_callee, _) => {
- // If the call spans more than one line and the callee kind is
- // itself another `ExprCall`, that's a clue that we might just be
- // missing a semicolon (Issue #51055)
- let call_is_multiline =
- self.tcx.sess.source_map().is_multiline(call_expr.span);
- if call_is_multiline {
- err.span_suggestion(
- callee_expr.span.shrink_to_hi(),
- "consider using a semicolon here",
- ";",
- Applicability::MaybeIncorrect,
- );
- }
- if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
- inner_callee_path = Some(inner_qpath);
- self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
- } else {
- Res::Err
- }
- }
- _ => Res::Err,
- };
-
- if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
- if let Some((maybe_def, output_ty, _)) = self.extract_callable_info(callee_expr, callee_ty)
- && !self.type_is_sized_modulo_regions(self.param_env, output_ty, callee_expr.span)
+ // Try suggesting `foo(a)` -> `a.foo()` if possible.
+ if let Some(ty) =
+ self.suggest_call_as_method(
+ &mut diag,
+ segment,
+ arg_exprs,
+ call_expr,
+ expected
+ )
{
- let descr = match maybe_def {
- DefIdOrName::DefId(def_id) => self.tcx.def_kind(def_id).descr(def_id),
- DefIdOrName::Name(name) => name,
- };
- err.span_label(
- callee_expr.span,
- format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
- );
- if let DefIdOrName::DefId(def_id) = maybe_def
- && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
- {
- err.span_label(def_span, "the callable type is defined here");
- }
+ diag.emit();
+ return ty;
} else {
- err.span_label(call_expr.span, "call expression requires function");
+ diag.emit();
}
}
- if let Some(span) = self.tcx.hir().res_span(def) {
- let callee_ty = callee_ty.to_string();
- let label = match (unit_variant, inner_callee_path) {
- (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
- (_, Some(hir::QPath::Resolved(_, path))) => self
- .tcx
- .sess
- .source_map()
- .span_to_snippet(path.span)
- .ok()
- .map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
- _ => {
- match def {
- // Emit a different diagnostic for local variables, as they are not
- // type definitions themselves, but rather variables *of* that type.
- Res::Local(hir_id) => Some(format!(
- "`{}` has type `{}`",
- self.tcx.hir().name(hir_id),
- callee_ty
- )),
- Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
- Some(format!(
- "`{}` defined here",
- self.tcx.def_path_str(def_id),
- ))
- }
- _ => Some(format!("`{callee_ty}` defined here")),
- }
- }
- };
- if let Some(label) = label {
- err.span_label(span, label);
- }
- }
- err.emit();
+ self.report_invalid_callee(call_expr, callee_expr, callee_ty, arg_exprs);
// This is the "default" function signature, used in case of error.
// In that case, we check each argument against "error" in order to
@@ -574,6 +474,243 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn_sig.output()
}
+ /// Attempts to reinterpret `method(rcvr, args...)` as `rcvr.method(args...)`
+ /// and suggesting the fix if the method probe is successful.
+ fn suggest_call_as_method(
+ &self,
+ diag: &mut Diagnostic,
+ segment: &'tcx hir::PathSegment<'tcx>,
+ arg_exprs: &'tcx [hir::Expr<'tcx>],
+ call_expr: &'tcx hir::Expr<'tcx>,
+ expected: Expectation<'tcx>,
+ ) -> Option<Ty<'tcx>> {
+ if let [callee_expr, rest @ ..] = arg_exprs {
+ let callee_ty = self.check_expr(callee_expr);
+ // First, do a probe with `IsSuggestion(true)` to avoid emitting
+ // any strange errors. If it's successful, then we'll do a true
+ // method lookup.
+ let Ok(pick) = self
+ .probe_for_name(
+ call_expr.span,
+ Mode::MethodCall,
+ segment.ident,
+ IsSuggestion(true),
+ callee_ty,
+ call_expr.hir_id,
+ // We didn't record the in scope traits during late resolution
+ // so we need to probe AllTraits unfortunately
+ ProbeScope::AllTraits,
+ ) else {
+ return None;
+ };
+
+ let pick = self.confirm_method(
+ call_expr.span,
+ callee_expr,
+ call_expr,
+ callee_ty,
+ pick,
+ segment,
+ );
+ if pick.illegal_sized_bound.is_some() {
+ return None;
+ }
+
+ let up_to_rcvr_span = segment.ident.span.until(callee_expr.span);
+ let rest_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
+ let rest_snippet = if let Some(first) = rest.first() {
+ self.tcx
+ .sess
+ .source_map()
+ .span_to_snippet(first.span.to(call_expr.span.shrink_to_hi()))
+ } else {
+ Ok(")".to_string())
+ };
+
+ if let Ok(rest_snippet) = rest_snippet {
+ let sugg = if callee_expr.precedence().order() >= PREC_POSTFIX {
+ vec![
+ (up_to_rcvr_span, "".to_string()),
+ (rest_span, format!(".{}({rest_snippet}", segment.ident)),
+ ]
+ } else {
+ vec![
+ (up_to_rcvr_span, "(".to_string()),
+ (rest_span, format!(").{}({rest_snippet}", segment.ident)),
+ ]
+ };
+ let self_ty = self.resolve_vars_if_possible(pick.callee.sig.inputs()[0]);
+ diag.multipart_suggestion(
+ format!(
+ "use the `.` operator to call the method `{}{}` on `{self_ty}`",
+ self.tcx
+ .associated_item(pick.callee.def_id)
+ .trait_container(self.tcx)
+ .map_or_else(
+ || String::new(),
+ |trait_def_id| self.tcx.def_path_str(trait_def_id) + "::"
+ ),
+ segment.ident
+ ),
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+
+ // Let's check the method fully now
+ let return_ty = self.check_method_argument_types(
+ segment.ident.span,
+ call_expr,
+ Ok(pick.callee),
+ rest,
+ TupleArgumentsFlag::DontTupleArguments,
+ expected,
+ );
+
+ return Some(return_ty);
+ }
+ }
+
+ None
+ }
+
+ fn report_invalid_callee(
+ &self,
+ call_expr: &'tcx hir::Expr<'tcx>,
+ callee_expr: &'tcx hir::Expr<'tcx>,
+ callee_ty: Ty<'tcx>,
+ arg_exprs: &'tcx [hir::Expr<'tcx>],
+ ) {
+ let mut unit_variant = None;
+ if let hir::ExprKind::Path(qpath) = &callee_expr.kind
+ && let Res::Def(def::DefKind::Ctor(kind, def::CtorKind::Const), _)
+ = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
+ // Only suggest removing parens if there are no arguments
+ && arg_exprs.is_empty()
+ {
+ let descr = match kind {
+ def::CtorOf::Struct => "struct",
+ def::CtorOf::Variant => "enum variant",
+ };
+ let removal_span = callee_expr.span.shrink_to_hi().to(call_expr.span.shrink_to_hi());
+ unit_variant = Some((removal_span, descr, rustc_hir_pretty::qpath_to_string(qpath)));
+ }
+
+ let callee_ty = self.resolve_vars_if_possible(callee_ty);
+ let mut err = type_error_struct!(
+ self.tcx.sess,
+ callee_expr.span,
+ callee_ty,
+ E0618,
+ "expected function, found {}",
+ match &unit_variant {
+ Some((_, kind, path)) => format!("{kind} `{path}`"),
+ None => format!("`{callee_ty}`"),
+ }
+ );
+
+ self.identify_bad_closure_def_and_call(
+ &mut err,
+ call_expr.hir_id,
+ &callee_expr.kind,
+ callee_expr.span,
+ );
+
+ if let Some((removal_span, kind, path)) = &unit_variant {
+ err.span_suggestion_verbose(
+ *removal_span,
+ &format!(
+ "`{path}` is a unit {kind}, and does not take parentheses to be constructed",
+ ),
+ "",
+ Applicability::MachineApplicable,
+ );
+ }
+
+ let mut inner_callee_path = None;
+ let def = match callee_expr.kind {
+ hir::ExprKind::Path(ref qpath) => {
+ self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
+ }
+ hir::ExprKind::Call(ref inner_callee, _) => {
+ // If the call spans more than one line and the callee kind is
+ // itself another `ExprCall`, that's a clue that we might just be
+ // missing a semicolon (Issue #51055)
+ let call_is_multiline = self.tcx.sess.source_map().is_multiline(call_expr.span);
+ if call_is_multiline {
+ err.span_suggestion(
+ callee_expr.span.shrink_to_hi(),
+ "consider using a semicolon here",
+ ";",
+ Applicability::MaybeIncorrect,
+ );
+ }
+ if let hir::ExprKind::Path(ref inner_qpath) = inner_callee.kind {
+ inner_callee_path = Some(inner_qpath);
+ self.typeck_results.borrow().qpath_res(inner_qpath, inner_callee.hir_id)
+ } else {
+ Res::Err
+ }
+ }
+ _ => Res::Err,
+ };
+
+ if !self.maybe_suggest_bad_array_definition(&mut err, call_expr, callee_expr) {
+ if let Some((maybe_def, output_ty, _)) =
+ self.extract_callable_info(callee_expr, callee_ty)
+ && !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::Name(name) => name,
+ };
+ err.span_label(
+ callee_expr.span,
+ format!("this {descr} returns an unsized value `{output_ty}`, so it cannot be called")
+ );
+ if let DefIdOrName::DefId(def_id) = maybe_def
+ && let Some(def_span) = self.tcx.hir().span_if_local(def_id)
+ {
+ err.span_label(def_span, "the callable type is defined here");
+ }
+ } else {
+ err.span_label(call_expr.span, "call expression requires function");
+ }
+ }
+
+ if let Some(span) = self.tcx.hir().res_span(def) {
+ let callee_ty = callee_ty.to_string();
+ let label = match (unit_variant, inner_callee_path) {
+ (Some((_, kind, path)), _) => Some(format!("{kind} `{path}` defined here")),
+ (_, Some(hir::QPath::Resolved(_, path))) => self
+ .tcx
+ .sess
+ .source_map()
+ .span_to_snippet(path.span)
+ .ok()
+ .map(|p| format!("`{p}` defined here returns `{callee_ty}`")),
+ _ => {
+ match def {
+ // Emit a different diagnostic for local variables, as they are not
+ // type definitions themselves, but rather variables *of* that type.
+ Res::Local(hir_id) => Some(format!(
+ "`{}` has type `{}`",
+ self.tcx.hir().name(hir_id),
+ callee_ty
+ )),
+ Res::Def(kind, def_id) if kind.ns() == Some(Namespace::ValueNS) => {
+ Some(format!("`{}` defined here", self.tcx.def_path_str(def_id),))
+ }
+ _ => Some(format!("`{callee_ty}` defined here")),
+ }
+ }
+ };
+ if let Some(label) = label {
+ err.span_label(span, label);
+ }
+ }
+ err.emit();
+ }
+
fn confirm_deferred_closure_call(
&self,
call_expr: &'tcx hir::Expr<'tcx>,
diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 81a979865..d1dab0540 100644
--- a/compiler/rustc_typeck/src/check/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -30,20 +30,18 @@
use super::FnCtxt;
-use crate::hir::def_id::DefId;
use crate::type_error_struct;
-use hir::def_id::LOCAL_CRATE;
-use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{struct_span_err, Applicability, DelayDm, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
-use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode};
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::subst::SubstsRef;
-use rustc_middle::ty::{self, Binder, Ty, TypeAndMut, TypeVisitable, VariantDef};
+use rustc_middle::ty::{self, Ty, TypeAndMut, TypeVisitable, VariantDef};
use rustc_session::lint;
use rustc_session::Session;
+use rustc_span::def_id::{DefId, LOCAL_CRATE};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
@@ -62,6 +60,8 @@ pub struct CastCheck<'tcx> {
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
+ /// whether the cast is made in a const context or not.
+ pub constness: hir::Constness,
}
/// The kind of pointer and associated metadata (thin, length or vtable) - we
@@ -204,85 +204,18 @@ fn make_invalid_casting_error<'a, 'tcx>(
)
}
-pub enum CastCheckResult<'tcx> {
- Ok,
- Deferred(CastCheck<'tcx>),
- Err(ErrorGuaranteed),
-}
-
-pub fn check_cast<'tcx>(
- fcx: &FnCtxt<'_, 'tcx>,
- expr: &'tcx hir::Expr<'tcx>,
- expr_ty: Ty<'tcx>,
- cast_ty: Ty<'tcx>,
- cast_span: Span,
- span: Span,
-) -> CastCheckResult<'tcx> {
- if cast_ty.is_dyn_star() {
- check_dyn_star_cast(fcx, expr, expr_ty, cast_ty)
- } else {
- match CastCheck::new(fcx, expr, expr_ty, cast_ty, cast_span, span) {
- Ok(check) => CastCheckResult::Deferred(check),
- Err(e) => CastCheckResult::Err(e),
- }
- }
-}
-
-fn check_dyn_star_cast<'tcx>(
- fcx: &FnCtxt<'_, 'tcx>,
- expr: &'tcx hir::Expr<'tcx>,
- expr_ty: Ty<'tcx>,
- cast_ty: Ty<'tcx>,
-) -> CastCheckResult<'tcx> {
- // Find the bounds in the dyn*. For eaxmple, if we have
- //
- // let x = 22_usize as dyn* (Clone + Debug + 'static)
- //
- // this would return `existential_predicates = [?Self: Clone, ?Self: Debug]` and `region = 'static`.
- let (existential_predicates, region) = match cast_ty.kind() {
- ty::Dynamic(predicates, region, ty::DynStar) => (predicates, region),
- _ => panic!("Invalid dyn* cast_ty"),
- };
-
- let cause = ObligationCause::new(
- expr.span,
- fcx.body_id,
- // FIXME(dyn-star): Use a better obligation cause code
- ObligationCauseCode::MiscObligation,
- );
-
- // For each existential predicate (e.g., `?Self: Clone`) substitute
- // the type of the expression (e.g., `usize` in our example above)
- // and then require that the resulting predicate (e.g., `usize: Clone`)
- // holds (it does).
- for existential_predicate in existential_predicates.iter() {
- let predicate = existential_predicate.with_self_ty(fcx.tcx, expr_ty);
- fcx.register_predicate(Obligation::new(cause.clone(), fcx.param_env, predicate));
- }
-
- // Enforce the region bound `'static` (e.g., `usize: 'static`, in our example).
- fcx.register_predicate(Obligation::new(
- cause,
- fcx.param_env,
- fcx.tcx.mk_predicate(Binder::dummy(ty::PredicateKind::TypeOutlives(
- ty::OutlivesPredicate(expr_ty, *region),
- ))),
- ));
-
- CastCheckResult::Ok
-}
-
impl<'a, 'tcx> CastCheck<'tcx> {
- fn new(
+ pub fn new(
fcx: &FnCtxt<'a, 'tcx>,
expr: &'tcx hir::Expr<'tcx>,
expr_ty: Ty<'tcx>,
cast_ty: Ty<'tcx>,
cast_span: Span,
span: Span,
+ constness: hir::Constness,
) -> Result<CastCheck<'tcx>, ErrorGuaranteed> {
let expr_span = expr.span.find_ancestor_inside(span).unwrap_or(expr.span);
- let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span };
+ let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span, constness };
// For better error messages, check for some obviously unsized
// cases now. We do a more thorough check at the end, once
@@ -596,7 +529,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
err.emit();
}
CastError::SizedUnsizedCast => {
- use crate::structured_errors::{SizedUnsizedCast, StructuredDiagnostic};
+ use rustc_hir_analysis::structured_errors::{
+ SizedUnsizedCast, StructuredDiagnostic,
+ };
SizedUnsizedCast {
sess: &fcx.tcx.sess,
@@ -754,19 +689,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
} else {
("", lint::builtin::TRIVIAL_CASTS)
};
- fcx.tcx.struct_span_lint_hir(lint, self.expr.hir_id, self.span, |err| {
- err.build(&format!(
- "trivial {}cast: `{}` as `{}`",
- adjective,
- fcx.ty_to_string(t_expr),
- fcx.ty_to_string(t_cast)
- ))
- .help(&format!(
- "cast can be replaced by coercion; this might \
- require {type_asc_or}a temporary variable"
- ))
- .emit();
- });
+ fcx.tcx.struct_span_lint_hir(
+ lint,
+ self.expr.hir_id,
+ self.span,
+ DelayDm(|| {
+ format!(
+ "trivial {}cast: `{}` as `{}`",
+ adjective,
+ fcx.ty_to_string(t_expr),
+ fcx.ty_to_string(t_cast)
+ )
+ }),
+ |lint| {
+ lint.help(format!(
+ "cast can be replaced by coercion; this might \
+ require {type_asc_or}a temporary variable"
+ ))
+ },
+ );
}
#[instrument(skip(fcx), level = "debug")]
@@ -928,11 +869,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
- // FIXME(dyn-star): this needs more conditions...
- (_, DynStar) => Ok(CastKind::DynStarCast),
-
- // FIXME(dyn-star): do we want to allow dyn* upcasting or other casts?
- (DynStar, _) => Err(CastError::IllegalCast),
+ (_, DynStar) | (DynStar, _) => {
+ if fcx.tcx.features().dyn_star {
+ bug!("should be handled by `try_coerce`")
+ } else {
+ Err(CastError::IllegalCast)
+ }
+ }
}
}
@@ -1074,12 +1017,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
lint::builtin::CENUM_IMPL_DROP_CAST,
self.expr.hir_id,
self.span,
- |err| {
- err.build(&format!(
- "cannot cast enum `{}` into integer `{}` because it implements `Drop`",
- self.expr_ty, self.cast_ty
- ))
- .emit();
+ DelayDm(|| format!(
+ "cannot cast enum `{}` into integer `{}` because it implements `Drop`",
+ self.expr_ty, self.cast_ty
+ )),
+ |lint| {
+ lint
},
);
}
@@ -1090,12 +1033,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
lint::builtin::LOSSY_PROVENANCE_CASTS,
self.expr.hir_id,
self.span,
- |err| {
- let mut err = err.build(&format!(
+ DelayDm(|| format!(
"under strict provenance it is considered bad style to cast pointer `{}` to integer `{}`",
self.expr_ty, self.cast_ty
- ));
-
+ )),
+ |lint| {
let msg = "use `.addr()` to obtain the address of a pointer";
let expr_prec = self.expr.precedence().order();
@@ -1114,9 +1056,9 @@ impl<'a, 'tcx> CastCheck<'tcx> {
(cast_span, format!(").addr(){scalar_cast}")),
];
- err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
+ lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
} else {
- err.span_suggestion(
+ lint.span_suggestion(
cast_span,
msg,
format!(".addr(){scalar_cast}"),
@@ -1124,12 +1066,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
);
}
- err.help(
+ lint.help(
"if you can't comply with strict provenance and need to expose the pointer \
provenance you can use `.expose_addr()` instead"
);
- err.emit();
+ lint
},
);
}
@@ -1139,24 +1081,24 @@ impl<'a, 'tcx> CastCheck<'tcx> {
lint::builtin::FUZZY_PROVENANCE_CASTS,
self.expr.hir_id,
self.span,
- |err| {
- let mut err = err.build(&format!(
- "strict provenance disallows casting integer `{}` to pointer `{}`",
- self.expr_ty, self.cast_ty
- ));
+ DelayDm(|| format!(
+ "strict provenance disallows casting integer `{}` to pointer `{}`",
+ self.expr_ty, self.cast_ty
+ )),
+ |lint| {
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address";
let suggestions = vec![
(self.expr_span.shrink_to_lo(), String::from("(...).with_addr(")),
(self.expr_span.shrink_to_hi().to(self.cast_span), String::from(")")),
];
- err.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
- err.help(
+ lint.multipart_suggestion(msg, suggestions, Applicability::MaybeIncorrect);
+ lint.help(
"if you can't comply with strict provenance and don't have a pointer with \
the correct provenance you can use `std::ptr::from_exposed_addr()` instead"
);
- err.emit();
+ lint
},
);
}
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
new file mode 100644
index 000000000..7f76364e1
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -0,0 +1,324 @@
+use crate::coercion::CoerceMany;
+use crate::gather_locals::GatherLocalsVisitor;
+use crate::{FnCtxt, Inherited};
+use crate::{GeneratorTypes, UnsafetyState};
+use rustc_hir as hir;
+use rustc_hir::def::DefKind;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::lang_items::LangItem;
+use rustc_hir::{ImplicitSelfKind, ItemKind, Node};
+use rustc_hir_analysis::check::fn_maybe_err;
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::RegionVariableOrigin;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::def_id::LocalDefId;
+use rustc_target::spec::abi::Abi;
+use rustc_trait_selection::traits;
+use std::cell::RefCell;
+
+/// Helper used for fns and closures. Does the grungy work of checking a function
+/// body and returns the function context used for that purpose, since in the case of a fn item
+/// there is still a bit more to do.
+///
+/// * ...
+/// * inherited: other fields inherited from the enclosing fn (if any)
+#[instrument(skip(inherited, body), level = "debug")]
+pub(super) fn check_fn<'a, 'tcx>(
+ inherited: &'a Inherited<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ fn_sig: ty::FnSig<'tcx>,
+ decl: &'tcx hir::FnDecl<'tcx>,
+ fn_id: hir::HirId,
+ body: &'tcx hir::Body<'tcx>,
+ can_be_generator: Option<hir::Movability>,
+ return_type_pre_known: bool,
+) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
+ // Create the function context. This is either derived from scratch or,
+ // in the case of closures, based on the outer context.
+ let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
+ fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
+ fcx.return_type_pre_known = return_type_pre_known;
+
+ let tcx = fcx.tcx;
+ let hir = tcx.hir();
+
+ let declared_ret_ty = fn_sig.output();
+
+ let ret_ty =
+ fcx.register_infer_ok_obligations(fcx.infcx.replace_opaque_types_with_inference_vars(
+ declared_ret_ty,
+ body.value.hir_id,
+ decl.output.span(),
+ param_env,
+ ));
+ // If we replaced declared_ret_ty with infer vars, then we must be inferring
+ // an opaque type, so set a flag so we can improve diagnostics.
+ fcx.return_type_has_opaque = ret_ty != declared_ret_ty;
+
+ fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(ret_ty)));
+
+ let span = body.value.span;
+
+ fn_maybe_err(tcx, span, fn_sig.abi);
+
+ if fn_sig.abi == Abi::RustCall {
+ let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
+
+ let err = || {
+ let item = match tcx.hir().get(fn_id) {
+ Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
+ Node::ImplItem(hir::ImplItem {
+ kind: hir::ImplItemKind::Fn(header, ..), ..
+ }) => Some(header),
+ Node::TraitItem(hir::TraitItem {
+ kind: hir::TraitItemKind::Fn(header, ..),
+ ..
+ }) => Some(header),
+ // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
+ Node::Expr(hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => None,
+ node => bug!("Item being checked wasn't a function/closure: {:?}", node),
+ };
+
+ if let Some(header) = item {
+ tcx.sess.span_err(header.span, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
+ }
+ };
+
+ if fn_sig.inputs().len() != expected_args {
+ err()
+ } else {
+ // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
+ // This will probably require wide-scale changes to support a TupleKind obligation
+ // We can't resolve this without knowing the type of the param
+ if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
+ err()
+ }
+ }
+ }
+
+ if body.generator_kind.is_some() && can_be_generator.is_some() {
+ let yield_ty = fcx
+ .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
+ fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+
+ // Resume type defaults to `()` if the generator has no argument.
+ let resume_ty = fn_sig.inputs().get(0).copied().unwrap_or_else(|| tcx.mk_unit());
+
+ fcx.resume_yield_tys = Some((resume_ty, yield_ty));
+ }
+
+ GatherLocalsVisitor::new(&fcx).visit_body(body);
+
+ // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
+ // (as it's created inside the body itself, not passed in from outside).
+ let maybe_va_list = if fn_sig.c_variadic {
+ 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
+ };
+
+ // Add formal parameters.
+ let inputs_hir = hir.fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs);
+ let inputs_fn = fn_sig.inputs().iter().copied();
+ 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);
+
+ // Check that argument is Sized.
+ // The check for a non-trivial pattern is a hack to avoid duplicate warnings
+ // for simple cases like `fn foo(x: Trait)`,
+ // where we would error once on the parameter as a whole, and once on the binding `x`.
+ if param.pat.simple_ident().is_none() && !tcx.features().unsized_fn_params {
+ fcx.require_type_is_sized(param_ty, param.pat.span, traits::SizedArgumentType(ty_span));
+ }
+
+ fcx.write_ty(param.hir_id, param_ty);
+ }
+
+ inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig);
+
+ fcx.in_tail_expr = true;
+ if let ty::Dynamic(..) = declared_ret_ty.kind() {
+ // FIXME: We need to verify that the return type is `Sized` after the return expression has
+ // been evaluated so that we have types available for all the nodes being returned, but that
+ // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
+ // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
+ // while keeping the current ordering we will ignore the tail expression's type because we
+ // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
+ // because we will trigger "unreachable expression" lints unconditionally.
+ // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
+ // case that a newcomer might make, returning a bare trait, and in that case we populate
+ // the tail expression's type so that the suggestion will be correct, but ignore all other
+ // possible cases.
+ fcx.check_expr(&body.value);
+ fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+ } else {
+ fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType);
+ fcx.check_return_expr(&body.value, false);
+ }
+ fcx.in_tail_expr = false;
+
+ // We insert the deferred_generator_interiors entry after visiting the body.
+ // This ensures that all nested generators appear before the entry of this generator.
+ // resolve_generator_interiors relies on this property.
+ 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));
+
+ let (resume_ty, yield_ty) = fcx.resume_yield_tys.unwrap();
+ Some(GeneratorTypes {
+ resume_ty,
+ yield_ty,
+ interior,
+ movability: can_be_generator.unwrap(),
+ })
+ } else {
+ None
+ };
+
+ // Finalize the return check by taking the LUB of the return types
+ // we saw and assigning it to the expected return type. This isn't
+ // really expected to fail, since the coercions would have failed
+ // earlier when trying to find a LUB.
+ let coercion = fcx.ret_coercion.take().unwrap().into_inner();
+ let mut actual_return_ty = coercion.complete(&fcx);
+ debug!("actual_return_ty = {:?}", actual_return_ty);
+ if let ty::Dynamic(..) = declared_ret_ty.kind() {
+ // We have special-cased the case where the function is declared
+ // `-> dyn Foo` and we don't actually relate it to the
+ // `fcx.ret_coercion`, so just substitute a type variable.
+ actual_return_ty =
+ fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
+ debug!("actual_return_ty replaced with {:?}", actual_return_ty);
+ }
+
+ // HACK(oli-obk, compiler-errors): We should be comparing this against
+ // `declared_ret_ty`, but then anything uninferred would be inferred to
+ // the opaque type itself. That again would cause writeback to assume
+ // we have a recursive call site and do the sadly stabilized fallback to `()`.
+ fcx.demand_suptype(span, ret_ty, actual_return_ty);
+
+ // 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()
+ {
+ check_panic_info_fn(tcx, panic_impl_did.expect_local(), fn_sig, decl, declared_ret_ty);
+ }
+
+ // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
+ if let Some(alloc_error_handler_did) = tcx.lang_items().oom()
+ && alloc_error_handler_did == hir.local_def_id(fn_id).to_def_id()
+ {
+ check_alloc_error_fn(tcx, alloc_error_handler_did.expect_local(), fn_sig, decl, declared_ret_ty);
+ }
+
+ (fcx, gen_ty)
+}
+
+fn check_panic_info_fn(
+ tcx: TyCtxt<'_>,
+ fn_id: LocalDefId,
+ fn_sig: ty::FnSig<'_>,
+ decl: &hir::FnDecl<'_>,
+ declared_ret_ty: Ty<'_>,
+) {
+ let Some(panic_info_did) = tcx.lang_items().panic_info() else {
+ tcx.sess.err("language item required, but not found: `panic_info`");
+ return;
+ };
+
+ if *declared_ret_ty.kind() != ty::Never {
+ tcx.sess.span_err(decl.output.span(), "return type should be `!`");
+ }
+
+ let inputs = fn_sig.inputs();
+ if inputs.len() != 1 {
+ tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
+ return;
+ }
+
+ let arg_is_panic_info = match *inputs[0].kind() {
+ ty::Ref(region, ty, mutbl) => match *ty.kind() {
+ ty::Adt(ref adt, _) => {
+ adt.did() == panic_info_did && mutbl == hir::Mutability::Not && !region.is_static()
+ }
+ _ => false,
+ },
+ _ => false,
+ };
+
+ if !arg_is_panic_info {
+ tcx.sess.span_err(decl.inputs[0].span, "argument should be `&PanicInfo`");
+ }
+
+ let DefKind::Fn = tcx.def_kind(fn_id) else {
+ let span = tcx.def_span(fn_id);
+ tcx.sess.span_err(span, "should be a function");
+ return;
+ };
+
+ let generic_counts = tcx.generics_of(fn_id).own_counts();
+ if generic_counts.types != 0 {
+ let span = tcx.def_span(fn_id);
+ tcx.sess.span_err(span, "should have no type parameters");
+ }
+ if generic_counts.consts != 0 {
+ let span = tcx.def_span(fn_id);
+ tcx.sess.span_err(span, "should have no const parameters");
+ }
+}
+
+fn check_alloc_error_fn(
+ tcx: TyCtxt<'_>,
+ fn_id: LocalDefId,
+ fn_sig: ty::FnSig<'_>,
+ decl: &hir::FnDecl<'_>,
+ declared_ret_ty: Ty<'_>,
+) {
+ let Some(alloc_layout_did) = tcx.lang_items().alloc_layout() else {
+ tcx.sess.err("language item required, but not found: `alloc_layout`");
+ return;
+ };
+
+ if *declared_ret_ty.kind() != ty::Never {
+ tcx.sess.span_err(decl.output.span(), "return type should be `!`");
+ }
+
+ let inputs = fn_sig.inputs();
+ if inputs.len() != 1 {
+ tcx.sess.span_err(tcx.def_span(fn_id), "function should have one argument");
+ return;
+ }
+
+ let arg_is_alloc_layout = match inputs[0].kind() {
+ ty::Adt(ref adt, _) => adt.did() == alloc_layout_did,
+ _ => false,
+ };
+
+ if !arg_is_alloc_layout {
+ tcx.sess.span_err(decl.inputs[0].span, "argument should be `Layout`");
+ }
+
+ let DefKind::Fn = tcx.def_kind(fn_id) else {
+ let span = tcx.def_span(fn_id);
+ tcx.sess.span_err(span, "`#[alloc_error_handler]` should be a function");
+ return;
+ };
+
+ let generic_counts = tcx.generics_of(fn_id).own_counts();
+ if generic_counts.types != 0 {
+ let span = tcx.def_span(fn_id);
+ tcx.sess.span_err(span, "`#[alloc_error_handler]` function should have no type parameters");
+ }
+ if generic_counts.consts != 0 {
+ let span = tcx.def_span(fn_id);
+ tcx.sess
+ .span_err(span, "`#[alloc_error_handler]` function should have no const parameters");
+ }
+}
diff --git a/compiler/rustc_typeck/src/check/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 9b943b160..a5a45f75e 100644
--- a/compiler/rustc_typeck/src/check/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -2,12 +2,11 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
-use crate::astconv::AstConv;
-use crate::rustc_middle::ty::subst::Subst;
use hir::def::DefKind;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
+use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
@@ -177,24 +176,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
- let sig = bounds
- .transpose_iter()
- .map(|e| e.map_bound(|e| *e).transpose_tuple2())
- .find_map(|(pred, span)| match pred.0.kind().skip_binder() {
+ let sig =
+ bounds.subst_iter_copied(self.tcx, substs).find_map(|(pred, span)| match pred
+ .kind()
+ .skip_binder()
+ {
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
- Some(span.0),
- pred.0
- .kind()
- .rebind(pred.rebind(proj_predicate).subst(self.tcx, substs)),
+ Some(span),
+ pred.kind().rebind(proj_predicate),
),
_ => None,
});
let kind = bounds
- .transpose_iter()
- .map(|e| e.map_bound(|e| *e).transpose_tuple2())
- .filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
+ .0
+ .iter()
+ .filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
@@ -642,6 +640,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
bound_vars,
);
+ // Astconv can't normalize inputs or outputs with escaping bound vars,
+ // so normalize them here, after we've wrapped them in a binder.
+ let result = self.normalize_associated_types_in(self.tcx.hir().span(hir_id), result);
let c_result = self.inh.infcx.canonicalize_response(result);
self.typeck_results.borrow_mut().user_provided_sigs.insert(expr_def_id, c_result);
@@ -695,18 +696,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Opaque(def_id, substs) => self
.tcx
.bound_explicit_item_bounds(def_id)
- .transpose_iter()
- .map(|e| e.map_bound(|e| *e).transpose_tuple2())
- .find_map(|(p, s)| get_future_output(p.subst(self.tcx, substs), s.0))?,
+ .subst_iter_copied(self.tcx, substs)
+ .find_map(|(p, s)| get_future_output(p, s))?,
ty::Error(_) => return None,
ty::Projection(proj)
if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
{
self.tcx
.bound_explicit_item_bounds(proj.item_def_id)
- .transpose_iter()
- .map(|e| e.map_bound(|e| *e).transpose_tuple2())
- .find_map(|(p, s)| get_future_output(p.subst(self.tcx, proj.substs), s.0))?
+ .subst_iter_copied(self.tcx, proj.substs)
+ .find_map(|(p, s)| get_future_output(p, s))?
}
_ => span_bug!(
self.tcx.def_span(expr_def_id),
diff --git a/compiler/rustc_typeck/src/check/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index def592c46..86597a703 100644
--- a/compiler/rustc_typeck/src/check/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -35,8 +35,7 @@
//! // and are then unable to coerce `&7i32` to `&mut i32`.
//! ```
-use crate::astconv::AstConv;
-use crate::check::FnCtxt;
+use crate::FnCtxt;
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
@@ -44,6 +43,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Expr;
+use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{Coercion, InferOk, InferResult};
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt};
@@ -61,7 +61,7 @@ use rustc_span::symbol::sym;
use rustc_span::{self, BytePos, DesugaringKind, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
use smallvec::{smallvec, SmallVec};
@@ -216,6 +216,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
ty::Ref(r_b, _, mutbl_b) => {
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
}
+ ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star => {
+ return self.coerce_dyn_star(a, b, predicates, region);
+ }
_ => {}
}
@@ -702,7 +705,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// Object safety violations or miscellaneous.
Err(err) => {
- self.report_selection_error(obligation.clone(), &obligation, &err, false);
+ self.err_ctxt().report_selection_error(
+ obligation.clone(),
+ &obligation,
+ &err,
+ false,
+ );
// Treat this like an obligation and follow through
// with the unsizing - the lack of a coercion should
// be silent, as it causes a type mismatch later.
@@ -740,6 +748,63 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Ok(coercion)
}
+ fn coerce_dyn_star(
+ &self,
+ a: Ty<'tcx>,
+ b: Ty<'tcx>,
+ predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
+ b_region: ty::Region<'tcx>,
+ ) -> CoerceResult<'tcx> {
+ if !self.tcx.features().dyn_star {
+ return Err(TypeError::Mismatch);
+ }
+
+ if let ty::Dynamic(a_data, _, _) = a.kind()
+ && let ty::Dynamic(b_data, _, _) = b.kind()
+ {
+ if a_data.principal_def_id() == b_data.principal_def_id() {
+ return self.unify_and(a, b, |_| vec![]);
+ } else if !self.tcx().features().trait_upcasting {
+ let mut err = feature_err(
+ &self.tcx.sess.parse_sess,
+ sym::trait_upcasting,
+ self.cause.span,
+ &format!(
+ "cannot cast `{a}` to `{b}`, trait upcasting coercion is experimental"
+ ),
+ );
+ err.emit();
+ }
+ }
+
+ // Check the obligations of the cast -- for example, when casting
+ // `usize` to `dyn* Clone + 'static`:
+ let obligations = predicates
+ .iter()
+ .map(|predicate| {
+ // For each existential predicate (e.g., `?Self: Clone`) substitute
+ // the type of the expression (e.g., `usize` in our example above)
+ // and then require that the resulting predicate (e.g., `usize: Clone`)
+ // holds (it does).
+ let predicate = predicate.with_self_ty(self.tcx, a);
+ Obligation::new(self.cause.clone(), self.param_env, predicate)
+ })
+ // Enforce the region bound (e.g., `usize: 'static`, in our example).
+ .chain([Obligation::new(
+ self.cause.clone(),
+ self.param_env,
+ self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives(
+ ty::OutlivesPredicate(a, b_region),
+ ))),
+ )])
+ .collect();
+
+ Ok(InferOk {
+ value: (vec![Adjustment { kind: Adjust::DynStar, target: b }], b),
+ obligations,
+ })
+ }
+
fn coerce_from_safe_fn<F, G>(
&self,
a: Ty<'tcx>,
@@ -1549,7 +1614,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
}
_ => {
- err = fcx.report_mismatched_types(
+ err = fcx.err_ctxt().report_mismatched_types(
cause,
expected,
found,
@@ -1629,7 +1694,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
expression: Option<&'tcx hir::Expr<'tcx>>,
blk_id: Option<hir::HirId>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- let mut err = fcx.report_mismatched_types(cause, expected, found, ty_err);
+ let mut err = fcx.err_ctxt().report_mismatched_types(cause, expected, found, ty_err);
let mut pointing_at_return_type = false;
let mut fn_output = None;
@@ -1683,7 +1748,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
expected,
found,
can_suggest,
- fcx.tcx.hir().local_def_id_to_hir_id(fcx.tcx.hir().get_parent_item(id)),
+ fcx.tcx.hir().get_parent_item(id).into(),
);
}
if !pointing_at_return_type {
@@ -1692,7 +1757,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
}
let parent_id = fcx.tcx.hir().get_parent_item(id);
- let parent_item = fcx.tcx.hir().get_by_def_id(parent_id);
+ let parent_item = fcx.tcx.hir().get_by_def_id(parent_id.def_id);
if let (Some(expr), Some(_), Some((fn_decl, _, _))) =
(expression, blk_id, fcx.get_node_fn_decl(parent_item))
@@ -1704,7 +1769,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
expected,
found,
id,
- fcx.tcx.hir().local_def_id_to_hir_id(parent_id),
+ parent_id.into(),
);
}
diff --git a/compiler/rustc_typeck/src/check/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index e1d55ff82..16febfc46 100644
--- a/compiler/rustc_typeck/src/check/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -1,21 +1,20 @@
-use crate::check::FnCtxt;
-use rustc_infer::infer::InferOk;
-use rustc_middle::middle::stability::EvalResult;
-use rustc_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::ObligationCause;
-
+use crate::FnCtxt;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
use rustc_hir as hir;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{is_range_literal, Node};
+use rustc_infer::infer::InferOk;
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_span::symbol::{sym, Symbol};
use rustc_span::{BytePos, Span};
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::ObligationCause;
use super::method::probe;
@@ -32,17 +31,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error: Option<TypeError<'tcx>>,
) {
self.annotate_expected_due_to_let_ty(err, expr, error);
- self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr);
- self.suggest_compatible_variants(err, expr, expected, expr_ty);
- self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty);
- if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
- return;
- }
- self.suggest_no_capture_closure(err, expected, expr_ty);
- self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
- self.suggest_missing_parentheses(err, expr);
- self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected);
- self.suggest_copied_or_cloned(err, expr, expr_ty, expected);
+
+ // Use `||` to give these suggestions a precedence
+ let _ = self.suggest_missing_parentheses(err, expr)
+ || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr)
+ || self.suggest_compatible_variants(err, expr, expected, expr_ty)
+ || self.suggest_non_zero_new_unwrap(err, expr, expected, expr_ty)
+ || self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty)
+ || self.suggest_no_capture_closure(err, expected, expr_ty)
+ || self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty)
+ || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
+ || self.suggest_copied_or_cloned(err, expr, expr_ty, expected)
+ || self.suggest_into(err, expr, expr_ty, expected);
+
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);
@@ -77,7 +78,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_predicates(obligations);
None
}
- Err(e) => Some(self.report_mismatched_types(&cause, expected, actual, e)),
+ Err(e) => Some(self.err_ctxt().report_mismatched_types(&cause, expected, actual, e)),
}
}
@@ -107,7 +108,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.register_predicates(obligations);
None
}
- Err(e) => Some(self.report_mismatched_types(cause, expected, actual, e)),
+ Err(e) => Some(self.err_ctxt().report_mismatched_types(cause, expected, actual, e)),
}
}
@@ -151,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expr = expr.peel_drop_temps();
let cause = self.misc(expr.span);
let expr_ty = self.resolve_vars_with_obligations(checked_ty);
- let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e.clone());
+ let mut err = self.err_ctxt().report_mismatched_types(&cause, expected, expr_ty, e.clone());
let is_insufficiently_polymorphic =
matches!(e, TypeError::RegionsInsufficientlyPolymorphic(..));
@@ -286,7 +287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
expected: Ty<'tcx>,
expr_ty: Ty<'tcx>,
- ) {
+ ) -> bool {
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);
@@ -299,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"",
Applicability::MaybeIncorrect,
);
- return
+ return true;
}
}
@@ -338,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else if self.tcx.is_diagnostic_item(sym::Option, expected_adt.did()) {
vec!["None", "Some(())"]
} else {
- return;
+ return false;
};
if let Some(indent) =
self.tcx.sess.source_map().indentation_before(span.shrink_to_lo())
@@ -358,7 +359,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
}
- return;
+ return true;
}
}
}
@@ -375,7 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let field_is_local = sole_field.did.is_local();
let field_is_accessible =
- sole_field.vis.is_accessible_from(expr.hir_id.owner, self.tcx)
+ sole_field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
// Skip suggestions for unstable public fields (for example `Pin::pointer`)
&& matches!(self.tcx.eval_stability(sole_field.did, None, expr.span, None), EvalResult::Allow | EvalResult::Unmarked);
@@ -417,6 +418,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::def::CtorKind::Const => unreachable!(),
};
+ // Suggest constructor as deep into the block tree as possible.
+ // This fixes https://github.com/rust-lang/rust/issues/101065,
+ // and also just helps make the most minimal suggestions.
+ let mut expr = expr;
+ while let hir::ExprKind::Block(block, _) = &expr.kind
+ && let Some(expr_) = &block.expr
+ {
+ expr = expr_
+ }
+
vec![
(expr.span.shrink_to_lo(), format!("{prefix}{variant}{open}")),
(expr.span.shrink_to_hi(), close.to_owned()),
@@ -435,6 +446,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggestions_for(&**variant, *ctor_kind, *field_name),
Applicability::MaybeIncorrect,
);
+ return true;
}
_ => {
// More than one matching variant.
@@ -450,9 +462,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
Applicability::MaybeIncorrect,
);
+ return true;
}
}
}
+
+ false
}
fn suggest_non_zero_new_unwrap(
@@ -461,19 +476,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
expected: Ty<'tcx>,
expr_ty: Ty<'tcx>,
- ) {
+ ) -> bool {
let tcx = self.tcx;
let (adt, unwrap) = match expected.kind() {
// In case Option<NonZero*> is wanted, but * is provided, suggest calling new
ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
// Unwrap option
- let ty::Adt(adt, _) = substs.type_at(0).kind() else { return };
+ let ty::Adt(adt, _) = substs.type_at(0).kind() else { return false; };
(adt, "")
}
// In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
ty::Adt(adt, _) => (adt, ".unwrap()"),
- _ => return,
+ _ => return false,
};
let map = [
@@ -492,7 +507,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let Some((s, _)) = map
.iter()
.find(|&&(s, t)| self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t))
- else { return };
+ else { return false; };
let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
@@ -504,6 +519,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
],
Applicability::MaybeIncorrect,
);
+
+ true
}
pub fn get_conversion_methods(
@@ -513,24 +530,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
checked_ty: Ty<'tcx>,
hir_id: hir::HirId,
) -> Vec<AssocItem> {
- let mut methods =
- self.probe_for_return_type(span, probe::Mode::MethodCall, expected, checked_ty, hir_id);
- methods.retain(|m| {
- self.has_only_self_parameter(m)
- && self
- .tcx
- // This special internal attribute is used to permit
- // "identity-like" conversion methods to be suggested here.
- //
- // FIXME (#46459 and #46460): ideally
- // `std::convert::Into::into` and `std::borrow:ToOwned` would
- // also be `#[rustc_conversion_suggestion]`, if not for
- // method-probing false-positives and -negatives (respectively).
- //
- // FIXME? Other potential candidate methods: `as_ref` and
- // `as_mut`?
- .has_attr(m.def_id, sym::rustc_conversion_suggestion)
- });
+ let methods = self.probe_for_return_type(
+ span,
+ probe::Mode::MethodCall,
+ expected,
+ checked_ty,
+ hir_id,
+ |m| {
+ self.has_only_self_parameter(m)
+ && self
+ .tcx
+ // This special internal attribute is used to permit
+ // "identity-like" conversion methods to be suggested here.
+ //
+ // FIXME (#46459 and #46460): ideally
+ // `std::convert::Into::into` and `std::borrow:ToOwned` would
+ // also be `#[rustc_conversion_suggestion]`, if not for
+ // method-probing false-positives and -negatives (respectively).
+ //
+ // FIXME? Other potential candidate methods: `as_ref` and
+ // `as_mut`?
+ .has_attr(m.def_id, sym::rustc_conversion_suggestion)
+ },
+ );
methods
}
@@ -697,7 +719,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'tcx>,
checked_ty: Ty<'tcx>,
expected: Ty<'tcx>,
- ) -> Option<(Span, String, String, Applicability, bool /* verbose */)> {
+ ) -> Option<(
+ Span,
+ String,
+ String,
+ Applicability,
+ bool, /* verbose */
+ bool, /* suggest `&` or `&mut` type annotation */
+ )> {
let sess = self.sess();
let sp = expr.span;
@@ -729,6 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
+ false,
));
}
}
@@ -743,6 +773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"b".to_string(),
Applicability::MachineApplicable,
true,
+ false,
));
}
}
@@ -800,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg.2,
Applicability::MachineApplicable,
false,
+ false,
));
}
@@ -827,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{prefix}&mut {sugg_expr}"),
Applicability::MachineApplicable,
false,
+ false,
),
hir::Mutability::Not => (
sp,
@@ -834,6 +867,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("{prefix}&{sugg_expr}"),
Applicability::MachineApplicable,
false,
+ false,
),
});
}
@@ -863,6 +897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
+ true
));
}
return None;
@@ -876,6 +911,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
String::new(),
Applicability::MachineApplicable,
true,
+ true,
));
}
}
@@ -942,6 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
src,
applicability,
true,
+ false,
));
}
}
@@ -982,6 +1019,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Applicability::MachineApplicable
},
true,
+ false,
));
}
@@ -1033,6 +1071,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggestion,
Applicability::MachineApplicable,
true,
+ false,
));
}
}
diff --git a/compiler/rustc_typeck/src/check/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs
index 963a93a95..963a93a95 100644
--- a/compiler/rustc_typeck/src/check/diverges.rs
+++ b/compiler/rustc_hir_typeck/src/diverges.rs
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
new file mode 100644
index 000000000..175037f9b
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -0,0 +1,126 @@
+//! Errors emitted by `rustc_hir_analysis`.
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_middle::ty::Ty;
+use rustc_span::{symbol::Ident, Span};
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_field_multiply_specified_in_initializer, code = "E0062")]
+pub struct FieldMultiplySpecifiedInInitializer {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(previous_use_label)]
+ pub prev_span: Span,
+ pub ident: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_stmt_outside_of_fn_body, code = "E0572")]
+pub struct ReturnStmtOutsideOfFnBody {
+ #[primary_span]
+ pub span: Span,
+ #[label(encl_body_label)]
+ pub encl_body_span: Option<Span>,
+ #[label(encl_fn_label)]
+ pub encl_fn_span: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_yield_expr_outside_of_generator, code = "E0627")]
+pub struct YieldExprOutsideOfGenerator {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_struct_expr_non_exhaustive, code = "E0639")]
+pub struct StructExprNonExhaustive {
+ #[primary_span]
+ pub span: Span,
+ pub what: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_method_call_on_unknown_type, code = "E0699")]
+pub struct MethodCallOnUnknownType {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_functional_record_update_on_non_struct, code = "E0436")]
+pub struct FunctionalRecordUpdateOnNonStruct {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_address_of_temporary_taken, code = "E0745")]
+pub struct AddressOfTemporaryTaken {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub enum AddReturnTypeSuggestion {
+ #[suggestion(
+ hir_analysis_add_return_type_add,
+ code = "-> {found} ",
+ applicability = "machine-applicable"
+ )]
+ Add {
+ #[primary_span]
+ span: Span,
+ found: String,
+ },
+ #[suggestion(
+ hir_analysis_add_return_type_missing_here,
+ code = "-> _ ",
+ applicability = "has-placeholders"
+ )]
+ MissingHere {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub enum ExpectedReturnTypeLabel<'tcx> {
+ #[label(hir_analysis_expected_default_return_type)]
+ Unit {
+ #[primary_span]
+ span: Span,
+ },
+ #[label(hir_analysis_expected_return_type)]
+ Other {
+ #[primary_span]
+ span: Span,
+ expected: Ty<'tcx>,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_missing_parentheses_in_range, code = "E0689")]
+pub struct MissingParentheseInRange {
+ #[primary_span]
+ #[label(hir_analysis_missing_parentheses_in_range)]
+ pub span: Span,
+ pub ty_str: String,
+ pub method_name: String,
+ #[subdiagnostic]
+ pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion_verbose(
+ hir_analysis_add_missing_parentheses_in_range,
+ applicability = "maybe-incorrect"
+)]
+pub struct AddMissingParenthesesInRange {
+ pub func_name: String,
+ #[suggestion_part(code = "(")]
+ pub left: Span,
+ #[suggestion_part(code = ")")]
+ pub right: Span,
+}
diff --git a/compiler/rustc_typeck/src/check/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index e9e810344..e9e810344 100644
--- a/compiler/rustc_typeck/src/check/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 93b008500..9fde62a81 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2,23 +2,22 @@
//!
//! See `mod.rs` for more context on type checking in general.
-use crate::astconv::AstConv as _;
-use crate::check::cast::{self, CastCheckResult};
-use crate::check::coercion::CoerceMany;
-use crate::check::fatally_break_rust;
-use crate::check::method::SelfSource;
-use crate::check::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
-use crate::check::{
- report_unexpected_variant_res, BreakableCtxt, Diverges, DynamicCoerceMany, FnCtxt, Needs,
- TupleArgumentsFlag::DontTupleArguments,
-};
+use crate::cast;
+use crate::coercion::CoerceMany;
+use crate::coercion::DynamicCoerceMany;
+use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
use crate::errors::{
FieldMultiplySpecifiedInInitializer, FunctionalRecordUpdateOnNonStruct,
YieldExprOutsideOfGenerator,
};
+use crate::fatally_break_rust;
+use crate::method::SelfSource;
use crate::type_error_struct;
-
-use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive};
+use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation};
+use crate::{
+ report_unexpected_variant_res, BreakableCtxt, Diverges, FnCtxt, Needs,
+ TupleArgumentsFlag::DontTupleArguments,
+};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -32,6 +31,8 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Closure, ExprKind, HirId, QPath};
+use rustc_hir_analysis::astconv::AstConv as _;
+use rustc_hir_analysis::check::ty_kind_suggestion;
use rustc_infer::infer;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::InferOk;
@@ -41,6 +42,7 @@ 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_session::errors::ExprParenthesesNeeded;
use rustc_session::parse::feature_err;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::lev_distance::find_best_match_for_name;
@@ -394,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(sp) =
tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
{
- tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
err.emit();
oprnd_t = tcx.ty_error();
@@ -541,7 +543,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// been resolved or we errored. This is important as we can only check transmute
// on concrete types, but the output type may not be known yet (it would only
// be known if explicitly specified via turbofish).
- self.deferred_transmute_checks.borrow_mut().push((from, to, expr.span));
+ self.deferred_transmute_checks.borrow_mut().push((from, to, expr.hir_id));
}
if !tcx.features().unsized_fn_params {
// We want to remove some Sized bounds from std functions,
@@ -752,7 +754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
kind: hir::ImplItemKind::Fn(..),
span: encl_fn_span,
..
- })) = self.tcx.hir().find_by_def_id(encl_item_id)
+ })) = self.tcx.hir().find_by_def_id(encl_item_id.def_id)
{
// We are inside a function body, so reporting "return statement
// outside of function body" needs an explanation.
@@ -761,7 +763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If this didn't hold, we would not have to report an error in
// the first place.
- assert_ne!(encl_item_id, encl_body_owner_id);
+ assert_ne!(encl_item_id.def_id, encl_body_owner_id);
let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
let encl_body = self.tcx.hir().body(encl_body_id);
@@ -881,7 +883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
- // FIXME: Make this use SessionDiagnostic once error codes can be dynamically set.
+ // FIXME: Make this use Diagnostic once error codes can be dynamically set.
let mut err = self.tcx.sess.struct_span_err_with_code(
op_span,
"invalid left-hand side of assignment",
@@ -1044,6 +1046,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let rhs_ty = self.check_expr(&rhs);
let (applicability, eq) = if self.can_coerce(rhs_ty, lhs_ty) {
(Applicability::MachineApplicable, true)
+ } else if let ExprKind::Binary(
+ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ _,
+ rhs_expr,
+ ) = lhs.kind
+ {
+ // if x == 1 && y == 2 { .. }
+ // +
+ let actual_lhs_ty = self.check_expr(&rhs_expr);
+ (Applicability::MaybeIncorrect, self.can_coerce(rhs_ty, actual_lhs_ty))
+ } else if let ExprKind::Binary(
+ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
+ lhs_expr,
+ _,
+ ) = rhs.kind
+ {
+ // if x == 1 && y == 2 { .. }
+ // +
+ let actual_rhs_ty = self.check_expr(&lhs_expr);
+ (Applicability::MaybeIncorrect, self.can_coerce(actual_rhs_ty, lhs_ty))
} else {
(Applicability::MaybeIncorrect, false)
};
@@ -1066,9 +1088,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
if eq {
err.span_suggestion_verbose(
- span,
+ span.shrink_to_hi(),
"you might have meant to compare for equality",
- "==",
+ '=',
applicability,
);
}
@@ -1109,11 +1131,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- self.check_lhs_assignable(lhs, "E0070", span, |err| {
- let rhs_ty = self.check_expr(&rhs);
- suggest_deref_binop(err, rhs_ty);
- });
-
// This is (basically) inlined `check_expr_coercable_to_type`, but we want
// to suggest an additional fixup here in `suggest_deref_binop`.
let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty);
@@ -1124,6 +1141,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diag.emit();
}
+ self.check_lhs_assignable(lhs, "E0070", span, |err| {
+ if let Some(rhs_ty) = self.typeck_results.borrow().expr_ty_opt(rhs) {
+ suggest_deref_binop(err, rhs_ty);
+ }
+ });
+
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
if lhs_ty.references_error() || rhs_ty.references_error() {
@@ -1249,9 +1272,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// Defer other checks until we're done type checking.
let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
- match cast::check_cast(self, e, t_expr, t_cast, t.span, expr.span) {
- CastCheckResult::Ok => t_cast,
- CastCheckResult::Deferred(cast_check) => {
+ match cast::CastCheck::new(
+ self,
+ e,
+ t_expr,
+ t_cast,
+ t.span,
+ expr.span,
+ self.param_env.constness(),
+ ) {
+ Ok(cast_check) => {
debug!(
"check_expr_cast: deferring cast from {:?} to {:?}: {:?}",
t_cast, t_expr, cast_check,
@@ -1259,7 +1289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
deferred_cast_checks.push(cast_check);
t_cast
}
- CastCheckResult::Err(ErrorGuaranteed { .. }) => self.tcx.ty_error(),
+ Err(_) => self.tcx.ty_error(),
}
}
}
@@ -1341,7 +1371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Create a new function context.
let fcx = FnCtxt::new(self, self.param_env.with_const(), body.value.hir_id);
- crate::check::GatherLocalsVisitor::new(&fcx).visit_body(body);
+ crate::GatherLocalsVisitor::new(&fcx).visit_body(body);
let ty = fcx.check_expr_with_expectation(&body.value, expected);
fcx.require_type_is_sized(ty, body.value.span, traits::ConstSized);
@@ -1640,13 +1670,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Err(_) => {
// This should never happen, since we're just subtyping the
// remaining_fields, but it's fine to emit this, I guess.
- self.report_mismatched_types(
- &cause,
- target_ty,
- fru_ty,
- FieldMisMatch(variant.name, ident.name),
- )
- .emit();
+ self.err_ctxt()
+ .report_mismatched_types(
+ &cause,
+ target_ty,
+ fru_ty,
+ FieldMisMatch(variant.name, ident.name),
+ )
+ .emit();
}
}
}
@@ -1933,7 +1964,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.set_tainted_by_errors();
return;
}
- let mut err = self.type_error_struct_with_diag(
+ let mut err = self.err_ctxt().type_error_struct_with_diag(
field.ident.span,
|actual| match ty.kind() {
ty::Adt(adt, ..) if adt.is_enum() => struct_span_err!(
@@ -2338,7 +2369,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() {
def.non_enum_variant().fields.iter().any(|field| {
field.ident(self.tcx) == ident
- && field.vis.is_accessible_from(expr.hir_id.owner, self.tcx)
+ && field.vis.is_accessible_from(expr.hir_id.owner.def_id, self.tcx)
})
} else if let ty::Tuple(tys) = output_ty.kind()
&& let Ok(idx) = ident.as_str().parse::<usize>()
@@ -2863,14 +2894,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
-
-pub(super) fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
- Some(match ty.kind() {
- ty::Bool => "true",
- ty::Char => "'a'",
- ty::Int(_) | ty::Uint(_) => "42",
- ty::Float(_) => "3.14159",
- ty::Error(_) | ty::Never => return None,
- _ => "value",
- })
-}
diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index f483342b4..fce2a5888 100644
--- a/compiler/rustc_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -89,15 +89,6 @@ enum ConsumeMode {
Move,
}
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum MutateMode {
- Init,
- /// Example: `x = y`
- JustWrite,
- /// Example: `x += y`
- WriteAndRead,
-}
-
/// The ExprUseVisitor type
///
/// This is the code that actually walks the tree.
@@ -134,7 +125,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
/// - `typeck_results` --- typeck results for the code being analyzed
pub fn new(
delegate: &'a mut (dyn Delegate<'tcx> + 'a),
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
body_owner: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
typeck_results: &'a ty::TypeckResults<'tcx>,
@@ -583,7 +574,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
for adjustment in adjustments {
debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment);
match adjustment.kind {
- adjustment::Adjust::NeverToAny | adjustment::Adjust::Pointer(_) => {
+ adjustment::Adjust::NeverToAny
+ | adjustment::Adjust::Pointer(_)
+ | adjustment::Adjust::DynStar => {
// Creating a closure/fn-pointer or unsizing consumes
// the input and stores it into the resulting rvalue.
self.delegate_consume(&place_with_id, place_with_id.hir_id);
diff --git a/compiler/rustc_typeck/src/check/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 4059b3403..747ecb036 100644
--- a/compiler/rustc_typeck/src/check/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -1,4 +1,4 @@
-use crate::check::FnCtxt;
+use crate::FnCtxt;
use rustc_data_structures::{
fx::{FxHashMap, FxHashSet},
graph::WithSuccessors,
@@ -72,7 +72,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
//
// - Unconstrained ints are replaced with `i32`.
//
- // - Unconstrained floats are replaced with with `f64`.
+ // - Unconstrained floats are replaced with `f64`.
//
// - Non-numerics may get replaced with `()` or `!`, depending on
// how they were categorized by `calculate_diverging_fallback`
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index a40478db9..6a1cffe3e 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1,12 +1,7 @@
-use crate::astconv::{
- AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
- GenericArgCountResult, IsMethodCall, PathSeg,
-};
-use crate::check::callee::{self, DeferredCallResolution};
-use crate::check::method::{self, MethodCallee, SelfSource};
-use crate::check::rvalue_scopes;
-use crate::check::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
-
+use crate::callee::{self, DeferredCallResolution};
+use crate::method::{self, MethodCallee, SelfSource};
+use crate::rvalue_scopes;
+use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy};
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{Applicability, Diagnostic, ErrorGuaranteed, MultiSpan};
@@ -15,26 +10,28 @@ use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ExprKind, GenericArg, Node, QPath};
+use rustc_hir_analysis::astconv::{
+ AstConv, CreateSubstsForGenericArgsCtxt, ExplicitLateBound, GenericArgCountMismatch,
+ GenericArgCountResult, IsMethodCall, PathSeg,
+};
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{
- self, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSelfTy, UserSubsts,
-};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef,
ToPredicate, Ty, UserType,
};
+use rustc_middle::ty::{GenericArgKind, InternalSubsts, 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_trait_selection::infer::InferCtxtExt as _;
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt,
};
@@ -60,17 +57,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
- self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, |lint| {
- let msg = format!("unreachable {}", kind);
- lint.build(&msg)
- .span_label(span, &msg)
- .span_label(
+ let msg = format!("unreachable {}", kind);
+ self.tcx().struct_span_lint_hir(
+ lint::builtin::UNREACHABLE_CODE,
+ id,
+ span,
+ &msg,
+ |lint| {
+ lint.span_label(span, &msg).span_label(
orig_span,
custom_note
.unwrap_or("any code following this expression is unreachable"),
)
- .emit();
- })
+ },
+ )
}
}
}
@@ -90,14 +90,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mutate_fulfillment_errors: impl Fn(&mut Vec<traits::FulfillmentError<'tcx>>),
) -> Ty<'tcx> {
// No Infer()? Nothing needs doing.
- if !ty.has_infer_types_or_consts() {
+ if !ty.has_non_region_infer() {
debug!("no inference var, nothing needs doing");
return ty;
}
// If `ty` is a type variable, see whether we already know what it is.
ty = self.resolve_vars_if_possible(ty);
- if !ty.has_infer_types_or_consts() {
+ if !ty.has_non_region_infer() {
debug!(?ty);
return ty;
}
@@ -489,18 +489,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn array_length_to_const(&self, length: &hir::ArrayLen) -> ty::Const<'tcx> {
match length {
&hir::ArrayLen::Infer(_, span) => self.ct_infer(self.tcx.types.usize, None, span),
- hir::ArrayLen::Body(anon_const) => self.to_const(anon_const),
+ hir::ArrayLen::Body(anon_const) => {
+ let const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
+ let span = self.tcx.hir().span(anon_const.hir_id);
+ let c = ty::Const::from_anon_const(self.tcx, const_def_id);
+ self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
+ self.normalize_associated_types_in(span, c)
+ }
}
}
- pub fn to_const(&self, ast_c: &hir::AnonConst) -> ty::Const<'tcx> {
- let const_def_id = self.tcx.hir().local_def_id(ast_c.hir_id);
- let span = self.tcx.hir().span(ast_c.hir_id);
- let c = ty::Const::from_anon_const(self.tcx, const_def_id);
- self.register_wf_obligation(c.into(), span, ObligationCauseCode::WellFormed(None));
- self.normalize_associated_types_in(span, c)
- }
-
pub fn const_arg_to_const(
&self,
ast_c: &hir::AnonConst,
@@ -559,7 +557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Registers an obligation for checking later, during regionck, that `arg` is well-formed.
pub fn register_wf_obligation(
&self,
- arg: subst::GenericArg<'tcx>,
+ arg: ty::GenericArg<'tcx>,
span: Span,
code: traits::ObligationCauseCode<'tcx>,
) {
@@ -604,9 +602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut generators = self.deferred_generator_interiors.borrow_mut();
for (body_id, interior, kind) in generators.drain(..) {
self.select_obligations_where_possible(false, |_| {});
- crate::check::generator_interior::resolve_interior(
- self, def_id, body_id, interior, kind,
- );
+ crate::generator_interior::resolve_interior(self, def_id, body_id, interior, kind);
}
}
@@ -616,7 +612,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !errors.is_empty() {
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
- self.report_fulfillment_errors(&errors, self.inh.body_id, false);
+ self.err_ctxt().report_fulfillment_errors(&errors, self.inh.body_id, false);
}
}
@@ -630,7 +626,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !result.is_empty() {
mutate_fulfillment_errors(&mut result);
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
- self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
+ self.err_ctxt().report_fulfillment_errors(
+ &result,
+ self.inh.body_id,
+ fallback_has_occurred,
+ );
}
}
@@ -1271,7 +1271,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut self,
param: &ty::GenericParamDef,
arg: &GenericArg<'_>,
- ) -> subst::GenericArg<'tcx> {
+ ) -> ty::GenericArg<'tcx> {
match (&param.kind, arg) {
(GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => {
<dyn AstConv<'_>>::ast_region_to_region(self.fcx, lt, Some(param)).into()
@@ -1295,10 +1295,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn inferred_kind(
&mut self,
- substs: Option<&[subst::GenericArg<'tcx>]>,
+ substs: Option<&[ty::GenericArg<'tcx>]>,
param: &ty::GenericParamDef,
infer_args: bool,
- ) -> subst::GenericArg<'tcx> {
+ ) -> ty::GenericArg<'tcx> {
let tcx = self.fcx.tcx();
match param.kind {
GenericParamDefKind::Lifetime => {
@@ -1410,7 +1410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
})
}
- #[instrument(level = "debug", skip(self, code, span, def_id, substs))]
+ #[instrument(level = "debug", skip(self, code, span, substs))]
fn add_required_obligations_with_code(
&self,
span: Span,
@@ -1418,15 +1418,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
substs: SubstsRef<'tcx>,
code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>,
) {
+ let param_env = self.param_env;
+
+ let remap = match self.tcx.def_kind(def_id) {
+ // Associated consts have `Self: ~const Trait` bounds that should be satisfiable when
+ // `Self: Trait` is satisfied because it does not matter whether the impl is `const`.
+ // Therefore we have to remap the param env here to be non-const.
+ hir::def::DefKind::AssocConst => true,
+ hir::def::DefKind::AssocFn
+ if self.tcx.def_kind(self.tcx.parent(def_id)) == hir::def::DefKind::Trait =>
+ {
+ // N.B.: All callsites to this function involve checking a path expression.
+ //
+ // When instantiating a trait method as a function item, it does not actually matter whether
+ // the trait is `const` or not, or whether `where T: ~const Tr` needs to be satisfied as
+ // `const`. If we were to introduce instantiating trait methods as `const fn`s, we would
+ // check that after this, either via a bound `where F: ~const FnOnce` or when coercing to a
+ // `const fn` pointer.
+ //
+ // FIXME(fee1-dead) FIXME(const_trait_impl): update this doc when trait methods can satisfy
+ // `~const FnOnce` or can be coerced to `const fn` pointer.
+ true
+ }
+ _ => false,
+ };
let (bounds, _) = self.instantiate_bounds(span, def_id, &substs);
- for obligation in traits::predicates_for_generics(
+ for mut obligation in traits::predicates_for_generics(
|idx, predicate_span| {
traits::ObligationCause::new(span, self.body_id, code(idx, predicate_span))
},
- self.param_env,
+ param_env,
bounds,
) {
+ if remap {
+ obligation = obligation.without_const(self.tcx);
+ }
self.register_predicate(obligation);
}
}
@@ -1440,7 +1467,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty
} else {
if !self.is_tainted_by_errors() {
- self.emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
+ self.err_ctxt()
+ .emit_inference_failure_err((**self).body_id, sp, ty.into(), E0282, true)
.emit();
}
let err = self.tcx.ty_error();
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
index fc83994ca..fc83994ca 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/arg_matrix.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/arg_matrix.rs
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 311fcaada..8e0fcb56c 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,19 +1,13 @@
-use crate::astconv::AstConv;
-use crate::check::coercion::CoerceMany;
-use crate::check::fn_ctxt::arg_matrix::{
- ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx,
+use crate::coercion::CoerceMany;
+use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
+use crate::gather_locals::Declaration;
+use crate::method::MethodCallee;
+use crate::Expectation::*;
+use crate::TupleArgumentsFlag::*;
+use crate::{
+ struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt, LocalTy, Needs,
+ TupleArgumentsFlag,
};
-use crate::check::gather_locals::Declaration;
-use crate::check::intrinsicck::InlineAsmCtxt;
-use crate::check::method::MethodCallee;
-use crate::check::Expectation::*;
-use crate::check::TupleArgumentsFlag::*;
-use crate::check::{
- potentially_plural_count, struct_span_err, BreakableCtxt, Diverges, Expectation, FnCtxt,
- LocalTy, Needs, TupleArgumentsFlag,
-};
-use crate::structured_errors::StructuredDiagnostic;
-
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
@@ -21,6 +15,10 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::{ExprKind, Node, QPath};
+use rustc_hir_analysis::astconv::AstConv;
+use rustc_hir_analysis::check::intrinsicck::InlineAsmCtxt;
+use rustc_hir_analysis::check::potentially_plural_count;
+use rustc_hir_analysis::structured_errors::StructuredDiagnostic;
use rustc_index::vec::IndexVec;
use rustc_infer::infer::error_reporting::{FailureCode, ObligationCauseExt};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -35,23 +33,34 @@ use rustc_span::{self, sym, Span};
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(&self) {
- let mut deferred_cast_checks = self.deferred_cast_checks.borrow_mut();
+ pub(in super::super) fn check_casts(&mut self) {
+ // don't hold the borrow to deferred_cast_checks while checking to avoid borrow checker errors
+ // when writing to `self.param_env`.
+ let mut deferred_cast_checks = mem::take(&mut *self.deferred_cast_checks.borrow_mut());
+
debug!("FnCtxt::check_casts: {} deferred checks", deferred_cast_checks.len());
for cast in deferred_cast_checks.drain(..) {
+ let prev_env = self.param_env;
+ self.param_env = self.param_env.with_constness(cast.constness);
+
cast.check(self);
+
+ self.param_env = prev_env;
}
+
+ *self.deferred_cast_checks.borrow_mut() = deferred_cast_checks;
}
pub(in super::super) fn check_transmutes(&self) {
let mut deferred_transmute_checks = self.deferred_transmute_checks.borrow_mut();
debug!("FnCtxt::check_transmutes: {} deferred checks", deferred_transmute_checks.len());
- for (from, to, span) in deferred_transmute_checks.drain(..) {
- self.check_transmute(span, from, to);
+ for (from, to, hir_id) in deferred_transmute_checks.drain(..) {
+ self.check_transmute(from, to, hir_id);
}
}
@@ -63,7 +72,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let get_operand_ty = |expr| {
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.resolve_vars_if_possible(ty);
- if ty.has_infer_types_or_consts() {
+ if ty.has_non_region_infer() {
assert!(self.is_tainted_by_errors());
self.tcx.ty_error()
} else {
@@ -391,7 +400,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty: Ty<'tcx>,
cast_ty: &str,
) {
- use crate::structured_errors::MissingCastForVariadicArg;
+ use rustc_hir_analysis::structured_errors::MissingCastForVariadicArg;
MissingCastForVariadicArg { sess, span, ty, cast_ty }.diagnostic().emit();
}
@@ -650,7 +659,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if tys.len() == 1 {
// A tuple wrap suggestion actually occurs within,
// so don't do anything special here.
- err = self.report_and_explain_type_error(
+ err = self.err_ctxt().report_and_explain_type_error(
TypeTrace::types(
&self.misc(*lo),
true,
@@ -742,7 +751,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = &self.misc(provided_span);
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308(_)) {
- self.report_and_explain_type_error(trace, *e).emit();
+ self.err_ctxt().report_and_explain_type_error(trace, *e).emit();
return true;
}
false
@@ -766,7 +775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let (provided_ty, provided_arg_span) = provided_arg_tys[*provided_idx];
let cause = &self.misc(provided_arg_span);
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
- let mut err = self.report_and_explain_type_error(trace, *err);
+ let mut err = self.err_ctxt().report_and_explain_type_error(trace, *err);
self.emit_coerce_suggestions(
&mut err,
&provided_args[*provided_idx],
@@ -840,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cause = &self.misc(provided_span);
let trace = TypeTrace::types(cause, true, expected_ty, provided_ty);
if let Some(e) = error {
- self.note_type_err(
+ self.err_ctxt().note_type_err(
&mut err,
&trace.cause,
None,
@@ -1199,7 +1208,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => bug!("unexpected type: {:?}", ty),
},
Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
- | Res::SelfTy { .. } => match ty.kind() {
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. } => match ty.kind() {
ty::Adt(adt, substs) if !adt.is_enum() => {
Some((adt.non_enum_variant(), adt.did(), substs))
}
@@ -1473,7 +1483,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&mut |err| {
if let Some(expected_ty) = expected.only_has_type(self) {
if !self.consider_removing_semicolon(blk, expected_ty, err) {
- self.consider_returning_binding(blk, expected_ty, err);
+ self.err_ctxt().consider_returning_binding(
+ blk,
+ expected_ty,
+ err,
+ );
}
if expected_ty == self.tcx.types.bool {
// If this is caused by a missing `let` in a `while let`,
@@ -1543,7 +1557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
fn parent_item_span(&self, id: hir::HirId) -> Option<Span> {
- let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id));
+ let node = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(id).def_id);
match node {
Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })
| Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => {
@@ -1559,7 +1573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Given a function block's `HirId`, returns its `FnDecl` if it exists, or `None` otherwise.
fn get_parent_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl<'tcx>, Ident)> {
- let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id));
+ let parent = self.tcx.hir().get_by_def_id(self.tcx.hir().get_parent_item(blk_id).def_id);
self.get_node_fn_decl(parent).map(|(fn_decl, ident, _)| (fn_decl, ident))
}
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 0e22971d3..0c600daf4 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -6,13 +6,13 @@ mod suggestions;
pub use _impl::*;
pub use suggestions::*;
-use crate::astconv::AstConv;
-use crate::check::coercion::DynamicCoerceMany;
-use crate::check::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
-
+use crate::coercion::DynamicCoerceMany;
+use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
+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;
@@ -35,7 +35,7 @@ use std::ops::Deref;
///
/// See [`ItemCtxt`]'s docs for more.
///
-/// [`ItemCtxt`]: crate::collect::ItemCtxt
+/// [`ItemCtxt`]: rustc_hir_analysis::collect::ItemCtxt
/// [`InferCtxt`]: infer::InferCtxt
pub struct FnCtxt<'a, 'tcx> {
pub(super) body_id: hir::HirId,
@@ -117,7 +117,7 @@ pub struct FnCtxt<'a, 'tcx> {
pub(super) enclosing_breakables: RefCell<EnclosingBreakables<'tcx>>,
- pub(super) inh: &'a Inherited<'a, 'tcx>,
+ pub(super) inh: &'a Inherited<'tcx>,
/// True if the function or closure's return type is known before
/// entering the function/closure, i.e. if the return type is
@@ -131,7 +131,7 @@ pub struct FnCtxt<'a, 'tcx> {
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub fn new(
- inh: &'a Inherited<'a, 'tcx>,
+ inh: &'a Inherited<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
) -> FnCtxt<'a, 'tcx> {
@@ -168,13 +168,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self.tcx.sess
}
+ /// Creates an `TypeErrCtxt` with a reference to the in-progress
+ /// `TypeckResults` which is used for diagnostics.
+ /// Use [`InferCtxt::err_ctxt`] to start one without a `TypeckResults`.
+ ///
+ /// [`InferCtxt::err_ctxt`]: infer::InferCtxt::err_ctxt
+ pub fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
+ TypeErrCtxt { infcx: &self.infcx, typeck_results: Some(self.typeck_results.borrow()) }
+ }
+
pub fn errors_reported_since_creation(&self) -> bool {
self.tcx.sess.err_count() > self.err_count_on_creation
}
}
impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> {
- type Target = Inherited<'a, 'tcx>;
+ type Target = Inherited<'tcx>;
fn deref(&self) -> &Self::Target {
&self.inh
}
@@ -276,7 +285,6 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
let item_substs = <dyn AstConv<'tcx>>::create_substs_for_associated_item(
self,
- self.tcx,
span,
item_def_id,
item_segment,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index ee0ad7b5d..4db9c56f9 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1,9 +1,7 @@
use super::FnCtxt;
-use crate::astconv::AstConv;
-use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
-use hir::def_id::DefId;
-use rustc_ast::util::parser::ExprPrecedence;
+use crate::errors::{AddReturnTypeSuggestion, ExpectedReturnTypeLabel};
+use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind};
@@ -11,13 +9,16 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{
Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
};
+use rustc_hir_analysis::astconv::AstConv;
use rustc_infer::infer::{self, TyCtxtInferExt};
use rustc_infer::traits::{self, StatementAsExpression};
use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty};
+use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty};
+use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::DefIdOrName;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -64,7 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
/// When encountering an fn-like type, try accessing the output of the type
- /// // and suggesting calling it if it satisfies a predicate (i.e. if the
+ /// and suggesting calling it if it satisfies a predicate (i.e. if the
/// output has a method or a field):
/// ```compile_fail,E0308
/// fn foo(x: usize) -> usize { x }
@@ -89,7 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if ty.is_suggestable(self.tcx, false) {
format!("/* {ty} */")
} else {
- "".to_string()
+ "/* value */".to_string()
}
})
.collect::<Vec<_>>()
@@ -101,10 +102,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let msg = match def_id_or_name {
DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
- DefKind::Ctor(CtorOf::Struct, _) => "instantiate this tuple struct".to_string(),
- DefKind::Ctor(CtorOf::Variant, _) => {
- "instantiate this tuple variant".to_string()
- }
+ 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)),
},
DefIdOrName::Name(name) => format!("call this {name}"),
@@ -138,7 +137,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sugg,
applicability,
);
-
return true;
}
false
@@ -327,9 +325,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
found: Ty<'tcx>,
expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
- ) {
+ ) -> bool {
let expr = expr.peel_blocks();
- if let Some((sp, msg, suggestion, applicability, verbose)) =
+ if let Some((sp, msg, suggestion, applicability, verbose, annotation)) =
self.check_ref(expr, found, expected)
{
if verbose {
@@ -337,12 +335,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.span_suggestion(sp, &msg, suggestion, applicability);
}
+ if annotation {
+ let suggest_annotation = match expr.peel_drop_temps().kind {
+ hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, _) => "&",
+ hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, _) => "&mut ",
+ _ => return true,
+ };
+ let mut tuple_indexes = Vec::new();
+ let mut expr_id = expr.hir_id;
+ for (parent_id, node) in self.tcx.hir().parent_iter(expr.hir_id) {
+ match node {
+ Node::Expr(&Expr { kind: ExprKind::Tup(subs), .. }) => {
+ tuple_indexes.push(
+ subs.iter()
+ .enumerate()
+ .find(|(_, sub_expr)| sub_expr.hir_id == expr_id)
+ .unwrap()
+ .0,
+ );
+ expr_id = parent_id;
+ }
+ Node::Local(local) => {
+ if let Some(mut ty) = local.ty {
+ while let Some(index) = tuple_indexes.pop() {
+ match ty.kind {
+ TyKind::Tup(tys) => ty = &tys[index],
+ _ => return true,
+ }
+ }
+ let annotation_span = ty.span;
+ err.span_suggestion(
+ annotation_span.with_hi(annotation_span.lo()),
+ format!("alternatively, consider changing the type annotation"),
+ suggest_annotation,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ break;
+ }
+ _ => break,
+ }
+ }
+ }
+ return true;
+ } else if self.suggest_else_fn_with_closure(err, expr, found, expected) {
+ return true;
} else if self.suggest_fn_call(err, expr, found, |output| self.can_coerce(output, expected))
&& let ty::FnDef(def_id, ..) = &found.kind()
&& let Some(sp) = self.tcx.hir().span_if_local(*def_id)
{
err.span_label(sp, format!("{found} defined here"));
- } else if !self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
+ return true;
+ } else if self.check_for_cast(err, expr, found, expected, expected_ty_expr) {
+ return true;
+ } else {
let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id);
if !methods.is_empty() {
let mut suggestions = methods.iter()
@@ -393,6 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
suggestions,
Applicability::MaybeIncorrect,
);
+ return true;
}
} else if let ty::Adt(found_adt, found_substs) = found.kind()
&& self.tcx.is_diagnostic_item(sym::Option, found_adt.did())
@@ -417,9 +464,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!(".map(|x| &*{}x)", "*".repeat(ref_cnt)),
Applicability::MaybeIncorrect,
);
+ return true;
}
}
}
+
+ false
}
/// When encountering the expected boxed value allocated in the stack, suggest allocating it
@@ -430,13 +480,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
expected: Ty<'tcx>,
found: Ty<'tcx>,
- ) {
+ ) -> bool {
if self.tcx.hir().is_inside_const_context(expr.hir_id) {
// Do not suggest `Box::new` in const context.
- return;
+ return false;
}
if !expected.is_box() || found.is_box() {
- return;
+ return false;
}
let boxed_found = self.tcx.mk_box(found);
if self.can_coerce(boxed_found, expected) {
@@ -454,6 +504,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
https://doc.rust-lang.org/rust-by-example/std/box.html, and \
https://doc.rust-lang.org/std/boxed/index.html",
);
+ true
+ } else {
+ false
}
}
@@ -464,7 +517,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err: &mut Diagnostic,
expected: Ty<'tcx>,
found: Ty<'tcx>,
- ) {
+ ) -> bool {
if let (ty::FnPtr(_), ty::Closure(def_id, _)) = (expected.kind(), found.kind()) {
if let Some(upvars) = self.tcx.upvars_mentioned(*def_id) {
// Report upto four upvars being captured to reduce the amount error messages
@@ -488,8 +541,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
multi_span,
"closures can only be coerced to `fn` types if they do not capture any variables"
);
+ return true;
}
}
+ false
}
/// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
@@ -860,18 +915,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
let ty = self.normalize_associated_types_in(expr.span, ty);
let ty = match self.tcx.asyncness(fn_id.owner) {
- hir::IsAsync::Async => self
- .tcx
- .infer_ctxt()
- .enter(|infcx| {
- infcx.get_impl_future_output_ty(ty).unwrap_or_else(|| {
+ hir::IsAsync::Async => {
+ let infcx = self.tcx.infer_ctxt().build();
+ infcx
+ .get_impl_future_output_ty(ty)
+ .unwrap_or_else(|| {
span_bug!(
fn_decl.output.span(),
"failed to get output type of async function"
)
})
- })
- .skip_binder(),
+ .skip_binder()
+ }
hir::IsAsync::NotAsync => ty,
};
if self.can_coerce(found, ty) {
@@ -891,11 +946,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
err: &mut Diagnostic,
expr: &hir::Expr<'_>,
- ) {
+ ) -> bool {
let sp = self.tcx.sess.source_map().start_point(expr.span);
if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
// `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
- self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
+ true
+ } else {
+ false
}
}
@@ -908,7 +966,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mut expr: &hir::Expr<'_>,
mut expr_ty: Ty<'tcx>,
mut expected_ty: Ty<'tcx>,
- ) {
+ ) -> bool {
loop {
match (&expr.kind, expr_ty.kind(), expected_ty.kind()) {
(
@@ -922,9 +980,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
(hir::ExprKind::Block(blk, _), _, _) => {
self.suggest_block_to_brackets(diag, *blk, expr_ty, expected_ty);
- break;
+ break true;
}
- _ => break,
+ _ => break false,
}
}
}
@@ -935,11 +993,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &hir::Expr<'_>,
expr_ty: Ty<'tcx>,
expected_ty: Ty<'tcx>,
- ) {
- let ty::Adt(adt_def, substs) = expr_ty.kind() else { return; };
- let ty::Adt(expected_adt_def, expected_substs) = expected_ty.kind() else { return; };
+ ) -> bool {
+ let ty::Adt(adt_def, substs) = expr_ty.kind() else { return false; };
+ let ty::Adt(expected_adt_def, expected_substs) = expected_ty.kind() else { return false; };
if adt_def != expected_adt_def {
- return;
+ return false;
}
let mut suggest_copied_or_cloned = || {
@@ -958,6 +1016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".copied()",
Applicability::MachineApplicable,
);
+ return true;
} else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
&& rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
self,
@@ -975,8 +1034,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
".cloned()",
Applicability::MachineApplicable,
);
+ return true;
}
}
+ false
};
if let Some(result_did) = self.tcx.get_diagnostic_item(sym::Result)
@@ -984,12 +1045,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Check that the error types are equal
&& self.can_eq(self.param_env, substs.type_at(1), expected_substs.type_at(1)).is_ok()
{
- suggest_copied_or_cloned();
+ return suggest_copied_or_cloned();
} else if let Some(option_did) = self.tcx.get_diagnostic_item(sym::Option)
&& adt_def.did() == option_did
{
- suggest_copied_or_cloned();
+ return suggest_copied_or_cloned();
}
+
+ false
+ }
+
+ pub(crate) fn suggest_into(
+ &self,
+ diag: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ expr_ty: Ty<'tcx>,
+ expected_ty: Ty<'tcx>,
+ ) -> bool {
+ let expr = expr.peel_blocks();
+
+ // We have better suggestions for scalar interconversions...
+ if expr_ty.is_scalar() && expected_ty.is_scalar() {
+ return false;
+ }
+
+ // Don't suggest turning a block into another type (e.g. `{}.into()`)
+ if matches!(expr.kind, hir::ExprKind::Block(..)) {
+ return false;
+ }
+
+ // We'll later suggest `.as_ref` when noting the type error,
+ // so skip if we will suggest that instead.
+ if self.err_ctxt().should_suggest_as_ref(expected_ty, expr_ty).is_some() {
+ return false;
+ }
+
+ if let Some(into_def_id) = self.tcx.get_diagnostic_item(sym::Into)
+ && self.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+ self.misc(expr.span),
+ self.param_env,
+ ty::Binder::dummy(ty::TraitRef {
+ def_id: into_def_id,
+ substs: self.tcx.mk_substs_trait(expr_ty, &[expected_ty.into()]),
+ })
+ .to_poly_trait_predicate()
+ .to_predicate(self.tcx),
+ ))
+ {
+ let sugg = if expr.precedence().order() >= PREC_POSTFIX {
+ vec![(expr.span.shrink_to_hi(), ".into()".to_owned())]
+ } else {
+ vec![(expr.span.shrink_to_lo(), "(".to_owned()), (expr.span.shrink_to_hi(), ").into()".to_owned())]
+ };
+ diag.multipart_suggestion(
+ format!("call `Into::into` on this expression to convert `{expr_ty}` into `{expected_ty}`"),
+ sugg,
+ Applicability::MaybeIncorrect
+ );
+ return true;
+ }
+
+ false
}
/// Suggest wrapping the block in square brackets instead of curly braces
@@ -1110,7 +1226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>,
err: &mut Diagnostic,
) -> bool {
- if let Some((span_semi, boxed)) = self.could_remove_semicolon(blk, expected_ty) {
+ if let Some((span_semi, boxed)) = self.err_ctxt().could_remove_semicolon(blk, expected_ty) {
if let StatementAsExpression::NeedsBoxing = boxed {
err.span_suggestion_verbose(
span_semi,
@@ -1121,7 +1237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
err.span_suggestion_short(
span_semi,
- "remove this semicolon",
+ "remove this semicolon to return this value",
"",
Applicability::MachineApplicable,
);
@@ -1132,8 +1248,3 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
-
-pub enum DefIdOrName {
- DefId(DefId),
- Name(&'static str),
-}
diff --git a/compiler/rustc_typeck/src/check/gather_locals.rs b/compiler/rustc_hir_typeck/src/gather_locals.rs
index 8f34a970f..9a096f24f 100644
--- a/compiler/rustc_typeck/src/check/gather_locals.rs
+++ b/compiler/rustc_hir_typeck/src/gather_locals.rs
@@ -1,9 +1,10 @@
-use crate::check::{FnCtxt, LocalTy, UserType};
+use crate::{FnCtxt, LocalTy};
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
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::Span;
use rustc_trait_selection::traits;
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
index 016f4056b..122ad7009 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_build.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_build.rs
@@ -210,7 +210,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
}
/// For an expression with an uninhabited return type (e.g. a function that returns !),
- /// this adds a self edge to to the CFG to model the fact that the function does not
+ /// this adds a self edge to the CFG to model the fact that the function does not
/// return.
fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) {
let ty = self.typeck_results.expr_ty(expr);
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs
index 139d17d2e..139d17d2e 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_propagate.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_propagate.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
index c0a0bfe8e..c0a0bfe8e 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/cfg_visualize.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/cfg_visualize.rs
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
index 518cd7342..4f3bdfbe7 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/mod.rs
@@ -14,7 +14,7 @@
use self::cfg_build::build_control_flow_graph;
use self::record_consumed_borrow::find_consumed_and_borrowed;
-use crate::check::FnCtxt;
+use crate::FnCtxt;
use hir::def_id::DefId;
use hir::{Body, HirId, HirIdMap, Node};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
diff --git a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
index e22675e9d..bfe95852a 100644
--- a/compiler/rustc_typeck/src/check/generator_interior/drop_ranges/record_consumed_borrow.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs
@@ -1,13 +1,16 @@
use super::TrackedValue;
use crate::{
- check::FnCtxt,
expr_use_visitor::{self, ExprUseVisitor},
+ FnCtxt,
};
use hir::{def_id::DefId, Body, HirId, HirIdMap};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir as hir;
-use rustc_middle::hir::place::{PlaceBase, Projection, ProjectionKind};
use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_middle::{
+ hir::place::{PlaceBase, Projection, ProjectionKind},
+ ty::TypeVisitable,
+};
pub(super) fn find_consumed_and_borrowed<'a, 'tcx>(
fcx: &'a FnCtxt<'a, 'tcx>,
@@ -198,7 +201,13 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> {
// If the type being assigned needs dropped, then the mutation counts as a borrow
// since it is essentially doing `Drop::drop(&mut x); x = new_value;`.
- if assignee_place.place.base_ty.needs_drop(self.tcx, self.param_env) {
+ let ty = self.tcx.erase_regions(assignee_place.place.base_ty);
+ if ty.needs_infer() {
+ self.tcx.sess.delay_span_bug(
+ self.tcx.hir().span(assignee_place.hir_id),
+ &format!("inference variables in {ty}"),
+ );
+ } else if ty.needs_drop(self.tcx, self.param_env) {
self.places
.borrowed
.insert(TrackedValue::from_place_with_projections_allowed(assignee_place));
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 7ab6d9e2b..b7dd599cd 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -6,7 +6,7 @@
use self::drop_ranges::DropRanges;
use super::FnCtxt;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_errors::pluralize;
+use rustc_errors::{pluralize, DelayDm};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::DefId;
@@ -218,7 +218,8 @@ pub fn resolve_interior<'a, 'tcx>(
.filter_map(|mut cause| {
// Erase regions and canonicalize late-bound regions to deduplicate as many types as we
// can.
- let erased = fcx.tcx.erase_regions(cause.ty);
+ let ty = fcx.normalize_associated_types_in(cause.span, cause.ty);
+ let erased = fcx.tcx.erase_regions(ty);
if captured_tys.insert(erased) {
// 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,
@@ -263,7 +264,7 @@ pub fn resolve_interior<'a, 'tcx>(
// Unify the type variable inside the generator with the new witness
match fcx.at(&fcx.misc(body.value.span), fcx.param_env).eq(interior, witness) {
Ok(ok) => fcx.register_infer_ok_obligations(ok),
- _ => bug!(),
+ _ => bug!("failed to relate {interior} and {witness}"),
}
}
@@ -376,15 +377,6 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
debug!("is_borrowed_temporary: {:?}", self.drop_ranges.is_borrowed_temporary(expr));
let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted_opt(expr);
- let may_need_drop = |ty: Ty<'tcx>| {
- // Avoid ICEs in needs_drop.
- let ty = self.fcx.resolve_vars_if_possible(ty);
- let ty = self.fcx.tcx.erase_regions(ty);
- if ty.needs_infer() {
- return true;
- }
- ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
- };
// Typically, the value produced by an expression is consumed by its parent in some way,
// so we only have to check if the parent contains a yield (note that the parent may, for
@@ -402,9 +394,18 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
// src/test/ui/generator/drop-tracking-parent-expression.rs.
let scope = if self.drop_ranges.is_borrowed_temporary(expr)
|| ty.map_or(true, |ty| {
- let needs_drop = may_need_drop(ty);
- debug!(?needs_drop, ?ty);
- needs_drop
+ // Avoid ICEs in needs_drop.
+ let ty = self.fcx.resolve_vars_if_possible(ty);
+ let ty = self.fcx.tcx.erase_regions(ty);
+ if ty.needs_infer() {
+ self.fcx
+ .tcx
+ .sess
+ .delay_span_bug(expr.span, &format!("inference variables in {ty}"));
+ true
+ } else {
+ ty.needs_drop(self.fcx.tcx, self.fcx.param_env)
+ }
}) {
self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id)
} else {
@@ -609,33 +610,33 @@ fn check_must_not_suspend_def(
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
hir_id,
data.source_span,
- |lint| {
- let msg = format!(
+ DelayDm(|| {
+ format!(
"{}`{}`{} held across a suspend point, but should not be",
data.descr_pre,
tcx.def_path_str(def_id),
data.descr_post,
- );
- let mut err = lint.build(&msg);
-
+ )
+ }),
+ |lint| {
// add span pointing to the offending yield/await
- err.span_label(data.yield_span, "the value is held across this suspend point");
+ 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
- err.span_note(data.source_span, note.as_str());
+ 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?
- err.span_help(
+ lint.span_help(
data.source_span,
"consider using a block (`{ ... }`) \
to shrink the value's scope, ending before the suspend point",
);
- err.emit();
+ lint
},
);
diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 37c830d4e..0fb7651b3 100644
--- a/compiler/rustc_typeck/src/check/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -6,7 +6,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::HirIdMap;
use rustc_infer::infer;
-use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt};
+use rustc_infer::infer::{DefiningAnchor, InferCtxt, InferOk, TyCtxtInferExt};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, Ty, TyCtxt};
@@ -29,10 +29,10 @@ use std::ops::Deref;
/// Here, the function `foo()` and the closure passed to
/// `bar()` will each have their own `FnCtxt`, but they will
/// share the inherited fields.
-pub struct Inherited<'a, 'tcx> {
- pub(super) infcx: InferCtxt<'a, 'tcx>,
+pub struct Inherited<'tcx> {
+ pub(super) infcx: InferCtxt<'tcx>,
- pub(super) typeck_results: &'a RefCell<ty::TypeckResults<'tcx>>,
+ pub(super) typeck_results: RefCell<ty::TypeckResults<'tcx>>,
pub(super) locals: RefCell<HirIdMap<super::LocalTy<'tcx>>>,
@@ -55,7 +55,7 @@ pub struct Inherited<'a, 'tcx> {
pub(super) deferred_cast_checks: RefCell<Vec<super::cast::CastCheck<'tcx>>>,
- pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, Span)>>,
+ pub(super) deferred_transmute_checks: RefCell<Vec<(Ty<'tcx>, Ty<'tcx>, hir::HirId)>>,
pub(super) deferred_asm_checks: RefCell<Vec<(&'tcx hir::InlineAsm<'tcx>, hir::HirId)>>,
@@ -70,22 +70,23 @@ pub struct Inherited<'a, 'tcx> {
pub(super) diverging_type_vars: RefCell<FxHashSet<Ty<'tcx>>>,
}
-impl<'a, 'tcx> Deref for Inherited<'a, 'tcx> {
- type Target = InferCtxt<'a, 'tcx>;
+impl<'tcx> Deref for Inherited<'tcx> {
+ type Target = InferCtxt<'tcx>;
fn deref(&self) -> &Self::Target {
&self.infcx
}
}
/// A temporary returned by `Inherited::build(...)`. This is necessary
-/// for multiple `InferCtxt` to share the same `in_progress_typeck_results`
+/// for multiple `InferCtxt` to share the same `typeck_results`
/// without using `Rc` or something similar.
pub struct InheritedBuilder<'tcx> {
infcx: infer::InferCtxtBuilder<'tcx>,
def_id: LocalDefId,
+ typeck_results: RefCell<ty::TypeckResults<'tcx>>,
}
-impl<'tcx> Inherited<'_, 'tcx> {
+impl<'tcx> Inherited<'tcx> {
pub fn build(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> InheritedBuilder<'tcx> {
let hir_owner = tcx.hir().local_def_id_to_hir_id(def_id).owner;
@@ -93,7 +94,7 @@ impl<'tcx> Inherited<'_, 'tcx> {
infcx: tcx
.infer_ctxt()
.ignoring_regions()
- .with_fresh_in_progress_typeck_results(hir_owner)
+ .with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id))
.with_normalize_fn_sig_for_diagnostic(Lrc::new(move |infcx, fn_sig| {
if fn_sig.has_escaping_bound_vars() {
return fn_sig;
@@ -117,26 +118,29 @@ impl<'tcx> Inherited<'_, 'tcx> {
})
})),
def_id,
+ typeck_results: RefCell::new(ty::TypeckResults::new(hir_owner)),
}
}
}
impl<'tcx> InheritedBuilder<'tcx> {
- pub fn enter<F, R>(&mut self, f: F) -> R
+ pub fn enter<F, R>(mut self, f: F) -> R
where
- F: for<'a> FnOnce(Inherited<'a, 'tcx>) -> R,
+ F: FnOnce(&Inherited<'tcx>) -> R,
{
let def_id = self.def_id;
- self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
+ f(&Inherited::new(self.infcx.build(), def_id, self.typeck_results))
}
}
-impl<'a, 'tcx> Inherited<'a, 'tcx> {
- fn new(infcx: InferCtxt<'a, 'tcx>, def_id: LocalDefId) -> Self {
+impl<'tcx> Inherited<'tcx> {
+ fn new(
+ infcx: InferCtxt<'tcx>,
+ def_id: LocalDefId,
+ typeck_results: RefCell<ty::TypeckResults<'tcx>>,
+ ) -> Self {
let tcx = infcx.tcx;
let body_id = tcx.hir().maybe_body_owned_by(def_id);
- let typeck_results =
- infcx.in_progress_typeck_results.expect("building `FnCtxt` without typeck results");
Inherited {
typeck_results,
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
new file mode 100644
index 000000000..9812d96fc
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -0,0 +1,108 @@
+use hir::HirId;
+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};
+use rustc_target::abi::{Pointer, VariantIdx};
+
+use super::FnCtxt;
+
+/// If the type is `Option<T>`, it will return `T`, otherwise
+/// the type itself. Works on most `Option`-like types.
+fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
+ let ty::Adt(def, substs) = *ty.kind() else { return ty };
+
+ if def.variants().len() == 2 && !def.repr().c() && def.repr().int.is_none() {
+ let data_idx;
+
+ let one = VariantIdx::new(1);
+ let zero = VariantIdx::new(0);
+
+ if def.variant(zero).fields.is_empty() {
+ data_idx = one;
+ } else if def.variant(one).fields.is_empty() {
+ data_idx = zero;
+ } else {
+ return ty;
+ }
+
+ if def.variant(data_idx).fields.len() == 1 {
+ return def.variant(data_idx).fields[0].ty(tcx, substs);
+ }
+ }
+
+ ty
+}
+
+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 span = tcx.hir().span(hir_id);
+ let normalize = |ty| {
+ let ty = self.resolve_vars_if_possible(ty);
+ self.tcx.normalize_erasing_regions(self.param_env, ty)
+ };
+ let from = normalize(from);
+ let to = normalize(to);
+ trace!(?from, ?to);
+
+ // Transmutes that are only changing lifetimes are always ok.
+ if from == to {
+ return;
+ }
+
+ let skel = |ty| SizeSkeleton::compute(ty, tcx, self.param_env);
+ let sk_from = skel(from);
+ let sk_to = skel(to);
+ trace!(?sk_from, ?sk_to);
+
+ // Check for same size using the skeletons.
+ if let (Ok(sk_from), Ok(sk_to)) = (sk_from, sk_to) {
+ if sk_from.same_size(sk_to) {
+ return;
+ }
+
+ // 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) {
+ struct_span_err!(tcx.sess, span, E0591, "can't transmute zero-sized type")
+ .note(&format!("source type: {from}"))
+ .note(&format!("target type: {to}"))
+ .help("cast with `as` to a pointer instead")
+ .emit();
+ return;
+ }
+ }
+
+ // Try to display a sensible error with as much information as possible.
+ let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
+ Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()),
+ Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
+ Err(LayoutError::Unknown(bad)) => {
+ if bad == ty {
+ "this type does not have a fixed size".to_owned()
+ } else {
+ format!("size can vary because of {bad}")
+ }
+ }
+ Err(err) => err.to_string(),
+ };
+
+ let mut err = struct_span_err!(
+ tcx.sess,
+ span,
+ E0512,
+ "cannot transmute between types of different sizes, \
+ or dependently-sized types"
+ );
+ if from == to {
+ err.note(&format!("`{from}` does not have a fixed size"));
+ } else {
+ err.note(&format!("source type: `{}` ({})", from, skeleton_string(from, sk_from)))
+ .note(&format!("target type: `{}` ({})", to, skeleton_string(to, sk_to)));
+ }
+ err.emit();
+ }
+}
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
new file mode 100644
index 000000000..959c54866
--- /dev/null
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -0,0 +1,507 @@
+#![feature(if_let_guard)]
+#![feature(let_chains)]
+#![feature(try_blocks)]
+#![feature(never_type)]
+#![feature(min_specialization)]
+#![feature(control_flow_enum)]
+#![feature(drain_filter)]
+#![allow(rustc::potential_query_instability)]
+#![recursion_limit = "256"]
+
+#[macro_use]
+extern crate tracing;
+
+#[macro_use]
+extern crate rustc_middle;
+
+mod _match;
+mod autoderef;
+mod callee;
+// Used by clippy;
+pub mod cast;
+mod check;
+mod closure;
+mod coercion;
+mod demand;
+mod diverges;
+mod errors;
+mod expectation;
+mod expr;
+// Used by clippy;
+pub mod expr_use_visitor;
+mod fallback;
+mod fn_ctxt;
+mod gather_locals;
+mod generator_interior;
+mod inherited;
+mod intrinsicck;
+mod mem_categorization;
+mod method;
+mod op;
+mod pat;
+mod place_op;
+mod rvalue_scopes;
+mod upvar;
+mod writeback;
+
+pub use diverges::Diverges;
+pub use expectation::Expectation;
+pub use fn_ctxt::*;
+pub use inherited::{Inherited, InheritedBuilder};
+
+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, MultiSpan};
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::Visitor;
+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_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;
+
+#[macro_export]
+macro_rules! type_error_struct {
+ ($session:expr, $span:expr, $typ:expr, $code:ident, $($message:tt)*) => ({
+ let mut err = rustc_errors::struct_span_err!($session, $span, $code, $($message)*);
+
+ if $typ.references_error() {
+ err.downgrade_to_delayed_bug();
+ }
+
+ err
+ })
+}
+
+/// The type of a local binding, including the revealed type for anon types.
+#[derive(Copy, Clone, Debug)]
+pub struct LocalTy<'tcx> {
+ decl_ty: Ty<'tcx>,
+ revealed_ty: Ty<'tcx>,
+}
+
+#[derive(Copy, Clone)]
+pub struct UnsafetyState {
+ pub def: hir::HirId,
+ pub unsafety: hir::Unsafety,
+ from_fn: bool,
+}
+
+impl UnsafetyState {
+ pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
+ UnsafetyState { def, unsafety, from_fn: true }
+ }
+
+ pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
+ use hir::BlockCheckMode;
+ match self.unsafety {
+ // If this unsafe, then if the outer function was already marked as
+ // unsafe we shouldn't attribute the unsafe'ness to the block. This
+ // way the block can be warned about instead of ignoring this
+ // extraneous block (functions are never warned about).
+ hir::Unsafety::Unsafe if self.from_fn => self,
+
+ unsafety => {
+ let (unsafety, def) = match blk.rules {
+ BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
+ BlockCheckMode::DefaultBlock => (unsafety, self.def),
+ };
+ UnsafetyState { def, unsafety, from_fn: false }
+ }
+ }
+ }
+}
+
+/// If this `DefId` is a "primary tables entry", returns
+/// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
+///
+/// If this function returns `Some`, then `typeck_results(def_id)` will
+/// succeed; if it returns `None`, then `typeck_results(def_id)` may or
+/// may not succeed. In some cases where this function returns `None`
+/// (notably closures), `typeck_results(def_id)` would wind up
+/// redirecting to the owning function.
+fn primary_body_of(
+ tcx: TyCtxt<'_>,
+ id: hir::HirId,
+) -> Option<(hir::BodyId, Option<&hir::Ty<'_>>, Option<&hir::FnSig<'_>>)> {
+ match tcx.hir().get(id) {
+ Node::Item(item) => match item.kind {
+ hir::ItemKind::Const(ty, body) | hir::ItemKind::Static(ty, _, body) => {
+ Some((body, Some(ty), None))
+ }
+ hir::ItemKind::Fn(ref sig, .., body) => Some((body, None, Some(sig))),
+ _ => None,
+ },
+ Node::TraitItem(item) => match item.kind {
+ hir::TraitItemKind::Const(ty, Some(body)) => Some((body, Some(ty), None)),
+ hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
+ Some((body, None, Some(sig)))
+ }
+ _ => None,
+ },
+ Node::ImplItem(item) => match item.kind {
+ hir::ImplItemKind::Const(ty, body) => Some((body, Some(ty), None)),
+ hir::ImplItemKind::Fn(ref sig, body) => Some((body, None, Some(sig))),
+ _ => None,
+ },
+ Node::AnonConst(constant) => Some((constant.body, None, None)),
+ _ => None,
+ }
+}
+
+fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ // Closures' typeck results come from their outermost function,
+ // as they are part of the same "inference environment".
+ let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
+ if typeck_root_def_id != def_id {
+ return tcx.has_typeck_results(typeck_root_def_id);
+ }
+
+ if let Some(def_id) = def_id.as_local() {
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
+ primary_body_of(tcx, id).is_some()
+ } else {
+ false
+ }
+}
+
+fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
+ &*tcx.typeck(def_id).used_trait_imports
+}
+
+fn typeck_item_bodies(tcx: TyCtxt<'_>, (): ()) {
+ tcx.hir().par_body_owners(|body_owner_def_id| tcx.ensure().typeck(body_owner_def_id));
+}
+
+fn typeck_const_arg<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (did, param_did): (LocalDefId, DefId),
+) -> &ty::TypeckResults<'tcx> {
+ let fallback = move || tcx.type_of(param_did);
+ typeck_with_fallback(tcx, did, fallback)
+}
+
+fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
+ 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());
+ typeck_with_fallback(tcx, def_id, fallback)
+ }
+}
+
+/// Used only to get `TypeckResults` for type inference during error recovery.
+/// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
+fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
+ let fallback = move || {
+ let span = tcx.hir().span(tcx.hir().local_def_id_to_hir_id(def_id));
+ tcx.ty_error_with_message(span, "diagnostic only typeck table used")
+ };
+ typeck_with_fallback(tcx, def_id, fallback)
+}
+
+fn typeck_with_fallback<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ def_id: LocalDefId,
+ fallback: impl Fn() -> Ty<'tcx> + 'tcx,
+) -> &'tcx ty::TypeckResults<'tcx> {
+ // Closures' typeck results come from their outermost function,
+ // as they are part of the same "inference environment".
+ let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()).expect_local();
+ if typeck_root_def_id != def_id {
+ return tcx.typeck(typeck_root_def_id);
+ }
+
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
+ let span = tcx.hir().span(id);
+
+ // Figure out what primary body this item has.
+ let (body_id, body_ty, fn_sig) = primary_body_of(tcx, id).unwrap_or_else(|| {
+ span_bug!(span, "can't type-check body of {:?}", def_id);
+ });
+ let body = tcx.hir().body(body_id);
+
+ let typeck_results = Inherited::build(tcx, def_id).enter(|inh| {
+ let param_env = tcx.param_env(def_id);
+ let mut fcx = 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() {
+ let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
+ <dyn AstConv<'_>>::ty_of_fn(&fcx, id, header.unsafety, header.abi, decl, None, None)
+ } else {
+ tcx.fn_sig(def_id)
+ };
+
+ check_abi(tcx, id, span, fn_sig.abi());
+
+ // Compute the function signature from point of view of inside the fn.
+ let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
+ let fn_sig = inh.normalize_associated_types_in(
+ body.value.span,
+ body_id.hir_id,
+ param_env,
+ fn_sig,
+ );
+ check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0
+ } else {
+ let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id);
+ let expected_type = body_ty
+ .and_then(|ty| match ty.kind {
+ hir::TyKind::Infer => Some(<dyn AstConv<'_>>::ast_ty_to_ty(&fcx, ty)),
+ _ => None,
+ })
+ .unwrap_or_else(|| match tcx.hir().get(id) {
+ Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) {
+ Node::Expr(&hir::Expr {
+ kind: hir::ExprKind::ConstBlock(ref anon_const),
+ ..
+ }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ }),
+ Node::Ty(&hir::Ty {
+ kind: hir::TyKind::Typeof(ref anon_const), ..
+ }) if anon_const.hir_id == id => fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::TypeInference,
+ span,
+ }),
+ Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
+ | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
+ let operand_ty = asm
+ .operands
+ .iter()
+ .filter_map(|(op, _op_sp)| match op {
+ hir::InlineAsmOperand::Const { anon_const }
+ if anon_const.hir_id == id =>
+ {
+ // Inline assembly constants must be integers.
+ Some(fcx.next_int_var())
+ }
+ hir::InlineAsmOperand::SymFn { anon_const }
+ if anon_const.hir_id == id =>
+ {
+ Some(fcx.next_ty_var(TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span,
+ }))
+ }
+ _ => None,
+ })
+ .next();
+ operand_ty.unwrap_or_else(fallback)
+ }
+ _ => fallback(),
+ },
+ _ => fallback(),
+ });
+
+ let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
+ fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
+
+ // Gather locals in statics (because of block expressions).
+ GatherLocalsVisitor::new(&fcx).visit_body(body);
+
+ fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
+
+ fcx.write_ty(id, expected_type);
+
+ fcx
+ };
+
+ let fallback_has_occurred = fcx.type_inference_fallback();
+
+ // Even though coercion casts provide type hints, we check casts after fallback for
+ // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
+ fcx.check_casts();
+ fcx.select_obligations_where_possible(fallback_has_occurred, |_| {});
+
+ // Closure and generator analysis may run after fallback
+ // because they don't constrain other type variables.
+ // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
+ let prev_constness = fcx.param_env.constness();
+ fcx.param_env = fcx.param_env.without_const();
+ fcx.closure_analyze(body);
+ fcx.param_env = fcx.param_env.with_constness(prev_constness);
+ assert!(fcx.deferred_call_resolutions.borrow().is_empty());
+ // 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_ty(span, ty);
+ fcx.require_type_is_sized(ty, span, code);
+ }
+
+ fcx.select_all_obligations_or_error();
+
+ if !fcx.infcx.is_tainted_by_errors() {
+ fcx.check_transmutes();
+ }
+
+ fcx.check_asms();
+
+ fcx.infcx.skip_region_resolution();
+
+ fcx.resolve_type_vars_in_body(body)
+ });
+
+ // Consistency check our TypeckResults instance can hold all ItemLocalIds
+ // it will need to hold.
+ assert_eq!(typeck_results.hir_owner, id.owner);
+
+ typeck_results
+}
+
+/// When `check_fn` is invoked on a generator (i.e., a body that
+/// includes yield), it returns back some information about the yield
+/// points.
+struct GeneratorTypes<'tcx> {
+ /// Type of generator argument / values returned by `yield`.
+ resume_ty: Ty<'tcx>,
+
+ /// Type of value that is yielded.
+ yield_ty: Ty<'tcx>,
+
+ /// Types that are captured (see `GeneratorInterior` for more).
+ interior: Ty<'tcx>,
+
+ /// Indicates if the generator is movable or static (immovable).
+ movability: hir::Movability,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Needs {
+ MutPlace,
+ None,
+}
+
+impl Needs {
+ fn maybe_mut_place(m: hir::Mutability) -> Self {
+ match m {
+ hir::Mutability::Mut => Needs::MutPlace,
+ hir::Mutability::Not => Needs::None,
+ }
+ }
+}
+
+#[derive(Debug, Copy, Clone)]
+pub enum PlaceOp {
+ Deref,
+ Index,
+}
+
+pub struct BreakableCtxt<'tcx> {
+ may_break: bool,
+
+ // this is `null` for loops where break with a value is illegal,
+ // such as `while`, `for`, and `while let`
+ coerce: Option<DynamicCoerceMany<'tcx>>,
+}
+
+pub struct EnclosingBreakables<'tcx> {
+ stack: Vec<BreakableCtxt<'tcx>>,
+ by_id: HirIdMap<usize>,
+}
+
+impl<'tcx> EnclosingBreakables<'tcx> {
+ fn find_breakable(&mut self, target_id: hir::HirId) -> &mut BreakableCtxt<'tcx> {
+ self.opt_find_breakable(target_id).unwrap_or_else(|| {
+ bug!("could not find enclosing breakable with id {}", target_id);
+ })
+ }
+
+ fn opt_find_breakable(&mut self, target_id: hir::HirId) -> Option<&mut BreakableCtxt<'tcx>> {
+ match self.by_id.get(&target_id) {
+ Some(ix) => Some(&mut self.stack[*ix]),
+ None => None,
+ }
+ }
+}
+
+fn report_unexpected_variant_res(tcx: TyCtxt<'_>, res: Res, qpath: &hir::QPath<'_>, span: Span) {
+ struct_span_err!(
+ tcx.sess,
+ span,
+ E0533,
+ "expected unit struct, unit variant or constant, found {} `{}`",
+ res.descr(),
+ rustc_hir_pretty::qpath_to_string(qpath),
+ )
+ .emit();
+}
+
+/// Controls whether the arguments are tupled. This is used for the call
+/// operator.
+///
+/// Tupling means that all call-side arguments are packed into a tuple and
+/// passed as a single parameter. For example, if tupling is enabled, this
+/// function:
+/// ```
+/// fn f(x: (isize, isize)) {}
+/// ```
+/// Can be called as:
+/// ```ignore UNSOLVED (can this be done in user code?)
+/// # fn f(x: (isize, isize)) {}
+/// f(1, 2);
+/// ```
+/// Instead of:
+/// ```
+/// # fn f(x: (isize, isize)) {}
+/// f((1, 2));
+/// ```
+#[derive(Clone, Eq, PartialEq)]
+enum TupleArgumentsFlag {
+ DontTupleArguments,
+ TupleArguments,
+}
+
+fn fatally_break_rust(sess: &Session) {
+ let handler = sess.diagnostic();
+ handler.span_bug_no_panic(
+ MultiSpan::new(),
+ "It looks like you're trying to break rust; would you like some ICE?",
+ );
+ handler.note_without_error("the compiler expectedly panicked. this is a feature.");
+ handler.note_without_error(
+ "we would appreciate a joke overview: \
+ https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675",
+ );
+ handler.note_without_error(&format!(
+ "rustc {} running on {}",
+ option_env!("CFG_VERSION").unwrap_or("unknown_version"),
+ config::host_triple(),
+ ));
+}
+
+fn has_expected_num_generic_args<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ trait_did: Option<DefId>,
+ expected: usize,
+) -> bool {
+ trait_did.map_or(true, |trait_did| {
+ let generics = tcx.generics_of(trait_did);
+ generics.count() == expected + if generics.has_self { 1 } else { 0 }
+ })
+}
+
+pub fn provide(providers: &mut Providers) {
+ method::provide(providers);
+ *providers = Providers {
+ typeck_item_bodies,
+ typeck_const_arg,
+ typeck,
+ diagnostic_only_typeck,
+ has_typeck_results,
+ used_trait_imports,
+ ..*providers
+ };
+}
diff --git a/compiler/rustc_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs
index ced919f66..362f1c343 100644
--- a/compiler/rustc_typeck/src/mem_categorization.rs
+++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs
@@ -92,7 +92,7 @@ impl HirNode for hir::Pat<'_> {
#[derive(Clone)]
pub(crate) struct MemCategorizationContext<'a, 'tcx> {
pub(crate) typeck_results: &'a ty::TypeckResults<'tcx>,
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_owner: LocalDefId,
upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
@@ -103,7 +103,7 @@ pub(crate) type McResult<T> = Result<T, ()>;
impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
/// Creates a `MemCategorizationContext`.
pub(crate) fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_owner: LocalDefId,
typeck_results: &'a ty::TypeckResults<'tcx>,
@@ -184,7 +184,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
/// modes #42640) may look like `Some(x)` but in fact have
/// implicit deref patterns attached (e.g., it is really
/// `&Some(x)`). In that case, we return the "outermost" type
- /// (e.g., `&Option<T>).
+ /// (e.g., `&Option<T>`).
pub(crate) fn pat_ty_adjusted(&self, pat: &hir::Pat<'_>) -> McResult<Ty<'tcx>> {
// Check for implicit `&` types wrapping the pattern; note
// that these are never attached to binding patterns, so
@@ -265,6 +265,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment)
}
+ #[instrument(level = "debug", skip(self, previous))]
fn cat_expr_adjusted_with<F>(
&self,
expr: &hir::Expr<'_>,
@@ -274,7 +275,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
where
F: FnOnce() -> McResult<PlaceWithHirId<'tcx>>,
{
- debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr);
let target = self.resolve_vars_if_possible(adjustment.target);
match adjustment.kind {
adjustment::Adjust::Deref(overloaded) => {
@@ -292,13 +292,15 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
adjustment::Adjust::NeverToAny
| adjustment::Adjust::Pointer(_)
- | adjustment::Adjust::Borrow(_) => {
+ | adjustment::Adjust::Borrow(_)
+ | adjustment::Adjust::DynStar => {
// Result is an rvalue.
Ok(self.cat_rvalue(expr.hir_id, expr.span, target))
}
}
}
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn cat_expr_unadjusted(
&self,
expr: &hir::Expr<'_>,
@@ -387,6 +389,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
}
}
+ #[instrument(level = "debug", skip(self, span))]
pub(crate) fn cat_res(
&self,
hir_id: hir::HirId,
@@ -394,8 +397,6 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
expr_ty: Ty<'tcx>,
res: Res,
) -> McResult<PlaceWithHirId<'tcx>> {
- debug!("cat_res: id={:?} expr={:?} def={:?}", hir_id, expr_ty, res);
-
match res {
Res::Def(
DefKind::Ctor(..)
@@ -475,13 +476,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
ret
}
+ #[instrument(level = "debug", skip(self))]
fn cat_overloaded_place(
&self,
expr: &hir::Expr<'_>,
base: &hir::Expr<'_>,
) -> McResult<PlaceWithHirId<'tcx>> {
- debug!("cat_overloaded_place(expr={:?}, base={:?})", expr, base);
-
// Reconstruct the output assuming it's a reference with the
// same region and mutability as the receiver. This holds for
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
@@ -497,13 +497,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
self.cat_deref(expr, base)
}
+ #[instrument(level = "debug", skip(self, node))]
fn cat_deref(
&self,
node: &impl HirNode,
base_place: PlaceWithHirId<'tcx>,
) -> McResult<PlaceWithHirId<'tcx>> {
- debug!("cat_deref: base_place={:?}", base_place);
-
let base_curr_ty = base_place.place.ty();
let deref_ty = match base_curr_ty.builtin_deref(true) {
Some(mt) => mt.ty,
@@ -562,7 +561,8 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> {
Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _)
| Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _)
| Res::SelfCtor(..)
- | Res::SelfTy { .. } => {
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. } => {
// Structs and Unions have only have one variant.
Ok(VariantIdx::new(0))
}
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 59fd5c315..be4ea9986 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -1,16 +1,16 @@
use super::{probe, MethodCallee};
-use crate::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
-use crate::check::{callee, FnCtxt};
+use crate::{callee, FnCtxt};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
+use rustc_hir_analysis::astconv::{AstConv, CreateSubstsForGenericArgsCtxt, IsMethodCall};
use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
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, Subst, SubstsRef};
+use rustc_middle::ty::subst::{self, SubstsRef};
use rustc_middle::ty::{self, GenericParamDefKind, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits;
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index 249e9c66b..a1278edef 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -10,15 +10,14 @@ mod suggest;
pub use self::suggest::SelfSource;
pub use self::MethodError::*;
-use crate::check::{Expectation, FnCtxt};
-use crate::ObligationCause;
+use crate::{Expectation, FnCtxt};
use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_infer::infer::{self, InferOk};
-use rustc_middle::ty::subst::Subst;
+use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable};
use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_typeck/src/check/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 392695cca..3c98a2aa3 100644
--- a/compiler/rustc_typeck/src/check/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -1,3 +1,7 @@
+use crate::{
+ method::probe::{self, Pick},
+ FnCtxt,
+};
use hir::def_id::DefId;
use hir::HirId;
use hir::ItemKind;
@@ -12,11 +16,6 @@ use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
-use crate::check::{
- method::probe::{self, Pick},
- FnCtxt,
-};
-
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pub(super) fn lint_dot_call_from_2018(
&self,
@@ -82,14 +81,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
prelude_or_array_lint,
self_expr.hir_id,
self_expr.span,
+ format!("trait method `{}` will become ambiguous in Rust 2021", segment.ident.name),
|lint| {
let sp = self_expr.span;
- let mut lint = lint.build(&format!(
- "trait method `{}` will become ambiguous in Rust 2021",
- segment.ident.name
- ));
-
let derefs = "*".repeat(pick.autoderefs);
let autoref = match pick.autoref_or_ptr_adjustment {
@@ -133,7 +128,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
- lint.emit();
+ lint
},
);
} else {
@@ -143,6 +138,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
prelude_or_array_lint,
call_expr.hir_id,
call_expr.span,
+ format!("trait method `{}` will become ambiguous in Rust 2021", segment.ident.name),
|lint| {
let sp = call_expr.span;
let trait_name = self.trait_path_or_bare_name(
@@ -151,11 +147,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pick.item.container_id(self.tcx),
);
- let mut lint = lint.build(&format!(
- "trait method `{}` will become ambiguous in Rust 2021",
- segment.ident.name
- ));
-
let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
if precise {
let args = args
@@ -202,7 +193,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
- lint.emit();
+ lint
},
);
}
@@ -257,15 +248,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
- self.tcx.struct_span_lint_hir(RUST_2021_PRELUDE_COLLISIONS, expr_id, span, |lint| {
- // "type" refers to either a type or, more likely, a trait from which
- // the associated function or method is from.
- let container_id = pick.item.container_id(self.tcx);
- let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
- let trait_generics = self.tcx.generics_of(container_id);
-
- let trait_name =
- if trait_generics.params.len() <= trait_generics.has_self as usize {
+ self.tcx.struct_span_lint_hir(
+ RUST_2021_PRELUDE_COLLISIONS,
+ expr_id,
+ span,
+ format!(
+ "trait-associated function `{}` will become ambiguous in Rust 2021",
+ method_name.name
+ ),
+ |lint| {
+ // "type" refers to either a type or, more likely, a trait from which
+ // the associated function or method is from.
+ let container_id = pick.item.container_id(self.tcx);
+ let trait_path = self.trait_path_or_bare_name(span, expr_id, container_id);
+ let trait_generics = self.tcx.generics_of(container_id);
+
+ let trait_name = if trait_generics.params.len() <= trait_generics.has_self as usize
+ {
trait_path
} else {
let counts = trait_generics.own_counts();
@@ -282,44 +281,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
)
};
- let mut lint = lint.build(&format!(
- "trait-associated function `{}` will become ambiguous in Rust 2021",
- method_name.name
- ));
-
- let mut self_ty_name = self_ty_span
- .find_ancestor_inside(span)
- .and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
- .unwrap_or_else(|| self_ty.to_string());
-
- // Get the number of generics the self type has (if an Adt) unless we can determine that
- // the user has written the self type with generics already which we (naively) do by looking
- // for a "<" in `self_ty_name`.
- if !self_ty_name.contains('<') {
- if let Adt(def, _) = self_ty.kind() {
- let generics = self.tcx.generics_of(def.did());
- if !generics.params.is_empty() {
- let counts = generics.own_counts();
- self_ty_name += &format!(
- "<{}>",
- std::iter::repeat("'_")
- .take(counts.lifetimes)
- .chain(std::iter::repeat("_").take(counts.types + counts.consts))
- .collect::<Vec<_>>()
- .join(", ")
- );
+ let mut self_ty_name = self_ty_span
+ .find_ancestor_inside(span)
+ .and_then(|span| self.sess().source_map().span_to_snippet(span).ok())
+ .unwrap_or_else(|| self_ty.to_string());
+
+ // Get the number of generics the self type has (if an Adt) unless we can determine that
+ // the user has written the self type with generics already which we (naively) do by looking
+ // for a "<" in `self_ty_name`.
+ if !self_ty_name.contains('<') {
+ if let Adt(def, _) = self_ty.kind() {
+ let generics = self.tcx.generics_of(def.did());
+ if !generics.params.is_empty() {
+ let counts = generics.own_counts();
+ self_ty_name += &format!(
+ "<{}>",
+ std::iter::repeat("'_")
+ .take(counts.lifetimes)
+ .chain(
+ std::iter::repeat("_").take(counts.types + counts.consts)
+ )
+ .collect::<Vec<_>>()
+ .join(", ")
+ );
+ }
}
}
- }
- lint.span_suggestion(
- span,
- "disambiguate the associated function",
- format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
- Applicability::MachineApplicable,
- );
-
- lint.emit();
- });
+ lint.span_suggestion(
+ span,
+ "disambiguate the associated function",
+ format!("<{} as {}>::{}", self_ty_name, trait_name, method_name.name,),
+ Applicability::MachineApplicable,
+ );
+
+ lint
+ },
+ );
}
fn trait_path_or_bare_name(
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index e9f55ab34..28aa2302f 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -3,14 +3,12 @@ use super::CandidateSource;
use super::MethodError;
use super::NoMatchData;
-use crate::check::FnCtxt;
use crate::errors::MethodCallOnUnknownType;
-use crate::hir::def::DefKind;
-use crate::hir::def_id::DefId;
-
+use crate::FnCtxt;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir as hir;
+use rustc_hir::def::DefKind;
use rustc_hir::def::Namespace;
use rustc_infer::infer::canonical::OriginalQueryValues;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
@@ -19,10 +17,11 @@ 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::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
+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,
@@ -253,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// would result in an error (basically, the same criteria we
/// would use to decide if a method is a plausible fit for
/// ambiguity purposes).
- #[instrument(level = "debug", skip(self))]
+ #[instrument(level = "debug", skip(self, candidate_filter))]
pub fn probe_for_return_type(
&self,
span: Span,
@@ -261,6 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return_type: Ty<'tcx>,
self_ty: Ty<'tcx>,
scope_expr_id: hir::HirId,
+ candidate_filter: impl Fn(&ty::AssocItem) -> bool,
) -> Vec<ty::AssocItem> {
let method_names = self
.probe_op(
@@ -272,7 +272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self_ty,
scope_expr_id,
ProbeScope::AllTraits,
- |probe_cx| Ok(probe_cx.candidate_method_names()),
+ |probe_cx| Ok(probe_cx.candidate_method_names(candidate_filter)),
)
.unwrap_or_default();
method_names
@@ -409,9 +409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
scope_expr_id,
span,
- |lint| {
- lint.build("type annotations needed").emit();
- },
+ "type annotations needed",
+ |lint| lint,
);
}
} else {
@@ -473,69 +472,65 @@ fn method_autoderef_steps<'tcx>(
) -> MethodAutoderefStepsResult<'tcx> {
debug!("method_autoderef_steps({:?})", goal);
- tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &goal, |ref infcx, goal, inference_vars| {
- let ParamEnvAnd { param_env, value: self_ty } = goal;
-
- let mut autoderef =
- Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
- .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,
- ),
- autoderefs: d,
- from_unsafe_deref: reached_raw_pointer,
- unsize: false,
- };
- if let ty::RawPtr(_) = ty.kind() {
- // all the subsequent steps will be from_unsafe_deref
- reached_raw_pointer = true;
- }
- step
- })
- .collect();
-
- let final_ty = autoderef.final_ty(true);
- let opt_bad_ty = match final_ty.kind() {
- ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
- reached_raw_pointer,
- ty: infcx
- .make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
- }),
- ty::Array(elem_ty, _) => {
- let dereferences = steps.len() - 1;
-
- steps.push(CandidateStep {
- self_ty: infcx.make_query_response_ignoring_pending_obligations(
- inference_vars,
- infcx.tcx.mk_slice(*elem_ty),
- ),
- autoderefs: dereferences,
- // this could be from an unsafe deref if we had
- // a *mut/const [T; N]
- from_unsafe_deref: reached_raw_pointer,
- unsize: true,
- });
-
- None
+ 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, DUMMY_SP)
+ .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),
+ autoderefs: d,
+ from_unsafe_deref: reached_raw_pointer,
+ unsize: false,
+ };
+ if let ty::RawPtr(_) = ty.kind() {
+ // all the subsequent steps will be from_unsafe_deref
+ reached_raw_pointer = true;
}
- _ => None,
- };
-
- debug!("method_autoderef_steps: steps={:?} opt_bad_ty={:?}", steps, opt_bad_ty);
+ step
+ })
+ .collect();
+
+ let final_ty = autoderef.final_ty(true);
+ let opt_bad_ty = match final_ty.kind() {
+ ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy {
+ reached_raw_pointer,
+ ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty),
+ }),
+ ty::Array(elem_ty, _) => {
+ let dereferences = steps.len() - 1;
+
+ steps.push(CandidateStep {
+ self_ty: infcx.make_query_response_ignoring_pending_obligations(
+ inference_vars,
+ infcx.tcx.mk_slice(*elem_ty),
+ ),
+ autoderefs: dereferences,
+ // this could be from an unsafe deref if we had
+ // a *mut/const [T; N]
+ from_unsafe_deref: reached_raw_pointer,
+ unsize: true,
+ });
- MethodAutoderefStepsResult {
- steps: tcx.arena.alloc_from_iter(steps),
- opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
- reached_recursion_limit: autoderef.reached_recursion_limit(),
+ None
}
- })
+ _ => None,
+ };
+
+ debug!("method_autoderef_steps: steps={:?} opt_bad_ty={:?}", steps, opt_bad_ty);
+
+ MethodAutoderefStepsResult {
+ steps: tcx.arena.alloc_from_iter(steps),
+ opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)),
+ reached_recursion_limit: autoderef.reached_recursion_limit(),
+ }
}
impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
@@ -972,12 +967,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
- fn candidate_method_names(&self) -> Vec<Ident> {
+ fn candidate_method_names(
+ &self,
+ candidate_filter: impl Fn(&ty::AssocItem) -> bool,
+ ) -> Vec<Ident> {
let mut set = FxHashSet::default();
let mut names: Vec<_> = self
.inherent_candidates
.iter()
.chain(&self.extension_candidates)
+ .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)
@@ -1358,24 +1357,24 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
stable_pick: &Pick<'_>,
unstable_candidates: &[(Candidate<'tcx>, Symbol)],
) {
+ let def_kind = stable_pick.item.kind.as_def_kind();
self.tcx.struct_span_lint_hir(
lint::builtin::UNSTABLE_NAME_COLLISIONS,
self.scope_expr_id,
self.span,
+ format!(
+ "{} {} with this name may be added to the standard library in the future",
+ def_kind.article(),
+ def_kind.descr(stable_pick.item.def_id),
+ ),
|lint| {
- let def_kind = stable_pick.item.kind.as_def_kind();
- let mut diag = lint.build(&format!(
- "{} {} with this name may be added to the standard library in the future",
- def_kind.article(),
- def_kind.descr(stable_pick.item.def_id),
- ));
match (stable_pick.item.kind, stable_pick.item.container) {
(ty::AssocKind::Fn, _) => {
// FIXME: This should be a `span_suggestion` instead of `help`
// However `self.span` only
// highlights the method name, so we can't use it. Also consider reusing
// the code from `report_method_error()`.
- diag.help(&format!(
+ lint.help(&format!(
"call with fully qualified syntax `{}(...)` to keep using the current \
method",
self.tcx.def_path_str(stable_pick.item.def_id),
@@ -1383,7 +1382,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
let def_id = stable_pick.item.container_id(self.tcx);
- diag.span_suggestion(
+ lint.span_suggestion(
self.span,
"use the fully qualified path to the associated const",
format!(
@@ -1399,7 +1398,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
if self.tcx.sess.is_nightly_build() {
for (candidate, feature) in unstable_candidates {
- diag.help(&format!(
+ lint.help(&format!(
"add `#![feature({})]` to the crate attributes to enable `{}`",
feature,
self.tcx.def_path_str(candidate.item.def_id),
@@ -1407,7 +1406,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
}
- diag.emit();
+ lint
},
);
}
@@ -1695,7 +1694,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
pcx.allow_similar_names = true;
pcx.assemble_inherent_candidates();
- let method_names = pcx.candidate_method_names();
+ let method_names = pcx.candidate_method_names(|_| true);
pcx.allow_similar_names = false;
let applicable_close_candidates: Vec<ty::AssocItem> = method_names
.iter()
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 2d459b2cc..6c21ed902 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1,7 +1,9 @@
//! Give useful errors and suggestions to users when an item can't be
//! found or is otherwise invalid.
-use crate::check::FnCtxt;
+use crate::errors;
+use crate::FnCtxt;
+use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -21,7 +23,7 @@ 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_trait_selection::traits::error_reporting::on_unimplemented::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::{
FulfillmentError, Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedNote,
@@ -30,7 +32,7 @@ use rustc_trait_selection::traits::{
use std::cmp::Ordering;
use std::iter;
-use super::probe::{IsSuggestion, Mode, ProbeScope};
+use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -104,7 +106,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let report_candidates = |span: Span,
err: &mut Diagnostic,
- mut sources: Vec<CandidateSource>,
+ sources: &mut Vec<CandidateSource>,
sugg_span: Span| {
sources.sort();
sources.dedup();
@@ -246,7 +248,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match error {
MethodError::NoMatch(NoMatchData {
- static_candidates: static_sources,
+ static_candidates: mut static_sources,
unsatisfied_predicates,
out_of_scope_traits,
lev_candidate,
@@ -270,7 +272,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
};
- if self.suggest_constraining_numerical_ty(
+ if self.suggest_wrapping_range_with_parens(
+ tcx, actual, source, span, item_name, &ty_str,
+ ) || self.suggest_constraining_numerical_ty(
tcx, actual, source, span, item_kind, item_name, &ty_str,
) {
return None;
@@ -418,9 +422,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
err.help(&format!("try with `{}::{}`", ty_str, item_name,));
}
- report_candidates(span, &mut err, static_sources, sugg_span);
+ report_candidates(span, &mut err, &mut static_sources, sugg_span);
} else if static_sources.len() > 1 {
- report_candidates(span, &mut err, static_sources, sugg_span);
+ report_candidates(span, &mut err, &mut static_sources, sugg_span);
}
let mut bound_spans = vec![];
@@ -854,8 +858,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Avoid crashing.
return (None, None);
}
- let OnUnimplementedNote { message, label, .. } =
- self.on_unimplemented_note(trait_ref, &obligation);
+ let OnUnimplementedNote { message, label, .. } = self
+ .err_ctxt()
+ .on_unimplemented_note(trait_ref, &obligation);
(message, label)
})
.unwrap_or((None, None))
@@ -983,7 +988,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_for_field_method(&mut err, source, span, actual, item_name);
}
- self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
+ self.check_for_inner_self(&mut err, source, span, actual, item_name);
bound_spans.sort();
bound_spans.dedup();
@@ -1002,6 +1007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
source,
out_of_scope_traits,
&unsatisfied_predicates,
+ &static_sources,
unsatisfied_bounds,
);
}
@@ -1074,7 +1080,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Some(err);
}
- MethodError::Ambiguity(sources) => {
+ MethodError::Ambiguity(mut sources) => {
let mut err = struct_span_err!(
self.sess(),
item_name.span,
@@ -1083,7 +1089,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
err.span_label(item_name.span, format!("multiple `{}` found", item_name));
- report_candidates(span, &mut err, sources, sugg_span);
+ report_candidates(span, &mut err, &mut sources, sugg_span);
err.emit();
}
@@ -1200,6 +1206,89 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
false
}
+ /// Suggest possible range with adding parentheses, for example:
+ /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
+ fn suggest_wrapping_range_with_parens(
+ &self,
+ tcx: TyCtxt<'tcx>,
+ actual: Ty<'tcx>,
+ source: SelfSource<'tcx>,
+ span: Span,
+ item_name: Ident,
+ ty_str: &str,
+ ) -> bool {
+ if let SelfSource::MethodCall(expr) = source {
+ for (_, parent) in tcx.hir().parent_iter(expr.hir_id).take(5) {
+ if let Node::Expr(parent_expr) = parent {
+ let lang_item = match parent_expr.kind {
+ ExprKind::Struct(ref qpath, _, _) => match **qpath {
+ QPath::LangItem(LangItem::Range, ..) => Some(LangItem::Range),
+ QPath::LangItem(LangItem::RangeTo, ..) => Some(LangItem::RangeTo),
+ QPath::LangItem(LangItem::RangeToInclusive, ..) => {
+ Some(LangItem::RangeToInclusive)
+ }
+ _ => None,
+ },
+ ExprKind::Call(ref func, _) => match func.kind {
+ // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
+ ExprKind::Path(QPath::LangItem(LangItem::RangeInclusiveNew, ..)) => {
+ Some(LangItem::RangeInclusiveStruct)
+ }
+ _ => None,
+ },
+ _ => None,
+ };
+
+ if lang_item.is_none() {
+ continue;
+ }
+
+ let span_included = match parent_expr.kind {
+ hir::ExprKind::Struct(_, eps, _) => {
+ eps.len() > 0 && eps.last().map_or(false, |ep| ep.span.contains(span))
+ }
+ // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
+ hir::ExprKind::Call(ref func, ..) => func.span.contains(span),
+ _ => false,
+ };
+
+ if !span_included {
+ continue;
+ }
+
+ 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 pick = self.probe_for_name(
+ span,
+ Mode::MethodCall,
+ item_name,
+ IsSuggestion(true),
+ range_ty,
+ expr.hir_id,
+ ProbeScope::AllTraits,
+ );
+ if pick.is_ok() {
+ let range_span = parent_expr.span.with_hi(expr.span.hi());
+ tcx.sess.emit_err(errors::MissingParentheseInRange {
+ span,
+ ty_str: ty_str.to_string(),
+ method_name: item_name.as_str().to_string(),
+ add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
+ func_name: item_name.name.as_str().to_string(),
+ left: range_span.shrink_to_lo(),
+ right: range_span.shrink_to_hi(),
+ }),
+ });
+ return true;
+ }
+ }
+ }
+ }
+ false
+ }
+
fn suggest_constraining_numerical_ty(
&self,
tcx: TyCtxt<'tcx>,
@@ -1262,7 +1351,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If this is a floating point literal that ends with '.',
// get rid of it to stop this from becoming a member access.
let snippet = snippet.strip_suffix('.').unwrap_or(&snippet);
-
err.span_suggestion(
lit.span,
&format!(
@@ -1395,7 +1483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
- fn check_for_unwrap_self(
+ fn check_for_inner_self(
&self,
err: &mut Diagnostic,
source: SelfSource<'tcx>,
@@ -1408,81 +1496,168 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
let ty::Adt(kind, substs) = actual.kind() else { return; };
- if !kind.is_enum() {
- return;
- }
+ match kind.adt_kind() {
+ ty::AdtKind::Enum => {
+ let matching_variants: Vec<_> = kind
+ .variants()
+ .iter()
+ .flat_map(|variant| {
+ let [field] = &variant.fields[..] else { return None; };
+ let field_ty = field.ty(tcx, substs);
+
+ // Skip `_`, since that'll just lead to ambiguity.
+ if self.resolve_vars_if_possible(field_ty).is_ty_var() {
+ return None;
+ }
- let matching_variants: Vec<_> = kind
- .variants()
- .iter()
- .flat_map(|variant| {
- let [field] = &variant.fields[..] else { return None; };
- let field_ty = field.ty(tcx, substs);
+ self.lookup_probe(
+ span,
+ item_name,
+ field_ty,
+ call_expr,
+ ProbeScope::TraitsInScope,
+ )
+ .ok()
+ .map(|pick| (variant, field, pick))
+ })
+ .collect();
+
+ let ret_ty_matches = |diagnostic_item| {
+ if let Some(ret_ty) = self
+ .ret_coercion
+ .as_ref()
+ .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
+ && let ty::Adt(kind, _) = ret_ty.kind()
+ && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
+ {
+ true
+ } else {
+ false
+ }
+ };
- // Skip `_`, since that'll just lead to ambiguity.
- if self.resolve_vars_if_possible(field_ty).is_ty_var() {
- return None;
+ match &matching_variants[..] {
+ [(_, field, pick)] => {
+ let self_ty = field.ty(tcx, substs);
+ err.span_note(
+ tcx.def_span(pick.item.def_id),
+ &format!("the method `{item_name}` exists on the type `{self_ty}`"),
+ );
+ let (article, kind, variant, question) =
+ if tcx.is_diagnostic_item(sym::Result, kind.did()) {
+ ("a", "Result", "Err", ret_ty_matches(sym::Result))
+ } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
+ ("an", "Option", "None", ret_ty_matches(sym::Option))
+ } else {
+ return;
+ };
+ if question {
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ format!(
+ "use the `?` operator to extract the `{self_ty}` value, propagating \
+ {article} `{kind}::{variant}` value to the caller"
+ ),
+ "?",
+ Applicability::MachineApplicable,
+ );
+ } else {
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ format!(
+ "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
+ panicking if the value is {article} `{kind}::{variant}`"
+ ),
+ ".expect(\"REASON\")",
+ Applicability::HasPlaceholders,
+ );
+ }
+ }
+ // FIXME(compiler-errors): Support suggestions for other matching enum variants
+ _ => {}
}
-
- self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
- .ok()
- .map(|pick| (variant, field, pick))
- })
- .collect();
-
- let ret_ty_matches = |diagnostic_item| {
- if let Some(ret_ty) = self
- .ret_coercion
- .as_ref()
- .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
- && let ty::Adt(kind, _) = ret_ty.kind()
- && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
- {
- true
- } else {
- false
}
- };
+ // Target wrapper types - types that wrap or pretend to wrap another type,
+ // perhaps this inner type is meant to be called?
+ ty::AdtKind::Struct | ty::AdtKind::Union => {
+ let [first] = ***substs else { return; };
+ let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
+ let Ok(pick) = self.lookup_probe(
+ span,
+ item_name,
+ ty,
+ call_expr,
+ ProbeScope::TraitsInScope,
+ ) else { return; };
- match &matching_variants[..] {
- [(_, field, pick)] => {
- let self_ty = field.ty(tcx, substs);
- err.span_note(
- tcx.def_span(pick.item.def_id),
- &format!("the method `{item_name}` exists on the type `{self_ty}`"),
- );
- let (article, kind, variant, question) =
- if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
- ("a", "Result", "Err", ret_ty_matches(sym::Result))
- } else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
- ("an", "Option", "None", ret_ty_matches(sym::Option))
- } else {
- return;
+ let name = self.ty_to_value_string(actual);
+ let inner_id = kind.did();
+ let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
+ pick.autoref_or_ptr_adjustment
+ {
+ Some(mutbl)
+ } else {
+ None
+ };
+
+ if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
+ err.help("use `with` or `try_with` to access thread local storage");
+ } else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
+ err.help(format!(
+ "if this `{name}` has been initialized, \
+ use one of the `assume_init` methods to access the inner value"
+ ));
+ } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
+ let (suggestion, borrow_kind, panic_if) = match mutable {
+ Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
+ Some(Mutability::Mut) => {
+ (".borrow_mut()", "mutably borrow", "any borrows exist")
+ }
+ None => return,
};
- if question {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
- "use the `?` operator to extract the `{self_ty}` value, propagating \
- {article} `{kind}::{variant}` value to the caller"
+ "use `{suggestion}` to {borrow_kind} the `{ty}`, \
+ panicking if {panic_if}"
),
- "?",
- Applicability::MachineApplicable,
+ suggestion,
+ Applicability::MaybeIncorrect,
);
- } else {
+ } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
- "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
- panicking if the value is {article} `{kind}::{variant}`"
+ "use `.lock().unwrap()` to borrow the `{ty}`, \
+ blocking the current thread until it can be acquired"
),
- ".expect(\"REASON\")",
- Applicability::HasPlaceholders,
+ ".lock().unwrap()",
+ Applicability::MaybeIncorrect,
);
- }
+ } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
+ let (suggestion, borrow_kind) = match mutable {
+ Some(Mutability::Not) => (".read().unwrap()", "borrow"),
+ Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
+ None => return,
+ };
+ err.span_suggestion_verbose(
+ expr.span.shrink_to_hi(),
+ format!(
+ "use `{suggestion}` to {borrow_kind} the `{ty}`, \
+ blocking the current thread until it can be acquired"
+ ),
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ return;
+ };
+
+ err.span_note(
+ tcx.def_span(pick.item.def_id),
+ &format!("the method `{item_name}` exists on the type `{ty}`"),
+ );
}
- // FIXME(compiler-errors): Support suggestions for other matching enum variants
- _ => {}
}
}
@@ -1841,6 +2016,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Option<ty::Predicate<'tcx>>,
Option<ObligationCause<'tcx>>,
)],
+ static_candidates: &[CandidateSource],
unsatisfied_bounds: bool,
) {
let mut alt_rcvr_sugg = false;
@@ -1955,6 +2131,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None => true,
})
.filter(|info| {
+ // Static candidates are already implemented, and known not to work
+ // Do not suggest them again
+ static_candidates.iter().all(|sc| match *sc {
+ CandidateSource::Trait(def_id) => def_id != info.def_id,
+ CandidateSource::Impl(def_id) => {
+ self.tcx.trait_id_of_impl(def_id) != Some(info.def_id)
+ }
+ })
+ })
+ .filter(|info| {
// We approximate the coherence rules to only suggest
// traits that are legal to implement by requiring that
// either the type or trait is local. Multi-dispatch means
@@ -2077,7 +2263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Colon,
Nothing,
}
- let ast_generics = hir.get_generics(id.owner).unwrap();
+ let ast_generics = hir.get_generics(id.owner.def_id).unwrap();
let (sp, mut introducer) = if let Some(span) =
ast_generics.bounds_span_for_suggestions(def_id)
{
@@ -2236,6 +2422,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
+ /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
+ /// FIXME: currently not working for suggesting `map_or_else`, see #102408
+ pub(crate) fn suggest_else_fn_with_closure(
+ &self,
+ err: &mut Diagnostic,
+ expr: &hir::Expr<'_>,
+ found: Ty<'tcx>,
+ expected: Ty<'tcx>,
+ ) -> bool {
+ let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(expr, found)
+ else { return false; };
+
+ if !self.can_coerce(output, expected) {
+ return false;
+ }
+
+ let parent = self.tcx.hir().get_parent_node(expr.hir_id);
+ if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) &&
+ let hir::ExprKind::MethodCall(
+ hir::PathSegment { ident: method_name, .. },
+ self_expr,
+ args,
+ ..,
+ ) = call_expr.kind &&
+ let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr) {
+ let new_name = Ident {
+ name: Symbol::intern(&format!("{}_else", method_name.as_str())),
+ span: method_name.span,
+ };
+ let probe = self.lookup_probe(
+ expr.span,
+ new_name,
+ self_ty,
+ self_expr,
+ ProbeScope::TraitsInScope,
+ );
+
+ // 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() &&
+ fn_args.len() == args.len() + 1 {
+ err.span_suggestion_verbose(
+ method_name.span.shrink_to_hi(),
+ &format!("try calling `{}` instead", new_name.name.as_str()),
+ "_else",
+ Applicability::MaybeIncorrect,
+ );
+ return true;
+ }
+ }
+ false
+ }
+
/// Checks whether there is a local type somewhere in the chain of
/// autoderefs of `rcvr_ty`.
fn type_derefs_to_local(
diff --git a/compiler/rustc_typeck/src/check/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 4754717c2..895739976 100644
--- a/compiler/rustc_typeck/src/check/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -2,7 +2,7 @@
use super::method::MethodCallee;
use super::{has_expected_num_generic_args, FnCtxt};
-use crate::check::Expectation;
+use crate::Expectation;
use rustc_ast as ast;
use rustc_errors::{self, struct_span_err, Applicability, Diagnostic};
use rustc_hir as hir;
@@ -13,11 +13,12 @@ use rustc_middle::ty::adjustment::{
};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitable};
+use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::Span;
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt as _;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt as _;
use rustc_trait_selection::traits::{FulfillmentError, TraitEngine, TraitEngineExt};
use rustc_type_ir::sty::TyKind::*;
@@ -470,7 +471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// This has nothing here because it means we did string
// concatenation (e.g., "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted
- } else if lhs_ty.has_param_types_or_consts() {
+ } else if lhs_ty.has_non_region_param() {
// Look for a TraitPredicate in the Fulfillment errors,
// and use it to generate a suggestion.
//
@@ -511,7 +512,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => None,
};
- self.suggest_restricting_param_bound(
+ self.err_ctxt().suggest_restricting_param_bound(
&mut err,
trait_pred,
output_associated_item,
@@ -656,12 +657,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
format!("cannot apply unary operator `{}`", op.as_str()),
);
- if operand_ty.has_param_types_or_consts() {
+ if operand_ty.has_non_region_param() {
let predicates = errors.iter().filter_map(|error| {
error.obligation.predicate.to_opt_poly_trait_pred()
});
for pred in predicates {
- self.suggest_restricting_param_bound(
+ self.err_ctxt().suggest_restricting_param_bound(
&mut err,
pred,
None,
@@ -677,7 +678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the previous expression was a block expression, suggest parentheses
// (turning this into a binary subtraction operation instead.)
// for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
- self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
} else {
match actual.kind() {
Uint(_) if op == hir::UnOp::Neg => {
diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 8906b622b..ea90da4a6 100644
--- a/compiler/rustc_typeck/src/check/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1,6 +1,5 @@
-use crate::check::FnCtxt;
+use crate::FnCtxt;
use rustc_ast as ast;
-
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -1790,10 +1789,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&unmentioned_fields.iter().map(|(_, i)| i).collect::<Vec<_>>(),
);
- self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, |build| {
- let mut lint = build.build("some fields are not explicitly listed");
+ self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
-
lint.help(
"ensure that all fields are mentioned explicitly by adding the suggested fields",
);
@@ -1801,7 +1798,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
"the pattern is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
ty,
));
- lint.emit();
+
+ lint
});
}
diff --git a/compiler/rustc_typeck/src/check/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs
index 2e0f37eba..ba8cf6926 100644
--- a/compiler/rustc_typeck/src/check/place_op.rs
+++ b/compiler/rustc_hir_typeck/src/place_op.rs
@@ -1,5 +1,5 @@
-use crate::check::method::MethodCallee;
-use crate::check::{has_expected_num_generic_args, FnCtxt, PlaceOp};
+use crate::method::MethodCallee;
+use crate::{has_expected_num_generic_args, FnCtxt, PlaceOp};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_hir as hir;
diff --git a/compiler/rustc_typeck/src/check/rvalue_scopes.rs b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
index 22c9e7961..22c9e7961 100644
--- a/compiler/rustc_typeck/src/check/rvalue_scopes.rs
+++ b/compiler/rustc_hir_typeck/src/rvalue_scopes.rs
diff --git a/compiler/rustc_typeck/src/check/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 0b207a6c0..4dea40829 100644
--- a/compiler/rustc_typeck/src/check/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -352,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// and that the path can be captured with required capture kind (depending on use in closure,
/// move closure etc.)
///
- /// Returns the set of of adjusted information along with the inferred closure kind and span
+ /// Returns the set of adjusted information along with the inferred closure kind and span
/// associated with the closure kind inference.
///
/// Note that we *always* infer a minimal kind, even if
@@ -749,10 +749,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
closure_hir_id,
closure_head_span,
+ reasons.migration_message(),
|lint| {
- let mut diagnostics_builder = lint.build(
- &reasons.migration_message(),
- );
for NeededMigration { var_hir_id, diagnostics_info } in &need_migrations {
// Labels all the usage of the captured variable and why they are responsible
// for migration being needed
@@ -760,13 +758,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match &lint_note.captures_info {
UpvarMigrationInfo::CapturingPrecise { source_expr: Some(capture_expr_id), var_name: captured_name } => {
let cause_span = self.tcx.hir().span(*capture_expr_id);
- diagnostics_builder.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
+ lint.span_label(cause_span, format!("in Rust 2018, this closure captures all of `{}`, but in Rust 2021, it will only capture `{}`",
self.tcx.hir().name(*var_hir_id),
captured_name,
));
}
UpvarMigrationInfo::CapturingNothing { use_span } => {
- diagnostics_builder.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
+ lint.span_label(*use_span, format!("in Rust 2018, this causes the closure to capture `{}`, but in Rust 2021, it has no effect",
self.tcx.hir().name(*var_hir_id),
));
}
@@ -781,13 +779,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match &lint_note.captures_info {
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
- diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
+ lint.span_label(drop_location_span, format!("in Rust 2018, `{}` is dropped here, but in Rust 2021, only `{}` will be dropped here as part of the closure",
self.tcx.hir().name(*var_hir_id),
captured_name,
));
}
UpvarMigrationInfo::CapturingNothing { use_span: _ } => {
- diagnostics_builder.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
+ lint.span_label(drop_location_span, format!("in Rust 2018, `{v}` is dropped here along with the closure, but in Rust 2021 `{v}` is not part of the closure",
v = self.tcx.hir().name(*var_hir_id),
));
}
@@ -800,7 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match &lint_note.captures_info {
UpvarMigrationInfo::CapturingPrecise { var_name: captured_name, .. } => {
let var_name = self.tcx.hir().name(*var_hir_id);
- diagnostics_builder.span_label(closure_head_span, format!("\
+ lint.span_label(closure_head_span, format!("\
in Rust 2018, this closure implements {missing_trait} \
as `{var_name}` implements {missing_trait}, but in Rust 2021, \
this closure will no longer implement {missing_trait} \
@@ -814,7 +812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
- diagnostics_builder.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
+ lint.note("for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>");
let diagnostic_msg = format!(
"add a dummy let to cause {} to be fully captured",
@@ -857,7 +855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We take the indentation from the next non-empty line.
let line2 = lines.find(|line| !line.is_empty()).unwrap_or_default();
let indent = line2.split_once(|c: char| !c.is_whitespace()).unwrap_or_default().0;
- diagnostics_builder.span_suggestion(
+ lint.span_suggestion(
closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(),
&diagnostic_msg,
format!("\n{indent}{migration_string};"),
@@ -868,7 +866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// braces, but with more than just the opening
// brace on the first line. We put the `let`
// directly after the `{`.
- diagnostics_builder.span_suggestion(
+ lint.span_suggestion(
closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(),
&diagnostic_msg,
format!(" {migration_string};"),
@@ -877,7 +875,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// This is a closure without braces around the body.
// We add braces to add the `let` before the body.
- diagnostics_builder.multipart_suggestion(
+ lint.multipart_suggestion(
&diagnostic_msg,
vec![
(closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")),
@@ -887,7 +885,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
} else {
- diagnostics_builder.span_suggestion(
+ lint.span_suggestion(
closure_span,
&diagnostic_msg,
migration_string,
@@ -895,7 +893,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
- diagnostics_builder.emit();
+ lint
},
);
}
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 9ecf34e9a..1e26daa9c 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -2,7 +2,7 @@
// unresolved type variables and replaces "ty_var" types with their
// substitutions.
-use crate::check::FnCtxt;
+use crate::FnCtxt;
use hir::def_id::LocalDefId;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::ErrorGuaranteed;
@@ -536,33 +536,37 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let opaque_types =
self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
for (opaque_type_key, decl) in opaque_types {
- let hidden_type = match decl.origin {
- hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
- let ty = self.resolve(decl.hidden_type.ty, &decl.hidden_type.span);
- struct RecursionChecker {
- def_id: LocalDefId,
- }
- impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
- type BreakTy = ();
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if let ty::Opaque(def_id, _) = *t.kind() {
- if def_id == self.def_id.to_def_id() {
- return ControlFlow::Break(());
- }
- }
- t.super_visit_with(self)
+ let hidden_type = self.resolve(decl.hidden_type, &decl.hidden_type.span);
+ let opaque_type_key = self.resolve(opaque_type_key, &decl.hidden_type.span);
+
+ struct RecursionChecker {
+ def_id: LocalDefId,
+ }
+ impl<'tcx> ty::TypeVisitor<'tcx> for RecursionChecker {
+ type BreakTy = ();
+ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+ if let ty::Opaque(def_id, _) = *t.kind() {
+ if def_id == self.def_id.to_def_id() {
+ return ControlFlow::Break(());
}
}
- if ty
- .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
- .is_break()
- {
- return;
- }
- Some(ty)
+ t.super_visit_with(self)
}
- hir::OpaqueTyOrigin::TyAlias => None,
- };
+ }
+ if hidden_type
+ .visit_with(&mut RecursionChecker { def_id: opaque_type_key.def_id })
+ .is_break()
+ {
+ continue;
+ }
+
+ let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
+ opaque_type_key,
+ self.fcx.infcx.tcx,
+ true,
+ decl.origin,
+ );
+
self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
}
}
@@ -700,7 +704,7 @@ impl Locatable for hir::HirId {
/// unresolved types and so forth.
struct Resolver<'cx, 'tcx> {
tcx: TyCtxt<'tcx>,
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
span: &'cx dyn Locatable,
body: &'tcx hir::Body<'tcx>,
@@ -717,27 +721,14 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
Resolver { tcx: fcx.tcx, infcx: fcx, span, body, replaced_with_error: false }
}
- fn report_type_error(&self, t: Ty<'tcx>) {
+ fn report_error(&self, p: impl Into<ty::GenericArg<'tcx>>) {
if !self.tcx.sess.has_errors().is_some() {
self.infcx
+ .err_ctxt()
.emit_inference_failure_err(
Some(self.body.id()),
self.span.to_span(self.tcx),
- t.into(),
- E0282,
- false,
- )
- .emit();
- }
- }
-
- fn report_const_error(&self, c: ty::Const<'tcx>) {
- if self.tcx.sess.has_errors().is_none() {
- self.infcx
- .emit_inference_failure_err(
- Some(self.body.id()),
- self.span.to_span(self.tcx),
- c.into(),
+ p.into(),
E0282,
false,
)
@@ -782,7 +773,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
}
Err(_) => {
debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t);
- self.report_type_error(t);
+ self.report_error(t);
self.replaced_with_error = true;
self.tcx().ty_error()
}
@@ -799,7 +790,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
Ok(ct) => self.tcx.erase_regions(ct),
Err(_) => {
debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct);
- self.report_const_error(ct);
+ self.report_error(ct);
self.replaced_with_error = true;
self.tcx().const_error(ct.ty())
}
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index d3c425a07..179e85f32 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_graphviz = { path = "../rustc_graphviz" }
diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs
index 2c9e21f76..83dd9a67e 100644
--- a/compiler/rustc_incremental/src/lib.rs
+++ b/compiler/rustc_incremental/src/lib.rs
@@ -2,7 +2,6 @@
#![deny(missing_docs)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index 710c4a01b..79e2d371e 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -149,19 +149,19 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- dirty_clean_visitor.check_item(id.def_id);
+ dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.trait_items() {
- dirty_clean_visitor.check_item(id.def_id);
+ dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.impl_items() {
- dirty_clean_visitor.check_item(id.def_id);
+ dirty_clean_visitor.check_item(id.owner_id.def_id);
}
for id in crate_items.foreign_items() {
- dirty_clean_visitor.check_item(id.def_id);
+ dirty_clean_visitor.check_item(id.owner_id.def_id);
}
let mut all_attrs = FindAllAttrs { tcx, found_attrs: vec![] };
@@ -302,7 +302,7 @@ impl<'tcx> DirtyCleanVisitor<'tcx> {
HirNode::ImplItem(item) => match item.kind {
ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL),
ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL),
- ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
+ ImplItemKind::Type(..) => ("NodeImplType", LABELS_CONST_IN_IMPL),
},
_ => self.tcx.sess.span_fatal(
attr.span,
diff --git a/compiler/rustc_index/Cargo.toml b/compiler/rustc_index/Cargo.toml
index 8a81a93a9..d8ea5aa80 100644
--- a/compiler/rustc_index/Cargo.toml
+++ b/compiler/rustc_index/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
arrayvec = { version = "0.7", default-features = false }
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index a00d7bd68..23a4c1f06 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,9 +1,7 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(allow_internal_unstable)]
-#![feature(bench_black_box)]
#![feature(extend_one)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(new_uninit)]
#![feature(step_trait)]
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index d232a1864..2131d1906 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,10 +1,11 @@
use hir::GenericParamKind;
use rustc_errors::{
- fluent, AddSubdiagnostic, Applicability, DiagnosticMessage, DiagnosticStyledString, MultiSpan,
+ fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
+ MultiSpan, SubdiagnosticMessage,
};
use rustc_hir as hir;
use rustc_hir::{FnRetTy, Ty};
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::{Region, TyCtxt};
use rustc_span::symbol::kw;
use rustc_span::{symbol::Ident, BytePos, Span};
@@ -16,20 +17,20 @@ use crate::infer::error_reporting::{
pub mod note_and_explain;
-#[derive(SessionDiagnostic)]
-#[diag(infer::opaque_hidden_type)]
+#[derive(Diagnostic)]
+#[diag(infer_opaque_hidden_type)]
pub struct OpaqueHiddenTypeDiag {
#[primary_span]
#[label]
pub span: Span,
- #[note(infer::opaque_type)]
+ #[note(opaque_type)]
pub opaque_type: Span,
- #[note(infer::hidden_type)]
+ #[note(hidden_type)]
pub hidden_type: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0282")]
+#[derive(Diagnostic)]
+#[diag(infer_type_annotations_needed, code = "E0282")]
pub struct AnnotationRequired<'a> {
#[primary_span]
pub span: Span,
@@ -46,8 +47,8 @@ pub struct AnnotationRequired<'a> {
}
// Copy of `AnnotationRequired` for E0283
-#[derive(SessionDiagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0283")]
+#[derive(Diagnostic)]
+#[diag(infer_type_annotations_needed, code = "E0283")]
pub struct AmbigousImpl<'a> {
#[primary_span]
pub span: Span,
@@ -64,8 +65,8 @@ pub struct AmbigousImpl<'a> {
}
// Copy of `AnnotationRequired` for E0284
-#[derive(SessionDiagnostic)]
-#[diag(infer::type_annotations_needed, code = "E0284")]
+#[derive(Diagnostic)]
+#[diag(infer_type_annotations_needed, code = "E0284")]
pub struct AmbigousReturn<'a> {
#[primary_span]
pub span: Span,
@@ -81,8 +82,8 @@ pub struct AmbigousReturn<'a> {
pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
}
-#[derive(SessionDiagnostic)]
-#[diag(infer::need_type_info_in_generator, code = "E0698")]
+#[derive(Diagnostic)]
+#[diag(infer_need_type_info_in_generator, code = "E0698")]
pub struct NeedTypeInfoInGenerator<'a> {
#[primary_span]
pub span: Span,
@@ -92,8 +93,8 @@ pub struct NeedTypeInfoInGenerator<'a> {
}
// Used when a better one isn't available
-#[derive(SessionSubdiagnostic)]
-#[label(infer::label_bad)]
+#[derive(Subdiagnostic)]
+#[label(infer_label_bad)]
pub struct InferenceBadError<'a> {
#[primary_span]
pub span: Span,
@@ -106,10 +107,10 @@ pub struct InferenceBadError<'a> {
pub name: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum SourceKindSubdiag<'a> {
#[suggestion_verbose(
- infer::source_kind_subdiag_let,
+ infer_source_kind_subdiag_let,
code = ": {type_name}",
applicability = "has-placeholders"
)]
@@ -124,7 +125,7 @@ pub enum SourceKindSubdiag<'a> {
prefix: &'a str,
arg_name: String,
},
- #[label(infer::source_kind_subdiag_generic_label)]
+ #[label(infer_source_kind_subdiag_generic_label)]
GenericLabel {
#[primary_span]
span: Span,
@@ -135,7 +136,7 @@ pub enum SourceKindSubdiag<'a> {
parent_name: String,
},
#[suggestion_verbose(
- infer::source_kind_subdiag_generic_suggestion,
+ infer_source_kind_subdiag_generic_suggestion,
code = "::<{args}>",
applicability = "has-placeholders"
)]
@@ -147,10 +148,10 @@ pub enum SourceKindSubdiag<'a> {
},
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum SourceKindMultiSuggestion<'a> {
#[multipart_suggestion_verbose(
- infer::source_kind_fully_qualified,
+ infer_source_kind_fully_qualified,
applicability = "has-placeholders"
)]
FullyQualified {
@@ -163,7 +164,7 @@ pub enum SourceKindMultiSuggestion<'a> {
successor_pos: &'a str,
},
#[multipart_suggestion_verbose(
- infer::source_kind_closure_return,
+ infer_source_kind_closure_return,
applicability = "has-placeholders"
)]
ClosureReturn {
@@ -228,8 +229,11 @@ pub enum RegionOriginNote<'a> {
},
}
-impl AddSubdiagnostic for RegionOriginNote<'_> {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for RegionOriginNote<'_> {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
let mut label_or_note = |span, msg: DiagnosticMessage| {
let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count();
let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count();
@@ -256,7 +260,7 @@ impl AddSubdiagnostic for RegionOriginNote<'_> {
requirement,
expected_found: Some((expected, found)),
} => {
- label_or_note(span, fluent::infer::subtype);
+ label_or_note(span, fluent::infer_subtype);
diag.set_arg("requirement", requirement);
diag.note_expected_found(&"", expected, &"", found);
@@ -265,7 +269,7 @@ impl AddSubdiagnostic for RegionOriginNote<'_> {
// FIXME: this really should be handled at some earlier stage. Our
// handling of region checking when type errors are present is
// *terrible*.
- label_or_note(span, fluent::infer::subtype_2);
+ label_or_note(span, fluent::infer_subtype_2);
diag.set_arg("requirement", requirement);
}
};
@@ -289,13 +293,16 @@ pub enum LifetimeMismatchLabels {
},
}
-impl AddSubdiagnostic for LifetimeMismatchLabels {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for LifetimeMismatchLabels {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
match self {
LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => {
- diag.span_label(param_span, fluent::infer::declared_different);
- diag.span_label(ret_span, fluent::infer::nothing);
- diag.span_label(span, fluent::infer::data_returned);
+ diag.span_label(param_span, fluent::infer_declared_different);
+ diag.span_label(ret_span, fluent::infer_nothing);
+ diag.span_label(span, fluent::infer_data_returned);
diag.set_arg("label_var1_exists", label_var1.is_some());
diag.set_arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default());
}
@@ -308,13 +315,13 @@ impl AddSubdiagnostic for LifetimeMismatchLabels {
sub: label_var2,
} => {
if hir_equal {
- diag.span_label(ty_sup, fluent::infer::declared_multiple);
- diag.span_label(ty_sub, fluent::infer::nothing);
- diag.span_label(span, fluent::infer::data_lifetime_flow);
+ diag.span_label(ty_sup, fluent::infer_declared_multiple);
+ diag.span_label(ty_sub, fluent::infer_nothing);
+ diag.span_label(span, fluent::infer_data_lifetime_flow);
} else {
- diag.span_label(ty_sup, fluent::infer::types_declared_different);
- diag.span_label(ty_sub, fluent::infer::nothing);
- diag.span_label(span, fluent::infer::data_flows);
+ diag.span_label(ty_sup, fluent::infer_types_declared_different);
+ diag.span_label(ty_sub, fluent::infer_nothing);
+ diag.span_label(span, fluent::infer_data_flows);
diag.set_arg("label_var1_exists", label_var1.is_some());
diag.set_arg(
"label_var1",
@@ -339,8 +346,11 @@ pub struct AddLifetimeParamsSuggestion<'a> {
pub add_note: bool,
}
-impl AddSubdiagnostic for AddLifetimeParamsSuggestion<'_> {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
let mut mk_suggestion = || {
let (
hir::Ty { kind: hir::TyKind::Rptr(lifetime_sub, _), .. },
@@ -409,7 +419,7 @@ impl AddSubdiagnostic for AddLifetimeParamsSuggestion<'_> {
}
diag.multipart_suggestion(
- fluent::infer::lifetime_param_suggestion,
+ fluent::infer_lifetime_param_suggestion,
suggestions,
Applicability::MaybeIncorrect,
);
@@ -417,13 +427,13 @@ impl AddSubdiagnostic for AddLifetimeParamsSuggestion<'_> {
true
};
if mk_suggestion() && self.add_note {
- diag.note(fluent::infer::lifetime_param_suggestion_elided);
+ diag.note(fluent::infer_lifetime_param_suggestion_elided);
}
}
}
-#[derive(SessionDiagnostic)]
-#[diag(infer::lifetime_mismatch, code = "E0623")]
+#[derive(Diagnostic)]
+#[diag(infer_lifetime_mismatch, code = "E0623")]
pub struct LifetimeMismatch<'a> {
#[primary_span]
pub span: Span,
@@ -438,53 +448,49 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
pub binding_span: Span,
}
-impl AddSubdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
- fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
+ fn add_to_diagnostic_with<F>(mut self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
self.unmet_requirements
- .push_span_label(self.binding_span, fluent::infer::msl_introduces_static);
- diag.span_note(self.unmet_requirements, fluent::infer::msl_unmet_req);
+ .push_span_label(self.binding_span, fluent::infer_msl_introduces_static);
+ diag.span_note(self.unmet_requirements, fluent::infer_msl_unmet_req);
}
}
-pub struct ImplNote {
- pub impl_span: Option<Span>,
-}
-
-impl AddSubdiagnostic for ImplNote {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
- match self.impl_span {
- Some(span) => diag.span_note(span, fluent::infer::msl_impl_note),
- None => diag.note(fluent::infer::msl_impl_note),
- };
- }
-}
-
-pub enum TraitSubdiag {
- Note { span: Span },
- Sugg { span: Span },
+// FIXME(#100717): replace with a `Option<Span>` when subdiagnostic supports that
+#[derive(Subdiagnostic)]
+pub enum DoesNotOutliveStaticFromImpl {
+ #[note(infer_does_not_outlive_static_from_impl)]
+ Spanned {
+ #[primary_span]
+ span: Span,
+ },
+ #[note(infer_does_not_outlive_static_from_impl)]
+ Unspanned,
}
-// FIXME(#100717) used in `Vec<TraitSubdiag>` so requires eager translation/list support
-impl AddSubdiagnostic for TraitSubdiag {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
- match self {
- TraitSubdiag::Note { span } => {
- diag.span_note(span, "this has an implicit `'static` lifetime requirement");
- }
- TraitSubdiag::Sugg { span } => {
- diag.span_suggestion_verbose(
- span,
- "consider relaxing the implicit `'static` requirement",
- " + '_".to_owned(),
- rustc_errors::Applicability::MaybeIncorrect,
- );
- }
- }
- }
+#[derive(Subdiagnostic)]
+pub enum ImplicitStaticLifetimeSubdiag {
+ #[note(infer_implicit_static_lifetime_note)]
+ Note {
+ #[primary_span]
+ span: Span,
+ },
+ #[suggestion_verbose(
+ infer_implicit_static_lifetime_suggestion,
+ code = " + '_",
+ applicability = "maybe-incorrect"
+ )]
+ Sugg {
+ #[primary_span]
+ span: Span,
+ },
}
-#[derive(SessionDiagnostic)]
-#[diag(infer::mismatched_static_lifetime)]
+#[derive(Diagnostic)]
+#[diag(infer_mismatched_static_lifetime)]
pub struct MismatchedStaticLifetime<'a> {
#[primary_span]
pub cause_span: Span,
@@ -493,7 +499,7 @@ pub struct MismatchedStaticLifetime<'a> {
#[subdiagnostic]
pub expl: Option<note_and_explain::RegionExplanation<'a>>,
#[subdiagnostic]
- pub impl_note: ImplNote,
- #[subdiagnostic]
- pub trait_subdiags: Vec<TraitSubdiag>,
+ pub does_not_outlive_static_from_impl: DoesNotOutliveStaticFromImpl,
+ #[subdiagnostic(eager)]
+ pub implicit_static_lifetimes: Vec<ImplicitStaticLifetimeSubdiag>,
}
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 7e051835b..6a29d8562 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,5 +1,7 @@
use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{self, fluent, AddSubdiagnostic, IntoDiagnosticArg};
+use rustc_errors::{
+ self, fluent, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage,
+};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{symbol::kw, Span};
@@ -158,12 +160,15 @@ impl RegionExplanation<'_> {
}
}
-impl AddSubdiagnostic for RegionExplanation<'_> {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for RegionExplanation<'_> {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
if let Some(span) = self.desc.span {
- diag.span_note(span, fluent::infer::region_explanation);
+ diag.span_note(span, fluent::infer_region_explanation);
} else {
- diag.note(fluent::infer::region_explanation);
+ diag.note(fluent::infer_region_explanation);
}
self.desc.add_to(diag);
diag.set_arg("pref_kind", self.prefix);
diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs
index 00e238648..5ff3779fa 100644
--- a/compiler/rustc_infer/src/infer/at.rs
+++ b/compiler/rustc_infer/src/infer/at.rs
@@ -31,7 +31,7 @@ use rustc_middle::ty::relate::{Relate, TypeRelation};
use rustc_middle::ty::{Const, ImplSubject};
pub struct At<'a, 'tcx> {
- pub infcx: &'a InferCtxt<'a, 'tcx>,
+ pub infcx: &'a InferCtxt<'tcx>,
pub cause: &'a ObligationCause<'tcx>,
pub param_env: ty::ParamEnv<'tcx>,
/// Whether we should define opaque types
@@ -48,9 +48,9 @@ pub struct Trace<'a, 'tcx> {
trace: TypeTrace<'tcx>,
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
#[inline]
- pub fn at(
+ pub fn at<'a>(
&'a self,
cause: &'a ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -66,7 +66,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
tcx: self.tcx,
defining_use_anchor: self.defining_use_anchor,
considering_regions: self.considering_regions,
- in_progress_typeck_results: self.in_progress_typeck_results,
inner: self.inner.clone(),
skip_leak_check: self.skip_leak_check.clone(),
lexical_region_resolutions: self.lexical_region_resolutions.clone(),
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 9488d0a6c..a3ff70363 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -20,7 +20,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::Idx;
use smallvec::SmallVec;
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Canonicalizes a query value `V`. When we canonicalize a query,
/// we not only canonicalize unbound inference variables, but we
/// *also* replace all free regions whatsoever. So for example a
@@ -316,7 +316,7 @@ impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic {
}
struct Canonicalizer<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
variables: SmallVec<[CanonicalVarInfo<'tcx>; 8]>,
query_state: &'cx mut OriginalQueryValues<'tcx>,
@@ -521,7 +521,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
/// `canonicalize_query` and `canonicalize_response`.
fn canonicalize<V>(
value: V,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
tcx: TyCtxt<'tcx>,
canonicalize_region_mode: &dyn CanonicalizeMode,
query_state: &mut OriginalQueryValues<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index a9294a85e..06ca2534d 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -36,7 +36,7 @@ mod canonicalizer;
pub mod query_response;
mod substitute;
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Creates a substitution S for the canonical value with fresh
/// inference variables and applies it to the canonical value.
/// Returns both the instantiated result *and* the substitution S.
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 56e834898..a299a3e57 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -16,8 +16,8 @@ use crate::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelating
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution};
-use crate::traits::TraitEngine;
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
+use crate::traits::{PredicateObligations, TraitEngine};
use rustc_data_structures::captures::Captures;
use rustc_index::vec::Idx;
use rustc_index::vec::IndexVec;
@@ -32,7 +32,7 @@ use rustc_span::Span;
use std::fmt::Debug;
use std::iter;
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// This method is meant to be invoked as the final step of a canonical query
/// implementation. It is given:
///
@@ -509,7 +509,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, '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.handle_opaque_type(a, b, true, cause, param_env)?.obligations);
+ obligations.extend(self.at(cause, param_env).eq(a, b)?.obligations);
}
Ok(InferOk { value: result_subst, obligations })
@@ -677,7 +677,7 @@ pub fn make_query_region_constraints<'tcx>(
}
struct QueryTypeRelatingDelegate<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
obligations: &'a mut Vec<PredicateObligation<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
cause: &'a ObligationCause<'tcx>,
@@ -741,17 +741,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> {
true
}
- fn register_opaque_type(
+ fn register_opaque_type_obligations(
&mut self,
- a: Ty<'tcx>,
- b: Ty<'tcx>,
- a_is_expected: bool,
+ obligations: PredicateObligations<'tcx>,
) -> Result<(), TypeError<'tcx>> {
- self.obligations.extend(
- self.infcx
- .handle_opaque_type(a, b, a_is_expected, &self.cause, self.param_env)?
- .obligations,
- );
+ self.obligations.extend(obligations);
Ok(())
}
}
diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs
index c406df9e4..b5427f639 100644
--- a/compiler/rustc_infer/src/infer/combine.rs
+++ b/compiler/rustc_infer/src/infer/combine.rs
@@ -43,7 +43,7 @@ use rustc_span::{Span, DUMMY_SP};
#[derive(Clone)]
pub struct CombineFields<'infcx, 'tcx> {
- pub infcx: &'infcx InferCtxt<'infcx, 'tcx>,
+ pub infcx: &'infcx InferCtxt<'tcx>,
pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>,
pub param_env: ty::ParamEnv<'tcx>,
@@ -63,7 +63,7 @@ pub enum RelationDir {
EqTo,
}
-impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
pub fn super_combine_tys<R>(
&self,
relation: &mut R,
@@ -147,11 +147,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
ty::ConstKind::Infer(InferConst::Var(a_vid)),
ty::ConstKind::Infer(InferConst::Var(b_vid)),
) => {
- self.inner
- .borrow_mut()
- .const_unification_table()
- .unify_var_var(a_vid, b_vid)
- .map_err(|e| const_unification_error(a_is_expected, e))?;
+ self.inner.borrow_mut().const_unification_table().union(a_vid, b_vid);
return Ok(a);
}
@@ -246,21 +242,17 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> {
let value = ConstInferUnifier { infcx: self, span, param_env, for_universe, target_vid }
.relate(ct, ct)?;
- self.inner
- .borrow_mut()
- .const_unification_table()
- .unify_var_value(
- target_vid,
- ConstVarValue {
- origin: ConstVariableOrigin {
- kind: ConstVariableOriginKind::ConstInference,
- span: DUMMY_SP,
- },
- val: ConstVariableValue::Known { value },
+ self.inner.borrow_mut().const_unification_table().union_value(
+ target_vid,
+ ConstVarValue {
+ origin: ConstVariableOrigin {
+ kind: ConstVariableOriginKind::ConstInference,
+ span: DUMMY_SP,
},
- )
- .map(|()| value)
- .map_err(|e| const_unification_error(vid_is_expected, e))
+ val: ConstVariableValue::Known { value },
+ },
+ );
+ Ok(value)
}
fn unify_integral_variable(
@@ -460,7 +452,7 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
}
struct Generalizer<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
/// The span, used when creating new type variables and things.
cause: &'cx ObligationCause<'tcx>,
@@ -742,9 +734,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
}
}
}
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
- assert_eq!(promoted, ());
-
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@@ -753,7 +743,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
)?;
Ok(self.tcx().mk_const(ty::ConstS {
ty: c.ty(),
- kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+ kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
}))
}
_ => relate::super_relate_consts(self, c, c),
@@ -768,13 +758,6 @@ pub trait ConstEquateRelation<'tcx>: TypeRelation<'tcx> {
fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
}
-pub fn const_unification_error<'tcx>(
- a_is_expected: bool,
- (a, b): (ty::Const<'tcx>, ty::Const<'tcx>),
-) -> TypeError<'tcx> {
- TypeError::ConstMismatch(ExpectedFound::new(a_is_expected, a, b))
-}
-
fn int_unification_error<'tcx>(
a_is_expected: bool,
v: (ty::IntVarValue, ty::IntVarValue),
@@ -792,7 +775,7 @@ fn float_unification_error<'tcx>(
}
struct ConstInferUnifier<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
span: Span,
@@ -964,9 +947,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
}
}
}
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
- assert_eq!(promoted, ());
-
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@@ -976,7 +957,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
Ok(self.tcx().mk_const(ty::ConstS {
ty: c.ty(),
- kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
+ kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
}))
}
_ => relate::super_relate_consts(self, c, c),
diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs
index 3b1798ca7..59728148a 100644
--- a/compiler/rustc_infer/src/infer/equate.rs
+++ b/compiler/rustc_infer/src/infer/equate.rs
@@ -110,6 +110,25 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> {
.obligations,
);
}
+ // Optimization of GeneratorWitness relation since we know that all
+ // free regions are replaced with bound regions during construction.
+ // This greatly speeds up equating of GeneratorWitness.
+ (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
+ 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(
+ a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
+ );
+ for (a, b) in std::iter::zip(a_types, b_types) {
+ self.relate(a, b)?;
+ }
+ } else {
+ return Err(ty::error::TypeError::Sorts(ty::relate::expected_found(
+ self, a, b,
+ )));
+ }
+ }
_ => {
self.fields.infcx.super_combine_tys(self, a, b)?;
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index eb5afe828..9ff703e52 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -51,6 +51,7 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa
use crate::infer;
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
+use crate::infer::ExpectedFound;
use crate::traits::error_reporting::report_object_safety_error;
use crate::traits::{
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
@@ -69,12 +70,12 @@ use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
use rustc_middle::ty::{
- self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
- TypeSuperVisitable, TypeVisitable,
+ self, error::TypeError, Binder, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+ TypeVisitable,
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
-use std::ops::ControlFlow;
+use std::ops::{ControlFlow, Deref};
use std::{cmp, fmt, iter};
mod note;
@@ -84,6 +85,31 @@ pub use need_type_info::TypeAnnotationNeeded;
pub mod nice_region_error;
+/// A helper for building type related errors. The `typeck_results`
+/// field is only populated during an in-progress typeck.
+/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`.
+pub struct TypeErrCtxt<'a, 'tcx> {
+ pub infcx: &'a InferCtxt<'tcx>,
+ pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
+}
+
+impl TypeErrCtxt<'_, '_> {
+ /// This is just to avoid a potential footgun of accidentally
+ /// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
+ #[deprecated(note = "you already have a `TypeErrCtxt`")]
+ #[allow(unused)]
+ pub fn err_ctxt(&self) -> ! {
+ bug!("called `err_ctxt` on `TypeErrCtxt`. Try removing the call");
+ }
+}
+
+impl<'tcx> Deref for TypeErrCtxt<'_, 'tcx> {
+ type Target = InferCtxt<'tcx>;
+ fn deref(&self) -> &InferCtxt<'tcx> {
+ &self.infcx
+ }
+}
+
pub(super) fn note_and_explain_region<'tcx>(
tcx: TyCtxt<'tcx>,
err: &mut Diagnostic,
@@ -303,7 +329,38 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>(
err
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
+ pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
+ if let ty::Opaque(def_id, substs) = ty.kind() {
+ let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
+ // Future::Output
+ let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
+
+ let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
+
+ for (predicate, _) in bounds.subst_iter_copied(self.tcx, substs) {
+ let output = predicate
+ .kind()
+ .map_bound(|kind| match kind {
+ ty::PredicateKind::Projection(projection_predicate)
+ if projection_predicate.projection_ty.item_def_id == item_def_id =>
+ {
+ projection_predicate.term.ty()
+ }
+ _ => None,
+ })
+ .transpose();
+ if output.is_some() {
+ // We don't account for multiple `Future::Output = Ty` constraints.
+ return output;
+ }
+ }
+ }
+ None
+ }
+}
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub fn report_region_errors(
&self,
generic_param_scope: LocalDefId,
@@ -577,13 +634,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
{
// don't show type `_`
if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
- && let ty::Adt(def, substs) = ty.kind()
- && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
+ && let ty::Adt(def, substs) = ty.kind()
+ && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
{
err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
} else {
- err.span_label(span, format!("this expression has type `{}`", ty));
- }
+ err.span_label(span, format!("this expression has type `{}`", ty));
+ }
}
if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
&& ty.is_box() && ty.boxed_ty() == found
@@ -619,8 +676,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
let arg_expr = args.first().expect("try desugaring call w/out arg");
- self.in_progress_typeck_results.and_then(|typeck_results| {
- typeck_results.borrow().expr_ty_opt(arg_expr)
+ self.typeck_results.as_ref().and_then(|typeck_results| {
+ typeck_results.expr_ty_opt(arg_expr)
})
} else {
bug!("try desugaring w/out call expr as scrutinee");
@@ -726,10 +783,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => {
if let ObligationCauseCode::BindingObligation(_, span)
| ObligationCauseCode::ExprBindingObligation(_, span, ..)
- = cause.code().peel_derives()
+ = cause.code().peel_derives()
&& let TypeError::RegionsPlaceholderMismatch = terr
{
- err.span_note(*span, "the lifetime requirement is introduced here");
+ err.span_note( * span,
+ "the lifetime requirement is introduced here");
}
}
}
@@ -1653,8 +1711,114 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
),
Mismatch::Fixed(s) => (s.into(), s.into(), None),
};
- match (&terr, expected == found) {
- (TypeError::Sorts(values), extra) => {
+
+ enum Similar<'tcx> {
+ Adts { expected: ty::AdtDef<'tcx>, found: ty::AdtDef<'tcx> },
+ PrimitiveFound { expected: ty::AdtDef<'tcx>, found: Ty<'tcx> },
+ PrimitiveExpected { expected: Ty<'tcx>, found: ty::AdtDef<'tcx> },
+ }
+
+ let similarity = |ExpectedFound { expected, found }: ExpectedFound<Ty<'tcx>>| {
+ if let ty::Adt(expected, _) = expected.kind() && let Some(primitive) = found.primitive_symbol() {
+ let path = self.tcx.def_path(expected.did()).data;
+ let name = path.last().unwrap().data.get_opt_name();
+ if name == Some(primitive) {
+ return Some(Similar::PrimitiveFound { expected: *expected, found });
+ }
+ } else if let Some(primitive) = expected.primitive_symbol() && let ty::Adt(found, _) = found.kind() {
+ let path = self.tcx.def_path(found.did()).data;
+ let name = path.last().unwrap().data.get_opt_name();
+ if name == Some(primitive) {
+ return Some(Similar::PrimitiveExpected { expected, found: *found });
+ }
+ } else if let ty::Adt(expected, _) = expected.kind() && let ty::Adt(found, _) = found.kind() {
+ if !expected.did().is_local() && expected.did().krate == found.did().krate {
+ // Most likely types from different versions of the same crate
+ // are in play, in which case this message isn't so helpful.
+ // A "perhaps two different versions..." error is already emitted for that.
+ return None;
+ }
+ let f_path = self.tcx.def_path(found.did()).data;
+ let e_path = self.tcx.def_path(expected.did()).data;
+
+ if let (Some(e_last), Some(f_last)) = (e_path.last(), f_path.last()) && e_last == f_last {
+ return Some(Similar::Adts{expected: *expected, found: *found});
+ }
+ }
+ None
+ };
+
+ match terr {
+ // If two types mismatch but have similar names, mention that specifically.
+ TypeError::Sorts(values) if let Some(s) = similarity(values) => {
+ let diagnose_primitive =
+ |prim: Ty<'tcx>,
+ shadow: Ty<'tcx>,
+ defid: DefId,
+ diagnostic: &mut Diagnostic| {
+ let name = shadow.sort_string(self.tcx);
+ diagnostic.note(format!(
+ "{prim} and {name} have similar names, but are actually distinct types"
+ ));
+ diagnostic
+ .note(format!("{prim} is a primitive defined by the language"));
+ let def_span = self.tcx.def_span(defid);
+ let msg = if defid.is_local() {
+ 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}")
+ };
+ diagnostic.span_note(def_span, msg);
+ };
+
+ let diagnose_adts =
+ |expected_adt : ty::AdtDef<'tcx>,
+ found_adt: ty::AdtDef<'tcx>,
+ diagnostic: &mut Diagnostic| {
+ let found_name = values.found.sort_string(self.tcx);
+ let expected_name = values.expected.sort_string(self.tcx);
+
+ let found_defid = found_adt.did();
+ let expected_defid = expected_adt.did();
+
+ diagnostic.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
+ for (defid, name) in
+ [(found_defid, found_name), (expected_defid, expected_name)]
+ {
+ let def_span = self.tcx.def_span(defid);
+
+ let msg = if found_defid.is_local() && expected_defid.is_local() {
+ let module = self
+ .tcx
+ .parent_module_from_def_id(defid.expect_local())
+ .to_def_id();
+ let module_name = self.tcx.def_path(module).to_string_no_crate_verbose();
+ format!("{name} is defined in module `crate{module_name}` of the current crate")
+ } else if defid.is_local() {
+ 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}`")
+ };
+ diagnostic.span_note(def_span, msg);
+ }
+ };
+
+ match s {
+ Similar::Adts{expected, found} => {
+ diagnose_adts(expected, found, diag)
+ }
+ Similar::PrimitiveFound{expected, found: prim} => {
+ diagnose_primitive(prim, values.expected, expected.did(), diag)
+ }
+ Similar::PrimitiveExpected{expected: prim, found} => {
+ diagnose_primitive(prim, values.found, found.did(), diag)
+ }
+ }
+ }
+ TypeError::Sorts(values) => {
+ let extra = expected == found;
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
(true, ty::Opaque(def_id, _)) => {
let sm = self.tcx.sess.source_map();
@@ -1707,10 +1871,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
);
}
}
- (TypeError::ObjectUnsafeCoercion(_), _) => {
+ TypeError::ObjectUnsafeCoercion(_) => {
diag.note_unsuccessful_coercion(found, expected);
}
- (_, _) => {
+ _ => {
debug!(
"note_type_err: exp_found={:?}, expected={:?} found={:?}",
exp_found, expected, found
@@ -1755,7 +1919,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// 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
- // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
+ // rustc_hir_analysis/check/compare_method.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(|| {
@@ -1847,36 +2011,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
- pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Binder<'tcx, Ty<'tcx>>> {
- if let ty::Opaque(def_id, substs) = ty.kind() {
- let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
- // Future::Output
- let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
-
- let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
-
- for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
- let predicate = predicate.subst(self.tcx, substs);
- let output = predicate
- .kind()
- .map_bound(|kind| match kind {
- ty::PredicateKind::Projection(projection_predicate)
- if projection_predicate.projection_ty.item_def_id == item_def_id =>
- {
- projection_predicate.term.ty()
- }
- _ => None,
- })
- .transpose();
- if output.is_some() {
- // We don't account for multiple `Future::Output = Ty` constraints.
- return output;
- }
- }
- }
- None
- }
-
/// A possible error is to forget to add `.await` when using futures:
///
/// ```compile_fail,E0308
@@ -2051,8 +2185,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
diag: &mut Diagnostic,
) {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
+ {
+ diag.span_suggestion(
+ span,
+ msg,
+ // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+ format!("{}.as_ref()", snippet.trim_start_matches('&')),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ 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, _)) =
- (exp_found.expected.kind(), exp_found.found.kind())
+ (expected.kind(), found.kind())
{
if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
if exp_def == &found_def {
@@ -2090,21 +2238,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
_ => show_suggestion = false,
}
}
- if let (Ok(snippet), true) =
- (self.tcx.sess.source_map().span_to_snippet(span), show_suggestion)
- {
- diag.span_suggestion(
- span,
- *msg,
- // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
- format!("{}.as_ref()", snippet.trim_start_matches('&')),
- Applicability::MachineApplicable,
- );
+ if show_suggestion {
+ return Some(*msg);
}
}
}
}
}
+ None
}
pub fn report_and_explain_type_error(
@@ -2130,6 +2271,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
}
FailureCode::Error0308(failure_str) => {
+ fn escape_literal(s: &str) -> String {
+ let mut escaped = String::with_capacity(s.len());
+ let mut chrs = s.chars().peekable();
+ while let Some(first) = chrs.next() {
+ match (first, chrs.peek()) {
+ ('\\', Some(&delim @ '"') | Some(&delim @ '\'')) => {
+ escaped.push('\\');
+ escaped.push(delim);
+ chrs.next();
+ }
+ ('"' | '\'', _) => {
+ escaped.push('\\');
+ escaped.push(first)
+ }
+ (c, _) => escaped.push(c),
+ };
+ }
+ escaped
+ }
let mut err = struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str);
if let Some((expected, found)) = trace.values.ty() {
match (expected.kind(), found.kind()) {
@@ -2151,7 +2311,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `char` literal, use single quotes",
- format!("'{}'", code),
+ format!("'{}'", escape_literal(code)),
Applicability::MachineApplicable,
);
}
@@ -2166,7 +2326,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.span_suggestion(
span,
"if you meant to write a `str` literal, use double quotes",
- format!("\"{}\"", code),
+ format!("\"{}\"", escape_literal(code)),
Applicability::MachineApplicable,
);
}
@@ -2317,7 +2477,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: Option<SubregionOrigin<'tcx>>,
bound_kind: GenericKind<'tcx>,
sub: Region<'tcx>,
- ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
// Attempt to obtain the span of the parameter so we can
// suggest adding an explicit lifetime bound to it.
let generics = self.tcx.generics_of(generic_param_scope);
@@ -2333,7 +2493,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// We do this to avoid suggesting code that ends up as `T: 'a'b`,
// instead we suggest `T: 'a + 'b` in that case.
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- let ast_generics = self.tcx.hir().get_generics(hir_id.owner);
+ let ast_generics = self.tcx.hir().get_generics(hir_id.owner.def_id);
let bounds =
ast_generics.and_then(|g| g.bounds_span_for_suggestions(def_id));
// `sp` only covers `T`, change it so that it covers
@@ -2374,6 +2534,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let labeled_user_string = match bound_kind {
GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
+ GenericKind::Opaque(def_id, substs) => {
+ format!("the opaque type `{}`", self.tcx.def_path_str_with_substs(def_id, substs))
+ }
};
if let Some(SubregionOrigin::CompareImplItemObligation {
@@ -2453,7 +2616,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
for h in self.tcx.hir().parent_iter(param.hir_id) {
break 'origin match h.1 {
Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::TyAlias(..),
+ kind: hir::ImplItemKind::Type(..),
generics,
..
})
@@ -2692,7 +2855,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
-struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'a, 'tcx>);
+struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'tcx>);
impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
@@ -2779,7 +2942,7 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
}
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
fn report_inference_failure(
&self,
var_origin: RegionVariableOrigin,
@@ -2967,7 +3130,7 @@ impl TyCategory {
}
}
-impl<'tcx> InferCtxt<'_, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Given a [`hir::Block`], get the span of its last expression or
/// statement, peeling off any inner blocks.
pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
@@ -2994,7 +3157,9 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
_ => rustc_span::DUMMY_SP,
}
}
+}
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
/// Be helpful when the user wrote `{... expr; }` and taking the `;` off
/// is enough to fix the error.
pub fn could_remove_semicolon(
@@ -3011,7 +3176,7 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
return None;
};
- let last_expr_ty = self.in_progress_typeck_results?.borrow().expr_ty_opt(*last_expr)?;
+ let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
_ if last_expr_ty.references_error() => return None,
_ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
@@ -3094,8 +3259,9 @@ impl<'tcx> InferCtxt<'_, 'tcx> {
let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
&& let Some(pat_ty) = self
- .in_progress_typeck_results
- .and_then(|typeck_results| typeck_results.borrow().node_type_opt(*hir_id))
+ .typeck_results
+ .as_ref()
+ .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
{
let pat_ty = self.resolve_vars_if_possible(pat_ty);
if self.same_type_modulo_infer(pat_ty, expected_ty)
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 cb2be9358..7b3178e61 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
@@ -2,8 +2,10 @@ use crate::errors::{
AmbigousImpl, AmbigousReturn, AnnotationRequired, InferenceBadError, NeedTypeInfoInGenerator,
SourceKindMultiSuggestion, SourceKindSubdiag,
};
+use crate::infer::error_reporting::TypeErrCtxt;
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::InferCtxt;
+use rustc_errors::IntoDiagnostic;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg};
use rustc_hir as hir;
use rustc_hir::def::Res;
@@ -15,10 +17,9 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use rustc_middle::ty::{self, DefIdTree, InferConst};
+use rustc_middle::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeckResults};
-use rustc_session::SessionDiagnostic;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{BytePos, Span};
use std::borrow::Cow;
@@ -151,7 +152,7 @@ impl UnderspecifiedArgKind {
}
}
-fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'_, 'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
+fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
let mut printer = FmtPrinter::new(infcx.tcx, ns);
let ty_getter = move |ty_vid| {
if infcx.probe_ty_var(ty_vid).is_ok() {
@@ -182,7 +183,7 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'_, 'tcx>, ns: Namespace) -> FmtPr
printer
}
-fn ty_to_string<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String {
+fn ty_to_string<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
let printer = fmt_printer(infcx, Namespace::TypeNS);
let ty = infcx.resolve_vars_if_possible(ty);
match ty.kind() {
@@ -201,7 +202,7 @@ fn ty_to_string<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String {
/// We don't want to directly use `ty_to_string` for closures as their type isn't really
/// something users are familiar with. Directly printing the `fn_sig` of closures also
/// doesn't work as they actually use the "rust-call" API.
-fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String {
+fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
let ty::Closure(_, substs) = ty.kind() else { unreachable!() };
let fn_sig = substs.as_closure().sig();
let args = fn_sig
@@ -225,7 +226,7 @@ fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> String
format!("fn({}){}", args, ret)
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Extracts data used by diagnostic for either types or constants
/// which were stuck during inference.
pub fn extract_inference_diagnostics_data(
@@ -317,7 +318,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
- /// Used as a fallback in [InferCtxt::emit_inference_failure_err]
+ /// Used as a fallback in [TypeErrCtxt::emit_inference_failure_err]
/// in case we weren't able to get a better error.
fn bad_inference_failure_err(
&self,
@@ -364,7 +365,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
}
}
+}
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub fn emit_inference_failure_err(
&self,
body_id: Option<hir::BodyId>,
@@ -376,14 +379,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let arg = self.resolve_vars_if_possible(arg);
let arg_data = self.extract_inference_diagnostics_data(arg, None);
- let Some(typeck_results) = self.in_progress_typeck_results else {
+ let Some(typeck_results) = &self.typeck_results else {
// If we don't have any typeck results we're outside
// of a body, so we won't be able to get better info
// here.
return self.bad_inference_failure_err(failure_span, arg_data, error_code);
};
- let typeck_results = typeck_results.borrow();
- let typeck_results = &typeck_results;
let mut local_visitor = FindInferSourceVisitor::new(&self, typeck_results, arg);
if let Some(body_id) = body_id {
@@ -435,6 +436,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
generics_def_id,
def_id: _,
generic_args,
+ have_turbofish,
} => {
let generics = self.tcx.generics_of(generics_def_id);
let is_type = matches!(arg.unpack(), GenericArgKind::Type(_));
@@ -482,11 +484,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.unwrap()
.into_buffer();
- infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
- span: insert_span,
- arg_count: generic_args.len(),
- args,
- });
+ if !have_turbofish {
+ infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
+ span: insert_span,
+ arg_count: generic_args.len(),
+ args,
+ });
+ }
}
InferSourceKind::FullyQualifiedMethodCall { receiver, successor, substs, def_id } => {
let printer = fmt_printer(self, Namespace::ValueNS);
@@ -560,7 +564,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.into_diagnostic(&self.tcx.sess.parse_sess.span_diagnostic),
}
}
+}
+impl<'tcx> InferCtxt<'tcx> {
pub fn need_type_info_err_in_generator(
&self,
kind: hir::GeneratorKind,
@@ -616,6 +622,7 @@ enum InferSourceKind<'tcx> {
generics_def_id: DefId,
def_id: DefId,
generic_args: &'tcx [GenericArg<'tcx>],
+ have_turbofish: bool,
},
FullyQualifiedMethodCall {
receiver: &'tcx Expr<'tcx>,
@@ -650,7 +657,7 @@ impl<'tcx> InferSource<'tcx> {
}
impl<'tcx> InferSourceKind<'tcx> {
- fn ty_localized_msg(&self, infcx: &InferCtxt<'_, 'tcx>) -> (&'static str, String) {
+ fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String) {
match *self {
InferSourceKind::LetBinding { ty, .. }
| InferSourceKind::ClosureArg { ty, .. }
@@ -676,6 +683,7 @@ struct InsertableGenericArgs<'tcx> {
substs: SubstsRef<'tcx>,
generics_def_id: DefId,
def_id: DefId,
+ have_turbofish: bool,
}
/// A visitor which searches for the "best" spot to use in the inference error.
@@ -686,7 +694,7 @@ struct InsertableGenericArgs<'tcx> {
/// While doing so, the currently best spot is stored in `infer_source`.
/// For details on how we rank spots, see [Self::source_cost]
struct FindInferSourceVisitor<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
typeck_results: &'a TypeckResults<'tcx>,
target: GenericArg<'tcx>,
@@ -698,7 +706,7 @@ struct FindInferSourceVisitor<'a, 'tcx> {
impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
typeck_results: &'a TypeckResults<'tcx>,
target: GenericArg<'tcx>,
) -> Self {
@@ -894,11 +902,18 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
// impl is currently the `DefId` of `Output` in the trait definition
// which makes this somewhat difficult and prevents us from just
// using `self.path_inferred_subst_iter` here.
- hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _) => {
- if let Some(ty) = self.opt_node_type(expr.hir_id) {
- if let ty::Adt(_, substs) = ty.kind() {
- return Box::new(self.resolved_path_inferred_subst_iter(path, substs));
- }
+ hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
+ // FIXME(TaKO8Ki): Ideally we should support this. For that
+ // we have to map back from the self type to the
+ // type alias though. That's difficult.
+ //
+ // See the `need_type_info/issue-103053.rs` test for
+ // a example.
+ if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => {
+ if let Some(ty) = self.opt_node_type(expr.hir_id)
+ && let ty::Adt(_, substs) = ty.kind()
+ {
+ return Box::new(self.resolved_path_inferred_subst_iter(path, substs));
}
}
hir::ExprKind::MethodCall(segment, ..) => {
@@ -916,6 +931,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
substs,
generics_def_id: def_id,
def_id,
+ have_turbofish: false,
}
};
return Box::new(insertable.into_iter());
@@ -933,6 +949,9 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
substs: SubstsRef<'tcx>,
) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'a {
let tcx = self.infcx.tcx;
+ let have_turbofish = path.segments.iter().any(|segment| {
+ segment.args.map_or(false, |args| args.args.iter().any(|arg| arg.is_ty_or_const()))
+ });
// The last segment of a path often has `Res::Err` and the
// correct `Res` is the one of the whole path.
//
@@ -942,7 +961,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
let generics_def_id = tcx.res_generics_def_id(path.res)?;
let generics = tcx.generics_of(generics_def_id);
if generics.has_impl_trait() {
- None?
+ None?;
}
let insert_span =
path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
@@ -951,6 +970,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
substs,
generics_def_id,
def_id: path.res.def_id(),
+ have_turbofish,
}
};
@@ -970,6 +990,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
substs,
generics_def_id,
def_id: res.def_id(),
+ have_turbofish,
})
})
.chain(last_segment_using_path_data)
@@ -998,7 +1019,13 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
}
let span = tcx.hir().span(segment.hir_id);
let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
- InsertableGenericArgs { insert_span, substs, generics_def_id: def_id, def_id }
+ InsertableGenericArgs {
+ insert_span,
+ substs,
+ generics_def_id: def_id,
+ def_id,
+ have_turbofish: false,
+ }
};
let parent_def_id = generics.parent.unwrap();
@@ -1021,7 +1048,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
}
// There cannot be inference variables in the self type,
// so there's nothing for us to do here.
- Res::SelfTy { .. } => {}
+ Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
_ => warn!(
"unexpected path: def={:?} substs={:?} path={:?}",
def, substs, path,
@@ -1121,7 +1148,13 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
for args in self.expr_inferred_subst_iter(expr) {
debug!(?args);
- let InsertableGenericArgs { insert_span, substs, generics_def_id, def_id } = args;
+ let InsertableGenericArgs {
+ insert_span,
+ substs,
+ generics_def_id,
+ def_id,
+ have_turbofish,
+ } = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(argument_index) = generics
.own_substs(substs)
@@ -1144,6 +1177,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
generics_def_id,
def_id,
generic_args,
+ have_turbofish,
},
});
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index 3a4320a9a..da0271a34 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -11,7 +11,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::SubregionOrigin;
use crate::infer::TyCtxt;
-use rustc_errors::AddSubdiagnostic;
+use rustc_errors::AddToDiagnostic;
use rustc_errors::{Diagnostic, ErrorGuaranteed};
use rustc_hir::Ty;
use rustc_middle::ty::Region;
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 1410e2b63..c5f2a1a3f 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
@@ -2,7 +2,9 @@
//! to hold.
use crate::errors::{note_and_explain, IntroducesStaticBecauseUnmetLifetimeReq};
-use crate::errors::{ImplNote, MismatchedStaticLifetime, TraitSubdiag};
+use crate::errors::{
+ DoesNotOutliveStaticFromImpl, ImplicitStaticLifetimeSubdiag, MismatchedStaticLifetime,
+};
use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::{SubregionOrigin, TypeTrace};
@@ -56,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
note_and_explain::SuffixKind::Continues,
);
let mut impl_span = None;
- let mut trait_subdiags = Vec::new();
+ let mut implicit_static_lifetimes = Vec::new();
if let Some(impl_node) = self.tcx().hir().get_if_local(*impl_def_id) {
// If an impl is local, then maybe this isn't what they want. Try to
// be as helpful as possible with implicit lifetimes.
@@ -90,10 +92,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
// Otherwise, point at all implicit static lifetimes
for span in &traits {
- trait_subdiags.push(TraitSubdiag::Note { span: *span });
+ implicit_static_lifetimes
+ .push(ImplicitStaticLifetimeSubdiag::Note { span: *span });
// It would be nice to put this immediately under the above note, but they get
// pushed to the end.
- trait_subdiags.push(TraitSubdiag::Sugg { span: span.shrink_to_hi() });
+ implicit_static_lifetimes
+ .push(ImplicitStaticLifetimeSubdiag::Sugg { span: span.shrink_to_hi() });
}
}
} else {
@@ -105,8 +109,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
cause_span: cause.span,
unmet_lifetime_reqs: multispan_subdiag,
expl,
- impl_note: ImplNote { impl_span },
- trait_subdiags,
+ does_not_outlive_static_from_impl: impl_span
+ .map(|span| DoesNotOutliveStaticFromImpl::Spanned { span })
+ .unwrap_or(DoesNotOutliveStaticFromImpl::Unspanned),
+ implicit_static_lifetimes,
};
let reported = self.tcx().sess.emit_err(err);
Some(reported)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
index 53d9acf7d..aaf5a7af0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs
@@ -1,6 +1,6 @@
+use crate::infer::error_reporting::TypeErrCtxt;
use crate::infer::lexical_region_resolve::RegionResolutionError;
use crate::infer::lexical_region_resolve::RegionResolutionError::*;
-use crate::infer::InferCtxt;
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::source_map::Span;
@@ -19,34 +19,34 @@ pub use find_anon_type::find_anon_type;
pub use static_impl_trait::{suggest_new_region_bound, HirTraitObjectVisitor, TraitObjectVisitor};
pub use util::find_param_with_region;
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
- pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool {
+impl<'cx, 'tcx> TypeErrCtxt<'cx, 'tcx> {
+ pub fn try_report_nice_region_error(&'cx self, error: &RegionResolutionError<'tcx>) -> bool {
NiceRegionError::new(self, error.clone()).try_report().is_some()
}
}
pub struct NiceRegionError<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ cx: &'cx TypeErrCtxt<'cx, 'tcx>,
error: Option<RegionResolutionError<'tcx>>,
regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>,
}
impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
- Self { infcx, error: Some(error), regions: None }
+ pub fn new(cx: &'cx TypeErrCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self {
+ Self { cx, error: Some(error), regions: None }
}
pub fn new_from_span(
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ cx: &'cx TypeErrCtxt<'cx, 'tcx>,
span: Span,
sub: ty::Region<'tcx>,
sup: ty::Region<'tcx>,
) -> Self {
- Self { infcx, error: None, regions: Some((span, sub, sup)) }
+ Self { cx, error: None, regions: Some((span, sub, sup)) }
}
fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
+ self.cx.tcx
}
pub fn try_report_from_nll(&self) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
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 d4db07512..a58516829 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
@@ -226,12 +226,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
false
};
- let expected_trait_ref = self.infcx.resolve_vars_if_possible(ty::TraitRef {
+ let expected_trait_ref = self.cx.resolve_vars_if_possible(ty::TraitRef {
def_id: trait_def_id,
substs: expected_substs,
});
let actual_trait_ref = self
- .infcx
+ .cx
.resolve_vars_if_possible(ty::TraitRef { def_id: trait_def_id, substs: actual_substs });
// Search the expected and actual trait references to see (a)
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 ae56bea6f..9bf755d7f 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
@@ -185,8 +185,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
| ObligationCauseCode::BlockTailExpression(hir_id) = cause.code()
{
let parent_id = tcx.hir().get_parent_item(*hir_id);
- let parent_id = tcx.hir().local_def_id_to_hir_id(parent_id);
- if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id) {
+ if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) {
let mut span: MultiSpan = fn_decl.output.span().into();
let mut add_label = true;
if let hir::FnRetTy::Return(ty) = fn_decl.output {
@@ -287,8 +286,8 @@ pub fn suggest_new_region_bound(
) {
debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns);
// FIXME: account for the need of parens in `&(dyn Trait + '_)`
- let consider = "consider changing the";
- let declare = "to declare that the";
+ let consider = "consider changing";
+ let declare = "to declare that";
let explicit = format!("you can add an explicit `{}` lifetime bound", lifetime_name);
let explicit_static =
arg.map(|arg| format!("explicit `'static` bound to the lifetime of {}", arg));
@@ -306,6 +305,10 @@ pub fn suggest_new_region_bound(
return;
};
+ // Get the identity type for this RPIT
+ let did = item_id.owner_id.to_def_id();
+ let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did));
+
if let Some(span) = opaque
.bounds
.iter()
@@ -322,7 +325,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
span,
- &format!("{} `impl Trait`'s {}", consider, explicit_static),
+ &format!("{consider} `{ty}`'s {explicit_static}"),
&lifetime_name,
Applicability::MaybeIncorrect,
);
@@ -352,12 +355,7 @@ pub fn suggest_new_region_bound(
} else {
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
- &format!(
- "{declare} `impl Trait` {captures}, {explicit}",
- declare = declare,
- captures = captures,
- explicit = explicit,
- ),
+ &format!("{declare} `{ty}` {captures}, {explicit}",),
&plus_lt,
Applicability::MaybeIncorrect,
);
@@ -368,7 +366,7 @@ pub fn suggest_new_region_bound(
err.span_suggestion_verbose(
fn_return.span.shrink_to_hi(),
&format!(
- "{declare} trait object {captures}, {explicit}",
+ "{declare} the trait object {captures}, {explicit}",
declare = declare,
captures = captures,
explicit = explicit,
@@ -385,7 +383,7 @@ pub fn suggest_new_region_bound(
if let Some(explicit_static) = &explicit_static {
err.span_suggestion_verbose(
lt.span,
- &format!("{} trait object's {}", consider, explicit_static),
+ &format!("{} the trait object's {}", consider, explicit_static),
&lifetime_name,
Applicability::MaybeIncorrect,
);
@@ -415,7 +413,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let tcx = self.tcx();
match tcx.hir().get_if_local(def_id) {
Some(Node::ImplItem(impl_item)) => {
- match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id())) {
+ match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id)
+ {
Some(Node::Item(Item {
kind: ItemKind::Impl(hir::Impl { self_ty, .. }),
..
@@ -425,7 +424,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
}
Some(Node::TraitItem(trait_item)) => {
let trait_did = tcx.hir().get_parent_item(trait_item.hir_id());
- match tcx.hir().find_by_def_id(trait_did) {
+ match tcx.hir().find_by_def_id(trait_did.def_id) {
Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => {
// The method being called is defined in the `trait`, but the `'static`
// obligation comes from the `impl`. Find that `impl` so that we can point
@@ -486,7 +485,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
tcx,
ctxt.param_env,
ctxt.assoc_item.def_id,
- self.infcx.resolve_vars_if_possible(ctxt.substs),
+ self.cx.resolve_vars_if_possible(ctxt.substs),
) else {
return false;
};
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 a6a39d062..5d536e982 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
@@ -84,12 +84,12 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let expected_highlight = HighlightBuilder::build(self.tcx(), expected);
let expected = self
- .infcx
+ .cx
.extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
.name;
let found_highlight = HighlightBuilder::build(self.tcx(), found);
let found =
- self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
+ self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
err.span_label(sp, &format!("found `{}`", found));
err.span_label(trait_sp, &format!("expected `{}`", expected));
@@ -156,7 +156,8 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
[segment]
if matches!(
segment.res,
- Res::SelfTy { trait_: _, alias_to: _ }
+ Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::Def(hir::def::DefKind::TyParam, _)
) =>
{
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 3e9d491af..f1461d701 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
@@ -130,7 +130,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let ret_ty = fn_ty.fn_sig(self.tcx()).output();
let span = hir_sig.decl.output.span();
let future_output = if hir_sig.header.is_async() {
- ret_ty.map_bound(|ty| self.infcx.get_impl_future_output_ty(ty)).transpose()
+ ret_ty.map_bound(|ty| self.cx.get_impl_future_output_ty(ty)).transpose()
} else {
None
};
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index adaa47c01..41b115f33 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -1,8 +1,8 @@
use crate::errors::RegionOriginNote;
-use crate::infer::error_reporting::note_and_explain_region;
-use crate::infer::{self, InferCtxt, SubregionOrigin};
+use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
+use crate::infer::{self, SubregionOrigin};
use rustc_errors::{
- fluent, struct_span_err, AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+ fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
};
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::error::TypeError;
@@ -10,7 +10,7 @@ use rustc_middle::ty::{self, Region};
use super::ObligationCauseAsDiagArg;
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
match *origin {
infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
@@ -19,26 +19,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
expected_found: self.values_str(trace.values),
}
.add_to_diagnostic(err),
- infer::Reborrow(span) => RegionOriginNote::Plain { span, msg: fluent::infer::reborrow }
- .add_to_diagnostic(err),
+ infer::Reborrow(span) => {
+ RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+ }
infer::ReborrowUpvar(span, ref upvar_id) => {
let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
RegionOriginNote::WithName {
span,
- msg: fluent::infer::reborrow,
+ msg: fluent::infer_reborrow,
name: &var_name.to_string(),
continues: false,
}
.add_to_diagnostic(err);
}
infer::RelateObjectBound(span) => {
- RegionOriginNote::Plain { span, msg: fluent::infer::relate_object_bound }
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
.add_to_diagnostic(err);
}
infer::DataBorrowed(ty, span) => {
RegionOriginNote::WithName {
span,
- msg: fluent::infer::data_borrowed,
+ msg: fluent::infer_data_borrowed,
name: &self.ty_to_string(ty),
continues: false,
}
@@ -47,7 +48,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::ReferenceOutlivesReferent(ty, span) => {
RegionOriginNote::WithName {
span,
- msg: fluent::infer::reference_outlives_referent,
+ msg: fluent::infer_reference_outlives_referent,
name: &self.ty_to_string(ty),
continues: false,
}
@@ -56,22 +57,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::RelateParamBound(span, ty, opt_span) => {
RegionOriginNote::WithName {
span,
- msg: fluent::infer::relate_param_bound,
+ msg: fluent::infer_relate_param_bound,
name: &self.ty_to_string(ty),
continues: opt_span.is_some(),
}
.add_to_diagnostic(err);
if let Some(span) = opt_span {
- RegionOriginNote::Plain { span, msg: fluent::infer::relate_param_bound_2 }
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
.add_to_diagnostic(err);
}
}
infer::RelateRegionParamBound(span) => {
- RegionOriginNote::Plain { span, msg: fluent::infer::relate_region_param_bound }
+ RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
.add_to_diagnostic(err);
}
infer::CompareImplItemObligation { span, .. } => {
- RegionOriginNote::Plain { span, msg: fluent::infer::compare_impl_item_obligation }
+ RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
.add_to_diagnostic(err);
}
infer::CheckAssociatedTypeBounds { ref parent, .. } => {
@@ -80,7 +81,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::AscribeUserTypeProvePredicate(span) => {
RegionOriginNote::Plain {
span,
- msg: fluent::infer::ascribe_user_type_prove_predicate,
+ msg: fluent::infer_ascribe_user_type_prove_predicate,
}
.add_to_diagnostic(err);
}
diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs
index fee15afc7..ff5d1a05a 100644
--- a/compiler/rustc_infer/src/infer/freshen.rs
+++ b/compiler/rustc_infer/src/infer/freshen.rs
@@ -38,7 +38,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVi
use std::collections::hash_map::Entry;
pub struct TypeFreshener<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
ty_freshen_count: u32,
const_freshen_count: u32,
ty_freshen_map: FxHashMap<ty::InferTy, Ty<'tcx>>,
@@ -47,7 +47,7 @@ pub struct TypeFreshener<'a, 'tcx> {
}
impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> {
+ pub fn new(infcx: &'a InferCtxt<'tcx>, keep_static: bool) -> TypeFreshener<'a, 'tcx> {
TypeFreshener {
infcx,
ty_freshen_count: 0,
diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs
index 2f0eadce6..6dd6c4e1f 100644
--- a/compiler/rustc_infer/src/infer/fudge.rs
+++ b/compiler/rustc_infer/src/infer/fudge.rs
@@ -43,7 +43,7 @@ struct VariableLengths {
region_constraints_len: usize,
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
fn variable_lengths(&self) -> VariableLengths {
let mut inner = self.inner.borrow_mut();
VariableLengths {
@@ -167,7 +167,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
pub struct InferenceFudger<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>),
int_vars: Range<IntVid>,
float_vars: Range<FloatVid>,
diff --git a/compiler/rustc_infer/src/infer/glb.rs b/compiler/rustc_infer/src/infer/glb.rs
index 1570a08f3..6ffefcb7a 100644
--- a/compiler/rustc_infer/src/infer/glb.rs
+++ b/compiler/rustc_infer/src/infer/glb.rs
@@ -113,7 +113,7 @@ impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
}
impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
- fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> {
+ fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
self.fields.infcx
}
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index 0ce271c0e..28c87a115 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -59,7 +59,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
}
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Replaces all bound variables (lifetimes, types, and constants) bound by
/// `binder` with placeholder variables in a new universe. This means that the
/// new placeholders can only be named by inference variables created after
@@ -114,7 +114,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn leak_check(
&self,
overly_polymorphic: bool,
- snapshot: &CombinedSnapshot<'_, 'tcx>,
+ snapshot: &CombinedSnapshot<'tcx>,
) -> RelateResult<'tcx, ()> {
// If the user gave `-Zno-leak-check`, or we have been
// configured to skip the leak check, then skip the leak check
diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs
index 1e3293efa..eba65361a 100644
--- a/compiler/rustc_infer/src/infer/lattice.rs
+++ b/compiler/rustc_infer/src/infer/lattice.rs
@@ -31,7 +31,7 @@ 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> {
- fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
+ fn infcx(&self) -> &'f InferCtxt<'tcx>;
fn cause(&self) -> &ObligationCause<'tcx>;
diff --git a/compiler/rustc_infer/src/infer/lub.rs b/compiler/rustc_infer/src/infer/lub.rs
index 9f96d52c8..d6e56fcb7 100644
--- a/compiler/rustc_infer/src/infer/lub.rs
+++ b/compiler/rustc_infer/src/infer/lub.rs
@@ -119,7 +119,7 @@ impl<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
}
impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
- fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> {
+ fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
self.fields.infcx
}
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 3abed1221..ffb020398 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -35,10 +35,11 @@ use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
-use std::cell::{Cell, Ref, RefCell};
+use std::cell::{Cell, RefCell};
use std::fmt;
use self::combine::CombineFields;
+use self::error_reporting::TypeErrCtxt;
use self::free_regions::RegionRelations;
use self::lexical_region_resolve::LexicalRegionResolutions;
use self::outlives::env::OutlivesEnvironment;
@@ -252,7 +253,7 @@ pub enum DefiningAnchor {
Error,
}
-pub struct InferCtxt<'a, 'tcx> {
+pub struct InferCtxt<'tcx> {
pub tcx: TyCtxt<'tcx>,
/// The `DefId` of the item in whose context we are performing inference or typeck.
@@ -272,12 +273,6 @@ pub struct InferCtxt<'a, 'tcx> {
/// solving is left to borrowck instead.
pub considering_regions: bool,
- /// During type-checking/inference of a body, `in_progress_typeck_results`
- /// contains a reference to the typeck results being built up, which are
- /// used for reading closure kinds/signatures as they are inferred,
- /// and for error reporting logic to read arbitrary node types.
- pub in_progress_typeck_results: Option<&'a RefCell<ty::TypeckResults<'tcx>>>,
-
pub inner: RefCell<InferCtxtInner<'tcx>>,
/// If set, this flag causes us to skip the 'leak check' during
@@ -340,7 +335,7 @@ pub struct InferCtxt<'a, 'tcx> {
universe: Cell<ty::UniverseIndex>,
normalize_fn_sig_for_diagnostic:
- Option<Lrc<dyn Fn(&InferCtxt<'_, 'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
+ Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
}
/// See the `error_reporting` module for more details.
@@ -551,16 +546,13 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
}
}
-/// A temporary returned by `tcx.infer_ctxt()`. This is necessary
-/// for multiple `InferCtxt` to share the same `in_progress_typeck_results`
-/// without using `Rc` or something similar.
+/// Used to configure inference contexts before their creation
pub struct InferCtxtBuilder<'tcx> {
tcx: TyCtxt<'tcx>,
defining_use_anchor: DefiningAnchor,
considering_regions: bool,
- fresh_typeck_results: Option<RefCell<ty::TypeckResults<'tcx>>>,
normalize_fn_sig_for_diagnostic:
- Option<Lrc<dyn Fn(&InferCtxt<'_, 'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
+ Option<Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>>,
}
pub trait TyCtxtInferExt<'tcx> {
@@ -573,26 +565,17 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> {
tcx: self,
defining_use_anchor: DefiningAnchor::Error,
considering_regions: true,
- fresh_typeck_results: None,
normalize_fn_sig_for_diagnostic: None,
}
}
}
impl<'tcx> InferCtxtBuilder<'tcx> {
- /// Used only by `rustc_typeck` during body type-checking/inference,
- /// will initialize `in_progress_typeck_results` with fresh `TypeckResults`.
- /// Will also change the scope for opaque type defining use checks to the given owner.
- pub fn with_fresh_in_progress_typeck_results(mut self, table_owner: LocalDefId) -> Self {
- self.fresh_typeck_results = Some(RefCell::new(ty::TypeckResults::new(table_owner)));
- self.with_opaque_type_inference(DefiningAnchor::Bind(table_owner))
- }
-
/// Whenever the `InferCtxt` should be able to handle defining uses of opaque types,
/// you need to call this function. Otherwise the opaque type will be treated opaquely.
///
/// It is only meant to be called in two places, for typeck
- /// (via `with_fresh_in_progress_typeck_results`) and for the inference context used
+ /// (via `Inherited::build`) and for the inference context used
/// in mir borrowck.
pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
self.defining_use_anchor = defining_use_anchor;
@@ -606,7 +589,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
pub fn with_normalize_fn_sig_for_diagnostic(
mut self,
- fun: Lrc<dyn Fn(&InferCtxt<'_, 'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>,
+ fun: Lrc<dyn Fn(&InferCtxt<'tcx>, ty::PolyFnSig<'tcx>) -> ty::PolyFnSig<'tcx>>,
) -> Self {
self.normalize_fn_sig_for_diagnostic = Some(fun);
self
@@ -619,36 +602,30 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
/// `V` and a substitution `S`. This substitution `S` maps from
/// the bound values in `C` to their instantiated values in `V`
/// (in other words, `S(C) = V`).
- pub fn enter_with_canonical<T, R>(
+ pub fn build_with_canonical<T>(
&mut self,
span: Span,
canonical: &Canonical<'tcx, T>,
- f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>, T, CanonicalVarValues<'tcx>) -> R,
- ) -> R
+ ) -> (InferCtxt<'tcx>, T, CanonicalVarValues<'tcx>)
where
T: TypeFoldable<'tcx>,
{
- self.enter(|infcx| {
- let (value, subst) =
- infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
- f(infcx, value, subst)
- })
+ let infcx = self.build();
+ let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
+ (infcx, value, subst)
}
- pub fn enter<R>(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R {
+ pub fn build(&mut self) -> InferCtxt<'tcx> {
let InferCtxtBuilder {
tcx,
defining_use_anchor,
considering_regions,
- ref fresh_typeck_results,
ref normalize_fn_sig_for_diagnostic,
} = *self;
- let in_progress_typeck_results = fresh_typeck_results.as_ref();
- f(InferCtxt {
+ InferCtxt {
tcx,
defining_use_anchor,
considering_regions,
- in_progress_typeck_results,
inner: RefCell::new(InferCtxtInner::new()),
lexical_region_resolutions: RefCell::new(None),
selection_cache: Default::default(),
@@ -663,7 +640,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
normalize_fn_sig_for_diagnostic: normalize_fn_sig_for_diagnostic
.as_ref()
.map(|f| f.clone()),
- })
+ }
}
}
@@ -675,7 +652,7 @@ impl<'tcx, T> InferOk<'tcx, T> {
/// Extracts `value`, registering any obligations into `fulfill_cx`.
pub fn into_value_registering_obligations(
self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx>,
) -> T {
let InferOk { value, obligations } = self;
@@ -691,29 +668,34 @@ impl<'tcx> InferOk<'tcx, ()> {
}
#[must_use = "once you start a snapshot, you should always consume it"]
-pub struct CombinedSnapshot<'a, 'tcx> {
+pub struct CombinedSnapshot<'tcx> {
undo_snapshot: Snapshot<'tcx>,
region_constraints_snapshot: RegionSnapshot,
universe: ty::UniverseIndex,
was_in_snapshot: bool,
- _in_progress_typeck_results: Option<Ref<'a, ty::TypeckResults<'tcx>>>,
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
+ /// Creates a `TypeErrCtxt` for emitting various inference errors.
+ /// During typeck, use `FnCtxt::infer_err` instead.
+ pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
+ TypeErrCtxt { infcx: self, typeck_results: None }
+ }
+
/// calls `tcx.try_unify_abstract_consts` after
/// canonicalizing the consts.
#[instrument(skip(self), level = "debug")]
pub fn try_unify_abstract_consts(
&self,
- a: ty::Unevaluated<'tcx, ()>,
- b: ty::Unevaluated<'tcx, ()>,
+ a: ty::UnevaluatedConst<'tcx>,
+ b: ty::UnevaluatedConst<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
// Reject any attempt to unify two unevaluated constants that contain inference
// variables, since inference variables in queries lead to ICEs.
- if a.substs.has_infer_types_or_consts()
- || b.substs.has_infer_types_or_consts()
- || param_env.has_infer_types_or_consts()
+ if a.substs.has_non_region_infer()
+ || b.substs.has_non_region_infer()
+ || param_env.has_non_region_infer()
{
debug!("a or b or param_env contain infer vars in its substs -> cannot unify");
return false;
@@ -738,7 +720,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// if this is not a type variable.
///
/// No attempt is made to resolve `ty`.
- pub fn type_var_origin(&'a self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
+ pub fn type_var_origin(&self, ty: Ty<'tcx>) -> Option<TypeVariableOrigin> {
match *ty.kind() {
ty::Infer(ty::TyVar(vid)) => {
Some(*self.inner.borrow_mut().type_variables().var_origin(vid))
@@ -779,7 +761,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
vars
}
- fn combine_fields(
+ fn combine_fields<'a>(
&'a self,
trace: TypeTrace<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -821,7 +803,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
result
}
- fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
+ fn start_snapshot(&self) -> CombinedSnapshot<'tcx> {
debug!("start_snapshot()");
let in_snapshot = self.in_snapshot.replace(true);
@@ -833,22 +815,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(),
universe: self.universe(),
was_in_snapshot: in_snapshot,
- // Borrow typeck results "in progress" (i.e., during typeck)
- // to ban writes from within a snapshot to them.
- _in_progress_typeck_results: self
- .in_progress_typeck_results
- .map(|typeck_results| typeck_results.borrow()),
}
}
#[instrument(skip(self, snapshot), level = "debug")]
- fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
+ fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) {
let CombinedSnapshot {
undo_snapshot,
region_constraints_snapshot,
universe,
was_in_snapshot,
- _in_progress_typeck_results,
} = snapshot;
self.in_snapshot.set(was_in_snapshot);
@@ -860,13 +836,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
#[instrument(skip(self, snapshot), level = "debug")]
- fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
+ fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) {
let CombinedSnapshot {
undo_snapshot,
region_constraints_snapshot: _,
universe: _,
was_in_snapshot,
- _in_progress_typeck_results,
} = snapshot;
self.in_snapshot.set(was_in_snapshot);
@@ -878,7 +853,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self, f), level = "debug")]
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E>
where
- F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>,
+ F: FnOnce(&CombinedSnapshot<'tcx>) -> Result<T, E>,
{
let snapshot = self.start_snapshot();
let r = f(&snapshot);
@@ -898,7 +873,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self, f), level = "debug")]
pub fn probe<R, F>(&self, f: F) -> R
where
- F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
+ F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
{
let snapshot = self.start_snapshot();
let r = f(&snapshot);
@@ -910,7 +885,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
#[instrument(skip(self, f), level = "debug")]
pub fn probe_maybe_skip_leak_check<R, F>(&self, should_skip: bool, f: F) -> R
where
- F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
+ F: FnOnce(&CombinedSnapshot<'tcx>) -> R,
{
let snapshot = self.start_snapshot();
let was_skip_leak_check = self.skip_leak_check.get();
@@ -930,7 +905,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders
pub fn region_constraints_added_in_snapshot(
&self,
- snapshot: &CombinedSnapshot<'a, 'tcx>,
+ snapshot: &CombinedSnapshot<'tcx>,
) -> Option<bool> {
self.inner
.borrow_mut()
@@ -938,7 +913,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
}
- pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool {
+ pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool {
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
}
@@ -1175,8 +1150,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// Return the universe that the region `r` was created in. For
/// most regions (e.g., `'static`, named regions from the user,
/// etc) this is the root universe U0. For inference variables or
- /// placeholders, however, it will return the universe which which
- /// they are associated.
+ /// placeholders, however, it will return the universe which they
+ /// are associated.
pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex {
self.inner.borrow_mut().unwrap_region_constraints().universe(r)
}
@@ -1308,7 +1283,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
assert!(old_value.is_none());
}
- /// Process the region constraints and return any any errors that
+ /// Process the region constraints and return any errors that
/// result. After this, no more unification operations should be
/// done -- or the compiler will panic -- but it is legal to use
/// `resolve_vars_if_possible` as well as `fully_resolve`.
@@ -1342,32 +1317,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
errors
}
-
- /// Process the region constraints and report any errors that
- /// result. After this, no more unification operations should be
- /// done -- or the compiler will panic -- but it is legal to use
- /// `resolve_vars_if_possible` as well as `fully_resolve`.
- ///
- /// Make sure to call [`InferCtxt::process_registered_region_obligations`]
- /// first, or preferably use [`InferCtxt::check_region_obligations_and_report_errors`]
- /// to do both of these operations together.
- pub fn resolve_regions_and_report_errors(
- &self,
- generic_param_scope: LocalDefId,
- outlives_env: &OutlivesEnvironment<'tcx>,
- ) {
- let errors = self.resolve_regions(outlives_env);
-
- if !self.is_tainted_by_errors() {
- // As a heuristic, just skip reporting region errors
- // altogether if other errors have been reported while
- // this infcx was in use. This is totally hokey but
- // otherwise we have a hard time separating legit region
- // errors from silly ones.
- self.report_region_errors(generic_param_scope, &errors);
- }
- }
-
/// Obtains (and clears) the current set of region
/// constraints. The inference context is still usable: further
/// unifications will simply add new constraints.
@@ -1520,60 +1469,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
* except during the writeback phase.
*/
- resolve::fully_resolve(self, value)
- }
-
- // [Note-Type-error-reporting]
- // An invariant is that anytime the expected or actual type is Error (the special
- // error type, meaning that an error occurred when typechecking this expression),
- // this is a derived error. The error cascaded from another error (that was already
- // reported), so it's not useful to display it to the user.
- // The following methods implement this logic.
- // They check if either the actual or expected type is Error, and don't print the error
- // 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,
- mk_diag: M,
- actual_ty: Ty<'tcx>,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
- where
- M: FnOnce(String) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>,
- {
- let actual_ty = self.resolve_vars_if_possible(actual_ty);
- debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
-
- let mut err = mk_diag(self.ty_to_string(actual_ty));
-
- // Don't report an error if actual type is `Error`.
- if actual_ty.references_error() {
- err.downgrade_to_delayed_bug();
- }
-
- err
- }
-
- pub fn report_mismatched_types(
- &self,
- cause: &ObligationCause<'tcx>,
- expected: Ty<'tcx>,
- actual: Ty<'tcx>,
- err: TypeError<'tcx>,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
- }
-
- pub fn report_mismatched_consts(
- &self,
- cause: &ObligationCause<'tcx>,
- expected: ty::Const<'tcx>,
- actual: ty::Const<'tcx>,
- err: TypeError<'tcx>,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
+ let value = resolve::fully_resolve(self, value);
+ assert!(
+ value.as_ref().map_or(true, |value| !value.needs_infer()),
+ "`{value:?}` is not fully resolved"
+ );
+ value
}
pub fn replace_bound_vars_with_fresh_vars<T>(
@@ -1590,7 +1491,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
struct ToFreshVars<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
span: Span,
lbrct: LateBoundRegionConversionTime,
map: FxHashMap<ty::BoundVar, ty::GenericArg<'tcx>>,
@@ -1690,7 +1591,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn try_const_eval_resolve(
&self,
param_env: ty::ParamEnv<'tcx>,
- unevaluated: ty::Unevaluated<'tcx, ()>,
+ unevaluated: ty::UnevaluatedConst<'tcx>,
ty: Ty<'tcx>,
span: Option<Span>,
) -> Result<ty::Const<'tcx>, ErrorHandled> {
@@ -1725,7 +1626,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn const_eval_resolve(
&self,
mut param_env: ty::ParamEnv<'tcx>,
- unevaluated: ty::Unevaluated<'tcx, ()>,
+ unevaluated: ty::UnevaluatedConst<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@@ -1733,7 +1634,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Postpone the evaluation of constants whose substs depend on inference
// variables
- if substs.has_infer_types_or_consts() {
+ if substs.has_non_region_infer() {
let ac = AbstractConst::new(self.tcx, unevaluated);
match ac {
Ok(None) => {
@@ -1756,8 +1657,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
debug!(?param_env_erased);
debug!(?substs_erased);
- let unevaluated =
- ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
+ let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased };
// The return value is the evaluated value which doesn't contain any reference to inference
// variables, thus we don't need to substitute back the original values.
@@ -1816,6 +1716,86 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+ /// Process the region constraints and report any errors that
+ /// result. After this, no more unification operations should be
+ /// done -- or the compiler will panic -- but it is legal to use
+ /// `resolve_vars_if_possible` as well as `fully_resolve`.
+ ///
+ /// Make sure to call [`InferCtxt::process_registered_region_obligations`]
+ /// first, or preferably use [`InferCtxt::check_region_obligations_and_report_errors`]
+ /// to do both of these operations together.
+ pub fn resolve_regions_and_report_errors(
+ &self,
+ generic_param_scope: LocalDefId,
+ outlives_env: &OutlivesEnvironment<'tcx>,
+ ) {
+ let errors = self.resolve_regions(outlives_env);
+
+ if !self.is_tainted_by_errors() {
+ // As a heuristic, just skip reporting region errors
+ // altogether if other errors have been reported while
+ // this infcx was in use. This is totally hokey but
+ // otherwise we have a hard time separating legit region
+ // errors from silly ones.
+ self.report_region_errors(generic_param_scope, &errors);
+ }
+ }
+
+ // [Note-Type-error-reporting]
+ // An invariant is that anytime the expected or actual type is Error (the special
+ // error type, meaning that an error occurred when typechecking this expression),
+ // this is a derived error. The error cascaded from another error (that was already
+ // reported), so it's not useful to display it to the user.
+ // The following methods implement this logic.
+ // They check if either the actual or expected type is Error, and don't print the error
+ // 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,
+ mk_diag: M,
+ actual_ty: Ty<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>
+ where
+ M: FnOnce(String) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+ {
+ let actual_ty = self.resolve_vars_if_possible(actual_ty);
+ debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
+
+ let mut err = mk_diag(self.ty_to_string(actual_ty));
+
+ // Don't report an error if actual type is `Error`.
+ if actual_ty.references_error() {
+ err.downgrade_to_delayed_bug();
+ }
+
+ err
+ }
+
+ pub fn report_mismatched_types(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ expected: Ty<'tcx>,
+ actual: Ty<'tcx>,
+ err: TypeError<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ self.report_and_explain_type_error(TypeTrace::types(cause, true, expected, actual), err)
+ }
+
+ pub fn report_mismatched_consts(
+ &self,
+ cause: &ObligationCause<'tcx>,
+ expected: ty::Const<'tcx>,
+ actual: ty::Const<'tcx>,
+ err: TypeError<'tcx>,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ self.report_and_explain_type_error(TypeTrace::consts(cause, true, expected, actual), err)
+ }
+}
+
/// Helper for `ty_or_const_infer_var_changed` (see comment on that), currently
/// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
#[derive(Copy, Clone, Debug)]
@@ -1885,7 +1865,7 @@ impl<'tcx> TypeFolder<'tcx> for InferenceLiteralEraser<'tcx> {
}
struct ShallowResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
@@ -2072,21 +2052,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
) -> SubstsRef<'tcx> {
tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
match arg.unpack() {
- GenericArgKind::Type(_)
- if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
- {
+ GenericArgKind::Type(_) if arg.has_non_region_param() || arg.has_non_region_infer() => {
tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
universe: ty::UniverseIndex::ROOT,
name: ty::BoundVar::from_usize(idx),
}))
.into()
}
- GenericArgKind::Const(ct)
- if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
- {
+ GenericArgKind::Const(ct) if ct.has_non_region_infer() || ct.has_non_region_param() => {
let ty = ct.ty();
// If the type references param or infer, replace that too...
- if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
+ if ty.has_non_region_param() || ty.has_non_region_infer() {
bug!("const `{ct}`'s type should not reference params or types");
}
tcx.mk_const(ty::ConstS {
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 00fc442d3..600f94f09 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -25,7 +25,9 @@ use crate::infer::combine::ConstEquateRelation;
use crate::infer::InferCtxt;
use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
+use crate::traits::PredicateObligation;
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};
@@ -44,7 +46,7 @@ pub struct TypeRelating<'me, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
{
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
/// Callback to use when we deduce an outlives relationship.
delegate: D,
@@ -91,11 +93,9 @@ pub trait TypeRelatingDelegate<'tcx> {
);
fn const_equate(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>);
- fn register_opaque_type(
+ fn register_opaque_type_obligations(
&mut self,
- a: Ty<'tcx>,
- b: Ty<'tcx>,
- a_is_expected: bool,
+ obligations: Vec<PredicateObligation<'tcx>>,
) -> Result<(), TypeError<'tcx>>;
/// Creates a new universe index. Used when instantiating placeholders.
@@ -149,11 +149,7 @@ impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
{
- pub fn new(
- infcx: &'me InferCtxt<'me, 'tcx>,
- delegate: D,
- ambient_variance: ty::Variance,
- ) -> Self {
+ pub fn new(infcx: &'me InferCtxt<'tcx>, delegate: D, ambient_variance: ty::Variance) -> Self {
Self {
infcx,
delegate,
@@ -357,7 +353,7 @@ where
// In NLL, we don't have type inference variables
// floating around, so we can do this rather imprecise
// variant of the occurs-check.
- assert!(!generalized_ty.has_infer_types_or_consts());
+ assert!(!generalized_ty.has_non_region_infer());
}
self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
@@ -418,7 +414,12 @@ where
(_, &ty::Opaque(..)) => (generalize(a, true)?, b),
_ => unreachable!(),
};
- self.delegate.register_opaque_type(a, b, true)?;
+ let cause = ObligationCause::dummy_with_span(self.delegate.span());
+ let obligations = self
+ .infcx
+ .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
+ .obligations;
+ self.delegate.register_opaque_type_obligations(obligations)?;
trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
Ok(a)
}
@@ -867,7 +868,7 @@ struct TypeGeneralizer<'me, 'tcx, D>
where
D: TypeRelatingDelegate<'tcx>,
{
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
delegate: &'me mut D,
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index 8c9ddf866..a982f11f7 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -1,14 +1,16 @@
use crate::errors::OpaqueHiddenTypeDiag;
use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
use crate::traits;
+use hir::def::DefKind;
use hir::def_id::{DefId, LocalDefId};
use hir::{HirId, OpaqueTyOrigin};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
use rustc_middle::traits::ObligationCause;
+use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::subst::{GenericArgKind, Subst};
+use rustc_middle::ty::GenericArgKind;
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitor,
@@ -40,7 +42,7 @@ pub struct OpaqueTypeDecl<'tcx> {
pub origin: hir::OpaqueTyOrigin,
}
-impl<'a, 'tcx> InferCtxt<'a, '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>>(
@@ -101,7 +103,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
return Ok(InferOk { value: (), obligations: vec![] });
}
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
- let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
+ let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() {
ty::Opaque(def_id, substs) if def_id.is_local() => {
let def_id = def_id.expect_local();
let origin = match self.defining_use_anchor {
@@ -167,25 +169,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
param_env,
b,
origin,
+ a_is_expected,
))
}
_ => None,
};
- if let Some(res) = process(a, b) {
+ if let Some(res) = process(a, b, true) {
res
- } else if let Some(res) = process(b, a) {
+ } else if let Some(res) = process(b, a, false) {
res
} else {
- // Rerun equality check, but this time error out due to
- // different types.
- match self.at(cause, param_env).define_opaque_types(false).eq(a, b) {
- Ok(_) => span_bug!(
- cause.span,
- "opaque types are never equal to anything but themselves: {:#?}",
- (a.kind(), b.kind())
- ),
- Err(e) => Err(e),
- }
+ let (a, b) = self.resolve_vars_if_possible((a, b));
+ Err(TypeError::Sorts(ExpectedFound::new(true, a, b)))
}
}
@@ -518,15 +513,16 @@ impl UseKind {
}
}
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
#[instrument(skip(self), level = "debug")]
- pub fn register_hidden_type(
+ fn register_hidden_type(
&self,
opaque_type_key: OpaqueTypeKey<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
hidden_ty: Ty<'tcx>,
origin: hir::OpaqueTyOrigin,
+ a_is_expected: bool,
) -> InferResult<'tcx, ()> {
let tcx = self.tcx;
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
@@ -545,21 +541,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin,
);
if let Some(prev) = prev {
- obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations;
+ obligations =
+ self.at(&cause, param_env).eq_exp(a_is_expected, prev, hidden_ty)?.obligations;
}
let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id());
- for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
- debug!(?predicate);
- let predicate = predicate.subst(tcx, substs);
-
+ for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) {
let predicate = predicate.fold_with(&mut BottomUpFolder {
tcx,
ty_op: |ty| match *ty.kind() {
// We can't normalize associated types from `rustc_infer`,
// but we can eagerly register inference variables for them.
- ty::Projection(projection_ty) if !projection_ty.has_escaping_bound_vars() => {
+ // FIXME(RPITIT): Don't replace RPITITs with inference vars.
+ ty::Projection(projection_ty)
+ if !projection_ty.has_escaping_bound_vars()
+ && tcx.def_kind(projection_ty.item_def_id)
+ != DefKind::ImplTraitPlaceholder =>
+ {
self.infer_projection(
param_env,
projection_ty,
@@ -575,6 +574,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
{
hidden_ty
}
+ // FIXME(RPITIT): This can go away when we move to associated types
+ ty::Projection(proj)
+ if def_id.to_def_id() == proj.item_def_id && substs == proj.substs =>
+ {
+ hidden_ty
+ }
_ => ty,
},
lt_op: |lt| lt,
@@ -623,7 +628,7 @@ fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hi
let scope = tcx.hir().get_defining_scope(opaque_hir_id);
// We walk up the node tree until we hit the root or the scope of the opaque type.
while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
- hir_id = tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(hir_id));
+ hir_id = tcx.hir().get_parent_item(hir_id).into();
}
// Syntactically, we are allowed to define the concrete type if:
let res = hir_id == scope;
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index b2d7f4a66..14ee9f051 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -3,8 +3,9 @@
// RFC for reference.
use rustc_data_structures::sso::SsoHashSet;
+use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitable};
use smallvec::{smallvec, SmallVec};
#[derive(Debug)]
@@ -45,6 +46,8 @@ pub enum Component<'tcx> {
// them. This gives us room to improve the regionck reasoning in
// the future without breaking backwards compat.
EscapingProjection(Vec<Component<'tcx>>),
+
+ Opaque(DefId, SubstsRef<'tcx>),
}
/// Push onto `out` all the things that must outlive `'a` for the condition
@@ -120,6 +123,17 @@ fn compute_components<'tcx>(
out.push(Component::Param(p));
}
+ // Ignore lifetimes found in opaque types. Opaque types can
+ // have lifetimes in their substs which their hidden type doesn't
+ // actually use. If we inferred that an opaque type is outlived by
+ // its parameter lifetimes, then we could prove that any lifetime
+ // outlives any other lifetime, which is unsound.
+ // See https://github.com/rust-lang/rust/issues/84305 for
+ // more details.
+ ty::Opaque(def_id, substs) => {
+ out.push(Component::Opaque(def_id, substs));
+ },
+
// For projections, we prefer to generate an obligation like
// `<P0 as Trait<P1...Pn>>::Foo: 'a`, because this gives the
// regionck more ways to prove that it holds. However,
@@ -168,7 +182,6 @@ fn compute_components<'tcx>(
ty::Float(..) | // OutlivesScalar
ty::Never | // ...
ty::Adt(..) | // OutlivesNominalType
- ty::Opaque(..) | // OutlivesNominalType (ish)
ty::Foreign(..) | // OutlivesNominalType
ty::Str | // OutlivesScalar (ish)
ty::Slice(..) | // ...
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index 9922b156e..33543135d 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -87,9 +87,9 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
}
/// Create a new `OutlivesEnvironment` with extra outlives bounds.
- pub fn with_bounds<'a>(
+ pub fn with_bounds(
param_env: ty::ParamEnv<'tcx>,
- infcx: Option<&InferCtxt<'a, 'tcx>>,
+ infcx: Option<&InferCtxt<'tcx>>,
extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
) -> Self {
let mut builder = Self::builder(param_env);
@@ -108,7 +108,7 @@ impl<'tcx> OutlivesEnvironment<'tcx> {
}
}
-impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
+impl<'tcx> OutlivesEnvironmentBuilder<'tcx> {
#[inline]
#[instrument(level = "debug")]
fn build(self) -> OutlivesEnvironment<'tcx> {
@@ -125,7 +125,7 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
/// contain inference variables, it must be supplied, in which
/// case we will register "givens" on the inference context. (See
/// `RegionConstraintData`.)
- fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
+ fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'tcx>>, outlives_bounds: I)
where
I: IntoIterator<Item = OutlivesBound<'tcx>>,
{
@@ -142,6 +142,10 @@ impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
self.region_bound_pairs
.insert(ty::OutlivesPredicate(GenericKind::Projection(projection_b), r_a));
}
+ OutlivesBound::RegionSubOpaque(r_a, def_id, substs) => {
+ self.region_bound_pairs
+ .insert(ty::OutlivesPredicate(GenericKind::Opaque(def_id, substs), r_a));
+ }
OutlivesBound::RegionSubRegion(r_a, r_b) => {
if let (ReEarlyBound(_) | ReFree(_), ReVar(vid_b)) = (r_a.kind(), r_b.kind()) {
infcx
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index 5bd1774f6..6ca884799 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -68,13 +68,14 @@ use crate::infer::{
};
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
+use rustc_hir::def_id::DefId;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitable};
use smallvec::smallvec;
-impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Registers that the given region obligation must be resolved
/// from within the scope of `body_id`. These regions are enqueued
/// and later processed by regionck, when full type information is
@@ -182,7 +183,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
outlives_env.param_env,
);
- self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
+ self.err_ctxt().resolve_regions_and_report_errors(generic_param_scope, outlives_env)
}
}
@@ -283,6 +284,9 @@ where
Component::Param(param_ty) => {
self.param_ty_must_outlive(origin, region, *param_ty);
}
+ Component::Opaque(def_id, substs) => {
+ self.opaque_must_outlive(*def_id, substs, origin, region)
+ }
Component::Projection(projection_ty) => {
self.projection_must_outlive(origin, region, *projection_ty);
}
@@ -314,17 +318,69 @@ where
);
let generic = GenericKind::Param(param_ty);
- let verify_bound = self.verify_bound.generic_bound(generic);
+ let verify_bound = self.verify_bound.param_bound(param_ty);
self.delegate.push_verify(origin, generic, region, verify_bound);
}
#[instrument(level = "debug", skip(self))]
+ fn opaque_must_outlive(
+ &mut self,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+ origin: infer::SubregionOrigin<'tcx>,
+ region: ty::Region<'tcx>,
+ ) {
+ self.generic_must_outlive(
+ origin,
+ region,
+ GenericKind::Opaque(def_id, substs),
+ def_id,
+ substs,
+ true,
+ |ty| match *ty.kind() {
+ ty::Opaque(def_id, substs) => (def_id, substs),
+ _ => bug!("expected only projection types from env, not {:?}", ty),
+ },
+ );
+ }
+
+ #[instrument(level = "debug", skip(self))]
fn projection_must_outlive(
&mut self,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
) {
+ self.generic_must_outlive(
+ origin,
+ region,
+ GenericKind::Projection(projection_ty),
+ projection_ty.item_def_id,
+ projection_ty.substs,
+ false,
+ |ty| match ty.kind() {
+ ty::Projection(projection_ty) => (projection_ty.item_def_id, projection_ty.substs),
+ _ => bug!("expected only projection types from env, not {:?}", ty),
+ },
+ );
+ }
+
+ #[instrument(level = "debug", skip(self, filter))]
+ fn generic_must_outlive(
+ &mut self,
+ origin: infer::SubregionOrigin<'tcx>,
+ region: ty::Region<'tcx>,
+ generic: GenericKind<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
+ is_opaque: bool,
+ filter: impl Fn(Ty<'tcx>) -> (DefId, SubstsRef<'tcx>),
+ ) {
+ // An optimization for a common case with opaque types.
+ if substs.is_empty() {
+ return;
+ }
+
// This case is thorny for inference. The fundamental problem is
// that there are many cases where we have choice, and inference
// doesn't like choice (the current region inference in
@@ -343,16 +399,15 @@ where
// These are guaranteed to apply, no matter the inference
// results.
let trait_bounds: Vec<_> =
- self.verify_bound.projection_declared_bounds_from_trait(projection_ty).collect();
+ self.verify_bound.declared_region_bounds(def_id, substs).collect();
debug!(?trait_bounds);
// Compute the bounds we can derive from the environment. This
// is an "approximate" match -- in some cases, these bounds
// may not apply.
- let mut approx_env_bounds =
- self.verify_bound.projection_approx_declared_bounds_from_env(projection_ty);
- debug!("projection_must_outlive: approx_env_bounds={:?}", approx_env_bounds);
+ let mut approx_env_bounds = self.verify_bound.approx_declared_bounds_from_env(generic);
+ debug!(?approx_env_bounds);
// Remove outlives bounds that we get from the environment but
// which are also deducible from the trait. This arises (cc
@@ -366,14 +421,8 @@ where
// If the declaration is `trait Trait<'b> { type Item: 'b; }`, then `projection_declared_bounds_from_trait`
// will be invoked with `['b => ^1]` and so we will get `^1` returned.
let bound = bound_outlives.skip_binder();
- match *bound.0.kind() {
- ty::Projection(projection_ty) => self
- .verify_bound
- .projection_declared_bounds_from_trait(projection_ty)
- .all(|r| r != bound.1),
-
- _ => panic!("expected only projection types from env, not {:?}", bound.0),
- }
+ let (def_id, substs) = filter(bound.0);
+ self.verify_bound.declared_region_bounds(def_id, substs).all(|r| r != bound.1)
});
// If declared bounds list is empty, the only applicable rule is
@@ -390,29 +439,11 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
- let needs_infer = projection_ty.needs_infer();
- if approx_env_bounds.is_empty() && trait_bounds.is_empty() && needs_infer {
- debug!("projection_must_outlive: no declared bounds");
-
- let constraint = origin.to_constraint_category();
- for k in projection_ty.substs {
- match k.unpack() {
- GenericArgKind::Lifetime(lt) => {
- self.delegate.push_sub_region_constraint(
- origin.clone(),
- region,
- lt,
- constraint,
- );
- }
- GenericArgKind::Type(ty) => {
- self.type_must_outlive(origin.clone(), ty, region, constraint);
- }
- GenericArgKind::Const(_) => {
- // Const parameters don't impose constraints.
- }
- }
- }
+ let needs_infer = substs.needs_infer();
+ if approx_env_bounds.is_empty() && trait_bounds.is_empty() && (needs_infer || is_opaque) {
+ debug!("no declared bounds");
+
+ self.substs_must_outlive(substs, origin, region);
return;
}
@@ -442,8 +473,8 @@ where
.all(|b| b == Some(trait_bounds[0]))
{
let unique_bound = trait_bounds[0];
- debug!("projection_must_outlive: unique trait bound = {:?}", unique_bound);
- debug!("projection_must_outlive: unique declared bound appears in trait ref");
+ debug!(?unique_bound);
+ debug!("unique declared bound appears in trait ref");
let category = origin.to_constraint_category();
self.delegate.push_sub_region_constraint(origin, region, unique_bound, category);
return;
@@ -454,14 +485,45 @@ where
// projection outlive; in some cases, this may add insufficient
// edges into the inference graph, leading to inference failures
// even though a satisfactory solution exists.
- let generic = GenericKind::Projection(projection_ty);
- let verify_bound = self.verify_bound.generic_bound(generic);
+ let verify_bound = self.verify_bound.projection_opaque_bounds(
+ generic,
+ def_id,
+ substs,
+ &mut Default::default(),
+ );
debug!("projection_must_outlive: pushing {:?}", verify_bound);
self.delegate.push_verify(origin, generic, region, verify_bound);
}
+
+ fn substs_must_outlive(
+ &mut self,
+ substs: SubstsRef<'tcx>,
+ origin: infer::SubregionOrigin<'tcx>,
+ region: ty::Region<'tcx>,
+ ) {
+ let constraint = origin.to_constraint_category();
+ for k in substs {
+ match k.unpack() {
+ GenericArgKind::Lifetime(lt) => {
+ self.delegate.push_sub_region_constraint(
+ origin.clone(),
+ region,
+ lt,
+ constraint,
+ );
+ }
+ GenericArgKind::Type(ty) => {
+ self.type_must_outlive(origin.clone(), ty, region, constraint);
+ }
+ GenericArgKind::Const(_) => {
+ // Const parameters don't impose constraints.
+ }
+ }
+ }
+ }
}
-impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'cx, 'tcx> {
+impl<'cx, 'tcx> TypeOutlivesDelegate<'tcx> for &'cx InferCtxt<'tcx> {
fn push_sub_region_constraint(
&mut self,
origin: SubregionOrigin<'tcx>,
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 752334950..f470b2eb8 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -2,11 +2,10 @@ use crate::infer::outlives::components::{compute_components_recursive, Component
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::{GenericKind, VerifyBound};
-use rustc_data_structures::captures::Captures;
use rustc_data_structures::sso::SsoHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, Subst};
-use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, Ty, TyCtxt};
+use rustc_middle::ty::GenericArg;
+use rustc_middle::ty::{self, EarlyBinder, OutlivesPredicate, SubstsRef, Ty, TyCtxt};
use smallvec::smallvec;
@@ -38,20 +37,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
Self { tcx, region_bound_pairs, implicit_region_bound, param_env }
}
- /// Returns a "verify bound" that encodes what we know about
- /// `generic` and the regions it outlives.
- pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
- let mut visited = SsoHashSet::new();
- match generic {
- GenericKind::Param(param_ty) => self.param_bound(param_ty),
- GenericKind::Projection(projection_ty) => {
- self.projection_bound(projection_ty, &mut visited)
- }
- }
- }
-
#[instrument(level = "debug", skip(self))]
- fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
+ pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
// Start with anything like `T: 'a` we can scrape from the
// environment. If the environment contains something like
// `for<'a> T: 'a`, then we know that `T` outlives everything.
@@ -105,41 +92,31 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
/// the clause from the environment only applies if `'0 = 'a`,
/// which we don't know yet. But we would still include `'b` in
/// this list.
- pub fn projection_approx_declared_bounds_from_env(
+ pub fn approx_declared_bounds_from_env(
&self,
- projection_ty: ty::ProjectionTy<'tcx>,
+ generic: GenericKind<'tcx>,
) -> Vec<ty::Binder<'tcx, ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>>> {
- let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx);
+ let projection_ty = generic.to_ty(self.tcx);
let erased_projection_ty = self.tcx.erase_regions(projection_ty);
self.declared_generic_bounds_from_env_for_erased_ty(erased_projection_ty)
}
- /// Searches the where-clauses in scope for regions that
- /// `projection_ty` is known to outlive. Currently requires an
- /// exact match.
- pub fn projection_declared_bounds_from_trait(
+ #[instrument(level = "debug", skip(self, visited))]
+ pub fn projection_opaque_bounds(
&self,
- projection_ty: ty::ProjectionTy<'tcx>,
- ) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
- self.declared_projection_bounds_from_trait(projection_ty)
- }
-
- pub fn projection_bound(
- &self,
- projection_ty: ty::ProjectionTy<'tcx>,
+ generic: GenericKind<'tcx>,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
- debug!("projection_bound(projection_ty={:?})", projection_ty);
-
- let projection_ty_as_ty =
- self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
+ let generic_ty = generic.to_ty(self.tcx);
// Search the env for where clauses like `P: 'a`.
- let env_bounds = self
- .projection_approx_declared_bounds_from_env(projection_ty)
+ let projection_opaque_bounds = self
+ .approx_declared_bounds_from_env(generic)
.into_iter()
.map(|binder| {
- if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty {
+ if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
// Micro-optimize if this is an exact match (this
// occurs often when there are no region variables
// involved).
@@ -149,21 +126,19 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
VerifyBound::IfEq(verify_if_eq_b)
}
});
-
// Extend with bounds that we can find from the trait.
- let trait_bounds = self
- .projection_declared_bounds_from_trait(projection_ty)
- .map(|r| VerifyBound::OutlivedBy(r));
+ let trait_bounds =
+ self.declared_region_bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
- compute_components_recursive(self.tcx, ty.into(), &mut components, visited);
+ compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
self.bound_from_components(&components, visited)
};
- VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
+ VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
+ .or(recursive_bound)
}
fn bound_from_components(
@@ -195,7 +170,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
match *component {
Component::Region(lt) => VerifyBound::OutlivedBy(lt),
Component::Param(param_ty) => self.param_bound(param_ty),
- Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited),
+ Component::Opaque(did, substs) => self.projection_opaque_bounds(
+ GenericKind::Opaque(did, substs),
+ did,
+ substs,
+ visited,
+ ),
+ Component::Projection(projection_ty) => self.projection_opaque_bounds(
+ GenericKind::Projection(projection_ty),
+ projection_ty.item_def_id,
+ projection_ty.substs,
+ visited,
+ ),
Component::EscapingProjection(ref components) => {
self.bound_from_components(components, visited)
}
@@ -293,30 +279,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
/// }
/// ```
///
- /// then this function would return `'x`. This is subject to the
- /// limitations around higher-ranked bounds described in
- /// `region_bounds_declared_on_associated_item`.
- fn declared_projection_bounds_from_trait(
- &self,
- projection_ty: ty::ProjectionTy<'tcx>,
- ) -> impl Iterator<Item = ty::Region<'tcx>> + 'cx + Captures<'tcx> {
- debug!("projection_bounds(projection_ty={:?})", projection_ty);
- let tcx = self.tcx;
- self.region_bounds_declared_on_associated_item(projection_ty.item_def_id)
- .map(move |r| EarlyBinder(r).subst(tcx, projection_ty.substs))
- }
-
- /// Given the `DefId` of an associated item, returns any region
- /// bounds attached to that associated item from the trait definition.
- ///
- /// For example:
- ///
- /// ```rust
- /// trait Foo<'a> {
- /// type Bar: 'a;
- /// }
- /// ```
- ///
/// If we were given the `DefId` of `Foo::Bar`, we would return
/// `'a`. You could then apply the substitutions from the
/// projection to convert this into your namespace. This also
@@ -336,17 +298,20 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
///
/// This is for simplicity, and because we are not really smart
/// enough to cope with such bounds anywhere.
- fn region_bounds_declared_on_associated_item(
+ pub fn declared_region_bounds(
&self,
- assoc_item_def_id: DefId,
+ def_id: DefId,
+ substs: SubstsRef<'tcx>,
) -> impl Iterator<Item = ty::Region<'tcx>> {
let tcx = self.tcx;
- let bounds = tcx.item_bounds(assoc_item_def_id);
+ let bounds = tcx.item_bounds(def_id);
+ trace!("{:#?}", bounds);
bounds
.into_iter()
.filter_map(|p| p.to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars())
.map(|b| b.1)
+ .map(move |r| EarlyBinder(r).subst(tcx, substs))
}
/// Searches through a predicate list for a predicate `T: 'a`.
diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs
index b45a6514d..9f12bc972 100644
--- a/compiler/rustc_infer/src/infer/projection.rs
+++ b/compiler/rustc_infer/src/infer/projection.rs
@@ -6,7 +6,7 @@ use crate::traits::{Obligation, PredicateObligation};
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::InferCtxt;
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
/// Instead of normalizing an associated type projection,
/// this function generates an inference variable and registers
/// an obligation that this inference variable must be the result
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 397efe6ee..90858e307 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -66,7 +66,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
tcx: TyCtxt<'tcx>,
overly_polymorphic: bool,
max_universe: ty::UniverseIndex,
- snapshot: &CombinedSnapshot<'_, 'tcx>,
+ snapshot: &CombinedSnapshot<'tcx>,
) -> RelateResult<'tcx, ()> {
debug!(
"leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})",
diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
index e43d28ee5..67b3da687 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs
@@ -12,8 +12,10 @@ use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_data_structures::unify as ut;
+use rustc_hir::def_id::DefId;
use rustc_index::vec::IndexVec;
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
+use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::ReStatic;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{ReLateBound, ReVar};
@@ -168,6 +170,7 @@ pub struct Verify<'tcx> {
pub enum GenericKind<'tcx> {
Param(ty::ParamTy),
Projection(ty::ProjectionTy<'tcx>),
+ Opaque(DefId, SubstsRef<'tcx>),
}
/// Describes the things that some `GenericKind` value `G` is known to
@@ -747,6 +750,9 @@ impl<'tcx> fmt::Debug for GenericKind<'tcx> {
match *self {
GenericKind::Param(ref p) => write!(f, "{:?}", p),
GenericKind::Projection(ref p) => write!(f, "{:?}", p),
+ GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| {
+ write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap()))
+ }),
}
}
}
@@ -756,6 +762,9 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
match *self {
GenericKind::Param(ref p) => write!(f, "{}", p),
GenericKind::Projection(ref p) => write!(f, "{}", p),
+ GenericKind::Opaque(def_id, substs) => ty::tls::with(|tcx| {
+ write!(f, "{}", tcx.def_path_str_with_substs(def_id, tcx.lift(substs).unwrap()))
+ }),
}
}
}
@@ -765,6 +774,7 @@ impl<'tcx> GenericKind<'tcx> {
match *self {
GenericKind::Param(ref p) => p.to_ty(tcx),
GenericKind::Projection(ref p) => tcx.mk_projection(p.item_def_id, p.substs),
+ GenericKind::Opaque(def_id, substs) => tcx.mk_opaque(def_id, substs),
}
}
}
diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs
index 3d99f0958..4db4ff238 100644
--- a/compiler/rustc_infer/src/infer/resolve.rs
+++ b/compiler/rustc_infer/src/infer/resolve.rs
@@ -1,6 +1,5 @@
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::{FixupError, FixupResult, InferCtxt, Span};
-use rustc_middle::mir;
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};
@@ -16,12 +15,12 @@ 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<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> OpportunisticVarResolver<'a, 'tcx> {
#[inline]
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
OpportunisticVarResolver { infcx }
}
}
@@ -32,7 +31,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if !t.has_infer_types_or_consts() {
+ 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);
@@ -41,17 +40,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
}
fn fold_const(&mut self, ct: Const<'tcx>) -> Const<'tcx> {
- if !ct.has_infer_types_or_consts() {
+ 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);
ct.super_fold_with(self)
}
}
-
- fn fold_mir_const(&mut self, constant: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
- constant.super_fold_with(self)
- }
}
/// The opportunistic region resolver opportunistically resolves regions
@@ -62,11 +57,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> {
/// If you want to resolve type and const variables as well, call
/// [InferCtxt::resolve_vars_if_possible] first.
pub struct OpportunisticRegionResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> OpportunisticRegionResolver<'a, 'tcx> {
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
OpportunisticRegionResolver { infcx }
}
}
@@ -116,11 +111,11 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticRegionResolver<'a, 'tcx> {
/// It does not construct the fully resolved type (which might
/// involve some hashing and so forth).
pub struct UnresolvedTypeFinder<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> UnresolvedTypeFinder<'a, 'tcx> {
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
UnresolvedTypeFinder { infcx }
}
}
@@ -167,7 +162,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
/// Full type resolution replaces all type and region variables with
/// their concrete results. If any variable cannot be replaced (never unified, etc)
/// then an `Err` result is returned.
-pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: T) -> FixupResult<'tcx, T>
+pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult<'tcx, T>
where
T: TypeFoldable<'tcx>,
{
@@ -177,7 +172,7 @@ where
// N.B. This type is not public because the protocol around checking the
// `err` field is not enforceable otherwise.
struct FullTypeResolver<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
}
impl<'a, 'tcx> FallibleTypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs
index b7eab5d43..97354ba5d 100644
--- a/compiler/rustc_infer/src/infer/sub.rs
+++ b/compiler/rustc_infer/src/infer/sub.rs
@@ -2,9 +2,7 @@ use super::combine::{CombineFields, RelationDir};
use super::SubregionOrigin;
use crate::infer::combine::ConstEquateRelation;
-use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::Obligation;
-use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::TyVar;
@@ -12,8 +10,8 @@ use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
-pub struct Sub<'combine, 'infcx, 'tcx> {
- fields: &'combine mut CombineFields<'infcx, 'tcx>,
+pub struct Sub<'combine, 'a, 'tcx> {
+ fields: &'combine mut CombineFields<'a, 'tcx>,
a_is_expected: bool,
}
@@ -130,39 +128,36 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> {
(&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..))
if self.fields.define_opaque_types && did.is_local() =>
{
- let mut generalize = |ty, ty_is_expected| {
- let var = infcx.next_ty_var_id_in_universe(
- TypeVariableOrigin {
- kind: TypeVariableOriginKind::MiscVariable,
- span: self.fields.trace.cause.span,
- },
- ty::UniverseIndex::ROOT,
- );
- self.fields.instantiate(ty, RelationDir::SubtypeOf, var, ty_is_expected)?;
- Ok(infcx.tcx.mk_ty_var(var))
- };
- let (a, b) = if self.a_is_expected { (a, b) } else { (b, a) };
- let (ga, gb) = match (a.kind(), b.kind()) {
- (&ty::Opaque(..), _) => (a, generalize(b, true)?),
- (_, &ty::Opaque(..)) => (generalize(a, false)?, b),
- _ => unreachable!(),
- };
self.fields.obligations.extend(
infcx
- .handle_opaque_type(ga, gb, true, &self.fields.trace.cause, self.param_env())
- // Don't leak any generalized type variables out of this
- // subtyping relation in the case of a type error.
- .map_err(|err| {
- let (ga, gb) = self.fields.infcx.resolve_vars_if_possible((ga, gb));
- if let TypeError::Sorts(sorts) = err && sorts.expected == ga && sorts.found == gb {
- TypeError::Sorts(ExpectedFound { expected: a, found: b })
- } else {
- err
- }
- })?
+ .handle_opaque_type(
+ a,
+ b,
+ self.a_is_expected,
+ &self.fields.trace.cause,
+ self.param_env(),
+ )?
.obligations,
);
- Ok(ga)
+ Ok(a)
+ }
+ // Optimization of GeneratorWitness relation since we know that all
+ // free regions are replaced with bound regions during construction.
+ // This greatly speeds up subtyping of GeneratorWitness.
+ (&ty::GeneratorWitness(a_types), &ty::GeneratorWitness(b_types)) => {
+ 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(
+ a_types.map_bound(|a_types| (a_types, b_types.skip_binder())),
+ );
+ for (a, b) in std::iter::zip(a_types, b_types) {
+ self.relate(a, b)?;
+ }
+ Ok(a)
+ } else {
+ Err(ty::error::TypeError::Sorts(ty::relate::expected_found(self, a, b)))
+ }
}
_ => {
diff --git a/compiler/rustc_infer/src/lib.rs b/compiler/rustc_infer/src/lib.rs
index ef60d2c91..e040634ed 100644
--- a/compiler/rustc_infer/src/lib.rs
+++ b/compiler/rustc_infer/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! - **Type inference.** The type inference code can be found in the `infer` module;
//! this code handles low-level equality and subtyping operations. The
-//! type check pass in the compiler is found in the `rustc_typeck` crate.
+//! type check pass in the compiler is found in the `rustc_hir_analysis` crate.
//!
//! For more information about how rustc works, see the [rustc dev guide].
//!
@@ -17,9 +17,8 @@
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extend_one)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
+#![feature(if_let_guard)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(try_blocks)]
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs
index 736278ba0..b2b985a22 100644
--- a/compiler/rustc_infer/src/traits/engine.rs
+++ b/compiler/rustc_infer/src/traits/engine.rs
@@ -10,7 +10,7 @@ use super::{ObligationCause, PredicateObligation};
pub trait TraitEngine<'tcx>: 'tcx {
fn normalize_projection_type(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>,
@@ -21,7 +21,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
/// parameters (except for `Self`).
fn register_bound(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
@@ -41,14 +41,13 @@ pub trait TraitEngine<'tcx>: 'tcx {
fn register_predicate_obligation(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>,
);
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'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 select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>;
@@ -58,7 +57,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
pub trait TraitEngineExt<'tcx> {
fn register_predicate_obligations(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
);
}
@@ -66,7 +65,7 @@ pub trait TraitEngineExt<'tcx> {
impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T {
fn register_predicate_obligations(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
) {
for obligation in obligations {
diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
index 95b6c4ce1..f8b5009a5 100644
--- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs
@@ -10,7 +10,7 @@ use rustc_span::Span;
use std::fmt;
use std::iter;
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxt<'tcx> {
pub fn report_extra_impl_obligation(
&self,
error_span: Span,
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index 4df4de21a..c8600ded9 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -67,6 +67,14 @@ impl<'tcx> PredicateObligation<'tcx> {
recursion_depth: self.recursion_depth,
})
}
+
+ pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> {
+ self.param_env = self.param_env.without_const();
+ if let ty::PredicateKind::Trait(trait_pred) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() {
+ self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Trait(trait_pred.without_const())));
+ }
+ self
+ }
}
impl<'tcx> TraitObligation<'tcx> {
@@ -105,6 +113,8 @@ pub struct FulfillmentError<'tcx> {
#[derive(Clone)]
pub enum FulfillmentErrorCode<'tcx> {
+ /// Inherently impossible to fulfill; this trait is implemented if and only if it is already implemented.
+ CodeCycle(Vec<Obligation<'tcx, ty::Predicate<'tcx>>>),
CodeSelectionError(SelectionError<'tcx>),
CodeProjectionError(MismatchedProjectionTypes<'tcx>),
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs
index 573d2d1e3..1c6ab6a08 100644
--- a/compiler/rustc_infer/src/traits/structural_impls.rs
+++ b/compiler/rustc_infer/src/traits/structural_impls.rs
@@ -47,6 +47,7 @@ impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
write!(f, "CodeConstEquateError({:?}, {:?})", a, b)
}
super::CodeAmbiguity => write!(f, "Ambiguity"),
+ super::CodeCycle(ref cycle) => write!(f, "Cycle({:?})", cycle),
}
}
}
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index f5a1edf6d..e12c069dc 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -246,6 +246,13 @@ impl<'tcx> Elaborator<'tcx> {
Component::UnresolvedInferenceVariable(_) => None,
+ Component::Opaque(def_id, substs) => {
+ let ty = tcx.mk_opaque(def_id, substs);
+ Some(ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(
+ ty, r_min,
+ )))
+ }
+
Component::Projection(projection) => {
// We might end up here if we have `Foo<<Bar as Baz>::Assoc>: 'a`.
// With this, we can deduce that `<Bar as Baz>::Assoc: 'a`.
@@ -262,8 +269,9 @@ impl<'tcx> Elaborator<'tcx> {
None
}
})
- .map(ty::Binder::dummy)
- .map(|predicate_kind| predicate_kind.to_predicate(tcx))
+ .map(|predicate_kind| {
+ bound_predicate.rebind(predicate_kind).to_predicate(tcx)
+ })
.filter(|&predicate| visited.insert(predicate))
.map(|predicate| {
predicate_obligation(
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index da4002d09..6a4c5b4d3 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
libloading = "0.7.1"
@@ -38,7 +37,8 @@ rustc_mir_build = { path = "../rustc_mir_build" }
rustc_mir_transform = { path = "../rustc_mir_transform" }
rustc_monomorphize = { path = "../rustc_monomorphize" }
rustc_passes = { path = "../rustc_passes" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
+rustc_hir_typeck = { path = "../rustc_hir_typeck" }
rustc_lint = { path = "../rustc_lint" }
rustc_errors = { path = "../rustc_errors" }
rustc_plugin_impl = { path = "../rustc_plugin_impl" }
diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs
index 6a497aed4..f5135c78d 100644
--- a/compiler/rustc_interface/src/errors.rs
+++ b/compiler/rustc_interface/src/errors.rs
@@ -1,11 +1,11 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
use std::io;
use std::path::Path;
-#[derive(SessionDiagnostic)]
-#[diag(interface::ferris_identifier)]
+#[derive(Diagnostic)]
+#[diag(interface_ferris_identifier)]
pub struct FerrisIdentifier {
#[primary_span]
pub spans: Vec<Span>,
@@ -13,76 +13,76 @@ pub struct FerrisIdentifier {
pub first_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::emoji_identifier)]
+#[derive(Diagnostic)]
+#[diag(interface_emoji_identifier)]
pub struct EmojiIdentifier {
#[primary_span]
pub spans: Vec<Span>,
pub ident: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::mixed_bin_crate)]
+#[derive(Diagnostic)]
+#[diag(interface_mixed_bin_crate)]
pub struct MixedBinCrate;
-#[derive(SessionDiagnostic)]
-#[diag(interface::mixed_proc_macro_crate)]
+#[derive(Diagnostic)]
+#[diag(interface_mixed_proc_macro_crate)]
pub struct MixedProcMacroCrate;
-#[derive(SessionDiagnostic)]
-#[diag(interface::proc_macro_doc_without_arg)]
+#[derive(Diagnostic)]
+#[diag(interface_proc_macro_doc_without_arg)]
pub struct ProcMacroDocWithoutArg;
-#[derive(SessionDiagnostic)]
-#[diag(interface::error_writing_dependencies)]
+#[derive(Diagnostic)]
+#[diag(interface_error_writing_dependencies)]
pub struct ErrorWritingDependencies<'a> {
pub path: &'a Path,
pub error: io::Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::input_file_would_be_overwritten)]
+#[derive(Diagnostic)]
+#[diag(interface_input_file_would_be_overwritten)]
pub struct InputFileWouldBeOverWritten<'a> {
pub path: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::generated_file_conflicts_with_directory)]
+#[derive(Diagnostic)]
+#[diag(interface_generated_file_conflicts_with_directory)]
pub struct GeneratedFileConflictsWithDirectory<'a> {
pub input_path: &'a Path,
pub dir_path: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::temps_dir_error)]
+#[derive(Diagnostic)]
+#[diag(interface_temps_dir_error)]
pub struct TempsDirError;
-#[derive(SessionDiagnostic)]
-#[diag(interface::out_dir_error)]
+#[derive(Diagnostic)]
+#[diag(interface_out_dir_error)]
pub struct OutDirError;
-#[derive(SessionDiagnostic)]
-#[diag(interface::cant_emit_mir)]
+#[derive(Diagnostic)]
+#[diag(interface_cant_emit_mir)]
pub struct CantEmitMIR {
pub error: io::Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::rustc_error_fatal)]
+#[derive(Diagnostic)]
+#[diag(interface_rustc_error_fatal)]
pub struct RustcErrorFatal {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::rustc_error_unexpected_annotation)]
+#[derive(Diagnostic)]
+#[diag(interface_rustc_error_unexpected_annotation)]
pub struct RustcErrorUnexpectedAnnotation {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(interface::failed_writing_file)]
+#[derive(Diagnostic)]
+#[diag(interface_failed_writing_file)]
pub struct FailedWritingFile<'a> {
pub path: &'a Path,
pub error: io::Error,
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 949bd02ad..89aaa0b95 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -17,7 +17,7 @@ use rustc_session::config::{self, CheckCfg, ErrorOutputType, Input, OutputFilena
use rustc_session::early_error;
use rustc_session::lint;
use rustc_session::parse::{CrateConfig, ParseSess};
-use rustc_session::{DiagnosticOutput, Session};
+use rustc_session::Session;
use rustc_span::source_map::{FileLoader, FileName};
use rustc_span::symbol::sym;
use std::path::PathBuf;
@@ -25,7 +25,10 @@ use std::result;
pub type Result<T> = result::Result<T, ErrorGuaranteed>;
-/// Represents a compiler session.
+/// Represents a compiler session. Note that every `Compiler` contains a
+/// `Session`, but `Compiler` also contains some things that cannot be in
+/// `Session`, due to `Session` being in a crate that has many fewer
+/// dependencies than this crate.
///
/// Can be used to run `rustc_interface` queries.
/// Created by passing [`Config`] to [`run_compiler`].
@@ -247,7 +250,6 @@ pub struct Config {
pub output_dir: Option<PathBuf>,
pub output_file: Option<PathBuf>,
pub file_loader: Option<Box<dyn FileLoader + Send + Sync>>,
- pub diagnostic_output: DiagnosticOutput,
pub lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -276,59 +278,6 @@ pub struct Config {
pub registry: Registry,
}
-pub fn create_compiler_and_run<R>(config: Config, f: impl FnOnce(&Compiler) -> R) -> R {
- crate::callbacks::setup_callbacks();
-
- let registry = &config.registry;
- let (mut sess, codegen_backend) = util::create_session(
- config.opts,
- config.crate_cfg,
- config.crate_check_cfg,
- config.diagnostic_output,
- config.file_loader,
- config.input_path.clone(),
- config.lint_caps,
- config.make_codegen_backend,
- registry.clone(),
- );
-
- if let Some(parse_sess_created) = config.parse_sess_created {
- parse_sess_created(
- &mut Lrc::get_mut(&mut sess)
- .expect("create_session() should never share the returned session")
- .parse_sess,
- );
- }
-
- let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
-
- let compiler = Compiler {
- sess,
- codegen_backend,
- input: config.input,
- input_path: config.input_path,
- output_dir: config.output_dir,
- output_file: config.output_file,
- temps_dir,
- register_lints: config.register_lints,
- override_queries: config.override_queries,
- };
-
- rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
- let r = {
- let _sess_abort_error = OnDrop(|| {
- compiler.sess.finish_diagnostics(registry);
- });
-
- f(&compiler)
- };
-
- let prof = compiler.sess.prof.clone();
- prof.generic_activity("drop_compiler").run(move || drop(compiler));
- r
- })
-}
-
// JUSTIFICATION: before session exists, only config
#[allow(rustc::bad_opt_access)]
pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R {
@@ -336,7 +285,53 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
util::run_in_thread_pool_with_globals(
config.opts.edition,
config.opts.unstable_opts.threads,
- || create_compiler_and_run(config, f),
+ || {
+ crate::callbacks::setup_callbacks();
+
+ let registry = &config.registry;
+ let (mut sess, codegen_backend) = util::create_session(
+ config.opts,
+ config.crate_cfg,
+ config.crate_check_cfg,
+ config.file_loader,
+ config.input_path.clone(),
+ config.lint_caps,
+ config.make_codegen_backend,
+ registry.clone(),
+ );
+
+ if let Some(parse_sess_created) = config.parse_sess_created {
+ parse_sess_created(&mut sess.parse_sess);
+ }
+
+ let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o));
+
+ let compiler = Compiler {
+ sess: Lrc::new(sess),
+ codegen_backend: Lrc::new(codegen_backend),
+ input: config.input,
+ input_path: config.input_path,
+ output_dir: config.output_dir,
+ output_file: config.output_file,
+ temps_dir,
+ register_lints: config.register_lints,
+ override_queries: config.override_queries,
+ };
+
+ rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || {
+ let r = {
+ let _sess_abort_error = OnDrop(|| {
+ compiler.sess.finish_diagnostics(registry);
+ });
+
+ f(&compiler)
+ };
+
+ let prof = compiler.sess.prof.clone();
+ prof.generic_activity("drop_compiler").run(move || drop(compiler));
+ r
+ })
+ },
)
}
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index 41cd7b0e9..a41a749ee 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(box_patterns)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(internal_output_capture)]
#![feature(thread_spawn_unchecked)]
#![feature(once_cell)]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index c41b154c3..7f1d21bf1 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -16,7 +16,6 @@ use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal};
use rustc_errors::{ErrorGuaranteed, PResult};
use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand};
use rustc_hir::def_id::StableCrateId;
-use rustc_hir::definitions::Definitions;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore};
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
@@ -30,14 +29,13 @@ use rustc_plugin_impl as plugin;
use rustc_query_impl::{OnDiskCache, Queries as TcxQueries};
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType};
-use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, MetadataLoaderDyn};
+use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn};
use rustc_session::output::filename_for_input;
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::FileName;
use rustc_trait_selection::traits;
-use rustc_typeck as typeck;
use std::any::Any;
use std::cell::RefCell;
@@ -136,10 +134,7 @@ mod boxed_resolver {
f((&mut *resolver).as_mut().unwrap())
}
- pub fn to_resolver_outputs(
- resolver: Rc<RefCell<BoxedResolver>>,
- ) -> (Definitions, Box<CrateStoreDyn>, ty::ResolverOutputs, ty::ResolverAstLowering)
- {
+ pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ty::ResolverOutputs {
match Rc::try_unwrap(resolver) {
Ok(resolver) => {
let mut resolver = resolver.into_inner();
@@ -736,11 +731,11 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
rustc_mir_transform::provide(providers);
rustc_monomorphize::provide(providers);
rustc_privacy::provide(providers);
- typeck::provide(providers);
+ rustc_hir_analysis::provide(providers);
+ rustc_hir_typeck::provide(providers);
ty::provide(providers);
traits::provide(providers);
rustc_passes::provide(providers);
- rustc_resolve::provide(providers);
rustc_traits::provide(providers);
rustc_ty_utils::provide(providers);
rustc_metadata::provide(providers);
@@ -789,8 +784,7 @@ pub fn create_global_ctxt<'tcx>(
// incr. comp. yet.
dep_graph.assert_ignored();
- let (definitions, cstore, resolver_outputs, resolver_for_lowering) =
- BoxedResolver::to_resolver_outputs(resolver);
+ let resolver_outputs = BoxedResolver::to_resolver_outputs(resolver);
let sess = &compiler.session();
let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);
@@ -817,10 +811,7 @@ pub fn create_global_ctxt<'tcx>(
lint_store,
arena,
hir_arena,
- definitions,
- cstore,
resolver_outputs,
- resolver_for_lowering,
krate,
dep_graph,
queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
@@ -880,7 +871,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
});
// passes are timed inside typeck
- typeck::check_crate(tcx)?;
+ rustc_hir_analysis::check_crate(tcx)?;
sess.time("misc_checking_2", || {
parallel!(
@@ -936,7 +927,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
sess.time("misc_checking_3", || {
parallel!(
{
- tcx.ensure().privacy_access_levels(());
+ tcx.ensure().effective_visibilities(());
parallel!(
{
diff --git a/compiler/rustc_interface/src/proc_macro_decls.rs b/compiler/rustc_interface/src/proc_macro_decls.rs
index 5371c513d..4c236c693 100644
--- a/compiler/rustc_interface/src/proc_macro_decls.rs
+++ b/compiler/rustc_interface/src/proc_macro_decls.rs
@@ -1,4 +1,3 @@
-use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::TyCtxt;
@@ -10,7 +9,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
for id in tcx.hir().items() {
let attrs = finder.tcx.hir().attrs(id.hir_id());
if finder.tcx.sess.contains_name(attrs, sym::rustc_proc_macro_decls) {
- finder.decls = Some(id.def_id);
+ finder.decls = Some(id.owner_id.def_id);
}
}
@@ -19,7 +18,7 @@ fn proc_macro_decls_static(tcx: TyCtxt<'_>, (): ()) -> Option<LocalDefId> {
struct Finder<'tcx> {
tcx: TyCtxt<'tcx>,
- decls: Option<hir::def_id::LocalDefId>,
+ decls: Option<LocalDefId>,
}
pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 6c725a01b..91d180e1e 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -246,6 +246,10 @@ impl<'tcx> Queries<'tcx> {
// Don't do code generation if there were any errors
self.session().compile_status()?;
+ // If we have any delayed bugs, for example because we created TyKind::Error earlier,
+ // it's likely that codegen will only cause more ICEs, obscuring the original problem
+ self.session().diagnostic().flush_delayed();
+
// Hook for UI tests.
Self::check_for_rustc_errors_attr(tcx);
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index c7615a577..eb8e65a6d 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -17,7 +17,7 @@ use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, Switc
use rustc_session::lint::Level;
use rustc_session::search_paths::SearchPath;
use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
+use rustc_session::{build_session, getopts, Session};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
use rustc_span::symbol::sym;
use rustc_span::SourceFileHashAlgorithm;
@@ -40,16 +40,7 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options
fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
let registry = registry::Registry::new(&[]);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
- let sess = build_session(
- sessopts,
- None,
- None,
- registry,
- DiagnosticOutput::Default,
- Default::default(),
- None,
- None,
- );
+ let sess = build_session(sessopts, None, None, registry, Default::default(), None, None);
(sess, cfg)
}
@@ -540,7 +531,7 @@ fn test_codegen_options_tracking_hash() {
}
// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
untracked!(ar, String::from("abc"));
untracked!(codegen_units, Some(42));
untracked!(default_linker_libraries, true);
@@ -556,6 +547,7 @@ fn test_codegen_options_tracking_hash() {
untracked!(rpath, true);
untracked!(save_temps, true);
untracked!(strip, Strip::Debuginfo);
+ // tidy-alphabetical-end
macro_rules! tracked {
($name: ident, $non_default_value: expr) => {
@@ -567,7 +559,7 @@ fn test_codegen_options_tracking_hash() {
}
// Make sure that changing a [TRACKED] option changes the hash.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
tracked!(code_model, Some(CodeModel::Large));
tracked!(control_flow_guard, CFGuard::Checks);
tracked!(debug_assertions, Some(true));
@@ -577,8 +569,8 @@ fn test_codegen_options_tracking_hash() {
tracked!(force_unwind_tables, Some(true));
tracked!(inline_threshold, Some(0xf007ba11));
tracked!(instrument_coverage, Some(InstrumentCoverage::All));
- tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
tracked!(link_dead_code, Some(true));
+ tracked!(linker_plugin_lto, LinkerPluginLto::LinkerPluginAuto);
tracked!(llvm_args, vec![String::from("1"), String::from("2")]);
tracked!(lto, LtoCli::Fat);
tracked!(metadata, vec![String::from("A"), String::from("B")]);
@@ -599,6 +591,7 @@ fn test_codegen_options_tracking_hash() {
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
tracked!(target_cpu, Some(String::from("abc")));
tracked!(target_feature, String::from("all the features, all of them"));
+ // tidy-alphabetical-end
}
#[test]
@@ -619,12 +612,13 @@ fn test_top_level_options_tracked_no_crate() {
}
// Make sure that changing a [TRACKED_NO_CRATE_HASH] option leaves the crate hash unchanged but changes the incremental hash.
- // This list is in alphabetical order.
- tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
+ // tidy-alphabetical-start
tracked!(
real_rust_source_base_dir,
Some("/home/bors/rust/.rustup/toolchains/nightly/lib/rustlib/src/rust".into())
);
+ tracked!(remap_path_prefix, vec![("/home/bors/rust".into(), "src".into())]);
+ // tidy-alphabetical-end
}
#[test]
@@ -641,7 +635,7 @@ fn test_unstable_options_tracking_hash() {
}
// Make sure that changing an [UNTRACKED] option leaves the hash unchanged.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
untracked!(assert_incr_state, Some(String::from("loaded")));
untracked!(deduplicate_diagnostics, false);
untracked!(dep_tasks, true);
@@ -654,6 +648,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(dump_mir_dir, String::from("abc"));
untracked!(dump_mir_exclude_pass_number, true);
untracked!(dump_mir_graphviz, true);
+ untracked!(dylib_lto, true);
untracked!(emit_stack_sizes, true);
untracked!(future_incompat_test, true);
untracked!(hir_stats, true);
@@ -678,12 +673,12 @@ fn test_unstable_options_tracking_hash() {
untracked!(perf_stats, true);
// `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
- untracked!(profile_closures, true);
untracked!(print_llvm_passes, true);
untracked!(print_mono_items, Some(String::from("abc")));
untracked!(print_type_sizes, true);
untracked!(proc_macro_backtrace, true);
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));
@@ -692,7 +687,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(span_free_formats, true);
untracked!(temps_dir, Some(String::from("abc")));
untracked!(threads, 99);
- untracked!(time, true);
untracked!(time_llvm_passes, true);
untracked!(time_passes, true);
untracked!(trace_macros, true);
@@ -702,6 +696,7 @@ fn test_unstable_options_tracking_hash() {
untracked!(unstable_options, true);
untracked!(validate_mir, true);
untracked!(verbose, true);
+ // tidy-alphabetical-end
macro_rules! tracked {
($name: ident, $non_default_value: expr) => {
@@ -713,7 +708,7 @@ fn test_unstable_options_tracking_hash() {
}
// Make sure that changing a [TRACKED] option changes the hash.
- // This list is in alphabetical order.
+ // tidy-alphabetical-start
tracked!(allow_features, Some(vec![String::from("lang_items")]));
tracked!(always_encode_mir, true);
tracked!(asm_comments, true);
@@ -734,10 +729,10 @@ fn test_unstable_options_tracking_hash() {
tracked!(debug_macros, true);
tracked!(dep_info_omit_d_target, true);
tracked!(drop_tracking, true);
- tracked!(export_executable_symbols, true);
tracked!(dual_proc_macros, true);
tracked!(dwarf_version, Some(5));
tracked!(emit_thin_lto, false);
+ tracked!(export_executable_symbols, true);
tracked!(fewer_names, Some(true));
tracked!(force_unstable_if_unmarked, true);
tracked!(fuel, Some(("abc".to_string(), 99)));
@@ -758,11 +753,10 @@ fn test_unstable_options_tracking_hash() {
tracked!(mir_opt_level, Some(4));
tracked!(move_size_limit, Some(4096));
tracked!(mutable_noalias, Some(true));
- tracked!(new_llvm_pass_manager, Some(true));
tracked!(no_generate_arange_section, true);
tracked!(no_link, true);
- tracked!(no_unique_section_names, true);
tracked!(no_profiler_runtime, true);
+ tracked!(no_unique_section_names, true);
tracked!(oom, OomStrategy::Panic);
tracked!(osx_rpath_install_name, true);
tracked!(packed_bundled_libs, true);
@@ -775,8 +769,8 @@ fn test_unstable_options_tracking_hash() {
tracked!(print_fuel, Some("abc".to_string()));
tracked!(profile, true);
tracked!(profile_emit, Some(PathBuf::from("abc")));
- tracked!(profiler_runtime, "abc".to_string());
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
+ tracked!(profiler_runtime, "abc".to_string());
tracked!(relax_elf_relocations, Some(true));
tracked!(relro_level, Some(RelroLevel::Full));
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));
@@ -805,6 +799,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(verify_llvm_ir, true);
tracked!(virtual_function_elimination, true);
tracked!(wasi_exec_model, Some(WasiExecModel::Reactor));
+ // tidy-alphabetical-end
macro_rules! tracked_no_crate_hash {
($name: ident, $non_default_value: expr) => {
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index f7e70d355..519b8a7fc 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -3,22 +3,15 @@ use libloading::Library;
use rustc_ast as ast;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-#[cfg(parallel_compiler)]
-use rustc_data_structures::jobserver;
-use rustc_data_structures::sync::Lrc;
use rustc_errors::registry::Registry;
-#[cfg(parallel_compiler)]
-use rustc_middle::ty::tls;
use rustc_parse::validate_attr;
-#[cfg(parallel_compiler)]
-use rustc_query_impl::{QueryContext, QueryCtxt};
use rustc_session as session;
use rustc_session::config::CheckCfg;
use rustc_session::config::{self, CrateType};
use rustc_session::config::{ErrorOutputType, Input, OutputFilenames};
use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::CrateConfig;
-use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
+use rustc_session::{early_error, filesearch, output, Session};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
use rustc_span::source_map::FileLoader;
@@ -26,8 +19,6 @@ use rustc_span::symbol::{sym, Symbol};
use std::env;
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
use std::mem;
-#[cfg(not(parallel_compiler))]
-use std::panic;
use std::path::{Path, PathBuf};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::OnceLock;
@@ -65,7 +56,6 @@ pub fn create_session(
sopts: config::Options,
cfg: FxHashSet<(String, Option<String>)>,
check_cfg: CheckCfg,
- diagnostic_output: DiagnosticOutput,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
input_path: Option<PathBuf>,
lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -73,7 +63,7 @@ pub fn create_session(
Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>,
>,
descriptions: Registry,
-) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
+) -> (Session, Box<dyn CodegenBackend>) {
let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend {
make_codegen_backend(&sopts)
} else {
@@ -104,7 +94,6 @@ pub fn create_session(
input_path,
bundle,
descriptions,
- diagnostic_output,
lint_caps,
file_loader,
target_override,
@@ -121,7 +110,7 @@ pub fn create_session(
sess.parse_sess.config = cfg;
sess.parse_sess.check_config = check_cfg;
- (Lrc::new(sess), Lrc::new(codegen_backend))
+ (sess, codegen_backend)
}
const STACK_SIZE: usize = 8 * 1024 * 1024;
@@ -132,79 +121,86 @@ fn get_stack_size() -> Option<usize> {
env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE)
}
-/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need
-/// for `'static` bounds.
-#[cfg(not(parallel_compiler))]
-fn scoped_thread<F: FnOnce() -> R + Send, R: Send>(cfg: thread::Builder, f: F) -> R {
- // SAFETY: join() is called immediately, so any closure captures are still
- // alive.
- match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() {
- Ok(v) => v,
- Err(e) => panic::resume_unwind(e),
- }
-}
-
#[cfg(not(parallel_compiler))]
-pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
_threads: usize,
f: F,
) -> R {
- let mut cfg = thread::Builder::new().name("rustc".to_string());
-
+ // The "thread pool" is a single spawned thread in the non-parallel
+ // compiler. We run on a spawned thread instead of the main thread (a) to
+ // provide control over the stack size, and (b) to increase similarity with
+ // the parallel compiler, in particular to ensure there is no accidental
+ // sharing of data between the main thread and the compilation thread
+ // (which might cause problems for the parallel compiler).
+ let mut builder = thread::Builder::new().name("rustc".to_string());
if let Some(size) = get_stack_size() {
- cfg = cfg.stack_size(size);
+ builder = builder.stack_size(size);
}
- let main_handler = move || rustc_span::create_session_globals_then(edition, f);
-
- scoped_thread(cfg, main_handler)
-}
-
-/// Creates a new thread and forwards information in thread locals to it.
-/// The new thread runs the deadlock handler.
-/// Must only be called when a deadlock is about to happen.
-#[cfg(parallel_compiler)]
-unsafe fn handle_deadlock() {
- let registry = rustc_rayon_core::Registry::current();
-
- let query_map = tls::with(|tcx| {
- QueryCtxt::from_tcx(tcx)
- .try_collect_active_jobs()
- .expect("active jobs shouldn't be locked in deadlock handler")
- });
- thread::spawn(move || rustc_query_impl::deadlock(query_map, &registry));
+ // We build the session globals and run `f` on the spawned thread, because
+ // `SessionGlobals` does not impl `Send` in the non-parallel compiler.
+ thread::scope(|s| {
+ // `unwrap` is ok here because `spawn_scoped` only panics if the thread
+ // name contains null bytes.
+ let r = builder
+ .spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f))
+ .unwrap()
+ .join();
+
+ match r {
+ Ok(v) => v,
+ Err(e) => std::panic::resume_unwind(e),
+ }
+ })
}
#[cfg(parallel_compiler)]
-pub fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
+pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
edition: Edition,
threads: usize,
f: F,
) -> R {
- let mut config = rayon::ThreadPoolBuilder::new()
+ use rustc_data_structures::jobserver;
+ use rustc_middle::ty::tls;
+ use rustc_query_impl::{deadlock, QueryContext, QueryCtxt};
+
+ let mut builder = rayon::ThreadPoolBuilder::new()
.thread_name(|_| "rustc".to_string())
.acquire_thread_handler(jobserver::acquire_thread)
.release_thread_handler(jobserver::release_thread)
.num_threads(threads)
- .deadlock_handler(|| unsafe { handle_deadlock() });
-
+ .deadlock_handler(|| {
+ // On deadlock, creates a new thread and forwards information in thread
+ // locals to it. The new thread runs the deadlock handler.
+ let query_map = tls::with(|tcx| {
+ QueryCtxt::from_tcx(tcx)
+ .try_collect_active_jobs()
+ .expect("active jobs shouldn't be locked in deadlock handler")
+ });
+ let registry = rustc_rayon_core::Registry::current();
+ thread::spawn(move || deadlock(query_map, &registry));
+ });
if let Some(size) = get_stack_size() {
- config = config.stack_size(size);
+ builder = builder.stack_size(size);
}
- let with_pool = move |pool: &rayon::ThreadPool| pool.install(f);
-
+ // We create the session globals on the main thread, then create the thread
+ // pool. Upon creation, each worker thread created gets a copy of the
+ // session globals in TLS. This is possible because `SessionGlobals` impls
+ // `Send` in the parallel compiler.
rustc_span::create_session_globals_then(edition, || {
rustc_span::with_session_globals(|session_globals| {
- // The main handler runs for each Rayon worker thread and sets up
- // the thread local rustc uses. `session_globals` is captured and set
- // on the new threads.
- let main_handler = move |thread: rayon::ThreadBuilder| {
- rustc_span::set_session_globals_then(session_globals, || thread.run())
- };
-
- config.build_scoped(main_handler, with_pool).unwrap()
+ builder
+ .build_scoped(
+ // Initialize each new worker thread when created.
+ move |thread: rayon::ThreadBuilder| {
+ rustc_span::set_session_globals_then(session_globals, || thread.run())
+ },
+ // Run `f` on the first thread in the thread pool.
+ move |pool: &rayon::ThreadPool| pool.install(f),
+ )
+ .unwrap()
})
})
}
diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml
index 35af11053..ad685c2ad 100644
--- a/compiler/rustc_lexer/Cargo.toml
+++ b/compiler/rustc_lexer/Cargo.toml
@@ -12,7 +12,6 @@ Rust lexer used by rustc. No stability guarantees are provided.
# Note: do not remove this blank `[lib]` section.
# This will be used when publishing this crate as `rustc-ap-rustc_lexer`.
[lib]
-doctest = false
# Note that this crate purposefully does not depend on other rustc crates
[dependencies]
diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs
index 21557a9c8..eceef5980 100644
--- a/compiler/rustc_lexer/src/cursor.rs
+++ b/compiler/rustc_lexer/src/cursor.rs
@@ -4,8 +4,8 @@ use std::str::Chars;
///
/// Next characters can be peeked via `first` method,
/// and position can be shifted forward via `bump` method.
-pub(crate) struct Cursor<'a> {
- initial_len: usize,
+pub struct Cursor<'a> {
+ len_remaining: usize,
/// Iterator over chars. Slightly faster than a &str.
chars: Chars<'a>,
#[cfg(debug_assertions)]
@@ -15,9 +15,9 @@ pub(crate) struct Cursor<'a> {
pub(crate) const EOF_CHAR: char = '\0';
impl<'a> Cursor<'a> {
- pub(crate) fn new(input: &'a str) -> Cursor<'a> {
+ pub fn new(input: &'a str) -> Cursor<'a> {
Cursor {
- initial_len: input.len(),
+ len_remaining: input.len(),
chars: input.chars(),
#[cfg(debug_assertions)]
prev: EOF_CHAR,
@@ -61,13 +61,13 @@ impl<'a> Cursor<'a> {
}
/// Returns amount of already consumed symbols.
- pub(crate) fn len_consumed(&self) -> u32 {
- (self.initial_len - self.chars.as_str().len()) as u32
+ pub(crate) fn pos_within_token(&self) -> u32 {
+ (self.len_remaining - self.chars.as_str().len()) as u32
}
/// Resets the number of bytes consumed to 0.
- pub(crate) fn reset_len_consumed(&mut self) {
- self.initial_len = self.chars.as_str().len();
+ pub(crate) fn reset_pos_within_token(&mut self) {
+ self.len_remaining = self.chars.as_str().len();
}
/// Moves to the next character.
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index a79c98264..51515976e 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -29,9 +29,11 @@ pub mod unescape;
#[cfg(test)]
mod tests;
+pub use crate::cursor::Cursor;
+
use self::LiteralKind::*;
use self::TokenKind::*;
-use crate::cursor::{Cursor, EOF_CHAR};
+use crate::cursor::EOF_CHAR;
use std::convert::TryFrom;
/// Parsed token.
@@ -55,29 +57,42 @@ pub enum TokenKind {
// Multi-char tokens:
/// "// comment"
LineComment { doc_style: Option<DocStyle> },
+
/// `/* block comment */`
///
- /// Block comments can be recursive, so the sequence like `/* /* */`
+ /// Block comments can be recursive, so a sequence like `/* /* */`
/// will not be considered terminated and will result in a parsing error.
BlockComment { doc_style: Option<DocStyle>, terminated: bool },
- /// Any whitespace characters sequence.
+
+ /// Any whitespace character sequence.
Whitespace,
+
/// "ident" or "continue"
- /// At this step keywords are also considered identifiers.
+ ///
+ /// At this step, keywords are also considered identifiers.
Ident,
+
/// Like the above, but containing invalid unicode codepoints.
InvalidIdent,
+
/// "r#ident"
RawIdent,
- /// An unknown prefix like `foo#`, `foo'`, `foo"`. Note that only the
+
+ /// 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.
+
+ /// Examples: `"12_u8"`, `"1.0e-40"`, `b"123`.
+ ///
+ /// See [LiteralKind] for more details.
Literal { kind: LiteralKind, suffix_start: u32 },
+
/// "'a"
Lifetime { starts_with_number: bool },
@@ -139,6 +154,9 @@ pub enum TokenKind {
/// Unknown token, not expected by the lexer, e.g. "№"
Unknown,
+
+ /// End of input.
+ Eof,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -219,13 +237,6 @@ pub fn strip_shebang(input: &str) -> Option<usize> {
None
}
-/// Parses the first token from the provided input string.
-#[inline]
-pub fn first_token(input: &str) -> Token {
- debug_assert!(!input.is_empty());
- Cursor::new(input).advance_token()
-}
-
/// Validates a raw string literal. Used for getting more information about a
/// problem with a `RawStr`/`RawByteStr` with a `None` field.
#[inline]
@@ -243,12 +254,8 @@ pub fn validate_raw_str(input: &str, prefix_len: u32) -> Result<(), RawStrError>
pub fn tokenize(input: &str) -> impl Iterator<Item = Token> + '_ {
let mut cursor = Cursor::new(input);
std::iter::from_fn(move || {
- if cursor.is_eof() {
- None
- } else {
- cursor.reset_len_consumed();
- Some(cursor.advance_token())
- }
+ let token = cursor.advance_token();
+ if token.kind != TokenKind::Eof { Some(token) } else { None }
})
}
@@ -311,8 +318,11 @@ pub fn is_ident(string: &str) -> bool {
impl Cursor<'_> {
/// Parses a token from the input string.
- fn advance_token(&mut self) -> Token {
- let first_char = self.bump().unwrap();
+ pub fn advance_token(&mut self) -> Token {
+ let first_char = match self.bump() {
+ Some(c) => c,
+ None => return Token::new(TokenKind::Eof, 0),
+ };
let token_kind = match first_char {
// Slash, comment or block comment.
'/' => match self.first() {
@@ -329,7 +339,7 @@ impl Cursor<'_> {
('#', c1) if is_id_start(c1) => self.raw_ident(),
('#', _) | ('"', _) => {
let res = self.raw_double_quoted_string(1);
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if res.is_ok() {
self.eat_literal_suffix();
}
@@ -344,7 +354,7 @@ impl Cursor<'_> {
('\'', _) => {
self.bump();
let terminated = self.single_quoted_string();
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if terminated {
self.eat_literal_suffix();
}
@@ -354,7 +364,7 @@ impl Cursor<'_> {
('"', _) => {
self.bump();
let terminated = self.double_quoted_string();
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if terminated {
self.eat_literal_suffix();
}
@@ -364,7 +374,7 @@ impl Cursor<'_> {
('r', '"') | ('r', '#') => {
self.bump();
let res = self.raw_double_quoted_string(2);
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if res.is_ok() {
self.eat_literal_suffix();
}
@@ -381,7 +391,7 @@ impl Cursor<'_> {
// Numeric literal.
c @ '0'..='9' => {
let literal_kind = self.number(c);
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
self.eat_literal_suffix();
TokenKind::Literal { kind: literal_kind, suffix_start }
}
@@ -420,7 +430,7 @@ impl Cursor<'_> {
// String literal.
'"' => {
let terminated = self.double_quoted_string();
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if terminated {
self.eat_literal_suffix();
}
@@ -433,7 +443,9 @@ impl Cursor<'_> {
}
_ => Unknown,
};
- Token::new(token_kind, self.len_consumed())
+ let res = Token::new(token_kind, self.pos_within_token());
+ self.reset_pos_within_token();
+ res
}
fn line_comment(&mut self) -> TokenKind {
@@ -618,7 +630,7 @@ impl Cursor<'_> {
if !can_be_a_lifetime {
let terminated = self.single_quoted_string();
- let suffix_start = self.len_consumed();
+ let suffix_start = self.pos_within_token();
if terminated {
self.eat_literal_suffix();
}
@@ -643,7 +655,7 @@ impl Cursor<'_> {
if self.first() == '\'' {
self.bump();
let kind = Char { terminated: true };
- Literal { kind, suffix_start: self.len_consumed() }
+ Literal { kind, suffix_start: self.pos_within_token() }
} else {
Lifetime { starts_with_number }
}
@@ -724,7 +736,7 @@ impl Cursor<'_> {
fn raw_string_unvalidated(&mut self, prefix_len: u32) -> Result<u32, RawStrError> {
debug_assert!(self.prev() == 'r');
- let start_pos = self.len_consumed();
+ let start_pos = self.pos_within_token();
let mut possible_terminator_offset = None;
let mut max_hashes = 0;
@@ -778,7 +790,7 @@ impl Cursor<'_> {
// Keep track of possible terminators to give a hint about
// where there might be a missing terminator
possible_terminator_offset =
- Some(self.len_consumed() - start_pos - n_end_hashes + prefix_len);
+ Some(self.pos_within_token() - start_pos - n_end_hashes + prefix_len);
max_hashes = n_end_hashes;
}
}
diff --git a/compiler/rustc_lexer/src/unescape.rs b/compiler/rustc_lexer/src/unescape.rs
index 3da6bc146..8f64b5f51 100644
--- a/compiler/rustc_lexer/src/unescape.rs
+++ b/compiler/rustc_lexer/src/unescape.rs
@@ -93,7 +93,7 @@ where
// NOTE: Raw strings do not perform any explicit character escaping, here we
// only translate CRLF to LF and produce errors on bare CR.
Mode::RawStr | Mode::RawByteStr => {
- unescape_raw_str_or_byte_str(literal_text, mode, callback)
+ unescape_raw_str_or_raw_byte_str(literal_text, mode, callback)
}
}
}
@@ -105,7 +105,7 @@ pub fn unescape_byte_literal<F>(literal_text: &str, mode: Mode, callback: &mut F
where
F: FnMut(Range<usize>, Result<u8, EscapeError>),
{
- assert!(mode.is_bytes());
+ debug_assert!(mode.is_bytes());
unescape_literal(literal_text, mode, &mut |range, result| {
callback(range, result.map(byte_from_char));
})
@@ -129,7 +129,7 @@ pub fn unescape_byte(literal_text: &str) -> Result<u8, (usize, EscapeError)> {
}
/// What kind of literal do we parse.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Mode {
Char,
Str,
@@ -140,17 +140,13 @@ pub enum Mode {
}
impl Mode {
- pub fn in_single_quotes(self) -> bool {
+ pub fn in_double_quotes(self) -> bool {
match self {
- Mode::Char | Mode::Byte => true,
- Mode::Str | Mode::ByteStr | Mode::RawStr | Mode::RawByteStr => false,
+ Mode::Str | Mode::ByteStr | Mode::RawStr | Mode::RawByteStr => true,
+ Mode::Char | Mode::Byte => false,
}
}
- pub fn in_double_quotes(self) -> bool {
- !self.in_single_quotes()
- }
-
pub fn is_bytes(self) -> bool {
match self {
Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true,
@@ -184,7 +180,7 @@ fn scan_escape(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
let value = hi * 16 + lo;
- // For a byte literal verify that it is within ASCII range.
+ // For a non-byte literal verify that it is within ASCII range.
if !mode.is_bytes() && !is_ascii(value) {
return Err(EscapeError::OutOfRangeHexEscape);
}
@@ -263,6 +259,7 @@ fn ascii_check(first_char: char, mode: Mode) -> Result<char, EscapeError> {
}
fn unescape_char_or_byte(chars: &mut Chars<'_>, mode: Mode) -> Result<char, EscapeError> {
+ debug_assert!(mode == Mode::Char || mode == Mode::Byte);
let first_char = chars.next().ok_or(EscapeError::ZeroChars)?;
let res = match first_char {
'\\' => scan_escape(chars, mode),
@@ -282,7 +279,7 @@ fn unescape_str_or_byte_str<F>(src: &str, mode: Mode, callback: &mut F)
where
F: FnMut(Range<usize>, Result<char, EscapeError>),
{
- assert!(mode.in_double_quotes());
+ debug_assert!(mode == Mode::Str || mode == Mode::ByteStr);
let initial_len = src.len();
let mut chars = src.chars();
while let Some(first_char) = chars.next() {
@@ -344,11 +341,11 @@ where
/// sequence of characters or errors.
/// NOTE: Raw strings do not perform any explicit character escaping, here we
/// only translate CRLF to LF and produce errors on bare CR.
-fn unescape_raw_str_or_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
+fn unescape_raw_str_or_raw_byte_str<F>(literal_text: &str, mode: Mode, callback: &mut F)
where
F: FnMut(Range<usize>, Result<char, EscapeError>),
{
- assert!(mode.in_double_quotes());
+ debug_assert!(mode == Mode::RawStr || mode == Mode::RawByteStr);
let initial_len = literal_text.len();
let mut chars = literal_text.chars();
@@ -368,7 +365,7 @@ where
fn byte_from_char(c: char) -> u8 {
let res = c as u32;
- assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
+ debug_assert!(res <= u8::MAX as u32, "guaranteed because of Mode::ByteStr");
res as u8
}
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 7c0f2c440..abe61406c 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2021"
[dependencies]
tracing = "0.1"
-unicode-security = "0.0.5"
+unicode-security = "0.1.0"
rustc_middle = { path = "../rustc_middle" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
rustc_attr = { path = "../rustc_attr" }
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index b97f8acb3..abebc533c 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -118,37 +118,41 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
// to an array or to a slice.
_ => bug!("array type coerced to something other than array or slice"),
};
- cx.struct_span_lint(ARRAY_INTO_ITER, call.ident.span, |lint| {
- let mut diag = lint.build(fluent::lint::array_into_iter);
- diag.set_arg("target", target);
- diag.span_suggestion(
- call.ident.span,
- fluent::lint::use_iter_suggestion,
- "iter",
- Applicability::MachineApplicable,
- );
- if self.for_expr_span == expr.span {
+ cx.struct_span_lint(
+ ARRAY_INTO_ITER,
+ call.ident.span,
+ fluent::lint_array_into_iter,
+ |diag| {
+ diag.set_arg("target", target);
diag.span_suggestion(
- receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
- fluent::lint::remove_into_iter_suggestion,
- "",
- Applicability::MaybeIncorrect,
+ call.ident.span,
+ fluent::use_iter_suggestion,
+ "iter",
+ Applicability::MachineApplicable,
);
- } else if receiver_ty.is_array() {
- diag.multipart_suggestion(
- fluent::lint::use_explicit_into_iter_suggestion,
- vec![
- (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
- (
- receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
- ")".into(),
- ),
- ],
- Applicability::MaybeIncorrect,
- );
- }
- diag.emit();
- })
+ if self.for_expr_span == expr.span {
+ diag.span_suggestion(
+ receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
+ fluent::remove_into_iter_suggestion,
+ "",
+ Applicability::MaybeIncorrect,
+ );
+ } else if receiver_ty.is_array() {
+ diag.multipart_suggestion(
+ fluent::use_explicit_into_iter_suggestion,
+ vec![
+ (expr.span.shrink_to_lo(), "IntoIterator::into_iter(".into()),
+ (
+ receiver_arg.span.shrink_to_hi().to(expr.span.shrink_to_hi()),
+ ")".into(),
+ ),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ }
+ diag
+ },
+ )
}
}
}
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 0ff2ef5cd..d425adf47 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -33,8 +33,8 @@ 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, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
- LintDiagnosticBuilder, MultiSpan,
+ fluent, Applicability, DelayDm, Diagnostic, DiagnosticBuilder, DiagnosticMessage,
+ DiagnosticStyledString, MultiSpan,
};
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
use rustc_hir as hir;
@@ -46,8 +46,7 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::Instance;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Instance, Ty, TyCtxt, VariantDef};
use rustc_session::lint::{BuiltinLintDiagnostics, FutureIncompatibilityReason};
use rustc_span::edition::Edition;
use rustc_span::source_map::Spanned;
@@ -98,30 +97,31 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
impl EarlyLintPass for WhileTrue {
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
- if let ast::ExprKind::While(cond, _, label) = &e.kind {
- if let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind {
- if let ast::LitKind::Bool(true) = lit.kind {
- if !lit.span.from_expansion() {
- let condition_span = e.span.with_hi(cond.span.hi());
- cx.struct_span_lint(WHILE_TRUE, condition_span, |lint| {
- lint.build(fluent::lint::builtin_while_true)
- .span_suggestion_short(
- condition_span,
- fluent::lint::suggestion,
- format!(
- "{}loop",
- label.map_or_else(String::new, |label| format!(
- "{}: ",
- label.ident,
- ))
- ),
- Applicability::MachineApplicable,
- )
- .emit();
- })
- }
- }
- }
+ if let ast::ExprKind::While(cond, _, label) = &e.kind
+ && let ast::ExprKind::Lit(ref lit) = pierce_parens(cond).kind
+ && let ast::LitKind::Bool(true) = lit.kind
+ && !lit.span.from_expansion()
+ {
+ let condition_span = e.span.with_hi(cond.span.hi());
+ cx.struct_span_lint(
+ WHILE_TRUE,
+ condition_span,
+ fluent::lint_builtin_while_true,
+ |lint| {
+ lint.span_suggestion_short(
+ condition_span,
+ fluent::suggestion,
+ format!(
+ "{}loop",
+ label.map_or_else(String::new, |label| format!(
+ "{}: ",
+ label.ident,
+ ))
+ ),
+ Applicability::MachineApplicable,
+ )
+ },
+ )
}
}
}
@@ -157,9 +157,12 @@ impl BoxPointers {
for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if leaf_ty.is_box() {
- cx.struct_span_lint(BOX_POINTERS, span, |lint| {
- lint.build(fluent::lint::builtin_box_pointers).set_arg("ty", ty).emit();
- });
+ cx.struct_span_lint(
+ BOX_POINTERS,
+ span,
+ fluent::lint_builtin_box_pointers,
+ |lint| lint.set_arg("ty", ty),
+ );
}
}
}
@@ -174,7 +177,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.def_id))
+ self.check_heap_type(cx, it.span, cx.tcx.type_of(it.owner_id))
}
_ => (),
}
@@ -258,19 +261,21 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
if cx.tcx.find_field_index(ident, &variant)
== Some(cx.tcx.field_index(fieldpat.hir_id, cx.typeck_results()))
{
- cx.struct_span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span, |lint| {
- let suggested_ident =
- format!("{}{}", binding_annot.prefix_str(), ident);
- lint.build(fluent::lint::builtin_non_shorthand_field_patterns)
- .set_arg("ident", ident.clone())
- .span_suggestion(
+ cx.struct_span_lint(
+ NON_SHORTHAND_FIELD_PATTERNS,
+ fieldpat.span,
+ fluent::lint_builtin_non_shorthand_field_patterns,
+ |lint| {
+ let suggested_ident =
+ format!("{}{}", binding_annot.prefix_str(), ident);
+ lint.set_arg("ident", ident.clone()).span_suggestion(
fieldpat.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
suggested_ident,
Applicability::MachineApplicable,
)
- .emit();
- });
+ },
+ );
}
}
}
@@ -310,14 +315,17 @@ impl UnsafeCode {
&self,
cx: &EarlyContext<'_>,
span: Span,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
// This comes from a macro that has `#[allow_internal_unsafe]`.
if span.allows_unsafe() {
return;
}
- cx.struct_span_lint(UNSAFE_CODE, span, decorate);
+ cx.struct_span_lint(UNSAFE_CODE, span, msg, decorate);
}
fn report_overridden_symbol_name(
@@ -326,8 +334,8 @@ impl UnsafeCode {
span: Span,
msg: DiagnosticMessage,
) {
- self.report_unsafe(cx, span, |lint| {
- lint.build(msg).note(fluent::lint::builtin_overridden_symbol_name).emit();
+ self.report_unsafe(cx, span, msg, |lint| {
+ lint.note(fluent::lint_builtin_overridden_symbol_name)
})
}
@@ -337,8 +345,8 @@ impl UnsafeCode {
span: Span,
msg: DiagnosticMessage,
) {
- self.report_unsafe(cx, span, |lint| {
- lint.build(msg).note(fluent::lint::builtin_overridden_symbol_section).emit();
+ self.report_unsafe(cx, span, msg, |lint| {
+ lint.note(fluent::lint_builtin_overridden_symbol_section)
})
}
}
@@ -346,8 +354,8 @@ impl UnsafeCode {
impl EarlyLintPass for UnsafeCode {
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
if attr.has_name(sym::allow_internal_unsafe) {
- self.report_unsafe(cx, attr.span, |lint| {
- lint.build(fluent::lint::builtin_allow_internal_unsafe).emit();
+ self.report_unsafe(cx, attr.span, fluent::lint_builtin_allow_internal_unsafe, |lint| {
+ lint
});
}
}
@@ -356,31 +364,27 @@ impl EarlyLintPass for UnsafeCode {
if let ast::ExprKind::Block(ref blk, _) = e.kind {
// Don't warn about generated blocks; that'll just pollute the output.
if blk.rules == ast::BlockCheckMode::Unsafe(ast::UserProvided) {
- self.report_unsafe(cx, blk.span, |lint| {
- lint.build(fluent::lint::builtin_unsafe_block).emit();
- });
+ self.report_unsafe(cx, blk.span, fluent::lint_builtin_unsafe_block, |lint| lint);
}
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
match it.kind {
- ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => self
- .report_unsafe(cx, it.span, |lint| {
- lint.build(fluent::lint::builtin_unsafe_trait).emit();
- }),
+ ast::ItemKind::Trait(box ast::Trait { unsafety: ast::Unsafe::Yes(_), .. }) => {
+ self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_trait, |lint| lint)
+ }
- ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => self
- .report_unsafe(cx, it.span, |lint| {
- lint.build(fluent::lint::builtin_unsafe_impl).emit();
- }),
+ ast::ItemKind::Impl(box ast::Impl { unsafety: ast::Unsafe::Yes(_), .. }) => {
+ self.report_unsafe(cx, it.span, fluent::lint_builtin_unsafe_impl, |lint| lint)
+ }
ast::ItemKind::Fn(..) => {
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::no_mangle) {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_no_mangle_fn,
+ fluent::lint_builtin_no_mangle_fn,
);
}
@@ -388,7 +392,7 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_export_name_fn,
+ fluent::lint_builtin_export_name_fn,
);
}
@@ -396,7 +400,7 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_section(
cx,
attr.span,
- fluent::lint::builtin_link_section_fn,
+ fluent::lint_builtin_link_section_fn,
);
}
}
@@ -406,7 +410,7 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_no_mangle_static,
+ fluent::lint_builtin_no_mangle_static,
);
}
@@ -414,7 +418,7 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_export_name_static,
+ fluent::lint_builtin_export_name_static,
);
}
@@ -422,7 +426,7 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_section(
cx,
attr.span,
- fluent::lint::builtin_link_section_static,
+ fluent::lint_builtin_link_section_static,
);
}
}
@@ -437,14 +441,14 @@ impl EarlyLintPass for UnsafeCode {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_no_mangle_method,
+ fluent::lint_builtin_no_mangle_method,
);
}
if let Some(attr) = cx.sess().find_by_name(&it.attrs, sym::export_name) {
self.report_overridden_symbol_name(
cx,
attr.span,
- fluent::lint::builtin_export_name_method,
+ fluent::lint_builtin_export_name_method,
);
}
}
@@ -462,13 +466,11 @@ impl EarlyLintPass for UnsafeCode {
{
let msg = match ctxt {
FnCtxt::Foreign => return,
- FnCtxt::Free => fluent::lint::builtin_decl_unsafe_fn,
- FnCtxt::Assoc(_) if body.is_none() => fluent::lint::builtin_decl_unsafe_method,
- FnCtxt::Assoc(_) => fluent::lint::builtin_impl_unsafe_method,
+ FnCtxt::Free => fluent::lint_builtin_decl_unsafe_fn,
+ FnCtxt::Assoc(_) if body.is_none() => fluent::lint_builtin_decl_unsafe_method,
+ FnCtxt::Assoc(_) => fluent::lint_builtin_impl_unsafe_method,
};
- self.report_unsafe(cx, span, |lint| {
- lint.build(msg).emit();
- });
+ self.report_unsafe(cx, span, msg, |lint| lint);
}
}
}
@@ -561,7 +563,7 @@ impl MissingDoc {
// It's an option so the crate root can also use this function (it doesn't
// have a `NodeId`).
if def_id != CRATE_DEF_ID {
- if !cx.access_levels.is_exported(def_id) {
+ if !cx.effective_visibilities.is_exported(def_id) {
return;
}
}
@@ -569,12 +571,12 @@ impl MissingDoc {
let attrs = cx.tcx.hir().attrs(cx.tcx.hir().local_def_id_to_hir_id(def_id));
let has_doc = attrs.iter().any(has_doc);
if !has_doc {
- cx.struct_span_lint(MISSING_DOCS, cx.tcx.def_span(def_id), |lint| {
- lint.build(fluent::lint::builtin_missing_doc)
- .set_arg("article", article)
- .set_arg("desc", desc)
- .emit();
- });
+ cx.struct_span_lint(
+ MISSING_DOCS,
+ cx.tcx.def_span(def_id),
+ fluent::lint_builtin_missing_doc,
+ |lint| lint.set_arg("article", article).set_arg("desc", desc),
+ );
}
}
}
@@ -604,9 +606,9 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
match it.kind {
hir::ItemKind::Trait(..) => {
// Issue #11592: traits are always considered exported, even when private.
- if cx.tcx.visibility(it.def_id)
+ if cx.tcx.visibility(it.owner_id)
== ty::Visibility::Restricted(
- cx.tcx.parent_module_from_def_id(it.def_id).to_def_id(),
+ cx.tcx.parent_module_from_def_id(it.owner_id.def_id).to_def_id(),
)
{
return;
@@ -625,15 +627,15 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
_ => return,
};
- let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
- self.check_missing_docs_attrs(cx, it.def_id, article, desc);
+ self.check_missing_docs_attrs(cx, it.owner_id.def_id, article, desc);
}
fn check_trait_item(&mut self, cx: &LateContext<'_>, trait_item: &hir::TraitItem<'_>) {
- let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
- self.check_missing_docs_attrs(cx, trait_item.def_id, article, desc);
+ self.check_missing_docs_attrs(cx, trait_item.owner_id.def_id, article, desc);
}
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
@@ -660,13 +662,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
}
- let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
- self.check_missing_docs_attrs(cx, impl_item.def_id, article, desc);
+ let (article, desc) = cx.tcx.article_and_description(impl_item.owner_id.to_def_id());
+ self.check_missing_docs_attrs(cx, impl_item.owner_id.def_id, article, desc);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'_>) {
- let (article, desc) = cx.tcx.article_and_description(foreign_item.def_id.to_def_id());
- self.check_missing_docs_attrs(cx, foreign_item.def_id, article, desc);
+ let (article, desc) = cx.tcx.article_and_description(foreign_item.owner_id.to_def_id());
+ self.check_missing_docs_attrs(cx, foreign_item.owner_id.def_id, article, desc);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, sf: &hir::FieldDef<'_>) {
@@ -719,7 +721,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- if !cx.access_levels.is_reachable(item.def_id) {
+ if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
let (def, ty) = match item.kind {
@@ -727,21 +729,21 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(item.def_id);
+ let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Union(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(item.def_id);
+ let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
hir::ItemKind::Enum(_, ref ast_generics) => {
if !ast_generics.params.is_empty() {
return;
}
- let def = cx.tcx.adt_def(item.def_id);
+ let def = cx.tcx.adt_def(item.owner_id);
(def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[])))
}
_ => return,
@@ -750,7 +752,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
return;
}
let param_env = ty::ParamEnv::empty();
- if ty.is_copy_modulo_regions(cx.tcx.at(item.span), param_env) {
+ if ty.is_copy_modulo_regions(cx.tcx, param_env) {
return;
}
if can_type_implement_copy(
@@ -761,9 +763,12 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
)
.is_ok()
{
- cx.struct_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, |lint| {
- lint.build(fluent::lint::builtin_missing_copy_impl).emit();
- })
+ cx.struct_span_lint(
+ MISSING_COPY_IMPLEMENTATIONS,
+ item.span,
+ fluent::lint_builtin_missing_copy_impl,
+ |lint| lint,
+ )
}
}
}
@@ -809,7 +814,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- if !cx.access_levels.is_reachable(item.def_id) {
+ if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
@@ -836,12 +841,13 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
debug!("{:?}", self.impling_types);
}
- if !self.impling_types.as_ref().unwrap().contains(&item.def_id) {
- cx.struct_span_lint(MISSING_DEBUG_IMPLEMENTATIONS, item.span, |lint| {
- lint.build(fluent::lint::builtin_missing_debug_impl)
- .set_arg("debug", cx.tcx.def_path_str(debug))
- .emit();
- });
+ if !self.impling_types.as_ref().unwrap().contains(&item.owner_id.def_id) {
+ cx.struct_span_lint(
+ MISSING_DEBUG_IMPLEMENTATIONS,
+ item.span,
+ fluent::lint_builtin_missing_debug_impl,
+ |lint| lint.set_arg("debug", cx.tcx.def_path_str(debug)),
+ );
}
}
}
@@ -909,24 +915,26 @@ impl EarlyLintPass for AnonymousParameters {
for arg in sig.decl.inputs.iter() {
if let ast::PatKind::Ident(_, ident, None) = arg.pat.kind {
if ident.name == kw::Empty {
- cx.struct_span_lint(ANONYMOUS_PARAMETERS, arg.pat.span, |lint| {
- let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
-
- let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
- (snip.as_str(), Applicability::MachineApplicable)
- } else {
- ("<type>", Applicability::HasPlaceholders)
- };
+ let ty_snip = cx.sess().source_map().span_to_snippet(arg.ty.span);
- lint.build(fluent::lint::builtin_anonymous_params)
- .span_suggestion(
+ let (ty_snip, appl) = if let Ok(ref snip) = ty_snip {
+ (snip.as_str(), Applicability::MachineApplicable)
+ } else {
+ ("<type>", Applicability::HasPlaceholders)
+ };
+ cx.struct_span_lint(
+ ANONYMOUS_PARAMETERS,
+ arg.pat.span,
+ fluent::lint_builtin_anonymous_params,
+ |lint| {
+ lint.span_suggestion(
arg.pat.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
format!("_: {}", ty_snip),
appl,
)
- .emit();
- })
+ },
+ )
}
}
}
@@ -961,38 +969,44 @@ impl EarlyLintPass for DeprecatedAttr {
_,
) = gate
{
- cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
- // FIXME(davidtwco) translatable deprecated attr
- lint.build(fluent::lint::builtin_deprecated_attr_link)
- .set_arg("name", name)
- .set_arg("reason", reason)
- .set_arg("link", link)
- .span_suggestion_short(
- attr.span,
- suggestion.map(|s| s.into()).unwrap_or(
- fluent::lint::builtin_deprecated_attr_default_suggestion,
- ),
- "",
- Applicability::MachineApplicable,
- )
- .emit();
- });
+ // FIXME(davidtwco) translatable deprecated attr
+ cx.struct_span_lint(
+ DEPRECATED,
+ attr.span,
+ fluent::lint_builtin_deprecated_attr_link,
+ |lint| {
+ lint.set_arg("name", name)
+ .set_arg("reason", reason)
+ .set_arg("link", link)
+ .span_suggestion_short(
+ attr.span,
+ suggestion.map(|s| s.into()).unwrap_or(
+ fluent::lint_builtin_deprecated_attr_default_suggestion,
+ ),
+ "",
+ Applicability::MachineApplicable,
+ )
+ },
+ );
}
return;
}
}
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
- cx.struct_span_lint(DEPRECATED, attr.span, |lint| {
- lint.build(fluent::lint::builtin_deprecated_attr_used)
- .set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
- .span_suggestion_short(
- attr.span,
- fluent::lint::builtin_deprecated_attr_default_suggestion,
- "",
- Applicability::MachineApplicable,
- )
- .emit();
- });
+ cx.struct_span_lint(
+ DEPRECATED,
+ attr.span,
+ fluent::lint_builtin_deprecated_attr_used,
+ |lint| {
+ lint.set_arg("name", pprust::path_to_string(&attr.get_normal_item().path))
+ .span_suggestion_short(
+ attr.span,
+ fluent::lint_builtin_deprecated_attr_default_suggestion,
+ "",
+ Applicability::MachineApplicable,
+ )
+ },
+ );
}
}
}
@@ -1019,20 +1033,21 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
let span = sugared_span.take().unwrap_or(attr.span);
if is_doc_comment || attr.has_name(sym::doc) {
- cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| {
- let mut err = lint.build(fluent::lint::builtin_unused_doc_comment);
- err.set_arg("kind", node_kind);
- err.span_label(node_span, fluent::lint::label);
- match attr.kind {
- AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
- err.help(fluent::lint::plain_help);
- }
- AttrKind::DocComment(CommentKind::Block, _) => {
- err.help(fluent::lint::block_help);
- }
- }
- err.emit();
- });
+ cx.struct_span_lint(
+ UNUSED_DOC_COMMENTS,
+ span,
+ fluent::lint_builtin_unused_doc_comment,
+ |lint| {
+ lint.set_arg("kind", node_kind).span_label(node_span, fluent::label).help(
+ match attr.kind {
+ AttrKind::DocComment(CommentKind::Line, _) | AttrKind::Normal(..) => {
+ fluent::plain_help
+ }
+ AttrKind::DocComment(CommentKind::Block, _) => fluent::block_help,
+ },
+ )
+ },
+ );
}
}
}
@@ -1146,18 +1161,21 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, span, |lint| {
- lint.build(fluent::lint::builtin_no_mangle_generic)
- .span_suggestion_short(
+ cx.struct_span_lint(
+ NO_MANGLE_GENERIC_ITEMS,
+ span,
+ fluent::lint_builtin_no_mangle_generic,
+ |lint| {
+ lint.span_suggestion_short(
no_mangle_attr.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
"",
// Use of `#[no_mangle]` suggests FFI intent; correct
// fix may be to monomorphize source by hand
Applicability::MaybeIncorrect,
)
- .emit();
- });
+ },
+ );
break;
}
}
@@ -1173,27 +1191,29 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
if cx.sess().contains_name(attrs, sym::no_mangle) {
// Const items do not refer to a particular location in memory, and therefore
// don't have anything to attach a symbol to
- cx.struct_span_lint(NO_MANGLE_CONST_ITEMS, it.span, |lint| {
- let mut err = lint.build(fluent::lint::builtin_const_no_mangle);
-
- // account for "pub const" (#45562)
- let start = cx
- .tcx
- .sess
- .source_map()
- .span_to_snippet(it.span)
- .map(|snippet| snippet.find("const").unwrap_or(0))
- .unwrap_or(0) as u32;
- // `const` is 5 chars
- let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
- err.span_suggestion(
- const_span,
- fluent::lint::suggestion,
- "pub static",
- Applicability::MachineApplicable,
- );
- err.emit();
- });
+ cx.struct_span_lint(
+ NO_MANGLE_CONST_ITEMS,
+ it.span,
+ fluent::lint_builtin_const_no_mangle,
+ |lint| {
+ // account for "pub const" (#45562)
+ let start = cx
+ .tcx
+ .sess
+ .source_map()
+ .span_to_snippet(it.span)
+ .map(|snippet| snippet.find("const").unwrap_or(0))
+ .unwrap_or(0) as u32;
+ // `const` is 5 chars
+ let const_span = it.span.with_hi(BytePos(it.span.lo().0 + start + 5));
+ lint.span_suggestion(
+ const_span,
+ fluent::suggestion,
+ "pub static",
+ Applicability::MachineApplicable,
+ )
+ },
+ );
}
}
hir::ItemKind::Impl(hir::Impl { generics, items, .. }) => {
@@ -1206,7 +1226,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
check_no_mangle_on_generic_fn(
no_mangle_attr,
Some(generics),
- cx.tcx.hir().get_generics(it.id.def_id).unwrap(),
+ cx.tcx.hir().get_generics(it.id.owner_id.def_id).unwrap(),
it.span,
);
}
@@ -1253,9 +1273,12 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
{
if to_mt == hir::Mutability::Mut && from_mt == hir::Mutability::Not {
- cx.struct_span_lint(MUTABLE_TRANSMUTES, expr.span, |lint| {
- lint.build(fluent::lint::builtin_mutable_transmutes).emit();
- });
+ cx.struct_span_lint(
+ MUTABLE_TRANSMUTES,
+ expr.span,
+ fluent::lint_builtin_mutable_transmutes,
+ |lint| lint,
+ );
}
}
@@ -1303,9 +1326,12 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
if attr.has_name(sym::feature) {
if let Some(items) = attr.meta_item_list() {
for item in items {
- cx.struct_span_lint(UNSTABLE_FEATURES, item.span(), |lint| {
- lint.build(fluent::lint::builtin_unstable_features).emit();
- });
+ cx.struct_span_lint(
+ UNSTABLE_FEATURES,
+ item.span(),
+ fluent::lint_builtin_unstable_features,
+ |lint| lint,
+ );
}
}
}
@@ -1359,26 +1385,26 @@ impl UnreachablePub {
exportable: bool,
) {
let mut applicability = Applicability::MachineApplicable;
- if cx.tcx.visibility(def_id).is_public() && !cx.access_levels.is_reachable(def_id) {
+ if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id)
+ {
if vis_span.from_expansion() {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.def_span(def_id);
- cx.struct_span_lint(UNREACHABLE_PUB, def_span, |lint| {
- let mut err = lint.build(fluent::lint::builtin_unreachable_pub);
- err.set_arg("what", what);
-
- err.span_suggestion(
- vis_span,
- fluent::lint::suggestion,
- "pub(crate)",
- applicability,
- );
- if exportable {
- err.help(fluent::lint::help);
- }
- err.emit();
- });
+ cx.struct_span_lint(
+ UNREACHABLE_PUB,
+ def_span,
+ fluent::lint_builtin_unreachable_pub,
+ |lint| {
+ lint.set_arg("what", what);
+
+ lint.span_suggestion(vis_span, fluent::suggestion, "pub(crate)", applicability);
+ if exportable {
+ lint.help(fluent::help);
+ }
+ lint
+ },
+ );
}
}
}
@@ -1389,11 +1415,11 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind {
return;
}
- self.perform_lint(cx, "item", item.def_id, item.vis_span, true);
+ self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true);
}
fn check_foreign_item(&mut self, cx: &LateContext<'_>, foreign_item: &hir::ForeignItem<'tcx>) {
- self.perform_lint(cx, "item", foreign_item.def_id, foreign_item.vis_span, true);
+ self.perform_lint(cx, "item", foreign_item.owner_id.def_id, foreign_item.vis_span, true);
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
@@ -1403,8 +1429,8 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub {
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
// Only lint inherent impl items.
- if cx.tcx.associated_item(impl_item.def_id).trait_item_def_id.is_none() {
- self.perform_lint(cx, "item", impl_item.def_id, impl_item.vis_span, false);
+ if cx.tcx.associated_item(impl_item.owner_id).trait_item_def_id.is_none() {
+ self.perform_lint(cx, "item", impl_item.owner_id.def_id, impl_item.vis_span, false);
}
}
}
@@ -1465,7 +1491,7 @@ impl TypeAliasBounds {
impl Visitor<'_> for WalkAssocTypes<'_> {
fn visit_qpath(&mut self, qpath: &hir::QPath<'_>, id: hir::HirId, span: Span) {
if TypeAliasBounds::is_type_variable_assoc(qpath) {
- self.err.span_help(span, fluent::lint::builtin_type_alias_bounds_help);
+ self.err.span_help(span, fluent::lint_builtin_type_alias_bounds_help);
}
intravisit::walk_qpath(self, qpath, id)
}
@@ -1508,36 +1534,34 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
let mut suggested_changing_assoc_types = false;
if !where_spans.is_empty() {
- cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
- let mut err = lint.build(fluent::lint::builtin_type_alias_where_clause);
- err.set_span(where_spans);
- err.span_suggestion(
+ cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_where_clause, |lint| {
+ lint.set_span(where_spans);
+ lint.span_suggestion(
type_alias_generics.where_clause_span,
- fluent::lint::suggestion,
+ fluent::suggestion,
"",
Applicability::MachineApplicable,
);
if !suggested_changing_assoc_types {
- TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
+ TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
suggested_changing_assoc_types = true;
}
- err.emit();
+ lint
});
}
if !inline_spans.is_empty() {
- cx.lint(TYPE_ALIAS_BOUNDS, |lint| {
- let mut err = lint.build(fluent::lint::builtin_type_alias_generic_bounds);
- err.set_span(inline_spans);
- err.multipart_suggestion(
- fluent::lint::suggestion,
+ cx.lint(TYPE_ALIAS_BOUNDS, fluent::lint_builtin_type_alias_generic_bounds, |lint| {
+ lint.set_span(inline_spans);
+ lint.multipart_suggestion(
+ fluent::suggestion,
inline_sugg,
Applicability::MachineApplicable,
);
if !suggested_changing_assoc_types {
- TypeAliasBounds::suggest_changing_assoc_types(ty, &mut err);
+ TypeAliasBounds::suggest_changing_assoc_types(ty, lint);
}
- err.emit();
+ lint
});
}
}
@@ -1615,7 +1639,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
use rustc_middle::ty::PredicateKind::*;
if cx.tcx.features().trivial_bounds {
- let predicates = cx.tcx.predicates_of(item.def_id);
+ let predicates = cx.tcx.predicates_of(item.owner_id);
for &(predicate, span) in predicates.predicates {
let predicate_kind_name = match predicate.kind().skip_binder() {
Trait(..) => "trait",
@@ -1636,12 +1660,15 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
TypeWellFormedFromEnv(..) => continue,
};
if predicate.is_global() {
- cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
- lint.build(fluent::lint::builtin_trivial_bounds)
- .set_arg("predicate_kind_name", predicate_kind_name)
- .set_arg("predicate", predicate)
- .emit();
- });
+ cx.struct_span_lint(
+ TRIVIAL_BOUNDS,
+ span,
+ fluent::lint_builtin_trivial_bounds,
+ |lint| {
+ lint.set_arg("predicate_kind_name", predicate_kind_name)
+ .set_arg("predicate", predicate)
+ },
+ );
}
}
}
@@ -1741,8 +1768,8 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
};
if let Some((start, end, join)) = endpoints {
- let msg = fluent::lint::builtin_ellipsis_inclusive_range_patterns;
- let suggestion = fluent::lint::suggestion;
+ let msg = fluent::lint_builtin_ellipsis_inclusive_range_patterns;
+ let suggestion = fluent::suggestion;
if parenthesise {
self.node_id = Some(pat.id);
let end = expr_to_string(&end);
@@ -1757,15 +1784,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
replace,
});
} else {
- cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, |lint| {
- lint.build(msg)
- .span_suggestion(
- pat.span,
- suggestion,
- replace,
- Applicability::MachineApplicable,
- )
- .emit();
+ cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, pat.span, msg, |lint| {
+ lint.span_suggestion(
+ pat.span,
+ suggestion,
+ replace,
+ Applicability::MachineApplicable,
+ )
});
}
} else {
@@ -1777,15 +1802,13 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
replace: replace.to_string(),
});
} else {
- cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, |lint| {
- lint.build(msg)
- .span_suggestion_short(
- join,
- suggestion,
- replace,
- Applicability::MachineApplicable,
- )
- .emit();
+ cx.struct_span_lint(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS, join, msg, |lint| {
+ lint.span_suggestion_short(
+ join,
+ suggestion,
+ replace,
+ Applicability::MachineApplicable,
+ )
});
}
};
@@ -1841,7 +1864,7 @@ declare_lint! {
}
pub struct UnnameableTestItems {
- boundary: Option<LocalDefId>, // Id of the item under which things are not nameable
+ boundary: Option<hir::OwnerId>, // Id of the item under which things are not nameable
items_nameable: bool,
}
@@ -1859,21 +1882,24 @@ impl<'tcx> LateLintPass<'tcx> for UnnameableTestItems {
if let hir::ItemKind::Mod(..) = it.kind {
} else {
self.items_nameable = false;
- self.boundary = Some(it.def_id);
+ self.boundary = Some(it.owner_id);
}
return;
}
let attrs = cx.tcx.hir().attrs(it.hir_id());
if let Some(attr) = cx.sess().find_by_name(attrs, sym::rustc_test_marker) {
- cx.struct_span_lint(UNNAMEABLE_TEST_ITEMS, attr.span, |lint| {
- lint.build(fluent::lint::builtin_unnameable_test_items).emit();
- });
+ cx.struct_span_lint(
+ UNNAMEABLE_TEST_ITEMS,
+ attr.span,
+ fluent::lint_builtin_unnameable_test_items,
+ |lint| lint,
+ );
}
}
fn check_item_post(&mut self, _cx: &LateContext<'_>, it: &hir::Item<'_>) {
- if !self.items_nameable && self.boundary == Some(it.def_id) {
+ if !self.items_nameable && self.boundary == Some(it.owner_id) {
self.items_nameable = true;
}
}
@@ -1984,18 +2010,19 @@ impl KeywordIdents {
return;
}
- cx.struct_span_lint(KEYWORD_IDENTS, ident.span, |lint| {
- lint.build(fluent::lint::builtin_keyword_idents)
- .set_arg("kw", ident.clone())
- .set_arg("next", next_edition)
- .span_suggestion(
+ cx.struct_span_lint(
+ KEYWORD_IDENTS,
+ ident.span,
+ fluent::lint_builtin_keyword_idents,
+ |lint| {
+ lint.set_arg("kw", ident.clone()).set_arg("next", next_edition).span_suggestion(
ident.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
format!("r#{}", ident),
Applicability::MachineApplicable,
)
- .emit();
- });
+ },
+ );
}
}
@@ -2138,7 +2165,7 @@ 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;
- let def_id = item.def_id;
+ let def_id = item.owner_id.def_id;
if let hir::ItemKind::Struct(_, ref hir_generics)
| hir::ItemKind::Enum(_, ref hir_generics)
| hir::ItemKind::Union(_, ref hir_generics) = item.kind
@@ -2246,19 +2273,21 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
}
if !lint_spans.is_empty() {
- cx.struct_span_lint(EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), |lint| {
- lint.build(fluent::lint::builtin_explicit_outlives)
- .set_arg("count", bound_count)
- .multipart_suggestion(
- fluent::lint::suggestion,
+ cx.struct_span_lint(
+ EXPLICIT_OUTLIVES_REQUIREMENTS,
+ lint_spans.clone(),
+ fluent::lint_builtin_explicit_outlives,
+ |lint| {
+ lint.set_arg("count", bound_count).multipart_suggestion(
+ fluent::suggestion,
lint_spans
.into_iter()
.map(|span| (span, String::new()))
.collect::<Vec<_>>(),
Applicability::MachineApplicable,
)
- .emit();
- });
+ },
+ );
}
}
}
@@ -2305,18 +2334,24 @@ impl EarlyLintPass for IncompleteFeatures {
.chain(features.declared_lib_features.iter().map(|(name, span)| (name, span)))
.filter(|(&name, _)| features.incomplete(name))
.for_each(|(&name, &span)| {
- cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| {
- let mut builder = lint.build(fluent::lint::builtin_incomplete_features);
- builder.set_arg("name", name);
- if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) {
- builder.set_arg("n", n);
- builder.note(fluent::lint::note);
- }
- if HAS_MIN_FEATURES.contains(&name) {
- builder.help(fluent::lint::help);
- }
- builder.emit();
- })
+ cx.struct_span_lint(
+ INCOMPLETE_FEATURES,
+ span,
+ fluent::lint_builtin_incomplete_features,
+ |lint| {
+ lint.set_arg("name", name);
+ if let Some(n) =
+ rustc_feature::find_feature_issue(name, GateIssue::Language)
+ {
+ lint.set_arg("n", n);
+ lint.note(fluent::note);
+ }
+ if HAS_MIN_FEATURES.contains(&name) {
+ lint.help(fluent::help);
+ }
+ lint
+ },
+ )
});
}
}
@@ -2425,12 +2460,27 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
None
}
- /// Test if this enum has several actually "existing" variants.
- /// Zero-sized uninhabited variants do not always have a tag assigned and thus do not "exist".
- fn is_multi_variant<'tcx>(adt: ty::AdtDef<'tcx>) -> bool {
- // As an approximation, we only count dataless variants. Those are definitely inhabited.
- let existing_variants = adt.variants().iter().filter(|v| v.fields.is_empty()).count();
- existing_variants > 1
+ fn variant_find_init_error<'tcx>(
+ cx: &LateContext<'tcx>,
+ variant: &VariantDef,
+ substs: ty::SubstsRef<'tcx>,
+ descr: &str,
+ init: InitKind,
+ ) -> Option<InitError> {
+ variant.fields.iter().find_map(|field| {
+ ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(|(mut msg, span)| {
+ if span.is_none() {
+ // Point to this field, should be helpful for figuring
+ // out where the source of the error is.
+ let span = cx.tcx.def_span(field.did);
+ write!(&mut msg, " (in this {descr})").unwrap();
+ (msg, Some(span))
+ } else {
+ // Just forward.
+ (msg, span)
+ }
+ })
+ })
}
/// Return `Some` only if we are sure this type does *not*
@@ -2468,7 +2518,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
RawPtr(_) if init == InitKind::Uninit => {
Some(("raw pointers must not be uninitialized".to_string(), None))
}
- // Recurse and checks for some compound types.
+ // Recurse and checks for some compound types. (but not unions)
Adt(adt_def, substs) if !adt_def.is_union() => {
// First check if this ADT has a layout attribute (like `NonNull` and friends).
use std::ops::Bound;
@@ -2476,7 +2526,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
// We exploit here that `layout_scalar_valid_range` will never
// return `Bound::Excluded`. (And we have tests checking that we
// handle the attribute correctly.)
- (Bound::Included(lo), _) if lo > 0 => {
+ // We don't add a span since users cannot declare such types anyway.
+ (Bound::Included(lo), Bound::Included(hi)) if 0 < lo && lo < hi => {
+ return Some((format!("`{}` must be non-null", ty), None));
+ }
+ (Bound::Included(lo), Bound::Unbounded) if 0 < lo => {
return Some((format!("`{}` must be non-null", ty), None));
}
(Bound::Included(_), _) | (_, Bound::Included(_))
@@ -2492,50 +2546,65 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
}
_ => {}
}
- // Now, recurse.
- match adt_def.variants().len() {
- 0 => Some(("enums with no variants have no valid value".to_string(), None)),
- 1 => {
- // Struct, or enum with exactly one variant.
- // Proceed recursively, check all fields.
- let variant = &adt_def.variant(VariantIdx::from_u32(0));
- variant.fields.iter().find_map(|field| {
- ty_find_init_error(cx, field.ty(cx.tcx, substs), init).map(
- |(mut msg, span)| {
- if span.is_none() {
- // Point to this field, should be helpful for figuring
- // out where the source of the error is.
- let span = cx.tcx.def_span(field.did);
- write!(
- &mut msg,
- " (in this {} field)",
- adt_def.descr()
- )
- .unwrap();
- (msg, Some(span))
- } else {
- // Just forward.
- (msg, span)
- }
- },
- )
- })
- }
- // Multi-variant enum.
- _ => {
- if init == InitKind::Uninit && is_multi_variant(*adt_def) {
- let span = cx.tcx.def_span(adt_def.did());
- Some((
- "enums have to be initialized to a variant".to_string(),
- Some(span),
- ))
- } else {
- // In principle, for zero-initialization we could figure out which variant corresponds
- // to tag 0, and check that... but for now we just accept all zero-initializations.
- None
- }
+ // Handle structs.
+ if adt_def.is_struct() {
+ return variant_find_init_error(
+ cx,
+ adt_def.non_enum_variant(),
+ substs,
+ "struct field",
+ init,
+ );
+ }
+ // And now, enums.
+ let span = cx.tcx.def_span(adt_def.did());
+ let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
+ let definitely_inhabited = match variant
+ .inhabited_predicate(cx.tcx, *adt_def)
+ .subst(cx.tcx, substs)
+ .apply_any_module(cx.tcx, cx.param_env)
+ {
+ // Entirely skip uninhbaited variants.
+ Some(false) => return None,
+ // Forward the others, but remember which ones are definitely inhabited.
+ Some(true) => true,
+ None => false,
+ };
+ Some((variant, definitely_inhabited))
+ });
+ let Some(first_variant) = potential_variants.next() else {
+ return Some(("enums with no inhabited variants have no valid value".to_string(), Some(span)));
+ };
+ // So we have at least one potentially inhabited variant. Might we have two?
+ let Some(second_variant) = potential_variants.next() else {
+ // There is only one potentially inhabited variant. So we can recursively check that variant!
+ return variant_find_init_error(
+ cx,
+ &first_variant.0,
+ substs,
+ "field of the only potentially inhabited enum variant",
+ init,
+ );
+ };
+ // So we have at least two potentially inhabited variants.
+ // If we can prove that we have at least two *definitely* inhabited variants,
+ // then we have a tag and hence leaving this uninit is definitely disallowed.
+ // (Leaving it zeroed could be okay, depending on which variant is encoded as zero tag.)
+ if init == InitKind::Uninit {
+ let definitely_inhabited = (first_variant.1 as usize)
+ + (second_variant.1 as usize)
+ + potential_variants
+ .filter(|(_variant, definitely_inhabited)| *definitely_inhabited)
+ .count();
+ if definitely_inhabited > 1 {
+ return Some((
+ "enums with multiple inhabited variants have to be initialized to a variant".to_string(),
+ Some(span),
+ ));
}
}
+ // We couldn't find anything wrong here.
+ None
}
Tuple(..) => {
// Proceed recursively, check all fields.
@@ -2564,28 +2633,37 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
with_no_trimmed_paths!(ty_find_init_error(cx, conjured_ty, init))
{
// FIXME(davidtwco): make translatable
- cx.struct_span_lint(INVALID_VALUE, expr.span, |lint| {
- let mut err = lint.build(&format!(
- "the type `{}` does not permit {}",
- conjured_ty,
- match init {
- InitKind::Zeroed => "zero-initialization",
- InitKind::Uninit => "being left uninitialized",
- },
- ));
- err.span_label(expr.span, "this code causes undefined behavior when executed");
- err.span_label(
- expr.span,
- "help: use `MaybeUninit<T>` instead, \
+ cx.struct_span_lint(
+ INVALID_VALUE,
+ expr.span,
+ DelayDm(|| {
+ format!(
+ "the type `{}` does not permit {}",
+ conjured_ty,
+ match init {
+ InitKind::Zeroed => "zero-initialization",
+ InitKind::Uninit => "being left uninitialized",
+ },
+ )
+ }),
+ |lint| {
+ lint.span_label(
+ expr.span,
+ "this code causes undefined behavior when executed",
+ );
+ lint.span_label(
+ expr.span,
+ "help: use `MaybeUninit<T>` instead, \
and only call `assume_init` after initialization is done",
- );
- if let Some(span) = span {
- err.span_note(span, &msg);
- } else {
- err.note(&msg);
- }
- err.emit();
- });
+ );
+ if let Some(span) = span {
+ lint.span_note(span, &msg);
+ } else {
+ lint.note(&msg);
+ }
+ lint
+ },
+ );
}
}
}
@@ -2666,7 +2744,7 @@ impl ClashingExternDeclarations {
/// 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> {
- let did = fi.def_id.to_def_id();
+ 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) {
@@ -2684,14 +2762,14 @@ impl ClashingExternDeclarations {
/// symbol's name.
fn name_of_extern_decl(tcx: TyCtxt<'_>, fi: &hir::ForeignItem<'_>) -> SymbolName {
if let Some((overridden_link_name, overridden_link_name_span)) =
- tcx.codegen_fn_attrs(fi.def_id).link_name.map(|overridden_link_name| {
+ tcx.codegen_fn_attrs(fi.owner_id).link_name.map(|overridden_link_name| {
// FIXME: Instead of searching through the attributes again to get span
// information, we could have codegen_fn_attrs also give span information back for
// where the attribute was defined. However, until this is found to be a
// bottleneck, this does just fine.
(
overridden_link_name,
- tcx.get_attr(fi.def_id.to_def_id(), sym::link_name).unwrap().span,
+ tcx.get_attr(fi.owner_id.to_def_id(), sym::link_name).unwrap().span,
)
})
{
@@ -2908,10 +2986,10 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
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.def_id);
+ let this_decl_ty = tcx.type_of(this_fi.owner_id);
debug!(
"ClashingExternDeclarations: Comparing existing {:?}: {:?} to this {:?}: {:?}",
- existing_hid, existing_decl_ty, this_fi.def_id, this_decl_ty
+ existing_hid, existing_decl_ty, this_fi.owner_id, this_decl_ty
);
// Check that the declarations match.
if !Self::structurally_same_type(
@@ -2931,31 +3009,29 @@ impl<'tcx> LateLintPass<'tcx> for ClashingExternDeclarations {
SymbolName::Link(_, annot_span) => fi.span.to(annot_span),
};
// Finally, emit the diagnostic.
+
+ let msg = if orig.get_name() == this_fi.ident.name {
+ fluent::lint_builtin_clashing_extern_same_name
+ } else {
+ fluent::lint_builtin_clashing_extern_diff_name
+ };
tcx.struct_span_lint_hir(
CLASHING_EXTERN_DECLARATIONS,
this_fi.hir_id(),
get_relevant_span(this_fi),
+ msg,
|lint| {
let mut expected_str = DiagnosticStyledString::new();
expected_str.push(existing_decl_ty.fn_sig(tcx).to_string(), false);
let mut found_str = DiagnosticStyledString::new();
found_str.push(this_decl_ty.fn_sig(tcx).to_string(), true);
- lint.build(if orig.get_name() == this_fi.ident.name {
- fluent::lint::builtin_clashing_extern_same_name
- } else {
- fluent::lint::builtin_clashing_extern_diff_name
- })
- .set_arg("this_fi", this_fi.ident.name)
- .set_arg("orig", orig.get_name())
- .span_label(
- get_relevant_span(orig_fi),
- fluent::lint::previous_decl_label,
- )
- .span_label(get_relevant_span(this_fi), fluent::lint::mismatch_label)
- // FIXME(davidtwco): translatable expected/found
- .note_expected_found(&"", expected_str, &"", found_str)
- .emit();
+ lint.set_arg("this_fi", this_fi.ident.name)
+ .set_arg("orig", orig.get_name())
+ .span_label(get_relevant_span(orig_fi), fluent::previous_decl_label)
+ .span_label(get_relevant_span(this_fi), fluent::mismatch_label)
+ // FIXME(davidtwco): translatable expected/found
+ .note_expected_found(&"", expected_str, &"", found_str)
},
);
}
@@ -3036,11 +3112,12 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
if is_null_ptr(cx, expr_deref) {
- cx.struct_span_lint(DEREF_NULLPTR, expr.span, |lint| {
- let mut err = lint.build(fluent::lint::builtin_deref_nullptr);
- err.span_label(expr.span, fluent::lint::label);
- err.emit();
- });
+ cx.struct_span_lint(
+ DEREF_NULLPTR,
+ expr.span,
+ fluent::lint_builtin_deref_nullptr,
+ |lint| lint.span_label(expr.span, fluent::label),
+ );
}
}
}
@@ -3053,6 +3130,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
+ /// # #![feature(asm_experimental_arch)]
/// use std::arch::asm;
///
/// fn main() {
@@ -3150,9 +3228,8 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
cx.lookup_with_diagnostics(
NAMED_ASM_LABELS,
Some(target_spans),
- |diag| {
- diag.build(fluent::lint::builtin_asm_labels).emit();
- },
+ fluent::lint_builtin_asm_labels,
+ |lint| lint,
BuiltinLintDiagnostics::NamedAsmLabel(
"only local labels of the form `<number>:` should be used in inline asm"
.to_string(),
@@ -3188,7 +3265,7 @@ declare_lint! {
/// explicitly.
///
/// To access a library from a binary target within the same crate,
- /// use `your_crate_name::` as the path path instead of `lib::`:
+ /// use `your_crate_name::` as the path instead of `lib::`:
///
/// ```rust,compile_fail
/// // bar/src/lib.rs
@@ -3224,16 +3301,14 @@ impl EarlyLintPass for SpecialModuleName {
}
match item.ident.name.as_str() {
- "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
- lint.build("found module declaration for lib.rs")
+ "lib" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for lib.rs", |lint| {
+ lint
.note("lib.rs is the root of this crate's library target")
.help("to refer to it from other targets, use the library's name as the path")
- .emit()
}),
- "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, |lint| {
- lint.build("found module declaration for main.rs")
+ "main" => cx.struct_span_lint(SPECIAL_MODULE_NAME, item.span, "found module declaration for main.rs", |lint| {
+ lint
.note("a binary crate cannot be used as library")
- .emit()
}),
_ => continue
}
@@ -3253,24 +3328,27 @@ impl EarlyLintPass for UnexpectedCfgs {
for &(name, value) in cfg {
if let Some(names_valid) = &check_cfg.names_valid {
if !names_valid.contains(&name) {
- cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
- diag.build(fluent::lint::builtin_unexpected_cli_config_name)
- .help(fluent::lint::help)
- .set_arg("name", name)
- .emit();
- });
+ cx.lookup(
+ UNEXPECTED_CFGS,
+ None::<MultiSpan>,
+ fluent::lint_builtin_unexpected_cli_config_name,
+ |diag| diag.help(fluent::help).set_arg("name", name),
+ );
}
}
if let Some(value) = value {
if let Some(values) = &check_cfg.values_valid.get(&name) {
if !values.contains(&value) {
- cx.lookup(UNEXPECTED_CFGS, None::<MultiSpan>, |diag| {
- diag.build(fluent::lint::builtin_unexpected_cli_config_value)
- .help(fluent::lint::help)
- .set_arg("name", name)
- .set_arg("value", value)
- .emit();
- });
+ cx.lookup(
+ UNEXPECTED_CFGS,
+ None::<MultiSpan>,
+ fluent::lint_builtin_unexpected_cli_config_value,
+ |diag| {
+ diag.help(fluent::help)
+ .set_arg("name", name)
+ .set_arg("value", value)
+ },
+ );
}
}
}
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 7ca6ec5d9..cec0003ff 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -25,15 +25,13 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync;
-use rustc_errors::add_elided_lifetime_in_path_suggestion;
-use rustc_errors::{
- Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
-};
+use rustc_errors::{add_elided_lifetime_in_path_suggestion, DiagnosticBuilder, DiagnosticMessage};
+use rustc_errors::{Applicability, DecorateLint, MultiSpan, SuggestionStyle};
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability;
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -544,7 +542,7 @@ pub struct LateContext<'tcx> {
pub param_env: ty::ParamEnv<'tcx>,
/// Items accessible from the crate being checked.
- pub access_levels: &'tcx AccessLevels,
+ pub effective_visibilities: &'tcx EffectiveVisibilities,
/// The store of registered lints and the lint levels.
pub lint_store: &'tcx LintStore,
@@ -560,7 +558,7 @@ pub struct LateContext<'tcx> {
/// Context for lint checking of the AST, after expansion, before lowering to HIR.
pub struct EarlyContext<'a> {
- pub builder: LintLevelsBuilder<'a>,
+ pub builder: LintLevelsBuilder<'a, crate::levels::TopDown>,
pub buffered: LintBuffer,
}
@@ -576,17 +574,23 @@ pub trait LintContext: Sized {
fn sess(&self) -> &Session;
fn lints(&self) -> &LintStore;
+ /// Emit a lint at the appropriate level, with an optional associated span and an existing diagnostic.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
fn lookup_with_diagnostics(
&self,
lint: &'static Lint,
span: Option<impl Into<MultiSpan>>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
diagnostic: BuiltinLintDiagnostics,
) {
- self.lookup(lint, span, |lint| {
- // We first generate a blank diagnostic.
- let mut db = lint.build("");
-
+ // We first generate a blank diagnostic.
+ self.lookup(lint, span, msg,|db| {
// Now, set up surrounding context.
let sess = self.sess();
match diagnostic {
@@ -660,7 +664,7 @@ pub trait LintContext: Sized {
) => {
add_elided_lifetime_in_path_suggestion(
sess.source_map(),
- &mut db,
+ db,
n,
path_span,
incl_angl_brckt,
@@ -696,7 +700,7 @@ pub trait LintContext: Sized {
}
}
BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => {
- stability::deprecation_suggestion(&mut db, "macro", suggestion, span)
+ stability::deprecation_suggestion(db, "macro", suggestion, span)
}
BuiltinLintDiagnostics::UnusedDocComment(span) => {
db.span_label(span, "rustdoc does not generate documentation for macro invocations");
@@ -867,17 +871,25 @@ pub trait LintContext: Sized {
}
}
// Rewrap `db`, and pass control to the user.
- decorate(LintDiagnosticBuilder::new(db));
+ decorate(db)
});
}
// FIXME: These methods should not take an Into<MultiSpan> -- instead, callers should need to
// set the span in their `decorate` function (preferably using set_span).
+ /// Emit a lint at the appropriate level, with an optional associated span.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
fn lookup<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: Option<S>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
);
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
@@ -888,31 +900,48 @@ pub trait LintContext: Sized {
span: S,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag));
+ self.lookup(lint, Some(span), decorator.msg(), |diag| decorator.decorate_lint(diag));
}
+ /// Emit a lint at the appropriate level, with an associated span.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
fn struct_span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
span: S,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
- self.lookup(lint, Some(span), decorate);
+ self.lookup(lint, Some(span), msg, decorate);
}
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
/// generated by `#[derive(LintDiagnostic)]`).
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
- self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag));
+ self.lookup(lint, None as Option<Span>, decorator.msg(), |diag| {
+ decorator.decorate_lint(diag)
+ });
}
/// Emit a lint at the appropriate level, with no associated span.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
fn lint(
&self,
lint: &'static Lint,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
- self.lookup(lint, None as Option<Span>, decorate);
+ self.lookup(lint, None as Option<Span>, msg, decorate);
}
/// This returns the lint level for the given lint at the current location.
@@ -975,13 +1004,16 @@ impl<'tcx> LintContext for LateContext<'tcx> {
&self,
lint: &'static Lint,
span: Option<S>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
let hir_id = self.last_node_with_lint_attrs;
match span {
- Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, decorate),
- None => self.tcx.struct_lint_node(lint, hir_id, decorate),
+ Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg, decorate),
+ None => self.tcx.struct_lint_node(lint, hir_id, msg, decorate),
}
}
@@ -1006,9 +1038,12 @@ impl LintContext for EarlyContext<'_> {
&self,
lint: &'static Lint,
span: Option<S>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
- self.builder.struct_lint(lint, span.map(|s| s.into()), decorate)
+ self.builder.struct_lint(lint, span.map(|s| s.into()), msg, decorate)
}
fn get_lint_level(&self, lint: &'static Lint) -> Level {
@@ -1048,7 +1083,7 @@ impl<'tcx> LateContext<'tcx> {
.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))
+ Some(self.tcx.typeck(id.owner.def_id))
} else {
None
}
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 96ecd79a6..aee870dd2 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -43,9 +43,8 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
self.context.lookup_with_diagnostics(
lint_id.lint,
Some(span),
- |lint| {
- lint.build(msg).emit();
- },
+ msg,
+ |lint| lint,
diagnostic,
);
}
@@ -59,6 +58,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
F: FnOnce(&mut Self),
{
let is_crate_node = id == ast::CRATE_NODE_ID;
+ debug!(?id);
let push = self.context.builder.push(attrs, is_crate_node, None);
self.check_id(id);
@@ -409,7 +409,7 @@ pub fn check_ast_node<'a>(
if sess.opts.unstable_opts.no_interleave_lints {
for (i, pass) in passes.iter_mut().enumerate() {
buffered =
- sess.prof.extra_verbose_generic_activity("run_lint", pass.name()).run(|| {
+ sess.prof.verbose_generic_activity_with_arg("run_lint", pass.name()).run(|| {
early_lint_node(
sess,
!pre_expansion && i == 0,
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index f41ee6404..f9d746622 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -50,26 +50,24 @@ fn enforce_mem_discriminant(
) {
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
if is_non_enum(ty_param) {
- cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, expr_span, |builder| {
- builder
- .build(fluent::lint::enum_intrinsics_mem_discriminant)
- .set_arg("ty_param", ty_param)
- .span_note(args_span, fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ ENUM_INTRINSICS_NON_ENUMS,
+ expr_span,
+ fluent::lint_enum_intrinsics_mem_discriminant,
+ |lint| lint.set_arg("ty_param", ty_param).span_note(args_span, fluent::note),
+ );
}
}
fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
let ty_param = cx.typeck_results().node_substs(func_expr.hir_id).type_at(0);
if is_non_enum(ty_param) {
- cx.struct_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, |builder| {
- builder
- .build(fluent::lint::enum_intrinsics_mem_variant)
- .set_arg("ty_param", ty_param)
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ ENUM_INTRINSICS_NON_ENUMS,
+ span,
+ fluent::lint_enum_intrinsics_mem_variant,
+ |lint| lint.set_arg("ty_param", ty_param).note(fluent::note),
+ );
}
}
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index 5c183d409..a49d1bdac 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,10 +1,13 @@
-use rustc_errors::{fluent, AddSubdiagnostic, ErrorGuaranteed, Handler};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
-use rustc_session::{lint::Level, SessionDiagnostic};
+use rustc_errors::{
+ fluent, AddToDiagnostic, Diagnostic, ErrorGuaranteed, Handler, IntoDiagnostic,
+ SubdiagnosticMessage,
+};
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_session::lint::Level;
use rustc_span::{Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(lint::overruled_attribute, code = "E0453")]
+#[derive(Diagnostic)]
+#[diag(lint_overruled_attribute, code = "E0453")]
pub struct OverruledAttribute {
#[primary_span]
pub span: Span,
@@ -22,28 +25,31 @@ pub enum OverruledAttributeSub {
CommandLineSource,
}
-impl AddSubdiagnostic for OverruledAttributeSub {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
+impl AddToDiagnostic for OverruledAttributeSub {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
match self {
OverruledAttributeSub::DefaultSource { id } => {
- diag.note(fluent::lint::default_source);
+ diag.note(fluent::lint_default_source);
diag.set_arg("id", id);
}
OverruledAttributeSub::NodeSource { span, reason } => {
- diag.span_label(span, fluent::lint::node_source);
+ diag.span_label(span, fluent::lint_node_source);
if let Some(rationale) = reason {
diag.note(rationale.as_str());
}
}
OverruledAttributeSub::CommandLineSource => {
- diag.note(fluent::lint::command_line_source);
+ diag.note(fluent::lint_command_line_source);
}
}
}
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::malformed_attribute, code = "E0452")]
+#[derive(Diagnostic)]
+#[diag(lint_malformed_attribute, code = "E0452")]
pub struct MalformedAttribute {
#[primary_span]
pub span: Span,
@@ -51,18 +57,18 @@ pub struct MalformedAttribute {
pub sub: MalformedAttributeSub,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum MalformedAttributeSub {
- #[label(lint::bad_attribute_argument)]
+ #[label(lint_bad_attribute_argument)]
BadAttributeArgument(#[primary_span] Span),
- #[label(lint::reason_must_be_string_literal)]
+ #[label(lint_reason_must_be_string_literal)]
ReasonMustBeStringLiteral(#[primary_span] Span),
- #[label(lint::reason_must_come_last)]
+ #[label(lint_reason_must_come_last)]
ReasonMustComeLast(#[primary_span] Span),
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::unknown_tool_in_scoped_lint, code = "E0710")]
+#[derive(Diagnostic)]
+#[diag(lint_unknown_tool_in_scoped_lint, code = "E0710")]
pub struct UnknownToolInScopedLint {
#[primary_span]
pub span: Option<Span>,
@@ -72,8 +78,8 @@ pub struct UnknownToolInScopedLint {
pub is_nightly_build: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
+#[derive(Diagnostic)]
+#[diag(lint_builtin_ellipsis_inclusive_range_patterns, code = "E0783")]
pub struct BuiltinEllpisisInclusiveRangePatterns {
#[primary_span]
pub span: Span,
@@ -82,33 +88,15 @@ pub struct BuiltinEllpisisInclusiveRangePatterns {
pub replace: String,
}
+#[derive(Subdiagnostic)]
+#[note(lint_requested_level)]
pub struct RequestedLevel {
pub level: Level,
pub lint_name: String,
}
-impl AddSubdiagnostic for RequestedLevel {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
- diag.note(fluent::lint::requested_level);
- diag.set_arg(
- "level",
- match self.level {
- Level::Allow => "-A",
- Level::Warn => "-W",
- Level::ForceWarn(_) => "--force-warn",
- Level::Deny => "-D",
- Level::Forbid => "-F",
- Level::Expect(_) => {
- unreachable!("lints with the level of `expect` should not run this code");
- }
- },
- );
- diag.set_arg("lint_name", self.lint_name);
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(lint::unsupported_group, code = "E0602")]
+#[derive(Diagnostic)]
+#[diag(lint_unsupported_group, code = "E0602")]
pub struct UnsupportedGroup {
pub lint_group: String,
}
@@ -119,15 +107,15 @@ pub struct CheckNameUnknown {
pub sub: RequestedLevel,
}
-impl SessionDiagnostic<'_> for CheckNameUnknown {
+impl IntoDiagnostic<'_> for CheckNameUnknown {
fn into_diagnostic(
self,
handler: &Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(fluent::lint::check_name_unknown);
+ 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::lint::help);
+ diag.help(fluent::help);
diag.set_arg("suggestion", suggestion);
}
diag.set_arg("lint_name", self.lint_name);
@@ -136,24 +124,24 @@ impl SessionDiagnostic<'_> for CheckNameUnknown {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::check_name_unknown_tool, code = "E0602")]
+#[derive(Diagnostic)]
+#[diag(lint_check_name_unknown_tool, code = "E0602")]
pub struct CheckNameUnknownTool {
pub tool_name: Symbol,
#[subdiagnostic]
pub sub: RequestedLevel,
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::check_name_warning)]
+#[derive(Diagnostic)]
+#[diag(lint_check_name_warning)]
pub struct CheckNameWarning {
pub msg: String,
#[subdiagnostic]
pub sub: RequestedLevel,
}
-#[derive(SessionDiagnostic)]
-#[diag(lint::check_name_deprecated)]
+#[derive(Diagnostic)]
+#[diag(lint_check_name_deprecated)]
pub struct CheckNameDeprecated {
pub lint_name: String,
pub new_name: String,
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 699e81543..cf8f31bcb 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -16,8 +16,10 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
return;
}
+ let lint_expectations = tcx.lint_expectations(());
let fulfilled_expectations = tcx.sess.diagnostic().steal_fulfilled_expectation_ids();
- let lint_expectations = &tcx.lint_levels(()).lint_expectations;
+
+ tracing::debug!(?lint_expectations, ?fulfilled_expectations);
for (id, expectation) in lint_expectations {
// This check will always be true, since `lint_expectations` only
@@ -43,17 +45,17 @@ fn emit_unfulfilled_expectation_lint(
builtin::UNFULFILLED_LINT_EXPECTATIONS,
hir_id,
expectation.emission_span,
- |diag| {
- let mut diag = diag.build(fluent::lint::expectation);
+ fluent::lint_expectation,
+ |lint| {
if let Some(rationale) = expectation.reason {
- diag.note(rationale.as_str());
+ lint.note(rationale.as_str());
}
if expectation.is_unfulfilled_lint_expectations {
- diag.note(fluent::lint::note);
+ lint.note(fluent::note);
}
- diag.emit();
+ lint
},
);
}
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
new file mode 100644
index 000000000..ed8d424e0
--- /dev/null
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -0,0 +1,183 @@
+use crate::{LateContext, LateLintPass, LintContext};
+
+use hir::{Expr, Pat};
+use rustc_errors::{Applicability, DelayDm};
+use rustc_hir as hir;
+use rustc_infer::traits::TraitEngine;
+use rustc_infer::{infer::TyCtxtInferExt, traits::ObligationCause};
+use rustc_middle::ty::{self, List};
+use rustc_span::{sym, Span};
+use rustc_trait_selection::traits::TraitEngineExt;
+
+declare_lint! {
+ /// The `for_loops_over_fallibles` lint checks for `for` loops over `Option` or `Result` values.
+ ///
+ /// ### Example
+ ///
+ /// ```rust
+ /// let opt = Some(1);
+ /// for x in opt { /* ... */}
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// Both `Option` and `Result` implement `IntoIterator` trait, which allows using them in a `for` loop.
+ /// `for` loop over `Option` or `Result` will iterate either 0 (if the value is `None`/`Err(_)`)
+ /// or 1 time (if the value is `Some(_)`/`Ok(_)`). This is not very useful and is more clearly expressed
+ /// via `if let`.
+ ///
+ /// `for` loop can also be accidentally written with the intention to call a function multiple times,
+ /// while the function returns `Some(_)`, in these cases `while let` loop should be used instead.
+ ///
+ /// The "intended" use of `IntoIterator` implementations for `Option` and `Result` is passing them to
+ /// generic code that expects something implementing `IntoIterator`. For example using `.chain(option)`
+ /// to optionally add a value to an iterator.
+ pub FOR_LOOPS_OVER_FALLIBLES,
+ Warn,
+ "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"
+}
+
+declare_lint_pass!(ForLoopsOverFallibles => [FOR_LOOPS_OVER_FALLIBLES]);
+
+impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ let Some((pat, arg)) = extract_for_loop(expr) else { return };
+
+ let ty = cx.typeck_results().expr_ty(arg);
+
+ let &ty::Adt(adt, substs) = ty.kind() else { return };
+
+ let (article, ty, var) = match adt.did() {
+ did if cx.tcx.is_diagnostic_item(sym::Option, did) => ("an", "Option", "Some"),
+ did if cx.tcx.is_diagnostic_item(sym::Result, did) => ("a", "Result", "Ok"),
+ _ => return,
+ };
+
+ let msg = DelayDm(|| {
+ format!(
+ "for loop over {article} `{ty}`. This is more readably written as an `if let` statement",
+ )
+ });
+
+ cx.struct_span_lint(FOR_LOOPS_OVER_FALLIBLES, arg.span, msg, |lint| {
+ if let Some(recv) = extract_iterator_next_call(cx, arg)
+ && let Ok(recv_snip) = cx.sess().source_map().span_to_snippet(recv.span)
+ {
+ lint.span_suggestion(
+ recv.span.between(arg.span.shrink_to_hi()),
+ format!("to iterate over `{recv_snip}` remove the call to `next`"),
+ ".by_ref()",
+ Applicability::MaybeIncorrect
+ );
+ } else {
+ lint.multipart_suggestion_verbose(
+ format!("to check pattern in a loop use `while let`"),
+ vec![
+ // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
+ (expr.span.with_hi(pat.span.lo()), format!("while let {var}(")),
+ (pat.span.between(arg.span), format!(") = ")),
+ ],
+ Applicability::MaybeIncorrect
+ );
+ }
+
+ if suggest_question_mark(cx, adt, substs, expr.span) {
+ lint.span_suggestion(
+ arg.span.shrink_to_hi(),
+ "consider unwrapping the `Result` with `?` to iterate over its contents",
+ "?",
+ Applicability::MaybeIncorrect,
+ );
+ }
+
+ lint.multipart_suggestion_verbose(
+ "consider using `if let` to clear intent",
+ vec![
+ // NB can't use `until` here because `expr.span` and `pat.span` have different syntax contexts
+ (expr.span.with_hi(pat.span.lo()), format!("if let {var}(")),
+ (pat.span.between(arg.span), format!(") = ")),
+ ],
+ Applicability::MaybeIncorrect,
+ )
+ })
+ }
+}
+
+fn extract_for_loop<'tcx>(expr: &Expr<'tcx>) -> Option<(&'tcx Pat<'tcx>, &'tcx Expr<'tcx>)> {
+ if let hir::ExprKind::DropTemps(e) = expr.kind
+ && let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind
+ && let hir::ExprKind::Call(_, [arg]) = iterexpr.kind
+ && let hir::ExprKind::Loop(block, ..) = arm.body.kind
+ && let [stmt] = block.stmts
+ && let hir::StmtKind::Expr(e) = stmt.kind
+ && let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind
+ && let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind
+ {
+ Some((field.pat, arg))
+ } else {
+ None
+ }
+}
+
+fn extract_iterator_next_call<'tcx>(
+ cx: &LateContext<'_>,
+ expr: &Expr<'tcx>,
+) -> Option<&'tcx Expr<'tcx>> {
+ // This won't work for `Iterator::next(iter)`, is this an issue?
+ if let hir::ExprKind::MethodCall(_, recv, _, _) = expr.kind
+ && cx.typeck_results().type_dependent_def_id(expr.hir_id) == cx.tcx.lang_items().next_fn()
+ {
+ Some(recv)
+ } else {
+ return None
+ }
+}
+
+fn suggest_question_mark<'tcx>(
+ cx: &LateContext<'tcx>,
+ adt: ty::AdtDef<'tcx>,
+ substs: &List<ty::GenericArg<'tcx>>,
+ span: Span,
+) -> bool {
+ let Some(body_id) = cx.enclosing_body else { return false };
+ let Some(into_iterator_did) = cx.tcx.get_diagnostic_item(sym::IntoIterator) else { return false };
+
+ if !cx.tcx.is_diagnostic_item(sym::Result, adt.did()) {
+ return false;
+ }
+
+ // Check that the function/closure/constant we are in has a `Result` type.
+ // Otherwise suggesting using `?` may not be a good idea.
+ {
+ let ty = cx.typeck_results().expr_ty(&cx.tcx.hir().body(body_id).value);
+ let ty::Adt(ret_adt, ..) = ty.kind() else { return false };
+ if !cx.tcx.is_diagnostic_item(sym::Result, ret_adt.did()) {
+ return false;
+ }
+ }
+
+ let ty = substs.type_at(0);
+ let infcx = cx.tcx.infer_ctxt().build();
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+
+ let cause = ObligationCause::new(
+ span,
+ body_id.hir_id,
+ rustc_infer::traits::ObligationCauseCode::MiscObligation,
+ );
+ fulfill_cx.register_bound(
+ &infcx,
+ ty::ParamEnv::empty(),
+ // Erase any region vids from the type, which may not be resolved
+ infcx.tcx.erase_regions(ty),
+ into_iterator_did,
+ cause,
+ );
+
+ // Select all, including ambiguous predicates
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+
+ errors.is_empty()
+}
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index 8f2222132..7e884e990 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -60,52 +60,56 @@ impl HiddenUnicodeCodepoints {
})
.collect();
- cx.struct_span_lint(TEXT_DIRECTION_CODEPOINT_IN_LITERAL, span, |lint| {
- let mut err = lint.build(fluent::lint::hidden_unicode_codepoints);
- err.set_arg("label", label);
- err.set_arg("count", spans.len());
- err.span_label(span, fluent::lint::label);
- err.note(fluent::lint::note);
- if point_at_inner_spans {
- for (c, span) in &spans {
- err.span_label(*span, format!("{:?}", c));
+ cx.struct_span_lint(
+ TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
+ span,
+ fluent::lint_hidden_unicode_codepoints,
+ |lint| {
+ lint.set_arg("label", label);
+ lint.set_arg("count", spans.len());
+ lint.span_label(span, fluent::label);
+ lint.note(fluent::note);
+ if point_at_inner_spans {
+ for (c, span) in &spans {
+ lint.span_label(*span, format!("{:?}", c));
+ }
}
- }
- if point_at_inner_spans && !spans.is_empty() {
- err.multipart_suggestion_with_style(
- fluent::lint::suggestion_remove,
- spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
- Applicability::MachineApplicable,
- SuggestionStyle::HideCodeAlways,
- );
- err.multipart_suggestion(
- fluent::lint::suggestion_escape,
- spans
- .into_iter()
- .map(|(c, span)| {
- let c = format!("{:?}", c);
- (span, c[1..c.len() - 1].to_string())
- })
- .collect(),
- Applicability::MachineApplicable,
- );
- } else {
- // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
- // should do the same here to provide the same good suggestions as we do for
- // literals above.
- err.set_arg(
- "escaped",
- spans
- .into_iter()
- .map(|(c, _)| format!("{:?}", c))
- .collect::<Vec<String>>()
- .join(", "),
- );
- err.note(fluent::lint::suggestion_remove);
- err.note(fluent::lint::no_suggestion_note_escape);
- }
- err.emit();
- });
+ if point_at_inner_spans && !spans.is_empty() {
+ lint.multipart_suggestion_with_style(
+ fluent::suggestion_remove,
+ spans.iter().map(|(_, span)| (*span, "".to_string())).collect(),
+ Applicability::MachineApplicable,
+ SuggestionStyle::HideCodeAlways,
+ );
+ lint.multipart_suggestion(
+ fluent::suggestion_escape,
+ spans
+ .into_iter()
+ .map(|(c, span)| {
+ let c = format!("{:?}", c);
+ (span, c[1..c.len() - 1].to_string())
+ })
+ .collect(),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ // FIXME: in other suggestions we've reversed the inner spans of doc comments. We
+ // should do the same here to provide the same good suggestions as we do for
+ // literals above.
+ lint.set_arg(
+ "escaped",
+ spans
+ .into_iter()
+ .map(|(c, _)| format!("{:?}", c))
+ .collect::<Vec<String>>()
+ .join(", "),
+ );
+ lint.note(fluent::suggestion_remove);
+ lint.note(fluent::no_suggestion_note_escape);
+ }
+ lint
+ },
+ );
}
}
impl EarlyLintPass for HiddenUnicodeCodepoints {
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index dd1fc5916..11e4650cb 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -34,13 +34,16 @@ impl LateLintPass<'_> for DefaultHashTypes {
Some(sym::HashSet) => "FxHashSet",
_ => return,
};
- cx.struct_span_lint(DEFAULT_HASH_TYPES, path.span, |lint| {
- lint.build(fluent::lint::default_hash_types)
- .set_arg("preferred", replace)
- .set_arg("used", cx.tcx.item_name(def_id))
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ DEFAULT_HASH_TYPES,
+ path.span,
+ fluent::lint_default_hash_types,
+ |lint| {
+ lint.set_arg("preferred", replace)
+ .set_arg("used", cx.tcx.item_name(def_id))
+ .note(fluent::note)
+ },
+ );
}
}
@@ -80,12 +83,12 @@ impl LateLintPass<'_> for QueryStability {
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, substs) {
let def_id = instance.def_id();
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
- cx.struct_span_lint(POTENTIAL_QUERY_INSTABILITY, span, |lint| {
- lint.build(fluent::lint::query_instability)
- .set_arg("query", cx.tcx.item_name(def_id))
- .note(fluent::lint::note)
- .emit();
- })
+ cx.struct_span_lint(
+ POTENTIAL_QUERY_INSTABILITY,
+ span,
+ fluent::lint_query_instability,
+ |lint| lint.set_arg("query", cx.tcx.item_name(def_id)).note(fluent::note),
+ )
}
}
}
@@ -123,15 +126,14 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
let span = path.span.with_hi(
segment.args.map_or(segment.ident.span, |a| a.span_ext).hi()
);
- cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
- lint.build(fluent::lint::tykind_kind)
+ cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, fluent::lint_tykind_kind, |lint| {
+ lint
.span_suggestion(
span,
- fluent::lint::suggestion,
+ fluent::suggestion,
"ty",
Applicability::MaybeIncorrect, // ty maybe needs an import
)
- .emit();
});
}
}
@@ -140,85 +142,85 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
match &ty.kind {
TyKind::Path(QPath::Resolved(_, path)) => {
if lint_ty_kind_usage(cx, &path.res) {
- cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, |lint| {
- let hir = cx.tcx.hir();
- match hir.find(hir.get_parent_node(ty.hir_id)) {
- Some(Node::Pat(Pat {
- kind:
- PatKind::Path(qpath)
- | PatKind::TupleStruct(qpath, ..)
- | PatKind::Struct(qpath, ..),
- ..
- })) => {
- if let QPath::TypeRelative(qpath_ty, ..) = qpath
- && qpath_ty.hir_id == ty.hir_id
- {
- lint.build(fluent::lint::tykind_kind)
- .span_suggestion(
- path.span,
- fluent::lint::suggestion,
- "ty",
- Applicability::MaybeIncorrect, // ty maybe needs an import
- )
- .emit();
- return;
- }
+ let hir = cx.tcx.hir();
+ let span = match hir.find(hir.get_parent_node(ty.hir_id)) {
+ Some(Node::Pat(Pat {
+ kind:
+ PatKind::Path(qpath)
+ | PatKind::TupleStruct(qpath, ..)
+ | PatKind::Struct(qpath, ..),
+ ..
+ })) => {
+ if let QPath::TypeRelative(qpath_ty, ..) = qpath
+ && qpath_ty.hir_id == ty.hir_id
+ {
+ Some(path.span)
+ } else {
+ None
}
- Some(Node::Expr(Expr {
- kind: ExprKind::Path(qpath),
- ..
- })) => {
- if let QPath::TypeRelative(qpath_ty, ..) = qpath
- && qpath_ty.hir_id == ty.hir_id
- {
- lint.build(fluent::lint::tykind_kind)
- .span_suggestion(
- path.span,
- fluent::lint::suggestion,
- "ty",
- Applicability::MaybeIncorrect, // ty maybe needs an import
- )
- .emit();
- return;
- }
+ }
+ Some(Node::Expr(Expr {
+ kind: ExprKind::Path(qpath),
+ ..
+ })) => {
+ if let QPath::TypeRelative(qpath_ty, ..) = qpath
+ && qpath_ty.hir_id == ty.hir_id
+ {
+ Some(path.span)
+ } else {
+ None
}
- // Can't unify these two branches because qpath below is `&&` and above is `&`
- // and `A | B` paths don't play well together with adjustments, apparently.
- Some(Node::Expr(Expr {
- kind: ExprKind::Struct(qpath, ..),
- ..
- })) => {
- if let QPath::TypeRelative(qpath_ty, ..) = qpath
- && qpath_ty.hir_id == ty.hir_id
- {
- lint.build(fluent::lint::tykind_kind)
- .span_suggestion(
- path.span,
- fluent::lint::suggestion,
- "ty",
- Applicability::MaybeIncorrect, // ty maybe needs an import
- )
- .emit();
- return;
- }
+ }
+ // Can't unify these two branches because qpath below is `&&` and above is `&`
+ // and `A | B` paths don't play well together with adjustments, apparently.
+ Some(Node::Expr(Expr {
+ kind: ExprKind::Struct(qpath, ..),
+ ..
+ })) => {
+ if let QPath::TypeRelative(qpath_ty, ..) = qpath
+ && qpath_ty.hir_id == ty.hir_id
+ {
+ Some(path.span)
+ } else {
+ None
}
- _ => {}
}
- lint.build(fluent::lint::tykind).help(fluent::lint::help).emit();
- })
+ _ => None
+ };
+
+ match span {
+ Some(span) => {
+ cx.struct_span_lint(
+ USAGE_OF_TY_TYKIND,
+ path.span,
+ fluent::lint_tykind_kind,
+ |lint| lint.span_suggestion(
+ span,
+ fluent::suggestion,
+ "ty",
+ Applicability::MaybeIncorrect, // ty maybe needs an import
+ )
+ )
+ },
+ None => cx.struct_span_lint(
+ USAGE_OF_TY_TYKIND,
+ path.span,
+ fluent::lint_tykind,
+ |lint| lint.help(fluent::help)
+ )
+ }
} else if !ty.span.from_expansion() && let Some(t) = is_ty_or_ty_ctxt(cx, &path) {
if path.segments.len() > 1 {
- cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, |lint| {
- lint.build(fluent::lint::ty_qualified)
+ cx.struct_span_lint(USAGE_OF_QUALIFIED_TY, path.span, fluent::lint_ty_qualified, |lint| {
+ lint
.set_arg("ty", t.clone())
.span_suggestion(
path.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
t,
// The import probably needs to be changed
Applicability::MaybeIncorrect,
)
- .emit();
})
}
}
@@ -244,7 +246,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::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
+ Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).kind() {
if let Some(name @ (sym::Ty | sym::TyCtxt)) = cx.tcx.get_diagnostic_name(adt.did())
{
@@ -308,11 +310,8 @@ impl EarlyLintPass for LintPassImpl {
cx.struct_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span,
- |lint| {
- lint.build(fluent::lint::lintpass_by_hand)
- .help(fluent::lint::help)
- .emit();
- },
+ fluent::lint_lintpass_by_hand,
+ |lint| lint.help(fluent::help),
)
}
}
@@ -349,12 +348,12 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
if is_doc_keyword(v) {
return;
}
- cx.struct_span_lint(EXISTING_DOC_KEYWORD, attr.span, |lint| {
- lint.build(fluent::lint::non_existant_doc_keyword)
- .set_arg("keyword", v)
- .help(fluent::lint::help)
- .emit();
- });
+ cx.struct_span_lint(
+ EXISTING_DOC_KEYWORD,
+ attr.span,
+ fluent::lint_non_existant_doc_keyword,
+ |lint| lint.set_arg("keyword", v).help(fluent::help),
+ );
}
}
}
@@ -372,7 +371,7 @@ declare_tool_lint! {
declare_tool_lint! {
pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
Allow,
- "prevent creation of diagnostics outside of `SessionDiagnostic`/`AddSubdiagnostic` impls",
+ "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls",
report_in_external_macro: true
}
@@ -404,7 +403,7 @@ impl LateLintPass<'_> for Diagnostics {
let Impl { of_trait: Some(of_trait), .. } = impl_ &&
let Some(def_id) = of_trait.trait_def_id() &&
let Some(name) = cx.tcx.get_diagnostic_name(def_id) &&
- matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic | sym::DecorateLint)
+ matches!(name, sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint)
{
found_impl = true;
break;
@@ -412,9 +411,12 @@ impl LateLintPass<'_> for Diagnostics {
}
debug!(?found_impl);
if !found_parent_with_attr && !found_impl {
- cx.struct_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, |lint| {
- lint.build(fluent::lint::diag_out_of_impl).emit();
- })
+ cx.struct_span_lint(
+ DIAGNOSTIC_OUTSIDE_OF_IMPL,
+ span,
+ fluent::lint_diag_out_of_impl,
+ |lint| lint,
+ )
}
let mut found_diagnostic_message = false;
@@ -430,9 +432,12 @@ impl LateLintPass<'_> for Diagnostics {
}
debug!(?found_diagnostic_message);
if !found_parent_with_attr && !found_diagnostic_message {
- cx.struct_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, |lint| {
- lint.build(fluent::lint::untranslatable_diag).emit();
- })
+ cx.struct_span_lint(
+ UNTRANSLATABLE_DIAGNOSTIC,
+ span,
+ fluent::lint_untranslatable_diag,
+ |lint| lint,
+ )
}
}
}
@@ -464,8 +469,8 @@ impl LateLintPass<'_> for BadOptAccess {
let Some(literal) = item.literal() &&
let ast::LitKind::Str(val, _) = literal.kind
{
- cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, |lint| {
- lint.build(val.as_str()).emit(); }
+ cx.struct_span_lint(BAD_OPT_ACCESS, expr.span, val.as_str(), |lint|
+ lint
);
}
}
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index da6f1c5ee..303fcb1a1 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -338,14 +338,14 @@ fn late_lint_mod_pass<'tcx, T: LateLintPass<'tcx>>(
module_def_id: LocalDefId,
pass: T,
) {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
- access_levels,
+ effective_visibilities,
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: tcx.hir().local_def_id_to_hir_id(module_def_id),
generics: None,
@@ -386,14 +386,14 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx>>(
}
fn late_lint_pass_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, pass: T) {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
let context = LateContext {
tcx,
enclosing_body: None,
cached_typeck_results: Cell::new(None),
param_env: ty::ParamEnv::empty(),
- access_levels,
+ effective_visibilities,
lint_store: unerased_lint_store(tcx),
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
generics: None,
@@ -425,20 +425,23 @@ fn late_lint_crate<'tcx, T: LateLintPass<'tcx>>(tcx: TyCtxt<'tcx>, builtin_lints
late_lint_pass_crate(tcx, builtin_lints);
} else {
for pass in &mut passes {
- tcx.sess.prof.extra_verbose_generic_activity("run_late_lint", pass.name()).run(|| {
- late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
- });
+ tcx.sess.prof.verbose_generic_activity_with_arg("run_late_lint", pass.name()).run(
+ || {
+ late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
+ },
+ );
}
let mut passes: Vec<_> =
unerased_lint_store(tcx).late_module_passes.iter().map(|pass| (pass)(tcx)).collect();
for pass in &mut passes {
- tcx.sess.prof.extra_verbose_generic_activity("run_late_module_lint", pass.name()).run(
- || {
+ tcx.sess
+ .prof
+ .verbose_generic_activity_with_arg("run_late_module_lint", pass.name())
+ .run(|| {
late_lint_pass_crate(tcx, LateLintPassObjects { lints: slice::from_mut(pass) });
- },
- );
+ });
}
}
}
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index 7e885e6c5..78f355ec3 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -1,5 +1,5 @@
use crate::{LateContext, LateLintPass, LintContext};
-use rustc_errors::{Applicability, LintDiagnosticBuilder, MultiSpan};
+use rustc_errors::{Applicability, DiagnosticBuilder, MultiSpan};
use rustc_hir as hir;
use rustc_middle::ty;
use rustc_span::Symbol;
@@ -128,48 +128,41 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
init.span,
"this binding will immediately drop the value assigned to it".to_string(),
);
- cx.struct_span_lint(LET_UNDERSCORE_LOCK, span, |lint| {
- build_and_emit_lint(
- lint,
- local,
- init.span,
- "non-binding let on a synchronization lock",
- )
- })
+ cx.struct_span_lint(
+ LET_UNDERSCORE_LOCK,
+ span,
+ "non-binding let on a synchronization lock",
+ |lint| build_lint(lint, local, init.span),
+ )
} else {
- cx.struct_span_lint(LET_UNDERSCORE_DROP, local.span, |lint| {
- build_and_emit_lint(
- lint,
- local,
- init.span,
- "non-binding let on a type that implements `Drop`",
- );
- })
+ cx.struct_span_lint(
+ LET_UNDERSCORE_DROP,
+ local.span,
+ "non-binding let on a type that implements `Drop`",
+ |lint| build_lint(lint, local, init.span),
+ )
}
}
}
}
-fn build_and_emit_lint(
- lint: LintDiagnosticBuilder<'_, ()>,
+fn build_lint<'a, 'b>(
+ lint: &'a mut DiagnosticBuilder<'b, ()>,
local: &hir::Local<'_>,
init_span: rustc_span::Span,
- msg: &str,
-) {
- lint.build(msg)
- .span_suggestion_verbose(
- local.pat.span,
- "consider binding to an unused variable to avoid immediately dropping the value",
- "_unused",
- Applicability::MachineApplicable,
- )
- .multipart_suggestion(
- "consider immediately dropping the value",
- vec![
- (local.span.until(init_span), "drop(".to_string()),
- (init_span.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
+) -> &'a mut DiagnosticBuilder<'b, ()> {
+ lint.span_suggestion_verbose(
+ local.pat.span,
+ "consider binding to an unused variable to avoid immediately dropping the value",
+ "_unused",
+ Applicability::MachineApplicable,
+ )
+ .multipart_suggestion(
+ "consider immediately dropping the value",
+ vec![
+ (local.span.until(init_span), "drop(".to_string()),
+ (init_span.shrink_to_hi(), ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ )
}
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 1e16ac51e..db0a3419e 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -3,13 +3,15 @@ use crate::late::unerased_lint_store;
use rustc_ast as ast;
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
+use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
use rustc_hir as hir;
-use rustc_hir::{intravisit, HirId};
+use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::HirId;
+use rustc_index::vec::IndexVec;
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::{
- struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets,
- LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE,
+ reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
+ ShallowLintLevelMap,
};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{RegisteredTools, TyCtxt};
@@ -27,47 +29,408 @@ use crate::errors::{
UnknownToolInScopedLint,
};
-fn lint_levels(tcx: TyCtxt<'_>, (): ()) -> LintLevelMap {
- let store = unerased_lint_store(tcx);
- let levels =
- LintLevelsBuilder::new(tcx.sess, false, &store, &tcx.resolutions(()).registered_tools);
- let mut builder = LintLevelMapBuilder { levels, tcx };
- let krate = tcx.hir().krate();
+/// Collection of lint levels for the whole crate.
+/// This is used by AST-based lints, which do not
+/// wait until we have built HIR to be emitted.
+#[derive(Debug)]
+struct LintLevelSets {
+ /// Linked list of specifications.
+ list: IndexVec<LintStackIndex, LintSet>,
+}
+
+rustc_index::newtype_index! {
+ struct LintStackIndex {
+ ENCODABLE = custom, // we don't need encoding
+ const COMMAND_LINE = 0,
+ }
+}
+
+/// Specifications found at this position in the stack. This map only represents the lints
+/// found for one set of attributes (like `shallow_lint_levels_on` does).
+///
+/// We store the level specifications as a linked list.
+/// Each `LintSet` represents a set of attributes on the same AST node.
+/// The `parent` forms a linked list that matches the AST tree.
+/// This way, walking the linked list is equivalent to walking the AST bottom-up
+/// to find the specifications for a given lint.
+#[derive(Debug)]
+struct LintSet {
+ // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
+ // flag.
+ specs: FxHashMap<LintId, LevelAndSource>,
+ parent: LintStackIndex,
+}
+
+impl LintLevelSets {
+ fn new() -> Self {
+ LintLevelSets { list: IndexVec::new() }
+ }
+
+ fn get_lint_level(
+ &self,
+ lint: &'static Lint,
+ idx: LintStackIndex,
+ aux: Option<&FxHashMap<LintId, LevelAndSource>>,
+ sess: &Session,
+ ) -> LevelAndSource {
+ let lint = LintId::of(lint);
+ let (level, mut src) = self.raw_lint_id_level(lint, idx, aux);
+ let level = reveal_actual_level(level, &mut src, sess, lint, |id| {
+ self.raw_lint_id_level(id, idx, aux)
+ });
+ (level, src)
+ }
- builder.levels.id_to_set.reserve(krate.owners.len() + 1);
+ fn raw_lint_id_level(
+ &self,
+ id: LintId,
+ mut idx: LintStackIndex,
+ aux: Option<&FxHashMap<LintId, LevelAndSource>>,
+ ) -> (Option<Level>, LintLevelSource) {
+ if let Some(specs) = aux {
+ if let Some(&(level, src)) = specs.get(&id) {
+ return (Some(level), src);
+ }
+ }
+ loop {
+ let LintSet { ref specs, parent } = self.list[idx];
+ if let Some(&(level, src)) = specs.get(&id) {
+ return (Some(level), src);
+ }
+ if idx == COMMAND_LINE {
+ return (None, LintLevelSource::Default);
+ }
+ idx = parent;
+ }
+ }
+}
- let push =
- builder.levels.push(tcx.hir().attrs(hir::CRATE_HIR_ID), true, Some(hir::CRATE_HIR_ID));
+fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> {
+ let store = unerased_lint_store(tcx);
- builder.levels.register_id(hir::CRATE_HIR_ID);
+ let mut builder = LintLevelsBuilder {
+ sess: tcx.sess,
+ provider: QueryMapExpectationsWrapper {
+ tcx,
+ cur: hir::CRATE_HIR_ID,
+ specs: ShallowLintLevelMap::default(),
+ expectations: Vec::new(),
+ unstable_to_stable_ids: FxHashMap::default(),
+ empty: FxHashMap::default(),
+ },
+ warn_about_weird_lints: false,
+ store,
+ registered_tools: &tcx.resolutions(()).registered_tools,
+ };
+
+ builder.add_command_line();
+ builder.add_id(hir::CRATE_HIR_ID);
tcx.hir().walk_toplevel_module(&mut builder);
- builder.levels.pop(push);
- builder.levels.update_unstable_expectation_ids();
- builder.levels.build_map()
+ tcx.sess.diagnostic().update_unstable_expectation_id(&builder.provider.unstable_to_stable_ids);
+
+ builder.provider.expectations
}
-pub struct LintLevelsBuilder<'s> {
- sess: &'s Session,
- lint_expectations: Vec<(LintExpectationId, LintExpectation)>,
- /// Each expectation has a stable and an unstable identifier. This map
- /// is used to map from unstable to stable [`LintExpectationId`]s.
- expectation_id_map: FxHashMap<LintExpectationId, LintExpectationId>,
+#[instrument(level = "trace", skip(tcx), ret)]
+fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
+ let store = unerased_lint_store(tcx);
+ let attrs = tcx.hir_attrs(owner);
+
+ let mut levels = LintLevelsBuilder {
+ sess: tcx.sess,
+ provider: LintLevelQueryMap {
+ tcx,
+ cur: owner.into(),
+ specs: ShallowLintLevelMap::default(),
+ empty: FxHashMap::default(),
+ attrs,
+ },
+ warn_about_weird_lints: false,
+ store,
+ registered_tools: &tcx.resolutions(()).registered_tools,
+ };
+
+ if owner == hir::CRATE_OWNER_ID {
+ levels.add_command_line();
+ }
+
+ match attrs.map.range(..) {
+ // There is only something to do if there are attributes at all.
+ [] => {}
+ // Most of the time, there is only one attribute. Avoid fetching HIR in that case.
+ [(local_id, _)] => levels.add_id(HirId { owner, local_id: *local_id }),
+ // Otherwise, we need to visit the attributes in source code order, so we fetch HIR and do
+ // a standard visit.
+ // FIXME(#102522) Just iterate on attrs once that iteration order matches HIR's.
+ _ => match tcx.hir().expect_owner(owner) {
+ hir::OwnerNode::Item(item) => levels.visit_item(item),
+ hir::OwnerNode::ForeignItem(item) => levels.visit_foreign_item(item),
+ hir::OwnerNode::TraitItem(item) => levels.visit_trait_item(item),
+ hir::OwnerNode::ImplItem(item) => levels.visit_impl_item(item),
+ hir::OwnerNode::Crate(mod_) => {
+ levels.add_id(hir::CRATE_HIR_ID);
+ levels.visit_mod(mod_, mod_.spans.inner_span, hir::CRATE_HIR_ID)
+ }
+ },
+ }
+
+ let specs = levels.provider.specs;
+
+ #[cfg(debug_assertions)]
+ for (_, v) in specs.specs.iter() {
+ debug_assert!(!v.is_empty());
+ }
+
+ specs
+}
+
+pub struct TopDown {
sets: LintLevelSets,
- id_to_set: FxHashMap<HirId, LintStackIndex>,
cur: LintStackIndex,
+}
+
+pub trait LintLevelsProvider {
+ fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource>;
+ fn insert(&mut self, id: LintId, lvl: LevelAndSource);
+ fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource;
+ fn push_expectation(&mut self, _id: LintExpectationId, _expectation: LintExpectation) {}
+}
+
+impl LintLevelsProvider for TopDown {
+ fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
+ &self.sets.list[self.cur].specs
+ }
+
+ fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
+ self.sets.list[self.cur].specs.insert(id, lvl);
+ }
+
+ fn get_lint_level(&self, lint: &'static Lint, sess: &Session) -> LevelAndSource {
+ self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), sess)
+ }
+}
+
+struct LintLevelQueryMap<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ cur: HirId,
+ specs: ShallowLintLevelMap,
+ /// Empty hash map to simplify code.
+ empty: FxHashMap<LintId, LevelAndSource>,
+ attrs: &'tcx hir::AttributeMap<'tcx>,
+}
+
+impl LintLevelsProvider for LintLevelQueryMap<'_> {
+ fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
+ self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
+ }
+ fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
+ self.specs.specs.get_mut_or_insert_default(self.cur.local_id).insert(id, lvl);
+ }
+ fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
+ self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
+ }
+}
+
+struct QueryMapExpectationsWrapper<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ cur: HirId,
+ specs: ShallowLintLevelMap,
+ expectations: Vec<(LintExpectationId, LintExpectation)>,
+ unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>,
+ /// Empty hash map to simplify code.
+ empty: FxHashMap<LintId, LevelAndSource>,
+}
+
+impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
+ fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
+ self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
+ }
+ fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
+ let specs = self.specs.specs.get_mut_or_insert_default(self.cur.local_id);
+ specs.clear();
+ specs.insert(id, lvl);
+ }
+ fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
+ self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
+ }
+ fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
+ let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") };
+ let key = LintExpectationId::Unstable { attr_id, lint_index: None };
+
+ if !self.unstable_to_stable_ids.contains_key(&key) {
+ self.unstable_to_stable_ids.insert(
+ key,
+ LintExpectationId::Stable { hir_id, attr_index, lint_index: None, attr_id: None },
+ );
+ }
+
+ self.expectations.push((id.normalize(), expectation));
+ }
+}
+
+impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
+ fn add_id(&mut self, hir_id: HirId) {
+ self.provider.cur = hir_id;
+ self.add(
+ self.provider.attrs.get(hir_id.local_id),
+ hir_id == hir::CRATE_HIR_ID,
+ Some(hir_id),
+ );
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
+ type NestedFilter = nested_filter::OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.provider.tcx.hir()
+ }
+
+ fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+ self.add_id(param.hir_id);
+ intravisit::walk_param(self, param);
+ }
+
+ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
+ self.add_id(it.hir_id());
+ intravisit::walk_item(self, it);
+ }
+
+ fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
+ self.add_id(it.hir_id());
+ intravisit::walk_foreign_item(self, it);
+ }
+
+ fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) {
+ // We will call `add_id` when we walk
+ // the `StmtKind`. The outer statement itself doesn't
+ // define the lint levels.
+ intravisit::walk_stmt(self, e);
+ }
+
+ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
+ self.add_id(e.hir_id);
+ intravisit::walk_expr(self, e);
+ }
+
+ fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
+ self.add_id(s.hir_id);
+ intravisit::walk_field_def(self, s);
+ }
+
+ fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) {
+ self.add_id(v.id);
+ intravisit::walk_variant(self, v);
+ }
+
+ fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
+ self.add_id(l.hir_id);
+ intravisit::walk_local(self, l);
+ }
+
+ fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
+ self.add_id(a.hir_id);
+ intravisit::walk_arm(self, a);
+ }
+
+ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
+ self.add_id(trait_item.hir_id());
+ intravisit::walk_trait_item(self, trait_item);
+ }
+
+ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
+ self.add_id(impl_item.hir_id());
+ intravisit::walk_impl_item(self, impl_item);
+ }
+}
+
+impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
+ fn add_id(&mut self, hir_id: HirId) {
+ self.provider.cur = hir_id;
+ self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id));
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
+ type NestedFilter = nested_filter::All;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.provider.tcx.hir()
+ }
+
+ fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
+ self.add_id(param.hir_id);
+ intravisit::walk_param(self, param);
+ }
+
+ fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
+ self.add_id(it.hir_id());
+ intravisit::walk_item(self, it);
+ }
+
+ fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
+ self.add_id(it.hir_id());
+ intravisit::walk_foreign_item(self, it);
+ }
+
+ fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) {
+ // We will call `add_id` when we walk
+ // the `StmtKind`. The outer statement itself doesn't
+ // define the lint levels.
+ intravisit::walk_stmt(self, e);
+ }
+
+ fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
+ self.add_id(e.hir_id);
+ intravisit::walk_expr(self, e);
+ }
+
+ fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
+ self.add_id(s.hir_id);
+ intravisit::walk_field_def(self, s);
+ }
+
+ fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) {
+ self.add_id(v.id);
+ intravisit::walk_variant(self, v);
+ }
+
+ fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
+ self.add_id(l.hir_id);
+ intravisit::walk_local(self, l);
+ }
+
+ fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
+ self.add_id(a.hir_id);
+ intravisit::walk_arm(self, a);
+ }
+
+ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
+ self.add_id(trait_item.hir_id());
+ intravisit::walk_trait_item(self, trait_item);
+ }
+
+ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
+ self.add_id(impl_item.hir_id());
+ intravisit::walk_impl_item(self, impl_item);
+ }
+}
+
+pub struct LintLevelsBuilder<'s, P> {
+ sess: &'s Session,
+ provider: P,
warn_about_weird_lints: bool,
store: &'s LintStore,
registered_tools: &'s RegisteredTools,
}
-pub struct BuilderPush {
+pub(crate) struct BuilderPush {
prev: LintStackIndex,
- pub changed: bool,
}
-impl<'s> LintLevelsBuilder<'s> {
- pub fn new(
+impl<'s> LintLevelsBuilder<'s, TopDown> {
+ pub(crate) fn new(
sess: &'s Session,
warn_about_weird_lints: bool,
store: &'s LintStore,
@@ -75,20 +438,74 @@ impl<'s> LintLevelsBuilder<'s> {
) -> Self {
let mut builder = LintLevelsBuilder {
sess,
- lint_expectations: Default::default(),
- expectation_id_map: Default::default(),
- sets: LintLevelSets::new(),
- cur: COMMAND_LINE,
- id_to_set: Default::default(),
+ provider: TopDown { sets: LintLevelSets::new(), cur: COMMAND_LINE },
warn_about_weird_lints,
store,
registered_tools,
};
- builder.process_command_line(sess, store);
- assert_eq!(builder.sets.list.len(), 1);
+ builder.process_command_line();
+ assert_eq!(builder.provider.sets.list.len(), 1);
builder
}
+ fn process_command_line(&mut self) {
+ self.provider.cur = self
+ .provider
+ .sets
+ .list
+ .push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE });
+ self.add_command_line();
+ }
+
+ /// Pushes a list of AST lint attributes onto this context.
+ ///
+ /// This function will return a `BuilderPush` object which should be passed
+ /// to `pop` when this scope for the attributes provided is exited.
+ ///
+ /// This function will perform a number of tasks:
+ ///
+ /// * It'll validate all lint-related attributes in `attrs`
+ /// * It'll mark all lint-related attributes as used
+ /// * Lint levels will be updated based on the attributes provided
+ /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to
+ /// `#[allow]`
+ ///
+ /// Don't forget to call `pop`!
+ pub(crate) fn push(
+ &mut self,
+ attrs: &[ast::Attribute],
+ is_crate_node: bool,
+ source_hir_id: Option<HirId>,
+ ) -> BuilderPush {
+ let prev = self.provider.cur;
+ self.provider.cur =
+ self.provider.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev });
+
+ self.add(attrs, is_crate_node, source_hir_id);
+
+ if self.provider.current_specs().is_empty() {
+ self.provider.sets.list.pop();
+ self.provider.cur = prev;
+ }
+
+ BuilderPush { prev }
+ }
+
+ /// Called after `push` when the scope of a set of attributes are exited.
+ pub(crate) fn pop(&mut self, push: BuilderPush) {
+ self.provider.cur = push.prev;
+ std::mem::forget(push);
+ }
+}
+
+#[cfg(debug_assertions)]
+impl Drop for BuilderPush {
+ fn drop(&mut self) {
+ panic!("Found a `push` without a `pop`.");
+ }
+}
+
+impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
pub(crate) fn sess(&self) -> &Session {
self.sess
}
@@ -98,24 +515,20 @@ impl<'s> LintLevelsBuilder<'s> {
}
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
- &self.sets.list[self.cur].specs
+ self.provider.current_specs()
}
- fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> {
- &mut self.sets.list[self.cur].specs
+ fn insert(&mut self, id: LintId, lvl: LevelAndSource) {
+ self.provider.insert(id, lvl)
}
- fn process_command_line(&mut self, sess: &Session, store: &LintStore) {
- self.sets.lint_cap = sess.opts.lint_cap.unwrap_or(Level::Forbid);
-
- self.cur =
- self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: COMMAND_LINE });
- for &(ref lint_name, level) in &sess.opts.lint_opts {
- store.check_lint_name_cmdline(sess, &lint_name, level, self.registered_tools);
+ fn add_command_line(&mut self) {
+ for &(ref lint_name, level) in &self.sess.opts.lint_opts {
+ self.store.check_lint_name_cmdline(self.sess, &lint_name, level, self.registered_tools);
let orig_level = level;
let lint_flag_val = Symbol::intern(lint_name);
- let Ok(ids) = store.find_lints(&lint_name) else {
+ let Ok(ids) = self.store.find_lints(&lint_name) else {
// errors handled in check_lint_name_cmdline above
continue
};
@@ -129,7 +542,7 @@ impl<'s> LintLevelsBuilder<'s> {
if self.check_gated_lint(id, DUMMY_SP) {
let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
- self.current_specs_mut().insert(id, (level, src));
+ self.insert(id, (level, src));
}
}
}
@@ -138,9 +551,11 @@ impl<'s> LintLevelsBuilder<'s> {
/// Attempts to insert the `id` to `level_src` map entry. If unsuccessful
/// (e.g. if a forbid was already inserted on the same scope), then emits a
/// diagnostic with no change to `specs`.
- fn insert_spec(&mut self, id: LintId, (level, src): LevelAndSource) {
- let (old_level, old_src) =
- self.sets.get_lint_level(id.lint, self.cur, Some(self.current_specs()), &self.sess);
+ fn insert_spec(&mut self, id: LintId, (mut level, src): LevelAndSource) {
+ let (old_level, old_src) = self.provider.get_lint_level(id.lint, &self.sess);
+ if let Level::Expect(id) = &mut level && let LintExpectationId::Stable { .. } = id {
+ *id = id.normalize();
+ }
// Setting to a non-forbid level is an error if the lint previously had
// a forbid level. Note that this is not necessarily true even with a
// `#[forbid(..)]` attribute present, as that is overridden by `--cap-lints`.
@@ -158,7 +573,7 @@ impl<'s> LintLevelsBuilder<'s> {
let id_name = id.lint.name_lower();
let fcw_warning = match old_src {
LintLevelSource::Default => false,
- LintLevelSource::Node(symbol, _, _) => self.store.is_lint_group(symbol),
+ LintLevelSource::Node { name, .. } => self.store.is_lint_group(name),
LintLevelSource::CommandLine(symbol, _) => self.store.is_lint_group(symbol),
};
debug!(
@@ -178,8 +593,8 @@ impl<'s> LintLevelsBuilder<'s> {
id.to_string()
));
}
- LintLevelSource::Node(_, forbid_source_span, reason) => {
- diag.span_label(forbid_source_span, "`forbid` level set here");
+ LintLevelSource::Node { span, reason, .. } => {
+ diag.span_label(span, "`forbid` level set here");
if let Some(rationale) = reason {
diag.note(rationale.as_str());
}
@@ -199,11 +614,8 @@ impl<'s> LintLevelsBuilder<'s> {
LintLevelSource::Default => {
OverruledAttributeSub::DefaultSource { id: id.to_string() }
}
- LintLevelSource::Node(_, forbid_source_span, reason) => {
- OverruledAttributeSub::NodeSource {
- span: forbid_source_span,
- reason,
- }
+ LintLevelSource::Node { span, reason, .. } => {
+ OverruledAttributeSub::NodeSource { span, reason }
}
LintLevelSource::CommandLine(_, _) => {
OverruledAttributeSub::CommandLineSource
@@ -214,14 +626,14 @@ impl<'s> LintLevelsBuilder<'s> {
self.struct_lint(
FORBIDDEN_LINT_GROUPS,
Some(src.span().into()),
- |diag_builder| {
- let mut diag_builder = diag_builder.build(&format!(
- "{}({}) incompatible with previous forbid",
- level.as_str(),
- src.name(),
- ));
- decorate_diag(&mut diag_builder);
- diag_builder.emit();
+ format!(
+ "{}({}) incompatible with previous forbid",
+ level.as_str(),
+ src.name(),
+ ),
+ |lint| {
+ decorate_diag(lint);
+ lint
},
);
}
@@ -244,45 +656,21 @@ impl<'s> LintLevelsBuilder<'s> {
match (old_level, level) {
// If the new level is an expectation store it in `ForceWarn`
- (Level::ForceWarn(_), Level::Expect(expectation_id)) => self
- .current_specs_mut()
- .insert(id, (Level::ForceWarn(Some(expectation_id)), old_src)),
- // Keep `ForceWarn` level but drop the expectation
- (Level::ForceWarn(_), _) => {
- self.current_specs_mut().insert(id, (Level::ForceWarn(None), old_src))
+ (Level::ForceWarn(_), Level::Expect(expectation_id)) => {
+ self.insert(id, (Level::ForceWarn(Some(expectation_id)), old_src))
}
+ // Keep `ForceWarn` level but drop the expectation
+ (Level::ForceWarn(_), _) => self.insert(id, (Level::ForceWarn(None), old_src)),
// Set the lint level as normal
- _ => self.current_specs_mut().insert(id, (level, src)),
+ _ => self.insert(id, (level, src)),
};
}
- /// Pushes a list of AST lint attributes onto this context.
- ///
- /// This function will return a `BuilderPush` object which should be passed
- /// to `pop` when this scope for the attributes provided is exited.
- ///
- /// This function will perform a number of tasks:
- ///
- /// * It'll validate all lint-related attributes in `attrs`
- /// * It'll mark all lint-related attributes as used
- /// * Lint levels will be updated based on the attributes provided
- /// * Lint attributes are validated, e.g., a `#[forbid]` can't be switched to
- /// `#[allow]`
- ///
- /// Don't forget to call `pop`!
- pub(crate) fn push(
- &mut self,
- attrs: &[ast::Attribute],
- is_crate_node: bool,
- source_hir_id: Option<HirId>,
- ) -> BuilderPush {
- let prev = self.cur;
- self.cur = self.sets.list.push(LintSet { specs: FxHashMap::default(), parent: prev });
-
+ fn add(&mut self, attrs: &[ast::Attribute], is_crate_node: bool, source_hir_id: Option<HirId>) {
let sess = self.sess;
for (attr_index, attr) in attrs.iter().enumerate() {
if attr.has_name(sym::automatically_derived) {
- self.current_specs_mut().insert(
+ self.insert(
LintId::of(SINGLE_USE_LIFETIMES),
(Level::Allow, LintLevelSource::Default),
);
@@ -293,7 +681,17 @@ impl<'s> LintLevelsBuilder<'s> {
None => continue,
// This is the only lint level with a `LintExpectationId` that can be created from an attribute
Some(Level::Expect(unstable_id)) if let Some(hir_id) = source_hir_id => {
- let stable_id = self.create_stable_id(unstable_id, hir_id, attr_index);
+ let LintExpectationId::Unstable { attr_id, lint_index } = unstable_id
+ else { bug!("stable id Level::from_attr") };
+
+ let stable_id = LintExpectationId::Stable {
+ hir_id,
+ attr_index: attr_index.try_into().unwrap(),
+ lint_index,
+ // we pass the previous unstable attr_id such that we can trace the ast id when building a map
+ // to go from unstable to stable id.
+ attr_id: Some(attr_id),
+ };
Level::Expect(stable_id)
}
@@ -408,7 +806,7 @@ impl<'s> LintLevelsBuilder<'s> {
[lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS),
_ => false,
};
- self.lint_expectations.push((
+ self.provider.push_expectation(
expect_id,
LintExpectation::new(
reason,
@@ -416,13 +814,19 @@ impl<'s> LintLevelsBuilder<'s> {
is_unfulfilled_lint_expectations,
tool_name,
),
- ));
+ );
}
- let src = LintLevelSource::Node(
- meta_item.path.segments.last().expect("empty lint name").ident.name,
- sp,
+ let src = LintLevelSource::Node {
+ name: meta_item
+ .path
+ .segments
+ .last()
+ .expect("empty lint name")
+ .ident
+ .name,
+ span: sp,
reason,
- );
+ };
for &id in *ids {
if self.check_gated_lint(id, attr.span) {
self.insert_spec(id, (level, src));
@@ -435,67 +839,60 @@ impl<'s> LintLevelsBuilder<'s> {
Ok(ids) => {
let complete_name =
&format!("{}::{}", tool_ident.unwrap().name, name);
- let src = LintLevelSource::Node(
- Symbol::intern(complete_name),
- sp,
+ let src = LintLevelSource::Node {
+ name: Symbol::intern(complete_name),
+ span: sp,
reason,
- );
+ };
for &id in ids {
if self.check_gated_lint(id, attr.span) {
self.insert_spec(id, (level, src));
}
}
if let Level::Expect(expect_id) = level {
- self.lint_expectations.push((
+ self.provider.push_expectation(
expect_id,
LintExpectation::new(reason, sp, false, tool_name),
- ));
+ );
}
}
Err((Some(ids), ref new_lint_name)) => {
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
- let (lvl, src) = self.sets.get_lint_level(
- lint,
- self.cur,
- Some(self.current_specs()),
- &sess,
- );
+ let (lvl, src) = self.provider.get_lint_level(lint, &sess);
struct_lint_level(
self.sess,
lint,
lvl,
src,
Some(sp.into()),
+ format!(
+ "lint name `{}` is deprecated \
+ and may not have an effect in the future.",
+ name
+ ),
|lint| {
- let msg = format!(
- "lint name `{}` is deprecated \
- and may not have an effect in the future.",
- name
- );
- lint.build(&msg)
- .span_suggestion(
- sp,
- "change it to",
- new_lint_name,
- Applicability::MachineApplicable,
- )
- .emit();
+ lint.span_suggestion(
+ sp,
+ "change it to",
+ new_lint_name,
+ Applicability::MachineApplicable,
+ )
},
);
- let src = LintLevelSource::Node(
- Symbol::intern(&new_lint_name),
- sp,
+ let src = LintLevelSource::Node {
+ name: Symbol::intern(&new_lint_name),
+ span: sp,
reason,
- );
+ };
for id in ids {
self.insert_spec(*id, (level, src));
}
if let Level::Expect(expect_id) = level {
- self.lint_expectations.push((
+ self.provider.push_expectation(
expect_id,
LintExpectation::new(reason, sp, false, tool_name),
- ));
+ );
}
}
Err((None, _)) => {
@@ -521,57 +918,54 @@ impl<'s> LintLevelsBuilder<'s> {
CheckLintNameResult::Warning(msg, renamed) => {
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
- let (renamed_lint_level, src) = self.sets.get_lint_level(
- lint,
- self.cur,
- Some(self.current_specs()),
- &sess,
- );
+ let (renamed_lint_level, src) = self.provider.get_lint_level(lint, &sess);
struct_lint_level(
self.sess,
lint,
renamed_lint_level,
src,
Some(sp.into()),
+ msg,
|lint| {
- let mut err = lint.build(msg);
if let Some(new_name) = &renamed {
- err.span_suggestion(
+ lint.span_suggestion(
sp,
"use the new name",
new_name,
Applicability::MachineApplicable,
);
}
- err.emit();
+ lint
},
);
}
CheckLintNameResult::NoLint(suggestion) => {
let lint = builtin::UNKNOWN_LINTS;
- let (level, src) = self.sets.get_lint_level(
- lint,
- self.cur,
- Some(self.current_specs()),
+ let (level, src) = self.provider.get_lint_level(lint, self.sess);
+ let name = if let Some(tool_ident) = tool_ident {
+ format!("{}::{}", tool_ident.name, name)
+ } else {
+ name.to_string()
+ };
+ struct_lint_level(
self.sess,
+ lint,
+ level,
+ src,
+ Some(sp.into()),
+ format!("unknown lint: `{}`", name),
+ |lint| {
+ if let Some(suggestion) = suggestion {
+ lint.span_suggestion(
+ sp,
+ "did you mean",
+ suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ lint
+ },
);
- struct_lint_level(self.sess, lint, level, src, Some(sp.into()), |lint| {
- let name = if let Some(tool_ident) = tool_ident {
- format!("{}::{}", tool_ident.name, name)
- } else {
- name.to_string()
- };
- let mut db = lint.build(format!("unknown lint: `{}`", name));
- if let Some(suggestion) = suggestion {
- db.span_suggestion(
- sp,
- "did you mean",
- suggestion,
- Applicability::MachineApplicable,
- );
- }
- db.emit();
- });
}
}
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
@@ -583,17 +977,21 @@ impl<'s> LintLevelsBuilder<'s> {
if let CheckLintNameResult::Ok(ids) =
self.store.check_lint_name(&new_name, None, self.registered_tools)
{
- let src = LintLevelSource::Node(Symbol::intern(&new_name), sp, reason);
+ let src = LintLevelSource::Node {
+ name: Symbol::intern(&new_name),
+ span: sp,
+ reason,
+ };
for &id in ids {
if self.check_gated_lint(id, attr.span) {
self.insert_spec(id, (level, src));
}
}
if let Level::Expect(expect_id) = level {
- self.lint_expectations.push((
+ self.provider.push_expectation(
expect_id,
LintExpectation::new(reason, sp, false, tool_name),
- ));
+ );
}
} else {
panic!("renamed lint does not exist: {}", new_name);
@@ -608,232 +1006,87 @@ impl<'s> LintLevelsBuilder<'s> {
continue;
}
- let LintLevelSource::Node(lint_attr_name, lint_attr_span, _) = *src else {
+ let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src else {
continue
};
let lint = builtin::UNUSED_ATTRIBUTES;
- let (lint_level, lint_src) =
- self.sets.get_lint_level(lint, self.cur, Some(self.current_specs()), self.sess);
+ let (lint_level, lint_src) = self.provider.get_lint_level(lint, &self.sess);
struct_lint_level(
self.sess,
lint,
lint_level,
lint_src,
Some(lint_attr_span.into()),
- |lint| {
- let mut db = lint.build(&format!(
- "{}({}) is ignored unless specified at crate level",
- level.as_str(),
- lint_attr_name
- ));
- db.emit();
- },
+ format!(
+ "{}({}) is ignored unless specified at crate level",
+ level.as_str(),
+ lint_attr_name
+ ),
+ |lint| lint,
);
// don't set a separate error for every lint in the group
break;
}
}
-
- if self.current_specs().is_empty() {
- self.sets.list.pop();
- self.cur = prev;
- }
-
- BuilderPush { prev, changed: prev != self.cur }
- }
-
- fn create_stable_id(
- &mut self,
- unstable_id: LintExpectationId,
- hir_id: HirId,
- attr_index: usize,
- ) -> LintExpectationId {
- let stable_id =
- LintExpectationId::Stable { hir_id, attr_index: attr_index as u16, lint_index: None };
-
- self.expectation_id_map.insert(unstable_id, stable_id);
-
- stable_id
}
/// Checks if the lint is gated on a feature that is not enabled.
///
/// Returns `true` if the lint's feature is enabled.
+ // FIXME only emit this once for each attribute, instead of repeating it 4 times for
+ // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
if let Some(feature) = lint_id.lint.feature_gate {
if !self.sess.features_untracked().enabled(feature) {
let lint = builtin::UNKNOWN_LINTS;
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
- struct_lint_level(self.sess, lint, level, src, Some(span.into()), |lint_db| {
- let mut db =
- lint_db.build(&format!("unknown lint: `{}`", lint_id.lint.name_lower()));
- db.note(&format!("the `{}` lint is unstable", lint_id.lint.name_lower(),));
- add_feature_diagnostics(&mut db, &self.sess.parse_sess, feature);
- db.emit();
- });
+ struct_lint_level(
+ self.sess,
+ lint,
+ level,
+ src,
+ Some(span.into()),
+ format!("unknown lint: `{}`", lint_id.lint.name_lower()),
+ |lint| {
+ lint.note(
+ &format!("the `{}` lint is unstable", lint_id.lint.name_lower(),),
+ );
+ add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
+ lint
+ },
+ );
return false;
}
}
true
}
- /// Called after `push` when the scope of a set of attributes are exited.
- pub fn pop(&mut self, push: BuilderPush) {
- self.cur = push.prev;
- }
-
/// Find the lint level for a lint.
- pub fn lint_level(&self, lint: &'static Lint) -> (Level, LintLevelSource) {
- self.sets.get_lint_level(lint, self.cur, None, self.sess)
+ pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource {
+ self.provider.get_lint_level(lint, self.sess)
}
/// Used to emit a lint-related diagnostic based on the current state of
/// this lint context.
- pub fn struct_lint(
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ pub(crate) fn struct_lint(
&self,
lint: &'static Lint,
span: Option<MultiSpan>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
let (level, src) = self.lint_level(lint);
- struct_lint_level(self.sess, lint, level, src, span, decorate)
- }
-
- /// Registers the ID provided with the current set of lints stored in
- /// this context.
- pub fn register_id(&mut self, id: HirId) {
- self.id_to_set.insert(id, self.cur);
- }
-
- fn update_unstable_expectation_ids(&self) {
- self.sess.diagnostic().update_unstable_expectation_id(&self.expectation_id_map);
- }
-
- pub fn build_map(self) -> LintLevelMap {
- LintLevelMap {
- sets: self.sets,
- id_to_set: self.id_to_set,
- lint_expectations: self.lint_expectations,
- }
- }
-}
-
-struct LintLevelMapBuilder<'tcx> {
- levels: LintLevelsBuilder<'tcx>,
- tcx: TyCtxt<'tcx>,
-}
-
-impl LintLevelMapBuilder<'_> {
- fn with_lint_attrs<F>(&mut self, id: hir::HirId, f: F)
- where
- F: FnOnce(&mut Self),
- {
- let is_crate_hir = id == hir::CRATE_HIR_ID;
- let attrs = self.tcx.hir().attrs(id);
- let push = self.levels.push(attrs, is_crate_hir, Some(id));
-
- if push.changed {
- self.levels.register_id(id);
- }
- f(self);
- self.levels.pop(push);
- }
-}
-
-impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.tcx.hir()
- }
-
- fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
- self.with_lint_attrs(param.hir_id, |builder| {
- intravisit::walk_param(builder, param);
- });
- }
-
- fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) {
- self.with_lint_attrs(it.hir_id(), |builder| {
- intravisit::walk_item(builder, it);
- });
- }
-
- fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) {
- self.with_lint_attrs(it.hir_id(), |builder| {
- intravisit::walk_foreign_item(builder, it);
- })
- }
-
- fn visit_stmt(&mut self, e: &'tcx hir::Stmt<'tcx>) {
- // We will call `with_lint_attrs` when we walk
- // the `StmtKind`. The outer statement itself doesn't
- // define the lint levels.
- intravisit::walk_stmt(self, e);
- }
-
- fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
- self.with_lint_attrs(e.hir_id, |builder| {
- intravisit::walk_expr(builder, e);
- })
- }
-
- fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
- self.with_lint_attrs(field.hir_id, |builder| {
- intravisit::walk_expr_field(builder, field);
- })
- }
-
- fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) {
- self.with_lint_attrs(s.hir_id, |builder| {
- intravisit::walk_field_def(builder, s);
- })
- }
-
- fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) {
- self.with_lint_attrs(v.id, |builder| {
- intravisit::walk_variant(builder, v);
- })
- }
-
- fn visit_local(&mut self, l: &'tcx hir::Local<'tcx>) {
- self.with_lint_attrs(l.hir_id, |builder| {
- intravisit::walk_local(builder, l);
- })
- }
-
- fn visit_arm(&mut self, a: &'tcx hir::Arm<'tcx>) {
- self.with_lint_attrs(a.hir_id, |builder| {
- intravisit::walk_arm(builder, a);
- })
- }
-
- fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
- self.with_lint_attrs(trait_item.hir_id(), |builder| {
- intravisit::walk_trait_item(builder, trait_item);
- });
- }
-
- fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
- self.with_lint_attrs(impl_item.hir_id(), |builder| {
- intravisit::walk_impl_item(builder, impl_item);
- });
- }
-
- fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) {
- self.with_lint_attrs(field.hir_id, |builder| {
- intravisit::walk_pat_field(builder, field);
- })
- }
-
- fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
- self.with_lint_attrs(p.hir_id, |builder| {
- intravisit::walk_generic_param(builder, p);
- });
+ struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
}
}
-pub fn provide(providers: &mut Providers) {
- providers.lint_levels = lint_levels;
+pub(crate) fn provide(providers: &mut Providers) {
+ *providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers };
}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 752a751f6..5288fc542 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -34,7 +34,7 @@
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
+#![feature(min_specialization)]
#![feature(never_type)]
#![recursion_limit = "256"]
@@ -52,6 +52,7 @@ mod early;
mod enum_intrinsics_non_enums;
mod errors;
mod expect;
+mod for_loops_over_fallibles;
pub mod hidden_unicode_codepoints;
mod internal;
mod late;
@@ -62,6 +63,7 @@ mod non_ascii_idents;
mod non_fmt_panic;
mod nonstandard_style;
mod noop_method_call;
+mod opaque_hidden_inferred_bound;
mod pass_by_value;
mod passes;
mod redundant_semicolon;
@@ -85,6 +87,7 @@ use rustc_span::Span;
use array_into_iter::ArrayIntoIter;
use builtin::*;
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
+use for_loops_over_fallibles::*;
use hidden_unicode_codepoints::*;
use internal::*;
use let_underscore::*;
@@ -93,6 +96,7 @@ use non_ascii_idents::*;
use non_fmt_panic::NonPanicFmt;
use nonstandard_style::*;
use noop_method_call::*;
+use opaque_hidden_inferred_bound::*;
use pass_by_value::*;
use redundant_semicolon::*;
use traits::*;
@@ -186,6 +190,7 @@ macro_rules! late_lint_mod_passes {
$macro!(
$args,
[
+ ForLoopsOverFallibles: ForLoopsOverFallibles,
HardwiredLints: HardwiredLints,
ImproperCTypesDeclarations: ImproperCTypesDeclarations,
ImproperCTypesDefinitions: ImproperCTypesDefinitions,
@@ -207,7 +212,7 @@ macro_rules! late_lint_mod_passes {
TypeLimits: TypeLimits::new(),
NonSnakeCase: NonSnakeCase,
InvalidNoMangleItems: InvalidNoMangleItems,
- // Depends on access levels
+ // Depends on effective visibilities
UnreachablePub: UnreachablePub,
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
InvalidValue: InvalidValue,
@@ -223,6 +228,7 @@ macro_rules! late_lint_mod_passes {
EnumIntrinsicsNonEnums: EnumIntrinsicsNonEnums,
InvalidAtomicOrdering: InvalidAtomicOrdering,
NamedAsmLabels: NamedAsmLabels,
+ OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
]
);
};
@@ -519,6 +525,11 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) {
"now allowed, see issue #59159 \
<https://github.com/rust-lang/rust/issues/59159> for more information",
);
+ store.register_removed(
+ "const_err",
+ "converted into hard error, see issue #71800 \
+ <https://github.com/rust-lang/rust/issues/71800> for more information",
+ );
}
fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 5f7f03480..e2d7d5b49 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -90,14 +90,17 @@ fn lint_cstring_as_ptr(
if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
if let ty::Adt(adt, _) = substs.type_at(0).kind() {
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
- cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| {
- diag.build(fluent::lint::cstring_ptr)
- .span_label(as_ptr_span, fluent::lint::as_ptr_label)
- .span_label(unwrap.span, fluent::lint::unwrap_label)
- .note(fluent::lint::note)
- .help(fluent::lint::help)
- .emit();
- });
+ cx.struct_span_lint(
+ TEMPORARY_CSTRING_AS_PTR,
+ as_ptr_span,
+ fluent::lint_cstring_ptr,
+ |diag| {
+ diag.span_label(as_ptr_span, fluent::as_ptr_label)
+ .span_label(unwrap.span, fluent::unwrap_label)
+ .note(fluent::note)
+ .help(fluent::help)
+ },
+ );
}
}
}
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 764003e61..dea9506ac 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -180,15 +180,21 @@ impl EarlyLintPass for NonAsciiIdents {
continue;
}
has_non_ascii_idents = true;
- cx.struct_span_lint(NON_ASCII_IDENTS, sp, |lint| {
- lint.build(fluent::lint::identifier_non_ascii_char).emit();
- });
+ cx.struct_span_lint(
+ NON_ASCII_IDENTS,
+ sp,
+ fluent::lint_identifier_non_ascii_char,
+ |lint| lint,
+ );
if check_uncommon_codepoints
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
{
- cx.struct_span_lint(UNCOMMON_CODEPOINTS, sp, |lint| {
- lint.build(fluent::lint::identifier_uncommon_codepoints).emit();
- })
+ cx.struct_span_lint(
+ UNCOMMON_CODEPOINTS,
+ sp,
+ fluent::lint_identifier_uncommon_codepoints,
+ |lint| lint,
+ )
}
}
@@ -216,13 +222,16 @@ impl EarlyLintPass for NonAsciiIdents {
.entry(skeleton_sym)
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
if !*existing_is_ascii || !is_ascii {
- cx.struct_span_lint(CONFUSABLE_IDENTS, sp, |lint| {
- lint.build(fluent::lint::confusable_identifier_pair)
- .set_arg("existing_sym", *existing_symbol)
- .set_arg("sym", symbol)
- .span_label(*existing_span, fluent::lint::label)
- .emit();
- });
+ cx.struct_span_lint(
+ CONFUSABLE_IDENTS,
+ sp,
+ fluent::lint_confusable_identifier_pair,
+ |lint| {
+ lint.set_arg("existing_sym", *existing_symbol)
+ .set_arg("sym", symbol)
+ .span_label(*existing_span, fluent::label)
+ },
+ );
}
if *existing_is_ascii && !is_ascii {
*existing_symbol = symbol;
@@ -322,22 +331,25 @@ impl EarlyLintPass for NonAsciiIdents {
}
for ((sp, ch_list), script_set) in lint_reports {
- cx.struct_span_lint(MIXED_SCRIPT_CONFUSABLES, sp, |lint| {
- let mut includes = String::new();
- for (idx, ch) in ch_list.into_iter().enumerate() {
- if idx != 0 {
- includes += ", ";
+ cx.struct_span_lint(
+ MIXED_SCRIPT_CONFUSABLES,
+ sp,
+ fluent::lint_mixed_script_confusables,
+ |lint| {
+ let mut includes = String::new();
+ for (idx, ch) in ch_list.into_iter().enumerate() {
+ if idx != 0 {
+ includes += ", ";
+ }
+ let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
+ includes += &char_info;
}
- let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
- includes += &char_info;
- }
- lint.build(fluent::lint::mixed_script_confusables)
- .set_arg("set", script_set.to_string())
- .set_arg("includes", includes)
- .note(fluent::lint::includes_note)
- .note(fluent::lint::note)
- .emit();
- });
+ lint.set_arg("set", script_set.to_string())
+ .set_arg("includes", includes)
+ .note(fluent::includes_note)
+ .note(fluent::note)
+ },
+ );
}
}
}
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index cdad2d2e8..6ad2e0294 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -119,22 +119,20 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
arg_span = expn.call_site;
}
- cx.struct_span_lint(NON_FMT_PANICS, arg_span, |lint| {
- let mut l = lint.build(fluent::lint::non_fmt_panic);
- l.set_arg("name", symbol);
- l.note(fluent::lint::note);
- l.note(fluent::lint::more_info_note);
+ 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);
if !is_arg_inside_call(arg_span, span) {
// No clue where this argument is coming from.
- l.emit();
- return;
+ return lint;
}
if arg_macro.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::format_macro, id)) {
// A case of `panic!(format!(..))`.
- l.note(fluent::lint::supports_fmt_note);
+ lint.note(fluent::supports_fmt_note);
if let Some((open, close, _)) = find_delimiters(cx, arg_span) {
- l.multipart_suggestion(
- fluent::lint::supports_fmt_suggestion,
+ lint.multipart_suggestion(
+ fluent::supports_fmt_suggestion,
vec![
(arg_span.until(open.shrink_to_hi()), "".into()),
(close.until(arg_span.shrink_to_hi()), "".into()),
@@ -153,21 +151,19 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
Some(ty_def) if cx.tcx.is_diagnostic_item(sym::String, ty_def.did()),
);
- let (suggest_display, suggest_debug) = cx.tcx.infer_ctxt().enter(|infcx| {
- let display = is_str
- || cx.tcx.get_diagnostic_item(sym::Display).map(|t| {
- infcx
- .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
- .may_apply()
- }) == Some(true);
- let debug = !display
- && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| {
- infcx
- .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
- .may_apply()
- }) == Some(true);
- (display, debug)
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ let suggest_display = is_str
+ || cx.tcx.get_diagnostic_item(sym::Display).map(|t| {
+ infcx
+ .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
+ .may_apply()
+ }) == Some(true);
+ let suggest_debug = !suggest_display
+ && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| {
+ infcx
+ .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env)
+ .may_apply()
+ }) == Some(true);
let suggest_panic_any = !is_str && panic == sym::std_panic_macro;
@@ -180,17 +176,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
};
if suggest_display {
- l.span_suggestion_verbose(
+ lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::lint::display_suggestion,
+ fluent::display_suggestion,
"\"{}\", ",
fmt_applicability,
);
} else if suggest_debug {
- l.set_arg("ty", ty);
- l.span_suggestion_verbose(
+ lint.set_arg("ty", ty);
+ lint.span_suggestion_verbose(
arg_span.shrink_to_lo(),
- fluent::lint::debug_suggestion,
+ fluent::debug_suggestion,
"\"{:?}\", ",
fmt_applicability,
);
@@ -198,9 +194,9 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
if suggest_panic_any {
if let Some((open, close, del)) = find_delimiters(cx, span) {
- l.set_arg("already_suggested", suggest_display || suggest_debug);
- l.multipart_suggestion(
- fluent::lint::panic_suggestion,
+ lint.set_arg("already_suggested", suggest_display || suggest_debug);
+ lint.multipart_suggestion(
+ fluent::panic_suggestion,
if del == '(' {
vec![(span.until(open), "std::panic::panic_any".into())]
} else {
@@ -214,7 +210,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
}
}
}
- l.emit();
+ lint
});
}
@@ -258,25 +254,24 @@ fn check_panic_str<'tcx>(
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
.collect(),
};
- cx.struct_span_lint(NON_FMT_PANICS, arg_spans, |lint| {
- let mut l = lint.build(fluent::lint::non_fmt_panic_unused);
- l.set_arg("count", n_arguments);
- l.note(fluent::lint::note);
+ cx.struct_span_lint(NON_FMT_PANICS, arg_spans, fluent::lint_non_fmt_panic_unused, |lint| {
+ lint.set_arg("count", n_arguments);
+ lint.note(fluent::note);
if is_arg_inside_call(arg.span, span) {
- l.span_suggestion(
+ lint.span_suggestion(
arg.span.shrink_to_hi(),
- fluent::lint::add_args_suggestion,
+ fluent::add_args_suggestion,
", ...",
Applicability::HasPlaceholders,
);
- l.span_suggestion(
+ lint.span_suggestion(
arg.span.shrink_to_lo(),
- fluent::lint::add_fmt_suggestion,
+ fluent::add_fmt_suggestion,
"\"{}\", ",
Applicability::MachineApplicable,
);
}
- l.emit();
+ lint
});
} else {
let brace_spans: Option<Vec<_>> =
@@ -287,20 +282,24 @@ fn check_panic_str<'tcx>(
.collect()
});
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
- cx.struct_span_lint(NON_FMT_PANICS, brace_spans.unwrap_or_else(|| vec![span]), |lint| {
- let mut l = lint.build(fluent::lint::non_fmt_panic_braces);
- l.set_arg("count", count);
- l.note(fluent::lint::note);
- if is_arg_inside_call(arg.span, span) {
- l.span_suggestion(
- arg.span.shrink_to_lo(),
- fluent::lint::suggestion,
- "\"{}\", ",
- Applicability::MachineApplicable,
- );
- }
- l.emit();
- });
+ cx.struct_span_lint(
+ NON_FMT_PANICS,
+ brace_spans.unwrap_or_else(|| vec![span]),
+ fluent::lint_non_fmt_panic_braces,
+ |lint| {
+ lint.set_arg("count", count);
+ lint.note(fluent::note);
+ if is_arg_inside_call(arg.span, span) {
+ lint.span_suggestion(
+ arg.span.shrink_to_lo(),
+ fluent::suggestion,
+ "\"{}\", ",
+ Applicability::MachineApplicable,
+ );
+ }
+ lint
+ },
+ );
}
}
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 768ad8483..7e50801f8 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -136,26 +136,30 @@ impl NonCamelCaseTypes {
let name = ident.name.as_str();
if !is_camel_case(name) {
- cx.struct_span_lint(NON_CAMEL_CASE_TYPES, ident.span, |lint| {
- let mut err = lint.build(fluent::lint::non_camel_case_type);
- let cc = to_camel_case(name);
- // We cannot provide meaningful suggestions
- // if the characters are in the category of "Lowercase Letter".
- if *name != cc {
- err.span_suggestion(
- ident.span,
- fluent::lint::suggestion,
- to_camel_case(name),
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_label(ident.span, fluent::lint::label);
- }
+ cx.struct_span_lint(
+ NON_CAMEL_CASE_TYPES,
+ ident.span,
+ fluent::lint_non_camel_case_type,
+ |lint| {
+ let cc = to_camel_case(name);
+ // We cannot provide meaningful suggestions
+ // if the characters are in the category of "Lowercase Letter".
+ if *name != cc {
+ lint.span_suggestion(
+ ident.span,
+ fluent::suggestion,
+ to_camel_case(name),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ lint.span_label(ident.span, fluent::label);
+ }
- err.set_arg("sort", sort);
- err.set_arg("name", name);
- err.emit();
- })
+ lint.set_arg("sort", sort);
+ lint.set_arg("name", name);
+ lint
+ },
+ )
}
}
}
@@ -183,7 +187,7 @@ impl EarlyLintPass for NonCamelCaseTypes {
}
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) {
- if let ast::AssocItemKind::TyAlias(..) = it.kind {
+ if let ast::AssocItemKind::Type(..) = it.kind {
self.check_case(cx, "associated type", &it.ident);
}
}
@@ -280,9 +284,8 @@ impl NonSnakeCase {
let name = ident.name.as_str();
if !is_snake_case(name) {
- cx.struct_span_lint(NON_SNAKE_CASE, ident.span, |lint| {
+ cx.struct_span_lint(NON_SNAKE_CASE, ident.span, fluent::lint_non_snake_case, |lint| {
let sc = NonSnakeCase::to_snake_case(name);
- let mut err = lint.build(fluent::lint::non_snake_case);
// We cannot provide meaningful suggestions
// if the characters are in the category of "Uppercase Letter".
if name != sc {
@@ -295,32 +298,32 @@ impl NonSnakeCase {
// Instead, recommend renaming the identifier entirely or, if permitted,
// escaping it to create a raw identifier.
if sc_ident.name.can_be_raw() {
- (fluent::lint::rename_or_convert_suggestion, sc_ident.to_string())
+ (fluent::rename_or_convert_suggestion, sc_ident.to_string())
} else {
- err.note(fluent::lint::cannot_convert_note);
- (fluent::lint::rename_suggestion, String::new())
+ lint.note(fluent::cannot_convert_note);
+ (fluent::rename_suggestion, String::new())
}
} else {
- (fluent::lint::convert_suggestion, sc.clone())
+ (fluent::convert_suggestion, sc.clone())
};
- err.span_suggestion(
+ lint.span_suggestion(
ident.span,
message,
suggestion,
Applicability::MaybeIncorrect,
);
} else {
- err.help(fluent::lint::help);
+ lint.help(fluent::help);
}
} else {
- err.span_label(ident.span, fluent::lint::label);
+ lint.span_label(ident.span, fluent::label);
}
- err.set_arg("sort", sort);
- err.set_arg("name", name);
- err.set_arg("sc", sc);
- err.emit();
+ lint.set_arg("sort", sort);
+ lint.set_arg("name", name);
+ lint.set_arg("sc", sc);
+ lint
});
}
}
@@ -478,26 +481,30 @@ impl NonUpperCaseGlobals {
fn check_upper_case(cx: &LateContext<'_>, sort: &str, ident: &Ident) {
let name = ident.name.as_str();
if name.chars().any(|c| c.is_lowercase()) {
- cx.struct_span_lint(NON_UPPER_CASE_GLOBALS, ident.span, |lint| {
- let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
- let mut err = lint.build(fluent::lint::non_upper_case_global);
- // We cannot provide meaningful suggestions
- // if the characters are in the category of "Lowercase Letter".
- if *name != uc {
- err.span_suggestion(
- ident.span,
- fluent::lint::suggestion,
- uc,
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_label(ident.span, fluent::lint::label);
- }
+ cx.struct_span_lint(
+ NON_UPPER_CASE_GLOBALS,
+ ident.span,
+ fluent::lint_non_upper_case_global,
+ |lint| {
+ let uc = NonSnakeCase::to_snake_case(&name).to_uppercase();
+ // We cannot provide meaningful suggestions
+ // if the characters are in the category of "Lowercase Letter".
+ if *name != uc {
+ lint.span_suggestion(
+ ident.span,
+ fluent::suggestion,
+ uc,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ lint.span_label(ident.span, fluent::label);
+ }
- err.set_arg("sort", sort);
- err.set_arg("name", name);
- err.emit();
- })
+ lint.set_arg("sort", sort);
+ lint.set_arg("name", name);
+ lint
+ },
+ )
}
}
}
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index d1449496d..2ef425a10 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -1,5 +1,4 @@
use crate::context::LintContext;
-use crate::rustc_middle::ty::TypeVisitable;
use crate::LateContext;
use crate::LateLintPass;
use rustc_errors::fluent;
@@ -46,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
};
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
// traits and ignore any other method call.
- let (trait_id, did) = match cx.typeck_results().type_dependent_def(expr.hir_id) {
+ let did = match cx.typeck_results().type_dependent_def(expr.hir_id) {
// Verify we are dealing with a method/associated function.
Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) {
// Check that we're dealing with a trait method for one of the traits we care about.
@@ -56,21 +55,17 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
Some(sym::Borrow | sym::Clone | sym::Deref)
) =>
{
- (trait_id, did)
+ did
}
_ => return,
},
_ => return,
};
- let substs = cx.typeck_results().node_substs(expr.hir_id);
- if substs.needs_subst() {
- // We can't resolve on types that require monomorphization, so we don't handle them if
- // we need to perform substitution.
- return;
- }
- let param_env = cx.tcx.param_env(trait_id);
+ let substs = cx
+ .tcx
+ .normalize_erasing_regions(cx.param_env, cx.typeck_results().node_substs(expr.hir_id));
// Resolve the trait method instance.
- let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, param_env, did, substs) else {
+ let Ok(Some(i)) = ty::Instance::resolve(cx.tcx, cx.param_env, did, substs) else {
return
};
// (Re)check that it implements the noop diagnostic.
@@ -90,13 +85,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
}
let expr_span = expr.span;
let span = expr_span.with_lo(receiver.span.hi());
- cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
- lint.build(fluent::lint::noop_method_call)
- .set_arg("method", call.ident.name)
+ cx.struct_span_lint(NOOP_METHOD_CALL, span, fluent::lint_noop_method_call, |lint| {
+ lint.set_arg("method", call.ident.name)
.set_arg("receiver_ty", receiver_ty)
- .span_label(span, fluent::lint::label)
- .note(fluent::lint::note)
- .emit();
+ .span_label(span, fluent::label)
+ .note(fluent::note)
});
}
}
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
new file mode 100644
index 000000000..00bf287ba
--- /dev/null
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -0,0 +1,163 @@
+use rustc_hir as hir;
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_macros::{LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{
+ self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
+};
+use rustc_span::Span;
+use rustc_trait_selection::traits;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
+
+use crate::{LateContext, LateLintPass, LintContext};
+
+declare_lint! {
+ /// The `opaque_hidden_inferred_bound` lint detects cases in which nested
+ /// `impl Trait` in associated type bounds are not written generally enough
+ /// to satisfy the bounds of the associated type.
+ ///
+ /// ### Explanation
+ ///
+ /// This functionality was removed in #97346, but then rolled back in #99860
+ /// because it caused regressions.
+ ///
+ /// We plan on reintroducing this as a hard error, but in the mean time,
+ /// this lint serves to warn and suggest fixes for any use-cases which rely
+ /// on this behavior.
+ ///
+ /// ### Example
+ ///
+ /// ```
+ /// trait Trait {
+ /// type Assoc: Send;
+ /// }
+ ///
+ /// struct Struct;
+ ///
+ /// impl Trait for Struct {
+ /// type Assoc = i32;
+ /// }
+ ///
+ /// fn test() -> impl Trait<Assoc = impl Sized> {
+ /// Struct
+ /// }
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// In this example, `test` declares that the associated type `Assoc` for
+ /// `impl Trait` is `impl Sized`, which does not satisfy the `Send` bound
+ /// on the associated type.
+ ///
+ /// Although the hidden type, `i32` does satisfy this bound, we do not
+ /// consider the return type to be well-formed with this lint. It can be
+ /// fixed by changing `impl Sized` into `impl Sized + Send`.
+ pub OPAQUE_HIDDEN_INFERRED_BOUND,
+ Warn,
+ "detects the use of nested `impl Trait` types in associated type bounds that are not general enough"
+}
+
+declare_lint_pass!(OpaqueHiddenInferredBound => [OPAQUE_HIDDEN_INFERRED_BOUND]);
+
+impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
+ let hir::ItemKind::OpaqueTy(_) = &item.kind else { return; };
+ let def_id = item.owner_id.def_id.to_def_id();
+ let infcx = &cx.tcx.infer_ctxt().build();
+ // For every projection predicate in the opaque type's explicit bounds,
+ // check that the type that we're assigning actually satisfies the bounds
+ // of the associated type.
+ for &(pred, pred_span) in cx.tcx.explicit_item_bounds(def_id) {
+ // Liberate bound regions in the predicate since we
+ // don't actually care about lifetimes in this check.
+ let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind());
+ let ty::PredicateKind::Projection(proj) = predicate else {
+ continue;
+ };
+ // Only check types, since those are the only things that may
+ // have opaques in them anyways.
+ let Some(proj_term) = proj.term.ty() else { continue };
+
+ let proj_ty =
+ cx.tcx.mk_projection(proj.projection_ty.item_def_id, proj.projection_ty.substs);
+ // For every instance of the projection type in the bounds,
+ // replace them with the term we're assigning to the associated
+ // type in our opaque type.
+ let proj_replacer = &mut BottomUpFolder {
+ tcx: cx.tcx,
+ ty_op: |ty| if ty == proj_ty { proj_term } else { ty },
+ lt_op: |lt| lt,
+ ct_op: |ct| ct,
+ };
+ // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
+ // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
+ // with `impl Send: OtherTrait`.
+ for (assoc_pred, assoc_pred_span) in cx
+ .tcx
+ .bound_explicit_item_bounds(proj.projection_ty.item_def_id)
+ .subst_iter_copied(cx.tcx, &proj.projection_ty.substs)
+ {
+ let assoc_pred = assoc_pred.fold_with(proj_replacer);
+ let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else {
+ continue;
+ };
+ // If that predicate doesn't hold modulo regions (but passed during type-check),
+ // then we must've taken advantage of the hack in `project_and_unify_types` where
+ // we replace opaques with inference vars. Emit a warning!
+ if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new(
+ traits::ObligationCause::dummy(),
+ cx.param_env,
+ assoc_pred,
+ )) {
+ // If it's a trait bound and an opaque that doesn't satisfy it,
+ // then we can emit a suggestion to add the bound.
+ let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) {
+ (ty::Opaque(def_id, _), ty::PredicateKind::Trait(trait_pred)) => {
+ Some(AddBound {
+ suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(),
+ trait_ref: trait_pred.print_modifiers_and_trait_path(),
+ })
+ }
+ _ => None,
+ };
+ cx.emit_spanned_lint(
+ OPAQUE_HIDDEN_INFERRED_BOUND,
+ pred_span,
+ OpaqueHiddenInferredBoundLint {
+ ty: cx.tcx.mk_opaque(
+ def_id,
+ ty::InternalSubsts::identity_for_item(cx.tcx, def_id),
+ ),
+ proj_ty: proj_term,
+ assoc_pred_span,
+ add_bound,
+ },
+ );
+ }
+ }
+ }
+ }
+}
+
+#[derive(LintDiagnostic)]
+#[diag(lint_opaque_hidden_inferred_bound)]
+struct OpaqueHiddenInferredBoundLint<'tcx> {
+ ty: Ty<'tcx>,
+ proj_ty: Ty<'tcx>,
+ #[label(specifically)]
+ assoc_pred_span: Span,
+ #[subdiagnostic]
+ add_bound: Option<AddBound<'tcx>>,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion_verbose(
+ lint_opaque_hidden_inferred_bound_sugg,
+ applicability = "machine-applicable",
+ code = " + {trait_ref}"
+)]
+struct AddBound<'tcx> {
+ #[primary_span]
+ suggest_span: Span,
+ #[skip_arg]
+ trait_ref: TraitPredPrintModifiersAndPath<'tcx>,
+}
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index af5e5faf1..01bface71 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -29,18 +29,20 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
}
}
if let Some(t) = path_for_pass_by_value(cx, &inner_ty) {
- cx.struct_span_lint(PASS_BY_VALUE, ty.span, |lint| {
- lint.build(fluent::lint::pass_by_value)
- .set_arg("ty", t.clone())
- .span_suggestion(
+ cx.struct_span_lint(
+ PASS_BY_VALUE,
+ ty.span,
+ fluent::lint_pass_by_value,
+ |lint| {
+ lint.set_arg("ty", t.clone()).span_suggestion(
ty.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
t,
// Changing type of function argument
Applicability::MaybeIncorrect,
)
- .emit();
- })
+ },
+ )
}
}
_ => {}
@@ -56,7 +58,7 @@ fn path_for_pass_by_value(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> Option<Stri
let path_segment = path.segments.last().unwrap();
return Some(format!("{}{}", name, gen_args(cx, path_segment)));
}
- Res::SelfTy { trait_: None, alias_to: Some((did, _)) } => {
+ Res::SelfTyAlias { alias_to: did, is_trait_impl: false, .. } => {
if let ty::Adt(adt, substs) = cx.tcx.type_of(did).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/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs
index 26f413453..3521de7fc 100644
--- a/compiler/rustc_lint/src/redundant_semicolon.rs
+++ b/compiler/rustc_lint/src/redundant_semicolon.rs
@@ -48,11 +48,18 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
return;
}
- cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| {
- lint.build(fluent::lint::redundant_semicolons)
- .set_arg("multiple", multiple)
- .span_suggestion(span, fluent::lint::suggestion, "", Applicability::MaybeIncorrect)
- .emit();
- });
+ cx.struct_span_lint(
+ REDUNDANT_SEMICOLONS,
+ span,
+ fluent::lint_redundant_semicolons,
+ |lint| {
+ lint.set_arg("multiple", multiple).span_suggestion(
+ span,
+ fluent::suggestion,
+ "",
+ Applicability::MaybeIncorrect,
+ )
+ },
+ );
}
}
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index df1587c59..f22f38aa2 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::PredicateKind::*;
- let predicates = cx.tcx.explicit_predicates_of(item.def_id);
+ let predicates = cx.tcx.explicit_predicates_of(item.owner_id);
for &(predicate, span) in predicates.predicates {
let Trait(trait_predicate) = predicate.kind().skip_binder() else {
continue
@@ -100,15 +100,18 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
if trait_predicate.trait_ref.self_ty().is_impl_trait() {
continue;
}
- cx.struct_span_lint(DROP_BOUNDS, span, |lint| {
- let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
- return
- };
- lint.build(fluent::lint::drop_trait_constraints)
- .set_arg("predicate", predicate)
- .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
- .emit();
- });
+ let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
+ continue;
+ };
+ cx.struct_span_lint(
+ DROP_BOUNDS,
+ span,
+ fluent::lint_drop_trait_constraints,
+ |lint| {
+ lint.set_arg("predicate", predicate)
+ .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
+ },
+ );
}
}
}
@@ -119,14 +122,11 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
};
for bound in &bounds[..] {
let def_id = bound.trait_ref.trait_def_id();
- if cx.tcx.lang_items().drop_trait() == def_id {
- cx.struct_span_lint(DYN_DROP, bound.span, |lint| {
- let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop) else {
- return
- };
- lint.build(fluent::lint::drop_glue)
- .set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
- .emit();
+ if cx.tcx.lang_items().drop_trait() == def_id
+ && let Some(needs_drop) = cx.tcx.get_diagnostic_item(sym::needs_drop)
+ {
+ cx.struct_span_lint(DYN_DROP, bound.span, fluent::lint_drop_glue, |lint| {
+ lint.set_arg("needs_drop", cx.tcx.def_path_str(needs_drop))
});
}
}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 4fb6d65a6..37caab2da 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -11,7 +11,7 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_span::source_map;
use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol};
use rustc_target::abi::{Abi, WrappingRange};
use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi;
@@ -116,8 +116,8 @@ impl TypeLimits {
}
}
-/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint.
-/// Returns `true` iff the lint was overridden.
+/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
+/// Returns `true` iff the lint was emitted.
fn lint_overflowing_range_endpoint<'tcx>(
cx: &LateContext<'tcx>,
lit: &hir::Lit,
@@ -140,37 +140,46 @@ fn lint_overflowing_range_endpoint<'tcx>(
return false;
}
- let mut overwritten = false;
// We can suggest using an inclusive range
// (`..=`) instead only if it is the `end` that is
// overflowing and only by 1.
- if eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max {
- cx.struct_span_lint(OVERFLOWING_LITERALS, struct_expr.span, |lint| {
- let mut err = lint.build(fluent::lint::range_endpoint_out_of_range);
- err.set_arg("ty", ty);
- if let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) {
- use ast::{LitIntType, LitKind};
- // We need to preserve the literal's suffix,
- // as it may determine typing information.
- let suffix = match lit.node {
- LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
- LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
- LitKind::Int(_, LitIntType::Unsuffixed) => "",
- _ => bug!(),
- };
- let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
- err.span_suggestion(
- struct_expr.span,
- fluent::lint::suggestion,
- suggestion,
- Applicability::MachineApplicable,
- );
- err.emit();
- overwritten = true;
- }
- });
- }
- overwritten
+ if !(eps[1].expr.hir_id == expr.hir_id && lit_val - 1 == max) {
+ return false;
+ };
+ let Ok(start) = cx.sess().source_map().span_to_snippet(eps[0].span) else { return false };
+
+ cx.struct_span_lint(
+ OVERFLOWING_LITERALS,
+ struct_expr.span,
+ fluent::lint_range_endpoint_out_of_range,
+ |lint| {
+ use ast::{LitIntType, LitKind};
+
+ lint.set_arg("ty", ty);
+
+ // We need to preserve the literal's suffix,
+ // as it may determine typing information.
+ let suffix = match lit.node {
+ LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
+ LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
+ LitKind::Int(_, LitIntType::Unsuffixed) => "",
+ _ => bug!(),
+ };
+ let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix);
+ lint.span_suggestion(
+ struct_expr.span,
+ fluent::suggestion,
+ suggestion,
+ Applicability::MachineApplicable,
+ );
+
+ lint
+ },
+ );
+
+ // We've just emitted a lint, special cased for `(...)..MAX+1` ranges,
+ // return `true` so the callers don't also emit a lint
+ true
}
// For `isize` & `usize`, be conservative with the warnings, so that the
@@ -221,52 +230,58 @@ fn report_bin_hex_error(
negative: bool,
) {
let size = Integer::from_attr(&cx.tcx, ty).size();
- cx.struct_span_lint(OVERFLOWING_LITERALS, expr.span, |lint| {
- let (t, actually) = match ty {
- attr::IntType::SignedInt(t) => {
- let actually = if negative {
- -(size.sign_extend(val) as i128)
- } else {
- size.sign_extend(val) as i128
- };
- (t.name_str(), actually.to_string())
- }
- attr::IntType::UnsignedInt(t) => {
- let actually = size.truncate(val);
- (t.name_str(), actually.to_string())
- }
- };
- let mut err = lint.build(fluent::lint::overflowing_bin_hex);
- if negative {
- // If the value is negative,
- // emits a note about the value itself, apart from the literal.
- err.note(fluent::lint::negative_note);
- err.note(fluent::lint::negative_becomes_note);
- } else {
- err.note(fluent::lint::positive_note);
- }
- if let Some(sugg_ty) =
- get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
- {
- err.set_arg("suggestion_ty", sugg_ty);
- if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
- let (sans_suffix, _) = repr_str.split_at(pos);
- err.span_suggestion(
- expr.span,
- fluent::lint::suggestion,
- format!("{}{}", sans_suffix, sugg_ty),
- Applicability::MachineApplicable,
- );
+ cx.struct_span_lint(
+ OVERFLOWING_LITERALS,
+ expr.span,
+ fluent::lint_overflowing_bin_hex,
+ |lint| {
+ let (t, actually) = match ty {
+ attr::IntType::SignedInt(t) => {
+ let actually = if negative {
+ -(size.sign_extend(val) as i128)
+ } else {
+ size.sign_extend(val) as i128
+ };
+ (t.name_str(), actually.to_string())
+ }
+ attr::IntType::UnsignedInt(t) => {
+ let actually = size.truncate(val);
+ (t.name_str(), actually.to_string())
+ }
+ };
+
+ if negative {
+ // If the value is negative,
+ // emits a note about the value itself, apart from the literal.
+ lint.note(fluent::negative_note);
+ lint.note(fluent::negative_becomes_note);
} else {
- err.help(fluent::lint::help);
+ lint.note(fluent::positive_note);
}
- }
- err.set_arg("ty", t);
- err.set_arg("lit", repr_str);
- err.set_arg("dec", val);
- err.set_arg("actually", actually);
- err.emit();
- });
+ if let Some(sugg_ty) =
+ get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative)
+ {
+ lint.set_arg("suggestion_ty", sugg_ty);
+ if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
+ let (sans_suffix, _) = repr_str.split_at(pos);
+ lint.span_suggestion(
+ expr.span,
+ fluent::suggestion,
+ format!("{}{}", sans_suffix, sugg_ty),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ lint.help(fluent::help);
+ }
+ }
+ lint.set_arg("ty", t)
+ .set_arg("lit", repr_str)
+ .set_arg("dec", val)
+ .set_arg("actually", actually);
+
+ lint
+ },
+ );
}
// This function finds the next fitting type and generates a suggestion string.
@@ -345,30 +360,31 @@ fn lint_int_literal<'tcx>(
}
if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
- // The overflowing literal lint was overridden.
+ // The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
return;
}
- cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
- let mut err = lint.build(fluent::lint::overflowing_int);
- err.set_arg("ty", t.name_str());
- err.set_arg(
- "lit",
- cx.sess()
- .source_map()
- .span_to_snippet(lit.span)
- .expect("must get snippet from literal"),
- );
- err.set_arg("min", min);
- err.set_arg("max", max);
- err.note(fluent::lint::note);
+ cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_int, |lint| {
+ lint.set_arg("ty", t.name_str())
+ .set_arg(
+ "lit",
+ cx.sess()
+ .source_map()
+ .span_to_snippet(lit.span)
+ .expect("must get snippet from literal"),
+ )
+ .set_arg("min", min)
+ .set_arg("max", max)
+ .note(fluent::note);
+
if let Some(sugg_ty) =
get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
{
- err.set_arg("suggestion_ty", sugg_ty);
- err.help(fluent::lint::help);
+ lint.set_arg("suggestion_ty", sugg_ty);
+ lint.help(fluent::help);
}
- err.emit();
+
+ lint
});
}
}
@@ -393,16 +409,19 @@ fn lint_uint_literal<'tcx>(
match par_e.kind {
hir::ExprKind::Cast(..) => {
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
- cx.struct_span_lint(OVERFLOWING_LITERALS, par_e.span, |lint| {
- lint.build(fluent::lint::only_cast_u8_to_char)
- .span_suggestion(
+ cx.struct_span_lint(
+ OVERFLOWING_LITERALS,
+ par_e.span,
+ fluent::lint_only_cast_u8_to_char,
+ |lint| {
+ lint.span_suggestion(
par_e.span,
- fluent::lint::suggestion,
+ fluent::suggestion,
format!("'\\u{{{:X}}}'", lit_val),
Applicability::MachineApplicable,
)
- .emit();
- });
+ },
+ );
return;
}
}
@@ -410,7 +429,7 @@ fn lint_uint_literal<'tcx>(
}
}
if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
- // The overflowing literal lint was overridden.
+ // The overflowing literal lint was emited by `lint_overflowing_range_endpoint`.
return;
}
if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
@@ -424,9 +443,8 @@ fn lint_uint_literal<'tcx>(
);
return;
}
- cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
- lint.build(fluent::lint::overflowing_uint)
- .set_arg("ty", t.name_str())
+ cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, fluent::lint_overflowing_uint, |lint| {
+ lint.set_arg("ty", t.name_str())
.set_arg(
"lit",
cx.sess()
@@ -436,8 +454,7 @@ fn lint_uint_literal<'tcx>(
)
.set_arg("min", min)
.set_arg("max", max)
- .note(fluent::lint::note)
- .emit();
+ .note(fluent::note)
});
}
}
@@ -467,19 +484,22 @@ fn lint_literal<'tcx>(
_ => bug!(),
};
if is_infinite == Ok(true) {
- cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| {
- lint.build(fluent::lint::overflowing_literal)
- .set_arg("ty", t.name_str())
- .set_arg(
- "lit",
- cx.sess()
- .source_map()
- .span_to_snippet(lit.span)
- .expect("must get snippet from literal"),
- )
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ OVERFLOWING_LITERALS,
+ e.span,
+ fluent::lint_overflowing_literal,
+ |lint| {
+ lint.set_arg("ty", t.name_str())
+ .set_arg(
+ "lit",
+ cx.sess()
+ .source_map()
+ .span_to_snippet(lit.span)
+ .expect("must get snippet from literal"),
+ )
+ .note(fluent::note)
+ },
+ );
}
}
_ => {}
@@ -497,9 +517,12 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
}
hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop) && !check_limits(cx, binop, &l, &r) {
- cx.struct_span_lint(UNUSED_COMPARISONS, e.span, |lint| {
- lint.build(fluent::lint::unused_comparisons).emit();
- });
+ cx.struct_span_lint(
+ UNUSED_COMPARISONS,
+ e.span,
+ fluent::lint_unused_comparisons,
+ |lint| lint,
+ );
}
}
hir::ExprKind::Lit(ref lit) => lint_literal(cx, self, e, lit),
@@ -819,8 +842,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
self.emit_ffi_unsafe_type_lint(
ty,
sp,
- fluent::lint::improper_ctypes_array_reason,
- Some(fluent::lint::improper_ctypes_array_help),
+ fluent::lint_improper_ctypes_array_reason,
+ Some(fluent::lint_improper_ctypes_array_help),
);
true
} else {
@@ -863,7 +886,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
} else {
// All fields are ZSTs; this means that the type should behave
// like (), which is FFI-unsafe
- FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_struct_zst, help: None }
+ FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_struct_zst, help: None }
}
} else {
// We can't completely trust repr(C) markings; make sure the fields are
@@ -877,7 +900,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
FfiPhantom(..) if def.is_enum() => {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_enum_phantomdata,
+ reason: fluent::lint_improper_ctypes_enum_phantomdata,
help: None,
};
}
@@ -908,12 +931,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
match *ty.kind() {
ty::Adt(def, substs) => {
if def.is_box() && matches!(self.mode, CItemKind::Definition) {
- if ty.boxed_ty().is_sized(tcx.at(DUMMY_SP), self.cx.param_env) {
+ if ty.boxed_ty().is_sized(tcx, self.cx.param_env) {
return FfiSafe;
} else {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_box,
+ reason: fluent::lint_improper_ctypes_box,
help: None,
};
}
@@ -927,14 +950,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
return FfiUnsafe {
ty,
reason: if def.is_struct() {
- fluent::lint::improper_ctypes_struct_layout_reason
+ fluent::lint_improper_ctypes_struct_layout_reason
} else {
- fluent::lint::improper_ctypes_union_layout_reason
+ fluent::lint_improper_ctypes_union_layout_reason
},
help: if def.is_struct() {
- Some(fluent::lint::improper_ctypes_struct_layout_help)
+ Some(fluent::lint_improper_ctypes_struct_layout_help)
} else {
- Some(fluent::lint::improper_ctypes_union_layout_help)
+ Some(fluent::lint_improper_ctypes_union_layout_help)
},
};
}
@@ -945,9 +968,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
return FfiUnsafe {
ty,
reason: if def.is_struct() {
- fluent::lint::improper_ctypes_struct_non_exhaustive
+ fluent::lint_improper_ctypes_struct_non_exhaustive
} else {
- fluent::lint::improper_ctypes_union_non_exhaustive
+ fluent::lint_improper_ctypes_union_non_exhaustive
},
help: None,
};
@@ -957,14 +980,14 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
return FfiUnsafe {
ty,
reason: if def.is_struct() {
- fluent::lint::improper_ctypes_struct_fieldless_reason
+ fluent::lint_improper_ctypes_struct_fieldless_reason
} else {
- fluent::lint::improper_ctypes_union_fieldless_reason
+ fluent::lint_improper_ctypes_union_fieldless_reason
},
help: if def.is_struct() {
- Some(fluent::lint::improper_ctypes_struct_fieldless_help)
+ Some(fluent::lint_improper_ctypes_struct_fieldless_help)
} else {
- Some(fluent::lint::improper_ctypes_union_fieldless_help)
+ Some(fluent::lint_improper_ctypes_union_fieldless_help)
},
};
}
@@ -985,8 +1008,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if repr_nullable_ptr(self.cx, ty, self.mode).is_none() {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_enum_repr_reason,
- help: Some(fluent::lint::improper_ctypes_enum_repr_help),
+ reason: fluent::lint_improper_ctypes_enum_repr_reason,
+ help: Some(fluent::lint_improper_ctypes_enum_repr_help),
};
}
}
@@ -994,7 +1017,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if def.is_variant_list_non_exhaustive() && !def.did().is_local() {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_non_exhaustive,
+ reason: fluent::lint_improper_ctypes_non_exhaustive,
help: None,
};
}
@@ -1005,7 +1028,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if is_non_exhaustive && !variant.def_id.is_local() {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_non_exhaustive_variant,
+ reason: fluent::lint_improper_ctypes_non_exhaustive_variant,
help: None,
};
}
@@ -1023,12 +1046,12 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::Char => FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_char_reason,
- help: Some(fluent::lint::improper_ctypes_char_help),
+ reason: fluent::lint_improper_ctypes_char_reason,
+ help: Some(fluent::lint_improper_ctypes_char_help),
},
ty::Int(ty::IntTy::I128) | ty::Uint(ty::UintTy::U128) => {
- FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_128bit, help: None }
+ FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_128bit, help: None }
}
// Primitive types with a stable representation.
@@ -1036,30 +1059,30 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
ty::Slice(_) => FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_slice_reason,
- help: Some(fluent::lint::improper_ctypes_slice_help),
+ reason: fluent::lint_improper_ctypes_slice_reason,
+ help: Some(fluent::lint_improper_ctypes_slice_help),
},
ty::Dynamic(..) => {
- FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_dyn, help: None }
+ FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_dyn, help: None }
}
ty::Str => FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_str_reason,
- help: Some(fluent::lint::improper_ctypes_str_help),
+ reason: fluent::lint_improper_ctypes_str_reason,
+ help: Some(fluent::lint_improper_ctypes_str_help),
},
ty::Tuple(..) => FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_tuple_reason,
- help: Some(fluent::lint::improper_ctypes_tuple_help),
+ reason: fluent::lint_improper_ctypes_tuple_reason,
+ help: Some(fluent::lint_improper_ctypes_tuple_help),
},
ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _)
if {
matches!(self.mode, CItemKind::Definition)
- && ty.is_sized(self.cx.tcx.at(DUMMY_SP), self.cx.param_env)
+ && ty.is_sized(self.cx.tcx, self.cx.param_env)
} =>
{
FfiSafe
@@ -1084,8 +1107,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
if self.is_internal_abi(sig.abi()) {
return FfiUnsafe {
ty,
- reason: fluent::lint::improper_ctypes_fnptr_reason,
- help: Some(fluent::lint::improper_ctypes_fnptr_help),
+ reason: fluent::lint_improper_ctypes_fnptr_reason,
+ help: Some(fluent::lint_improper_ctypes_fnptr_help),
};
}
@@ -1116,7 +1139,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
// While opaque types are checked for earlier, if a projection in a struct field
// normalizes to an opaque type, then it will reach this branch.
ty::Opaque(..) => {
- FfiUnsafe { ty, reason: fluent::lint::improper_ctypes_opaque, help: None }
+ FfiUnsafe { ty, reason: fluent::lint_improper_ctypes_opaque, help: None }
}
// `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe,
@@ -1150,25 +1173,24 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
CItemKind::Definition => IMPROPER_CTYPES_DEFINITIONS,
};
- self.cx.struct_span_lint(lint, sp, |lint| {
+ self.cx.struct_span_lint(lint, sp, fluent::lint_improper_ctypes, |lint| {
let item_description = match self.mode {
CItemKind::Declaration => "block",
CItemKind::Definition => "fn",
};
- let mut diag = lint.build(fluent::lint::improper_ctypes);
- diag.set_arg("ty", ty);
- diag.set_arg("desc", item_description);
- diag.span_label(sp, fluent::lint::label);
+ lint.set_arg("ty", ty);
+ lint.set_arg("desc", item_description);
+ lint.span_label(sp, fluent::label);
if let Some(help) = help {
- diag.help(help);
+ lint.help(help);
}
- diag.note(note);
+ lint.note(note);
if let ty::Adt(def, _) = ty.kind() {
if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did()) {
- diag.span_note(sp, fluent::lint::note);
+ lint.span_note(sp, fluent::note);
}
}
- diag.emit();
+ lint
});
}
@@ -1202,7 +1224,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
}
if let Some(ty) = ty.visit_with(&mut ProhibitOpaqueTypes { cx: self.cx }).break_value() {
- self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint::improper_ctypes_opaque, None);
+ self.emit_ffi_unsafe_type_lint(ty, sp, fluent::lint_improper_ctypes_opaque, None);
true
} else {
false
@@ -1247,7 +1269,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
self.emit_ffi_unsafe_type_lint(
ty,
sp,
- fluent::lint::improper_ctypes_only_phantomdata,
+ fluent::lint_improper_ctypes_only_phantomdata,
None,
);
}
@@ -1338,7 +1360,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.def_id);
+ let t = cx.tcx.type_of(it.owner_id);
let ty = cx.tcx.erase_regions(t);
let Ok(layout) = cx.layout_of(ty) else { return };
let Variants::Multiple {
@@ -1381,11 +1403,8 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
cx.struct_span_lint(
VARIANT_SIZE_DIFFERENCES,
enum_definition.variants[largest_index].span,
- |lint| {
- lint.build(fluent::lint::variant_size_differences)
- .set_arg("largest", largest)
- .emit();
- },
+ fluent::lint_variant_size_differences,
+ |lint| lint.set_arg("largest", largest),
);
}
}
@@ -1493,25 +1512,16 @@ impl InvalidAtomicOrdering {
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
- && let Some((ordering_arg, invalid_ordering)) = match method {
- sym::load => Some((&args[0], sym::Release)),
- sym::store => Some((&args[1], sym::Acquire)),
+ && let Some((ordering_arg, invalid_ordering, msg)) = match method {
+ sym::load => Some((&args[0], sym::Release, fluent::lint_atomic_ordering_load)),
+ sym::store => Some((&args[1], sym::Acquire, fluent::lint_atomic_ordering_store)),
_ => None,
}
&& let Some(ordering) = Self::match_ordering(cx, ordering_arg)
&& (ordering == invalid_ordering || ordering == sym::AcqRel)
{
- cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
- if method == sym::load {
- diag.build(fluent::lint::atomic_ordering_load)
- .help(fluent::lint::help)
- .emit()
- } else {
- debug_assert_eq!(method, sym::store);
- diag.build(fluent::lint::atomic_ordering_store)
- .help(fluent::lint::help)
- .emit();
- }
+ cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, msg, |lint| {
+ lint.help(fluent::help)
});
}
}
@@ -1523,10 +1533,9 @@ impl InvalidAtomicOrdering {
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
{
- cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
- diag.build(fluent::lint::atomic_ordering_fence)
- .help(fluent::lint::help)
- .emit();
+ cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, fluent::lint_atomic_ordering_fence, |lint| {
+ lint
+ .help(fluent::help)
});
}
}
@@ -1545,7 +1554,7 @@ impl InvalidAtomicOrdering {
if matches!(fail_ordering, sym::Release | sym::AcqRel) {
#[derive(LintDiagnostic)]
- #[diag(lint::atomic_ordering_invalid)]
+ #[diag(lint_atomic_ordering_invalid)]
#[help]
struct InvalidAtomicOrderingDiag {
method: Symbol,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 8c9ceb711..46706e498 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -7,6 +7,7 @@ use rustc_errors::{fluent, pluralize, Applicability, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
+use rustc_infer::traits::util::elaborate_predicates_with_span;
use rustc_middle::ty::adjustment;
use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::Symbol;
@@ -154,24 +155,22 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
};
if let Some(must_use_op) = must_use_op {
- cx.struct_span_lint(UNUSED_MUST_USE, expr.span, |lint| {
- lint.build(fluent::lint::unused_op)
- .set_arg("op", must_use_op)
- .span_label(expr.span, fluent::lint::label)
+ cx.struct_span_lint(UNUSED_MUST_USE, expr.span, fluent::lint_unused_op, |lint| {
+ lint.set_arg("op", must_use_op)
+ .span_label(expr.span, fluent::label)
.span_suggestion_verbose(
expr.span.shrink_to_lo(),
- fluent::lint::suggestion,
+ fluent::suggestion,
"let _ = ",
Applicability::MachineApplicable,
)
- .emit();
});
op_warned = true;
}
if !(type_permits_lack_of_use || fn_warned || op_warned) {
- cx.struct_span_lint(UNUSED_RESULTS, s.span, |lint| {
- lint.build(fluent::lint::unused_result).set_arg("ty", ty).emit();
+ cx.struct_span_lint(UNUSED_RESULTS, s.span, fluent::lint_unused_result, |lint| {
+ lint.set_arg("ty", ty)
});
}
@@ -206,10 +205,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
ty::Adt(def, _) => check_must_use_def(cx, def.did(), span, descr_pre, descr_post),
ty::Opaque(def, _) => {
let mut has_emitted = false;
- for &(predicate, _) in cx.tcx.explicit_item_bounds(def) {
+ for obligation in elaborate_predicates_with_span(
+ cx.tcx,
+ cx.tcx.explicit_item_bounds(def).iter().cloned(),
+ ) {
// We only look at the `DefId`, so it is safe to skip the binder here.
if let ty::PredicateKind::Trait(ref poly_trait_predicate) =
- predicate.kind().skip_binder()
+ obligation.predicate.kind().skip_binder()
{
let def_id = poly_trait_predicate.trait_ref.def_id;
let descr_pre =
@@ -267,29 +269,35 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
},
ty::Closure(..) => {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
- // FIXME(davidtwco): this isn't properly translatable because of the
- // pre/post strings
- lint.build(fluent::lint::unused_closure)
- .set_arg("count", plural_len)
- .set_arg("pre", descr_pre)
- .set_arg("post", descr_post)
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ UNUSED_MUST_USE,
+ span,
+ fluent::lint_unused_closure,
+ |lint| {
+ // FIXME(davidtwco): this isn't properly translatable because of the
+ // pre/post strings
+ lint.set_arg("count", plural_len)
+ .set_arg("pre", descr_pre)
+ .set_arg("post", descr_post)
+ .note(fluent::note)
+ },
+ );
true
}
ty::Generator(..) => {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
- // FIXME(davidtwco): this isn't properly translatable because of the
- // pre/post strings
- lint.build(fluent::lint::unused_generator)
- .set_arg("count", plural_len)
- .set_arg("pre", descr_pre)
- .set_arg("post", descr_post)
- .note(fluent::lint::note)
- .emit();
- });
+ cx.struct_span_lint(
+ UNUSED_MUST_USE,
+ span,
+ fluent::lint_unused_generator,
+ |lint| {
+ // FIXME(davidtwco): this isn't properly translatable because of the
+ // pre/post strings
+ lint.set_arg("count", plural_len)
+ .set_arg("pre", descr_pre)
+ .set_arg("post", descr_post)
+ .note(fluent::note)
+ },
+ );
true
}
_ => false,
@@ -309,18 +317,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
descr_post_path: &str,
) -> bool {
if let Some(attr) = cx.tcx.get_attr(def_id, sym::must_use) {
- cx.struct_span_lint(UNUSED_MUST_USE, span, |lint| {
+ cx.struct_span_lint(UNUSED_MUST_USE, span, fluent::lint_unused_def, |lint| {
// FIXME(davidtwco): this isn't properly translatable because of the pre/post
// strings
- let mut err = lint.build(fluent::lint::unused_def);
- err.set_arg("pre", descr_pre_path);
- err.set_arg("post", descr_post_path);
- err.set_arg("def", cx.tcx.def_path_str(def_id));
+ lint.set_arg("pre", descr_pre_path);
+ lint.set_arg("post", descr_post_path);
+ lint.set_arg("def", cx.tcx.def_path_str(def_id));
// check for #[must_use = "..."]
if let Some(note) = attr.value_str() {
- err.note(note.as_str());
+ lint.note(note.as_str());
}
- err.emit();
+ lint
});
true
} else {
@@ -357,25 +364,34 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
if let hir::StmtKind::Semi(expr) = s.kind {
if let hir::ExprKind::Path(_) = expr.kind {
- cx.struct_span_lint(PATH_STATEMENTS, s.span, |lint| {
- let ty = cx.typeck_results().expr_ty(expr);
- if ty.needs_drop(cx.tcx, cx.param_env) {
- let mut lint = lint.build(fluent::lint::path_statement_drop);
- if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
- lint.span_suggestion(
- s.span,
- fluent::lint::suggestion,
- format!("drop({});", snippet),
- Applicability::MachineApplicable,
- );
- } else {
- lint.span_help(s.span, fluent::lint::suggestion);
- }
- lint.emit();
- } else {
- lint.build(fluent::lint::path_statement_no_effect).emit();
- }
- });
+ let ty = cx.typeck_results().expr_ty(expr);
+ if ty.needs_drop(cx.tcx, cx.param_env) {
+ cx.struct_span_lint(
+ PATH_STATEMENTS,
+ s.span,
+ fluent::lint_path_statement_drop,
+ |lint| {
+ if let Ok(snippet) = cx.sess().source_map().span_to_snippet(expr.span) {
+ lint.span_suggestion(
+ s.span,
+ fluent::suggestion,
+ format!("drop({});", snippet),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ lint.span_help(s.span, fluent::suggestion);
+ }
+ lint
+ },
+ );
+ } else {
+ cx.struct_span_lint(
+ PATH_STATEMENTS,
+ s.span,
+ fluent::lint_path_statement_no_effect,
+ |lint| lint,
+ );
+ }
}
}
}
@@ -545,22 +561,21 @@ trait UnusedDelimLint {
} else {
MultiSpan::from(value_span)
};
- cx.struct_span_lint(self.lint(), primary_span, |lint| {
- let mut db = lint.build(fluent::lint::unused_delim);
- db.set_arg("delim", Self::DELIM_STR);
- db.set_arg("item", msg);
+ cx.struct_span_lint(self.lint(), primary_span, fluent::lint_unused_delim, |lint| {
+ lint.set_arg("delim", Self::DELIM_STR);
+ lint.set_arg("item", msg);
if let Some((lo, hi)) = spans {
let replacement = vec![
(lo, if keep_space.0 { " ".into() } else { "".into() }),
(hi, if keep_space.1 { " ".into() } else { "".into() }),
];
- db.multipart_suggestion(
- fluent::lint::suggestion,
+ lint.multipart_suggestion(
+ fluent::suggestion,
replacement,
Applicability::MachineApplicable,
);
}
- db.emit();
+ lint
});
}
@@ -608,8 +623,7 @@ trait UnusedDelimLint {
ref call_or_other => {
let (args_to_check, ctx) = match *call_or_other {
Call(_, ref args) => (&args[..], UnusedDelimsCtx::FunctionArg),
- // first "argument" is self (which sometimes needs delims)
- MethodCall(_, ref args, _) => (&args[1..], UnusedDelimsCtx::MethodArg),
+ MethodCall(_, _, ref args, _) => (&args[..], UnusedDelimsCtx::MethodArg),
// actual catch-all arm
_ => {
return;
@@ -1129,9 +1143,12 @@ impl UnusedImportBraces {
ast::UseTreeKind::Nested(_) => return,
};
- cx.struct_span_lint(UNUSED_IMPORT_BRACES, item.span, |lint| {
- lint.build(fluent::lint::unused_import_braces).set_arg("node", node_name).emit();
- });
+ cx.struct_span_lint(
+ UNUSED_IMPORT_BRACES,
+ item.span,
+ fluent::lint_unused_import_braces,
+ |lint| lint.set_arg("node", node_name),
+ );
}
}
}
@@ -1180,15 +1197,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
for adj in cx.typeck_results().expr_adjustments(e) {
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
- cx.struct_span_lint(UNUSED_ALLOCATION, e.span, |lint| {
- lint.build(match m {
- adjustment::AutoBorrowMutability::Not => fluent::lint::unused_allocation,
+ cx.struct_span_lint(
+ UNUSED_ALLOCATION,
+ e.span,
+ match m {
+ adjustment::AutoBorrowMutability::Not => fluent::lint_unused_allocation,
adjustment::AutoBorrowMutability::Mut { .. } => {
- fluent::lint::unused_allocation_mut
+ fluent::lint_unused_allocation_mut
}
- })
- .emit();
- });
+ },
+ |lint| lint,
+ );
}
}
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e5dfda24d..61ee467f5 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -264,37 +264,6 @@ declare_lint! {
}
declare_lint! {
- /// The `const_err` lint detects an erroneous expression while doing
- /// constant evaluation.
- ///
- /// ### Example
- ///
- /// ```rust,compile_fail
- /// #![allow(unconditional_panic)]
- /// const C: i32 = 1/0;
- /// ```
- ///
- /// {{produces}}
- ///
- /// ### Explanation
- ///
- /// This lint detects constants that fail to evaluate. Allowing the lint will accept the
- /// constant declaration, but any use of this constant will still lead to a hard error. This is
- /// a future incompatibility lint; the plan is to eventually entirely forbid even declaring
- /// constants that cannot be evaluated. See [issue #71800] for more details.
- ///
- /// [issue #71800]: https://github.com/rust-lang/rust/issues/71800
- pub CONST_ERR,
- Deny,
- "constant evaluation encountered erroneous expression",
- @future_incompatible = FutureIncompatibleInfo {
- reference: "issue #71800 <https://github.com/rust-lang/rust/issues/71800>",
- reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
- };
- report_in_external_macro
-}
-
-declare_lint! {
/// The `unused_imports` lint detects imports that are never used.
///
/// ### Example
@@ -1458,6 +1427,7 @@ declare_lint! {
"trait-object types were treated as different depending on marker-trait order",
@future_incompatible = FutureIncompatibleInfo {
reference: "issue #56484 <https://github.com/rust-lang/rust/issues/56484>",
+ reason: FutureIncompatibilityReason::FutureReleaseErrorReportNow,
};
}
@@ -2909,7 +2879,7 @@ declare_lint! {
/// ### Example
///
/// ```rust
- /// #![feature(naked_functions)]
+ /// #![feature(asm_experimental_arch, naked_functions)]
///
/// use std::arch::asm;
///
@@ -3295,7 +3265,6 @@ declare_lint_pass! {
EXPORTED_PRIVATE_DEPENDENCIES,
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
INVALID_TYPE_PARAM_DEFAULT,
- CONST_ERR,
RENAMED_AND_REMOVED_LINTS,
UNALIGNED_REFERENCES,
CONST_ITEM_MUTATION,
@@ -3969,7 +3938,7 @@ declare_lint! {
///
/// The compiler disables the automatic implementation if an explicit one
/// exists for given type constructor. The exact rules governing this
- /// are currently unsound and quite subtle and and will be modified in the future.
+ /// are currently unsound, quite subtle, and will be modified in the future.
/// This change will cause the automatic implementation to be disabled in more
/// cases, potentially breaking some code.
pub SUSPICIOUS_AUTO_TRAIT_IMPLS,
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 11b2d057a..aa54b3d8a 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -25,6 +25,9 @@ macro_rules! pluralize {
($x:expr) => {
if $x != 1 { "s" } else { "" }
};
+ ("has", $x:expr) => {
+ if $x == 1 { "has" } else { "have" }
+ };
("is", $x:expr) => {
if $x == 1 { "is" } else { "are" }
};
@@ -92,7 +95,7 @@ pub enum LintExpectationId {
/// stable and can be cached. The additional index ensures that nodes with
/// several expectations can correctly match diagnostics to the individual
/// expectation.
- Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16> },
+ Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16>, attr_id: Option<AttrId> },
}
impl LintExpectationId {
@@ -116,13 +119,31 @@ impl LintExpectationId {
*lint_index = new_lint_index
}
+
+ /// Prepares the id for hashing. Removes references to the ast.
+ /// Should only be called when the id is stable.
+ pub fn normalize(self) -> Self {
+ match self {
+ Self::Stable { hir_id, attr_index, lint_index, .. } => {
+ Self::Stable { hir_id, attr_index, lint_index, attr_id: None }
+ }
+ Self::Unstable { .. } => {
+ unreachable!("`normalize` called when `ExpectationId` is unstable")
+ }
+ }
+ }
}
impl<HCX: rustc_hir::HashStableContext> HashStable<HCX> for LintExpectationId {
#[inline]
fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
match self {
- LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
+ LintExpectationId::Stable {
+ hir_id,
+ attr_index,
+ lint_index: Some(lint_index),
+ attr_id: _,
+ } => {
hir_id.hash_stable(hcx, hasher);
attr_index.hash_stable(hcx, hasher);
lint_index.hash_stable(hcx, hasher);
@@ -142,9 +163,12 @@ impl<HCX: rustc_hir::HashStableContext> ToStableHashKey<HCX> for LintExpectation
#[inline]
fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType {
match self {
- LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
- (*hir_id, *attr_index, *lint_index)
- }
+ LintExpectationId::Stable {
+ hir_id,
+ attr_index,
+ lint_index: Some(lint_index),
+ attr_id: _,
+ } => (*hir_id, *attr_index, *lint_index),
_ => {
unreachable!("HashStable should only be called for a filled `LintExpectationId`")
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 24e188260..18d37d95a 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -31,13 +31,12 @@
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Transforms/IPO/AlwaysInliner.h"
#include "llvm/Transforms/IPO/FunctionImport.h"
-#if LLVM_VERSION_GE(15, 0)
+#include "llvm/Transforms/IPO/Internalize.h"
#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
-#endif
#include "llvm/Transforms/Utils/AddDiscriminators.h"
#include "llvm/Transforms/Utils/FunctionImportUtils.h"
#include "llvm/LTO/LTO.h"
-#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm-c/Transforms/PassManagerBuilder.h"
#include "llvm/Transforms/Instrumentation.h"
@@ -70,7 +69,9 @@ extern "C" void LLVMInitializePasses() {
initializeAnalysis(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
+#if LLVM_VERSION_LT(16, 0)
initializeInstrumentation(Registry);
+#endif
initializeTarget(Registry);
}
@@ -93,172 +94,6 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) {
timeTraceProfilerCleanup();
}
-extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
-#if LLVM_VERSION_LT(15, 0)
- StringRef SR(PassName);
- PassRegistry *PR = PassRegistry::getPassRegistry();
-
- const PassInfo *PI = PR->getPassInfo(SR);
- if (PI) {
- return wrap(PI->createPass());
- }
- return nullptr;
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassRef LLVMRustCreateAddressSanitizerFunctionPass(bool Recover) {
-#if LLVM_VERSION_LT(15, 0)
- const bool CompileKernel = false;
- const bool UseAfterScope = true;
-
- return wrap(createAddressSanitizerFunctionPass(CompileKernel, Recover, UseAfterScope));
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassRef LLVMRustCreateModuleAddressSanitizerPass(bool Recover) {
-#if LLVM_VERSION_LT(15, 0)
- const bool CompileKernel = false;
-
- return wrap(createModuleAddressSanitizerLegacyPassPass(CompileKernel, Recover));
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassRef LLVMRustCreateMemorySanitizerPass(int TrackOrigins, bool Recover) {
-#if LLVM_VERSION_LT(15, 0)
- const bool CompileKernel = false;
-
- return wrap(createMemorySanitizerLegacyPassPass(
-#if LLVM_VERSION_GE(14, 0)
- MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel, /*EagerChecks=*/true}
-#else
- MemorySanitizerOptions{TrackOrigins, Recover, CompileKernel}
-#endif
- ));
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassRef LLVMRustCreateThreadSanitizerPass() {
-#if LLVM_VERSION_LT(15, 0)
- return wrap(createThreadSanitizerLegacyPassPass());
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) {
-#if LLVM_VERSION_LT(15, 0)
- const bool CompileKernel = false;
-
- return wrap(createHWAddressSanitizerLegacyPassPass(CompileKernel, Recover));
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
-#if LLVM_VERSION_LT(15, 0)
- assert(RustPass);
- Pass *Pass = unwrap(RustPass);
- PassManagerBase *PMB = unwrap(PMR);
- PMB->add(Pass);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" LLVMPassManagerBuilderRef LLVMRustPassManagerBuilderCreate() {
-#if LLVM_VERSION_LT(15, 0)
- return LLVMPassManagerBuilderCreate();
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) {
-#if LLVM_VERSION_LT(15, 0)
- LLVMPassManagerBuilderDispose(PMB);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustPassManagerBuilderPopulateFunctionPassManager(
- LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
-#if LLVM_VERSION_LT(15, 0)
- LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustPassManagerBuilderPopulateModulePassManager(
- LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) {
-#if LLVM_VERSION_LT(15, 0)
- LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustPassManagerBuilderPopulateLTOPassManager(
- LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM, bool Internalize, bool RunInliner) {
-#if LLVM_VERSION_LT(15, 0)
- LLVMPassManagerBuilderPopulateLTOPassManager(PMB, PM, Internalize, RunInliner);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C"
-void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
- LLVMPassManagerBuilderRef PMBR,
- LLVMPassManagerRef PMR
-) {
-#if LLVM_VERSION_LT(15, 0)
- unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C" void LLVMRustPassManagerBuilderUseInlinerWithThreshold(
- LLVMPassManagerBuilderRef PMB, unsigned Threshold) {
-#if LLVM_VERSION_LT(15, 0)
- LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-extern "C"
-void LLVMRustAddLastExtensionPasses(
- LLVMPassManagerBuilderRef PMBR, LLVMPassRef *Passes, size_t NumPasses) {
-#if LLVM_VERSION_LT(15, 0)
- auto AddExtensionPasses = [Passes, NumPasses](
- const PassManagerBuilder &Builder, PassManagerBase &PM) {
- for (size_t I = 0; I < NumPasses; I++) {
- PM.add(unwrap(Passes[I]));
- }
- };
- // Add the passes to both of the pre-finalization extension points,
- // so they are run for optimized and non-optimized builds.
- unwrap(PMBR)->addExtension(PassManagerBuilder::EP_OptimizerLast,
- AddExtensionPasses);
- unwrap(PMBR)->addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
- AddExtensionPasses);
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
#ifdef LLVM_COMPONENT_X86
#define SUBTARGET_X86 SUBTARGET(X86)
#else
@@ -604,47 +439,6 @@ extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
delete unwrap(TM);
}
-extern "C" void LLVMRustConfigurePassManagerBuilder(
- LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
- bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
- const char* PGOGenPath, const char* PGOUsePath, const char* PGOSampleUsePath,
- int SizeLevel) {
-#if LLVM_VERSION_LT(15, 0)
- unwrap(PMBR)->MergeFunctions = MergeFunctions;
- unwrap(PMBR)->SLPVectorize = SLPVectorize;
- unwrap(PMBR)->OptLevel = fromRust(OptLevel);
- unwrap(PMBR)->LoopVectorize = LoopVectorize;
- unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
- unwrap(PMBR)->SizeLevel = SizeLevel;
- unwrap(PMBR)->DisableUnrollLoops = SizeLevel != 0;
-
- if (PGOGenPath) {
- assert(!PGOUsePath && !PGOSampleUsePath);
- unwrap(PMBR)->EnablePGOInstrGen = true;
- unwrap(PMBR)->PGOInstrGen = PGOGenPath;
- } else if (PGOUsePath) {
- assert(!PGOSampleUsePath);
- unwrap(PMBR)->PGOInstrUse = PGOUsePath;
- } else if (PGOSampleUsePath) {
- unwrap(PMBR)->PGOSampleUse = PGOSampleUsePath;
- }
-#else
- report_fatal_error("Legacy PM not supported with LLVM 15");
-#endif
-}
-
-// Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
-// field of a PassManagerBuilder, we expose our own method of doing so.
-extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
- LLVMModuleRef M,
- bool DisableSimplifyLibCalls) {
- Triple TargetTriple(unwrap(M)->getTargetTriple());
- TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
- if (DisableSimplifyLibCalls)
- TLI->disableAllFunctions();
- unwrap(PMBR)->LibraryInfo = TLI;
-}
-
// Unfortunately, the LLVM C API doesn't provide a way to create the
// TargetLibraryInfo pass, so we use this method to do so.
extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
@@ -656,27 +450,6 @@ extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
}
-// Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
-// all the functions in a module, so we do that manually here. You'll find
-// similar code in clang's BackendUtil.cpp file.
-extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
- LLVMModuleRef M) {
- llvm::legacy::FunctionPassManager *P =
- unwrap<llvm::legacy::FunctionPassManager>(PMR);
- P->doInitialization();
-
- // Upgrade all calls to old intrinsics first.
- for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
- UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
-
- for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
- ++I)
- if (!I->isDeclaration())
- P->run(*I);
-
- P->doFinalization();
-}
-
extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
// Initializing the command-line options more than once is not allowed. So,
// check if they've already been initialized. (This could happen if we're
@@ -820,7 +593,7 @@ struct LLVMRustSanitizerOptions {
};
extern "C" LLVMRustResult
-LLVMRustOptimizeWithNewPassManager(
+LLVMRustOptimize(
LLVMModuleRef ModuleRef,
LLVMTargetMachineRef TMRef,
LLVMRustPassBuilderOptLevel OptLevelRust,
@@ -1241,15 +1014,8 @@ extern "C" void LLVMRustPrintPasses() {
PR->enumerateWith(&Listener);
}
-extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
- bool AddLifetimes) {
- unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
-}
-
extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
size_t Len) {
- llvm::legacy::PassManager passes;
-
auto PreserveFunctions = [=](const GlobalValue &GV) {
for (size_t I = 0; I < Len; I++) {
if (GV.getName() == Symbols[I]) {
@@ -1259,9 +1025,7 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
return false;
};
- passes.add(llvm::createInternalizePass(PreserveFunctions));
-
- passes.run(*unwrap(M));
+ internalizeModule(*unwrap(M), PreserveFunctions);
}
extern "C" void
@@ -1282,7 +1046,7 @@ extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
extern "C" void LLVMRustSetModuleCodeModel(LLVMModuleRef M,
LLVMRustCodeModel Model) {
auto CM = fromRust(Model);
- if (!CM.hasValue())
+ if (!CM)
return;
unwrap(M)->setCodeModel(*CM);
}
@@ -1610,11 +1374,6 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
raw_string_ostream OS(Ret->data);
{
if (is_thin) {
-#if LLVM_VERSION_LT(15, 0)
- legacy::PassManager PM;
- PM.add(createWriteThinLTOBitcodePass(OS));
- PM.run(*unwrap(M));
-#else
PassBuilder PB;
LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
@@ -1628,11 +1387,8 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
ModulePassManager MPM;
MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
MPM.run(*unwrap(M), MAM);
-#endif
} else {
- legacy::PassManager PM;
- PM.add(createBitcodeWriterPass(OS));
- PM.run(*unwrap(M));
+ WriteBitcodeToFile(*unwrap(M), OS);
}
}
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 6ee3c7d68..6f36281af 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -12,7 +12,7 @@
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Pass.h"
-#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Support/Signals.h"
#include "llvm/ADT/Optional.h"
@@ -406,45 +406,6 @@ extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
return wrap(SI);
}
-// FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
-// once we raise our minimum support to LLVM 10.
-extern "C" LLVMValueRef
-LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
- LLVMValueRef Old, LLVMValueRef Source,
- LLVMAtomicOrdering Order,
- LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
- // Rust probably knows the alignment of the target value and should be able to
- // specify something more precise than MaybeAlign here. See also
- // https://reviews.llvm.org/D97224 which may be a useful reference.
- AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
- unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
- fromRust(FailureOrder));
- ACXI->setWeak(Weak);
- return wrap(ACXI);
-}
-
-enum class LLVMRustSynchronizationScope {
- SingleThread,
- CrossThread,
-};
-
-static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
- switch (Scope) {
- case LLVMRustSynchronizationScope::SingleThread:
- return SyncScope::SingleThread;
- case LLVMRustSynchronizationScope::CrossThread:
- return SyncScope::System;
- default:
- report_fatal_error("bad SynchronizationScope.");
- }
-}
-
-extern "C" LLVMValueRef
-LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
- LLVMRustSynchronizationScope Scope) {
- return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
-}
-
enum class LLVMRustAsmDialect {
Att,
Intel,
@@ -1709,11 +1670,7 @@ LLVMRustModuleBufferCreate(LLVMModuleRef M) {
auto Ret = std::make_unique<LLVMRustModuleBuffer>();
{
raw_string_ostream OS(Ret->data);
- {
- legacy::PassManager PM;
- PM.add(createBitcodeWriterPass(OS));
- PM.run(*unwrap(M));
- }
+ WriteBitcodeToFile(*unwrap(M), OS);
}
return Ret.release();
}
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index cf1c59455..ef1985b96 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -2,94 +2,77 @@
use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind};
use crate::diagnostics::error::{span_err, DiagnosticDeriveError};
-use crate::diagnostics::utils::{build_field_mapping, SetOnce};
+use crate::diagnostics::utils::SetOnce;
use proc_macro2::TokenStream;
use quote::quote;
-use syn::spanned::Spanned;
use synstructure::Structure;
/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
-pub(crate) struct SessionDiagnosticDerive<'a> {
+pub(crate) struct DiagnosticDerive<'a> {
structure: Structure<'a>,
- sess: syn::Ident,
builder: DiagnosticDeriveBuilder,
}
-impl<'a> SessionDiagnosticDerive<'a> {
- pub(crate) fn new(diag: syn::Ident, sess: syn::Ident, structure: Structure<'a>) -> Self {
+impl<'a> DiagnosticDerive<'a> {
+ pub(crate) fn new(diag: syn::Ident, handler: syn::Ident, structure: Structure<'a>) -> Self {
Self {
builder: DiagnosticDeriveBuilder {
diag,
- fields: build_field_mapping(&structure),
- kind: DiagnosticDeriveKind::SessionDiagnostic,
- code: None,
- slug: None,
+ kind: DiagnosticDeriveKind::Diagnostic { handler },
},
- sess,
structure,
}
}
pub(crate) fn into_tokens(self) -> TokenStream {
- let SessionDiagnosticDerive { mut structure, sess, mut builder } = self;
-
- let ast = structure.ast();
- let implementation = {
- if let syn::Data::Struct(..) = ast.data {
- let preamble = builder.preamble(&structure);
- let (attrs, args) = builder.body(&mut structure);
-
- let span = ast.span().unwrap();
- let diag = &builder.diag;
- let init = match builder.slug.value() {
- None => {
- span_err(span, "diagnostic slug not specified")
- .help(&format!(
- "specify the slug as the first argument to the `#[diag(...)]` attribute, \
- such as `#[diag(typeck::example_error)]`",
- ))
- .emit();
- return DiagnosticDeriveError::ErrorHandled.to_compile_error();
- }
- Some(slug) => {
- quote! {
- let mut #diag = #sess.struct_diagnostic(rustc_errors::fluent::#slug);
- }
- }
- };
-
- quote! {
- #init
- #preamble
- match self {
- #attrs
- }
- match self {
- #args
+ let DiagnosticDerive { mut structure, mut builder } = self;
+
+ let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
+ let preamble = builder.preamble(&variant);
+ let body = builder.body(&variant);
+
+ let diag = &builder.parent.diag;
+ let DiagnosticDeriveKind::Diagnostic { handler } = &builder.parent.kind else {
+ unreachable!()
+ };
+ let init = match builder.slug.value_ref() {
+ None => {
+ span_err(builder.span, "diagnostic slug not specified")
+ .help(&format!(
+ "specify the slug as the first argument to the `#[diag(...)]` \
+ attribute, such as `#[diag(hir_analysis_example_error)]`",
+ ))
+ .emit();
+ return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+ }
+ Some(slug) => {
+ quote! {
+ let mut #diag = #handler.struct_diagnostic(rustc_errors::fluent::#slug);
}
- #diag
}
- } else {
- span_err(
- ast.span().unwrap(),
- "`#[derive(SessionDiagnostic)]` can only be used on structs",
- )
- .emit();
-
- DiagnosticDeriveError::ErrorHandled.to_compile_error()
+ };
+
+ let formatting_init = &builder.formatting_init;
+ quote! {
+ #init
+ #formatting_init
+ #preamble
+ #body
+ #diag
}
- };
+ });
+ let DiagnosticDeriveKind::Diagnostic { handler } = &builder.kind else { unreachable!() };
structure.gen_impl(quote! {
- gen impl<'__session_diagnostic_sess, G>
- rustc_session::SessionDiagnostic<'__session_diagnostic_sess, G>
+ gen impl<'__diagnostic_handler_sess, G>
+ rustc_errors::IntoDiagnostic<'__diagnostic_handler_sess, G>
for @Self
where G: rustc_errors::EmissionGuarantee
{
fn into_diagnostic(
self,
- #sess: &'__session_diagnostic_sess rustc_errors::Handler
- ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, G> {
+ #handler: &'__diagnostic_handler_sess rustc_errors::Handler
+ ) -> rustc_errors::DiagnosticBuilder<'__diagnostic_handler_sess, G> {
use rustc_errors::IntoDiagnosticArg;
#implementation
}
@@ -107,13 +90,7 @@ pub(crate) struct LintDiagnosticDerive<'a> {
impl<'a> LintDiagnosticDerive<'a> {
pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self {
Self {
- builder: DiagnosticDeriveBuilder {
- diag,
- fields: build_field_mapping(&structure),
- kind: DiagnosticDeriveKind::LintDiagnostic,
- code: None,
- slug: None,
- },
+ builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic },
structure,
}
}
@@ -121,62 +98,52 @@ impl<'a> LintDiagnosticDerive<'a> {
pub(crate) fn into_tokens(self) -> TokenStream {
let LintDiagnosticDerive { mut structure, mut builder } = self;
- let ast = structure.ast();
- let implementation = {
- if let syn::Data::Struct(..) = ast.data {
- let preamble = builder.preamble(&structure);
- let (attrs, args) = builder.body(&mut structure);
-
- let diag = &builder.diag;
- let span = ast.span().unwrap();
- let init = match builder.slug.value() {
- None => {
- span_err(span, "diagnostic slug not specified")
- .help(&format!(
- "specify the slug as the first argument to the attribute, such as \
- `#[diag(typeck::example_error)]`",
- ))
- .emit();
- return DiagnosticDeriveError::ErrorHandled.to_compile_error();
- }
- Some(slug) => {
- quote! {
- let mut #diag = #diag.build(rustc_errors::fluent::#slug);
- }
- }
- };
-
- let implementation = quote! {
- #init
- #preamble
- match self {
- #attrs
- }
- match self {
- #args
- }
- #diag.emit();
- };
-
- implementation
- } else {
- span_err(
- ast.span().unwrap(),
- "`#[derive(LintDiagnostic)]` can only be used on structs",
- )
- .emit();
-
- DiagnosticDeriveError::ErrorHandled.to_compile_error()
+ let implementation = builder.each_variant(&mut structure, |mut builder, variant| {
+ let preamble = builder.preamble(&variant);
+ let body = builder.body(&variant);
+
+ let diag = &builder.parent.diag;
+ let formatting_init = &builder.formatting_init;
+ quote! {
+ #preamble
+ #formatting_init
+ #body
+ #diag
}
- };
+ });
+
+ let msg = builder.each_variant(&mut structure, |mut builder, variant| {
+ // Collect the slug by generating the preamble.
+ let _ = builder.preamble(&variant);
+
+ match builder.slug.value_ref() {
+ None => {
+ span_err(builder.span, "diagnostic slug not specified")
+ .help(&format!(
+ "specify the slug as the first argument to the attribute, such as \
+ `#[diag(compiletest_example)]`",
+ ))
+ .emit();
+ return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+ }
+ Some(slug) => quote! { rustc_errors::fluent::#slug.into() },
+ }
+ });
let diag = &builder.diag;
structure.gen_impl(quote! {
gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self {
- fn decorate_lint(self, #diag: rustc_errors::LintDiagnosticBuilder<'__a, ()>) {
+ fn decorate_lint<'__b>(
+ self,
+ #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()>
+ ) -> &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> {
use rustc_errors::IntoDiagnosticArg;
#implementation
}
+
+ fn msg(&self) -> rustc_errors::DiagnosticMessage {
+ #msg
+ }
}
})
}
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 2a4fe48a8..3ea83fd09 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -5,56 +5,124 @@ use crate::diagnostics::error::{
DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
- report_error_if_not_applied_to_span, report_type_error, type_is_unit, type_matches_path,
- Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce,
+ build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
+ should_generate_set_arg, type_is_unit, type_matches_path, FieldInfo, FieldInnerTy, FieldMap,
+ HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote};
-use std::collections::HashMap;
-use std::str::FromStr;
use syn::{
- parse_quote, spanned::Spanned, Attribute, Field, Meta, MetaList, MetaNameValue, NestedMeta,
- Path, Type,
+ parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
};
-use synstructure::{BindingInfo, Structure};
+use synstructure::{BindingInfo, Structure, VariantInfo};
/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Clone, PartialEq, Eq)]
pub(crate) enum DiagnosticDeriveKind {
- SessionDiagnostic,
+ Diagnostic { handler: syn::Ident },
LintDiagnostic,
}
-/// Tracks persistent information required for building up individual calls to diagnostic methods
-/// for generated diagnostic derives - both `SessionDiagnostic` for fatal/errors/warnings and
-/// `LintDiagnostic` for lints.
+/// Tracks persistent information required for the entire type when building up individual calls to
+/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for
+/// fatal/errors/warnings and `LintDiagnostic` for lints.
pub(crate) struct DiagnosticDeriveBuilder {
/// The identifier to use for the generated `DiagnosticBuilder` instance.
pub diag: syn::Ident,
+ /// Kind of diagnostic that should be derived.
+ pub kind: DiagnosticDeriveKind,
+}
+
+/// Tracks persistent information required for a specific variant when building up individual calls
+/// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for
+/// fatal/errors/warnings and `LintDiagnostic` for lints.
+pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> {
+ /// The parent builder for the entire type.
+ pub parent: &'parent DiagnosticDeriveBuilder,
+
+ /// Initialization of format strings for code suggestions.
+ pub formatting_init: TokenStream,
+
+ /// Span of the struct or the enum variant.
+ pub span: proc_macro::Span,
/// Store a map of field name to its corresponding field. This is built on construction of the
/// derive builder.
- pub fields: HashMap<String, TokenStream>,
+ pub field_map: FieldMap,
- /// Kind of diagnostic that should be derived.
- pub kind: DiagnosticDeriveKind,
/// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
/// has the actual diagnostic message.
- pub slug: Option<(Path, proc_macro::Span)>,
+ pub slug: SpannedOption<Path>,
/// Error codes are a optional part of the struct attribute - this is only set to detect
/// multiple specifications.
- pub code: Option<(String, proc_macro::Span)>,
+ pub code: SpannedOption<()>,
}
-impl HasFieldMap for DiagnosticDeriveBuilder {
+impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> {
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
- self.fields.get(field)
+ self.field_map.get(field)
}
}
impl DiagnosticDeriveBuilder {
- pub fn preamble<'s>(&mut self, structure: &Structure<'s>) -> TokenStream {
+ /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the
+ /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions
+ /// or attributes on the type itself when input is an enum.
+ pub fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream
+ where
+ F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream,
+ {
let ast = structure.ast();
+ let span = ast.span().unwrap();
+ match ast.data {
+ syn::Data::Struct(..) | syn::Data::Enum(..) => (),
+ syn::Data::Union(..) => {
+ span_err(span, "diagnostic derives can only be used on structs and enums");
+ }
+ }
+
+ if matches!(ast.data, syn::Data::Enum(..)) {
+ for attr in &ast.attrs {
+ span_err(
+ attr.span().unwrap(),
+ "unsupported type attribute for diagnostic derive enum",
+ )
+ .emit();
+ }
+ }
+
+ structure.bind_with(|_| synstructure::BindStyle::Move);
+ let variants = structure.each_variant(|variant| {
+ let span = match structure.ast().data {
+ syn::Data::Struct(..) => span,
+ // There isn't a good way to get the span of the variant, so the variant's
+ // name will need to do.
+ _ => variant.ast().ident.span().unwrap(),
+ };
+ let builder = DiagnosticDeriveVariantBuilder {
+ parent: &self,
+ span,
+ field_map: build_field_mapping(variant),
+ formatting_init: TokenStream::new(),
+ slug: None,
+ code: None,
+ };
+ f(builder, variant)
+ });
+
+ quote! {
+ match self {
+ #variants
+ }
+ }
+ }
+}
+
+impl<'a> DiagnosticDeriveVariantBuilder<'a> {
+ /// Generates calls to `code` and similar functions based on the attributes on the type or
+ /// variant.
+ pub fn preamble<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
+ let ast = variant.ast();
let attrs = &ast.attrs;
let preamble = attrs.iter().map(|attr| {
self.generate_structure_code_for_attr(attr).unwrap_or_else(|v| v.to_compile_error())
@@ -65,66 +133,48 @@ impl DiagnosticDeriveBuilder {
}
}
- pub fn body<'s>(&mut self, structure: &mut Structure<'s>) -> (TokenStream, TokenStream) {
- // Keep track of which fields need to be handled with a by-move binding.
- let mut needs_moved = std::collections::HashSet::new();
-
- // Generates calls to `span_label` and similar functions based on the attributes
- // on fields. Code for suggestions uses formatting machinery and the value of
- // other fields - because any given field can be referenced multiple times, it
- // should be accessed through a borrow. When passing fields to `add_subdiagnostic`
- // or `set_arg` (which happens below) for Fluent, we want to move the data, so that
- // has to happen in a separate pass over the fields.
- let attrs = structure
- .clone()
- .filter(|field_binding| {
- let ast = &field_binding.ast();
- !self.needs_move(ast) || {
- needs_moved.insert(field_binding.binding.clone());
- false
- }
- })
- .each(|field_binding| self.generate_field_attrs_code(field_binding));
-
- structure.bind_with(|_| synstructure::BindStyle::Move);
- // When a field has attributes like `#[label]` or `#[note]` then it doesn't
- // need to be passed as an argument to the diagnostic. But when a field has no
- // attributes or a `#[subdiagnostic]` attribute then it must be passed as an
- // argument to the diagnostic so that it can be referred to by Fluent messages.
- let args = structure
- .filter(|field_binding| needs_moved.contains(&field_binding.binding))
- .each(|field_binding| self.generate_field_attrs_code(field_binding));
-
- (attrs, args)
+ /// Generates calls to `span_label` and similar functions based on the attributes on fields or
+ /// calls to `set_arg` when no attributes are present.
+ pub fn body<'s>(&mut self, variant: &VariantInfo<'s>) -> TokenStream {
+ let mut body = quote! {};
+ // Generate `set_arg` calls first..
+ for binding in variant.bindings().iter().filter(|bi| should_generate_set_arg(bi.ast())) {
+ body.extend(self.generate_field_code(binding));
+ }
+ // ..and then subdiagnostic additions.
+ for binding in variant.bindings().iter().filter(|bi| !should_generate_set_arg(bi.ast())) {
+ body.extend(self.generate_field_attrs_code(binding));
+ }
+ body
}
- /// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
- /// call (like `span_label`).
- fn should_generate_set_arg(&self, field: &Field) -> bool {
- field.attrs.is_empty()
- }
+ /// Parse a `SubdiagnosticKind` from an `Attribute`.
+ fn parse_subdiag_attribute(
+ &self,
+ attr: &Attribute,
+ ) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
+ let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
+ // Some attributes aren't errors - like documentation comments - but also aren't
+ // subdiagnostics.
+ return Ok(None);
+ };
- /// Returns `true` if `field` needs to have code generated in the by-move branch of the
- /// generated derive rather than the by-ref branch.
- fn needs_move(&self, field: &Field) -> bool {
- let generates_set_arg = self.should_generate_set_arg(field);
- let is_multispan = type_matches_path(&field.ty, &["rustc_errors", "MultiSpan"]);
- // FIXME(davidtwco): better support for one field needing to be in the by-move and
- // by-ref branches.
- let is_subdiagnostic = field
- .attrs
- .iter()
- .map(|attr| attr.path.segments.last().unwrap().ident.to_string())
- .any(|attr| attr == "subdiagnostic");
-
- // `set_arg` calls take their argument by-move..
- generates_set_arg
- // If this is a `MultiSpan` field then it needs to be moved to be used by any
- // attribute..
- || is_multispan
- // If this a `#[subdiagnostic]` then it needs to be moved as the other diagnostic is
- // unlikely to be `Copy`..
- || is_subdiagnostic
+ if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
+ let meta = attr.parse_meta()?;
+ throw_invalid_attr!(attr, &meta, |diag| diag
+ .help("consider creating a `Subdiagnostic` instead"));
+ }
+
+ let slug = slug.unwrap_or_else(|| match subdiag {
+ SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
+ SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
+ SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
+ SubdiagnosticKind::Warn => parse_quote! { _subdiag::warn },
+ SubdiagnosticKind::Suggestion { .. } => parse_quote! { _subdiag::suggestion },
+ SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
+ });
+
+ Ok(Some((subdiag, slug)))
}
/// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
@@ -134,99 +184,70 @@ impl DiagnosticDeriveBuilder {
&mut self,
attr: &Attribute,
) -> Result<TokenStream, DiagnosticDeriveError> {
- let diag = &self.diag;
- let span = attr.span().unwrap();
+ let diag = &self.parent.diag;
+
+ // Always allow documentation comments.
+ if is_doc_comment(attr) {
+ return Ok(quote! {});
+ }
let name = attr.path.segments.last().unwrap().ident.to_string();
let name = name.as_str();
let meta = attr.parse_meta()?;
- let is_diag = name == "diag";
-
- let nested = match meta {
- // Most attributes are lists, like `#[diag(..)]` for most cases or
- // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug.
- Meta::List(MetaList { ref nested, .. }) => nested,
- // Subdiagnostics without spans can be applied to the type too, and these are just
- // paths: `#[help]`, `#[note]` and `#[warning]`
- Meta::Path(_) if !is_diag => {
- let fn_name = if name == "warning" {
- Ident::new("warn", attr.span())
- } else {
- Ident::new(name, attr.span())
- };
- return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::_subdiag::#fn_name); });
- }
- _ => throw_invalid_attr!(attr, &meta),
- };
-
- // Check the kind before doing any further processing so that there aren't misleading
- // "no kind specified" errors if there are failures later.
- match name {
- "error" | "lint" => throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("`error` and `lint` have been replaced by `diag`")
- }),
- "warn_" => throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("`warn_` have been replaced by `warning`")
- }),
- "diag" | "help" | "note" | "warning" => (),
- _ => throw_invalid_attr!(attr, &meta, |diag| {
- diag.help("only `diag`, `help`, `note` and `warning` are valid attributes")
- }),
- }
+ if name == "diag" {
+ let Meta::List(MetaList { ref nested, .. }) = meta else {
+ throw_invalid_attr!(
+ attr,
+ &meta
+ );
+ };
- // First nested element should always be the path, e.g. `#[diag(typeck::invalid)]` or
- // `#[help(typeck::another_help)]`.
- let mut nested_iter = nested.into_iter();
- if let Some(nested_attr) = nested_iter.next() {
- // Report an error if there are any other list items after the path.
- if !is_diag && nested_iter.next().is_some() {
- throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help(
- "`help`, `note` and `warning` struct attributes can only have one argument",
- )
- });
- }
+ let mut nested_iter = nested.into_iter().peekable();
- match nested_attr {
- NestedMeta::Meta(Meta::Path(path)) => {
- if is_diag {
- self.slug.set_once((path.clone(), span));
- } else {
- let fn_name = proc_macro2::Ident::new(name, attr.span());
- return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); });
- }
- }
- NestedMeta::Meta(meta @ Meta::NameValue(_))
- if is_diag && meta.path().segments.last().unwrap().ident == "code" =>
- {
- // don't error for valid follow-up attributes
+ match nested_iter.peek() {
+ Some(NestedMeta::Meta(Meta::Path(slug))) => {
+ self.slug.set_once(slug.clone(), slug.span().unwrap());
+ nested_iter.next();
}
- nested_attr => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help("first argument of the attribute should be the diagnostic slug")
- }),
+ Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
+ Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| diag
+ .help("a diagnostic slug is required as the first argument")),
+ None => throw_invalid_attr!(attr, &meta, |diag| diag
+ .help("a diagnostic slug is required as the first argument")),
};
- }
- // Remaining attributes are optional, only `code = ".."` at the moment.
- let mut tokens = Vec::new();
- for nested_attr in nested_iter {
- let meta = match nested_attr {
- syn::NestedMeta::Meta(meta) => meta,
- _ => throw_invalid_nested_attr!(attr, &nested_attr),
- };
+ // Remaining attributes are optional, only `code = ".."` at the moment.
+ let mut tokens = TokenStream::new();
+ for nested_attr in nested_iter {
+ let (value, path) = match nested_attr {
+ NestedMeta::Meta(Meta::NameValue(MetaNameValue {
+ lit: syn::Lit::Str(value),
+ path,
+ ..
+ })) => (value, path),
+ NestedMeta::Meta(Meta::Path(_)) => {
+ invalid_nested_attr(attr, &nested_attr)
+ .help("diagnostic slug must be the first argument")
+ .emit();
+ continue;
+ }
+ _ => {
+ invalid_nested_attr(attr, &nested_attr).emit();
+ continue;
+ }
+ };
- let path = meta.path();
- let nested_name = path.segments.last().unwrap().ident.to_string();
- // Struct attributes are only allowed to be applied once, and the diagnostic
- // changes will be set in the initialisation code.
- if let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) = &meta {
- let span = s.span().unwrap();
+ let nested_name = path.segments.last().unwrap().ident.to_string();
+ // Struct attributes are only allowed to be applied once, and the diagnostic
+ // changes will be set in the initialisation code.
+ let span = value.span().unwrap();
match nested_name.as_str() {
"code" => {
- self.code.set_once((s.value(), span));
- let code = &self.code.as_ref().map(|(v, _)| v);
- tokens.push(quote! {
+ self.code.set_once((), span);
+
+ let code = value.value();
+ tokens.extend(quote! {
#diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
});
}
@@ -234,46 +255,68 @@ impl DiagnosticDeriveBuilder {
.help("only `code` is a valid nested attributes following the slug")
.emit(),
}
- } else {
- invalid_nested_attr(attr, &nested_attr).emit()
}
+ return Ok(tokens);
}
- Ok(tokens.into_iter().collect())
+ let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
+ // Some attributes aren't errors - like documentation comments - but also aren't
+ // subdiagnostics.
+ return Ok(quote! {});
+ };
+ let fn_ident = format_ident!("{}", subdiag);
+ match subdiag {
+ SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
+ Ok(self.add_subdiagnostic(&fn_ident, slug))
+ }
+ SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
+ throw_invalid_attr!(attr, &meta, |diag| diag
+ .help("`#[label]` and `#[suggestion]` can only be applied to fields"));
+ }
+ SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
+ }
}
- fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
+ fn generate_field_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
+ let diag = &self.parent.diag;
+
let field = binding_info.ast();
let field_binding = &binding_info.binding;
- if self.should_generate_set_arg(&field) {
- let diag = &self.diag;
- let ident = field.ident.as_ref().unwrap();
- return quote! {
- #diag.set_arg(
- stringify!(#ident),
- #field_binding
- );
- };
+ let ident = field.ident.as_ref().unwrap();
+ let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
+
+ quote! {
+ #diag.set_arg(
+ stringify!(#ident),
+ #field_binding
+ );
}
+ }
+
+ fn generate_field_attrs_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
+ let field = binding_info.ast();
+ let field_binding = &binding_info.binding;
- let needs_move = self.needs_move(&field);
let inner_ty = FieldInnerTy::from_type(&field.ty);
field
.attrs
.iter()
.map(move |attr| {
+ // Always allow documentation comments.
+ if is_doc_comment(attr) {
+ return quote! {};
+ }
+
let name = attr.path.segments.last().unwrap().ident.to_string();
let needs_clone =
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
let (binding, needs_destructure) = if needs_clone {
// `primary_span` can accept a `Vec<Span>` so don't destructure that.
(quote! { #field_binding.clone() }, false)
- } else if needs_move {
- (quote! { #field_binding }, true)
} else {
- (quote! { *#field_binding }, true)
+ (quote! { #field_binding }, true)
};
let generated_code = self
@@ -303,42 +346,23 @@ impl DiagnosticDeriveBuilder {
info: FieldInfo<'_>,
binding: TokenStream,
) -> Result<TokenStream, DiagnosticDeriveError> {
- let meta = attr.parse_meta()?;
- match meta {
- Meta::Path(_) => self.generate_inner_field_code_path(attr, info, binding),
- Meta::List(MetaList { .. }) => self.generate_inner_field_code_list(attr, info, binding),
- _ => throw_invalid_attr!(attr, &meta),
- }
- }
-
- fn generate_inner_field_code_path(
- &mut self,
- attr: &Attribute,
- info: FieldInfo<'_>,
- binding: TokenStream,
- ) -> Result<TokenStream, DiagnosticDeriveError> {
- assert!(matches!(attr.parse_meta()?, Meta::Path(_)));
- let diag = &self.diag;
-
+ let diag = &self.parent.diag;
let meta = attr.parse_meta()?;
let ident = &attr.path.segments.last().unwrap().ident;
let name = ident.to_string();
- let name = name.as_str();
- match name {
- "skip_arg" => {
- // Don't need to do anything - by virtue of the attribute existing, the
- // `set_arg` call will not be generated.
- Ok(quote! {})
- }
- "primary_span" => {
- match self.kind {
- DiagnosticDeriveKind::SessionDiagnostic => {
+ match (&meta, name.as_str()) {
+ // Don't need to do anything - by virtue of the attribute existing, the
+ // `set_arg` call will not be generated.
+ (Meta::Path(_), "skip_arg") => return Ok(quote! {}),
+ (Meta::Path(_), "primary_span") => {
+ match self.parent.kind {
+ DiagnosticDeriveKind::Diagnostic { .. } => {
report_error_if_not_applied_to_span(attr, &info)?;
- Ok(quote! {
+ return Ok(quote! {
#diag.set_span(#binding);
- })
+ });
}
DiagnosticDeriveKind::LintDiagnostic => {
throw_invalid_attr!(attr, &meta, |diag| {
@@ -347,188 +371,100 @@ impl DiagnosticDeriveBuilder {
}
}
}
- "label" => {
- report_error_if_not_applied_to_span(attr, &info)?;
- Ok(self.add_spanned_subdiagnostic(binding, ident, parse_quote! { _subdiag::label }))
+ (Meta::Path(_), "subdiagnostic") => {
+ return Ok(quote! { #diag.subdiagnostic(#binding); });
}
- "note" | "help" | "warning" => {
- let warn_ident = Ident::new("warn", Span::call_site());
- let (ident, path) = match name {
- "note" => (ident, parse_quote! { _subdiag::note }),
- "help" => (ident, parse_quote! { _subdiag::help }),
- "warning" => (&warn_ident, parse_quote! { _subdiag::warn }),
- _ => unreachable!(),
- };
- if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
- Ok(self.add_spanned_subdiagnostic(binding, ident, path))
- } else if type_is_unit(&info.ty) {
- Ok(self.add_subdiagnostic(ident, path))
- } else {
- report_type_error(attr, "`Span` or `()`")?
- }
+ (Meta::NameValue(_), "subdiagnostic") => {
+ throw_invalid_attr!(attr, &meta, |diag| {
+ diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+ })
}
- "subdiagnostic" => Ok(quote! { #diag.subdiagnostic(#binding); }),
- _ => throw_invalid_attr!(attr, &meta, |diag| {
- diag.help(
- "only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` \
- are valid field attributes",
- )
- }),
- }
- }
+ (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
+ if nested.len() != 1 {
+ throw_invalid_attr!(attr, &meta, |diag| {
+ diag.help(
+ "`eager` is the only supported nested attribute for `subdiagnostic`",
+ )
+ })
+ }
- fn generate_inner_field_code_list(
- &mut self,
- attr: &Attribute,
- info: FieldInfo<'_>,
- binding: TokenStream,
- ) -> Result<TokenStream, DiagnosticDeriveError> {
- let meta = attr.parse_meta()?;
- let Meta::List(MetaList { ref path, ref nested, .. }) = meta else { unreachable!() };
+ let handler = match &self.parent.kind {
+ DiagnosticDeriveKind::Diagnostic { handler } => handler,
+ DiagnosticDeriveKind::LintDiagnostic => {
+ throw_invalid_attr!(attr, &meta, |diag| {
+ diag.help("eager subdiagnostics are not supported on lints")
+ })
+ }
+ };
- let ident = &attr.path.segments.last().unwrap().ident;
- let name = path.segments.last().unwrap().ident.to_string();
- let name = name.as_ref();
- match name {
- "suggestion" | "suggestion_short" | "suggestion_hidden" | "suggestion_verbose" => {
- return self.generate_inner_field_code_suggestion(attr, info);
+ let nested_attr = nested.first().expect("pop failed for single element list");
+ match nested_attr {
+ NestedMeta::Meta(meta @ Meta::Path(_))
+ if meta.path().segments.last().unwrap().ident.to_string().as_str()
+ == "eager" =>
+ {
+ return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
+ }
+ _ => {
+ throw_invalid_nested_attr!(attr, nested_attr, |diag| {
+ diag.help("`eager` is the only supported nested attribute for `subdiagnostic`")
+ })
+ }
+ }
}
- "label" | "help" | "note" | "warning" => (),
- _ => throw_invalid_attr!(attr, &meta, |diag| {
- diag.help(
- "only `label`, `help`, `note`, `warn` or `suggestion{,_short,_hidden,_verbose}` are \
- valid field attributes",
- )
- }),
+ _ => (),
}
- // For `#[label(..)]`, `#[note(..)]` and `#[help(..)]`, the first nested element must be a
- // path, e.g. `#[label(typeck::label)]`.
- let mut nested_iter = nested.into_iter();
- let msg = match nested_iter.next() {
- Some(NestedMeta::Meta(Meta::Path(path))) => path.clone(),
- Some(nested_attr) => throw_invalid_nested_attr!(attr, &nested_attr),
- None => throw_invalid_attr!(attr, &meta),
+ let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
+ // Some attributes aren't errors - like documentation comments - but also aren't
+ // subdiagnostics.
+ return Ok(quote! {});
};
-
- // None of these attributes should have anything following the slug.
- if nested_iter.next().is_some() {
- throw_invalid_attr!(attr, &meta);
- }
-
- match name {
- "label" => {
+ let fn_ident = format_ident!("{}", subdiag);
+ match subdiag {
+ SubdiagnosticKind::Label => {
report_error_if_not_applied_to_span(attr, &info)?;
- Ok(self.add_spanned_subdiagnostic(binding, ident, msg))
+ Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
}
- "note" | "help" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => {
- Ok(self.add_spanned_subdiagnostic(binding, ident, msg))
- }
- "note" | "help" if type_is_unit(&info.ty) => Ok(self.add_subdiagnostic(ident, msg)),
- // `warning` must be special-cased because the attribute `warn` already has meaning and
- // so isn't used, despite the diagnostic API being named `warn`.
- "warning" if type_matches_path(&info.ty, &["rustc_span", "Span"]) => Ok(self
- .add_spanned_subdiagnostic(binding, &Ident::new("warn", Span::call_site()), msg)),
- "warning" if type_is_unit(&info.ty) => {
- Ok(self.add_subdiagnostic(&Ident::new("warn", Span::call_site()), msg))
- }
- "note" | "help" | "warning" => report_type_error(attr, "`Span` or `()`")?,
- _ => unreachable!(),
- }
- }
-
- fn generate_inner_field_code_suggestion(
- &mut self,
- attr: &Attribute,
- info: FieldInfo<'_>,
- ) -> Result<TokenStream, DiagnosticDeriveError> {
- let diag = &self.diag;
-
- let mut meta = attr.parse_meta()?;
- let Meta::List(MetaList { ref path, ref mut nested, .. }) = meta else { unreachable!() };
-
- let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
-
- let mut msg = None;
- let mut code = None;
-
- let mut nested_iter = nested.into_iter().peekable();
- if let Some(nested_attr) = nested_iter.peek() {
- if let NestedMeta::Meta(Meta::Path(path)) = nested_attr {
- msg = Some(path.clone());
+ SubdiagnosticKind::Note | SubdiagnosticKind::Help | SubdiagnosticKind::Warn => {
+ if type_matches_path(&info.ty, &["rustc_span", "Span"]) {
+ Ok(self.add_spanned_subdiagnostic(binding, &fn_ident, slug))
+ } else if type_is_unit(&info.ty) {
+ Ok(self.add_subdiagnostic(&fn_ident, slug))
+ } else {
+ report_type_error(attr, "`Span` or `()`")?
+ }
}
- };
- // Move the iterator forward if a path was found (don't otherwise so that
- // code/applicability can be found or an error emitted).
- if msg.is_some() {
- let _ = nested_iter.next();
- }
-
- for nested_attr in nested_iter {
- let meta = match nested_attr {
- syn::NestedMeta::Meta(ref meta) => meta,
- syn::NestedMeta::Lit(_) => throw_invalid_nested_attr!(attr, &nested_attr),
- };
-
- let nested_name = meta.path().segments.last().unwrap().ident.to_string();
- let nested_name = nested_name.as_str();
- match meta {
- Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => {
- let span = meta.span().unwrap();
- match nested_name {
- "code" => {
- let formatted_str = self.build_format(&s.value(), s.span());
- code = Some(formatted_str);
- }
- "applicability" => {
- applicability = match applicability {
- Some(v) => {
- span_err(
- span,
- "applicability cannot be set in both the field and \
- attribute",
- )
- .emit();
- Some(v)
- }
- None => match Applicability::from_str(&s.value()) {
- Ok(v) => Some(quote! { #v }),
- Err(()) => {
- span_err(span, "invalid applicability").emit();
- None
- }
- },
- }
- }
- _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help(
- "only `message`, `code` and `applicability` are valid field \
- attributes",
- )
- }),
- }
+ SubdiagnosticKind::Suggestion {
+ suggestion_kind,
+ applicability: static_applicability,
+ code_field,
+ code_init,
+ } => {
+ let (span_field, mut applicability) = self.span_and_applicability_of_ty(info)?;
+
+ if let Some((static_applicability, span)) = static_applicability {
+ applicability.set_once(quote! { #static_applicability }, span);
}
- _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- if matches!(meta, Meta::Path(_)) {
- diag.help("a diagnostic slug must be the first argument to the attribute")
- } else {
- diag
- }
- }),
+
+ let applicability = applicability
+ .value()
+ .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
+ let style = suggestion_kind.to_suggestion_style();
+
+ self.formatting_init.extend(code_init);
+ Ok(quote! {
+ #diag.span_suggestions_with_style(
+ #span_field,
+ rustc_errors::fluent::#slug,
+ #code_field,
+ #applicability,
+ #style
+ );
+ })
}
+ SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
}
-
- let applicability =
- applicability.unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified));
-
- let name = path.segments.last().unwrap().ident.to_string();
- let method = format_ident!("span_{}", name);
-
- let msg = msg.unwrap_or_else(|| parse_quote! { _subdiag::suggestion });
- let msg = quote! { rustc_errors::fluent::#msg };
- let code = code.unwrap_or_else(|| quote! { String::new() });
-
- Ok(quote! { #diag.#method(#span_field, #msg, #code, #applicability); })
}
/// Adds a spanned subdiagnostic by generating a `diag.span_$kind` call with the current slug
@@ -539,7 +475,7 @@ impl DiagnosticDeriveBuilder {
kind: &Ident,
fluent_attr_identifier: Path,
) -> TokenStream {
- let diag = &self.diag;
+ let diag = &self.parent.diag;
let fn_name = format_ident!("span_{}", kind);
quote! {
#diag.#fn_name(
@@ -552,7 +488,7 @@ impl DiagnosticDeriveBuilder {
/// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug
/// and `fluent_attr_identifier`.
fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream {
- let diag = &self.diag;
+ let diag = &self.parent.diag;
quote! {
#diag.#kind(rustc_errors::fluent::#fluent_attr_identifier);
}
@@ -561,58 +497,49 @@ impl DiagnosticDeriveBuilder {
fn span_and_applicability_of_ty(
&self,
info: FieldInfo<'_>,
- ) -> Result<(TokenStream, Option<TokenStream>), DiagnosticDeriveError> {
+ ) -> Result<(TokenStream, SpannedOption<TokenStream>), DiagnosticDeriveError> {
match &info.ty {
// 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;
- Ok((quote!(*#binding), None))
+ Ok((quote!(#binding), None))
}
// If `ty` is `(Span, Applicability)` then return tokens accessing those.
Type::Tuple(tup) => {
let mut span_idx = None;
let mut applicability_idx = None;
+ fn type_err(span: &Span) -> Result<!, DiagnosticDeriveError> {
+ span_err(span.unwrap(), "wrong types for suggestion")
+ .help(
+ "`#[suggestion(...)]` on a tuple field must be applied to fields \
+ of type `(Span, Applicability)`",
+ )
+ .emit();
+ Err(DiagnosticDeriveError::ErrorHandled)
+ }
+
for (idx, elem) in tup.elems.iter().enumerate() {
if type_matches_path(elem, &["rustc_span", "Span"]) {
- if span_idx.is_none() {
- span_idx = Some(syn::Index::from(idx));
- } else {
- throw_span_err!(
- info.span.unwrap(),
- "type of field annotated with `#[suggestion(...)]` contains more \
- than one `Span`"
- );
- }
+ span_idx.set_once(syn::Index::from(idx), elem.span().unwrap());
} else if type_matches_path(elem, &["rustc_errors", "Applicability"]) {
- if applicability_idx.is_none() {
- applicability_idx = Some(syn::Index::from(idx));
- } else {
- throw_span_err!(
- info.span.unwrap(),
- "type of field annotated with `#[suggestion(...)]` contains more \
- than one Applicability"
- );
- }
+ applicability_idx.set_once(syn::Index::from(idx), elem.span().unwrap());
+ } else {
+ type_err(&elem.span())?;
}
}
- if let Some(span_idx) = span_idx {
- let binding = &info.binding.binding;
- let span = quote!(#binding.#span_idx);
- let applicability = applicability_idx
- .map(|applicability_idx| quote!(#binding.#applicability_idx))
- .unwrap_or_else(|| quote!(rustc_errors::Applicability::Unspecified));
-
- return Ok((span, Some(applicability)));
- }
+ let Some((span_idx, _)) = span_idx else {
+ type_err(&tup.span())?;
+ };
+ let Some((applicability_idx, applicability_span)) = applicability_idx else {
+ type_err(&tup.span())?;
+ };
+ let binding = &info.binding.binding;
+ let span = quote!(#binding.#span_idx);
+ let applicability = quote!(#binding.#applicability_idx);
- throw_span_err!(info.span.unwrap(), "wrong types for suggestion", |diag| {
- diag.help(
- "`#[suggestion(...)]` on a tuple field must be applied to fields of type \
- `(Span, Applicability)`",
- )
- });
+ Ok((span, Some((applicability, applicability_span))))
}
// If `ty` isn't a `Span` or `(Span, Applicability)` then emit an error.
_ => throw_span_err!(info.span.unwrap(), "wrong field type for suggestion", |diag| {
diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs
index f7d8b494e..3e447c94e 100644
--- a/compiler/rustc_macros/src/diagnostics/fluent.rs
+++ b/compiler/rustc_macros/src/diagnostics/fluent.rs
@@ -25,18 +25,18 @@ use syn::{
use unic_langid::langid;
struct Resource {
- ident: Ident,
+ krate: Ident,
#[allow(dead_code)]
fat_arrow_token: token::FatArrow,
- resource: LitStr,
+ resource_path: LitStr,
}
impl Parse for Resource {
fn parse(input: ParseStream<'_>) -> Result<Self> {
Ok(Resource {
- ident: input.parse()?,
+ krate: input.parse()?,
fat_arrow_token: input.parse()?,
- resource: input.parse()?,
+ resource_path: input.parse()?,
})
}
}
@@ -94,19 +94,20 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
// 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();
- for res in resources.0 {
- let ident_span = res.ident.span().unwrap();
- let path_span = res.resource.span().unwrap();
- // 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();
+ for res in resources.0 {
+ let krate_span = res.krate.span().unwrap();
+ let path_span = res.resource_path.span().unwrap();
- let relative_ftl_path = res.resource.value();
+ let relative_ftl_path = res.resource_path.value();
let absolute_ftl_path =
- invocation_relative_path_to_absolute(ident_span, &relative_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) {
@@ -185,7 +186,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
let mut constants = TokenStream::new();
for entry in resource.entries() {
- let span = res.ident.span();
+ 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);
@@ -199,29 +200,30 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
.emit();
}
- // `typeck_foo_bar` => `foo_bar` (in `typeck.ftl`)
- // `const_eval_baz` => `baz` (in `const_eval.ftl`)
+ // 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.ident);
+ let crate_prefix = format!("{}_", res.krate);
let snake_name = name.replace('-', "_");
- let snake_name = match snake_name.strip_prefix(&crate_prefix) {
- Some(rest) => Ident::new(rest, span),
- None => {
- Diagnostic::spanned(
- path_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();
- Ident::new(&snake_name, span)
- }
+ if !snake_name.starts_with(&crate_prefix) {
+ Diagnostic::spanned(
+ path_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, span);
+
constants.extend(quote! {
pub const #snake_name: crate::DiagnosticMessage =
crate::DiagnosticMessage::FluentIdentifier(
@@ -275,12 +277,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok
includes.extend(quote! { include_str!(#relative_ftl_path), });
- let ident = res.ident;
- generated.extend(quote! {
- pub mod #ident {
- #constants
- }
- });
+ generated.extend(constants);
}
quote! {
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 2ff21e18f..860340b43 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -5,14 +5,14 @@ mod fluent;
mod subdiagnostic;
mod utils;
-use diagnostic::{LintDiagnosticDerive, SessionDiagnosticDerive};
+use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
pub(crate) use fluent::fluent_messages;
use proc_macro2::TokenStream;
use quote::format_ident;
-use subdiagnostic::SessionSubdiagnosticDerive;
+use subdiagnostic::SubdiagnosticDeriveBuilder;
use synstructure::Structure;
-/// Implements `#[derive(SessionDiagnostic)]`, which allows for errors to be specified as a struct,
+/// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
/// independent from the actual diagnostics emitting code.
///
/// ```ignore (rust)
@@ -22,15 +22,15 @@ use synstructure::Structure;
/// # use rustc_span::{symbol::Ident, Span};
/// # extern crate rust_middle;
/// # use rustc_middle::ty::Ty;
-/// #[derive(SessionDiagnostic)]
-/// #[diag(borrowck::move_out_of_borrow, code = "E0505")]
+/// #[derive(Diagnostic)]
+/// #[diag(borrowck_move_out_of_borrow, code = "E0505")]
/// pub struct MoveOutOfBorrowError<'tcx> {
/// pub name: Ident,
/// pub ty: Ty<'tcx>,
/// #[primary_span]
/// #[label]
/// pub span: Span,
-/// #[label(borrowck::first_borrow_label)]
+/// #[label(first_borrow_label)]
/// pub first_borrow_span: Span,
/// #[suggestion(code = "{name}.clone()")]
/// pub clone_sugg: Option<(Span, Applicability)>
@@ -56,10 +56,10 @@ use synstructure::Structure;
/// });
/// ```
///
-/// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`:
+/// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
- SessionDiagnosticDerive::new(format_ident!("diag"), format_ident!("sess"), s).into_tokens()
+ DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens()
}
/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
@@ -67,14 +67,14 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
///
/// ```ignore (rust)
/// #[derive(LintDiagnostic)]
-/// #[diag(lint::atomic_ordering_invalid_fail_success)]
+/// #[diag(lint_atomic_ordering_invalid_fail_success)]
/// pub struct AtomicOrderingInvalidLint {
/// method: Symbol,
/// success_ordering: Symbol,
/// fail_ordering: Symbol,
-/// #[label(lint::fail_label)]
+/// #[label(fail_label)]
/// fail_order_arg_span: Span,
-/// #[label(lint::success_label)]
+/// #[label(success_label)]
/// #[suggestion(
/// code = "std::sync::atomic::Ordering::{success_suggestion}",
/// applicability = "maybe-incorrect"
@@ -103,24 +103,24 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
/// ```
///
/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
-/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html>
+/// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html#reference>
pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens()
}
-/// Implements `#[derive(SessionSubdiagnostic)]`, which allows for labels, notes, helps and
+/// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and
/// suggestions to be specified as a structs or enums, independent from the actual diagnostics
/// emitting code or diagnostic derives.
///
/// ```ignore (rust)
-/// #[derive(SessionSubdiagnostic)]
+/// #[derive(Subdiagnostic)]
/// pub enum ExpectedIdentifierLabel<'tcx> {
-/// #[label(parser::expected_identifier)]
+/// #[label(expected_identifier)]
/// WithoutFound {
/// #[primary_span]
/// span: Span,
/// }
-/// #[label(parser::expected_identifier_found)]
+/// #[label(expected_identifier_found)]
/// WithFound {
/// #[primary_span]
/// span: Span,
@@ -128,7 +128,7 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
/// }
/// }
///
-/// #[derive(SessionSubdiagnostic)]
+/// #[derive(Subdiagnostic)]
/// #[suggestion_verbose(parser::raw_identifier)]
/// pub struct RawIdentifierSuggestion<'tcx> {
/// #[primary_span]
@@ -155,5 +155,5 @@ pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
/// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
/// ```
pub fn session_subdiagnostic_derive(s: Structure<'_>) -> TokenStream {
- SessionSubdiagnosticDerive::new(s).into_tokens()
+ SubdiagnosticDeriveBuilder::new().into_tokens(s)
}
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index dce5d3cfb..fa0ca5a52 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -1,116 +1,35 @@
#![deny(unused_must_use)]
use crate::diagnostics::error::{
- span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
+ invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
+ DiagnosticDeriveError,
};
use crate::diagnostics::utils::{
- report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span,
- Applicability, FieldInfo, FieldInnerTy, HasFieldMap, SetOnce,
+ build_field_mapping, is_doc_comment, new_code_ident,
+ report_error_if_not_applied_to_applicability, report_error_if_not_applied_to_span, FieldInfo,
+ FieldInnerTy, FieldMap, HasFieldMap, SetOnce, SpannedOption, SubdiagnosticKind,
};
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
-use std::collections::HashMap;
-use std::fmt;
-use std::str::FromStr;
-use syn::{spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path};
+use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path};
use synstructure::{BindingInfo, Structure, VariantInfo};
-/// Which kind of suggestion is being created?
-#[derive(Clone, Copy)]
-enum SubdiagnosticSuggestionKind {
- /// `#[suggestion]`
- Normal,
- /// `#[suggestion_short]`
- Short,
- /// `#[suggestion_hidden]`
- Hidden,
- /// `#[suggestion_verbose]`
- Verbose,
-}
-
-impl FromStr for SubdiagnosticSuggestionKind {
- type Err = ();
-
- fn from_str(s: &str) -> Result<Self, Self::Err> {
- match s {
- "" => Ok(SubdiagnosticSuggestionKind::Normal),
- "_short" => Ok(SubdiagnosticSuggestionKind::Short),
- "_hidden" => Ok(SubdiagnosticSuggestionKind::Hidden),
- "_verbose" => Ok(SubdiagnosticSuggestionKind::Verbose),
- _ => Err(()),
- }
- }
-}
-
-impl SubdiagnosticSuggestionKind {
- pub fn to_suggestion_style(&self) -> TokenStream {
- match self {
- SubdiagnosticSuggestionKind::Normal => {
- quote! { rustc_errors::SuggestionStyle::ShowCode }
- }
- SubdiagnosticSuggestionKind::Short => {
- quote! { rustc_errors::SuggestionStyle::HideCodeInline }
- }
- SubdiagnosticSuggestionKind::Hidden => {
- quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
- }
- SubdiagnosticSuggestionKind::Verbose => {
- quote! { rustc_errors::SuggestionStyle::ShowAlways }
- }
- }
- }
-}
-
-/// Which kind of subdiagnostic is being created from a variant?
-#[derive(Clone)]
-enum SubdiagnosticKind {
- /// `#[label(...)]`
- Label,
- /// `#[note(...)]`
- Note,
- /// `#[help(...)]`
- Help,
- /// `#[warning(...)]`
- Warn,
- /// `#[suggestion{,_short,_hidden,_verbose}]`
- Suggestion { suggestion_kind: SubdiagnosticSuggestionKind, code: TokenStream },
- /// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
- MultipartSuggestion { suggestion_kind: SubdiagnosticSuggestionKind },
-}
-
-impl quote::IdentFragment for SubdiagnosticKind {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- SubdiagnosticKind::Label => write!(f, "label"),
- SubdiagnosticKind::Note => write!(f, "note"),
- SubdiagnosticKind::Help => write!(f, "help"),
- SubdiagnosticKind::Warn => write!(f, "warn"),
- SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestion_with_style"),
- SubdiagnosticKind::MultipartSuggestion { .. } => {
- write!(f, "multipart_suggestion_with_style")
- }
- }
- }
-
- fn span(&self) -> Option<proc_macro2::Span> {
- None
- }
-}
+use super::utils::{build_suggestion_code, AllowMultipleAlternatives};
/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
-pub(crate) struct SessionSubdiagnosticDerive<'a> {
- structure: Structure<'a>,
+pub(crate) struct SubdiagnosticDeriveBuilder {
diag: syn::Ident,
+ f: syn::Ident,
}
-impl<'a> SessionSubdiagnosticDerive<'a> {
- pub(crate) fn new(structure: Structure<'a>) -> Self {
+impl SubdiagnosticDeriveBuilder {
+ pub(crate) fn new() -> Self {
let diag = format_ident!("diag");
- Self { structure, diag }
+ let f = format_ident!("f");
+ Self { diag, f }
}
- pub(crate) fn into_tokens(self) -> TokenStream {
- let SessionSubdiagnosticDerive { mut structure, diag } = self;
+ pub(crate) fn into_tokens<'a>(self, mut structure: Structure<'a>) -> TokenStream {
let implementation = {
let ast = structure.ast();
let span = ast.span().unwrap();
@@ -119,13 +38,19 @@ impl<'a> SessionSubdiagnosticDerive<'a> {
syn::Data::Union(..) => {
span_err(
span,
- "`#[derive(SessionSubdiagnostic)]` can only be used on structs and enums",
+ "`#[derive(Subdiagnostic)]` can only be used on structs and enums",
);
}
}
- if matches!(ast.data, syn::Data::Enum(..)) {
+ let is_enum = matches!(ast.data, syn::Data::Enum(..));
+ if is_enum {
for attr in &ast.attrs {
+ // Always allow documentation comments.
+ if is_doc_comment(attr) {
+ continue;
+ }
+
span_err(
attr.span().unwrap(),
"unsupported type attribute for subdiagnostic enum",
@@ -136,24 +61,16 @@ impl<'a> SessionSubdiagnosticDerive<'a> {
structure.bind_with(|_| synstructure::BindStyle::Move);
let variants_ = structure.each_variant(|variant| {
- // Build the mapping of field names to fields. This allows attributes to peek
- // values from other fields.
- let mut fields_map = HashMap::new();
- for binding in variant.bindings() {
- let field = binding.ast();
- if let Some(ident) = &field.ident {
- fields_map.insert(ident.to_string(), quote! { #binding });
- }
- }
-
- let mut builder = SessionSubdiagnosticDeriveBuilder {
- diag: &diag,
+ let mut builder = SubdiagnosticDeriveVariantBuilder {
+ parent: &self,
variant,
span,
- fields: fields_map,
+ formatting_init: TokenStream::new(),
+ fields: build_field_mapping(variant),
span_field: None,
applicability: None,
has_suggestion_parts: false,
+ is_enum,
};
builder.into_tokens().unwrap_or_else(|v| v.to_compile_error())
});
@@ -165,9 +82,17 @@ impl<'a> SessionSubdiagnosticDerive<'a> {
}
};
+ let diag = &self.diag;
+ let f = &self.f;
let ret = structure.gen_impl(quote! {
- gen impl rustc_errors::AddSubdiagnostic for @Self {
- fn add_to_diagnostic(self, #diag: &mut rustc_errors::Diagnostic) {
+ gen impl rustc_errors::AddToDiagnostic for @Self {
+ fn add_to_diagnostic_with<__F>(self, #diag: &mut rustc_errors::Diagnostic, #f: __F)
+ where
+ __F: core::ops::Fn(
+ &mut rustc_errors::Diagnostic,
+ rustc_errors::SubdiagnosticMessage
+ ) -> rustc_errors::SubdiagnosticMessage,
+ {
use rustc_errors::{Applicability, IntoDiagnosticArg};
#implementation
}
@@ -178,34 +103,40 @@ impl<'a> SessionSubdiagnosticDerive<'a> {
}
/// Tracks persistent information required for building up the call to add to the diagnostic
-/// for the final generated method. This is a separate struct to `SessionSubdiagnosticDerive`
+/// for the final generated method. This is a separate struct to `SubdiagnosticDerive`
/// only to be able to destructure and split `self.builder` and the `self.structure` up to avoid a
/// double mut borrow later on.
-struct SessionSubdiagnosticDeriveBuilder<'a> {
+struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
/// The identifier to use for the generated `DiagnosticBuilder` instance.
- diag: &'a syn::Ident,
+ parent: &'parent SubdiagnosticDeriveBuilder,
/// Info for the current variant (or the type if not an enum).
variant: &'a VariantInfo<'a>,
/// Span for the entire type.
span: proc_macro::Span,
+ /// Initialization of format strings for code suggestions.
+ formatting_init: TokenStream,
+
/// Store a map of field name to its corresponding field. This is built on construction of the
/// derive builder.
- fields: HashMap<String, TokenStream>,
+ fields: FieldMap,
/// Identifier for the binding to the `#[primary_span]` field.
- span_field: Option<(proc_macro2::Ident, proc_macro::Span)>,
- /// If a suggestion, the identifier for the binding to the `#[applicability]` field or a
- /// `rustc_errors::Applicability::*` variant directly.
- applicability: Option<(TokenStream, proc_macro::Span)>,
+ span_field: SpannedOption<proc_macro2::Ident>,
+
+ /// The binding to the `#[applicability]` field, if present.
+ applicability: SpannedOption<TokenStream>,
/// Set to true when a `#[suggestion_part]` field is encountered, used to generate an error
/// during finalization if still `false`.
has_suggestion_parts: bool,
+
+ /// Set to true when this variant is an enum variant rather than just the body of a struct.
+ is_enum: bool,
}
-impl<'a> HasFieldMap for SessionSubdiagnosticDeriveBuilder<'a> {
+impl<'parent, 'a> HasFieldMap for SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
fn get_field_binding(&self, field: &String) -> Option<&TokenStream> {
self.fields.get(field)
}
@@ -217,6 +148,7 @@ struct KindsStatistics {
has_multipart_suggestion: bool,
all_multipart_suggestions: bool,
has_normal_suggestion: bool,
+ all_applicabilities_static: bool,
}
impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
@@ -225,8 +157,15 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
has_multipart_suggestion: false,
all_multipart_suggestions: true,
has_normal_suggestion: false,
+ all_applicabilities_static: true,
};
+
for kind in kinds {
+ if let SubdiagnosticKind::MultipartSuggestion { applicability: None, .. }
+ | SubdiagnosticKind::Suggestion { applicability: None, .. } = kind
+ {
+ ret.all_applicabilities_static = false;
+ }
if let SubdiagnosticKind::MultipartSuggestion { .. } = kind {
ret.has_multipart_suggestion = true;
} else {
@@ -241,134 +180,23 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
}
}
-impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
+impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
let mut kind_slugs = vec![];
for attr in self.variant.ast().attrs {
- let span = attr.span().unwrap();
-
- let name = attr.path.segments.last().unwrap().ident.to_string();
- let name = name.as_str();
-
- let meta = attr.parse_meta()?;
- let Meta::List(MetaList { ref nested, .. }) = meta else {
- throw_invalid_attr!(attr, &meta);
+ let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
+ // Some attributes aren't errors - like documentation comments - but also aren't
+ // subdiagnostics.
+ continue;
};
- let mut kind = match name {
- "label" => SubdiagnosticKind::Label,
- "note" => SubdiagnosticKind::Note,
- "help" => SubdiagnosticKind::Help,
- "warning" => SubdiagnosticKind::Warn,
- _ => {
- if let Some(suggestion_kind) =
- name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
- {
- SubdiagnosticKind::Suggestion { suggestion_kind, code: TokenStream::new() }
- } else if let Some(suggestion_kind) =
- name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
- {
- SubdiagnosticKind::MultipartSuggestion { suggestion_kind }
- } else {
- throw_invalid_attr!(attr, &meta);
- }
- }
- };
-
- let mut slug = None;
- let mut code = None;
-
- let mut nested_iter = nested.into_iter();
- if let Some(nested_attr) = nested_iter.next() {
- match nested_attr {
- NestedMeta::Meta(Meta::Path(path)) => {
- slug.set_once((path.clone(), span));
- }
- NestedMeta::Meta(meta @ Meta::NameValue(_))
- if matches!(
- meta.path().segments.last().unwrap().ident.to_string().as_str(),
- "code" | "applicability"
- ) =>
- {
- // Don't error for valid follow-up attributes.
- }
- nested_attr => {
- throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help(
- "first argument of the attribute should be the diagnostic \
- slug",
- )
- })
- }
- };
- }
-
- for nested_attr in nested_iter {
- let meta = match nested_attr {
- NestedMeta::Meta(ref meta) => meta,
- _ => throw_invalid_nested_attr!(attr, &nested_attr),
- };
-
- let span = meta.span().unwrap();
- let nested_name = meta.path().segments.last().unwrap().ident.to_string();
- let nested_name = nested_name.as_str();
-
- let value = match meta {
- Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => value,
- Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help("a diagnostic slug must be the first argument to the attribute")
- }),
- _ => throw_invalid_nested_attr!(attr, &nested_attr),
- };
-
- match nested_name {
- "code" => {
- if matches!(kind, SubdiagnosticKind::Suggestion { .. }) {
- let formatted_str = self.build_format(&value.value(), value.span());
- code.set_once((formatted_str, span));
- } else {
- span_err(
- span,
- &format!(
- "`code` is not a valid nested attribute of a `{}` attribute",
- name
- ),
- )
- .emit();
- }
- }
- "applicability" => {
- if matches!(
- kind,
- SubdiagnosticKind::Suggestion { .. }
- | SubdiagnosticKind::MultipartSuggestion { .. }
- ) {
- let value =
- Applicability::from_str(&value.value()).unwrap_or_else(|()| {
- span_err(span, "invalid applicability").emit();
- Applicability::Unspecified
- });
- self.applicability.set_once((quote! { #value }, span));
- } else {
- span_err(
- span,
- &format!(
- "`applicability` is not a valid nested attribute of a `{}` attribute",
- name
- )
- ).emit();
- }
- }
- _ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
- diag.help("only `code` and `applicability` are valid nested attributes")
- }),
- }
- }
+ let Some(slug) = slug else {
+ let name = attr.path.segments.last().unwrap().ident.to_string();
+ let name = name.as_str();
- let Some((slug, _)) = slug else {
throw_span_err!(
- span,
+ attr.span().unwrap(),
&format!(
"diagnostic slug must be first argument of a `#[{}(...)]` attribute",
name
@@ -376,21 +204,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
);
};
- match kind {
- SubdiagnosticKind::Suggestion { code: ref mut code_field, .. } => {
- let Some((code, _)) = code else {
- throw_span_err!(span, "suggestion without `code = \"...\"`");
- };
- *code_field = code;
- }
- SubdiagnosticKind::Label
- | SubdiagnosticKind::Note
- | SubdiagnosticKind::Help
- | SubdiagnosticKind::Warn
- | SubdiagnosticKind::MultipartSuggestion { .. } => {}
- }
-
- kind_slugs.push((kind, slug))
+ kind_slugs.push((kind, slug));
}
Ok(kind_slugs)
@@ -401,8 +215,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
let ast = binding.ast();
assert_eq!(ast.attrs.len(), 0, "field with attribute used as diagnostic arg");
- let diag = &self.diag;
+ let diag = &self.parent.diag;
let ident = ast.ident.as_ref().unwrap();
+ // strip `r#` prefix, if present
+ let ident = format_ident!("{}", ident);
+
quote! {
#diag.set_arg(
stringify!(#ident),
@@ -426,6 +243,11 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
ast.attrs
.iter()
.map(|attr| {
+ // Always allow documentation comments.
+ if is_doc_comment(attr) {
+ return quote! {};
+ }
+
let info = FieldInfo {
binding,
ty: inner_ty.inner_type().unwrap_or(&ast.ty),
@@ -433,7 +255,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
};
let generated = self
- .generate_field_code_inner(kind_stats, attr, info)
+ .generate_field_code_inner(kind_stats, attr, info, inner_ty.will_iterate())
.unwrap_or_else(|v| v.to_compile_error());
inner_ty.with(binding, generated)
@@ -446,13 +268,18 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
kind_stats: KindsStatistics,
attr: &Attribute,
info: FieldInfo<'_>,
+ clone_suggestion_code: bool,
) -> Result<TokenStream, DiagnosticDeriveError> {
let meta = attr.parse_meta()?;
match meta {
Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path),
- Meta::List(list @ MetaList { .. }) => {
- self.generate_field_code_inner_list(kind_stats, attr, info, list)
- }
+ Meta::List(list @ MetaList { .. }) => self.generate_field_code_inner_list(
+ kind_stats,
+ attr,
+ info,
+ list,
+ clone_suggestion_code,
+ ),
_ => throw_invalid_attr!(attr, &meta),
}
}
@@ -474,18 +301,20 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
"skip_arg" => Ok(quote! {}),
"primary_span" => {
if kind_stats.has_multipart_suggestion {
- throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
- diag.help(
+ invalid_attr(attr, &Meta::Path(path))
+ .help(
"multipart suggestions use one or more `#[suggestion_part]`s rather \
than one `#[primary_span]`",
)
- })
- }
-
- report_error_if_not_applied_to_span(attr, &info)?;
+ .emit();
+ } else {
+ report_error_if_not_applied_to_span(attr, &info)?;
- let binding = info.binding.binding.clone();
- self.span_field.set_once((binding, span));
+ let binding = info.binding.binding.clone();
+ // FIXME(#100717): support `Option<Span>` on `primary_span` like in the
+ // diagnostic derive
+ self.span_field.set_once(binding, span);
+ }
Ok(quote! {})
}
@@ -495,28 +324,39 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
if kind_stats.has_multipart_suggestion {
span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
.emit();
- Ok(quote! {})
} else {
- throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
- diag.help(
- "`#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead",
- )
- });
+ invalid_attr(attr, &Meta::Path(path))
+ .help(
+ "`#[suggestion_part(...)]` is only valid in multipart suggestions, \
+ use `#[primary_span]` instead",
+ )
+ .emit();
}
+
+ Ok(quote! {})
}
"applicability" => {
if kind_stats.has_multipart_suggestion || kind_stats.has_normal_suggestion {
report_error_if_not_applied_to_applicability(attr, &info)?;
+ if kind_stats.all_applicabilities_static {
+ span_err(
+ span,
+ "`#[applicability]` has no effect if all `#[suggestion]`/\
+ `#[multipart_suggestion]` attributes have a static \
+ `applicability = \"...\"`",
+ )
+ .emit();
+ }
let binding = info.binding.binding.clone();
- self.applicability.set_once((quote! { #binding }, span));
+ self.applicability.set_once(quote! { #binding }, span);
} else {
span_err(span, "`#[applicability]` is only valid on suggestions").emit();
}
Ok(quote! {})
}
- _ => throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+ _ => {
let mut span_attrs = vec![];
if kind_stats.has_multipart_suggestion {
span_attrs.push("suggestion_part");
@@ -524,11 +364,16 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
if !kind_stats.all_multipart_suggestions {
span_attrs.push("primary_span")
}
- diag.help(format!(
- "only `{}`, `applicability` and `skip_arg` are valid field attributes",
- span_attrs.join(", ")
- ))
- }),
+
+ invalid_attr(attr, &Meta::Path(path))
+ .help(format!(
+ "only `{}`, `applicability` and `skip_arg` are valid field attributes",
+ span_attrs.join(", ")
+ ))
+ .emit();
+
+ Ok(quote! {})
+ }
}
}
@@ -540,6 +385,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
attr: &Attribute,
info: FieldInfo<'_>,
list: MetaList,
+ clone_suggestion_code: bool,
) -> Result<TokenStream, DiagnosticDeriveError> {
let span = attr.span().unwrap();
let ident = &list.path.segments.last().unwrap().ident;
@@ -570,14 +416,16 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
let nested_name = meta.path().segments.last().unwrap().ident.to_string();
let nested_name = nested_name.as_str();
- let Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) = meta else {
- throw_invalid_nested_attr!(attr, &nested_attr);
- };
-
match nested_name {
"code" => {
- let formatted_str = self.build_format(&value.value(), value.span());
- code.set_once((formatted_str, span));
+ let code_field = new_code_ident();
+ let formatting_init = build_suggestion_code(
+ &code_field,
+ meta,
+ self,
+ AllowMultipleAlternatives::No,
+ );
+ code.set_once((code_field, formatting_init), span);
}
_ => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
diag.help("`code` is the only valid nested attribute")
@@ -585,14 +433,20 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
}
}
- let Some((code, _)) = code else {
+ let Some((code_field, formatting_init)) = code.value() else {
span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
.emit();
return Ok(quote! {});
};
let binding = info.binding;
- Ok(quote! { suggestions.push((#binding, #code)); })
+ self.formatting_init.extend(formatting_init);
+ let code_field = if clone_suggestion_code {
+ quote! { #code_field.clone() }
+ } else {
+ quote! { #code_field }
+ };
+ Ok(quote! { suggestions.push((#binding, #code_field)); })
}
_ => throw_invalid_attr!(attr, &Meta::List(list), |diag| {
let mut span_attrs = vec![];
@@ -613,10 +467,16 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
pub fn into_tokens(&mut self) -> Result<TokenStream, DiagnosticDeriveError> {
let kind_slugs = self.identify_kind()?;
if kind_slugs.is_empty() {
- throw_span_err!(
- self.variant.ast().ident.span().unwrap(),
- "subdiagnostic kind not specified"
- );
+ if self.is_enum {
+ // It's okay for a variant to not be a subdiagnostic at all..
+ return Ok(quote! {});
+ } else {
+ // ..but structs should always be _something_.
+ throw_span_err!(
+ self.variant.ast().ident.span().unwrap(),
+ "subdiagnostic kind not specified"
+ );
+ }
};
let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
@@ -635,29 +495,46 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
.map(|binding| self.generate_field_attr_code(binding, kind_stats))
.collect();
- let span_field = self.span_field.as_ref().map(|(span, _)| span);
- let applicability = self.applicability.take().map_or_else(
- || quote! { rustc_errors::Applicability::Unspecified },
- |(applicability, _)| applicability,
- );
+ let span_field = self.span_field.value_ref();
- let diag = &self.diag;
+ let diag = &self.parent.diag;
+ let f = &self.parent.f;
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()); });
+
let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
- let message = quote! { rustc_errors::fluent::#slug };
let call = match kind {
- SubdiagnosticKind::Suggestion { suggestion_kind, code } => {
+ SubdiagnosticKind::Suggestion {
+ suggestion_kind,
+ applicability,
+ code_init,
+ code_field,
+ } => {
+ self.formatting_init.extend(code_init);
+
+ let applicability = applicability
+ .value()
+ .map(|a| quote! { #a })
+ .or_else(|| self.applicability.take().value())
+ .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
+
if let Some(span) = span_field {
let style = suggestion_kind.to_suggestion_style();
-
- quote! { #diag.#name(#span, #message, #code, #applicability, #style); }
+ quote! { #diag.#name(#span, #message, #code_field, #applicability, #style); }
} else {
span_err(self.span, "suggestion without `#[primary_span]` field").emit();
quote! { unreachable!(); }
}
}
- SubdiagnosticKind::MultipartSuggestion { suggestion_kind } => {
+ SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability } => {
+ let applicability = applicability
+ .value()
+ .map(|a| quote! { #a })
+ .or_else(|| self.applicability.take().value())
+ .unwrap_or_else(|| quote! { rustc_errors::Applicability::Unspecified });
+
if !self.has_suggestion_parts {
span_err(
self.span,
@@ -686,6 +563,7 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
}
}
};
+
calls.extend(call);
}
@@ -697,11 +575,13 @@ impl<'a> SessionSubdiagnosticDeriveBuilder<'a> {
.map(|binding| self.generate_field_set_arg(binding))
.collect();
+ let formatting_init = &self.formatting_init;
Ok(quote! {
#init
+ #formatting_init
#attr_args
- #calls
#plain_args
+ #calls
})
}
}
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index ad9ecd39b..374c795d0 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -1,11 +1,31 @@
-use crate::diagnostics::error::{span_err, throw_span_err, DiagnosticDeriveError};
+use crate::diagnostics::error::{
+ span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
+};
use proc_macro::Span;
-use proc_macro2::TokenStream;
+use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote, ToTokens};
+use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
+use std::fmt;
use std::str::FromStr;
-use syn::{spanned::Spanned, Attribute, Meta, Type, TypeTuple};
-use synstructure::{BindingInfo, Structure};
+use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
+use syn::{MetaList, MetaNameValue, NestedMeta, Path};
+use synstructure::{BindingInfo, VariantInfo};
+
+use super::error::invalid_nested_attr;
+
+thread_local! {
+ pub static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0);
+}
+
+/// Returns an ident of the form `__code_N` where `N` is incremented once with every call.
+pub(crate) fn new_code_ident() -> syn::Ident {
+ CODE_IDENT_COUNT.with(|count| {
+ let ident = format_ident!("__code_{}", *count.borrow());
+ *count.borrow_mut() += 1;
+ ident
+ })
+}
/// Checks whether the type name of `ty` matches `name`.
///
@@ -135,6 +155,15 @@ impl<'ty> FieldInnerTy<'ty> {
unreachable!();
}
+ /// Returns `true` if `FieldInnerTy::with` will result in iteration for this inner type (i.e.
+ /// that cloning might be required for values moved in the loop body).
+ pub(crate) fn will_iterate(&self) -> bool {
+ match self {
+ FieldInnerTy::Vec(..) => true,
+ FieldInnerTy::Option(..) | FieldInnerTy::None => false,
+ }
+ }
+
/// Returns `Option` containing inner type if there is one.
pub(crate) fn inner_type(&self) -> Option<&'ty Type> {
match self {
@@ -172,13 +201,17 @@ pub(crate) struct FieldInfo<'a> {
/// Small helper trait for abstracting over `Option` fields that contain a value and a `Span`
/// for error reporting if they are set more than once.
pub(crate) trait SetOnce<T> {
- fn set_once(&mut self, _: (T, Span));
+ fn set_once(&mut self, value: T, span: Span);
fn value(self) -> Option<T>;
+ fn value_ref(&self) -> Option<&T>;
}
-impl<T> SetOnce<T> for Option<(T, Span)> {
- fn set_once(&mut self, (value, span): (T, Span)) {
+/// An [`Option<T>`] that keeps track of the span that caused it to be set; used with [`SetOnce`].
+pub(super) type SpannedOption<T> = Option<(T, Span)>;
+
+impl<T> SetOnce<T> for SpannedOption<T> {
+ fn set_once(&mut self, value: T, span: Span) {
match self {
None => {
*self = Some((value, span));
@@ -194,8 +227,14 @@ impl<T> SetOnce<T> for Option<(T, Span)> {
fn value(self) -> Option<T> {
self.map(|(v, _)| v)
}
+
+ fn value_ref(&self) -> Option<&T> {
+ self.as_ref().map(|(v, _)| v)
+ }
}
+pub(super) type FieldMap = HashMap<String, TokenStream>;
+
pub(crate) trait HasFieldMap {
/// Returns the binding for the field with the given name, if it exists on the type.
fn get_field_binding(&self, field: &String) -> Option<&TokenStream>;
@@ -303,6 +342,7 @@ pub(crate) trait HasFieldMap {
/// `Applicability` of a suggestion - mirrors `rustc_errors::Applicability` - and used to represent
/// the user's selection of applicability if specified in an attribute.
+#[derive(Clone, Copy)]
pub(crate) enum Applicability {
MachineApplicable,
MaybeIncorrect,
@@ -345,17 +385,366 @@ impl quote::ToTokens for Applicability {
/// Build the mapping of field names to fields. This allows attributes to peek values from
/// other fields.
-pub(crate) fn build_field_mapping<'a>(structure: &Structure<'a>) -> HashMap<String, TokenStream> {
- let mut fields_map = HashMap::new();
-
- let ast = structure.ast();
- if let syn::Data::Struct(syn::DataStruct { fields, .. }) = &ast.data {
- for field in fields.iter() {
- if let Some(ident) = &field.ident {
- fields_map.insert(ident.to_string(), quote! { &self.#ident });
+pub(super) fn build_field_mapping<'v>(variant: &VariantInfo<'v>) -> HashMap<String, TokenStream> {
+ let mut fields_map = FieldMap::new();
+ for binding in variant.bindings() {
+ if let Some(ident) = &binding.ast().ident {
+ fields_map.insert(ident.to_string(), quote! { #binding });
+ }
+ }
+ fields_map
+}
+
+#[derive(Copy, Clone, Debug)]
+pub(super) enum AllowMultipleAlternatives {
+ No,
+ Yes,
+}
+
+/// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or
+/// `#[suggestion*(code("foo", "bar"))]` attribute field
+pub(super) fn build_suggestion_code(
+ code_field: &Ident,
+ meta: &Meta,
+ fields: &impl HasFieldMap,
+ allow_multiple: AllowMultipleAlternatives,
+) -> TokenStream {
+ let values = match meta {
+ // `code = "foo"`
+ Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s],
+ // `code("foo", "bar")`
+ Meta::List(MetaList { nested, .. }) => {
+ if let AllowMultipleAlternatives::No = allow_multiple {
+ span_err(
+ meta.span().unwrap(),
+ "expected exactly one string literal for `code = ...`",
+ )
+ .emit();
+ vec![]
+ } else if nested.is_empty() {
+ span_err(
+ meta.span().unwrap(),
+ "expected at least one string literal for `code(...)`",
+ )
+ .emit();
+ vec![]
+ } else {
+ nested
+ .into_iter()
+ .filter_map(|item| {
+ if let NestedMeta::Lit(syn::Lit::Str(s)) = item {
+ Some(s)
+ } else {
+ span_err(
+ item.span().unwrap(),
+ "`code(...)` must contain only string literals",
+ )
+ .emit();
+ None
+ }
+ })
+ .collect()
}
}
+ _ => {
+ span_err(
+ meta.span().unwrap(),
+ r#"`code = "..."`/`code(...)` must contain only string literals"#,
+ )
+ .emit();
+ vec![]
+ }
+ };
+
+ if let AllowMultipleAlternatives::Yes = allow_multiple {
+ let formatted_strings: Vec<_> = values
+ .into_iter()
+ .map(|value| fields.build_format(&value.value(), value.span()))
+ .collect();
+ quote! { let #code_field = [#(#formatted_strings),*].into_iter(); }
+ } else if let [value] = values.as_slice() {
+ let formatted_str = fields.build_format(&value.value(), value.span());
+ quote! { let #code_field = #formatted_str; }
+ } else {
+ // error handled previously
+ quote! { let #code_field = String::new(); }
}
+}
- fields_map
+/// Possible styles for suggestion subdiagnostics.
+#[derive(Clone, Copy)]
+pub(super) enum SuggestionKind {
+ /// `#[suggestion]`
+ Normal,
+ /// `#[suggestion_short]`
+ Short,
+ /// `#[suggestion_hidden]`
+ Hidden,
+ /// `#[suggestion_verbose]`
+ Verbose,
+}
+
+impl FromStr for SuggestionKind {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "" => Ok(SuggestionKind::Normal),
+ "_short" => Ok(SuggestionKind::Short),
+ "_hidden" => Ok(SuggestionKind::Hidden),
+ "_verbose" => Ok(SuggestionKind::Verbose),
+ _ => Err(()),
+ }
+ }
+}
+
+impl SuggestionKind {
+ pub fn to_suggestion_style(&self) -> TokenStream {
+ match self {
+ SuggestionKind::Normal => {
+ quote! { rustc_errors::SuggestionStyle::ShowCode }
+ }
+ SuggestionKind::Short => {
+ quote! { rustc_errors::SuggestionStyle::HideCodeInline }
+ }
+ SuggestionKind::Hidden => {
+ quote! { rustc_errors::SuggestionStyle::HideCodeAlways }
+ }
+ SuggestionKind::Verbose => {
+ quote! { rustc_errors::SuggestionStyle::ShowAlways }
+ }
+ }
+ }
+}
+
+/// Types of subdiagnostics that can be created using attributes
+#[derive(Clone)]
+pub(super) enum SubdiagnosticKind {
+ /// `#[label(...)]`
+ Label,
+ /// `#[note(...)]`
+ Note,
+ /// `#[help(...)]`
+ Help,
+ /// `#[warning(...)]`
+ Warn,
+ /// `#[suggestion{,_short,_hidden,_verbose}]`
+ Suggestion {
+ suggestion_kind: SuggestionKind,
+ applicability: SpannedOption<Applicability>,
+ /// Identifier for variable used for formatted code, e.g. `___code_0`. Enables separation
+ /// of formatting and diagnostic emission so that `set_arg` calls can happen in-between..
+ code_field: syn::Ident,
+ /// Initialization logic for `code_field`'s variable, e.g.
+ /// `let __formatted_code = /* whatever */;`
+ code_init: TokenStream,
+ },
+ /// `#[multipart_suggestion{,_short,_hidden,_verbose}]`
+ MultipartSuggestion {
+ suggestion_kind: SuggestionKind,
+ applicability: SpannedOption<Applicability>,
+ },
+}
+
+impl SubdiagnosticKind {
+ /// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`,
+ /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the
+ /// `SubdiagnosticKind` and the diagnostic slug, if specified.
+ pub(super) fn from_attr(
+ attr: &Attribute,
+ fields: &impl HasFieldMap,
+ ) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
+ // Always allow documentation comments.
+ if is_doc_comment(attr) {
+ return Ok(None);
+ }
+
+ let span = attr.span().unwrap();
+
+ let name = attr.path.segments.last().unwrap().ident.to_string();
+ let name = name.as_str();
+
+ let meta = attr.parse_meta()?;
+ let mut kind = match name {
+ "label" => SubdiagnosticKind::Label,
+ "note" => SubdiagnosticKind::Note,
+ "help" => SubdiagnosticKind::Help,
+ "warning" => SubdiagnosticKind::Warn,
+ _ => {
+ if let Some(suggestion_kind) =
+ name.strip_prefix("suggestion").and_then(|s| s.parse().ok())
+ {
+ SubdiagnosticKind::Suggestion {
+ suggestion_kind,
+ applicability: None,
+ code_field: new_code_ident(),
+ code_init: TokenStream::new(),
+ }
+ } else if let Some(suggestion_kind) =
+ name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok())
+ {
+ SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability: None }
+ } else {
+ throw_invalid_attr!(attr, &meta);
+ }
+ }
+ };
+
+ let nested = match meta {
+ Meta::List(MetaList { ref nested, .. }) => {
+ // An attribute with properties, such as `#[suggestion(code = "...")]` or
+ // `#[error(some::slug)]`
+ nested
+ }
+ Meta::Path(_) => {
+ // An attribute without a slug or other properties, such as `#[note]` - return
+ // without further processing.
+ //
+ // Only allow this if there are no mandatory properties, such as `code = "..."` in
+ // `#[suggestion(...)]`
+ match kind {
+ SubdiagnosticKind::Label
+ | SubdiagnosticKind::Note
+ | SubdiagnosticKind::Help
+ | SubdiagnosticKind::Warn
+ | SubdiagnosticKind::MultipartSuggestion { .. } => {
+ return Ok(Some((kind, None)));
+ }
+ SubdiagnosticKind::Suggestion { .. } => {
+ throw_span_err!(span, "suggestion without `code = \"...\"`")
+ }
+ }
+ }
+ _ => {
+ throw_invalid_attr!(attr, &meta)
+ }
+ };
+
+ let mut code = None;
+
+ let mut nested_iter = nested.into_iter().peekable();
+
+ // Peek at the first nested attribute: if it's a slug path, consume it.
+ let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() {
+ let path = path.clone();
+ // Advance the iterator.
+ nested_iter.next();
+ Some(path)
+ } else {
+ None
+ };
+
+ for nested_attr in nested_iter {
+ let meta = match nested_attr {
+ NestedMeta::Meta(ref meta) => meta,
+ NestedMeta::Lit(_) => {
+ invalid_nested_attr(attr, &nested_attr).emit();
+ continue;
+ }
+ };
+
+ let span = meta.span().unwrap();
+ let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+ let nested_name = nested_name.as_str();
+
+ let string_value = match meta {
+ Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value),
+
+ Meta::Path(_) => throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
+ diag.help("a diagnostic slug must be the first argument to the attribute")
+ }),
+ _ => None,
+ };
+
+ match (nested_name, &mut kind) {
+ ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
+ let code_init = build_suggestion_code(
+ code_field,
+ meta,
+ fields,
+ AllowMultipleAlternatives::Yes,
+ );
+ code.set_once(code_init, span);
+ }
+ (
+ "applicability",
+ SubdiagnosticKind::Suggestion { ref mut applicability, .. }
+ | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
+ ) => {
+ let Some(value) = string_value else {
+ invalid_nested_attr(attr, &nested_attr).emit();
+ continue;
+ };
+
+ let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
+ span_err(span, "invalid applicability").emit();
+ Applicability::Unspecified
+ });
+ applicability.set_once(value, span);
+ }
+
+ // Invalid nested attribute
+ (_, SubdiagnosticKind::Suggestion { .. }) => {
+ invalid_nested_attr(attr, &nested_attr)
+ .help("only `code` and `applicability` are valid nested attributes")
+ .emit();
+ }
+ (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
+ invalid_nested_attr(attr, &nested_attr)
+ .help("only `applicability` is a valid nested attributes")
+ .emit()
+ }
+ _ => {
+ invalid_nested_attr(attr, &nested_attr).emit();
+ }
+ }
+ }
+
+ match kind {
+ SubdiagnosticKind::Suggestion { ref code_field, ref mut code_init, .. } => {
+ *code_init = if let Some(init) = code.value() {
+ init
+ } else {
+ span_err(span, "suggestion without `code = \"...\"`").emit();
+ quote! { let #code_field = std::iter::empty(); }
+ };
+ }
+ SubdiagnosticKind::Label
+ | SubdiagnosticKind::Note
+ | SubdiagnosticKind::Help
+ | SubdiagnosticKind::Warn
+ | SubdiagnosticKind::MultipartSuggestion { .. } => {}
+ }
+
+ Ok(Some((kind, slug)))
+ }
+}
+
+impl quote::IdentFragment for SubdiagnosticKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ SubdiagnosticKind::Label => write!(f, "label"),
+ SubdiagnosticKind::Note => write!(f, "note"),
+ SubdiagnosticKind::Help => write!(f, "help"),
+ SubdiagnosticKind::Warn => write!(f, "warn"),
+ SubdiagnosticKind::Suggestion { .. } => write!(f, "suggestions_with_style"),
+ SubdiagnosticKind::MultipartSuggestion { .. } => {
+ write!(f, "multipart_suggestion_with_style")
+ }
+ }
+ }
+
+ fn span(&self) -> Option<proc_macro2::Span> {
+ None
+ }
+}
+
+/// Returns `true` if `field` should generate a `set_arg` call rather than any other diagnostic
+/// call (like `span_label`).
+pub(super) fn should_generate_set_arg(field: &Field) -> bool {
+ field.attrs.is_empty()
+}
+
+pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
+ attr.path.segments.last().unwrap().ident.to_string() == "doc"
}
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 2c027d754..36bda3e0f 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(allow_internal_unstable)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![feature(proc_macro_diagnostic)]
#![feature(proc_macro_span)]
@@ -127,7 +126,7 @@ decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_fo
decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
decl_derive!(
- [SessionDiagnostic, attributes(
+ [Diagnostic, attributes(
// struct attributes
diag,
help,
@@ -161,7 +160,7 @@ decl_derive!(
suggestion_verbose)] => diagnostics::lint_diagnostic_derive
);
decl_derive!(
- [SessionSubdiagnostic, attributes(
+ [Subdiagnostic, attributes(
// struct/variant attributes
label,
help,
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index d49926c90..7cefafef9 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -237,27 +237,32 @@ fn doc_comment_from_desc(list: &Punctuated<Expr, token::Comma>) -> Result<Attrib
}
/// Add the impl of QueryDescription for the query to `impls` if one is requested
-fn add_query_description_impl(query: &Query, impls: &mut proc_macro2::TokenStream) {
- let name = &query.name;
- let key = &query.key;
- let modifiers = &query.modifiers;
+fn add_query_desc_cached_impl(
+ query: &Query,
+ descs: &mut proc_macro2::TokenStream,
+ cached: &mut proc_macro2::TokenStream,
+) {
+ let Query { name, key, modifiers, .. } = &query;
// Find out if we should cache the query on disk
let cache = if let Some((args, expr)) = modifiers.cache.as_ref() {
let tcx = args.as_ref().map(|t| quote! { #t }).unwrap_or_else(|| quote! { _ });
// expr is a `Block`, meaning that `{ #expr }` gets expanded
// to `{ { stmts... } }`, which triggers the `unused_braces` lint.
+ // we're taking `key` by reference, but some rustc types usually prefer being passed by value
quote! {
- #[allow(unused_variables, unused_braces)]
+ #[allow(unused_variables, unused_braces, rustc::pass_by_value)]
#[inline]
- fn cache_on_disk(#tcx: TyCtxt<'tcx>, #key: &Self::Key) -> bool {
+ pub fn #name<'tcx>(#tcx: TyCtxt<'tcx>, #key: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
#expr
}
}
} else {
quote! {
+ // we're taking `key` by reference, but some rustc types usually prefer being passed by value
+ #[allow(rustc::pass_by_value)]
#[inline]
- fn cache_on_disk(_: TyCtxt<'tcx>, _: &Self::Key) -> bool {
+ pub fn #name<'tcx>(_: TyCtxt<'tcx>, _: &crate::ty::query::query_keys::#name<'tcx>) -> bool {
false
}
}
@@ -268,19 +273,20 @@ fn add_query_description_impl(query: &Query, impls: &mut proc_macro2::TokenStrea
let desc = quote! {
#[allow(unused_variables)]
- fn describe(tcx: QueryCtxt<'tcx>, key: Self::Key) -> String {
- let (#tcx, #key) = (*tcx, key);
+ pub fn #name<'tcx>(tcx: TyCtxt<'tcx>, key: crate::ty::query::query_keys::#name<'tcx>) -> String {
+ let (#tcx, #key) = (tcx, key);
::rustc_middle::ty::print::with_no_trimmed_paths!(
format!(#desc)
)
}
};
- impls.extend(quote! {
- (#name) => {
- #desc
- #cache
- };
+ descs.extend(quote! {
+ #desc
+ });
+
+ cached.extend(quote! {
+ #cache
});
}
@@ -289,7 +295,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
let mut query_stream = quote! {};
let mut query_description_stream = quote! {};
- let mut cached_queries = quote! {};
+ let mut query_cached_stream = quote! {};
for query in queries.0 {
let Query { name, arg, modifiers, .. } = &query;
@@ -299,12 +305,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
_ => quote! { #result_full },
};
- if modifiers.cache.is_some() {
- cached_queries.extend(quote! {
- #name,
- });
- }
-
let mut attributes = Vec::new();
macro_rules! passthrough {
@@ -350,7 +350,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
[#attribute_stream] fn #name(#arg) #result,
});
- add_query_description_impl(&query, &mut query_description_stream);
+ add_query_desc_cached_impl(&query, &mut query_description_stream, &mut query_cached_stream);
}
TokenStream::from(quote! {
@@ -364,9 +364,13 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
}
}
- #[macro_export]
- macro_rules! rustc_query_description {
+ pub mod descs {
+ use super::*;
#query_description_stream
}
+ pub mod cached {
+ use super::*;
+ #query_cached_stream
+ }
})
}
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 2c5db9d8b..6d85103c9 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
libloading = "0.7.1"
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 7d63fad32..7c387b9a9 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -3,137 +3,137 @@ use std::{
path::{Path, PathBuf},
};
-use rustc_errors::{error_code, ErrorGuaranteed};
-use rustc_macros::SessionDiagnostic;
-use rustc_session::{config, SessionDiagnostic};
+use rustc_errors::{error_code, ErrorGuaranteed, IntoDiagnostic};
+use rustc_macros::Diagnostic;
+use rustc_session::config;
use rustc_span::{sym, Span, Symbol};
use rustc_target::spec::{PanicStrategy, TargetTriple};
use crate::locator::CrateFlavor;
-#[derive(SessionDiagnostic)]
-#[diag(metadata::rlib_required)]
+#[derive(Diagnostic)]
+#[diag(metadata_rlib_required)]
pub struct RlibRequired {
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::lib_required)]
+#[derive(Diagnostic)]
+#[diag(metadata_lib_required)]
pub struct LibRequired<'a> {
pub crate_name: Symbol,
pub kind: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::crate_dep_multiple)]
+#[derive(Diagnostic)]
+#[diag(metadata_crate_dep_multiple)]
#[help]
pub struct CrateDepMultiple {
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::two_panic_runtimes)]
+#[derive(Diagnostic)]
+#[diag(metadata_two_panic_runtimes)]
pub struct TwoPanicRuntimes {
pub prev_name: Symbol,
pub cur_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::bad_panic_strategy)]
+#[derive(Diagnostic)]
+#[diag(metadata_bad_panic_strategy)]
pub struct BadPanicStrategy {
pub runtime: Symbol,
pub strategy: PanicStrategy,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::required_panic_strategy)]
+#[derive(Diagnostic)]
+#[diag(metadata_required_panic_strategy)]
pub struct RequiredPanicStrategy {
pub crate_name: Symbol,
pub found_strategy: PanicStrategy,
pub desired_strategy: PanicStrategy,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::incompatible_panic_in_drop_strategy)]
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_panic_in_drop_strategy)]
pub struct IncompatiblePanicInDropStrategy {
pub crate_name: Symbol,
pub found_strategy: PanicStrategy,
pub desired_strategy: PanicStrategy,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_names_in_link)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_names_in_link)]
pub struct MultipleNamesInLink {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_kinds_in_link)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_kinds_in_link)]
pub struct MultipleKindsInLink {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_name_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_name_form)]
pub struct LinkNameForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_kind_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_kind_form)]
pub struct LinkKindForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_modifiers_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_modifiers_form)]
pub struct LinkModifiersForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_cfg_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_cfg_form)]
pub struct LinkCfgForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::wasm_import_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_wasm_import_form)]
pub struct WasmImportForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::empty_link_name, code = "E0454")]
+#[derive(Diagnostic)]
+#[diag(metadata_empty_link_name, code = "E0454")]
pub struct EmptyLinkName {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_framework_apple, code = "E0455")]
+#[derive(Diagnostic)]
+#[diag(metadata_link_framework_apple, code = "E0455")]
pub struct LinkFrameworkApple {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::framework_only_windows, code = "E0455")]
+#[derive(Diagnostic)]
+#[diag(metadata_framework_only_windows, code = "E0455")]
pub struct FrameworkOnlyWindows {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unknown_link_kind, code = "E0458")]
+#[derive(Diagnostic)]
+#[diag(metadata_unknown_link_kind, code = "E0458")]
pub struct UnknownLinkKind<'a> {
#[primary_span]
#[label]
@@ -141,269 +141,303 @@ pub struct UnknownLinkKind<'a> {
pub kind: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_link_modifiers)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_link_modifiers)]
pub struct MultipleLinkModifiers {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_cfgs)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_cfgs)]
pub struct MultipleCfgs {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_cfg_single_predicate)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_cfg_single_predicate)]
pub struct LinkCfgSinglePredicate {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_wasm_import)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_wasm_import)]
pub struct MultipleWasmImport {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unexpected_link_arg)]
+#[derive(Diagnostic)]
+#[diag(metadata_unexpected_link_arg)]
pub struct UnexpectedLinkArg {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::invalid_link_modifier)]
+#[derive(Diagnostic)]
+#[diag(metadata_invalid_link_modifier)]
pub struct InvalidLinkModifier {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_modifiers)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_modifiers)]
pub struct MultipleModifiers<'a> {
#[primary_span]
pub span: Span,
pub modifier: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::bundle_needs_static)]
+#[derive(Diagnostic)]
+#[diag(metadata_bundle_needs_static)]
pub struct BundleNeedsStatic {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::whole_archive_needs_static)]
+#[derive(Diagnostic)]
+#[diag(metadata_whole_archive_needs_static)]
pub struct WholeArchiveNeedsStatic {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::as_needed_compatibility)]
+#[derive(Diagnostic)]
+#[diag(metadata_as_needed_compatibility)]
pub struct AsNeededCompatibility {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unknown_link_modifier)]
+#[derive(Diagnostic)]
+#[diag(metadata_unknown_link_modifier)]
pub struct UnknownLinkModifier<'a> {
#[primary_span]
pub span: Span,
pub modifier: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::incompatible_wasm_link)]
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_wasm_link)]
pub struct IncompatibleWasmLink {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_requires_name, code = "E0459")]
+#[derive(Diagnostic)]
+#[diag(metadata_link_requires_name, code = "E0459")]
pub struct LinkRequiresName {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::raw_dylib_no_nul)]
+#[derive(Diagnostic)]
+#[diag(metadata_raw_dylib_no_nul)]
pub struct RawDylibNoNul {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::link_ordinal_raw_dylib)]
+#[derive(Diagnostic)]
+#[diag(metadata_link_ordinal_raw_dylib)]
pub struct LinkOrdinalRawDylib {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::lib_framework_apple)]
+#[derive(Diagnostic)]
+#[diag(metadata_lib_framework_apple)]
pub struct LibFrameworkApple;
-#[derive(SessionDiagnostic)]
-#[diag(metadata::empty_renaming_target)]
+#[derive(Diagnostic)]
+#[diag(metadata_empty_renaming_target)]
pub struct EmptyRenamingTarget<'a> {
pub lib_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::renaming_no_link)]
+#[derive(Diagnostic)]
+#[diag(metadata_renaming_no_link)]
pub struct RenamingNoLink<'a> {
pub lib_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_renamings)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_renamings)]
pub struct MultipleRenamings<'a> {
pub lib_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_link_mod_override)]
+#[derive(Diagnostic)]
+#[diag(metadata_no_link_mod_override)]
pub struct NoLinkModOverride {
#[primary_span]
pub span: Option<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unsupported_abi_i686)]
+#[derive(Diagnostic)]
+#[diag(metadata_unsupported_abi_i686)]
pub struct UnsupportedAbiI686 {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unsupported_abi)]
+#[derive(Diagnostic)]
+#[diag(metadata_unsupported_abi)]
pub struct UnsupportedAbi {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::fail_create_file_encoder)]
+#[derive(Diagnostic)]
+#[diag(metadata_fail_create_file_encoder)]
pub struct FailCreateFileEncoder {
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::fail_seek_file)]
+#[derive(Diagnostic)]
+#[diag(metadata_fail_seek_file)]
pub struct FailSeekFile {
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::fail_write_file)]
+#[derive(Diagnostic)]
+#[diag(metadata_fail_write_file)]
pub struct FailWriteFile {
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::crate_not_panic_runtime)]
+#[derive(Diagnostic)]
+#[diag(metadata_crate_not_panic_runtime)]
pub struct CrateNotPanicRuntime {
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_panic_strategy)]
+#[derive(Diagnostic)]
+#[diag(metadata_no_panic_strategy)]
pub struct NoPanicStrategy {
pub crate_name: Symbol,
pub strategy: PanicStrategy,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::profiler_builtins_needs_core)]
+#[derive(Diagnostic)]
+#[diag(metadata_profiler_builtins_needs_core)]
pub struct ProfilerBuiltinsNeedsCore;
-#[derive(SessionDiagnostic)]
-#[diag(metadata::not_profiler_runtime)]
+#[derive(Diagnostic)]
+#[diag(metadata_not_profiler_runtime)]
pub struct NotProfilerRuntime {
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_multiple_global_alloc)]
+#[derive(Diagnostic)]
+#[diag(metadata_no_multiple_global_alloc)]
pub struct NoMultipleGlobalAlloc {
#[primary_span]
#[label]
pub span2: Span,
- #[label(metadata::prev_global_alloc)]
+ #[label(metadata_prev_global_alloc)]
pub span1: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::conflicting_global_alloc)]
+#[derive(Diagnostic)]
+#[diag(metadata_conflicting_global_alloc)]
pub struct ConflictingGlobalAlloc {
pub crate_name: Symbol,
pub other_crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::global_alloc_required)]
+#[derive(Diagnostic)]
+#[diag(metadata_global_alloc_required)]
pub struct GlobalAllocRequired;
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_transitive_needs_dep)]
+#[derive(Diagnostic)]
+#[diag(metadata_no_transitive_needs_dep)]
pub struct NoTransitiveNeedsDep<'a> {
pub crate_name: Symbol,
pub needs_crate_name: &'a str,
pub deps_crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::failed_write_error)]
+#[derive(Diagnostic)]
+#[diag(metadata_failed_write_error)]
pub struct FailedWriteError {
pub filename: PathBuf,
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::missing_native_library)]
+#[derive(Diagnostic)]
+#[diag(metadata_missing_native_library)]
pub struct MissingNativeLibrary<'a> {
- pub libname: &'a str,
+ libname: &'a str,
+ #[subdiagnostic]
+ suggest_name: Option<SuggestLibraryName<'a>>,
+}
+
+impl<'a> MissingNativeLibrary<'a> {
+ pub fn new(libname: &'a str, verbatim: bool) -> Self {
+ // if it looks like the user has provided a complete filename rather just the bare lib name,
+ // then provide a note that they might want to try trimming the name
+ let suggested_name = if !verbatim {
+ if let Some(libname) = libname.strip_prefix("lib") && let Some(libname) = libname.strip_suffix(".a") {
+ // this is a unix style filename so trim prefix & suffix
+ Some(libname)
+ } else if let Some(libname) = libname.strip_suffix(".lib") {
+ // this is a Windows style filename so just trim the suffix
+ Some(libname)
+ } else {
+ None
+ }
+ } else {
+ None
+ };
+
+ Self {
+ libname,
+ suggest_name: suggested_name
+ .map(|suggested_name| SuggestLibraryName { suggested_name }),
+ }
+ }
+}
+
+#[derive(Subdiagnostic)]
+#[help(metadata_only_provide_library_name)]
+pub struct SuggestLibraryName<'a> {
+ suggested_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::failed_create_tempdir)]
+#[derive(Diagnostic)]
+#[diag(metadata_failed_create_tempdir)]
pub struct FailedCreateTempdir {
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::failed_create_file)]
+#[derive(Diagnostic)]
+#[diag(metadata_failed_create_file)]
pub struct FailedCreateFile<'a> {
pub filename: &'a Path,
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::failed_create_encoded_metadata)]
+#[derive(Diagnostic)]
+#[diag(metadata_failed_create_encoded_metadata)]
pub struct FailedCreateEncodedMetadata {
pub err: Error,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::non_ascii_name)]
+#[derive(Diagnostic)]
+#[diag(metadata_non_ascii_name)]
pub struct NonAsciiName {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::extern_location_not_exist)]
+#[derive(Diagnostic)]
+#[diag(metadata_extern_location_not_exist)]
pub struct ExternLocationNotExist<'a> {
#[primary_span]
pub span: Span,
@@ -411,8 +445,8 @@ pub struct ExternLocationNotExist<'a> {
pub location: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::extern_location_not_file)]
+#[derive(Diagnostic)]
+#[diag(metadata_extern_location_not_file)]
pub struct ExternLocationNotFile<'a> {
#[primary_span]
pub span: Span,
@@ -427,12 +461,12 @@ pub(crate) struct MultipleCandidates {
pub candidates: Vec<PathBuf>,
}
-impl SessionDiagnostic<'_> for MultipleCandidates {
+impl IntoDiagnostic<'_> for MultipleCandidates {
fn into_diagnostic(
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(rustc_errors::fluent::metadata_multiple_candidates);
diag.set_arg("crate_name", self.crate_name);
diag.set_arg("flavor", self.flavor);
diag.code(error_code!(E0465));
@@ -444,8 +478,8 @@ impl SessionDiagnostic<'_> for MultipleCandidates {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_matching_crates, code = "E0464")]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_matching_crates, code = "E0464")]
#[note]
pub struct MultipleMatchingCrates {
#[primary_span]
@@ -454,24 +488,24 @@ pub struct MultipleMatchingCrates {
pub candidates: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::symbol_conflicts_current, code = "E0519")]
+#[derive(Diagnostic)]
+#[diag(metadata_symbol_conflicts_current, code = "E0519")]
pub struct SymbolConflictsCurrent {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::symbol_conflicts_others, code = "E0523")]
+#[derive(Diagnostic)]
+#[diag(metadata_symbol_conflicts_others, code = "E0523")]
pub struct SymbolConflictsOthers {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::stable_crate_id_collision)]
+#[derive(Diagnostic)]
+#[diag(metadata_stable_crate_id_collision)]
pub struct StableCrateIdCollision {
#[primary_span]
pub span: Span,
@@ -479,18 +513,18 @@ pub struct StableCrateIdCollision {
pub crate_name1: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::dl_error)]
+#[derive(Diagnostic)]
+#[diag(metadata_dl_error)]
pub struct DlError {
#[primary_span]
pub span: Span,
pub err: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::newer_crate_version, code = "E0460")]
+#[derive(Diagnostic)]
+#[diag(metadata_newer_crate_version, code = "E0460")]
#[note]
-#[note(metadata::found_crate_versions)]
+#[note(metadata_found_crate_versions)]
pub struct NewerCrateVersion {
#[primary_span]
pub span: Span,
@@ -499,9 +533,9 @@ pub struct NewerCrateVersion {
pub found_crates: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_crate_with_triple, code = "E0461")]
-#[note(metadata::found_crate_versions)]
+#[derive(Diagnostic)]
+#[diag(metadata_no_crate_with_triple, code = "E0461")]
+#[note(metadata_found_crate_versions)]
pub struct NoCrateWithTriple<'a> {
#[primary_span]
pub span: Span,
@@ -511,9 +545,9 @@ pub struct NoCrateWithTriple<'a> {
pub found_crates: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::found_staticlib, code = "E0462")]
-#[note(metadata::found_crate_versions)]
+#[derive(Diagnostic)]
+#[diag(metadata_found_staticlib, code = "E0462")]
+#[note(metadata_found_crate_versions)]
#[help]
pub struct FoundStaticlib {
#[primary_span]
@@ -523,9 +557,9 @@ pub struct FoundStaticlib {
pub found_crates: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::incompatible_rustc, code = "E0514")]
-#[note(metadata::found_crate_versions)]
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_rustc, code = "E0514")]
+#[note(metadata_found_crate_versions)]
#[help]
pub struct IncompatibleRustc {
#[primary_span]
@@ -543,12 +577,12 @@ pub struct InvalidMetadataFiles {
pub crate_rejections: Vec<String>,
}
-impl SessionDiagnostic<'_> for InvalidMetadataFiles {
+impl IntoDiagnostic<'_> for InvalidMetadataFiles {
fn into_diagnostic(
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(rustc_errors::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));
@@ -571,12 +605,12 @@ pub struct CannotFindCrate {
pub locator_triple: TargetTriple,
}
-impl SessionDiagnostic<'_> for CannotFindCrate {
+impl IntoDiagnostic<'_> for CannotFindCrate {
fn into_diagnostic(
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(rustc_errors::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);
@@ -587,54 +621,54 @@ impl SessionDiagnostic<'_> 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(rustc_errors::fluent::metadata_target_not_installed);
} else {
- diag.note(rustc_errors::fluent::metadata::target_no_std_support);
+ diag.note(rustc_errors::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(rustc_errors::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(rustc_errors::fluent::metadata_std_required);
}
if self.is_nightly_build {
- diag.help(rustc_errors::fluent::metadata::consider_building_std);
+ diag.help(rustc_errors::fluent::metadata_consider_building_std);
}
} else if self.crate_name == self.profiler_runtime {
- diag.note(rustc_errors::fluent::metadata::compiler_missing_profiler);
+ diag.note(rustc_errors::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(rustc_errors::fluent::metadata_install_missing_components);
}
- diag.span_label(self.span, rustc_errors::fluent::metadata::cant_find_crate);
+ diag.span_label(self.span, rustc_errors::fluent::metadata_cant_find_crate);
diag
}
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::no_dylib_plugin, code = "E0457")]
+#[derive(Diagnostic)]
+#[diag(metadata_no_dylib_plugin, code = "E0457")]
pub struct NoDylibPlugin {
#[primary_span]
pub span: Span,
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::crate_location_unknown_type)]
+#[derive(Diagnostic)]
+#[diag(metadata_crate_location_unknown_type)]
pub struct CrateLocationUnknownType<'a> {
#[primary_span]
pub span: Span,
pub path: &'a Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::lib_filename_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_lib_filename_form)]
pub struct LibFilenameForm<'a> {
#[primary_span]
pub span: Span,
@@ -642,37 +676,37 @@ pub struct LibFilenameForm<'a> {
pub dll_suffix: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::multiple_import_name_type)]
+#[derive(Diagnostic)]
+#[diag(metadata_multiple_import_name_type)]
pub struct MultipleImportNameType {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::import_name_type_form)]
+#[derive(Diagnostic)]
+#[diag(metadata_import_name_type_form)]
pub struct ImportNameTypeForm {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::import_name_type_x86)]
+#[derive(Diagnostic)]
+#[diag(metadata_import_name_type_x86)]
pub struct ImportNameTypeX86 {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::unknown_import_name_type)]
+#[derive(Diagnostic)]
+#[diag(metadata_unknown_import_name_type)]
pub struct UnknownImportNameType<'a> {
#[primary_span]
pub span: Span,
pub import_name_type: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(metadata::import_name_type_raw)]
+#[derive(Diagnostic)]
+#[diag(metadata_import_name_type_raw)]
pub struct ImportNameTypeRaw {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_metadata/src/foreign_modules.rs b/compiler/rustc_metadata/src/foreign_modules.rs
index 2ca4cd17f..d1c2f3104 100644
--- a/compiler/rustc_metadata/src/foreign_modules.rs
+++ b/compiler/rustc_metadata/src/foreign_modules.rs
@@ -6,13 +6,13 @@ use rustc_session::cstore::ForeignModule;
pub(crate) fn collect(tcx: TyCtxt<'_>) -> Vec<ForeignModule> {
let mut modules = Vec::new();
for id in tcx.hir().items() {
- if !matches!(tcx.def_kind(id.def_id), DefKind::ForeignMod) {
+ if !matches!(tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
continue;
}
let item = tcx.hir().item(id);
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
- let foreign_items = items.iter().map(|it| it.id.def_id.to_def_id()).collect();
- modules.push(ForeignModule { foreign_items, def_id: id.def_id.to_def_id() });
+ let foreign_items = items.iter().map(|it| it.id.owner_id.to_def_id()).collect();
+ modules.push(ForeignModule { foreign_items, def_id: id.owner_id.to_def_id() });
}
}
modules
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 6f5604b7e..98cf6fef5 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -2,10 +2,8 @@
#![feature(decl_macro)]
#![feature(drain_filter)]
#![feature(generators)]
-#![cfg_attr(bootstrap, feature(generic_associated_types))]
#![feature(iter_from_generator)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(once_cell)]
#![feature(proc_macro_internals)]
#![feature(macro_metavar_expr)]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 257741c13..20a2e7829 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -33,29 +33,26 @@ pub fn find_native_static_library(
search_paths: &[PathBuf],
sess: &Session,
) -> PathBuf {
- let verbatim = verbatim.unwrap_or(false);
- // On Windows, static libraries sometimes show up as libfoo.a and other
- // times show up as foo.lib
- let oslibname = if verbatim {
- name.to_string()
+ let formats = if verbatim.unwrap_or(false) {
+ vec![("".into(), "".into())]
} else {
- format!("{}{}{}", sess.target.staticlib_prefix, name, sess.target.staticlib_suffix)
+ let os = (sess.target.staticlib_prefix.clone(), sess.target.staticlib_suffix.clone());
+ // On Windows, static libraries sometimes show up as libfoo.a and other
+ // times show up as foo.lib
+ let unix = ("lib".into(), ".a".into());
+ if os == unix { vec![os] } else { vec![os, unix] }
};
- let unixlibname = format!("lib{}.a", name);
for path in search_paths {
- let test = path.join(&oslibname);
- if test.exists() {
- return test;
- }
- if oslibname != unixlibname {
- let test = path.join(&unixlibname);
+ for (prefix, suffix) in &formats {
+ let test = path.join(format!("{}{}{}", prefix, name, suffix));
if test.exists() {
return test;
}
}
}
- sess.emit_fatal(MissingNativeLibrary { libname: name });
+
+ sess.emit_fatal(MissingNativeLibrary::new(name, verbatim.unwrap_or(false)));
}
fn find_bundled_library(
@@ -101,7 +98,7 @@ struct Collector<'tcx> {
impl<'tcx> Collector<'tcx> {
fn process_item(&mut self, id: rustc_hir::ItemId) {
- if !matches!(self.tcx.def_kind(id.def_id), DefKind::ForeignMod) {
+ if !matches!(self.tcx.def_kind(id.owner_id), DefKind::ForeignMod) {
return;
}
@@ -375,17 +372,17 @@ impl<'tcx> Collector<'tcx> {
}
_ => {
for child_item in foreign_mod_items {
- if self.tcx.def_kind(child_item.id.def_id).has_codegen_attrs()
+ if self.tcx.def_kind(child_item.id.owner_id).has_codegen_attrs()
&& self
.tcx
- .codegen_fn_attrs(child_item.id.def_id)
+ .codegen_fn_attrs(child_item.id.owner_id)
.link_ordinal
.is_some()
{
let link_ordinal_attr = self
.tcx
.hir()
- .attrs(self.tcx.hir().local_def_id_to_hir_id(child_item.id.def_id))
+ .attrs(child_item.id.owner_id.into())
.iter()
.find(|a| a.has_name(sym::link_ordinal))
.unwrap();
@@ -405,7 +402,7 @@ impl<'tcx> Collector<'tcx> {
filename,
kind,
cfg,
- foreign_module: Some(it.def_id.to_def_id()),
+ foreign_module: Some(it.owner_id.to_def_id()),
wasm_import_module: wasm_import_module.map(|(name, _)| name),
verbatim,
dll_imports,
@@ -508,7 +505,7 @@ impl<'tcx> Collector<'tcx> {
fn i686_arg_list_size(&self, item: &hir::ForeignItemRef) -> usize {
let argument_types: &List<Ty<'_>> = self.tcx.erase_late_bound_regions(
self.tcx
- .type_of(item.id.def_id)
+ .type_of(item.id.owner_id)
.fn_sig(self.tcx)
.inputs()
.map_bound(|slice| self.tcx.mk_type_list(slice.iter())),
@@ -560,7 +557,7 @@ impl<'tcx> Collector<'tcx> {
}
};
- let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.def_id);
+ let codegen_fn_attrs = self.tcx.codegen_fn_attrs(item.id.owner_id);
let import_name_type = codegen_fn_attrs
.link_ordinal
.map_or(import_name_type, |ord| Some(PeImportNameType::Ordinal(ord)));
@@ -570,7 +567,7 @@ impl<'tcx> Collector<'tcx> {
import_name_type,
calling_convention,
span: item.span,
- is_fn: self.tcx.def_kind(item.id.def_id).is_fn_like(),
+ is_fn: self.tcx.def_kind(item.id.owner_id).is_fn_like(),
}
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 830417eea..691e3d0f8 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> {
- self.def_key(item_index).disambiguated_data.data.get_opt_name()
+ let def_key = self.def_key(item_index);
+ def_key.disambiguated_data.data.get_opt_name().or_else(|| {
+ if def_key.disambiguated_data.data == DefPathData::Ctor {
+ let parent_index = def_key.parent.expect("no parent for a constructor");
+ self.def_key(parent_index).disambiguated_data.data.get_opt_name()
+ } else {
+ None
+ }
+ })
}
fn item_name(self, item_index: DefIndex) -> Symbol {
@@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.get(self, item_id)
.unwrap_or_else(LazyArray::empty)
.decode(self)
- .map(|index| self.get_variant(&self.def_kind(index), index, did))
+ .filter_map(|index| {
+ let kind = self.def_kind(index);
+ match kind {
+ DefKind::Ctor(..) => None,
+ _ => Some(self.get_variant(&kind, index, did)),
+ }
+ })
.collect()
} else {
std::iter::once(self.get_variant(&kind, item_id, did)).collect()
@@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
callback(ModChild { ident, res, vis, span, macro_rules });
- // For non-re-export structs and variants add their constructors to children.
- // Re-export lists automatically contain constructors when necessary.
- match kind {
- DefKind::Struct => {
- if let Some((ctor_def_id, ctor_kind)) =
- self.get_ctor_def_id_and_kind(child_index)
- {
- let ctor_res =
- Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
- let vis = self.get_visibility(ctor_def_id.index);
- callback(ModChild {
- ident,
- res: ctor_res,
- vis,
- span,
- macro_rules: false,
- });
- }
- }
- DefKind::Variant => {
- // Braced variants, unlike structs, generate unusable names in
- // value namespace, they are reserved for possible future use.
- // It's ok to use the variant's id as a ctor id since an
- // error will be reported on any use of such resolution anyway.
- let (ctor_def_id, ctor_kind) = self
- .get_ctor_def_id_and_kind(child_index)
- .unwrap_or((def_id, CtorKind::Fictive));
- let ctor_res =
- Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
- let mut vis = self.get_visibility(ctor_def_id.index);
- if ctor_def_id == def_id && vis.is_public() {
- // For non-exhaustive variants lower the constructor visibility to
- // within the crate. We only need this for fictive constructors,
- // for other constructors correct visibilities
- // were already encoded in metadata.
- let mut attrs = self.get_item_attrs(def_id.index, sess);
- if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
- let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
- vis = ty::Visibility::Restricted(crate_def_id);
- }
+ // For non-reexport variants add their fictive constructors to children.
+ // Braced variants, unlike structs, generate unusable names in value namespace,
+ // they are reserved for possible future use. It's ok to use the variant's id as
+ // a ctor id since an error will be reported on any use of such resolution anyway.
+ // Reexport lists automatically contain such constructors when necessary.
+ if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none()
+ {
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id);
+ let mut vis = vis;
+ if vis.is_public() {
+ // For non-exhaustive variants lower the constructor visibility to
+ // within the crate. We only need this for fictive constructors,
+ // for other constructors correct visibilities
+ // were already encoded in metadata.
+ let mut attrs = self.get_item_attrs(def_id.index, sess);
+ if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
+ vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX));
}
- callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
}
- _ => {}
+ callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
}
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index dede1b212..a0a085525 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -15,7 +15,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_session::cstore::{CrateSource, CrateStore};
-use rustc_session::utils::NativeLibKind;
use rustc_session::{Session, StableCrateId};
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::source_map::{Span, Spanned};
@@ -210,6 +209,7 @@ provide! { tcx, def_id, other, cdata,
lookup_const_stability => { table }
lookup_default_body_stability => { table }
lookup_deprecation_entry => { table }
+ params_in_repr => { table }
unused_generic_params => { table }
opt_def_kind => { table_direct }
impl_parent => { table }
@@ -223,6 +223,16 @@ provide! { tcx, def_id, other, cdata,
fn_arg_names => { table }
generator_kind => { table }
trait_def => { table }
+ deduced_param_attrs => { table }
+ collect_trait_impl_trait_tys => {
+ Ok(cdata
+ .root
+ .tables
+ .trait_impl_trait_tys
+ .get(cdata, def_id.index)
+ .map(|lazy| lazy.decode((cdata, tcx)))
+ .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id)))
+ }
visibility => { cdata.get_visibility(def_id.index) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
@@ -329,20 +339,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
// resolve! Does this work? Unsure! That's what the issue is about
*providers = Providers {
allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
- is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
- Some(
- NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified,
- ) => true,
- _ => false,
- },
- is_statically_included_foreign_item: |tcx, id| {
- matches!(tcx.native_library_kind(id), Some(NativeLibKind::Static { .. }))
- },
is_private_dep: |_tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
false
},
- native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind),
native_library: |tcx, id| {
tcx.native_libraries(id.krate)
.iter()
@@ -587,11 +587,6 @@ impl CStore {
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
}
- /// Decodes all traits in the crate (for rustdoc).
- pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
- self.get_crate_data(cnum).get_traits()
- }
-
/// Decodes all trait impls in the crate (for rustdoc).
pub fn trait_impls_in_crate_untracked(
&self,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 5a60ea794..049514ec7 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -3,6 +3,7 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::TableBuilder;
use crate::rmeta::*;
+use rustc_ast::Attribute;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
@@ -28,8 +29,9 @@ use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
+use rustc_middle::util::common::to_readable_str;
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
-use rustc_session::config::CrateType;
+use rustc_session::config::{CrateType, OptLevel};
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
use rustc_span::symbol::{sym, Symbol};
@@ -261,10 +263,10 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
// This allows us to avoid loading the dependencies of proc-macro crates: all of
// the information we need to decode `Span`s is stored in the proc-macro crate.
let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
- // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
- // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
- // are relative to the source map information for the 'foreign' crate whose CrateNum
- // we write into the metadata. This allows `imported_source_files` to binary
+ // To simplify deserialization, we 'rebase' this span onto the crate it originally came
+ // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
+ // values are relative to the source map information for the 'foreign' crate whose
+ // CrateNum we write into the metadata. This allows `imported_source_files` to binary
// search through the 'foreign' crate's source map information, using the
// deserialized 'lo' and 'hi' values directly.
//
@@ -554,78 +556,56 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
let tcx = self.tcx;
- let mut i = 0;
- let preamble_bytes = self.position() - i;
-
- // Encode the crate deps
- i = self.position();
- let crate_deps = self.encode_crate_deps();
- let dylib_dependency_formats = self.encode_dylib_dependency_formats();
- let dep_bytes = self.position() - i;
-
- // Encode the lib features.
- i = self.position();
- let lib_features = self.encode_lib_features();
- let lib_feature_bytes = self.position() - i;
-
- // Encode the stability implications.
- i = self.position();
- let stability_implications = self.encode_stability_implications();
- let stability_implications_bytes = self.position() - i;
-
- // Encode the language items.
- i = self.position();
- let lang_items = self.encode_lang_items();
- let lang_items_missing = self.encode_lang_items_missing();
- let lang_item_bytes = self.position() - i;
-
- // Encode the diagnostic items.
- i = self.position();
- let diagnostic_items = self.encode_diagnostic_items();
- let diagnostic_item_bytes = self.position() - i;
-
- // Encode the native libraries used
- i = self.position();
- let native_libraries = self.encode_native_libraries();
- let native_lib_bytes = self.position() - i;
-
- i = self.position();
- let foreign_modules = self.encode_foreign_modules();
- let foreign_modules_bytes = self.position() - i;
-
- // Encode DefPathTable
- i = self.position();
- self.encode_def_path_table();
- let def_path_table_bytes = self.position() - i;
+ let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
+
+ macro_rules! stat {
+ ($label:literal, $f:expr) => {{
+ let orig_pos = self.position();
+ let res = $f();
+ stats.push(($label, self.position() - orig_pos));
+ res
+ }};
+ }
+
+ // We have already encoded some things. Get their combined size from the current position.
+ stats.push(("preamble", self.position()));
+
+ let (crate_deps, dylib_dependency_formats) =
+ stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
+
+ let lib_features = stat!("lib-features", || self.encode_lib_features());
+
+ let stability_implications =
+ stat!("stability-implications", || self.encode_stability_implications());
+
+ let (lang_items, lang_items_missing) = stat!("lang-items", || {
+ (self.encode_lang_items(), self.encode_lang_items_missing())
+ });
+
+ let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
+
+ let native_libraries = stat!("native-libs", || self.encode_native_libraries());
+
+ let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
+
+ _ = stat!("def-path-table", || self.encode_def_path_table());
// Encode the def IDs of traits, for rustdoc and diagnostics.
- i = self.position();
- let traits = self.encode_traits();
- let traits_bytes = self.position() - i;
+ let traits = stat!("traits", || self.encode_traits());
// Encode the def IDs of impls, for coherence checking.
- i = self.position();
- let impls = self.encode_impls();
- let impls_bytes = self.position() - i;
-
- i = self.position();
- let incoherent_impls = self.encode_incoherent_impls();
- let incoherent_impls_bytes = self.position() - i;
-
- // Encode MIR.
- i = self.position();
- self.encode_mir();
- let mir_bytes = self.position() - i;
-
- // Encode the items.
- i = self.position();
- self.encode_def_ids();
- self.encode_info_for_items();
- let item_bytes = self.position() - i;
-
- // Encode the allocation index
- i = self.position();
- let interpret_alloc_index = {
+ let impls = stat!("impls", || self.encode_impls());
+
+ let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
+
+ _ = stat!("mir", || self.encode_mir());
+
+ _ = stat!("items", || {
+ self.encode_def_ids();
+ self.encode_info_for_items();
+ });
+
+ let interpret_alloc_index = stat!("interpret-alloc-index", || {
let mut interpret_alloc_index = Vec::new();
let mut n = 0;
trace!("beginning to encode alloc ids");
@@ -646,126 +626,90 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
n = new_n;
}
self.lazy_array(interpret_alloc_index)
- };
- let interpret_alloc_index_bytes = self.position() - i;
+ });
- // Encode the proc macro data. This affects 'tables',
- // so we need to do this before we encode the tables.
- // This overwrites def_keys, so it must happen after encode_def_path_table.
- i = self.position();
- let proc_macro_data = self.encode_proc_macros();
- let proc_macro_data_bytes = self.position() - i;
+ // Encode the proc macro data. This affects `tables`, so we need to do this before we
+ // encode the tables. This overwrites def_keys, so it must happen after
+ // encode_def_path_table.
+ let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
- i = self.position();
- let tables = self.tables.encode(&mut self.opaque);
- let tables_bytes = self.position() - i;
+ let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
- i = self.position();
- let debugger_visualizers = self.encode_debugger_visualizers();
- let debugger_visualizers_bytes = self.position() - i;
+ let debugger_visualizers =
+ stat!("debugger-visualizers", || self.encode_debugger_visualizers());
// Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
// this as late as possible to give the prefetching as much time as possible to complete.
- i = self.position();
- let exported_symbols = tcx.exported_symbols(LOCAL_CRATE);
- let exported_symbols = self.encode_exported_symbols(&exported_symbols);
- let exported_symbols_bytes = self.position() - i;
-
- // Encode the hygiene data,
- // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
- // of encoding other items (e.g. `optimized_mir`) may cause us to load
- // data from the incremental cache. If this causes us to deserialize a `Span`,
- // then we may load additional `SyntaxContext`s into the global `HygieneData`.
- // Therefore, we need to encode the hygiene data last to ensure that we encode
- // any `SyntaxContext`s that might be used.
- i = self.position();
- let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
- let hygiene_bytes = self.position() - i;
-
- i = self.position();
- let def_path_hash_map = self.encode_def_path_hash_map();
- let def_path_hash_map_bytes = self.position() - i;
-
- // Encode source_map. This needs to be done last,
- // since encoding `Span`s tells us which `SourceFiles` we actually
- // need to encode.
- i = self.position();
- let source_map = self.encode_source_map();
- let source_map_bytes = self.position() - i;
-
- i = self.position();
- let attrs = tcx.hir().krate_attrs();
- let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
- let root = self.lazy(CrateRoot {
- name: tcx.crate_name(LOCAL_CRATE),
- extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
- triple: tcx.sess.opts.target_triple.clone(),
- hash: tcx.crate_hash(LOCAL_CRATE),
- stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
- required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
- panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
- edition: tcx.sess.edition(),
- has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
- has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
- has_default_lib_allocator,
- proc_macro_data,
- debugger_visualizers,
- compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
- needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
- needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
- no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
- panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
- profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
- symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
-
- crate_deps,
- dylib_dependency_formats,
- lib_features,
- stability_implications,
- lang_items,
- diagnostic_items,
- lang_items_missing,
- native_libraries,
- foreign_modules,
- source_map,
- traits,
- impls,
- incoherent_impls,
- exported_symbols,
- interpret_alloc_index,
- tables,
- syntax_contexts,
- expn_data,
- expn_hashes,
- def_path_hash_map,
+ let exported_symbols = stat!("exported-symbols", || {
+ self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
+ });
+
+ // Encode the hygiene data.
+ // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
+ // process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
+ // the incremental cache. If this causes us to deserialize a `Span`, then we may load
+ // additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
+ // the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
+ let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
+
+ let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
+
+ // Encode source_map. This needs to be done last, because encoding `Span`s tells us which
+ // `SourceFiles` we actually need to encode.
+ let source_map = stat!("source-map", || self.encode_source_map());
+
+ let root = stat!("final", || {
+ let attrs = tcx.hir().krate_attrs();
+ self.lazy(CrateRoot {
+ name: tcx.crate_name(LOCAL_CRATE),
+ extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
+ triple: tcx.sess.opts.target_triple.clone(),
+ hash: tcx.crate_hash(LOCAL_CRATE),
+ stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
+ required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
+ panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+ edition: tcx.sess.edition(),
+ has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
+ has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
+ has_default_lib_allocator: tcx
+ .sess
+ .contains_name(&attrs, sym::default_lib_allocator),
+ proc_macro_data,
+ debugger_visualizers,
+ compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
+ needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
+ needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
+ no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
+ panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
+ profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
+ symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
+
+ crate_deps,
+ dylib_dependency_formats,
+ lib_features,
+ stability_implications,
+ lang_items,
+ diagnostic_items,
+ lang_items_missing,
+ native_libraries,
+ foreign_modules,
+ source_map,
+ traits,
+ impls,
+ incoherent_impls,
+ exported_symbols,
+ interpret_alloc_index,
+ tables,
+ syntax_contexts,
+ expn_data,
+ expn_hashes,
+ def_path_hash_map,
+ })
});
- let final_bytes = self.position() - i;
let total_bytes = self.position();
- let computed_total_bytes = preamble_bytes
- + dep_bytes
- + lib_feature_bytes
- + stability_implications_bytes
- + lang_item_bytes
- + diagnostic_item_bytes
- + native_lib_bytes
- + foreign_modules_bytes
- + def_path_table_bytes
- + traits_bytes
- + impls_bytes
- + incoherent_impls_bytes
- + mir_bytes
- + item_bytes
- + interpret_alloc_index_bytes
- + proc_macro_data_bytes
- + tables_bytes
- + debugger_visualizers_bytes
- + exported_symbols_bytes
- + hygiene_bytes
- + def_path_hash_map_bytes
- + source_map_bytes
- + final_bytes;
+ let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
assert_eq!(total_bytes, computed_total_bytes);
if tcx.sess.meta_stats() {
@@ -783,48 +727,77 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
+ stats.sort_by_key(|&(_, usize)| usize);
+
+ let prefix = "meta-stats";
let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
- let p = |label, bytes| {
- eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
- };
- eprintln!("");
+ eprintln!("{} METADATA STATS", prefix);
+ eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
+ eprintln!(
+ "{} ----------------------------------------------------------------",
+ prefix
+ );
+ for (label, size) in stats {
+ eprintln!(
+ "{} {:<23}{:>10} ({:4.1}%)",
+ prefix,
+ label,
+ to_readable_str(size),
+ perc(size)
+ );
+ }
+ eprintln!(
+ "{} ----------------------------------------------------------------",
+ prefix
+ );
eprintln!(
- "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
- total_bytes,
- zero_bytes,
+ "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
+ prefix,
+ "Total",
+ to_readable_str(total_bytes),
perc(zero_bytes)
);
- p("preamble", preamble_bytes);
- p("dep", dep_bytes);
- p("lib feature", lib_feature_bytes);
- p("stability_implications", stability_implications_bytes);
- p("lang item", lang_item_bytes);
- p("diagnostic item", diagnostic_item_bytes);
- p("native lib", native_lib_bytes);
- p("foreign modules", foreign_modules_bytes);
- p("def-path table", def_path_table_bytes);
- p("traits", traits_bytes);
- p("impls", impls_bytes);
- p("incoherent_impls", incoherent_impls_bytes);
- p("mir", mir_bytes);
- p("item", item_bytes);
- p("interpret_alloc_index", interpret_alloc_index_bytes);
- p("proc-macro-data", proc_macro_data_bytes);
- p("tables", tables_bytes);
- p("debugger visualizers", debugger_visualizers_bytes);
- p("exported symbols", exported_symbols_bytes);
- p("hygiene", hygiene_bytes);
- p("def-path hashes", def_path_hash_map_bytes);
- p("source_map", source_map_bytes);
- p("final", final_bytes);
- eprintln!("");
+ eprintln!("{}", prefix);
}
root
}
}
+/// 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
+/// 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 {
+ 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(()).effective_vis(def_id).is_some())
+ } 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)
+ } else {
+ true
+ }
+}
+
fn should_encode_visibility(def_kind: DefKind) -> bool {
match def_kind {
DefKind::Mod
@@ -1120,14 +1093,44 @@ fn should_encode_const(def_kind: DefKind) -> bool {
}
}
+fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, 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;
+ }
+
+ 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::Projection(data) = ty.kind()
+ && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ {
+ true
+ } else {
+ false
+ }
+ })
+}
+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_attrs(&mut self, def_id: LocalDefId) {
- let mut attrs = self
- .tcx
+ let tcx = self.tcx;
+ let mut is_public: Option<bool> = None;
+
+ let mut attrs = tcx
.hir()
- .attrs(self.tcx.hir().local_def_id_to_hir_id(def_id))
+ .attrs(tcx.hir().local_def_id_to_hir_id(def_id))
.iter()
- .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty()));
+ .filter(move |attr| should_encode_attr(tcx, attr, def_id, &mut is_public));
record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
if attrs.any(|attr| attr.may_have_doc_links()) {
@@ -1189,6 +1192,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
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);
+ }
+ if should_encode_trait_impl_trait_tys(tcx, def_id)
+ && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id)
+ {
+ record!(self.tables.trait_impl_trait_tys[def_id] <- table);
+ }
}
let inherent_impls = tcx.crate_inherent_impls(());
for (def_id, implementations) in inherent_impls.inherent_impls.iter() {
@@ -1278,14 +1290,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// from name resolution point of view.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- yield foreign_item.id.def_id.local_def_index;
+ yield foreign_item.id.owner_id.def_id.local_def_index;
}
}
// Only encode named non-reexport children, reexports are encoded
// separately and unnamed items are not used by name resolution.
hir::ItemKind::ExternCrate(..) => continue,
- _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => {
- yield item_id.def_id.local_def_index;
+ 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 tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
+ yield item_id.owner_id.def_id.local_def_index;
}
_ => continue,
}
@@ -1436,6 +1455,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
}
}
+
+ // Encode all the deduced parameter attributes for everything that has MIR, even for items
+ // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to
+ // save the query traffic.
+ if tcx.sess.opts.output_types.should_codegen()
+ && tcx.sess.opts.optimize != OptLevel::No
+ && tcx.sess.opts.incremental.is_none()
+ {
+ for &local_def_id in tcx.mir_keys(()) {
+ if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) {
+ record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <-
+ self.tcx.deduced_param_attrs(local_def_id.to_def_id()));
+ }
+ }
+ }
}
fn encode_stability(&mut self, def_id: DefId) {
@@ -1507,7 +1541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
}
hir::ItemKind::Mod(ref m) => {
- return self.encode_info_for_mod(item.def_id, m);
+ return self.encode_info_for_mod(item.owner_id.def_id, m);
}
hir::ItemKind::OpaqueTy(..) => {
self.encode_explicit_item_bounds(def_id);
@@ -1592,12 +1626,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
};
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
- hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <-
- self.tcx.adt_def(def_id).variants().iter().map(|v| {
- assert!(v.def_id.is_local());
- v.def_id.index
- })
- ),
+ 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| {
@@ -1634,7 +1673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// normally in the visitor walk.
match item.kind {
hir::ItemKind::Enum(..) => {
- let def = self.tcx.adt_def(item.def_id.to_def_id());
+ let def = self.tcx.adt_def(item.owner_id.to_def_id());
for (i, variant) in def.variants().iter_enumerated() {
self.encode_enum_variant_info(def, i);
@@ -1644,7 +1683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
hir::ItemKind::Struct(ref struct_def, _) => {
- let def = self.tcx.adt_def(item.def_id.to_def_id());
+ let def = self.tcx.adt_def(item.owner_id.to_def_id());
// If the struct has a constructor, encode it.
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
@@ -1653,13 +1692,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemKind::Impl { .. } => {
for &trait_item_def_id in
- self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+ self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
{
self.encode_info_for_impl_item(trait_item_def_id);
}
}
hir::ItemKind::Trait(..) => {
- for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+ for &item_def_id in
+ self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
{
self.encode_info_for_trait_item(item_def_id);
}
@@ -1900,8 +1940,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
FxHashMap::default();
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
- if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
@@ -1911,7 +1951,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fx_hash_map
.entry(trait_ref.def_id)
.or_default()
- .push((id.def_id.local_def_index, simplified_self_ty));
+ .push((id.owner_id.def_id.local_def_index, simplified_self_ty));
}
}
}
@@ -2052,12 +2092,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> {
intravisit::walk_item(self, item);
match item.kind {
hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
- _ => self.encode_info_for_item(item.def_id.to_def_id(), item),
+ _ => self.encode_info_for_item(item.owner_id.to_def_id(), item),
}
}
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
intravisit::walk_foreign_item(self, ni);
- self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni);
+ self.encode_info_for_foreign_item(ni.owner_id.to_def_id(), ni);
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
intravisit::walk_generics(self, generics);
@@ -2276,8 +2316,8 @@ pub fn provide(providers: &mut Providers) {
let mut traits = Vec::new();
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Trait | DefKind::TraitAlias) {
- traits.push(id.def_id.to_def_id())
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
+ traits.push(id.owner_id.to_def_id())
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 748b3afec..27dc8ff16 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -1,6 +1,7 @@
use crate::creader::CrateMetadataRef;
use decoder::Metadata;
use def_path_hash_map::DefPathHashMapRef;
+use rustc_data_structures::fx::FxHashMap;
use table::TableBuilder;
use rustc_ast as ast;
@@ -12,7 +13,8 @@ use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items;
-use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
+use rustc_index::bit_set::{BitSet, FiniteBitSet};
+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};
@@ -21,7 +23,7 @@ use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ReprOptions, Ty};
-use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
+use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
use rustc_serialize::opaque::FileEncoder;
use rustc_session::config::SymbolManglingVersion;
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@@ -382,6 +384,7 @@ define_tables! {
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>,
+ params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
// `def_keys` and `def_path_hashes` represent a lazy version of a
// `DefPathTable`. This allows us to avoid deserializing an entire
@@ -399,6 +402,9 @@ define_tables! {
macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>,
proc_macro: Table<DefIndex, MacroKind>,
module_reexports: Table<DefIndex, LazyArray<ModChild>>,
+ deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
+
+ trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
}
#[derive(TyEncodable, TyDecodable)]
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index cca17a4ec..de916ea8c 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -12,8 +12,6 @@ chalk-ir = "0.80.0"
either = "1.5.0"
gsgdt = "0.1.2"
polonius-engine = "0.13.0"
-rand = "0.8.4"
-rand_xoshiro = "0.6.0"
rustc_apfloat = { path = "../rustc_apfloat" }
rustc_arena = { path = "../rustc_arena" }
rustc_ast = { path = "../rustc_ast" }
diff --git a/compiler/rustc_middle/benches/lib.rs b/compiler/rustc_middle/benches/lib.rs
deleted file mode 100644
index 237751bcb..000000000
--- a/compiler/rustc_middle/benches/lib.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-#![feature(test)]
-
-extern crate test;
-
-use test::Bencher;
-
-// Static/dynamic method dispatch
-
-struct Struct {
- field: isize,
-}
-
-trait Trait {
- fn method(&self) -> isize;
-}
-
-impl Trait for Struct {
- fn method(&self) -> isize {
- self.field
- }
-}
-
-#[bench]
-fn trait_vtable_method_call(b: &mut Bencher) {
- let s = Struct { field: 10 };
- let t = &s as &dyn Trait;
- b.iter(|| t.method());
-}
-
-#[bench]
-fn trait_static_method_call(b: &mut Bencher) {
- let s = Struct { field: 10 };
- b.iter(|| s.method());
-}
-
-// Overhead of various match forms
-
-#[bench]
-fn option_some(b: &mut Bencher) {
- let x = Some(10);
- b.iter(|| match x {
- Some(y) => y,
- None => 11,
- });
-}
-
-#[bench]
-fn vec_pattern(b: &mut Bencher) {
- let x = [1, 2, 3, 4, 5, 6];
- b.iter(|| match x {
- [1, 2, 3, ..] => 10,
- _ => 11,
- });
-}
diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs
index 6bdf5a023..f8aae86fe 100644
--- a/compiler/rustc_middle/src/arena.rs
+++ b/compiler/rustc_middle/src/arena.rs
@@ -77,7 +77,7 @@ macro_rules! arena_types {
rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
>,
[] all_traits: Vec<rustc_hir::def_id::DefId>,
- [] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
+ [] effective_visibilities: rustc_middle::middle::privacy::EffectiveVisibilities,
[] foreign_module: rustc_session::cstore::ForeignModule,
[] foreign_modules: Vec<rustc_session::cstore::ForeignModule>,
[] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
@@ -96,13 +96,14 @@ macro_rules! arena_types {
// since we need to allocate this type on both the `rustc_hir` arena
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
[decode] asm_template: rustc_ast::InlineAsmTemplatePiece,
- [decode] used_trait_imports: rustc_data_structures::fx::FxHashSet<rustc_hir::def_id::LocalDefId>,
+ [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] 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>,
]);
)
}
diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs
index 1fa0c6bab..6b5568269 100644
--- a/compiler/rustc_middle/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs
@@ -62,86 +62,13 @@ use crate::ty::TyCtxt;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::definitions::DefPathHash;
-use rustc_hir::HirId;
+use rustc_hir::{HirId, ItemLocalId, OwnerId};
use rustc_query_system::dep_graph::FingerprintStyle;
use rustc_span::symbol::Symbol;
use std::hash::Hash;
pub use rustc_query_system::dep_graph::{DepContext, DepNodeParams};
-/// This struct stores metadata about each DepKind.
-///
-/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
-/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
-/// jump table instead of large matches.
-pub struct DepKindStruct<'tcx> {
- /// Anonymous queries cannot be replayed from one compiler invocation to the next.
- /// When their result is needed, it is recomputed. They are useful for fine-grained
- /// dependency tracking, and caching within one compiler invocation.
- pub is_anon: bool,
-
- /// Eval-always queries do not track their dependencies, and are always recomputed, even if
- /// their inputs have not changed since the last compiler invocation. The result is still
- /// cached within one compiler invocation.
- pub is_eval_always: bool,
-
- /// Whether the query key can be recovered from the hashed fingerprint.
- /// See [DepNodeParams] trait for the behaviour of each key type.
- pub fingerprint_style: FingerprintStyle,
-
- /// The red/green evaluation system will try to mark a specific DepNode in the
- /// dependency graph as green by recursively trying to mark the dependencies of
- /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
- /// where we don't know if it is red or green and we therefore actually have
- /// to recompute its value in order to find out. Since the only piece of
- /// information that we have at that point is the `DepNode` we are trying to
- /// re-evaluate, we need some way to re-run a query from just that. This is what
- /// `force_from_dep_node()` implements.
- ///
- /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
- /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
- /// is usually constructed by computing a stable hash of the query-key that the
- /// `DepNode` corresponds to. Consequently, it is not in general possible to go
- /// back from hash to query-key (since hash functions are not reversible). For
- /// this reason `force_from_dep_node()` is expected to fail from time to time
- /// because we just cannot find out, from the `DepNode` alone, what the
- /// corresponding query-key is and therefore cannot re-run the query.
- ///
- /// The system deals with this case letting `try_mark_green` fail which forces
- /// the root query to be re-evaluated.
- ///
- /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
- /// Fortunately, we can use some contextual information that will allow us to
- /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
- /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
- /// valid `DefPathHash`. Since we also always build a huge table that maps every
- /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
- /// everything we need to re-run the query.
- ///
- /// Take the `mir_promoted` query as an example. Like many other queries, it
- /// just has a single parameter: the `DefId` of the item it will compute the
- /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
- /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
- /// is actually a `DefPathHash`, and can therefore just look up the corresponding
- /// `DefId` in `tcx.def_path_hash_to_def_id`.
- pub force_from_dep_node: Option<fn(tcx: TyCtxt<'tcx>, dep_node: DepNode) -> bool>,
-
- /// Invoke a query to put the on-disk cached value in memory.
- pub try_load_from_on_disk_cache: Option<fn(TyCtxt<'tcx>, DepNode)>,
-}
-
-impl DepKind {
- #[inline(always)]
- pub fn fingerprint_style(self, tcx: TyCtxt<'_>) -> FingerprintStyle {
- // Only fetch the DepKindStruct once.
- let data = tcx.query_kind(self);
- if data.is_anon {
- return FingerprintStyle::Opaque;
- }
- data.fingerprint_style
- }
-}
-
macro_rules! define_dep_nodes {
(
$($(#[$attr:meta])*
@@ -159,7 +86,7 @@ macro_rules! define_dep_nodes {
$( $( #[$attr] )* $variant),*
}
- fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
+ pub(super) fn dep_kind_from_label_string(label: &str) -> Result<DepKind, ()> {
match label {
$(stringify!($variant) => Ok(DepKind::$variant),)*
_ => Err(()),
@@ -214,11 +141,6 @@ static_assert_size!(DepNode, 18);
static_assert_size!(DepNode, 24);
pub trait DepNodeExt: Sized {
- /// Construct a DepNode from the given DepKind and DefPathHash. This
- /// method will assert that the given DepKind actually requires a
- /// single DefId/DefPathHash parameter.
- fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> Self;
-
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
///
@@ -243,14 +165,6 @@ pub trait DepNodeExt: Sized {
}
impl DepNodeExt for DepNode {
- /// Construct a DepNode from the given DepKind and DefPathHash. This
- /// method will assert that the given DepKind actually requires a
- /// single DefId/DefPathHash parameter.
- fn from_def_path_hash(tcx: TyCtxt<'_>, def_path_hash: DefPathHash, kind: DepKind) -> DepNode {
- debug_assert!(kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash);
- DepNode { kind, hash: def_path_hash.0.into() }
- }
-
/// Extracts the DefId corresponding to this DepNode. This will work
/// if two conditions are met:
///
@@ -262,7 +176,7 @@ impl DepNodeExt for DepNode {
/// refers to something from the previous compilation session that
/// has been removed.
fn extract_def_id<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<DefId> {
- if self.kind.fingerprint_style(tcx) == FingerprintStyle::DefPathHash {
+ if tcx.fingerprint_style(self.kind) == FingerprintStyle::DefPathHash {
Some(tcx.def_path_hash_to_def_id(DefPathHash(self.hash.into()), &mut || {
panic!("Failed to extract DefId: {:?} {}", self.kind, self.hash)
}))
@@ -279,8 +193,8 @@ impl DepNodeExt for DepNode {
) -> Result<DepNode, ()> {
let kind = dep_kind_from_label_string(label)?;
- match kind.fingerprint_style(tcx) {
- FingerprintStyle::Opaque => Err(()),
+ match tcx.fingerprint_style(kind) {
+ FingerprintStyle::Opaque | FingerprintStyle::HirId => Err(()),
FingerprintStyle::Unit => Ok(DepNode::new_no_params(tcx, kind)),
FingerprintStyle::DefPathHash => {
Ok(DepNode::from_def_path_hash(tcx, def_path_hash, kind))
@@ -355,6 +269,28 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
}
}
+impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for OwnerId {
+ #[inline(always)]
+ fn fingerprint_style() -> FingerprintStyle {
+ FingerprintStyle::DefPathHash
+ }
+
+ #[inline(always)]
+ fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
+ self.to_def_id().to_fingerprint(tcx)
+ }
+
+ #[inline(always)]
+ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
+ self.to_def_id().to_debug_str(tcx)
+ }
+
+ #[inline(always)]
+ fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+ dep_node.extract_def_id(tcx).map(|id| OwnerId { def_id: id.expect_local() })
+ }
+}
+
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
@@ -408,7 +344,7 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
#[inline(always)]
fn fingerprint_style() -> FingerprintStyle {
- FingerprintStyle::Opaque
+ FingerprintStyle::HirId
}
// We actually would not need to specialize the implementation of this
@@ -417,10 +353,36 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
#[inline(always)]
fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
let HirId { owner, local_id } = *self;
-
let def_path_hash = tcx.def_path_hash(owner.to_def_id());
- let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into());
+ Fingerprint::new(
+ // `owner` is local, so is completely defined by the local hash
+ def_path_hash.local_hash(),
+ local_id.as_u32().into(),
+ )
+ }
+
+ #[inline(always)]
+ fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String {
+ let HirId { owner, local_id } = *self;
+ format!("{}.{}", tcx.def_path_str(owner.to_def_id()), local_id.as_u32())
+ }
- def_path_hash.0.combine(local_id)
+ #[inline(always)]
+ fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option<Self> {
+ if tcx.fingerprint_style(dep_node.kind) == FingerprintStyle::HirId {
+ let (local_hash, local_id) = Fingerprint::from(dep_node.hash).as_value();
+ let def_path_hash = DefPathHash::new(tcx.sess.local_stable_crate_id(), local_hash);
+ let def_id = tcx
+ .def_path_hash_to_def_id(def_path_hash, &mut || {
+ panic!("Failed to extract HirId: {:?} {}", dep_node.kind, dep_node.hash)
+ })
+ .expect_local();
+ let local_id = local_id
+ .try_into()
+ .unwrap_or_else(|_| panic!("local id should be u32, found {:?}", local_id));
+ Some(HirId { owner: OwnerId { def_id }, local_id: ItemLocalId::from_u32(local_id) })
+ } else {
+ None
+ }
}
}
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index c8b3b52b0..2e62bebc8 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -11,15 +11,17 @@ pub use rustc_query_system::dep_graph::{
SerializedDepNodeIndex, WorkProduct, WorkProductId,
};
-pub use dep_node::{label_strs, DepKind, DepKindStruct, DepNode, DepNodeExt};
+pub use dep_node::{label_strs, DepKind, DepNode, DepNodeExt};
pub(crate) use dep_node::{make_compile_codegen_unit, make_compile_mono_item};
pub type DepGraph = rustc_query_system::dep_graph::DepGraph<DepKind>;
+
pub type TaskDeps = rustc_query_system::dep_graph::TaskDeps<DepKind>;
pub type TaskDepsRef<'a> = rustc_query_system::dep_graph::TaskDepsRef<'a, DepKind>;
pub type DepGraphQuery = rustc_query_system::dep_graph::DepGraphQuery<DepKind>;
pub type SerializedDepGraph = rustc_query_system::dep_graph::SerializedDepGraph<DepKind>;
pub type EdgeFilter = rustc_query_system::dep_graph::debug::EdgeFilter<DepKind>;
+pub type DepKindStruct<'tcx> = rustc_query_system::dep_graph::DepKindStruct<TyCtxt<'tcx>>;
impl rustc_query_system::dep_graph::DepKind for DepKind {
const NULL: Self = DepKind::Null;
@@ -91,50 +93,8 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
self.sess
}
- #[inline(always)]
- fn fingerprint_style(&self, kind: DepKind) -> rustc_query_system::dep_graph::FingerprintStyle {
- kind.fingerprint_style(*self)
- }
-
- #[inline(always)]
- fn is_eval_always(&self, kind: DepKind) -> bool {
- self.query_kind(kind).is_eval_always
- }
-
- fn try_force_from_dep_node(&self, dep_node: DepNode) -> bool {
- debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
-
- // We must avoid ever having to call `force_from_dep_node()` for a
- // `DepNode::codegen_unit`:
- // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
- // would always end up having to evaluate the first caller of the
- // `codegen_unit` query that *is* reconstructible. This might very well be
- // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
- // to re-trigger calling the `codegen_unit` query with the right key. At
- // that point we would already have re-done all the work we are trying to
- // avoid doing in the first place.
- // The solution is simple: Just explicitly call the `codegen_unit` query for
- // each CGU, right after partitioning. This way `try_mark_green` will always
- // hit the cache instead of having to go through `force_from_dep_node`.
- // This assertion makes sure, we actually keep applying the solution above.
- debug_assert!(
- dep_node.kind != DepKind::codegen_unit,
- "calling force_from_dep_node() on DepKind::codegen_unit"
- );
-
- let cb = self.query_kind(dep_node.kind);
- if let Some(f) = cb.force_from_dep_node {
- f(*self, dep_node);
- true
- } else {
- false
- }
- }
-
- fn try_load_from_on_disk_cache(&self, dep_node: DepNode) {
- let cb = self.query_kind(dep_node.kind);
- if let Some(f) = cb.try_load_from_on_disk_cache {
- f(*self, dep_node)
- }
+ #[inline]
+ fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> {
+ &self.query_kinds[dep_kind as usize]
}
}
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 18b31a75b..a7a7ac059 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,10 +1,10 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::Span;
use crate::ty::Ty;
-#[derive(SessionDiagnostic)]
-#[diag(middle::drop_check_overflow, code = "E0320")]
+#[derive(Diagnostic)]
+#[diag(middle_drop_check_overflow, code = "E0320")]
#[note]
pub struct DropCheckOverflow<'tcx> {
#[primary_span]
@@ -13,8 +13,8 @@ pub struct DropCheckOverflow<'tcx> {
pub overflow_ty: Ty<'tcx>,
}
-#[derive(SessionDiagnostic)]
-#[diag(middle::opaque_hidden_type_mismatch)]
+#[derive(Diagnostic)]
+#[diag(middle_opaque_hidden_type_mismatch)]
pub struct OpaqueHiddenTypeMismatch<'tcx> {
pub self_ty: Ty<'tcx>,
pub other_ty: Ty<'tcx>,
@@ -25,22 +25,22 @@ pub struct OpaqueHiddenTypeMismatch<'tcx> {
pub sub: TypeMismatchReason,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum TypeMismatchReason {
- #[label(middle::conflict_types)]
+ #[label(middle_conflict_types)]
ConflictType {
#[primary_span]
span: Span,
},
- #[note(middle::previous_use_here)]
+ #[note(middle_previous_use_here)]
PreviousUse {
#[primary_span]
span: Span,
},
}
-#[derive(SessionDiagnostic)]
-#[diag(middle::limit_invalid)]
+#[derive(Diagnostic)]
+#[diag(middle_limit_invalid)]
pub struct LimitInvalid<'a> {
#[primary_span]
pub span: Span,
@@ -48,3 +48,10 @@ pub struct LimitInvalid<'a> {
pub value_span: Span,
pub error_str: &'a str,
}
+
+#[derive(Diagnostic)]
+#[diag(middle_const_eval_non_int)]
+pub struct ConstEvalNonIntError {
+ #[primary_span]
+ pub span: Span,
+}
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 30a23c342..83a4d16d7 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -14,7 +14,7 @@ use rustc_index::vec::Idx;
use rustc_middle::hir::nested_filter;
use rustc_span::def_id::StableCrateId;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;
#[inline]
@@ -61,7 +61,7 @@ pub struct ParentHirIterator<'hir> {
}
impl<'hir> Iterator for ParentHirIterator<'hir> {
- type Item = (HirId, Node<'hir>);
+ type Item = HirId;
fn next(&mut self) -> Option<Self::Item> {
if self.current_id == CRATE_HIR_ID {
@@ -77,10 +77,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> {
}
self.current_id = parent_id;
- if let Some(node) = self.map.find(parent_id) {
- return Some((parent_id, node));
- }
- // If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
+ return Some(parent_id);
}
}
}
@@ -93,7 +90,7 @@ pub struct ParentOwnerIterator<'hir> {
}
impl<'hir> Iterator for ParentOwnerIterator<'hir> {
- type Item = (LocalDefId, OwnerNode<'hir>);
+ type Item = (OwnerId, OwnerNode<'hir>);
fn next(&mut self) -> Option<Self::Item> {
if self.current_id.local_id.index() != 0 {
@@ -107,13 +104,13 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
}
loop {
// There are nodes that do not have entries, so we need to skip them.
- let parent_id = self.map.def_key(self.current_id.owner).parent;
+ let parent_id = self.map.def_key(self.current_id.owner.def_id).parent;
- let parent_id = parent_id.map_or(CRATE_HIR_ID.owner, |local_def_index| {
+ let parent_id = parent_id.map_or(CRATE_OWNER_ID, |local_def_index| {
let def_id = LocalDefId { local_def_index };
self.map.local_def_id_to_hir_id(def_id).owner
});
- self.current_id = HirId::make_owner(parent_id);
+ self.current_id = HirId::make_owner(parent_id.def_id);
// If this `HirId` doesn't have an entry, skip it and look for its `parent_id`.
if let Some(node) = self.map.tcx.hir_owner(self.current_id.owner) {
@@ -131,7 +128,7 @@ impl<'hir> Map<'hir> {
#[inline]
pub fn root_module(self) -> &'hir Mod<'hir> {
- match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) {
+ match self.tcx.hir_owner(CRATE_OWNER_ID).map(|o| o.node) {
Some(OwnerNode::Crate(item)) => item,
_ => bug!(),
}
@@ -186,7 +183,7 @@ impl<'hir> Map<'hir> {
#[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)
+ Some(hir_id.owner.def_id)
} else {
self.tcx
.hir_owner_nodes(hir_id.owner)
@@ -244,7 +241,7 @@ impl<'hir> Map<'hir> {
Node::ImplItem(item) => match item.kind {
ImplItemKind::Const(..) => DefKind::AssocConst,
ImplItemKind::Fn(..) => DefKind::AssocFn,
- ImplItemKind::TyAlias(..) => DefKind::AssocTy,
+ ImplItemKind::Type(..) => DefKind::AssocTy,
},
Node::Variant(_) => DefKind::Variant,
Node::Ctor(variant_data) => {
@@ -352,24 +349,24 @@ impl<'hir> Map<'hir> {
}
pub fn get_generics(self, id: LocalDefId) -> Option<&'hir Generics<'hir>> {
- let node = self.tcx.hir_owner(id)?;
+ let node = self.tcx.hir_owner(OwnerId { def_id: id })?;
node.node.generics()
}
pub fn item(self, id: ItemId) -> &'hir Item<'hir> {
- self.tcx.hir_owner(id.def_id).unwrap().node.expect_item()
+ self.tcx.hir_owner(id.owner_id).unwrap().node.expect_item()
}
pub fn trait_item(self, id: TraitItemId) -> &'hir TraitItem<'hir> {
- self.tcx.hir_owner(id.def_id).unwrap().node.expect_trait_item()
+ self.tcx.hir_owner(id.owner_id).unwrap().node.expect_trait_item()
}
pub fn impl_item(self, id: ImplItemId) -> &'hir ImplItem<'hir> {
- self.tcx.hir_owner(id.def_id).unwrap().node.expect_impl_item()
+ self.tcx.hir_owner(id.owner_id).unwrap().node.expect_impl_item()
}
pub fn foreign_item(self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
- self.tcx.hir_owner(id.def_id).unwrap().node.expect_foreign_item()
+ self.tcx.hir_owner(id.owner_id).unwrap().node.expect_foreign_item()
}
pub fn body(self, id: BodyId) -> &'hir Body<'hir> {
@@ -393,8 +390,8 @@ impl<'hir> Map<'hir> {
}
pub fn enclosing_body_owner(self, hir_id: HirId) -> LocalDefId {
- for (parent, _) in self.parent_iter(hir_id) {
- if let Some(body) = self.find(parent).map(associated_body).flatten() {
+ for (_, node) in self.parent_iter(hir_id) {
+ if let Some(body) = associated_body(node) {
return self.body_owner_def_id(body);
}
}
@@ -532,7 +529,7 @@ impl<'hir> Map<'hir> {
pub fn get_module(self, module: LocalDefId) -> (&'hir Mod<'hir>, Span, HirId) {
let hir_id = HirId::make_owner(module);
- match self.tcx.hir_owner(module).map(|o| o.node) {
+ match self.tcx.hir_owner(hir_id.owner).map(|o| o.node) {
Some(OwnerNode::Item(&Item { span, kind: ItemKind::Mod(ref m), .. })) => {
(m, span, hir_id)
}
@@ -622,26 +619,33 @@ impl<'hir> Map<'hir> {
pub fn for_each_module(self, mut f: impl FnMut(LocalDefId)) {
let crate_items = self.tcx.hir_crate_items(());
for module in crate_items.submodules.iter() {
- f(*module)
+ f(module.def_id)
}
}
#[inline]
pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
let crate_items = self.tcx.hir_crate_items(());
- par_for_each_in(&crate_items.submodules[..], |module| f(*module))
+ par_for_each_in(&crate_items.submodules[..], |module| f(module.def_id))
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
#[inline]
- pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
+ pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator<Item = HirId> + 'hir {
ParentHirIterator { current_id, map: self }
}
/// Returns an iterator for the nodes in the ancestor tree of the `current_id`
/// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
#[inline]
+ pub fn parent_iter(self, current_id: HirId) -> impl Iterator<Item = (HirId, Node<'hir>)> {
+ self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?)))
+ }
+
+ /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
+ /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+ #[inline]
pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
ParentOwnerIterator { current_id, map: self }
}
@@ -721,27 +725,27 @@ impl<'hir> Map<'hir> {
None
}
- /// Retrieves the `HirId` for `id`'s parent item, or `id` itself if no
+ /// Retrieves the `OwnerId` for `id`'s parent item, or `id` itself if no
/// parent item is in this map. The "parent item" is the closest parent node
/// in the HIR which is recorded by the map and is an item, either an item
/// in a module, trait, or impl.
- pub fn get_parent_item(self, hir_id: HirId) -> LocalDefId {
+ pub fn get_parent_item(self, hir_id: HirId) -> OwnerId {
if let Some((def_id, _node)) = self.parent_owner_iter(hir_id).next() {
def_id
} else {
- CRATE_DEF_ID
+ CRATE_OWNER_ID
}
}
- /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no
+ /// Returns the `OwnerId` of `id`'s nearest module parent, or `id` itself if no
/// module parent is in this map.
- pub(super) fn get_module_parent_node(self, hir_id: HirId) -> LocalDefId {
+ pub(super) fn get_module_parent_node(self, hir_id: HirId) -> OwnerId {
for (def_id, node) in self.parent_owner_iter(hir_id) {
if let OwnerNode::Item(&Item { kind: ItemKind::Mod(_), .. }) = node {
return def_id;
}
}
- CRATE_DEF_ID
+ CRATE_OWNER_ID
}
/// When on an if expression, a match arm tail expression or a match arm, give back
@@ -814,30 +818,30 @@ impl<'hir> Map<'hir> {
}
bug!(
"expected foreign mod or inlined parent, found {}",
- self.node_to_string(HirId::make_owner(parent))
+ self.node_to_string(HirId::make_owner(parent.def_id))
)
}
- pub fn expect_owner(self, id: LocalDefId) -> OwnerNode<'hir> {
+ pub fn expect_owner(self, id: OwnerId) -> OwnerNode<'hir> {
self.tcx.hir_owner(id).unwrap_or_else(|| bug!("expected owner for {:?}", id)).node
}
pub fn expect_item(self, id: LocalDefId) -> &'hir Item<'hir> {
- match self.tcx.hir_owner(id) {
+ match self.tcx.hir_owner(OwnerId { def_id: id }) {
Some(Owner { node: OwnerNode::Item(item), .. }) => item,
_ => bug!("expected item, found {}", self.node_to_string(HirId::make_owner(id))),
}
}
pub fn expect_impl_item(self, id: LocalDefId) -> &'hir ImplItem<'hir> {
- match self.tcx.hir_owner(id) {
+ match self.tcx.hir_owner(OwnerId { def_id: id }) {
Some(Owner { node: OwnerNode::ImplItem(item), .. }) => item,
_ => bug!("expected impl item, found {}", self.node_to_string(HirId::make_owner(id))),
}
}
pub fn expect_trait_item(self, id: LocalDefId) -> &'hir TraitItem<'hir> {
- match self.tcx.hir_owner(id) {
+ match self.tcx.hir_owner(OwnerId { def_id: id }) {
Some(Owner { node: OwnerNode::TraitItem(item), .. }) => item,
_ => bug!("expected trait item, found {}", self.node_to_string(HirId::make_owner(id))),
}
@@ -850,11 +854,14 @@ impl<'hir> Map<'hir> {
}
}
- pub fn expect_foreign_item(self, id: LocalDefId) -> &'hir ForeignItem<'hir> {
+ pub fn expect_foreign_item(self, id: OwnerId) -> &'hir ForeignItem<'hir> {
match self.tcx.hir_owner(id) {
Some(Owner { node: OwnerNode::ForeignItem(item), .. }) => item,
_ => {
- bug!("expected foreign item, found {}", self.node_to_string(HirId::make_owner(id)))
+ bug!(
+ "expected foreign item, found {}",
+ self.node_to_string(HirId::make_owner(id.def_id))
+ )
}
}
}
@@ -934,9 +941,19 @@ impl<'hir> Map<'hir> {
let span = match self.find(hir_id)? {
// Function-like.
- Node::Item(Item { kind: ItemKind::Fn(sig, ..), .. })
- | Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(sig, ..), .. })
- | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(sig, ..), .. }) => sig.span,
+ Node::Item(Item { kind: ItemKind::Fn(sig, ..), span: outer_span, .. })
+ | Node::TraitItem(TraitItem {
+ kind: TraitItemKind::Fn(sig, ..),
+ span: outer_span,
+ ..
+ })
+ | Node::ImplItem(ImplItem {
+ kind: ImplItemKind::Fn(sig, ..), span: outer_span, ..
+ }) => {
+ // Ensure that the returned span has the item's SyntaxContext, and not the
+ // SyntaxContext of the visibility.
+ sig.span.find_ancestor_in_same_ctxt(*outer_span).unwrap_or(*outer_span)
+ }
// Constants and Statics.
Node::Item(Item {
kind:
@@ -978,7 +995,11 @@ impl<'hir> Map<'hir> {
}
// Other cases.
Node::Item(item) => match &item.kind {
- ItemKind::Use(path, _) => path.span,
+ ItemKind::Use(path, _) => {
+ // Ensure that the returned span has the item's SyntaxContext, and not the
+ // SyntaxContext of the path.
+ path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span)
+ }
_ => named_span(item.span, item.ident, item.kind.generics()),
},
Node::Variant(variant) => named_span(variant.span, variant.ident, None),
@@ -988,11 +1009,17 @@ impl<'hir> Map<'hir> {
_ => named_span(item.span, item.ident, None),
},
Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)),
- Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), .. }) => {
- *fn_decl_span
+ Node::Expr(Expr {
+ kind: ExprKind::Closure(Closure { fn_decl_span, .. }),
+ span,
+ ..
+ }) => {
+ // Ensure that the returned span has the item's SyntaxContext.
+ fn_decl_span.find_ancestor_in_same_ctxt(*span).unwrap_or(*span)
}
_ => self.span_with_body(hir_id),
};
+ debug_assert_eq!(span.ctxt(), self.span_with_body(hir_id).ctxt());
Some(span)
}
@@ -1128,7 +1155,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
.filter_map(|(def_id, info)| {
let _ = info.as_owner()?;
let def_path_hash = definitions.def_path_hash(def_id);
- let span = resolutions.source_span[def_id];
+ let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
debug_assert_eq!(span.parent(), None);
Some((def_path_hash, span))
})
@@ -1217,7 +1244,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
format!("assoc const {} in {}{}", ii.ident, path_str(), id_str)
}
ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str),
- ImplItemKind::TyAlias(_) => {
+ ImplItemKind::Type(_) => {
format!("assoc type {} in {}{}", ii.ident, path_str(), id_str)
}
},
@@ -1290,7 +1317,7 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems {
// A "crate collector" and "module collector" start at a
// module item (the former starts at the crate root) but only
// the former needs to collect it. ItemCollector does not do this for us.
- collector.submodules.push(CRATE_DEF_ID);
+ collector.submodules.push(CRATE_OWNER_ID);
tcx.hir().walk_toplevel_module(&mut collector);
let ItemCollector {
@@ -1318,7 +1345,7 @@ struct ItemCollector<'tcx> {
// otherwise it collects items in some module.
crate_collector: bool,
tcx: TyCtxt<'tcx>,
- submodules: Vec<LocalDefId>,
+ submodules: Vec<OwnerId>,
items: Vec<ItemId>,
trait_items: Vec<TraitItemId>,
impl_items: Vec<ImplItemId>,
@@ -1350,14 +1377,14 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
fn visit_item(&mut self, item: &'hir Item<'hir>) {
if associated_body(Node::Item(item)).is_some() {
- self.body_owners.push(item.def_id);
+ self.body_owners.push(item.owner_id.def_id);
}
self.items.push(item.item_id());
// Items that are modules are handled here instead of in visit_mod.
if let ItemKind::Mod(module) = &item.kind {
- self.submodules.push(item.def_id);
+ self.submodules.push(item.owner_id);
// A module collector does not recurse inside nested modules.
if self.crate_collector {
intravisit::walk_mod(self, module, item.hir_id());
@@ -1386,7 +1413,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
fn visit_trait_item(&mut self, item: &'hir TraitItem<'hir>) {
if associated_body(Node::TraitItem(item)).is_some() {
- self.body_owners.push(item.def_id);
+ self.body_owners.push(item.owner_id.def_id);
}
self.trait_items.push(item.trait_item_id());
@@ -1395,7 +1422,7 @@ impl<'hir> Visitor<'hir> for ItemCollector<'hir> {
fn visit_impl_item(&mut self, item: &'hir ImplItem<'hir>) {
if associated_body(Node::ImplItem(item)).is_some() {
- self.body_owners.push(item.def_id);
+ self.body_owners.push(item.owner_id.def_id);
}
self.impl_items.push(item.impl_item_id());
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 211a61471..1c6264ad0 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -39,7 +39,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
/// bodies. The Ids are in visitor order. This is used to partition a pass between modules.
#[derive(Debug, HashStable, Encodable, Decodable)]
pub struct ModuleItems {
- submodules: Box<[LocalDefId]>,
+ submodules: Box<[OwnerId]>,
items: Box<[ItemId]>,
trait_items: Box<[TraitItemId]>,
impl_items: Box<[ImplItemId]>,
@@ -67,10 +67,10 @@ impl ModuleItems {
pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.items
.iter()
- .map(|id| id.def_id)
- .chain(self.trait_items.iter().map(|id| id.def_id))
- .chain(self.impl_items.iter().map(|id| id.def_id))
- .chain(self.foreign_items.iter().map(|id| id.def_id))
+ .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))
}
pub fn par_items(&self, f: impl Fn(ItemId) + Send + Sync) {
@@ -97,7 +97,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn parent_module(self, id: HirId) -> LocalDefId {
- self.parent_module_from_def_id(id.owner)
+ self.parent_module_from_def_id(id.owner.def_id)
}
pub fn impl_subject(self, def_id: DefId) -> ImplSubject<'tcx> {
@@ -110,13 +110,13 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn provide(providers: &mut Providers) {
providers.parent_module_from_def_id = |tcx, id| {
let hir = tcx.hir();
- hir.get_module_parent_node(hir.local_def_id_to_hir_id(id))
+ hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)).def_id
};
providers.hir_crate_items = map::hir_crate_items;
providers.crate_hash = map::crate_hash;
providers.hir_module_items = map::hir_module_items;
providers.hir_owner = |tcx, id| {
- let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?;
+ let owner = tcx.hir_crate(()).owners.get(id.def_id)?.as_owner()?;
let node = owner.node();
Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies })
};
@@ -128,21 +128,24 @@ pub fn provide(providers: &mut Providers) {
MaybeOwner::NonOwner(hir_id) => hir_id,
}
};
- providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes);
+ providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id.def_id].map(|i| &i.nodes);
providers.hir_owner_parent = |tcx, id| {
// Accessing the local_parent is ok since its value is hashed as part of `id`'s DefPathHash.
- tcx.opt_local_parent(id).map_or(CRATE_HIR_ID, |parent| {
+ tcx.opt_local_parent(id.def_id).map_or(CRATE_HIR_ID, |parent| {
let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent);
- if let Some(local_id) =
- tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id)
+ if let Some(local_id) = tcx.hir_crate(()).owners[parent_hir_id.owner.def_id]
+ .unwrap()
+ .parenting
+ .get(&id.def_id)
{
parent_hir_id.local_id = *local_id;
}
parent_hir_id
})
};
- providers.hir_attrs =
- |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs);
+ providers.hir_attrs = |tcx, id| {
+ tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
+ };
providers.source_span =
|tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
providers.def_span = |tcx, def_id| {
@@ -177,6 +180,7 @@ pub fn provide(providers: &mut Providers) {
let id = id.expect_local();
tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root())
};
- providers.in_scope_traits_map =
- |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map);
+ providers.in_scope_traits_map = |tcx, id| {
+ tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map)
+ };
}
diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs
index f2627885d..41d8c7ffd 100644
--- a/compiler/rustc_middle/src/infer/unify_key.rs
+++ b/compiler/rustc_middle/src/infer/unify_key.rs
@@ -129,7 +129,7 @@ impl<'tcx> UnifyKey for ty::ConstVid<'tcx> {
}
impl<'tcx> UnifyValue for ConstVarValue<'tcx> {
- type Error = (ty::Const<'tcx>, ty::Const<'tcx>);
+ type Error = NoError;
fn unify_values(&value1: &Self, &value2: &Self) -> Result<Self, Self::Error> {
Ok(match (value1.val, value2.val) {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 01b9277b9..a58cbc376 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -31,22 +31,19 @@
#![feature(discriminant_kind)]
#![feature(exhaustive_patterns)]
#![feature(get_mut_unchecked)]
-#![cfg_attr(bootstrap, feature(generic_associated_types))]
#![feature(if_let_guard)]
-#![feature(map_first_last)]
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(extern_types)]
#![feature(new_uninit)]
#![feature(once_cell)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(trusted_len)]
#![feature(type_alias_impl_trait)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
-#![feature(half_open_range_patterns)]
+#![cfg_attr(bootstrap, feature(half_open_range_patterns))]
#![feature(control_flow_enum)]
#![feature(associated_type_defaults)]
#![feature(trusted_step)]
@@ -58,6 +55,7 @@
#![feature(drain_filter)]
#![feature(intra_doc_pointers)]
#![feature(yeet_expr)]
+#![feature(result_option_inspect)]
#![feature(const_option)]
#![recursion_limit = "512"]
#![allow(rustc::potential_query_instability)]
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 2f45222de..79522bd0b 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -1,20 +1,20 @@
use std::cmp;
use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_errors::{Diagnostic, DiagnosticId, LintDiagnosticBuilder, MultiSpan};
-use rustc_hir::HirId;
-use rustc_index::vec::IndexVec;
-use rustc_query_system::ich::StableHashingContext;
+use rustc_data_structures::sorted_map::SortedMap;
+use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
+use rustc_hir::{HirId, ItemLocalId};
use rustc_session::lint::{
builtin::{self, FORBIDDEN_LINT_GROUPS},
- FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
+ FutureIncompatibilityReason, Level, Lint, LintId,
};
use rustc_session::Session;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::{DesugaringKind, ExpnKind};
use rustc_span::{symbol, Span, Symbol, DUMMY_SP};
+use crate::ty::TyCtxt;
+
/// How a lint level was set.
#[derive(Clone, Copy, PartialEq, Eq, HashStable, Debug)]
pub enum LintLevelSource {
@@ -23,7 +23,12 @@ pub enum LintLevelSource {
Default,
/// Lint level was set by an attribute.
- Node(Symbol, Span, Option<Symbol> /* RFC 2383 reason */),
+ Node {
+ name: Symbol,
+ span: Span,
+ /// RFC 2383 reason
+ reason: Option<Symbol>,
+ },
/// Lint level was set by a command-line flag.
/// The provided `Level` is the level specified on the command line.
@@ -35,7 +40,7 @@ impl LintLevelSource {
pub fn name(&self) -> Symbol {
match *self {
LintLevelSource::Default => symbol::kw::Default,
- LintLevelSource::Node(name, _, _) => name,
+ LintLevelSource::Node { name, .. } => name,
LintLevelSource::CommandLine(name, _) => name,
}
}
@@ -43,7 +48,7 @@ impl LintLevelSource {
pub fn span(&self) -> Span {
match *self {
LintLevelSource::Default => DUMMY_SP,
- LintLevelSource::Node(_, span, _) => span,
+ LintLevelSource::Node { span, .. } => span,
LintLevelSource::CommandLine(_, _) => DUMMY_SP,
}
}
@@ -52,145 +57,137 @@ impl LintLevelSource {
/// A tuple of a lint level and its source.
pub type LevelAndSource = (Level, LintLevelSource);
-#[derive(Debug, HashStable)]
-pub struct LintLevelSets {
- pub list: IndexVec<LintStackIndex, LintSet>,
- pub lint_cap: Level,
-}
-
-rustc_index::newtype_index! {
- #[derive(HashStable)]
- pub struct LintStackIndex {
- const COMMAND_LINE = 0,
- }
-}
-
-#[derive(Debug, HashStable)]
-pub struct LintSet {
- // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
- // flag.
- pub specs: FxHashMap<LintId, LevelAndSource>,
-
- pub parent: LintStackIndex,
+/// Return type for the `shallow_lint_levels_on` query.
+///
+/// This map represents the set of allowed lints and allowance levels given
+/// by the attributes for *a single HirId*.
+#[derive(Default, Debug, HashStable)]
+pub struct ShallowLintLevelMap {
+ pub specs: SortedMap<ItemLocalId, FxHashMap<LintId, LevelAndSource>>,
}
-impl LintLevelSets {
- pub fn new() -> Self {
- LintLevelSets { list: IndexVec::new(), lint_cap: Level::Forbid }
- }
-
- pub fn get_lint_level(
- &self,
- lint: &'static Lint,
- idx: LintStackIndex,
- aux: Option<&FxHashMap<LintId, LevelAndSource>>,
- sess: &Session,
- ) -> LevelAndSource {
- let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
-
- // If `level` is none then we actually assume the default level for this
- // lint.
- let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
-
- // If we're about to issue a warning, check at the last minute for any
- // directives against the warnings "lint". If, for example, there's an
- // `allow(warnings)` in scope then we want to respect that instead.
- //
- // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically
- // triggers in cases (like #80988) where you have `forbid(warnings)`,
- // and so if we turned that into an error, it'd defeat the purpose of the
- // future compatibility warning.
- if level == Level::Warn && LintId::of(lint) != LintId::of(FORBIDDEN_LINT_GROUPS) {
- let (warnings_level, warnings_src) =
- self.get_lint_id_level(LintId::of(builtin::WARNINGS), idx, aux);
- if let Some(configured_warning_level) = warnings_level {
- if configured_warning_level != Level::Warn {
- level = configured_warning_level;
- src = warnings_src;
- }
+/// From an initial level and source, verify the effect of special annotations:
+/// `warnings` lint level and lint caps.
+///
+/// The return of this function is suitable for diagnostics.
+pub fn reveal_actual_level(
+ level: Option<Level>,
+ src: &mut LintLevelSource,
+ sess: &Session,
+ lint: LintId,
+ probe_for_lint_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource),
+) -> Level {
+ // If `level` is none then we actually assume the default level for this lint.
+ let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition()));
+
+ // If we're about to issue a warning, check at the last minute for any
+ // directives against the warnings "lint". If, for example, there's an
+ // `allow(warnings)` in scope then we want to respect that instead.
+ //
+ // We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically
+ // triggers in cases (like #80988) where you have `forbid(warnings)`,
+ // and so if we turned that into an error, it'd defeat the purpose of the
+ // future compatibility warning.
+ if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) {
+ let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS));
+ if let Some(configured_warning_level) = warnings_level {
+ if configured_warning_level != Level::Warn {
+ level = configured_warning_level;
+ *src = warnings_src;
}
}
+ }
- // Ensure that we never exceed the `--cap-lints` argument
- // unless the source is a --force-warn
- level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src {
- level
- } else {
- cmp::min(level, self.lint_cap)
- };
-
- if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
- // Ensure that we never exceed driver level.
- level = cmp::min(*driver_level, level);
- }
+ // Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn
+ level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src {
+ level
+ } else {
+ cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid))
+ };
- (level, src)
+ if let Some(driver_level) = sess.driver_lint_caps.get(&lint) {
+ // Ensure that we never exceed driver level.
+ level = cmp::min(*driver_level, level);
}
- pub fn get_lint_id_level(
+ level
+}
+
+impl ShallowLintLevelMap {
+ /// Perform a deep probe in the HIR tree looking for the actual level for the lint.
+ /// This lint level is not usable for diagnostics, it needs to be corrected by
+ /// `reveal_actual_level` beforehand.
+ #[instrument(level = "trace", skip(self, tcx), ret)]
+ fn probe_for_lint_level(
&self,
+ tcx: TyCtxt<'_>,
id: LintId,
- mut idx: LintStackIndex,
- aux: Option<&FxHashMap<LintId, LevelAndSource>>,
+ start: HirId,
) -> (Option<Level>, LintLevelSource) {
- if let Some(specs) = aux {
- if let Some(&(level, src)) = specs.get(&id) {
- return (Some(level), src);
- }
+ if let Some(map) = self.specs.get(&start.local_id)
+ && let Some(&(level, src)) = map.get(&id)
+ {
+ return (Some(level), src);
}
- loop {
- let LintSet { ref specs, parent } = self.list[idx];
- if let Some(&(level, src)) = specs.get(&id) {
- return (Some(level), src);
+
+ let mut owner = start.owner;
+ let mut specs = &self.specs;
+
+ for parent in tcx.hir().parent_id_iter(start) {
+ if parent.owner != owner {
+ owner = parent.owner;
+ specs = &tcx.shallow_lint_levels_on(owner).specs;
}
- if idx == COMMAND_LINE {
- return (None, LintLevelSource::Default);
+ if let Some(map) = specs.get(&parent.local_id)
+ && let Some(&(level, src)) = map.get(&id)
+ {
+ return (Some(level), src);
}
- idx = parent;
}
- }
-}
-#[derive(Debug)]
-pub struct LintLevelMap {
- /// This is a collection of lint expectations as described in RFC 2383, that
- /// can be fulfilled during this compilation session. This means that at least
- /// one expected lint is currently registered in the lint store.
- ///
- /// The [`LintExpectationId`] is stored as a part of the [`Expect`](Level::Expect)
- /// lint level.
- pub lint_expectations: Vec<(LintExpectationId, LintExpectation)>,
- pub sets: LintLevelSets,
- pub id_to_set: FxHashMap<HirId, LintStackIndex>,
-}
+ (None, LintLevelSource::Default)
+ }
-impl LintLevelMap {
- /// If the `id` was previously registered with `register_id` when building
- /// this `LintLevelMap` this returns the corresponding lint level and source
- /// of the lint level for the lint provided.
- ///
- /// If the `id` was not previously registered, returns `None`. If `None` is
- /// returned then the parent of `id` should be acquired and this function
- /// should be called again.
- pub fn level_and_source(
+ /// Fetch and return the user-visible lint level for the given lint at the given HirId.
+ #[instrument(level = "trace", skip(self, tcx), ret)]
+ pub fn lint_level_id_at_node(
&self,
- lint: &'static Lint,
- id: HirId,
- session: &Session,
- ) -> Option<LevelAndSource> {
- self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
+ tcx: TyCtxt<'_>,
+ lint: LintId,
+ cur: HirId,
+ ) -> (Level, LintLevelSource) {
+ let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur);
+ let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| {
+ self.probe_for_lint_level(tcx, lint, cur)
+ });
+ (level, src)
}
}
-impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
- #[inline]
- fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let LintLevelMap { ref sets, ref id_to_set, ref lint_expectations } = *self;
+impl TyCtxt<'_> {
+ /// Fetch and return the user-visible lint level for the given lint at the given HirId.
+ pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) {
+ self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id)
+ }
- id_to_set.hash_stable(hcx, hasher);
- lint_expectations.hash_stable(hcx, hasher);
+ /// Walks upwards from `id` to find a node which might change lint levels with attributes.
+ /// It stops at `bound` and just returns it if reached.
+ pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
+ let hir = self.hir();
+ loop {
+ if id == bound {
+ return bound;
+ }
- hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher))
+ if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
+ return id;
+ }
+ let next = hir.get_parent_node(id);
+ if next == id {
+ bug!("lint traversal reached the root of the crate");
+ }
+ id = next;
+ }
}
}
@@ -261,11 +258,11 @@ pub fn explain_lint_level_source(
));
}
}
- LintLevelSource::Node(lint_attr_name, src, reason) => {
+ LintLevelSource::Node { name: lint_attr_name, span, reason, .. } => {
if let Some(rationale) = reason {
err.note(rationale.as_str());
}
- err.span_note_once(src, "the lint level is defined here");
+ err.span_note_once(span, "the lint level is defined here");
if lint_attr_name.as_str() != name {
let level_str = level.as_str();
err.note_once(&format!(
@@ -277,23 +274,65 @@ pub fn explain_lint_level_source(
}
}
-pub fn struct_lint_level<'s, 'd>(
- sess: &'s Session,
+/// The innermost function for emitting lints.
+///
+/// If you are loocking to implement a lint, look for higher level functions,
+/// for example:
+/// - [`TyCtxt::emit_spanned_lint`]
+/// - [`TyCtxt::struct_span_lint_hir`]
+/// - [`TyCtxt::emit_lint`]
+/// - [`TyCtxt::struct_lint_node`]
+/// - `LintContext::lookup`
+///
+/// ## `decorate` signature
+///
+/// The return value of `decorate` is ignored by this function. So what is the
+/// point of returning `&'b mut DiagnosticBuilder<'a, ()>`?
+///
+/// There are 2 reasons for this signature.
+///
+/// First of all, it prevents accidental use of `.emit()` -- it's clear that the
+/// builder will be later used and shouldn't be emitted right away (this is
+/// especially important because the old API expected you to call `.emit()` in
+/// the closure).
+///
+/// Second of all, it makes the most common case of adding just a single label
+/// /suggestion much nicer, since [`DiagnosticBuilder`] methods return
+/// `&mut DiagnosticBuilder`, you can just chain methods, without needed
+/// awkward `{ ...; }`:
+/// ```ignore pseudo-code
+/// struct_lint_level(
+/// ...,
+/// |lint| lint.span_label(sp, "lbl")
+/// // ^^^^^^^^^^^^^^^^^^^^^ returns `&mut DiagnosticBuilder` by default
+/// )
+/// ```
+pub fn struct_lint_level(
+ sess: &Session,
lint: &'static Lint,
level: Level,
src: LintLevelSource,
span: Option<MultiSpan>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>) + 'd,
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
// the "real" work.
- fn struct_lint_level_impl<'s, 'd>(
- sess: &'s Session,
+ fn struct_lint_level_impl(
+ sess: &Session,
lint: &'static Lint,
level: Level,
src: LintLevelSource,
span: Option<MultiSpan>,
- decorate: Box<dyn for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) + 'd>,
+ msg: impl Into<DiagnosticMessage>,
+ decorate: Box<
+ dyn '_
+ + for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
+ >,
) {
// Check for future incompatibility lints and issue a stronger warning.
let future_incompatible = lint.future_incompatible;
@@ -344,6 +383,8 @@ pub fn struct_lint_level<'s, 'd>(
(Level::Deny | Level::Forbid, None) => sess.diagnostic().struct_err_lint(""),
};
+ err.set_is_lint();
+
// If this code originates in a foreign macro, aka something that this crate
// did not itself author, then it's likely that there's nothing this crate
// can do about it. We probably want to skip the lint entirely.
@@ -366,6 +407,10 @@ pub fn struct_lint_level<'s, 'd>(
}
}
+ // Delay evaluating and setting the primary message until after we've
+ // suppressed the lint due to macros.
+ err.set_primary_message(msg);
+
// Lint diagnostics that are covered by the expect level will not be emitted outside
// the compiler. It is therefore not necessary to add any information for the user.
// This will therefore directly call the decorate function which will in turn emit
@@ -373,12 +418,12 @@ pub fn struct_lint_level<'s, 'd>(
if let Level::Expect(_) = level {
let name = lint.name_lower();
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false });
- decorate(LintDiagnosticBuilder::new(err));
+
+ decorate(&mut err);
+ err.emit();
return;
}
- explain_lint_level_source(lint, level, src, &mut err);
-
let name = lint.name_lower();
let is_force_warn = matches!(level, Level::ForceWarn(_));
err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn });
@@ -417,10 +462,12 @@ pub fn struct_lint_level<'s, 'd>(
}
}
- // Finally, run `decorate`. This function is also responsible for emitting the diagnostic.
- decorate(LintDiagnosticBuilder::new(err));
+ // Finally, run `decorate`.
+ decorate(&mut err);
+ explain_lint_level_source(lint, level, src, &mut *err);
+ err.emit()
}
- struct_lint_level_impl(sess, lint, level, src, span, Box::new(decorate))
+ struct_lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
}
/// Returns whether `span` originates in a foreign crate's external macro.
@@ -432,7 +479,9 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
match expn_data.kind {
ExpnKind::Inlined
| ExpnKind::Root
- | ExpnKind::Desugaring(DesugaringKind::ForLoop | DesugaringKind::WhileLoop) => false,
+ | ExpnKind::Desugaring(
+ DesugaringKind::ForLoop | DesugaringKind::WhileLoop | DesugaringKind::OpaqueTy,
+ ) => false,
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.
diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs
index 0e85c60a3..01fe72de6 100644
--- a/compiler/rustc_middle/src/macros.rs
+++ b/compiler/rustc_middle/src/macros.rs
@@ -54,13 +54,22 @@ macro_rules! TrivialTypeTraversalImpls {
impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
fn try_fold_with<F: $crate::ty::fold::FallibleTypeFolder<$tcx>>(
self,
- _: &mut F
- ) -> ::std::result::Result<$ty, F::Error> {
+ _: &mut F,
+ ) -> ::std::result::Result<Self, F::Error> {
Ok(self)
}
+
+ #[inline]
+ fn fold_with<F: $crate::ty::fold::TypeFolder<$tcx>>(
+ self,
+ _: &mut F,
+ ) -> Self {
+ self
+ }
}
impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
+ #[inline]
fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
&self,
_: &mut F)
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index 53c4d9267..12aef66bc 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -38,7 +38,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
tcx.hir().krate_attrs(),
tcx.sess,
sym::const_eval_limit,
- 1_000_000,
+ 2_000_000,
),
}
}
diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs
index 751c7f464..9c68c7504 100644
--- a/compiler/rustc_middle/src/middle/privacy.rs
+++ b/compiler/rustc_middle/src/middle/privacy.rs
@@ -1,64 +1,218 @@
//! A pass that checks to make sure private fields and methods aren't used
//! outside their scopes. This pass will also generate a set of exported items
//! which are available for use externally when compiled as a library.
-
+use crate::ty::{DefIdTree, Visibility};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
-use rustc_span::def_id::LocalDefId;
+use rustc_span::def_id::{DefId, LocalDefId};
use std::hash::Hash;
-/// Represents the levels of accessibility an item can have.
+/// Represents the levels of effective visibility an item can have.
///
-/// The variants are sorted in ascending order of accessibility.
+/// The variants are sorted in ascending order of directness.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, HashStable)]
-pub enum AccessLevel {
- /// Superset of `AccessLevel::Reachable` used to mark impl Trait items.
- ReachableFromImplTrait,
- /// Exported items + items participating in various kinds of public interfaces,
- /// but not directly nameable. For example, if function `fn f() -> T {...}` is
- /// public, then type `T` is reachable. Its values can be obtained by other crates
- /// even if the type itself is not nameable.
+pub enum Level {
+ /// Superset of `Reachable` including items leaked through return position `impl Trait`.
+ ReachableThroughImplTrait,
+ /// Item is either reexported, or leaked through any kind of interface.
+ /// For example, if function `fn f() -> T {...}` is directly public, then type `T` is publicly
+ /// reachable and its values can be obtained by other crates even if the type itself is not
+ /// nameable.
Reachable,
- /// Public items + items accessible to other crates with the help of `pub use` re-exports.
- Exported,
- /// Items accessible to other crates directly, without the help of re-exports.
- Public,
+ /// Item is accessible either directly, or with help of `use` reexports.
+ Reexported,
+ /// Item is directly accessible, without help of reexports.
+ Direct,
+}
+
+impl Level {
+ pub fn all_levels() -> [Level; 4] {
+ [Level::Direct, Level::Reexported, Level::Reachable, Level::ReachableThroughImplTrait]
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
+pub struct EffectiveVisibility {
+ direct: Visibility,
+ reexported: Visibility,
+ reachable: Visibility,
+ reachable_through_impl_trait: Visibility,
+}
+
+impl EffectiveVisibility {
+ pub fn at_level(&self, level: Level) -> &Visibility {
+ match level {
+ Level::Direct => &self.direct,
+ Level::Reexported => &self.reexported,
+ Level::Reachable => &self.reachable,
+ Level::ReachableThroughImplTrait => &self.reachable_through_impl_trait,
+ }
+ }
+
+ fn at_level_mut(&mut self, level: Level) -> &mut Visibility {
+ match level {
+ Level::Direct => &mut self.direct,
+ Level::Reexported => &mut self.reexported,
+ Level::Reachable => &mut self.reachable,
+ Level::ReachableThroughImplTrait => &mut self.reachable_through_impl_trait,
+ }
+ }
+
+ pub fn is_public_at_level(&self, level: Level) -> bool {
+ self.at_level(level).is_public()
+ }
+
+ pub fn from_vis(vis: Visibility) -> EffectiveVisibility {
+ EffectiveVisibility {
+ direct: vis,
+ reexported: vis,
+ reachable: vis,
+ reachable_through_impl_trait: vis,
+ }
+ }
}
-/// Holds a map of accessibility levels for reachable HIR nodes.
+/// Holds a map of effective visibilities for reachable HIR nodes.
#[derive(Debug, Clone)]
-pub struct AccessLevels<Id = LocalDefId> {
- pub map: FxHashMap<Id, AccessLevel>,
+pub struct EffectiveVisibilities<Id = LocalDefId> {
+ map: FxHashMap<Id, EffectiveVisibility>,
}
-impl<Id: Hash + Eq> AccessLevels<Id> {
- /// See `AccessLevel::Reachable`.
+impl<Id: Hash + Eq + Copy> EffectiveVisibilities<Id> {
+ pub fn is_public_at_level(&self, id: Id, level: Level) -> bool {
+ self.effective_vis(id)
+ .map_or(false, |effective_vis| effective_vis.is_public_at_level(level))
+ }
+
+ /// See `Level::Reachable`.
pub fn is_reachable(&self, id: Id) -> bool {
- self.map.get(&id) >= Some(&AccessLevel::Reachable)
+ self.is_public_at_level(id, Level::Reachable)
}
- /// See `AccessLevel::Exported`.
+ /// See `Level::Reexported`.
pub fn is_exported(&self, id: Id) -> bool {
- self.map.get(&id) >= Some(&AccessLevel::Exported)
+ self.is_public_at_level(id, Level::Reexported)
+ }
+
+ /// See `Level::Direct`.
+ pub fn is_directly_public(&self, id: Id) -> bool {
+ self.is_public_at_level(id, Level::Direct)
+ }
+
+ pub fn public_at_level(&self, id: Id) -> Option<Level> {
+ self.effective_vis(id).and_then(|effective_vis| {
+ for level in Level::all_levels() {
+ if effective_vis.is_public_at_level(level) {
+ return Some(level);
+ }
+ }
+ None
+ })
+ }
+
+ pub fn effective_vis(&self, id: Id) -> Option<&EffectiveVisibility> {
+ self.map.get(&id)
}
- /// See `AccessLevel::Public`.
- pub fn is_public(&self, id: Id) -> bool {
- self.map.get(&id) >= Some(&AccessLevel::Public)
+ pub fn iter(&self) -> impl Iterator<Item = (&Id, &EffectiveVisibility)> {
+ self.map.iter()
+ }
+
+ pub fn map_id<OutId: Hash + Eq + Copy>(
+ &self,
+ f: impl Fn(Id) -> OutId,
+ ) -> EffectiveVisibilities<OutId> {
+ EffectiveVisibilities { map: self.map.iter().map(|(k, v)| (f(*k), *v)).collect() }
+ }
+
+ pub fn set_public_at_level(
+ &mut self,
+ id: Id,
+ default_vis: impl FnOnce() -> Visibility,
+ level: Level,
+ ) {
+ let mut effective_vis = self
+ .effective_vis(id)
+ .copied()
+ .unwrap_or_else(|| EffectiveVisibility::from_vis(default_vis()));
+ for l in Level::all_levels() {
+ if l <= level {
+ *effective_vis.at_level_mut(l) = Visibility::Public;
+ }
+ }
+ self.map.insert(id, effective_vis);
+ }
+}
+
+impl<Id: Hash + Eq + Copy + Into<DefId>> EffectiveVisibilities<Id> {
+ // `parent_id` is not necessarily a parent in source code tree,
+ // it is the node from which the maximum effective visibility is inherited.
+ pub fn update(
+ &mut self,
+ id: Id,
+ nominal_vis: Visibility,
+ default_vis: impl FnOnce() -> Visibility,
+ parent_id: Id,
+ level: Level,
+ tree: impl DefIdTree,
+ ) -> bool {
+ let mut changed = false;
+ let mut current_effective_vis = self.effective_vis(id).copied().unwrap_or_else(|| {
+ if id.into().is_crate_root() {
+ EffectiveVisibility::from_vis(Visibility::Public)
+ } else {
+ EffectiveVisibility::from_vis(default_vis())
+ }
+ });
+ if let Some(inherited_effective_vis) = self.effective_vis(parent_id) {
+ 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;
+ for l in Level::all_levels() {
+ if level >= l {
+ let inherited_effective_vis_at_level = *inherited_effective_vis.at_level(l);
+ let current_effective_vis_at_level = current_effective_vis.at_level_mut(l);
+ // effective visibility for id shouldn't be recalculated if
+ // inherited from parent_id effective visibility isn't changed at next level
+ if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
+ && level != l)
+ {
+ calculated_effective_vis =
+ if nominal_vis.is_at_least(inherited_effective_vis_at_level, tree) {
+ inherited_effective_vis_at_level
+ } else {
+ nominal_vis
+ };
+ }
+ // effective visibility can't be decreased at next update call for the
+ // same id
+ if *current_effective_vis_at_level != calculated_effective_vis
+ && calculated_effective_vis
+ .is_at_least(*current_effective_vis_at_level, tree)
+ {
+ changed = true;
+ *current_effective_vis_at_level = calculated_effective_vis;
+ }
+ inherited_effective_vis_at_prev_level = inherited_effective_vis_at_level;
+ }
+ }
+ }
+ self.map.insert(id, current_effective_vis);
+ changed
}
}
-impl<Id> Default for AccessLevels<Id> {
+impl<Id> Default for EffectiveVisibilities<Id> {
fn default() -> Self {
- AccessLevels { map: Default::default() }
+ EffectiveVisibilities { map: Default::default() }
}
}
-impl<'a> HashStable<StableHashingContext<'a>> for AccessLevels {
+impl<'a> HashStable<StableHashingContext<'a>> for EffectiveVisibilities {
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
- let AccessLevels { ref map } = *self;
+ let EffectiveVisibilities { ref map } = *self;
map.hash_stable(hcx, hasher);
}
}
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index a171f5711..c3bf1c717 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -2,9 +2,9 @@
use crate::ty;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::ItemLocalId;
+use rustc_data_structures::fx::FxHashMap;
+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)]
@@ -49,12 +49,7 @@ pub enum ObjectLifetimeDefault {
pub struct ResolveLifetimes {
/// Maps from every use of a named (not anonymous) lifetime to a
/// `Region` describing how that region is bound
- pub defs: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Region>>,
+ pub defs: FxHashMap<OwnerId, FxHashMap<ItemLocalId, Region>>,
- /// Set of lifetime def ids that are late-bound; a region can
- /// be late-bound if (a) it does NOT appear in a where-clause and
- /// (b) it DOES appear in the arguments.
- pub late_bound: FxHashMap<LocalDefId, FxHashSet<LocalDefId>>,
-
- pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
+ 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 d182929c4..61bc089e4 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -253,13 +253,12 @@ fn late_report_deprecation(
return;
}
let method_span = method_span.unwrap_or(span);
- tcx.struct_span_lint_hir(lint, hir_id, method_span, |lint| {
- let mut diag = lint.build(message);
+ 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);
- deprecation_suggestion(&mut diag, kind, suggestion, method_span);
+ deprecation_suggestion(diag, kind, suggestion, method_span);
}
- diag.emit();
+ diag
});
}
@@ -621,9 +620,7 @@ impl<'tcx> TyCtxt<'tcx> {
unmarked: impl FnOnce(Span, DefId),
) -> bool {
let soft_handler = |lint, span, msg: &_| {
- self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, |lint| {
- lint.build(msg).emit();
- })
+ self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |lint| lint)
};
let eval_result =
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index e4039cc7c..b5a50cc15 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -479,12 +479,7 @@ impl<T: Any> AsAny for T {
}
/// A trait for machine-specific errors (or other "machine stop" conditions).
-pub trait MachineStopType: AsAny + fmt::Display + Send {
- /// If `true`, emit a hard error instead of going through the `CONST_ERR` lint
- fn is_hard_err(&self) -> bool {
- false
- }
-}
+pub trait MachineStopType: AsAny + fmt::Display + Send {}
impl dyn MachineStopType {
#[inline(always)]
@@ -543,16 +538,4 @@ impl InterpError<'_> {
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
)
}
-
- /// Should this error be reported as a hard error, preventing compilation, or a soft error,
- /// causing a deny-by-default lint?
- pub fn is_hard_err(&self) -> bool {
- use InterpError::*;
- match *self {
- MachineStop(ref err) => err.is_hard_err(),
- UndefinedBehavior(_) => true,
- ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) => true,
- _ => false,
- }
- }
}
diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs
index 95e52e391..23c2ce647 100644
--- a/compiler/rustc_middle/src/mir/interpret/pointer.rs
+++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs
@@ -43,7 +43,7 @@ pub trait PointerArithmetic: HasDataLayout {
let val = val as i64;
// Now wrap-around into the machine_isize range.
if val > self.machine_isize_max() {
- // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into
+ // 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);
let max_usize_plus_1 = 1u128 << self.pointer_size().bits();
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index 4207988d7..473894ac1 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -4,7 +4,9 @@ use crate::mir;
use crate::ty::subst::InternalSubsts;
use crate::ty::visit::TypeVisitable;
use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
+use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
+use rustc_session::lint;
use rustc_span::{Span, DUMMY_SP};
impl<'tcx> TyCtxt<'tcx> {
@@ -36,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve(
self,
param_env: ty::ParamEnv<'tcx>,
- ct: ty::Unevaluated<'tcx>,
+ ct: mir::UnevaluatedConst<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
@@ -45,11 +47,15 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_infer_types_or_consts() {
+ if ct.substs.has_non_region_infer() {
bug!("did not expect inference variables here");
}
- match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
+ match ty::Instance::resolve_opt_const_arg(
+ self, param_env,
+ // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst?
+ ct.def, ct.substs,
+ ) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)
@@ -63,7 +69,7 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn const_eval_resolve_for_typeck(
self,
param_env: ty::ParamEnv<'tcx>,
- ct: ty::Unevaluated<'tcx, ()>,
+ ct: ty::UnevaluatedConst<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// Cannot resolve `Unevaluated` constants that contain inference
@@ -72,14 +78,36 @@ impl<'tcx> TyCtxt<'tcx> {
//
// When trying to evaluate constants containing inference variables,
// use `Infcx::const_eval_resolve` instead.
- if ct.substs.has_infer_types_or_consts() {
+ if ct.substs.has_non_region_infer() {
bug!("did not expect inference variables here");
}
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: None };
- self.const_eval_global_id_for_typeck(param_env, cid, span)
+ self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| {
+ // We are emitting the lint here instead of in `is_const_evaluatable`
+ // as we normalize obligations before checking them, and normalization
+ // uses this function to evaluate this constant.
+ //
+ // @lcnr believes that successfully evaluating even though there are
+ // used generic parameters is a bug of evaluation, so checking for it
+ // here does feel somewhat sensible.
+ if !self.features().generic_const_exprs && ct.substs.has_non_region_param() {
+ assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst));
+ let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def);
+ if mir_body.is_polymorphic {
+ let Some(local_def_id) = ct.def.did.as_local() else { return };
+ self.struct_span_lint_hir(
+ lint::builtin::CONST_EVALUATABLE_UNCHECKED,
+ self.hir().local_def_id_to_hir_id(local_def_id),
+ self.def_span(ct.def.did),
+ "cannot use constants which depend on generic parameters in types",
+ |err| err,
+ )
+ }
+ }
+ })
}
Ok(None) => Err(ErrorHandled::TooGeneric),
Err(error_reported) => Err(ErrorHandled::Reported(error_reported)),
@@ -211,7 +239,7 @@ impl<'tcx> TyCtxt<'tcx> {
self,
param_env: ty::ParamEnv<'tcx>,
constant: mir::ConstantKind<'tcx>,
- ) -> mir::DestructuredMirConstant<'tcx> {
+ ) -> mir::DestructuredConstant<'tcx> {
self.try_destructure_mir_constant(param_env.and(constant)).unwrap()
}
}
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 3d7a6230e..79db35a76 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -7,12 +7,12 @@ use crate::mir::interpret::{
};
use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
-use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
+use crate::ty::fold::{FallibleTypeFolder, TypeFoldable};
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
-use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
+use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
+use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
use rustc_data_structures::captures::Captures;
use rustc_errors::ErrorGuaranteed;
@@ -116,11 +116,6 @@ pub trait MirPass<'tcx> {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>);
- /// If this pass causes the MIR to enter a new phase, return that phase.
- fn phase_change(&self) -> Option<MirPhase> {
- None
- }
-
fn is_mir_dump_enabled(&self) -> bool {
true
}
@@ -145,6 +140,35 @@ impl MirPhase {
}
}
+impl Display for MirPhase {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match self {
+ MirPhase::Built => write!(f, "built"),
+ MirPhase::Analysis(p) => write!(f, "analysis-{}", p),
+ MirPhase::Runtime(p) => write!(f, "runtime-{}", p),
+ }
+ }
+}
+
+impl Display for AnalysisPhase {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match self {
+ AnalysisPhase::Initial => write!(f, "initial"),
+ AnalysisPhase::PostCleanup => write!(f, "post_cleanup"),
+ }
+ }
+}
+
+impl Display for RuntimePhase {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ match self {
+ RuntimePhase::Initial => write!(f, "initial"),
+ RuntimePhase::PostCleanup => write!(f, "post_cleanup"),
+ RuntimePhase::Optimized => write!(f, "optimized"),
+ }
+ }
+}
+
/// Where a specific `mir::Body` comes from.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
@@ -207,6 +231,9 @@ pub struct Body<'tcx> {
/// us to see the difference and forego optimization on the inlined promoted items.
pub phase: MirPhase,
+ /// How many passses we have executed since starting the current phase. Used for debug output.
+ pub pass_count: usize,
+
pub source: MirSource<'tcx>,
/// A list of source scopes; these are referenced by statements
@@ -292,6 +319,7 @@ impl<'tcx> Body<'tcx> {
let mut body = Body {
phase: MirPhase::Built,
+ pass_count: 1,
source,
basic_blocks: BasicBlocks::new(basic_blocks),
source_scopes,
@@ -313,7 +341,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
tainted_by_errors,
};
- body.is_polymorphic = body.has_param_types_or_consts();
+ body.is_polymorphic = body.has_non_region_param();
body
}
@@ -325,6 +353,7 @@ impl<'tcx> Body<'tcx> {
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
let mut body = Body {
phase: MirPhase::Built,
+ pass_count: 1,
source: MirSource::item(CRATE_DEF_ID.to_def_id()),
basic_blocks: BasicBlocks::new(basic_blocks),
source_scopes: IndexVec::new(),
@@ -339,7 +368,7 @@ impl<'tcx> Body<'tcx> {
is_polymorphic: false,
tainted_by_errors: None,
};
- body.is_polymorphic = body.has_param_types_or_consts();
+ body.is_polymorphic = body.has_non_region_param();
body
}
@@ -1380,6 +1409,7 @@ impl<V, T> ProjectionElem<V, T> {
Self::Field(_, _)
| Self::Index(_)
+ | Self::OpaqueCast(_)
| Self::ConstantIndex { .. }
| Self::Subslice { .. }
| Self::Downcast(_, _) => false,
@@ -1574,7 +1604,9 @@ impl Debug for Place<'_> {
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
for elem in self.projection.iter().rev() {
match elem {
- ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => {
+ ProjectionElem::OpaqueCast(_)
+ | ProjectionElem::Downcast(_, _)
+ | ProjectionElem::Field(_, _) => {
write!(fmt, "(").unwrap();
}
ProjectionElem::Deref => {
@@ -1590,6 +1622,9 @@ impl Debug for Place<'_> {
for elem in self.projection.iter() {
match elem {
+ ProjectionElem::OpaqueCast(ty) => {
+ write!(fmt, " as {})", ty)?;
+ }
ProjectionElem::Downcast(Some(name), _index) => {
write!(fmt, " as {})", name)?;
}
@@ -1818,7 +1853,6 @@ impl<'tcx> Rvalue<'tcx> {
// While the model is undecided, we should be conservative. See
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
- Rvalue::Cast(CastKind::DynStar, _, _) => false,
Rvalue::Use(_)
| Rvalue::CopyForDeref(_)
@@ -1828,7 +1862,15 @@ impl<'tcx> Rvalue<'tcx> {
| Rvalue::AddressOf(_, _)
| Rvalue::Len(_)
| Rvalue::Cast(
- CastKind::Misc | CastKind::Pointer(_) | CastKind::PointerFromExposedAddress,
+ CastKind::IntToInt
+ | CastKind::FloatToInt
+ | CastKind::FloatToFloat
+ | CastKind::IntToFloat
+ | CastKind::FnPtrToPtr
+ | CastKind::PtrToPtr
+ | CastKind::Pointer(_)
+ | CastKind::PointerFromExposedAddress
+ | CastKind::DynStar,
_,
_,
)
@@ -2043,13 +2085,13 @@ pub struct Constant<'tcx> {
}
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
-#[derive(Lift)]
+#[derive(Lift, TypeFoldable, TypeVisitable)]
pub enum ConstantKind<'tcx> {
/// This constant came from the type system
Ty(ty::Const<'tcx>),
/// An unevaluated mir constant which is not part of the type system.
- Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
+ Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
/// This constant cannot go back into the type system, as it represents
/// something the type system cannot handle (e.g. pointers).
@@ -2309,12 +2351,11 @@ impl<'tcx> ConstantKind<'tcx> {
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
.substs;
- let uneval = ty::Unevaluated {
+ let uneval = UnevaluatedConst {
def: ty::WithOptConstParam::unknown(def_id).to_global(),
substs,
promoted: None,
};
-
debug_assert!(!uneval.has_free_regions());
Self::Unevaluated(uneval, ty)
@@ -2398,7 +2439,7 @@ impl<'tcx> ConstantKind<'tcx> {
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
let span = tcx.hir().span(hir_id);
- let uneval = ty::Unevaluated::new(def.to_global(), substs);
+ let uneval = UnevaluatedConst::new(def.to_global(), substs);
debug!(?span, ?param_env);
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2411,7 +2452,7 @@ impl<'tcx> ConstantKind<'tcx> {
// Error was handled in `const_eval_resolve`. Here we just create a
// new unevaluated const and error hard later in codegen
Self::Unevaluated(
- ty::Unevaluated {
+ UnevaluatedConst {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None,
@@ -2434,6 +2475,34 @@ impl<'tcx> ConstantKind<'tcx> {
}
}
+/// An unevaluated (potentially generic) constant used in MIR.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
+pub struct UnevaluatedConst<'tcx> {
+ pub def: ty::WithOptConstParam<DefId>,
+ pub substs: SubstsRef<'tcx>,
+ pub promoted: Option<Promoted>,
+}
+
+impl<'tcx> UnevaluatedConst<'tcx> {
+ // FIXME: probably should get rid of this method. It's also wrong to
+ // shrink and then later expand a promoted.
+ #[inline]
+ pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
+ ty::UnevaluatedConst { def: self.def, substs: self.substs }
+ }
+}
+
+impl<'tcx> UnevaluatedConst<'tcx> {
+ #[inline]
+ pub fn new(
+ def: ty::WithOptConstParam<DefId>,
+ substs: SubstsRef<'tcx>,
+ ) -> UnevaluatedConst<'tcx> {
+ UnevaluatedConst { def, substs, promoted: Default::default() }
+ }
+}
+
/// A collection of projections into user types.
///
/// They are projections because a binding can occur a part of a
@@ -2727,7 +2796,7 @@ fn pretty_print_const_value<'tcx>(
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
//
- // NB: the `has_param_types_or_consts` check ensures that we can use
+ // NB: the `has_non_region_param` check ensures that we can use
// 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`
@@ -2735,7 +2804,7 @@ fn pretty_print_const_value<'tcx>(
//
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
// correct `ty::ParamEnv` to allow printing *all* constant values.
- (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
+ (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => {
let ct = tcx.lift(ct).unwrap();
let ty = tcx.lift(ty).unwrap();
if let Some(contents) = tcx.try_destructure_mir_constant(
@@ -2906,11 +2975,12 @@ impl Location {
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(BasicBlockData<'_>, 144);
static_assert_size!(LocalDecl<'_>, 56);
static_assert_size!(Statement<'_>, 32);
static_assert_size!(StatementKind<'_>, 16);
static_assert_size!(Terminator<'_>, 112);
static_assert_size!(TerminatorKind<'_>, 96);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 21ae121e1..15a24aa4a 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -81,7 +81,7 @@ impl<'tcx> MonoItem<'tcx> {
MonoItem::Fn(instance) => tcx.symbol_name(instance),
MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)),
MonoItem::GlobalAsm(item_id) => {
- SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id))
+ SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.owner_id))
}
}
}
@@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> {
match *self {
MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(),
MonoItem::Static(def_id) => def_id.as_local(),
- MonoItem::GlobalAsm(item_id) => Some(item_id.def_id),
+ MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id),
}
.map(|def_id| tcx.def_span(def_id))
}
@@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> {
}
}
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),
- MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.index()),
+ MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.index()),
},
item.symbol_name(tcx),
)
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 0b42137d4..05dcfba77 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
ty::ConstKind::Param(p) => format!("Param({})", p),
ty::ConstKind::Unevaluated(uv) => {
format!(
- "Unevaluated({}, {:?}, {:?})",
+ "Unevaluated({}, {:?})",
self.tcx.def_path_str(uv.def.did),
uv.substs,
- uv.promoted,
)
}
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index d89efe2b3..efd7357af 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -392,16 +392,9 @@ pub enum ClosureOutlivesSubject<'tcx> {
Region(ty::RegionVid),
}
-/// The constituent parts of a type level constant of kind ADT or array.
-#[derive(Copy, Clone, Debug, HashStable)]
-pub struct DestructuredConst<'tcx> {
- pub variant: Option<VariantIdx>,
- pub fields: &'tcx [ty::Const<'tcx>],
-}
-
/// The constituent parts of a mir constant of kind ADT or array.
#[derive(Copy, Clone, Debug, HashStable)]
-pub struct DestructuredMirConstant<'tcx> {
+pub struct DestructuredConstant<'tcx> {
pub variant: Option<VariantIdx>,
pub fields: &'tcx [ConstantKind<'tcx>],
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index c7d0283aa..85ef51f12 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -82,9 +82,10 @@ pub enum MirPhase {
/// access to. This occurs in generator bodies. Such locals do not behave like other locals,
/// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals -
/// all generator bodies are lowered and so all places that look like locals really are locals.
- /// - Const prop lints: The lint pass which reports eg `200_u8 + 200_u8` as an error is run as a
- /// part of analysis to runtime MIR lowering. This means that transformations which may supress
- /// such errors may not run on analysis MIR.
+ ///
+ /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part
+ /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that
+ /// transformations which may supress such errors should not run on analysis MIR.
Runtime(RuntimePhase),
}
@@ -829,6 +830,9 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
/// generator has more than one variant, the parent place's variant index must be set, indicating
/// which variant is being used. If it has just one variant, the variant index may or may not be
/// included - the single possible variant is inferred if it is not included.
+/// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the
+/// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an
+/// opaque type from the current crate is not well-formed.
/// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the
/// place as described in the documentation for the `ProjectionElem`. The resulting address is
/// the parent's address plus that offset, and the type is `T`. This is only legal if the parent
@@ -928,6 +932,10 @@ pub enum ProjectionElem<V, T> {
///
/// The included Symbol is the name of the variant, used for printing MIR.
Downcast(Option<Symbol>, VariantIdx),
+
+ /// Like an explicit cast from an opaque type to a concrete type, but without
+ /// requiring an intermediate variable.
+ OpaqueCast(T),
}
/// Alias for projections as they appear in places, where the base is a place
@@ -1141,8 +1149,12 @@ pub enum CastKind {
Pointer(PointerCast),
/// Cast into a dyn* object.
DynStar,
- /// Remaining unclassified casts.
- Misc,
+ IntToInt,
+ FloatToInt,
+ FloatToFloat,
+ IntToFloat,
+ PtrToPtr,
+ FnPtrToPtr,
}
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
@@ -1233,11 +1245,11 @@ pub enum BinOp {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
- // These are in alphabetical order, which is easy to maintain.
- #[cfg(not(bootstrap))]
+ // tidy-alphabetical-start
static_assert_size!(AggregateKind<'_>, 40);
static_assert_size!(Operand<'_>, 24);
static_assert_size!(Place<'_>, 16);
static_assert_size!(PlaceElem<'_>, 24);
static_assert_size!(Rvalue<'_>, 40);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 405003156..fa3adafd4 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -4,7 +4,6 @@
*/
use crate::mir::*;
-use crate::ty::subst::Subst;
use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_target::abi::VariantIdx;
@@ -57,7 +56,7 @@ impl<'tcx> PlaceTy<'tcx> {
/// `PlaceElem`, where we can just use the `Ty` that is already
/// stored inline on field projection elems.
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
- self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty)
+ self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty)
}
/// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -71,6 +70,7 @@ impl<'tcx> PlaceTy<'tcx> {
param_env: ty::ParamEnv<'tcx>,
elem: &ProjectionElem<V, T>,
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
+ mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
) -> PlaceTy<'tcx>
where
V: ::std::fmt::Debug,
@@ -109,6 +109,7 @@ impl<'tcx> PlaceTy<'tcx> {
PlaceTy { ty: self.ty, variant_index: Some(index) }
}
ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)),
+ ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)),
};
debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
answer
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 9d098c808..4c0974f86 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -26,6 +26,12 @@ TrivialTypeTraversalAndLiftImpls! {
GeneratorSavedLocal,
}
+TrivialTypeTraversalImpls! {
+ for <'tcx> {
+ ConstValue<'tcx>,
+ }
+}
+
impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
Ok(self)
@@ -49,25 +55,3 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
Ok(self)
}
}
-
-impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
- #[inline(always)]
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- folder.try_fold_mir_const(self)
- }
-}
-
-impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- match self {
- ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)),
- ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
- ConstantKind::Unevaluated(uv, t) => {
- Ok(ConstantKind::Unevaluated(uv.try_fold_with(folder)?, t.try_fold_with(folder)?))
- }
- }
- }
-}
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
index be19bb486..e7cd497b2 100644
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ b/compiler/rustc_middle/src/mir/type_visitable.rs
@@ -7,22 +7,3 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
ControlFlow::CONTINUE
}
}
-
-impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- visitor.visit_mir_const(*self)
- }
-}
-
-impl<'tcx> TypeSuperVisitable<'tcx> for ConstantKind<'tcx> {
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- match *self {
- ConstantKind::Ty(c) => c.visit_with(visitor),
- ConstantKind::Val(_, t) => t.visit_with(visitor),
- ConstantKind::Unevaluated(uv, t) => {
- uv.visit_with(visitor)?;
- t.visit_with(visitor)
- }
- }
- }
-}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index d9b24566b..ddcf3711b 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -1084,6 +1084,11 @@ macro_rules! visit_place_fns {
self.visit_ty(&mut new_ty, TyContext::Location(location));
if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None }
}
+ PlaceElem::OpaqueCast(ty) => {
+ let mut new_ty = ty;
+ self.visit_ty(&mut new_ty, TyContext::Location(location));
+ if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None }
+ }
PlaceElem::Deref
| PlaceElem::ConstantIndex { .. }
| PlaceElem::Subslice { .. }
@@ -1153,7 +1158,7 @@ macro_rules! visit_place_fns {
location: Location,
) {
match elem {
- ProjectionElem::Field(_field, ty) => {
+ ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 4b336ea62..3d720f09b 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -4,6 +4,9 @@
//! ["Queries: demand-driven compilation"](https://rustc-dev-guide.rust-lang.org/query.html).
//! This chapter includes instructions for adding new queries.
+use crate::ty::{self, print::describe_as_module, TyCtxt};
+use rustc_span::def_id::LOCAL_CRATE;
+
// Each of these queries corresponds to a function pointer field in the
// `Providers` struct for requesting a value of that type, and a method
// on `tcx: TyCtxt` (and `tcx.at(span)`) for doing that request in a way
@@ -17,19 +20,19 @@
// as they will raise an fatal error on query cycles instead.
rustc_queries! {
query trigger_delay_span_bug(key: DefId) -> () {
- desc { "trigger a delay span bug" }
+ desc { "triggering a delay span bug" }
}
- query resolutions(_: ()) -> &'tcx ty::ResolverOutputs {
+ query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt {
eval_always
no_hash
- desc { "get the resolver outputs" }
+ desc { "getting the resolver outputs" }
}
query resolver_for_lowering(_: ()) -> &'tcx Steal<ty::ResolverAstLowering> {
eval_always
no_hash
- desc { "get the resolver for lowering" }
+ desc { "getting the resolver for lowering" }
}
/// Return the span for a definition.
@@ -37,7 +40,7 @@ rustc_queries! {
/// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
/// of rustc_middle::hir::source_map.
query source_span(key: LocalDefId) -> Span {
- desc { "get the source span" }
+ desc { "getting the source span" }
}
/// Represents crate as a whole (as distinct from the top-level crate module).
@@ -49,14 +52,14 @@ rustc_queries! {
query hir_crate(key: ()) -> Crate<'tcx> {
arena_cache
eval_always
- desc { "get the crate HIR" }
+ desc { "getting the crate HIR" }
}
/// All items in the crate.
query hir_crate_items(_: ()) -> rustc_middle::hir::ModuleItems {
arena_cache
eval_always
- desc { "get HIR crate items" }
+ desc { "getting HIR crate items" }
}
/// The items in a module.
@@ -65,7 +68,7 @@ rustc_queries! {
/// Avoid calling this query directly.
query hir_module_items(key: LocalDefId) -> rustc_middle::hir::ModuleItems {
arena_cache
- desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
+ desc { |tcx| "getting HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
@@ -73,8 +76,8 @@ rustc_queries! {
///
/// This can be conveniently accessed by methods on `tcx.hir()`.
/// Avoid calling this query directly.
- query hir_owner(key: LocalDefId) -> Option<crate::hir::Owner<'tcx>> {
- desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) }
+ query hir_owner(key: hir::OwnerId) -> Option<crate::hir::Owner<'tcx>> {
+ 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`.
@@ -82,31 +85,31 @@ rustc_queries! {
/// 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 {
- desc { |tcx| "HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
+ desc { |tcx| "getting HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Gives access to the HIR node's parent for the HIR owner `key`.
///
/// This can be conveniently accessed by methods on `tcx.hir()`.
/// Avoid calling this query directly.
- query hir_owner_parent(key: LocalDefId) -> hir::HirId {
- desc { |tcx| "HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) }
+ query hir_owner_parent(key: hir::OwnerId) -> hir::HirId {
+ desc { |tcx| "getting HIR parent of `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Gives access to the HIR nodes and bodies inside the HIR owner `key`.
///
/// This can be conveniently accessed by methods on `tcx.hir()`.
/// Avoid calling this query directly.
- query hir_owner_nodes(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> {
- desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
+ query hir_owner_nodes(key: hir::OwnerId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> {
+ desc { |tcx| "getting HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Gives access to the HIR attributes inside the HIR owner `key`.
///
/// This can be conveniently accessed by methods on `tcx.hir()`.
/// Avoid calling this query directly.
- query hir_attrs(key: LocalDefId) -> &'tcx hir::AttributeMap<'tcx> {
- desc { |tcx| "HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
+ query hir_attrs(key: hir::OwnerId) -> &'tcx hir::AttributeMap<'tcx> {
+ desc { |tcx| "getting HIR owner attributes in `{}`", tcx.def_path_str(key.to_def_id()) }
}
/// Computes the `DefId` of the corresponding const parameter in case the `key` is a
@@ -135,7 +138,7 @@ rustc_queries! {
/// Given the def_id of a const-generic parameter, computes the associated default const
/// parameter. e.g. `fn example<const N: usize=3>` called on `N` would return `3`.
query const_param_default(param: DefId) -> ty::Const<'tcx> {
- desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) }
+ desc { |tcx| "computing const default for a given parameter `{}`", tcx.def_path_str(param) }
cache_on_disk_if { param.is_local() }
separate_provide_extern
}
@@ -164,7 +167,7 @@ rustc_queries! {
query collect_trait_impl_trait_tys(key: DefId)
-> Result<&'tcx FxHashMap<DefId, Ty<'tcx>>, ErrorGuaranteed>
{
- desc { "compare an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
+ desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
@@ -274,19 +277,24 @@ rustc_queries! {
separate_provide_extern
}
- query lint_levels(_: ()) -> LintLevelMap {
+ query shallow_lint_levels_on(key: hir::OwnerId) -> rustc_middle::lint::ShallowLintLevelMap {
+ eval_always // fetches `resolutions`
arena_cache
- eval_always
- desc { "computing the lint levels for items in this crate" }
+ desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key.to_def_id()) }
+ }
+
+ query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> {
+ arena_cache
+ desc { "computing `#[expect]`ed lints in this crate" }
}
query parent_module_from_def_id(key: LocalDefId) -> LocalDefId {
eval_always
- desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
+ desc { |tcx| "getting the parent module of `{}`", tcx.def_path_str(key.to_def_id()) }
}
query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
- desc { |tcx| "expansion that defined `{}`", tcx.def_path_str(key) }
+ desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
@@ -296,6 +304,32 @@ rustc_queries! {
separate_provide_extern
}
+ /// Checks whether a type is representable or infinitely sized
+ query representability(_: LocalDefId) -> rustc_middle::ty::Representability {
+ desc { "checking if `{}` is representable", tcx.def_path_str(key.to_def_id()) }
+ // infinitely sized types will cause a cycle
+ cycle_delay_bug
+ // we don't want recursive representability calls to be forced with
+ // incremental compilation because, if a cycle occurs, we need the
+ // entire cycle to be in memory for diagnostics
+ anon
+ }
+
+ /// An implementation detail for the `representability` query
+ query representability_adt_ty(_: Ty<'tcx>) -> rustc_middle::ty::Representability {
+ desc { "checking if `{}` is representable", key }
+ cycle_delay_bug
+ anon
+ }
+
+ /// 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> {
+ desc { "finding type parameters in the representation" }
+ arena_cache
+ no_hash
+ separate_provide_extern
+ }
+
/// Fetch the THIR for a given body. If typeck for that body failed, returns an empty `Thir`.
query thir_body(key: ty::WithOptConstParam<LocalDefId>)
-> Result<(&'tcx Steal<thir::Thir<'tcx>>, thir::ExprId), ErrorGuaranteed>
@@ -349,7 +383,7 @@ rustc_queries! {
/// See the README for the `mir` module for details.
query mir_const(key: ty::WithOptConstParam<LocalDefId>) -> &'tcx Steal<mir::Body<'tcx>> {
desc {
- |tcx| "processing MIR for {}`{}`",
+ |tcx| "preparing {}`{}` for borrow checking",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
@@ -361,7 +395,7 @@ rustc_queries! {
key: DefId
) -> Result<Option<&'tcx [ty::abstract_const::Node<'tcx>]>, ErrorGuaranteed> {
desc {
- |tcx| "building an abstract representation for {}", tcx.def_path_str(key),
+ |tcx| "building an abstract representation for `{}`", tcx.def_path_str(key),
}
separate_provide_extern
}
@@ -371,16 +405,16 @@ rustc_queries! {
) -> Result<Option<&'tcx [ty::abstract_const::Node<'tcx>]>, ErrorGuaranteed> {
desc {
|tcx|
- "building an abstract representation for the const argument {}",
+ "building an abstract representation for the const argument `{}`",
tcx.def_path_str(key.0.to_def_id()),
}
}
query try_unify_abstract_consts(key:
- ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
+ ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>
)>) -> bool {
desc {
- |tcx| "trying to unify the generic constants {} and {}",
+ |tcx| "trying to unify the generic constants `{}` and `{}`",
tcx.def_path_str(key.value.0.def.did), tcx.def_path_str(key.value.1.def.did)
}
}
@@ -402,7 +436,7 @@ rustc_queries! {
query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> {
desc {
- |tcx| "MIR for CTFE of the const argument `{}`",
+ |tcx| "caching MIR for CTFE of the const argument `{}`",
tcx.def_path_str(key.0.to_def_id())
}
}
@@ -414,7 +448,7 @@ rustc_queries! {
) {
no_hash
desc {
- |tcx| "processing {}`{}`",
+ |tcx| "processing MIR for {}`{}`",
if key.const_param_did.is_some() { "the const argument " } else { "" },
tcx.def_path_str(key.did.to_def_id()),
}
@@ -425,7 +459,7 @@ rustc_queries! {
) -> Vec<rustc_span::Symbol> {
arena_cache
desc {
- |tcx| "symbols for captures of closure `{}` in `{}`",
+ |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())
}
@@ -487,12 +521,12 @@ rustc_queries! {
// queries). Making it anonymous avoids hashing the result, which
// may save a bit of time.
anon
- desc { "erasing regions from `{:?}`", ty }
+ desc { "erasing regions from `{}`", ty }
}
query wasm_import_module_map(_: CrateNum) -> FxHashMap<DefId, String> {
arena_cache
- desc { "wasm import module map" }
+ desc { "getting wasm import module map" }
}
/// Maps from the `DefId` of an item (trait/struct/enum/fn) to the
@@ -582,16 +616,8 @@ rustc_queries! {
separate_provide_extern
}
- // The cycle error here should be reported as an error by `check_representable`.
- // We consider the type as Sized in the meanwhile to avoid
- // further errors (done in impl Value for AdtSizedConstraint).
- // Use `cycle_delay_bug` to delay the cycle error here to be emitted later
- // in case we accidentally otherwise don't emit an error.
- query adt_sized_constraint(
- key: DefId
- ) -> AdtSizedConstraint<'tcx> {
+ query adt_sized_constraint(key: DefId) -> &'tcx [Ty<'tcx>] {
desc { |tcx| "computing `Sized` constraints for `{}`", tcx.def_path_str(key) }
- cycle_delay_bug
}
query adt_dtorck_constraint(
@@ -680,7 +706,7 @@ rustc_queries! {
/// Collects the associated items defined on a trait or impl.
query associated_items(key: DefId) -> ty::AssocItems<'tcx> {
arena_cache
- desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) }
+ desc { |tcx| "collecting associated items of `{}`", tcx.def_path_str(key) }
}
/// Maps from associated items on a trait to the corresponding associated
@@ -706,7 +732,7 @@ rustc_queries! {
///`{ trait_f: impl_f, trait_g: impl_g }`
query impl_item_implementor_ids(impl_id: DefId) -> FxHashMap<DefId, DefId> {
arena_cache
- desc { |tcx| "comparing impl items against trait for {}", tcx.def_path_str(impl_id) }
+ desc { |tcx| "comparing impl items against trait for `{}`", tcx.def_path_str(impl_id) }
}
/// Given an `impl_id`, return the trait it implements.
@@ -778,7 +804,7 @@ rustc_queries! {
/// Note that we've liberated the late bound regions of function signatures, so
/// this can not be used to check whether these types are well formed.
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
- desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) }
+ desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
}
/// Computes the signature of the function.
@@ -827,7 +853,7 @@ rustc_queries! {
}
query check_liveness(key: DefId) {
- desc { |tcx| "checking liveness of variables in {}", tcx.def_path_str(key) }
+ desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key) }
}
/// Return the live symbols in the crate for dead code check.
@@ -839,7 +865,7 @@ rustc_queries! {
FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
) {
arena_cache
- desc { "find live symbols in crate" }
+ desc { "finding live symbols in crate" }
}
query check_mod_deathness(key: LocalDefId) -> () {
@@ -886,8 +912,8 @@ rustc_queries! {
cache_on_disk_if { true }
}
- query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet<LocalDefId> {
- desc { |tcx| "used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) }
+ query used_trait_imports(key: LocalDefId) -> &'tcx UnordSet<LocalDefId> {
+ desc { |tcx| "finding used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
@@ -916,7 +942,7 @@ rustc_queries! {
/// Not meant to be used directly outside of coherence.
query crate_inherent_impls(k: ()) -> CrateInherentImpls {
arena_cache
- desc { "all inherent impls defined in crate" }
+ desc { "finding all inherent impls defined in crate" }
}
/// Checks all types in the crate for overlap in their inherent impls. Reports errors.
@@ -1003,8 +1029,10 @@ rustc_queries! {
/// Tries to destructure an `mir::ConstantKind` ADT or array into its variant index
/// and its field values.
- query try_destructure_mir_constant(key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>) -> Option<mir::DestructuredMirConstant<'tcx>> {
- desc { "destructuring mir constant"}
+ query try_destructure_mir_constant(
+ key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
+ ) -> Option<mir::DestructuredConstant<'tcx>> {
+ desc { "destructuring MIR constant"}
remap_env_constness
}
@@ -1013,12 +1041,12 @@ rustc_queries! {
query deref_mir_constant(
key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
) -> mir::ConstantKind<'tcx> {
- desc { "dereferencing mir constant" }
+ desc { "dereferencing MIR constant" }
remap_env_constness
}
query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
- desc { "get a &core::panic::Location referring to a span" }
+ desc { "getting a &core::panic::Location referring to a span" }
}
// FIXME get rid of this with valtrees
@@ -1037,10 +1065,10 @@ rustc_queries! {
cache_on_disk_if { key.is_local() }
}
- /// Performs part of the privacy check and computes "access levels".
- query privacy_access_levels(_: ()) -> &'tcx AccessLevels {
+ /// Performs part of the privacy check and computes effective visibilities.
+ query effective_visibilities(_: ()) -> &'tcx EffectiveVisibilities {
eval_always
- desc { "privacy access levels" }
+ desc { "checking effective visibilities" }
}
query check_private_in_public(_: ()) -> () {
eval_always
@@ -1124,6 +1152,11 @@ rustc_queries! {
desc { |tcx| "checking whether `{}` is `doc(hidden)`", tcx.def_path_str(def_id) }
}
+ /// Determines whether an item is annotated with `doc(notable_trait)`.
+ query is_doc_notable_trait(def_id: DefId) -> bool {
+ desc { |tcx| "checking whether `{}` is `doc(notable_trait)`", tcx.def_path_str(def_id) }
+ }
+
/// Returns the attributes on the item at `def_id`.
///
/// Do not use this directly, use `tcx.get_attrs` instead.
@@ -1163,29 +1196,29 @@ rustc_queries! {
}
query is_ctfe_mir_available(key: DefId) -> bool {
- desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) }
+ desc { |tcx| "checking if item has CTFE MIR available: `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query is_mir_available(key: DefId) -> bool {
- desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) }
+ desc { |tcx| "checking if item has MIR available: `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}
query own_existential_vtable_entries(
- key: ty::PolyExistentialTraitRef<'tcx>
+ key: DefId
) -> &'tcx [DefId] {
- desc { |tcx| "finding all existential vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
+ desc { |tcx| "finding all existential vtable entries for trait `{}`", tcx.def_path_str(key) }
}
query vtable_entries(key: ty::PolyTraitRef<'tcx>)
-> &'tcx [ty::VtblEntry<'tcx>] {
- desc { |tcx| "finding all vtable entries for trait {}", tcx.def_path_str(key.def_id()) }
+ desc { |tcx| "finding all vtable entries for trait `{}`", tcx.def_path_str(key.def_id()) }
}
- query vtable_trait_upcasting_coercion_new_vptr_slot(key: (ty::Ty<'tcx>, ty::Ty<'tcx>)) -> Option<usize> {
- desc { |tcx| "finding the slot within vtable for trait object {} vtable ptr during trait upcasting coercion from {} vtable",
+ query vtable_trait_upcasting_coercion_new_vptr_slot(key: (Ty<'tcx>, Ty<'tcx>)) -> Option<usize> {
+ desc { |tcx| "finding the slot within vtable for trait object `{}` vtable ptr during trait upcasting coercion from `{}` vtable",
key.1, key.0 }
}
@@ -1205,13 +1238,13 @@ rustc_queries! {
/// Return all `impl` blocks in the current crate.
query all_local_trait_impls(_: ()) -> &'tcx rustc_data_structures::fx::FxIndexMap<DefId, Vec<LocalDefId>> {
- desc { "local trait impls" }
+ desc { "finding local trait impls" }
}
/// Given a trait `trait_id`, return all known `impl` blocks.
query trait_impls_of(trait_id: DefId) -> ty::trait_def::TraitImpls {
arena_cache
- desc { |tcx| "trait impls of `{}`", tcx.def_path_str(trait_id) }
+ desc { |tcx| "finding trait impls of `{}`", tcx.def_path_str(trait_id) }
}
query specialization_graph_of(trait_id: DefId) -> specialization_graph::Graph {
@@ -1220,7 +1253,7 @@ rustc_queries! {
cache_on_disk_if { true }
}
query object_safety_violations(trait_id: DefId) -> &'tcx [traits::ObjectSafetyViolation] {
- desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(trait_id) }
+ desc { |tcx| "determining object safety of trait `{}`", tcx.def_path_str(trait_id) }
}
/// Gets the ParameterEnvironment for a given item; this environment
@@ -1278,7 +1311,7 @@ rustc_queries! {
/// correctly.
query has_structural_eq_impls(ty: Ty<'tcx>) -> bool {
desc {
- "computing whether `{:?}` implements `PartialStructuralEq` and `StructuralEq`",
+ "computing whether `{}` implements `PartialStructuralEq` and `StructuralEq`",
ty
}
}
@@ -1337,13 +1370,13 @@ rustc_queries! {
query dylib_dependency_formats(_: CrateNum)
-> &'tcx [(CrateNum, LinkagePreference)] {
- desc { "dylib dependency formats of crate" }
+ desc { "getting dylib dependency formats of crate" }
separate_provide_extern
}
query dependency_formats(_: ()) -> Lrc<crate::middle::dependency_format::Dependencies> {
arena_cache
- desc { "get the linkage format of all dependencies" }
+ desc { "getting the linkage format of all dependencies" }
}
query is_compiler_builtins(_: CrateNum) -> bool {
@@ -1365,31 +1398,31 @@ rustc_queries! {
}
query is_profiler_runtime(_: CrateNum) -> bool {
fatal_cycle
- desc { "query a crate is `#![profiler_runtime]`" }
+ desc { "checking if a crate is `#![profiler_runtime]`" }
separate_provide_extern
}
query has_ffi_unwind_calls(key: LocalDefId) -> bool {
- desc { |tcx| "check if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) }
+ desc { |tcx| "checking if `{}` contains FFI-unwind calls", tcx.def_path_str(key.to_def_id()) }
cache_on_disk_if { true }
}
query required_panic_strategy(_: CrateNum) -> Option<PanicStrategy> {
fatal_cycle
- desc { "query a crate's required panic strategy" }
+ desc { "getting a crate's required panic strategy" }
separate_provide_extern
}
query panic_in_drop_strategy(_: CrateNum) -> PanicStrategy {
fatal_cycle
- desc { "query a crate's configured panic-in-drop strategy" }
+ desc { "getting a crate's configured panic-in-drop strategy" }
separate_provide_extern
}
query is_no_builtins(_: CrateNum) -> bool {
fatal_cycle
- desc { "test whether a crate has `#![no_builtins]`" }
+ desc { "getting whether a crate has `#![no_builtins]`" }
separate_provide_extern
}
query symbol_mangling_version(_: CrateNum) -> SymbolManglingVersion {
fatal_cycle
- desc { "query a crate's symbol mangling version" }
+ desc { "getting a crate's symbol mangling version" }
separate_provide_extern
}
@@ -1402,9 +1435,9 @@ rustc_queries! {
query specializes(_: (DefId, DefId)) -> bool {
desc { "computing whether impls specialize one another" }
}
- query in_scope_traits_map(_: LocalDefId)
+ query in_scope_traits_map(_: hir::OwnerId)
-> Option<&'tcx FxHashMap<ItemLocalId, Box<[TraitCandidate]>>> {
- desc { "traits in scope at a block" }
+ desc { "getting traits in scope at a block" }
}
query module_reexports(def_id: LocalDefId) -> Option<&'tcx [ModChild]> {
@@ -1417,7 +1450,7 @@ rustc_queries! {
separate_provide_extern
}
- query check_well_formed(key: LocalDefId) -> () {
+ query check_well_formed(key: hir::OwnerId) -> () {
desc { |tcx| "checking that `{}` is well-formed", tcx.def_path_str(key.to_def_id()) }
}
@@ -1554,18 +1587,8 @@ rustc_queries! {
separate_provide_extern
}
- query is_dllimport_foreign_item(def_id: DefId) -> bool {
- desc { |tcx| "is_dllimport_foreign_item({})", tcx.def_path_str(def_id) }
- }
- query is_statically_included_foreign_item(def_id: DefId) -> bool {
- desc { |tcx| "is_statically_included_foreign_item({})", tcx.def_path_str(def_id) }
- }
- query native_library_kind(def_id: DefId)
- -> Option<NativeLibKind> {
- desc { |tcx| "native_library_kind({})", tcx.def_path_str(def_id) }
- }
query native_library(def_id: DefId) -> Option<&'tcx NativeLib> {
- desc { |tcx| "native_library({})", tcx.def_path_str(def_id) }
+ desc { |tcx| "getting the native library for `{}`", tcx.def_path_str(def_id) }
}
/// Does lifetime resolution, but does not descend into trait items. This
@@ -1584,7 +1607,7 @@ rustc_queries! {
arena_cache
desc { "resolving lifetimes" }
}
- query named_region_map(_: LocalDefId) ->
+ query named_region_map(_: hir::OwnerId) ->
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
desc { "looking up a named region" }
}
@@ -1600,7 +1623,7 @@ rustc_queries! {
desc { "looking up lifetime defaults for generic parameter `{}`", tcx.def_path_str(key) }
separate_provide_extern
}
- query late_bound_vars_map(_: LocalDefId)
+ query late_bound_vars_map(_: hir::OwnerId)
-> Option<&'tcx FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>> {
desc { "looking up late bound vars" }
}
@@ -1620,14 +1643,13 @@ rustc_queries! {
separate_provide_extern
}
- /// Computes the set of modules from which this type is visibly uninhabited.
- /// To check whether a type is uninhabited at all (not just from a given module), you could
- /// check whether the forest is empty.
- query type_uninhabited_from(
- key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
- ) -> ty::inhabitedness::DefIdForest<'tcx> {
- desc { "computing the inhabitedness of `{:?}`", key }
- remap_env_constness
+ query inhabited_predicate_adt(key: DefId) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
+ desc { "computing the uninhabited predicate of `{:?}`", key }
+ }
+
+ /// Do not call this query directly: invoke `Ty::inhabited_predicate` instead.
+ query inhabited_predicate_type(key: Ty<'tcx>) -> ty::inhabitedness::InhabitedPredicate<'tcx> {
+ desc { "computing the uninhabited predicate of `{}`", key }
}
query dep_kind(_: CrateNum) -> CrateDepKind {
@@ -1665,7 +1687,7 @@ rustc_queries! {
}
/// Whether the function is an intrinsic
query is_intrinsic(def_id: DefId) -> bool {
- desc { |tcx| "is_intrinsic({})", tcx.def_path_str(def_id) }
+ desc { |tcx| "checking whether `{}` is an intrinsic", tcx.def_path_str(def_id) }
separate_provide_extern
}
/// Returns the lang items defined in another crate by loading it from metadata.
@@ -1732,12 +1754,12 @@ rustc_queries! {
/// is marked as a private dependency
query is_private_dep(c: CrateNum) -> bool {
eval_always
- desc { "check whether crate {} is a private dependency", c }
+ desc { "checking whether crate `{}` is a private dependency", c }
separate_provide_extern
}
query allocator_kind(_: ()) -> Option<AllocatorKind> {
eval_always
- desc { "allocator kind for the current crate" }
+ desc { "getting the allocator kind for the current crate" }
}
query upvars_mentioned(def_id: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
@@ -1750,7 +1772,7 @@ rustc_queries! {
desc { "looking up all possibly unused extern crates" }
}
query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
- desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
+ desc { |tcx| "finding names imported by glob use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
}
query stability_index(_: ()) -> stability::Index {
@@ -1776,7 +1798,7 @@ rustc_queries! {
/// correspond to a publicly visible symbol in `cnum` machine code.
/// - The `exported_symbols` sets of different crates do not intersect.
query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
- desc { "exported_symbols" }
+ desc { "collecting exported symbols for crate `{}`", cnum}
cache_on_disk_if { *cnum == LOCAL_CRATE }
separate_provide_extern
}
@@ -1785,6 +1807,7 @@ rustc_queries! {
eval_always
desc { "collect_and_partition_mono_items" }
}
+
query is_codegened_item(def_id: DefId) -> bool {
desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) }
}
@@ -1792,12 +1815,13 @@ rustc_queries! {
/// All items participating in code generation together with items inlined into them.
query codegened_and_inlined_items(_: ()) -> &'tcx DefIdSet {
eval_always
- desc { "codegened_and_inlined_items" }
+ desc { "collecting codegened and inlined items" }
}
- query codegen_unit(_: Symbol) -> &'tcx CodegenUnit<'tcx> {
- desc { "codegen_unit" }
+ query codegen_unit(sym: Symbol) -> &'tcx CodegenUnit<'tcx> {
+ desc { "getting codegen unit `{sym}`" }
}
+
query unused_generic_params(key: ty::InstanceDef<'tcx>) -> FiniteBitSet<u32> {
cache_on_disk_if { key.def_id().is_local() }
desc {
@@ -1806,6 +1830,7 @@ rustc_queries! {
}
separate_provide_extern
}
+
query backend_optimization_level(_: ()) -> OptLevel {
desc { "optimization level used by backend" }
}
@@ -1816,7 +1841,7 @@ rustc_queries! {
/// has been destroyed.
query output_filenames(_: ()) -> &'tcx Arc<OutputFilenames> {
eval_always
- desc { "output_filenames" }
+ desc { "getting output filenames" }
}
/// Do not call this query directly: invoke `normalize` instead.
@@ -1826,7 +1851,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
NoSolution,
> {
- desc { "normalizing `{:?}`", goal }
+ desc { "normalizing `{}`", goal.value.value }
remap_env_constness
}
@@ -1838,21 +1863,13 @@ rustc_queries! {
remap_env_constness
}
- /// Do not call this query directly: invoke `try_normalize_erasing_regions` instead.
- query try_normalize_mir_const_after_erasing_regions(
- goal: ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
- ) -> Result<mir::ConstantKind<'tcx>, NoSolution> {
- desc { "normalizing `{}`", goal.value }
- remap_env_constness
- }
-
query implied_outlives_bounds(
goal: CanonicalTyGoal<'tcx>
) -> Result<
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
NoSolution,
> {
- desc { "computing implied outlives bounds for `{:?}`", goal }
+ desc { "computing implied outlives bounds for `{}`", goal.value.value }
remap_env_constness
}
@@ -1864,7 +1881,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>,
NoSolution,
> {
- desc { "computing dropck types for `{:?}`", goal }
+ desc { "computing dropck types for `{}`", goal.value.value }
remap_env_constness
}
@@ -1892,7 +1909,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
- desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal }
+ desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal.value.value }
remap_env_constness
}
@@ -1903,7 +1920,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
- desc { "evaluating `type_op_eq` `{:?}`", goal }
+ desc { "evaluating `type_op_eq` `{:?}`", goal.value.value }
remap_env_constness
}
@@ -1914,7 +1931,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
- desc { "evaluating `type_op_subtype` `{:?}`", goal }
+ desc { "evaluating `type_op_subtype` `{:?}`", goal.value.value }
remap_env_constness
}
@@ -1925,7 +1942,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>,
NoSolution,
> {
- desc { "evaluating `type_op_prove_predicate` `{:?}`", goal }
+ desc { "evaluating `type_op_prove_predicate` `{:?}`", goal.value.value }
}
/// Do not call this query directly: part of the `Normalize` type-op
@@ -1935,7 +1952,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>,
NoSolution,
> {
- desc { "normalizing `{:?}`", goal }
+ desc { "normalizing `{}`", goal.value.value.value }
remap_env_constness
}
@@ -1946,7 +1963,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>,
NoSolution,
> {
- desc { "normalizing `{:?}`", goal }
+ desc { "normalizing `{:?}`", goal.value.value.value }
remap_env_constness
}
@@ -1957,7 +1974,7 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>,
NoSolution,
> {
- desc { "normalizing `{:?}`", goal }
+ desc { "normalizing `{:?}`", goal.value.value.value }
remap_env_constness
}
@@ -1968,20 +1985,20 @@ rustc_queries! {
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>,
NoSolution,
> {
- desc { "normalizing `{:?}`", goal }
+ desc { "normalizing `{:?}`", goal.value.value.value }
remap_env_constness
}
query subst_and_check_impossible_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
desc { |tcx|
- "impossible substituted predicates:`{}`",
+ "checking impossible substituted predicates: `{}`",
tcx.def_path_str(key.0)
}
}
query is_impossible_method(key: (DefId, DefId)) -> bool {
desc { |tcx|
- "checking if {} is impossible to call within {}",
+ "checking if `{}` is impossible to call within `{}`",
tcx.def_path_str(key.1),
tcx.def_path_str(key.0),
}
@@ -1990,7 +2007,7 @@ rustc_queries! {
query method_autoderef_steps(
goal: CanonicalTyGoal<'tcx>
) -> MethodAutoderefStepsResult<'tcx> {
- desc { "computing autoderef types for `{:?}`", goal }
+ desc { "computing autoderef types for `{}`", goal.value.value }
remap_env_constness
}
@@ -2038,7 +2055,7 @@ rustc_queries! {
}
query normalize_opaque_types(key: &'tcx ty::List<ty::Predicate<'tcx>>) -> &'tcx ty::List<ty::Predicate<'tcx>> {
- desc { "normalizing opaque types in {:?}", key }
+ desc { "normalizing opaque types in `{:?}`", key }
}
/// Checks whether a type is definitely uninhabited. This is
@@ -2048,7 +2065,7 @@ rustc_queries! {
/// will be `Abi::Uninhabited`. (Note that uninhabited types may have nonzero
/// size, to account for partial initialisation. See #49298 for details.)
query conservative_is_privately_uninhabited(key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
- desc { "conservatively checking if {:?} is privately uninhabited", key }
+ desc { "conservatively checking if `{}` is privately uninhabited", key.value }
remap_env_constness
}
@@ -2068,7 +2085,7 @@ rustc_queries! {
arena_cache
eval_always
no_hash
- desc { "performing HIR wf-checking for predicate {:?} at item {:?}", key.0, key.1 }
+ desc { "performing HIR wf-checking for predicate `{:?}` at item `{:?}`", key.0, key.1 }
}
@@ -2087,10 +2104,21 @@ rustc_queries! {
}
query permits_uninit_init(key: TyAndLayout<'tcx>) -> bool {
- desc { "checking to see if {:?} permits being left uninit", key.ty }
+ 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 }
+ desc { "checking to see if `{}` permits being left zeroed", key.ty }
+ }
+
+ query compare_assoc_const_impl_item_with_trait_item(
+ key: (LocalDefId, DefId)
+ ) -> Result<(), ErrorGuaranteed> {
+ desc { |tcx| "checking assoc const `{}` has the same type as trait item", tcx.def_path_str(key.0.to_def_id()) }
+ }
+
+ query deduced_param_attrs(def_id: DefId) -> &'tcx [ty::DeducedParamAttrs] {
+ desc { |tcx| "deducing parameter attributes for {}", tcx.def_path_str(def_id) }
+ separate_provide_extern
}
}
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 86b415050..ea7a507d7 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -203,7 +203,7 @@ pub enum StmtKind<'tcx> {
/// `let pat: ty = <INIT>`
initializer: Option<ExprId>,
- /// `let pat: ty = <INIT> else { <ELSE> }
+ /// `let pat: ty = <INIT> else { <ELSE> }`
else_block: Option<BlockId>,
/// The lint level for this `let` statement.
@@ -848,16 +848,13 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
mod size_asserts {
use super::*;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(Block, 56);
static_assert_size!(Expr<'_>, 64);
static_assert_size!(ExprKind<'_>, 40);
- #[cfg(not(bootstrap))]
static_assert_size!(Pat<'_>, 72);
- #[cfg(not(bootstrap))]
static_assert_size!(PatKind<'_>, 56);
- #[cfg(not(bootstrap))]
static_assert_size!(Stmt<'_>, 48);
- #[cfg(not(bootstrap))]
static_assert_size!(StmtKind<'_>, 40);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 68a7af0b8..e73d44bbb 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -598,11 +598,6 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
/// // type parameters, ImplSource will carry resolutions for those as well:
/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
///
-/// // Case A: ImplSource points at a specific impl. Only possible when
-/// // type is concretely known. If the impl itself has bounded
-/// // type parameters, ImplSource will carry resolutions for those as well:
-/// concrete.clone(); // ImplSource(Impl_1, [ImplSource(Impl_2, [ImplSource(Impl_3)])])
-///
/// // Case B: ImplSource must be provided by caller. This applies when
/// // type is a type parameter.
/// param.clone(); // ImplSource::Param
@@ -664,10 +659,6 @@ pub enum ImplSource<'tcx, N> {
/// ImplSource for a `const Drop` implementation.
ConstDestruct(ImplSourceConstDestructData<N>),
-
- /// ImplSource for a `std::marker::Tuple` implementation.
- /// This has no nested predicates ever, so no data.
- Tuple,
}
impl<'tcx, N> ImplSource<'tcx, N> {
@@ -682,8 +673,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
ImplSource::Object(d) => d.nested,
ImplSource::FnPointer(d) => d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData)
- | ImplSource::Tuple => Vec::new(),
+ | ImplSource::Pointee(ImplSourcePointeeData) => vec![],
ImplSource::TraitAlias(d) => d.nested,
ImplSource::TraitUpcasting(d) => d.nested,
ImplSource::ConstDestruct(i) => i.nested,
@@ -701,8 +691,7 @@ impl<'tcx, N> ImplSource<'tcx, N> {
ImplSource::Object(d) => &d.nested,
ImplSource::FnPointer(d) => &d.nested,
ImplSource::DiscriminantKind(ImplSourceDiscriminantKindData)
- | ImplSource::Pointee(ImplSourcePointeeData)
- | ImplSource::Tuple => &[],
+ | ImplSource::Pointee(ImplSourcePointeeData) => &[],
ImplSource::TraitAlias(d) => &d.nested,
ImplSource::TraitUpcasting(d) => &d.nested,
ImplSource::ConstDestruct(i) => &i.nested,
@@ -769,7 +758,6 @@ impl<'tcx, N> ImplSource<'tcx, N> {
nested: i.nested.into_iter().map(f).collect(),
})
}
- ImplSource::Tuple => ImplSource::Tuple,
}
}
}
diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs
index 0e6cacb9f..fb152b63f 100644
--- a/compiler/rustc_middle/src/traits/query.rs
+++ b/compiler/rustc_middle/src/traits/query.rs
@@ -8,8 +8,9 @@
use crate::error::DropCheckOverflow;
use crate::infer::canonical::{Canonical, QueryResponse};
use crate::ty::error::TypeError;
-use crate::ty::subst::GenericArg;
+use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::{self, Ty, TyCtxt};
+use rustc_hir::def_id::DefId;
use rustc_span::source_map::Span;
use std::iter::FromIterator;
@@ -219,4 +220,5 @@ pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),
RegionSubProjection(ty::Region<'tcx>, ty::ProjectionTy<'tcx>),
+ RegionSubOpaque(ty::Region<'tcx>, DefId, SubstsRef<'tcx>),
}
diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs
index 53af3e905..85ead3171 100644
--- a/compiler/rustc_middle/src/traits/select.rs
+++ b/compiler/rustc_middle/src/traits/select.rs
@@ -115,12 +115,13 @@ pub enum SelectionCandidate<'tcx> {
ParamCandidate(ty::PolyTraitPredicate<'tcx>),
ImplCandidate(DefId),
- AutoImplCandidate(DefId),
+ AutoImplCandidate,
/// This is a trait matching with a projected type as `Self`, and we found
/// an applicable bound in the trait definition. The `usize` is an index
- /// into the list returned by `tcx.item_bounds`.
- ProjectionCandidate(usize),
+ /// into the list returned by `tcx.item_bounds`. The constness is the
+ /// constness of the bound in the trait.
+ ProjectionCandidate(usize, ty::BoundConstness),
/// Implementation of a `Fn`-family trait by one of the anonymous types
/// generated for an `||` expression.
@@ -142,7 +143,7 @@ pub enum SelectionCandidate<'tcx> {
/// Builtin implementation of `Pointee`.
PointeeCandidate,
- TraitAliasCandidate(DefId),
+ TraitAliasCandidate,
/// Matching `dyn Trait` with a supertrait of `Trait`. The index is the
/// position in the iterator returned by
@@ -160,9 +161,6 @@ pub enum SelectionCandidate<'tcx> {
/// Implementation of `const Destruct`, optionally from a custom `impl const Drop`.
ConstDestructCandidate(Option<DefId>),
-
- /// Witnesses the fact that a type is a tuple.
- TupleCandidate,
}
/// The result of trait evaluation. The order is important
diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs
index c526344e1..7fbd57ac7 100644
--- a/compiler/rustc_middle/src/traits/structural_impls.rs
+++ b/compiler/rustc_middle/src/traits/structural_impls.rs
@@ -34,8 +34,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> {
super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d),
super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d),
-
- super::ImplSource::Tuple => write!(f, "ImplSource::Tuple"),
}
}
}
diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs
index 8f79b4705..1aa4df778 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::mir;
use crate::ty::visit::TypeVisitable;
-use crate::ty::{self, subst::Subst, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt};
+use crate::ty::{self, DelaySpanBugEmitted, EarlyBinder, SubstsRef, Ty, TyCtxt};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use std::cmp;
@@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
impl<'tcx> AbstractConst<'tcx> {
pub fn new(
tcx: TyCtxt<'tcx>,
- uv: ty::Unevaluated<'tcx, ()>,
+ uv: ty::UnevaluatedConst<'tcx>,
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
@@ -71,16 +71,16 @@ impl<'tcx> AbstractConst<'tcx> {
walk_abstract_const::<!, _>(tcx, self, |node| {
match node.root(tcx) {
Node::Leaf(leaf) => {
- if leaf.has_infer_types_or_consts() {
+ if leaf.has_non_region_infer() {
failure_kind = FailureKind::MentionsInfer;
- } else if leaf.has_param_types_or_consts() {
+ } else if leaf.has_non_region_param() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
}
Node::Cast(_, _, ty) => {
- if ty.has_infer_types_or_consts() {
+ if ty.has_non_region_infer() {
failure_kind = FailureKind::MentionsInfer;
- } else if ty.has_param_types_or_consts() {
+ } else if ty.has_non_region_param() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
}
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index b809f1767..4682ac96b 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -101,6 +101,9 @@ pub enum Adjust<'tcx> {
Borrow(AutoBorrow<'tcx>),
Pointer(PointerCast),
+
+ /// Cast into a dyn* object.
+ DynStar,
}
/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 2e596b275..b0a2412ab 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -26,9 +26,6 @@ use super::{
Destructor, FieldDef, GenericPredicates, ReprOptions, Ty, TyCtxt, VariantDef, VariantDiscr,
};
-#[derive(Copy, Clone, HashStable, Debug)]
-pub struct AdtSizedConstraint<'tcx>(pub &'tcx [Ty<'tcx>]);
-
bitflags! {
#[derive(HashStable, TyEncodable, TyDecodable)]
pub struct AdtFlags: u32 {
@@ -332,13 +329,13 @@ impl<'tcx> AdtDef<'tcx> {
self.flags().contains(AdtFlags::IS_PHANTOM_DATA)
}
- /// Returns `true` if this is Box<T>.
+ /// Returns `true` if this is `Box<T>`.
#[inline]
pub fn is_box(self) -> bool {
self.flags().contains(AdtFlags::IS_BOX)
}
- /// Returns `true` if this is UnsafeCell<T>.
+ /// Returns `true` if this is `UnsafeCell<T>`.
#[inline]
pub fn is_unsafe_cell(self) -> bool {
self.flags().contains(AdtFlags::IS_UNSAFE_CELL)
@@ -438,7 +435,8 @@ impl<'tcx> AdtDef<'tcx> {
| Res::Def(DefKind::Union, _)
| Res::Def(DefKind::TyAlias, _)
| Res::Def(DefKind::AssocTy, _)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::SelfCtor(..) => self.non_enum_variant(),
_ => bug!("unexpected res {:?} in variant_of_res", res),
}
@@ -457,11 +455,9 @@ impl<'tcx> AdtDef<'tcx> {
Some(Discr { val: b, ty })
} else {
info!("invalid enum discriminant: {:#?}", val);
- crate::mir::interpret::struct_error(
- tcx.at(tcx.def_span(expr_did)),
- "constant evaluation of enum discriminant resulted in non-integer",
- )
- .emit();
+ tcx.sess.emit_err(crate::error::ConstEvalNonIntError {
+ span: tcx.def_span(expr_did),
+ });
None
}
}
@@ -564,6 +560,13 @@ impl<'tcx> AdtDef<'tcx> {
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
- ty::EarlyBinder(tcx.adt_sized_constraint(self.did()).0)
+ ty::EarlyBinder(tcx.adt_sized_constraint(self.did()))
}
}
+
+#[derive(Clone, Copy, Debug)]
+#[derive(HashStable)]
+pub enum Representability {
+ Representable,
+ Infinite,
+}
diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs
index 981e2d3b6..e65585955 100644
--- a/compiler/rustc_middle/src/ty/cast.rs
+++ b/compiler/rustc_middle/src/ty/cast.rs
@@ -2,6 +2,7 @@
// typeck and codegen.
use crate::ty::{self, Ty};
+use rustc_middle::mir;
use rustc_macros::HashStable;
@@ -38,7 +39,7 @@ pub enum CastTy<'tcx> {
}
/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
-/// (or librustc_typeck/check/cast.rs).
+/// (or rustc_hir_analysis/check/cast.rs).
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum CastKind {
CoercionCast,
@@ -75,3 +76,28 @@ impl<'tcx> CastTy<'tcx> {
}
}
}
+
+/// Returns `mir::CastKind` from the given parameters.
+pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKind {
+ let from = CastTy::from_ty(from_ty);
+ let cast = CastTy::from_ty(cast_ty);
+ let cast_kind = match (from, cast) {
+ (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
+ mir::CastKind::PointerExposeAddress
+ }
+ (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerFromExposedAddress,
+ (_, Some(CastTy::DynStar)) => mir::CastKind::DynStar,
+ (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt,
+ (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr,
+
+ (Some(CastTy::Float), Some(CastTy::Int(_))) => mir::CastKind::FloatToInt,
+ (Some(CastTy::Int(_)), Some(CastTy::Float)) => mir::CastKind::IntToFloat,
+ (Some(CastTy::Float), Some(CastTy::Float)) => mir::CastKind::FloatToFloat,
+ (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PtrToPtr,
+
+ (_, _) => {
+ bug!("Attempting to cast non-castable types {:?} and {:?}", from_ty, cast_ty)
+ }
+ };
+ cast_kind
+}
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 51137c526..14ec88b7e 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -455,6 +455,7 @@ impl_arena_copy_decoder! {<'tcx>
rustc_span::def_id::DefId,
rustc_span::def_id::LocalDefId,
(rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo),
+ ty::DeducedParamAttrs,
}
#[macro_export]
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 339ff4d35..f998e6083 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -1,9 +1,6 @@
use crate::mir::interpret::LitToConstInput;
use crate::mir::ConstantKind;
-use crate::ty::{
- self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
- TyCtxt, TypeVisitable,
-};
+use crate::ty::{self, InternalSubsts, ParamEnv, ParamEnvAnd, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -81,10 +78,9 @@ impl<'tcx> Const<'tcx> {
match Self::try_eval_lit_or_param(tcx, ty, expr) {
Some(v) => v,
None => tcx.mk_const(ty::ConstS {
- kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
+ kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
def: def.to_global(),
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
- promoted: (),
}),
ty,
}),
@@ -151,46 +147,6 @@ impl<'tcx> Const<'tcx> {
}
}
- pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
- debug!("Const::from_inline_const(def_id={:?})", def_id);
-
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-
- let body_id = match tcx.hir().get(hir_id) {
- hir::Node::AnonConst(ac) => ac.body,
- _ => span_bug!(
- tcx.def_span(def_id.to_def_id()),
- "from_inline_const can only process anonymous constants"
- ),
- };
-
- let expr = &tcx.hir().body(body_id).value;
-
- let ty = tcx.typeck(def_id).node_type(hir_id);
-
- let ret = match Self::try_eval_lit_or_param(tcx, ty, expr) {
- Some(v) => v,
- None => {
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
- let parent_substs =
- tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
- let substs =
- InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty })
- .substs;
- tcx.mk_const(ty::ConstS {
- kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
- def: ty::WithOptConstParam::unknown(def_id).to_global(),
- substs,
- promoted: (),
- }),
- ty,
- })
- }
- };
- debug_assert!(!ret.has_free_regions());
- ret
- }
-
/// Interns the given value as a constant.
#[inline]
pub fn from_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Self {
@@ -307,6 +263,10 @@ impl<'tcx> Const<'tcx> {
self.try_eval_usize(tcx, param_env)
.unwrap_or_else(|| bug!("expected usize, got {:#?}", self))
}
+
+ pub fn is_ct_infer(self) -> bool {
+ matches!(self.kind(), ty::ConstKind::Infer(_))
+ }
}
pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Const<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index 455015280..4ab761e07 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -1,10 +1,11 @@
use std::convert::TryInto;
+use crate::mir;
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
-use crate::mir::Promoted;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::ParamEnv;
use crate::ty::{self, TyCtxt, TypeVisitable};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
@@ -12,40 +13,34 @@ use rustc_target::abi::Size;
use super::ScalarInt;
-/// An unevaluated, potentially generic, constant.
+/// An unevaluated (potentially generic) constant used in the type-system.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
-#[derive(Hash, HashStable)]
-pub struct Unevaluated<'tcx, P = Option<Promoted>> {
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
+pub struct UnevaluatedConst<'tcx> {
pub def: ty::WithOptConstParam<DefId>,
pub substs: SubstsRef<'tcx>,
- pub promoted: P,
}
-impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> {
+impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
format!("{:?}", self).into_diagnostic_arg()
}
}
-impl<'tcx> Unevaluated<'tcx> {
- #[inline]
- pub fn shrink(self) -> Unevaluated<'tcx, ()> {
- debug_assert_eq!(self.promoted, None);
- Unevaluated { def: self.def, substs: self.substs, promoted: () }
- }
-}
-
-impl<'tcx> Unevaluated<'tcx, ()> {
+impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn expand(self) -> Unevaluated<'tcx> {
- Unevaluated { def: self.def, substs: self.substs, promoted: None }
+ pub fn expand(self) -> mir::UnevaluatedConst<'tcx> {
+ mir::UnevaluatedConst { def: self.def, substs: self.substs, promoted: None }
}
}
-impl<'tcx, P: Default> Unevaluated<'tcx, P> {
+impl<'tcx> UnevaluatedConst<'tcx> {
#[inline]
- pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
- Unevaluated { def, substs, promoted: Default::default() }
+ pub fn new(
+ def: ty::WithOptConstParam<DefId>,
+ substs: SubstsRef<'tcx>,
+ ) -> UnevaluatedConst<'tcx> {
+ UnevaluatedConst { def, substs }
}
}
@@ -67,7 +62,7 @@ pub enum ConstKind<'tcx> {
/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
/// variants when the code is monomorphic enough for that.
- Unevaluated(Unevaluated<'tcx, ()>),
+ Unevaluated(UnevaluatedConst<'tcx>),
/// Used to hold computed value.
Value(ty::ValTree<'tcx>),
@@ -114,7 +109,6 @@ impl<'tcx> ConstKind<'tcx> {
/// An inference variable for a const, for use in const generics.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
-#[derive(HashStable)]
pub enum InferConst<'tcx> {
/// Infer the value of the const.
Var(ty::ConstVid<'tcx>),
@@ -122,6 +116,15 @@ pub enum InferConst<'tcx> {
Fresh(u32),
}
+impl<CTX> HashStable<CTX> for InferConst<'_> {
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ match self {
+ InferConst::Var(_) => panic!("const variables should not be hashed: {self:?}"),
+ InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
+ }
+ }
+}
+
enum EvalMode {
Typeck,
Mir,
@@ -185,8 +188,6 @@ impl<'tcx> ConstKind<'tcx> {
if let ConstKind::Unevaluated(unevaluated) = self {
use crate::mir::interpret::ErrorHandled;
- assert_eq!(unevaluated.promoted, ());
-
// HACK(eddyb) this erases lifetimes even though `const_eval_resolve`
// also does later, but we want to do it before checking for
// inference variables.
@@ -204,10 +205,9 @@ impl<'tcx> ConstKind<'tcx> {
// 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() {
- tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
+ tcx.param_env(unevaluated.def.did).and(ty::UnevaluatedConst {
def: unevaluated.def,
substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
- promoted: (),
})
} else {
param_env_and
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 0b497fa4a..3d7e2a083 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1,10 +1,10 @@
//! Type context book-keeping.
use crate::arena::Arena;
-use crate::dep_graph::{DepGraph, DepKind, DepKindStruct};
+use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::hir::place::Place as HirPlace;
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
-use crate::lint::{struct_lint_level, LintLevelSource};
+use crate::lint::struct_lint_level;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_lifetime;
use crate::middle::stability;
@@ -15,7 +15,6 @@ use crate::mir::{
use crate::thir::Thir;
use crate::traits;
use crate::ty::query::{self, TyCtxtAt};
-use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
use crate::ty::{
self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig,
ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy,
@@ -24,6 +23,7 @@ use crate::ty::{
RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy,
Visibility,
};
+use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts};
use rustc_ast as ast;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -34,12 +34,16 @@ 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, RwLock, WorkerLocal};
+use rustc_data_structures::unord::UnordSet;
use rustc_data_structures::vec_map::VecMap;
-use rustc_errors::{DecorateLint, ErrorGuaranteed, LintDiagnosticBuilder, MultiSpan};
+use rustc_errors::{
+ DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
+use rustc_hir::hir_id::OwnerId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{
@@ -53,7 +57,7 @@ use rustc_query_system::ich::StableHashingContext;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_session::config::{CrateType, OutputFilenames};
use rustc_session::cstore::CrateStoreDyn;
-use rustc_session::lint::{Level, Lint};
+use rustc_session::lint::Lint;
use rustc_session::Limit;
use rustc_session::Session;
use rustc_span::def_id::{DefPathHash, StableCrateId};
@@ -76,7 +80,7 @@ use std::mem;
use std::ops::{Bound, Deref};
use std::sync::Arc;
-use super::{ImplPolarity, RvalueScopes};
+use super::{ImplPolarity, ResolverOutputs, RvalueScopes};
pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync {
/// Creates a new `OnDiskCache` instance from the serialized data in `data`.
@@ -195,9 +199,9 @@ impl<'tcx> CtxtInterners<'tcx> {
.intern(kind, |kind| {
let flags = super::flags::FlagComputation::for_kind(&kind);
- // It's impossible to hash inference regions (and will ICE), so we don't need to try to cache them.
+ // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
- let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER)
+ let stable_hash = if flags.flags.intersects(TypeFlags::NEEDS_INFER)
|| sess.opts.incremental.is_none()
{
Fingerprint::ZERO
@@ -288,7 +292,7 @@ pub struct CommonConsts<'tcx> {
}
pub struct LocalTableInContext<'a, V> {
- hir_owner: LocalDefId,
+ hir_owner: OwnerId,
data: &'a ItemLocalMap<V>,
}
@@ -300,7 +304,7 @@ pub struct LocalTableInContext<'a, V> {
/// would result in lookup errors, or worse, in silently wrong data being
/// stored/returned.
#[inline]
-fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId) {
+fn validate_hir_id_for_typeck_results(hir_owner: OwnerId, hir_id: hir::HirId) {
if hir_id.owner != hir_owner {
invalid_hir_id_for_typeck_results(hir_owner, hir_id);
}
@@ -308,7 +312,7 @@ fn validate_hir_id_for_typeck_results(hir_owner: LocalDefId, hir_id: hir::HirId)
#[cold]
#[inline(never)]
-fn invalid_hir_id_for_typeck_results(hir_owner: LocalDefId, 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 {:?}",
@@ -344,7 +348,7 @@ impl<'a, V> ::std::ops::Index<hir::HirId> for LocalTableInContext<'a, V> {
}
pub struct LocalTableInContextMut<'a, V> {
- hir_owner: LocalDefId,
+ hir_owner: OwnerId,
data: &'a mut ItemLocalMap<V>,
}
@@ -416,7 +420,7 @@ pub struct GeneratorDiagnosticData<'tcx> {
#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
pub struct TypeckResults<'tcx> {
/// The `HirId::owner` all `ItemLocalId`s in this table are relative to.
- pub hir_owner: LocalDefId,
+ pub hir_owner: OwnerId,
/// Resolved definitions for `<T>::X` associated paths and
/// method calls, including those of overloaded operators.
@@ -528,19 +532,17 @@ pub struct TypeckResults<'tcx> {
/// This is used for warning unused imports. During type
/// checking, this `Lrc` should not be cloned: it must have a ref-count
/// of 1 so that we can insert things into the set mutably.
- pub used_trait_imports: Lrc<FxHashSet<LocalDefId>>,
+ pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
/// If any errors occurred while type-checking this body,
/// this field will be set to `Some(ErrorGuaranteed)`.
pub tainted_by_errors: Option<ErrorGuaranteed>,
/// All the opaque types that have hidden types set
- /// by this function. For return-position-impl-trait we also store the
- /// type here, so that mir-borrowck can figure out hidden types,
+ /// by this function. We also store the
+ /// type here, so that mir-borrowck can use it as a hint for figuring out hidden types,
/// even if they are only set in dead code (which doesn't show up in MIR).
- /// For type-alias-impl-trait, this map is only used to prevent query cycles,
- /// so the hidden types are all `None`.
- pub concrete_opaque_types: VecMap<LocalDefId, Option<Ty<'tcx>>>,
+ pub concrete_opaque_types: VecMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
/// Tracks the minimum captures required for a closure;
/// see `MinCaptureInformationMap` for more details.
@@ -572,7 +574,7 @@ pub struct TypeckResults<'tcx> {
/// Tracks the rvalue scoping rules which defines finer scoping for rvalue expressions
/// by applying extended parameter rules.
- /// Details may be find in `rustc_typeck::check::rvalue_scopes`.
+ /// Details may be find in `rustc_hir_analysis::check::rvalue_scopes`.
pub rvalue_scopes: RvalueScopes,
/// Stores the type, expression, span and optional scope span of all types
@@ -591,7 +593,7 @@ pub struct TypeckResults<'tcx> {
}
impl<'tcx> TypeckResults<'tcx> {
- pub fn new(hir_owner: LocalDefId) -> TypeckResults<'tcx> {
+ pub fn new(hir_owner: OwnerId) -> TypeckResults<'tcx> {
TypeckResults {
hir_owner,
type_dependent_defs: Default::default(),
@@ -1066,10 +1068,9 @@ pub struct GlobalCtxt<'tcx> {
pub consts: CommonConsts<'tcx>,
definitions: RwLock<Definitions>,
- cstore: Box<CrateStoreDyn>,
/// Output of the resolver.
- pub(crate) untracked_resolutions: ty::ResolverOutputs,
+ pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
untracked_resolver_for_lowering: Steal<ty::ResolverAstLowering>,
/// The entire crate as AST. This field serves as the input for the hir_crate query,
/// which lowers it from AST to HIR. It must not be read or used by anything else.
@@ -1083,7 +1084,7 @@ pub struct GlobalCtxt<'tcx> {
pub queries: &'tcx dyn query::QueryEngine<'tcx>,
pub query_caches: query::QueryCaches<'tcx>,
- query_kinds: &'tcx [DepKindStruct<'tcx>],
+ pub(crate) query_kinds: &'tcx [DepKindStruct<'tcx>],
// Internal caches for metadata decoding. No need to track deps on this.
pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
@@ -1232,10 +1233,7 @@ impl<'tcx> TyCtxt<'tcx> {
lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
- definitions: Definitions,
- cstore: Box<CrateStoreDyn>,
- untracked_resolutions: ty::ResolverOutputs,
- untracked_resolver_for_lowering: ty::ResolverAstLowering,
+ resolver_outputs: ResolverOutputs,
krate: Lrc<ast::Crate>,
dep_graph: DepGraph,
on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
@@ -1244,6 +1242,11 @@ impl<'tcx> TyCtxt<'tcx> {
crate_name: &str,
output_filenames: OutputFilenames,
) -> GlobalCtxt<'tcx> {
+ let ResolverOutputs {
+ definitions,
+ global_ctxt: untracked_resolutions,
+ ast_lowering: untracked_resolver_for_lowering,
+ } = resolver_outputs;
let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| {
s.emit_fatal(err);
});
@@ -1252,7 +1255,7 @@ impl<'tcx> TyCtxt<'tcx> {
&interners,
s,
&definitions,
- &*cstore,
+ &*untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
&untracked_resolutions.source_span,
);
@@ -1267,7 +1270,6 @@ impl<'tcx> TyCtxt<'tcx> {
interners,
dep_graph,
definitions: RwLock::new(definitions),
- cstore,
prof: s.prof.clone(),
types: common_types,
lifetimes: common_lifetimes,
@@ -1290,10 +1292,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
- pub(crate) fn query_kind(self, k: DepKind) -> &'tcx DepKindStruct<'tcx> {
- &self.query_kinds[k as usize]
- }
-
/// Constructs a `TyKind::Error` type and registers a `delay_span_bug` to ensure it gets used.
#[track_caller]
pub fn ty_error(self) -> Ty<'tcx> {
@@ -1372,7 +1370,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_key(id)
} else {
- self.cstore.def_key(id)
+ self.untracked_resolutions.cstore.def_key(id)
}
}
@@ -1386,7 +1384,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(id) = id.as_local() {
self.definitions_untracked().def_path(id)
} else {
- self.cstore.def_path(id)
+ self.untracked_resolutions.cstore.def_path(id)
}
}
@@ -1396,7 +1394,7 @@ impl<'tcx> TyCtxt<'tcx> {
if let Some(def_id) = def_id.as_local() {
self.definitions_untracked().def_path_hash(def_id)
} else {
- self.cstore.def_path_hash(def_id)
+ self.untracked_resolutions.cstore.def_path_hash(def_id)
}
}
@@ -1405,7 +1403,7 @@ impl<'tcx> TyCtxt<'tcx> {
if crate_num == LOCAL_CRATE {
self.sess.local_stable_crate_id()
} else {
- self.cstore.stable_crate_id(crate_num)
+ self.untracked_resolutions.cstore.stable_crate_id(crate_num)
}
}
@@ -1416,7 +1414,7 @@ impl<'tcx> TyCtxt<'tcx> {
if stable_crate_id == self.sess.local_stable_crate_id() {
LOCAL_CRATE
} else {
- self.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+ self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
}
}
@@ -1435,8 +1433,9 @@ impl<'tcx> TyCtxt<'tcx> {
} else {
// If this is a DefPathHash from an upstream crate, let the CrateStore map
// it to a DefId.
- let cnum = self.cstore.stable_crate_id_to_crate_num(stable_crate_id);
- self.cstore.def_path_hash_to_def_id(cnum, hash)
+ let cstore = &*self.untracked_resolutions.cstore;
+ let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
+ cstore.def_path_hash_to_def_id(cnum, hash)
}
}
@@ -1448,7 +1447,7 @@ impl<'tcx> TyCtxt<'tcx> {
let (crate_name, stable_crate_id) = if def_id.is_local() {
(self.crate_name, self.sess.local_stable_crate_id())
} else {
- let cstore = &self.cstore;
+ let cstore = &*self.untracked_resolutions.cstore;
(cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
};
@@ -1523,7 +1522,7 @@ 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.cstore
+ &*self.untracked_resolutions.cstore
}
/// Note that this is *untracked* and should only be used within the query
@@ -1549,7 +1548,7 @@ impl<'tcx> TyCtxt<'tcx> {
let hcx = StableHashingContext::new(
self.sess,
&*definitions,
- &*self.cstore,
+ &*self.untracked_resolutions.cstore,
&self.untracked_resolutions.source_span,
);
f(hcx)
@@ -1725,7 +1724,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn local_visibility(self, def_id: LocalDefId) -> Visibility {
- self.visibility(def_id.to_def_id()).expect_local()
+ self.visibility(def_id).expect_local()
}
}
@@ -2367,7 +2366,7 @@ impl<'tcx> TyCtxt<'tcx> {
st,
self.sess,
&self.definitions.read(),
- &*self.cstore,
+ &*self.untracked_resolutions.cstore,
// This is only used to create a stable hashing context.
&self.untracked_resolutions.source_span,
)
@@ -2812,44 +2811,6 @@ impl<'tcx> TyCtxt<'tcx> {
iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
}
- /// Walks upwards from `id` to find a node which might change lint levels with attributes.
- /// It stops at `bound` and just returns it if reached.
- pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
- let hir = self.hir();
- loop {
- if id == bound {
- return bound;
- }
-
- if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
- return id;
- }
- let next = hir.get_parent_node(id);
- if next == id {
- bug!("lint traversal reached the root of the crate");
- }
- id = next;
- }
- }
-
- pub fn lint_level_at_node(
- self,
- lint: &'static Lint,
- mut id: hir::HirId,
- ) -> (Level, LintLevelSource) {
- let sets = self.lint_levels(());
- loop {
- if let Some(pair) = sets.level_and_source(lint, id, self.sess) {
- return pair;
- }
- let next = self.hir().get_parent_node(id);
- if next == id {
- bug!("lint traversal reached the root of the crate");
- }
- id = next;
- }
- }
-
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
/// typically generated by `#[derive(LintDiagnostic)]`).
pub fn emit_spanned_lint(
@@ -2859,18 +2820,28 @@ impl<'tcx> TyCtxt<'tcx> {
span: impl Into<MultiSpan>,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.struct_span_lint_hir(lint, hir_id, span, |diag| decorator.decorate_lint(diag))
+ self.struct_span_lint_hir(lint, hir_id, span, decorator.msg(), |diag| {
+ decorator.decorate_lint(diag)
+ })
}
+ /// Emit a lint at the appropriate level for a hir node, with an associated span.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
pub fn struct_span_lint_hir(
self,
lint: &'static Lint,
hir_id: HirId,
span: impl Into<MultiSpan>,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
let (level, src) = self.lint_level_at_node(lint, hir_id);
- struct_lint_level(self.sess, lint, level, src, Some(span.into()), decorate);
+ struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
}
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
@@ -2881,17 +2852,25 @@ impl<'tcx> TyCtxt<'tcx> {
id: HirId,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.struct_lint_node(lint, id, |diag| decorator.decorate_lint(diag))
+ self.struct_lint_node(lint, id, decorator.msg(), |diag| decorator.decorate_lint(diag))
}
+ /// Emit a lint at the appropriate level for a hir node.
+ ///
+ /// Return value of the `decorate` closure is ignored, see [`struct_lint_level`] for a detailed explanation.
+ ///
+ /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
pub fn struct_lint_node(
self,
lint: &'static Lint,
id: HirId,
- decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'b mut DiagnosticBuilder<'a, ()>,
+ ) -> &'b mut DiagnosticBuilder<'a, ()>,
) {
let (level, src) = self.lint_level_at_node(lint, id);
- struct_lint_level(self.sess, lint, level, src, None, decorate);
+ struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
}
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
@@ -2906,7 +2885,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn is_late_bound(self, id: HirId) -> bool {
- self.is_late_bound_map(id.owner).map_or(false, |set| {
+ 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)
})
@@ -2977,6 +2956,21 @@ impl<'tcx> TyCtxtAt<'tcx> {
}
}
+/// Parameter attributes that can only be determined by examining the body of a function instead
+/// of just its signature.
+///
+/// These can be useful for optimization purposes when a function is directly called. We compute
+/// them and store them into the crate metadata so that downstream crates can make use of them.
+///
+/// Right now, we only have `read_only`, but `no_capture` and `no_alias` might be useful in the
+/// future.
+#[derive(Clone, Copy, PartialEq, Debug, Default, TyDecodable, TyEncodable, HashStable)]
+pub struct DeducedParamAttrs {
+ /// The parameter is marked immutable in the function and contains no `UnsafeCell` (i.e. its
+ /// type is freeze).
+ 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 {
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 855917fb8..b8fd01e6a 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -511,3 +511,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
c.super_visit_with(self)
}
}
+
+#[derive(Diagnostic)]
+#[diag(borrowck_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 3226950e7..ffdac93bc 100644
--- a/compiler/rustc_middle/src/ty/erase_regions.rs
+++ b/compiler/rustc_middle/src/ty/erase_regions.rs
@@ -1,4 +1,3 @@
-use crate::mir;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::visit::TypeVisitable;
use crate::ty::{self, Ty, TyCtxt, TypeFlags};
@@ -67,8 +66,4 @@ impl<'tcx> TypeFolder<'tcx> for RegionEraserVisitor<'tcx> {
_ => self.tcx.lifetimes.re_erased,
}
}
-
- fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
- c.super_fold_with(self)
- }
}
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index 01e1e97b2..4e6cdb786 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -861,7 +861,7 @@ fn foo(&self) -> Self::T { String::new() }
// 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);
+ 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), .. })) => {
@@ -872,9 +872,9 @@ fn foo(&self) -> Self::T { String::new() }
// 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.def_id)
+ self.impl_defaultness(item.id.owner_id)
{
- if self.type_of(item.id.def_id) == found {
+ if self.type_of(item.id.owner_id) == found {
diag.span_label(
item.span,
"associated type defaults can't be assumed inside the \
@@ -894,7 +894,7 @@ fn foo(&self) -> Self::T { String::new() }
})) => {
for item in &items[..] {
if let hir::AssocItemKind::Type = item.kind {
- if self.type_of(item.id.def_id) == found {
+ if self.type_of(item.id.owner_id) == found {
diag.span_label(item.span, "expected this associated type");
return true;
}
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs
index 8d019a3ba..3be0bc4de 100644
--- a/compiler/rustc_middle/src/ty/fast_reject.rs
+++ b/compiler/rustc_middle/src/ty/fast_reject.rs
@@ -132,7 +132,7 @@ pub fn simplify_type<'tcx>(
// don't unify with anything else as long as they are fully normalized.
//
// We will have to be careful with lazy normalization here.
- TreatParams::AsPlaceholder if !ty.has_infer_types_or_consts() => {
+ TreatParams::AsPlaceholder if !ty.has_non_region_infer() => {
debug!("treating `{}` as a placeholder", ty);
Some(PlaceholderSimplifiedType)
}
@@ -384,14 +384,7 @@ impl DeepRejectCtxt {
// they might unify with any value.
ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => true,
ty::ConstKind::Value(obl) => match k {
- ty::ConstKind::Value(imp) => {
- // FIXME(valtrees): Once we have valtrees, we can just
- // compare them directly here.
- match (obl.try_to_scalar_int(), imp.try_to_scalar_int()) {
- (Some(obl), Some(imp)) => obl == imp,
- _ => true,
- }
- }
+ ty::ConstKind::Value(imp) => obl == imp,
_ => true,
},
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index 98b8a7386..7201737be 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -34,12 +34,6 @@ impl FlagComputation {
result.flags
}
- pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
- let mut result = FlagComputation::new();
- result.add_unevaluated_const(uv);
- result.flags
- }
-
fn add_flags(&mut self, flags: TypeFlags) {
self.flags = self.flags | flags;
}
@@ -256,7 +250,7 @@ impl FlagComputation {
self.add_substs(substs);
}
ty::PredicateKind::ConstEvaluatable(uv) => {
- self.add_unevaluated_const(uv);
+ self.add_const(uv);
}
ty::PredicateKind::ConstEquate(expected, found) => {
self.add_const(expected);
@@ -289,7 +283,10 @@ impl FlagComputation {
fn add_const(&mut self, c: ty::Const<'_>) {
self.add_ty(c.ty());
match c.kind() {
- ty::ConstKind::Unevaluated(unevaluated) => self.add_unevaluated_const(unevaluated),
+ ty::ConstKind::Unevaluated(uv) => {
+ self.add_substs(uv.substs);
+ self.add_flags(TypeFlags::HAS_CT_PROJECTION);
+ }
ty::ConstKind::Infer(infer) => {
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
match infer {
@@ -313,11 +310,6 @@ impl FlagComputation {
}
}
- fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
- self.add_substs(ct.substs);
- self.add_flags(TypeFlags::HAS_CT_PROJECTION);
- }
-
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
self.add_substs(projection.substs);
match projection.term.unpack() {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index cac95e14a..54f1499eb 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -13,8 +13,7 @@
//!
//! 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 the methods delegate to the
-//! folder.
+//! - 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,
@@ -43,7 +42,6 @@
//! - ty.super_fold_with(folder)
//! - u.fold_with(folder)
//! ```
-use crate::mir;
use crate::ty::{self, Binder, BoundTy, Ty, TyCtxt, TypeVisitable};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
@@ -128,17 +126,9 @@ pub trait TypeFolder<'tcx>: FallibleTypeFolder<'tcx, Error = !> {
c.super_fold_with(self)
}
- fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> {
- uv.super_fold_with(self)
- }
-
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
p.super_fold_with(self)
}
-
- fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
- bug!("most type folders should not be folding MIR datastructures: {:?}", c)
- }
}
/// This trait is implemented for every folding traversal. There is a fold
@@ -172,26 +162,12 @@ pub trait FallibleTypeFolder<'tcx>: Sized {
c.try_super_fold_with(self)
}
- fn try_fold_unevaluated(
- &mut self,
- c: ty::Unevaluated<'tcx>,
- ) -> Result<ty::Unevaluated<'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)
}
-
- fn try_fold_mir_const(
- &mut self,
- c: mir::ConstantKind<'tcx>,
- ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
- bug!("most type folders should not be folding MIR datastructures: {:?}", c)
- }
}
// This blanket implementation of the fallible trait for infallible folders
@@ -225,23 +201,9 @@ where
Ok(self.fold_const(c))
}
- fn try_fold_unevaluated(
- &mut self,
- c: ty::Unevaluated<'tcx>,
- ) -> Result<ty::Unevaluated<'tcx>, !> {
- Ok(self.fold_unevaluated(c))
- }
-
fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result<ty::Predicate<'tcx>, !> {
Ok(self.fold_predicate(p))
}
-
- fn try_fold_mir_const(
- &mut self,
- c: mir::ConstantKind<'tcx>,
- ) -> Result<mir::ConstantKind<'tcx>, !> {
- Ok(self.fold_mir_const(c))
- }
}
///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 0c8bdde9c..19754d145 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -1,6 +1,5 @@
use crate::ty;
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::EarlyBinder;
+use crate::ty::{EarlyBinder, SubstsRef};
use rustc_ast as ast;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::DefId;
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs b/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
deleted file mode 100644
index c4ad698ba..000000000
--- a/compiler/rustc_middle/src/ty/inhabitedness/def_id_forest.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-use crate::ty::context::TyCtxt;
-use crate::ty::{DefId, DefIdTree};
-use rustc_span::def_id::CRATE_DEF_ID;
-use smallvec::SmallVec;
-use std::mem;
-
-use DefIdForest::*;
-
-/// Represents a forest of `DefId`s closed under the ancestor relation. That is,
-/// if a `DefId` representing a module is contained in the forest then all
-/// `DefId`s defined in that module or submodules are also implicitly contained
-/// in the forest.
-///
-/// This is used to represent a set of modules in which a type is visibly
-/// uninhabited.
-///
-/// We store the minimal set of `DefId`s required to represent the whole set. If A and B are
-/// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is
-/// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored.
-#[derive(Copy, Clone, HashStable, Debug)]
-pub enum DefIdForest<'a> {
- Empty,
- Single(DefId),
- /// This variant is very rare.
- /// Invariant: >1 elements
- Multiple(&'a [DefId]),
-}
-
-/// Tests whether a slice of roots contains a given DefId.
-#[inline]
-fn slice_contains<'tcx>(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool {
- slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
-}
-
-impl<'tcx> DefIdForest<'tcx> {
- /// Creates an empty forest.
- pub fn empty() -> DefIdForest<'tcx> {
- DefIdForest::Empty
- }
-
- /// Creates a forest consisting of a single tree representing the entire
- /// crate.
- #[inline]
- pub fn full() -> DefIdForest<'tcx> {
- DefIdForest::from_id(CRATE_DEF_ID.to_def_id())
- }
-
- /// Creates a forest containing a `DefId` and all its descendants.
- pub fn from_id(id: DefId) -> DefIdForest<'tcx> {
- DefIdForest::Single(id)
- }
-
- fn as_slice(&self) -> &[DefId] {
- match self {
- Empty => &[],
- Single(id) => std::slice::from_ref(id),
- Multiple(root_ids) => root_ids,
- }
- }
-
- // Only allocates in the rare `Multiple` case.
- fn from_vec(tcx: TyCtxt<'tcx>, root_ids: SmallVec<[DefId; 1]>) -> DefIdForest<'tcx> {
- match &root_ids[..] {
- [] => Empty,
- [id] => Single(*id),
- _ => DefIdForest::Multiple(tcx.arena.alloc_from_iter(root_ids)),
- }
- }
-
- /// Tests whether the forest is empty.
- pub fn is_empty(&self) -> bool {
- match self {
- Empty => true,
- Single(..) | Multiple(..) => false,
- }
- }
-
- /// Iterate over the set of roots.
- fn iter(&self) -> impl Iterator<Item = DefId> + '_ {
- self.as_slice().iter().copied()
- }
-
- /// Tests whether the forest contains a given DefId.
- pub fn contains(&self, tcx: TyCtxt<'tcx>, id: DefId) -> bool {
- slice_contains(tcx, self.as_slice(), id)
- }
-
- /// Calculate the intersection of a collection of forests.
- pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
- where
- I: IntoIterator<Item = DefIdForest<'tcx>>,
- {
- let mut iter = iter.into_iter();
- let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() {
- SmallVec::from_slice(first.as_slice())
- } else {
- return DefIdForest::full();
- };
-
- let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
- for next_forest in iter {
- // No need to continue if the intersection is already empty.
- if ret.is_empty() || next_forest.is_empty() {
- return DefIdForest::empty();
- }
-
- // We keep the elements in `ret` that are also in `next_forest`.
- next_ret.extend(ret.iter().copied().filter(|&id| next_forest.contains(tcx, id)));
- // We keep the elements in `next_forest` that are also in `ret`.
- next_ret.extend(next_forest.iter().filter(|&id| slice_contains(tcx, &ret, id)));
-
- mem::swap(&mut next_ret, &mut ret);
- next_ret.clear();
- }
- DefIdForest::from_vec(tcx, ret)
- }
-
- /// Calculate the union of a collection of forests.
- pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
- where
- I: IntoIterator<Item = DefIdForest<'tcx>>,
- {
- let mut ret: SmallVec<[_; 1]> = SmallVec::new();
- let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
- for next_forest in iter {
- // Union with the empty set is a no-op.
- if next_forest.is_empty() {
- continue;
- }
-
- // We add everything in `ret` that is not in `next_forest`.
- next_ret.extend(ret.iter().copied().filter(|&id| !next_forest.contains(tcx, id)));
- // We add everything in `next_forest` that we haven't added yet.
- for id in next_forest.iter() {
- if !slice_contains(tcx, &next_ret, id) {
- next_ret.push(id);
- }
- }
-
- mem::swap(&mut next_ret, &mut ret);
- next_ret.clear();
- }
- DefIdForest::from_vec(tcx, ret)
- }
-}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
new file mode 100644
index 000000000..b7aa45572
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs
@@ -0,0 +1,204 @@
+use crate::ty::context::TyCtxt;
+use crate::ty::{self, DefId, DefIdTree, ParamEnv, Ty};
+
+/// Represents whether some type is inhabited in a given context.
+/// Examples of uninhabited types are `!`, `enum Void {}`, or a struct
+/// containing either of those types.
+/// A type's inhabitedness may depend on the `ParamEnv` as well as what types
+/// are visible in the current module.
+#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
+pub enum InhabitedPredicate<'tcx> {
+ /// Inhabited
+ True,
+ /// Uninhabited
+ False,
+ /// Uninhabited when a const value is non-zero. This occurs when there is an
+ /// array of uninhabited items, but the array is inhabited if it is empty.
+ ConstIsZero(ty::Const<'tcx>),
+ /// Uninhabited if within a certain module. This occurs when an uninhabited
+ /// type has restricted visibility.
+ NotInModule(DefId),
+ /// Inhabited if some generic type is inhabited.
+ /// These are replaced by calling [`Self::subst`].
+ GenericType(Ty<'tcx>),
+ /// A AND B
+ And(&'tcx [InhabitedPredicate<'tcx>; 2]),
+ /// A OR B
+ Or(&'tcx [InhabitedPredicate<'tcx>; 2]),
+}
+
+impl<'tcx> InhabitedPredicate<'tcx> {
+ /// Returns true if the corresponding type is inhabited in the given
+ /// `ParamEnv` and module
+ pub fn apply(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, module_def_id: DefId) -> bool {
+ let Ok(result) = self
+ .apply_inner::<!>(tcx, param_env, &|id| Ok(tcx.is_descendant_of(module_def_id, id)));
+ result
+ }
+
+ /// Same as `apply`, but returns `None` if self contains a module predicate
+ pub fn apply_any_module(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option<bool> {
+ self.apply_inner(tcx, param_env, &|_| Err(())).ok()
+ }
+
+ fn apply_inner<E>(
+ self,
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ in_module: &impl Fn(DefId) -> Result<bool, E>,
+ ) -> Result<bool, E> {
+ match self {
+ Self::False => Ok(false),
+ Self::True => Ok(true),
+ Self::ConstIsZero(const_) => match const_.try_eval_usize(tcx, param_env) {
+ None | Some(0) => Ok(true),
+ Some(1..) => Ok(false),
+ },
+ Self::NotInModule(id) => in_module(id).map(|in_mod| !in_mod),
+ Self::GenericType(_) => Ok(true),
+ Self::And([a, b]) => try_and(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+ Self::Or([a, b]) => try_or(a, b, |x| x.apply_inner(tcx, param_env, in_module)),
+ }
+ }
+
+ pub fn and(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
+ self.reduce_and(tcx, other).unwrap_or_else(|| Self::And(tcx.arena.alloc([self, other])))
+ }
+
+ pub fn or(self, tcx: TyCtxt<'tcx>, other: Self) -> Self {
+ self.reduce_or(tcx, other).unwrap_or_else(|| Self::Or(tcx.arena.alloc([self, other])))
+ }
+
+ pub fn all(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
+ let mut result = Self::True;
+ for pred in iter {
+ if matches!(pred, Self::False) {
+ return Self::False;
+ }
+ result = result.and(tcx, pred);
+ }
+ result
+ }
+
+ pub fn any(tcx: TyCtxt<'tcx>, iter: impl IntoIterator<Item = Self>) -> Self {
+ let mut result = Self::False;
+ for pred in iter {
+ if matches!(pred, Self::True) {
+ return Self::True;
+ }
+ result = result.or(tcx, pred);
+ }
+ result
+ }
+
+ fn reduce_and(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
+ match (self, other) {
+ (Self::True, a) | (a, Self::True) => Some(a),
+ (Self::False, _) | (_, Self::False) => Some(Self::False),
+ (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
+ (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
+ (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
+ Some(Self::NotInModule(b))
+ }
+ (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
+ Some(Self::NotInModule(a))
+ }
+ (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
+ (Self::And(&[a, b]), c) | (c, Self::And(&[a, b])) => {
+ if let Some(ac) = a.reduce_and(tcx, c) {
+ Some(ac.and(tcx, b))
+ } else if let Some(bc) = b.reduce_and(tcx, c) {
+ Some(Self::And(tcx.arena.alloc([a, bc])))
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ }
+
+ fn reduce_or(self, tcx: TyCtxt<'tcx>, other: Self) -> Option<Self> {
+ match (self, other) {
+ (Self::True, _) | (_, Self::True) => Some(Self::True),
+ (Self::False, a) | (a, Self::False) => Some(a),
+ (Self::ConstIsZero(a), Self::ConstIsZero(b)) if a == b => Some(Self::ConstIsZero(a)),
+ (Self::NotInModule(a), Self::NotInModule(b)) if a == b => Some(Self::NotInModule(a)),
+ (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(a, b) => {
+ Some(Self::NotInModule(a))
+ }
+ (Self::NotInModule(a), Self::NotInModule(b)) if tcx.is_descendant_of(b, a) => {
+ Some(Self::NotInModule(b))
+ }
+ (Self::GenericType(a), Self::GenericType(b)) if a == b => Some(Self::GenericType(a)),
+ (Self::Or(&[a, b]), c) | (c, Self::Or(&[a, b])) => {
+ if let Some(ac) = a.reduce_or(tcx, c) {
+ Some(ac.or(tcx, b))
+ } else if let Some(bc) = b.reduce_or(tcx, c) {
+ Some(Self::Or(tcx.arena.alloc([a, bc])))
+ } else {
+ None
+ }
+ }
+ _ => None,
+ }
+ }
+
+ /// Replaces generic types with its corresponding predicate
+ pub fn subst(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Self {
+ self.subst_opt(tcx, substs).unwrap_or(self)
+ }
+
+ fn subst_opt(self, tcx: TyCtxt<'tcx>, substs: ty::SubstsRef<'tcx>) -> Option<Self> {
+ match self {
+ Self::ConstIsZero(c) => {
+ let c = ty::EarlyBinder(c).subst(tcx, substs);
+ let pred = match c.kind().try_to_machine_usize(tcx) {
+ Some(0) => Self::True,
+ Some(1..) => Self::False,
+ None => Self::ConstIsZero(c),
+ };
+ Some(pred)
+ }
+ Self::GenericType(t) => {
+ Some(ty::EarlyBinder(t).subst(tcx, substs).inhabited_predicate(tcx))
+ }
+ Self::And(&[a, b]) => match a.subst_opt(tcx, substs) {
+ None => b.subst_opt(tcx, substs).map(|b| a.and(tcx, b)),
+ Some(InhabitedPredicate::False) => Some(InhabitedPredicate::False),
+ Some(a) => Some(a.and(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+ },
+ Self::Or(&[a, b]) => match a.subst_opt(tcx, substs) {
+ None => b.subst_opt(tcx, substs).map(|b| a.or(tcx, b)),
+ Some(InhabitedPredicate::True) => Some(InhabitedPredicate::True),
+ Some(a) => Some(a.or(tcx, b.subst_opt(tcx, substs).unwrap_or(b))),
+ },
+ _ => None,
+ }
+ }
+}
+
+// this is basically like `f(a)? && f(b)?` but different in the case of
+// `Ok(false) && Err(_) -> Ok(false)`
+fn try_and<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+ let a = f(a);
+ if matches!(a, Ok(false)) {
+ return Ok(false);
+ }
+ match (a, f(b)) {
+ (_, Ok(false)) | (Ok(false), _) => Ok(false),
+ (Ok(true), Ok(true)) => Ok(true),
+ (Err(e), _) | (_, Err(e)) => Err(e),
+ }
+}
+
+fn try_or<T, E>(a: T, b: T, f: impl Fn(T) -> Result<bool, E>) -> Result<bool, E> {
+ let a = f(a);
+ if matches!(a, Ok(true)) {
+ return Ok(true);
+ }
+ match (a, f(b)) {
+ (_, Ok(true)) | (Ok(true), _) => Ok(true),
+ (Ok(false), Ok(false)) => Ok(false),
+ (Err(e), _) | (_, Err(e)) => Err(e),
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
index aaa66deb2..279a728ea 100644
--- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
+++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs
@@ -1,57 +1,60 @@
-pub use self::def_id_forest::DefIdForest;
+//! This module contains logic for determining whether a type is inhabited or
+//! uninhabited. The [`InhabitedPredicate`] type captures the minimum
+//! information needed to determine whether a type is inhabited given a
+//! `ParamEnv` and module ID.
+//!
+//! # Example
+//! ```rust
+//! enum Void {}
+//! mod a {
+//! pub mod b {
+//! pub struct SecretlyUninhabited {
+//! _priv: !,
+//! }
+//! }
+//! }
+//!
+//! mod c {
+//! pub struct AlsoSecretlyUninhabited {
+//! _priv: Void,
+//! }
+//! mod d {
+//! }
+//! }
+//!
+//! struct Foo {
+//! x: a::b::SecretlyUninhabited,
+//! y: c::AlsoSecretlyUninhabited,
+//! }
+//! ```
+//! In this code, the type `Foo` will only be visibly uninhabited inside the
+//! modules `b`, `c` and `d`. Calling `uninhabited_predicate` on `Foo` will
+//! return `NotInModule(b) AND NotInModule(c)`.
+//!
+//! We need this information for pattern-matching on `Foo` or types that contain
+//! `Foo`.
+//!
+//! # Example
+//! ```rust
+//! let foo_result: Result<T, Foo> = ... ;
+//! let Ok(t) = foo_result;
+//! ```
+//! This code should only compile in modules where the uninhabitedness of `Foo`
+//! is visible.
-use crate::ty;
use crate::ty::context::TyCtxt;
-use crate::ty::{AdtDef, FieldDef, Ty, VariantDef};
-use crate::ty::{AdtKind, Visibility};
-use crate::ty::{DefId, SubstsRef};
+use crate::ty::{self, DefId, Ty, VariantDef, Visibility};
use rustc_type_ir::sty::TyKind::*;
-mod def_id_forest;
+pub mod inhabited_predicate;
-// The methods in this module calculate `DefIdForest`s of modules in which an
-// `AdtDef`/`VariantDef`/`FieldDef` is visibly uninhabited.
-//
-// # Example
-// ```rust
-// enum Void {}
-// mod a {
-// pub mod b {
-// pub struct SecretlyUninhabited {
-// _priv: !,
-// }
-// }
-// }
-//
-// mod c {
-// pub struct AlsoSecretlyUninhabited {
-// _priv: Void,
-// }
-// mod d {
-// }
-// }
-//
-// struct Foo {
-// x: a::b::SecretlyUninhabited,
-// y: c::AlsoSecretlyUninhabited,
-// }
-// ```
-// In this code, the type `Foo` will only be visibly uninhabited inside the
-// modules `b`, `c` and `d`. Calling `uninhabited_from` on `Foo` or its `AdtDef` will
-// return the forest of modules {`b`, `c`->`d`} (represented in a `DefIdForest` by the
-// set {`b`, `c`}).
-//
-// We need this information for pattern-matching on `Foo` or types that contain
-// `Foo`.
-//
-// # Example
-// ```rust
-// let foo_result: Result<T, Foo> = ... ;
-// let Ok(t) = foo_result;
-// ```
-// This code should only compile in modules where the uninhabitedness of `Foo` is
-// visible.
+pub use inhabited_predicate::InhabitedPredicate;
+
+pub(crate) fn provide(providers: &mut ty::query::Providers) {
+ *providers =
+ ty::query::Providers { inhabited_predicate_adt, inhabited_predicate_type, ..*providers };
+}
impl<'tcx> TyCtxt<'tcx> {
/// Checks whether a type is visibly uninhabited from a particular module.
@@ -100,131 +103,92 @@ impl<'tcx> TyCtxt<'tcx> {
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
- // To check whether this type is uninhabited at all (not just from the
- // given node), you could check whether the forest is empty.
- // ```
- // forest.is_empty()
- // ```
- ty.uninhabited_from(self, param_env).contains(self, module)
+ !ty.inhabited_predicate(self).apply(self, param_env, module)
}
}
-impl<'tcx> AdtDef<'tcx> {
- /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited.
- fn uninhabited_from(
- self,
- tcx: TyCtxt<'tcx>,
- substs: SubstsRef<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> DefIdForest<'tcx> {
- // Non-exhaustive ADTs from other crates are always considered inhabited.
- if self.is_variant_list_non_exhaustive() && !self.did().is_local() {
- DefIdForest::empty()
- } else {
- DefIdForest::intersection(
- tcx,
- self.variants()
- .iter()
- .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)),
- )
+/// Returns an `InhabitedPredicate` that is generic over type parameters and
+/// requires calling [`InhabitedPredicate::subst`]
+fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> {
+ if let Some(def_id) = def_id.as_local() {
+ if matches!(tcx.representability(def_id), ty::Representability::Infinite) {
+ return InhabitedPredicate::True;
}
}
+ let adt = tcx.adt_def(def_id);
+ InhabitedPredicate::any(
+ tcx,
+ adt.variants().iter().map(|variant| variant.inhabited_predicate(tcx, adt)),
+ )
}
impl<'tcx> VariantDef {
/// Calculates the forest of `DefId`s from which this variant is visibly uninhabited.
- pub fn uninhabited_from(
+ pub fn inhabited_predicate(
&self,
tcx: TyCtxt<'tcx>,
- substs: SubstsRef<'tcx>,
- adt_kind: AdtKind,
- param_env: ty::ParamEnv<'tcx>,
- ) -> DefIdForest<'tcx> {
- let is_enum = match adt_kind {
- // For now, `union`s are never considered uninhabited.
- // The precise semantics of inhabitedness with respect to unions is currently undecided.
- AdtKind::Union => return DefIdForest::empty(),
- AdtKind::Enum => true,
- AdtKind::Struct => false,
- };
- // Non-exhaustive variants from other crates are always considered inhabited.
+ adt: ty::AdtDef<'_>,
+ ) -> InhabitedPredicate<'tcx> {
+ debug_assert!(!adt.is_union());
if self.is_field_list_non_exhaustive() && !self.def_id.is_local() {
- DefIdForest::empty()
- } else {
- DefIdForest::union(
- tcx,
- self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)),
- )
+ // Non-exhaustive variants from other crates are always considered inhabited.
+ return InhabitedPredicate::True;
}
- }
-}
-
-impl<'tcx> FieldDef {
- /// Calculates the forest of `DefId`s from which this field is visibly uninhabited.
- fn uninhabited_from(
- &self,
- tcx: TyCtxt<'tcx>,
- substs: SubstsRef<'tcx>,
- is_enum: bool,
- param_env: ty::ParamEnv<'tcx>,
- ) -> DefIdForest<'tcx> {
- let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
- if is_enum {
- data_uninhabitedness()
- } else {
- match self.vis {
- Visibility::Restricted(from) => {
- let forest = DefIdForest::from_id(from);
- let iter = Some(forest).into_iter().chain(Some(data_uninhabitedness()));
- DefIdForest::intersection(tcx, iter)
+ InhabitedPredicate::all(
+ tcx,
+ self.fields.iter().map(|field| {
+ let pred = tcx.type_of(field.did).inhabited_predicate(tcx);
+ if adt.is_enum() {
+ return pred;
}
- Visibility::Public => data_uninhabitedness(),
- }
- }
+ match field.vis {
+ Visibility::Public => pred,
+ Visibility::Restricted(from) => {
+ pred.or(tcx, InhabitedPredicate::NotInModule(from))
+ }
+ }
+ }),
+ )
}
}
impl<'tcx> Ty<'tcx> {
- /// Calculates the forest of `DefId`s from which this type is visibly uninhabited.
- fn uninhabited_from(
- self,
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> DefIdForest<'tcx> {
- tcx.type_uninhabited_from(param_env.and(self))
+ pub fn inhabited_predicate(self, tcx: TyCtxt<'tcx>) -> InhabitedPredicate<'tcx> {
+ match self.kind() {
+ // For now, union`s 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() => {
+ InhabitedPredicate::True
+ }
+ Never => InhabitedPredicate::False,
+ Param(_) | Projection(_) => InhabitedPredicate::GenericType(self),
+ Tuple(tys) if tys.is_empty() => InhabitedPredicate::True,
+ // use a query for more complex cases
+ Adt(..) | Array(..) | Tuple(_) => tcx.inhabited_predicate_type(self),
+ // references and other types are inhabited
+ _ => InhabitedPredicate::True,
+ }
}
}
-// Query provider for `type_uninhabited_from`.
-pub(crate) fn type_uninhabited_from<'tcx>(
- tcx: TyCtxt<'tcx>,
- key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> DefIdForest<'tcx> {
- let ty = key.value;
- let param_env = key.param_env;
+/// N.B. this query should only be called through `Ty::inhabited_predicate`
+fn inhabited_predicate_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> InhabitedPredicate<'tcx> {
match *ty.kind() {
- Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env),
+ Adt(adt, substs) => tcx.inhabited_predicate_adt(adt.did()).subst(tcx, substs),
- Never => DefIdForest::full(),
-
- Tuple(ref tys) => {
- DefIdForest::union(tcx, tys.iter().map(|ty| ty.uninhabited_from(tcx, param_env)))
+ Tuple(tys) => {
+ InhabitedPredicate::all(tcx, tys.iter().map(|ty| ty.inhabited_predicate(tcx)))
}
- Array(ty, len) => match len.try_eval_usize(tcx, param_env) {
- Some(0) | None => DefIdForest::empty(),
- // If the array is definitely non-empty, it's uninhabited if
- // the type of its elements is uninhabited.
- Some(1..) => ty.uninhabited_from(tcx, param_env),
+ // 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) {
+ Some(0) => InhabitedPredicate::True,
+ Some(1..) => ty.inhabited_predicate(tcx),
+ None => ty.inhabited_predicate(tcx).or(tcx, InhabitedPredicate::ConstIsZero(len)),
},
- // References to uninitialised memory are valid for any type, including
- // uninhabited types, in unsafe code, so we treat all references as
- // inhabited.
- // The precise semantics of inhabitedness with respect to references is currently
- // undecided.
- Ref(..) => DefIdForest::empty(),
-
- _ => DefIdForest::empty(),
+ _ => bug!("unexpected TyKind, use `Ty::inhabited_predicate`"),
}
}
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 9afd66207..6c1414f7b 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -1,9 +1,7 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
-use crate::ty::subst::{InternalSubsts, Subst};
-use crate::ty::{
- self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable,
-};
+use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
+use crate::ty::{EarlyBinder, InternalSubsts, SubstsRef};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 042eeec3f..3312f44c6 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,41 +1,23 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::subst::Subst;
-use crate::ty::{
- self, layout_sanity_check::sanity_check_layout, subst::SubstsRef, EarlyBinder, ReprOptions, Ty,
- TyCtxt, TypeVisitable,
-};
+use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitable};
use rustc_ast as ast;
use rustc_attr as attr;
+use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItem;
-use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{Idx, IndexVec};
-use rustc_session::{config::OptLevel, DataTypeKind, FieldInfo, SizeKind, VariantInfo};
-use rustc_span::symbol::Symbol;
+use rustc_index::vec::Idx;
+use rustc_session::config::OptLevel;
use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::call::{
- ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
-};
+use rustc_target::abi::call::FnAbi;
use rustc_target::abi::*;
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
-use std::cmp::{self, Ordering};
+use std::cmp::{self};
use std::fmt;
-use std::iter;
use std::num::NonZeroUsize;
use std::ops::Bound;
-use rand::{seq::SliceRandom, SeedableRng};
-use rand_xoshiro::Xoshiro128StarStar;
-
-pub fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
-}
-
pub trait IntegerExt {
fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>;
fn from_attr<C: HasDataLayout>(cx: &C, ity: attr::IntType) -> Integer;
@@ -207,6 +189,31 @@ pub enum LayoutError<'tcx> {
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
}
+impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
+ fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
+ let mut diag = handler.struct_fatal("");
+
+ match self {
+ LayoutError::Unknown(ty) => {
+ diag.set_arg("ty", ty);
+ diag.set_primary_message(rustc_errors::fluent::middle_unknown_layout);
+ }
+ LayoutError::SizeOverflow(ty) => {
+ diag.set_arg("ty", ty);
+ diag.set_primary_message(rustc_errors::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
+ }
+}
+
+// FIXME: Once the other errors that embed this error have been converted to translateable
+// diagnostics, this Display impl should be removed.
impl<'tcx> fmt::Display for LayoutError<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
@@ -224,1814 +231,12 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
}
}
-#[instrument(skip(tcx, query), level = "debug")]
-fn layout_of<'tcx>(
- tcx: TyCtxt<'tcx>,
- query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
-) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
- let (param_env, ty) = query.into_parts();
- debug!(?ty);
-
- let param_env = param_env.with_reveal_all_normalized(tcx);
- let unnormalized_ty = ty;
-
- // FIXME: We might want to have two different versions of `layout_of`:
- // One that can be called after typecheck has completed and can use
- // `normalize_erasing_regions` here and another one that can be called
- // before typecheck has completed and uses `try_normalize_erasing_regions`.
- let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
- Ok(t) => t,
- Err(normalization_error) => {
- return Err(LayoutError::NormalizationFailure(ty, normalization_error));
- }
- };
-
- if ty != unnormalized_ty {
- // Ensure this layout is also cached for the normalized type.
- return tcx.layout_of(param_env.and(ty));
- }
-
- let cx = LayoutCx { tcx, param_env };
-
- let layout = cx.layout_of_uncached(ty)?;
- let layout = TyAndLayout { ty, layout };
-
- cx.record_layout_for_printing(layout);
-
- sanity_check_layout(&cx, &layout);
-
- Ok(layout)
-}
-
#[derive(Clone, Copy)]
pub struct LayoutCx<'tcx, C> {
pub tcx: C,
pub param_env: ty::ParamEnv<'tcx>,
}
-#[derive(Copy, Clone, Debug)]
-enum StructKind {
- /// A tuple, closure, or univariant which cannot be coerced to unsized.
- AlwaysSized,
- /// A univariant, the last field of which may be coerced to unsized.
- MaybeUnsized,
- /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
- Prefixed(Size, Align),
-}
-
-// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
-// This is used to go between `memory_index` (source field order to memory order)
-// and `inverse_memory_index` (memory order to source field order).
-// See also `FieldsShape::Arbitrary::memory_index` for more details.
-// FIXME(eddyb) build a better abstraction for permutations, if possible.
-fn invert_mapping(map: &[u32]) -> Vec<u32> {
- let mut inverse = vec![0; map.len()];
- for i in 0..map.len() {
- inverse[map[i] as usize] = i as u32;
- }
- inverse
-}
-
-impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
- fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
- let dl = self.data_layout();
- let b_align = b.align(dl);
- let align = a.align(dl).max(b_align).max(dl.aggregate_align);
- let b_offset = a.size(dl).align_to(b_align.abi);
- let size = (b_offset + b.size(dl)).align_to(align.abi);
-
- // HACK(nox): We iter on `b` and then `a` because `max_by_key`
- // returns the last maximum.
- let largest_niche = Niche::from_scalar(dl, b_offset, b)
- .into_iter()
- .chain(Niche::from_scalar(dl, Size::ZERO, a))
- .max_by_key(|niche| niche.available(dl));
-
- LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Arbitrary {
- offsets: vec![Size::ZERO, b_offset],
- memory_index: vec![0, 1],
- },
- abi: Abi::ScalarPair(a, b),
- largest_niche,
- align,
- size,
- }
- }
-
- fn univariant_uninterned(
- &self,
- ty: Ty<'tcx>,
- fields: &[TyAndLayout<'_>],
- repr: &ReprOptions,
- kind: StructKind,
- ) -> Result<LayoutS<'tcx>, LayoutError<'tcx>> {
- let dl = self.data_layout();
- let pack = repr.pack;
- if pack.is_some() && repr.align.is_some() {
- self.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
- return Err(LayoutError::Unknown(ty));
- }
-
- let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
- let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
-
- let optimize = !repr.inhibit_struct_field_reordering_opt();
- if optimize {
- let end =
- if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
- let optimizing = &mut inverse_memory_index[..end];
- let field_align = |f: &TyAndLayout<'_>| {
- if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
- };
-
- // If `-Z randomize-layout` was enabled for the type definition we can shuffle
- // the field ordering to try and catch some code making assumptions about layouts
- // we don't guarantee
- if repr.can_randomize_type_layout() {
- // `ReprOptions.layout_seed` is a deterministic seed that we can use to
- // randomize field ordering with
- let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
-
- // Shuffle the ordering of the fields
- optimizing.shuffle(&mut rng);
-
- // Otherwise we just leave things alone and actually optimize the type's fields
- } else {
- match kind {
- StructKind::AlwaysSized | StructKind::MaybeUnsized => {
- optimizing.sort_by_key(|&x| {
- // Place ZSTs first to avoid "interesting offsets",
- // especially with only one or two non-ZST fields.
- let f = &fields[x as usize];
- (!f.is_zst(), cmp::Reverse(field_align(f)))
- });
- }
-
- StructKind::Prefixed(..) => {
- // Sort in ascending alignment so that the layout stays optimal
- // regardless of the prefix
- optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
- }
- }
-
- // FIXME(Kixiron): We can always shuffle fields within a given alignment class
- // regardless of the status of `-Z randomize-layout`
- }
- }
-
- // inverse_memory_index holds field indices by increasing memory offset.
- // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
- // We now write field offsets to the corresponding offset slot;
- // field 5 with offset 0 puts 0 in offsets[5].
- // At the bottom of this function, we invert `inverse_memory_index` to
- // produce `memory_index` (see `invert_mapping`).
-
- let mut sized = true;
- let mut offsets = vec![Size::ZERO; fields.len()];
- let mut offset = Size::ZERO;
- let mut largest_niche = None;
- let mut largest_niche_available = 0;
-
- if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
- let prefix_align =
- if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
- align = align.max(AbiAndPrefAlign::new(prefix_align));
- offset = prefix_size.align_to(prefix_align);
- }
-
- for &i in &inverse_memory_index {
- let field = fields[i as usize];
- if !sized {
- self.tcx.sess.delay_span_bug(
- DUMMY_SP,
- &format!(
- "univariant: field #{} of `{}` comes after unsized field",
- offsets.len(),
- ty
- ),
- );
- }
-
- if field.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))
- } else {
- field.align
- };
- offset = offset.align_to(field_align.abi);
- align = align.max(field_align);
-
- debug!("univariant offset: {:?} field: {:#?}", offset, field);
- offsets[i as usize] = offset;
-
- if let Some(mut niche) = field.largest_niche {
- let available = niche.available(dl);
- if available > largest_niche_available {
- largest_niche_available = available;
- niche.offset += offset;
- largest_niche = Some(niche);
- }
- }
-
- offset = offset.checked_add(field.size, dl).ok_or(LayoutError::SizeOverflow(ty))?;
- }
-
- if let Some(repr_align) = repr.align {
- align = align.max(AbiAndPrefAlign::new(repr_align));
- }
-
- debug!("univariant min_size: {:?}", offset);
- let min_size = offset;
-
- // As stated above, inverse_memory_index holds field indices by increasing offset.
- // This makes it an already-sorted view of the offsets vec.
- // To invert it, consider:
- // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
- // Field 5 would be the first element, so memory_index is i:
- // Note: if we didn't optimize, it's already right.
-
- let memory_index =
- if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index };
-
- let size = min_size.align_to(align.abi);
- let mut abi = Abi::Aggregate { sized };
-
- // 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());
-
- 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
- {
- 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;
- }
- // But scalar pairs are Rust-specific and get
- // treated as aggregates by C ABIs anyway.
- Abi::ScalarPair(..) => {
- abi = field.abi;
- }
- _ => {}
- }
- }
- }
-
- // Two non-ZST fields, and they're both scalars.
- (Some((i, a)), Some((j, b)), None) => {
- 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] {
- ((i, a), (j, b))
- } else {
- ((j, b), (i, a))
- };
- 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]);
- offsets
- }
- _ => bug!(),
- };
- if offsets[i] == pair_offsets[0]
- && offsets[j] == pair_offsets[1]
- && align == pair.align
- && size == pair.size
- {
- // We can use `ScalarPair` only when it matches our
- // already computed layout (including `#[repr(C)]`).
- abi = pair.abi;
- }
- }
- _ => {}
- }
- }
-
- _ => {}
- }
- }
-
- if fields.iter().any(|f| f.abi.is_uninhabited()) {
- abi = Abi::Uninhabited;
- }
-
- Ok(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Arbitrary { offsets, memory_index },
- abi,
- largest_niche,
- align,
- size,
- })
- }
-
- fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
- let tcx = self.tcx;
- let param_env = self.param_env;
- let dl = self.data_layout();
- let scalar_unit = |value: Primitive| {
- let size = value.size(dl);
- assert!(size.bits() <= 128);
- Scalar::Initialized { value, valid_range: WrappingRange::full(size) }
- };
- let scalar =
- |value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value)));
-
- let univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
- Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?))
- };
- debug_assert!(!ty.has_infer_types_or_consts());
-
- Ok(match *ty.kind() {
- // Basic scalars.
- ty::Bool => tcx.intern_layout(LayoutS::scalar(
- self,
- Scalar::Initialized {
- value: Int(I8, false),
- valid_range: WrappingRange { start: 0, end: 1 },
- },
- )),
- ty::Char => tcx.intern_layout(LayoutS::scalar(
- self,
- Scalar::Initialized {
- value: Int(I32, false),
- valid_range: WrappingRange { start: 0, end: 0x10FFFF },
- },
- )),
- ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
- ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
- ty::Float(fty) => scalar(match fty {
- ty::FloatTy::F32 => F32,
- ty::FloatTy::F64 => F64,
- }),
- ty::FnPtr(_) => {
- let mut ptr = scalar_unit(Pointer);
- ptr.valid_range_mut().start = 1;
- tcx.intern_layout(LayoutS::scalar(self, ptr))
- }
-
- // The never type.
- ty::Never => tcx.intern_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Primitive,
- abi: Abi::Uninhabited,
- largest_niche: None,
- align: dl.i8_align,
- size: Size::ZERO,
- }),
-
- // Potentially-wide pointers.
- ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
- let mut data_ptr = scalar_unit(Pointer);
- 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.at(DUMMY_SP), param_env) {
- return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
- }
-
- let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
- let metadata = match unsized_part.kind() {
- ty::Foreign(..) => {
- return Ok(tcx.intern_layout(LayoutS::scalar(self, data_ptr)));
- }
- ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
- ty::Dynamic(..) => {
- let mut vtable = scalar_unit(Pointer);
- vtable.valid_range_mut().start = 1;
- vtable
- }
- _ => return Err(LayoutError::Unknown(unsized_part)),
- };
-
- // Effectively a (ptr, meta) tuple.
- tcx.intern_layout(self.scalar_pair(data_ptr, metadata))
- }
-
- ty::Dynamic(_, _, ty::DynStar) => {
- let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false));
- data.valid_range_mut().start = 0;
- let mut vtable = scalar_unit(Pointer);
- vtable.valid_range_mut().start = 1;
- tcx.intern_layout(self.scalar_pair(data, vtable))
- }
-
- // Arrays and slices.
- ty::Array(element, mut count) => {
- if count.has_projections() {
- count = tcx.normalize_erasing_regions(param_env, count);
- if count.has_projections() {
- return Err(LayoutError::Unknown(ty));
- }
- }
-
- let count = count.try_eval_usize(tcx, param_env).ok_or(LayoutError::Unknown(ty))?;
- let element = self.layout_of(element)?;
- let size =
- element.size.checked_mul(count, dl).ok_or(LayoutError::SizeOverflow(ty))?;
-
- let abi =
- if count != 0 && tcx.conservative_is_privately_uninhabited(param_env.and(ty)) {
- Abi::Uninhabited
- } else {
- Abi::Aggregate { sized: true }
- };
-
- let largest_niche = if count != 0 { element.largest_niche } else { None };
-
- tcx.intern_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Array { stride: element.size, count },
- abi,
- largest_niche,
- align: element.align,
- size,
- })
- }
- ty::Slice(element) => {
- let element = self.layout_of(element)?;
- tcx.intern_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Array { stride: element.size, count: 0 },
- abi: Abi::Aggregate { sized: false },
- largest_niche: None,
- align: element.align,
- size: Size::ZERO,
- })
- }
- ty::Str => tcx.intern_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
- abi: Abi::Aggregate { sized: false },
- largest_niche: None,
- align: dl.i8_align,
- size: Size::ZERO,
- }),
-
- // Odd unit types.
- ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
- ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
- let mut unit = self.univariant_uninterned(
- ty,
- &[],
- &ReprOptions::default(),
- StructKind::AlwaysSized,
- )?;
- match unit.abi {
- Abi::Aggregate { ref mut sized } => *sized = false,
- _ => bug!(),
- }
- tcx.intern_layout(unit)
- }
-
- ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?,
-
- ty::Closure(_, ref substs) => {
- let tys = substs.as_closure().upvar_tys();
- univariant(
- &tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
- &ReprOptions::default(),
- StructKind::AlwaysSized,
- )?
- }
-
- ty::Tuple(tys) => {
- let kind =
- if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
-
- univariant(
- &tys.iter().map(|k| self.layout_of(k)).collect::<Result<Vec<_>, _>>()?,
- &ReprOptions::default(),
- kind,
- )?
- }
-
- // SIMD vector types.
- ty::Adt(def, substs) if def.repr().simd() => {
- if !def.is_struct() {
- // Should have yielded E0517 by now.
- tcx.sess.delay_span_bug(
- DUMMY_SP,
- "#[repr(simd)] was applied to an ADT that is not a struct",
- );
- return Err(LayoutError::Unknown(ty));
- }
-
- // Supported SIMD vectors are homogeneous ADTs with at least one field:
- //
- // * #[repr(simd)] struct S(T, T, T, T);
- // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T }
- // * #[repr(simd)] struct S([T; 4])
- //
- // where T is a primitive scalar (integer/float/pointer).
-
- // SIMD vectors with zero fields are not supported.
- // (should be caught by typeck)
- if def.non_enum_variant().fields.is_empty() {
- tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
- }
-
- // Type of the first ADT field:
- let f0_ty = def.non_enum_variant().fields[0].ty(tcx, substs);
-
- // Heterogeneous SIMD vectors are not supported:
- // (should be caught by typeck)
- for fi in &def.non_enum_variant().fields {
- if fi.ty(tcx, substs) != f0_ty {
- tcx.sess.fatal(&format!("monomorphising heterogeneous SIMD type `{}`", ty));
- }
- }
-
- // The element type and number of elements of the SIMD vector
- // are obtained from:
- //
- // * the element type and length of the single array field, if
- // the first field is of array type, or
- //
- // * the homogeneous field type and the number of fields.
- let (e_ty, e_len, is_array) = if let ty::Array(e_ty, _) = f0_ty.kind() {
- // First ADT field is an array:
-
- // SIMD vectors with multiple array fields are not supported:
- // (should be caught by typeck)
- if def.non_enum_variant().fields.len() != 1 {
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` with more than one array field",
- ty
- ));
- }
-
- // Extract the number of elements from the layout of the array field:
- let FieldsShape::Array { count, .. } = self.layout_of(f0_ty)?.layout.fields() else {
- return Err(LayoutError::Unknown(ty));
- };
-
- (*e_ty, *count, true)
- } else {
- // First ADT field is not an array:
- (f0_ty, def.non_enum_variant().fields.len() as _, false)
- };
-
- // SIMD vectors of zero length are not supported.
- // Additionally, lengths are capped at 2^16 as a fixed maximum backends must
- // support.
- //
- // Can't be caught in typeck if the array length is generic.
- if e_len == 0 {
- tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
- } else if e_len > MAX_SIMD_LANES {
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` of length greater than {}",
- ty, MAX_SIMD_LANES,
- ));
- }
-
- // Compute the ABI of the element type:
- let e_ly = self.layout_of(e_ty)?;
- let Abi::Scalar(e_abi) = e_ly.abi else {
- // This error isn't caught in typeck, e.g., if
- // the element type of the vector is generic.
- tcx.sess.fatal(&format!(
- "monomorphising SIMD type `{}` with a non-primitive-scalar \
- (integer/float/pointer) element type `{}`",
- ty, e_ty
- ))
- };
-
- // Compute the size and alignment of the vector:
- let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?;
- let align = dl.vector_align(size);
- let size = size.align_to(align.abi);
-
- // Compute the placement of the vector fields:
- let fields = if is_array {
- FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] }
- } else {
- FieldsShape::Array { stride: e_ly.size, count: e_len }
- };
-
- tcx.intern_layout(LayoutS {
- variants: Variants::Single { index: VariantIdx::new(0) },
- fields,
- abi: Abi::Vector { element: e_abi, count: e_len },
- largest_niche: e_ly.largest_niche,
- size,
- align,
- })
- }
-
- // ADTs.
- ty::Adt(def, substs) => {
- // Cache the field layouts.
- let variants = def
- .variants()
- .iter()
- .map(|v| {
- v.fields
- .iter()
- .map(|field| self.layout_of(field.ty(tcx, substs)))
- .collect::<Result<Vec<_>, _>>()
- })
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
- if def.is_union() {
- if def.repr().pack.is_some() && def.repr().align.is_some() {
- self.tcx.sess.delay_span_bug(
- tcx.def_span(def.did()),
- "union cannot be packed and aligned",
- );
- return Err(LayoutError::Unknown(ty));
- }
-
- let mut align =
- if def.repr().pack.is_some() { dl.i8_align } else { dl.aggregate_align };
-
- if let Some(repr_align) = def.repr().align {
- align = align.max(AbiAndPrefAlign::new(repr_align));
- }
-
- let optimize = !def.repr().inhibit_union_abi_opt();
- let mut size = Size::ZERO;
- let mut abi = Abi::Aggregate { sized: true };
- let index = VariantIdx::new(0);
- for field in &variants[index] {
- assert!(!field.is_unsized());
- align = align.max(field.align);
-
- // If all non-ZST fields have the same ABI, forward this ABI
- if optimize && !field.is_zst() {
- // Discard valid range information and allow undef
- 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 } => {
- Abi::Vector { element: x.to_union(), count }
- }
- Abi::Uninhabited | Abi::Aggregate { .. } => {
- Abi::Aggregate { sized: true }
- }
- };
-
- if size == Size::ZERO {
- // first non ZST: initialize 'abi'
- abi = field_abi;
- } else if abi != field_abi {
- // different fields have different ABI: reset to Aggregate
- abi = Abi::Aggregate { sized: true };
- }
- }
-
- size = cmp::max(size, field.size);
- }
-
- if let Some(pack) = def.repr().pack {
- align = align.min(AbiAndPrefAlign::new(pack));
- }
-
- return Ok(tcx.intern_layout(LayoutS {
- variants: Variants::Single { index },
- fields: FieldsShape::Union(
- NonZeroUsize::new(variants[index].len())
- .ok_or(LayoutError::Unknown(ty))?,
- ),
- abi,
- largest_niche: None,
- align,
- size: size.align_to(align.abi),
- }));
- }
-
- // A variant is absent if it's uninhabited and only has ZST fields.
- // Present uninhabited variants only require space for their fields,
- // 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: &[TyAndLayout<'_>]| {
- let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
- let is_zst = fields.iter().all(|f| f.is_zst());
- uninhabited && is_zst
- };
- let (present_first, present_second) = {
- let mut present_variants = variants
- .iter_enumerated()
- .filter_map(|(i, v)| if absent(v) { None } else { Some(i) });
- (present_variants.next(), present_variants.next())
- };
- let present_first = match present_first {
- Some(present_first) => present_first,
- // Uninhabited because it has no variants, or only absent ones.
- None if def.is_enum() => {
- return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout);
- }
- // If it's a struct, still compute a layout so that we can still compute the
- // field offsets.
- None => VariantIdx::new(0),
- };
-
- let is_struct = !def.is_enum() ||
- // Only one variant is present.
- (present_second.is_none() &&
- // Representation optimizations are allowed.
- !def.repr().inhibit_enum_layout_opt());
- if is_struct {
- // Struct, or univariant enum equivalent to a struct.
- // (Typechecking will reject discriminant-sizing attrs.)
-
- let v = present_first;
- let kind = if def.is_enum() || variants[v].is_empty() {
- StructKind::AlwaysSized
- } else {
- let param_env = tcx.param_env(def.did());
- let last_field = def.variant(v).fields.last().unwrap();
- let always_sized =
- tcx.type_of(last_field.did).is_sized(tcx.at(DUMMY_SP), param_env);
- if !always_sized {
- StructKind::MaybeUnsized
- } else {
- StructKind::AlwaysSized
- }
- };
-
- let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?;
- st.variants = Variants::Single { index: v };
-
- if def.is_unsafe_cell() {
- let hide_niches = |scalar: &mut _| match scalar {
- Scalar::Initialized { value, valid_range } => {
- *valid_range = WrappingRange::full(value.size(dl))
- }
- // Already doesn't have any niches
- Scalar::Union { .. } => {}
- };
- match &mut st.abi {
- Abi::Uninhabited => {}
- Abi::Scalar(scalar) => hide_niches(scalar),
- Abi::ScalarPair(a, b) => {
- hide_niches(a);
- hide_niches(b);
- }
- Abi::Vector { element, count: _ } => hide_niches(element),
- Abi::Aggregate { sized: _ } => {}
- }
- st.largest_niche = None;
- return Ok(tcx.intern_layout(st));
- }
-
- let (start, end) = self.tcx.layout_scalar_valid_range(def.did());
- match st.abi {
- Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
- // the asserts ensure that we are not using the
- // `#[rustc_layout_scalar_valid_range(n)]`
- // attribute to widen the range of anything as that would probably
- // result in UB somewhere
- // FIXME(eddyb) the asserts are probably not needed,
- // as larger validity ranges would result in missed
- // optimizations, *not* wrongly assuming the inner
- // value is valid. e.g. unions enlarge validity ranges,
- // because the values may be uninitialized.
- if let Bound::Included(start) = start {
- // FIXME(eddyb) this might be incorrect - it doesn't
- // account for wrap-around (end < start) ranges.
- let valid_range = scalar.valid_range_mut();
- assert!(valid_range.start <= start);
- valid_range.start = start;
- }
- if let Bound::Included(end) = end {
- // FIXME(eddyb) this might be incorrect - it doesn't
- // account for wrap-around (end < start) ranges.
- let valid_range = scalar.valid_range_mut();
- assert!(valid_range.end >= end);
- valid_range.end = end;
- }
-
- // Update `largest_niche` if we have introduced a larger niche.
- let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
- if let Some(niche) = niche {
- match st.largest_niche {
- Some(largest_niche) => {
- // Replace the existing niche even if they're equal,
- // because this one is at a lower offset.
- if largest_niche.available(dl) <= niche.available(dl) {
- st.largest_niche = Some(niche);
- }
- }
- None => st.largest_niche = Some(niche),
- }
- }
- }
- _ => assert!(
- start == Bound::Unbounded && end == Bound::Unbounded,
- "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}",
- def,
- st,
- ),
- }
-
- return Ok(tcx.intern_layout(st));
- }
-
- // At this point, we have handled all unions and
- // structs. (We have also handled univariant enums
- // that allow representation optimization.)
- assert!(def.is_enum());
-
- // Until we've decided whether to use the tagged or
- // niche filling LayoutS, we don't want to intern the
- // 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<'tcx> {
- layout: LayoutS<'tcx>,
- variants: IndexVec<VariantIdx, LayoutS<'tcx>>,
- }
-
- let calculate_niche_filling_layout =
- || -> Result<Option<TmpLayout<'tcx>>, LayoutError<'tcx>> {
- // The current code for niche-filling relies on variant indices
- // instead of actual discriminants, so enums with
- // explicit discriminants (RFC #2363) would misbehave.
- if def.repr().inhibit_enum_layout_opt()
- || def
- .variants()
- .iter_enumerated()
- .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32()))
- {
- return Ok(None);
- }
-
- if variants.len() < 2 {
- return Ok(None);
- }
-
- let mut align = dl.aggregate_align;
- let mut variant_layouts = variants
- .iter_enumerated()
- .map(|(j, v)| {
- let mut st = self.univariant_uninterned(
- ty,
- v,
- &def.repr(),
- StructKind::AlwaysSized,
- )?;
- st.variants = Variants::Single { index: j };
-
- align = align.max(st.align);
-
- Ok(st)
- })
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
- let largest_variant_index = match variant_layouts
- .iter_enumerated()
- .max_by_key(|(_i, layout)| layout.size.bytes())
- .map(|(i, _layout)| i)
- {
- None => return Ok(None),
- Some(i) => i,
- };
-
- let all_indices = VariantIdx::new(0)..=VariantIdx::new(variants.len() - 1);
- let needs_disc = |index: VariantIdx| {
- index != largest_variant_index && !absent(&variants[index])
- };
- let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
- ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
-
- let count = niche_variants.size_hint().1.unwrap() as u128;
-
- // Find the field with the largest niche
- let (field_index, niche, (niche_start, niche_scalar)) = match variants
- [largest_variant_index]
- .iter()
- .enumerate()
- .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(self, count)?)))
- {
- None => return Ok(None),
- Some(x) => x,
- };
-
- let niche_offset = niche.offset
- + variant_layouts[largest_variant_index].fields.offset(field_index);
- let niche_size = niche.value.size(dl);
- let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
-
- let all_variants_fit =
- variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
- if i == largest_variant_index {
- return true;
- }
-
- layout.largest_niche = None;
-
- if layout.size <= niche_offset {
- // This variant will fit before the niche.
- return true;
- }
-
- // Determine if it'll fit after the niche.
- let this_align = layout.align.abi;
- let this_offset = (niche_offset + niche_size).align_to(this_align);
-
- if this_offset + layout.size > size {
- return false;
- }
-
- // It'll fit, but we need to make some adjustments.
- match layout.fields {
- FieldsShape::Arbitrary { ref mut offsets, .. } => {
- for (j, offset) in offsets.iter_mut().enumerate() {
- if !variants[i][j].is_zst() {
- *offset += this_offset;
- }
- }
- }
- _ => {
- panic!("Layout of fields should be Arbitrary for variants")
- }
- }
-
- // It can't be a Scalar or ScalarPair because the offset isn't 0.
- if !layout.abi.is_uninhabited() {
- layout.abi = Abi::Aggregate { sized: true };
- }
- layout.size += this_offset;
-
- true
- });
-
- if !all_variants_fit {
- return Ok(None);
- }
-
- let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar);
-
- let others_zst = variant_layouts.iter_enumerated().all(|(i, layout)| {
- i == largest_variant_index || layout.size == Size::ZERO
- });
- let same_size = size == variant_layouts[largest_variant_index].size;
- let same_align = align == variant_layouts[largest_variant_index].align;
-
- let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) {
- Abi::Uninhabited
- } else if same_size && same_align && others_zst {
- match variant_layouts[largest_variant_index].abi {
- // When the total alignment and size match, we can use the
- // same ABI as the scalar variant with the reserved niche.
- Abi::Scalar(_) => Abi::Scalar(niche_scalar),
- Abi::ScalarPair(first, second) => {
- // Only the niche is guaranteed to be initialised,
- // so use union layouts for the other primitive.
- if niche_offset == Size::ZERO {
- Abi::ScalarPair(niche_scalar, second.to_union())
- } else {
- Abi::ScalarPair(first.to_union(), niche_scalar)
- }
- }
- _ => Abi::Aggregate { sized: true },
- }
- } else {
- Abi::Aggregate { sized: true }
- };
-
- let layout = LayoutS {
- variants: Variants::Multiple {
- tag: niche_scalar,
- tag_encoding: TagEncoding::Niche {
- untagged_variant: largest_variant_index,
- niche_variants,
- niche_start,
- },
- tag_field: 0,
- variants: IndexVec::new(),
- },
- fields: FieldsShape::Arbitrary {
- offsets: vec![niche_offset],
- memory_index: vec![0],
- },
- abi,
- largest_niche,
- size,
- align,
- };
-
- Ok(Some(TmpLayout { layout, variants: variant_layouts }))
- };
-
- let niche_filling_layout = calculate_niche_filling_layout()?;
-
- let (mut min, mut max) = (i128::MAX, i128::MIN);
- let discr_type = def.repr().discr_type();
- let bits = Integer::from_attr(self, discr_type).size().bits();
- for (i, discr) in def.discriminants(tcx) {
- if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
- continue;
- }
- let mut x = discr.val as i128;
- if discr_type.is_signed() {
- // sign extend the raw representation to be an i128
- x = (x << (128 - bits)) >> (128 - bits);
- }
- if x < min {
- min = x;
- }
- if x > max {
- max = x;
- }
- }
- // We might have no inhabited variants, so pretend there's at least one.
- if (min, max) == (i128::MAX, i128::MIN) {
- min = 0;
- max = 0;
- }
- assert!(min <= max, "discriminant range is {}...{}", min, max);
- let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr(), min, max);
-
- let mut align = dl.aggregate_align;
- let mut size = Size::ZERO;
-
- // We're interested in the smallest alignment, so start large.
- let mut start_align = Align::from_bytes(256).unwrap();
- assert_eq!(Integer::for_align(dl, start_align), None);
-
- // repr(C) on an enum tells us to make a (tag, union) layout,
- // so we need to grow the prefix alignment to be at least
- // the alignment of the union. (This value is used both for
- // determining the alignment of the overall enum, and the
- // determining the alignment of the payload after the tag.)
- let mut prefix_align = min_ity.align(dl).abi;
- if def.repr().c() {
- for fields in &variants {
- for field in fields {
- prefix_align = prefix_align.max(field.align.abi);
- }
- }
- }
-
- // Create the set of structs that represent each variant.
- let mut layout_variants = variants
- .iter_enumerated()
- .map(|(i, field_layouts)| {
- let mut st = self.univariant_uninterned(
- ty,
- &field_layouts,
- &def.repr(),
- StructKind::Prefixed(min_ity.size(), prefix_align),
- )?;
- st.variants = Variants::Single { index: i };
- // 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);
- break;
- }
- }
- size = cmp::max(size, st.size);
- align = align.max(st.align);
- Ok(st)
- })
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
- // Align the maximum variant size to the largest alignment.
- size = size.align_to(align.abi);
-
- if size.bytes() >= dl.obj_size_bound() {
- return Err(LayoutError::SizeOverflow(ty));
- }
-
- let typeck_ity = Integer::from_attr(dl, def.repr().discr_type());
- if typeck_ity < min_ity {
- // It is a bug if Layout decided on a greater discriminant size than typeck for
- // some reason at this point (based on values discriminant can take on). Mostly
- // because this discriminant will be loaded, and then stored into variable of
- // type calculated by typeck. Consider such case (a bug): typeck decided on
- // byte-sized discriminant, but layout thinks we need a 16-bit to store all
- // discriminant values. That would be a bug, because then, in codegen, in order
- // to store this 16-bit discriminant into 8-bit sized temporary some of the
- // space necessary to represent would have to be discarded (or layout is wrong
- // on thinking it needs 16 bits)
- bug!(
- "layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
- min_ity,
- typeck_ity
- );
- // However, it is fine to make discr type however large (as an optimisation)
- // after this point – we’ll just truncate the value we load in codegen.
- }
-
- // Check to see if we should use a different type for the
- // discriminant. We can safely use a type with the same size
- // as the alignment of the first field of each variant.
- // We increase the size of the discriminant to avoid LLVM copying
- // padding when it doesn't need to. This normally causes unaligned
- // load/stores and excessive memcpy/memset operations. By using a
- // bigger integer size, LLVM can be sure about its contents and
- // won't be so conservative.
-
- // Use the initial field alignment
- let mut ity = if def.repr().c() || def.repr().int.is_some() {
- min_ity
- } else {
- Integer::for_align(dl, start_align).unwrap_or(min_ity)
- };
-
- // If the alignment is not larger than the chosen discriminant size,
- // don't use the alignment as the final size.
- if ity <= min_ity {
- ity = min_ity;
- } else {
- // Patch up the variants' first few fields.
- let old_ity_size = min_ity.size();
- let new_ity_size = ity.size();
- for variant in &mut layout_variants {
- match variant.fields {
- FieldsShape::Arbitrary { ref mut offsets, .. } => {
- for i in offsets {
- if *i <= old_ity_size {
- assert_eq!(*i, old_ity_size);
- *i = new_ity_size;
- }
- }
- // We might be making the struct larger.
- if variant.size <= old_ity_size {
- variant.size = new_ity_size;
- }
- }
- _ => bug!(),
- }
- }
- }
-
- let tag_mask = ity.size().unsigned_int_max();
- let tag = Scalar::Initialized {
- value: Int(ity, signed),
- valid_range: WrappingRange {
- start: (min as u128 & tag_mask),
- end: (max as u128 & tag_mask),
- },
- };
- let mut abi = Abi::Aggregate { sized: true };
-
- if layout_variants.iter().all(|v| v.abi.is_uninhabited()) {
- abi = Abi::Uninhabited;
- } else if tag.size(dl) == size {
- // Make sure we only use scalar layout when the enum is entirely its
- // own tag (i.e. it has no padding nor any non-ZST variant fields).
- abi = Abi::Scalar(tag);
- } else {
- // Try to use a ScalarPair for all tagged enums.
- let mut common_prim = None;
- let mut common_prim_initialized_in_all_variants = true;
- for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
- let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
- bug!();
- };
- let mut fields =
- iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
- let (field, offset) = match (fields.next(), fields.next()) {
- (None, None) => {
- common_prim_initialized_in_all_variants = false;
- continue;
- }
- (Some(pair), None) => pair,
- _ => {
- common_prim = None;
- break;
- }
- };
- let prim = match field.abi {
- Abi::Scalar(scalar) => {
- common_prim_initialized_in_all_variants &=
- matches!(scalar, Scalar::Initialized { .. });
- scalar.primitive()
- }
- _ => {
- common_prim = None;
- break;
- }
- };
- if let Some(pair) = common_prim {
- // This is pretty conservative. We could go fancier
- // by conflating things like i32 and u32, or even
- // realising that (u8, u8) could just cohabit with
- // u16 or even u32.
- if pair != (prim, offset) {
- common_prim = None;
- break;
- }
- } else {
- common_prim = Some((prim, offset));
- }
- }
- if let Some((prim, offset)) = common_prim {
- let prim_scalar = if common_prim_initialized_in_all_variants {
- scalar_unit(prim)
- } else {
- // Common prim might be uninit.
- Scalar::Union { value: prim }
- };
- 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]);
- offsets
- }
- _ => bug!(),
- };
- if pair_offsets[0] == Size::ZERO
- && pair_offsets[1] == *offset
- && align == pair.align
- && size == pair.size
- {
- // We can use `ScalarPair` only when it matches our
- // already computed layout (including `#[repr(C)]`).
- abi = pair.abi;
- }
- }
- }
-
- // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
- // variants to ensure they are consistent. This is because a downcast is
- // semantically a NOP, and thus should not affect layout.
- if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
- for variant in &mut layout_variants {
- // We only do this for variants with fields; the others are not accessed anyway.
- // Also do not overwrite any already existing "clever" ABIs.
- if variant.fields.count() > 0
- && matches!(variant.abi, Abi::Aggregate { .. })
- {
- variant.abi = abi;
- // Also need to bump up the size and alignment, so that the entire value fits in here.
- variant.size = cmp::max(variant.size, size);
- variant.align.abi = cmp::max(variant.align.abi, align.abi);
- }
- }
- }
-
- let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
-
- let tagged_layout = LayoutS {
- variants: Variants::Multiple {
- tag,
- tag_encoding: TagEncoding::Direct,
- tag_field: 0,
- variants: IndexVec::new(),
- },
- fields: FieldsShape::Arbitrary {
- offsets: vec![Size::ZERO],
- memory_index: vec![0],
- },
- largest_niche,
- abi,
- align,
- size,
- };
-
- let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
-
- let mut best_layout = match (tagged_layout, niche_filling_layout) {
- (tl, Some(nl)) => {
- // Pick the smaller layout; otherwise,
- // pick the layout with the larger niche; otherwise,
- // pick tagged as it has simpler codegen.
- use Ordering::*;
- 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,
- _ => tl,
- }
- }
- (tl, None) => tl,
- };
-
- // Now we can intern the variant layouts and store them in the enum layout.
- best_layout.layout.variants = match best_layout.layout.variants {
- Variants::Multiple { tag, tag_encoding, tag_field, .. } => Variants::Multiple {
- tag,
- tag_encoding,
- tag_field,
- variants: best_layout
- .variants
- .into_iter()
- .map(|layout| tcx.intern_layout(layout))
- .collect(),
- },
- _ => bug!(),
- };
-
- tcx.intern_layout(best_layout.layout)
- }
-
- // Types with no meaningful known layout.
- ty::Projection(_) | ty::Opaque(..) => {
- // NOTE(eddyb) `layout_of` query should've normalized these away,
- // if that was possible, so there's no reason to try again here.
- return Err(LayoutError::Unknown(ty));
- }
-
- ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
- bug!("Layout::compute: unexpected type `{}`", ty)
- }
-
- ty::Bound(..) | ty::Param(_) | ty::Error(_) => {
- return Err(LayoutError::Unknown(ty));
- }
- })
- }
-}
-
-/// Overlap eligibility and variant assignment for each GeneratorSavedLocal.
-#[derive(Clone, Debug, PartialEq)]
-enum SavedLocalEligibility {
- Unassigned,
- Assigned(VariantIdx),
- // FIXME: Use newtype_index so we aren't wasting bytes
- Ineligible(Option<u32>),
-}
-
-// When laying out generators, we divide our saved local fields into two
-// categories: overlap-eligible and overlap-ineligible.
-//
-// Those fields which are ineligible for overlap go in a "prefix" at the
-// beginning of the layout, and always have space reserved for them.
-//
-// Overlap-eligible fields are only assigned to one variant, so we lay
-// those fields out for each variant and put them right after the
-// prefix.
-//
-// Finally, in the layout details, we point to the fields from the
-// variants they are assigned to. It is possible for some fields to be
-// included in multiple variants. No field ever "moves around" in the
-// layout; its offset is always the same.
-//
-// Also included in the layout are the upvars and the discriminant.
-// These are included as fields on the "outer" layout; they are not part
-// of any variant.
-impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
- /// Compute the eligibility and assignment of each local.
- fn generator_saved_local_eligibility(
- &self,
- info: &GeneratorLayout<'tcx>,
- ) -> (BitSet<GeneratorSavedLocal>, IndexVec<GeneratorSavedLocal, SavedLocalEligibility>) {
- use SavedLocalEligibility::*;
-
- let mut assignments: IndexVec<GeneratorSavedLocal, SavedLocalEligibility> =
- IndexVec::from_elem_n(Unassigned, info.field_tys.len());
-
- // The saved locals not eligible for overlap. These will get
- // "promoted" to the prefix of our generator.
- let mut ineligible_locals = BitSet::new_empty(info.field_tys.len());
-
- // Figure out which of our saved locals are fields in only
- // one variant. The rest are deemed ineligible for overlap.
- for (variant_index, fields) in info.variant_fields.iter_enumerated() {
- for local in fields {
- match assignments[*local] {
- Unassigned => {
- assignments[*local] = Assigned(variant_index);
- }
- Assigned(idx) => {
- // We've already seen this local at another suspension
- // point, so it is no longer a candidate.
- trace!(
- "removing local {:?} in >1 variant ({:?}, {:?})",
- local,
- variant_index,
- idx
- );
- ineligible_locals.insert(*local);
- assignments[*local] = Ineligible(None);
- }
- Ineligible(_) => {}
- }
- }
- }
-
- // Next, check every pair of eligible locals to see if they
- // conflict.
- for local_a in info.storage_conflicts.rows() {
- let conflicts_a = info.storage_conflicts.count(local_a);
- if ineligible_locals.contains(local_a) {
- continue;
- }
-
- for local_b in info.storage_conflicts.iter(local_a) {
- // local_a and local_b are storage live at the same time, therefore they
- // cannot overlap in the generator layout. The only way to guarantee
- // this is if they are in the same variant, or one is ineligible
- // (which means it is stored in every variant).
- if ineligible_locals.contains(local_b)
- || assignments[local_a] == assignments[local_b]
- {
- continue;
- }
-
- // If they conflict, we will choose one to make ineligible.
- // This is not always optimal; it's just a greedy heuristic that
- // seems to produce good results most of the time.
- let conflicts_b = info.storage_conflicts.count(local_b);
- let (remove, other) =
- if conflicts_a > conflicts_b { (local_a, local_b) } else { (local_b, local_a) };
- ineligible_locals.insert(remove);
- assignments[remove] = Ineligible(None);
- trace!("removing local {:?} due to conflict with {:?}", remove, other);
- }
- }
-
- // Count the number of variants in use. If only one of them, then it is
- // impossible to overlap any locals in our layout. In this case it's
- // always better to make the remaining locals ineligible, so we can
- // lay them out with the other locals in the prefix and eliminate
- // unnecessary padding bytes.
- {
- let mut used_variants = BitSet::new_empty(info.variant_fields.len());
- for assignment in &assignments {
- if let Assigned(idx) = assignment {
- used_variants.insert(*idx);
- }
- }
- if used_variants.count() < 2 {
- for assignment in assignments.iter_mut() {
- *assignment = Ineligible(None);
- }
- ineligible_locals.insert_all();
- }
- }
-
- // Write down the order of our locals that will be promoted to the prefix.
- {
- for (idx, local) in ineligible_locals.iter().enumerate() {
- assignments[local] = Ineligible(Some(idx as u32));
- }
- }
- debug!("generator saved local assignments: {:?}", assignments);
-
- (ineligible_locals, assignments)
- }
-
- /// Compute the full generator layout.
- fn generator_layout(
- &self,
- ty: Ty<'tcx>,
- def_id: hir::def_id::DefId,
- substs: SubstsRef<'tcx>,
- ) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
- use SavedLocalEligibility::*;
- let tcx = self.tcx;
- let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
-
- let Some(info) = tcx.generator_layout(def_id) else {
- return Err(LayoutError::Unknown(ty));
- };
- let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info);
-
- // Build a prefix layout, including "promoting" all ineligible
- // locals as part of the prefix. We compute the layout of all of
- // these fields at once to get optimal packing.
- let tag_index = substs.as_generator().prefix_tys().count();
-
- // `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 = self.tcx.intern_layout(LayoutS::scalar(self, tag));
- let tag_layout = TyAndLayout { ty: discr_int_ty, layout: tag_layout };
-
- let promoted_layouts = ineligible_locals
- .iter()
- .map(|local| subst_field(info.field_tys[local]))
- .map(|ty| tcx.mk_maybe_uninit(ty))
- .map(|ty| self.layout_of(ty));
- let prefix_layouts = substs
- .as_generator()
- .prefix_tys()
- .map(|ty| self.layout_of(ty))
- .chain(iter::once(Ok(tag_layout)))
- .chain(promoted_layouts)
- .collect::<Result<Vec<_>, _>>()?;
- let prefix = self.univariant_uninterned(
- ty,
- &prefix_layouts,
- &ReprOptions::default(),
- StructKind::AlwaysSized,
- )?;
-
- let (prefix_size, prefix_align) = (prefix.size, prefix.align);
-
- // Split the prefix layout into the "outer" fields (upvars and
- // discriminant) and the "promoted" fields. Promoted fields will
- // get included in each variant that requested them in
- // GeneratorLayout.
- debug!("prefix = {:#?}", prefix);
- let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
- FieldsShape::Arbitrary { mut offsets, memory_index } => {
- let mut inverse_memory_index = invert_mapping(&memory_index);
-
- // "a" (`0..b_start`) and "b" (`b_start..`) correspond to
- // "outer" and "promoted" fields respectively.
- let b_start = (tag_index + 1) as u32;
- let offsets_b = offsets.split_off(b_start as usize);
- let offsets_a = offsets;
-
- // Disentangle the "a" and "b" components of `inverse_memory_index`
- // by preserving the order but keeping only one disjoint "half" each.
- // FIXME(eddyb) build a better abstraction for permutations, if possible.
- let inverse_memory_index_b: Vec<_> =
- inverse_memory_index.iter().filter_map(|&i| i.checked_sub(b_start)).collect();
- inverse_memory_index.retain(|&i| i < b_start);
- let inverse_memory_index_a = inverse_memory_index;
-
- // Since `inverse_memory_index_{a,b}` each only refer to their
- // respective fields, they can be safely inverted
- let memory_index_a = invert_mapping(&inverse_memory_index_a);
- let memory_index_b = invert_mapping(&inverse_memory_index_b);
-
- let outer_fields =
- FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
- (outer_fields, offsets_b, memory_index_b)
- }
- _ => bug!(),
- };
-
- let mut size = prefix.size;
- let mut align = prefix.align;
- let variants = info
- .variant_fields
- .iter_enumerated()
- .map(|(index, variant_fields)| {
- // Only include overlap-eligible fields when we compute our variant layout.
- let variant_only_tys = variant_fields
- .iter()
- .filter(|local| match assignments[**local] {
- Unassigned => bug!(),
- Assigned(v) if v == index => true,
- Assigned(_) => bug!("assignment does not match variant"),
- Ineligible(_) => false,
- })
- .map(|local| subst_field(info.field_tys[*local]));
-
- let mut variant = self.univariant_uninterned(
- ty,
- &variant_only_tys
- .map(|ty| self.layout_of(ty))
- .collect::<Result<Vec<_>, _>>()?,
- &ReprOptions::default(),
- StructKind::Prefixed(prefix_size, prefix_align.abi),
- )?;
- variant.variants = Variants::Single { index };
-
- let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else {
- bug!();
- };
-
- // Now, stitch the promoted and variant-only fields back together in
- // the order they are mentioned by our GeneratorLayout.
- // Because we only use some subset (that can differ between variants)
- // of the promoted fields, we can't just pick those elements of the
- // `promoted_memory_index` (as we'd end up with gaps).
- // So instead, we build an "inverse memory_index", as if all of the
- // promoted fields were being used, but leave the elements not in the
- // subset as `INVALID_FIELD_IDX`, which we can filter out later to
- // obtain a valid (bijective) mapping.
- const INVALID_FIELD_IDX: u32 = !0;
- let mut combined_inverse_memory_index =
- vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()];
- let mut offsets_and_memory_index = iter::zip(offsets, memory_index);
- let combined_offsets = variant_fields
- .iter()
- .enumerate()
- .map(|(i, local)| {
- let (offset, memory_index) = match assignments[*local] {
- Unassigned => bug!(),
- Assigned(_) => {
- let (offset, memory_index) =
- offsets_and_memory_index.next().unwrap();
- (offset, promoted_memory_index.len() as u32 + memory_index)
- }
- Ineligible(field_idx) => {
- let field_idx = field_idx.unwrap() as usize;
- (promoted_offsets[field_idx], promoted_memory_index[field_idx])
- }
- };
- combined_inverse_memory_index[memory_index as usize] = i as u32;
- offset
- })
- .collect();
-
- // Remove the unused slots and invert the mapping to obtain the
- // combined `memory_index` (also see previous comment).
- combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
- let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
-
- variant.fields = FieldsShape::Arbitrary {
- offsets: combined_offsets,
- memory_index: combined_memory_index,
- };
-
- size = size.max(variant.size);
- align = align.max(variant.align);
- Ok(tcx.intern_layout(variant))
- })
- .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
-
- size = size.align_to(align.abi);
-
- let abi =
- if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) {
- Abi::Uninhabited
- } else {
- Abi::Aggregate { sized: true }
- };
-
- let layout = tcx.intern_layout(LayoutS {
- variants: Variants::Multiple {
- tag,
- tag_encoding: TagEncoding::Direct,
- tag_field: tag_index,
- variants,
- },
- fields: outer_fields,
- abi,
- largest_niche: prefix.largest_niche,
- size,
- align,
- });
- debug!("generator layout ({:?}): {:#?}", ty, layout);
- Ok(layout)
- }
-
- /// This is invoked by the `layout_of` query to record the final
- /// layout of each type.
- #[inline(always)]
- fn record_layout_for_printing(&self, layout: TyAndLayout<'tcx>) {
- // If we are running with `-Zprint-type-sizes`, maybe record layouts
- // for dumping later.
- if self.tcx.sess.opts.unstable_opts.print_type_sizes {
- self.record_layout_for_printing_outlined(layout)
- }
- }
-
- fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) {
- // Ignore layouts that are done with non-empty environments or
- // non-monomorphic layouts, as the user only wants to see the stuff
- // resulting from the final codegen session.
- if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
- return;
- }
-
- // (delay format until we actually need it)
- let record = |kind, packed, opt_discr_size, variants| {
- let type_desc = format!("{:?}", layout.ty);
- self.tcx.sess.code_stats.record_type_size(
- kind,
- type_desc,
- layout.align.abi,
- layout.size,
- packed,
- opt_discr_size,
- variants,
- );
- };
-
- let adt_def = match *layout.ty.kind() {
- ty::Adt(ref adt_def, _) => {
- debug!("print-type-size t: `{:?}` process adt", layout.ty);
- adt_def
- }
-
- ty::Closure(..) => {
- debug!("print-type-size t: `{:?}` record closure", layout.ty);
- record(DataTypeKind::Closure, false, None, vec![]);
- return;
- }
-
- _ => {
- debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
- return;
- }
- };
-
- let adt_kind = adt_def.adt_kind();
- let adt_packed = adt_def.repr().pack.is_some();
-
- let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
- let mut min_size = Size::ZERO;
- let field_info: Vec<_> = flds
- .iter()
- .enumerate()
- .map(|(i, &name)| {
- let field_layout = layout.field(self, i);
- let offset = layout.fields.offset(i);
- let field_end = offset + field_layout.size;
- if min_size < field_end {
- min_size = field_end;
- }
- FieldInfo {
- name,
- offset: offset.bytes(),
- size: field_layout.size.bytes(),
- align: field_layout.align.abi.bytes(),
- }
- })
- .collect();
-
- VariantInfo {
- name: n,
- kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
- align: layout.align.abi.bytes(),
- size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
- fields: field_info,
- }
- };
-
- match layout.variants {
- Variants::Single { index } => {
- if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
- debug!(
- "print-type-size `{:#?}` variant {}",
- layout,
- adt_def.variant(index).name
- );
- let variant_def = &adt_def.variant(index);
- let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
- record(
- adt_kind.into(),
- adt_packed,
- None,
- vec![build_variant_info(Some(variant_def.name), &fields, layout)],
- );
- } else {
- // (This case arises for *empty* enums; so give it
- // zero variants.)
- record(adt_kind.into(), adt_packed, None, vec![]);
- }
- }
-
- Variants::Multiple { tag, ref tag_encoding, .. } => {
- debug!(
- "print-type-size `{:#?}` adt general variants def {}",
- layout.ty,
- adt_def.variants().len()
- );
- let variant_infos: Vec<_> = adt_def
- .variants()
- .iter_enumerated()
- .map(|(i, variant_def)| {
- let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
- build_variant_info(
- Some(variant_def.name),
- &fields,
- layout.for_variant(self, i),
- )
- })
- .collect();
- record(
- adt_kind.into(),
- adt_packed,
- match tag_encoding {
- TagEncoding::Direct => Some(tag.size(self)),
- _ => None,
- },
- variant_infos,
- );
- }
- }
- }
-}
-
/// Type size "skeleton", i.e., the only information determining a type's size.
/// While this is conservative, (aside from constant sizes, only pointers,
/// newtypes thereof and null pointer optimized enums are allowed), it is
@@ -2058,7 +263,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
- debug_assert!(!ty.has_infer_types_or_consts());
+ debug_assert!(!ty.has_non_region_infer());
// First try computing a static layout.
let err = match tcx.layout_of(param_env.and(ty)) {
@@ -2074,7 +279,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
ty::Param(_) | ty::Projection(_) => {
- debug_assert!(tail.has_param_types_or_consts());
+ debug_assert!(tail.has_non_region_param());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
_ => bug!(
@@ -2625,7 +830,7 @@ where
} else {
match mt {
hir::Mutability::Not => {
- if ty.is_freeze(tcx.at(DUMMY_SP), cx.param_env()) {
+ if ty.is_freeze(tcx, cx.param_env()) {
PointerKind::Frozen
} else {
PointerKind::SharedMutable
@@ -2636,7 +841,7 @@ where
// noalias, as another pointer to the structure can be obtained, that
// is not based-on the original reference. We consider all !Unpin
// types to be potentially self-referential here.
- if ty.is_unpin(tcx.at(DUMMY_SP), cx.param_env()) {
+ if ty.is_unpin(tcx, cx.param_env()) {
PointerKind::UniqueBorrowed
} else {
PointerKind::UniqueBorrowedPinned
@@ -2748,112 +953,6 @@ where
}
}
-impl<'tcx> ty::Instance<'tcx> {
- // NOTE(eddyb) this is private to avoid using it from outside of
- // `fn_abi_of_instance` - any other uses are either too high-level
- // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
- // or should go through `FnAbi` instead, to avoid losing any
- // adjustments `fn_abi_of_instance` might be performing.
- #[tracing::instrument(level = "debug", skip(tcx, param_env))]
- fn fn_sig_for_fn_abi(
- &self,
- tcx: TyCtxt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> ty::PolyFnSig<'tcx> {
- let ty = self.ty(tcx, param_env);
- match *ty.kind() {
- ty::FnDef(..) => {
- // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
- // parameters unused if they show up in the signature, but not in the `mir::Body`
- // (i.e. due to being inside a projection that got normalized, see
- // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
- // track of a polymorphization `ParamEnv` to allow normalizing later.
- let mut sig = match *ty.kind() {
- ty::FnDef(def_id, substs) => tcx
- .normalize_erasing_regions(tcx.param_env(def_id), tcx.bound_fn_sig(def_id))
- .subst(tcx, substs),
- _ => unreachable!(),
- };
-
- if let ty::InstanceDef::VTableShim(..) = self.def {
- // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
- 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
- });
- }
- sig
- }
- ty::Closure(def_id, substs) => {
- let sig = substs.as_closure().sig();
-
- let bound_vars = tcx.mk_bound_variable_kinds(
- sig.bound_vars()
- .iter()
- .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
- );
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_usize(bound_vars.len() - 1),
- kind: ty::BoundRegionKind::BrEnv,
- };
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
- let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
-
- let sig = sig.skip_binder();
- ty::Binder::bind_with_vars(
- tcx.mk_fn_sig(
- iter::once(env_ty).chain(sig.inputs().iter().cloned()),
- sig.output(),
- sig.c_variadic,
- sig.unsafety,
- sig.abi,
- ),
- bound_vars,
- )
- }
- ty::Generator(_, substs, _) => {
- let sig = substs.as_generator().poly_sig();
-
- let bound_vars = tcx.mk_bound_variable_kinds(
- sig.bound_vars()
- .iter()
- .chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
- );
- let br = ty::BoundRegion {
- var: ty::BoundVar::from_usize(bound_vars.len() - 1),
- kind: ty::BoundRegionKind::BrEnv,
- };
- let env_region = ty::ReLateBound(ty::INNERMOST, br);
- let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
-
- 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 env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
-
- let sig = sig.skip_binder();
- let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
- let state_adt_ref = tcx.adt_def(state_did);
- let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
- let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
- ty::Binder::bind_with_vars(
- tcx.mk_fn_sig(
- [env_ty, sig.resume_ty].iter(),
- &ret_ty,
- false,
- hir::Unsafety::Normal,
- rustc_target::spec::abi::Abi::Rust,
- ),
- bound_vars,
- )
- }
- _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
- }
- }
-}
-
/// Calculates whether a function's ABI can unwind or not.
///
/// This takes two primary parameters:
@@ -2996,40 +1095,6 @@ pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option<DefId>, abi: Spe
}
}
-#[inline]
-pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
- use rustc_target::spec::abi::Abi::*;
- match tcx.sess.target.adjust_abi(abi) {
- RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
- RustCold => Conv::RustCold,
-
- // It's the ABI's job to select this, not ours.
- System { .. } => bug!("system abi should be selected elsewhere"),
- EfiApi => bug!("eficall abi should be selected elsewhere"),
-
- Stdcall { .. } => Conv::X86Stdcall,
- Fastcall { .. } => Conv::X86Fastcall,
- Vectorcall { .. } => Conv::X86VectorCall,
- Thiscall { .. } => Conv::X86ThisCall,
- C { .. } => Conv::C,
- Unadjusted => Conv::C,
- Win64 { .. } => Conv::X86_64Win64,
- SysV64 { .. } => Conv::X86_64SysV,
- Aapcs { .. } => Conv::ArmAapcs,
- CCmseNonSecureCall => Conv::CCmseNonSecureCall,
- PtxKernel => Conv::PtxKernel,
- Msp430Interrupt => Conv::Msp430Intr,
- X86Interrupt => Conv::X86Intr,
- AmdGpuKernel => Conv::AmdGpuKernel,
- AvrInterrupt => Conv::AvrInterrupt,
- AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
- Wasm => Conv::C,
-
- // These API constants ought to be more specific...
- Cdecl { .. } => Conv::C,
- }
-}
-
/// Error produced by attempting to compute or adjust a `FnAbi`.
#[derive(Copy, Clone, Debug, HashStable)]
pub enum FnAbiError<'tcx> {
@@ -3061,6 +1126,12 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
}
}
+impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> {
+ fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> {
+ handler.struct_fatal(self.to_string())
+ }
+}
+
// FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
// just for error handling.
#[derive(Debug)]
@@ -3142,367 +1213,3 @@ pub trait FnAbiOf<'tcx>: FnAbiOfHelpers<'tcx> {
}
impl<'tcx, C: FnAbiOfHelpers<'tcx>> FnAbiOf<'tcx> for C {}
-
-fn fn_abi_of_fn_ptr<'tcx>(
- tcx: TyCtxt<'tcx>,
- query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
- let (param_env, (sig, extra_args)) = query.into_parts();
-
- LayoutCx { tcx, param_env }.fn_abi_new_uncached(sig, extra_args, None, None, false)
-}
-
-fn fn_abi_of_instance<'tcx>(
- tcx: TyCtxt<'tcx>,
- query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
-) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
- let (param_env, (instance, extra_args)) = query.into_parts();
-
- let sig = instance.fn_sig_for_fn_abi(tcx, param_env);
-
- let caller_location = if instance.def.requires_caller_location(tcx) {
- Some(tcx.caller_location_ty())
- } else {
- None
- };
-
- LayoutCx { tcx, param_env }.fn_abi_new_uncached(
- sig,
- extra_args,
- caller_location,
- Some(instance.def_id()),
- matches!(instance.def, ty::InstanceDef::Virtual(..)),
- )
-}
-
-// Handle safe Rust thin and fat pointers.
-pub fn adjust_for_rust_scalar<'tcx>(
- cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
- attrs: &mut ArgAttributes,
- scalar: Scalar,
- layout: TyAndLayout<'tcx>,
- offset: Size,
- is_return: bool,
-) {
- // Booleans are always a noundef i1 that needs to be zero-extended.
- if scalar.is_bool() {
- attrs.ext(ArgExtension::Zext);
- attrs.set(ArgAttribute::NoUndef);
- return;
- }
-
- // Scalars which have invalid values cannot be undef.
- if !scalar.is_always_valid(&cx) {
- attrs.set(ArgAttribute::NoUndef);
- }
-
- // Only pointer types handled below.
- let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
-
- if !valid_range.contains(0) {
- attrs.set(ArgAttribute::NonNull);
- }
-
- if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
- 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.
- attrs.pointee_size = match kind {
- PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned
- | PointerKind::Frozen => pointee.size,
- PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
- };
-
- // `Box`, `&T`, and `&mut T` cannot be undef.
- // Note that this only applies to the value of the pointer itself;
- // this attribute doesn't make it UB for the pointed-to data to be undef.
- attrs.set(ArgAttribute::NoUndef);
-
- // The aliasing rules for `Box<T>` are still not decided, but currently we emit
- // `noalias` for it. This can be turned off using an unstable flag.
- // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
- let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
-
- // `&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
- //
- // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
- // for UniqueBorrowed arguments, so that the codegen backend can decide whether
- // or not to actually emit the attribute. It can also be controlled with the
- // `-Zmutable-noalias` debugging option.
- let no_alias = match kind {
- PointerKind::SharedMutable
- | PointerKind::UniqueBorrowed
- | PointerKind::UniqueBorrowedPinned => false,
- PointerKind::UniqueOwned => noalias_for_box,
- PointerKind::Frozen => !is_return,
- };
- if no_alias {
- attrs.set(ArgAttribute::NoAlias);
- }
-
- if kind == PointerKind::Frozen && !is_return {
- attrs.set(ArgAttribute::ReadOnly);
- }
-
- if kind == PointerKind::UniqueBorrowed && !is_return {
- attrs.set(ArgAttribute::NoAliasMutRef);
- }
- }
- }
-}
-
-impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
- // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
- // arguments of this method, into a separate `struct`.
- #[tracing::instrument(
- level = "debug",
- skip(self, caller_location, fn_def_id, force_thin_self_ptr)
- )]
- fn fn_abi_new_uncached(
- &self,
- sig: ty::PolyFnSig<'tcx>,
- extra_args: &[Ty<'tcx>],
- caller_location: Option<Ty<'tcx>>,
- fn_def_id: Option<DefId>,
- // FIXME(eddyb) replace this with something typed, like an `enum`.
- force_thin_self_ptr: bool,
- ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
- let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig);
-
- let conv = conv_from_spec_abi(self.tcx(), sig.abi);
-
- let mut inputs = sig.inputs();
- let extra_args = if sig.abi == RustCall {
- assert!(!sig.c_variadic && extra_args.is_empty());
-
- if let Some(input) = sig.inputs().last() {
- if let ty::Tuple(tupled_arguments) = input.kind() {
- inputs = &sig.inputs()[0..sig.inputs().len() - 1];
- tupled_arguments
- } else {
- bug!(
- "argument to function with \"rust-call\" ABI \
- is not a tuple"
- );
- }
- } else {
- bug!(
- "argument to function with \"rust-call\" ABI \
- is not a tuple"
- );
- }
- } else {
- assert!(sig.c_variadic || extra_args.is_empty());
- extra_args
- };
-
- let target = &self.tcx.sess.target;
- let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc");
- let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
- let linux_s390x_gnu_like =
- target.os == "linux" && target.arch == "s390x" && target_env_gnu_like;
- let linux_sparc64_gnu_like =
- target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like;
- let linux_powerpc_gnu_like =
- target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like;
- use SpecAbi::*;
- let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
-
- let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
- let span = tracing::debug_span!("arg_of");
- let _entered = span.enter();
- let is_return = arg_idx.is_none();
-
- let layout = self.layout_of(ty)?;
- let layout = if force_thin_self_ptr && arg_idx == Some(0) {
- // Don't pass the vtable, it's not an argument of the virtual fn.
- // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
- // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
- make_thin_self_ptr(self, layout)
- } else {
- layout
- };
-
- let mut arg = ArgAbi::new(self, layout, |layout, scalar, offset| {
- let mut attrs = ArgAttributes::new();
- adjust_for_rust_scalar(*self, &mut attrs, scalar, *layout, offset, is_return);
- attrs
- });
-
- if arg.layout.is_zst() {
- // For some forsaken reason, x86_64-pc-windows-gnu
- // doesn't ignore zero-sized struct arguments.
- // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
- if is_return
- || rust_abi
- || (!win_x64_gnu
- && !linux_s390x_gnu_like
- && !linux_sparc64_gnu_like
- && !linux_powerpc_gnu_like)
- {
- arg.mode = PassMode::Ignore;
- }
- }
-
- Ok(arg)
- };
-
- let mut fn_abi = FnAbi {
- ret: arg_of(sig.output(), None)?,
- args: inputs
- .iter()
- .copied()
- .chain(extra_args.iter().copied())
- .chain(caller_location)
- .enumerate()
- .map(|(i, ty)| arg_of(ty, Some(i)))
- .collect::<Result<_, _>>()?,
- c_variadic: sig.c_variadic,
- fixed_count: inputs.len() as u32,
- conv,
- can_unwind: fn_can_unwind(self.tcx(), fn_def_id, sig.abi),
- };
- self.fn_abi_adjust_for_abi(&mut fn_abi, sig.abi)?;
- debug!("fn_abi_new_uncached = {:?}", fn_abi);
- Ok(self.tcx.arena.alloc(fn_abi))
- }
-
- #[tracing::instrument(level = "trace", skip(self))]
- fn fn_abi_adjust_for_abi(
- &self,
- fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
- abi: SpecAbi,
- ) -> Result<(), FnAbiError<'tcx>> {
- if abi == SpecAbi::Unadjusted {
- return Ok(());
- }
-
- if abi == SpecAbi::Rust
- || abi == SpecAbi::RustCall
- || abi == SpecAbi::RustIntrinsic
- || abi == SpecAbi::PlatformIntrinsic
- {
- let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>| {
- if arg.is_ignore() {
- return;
- }
-
- match arg.layout.abi {
- Abi::Aggregate { .. } => {}
-
- // This is a fun case! The gist of what this is doing is
- // that we want callers and callees to always agree on the
- // ABI of how they pass SIMD arguments. If we were to *not*
- // make these arguments indirect then they'd be immediates
- // in LLVM, which means that they'd used whatever the
- // appropriate ABI is for the callee and the caller. That
- // means, for example, if the caller doesn't have AVX
- // enabled but the callee does, then passing an AVX argument
- // across this boundary would cause corrupt data to show up.
- //
- // This problem is fixed by unconditionally passing SIMD
- // arguments through memory between callers and callees
- // which should get them all to agree on ABI regardless of
- // target feature sets. Some more information about this
- // issue can be found in #44367.
- //
- // Note that the platform intrinsic ABI is exempt here as
- // that's how we connect up to LLVM and it's unstable
- // anyway, we control all calls to it in libstd.
- Abi::Vector { .. }
- if abi != SpecAbi::PlatformIntrinsic
- && self.tcx.sess.target.simd_types_indirect =>
- {
- arg.make_indirect();
- return;
- }
-
- _ => return,
- }
-
- let size = arg.layout.size;
- if arg.layout.is_unsized() || size > Pointer.size(self) {
- arg.make_indirect();
- } else {
- // We want to pass small aggregates as immediates, but using
- // a LLVM aggregate type for this leads to bad optimizations,
- // so we pick an appropriately sized integer type instead.
- arg.cast_to(Reg { kind: RegKind::Integer, size });
- }
- };
- fixup(&mut fn_abi.ret);
- for arg in fn_abi.args.iter_mut() {
- fixup(arg);
- }
- } else {
- fn_abi.adjust_for_foreign_abi(self, abi)?;
- }
-
- Ok(())
- }
-}
-
-#[tracing::instrument(level = "debug", skip(cx))]
-fn make_thin_self_ptr<'tcx>(
- cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
- layout: TyAndLayout<'tcx>,
-) -> TyAndLayout<'tcx> {
- let tcx = cx.tcx();
- let fat_pointer_ty = if layout.is_unsized() {
- // unsized `self` is passed as a pointer to `self`
- // FIXME (mikeyhew) change this to use &own if it is ever added to the language
- tcx.mk_mut_ptr(layout.ty)
- } else {
- match layout.abi {
- Abi::ScalarPair(..) | Abi::Scalar(..) => (),
- _ => bug!("receiver type has unsupported layout: {:?}", layout),
- }
-
- // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
- // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
- // elsewhere in the compiler as a method on a `dyn Trait`.
- // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
- // get a built-in pointer type
- let mut fat_pointer_layout = layout;
- 'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
- && !fat_pointer_layout.ty.is_region_ptr()
- {
- for i in 0..fat_pointer_layout.fields.count() {
- let field_layout = fat_pointer_layout.field(cx, i);
-
- if !field_layout.is_zst() {
- fat_pointer_layout = field_layout;
- continue 'descend_newtypes;
- }
- }
-
- bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
- }
-
- fat_pointer_layout.ty
- };
-
- // we now have a type like `*mut RcBox<dyn Trait>`
- // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
- // this is understood as a special case elsewhere in the compiler
- let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit());
-
- TyAndLayout {
- ty: fat_pointer_ty,
-
- // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
- // should always work because the type is always `*mut ()`.
- ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
- }
-}
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3f9871190..a42d05706 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -17,7 +17,7 @@ pub use self::IntVarValue::*;
pub use self::Variance::*;
use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
use crate::metadata::ModChild;
-use crate::middle::privacy::AccessLevels;
+use crate::middle::privacy::EffectiveVisibilities;
use crate::mir::{Body, GeneratorLayout};
use crate::traits::{self, Reveal};
use crate::ty;
@@ -26,6 +26,7 @@ use crate::ty::util::Discr;
pub use adt::*;
pub use assoc::*;
pub use generics::*;
+use hir::OpaqueTyOrigin;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
@@ -37,11 +38,13 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
+use rustc_hir::definitions::Definitions;
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::CrateStoreDyn;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{ExpnId, Span};
@@ -73,11 +76,11 @@ pub use self::closure::{
CAPTURE_STRUCT_LOCAL,
};
pub use self::consts::{
- Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, Unevaluated, ValTree,
+ Const, ConstInt, ConstKind, ConstS, InferConst, ScalarInt, UnevaluatedConst, ValTree,
};
pub use self::context::{
tls, CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
- CtxtInterners, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
+ CtxtInterners, DeducedParamAttrs, DelaySpanBugEmitted, FreeRegionInfo, GeneratorDiagnosticData,
GeneratorInteriorTypeCause, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TypeckResults, UserType,
UserTypeAnnotationIndex,
};
@@ -89,9 +92,9 @@ pub use self::sty::BoundRegionKind::*;
pub use self::sty::{
Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid,
- EarlyBinder, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection,
- ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts,
- InlineConstSubsts, InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
+ EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
+ FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts,
+ InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection,
PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind,
RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo,
};
@@ -130,8 +133,8 @@ mod erase_regions;
mod generics;
mod impls_ty;
mod instance;
-mod layout_sanity_check;
mod list;
+mod opaque_types;
mod parameterized;
mod rvalue_scopes;
mod structural_impls;
@@ -141,8 +144,15 @@ mod sty;
pub type RegisteredTools = FxHashSet<Ident>;
-#[derive(Debug)]
pub struct ResolverOutputs {
+ pub definitions: Definitions,
+ pub global_ctxt: ResolverGlobalCtxt,
+ pub ast_lowering: ResolverAstLowering,
+}
+
+#[derive(Debug)]
+pub struct ResolverGlobalCtxt {
+ pub cstore: Box<CrateStoreDyn>,
pub visibilities: FxHashMap<LocalDefId, Visibility>,
/// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
pub has_pub_restricted: bool,
@@ -150,7 +160,7 @@ pub struct ResolverOutputs {
pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
/// Reference span for definitions.
pub source_span: IndexVec<LocalDefId, Span>,
- pub access_levels: AccessLevels,
+ 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)>,
@@ -682,7 +692,7 @@ pub enum PredicateKind<'tcx> {
Coerce(CoercePredicate<'tcx>),
/// Constant initializer must evaluate successfully.
- ConstEvaluatable(ty::Unevaluated<'tcx, ()>),
+ ConstEvaluatable(ty::Const<'tcx>),
/// Constants must be equal. The first component is the const that is expected.
ConstEquate(Const<'tcx>, Const<'tcx>),
@@ -861,6 +871,11 @@ impl<'tcx> TraitPredicate<'tcx> {
(BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
}
}
+
+ pub fn without_const(mut self) -> Self {
+ self.constness = BoundConstness::NotConst;
+ self
+ }
}
impl<'tcx> PolyTraitPredicate<'tcx> {
@@ -1296,6 +1311,106 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
sub: sub_diag,
});
}
+
+ #[instrument(level = "debug", skip(tcx), ret)]
+ pub fn remap_generic_params_to_declaration_params(
+ self,
+ opaque_type_key: OpaqueTypeKey<'tcx>,
+ tcx: TyCtxt<'tcx>,
+ // typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
+ ignore_errors: bool,
+ origin: OpaqueTyOrigin,
+ ) -> Self {
+ let OpaqueTypeKey { def_id, substs } = opaque_type_key;
+
+ // Use substs to build up a reverse map from regions to their
+ // identity mappings. This is necessary because of `impl
+ // Trait` lifetimes are computed by replacing existing
+ // lifetimes with 'static and remapping only those used in the
+ // `impl Trait` return type, resulting in the parameters
+ // shifting.
+ let id_substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ debug!(?id_substs);
+
+ let map = substs.iter().zip(id_substs);
+
+ let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = match origin {
+ // HACK: The HIR lowering for async fn does not generate
+ // any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes
+ // would now fail to compile. We should probably just make hir lowering fill this in properly.
+ OpaqueTyOrigin::AsyncFn(_) => map.collect(),
+ OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::TyAlias => {
+ // Opaque types may only use regions that are bound. So for
+ // ```rust
+ // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
+ // ```
+ // we may not use `'c` in the hidden type.
+ struct OpaqueTypeLifetimeCollector<'tcx> {
+ lifetimes: FxHashSet<ty::Region<'tcx>>,
+ }
+
+ impl<'tcx> ty::TypeVisitor<'tcx> for OpaqueTypeLifetimeCollector<'tcx> {
+ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+ self.lifetimes.insert(r);
+ r.super_visit_with(self)
+ }
+ }
+
+ let mut collector = OpaqueTypeLifetimeCollector { lifetimes: Default::default() };
+
+ for pred in tcx.bound_explicit_item_bounds(def_id.to_def_id()).transpose_iter() {
+ let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs);
+
+ trace!(pred=?pred.kind());
+
+ // We only ignore opaque type substs if the opaque type is the outermost type.
+ // The opaque type may be nested within itself via recursion in e.g.
+ // type Foo<'a> = impl PartialEq<Foo<'a>>;
+ // which thus mentions `'a` and should thus accept hidden types that borrow 'a
+ // instead of requiring an additional `+ 'a`.
+ match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(TraitPredicate {
+ trait_ref: ty::TraitRef { def_id: _, substs },
+ constness: _,
+ polarity: _,
+ }) => {
+ trace!(?substs);
+ for subst in &substs[1..] {
+ subst.visit_with(&mut collector);
+ }
+ }
+ ty::PredicateKind::Projection(ty::ProjectionPredicate {
+ projection_ty: ty::ProjectionTy { substs, item_def_id: _ },
+ term,
+ }) => {
+ for subst in &substs[1..] {
+ subst.visit_with(&mut collector);
+ }
+ term.visit_with(&mut collector);
+ }
+ _ => {
+ pred.visit_with(&mut collector);
+ }
+ }
+ }
+ let lifetimes = collector.lifetimes;
+ trace!(?lifetimes);
+ map.filter(|(_, v)| {
+ let ty::GenericArgKind::Lifetime(lt) = v.unpack() else {
+ return true;
+ };
+ lifetimes.contains(&lt)
+ })
+ .collect()
+ }
+ };
+ debug!("map = {:#?}", map);
+
+ // Convert the type from the function into a type valid outside
+ // the function, by replacing invalid regions with 'static,
+ // after producing an error for each of them.
+ self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span, ignore_errors))
+ }
}
/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are
@@ -2590,7 +2705,7 @@ pub fn provide(providers: &mut ty::query::Providers) {
closure::provide(providers);
context::provide(providers);
erase_regions::provide(providers);
- layout::provide(providers);
+ inhabitedness::provide(providers);
util::provide(providers);
print::provide(providers);
super::util::bug::provide(providers);
@@ -2598,7 +2713,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers {
trait_impls_of: trait_def::trait_impls_of_provider,
incoherent_impls: trait_def::incoherent_impls_provider,
- type_uninhabited_from: inhabitedness::type_uninhabited_from,
const_param_default: consts::const_param_default,
vtable_allocation: vtable::vtable_allocation_provider,
..*providers
@@ -2667,8 +2781,9 @@ pub struct DestructuredConst<'tcx> {
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(PredicateS<'_>, 48);
static_assert_size!(TyS<'_>, 40);
static_assert_size!(WithStableHash<TyS<'_>>, 56);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
index 9db5a2894..ee13920d5 100644
--- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
+++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
@@ -10,8 +10,7 @@
use crate::mir;
use crate::traits::query::NoSolution;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder};
-use crate::ty::subst::{Subst, SubstsRef};
-use crate::ty::{self, EarlyBinder, Ty, TyCtxt};
+use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt};
#[derive(Debug, Copy, Clone, HashStable, TyEncodable, TyDecodable)]
pub enum NormalizationError<'tcx> {
@@ -215,15 +214,6 @@ impl<'tcx> TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
}
-
- #[inline]
- fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
- // FIXME: This *probably* needs canonicalization too!
- let arg = self.param_env.and(c);
- self.tcx
- .try_normalize_mir_const_after_erasing_regions(arg)
- .unwrap_or_else(|_| bug!("failed to normalize {:?}", c))
- }
}
struct TryNormalizeAfterErasingRegionsFolder<'tcx> {
@@ -268,16 +258,4 @@ impl<'tcx> FallibleTypeFolder<'tcx> for TryNormalizeAfterErasingRegionsFolder<'t
Err(_) => Err(NormalizationError::Const(c)),
}
}
-
- fn try_fold_mir_const(
- &mut self,
- c: mir::ConstantKind<'tcx>,
- ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
- // FIXME: This *probably* needs canonicalization too!
- let arg = self.param_env.and(c);
- match self.tcx.try_normalize_mir_const_after_erasing_regions(arg) {
- Ok(c) => Ok(c),
- Err(_) => Err(NormalizationError::ConstantKind(c)),
- }
- }
}
diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs
new file mode 100644
index 000000000..b05c63109
--- /dev/null
+++ b/compiler/rustc_middle/src/ty/opaque_types.rs
@@ -0,0 +1,218 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
+use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc_span::Span;
+
+/// Converts generic params of a TypeFoldable from one
+/// item's generics to another. Usually from a function's generics
+/// list to the opaque type's own generics.
+pub(super) struct ReverseMapper<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
+ /// see call sites to fold_kind_no_missing_regions_error
+ /// for an explanation of this field.
+ do_not_error: bool,
+
+ /// We do not want to emit any errors in typeck because
+ /// the spans in typeck are subpar at the moment.
+ /// Borrowck will do the same work again (this time with
+ /// lifetime information) and thus report better errors.
+ ignore_errors: bool,
+
+ /// Span of function being checked.
+ span: Span,
+}
+
+impl<'tcx> ReverseMapper<'tcx> {
+ pub(super) fn new(
+ tcx: TyCtxt<'tcx>,
+ map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
+ span: Span,
+ ignore_errors: bool,
+ ) -> Self {
+ Self { tcx, map, do_not_error: false, ignore_errors, span }
+ }
+
+ fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
+ assert!(!self.do_not_error);
+ self.do_not_error = true;
+ let kind = kind.fold_with(self);
+ self.do_not_error = false;
+ kind
+ }
+
+ fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
+ assert!(!self.do_not_error);
+ kind.fold_with(self)
+ }
+}
+
+impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
+ fn tcx(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ #[instrument(skip(self), level = "debug")]
+ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+ match *r {
+ // Ignore bound regions and `'static` regions that appear in the
+ // type, we only need to remap regions that reference lifetimes
+ // from the function declaration.
+ // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
+ ty::ReLateBound(..) | ty::ReStatic => return r,
+
+ // If regions have been erased (by writeback), don't try to unerase
+ // them.
+ ty::ReErased => return r,
+
+ // The regions that we expect from borrow checking.
+ ty::ReEarlyBound(_) | ty::ReFree(_) => {}
+
+ ty::RePlaceholder(_) | ty::ReVar(_) => {
+ // All of the regions in the type should either have been
+ // erased by writeback, or mapped back to named regions by
+ // borrow checking.
+ bug!("unexpected region kind in opaque type: {:?}", r);
+ }
+ }
+
+ match self.map.get(&r.into()).map(|k| k.unpack()) {
+ Some(GenericArgKind::Lifetime(r1)) => r1,
+ Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
+ None if self.do_not_error => self.tcx.lifetimes.re_static,
+ None => {
+ 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",
+ r
+ ),
+ )
+ .emit();
+
+ self.tcx().lifetimes.re_static
+ }
+ }
+ }
+
+ 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)
+ }
+ }));
+
+ 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)
+ }
+ }));
+
+ self.tcx.mk_generator(def_id, substs, movability)
+ }
+
+ ty::Param(param) => {
+ // Look it up in the substitution list.
+ match self.map.get(&ty.into()).map(|k| k.unpack()) {
+ // Found it in the substitution list; replace with the parameter from the
+ // opaque type.
+ Some(GenericArgKind::Type(t1)) => t1,
+ Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
+ None => {
+ debug!(?param, ?self.map);
+ if !self.ignore_errors {
+ self.tcx
+ .sess
+ .struct_span_err(
+ self.span,
+ &format!(
+ "type parameter `{}` is part of concrete type but not \
+ used in parameter list for the `impl Trait` type alias",
+ ty
+ ),
+ )
+ .emit();
+ }
+
+ self.tcx().ty_error()
+ }
+ }
+ }
+
+ _ => ty.super_fold_with(self),
+ }
+ }
+
+ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+ trace!("checking const {:?}", ct);
+ // Find a const parameter
+ match ct.kind() {
+ ty::ConstKind::Param(..) => {
+ // Look it up in the substitution list.
+ match self.map.get(&ct.into()).map(|k| k.unpack()) {
+ // Found it in the substitution list, replace with the parameter from the
+ // opaque type.
+ Some(GenericArgKind::Const(c1)) => c1,
+ Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
+ None => {
+ if !self.ignore_errors {
+ self.tcx.sess.emit_err(ty::ConstNotUsedTraitAlias {
+ ct: ct.to_string(),
+ span: self.span,
+ });
+ }
+
+ self.tcx().const_error(ct.ty())
+ }
+ }
+ }
+
+ _ => ct,
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs
index 9c8dc30e2..e1e705a92 100644
--- a/compiler/rustc_middle/src/ty/parameterized.rs
+++ b/compiler/rustc_middle/src/ty/parameterized.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, DefIndex};
use rustc_index::vec::{Idx, IndexVec};
@@ -29,6 +30,10 @@ impl<I: Idx + 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for IndexVe
type Value<'tcx> = IndexVec<I, T::Value<'tcx>>;
}
+impl<I: 'static, T: ParameterizedOverTcx> ParameterizedOverTcx for FxHashMap<I, T> {
+ type Value<'tcx> = FxHashMap<I, T::Value<'tcx>>;
+}
+
impl<T: ParameterizedOverTcx> ParameterizedOverTcx for ty::Binder<'static, T> {
type Value<'tcx> = ty::Binder<'tcx, T::Value<'tcx>>;
}
@@ -56,6 +61,7 @@ trivially_parameterized_over_tcx! {
crate::middle::resolve_lifetime::ObjectLifetimeDefault,
crate::mir::ConstQualifs,
ty::AssocItemContainer,
+ ty::DeducedParamAttrs,
ty::Generics,
ty::ImplPolarity,
ty::ReprOptions,
@@ -77,6 +83,7 @@ trivially_parameterized_over_tcx! {
rustc_hir::def::DefKind,
rustc_hir::def_id::DefIndex,
rustc_hir::definitions::DefKey,
+ rustc_index::bit_set::BitSet<u32>,
rustc_index::bit_set::FiniteBitSet<u32>,
rustc_session::cstore::ForeignModule,
rustc_session::cstore::LinkagePreference,
diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs
index d57cf8f01..44b9548db 100644
--- a/compiler/rustc_middle/src/ty/print/mod.rs
+++ b/compiler/rustc_middle/src/ty/print/mod.rs
@@ -1,9 +1,9 @@
-use crate::ty::subst::{GenericArg, Subst};
+use crate::ty::GenericArg;
use crate::ty::{self, DefIdTree, Ty, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
-use rustc_hir::def_id::{CrateNum, DefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
// `pretty` is a separate module only for organization.
@@ -325,3 +325,12 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for ty::Const<'tcx> {
cx.print_const(*self)
}
}
+
+// This is only used by query descriptions
+pub fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
+ if def_id.is_top_level_module() {
+ "top-level module".to_string()
+ } else {
+ format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 97bddb93e..ef9aa236b 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1,9 +1,9 @@
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
-use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
use crate::ty::{
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
};
+use crate::ty::{GenericArg, GenericArgKind};
use rustc_apfloat::ieee::{Double, Single};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sso::SsoHashSet;
@@ -16,6 +16,7 @@ use rustc_session::cstore::{ExternCrate, ExternCrateSource};
use rustc_span::symbol::{kw, Ident, Symbol};
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
+use smallvec::SmallVec;
use std::cell::Cell;
use std::char;
@@ -62,6 +63,7 @@ thread_local! {
static NO_TRIMMED_PATH: Cell<bool> = const { Cell::new(false) };
static NO_QUERIES: Cell<bool> = const { Cell::new(false) };
static NO_VISIBLE_PATH: Cell<bool> = const { Cell::new(false) };
+ static NO_VERBOSE_CONSTANTS: Cell<bool> = const { Cell::new(false) };
}
macro_rules! define_helper {
@@ -116,6 +118,9 @@ define_helper!(
/// Prevent selection of visible paths. `Display` impl of DefId will prefer
/// visible (public) reexports of types as paths.
fn with_no_visible_paths(NoVisibleGuard, NO_VISIBLE_PATH);
+ /// Prevent verbose printing of constants. Verbose printing of constants is
+ /// never desirable in some contexts like `std::any::type_name`.
+ fn with_no_verbose_constants(NoVerboseConstantsGuard, NO_VERBOSE_CONSTANTS);
);
/// The "region highlights" are used to control region printing during
@@ -637,7 +642,9 @@ pub trait PrettyPrinter<'tcx>:
p!(print_def_path(def_id, &[]));
}
ty::Projection(ref data) => {
- if self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder {
+ if !(self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get()))
+ && self.tcx().def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ {
return self.pretty_print_opaque_impl_type(data.item_def_id, data.substs);
} else {
p!(print(data))
@@ -756,7 +763,7 @@ pub trait PrettyPrinter<'tcx>:
}
ty::Array(ty, sz) => {
p!("[", print(ty), "; ");
- if self.tcx().sess.verbose() {
+ if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() {
p!(write("{:?}", sz));
} else if let ty::ConstKind::Unevaluated(..) = sz.kind() {
// Do not try to evaluate unevaluated constants. If we are const evaluating an
@@ -792,9 +799,9 @@ pub trait PrettyPrinter<'tcx>:
let mut traits = FxIndexMap::default();
let mut fn_traits = FxIndexMap::default();
let mut is_sized = false;
+ let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new();
- for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
- let predicate = predicate.subst(tcx, substs);
+ for (predicate, _) in bounds.subst_iter_copied(tcx, substs) {
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
@@ -823,6 +830,9 @@ pub trait PrettyPrinter<'tcx>:
&mut fn_traits,
);
}
+ ty::PredicateKind::TypeOutlives(outlives) => {
+ lifetimes.push(outlives.1);
+ }
_ => {}
}
}
@@ -927,7 +937,7 @@ pub trait PrettyPrinter<'tcx>:
// unless we can find out what generator return type it comes from.
let term = if let Some(ty) = term.skip_binder().ty()
&& let ty::Projection(proj) = ty.kind()
- && let assoc = tcx.associated_item(proj.item_def_id)
+ && let Some(assoc) = tcx.opt_associated_item(proj.item_def_id)
&& assoc.trait_container(tcx) == tcx.lang_items().gen_trait()
&& assoc.name == rustc_span::sym::Return
{
@@ -976,6 +986,11 @@ pub trait PrettyPrinter<'tcx>:
write!(self, "Sized")?;
}
+ for re in lifetimes {
+ write!(self, " + ")?;
+ self = self.print_region(re)?;
+ }
+
Ok(self)
}
@@ -1088,17 +1103,9 @@ pub trait PrettyPrinter<'tcx>:
.generics_of(principal.def_id)
.own_substs_no_defaults(cx.tcx(), principal.substs);
- // Don't print `'_` if there's no unerased regions.
- let print_regions = args.iter().any(|arg| match arg.unpack() {
- GenericArgKind::Lifetime(r) => !r.is_erased(),
- _ => false,
- });
- let mut args = args.iter().cloned().filter(|arg| match arg.unpack() {
- GenericArgKind::Lifetime(_) => print_regions,
- _ => true,
- });
let mut projections = predicates.projection_bounds();
+ let mut args = args.iter().cloned();
let arg0 = args.next();
let projection0 = projections.next();
if arg0.is_some() || projection0.is_some() {
@@ -1178,7 +1185,7 @@ pub trait PrettyPrinter<'tcx>:
) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
- if self.tcx().sess.verbose() {
+ if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() {
p!(write("Const({:?}: {:?})", ct.kind(), ct.ty()));
return Ok(self);
}
@@ -1201,9 +1208,7 @@ pub trait PrettyPrinter<'tcx>:
}
match ct.kind() {
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
- assert_eq!(promoted, ());
-
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
match self.tcx().def_kind(def.did) {
DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => {
p!(print_value_path(def.did, substs))
@@ -1415,7 +1420,7 @@ pub trait PrettyPrinter<'tcx>:
) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);
- if self.tcx().sess.verbose() {
+ if !NO_VERBOSE_CONSTANTS.with(|flag| flag.get()) && self.tcx().sess.verbose() {
p!(write("ValTree({:?}: ", valtree), print(ty), ")");
return Ok(self);
}
@@ -1572,7 +1577,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
in_value: bool,
pub print_alloc_ids: bool,
+ // set of all named (non-anonymous) region names
used_region_names: FxHashSet<Symbol>,
+
region_index: usize,
binder_depth: usize,
printed_type_count: usize,
@@ -1847,22 +1854,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
) -> Result<Self::Path, Self::Error> {
self = print_prefix(self)?;
- // Don't print `'_` if there's no unerased regions.
- let print_regions = self.tcx.sess.verbose()
- || args.iter().any(|arg| match arg.unpack() {
- GenericArgKind::Lifetime(r) => !r.is_erased(),
- _ => false,
- });
- let args = args.iter().cloned().filter(|arg| match arg.unpack() {
- GenericArgKind::Lifetime(_) => print_regions,
- _ => true,
- });
-
- if args.clone().next().is_some() {
+ if args.first().is_some() {
if self.in_value {
write!(self, "::")?;
}
- self.generic_delimiters(|cx| cx.comma_sep(args))
+ self.generic_delimiters(|cx| cx.comma_sep(args.iter().cloned()))
} else {
Ok(self)
}
@@ -2074,7 +2070,14 @@ struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
current_index: ty::DebruijnIndex,
region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
- name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a),
+ name: &'a mut (
+ dyn FnMut(
+ Option<ty::DebruijnIndex>, // Debruijn index of the folded late-bound region
+ ty::DebruijnIndex, // Index corresponding to binder level
+ ty::BoundRegion,
+ ) -> ty::Region<'tcx>
+ + 'a
+ ),
}
impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
@@ -2105,7 +2108,9 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let name = &mut self.name;
let region = match *r {
- ty::ReLateBound(_, br) => *self.region_map.entry(br).or_insert_with(|| name(br)),
+ ty::ReLateBound(db, br) if db >= self.current_index => {
+ *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
+ }
ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
// If this is an anonymous placeholder, don't rename. Otherwise, in some
// async fns, we get a `for<'r> Send` bound
@@ -2114,7 +2119,10 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> {
_ => {
// Index doesn't matter, since this is just for naming and these never get bound
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind };
- *self.region_map.entry(br).or_insert_with(|| name(br))
+ *self
+ .region_map
+ .entry(br)
+ .or_insert_with(|| name(None, self.current_index, br))
}
}
}
@@ -2139,23 +2147,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
where
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{
- fn name_by_region_index(index: usize) -> Symbol {
- match index {
- 0 => Symbol::intern("'r"),
- 1 => Symbol::intern("'s"),
- i => Symbol::intern(&format!("'t{}", i - 2)),
+ fn name_by_region_index(
+ index: usize,
+ available_names: &mut Vec<Symbol>,
+ num_available: usize,
+ ) -> Symbol {
+ if let Some(name) = available_names.pop() {
+ name
+ } else {
+ Symbol::intern(&format!("'z{}", index - num_available))
}
}
+ debug!("name_all_regions");
+
// Replace any anonymous late-bound regions with named
// variants, using new unique identifiers, so that we can
// clearly differentiate between named and unnamed regions in
// the output. We'll probably want to tweak this over time to
// decide just how much information to give.
if self.binder_depth == 0 {
- self.prepare_late_bound_region_info(value);
+ self.prepare_region_info(value);
}
+ debug!("self.used_region_names: {:?}", &self.used_region_names);
+
let mut empty = true;
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
let w = if empty {
@@ -2172,13 +2188,30 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
define_scoped_cx!(self);
+ let possible_names =
+ ('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))).collect::<Vec<_>>();
+
+ let mut available_names = possible_names
+ .into_iter()
+ .filter(|name| !self.used_region_names.contains(&name))
+ .collect::<Vec<_>>();
+ debug!(?available_names);
+ let num_available = available_names.len();
+
let mut region_index = self.region_index;
- let mut next_name = |this: &Self| loop {
- let name = name_by_region_index(region_index);
- region_index += 1;
- if !this.used_region_names.contains(&name) {
- break name;
+ let mut next_name = |this: &Self| {
+ let mut name;
+
+ loop {
+ name = name_by_region_index(region_index, &mut available_names, num_available);
+ region_index += 1;
+
+ if !this.used_region_names.contains(&name) {
+ break;
+ }
}
+
+ name
};
// If we want to print verbosely, then print *all* binders, even if they
@@ -2199,6 +2232,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
ty::BrAnon(_) | ty::BrEnv => {
start_or_continue(&mut self, "for<", ", ");
let name = next_name(&self);
+ debug!(?name);
do_continue(&mut self, name);
ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
}
@@ -2227,24 +2261,63 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
})
} else {
let tcx = self.tcx;
- let mut name = |br: ty::BoundRegion| {
- start_or_continue(&mut self, "for<", ", ");
- let kind = match br.kind {
+
+ // 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
+ // whether a name has already been created for the currently folded region,
+ // see issue #102392.
+ let mut name = |lifetime_idx: Option<ty::DebruijnIndex>,
+ binder_level_idx: ty::DebruijnIndex,
+ br: ty::BoundRegion| {
+ let (name, kind) = match br.kind {
ty::BrAnon(_) | ty::BrEnv => {
let name = next_name(&self);
- do_continue(&mut self, name);
- ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
+
+ 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(
+ ty::INNERMOST,
+ ty::BoundRegion { var: br.var, kind },
+ ));
+ }
+ }
+
+ (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name))
}
ty::BrNamed(def_id, kw::UnderscoreLifetime) => {
let name = next_name(&self);
- do_continue(&mut self, name);
- ty::BrNamed(def_id, name)
+
+ 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(
+ ty::INNERMOST,
+ ty::BoundRegion { var: br.var, kind },
+ ));
+ }
+ }
+
+ (name, ty::BrNamed(def_id, name))
}
ty::BrNamed(_, name) => {
- do_continue(&mut self, name);
- br.kind
+ if let Some(lt_idx) = lifetime_idx {
+ if lt_idx > binder_level_idx {
+ let kind = br.kind;
+ return tcx.mk_region(ty::ReLateBound(
+ ty::INNERMOST,
+ ty::BoundRegion { var: br.var, kind },
+ ));
+ }
+ }
+
+ (name, br.kind)
}
};
+
+ start_or_continue(&mut self, "for<", ", ");
+ do_continue(&mut self, name);
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
};
let mut folder = RegionFolder {
@@ -2292,29 +2365,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
Ok(inner)
}
- fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
+ fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
T: TypeVisitable<'tcx>,
{
- struct LateBoundRegionNameCollector<'a, 'tcx> {
- used_region_names: &'a mut FxHashSet<Symbol>,
+ struct RegionNameCollector<'tcx> {
+ used_region_names: FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>,
}
- impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
+ impl<'tcx> RegionNameCollector<'tcx> {
+ fn new() -> Self {
+ RegionNameCollector {
+ used_region_names: Default::default(),
+ type_collector: SsoHashSet::new(),
+ }
+ }
+ }
+
+ impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> {
type BreakTy = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
trace!("address: {:p}", r.0.0);
- if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
- self.used_region_names.insert(name);
- } else if let ty::RePlaceholder(ty::PlaceholderRegion {
- name: ty::BrNamed(_, name),
- ..
- }) = *r
- {
+
+ // Collect all named lifetimes. These allow us to prevent duplication
+ // of already existing lifetime names when introducing names for
+ // anonymous late-bound regions.
+ if let Some(name) = r.get_name() {
self.used_region_names.insert(name);
}
+
r.super_visit_with(self)
}
@@ -2330,12 +2411,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
}
- self.used_region_names.clear();
- let mut collector = LateBoundRegionNameCollector {
- used_region_names: &mut self.used_region_names,
- type_collector: SsoHashSet::new(),
- };
+ let mut collector = RegionNameCollector::new();
value.visit_with(&mut collector);
+ self.used_region_names = collector.used_region_names;
self.region_index = 0;
}
}
@@ -2637,8 +2715,8 @@ define_print_and_forward_display! {
print_value_path(closure_def_id, &[]),
write("` implements the trait `{}`", kind))
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
- p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
+ ty::PredicateKind::ConstEvaluatable(ct) => {
+ p!("the constant `", print(ct), "` can be evaluated")
}
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
@@ -2662,7 +2740,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
// Iterate all local crate items no matter where they are defined.
let hir = tcx.hir();
for id in hir.items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Use) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Use) {
continue;
}
@@ -2671,7 +2749,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
continue;
}
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
let ns = tcx.def_kind(def_id).ns().unwrap_or(Namespace::TypeNS);
collect_fn(&item.ident, ns, def_id);
}
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index a300a8df2..ec90590ad 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -1,11 +1,11 @@
use crate::dep_graph;
use crate::infer::canonical::{self, Canonical};
-use crate::lint::LintLevelMap;
+use crate::lint::LintExpectation;
use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use crate::middle::lib_features::LibFeatures;
-use crate::middle::privacy::AccessLevels;
+use crate::middle::privacy::EffectiveVisibilities;
use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLifetimes};
use crate::middle::stability::{self, DeprecationEntry};
use crate::mir;
@@ -32,7 +32,7 @@ use crate::ty::layout::TyAndLayout;
use crate::ty::subst::{GenericArg, SubstsRef};
use crate::ty::util::AlwaysRequiresDrop;
use crate::ty::GeneratorDiagnosticData;
-use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
+use crate::ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
use rustc_ast as ast;
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_attr as attr;
@@ -40,17 +40,19 @@ 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::unord::UnordSet;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
+use rustc_hir::hir_id::OwnerId;
use rustc_hir::lang_items::{LangItem, LanguageItems};
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
use rustc_session::cstore::{CrateDepKind, CrateSource};
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
-use rustc_session::utils::NativeLibKind;
+use rustc_session::lint::LintExpectationId;
use rustc_session::Limits;
use rustc_span::symbol::Symbol;
use rustc_span::{Span, DUMMY_SP};
@@ -275,8 +277,9 @@ macro_rules! define_callbacks {
fn default() -> Self {
Providers {
$($name: |_, key| bug!(
- "`tcx.{}({:?})` unsupported by its crate; \
- perhaps the `{}` query was never assigned a provider function",
+ "`tcx.{}({:?})` is not supported for external or local 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 (likely the local crate).\n
+ If that's not the case, {} was likely never assigned to a provider function.\n",
stringify!($name),
key,
stringify!($name),
@@ -335,7 +338,7 @@ macro_rules! define_callbacks {
rustc_query_append! { define_callbacks! }
mod sealed {
- use super::{DefId, LocalDefId};
+ use super::{DefId, LocalDefId, OwnerId};
/// An analogue of the `Into` trait that's intended only for query parameters.
///
@@ -365,6 +368,13 @@ mod sealed {
self.to_def_id()
}
}
+
+ impl IntoQueryParam<DefId> for OwnerId {
+ #[inline(always)]
+ fn into_query_param(self) -> DefId {
+ self.to_def_id()
+ }
+ }
}
use sealed::IntoQueryParam;
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 61c34730d..b25b4bd4f 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -5,8 +5,8 @@
//! subtyping, type equality, etc.
use crate::ty::error::{ExpectedFound, TypeError};
-use crate::ty::subst::{GenericArg, GenericArgKind, Subst, SubstsRef};
use crate::ty::{self, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
+use crate::ty::{GenericArg, GenericArgKind, SubstsRef};
use rustc_hir as ast;
use rustc_hir::def_id::DefId;
use rustc_span::DUMMY_SP;
@@ -632,11 +632,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
// While this is slightly incorrect, it shouldn't matter for `min_const_generics`
// and is the better alternative to waiting until `generic_const_exprs` can
// be stabilized.
- (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu))
- if au.def == bu.def && au.promoted == bu.promoted =>
- {
- assert_eq!(au.promoted, ());
-
+ (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => {
let substs = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
@@ -644,11 +640,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>(
bu.substs,
)?;
return Ok(tcx.mk_const(ty::ConstS {
- kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
- def: au.def,
- substs,
- promoted: (),
- }),
+ kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def: au.def, substs }),
ty: a.ty(),
}));
}
diff --git a/compiler/rustc_middle/src/ty/rvalue_scopes.rs b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
index e86dafae3..e79b79a25 100644
--- a/compiler/rustc_middle/src/ty/rvalue_scopes.rs
+++ b/compiler/rustc_middle/src/ty/rvalue_scopes.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
/// `RvalueScopes` is a mapping from sub-expressions to _extended_ lifetime as determined by
-/// rules laid out in `rustc_typeck::check::rvalue_scopes`.
+/// rules laid out in `rustc_hir_analysis::check::rvalue_scopes`.
#[derive(TyEncodable, TyDecodable, Clone, Debug, Default, Eq, PartialEq, HashStable)]
pub struct RvalueScopes {
map: FxHashMap<hir::ItemLocalId, Option<Scope>>,
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 84d6a8b97..2cad333e3 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -166,8 +166,8 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
ty::PredicateKind::ClosureKind(closure_def_id, closure_substs, kind) => {
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
- write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
+ ty::PredicateKind::ConstEvaluatable(ct) => {
+ write!(f, "ConstEvaluatable({ct:?})")
}
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
@@ -560,18 +560,6 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> {
}
}
-impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::EarlyBinder<T> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- self.try_map_bound(|ty| ty.try_fold_with(folder))
- }
-}
-
-impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::EarlyBinder<T> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.as_ref().0.visit_with(visitor)
- }
-}
-
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)
@@ -844,45 +832,8 @@ impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- folder.try_fold_unevaluated(self)
- }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- visitor.visit_unevaluated(*self)
- }
-}
-
-impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> {
- fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
- self,
- folder: &mut F,
- ) -> Result<Self, F::Error> {
- Ok(ty::Unevaluated {
- def: self.def,
- substs: self.substs.try_fold_with(folder)?,
- promoted: self.promoted,
- })
- }
-}
-
-impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> {
+impl<'tcx> TypeSuperVisitable<'tcx> for ty::UnevaluatedConst<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
}
}
-
-impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
- fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
- Ok(self.expand().try_fold_with(folder)?.shrink())
- }
-}
-
-impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> {
- fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
- self.expand().visit_with(visitor)
- }
-}
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 36e560850..cf420bafe 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -3,7 +3,7 @@
#![allow(rustc::usage_of_ty_tykind)]
use crate::infer::canonical::Canonical;
-use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
+use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
@@ -19,7 +19,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_index::vec::Idx;
use rustc_macros::HashStable;
-use rustc_span::symbol::{kw, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi;
use std::borrow::Cow;
@@ -85,6 +85,17 @@ impl BoundRegionKind {
_ => false,
}
}
+
+ pub fn get_name(&self) -> Option<Symbol> {
+ if self.is_named() {
+ match *self {
+ BoundRegionKind::BrNamed(_, name) => return Some(name),
+ _ => unreachable!(),
+ }
+ }
+
+ None
+ }
}
pub trait Article {
@@ -304,7 +315,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
/// closure.
// FIXME(eddyb) this should be unnecessary, as the shallowly resolved
// type is known at the time of the creation of `ClosureSubsts`,
- // see `rustc_typeck::check::closure`.
+ // see `rustc_hir_analysis::check::closure`.
pub fn sig_as_fn_ptr_ty(self) -> Ty<'tcx> {
self.split().closure_sig_as_fn_ptr_ty.expect_ty()
}
@@ -551,7 +562,7 @@ impl<'tcx> GeneratorSubsts<'tcx> {
layout.variant_fields.iter().map(move |variant| {
variant
.iter()
- .map(move |field| EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
+ .map(move |field| ty::EarlyBinder(layout.field_tys[*field]).subst(tcx, self.substs))
})
}
@@ -915,73 +926,6 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(Encodable, Decodable, HashStable)]
-pub struct EarlyBinder<T>(pub T);
-
-impl<T> EarlyBinder<T> {
- pub fn as_ref(&self) -> EarlyBinder<&T> {
- EarlyBinder(&self.0)
- }
-
- pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
- where
- F: FnOnce(&T) -> U,
- {
- self.as_ref().map_bound(f)
- }
-
- pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
- where
- F: FnOnce(T) -> U,
- {
- let value = f(self.0);
- EarlyBinder(value)
- }
-
- pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
- where
- F: FnOnce(T) -> Result<U, E>,
- {
- let value = f(self.0)?;
- Ok(EarlyBinder(value))
- }
-
- pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
- EarlyBinder(value)
- }
-}
-
-impl<T> EarlyBinder<Option<T>> {
- pub fn transpose(self) -> Option<EarlyBinder<T>> {
- self.0.map(|v| EarlyBinder(v))
- }
-}
-
-impl<T, U> EarlyBinder<(T, U)> {
- pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
- (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
- }
-}
-
-pub struct EarlyBinderIter<T> {
- t: T,
-}
-
-impl<T: IntoIterator> EarlyBinder<T> {
- pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
- EarlyBinderIter { t: self.0.into_iter() }
- }
-}
-
-impl<T: Iterator> Iterator for EarlyBinderIter<T> {
- type Item = EarlyBinder<T::Item>;
-
- fn next(&mut self) -> Option<Self::Item> {
- self.t.next().map(|i| EarlyBinder(i))
- }
-}
-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable)]
pub enum BoundVariableKind {
@@ -1200,9 +1144,13 @@ pub struct ProjectionTy<'tcx> {
impl<'tcx> ProjectionTy<'tcx> {
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
- let parent = tcx.parent(self.item_def_id);
- assert_eq!(tcx.def_kind(parent), DefKind::Trait);
- parent
+ match tcx.def_kind(self.item_def_id) {
+ DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.item_def_id),
+ DefKind::ImplTraitPlaceholder => {
+ tcx.parent(tcx.impl_trait_in_trait_parent(self.item_def_id))
+ }
+ kind => bug!("unexpected DefKind in ProjectionTy: {kind:?}"),
+ }
}
/// Extracts the underlying trait reference and own substs from this projection.
@@ -1213,6 +1161,7 @@ impl<'tcx> ProjectionTy<'tcx> {
tcx: TyCtxt<'tcx>,
) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
let def_id = tcx.parent(self.item_def_id);
+ assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
let trait_generics = tcx.generics_of(def_id);
(
ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
@@ -1508,6 +1457,23 @@ impl<'tcx> Region<'tcx> {
*self.0.0
}
+ pub fn get_name(self) -> Option<Symbol> {
+ if self.has_name() {
+ let name = match *self {
+ ty::ReEarlyBound(ebr) => Some(ebr.name),
+ ty::ReLateBound(_, br) => br.kind.get_name(),
+ ty::ReFree(fr) => fr.bound_region.get_name(),
+ ty::ReStatic => Some(kw::StaticLifetime),
+ ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
+ _ => None,
+ };
+
+ return name;
+ }
+
+ None
+ }
+
/// Is this region named by the user?
pub fn has_name(self) -> bool {
match *self {
@@ -2156,7 +2122,7 @@ impl<'tcx> Ty<'tcx> {
///
/// Note that during type checking, we use an inference variable
/// to represent the closure kind, because it has not yet been
- /// inferred. Once upvar inference (in `rustc_typeck/src/check/upvar.rs`)
+ /// inferred. Once upvar inference (in `rustc_hir_analysis/src/check/upvar.rs`)
/// is complete, that type variable will be unified.
pub fn to_opt_closure_kind(self) -> Option<ty::ClosureKind> {
match self.kind() {
@@ -2239,7 +2205,10 @@ impl<'tcx> Ty<'tcx> {
// These aren't even `Clone`
ty::Str | ty::Slice(..) | ty::Foreign(..) | ty::Dynamic(..) => false,
- ty::Int(..) | ty::Uint(..) | ty::Float(..) => true,
+ ty::Infer(ty::InferTy::FloatVar(_) | ty::InferTy::IntVar(_))
+ | ty::Int(..)
+ | ty::Uint(..)
+ | ty::Float(..) => true,
// The voldemort ZSTs are fine.
ty::FnDef(..) => true,
@@ -2274,6 +2243,35 @@ impl<'tcx> Ty<'tcx> {
}
}
}
+
+ // If `self` is a primitive, return its [`Symbol`].
+ pub fn primitive_symbol(self) -> Option<Symbol> {
+ match self.kind() {
+ ty::Bool => Some(sym::bool),
+ ty::Char => Some(sym::char),
+ ty::Float(f) => match f {
+ ty::FloatTy::F32 => Some(sym::f32),
+ ty::FloatTy::F64 => Some(sym::f64),
+ },
+ ty::Int(f) => match f {
+ ty::IntTy::Isize => Some(sym::isize),
+ ty::IntTy::I8 => Some(sym::i8),
+ ty::IntTy::I16 => Some(sym::i16),
+ ty::IntTy::I32 => Some(sym::i32),
+ ty::IntTy::I64 => Some(sym::i64),
+ ty::IntTy::I128 => Some(sym::i128),
+ },
+ ty::Uint(f) => match f {
+ ty::UintTy::Usize => Some(sym::usize),
+ ty::UintTy::U8 => Some(sym::u8),
+ ty::UintTy::U16 => Some(sym::u16),
+ ty::UintTy::U32 => Some(sym::u32),
+ ty::UintTy::U64 => Some(sym::u64),
+ ty::UintTy::U128 => Some(sym::u128),
+ },
+ _ => None,
+ }
+ }
}
/// Extra information about why we ended up with a particular variance.
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 8e69bf067..0660e9b79 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -1,12 +1,12 @@
// Type substitutions.
-use crate::mir;
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::{self, Lift, List, ParamConst, Ty, TyCtxt};
+use rustc_data_structures::captures::Captures;
use rustc_data_structures::intern::{Interned, WithStableHash};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
@@ -189,6 +189,14 @@ impl<'tcx> GenericArg<'tcx> {
_ => bug!("expected a const, but found another kind"),
}
}
+
+ pub fn is_non_region_infer(self) -> bool {
+ match self.unpack() {
+ GenericArgKind::Lifetime(_) => false,
+ GenericArgKind::Type(ty) => ty.is_ty_infer(),
+ GenericArgKind::Const(ct) => ct.is_ct_infer(),
+ }
+ }
}
impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> {
@@ -492,23 +500,107 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> {
+ #[inline]
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
-// Just call `foo.subst(tcx, substs)` to perform a substitution across `foo`.
-#[rustc_on_unimplemented(message = "Calling `subst` must now be done through an `EarlyBinder`")]
-pub trait Subst<'tcx>: Sized {
- type Inner;
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Encodable, Decodable, HashStable)]
+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<T> EarlyBinder<T> {
+ pub fn as_ref(&self) -> EarlyBinder<&T> {
+ EarlyBinder(&self.0)
+ }
- fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner;
+ pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U>
+ where
+ F: FnOnce(&T) -> U,
+ {
+ self.as_ref().map_bound(f)
+ }
+
+ pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U>
+ where
+ F: FnOnce(T) -> U,
+ {
+ let value = f(self.0);
+ EarlyBinder(value)
+ }
+
+ pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E>
+ where
+ F: FnOnce(T) -> Result<U, E>,
+ {
+ let value = f(self.0)?;
+ Ok(EarlyBinder(value))
+ }
+
+ pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
+ EarlyBinder(value)
+ }
}
-impl<'tcx, T: TypeFoldable<'tcx>> Subst<'tcx> for ty::EarlyBinder<T> {
- type Inner = T;
+impl<T> EarlyBinder<Option<T>> {
+ pub fn transpose(self) -> Option<EarlyBinder<T>> {
+ self.0.map(|v| EarlyBinder(v))
+ }
+}
+
+impl<T, U> EarlyBinder<(T, U)> {
+ pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) {
+ (EarlyBinder(self.0.0), EarlyBinder(self.0.1))
+ }
+}
- fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> Self::Inner {
+impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> {
+ pub fn subst_iter(
+ self,
+ tcx: TyCtxt<'tcx>,
+ substs: &'s [GenericArg<'tcx>],
+ ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> {
+ self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs))
+ }
+}
+
+impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a>
+ EarlyBinder<T>
+{
+ pub fn subst_iter_copied(
+ self,
+ tcx: TyCtxt<'tcx>,
+ substs: &'s [GenericArg<'tcx>],
+ ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> {
+ self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs))
+ }
+}
+
+pub struct EarlyBinderIter<T> {
+ t: T,
+}
+
+impl<T: IntoIterator> EarlyBinder<T> {
+ pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> {
+ EarlyBinderIter { t: self.0.into_iter() }
+ }
+}
+
+impl<T: Iterator> Iterator for EarlyBinderIter<T> {
+ type Item = EarlyBinder<T::Item>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.t.next().map(|i| EarlyBinder(i))
+ }
+}
+
+impl<'tcx, T: TypeFoldable<'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)
}
@@ -544,9 +636,21 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
#[cold]
#[inline(never)]
- fn region_param_out_of_range(data: ty::EarlyBoundRegion) -> ! {
+ fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! {
bug!(
- "Region parameter out of range when substituting in region {} (index={})",
+ "Region parameter out of range when substituting in region {} (index={}, substs = {:?})",
+ data.name,
+ data.index,
+ substs,
+ )
+ }
+
+ #[cold]
+ #[inline(never)]
+ fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! {
+ bug!(
+ "Unexpected parameter {:?} when substituting in region {} (index={})",
+ other,
data.name,
data.index
)
@@ -562,7 +666,8 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
let rk = self.substs.get(data.index as usize).map(|k| k.unpack());
match rk {
Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt),
- _ => region_param_out_of_range(data),
+ Some(other) => region_param_invalid(data, other),
+ None => region_param_out_of_range(data, self.substs),
}
}
_ => r,
@@ -587,11 +692,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
c.super_fold_with(self)
}
}
-
- #[inline]
- fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
- c.super_fold_with(self)
- }
}
impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 23ad4d27d..f72e236ed 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -2,12 +2,11 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::layout::IntegerExt;
-use crate::ty::query::TyCtxtAt;
-use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable,
};
+use crate::ty::{GenericArgKind, SubstsRef};
use rustc_apfloat::Float as _;
use rustc_ast as ast;
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
@@ -821,12 +820,8 @@ impl<'tcx> Ty<'tcx> {
/// does copies even when the type actually doesn't satisfy the
/// full requirements for the `Copy` trait (cc #29149) -- this
/// winds up being reported as an error during NLL borrow check.
- pub fn is_copy_modulo_regions(
- self,
- tcx_at: TyCtxtAt<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- ) -> bool {
- self.is_trivially_pure_clone_copy() || tcx_at.is_copy_raw(param_env.and(self))
+ pub fn is_copy_modulo_regions(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ self.is_trivially_pure_clone_copy() || tcx.is_copy_raw(param_env.and(self))
}
/// Checks whether values of this type `T` have a size known at
@@ -835,8 +830,8 @@ impl<'tcx> Ty<'tcx> {
/// over-approximation in generic contexts, where one can have
/// strange rules like `<T as Foo<'static>>::Bar: Sized` that
/// actually carry lifetime requirements.
- pub fn is_sized(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
- self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self))
+ pub fn is_sized(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ self.is_trivially_sized(tcx) || tcx.is_sized_raw(param_env.and(self))
}
/// Checks whether values of this type `T` implement the `Freeze`
@@ -846,8 +841,8 @@ impl<'tcx> Ty<'tcx> {
/// optimization as well as the rules around static values. Note
/// that the `Freeze` trait is not exposed to end users and is
/// effectively an implementation detail.
- pub fn is_freeze(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
- self.is_trivially_freeze() || tcx_at.is_freeze_raw(param_env.and(self))
+ pub fn is_freeze(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ self.is_trivially_freeze() || tcx.is_freeze_raw(param_env.and(self))
}
/// Fast path helper for testing if a type is `Freeze`.
@@ -886,8 +881,8 @@ impl<'tcx> Ty<'tcx> {
}
/// Checks whether values of this type `T` implement the `Unpin` trait.
- pub fn is_unpin(self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
- self.is_trivially_unpin() || tcx_at.is_unpin_raw(param_env.and(self))
+ pub fn is_unpin(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
+ self.is_trivially_unpin() || tcx.is_unpin_raw(param_env.and(self))
}
/// Fast path helper for testing if a type is `Unpin`.
@@ -958,7 +953,7 @@ impl<'tcx> Ty<'tcx> {
}
}
- /// Checks if `ty` has has a significant drop.
+ /// Checks if `ty` has a significant drop.
///
/// Note that this method can return false even if `ty` has a destructor
/// attached; even if that is the case then the adt has been marked with
@@ -1289,12 +1284,24 @@ pub fn is_doc_hidden(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
.any(|items| items.iter().any(|item| item.has_name(sym::hidden)))
}
+/// Determines whether an item is annotated with `doc(notable_trait)`.
+pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
+ tcx.get_attrs(def_id, sym::doc)
+ .filter_map(|attr| attr.meta_item_list())
+ .any(|items| items.iter().any(|item| item.has_name(sym::notable_trait)))
+}
+
/// 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)
}
pub fn provide(providers: &mut ty::query::Providers) {
- *providers =
- ty::query::Providers { normalize_opaque_types, is_doc_hidden, is_intrinsic, ..*providers }
+ *providers = ty::query::Providers {
+ normalize_opaque_types,
+ is_doc_hidden,
+ is_doc_notable_trait,
+ is_intrinsic,
+ ..*providers
+ }
}
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 5f8cb5782..c09f71f9a 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -10,8 +10,7 @@
//!
//! 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 the methods delegate to the
-//! visitor.
+//! - 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,
@@ -39,7 +38,6 @@
//! - ty.super_visit_with(visitor)
//! - u.visit_with(visitor)
//! ```
-use crate::mir;
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
@@ -104,8 +102,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
None
}
}
- fn has_param_types_or_consts(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
+ fn has_non_region_param(&self) -> bool {
+ self.has_type_flags(TypeFlags::NEEDS_SUBST - TypeFlags::HAS_RE_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
@@ -113,8 +111,8 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
- fn has_infer_types_or_consts(&self) -> bool {
- self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
+ fn has_non_region_infer(&self) -> bool {
+ self.has_type_flags(TypeFlags::NEEDS_INFER - TypeFlags::HAS_RE_INFER)
}
fn needs_infer(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_INFER)
@@ -199,17 +197,9 @@ pub trait TypeVisitor<'tcx>: Sized {
c.super_visit_with(self)
}
- fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
- uv.super_visit_with(self)
- }
-
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
p.super_visit_with(self)
}
-
- fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
- c.super_visit_with(self)
- }
}
///////////////////////////////////////////////////////////////////////////
@@ -597,18 +587,6 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
#[inline]
#[instrument(level = "trace", ret)]
- fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
- let flags = FlagComputation::for_unevaluated_const(uv);
- trace!(r.flags=?flags);
- if flags.intersects(self.flags) {
- ControlFlow::Break(FoundFlags)
- } else {
- ControlFlow::CONTINUE
- }
- }
-
- #[inline]
- #[instrument(level = "trace", ret)]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!(
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index a3e11bbf0..91db9698c 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -112,6 +112,22 @@ impl<'tcx> Ty<'tcx> {
}
}
+impl<'tcx> ty::Const<'tcx> {
+ /// Iterator that walks `self` and any types reachable from
+ /// `self`, in depth-first order. Note that just walks the types
+ /// that appear in `self`, it does not descend into the fields of
+ /// structs or variants. For example:
+ ///
+ /// ```text
+ /// isize => { isize }
+ /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
+ /// [isize] => { [isize], isize }
+ /// ```
+ pub fn walk(self) -> TypeWalker<'tcx> {
+ TypeWalker::new(self.into())
+ }
+}
+
/// We push `GenericArg`s on the stack in reverse order so as to
/// maintain a pre-order traversal. As of the time of this
/// writing, the fact that the traversal is pre-order is not
diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs
index 7fbe9ae2a..f4b4c3fb0 100644
--- a/compiler/rustc_middle/src/values.rs
+++ b/compiler/rustc_middle/src/values.rs
@@ -1,8 +1,18 @@
-use rustc_middle::ty::{self, AdtSizedConstraint, Ty, TyCtxt};
+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_middle::ty::Representability;
+use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt};
+use rustc_query_system::query::QueryInfo;
use rustc_query_system::Value;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::Span;
+
+use std::fmt::Write;
impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> 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()) }
@@ -10,7 +20,7 @@ impl<'tcx> Value<TyCtxt<'tcx>> for Ty<'_> {
}
impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
// SAFETY: This is never called when `Self` is not `SymbolName<'tcx>`.
// FIXME: Represent the above fact in the trait system somehow.
unsafe {
@@ -21,20 +31,8 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::SymbolName<'_> {
}
}
-impl<'tcx> Value<TyCtxt<'tcx>> for AdtSizedConstraint<'_> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
- // SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`.
- // FIXME: Represent the above fact in the trait system somehow.
- unsafe {
- std::mem::transmute::<AdtSizedConstraint<'tcx>, AdtSizedConstraint<'_>>(
- AdtSizedConstraint(tcx.intern_type_list(&[tcx.ty_error()])),
- )
- }
- }
-}
-
impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
- fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, _: &[QueryInfo]) -> Self {
let err = tcx.ty_error();
// FIXME(compiler-errors): It would be nice if we could get the
// query key, so we could at least generate a fn signature that
@@ -52,3 +50,153 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::Binder<'_, ty::FnSig<'_>> {
unsafe { std::mem::transmute::<ty::PolyFnSig<'tcx>, ty::Binder<'_, ty::FnSig<'_>>>(fn_sig) }
}
}
+
+impl<'tcx> Value<TyCtxt<'tcx>> for Representability {
+ fn from_cycle_error(tcx: TyCtxt<'tcx>, cycle: &[QueryInfo]) -> Self {
+ let mut item_and_field_ids = Vec::new();
+ let mut representable_ids = FxHashSet::default();
+ for info in cycle {
+ if info.query.name == "representability"
+ && let Some(field_id) = info.query.def_id
+ && let Some(field_id) = field_id.as_local()
+ && let Some(DefKind::Field) = info.query.def_kind
+ {
+ let parent_id = tcx.parent(field_id.to_def_id());
+ let item_id = match tcx.def_kind(parent_id) {
+ DefKind::Variant => tcx.parent(parent_id),
+ _ => parent_id,
+ };
+ item_and_field_ids.push((item_id.expect_local(), field_id));
+ }
+ }
+ for info in cycle {
+ if info.query.name == "representability_adt_ty"
+ && let Some(def_id) = info.query.ty_adt_id
+ && let Some(def_id) = def_id.as_local()
+ && !item_and_field_ids.iter().any(|&(id, _)| id == def_id)
+ {
+ representable_ids.insert(def_id);
+ }
+ }
+ recursive_type_error(tcx, item_and_field_ids, &representable_ids);
+ Representability::Infinite
+ }
+}
+
+// item_and_field_ids should form a cycle where each field contains the
+// type in the next element in the list
+pub fn recursive_type_error(
+ tcx: TyCtxt<'_>,
+ mut item_and_field_ids: Vec<(LocalDefId, LocalDefId)>,
+ representable_ids: &FxHashSet<LocalDefId>,
+) {
+ const ITEM_LIMIT: usize = 5;
+
+ // Rotate the cycle so that the item with the lowest span is first
+ let start_index = item_and_field_ids
+ .iter()
+ .enumerate()
+ .min_by_key(|&(_, &(id, _))| tcx.def_span(id))
+ .unwrap()
+ .0;
+ item_and_field_ids.rotate_left(start_index);
+
+ let cycle_len = item_and_field_ids.len();
+ let show_cycle_len = cycle_len.min(ITEM_LIMIT);
+
+ let mut err_span = MultiSpan::from_spans(
+ item_and_field_ids[..show_cycle_len]
+ .iter()
+ .map(|(id, _)| tcx.def_span(id.to_def_id()))
+ .collect(),
+ );
+ let mut suggestion = Vec::with_capacity(show_cycle_len * 2);
+ for i in 0..show_cycle_len {
+ let (_, field_id) = item_and_field_ids[i];
+ let (next_item_id, _) = item_and_field_ids[(i + 1) % cycle_len];
+ // Find the span(s) that contain the next item in the cycle
+ let hir_id = tcx.hir().local_def_id_to_hir_id(field_id);
+ let hir::Node::Field(field) = tcx.hir().get(hir_id) else { bug!("expected field") };
+ let mut found = Vec::new();
+ find_item_ty_spans(tcx, field.ty, next_item_id, &mut found, representable_ids);
+
+ // Couldn't find the type. Maybe it's behind a type alias?
+ // In any case, we'll just suggest boxing the whole field.
+ if found.is_empty() {
+ found.push(field.ty.span);
+ }
+
+ for span in found {
+ err_span.push_span_label(span, "recursive without indirection");
+ // FIXME(compiler-errors): This suggestion might be erroneous if Box is shadowed
+ suggestion.push((span.shrink_to_lo(), "Box<".to_string()));
+ suggestion.push((span.shrink_to_hi(), ">".to_string()));
+ }
+ }
+ let items_list = {
+ let mut s = String::new();
+ for (i, (item_id, _)) in item_and_field_ids.iter().enumerate() {
+ let path = tcx.def_path_str(item_id.to_def_id());
+ write!(&mut s, "`{path}`").unwrap();
+ if i == (ITEM_LIMIT - 1) && cycle_len > ITEM_LIMIT {
+ write!(&mut s, " and {} more", cycle_len - 5).unwrap();
+ break;
+ }
+ if cycle_len > 1 && i < cycle_len - 2 {
+ s.push_str(", ");
+ } else if cycle_len > 1 && i == cycle_len - 2 {
+ s.push_str(" and ")
+ }
+ }
+ s
+ };
+ let mut err = struct_span_err!(
+ tcx.sess,
+ err_span,
+ E0072,
+ "recursive type{} {} {} infinite size",
+ pluralize!(cycle_len),
+ items_list,
+ pluralize!("has", cycle_len),
+ );
+ err.multipart_suggestion(
+ "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle",
+ suggestion,
+ Applicability::HasPlaceholders,
+ );
+ err.emit();
+}
+
+fn find_item_ty_spans(
+ tcx: TyCtxt<'_>,
+ ty: &hir::Ty<'_>,
+ needle: LocalDefId,
+ spans: &mut Vec<Span>,
+ seen_representable: &FxHashSet<LocalDefId>,
+) {
+ match ty.kind {
+ hir::TyKind::Path(hir::QPath::Resolved(_, path)) => {
+ if let Some(def_id) = path.res.opt_def_id() {
+ let check_params = def_id.as_local().map_or(true, |def_id| {
+ if def_id == needle {
+ spans.push(ty.span);
+ }
+ seen_representable.contains(&def_id)
+ });
+ if check_params && let Some(args) = path.segments.last().unwrap().args {
+ let params_in_repr = tcx.params_in_repr(def_id);
+ for (i, arg) in args.args.iter().enumerate() {
+ if let hir::GenericArg::Type(ty) = arg && params_in_repr.contains(i as u32) {
+ find_item_ty_spans(tcx, ty, needle, spans, seen_representable);
+ }
+ }
+ }
+ }
+ }
+ hir::TyKind::Array(ty, _) => find_item_ty_spans(tcx, ty, needle, spans, seen_representable),
+ hir::TyKind::Tup(tys) => {
+ tys.iter().for_each(|ty| find_item_ty_spans(tcx, ty, needle, spans, seen_representable))
+ }
+ _ => {}
+ }
+}
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index 30f90e383..c726fa3a3 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_arena = { path = "../rustc_arena" }
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 784583d94..183db56d7 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -221,26 +221,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let init = &this.thir[*initializer];
let initializer_span = init.span;
- this.declare_bindings(
- visibility_scope,
- remainder_span,
- pattern,
- ArmHasGuard(false),
- Some((None, initializer_span)),
- );
- this.visit_primary_bindings(
- pattern,
- UserTypeProjections::none(),
- &mut |this, _, _, _, node, span, _, _| {
- this.storage_live_binding(block, node, span, OutsideGuard, true);
- },
- );
let failure = unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let scope = (*init_scope, source_info);
this.in_scope(scope, *lint_level, |this| {
+ this.declare_bindings(
+ visibility_scope,
+ remainder_span,
+ pattern,
+ ArmHasGuard(false),
+ Some((None, initializer_span)),
+ );
+ this.visit_primary_bindings(
+ pattern,
+ UserTypeProjections::none(),
+ &mut |this, _, _, _, node, span, _, _| {
+ this.storage_live_binding(
+ block,
+ node,
+ span,
+ OutsideGuard,
+ true,
+ );
+ },
+ );
this.ast_let_else(
block,
init,
@@ -305,7 +311,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ArmHasGuard(false),
Some((None, initializer_span)),
);
- this.expr_into_pattern(block, &pattern, init) // irrefutable pattern
+ this.expr_into_pattern(block, &pattern, init)
+ // irrefutable pattern
})
},
)
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 c9bec130c..37dc1ad9f 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -2,6 +2,7 @@
use crate::build::{parse_float_into_constval, Builder};
use rustc_ast as ast;
+use rustc_middle::mir;
use rustc_middle::mir::interpret::{
Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar,
};
@@ -66,7 +67,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
})
});
- let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval =
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty, span, literal }
@@ -79,7 +81,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { user_ty: None, span, literal }
}
ExprKind::ConstBlock { did: def_id, substs } => {
- let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval =
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let literal = ConstantKind::Unevaluated(uneval, ty);
Constant { user_ty: None, span, literal }
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 e707c373f..c8610af70 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs
@@ -153,12 +153,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if tcx.features().unsized_fn_params {
let ty = expr.ty;
- let span = expr.span;
let param_env = this.param_env;
- if !ty.is_sized(tcx.at(span), param_env) {
+ if !ty.is_sized(tcx, param_env) {
// !sized means !copy, so this is an unsized move
- assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env));
+ assert!(!ty.is_copy_modulo_regions(tcx, param_env));
// As described above, detect the case where we are passing a value of unsized
// type, and that value is coming from the deref of a box.
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 ebb56e5a2..396782d45 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_place.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs
@@ -17,6 +17,7 @@ use rustc_target::abi::VariantIdx;
use rustc_index::vec::Idx;
+use std::assert_matches::assert_matches;
use std::iter;
/// The "outermost" place that holds this value.
@@ -69,7 +70,7 @@ pub(crate) enum PlaceBase {
/// This is used internally when building a place for an expression like `a.b.c`. The fields `b`
/// and `c` can be progressively pushed onto the place builder that is created when converting `a`.
#[derive(Clone, Debug, PartialEq)]
-pub(crate) struct PlaceBuilder<'tcx> {
+pub(in crate::build) struct PlaceBuilder<'tcx> {
base: PlaceBase,
projection: Vec<PlaceElem<'tcx>>,
}
@@ -102,6 +103,8 @@ fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
variant = Some(*idx);
continue;
}
+ // These do not affect anything, they just make sure we know the right type.
+ ProjectionElem::OpaqueCast(_) => continue,
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => {
@@ -168,22 +171,22 @@ fn find_capture_matching_projections<'a, 'tcx>(
/// `PlaceBuilder` now starts from `PlaceBase::Local`.
///
/// Returns a Result with the error being the PlaceBuilder (`from_builder`) that was not found.
-fn to_upvars_resolved_place_builder<'a, 'tcx>(
+#[instrument(level = "trace", skip(cx), ret)]
+fn to_upvars_resolved_place_builder<'tcx>(
from_builder: PlaceBuilder<'tcx>,
- tcx: TyCtxt<'tcx>,
- upvars: &'a CaptureMap<'tcx>,
+ cx: &Builder<'_, 'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
match from_builder.base {
PlaceBase::Local(_) => Ok(from_builder),
PlaceBase::Upvar { var_hir_id, closure_def_id } => {
let Some((capture_index, capture)) =
find_capture_matching_projections(
- upvars,
+ &cx.upvars,
var_hir_id,
&from_builder.projection,
) else {
- let closure_span = tcx.def_span(closure_def_id);
- if !enable_precise_capture(tcx, closure_span) {
+ let closure_span = cx.tcx.def_span(closure_def_id);
+ if !enable_precise_capture(cx.tcx, closure_span) {
bug!(
"No associated capture found for {:?}[{:#?}] even though \
capture_disjoint_fields isn't enabled",
@@ -200,12 +203,13 @@ fn to_upvars_resolved_place_builder<'a, 'tcx>(
};
// Access the capture by accessing the field within the Closure struct.
- let capture_info = &upvars[capture_index];
+ let capture_info = &cx.upvars[capture_index];
let mut upvar_resolved_place_builder = PlaceBuilder::from(capture_info.use_place);
// We used some of the projections to build the capture itself,
// now we apply the remaining to the upvar resolved place.
+ trace!(?capture.captured_place, ?from_builder.projection);
let remaining_projections = strip_prefix(
capture.captured_place.place.base_ty,
from_builder.projection,
@@ -229,17 +233,20 @@ fn strip_prefix<'tcx>(
projections: Vec<PlaceElem<'tcx>>,
prefix_projections: &[HirProjection<'tcx>],
) -> impl Iterator<Item = PlaceElem<'tcx>> {
- let mut iter = projections.into_iter();
+ let mut iter = projections
+ .into_iter()
+ // Filter out opaque casts, they are unnecessary in the prefix.
+ .filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
for projection in prefix_projections {
match projection.kind {
HirProjectionKind::Deref => {
- assert!(matches!(iter.next(), Some(ProjectionElem::Deref)));
+ assert_matches!(iter.next(), Some(ProjectionElem::Deref));
}
HirProjectionKind::Field(..) => {
if base_ty.is_enum() {
- assert!(matches!(iter.next(), Some(ProjectionElem::Downcast(..))));
+ assert_matches!(iter.next(), Some(ProjectionElem::Downcast(..)));
}
- assert!(matches!(iter.next(), Some(ProjectionElem::Field(..))));
+ assert_matches!(iter.next(), Some(ProjectionElem::Field(..)));
}
HirProjectionKind::Index | HirProjectionKind::Subslice => {
bug!("unexpected projection kind: {:?}", projection);
@@ -251,24 +258,16 @@ fn strip_prefix<'tcx>(
}
impl<'tcx> PlaceBuilder<'tcx> {
- pub(in crate::build) fn into_place<'a>(
- self,
- tcx: TyCtxt<'tcx>,
- upvars: &'a CaptureMap<'tcx>,
- ) -> Place<'tcx> {
+ pub(in crate::build) fn into_place(self, cx: &Builder<'_, 'tcx>) -> Place<'tcx> {
if let PlaceBase::Local(local) = self.base {
- Place { local, projection: tcx.intern_place_elems(&self.projection) }
+ Place { local, projection: cx.tcx.intern_place_elems(&self.projection) }
} else {
- self.expect_upvars_resolved(tcx, upvars).into_place(tcx, upvars)
+ self.expect_upvars_resolved(cx).into_place(cx)
}
}
- fn expect_upvars_resolved<'a>(
- self,
- tcx: TyCtxt<'tcx>,
- upvars: &'a CaptureMap<'tcx>,
- ) -> PlaceBuilder<'tcx> {
- to_upvars_resolved_place_builder(self, tcx, upvars).unwrap()
+ fn expect_upvars_resolved(self, cx: &Builder<'_, 'tcx>) -> PlaceBuilder<'tcx> {
+ to_upvars_resolved_place_builder(self, cx).unwrap()
}
/// Attempts to resolve the `PlaceBuilder`.
@@ -282,18 +281,21 @@ impl<'tcx> PlaceBuilder<'tcx> {
/// not captured. This can happen because the final mir that will be
/// generated doesn't require a read for this place. Failures will only
/// happen inside closures.
- pub(in crate::build) fn try_upvars_resolved<'a>(
+ pub(in crate::build) fn try_upvars_resolved(
self,
- tcx: TyCtxt<'tcx>,
- upvars: &'a CaptureMap<'tcx>,
+ cx: &Builder<'_, 'tcx>,
) -> Result<PlaceBuilder<'tcx>, PlaceBuilder<'tcx>> {
- to_upvars_resolved_place_builder(self, tcx, upvars)
+ to_upvars_resolved_place_builder(self, cx)
}
pub(crate) fn base(&self) -> PlaceBase {
self.base
}
+ pub(crate) fn projection(&self) -> &[PlaceElem<'tcx>] {
+ &self.projection
+ }
+
pub(crate) fn field(self, f: Field, ty: Ty<'tcx>) -> Self {
self.project(PlaceElem::Field(f, ty))
}
@@ -353,7 +355,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_place_builder(block, expr));
- block.and(place_builder.into_place(self.tcx, &self.upvars))
+ block.and(place_builder.into_place(self))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -377,7 +379,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
- block.and(place_builder.into_place(self.tcx, &self.upvars))
+ block.and(place_builder.into_place(self))
}
/// This is used when constructing a compound `Place`, so that we can avoid creating
@@ -472,7 +474,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
inferred_ty: expr.ty,
});
- let place = place_builder.clone().into_place(this.tcx, &this.upvars);
+ let place = place_builder.clone().into_place(this);
this.cfg.push(
block,
Statement {
@@ -610,7 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if is_outermost_index {
self.read_fake_borrows(block, fake_borrow_temps, source_info)
} else {
- base_place = base_place.expect_upvars_resolved(self.tcx, &self.upvars);
+ base_place = base_place.expect_upvars_resolved(self);
self.add_fake_borrows_of_base(
&base_place,
block,
@@ -638,12 +640,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let lt = self.temp(bool_ty, expr_span);
// len = len(slice)
- self.cfg.push_assign(
- block,
- source_info,
- len,
- Rvalue::Len(slice.into_place(self.tcx, &self.upvars)),
- );
+ self.cfg.push_assign(block, source_info, len, Rvalue::Len(slice.into_place(self)));
// lt = idx < len
self.cfg.push_assign(
block,
@@ -723,6 +720,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
ProjectionElem::Field(..)
| ProjectionElem::Downcast(..)
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } => (),
}
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 f88ab63f0..3dafdcb78 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -12,7 +12,7 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::Place;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::cast::CastTy;
+use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
use rustc_middle::ty::{self, Ty, UpvarSubsts};
use rustc_span::Span;
@@ -217,16 +217,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let from_ty = CastTy::from_ty(ty);
let cast_ty = CastTy::from_ty(expr.ty);
debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
- let cast_kind = match (from_ty, cast_ty) {
- (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
- CastKind::PointerExposeAddress
- }
- (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
- CastKind::PointerFromExposedAddress
- }
- (_, Some(CastTy::DynStar)) => CastKind::DynStar,
- (_, _) => CastKind::Misc,
- };
+ let cast_kind = mir_cast_kind(ty, expr.ty);
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
}
ExprKind::Pointer { cast, source } => {
@@ -329,10 +320,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let place_builder =
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
- if let Ok(place_builder_resolved) =
- place_builder.try_upvars_resolved(this.tcx, &this.upvars)
- {
- let mir_place = place_builder_resolved.into_place(this.tcx, &this.upvars);
+ if let Ok(place_builder_resolved) = place_builder.try_upvars_resolved(this) {
+ let mir_place = place_builder_resolved.into_place(this);
this.cfg.push_fake_read(
block,
this.source_info(this.tcx.hir().span(*hir_id)),
@@ -623,8 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// by the parent itself. The mutability of the current capture
// is same as that of the capture in the parent closure.
PlaceBase::Upvar { .. } => {
- let enclosing_upvars_resolved =
- arg_place_builder.clone().into_place(this.tcx, &this.upvars);
+ let enclosing_upvars_resolved = arg_place_builder.clone().into_place(this);
match enclosing_upvars_resolved.as_ref() {
PlaceRef {
@@ -661,7 +649,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false },
};
- let arg_place = arg_place_builder.into_place(this.tcx, &this.upvars);
+ let arg_place = arg_place_builder.into_place(this);
this.cfg.push_assign(
block,
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 e5dafb820..0ca4e3745 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs
@@ -23,6 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability))
}
+ #[instrument(skip(self), level = "debug")]
fn as_temp_inner(
&mut self,
mut block: BasicBlock,
@@ -30,10 +31,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr: &Expr<'tcx>,
mutability: Mutability,
) -> BlockAnd<Local> {
- debug!(
- "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})",
- block, temp_lifetime, expr, mutability
- );
let this = self;
let expr_span = expr.span;
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 224a1b80f..24ecd0a53 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -15,14 +15,13 @@ use std::iter;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, storing the result into `destination`, which
/// is assumed to be uninitialized.
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn expr_into_dest(
&mut self,
destination: Place<'tcx>,
mut block: BasicBlock,
expr: &Expr<'tcx>,
) -> BlockAnd<()> {
- debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);
-
// since we frequently have to reference `self` from within a
// closure, where `self` would be shadowed, it's easier to
// just use the name `this` uniformly
@@ -366,7 +365,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None => {
let place_builder = place_builder.clone();
this.consume_by_copy_or_move(
- place_builder.field(n, *ty).into_place(this.tcx, &this.upvars),
+ place_builder.field(n, *ty).into_place(this),
)
}
})
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 93f382cc6..3f813e0af 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -220,10 +220,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let cause_matched_place = FakeReadCause::ForMatchedPlace(None);
let source_info = self.source_info(scrutinee_span);
- if let Ok(scrutinee_builder) =
- scrutinee_place_builder.clone().try_upvars_resolved(self.tcx, &self.upvars)
- {
- let scrutinee_place = scrutinee_builder.into_place(self.tcx, &self.upvars);
+ if let Ok(scrutinee_builder) = scrutinee_place_builder.clone().try_upvars_resolved(self) {
+ let scrutinee_place = scrutinee_builder.into_place(self);
self.cfg.push_fake_read(block, source_info, cause_matched_place, scrutinee_place);
}
@@ -246,7 +244,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.map(|arm| {
let arm = &self.thir[arm];
let arm_has_guard = arm.guard.is_some();
- let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
+ let arm_candidate =
+ Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard, self);
(arm, arm_candidate)
})
.collect()
@@ -349,9 +348,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut opt_scrutinee_place: Option<(Option<&Place<'tcx>>, Span)> = None;
let scrutinee_place: Place<'tcx>;
if let Ok(scrutinee_builder) =
- scrutinee_place_builder.clone().try_upvars_resolved(this.tcx, &this.upvars)
+ scrutinee_place_builder.clone().try_upvars_resolved(this)
{
- scrutinee_place = scrutinee_builder.into_place(this.tcx, &this.upvars);
+ scrutinee_place = scrutinee_builder.into_place(this);
opt_scrutinee_place = Some((Some(&scrutinee_place), scrutinee_span));
}
let scope = this.declare_bindings(
@@ -584,7 +583,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
initializer: PlaceBuilder<'tcx>,
set_match_place: bool,
) -> BlockAnd<()> {
- let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false);
+ let mut candidate = Candidate::new(initializer.clone(), &irrefutable_pat, false, self);
let fake_borrow_temps = self.lower_match_tree(
block,
irrefutable_pat.span,
@@ -601,12 +600,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
while let Some(next) = {
for binding in &candidate_ref.bindings {
let local = self.var_local_id(binding.var_id, OutsideGuard);
-
- let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
- VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
- )))) = self.local_decls[local].local_info else {
- bug!("Let binding to non-user variable.")
- };
// `try_upvars_resolved` may fail if it is unable to resolve the given
// `PlaceBuilder` inside a closure. In this case, we don't want to include
// a scrutinee place. `scrutinee_place_builder` will fail for destructured
@@ -621,10 +614,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// let (v1, v2) = foo;
// };
// ```
- if let Ok(match_pair_resolved) =
- initializer.clone().try_upvars_resolved(self.tcx, &self.upvars)
- {
- let place = match_pair_resolved.into_place(self.tcx, &self.upvars);
+ if let Ok(match_pair_resolved) = initializer.clone().try_upvars_resolved(self) {
+ let place = match_pair_resolved.into_place(self);
+
+ let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
+ VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. },
+ )))) = self.local_decls[local].local_info else {
+ bug!("Let binding to non-user variable.")
+ };
*match_place = Some(place);
}
}
@@ -654,6 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// scope for the bindings in these patterns, if such a scope had to be
/// created. NOTE: Declaring the bindings should always be done in their
/// drop scope.
+ #[instrument(skip(self), level = "debug")]
pub(crate) fn declare_bindings(
&mut self,
mut visibility_scope: Option<SourceScope>,
@@ -662,7 +660,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
has_guard: ArmHasGuard,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
- debug!("declare_bindings: pattern={:?}", pattern);
self.visit_primary_bindings(
&pattern,
UserTypeProjections::none(),
@@ -868,11 +865,16 @@ struct Candidate<'pat, 'tcx> {
}
impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
- fn new(place: PlaceBuilder<'tcx>, pattern: &'pat Pat<'tcx>, has_guard: bool) -> Self {
+ fn new(
+ place: PlaceBuilder<'tcx>,
+ pattern: &'pat Pat<'tcx>,
+ has_guard: bool,
+ cx: &Builder<'_, 'tcx>,
+ ) -> Self {
Candidate {
span: pattern.span,
has_guard,
- match_pairs: smallvec![MatchPair { place, pattern }],
+ match_pairs: smallvec![MatchPair::new(place, pattern, cx)],
bindings: Vec::new(),
ascriptions: Vec::new(),
subcandidates: Vec::new(),
@@ -1048,6 +1050,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// if `x.0` matches `false` (for the third arm). In the (impossible at
/// runtime) case when `x.0` is now `true`, we branch to
/// `otherwise_block`.
+ #[instrument(skip(self, fake_borrows), level = "debug")]
fn match_candidates<'pat>(
&mut self,
span: Span,
@@ -1057,11 +1060,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidates: &mut [&mut Candidate<'pat, 'tcx>],
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) {
- debug!(
- "matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
- span, candidates, start_block, otherwise_block,
- );
-
// Start by simplifying candidates. Once this process is complete, all
// the match pairs which remain require some form of test, whether it
// be a switch or pattern comparison.
@@ -1380,6 +1378,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
)
}
+ #[instrument(
+ skip(self, otherwise, or_span, place, fake_borrows, candidate, pats),
+ level = "debug"
+ )]
fn test_or_pattern<'pat>(
&mut self,
candidate: &mut Candidate<'pat, 'tcx>,
@@ -1389,10 +1391,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
place: PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) {
- debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
+ debug!("candidate={:#?}\npats={:#?}", candidate, pats);
let mut or_candidates: Vec<_> = pats
.iter()
- .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard))
+ .map(|pat| Candidate::new(place.clone(), pat, candidate.has_guard, self))
.collect();
let mut or_candidate_refs: Vec<_> = or_candidates.iter_mut().collect();
let otherwise = if candidate.otherwise_block.is_some() {
@@ -1605,9 +1607,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// Insert a Shallow borrow of any places that is switched on.
if let Some(fb) = fake_borrows && let Ok(match_place_resolved) =
- match_place.clone().try_upvars_resolved(self.tcx, &self.upvars)
+ match_place.clone().try_upvars_resolved(self)
{
- let resolved_place = match_place_resolved.into_place(self.tcx, &self.upvars);
+ let resolved_place = match_place_resolved.into_place(self);
fb.insert(resolved_place);
}
@@ -1634,9 +1636,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidates = rest;
}
// at least the first candidate ought to be tested
- assert!(total_candidate_count > candidates.len());
- debug!("test_candidates: tested_candidates: {}", total_candidate_count - candidates.len());
- debug!("test_candidates: untested_candidates: {}", candidates.len());
+ assert!(
+ total_candidate_count > candidates.len(),
+ "{}, {:#?}",
+ total_candidate_count,
+ candidates
+ );
+ debug!("tested_candidates: {}", total_candidate_count - candidates.len());
+ debug!("untested_candidates: {}", candidates.len());
// HACK(matthewjasper) This is a closure so that we can let the test
// create its blocks before the rest of the match. This currently
@@ -1783,8 +1790,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let expr_span = expr.span;
let expr_place_builder = unpack!(block = self.lower_scrutinee(block, expr, expr_span));
let wildcard = Pat::wildcard_from_ty(pat.ty);
- let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false);
- let mut otherwise_candidate = Candidate::new(expr_place_builder.clone(), &wildcard, false);
+ let mut guard_candidate = Candidate::new(expr_place_builder.clone(), &pat, false, self);
+ let mut otherwise_candidate =
+ Candidate::new(expr_place_builder.clone(), &wildcard, false, self);
let fake_borrow_temps = self.lower_match_tree(
block,
pat.span,
@@ -1794,8 +1802,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
let mut opt_expr_place: Option<(Option<&Place<'tcx>>, Span)> = None;
let expr_place: Place<'tcx>;
- if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self.tcx, &self.upvars) {
- expr_place = expr_builder.into_place(self.tcx, &self.upvars);
+ if let Ok(expr_builder) = expr_place_builder.try_upvars_resolved(self) {
+ expr_place = expr_builder.into_place(self);
opt_expr_place = Some((Some(&expr_place), expr_span));
}
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
@@ -2209,6 +2217,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// first local is a binding for occurrences of `var` in the guard, which
/// will have type `&T`. The second local is a binding for occurrences of
/// `var` in the arm body, which will have type `T`.
+ #[instrument(skip(self), level = "debug")]
fn declare_binding(
&mut self,
source_info: SourceInfo,
@@ -2223,19 +2232,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
pat_span: Span,
) {
- debug!(
- "declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
- visibility_scope={:?}, source_info={:?})",
- var_id, name, mode, var_ty, visibility_scope, source_info
- );
-
let tcx = self.tcx;
let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope };
let binding_mode = match mode {
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability),
BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability),
};
- debug!("declare_binding: user_ty={:?}", user_ty);
let local = LocalDecl::<'tcx> {
mutability,
ty: var_ty,
@@ -2285,7 +2287,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} else {
LocalsForNode::One(for_arm_body)
};
- debug!("declare_binding: vars={:?}", locals);
+ debug!(?locals);
self.var_indices.insert(var_id, locals);
}
@@ -2302,8 +2304,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let (matching, failure) = self.in_if_then_scope(*let_else_scope, else_block_span, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
- let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
- let mut candidate = Candidate::new(scrutinee.clone(), pattern, false);
+ let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false, this);
+ let mut candidate = Candidate::new(scrutinee.clone(), pattern, false, this);
let fake_borrow_temps = this.lower_match_tree(
block,
initializer_span,
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index df221d356..924d2f555 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -37,12 +37,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
///
/// only generates a single switch. If this happens this method returns
/// `true`.
+ #[instrument(skip(self, candidate), level = "debug")]
pub(super) fn simplify_candidate<'pat>(
&mut self,
candidate: &mut Candidate<'pat, 'tcx>,
) -> bool {
// repeatedly simplify match pairs until fixed point is reached
- debug!(?candidate, "simplify_candidate");
+ debug!("{candidate:#?}");
// existing_bindings and new_bindings exists to keep the semantics in order.
// Reversing the binding order for bindings after `@` changes the binding order in places
@@ -131,7 +132,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
) -> Vec<Candidate<'pat, 'tcx>> {
pats.iter()
.map(|box pat| {
- let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard);
+ let mut candidate = Candidate::new(place.clone(), pat, candidate.has_guard, self);
self.simplify_candidate(&mut candidate);
candidate
})
@@ -155,17 +156,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ascription: thir::Ascription { ref annotation, variance },
} => {
// Apply the type ascription to the value at `match_pair.place`, which is the
- if let Ok(place_resolved) =
- match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
- {
+ if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
candidate.ascriptions.push(Ascription {
annotation: annotation.clone(),
- source: place_resolved.into_place(self.tcx, &self.upvars),
+ source: place_resolved.into_place(self),
variance,
});
}
- candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
+ candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
Ok(())
}
@@ -184,12 +183,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
ref subpattern,
is_primary: _,
} => {
- if let Ok(place_resolved) =
- match_pair.place.clone().try_upvars_resolved(self.tcx, &self.upvars)
- {
+ if let Ok(place_resolved) = match_pair.place.clone().try_upvars_resolved(self) {
candidate.bindings.push(Binding {
span: match_pair.pattern.span,
- source: place_resolved.into_place(self.tcx, &self.upvars),
+ source: place_resolved.into_place(self),
var_id: var,
binding_mode: mode,
});
@@ -197,7 +194,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if let Some(subpattern) = subpattern.as_ref() {
// this is the `x @ P` case; have to keep matching against `P` now
- candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern));
+ candidate.match_pairs.push(MatchPair::new(match_pair.place, subpattern, self));
}
Ok(())
@@ -267,14 +264,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| {
i == variant_index || {
self.tcx.features().exhaustive_patterns
- && !v
- .uninhabited_from(
- self.tcx,
- substs,
- adt_def.adt_kind(),
- self.param_env,
- )
- .is_empty()
+ && v.inhabited_predicate(self.tcx, adt_def)
+ .subst(self.tcx, substs)
+ .apply_any_module(self.tcx, self.param_env)
+ != Some(true)
}
}) && (adt_def.did().is_local()
|| !adt_def.is_variant_list_non_exhaustive());
@@ -308,7 +301,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
PatKind::Deref { ref subpattern } => {
let place_builder = match_pair.place.deref();
- candidate.match_pairs.push(MatchPair::new(place_builder, subpattern));
+ candidate.match_pairs.push(MatchPair::new(place_builder, subpattern, self));
Ok(())
}
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 47d05a6e3..b597ecfaa 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -14,8 +14,8 @@ use rustc_hir::{LangItem, RangeEnd};
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
-use rustc_middle::ty::subst::{GenericArg, Subst};
use rustc_middle::ty::util::IntTypeExt;
+use rustc_middle::ty::GenericArg;
use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Symbol};
@@ -144,6 +144,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}
+ #[instrument(skip(self, make_target_blocks, place_builder), level = "debug")]
pub(super) fn perform_test(
&mut self,
match_start_span: Span,
@@ -153,19 +154,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
test: &Test<'tcx>,
make_target_blocks: impl FnOnce(&mut Self) -> Vec<BasicBlock>,
) {
- let place: Place<'tcx>;
- if let Ok(test_place_builder) = place_builder.try_upvars_resolved(self.tcx, &self.upvars) {
- place = test_place_builder.into_place(self.tcx, &self.upvars);
- } else {
- return;
- }
- debug!(
- "perform_test({:?}, {:?}: {:?}, {:?})",
- block,
- place,
- place.ty(&self.local_decls, self.tcx),
- test
- );
+ let place = place_builder.into_place(self);
+ let place_ty = place.ty(&self.local_decls, self.tcx);
+ debug!(?place, ?place_ty,);
let source_info = self.source_info(test.span);
match test.kind {
@@ -733,14 +724,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`,
// we want to create a set of derived match-patterns like
// `(x as Variant).0 @ P1` and `(x as Variant).1 @ P1`.
- let elem =
- ProjectionElem::Downcast(Some(adt_def.variant(variant_index).name), variant_index);
- let downcast_place = match_pair.place.project(elem); // `(x as Variant)`
+ let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
// e.g., `(x as Variant).0`
let place = downcast_place.clone().field(subpattern.field, subpattern.pattern.ty);
// e.g., `(x as Variant).0 @ P1`
- MatchPair::new(place, &subpattern.pattern)
+ MatchPair::new(place, &subpattern.pattern, self)
});
candidate.match_pairs.extend(consequent_match_pairs);
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index b61c4fe50..b854ba47f 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -1,9 +1,11 @@
+use crate::build::expr::as_place::PlaceBase;
use crate::build::expr::as_place::PlaceBuilder;
use crate::build::matches::MatchPair;
use crate::build::Builder;
use rustc_middle::mir::*;
use rustc_middle::thir::*;
use rustc_middle::ty;
+use rustc_middle::ty::TypeVisitable;
use smallvec::SmallVec;
use std::convert::TryInto;
@@ -17,7 +19,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
.iter()
.map(|fieldpat| {
let place = place.clone().field(fieldpat.field, fieldpat.pattern.ty);
- MatchPair::new(place, &fieldpat.pattern)
+ MatchPair::new(place, &fieldpat.pattern, self)
})
.collect()
}
@@ -31,23 +33,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
suffix: &'pat [Box<Pat<'tcx>>],
) {
let tcx = self.tcx;
- let (min_length, exact_size) = if let Ok(place_resolved) =
- place.clone().try_upvars_resolved(tcx, &self.upvars)
- {
- match place_resolved.into_place(tcx, &self.upvars).ty(&self.local_decls, tcx).ty.kind()
- {
- ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
- _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
- }
- } else {
- ((prefix.len() + suffix.len()).try_into().unwrap(), false)
- };
+ let (min_length, exact_size) =
+ if let Ok(place_resolved) = place.clone().try_upvars_resolved(self) {
+ match place_resolved.into_place(self).ty(&self.local_decls, tcx).ty.kind() {
+ ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true),
+ _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false),
+ }
+ } else {
+ ((prefix.len() + suffix.len()).try_into().unwrap(), false)
+ };
match_pairs.extend(prefix.iter().enumerate().map(|(idx, subpattern)| {
let elem =
ProjectionElem::ConstantIndex { offset: idx as u64, min_length, from_end: false };
let place = place.clone().project(elem);
- MatchPair::new(place, subpattern)
+ MatchPair::new(place, subpattern, self)
}));
if let Some(subslice_pat) = opt_slice {
@@ -57,7 +57,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
to: if exact_size { min_length - suffix_len } else { suffix_len },
from_end: !exact_size,
});
- match_pairs.push(MatchPair::new(subslice, subslice_pat));
+ match_pairs.push(MatchPair::new(subslice, subslice_pat, self));
}
match_pairs.extend(suffix.iter().rev().enumerate().map(|(idx, subpattern)| {
@@ -68,7 +68,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
from_end: !exact_size,
};
let place = place.clone().project(elem);
- MatchPair::new(place, subpattern)
+ MatchPair::new(place, subpattern, self)
}));
}
@@ -96,10 +96,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
impl<'pat, 'tcx> MatchPair<'pat, 'tcx> {
- pub(crate) fn new(
+ pub(in crate::build) fn new(
place: PlaceBuilder<'tcx>,
pattern: &'pat Pat<'tcx>,
+ cx: &Builder<'_, 'tcx>,
) -> MatchPair<'pat, 'tcx> {
+ // Force the place type to the pattern's type.
+ // FIXME(oli-obk): can we use this to simplify slice/array pattern hacks?
+ let mut place = match place.try_upvars_resolved(cx) {
+ Ok(val) | Err(val) => val,
+ };
+
+ // Only add the OpaqueCast projection if the given place is an opaque type and the
+ // expected type from the pattern is not.
+ let may_need_cast = match place.base() {
+ PlaceBase::Local(local) => {
+ let ty = Place::ty_from(local, place.projection(), &cx.local_decls, cx.tcx).ty;
+ ty != pattern.ty && ty.has_opaque_types()
+ }
+ _ => true,
+ };
+ if may_need_cast {
+ place = place.project(ProjectionElem::OpaqueCast(pattern.ty));
+ }
MatchPair { place, pattern }
}
}
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 25c4e51cb..cbcf9cd12 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -157,7 +157,7 @@ struct BlockContext(Vec<BlockFrame>);
struct Builder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- infcx: InferCtxt<'a, 'tcx>,
+ infcx: InferCtxt<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
region_scope_tree: &'tcx region::ScopeTree,
param_env: ty::ParamEnv<'tcx>,
@@ -481,54 +481,49 @@ fn construct_fn<'tcx>(
(None, fn_sig.output())
};
- let mut body = tcx.infer_ctxt().enter(|infcx| {
- let mut builder = Builder::new(
- thir,
- infcx,
- fn_def,
- fn_id,
- span_with_body,
- arguments.len(),
- safety,
- return_ty,
- return_ty_span,
- generator_kind,
- );
+ let infcx = tcx.infer_ctxt().build();
+ let mut builder = Builder::new(
+ thir,
+ infcx,
+ fn_def,
+ fn_id,
+ span_with_body,
+ arguments.len(),
+ safety,
+ return_ty,
+ return_ty_span,
+ generator_kind,
+ );
- let call_site_scope =
- region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite };
- let arg_scope =
- region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments };
- let source_info = builder.source_info(span);
- let call_site_s = (call_site_scope, source_info);
- unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
- let arg_scope_s = (arg_scope, source_info);
- // Attribute epilogue to function's closing brace
- let fn_end = span_with_body.shrink_to_hi();
- 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],
- )
- }))
- }
- ));
- let source_info = builder.source_info(fn_end);
- builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
- builder.build_drop_trees();
- return_block.unit()
- }));
-
- builder.finish()
- });
+ let call_site_scope =
+ region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::CallSite };
+ let arg_scope =
+ region::Scope { id: body_id.hir_id.local_id, data: region::ScopeData::Arguments };
+ let source_info = builder.source_info(span);
+ let call_site_s = (call_site_scope, source_info);
+ unpack!(builder.in_scope(call_site_s, LintLevel::Inherited, |builder| {
+ let arg_scope_s = (arg_scope, source_info);
+ // Attribute epilogue to function's closing brace
+ let fn_end = span_with_body.shrink_to_hi();
+ 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],
+ )
+ }))
+ }));
+ let source_info = builder.source_info(fn_end);
+ builder.cfg.terminate(return_block, source_info, TerminatorKind::Return);
+ builder.build_drop_trees();
+ return_block.unit()
+ }));
+
+ let mut body = builder.finish();
body.spread_arg = if abi == Abi::RustCall {
// RustCall pseudo-ABI untuples the last argument.
@@ -584,30 +579,29 @@ fn construct_const<'a, 'tcx>(
let typeck_results = tcx.typeck_opt_const_arg(def);
let const_ty = typeck_results.node_type(hir_id);
- tcx.infer_ctxt().enter(|infcx| {
- let mut builder = Builder::new(
- thir,
- infcx,
- def,
- hir_id,
- span,
- 0,
- Safety::Safe,
- const_ty,
- const_ty_span,
- None,
- );
+ let infcx = tcx.infer_ctxt().build();
+ let mut builder = Builder::new(
+ thir,
+ infcx,
+ def,
+ hir_id,
+ span,
+ 0,
+ Safety::Safe,
+ const_ty,
+ const_ty_span,
+ None,
+ );
- let mut block = START_BLOCK;
- unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
+ let mut block = START_BLOCK;
+ unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
- let source_info = builder.source_info(span);
- builder.cfg.terminate(block, source_info, TerminatorKind::Return);
+ let source_info = builder.source_info(span);
+ builder.cfg.terminate(block, source_info, TerminatorKind::Return);
- builder.build_drop_trees();
+ builder.build_drop_trees();
- builder.finish()
- })
+ builder.finish()
}
/// Construct MIR for an item that has had errors in type checking.
@@ -683,7 +677,7 @@ fn construct_error<'tcx>(
impl<'a, 'tcx> Builder<'a, 'tcx> {
fn new(
thir: &'a Thir<'tcx>,
- infcx: InferCtxt<'a, 'tcx>,
+ infcx: InferCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
hir_id: hir::HirId,
span: Span,
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index ff66ca595..3cebd5ebe 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -555,6 +555,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Convenience wrapper that pushes a scope and then executes `f`
/// to build its contents, popping the scope afterwards.
+ #[instrument(skip(self, f), level = "debug")]
pub(crate) fn in_scope<F, R>(
&mut self,
region_scope: (region::Scope, SourceInfo),
@@ -564,7 +565,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
where
F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>,
{
- debug!("in_scope(region_scope={:?})", region_scope);
let source_scope = self.source_scope;
let tcx = self.tcx;
if let LintLevel::Explicit(current_hir_id) = lint_level {
@@ -591,7 +591,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let rv = unpack!(block = f(self));
unpack!(block = self.pop_scope(region_scope, block));
self.source_scope = source_scope;
- debug!("in_scope: exiting region_scope={:?} block={:?}", region_scope, block);
+ debug!(?block);
block.and(rv)
}
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 495738ebe..fb1ea9ed3 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -89,15 +89,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
UNSAFE_OP_IN_UNSAFE_FN,
self.hir_context,
span,
- |lint| {
- lint.build(&format!(
- "{} is unsafe and requires unsafe block (error E0133)",
- description,
- ))
- .span_label(span, kind.simple_description())
- .note(note)
- .emit();
- },
+ format!("{} is unsafe and requires unsafe block (error E0133)", description,),
+ |lint| lint.span_label(span, kind.simple_description()).note(note),
)
}
SafetyContext::Safe => {
@@ -125,14 +118,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
enclosing_unsafe: Option<(Span, &'static str)>,
) {
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
- self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, |lint| {
- let msg = "unnecessary `unsafe` block";
- let mut db = lint.build(msg);
- db.span_label(block_span, msg);
+ let msg = "unnecessary `unsafe` block";
+ self.tcx.struct_span_lint_hir(UNUSED_UNSAFE, hir_id, block_span, msg, |lint| {
+ lint.span_label(block_span, msg);
if let Some((span, kind)) = enclosing_unsafe {
- db.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
+ lint.span_label(span, format!("because it's nested under this `unsafe` {}", kind));
}
- db.emit();
+ lint
});
}
@@ -268,7 +260,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
};
match borrow_kind {
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique => {
- if !ty.is_freeze(self.tcx.at(pat.span), self.param_env) {
+ if !ty.is_freeze(self.tcx, self.param_env) {
self.requires_unsafe(pat.span, BorrowOfLayoutConstrainedField);
}
}
@@ -364,7 +356,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
// If the called function has target features the calling function hasn't,
// the call requires `unsafe`. Don't check this on wasm
// targets, though. For more information on wasm see the
- // is_like_wasm check in typeck/src/collect.rs
+ // is_like_wasm check in hir_analysis/src/collect.rs
if !self.tcx.sess.target.options.is_like_wasm
&& !self
.tcx
@@ -465,9 +457,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
if visitor.found {
match borrow_kind {
BorrowKind::Shallow | BorrowKind::Shared | BorrowKind::Unique
- if !self.thir[arg]
- .ty
- .is_freeze(self.tcx.at(self.thir[arg].span), self.param_env) =>
+ if !self.thir[arg].ty.is_freeze(self.tcx, self.param_env) =>
{
self.requires_unsafe(expr.span, BorrowOfLayoutConstrainedField)
}
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index 0c0a2fe9c..b53bd3d07 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -2,11 +2,11 @@
//!
//! This crate also contains the match exhaustiveness and usefulness checking.
#![allow(rustc::potential_query_instability)]
+#![feature(assert_matches)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(once_cell)]
#![recursion_limit = "256"]
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 54d549fd6..b21f30efc 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -36,16 +36,20 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let sp = tcx.def_span(def_id);
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- tcx.struct_span_lint_hir(UNCONDITIONAL_RECURSION, hir_id, sp, |lint| {
- let mut db = lint.build("function cannot return without recursing");
- db.span_label(sp, "cannot return without recursing");
- // offer some help to the programmer.
- for call_span in vis.reachable_recursive_calls {
- db.span_label(call_span, "recursive call site");
- }
- db.help("a `loop` may express intention better if this is on purpose");
- db.emit();
- });
+ tcx.struct_span_lint_hir(
+ UNCONDITIONAL_RECURSION,
+ hir_id,
+ sp,
+ "function cannot return without recursing",
+ |lint| {
+ lint.span_label(sp, "cannot return without recursing");
+ // offer some help to the programmer.
+ for call_span in vis.reachable_recursive_calls {
+ lint.span_label(call_span, "recursive call site");
+ }
+ lint.help("a `loop` may express intention better if this is on purpose")
+ },
+ );
}
}
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index d059877f8..c7a7c3e3f 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -48,6 +48,8 @@ impl<'tcx> Cx<'tcx> {
_ => None,
};
+ trace!(?expr.ty);
+
// Now apply adjustments, if any.
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
trace!(?expr, ?adjustment);
@@ -56,6 +58,8 @@ impl<'tcx> Cx<'tcx> {
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
}
+ trace!(?expr.ty, "after adjustments");
+
// Next, wrap this up in the expr's scope.
expr = Expr {
temp_lifetime,
@@ -155,6 +159,7 @@ impl<'tcx> Cx<'tcx> {
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(expr) }
}
+ Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
};
Expr { temp_lifetime, ty: adjustment.target, span, kind }
@@ -994,7 +999,7 @@ impl<'tcx> Cx<'tcx> {
.temporary_scope(self.region_scope_tree, closure_expr.hir_id.local_id);
let var_ty = place.base_ty;
- // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path
+ // The result of capture analysis in `rustc_hir_analysis/check/upvar.rs`represents a captured path
// as it's seen for use within the closure and not at the time of closure creation.
//
// That is we see expect to see it start from a captured upvar and not something that is local
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 3ef1b263f..1d95d6b53 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -15,7 +15,7 @@ use rustc_hir::HirId;
use rustc_hir::Node;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
-use rustc_middle::ty::{self, RvalueScopes, Subst, TyCtxt};
+use rustc_middle::ty::{self, RvalueScopes, TyCtxt};
use rustc_span::Span;
pub(crate) fn thir_body<'tcx>(
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 d45b88690..858129c74 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -7,7 +7,7 @@ use super::{PatCtxt, PatternError};
use rustc_arena::TypedArena;
use rustc_ast::Mutability;
use rustc_errors::{
- error_code, pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder,
+ error_code, pluralize, struct_span_err, Applicability, DelayDm, Diagnostic, DiagnosticBuilder,
ErrorGuaranteed, MultiSpan,
};
use rustc_hir as hir;
@@ -347,27 +347,35 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
let span_end = affix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let cnt = affix.len();
- cx.tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, top, span, |lint| {
- let s = pluralize!(cnt);
- let mut diag = lint.build(&format!("{kind} irrefutable pattern{s} in let chain"));
- diag.note(&format!(
- "{these} pattern{s} will always match",
- these = pluralize!("this", cnt),
- ));
- diag.help(&format!(
- "consider moving {} {suggestion}",
- if cnt > 1 { "them" } else { "it" }
- ));
- diag.emit()
- });
+ let s = pluralize!(cnt);
+ cx.tcx.struct_span_lint_hir(
+ IRREFUTABLE_LET_PATTERNS,
+ top,
+ span,
+ format!("{kind} irrefutable pattern{s} in let chain"),
+ |lint| {
+ lint.note(format!(
+ "{these} pattern{s} will always match",
+ these = pluralize!("this", cnt),
+ ))
+ .help(format!(
+ "consider moving {} {suggestion}",
+ if cnt > 1 { "them" } else { "it" }
+ ))
+ },
+ );
};
if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
// The chain has a non-zero prefix of irrefutable `let` statements.
// Check if the let source is while, for there is no alternative place to put a prefix,
// and we shouldn't lint.
+ // For let guards inside a match, prefixes might use bindings of the match pattern,
+ // so can't always be moved out.
+ // FIXME: Add checking whether the bindings are actually used in the prefix,
+ // and lint if they are not.
let let_source = let_source_parent(self.tcx, top, None);
- if !matches!(let_source, LetSource::WhileLet) {
+ if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
// Emit the lint
let prefix = &chain_refutabilities[..until];
lint_affix(prefix, "leading", "outside of the construct");
@@ -487,7 +495,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
],
Applicability::HasPlaceholders,
);
- if !bindings.is_empty() && cx.tcx.sess.is_nightly_build() {
+ if !bindings.is_empty() {
err.span_suggestion_verbose(
semi_span.shrink_to_lo(),
&format!(
@@ -561,26 +569,28 @@ fn check_for_bindings_named_same_as_variants(
BINDINGS_WITH_VARIANT_NAME,
p.hir_id,
p.span,
+ DelayDm(|| format!(
+ "pattern binding `{}` is named the same as one \
+ of the variants of the type `{}`",
+ ident, cx.tcx.def_path_str(edef.did())
+ )),
|lint| {
let ty_path = cx.tcx.def_path_str(edef.did());
- let mut err = lint.build(&format!(
- "pattern binding `{}` is named the same as one \
- of the variants of the type `{}`",
- ident, ty_path
- ));
- err.code(error_code!(E0170));
+ lint.code(error_code!(E0170));
+
// If this is an irrefutable pattern, and there's > 1 variant,
// then we can't actually match on this. Applying the below
// suggestion would produce code that breaks on `check_irrefutable`.
if rf == Refutable || variant_count == 1 {
- err.span_suggestion(
+ lint.span_suggestion(
p.span,
"to match on the variant, qualify the path",
format!("{}::{}", ty_path, ident),
Applicability::MachineApplicable,
);
}
- err.emit();
+
+ lint
},
)
}
@@ -598,14 +608,13 @@ fn pat_is_catchall(pat: &DeconstructedPat<'_, '_>) -> bool {
}
fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<Span>) {
- tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, |lint| {
- let mut err = lint.build("unreachable pattern");
+ tcx.struct_span_lint_hir(UNREACHABLE_PATTERNS, id, span, "unreachable pattern", |lint| {
if let Some(catchall) = catchall {
// We had a catchall pattern, hint at that.
- err.span_label(span, "unreachable pattern");
- err.span_label(catchall, "matches any value");
+ lint.span_label(span, "unreachable pattern");
+ lint.span_label(catchall, "matches any value");
}
- err.emit();
+ lint
});
}
@@ -621,6 +630,11 @@ fn irrefutable_let_patterns(
count: usize,
span: Span,
) {
+ let span = match source {
+ LetSource::LetElse(span) => span,
+ _ => span,
+ };
+
macro_rules! emit_diag {
(
$lint:expr,
@@ -630,18 +644,23 @@ fn irrefutable_let_patterns(
) => {{
let s = pluralize!(count);
let these = pluralize!("this", count);
- let mut diag = $lint.build(&format!("irrefutable {} pattern{s}", $source_name));
- diag.note(&format!("{these} pattern{s} will always match, so the {}", $note_sufix));
- diag.help(concat!("consider ", $help_sufix));
- diag.emit()
+ tcx.struct_span_lint_hir(
+ IRREFUTABLE_LET_PATTERNS,
+ id,
+ span,
+ format!("irrefutable {} pattern{s}", $source_name),
+ |lint| {
+ lint.note(&format!(
+ "{these} pattern{s} will always match, so the {}",
+ $note_sufix
+ ))
+ .help(concat!("consider ", $help_sufix))
+ },
+ )
}};
}
- let span = match source {
- LetSource::LetElse(span) => span,
- _ => span,
- };
- tcx.struct_span_lint_hir(IRREFUTABLE_LET_PATTERNS, id, span, |lint| match source {
+ match source {
LetSource::GenericLet => {
emit_diag!(lint, "`let`", "`let` is useless", "removing `let`");
}
@@ -677,7 +696,7 @@ fn irrefutable_let_patterns(
"instead using a `loop { ... }` with a `let` inside it"
);
}
- });
+ };
}
fn is_let_irrefutable<'p, 'tcx>(
@@ -985,8 +1004,8 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
}
/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
-fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId, span: Span) -> bool {
- !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx.at(span), cx.param_env)
+fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool {
+ !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env)
}
/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
@@ -1012,7 +1031,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
// Get the binding move, extract the mutability if by-ref.
let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) {
- Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id, pat.span) => {
+ Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => {
// We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
let mut conflicts_ref = Vec::new();
sub.each_binding(|_, hir_id, span, _| {
@@ -1051,7 +1070,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
(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.
},
- Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => {
+ Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => {
conflicts_move.push((span, name)) // `ref mut?` + by-move conflict.
}
Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
@@ -1136,10 +1155,14 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> L
let parent_parent = hir.get_parent_node(parent);
let parent_parent_node = hir.get(parent_parent);
- if let hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), span, .. }) =
- parent_parent_node
- {
- return LetSource::LetElse(*span);
+ match parent_parent_node {
+ hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), span, .. }) => {
+ return LetSource::LetElse(*span);
+ }
+ hir::Node::Arm(hir::Arm { guard: Some(hir::Guard::If(_)), .. }) => {
+ return LetSource::IfLetGuard;
+ }
+ _ => {}
}
let parent_parent_parent = hir.get_parent_node(parent_parent);
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 b58685e89..ad12e0116 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
@@ -1,3 +1,4 @@
+use rustc_errors::DelayDm;
use rustc_hir as hir;
use rustc_index::vec::Idx;
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -27,14 +28,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
span: Span,
mir_structural_match_violation: bool,
) -> Box<Pat<'tcx>> {
- self.tcx.infer_ctxt().enter(|infcx| {
- let mut convert = ConstToPat::new(self, id, span, infcx);
- convert.to_pat(cv, mir_structural_match_violation)
- })
+ let infcx = self.tcx.infer_ctxt().build();
+ let mut convert = ConstToPat::new(self, id, span, infcx);
+ convert.to_pat(cv, mir_structural_match_violation)
}
}
-struct ConstToPat<'a, 'tcx> {
+struct ConstToPat<'tcx> {
id: hir::HirId,
span: Span,
param_env: ty::ParamEnv<'tcx>,
@@ -54,7 +54,7 @@ struct ConstToPat<'a, 'tcx> {
behind_reference: Cell<bool>,
// inference context used for checking `T: Structural` bounds.
- infcx: InferCtxt<'a, 'tcx>,
+ infcx: InferCtxt<'tcx>,
include_lint_checks: bool,
@@ -70,21 +70,19 @@ mod fallback_to_const_ref {
/// hoops to get a reference to the value.
pub(super) struct FallbackToConstRef(());
- pub(super) fn fallback_to_const_ref<'a, 'tcx>(
- c2p: &super::ConstToPat<'a, 'tcx>,
- ) -> FallbackToConstRef {
+ pub(super) fn fallback_to_const_ref<'tcx>(c2p: &super::ConstToPat<'tcx>) -> FallbackToConstRef {
assert!(c2p.behind_reference.get());
FallbackToConstRef(())
}
}
use fallback_to_const_ref::{fallback_to_const_ref, FallbackToConstRef};
-impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
+impl<'tcx> ConstToPat<'tcx> {
fn new(
pat_ctxt: &PatCtxt<'_, 'tcx>,
id: hir::HirId,
span: Span,
- infcx: InferCtxt<'a, 'tcx>,
+ infcx: InferCtxt<'tcx>,
) -> Self {
trace!(?pat_ctxt.typeck_results.hir_owner);
ConstToPat {
@@ -205,9 +203,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
self.span,
- |lint| {
- lint.build(&msg).emit();
- },
+ msg,
+ |lint| lint,
);
} else {
debug!(
@@ -286,9 +283,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id,
span,
- |lint| {
- lint.build("floating-point types cannot be used in patterns").emit();
- },
+ "floating-point types cannot be used in patterns",
+ |lint| lint,
);
}
PatKind::Constant { value: cv }
@@ -340,15 +336,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id,
span,
- |lint| {
- let msg = format!(
+ DelayDm(|| {
+ format!(
"to use a constant of type `{}` in a pattern, \
`{}` must be annotated with `#[derive(PartialEq, Eq)]`",
cv.ty(),
cv.ty(),
- );
- lint.build(&msg).emit();
- },
+ )
+ }),
+ |lint| lint,
);
}
// Since we are behind a reference, we can just bubble the error up so we get a
@@ -488,7 +484,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
self.span,
- |lint| {lint.build(&msg).emit();},
+ msg,
+ |lint| lint,
);
}
PatKind::Constant { value: cv }
@@ -509,7 +506,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
// convert the dereferenced constant to a pattern that is the sub-pattern of the
// deref pattern.
_ => {
- if !pointee_ty.is_sized(tcx.at(span), param_env) {
+ if !pointee_ty.is_sized(tcx, param_env) {
// `tcx.deref_mir_constant()` below will ICE with an unsized type
// (except slices, which are handled in a separate arm above).
let msg = format!("cannot use unsized non-slice type `{}` in constant patterns", pointee_ty);
@@ -537,7 +534,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
PatKind::Constant { value: cv }
}
- ty::RawPtr(pointee) if pointee.ty.is_sized(tcx.at(span), param_env) => {
+ ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => {
PatKind::Constant { value: cv }
}
// FIXME: these can have very surprising behaviour where optimization levels or other
@@ -556,9 +553,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::POINTER_STRUCTURAL_MATCH,
id,
span,
- |lint| {
- lint.build(msg).emit();
- },
+ msg,
+ |lint| lint,
);
}
PatKind::Constant { value: cv }
@@ -594,9 +590,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
id,
span,
- |lint| {
- lint.build(&msg).emit();
- },
+ msg,
+ |lint| lint,
);
}
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 5105f059f..595abc8f6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -299,10 +299,10 @@ impl IntRange {
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
hir_id,
pcx.span,
+ "multiple patterns overlap on their endpoints",
|lint| {
- let mut err = lint.build("multiple patterns overlap on their endpoints");
for (int_range, span) in overlaps {
- err.span_label(
+ lint.span_label(
span,
&format!(
"this range overlaps on `{}`...",
@@ -310,9 +310,9 @@ impl IntRange {
),
);
}
- err.span_label(pcx.span, "... with this range");
- err.note("you likely meant to write mutually exclusive ranges");
- err.emit();
+ lint.span_label(pcx.span, "... with this range");
+ lint.note("you likely meant to write mutually exclusive ranges");
+ lint
},
);
}
@@ -988,10 +988,12 @@ impl<'tcx> SplitWildcard<'tcx> {
.filter(|(_, v)| {
// If `exhaustive_patterns` is enabled, we exclude variants known to be
// uninhabited.
- let is_uninhabited = is_exhaustive_pat_feature
- && v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env)
- .contains(cx.tcx, cx.module);
- !is_uninhabited
+ !is_exhaustive_pat_feature
+ || v.inhabited_predicate(cx.tcx, *def).subst(cx.tcx, substs).apply(
+ cx.tcx,
+ cx.param_env,
+ cx.module,
+ )
})
.map(|(idx, _)| Variant(idx))
.collect();
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 0edf6a983..2526522a2 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -86,7 +86,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// ```
//
// the type assigned to `Some(n)` in `unadjusted_pat` would be `Option<i32>` (this is
- // determined in rustc_typeck::check::match). The adjustments would be
+ // determined in rustc_hir_analysis::check::match). The adjustments would be
//
// `vec![&&Option<i32>, &Option<i32>]`.
//
@@ -200,6 +200,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
}
}
+ #[instrument(skip(self), level = "debug")]
fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
let mut ty = self.typeck_results.node_type(pat.hir_id);
let mut span = pat.span;
@@ -432,7 +433,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
| DefKind::AssocTy,
_,
)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
_ => {
let pattern_error = match res {
@@ -684,7 +686,7 @@ macro_rules! ClonePatternFoldableImpls {
}
ClonePatternFoldableImpls! { <'tcx>
- Span, Field, Mutability, Symbol, LocalVarId, usize, ty::Const<'tcx>,
+ Span, Field, Mutability, Symbol, LocalVarId, usize,
Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>,
SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>,
UserTypeProjection, CanonicalUserTypeAnnotation<'tcx>
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 115d34ff8..8dc9976ea 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -746,7 +746,7 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
/// Report that a match of a `non_exhaustive` enum marked with `non_exhaustive_omitted_patterns`
/// is not exhaustive enough.
///
-/// NB: The partner lint for structs lives in `compiler/rustc_typeck/src/check/pat.rs`.
+/// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>,
scrut_ty: Ty<'tcx>,
@@ -754,9 +754,8 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
hir_id: HirId,
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
) {
- cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, |build| {
+ cx.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, hir_id, sp, "some variants are not matched explicitly", |lint| {
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
- let mut lint = build.build("some variants are not matched explicitly");
lint.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns));
lint.help(
"ensure that all variants are matched explicitly by adding the suggested match arms",
@@ -765,7 +764,7 @@ fn lint_non_exhaustive_omitted_patterns<'p, 'tcx>(
"the matched value is of type `{}` and the `non_exhaustive_omitted_patterns` attribute was found",
scrut_ty,
));
- lint.emit();
+ lint
});
}
@@ -842,7 +841,15 @@ fn is_useful<'p, 'tcx>(
}
}
} else {
- let ty = v.head().ty();
+ let mut ty = v.head().ty();
+
+ // Opaque types can't get destructured/split, but the patterns can
+ // actually hint at hidden types, so we use the patterns' types instead.
+ if let ty::Opaque(..) = ty.kind() {
+ if let Some(row) = rows.first() {
+ ty = row.head().ty();
+ }
+ }
let is_non_exhaustive = cx.is_foreign_non_exhaustive_enum(ty);
debug!("v.head: {:?}, v.span: {:?}", v.head(), v.head().span());
let pcx = &PatCtxt { cx, ty, span: v.head().span(), is_top_level, is_non_exhaustive };
@@ -878,7 +885,7 @@ fn is_useful<'p, 'tcx>(
// that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
// To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
if is_non_exhaustive_and_wild
- // We check that the match has a wildcard pattern and that that wildcard is useful,
+ // We check that the match has a wildcard pattern and that wildcard is useful,
// meaning there are variants that are covered by the wildcard. Without the check
// for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
&& usefulness.is_useful() && matches!(witness_preference, RealArm)
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 385e9ba74..324644b67 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
polonius-engine = "0.13.0"
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index c0b0cc3c5..23403628c 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -823,9 +823,10 @@ where
// tmp = &raw mut P;
// cur = tmp as *mut T;
// end = Offset(cur, len);
+ let mir_cast_kind = ty::cast::mir_cast_kind(iter_ty, tmp_ty);
vec![
self.assign(tmp, Rvalue::AddressOf(Mutability::Mut, self.place)),
- self.assign(cur, Rvalue::Cast(CastKind::Misc, Operand::Move(tmp), iter_ty)),
+ self.assign(cur, Rvalue::Cast(mir_cast_kind, Operand::Move(tmp), iter_ty)),
self.assign(
length_or_end,
Rvalue::BinaryOp(
@@ -893,7 +894,7 @@ where
}
ty::Slice(ety) => self.open_drop_for_array(*ety, None),
- _ => bug!("open drop from non-ADT `{:?}`", ty),
+ _ => span_bug!(self.source_info.span, "open drop from non-ADT `{:?}`", ty),
}
}
diff --git a/compiler/rustc_mir_dataflow/src/errors.rs b/compiler/rustc_mir_dataflow/src/errors.rs
index cc1425787..cfacc0ec3 100644
--- a/compiler/rustc_mir_dataflow/src/errors.rs
+++ b/compiler/rustc_mir_dataflow/src/errors.rs
@@ -1,70 +1,70 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::path_must_end_in_filename)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_path_must_end_in_filename)]
pub(crate) struct PathMustEndInFilename {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::unknown_formatter)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_unknown_formatter)]
pub(crate) struct UnknownFormatter {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::duplicate_values_for)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_duplicate_values_for)]
pub(crate) struct DuplicateValuesFor {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::requires_an_argument)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_requires_an_argument)]
pub(crate) struct RequiresAnArgument {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::stop_after_dataflow_ended_compilation)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_stop_after_dataflow_ended_compilation)]
pub(crate) struct StopAfterDataFlowEndedCompilation;
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::peek_must_be_place_or_ref_place)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_peek_must_be_place_or_ref_place)]
pub(crate) struct PeekMustBePlaceOrRefPlace {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::peek_must_be_not_temporary)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_peek_must_be_not_temporary)]
pub(crate) struct PeekMustBeNotTemporary {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::peek_bit_not_set)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_peek_bit_not_set)]
pub(crate) struct PeekBitNotSet {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::peek_argument_not_a_local)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_peek_argument_not_a_local)]
pub(crate) struct PeekArgumentNotALocal {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(mir_dataflow::peek_argument_untracked)]
+#[derive(Diagnostic)]
+#[diag(mir_dataflow_peek_argument_untracked)]
pub(crate) struct PeekArgumentUntracked {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index b45c32ee9..b471d04fd 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -1,7 +1,6 @@
#![feature(associated_type_defaults)]
#![feature(box_patterns)]
#![feature(exact_size_is_empty)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(once_cell)]
#![feature(stmt_expr_attributes)]
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
index 28936274b..7806e8f45 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
@@ -48,6 +48,7 @@ impl<'tcx> Lift for PlaceElem<'tcx> {
match *self {
ProjectionElem::Deref => ProjectionElem::Deref,
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty.lift()),
+ ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty.lift()),
ProjectionElem::Index(ref i) => ProjectionElem::Index(i.lift()),
ProjectionElem::Subslice { from, to, from_end } => {
ProjectionElem::Subslice { from, to, from_end }
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 85b7a4af5..53545cff0 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
itertools = "0.10.1"
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 8838b14c5..fa5f392fa 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{DiagnosticBuilder, LintDiagnosticBuilder};
+use rustc_errors::{DiagnosticBuilder, DiagnosticMessage};
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
@@ -63,7 +63,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
place: &Place<'tcx>,
const_item: DefId,
location: Location,
- decorate: impl for<'b> FnOnce(LintDiagnosticBuilder<'b, ()>) -> DiagnosticBuilder<'b, ()>,
+ msg: impl Into<DiagnosticMessage>,
+ decorate: impl for<'a, 'b> FnOnce(
+ &'a mut DiagnosticBuilder<'b, ()>,
+ ) -> &'a mut DiagnosticBuilder<'b, ()>,
) {
// Don't lint on borrowing/assigning when a dereference is involved.
// If we 'leave' the temporary via a dereference, we must
@@ -84,10 +87,10 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
CONST_ITEM_MUTATION,
lint_root,
source_info.span,
+ msg,
|lint| {
decorate(lint)
.span_note(self.tcx.def_span(const_item), "`const` item defined here")
- .emit();
},
);
}
@@ -102,10 +105,8 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
// so emitting a lint would be redundant.
if !lhs.projection.is_empty() {
if let Some(def_id) = self.is_const_item_without_destructor(lhs.local) {
- self.lint_const_item_usage(&lhs, def_id, loc, |lint| {
- let mut lint = lint.build("attempting to modify a `const` item");
- lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified");
- lint
+ self.lint_const_item_usage(&lhs, def_id, loc, "attempting to modify a `const` item",|lint| {
+ lint.note("each usage of a `const` item creates a new temporary; the original `const` item will not be modified")
})
}
}
@@ -137,8 +138,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
});
let lint_loc =
if method_did.is_some() { self.body.terminator_loc(loc.block) } else { loc };
- self.lint_const_item_usage(place, def_id, lint_loc, |lint| {
- let mut lint = lint.build("taking a mutable reference to a `const` item");
+ self.lint_const_item_usage(place, def_id, lint_loc, "taking a mutable reference to a `const` item", |lint| {
lint
.note("each usage of a `const` item creates a new temporary")
.note("the mutable reference will refer to this temporary, not the original `const` item");
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index 3b7ba3f9a..51abcf511 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -33,21 +33,27 @@ struct PackedRefChecker<'a, 'tcx> {
fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let lint_hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
- tcx.struct_span_lint_hir(UNALIGNED_REFERENCES, lint_hir_id, tcx.def_span(def_id), |lint| {
- // FIXME: when we make this a hard error, this should have its
- // own error code.
- let 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
- );
- lint.build(message).emit();
- });
+ // 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> {
@@ -86,8 +92,9 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
UNALIGNED_REFERENCES,
lint_root,
source_info.span,
+ "reference to packed field is unaligned",
|lint| {
- lint.build("reference to packed field is unaligned")
+ lint
.note(
"fields of packed structs are not properly aligned, and creating \
a misaligned reference is undefined behavior (even if that \
@@ -98,7 +105,6 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
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 beff19a3a..f8f04214a 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -312,7 +312,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
} else if !place
.ty(self.body, self.tcx)
.ty
- .is_freeze(self.tcx.at(self.source_info.span), self.param_env)
+ .is_freeze(self.tcx, self.param_env)
{
UnsafetyViolationDetails::BorrowOfLayoutConstrainedField
} else {
@@ -489,21 +489,20 @@ fn unsafety_check_result<'tcx>(
fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
let span = tcx.sess.source_map().guess_head_span(tcx.hir().span(id));
- tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, |lint| {
- let msg = "unnecessary `unsafe` block";
- let mut db = lint.build(msg);
- db.span_label(span, msg);
+ let msg = "unnecessary `unsafe` block";
+ tcx.struct_span_lint_hir(UNUSED_UNSAFE, id, span, msg, |lint| {
+ lint.span_label(span, msg);
match kind {
UnusedUnsafe::Unused => {}
UnusedUnsafe::InUnsafeBlock(id) => {
- db.span_label(
+ lint.span_label(
tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
"because it's nested under this `unsafe` block",
);
}
}
- db.emit();
+ lint
});
}
@@ -543,15 +542,8 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
UNSAFE_OP_IN_UNSAFE_FN,
lint_root,
source_info.span,
- |lint| {
- lint.build(&format!(
- "{} is unsafe and requires unsafe block (error E0133)",
- description,
- ))
- .span_label(source_info.span, description)
- .note(note)
- .emit();
- },
+ format!("{} is unsafe and requires unsafe block (error E0133)", description,),
+ |lint| lint.span_label(source_info.span, description).note(note),
),
}
}
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 7a2a15a84..4e4515888 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -17,7 +17,7 @@ use rustc_middle::mir::{
RETURN_PLACE,
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_span::{def_id::DefId, Span};
use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
@@ -471,7 +471,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}
- self.ecx.mir_const_to_op(&c.literal, None).ok()
+ self.ecx.const_to_op(&c.literal, None).ok()
}
/// Returns the value, if any, of evaluating `place`.
@@ -633,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
- .is_sized(self.ecx.tcx, self.param_env)
+ .is_sized(*self.ecx.tcx, self.param_env)
{
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 37e78f4ac..479c4e577 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -16,12 +16,12 @@ use rustc_index::bit_set::BitSet;
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{
- AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place,
- Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator,
- TerminatorKind, UnOp, RETURN_PLACE,
+ AssertKind, BinOp, Body, Constant, Local, LocalDecl, Location, Operand, Place, Rvalue,
+ SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
+ UnOp, RETURN_PLACE,
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, ConstInt, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable};
use rustc_session::lint;
use rustc_span::Span;
@@ -286,39 +286,22 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
/// Returns the value, if any, of evaluating `c`.
- fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
+ fn eval_constant(
+ &mut self,
+ c: &Constant<'tcx>,
+ _source_info: SourceInfo,
+ ) -> Option<OpTy<'tcx>> {
// FIXME we need to revisit this for #67176
if c.needs_subst() {
return None;
}
- match self.ecx.mir_const_to_op(&c.literal, None) {
+ match self.ecx.const_to_op(&c.literal, None) {
Ok(op) => Some(op),
Err(error) => {
let tcx = self.ecx.tcx.at(c.span);
let err = ConstEvalErr::new(&self.ecx, error, Some(c.span));
- if let Some(lint_root) = self.lint_root(source_info) {
- let lint_only = match c.literal {
- ConstantKind::Ty(ct) => ct.needs_subst(),
- ConstantKind::Unevaluated(
- ty::Unevaluated { def: _, substs: _, promoted: Some(_) },
- _,
- ) => {
- // Promoteds must lint and not error as the user didn't ask for them
- true
- }
- ConstantKind::Unevaluated(..) | ConstantKind::Val(..) => c.needs_subst(),
- };
- if lint_only {
- // Out of backwards compatibility we cannot report hard errors in unused
- // generic functions using associated constants of the generic parameters.
- err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
- } else {
- err.report_as_error(tcx, "erroneous constant used");
- }
- } else {
- err.report_as_error(tcx, "erroneous constant used");
- }
+ err.report_as_error(tcx, "erroneous constant used");
None
}
}
@@ -347,10 +330,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
panic: AssertKind<impl std::fmt::Debug>,
) {
if let Some(lint_root) = self.lint_root(source_info) {
- self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| {
- let mut err = lint.build(message);
- err.span_label(source_info.span, format!("{:?}", panic));
- err.emit();
+ self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, message, |lint| {
+ lint.span_label(source_info.span, format!("{:?}", panic))
});
}
}
@@ -519,7 +500,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
}
if !rvalue
.ty(&self.ecx.frame().body.local_decls, *self.ecx.tcx)
- .is_sized(self.ecx.tcx, self.param_env)
+ .is_sized(*self.ecx.tcx, self.param_env)
{
// the interpreter doesn't support unsized locals (only unsized arguments),
// but rustc does (in a kinda broken way), so we have to skip them here
diff --git a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
index f5e8b6565..f753caa91 100644
--- a/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
+++ b/compiler/rustc_mir_transform/src/coverage/test_macros/Cargo.toml
@@ -5,4 +5,3 @@ edition = "2021"
[lib]
proc-macro = true
-doctest = false
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
new file mode 100644
index 000000000..28b1c5a48
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -0,0 +1,248 @@
+//! Deduces supplementary parameter attributes from MIR.
+//!
+//! Deduced parameter attributes are those that can only be soundly determined by examining the
+//! body of the function instead of just the signature. These can be useful for optimization
+//! purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+//! dependent crates can use them.
+
+use rustc_hir::def_id::DefId;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE};
+use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
+
+/// A visitor that determines which arguments have been mutated. We can't use the mutability field
+/// on LocalDecl for this because it has no meaning post-optimization.
+struct DeduceReadOnly {
+ /// Each bit is indexed by argument number, starting at zero (so 0 corresponds to local decl
+ /// 1). The bit is true if the argument may have been mutated or false if we know it hasn't
+ /// been up to the point we're at.
+ mutable_args: BitSet<usize>,
+}
+
+impl DeduceReadOnly {
+ /// Returns a new DeduceReadOnly instance.
+ fn new(arg_count: usize) -> Self {
+ Self { mutable_args: BitSet::new_empty(arg_count) }
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
+ fn visit_local(&mut self, local: Local, mut context: PlaceContext, _: Location) {
+ // We're only interested in arguments.
+ if local == RETURN_PLACE || local.index() > self.mutable_args.domain_size() {
+ return;
+ }
+
+ // Replace place contexts that are moves with copies. This is safe in all cases except
+ // function argument position, which we already handled in `visit_terminator()` by using the
+ // ArgumentChecker. See the comment in that method for more details.
+ //
+ // In the future, we might want to move this out into a separate pass, but for now let's
+ // just do it on the fly because that's faster.
+ if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)) {
+ context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+ }
+
+ match context {
+ PlaceContext::MutatingUse(..)
+ | PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) => {
+ // This is a mutation, so mark it as such.
+ self.mutable_args.insert(local.index() - 1);
+ }
+ PlaceContext::NonMutatingUse(..) | PlaceContext::NonUse(..) => {
+ // Not mutating, so it's fine.
+ }
+ }
+ }
+
+ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+ // OK, this is subtle. Suppose that we're trying to deduce whether `x` in `f` is read-only
+ // and we have the following:
+ //
+ // fn f(x: BigStruct) { g(x) }
+ // fn g(mut y: BigStruct) { y.foo = 1 }
+ //
+ // If, at the generated MIR level, `f` turned into something like:
+ //
+ // fn f(_1: BigStruct) -> () {
+ // let mut _0: ();
+ // bb0: {
+ // _0 = g(move _1) -> bb1;
+ // }
+ // ...
+ // }
+ //
+ // then it would be incorrect to mark `x` (i.e. `_1`) as `readonly`, because `g`'s write to
+ // its copy of the indirect parameter would actually be a write directly to the pointer that
+ // `f` passes. Note that function arguments are the only situation in which this problem can
+ // arise: every other use of `move` in MIR doesn't actually write to the value it moves
+ // from.
+ //
+ // Anyway, right now this situation doesn't actually arise in practice. Instead, the MIR for
+ // that function looks like this:
+ //
+ // fn f(_1: BigStruct) -> () {
+ // let mut _0: ();
+ // let mut _2: BigStruct;
+ // bb0: {
+ // _2 = move _1;
+ // _0 = g(move _2) -> bb1;
+ // }
+ // ...
+ // }
+ //
+ // Because of that extra move that MIR construction inserts, `x` (i.e. `_1`) can *in
+ // practice* safely be marked `readonly`.
+ //
+ // To handle the possibility that other optimizations (for example, destination propagation)
+ // might someday generate MIR like the first example above, we panic upon seeing an argument
+ // to *our* function that is directly moved into *another* function as an argument. Having
+ // eliminated that problematic case, we can safely treat moves as copies in this analysis.
+ //
+ // In the future, if MIR optimizations cause arguments of a caller to be directly moved into
+ // the argument of a callee, we can just add that argument to `mutated_args` instead of
+ // panicking.
+ //
+ // Note that, because the problematic MIR is never actually generated, we can't add a test
+ // case for this.
+
+ if let TerminatorKind::Call { ref args, .. } = terminator.kind {
+ for arg in args {
+ if let Operand::Move(_) = *arg {
+ // ArgumentChecker panics if a direct move of an argument from a caller to a
+ // callee was detected.
+ //
+ // If, in the future, MIR optimizations cause arguments to be moved directly
+ // from callers to callees, change the panic to instead add the argument in
+ // question to `mutating_uses`.
+ ArgumentChecker::new(self.mutable_args.domain_size())
+ .visit_operand(arg, location)
+ }
+ }
+ };
+
+ self.super_terminator(terminator, location);
+ }
+}
+
+/// A visitor that simply panics if a direct move of an argument from a caller to a callee was
+/// detected.
+struct ArgumentChecker {
+ /// The number of arguments to the calling function.
+ arg_count: usize,
+}
+
+impl ArgumentChecker {
+ /// Creates a new ArgumentChecker.
+ fn new(arg_count: usize) -> Self {
+ Self { arg_count }
+ }
+}
+
+impl<'tcx> Visitor<'tcx> for ArgumentChecker {
+ fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
+ // Check to make sure that, if this local is an argument, we didn't move directly from it.
+ if matches!(context, PlaceContext::NonMutatingUse(NonMutatingUseContext::Move))
+ && local != RETURN_PLACE
+ && local.index() <= self.arg_count
+ {
+ // If, in the future, MIR optimizations cause arguments to be moved directly from
+ // callers to callees, change this panic to instead add the argument in question to
+ // `mutating_uses`.
+ panic!("Detected a direct move from a caller's argument to a callee's argument!")
+ }
+ }
+}
+
+/// Returns true if values of a given type will never be passed indirectly, regardless of ABI.
+fn type_will_always_be_passed_directly<'tcx>(ty: Ty<'tcx>) -> bool {
+ matches!(
+ ty.kind(),
+ ty::Bool
+ | ty::Char
+ | ty::Float(..)
+ | ty::Int(..)
+ | ty::RawPtr(..)
+ | ty::Ref(..)
+ | ty::Slice(..)
+ | ty::Uint(..)
+ )
+}
+
+/// Returns the deduced parameter attributes for a function.
+///
+/// Deduced parameter attributes are those that can only be soundly determined by examining the
+/// body of the function instead of just the signature. These can be useful for optimization
+/// purposes on a best-effort basis. We compute them here and store them into the crate metadata so
+/// dependent crates can use them.
+pub fn deduced_param_attrs<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [DeducedParamAttrs] {
+ // This computation is unfortunately rather expensive, so don't do it unless we're optimizing.
+ // Also skip it in incremental mode.
+ if tcx.sess.opts.optimize == OptLevel::No || tcx.sess.opts.incremental.is_some() {
+ return &[];
+ }
+
+ // If the Freeze language item isn't present, then don't bother.
+ if tcx.lang_items().freeze_trait().is_none() {
+ return &[];
+ }
+
+ // 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);
+ if matches!(fn_ty.kind(), ty::FnDef(..)) {
+ if fn_ty
+ .fn_sig(tcx)
+ .inputs()
+ .skip_binder()
+ .iter()
+ .cloned()
+ .all(type_will_always_be_passed_directly)
+ {
+ return &[];
+ }
+ }
+
+ // Don't deduce any attributes for functions that have no MIR.
+ if !tcx.is_mir_available(def_id) {
+ return &[];
+ }
+
+ // Deduced attributes for other crates should be read from the metadata instead of via this
+ // function.
+ debug_assert!(def_id.is_local());
+
+ // Grab the optimized MIR. Analyze it to determine which arguments have been mutated.
+ let body: &Body<'tcx> = tcx.optimized_mir(def_id);
+ let mut deduce_read_only = DeduceReadOnly::new(body.arg_count);
+ deduce_read_only.visit_body(body);
+
+ // Set the `readonly` attribute for every argument that we concluded is immutable and that
+ // contains no UnsafeCells.
+ //
+ // FIXME: This is overly conservative around generic parameters: `is_freeze()` will always
+ // return false for them. For a description of alternatives that could do a better job here,
+ // see [1].
+ //
+ // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997
+ let mut deduced_param_attrs = tcx.arena.alloc_from_iter(
+ body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
+ |(arg_index, local_decl)| DeducedParamAttrs {
+ read_only: !deduce_read_only.mutable_args.contains(arg_index)
+ && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()),
+ },
+ ),
+ );
+
+ // Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
+ // default set of attributes, so we don't have to store them explicitly. Pop them off to save a
+ // few bytes in metadata.
+ while deduced_param_attrs.last() == Some(&DeducedParamAttrs::default()) {
+ let last_index = deduced_param_attrs.len() - 1;
+ deduced_param_attrs = &mut deduced_param_attrs[0..last_index];
+ }
+
+ deduced_param_attrs
+}
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 294af2455..ef8d6bb65 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -8,7 +8,6 @@ use rustc_index::vec::Idx;
use rustc_middle::mir::patch::MirPatch;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{Ty, TyCtxt};
/// Constructs the types used when accessing a Box's pointer
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 7522a50a8..1244c1802 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -106,14 +106,12 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
.lint_root;
let span = terminator.source_info.span;
- tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, |lint| {
- let msg = match fn_def_id {
- Some(_) => "call to foreign function with FFI-unwind ABI",
- None => "call to function pointer with FFI-unwind ABI",
- };
- let mut db = lint.build(msg);
- db.span_label(span, msg);
- db.emit();
+ let msg = match fn_def_id {
+ Some(_) => "call to foreign function with FFI-unwind ABI",
+ None => "call to function pointer with FFI-unwind ABI",
+ };
+ tcx.struct_span_lint_hir(FFI_UNWIND_CALLS, lint_root, span, msg, |lint| {
+ lint.span_label(span, msg)
});
tainted = true;
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 2e4fe1e3e..469566694 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -3,11 +3,7 @@ use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
-use rustc_middle::ty::{
- self,
- subst::{GenericArgKind, Subst, SubstsRef},
- EarlyBinder, PredicateKind, Ty, TyCtxt,
-};
+use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_span::{symbol::sym, Span};
use rustc_target::spec::abi::Abi;
@@ -183,11 +179,15 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder();
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" };
- self.tcx.struct_span_lint_hir(FUNCTION_ITEM_REFERENCES, lint_root, span, |lint| {
- lint.build("taking a reference to a function item does not give a function pointer")
- .span_suggestion(
+ self.tcx.struct_span_lint_hir(
+ FUNCTION_ITEM_REFERENCES,
+ lint_root,
+ span,
+ "taking a reference to a function item does not give a function pointer",
+ |lint| {
+ lint.span_suggestion(
span,
- &format!("cast `{}` to obtain a function pointer", ident),
+ format!("cast `{}` to obtain a function pointer", ident),
format!(
"{} as {}{}fn({}{}){}",
if params.is_empty() { ident } else { format!("{}::<{}>", ident, params) },
@@ -199,7 +199,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
),
Applicability::Unspecified,
)
- .emit();
- });
+ },
+ );
}
}
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 705cf776f..c833de3a8 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -61,9 +61,8 @@ use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::dump_mir;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
-use rustc_middle::ty::GeneratorSubsts;
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
+use rustc_middle::ty::{GeneratorSubsts, SubstsRef};
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
};
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index d00a384cb..780b91d92 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -7,7 +7,6 @@ use rustc_index::vec::Idx;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
use rustc_session::config::OptLevel;
use rustc_span::def_id::DefId;
@@ -606,7 +605,7 @@ impl<'tcx> Inliner<'tcx> {
caller_body.required_consts.extend(
callee_body.required_consts.iter().copied().filter(|&ct| match ct.literal {
ConstantKind::Ty(_) => {
- bug!("should never encounter ty::Unevaluated in `required_consts`")
+ bug!("should never encounter ty::UnevaluatedConst in `required_consts`")
}
ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => true,
}),
@@ -978,6 +977,21 @@ impl Integrator<'_, '_> {
trace!("mapping block `{:?}` to `{:?}`", block, new);
new
}
+
+ fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
+ if self.in_cleanup_block {
+ if unwind.is_some() {
+ bug!("cleanup on cleanup block");
+ }
+ return unwind;
+ }
+
+ match unwind {
+ Some(target) => Some(self.map_block(target)),
+ // Add an unwind edge to the original call's cleanup block
+ None => self.cleanup_block,
+ }
+ }
}
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
@@ -1086,35 +1100,17 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::Drop { ref mut target, ref mut unwind, .. }
| TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
*target = self.map_block(*target);
- if let Some(tgt) = *unwind {
- *unwind = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this drop is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *unwind = self.cleanup_block;
- }
+ *unwind = self.map_unwind(*unwind);
}
TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
if let Some(ref mut tgt) = *target {
*tgt = self.map_block(*tgt);
}
- if let Some(tgt) = *cleanup {
- *cleanup = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this call is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
- }
+ *cleanup = self.map_unwind(*cleanup);
}
TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
*target = self.map_block(*target);
- if let Some(tgt) = *cleanup {
- *cleanup = Some(self.map_block(tgt));
- } else if !self.in_cleanup_block {
- // Unless this assert is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
- }
+ *cleanup = self.map_unwind(*cleanup);
}
TerminatorKind::Return => {
terminator.kind = if let Some(tgt) = self.callsite.target {
@@ -1142,11 +1138,8 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
if let Some(ref mut tgt) = *destination {
*tgt = self.map_block(*tgt);
- } else if !self.in_cleanup_block {
- // Unless this inline asm is in a cleanup block, add an unwind edge to
- // the original call's cleanup block
- *cleanup = self.cleanup_block;
}
+ *cleanup = self.map_unwind(*cleanup);
}
}
}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index e6fc85595..5be223254 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -1,7 +1,6 @@
#![allow(rustc::potential_query_instability)]
#![feature(box_patterns)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(never_type)]
@@ -57,6 +56,7 @@ mod const_prop_lint;
mod coverage;
mod dead_store_elimination;
mod deaggregator;
+mod deduce_param_attrs;
mod deduplicate_blocks;
mod deref_separator;
mod dest_prop;
@@ -71,7 +71,6 @@ mod inline;
mod instcombine;
mod lower_intrinsics;
mod lower_slice_len;
-mod marker;
mod match_branches;
mod multiple_return_terminators;
mod normalize_array_len;
@@ -140,6 +139,7 @@ pub fn provide(providers: &mut Providers) {
promoted_mir_of_const_arg: |tcx, (did, param_did)| {
promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
},
+ deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
..*providers
};
}
@@ -302,6 +302,7 @@ fn mir_const<'tcx>(
&simplify::SimplifyCfg::new("initial"),
&rustc_peek::SanityCheck, // Just a lint
],
+ None,
);
tcx.alloc_steal_mir(body)
}
@@ -341,6 +342,7 @@ fn mir_promoted<'tcx>(
&simplify::SimplifyCfg::new("promote-consts"),
&coverage::InstrumentCoverage,
],
+ Some(MirPhase::Analysis(AnalysisPhase::Initial)),
);
let promoted = promote_pass.promoted_fragments.into_inner();
@@ -408,10 +410,8 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
pm::run_passes(
tcx,
&mut body,
- &[
- &const_prop::ConstProp,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
- ],
+ &[&const_prop::ConstProp],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
}
}
@@ -473,6 +473,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>
&remove_uninit_drops::RemoveUninitDrops,
&simplify::SimplifyCfg::new("remove-false-edges"),
],
+ None,
);
check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
}
@@ -497,10 +498,9 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&cleanup_post_borrowck::CleanupNonCodegenStatements,
&simplify::SimplifyCfg::new("early-opt"),
&deref_separator::Derefer,
- &marker::PhaseChange(MirPhase::Analysis(AnalysisPhase::PostCleanup)),
];
- pm::run_passes(tcx, body, passes);
+ pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)));
}
/// Returns the sequence of passes that lowers analysis to runtime MIR.
@@ -525,9 +525,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// CTFE support for aggregates.
&deaggregator::Deaggregator,
&Lint(const_prop_lint::ConstProp),
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Initial)),
];
- pm::run_passes_no_validate(tcx, body, passes);
+ pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
}
/// Returns the sequence of passes that do the initial cleanup of runtime MIR.
@@ -536,10 +535,9 @@ fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&elaborate_box_derefs::ElaborateBoxDerefs,
&lower_intrinsics::LowerIntrinsics,
&simplify::SimplifyCfg::new("elaborate-drops"),
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::PostCleanup)),
];
- pm::run_passes(tcx, body, passes);
+ pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
}
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -590,10 +588,10 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
&deduplicate_blocks::DeduplicateBlocks,
// Some cleanup necessary at least for LLVM and potentially other codegen backends.
&add_call_guards::CriticalCallEdges,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
// Dump the end result for testing and debugging purposes.
&dump_mir::Marker("PreCodegen"),
],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
}
diff --git a/compiler/rustc_mir_transform/src/marker.rs b/compiler/rustc_mir_transform/src/marker.rs
deleted file mode 100644
index 06819fc1d..000000000
--- a/compiler/rustc_mir_transform/src/marker.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::borrow::Cow;
-
-use crate::MirPass;
-use rustc_middle::mir::{Body, MirPhase};
-use rustc_middle::ty::TyCtxt;
-
-/// Changes the MIR phase without changing the MIR itself.
-pub struct PhaseChange(pub MirPhase);
-
-impl<'tcx> MirPass<'tcx> for PhaseChange {
- fn phase_change(&self) -> Option<MirPhase> {
- Some(self.0)
- }
-
- fn name(&self) -> Cow<'_, str> {
- Cow::from(format!("PhaseChange-{:?}", self.0))
- }
-
- fn run_pass(&self, _: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {}
-}
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 67dae7146..230c6a7cb 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -66,10 +66,6 @@ where
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
self.1.run_pass(tcx, body)
}
-
- fn phase_change(&self) -> Option<MirPhase> {
- self.1.phase_change()
- }
}
/// Run the sequence of passes without validating the MIR after each pass. The MIR is still
@@ -78,23 +74,28 @@ pub fn run_passes_no_validate<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
) {
- run_passes_inner(tcx, body, passes, false);
+ run_passes_inner(tcx, body, passes, phase_change, false);
}
-pub fn run_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>]) {
- run_passes_inner(tcx, body, passes, true);
+/// The optional `phase_change` is applied after executing all the passes, if present
+pub fn run_passes<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ body: &mut Body<'tcx>,
+ passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
+) {
+ run_passes_inner(tcx, body, passes, phase_change, true);
}
fn run_passes_inner<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
passes: &[&dyn MirPass<'tcx>],
+ phase_change: Option<MirPhase>,
validate_each: bool,
) {
- let start_phase = body.phase;
- let mut cnt = 0;
-
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
trace!(?overridden_passes);
@@ -102,7 +103,6 @@ fn run_passes_inner<'tcx>(
for pass in passes {
let name = pass.name();
- // Gather information about what we should be doing for this pass
let overridden =
overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| {
trace!(
@@ -112,32 +112,44 @@ fn run_passes_inner<'tcx>(
);
*polarity
});
- let is_enabled = overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess));
- let new_phase = pass.phase_change();
- let dump_enabled = (is_enabled && pass.is_mir_dump_enabled()) || new_phase.is_some();
- let validate = (validate && is_enabled)
- || new_phase == Some(MirPhase::Runtime(RuntimePhase::Optimized));
+ if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
+ continue;
+ }
+
+ let dump_enabled = pass.is_mir_dump_enabled();
if dump_enabled {
- dump_mir(tcx, body, start_phase, &name, cnt, false);
- }
- if is_enabled {
- pass.run_pass(tcx, body);
+ dump_mir_for_pass(tcx, body, &name, false);
}
- if dump_enabled {
- dump_mir(tcx, body, start_phase, &name, cnt, true);
- cnt += 1;
+ if validate {
+ validate_body(tcx, body, format!("before pass {}", name));
}
- if let Some(new_phase) = pass.phase_change() {
- if body.phase >= new_phase {
- panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
- }
- body.phase = new_phase;
+ pass.run_pass(tcx, body);
+
+ if dump_enabled {
+ dump_mir_for_pass(tcx, body, &name, true);
}
if validate {
validate_body(tcx, body, format!("after pass {}", name));
}
+
+ body.pass_count += 1;
+ }
+
+ if let Some(new_phase) = phase_change {
+ if body.phase >= new_phase {
+ panic!("Invalid MIR phase transition from {:?} to {:?}", body.phase, new_phase);
+ }
+
+ body.phase = new_phase;
+
+ dump_mir_for_phase_change(tcx, body);
+ if validate || new_phase == MirPhase::Runtime(RuntimePhase::Optimized) {
+ validate_body(tcx, body, format!("after phase change to {}", new_phase));
+ }
+
+ body.pass_count = 1;
}
}
@@ -145,22 +157,33 @@ pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: Strin
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
}
-pub fn dump_mir<'tcx>(
+pub fn dump_mir_for_pass<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
- phase: MirPhase,
pass_name: &str,
- cnt: usize,
is_after: bool,
) {
- let phase_index = phase.phase_index();
+ let phase_index = body.phase.phase_index();
mir::dump_mir(
tcx,
- Some(&format_args!("{:03}-{:03}", phase_index, cnt)),
+ Some(&format_args!("{:03}-{:03}", phase_index, body.pass_count)),
pass_name,
if is_after { &"after" } else { &"before" },
body,
|_, _| Ok(()),
);
}
+
+pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
+ let phase_index = body.phase.phase_index();
+
+ mir::dump_mir(
+ tcx,
+ Some(&format_args!("{:03}-000", phase_index)),
+ &format!("{}", body.phase),
+ &"after",
+ body,
+ |_, _| Ok(()),
+ )
+}
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 882136200..4e8798b7a 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_middle::mir::*;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
use rustc_target::abi::VariantIdx;
@@ -17,7 +17,7 @@ use std::iter;
use crate::util::expand_aggregate;
use crate::{
- abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, marker,
+ abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator,
pass_manager as pm, remove_noop_landing_pads, simplify,
};
use rustc_middle::mir::patch::MirPatch;
@@ -97,8 +97,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
&simplify::SimplifyCfg::new("make_shim"),
&add_call_guards::CriticalCallEdges,
&abort_unwinding_calls::AbortUnwindingCalls,
- &marker::PhaseChange(MirPhase::Runtime(RuntimePhase::Optimized)),
],
+ Some(MirPhase::Runtime(RuntimePhase::Optimized)),
);
debug!("make_shim({:?}) = {:?}", instance, result);
@@ -312,7 +312,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -
let param_env = tcx.param_env(def_id);
let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
- let is_copy = self_ty.is_copy_modulo_regions(tcx.at(builder.span), param_env);
+ let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
let dest = Place::return_place();
let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 59ca04ec8..6ee5330b6 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index f1a25a60d..a71218e69 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1067,7 +1067,7 @@ fn find_vtable_types_for_unsizing<'tcx>(
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
let param_env = ty::ParamEnv::reveal_all();
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
- if ty.is_sized(tcx.at(DUMMY_SP), param_env) {
+ if ty.is_sized(tcx, param_env) {
return false;
}
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
@@ -1192,7 +1192,7 @@ struct RootCollector<'a, 'tcx> {
impl<'v> RootCollector<'_, 'v> {
fn process_item(&mut self, id: hir::ItemId) {
- match self.tcx.def_kind(id.def_id) {
+ match self.tcx.def_kind(id.owner_id) {
DefKind::Enum | DefKind::Struct | DefKind::Union => {
let item = self.tcx.hir().item(id);
match item.kind {
@@ -1203,12 +1203,14 @@ impl<'v> RootCollector<'_, 'v> {
if self.mode == MonoItemCollectionMode::Eager {
debug!(
"RootCollector: ADT drop-glue for {}",
- self.tcx.def_path_str(item.def_id.to_def_id())
+ self.tcx.def_path_str(item.owner_id.to_def_id())
);
- let ty =
- Instance::new(item.def_id.to_def_id(), InternalSubsts::empty())
- .ty(self.tcx, ty::ParamEnv::reveal_all());
+ 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);
}
}
@@ -1219,23 +1221,23 @@ impl<'v> RootCollector<'_, 'v> {
DefKind::GlobalAsm => {
debug!(
"RootCollector: ItemKind::GlobalAsm({})",
- self.tcx.def_path_str(id.def_id.to_def_id())
+ self.tcx.def_path_str(id.owner_id.to_def_id())
);
self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
}
DefKind::Static(..) => {
debug!(
"RootCollector: ItemKind::Static({})",
- self.tcx.def_path_str(id.def_id.to_def_id())
+ self.tcx.def_path_str(id.owner_id.to_def_id())
);
- self.output.push(dummy_spanned(MonoItem::Static(id.def_id.to_def_id())));
+ self.output.push(dummy_spanned(MonoItem::Static(id.owner_id.to_def_id())));
}
DefKind::Const => {
// const items only generate mono items if they are
// actually used somewhere. Just declaring them is insufficient.
// but even just declaring them must collect the items they refer to
- if let Ok(val) = self.tcx.const_eval_poly(id.def_id.to_def_id()) {
+ if let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id()) {
collect_const_value(self.tcx, val, &mut self.output);
}
}
@@ -1246,15 +1248,15 @@ impl<'v> RootCollector<'_, 'v> {
}
}
DefKind::Fn => {
- self.push_if_root(id.def_id);
+ self.push_if_root(id.owner_id.def_id);
}
_ => {}
}
}
fn process_impl_item(&mut self, id: hir::ImplItemId) {
- if matches!(self.tcx.def_kind(id.def_id), DefKind::AssocFn) {
- self.push_if_root(id.def_id);
+ if matches!(self.tcx.def_kind(id.owner_id), DefKind::AssocFn) {
+ self.push_if_root(id.owner_id.def_id);
}
}
@@ -1352,13 +1354,13 @@ fn create_mono_items_for_default_impls<'tcx>(
debug!(
"create_mono_items_for_default_impls(item={})",
- tcx.def_path_str(item.def_id.to_def_id())
+ tcx.def_path_str(item.owner_id.to_def_id())
);
- if let Some(trait_ref) = tcx.impl_trait_ref(item.def_id) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(item.owner_id) {
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.def_id);
+ 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;
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index d5f05e790..ce097b8d8 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,12 +1,12 @@
use std::path::PathBuf;
use rustc_errors::ErrorGuaranteed;
-use rustc_macros::{LintDiagnostic, SessionDiagnostic};
-use rustc_session::SessionDiagnostic;
+use rustc_errors::IntoDiagnostic;
+use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(monomorphize::recursion_limit)]
+#[derive(Diagnostic)]
+#[diag(monomorphize_recursion_limit)]
pub struct RecursionLimit {
#[primary_span]
pub span: Span,
@@ -14,26 +14,26 @@ pub struct RecursionLimit {
#[note]
pub def_span: Span,
pub def_path_str: String,
- #[note(monomorphize::written_to_path)]
+ #[note(monomorphize_written_to_path)]
pub was_written: Option<()>,
pub path: PathBuf,
}
-#[derive(SessionDiagnostic)]
-#[diag(monomorphize::type_length_limit)]
-#[help(monomorphize::consider_type_length_limit)]
+#[derive(Diagnostic)]
+#[diag(monomorphize_type_length_limit)]
+#[help(monomorphize_consider_type_length_limit)]
pub struct TypeLengthLimit {
#[primary_span]
pub span: Span,
pub shrunk: String,
- #[note(monomorphize::written_to_path)]
+ #[note(monomorphize_written_to_path)]
pub was_written: Option<()>,
pub path: PathBuf,
pub type_length: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(monomorphize::requires_lang_item)]
+#[derive(Diagnostic)]
+#[diag(monomorphize_requires_lang_item)]
pub struct RequiresLangItem {
pub lang_item: String,
}
@@ -44,13 +44,12 @@ pub struct UnusedGenericParams {
pub param_names: Vec<String>,
}
-impl SessionDiagnostic<'_> for UnusedGenericParams {
+impl IntoDiagnostic<'_> for UnusedGenericParams {
fn into_diagnostic(
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(rustc_errors::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,
@@ -63,7 +62,7 @@ impl SessionDiagnostic<'_> for UnusedGenericParams {
}
#[derive(LintDiagnostic)]
-#[diag(monomorphize::large_assignments)]
+#[diag(monomorphize_large_assignments)]
#[note]
pub struct LargeAssignmentsLint {
#[label]
@@ -72,12 +71,12 @@ pub struct LargeAssignmentsLint {
pub limit: u64,
}
-#[derive(SessionDiagnostic)]
-#[diag(monomorphize::unknown_partition_strategy)]
+#[derive(Diagnostic)]
+#[diag(monomorphize_unknown_partition_strategy)]
pub struct UnknownPartitionStrategy;
-#[derive(SessionDiagnostic)]
-#[diag(monomorphize::symbol_already_defined)]
+#[derive(Diagnostic)]
+#[diag(monomorphize_symbol_already_defined)]
pub struct SymbolAlreadyDefined {
#[primary_span]
pub span: Option<Span>,
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index ba6ce9fd4..42781bd25 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(array_windows)]
#![feature(control_flow_enum)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![deny(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_monomorphize/src/partitioning/default.rs b/compiler/rustc_monomorphize/src/partitioning/default.rs
index 15276569c..29009c480 100644
--- a/compiler/rustc_monomorphize/src/partitioning/default.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/default.rs
@@ -319,7 +319,7 @@ fn characteristic_def_id_of_mono_item<'tcx>(
Some(def_id)
}
MonoItem::Static(def_id) => Some(def_id),
- MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.to_def_id()),
+ MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.to_def_id()),
}
}
@@ -411,9 +411,9 @@ fn mono_item_visibility<'tcx>(
};
}
MonoItem::GlobalAsm(item_id) => {
- return if tcx.is_reachable_non_generic(item_id.def_id) {
+ return if tcx.is_reachable_non_generic(item_id.owner_id) {
*can_be_internalized = false;
- default_visibility(tcx, item_id.def_id.to_def_id(), false)
+ default_visibility(tcx, item_id.owner_id.to_def_id(), false)
} else {
Visibility::Hidden
};
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 71cab0232..650076c22 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -8,6 +8,7 @@
use rustc_hir::{def::DefKind, def_id::DefId, ConstContext};
use rustc_index::bit_set::FiniteBitSet;
use rustc_middle::mir::{
+ self,
visit::{TyContext, Visitor},
Constant, ConstantKind, Local, LocalDecl, Location,
};
@@ -275,9 +276,21 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
ConstantKind::Ty(c) => {
c.visit_with(self);
}
- ConstantKind::Val(_, ty) | ConstantKind::Unevaluated(_, ty) => {
- Visitor::visit_ty(self, ty, TyContext::Location(location))
+ ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs: _, promoted }, ty) => {
+ // Avoid considering `T` unused when constants are of the form:
+ // `<Self as Foo<T>>::foo::promoted[p]`
+ if let Some(p) = promoted {
+ if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self {
+ // If there is a promoted, don't look at the substs - since it will always contain
+ // the generic parameters, instead, traverse the promoted MIR.
+ let promoted = self.tcx.promoted_mir(def.did);
+ self.visit_body(&promoted[p]);
+ }
+ }
+
+ Visitor::visit_ty(self, ty, TyContext::Location(location));
}
+ ConstantKind::Val(_, ty) => Visitor::visit_ty(self, ty, TyContext::Location(location)),
}
}
@@ -289,7 +302,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.has_param_types_or_consts() {
+ if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -299,11 +312,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE
}
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs })
if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) =>
{
- assert_eq!(promoted, ());
-
self.visit_child_body(def.did, substs);
ControlFlow::CONTINUE
}
@@ -311,33 +322,9 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
}
}
- fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !constant.has_param_types_or_consts() {
- return ControlFlow::CONTINUE;
- }
-
- match constant {
- ConstantKind::Ty(ct) => ct.visit_with(self),
- ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _)
- // Avoid considering `T` unused when constants are of the form:
- // `<Self as Foo<T>>::foo::promoted[p]`
- if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
- {
- // If there is a promoted, don't look at the substs - since it will always contain
- // the generic parameters, instead, traverse the promoted MIR.
- let promoted = self.tcx.promoted_mir(def.did);
- self.visit_body(&promoted[p]);
- ControlFlow::CONTINUE
- }
- ConstantKind::Val(..) | ConstantKind::Unevaluated(..) => {
- constant.super_visit_with(self)
- }
- }
- }
-
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.has_param_types_or_consts() {
+ if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -374,7 +361,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.has_param_types_or_consts() {
+ if !c.has_non_region_param() {
return ControlFlow::CONTINUE;
}
@@ -392,7 +379,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.has_param_types_or_consts() {
+ if !ty.has_non_region_param() {
return ControlFlow::CONTINUE;
}
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index c6ca260e9..a5c94e164 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.0"
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
new file mode 100644
index 000000000..9b177c518
--- /dev/null
+++ b/compiler/rustc_parse/src/errors.rs
@@ -0,0 +1,1237 @@
+use rustc_ast::token::Token;
+use rustc_ast::Path;
+use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::symbol::Ident;
+use rustc_span::{Span, Symbol};
+
+use crate::parser::TokenDescription;
+
+#[derive(Diagnostic)]
+#[diag(parser_maybe_report_ambiguous_plus)]
+pub(crate) struct AmbiguousPlus {
+ pub sum_ty: String,
+ #[primary_span]
+ #[suggestion(code = "({sum_ty})")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_maybe_recover_from_bad_type_plus, code = "E0178")]
+pub(crate) struct BadTypePlus {
+ pub ty: String,
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: BadTypePlusSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum BadTypePlusSub {
+ #[suggestion(
+ parser_add_paren,
+ code = "{sum_with_parens}",
+ applicability = "machine-applicable"
+ )]
+ AddParen {
+ sum_with_parens: String,
+ #[primary_span]
+ span: Span,
+ },
+ #[label(parser_forgot_paren)]
+ ForgotParen {
+ #[primary_span]
+ span: Span,
+ },
+ #[label(parser_expect_path)]
+ ExpectPath {
+ #[primary_span]
+ span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_maybe_recover_from_bad_qpath_stage_2)]
+pub(crate) struct BadQPathStage2 {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "maybe-incorrect")]
+ pub span: Span,
+ pub ty: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_incorrect_semicolon)]
+pub(crate) struct IncorrectSemicolon<'a> {
+ #[primary_span]
+ #[suggestion_short(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ #[help]
+ pub opt_help: Option<()>,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_incorrect_use_of_await)]
+pub(crate) struct IncorrectUseOfAwait {
+ #[primary_span]
+ #[suggestion(parentheses_suggestion, code = "", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_incorrect_use_of_await)]
+pub(crate) struct IncorrectAwait {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(postfix_suggestion, code = "{expr}.await{question_mark}")]
+ pub sugg_span: (Span, Applicability),
+ pub expr: String,
+ pub question_mark: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_in_in_typo)]
+pub(crate) struct InInTypo {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub sugg_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_variable_declaration)]
+pub(crate) struct InvalidVariableDeclaration {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: InvalidVariableDeclarationSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum InvalidVariableDeclarationSub {
+ #[suggestion(parser_switch_mut_let_order, applicability = "maybe-incorrect", code = "let mut")]
+ SwitchMutLetOrder(#[primary_span] Span),
+ #[suggestion(
+ parser_missing_let_before_mut,
+ applicability = "machine-applicable",
+ code = "let mut"
+ )]
+ MissingLet(#[primary_span] Span),
+ #[suggestion(parser_use_let_not_auto, applicability = "machine-applicable", code = "let")]
+ UseLetNotAuto(#[primary_span] Span),
+ #[suggestion(parser_use_let_not_var, applicability = "machine-applicable", code = "let")]
+ UseLetNotVar(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_comparison_operator)]
+pub(crate) struct InvalidComparisonOperator {
+ #[primary_span]
+ pub span: Span,
+ pub invalid: String,
+ #[subdiagnostic]
+ pub sub: InvalidComparisonOperatorSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum InvalidComparisonOperatorSub {
+ #[suggestion_short(use_instead, applicability = "machine-applicable", code = "{correct}")]
+ Correctable {
+ #[primary_span]
+ span: Span,
+ invalid: String,
+ correct: String,
+ },
+ #[label(spaceship_operator_invalid)]
+ Spaceship(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_logical_operator)]
+#[note]
+pub(crate) struct InvalidLogicalOperator {
+ #[primary_span]
+ pub span: Span,
+ pub incorrect: String,
+ #[subdiagnostic]
+ pub sub: InvalidLogicalOperatorSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum InvalidLogicalOperatorSub {
+ #[suggestion_short(
+ use_amp_amp_for_conjunction,
+ applicability = "machine-applicable",
+ code = "&&"
+ )]
+ Conjunction(#[primary_span] Span),
+ #[suggestion_short(
+ use_pipe_pipe_for_disjunction,
+ applicability = "machine-applicable",
+ code = "||"
+ )]
+ Disjunction(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_tilde_is_not_unary_operator)]
+pub(crate) struct TildeAsUnaryOperator(
+ #[primary_span]
+ #[suggestion_short(applicability = "machine-applicable", code = "!")]
+ pub Span,
+);
+
+#[derive(Diagnostic)]
+#[diag(parser_unexpected_token_after_not)]
+pub(crate) struct NotAsNegationOperator {
+ #[primary_span]
+ pub negated: Span,
+ pub negated_desc: String,
+ #[subdiagnostic]
+ pub sub: NotAsNegationOperatorSub,
+}
+
+#[derive(Subdiagnostic)]
+pub enum NotAsNegationOperatorSub {
+ #[suggestion_short(
+ parser_unexpected_token_after_not_default,
+ applicability = "machine-applicable",
+ code = "!"
+ )]
+ SuggestNotDefault(#[primary_span] Span),
+
+ #[suggestion_short(
+ parser_unexpected_token_after_not_bitwise,
+ applicability = "machine-applicable",
+ code = "!"
+ )]
+ SuggestNotBitwise(#[primary_span] Span),
+
+ #[suggestion_short(
+ parser_unexpected_token_after_not_logical,
+ applicability = "machine-applicable",
+ code = "!"
+ )]
+ SuggestNotLogical(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_malformed_loop_label)]
+pub(crate) struct MalformedLoopLabel {
+ #[primary_span]
+ #[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
+ pub span: Span,
+ pub correct_label: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_lifetime_in_borrow_expression)]
+pub(crate) struct LifetimeInBorrowExpression {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(applicability = "machine-applicable", code = "")]
+ #[label]
+ pub lifetime_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_field_expression_with_generic)]
+pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
+
+#[derive(Diagnostic)]
+#[diag(parser_macro_invocation_with_qualified_path)]
+pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
+
+#[derive(Diagnostic)]
+#[diag(parser_unexpected_token_after_label)]
+pub(crate) struct UnexpectedTokenAfterLabel {
+ #[primary_span]
+ #[label(parser_unexpected_token_after_label)]
+ pub span: Span,
+ #[suggestion_verbose(suggestion_remove_label, code = "")]
+ pub remove_label: Option<Span>,
+ #[subdiagnostic]
+ pub enclose_in_block: Option<UnexpectedTokenAfterLabelSugg>,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion_enclose_in_block, applicability = "machine-applicable")]
+pub(crate) struct UnexpectedTokenAfterLabelSugg {
+ #[suggestion_part(code = "{{ ")]
+ pub left: Span,
+ #[suggestion_part(code = " }}")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_require_colon_after_labeled_expression)]
+#[note]
+pub(crate) struct RequireColonAfterLabeledExpression {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub label: Span,
+ #[suggestion_short(applicability = "machine-applicable", code = ": ")]
+ pub label_end: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_do_catch_syntax_removed)]
+#[note]
+pub(crate) struct DoCatchSyntaxRemoved {
+ #[primary_span]
+ #[suggestion(applicability = "machine-applicable", code = "try")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_float_literal_requires_integer_part)]
+pub(crate) struct FloatLiteralRequiresIntegerPart {
+ #[primary_span]
+ #[suggestion(applicability = "machine-applicable", code = "{correct}")]
+ pub span: Span,
+ pub correct: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_int_literal_width)]
+#[help]
+pub(crate) struct InvalidIntLiteralWidth {
+ #[primary_span]
+ pub span: Span,
+ pub width: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_num_literal_base_prefix)]
+#[note]
+pub(crate) struct InvalidNumLiteralBasePrefix {
+ #[primary_span]
+ #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
+ pub span: Span,
+ pub fixed: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_num_literal_suffix)]
+#[help]
+pub(crate) struct InvalidNumLiteralSuffix {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub suffix: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_float_literal_width)]
+#[help]
+pub(crate) struct InvalidFloatLiteralWidth {
+ #[primary_span]
+ pub span: Span,
+ pub width: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_float_literal_suffix)]
+#[help]
+pub(crate) struct InvalidFloatLiteralSuffix {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub suffix: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_int_literal_too_large)]
+pub(crate) struct IntLiteralTooLarge {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_missing_semicolon_before_array)]
+pub(crate) struct MissingSemicolonBeforeArray {
+ #[primary_span]
+ pub open_delim: Span,
+ #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")]
+ pub semicolon: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_block_macro_segment)]
+pub(crate) struct InvalidBlockMacroSegment {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub context: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_if_expression_missing_then_block)]
+pub(crate) struct IfExpressionMissingThenBlock {
+ #[primary_span]
+ pub if_span: Span,
+ #[subdiagnostic]
+ pub sub: IfExpressionMissingThenBlockSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum IfExpressionMissingThenBlockSub {
+ #[help(condition_possibly_unfinished)]
+ UnfinishedCondition(#[primary_span] Span),
+ #[help(add_then_block)]
+ AddThenBlock(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_if_expression_missing_condition)]
+pub(crate) struct IfExpressionMissingCondition {
+ #[primary_span]
+ #[label(condition_label)]
+ pub if_span: Span,
+ #[label(block_label)]
+ pub block_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_expected_expression_found_let)]
+pub(crate) struct ExpectedExpressionFoundLet {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_expected_else_block)]
+pub(crate) struct ExpectedElseBlock {
+ #[primary_span]
+ pub first_tok_span: Span,
+ pub first_tok: String,
+ #[label]
+ pub else_span: Span,
+ #[suggestion(applicability = "maybe-incorrect", code = "if ")]
+ pub condition_start: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_outer_attribute_not_allowed_on_if_else)]
+pub(crate) struct OuterAttributeNotAllowedOnIfElse {
+ #[primary_span]
+ pub last: Span,
+
+ #[label(branch_label)]
+ pub branch_span: Span,
+
+ #[label(ctx_label)]
+ pub ctx_span: Span,
+ pub ctx: String,
+
+ #[suggestion(applicability = "machine-applicable", code = "")]
+ pub attributes: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_missing_in_in_for_loop)]
+pub(crate) struct MissingInInForLoop {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: MissingInInForLoopSub,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MissingInInForLoopSub {
+ // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
+ #[suggestion_short(use_in_not_of, applicability = "maybe-incorrect", code = "in")]
+ InNotOf(#[primary_span] Span),
+ #[suggestion_short(add_in, applicability = "maybe-incorrect", code = " in ")]
+ AddIn(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_missing_comma_after_match_arm)]
+pub(crate) struct MissingCommaAfterMatchArm {
+ #[primary_span]
+ #[suggestion(applicability = "machine-applicable", code = ",")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_catch_after_try)]
+#[help]
+pub(crate) struct CatchAfterTry {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_comma_after_base_struct)]
+#[note]
+pub(crate) struct CommaAfterBaseStruct {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion_short(applicability = "machine-applicable", code = "")]
+ pub comma: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_eq_field_init)]
+pub(crate) struct EqFieldInit {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(applicability = "machine-applicable", code = ":")]
+ pub eq: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_dotdotdot)]
+pub(crate) struct DotDotDot {
+ #[primary_span]
+ #[suggestion(suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
+ #[suggestion(suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_left_arrow_operator)]
+pub(crate) struct LeftArrowOperator {
+ #[primary_span]
+ #[suggestion(applicability = "maybe-incorrect", code = "< -")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_remove_let)]
+pub(crate) struct RemoveLet {
+ #[primary_span]
+ #[suggestion(applicability = "machine-applicable", code = "")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_use_eq_instead)]
+pub(crate) struct UseEqInstead {
+ #[primary_span]
+ #[suggestion_short(applicability = "machine-applicable", code = "=")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_use_empty_block_not_semi)]
+pub(crate) struct UseEmptyBlockNotSemi {
+ #[primary_span]
+ #[suggestion_hidden(applicability = "machine-applicable", code = "{{}}")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_comparison_interpreted_as_generic)]
+pub(crate) struct ComparisonInterpretedAsGeneric {
+ #[primary_span]
+ #[label(label_comparison)]
+ pub comparison: Span,
+ pub r#type: Path,
+ #[label(label_args)]
+ pub args: Span,
+ #[subdiagnostic]
+ pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_shift_interpreted_as_generic)]
+pub(crate) struct ShiftInterpretedAsGeneric {
+ #[primary_span]
+ #[label(label_comparison)]
+ pub shift: Span,
+ pub r#type: Path,
+ #[label(label_args)]
+ pub args: Span,
+ #[subdiagnostic]
+ pub suggestion: ComparisonOrShiftInterpretedAsGenericSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct ComparisonOrShiftInterpretedAsGenericSugg {
+ #[suggestion_part(code = "(")]
+ pub left: Span,
+ #[suggestion_part(code = ")")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_found_expr_would_be_stmt)]
+pub(crate) struct FoundExprWouldBeStmt {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub token: Token,
+ #[subdiagnostic]
+ pub suggestion: ExprParenthesesNeeded,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_leading_plus_not_supported)]
+pub(crate) struct LeadingPlusNotSupported {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[suggestion_verbose(suggestion_remove_plus, code = "", applicability = "machine-applicable")]
+ pub remove_plus: Option<Span>,
+ #[subdiagnostic]
+ pub add_parentheses: Option<ExprParenthesesNeeded>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_parentheses_with_struct_fields)]
+pub(crate) struct ParenthesesWithStructFields {
+ #[primary_span]
+ pub span: Span,
+ pub r#type: Path,
+ #[subdiagnostic]
+ pub braces_for_struct: BracesForStructLiteral,
+ #[subdiagnostic]
+ pub no_fields_for_fn: NoFieldsForFnCall,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion_braces_for_struct, applicability = "maybe-incorrect")]
+pub(crate) struct BracesForStructLiteral {
+ #[suggestion_part(code = " {{ ")]
+ pub first: Span,
+ #[suggestion_part(code = " }}")]
+ pub second: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion_no_fields_for_fn, applicability = "maybe-incorrect")]
+pub(crate) struct NoFieldsForFnCall {
+ #[suggestion_part(code = "")]
+ pub fields: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_labeled_loop_in_break)]
+pub(crate) struct LabeledLoopInBreak {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: WrapExpressionInParentheses,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+ parser_sugg_wrap_expression_in_parentheses,
+ applicability = "machine-applicable"
+)]
+pub(crate) struct WrapExpressionInParentheses {
+ #[suggestion_part(code = "(")]
+ pub left: Span,
+ #[suggestion_part(code = ")")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_array_brackets_instead_of_braces)]
+pub(crate) struct ArrayBracketsInsteadOfSpaces {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: ArrayBracketsInsteadOfSpacesSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "maybe-incorrect")]
+pub(crate) struct ArrayBracketsInsteadOfSpacesSugg {
+ #[suggestion_part(code = "[")]
+ pub left: Span,
+ #[suggestion_part(code = "]")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_match_arm_body_without_braces)]
+pub(crate) struct MatchArmBodyWithoutBraces {
+ #[primary_span]
+ #[label(label_statements)]
+ pub statements: Span,
+ #[label(label_arrow)]
+ pub arrow: Span,
+ pub num_statements: usize,
+ #[subdiagnostic]
+ pub sub: MatchArmBodyWithoutBracesSugg,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MatchArmBodyWithoutBracesSugg {
+ #[multipart_suggestion(suggestion_add_braces, applicability = "machine-applicable")]
+ AddBraces {
+ #[suggestion_part(code = "{{ ")]
+ left: Span,
+ #[suggestion_part(code = " }}")]
+ right: Span,
+ },
+ #[suggestion(
+ suggestion_use_comma_not_semicolon,
+ code = ",",
+ applicability = "machine-applicable"
+ )]
+ UseComma {
+ #[primary_span]
+ semicolon: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_struct_literal_not_allowed_here)]
+pub(crate) struct StructLiteralNotAllowedHere {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sub: StructLiteralNotAllowedHereSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct StructLiteralNotAllowedHereSugg {
+ #[suggestion_part(code = "(")]
+ pub left: Span,
+ #[suggestion_part(code = ")")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_interpolated_expression)]
+pub(crate) struct InvalidInterpolatedExpression {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_hexadecimal_float_literal_not_supported)]
+pub(crate) struct HexadecimalFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(parser_not_supported)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_octal_float_literal_not_supported)]
+pub(crate) struct OctalFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(parser_not_supported)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_binary_float_literal_not_supported)]
+pub(crate) struct BinaryFloatLiteralNotSupported {
+ #[primary_span]
+ #[label(parser_not_supported)]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_literal_suffix)]
+pub(crate) struct InvalidLiteralSuffix {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ // FIXME(#100717)
+ pub kind: String,
+ pub suffix: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_literal_suffix_on_tuple_index)]
+pub(crate) struct InvalidLiteralSuffixOnTupleIndex {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub suffix: Symbol,
+ #[help(tuple_exception_line_1)]
+ #[help(tuple_exception_line_2)]
+ #[help(tuple_exception_line_3)]
+ pub exception: Option<()>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_non_string_abi_literal)]
+pub(crate) struct NonStringAbiLiteral {
+ #[primary_span]
+ #[suggestion(code = "\"C\"", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_mismatched_closing_delimiter)]
+pub(crate) struct MismatchedClosingDelimiter {
+ #[primary_span]
+ pub spans: Vec<Span>,
+ pub delimiter: String,
+ #[label(label_unmatched)]
+ pub unmatched: Span,
+ #[label(label_opening_candidate)]
+ pub opening_candidate: Option<Span>,
+ #[label(label_unclosed)]
+ pub unclosed: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_incorrect_visibility_restriction, code = "E0704")]
+#[help]
+pub(crate) struct IncorrectVisibilityRestriction {
+ #[primary_span]
+ #[suggestion(code = "in {inner_str}", applicability = "machine-applicable")]
+ pub span: Span,
+ pub inner_str: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_assignment_else_not_allowed)]
+pub(crate) struct AssignmentElseNotAllowed {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_expected_statement_after_outer_attr)]
+pub(crate) struct ExpectedStatementAfterOuterAttr {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_doc_comment_does_not_document_anything, code = "E0585")]
+#[help]
+pub(crate) struct DocCommentDoesNotDocumentAnything {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = ",", applicability = "machine-applicable")]
+ pub missing_comma: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_const_let_mutually_exclusive)]
+pub(crate) struct ConstLetMutuallyExclusive {
+ #[primary_span]
+ #[suggestion(code = "const", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_expression_in_let_else)]
+pub(crate) struct InvalidExpressionInLetElse {
+ #[primary_span]
+ pub span: Span,
+ pub operator: &'static str,
+ #[subdiagnostic]
+ pub sugg: WrapExpressionInParentheses,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_curly_in_let_else)]
+pub(crate) struct InvalidCurlyInLetElse {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: WrapExpressionInParentheses,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_compound_assignment_expression_in_let)]
+#[help]
+pub(crate) struct CompoundAssignmentExpressionInLet {
+ #[primary_span]
+ #[suggestion_short(code = "=", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_suffixed_literal_in_attribute)]
+#[help]
+pub(crate) struct SuffixedLiteralInAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_invalid_meta_item)]
+pub(crate) struct InvalidMetaItem {
+ #[primary_span]
+ pub span: Span,
+ pub token: Token,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion_verbose(
+ parser_sugg_escape_to_use_as_identifier,
+ applicability = "maybe-incorrect",
+ code = "r#"
+)]
+pub(crate) struct SuggEscapeToUseAsIdentifier {
+ #[primary_span]
+ pub span: Span,
+ pub ident_name: String,
+}
+
+#[derive(Subdiagnostic)]
+#[suggestion(parser_sugg_remove_comma, applicability = "machine-applicable", code = "")]
+pub(crate) struct SuggRemoveComma {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ExpectedIdentifierFound {
+ #[label(parser_expected_identifier_found_reserved_identifier)]
+ ReservedIdentifier(#[primary_span] Span),
+ #[label(parser_expected_identifier_found_keyword)]
+ Keyword(#[primary_span] Span),
+ #[label(parser_expected_identifier_found_reserved_keyword)]
+ ReservedKeyword(#[primary_span] Span),
+ #[label(parser_expected_identifier_found_doc_comment)]
+ DocComment(#[primary_span] Span),
+ #[label(parser_expected_identifier)]
+ Other(#[primary_span] Span),
+}
+
+impl ExpectedIdentifierFound {
+ pub fn new(token_descr: Option<TokenDescription>, span: Span) -> Self {
+ (match token_descr {
+ Some(TokenDescription::ReservedIdentifier) => {
+ ExpectedIdentifierFound::ReservedIdentifier
+ }
+ Some(TokenDescription::Keyword) => ExpectedIdentifierFound::Keyword,
+ Some(TokenDescription::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
+ Some(TokenDescription::DocComment) => ExpectedIdentifierFound::DocComment,
+ None => ExpectedIdentifierFound::Other,
+ })(span)
+ }
+}
+
+pub(crate) struct ExpectedIdentifier {
+ pub span: Span,
+ pub token: Token,
+ pub suggest_raw: Option<SuggEscapeToUseAsIdentifier>,
+ pub suggest_remove_comma: Option<SuggRemoveComma>,
+}
+
+impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, G> {
+ let token_descr = super::parser::TokenDescription::from_token(&self.token);
+
+ let mut diag = handler.struct_diagnostic(match token_descr {
+ Some(TokenDescription::ReservedIdentifier) => {
+ fluent::parser_expected_identifier_found_reserved_identifier_str
+ }
+ Some(TokenDescription::Keyword) => fluent::parser_expected_identifier_found_keyword_str,
+ Some(TokenDescription::ReservedKeyword) => {
+ fluent::parser_expected_identifier_found_reserved_keyword_str
+ }
+ Some(TokenDescription::DocComment) => {
+ fluent::parser_expected_identifier_found_doc_comment_str
+ }
+ None => fluent::parser_expected_identifier_found_str,
+ });
+ diag.set_span(self.span);
+ diag.set_arg("token", self.token);
+
+ if let Some(sugg) = self.suggest_raw {
+ sugg.add_to_diagnostic(&mut diag);
+ }
+
+ ExpectedIdentifierFound::new(token_descr, self.span).add_to_diagnostic(&mut diag);
+
+ if let Some(sugg) = self.suggest_remove_comma {
+ sugg.add_to_diagnostic(&mut diag);
+ }
+
+ diag
+ }
+}
+
+pub(crate) struct ExpectedSemi {
+ pub span: Span,
+ pub token: Token,
+
+ pub unexpected_token_label: Option<Span>,
+ pub sugg: ExpectedSemiSugg,
+}
+
+impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, G> {
+ let token_descr = super::parser::TokenDescription::from_token(&self.token);
+
+ let mut diag = handler.struct_diagnostic(match token_descr {
+ Some(TokenDescription::ReservedIdentifier) => {
+ fluent::parser_expected_semi_found_reserved_identifier_str
+ }
+ Some(TokenDescription::Keyword) => fluent::parser_expected_semi_found_keyword_str,
+ Some(TokenDescription::ReservedKeyword) => {
+ fluent::parser_expected_semi_found_reserved_keyword_str
+ }
+ Some(TokenDescription::DocComment) => {
+ fluent::parser_expected_semi_found_doc_comment_str
+ }
+ None => fluent::parser_expected_semi_found_str,
+ });
+ diag.set_span(self.span);
+ diag.set_arg("token", self.token);
+
+ if let Some(unexpected_token_label) = self.unexpected_token_label {
+ diag.span_label(unexpected_token_label, fluent::parser_label_unexpected_token);
+ }
+
+ self.sugg.add_to_diagnostic(&mut diag);
+
+ diag
+ }
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ExpectedSemiSugg {
+ #[suggestion(
+ parser_sugg_change_this_to_semi,
+ code = ";",
+ applicability = "machine-applicable"
+ )]
+ ChangeToSemi(#[primary_span] Span),
+ #[suggestion_short(parser_sugg_add_semi, code = ";", applicability = "machine-applicable")]
+ AddSemi(#[primary_span] Span),
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_struct_literal_body_without_path)]
+pub(crate) struct StructLiteralBodyWithoutPath {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: StructLiteralBodyWithoutPathSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "has-placeholders")]
+pub(crate) struct StructLiteralBodyWithoutPathSugg {
+ #[suggestion_part(code = "{{ SomeStruct ")]
+ pub before: Span,
+ #[suggestion_part(code = " }}")]
+ pub after: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_unmatched_angle_brackets)]
+pub(crate) struct UnmatchedAngleBrackets {
+ #[primary_span]
+ #[suggestion(code = "", applicability = "machine-applicable")]
+ pub span: Span,
+ pub num_extra_brackets: usize,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_generic_parameters_without_angle_brackets)]
+pub(crate) struct GenericParamsWithoutAngleBrackets {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: GenericParamsWithoutAngleBracketsSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct GenericParamsWithoutAngleBracketsSugg {
+ #[suggestion_part(code = "<")]
+ pub left: Span,
+ #[suggestion_part(code = ">")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_comparison_operators_cannot_be_chained)]
+pub(crate) struct ComparisonOperatorsCannotBeChained {
+ #[primary_span]
+ pub span: Vec<Span>,
+ #[suggestion_verbose(
+ parser_sugg_turbofish_syntax,
+ code = "::",
+ applicability = "maybe-incorrect"
+ )]
+ pub suggest_turbofish: Option<Span>,
+ #[help(parser_sugg_turbofish_syntax)]
+ #[help(sugg_parentheses_for_function_args)]
+ pub help_turbofish: Option<()>,
+ #[subdiagnostic]
+ pub chaining_sugg: Option<ComparisonOperatorsCannotBeChainedSugg>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum ComparisonOperatorsCannotBeChainedSugg {
+ #[suggestion_verbose(
+ sugg_split_comparison,
+ code = " && {middle_term}",
+ applicability = "maybe-incorrect"
+ )]
+ SplitComparison {
+ #[primary_span]
+ span: Span,
+ middle_term: String,
+ },
+ #[multipart_suggestion(sugg_parenthesize, applicability = "maybe-incorrect")]
+ Parenthesize {
+ #[suggestion_part(code = "(")]
+ left: Span,
+ #[suggestion_part(code = ")")]
+ right: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_question_mark_in_type)]
+pub(crate) struct QuestionMarkInType {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: QuestionMarkInTypeSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct QuestionMarkInTypeSugg {
+ #[suggestion_part(code = "Option<")]
+ pub left: Span,
+ #[suggestion_part(code = ">")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_unexpected_parentheses_in_for_head)]
+pub(crate) struct ParenthesesInForHead {
+ #[primary_span]
+ pub span: Vec<Span>,
+ #[subdiagnostic]
+ pub sugg: ParenthesesInForHeadSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct ParenthesesInForHeadSugg {
+ #[suggestion_part(code = "")]
+ pub left: Span,
+ #[suggestion_part(code = "")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_doc_comment_on_param_type)]
+pub(crate) struct DocCommentOnParamType {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_attribute_on_param_type)]
+pub(crate) struct AttributeOnParamType {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_pattern_method_param_without_body, code = "E0642")]
+pub(crate) struct PatternMethodParamWithoutBody {
+ #[primary_span]
+ #[suggestion(code = "_", applicability = "machine-applicable")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_self_param_not_first)]
+pub(crate) struct SelfParamNotFirst {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_const_generic_without_braces)]
+pub(crate) struct ConstGenericWithoutBraces {
+ #[primary_span]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: ConstGenericWithoutBracesSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+pub(crate) struct ConstGenericWithoutBracesSugg {
+ #[suggestion_part(code = "{{ ")]
+ pub left: Span,
+ #[suggestion_part(code = " }}")]
+ pub right: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_unexpected_const_param_declaration)]
+pub(crate) struct UnexpectedConstParamDeclaration {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[subdiagnostic]
+ pub sugg: Option<UnexpectedConstParamDeclarationSugg>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum UnexpectedConstParamDeclarationSugg {
+ #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+ AddParam {
+ #[suggestion_part(code = "<{snippet}>")]
+ impl_generics: Span,
+ #[suggestion_part(code = "{ident}")]
+ incorrect_decl: Span,
+ snippet: String,
+ ident: String,
+ },
+ #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
+ AppendParam {
+ #[suggestion_part(code = ", {snippet}")]
+ impl_generics_end: Span,
+ #[suggestion_part(code = "{ident}")]
+ incorrect_decl: Span,
+ snippet: String,
+ ident: String,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_unexpected_const_in_generic_param)]
+pub(crate) struct UnexpectedConstInGenericParam {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion_verbose(code = "", applicability = "maybe-incorrect")]
+ pub to_remove: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_async_move_order_incorrect)]
+pub(crate) struct AsyncMoveOrderIncorrect {
+ #[primary_span]
+ #[suggestion_verbose(code = "async move", applicability = "maybe-incorrect")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(parser_double_colon_in_bound)]
+pub(crate) struct DoubleColonInBound {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = ": ", applicability = "machine-applicable")]
+ pub between: Span,
+}
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 63819a2f9..462bce16a 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -1,10 +1,13 @@
use crate::lexer::unicode_chars::UNICODE_ARRAY;
use rustc_ast::ast::{self, AttrStyle};
use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{Spacing, TokenStream};
+use rustc_ast::tokenstream::TokenStream;
use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{
+ error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult, StashKey,
+};
use rustc_lexer::unescape::{self, Mode};
+use rustc_lexer::Cursor;
use rustc_lexer::{Base, DocStyle, RawStrError};
use rustc_session::lint::builtin::{
RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
@@ -38,11 +41,20 @@ pub struct UnmatchedBrace {
pub(crate) fn parse_token_trees<'a>(
sess: &'a ParseSess,
- src: &'a str,
- start_pos: BytePos,
+ mut src: &'a str,
+ mut start_pos: BytePos,
override_span: Option<Span>,
) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
- StringReader { sess, start_pos, pos: start_pos, src, override_span }.into_token_trees()
+ // Skip `#!`, if present.
+ if let Some(shebang_len) = rustc_lexer::strip_shebang(src) {
+ src = &src[shebang_len..];
+ start_pos = start_pos + BytePos::from_usize(shebang_len);
+ }
+
+ let cursor = Cursor::new(src);
+ let string_reader =
+ StringReader { sess, start_pos, pos: start_pos, src, cursor, override_span };
+ tokentrees::TokenTreesReader::parse_all_token_trees(string_reader)
}
struct StringReader<'a> {
@@ -53,6 +65,8 @@ struct StringReader<'a> {
pos: BytePos,
/// Source text to tokenize.
src: &'a str,
+ /// Cursor for getting lexer tokens.
+ cursor: Cursor<'a>,
override_span: Option<Span>,
}
@@ -61,42 +75,198 @@ impl<'a> StringReader<'a> {
self.override_span.unwrap_or_else(|| Span::with_root_ctxt(lo, hi))
}
- /// Returns the next token, and info about preceding whitespace, if any.
- fn next_token(&mut self) -> (Spacing, Token) {
- let mut spacing = Spacing::Joint;
-
- // Skip `#!` at the start of the file
- if self.pos == self.start_pos
- && let Some(shebang_len) = rustc_lexer::strip_shebang(self.src)
- {
- self.pos = self.pos + BytePos::from_usize(shebang_len);
- spacing = Spacing::Alone;
- }
+ /// Returns the next token, paired with a bool indicating if the token was
+ /// preceded by whitespace.
+ fn next_token(&mut self) -> (Token, bool) {
+ let mut preceded_by_whitespace = false;
// Skip trivial (whitespace & comments) tokens
loop {
- let start_src_index = self.src_index(self.pos);
- let text: &str = &self.src[start_src_index..];
-
- if text.is_empty() {
- let span = self.mk_sp(self.pos, self.pos);
- return (spacing, Token::new(token::Eof, span));
- }
-
- let token = rustc_lexer::first_token(text);
-
+ let token = self.cursor.advance_token();
let start = self.pos;
self.pos = self.pos + BytePos(token.len);
debug!("next_token: {:?}({:?})", token.kind, self.str_from(start));
- match self.cook_lexer_token(token.kind, start) {
- Some(kind) => {
+ // Now "cook" the token, converting the simple `rustc_lexer::TokenKind` enum into a
+ // rich `rustc_ast::TokenKind`. This turns strings into interned symbols and runs
+ // additional validation.
+ let kind = match token.kind {
+ rustc_lexer::TokenKind::LineComment { doc_style } => {
+ // Skip non-doc comments
+ let Some(doc_style) = doc_style else {
+ self.lint_unicode_text_flow(start);
+ preceded_by_whitespace = true;
+ continue;
+ };
+
+ // Opening delimiter of the length 3 is not included into the symbol.
+ let content_start = start + BytePos(3);
+ let content = self.str_from(content_start);
+ self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style)
+ }
+ rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
+ if !terminated {
+ self.report_unterminated_block_comment(start, doc_style);
+ }
+
+ // Skip non-doc comments
+ let Some(doc_style) = doc_style else {
+ self.lint_unicode_text_flow(start);
+ preceded_by_whitespace = true;
+ continue;
+ };
+
+ // Opening delimiter of the length 3 and closing delimiter of the length 2
+ // are not included into the symbol.
+ let content_start = start + BytePos(3);
+ let content_end = self.pos - BytePos(if terminated { 2 } else { 0 });
+ let content = self.str_from_to(content_start, content_end);
+ self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style)
+ }
+ rustc_lexer::TokenKind::Whitespace => {
+ preceded_by_whitespace = true;
+ continue;
+ }
+ rustc_lexer::TokenKind::Ident => {
+ let sym = nfc_normalize(self.str_from(start));
let span = self.mk_sp(start, self.pos);
- return (spacing, Token::new(kind, span));
+ self.sess.symbol_gallery.insert(sym, span);
+ token::Ident(sym, false)
}
- None => spacing = Spacing::Alone,
- }
+ rustc_lexer::TokenKind::RawIdent => {
+ let sym = nfc_normalize(self.str_from(start + BytePos(2)));
+ 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.raw_identifier_spans.borrow_mut().push(span);
+ token::Ident(sym, true)
+ }
+ rustc_lexer::TokenKind::UnknownPrefix => {
+ self.report_unknown_prefix(start);
+ let sym = nfc_normalize(self.str_from(start));
+ let span = self.mk_sp(start, self.pos);
+ self.sess.symbol_gallery.insert(sym, span);
+ token::Ident(sym, false)
+ }
+ rustc_lexer::TokenKind::InvalidIdent
+ // Do not recover an identifier with emoji if the codepoint is a confusable
+ // with a recoverable substitution token, like `➖`.
+ if !UNICODE_ARRAY
+ .iter()
+ .any(|&(c, _, _)| {
+ let sym = self.str_from(start);
+ sym.chars().count() == 1 && c == sym.chars().next().unwrap()
+ }) =>
+ {
+ let sym = nfc_normalize(self.str_from(start));
+ let span = self.mk_sp(start, self.pos);
+ self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
+ .push(span);
+ token::Ident(sym, false)
+ }
+ rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
+ let suffix_start = start + BytePos(suffix_start);
+ let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
+ let suffix = if suffix_start < self.pos {
+ let string = self.str_from(suffix_start);
+ if string == "_" {
+ self.sess
+ .span_diagnostic
+ .struct_span_warn(
+ self.mk_sp(suffix_start, self.pos),
+ "underscore literal suffix is not allowed",
+ )
+ .warn(
+ "this was previously accepted by the compiler but is \
+ being phased out; it will become a hard error in \
+ a future release!",
+ )
+ .note(
+ "see issue #42326 \
+ <https://github.com/rust-lang/rust/issues/42326> \
+ for more information",
+ )
+ .emit();
+ None
+ } else {
+ Some(Symbol::intern(string))
+ }
+ } else {
+ None
+ };
+ token::Literal(token::Lit { kind, symbol, suffix })
+ }
+ rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
+ // Include the leading `'` in the real identifier, for macro
+ // expansion purposes. See #12512 for the gory details of why
+ // this is necessary.
+ let lifetime_name = self.str_from(start);
+ if starts_with_number {
+ let span = self.mk_sp(start, self.pos);
+ let mut diag = self.sess.struct_err("lifetimes cannot start with a number");
+ diag.set_span(span);
+ diag.stash(span, StashKey::LifetimeIsChar);
+ }
+ let ident = Symbol::intern(lifetime_name);
+ token::Lifetime(ident)
+ }
+ rustc_lexer::TokenKind::Semi => token::Semi,
+ rustc_lexer::TokenKind::Comma => token::Comma,
+ rustc_lexer::TokenKind::Dot => token::Dot,
+ rustc_lexer::TokenKind::OpenParen => token::OpenDelim(Delimiter::Parenthesis),
+ rustc_lexer::TokenKind::CloseParen => token::CloseDelim(Delimiter::Parenthesis),
+ rustc_lexer::TokenKind::OpenBrace => token::OpenDelim(Delimiter::Brace),
+ rustc_lexer::TokenKind::CloseBrace => token::CloseDelim(Delimiter::Brace),
+ rustc_lexer::TokenKind::OpenBracket => token::OpenDelim(Delimiter::Bracket),
+ rustc_lexer::TokenKind::CloseBracket => token::CloseDelim(Delimiter::Bracket),
+ rustc_lexer::TokenKind::At => token::At,
+ rustc_lexer::TokenKind::Pound => token::Pound,
+ rustc_lexer::TokenKind::Tilde => token::Tilde,
+ rustc_lexer::TokenKind::Question => token::Question,
+ rustc_lexer::TokenKind::Colon => token::Colon,
+ rustc_lexer::TokenKind::Dollar => token::Dollar,
+ rustc_lexer::TokenKind::Eq => token::Eq,
+ rustc_lexer::TokenKind::Bang => token::Not,
+ rustc_lexer::TokenKind::Lt => token::Lt,
+ rustc_lexer::TokenKind::Gt => token::Gt,
+ rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus),
+ rustc_lexer::TokenKind::And => token::BinOp(token::And),
+ rustc_lexer::TokenKind::Or => token::BinOp(token::Or),
+ rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus),
+ rustc_lexer::TokenKind::Star => token::BinOp(token::Star),
+ rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash),
+ rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
+ rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
+
+ rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
+ let c = self.str_from(start).chars().next().unwrap();
+ let mut err =
+ self.struct_err_span_char(start, self.pos, "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);
+ if c == '\x00' {
+ err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
+ }
+ err.emit();
+ if let Some(token) = token {
+ token
+ } else {
+ preceded_by_whitespace = true;
+ continue;
+ }
+ }
+ rustc_lexer::TokenKind::Eof => token::Eof,
+ };
+ let span = self.mk_sp(start, self.pos);
+ return (Token::new(kind, span), preceded_by_whitespace);
}
}
@@ -162,171 +332,6 @@ impl<'a> StringReader<'a> {
}
}
- /// Turns simple `rustc_lexer::TokenKind` enum into a rich
- /// `rustc_ast::TokenKind`. This turns strings into interned
- /// symbols and runs additional validation.
- fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> Option<TokenKind> {
- Some(match token {
- rustc_lexer::TokenKind::LineComment { doc_style } => {
- // Skip non-doc comments
- let Some(doc_style) = doc_style else {
- self.lint_unicode_text_flow(start);
- return None;
- };
-
- // Opening delimiter of the length 3 is not included into the symbol.
- let content_start = start + BytePos(3);
- let content = self.str_from(content_start);
- self.cook_doc_comment(content_start, content, CommentKind::Line, doc_style)
- }
- rustc_lexer::TokenKind::BlockComment { doc_style, terminated } => {
- if !terminated {
- self.report_unterminated_block_comment(start, doc_style);
- }
-
- // Skip non-doc comments
- let Some(doc_style) = doc_style else {
- self.lint_unicode_text_flow(start);
- return None;
- };
-
- // Opening delimiter of the length 3 and closing delimiter of the length 2
- // are not included into the symbol.
- let content_start = start + BytePos(3);
- let content_end = self.pos - BytePos(if terminated { 2 } else { 0 });
- let content = self.str_from_to(content_start, content_end);
- self.cook_doc_comment(content_start, content, CommentKind::Block, doc_style)
- }
- rustc_lexer::TokenKind::Whitespace => return None,
- rustc_lexer::TokenKind::Ident
- | rustc_lexer::TokenKind::RawIdent
- | rustc_lexer::TokenKind::UnknownPrefix => {
- let is_raw_ident = token == rustc_lexer::TokenKind::RawIdent;
- let is_unknown_prefix = token == rustc_lexer::TokenKind::UnknownPrefix;
- let mut ident_start = start;
- if is_raw_ident {
- ident_start = ident_start + BytePos(2);
- }
- if is_unknown_prefix {
- self.report_unknown_prefix(start);
- }
- let sym = nfc_normalize(self.str_from(ident_start));
- let span = self.mk_sp(start, self.pos);
- self.sess.symbol_gallery.insert(sym, span);
- if is_raw_ident {
- if !sym.can_be_raw() {
- self.err_span(span, &format!("`{}` cannot be a raw identifier", sym));
- }
- self.sess.raw_identifier_spans.borrow_mut().push(span);
- }
- token::Ident(sym, is_raw_ident)
- }
- rustc_lexer::TokenKind::InvalidIdent
- // Do not recover an identifier with emoji if the codepoint is a confusable
- // with a recoverable substitution token, like `➖`.
- if !UNICODE_ARRAY
- .iter()
- .any(|&(c, _, _)| {
- let sym = self.str_from(start);
- sym.chars().count() == 1 && c == sym.chars().next().unwrap()
- })
- =>
- {
- let sym = nfc_normalize(self.str_from(start));
- let span = self.mk_sp(start, self.pos);
- self.sess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default().push(span);
- token::Ident(sym, false)
- }
- rustc_lexer::TokenKind::Literal { kind, suffix_start } => {
- let suffix_start = start + BytePos(suffix_start);
- let (kind, symbol) = self.cook_lexer_literal(start, suffix_start, kind);
- let suffix = if suffix_start < self.pos {
- let string = self.str_from(suffix_start);
- if string == "_" {
- self.sess
- .span_diagnostic
- .struct_span_warn(
- self.mk_sp(suffix_start, self.pos),
- "underscore literal suffix is not allowed",
- )
- .warn(
- "this was previously accepted by the compiler but is \
- being phased out; it will become a hard error in \
- a future release!",
- )
- .note(
- "see issue #42326 \
- <https://github.com/rust-lang/rust/issues/42326> \
- for more information",
- )
- .emit();
- None
- } else {
- Some(Symbol::intern(string))
- }
- } else {
- None
- };
- token::Literal(token::Lit { kind, symbol, suffix })
- }
- rustc_lexer::TokenKind::Lifetime { starts_with_number } => {
- // Include the leading `'` in the real identifier, for macro
- // expansion purposes. See #12512 for the gory details of why
- // this is necessary.
- let lifetime_name = self.str_from(start);
- if starts_with_number {
- self.err_span_(start, self.pos, "lifetimes cannot start with a number");
- }
- let ident = Symbol::intern(lifetime_name);
- token::Lifetime(ident)
- }
- rustc_lexer::TokenKind::Semi => token::Semi,
- rustc_lexer::TokenKind::Comma => token::Comma,
- rustc_lexer::TokenKind::Dot => token::Dot,
- rustc_lexer::TokenKind::OpenParen => token::OpenDelim(Delimiter::Parenthesis),
- rustc_lexer::TokenKind::CloseParen => token::CloseDelim(Delimiter::Parenthesis),
- rustc_lexer::TokenKind::OpenBrace => token::OpenDelim(Delimiter::Brace),
- rustc_lexer::TokenKind::CloseBrace => token::CloseDelim(Delimiter::Brace),
- rustc_lexer::TokenKind::OpenBracket => token::OpenDelim(Delimiter::Bracket),
- rustc_lexer::TokenKind::CloseBracket => token::CloseDelim(Delimiter::Bracket),
- rustc_lexer::TokenKind::At => token::At,
- rustc_lexer::TokenKind::Pound => token::Pound,
- rustc_lexer::TokenKind::Tilde => token::Tilde,
- rustc_lexer::TokenKind::Question => token::Question,
- rustc_lexer::TokenKind::Colon => token::Colon,
- rustc_lexer::TokenKind::Dollar => token::Dollar,
- rustc_lexer::TokenKind::Eq => token::Eq,
- rustc_lexer::TokenKind::Bang => token::Not,
- rustc_lexer::TokenKind::Lt => token::Lt,
- rustc_lexer::TokenKind::Gt => token::Gt,
- rustc_lexer::TokenKind::Minus => token::BinOp(token::Minus),
- rustc_lexer::TokenKind::And => token::BinOp(token::And),
- rustc_lexer::TokenKind::Or => token::BinOp(token::Or),
- rustc_lexer::TokenKind::Plus => token::BinOp(token::Plus),
- rustc_lexer::TokenKind::Star => token::BinOp(token::Star),
- rustc_lexer::TokenKind::Slash => token::BinOp(token::Slash),
- rustc_lexer::TokenKind::Caret => token::BinOp(token::Caret),
- rustc_lexer::TokenKind::Percent => token::BinOp(token::Percent),
-
- rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
- let c = self.str_from(start).chars().next().unwrap();
- let mut err =
- self.struct_err_span_char(start, self.pos, "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);
- if c == '\x00' {
- err.help("source files must contain UTF-8 encoded text, unexpected null bytes might occur when a different encoding is used");
- }
- err.emit();
- token?
- }
- })
- }
-
fn cook_doc_comment(
&self,
content_start: BytePos,
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index aa70912dc..b2701817d 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -1,31 +1,15 @@
use super::{StringReader, UnmatchedBrace};
-
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::PResult;
+use rustc_errors::{PErr, PResult};
use rustc_span::Span;
-impl<'a> StringReader<'a> {
- pub(super) fn into_token_trees(self) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
- let mut tt_reader = TokenTreesReader {
- string_reader: self,
- 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(),
- };
- let res = tt_reader.parse_all_token_trees();
- (res, tt_reader.unmatched_braces)
- }
-}
-
-struct TokenTreesReader<'a> {
+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)>,
@@ -43,254 +27,232 @@ struct TokenTreesReader<'a> {
}
impl<'a> TokenTreesReader<'a> {
- // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
- fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
- let mut buf = TokenStreamBuilder::default();
-
- self.bump();
- while self.token != token::Eof {
- buf.push(self.parse_token_tree()?);
- }
-
- Ok(buf.into_token_stream())
+ pub(super) fn parse_all_token_trees(
+ string_reader: StringReader<'a>,
+ ) -> (PResult<'a, TokenStream>, Vec<UnmatchedBrace>) {
+ 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(),
+ };
+ let res = tt_reader.parse_token_trees(/* is_delimited */ false);
+ (res, tt_reader.unmatched_braces)
}
- // Parse a stream of tokens into a list of `TokenTree`s, up to a `CloseDelim`.
- fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
- let mut buf = TokenStreamBuilder::default();
+ // Parse a stream of tokens into a list of `TokenTree`s.
+ fn parse_token_trees(&mut self, is_delimited: bool) -> PResult<'a, TokenStream> {
+ self.token = self.string_reader.next_token().0;
+ let mut buf = Vec::new();
loop {
- if let token::CloseDelim(..) = self.token.kind {
- return buf.into_token_stream();
- }
-
- match self.parse_token_tree() {
- Ok(tree) => buf.push(tree),
- Err(mut e) => {
- e.emit();
- return buf.into_token_stream();
+ match self.token.kind {
+ token::OpenDelim(delim) => buf.push(self.parse_token_tree_open_delim(delim)),
+ token::CloseDelim(delim) => {
+ return if is_delimited {
+ Ok(TokenStream::new(buf))
+ } else {
+ Err(self.close_delim_err(delim))
+ };
+ }
+ token::Eof => {
+ if is_delimited {
+ self.eof_err().emit();
+ }
+ return Ok(TokenStream::new(buf));
+ }
+ _ => {
+ // Get the next normal token. This might require getting multiple adjacent
+ // single-char tokens and joining them together.
+ let (this_spacing, next_tok) = loop {
+ let (next_tok, is_next_tok_preceded_by_whitespace) =
+ self.string_reader.next_token();
+ if !is_next_tok_preceded_by_whitespace {
+ if let Some(glued) = self.token.glue(&next_tok) {
+ self.token = glued;
+ } else {
+ let this_spacing =
+ if next_tok.is_op() { Spacing::Joint } else { Spacing::Alone };
+ break (this_spacing, next_tok);
+ }
+ } else {
+ break (Spacing::Alone, next_tok);
+ }
+ };
+ let this_tok = std::mem::replace(&mut self.token, next_tok);
+ buf.push(TokenTree::Token(this_tok, this_spacing));
}
}
}
}
- fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
- let sm = self.string_reader.sess.source_map();
-
- match self.token.kind {
- token::Eof => {
- 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 {
- err.span_label(sp, "unclosed delimiter");
- self.unmatched_braces.push(UnmatchedBrace {
- expected_delim: Delimiter::Brace,
- found_delim: None,
- found_span: self.token.span,
- unclosed_span: Some(sp),
- candidate_span: None,
- });
- }
+ 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 {
+ err.span_label(sp, "unclosed delimiter");
+ self.unmatched_braces.push(UnmatchedBrace {
+ expected_delim: Delimiter::Brace,
+ found_delim: None,
+ found_span: self.token.span,
+ unclosed_span: Some(sp),
+ candidate_span: None,
+ });
+ }
- 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)| {
- 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.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;
+ }
}
- }
- Err(err)
+ 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");
}
- token::OpenDelim(delim) => {
- // The span for beginning of the delimited section
- let pre_span = self.token.span;
-
- // Parse the open delimiter.
- self.open_braces.push((delim, self.token.span));
- self.bump();
+ }
+ err
+ }
- // 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_until_close_delim();
+ fn parse_token_tree_open_delim(&mut self, open_delim: Delimiter) -> TokenTree {
+ // The span for beginning of the delimited section
+ let pre_span = self.token.span;
- // Expand to cover the entire delimited token tree
- let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
+ self.open_braces.push((open_delim, self.token.span));
- match self.token.kind {
- // Correct delimiter.
- token::CloseDelim(d) if d == delim => {
- let (open_brace, open_brace_span) = self.open_braces.pop().unwrap();
- let close_brace_span = 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();
- if tts.is_empty() {
- let empty_block_span = open_brace_span.to(close_brace_span);
- 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(delim, empty_block_span);
- }
- }
+ // Expand to cover the entire delimited token tree
+ let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
- //only add braces
- if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, delim) {
- self.matching_block_spans.push((open_brace_span, close_brace_span));
- }
+ 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 close_brace_span = self.token.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,
- ));
- }
- // Parse the closing delimiter.
- self.bump();
+ if tts.is_empty() {
+ 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);
}
- // Incorrect delimiter.
- token::CloseDelim(other) => {
- let mut unclosed_delimiter = None;
- let mut candidate = None;
-
- if self.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);
- // 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() {
- unclosed_delimiter = Some(sp);
- };
- 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 == &other {
- candidate = Some(*brace_span);
- }
- }
- }
- }
- let (tok, _) = self.open_braces.pop().unwrap();
- self.unmatched_braces.push(UnmatchedBrace {
- expected_delim: tok,
- found_delim: Some(other),
- found_span: self.token.span,
- unclosed_span: unclosed_delimiter,
- candidate_span: candidate,
- });
- } else {
- self.open_braces.pop();
- }
+ }
- // If the incorrect delimiter matches an earlier opening
- // delimiter, then don't consume it (it can be used to
- // close the earlier one). Otherwise, consume it.
- // E.g., we try to recover from:
- // fn foo() {
- // bar(baz(
- // } // Incorrect delimiter but matches the earlier `{`
- if !self.open_braces.iter().any(|&(b, _)| b == other) {
- self.bump();
- }
- }
- token::Eof => {
- // Silently recover, the EOF token will be seen again
- // and an error emitted then. Thus we don't pop from
- // self.open_braces here.
- }
- _ => {}
+ //only add braces
+ if let (Delimiter::Brace, Delimiter::Brace) = (open_brace, open_delim) {
+ self.matching_block_spans.push((open_brace_span, close_brace_span));
}
- Ok(TokenTree::Delimited(delim_span, delim, tts))
+ 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;
}
- token::CloseDelim(delim) => {
- // An unexpected closing delimiter (i.e., there is no
- // matching opening delimiter).
- let token_str = token_to_string(&self.token);
- let msg = format!("unexpected closing delimiter: `{}`", token_str);
- let mut err =
- self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
+ // Incorrect delimiter.
+ token::CloseDelim(close_delim) => {
+ let mut unclosed_delimiter = None;
+ let mut candidate = None;
- // 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");
+ if self.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);
+ // 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() {
+ 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);
+ }
+ }
}
- } else {
- err.span_label(parent.0, "this opening brace...");
-
- err.span_label(parent.1, "...matches this closing brace");
}
+ let (tok, _) = self.open_braces.pop().unwrap();
+ self.unmatched_braces.push(UnmatchedBrace {
+ expected_delim: tok,
+ found_delim: Some(close_delim),
+ found_span: self.token.span,
+ unclosed_span: unclosed_delimiter,
+ candidate_span: candidate,
+ });
+ } else {
+ self.open_braces.pop();
}
- err.span_label(self.token.span, "unexpected closing delimiter");
- Err(err)
- }
- _ => {
- let tok = self.token.take();
- let mut spacing = self.bump();
- if !self.token.is_op() {
- spacing = Spacing::Alone;
+ // If the incorrect delimiter matches an earlier opening
+ // delimiter, then don't consume it (it can be used to
+ // close the earlier one). Otherwise, consume it.
+ // E.g., we try to recover from:
+ // fn foo() {
+ // bar(baz(
+ // } // Incorrect delimiter but matches the earlier `{`
+ if !self.open_braces.iter().any(|&(b, _)| b == close_delim) {
+ self.token = self.string_reader.next_token().0;
}
- Ok(TokenTree::Token(tok, spacing))
}
+ token::Eof => {
+ // Silently recover, the EOF token will be seen again
+ // and an error emitted then. Thus we don't pop from
+ // self.open_braces here.
+ }
+ _ => unreachable!(),
}
- }
- fn bump(&mut self) -> Spacing {
- let (spacing, token) = self.string_reader.next_token();
- self.token = token;
- spacing
+ TokenTree::Delimited(delim_span, open_delim, tts)
}
-}
-#[derive(Default)]
-struct TokenStreamBuilder {
- buf: Vec<TokenTree>,
-}
+ fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'a> {
+ // An unexpected closing delimiter (i.e., there is no
+ // matching opening delimiter).
+ let token_str = token_to_string(&self.token);
+ let msg = format!("unexpected closing delimiter: `{}`", token_str);
+ let mut err =
+ self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, &msg);
-impl TokenStreamBuilder {
- #[inline(always)]
- fn push(&mut self, tree: TokenTree) {
- if let Some(TokenTree::Token(prev_token, Spacing::Joint)) = self.buf.last()
- && let TokenTree::Token(token, joint) = &tree
- && let Some(glued) = prev_token.glue(token)
- {
- self.buf.pop();
- self.buf.push(TokenTree::Token(glued, *joint));
- } else {
- self.buf.push(tree)
+ // 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");
+ }
}
- }
- fn into_token_stream(self) -> TokenStream {
- TokenStream::new(self.buf)
+ 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 77c4fadab..f075de714 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -113,11 +113,26 @@ pub(crate) fn emit_unescape_error(
} else {
("", "if you meant to write a `str` literal, use double quotes")
};
-
+ let mut escaped = String::with_capacity(lit.len());
+ let mut chrs = lit.chars().peekable();
+ while let Some(first) = chrs.next() {
+ match (first, chrs.peek()) {
+ ('\\', Some('"')) => {
+ escaped.push('\\');
+ escaped.push('"');
+ chrs.next();
+ }
+ ('"', _) => {
+ escaped.push('\\');
+ escaped.push('"')
+ }
+ (c, _) => escaped.push(c),
+ };
+ }
handler.span_suggestion(
span_with_quotes,
msg,
- format!("{}\"{}\"", prefix, lit),
+ format!("{prefix}\"{escaped}\""),
Applicability::MachineApplicable,
);
}
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index a37327f42..3dcadb4c9 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -4,7 +4,6 @@
#![feature(box_patterns)]
#![feature(if_let_guard)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![feature(rustc_attrs)]
#![recursion_limit = "256"]
@@ -33,12 +32,15 @@ use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser};
pub mod lexer;
pub mod validate_attr;
+mod errors;
+
// 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
// `source_str`.
-/// A variant of 'panictry!' that works on a Vec<Diagnostic> instead of a single DiagnosticBuilder.
+/// A variant of 'panictry!' that works on a `Vec<Diagnostic>` instead of a single
+/// `DiagnosticBuilder`.
macro_rules! panictry_buffer {
($handler:expr, $e:expr) => {{
use rustc_errors::FatalError;
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 5fd69b15e..9e4565694 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -1,27 +1,26 @@
+use crate::errors::{InvalidMetaItem, SuffixedLiteralInAttribute};
+
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_ast_pretty::pprust;
-use rustc_errors::{error_code, Diagnostic, PResult};
+use rustc_errors::{error_code, fluent, Diagnostic, IntoDiagnostic, PResult};
use rustc_span::{sym, BytePos, Span};
use std::convert::TryInto;
// Public for rustfmt usage
#[derive(Debug)]
-pub enum InnerAttrPolicy<'a> {
+pub enum InnerAttrPolicy {
Permitted,
- Forbidden { reason: &'a str, saw_doc_comment: bool, prev_outer_attr_sp: Option<Span> },
+ Forbidden(Option<InnerAttrForbiddenReason>),
}
-const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \
- permitted in this context";
-
-pub(super) const DEFAULT_INNER_ATTR_FORBIDDEN: InnerAttrPolicy<'_> = InnerAttrPolicy::Forbidden {
- reason: DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG,
- saw_doc_comment: false,
- prev_outer_attr_sp: None,
-};
+#[derive(Clone, Copy, Debug)]
+pub enum InnerAttrForbiddenReason {
+ InCodeBlock,
+ AfterOuterDocComment { prev_doc_comment_span: Span },
+ AfterOuterAttribute { prev_outer_attr_sp: Span },
+}
enum OuterAttributeType {
DocComment,
@@ -40,17 +39,15 @@ impl<'a> Parser<'a> {
let prev_outer_attr_sp = outer_attrs.last().map(|attr| attr.span);
let inner_error_reason = if just_parsed_doc_comment {
- "an inner attribute is not permitted following an outer doc comment"
- } else if prev_outer_attr_sp.is_some() {
- "an inner attribute is not permitted following an outer attribute"
+ Some(InnerAttrForbiddenReason::AfterOuterDocComment {
+ prev_doc_comment_span: prev_outer_attr_sp.unwrap(),
+ })
+ } else if let Some(prev_outer_attr_sp) = prev_outer_attr_sp {
+ Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp })
} else {
- DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG
- };
- let inner_parse_policy = InnerAttrPolicy::Forbidden {
- reason: inner_error_reason,
- saw_doc_comment: just_parsed_doc_comment,
- prev_outer_attr_sp,
+ None
};
+ let inner_parse_policy = InnerAttrPolicy::Forbidden(inner_error_reason);
just_parsed_doc_comment = false;
Some(self.parse_attribute(inner_parse_policy)?)
} else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind {
@@ -58,7 +55,7 @@ impl<'a> Parser<'a> {
let span = self.token.span;
let mut err = self.sess.span_diagnostic.struct_span_err_with_code(
span,
- "expected outer doc comment",
+ fluent::parser_inner_doc_comment_not_permitted,
error_code!(E0753),
);
if let Some(replacement_span) = self.annotate_following_item_if_applicable(
@@ -69,13 +66,10 @@ impl<'a> Parser<'a> {
token::CommentKind::Block => OuterAttributeType::DocBlockComment,
},
) {
- err.note(
- "inner doc comments like this (starting with `//!` or `/*!`) can \
- only appear before items",
- );
+ err.note(fluent::note);
err.span_suggestion_verbose(
replacement_span,
- "you might have meant to write a regular comment",
+ fluent::suggestion,
"",
rustc_errors::Applicability::MachineApplicable,
);
@@ -113,7 +107,7 @@ impl<'a> Parser<'a> {
// Public for rustfmt usage.
pub fn parse_attribute(
&mut self,
- inner_parse_policy: InnerAttrPolicy<'_>,
+ inner_parse_policy: InnerAttrPolicy,
) -> PResult<'a, ast::Attribute> {
debug!(
"parse_attribute: inner_parse_policy={:?} self.token={:?}",
@@ -122,35 +116,22 @@ impl<'a> Parser<'a> {
let lo = self.token.span;
// Attributes can't have attributes of their own [Editor's note: not with that attitude]
self.collect_tokens_no_attrs(|this| {
- if this.eat(&token::Pound) {
- let style = if this.eat(&token::Not) {
- ast::AttrStyle::Inner
- } else {
- ast::AttrStyle::Outer
- };
+ assert!(this.eat(&token::Pound), "parse_attribute called in non-attribute position");
- this.expect(&token::OpenDelim(Delimiter::Bracket))?;
- let item = this.parse_attr_item(false)?;
- this.expect(&token::CloseDelim(Delimiter::Bracket))?;
- let attr_sp = lo.to(this.prev_token.span);
+ let style =
+ if this.eat(&token::Not) { ast::AttrStyle::Inner } else { ast::AttrStyle::Outer };
- // Emit error if inner attribute is encountered and forbidden.
- if style == ast::AttrStyle::Inner {
- this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
- }
+ this.expect(&token::OpenDelim(Delimiter::Bracket))?;
+ let item = this.parse_attr_item(false)?;
+ this.expect(&token::CloseDelim(Delimiter::Bracket))?;
+ let attr_sp = lo.to(this.prev_token.span);
- Ok(attr::mk_attr_from_item(
- &self.sess.attr_id_generator,
- item,
- None,
- style,
- attr_sp,
- ))
- } else {
- let token_str = pprust::token_to_string(&this.token);
- let msg = &format!("expected `#`, found `{token_str}`");
- Err(this.struct_span_err(this.token.span, msg))
+ // Emit error if inner attribute is encountered and forbidden.
+ if style == ast::AttrStyle::Inner {
+ this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
}
+
+ Ok(attr::mk_attr_from_item(&self.sess.attr_id_generator, item, None, style, attr_sp))
})
}
@@ -190,21 +171,12 @@ impl<'a> Parser<'a> {
ForceCollect::No,
) {
Ok(Some(item)) => {
- let attr_name = match attr_type {
- OuterAttributeType::Attribute => "attribute",
- _ => "doc comment",
- };
- err.span_label(
- item.span,
- &format!("the inner {} doesn't annotate this {}", attr_name, item.kind.descr()),
- );
+ // FIXME(#100717)
+ err.set_arg("item", item.kind.descr());
+ err.span_label(item.span, fluent::label_does_not_annotate_this);
err.span_suggestion_verbose(
replacement_span,
- &format!(
- "to annotate the {}, change the {} from inner to outer style",
- item.kind.descr(),
- attr_name
- ),
+ fluent::sugg_change_inner_to_outer,
match attr_type {
OuterAttributeType::Attribute => "",
OuterAttributeType::DocBlockComment => "*",
@@ -222,22 +194,33 @@ impl<'a> Parser<'a> {
Some(replacement_span)
}
- pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy<'_>) {
- if let InnerAttrPolicy::Forbidden { reason, saw_doc_comment, prev_outer_attr_sp } = policy {
- let prev_outer_attr_note =
- if saw_doc_comment { "previous doc comment" } else { "previous outer attribute" };
-
- let mut diag = self.struct_span_err(attr_sp, reason);
-
- if let Some(prev_outer_attr_sp) = prev_outer_attr_sp {
- diag.span_label(attr_sp, "not permitted following an outer attribute")
- .span_label(prev_outer_attr_sp, prev_outer_attr_note);
- }
+ pub(super) fn error_on_forbidden_inner_attr(&self, attr_sp: Span, policy: InnerAttrPolicy) {
+ if let InnerAttrPolicy::Forbidden(reason) = policy {
+ let mut diag = match reason.as_ref().copied() {
+ Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => {
+ let mut diag = self.struct_span_err(
+ attr_sp,
+ fluent::parser_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
+ }
+ Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => {
+ let mut diag = self.struct_span_err(
+ attr_sp,
+ fluent::parser_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
+ }
+ Some(InnerAttrForbiddenReason::InCodeBlock) | None => {
+ self.struct_span_err(attr_sp, fluent::parser_inner_attr_not_permitted)
+ }
+ };
- diag.note(
- "inner attributes, like `#![no_std]`, annotate the item enclosing them, and \
- are usually found at the beginning of source files",
- );
+ diag.note(fluent::parser_inner_attr_explanation);
if self
.annotate_following_item_if_applicable(
&mut diag,
@@ -246,7 +229,7 @@ impl<'a> Parser<'a> {
)
.is_some()
{
- diag.note("outer attributes, like `#[test]`, annotate the item following them");
+ diag.note(fluent::parser_outer_attr_explanation);
};
diag.emit();
}
@@ -337,12 +320,7 @@ impl<'a> Parser<'a> {
debug!("checking if {:?} is unusuffixed", lit);
if !lit.kind.is_unsuffixed() {
- self.struct_span_err(lit.span, "suffixed literals are not allowed in attributes")
- .help(
- "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), \
- use an unsuffixed version (`1`, `1.0`, etc.)",
- )
- .emit();
+ self.sess.emit_err(SuffixedLiteralInAttribute { span: lit.span });
}
Ok(lit)
@@ -435,9 +413,8 @@ impl<'a> Parser<'a> {
Err(err) => err.cancel(),
}
- let found = pprust::token_to_string(&self.token);
- let msg = format!("expected unsuffixed literal or identifier, found `{found}`");
- Err(self.struct_span_err(self.token.span, &msg))
+ Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() }
+ .into_diagnostic(&self.sess.span_diagnostic))
}
}
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 5fdafd187..1b16ecb5e 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -32,11 +32,6 @@ pub struct AttrWrapper {
start_pos: usize,
}
-// This struct is passed around very frequently,
-// so make sure it doesn't accidentally get larger
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(AttrWrapper, 16);
-
impl AttrWrapper {
pub(super) fn new(attrs: AttrVec, start_pos: usize) -> AttrWrapper {
AttrWrapper { attrs, start_pos }
@@ -96,9 +91,6 @@ struct LazyAttrTokenStreamImpl {
replace_ranges: Box<[ReplaceRange]>,
}
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(LazyAttrTokenStreamImpl, 144);
-
impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
fn to_attr_token_stream(&self) -> AttrTokenStream {
// The token produced by the final call to `{,inlined_}next` was not
@@ -281,16 +273,23 @@ impl<'a> Parser<'a> {
let cursor_snapshot_next_calls = cursor_snapshot.num_next_calls;
let mut end_pos = self.token_cursor.num_next_calls;
+ let mut captured_trailing = false;
+
// Capture a trailing token if requested by the callback 'f'
match trailing {
TrailingToken::None => {}
+ TrailingToken::Gt => {
+ assert_eq!(self.token.kind, token::Gt);
+ }
TrailingToken::Semi => {
assert_eq!(self.token.kind, token::Semi);
end_pos += 1;
+ captured_trailing = true;
}
TrailingToken::MaybeComma => {
if self.token.kind == token::Comma {
end_pos += 1;
+ captured_trailing = true;
}
}
}
@@ -300,11 +299,7 @@ impl<'a> Parser<'a> {
// was not actually bumped past it. When the `LazyAttrTokenStream` gets converted
// into an `AttrTokenStream`, we will create the proper token.
if self.token_cursor.break_last_token {
- assert_eq!(
- trailing,
- TrailingToken::None,
- "Cannot set `break_last_token` and have trailing token"
- );
+ assert!(!captured_trailing, "Cannot set break_last_token and have trailing token");
end_pos += 1;
}
@@ -459,6 +454,16 @@ fn make_token_stream(
panic!("Unexpected last token {:?}", last_token)
}
}
- assert!(stack.is_empty(), "Stack should be empty: final_buf={:?} stack={:?}", final_buf, stack);
AttrTokenStream::new(final_buf.inner)
}
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+ use super::*;
+ use rustc_data_structures::static_assert_size;
+ // tidy-alphabetical-start
+ static_assert_size!(AttrWrapper, 16);
+ static_assert_size!(LazyAttrTokenStreamImpl, 144);
+ // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index be524db78..309717350 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -3,6 +3,19 @@ use super::{
BlockMode, CommaRecoveryMode, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep,
TokenExpectType, TokenType,
};
+use crate::errors::{
+ AmbiguousPlus, AttributeOnParamType, BadQPathStage2, BadTypePlus, BadTypePlusSub,
+ ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg,
+ ConstGenericWithoutBraces, ConstGenericWithoutBracesSugg, DocCommentOnParamType,
+ DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg,
+ GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, InInTypo,
+ IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, ParenthesesInForHead,
+ ParenthesesInForHeadSugg, PatternMethodParamWithoutBody, QuestionMarkInType,
+ QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath,
+ StructLiteralBodyWithoutPathSugg, SuggEscapeToUseAsIdentifier, SuggRemoveComma,
+ UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration,
+ UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead,
+};
use crate::lexer::UnmatchedBrace;
use rustc_ast as ast;
@@ -19,8 +32,8 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{
fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
};
-use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+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};
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
@@ -30,9 +43,6 @@ use std::mem::take;
use crate::parser;
-const TURBOFISH_SUGGESTION_STR: &str =
- "use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments";
-
/// Creates a placeholder argument.
pub(super) fn dummy_arg(ident: Ident) -> Param {
let pat = P(Pat {
@@ -52,34 +62,6 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
}
}
-pub enum Error {
- UselessDocComment,
-}
-
-impl Error {
- fn span_err(
- self,
- sp: impl Into<MultiSpan>,
- handler: &Handler,
- ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
- match self {
- Error::UselessDocComment => {
- let mut err = struct_span_err!(
- handler,
- sp,
- E0585,
- "found a documentation comment that doesn't document anything",
- );
- err.help(
- "doc comments must come before what they document, maybe a comment was \
- intended with `//`?",
- );
- err
- }
- }
- }
-}
-
pub(super) trait RecoverQPath: Sized + 'static {
const PATH_STYLE: PathStyle = PathStyle::Expr;
fn to_ty(&self) -> Option<P<Ty>>;
@@ -242,485 +224,6 @@ impl MultiSugg {
}
}
-#[derive(SessionDiagnostic)]
-#[diag(parser::maybe_report_ambiguous_plus)]
-struct AmbiguousPlus {
- pub sum_ty: String,
- #[primary_span]
- #[suggestion(code = "({sum_ty})")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
-struct BadTypePlus {
- pub ty: String,
- #[primary_span]
- pub span: Span,
- #[subdiagnostic]
- pub sub: BadTypePlusSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub enum BadTypePlusSub {
- #[suggestion(
- parser::add_paren,
- code = "{sum_with_parens}",
- applicability = "machine-applicable"
- )]
- AddParen {
- sum_with_parens: String,
- #[primary_span]
- span: Span,
- },
- #[label(parser::forgot_paren)]
- ForgotParen {
- #[primary_span]
- span: Span,
- },
- #[label(parser::expect_path)]
- ExpectPath {
- #[primary_span]
- span: Span,
- },
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::maybe_recover_from_bad_qpath_stage_2)]
-struct BadQPathStage2 {
- #[primary_span]
- #[suggestion(applicability = "maybe-incorrect")]
- span: Span,
- ty: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::incorrect_semicolon)]
-struct IncorrectSemicolon<'a> {
- #[primary_span]
- #[suggestion_short(applicability = "machine-applicable")]
- span: Span,
- #[help]
- opt_help: Option<()>,
- name: &'a str,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::incorrect_use_of_await)]
-struct IncorrectUseOfAwait {
- #[primary_span]
- #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")]
- span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::incorrect_use_of_await)]
-struct IncorrectAwait {
- #[primary_span]
- span: Span,
- #[suggestion(parser::postfix_suggestion, code = "{expr}.await{question_mark}")]
- sugg_span: (Span, Applicability),
- expr: String,
- question_mark: &'static str,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::in_in_typo)]
-struct InInTypo {
- #[primary_span]
- span: Span,
- #[suggestion(applicability = "machine-applicable")]
- sugg_span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_variable_declaration)]
-pub struct InvalidVariableDeclaration {
- #[primary_span]
- pub span: Span,
- #[subdiagnostic]
- pub sub: InvalidVariableDeclarationSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub enum InvalidVariableDeclarationSub {
- #[suggestion(
- parser::switch_mut_let_order,
- applicability = "maybe-incorrect",
- code = "let mut"
- )]
- SwitchMutLetOrder(#[primary_span] Span),
- #[suggestion(
- parser::missing_let_before_mut,
- applicability = "machine-applicable",
- code = "let mut"
- )]
- MissingLet(#[primary_span] Span),
- #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")]
- UseLetNotAuto(#[primary_span] Span),
- #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")]
- UseLetNotVar(#[primary_span] Span),
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_comparison_operator)]
-pub(crate) struct InvalidComparisonOperator {
- #[primary_span]
- pub span: Span,
- pub invalid: String,
- #[subdiagnostic]
- pub sub: InvalidComparisonOperatorSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub(crate) enum InvalidComparisonOperatorSub {
- #[suggestion_short(
- parser::use_instead,
- applicability = "machine-applicable",
- code = "{correct}"
- )]
- Correctable {
- #[primary_span]
- span: Span,
- invalid: String,
- correct: String,
- },
- #[label(parser::spaceship_operator_invalid)]
- Spaceship(#[primary_span] Span),
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_logical_operator)]
-#[note]
-pub(crate) struct InvalidLogicalOperator {
- #[primary_span]
- pub span: Span,
- pub incorrect: String,
- #[subdiagnostic]
- pub sub: InvalidLogicalOperatorSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub(crate) enum InvalidLogicalOperatorSub {
- #[suggestion_short(
- parser::use_amp_amp_for_conjunction,
- applicability = "machine-applicable",
- code = "&&"
- )]
- Conjunction(#[primary_span] Span),
- #[suggestion_short(
- parser::use_pipe_pipe_for_disjunction,
- applicability = "machine-applicable",
- code = "||"
- )]
- Disjunction(#[primary_span] Span),
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::tilde_is_not_unary_operator)]
-pub(crate) struct TildeAsUnaryOperator(
- #[primary_span]
- #[suggestion_short(applicability = "machine-applicable", code = "!")]
- pub Span,
-);
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::unexpected_token_after_not)]
-pub(crate) struct NotAsNegationOperator {
- #[primary_span]
- pub negated: Span,
- pub negated_desc: String,
- #[suggestion_short(applicability = "machine-applicable", code = "!")]
- pub not: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::malformed_loop_label)]
-pub(crate) struct MalformedLoopLabel {
- #[primary_span]
- #[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
- pub span: Span,
- pub correct_label: Ident,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::lifetime_in_borrow_expression)]
-pub(crate) struct LifetimeInBorrowExpression {
- #[primary_span]
- pub span: Span,
- #[suggestion(applicability = "machine-applicable", code = "")]
- #[label]
- pub lifetime_span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::field_expression_with_generic)]
-pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::macro_invocation_with_qualified_path)]
-pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::unexpected_token_after_label)]
-pub(crate) struct UnexpectedTokenAfterLabel(
- #[primary_span]
- #[label(parser::unexpected_token_after_label)]
- pub Span,
-);
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::require_colon_after_labeled_expression)]
-#[note]
-pub(crate) struct RequireColonAfterLabeledExpression {
- #[primary_span]
- pub span: Span,
- #[label]
- pub label: Span,
- #[suggestion_short(applicability = "machine-applicable", code = ": ")]
- pub label_end: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::do_catch_syntax_removed)]
-#[note]
-pub(crate) struct DoCatchSyntaxRemoved {
- #[primary_span]
- #[suggestion(applicability = "machine-applicable", code = "try")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::float_literal_requires_integer_part)]
-pub(crate) struct FloatLiteralRequiresIntegerPart {
- #[primary_span]
- #[suggestion(applicability = "machine-applicable", code = "{correct}")]
- pub span: Span,
- pub correct: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_int_literal_width)]
-#[help]
-pub(crate) struct InvalidIntLiteralWidth {
- #[primary_span]
- pub span: Span,
- pub width: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_num_literal_base_prefix)]
-#[note]
-pub(crate) struct InvalidNumLiteralBasePrefix {
- #[primary_span]
- #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
- pub span: Span,
- pub fixed: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_num_literal_suffix)]
-#[help]
-pub(crate) struct InvalidNumLiteralSuffix {
- #[primary_span]
- #[label]
- pub span: Span,
- pub suffix: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_float_literal_width)]
-#[help]
-pub(crate) struct InvalidFloatLiteralWidth {
- #[primary_span]
- pub span: Span,
- pub width: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_float_literal_suffix)]
-#[help]
-pub(crate) struct InvalidFloatLiteralSuffix {
- #[primary_span]
- #[label]
- pub span: Span,
- pub suffix: String,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::int_literal_too_large)]
-pub(crate) struct IntLiteralTooLarge {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::missing_semicolon_before_array)]
-pub(crate) struct MissingSemicolonBeforeArray {
- #[primary_span]
- pub open_delim: Span,
- #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")]
- pub semicolon: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::invalid_block_macro_segment)]
-pub(crate) struct InvalidBlockMacroSegment {
- #[primary_span]
- pub span: Span,
- #[label]
- pub context: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::if_expression_missing_then_block)]
-pub(crate) struct IfExpressionMissingThenBlock {
- #[primary_span]
- pub if_span: Span,
- #[subdiagnostic]
- pub sub: IfExpressionMissingThenBlockSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub(crate) enum IfExpressionMissingThenBlockSub {
- #[help(parser::condition_possibly_unfinished)]
- UnfinishedCondition(#[primary_span] Span),
- #[help(parser::add_then_block)]
- AddThenBlock(#[primary_span] Span),
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::if_expression_missing_condition)]
-pub(crate) struct IfExpressionMissingCondition {
- #[primary_span]
- #[label(parser::condition_label)]
- pub if_span: Span,
- #[label(parser::block_label)]
- pub block_span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::expected_expression_found_let)]
-pub(crate) struct ExpectedExpressionFoundLet {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::expected_else_block)]
-pub(crate) struct ExpectedElseBlock {
- #[primary_span]
- pub first_tok_span: Span,
- pub first_tok: String,
- #[label]
- pub else_span: Span,
- #[suggestion(applicability = "maybe-incorrect", code = "if ")]
- pub condition_start: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::outer_attribute_not_allowed_on_if_else)]
-pub(crate) struct OuterAttributeNotAllowedOnIfElse {
- #[primary_span]
- pub last: Span,
-
- #[label(parser::branch_label)]
- pub branch_span: Span,
-
- #[label(parser::ctx_label)]
- pub ctx_span: Span,
- pub ctx: String,
-
- #[suggestion(applicability = "machine-applicable", code = "")]
- pub attributes: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::missing_in_in_for_loop)]
-pub(crate) struct MissingInInForLoop {
- #[primary_span]
- pub span: Span,
- #[subdiagnostic]
- pub sub: MissingInInForLoopSub,
-}
-
-#[derive(SessionSubdiagnostic)]
-pub(crate) enum MissingInInForLoopSub {
- // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
- #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")]
- InNotOf(#[primary_span] Span),
- #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")]
- AddIn(#[primary_span] Span),
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::missing_comma_after_match_arm)]
-pub(crate) struct MissingCommaAfterMatchArm {
- #[primary_span]
- #[suggestion(applicability = "machine-applicable", code = ",")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::catch_after_try)]
-#[help]
-pub(crate) struct CatchAfterTry {
- #[primary_span]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::comma_after_base_struct)]
-#[note]
-pub(crate) struct CommaAfterBaseStruct {
- #[primary_span]
- pub span: Span,
- #[suggestion_short(applicability = "machine-applicable", code = "")]
- pub comma: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::eq_field_init)]
-pub(crate) struct EqFieldInit {
- #[primary_span]
- pub span: Span,
- #[suggestion(applicability = "machine-applicable", code = ":")]
- pub eq: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::dotdotdot)]
-pub(crate) struct DotDotDot {
- #[primary_span]
- #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
- #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::left_arrow_operator)]
-pub(crate) struct LeftArrowOperator {
- #[primary_span]
- #[suggestion(applicability = "maybe-incorrect", code = "< -")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::remove_let)]
-pub(crate) struct RemoveLet {
- #[primary_span]
- #[suggestion(applicability = "machine-applicable", code = "")]
- pub span: Span,
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(parser::use_eq_instead)]
-pub(crate) struct UseEqInstead {
- #[primary_span]
- #[suggestion_short(applicability = "machine-applicable", code = "=")]
- pub span: Span,
-}
-
// SnapshotParser is used to create a snapshot of the parser
// without causing duplicate errors being emitted when the `Parser`
// is dropped.
@@ -745,15 +248,6 @@ impl<'a> DerefMut for SnapshotParser<'a> {
impl<'a> Parser<'a> {
#[rustc_lint_diagnostics]
- pub(super) fn span_err<S: Into<MultiSpan>>(
- &self,
- sp: S,
- err: Error,
- ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- err.span_err(sp, self.diagnostic())
- }
-
- #[rustc_lint_diagnostics]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -798,10 +292,6 @@ impl<'a> Parser<'a> {
}
pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- let mut err = self.struct_span_err(
- self.token.span,
- &format!("expected identifier, found {}", super::token_descr(&self.token)),
- );
let valid_follow = &[
TokenKind::Eq,
TokenKind::Colon,
@@ -813,34 +303,35 @@ impl<'a> Parser<'a> {
TokenKind::CloseDelim(Delimiter::Brace),
TokenKind::CloseDelim(Delimiter::Parenthesis),
];
- match self.token.ident() {
+ let suggest_raw = match self.token.ident() {
Some((ident, false))
if ident.is_raw_guess()
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
{
- err.span_suggestion_verbose(
- ident.span.shrink_to_lo(),
- &format!("escape `{}` to use it as an identifier", ident.name),
- "r#",
- Applicability::MaybeIncorrect,
- );
+ Some(SuggEscapeToUseAsIdentifier {
+ span: ident.span.shrink_to_lo(),
+ // `Symbol::to_string()` is different from `Symbol::into_diagnostic_arg()`,
+ // which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#`
+ ident_name: ident.name.to_string(),
+ })
}
- _ => {}
- }
- if let Some(token_descr) = super::token_descr_opt(&self.token) {
- err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
- } else {
- err.span_label(self.token.span, "expected identifier");
+ _ => None,
+ };
+
+ let suggest_remove_comma =
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
- err.span_suggestion(
- self.token.span,
- "remove this comma",
- "",
- Applicability::MachineApplicable,
- );
- }
- }
- err
+ Some(SuggRemoveComma { span: self.token.span })
+ } else {
+ None
+ };
+
+ let err = ExpectedIdentifier {
+ span: self.token.span,
+ token: self.token.clone(),
+ suggest_raw,
+ suggest_remove_comma,
+ };
+ err.into_diagnostic(&self.sess.span_diagnostic)
}
pub(super) fn expected_one_of_not_found(
@@ -905,8 +396,8 @@ impl<'a> Parser<'a> {
expected.dedup();
let sm = self.sess.source_map();
- let msg = format!("expected `;`, found {}", super::token_descr(&self.token));
- let appl = Applicability::MachineApplicable;
+
+ // Special-case "expected `;`" errors
if expected.contains(&TokenType::Token(token::Semi)) {
if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP {
// Likely inside a macro, can't provide meaningful suggestions.
@@ -934,11 +425,13 @@ impl<'a> Parser<'a> {
//
// let x = 32:
// let y = 42;
+ self.sess.emit_err(ExpectedSemi {
+ span: self.token.span,
+ token: self.token.clone(),
+ unexpected_token_label: None,
+ sugg: ExpectedSemiSugg::ChangeToSemi(self.token.span),
+ });
self.bump();
- let sp = self.prev_token.span;
- self.struct_span_err(sp, &msg)
- .span_suggestion_short(sp, "change this to `;`", ";", appl)
- .emit();
return Ok(true);
} else if self.look_ahead(0, |t| {
t == &token::CloseDelim(Delimiter::Brace)
@@ -956,11 +449,13 @@ impl<'a> Parser<'a> {
//
// let x = 32
// let y = 42;
- let sp = self.prev_token.span.shrink_to_hi();
- self.struct_span_err(sp, &msg)
- .span_label(self.token.span, "unexpected token")
- .span_suggestion_short(sp, "add `;` here", ";", appl)
- .emit();
+ let span = self.prev_token.span.shrink_to_hi();
+ self.sess.emit_err(ExpectedSemi {
+ span,
+ token: self.token.clone(),
+ unexpected_token_label: Some(self.token.span),
+ sugg: ExpectedSemiSugg::AddSemi(span),
+ });
return Ok(true);
}
}
@@ -997,6 +492,7 @@ impl<'a> Parser<'a> {
)
};
self.last_unexpected_token_span = Some(self.token.span);
+ // FIXME: translation requires list formatting (for `expect`)
let mut err = self.struct_span_err(self.token.span, &msg_exp);
if let TokenKind::Ident(symbol, _) = &self.prev_token.kind {
@@ -1005,7 +501,7 @@ impl<'a> Parser<'a> {
self.prev_token.span,
&format!("write `fn` instead of `{symbol}` to declare a function"),
"fn",
- appl,
+ Applicability::MachineApplicable,
);
}
}
@@ -1019,7 +515,7 @@ impl<'a> Parser<'a> {
self.prev_token.span,
"write `pub` instead of `public` to make the item public",
"pub",
- appl,
+ Applicability::MachineApplicable,
);
}
@@ -1157,19 +653,13 @@ impl<'a> Parser<'a> {
// field: value,
// } }
err.delay_as_bug();
- self.struct_span_err(
- expr.span,
- fluent::parser::struct_literal_body_without_path,
- )
- .multipart_suggestion(
- fluent::parser::suggestion,
- vec![
- (expr.span.shrink_to_lo(), "{ SomeStruct ".to_string()),
- (expr.span.shrink_to_hi(), " }".to_string()),
- ],
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(StructLiteralBodyWithoutPath {
+ span: expr.span,
+ sugg: StructLiteralBodyWithoutPathSugg {
+ before: expr.span.shrink_to_lo(),
+ after: expr.span.shrink_to_hi(),
+ },
+ });
self.restore_snapshot(snapshot);
let mut tail = self.mk_block(
vec![self.mk_stmt_err(expr.span)],
@@ -1363,18 +853,8 @@ impl<'a> Parser<'a> {
self.eat_to_tokens(end);
let span = lo.until(self.token.span);
- let total_num_of_gt = number_of_gt + number_of_shr * 2;
- self.struct_span_err(
- span,
- &format!("unmatched angle bracket{}", pluralize!(total_num_of_gt)),
- )
- .span_suggestion(
- span,
- &format!("remove extra angle bracket{}", pluralize!(total_num_of_gt)),
- "",
- Applicability::MachineApplicable,
- )
- .emit();
+ let num_extra_brackets = number_of_gt + number_of_shr * 2;
+ self.sess.emit_err(UnmatchedAngleBrackets { span, num_extra_brackets });
return true;
}
false
@@ -1403,19 +883,13 @@ impl<'a> Parser<'a> {
let args = AngleBracketedArgs { args, span }.into();
segment.args = args;
- self.struct_span_err(
+ self.sess.emit_err(GenericParamsWithoutAngleBrackets {
span,
- "generic parameters without surrounding angle brackets",
- )
- .multipart_suggestion(
- "surround the type parameters with angle brackets",
- vec![
- (span.shrink_to_lo(), "<".to_string()),
- (trailing_span, ">".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
+ sugg: GenericParamsWithoutAngleBracketsSugg {
+ left: span.shrink_to_lo(),
+ right: trailing_span,
+ },
+ });
} else {
// This doesn't look like an invalid turbofish, can't recover parse state.
self.restore_snapshot(snapshot);
@@ -1452,7 +926,7 @@ impl<'a> Parser<'a> {
if self.eat(&token::Gt) {
e.span_suggestion_verbose(
binop.span.shrink_to_lo(),
- TURBOFISH_SUGGESTION_STR,
+ fluent::parser_sugg_turbofish_syntax,
"::",
Applicability::MaybeIncorrect,
)
@@ -1484,7 +958,7 @@ impl<'a> Parser<'a> {
/// parenthesising the leftmost comparison.
fn attempt_chained_comparison_suggestion(
&mut self,
- err: &mut Diagnostic,
+ err: &mut ComparisonOperatorsCannotBeChained,
inner_op: &Expr,
outer_op: &Spanned<AssocOp>,
) -> bool /* advanced the cursor */ {
@@ -1497,16 +971,6 @@ impl<'a> Parser<'a> {
// suggestion being the only one to apply is high.
return false;
}
- let mut enclose = |left: Span, right: Span| {
- err.multipart_suggestion(
- "parenthesize the comparison",
- vec![
- (left.shrink_to_lo(), "(".to_string()),
- (right.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- };
return match (op.node, &outer_op.node) {
// `x == y == z`
(BinOpKind::Eq, AssocOp::Equal) |
@@ -1520,12 +984,10 @@ impl<'a> Parser<'a> {
self.span_to_snippet(e.span)
.unwrap_or_else(|_| pprust::expr_to_string(&e))
};
- err.span_suggestion_verbose(
- inner_op.span.shrink_to_hi(),
- "split the comparison into two",
- format!(" && {}", expr_to_str(&r1)),
- Applicability::MaybeIncorrect,
- );
+ err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::SplitComparison {
+ span: inner_op.span.shrink_to_hi(),
+ middle_term: expr_to_str(&r1),
+ });
false // Keep the current parse behavior, where the AST is `(x < y) < z`.
}
// `x == y < z`
@@ -1536,7 +998,10 @@ impl<'a> Parser<'a> {
Ok(r2) => {
// We are sure that outer-op-rhs could be consumed, the suggestion is
// likely correct.
- enclose(r1.span, r2.span);
+ err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
+ left: r1.span.shrink_to_lo(),
+ right: r2.span.shrink_to_hi(),
+ });
true
}
Err(expr_err) => {
@@ -1553,7 +1018,10 @@ impl<'a> Parser<'a> {
// further checks are necessary.
match self.parse_expr() {
Ok(_) => {
- enclose(l1.span, r1.span);
+ err.chaining_sugg = Some(ComparisonOperatorsCannotBeChainedSugg::Parenthesize {
+ left: l1.span.shrink_to_lo(),
+ right: r1.span.shrink_to_hi(),
+ });
true
}
Err(expr_err) => {
@@ -1602,18 +1070,11 @@ impl<'a> Parser<'a> {
match inner_op.kind {
ExprKind::Binary(op, ref l1, ref r1) if op.node.is_comparison() => {
- let mut err = self.struct_span_err(
- vec![op.span, self.prev_token.span],
- "comparison operators cannot be chained",
- );
-
- let suggest = |err: &mut Diagnostic| {
- err.span_suggestion_verbose(
- op.span.shrink_to_lo(),
- TURBOFISH_SUGGESTION_STR,
- "::",
- Applicability::MaybeIncorrect,
- );
+ let mut err = ComparisonOperatorsCannotBeChained {
+ span: vec![op.span, self.prev_token.span],
+ suggest_turbofish: None,
+ help_turbofish: None,
+ chaining_sugg: None,
};
// Include `<` to provide this recommendation even in a case like
@@ -1640,7 +1101,7 @@ impl<'a> Parser<'a> {
return if token::ModSep == self.token.kind {
// We have some certainty that this was a bad turbofish at this point.
// `foo< bar >::`
- suggest(&mut err);
+ err.suggest_turbofish = Some(op.span.shrink_to_lo());
let snapshot = self.create_snapshot_for_diagnostic();
self.bump(); // `::`
@@ -1649,7 +1110,7 @@ impl<'a> Parser<'a> {
match self.parse_expr() {
Ok(_) => {
// 99% certain that the suggestion is correct, continue parsing.
- err.emit();
+ self.sess.emit_err(err);
// FIXME: actually check that the two expressions in the binop are
// paths and resynthesize new fn call expression instead of using
// `ExprKind::Err` placeholder.
@@ -1660,18 +1121,18 @@ impl<'a> Parser<'a> {
// Not entirely sure now, but we bubble the error up with the
// suggestion.
self.restore_snapshot(snapshot);
- Err(err)
+ Err(err.into_diagnostic(&self.sess.span_diagnostic))
}
}
} else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
// We have high certainty that this was a bad turbofish at this point.
// `foo< bar >(`
- suggest(&mut err);
+ err.suggest_turbofish = Some(op.span.shrink_to_lo());
// Consume the fn call arguments.
match self.consume_fn_args() {
- Err(()) => Err(err),
+ Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)),
Ok(()) => {
- err.emit();
+ self.sess.emit_err(err);
// FIXME: actually check that the two expressions in the binop are
// paths and resynthesize new fn call expression instead of using
// `ExprKind::Err` placeholder.
@@ -1684,25 +1145,24 @@ impl<'a> Parser<'a> {
{
// All we know is that this is `foo < bar >` and *nothing* else. Try to
// be helpful, but don't attempt to recover.
- err.help(TURBOFISH_SUGGESTION_STR);
- err.help("or use `(...)` if you meant to specify fn arguments");
+ err.help_turbofish = Some(());
}
// If it looks like a genuine attempt to chain operators (as opposed to a
// misformatted turbofish, for instance), suggest a correct form.
if self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op)
{
- err.emit();
+ self.sess.emit_err(err);
mk_err_expr(self, inner_op.span.to(self.prev_token.span))
} else {
// These cases cause too many knock-down errors, bail out (#61329).
- Err(err)
+ Err(err.into_diagnostic(&self.sess.span_diagnostic))
}
};
}
let recover =
self.attempt_chained_comparison_suggestion(&mut err, inner_op, outer_op);
- err.emit();
+ self.sess.emit_err(err);
if recover {
return mk_err_expr(self, inner_op.span.to(self.prev_token.span));
}
@@ -1743,17 +1203,13 @@ impl<'a> Parser<'a> {
pub(super) fn maybe_recover_from_question_mark(&mut self, ty: P<Ty>) -> P<Ty> {
if self.token == token::Question {
self.bump();
- self.struct_span_err(self.prev_token.span, "invalid `?` in type")
- .span_label(self.prev_token.span, "`?` is only allowed on expressions, not types")
- .multipart_suggestion(
- "if you meant to express that the type might not contain a value, use the `Option` wrapper type",
- vec![
- (ty.span.shrink_to_lo(), "Option<".to_string()),
- (self.prev_token.span, ">".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(QuestionMarkInType {
+ span: self.prev_token.span,
+ sugg: QuestionMarkInTypeSugg {
+ left: ty.span.shrink_to_lo(),
+ right: self.prev_token.span,
+ },
+ });
self.mk_ty(ty.span.to(self.prev_token.span), TyKind::Err)
} else {
ty
@@ -1918,9 +1374,17 @@ impl<'a> Parser<'a> {
kind: IncDecRecovery,
(pre_span, post_span): (Span, Span),
) -> MultiSugg {
+ let mut patches = Vec::new();
+
+ if !pre_span.is_empty() {
+ patches.push((pre_span, String::new()));
+ }
+
+ patches.push((post_span, format!(" {}= 1", kind.op.chr())));
+
MultiSugg {
msg: format!("use `{}= 1` instead", kind.op.chr()),
- patches: vec![(pre_span, String::new()), (post_span, format!(" {}= 1", kind.op.chr()))],
+ patches,
applicability: Applicability::MachineApplicable,
}
}
@@ -2005,7 +1469,7 @@ impl<'a> Parser<'a> {
let (prev_sp, sp) = match (&self.token.kind, self.subparser_name) {
// Point at the end of the macro call when reaching end of macro arguments.
(token::Eof, Some(_)) => {
- let sp = self.sess.source_map().next_point(self.prev_token.span);
+ let sp = self.prev_token.span.shrink_to_hi();
(sp, sp)
}
// We don't want to point at the following span after DUMMY_SP.
@@ -2177,19 +1641,16 @@ impl<'a> Parser<'a> {
(token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => {
self.bump();
- self.struct_span_err(
- MultiSpan::from_spans(vec![begin_par_sp, self.prev_token.span]),
- "unexpected parentheses surrounding `for` loop head",
- )
- .multipart_suggestion(
- "remove parentheses in `for` loop",
- vec![(begin_par_sp, String::new()), (self.prev_token.span, String::new())],
+ self.sess.emit_err(ParenthesesInForHead {
+ span: vec![begin_par_sp, self.prev_token.span],
// With e.g. `for (x) in y)` this would replace `(x) in y)`
// with `x) in y)` which is syntactically invalid.
// However, this is prevented before we get here.
- Applicability::MachineApplicable,
- )
- .emit();
+ sugg: ParenthesesInForHeadSugg {
+ left: begin_par_sp,
+ right: self.prev_token.span,
+ },
+ });
// Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint.
pat.and_then(|pat| match pat.kind {
@@ -2408,12 +1869,7 @@ impl<'a> Parser<'a> {
pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) {
if let token::DocComment(..) = self.token.kind {
- self.struct_span_err(
- self.token.span,
- "documentation comments cannot be applied to a function parameter's type",
- )
- .span_label(self.token.span, "doc comments are not allowed here")
- .emit();
+ self.sess.emit_err(DocCommentOnParamType { span: self.token.span });
self.bump();
} else if self.token == token::Pound
&& self.look_ahead(1, |t| *t == token::OpenDelim(Delimiter::Bracket))
@@ -2425,9 +1881,7 @@ impl<'a> Parser<'a> {
}
let sp = lo.to(self.token.span);
self.bump();
- self.struct_span_err(sp, "attributes cannot be applied to a function parameter's type")
- .span_label(sp, "attributes are not allowed here")
- .emit();
+ self.sess.emit_err(AttributeOnParamType { span: sp });
}
}
@@ -2548,19 +2002,7 @@ impl<'a> Parser<'a> {
self.expect(&token::Colon)?;
let ty = self.parse_ty()?;
- struct_span_err!(
- self.diagnostic(),
- pat.span,
- E0642,
- "patterns aren't allowed in methods without bodies",
- )
- .span_suggestion_short(
- pat.span,
- "give this argument a name or use an underscore to ignore it",
- "_",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(PatternMethodParamWithoutBody { span: pat.span });
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
let pat =
@@ -2569,11 +2011,9 @@ impl<'a> Parser<'a> {
}
pub(super) fn recover_bad_self_param(&mut self, mut param: Param) -> PResult<'a, Param> {
- let sp = param.pat.span;
+ let span = param.pat.span;
param.ty.kind = TyKind::Err;
- self.struct_span_err(sp, "unexpected `self` parameter in function")
- .span_label(sp, "must be the first parameter of an associated function")
- .emit();
+ self.sess.emit_err(SelfParamNotFirst { span });
Ok(param)
}
@@ -2607,7 +2047,7 @@ impl<'a> Parser<'a> {
pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let (span, msg) = match (&self.token.kind, self.subparser_name) {
(&token::Eof, Some(origin)) => {
- let sp = self.sess.source_map().next_point(self.prev_token.span);
+ let sp = self.prev_token.span.shrink_to_hi();
(sp, format!("expected expression, found end of {origin}"))
}
_ => (
@@ -2618,7 +2058,7 @@ impl<'a> Parser<'a> {
let mut err = self.struct_span_err(span, &msg);
let sp = self.sess.source_map().start_point(self.token.span);
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
- self.sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
err.span_label(span, "expected expression");
err
@@ -2722,20 +2162,13 @@ impl<'a> Parser<'a> {
err
})?;
if !self.expr_is_valid_const_arg(&expr) {
- self.struct_span_err(
- expr.span,
- "expressions must be enclosed in braces to be used as const generic \
- arguments",
- )
- .multipart_suggestion(
- "enclose the `const` expression in braces",
- vec![
- (expr.span.shrink_to_lo(), "{ ".to_string()),
- (expr.span.shrink_to_hi(), " }".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(ConstGenericWithoutBraces {
+ span: expr.span,
+ sugg: ConstGenericWithoutBracesSugg {
+ left: expr.span.shrink_to_lo(),
+ right: expr.span.shrink_to_hi(),
+ },
+ });
}
Ok(expr)
}
@@ -2750,24 +2183,30 @@ impl<'a> Parser<'a> {
return None;
}
};
- let mut err =
- self.struct_span_err(param.span(), "unexpected `const` parameter declaration");
- err.span_label(param.span(), "expected a `const` expression, not a parameter declaration");
- if let (Some(generics), Ok(snippet)) =
- (ty_generics, self.sess.source_map().span_to_snippet(param.span()))
- {
- let (span, sugg) = match &generics.params[..] {
- [] => (generics.span, format!("<{snippet}>")),
- [.., generic] => (generic.span().shrink_to_hi(), format!(", {snippet}")),
- };
- err.multipart_suggestion(
- "`const` parameters must be declared for the `impl`",
- vec![(span, sugg), (param.span(), param.ident.to_string())],
- Applicability::MachineApplicable,
- );
- }
+
+ let ident = param.ident.to_string();
+ let sugg = match (ty_generics, self.sess.source_map().span_to_snippet(param.span())) {
+ (Some(Generics { params, span: impl_generics, .. }), Ok(snippet)) => {
+ Some(match &params[..] {
+ [] => UnexpectedConstParamDeclarationSugg::AddParam {
+ impl_generics: *impl_generics,
+ incorrect_decl: param.span(),
+ snippet,
+ ident,
+ },
+ [.., generic] => UnexpectedConstParamDeclarationSugg::AppendParam {
+ impl_generics_end: generic.span().shrink_to_hi(),
+ incorrect_decl: param.span(),
+ snippet,
+ ident,
+ },
+ })
+ }
+ _ => None,
+ };
+ self.sess.emit_err(UnexpectedConstParamDeclaration { span: param.span(), sugg });
+
let value = self.mk_expr_err(param.span());
- err.emit();
Some(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }))
}
@@ -2785,20 +2224,15 @@ impl<'a> Parser<'a> {
self.bump(); // `const`
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
- let mut err = self
- .struct_span_err(start, "expected lifetime, type, or constant, found keyword `const`");
+ let mut err = UnexpectedConstInGenericParam { span: start, to_remove: None };
if self.check_const_arg() {
- err.span_suggestion_verbose(
- start.until(self.token.span),
- "the `const` keyword is only needed in the definition of the type",
- "",
- Applicability::MaybeIncorrect,
- );
- err.emit();
+ err.to_remove = Some(start.until(self.token.span));
+ self.sess.emit_err(err);
Ok(Some(GenericArg::Const(self.parse_const_arg()?)))
} else {
let after_kw_const = self.token.span;
- self.recover_const_arg(after_kw_const, err).map(Some)
+ self.recover_const_arg(after_kw_const, err.into_diagnostic(&self.sess.span_diagnostic))
+ .map(Some)
}
}
@@ -2806,7 +2240,7 @@ impl<'a> Parser<'a> {
///
/// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest
/// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion
- /// if we think that that the resulting expression would be well formed.
+ /// if we think that the resulting expression would be well formed.
pub fn recover_const_arg(
&mut self,
start: Span,
@@ -2904,24 +2338,6 @@ impl<'a> Parser<'a> {
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
}
- /// Get the diagnostics for the cases where `move async` is found.
- ///
- /// `move_async_span` starts at the 'm' of the move keyword and ends with the 'c' of the async keyword
- pub(super) fn incorrect_move_async_order_found(
- &self,
- move_async_span: Span,
- ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- let mut err =
- self.struct_span_err(move_async_span, "the order of `move` and `async` is incorrect");
- err.span_suggestion_verbose(
- move_async_span,
- "try switching the order",
- "async move",
- Applicability::MaybeIncorrect,
- );
- err
- }
-
/// Some special error handling for the "top-level" patterns in a match arm,
/// `for` loop, `let`, &c. (in contrast to subpatterns within such).
pub(crate) fn maybe_recover_colon_colon_in_pat_typo(
@@ -3040,11 +2456,15 @@ impl<'a> Parser<'a> {
}
pub(crate) fn maybe_recover_unexpected_block_label(&mut self) -> bool {
- let Some(label) = self.eat_label().filter(|_| {
- self.eat(&token::Colon) && self.token.kind == token::OpenDelim(Delimiter::Brace)
- }) else {
+ // Check for `'a : {`
+ if !(self.check_lifetime()
+ && self.look_ahead(1, |tok| tok.kind == token::Colon)
+ && self.look_ahead(2, |tok| tok.kind == token::OpenDelim(Delimiter::Brace)))
+ {
return false;
- };
+ }
+ let label = self.eat_label().expect("just checked if a label exists");
+ self.bump(); // eat `:`
let span = label.ident.span.to(self.prev_token.span);
let mut err = self.struct_span_err(span, "block label not supported here");
err.span_label(span, "not supported here");
@@ -3117,17 +2537,11 @@ impl<'a> Parser<'a> {
let (a_span, b_span) = (a.span(), b.span());
let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo());
if self.span_to_snippet(between_span).as_ref().map(|a| &a[..]) == Ok(":: ") {
- let mut err = self.struct_span_err(
- path.span.shrink_to_hi(),
- "expected `:` followed by trait or lifetime",
- );
- err.span_suggestion(
- between_span,
- "use single colon",
- ": ",
- Applicability::MachineApplicable,
- );
- return Err(err);
+ return Err(DoubleColonInBound {
+ span: path.span.shrink_to_hi(),
+ between: between_span,
+ }
+ .into_diagnostic(&self.sess.span_diagnostic));
}
}
}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 725768c1f..a781748ef 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,26 +1,33 @@
-use super::diagnostics::{
- CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
- ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
- FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
- IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
- InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub,
- LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
- MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
- NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression,
- SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
-};
+use super::diagnostics::SnapshotParser;
use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{
AttrWrapper, BlockMode, ClosureSpans, ForceCollect, Parser, PathStyle, Restrictions,
SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
};
-use crate::maybe_recover_from_interpolated_ty_qpath;
-use crate::parser::diagnostics::{
- IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
- InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix,
- MissingCommaAfterMatchArm,
+use crate::errors::{
+ ArrayBracketsInsteadOfSpaces, ArrayBracketsInsteadOfSpacesSugg, AsyncMoveOrderIncorrect,
+ BinaryFloatLiteralNotSupported, BracesForStructLiteral, CatchAfterTry, CommaAfterBaseStruct,
+ ComparisonInterpretedAsGeneric, ComparisonOrShiftInterpretedAsGenericSugg,
+ DoCatchSyntaxRemoved, DotDotDot, EqFieldInit, ExpectedElseBlock, ExpectedExpressionFoundLet,
+ FieldExpressionWithGeneric, FloatLiteralRequiresIntegerPart, FoundExprWouldBeStmt,
+ HexadecimalFloatLiteralNotSupported, IfExpressionMissingCondition,
+ IfExpressionMissingThenBlock, IfExpressionMissingThenBlockSub, IntLiteralTooLarge,
+ InvalidBlockMacroSegment, InvalidComparisonOperator, InvalidComparisonOperatorSub,
+ InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth, InvalidIntLiteralWidth,
+ InvalidInterpolatedExpression, InvalidLiteralSuffix, InvalidLiteralSuffixOnTupleIndex,
+ InvalidLogicalOperator, InvalidLogicalOperatorSub, InvalidNumLiteralBasePrefix,
+ InvalidNumLiteralSuffix, LabeledLoopInBreak, LeadingPlusNotSupported, LeftArrowOperator,
+ LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath, MalformedLoopLabel,
+ MatchArmBodyWithoutBraces, MatchArmBodyWithoutBracesSugg, MissingCommaAfterMatchArm,
+ MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray, NoFieldsForFnCall,
+ NotAsNegationOperator, NotAsNegationOperatorSub, OctalFloatLiteralNotSupported,
+ OuterAttributeNotAllowedOnIfElse, ParenthesesWithStructFields,
+ RequireColonAfterLabeledExpression, ShiftInterpretedAsGeneric, StructLiteralNotAllowedHere,
+ StructLiteralNotAllowedHereSugg, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
+ UnexpectedTokenAfterLabelSugg, WrapExpressionInParentheses,
};
+use crate::maybe_recover_from_interpolated_ty_qpath;
use core::mem;
use rustc_ast::ptr::P;
@@ -35,10 +42,13 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
use rustc_ast::{ClosureBinder, StmtKind};
use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diagnostic, PResult};
+use rustc_errors::{
+ Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
+ StashKey,
+};
+use rustc_session::errors::ExprParenthesesNeeded;
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
use rustc_session::lint::BuiltinLintDiagnostics;
-use rustc_session::SessionDiagnostic;
use rustc_span::source_map::{self, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{BytePos, Pos};
@@ -420,13 +430,11 @@ 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) {
- let mut err = self.struct_span_err(
- self.token.span,
- &format!("expected expression, found `{}`", pprust::token_to_string(&self.token),),
- );
- err.span_label(self.token.span, "expected expression");
- self.sess.expr_parentheses_needed(&mut err, lhs.span);
- err.emit();
+ self.sess.emit_err(FoundExprWouldBeStmt {
+ span: self.token.span,
+ token: self.token.clone(),
+ suggestion: ExprParenthesesNeeded::surrounding(lhs.span),
+ });
}
/// Possibly translate the current token to an associative operator.
@@ -577,21 +585,16 @@ impl<'a> Parser<'a> {
make_it!(this, attrs, |this, _| this.parse_borrow_expr(lo))
}
token::BinOp(token::Plus) if this.look_ahead(1, |tok| tok.is_numeric_lit()) => {
- let mut err = this.struct_span_err(lo, "leading `+` is not supported");
- err.span_label(lo, "unexpected `+`");
+ let mut err =
+ 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) {
- this.sess.expr_parentheses_needed(&mut err, *sp);
+ err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp));
} else {
- err.span_suggestion_verbose(
- lo,
- "try removing the `+`",
- "",
- Applicability::MachineApplicable,
- );
+ err.remove_plus = Some(lo);
}
- err.emit();
+ this.sess.emit_err(err);
this.bump();
this.parse_prefix_expr(None)
@@ -660,12 +663,23 @@ impl<'a> Parser<'a> {
fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
// Emit the error...
let negated_token = self.look_ahead(1, |t| t.clone());
+
+ let sub_diag = if negated_token.is_numeric_lit() {
+ NotAsNegationOperatorSub::SuggestNotBitwise
+ } else if negated_token.is_bool_lit() {
+ NotAsNegationOperatorSub::SuggestNotLogical
+ } else {
+ NotAsNegationOperatorSub::SuggestNotDefault
+ };
+
self.sess.emit_err(NotAsNegationOperator {
negated: negated_token.span,
negated_desc: super::token_descr(&negated_token),
// Span the `not` plus trailing whitespace to avoid
// trailing whitespace after the `!` in our suggestion
- not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
+ sub: sub_diag(
+ self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
+ ),
});
// ...and recover!
@@ -743,9 +757,34 @@ impl<'a> Parser<'a> {
match self.parse_path(PathStyle::Expr) {
Ok(path) => {
- let (op_noun, op_verb) = match self.token.kind {
- token::Lt => ("comparison", "comparing"),
- token::BinOp(token::Shl) => ("shift", "shifting"),
+ let span_after_type = parser_snapshot_after_type.token.span;
+ let expr = mk_expr(
+ self,
+ lhs,
+ self.mk_ty(path.span, TyKind::Path(None, path.clone())),
+ );
+
+ let args_span = self.look_ahead(1, |t| t.span).to(span_after_type);
+ let suggestion = 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::BinOp(token::Shl) => {
+ self.sess.emit_err(ShiftInterpretedAsGeneric {
+ shift: self.token.span,
+ r#type: path,
+ args: args_span,
+ suggestion,
+ })
+ }
_ => {
// We can end up here even without `<` being the next token, for
// example because `parse_ty_no_plus` returns `Err` on keywords,
@@ -759,33 +798,7 @@ impl<'a> Parser<'a> {
// Successfully parsed the type path leaving a `<` yet to parse.
type_err.cancel();
- // Report non-fatal diagnostics, keep `x as usize` as an expression
- // in AST and continue parsing.
- let msg = format!(
- "`<` is interpreted as a start of generic arguments for `{}`, not a {}",
- pprust::path_to_string(&path),
- op_noun,
- );
- let span_after_type = parser_snapshot_after_type.token.span;
- let expr =
- mk_expr(self, lhs, self.mk_ty(path.span, TyKind::Path(None, path)));
-
- self.struct_span_err(self.token.span, &msg)
- .span_label(
- self.look_ahead(1, |t| t.span).to(span_after_type),
- "interpreted as generic arguments",
- )
- .span_label(self.token.span, format!("not interpreted as {op_noun}"))
- .multipart_suggestion(
- &format!("try {op_verb} the cast value"),
- vec![
- (expr.span.shrink_to_lo(), "(".to_string()),
- (expr.span.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
-
+ // Keep `x as usize` as an expression in AST and continue parsing.
expr
}
Err(path_err) => {
@@ -832,7 +845,7 @@ impl<'a> Parser<'a> {
ExprKind::Index(_, _) => "indexing",
ExprKind::Try(_) => "`?`",
ExprKind::Field(_, _) => "a field access",
- ExprKind::MethodCall(_, _, _) => "a method call",
+ ExprKind::MethodCall(_, _, _, _) => "a method call",
ExprKind::Call(_, _) => "a function call",
ExprKind::Await(_) => "`.await`",
ExprKind::Err => return Ok(with_postfix),
@@ -1146,7 +1159,9 @@ impl<'a> Parser<'a> {
}
let span = self.prev_token.span;
let field = ExprKind::Field(base, Ident::new(field, span));
- self.expect_no_suffix(span, "a tuple index", suffix);
+ if let Some(suffix) = suffix {
+ self.expect_no_tuple_index_suffix(span, suffix);
+ }
self.mk_expr(lo.to(span), field)
}
@@ -1184,9 +1199,8 @@ impl<'a> Parser<'a> {
) -> Option<P<Expr>> {
match (seq.as_mut(), snapshot) {
(Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => {
- let name = pprust::path_to_string(&path);
snapshot.bump(); // `(`
- match snapshot.parse_struct_fields(path, false, Delimiter::Parenthesis) {
+ match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) {
Ok((fields, ..))
if snapshot.eat(&token::CloseDelim(Delimiter::Parenthesis)) =>
{
@@ -1196,29 +1210,25 @@ impl<'a> Parser<'a> {
let close_paren = self.prev_token.span;
let span = lo.to(self.prev_token.span);
if !fields.is_empty() {
- let replacement_err = self.struct_span_err(
+ let mut replacement_err = ParenthesesWithStructFields {
span,
- "invalid `struct` delimiters or `fn` call arguments",
- );
- mem::replace(err, replacement_err).cancel();
-
- err.multipart_suggestion(
- &format!("if `{name}` is a struct, use braces as delimiters"),
- vec![
- (open_paren, " { ".to_string()),
- (close_paren, " }".to_string()),
- ],
- Applicability::MaybeIncorrect,
- );
- err.multipart_suggestion(
- &format!("if `{name}` is a function, use the arguments directly"),
- fields
- .into_iter()
- .map(|field| (field.span.until(field.expr.span), String::new()))
- .collect(),
- Applicability::MaybeIncorrect,
- );
- err.emit();
+ r#type: path,
+ braces_for_struct: BracesForStructLiteral {
+ first: open_paren,
+ second: close_paren,
+ },
+ no_fields_for_fn: NoFieldsForFnCall {
+ fields: fields
+ .into_iter()
+ .map(|field| field.span.until(field.expr.span))
+ .collect(),
+ },
+ }
+ .into_diagnostic(&self.sess.span_diagnostic);
+ replacement_err.emit();
+
+ let old_err = mem::replace(err, replacement_err);
+ old_err.cancel();
} else {
err.emit();
}
@@ -1259,12 +1269,10 @@ impl<'a> Parser<'a> {
if self.check(&token::OpenDelim(Delimiter::Parenthesis)) {
// Method call `expr.f()`
- let mut args = self.parse_paren_expr_seq()?;
- args.insert(0, self_arg);
-
+ let args = self.parse_paren_expr_seq()?;
let fn_span = fn_span_lo.to(self.prev_token.span);
let span = lo.to(self.prev_token.span);
- Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args, fn_span)))
+ Ok(self.mk_expr(span, ExprKind::MethodCall(segment, self_arg, args, fn_span)))
} else {
// Field access `expr.f`
if let Some(args) = segment.args {
@@ -1304,7 +1312,7 @@ impl<'a> Parser<'a> {
// 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) {
- self.sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
err
})
@@ -1507,11 +1515,11 @@ impl<'a> Parser<'a> {
/// Parse `'label: $expr`. The label is already parsed.
fn parse_labeled_expr(
&mut self,
- label: Label,
+ label_: Label,
mut consume_colon: bool,
) -> PResult<'a, P<Expr>> {
- let lo = label.ident.span;
- let label = Some(label);
+ let lo = label_.ident.span;
+ 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)
@@ -1524,18 +1532,35 @@ impl<'a> Parser<'a> {
{
self.parse_block_expr(label, lo, BlockCheckMode::Default)
} else if !ate_colon
+ && (matches!(self.token.kind, token::CloseDelim(_) | token::Comma)
+ || self.token.is_op())
+ {
+ let lit = self.recover_unclosed_char(label_.ident, |self_| {
+ self_.sess.create_err(UnexpectedTokenAfterLabel {
+ span: self_.token.span,
+ remove_label: None,
+ enclose_in_block: None,
+ })
+ });
+ consume_colon = false;
+ Ok(self.mk_expr(lo, ExprKind::Lit(lit)))
+ } else if !ate_colon
&& (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.token.span));
+ self.sess.emit_err(UnexpectedTokenAfterLabel {
+ span: self.token.span,
+ remove_label: None,
+ enclose_in_block: None,
+ });
consume_colon = false;
Ok(self.mk_expr_err(lo))
} else {
- // FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions
- let msg = "expected `while`, `for`, `loop` or `{` after a label";
-
- let mut err = self.struct_span_err(self.token.span, msg);
- err.span_label(self.token.span, msg);
+ let mut err = UnexpectedTokenAfterLabel {
+ span: self.token.span,
+ remove_label: None,
+ enclose_in_block: None,
+ };
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
let expr = self.parse_expr().map(|expr| {
@@ -1562,28 +1587,15 @@ impl<'a> Parser<'a> {
// If there are no breaks that may use this label, suggest removing the label and
// recover to the unmodified expression.
if !found_labeled_breaks {
- let msg = "consider removing the label";
- err.span_suggestion_verbose(
- lo.until(span),
- msg,
- "",
- Applicability::MachineApplicable,
- );
+ err.remove_label = Some(lo.until(span));
return expr;
}
- let sugg_msg = "consider enclosing expression in a block";
- let suggestions = vec![
- (span.shrink_to_lo(), "{ ".to_owned()),
- (span.shrink_to_hi(), " }".to_owned()),
- ];
-
- err.multipart_suggestion_verbose(
- sugg_msg,
- suggestions,
- Applicability::MachineApplicable,
- );
+ err.enclose_in_block = Some(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));
@@ -1591,7 +1603,7 @@ impl<'a> Parser<'a> {
self.mk_expr(span, ExprKind::Block(blk, label))
});
- err.emit();
+ self.sess.emit_err(err);
expr
}?;
@@ -1606,6 +1618,39 @@ impl<'a> Parser<'a> {
Ok(expr)
}
+ /// Emit an error when a char is parsed as a lifetime because of a missing quote
+ pub(super) fn recover_unclosed_char(
+ &mut self,
+ lifetime: Ident,
+ err: impl FnOnce(&mut Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>,
+ ) -> ast::Lit {
+ if let Some(mut diag) =
+ self.sess.span_diagnostic.steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar)
+ {
+ diag.span_suggestion_verbose(
+ lifetime.span.shrink_to_hi(),
+ "add `'` to close the char literal",
+ "'",
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ } else {
+ err(self)
+ .span_suggestion_verbose(
+ lifetime.span.shrink_to_hi(),
+ "add `'` to close the char literal",
+ "'",
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ }
+ ast::Lit {
+ token_lit: token::Lit::new(token::LitKind::Char, lifetime.name, None),
+ kind: ast::LitKind::Char(lifetime.name.as_str().chars().next().unwrap_or('_')),
+ span: lifetime.span,
+ }
+ }
+
/// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
let lo = self.token.span;
@@ -1662,19 +1707,13 @@ impl<'a> Parser<'a> {
// 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.take().unwrap(), true)?;
- self.struct_span_err(
- lexpr.span,
- "parentheses are required around this expression to avoid confusion with a labeled break expression",
- )
- .multipart_suggestion(
- "wrap the expression in parentheses",
- vec![
- (lexpr.span.shrink_to_lo(), "(".to_string()),
- (lexpr.span.shrink_to_hi(), ")".to_string()),
- ],
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(LabeledLoopInBreak {
+ span: lexpr.span,
+ sub: WrapExpressionInParentheses {
+ left: lexpr.span.shrink_to_lo(),
+ right: lexpr.span.shrink_to_hi(),
+ },
+ });
Some(lexpr)
} else if self.token != token::OpenDelim(Delimiter::Brace)
|| !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL)
@@ -1737,7 +1776,7 @@ impl<'a> Parser<'a> {
}
pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> {
- self.parse_opt_lit().ok_or_else(|| {
+ self.parse_opt_lit().ok_or(()).or_else(|()| {
if let token::Interpolated(inner) = &self.token.kind {
let expr = match inner.as_ref() {
token::NtExpr(expr) => Some(expr),
@@ -1746,16 +1785,25 @@ impl<'a> Parser<'a> {
};
if let Some(expr) = expr {
if matches!(expr.kind, ExprKind::Err) {
- let mut err = self
- .diagnostic()
- .struct_span_err(self.token.span, "invalid interpolated expression");
+ let mut err = InvalidInterpolatedExpression { span: self.token.span }
+ .into_diagnostic(&self.sess.span_diagnostic);
err.downgrade_to_delayed_bug();
- return err;
+ return Err(err);
}
}
}
- let msg = format!("unexpected token: {}", super::token_descr(&self.token));
- self.struct_span_err(self.token.span, &msg)
+ let token = self.token.clone();
+ let err = |self_: &mut Self| {
+ let msg = format!("unexpected token: {}", super::token_descr(&token));
+ self_.struct_span_err(token.span, &msg)
+ };
+ // On an error path, eagerly consider a lifetime to be an unclosed character lit
+ if self.token.is_lifetime() {
+ let lt = self.expect_lifetime();
+ Ok(self.recover_unclosed_char(lt.ident, err))
+ } else {
+ Err(err(self))
+ }
})
}
@@ -1780,7 +1828,10 @@ impl<'a> Parser<'a> {
});
if let Some(token) = &recovered {
self.bump();
- self.error_float_lits_must_have_int_part(&token);
+ self.sess.emit_err(FloatLiteralRequiresIntegerPart {
+ span: token.span,
+ correct: pprust::token_to_string(token).into_owned(),
+ });
}
}
@@ -1808,13 +1859,6 @@ impl<'a> Parser<'a> {
}
}
- fn error_float_lits_must_have_int_part(&self, token: &Token) {
- self.sess.emit_err(FloatLiteralRequiresIntegerPart {
- span: token.span,
- correct: pprust::token_to_string(token).into_owned(),
- });
- }
-
fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
// Checks if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
@@ -1843,11 +1887,13 @@ impl<'a> Parser<'a> {
// by lexer, so here we don't report it the second time.
LitError::LexerError => {}
LitError::InvalidSuffix => {
- self.expect_no_suffix(
- span,
- &format!("{} {} literal", kind.article(), kind.descr()),
- suffix,
- );
+ if let Some(suffix) = suffix {
+ self.sess.emit_err(InvalidLiteralSuffix {
+ span,
+ kind: format!("{}", kind.descr()),
+ suffix,
+ });
+ }
}
LitError::InvalidIntSuffix => {
let suf = suffix.expect("suffix error with no suffix");
@@ -1873,15 +1919,12 @@ impl<'a> Parser<'a> {
}
}
LitError::NonDecimalFloat(base) => {
- let descr = match base {
- 16 => "hexadecimal",
- 8 => "octal",
- 2 => "binary",
+ match base {
+ 16 => self.sess.emit_err(HexadecimalFloatLiteralNotSupported { span }),
+ 8 => self.sess.emit_err(OctalFloatLiteralNotSupported { span }),
+ 2 => self.sess.emit_err(BinaryFloatLiteralNotSupported { span }),
_ => unreachable!(),
};
- self.struct_span_err(span, &format!("{descr} float literal is not supported"))
- .span_label(span, "not supported")
- .emit();
}
LitError::IntTooLarge => {
self.sess.emit_err(IntLiteralTooLarge { span });
@@ -1889,38 +1932,17 @@ impl<'a> Parser<'a> {
}
}
- pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<Symbol>) {
- if let Some(suf) = suffix {
- let mut err = if kind == "a tuple index"
- && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf)
- {
- // #59553: warn instead of reject out of hand to allow the fix to percolate
- // through the ecosystem when people fix their macros
- let mut err = self
- .sess
- .span_diagnostic
- .struct_span_warn(sp, &format!("suffixes on {kind} are invalid"));
- err.note(&format!(
- "`{}` is *temporarily* accepted on tuple index fields as it was \
- incorrectly accepted on stable for a few releases",
- suf,
- ));
- err.help(
- "on proc macros, you'll want to use `syn::Index::from` or \
- `proc_macro::Literal::*_unsuffixed` for code that will desugar \
- to tuple field access",
- );
- err.note(
- "see issue #60210 <https://github.com/rust-lang/rust/issues/60210> \
- for more information",
- );
- err
- } else {
- self.struct_span_err(sp, &format!("suffixes on {kind} are invalid"))
- .forget_guarantee()
- };
- err.span_label(sp, format!("invalid suffix `{suf}`"));
- err.emit();
+ pub(super) fn expect_no_tuple_index_suffix(&self, span: Span, suffix: Symbol) {
+ 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 {
+ span,
+ suffix,
+ exception: Some(()),
+ });
+ } else {
+ self.sess.emit_err(InvalidLiteralSuffixOnTupleIndex { span, suffix, exception: None });
}
}
@@ -1954,14 +1976,13 @@ impl<'a> Parser<'a> {
let mut snapshot = self.create_snapshot_for_diagnostic();
match snapshot.parse_array_or_repeat_expr(Delimiter::Brace) {
Ok(arr) => {
- let hi = snapshot.prev_token.span;
- self.struct_span_err(arr.span, "this is a block expression, not an array")
- .multipart_suggestion(
- "to make an array, use square brackets instead of curly braces",
- vec![(lo, "[".to_owned()), (hi, "]".to_owned())],
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(ArrayBracketsInsteadOfSpaces {
+ span: arr.span,
+ sub: ArrayBracketsInsteadOfSpacesSugg {
+ left: lo,
+ right: snapshot.prev_token.span,
+ },
+ });
self.restore_snapshot(snapshot);
Some(self.mk_expr_err(arr.span))
@@ -2088,6 +2109,12 @@ impl<'a> Parser<'a> {
if self.token.kind == TokenKind::Semi
&& matches!(self.token_cursor.frame.delim_sp, Some((Delimiter::Parenthesis, _)))
+ // HACK: This is needed so we can detect whether we're inside a macro,
+ // where regular assumptions about what tokens can follow other tokens
+ // don't necessarily apply.
+ && self.may_recover()
+ // FIXME(Nilstrieb): Remove this check once `may_recover` actually stops recovery
+ && self.subparser_name.is_none()
{
// It is likely that the closure body is a block but where the
// braces have been removed. We will recover and eat the next
@@ -2124,7 +2151,8 @@ 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(self.incorrect_move_async_order_found(move_async_span))
+ Err(AsyncMoveOrderIncorrect { span: move_async_span }
+ .into_diagnostic(&self.sess.span_diagnostic))
} else {
Ok(CaptureBy::Value)
}
@@ -2208,7 +2236,7 @@ impl<'a> Parser<'a> {
},
ExprKind::Block(_, None) => {
self.sess.emit_err(IfExpressionMissingCondition {
- if_span: self.sess.source_map().next_point(lo),
+ if_span: lo.shrink_to_hi(),
block_span: self.sess.source_map().start_point(cond_span),
});
std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
@@ -2505,39 +2533,22 @@ impl<'a> Parser<'a> {
self.bump(); // `;`
let mut stmts =
vec![self.mk_stmt(first_expr.span, ast::StmtKind::Expr(first_expr.clone()))];
- let err = |this: &mut Parser<'_>, stmts: Vec<ast::Stmt>| {
+ let err = |this: &Parser<'_>, stmts: Vec<ast::Stmt>| {
let span = stmts[0].span.to(stmts[stmts.len() - 1].span);
- let mut err = this.struct_span_err(span, "`match` arm body without braces");
- let (these, s, are) =
- if stmts.len() > 1 { ("these", "s", "are") } else { ("this", "", "is") };
- err.span_label(
- span,
- &format!(
- "{these} statement{s} {are} not surrounded by a body",
- these = these,
- s = s,
- are = are
- ),
- );
- err.span_label(arrow_span, "while parsing the `match` arm starting here");
- if stmts.len() > 1 {
- err.multipart_suggestion(
- &format!("surround the statement{s} with a body"),
- vec![
- (span.shrink_to_lo(), "{ ".to_string()),
- (span.shrink_to_hi(), " }".to_string()),
- ],
- Applicability::MachineApplicable,
- );
- } else {
- err.span_suggestion(
- semi_sp,
- "use a comma to end a `match` arm expression",
- ",",
- Applicability::MachineApplicable,
- );
- }
- err.emit();
+
+ this.sess.emit_err(MatchArmBodyWithoutBraces {
+ statements: span,
+ arrow: arrow_span,
+ num_statements: stmts.len(),
+ sub: if stmts.len() > 1 {
+ MatchArmBodyWithoutBracesSugg::AddBraces {
+ left: span.shrink_to_lo(),
+ right: span.shrink_to_hi(),
+ }
+ } else {
+ MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp }
+ },
+ });
this.mk_expr_err(span)
};
// We might have either a `,` -> `;` typo, or a block without braces. We need
@@ -2826,23 +2837,19 @@ impl<'a> Parser<'a> {
let expr = self.parse_struct_expr(qself.cloned(), 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.error_struct_lit_not_allowed_here(path.span, expr.span);
+ self.sess.emit_err(StructLiteralNotAllowedHere {
+ span: expr.span,
+ sub: StructLiteralNotAllowedHereSugg {
+ left: path.span.shrink_to_lo(),
+ right: expr.span.shrink_to_hi(),
+ },
+ });
}
return Some(expr);
}
None
}
- fn error_struct_lit_not_allowed_here(&self, lo: Span, sp: Span) {
- self.struct_span_err(sp, "struct literals are not allowed here")
- .multipart_suggestion(
- "surround the struct literal with parentheses",
- vec![(lo.shrink_to_lo(), "(".to_string()), (sp.shrink_to_hi(), ")".to_string())],
- Applicability::MachineApplicable,
- )
- .emit();
- }
-
pub(super) fn parse_struct_fields(
&mut self,
pth: ast::Path,
@@ -3137,6 +3144,8 @@ impl<'a> Parser<'a> {
&& this.token.kind == token::Semi
{
TrailingToken::Semi
+ } else if this.token.kind == token::Gt {
+ TrailingToken::Gt
} else {
// FIXME - pass this through from the place where we know
// we need a comma, rather than assuming that `#[attr] expr,`
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 4d0a8b05e..fa75670b2 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -1,7 +1,9 @@
use super::{ForceCollect, Parser, TrailingToken};
use rustc_ast::token;
-use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause};
+use rustc_ast::{
+ self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause,
+};
use rustc_errors::{Applicability, PResult};
use rustc_span::symbol::kw;
@@ -31,13 +33,43 @@ impl<'a> Parser<'a> {
let mut colon_span = None;
let bounds = if self.eat(&token::Colon) {
colon_span = Some(self.prev_token.span);
+ // recover from `impl Trait` in type param bound
+ if self.token.is_keyword(kw::Impl) {
+ let impl_span = self.token.span;
+ let snapshot = self.create_snapshot_for_diagnostic();
+ match self.parse_ty() {
+ Ok(p) => {
+ if let TyKind::ImplTrait(_, bounds) = &(*p).kind {
+ let span = impl_span.to(self.token.span.shrink_to_lo());
+ let mut err = self.struct_span_err(
+ span,
+ "expected trait bound, found `impl Trait` type",
+ );
+ err.span_label(span, "not a trait");
+ if let [bound, ..] = &bounds[..] {
+ err.span_suggestion_verbose(
+ impl_span.until(bound.span()),
+ "use the trait bounds directly",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ }
+ err.emit();
+ return Err(err);
+ }
+ }
+ Err(err) => {
+ err.cancel();
+ }
+ }
+ self.restore_snapshot(snapshot);
+ }
self.parse_generic_bounds(colon_span)?
} else {
Vec::new()
};
let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None };
-
Ok(GenericParam {
ident,
id: ast::DUMMY_NODE_ID,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index e55b5ce71..bda301c52 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -1,4 +1,6 @@
-use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error};
+use crate::errors::{DocCommentDoesNotDocumentAnything, UseEmptyBlockNotSemi};
+
+use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
@@ -13,7 +15,7 @@ use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, Vari
use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
use rustc_ast::{MacArgs, MacCall, MacDelimiter};
use rustc_ast_pretty::pprust;
-use rustc_errors::{struct_span_err, Applicability, PResult, StashKey};
+use rustc_errors::{struct_span_err, Applicability, IntoDiagnostic, PResult, StashKey};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::lev_distance;
use rustc_span::source_map::{self, Span};
@@ -664,6 +666,14 @@ impl<'a> Parser<'a> {
mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
) -> PResult<'a, Vec<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.bump();
+ return Ok(vec![]);
+ }
+
self.expect(&token::OpenDelim(Delimiter::Brace))?;
attrs.extend(self.parse_inner_attributes()?);
@@ -750,8 +760,8 @@ impl<'a> Parser<'a> {
)
.span_label(self.token.span, "this doc comment doesn't document anything")
.help(
- "doc comments must come before what they document, maybe a \
- comment was intended with `//`?",
+ "doc comments must come before what they document, if a comment was \
+ intended use `//`",
)
.emit();
self.bump();
@@ -1283,12 +1293,10 @@ impl<'a> Parser<'a> {
/// Parses an enum declaration.
fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> {
if self.token.is_keyword(kw::Struct) {
- let mut err = self.struct_span_err(
- self.prev_token.span.to(self.token.span),
- "`enum` and `struct` are mutually exclusive",
- );
+ 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(
- self.prev_token.span.to(self.token.span),
+ span,
"replace `enum struct` with",
"enum",
Applicability::MachineApplicable,
@@ -1305,12 +1313,20 @@ impl<'a> Parser<'a> {
let mut generics = self.parse_generics()?;
generics.where_clause = self.parse_where_clause()?;
- let (variants, _) = self
- .parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant())
- .map_err(|e| {
- self.recover_stmt();
- e
- })?;
+ // 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.bump();
+ (vec![], false)
+ } else {
+ self.parse_delim_comma_seq(Delimiter::Brace, |p| p.parse_enum_variant()).map_err(
+ |mut e| {
+ e.span_label(id.span, "while parsing this enum");
+ self.recover_stmt();
+ e
+ },
+ )?
+ };
let enum_definition = EnumDef { variants: variants.into_iter().flatten().collect() };
Ok((id, ItemKind::Enum(enum_definition, generics)))
@@ -1332,7 +1348,8 @@ impl<'a> Parser<'a> {
let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
// Parse a struct variant.
- let (fields, recovered) = this.parse_record_struct_body("struct", false)?;
+ let (fields, recovered) =
+ this.parse_record_struct_body("struct", ident.span, false)?;
VariantData::Struct(fields, recovered)
} else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) {
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
@@ -1386,8 +1403,11 @@ impl<'a> Parser<'a> {
VariantData::Unit(DUMMY_NODE_ID)
} else {
// If we see: `struct Foo<T> where T: Copy { ... }`
- let (fields, recovered) =
- self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
+ let (fields, recovered) = self.parse_record_struct_body(
+ "struct",
+ class_name.span,
+ generics.where_clause.has_where_token,
+ )?;
VariantData::Struct(fields, recovered)
}
// No `where` so: `struct Foo<T>;`
@@ -1395,8 +1415,11 @@ impl<'a> Parser<'a> {
VariantData::Unit(DUMMY_NODE_ID)
// Record-style struct definition
} else if self.token == token::OpenDelim(Delimiter::Brace) {
- let (fields, recovered) =
- self.parse_record_struct_body("struct", generics.where_clause.has_where_token)?;
+ let (fields, recovered) = self.parse_record_struct_body(
+ "struct",
+ class_name.span,
+ generics.where_clause.has_where_token,
+ )?;
VariantData::Struct(fields, recovered)
// Tuple-style struct definition with optional where-clause.
} else if self.token == token::OpenDelim(Delimiter::Parenthesis) {
@@ -1425,12 +1448,18 @@ impl<'a> Parser<'a> {
let vdata = if self.token.is_keyword(kw::Where) {
generics.where_clause = self.parse_where_clause()?;
- let (fields, recovered) =
- self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
+ let (fields, recovered) = self.parse_record_struct_body(
+ "union",
+ class_name.span,
+ generics.where_clause.has_where_token,
+ )?;
VariantData::Struct(fields, recovered)
} else if self.token == token::OpenDelim(Delimiter::Brace) {
- let (fields, recovered) =
- self.parse_record_struct_body("union", generics.where_clause.has_where_token)?;
+ let (fields, recovered) = self.parse_record_struct_body(
+ "union",
+ class_name.span,
+ generics.where_clause.has_where_token,
+ )?;
VariantData::Struct(fields, recovered)
} else {
let token_str = super::token_descr(&self.token);
@@ -1446,6 +1475,7 @@ impl<'a> Parser<'a> {
fn parse_record_struct_body(
&mut self,
adt_ty: &str,
+ ident_span: Span,
parsed_where: bool,
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
let mut fields = Vec::new();
@@ -1460,6 +1490,7 @@ impl<'a> Parser<'a> {
match field {
Ok(field) => fields.push(field),
Err(mut err) => {
+ err.span_label(ident_span, format!("while parsing this {adt_ty}"));
err.emit();
break;
}
@@ -1555,7 +1586,10 @@ impl<'a> Parser<'a> {
token::CloseDelim(Delimiter::Brace) => {}
token::DocComment(..) => {
let previous_span = self.prev_token.span;
- let mut err = self.span_err(self.token.span, Error::UselessDocComment);
+ let mut err = DocCommentDoesNotDocumentAnything {
+ span: self.token.span,
+ missing_comma: None,
+ };
self.bump(); // consume the doc comment
let comma_after_doc_seen = self.eat(&token::Comma);
// `seen_comma` is always false, because we are inside doc block
@@ -1564,18 +1598,13 @@ impl<'a> Parser<'a> {
seen_comma = true;
}
if comma_after_doc_seen || self.token == token::CloseDelim(Delimiter::Brace) {
- err.emit();
+ self.sess.emit_err(err);
} else {
if !seen_comma {
- let sp = self.sess.source_map().next_point(previous_span);
- err.span_suggestion(
- sp,
- "missing comma here",
- ",",
- Applicability::MachineApplicable,
- );
+ let sp = previous_span.shrink_to_hi();
+ err.missing_comma = Some(sp);
}
- return Err(err);
+ return Err(err.into_diagnostic(&self.sess.span_diagnostic));
}
}
_ => {
@@ -1715,6 +1744,7 @@ impl<'a> Parser<'a> {
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
let (ident, is_raw) = self.ident_or_err()?;
if !is_raw && ident.is_reserved() {
+ let snapshot = self.create_snapshot_for_diagnostic();
let err = if self.check_fn_front_matter(false) {
let inherited_vis = Visibility {
span: rustc_span::DUMMY_SP,
@@ -1723,20 +1753,63 @@ impl<'a> Parser<'a> {
};
// We use `parse_fn` to get a span for the function
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
- if let Err(mut db) =
- self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
+ match self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis) {
+ Ok(_) => {
+ let mut err = self.struct_span_err(
+ lo.to(self.prev_token.span),
+ &format!("functions are not allowed in {adt_ty} definitions"),
+ );
+ err.help(
+ "unlike in C++, Java, and C#, functions are declared in `impl` blocks",
+ );
+ err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
+ err
+ }
+ Err(err) => {
+ err.cancel();
+ self.restore_snapshot(snapshot);
+ self.expected_ident_found()
+ }
+ }
+ } else if self.eat_keyword(kw::Struct) {
+ match self.parse_item_struct() {
+ Ok((ident, _)) => {
+ let mut err = self.struct_span_err(
+ lo.with_hi(ident.span.hi()),
+ &format!("structs are not allowed in {adt_ty} definitions"),
+ );
+ err.help("consider creating a new `struct` definition instead of nesting");
+ err
+ }
+ Err(err) => {
+ err.cancel();
+ self.restore_snapshot(snapshot);
+ self.expected_ident_found()
+ }
+ }
+ } else {
+ let mut err = self.expected_ident_found();
+ if self.eat_keyword_noexpect(kw::Let)
+ && let removal_span = self.prev_token.span.until(self.token.span)
+ && let Ok(ident) = self.parse_ident_common(false)
+ // Cancel this error, we don't need it.
+ .map_err(|err| err.cancel())
+ && self.token.kind == TokenKind::Colon
{
- db.delay_as_bug();
+ err.span_suggestion(
+ removal_span,
+ "remove this `let` keyword",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ err.note("the `let` keyword is not allowed in `struct` fields");
+ err.note("see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information");
+ err.emit();
+ return Ok(ident);
+ } else {
+ self.restore_snapshot(snapshot);
}
- let mut err = self.struct_span_err(
- lo.to(self.prev_token.span),
- &format!("functions are not allowed in {adt_ty} definitions"),
- );
- err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
- err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");
err
- } else {
- self.expected_ident_found()
};
return Err(err);
}
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 4cb198561..5fe29062b 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -13,7 +13,6 @@ mod ty;
use crate::lexer::UnmatchedBrace;
pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery;
-use diagnostics::Error;
pub(crate) use item::FnParseMode;
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
pub use path::PathStyle;
@@ -32,7 +31,7 @@ use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashMap;
use rustc_errors::PResult;
use rustc_errors::{
- struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan,
+ Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan,
};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{Span, DUMMY_SP};
@@ -41,6 +40,11 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use std::ops::Range;
use std::{cmp, mem, slice};
+use crate::errors::{
+ DocCommentDoesNotDocumentAnything, IncorrectVisibilityRestriction, MismatchedClosingDelimiter,
+ NonStringAbiLiteral,
+};
+
bitflags::bitflags! {
struct Restrictions: u8 {
const STMT_EXPR = 1 << 0;
@@ -75,6 +79,7 @@ pub enum ForceCollect {
pub enum TrailingToken {
None,
Semi,
+ Gt,
/// If the trailing token is a comma, then capture it
/// Otherwise, ignore the trailing token
MaybeComma,
@@ -110,6 +115,12 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath {
};
}
+#[derive(Clone, Copy)]
+pub enum Recovery {
+ Allowed,
+ Forbidden,
+}
+
#[derive(Clone)]
pub struct Parser<'a> {
pub sess: &'a ParseSess,
@@ -147,12 +158,15 @@ pub struct Parser<'a> {
/// This allows us to recover when the user forget to add braces around
/// multiple statements in the closure body.
pub current_closure: Option<ClosureSpans>,
+ /// Whether the parser is allowed to do recovery.
+ /// This is disabled when parsing macro arguments, see #103534
+ pub recovery: Recovery,
}
-// This type is used a lot, e.g. it's cloned when matching many declarative macro rules. Make sure
+// 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<'_>, 328);
+rustc_data_structures::static_assert_size!(Parser<'_>, 336);
/// Stores span information about a closure.
#[derive(Clone)]
@@ -298,7 +312,10 @@ impl TokenCursor {
fn desugar(&mut self, attr_style: AttrStyle, data: Symbol, span: Span) -> (Token, Spacing) {
// Searches for the occurrences of `"#*` and returns the minimum number of `#`s
- // required to wrap the text.
+ // required to wrap the text. E.g.
+ // - `abc d` is wrapped as `r"abc d"` (num_of_hashes = 0)
+ // - `abc "d"` is wrapped as `r#"abc "d""#` (num_of_hashes = 1)
+ // - `abc "##d##"` is wrapped as `r###"abc "d""###` (num_of_hashes = 3)
let mut num_of_hashes = 0;
let mut count = 0;
for ch in data.as_str().chars() {
@@ -310,6 +327,7 @@ impl TokenCursor {
num_of_hashes = cmp::max(num_of_hashes, count);
}
+ // `/// foo` becomes `doc = r"foo".
let delim_span = DelimSpan::from_single(span);
let body = TokenTree::Delimited(
delim_span,
@@ -406,24 +424,39 @@ pub enum FollowedByType {
No,
}
-fn token_descr_opt(token: &Token) -> Option<&'static str> {
- Some(match token.kind {
- _ if token.is_special_ident() => "reserved identifier",
- _ if token.is_used_keyword() => "keyword",
- _ if token.is_unused_keyword() => "reserved keyword",
- token::DocComment(..) => "doc comment",
- _ => return None,
- })
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum TokenDescription {
+ ReservedIdentifier,
+ Keyword,
+ ReservedKeyword,
+ DocComment,
}
-pub(super) fn token_descr(token: &Token) -> String {
- let token_str = pprust::token_to_string(token);
- match token_descr_opt(token) {
- Some(prefix) => format!("{} `{}`", prefix, token_str),
- _ => format!("`{}`", token_str),
+impl TokenDescription {
+ pub fn from_token(token: &Token) -> Option<Self> {
+ match token.kind {
+ _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier),
+ _ if token.is_used_keyword() => Some(TokenDescription::Keyword),
+ _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword),
+ token::DocComment(..) => Some(TokenDescription::DocComment),
+ _ => None,
+ }
}
}
+pub(super) fn token_descr(token: &Token) -> String {
+ let name = pprust::token_to_string(token).to_string();
+
+ let kind = TokenDescription::from_token(token).map(|kind| match kind {
+ TokenDescription::ReservedIdentifier => "reserved identifier",
+ TokenDescription::Keyword => "keyword",
+ TokenDescription::ReservedKeyword => "reserved keyword",
+ TokenDescription::DocComment => "doc comment",
+ });
+
+ if let Some(kind) = kind { format!("{} `{}`", kind, name) } else { format!("`{}`", name) }
+}
+
impl<'a> Parser<'a> {
pub fn new(
sess: &'a ParseSess,
@@ -459,6 +492,7 @@ impl<'a> Parser<'a> {
inner_attr_ranges: Default::default(),
},
current_closure: None,
+ recovery: Recovery::Allowed,
};
// Make parser point to the first token.
@@ -467,6 +501,22 @@ impl<'a> Parser<'a> {
parser
}
+ pub fn forbid_recovery(mut self) -> Self {
+ self.recovery = Recovery::Forbidden;
+ self
+ }
+
+ /// Whether the parser is allowed to recover from broken code.
+ ///
+ /// If this returns false, recovering broken code into valid code (especially if this recovery does lookahead)
+ /// is not allowed. All recovery done by the parser must be gated behind this check.
+ ///
+ /// Technically, this only needs to restrict eager recovery by doing lookahead at more tokens.
+ /// But making the distinction is very subtle, and simply forbidding all recovery is a lot simpler to uphold.
+ fn may_recover(&self) -> bool {
+ matches!(self.recovery, Recovery::Allowed)
+ }
+
pub fn unexpected<T>(&mut self) -> PResult<'a, T> {
match self.expect_one_of(&[], &[]) {
Err(e) => Err(e),
@@ -518,9 +568,11 @@ impl<'a> Parser<'a> {
fn ident_or_err(&mut self) -> PResult<'a, (Ident, /* is_raw */ bool)> {
self.token.ident().ok_or_else(|| match self.prev_token.kind {
- TokenKind::DocComment(..) => {
- self.span_err(self.prev_token.span, Error::UselessDocComment)
+ TokenKind::DocComment(..) => DocCommentDoesNotDocumentAnything {
+ span: self.prev_token.span,
+ missing_comma: None,
}
+ .into_diagnostic(&self.sess.span_diagnostic),
_ => self.expected_ident_found(),
})
}
@@ -1144,7 +1196,9 @@ impl<'a> Parser<'a> {
fn parse_field_name(&mut self) -> PResult<'a, Ident> {
if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind
{
- self.expect_no_suffix(self.token.span, "a tuple index", suffix);
+ if let Some(suffix) = suffix {
+ self.expect_no_tuple_index_suffix(self.token.span, suffix);
+ }
self.bump();
Ok(Ident::new(symbol, self.prev_token.span))
} else {
@@ -1342,23 +1396,8 @@ impl<'a> Parser<'a> {
let path = self.parse_path(PathStyle::Mod)?;
self.expect(&token::CloseDelim(Delimiter::Parenthesis))?; // `)`
- let msg = "incorrect visibility restriction";
- let suggestion = r##"some possible visibility restrictions are:
-`pub(crate)`: visible only on the current crate
-`pub(super)`: visible only in the current module's parent
-`pub(in path::to::module)`: visible only on the specified path"##;
-
let path_str = pprust::path_to_string(&path);
-
- struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg)
- .help(suggestion)
- .span_suggestion(
- path.span,
- &format!("make this visible only to module `{}` with `in`", path_str),
- format!("in {}", path_str),
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(IncorrectVisibilityRestriction { span: path.span, inner_str: path_str });
Ok(())
}
@@ -1384,14 +1423,7 @@ impl<'a> Parser<'a> {
Err(Some(lit)) => match lit.kind {
ast::LitKind::Err => None,
_ => {
- self.struct_span_err(lit.span, "non-string ABI literal")
- .span_suggestion(
- lit.span,
- "specify the ABI with a string literal",
- "\"C\"",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(NonStringAbiLiteral { span: lit.span });
None
}
},
@@ -1432,25 +1464,18 @@ pub(crate) fn make_unclosed_delims_error(
// `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`.
let found_delim = unmatched.found_delim?;
- let span: MultiSpan = if let Some(sp) = unmatched.unclosed_span {
- vec![unmatched.found_span, sp].into()
- } else {
- unmatched.found_span.into()
- };
- let mut err = sess.span_diagnostic.struct_span_err(
- span,
- &format!(
- "mismatched closing delimiter: `{}`",
- pprust::token_kind_to_string(&token::CloseDelim(found_delim)),
- ),
- );
- err.span_label(unmatched.found_span, "mismatched closing delimiter");
- if let Some(sp) = unmatched.candidate_span {
- err.span_label(sp, "closing delimiter possibly meant for this");
- }
+ let mut spans = vec![unmatched.found_span];
if let Some(sp) = unmatched.unclosed_span {
- err.span_label(sp, "unclosed delimiter");
- }
+ spans.push(sp);
+ };
+ let err = MismatchedClosingDelimiter {
+ spans,
+ delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(),
+ unmatched: unmatched.found_span,
+ opening_candidate: unmatched.candidate_span,
+ unclosed: unmatched.unclosed_span,
+ }
+ .into_diagnostic(&sess.span_diagnostic);
Some(err)
}
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 120a3c267..52c11b4e3 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,5 +1,5 @@
use super::{ForceCollect, Parser, PathStyle, TrailingToken};
-use crate::parser::diagnostics::RemoveLet;
+use crate::errors::RemoveLet;
use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
use rustc_ast::ptr::P;
@@ -10,6 +10,7 @@ use rustc_ast::{
};
use rustc_ast_pretty::pprust;
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::{respan, Span, Spanned};
use rustc_span::symbol::{kw, sym, Ident};
@@ -401,6 +402,25 @@ impl<'a> Parser<'a> {
} else {
PatKind::Path(qself, path)
}
+ } else if matches!(self.token.kind, token::Lifetime(_))
+ // In pattern position, we're totally fine with using "next token isn't colon"
+ // as a heuristic. We could probably just always try to recover if it's a lifetime,
+ // because we never have `'a: label {}` in a pattern position anyways, but it does
+ // keep us from suggesting something like `let 'a: Ty = ..` => `let 'a': Ty = ..`
+ && !self.look_ahead(1, |token| matches!(token.kind, token::Colon))
+ {
+ // Recover a `'a` as a `'a'` literal
+ let lt = self.expect_lifetime();
+ let lit = self.recover_unclosed_char(lt.ident, |self_| {
+ let expected = expected.unwrap_or("pattern");
+ let msg =
+ format!("expected {}, found {}", expected, super::token_descr(&self_.token));
+
+ let mut err = self_.struct_span_err(self_.token.span, &msg);
+ err.span_label(self_.token.span, format!("expected {}", expected));
+ err
+ });
+ PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit)))
} else {
// Try to parse everything else as literal with optional minus
match self.parse_literal_maybe_minus() {
@@ -693,7 +713,7 @@ impl<'a> Parser<'a> {
let sp = self.sess.source_map().start_point(self.token.span);
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
- self.sess.expr_parentheses_needed(&mut err, *sp);
+ err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
}
Err(err)
@@ -776,7 +796,6 @@ impl<'a> Parser<'a> {
/// expression syntax `...expr` for splatting in expressions.
fn parse_pat_range_to(&mut self, mut re: Spanned<RangeEnd>) -> PResult<'a, PatKind> {
let end = self.parse_pat_range_end()?;
- self.sess.gated_spans.gate(sym::half_open_range_patterns, re.span.to(self.prev_token.span));
if let RangeEnd::Included(ref mut syn @ RangeSyntax::DotDotDot) = &mut re.node {
*syn = RangeSyntax::DotDotEq;
self.struct_span_err(re.span, "range-to patterns with `...` are not allowed")
@@ -799,6 +818,7 @@ impl<'a> Parser<'a> {
|| t.kind == token::Dot // e.g. `.5` for recovery;
|| t.can_begin_literal_maybe_minus() // e.g. `42`.
|| t.is_whole_expr()
+ || t.is_lifetime() // recover `'a` instead of `'a'`
})
}
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 3d957406b..12753c678 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,7 +1,5 @@
-use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
-use super::diagnostics::{
- AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
-};
+use super::attr::InnerAttrForbiddenReason;
+use super::diagnostics::AttemptLocalParseRecovery;
use super::expr::LhsExpr;
use super::pat::RecoverComma;
use super::path::PathStyle;
@@ -9,6 +7,12 @@ use super::TrailingToken;
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
};
+use crate::errors::{
+ AssignmentElseNotAllowed, CompoundAssignmentExpressionInLet, ConstLetMutuallyExclusive,
+ DocCommentDoesNotDocumentAnything, ExpectedStatementAfterOuterAttr, InvalidCurlyInLetElse,
+ InvalidExpressionInLetElse, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
+ WrapExpressionInParentheses,
+};
use crate::maybe_whole;
use rustc_ast as ast;
@@ -112,11 +116,7 @@ impl<'a> Parser<'a> {
let bl = self.parse_block()?;
// Destructuring assignment ... else.
// This is not allowed, but point it out in a nice way.
- let mut err = self.struct_span_err(
- e.span.to(bl.span),
- "<assignment> ... else { ... } is not allowed",
- );
- err.emit();
+ self.sess.emit_err(AssignmentElseNotAllowed { span: e.span.to(bl.span) });
}
self.mk_stmt(lo.to(e.span), StmtKind::Expr(e))
} else {
@@ -202,9 +202,12 @@ impl<'a> Parser<'a> {
fn error_outer_attrs(&self, attrs: &[Attribute]) {
if let [.., last] = attrs {
if last.is_doc_comment() {
- self.span_err(last.span, Error::UselessDocComment).emit();
+ self.sess.emit_err(DocCommentDoesNotDocumentAnything {
+ span: last.span,
+ missing_comma: None,
+ });
} else if attrs.iter().any(|a| a.style == AttrStyle::Outer) {
- self.struct_span_err(last.span, "expected statement after outer attribute").emit();
+ self.sess.emit_err(ExpectedStatementAfterOuterAttr { span: last.span });
}
}
}
@@ -255,17 +258,7 @@ 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.struct_span_err(
- lo.to(self.token.span),
- "`const` and `let` are mutually exclusive",
- )
- .span_suggestion(
- lo.to(self.token.span),
- "remove `let`",
- "const",
- Applicability::MaybeIncorrect,
- )
- .emit();
+ self.sess.emit_err(ConstLetMutuallyExclusive { span: lo.to(self.token.span) });
self.bump();
}
@@ -363,44 +356,27 @@ 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() {
- let suggs = vec![
- (init.span.shrink_to_lo(), "(".to_string()),
- (init.span.shrink_to_hi(), ")".to_string()),
- ];
- self.struct_span_err(
- init.span,
- &format!(
- "a `{}` expression cannot be directly assigned in `let...else`",
- op.node.to_string()
- ),
- )
- .multipart_suggestion(
- "wrap the expression in parentheses",
- suggs,
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(InvalidExpressionInLetElse {
+ span: init.span,
+ operator: op.node.to_string(),
+ sugg: WrapExpressionInParentheses {
+ left: init.span.shrink_to_lo(),
+ right: init.span.shrink_to_hi(),
+ },
+ });
}
}
}
fn check_let_else_init_trailing_brace(&self, init: &ast::Expr) {
if let Some(trailing) = classify::expr_trailing_brace(init) {
- let err_span = trailing.span.with_lo(trailing.span.hi() - BytePos(1));
- let suggs = vec![
- (trailing.span.shrink_to_lo(), "(".to_string()),
- (trailing.span.shrink_to_hi(), ")".to_string()),
- ];
- self.struct_span_err(
- err_span,
- "right curly brace `}` before `else` in a `let...else` statement not allowed",
- )
- .multipart_suggestion(
- "try wrapping the expression in parentheses",
- suggs,
- Applicability::MachineApplicable,
- )
- .emit();
+ self.sess.emit_err(InvalidCurlyInLetElse {
+ span: trailing.span.with_lo(trailing.span.hi() - BytePos(1)),
+ sugg: WrapExpressionInParentheses {
+ left: trailing.span.shrink_to_lo(),
+ right: trailing.span.shrink_to_hi(),
+ },
+ });
}
}
@@ -409,18 +385,7 @@ impl<'a> Parser<'a> {
let eq_consumed = match self.token.kind {
token::BinOpEq(..) => {
// Recover `let x <op>= 1` as `let x = 1`
- self.struct_span_err(
- self.token.span,
- "can't reassign to an uninitialized variable",
- )
- .span_suggestion_short(
- self.token.span,
- "initialize the variable",
- "=",
- Applicability::MaybeIncorrect,
- )
- .help("if you meant to overwrite, remove the `let` binding")
- .emit();
+ self.sess.emit_err(CompoundAssignmentExpressionInLet { span: self.token.span });
self.bump();
true
}
@@ -434,7 +399,12 @@ impl<'a> Parser<'a> {
pub(super) fn parse_block(&mut self) -> PResult<'a, P<Block>> {
let (attrs, block) = self.parse_inner_attrs_and_block()?;
if let [.., last] = &*attrs {
- self.error_on_forbidden_inner_attr(last.span, DEFAULT_INNER_ATTR_FORBIDDEN);
+ self.error_on_forbidden_inner_attr(
+ last.span,
+ super::attr::InnerAttrPolicy::Forbidden(Some(
+ InnerAttrForbiddenReason::InCodeBlock,
+ )),
+ );
}
Ok(block)
}
@@ -583,39 +553,46 @@ impl<'a> Parser<'a> {
match stmt.kind {
// Expression without semicolon.
StmtKind::Expr(ref mut expr)
- if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) =>
- {
+ if self.token != token::Eof && classify::expr_requires_semi_to_be_stmt(expr) => {
// Just check for errors and recover; do not eat semicolon yet.
- if let Err(mut e) =
- self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)])
- {
- if let TokenKind::DocComment(..) = self.token.kind {
- if let Ok(snippet) = self.span_to_snippet(self.token.span) {
- let sp = self.token.span;
- let marker = &snippet[..3];
- let (comment_marker, doc_comment_marker) = marker.split_at(2);
-
- e.span_suggestion(
- sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
- &format!(
- "add a space before `{}` to use a regular comment",
- doc_comment_marker,
- ),
- format!("{} {}", comment_marker, doc_comment_marker),
- Applicability::MaybeIncorrect,
- );
+ // `expect_one_of` returns PResult<'a, bool /* recovered */>
+ let replace_with_err =
+ match self.expect_one_of(&[], &[token::Semi, token::CloseDelim(Delimiter::Brace)]) {
+ // Recover from parser, skip type error to avoid extra errors.
+ Ok(true) => true,
+ Err(mut e) => {
+ if let TokenKind::DocComment(..) = self.token.kind &&
+ let Ok(snippet) = self.span_to_snippet(self.token.span) {
+ let sp = self.token.span;
+ let marker = &snippet[..3];
+ let (comment_marker, doc_comment_marker) = marker.split_at(2);
+
+ e.span_suggestion(
+ sp.with_hi(sp.lo() + BytePos(marker.len() as u32)),
+ &format!(
+ "add a space before `{}` to use a regular comment",
+ doc_comment_marker,
+ ),
+ format!("{} {}", comment_marker, doc_comment_marker),
+ Applicability::MaybeIncorrect,
+ );
}
- }
- if let Err(mut e) =
- self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
- {
- if recover.no() {
- return Err(e);
+
+ if let Err(mut e) =
+ self.check_mistyped_turbofish_with_multiple_type_params(e, expr)
+ {
+ if recover.no() {
+ return Err(e);
+ }
+ e.emit();
+ self.recover_stmt();
}
- e.emit();
- self.recover_stmt();
+ true
}
- // Don't complain about type errors in body tail after parse error (#57383).
+ _ => false
+ };
+ if replace_with_err {
+ // We already emitted an error, so don't emit another type error
let sp = expr.span.to(self.prev_token.span);
*expr = self.mk_expr_err(sp);
}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index b47f0c097..2a8512acf 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -397,10 +397,13 @@ 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;
- let msg = "expected mut or const in raw pointer type";
- self.struct_span_err(span, msg)
- .span_label(span, msg)
- .help("use `*mut T` or `*const T` as appropriate")
+ 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()].into_iter(),
+ Applicability::HasPlaceholders,
+ )
.emit();
Mutability::Not
});
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index a9e502016..1394993ab 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -224,7 +224,7 @@ impl<'a> Iterator for Parser<'a> {
'{' => {
let curr_last_brace = self.last_opening_brace;
let byte_pos = self.to_span_index(pos);
- let lbrace_end = InnerOffset(byte_pos.0 + 1);
+ let lbrace_end = self.to_span_index(pos + 1);
self.last_opening_brace = Some(byte_pos.to(lbrace_end));
self.cur.next();
if self.consume('{') {
@@ -740,20 +740,40 @@ impl<'a> Parser<'a> {
word
}
- /// Optionally parses an integer at the current position. This doesn't deal
- /// with overflow at all, it's just accumulating digits.
fn integer(&mut self) -> Option<usize> {
- let mut cur = 0;
+ let mut cur: usize = 0;
let mut found = false;
+ let mut overflow = false;
+ let start = self.current_pos();
while let Some(&(_, c)) = self.cur.peek() {
if let Some(i) = c.to_digit(10) {
- cur = cur * 10 + i as usize;
+ let (tmp, mul_overflow) = cur.overflowing_mul(10);
+ let (tmp, add_overflow) = tmp.overflowing_add(i as usize);
+ if mul_overflow || add_overflow {
+ overflow = true;
+ }
+ cur = tmp;
found = true;
self.cur.next();
} else {
break;
}
}
+
+ if overflow {
+ let end = self.current_pos();
+ let overflowed_int = &self.input[start..end];
+ self.err(
+ format!(
+ "integer `{}` does not fit into the type `usize` whose range is `0..={}`",
+ overflowed_int,
+ usize::MAX
+ ),
+ "integer out of range for `usize`",
+ self.span(start, end),
+ );
+ }
+
if found { Some(cur) } else { None }
}
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 2f8c229c6..3f9cb149b 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -58,6 +58,21 @@ fn invalid06() {
}
#[test]
+fn invalid_position() {
+ musterr("{18446744073709551616}");
+}
+
+#[test]
+fn invalid_width() {
+ musterr("{:18446744073709551616}");
+}
+
+#[test]
+fn invalid_precision() {
+ musterr("{:.18446744073709551616}");
+}
+
+#[test]
fn format_nothing() {
same(
"{}",
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index b3f15ba7c..27a57adf9 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -4,16 +4,21 @@
//! conflicts between multiple such attributes attached to the same
//! item.
-use crate::errors;
+use crate::errors::{
+ self, AttrApplication, DebugVisualizerUnreadable, InvalidAttrAtCrateLevel, ObjectLifetimeErr,
+ OnlyHasEffectOn, TransparentIncompatible, UnrecognizedReprHint,
+};
use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan};
+use rustc_errors::{fluent, Applicability, MultiSpan};
use rustc_expand::base::resolve_path;
use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID};
+use rustc_hir::{
+ self, FnSig, ForeignItem, HirId, Item, ItemKind, TraitItem, CRATE_HIR_ID, CRATE_OWNER_ID,
+};
use rustc_hir::{MethodKind, Target};
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::resolve_lifetime::ObjectLifetimeDefault;
@@ -35,8 +40,8 @@ pub(crate) fn target_from_impl_item<'tcx>(
match impl_item.kind {
hir::ImplItemKind::Const(..) => Target::AssocConst,
hir::ImplItemKind::Fn(..) => {
- let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id());
- let containing_item = tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
+ let containing_item = tcx.hir().expect_item(parent_def_id);
let containing_impl_is_for_trait = match &containing_item.kind {
hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
_ => bug!("parent of an ImplItem must be an Impl"),
@@ -47,7 +52,7 @@ pub(crate) fn target_from_impl_item<'tcx>(
Target::Method(MethodKind::Inherent)
}
}
- hir::ImplItemKind::TyAlias(..) => Target::AssocTy,
+ hir::ImplItemKind::Type(..) => Target::AssocTy,
}
}
@@ -162,17 +167,17 @@ impl CheckAttrVisitor<'_> {
sym::no_mangle => self.check_no_mangle(hir_id, attr, span, target),
sym::deprecated => self.check_deprecated(hir_id, attr, span, target),
sym::macro_use | sym::macro_escape => self.check_macro_use(hir_id, attr, target),
- sym::path => self.check_generic_attr(hir_id, attr, target, &[Target::Mod]),
+ 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 => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Fn])
+ self.check_generic_attr(hir_id, attr, target, Target::Fn)
}
sym::automatically_derived => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Impl])
+ self.check_generic_attr(hir_id, attr, target, Target::Impl)
}
sym::no_implicit_prelude => {
- self.check_generic_attr(hir_id, attr, target, &[Target::Mod])
+ self.check_generic_attr(hir_id, attr, target, Target::Mod)
}
sym::rustc_object_lifetime_default => self.check_object_lifetime_default(hir_id),
_ => {}
@@ -263,7 +268,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with
// just a lint, because we previously erroneously allowed it and some crates used it
- // accidentally, to to be compatible with crates depending on them, we can't throw an
+ // accidentally, to be compatible with crates depending on them, we can't throw an
// error here.
Target::AssocConst => {
self.tcx.emit_spanned_lint(
@@ -349,29 +354,18 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
attr: &Attribute,
target: Target,
- allowed_targets: &[Target],
+ allowed_target: Target,
) {
- if !allowed_targets.iter().any(|t| t == &target) {
- let name = attr.name_or_empty();
- let mut i = allowed_targets.iter();
- // Pluralize
- let b = i.next().map_or_else(String::new, |t| t.to_string() + "s");
- let supported_names = i.enumerate().fold(b, |mut b, (i, allowed_target)| {
- if allowed_targets.len() > 2 && i == allowed_targets.len() - 2 {
- b.push_str(", and ");
- } else if allowed_targets.len() == 2 && i == allowed_targets.len() - 2 {
- b.push_str(" and ");
- } else {
- b.push_str(", ");
- }
- // Pluralize
- b.push_str(&(allowed_target.to_string() + "s"));
- b
- });
- self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
- lint.build(&format!("`#[{name}]` only has an effect on {}", supported_names))
- .emit();
- });
+ if target != allowed_target {
+ self.tcx.emit_spanned_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ OnlyHasEffectOn {
+ attr_name: attr.name_or_empty(),
+ target_name: allowed_target.name().replace(" ", "_"),
+ },
+ );
}
}
@@ -382,7 +376,7 @@ impl CheckAttrVisitor<'_> {
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked");
@@ -427,7 +421,7 @@ impl CheckAttrVisitor<'_> {
ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
};
- tcx.sess.span_err(p.span, &repr);
+ tcx.sess.emit_err(ObjectLifetimeErr { span: p.span, repr });
}
}
}
@@ -462,7 +456,7 @@ impl CheckAttrVisitor<'_> {
Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[track_caller]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
for attr in attrs {
@@ -491,7 +485,7 @@ impl CheckAttrVisitor<'_> {
Target::Struct | Target::Enum | Target::Variant => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[non_exhaustive]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive");
@@ -513,7 +507,7 @@ impl CheckAttrVisitor<'_> {
Target::Trait => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[marker]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker");
@@ -572,7 +566,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[target_feature]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
@@ -640,8 +634,8 @@ impl CheckAttrVisitor<'_> {
let span = meta.span();
if let Some(location) = match target {
Target::AssocTy => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
- let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id;
+ let containing_item = self.tcx.hir().expect_item(parent_def_id);
if Target::from_item(containing_item) == Target::Impl {
Some("type alias in implementation block")
} else {
@@ -649,8 +643,8 @@ impl CheckAttrVisitor<'_> {
}
}
Target::AssocConst => {
- let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
- let containing_item = self.tcx.hir().expect_item(parent_hir_id);
+ let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id;
+ let containing_item = self.tcx.hir().expect_item(parent_def_id);
// We can't link to trait impl's consts.
let err = "associated constant in trait implementation block";
match containing_item.kind {
@@ -828,8 +822,8 @@ impl CheckAttrVisitor<'_> {
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);
+ 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;
}
@@ -875,25 +869,31 @@ impl CheckAttrVisitor<'_> {
hir_id: HirId,
) -> bool {
if hir_id != CRATE_HIR_ID {
- self.tcx.struct_span_lint_hir(INVALID_DOC_ATTRIBUTES, hir_id, meta.span(), |lint| {
- let mut err = lint.build(fluent::passes::attr_crate_level);
- if attr.style == AttrStyle::Outer
- && self.tcx.hir().get_parent_item(hir_id) == CRATE_DEF_ID
- {
- if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
- src.insert(1, '!');
- err.span_suggestion_verbose(
- attr.span,
- fluent::passes::suggestion,
- src,
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_help(attr.span, fluent::passes::help);
+ self.tcx.struct_span_lint_hir(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ fluent::passes_attr_crate_level,
+ |err| {
+ if attr.style == AttrStyle::Outer
+ && self.tcx.hir().get_parent_item(hir_id) == CRATE_OWNER_ID
+ {
+ if let Ok(mut src) = self.tcx.sess.source_map().span_to_snippet(attr.span) {
+ src.insert(1, '!');
+ err.span_suggestion_verbose(
+ attr.span,
+ fluent::suggestion,
+ src,
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_help(attr.span, fluent::help);
+ }
}
- }
- err.note(fluent::passes::note).emit();
- });
+ err.note(fluent::note);
+ err
+ },
+ );
return false;
}
true
@@ -934,6 +934,22 @@ impl CheckAttrVisitor<'_> {
is_valid
}
+ /// Check that the `#![doc(cfg_hide(...))]` attribute only contains a list of attributes.
+ /// Returns `true` if valid.
+ fn check_doc_cfg_hide(&self, meta: &NestedMetaItem, hir_id: HirId) -> bool {
+ if meta.meta_item_list().is_some() {
+ true
+ } else {
+ self.tcx.emit_spanned_lint(
+ INVALID_DOC_ATTRIBUTES,
+ hir_id,
+ meta.span(),
+ errors::DocCfgHideTakesList,
+ );
+ false
+ }
+ }
+
/// Runs various checks on `#[doc]` attributes. Returns `true` if valid.
///
/// `specified_inline` should be initialized to `None` and kept for the scope
@@ -987,6 +1003,13 @@ impl CheckAttrVisitor<'_> {
is_valid = false;
}
+ sym::cfg_hide
+ if !self.check_attr_crate_level(attr, meta, hir_id)
+ || !self.check_doc_cfg_hide(meta, hir_id) =>
+ {
+ is_valid = false;
+ }
+
sym::inline | sym::no_inline
if !self.check_doc_inline(
attr,
@@ -1205,7 +1228,7 @@ impl CheckAttrVisitor<'_> {
Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[cold]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "cold");
@@ -1247,7 +1270,7 @@ impl CheckAttrVisitor<'_> {
Target::ForeignFn | Target::ForeignStatic => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[link_name]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_name");
@@ -1281,7 +1304,7 @@ impl CheckAttrVisitor<'_> {
Target::ExternCrate => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_link]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link");
@@ -1311,7 +1334,7 @@ impl CheckAttrVisitor<'_> {
Target::Method(..) if self.is_impl_item(hir_id) => true,
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[export_name]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name");
@@ -1503,7 +1526,7 @@ impl CheckAttrVisitor<'_> {
Target::Static | Target::Fn | Target::Method(..) => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[link_section]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_section");
@@ -1528,7 +1551,7 @@ impl CheckAttrVisitor<'_> {
Target::Method(..) if self.is_impl_item(hir_id) => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
// `#[no_mangle]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle");
@@ -1594,12 +1617,17 @@ impl CheckAttrVisitor<'_> {
continue;
}
- let (article, allowed_targets) = match hint.name_or_empty() {
+ match hint.name_or_empty() {
sym::C => {
is_c = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
- _ => ("a", "struct, enum, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::align => {
@@ -1615,12 +1643,20 @@ impl CheckAttrVisitor<'_> {
match target {
Target::Struct | Target::Union | Target::Enum | Target::Fn => continue,
- _ => ("a", "struct, enum, function, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumFunctionUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::packed => {
if target != Target::Struct && target != Target::Union {
- ("a", "struct or union")
+ self.tcx.sess.emit_err(AttrApplication::StructUnion {
+ hint_span: hint.span(),
+ span,
+ });
} else {
continue;
}
@@ -1628,7 +1664,9 @@ impl CheckAttrVisitor<'_> {
sym::simd => {
is_simd = true;
if target != Target::Struct {
- ("a", "struct")
+ self.tcx
+ .sess
+ .emit_err(AttrApplication::Struct { hint_span: hint.span(), span });
} else {
continue;
}
@@ -1637,7 +1675,12 @@ impl CheckAttrVisitor<'_> {
is_transparent = true;
match target {
Target::Struct | Target::Union | Target::Enum => continue,
- _ => ("a", "struct, enum, or union"),
+ _ => {
+ self.tcx.sess.emit_err(AttrApplication::StructEnumUnion {
+ hint_span: hint.span(),
+ span,
+ });
+ }
}
}
sym::i8
@@ -1654,35 +1697,18 @@ impl CheckAttrVisitor<'_> {
| sym::usize => {
int_reprs += 1;
if target != Target::Enum {
- ("an", "enum")
+ self.tcx
+ .sess
+ .emit_err(AttrApplication::Enum { hint_span: hint.span(), span });
} else {
continue;
}
}
_ => {
- struct_span_err!(
- self.tcx.sess,
- hint.span(),
- E0552,
- "unrecognized representation hint"
- )
- .help("valid reprs are `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, \
- `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`")
- .emit();
-
+ self.tcx.sess.emit_err(UnrecognizedReprHint { span: hint.span() });
continue;
}
};
-
- struct_span_err!(
- self.tcx.sess,
- hint.span(),
- E0517,
- "{}",
- &format!("attribute should be applied to {article} {allowed_targets}")
- )
- .span_label(span, &format!("not {article} {allowed_targets}"))
- .emit();
}
// Just point at all repr hints if there are any incompatibilities.
@@ -1692,14 +1718,9 @@ impl CheckAttrVisitor<'_> {
// Error on repr(transparent, <anything else>).
if is_transparent && hints.len() > 1 {
let hint_spans: Vec<_> = hint_spans.clone().collect();
- struct_span_err!(
- self.tcx.sess,
- hint_spans,
- E0692,
- "transparent {} cannot have other repr hints",
- target
- )
- .emit();
+ self.tcx
+ .sess
+ .emit_err(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)
@@ -1742,7 +1763,7 @@ impl CheckAttrVisitor<'_> {
}
}
Some(_) => {
- // This error case is handled in rustc_typeck::collect.
+ // This error case is handled in rustc_hir_analysis::collect.
}
None => {
// Default case (compiler) when arg isn't defined.
@@ -1784,7 +1805,7 @@ impl CheckAttrVisitor<'_> {
Target::MacroDef => true,
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm => {
self.inline_attr_str_error_without_macro_def(
@@ -1851,14 +1872,12 @@ impl CheckAttrVisitor<'_> {
match std::fs::File::open(&file) {
Ok(_) => true,
- Err(err) => {
- self.tcx
- .sess
- .struct_span_err(
- meta_item.span,
- &format!("couldn't read {}: {}", file.display(), err),
- )
- .emit();
+ Err(error) => {
+ self.tcx.sess.emit_err(DebugVisualizerUnreadable {
+ span: meta_item.span,
+ file: &file,
+ error,
+ });
false
}
}
@@ -1881,7 +1900,7 @@ impl CheckAttrVisitor<'_> {
}
// FIXME(#80564): We permit struct fields and match arms to have an
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
- // erroneously allowed it and some crates used it accidentally, to to be compatible
+ // erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable");
@@ -2043,7 +2062,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
// so this lets us continue to run them while maintaining backwards compatibility.
// In the long run, the checks should be harmonized.
if let ItemKind::Macro(ref macro_def, _) = item.kind {
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
if macro_def.macro_rules && !self.tcx.has_attr(def_id, sym::macro_export) {
check_non_exported_macro_for_invalid_attrs(self.tcx, item);
}
@@ -2169,25 +2188,11 @@ 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) {
- let mut err = tcx.sess.struct_span_err(
- attr.span,
- &format!(
- "`{}` attribute cannot be used at crate level",
- attr_to_check.to_ident_string()
- ),
- );
- // Only emit an error with a suggestion if we can create a
- // string out of the attribute span
- if let Ok(src) = tcx.sess.source_map().span_to_snippet(attr.span) {
- let replacement = src.replace("#!", "#");
- err.span_suggestion_verbose(
- attr.span,
- "perhaps you meant to use an outer attribute",
- replacement,
- rustc_errors::Applicability::MachineApplicable,
- );
- }
- err.emit();
+ tcx.sess.emit_err(InvalidAttrAtCrateLevel {
+ span: attr.span,
+ snippet: tcx.sess.source_map().span_to_snippet(attr.span).ok(),
+ name: *attr_to_check,
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs
index 70518284c..aa726d6cd 100644
--- a/compiler/rustc_passes/src/check_const.rs
+++ b/compiler/rustc_passes/src/check_const.rs
@@ -8,7 +8,6 @@
//! through, but errors for structured control flow in a `const` should be emitted here.
use rustc_attr as attr;
-use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -18,6 +17,8 @@ use rustc_middle::ty::TyCtxt;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
+use crate::errors::ExprNotAllowedInContext;
+
/// An expression that is not *always* legal in a const context.
#[derive(Clone, Copy)]
enum NonConstExpr {
@@ -133,18 +134,22 @@ impl<'tcx> CheckConstVisitor<'tcx> {
let const_kind =
const_kind.expect("`const_check_violated` may only be called inside a const context");
- let msg = format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
-
let required_gates = required_gates.unwrap_or(&[]);
let missing_gates: Vec<_> =
required_gates.iter().copied().filter(|&g| !features.enabled(g)).collect();
match missing_gates.as_slice() {
[] => {
- struct_span_err!(tcx.sess, span, E0744, "{}", msg).emit();
+ tcx.sess.emit_err(ExprNotAllowedInContext {
+ span,
+ expr: expr.name(),
+ context: const_kind.keyword_name(),
+ });
}
[missing_primary, ref missing_secondary @ ..] => {
+ let msg =
+ format!("{} is not allowed in a `{}`", expr.name(), const_kind.keyword_name());
let mut err = feature_err(&tcx.sess.parse_sess, *missing_primary, span, &msg);
// If multiple feature gates would be required to enable this expression, include
@@ -191,10 +196,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
self.tcx.hir()
}
- fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- intravisit::walk_item(self, item);
- }
-
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
let kind = Some(hir::ConstContext::Const);
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index f141d7bee..753d01f46 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -11,13 +11,15 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Node, PatKind, TyKind};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::middle::privacy;
+use rustc_middle::middle::privacy::Level;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::lint;
use rustc_span::symbol::{sym, Symbol};
use std::mem;
+use crate::errors::UselessAssignment;
+
// Any local node that may call something in its body block should be
// explored. For example, if it's a live Node::Item that is a
// function, then we should explore its block to check for codes that
@@ -102,14 +104,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
}
Res::Def(_, def_id) => self.check_def_id(def_id),
- Res::SelfTy { trait_: t, alias_to: i } => {
- if let Some(t) = t {
- self.check_def_id(t);
- }
- if let Some((i, _)) = i {
- self.check_def_id(i);
- }
- }
+ Res::SelfTyParam { trait_: t } => self.check_def_id(t),
+ Res::SelfTyAlias { alias_to: i, .. } => self.check_def_id(i),
Res::ToolMod | Res::NonMacroAttr(..) | Res::Err => {}
}
}
@@ -186,18 +182,11 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
&& !assign.span.from_expansion()
{
let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));
- self.tcx.struct_span_lint_hir(
+ self.tcx.emit_spanned_lint(
lint::builtin::DEAD_CODE,
assign.hir_id,
assign.span,
- |lint| {
- lint.build(&format!(
- "useless assignment of {} of type `{}` to itself",
- if is_field_assign { "field" } else { "variable" },
- self.typeck_results().expr_ty(lhs),
- ))
- .emit();
- },
+ UselessAssignment { is_field_assign, ty: self.typeck_results().expr_ty(lhs) }
)
}
}
@@ -291,8 +280,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
}
fn visit_node(&mut self, node: Node<'tcx>) {
- if let Node::ImplItem(hir::ImplItem { def_id, .. }) = node
- && self.should_ignore_item(def_id.to_def_id())
+ if let Node::ImplItem(hir::ImplItem { owner_id, .. }) = node
+ && self.should_ignore_item(owner_id.to_def_id())
{
return;
}
@@ -304,7 +293,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
match node {
Node::Item(item) => match item.kind {
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
- let def = self.tcx.adt_def(item.def_id);
+ let def = self.tcx.adt_def(item.owner_id);
self.repr_has_repr_c = def.repr().c();
self.repr_has_repr_simd = def.repr().simd();
@@ -317,7 +306,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
intravisit::walk_trait_item(self, trait_item);
}
Node::ImplItem(impl_item) => {
- let item = self.tcx.local_parent(impl_item.def_id);
+ let item = self.tcx.local_parent(impl_item.owner_id.def_id);
if self.tcx.impl_trait_ref(item).is_none() {
//// If it's a type whose items are live, then it's live, too.
//// This is done to handle the case where, for example, the static
@@ -374,7 +363,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
if has_repr_c || (f.is_positional() && has_repr_simd) {
return Some(def_id);
}
- if !tcx.visibility(f.hir_id.owner).is_public() {
+ if !tcx.visibility(f.hir_id.owner.def_id).is_public() {
return None;
}
if tcx.visibility(def_id).is_public() { Some(def_id) } else { None }
@@ -528,10 +517,10 @@ fn check_item<'tcx>(
) {
let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.hir_id());
if allow_dead_code {
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
- match tcx.def_kind(id.def_id) {
+ match tcx.def_kind(id.owner_id) {
DefKind::Enum => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(ref enum_def, _) = item.kind {
@@ -551,15 +540,15 @@ fn check_item<'tcx>(
}
}
DefKind::Impl => {
- let of_trait = tcx.impl_trait_ref(id.def_id);
+ let of_trait = tcx.impl_trait_ref(id.owner_id);
if of_trait.is_some() {
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
// get DefIds from another query
let local_def_ids = tcx
- .associated_item_def_ids(id.def_id)
+ .associated_item_def_ids(id.owner_id)
.iter()
.filter_map(|def_id| def_id.as_local());
@@ -577,12 +566,12 @@ fn check_item<'tcx>(
if let hir::ItemKind::Struct(ref variant_data, _) = item.kind
&& let Some(ctor_hir_id) = variant_data.ctor_hir_id()
{
- struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.def_id);
+ struct_constructors.insert(tcx.hir().local_def_id(ctor_hir_id), item.owner_id.def_id);
}
}
DefKind::GlobalAsm => {
// global_asm! is always live.
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
_ => {}
}
@@ -590,12 +579,12 @@ fn check_item<'tcx>(
fn check_trait_item<'tcx>(tcx: TyCtxt<'tcx>, worklist: &mut Vec<LocalDefId>, id: hir::TraitItemId) {
use hir::TraitItemKind::{Const, Fn};
- if matches!(tcx.def_kind(id.def_id), DefKind::AssocConst | DefKind::AssocFn) {
+ 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())
{
- worklist.push(trait_item.def_id);
+ worklist.push(trait_item.owner_id.def_id);
}
}
}
@@ -605,27 +594,24 @@ fn check_foreign_item<'tcx>(
worklist: &mut Vec<LocalDefId>,
id: hir::ForeignItemId,
) {
- if matches!(tcx.def_kind(id.def_id), DefKind::Static(_) | DefKind::Fn)
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Static(_) | DefKind::Fn)
&& has_allow_dead_code_or_lang_attr(tcx, id.hir_id())
{
- worklist.push(id.def_id);
+ worklist.push(id.owner_id.def_id);
}
}
fn create_and_seed_worklist<'tcx>(
tcx: TyCtxt<'tcx>,
) -> (Vec<LocalDefId>, FxHashMap<LocalDefId, LocalDefId>) {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
// see `MarkSymbolVisitor::struct_constructors`
let mut struct_constructors = Default::default();
- let mut worklist = access_levels
- .map
+ let mut worklist = effective_visibilities
.iter()
- .filter_map(
- |(&id, &level)| {
- if level >= privacy::AccessLevel::Reachable { Some(id) } else { None }
- },
- )
+ .filter_map(|(&id, effective_vis)| {
+ effective_vis.is_public_at_level(Level::Reachable).then_some(id)
+ })
// Seed entry point
.chain(tcx.entry_fn(()).and_then(|(def_id, _)| def_id.as_local()))
.collect::<Vec<_>>();
@@ -726,6 +712,26 @@ impl<'tcx> DeadVisitor<'tcx> {
})
.collect();
+ let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
+ let span_len = dead_codes.len();
+ let names = match &names[..] {
+ _ if span_len > 6 => String::new(),
+ [name] => format!("`{name}` "),
+ [names @ .., last] => {
+ format!(
+ "{} and `{last}` ",
+ names.iter().map(|name| format!("`{name}`")).join(", ")
+ )
+ }
+ [] => unreachable!(),
+ };
+ let msg = format!(
+ "{these}{descr}{s} {names}{are} never {participle}",
+ these = if span_len > 6 { "multiple " } else { "" },
+ s = pluralize!(span_len),
+ are = pluralize!("is", span_len),
+ );
+
tcx.struct_span_lint_hir(
if is_positional {
lint::builtin::UNUSED_TUPLE_STRUCT_FIELDS
@@ -734,27 +740,8 @@ impl<'tcx> DeadVisitor<'tcx> {
},
tcx.hir().local_def_id_to_hir_id(first_id),
MultiSpan::from_spans(spans.clone()),
- |lint| {
- let descr = tcx.def_kind(first_id).descr(first_id.to_def_id());
- let span_len = dead_codes.len();
- let names = match &names[..] {
- _ if span_len > 6 => String::new(),
- [name] => format!("`{name}` "),
- [names @ .., last] => {
- format!(
- "{} and `{last}` ",
- names.iter().map(|name| format!("`{name}`")).join(", ")
- )
- }
- [] => unreachable!(),
- };
- let mut err = lint.build(&format!(
- "{these}{descr}{s} {names}{are} never {participle}",
- these = if span_len > 6 { "multiple " } else { "" },
- s = pluralize!(span_len),
- are = pluralize!("is", span_len),
- ));
-
+ msg,
+ |err| {
if is_positional {
err.multipart_suggestion(
&format!(
@@ -800,7 +787,7 @@ impl<'tcx> DeadVisitor<'tcx> {
);
err.note(&msg);
}
- err.emit();
+ err
},
);
}
@@ -874,19 +861,19 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
let module_items = tcx.hir_module_items(module);
for item in module_items.items() {
- if !live_symbols.contains(&item.def_id) {
- let parent = tcx.local_parent(item.def_id);
+ if !live_symbols.contains(&item.owner_id.def_id) {
+ let parent = tcx.local_parent(item.owner_id.def_id);
if parent != module && !live_symbols.contains(&parent) {
// We already have diagnosed something.
continue;
}
- visitor.check_definition(item.def_id);
+ visitor.check_definition(item.owner_id.def_id);
continue;
}
- let def_kind = tcx.def_kind(item.def_id);
+ let def_kind = tcx.def_kind(item.owner_id);
if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
- let adt = tcx.adt_def(item.def_id);
+ let adt = tcx.adt_def(item.owner_id);
let mut dead_variants = Vec::new();
for variant in adt.variants() {
@@ -929,16 +916,21 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalDefId) {
visitor.warn_dead_fields_and_variants(def_id, "read", dead_fields, is_positional)
}
- visitor.warn_dead_fields_and_variants(item.def_id, "constructed", dead_variants, false);
+ visitor.warn_dead_fields_and_variants(
+ item.owner_id.def_id,
+ "constructed",
+ dead_variants,
+ false,
+ );
}
}
for impl_item in module_items.impl_items() {
- visitor.check_definition(impl_item.def_id);
+ visitor.check_definition(impl_item.owner_id.def_id);
}
for foreign_item in module_items.foreign_items() {
- visitor.check_definition(foreign_item.def_id);
+ visitor.check_definition(foreign_item.owner_id.def_id);
}
// We do not warn trait items.
diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs
index e08683fe2..253b0a88e 100644
--- a/compiler/rustc_passes/src/debugger_visualizer.rs
+++ b/compiler/rustc_passes/src/debugger_visualizer.rs
@@ -13,6 +13,8 @@ use rustc_span::{sym, DebuggerVisualizerFile, DebuggerVisualizerType};
use std::sync::Arc;
+use crate::errors::DebugVisualizerUnreadable;
+
fn check_for_debugger_visualizer<'tcx>(
tcx: TyCtxt<'tcx>,
hir_id: HirId,
@@ -54,13 +56,12 @@ fn check_for_debugger_visualizer<'tcx>(
debugger_visualizers
.insert(DebuggerVisualizerFile::new(Arc::from(contents), visualizer_type));
}
- Err(err) => {
- tcx.sess
- .struct_span_err(
- meta_item.span,
- &format!("couldn't read {}: {}", file.display(), err),
- )
- .emit();
+ Err(error) => {
+ tcx.sess.emit_err(DebugVisualizerUnreadable {
+ span: meta_item.span,
+ file: &file,
+ error,
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs
index e6b69d898..a72056e00 100644
--- a/compiler/rustc_passes/src/diagnostic_items.rs
+++ b/compiler/rustc_passes/src/diagnostic_items.rs
@@ -14,7 +14,9 @@ use rustc_hir::diagnostic_items::DiagnosticItems;
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::{sym, Symbol};
+use rustc_span::symbol::{kw::Empty, sym, Symbol};
+
+use crate::errors::{DuplicateDiagnosticItem, DuplicateDiagnosticItemInCrate};
fn observe_item<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -33,25 +35,22 @@ 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 mut err = match tcx.hir().span_if_local(item_def_id) {
- Some(span) => tcx
- .sess
- .struct_span_err(span, &format!("duplicate diagnostic item found: `{name}`.")),
- None => tcx.sess.struct_err(&format!(
- "duplicate diagnostic item in crate `{}`: `{}`.",
- tcx.crate_name(item_def_id.krate),
- name
- )),
- };
- if let Some(span) = tcx.hir().span_if_local(original_def_id) {
- err.span_note(span, "the diagnostic item is first defined here");
+ let orig_span = tcx.hir().span_if_local(original_def_id);
+ let orig_crate_name = if orig_span.is_some() {
+ None
} else {
- err.note(&format!(
- "the diagnostic item is first defined in crate `{}`.",
- tcx.crate_name(original_def_id.krate)
- ));
- }
- err.emit();
+ 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,
+ }),
+ };
}
}
}
@@ -74,19 +73,19 @@ fn diagnostic_items<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> DiagnosticItems
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- observe_item(tcx, &mut diagnostic_items, id.def_id);
+ 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.def_id);
+ 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.def_id);
+ 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.def_id);
+ observe_item(tcx, &mut diagnostic_items, id.owner_id.def_id);
}
diagnostic_items
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index cd10170d3..5885f45ae 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -1,5 +1,5 @@
use rustc_ast::entry::EntryPointType;
-use rustc_errors::struct_span_err;
+use rustc_errors::error_code;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
use rustc_hir::{ItemId, Node, CRATE_HIR_ID};
@@ -8,7 +8,12 @@ use rustc_middle::ty::{DefIdTree, TyCtxt};
use rustc_session::config::{sigpipe, CrateType, EntryFnType};
use rustc_session::parse::feature_err;
use rustc_span::symbol::sym;
-use rustc_span::{Span, Symbol, DUMMY_SP};
+use rustc_span::{Span, Symbol};
+
+use crate::errors::{
+ AttrOnlyInFunctions, AttrOnlyOnMain, AttrOnlyOnRootMain, ExternMain, MultipleRustcMain,
+ MultipleStartFunctions, NoMainErr, UnixSigpipeValues,
+};
struct EntryContext<'tcx> {
tcx: TyCtxt<'tcx>,
@@ -57,7 +62,7 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
} else if ctxt.tcx.sess.contains_name(attrs, sym::rustc_main) {
EntryPointType::RustcMainAttr
} else {
- if let Some(name) = ctxt.tcx.opt_item_name(id.def_id.to_def_id())
+ if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id())
&& name == sym::main {
if at_root {
// This is a top-level function so can be `main`.
@@ -71,64 +76,57 @@ fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> Entry
}
}
-fn err_if_attr_found(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol, details: &str) {
+fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
let attrs = ctxt.tcx.hir().attrs(id.hir_id());
- if let Some(attr) = ctxt.tcx.sess.find_by_name(attrs, sym) {
- ctxt.tcx
- .sess
- .struct_span_err(attr.span, &format!("`{}` attribute {}", sym, details))
- .emit();
- }
+ ctxt.tcx.sess.find_by_name(attrs, sym).map(|attr| attr.span)
}
fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
- let at_root = ctxt.tcx.opt_local_parent(id.def_id) == Some(CRATE_DEF_ID);
+ let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
match entry_point_type(ctxt, id, at_root) {
EntryPointType::None => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
+ }
}
- _ if !matches!(ctxt.tcx.def_kind(id.def_id), DefKind::Fn) => {
- err_if_attr_found(ctxt, id, sym::start, "can only be used on functions");
- err_if_attr_found(ctxt, id, sym::rustc_main, "can only be used on functions");
+ _ if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) => {
+ for attr in [sym::start, sym::rustc_main] {
+ if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
+ ctxt.tcx.sess.emit_err(AttrOnlyInFunctions { span, attr });
+ }
+ }
}
EntryPointType::MainNamed => (),
EntryPointType::OtherMain => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on root `fn main()`");
- ctxt.non_main_fns.push(ctxt.tcx.def_span(id.def_id));
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnRootMain { span, attr: sym::unix_sigpipe });
+ }
+ ctxt.non_main_fns.push(ctxt.tcx.def_span(id.owner_id));
}
EntryPointType::RustcMainAttr => {
if ctxt.attr_main_fn.is_none() {
- ctxt.attr_main_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
+ ctxt.attr_main_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
- struct_span_err!(
- ctxt.tcx.sess,
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- E0137,
- "multiple functions with a `#[rustc_main]` attribute"
- )
- .span_label(
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- "additional `#[rustc_main]` function",
- )
- .span_label(ctxt.attr_main_fn.unwrap().1, "first `#[rustc_main]` function")
- .emit();
+ ctxt.tcx.sess.emit_err(MultipleRustcMain {
+ span: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ first: ctxt.attr_main_fn.unwrap().1,
+ additional: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ });
}
}
EntryPointType::Start => {
- err_if_attr_found(ctxt, id, sym::unix_sigpipe, "can only be used on `fn main()`");
+ if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
+ ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
+ }
if ctxt.start_fn.is_none() {
- ctxt.start_fn = Some((id.def_id, ctxt.tcx.def_span(id.def_id.to_def_id())));
+ ctxt.start_fn = Some((id.owner_id.def_id, ctxt.tcx.def_span(id.owner_id)));
} else {
- struct_span_err!(
- ctxt.tcx.sess,
- ctxt.tcx.def_span(id.def_id.to_def_id()),
- E0138,
- "multiple `start` functions"
- )
- .span_label(ctxt.start_fn.unwrap().1, "previous `#[start]` function here")
- .span_label(ctxt.tcx.def_span(id.def_id.to_def_id()), "multiple `start` functions")
- .emit();
+ ctxt.tcx.sess.emit_err(MultipleStartFunctions {
+ span: ctxt.tcx.def_span(id.owner_id),
+ labeled: ctxt.tcx.def_span(id.owner_id.to_def_id()),
+ previous: ctxt.start_fn.unwrap().1,
+ });
}
}
}
@@ -144,12 +142,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) -> Option<(DefId,
if let Some(main_def) = tcx.resolutions(()).main_def && let Some(def_id) = main_def.opt_fn_def_id() {
// non-local main imports are handled below
if let Some(def_id) = def_id.as_local() && matches!(tcx.hir().find_by_def_id(def_id), Some(Node::ForeignItem(_))) {
- tcx.sess
- .struct_span_err(
- tcx.def_span(def_id),
- "the `main` function cannot be declared in an `extern` block",
- )
- .emit();
+ tcx.sess.emit_err(ExternMain { span: tcx.def_span(def_id) });
return None;
}
@@ -182,12 +175,7 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
sigpipe::DEFAULT
}
_ => {
- tcx.sess
- .struct_span_err(
- attr.span,
- "valid values for `#[unix_sigpipe = \"...\"]` are `inherit`, `sig_ign`, or `sig_dfl`",
- )
- .emit();
+ tcx.sess.emit_err(UnixSigpipeValues { span: attr.span });
sigpipe::DEFAULT
}
}
@@ -206,52 +194,29 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) {
}
// There is no main function.
- let mut err = struct_span_err!(
- tcx.sess,
- DUMMY_SP,
- E0601,
- "`main` function not found in crate `{}`",
- tcx.crate_name(LOCAL_CRATE)
- );
- let filename = &tcx.sess.local_crate_source_file;
- let note = if !visitor.non_main_fns.is_empty() {
- for &span in &visitor.non_main_fns {
- err.span_note(span, "here is a function named `main`");
- }
- err.note("you have one or more functions named `main` not defined at the crate level");
- err.help("consider moving the `main` function definitions");
- // There were some functions named `main` though. Try to give the user a hint.
- format!(
- "the main function must be defined at the crate level{}",
- filename.as_ref().map(|f| format!(" (in `{}`)", f.display())).unwrap_or_default()
- )
- } else if let Some(filename) = filename {
- format!("consider adding a `main` function to `{}`", filename.display())
- } else {
- String::from("consider adding a `main` function at the crate level")
- };
+ let mut has_filename = true;
+ let filename = tcx.sess.local_crate_source_file.clone().unwrap_or_else(|| {
+ has_filename = false;
+ Default::default()
+ });
+ let main_def_opt = tcx.resolutions(()).main_def;
+ let diagnostic_id = error_code!(E0601);
+ let add_teach_note = tcx.sess.teach(&diagnostic_id);
// The file may be empty, which leads to the diagnostic machinery not emitting this
// note. This is a relatively simple way to detect that case and emit a span-less
// note instead.
- if tcx.sess.source_map().lookup_line(sp.hi()).is_ok() {
- err.set_span(sp.shrink_to_hi());
- err.span_label(sp.shrink_to_hi(), &note);
- } else {
- err.note(&note);
- }
-
- if let Some(main_def) = tcx.resolutions(()).main_def && main_def.opt_fn_def_id().is_none(){
- // There is something at `crate::main`, but it is not a function definition.
- err.span_label(main_def.span, "non-function item at `crate::main` is found");
- }
-
- if tcx.sess.teach(&err.get_code().unwrap()) {
- err.note(
- "If you don't know the basics of Rust, you can go look to the Rust Book \
- to get started: https://doc.rust-lang.org/book/",
- );
- }
- err.emit();
+ let file_empty = !tcx.sess.source_map().lookup_line(sp.hi()).is_ok();
+
+ tcx.sess.emit_err(NoMainErr {
+ sp,
+ crate_name: tcx.crate_name(LOCAL_CRATE),
+ has_filename,
+ filename,
+ file_empty,
+ non_main_fns: visitor.non_main_fns.clone(),
+ main_def_opt,
+ add_teach_note,
+ });
}
pub fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 96cc8ae98..adaaf5392 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -1,39 +1,49 @@
-use rustc_errors::{Applicability, MultiSpan};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
-use rustc_span::{Span, Symbol};
+use std::{
+ io::Error,
+ path::{Path, PathBuf},
+};
+
+use rustc_ast::Label;
+use rustc_errors::{error_code, Applicability, ErrorGuaranteed, IntoDiagnostic, MultiSpan};
+use rustc_hir::{self as hir, ExprKind, Target};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::ty::{MainDefinition, Ty};
+use rustc_span::{Span, Symbol, DUMMY_SP};
+
+use crate::lang_items::Duplicate;
#[derive(LintDiagnostic)]
-#[diag(passes::outer_crate_level_attr)]
+#[diag(passes_outer_crate_level_attr)]
pub struct OuterCrateLevelAttr;
#[derive(LintDiagnostic)]
-#[diag(passes::inner_crate_level_attr)]
+#[diag(passes_inner_crate_level_attr)]
pub struct InnerCrateLevelAttr;
#[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr_with_macro)]
+#[diag(passes_ignored_attr_with_macro)]
pub struct IgnoredAttrWithMacro<'a> {
pub sym: &'a str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::ignored_attr)]
+#[diag(passes_ignored_attr)]
pub struct IgnoredAttr<'a> {
pub sym: &'a str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_function_prototype)]
+#[diag(passes_inline_ignored_function_prototype)]
pub struct IgnoredInlineAttrFnProto;
#[derive(LintDiagnostic)]
-#[diag(passes::inline_ignored_constants)]
+#[diag(passes_inline_ignored_constants)]
#[warning]
#[note]
pub struct IgnoredInlineAttrConstants;
-#[derive(SessionDiagnostic)]
-#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
+#[derive(Diagnostic)]
+#[diag(passes_inline_not_fn_or_closure, code = "E0518")]
pub struct InlineNotFnOrClosure {
#[primary_span]
pub attr_span: Span,
@@ -42,19 +52,19 @@ pub struct InlineNotFnOrClosure {
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes_no_coverage_ignored_function_prototype)]
pub struct IgnoredNoCoverageFnProto;
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_propagate)]
+#[diag(passes_no_coverage_propagate)]
pub struct IgnoredNoCoveragePropagate;
#[derive(LintDiagnostic)]
-#[diag(passes::no_coverage_fn_defn)]
+#[diag(passes_no_coverage_fn_defn)]
pub struct IgnoredNoCoverageFnDefn;
-#[derive(SessionDiagnostic)]
-#[diag(passes::no_coverage_not_coverable, code = "E0788")]
+#[derive(Diagnostic)]
+#[diag(passes_no_coverage_not_coverable, code = "E0788")]
pub struct IgnoredNoCoverageNotCoverable {
#[primary_span]
pub attr_span: Span,
@@ -62,8 +72,8 @@ pub struct IgnoredNoCoverageNotCoverable {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_fn)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_fn)]
pub struct AttrShouldBeAppliedToFn {
#[primary_span]
pub attr_span: Span,
@@ -71,15 +81,15 @@ pub struct AttrShouldBeAppliedToFn {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::naked_tracked_caller, code = "E0736")]
+#[derive(Diagnostic)]
+#[diag(passes_naked_tracked_caller, code = "E0736")]
pub struct NakedTrackedCaller {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_fn, code = "E0739")]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_fn, code = "E0739")]
pub struct TrackedCallerWrongLocation {
#[primary_span]
pub attr_span: Span,
@@ -87,8 +97,8 @@ pub struct TrackedCallerWrongLocation {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_struct_enum, code = "E0701")]
pub struct NonExhaustiveWrongLocation {
#[primary_span]
pub attr_span: Span,
@@ -96,8 +106,8 @@ pub struct NonExhaustiveWrongLocation {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_trait)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_trait)]
pub struct AttrShouldBeAppliedToTrait {
#[primary_span]
pub attr_span: Span,
@@ -106,11 +116,11 @@ pub struct AttrShouldBeAppliedToTrait {
}
#[derive(LintDiagnostic)]
-#[diag(passes::target_feature_on_statement)]
+#[diag(passes_target_feature_on_statement)]
pub struct TargetFeatureOnStatement;
-#[derive(SessionDiagnostic)]
-#[diag(passes::should_be_applied_to_static)]
+#[derive(Diagnostic)]
+#[diag(passes_should_be_applied_to_static)]
pub struct AttrShouldBeAppliedToStatic {
#[primary_span]
pub attr_span: Span,
@@ -118,24 +128,24 @@ pub struct AttrShouldBeAppliedToStatic {
pub defn_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_expect_str)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_expect_str)]
pub struct DocExpectStr<'a> {
#[primary_span]
pub attr_span: Span,
pub attr_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_empty)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_empty)]
pub struct DocAliasEmpty<'a> {
#[primary_span]
pub span: Span,
pub attr_str: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_bad_char)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_bad_char)]
pub struct DocAliasBadChar<'a> {
#[primary_span]
pub span: Span,
@@ -143,16 +153,16 @@ pub struct DocAliasBadChar<'a> {
pub char_: char,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_start_end)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_start_end)]
pub struct DocAliasStartEnd<'a> {
#[primary_span]
pub span: Span,
pub attr_str: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_bad_location)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_bad_location)]
pub struct DocAliasBadLocation<'a> {
#[primary_span]
pub span: Span,
@@ -160,8 +170,8 @@ pub struct DocAliasBadLocation<'a> {
pub location: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_not_an_alias)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_not_an_alias)]
pub struct DocAliasNotAnAlias<'a> {
#[primary_span]
pub span: Span,
@@ -169,64 +179,64 @@ pub struct DocAliasNotAnAlias<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_alias_duplicated)]
+#[diag(passes_doc_alias_duplicated)]
pub struct DocAliasDuplicated {
#[label]
pub first_defn: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_not_string_literal)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_not_string_literal)]
pub struct DocAliasNotStringLiteral {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_alias_malformed)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_alias_malformed)]
pub struct DocAliasMalformed {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_empty_mod)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_empty_mod)]
pub struct DocKeywordEmptyMod {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_not_mod)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_not_mod)]
pub struct DocKeywordNotMod {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_invalid_ident)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_invalid_ident)]
pub struct DocKeywordInvalidIdent {
#[primary_span]
pub span: Span,
pub doc_keyword: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_fake_variadic_not_valid)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_fake_variadic_not_valid)]
pub struct DocFakeVariadicNotValid {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_keyword_only_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_keyword_only_impl)]
pub struct DocKeywordOnlyImpl {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_inline_conflict)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_inline_conflict)]
#[help]
pub struct DocKeywordConflict {
#[primary_span]
@@ -234,17 +244,17 @@ pub struct DocKeywordConflict {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_inline_only_use)]
+#[diag(passes_doc_inline_only_use)]
#[note]
pub struct DocInlineOnlyUse {
#[label]
pub attr_span: Span,
- #[label(passes::not_a_use_item_label)]
+ #[label(not_a_use_item_label)]
pub item_span: Option<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::doc_attr_not_crate_level)]
+#[derive(Diagnostic)]
+#[diag(passes_doc_attr_not_crate_level)]
pub struct DocAttrNotCrateLevel<'a> {
#[primary_span]
pub span: Span,
@@ -252,29 +262,33 @@ pub struct DocAttrNotCrateLevel<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown)]
+#[diag(passes_doc_test_unknown)]
pub struct DocTestUnknown {
pub path: String,
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_takes_list)]
+#[diag(passes_doc_test_takes_list)]
pub struct DocTestTakesList;
#[derive(LintDiagnostic)]
-#[diag(passes::doc_primitive)]
+#[diag(passes_doc_cfg_hide_takes_list)]
+pub struct DocCfgHideTakesList;
+
+#[derive(LintDiagnostic)]
+#[diag(passes_doc_primitive)]
pub struct DocPrimitive;
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_any)]
+#[diag(passes_doc_test_unknown_any)]
pub struct DocTestUnknownAny {
pub path: String,
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_spotlight)]
+#[diag(passes_doc_test_unknown_spotlight)]
#[note]
-#[note(passes::no_op_note)]
+#[note(no_op_note)]
pub struct DocTestUnknownSpotlight {
pub path: String,
#[suggestion_short(applicability = "machine-applicable", code = "notable_trait")]
@@ -282,7 +296,7 @@ pub struct DocTestUnknownSpotlight {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_test_unknown_include)]
+#[diag(passes_doc_test_unknown_include)]
pub struct DocTestUnknownInclude {
pub path: String,
pub value: String,
@@ -292,11 +306,11 @@ pub struct DocTestUnknownInclude {
}
#[derive(LintDiagnostic)]
-#[diag(passes::doc_invalid)]
+#[diag(passes_doc_invalid)]
pub struct DocInvalid;
-#[derive(SessionDiagnostic)]
-#[diag(passes::pass_by_value)]
+#[derive(Diagnostic)]
+#[diag(passes_pass_by_value)]
pub struct PassByValue {
#[primary_span]
pub attr_span: Span,
@@ -304,8 +318,8 @@ pub struct PassByValue {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::allow_incoherent_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_allow_incoherent_impl)]
pub struct AllowIncoherentImpl {
#[primary_span]
pub attr_span: Span,
@@ -313,8 +327,8 @@ pub struct AllowIncoherentImpl {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::has_incoherent_inherent_impl)]
+#[derive(Diagnostic)]
+#[diag(passes_has_incoherent_inherent_impl)]
pub struct HasIncoherentInherentImpl {
#[primary_span]
pub attr_span: Span,
@@ -323,21 +337,21 @@ pub struct HasIncoherentInherentImpl {
}
#[derive(LintDiagnostic)]
-#[diag(passes::must_use_async)]
+#[diag(passes_must_use_async)]
pub struct MustUseAsync {
#[label]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::must_use_no_effect)]
+#[diag(passes_must_use_no_effect)]
pub struct MustUseNoEffect {
pub article: &'static str,
pub target: rustc_hir::Target,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::must_not_suspend)]
+#[derive(Diagnostic)]
+#[diag(passes_must_not_suspend)]
pub struct MustNotSuspend {
#[primary_span]
pub attr_span: Span,
@@ -346,7 +360,7 @@ pub struct MustNotSuspend {
}
#[derive(LintDiagnostic)]
-#[diag(passes::cold)]
+#[diag(passes_cold)]
#[warning]
pub struct Cold {
#[label]
@@ -354,7 +368,7 @@ pub struct Cold {
}
#[derive(LintDiagnostic)]
-#[diag(passes::link)]
+#[diag(passes_link)]
#[warning]
pub struct Link {
#[label]
@@ -362,7 +376,7 @@ pub struct Link {
}
#[derive(LintDiagnostic)]
-#[diag(passes::link_name)]
+#[diag(passes_link_name)]
#[warning]
pub struct LinkName<'a> {
#[help]
@@ -372,8 +386,8 @@ pub struct LinkName<'a> {
pub value: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::no_link)]
+#[derive(Diagnostic)]
+#[diag(passes_no_link)]
pub struct NoLink {
#[primary_span]
pub attr_span: Span,
@@ -381,8 +395,8 @@ pub struct NoLink {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::export_name)]
+#[derive(Diagnostic)]
+#[diag(passes_export_name)]
pub struct ExportName {
#[primary_span]
pub attr_span: Span,
@@ -390,8 +404,8 @@ pub struct ExportName {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_layout_scalar_valid_range_not_struct)]
pub struct RustcLayoutScalarValidRangeNotStruct {
#[primary_span]
pub attr_span: Span,
@@ -399,15 +413,15 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_layout_scalar_valid_range_arg)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_layout_scalar_valid_range_arg)]
pub struct RustcLayoutScalarValidRangeArg {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_only)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_only)]
pub struct RustcLegacyConstGenericsOnly {
#[primary_span]
pub attr_span: Span,
@@ -415,8 +429,8 @@ pub struct RustcLegacyConstGenericsOnly {
pub param_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index)]
pub struct RustcLegacyConstGenericsIndex {
#[primary_span]
pub attr_span: Span,
@@ -424,8 +438,8 @@ pub struct RustcLegacyConstGenericsIndex {
pub generics_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_exceed)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index_exceed)]
pub struct RustcLegacyConstGenericsIndexExceed {
#[primary_span]
#[label]
@@ -433,22 +447,22 @@ pub struct RustcLegacyConstGenericsIndexExceed {
pub arg_count: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_legacy_const_generics_index_negative)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_legacy_const_generics_index_negative)]
pub struct RustcLegacyConstGenericsIndexNegative {
#[primary_span]
pub invalid_args: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_dirty_clean)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_dirty_clean)]
pub struct RustcDirtyClean {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::link_section)]
+#[diag(passes_link_section)]
#[warning]
pub struct LinkSection {
#[label]
@@ -456,52 +470,52 @@ pub struct LinkSection {
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_mangle_foreign)]
+#[diag(passes_no_mangle_foreign)]
#[warning]
#[note]
pub struct NoMangleForeign {
#[label]
pub span: Span,
- #[suggestion(applicability = "machine-applicable")]
+ #[suggestion(code = "", applicability = "machine-applicable")]
pub attr_span: Span,
pub foreign_item_kind: &'static str,
}
#[derive(LintDiagnostic)]
-#[diag(passes::no_mangle)]
+#[diag(passes_no_mangle)]
#[warning]
pub struct NoMangle {
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::repr_ident, code = "E0565")]
+#[derive(Diagnostic)]
+#[diag(passes_repr_ident, code = "E0565")]
pub struct ReprIdent {
#[primary_span]
pub span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::repr_conflicting, code = "E0566")]
+#[diag(passes_repr_conflicting, code = "E0566")]
pub struct ReprConflicting;
-#[derive(SessionDiagnostic)]
-#[diag(passes::used_static)]
+#[derive(Diagnostic)]
+#[diag(passes_used_static)]
pub struct UsedStatic {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::used_compiler_linker)]
+#[derive(Diagnostic)]
+#[diag(passes_used_compiler_linker)]
pub struct UsedCompilerLinker {
#[primary_span]
pub spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::allow_internal_unstable)]
+#[derive(Diagnostic)]
+#[diag(passes_allow_internal_unstable)]
pub struct AllowInternalUnstable {
#[primary_span]
pub attr_span: Span,
@@ -509,25 +523,34 @@ pub struct AllowInternalUnstable {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::debug_visualizer_placement)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_placement)]
pub struct DebugVisualizerPlacement {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::debug_visualizer_invalid)]
-#[note(passes::note_1)]
-#[note(passes::note_2)]
-#[note(passes::note_3)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_invalid)]
+#[note(note_1)]
+#[note(note_2)]
+#[note(note_3)]
pub struct DebugVisualizerInvalid {
#[primary_span]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_allow_const_fn_unstable)]
+#[derive(Diagnostic)]
+#[diag(passes_debug_visualizer_unreadable)]
+pub struct DebugVisualizerUnreadable<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub file: &'a Path,
+ pub error: Error,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_rustc_allow_const_fn_unstable)]
pub struct RustcAllowConstFnUnstable {
#[primary_span]
pub attr_span: Span,
@@ -535,8 +558,8 @@ pub struct RustcAllowConstFnUnstable {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_std_internal_symbol)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_std_internal_symbol)]
pub struct RustcStdInternalSymbol {
#[primary_span]
pub attr_span: Span,
@@ -544,66 +567,66 @@ pub struct RustcStdInternalSymbol {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::const_trait)]
+#[derive(Diagnostic)]
+#[diag(passes_const_trait)]
pub struct ConstTrait {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::link_ordinal)]
+#[derive(Diagnostic)]
+#[diag(passes_link_ordinal)]
pub struct LinkOrdinal {
#[primary_span]
pub attr_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::stability_promotable)]
+#[derive(Diagnostic)]
+#[diag(passes_stability_promotable)]
pub struct StabilityPromotable {
#[primary_span]
pub attr_span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(passes::deprecated)]
+#[diag(passes_deprecated)]
pub struct Deprecated;
#[derive(LintDiagnostic)]
-#[diag(passes::macro_use)]
+#[diag(passes_macro_use)]
pub struct MacroUse {
pub name: Symbol,
}
#[derive(LintDiagnostic)]
-#[diag(passes::macro_export)]
+#[diag(passes_macro_export)]
pub struct MacroExport;
#[derive(LintDiagnostic)]
-#[diag(passes::plugin_registrar)]
+#[diag(passes_plugin_registrar)]
pub struct PluginRegistrar;
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum UnusedNote {
- #[note(passes::unused_empty_lints_note)]
+ #[note(passes_unused_empty_lints_note)]
EmptyList { name: Symbol },
- #[note(passes::unused_no_lints_note)]
+ #[note(passes_unused_no_lints_note)]
NoLints { name: Symbol },
- #[note(passes::unused_default_method_body_const_note)]
+ #[note(passes_unused_default_method_body_const_note)]
DefaultMethodBodyConst,
}
#[derive(LintDiagnostic)]
-#[diag(passes::unused)]
+#[diag(passes_unused)]
pub struct Unused {
- #[suggestion(applicability = "machine-applicable")]
+ #[suggestion(code = "", applicability = "machine-applicable")]
pub attr_span: Span,
#[subdiagnostic]
pub note: UnusedNote,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[derive(Diagnostic)]
+#[diag(passes_non_exported_macro_invalid_attrs, code = "E0518")]
pub struct NonExportedMacroInvalidAttrs {
#[primary_span]
#[label]
@@ -611,7 +634,7 @@ pub struct NonExportedMacroInvalidAttrs {
}
#[derive(LintDiagnostic)]
-#[diag(passes::unused_duplicate)]
+#[diag(passes_unused_duplicate)]
pub struct UnusedDuplicate {
#[suggestion(code = "", applicability = "machine-applicable")]
pub this: Span,
@@ -621,8 +644,8 @@ pub struct UnusedDuplicate {
pub warning: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::unused_multiple)]
+#[derive(Diagnostic)]
+#[diag(passes_unused_multiple)]
pub struct UnusedMultiple {
#[primary_span]
#[suggestion(code = "", applicability = "machine-applicable")]
@@ -632,8 +655,8 @@ pub struct UnusedMultiple {
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_lint_opt_ty)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_lint_opt_ty)]
pub struct RustcLintOptTy {
#[primary_span]
pub attr_span: Span,
@@ -641,8 +664,8 @@ pub struct RustcLintOptTy {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::rustc_lint_opt_deny_field_access)]
+#[derive(Diagnostic)]
+#[diag(passes_rustc_lint_opt_deny_field_access)]
pub struct RustcLintOptDenyFieldAccess {
#[primary_span]
pub attr_span: Span,
@@ -650,11 +673,779 @@ pub struct RustcLintOptDenyFieldAccess {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(passes::collapse_debuginfo)]
+#[derive(Diagnostic)]
+#[diag(passes_collapse_debuginfo)]
pub struct CollapseDebuginfo {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_deprecated_annotation_has_no_effect)]
+pub struct DeprecatedAnnotationHasNoEffect {
+ #[suggestion(applicability = "machine-applicable", code = "")]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_external_lang_item, code = "E0264")]
+pub struct UnknownExternLangItem {
+ #[primary_span]
+ pub span: Span,
+ pub lang_item: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_panic_handler)]
+pub struct MissingPanicHandler;
+
+#[derive(Diagnostic)]
+#[diag(passes_alloc_func_required)]
+pub struct AllocFuncRequired;
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_alloc_error_handler)]
+pub struct MissingAllocErrorHandler;
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_lang_item)]
+#[note]
+#[help]
+pub struct MissingLangItem {
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_lang_item_on_incorrect_target, code = "E0718")]
+pub struct LangItemOnIncorrectTarget {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: Symbol,
+ pub expected_target: Target,
+ pub actual_target: Target,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_lang_item, code = "E0522")]
+pub struct UnknownLangItem {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+pub struct InvalidAttrAtCrateLevel {
+ pub span: Span,
+ pub snippet: Option<String>,
+ pub name: Symbol,
+}
+
+impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel {
+ fn into_diagnostic(
+ self,
+ handler: &'_ rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_err(rustc_errors::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
+ // of the attribute span
+ if let Some(src) = self.snippet {
+ let replacement = src.replace("#!", "#");
+ diag.span_suggestion_verbose(
+ self.span,
+ rustc_errors::fluent::suggestion,
+ replacement,
+ rustc_errors::Applicability::MachineApplicable,
+ );
+ }
+ diag
+ }
+}
+
+#[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 {
+ #[note(passes_diagnostic_item_first_defined)]
+ pub span: Option<Span>,
+ pub orig_crate_name: Symbol,
+ #[note]
+ pub have_orig_crate_name: Option<()>,
+ pub crate_name: Symbol,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_abi)]
+pub struct Abi {
+ #[primary_span]
+ pub span: Span,
+ pub abi: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_align)]
+pub struct Align {
+ #[primary_span]
+ pub span: Span,
+ pub align: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_size)]
+pub struct Size {
+ #[primary_span]
+ pub span: Span,
+ pub size: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_homogeneous_aggregate)]
+pub struct HomogeneousAggregate {
+ #[primary_span]
+ pub span: Span,
+ pub homogeneous_aggregate: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_layout_of)]
+pub struct LayoutOf {
+ #[primary_span]
+ pub span: Span,
+ pub normalized_ty: String,
+ pub ty_layout: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unrecognized_field)]
+pub struct UnrecognizedField {
+ #[primary_span]
+ pub span: Span,
+ pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_stable_twice, code = "E0711")]
+pub struct FeatureStableTwice {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub since: Symbol,
+ pub prev_since: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_previously_declared, code = "E0711")]
+pub struct FeaturePreviouslyDeclared<'a, 'b> {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub declared: &'a str,
+ pub prev_declared: &'b str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_expr_not_allowed_in_context, code = "E0744")]
+pub struct ExprNotAllowedInContext<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub expr: String,
+ pub context: &'a str,
+}
+
+pub struct BreakNonLoop<'a> {
+ pub span: Span,
+ pub head: Option<Span>,
+ pub kind: &'a str,
+ pub suggestion: String,
+ pub loop_label: Option<Label>,
+ pub break_label: Option<Label>,
+ pub break_expr_kind: &'a ExprKind<'a>,
+ pub break_expr_span: Span,
+}
+
+impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ self.span,
+ rustc_errors::fluent::passes_break_non_loop,
+ error_code!(E0571),
+ );
+ diag.set_arg("kind", self.kind);
+ diag.span_label(self.span, rustc_errors::fluent::label);
+ if let Some(head) = self.head {
+ diag.span_label(head, rustc_errors::fluent::label2);
+ }
+ diag.span_suggestion(
+ self.span,
+ rustc_errors::fluent::suggestion,
+ self.suggestion,
+ Applicability::MaybeIncorrect,
+ );
+ if let (Some(label), None) = (self.loop_label, self.break_label) {
+ match self.break_expr_kind {
+ ExprKind::Path(hir::QPath::Resolved(
+ None,
+ hir::Path { segments: [segment], res: hir::def::Res::Err, .. },
+ )) if label.ident.to_string() == format!("'{}", segment.ident) => {
+ // This error is redundant, we will have already emitted a
+ // suggestion to use the label when `segment` wasn't found
+ // (hence the `Res::Err` check).
+ diag.delay_as_bug();
+ }
+ _ => {
+ diag.span_suggestion(
+ self.break_expr_span,
+ rustc_errors::fluent::break_expr_suggestion,
+ label.ident,
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_continue_labeled_block, code = "E0696")]
+pub struct ContinueLabeledBlock {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(block_label)]
+ pub block_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_break_inside_closure, code = "E0267")]
+pub struct BreakInsideClosure<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(closure_label)]
+ pub closure_span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_break_inside_async_block, code = "E0267")]
+pub struct BreakInsideAsyncBlock<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(async_block_label)]
+ pub closure_span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_outside_loop, code = "E0268")]
+pub struct OutsideLoop<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unlabeled_in_labeled_block, code = "E0695")]
+pub struct UnlabeledInLabeledBlock<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub cf_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unlabeled_cf_in_while_condition, code = "E0590")]
+pub struct UnlabeledCfInWhileCondition<'a> {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ pub cf_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_cannot_inline_naked_function)]
+pub struct CannotInlineNakedFunction {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_undefined_naked_function_abi)]
+pub struct UndefinedNakedFunctionAbi;
+
+#[derive(Diagnostic)]
+#[diag(passes_no_patterns)]
+pub struct NoPatterns {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_params_not_allowed)]
+#[help]
+pub struct ParamsNotAllowed {
+ #[primary_span]
+ pub span: Span,
+}
+
+pub struct NakedFunctionsAsmBlock {
+ pub span: Span,
+ pub multiple_asms: Vec<Span>,
+ pub non_asms: Vec<Span>,
+}
+
+impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ self.span,
+ rustc_errors::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);
+ }
+ for span in self.non_asms.iter() {
+ diag.span_label(*span, rustc_errors::fluent::label_non_asm);
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_operands, code = "E0787")]
+pub struct NakedFunctionsOperands {
+ #[primary_span]
+ pub unsupported_operands: Vec<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_asm_options, code = "E0787")]
+pub struct NakedFunctionsAsmOptions {
+ #[primary_span]
+ pub span: Span,
+ pub unsupported_options: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_naked_functions_must_use_noreturn, code = "E0787")]
+pub struct NakedFunctionsMustUseNoreturn {
+ #[primary_span]
+ pub span: Span,
+ #[suggestion(code = ", options(noreturn)", applicability = "machine-applicable")]
+ pub last_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_on_main)]
+pub struct AttrOnlyOnMain {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_on_root_main)]
+pub struct AttrOnlyOnRootMain {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_attr_only_in_functions)]
+pub struct AttrOnlyInFunctions {
+ #[primary_span]
+ pub span: Span,
+ pub attr: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_multiple_rustc_main, code = "E0137")]
+pub struct MultipleRustcMain {
+ #[primary_span]
+ pub span: Span,
+ #[label(first)]
+ pub first: Span,
+ #[label(additional)]
+ pub additional: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_multiple_start_functions, code = "E0138")]
+pub struct MultipleStartFunctions {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub labeled: Span,
+ #[label(previous)]
+ pub previous: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_extern_main)]
+pub struct ExternMain {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unix_sigpipe_values)]
+pub struct UnixSigpipeValues {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_no_main_function, code = "E0601")]
+pub struct NoMainFunction {
+ #[primary_span]
+ pub span: Span,
+ pub crate_name: String,
+}
+
+pub struct NoMainErr {
+ pub sp: Span,
+ pub crate_name: Symbol,
+ pub has_filename: bool,
+ pub filename: PathBuf,
+ pub file_empty: bool,
+ pub non_main_fns: Vec<Span>,
+ pub main_def_opt: Option<MainDefinition>,
+ pub add_teach_note: bool,
+}
+
+impl<'a> IntoDiagnostic<'a> for NoMainErr {
+ fn into_diagnostic(
+ self,
+ handler: &'a rustc_errors::Handler,
+ ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> {
+ let mut diag = handler.struct_span_err_with_code(
+ DUMMY_SP,
+ rustc_errors::fluent::passes_no_main_function,
+ error_code!(E0601),
+ );
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("filename", self.filename);
+ 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.note(rustc_errors::fluent::one_or_more_possible_main);
+ diag.help(rustc_errors::fluent::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
+ } else if self.has_filename {
+ rustc_errors::fluent::consider_adding_main_to_file
+ } else {
+ rustc_errors::fluent::consider_adding_main_at_crate
+ };
+ if self.file_empty {
+ diag.note(note);
+ } else {
+ diag.set_span(self.sp.shrink_to_hi());
+ diag.span_label(self.sp.shrink_to_hi(), note);
+ }
+
+ 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);
+ }
+
+ if self.add_teach_note {
+ diag.note(rustc_errors::fluent::teach_note);
+ }
+ diag
+ }
+}
+
+pub struct DuplicateLangItem {
+ pub local_span: Option<Span>,
+ pub lang_item_name: Symbol,
+ pub crate_name: Symbol,
+ pub dependency_of: Symbol,
+ pub is_local: bool,
+ pub path: String,
+ pub first_defined_span: Option<Span>,
+ pub orig_crate_name: Symbol,
+ pub orig_dependency_of: Symbol,
+ pub orig_is_local: bool,
+ pub orig_path: String,
+ pub(crate) duplicate: Duplicate,
+}
+
+impl IntoDiagnostic<'_> for DuplicateLangItem {
+ fn into_diagnostic(
+ self,
+ handler: &rustc_errors::Handler,
+ ) -> 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
+ }
+ },
+ error_code!(E0152),
+ );
+ diag.set_arg("lang_item_name", self.lang_item_name);
+ diag.set_arg("crate_name", self.crate_name);
+ diag.set_arg("dependency_of", self.dependency_of);
+ diag.set_arg("path", self.path);
+ diag.set_arg("orig_crate_name", self.orig_crate_name);
+ diag.set_arg("orig_dependency_of", self.orig_dependency_of);
+ diag.set_arg("orig_path", self.orig_path);
+ if let Some(span) = self.local_span {
+ diag.set_span(span);
+ }
+ if let Some(span) = self.first_defined_span {
+ diag.span_note(span, rustc_errors::fluent::first_defined_span);
+ } else {
+ if self.orig_dependency_of.is_empty() {
+ diag.note(rustc_errors::fluent::first_defined_crate);
+ } else {
+ diag.note(rustc_errors::fluent::first_defined_crate_depends);
+ }
+
+ if self.orig_is_local {
+ diag.note(rustc_errors::fluent::first_definition_local);
+ } else {
+ diag.note(rustc_errors::fluent::first_definition_path);
+ }
+
+ if self.is_local {
+ diag.note(rustc_errors::fluent::second_definition_local);
+ } else {
+ diag.note(rustc_errors::fluent::second_definition_path);
+ }
+ }
+ diag
+ }
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_incorrect_target, code = "E0718")]
+pub struct IncorrectTarget<'a> {
+ #[primary_span]
+ pub span: Span,
+ #[label]
+ pub generics_span: Span,
+ pub name: &'a str, // cannot be symbol because it renders e.g. `r#fn` instead of `fn`
+ pub kind: &'static str,
+ pub num: usize,
+ pub actual_num: usize,
+ pub at_least: bool,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_useless_assignment)]
+pub struct UselessAssignment<'a> {
+ pub is_field_assign: bool,
+ pub ty: Ty<'a>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(passes_only_has_effect_on)]
+pub struct OnlyHasEffectOn {
+ pub attr_name: Symbol,
+ pub target_name: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_object_lifetime_err)]
+pub struct ObjectLifetimeErr {
+ #[primary_span]
+ pub span: Span,
+ pub repr: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unrecognized_repr_hint, code = "E0552")]
+#[help]
+pub struct UnrecognizedReprHint {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub enum AttrApplication {
+ #[diag(passes_attr_application_enum, code = "E0517")]
+ Enum {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct, code = "E0517")]
+ Struct {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_union, code = "E0517")]
+ StructUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_enum_union, code = "E0517")]
+ StructEnumUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+ #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")]
+ StructEnumFunctionUnion {
+ #[primary_span]
+ hint_span: Span,
+ #[label]
+ span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_transparent_incompatible, code = "E0692")]
+pub struct TransparentIncompatible {
+ #[primary_span]
+ pub hint_spans: Vec<Span>,
+ pub target: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_deprecated_attribute, code = "E0549")]
+pub struct DeprecatedAttribute {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_useless_stability)]
+pub struct UselessStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_invalid_stability)]
+pub struct InvalidStability {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_cannot_stabilize_deprecated)]
+pub struct CannotStabilizeDeprecated {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_invalid_deprecation_version)]
+pub struct InvalidDeprecationVersion {
+ #[primary_span]
+ #[label]
+ pub span: Span,
+ #[label(item)]
+ pub item_sp: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_stability_attr)]
+pub struct MissingStabilityAttr<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_missing_const_stab_attr)]
+pub struct MissingConstStabAttr<'a> {
+ #[primary_span]
+ pub span: Span,
+ pub descr: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_trait_impl_const_stable)]
+#[note]
+pub struct TraitImplConstStable {
+ #[primary_span]
+ pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_feature_only_on_nightly, code = "E0554")]
+pub struct FeatureOnlyOnNightly {
+ #[primary_span]
+ pub span: Span,
+ pub release_channel: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_unknown_feature, code = "E0635")]
+pub struct UnknownFeature {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_implied_feature_not_exist)]
+pub struct ImpliedFeatureNotExist {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+ pub implied_by: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(passes_duplicate_feature_err, code = "E0636")]
+pub struct DuplicateFeatureErr {
+ #[primary_span]
+ pub span: Span,
+ pub feature: Symbol,
+}
+#[derive(Diagnostic)]
+#[diag(passes_missing_const_err)]
+pub struct MissingConstErr {
+ #[primary_span]
+ #[help]
+ pub fn_sig_span: Span,
+ #[label]
+ pub const_span: Span,
+}
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index 3bb8c0bb4..88bb39deb 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -1,6 +1,5 @@
use rustc_data_structures::sync::Lock;
use rustc_hir as hir;
-use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
use rustc_hir::intravisit;
use rustc_hir::{HirId, ItemLocalId};
use rustc_index::bit_set::GrowableBitSet;
@@ -42,7 +41,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
struct HirIdValidator<'a, 'hir> {
hir_map: Map<'hir>,
- owner: Option<LocalDefId>,
+ owner: Option<hir::OwnerId>,
hir_ids_seen: GrowableBitSet<ItemLocalId>,
errors: &'a Lock<Vec<String>>,
}
@@ -63,12 +62,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
self.errors.lock().push(f());
}
- fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: LocalDefId, walk: F) {
+ fn check<F: FnOnce(&mut HirIdValidator<'a, 'hir>)>(&mut self, owner: hir::OwnerId, walk: F) {
assert!(self.owner.is_none());
self.owner = Some(owner);
walk(self);
- if owner == CRATE_DEF_ID {
+ if owner == hir::CRATE_OWNER_ID {
return;
}
@@ -97,14 +96,14 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
missing_items.push(format!(
"[local_id: {}, owner: {}]",
local_id,
- self.hir_map.def_path(owner).to_string_no_crate_verbose()
+ self.hir_map.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.hir_map.def_path(owner).to_string_no_crate_verbose(),
+ self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose(),
max,
missing_items,
self.hir_ids_seen
@@ -127,7 +126,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
fn visit_item(&mut self, i: &'hir hir::Item<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_item(this, i));
}
fn visit_id(&mut self, hir_id: HirId) {
@@ -138,8 +137,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
format!(
"HirIdValidator: The recorded owner of {} is {} instead of {}",
self.hir_map.node_to_string(hir_id),
- self.hir_map.def_path(hir_id.owner).to_string_no_crate_verbose(),
- self.hir_map.def_path(owner).to_string_no_crate_verbose()
+ self.hir_map.def_path(hir_id.owner.def_id).to_string_no_crate_verbose(),
+ self.hir_map.def_path(owner.def_id).to_string_no_crate_verbose()
)
});
}
@@ -149,16 +148,16 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
fn visit_foreign_item(&mut self, i: &'hir hir::ForeignItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_foreign_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_foreign_item(this, i));
}
fn visit_trait_item(&mut self, i: &'hir hir::TraitItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_trait_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_trait_item(this, i));
}
fn visit_impl_item(&mut self, i: &'hir hir::ImplItem<'hir>) {
let mut inner_visitor = self.new_visitor(self.hir_map);
- inner_visitor.check(i.def_id, |this| intravisit::walk_impl_item(this, i));
+ inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
}
}
diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs
index 0be2fc053..33220fd2b 100644
--- a/compiler/rustc_passes/src/hir_stats.rs
+++ b/compiler/rustc_passes/src/hir_stats.rs
@@ -391,7 +391,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) {
record_variants!(
(self, ii, ii.kind, Id::Node(ii.hir_id()), hir, ImplItem, ImplItemKind),
- [Const, Fn, TyAlias]
+ [Const, Fn, Type]
);
hir_visit::walk_impl_item(self, ii)
}
@@ -620,7 +620,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> {
fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
record_variants!(
(self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind),
- [Const, Fn, TyAlias, MacCall]
+ [Const, Fn, Type, MacCall]
);
ast_visit::walk_assoc_item(self, i, ctxt);
}
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index 79900a90a..df811be2a 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -8,9 +8,11 @@
//! * Functions called by the compiler itself.
use crate::check_attr::target_from_impl_item;
+use crate::errors::{
+ DuplicateLangItem, IncorrectTarget, LangItemOnIncorrectTarget, UnknownLangItem,
+};
use crate::weak_lang_items;
-use rustc_errors::{pluralize, struct_span_err};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
@@ -18,10 +20,16 @@ use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
use rustc_hir::{HirId, LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate;
-use rustc_span::Span;
+use rustc_span::{symbol::kw::Empty, Span};
use rustc_middle::ty::query::Providers;
+pub(crate) enum Duplicate {
+ Plain,
+ Crate,
+ CrateDepends,
+}
+
struct LanguageItemCollector<'tcx> {
items: LanguageItems,
tcx: TyCtxt<'tcx>,
@@ -34,42 +42,24 @@ impl<'tcx> LanguageItemCollector<'tcx> {
fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
let attrs = self.tcx.hir().attrs(hir_id);
- if let Some((value, span)) = extract(&attrs) {
- match ITEM_REFS.get(&value).cloned() {
+ if let Some((name, span)) = extract(&attrs) {
+ match ITEM_REFS.get(&name).cloned() {
// Known lang item with attribute on correct target.
Some((item_index, expected_target)) if actual_target == expected_target => {
self.collect_item_extended(item_index, hir_id, span);
}
// Known lang item with attribute on incorrect target.
Some((_, expected_target)) => {
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
span,
- E0718,
- "`{}` language item must be applied to a {}",
- value,
+ name,
expected_target,
- )
- .span_label(
- span,
- format!(
- "attribute should be applied to a {}, not a {}",
- expected_target, actual_target,
- ),
- )
- .emit();
+ actual_target,
+ });
}
// Unknown lang item.
_ => {
- struct_span_err!(
- self.tcx.sess,
- span,
- E0522,
- "definition of an unknown language item: `{}`",
- value
- )
- .span_label(span, format!("definition of unknown language item `{}`", value))
- .emit();
+ self.tcx.sess.emit_err(UnknownLangItem { span, name });
}
}
}
@@ -79,74 +69,72 @@ impl<'tcx> LanguageItemCollector<'tcx> {
// Check for duplicates.
if let Some(original_def_id) = self.items.items[item_index] {
if original_def_id != item_def_id {
- let lang_item = LangItem::from_u32(item_index as u32).unwrap();
- let name = lang_item.name();
- let mut err = match self.tcx.hir().span_if_local(item_def_id) {
- Some(span) => struct_span_err!(
- self.tcx.sess,
- span,
- E0152,
- "found duplicate lang item `{}`",
- name
- ),
- None => match self.tcx.extern_crate(item_def_id) {
- Some(ExternCrate { dependency_of, .. }) => {
- self.tcx.sess.struct_err(&format!(
- "duplicate lang item in crate `{}` (which `{}` depends on): `{}`.",
- self.tcx.crate_name(item_def_id.krate),
- self.tcx.crate_name(*dependency_of),
- name
- ))
- }
- _ => self.tcx.sess.struct_err(&format!(
- "duplicate lang item in crate `{}`: `{}`.",
- self.tcx.crate_name(item_def_id.krate),
- name
- )),
- },
+ let local_span = self.tcx.hir().span_if_local(item_def_id);
+ let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name();
+ let crate_name = self.tcx.crate_name(item_def_id.krate);
+ let mut dependency_of = Empty;
+ let is_local = item_def_id.is_local();
+ let path = if is_local {
+ String::new()
+ } else {
+ self.tcx
+ .crate_extern_paths(item_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ .into()
};
- if let Some(span) = self.tcx.hir().span_if_local(original_def_id) {
- err.span_note(span, "the lang item is first defined here");
+ let first_defined_span = self.tcx.hir().span_if_local(original_def_id);
+ let mut orig_crate_name = Empty;
+ let mut orig_dependency_of = Empty;
+ let orig_is_local = original_def_id.is_local();
+ let orig_path = if orig_is_local {
+ String::new()
} else {
- match self.tcx.extern_crate(original_def_id) {
- Some(ExternCrate { dependency_of, .. }) => {
- err.note(&format!(
- "the lang item is first defined in crate `{}` (which `{}` depends on)",
- self.tcx.crate_name(original_def_id.krate),
- self.tcx.crate_name(*dependency_of)
- ));
- }
- _ => {
- err.note(&format!(
- "the lang item is first defined in crate `{}`.",
- self.tcx.crate_name(original_def_id.krate)
- ));
- }
+ self.tcx
+ .crate_extern_paths(original_def_id.krate)
+ .iter()
+ .map(|p| p.display().to_string())
+ .collect::<Vec<_>>()
+ .join(", ")
+ .into()
+ };
+ if first_defined_span.is_none() {
+ orig_crate_name = self.tcx.crate_name(original_def_id.krate);
+ if let Some(ExternCrate { dependency_of: inner_dependency_of, .. }) =
+ self.tcx.extern_crate(original_def_id)
+ {
+ orig_dependency_of = self.tcx.crate_name(*inner_dependency_of);
}
- let mut note_def = |which, def_id: DefId| {
- let crate_name = self.tcx.crate_name(def_id.krate);
- let note = if def_id.is_local() {
- format!("{} definition in the local crate (`{}`)", which, crate_name)
- } else {
- let paths: Vec<_> = self
- .tcx
- .crate_extern_paths(def_id.krate)
- .iter()
- .map(|p| p.display().to_string())
- .collect();
- format!(
- "{} definition in `{}` loaded from {}",
- which,
- crate_name,
- paths.join(", ")
- )
- };
- err.note(&note);
- };
- note_def("first", original_def_id);
- note_def("second", item_def_id);
}
- err.emit();
+
+ let duplicate = if local_span.is_some() {
+ Duplicate::Plain
+ } else {
+ match self.tcx.extern_crate(item_def_id) {
+ Some(ExternCrate { dependency_of: inner_dependency_of, .. }) => {
+ dependency_of = self.tcx.crate_name(*inner_dependency_of);
+ Duplicate::CrateDepends
+ }
+ _ => Duplicate::Crate,
+ }
+ };
+
+ self.tcx.sess.emit_err(DuplicateLangItem {
+ local_span,
+ lang_item_name,
+ crate_name,
+ dependency_of,
+ is_local,
+ path,
+ first_defined_span,
+ orig_crate_name,
+ orig_dependency_of,
+ orig_is_local,
+ orig_path,
+ duplicate,
+ });
}
}
@@ -179,41 +167,30 @@ impl<'tcx> LanguageItemCollector<'tcx> {
None => (0, *item_span),
};
+ let mut at_least = false;
let required = match lang_item.required_generics() {
- GenericRequirement::Exact(num) if num != actual_num => {
- Some((format!("{}", num), pluralize!(num)))
- }
+ GenericRequirement::Exact(num) if num != actual_num => Some(num),
GenericRequirement::Minimum(num) if actual_num < num => {
- Some((format!("at least {}", num), pluralize!(num)))
- }
+ at_least = true;
+ Some(num)}
+ ,
// If the number matches, or there is no requirement, handle it normally
_ => None,
};
- if let Some((range_str, pluralized)) = required {
+ if let Some(num) = required {
// We are issuing E0718 "incorrect target" here, because while the
// item kind of the target is correct, the target is still wrong
// because of the wrong number of generic arguments.
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(IncorrectTarget {
span,
- E0718,
- "`{}` language item must be applied to a {} with {} generic argument{}",
- name,
- kind.descr(),
- range_str,
- pluralized,
- )
- .span_label(
generics_span,
- format!(
- "this {} has {} generic argument{}",
- kind.descr(),
- actual_num,
- pluralize!(actual_num),
- ),
- )
- .emit();
+ name: name.as_str(),
+ kind: kind.descr(),
+ num,
+ actual_num,
+ at_least,
+ });
// return early to not collect the lang item
return;
@@ -240,9 +217,9 @@ 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.def_id)), id.hir_id());
+ collector.check_for_lang(Target::from_def_kind(tcx.def_kind(id.owner_id)), id.hir_id());
- if matches!(tcx.def_kind(id.def_id), DefKind::Enum) {
+ 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 {
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index fd03f6571..5322baee7 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -3,20 +3,23 @@ use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
+use rustc_span::source_map::Spanned;
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::abi::{HasDataLayout, TargetDataLayout};
+use crate::errors::{Abi, Align, HomogeneousAggregate, LayoutOf, Size, UnrecognizedField};
+
pub fn test_layout(tcx: TyCtxt<'_>) {
if tcx.features().rustc_attrs {
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
for id in tcx.hir().items() {
if matches!(
- tcx.def_kind(id.def_id),
+ tcx.def_kind(id.owner_id),
DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union
) {
- for attr in tcx.get_attrs(id.def_id.to_def_id(), sym::rustc_layout) {
- dump_layout_of(tcx, id.def_id, attr);
+ for attr in tcx.get_attrs(id.owner_id.to_def_id(), sym::rustc_layout) {
+ dump_layout_of(tcx, id.owner_id.def_id, attr);
}
}
}
@@ -35,62 +38,64 @@ fn dump_layout_of<'tcx>(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, attr: &Attri
for meta_item in meta_items {
match meta_item.name_or_empty() {
sym::abi => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("abi: {:?}", ty_layout.abi),
- );
+ tcx.sess.emit_err(Abi {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ abi: format!("{:?}", ty_layout.abi),
+ });
}
sym::align => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("align: {:?}", ty_layout.align),
- );
+ tcx.sess.emit_err(Align {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ align: format!("{:?}", ty_layout.align),
+ });
}
sym::size => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("size: {:?}", ty_layout.size),
- );
+ tcx.sess.emit_err(Size {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ size: format!("{:?}", ty_layout.size),
+ });
}
sym::homogeneous_aggregate => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!(
- "homogeneous_aggregate: {:?}",
- ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env }),
+ tcx.sess.emit_err(HomogeneousAggregate {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ homogeneous_aggregate: format!(
+ "{:?}",
+ ty_layout.homogeneous_aggregate(&UnwrapLayoutCx { tcx, param_env })
),
- );
+ });
}
sym::debug => {
- let normalized_ty = tcx.normalize_erasing_regions(
- param_env.with_reveal_all_normalized(tcx),
- ty,
- );
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("layout_of({:?}) = {:#?}", normalized_ty, *ty_layout),
+ let normalized_ty = format!(
+ "{:?}",
+ tcx.normalize_erasing_regions(
+ param_env.with_reveal_all_normalized(tcx),
+ ty,
+ )
);
+ let ty_layout = format!("{:#?}", *ty_layout);
+ tcx.sess.emit_err(LayoutOf {
+ span: tcx.def_span(item_def_id.to_def_id()),
+ normalized_ty,
+ ty_layout,
+ });
}
name => {
- tcx.sess.span_err(
- meta_item.span(),
- &format!("unrecognized field name `{}`", name),
- );
+ tcx.sess.emit_err(UnrecognizedField { span: meta_item.span(), name });
}
}
}
}
Err(layout_error) => {
- tcx.sess.span_err(
- tcx.def_span(item_def_id.to_def_id()),
- &format!("layout error: {:?}", layout_error),
- );
+ tcx.sess.emit_fatal(Spanned {
+ node: layout_error,
+ span: tcx.def_span(item_def_id.to_def_id()),
+ });
}
}
}
diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs
index 39ebb8db2..15f60f626 100644
--- a/compiler/rustc_passes/src/lib.rs
+++ b/compiler/rustc_passes/src/lib.rs
@@ -5,10 +5,11 @@
//! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(map_try_insert)]
#![feature(min_specialization)]
#![feature(try_blocks)]
diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs
index 04173c792..b5843c0ae 100644
--- a/compiler/rustc_passes/src/lib_features.rs
+++ b/compiler/rustc_passes/src/lib_features.rs
@@ -6,7 +6,6 @@
use rustc_ast::{Attribute, MetaItemKind};
use rustc_attr::{rust_version_symbol, VERSION_PLACEHOLDER};
-use rustc_errors::struct_span_err;
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::lib_features::LibFeatures;
@@ -15,6 +14,8 @@ use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::Symbol;
use rustc_span::{sym, Span};
+use crate::errors::{FeaturePreviouslyDeclared, FeatureStableTwice};
+
fn new_lib_features() -> LibFeatures {
LibFeatures { stable: Default::default(), unstable: Default::default() }
}
@@ -92,14 +93,12 @@ impl<'tcx> LibFeatureCollector<'tcx> {
(Some(since), _, false) => {
if let Some((prev_since, _)) = self.lib_features.stable.get(&feature) {
if *prev_since != since {
- self.span_feature_error(
+ self.tcx.sess.emit_err(FeatureStableTwice {
span,
- &format!(
- "feature `{}` is declared stable since {}, \
- but was previously declared stable since {}",
- feature, since, prev_since,
- ),
- );
+ feature,
+ since,
+ prev_since: *prev_since,
+ });
return;
}
}
@@ -110,22 +109,17 @@ impl<'tcx> LibFeatureCollector<'tcx> {
self.lib_features.unstable.insert(feature, span);
}
(Some(_), _, true) | (None, true, _) => {
- self.span_feature_error(
+ let declared = if since.is_some() { "stable" } else { "unstable" };
+ let prev_declared = if since.is_none() { "stable" } else { "unstable" };
+ self.tcx.sess.emit_err(FeaturePreviouslyDeclared {
span,
- &format!(
- "feature `{}` is declared {}, but was previously declared {}",
- feature,
- if since.is_some() { "stable" } else { "unstable" },
- if since.is_none() { "stable" } else { "unstable" },
- ),
- );
+ feature,
+ declared,
+ prev_declared,
+ });
}
}
}
-
- fn span_feature_error(&self, span: Span, msg: &str) {
- struct_span_err!(self.tcx.sess, span, E0711, "{}", &msg).emit();
- }
}
impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 6a4cd79cd..c6fe40f72 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1319,14 +1319,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// that we do not emit the same warning twice if the uninhabited type
// is indeed `!`.
+ let msg = format!("unreachable {}", descr);
self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNREACHABLE_CODE,
expr_id,
expr_span,
- |lint| {
- let msg = format!("unreachable {}", descr);
- lint.build(&msg)
- .span_label(expr_span, &msg)
+ &msg,
+ |diag| {
+ diag.span_label(expr_span, &msg)
.span_label(orig_span, "any code following this expression is unreachable")
.span_note(
orig_span,
@@ -1335,7 +1335,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
orig_ty
),
)
- .emit();
},
);
}
@@ -1491,14 +1490,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_ASSIGNMENTS,
var_hir_id,
vec![span],
- |lint| {
- lint.build(&format!(
- "value captured by `{}` is never read",
- name
- ))
- .help("did you mean to capture by reference instead?")
- .emit();
- },
+ format!("value captured by `{}` is never read", name),
+ |lint| lint.help("did you mean to capture by reference instead?"),
);
}
}
@@ -1508,11 +1501,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_VARIABLES,
var_hir_id,
vec![span],
- |lint| {
- lint.build(&format!("unused variable: `{}`", name))
- .help("did you mean to capture by reference instead?")
- .emit();
- },
+ format!("unused variable: `{}`", name),
+ |lint| lint.help("did you mean to capture by reference instead?"),
);
}
}
@@ -1601,20 +1591,17 @@ impl<'tcx> Liveness<'_, 'tcx> {
.into_iter()
.map(|(_, _, ident_span)| ident_span)
.collect::<Vec<_>>(),
- |lint| {
- lint.build(&format!("variable `{}` is assigned to, but never used", name))
- .note(&format!("consider using `_{}` instead", name))
- .emit();
- },
+ format!("variable `{}` is assigned to, but never used", name),
+ |lint| lint.note(&format!("consider using `_{}` instead", name)),
)
} else if can_remove {
self.ir.tcx.struct_span_lint_hir(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"try removing the field",
hir_ids_and_spans
.iter()
@@ -1629,8 +1616,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
})
.collect(),
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
} else {
@@ -1661,14 +1647,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
.iter()
.map(|(_, pat_span, _)| *pat_span)
.collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"try ignoring the field",
shorthands,
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
} else {
@@ -1684,17 +1669,16 @@ impl<'tcx> Liveness<'_, 'tcx> {
.iter()
.map(|(_, _, ident_span)| *ident_span)
.collect::<Vec<_>>(),
+ format!("unused variable: `{}`", name),
|lint| {
- let mut err = lint.build(&format!("unused variable: `{}`", name));
- if self.has_added_lit_match_name_span(&name, opt_body, &mut err) {
- err.span_label(pat.span, "unused variable");
+ if self.has_added_lit_match_name_span(&name, opt_body, lint) {
+ lint.span_label(pat.span, "unused variable");
}
- err.multipart_suggestion(
+ lint.multipart_suggestion(
"if this is intentional, prefix it with an underscore",
non_shorthands,
Applicability::MachineApplicable,
- );
- err.emit();
+ )
},
);
}
@@ -1758,11 +1742,8 @@ impl<'tcx> Liveness<'_, 'tcx> {
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
- |lint| {
- lint.build(&message(&name))
- .help("maybe it is overwritten before being read?")
- .emit();
- },
+ message(&name),
+ |lint| lint.help("maybe it is overwritten before being read?"),
)
}
}
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index cdda0e388..077194ec6 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -1,6 +1,5 @@
use Context::*;
-use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
@@ -13,6 +12,11 @@ use rustc_session::Session;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::Span;
+use crate::errors::{
+ BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop,
+ UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
+};
+
#[derive(Clone, Copy, Debug, PartialEq)]
enum Context {
Normal,
@@ -90,7 +94,10 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
Ok(loop_id) => Some(loop_id),
Err(hir::LoopIdError::OutsideLoopScope) => None,
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
- self.emit_unlabled_cf_in_while_condition(e.span, "break");
+ self.sess.emit_err(UnlabeledCfInWhileCondition {
+ span: e.span,
+ cf_type: "break",
+ });
None
}
Err(hir::LoopIdError::UnresolvedLabel) => None,
@@ -116,69 +123,22 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
match loop_kind {
None | Some(hir::LoopSource::Loop) => (),
Some(kind) => {
- let mut err = struct_span_err!(
- self.sess,
- e.span,
- E0571,
- "`break` with value from a `{}` loop",
- kind.name()
- );
- err.span_label(
- e.span,
- "can only break with a value inside `loop` or breakable block",
+ let suggestion = format!(
+ "break{}",
+ break_label
+ .label
+ .map_or_else(String::new, |l| format!(" {}", l.ident))
);
- if let Some(head) = head {
- err.span_label(
- head,
- &format!(
- "you can't `break` with a value in a `{}` loop",
- kind.name()
- ),
- );
- }
- err.span_suggestion(
- e.span,
- &format!(
- "use `break` on its own without a value inside this `{}` loop",
- kind.name(),
- ),
- format!(
- "break{}",
- break_label
- .label
- .map_or_else(String::new, |l| format!(" {}", l.ident))
- ),
- Applicability::MaybeIncorrect,
- );
- if let (Some(label), None) = (loop_label, break_label.label) {
- match break_expr.kind {
- hir::ExprKind::Path(hir::QPath::Resolved(
- None,
- hir::Path {
- segments: [segment],
- res: hir::def::Res::Err,
- ..
- },
- )) if label.ident.to_string()
- == format!("'{}", segment.ident) =>
- {
- // This error is redundant, we will have already emitted a
- // suggestion to use the label when `segment` wasn't found
- // (hence the `Res::Err` check).
- err.delay_as_bug();
- }
- _ => {
- err.span_suggestion(
- break_expr.span,
- "alternatively, you might have meant to use the \
- available loop label",
- label.ident,
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
- err.emit();
+ self.sess.emit_err(BreakNonLoop {
+ span: e.span,
+ head,
+ kind: kind.name(),
+ suggestion,
+ loop_label,
+ break_label: break_label.label,
+ break_expr_kind: &break_expr.kind,
+ break_expr_span: break_expr.span,
+ });
}
}
}
@@ -191,19 +151,17 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
match destination.target_id {
Ok(loop_id) => {
if let Node::Block(block) = self.hir_map.find(loop_id).unwrap() {
- struct_span_err!(
- self.sess,
- e.span,
- E0696,
- "`continue` pointing to a labeled block"
- )
- .span_label(e.span, "labeled blocks cannot be `continue`'d")
- .span_label(block.span, "labeled block the `continue` points to")
- .emit();
+ self.sess.emit_err(ContinueLabeledBlock {
+ span: e.span,
+ block_span: block.span,
+ });
}
}
Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => {
- self.emit_unlabled_cf_in_while_condition(e.span, "continue");
+ self.sess.emit_err(UnlabeledCfInWhileCondition {
+ span: e.span,
+ cf_type: "continue",
+ });
}
Err(_) => {}
}
@@ -226,21 +184,16 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
}
fn require_break_cx(&self, name: &str, span: Span) {
- let err_inside_of = |article, ty, closure_span| {
- struct_span_err!(self.sess, span, E0267, "`{}` inside of {} {}", name, article, ty)
- .span_label(span, format!("cannot `{}` inside of {} {}", name, article, ty))
- .span_label(closure_span, &format!("enclosing {}", ty))
- .emit();
- };
-
match self.cx {
LabeledBlock | Loop(_) => {}
- Closure(closure_span) => err_inside_of("a", "closure", closure_span),
- AsyncClosure(closure_span) => err_inside_of("an", "`async` block", closure_span),
+ Closure(closure_span) => {
+ self.sess.emit_err(BreakInsideClosure { span, closure_span, name });
+ }
+ AsyncClosure(closure_span) => {
+ self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name });
+ }
Normal | AnonConst => {
- struct_span_err!(self.sess, span, E0268, "`{}` outside of a loop", name)
- .span_label(span, format!("cannot `{}` outside of a loop", name))
- .emit();
+ self.sess.emit_err(OutsideLoop { span, name });
}
}
}
@@ -251,37 +204,13 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
label: &Destination,
cf_type: &str,
) -> bool {
- if !span.is_desugaring(DesugaringKind::QuestionMark) && self.cx == LabeledBlock {
- if label.label.is_none() {
- struct_span_err!(
- self.sess,
- span,
- E0695,
- "unlabeled `{}` inside of a labeled block",
- cf_type
- )
- .span_label(
- span,
- format!(
- "`{}` statements that would diverge to or through \
- a labeled block need to bear a label",
- cf_type
- ),
- )
- .emit();
- return true;
- }
+ if !span.is_desugaring(DesugaringKind::QuestionMark)
+ && self.cx == LabeledBlock
+ && label.label.is_none()
+ {
+ self.sess.emit_err(UnlabeledInLabeledBlock { span, cf_type });
+ return true;
}
false
}
- fn emit_unlabled_cf_in_while_condition(&mut self, span: Span, cf_type: &str) {
- struct_span_err!(
- self.sess,
- span,
- E0590,
- "`break` or `continue` with no label in the condition of a `while` loop"
- )
- .span_label(span, format!("unlabeled `{}` in the condition of a `while` loop", cf_type))
- .emit();
- }
}
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 607973446..acc54e7e1 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,7 +1,6 @@
//! Checks validity of naked functions.
use rustc_ast::InlineAsmOptions;
-use rustc_errors::{struct_span_err, Applicability};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
@@ -14,6 +13,12 @@ use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
+use crate::errors::{
+ CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
+ NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
+ UndefinedNakedFunctionAbi,
+};
+
pub(crate) fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_naked_functions, ..*providers };
}
@@ -56,7 +61,7 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let attrs = tcx.get_attrs(def_id.to_def_id(), sym::inline);
for attr in attrs {
- tcx.sess.struct_span_err(attr.span, "naked functions cannot be inlined").emit();
+ tcx.sess.emit_err(CannotInlineNakedFunction { span: attr.span });
}
}
@@ -65,9 +70,12 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
if abi == Abi::Rust {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let span = tcx.def_span(def_id);
- tcx.struct_span_lint_hir(UNDEFINED_NAKED_FUNCTION_ABI, hir_id, span, |lint| {
- lint.build("Rust ABI is unsupported in naked functions").emit();
- });
+ tcx.emit_spanned_lint(
+ UNDEFINED_NAKED_FUNCTION_ABI,
+ hir_id,
+ span,
+ UndefinedNakedFunctionAbi,
+ );
}
}
@@ -78,12 +86,7 @@ fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
hir::PatKind::Wild
| hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, _, None) => {}
_ => {
- tcx.sess
- .struct_span_err(
- param.pat.span,
- "patterns not allowed in naked function parameters",
- )
- .emit();
+ tcx.sess.emit_err(NoPatterns { span: param.pat.span });
}
}
}
@@ -113,14 +116,7 @@ impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
)) = expr.kind
{
if self.params.contains(var_hir_id) {
- self.tcx
- .sess
- .struct_span_err(
- expr.span,
- "referencing function parameters is not allowed in naked functions",
- )
- .help("follow the calling convention in asm block to use parameters")
- .emit();
+ self.tcx.sess.emit_err(ParamsNotAllowed { span: expr.span });
return;
}
}
@@ -135,26 +131,21 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
if let [(ItemKind::Asm | ItemKind::Err, _)] = this.items[..] {
// Ok.
} else {
- let mut diag = struct_span_err!(
- tcx.sess,
- tcx.def_span(def_id),
- E0787,
- "naked functions must contain a single asm block"
- );
-
let mut must_show_error = false;
let mut has_asm = false;
let mut has_err = false;
+ let mut multiple_asms = vec![];
+ let mut non_asms = vec![];
for &(kind, span) in &this.items {
match kind {
ItemKind::Asm if has_asm => {
must_show_error = true;
- diag.span_label(span, "multiple asm blocks are unsupported in naked functions");
+ multiple_asms.push(span);
}
ItemKind::Asm => has_asm = true,
ItemKind::NonAsm => {
must_show_error = true;
- diag.span_label(span, "non-asm is unsupported in naked functions");
+ non_asms.push(span);
}
ItemKind::Err => has_err = true,
}
@@ -164,9 +155,11 @@ fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<
// errors, then don't show an additional error. This allows for appending/prepending
// `compile_error!("...")` statements and reduces error noise.
if must_show_error || !has_err {
- diag.emit();
- } else {
- diag.cancel();
+ tcx.sess.emit_err(NakedFunctionsAsmBlock {
+ span: tcx.def_span(def_id),
+ multiple_asms,
+ non_asms,
+ });
}
}
}
@@ -247,13 +240,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
})
.collect();
if !unsupported_operands.is_empty() {
- struct_span_err!(
- self.tcx.sess,
- unsupported_operands,
- E0787,
- "only `const` and `sym` operands are supported in naked functions",
- )
- .emit();
+ self.tcx.sess.emit_err(NakedFunctionsOperands { unsupported_operands });
}
let unsupported_options: Vec<&'static str> = [
@@ -269,14 +256,10 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
.collect();
if !unsupported_options.is_empty() {
- struct_span_err!(
- self.tcx.sess,
+ self.tcx.sess.emit_err(NakedFunctionsAsmOptions {
span,
- E0787,
- "asm options unsupported in naked functions: {}",
- unsupported_options.join(", ")
- )
- .emit();
+ unsupported_options: unsupported_options.join(", "),
+ });
}
if !asm.options.contains(InlineAsmOptions::NORETURN) {
@@ -286,20 +269,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
.map_or_else(|| asm.template_strs.last().unwrap().2, |op| op.1)
.shrink_to_hi();
- struct_span_err!(
- self.tcx.sess,
- span,
- E0787,
- "asm in naked functions must use `noreturn` option"
- )
- .span_suggestion(
- last_span,
- "consider specifying that the asm block is responsible \
- for returning from the function",
- ", options(noreturn)",
- Applicability::MachineApplicable,
- )
- .emit();
+ self.tcx.sess.emit_err(NakedFunctionsMustUseNoreturn { span, last_span });
}
}
}
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index f7e3fac6b..50070869a 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::Node;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
-use rustc_middle::middle::privacy;
+use rustc_middle::middle::privacy::{self, Level};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, DefIdTree, TyCtxt};
use rustc_session::config::CrateType;
@@ -29,7 +29,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'_>, item: &hir::Item<'_>, attrs: &CodegenF
match item.kind {
hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => true,
hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => {
- let generics = tcx.generics_of(item.def_id);
+ let generics = tcx.generics_of(item.owner_id);
generics.requires_monomorphization(tcx)
}
_ => false,
@@ -42,7 +42,7 @@ fn method_might_be_inlined(
impl_src: LocalDefId,
) -> bool {
let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id().owner.to_def_id());
- let generics = tcx.generics_of(impl_item.def_id);
+ let generics = tcx.generics_of(impl_item.owner_id);
if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) {
return true;
}
@@ -116,6 +116,17 @@ impl<'tcx> Visitor<'tcx> for ReachableContext<'tcx> {
intravisit::walk_expr(self, expr)
}
+
+ fn visit_inline_asm(&mut self, asm: &'tcx hir::InlineAsm<'tcx>, id: hir::HirId) {
+ for (op, _) in asm.operands {
+ if let hir::InlineAsmOperand::SymStatic { def_id, .. } = op {
+ if let Some(def_id) = def_id.as_local() {
+ self.reachable_symbols.insert(def_id);
+ }
+ }
+ }
+ intravisit::walk_inline_asm(self, asm, id);
+ }
}
impl<'tcx> ReachableContext<'tcx> {
@@ -153,9 +164,9 @@ impl<'tcx> ReachableContext<'tcx> {
hir::ImplItemKind::Fn(..) => {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
let impl_did = self.tcx.hir().get_parent_item(hir_id);
- method_might_be_inlined(self.tcx, impl_item, impl_did)
+ method_might_be_inlined(self.tcx, impl_item, impl_did.def_id)
}
- hir::ImplItemKind::TyAlias(_) => false,
+ hir::ImplItemKind::Type(_) => false,
},
Some(_) => false,
None => false, // This will happen for default methods.
@@ -216,7 +227,7 @@ impl<'tcx> ReachableContext<'tcx> {
if item_might_be_inlined(
self.tcx,
&item,
- self.tcx.codegen_fn_attrs(item.def_id),
+ self.tcx.codegen_fn_attrs(item.owner_id),
) {
self.visit_nested_body(body);
}
@@ -271,7 +282,7 @@ impl<'tcx> ReachableContext<'tcx> {
self.visit_nested_body(body)
}
}
- hir::ImplItemKind::TyAlias(_) => {}
+ hir::ImplItemKind::Type(_) => {}
},
Node::Expr(&hir::Expr {
kind: hir::ExprKind::Closure(&hir::Closure { body, .. }),
@@ -303,13 +314,13 @@ fn check_item<'tcx>(
tcx: TyCtxt<'tcx>,
id: hir::ItemId,
worklist: &mut Vec<LocalDefId>,
- access_levels: &privacy::AccessLevels,
+ effective_visibilities: &privacy::EffectiveVisibilities,
) {
- if has_custom_linkage(tcx, id.def_id) {
- worklist.push(id.def_id);
+ if has_custom_linkage(tcx, id.owner_id.def_id) {
+ worklist.push(id.owner_id.def_id);
}
- if !matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
+ if !matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
return;
}
@@ -318,8 +329,8 @@ fn check_item<'tcx>(
if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref trait_ref), ref items, .. }) =
item.kind
{
- if !access_levels.is_reachable(item.def_id) {
- worklist.extend(items.iter().map(|ii_ref| ii_ref.id.def_id));
+ if !effective_visibilities.is_reachable(item.owner_id.def_id) {
+ worklist.extend(items.iter().map(|ii_ref| ii_ref.id.owner_id.def_id));
let Res::Def(DefKind::Trait, trait_def_id) = trait_ref.path.res else {
unreachable!();
@@ -354,7 +365,7 @@ fn has_custom_linkage<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
}
fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
- let access_levels = &tcx.privacy_access_levels(());
+ let effective_visibilities = &tcx.effective_visibilities(());
let any_library =
tcx.sess.crate_types().iter().any(|ty| {
@@ -373,7 +384,13 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
// If other crates link to us, they're going to expect to be able to
// use the lang items, so we need to be sure to mark them as
// exported.
- reachable_context.worklist.extend(access_levels.map.keys());
+ reachable_context.worklist = effective_visibilities
+ .iter()
+ .filter_map(|(&id, effective_vis)| {
+ effective_vis.is_public_at_level(Level::ReachableThroughImplTrait).then_some(id)
+ })
+ .collect::<Vec<_>>();
+
for item in tcx.lang_items().items().iter() {
if let Some(def_id) = *item {
if let Some(def_id) = def_id.as_local() {
@@ -393,12 +410,12 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- check_item(tcx, id, &mut reachable_context.worklist, access_levels);
+ check_item(tcx, id, &mut reachable_context.worklist, effective_visibilities);
}
for id in crate_items.impl_items() {
- if has_custom_linkage(tcx, id.def_id) {
- reachable_context.worklist.push(id.def_id);
+ if has_custom_linkage(tcx, id.owner_id.def_id) {
+ reachable_context.worklist.push(id.owner_id.def_id);
}
}
}
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 9ba127609..78afa2f25 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -1,12 +1,18 @@
//! 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 rustc_attr::{
self as attr, rust_version_symbol, ConstStability, Stability, StabilityLevel, Unstable,
UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
-use rustc_errors::{struct_span_err, Applicability};
+use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID};
@@ -14,12 +20,11 @@ use rustc_hir::hir_id::CRATE_HIR_ID;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::middle::stability::{AllowUnstable, DeprecationEntry, Index};
use rustc_middle::ty::{query::Providers, TyCtxt};
use rustc_session::lint;
use rustc_session::lint::builtin::{INEFFECTIVE_UNSTABLE_TRAIT_IMPL, USELESS_DEPRECATED};
-use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::Span;
use rustc_target::spec::abi::Abi;
@@ -122,16 +127,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited || kind == AnnotationKind::DeprecationProhibited {
let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- self.tcx.struct_span_lint_hir(USELESS_DEPRECATED, hir_id, *span, |lint| {
- lint.build("this `#[deprecated]` annotation has no effect")
- .span_suggestion_short(
- *span,
- "remove the unnecessary deprecation attribute",
- "",
- rustc_errors::Applicability::MachineApplicable,
- )
- .emit();
- });
+ self.tcx.emit_spanned_lint(
+ USELESS_DEPRECATED,
+ hir_id,
+ *span,
+ errors::DeprecatedAnnotationHasNoEffect { span: *span },
+ );
}
// `Deprecation` is just two pointers, no need to intern it
@@ -182,7 +183,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if !self.in_trait_impl
|| (self.in_trait_impl && !self.tcx.is_const_fn_raw(def_id.to_def_id()))
{
- missing_const_err(&self.tcx.sess, fn_sig.span, const_span);
+ self.tcx
+ .sess
+ .emit_err(MissingConstErr { fn_sig_span: fn_sig.span, const_span });
}
}
}
@@ -200,14 +203,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if let Some((rustc_attr::Deprecation { is_since_rustc_version: true, .. }, span)) = &depr {
if stab.is_none() {
- struct_span_err!(
- self.tcx.sess,
- *span,
- E0549,
- "deprecated attribute must be paired with \
- either stable or unstable attribute"
- )
- .emit();
+ self.tcx.sess.emit_err(DeprecatedAttribute { span: *span });
}
}
@@ -223,10 +219,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if kind == AnnotationKind::Prohibited
|| (kind == AnnotationKind::Container && stab.level.is_stable() && is_deprecated)
{
- self.tcx.sess.struct_span_err(span,"this stability annotation is useless")
- .span_label(span, "useless stability annotation")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx.sess.emit_err(UselessStability { span, item_sp });
}
debug!("annotate: found {:?}", stab);
@@ -242,19 +235,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
{
match stab_v.parse::<u64>() {
Err(_) => {
- self.tcx.sess.struct_span_err(span, "invalid stability version found")
- .span_label(span, "invalid stability version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx.sess.emit_err(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.struct_span_err(span, "an API can't be stabilized after it is deprecated")
- .span_label(span, "invalid version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx
+ .sess
+ .emit_err(CannotStabilizeDeprecated { span, item_sp });
break;
}
Ordering::Equal => continue,
@@ -262,10 +251,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
},
Err(_) => {
if dep_v != "TBD" {
- self.tcx.sess.struct_span_err(span, "invalid deprecation version found")
- .span_label(span, "invalid deprecation version")
- .span_label(item_sp, "the stability attribute annotates this item")
- .emit();
+ self.tcx
+ .sess
+ .emit_err(InvalidDeprecationVersion { span, item_sp });
}
break;
}
@@ -274,7 +262,9 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
}
}
- if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab {
+ if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } =
+ stab
+ {
self.index.implications.insert(implied_by, feature);
}
@@ -388,7 +378,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
}
self.annotate(
- i.def_id,
+ i.owner_id.def_id,
i.span,
fn_sig,
kind,
@@ -407,7 +397,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
};
self.annotate(
- ti.def_id,
+ ti.owner_id.def_id,
ti.span,
fn_sig,
AnnotationKind::Required,
@@ -430,7 +420,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
};
self.annotate(
- ii.def_id,
+ ii.owner_id.def_id,
ii.span,
fn_sig,
kind,
@@ -488,7 +478,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
self.annotate(
- i.def_id,
+ i.owner_id.def_id,
i.span,
None,
AnnotationKind::Required,
@@ -526,15 +516,18 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
struct MissingStabilityAnnotations<'tcx> {
tcx: TyCtxt<'tcx>,
- access_levels: &'tcx AccessLevels,
+ effective_visibilities: &'tcx EffectiveVisibilities,
}
impl<'tcx> MissingStabilityAnnotations<'tcx> {
fn check_missing_stability(&self, def_id: LocalDefId, span: Span) {
let stab = self.tcx.stability().local_stability(def_id);
- if !self.tcx.sess.opts.test && stab.is_none() && self.access_levels.is_reachable(def_id) {
+ if !self.tcx.sess.opts.test
+ && 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.span_err(span, &format!("{} has missing stability attribute", descr));
+ self.tcx.sess.emit_err(MissingStabilityAttr { span, descr });
}
}
@@ -550,11 +543,11 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
.lookup_stability(def_id)
.map_or(false, |stability| stability.level.is_stable());
let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none();
- let is_reachable = self.access_levels.is_reachable(def_id);
+ 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.span_err(span, &format!("{descr} has missing const stability attribute"));
+ self.tcx.sess.emit_err(MissingConstStabAttr { span, descr });
}
}
}
@@ -576,25 +569,25 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
hir::ItemKind::Impl(hir::Impl { of_trait: None, .. })
| hir::ItemKind::ForeignMod { .. }
) {
- self.check_missing_stability(i.def_id, i.span);
+ self.check_missing_stability(i.owner_id.def_id, i.span);
}
// Ensure stable `const fn` have a const stability attribute.
- self.check_missing_const_stability(i.def_id, i.span);
+ self.check_missing_const_stability(i.owner_id.def_id, i.span);
intravisit::walk_item(self, i)
}
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
- self.check_missing_stability(ti.def_id, ti.span);
+ self.check_missing_stability(ti.owner_id.def_id, ti.span);
intravisit::walk_trait_item(self, ti);
}
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
- self.check_missing_stability(ii.def_id, ii.span);
- self.check_missing_const_stability(ii.def_id, ii.span);
+ self.check_missing_stability(ii.owner_id.def_id, ii.span);
+ self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
}
intravisit::walk_impl_item(self, ii);
}
@@ -613,7 +606,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
}
fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) {
- self.check_missing_stability(i.def_id, i.span);
+ self.check_missing_stability(i.owner_id.def_id, i.span);
intravisit::walk_foreign_item(self, i);
}
// Note that we don't need to `check_missing_stability` for default generic parameters,
@@ -719,7 +712,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
return;
}
- let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.def_id) else {
+ let Some(cnum) = self.tcx.extern_mod_stmt_cnum(item.owner_id.def_id) else {
return;
};
let def_id = cnum.as_def_id();
@@ -755,10 +748,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
span,
- |lint| {lint
- .build("an `#[unstable]` annotation here has no effect")
- .note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
- .emit();}
+ "an `#[unstable]` annotation here has no effect",
+ |lint| lint.note("see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information")
);
}
}
@@ -769,16 +760,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
&& *constness == hir::Constness::Const
&& const_stab.map_or(false, |(stab, _)| stab.is_const_stable())
{
- self.tcx
- .sess
- .struct_span_err(item.span, "trait implementations cannot be const stable yet")
- .note("see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information")
- .emit();
+ self.tcx.sess.emit_err(TraitImplConstStable { span: item.span });
}
}
for impl_item_ref in *items {
- let impl_item = self.tcx.associated_item(impl_item_ref.id.def_id);
+ let impl_item = self.tcx.associated_item(impl_item_ref.id.owner_id);
if let Some(def_id) = impl_item.trait_item_def_id {
// Pass `None` to skip deprecation warnings.
@@ -872,7 +859,7 @@ fn is_unstable_reexport<'tcx>(tcx: TyCtxt<'tcx>, id: hir::HirId) -> bool {
}
// If this is a path that isn't a use, we don't need to do anything special
- if !matches!(tcx.hir().item(hir::ItemId { def_id }).kind, ItemKind::Use(..)) {
+ if !matches!(tcx.hir().expect_item(def_id).kind, ItemKind::Use(..)) {
return false;
}
@@ -907,8 +894,25 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
if let TyKind::Never = t.kind {
self.fully_stable = false;
}
+ if let TyKind::BareFn(f) = t.kind {
+ if rustc_target::spec::abi::is_stable(f.abi.name()).is_err() {
+ self.fully_stable = false;
+ }
+ }
intravisit::walk_ty(self, t)
}
+
+ fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) {
+ for ty in fd.inputs {
+ self.visit_ty(ty)
+ }
+ if let hir::FnRetTy::Return(output_ty) = fd.output {
+ match output_ty.kind {
+ TyKind::Never => {} // `-> !` is stable
+ _ => self.visit_ty(output_ty),
+ }
+ }
+ }
}
/// Given the list of enabled features that were not language features (i.e., that
@@ -918,8 +922,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
let is_staged_api =
tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api;
if is_staged_api {
- let access_levels = &tcx.privacy_access_levels(());
- let mut missing = MissingStabilityAnnotations { tcx, access_levels };
+ let effective_visibilities = &tcx.effective_visibilities(());
+ let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
missing.check_missing_stability(CRATE_DEF_ID, tcx.hir().span(CRATE_HIR_ID));
tcx.hir().walk_toplevel_module(&mut missing);
tcx.hir().visit_all_item_likes_in_crate(&mut missing);
@@ -934,7 +938,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.
- duplicate_feature_err(tcx.sess, span, feature);
+ tcx.sess.emit_err(DuplicateFeatureErr { span, feature });
}
}
@@ -942,18 +946,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() {
- struct_span_err!(
- tcx.sess,
- *span,
- E0554,
- "`#![feature]` may not be used on the {} release channel",
- env!("CFG_RELEASE_CHANNEL")
- )
- .emit();
+ tcx.sess.emit_err(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.
- duplicate_feature_err(tcx.sess, *span, *feature);
+ tcx.sess.emit_err(DuplicateFeatureErr { span: *span, feature: *feature });
}
remaining_lib_features.insert(feature, *span);
}
@@ -1054,23 +1054,18 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
}
for (feature, span) in remaining_lib_features {
- struct_span_err!(tcx.sess, span, E0635, "unknown feature `{}`", feature).emit();
+ tcx.sess.emit_err(UnknownFeature { span, feature: *feature });
}
for (implied_by, feature) in remaining_implications {
let local_defined_features = tcx.lib_features(());
- let span = local_defined_features
+ let span = *local_defined_features
.stable
.get(&feature)
.map(|(_, span)| span)
.or_else(|| local_defined_features.unstable.get(&feature))
.expect("feature that implied another does not exist");
- tcx.sess
- .struct_span_err(
- *span,
- format!("feature `{implied_by}` implying `{feature}` does not exist"),
- )
- .emit();
+ tcx.sess.emit_err(ImpliedFeatureNotExist { span, feature, implied_by });
}
// FIXME(#44232): the `used_features` table no longer exists, so we
@@ -1084,27 +1079,31 @@ fn unnecessary_partially_stable_feature_lint(
implies: Symbol,
since: Symbol,
) {
- tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
- lint.build(&format!(
+ tcx.struct_span_lint_hir(
+ lint::builtin::STABLE_FEATURES,
+ hir::CRATE_HIR_ID,
+ span,
+ format!(
"the feature `{feature}` has been partially stabilized since {since} and is succeeded \
by the feature `{implies}`"
- ))
- .span_suggestion(
- span,
- &format!(
+ ),
+ |lint| {
+ lint.span_suggestion(
+ span,
+ &format!(
"if you are using features which are still unstable, change to using `{implies}`"
),
- implies,
- Applicability::MaybeIncorrect,
- )
- .span_suggestion(
- tcx.sess.source_map().span_extend_to_line(span),
- "if you are using features which are now stable, remove this line",
- "",
- Applicability::MaybeIncorrect,
- )
- .emit();
- });
+ implies,
+ Applicability::MaybeIncorrect,
+ )
+ .span_suggestion(
+ tcx.sess.source_map().span_extend_to_line(span),
+ "if you are using features which are now stable, remove this line",
+ "",
+ Applicability::MaybeIncorrect,
+ )
+ },
+ );
}
fn unnecessary_stable_feature_lint(
@@ -1116,28 +1115,7 @@ fn unnecessary_stable_feature_lint(
if since.as_str() == VERSION_PLACEHOLDER {
since = rust_version_symbol();
}
- tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, |lint| {
- lint.build(&format!(
- "the feature `{feature}` has been stable since {since} and no longer requires an \
- attribute to enable",
- ))
- .emit();
+ tcx.struct_span_lint_hir(lint::builtin::STABLE_FEATURES, hir::CRATE_HIR_ID, span, format!("the feature `{feature}` has been stable since {since} and no longer requires an attribute to enable"), |lint| {
+ lint
});
}
-
-fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) {
- struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature)
- .emit();
-}
-
-fn missing_const_err(session: &Session, fn_sig_span: Span, const_span: Span) {
- const ERROR_MSG: &'static str = "attributes `#[rustc_const_unstable]` \
- and `#[rustc_const_stable]` require \
- the function or method to be `const`";
-
- session
- .struct_span_err(fn_sig_span, ERROR_MSG)
- .span_help(fn_sig_span, "make the function or method const")
- .span_label(const_span, "attribute specified here")
- .emit();
-}
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index c48b4ecf8..959ee600c 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -1,13 +1,17 @@
//! Validity checking for weak lang items
use rustc_data_structures::fx::FxHashSet;
-use rustc_errors::struct_span_err;
use rustc_hir::lang_items::{self, LangItem};
use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
use rustc_middle::middle::lang_items::required;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
+use crate::errors::{
+ AllocFuncRequired, MissingAllocErrorHandler, MissingLangItem, MissingPanicHandler,
+ UnknownExternLangItem,
+};
+
/// Checks the crate for usage of weak lang items, returning a vector of all the
/// language items required by this crate, but not defined yet.
pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItems) {
@@ -30,15 +34,8 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
items.missing.push(item);
}
} else {
- let span = tcx.def_span(id.def_id);
- struct_span_err!(
- tcx.sess,
- span,
- E0264,
- "unknown external lang item: `{}`",
- lang_item
- )
- .emit();
+ let span = tcx.def_span(id.owner_id);
+ tcx.sess.emit_err(UnknownExternLangItem { span, lang_item });
}
}
}
@@ -71,20 +68,14 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
for (name, &item) in WEAK_ITEMS_REFS.iter() {
if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
if item == LangItem::PanicImpl {
- tcx.sess.err("`#[panic_handler]` function required, but not found");
+ tcx.sess.emit_err(MissingPanicHandler);
} else if item == LangItem::Oom {
if !tcx.features().default_alloc_error_handler {
- tcx.sess.err("`#[alloc_error_handler]` function required, but not found");
- tcx.sess.note_without_error("use `#![feature(default_alloc_error_handler)]` for a default error handler");
+ tcx.sess.emit_err(AllocFuncRequired);
+ tcx.sess.emit_note(MissingAllocErrorHandler);
}
} else {
- tcx
- .sess
- .diagnostic()
- .struct_err(&format!("language item required, but not found: `{}`", name))
- .note(&format!("this can occur when a binary crate with `#![no_std]` is compiled for a target where `{}` is defined in the standard library", name))
- .help(&format!("you may be able to compile for a target that doesn't need `{}`, specify a target with `--target` or in `.cargo/config`", name))
- .emit();
+ tcx.sess.emit_err(MissingLangItem { name: *name });
}
}
}
diff --git a/compiler/rustc_plugin_impl/Cargo.toml b/compiler/rustc_plugin_impl/Cargo.toml
index c409b6c3e..fa27bfc61 100644
--- a/compiler/rustc_plugin_impl/Cargo.toml
+++ b/compiler/rustc_plugin_impl/Cargo.toml
@@ -5,7 +5,6 @@ build = false
edition = "2021"
[lib]
-doctest = false
[dependencies]
libloading = "0.7.1"
diff --git a/compiler/rustc_plugin_impl/src/errors.rs b/compiler/rustc_plugin_impl/src/errors.rs
index 2bdb6e4fe..e6a7fc86b 100644
--- a/compiler/rustc_plugin_impl/src/errors.rs
+++ b/compiler/rustc_plugin_impl/src/errors.rs
@@ -1,18 +1,18 @@
//! Errors emitted by plugin_impl
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(plugin_impl::load_plugin_error)]
+#[derive(Diagnostic)]
+#[diag(plugin_impl_load_plugin_error)]
pub struct LoadPluginError {
#[primary_span]
pub span: Span,
pub msg: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(plugin_impl::malformed_plugin_attribute, code = "E0498")]
+#[derive(Diagnostic)]
+#[diag(plugin_impl_malformed_plugin_attribute, code = "E0498")]
pub struct MalformedPluginAttribute {
#[primary_span]
#[label]
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 5785921fb..832fdc9f0 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -14,5 +14,5 @@ rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
tracing = "0.1"
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index 63f83f896..a6c95f1a8 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -1,9 +1,9 @@
use rustc_errors::DiagnosticArgFromDisplay;
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(privacy::field_is_private, code = "E0451")]
+#[derive(Diagnostic)]
+#[diag(privacy_field_is_private, code = "E0451")]
pub struct FieldIsPrivate {
#[primary_span]
pub span: Span,
@@ -14,23 +14,23 @@ pub struct FieldIsPrivate {
pub label: FieldIsPrivateLabel,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum FieldIsPrivateLabel {
- #[label(privacy::field_is_private_is_update_syntax_label)]
+ #[label(privacy_field_is_private_is_update_syntax_label)]
IsUpdateSyntax {
#[primary_span]
span: Span,
field_name: Symbol,
},
- #[label(privacy::field_is_private_label)]
+ #[label(privacy_field_is_private_label)]
Other {
#[primary_span]
span: Span,
},
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::item_is_private)]
+#[derive(Diagnostic)]
+#[diag(privacy_item_is_private)]
pub struct ItemIsPrivate<'a> {
#[primary_span]
#[label]
@@ -39,8 +39,8 @@ pub struct ItemIsPrivate<'a> {
pub descr: DiagnosticArgFromDisplay<'a>,
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::unnamed_item_is_private)]
+#[derive(Diagnostic)]
+#[diag(privacy_unnamed_item_is_private)]
pub struct UnnamedItemIsPrivate {
#[primary_span]
pub span: Span,
@@ -48,8 +48,8 @@ pub struct UnnamedItemIsPrivate {
}
// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
-#[derive(SessionDiagnostic)]
-#[diag(privacy::in_public_interface, code = "E0445")]
+#[derive(Diagnostic)]
+#[diag(privacy_in_public_interface, code = "E0445")]
pub struct InPublicInterfaceTraits<'a> {
#[primary_span]
#[label]
@@ -57,13 +57,13 @@ pub struct InPublicInterfaceTraits<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(privacy::visibility_label)]
+ #[label(visibility_label)]
pub vis_span: Span,
}
// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
-#[derive(SessionDiagnostic)]
-#[diag(privacy::in_public_interface, code = "E0446")]
+#[derive(Diagnostic)]
+#[diag(privacy_in_public_interface, code = "E0446")]
pub struct InPublicInterface<'a> {
#[primary_span]
#[label]
@@ -71,20 +71,20 @@ pub struct InPublicInterface<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(privacy::visibility_label)]
+ #[label(visibility_label)]
pub vis_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::report_access_level)]
-pub struct ReportAccessLevel {
+#[derive(Diagnostic)]
+#[diag(privacy_report_effective_visibility)]
+pub struct ReportEffectiveVisibility {
#[primary_span]
pub span: Span,
pub descr: String,
}
#[derive(LintDiagnostic)]
-#[diag(privacy::from_private_dep_in_public_interface)]
+#[diag(privacy_from_private_dep_in_public_interface)]
pub struct FromPrivateDependencyInPublicInterface<'a> {
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
@@ -92,7 +92,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(privacy::private_in_public_lint)]
+#[diag(privacy_private_in_public_lint)]
pub struct PrivateInPublicLint<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 48ab31ab9..865d6306b 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,7 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(associated_type_defaults)]
#![feature(control_flow_enum)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(rustc_private)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
@@ -24,7 +23,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
use rustc_middle::span_bug;
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode};
use rustc_middle::ty::query::Providers;
@@ -42,7 +41,7 @@ use std::{cmp, fmt, mem};
use errors::{
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
- InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
+ InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportEffectiveVisibility,
UnnamedItemIsPrivate,
};
@@ -123,8 +122,20 @@ where
&mut self,
projection: ty::ProjectionTy<'tcx>,
) -> ControlFlow<V::BreakTy> {
- let (trait_ref, assoc_substs) =
- projection.trait_ref_and_own_substs(self.def_id_visitor.tcx());
+ let tcx = self.def_id_visitor.tcx();
+ let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
+ != DefKind::ImplTraitPlaceholder
+ {
+ projection.trait_ref_and_own_substs(tcx)
+ } else {
+ // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+ let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
+ let trait_generics = tcx.generics_of(def_id);
+ (
+ ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
+ &projection.substs[trait_generics.count()..],
+ )
+ };
self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() {
ControlFlow::CONTINUE
@@ -148,34 +159,12 @@ where
ty.visit_with(self)
}
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
- ty::PredicateKind::ConstEvaluatable(uv)
- if self.def_id_visitor.tcx().features().generic_const_exprs =>
- {
- let tcx = self.def_id_visitor.tcx();
- if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
- self.visit_abstract_const_expr(tcx, ct)?;
- }
- ControlFlow::CONTINUE
- }
+ ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
_ => bug!("unexpected predicate: {:?}", predicate),
}
}
- fn visit_abstract_const_expr(
- &mut self,
- tcx: TyCtxt<'tcx>,
- ct: AbstractConst<'tcx>,
- ) -> ControlFlow<V::BreakTy> {
- walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
- ACNode::Leaf(leaf) => self.visit_const(leaf),
- ACNode::Cast(_, _, ty) => self.visit_ty(ty),
- ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
- ControlFlow::CONTINUE
- }
- })
- }
-
fn visit_predicates(
&mut self,
predicates: ty::GenericPredicates<'tcx>,
@@ -298,9 +287,16 @@ where
self.visit_ty(c.ty())?;
let tcx = self.def_id_visitor.tcx();
if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) {
- self.visit_abstract_const_expr(tcx, ct)?;
+ walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
+ ACNode::Leaf(leaf) => self.visit_const(leaf),
+ ACNode::Cast(_, _, ty) => self.visit_ty(ty),
+ ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
+ ControlFlow::CONTINUE
+ }
+ })
+ } else {
+ ControlFlow::CONTINUE
}
- ControlFlow::CONTINUE
}
}
@@ -314,7 +310,7 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
struct FindMin<'a, 'tcx, VL: VisibilityLike> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
min: VL,
}
@@ -348,8 +344,12 @@ trait VisibilityLike: Sized {
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
// associated types for which we can't determine visibility precisely.
- fn of_impl(def_id: LocalDefId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self {
- let mut find = FindMin { tcx, access_levels, min: Self::MAX };
+ fn of_impl(
+ def_id: LocalDefId,
+ tcx: TyCtxt<'_>,
+ effective_visibilities: &EffectiveVisibilities,
+ ) -> Self {
+ let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
find.visit(tcx.type_of(def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref);
@@ -363,8 +363,8 @@ impl VisibilityLike for ty::Visibility {
min(find.tcx.local_visibility(def_id), find.min, find.tcx)
}
}
-impl VisibilityLike for Option<AccessLevel> {
- const MAX: Self = Some(AccessLevel::Public);
+impl VisibilityLike for Option<Level> {
+ const MAX: Self = Some(Level::Direct);
// Type inference is very smart sometimes.
// It can make an impl reachable even some components of its type or trait are unreachable.
// E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
@@ -376,7 +376,7 @@ impl VisibilityLike for Option<AccessLevel> {
// (which require reaching the `DefId`s in them).
const SHALLOW: bool = true;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
- cmp::min(find.access_levels.map.get(&def_id).copied(), find.min)
+ cmp::min(find.effective_visibilities.public_at_level(def_id), find.min)
}
}
@@ -387,8 +387,8 @@ impl VisibilityLike for Option<AccessLevel> {
struct EmbargoVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
- /// Accessibility levels for reachable nodes.
- access_levels: AccessLevels,
+ /// Effective visibilities for reachable nodes.
+ effective_visibilities: EffectiveVisibilities,
/// A set of pairs corresponding to modules, where the first module is
/// reachable via a macro that's defined in the second module. This cannot
/// be represented as reachable because it can't handle the following case:
@@ -402,38 +402,38 @@ struct EmbargoVisitor<'tcx> {
/// n::p::f()
/// }
macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
- /// Previous accessibility level; `None` means unreachable.
- prev_level: Option<AccessLevel>,
+ /// Previous visibility level; `None` means unreachable.
+ prev_level: Option<Level>,
/// Has something changed in the level map?
changed: bool,
}
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
- access_level: Option<AccessLevel>,
+ level: Option<Level>,
item_def_id: LocalDefId,
ev: &'a mut EmbargoVisitor<'tcx>,
}
impl<'tcx> EmbargoVisitor<'tcx> {
- fn get(&self, def_id: LocalDefId) -> Option<AccessLevel> {
- self.access_levels.map.get(&def_id).copied()
+ fn get(&self, def_id: LocalDefId) -> Option<Level> {
+ self.effective_visibilities.public_at_level(def_id)
}
- fn update_with_hir_id(
- &mut self,
- hir_id: hir::HirId,
- level: Option<AccessLevel>,
- ) -> Option<AccessLevel> {
+ fn update_with_hir_id(&mut self, hir_id: hir::HirId, level: Option<Level>) -> Option<Level> {
let def_id = self.tcx.hir().local_def_id(hir_id);
self.update(def_id, level)
}
/// Updates node level and returns the updated level.
- fn update(&mut self, def_id: LocalDefId, level: Option<AccessLevel>) -> Option<AccessLevel> {
+ fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> {
let old_level = self.get(def_id);
- // Accessibility levels can only grow.
+ // Visibility levels can only grow.
if level > old_level {
- self.access_levels.map.insert(def_id, level.unwrap());
+ self.effective_visibilities.set_public_at_level(
+ def_id,
+ || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
+ level.unwrap(),
+ );
self.changed = true;
level
} else {
@@ -444,10 +444,10 @@ impl<'tcx> EmbargoVisitor<'tcx> {
fn reach(
&mut self,
def_id: LocalDefId,
- access_level: Option<AccessLevel>,
+ level: Option<Level>,
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
- access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
+ level: cmp::min(level, Some(Level::Reachable)),
item_def_id: def_id,
ev: self,
}
@@ -505,9 +505,9 @@ impl<'tcx> EmbargoVisitor<'tcx> {
fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) {
let module = self.tcx.hir().get_module(module_def_id).0;
for item_id in module.item_ids {
- let def_kind = self.tcx.def_kind(item_id.def_id);
- let vis = self.tcx.local_visibility(item_id.def_id);
- self.update_macro_reachable_def(item_id.def_id, def_kind, vis, defining_mod);
+ let def_kind = self.tcx.def_kind(item_id.owner_id);
+ let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
+ self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
}
if let Some(exports) = self.tcx.module_reexports(module_def_id) {
for export in exports {
@@ -530,7 +530,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
vis: ty::Visibility,
module: LocalDefId,
) {
- let level = Some(AccessLevel::Reachable);
+ let level = Some(Level::Reachable);
if vis.is_public() {
self.update(def_id, level);
}
@@ -627,11 +627,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
let item_level = match item.kind {
hir::ItemKind::Impl { .. } => {
- let impl_level =
- Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels);
- self.update(item.def_id, impl_level)
+ let impl_level = Option::<Level>::of_impl(
+ item.owner_id.def_id,
+ self.tcx,
+ &self.effective_visibilities,
+ );
+ self.update(item.owner_id.def_id, impl_level)
}
- _ => self.get(item.def_id),
+ _ => self.get(item.owner_id.def_id),
};
// Update levels of nested things.
@@ -650,15 +653,15 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
hir::ItemKind::Impl(ref impl_) => {
for impl_item_ref in impl_.items {
if impl_.of_trait.is_some()
- || self.tcx.visibility(impl_item_ref.id.def_id).is_public()
+ || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
{
- self.update(impl_item_ref.id.def_id, item_level);
+ self.update(impl_item_ref.id.owner_id.def_id, item_level);
}
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
for trait_item_ref in trait_item_refs {
- self.update(trait_item_ref.id.def_id, item_level);
+ self.update(trait_item_ref.id.owner_id.def_id, item_level);
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
@@ -674,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
- self.update_reachability_from_macro(item.def_id, macro_def);
+ self.update_reachability_from_macro(item.owner_id.def_id, macro_def);
}
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- if self.tcx.visibility(foreign_item.id.def_id).is_public() {
- self.update(foreign_item.id.def_id, item_level);
+ if self.tcx.visibility(foreign_item.id.owner_id).is_public() {
+ self.update(foreign_item.id.owner_id.def_id, item_level);
}
}
}
@@ -702,7 +705,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
// All nested items are checked by `visit_item`.
hir::ItemKind::Mod(..) => {}
- // Handled in the access level of in rustc_resolve
+ // Handled in `rustc_resolve`.
hir::ItemKind::Use(..) => {}
// The interface is empty.
hir::ItemKind::GlobalAsm(..) => {}
@@ -715,9 +718,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// FIXME: This is some serious pessimization intended to workaround deficiencies
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
// reachable if they are returned via `impl Trait`, even from private functions.
- let exist_level =
- cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
- self.reach(item.def_id, exist_level).generics().predicates().ty();
+ let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait));
+ self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty();
}
}
// Visit everything.
@@ -726,20 +728,20 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
| hir::ItemKind::Fn(..)
| hir::ItemKind::TyAlias(..) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates().ty();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates().ty();
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
for trait_item_ref in trait_item_refs {
let tcx = self.tcx;
- let mut reach = self.reach(trait_item_ref.id.def_id, item_level);
+ let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level);
reach.generics().predicates();
if trait_item_ref.kind == AssocItemKind::Type
- && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value()
+ && !tcx.impl_defaultness(trait_item_ref.id.owner_id).has_value()
{
// No type to visit.
} else {
@@ -750,18 +752,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
hir::ItemKind::TraitAlias(..) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
}
}
// Visit everything except for private impl items.
hir::ItemKind::Impl(ref impl_) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref();
+ self.reach(item.owner_id.def_id, item_level)
+ .generics()
+ .predicates()
+ .ty()
+ .trait_ref();
for impl_item_ref in impl_.items {
- let impl_item_level = self.get(impl_item_ref.id.def_id);
+ let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id);
if impl_item_level.is_some() {
- self.reach(impl_item_ref.id.def_id, impl_item_level)
+ self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level)
.generics()
.predicates()
.ty();
@@ -773,7 +779,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but enum variants have their own levels.
hir::ItemKind::Enum(ref def, _) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
}
for variant in def.variants {
let variant_level = self.get(self.tcx.hir().local_def_id(variant.id));
@@ -784,13 +790,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
// Corner case: if the variant is reachable, but its
// enum is not, make the enum reachable as well.
- self.reach(item.def_id, variant_level).ty();
+ self.reach(item.owner_id.def_id, variant_level).ty();
}
if let Some(hir_id) = variant.data.ctor_hir_id() {
let ctor_def_id = self.tcx.hir().local_def_id(hir_id);
let ctor_level = self.get(ctor_def_id);
if ctor_level.is_some() {
- self.reach(item.def_id, ctor_level).ty();
+ self.reach(item.owner_id.def_id, ctor_level).ty();
}
}
}
@@ -798,9 +804,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but foreign items have their own levels.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- let foreign_item_level = self.get(foreign_item.id.def_id);
+ let foreign_item_level = self.get(foreign_item.id.owner_id.def_id);
if foreign_item_level.is_some() {
- self.reach(foreign_item.id.def_id, foreign_item_level)
+ self.reach(foreign_item.id.owner_id.def_id, foreign_item_level)
.generics()
.predicates()
.ty();
@@ -810,7 +816,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything except for private fields.
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
for field in struct_def.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
let field_level = self.get(def_id);
@@ -823,7 +829,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
let ctor_def_id = self.tcx.hir().local_def_id(hir_id);
let ctor_level = self.get(ctor_def_id);
if ctor_level.is_some() {
- self.reach(item.def_id, ctor_level).ty();
+ self.reach(item.owner_id.def_id, ctor_level).ty();
}
}
}
@@ -894,10 +900,10 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() {
- if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) =
- (self.tcx().visibility(def_id.to_def_id()), self.access_level)
+ if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) =
+ (self.tcx().visibility(def_id.to_def_id()), self.level)
{
- self.ev.update(def_id, self.access_level);
+ self.ev.update(def_id, self.level);
}
}
ControlFlow::CONTINUE
@@ -905,42 +911,64 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
}
////////////////////////////////////////////////////////////////////////////////
-/// Visitor, used for AccessLevels table checking
+/// Visitor, used for EffectiveVisibilities table checking
////////////////////////////////////////////////////////////////////////////////
pub struct TestReachabilityVisitor<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
}
impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
- fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
- if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
- let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
+ fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
+ if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) {
+ let mut error_msg = String::new();
let span = self.tcx.def_span(def_id.to_def_id());
- self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
+ if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
+ for level in Level::all_levels() {
+ let vis_str = match effective_vis.at_level(level) {
+ ty::Visibility::Restricted(restricted_id) => {
+ if restricted_id.is_top_level_module() {
+ "pub(crate)".to_string()
+ } else if *restricted_id == self.tcx.parent_module_from_def_id(def_id) {
+ "pub(self)".to_string()
+ } else {
+ format!("pub({})", self.tcx.item_name(restricted_id.to_def_id()))
+ }
+ }
+ ty::Visibility::Public => "pub".to_string(),
+ };
+ if level != Level::Direct {
+ error_msg.push_str(", ");
+ }
+ error_msg.push_str(&format!("{:?}: {}", level, vis_str));
+ }
+ } else {
+ error_msg.push_str("not in the table");
+ }
+ self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg });
}
}
}
impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
match item.kind {
hir::ItemKind::Enum(ref def, _) => {
for variant in def.variants.iter() {
let variant_id = self.tcx.hir().local_def_id(variant.id);
- self.access_level_diagnostic(variant_id);
+ self.effective_visibility_diagnostic(variant_id);
for field in variant.data.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
- self.access_level_diagnostic(def_id);
+ self.effective_visibility_diagnostic(def_id);
}
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
for field in def.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
- self.access_level_diagnostic(def_id);
+ self.effective_visibility_diagnostic(def_id);
}
}
_ => {}
@@ -948,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
}
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
}
@@ -1025,7 +1053,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
// Don't visit nested modules, since we run a separate visitor walk
- // for each module in `privacy_access_levels`
+ // for each module in `effective_visibilities`
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -1037,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
+ let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
intravisit::walk_item(self, item);
self.current_item = orig_current_item;
}
@@ -1150,7 +1178,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
// Don't visit nested modules, since we run a separate visitor walk
- // for each module in `privacy_access_levels`
+ // for each module in `effective_visibilities`
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -1180,7 +1208,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
// Types in signatures.
// FIXME: This is very ineffective. Ideally each HIR type should be converted
// into a semantic type only once and the result should be cached somehow.
- if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
+ if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
return;
}
}
@@ -1209,7 +1237,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
if self.maybe_typeck_results.is_none() {
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
// The traits' privacy in bodies is already checked as a part of trait object types.
- let bounds = rustc_typeck::hir_trait_to_predicates(
+ let bounds = rustc_hir_analysis::hir_trait_to_predicates(
self.tcx,
trait_ref,
// NOTE: This isn't really right, but the actual type doesn't matter here. It's
@@ -1340,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
// Check types in item interfaces.
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
+ let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
let old_maybe_typeck_results = self.maybe_typeck_results.take();
intravisit::walk_item(self, item);
self.maybe_typeck_results = old_maybe_typeck_results;
@@ -1375,7 +1403,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
in_variant: bool,
// Set of errors produced by this obsolete visitor.
old_error_set: HirIdSet,
@@ -1395,7 +1423,9 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path: &hir::Path<'_>) -> bool {
let did = match path.res {
- Res::PrimTy(..) | Res::SelfTy { .. } | Res::Err => return false,
+ Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
+ return false;
+ }
res => res.def_id(),
};
@@ -1416,7 +1446,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn trait_is_public(&self, trait_id: LocalDefId) -> bool {
// FIXME: this would preferably be using `exported_items`, but all
// traits are exported currently (see `EmbargoVisitor.exported_trait`).
- self.access_levels.is_public(trait_id)
+ self.effective_visibilities.is_directly_public(trait_id)
}
fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) {
@@ -1428,7 +1458,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn item_is_public(&self, def_id: LocalDefId) -> bool {
- self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
+ self.effective_visibilities.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
}
}
@@ -1482,7 +1512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
hir::ItemKind::ForeignMod { .. } => {}
hir::ItemKind::Trait(.., bounds, _) => {
- if !self.trait_is_public(item.def_id) {
+ if !self.trait_is_public(item.owner_id.def_id) {
return;
}
@@ -1542,10 +1572,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|| impl_.items.iter().any(|impl_item_ref| {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item.kind {
- hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
- self.access_levels.is_reachable(impl_item_ref.id.def_id)
- }
- hir::ImplItemKind::TyAlias(_) => false,
+ hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => self
+ .effective_visibilities
+ .is_reachable(impl_item_ref.id.owner_id.def_id),
+ hir::ImplItemKind::Type(_) => false,
}
});
@@ -1563,11 +1593,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item.kind {
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
- if self.item_is_public(impl_item.def_id) =>
+ if self.item_is_public(impl_item.owner_id.def_id) =>
{
intravisit::walk_impl_item(self, impl_item)
}
- hir::ImplItemKind::TyAlias(..) => {
+ hir::ImplItemKind::Type(..) => {
intravisit::walk_impl_item(self, impl_item)
}
_ => {}
@@ -1593,7 +1623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
// Those in 3. are warned with this call.
for impl_item_ref in impl_.items {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
- if let hir::ImplItemKind::TyAlias(ty) = impl_item.kind {
+ if let hir::ImplItemKind::Type(ty) = impl_item.kind {
self.visit_ty(ty);
}
}
@@ -1604,8 +1634,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for impl_item_ref in impl_.items {
- if self.access_levels.is_reachable(impl_item_ref.id.def_id)
- || self.tcx.visibility(impl_item_ref.id.def_id).is_public()
+ if self
+ .effective_visibilities
+ .is_reachable(impl_item_ref.id.owner_id.def_id)
+ || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
{
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
@@ -1633,7 +1665,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
hir::ItemKind::TyAlias(..) => return,
// Not at all public, so we don't care.
- _ if !self.item_is_public(item.def_id) => {
+ _ if !self.item_is_public(item.owner_id.def_id) => {
return;
}
@@ -1664,7 +1696,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- if self.access_levels.is_reachable(item.def_id) {
+ if self.effective_visibilities.is_reachable(item.owner_id.def_id) {
intravisit::walk_foreign_item(self, item)
}
}
@@ -1679,7 +1711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) {
- if self.access_levels.is_reachable(self.tcx.hir().local_def_id(v.id)) {
+ if self.effective_visibilities.is_reachable(self.tcx.hir().local_def_id(v.id)) {
self.in_variant = true;
intravisit::walk_variant(self, v);
self.in_variant = false;
@@ -1901,43 +1933,44 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
pub fn check_item(&mut self, id: ItemId) {
let tcx = self.tcx;
- let item_visibility = tcx.local_visibility(id.def_id);
- let def_kind = tcx.def_kind(id.def_id);
+ let def_id = id.owner_id.def_id;
+ let item_visibility = tcx.local_visibility(def_id);
+ let def_kind = tcx.def_kind(def_id);
match def_kind {
DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => {
- self.check(id.def_id, item_visibility).generics().predicates().ty();
+ self.check(def_id, item_visibility).generics().predicates().ty();
}
DefKind::OpaqueTy => {
// `ty()` for opaque types is the underlying type,
// it's not a part of interface, so we skip it.
- self.check(id.def_id, item_visibility).generics().bounds();
+ self.check(def_id, item_visibility).generics().bounds();
}
DefKind::Trait => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind {
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
self.check_assoc_item(
- trait_item_ref.id.def_id,
+ trait_item_ref.id.owner_id.def_id,
trait_item_ref.kind,
item_visibility,
);
if let AssocItemKind::Type = trait_item_ref.kind {
- self.check(trait_item_ref.id.def_id, item_visibility).bounds();
+ self.check(trait_item_ref.id.owner_id.def_id, item_visibility).bounds();
}
}
}
}
DefKind::TraitAlias => {
- self.check(id.def_id, item_visibility).generics().predicates();
+ self.check(def_id, item_visibility).generics().predicates();
}
DefKind::Enum => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(ref def, _) = item.kind {
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for variant in def.variants {
for field in variant.data.fields() {
@@ -1952,8 +1985,11 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
let item = tcx.hir().item(id);
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
for foreign_item in items {
- let vis = tcx.local_visibility(foreign_item.id.def_id);
- self.check(foreign_item.id.def_id, vis).generics().predicates().ty();
+ let vis = tcx.local_visibility(foreign_item.id.owner_id.def_id);
+ self.check(foreign_item.id.owner_id.def_id, vis)
+ .generics()
+ .predicates()
+ .ty();
}
}
}
@@ -1963,7 +1999,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
if let hir::ItemKind::Struct(ref struct_def, _)
| hir::ItemKind::Union(ref struct_def, _) = item.kind
{
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for field in struct_def.fields() {
let def_id = tcx.hir().local_def_id(field.hir_id);
@@ -1979,20 +2015,25 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
DefKind::Impl => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
- let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default());
+ let impl_vis =
+ ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default());
// check that private components do not appear in the generics or predicates of inherent impls
// this check is intentionally NOT performed for impls of traits, per #90586
if impl_.of_trait.is_none() {
- self.check(item.def_id, impl_vis).generics().predicates();
+ self.check(item.owner_id.def_id, impl_vis).generics().predicates();
}
for impl_item_ref in impl_.items {
let impl_item_vis = if impl_.of_trait.is_none() {
- min(tcx.local_visibility(impl_item_ref.id.def_id), impl_vis, tcx)
+ min(
+ tcx.local_visibility(impl_item_ref.id.owner_id.def_id),
+ impl_vis,
+ tcx,
+ )
} else {
impl_vis
};
self.check_assoc_item(
- impl_item_ref.id.def_id,
+ impl_item_ref.id.owner_id.def_id,
impl_item_ref.kind,
impl_item_vis,
);
@@ -2007,7 +2048,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
pub fn provide(providers: &mut Providers) {
*providers = Providers {
visibility,
- privacy_access_levels,
+ effective_visibilities,
check_private_in_public,
check_mod_privacy,
..*providers
@@ -2040,7 +2081,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
// Visibilities of trait impl items are inherited from their traits
// and are not filled in resolve.
Node::ImplItem(impl_item) => {
- match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id)) {
+ match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id).def_id) {
Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(tr), .. }),
..
@@ -2079,14 +2120,14 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
intravisit::walk_mod(&mut visitor, module, hir_id);
}
-fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
+fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
// Build up a set of all exported items in the AST. This is a set of all
// items which are reachable from external crates based on visibility.
let mut visitor = EmbargoVisitor {
tcx,
- access_levels: tcx.resolutions(()).access_levels.clone(),
+ effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
macro_reachable: Default::default(),
- prev_level: Some(AccessLevel::Public),
+ prev_level: Some(Level::Direct),
changed: false,
};
@@ -2099,18 +2140,19 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
}
}
- let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
+ let mut check_visitor =
+ TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
- tcx.arena.alloc(visitor.access_levels)
+ tcx.arena.alloc(visitor.effective_visibilities)
}
fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
- let access_levels = tcx.privacy_access_levels(());
+ let effective_visibilities = tcx.effective_visibilities(());
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
- access_levels,
+ effective_visibilities,
in_variant: false,
old_error_set: Default::default(),
};
diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs
index 49175e97f..8be2e2be8 100644
--- a/compiler/rustc_query_impl/src/keys.rs
+++ b/compiler/rustc_query_impl/src/keys.rs
@@ -1,6 +1,7 @@
//! Defines the set of legal keys that can be used in queries.
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::hir_id::{HirId, OwnerId};
use rustc_middle::infer::canonical::Canonical;
use rustc_middle::mir;
use rustc_middle::traits;
@@ -26,6 +27,10 @@ pub trait Key {
fn key_as_def_id(&self) -> Option<DefId> {
None
}
+
+ fn ty_adt_id(&self) -> Option<DefId> {
+ None
+ }
}
impl Key for () {
@@ -104,6 +109,19 @@ impl Key for CrateNum {
}
}
+impl Key for OwnerId {
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ self.to_def_id().default_span(tcx)
+ }
+ fn key_as_def_id(&self) -> Option<DefId> {
+ Some(self.to_def_id())
+ }
+}
+
impl Key for LocalDefId {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
@@ -275,7 +293,7 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
}
}
-impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) {
+impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) {
#[inline(always)]
fn query_crate_is_local(&self) -> bool {
(self.0).def.did.krate == LOCAL_CRATE
@@ -393,6 +411,12 @@ impl<'tcx> Key for Ty<'tcx> {
fn default_span(&self, _: TyCtxt<'_>) -> Span {
DUMMY_SP
}
+ fn ty_adt_id(&self) -> Option<DefId> {
+ match self.kind() {
+ ty::Adt(adt, _) => Some(adt.did()),
+ _ => None,
+ }
+ }
}
impl<'tcx> Key for TyAndLayout<'tcx> {
@@ -543,3 +567,19 @@ impl<'tcx> Key for (Ty<'tcx>, ty::ValTree<'tcx>) {
DUMMY_SP
}
}
+
+impl Key for HirId {
+ #[inline(always)]
+ fn query_crate_is_local(&self) -> bool {
+ true
+ }
+
+ fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
+ tcx.hir().span(*self)
+ }
+
+ #[inline(always)]
+ fn key_as_def_id(&self) -> Option<DefId> {
+ None
+ }
+}
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index c87d26b39..11d4c97e7 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -1,6 +1,8 @@
//! Support for serializing the dep-graph and reloading it.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+// this shouldn't be necessary, but the check for `&mut _` is too naive and denies returning a function pointer that takes a mut ref
+#![feature(const_mut_refs)]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
@@ -20,8 +22,7 @@ use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::{self, DepKindStruct};
use rustc_middle::ty::query::{query_keys, query_storage, query_stored, query_values};
use rustc_middle::ty::query::{ExternProviders, Providers, QueryEngine};
-use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::def_id::{LocalDefId, LOCAL_CRATE};
+use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
#[macro_use]
@@ -43,14 +44,6 @@ pub use on_disk_cache::OnDiskCache;
mod profiling_support;
pub use self::profiling_support::alloc_self_profile_query_strings;
-fn describe_as_module(def_id: LocalDefId, tcx: TyCtxt<'_>) -> String {
- if def_id.is_top_level_module() {
- "top-level module".to_string()
- } else {
- format!("module `{}`", tcx.def_path_str(def_id.to_def_id()))
- }
-}
-
rustc_query_append! { define_queries! }
impl<'tcx> Queries<'tcx> {
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 0e93f3ce1..9000f81d9 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -1,8 +1,9 @@
use crate::QueryCtxt;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::Mmap;
use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock};
use rustc_data_structures::unhash::UnhashMap;
+use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE};
use rustc_hir::definitions::DefPathHash;
use rustc_index::vec::{Idx, IndexVec};
@@ -118,12 +119,11 @@ pub type EncodedDepNodeIndex = Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>;
struct SourceFileIndex(u32);
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Encodable, Decodable)]
-pub struct AbsoluteBytePos(u32);
+pub struct AbsoluteBytePos(u64);
impl AbsoluteBytePos {
fn new(pos: usize) -> AbsoluteBytePos {
- debug_assert!(pos <= u32::MAX as usize);
- AbsoluteBytePos(pos as u32)
+ AbsoluteBytePos(pos.try_into().expect("Incremental cache file size overflowed u64."))
}
fn to_usize(self) -> usize {
@@ -792,7 +792,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for DefId {
}
}
-impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx FxHashSet<LocalDefId> {
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for &'tcx UnordSet<LocalDefId> {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
RefDecodable::decode(d)
}
@@ -848,6 +848,7 @@ impl_ref_decoder! {<'tcx>
rustc_span::def_id::DefId,
rustc_span::def_id::LocalDefId,
(rustc_middle::middle::exported_symbols::ExportedSymbol<'tcx>, rustc_middle::middle::exported_symbols::SymbolExportInfo),
+ ty::DeducedParamAttrs,
}
//- ENCODING -------------------------------------------------------------------
@@ -1067,7 +1068,7 @@ pub fn encode_query_results<'a, 'tcx, CTX, Q>(
let _timer = tcx
.dep_context()
.profiler()
- .extra_verbose_generic_activity("encode_query_results_for", std::any::type_name::<Q>());
+ .verbose_generic_activity_with_arg("encode_query_results_for", std::any::type_name::<Q>());
assert!(Q::query_state(tcx).all_inactive());
let cache = Q::query_cache(tcx);
diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs
index 6f39bbfc0..1d17f4221 100644
--- a/compiler/rustc_query_impl/src/plumbing.rs
+++ b/compiler/rustc_query_impl/src/plumbing.rs
@@ -3,7 +3,8 @@
//! manage the caches, and so forth.
use crate::keys::Key;
-use crate::on_disk_cache::CacheDecoder;
+use crate::on_disk_cache::{CacheDecoder, CacheEncoder, EncodedDepNodeIndex};
+use crate::profiling_support::QueryKeyStringCache;
use crate::{on_disk_cache, Queries};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{AtomicU64, Lock};
@@ -19,8 +20,10 @@ use rustc_query_system::query::{
force_query, QueryConfig, QueryContext, QueryDescription, QueryJobId, QueryMap,
QuerySideEffects, QueryStackFrame,
};
-use rustc_query_system::Value;
+use rustc_query_system::{LayoutOfDepth, QueryOverflow, Value};
use rustc_serialize::Decodable;
+use rustc_session::Limit;
+use rustc_span::def_id::LOCAL_CRATE;
use std::any::Any;
use std::num::NonZeroU64;
use thin_vec::ThinVec;
@@ -109,7 +112,7 @@ impl QueryContext for QueryCtxt<'_> {
// when accessing the `ImplicitCtxt`.
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();
+ self.depth_limit_error(token);
}
// Update the `ImplicitCtxt` to point to our new query job.
@@ -127,6 +130,29 @@ impl QueryContext for QueryCtxt<'_> {
})
})
}
+
+ 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() {
+ if let Some((info, depth)) = job.try_find_layout_root(map) {
+ span = Some(info.job.span);
+ layout_of_depth = Some(LayoutOfDepth { desc: info.query.description, depth });
+ }
+ }
+
+ let suggested_limit = match self.recursion_limit() {
+ Limit(0) => Limit(2),
+ limit => limit * 2,
+ };
+
+ self.sess.emit_fatal(QueryOverflow {
+ span,
+ layout_of_depth,
+ suggested_limit,
+ crate_name: self.crate_name(LOCAL_CRATE),
+ });
+ }
}
impl<'tcx> QueryCtxt<'tcx> {
@@ -148,34 +174,14 @@ impl<'tcx> QueryCtxt<'tcx> {
pub(super) fn encode_query_results(
self,
- encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
- query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
+ encoder: &mut CacheEncoder<'_, 'tcx>,
+ query_result_index: &mut EncodedDepNodeIndex,
) {
- macro_rules! expand_if_cached {
- ([] $encode:expr) => {};
- ([(cache) $($rest:tt)*] $encode:expr) => {
- $encode
- };
- ([$other:tt $($modifiers:tt)*] $encode:expr) => {
- expand_if_cached!([$($modifiers)*] $encode)
- };
- }
-
- macro_rules! encode_queries {
- (
- $($(#[$attr:meta])*
- [$($modifiers:tt)*] fn $query:ident($($K:tt)*) -> $V:ty,)*) => {
- $(
- expand_if_cached!([$($modifiers)*] on_disk_cache::encode_query_results::<_, super::queries::$query<'_>>(
- self,
- encoder,
- query_result_index
- ));
- )*
+ for query in &self.queries.query_structs {
+ if let Some(encode) = query.encode_query_results {
+ encode(self, encoder, query_result_index);
}
}
-
- rustc_query_append!(encode_queries!);
}
pub fn try_print_query_stack(
@@ -188,6 +194,14 @@ impl<'tcx> QueryCtxt<'tcx> {
}
}
+#[derive(Clone, Copy)]
+pub(crate) struct QueryStruct<'tcx> {
+ pub try_collect_active_jobs: fn(QueryCtxt<'tcx>, &mut QueryMap) -> Option<()>,
+ pub alloc_self_profile_query_strings: fn(TyCtxt<'tcx>, &mut QueryKeyStringCache),
+ pub encode_query_results:
+ Option<fn(QueryCtxt<'tcx>, &mut CacheEncoder<'_, 'tcx>, &mut EncodedDepNodeIndex)>,
+}
+
macro_rules! handle_cycle_error {
([]) => {{
rustc_query_system::HandleCycleError::Error
@@ -284,7 +298,7 @@ pub(crate) fn create_query_frame<
K: Copy + Key + for<'a> HashStable<StableHashingContext<'a>>,
>(
tcx: QueryCtxt<'tcx>,
- do_describe: fn(QueryCtxt<'tcx>, K) -> String,
+ do_describe: fn(TyCtxt<'tcx>, K) -> String,
key: K,
kind: DepKind,
name: &'static str,
@@ -293,7 +307,7 @@ pub(crate) fn create_query_frame<
// 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, key))
+ ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key))
);
let description =
if tcx.sess.verbose() { format!("{} [{}]", description, name) } else { description };
@@ -304,13 +318,12 @@ pub(crate) fn create_query_frame<
} else {
Some(key.default_span(*tcx))
};
+ let def_id = key.key_as_def_id();
let def_kind = if kind == dep_graph::DepKind::opt_def_kind {
// Try to avoid infinite recursion.
None
} else {
- key.key_as_def_id()
- .and_then(|def_id| def_id.as_local())
- .and_then(|def_id| tcx.opt_def_kind(def_id))
+ def_id.and_then(|def_id| def_id.as_local()).and_then(|def_id| tcx.opt_def_kind(def_id))
};
let hash = || {
tcx.with_stable_hashing_context(|mut hcx| {
@@ -320,8 +333,9 @@ pub(crate) fn create_query_frame<
hasher.finish::<u64>()
})
};
+ let ty_adt_id = key.ty_adt_id();
- QueryStackFrame::new(name, description, span, def_kind, hash)
+ QueryStackFrame::new(name, description, span, def_id, def_kind, ty_adt_id, hash)
}
fn try_load_from_on_disk_cache<'tcx, Q>(tcx: TyCtxt<'tcx>, dep_node: DepNode)
@@ -355,6 +369,24 @@ where
Q::Key: DepNodeParams<TyCtxt<'tcx>>,
Q::Value: Value<TyCtxt<'tcx>>,
{
+ // We must avoid ever having to call `force_from_dep_node()` for a
+ // `DepNode::codegen_unit`:
+ // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we
+ // would always end up having to evaluate the first caller of the
+ // `codegen_unit` query that *is* reconstructible. This might very well be
+ // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just
+ // to re-trigger calling the `codegen_unit` query with the right key. At
+ // that point we would already have re-done all the work we are trying to
+ // avoid doing in the first place.
+ // The solution is simple: Just explicitly call the `codegen_unit` query for
+ // each CGU, right after partitioning. This way `try_mark_green` will always
+ // hit the cache instead of having to go through `force_from_dep_node`.
+ // This assertion makes sure, we actually keep applying the solution above.
+ debug_assert!(
+ dep_node.kind != DepKind::codegen_unit,
+ "calling force_from_dep_node() on DepKind::codegen_unit"
+ );
+
if let Some(key) = Q::Key::recover(tcx, &dep_node) {
#[cfg(debug_assertions)]
let _guard = tracing::span!(tracing::Level::TRACE, stringify!($name), ?key).entered();
@@ -395,6 +427,18 @@ where
}
}
+macro_rules! expand_if_cached {
+ ([], $tokens:expr) => {{
+ None
+ }};
+ ([(cache) $($rest:tt)*], $tokens:expr) => {{
+ Some($tokens)
+ }};
+ ([$other:tt $($modifiers:tt)*], $tokens:expr) => {
+ expand_if_cached!([$($modifiers)*], $tokens)
+ };
+}
+
// NOTE: `$V` isn't used here, but we still need to match on it so it can be passed to other macros
// invoked by `rustc_query_append`.
macro_rules! define_queries {
@@ -422,7 +466,10 @@ macro_rules! define_queries {
}
impl<'tcx> QueryDescription<QueryCtxt<'tcx>> for queries::$name<'tcx> {
- rustc_query_description! { $name }
+ #[inline]
+ fn cache_on_disk(tcx: TyCtxt<'tcx>, key: &Self::Key) -> bool {
+ ::rustc_middle::query::cached::$name(tcx, key)
+ }
type Cache = query_storage::$name<'tcx>;
@@ -528,6 +575,59 @@ macro_rules! define_queries {
})*
}
+ mod query_structs {
+ use rustc_middle::ty::TyCtxt;
+ use $crate::plumbing::{QueryStruct, QueryCtxt};
+ use $crate::profiling_support::QueryKeyStringCache;
+ use rustc_query_system::query::QueryMap;
+
+ pub(super) const fn dummy_query_struct<'tcx>() -> QueryStruct<'tcx> {
+ fn noop_try_collect_active_jobs(_: QueryCtxt<'_>, _: &mut QueryMap) -> Option<()> {
+ None
+ }
+ fn noop_alloc_self_profile_query_strings(_: TyCtxt<'_>, _: &mut QueryKeyStringCache) {}
+
+ QueryStruct {
+ try_collect_active_jobs: noop_try_collect_active_jobs,
+ alloc_self_profile_query_strings: noop_alloc_self_profile_query_strings,
+ encode_query_results: None,
+ }
+ }
+
+ pub(super) use dummy_query_struct as Null;
+ pub(super) use dummy_query_struct as Red;
+ pub(super) use dummy_query_struct as TraitSelect;
+ pub(super) use dummy_query_struct as CompileCodegenUnit;
+ pub(super) use dummy_query_struct as CompileMonoItem;
+
+ $(
+ pub(super) const fn $name<'tcx>() -> QueryStruct<'tcx> { QueryStruct {
+ try_collect_active_jobs: |tcx, qmap| {
+ let make_query = |tcx, key| {
+ let kind = rustc_middle::dep_graph::DepKind::$name;
+ let name = stringify!($name);
+ $crate::plumbing::create_query_frame(tcx, rustc_middle::query::descs::$name, key, kind, name)
+ };
+ tcx.queries.$name.try_collect_active_jobs(
+ tcx,
+ make_query,
+ qmap,
+ )
+ },
+ alloc_self_profile_query_strings: |tcx, string_cache| {
+ $crate::profiling_support::alloc_self_profile_query_strings_for_query_cache(
+ tcx,
+ stringify!($name),
+ &tcx.query_caches.$name,
+ string_cache,
+ )
+ },
+ encode_query_results: expand_if_cached!([$($modifiers)*], |tcx, encoder, query_result_index|
+ $crate::on_disk_cache::encode_query_results::<_, super::queries::$name<'_>>(tcx, encoder, query_result_index)
+ ),
+ }})*
+ }
+
pub fn query_callbacks<'tcx>(arena: &'tcx Arena<'tcx>) -> &'tcx [DepKindStruct<'tcx>] {
arena.alloc_from_iter(make_dep_kind_array!(query_callbacks))
}
@@ -542,9 +642,11 @@ impl<'tcx> Queries<'tcx> {
extern_providers: ExternProviders,
on_disk_cache: Option<OnDiskCache<'tcx>>,
) -> Self {
+ use crate::query_structs;
Queries {
local_providers: Box::new(local_providers),
extern_providers: Box::new(extern_providers),
+ query_structs: make_dep_kind_array!(query_structs).to_vec(),
on_disk_cache,
jobs: AtomicU64::new(1),
..Queries::default()
@@ -559,6 +661,7 @@ macro_rules! define_queries_struct {
pub struct Queries<'tcx> {
local_providers: Box<Providers>,
extern_providers: Box<ExternProviders>,
+ query_structs: Vec<$crate::plumbing::QueryStruct<'tcx>>,
pub on_disk_cache: Option<OnDiskCache<'tcx>>,
@@ -575,18 +678,9 @@ macro_rules! define_queries_struct {
let tcx = QueryCtxt { tcx, queries: self };
let mut jobs = QueryMap::default();
- $(
- let make_query = |tcx, key| {
- let kind = dep_graph::DepKind::$name;
- let name = stringify!($name);
- $crate::plumbing::create_query_frame(tcx, queries::$name::describe, key, kind, name)
- };
- self.$name.try_collect_active_jobs(
- tcx,
- make_query,
- &mut jobs,
- )?;
- )*
+ for query in &self.query_structs {
+ (query.try_collect_active_jobs)(tcx, &mut jobs);
+ }
Some(jobs)
}
diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs
index 98ec3bc09..2cc311d48 100644
--- a/compiler/rustc_query_impl/src/profiling_support.rs
+++ b/compiler/rustc_query_impl/src/profiling_support.rs
@@ -1,3 +1,4 @@
+use crate::QueryCtxt;
use measureme::{StringComponent, StringId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::SelfProfiler;
@@ -8,7 +9,7 @@ use rustc_query_system::query::QueryCache;
use std::fmt::Debug;
use std::io::Write;
-struct QueryKeyStringCache {
+pub(crate) struct QueryKeyStringCache {
def_id_cache: FxHashMap<DefId, StringId>,
}
@@ -226,7 +227,7 @@ where
/// Allocate the self-profiling query strings for a single query cache. This
/// method is called from `alloc_self_profile_query_strings` which knows all
/// the queries via macro magic.
-fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
+pub(crate) fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
tcx: TyCtxt<'tcx>,
query_name: &'static str,
query_cache: &C,
@@ -298,27 +299,15 @@ fn alloc_self_profile_query_strings_for_query_cache<'tcx, C>(
/// If we are recording only summary data, the ids will point to
/// just the query names. If we are recording query keys too, we
/// allocate the corresponding strings here.
-pub fn alloc_self_profile_query_strings(tcx: TyCtxt<'_>) {
+pub fn alloc_self_profile_query_strings<'tcx>(tcx: TyCtxt<'tcx>) {
if !tcx.prof.enabled() {
return;
}
let mut string_cache = QueryKeyStringCache::new();
+ let queries = QueryCtxt::from_tcx(tcx);
- macro_rules! alloc_once {
- (
- $($(#[$attr:meta])*
- [$($modifiers:tt)*] fn $name:ident($($K:tt)*) -> $V:ty,)*) => {
- $(
- alloc_self_profile_query_strings_for_query_cache(
- tcx,
- stringify!($name),
- &tcx.query_caches.$name,
- &mut string_cache,
- );
- )+
- }
+ for query in &queries.queries.query_structs {
+ (query.alloc_self_profile_query_strings)(tcx, &mut string_cache);
}
-
- rustc_query_append! { alloc_once! }
}
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index d7599a56c..faddad741 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
parking_lot = "0.11"
diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
index 162c274d8..5c6ce0556 100644
--- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs
+++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs
@@ -47,6 +47,7 @@ use crate::ich::StableHashingContext;
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_hir::definitions::DefPathHash;
use std::fmt;
use std::hash::Hash;
@@ -88,6 +89,17 @@ impl<K: DepKind> DepNode<K> {
dep_node
}
+
+ /// Construct a DepNode from the given DepKind and DefPathHash. This
+ /// method will assert that the given DepKind actually requires a
+ /// single DefId/DefPathHash parameter.
+ pub fn from_def_path_hash<Ctxt>(tcx: Ctxt, def_path_hash: DefPathHash, kind: K) -> Self
+ where
+ Ctxt: super::DepContext<DepKind = K>,
+ {
+ debug_assert!(tcx.fingerprint_style(kind) == FingerprintStyle::DefPathHash);
+ DepNode { kind, hash: def_path_hash.0.into() }
+ }
}
impl<K: DepKind> fmt::Debug for DepNode<K> {
@@ -149,6 +161,67 @@ where
}
}
+/// This struct stores metadata about each DepKind.
+///
+/// Information is retrieved by indexing the `DEP_KINDS` array using the integer value
+/// of the `DepKind`. Overall, this allows to implement `DepContext` using this manual
+/// jump table instead of large matches.
+pub struct DepKindStruct<CTX: DepContext> {
+ /// Anonymous queries cannot be replayed from one compiler invocation to the next.
+ /// When their result is needed, it is recomputed. They are useful for fine-grained
+ /// dependency tracking, and caching within one compiler invocation.
+ pub is_anon: bool,
+
+ /// Eval-always queries do not track their dependencies, and are always recomputed, even if
+ /// their inputs have not changed since the last compiler invocation. The result is still
+ /// cached within one compiler invocation.
+ pub is_eval_always: bool,
+
+ /// Whether the query key can be recovered from the hashed fingerprint.
+ /// See [DepNodeParams] trait for the behaviour of each key type.
+ pub fingerprint_style: FingerprintStyle,
+
+ /// The red/green evaluation system will try to mark a specific DepNode in the
+ /// dependency graph as green by recursively trying to mark the dependencies of
+ /// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode`
+ /// where we don't know if it is red or green and we therefore actually have
+ /// to recompute its value in order to find out. Since the only piece of
+ /// information that we have at that point is the `DepNode` we are trying to
+ /// re-evaluate, we need some way to re-run a query from just that. This is what
+ /// `force_from_dep_node()` implements.
+ ///
+ /// In the general case, a `DepNode` consists of a `DepKind` and an opaque
+ /// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint
+ /// is usually constructed by computing a stable hash of the query-key that the
+ /// `DepNode` corresponds to. Consequently, it is not in general possible to go
+ /// back from hash to query-key (since hash functions are not reversible). For
+ /// this reason `force_from_dep_node()` is expected to fail from time to time
+ /// because we just cannot find out, from the `DepNode` alone, what the
+ /// corresponding query-key is and therefore cannot re-run the query.
+ ///
+ /// The system deals with this case letting `try_mark_green` fail which forces
+ /// the root query to be re-evaluated.
+ ///
+ /// Now, if `force_from_dep_node()` would always fail, it would be pretty useless.
+ /// Fortunately, we can use some contextual information that will allow us to
+ /// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we
+ /// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a
+ /// valid `DefPathHash`. Since we also always build a huge table that maps every
+ /// `DefPathHash` in the current codebase to the corresponding `DefId`, we have
+ /// everything we need to re-run the query.
+ ///
+ /// Take the `mir_promoted` query as an example. Like many other queries, it
+ /// just has a single parameter: the `DefId` of the item it will compute the
+ /// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode`
+ /// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode`
+ /// is actually a `DefPathHash`, and can therefore just look up the corresponding
+ /// `DefId` in `tcx.def_path_hash_to_def_id`.
+ pub force_from_dep_node: Option<fn(tcx: CTX, dep_node: DepNode<CTX::DepKind>) -> bool>,
+
+ /// Invoke a query to put the on-disk cached value in memory.
+ pub try_load_from_on_disk_cache: Option<fn(CTX, DepNode<CTX::DepKind>)>,
+}
+
/// A "work product" corresponds to a `.o` (or other) file that we
/// save in between runs. These IDs do not have a `DefId` but rather
/// some independent path or string that persists between runs without
diff --git a/compiler/rustc_query_system/src/dep_graph/mod.rs b/compiler/rustc_query_system/src/dep_graph/mod.rs
index 342d95ca4..da2075fd5 100644
--- a/compiler/rustc_query_system/src/dep_graph/mod.rs
+++ b/compiler/rustc_query_system/src/dep_graph/mod.rs
@@ -4,7 +4,7 @@ mod graph;
mod query;
mod serialized;
-pub use dep_node::{DepNode, DepNodeParams, WorkProductId};
+pub use dep_node::{DepKindStruct, DepNode, DepNodeParams, WorkProductId};
pub use graph::{
hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, TaskDepsRef, WorkProduct,
};
@@ -34,16 +34,43 @@ pub trait DepContext: Copy {
/// Access the compiler session.
fn sess(&self) -> &Session;
- /// Return whether this kind always require evaluation.
- fn is_eval_always(&self, kind: Self::DepKind) -> bool;
+ fn dep_kind_info(&self, dep_node: Self::DepKind) -> &DepKindStruct<Self>;
- fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle;
+ #[inline(always)]
+ fn fingerprint_style(&self, kind: Self::DepKind) -> FingerprintStyle {
+ let data = self.dep_kind_info(kind);
+ if data.is_anon {
+ return FingerprintStyle::Opaque;
+ }
+ data.fingerprint_style
+ }
+
+ #[inline(always)]
+ /// Return whether this kind always require evaluation.
+ fn is_eval_always(&self, kind: Self::DepKind) -> bool {
+ self.dep_kind_info(kind).is_eval_always
+ }
/// Try to force a dep node to execute and see if it's green.
- fn try_force_from_dep_node(&self, dep_node: DepNode<Self::DepKind>) -> bool;
+ fn try_force_from_dep_node(self, dep_node: DepNode<Self::DepKind>) -> bool {
+ debug!("try_force_from_dep_node({:?}) --- trying to force", dep_node);
+
+ let cb = self.dep_kind_info(dep_node.kind);
+ if let Some(f) = cb.force_from_dep_node {
+ f(self, dep_node);
+ true
+ } else {
+ false
+ }
+ }
/// Load data from the on-disk cache.
- fn try_load_from_on_disk_cache(&self, dep_node: DepNode<Self::DepKind>);
+ fn try_load_from_on_disk_cache(self, dep_node: DepNode<Self::DepKind>) {
+ let cb = self.dep_kind_info(dep_node.kind);
+ if let Some(f) = cb.try_load_from_on_disk_cache {
+ f(self, dep_node)
+ }
+ }
}
pub trait HasDepContext: Copy {
@@ -67,6 +94,8 @@ impl<T: DepContext> HasDepContext for T {
pub enum FingerprintStyle {
/// The fingerprint is actually a DefPathHash.
DefPathHash,
+ /// The fingerprint is actually a HirId.
+ HirId,
/// Query key was `()` or equivalent, so fingerprint is just zero.
Unit,
/// Some opaque hash.
@@ -77,7 +106,9 @@ impl FingerprintStyle {
#[inline]
pub fn reconstructible(self) -> bool {
match self {
- FingerprintStyle::DefPathHash | FingerprintStyle::Unit => true,
+ FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => {
+ true
+ }
FingerprintStyle::Opaque => false,
}
}
diff --git a/compiler/rustc_query_system/src/error.rs b/compiler/rustc_query_system/src/error.rs
index 3fb06cbed..7a20eaceb 100644
--- a/compiler/rustc_query_system/src/error.rs
+++ b/compiler/rustc_query_system/src/error.rs
@@ -1,17 +1,15 @@
-use rustc_errors::AddSubdiagnostic;
-use rustc_span::Span;
+use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_session::Limit;
+use rustc_span::{Span, Symbol};
+#[derive(Subdiagnostic)]
+#[note(query_system_cycle_stack_middle)]
pub struct CycleStack {
+ #[primary_span]
pub span: Span,
pub desc: String,
}
-impl AddSubdiagnostic for CycleStack {
- fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
- diag.span_note(self.span, &format!("...which requires {}...", self.desc));
- }
-}
-
#[derive(Copy, Clone)]
pub enum HandleCycleError {
Error,
@@ -19,39 +17,39 @@ pub enum HandleCycleError {
DelayBug,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum StackCount {
- #[note(query_system::cycle_stack_single)]
+ #[note(query_system_cycle_stack_single)]
Single,
- #[note(query_system::cycle_stack_multiple)]
+ #[note(query_system_cycle_stack_multiple)]
Multiple,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum Alias {
- #[note(query_system::cycle_recursive_ty_alias)]
- #[help(query_system::cycle_recursive_ty_alias_help1)]
- #[help(query_system::cycle_recursive_ty_alias_help2)]
+ #[note(query_system_cycle_recursive_ty_alias)]
+ #[help(query_system_cycle_recursive_ty_alias_help1)]
+ #[help(query_system_cycle_recursive_ty_alias_help2)]
Ty,
- #[note(query_system::cycle_recursive_trait_alias)]
+ #[note(query_system_cycle_recursive_trait_alias)]
Trait,
}
-#[derive(SessionSubdiagnostic)]
-#[note(query_system::cycle_usage)]
+#[derive(Subdiagnostic)]
+#[note(query_system_cycle_usage)]
pub struct CycleUsage {
#[primary_span]
pub span: Span,
pub usage: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(query_system::cycle, code = "E0391")]
+#[derive(Diagnostic)]
+#[diag(query_system_cycle, code = "E0391")]
pub struct Cycle {
#[primary_span]
pub span: Span,
pub stack_bottom: String,
- #[subdiagnostic]
+ #[subdiagnostic(eager)]
pub cycle_stack: Vec<CycleStack>,
#[subdiagnostic]
pub stack_count: StackCount,
@@ -61,20 +59,35 @@ pub struct Cycle {
pub cycle_usage: Option<CycleUsage>,
}
-#[derive(SessionDiagnostic)]
-#[diag(query_system::reentrant)]
+#[derive(Diagnostic)]
+#[diag(query_system_reentrant)]
pub struct Reentrant;
-#[derive(SessionDiagnostic)]
-#[diag(query_system::increment_compilation)]
+#[derive(Diagnostic)]
+#[diag(query_system_increment_compilation)]
#[help]
-#[note(query_system::increment_compilation_note1)]
-#[note(query_system::increment_compilation_note2)]
+#[note(query_system_increment_compilation_note1)]
+#[note(query_system_increment_compilation_note2)]
pub struct IncrementCompilation {
pub run_cmd: String,
pub dep_node: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(query_system::query_overflow)]
-pub struct QueryOverflow;
+#[derive(Diagnostic)]
+#[help]
+#[diag(query_system_query_overflow)]
+pub struct QueryOverflow {
+ #[primary_span]
+ pub span: Option<Span>,
+ #[subdiagnostic]
+ pub layout_of_depth: Option<LayoutOfDepth>,
+ pub suggested_limit: Limit,
+ pub crate_name: Symbol,
+}
+
+#[derive(Subdiagnostic)]
+#[note(query_system_layout_of_depth)]
+pub struct LayoutOfDepth {
+ pub desc: String,
+ pub depth: usize,
+}
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index a09b8ca30..148eabb38 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -12,7 +12,7 @@ use rustc_session::cstore::CrateStore;
use rustc_session::Session;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Symbol;
-use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData};
+use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData, DUMMY_SP};
/// This is the context state available during incr. comp. hashing. It contains
/// enough information to transform `DefId`s and `HirId`s into stable `DefPath`s (i.e.,
@@ -41,7 +41,10 @@ pub struct StableHashingContext<'a> {
pub(super) enum BodyResolver<'tcx> {
Forbidden,
Ignore,
- Traverse { owner: LocalDefId, bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>> },
+ Traverse {
+ owner: hir::OwnerId,
+ bodies: &'tcx SortedMap<hir::ItemLocalId, &'tcx hir::Body<'tcx>>,
+ },
}
impl<'a> StableHashingContext<'a> {
@@ -103,7 +106,7 @@ impl<'a> StableHashingContext<'a> {
#[inline]
pub fn with_hir_bodies(
&mut self,
- owner: LocalDefId,
+ owner: hir::OwnerId,
bodies: &SortedMap<hir::ItemLocalId, &hir::Body<'_>>,
f: impl FnOnce(&mut StableHashingContext<'_>),
) {
@@ -182,7 +185,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
#[inline]
fn def_span(&self, def_id: LocalDefId) -> Span {
- self.source_span[def_id]
+ *self.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 f92c3831f..f47760e9a 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -1,11 +1,10 @@
#![feature(assert_matches)]
#![feature(core_intrinsics)]
#![feature(hash_raw_entry)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(extern_types)]
#![allow(rustc::potential_query_instability)]
-// #![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
@@ -23,4 +22,6 @@ pub mod query;
mod values;
pub use error::HandleCycleError;
+pub use error::LayoutOfDepth;
+pub use error::QueryOverflow;
pub use values::Value;
diff --git a/compiler/rustc_query_system/src/query/config.rs b/compiler/rustc_query_system/src/query/config.rs
index c4549cc9e..0a1cffa3b 100644
--- a/compiler/rustc_query_system/src/query/config.rs
+++ b/compiler/rustc_query_system/src/query/config.rs
@@ -49,8 +49,6 @@ impl<CTX: QueryContext, K, V> QueryVTable<CTX, K, V> {
pub trait QueryDescription<CTX: QueryContext>: QueryConfig {
type Cache: QueryCache<Key = Self::Key, Stored = Self::Stored, Value = Self::Value>;
- fn describe(tcx: CTX, key: Self::Key) -> String;
-
// Don't use this method to access query results, instead use the methods on TyCtxt
fn query_state<'a>(tcx: CTX) -> &'a QueryState<Self::Key>
where
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index 45b4079fb..ed65393f5 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -3,9 +3,11 @@ use crate::query::plumbing::CycleError;
use crate::query::{QueryContext, QueryStackFrame};
use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, Level};
+use rustc_errors::{
+ Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, Level,
+};
use rustc_hir::def::DefKind;
-use rustc_session::{Session, SessionDiagnostic};
+use rustc_session::Session;
use rustc_span::Span;
use std::hash::Hash;
@@ -59,6 +61,7 @@ impl QueryJobId {
}
}
+#[derive(Clone)]
pub struct QueryJobInfo {
pub query: QueryStackFrame,
pub job: QueryJob,
@@ -116,10 +119,10 @@ impl QueryJob {
}
}
-#[cfg(not(parallel_compiler))]
impl QueryJobId {
#[cold]
#[inline(never)]
+ #[cfg(not(parallel_compiler))]
pub(super) fn find_cycle_in_stack(
&self,
query_map: QueryMap,
@@ -156,6 +159,24 @@ impl QueryJobId {
panic!("did not find a cycle")
}
+
+ #[cold]
+ #[inline(never)]
+ pub fn try_find_layout_root(&self, query_map: QueryMap) -> Option<(QueryJobInfo, usize)> {
+ let mut last_layout = None;
+ let mut current_id = Some(*self);
+ let mut depth = 0;
+
+ while let Some(id) = current_id {
+ let info = query_map.get(&id).unwrap();
+ if info.query.name == "layout_of" {
+ depth += 1;
+ last_layout = Some((info.clone(), depth));
+ }
+ current_id = info.job.parent;
+ }
+ last_layout
+ }
}
#[cfg(parallel_compiler)]
@@ -530,7 +551,7 @@ pub fn deadlock(query_map: QueryMap, registry: &rayon_core::Registry) {
#[cold]
pub(crate) fn report_cycle<'a>(
sess: &'a Session,
- CycleError { usage, cycle: stack }: CycleError,
+ CycleError { usage, cycle: stack }: &CycleError,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
assert!(!stack.is_empty());
@@ -548,10 +569,10 @@ pub(crate) fn report_cycle<'a>(
}
let mut cycle_usage = None;
- if let Some((span, query)) = usage {
+ if let Some((span, ref query)) = *usage {
cycle_usage = Some(crate::error::CycleUsage {
span: query.default_span(span),
- usage: query.description,
+ usage: query.description.to_string(),
});
}
diff --git a/compiler/rustc_query_system/src/query/mod.rs b/compiler/rustc_query_system/src/query/mod.rs
index 0b07bb64b..118703fc0 100644
--- a/compiler/rustc_query_system/src/query/mod.rs
+++ b/compiler/rustc_query_system/src/query/mod.rs
@@ -14,10 +14,11 @@ pub use self::caches::{
mod config;
pub use self::config::{QueryConfig, QueryDescription, QueryVTable};
-use crate::dep_graph::{DepContext, DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
+use crate::dep_graph::{DepNodeIndex, HasDepContext, SerializedDepNodeIndex};
use rustc_data_structures::sync::Lock;
use rustc_errors::Diagnostic;
use rustc_hir::def::DefKind;
+use rustc_span::def_id::DefId;
use rustc_span::Span;
use thin_vec::ThinVec;
@@ -29,7 +30,9 @@ pub struct QueryStackFrame {
pub name: &'static str,
pub description: String,
span: Option<Span>,
- def_kind: Option<DefKind>,
+ pub def_id: Option<DefId>,
+ pub def_kind: Option<DefKind>,
+ pub ty_adt_id: Option<DefId>,
/// This hash is used to deterministically pick
/// a query to remove cycles in the parallel compiler.
#[cfg(parallel_compiler)]
@@ -42,14 +45,18 @@ impl QueryStackFrame {
name: &'static str,
description: String,
span: Option<Span>,
+ def_id: Option<DefId>,
def_kind: Option<DefKind>,
+ ty_adt_id: Option<DefId>,
_hash: impl FnOnce() -> u64,
) -> Self {
Self {
name,
description,
span,
+ def_id,
def_kind,
+ ty_adt_id,
#[cfg(parallel_compiler)]
hash: _hash(),
}
@@ -123,7 +130,5 @@ pub trait QueryContext: HasDepContext {
compute: impl FnOnce() -> R,
) -> R;
- fn depth_limit_error(&self) {
- self.dep_context().sess().emit_fatal(crate::error::QueryOverflow);
- }
+ 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 8179a674a..15b89daa6 100644
--- a/compiler/rustc_query_system/src/query/plumbing.rs
+++ b/compiler/rustc_query_system/src/query/plumbing.rs
@@ -119,7 +119,7 @@ where
#[inline(never)]
fn mk_cycle<CTX, V, R>(
tcx: CTX,
- error: CycleError,
+ cycle_error: CycleError,
handler: HandleCycleError,
cache: &dyn crate::query::QueryStorage<Value = V, Stored = R>,
) -> R
@@ -128,13 +128,14 @@ where
V: std::fmt::Debug + Value<CTX::DepContext>,
R: Clone,
{
- let error = report_cycle(tcx.dep_context().sess(), error);
- let value = handle_cycle_error(*tcx.dep_context(), error, handler);
+ let error = report_cycle(tcx.dep_context().sess(), &cycle_error);
+ let value = handle_cycle_error(*tcx.dep_context(), &cycle_error, error, handler);
cache.store_nocache(value)
}
fn handle_cycle_error<CTX, V>(
tcx: CTX,
+ cycle_error: &CycleError,
mut error: DiagnosticBuilder<'_, ErrorGuaranteed>,
handler: HandleCycleError,
) -> V
@@ -146,7 +147,7 @@ where
match handler {
Error => {
error.emit();
- Value::from_cycle_error(tcx)
+ Value::from_cycle_error(tcx, &cycle_error.cycle)
}
Fatal => {
error.emit();
@@ -155,7 +156,7 @@ where
}
DelayBug => {
error.delay_as_bug();
- Value::from_cycle_error(tcx)
+ Value::from_cycle_error(tcx, &cycle_error.cycle)
}
}
}
diff --git a/compiler/rustc_query_system/src/values.rs b/compiler/rustc_query_system/src/values.rs
index aeef66f86..67fbf14e6 100644
--- a/compiler/rustc_query_system/src/values.rs
+++ b/compiler/rustc_query_system/src/values.rs
@@ -1,11 +1,12 @@
use crate::dep_graph::DepContext;
+use crate::query::QueryInfo;
pub trait Value<CTX: DepContext>: Sized {
- fn from_cycle_error(tcx: CTX) -> Self;
+ fn from_cycle_error(tcx: CTX, cycle: &[QueryInfo]) -> Self;
}
impl<CTX: DepContext, T> Value<CTX> for T {
- default fn from_cycle_error(tcx: CTX) -> T {
+ default fn from_cycle_error(tcx: CTX, _: &[QueryInfo]) -> T {
tcx.sess().abort_if_errors();
// Ideally we would use `bug!` here. But bug! is only defined in rustc_middle, and it's
// non-trivial to define it earlier.
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index 5d2b606b4..d66db1d7a 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.2.1"
diff --git a/compiler/rustc_resolve/src/access_levels.rs b/compiler/rustc_resolve/src/access_levels.rs
deleted file mode 100644
index 0a3add2e0..000000000
--- a/compiler/rustc_resolve/src/access_levels.rs
+++ /dev/null
@@ -1,185 +0,0 @@
-use crate::imports::ImportKind;
-use crate::NameBinding;
-use crate::NameBindingKind;
-use crate::Resolver;
-use rustc_ast::ast;
-use rustc_ast::visit;
-use rustc_ast::visit::Visitor;
-use rustc_ast::Crate;
-use rustc_ast::EnumDef;
-use rustc_ast::NodeId;
-use rustc_hir::def_id::LocalDefId;
-use rustc_hir::def_id::CRATE_DEF_ID;
-use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::DefIdTree;
-use rustc_span::sym;
-
-pub struct AccessLevelsVisitor<'r, 'a> {
- r: &'r mut Resolver<'a>,
- changed: bool,
-}
-
-impl<'r, 'a> AccessLevelsVisitor<'r, 'a> {
- /// Fills the `Resolver::access_levels` 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_access_levels<'c>(r: &'r mut Resolver<'a>, krate: &'c Crate) {
- let mut visitor = AccessLevelsVisitor { r, changed: false };
-
- visitor.set_access_level_def_id(CRATE_DEF_ID, Some(AccessLevel::Public));
- visitor.set_bindings_access_level(CRATE_DEF_ID);
-
- while visitor.changed {
- visitor.reset();
- visit::walk_crate(&mut visitor, krate);
- }
-
- info!("resolve::access_levels: {:#?}", r.access_levels);
- }
-
- fn reset(&mut self) {
- self.changed = false;
- }
-
- /// Update the access level of the bindings in the given module accordingly. The module access
- /// level has to be Exported or Public.
- /// This will also follow `use` chains (see PrivacyVisitor::set_import_binding_access_level).
- fn set_bindings_access_level(&mut self, module_id: LocalDefId) {
- assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
- let module_level = self.r.access_levels.map.get(&module_id).copied();
- if !module_level.is_some() {
- return;
- }
- // Set the given binding access level to `AccessLevel::Public` and
- // sets the rest of the `use` chain to `AccessLevel::Exported` until
- // we hit the actual exported item.
- let set_import_binding_access_level =
- |this: &mut Self, mut binding: &NameBinding<'a>, mut access_level| {
- while let NameBindingKind::Import { binding: nested_binding, import, .. } =
- binding.kind
- {
- this.set_access_level(import.id, access_level);
- if let ImportKind::Single { additional_ids, .. } = import.kind {
- this.set_access_level(additional_ids.0, access_level);
- this.set_access_level(additional_ids.1, access_level);
- }
-
- access_level = Some(AccessLevel::Exported);
- binding = nested_binding;
- }
- };
-
- let module = self.r.get_module(module_id.to_def_id()).unwrap();
- let resolutions = self.r.resolutions(module);
-
- for (.., name_resolution) in resolutions.borrow().iter() {
- if let Some(binding) = name_resolution.borrow().binding() && binding.vis.is_public() && !binding.is_ambiguity() {
- let access_level = match binding.is_import() {
- true => {
- set_import_binding_access_level(self, binding, module_level);
- Some(AccessLevel::Exported)
- },
- false => module_level,
- };
- if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
- self.set_access_level_def_id(def_id, access_level);
- }
- }
- }
- }
-
- /// Sets the access level of the `LocalDefId` corresponding to the given `NodeId`.
- /// This function will panic if the `NodeId` does not have a `LocalDefId`
- fn set_access_level(
- &mut self,
- node_id: NodeId,
- access_level: Option<AccessLevel>,
- ) -> Option<AccessLevel> {
- self.set_access_level_def_id(self.r.local_def_id(node_id), access_level)
- }
-
- fn set_access_level_def_id(
- &mut self,
- def_id: LocalDefId,
- access_level: Option<AccessLevel>,
- ) -> Option<AccessLevel> {
- let old_level = self.r.access_levels.map.get(&def_id).copied();
- if old_level < access_level {
- self.r.access_levels.map.insert(def_id, access_level.unwrap());
- self.changed = true;
- access_level
- } else {
- old_level
- }
- }
-}
-
-impl<'r, 'ast> Visitor<'ast> for AccessLevelsVisitor<'ast, 'r> {
- fn visit_item(&mut self, item: &'ast ast::Item) {
- let def_id = self.r.local_def_id(item.id);
- // Set access level of nested items.
- // If it's a mod, also make the visitor walk all of its items
- match item.kind {
- // Resolved in rustc_privacy when types are available
- ast::ItemKind::Impl(..) => return,
-
- // Should be unreachable at this stage
- ast::ItemKind::MacCall(..) => panic!(
- "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
- ),
-
- // Foreign modules inherit level from parents.
- ast::ItemKind::ForeignMod(..) => {
- let parent_level =
- self.r.access_levels.map.get(&self.r.local_parent(def_id)).copied();
- self.set_access_level(item.id, parent_level);
- }
-
- // Only exported `macro_rules!` items are public, but they always are
- ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
- if item.attrs.iter().any(|attr| attr.has_name(sym::macro_export)) {
- self.set_access_level(item.id, Some(AccessLevel::Public));
- }
- }
-
- ast::ItemKind::Mod(..) => {
- self.set_bindings_access_level(def_id);
- visit::walk_item(self, item);
- }
-
- ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
- self.set_bindings_access_level(def_id);
- for variant in variants {
- let variant_def_id = self.r.local_def_id(variant.id);
- let variant_level = self.r.access_levels.map.get(&variant_def_id).copied();
- for field in variant.data.fields() {
- self.set_access_level(field.id, variant_level);
- }
- }
- }
-
- ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
- let inherited_level = self.r.access_levels.map.get(&def_id).copied();
- for field in def.fields() {
- if field.vis.kind.is_pub() {
- self.set_access_level(field.id, inherited_level);
- }
- }
- }
-
- ast::ItemKind::Trait(..) => {
- self.set_bindings_access_level(def_id);
- }
-
- ast::ItemKind::ExternCrate(..)
- | ast::ItemKind::Use(..)
- | ast::ItemKind::Static(..)
- | ast::ItemKind::Const(..)
- | ast::ItemKind::GlobalAsm(..)
- | ast::ItemKind::TyAlias(..)
- | ast::ItemKind::TraitAlias(..)
- | ast::ItemKind::MacroDef(..)
- | ast::ItemKind::Fn(..) => return,
- }
- }
-}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 81b67b758..a17793ecd 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -326,7 +326,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
PathResult::Module(..) => Err(VisResolutionError::ModuleOnly(path.span)),
PathResult::NonModule(partial_res) => {
- expected_found_error(partial_res.base_res())
+ expected_found_error(partial_res.expect_full_res())
}
PathResult::Failed { span, label, suggestion, .. } => {
Err(VisResolutionError::FailedToResolve(span, label, suggestion))
@@ -1010,7 +1010,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
_,
)
| Res::Local(..)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::SelfCtor(..)
| Res::Err => bug!("unexpected resolution: {:?}", res),
}
@@ -1424,7 +1425,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> {
}
(DefKind::AssocFn, ValueNS)
}
- AssocItemKind::TyAlias(..) => (DefKind::AssocTy, TypeNS),
+ AssocItemKind::Type(..) => (DefKind::AssocTy, TypeNS),
AssocItemKind::MacCall(_) => bug!(), // handled above
};
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 8b58b32b6..01c3801f2 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -6,7 +6,7 @@
// `use` items.
//
// Unused trait imports can't be checked until the method resolution. We save
-// candidates here, and do the actual check in librustc_typeck/check_unused.rs.
+// candidates here, and do the actual check in rustc_hir_analysis/check_unused.rs.
//
// Checking for unused imports is split into three steps:
//
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 3f88f44ff..d36e0f61d 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -1,6 +1,5 @@
use crate::{ImplTraitContext, Resolver};
use rustc_ast::visit::{self, FnKind};
-use rustc_ast::walk_list;
use rustc_ast::*;
use rustc_expand::expand::AstFragment;
use rustc_hir::def_id::LocalDefId;
@@ -148,8 +147,13 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
self.with_parent(return_impl_trait_id, |this| {
this.visit_fn_ret_ty(&sig.decl.output)
});
- let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
- self.with_parent(closure_def, |this| walk_list!(this, visit_block, body));
+ // If this async fn has no body (i.e. it's an async fn signature in a trait)
+ // then the closure_def will never be used, and we should avoid generating a
+ // def-id for it.
+ if let Some(body) = body {
+ let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span);
+ self.with_parent(closure_def, |this| this.visit_block(body));
+ }
return;
}
}
@@ -235,7 +239,7 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
let def_data = match &i.kind {
AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name),
- AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name),
+ AssocItemKind::Type(..) => DefPathData::TypeNs(i.ident.name),
AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id),
};
@@ -281,21 +285,6 @@ impl<'a, 'b> visit::Visitor<'a> for DefCollector<'a, 'b> {
fn visit_ty(&mut self, ty: &'a Ty) {
match ty.kind {
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
- TyKind::ImplTrait(node_id, _) => {
- let parent_def = match self.impl_trait_context {
- ImplTraitContext::Universal(item_def) => self.resolver.create_def(
- item_def,
- node_id,
- DefPathData::ImplTrait,
- self.expansion.to_expn_id(),
- ty.span,
- ),
- ImplTraitContext::Existential => {
- self.create_def(node_id, DefPathData::ImplTrait, ty.span)
- }
- };
- self.with_parent(parent_def, |this| visit::walk_ty(this, ty))
- }
_ => visit::walk_ty(self, ty),
}
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index ab71fa0bc..5d868ebec 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -24,7 +24,7 @@ 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};
+use rustc_span::{BytePos, Span, SyntaxContext};
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::late::{PatternSource, Rib};
@@ -47,6 +47,7 @@ pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
/// similarly named label and whether or not it is reachable.
pub(crate) type LabelSuggestion = (Ident, bool);
+#[derive(Debug)]
pub(crate) enum SuggestionTarget {
/// The target has a similar name as the name used by the programmer (probably a typo)
SimilarlyNamed,
@@ -54,6 +55,7 @@ pub(crate) enum SuggestionTarget {
SingleItem,
}
+#[derive(Debug)]
pub(crate) struct TypoSuggestion {
pub candidate: Symbol,
pub res: Res,
@@ -70,6 +72,7 @@ impl TypoSuggestion {
}
/// A free importable items suggested in case of resolution failure.
+#[derive(Debug, Clone)]
pub(crate) struct ImportSuggestion {
pub did: Option<DefId>,
pub descr: &'static str,
@@ -120,7 +123,7 @@ impl<'a> Resolver<'a> {
}
fn report_with_use_injections(&mut self, krate: &Crate) {
- for UseError { mut err, candidates, def_id, instead, suggestion, path } in
+ for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
self.use_injections.drain(..)
{
let (span, found_use) = if let Some(def_id) = def_id.as_local() {
@@ -128,6 +131,7 @@ impl<'a> Resolver<'a> {
} else {
(None, FoundUse::No)
};
+
if !candidates.is_empty() {
show_candidates(
&self.session,
@@ -137,13 +141,18 @@ impl<'a> Resolver<'a> {
&candidates,
if instead { Instead::Yes } else { Instead::No },
found_use,
- IsPattern::No,
+ DiagnosticMode::Normal,
path,
);
+ err.emit();
} else if let Some((span, msg, sugg, appl)) = suggestion {
err.span_suggestion(span, msg, sugg, appl);
+ err.emit();
+ } else if let [segment] = path.as_slice() && is_call {
+ err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
+ } else {
+ err.emit();
}
- err.emit();
}
}
@@ -475,11 +484,12 @@ impl<'a> Resolver<'a> {
module: Module<'a>,
names: &mut Vec<TypoSuggestion>,
filter_fn: &impl Fn(Res) -> bool,
+ ctxt: Option<SyntaxContext>,
) {
for (key, resolution) in self.resolutions(module).borrow().iter() {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res();
- if filter_fn(res) {
+ if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
names.push(TypoSuggestion::typo_from_res(key.ident.name, res));
}
}
@@ -511,24 +521,18 @@ impl<'a> Resolver<'a> {
let sm = self.session.source_map();
let def_id = match outer_res {
- Res::SelfTy { trait_: maybe_trait_defid, alias_to: maybe_impl_defid } => {
- if let Some(impl_span) =
- maybe_impl_defid.and_then(|(def_id, _)| self.opt_span(def_id))
- {
+ Res::SelfTyParam { .. } => {
+ err.span_label(span, "can't use `Self` here");
+ return err;
+ }
+ Res::SelfTyAlias { alias_to: def_id, .. } => {
+ if let Some(impl_span) = self.opt_span(def_id) {
err.span_label(
reduce_impl_span_to_impl_keyword(sm, impl_span),
"`Self` type implicitly declared here, by this `impl`",
);
}
- match (maybe_trait_defid, maybe_impl_defid) {
- (Some(_), None) => {
- err.span_label(span, "can't use `Self` here");
- }
- (_, Some(_)) => {
- err.span_label(span, "use a type here instead");
- }
- (None, None) => bug!("`impl` without trait nor type?"),
- }
+ err.span_label(span, "use a type here instead");
return err;
}
Res::Def(DefKind::TyParam, def_id) => {
@@ -545,8 +549,9 @@ impl<'a> Resolver<'a> {
}
_ => {
bug!(
- "GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
- DefKind::TyParam or DefKind::ConstParam"
+ "GenericParamsFromOuterFunction should only be used with \
+ Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
+ DefKind::ConstParam"
);
}
};
@@ -696,7 +701,7 @@ impl<'a> Resolver<'a> {
&import_suggestions,
Instead::No,
FoundUse::Yes,
- IsPattern::Yes,
+ DiagnosticMode::Pattern,
vec![],
);
}
@@ -1046,6 +1051,19 @@ impl<'a> Resolver<'a> {
err.span_label(trait_item_span, "item in trait");
err
}
+ ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
+ let mut err = struct_span_err!(
+ self.session,
+ span,
+ E0201,
+ "duplicate definitions with name `{}`:",
+ name,
+ );
+ err.span_label(old_span, "previous definition here");
+ err.span_label(trait_item_span, "item in trait");
+ err.span_label(span, "duplicate definition");
+ err
+ }
ResolutionError::InvalidAsmSym => {
let mut err = self.session.struct_span_err(span, "invalid `sym` operand");
err.span_label(span, "is a local variable");
@@ -1166,10 +1184,10 @@ impl<'a> Resolver<'a> {
Scope::CrateRoot => {
let root_ident = Ident::new(kw::PathRoot, ident.span);
let root_module = this.resolve_crate_root(root_ident);
- this.add_module_candidates(root_module, &mut suggestions, filter_fn);
+ this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
}
Scope::Module(module, _) => {
- this.add_module_candidates(module, &mut suggestions, filter_fn);
+ this.add_module_candidates(module, &mut suggestions, filter_fn, None);
}
Scope::MacroUsePrelude => {
suggestions.extend(this.macro_use_prelude.iter().filter_map(
@@ -1206,7 +1224,7 @@ impl<'a> Resolver<'a> {
Scope::StdLibPrelude => {
if let Some(prelude) = this.prelude {
let mut tmp_suggestions = Vec::new();
- this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn);
+ this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
suggestions.extend(
tmp_suggestions
.into_iter()
@@ -1479,7 +1497,7 @@ impl<'a> Resolver<'a> {
&import_suggestions,
Instead::No,
FoundUse::Yes,
- IsPattern::No,
+ DiagnosticMode::Normal,
vec![],
);
@@ -2440,12 +2458,34 @@ enum FoundUse {
No,
}
-/// Whether a binding is part of a pattern or an expression. Used for diagnostics.
-enum IsPattern {
+/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
+enum DiagnosticMode {
+ Normal,
/// The binding is part of a pattern
- Yes,
- /// The binding is part of an expression
- No,
+ Pattern,
+ /// The binding is part of a use statement
+ Import,
+}
+
+pub(crate) fn import_candidates(
+ session: &Session,
+ source_span: &IndexVec<LocalDefId, Span>,
+ err: &mut Diagnostic,
+ // This is `None` if all placement locations are inside expansions
+ use_placement_span: Option<Span>,
+ candidates: &[ImportSuggestion],
+) {
+ show_candidates(
+ session,
+ source_span,
+ err,
+ use_placement_span,
+ candidates,
+ Instead::Yes,
+ FoundUse::Yes,
+ DiagnosticMode::Import,
+ vec![],
+ );
}
/// When an entity with a given name is not available in scope, we search for
@@ -2460,7 +2500,7 @@ fn show_candidates(
candidates: &[ImportSuggestion],
instead: Instead,
found_use: FoundUse,
- is_pattern: IsPattern,
+ mode: DiagnosticMode,
path: Vec<Segment>,
) {
if candidates.is_empty() {
@@ -2495,7 +2535,7 @@ fn show_candidates(
};
let instead = if let Instead::Yes = instead { " instead" } else { "" };
- let mut msg = if let IsPattern::Yes = is_pattern {
+ let mut msg = if let DiagnosticMode::Pattern = mode {
format!(
"if you meant to match on {}{}{}, use the full path in the pattern",
kind, instead, name
@@ -2508,19 +2548,25 @@ fn show_candidates(
err.note(note);
}
- if let (IsPattern::Yes, Some(span)) = (is_pattern, use_placement_span) {
- err.span_suggestions(
- span,
- &msg,
- accessible_path_strings.into_iter().map(|a| a.0),
- Applicability::MaybeIncorrect,
- );
- } else if let Some(span) = use_placement_span {
+ if let Some(span) = use_placement_span {
+ let add_use = match mode {
+ DiagnosticMode::Pattern => {
+ err.span_suggestions(
+ span,
+ &msg,
+ accessible_path_strings.into_iter().map(|a| a.0),
+ Applicability::MaybeIncorrect,
+ );
+ return;
+ }
+ DiagnosticMode::Import => "",
+ DiagnosticMode::Normal => "use ",
+ };
for candidate in &mut accessible_path_strings {
// produce an additional newline to separate the new use statement
// from the directly following item.
let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" };
- candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline);
+ candidate.0 = format!("{}{};\n{}", add_use, &candidate.0, additional_newline);
}
err.span_suggestions(
@@ -2550,11 +2596,14 @@ fn show_candidates(
err.note(&msg);
}
- } else {
+ } else if !matches!(mode, DiagnosticMode::Import) {
assert!(!inaccessible_path_strings.is_empty());
- let prefix =
- if let IsPattern::Yes = is_pattern { "you might have meant to match on " } else { "" };
+ let prefix = if let DiagnosticMode::Pattern = mode {
+ "you might have meant to match on "
+ } else {
+ ""
+ };
if inaccessible_path_strings.len() == 1 {
let (name, descr, def_id, note) = &inaccessible_path_strings[0];
let msg = format!(
@@ -2562,7 +2611,7 @@ fn show_candidates(
prefix,
descr,
name,
- if let IsPattern::Yes = is_pattern { ", which" } else { "" }
+ if let DiagnosticMode::Pattern = mode { ", which" } else { "" }
);
if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
new file mode 100644
index 000000000..c40669ac9
--- /dev/null
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -0,0 +1,188 @@
+use crate::{ImportKind, NameBindingKind, Resolver};
+use rustc_ast::ast;
+use rustc_ast::visit;
+use rustc_ast::visit::Visitor;
+use rustc_ast::Crate;
+use rustc_ast::EnumDef;
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::def_id::CRATE_DEF_ID;
+use rustc_middle::middle::privacy::Level;
+use rustc_middle::ty::{DefIdTree, Visibility};
+
+pub struct EffectiveVisibilitiesVisitor<'r, 'a> {
+ r: &'r mut Resolver<'a>,
+ changed: bool,
+}
+
+impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
+ /// 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) {
+ let mut visitor = EffectiveVisibilitiesVisitor { r, changed: false };
+
+ visitor.update(CRATE_DEF_ID, Visibility::Public, CRATE_DEF_ID, Level::Direct);
+ visitor.set_bindings_effective_visibilities(CRATE_DEF_ID);
+
+ while visitor.changed {
+ visitor.reset();
+ visit::walk_crate(&mut visitor, krate);
+ }
+
+ info!("resolve::effective_visibilities: {:#?}", r.effective_visibilities);
+ }
+
+ fn reset(&mut self) {
+ self.changed = false;
+ }
+
+ /// Update effective visibilities of bindings in the given module,
+ /// including their whole reexport chains.
+ fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
+ assert!(self.r.module_map.contains_key(&&module_id.to_def_id()));
+ let module = self.r.get_module(module_id.to_def_id()).unwrap();
+ let resolutions = self.r.resolutions(module);
+
+ for (_, name_resolution) in resolutions.borrow().iter() {
+ if let Some(mut binding) = name_resolution.borrow().binding() && !binding.is_ambiguity() {
+ // Set the given effective visibility level to `Level::Direct` and
+ // sets the rest of the `use` chain to `Level::Reexported` until
+ // we hit the actual exported item.
+
+ // FIXME: tag and is_public() condition should be removed, but assertions occur.
+ let tag = if binding.is_import() { Level::Reexported } else { Level::Direct };
+ if binding.vis.is_public() {
+ let mut prev_parent_id = module_id;
+ let mut level = Level::Direct;
+ while let NameBindingKind::Import { binding: nested_binding, import, .. } =
+ binding.kind
+ {
+ let mut update = |node_id| self.update(
+ self.r.local_def_id(node_id),
+ binding.vis.expect_local(),
+ prev_parent_id,
+ level,
+ );
+ // In theory all the import IDs have individual visibilities and effective
+ // visibilities, but in practice these IDs go straigth to HIR where all
+ // their few uses assume that their (effective) visibility applies to the
+ // whole syntactic `use` item. So we update them all to the maximum value
+ // among the potential individual effective visibilities. Maybe HIR for
+ // imports shouldn't use three IDs at all.
+ update(import.id);
+ if let ImportKind::Single { additional_ids, .. } = import.kind {
+ update(additional_ids.0);
+ update(additional_ids.1);
+ }
+
+ level = Level::Reexported;
+ prev_parent_id = self.r.local_def_id(import.id);
+ binding = nested_binding;
+ }
+ }
+
+ if let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local()) {
+ self.update(def_id, binding.vis.expect_local(), module_id, tag);
+ }
+ }
+ }
+ }
+
+ fn update(
+ &mut self,
+ def_id: LocalDefId,
+ nominal_vis: Visibility,
+ parent_id: LocalDefId,
+ tag: Level,
+ ) {
+ let module_id = self
+ .r
+ .get_nearest_non_block_module(def_id.to_def_id())
+ .nearest_parent_mod()
+ .expect_local();
+ if nominal_vis == Visibility::Restricted(module_id)
+ || self.r.visibilities[&parent_id] == Visibility::Restricted(module_id)
+ {
+ return;
+ }
+ let mut effective_visibilities = std::mem::take(&mut self.r.effective_visibilities);
+ self.changed |= effective_visibilities.update(
+ def_id,
+ nominal_vis,
+ || Visibility::Restricted(module_id),
+ parent_id,
+ tag,
+ &*self.r,
+ );
+ self.r.effective_visibilities = effective_visibilities;
+ }
+}
+
+impl<'r, 'ast> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r> {
+ 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.
+ // If it's a mod, also make the visitor walk all of its items
+ match item.kind {
+ // Resolved in rustc_privacy when types are available
+ ast::ItemKind::Impl(..) => return,
+
+ // Should be unreachable at this stage
+ ast::ItemKind::MacCall(..) => panic!(
+ "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage"
+ ),
+
+ // Foreign modules inherit level from parents.
+ ast::ItemKind::ForeignMod(..) => {
+ let parent_id = self.r.local_parent(def_id);
+ self.update(def_id, Visibility::Public, parent_id, Level::Direct);
+ }
+
+ // Only exported `macro_rules!` items are public, but they always are
+ ast::ItemKind::MacroDef(ref macro_def) if macro_def.macro_rules => {
+ let parent_id = self.r.local_parent(def_id);
+ let vis = self.r.visibilities[&def_id];
+ self.update(def_id, vis, parent_id, Level::Direct);
+ }
+
+ ast::ItemKind::Mod(..) => {
+ self.set_bindings_effective_visibilities(def_id);
+ visit::walk_item(self, item);
+ }
+
+ ast::ItemKind::Enum(EnumDef { ref variants }, _) => {
+ self.set_bindings_effective_visibilities(def_id);
+ for variant in variants {
+ let variant_def_id = self.r.local_def_id(variant.id);
+ for field in variant.data.fields() {
+ let field_def_id = self.r.local_def_id(field.id);
+ let vis = self.r.visibilities[&field_def_id];
+ self.update(field_def_id, vis, variant_def_id, Level::Direct);
+ }
+ }
+ }
+
+ ast::ItemKind::Struct(ref def, _) | ast::ItemKind::Union(ref def, _) => {
+ for field in def.fields() {
+ let field_def_id = self.r.local_def_id(field.id);
+ let vis = self.r.visibilities[&field_def_id];
+ self.update(field_def_id, vis, def_id, Level::Direct);
+ }
+ }
+
+ ast::ItemKind::Trait(..) => {
+ self.set_bindings_effective_visibilities(def_id);
+ }
+
+ ast::ItemKind::ExternCrate(..)
+ | ast::ItemKind::Use(..)
+ | ast::ItemKind::Static(..)
+ | ast::ItemKind::Const(..)
+ | ast::ItemKind::GlobalAsm(..)
+ | ast::ItemKind::TyAlias(..)
+ | ast::ItemKind::TraitAlias(..)
+ | ast::ItemKind::MacroDef(..)
+ | ast::ItemKind::Fn(..) => return,
+ }
+ }
+}
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 2287aa1eb..e0542d547 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -1162,7 +1162,7 @@ impl<'a> Resolver<'a> {
return Res::Err;
}
}
- Res::Def(DefKind::TyParam, _) | Res::SelfTy { .. } => {
+ Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
for rib in ribs {
let has_generic_params: HasGenericParams = match rib.kind {
NormalRibKind
@@ -1182,11 +1182,21 @@ impl<'a> Resolver<'a> {
if !(trivial == ConstantHasGenerics::Yes
|| features.generic_const_exprs)
{
- // HACK(min_const_generics): If we encounter `Self` in an anonymous constant
- // we can't easily tell if it's generic at this stage, so we instead remember
- // this and then enforce the self type to be concrete later on.
- if let Res::SelfTy { trait_, alias_to: Some((def, _)) } = res {
- res = Res::SelfTy { trait_, alias_to: Some((def, true)) }
+ // HACK(min_const_generics): If we encounter `Self` in an anonymous
+ // constant we can't easily tell if it's generic at this stage, so
+ // we instead remember this and then enforce the self type to be
+ // concrete later on.
+ if let Res::SelfTyAlias {
+ alias_to: def,
+ forbid_generic: _,
+ is_trait_impl,
+ } = res
+ {
+ res = Res::SelfTyAlias {
+ alias_to: def,
+ forbid_generic: true,
+ is_trait_impl,
+ }
} else {
if let Some(span) = finalize {
self.report_error(
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index c133c272b..f2cc50c19 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -1,9 +1,9 @@
//! A bunch of methods and structures more or less related to resolving imports.
-use crate::diagnostics::Suggestion;
+use crate::diagnostics::{import_candidates, Suggestion};
use crate::Determinacy::{self, *};
-use crate::Namespace::{MacroNS, TypeNS};
-use crate::{module_to_string, names_to_string};
+use crate::Namespace::*;
+use crate::{module_to_string, names_to_string, ImportSuggestion};
use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment};
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
use crate::{NameBinding, NameBindingKind, PathResult};
@@ -252,7 +252,7 @@ impl<'a> Resolver<'a> {
self.set_binding_parent_module(binding, module);
self.update_resolution(module, key, |this, resolution| {
if let Some(old_binding) = resolution.binding {
- if res == Res::Err {
+ if res == Res::Err && old_binding.res() != Res::Err {
// Do not override real bindings with `Res::Err`s from error recovery.
return Ok(());
}
@@ -381,6 +381,7 @@ struct UnresolvedImportError {
label: Option<String>,
note: Option<String>,
suggestion: Option<Suggestion>,
+ candidate: Option<Vec<ImportSuggestion>>,
}
pub struct ImportResolver<'a, 'b> {
@@ -472,6 +473,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
label: None,
note: None,
suggestion: None,
+ candidate: None,
};
if path.contains("::") {
errors.push((path, err))
@@ -522,6 +524,16 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
diag.multipart_suggestion(&msg, suggestions, applicability);
}
+
+ if let Some(candidate) = &err.candidate {
+ import_candidates(
+ self.r.session,
+ &self.r.source_span,
+ &mut diag,
+ Some(err.span),
+ &candidate,
+ )
+ }
}
diag.emit();
@@ -639,6 +651,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
Some(finalize),
ignore_binding,
);
+
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
import.vis.set(orig_vis);
let module = match path_res {
@@ -681,12 +694,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
String::from("a similar path exists"),
Applicability::MaybeIncorrect,
)),
+ candidate: None,
},
None => UnresolvedImportError {
span,
label: Some(label),
note: None,
suggestion,
+ candidate: None,
},
};
return Some(err);
@@ -729,6 +744,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
label: Some(String::from("cannot glob-import a module into itself")),
note: None,
suggestion: None,
+ candidate: None,
});
}
}
@@ -894,11 +910,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
};
+ let parent_suggestion =
+ self.r.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);
+
Some(UnresolvedImportError {
span: import.span,
label: Some(label),
note,
suggestion,
+ candidate: if !parent_suggestion.is_empty() {
+ Some(parent_suggestion)
+ } else {
+ None
+ },
})
} else {
// `resolve_ident_in_module` reported a privacy error.
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d8d82e125..00eb768ad 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -19,7 +19,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::DiagnosticId;
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};
+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::ty::DefIdTree;
@@ -35,7 +35,6 @@ use std::collections::{hash_map::Entry, BTreeSet};
use std::mem::{replace, take};
mod diagnostics;
-pub(crate) mod lifetimes;
type Res = def::Res<NodeId>;
@@ -226,22 +225,14 @@ enum LifetimeUseSet {
#[derive(Copy, Clone, Debug)]
enum LifetimeRibKind {
- /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
- Item,
-
+ // -- Ribs introducing named lifetimes
+ //
/// This rib declares generic parameters.
+ /// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },
- /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
- /// generics. We are disallowing this until we can decide on how we want to handle non-'static
- /// lifetimes in const generics. See issue #74052 for discussion.
- ConstGeneric,
-
- /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
- /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
- /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
- AnonConst,
-
+ // -- Ribs introducing unnamed lifetimes
+ //
/// Create a new anonymous lifetime parameter and reference it.
///
/// If `report_in_path`, report an error when encountering lifetime elision in a path:
@@ -258,16 +249,31 @@ enum LifetimeRibKind {
/// ```
AnonymousCreateParameter { binder: NodeId, report_in_path: bool },
+ /// Replace all anonymous lifetimes by provided lifetime.
+ Elided(LifetimeRes),
+
+ // -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
+ //
/// Give a hard error when either `&` or `'_` is written. Used to
/// rule out things like `where T: Foo<'_>`. Does not imply an
/// error on default object bounds (e.g., `Box<dyn Foo>`).
AnonymousReportError,
- /// Replace all anonymous lifetimes by provided lifetime.
- Elided(LifetimeRes),
-
/// Signal we cannot find which should be the anonymous lifetime.
ElisionFailure,
+
+ /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
+ /// generics. We are disallowing this until we can decide on how we want to handle non-'static
+ /// lifetimes in const generics. See issue #74052 for discussion.
+ ConstGeneric,
+
+ /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
+ /// This function will emit an error if `generic_const_exprs` is not enabled, the body
+ /// identified by `body_id` is an anonymous constant and `lifetime_ref` is non-static.
+ AnonConst,
+
+ /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
+ Item,
}
#[derive(Copy, Clone, Debug)]
@@ -415,7 +421,8 @@ impl<'a> PathSource<'a> {
| DefKind::ForeignTy,
_,
) | Res::PrimTy(..)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
),
PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
PathSource::Trait(AliasPossibility::Maybe) => {
@@ -449,7 +456,8 @@ impl<'a> PathSource<'a> {
| DefKind::TyAlias
| DefKind::AssocTy,
_,
- ) | Res::SelfTy { .. }
+ ) | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
),
PathSource::TraitItem(ns) => match res {
Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
@@ -517,6 +525,9 @@ struct DiagnosticMetadata<'ast> {
/// Used to detect possible `if let` written without `let` and to provide structured suggestion.
in_if_condition: Option<&'ast Expr>,
+ /// Used to detect possible new binding written without `let` and to provide structured suggestion.
+ in_assignment: Option<&'ast Expr>,
+
/// If we are currently in a trait object definition. Used to point at the bounds when
/// encountering a struct or enum.
current_trait_object: Option<&'ast [ast::GenericBound]>,
@@ -641,8 +652,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Check whether we should interpret this as a bare trait object.
if qself.is_none()
&& let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
- && partial_res.unresolved_segments() == 0
- && let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = partial_res.base_res()
+ && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) = partial_res.full_res()
{
// This path is actually a bare trait object. In case of a bare `Fn`-trait
// object with anonymous lifetimes, we need this rib to correctly place the
@@ -749,35 +759,31 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
match foreign_item.kind {
ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_generic_param_rib(
- &generics.params,
- ItemRibKind(HasGenericParams::Yes(generics.span)),
- LifetimeRibKind::Generics {
- binder: foreign_item.id,
- kind: LifetimeBinderKind::Item,
- span: generics.span,
- },
- |this| visit::walk_foreign_item(this, foreign_item),
- )
- });
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes(generics.span)),
+ LifetimeRibKind::Generics {
+ binder: foreign_item.id,
+ kind: LifetimeBinderKind::Item,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ );
}
ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_generic_param_rib(
- &generics.params,
- ItemRibKind(HasGenericParams::Yes(generics.span)),
- LifetimeRibKind::Generics {
- binder: foreign_item.id,
- kind: LifetimeBinderKind::Function,
- span: generics.span,
- },
- |this| visit::walk_foreign_item(this, foreign_item),
- )
- });
+ self.with_generic_param_rib(
+ &generics.params,
+ ItemRibKind(HasGenericParams::Yes(generics.span)),
+ LifetimeRibKind::Generics {
+ binder: foreign_item.id,
+ kind: LifetimeBinderKind::Function,
+ span: generics.span,
+ },
+ |this| visit::walk_foreign_item(this, foreign_item),
+ );
}
ForeignItemKind::Static(..) => {
- self.with_item_rib(|this| {
+ self.with_static_rib(|this| {
visit::walk_foreign_item(this, foreign_item);
});
}
@@ -806,7 +812,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
sig.decl.has_self(),
sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
&sig.decl.output,
- )
+ );
+
+ this.record_lifetime_params_for_async(
+ fn_id,
+ sig.header.asyncness.opt_return_id(),
+ );
},
);
return;
@@ -848,41 +859,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
},
);
- // Construct the list of in-scope lifetime parameters for async lowering.
- // We include all lifetime parameters, either named or "Fresh".
- // The order of those parameters does not matter, as long as it is
- // deterministic.
- if let Some((async_node_id, _)) = async_node_id {
- let mut extra_lifetime_params = this
- .r
- .extra_lifetime_params_map
- .get(&fn_id)
- .cloned()
- .unwrap_or_default();
- for rib in this.lifetime_ribs.iter().rev() {
- extra_lifetime_params.extend(
- rib.bindings
- .iter()
- .map(|(&ident, &(node_id, res))| (ident, node_id, res)),
- );
- match rib.kind {
- LifetimeRibKind::Item => break,
- LifetimeRibKind::AnonymousCreateParameter {
- binder, ..
- } => {
- if let Some(earlier_fresh) =
- this.r.extra_lifetime_params_map.get(&binder)
- {
- extra_lifetime_params.extend(earlier_fresh);
- }
- }
- _ => {}
- }
- }
- this.r
- .extra_lifetime_params_map
- .insert(async_node_id, extra_lifetime_params);
- }
+ this.record_lifetime_params_for_async(fn_id, async_node_id);
if let Some(body) = body {
// Ignore errors in function bodies if this is rustdoc
@@ -1421,9 +1398,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
return self.resolve_anonymous_lifetime(lifetime, false);
}
- let mut indices = (0..self.lifetime_ribs.len()).rev();
- for i in &mut indices {
- let rib = &self.lifetime_ribs[i];
+ let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
+ while let Some(rib) = lifetime_rib_iter.next() {
let normalized_ident = ident.normalize_to_macros_2_0();
if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);
@@ -1453,9 +1429,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
} else {
LifetimeUseSet::Many
}),
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => None,
+ LifetimeRibKind::Generics { .. } => None,
+ LifetimeRibKind::ConstGeneric | LifetimeRibKind::AnonConst => {
+ span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
+ }
})
.unwrap_or(LifetimeUseSet::Many);
debug!(?use_ctxt, ?use_set);
@@ -1490,13 +1467,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
return;
}
- _ => {}
+ LifetimeRibKind::AnonymousCreateParameter { .. }
+ | LifetimeRibKind::Elided(_)
+ | LifetimeRibKind::Generics { .. }
+ | LifetimeRibKind::ElisionFailure
+ | LifetimeRibKind::AnonymousReportError => {}
}
}
let mut outer_res = None;
- for i in indices {
- let rib = &self.lifetime_ribs[i];
+ for rib in lifetime_rib_iter {
let normalized_ident = ident.normalize_to_macros_2_0();
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
outer_res = Some(outer);
@@ -1523,8 +1503,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
count: 1,
};
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
- for i in (0..self.lifetime_ribs.len()).rev() {
- let rib = &mut self.lifetime_ribs[i];
+ for rib in self.lifetime_ribs.iter().rev() {
debug!(?rib.kind);
match rib.kind {
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
@@ -1564,9 +1543,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
return;
}
LifetimeRibKind::Item => break,
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => {}
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+ LifetimeRibKind::AnonConst => {
+ // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
+ }
}
}
self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
@@ -1781,9 +1762,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
break;
}
- LifetimeRibKind::Generics { .. }
- | LifetimeRibKind::ConstGeneric
- | LifetimeRibKind::AnonConst => {}
+ LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstGeneric => {}
+ LifetimeRibKind::AnonConst => {
+ // There is always an `Elided(LifetimeRes::Static)` inside an `AnonConst`.
+ span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
+ }
}
}
@@ -1896,9 +1879,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
for (index, (pat, ty)) in inputs.enumerate() {
debug!(?pat, ?ty);
- if let Some(pat) = pat {
- self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
- }
+ self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+ if let Some(pat) = pat {
+ this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ }
+ });
// Record elision candidates only for this parameter.
debug_assert_matches!(self.lifetime_elision_candidates, None);
@@ -1992,11 +1977,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
match ty.kind {
TyKind::ImplicitSelf => true,
TyKind::Path(None, _) => {
- let path_res = self.r.partial_res_map[&ty.id].base_res();
- if let Res::SelfTy { .. } = path_res {
+ let path_res = self.r.partial_res_map[&ty.id].full_res();
+ if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
return true;
}
- Some(path_res) == self.impl_self
+ self.impl_self.is_some() && path_res == self.impl_self
}
_ => false,
}
@@ -2033,7 +2018,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
None
}
})
- .map(|res| res.base_res())
+ .and_then(|res| res.full_res())
.filter(|res| {
// Permit the types that unambiguously always
// result in the same type constructor being used
@@ -2114,7 +2099,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
|this| {
let item_def_id = this.r.local_def_id(item.id).to_def_id();
this.with_self_rib(
- Res::SelfTy { trait_: None, alias_to: Some((item_def_id, false)) },
+ Res::SelfTyAlias {
+ alias_to: item_def_id,
+ forbid_generic: false,
+ is_trait_impl: false,
+ },
|this| {
visit::walk_item(this, item);
},
@@ -2228,14 +2217,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|this| {
let local_def_id = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(
- Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
- |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
- this.resolve_trait_items(items);
- },
- );
+ this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
+ this.resolve_trait_items(items);
+ });
},
);
}
@@ -2252,13 +2238,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|this| {
let local_def_id = this.r.local_def_id(item.id).to_def_id();
- this.with_self_rib(
- Res::SelfTy { trait_: Some(local_def_id), alias_to: None },
- |this| {
- this.visit_generics(generics);
- walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
- },
- );
+ this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
+ this.visit_generics(generics);
+ walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
+ });
},
);
}
@@ -2270,7 +2253,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => {
- self.with_item_rib(|this| {
+ self.with_static_rib(|this| {
this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Static), |this| {
this.visit_ty(ty);
});
@@ -2465,11 +2448,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.label_ribs.pop();
}
- fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) {
+ fn with_static_rib(&mut self, f: impl FnOnce(&mut Self)) {
let kind = ItemRibKind(HasGenericParams::No);
- self.with_lifetime_rib(LifetimeRibKind::Item, |this| {
- this.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
- })
+ self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
}
// HACK(min_const_generics,const_evaluatable_unchecked): We
@@ -2562,7 +2543,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
AssocItemKind::Fn(box Fn { generics, .. }) => {
walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
}
- AssocItemKind::TyAlias(box TyAlias { generics, .. }) => self
+ AssocItemKind::Type(box TyAlias { generics, .. }) => self
.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
}),
@@ -2595,7 +2576,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Finalize::new(trait_ref.ref_id, trait_ref.path.span),
);
self.diagnostic_metadata.currently_processing_impl_trait = None;
- if let Some(def_id) = res.base_res().opt_def_id() {
+ if let Some(def_id) = res.expect_full_res().opt_def_id() {
new_id = Some(def_id);
new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
}
@@ -2640,7 +2621,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
|this| {
// Dummy self type for better errors if `Self` is used in the trait path.
- this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| {
+ this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
this.with_lifetime_rib(
LifetimeRibKind::AnonymousCreateParameter {
binder: item_id,
@@ -2664,9 +2645,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
let item_def_id = item_def_id.to_def_id();
- let res = Res::SelfTy {
- trait_: trait_id,
- alias_to: Some((item_def_id, false)),
+ let res = Res::SelfTyAlias {
+ alias_to: item_def_id,
+ forbid_generic: false,
+ is_trait_impl: trait_id.is_some()
};
this.with_self_rib(res, |this| {
if let Some(trait_ref) = opt_trait_reference.as_ref() {
@@ -2682,8 +2664,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_current_self_type(self_type, |this| {
this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
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);
+ this.resolve_impl_item(&**item, &mut seen_trait_items);
}
});
});
@@ -2697,7 +2680,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
);
}
- fn resolve_impl_item(&mut self, item: &'ast AssocItem) {
+ fn resolve_impl_item(
+ &mut self,
+ item: &'ast AssocItem,
+ seen_trait_items: &mut FxHashMap<DefId, Span>,
+ ) {
use crate::ResolutionError::*;
match &item.kind {
AssocItemKind::Const(_, ty, default) => {
@@ -2710,6 +2697,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
ValueNS,
item.span,
+ seen_trait_items,
|i, s, c| ConstNotMemberOfTrait(i, s, c),
);
@@ -2750,6 +2738,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
ValueNS,
item.span,
+ seen_trait_items,
|i, s, c| MethodNotMemberOfTrait(i, s, c),
);
@@ -2757,8 +2746,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
},
);
}
- AssocItemKind::TyAlias(box TyAlias { generics, .. }) => {
- debug!("resolve_implementation AssocItemKind::TyAlias");
+ AssocItemKind::Type(box TyAlias { generics, .. }) => {
+ debug!("resolve_implementation AssocItemKind::Type");
// We also need a new scope for the impl item type parameters.
self.with_generic_param_rib(
&generics.params,
@@ -2778,6 +2767,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&item.kind,
TypeNS,
item.span,
+ seen_trait_items,
|i, s, c| TypeNotMemberOfTrait(i, s, c),
);
@@ -2799,6 +2789,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
kind: &AssocItemKind,
ns: Namespace,
span: Span,
+ seen_trait_items: &mut FxHashMap<DefId, Span>,
err: F,
) where
F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>,
@@ -2831,9 +2822,27 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
let res = binding.res();
- let Res::Def(def_kind, _) = res else { bug!() };
+ let Res::Def(def_kind, id_in_trait) = res else { bug!() };
+
+ match seen_trait_items.entry(id_in_trait) {
+ Entry::Occupied(entry) => {
+ self.report_error(
+ span,
+ ResolutionError::TraitImplDuplicate {
+ name: ident.name,
+ old_span: *entry.get(),
+ trait_item_span: binding.span,
+ },
+ );
+ return;
+ }
+ Entry::Vacant(entry) => {
+ entry.insert(span);
+ }
+ };
+
match (def_kind, kind) {
- (DefKind::AssocTy, AssocItemKind::TyAlias(..))
+ (DefKind::AssocTy, AssocItemKind::Type(..))
| (DefKind::AssocFn, AssocItemKind::Fn(..))
| (DefKind::AssocConst, AssocItemKind::Const(..)) => {
self.r.record_partial_res(id, PartialRes::new(res));
@@ -2847,7 +2856,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
let (code, kind) = match kind {
AssocItemKind::Const(..) => (rustc_errors::error_code!(E0323), "const"),
AssocItemKind::Fn(..) => (rustc_errors::error_code!(E0324), "method"),
- AssocItemKind::TyAlias(..) => (rustc_errors::error_code!(E0325), "type"),
+ AssocItemKind::Type(..) => (rustc_errors::error_code!(E0325), "type"),
AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"),
};
let trait_path = path_names_to_string(path);
@@ -2865,10 +2874,13 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
fn resolve_params(&mut self, params: &'ast [Param]) {
let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
- for Param { pat, ty, .. } in params {
- self.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
+ for Param { pat, .. } in params {
+ this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
+ }
+ });
+ for Param { ty, .. } in params {
self.visit_ty(ty);
- debug!("(resolving function / closure) recorded parameter");
}
}
@@ -2923,7 +2935,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
}
fn is_base_res_local(&self, nid: NodeId) -> bool {
- matches!(self.r.partial_res_map.get(&nid).map(|res| res.base_res()), Some(Res::Local(..)))
+ matches!(
+ self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()),
+ Some(Res::Local(..))
+ )
}
/// Checks that all of the arms in an or-pattern have exactly the
@@ -3326,6 +3341,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
instead,
suggestion,
path: path.into(),
+ is_call: source.is_call(),
});
}
@@ -3390,6 +3406,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
instead: false,
suggestion: None,
path: path.into(),
+ is_call: source.is_call(),
});
} else {
err.cancel();
@@ -3408,12 +3425,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
source.defer_to_typeck(),
finalize,
) {
- Ok(Some(partial_res)) if partial_res.unresolved_segments() == 0 => {
- if source.is_expected(partial_res.base_res()) || partial_res.base_res() == Res::Err
- {
+ Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
+ if source.is_expected(res) || res == Res::Err {
partial_res
} else {
- report_errors(self, Some(partial_res.base_res()))
+ report_errors(self, Some(res))
}
}
@@ -3621,20 +3637,21 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
};
if path.len() > 1
- && result.base_res() != Res::Err
+ && let Some(res) = result.full_res()
+ && res != Res::Err
&& path[0].ident.name != kw::PathRoot
&& path[0].ident.name != kw::DollarCrate
{
let unqualified_result = {
match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
- PathResult::NonModule(path_res) => path_res.base_res(),
+ PathResult::NonModule(path_res) => path_res.expect_full_res(),
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
module.res().unwrap()
}
_ => return Ok(Some(result)),
}
};
- if result.base_res() == unqualified_result {
+ if res == unqualified_result {
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
self.r.lint_buffer.buffer_lint(
lint,
@@ -3828,9 +3845,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
ExprKind::Field(ref subexpression, _) => {
self.resolve_expr(subexpression, Some(expr));
}
- ExprKind::MethodCall(ref segment, ref arguments, _) => {
- let mut arguments = arguments.iter();
- self.resolve_expr(arguments.next().unwrap(), Some(expr));
+ ExprKind::MethodCall(ref segment, ref receiver, ref arguments, _) => {
+ self.resolve_expr(receiver, Some(expr));
for argument in arguments {
self.resolve_expr(argument, None);
}
@@ -3927,6 +3943,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.resolve_expr(elem, Some(expr));
self.visit_expr(idx);
}
+ ExprKind::Assign(..) => {
+ let old = self.diagnostic_metadata.in_assignment.replace(expr);
+ visit::walk_expr(self, expr);
+ self.diagnostic_metadata.in_assignment = old;
+ }
_ => {
visit::walk_expr(self, expr);
}
@@ -3962,6 +3983,41 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
Some((ident.name, ns)),
)
}
+
+ /// Construct the list of in-scope lifetime parameters for async lowering.
+ /// We include all lifetime parameters, either named or "Fresh".
+ /// The order of those parameters does not matter, as long as it is
+ /// deterministic.
+ fn record_lifetime_params_for_async(
+ &mut self,
+ fn_id: NodeId,
+ async_node_id: Option<(NodeId, Span)>,
+ ) {
+ if let Some((async_node_id, span)) = async_node_id {
+ let mut extra_lifetime_params =
+ self.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
+ for rib in self.lifetime_ribs.iter().rev() {
+ extra_lifetime_params.extend(
+ rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)),
+ );
+ match rib.kind {
+ LifetimeRibKind::Item => break,
+ LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
+ if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
+ extra_lifetime_params.extend(earlier_fresh);
+ }
+ }
+ LifetimeRibKind::Generics { .. } => {}
+ _ => {
+ // We are in a function definition. We should only find `Generics`
+ // and `AnonymousCreateParameter` inside the innermost `Item`.
+ span_bug!(span, "unexpected rib kind: {:?}", rib.kind)
+ }
+ }
+ }
+ self.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
+ }
+ }
}
struct LifetimeCountVisitor<'a, 'b> {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 3b095eeeb..850f023b1 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -38,8 +38,8 @@ type Res = def::Res<ast::NodeId>;
/// A field or associated item from self type suggested in case of resolution failure.
enum AssocSuggestion {
Field,
- MethodWithSelf,
- AssocFn,
+ MethodWithSelf { called: bool },
+ AssocFn { called: bool },
AssocType,
AssocConst,
}
@@ -48,8 +48,14 @@ impl AssocSuggestion {
fn action(&self) -> &'static str {
match self {
AssocSuggestion::Field => "use the available field",
- AssocSuggestion::MethodWithSelf => "call the method with the fully-qualified path",
- AssocSuggestion::AssocFn => "call the associated function",
+ AssocSuggestion::MethodWithSelf { called: true } => {
+ "call the method with the fully-qualified path"
+ }
+ AssocSuggestion::MethodWithSelf { called: false } => {
+ "refer to the method with the fully-qualified path"
+ }
+ AssocSuggestion::AssocFn { called: true } => "call the associated function",
+ AssocSuggestion::AssocFn { called: false } => "refer to the associated function",
AssocSuggestion::AssocConst => "use the associated `const`",
AssocSuggestion::AssocType => "use the associated type",
}
@@ -130,6 +136,33 @@ pub(super) enum LifetimeElisionCandidate {
Missing(MissingLifetime),
}
+/// Only used for diagnostics.
+#[derive(Debug)]
+struct BaseError {
+ msg: String,
+ fallback_label: String,
+ span: Span,
+ span_label: Option<(Span, &'static str)>,
+ could_be_expr: bool,
+ suggestion: Option<(Span, &'static str, String)>,
+}
+
+#[derive(Debug)]
+enum TypoCandidate {
+ Typo(TypoSuggestion),
+ Shadowed(Res),
+ None,
+}
+
+impl TypoCandidate {
+ fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
+ match self {
+ TypoCandidate::Typo(sugg) => Some(sugg),
+ TypoCandidate::Shadowed(_) | TypoCandidate::None => None,
+ }
+ }
+}
+
impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
fn def_span(&self, def_id: DefId) -> Option<Span> {
match def_id.krate {
@@ -138,35 +171,18 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
- /// Handles error reporting for `smart_resolve_path_fragment` function.
- /// Creates base error and amends it with one short label and possibly some longer helps/notes.
- pub(crate) fn smart_resolve_report_errors(
+ fn make_base_error(
&mut self,
path: &[Segment],
span: Span,
source: PathSource<'_>,
res: Option<Res>,
- ) -> (DiagnosticBuilder<'a, ErrorGuaranteed>, Vec<ImportSuggestion>) {
- let ident_span = path.last().map_or(span, |ident| ident.ident.span);
- let ns = source.namespace();
- let is_expected = &|res| source.is_expected(res);
- let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
-
- debug!(?res, ?source);
-
+ ) -> BaseError {
// Make the base error.
- struct BaseError<'a> {
- msg: String,
- fallback_label: String,
- span: Span,
- span_label: Option<(Span, &'a str)>,
- could_be_expr: bool,
- suggestion: Option<(Span, &'a str, String)>,
- }
let mut expected = source.descr_expected();
let path_str = Segment::names_to_string(path);
let item_str = path.last().unwrap().ident;
- let base_error = if let Some(res) = res {
+ if let Some(res) = res {
BaseError {
msg: format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
fallback_label: format!("not a {expected}"),
@@ -277,8 +293,20 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
could_be_expr: false,
suggestion,
}
- };
+ }
+ }
+ /// Handles error reporting for `smart_resolve_path_fragment` function.
+ /// Creates base error and amends it with one short label and possibly some longer helps/notes.
+ pub(crate) fn smart_resolve_report_errors(
+ &mut self,
+ path: &[Segment],
+ span: Span,
+ source: PathSource<'_>,
+ res: Option<Res>,
+ ) -> (DiagnosticBuilder<'a, 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);
@@ -289,41 +317,79 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_label(span, label);
}
- if let Some(sugg) = base_error.suggestion {
- err.span_suggestion_verbose(sugg.0, sugg.1, sugg.2, Applicability::MaybeIncorrect);
+ if let Some(ref sugg) = base_error.suggestion {
+ err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect);
}
- if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal {
- err.multipart_suggestion(
- "you might have meant to write a `struct` literal",
- vec![
- (span.shrink_to_lo(), "{ SomeStruct ".to_string()),
- (span.shrink_to_hi(), "}".to_string()),
- ],
- Applicability::HasPlaceholders,
- );
+ self.suggest_bare_struct_literal(&mut err);
+ self.suggest_pattern_match_with_let(&mut err, source, span);
+
+ self.suggest_self_or_self_ref(&mut err, path, span);
+ self.detect_assoct_type_constraint_meant_as_path(&mut err, &base_error);
+ if self.suggest_self_ty(&mut err, source, path, span)
+ || self.suggest_self_value(&mut err, source, path, span)
+ {
+ return (err, Vec::new());
}
- match (source, self.diagnostic_metadata.in_if_condition) {
- (
- PathSource::Expr(_),
- Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }),
- ) => {
- // Icky heuristic so we don't suggest:
- // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
- // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span)
- if lhs.is_approximately_pattern() && lhs.span.contains(span) {
- err.span_suggestion_verbose(
- expr_span.shrink_to_lo(),
- "you might have meant to use pattern matching",
- "let ",
- Applicability::MaybeIncorrect,
- );
+
+ let (found, candidates) =
+ self.try_lookup_name_relaxed(&mut err, source, path, span, res, &base_error);
+ if found {
+ return (err, candidates);
+ }
+
+ if !self.type_ascription_suggestion(&mut err, base_error.span) {
+ let mut fallback =
+ self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
+ fallback |= self.suggest_typo(&mut err, source, path, span, &base_error);
+ if fallback {
+ // Fallback label.
+ err.span_label(base_error.span, &base_error.fallback_label);
+ }
+ }
+ self.err_code_special_cases(&mut err, source, path, span);
+
+ (err, candidates)
+ }
+
+ fn detect_assoct_type_constraint_meant_as_path(
+ &self,
+ err: &mut Diagnostic,
+ base_error: &BaseError,
+ ) {
+ let Some(ty) = self.diagnostic_metadata.current_type_path else { return; };
+ let TyKind::Path(_, path) = &ty.kind else { return; };
+ for segment in &path.segments {
+ let Some(params) = &segment.args else { continue; };
+ let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; };
+ for param in &params.args {
+ let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; };
+ let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else {
+ continue;
+ };
+ for bound in bounds {
+ let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)
+ = bound else
+ {
+ continue;
+ };
+ if base_error.span == trait_ref.span {
+ err.span_suggestion_verbose(
+ constraint.ident.span.between(trait_ref.span),
+ "you might have meant to write a path instead of an associated type bound",
+ "::",
+ Applicability::MachineApplicable,
+ );
+ }
}
}
- _ => {}
}
+ }
+ fn suggest_self_or_self_ref(&mut self, err: &mut Diagnostic, path: &[Segment], span: Span) {
let is_assoc_fn = self.self_type_is_available();
+ let Some(path_last_segment) = path.last() else { return };
+ let item_str = path_last_segment.ident;
// Emit help message for fake-self from other languages (e.g., `this` in Javascript).
if ["this", "my"].contains(&item_str.as_str()) && is_assoc_fn {
err.span_suggestion_short(
@@ -358,96 +424,25 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
}
+ }
- self.detect_assoct_type_constraint_meant_as_path(base_error.span, &mut err);
-
- // Emit special messages for unresolved `Self` and `self`.
- if is_self_type(path, ns) {
- err.code(rustc_errors::error_code!(E0411));
- err.span_label(
- span,
- "`Self` is only available in impls, traits, and type definitions".to_string(),
- );
- if let Some(item_kind) = self.diagnostic_metadata.current_item {
- err.span_label(
- item_kind.ident.span,
- format!(
- "`Self` not allowed in {} {}",
- item_kind.kind.article(),
- item_kind.kind.descr()
- ),
- );
- }
- return (err, Vec::new());
- }
- if is_self_value(path, ns) {
- debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
-
- err.code(rustc_errors::error_code!(E0424));
- err.span_label(span, match source {
- PathSource::Pat => "`self` value is a keyword and may not be bound to variables or shadowed",
- _ => "`self` value is a keyword only available in methods with a `self` parameter",
- });
- if let Some((fn_kind, span)) = &self.diagnostic_metadata.current_function {
- // 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()) {
- err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
- } else {
- let doesnt = if is_assoc_fn {
- let (span, sugg) = fn_kind
- .decl()
- .inputs
- .get(0)
- .map(|p| (p.span.shrink_to_lo(), "&self, "))
- .unwrap_or_else(|| {
- // Try to look for the "(" after the function name, if possible.
- // This avoids placing the suggestion into the visibility specifier.
- let span = fn_kind
- .ident()
- .map_or(*span, |ident| span.with_lo(ident.span.hi()));
- (
- self.r
- .session
- .source_map()
- .span_through_char(span, '(')
- .shrink_to_hi(),
- "&self",
- )
- });
- err.span_suggestion_verbose(
- span,
- "add a `self` receiver parameter to make the associated `fn` a method",
- sugg,
- Applicability::MaybeIncorrect,
- );
- "doesn't"
- } else {
- "can't"
- };
- if let Some(ident) = fn_kind.ident() {
- err.span_label(
- ident.span,
- &format!("this function {} have a `self` parameter", doesnt),
- );
- }
- }
- } else if let Some(item_kind) = self.diagnostic_metadata.current_item {
- err.span_label(
- item_kind.ident.span,
- format!(
- "`self` not allowed in {} {}",
- item_kind.kind.article(),
- item_kind.kind.descr()
- ),
- );
- }
- return (err, Vec::new());
- }
-
+ fn try_lookup_name_relaxed(
+ &mut self,
+ err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ source: PathSource<'_>,
+ path: &[Segment],
+ span: Span,
+ res: Option<Res>,
+ base_error: &BaseError,
+ ) -> (bool, Vec<ImportSuggestion>) {
// Try to lookup name in more relaxed fashion for better error reporting.
let ident = path.last().unwrap().ident;
+ let is_expected = &|res| source.is_expected(res);
+ let ns = source.namespace();
+ let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
+ let path_str = Segment::names_to_string(path);
+ let ident_span = path.last().map_or(span, |ident| ident.ident.span);
+
let mut candidates = self
.r
.lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
@@ -494,7 +489,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
{
// Already reported this issue on the lhs of the type ascription.
err.delay_as_bug();
- return (err, candidates);
+ return (true, candidates);
}
}
@@ -522,10 +517,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
}
}
+
// Try Levenshtein algorithm.
- let typo_sugg = self.lookup_typo_candidate(path, ns, is_expected);
+ let typo_sugg =
+ self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
if path.len() == 1 && self.self_type_is_available() {
- if let Some(candidate) = self.lookup_assoc_candidate(ident, ns, is_expected) {
+ if let Some(candidate) =
+ self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
+ {
let self_is_available = self.self_value_is_available(path[0].ident.span);
match candidate {
AssocSuggestion::Field => {
@@ -540,16 +539,21 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
err.span_label(span, "a field by this name exists in `Self`");
}
}
- AssocSuggestion::MethodWithSelf if self_is_available => {
+ AssocSuggestion::MethodWithSelf { called } if self_is_available => {
+ let msg = if called {
+ "you might have meant to call the method"
+ } else {
+ "you might have meant to refer to the method"
+ };
err.span_suggestion(
span,
- "you might have meant to call the method",
+ msg,
format!("self.{path_str}"),
Applicability::MachineApplicable,
);
}
- AssocSuggestion::MethodWithSelf
- | AssocSuggestion::AssocFn
+ AssocSuggestion::MethodWithSelf { .. }
+ | AssocSuggestion::AssocFn { .. }
| AssocSuggestion::AssocConst
| AssocSuggestion::AssocType => {
err.span_suggestion(
@@ -560,8 +564,8 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
);
}
}
- self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
- return (err, candidates);
+ self.r.add_typo_suggestion(err, typo_sugg, ident_span);
+ return (true, candidates);
}
// If the first argument in call is `self` suggest calling a method.
@@ -579,14 +583,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
format!("self.{path_str}({args_snippet})"),
Applicability::MachineApplicable,
);
- return (err, candidates);
+ return (true, candidates);
}
}
// Try context-dependent help if relaxed lookup didn't work.
if let Some(res) = res {
if self.smart_resolve_context_dependent_help(
- &mut err,
+ err,
span,
source,
res,
@@ -594,106 +598,148 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
&base_error.fallback_label,
) {
// We do this to avoid losing a secondary span when we override the main error span.
- self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span);
- return (err, candidates);
+ self.r.add_typo_suggestion(err, typo_sugg, ident_span);
+ return (true, candidates);
}
}
+ return (false, candidates);
+ }
+ fn suggest_trait_and_bounds(
+ &mut self,
+ err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ source: PathSource<'_>,
+ res: Option<Res>,
+ span: Span,
+ base_error: &BaseError,
+ ) -> bool {
let is_macro =
base_error.span.from_expansion() && base_error.span.desugaring_kind().is_none();
- if !self.type_ascription_suggestion(&mut err, base_error.span) {
- let mut fallback = false;
- if let (
- PathSource::Trait(AliasPossibility::Maybe),
- Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)),
- false,
- ) = (source, res, is_macro)
- {
- if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object {
- fallback = true;
- let spans: Vec<Span> = bounds
- .iter()
- .map(|bound| bound.span())
- .filter(|&sp| sp != base_error.span)
- .collect();
+ let mut fallback = false;
- let start_span = bounds[0].span();
- // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
- let end_span = bounds.last().unwrap().span();
- // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
- let last_bound_span = spans.last().cloned().unwrap();
- let mut multi_span: MultiSpan = spans.clone().into();
- for sp in spans {
- let msg = if sp == last_bound_span {
- format!(
- "...because of {these} bound{s}",
- these = pluralize!("this", bounds.len() - 1),
- s = pluralize!(bounds.len() - 1),
- )
- } else {
- String::new()
- };
- multi_span.push_span_label(sp, msg);
- }
- multi_span
- .push_span_label(base_error.span, "expected this type to be a trait...");
- err.span_help(
- multi_span,
- "`+` is used to constrain a \"trait object\" type with lifetimes or \
- auto-traits; structs and enums can't be bound in that way",
- );
- if bounds.iter().all(|bound| match bound {
- ast::GenericBound::Outlives(_) => true,
- ast::GenericBound::Trait(tr, _) => tr.span == base_error.span,
- }) {
- let mut sugg = vec![];
- if base_error.span != start_span {
- sugg.push((start_span.until(base_error.span), String::new()));
- }
- if base_error.span != end_span {
- sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new()));
- }
+ if let (
+ PathSource::Trait(AliasPossibility::Maybe),
+ Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)),
+ false,
+ ) = (source, res, is_macro)
+ {
+ if let Some(bounds @ [_, .., _]) = self.diagnostic_metadata.current_trait_object {
+ fallback = true;
+ let spans: Vec<Span> = bounds
+ .iter()
+ .map(|bound| bound.span())
+ .filter(|&sp| sp != base_error.span)
+ .collect();
- err.multipart_suggestion(
- "if you meant to use a type and not a trait here, remove the bounds",
- sugg,
- Applicability::MaybeIncorrect,
- );
+ let start_span = bounds[0].span();
+ // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
+ let end_span = bounds.last().unwrap().span();
+ // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
+ let last_bound_span = spans.last().cloned().unwrap();
+ let mut multi_span: MultiSpan = spans.clone().into();
+ for sp in spans {
+ let msg = if sp == last_bound_span {
+ format!(
+ "...because of {these} bound{s}",
+ these = pluralize!("this", bounds.len() - 1),
+ s = pluralize!(bounds.len() - 1),
+ )
+ } else {
+ String::new()
+ };
+ multi_span.push_span_label(sp, msg);
+ }
+ multi_span.push_span_label(base_error.span, "expected this type to be a trait...");
+ err.span_help(
+ multi_span,
+ "`+` is used to constrain a \"trait object\" type with lifetimes or \
+ auto-traits; structs and enums can't be bound in that way",
+ );
+ if bounds.iter().all(|bound| match bound {
+ ast::GenericBound::Outlives(_) => true,
+ ast::GenericBound::Trait(tr, _) => tr.span == base_error.span,
+ }) {
+ let mut sugg = vec![];
+ if base_error.span != start_span {
+ sugg.push((start_span.until(base_error.span), String::new()));
+ }
+ if base_error.span != end_span {
+ sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new()));
}
+
+ err.multipart_suggestion(
+ "if you meant to use a type and not a trait here, remove the bounds",
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
}
}
+ }
- fallback |= self.restrict_assoc_type_in_where_clause(span, &mut err);
+ fallback |= self.restrict_assoc_type_in_where_clause(span, err);
+ fallback
+ }
- if !self.r.add_typo_suggestion(&mut err, typo_sugg, ident_span) {
- fallback = true;
- match self.diagnostic_metadata.current_let_binding {
- Some((pat_sp, Some(ty_sp), None))
- if ty_sp.contains(base_error.span) && base_error.could_be_expr =>
- {
- err.span_suggestion_short(
- pat_sp.between(ty_sp),
- "use `=` if you meant to assign",
- " = ",
- Applicability::MaybeIncorrect,
- );
- }
- _ => {}
+ fn suggest_typo(
+ &mut self,
+ err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ source: PathSource<'_>,
+ path: &[Segment],
+ span: Span,
+ base_error: &BaseError,
+ ) -> bool {
+ let is_expected = &|res| source.is_expected(res);
+ let ident_span = path.last().map_or(span, |ident| ident.ident.span);
+ let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
+ if let TypoCandidate::Shadowed(res) = typo_sugg
+ && let Some(id) = res.opt_def_id()
+ && let Some(sugg_span) = self.r.opt_span(id)
+ {
+ err.span_label(
+ sugg_span,
+ format!("you might have meant to refer to this {}", res.descr()),
+ );
+ return true;
+ }
+ let mut fallback = false;
+ let typo_sugg = typo_sugg.to_opt_suggestion();
+ if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
+ fallback = true;
+ match self.diagnostic_metadata.current_let_binding {
+ Some((pat_sp, Some(ty_sp), None))
+ if ty_sp.contains(base_error.span) && base_error.could_be_expr =>
+ {
+ err.span_suggestion_short(
+ pat_sp.between(ty_sp),
+ "use `=` if you meant to assign",
+ " = ",
+ Applicability::MaybeIncorrect,
+ );
}
-
- // If the trait has a single item (which wasn't matched by Levenshtein), suggest it
- let suggestion = self.get_single_associated_item(&path, &source, is_expected);
- self.r.add_typo_suggestion(&mut err, suggestion, ident_span);
+ _ => {}
}
- if fallback {
- // Fallback label.
- err.span_label(base_error.span, base_error.fallback_label);
+
+ // If the trait has a single item (which wasn't matched by Levenshtein), 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);
}
}
+ fallback
+ }
+
+ fn err_code_special_cases(
+ &mut self,
+ err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ source: PathSource<'_>,
+ path: &[Segment],
+ span: Span,
+ ) {
if let Some(err_code) = &err.code {
if err_code == &rustc_errors::error_code!(E0425) {
for label_rib in &self.label_ribs {
for (label_ident, node_id) in &label_rib.bindings {
+ let ident = path.last().unwrap().ident;
if format!("'{}", ident) == label_ident.to_string() {
err.span_label(label_ident.span, "a label with a similar name exists");
if let PathSource::Expr(Some(Expr {
@@ -724,38 +770,116 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
}
+ }
- (err, candidates)
+ /// Emit special messages for unresolved `Self` and `self`.
+ fn suggest_self_ty(
+ &mut self,
+ err: &mut Diagnostic,
+ source: PathSource<'_>,
+ path: &[Segment],
+ span: Span,
+ ) -> bool {
+ if !is_self_type(path, source.namespace()) {
+ return false;
+ }
+ err.code(rustc_errors::error_code!(E0411));
+ err.span_label(
+ span,
+ "`Self` is only available in impls, traits, and type definitions".to_string(),
+ );
+ if let Some(item_kind) = self.diagnostic_metadata.current_item {
+ err.span_label(
+ item_kind.ident.span,
+ format!(
+ "`Self` not allowed in {} {}",
+ item_kind.kind.article(),
+ item_kind.kind.descr()
+ ),
+ );
+ }
+ true
}
- fn detect_assoct_type_constraint_meant_as_path(&self, base_span: Span, err: &mut Diagnostic) {
- let Some(ty) = self.diagnostic_metadata.current_type_path else { return; };
- let TyKind::Path(_, path) = &ty.kind else { return; };
- for segment in &path.segments {
- let Some(params) = &segment.args else { continue; };
- let ast::GenericArgs::AngleBracketed(ref params) = params.deref() else { continue; };
- for param in &params.args {
- let ast::AngleBracketedArg::Constraint(constraint) = param else { continue; };
- let ast::AssocConstraintKind::Bound { bounds } = &constraint.kind else {
- continue;
+ fn suggest_self_value(
+ &mut self,
+ err: &mut Diagnostic,
+ source: PathSource<'_>,
+ path: &[Segment],
+ span: Span,
+ ) -> bool {
+ if !is_self_value(path, source.namespace()) {
+ return false;
+ }
+
+ debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
+ err.code(rustc_errors::error_code!(E0424));
+ err.span_label(
+ span,
+ match source {
+ PathSource::Pat => {
+ "`self` value is a keyword and may not be bound to variables or shadowed"
+ }
+ _ => "`self` value is a keyword only available in methods with a `self` parameter",
+ },
+ );
+ 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
+ // 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()) {
+ err.span_label(*span, "this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters");
+ } else {
+ let doesnt = if is_assoc_fn {
+ let (span, sugg) = fn_kind
+ .decl()
+ .inputs
+ .get(0)
+ .map(|p| (p.span.shrink_to_lo(), "&self, "))
+ .unwrap_or_else(|| {
+ // Try to look for the "(" after the function name, if possible.
+ // This avoids placing the suggestion into the visibility specifier.
+ let span = fn_kind
+ .ident()
+ .map_or(*span, |ident| span.with_lo(ident.span.hi()));
+ (
+ self.r
+ .session
+ .source_map()
+ .span_through_char(span, '(')
+ .shrink_to_hi(),
+ "&self",
+ )
+ });
+ err.span_suggestion_verbose(
+ span,
+ "add a `self` receiver parameter to make the associated `fn` a method",
+ sugg,
+ Applicability::MaybeIncorrect,
+ );
+ "doesn't"
+ } else {
+ "can't"
};
- for bound in bounds {
- let ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)
- = bound else
- {
- continue;
- };
- if base_span == trait_ref.span {
- err.span_suggestion_verbose(
- constraint.ident.span.between(trait_ref.span),
- "you might have meant to write a path instead of an associated type bound",
- "::",
- Applicability::MachineApplicable,
- );
- }
+ if let Some(ident) = fn_kind.ident() {
+ err.span_label(
+ ident.span,
+ &format!("this function {} have a `self` parameter", doesnt),
+ );
}
}
+ } else if let Some(item_kind) = self.diagnostic_metadata.current_item {
+ err.span_label(
+ item_kind.ident.span,
+ format!(
+ "`self` not allowed in {} {}",
+ item_kind.kind.article(),
+ item_kind.kind.descr()
+ ),
+ );
}
+ true
}
fn suggest_swapping_misplaced_self_ty_and_trait(
@@ -787,6 +911,45 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
+ fn suggest_bare_struct_literal(&mut self, err: &mut Diagnostic) {
+ if let Some(span) = self.diagnostic_metadata.current_block_could_be_bare_struct_literal {
+ err.multipart_suggestion(
+ "you might have meant to write a `struct` literal",
+ vec![
+ (span.shrink_to_lo(), "{ SomeStruct ".to_string()),
+ (span.shrink_to_hi(), "}".to_string()),
+ ],
+ Applicability::HasPlaceholders,
+ );
+ }
+ }
+
+ fn suggest_pattern_match_with_let(
+ &mut self,
+ err: &mut Diagnostic,
+ source: PathSource<'_>,
+ span: Span,
+ ) {
+ if let PathSource::Expr(_) = source &&
+ let Some(Expr {
+ span: expr_span,
+ kind: ExprKind::Assign(lhs, _, _),
+ ..
+ }) = self.diagnostic_metadata.in_if_condition {
+ // Icky heuristic so we don't suggest:
+ // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
+ // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span)
+ if lhs.is_approximately_pattern() && lhs.span.contains(span) {
+ err.span_suggestion_verbose(
+ expr_span.shrink_to_lo(),
+ "you might have meant to use pattern matching",
+ "let ",
+ Applicability::MaybeIncorrect,
+ );
+ }
+ }
+ }
+
fn get_single_associated_item(
&mut self,
path: &[Segment],
@@ -849,11 +1012,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
return false;
};
- if !(matches!(
- partial_res.base_res(),
- hir::def::Res::Def(hir::def::DefKind::AssocTy, _)
- ) && partial_res.unresolved_segments() == 0)
- {
+ if !matches!(
+ partial_res.full_res(),
+ Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
+ ) {
return false;
}
(ty, position, path)
@@ -867,11 +1029,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
return false;
};
- if !(matches!(
- partial_res.base_res(),
- hir::def::Res::Def(hir::def::DefKind::TyParam, _)
- ) && partial_res.unresolved_segments() == 0)
- {
+ if !matches!(
+ partial_res.full_res(),
+ Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
+ ) {
return false;
}
if let (
@@ -959,41 +1120,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
// 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 mut sp = span;
- loop {
- sp = sm.next_point(sp);
- match sm.span_to_snippet(sp) {
- Ok(ref snippet) => {
- if snippet.chars().any(|c| !c.is_whitespace()) {
- break;
- }
- }
- _ => break,
- }
- }
+ 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
// by parentheses, find the appropriate span.
- let mut i = 0;
- let mut closing_brace = None;
- loop {
- sp = sm.next_point(sp);
- match sm.span_to_snippet(sp) {
- Ok(ref snippet) => {
- if snippet == "}" {
- closing_brace = Some(span.to(sp));
- break;
- }
- }
- _ => break,
- }
- i += 1;
- // The bigger the span, the more likely we're incorrect --
- // bound it to 100 chars long.
- if i > 100 {
- break;
- }
- }
+ let closing_span = sm.span_look_ahead(span, Some("}"), Some(50));
+ let closing_brace: Option<Span> = sm
+ .span_to_snippet(closing_span)
+ .map_or(None, |s| if s == "}" { Some(span.to(closing_span)) } else { None });
(followed_by_brace, closing_brace)
}
@@ -1017,7 +1151,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let (lhs_span, rhs_span) = match &expr.kind {
ExprKind::Field(base, ident) => (base.span, ident.span),
- ExprKind::MethodCall(_, args, span) => (args[0].span, *span),
+ ExprKind::MethodCall(_, receiver, _, span) => (receiver.span, *span),
_ => return false,
};
@@ -1330,7 +1464,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
Applicability::HasPlaceholders,
);
}
- (Res::SelfTy { .. }, _) if ns == ValueNS => {
+ (Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
err.span_label(span, fallback_label);
err.note("can't use `Self` as a constructor, you must use the implemented struct");
}
@@ -1363,7 +1497,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
.filter(|(_, res)| match (kind, res) {
(AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
(AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
- (AssocItemKind::TyAlias(..), Res::Def(DefKind::AssocTy, _)) => true,
+ (AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true,
_ => false,
})
.map(|(key, _)| key.ident.name)
@@ -1377,6 +1511,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
ident: Ident,
ns: Namespace,
filter_fn: FilterFn,
+ called: bool,
) -> Option<AssocSuggestion>
where
FilterFn: Fn(Res) -> bool,
@@ -1399,20 +1534,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
{
// Look for a field with the same name in the current self_type.
if let Some(resolution) = self.r.partial_res_map.get(&node_id) {
- match resolution.base_res() {
- Res::Def(DefKind::Struct | DefKind::Union, did)
- if resolution.unresolved_segments() == 0 =>
- {
- if let Some(field_names) = self.r.field_names.get(&did) {
- if field_names
- .iter()
- .any(|&field_name| ident.name == field_name.node)
- {
- return Some(AssocSuggestion::Field);
- }
+ if let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) =
+ resolution.full_res()
+ {
+ if let Some(field_names) = self.r.field_names.get(&did) {
+ if field_names.iter().any(|&field_name| ident.name == field_name.node) {
+ return Some(AssocSuggestion::Field);
}
}
- _ => {}
}
}
}
@@ -1424,10 +1553,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
return Some(match &assoc_item.kind {
ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
- AssocSuggestion::MethodWithSelf
+ AssocSuggestion::MethodWithSelf { called }
}
- ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn,
- ast::AssocItemKind::TyAlias(..) => AssocSuggestion::AssocType,
+ ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
+ ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
ast::AssocItemKind::MacCall(_) => continue,
});
}
@@ -1445,10 +1574,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let res = binding.res();
if filter_fn(res) {
if self.r.has_self.contains(&res.def_id()) {
- return Some(AssocSuggestion::MethodWithSelf);
+ return Some(AssocSuggestion::MethodWithSelf { called });
} else {
match res {
- Res::Def(DefKind::AssocFn, _) => return Some(AssocSuggestion::AssocFn),
+ Res::Def(DefKind::AssocFn, _) => {
+ return Some(AssocSuggestion::AssocFn { called });
+ }
Res::Def(DefKind::AssocConst, _) => {
return Some(AssocSuggestion::AssocConst);
}
@@ -1470,22 +1601,38 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
path: &[Segment],
ns: Namespace,
filter_fn: &impl Fn(Res) -> bool,
- ) -> Option<TypoSuggestion> {
+ ) -> TypoCandidate {
let mut names = Vec::new();
if path.len() == 1 {
+ let mut ctxt = path.last().unwrap().ident.span.ctxt();
+
// Search in lexical scope.
// Walk backwards up the ribs in scope and collect candidates.
for rib in self.ribs[ns].iter().rev() {
+ let rib_ctxt = if rib.kind.contains_params() {
+ ctxt.normalize_to_macros_2_0()
+ } else {
+ ctxt.normalize_to_macro_rules()
+ };
+
// Locals and type parameters
for (ident, &res) in &rib.bindings {
- if filter_fn(res) {
+ if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
names.push(TypoSuggestion::typo_from_res(ident.name, res));
}
}
+
+ if let RibKind::MacroDefinition(def) = rib.kind && def == self.r.macro_def(ctxt) {
+ // If an invocation of this macro created `ident`, give up on `ident`
+ // and switch to `ident`'s source from the macro definition.
+ ctxt.remove_mark();
+ continue;
+ }
+
// Items in scope
if let RibKind::ModuleRibKind(module) = rib.kind {
// Items from this module
- self.r.add_module_candidates(module, &mut names, &filter_fn);
+ self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
if let ModuleKind::Block = module.kind {
// We can see through blocks
@@ -1511,7 +1658,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}));
if let Some(prelude) = self.r.prelude {
- self.r.add_module_candidates(prelude, &mut names, &filter_fn);
+ self.r.add_module_candidates(prelude, &mut names, &filter_fn, None);
}
}
break;
@@ -1530,7 +1677,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, Some(TypeNS), None)
{
- self.r.add_module_candidates(module, &mut names, &filter_fn);
+ self.r.add_module_candidates(module, &mut names, &filter_fn, None);
}
}
@@ -1543,10 +1690,17 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
name,
None,
) {
- Some(found) if found != name => {
- names.into_iter().find(|suggestion| suggestion.candidate == found)
+ Some(found) => {
+ let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found) else {
+ return TypoCandidate::None;
+ };
+ if found == name {
+ TypoCandidate::Shadowed(sugg.res)
+ } else {
+ TypoCandidate::Typo(sugg)
+ }
}
- _ => None,
+ _ => TypoCandidate::None,
}
}
@@ -1616,26 +1770,16 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
}
}
if let Ok(base_snippet) = base_snippet {
- let mut sp = after_colon_sp;
- for _ in 0..100 {
- // Try to find an assignment
- sp = sm.next_point(sp);
- let snippet = sm.span_to_snippet(sp.to(sm.next_point(sp)));
- match snippet {
- Ok(ref x) if x.as_str() == "=" => {
- err.span_suggestion(
- base_span,
- "maybe you meant to write an assignment here",
- format!("let {}", base_snippet),
- Applicability::MaybeIncorrect,
- );
- show_label = false;
- break;
- }
- Ok(ref x) if x.as_str() == "\n" => break,
- Err(_) => break,
- Ok(_) => {}
- }
+ // Try to find an assignment
+ let eq_span = sm.span_look_ahead(after_colon_sp, Some("="), Some(50));
+ if let Ok(ref snippet) = sm.span_to_snippet(eq_span) && snippet == "=" {
+ err.span_suggestion(
+ base_span,
+ "maybe you meant to write an assignment here",
+ format!("let {}", base_snippet),
+ Applicability::MaybeIncorrect,
+ );
+ show_label = false;
}
}
}
@@ -1652,6 +1796,31 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
false
}
+ fn let_binding_suggestion(&self, err: &mut Diagnostic, ident_span: Span) -> bool {
+ // try to give a suggestion for this pattern: `name = 1`, which is common in other languages
+ let mut added_suggestion = false;
+ if let Some(Expr { kind: ExprKind::Assign(lhs, _rhs, _), .. }) = self.diagnostic_metadata.in_assignment &&
+ let ast::ExprKind::Path(None, _) = lhs.kind {
+ let sm = self.r.session.source_map();
+ let line_span = sm.span_extend_to_line(ident_span);
+ let ident_name = sm.span_to_snippet(ident_span).unwrap();
+ // HACK(chenyukang): make sure ident_name is at the starting of the line to protect against macros
+ if sm
+ .span_to_snippet(line_span)
+ .map_or(false, |s| s.trim().starts_with(&ident_name))
+ {
+ err.span_suggestion_verbose(
+ ident_span.shrink_to_lo(),
+ "you might have meant to introduce a new binding",
+ "let ".to_string(),
+ Applicability::MaybeIncorrect,
+ );
+ added_suggestion = true;
+ }
+ }
+ added_suggestion
+ }
+
fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> {
let mut result = None;
let mut seen_modules = FxHashSet::default();
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 26b9284fe..8aebb7da1 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -4,7 +4,7 @@
//! Paths in macros, imports, expressions, types, patterns are resolved here.
//! Label and lifetime names are resolved here as well.
//!
-//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_typeck`.
+//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)]
@@ -13,7 +13,6 @@
#![feature(if_let_guard)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![recursion_limit = "256"]
#![allow(rustdoc::private_intra_doc_links)]
@@ -42,12 +41,12 @@ use rustc_hir::TraitCandidate;
use rustc_index::vec::IndexVec;
use rustc_metadata::creader::{CStore, CrateLoader};
use rustc_middle::metadata::ModChild;
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::span_bug;
-use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools, ResolverOutputs};
+use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
+use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
use rustc_query_system::ich::StableHashingContext;
-use rustc_session::cstore::{CrateStore, CrateStoreDyn, MetadataLoaderDyn};
+use rustc_session::cstore::{CrateStore, MetadataLoaderDyn};
use rustc_session::lint::LintBuffer;
use rustc_session::Session;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
@@ -65,15 +64,15 @@ use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, PatternSource};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
-use crate::access_levels::AccessLevelsVisitor;
+use crate::effective_visibilities::EffectiveVisibilitiesVisitor;
type Res = def::Res<NodeId>;
-mod access_levels;
mod build_reduced_graph;
mod check_unused;
mod def_collector;
mod diagnostics;
+mod effective_visibilities;
mod ident;
mod imports;
mod late;
@@ -238,6 +237,8 @@ enum ResolutionError<'a> {
trait_item_span: Span,
code: rustc_errors::DiagnosticId,
},
+ /// Error E0201: multiple impl items for the same trait item.
+ TraitImplDuplicate { name: Symbol, trait_item_span: Span, old_span: Span },
/// Inline asm `sym` operand must refer to a `fn` or `static`.
InvalidAsmSym,
}
@@ -676,6 +677,8 @@ struct UseError<'a> {
/// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling
/// the user to import the item directly.
path: Vec<Segment>,
+ /// Whether the expected source is a call
+ is_call: bool,
}
#[derive(Clone, Copy, PartialEq, Debug)]
@@ -1028,7 +1031,7 @@ pub struct Resolver<'a> {
proc_macros: Vec<NodeId>,
confused_type_with_std_module: FxHashMap<Span, Span>,
- access_levels: AccessLevels,
+ effective_visibilities: EffectiveVisibilities,
}
/// Nothing really interesting here; it just provides memory for the rest of the crate.
@@ -1332,7 +1335,7 @@ impl<'a> Resolver<'a> {
trait_impls: Default::default(),
proc_macros: Default::default(),
confused_type_with_std_module: Default::default(),
- access_levels: Default::default(),
+ effective_visibilities: Default::default(),
};
let root_parent_scope = ParentScope::module(graph_root, &resolver);
@@ -1375,9 +1378,7 @@ impl<'a> Resolver<'a> {
Default::default()
}
- pub fn into_outputs(
- self,
- ) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) {
+ pub fn into_outputs(self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
let definitions = self.definitions;
let cstore = Box::new(self.crate_loader.into_cstore());
@@ -1392,13 +1393,14 @@ impl<'a> Resolver<'a> {
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 access_levels = self.access_levels;
- let resolutions = ResolverOutputs {
+ let effective_visibilities = self.effective_visibilities;
+ let global_ctxt = ResolverGlobalCtxt {
+ cstore,
source_span,
expn_that_defined,
visibilities,
has_pub_restricted,
- access_levels,
+ effective_visibilities,
extern_crate_map,
reexport_map,
glob_map,
@@ -1415,7 +1417,7 @@ impl<'a> Resolver<'a> {
confused_type_with_std_module,
registered_tools: self.registered_tools,
};
- let resolutions_lowering = ty::ResolverAstLowering {
+ let ast_lowering = ty::ResolverAstLowering {
legacy_const_generic_args: self.legacy_const_generic_args,
partial_res_map: self.partial_res_map,
import_res_map: self.import_res_map,
@@ -1428,16 +1430,15 @@ impl<'a> Resolver<'a> {
trait_map: self.trait_map,
builtin_macro_kinds: self.builtin_macro_kinds,
};
- (definitions, cstore, resolutions, resolutions_lowering)
+ ResolverOutputs { definitions, global_ctxt, ast_lowering }
}
- pub fn clone_outputs(
- &self,
- ) -> (Definitions, Box<CrateStoreDyn>, ResolverOutputs, ty::ResolverAstLowering) {
+ pub fn clone_outputs(&self) -> ResolverOutputs {
let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
let definitions = self.definitions.clone();
let cstore = Box::new(self.cstore().clone());
- let resolutions = ResolverOutputs {
+ let global_ctxt = ResolverGlobalCtxt {
+ cstore,
source_span: self.source_span.clone(),
expn_that_defined: self.expn_that_defined.clone(),
visibilities: self.visibilities.clone(),
@@ -1457,9 +1458,9 @@ impl<'a> Resolver<'a> {
proc_macros,
confused_type_with_std_module: self.confused_type_with_std_module.clone(),
registered_tools: self.registered_tools.clone(),
- access_levels: self.access_levels.clone(),
+ effective_visibilities: self.effective_visibilities.clone(),
};
- let resolutions_lowering = ty::ResolverAstLowering {
+ 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(),
@@ -1472,7 +1473,7 @@ impl<'a> Resolver<'a> {
trait_map: self.trait_map.clone(),
builtin_macro_kinds: self.builtin_macro_kinds.clone(),
};
- (definitions, cstore, resolutions, resolutions_lowering)
+ ResolverOutputs { definitions, global_ctxt, ast_lowering }
}
fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
@@ -1520,8 +1521,8 @@ impl<'a> Resolver<'a> {
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("resolve_access_levels", || {
- AccessLevelsVisitor::compute_access_levels(self, krate)
+ self.session.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));
@@ -1882,12 +1883,10 @@ impl<'a> Resolver<'a> {
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
- PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
- Some(path_res.base_res())
+ PathResult::NonModule(path_res) => path_res.full_res(),
+ PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
+ None
}
- PathResult::Module(ModuleOrUniformRoot::ExternPrelude)
- | PathResult::NonModule(..)
- | PathResult::Failed { .. } => None,
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
}
}
@@ -1911,6 +1910,11 @@ impl<'a> Resolver<'a> {
}
}
+ /// 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> {
@@ -1938,12 +1942,8 @@ impl<'a> Resolver<'a> {
return None;
}
- let partial_res = self.partial_res_map.get(&expr.id)?;
- if partial_res.unresolved_segments() != 0 {
- return None;
- }
-
- if let Res::Def(def::DefKind::Fn, def_id) = partial_res.base_res() {
+ let res = self.partial_res_map.get(&expr.id)?.full_res()?;
+ if let Res::Def(def::DefKind::Fn, def_id) = res {
// We only support cross-crate argument rewriting. Uses
// within the same crate should be updated to use the new
// const generics style.
@@ -2065,7 +2065,7 @@ struct Finalize {
/// Span of the whole path or some its characteristic fragment.
/// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths.
path_span: Span,
- /// Span of the path start, suitable for prepending something to to it.
+ /// Span of the path start, suitable for prepending something to it.
/// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths.
root_span: Span,
/// Whether to report privacy errors or silently return "no resolution" for them,
@@ -2082,7 +2082,3 @@ impl Finalize {
Finalize { node_id, path_span, root_span, report_private: true }
}
}
-
-pub fn provide(providers: &mut Providers) {
- late::lifetimes::provide(providers);
-}
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index dafa10e9e..9526296f9 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -12,7 +12,7 @@ use rustc_attr::StabilityLevel;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::intern::Interned;
use rustc_data_structures::sync::Lrc;
-use rustc_errors::struct_span_err;
+use rustc_errors::{struct_span_err, Applicability};
use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand};
use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
use rustc_expand::compile_declarative_macro;
@@ -590,9 +590,7 @@ impl<'a> Resolver<'a> {
let res = if path.len() > 1 {
let res = match self.maybe_resolve_path(&path, Some(MacroNS), parent_scope) {
- PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
- Ok(path_res.base_res())
- }
+ PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
PathResult::NonModule(..)
| PathResult::Indeterminate
@@ -692,12 +690,23 @@ impl<'a> Resolver<'a> {
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
None,
) {
- PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
- let res = path_res.base_res();
- check_consistency(self, &path, path_span, kind, initial_res, res);
+ PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
+ check_consistency(self, &path, path_span, kind, initial_res, res)
}
path_res @ PathResult::NonModule(..) | path_res @ PathResult::Failed { .. } => {
+ let mut suggestion = None;
let (span, label) = if let PathResult::Failed { span, label, .. } = path_res {
+ // 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 exclamation_span = sm.next_point(span);
+ suggestion = Some((
+ vec![(exclamation_span, "".to_string())],
+ format!("{} is not a macro, but a {}, try to remove `!`", Segment::names_to_string(&path), partial_res.base_res().descr()),
+ Applicability::MaybeIncorrect
+ ));
+ }
(span, label)
} else {
(
@@ -711,7 +720,7 @@ impl<'a> Resolver<'a> {
};
self.report_error(
span,
- ResolutionError::FailedToResolve { label, suggestion: None },
+ ResolutionError::FailedToResolve { label, suggestion },
);
}
PathResult::Module(..) | PathResult::Indeterminate => unreachable!(),
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index 8bd42d8d2..df5d992f6 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -57,7 +57,7 @@ macro_rules! access_from {
($save_ctxt:expr, $id:expr) => {
Access {
public: $save_ctxt.tcx.visibility($id).is_public(),
- reachable: $save_ctxt.access_levels.is_reachable($id),
+ reachable: $save_ctxt.effective_visibilities.is_reachable($id),
}
};
}
@@ -345,14 +345,14 @@ impl<'tcx> DumpVisitor<'tcx> {
body: hir::BodyId,
) {
let map = self.tcx.hir();
- self.nest_typeck_results(item.def_id, |v| {
+ 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.def_id), fn_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), fn_data);
}
for arg in decl.inputs {
@@ -373,10 +373,10 @@ impl<'tcx> DumpVisitor<'tcx> {
typ: &'tcx hir::Ty<'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) {
- self.nest_typeck_results(item.def_id, |v| {
+ 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.def_id), var_data);
+ v.dumper.dump_def(&access_from!(v.save_ctxt, item.owner_id.def_id), var_data);
}
v.visit_ty(&typ);
v.visit_expr(expr);
@@ -436,7 +436,7 @@ impl<'tcx> DumpVisitor<'tcx> {
) {
debug!("process_struct {:?} {:?}", item, item.span);
let name = item.ident.to_string();
- let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
+ let qualname = format!("::{}", self.tcx.def_path_str(item.owner_id.to_def_id()));
let kind = match item.kind {
hir::ItemKind::Struct(_, _) => DefKind::Struct,
@@ -473,10 +473,10 @@ impl<'tcx> DumpVisitor<'tcx> {
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.def_id),
+ &access_from!(self.save_ctxt, item.owner_id.def_id),
Def {
kind,
- id: id_from_def_id(item.def_id.to_def_id()),
+ id: id_from_def_id(item.owner_id.to_def_id()),
span,
name,
qualname: qualname.clone(),
@@ -491,7 +491,7 @@ impl<'tcx> DumpVisitor<'tcx> {
);
}
- self.nest_typeck_results(item.def_id, |v| {
+ 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);
@@ -513,7 +513,7 @@ impl<'tcx> DumpVisitor<'tcx> {
};
down_cast_data!(enum_data, DefData, item.span);
- let access = access_from!(self.save_ctxt, item.def_id);
+ 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();
@@ -528,7 +528,7 @@ impl<'tcx> DumpVisitor<'tcx> {
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
let id = id_from_hir_id(variant.id, &self.save_ctxt);
- let parent = Some(id_from_def_id(item.def_id.to_def_id()));
+ let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.id);
self.dumper.dump_def(
@@ -566,7 +566,7 @@ impl<'tcx> DumpVisitor<'tcx> {
if !self.span.filter_generated(name_span) {
let span = self.span_from_span(name_span);
let id = id_from_hir_id(variant.id, &self.save_ctxt);
- let parent = Some(id_from_def_id(item.def_id.to_def_id()));
+ let parent = Some(id_from_def_id(item.owner_id.to_def_id()));
let attrs = self.tcx.hir().attrs(variant.id);
self.dumper.dump_def(
@@ -612,14 +612,14 @@ impl<'tcx> DumpVisitor<'tcx> {
}
let map = self.tcx.hir();
- self.nest_typeck_results(item.def_id, |v| {
+ 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.def_id.to_def_id());
+ v.process_impl_item(map.impl_item(impl_item.id), item.owner_id.to_def_id());
}
});
}
@@ -632,7 +632,7 @@ impl<'tcx> DumpVisitor<'tcx> {
methods: &'tcx [hir::TraitItemRef],
) {
let name = item.ident.to_string();
- let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
+ 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));
@@ -642,13 +642,13 @@ impl<'tcx> DumpVisitor<'tcx> {
val.push_str(&bounds_to_string(trait_refs));
}
if !self.span.filter_generated(item.ident.span) {
- let id = id_from_def_id(item.def_id.to_def_id());
+ 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.def_id.to_def_id())).collect();
+ 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.def_id),
+ &access_from!(self.save_ctxt, item.owner_id.def_id),
Def {
kind: DefKind::Trait,
id,
@@ -692,7 +692,7 @@ impl<'tcx> DumpVisitor<'tcx> {
kind: RelationKind::SuperTrait,
span,
from: id_from_def_id(id),
- to: id_from_def_id(item.def_id.to_def_id()),
+ to: id_from_def_id(item.owner_id.to_def_id()),
});
}
}
@@ -702,7 +702,7 @@ impl<'tcx> DumpVisitor<'tcx> {
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.def_id.to_def_id())
+ self.process_trait_item(map.trait_item(method.id), item.owner_id.to_def_id())
}
}
@@ -710,7 +710,7 @@ impl<'tcx> DumpVisitor<'tcx> {
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.def_id), mod_data);
+ self.dumper.dump_def(&access_from!(self.save_ctxt, item.owner_id.def_id), mod_data);
}
}
@@ -913,7 +913,8 @@ impl<'tcx> DumpVisitor<'tcx> {
| HirDefKind::AssocTy,
_,
)
- | Res::SelfTy { .. } => {
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. } => {
self.dump_path_segment_ref(
id,
&hir::PathSegment::new(ident, hir::HirId::INVALID, Res::Err),
@@ -980,7 +981,7 @@ impl<'tcx> DumpVisitor<'tcx> {
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.def_id,
+ trait_item.owner_id.def_id,
trait_item.ident,
&ty,
body,
@@ -994,7 +995,7 @@ impl<'tcx> DumpVisitor<'tcx> {
self.process_method(
sig,
body,
- trait_item.def_id,
+ trait_item.owner_id.def_id,
trait_item.ident,
&trait_item.generics,
trait_item.span,
@@ -1004,11 +1005,11 @@ impl<'tcx> DumpVisitor<'tcx> {
// 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.def_id.to_def_id()));
+ 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.def_id.to_def_id());
+ 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(
@@ -1050,7 +1051,7 @@ impl<'tcx> DumpVisitor<'tcx> {
let body = self.tcx.hir().body(body);
let attrs = self.tcx.hir().attrs(impl_item.hir_id());
self.process_assoc_const(
- impl_item.def_id,
+ impl_item.owner_id.def_id,
impl_item.ident,
&ty,
Some(&body.value),
@@ -1062,13 +1063,13 @@ impl<'tcx> DumpVisitor<'tcx> {
self.process_method(
sig,
Some(body),
- impl_item.def_id,
+ impl_item.owner_id.def_id,
impl_item.ident,
&impl_item.generics,
impl_item.span,
);
}
- hir::ImplItemKind::TyAlias(ref ty) => {
+ 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.
@@ -1087,7 +1088,7 @@ impl<'tcx> DumpVisitor<'tcx> {
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.def_id.to_def_id())).collect();
+ 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);
@@ -1136,10 +1137,10 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
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.def_id);
+ 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.def_id);
+ let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
self.dumper.import(
&access,
Import {
@@ -1157,16 +1158,16 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
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.def_id);
+ 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.def_id);
+ 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.def_id);
+ let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
self.dumper.import(
&access,
Import {
@@ -1187,7 +1188,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
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.def_id);
+ let parent = self.save_ctxt.tcx.local_parent(item.owner_id.def_id);
self.dumper.import(
&Access { public: false, reachable: false },
Import {
@@ -1227,15 +1228,15 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
intravisit::walk_mod(self, m, item.hir_id());
}
hir::ItemKind::TyAlias(ty, ref generics) => {
- let qualname = format!("::{}", self.tcx.def_path_str(item.def_id.to_def_id()));
+ 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.def_id.to_def_id());
+ 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.def_id),
+ &access_from!(self.save_ctxt, item.owner_id.def_id),
Def {
kind: DefKind::Type,
id,
@@ -1323,7 +1324,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
hir::TyKind::OpaqueDef(item_id, _, _) => {
let item = self.tcx.hir().item(item_id);
- self.nest_typeck_results(item_id.def_id, |v| v.visit_item(item));
+ self.nest_typeck_results(item_id.owner_id.def_id, |v| v.visit_item(item));
}
_ => intravisit::walk_ty(self, t),
}
@@ -1430,7 +1431,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- let access = access_from!(self.save_ctxt, item.def_id);
+ let access = access_from!(self.save_ctxt, item.owner_id.def_id);
match item.kind {
hir::ForeignItemKind::Fn(decl, _, ref generics) => {
diff --git a/compiler/rustc_save_analysis/src/errors.rs b/compiler/rustc_save_analysis/src/errors.rs
index f0ce41d02..585aac8c1 100644
--- a/compiler/rustc_save_analysis/src/errors.rs
+++ b/compiler/rustc_save_analysis/src/errors.rs
@@ -1,9 +1,9 @@
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use std::path::Path;
-#[derive(SessionDiagnostic)]
-#[diag(save_analysis::could_not_open)]
+#[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
index ce03c2a8a..d0155c908 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -1,6 +1,5 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(if_let_guard)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#![feature(never_type)]
@@ -27,7 +26,7 @@ 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::AccessLevels;
+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};
@@ -55,7 +54,7 @@ use rls_data::{
pub struct SaveContext<'tcx> {
tcx: TyCtxt<'tcx>,
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
- access_levels: &'tcx AccessLevels,
+ effective_visibilities: &'tcx EffectiveVisibilities,
span_utils: SpanUtils<'tcx>,
config: Config,
impl_counter: Cell<u32>,
@@ -142,7 +141,7 @@ impl<'tcx> SaveContext<'tcx> {
}
pub fn get_extern_item_data(&self, item: &hir::ForeignItem<'_>) -> Option<Data> {
- let def_id = item.def_id.to_def_id();
+ 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 {
@@ -206,7 +205,7 @@ impl<'tcx> SaveContext<'tcx> {
}
pub fn get_item_data(&self, item: &hir::Item<'_>) -> Option<Data> {
- let def_id = item.def_id.to_def_id();
+ 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, _) => {
@@ -298,7 +297,7 @@ impl<'tcx> SaveContext<'tcx> {
children: m
.item_ids
.iter()
- .map(|i| id_from_def_id(i.def_id.to_def_id()))
+ .map(|i| id_from_def_id(i.owner_id.to_def_id()))
.collect(),
decl_id: None,
docs: self.docs_for_attrs(attrs),
@@ -364,7 +363,7 @@ impl<'tcx> SaveContext<'tcx> {
parent: None,
children: items
.iter()
- .map(|i| id_from_def_id(i.id.def_id.to_def_id()))
+ .map(|i| id_from_def_id(i.id.owner_id.to_def_id()))
.collect(),
docs: String::new(),
sig: None,
@@ -622,7 +621,7 @@ impl<'tcx> SaveContext<'tcx> {
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).qpath_res(qpath, hir_id)
+ self.tcx.typeck(hir_id.owner.def_id).qpath_res(qpath, hir_id)
} else {
Res::Err
}
@@ -741,7 +740,8 @@ impl<'tcx> SaveContext<'tcx> {
_,
)
| Res::PrimTy(..)
- | Res::SelfTy { .. }
+ | Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
| Res::ToolMod
| Res::NonMacroAttr(..)
| Res::SelfCtor(..)
@@ -806,7 +806,7 @@ impl<'tcx> SaveContext<'tcx> {
fn lookup_def_id(&self, ref_id: hir::HirId) -> Option<DefId> {
match self.get_path_res(ref_id) {
- Res::PrimTy(_) | Res::SelfTy { .. } | Res::Err => None,
+ Res::PrimTy(_) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => None,
def => def.opt_def_id(),
}
}
@@ -968,16 +968,16 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
info!("Dumping crate {}", cratename);
// Privacy checking must be done outside of type inference; use a
- // fallback in case the access levels couldn't have been correctly computed.
- let access_levels = match tcx.sess.compile_status() {
- Ok(..) => tcx.privacy_access_levels(()),
- Err(..) => tcx.arena.alloc(AccessLevels::default()),
+ // 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,
- access_levels: &access_levels,
+ effective_visibilities: &effective_visibilities,
span_utils: SpanUtils::new(&tcx.sess),
config: find_config(config),
impl_counter: Cell::new(0),
@@ -1041,7 +1041,7 @@ fn id_from_hir_id(id: hir::HirId, scx: &SaveContext<'_>) -> rls_data::Id {
// crate (very unlikely to actually happen).
rls_data::Id {
krate: LOCAL_CRATE.as_u32(),
- index: id.owner.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
+ index: id.owner.def_id.local_def_index.as_u32() | id.local_id.as_u32().reverse_bits(),
}
})
}
diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs
index bae1828cd..83c51d213 100644
--- a/compiler/rustc_save_analysis/src/sig.rs
+++ b/compiler/rustc_save_analysis/src/sig.rs
@@ -337,7 +337,7 @@ impl<'hir> Sig for hir::Item<'hir> {
}
let name = self.ident.to_string();
let defs = vec![SigElement {
- id: id_from_def_id(self.def_id.to_def_id()),
+ id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
@@ -359,7 +359,7 @@ impl<'hir> Sig for hir::Item<'hir> {
let mut text = "const ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
- id: id_from_def_id(self.def_id.to_def_id()),
+ id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
@@ -428,7 +428,7 @@ impl<'hir> Sig for hir::Item<'hir> {
let mut text = "mod ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
- id: id_from_def_id(self.def_id.to_def_id()),
+ id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
@@ -579,7 +579,7 @@ impl<'hir> Sig for hir::Path<'hir> {
let res = scx.get_path_res(id.ok_or("Missing id for Path")?);
let (name, start, end) = match res {
- Res::PrimTy(..) | Res::SelfTy { .. } | Res::Err => {
+ 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(..), _) => {
@@ -764,7 +764,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> {
}
let name = self.ident.to_string();
let defs = vec![SigElement {
- id: id_from_def_id(self.def_id.to_def_id()),
+ id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
@@ -780,7 +780,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> {
let mut text = "type ".to_owned();
let name = self.ident.to_string();
let defs = vec![SigElement {
- id: id_from_def_id(self.def_id.to_def_id()),
+ id: id_from_def_id(self.owner_id.to_def_id()),
start: offset + text.len(),
end: offset + text.len() + name.len(),
}];
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index fa9c7bd54..1f8d2336c 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -14,7 +14,6 @@ Core encoding and decoding interfaces.
#![feature(min_specialization)]
#![feature(core_intrinsics)]
#![feature(maybe_uninit_slice)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(new_uninit)]
#![feature(allocator_api)]
#![cfg_attr(test, feature(test))]
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 5c17ef6ac..f35cc08f4 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -193,7 +193,9 @@ impl FileEncoder {
// shaves an instruction off those code paths (on x86 at least).
assert!(capacity <= usize::MAX - max_leb128_len());
- let file = File::create(path)?;
+ // Create the file for reading and writing, because some encoders do both
+ // (e.g. the metadata encoder when -Zmeta-stats is enabled)
+ let file = File::options().read(true).write(true).create(true).truncate(true).open(path)?;
Ok(FileEncoder {
buf: Box::new_uninit_slice(capacity),
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 8bb3878fb..f2ee52262 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -537,6 +537,7 @@ pub enum PrintRequest {
TargetLibdir,
CrateName,
Cfg,
+ CallingConventions,
TargetList,
TargetCPUs,
TargetFeatures,
@@ -1353,8 +1354,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"",
"print",
"Compiler information to print on stdout",
- "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
- target-cpus|target-features|relocation-models|code-models|\
+ "[crate-name|file-names|sysroot|target-libdir|cfg|calling-conventions|\
+ target-list|target-cpus|target-features|relocation-models|code-models|\
tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\
link-args]",
),
@@ -1793,6 +1794,7 @@ fn collect_print_requests(
"sysroot" => PrintRequest::Sysroot,
"target-libdir" => PrintRequest::TargetLibdir,
"cfg" => PrintRequest::Cfg,
+ "calling-conventions" => PrintRequest::CallingConventions,
"target-list" => PrintRequest::TargetList,
"target-cpus" => PrintRequest::TargetCPUs,
"target-features" => PrintRequest::TargetFeatures,
diff --git a/compiler/rustc_session/src/config/sigpipe.rs b/compiler/rustc_session/src/config/sigpipe.rs
index a5c94118a..53692ad7c 100644
--- a/compiler/rustc_session/src/config/sigpipe.rs
+++ b/compiler/rustc_session/src/config/sigpipe.rs
@@ -1,5 +1,13 @@
//! NOTE: Keep these constants in sync with `library/std/src/sys/unix/mod.rs`!
+/// The default value if `#[unix_sigpipe]` is not specified. This resolves
+/// to `SIG_IGN` in `library/std/src/sys/unix/mod.rs`.
+///
+/// Note that `SIG_IGN` has been the Rust default since 2014. See
+/// <https://github.com/rust-lang/rust/issues/62569>.
+#[allow(dead_code)]
+pub const DEFAULT: u8 = 0;
+
/// Do not touch `SIGPIPE`. Use whatever the parent process uses.
#[allow(dead_code)]
pub const INHERIT: u8 = 1;
@@ -15,8 +23,3 @@ pub const SIG_IGN: u8 = 2;
/// such as `head -n 1`.
#[allow(dead_code)]
pub const SIG_DFL: u8 = 3;
-
-/// `SIG_IGN` has been the Rust default since 2014. See
-/// <https://github.com/rust-lang/rust/issues/62569>.
-#[allow(dead_code)]
-pub const DEFAULT: u8 = SIG_IGN;
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index c6596ff24..bf542faec 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -1,15 +1,13 @@
use std::num::NonZeroU32;
use crate::cgu_reuse_tracker::CguReuse;
-use crate::{self as rustc_session, SessionDiagnostic};
-use rustc_errors::{fluent, DiagnosticBuilder, ErrorGuaranteed, Handler, MultiSpan};
-use rustc_macros::SessionDiagnostic;
+use rustc_errors::MultiSpan;
+use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
-use rustc_target::abi::TargetDataLayoutErrors;
use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple};
-#[derive(SessionDiagnostic)]
-#[diag(session::incorrect_cgu_reuse_type)]
+#[derive(Diagnostic)]
+#[diag(session_incorrect_cgu_reuse_type)]
pub struct IncorrectCguReuseType<'a> {
#[primary_span]
pub span: Span,
@@ -19,166 +17,115 @@ pub struct IncorrectCguReuseType<'a> {
pub at_least: u8,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::cgu_not_recorded)]
+#[derive(Diagnostic)]
+#[diag(session_cgu_not_recorded)]
pub struct CguNotRecorded<'a> {
pub cgu_user_name: &'a str,
pub cgu_name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::feature_gate_error, code = "E0658")]
+#[derive(Diagnostic)]
+#[diag(session_feature_gate_error, code = "E0658")]
pub struct FeatureGateError<'a> {
#[primary_span]
pub span: MultiSpan,
pub explain: &'a str,
}
-#[derive(SessionSubdiagnostic)]
-#[note(session::feature_diagnostic_for_issue)]
+#[derive(Subdiagnostic)]
+#[note(session_feature_diagnostic_for_issue)]
pub struct FeatureDiagnosticForIssue {
pub n: NonZeroU32,
}
-#[derive(SessionSubdiagnostic)]
-#[help(session::feature_diagnostic_help)]
+#[derive(Subdiagnostic)]
+#[help(session_feature_diagnostic_help)]
pub struct FeatureDiagnosticHelp {
pub feature: Symbol,
}
-impl SessionDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
- fn into_diagnostic(self, sess: &Handler) -> DiagnosticBuilder<'_, !> {
- let mut diag;
- match self {
- TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
- diag = sess.struct_fatal(fluent::session::target_invalid_address_space);
- diag.set_arg("addr_space", addr_space);
- diag.set_arg("cause", cause);
- diag.set_arg("err", err);
- diag
- }
- TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => {
- diag = sess.struct_fatal(fluent::session::target_invalid_bits);
- diag.set_arg("kind", kind);
- diag.set_arg("bit", bit);
- diag.set_arg("cause", cause);
- diag.set_arg("err", err);
- diag
- }
- TargetDataLayoutErrors::MissingAlignment { cause } => {
- diag = sess.struct_fatal(fluent::session::target_missing_alignment);
- diag.set_arg("cause", cause);
- diag
- }
- TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
- diag = sess.struct_fatal(fluent::session::target_invalid_alignment);
- diag.set_arg("cause", cause);
- diag.set_arg("err", err);
- diag
- }
- TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
- diag = sess.struct_fatal(fluent::session::target_inconsistent_architecture);
- diag.set_arg("dl", dl);
- diag.set_arg("target", target);
- diag
- }
- TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => {
- diag = sess.struct_fatal(fluent::session::target_inconsistent_pointer_width);
- diag.set_arg("pointer_size", pointer_size);
- diag.set_arg("target", target);
- diag
- }
- TargetDataLayoutErrors::InvalidBitsSize { err } => {
- diag = sess.struct_fatal(fluent::session::target_invalid_bits_size);
- diag.set_arg("err", err);
- diag
- }
- }
- }
-}
-
-#[derive(SessionDiagnostic)]
-#[diag(session::not_circumvent_feature)]
+#[derive(Diagnostic)]
+#[diag(session_not_circumvent_feature)]
pub struct NotCircumventFeature;
-#[derive(SessionDiagnostic)]
-#[diag(session::linker_plugin_lto_windows_not_supported)]
+#[derive(Diagnostic)]
+#[diag(session_linker_plugin_lto_windows_not_supported)]
pub struct LinkerPluginToWindowsNotSupported;
-#[derive(SessionDiagnostic)]
-#[diag(session::profile_use_file_does_not_exist)]
+#[derive(Diagnostic)]
+#[diag(session_profile_use_file_does_not_exist)]
pub struct ProfileUseFileDoesNotExist<'a> {
pub path: &'a std::path::Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::profile_sample_use_file_does_not_exist)]
+#[derive(Diagnostic)]
+#[diag(session_profile_sample_use_file_does_not_exist)]
pub struct ProfileSampleUseFileDoesNotExist<'a> {
pub path: &'a std::path::Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::target_requires_unwind_tables)]
+#[derive(Diagnostic)]
+#[diag(session_target_requires_unwind_tables)]
pub struct TargetRequiresUnwindTables;
-#[derive(SessionDiagnostic)]
-#[diag(session::sanitizer_not_supported)]
+#[derive(Diagnostic)]
+#[diag(session_sanitizer_not_supported)]
pub struct SanitizerNotSupported {
pub us: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::sanitizers_not_supported)]
+#[derive(Diagnostic)]
+#[diag(session_sanitizers_not_supported)]
pub struct SanitizersNotSupported {
pub us: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::cannot_mix_and_match_sanitizers)]
+#[derive(Diagnostic)]
+#[diag(session_cannot_mix_and_match_sanitizers)]
pub struct CannotMixAndMatchSanitizers {
pub first: String,
pub second: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::cannot_enable_crt_static_linux)]
+#[derive(Diagnostic)]
+#[diag(session_cannot_enable_crt_static_linux)]
pub struct CannotEnableCrtStaticLinux;
-#[derive(SessionDiagnostic)]
-#[diag(session::sanitizer_cfi_enabled)]
+#[derive(Diagnostic)]
+#[diag(session_sanitizer_cfi_enabled)]
pub struct SanitizerCfiEnabled;
-#[derive(SessionDiagnostic)]
-#[diag(session::unstable_virtual_function_elimination)]
+#[derive(Diagnostic)]
+#[diag(session_unstable_virtual_function_elimination)]
pub struct UnstableVirtualFunctionElimination;
-#[derive(SessionDiagnostic)]
-#[diag(session::unsupported_dwarf_version)]
+#[derive(Diagnostic)]
+#[diag(session_unsupported_dwarf_version)]
pub struct UnsupportedDwarfVersion {
pub dwarf_version: u32,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::target_stack_protector_not_supported)]
+#[derive(Diagnostic)]
+#[diag(session_target_stack_protector_not_supported)]
pub struct StackProtectorNotSupportedForTarget<'a> {
pub stack_protector: StackProtector,
pub target_triple: &'a TargetTriple,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::split_debuginfo_unstable_platform)]
+#[derive(Diagnostic)]
+#[diag(session_split_debuginfo_unstable_platform)]
pub struct SplitDebugInfoUnstablePlatform {
pub debuginfo: SplitDebuginfo,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::file_is_not_writeable)]
+#[derive(Diagnostic)]
+#[diag(session_file_is_not_writeable)]
pub struct FileIsNotWriteable<'a> {
pub file: &'a std::path::Path,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::crate_name_does_not_match)]
+#[derive(Diagnostic)]
+#[diag(session_crate_name_does_not_match)]
pub struct CrateNameDoesNotMatch<'a> {
#[primary_span]
pub span: Span,
@@ -186,36 +133,61 @@ pub struct CrateNameDoesNotMatch<'a> {
pub name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::crate_name_invalid)]
+#[derive(Diagnostic)]
+#[diag(session_crate_name_invalid)]
pub struct CrateNameInvalid<'a> {
pub s: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(session::crate_name_empty)]
+#[derive(Diagnostic)]
+#[diag(session_crate_name_empty)]
pub struct CrateNameEmpty {
#[primary_span]
pub span: Option<Span>,
}
+#[derive(Diagnostic)]
+#[diag(session_invalid_character_in_create_name)]
pub struct InvalidCharacterInCrateName<'a> {
+ #[primary_span]
pub span: Option<Span>,
pub character: char,
pub crate_name: &'a str,
}
-impl crate::SessionDiagnostic<'_> for InvalidCharacterInCrateName<'_> {
- fn into_diagnostic(
- self,
- sess: &Handler,
- ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = sess.struct_err(fluent::session::invalid_character_in_create_name);
- if let Some(sp) = self.span {
- diag.set_span(sp);
- }
- diag.set_arg("character", self.character);
- diag.set_arg("crate_name", self.crate_name);
- diag
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(session_expr_parentheses_needed, applicability = "machine-applicable")]
+pub struct ExprParenthesesNeeded {
+ #[suggestion_part(code = "(")]
+ pub left: Span,
+ #[suggestion_part(code = ")")]
+ pub right: Span,
+}
+
+impl ExprParenthesesNeeded {
+ pub fn surrounding(s: Span) -> Self {
+ ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() }
}
}
+
+#[derive(Diagnostic)]
+#[diag(session_skipping_const_checks)]
+pub struct SkippingConstChecks {
+ #[subdiagnostic(eager)]
+ pub unleashed_features: Vec<UnleashedFeatureHelp>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum UnleashedFeatureHelp {
+ #[help(session_unleashed_feature_help_named)]
+ Named {
+ #[primary_span]
+ span: Span,
+ gate: Symbol,
+ },
+ #[help(session_unleashed_feature_help_unnamed)]
+ Unnamed {
+ #[primary_span]
+ span: Span,
+ },
+}
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index f6bab775e..39e871f53 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,6 +1,5 @@
#![feature(if_let_guard)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(once_cell)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index d7f1bc0be..3f234a47a 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -186,7 +186,7 @@ top_level_options!(
/// Remap source path prefixes in all output (messages, object files, debug, etc.).
remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH],
/// Base directory containing the `src/` for the Rust standard library, and
- /// potentially `rustc` as well, if we can can find it. Right now it's always
+ /// potentially `rustc` as well, if we can find it. Right now it's always
/// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component).
///
/// This directory is what the virtual `/rustc/$hash` is translated back to,
@@ -280,14 +280,6 @@ macro_rules! options {
) }
-impl Options {
- // JUSTIFICATION: defn of the suggested wrapper fn
- #[allow(rustc::bad_opt_access)]
- pub fn time_passes(&self) -> bool {
- self.unstable_opts.time_passes || self.unstable_opts.time
- }
-}
-
impl CodegenOptions {
// JUSTIFICATION: defn of the suggested wrapper fn
#[allow(rustc::bad_opt_access)]
@@ -1083,12 +1075,11 @@ mod parse {
options! {
CodegenOptions, CG_OPTIONS, cgopts, "C", "codegen",
- // This list is in alphabetical order.
- //
// If you add a new option, please update:
// - compiler/rustc_interface/src/tests.rs
// - src/doc/rustc/src/codegen-options/index.md
+ // tidy-alphabetical-start
ar: String = (String::new(), parse_string, [UNTRACKED],
"this option is deprecated and does nothing"),
#[rustc_lint_opt_deny_field_access("use `Session::code_model` instead of this field")]
@@ -1203,9 +1194,8 @@ options! {
target_feature: String = (String::new(), parse_target_feature, [TRACKED],
"target specific attributes. (`rustc --print target-features` for details). \
This feature is unsafe."),
+ // tidy-alphabetical-end
- // This list is in alphabetical order.
- //
// If you add a new option, please update:
// - compiler/rustc_interface/src/tests.rs
// - src/doc/rustc/src/codegen-options/index.md
@@ -1214,24 +1204,23 @@ options! {
options! {
UnstableOptions, Z_OPTIONS, dbopts, "Z", "unstable",
- // This list is in alphabetical order.
- //
// If you add a new option, please update:
// - compiler/rustc_interface/src/tests.rs
// - src/doc/unstable-book/src/compiler-flags
+ // tidy-alphabetical-start
allow_features: Option<Vec<String>> = (None, parse_opt_comma_list, [TRACKED],
"only allow the listed language features to be enabled in code (space separated)"),
always_encode_mir: bool = (false, parse_bool, [TRACKED],
"encode MIR of all functions into the crate metadata (default: no)"),
- assume_incomplete_release: bool = (false, parse_bool, [TRACKED],
- "make cfg(version) treat the current version as incomplete (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::asm_comments` instead of this field")]
asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior) (default: no)"),
assert_incr_state: Option<String> = (None, parse_opt_string, [UNTRACKED],
"assert that the incremental cache is in given state: \
either `loaded` or `not-loaded`."),
+ assume_incomplete_release: bool = (false, parse_bool, [TRACKED],
+ "make cfg(version) treat the current version as incomplete (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::binary_dep_depinfo` instead of this field")]
binary_dep_depinfo: bool = (false, parse_bool, [TRACKED],
"include artifacts (sysroot, crate dependencies) used during compilation in dep-info \
@@ -1264,6 +1253,8 @@ options! {
dep_tasks: bool = (false, parse_bool, [UNTRACKED],
"print tasks that execute and the color their dep node gets (requires debug build) \
(default: no)"),
+ diagnostic_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
+ "set the current output width for diagnostic truncation"),
dlltool: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"import library generation tool (windows-gnu only)"),
dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED],
@@ -1304,6 +1295,8 @@ options! {
an additional `.html` file showing the computed coverage spans."),
dwarf_version: Option<u32> = (None, parse_opt_number, [TRACKED],
"version of DWARF debug information to emit (default: 2 or 4, depending on platform)"),
+ dylib_lto: bool = (false, parse_bool, [UNTRACKED],
+ "enables LTO for dylib crate type"),
emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED],
"emit a section containing stack size metadata (default: no)"),
emit_thin_lto: bool = (true, parse_bool, [TRACKED],
@@ -1345,16 +1338,16 @@ options! {
"hash spans relative to their parent item for incr. comp. (default: no)"),
incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
"verify incr. comp. hashes of green query instances (default: no)"),
+ inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
+ "control whether `#[inline]` functions are in all CGUs"),
inline_llvm: bool = (true, parse_bool, [TRACKED],
"enable LLVM inlining (default: yes)"),
inline_mir: Option<bool> = (None, parse_opt_bool, [TRACKED],
"enable MIR inlining (default: no)"),
- inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
- "a default MIR inlining threshold (default: 50)"),
inline_mir_hint_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
"inlining threshold for functions with inline hint (default: 100)"),
- inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
- "control whether `#[inline]` functions are in all CGUs"),
+ inline_mir_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
+ "a default MIR inlining threshold (default: 50)"),
input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
@@ -1371,6 +1364,8 @@ options! {
"insert function instrument code for mcount-based tracing (default: no)"),
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_native_libraries: bool = (true, parse_bool, [UNTRACKED],
"link native libraries in the linker invocation (default: yes)"),
link_only: bool = (false, parse_bool, [TRACKED],
@@ -1400,17 +1395,15 @@ options! {
"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."),
- mir_pretty_relative_line_numbers: bool = (false, parse_bool, [UNTRACKED],
- "use line numbers relative to the function in mir pretty printing"),
#[rustc_lint_opt_deny_field_access("use `Session::mir_opt_level` instead of this field")]
mir_opt_level: Option<usize> = (None, parse_opt_number, [TRACKED],
"MIR optimization level (0-4; default: 1 in non optimized builds and 2 in optimized builds)"),
+ mir_pretty_relative_line_numbers: bool = (false, parse_bool, [UNTRACKED],
+ "use line numbers relative to the function in mir pretty printing"),
move_size_limit: Option<usize> = (None, parse_opt_number, [TRACKED],
"the size at which the `large_assignments` lint starts to be emitted"),
mutable_noalias: Option<bool> = (None, parse_opt_bool, [TRACKED],
"emit noalias metadata for mutable references (default: yes)"),
- new_llvm_pass_manager: Option<bool> = (None, parse_opt_bool, [TRACKED],
- "use new LLVM pass manager (default: no)"),
nll_facts: bool = (false, parse_bool, [UNTRACKED],
"dump facts from NLL analysis into side files (default: no)"),
nll_facts_dir: String = ("nll-facts".to_string(), parse_string, [UNTRACKED],
@@ -1429,18 +1422,16 @@ options! {
"compile without linking"),
no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
"run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
- no_unique_section_names: bool = (false, parse_bool, [TRACKED],
- "do not use unique names for text and data sections when -Z function-sections is used"),
no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
"prevent automatic injection of the profiler_builtins crate"),
+ no_unique_section_names: bool = (false, parse_bool, [TRACKED],
+ "do not use unique names for text and data sections when -Z function-sections is used"),
normalize_docs: bool = (false, parse_bool, [TRACKED],
"normalize associated items in rustdoc when generating documentation"),
oom: OomStrategy = (OomStrategy::Abort, parse_oom_strategy, [TRACKED],
"panic strategy for out-of-memory handling"),
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
"pass `-install_name @rpath/...` to the macOS linker (default: no)"),
- diagnostic_width: Option<usize> = (None, parse_opt_number, [UNTRACKED],
- "set the current output width for diagnostic truncation"),
packed_bundled_libs: bool = (false, parse_bool, [TRACKED],
"change rlib format to store native libraries as archives"),
panic_abort_tests: bool = (false, parse_bool, [TRACKED],
@@ -1490,25 +1481,20 @@ options! {
profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"file path to emit profiling data at runtime when using 'profile' \
(default based on relative source path)"),
- profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],
- "name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)"),
profile_sample_use: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"use the given `.prof` file for sampled profile-guided optimization (also known as AutoFDO)"),
+ profiler_runtime: String = (String::from("profiler_builtins"), parse_string, [TRACKED],
+ "name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"enable queries of the dependency graph for regression testing (default: no)"),
randomize_layout: bool = (false, parse_bool, [TRACKED],
"randomize the layout of types (default: no)"),
- layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
- "seed layout randomization"),
relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether ELF relocations can be relaxed"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
remap_cwd_prefix: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
"remap paths under the current working directory to this path prefix"),
- simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
- "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
- to rust's source base directory. only meant for testing purposes"),
report_delayed_bugs: bool = (false, parse_bool, [TRACKED],
"immediately print bugs registered with `delay_span_bug` (default: no)"),
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
@@ -1526,27 +1512,41 @@ options! {
self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled,
parse_switch_with_opt_path, [UNTRACKED],
"run the self profiler and output the raw event data"),
- /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs
- self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
- "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"),
self_profile_counter: String = ("wall-time".to_string(), parse_string, [UNTRACKED],
"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)"
),
+ /// keep this in sync with the event filter names in librustc_data_structures/profiling.rs
+ self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED],
+ "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"),
share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make the current crate share its generic instantiations"),
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
"show spans for compiler debugging (expr|pat|ty)"),
+ simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+ "simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
+ to rust's source base directory. only meant for testing purposes"),
span_debug: bool = (false, parse_bool, [UNTRACKED],
"forward proc_macro::Span's `Debug` impl to `Span`"),
/// o/w tests have closure@path
span_free_formats: bool = (false, parse_bool, [UNTRACKED],
"exclude spans when debug-printing compiler state (default: no)"),
+ split_dwarf_inlining: bool = (true, parse_bool, [TRACKED],
+ "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"),
+ split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED],
+ "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"),
src_hash_algorithm: Option<SourceFileHashAlgorithm> = (None, parse_src_file_hash, [TRACKED],
"hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
#[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")]
@@ -1556,17 +1556,6 @@ options! {
"control if mem::uninitialized and mem::zeroed panic on more UB"),
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
- split_dwarf_kind: SplitDwarfKind = (SplitDwarfKind::Split, parse_split_dwarf_kind, [TRACKED],
- "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"),
- split_dwarf_inlining: bool = (true, parse_bool, [TRACKED],
- "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"),
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
parse_symbol_mangling_version, [TRACKED],
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
@@ -1575,17 +1564,6 @@ options! {
"show extended diagnostic help (default: no)"),
temps_dir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"the directory the intermediate files are written to"),
- // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
- // alongside query results and changes to translation options can affect diagnostics - so
- // translation options should be tracked.
- translate_lang: Option<LanguageIdentifier> = (None, parse_opt_langid, [TRACKED],
- "language identifier for diagnostic output"),
- translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
- "additional fluent translation to preferentially use (for testing translation)"),
- translate_directionality_markers: bool = (false, parse_bool, [TRACKED],
- "emit directionality isolation markers in translated diagnostics"),
- tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
- "select processor to schedule for (`rustc --print target-cpus` for details)"),
#[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"),
@@ -1598,9 +1576,6 @@ options! {
#[rustc_lint_opt_deny_field_access("use `Session::threads` instead of this field")]
threads: usize = (1, parse_threads, [UNTRACKED],
"use a thread pool with N threads"),
- #[rustc_lint_opt_deny_field_access("use `Session::time_passes` instead of this field")]
- time: bool = (false, parse_bool, [UNTRACKED],
- "measure time of rustc processes (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::time_llvm_passes` instead of this field")]
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each LLVM pass (default: no)"),
@@ -1612,6 +1587,15 @@ options! {
"choose the TLS model to use (`rustc --print tls-models` for details)"),
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments (default: no)"),
+ // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved
+ // alongside query results and changes to translation options can affect diagnostics - so
+ // translation options should be tracked.
+ translate_additional_ftl: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+ "additional fluent translation to preferentially use (for testing translation)"),
+ translate_directionality_markers: bool = (false, parse_bool, [TRACKED],
+ "emit directionality isolation markers in translated diagnostics"),
+ translate_lang: Option<LanguageIdentifier> = (None, parse_opt_langid, [TRACKED],
+ "language identifier for diagnostic output"),
translate_remapped_path_to_local_path: bool = (true, parse_bool, [TRACKED],
"translate remapped paths into local paths when possible (default: yes)"),
trap_unreachable: Option<bool> = (None, parse_opt_bool, [TRACKED],
@@ -1620,6 +1604,8 @@ options! {
"treat error number `val` that occurs as bug"),
trim_diagnostic_paths: bool = (true, parse_bool, [UNTRACKED],
"in diagnostics, use heuristics to shorten paths referring to items"),
+ tune_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
+ "select processor to schedule for (`rustc --print target-cpus` for details)"),
ui_testing: bool = (false, parse_bool, [UNTRACKED],
"emit compiler diagnostics in a form suitable for UI testing (default: no)"),
uninit_const_chunk_threshold: usize = (16, parse_number, [TRACKED],
@@ -1660,9 +1646,8 @@ options! {
Requires `-Clto[=[fat,yes]]`"),
wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
"whether to build a wasi command or reactor"),
+ // tidy-alphabetical-end
- // This list is in alphabetical order.
- //
// If you add a new option, please update:
// - compiler/rustc_interface/src/tests.rs
}
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 0389b2a06..a199947eb 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -6,14 +6,13 @@ use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGat
use crate::lint::{
builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
};
-use crate::SessionDiagnostic;
use rustc_ast::node_id::NodeId;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
use rustc_errors::{
- fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
- DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, MultiSpan, StashKey,
+ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
+ EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey,
};
use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
use rustc_span::edition::Edition;
@@ -323,16 +322,6 @@ impl ParseSess {
});
}
- /// Extend an error with a suggestion to wrap an expression with parentheses to allow the
- /// parser to continue parsing the following operation as part of the same expression.
- pub fn expr_parentheses_needed(&self, err: &mut Diagnostic, span: Span) {
- err.multipart_suggestion(
- "parentheses are required to parse this as an expression",
- vec![(span.shrink_to_lo(), "(".to_string()), (span.shrink_to_hi(), ")".to_string())],
- Applicability::MachineApplicable,
- );
- }
-
pub fn save_proc_macro_span(&self, span: Span) -> usize {
let mut spans = self.proc_macro_quoted_spans.lock();
spans.push(span);
@@ -345,40 +334,49 @@ impl ParseSess {
pub fn create_err<'a>(
&'a self,
- err: impl SessionDiagnostic<'a>,
+ err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
err.into_diagnostic(&self.span_diagnostic)
}
- pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
+ pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.create_err(err).emit()
}
pub fn create_warning<'a>(
&'a self,
- warning: impl SessionDiagnostic<'a, ()>,
+ warning: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> {
warning.into_diagnostic(&self.span_diagnostic)
}
- pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
+ pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.create_warning(warning).emit()
}
+ pub fn create_note<'a>(
+ &'a self,
+ note: impl IntoDiagnostic<'a, Noted>,
+ ) -> DiagnosticBuilder<'a, Noted> {
+ note.into_diagnostic(&self.span_diagnostic)
+ }
+
+ pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
+ self.create_note(note).emit()
+ }
+
pub fn create_fatal<'a>(
&'a self,
- fatal: impl SessionDiagnostic<'a, !>,
+ fatal: impl IntoDiagnostic<'a, !>,
) -> DiagnosticBuilder<'a, !> {
fatal.into_diagnostic(&self.span_diagnostic)
}
- pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+ pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
self.create_fatal(fatal).emit()
}
#[rustc_lint_diagnostics]
- #[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -387,22 +385,16 @@ impl ParseSess {
}
#[rustc_lint_diagnostics]
- #[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.span_diagnostic.struct_warn(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.span_diagnostic.struct_fatal(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::diagnostic_outside_of_impl)]
- #[allow(rustc::untranslatable_diagnostic)]
pub fn struct_diagnostic<G: EmissionGuarantee>(
&self,
msg: impl Into<DiagnosticMessage>,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a001f87db..100c66f63 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -5,9 +5,10 @@ use crate::config::{self, CrateType, InstrumentCoverage, OptLevel, OutputType, S
use crate::errors::{
CannotEnableCrtStaticLinux, CannotMixAndMatchSanitizers, LinkerPluginToWindowsNotSupported,
NotCircumventFeature, ProfileSampleUseFileDoesNotExist, ProfileUseFileDoesNotExist,
- SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported,
+ SanitizerCfiEnabled, SanitizerNotSupported, SanitizersNotSupported, SkippingConstChecks,
SplitDebugInfoUnstablePlatform, StackProtectorNotSupportedForTarget,
- TargetRequiresUnwindTables, UnstableVirtualFunctionElimination, UnsupportedDwarfVersion,
+ TargetRequiresUnwindTables, UnleashedFeatureHelp, UnstableVirtualFunctionElimination,
+ UnsupportedDwarfVersion,
};
use crate::parse::{add_feature_diagnostics, ParseSess};
use crate::search_paths::{PathKind, SearchPath};
@@ -28,7 +29,7 @@ use rustc_errors::json::JsonEmitter;
use rustc_errors::registry::Registry;
use rustc_errors::{
error_code, fallback_fluent_bundle, DiagnosticBuilder, DiagnosticId, DiagnosticMessage,
- EmissionGuarantee, ErrorGuaranteed, FluentBundle, Handler, LazyFallbackBundle, MultiSpan,
+ ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, MultiSpan, Noted,
};
use rustc_macros::HashStable_Generic;
pub use rustc_span::def_id::StableCrateId;
@@ -44,7 +45,6 @@ use rustc_target::spec::{
use std::cell::{self, RefCell};
use std::env;
use std::fmt;
-use std::io::Write;
use std::ops::{Div, Mul};
use std::path::{Path, PathBuf};
use std::str::FromStr;
@@ -223,15 +223,6 @@ pub struct PerfStats {
pub normalize_projection_ty: AtomicUsize,
}
-/// Trait implemented by error types. This should not be implemented manually. Instead, use
-/// `#[derive(SessionDiagnostic)]` -- see [rustc_macros::SessionDiagnostic].
-#[rustc_diagnostic_item = "SessionDiagnostic"]
-pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
- /// Write out as a diagnostic out of `Handler`.
- #[must_use]
- fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>;
-}
-
impl Session {
pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) {
self.miri_unleashed_features.lock().push((span, feature_gate));
@@ -242,21 +233,19 @@ impl Session {
if !unleashed_features.is_empty() {
let mut must_err = false;
// Create a diagnostic pointing at where things got unleashed.
- // FIXME(#100717): needs eager translation/lists
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
- let mut diag = self.struct_warn("skipping const checks");
- for &(span, feature_gate) in unleashed_features.iter() {
- // FIXME: `span_label` doesn't do anything, so we use "help" as a hack.
- if let Some(gate) = feature_gate {
- diag.span_help(span, &format!("skipping check for `{gate}` feature"));
- // The unleash flag must *not* be used to just "hack around" feature gates.
- must_err = true;
- } else {
- diag.span_help(span, "skipping check that does not even have a feature gate");
- }
- }
- diag.emit();
+ self.emit_warning(SkippingConstChecks {
+ unleashed_features: unleashed_features
+ .iter()
+ .map(|(span, gate)| {
+ gate.map(|gate| {
+ must_err = true;
+ UnleashedFeatureHelp::Named { span: *span, gate }
+ })
+ .unwrap_or(UnleashedFeatureHelp::Unnamed { span: *span })
+ })
+ .collect(),
+ });
+
// 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.
@@ -297,8 +286,6 @@ impl Session {
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -307,8 +294,6 @@ impl Session {
self.diagnostic().struct_span_warn(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn_with_expectation<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -318,8 +303,6 @@ impl Session {
self.diagnostic().struct_span_warn_with_expectation(sp, msg, id)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -329,14 +312,10 @@ impl Session {
self.diagnostic().struct_span_warn_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_warn(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn_with_expectation(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -345,8 +324,6 @@ impl Session {
self.diagnostic().struct_warn_with_expectation(msg, id)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_allow<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -355,14 +332,10 @@ impl Session {
self.diagnostic().struct_span_allow(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
self.diagnostic().struct_allow(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -371,8 +344,6 @@ impl Session {
self.diagnostic().struct_expect(msg, id)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -381,8 +352,6 @@ impl Session {
self.diagnostic().struct_span_err(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -393,8 +362,6 @@ impl Session {
}
// FIXME: This method should be removed (every error should have an associated error code).
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -402,8 +369,6 @@ impl Session {
self.parse_sess.struct_err(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_err_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -412,8 +377,6 @@ impl Session {
self.diagnostic().struct_err_with_code(msg, code)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
@@ -422,8 +385,6 @@ impl Session {
self.diagnostic().struct_warn_with_code(msg, code)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_fatal<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -432,8 +393,6 @@ impl Session {
self.diagnostic().struct_span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -443,21 +402,15 @@ impl Session {
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
self.diagnostic().struct_fatal(msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().span_fatal(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -467,14 +420,10 @@ impl Session {
self.diagnostic().span_fatal_with_code(sp, msg, code)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn fatal(&self, msg: impl Into<DiagnosticMessage>) -> ! {
self.diagnostic().fatal(msg).raise()
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err_or_warn<S: Into<MultiSpan>>(
&self,
is_warning: bool,
@@ -488,8 +437,6 @@ impl Session {
}
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -498,8 +445,6 @@ impl Session {
self.diagnostic().span_err(sp, msg)
}
#[rustc_lint_diagnostics]
- #[allow(rustc::untranslatable_diagnostic)]
- #[allow(rustc::diagnostic_outside_of_impl)]
pub fn span_err_with_code<S: Into<MultiSpan>>(
&self,
sp: S,
@@ -514,13 +459,13 @@ impl Session {
}
pub fn create_err<'a>(
&'a self,
- err: impl SessionDiagnostic<'a>,
+ err: impl IntoDiagnostic<'a>,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
self.parse_sess.create_err(err)
}
pub fn create_feature_err<'a>(
&'a self,
- err: impl SessionDiagnostic<'a>,
+ err: impl IntoDiagnostic<'a>,
feature: Symbol,
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
let mut err = self.parse_sess.create_err(err);
@@ -530,25 +475,34 @@ impl Session {
add_feature_diagnostics(&mut err, &self.parse_sess, feature);
err
}
- pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed {
+ pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
self.parse_sess.emit_err(err)
}
pub fn create_warning<'a>(
&'a self,
- err: impl SessionDiagnostic<'a, ()>,
+ err: impl IntoDiagnostic<'a, ()>,
) -> DiagnosticBuilder<'a, ()> {
self.parse_sess.create_warning(err)
}
- pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
+ pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
self.parse_sess.emit_warning(warning)
}
+ pub fn create_note<'a>(
+ &'a self,
+ note: impl IntoDiagnostic<'a, Noted>,
+ ) -> DiagnosticBuilder<'a, Noted> {
+ self.parse_sess.create_note(note)
+ }
+ pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted {
+ self.parse_sess.emit_note(note)
+ }
pub fn create_fatal<'a>(
&'a self,
- fatal: impl SessionDiagnostic<'a, !>,
+ fatal: impl IntoDiagnostic<'a, !>,
) -> DiagnosticBuilder<'a, !> {
self.parse_sess.create_fatal(fatal)
}
- pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+ pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! {
self.parse_sess.emit_fatal(fatal)
}
#[inline]
@@ -659,10 +613,6 @@ impl Session {
self.parse_sess.source_map()
}
- pub fn time_passes(&self) -> bool {
- self.opts.time_passes()
- }
-
/// Returns `true` if internal lints should be added to the lint store - i.e. if
/// `-Zunstable-options` is provided and this isn't rustdoc (internal lints can trigger errors
/// to be emitted under rustdoc).
@@ -980,6 +930,10 @@ impl Session {
self.opts.unstable_opts.instrument_mcount
}
+ pub fn time_passes(&self) -> bool {
+ self.opts.unstable_opts.time_passes
+ }
+
pub fn time_llvm_passes(&self) -> bool {
self.opts.unstable_opts.time_llvm_passes
}
@@ -1257,11 +1211,10 @@ fn default_emitter(
source_map: Lrc<SourceMap>,
bundle: Option<Lrc<FluentBundle>>,
fallback_bundle: LazyFallbackBundle,
- emitter_dest: Option<Box<dyn Write + Send>>,
) -> Box<dyn Emitter + sync::Send> {
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
- match (sopts.error_format, emitter_dest) {
- (config::ErrorOutputType::HumanReadable(kind), dst) => {
+ match sopts.error_format {
+ config::ErrorOutputType::HumanReadable(kind) => {
let (short, color_config) = kind.unzip();
if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
@@ -1274,33 +1227,20 @@ fn default_emitter(
);
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
} else {
- let emitter = match dst {
- None => EmitterWriter::stderr(
- color_config,
- Some(source_map),
- bundle,
- fallback_bundle,
- short,
- sopts.unstable_opts.teach,
- sopts.diagnostic_width,
- macro_backtrace,
- ),
- Some(dst) => EmitterWriter::new(
- dst,
- Some(source_map),
- bundle,
- fallback_bundle,
- short,
- false, // no teach messages when writing to a buffer
- false, // no colors when writing to a buffer
- None, // no diagnostic width
- macro_backtrace,
- ),
- };
+ let emitter = EmitterWriter::stderr(
+ color_config,
+ Some(source_map),
+ bundle,
+ fallback_bundle,
+ short,
+ sopts.unstable_opts.teach,
+ sopts.diagnostic_width,
+ macro_backtrace,
+ );
Box::new(emitter.ui_testing(sopts.unstable_opts.ui_testing))
}
}
- (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new(
+ config::ErrorOutputType::Json { pretty, json_rendered } => Box::new(
JsonEmitter::stderr(
Some(registry),
source_map,
@@ -1313,28 +1253,9 @@ fn default_emitter(
)
.ui_testing(sopts.unstable_opts.ui_testing),
),
- (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new(
- JsonEmitter::new(
- dst,
- Some(registry),
- source_map,
- bundle,
- fallback_bundle,
- pretty,
- json_rendered,
- sopts.diagnostic_width,
- macro_backtrace,
- )
- .ui_testing(sopts.unstable_opts.ui_testing),
- ),
}
}
-pub enum DiagnosticOutput {
- Default,
- Raw(Box<dyn Write + Send>),
-}
-
// JUSTIFICATION: literally session construction
#[allow(rustc::bad_opt_access)]
pub fn build_session(
@@ -1342,7 +1263,6 @@ pub fn build_session(
local_crate_source_file: Option<PathBuf>,
bundle: Option<Lrc<rustc_errors::FluentBundle>>,
registry: rustc_errors::registry::Registry,
- diagnostics_output: DiagnosticOutput,
driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
target_override: Option<Target>,
@@ -1358,11 +1278,6 @@ pub fn build_session(
let cap_lints_allow = sopts.lint_cap.map_or(false, |cap| cap == lint::Allow);
let can_emit_warnings = !(warnings_allow || cap_lints_allow);
- let write_dest = match diagnostics_output {
- DiagnosticOutput::Default => None,
- DiagnosticOutput::Raw(write) => Some(write),
- };
-
let sysroot = match &sopts.maybe_sysroot {
Some(sysroot) => sysroot.clone(),
None => filesearch::get_or_default_sysroot(),
@@ -1395,8 +1310,7 @@ pub fn build_session(
rustc_errors::DEFAULT_LOCALE_RESOURCES,
sopts.unstable_opts.translate_directionality_markers,
);
- let emitter =
- default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle, write_dest);
+ let emitter = default_emitter(&sopts, registry, source_map.clone(), bundle, fallback_bundle);
let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
emitter,
@@ -1456,8 +1370,7 @@ pub fn build_session(
CguReuseTracker::new_disabled()
};
- let prof =
- SelfProfilerRef::new(self_profiler, sopts.time_passes(), sopts.unstable_opts.time_passes);
+ let prof = SelfProfilerRef::new(self_profiler, sopts.unstable_opts.time_passes);
let ctfe_backtrace = Lock::new(match env::var("RUSTC_CTFE_BACKTRACE") {
Ok(ref val) if val == "immediate" => CtfeBacktrace::Immediate,
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index 9a4f6f9f9..e65b6891e 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -53,6 +53,17 @@ impl NativeLibKind {
NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false,
}
}
+
+ pub fn is_statically_included(&self) -> bool {
+ matches!(self, NativeLibKind::Static { .. })
+ }
+
+ pub fn is_dllimport(&self) -> bool {
+ matches!(
+ self,
+ NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
+ )
+ }
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 7227b193f..48a2ab0f9 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 37b8371a8..bbeabdb55 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -218,7 +218,9 @@ impl<D: Decoder> Decodable<D> for DefIndex {
/// index and a def index.
///
/// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Copy)]
+#[derive(Clone, PartialEq, Eq, Copy)]
+// Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order.
+#[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))]
// On below-64 bit systems we can simply use the derived `Hash` impl
#[cfg_attr(not(target_pointer_width = "64"), derive(Hash))]
#[repr(C)]
@@ -260,6 +262,22 @@ impl Hash for DefId {
}
}
+// Implement the same comparison as derived with the other field order.
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl Ord for DefId {
+ #[inline]
+ fn cmp(&self, other: &DefId) -> std::cmp::Ordering {
+ Ord::cmp(&(self.index, self.krate), &(other.index, other.krate))
+ }
+}
+#[cfg(all(target_pointer_width = "64", target_endian = "big"))]
+impl PartialOrd for DefId {
+ #[inline]
+ fn partial_cmp(&self, other: &DefId) -> Option<std::cmp::Ordering> {
+ Some(Ord::cmp(self, other))
+ }
+}
+
impl DefId {
/// Makes a local `DefId` from the given `DefIndex`.
#[inline]
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index da31b3462..322c7104b 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -15,7 +15,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(if_let_guard)]
#![feature(negative_impls)]
#![feature(min_specialization)]
@@ -299,7 +298,11 @@ impl From<PathBuf> for FileName {
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum FileNameDisplayPreference {
+ /// Display the path after the application of rewrite rules provided via `--remap-path-prefix`.
+ /// This is appropriate for paths that get embedded into files produced by the compiler.
Remapped,
+ /// Display the path before the application of rewrite rules provided via `--remap-path-prefix`.
+ /// This is appropriate for use in user-facing output (such as diagnostics).
Local,
}
@@ -533,9 +536,6 @@ impl Span {
self.data().with_hi(hi)
}
#[inline]
- pub fn ctxt(self) -> SyntaxContext {
- self.data_untracked().ctxt
- }
pub fn eq_ctxt(self, other: Span) -> bool {
self.data_untracked().ctxt == other.data_untracked().ctxt
}
@@ -1637,11 +1637,7 @@ impl SourceFile {
/// number. If the source_file is empty or the position is located before the
/// first line, `None` is returned.
pub fn lookup_line(&self, pos: BytePos) -> Option<usize> {
- self.lines(|lines| match lines.binary_search(&pos) {
- Ok(idx) => Some(idx),
- Err(0) => None,
- Err(idx) => Some(idx - 1),
- })
+ self.lines(|lines| lines.partition_point(|x| x <= &pos).checked_sub(1))
}
pub fn line_bounds(&self, line_index: usize) -> Range<BytePos> {
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 4d94c92d3..f9566eeee 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -853,28 +853,56 @@ impl SourceMap {
}
/// Returns a new span representing the next character after the end-point of this span.
+ /// Special cases:
+ /// - if span is a dummy one, returns the same span
+ /// - if next_point reached the end of source, return span with lo = hi
+ /// - respect multi-byte characters
pub fn next_point(&self, sp: Span) -> Span {
if sp.is_dummy() {
return sp;
}
let start_of_next_point = sp.hi().0;
- let width = self.find_width_of_character_at_span(sp.shrink_to_hi(), true);
- // If the width is 1, then the next span should point to the same `lo` and `hi`. However,
- // in the case of a multibyte character, where the width != 1, the next span should
+ let width = self.find_width_of_character_at_span(sp, true);
+ if width == 0 {
+ return Span::new(sp.hi(), sp.hi(), sp.ctxt(), None);
+ }
+ // If the width is 1, then the next span should only contain the next char besides current ending.
+ // However, in the case of a multibyte character, where the width != 1, the next span should
// span multiple bytes to include the whole character.
let end_of_next_point =
- start_of_next_point.checked_add(width - 1).unwrap_or(start_of_next_point);
+ start_of_next_point.checked_add(width).unwrap_or(start_of_next_point);
- let end_of_next_point = BytePos(cmp::max(sp.lo().0 + 1, end_of_next_point));
+ let end_of_next_point = BytePos(cmp::max(start_of_next_point + 1, end_of_next_point));
Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt(), None)
}
+ /// Returns a new span to check next none-whitespace character or some specified expected character
+ /// If `expect` is none, the first span of non-whitespace character is returned.
+ /// If `expect` presented, the first span of the character `expect` is returned
+ /// Otherwise, the span reached to limit is returned.
+ pub fn span_look_ahead(&self, span: Span, expect: Option<&str>, limit: Option<usize>) -> Span {
+ let mut sp = span;
+ for _ in 0..limit.unwrap_or(100 as usize) {
+ sp = self.next_point(sp);
+ if let Ok(ref snippet) = self.span_to_snippet(sp) {
+ if expect.map_or(false, |es| snippet == es) {
+ break;
+ }
+ if expect.is_none() && snippet.chars().any(|c| !c.is_whitespace()) {
+ break;
+ }
+ }
+ }
+ sp
+ }
+
/// Finds the width of the character, either before or after the end of provided span,
/// depending on the `forwards` parameter.
fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
let sp = sp.data();
- if sp.lo == sp.hi {
+
+ if sp.lo == sp.hi && !forwards {
debug!("find_width_of_character_at_span: early return empty span");
return 1;
}
@@ -908,9 +936,9 @@ impl SourceMap {
let source_len = (local_begin.sf.end_pos - local_begin.sf.start_pos).to_usize();
debug!("find_width_of_character_at_span: source_len=`{:?}`", source_len);
// Ensure indexes are also not malformed.
- if start_index > end_index || end_index > source_len {
+ if start_index > end_index || end_index > source_len - 1 {
debug!("find_width_of_character_at_span: source indexes are malformed");
- return 1;
+ return 0;
}
let src = local_begin.sf.external_src.borrow();
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index 3058ec45a..1fd81018f 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -479,3 +479,48 @@ fn path_prefix_remapping_expand_to_absolute() {
RealFileName::Remapped { local_path: None, virtual_name: path("XYZ/src/main.rs") }
);
}
+
+#[test]
+fn test_next_point() {
+ let sm = SourceMap::new(FilePathMapping::empty());
+ sm.new_source_file(PathBuf::from("example.rs").into(), "a…b".to_string());
+
+ // Dummy spans don't advance.
+ let span = DUMMY_SP;
+ let span = sm.next_point(span);
+ assert_eq!(span.lo().0, 0);
+ assert_eq!(span.hi().0, 0);
+
+ // Span advance respect multi-byte character
+ let span = Span::with_root_ctxt(BytePos(0), BytePos(1));
+ assert_eq!(sm.span_to_snippet(span), Ok("a".to_string()));
+ let span = sm.next_point(span);
+ assert_eq!(sm.span_to_snippet(span), Ok("…".to_string()));
+ assert_eq!(span.lo().0, 1);
+ assert_eq!(span.hi().0, 4);
+
+ // An empty span pointing just before a multi-byte character should
+ // advance to contain the multi-byte character.
+ let span = Span::with_root_ctxt(BytePos(1), BytePos(1));
+ let span = sm.next_point(span);
+ assert_eq!(span.lo().0, 1);
+ assert_eq!(span.hi().0, 4);
+
+ let span = Span::with_root_ctxt(BytePos(1), BytePos(4));
+ let span = sm.next_point(span);
+ assert_eq!(span.lo().0, 4);
+ assert_eq!(span.hi().0, 5);
+
+ // A non-empty span at the last byte should advance to create an empty
+ // span pointing at the end of the file.
+ let span = Span::with_root_ctxt(BytePos(4), BytePos(5));
+ let span = sm.next_point(span);
+ assert_eq!(span.lo().0, 5);
+ assert_eq!(span.hi().0, 5);
+
+ // Empty span pointing just past the last byte.
+ let span = Span::with_root_ctxt(BytePos(5), BytePos(5));
+ let span = sm.next_point(span);
+ assert_eq!(span.lo().0, 5);
+ assert_eq!(span.hi().0, 5);
+}
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index 3ee329e97..b3de67415 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -28,12 +28,17 @@ use rustc_data_structures::fx::FxIndexSet;
/// Inline (compressed) format:
/// - `span.base_or_index == span_data.lo`
/// - `span.len_or_tag == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`)
-/// - `span.ctxt == span_data.ctxt` (must be `<= MAX_CTXT`)
+/// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`)
+///
+/// Interned format with inline `SyntaxContext`:
+/// - `span.base_or_index == index` (indexes into the interner table)
+/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
+/// - `span.ctxt_or_tag == span_data.ctxt` (must be `<= MAX_CTXT`)
///
/// Interned format:
/// - `span.base_or_index == index` (indexes into the interner table)
/// - `span.len_or_tag == LEN_TAG` (high bit set, all other bits are zero)
-/// - `span.ctxt == 0`
+/// - `span.ctxt_or_tag == CTXT_TAG`
///
/// The inline form uses 0 for the tag value (rather than 1) so that we don't
/// need to mask out the tag bit when getting the length, and so that the
@@ -50,10 +55,10 @@ use rustc_data_structures::fx::FxIndexSet;
/// at 3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough
/// for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur
/// dozens of times in a typical crate.
-/// - `ctxt` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
+/// - `ctxt_or_tag` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
/// large `ctxt` values will cause interning. The number of bits needed for
/// `ctxt` values depend partly on the crate size and partly on the form of
-/// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt`,
+/// the code. No crates in `rustc-perf` need more than 15 bits for `ctxt_or_tag`,
/// but larger crates might need more than 16 bits.
///
/// In order to reliably use parented spans in incremental compilation,
@@ -65,15 +70,16 @@ use rustc_data_structures::fx::FxIndexSet;
pub struct Span {
base_or_index: u32,
len_or_tag: u16,
- ctxt_or_zero: u16,
+ ctxt_or_tag: u16,
}
const LEN_TAG: u16 = 0b1000_0000_0000_0000;
const MAX_LEN: u32 = 0b0111_1111_1111_1111;
-const MAX_CTXT: u32 = 0b1111_1111_1111_1111;
+const CTXT_TAG: u32 = 0b1111_1111_1111_1111;
+const MAX_CTXT: u32 = CTXT_TAG - 1;
/// Dummy span, both position and length are zero, syntax context is zero as well.
-pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_zero: 0 };
+pub const DUMMY_SP: Span = Span { base_or_index: 0, len_or_tag: 0, ctxt_or_tag: 0 };
impl Span {
#[inline]
@@ -91,12 +97,13 @@ impl Span {
if len <= MAX_LEN && ctxt2 <= MAX_CTXT && parent.is_none() {
// Inline format.
- Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_zero: ctxt2 as u16 }
+ Span { base_or_index: base, len_or_tag: len as u16, ctxt_or_tag: ctxt2 as u16 }
} else {
// Interned format.
let index =
with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent }));
- Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_zero: 0 }
+ let ctxt_or_tag = if ctxt2 <= MAX_CTXT { ctxt2 } else { CTXT_TAG } as u16;
+ Span { base_or_index: index, len_or_tag: LEN_TAG, ctxt_or_tag }
}
}
@@ -119,16 +126,29 @@ impl Span {
SpanData {
lo: BytePos(self.base_or_index),
hi: BytePos(self.base_or_index + self.len_or_tag as u32),
- ctxt: SyntaxContext::from_u32(self.ctxt_or_zero as u32),
+ ctxt: SyntaxContext::from_u32(self.ctxt_or_tag as u32),
parent: None,
}
} else {
// Interned format.
- debug_assert!(self.ctxt_or_zero == 0);
let index = self.base_or_index;
with_span_interner(|interner| interner.spans[index as usize])
}
}
+
+ /// This function is used as a fast path when decoding the full `SpanData` is not necessary.
+ #[inline]
+ pub fn ctxt(self) -> SyntaxContext {
+ let ctxt_or_tag = self.ctxt_or_tag as u32;
+ if ctxt_or_tag <= MAX_CTXT {
+ // Inline format or interned format with inline ctxt.
+ SyntaxContext::from_u32(ctxt_or_tag)
+ } else {
+ // Interned format.
+ let index = self.base_or_index;
+ with_span_interner(|interner| interner.spans[index as usize].ctxt)
+ }
+ }
}
#[derive(Default)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ae4d1a463..7f16da52b 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -125,7 +125,7 @@ symbols! {
Symbols {
AcqRel,
Acquire,
- AddSubdiagnostic,
+ AddToDiagnostic,
Alignment,
Any,
Arc,
@@ -210,6 +210,7 @@ symbols! {
Implied,
Input,
Into,
+ IntoDiagnostic,
IntoFuture,
IntoIterator,
IoRead,
@@ -223,6 +224,7 @@ symbols! {
Left,
LinkedList,
LintPass,
+ LocalKey,
Mutex,
MutexGuard,
N,
@@ -265,6 +267,7 @@ symbols! {
Rc,
Ready,
Receiver,
+ RefCell,
Relaxed,
Release,
Result,
@@ -273,11 +276,11 @@ symbols! {
Rust,
RustcDecodable,
RustcEncodable,
+ RwLock,
RwLockReadGuard,
RwLockWriteGuard,
Send,
SeqCst,
- SessionDiagnostic,
SliceIndex,
Some,
String,
@@ -396,6 +399,7 @@ symbols! {
assume_init,
async_await,
async_closure,
+ async_fn_in_trait,
atomic,
atomic_mod,
atomics,
@@ -447,6 +451,7 @@ symbols! {
call_once,
caller_location,
capture_disjoint_fields,
+ cause,
cdylib,
ceilf32,
ceilf64,
@@ -781,6 +786,7 @@ symbols! {
globs,
gt,
half_open_range_patterns,
+ half_open_range_patterns_in_slices,
hash,
hexagon_target_feature,
hidden,
@@ -990,7 +996,18 @@ symbols! {
never_type,
never_type_fallback,
new,
+ new_binary,
+ new_debug,
+ new_display,
+ new_lower_exp,
+ new_lower_hex,
+ new_octal,
+ new_pointer,
new_unchecked,
+ new_upper_exp,
+ new_upper_hex,
+ new_v1,
+ new_v1_formatted,
next,
nll,
no,
@@ -1214,9 +1231,7 @@ symbols! {
rust_eh_unregister_frames,
rust_oom,
rustc,
- rustc_access_level,
rustc_allocator,
- rustc_allocator_nounwind,
rustc_allocator_zeroed,
rustc_allow_const_fn_unstable,
rustc_allow_incoherent_impl,
@@ -1242,6 +1257,7 @@ symbols! {
rustc_dump_program_clauses,
rustc_dump_user_substs,
rustc_dump_vtable,
+ rustc_effective_visibility,
rustc_error,
rustc_evaluate_where_clauses,
rustc_expected_cgu_reuse,
@@ -1262,6 +1278,7 @@ symbols! {
rustc_mir,
rustc_must_implement_one_of,
rustc_nonnull_optimization_guaranteed,
+ rustc_nounwind,
rustc_object_lifetime_default,
rustc_on_unimplemented,
rustc_outlives,
@@ -1281,6 +1298,7 @@ symbols! {
rustc_reallocator,
rustc_regions,
rustc_reservation_impl,
+ rustc_safe_intrinsic,
rustc_serialize,
rustc_skip_array_during_method_dispatch,
rustc_specialization_trait,
@@ -1688,6 +1706,7 @@ impl Ident {
/// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
/// non-transparent macros.
/// Technically, this operation strips all transparent marks from ident's syntactic context.
+ #[inline]
pub fn normalize_to_macro_rules(self) -> Ident {
Ident::new(self.name, self.span.normalize_to_macro_rules())
}
@@ -1703,6 +1722,7 @@ impl Ident {
}
impl PartialEq for Ident {
+ #[inline]
fn eq(&self, rhs: &Self) -> bool {
self.name == rhs.name && self.span.eq_ctxt(rhs.span)
}
@@ -1881,6 +1901,13 @@ impl fmt::Display for Symbol {
}
}
+// takes advantage of `str::to_string` specialization
+impl ToString for Symbol {
+ fn to_string(&self) -> String {
+ self.as_str().to_string()
+ }
+}
+
impl<S: Encoder> Encodable<S> for Symbol {
default fn encode(&self, s: &mut S) {
s.emit_str(self.as_str());
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 3db052257..2a29ad6a9 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.2.1"
diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs
index 664d2543f..f4d0751f7 100644
--- a/compiler/rustc_symbol_mangling/src/errors.rs
+++ b/compiler/rustc_symbol_mangling/src/errors.rs
@@ -1,11 +1,11 @@
//! Errors emitted by symbol_mangling.
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
-use rustc_macros::SessionDiagnostic;
+use rustc_macros::Diagnostic;
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(symbol_mangling::test_output)]
+#[derive(Diagnostic)]
+#[diag(symbol_mangling_test_output)]
pub struct TestOutput {
#[primary_span]
pub span: Span,
diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs
index 9d89c9c52..150459ce0 100644
--- a/compiler/rustc_symbol_mangling/src/test.rs
+++ b/compiler/rustc_symbol_mangling/src/test.rs
@@ -26,19 +26,19 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- symbol_names.process_attrs(id.def_id);
+ symbol_names.process_attrs(id.owner_id.def_id);
}
for id in crate_items.trait_items() {
- symbol_names.process_attrs(id.def_id);
+ symbol_names.process_attrs(id.owner_id.def_id);
}
for id in crate_items.impl_items() {
- symbol_names.process_attrs(id.def_id);
+ symbol_names.process_attrs(id.owner_id.def_id);
}
for id in crate_items.foreign_items() {
- symbol_names.process_attrs(id.def_id);
+ symbol_names.process_attrs(id.owner_id.def_id);
}
})
}
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 aa65a72ab..6aa031c83 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
@@ -540,7 +540,7 @@ fn encode_ty<'tcx>(
let mut s = String::new();
let def_id = adt_def.0.did;
if options.contains(EncodeTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c() {
- // For for cross-language CFI support, the encoding must be compatible at the FFI
+ // For cross-language CFI support, the encoding must be compatible at the FFI
// boundary. For instance:
//
// struct type1 {};
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index 79d0ef69b..ecfe6861e 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -7,10 +7,10 @@ use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::print::{Print, Printer};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{
self, EarlyBinder, FloatTy, Instance, IntTy, Ty, TyCtxt, TypeVisitable, UintTy,
};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::kw;
use rustc_target::abi::Integer;
use rustc_target::spec::abi::Abi;
@@ -301,7 +301,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
// Encode impl generic params if the substitutions contain parameters (implying
// polymorphization is enabled) and this isn't an inherent impl.
- if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
+ if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_non_region_param()) {
self = self.path_generic_args(
|this| {
this.path_append_ns(
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 162376af4..fc37fdb1c 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -8,7 +8,8 @@ bitflags = "1.2.1"
tracing = "0.1"
serde_json = "1.0.59"
rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_feature = { path = "../rustc_feature" }
+rustc_index = { path = "../rustc_index" }
rustc_macros = { path = "../rustc_macros" }
rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
-rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index d2fb8c32f..9e5f0e4d1 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -47,7 +47,7 @@ pub enum PassMode {
/// Pass the argument indirectly via a hidden pointer.
/// The `extra_attrs` value, if any, is for the extra data (vtable or length)
/// which indicates that it refers to an unsized rvalue.
- /// `on_stack` defines that the the value should be passed at a fixed
+ /// `on_stack` defines that the value should be passed at a fixed
/// stack offset in accordance to the ABI rather than passed using a
/// pointer. This corresponds to the `byval` LLVM argument attribute.
Indirect { attrs: ArgAttributes, extra_attrs: Option<ArgAttributes>, on_stack: bool },
@@ -740,7 +740,8 @@ impl<'a, Ty> FnAbi<'a, Ty> {
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(ArgAbi<'_, usize>, 56);
static_assert_size!(FnAbi<'_, usize>, 80);
+ // tidy-alphabetical-end
}
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index ec334e588..7171ca7bf 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -1392,7 +1392,7 @@ pub struct PointeeInfo {
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum InitKind {
Zero,
- Uninit,
+ UninitMitigated0x01Fill,
}
/// Trait that needs to be implemented by the higher-level type representation
@@ -1498,72 +1498,4 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
}
}
-
- /// Determines if this type permits "raw" initialization by just transmuting some
- /// memory into an instance of `T`.
- ///
- /// `init_kind` indicates if the memory is zero-initialized or left uninitialized.
- ///
- /// This code is intentionally conservative, and will not detect
- /// * zero init of an enum whose 0 variant does not allow zero initialization
- /// * making uninitialized types who have a full valid range (ints, floats, raw pointers)
- /// * Any form of invalid value being made inside an array (unless the value is uninhabited)
- ///
- /// A strict form of these checks that uses const evaluation exists in
- /// `rustc_const_eval::might_permit_raw_init`, and a tracking issue for making these checks
- /// stricter is <https://github.com/rust-lang/rust/issues/66151>.
- ///
- /// FIXME: Once all the conservatism is removed from here, and the checks are ran by default,
- /// we can use the const evaluation checks always instead.
- pub fn might_permit_raw_init<C>(self, cx: &C, init_kind: InitKind) -> bool
- where
- Self: Copy,
- Ty: TyAbiInterface<'a, C>,
- C: HasDataLayout,
- {
- let scalar_allows_raw_init = move |s: Scalar| -> bool {
- match init_kind {
- InitKind::Zero => {
- // The range must contain 0.
- s.valid_range(cx).contains(0)
- }
- InitKind::Uninit => {
- // The range must include all values.
- s.is_always_valid(cx)
- }
- }
- };
-
- // Check the ABI.
- let valid = match self.abi {
- Abi::Uninhabited => false, // definitely UB
- Abi::Scalar(s) => scalar_allows_raw_init(s),
- Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2),
- Abi::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s),
- Abi::Aggregate { .. } => true, // Fields are checked below.
- };
- if !valid {
- // This is definitely not okay.
- return false;
- }
-
- // If we have not found an error yet, we need to recursively descend into fields.
- match &self.fields {
- FieldsShape::Primitive | FieldsShape::Union { .. } => {}
- FieldsShape::Array { .. } => {
- // FIXME(#66151): For now, we are conservative and do not check arrays by default.
- }
- FieldsShape::Arbitrary { offsets, .. } => {
- for idx in 0..offsets.len() {
- if !self.field(cx, idx).might_permit_raw_init(cx, init_kind) {
- // We found a field that is unhappy with this kind of initialization.
- return false;
- }
- }
- }
- }
-
- // FIXME(#66151): For now, we are conservative and do not check `self.variants`.
- true
- }
}
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index a7deab9d2..aaba0d7f0 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -11,7 +11,6 @@
#![feature(assert_matches)]
#![feature(associated_type_bounds)]
#![feature(exhaustive_patterns)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
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 1dad07a9a..2d2671549 100644
--- a/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs
@@ -1,11 +1,11 @@
use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{FramePointer, LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "arm64-apple-ios14.0-macabi";
let mut base = opts("ios", Arch::Arm64_macabi);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-target", llvm_target]);
+ base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
Target {
llvm_target: llvm_target.into(),
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 b301ce68a..529e98d2c 100644
--- a/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/aarch64_nintendo_switch_freestanding.rs
@@ -1,4 +1,4 @@
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelroLevel, Target, TargetOptions};
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelroLevel, Target, TargetOptions};
const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding_linker_script.ld");
@@ -10,7 +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 {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
link_script: Some(LINKER_SCRIPT.into()),
os: "horizon".into(),
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
index d3fd7051a..4ae6d4120 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -6,11 +6,11 @@
//
// For example, `-C target-cpu=cortex-a53`.
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+strict-align,+neon,+fp-armv8".into(),
relocation_model: RelocModel::Static,
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 6316abe1b..2385cb69a 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none_softfloat.rs
@@ -6,12 +6,12 @@
//
// For example, `-C target-cpu=cortex-a53`.
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
abi: "softfloat".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+strict-align,-neon,-fp-armv8".into(),
relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
index 3ef04c676..817ff2422 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_uefi.rs
@@ -2,13 +2,13 @@
// uefi-base module for generic UEFI options.
use super::uefi_msvc_base;
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = uefi_msvc_base::opts();
base.max_atomic_width = Some(128);
- base.add_pre_link_args(LinkerFlavor::Msvc, &["/machine:arm64"]);
+ base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/machine:arm64"]);
Target {
llvm_target: "aarch64-unknown-windows".into(),
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index 337554dc9..ce45fa139 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -1,6 +1,8 @@
use std::fmt;
use rustc_macros::HashStable_Generic;
+use rustc_span::symbol::sym;
+use rustc_span::{Span, Symbol};
#[cfg(test)]
mod tests;
@@ -94,6 +96,142 @@ pub fn all_names() -> Vec<&'static str> {
AbiDatas.iter().map(|d| d.name).collect()
}
+pub fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
+ AbiDatas
+ .iter()
+ .map(|d| d.name)
+ .filter(|name| is_enabled(features, span, name).is_ok())
+ .collect()
+}
+
+pub enum AbiDisabled {
+ Unstable { feature: Symbol, explain: &'static str },
+ Unrecognized,
+}
+
+pub fn is_enabled(
+ features: &rustc_feature::Features,
+ span: Span,
+ name: &str,
+) -> Result<(), AbiDisabled> {
+ let s = is_stable(name);
+ if let Err(AbiDisabled::Unstable { feature, .. }) = s {
+ if features.enabled(feature) || span.allows_unstable(feature) {
+ return Ok(());
+ }
+ }
+ s
+}
+
+pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
+ match name {
+ // Stable
+ "Rust" | "C" | "cdecl" | "stdcall" | "fastcall" | "aapcs" | "win64" | "sysv64"
+ | "system" => Ok(()),
+ "rust-intrinsic" => Err(AbiDisabled::Unstable {
+ feature: sym::intrinsics,
+ explain: "intrinsics are subject to change",
+ }),
+ "platform-intrinsic" => Err(AbiDisabled::Unstable {
+ feature: sym::platform_intrinsics,
+ explain: "platform intrinsics are experimental and possibly buggy",
+ }),
+ "vectorcall" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_vectorcall,
+ explain: "vectorcall is experimental and subject to change",
+ }),
+ "thiscall" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_thiscall,
+ explain: "thiscall is experimental and subject to change",
+ }),
+ "rust-call" => Err(AbiDisabled::Unstable {
+ feature: sym::unboxed_closures,
+ explain: "rust-call ABI is subject to change",
+ }),
+ "rust-cold" => Err(AbiDisabled::Unstable {
+ feature: sym::rust_cold_cc,
+ explain: "rust-cold is experimental and subject to change",
+ }),
+ "ptx-kernel" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_ptx,
+ explain: "PTX ABIs are experimental and subject to change",
+ }),
+ "unadjusted" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_unadjusted,
+ explain: "unadjusted ABI is an implementation detail and perma-unstable",
+ }),
+ "msp430-interrupt" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_msp430_interrupt,
+ explain: "msp430-interrupt ABI is experimental and subject to change",
+ }),
+ "x86-interrupt" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_x86_interrupt,
+ explain: "x86-interrupt ABI is experimental and subject to change",
+ }),
+ "amdgpu-kernel" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_amdgpu_kernel,
+ explain: "amdgpu-kernel ABI is experimental and subject to change",
+ }),
+ "avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_avr_interrupt,
+ explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
+ }),
+ "efiapi" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_efiapi,
+ explain: "efiapi ABI is experimental and subject to change",
+ }),
+ "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
+ feature: sym::abi_c_cmse_nonsecure_call,
+ explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
+ }),
+ "C-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "C-unwind ABI is experimental and subject to change",
+ }),
+ "stdcall-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "stdcall-unwind ABI is experimental and subject to change",
+ }),
+ "system-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "system-unwind ABI is experimental and subject to change",
+ }),
+ "thiscall-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "thiscall-unwind ABI is experimental and subject to change",
+ }),
+ "cdecl-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "cdecl-unwind ABI is experimental and subject to change",
+ }),
+ "fastcall-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "fastcall-unwind ABI is experimental and subject to change",
+ }),
+ "vectorcall-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "vectorcall-unwind ABI is experimental and subject to change",
+ }),
+ "aapcs-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "aapcs-unwind ABI is experimental and subject to change",
+ }),
+ "win64-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "win64-unwind ABI is experimental and subject to change",
+ }),
+ "sysv64-unwind" => Err(AbiDisabled::Unstable {
+ feature: sym::c_unwind,
+ explain: "sysv64-unwind ABI is experimental and subject to change",
+ }),
+ "wasm" => Err(AbiDisabled::Unstable {
+ feature: sym::wasm_abi,
+ explain: "wasm ABI is experimental and subject to change",
+ }),
+ _ => Err(AbiDisabled::Unrecognized),
+ }
+}
+
impl Abi {
/// Default ABI chosen for `extern fn` declarations without an explicit ABI.
pub const FALLBACK: Abi = Abi::C { unwind: false };
diff --git a/compiler/rustc_target/src/spec/android_base.rs b/compiler/rustc_target/src/spec/android_base.rs
index 9f3e0bd5e..9c1df1a06 100644
--- a/compiler/rustc_target/src/spec/android_base.rs
+++ b/compiler/rustc_target/src/spec/android_base.rs
@@ -1,10 +1,12 @@
-use crate::spec::TargetOptions;
+use crate::spec::{SanitizerSet, TargetOptions};
pub fn opts() -> TargetOptions {
let mut base = super::linux_base::opts();
base.os = "android".into();
+ base.is_like_android = true;
base.default_dwarf_version = 2;
base.has_thread_local = false;
+ base.supported_sanitizers = SanitizerSet::ADDRESS;
// This is for backward compatibility, see https://github.com/rust-lang/rust/issues/49867
// for context. (At that time, there was no `-C force-unwind-tables`, so the only solution
// was to always emit `uwtable`).
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 2c72bf88a..40bc59ca1 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -1,7 +1,7 @@
use std::{borrow::Cow, env};
-use crate::spec::{cvs, DebuginfoKind, FramePointer, SplitDebuginfo, StaticCow, TargetOptions};
-use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor};
+use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs};
+use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions};
fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
let platform_name: StaticCow<str> = match abi {
@@ -20,17 +20,16 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
.into();
let mut args = TargetOptions::link_args(
- LinkerFlavor::Lld(LldFlavor::Ld64),
+ LinkerFlavor::Darwin(Cc::No, Lld::No),
&["-arch", arch, "-platform_version"],
);
- // Manually add owned args unsupported by link arg building helpers.
- args.entry(LinkerFlavor::Lld(LldFlavor::Ld64)).or_default().extend([
- platform_name,
- platform_version.clone(),
- platform_version,
- ]);
+ super::add_link_args_iter(
+ &mut args,
+ LinkerFlavor::Darwin(Cc::No, Lld::No),
+ [platform_name, platform_version.clone(), platform_version].into_iter(),
+ );
if abi != "macabi" {
- super::add_link_args(&mut args, LinkerFlavor::Gcc, &["-arch", arch]);
+ super::add_link_args(&mut args, LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-arch", arch]);
}
args
@@ -55,11 +54,11 @@ pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOp
TargetOptions {
os: os.into(),
vendor: "apple".into(),
+ linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
// macOS has -dead_strip, which doesn't rely on function_sections
function_sections: false,
dynamic_linking: true,
pre_link_args: pre_link_args(os, arch, abi),
- linker_is_gnu: false,
families: cvs!["unix"],
is_like_osx: true,
default_dwarf_version: 2,
@@ -71,7 +70,6 @@ pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOp
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
eh_frame_header: false,
- lld_flavor: LldFlavor::Ld64,
debuginfo_kind: DebuginfoKind::DwarfDsym,
// The historical default for macOS targets is to run `dsymutil` which
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
index 511693abe..8c65d6afc 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabi.rs
@@ -1,8 +1,7 @@
// Targets the Big endian Cortex-R4/R5 processor (ARMv7-R)
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -13,7 +12,7 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabi".into(),
endian: Endian::Big,
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
index 5df4a0a15..7013bc60d 100644
--- a/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armebv7r_none_eabihf.rs
@@ -1,8 +1,7 @@
// Targets the Cortex-R4F/R5F processor (ARMv7-R)
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -13,7 +12,7 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabihf".into(),
endian: Endian::Big,
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
index 797dfe52b..7ac1aab3b 100644
--- a/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_none_eabi.rs
@@ -16,7 +16,7 @@
//! The default link script is very likely wrong, so you should use
//! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
-use crate::spec::{cvs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -35,7 +35,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: "eabi".into(),
- linker_flavor: LinkerFlavor::Ld,
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No),
linker: Some("arm-none-eabi-ld".into()),
asm_args: cvs!["-mthumb-interwork", "-march=armv4t", "-mlittle-endian",],
// Force-enable 32-bit atomics, which allows the use of atomic load/store only.
diff --git a/compiler/rustc_target/src/spec/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/armv5te_none_eabi.rs
new file mode 100644
index 000000000..dfd27b654
--- /dev/null
+++ b/compiler/rustc_target/src/spec/armv5te_none_eabi.rs
@@ -0,0 +1,41 @@
+//! Targets the ARMv5TE, with code as `a32` code by default.
+
+use crate::spec::{cvs, FramePointer, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "armv5te-none-eabi".into(),
+ pointer_width: 32,
+ arch: "arm".into(),
+ /* Data layout args are '-' separated:
+ * little endian
+ * stack is 64-bit aligned (EABI)
+ * pointers are 32-bit
+ * i64 must be 64-bit aligned (EABI)
+ * mangle names with ELF style
+ * native integers are 32-bit
+ * All other elements are default
+ */
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // extra args passed to the external assembler (assuming `arm-none-eabi-as`):
+ // * activate t32/a32 interworking
+ // * use arch ARMv5TE
+ // * use little-endian
+ asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
+ // minimum extra features, these cannot be disabled via -C
+ // Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
+ // The resulting atomics are ABI incompatible with atomics backed by libatomic.
+ features: "+soft-float,+strict-align,+atomics-32".into(),
+ frame_pointer: FramePointer::MayOmit,
+ main_needs_argc_argv: false,
+ // don't have atomic compare-and-swap
+ atomic_cas: false,
+ has_thumb_interworking: true,
+
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
index 1bba39393..40ec6f961 100644
--- a/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/armv6k_nintendo_3ds.rs
@@ -1,4 +1,4 @@
-use crate::spec::{cvs, LinkerFlavor, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
/// A base target for Nintendo 3DS devices using the devkitARM toolchain.
///
@@ -6,7 +6,7 @@ use crate::spec::{cvs, LinkerFlavor, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
let pre_link_args = TargetOptions::link_args(
- LinkerFlavor::Gcc,
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-specs=3dsx.specs", "-mtune=mpcore", "-mfloat-abi=hard", "-mtp=soft"],
);
@@ -21,7 +21,6 @@ pub fn target() -> Target {
env: "newlib".into(),
vendor: "nintendo".into(),
abi: "eabihf".into(),
- linker_flavor: LinkerFlavor::Gcc,
cpu: "mpcore".into(),
families: cvs!["unix"],
linker: Some("arm-none-eabi-gcc".into()),
diff --git a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
index 38c117a49..402e0fd92 100644
--- a/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_linux_androideabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, Target, TargetOptions};
// This target if is for the baseline of the Android v7a ABI
// in thumb mode. It's named armv7-* instead of thumbv7-*
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, SanitizerSet, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::android_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
Target {
llvm_target: "armv7-none-linux-android".into(),
pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
index cb5cbe158..4e20fb325 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabi.rs
@@ -14,12 +14,12 @@
// - `relocation-model` set to `static`; also no PIE, no relro and no dynamic
// linking. rationale: matches `thumb` targets
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
abi: "eabi".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+v7,+thumb2,+soft-float,-neon,+strict-align".into(),
relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
index fb5dd2e75..ae70129ae 100644
--- a/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7a_none_eabihf.rs
@@ -5,12 +5,12 @@
// changes (list in `armv7a_none_eabi.rs`) to bring it closer to the bare-metal
// `thumb` & `aarch64` targets.
-use super::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
abi: "eabihf".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features: "+v7,+vfp3,-d32,+thumb2,-neon,+strict-align".into(),
relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
index 5f1da09b3..25f301ccc 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabi.rs
@@ -1,7 +1,6 @@
// Targets the Little-endian Cortex-R4/R5 processor (ARMv7-R)
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -12,7 +11,7 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabi".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
index 0038ed0df..40449759d 100644
--- a/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/armv7r_none_eabihf.rs
@@ -1,7 +1,6 @@
// Targets the Little-endian Cortex-R4F/R5F processor (ARMv7-R)
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -12,7 +11,7 @@ pub fn target() -> Target {
options: TargetOptions {
abi: "eabihf".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
panic_strategy: PanicStrategy::Abort,
diff --git a/compiler/rustc_target/src/spec/avr_gnu_base.rs b/compiler/rustc_target/src/spec/avr_gnu_base.rs
index 8cca33cc4..9c3406b53 100644
--- a/compiler/rustc_target/src/spec/avr_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/avr_gnu_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, RelocModel, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
/// A base target for AVR devices using the GNU toolchain.
///
@@ -17,8 +17,11 @@ pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
linker: Some("avr-gcc".into()),
eh_frame_header: false,
- pre_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &[mmcu]),
- late_link_args: TargetOptions::link_args(LinkerFlavor::Gcc, &["-lgcc"]),
+ pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]),
+ late_link_args: TargetOptions::link_args(
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ &["-lgcc"],
+ ),
max_atomic_width: Some(0),
atomic_cas: false,
relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/fuchsia_base.rs b/compiler/rustc_target/src/spec/fuchsia_base.rs
index 962ad0c66..4c2775850 100644
--- a/compiler/rustc_target/src/spec/fuchsia_base.rs
+++ b/compiler/rustc_target/src/spec/fuchsia_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{crt_objects, cvs, LinkOutputKind, LinkerFlavor, LldFlavor, TargetOptions};
+use crate::spec::{crt_objects, cvs, Cc, LinkOutputKind, LinkerFlavor, Lld, TargetOptions};
pub fn opts() -> TargetOptions {
// This mirrors the linker options provided by clang. We presume lld for
@@ -7,7 +7,7 @@ pub fn opts() -> TargetOptions {
//
// https://github.com/llvm/llvm-project/blob/db9322b2066c55254e7691efeab863f43bfcc084/clang/lib/Driver/ToolChains/Fuchsia.cpp#L31
let pre_link_args = TargetOptions::link_args(
- LinkerFlavor::Ld,
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
"--build-id",
"--hash-style=gnu",
@@ -25,7 +25,7 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "fuchsia".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
dynamic_linking: true,
families: cvs!["unix"],
diff --git a/compiler/rustc_target/src/spec/hermit_base.rs b/compiler/rustc_target/src/spec/hermit_base.rs
index 562ccef7e..dd9991381 100644
--- a/compiler/rustc_target/src/spec/hermit_base.rs
+++ b/compiler/rustc_target/src/spec/hermit_base.rs
@@ -1,14 +1,14 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, TargetOptions, TlsModel};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, TargetOptions, TlsModel};
pub fn opts() -> TargetOptions {
let pre_link_args = TargetOptions::link_args(
- LinkerFlavor::Ld,
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
&["--build-id", "--hash-style=gnu", "--Bstatic"],
);
TargetOptions {
os: "hermit".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
has_thread_local: true,
pre_link_args,
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 2a24e4459..3aad05eb2 100644
--- a/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/hexagon_unknown_linux_musl.rs
@@ -1,4 +1,4 @@
-use crate::spec::Target;
+use crate::spec::{Cc, LinkerFlavor, Target};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
@@ -9,7 +9,7 @@ pub fn target() -> Target {
base.crt_static_default = false;
base.has_rpath = true;
- base.linker_is_gnu = false;
+ base.linker_flavor = LinkerFlavor::Unix(Cc::Yes);
base.c_enum_min_bits = 8;
diff --git a/compiler/rustc_target/src/spec/i386_apple_ios.rs b/compiler/rustc_target/src/spec/i386_apple_ios.rs
index 8b6266c58..b85214a9c 100644
--- a/compiler/rustc_target/src/spec/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/i386_apple_ios.rs
@@ -14,8 +14,7 @@ pub fn target() -> Target {
arch: "x86".into(),
options: TargetOptions {
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
..base
},
}
diff --git a/compiler/rustc_target/src/spec/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
index 5e9ceb844..15607c12e 100644
--- a/compiler/rustc_target/src/spec/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/i686_apple_darwin.rs
@@ -1,14 +1,13 @@
-use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
// ld64 only understand i386 and not i686
let mut base = super::apple_base::opts("macos", "i386", "");
base.cpu = "yonah".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
base.frame_pointer = FramePointer::Always;
// Clang automatically chooses a more specific target based on
diff --git a/compiler/rustc_target/src/spec/i686_linux_android.rs b/compiler/rustc_target/src/spec/i686_linux_android.rs
index bdaf5c990..c7c30c239 100644
--- a/compiler/rustc_target/src/spec/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/i686_linux_android.rs
@@ -11,8 +11,7 @@ pub fn target() -> Target {
// https://developer.android.com/ndk/guides/abis.html#x86
base.cpu = "pentiumpro".into();
base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-linux-android".into(),
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
index 631865439..7a1113875 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, LinkerFlavor, Target};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_gnu_base::opts();
@@ -9,8 +9,11 @@ pub fn target() -> Target {
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
- base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["-m", "i386pe", "--large-address-aware"],
+ );
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,--large-address-aware"]);
Target {
llvm_target: "i686-pc-windows-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
index f4ceaa1ca..db4c00dc6 100644
--- a/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/i686_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_msvc_base::opts();
@@ -6,7 +6,7 @@ pub fn target() -> Target {
base.max_atomic_width = Some(64);
base.add_pre_link_args(
- LinkerFlavor::Msvc,
+ LinkerFlavor::Msvc(Lld::No),
&[
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
diff --git a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
index aff284bf2..35ca78034 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_freebsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-znotext"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
index 87aa74e40..e6b72336c 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_haiku.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::haiku_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-haiku".into(),
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
index 765803d16..73e536a7e 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_gnu.rs
@@ -1,12 +1,12 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.supported_sanitizers = SanitizerSet::ADDRESS;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
index d94928043..3825082ba 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_linux_musl.rs
@@ -1,12 +1,11 @@
-use crate::spec::{FramePointer, LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-Wl,-melf_i386"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
+ base.stack_probes = StackProbeType::X86;
// The unwinder used by i686-unknown-linux-musl, the LLVM libunwind
// implementation, apparently relies on frame pointers existing... somehow.
diff --git a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
index 8de698b51..b191996c7 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_netbsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::netbsd_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-netbsdelf".into(),
diff --git a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
index 7f25a1a16..8babe5597 100644
--- a/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/i686_unknown_openbsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::openbsd_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "-fuse-ld=lld"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
index d52810d2f..a3e325698 100644
--- a/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/i686_uwp_windows_gnu.rs
@@ -1,4 +1,4 @@
-use crate::spec::{FramePointer, LinkerFlavor, Target};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_uwp_gnu_base::opts();
@@ -8,8 +8,11 @@ pub fn target() -> Target {
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
- base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pe", "--large-address-aware"]);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-Wl,--large-address-aware"]);
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["-m", "i386pe", "--large-address-aware"],
+ );
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,--large-address-aware"]);
Target {
llvm_target: "i686-pc-windows-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
index f62404e82..b5cfdfceb 100644
--- a/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/i686_wrs_vxworks.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::vxworks_base::opts();
base.cpu = "pentium4".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "i686-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/illumos_base.rs b/compiler/rustc_target/src/spec/illumos_base.rs
index 77e000474..8ac351584 100644
--- a/compiler/rustc_target/src/spec/illumos_base.rs
+++ b/compiler/rustc_target/src/spec/illumos_base.rs
@@ -1,8 +1,8 @@
-use crate::spec::{cvs, FramePointer, LinkerFlavor, TargetOptions};
+use crate::spec::{cvs, Cc, FramePointer, LinkerFlavor, TargetOptions};
pub fn opts() -> TargetOptions {
let late_link_args = TargetOptions::link_args(
- LinkerFlavor::Gcc,
+ LinkerFlavor::Unix(Cc::Yes),
&[
// The illumos libc contains a stack unwinding implementation, as
// does libgcc_s. The latter implementation includes several
@@ -30,7 +30,7 @@ pub fn opts() -> TargetOptions {
has_rpath: true,
families: cvs!["unix"],
is_like_solaris: true,
- linker_is_gnu: false,
+ linker_flavor: LinkerFlavor::Unix(Cc::Yes),
limit_rdylib_exports: false, // Linker doesn't support this
frame_pointer: FramePointer::Always,
eh_frame_header: false,
diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs
index b7bc1072b..3a4d83fad 100644
--- a/compiler/rustc_target/src/spec/l4re_base.rs
+++ b/compiler/rustc_target/src/spec/l4re_base.rs
@@ -1,13 +1,12 @@
-use crate::spec::{cvs, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions};
pub fn opts() -> TargetOptions {
TargetOptions {
os: "l4re".into(),
env: "uclibc".into(),
- linker_flavor: LinkerFlavor::Ld,
+ linker_flavor: LinkerFlavor::Unix(Cc::No),
panic_strategy: PanicStrategy::Abort,
linker: Some("l4-bender".into()),
- linker_is_gnu: false,
families: cvs!["unix"],
relocation_model: RelocModel::Static,
..Default::default()
diff --git a/compiler/rustc_target/src/spec/linux_kernel_base.rs b/compiler/rustc_target/src/spec/linux_kernel_base.rs
index 0f5d85205..f41533a95 100644
--- a/compiler/rustc_target/src/spec/linux_kernel_base.rs
+++ b/compiler/rustc_target/src/spec/linux_kernel_base.rs
@@ -6,8 +6,7 @@ pub fn opts() -> TargetOptions {
env: "gnu".into(),
disable_redzone: true,
panic_strategy: PanicStrategy::Abort,
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
frame_pointer: FramePointer::Always,
position_independent_executables: true,
needs_plt: true,
diff --git a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
index cfc8ec21c..75beb91b1 100644
--- a/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/mipsel_sony_psp.rs
@@ -1,11 +1,13 @@
-use crate::spec::{cvs, Target, TargetOptions};
-use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions};
// The PSP has custom linker requirements.
const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
pub fn target() -> Target {
- let pre_link_args = TargetOptions::link_args(LinkerFlavor::Ld, &["--emit-relocs", "--nmagic"]);
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["--emit-relocs", "--nmagic"],
+ );
Target {
llvm_target: "mipsel-sony-psp".into(),
@@ -16,7 +18,7 @@ pub fn target() -> Target {
options: TargetOptions {
os: "psp".into(),
vendor: "sony".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
cpu: "mips2".into(),
linker: Some("rust-lld".into()),
relocation_model: RelocModel::Static,
diff --git a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
index fe2aa2de8..43b01e7a0 100644
--- a/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/mipsel_unknown_none.rs
@@ -2,8 +2,7 @@
//!
//! Can be used for MIPS M4K core (e.g. on PIC32MX devices)
-use crate::spec::{LinkerFlavor, LldFlavor, RelocModel};
-use crate::spec::{PanicStrategy, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -13,7 +12,7 @@ pub fn target() -> Target {
arch: "mips".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
cpu: "mips32r2".into(),
features: "+mips32r2,+soft-float,+noabicalls".into(),
max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index dc16739bd..8909cf33a 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -90,17 +90,73 @@ mod windows_msvc_base;
mod windows_uwp_gnu_base;
mod windows_uwp_msvc_base;
+/// Linker is called through a C/C++ compiler.
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum Cc {
+ Yes,
+ No,
+}
+
+/// Linker is LLD.
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
+pub enum Lld {
+ Yes,
+ No,
+}
+
+/// All linkers have some kinds of command line interfaces and rustc needs to know which commands
+/// to use with each of them. So we cluster all such interfaces into a (somewhat arbitrary) number
+/// of classes that we call "linker flavors".
+///
+/// Technically, it's not even necessary, we can nearly always infer the flavor from linker name
+/// and target properties like `is_like_windows`/`is_like_osx`/etc. However, the PRs originally
+/// introducing `-Clinker-flavor` (#40018 and friends) were aiming to reduce this kind of inference
+/// and provide something certain and explicitly specified instead, and that design goal is still
+/// relevant now.
+///
+/// The second goal is to keep the number of flavors to the minimum if possible.
+/// LLD somewhat forces our hand here because that linker is self-sufficent only if its executable
+/// (`argv[0]`) is named in specific way, otherwise it doesn't work and requires a
+/// `-flavor LLD_FLAVOR` argument to choose which logic to use. Our shipped `rust-lld` in
+/// particular is not named in such specific way, so it needs the flavor option, so we make our
+/// linker flavors sufficiently fine-grained to satisfy LLD without inferring its flavor from other
+/// target properties, in accordance with the first design goal.
+///
+/// The first component of the flavor is tightly coupled with the compilation target,
+/// while the `Cc` and `Lld` flags can vary withing the same target.
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum LinkerFlavor {
- Gcc,
- Ld,
- Lld(LldFlavor),
- Msvc,
+ /// Unix-like linker with GNU extensions (both naked and compiler-wrapped forms).
+ /// Besides similar "default" Linux/BSD linkers this also includes Windows/GNU linker,
+ /// which is somewhat different because it doesn't produce ELFs.
+ Gnu(Cc, Lld),
+ /// Unix-like linker for Apple targets (both naked and compiler-wrapped forms).
+ /// Extracted from the "umbrella" `Unix` flavor due to its corresponding LLD flavor.
+ Darwin(Cc, Lld),
+ /// Unix-like linker for Wasm targets (both naked and compiler-wrapped forms).
+ /// Extracted from the "umbrella" `Unix` flavor due to its corresponding LLD flavor.
+ /// Non-LLD version does not exist, so the lld flag is currently hardcoded here.
+ WasmLld(Cc),
+ /// Basic Unix-like linker for "any other Unix" targets (Solaris/illumos, L4Re, MSP430, etc),
+ /// possibly with non-GNU extensions (both naked and compiler-wrapped forms).
+ /// LLD doesn't support any of these.
+ Unix(Cc),
+ /// MSVC-style linker for Windows and UEFI, LLD supports it.
+ Msvc(Lld),
+ /// Emscripten Compiler Frontend, a wrapper around `WasmLld(Cc::Yes)` that has a different
+ /// interface and produces some additional JavaScript output.
EmCc,
+ // Below: other linker-like tools with unique interfaces for exotic targets.
+ /// Linker tool for BPF.
Bpf,
+ /// Linker tool for Nvidia PTX.
Ptx,
}
+/// Linker flavors available externally through command line (`-Clinker-flavor`)
+/// or json target specifications.
+/// FIXME: This set has accumulated historically, bring it more in line with the internal
+/// linker flavors (`LinkerFlavor`).
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum LinkerFlavorCli {
Gcc,
@@ -148,12 +204,32 @@ impl ToJson for LldFlavor {
}
impl LinkerFlavor {
- pub fn from_cli(cli: LinkerFlavorCli) -> LinkerFlavor {
+ pub fn from_cli(cli: LinkerFlavorCli, target: &TargetOptions) -> LinkerFlavor {
+ Self::from_cli_impl(cli, target.linker_flavor.lld_flavor(), target.linker_flavor.is_gnu())
+ }
+
+ /// The passed CLI flavor is preferred over other args coming from the default target spec,
+ /// so this function can produce a flavor that is incompatible with the current target.
+ /// FIXME: Produce errors when `-Clinker-flavor` is set to something incompatible
+ /// with the current target.
+ fn from_cli_impl(cli: LinkerFlavorCli, lld_flavor: LldFlavor, is_gnu: bool) -> LinkerFlavor {
match cli {
- LinkerFlavorCli::Gcc => LinkerFlavor::Gcc,
- LinkerFlavorCli::Ld => LinkerFlavor::Ld,
- LinkerFlavorCli::Lld(lld_flavor) => LinkerFlavor::Lld(lld_flavor),
- LinkerFlavorCli::Msvc => LinkerFlavor::Msvc,
+ LinkerFlavorCli::Gcc => match lld_flavor {
+ LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::Yes, Lld::No),
+ LldFlavor::Wasm => LinkerFlavor::WasmLld(Cc::Yes),
+ LldFlavor::Ld | LldFlavor::Link => LinkerFlavor::Unix(Cc::Yes),
+ },
+ LinkerFlavorCli::Ld => match lld_flavor {
+ LldFlavor::Ld if is_gnu => LinkerFlavor::Gnu(Cc::No, Lld::No),
+ LldFlavor::Ld64 => LinkerFlavor::Darwin(Cc::No, Lld::No),
+ LldFlavor::Ld | LldFlavor::Wasm | LldFlavor::Link => LinkerFlavor::Unix(Cc::No),
+ },
+ LinkerFlavorCli::Lld(LldFlavor::Ld) => LinkerFlavor::Gnu(Cc::No, Lld::Yes),
+ LinkerFlavorCli::Lld(LldFlavor::Ld64) => LinkerFlavor::Darwin(Cc::No, Lld::Yes),
+ LinkerFlavorCli::Lld(LldFlavor::Wasm) => LinkerFlavor::WasmLld(Cc::No),
+ LinkerFlavorCli::Lld(LldFlavor::Link) => LinkerFlavor::Msvc(Lld::Yes),
+ LinkerFlavorCli::Msvc => LinkerFlavor::Msvc(Lld::No),
LinkerFlavorCli::Em => LinkerFlavor::EmCc,
LinkerFlavorCli::BpfLinker => LinkerFlavor::Bpf,
LinkerFlavorCli::PtxLinker => LinkerFlavor::Ptx,
@@ -162,15 +238,40 @@ impl LinkerFlavor {
fn to_cli(self) -> LinkerFlavorCli {
match self {
- LinkerFlavor::Gcc => LinkerFlavorCli::Gcc,
- LinkerFlavor::Ld => LinkerFlavorCli::Ld,
- LinkerFlavor::Lld(lld_flavor) => LinkerFlavorCli::Lld(lld_flavor),
- LinkerFlavor::Msvc => LinkerFlavorCli::Msvc,
+ LinkerFlavor::Gnu(Cc::Yes, _)
+ | LinkerFlavor::Darwin(Cc::Yes, _)
+ | LinkerFlavor::WasmLld(Cc::Yes)
+ | LinkerFlavor::Unix(Cc::Yes) => LinkerFlavorCli::Gcc,
+ LinkerFlavor::Gnu(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld),
+ LinkerFlavor::Darwin(_, Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Ld64),
+ LinkerFlavor::WasmLld(..) => LinkerFlavorCli::Lld(LldFlavor::Wasm),
+ LinkerFlavor::Gnu(..) | LinkerFlavor::Darwin(..) | LinkerFlavor::Unix(..) => {
+ LinkerFlavorCli::Ld
+ }
+ LinkerFlavor::Msvc(Lld::Yes) => LinkerFlavorCli::Lld(LldFlavor::Link),
+ LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc,
LinkerFlavor::EmCc => LinkerFlavorCli::Em,
LinkerFlavor::Bpf => LinkerFlavorCli::BpfLinker,
LinkerFlavor::Ptx => LinkerFlavorCli::PtxLinker,
}
}
+
+ pub fn lld_flavor(self) -> LldFlavor {
+ match self {
+ LinkerFlavor::Gnu(..)
+ | LinkerFlavor::Unix(..)
+ | LinkerFlavor::EmCc
+ | LinkerFlavor::Bpf
+ | LinkerFlavor::Ptx => LldFlavor::Ld,
+ LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
+ LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
+ LinkerFlavor::Msvc(..) => LldFlavor::Link,
+ }
+ }
+
+ pub fn is_gnu(self) -> bool {
+ matches!(self, LinkerFlavor::Gnu(..))
+ }
}
macro_rules! linker_flavor_cli_impls {
@@ -635,6 +736,10 @@ pub enum StackProbeType {
}
impl StackProbeType {
+ // LLVM X86 targets (ix86 and x86_64) can use inline-asm stack probes starting with LLVM 16.
+ // Notable past issues were rust#83139 (fixed in 14) and rust#84667 (fixed in 16).
+ const X86: Self = Self::InlineOrCall { min_llvm_version_for_inline: (16, 0, 0) };
+
fn from_json(json: &Json) -> Result<Self, String> {
let object = json.as_object().ok_or_else(|| "expected a JSON object")?;
let kind = object
@@ -1120,6 +1225,8 @@ supported_targets! {
("mipsel-unknown-none", mipsel_unknown_none),
("thumbv4t-none-eabi", thumbv4t_none_eabi),
("armv4t-none-eabi", armv4t_none_eabi),
+ ("thumbv5te-none-eabi", thumbv5te_none_eabi),
+ ("armv5te-none-eabi", armv5te_none_eabi),
("aarch64_be-unknown-linux-gnu", aarch64_be_unknown_linux_gnu),
("aarch64-unknown-linux-gnu_ilp32", aarch64_unknown_linux_gnu_ilp32),
@@ -1252,16 +1359,11 @@ pub struct TargetOptions {
/// Linker to invoke
pub linker: Option<StaticCow<str>>,
/// Default linker flavor used if `-C linker-flavor` or `-C linker` are not passed
- /// on the command line. Defaults to `LinkerFlavor::Gcc`.
+ /// on the command line. Defaults to `LinkerFlavor::Gnu(Cc::Yes, Lld::No)`.
pub linker_flavor: LinkerFlavor,
linker_flavor_json: LinkerFlavorCli,
- /// LLD flavor used if `lld` (or `rust-lld`) is specified as a linker
- /// without clarifying its flavor in any way.
- /// FIXME: Merge this into `LinkerFlavor`.
- pub lld_flavor: LldFlavor,
- /// Whether the linker support GNU-like arguments such as -O. Defaults to true.
- /// FIXME: Merge this into `LinkerFlavor`.
- pub linker_is_gnu: bool,
+ lld_flavor_json: LldFlavor,
+ linker_is_gnu_json: bool,
/// Objects to link before and after all other object code.
pub pre_link_objects: CrtObjects,
@@ -1294,7 +1396,7 @@ pub struct TargetOptions {
/// Optional link script applied to `dylib` and `executable` crate types.
/// This is a string containing the script, not a path. Can only be applied
- /// to linkers where `linker_is_gnu` is true.
+ /// to linkers where linker flavor matches `LinkerFlavor::Gnu(..)`.
pub link_script: Option<StaticCow<str>>,
/// Environment variables to be set for the linker invocation.
pub link_env: StaticCow<[(StaticCow<str>, StaticCow<str>)]>,
@@ -1379,6 +1481,8 @@ pub struct TargetOptions {
pub is_like_msvc: bool,
/// Whether a target toolchain is like WASM.
pub is_like_wasm: bool,
+ /// Whether a target toolchain is like Android, implying a Linux kernel and a Bionic libc
+ pub is_like_android: bool,
/// Default supported version of DWARF on this platform.
/// Useful because some platforms (osx, bsd) only want up to DWARF2.
pub default_dwarf_version: u32,
@@ -1567,22 +1671,38 @@ pub struct TargetOptions {
/// Add arguments for the given flavor and also for its "twin" flavors
/// that have a compatible command line interface.
-fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
- let mut insert = |flavor| {
- link_args.entry(flavor).or_default().extend(args.iter().copied().map(Cow::Borrowed))
- };
+fn add_link_args_iter(
+ link_args: &mut LinkArgs,
+ flavor: LinkerFlavor,
+ args: impl Iterator<Item = StaticCow<str>> + Clone,
+) {
+ let mut insert = |flavor| link_args.entry(flavor).or_default().extend(args.clone());
insert(flavor);
match flavor {
- LinkerFlavor::Ld => insert(LinkerFlavor::Lld(LldFlavor::Ld)),
- LinkerFlavor::Msvc => insert(LinkerFlavor::Lld(LldFlavor::Link)),
- LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Lld(LldFlavor::Wasm) => {}
- LinkerFlavor::Lld(lld_flavor) => {
- panic!("add_link_args: use non-LLD flavor for {:?}", lld_flavor)
+ LinkerFlavor::Gnu(cc, lld) => {
+ assert_eq!(lld, Lld::No);
+ insert(LinkerFlavor::Gnu(cc, Lld::Yes));
+ }
+ LinkerFlavor::Darwin(cc, lld) => {
+ assert_eq!(lld, Lld::No);
+ insert(LinkerFlavor::Darwin(cc, Lld::Yes));
}
- LinkerFlavor::Gcc | LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {}
+ LinkerFlavor::Msvc(lld) => {
+ assert_eq!(lld, Lld::No);
+ insert(LinkerFlavor::Msvc(Lld::Yes));
+ }
+ LinkerFlavor::WasmLld(..)
+ | LinkerFlavor::Unix(..)
+ | LinkerFlavor::EmCc
+ | LinkerFlavor::Bpf
+ | LinkerFlavor::Ptx => {}
}
}
+fn add_link_args(link_args: &mut LinkArgs, flavor: LinkerFlavor, args: &[&'static str]) {
+ add_link_args_iter(link_args, flavor, args.iter().copied().map(Cow::Borrowed))
+}
+
impl TargetOptions {
fn link_args(flavor: LinkerFlavor, args: &[&'static str]) -> LinkArgs {
let mut link_args = LinkArgs::new();
@@ -1599,7 +1719,11 @@ impl TargetOptions {
}
fn update_from_cli(&mut self) {
- self.linker_flavor = LinkerFlavor::from_cli(self.linker_flavor_json);
+ self.linker_flavor = LinkerFlavor::from_cli_impl(
+ self.linker_flavor_json,
+ self.lld_flavor_json,
+ self.linker_is_gnu_json,
+ );
for (args, args_json) in [
(&mut self.pre_link_args, &self.pre_link_args_json),
(&mut self.late_link_args, &self.late_link_args_json),
@@ -1607,15 +1731,32 @@ impl TargetOptions {
(&mut self.late_link_args_static, &self.late_link_args_static_json),
(&mut self.post_link_args, &self.post_link_args_json),
] {
- *args = args_json
- .iter()
- .map(|(flavor, args)| (LinkerFlavor::from_cli(*flavor), args.clone()))
- .collect();
+ args.clear();
+ for (flavor, args_json) in args_json {
+ // Cannot use `from_cli` due to borrow checker.
+ let linker_flavor = LinkerFlavor::from_cli_impl(
+ *flavor,
+ self.lld_flavor_json,
+ self.linker_is_gnu_json,
+ );
+ // Normalize to no lld to avoid asserts.
+ let linker_flavor = match linker_flavor {
+ LinkerFlavor::Gnu(cc, _) => LinkerFlavor::Gnu(cc, Lld::No),
+ LinkerFlavor::Darwin(cc, _) => LinkerFlavor::Darwin(cc, Lld::No),
+ LinkerFlavor::Msvc(_) => LinkerFlavor::Msvc(Lld::No),
+ _ => linker_flavor,
+ };
+ if !args.contains_key(&linker_flavor) {
+ add_link_args_iter(args, linker_flavor, args_json.iter().cloned());
+ }
+ }
}
}
fn update_to_cli(&mut self) {
self.linker_flavor_json = self.linker_flavor.to_cli();
+ self.lld_flavor_json = self.linker_flavor.lld_flavor();
+ self.linker_is_gnu_json = self.linker_flavor.is_gnu();
for (args, args_json) in [
(&self.pre_link_args, &mut self.pre_link_args_json),
(&self.late_link_args, &mut self.late_link_args_json),
@@ -1642,10 +1783,10 @@ impl Default for TargetOptions {
abi: "".into(),
vendor: "unknown".into(),
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.into()),
- linker_flavor: LinkerFlavor::Gcc,
+ linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No),
linker_flavor_json: LinkerFlavorCli::Gcc,
- lld_flavor: LldFlavor::Ld,
- linker_is_gnu: true,
+ lld_flavor_json: LldFlavor::Ld,
+ linker_is_gnu_json: true,
link_script: None,
asm_args: cvs![],
cpu: "generic".into(),
@@ -1671,6 +1812,7 @@ impl Default for TargetOptions {
is_like_windows: false,
is_like_msvc: false,
is_like_wasm: false,
+ is_like_android: false,
default_dwarf_version: 4,
allows_weak_linkage: true,
has_rpath: false,
@@ -1913,6 +2055,12 @@ impl Target {
base.$key_name = s;
}
} );
+ ($key_name:ident = $json_name:expr, bool) => ( {
+ let name = $json_name;
+ if let Some(s) = obj.remove(name).and_then(|b| b.as_bool()) {
+ 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)) {
@@ -2084,9 +2232,9 @@ impl Target {
.map(|s| s.to_string().into());
}
} );
- ($key_name:ident, LldFlavor) => ( {
- let name = (stringify!($key_name)).replace("_", "-");
- obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
+ ($key_name:ident = $json_name:expr, LldFlavor) => ( {
+ let name = $json_name;
+ obj.remove(name).and_then(|o| o.as_str().and_then(|s| {
if let Some(flavor) = LldFlavor::from_str(&s) {
base.$key_name = flavor;
} else {
@@ -2280,8 +2428,8 @@ impl Target {
key!(vendor);
key!(linker, optional);
key!(linker_flavor_json = "linker-flavor", LinkerFlavor)?;
- key!(lld_flavor, LldFlavor)?;
- key!(linker_is_gnu, bool);
+ key!(lld_flavor_json = "lld-flavor", LldFlavor)?;
+ key!(linker_is_gnu_json = "linker-is-gnu", bool);
key!(pre_link_objects = "pre-link-objects", link_objects);
key!(post_link_objects = "post-link-objects", link_objects);
key!(pre_link_objects_self_contained = "pre-link-objects-fallback", link_objects);
@@ -2318,6 +2466,7 @@ impl Target {
key!(is_like_windows, bool);
key!(is_like_msvc, bool);
key!(is_like_wasm, bool);
+ key!(is_like_android, bool);
key!(default_dwarf_version, u32);
key!(allows_weak_linkage, bool);
key!(has_rpath, bool);
@@ -2529,8 +2678,8 @@ impl ToJson for Target {
target_option_val!(vendor);
target_option_val!(linker);
target_option_val!(linker_flavor_json, "linker-flavor");
- target_option_val!(lld_flavor);
- target_option_val!(linker_is_gnu);
+ target_option_val!(lld_flavor_json, "lld-flavor");
+ target_option_val!(linker_is_gnu_json, "linker-is-gnu");
target_option_val!(pre_link_objects);
target_option_val!(post_link_objects);
target_option_val!(pre_link_objects_self_contained, "pre-link-objects-fallback");
@@ -2568,6 +2717,7 @@ impl ToJson for Target {
target_option_val!(is_like_windows);
target_option_val!(is_like_msvc);
target_option_val!(is_like_wasm);
+ target_option_val!(is_like_android);
target_option_val!(default_dwarf_version);
target_option_val!(allows_weak_linkage);
target_option_val!(has_rpath);
diff --git a/compiler/rustc_target/src/spec/msp430_none_elf.rs b/compiler/rustc_target/src/spec/msp430_none_elf.rs
index 6b09386ae..251fd2a0a 100644
--- a/compiler/rustc_target/src/spec/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/msp430_none_elf.rs
@@ -1,4 +1,4 @@
-use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -16,7 +16,7 @@ pub fn target() -> Target {
// dependency on this specific gcc.
asm_args: cvs!["-mcpu=msp430"],
linker: Some("msp430-elf-gcc".into()),
- linker_is_gnu: false,
+ linker_flavor: LinkerFlavor::Unix(Cc::Yes),
// There are no atomic CAS instructions available in the MSP430
// instruction set, and the LLVM backend doesn't currently support
diff --git a/compiler/rustc_target/src/spec/msvc_base.rs b/compiler/rustc_target/src/spec/msvc_base.rs
index b3cd38a6e..1dad9133e 100644
--- a/compiler/rustc_target/src/spec/msvc_base.rs
+++ b/compiler/rustc_target/src/spec/msvc_base.rs
@@ -1,17 +1,15 @@
-use crate::spec::{DebuginfoKind, LinkerFlavor, LldFlavor, SplitDebuginfo, TargetOptions};
+use crate::spec::{DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
pub fn opts() -> TargetOptions {
// Suppress the verbose logo and authorship debugging output, which would needlessly
// clog any log files.
- let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc, &["/NOLOGO"]);
+ let pre_link_args = TargetOptions::link_args(LinkerFlavor::Msvc(Lld::No), &["/NOLOGO"]);
TargetOptions {
- linker_flavor: LinkerFlavor::Msvc,
+ linker_flavor: LinkerFlavor::Msvc(Lld::No),
is_like_windows: true,
is_like_msvc: true,
- lld_flavor: LldFlavor::Link,
- linker_is_gnu: false,
pre_link_args,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
diff --git a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
index 6ab3a8b7e..b0582b235 100644
--- a/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/nvptx64_nvidia_cuda.rs
@@ -13,7 +13,6 @@ pub fn target() -> Target {
linker_flavor: LinkerFlavor::Ptx,
// The linker can be installed from `crates.io`.
linker: Some("rust-ptx-linker".into()),
- linker_is_gnu: false,
// With `ptx-linker` approach, it can be later overridden via link flags.
cpu: "sm_30".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
index 803453c4a..08b273207 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_freebsd.rs
@@ -1,11 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.cpu = "ppc64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
index 5413c4f33..ce64de861 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_gnu.rs
@@ -1,15 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, RelroLevel, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.cpu = "ppc64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
-
- // ld.so in at least RHEL6 on ppc64 has a bug related to BIND_NOW, so only enable partial RELRO
- // for now. https://github.com/rust-lang/rust/pull/43170#issuecomment-315411474
- base.relro_level = RelroLevel::Partial;
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
index 159335eb6..81286a668 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_linux_musl.rs
@@ -1,11 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.cpu = "ppc64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
index 9cb3a67dc..7232dce3e 100644
--- a/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_unknown_openbsd.rs
@@ -1,11 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::openbsd_base::opts();
base.cpu = "ppc64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
index b7420d232..10da7872c 100644
--- a/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc64_wrs_vxworks.rs
@@ -1,11 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::vxworks_base::opts();
base.cpu = "ppc64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
index a3d180043..8c941e106 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_freebsd.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.cpu = "ppc64le".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64le-unknown-freebsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
index e18ff3be4..fd896e086 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_gnu.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.cpu = "ppc64le".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64le-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
index b84943d23..3cffcf497 100644
--- a/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc64le_unknown_linux_musl.rs
@@ -1,10 +1,11 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.cpu = "ppc64le".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc64le-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
index 75ac66c27..342f321bd 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_freebsd.rs
@@ -1,11 +1,15 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
// Extra hint to linker that we are generating secure-PLT code.
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--target=powerpc-unknown-freebsd13.0"]);
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ &["-m32", "--target=powerpc-unknown-freebsd13.0"],
+ );
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-freebsd13.0".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
index 6686a0bbf..c8c61dc46 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnu.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
index 6a250f4b5..5c51ec91f 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_gnuspe.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-linux-gnuspe".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
index 34200c679..fc7d802cb 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_linux_musl.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-linux-musl".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
index 60661ef9b..912149c79 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_netbsd.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::netbsd_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-netbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
index ad2c3d40f..dec85f996 100644
--- a/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/powerpc_unknown_openbsd.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::openbsd_base::opts();
base.endian = Endian::Big;
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
index 3f24966e0..a8c1c2a61 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::vxworks_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m32", "--secure-plt"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "--secure-plt"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
index 0f04f41f9..abb8d13da 100644
--- a/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/powerpc_wrs_vxworks_spe.rs
@@ -1,10 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::vxworks_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-mspe", "--secure-plt"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mspe", "--secure-plt"]);
base.max_atomic_width = Some(32);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "powerpc-unknown-linux-gnuspe".into(),
diff --git a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
index 232139db6..75a65a268 100644
--- a/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32i_unknown_none_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +8,7 @@ pub fn target() -> Target {
arch: "riscv32".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),
max_atomic_width: Some(0),
diff --git a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
index 3e5d2887f..f2242bbe0 100644
--- a/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32im_unknown_none_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +8,7 @@ pub fn target() -> Target {
arch: "riscv32".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),
max_atomic_width: Some(0),
diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
index 99317b9f1..55c6e4d16 100644
--- a/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_none_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +8,7 @@ pub fn target() -> Target {
arch: "riscv32".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs
index a5de645c9..a263e5d5c 100644
--- a/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imac_unknown_xous_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -10,7 +9,7 @@ pub fn target() -> Target {
options: TargetOptions {
os: "xous".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),
max_atomic_width: Some(32),
diff --git a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
index 03baef65c..25638a092 100644
--- a/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imc_esp_espidf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{cvs, Target, TargetOptions};
-use crate::spec::{LinkerFlavor, PanicStrategy, RelocModel};
+use crate::spec::{cvs, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -13,7 +12,6 @@ pub fn target() -> Target {
os: "espidf".into(),
env: "newlib".into(),
vendor: "espressif".into(),
- linker_flavor: LinkerFlavor::Gcc,
linker: Some("riscv32-esp-elf-gcc".into()),
cpu: "generic-rv32".into(),
diff --git a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
index bf510d204..01e773fae 100644
--- a/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv32imc_unknown_none_elf.rs
@@ -1,5 +1,4 @@
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +8,7 @@ pub fn target() -> Target {
arch: "riscv32".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv32".into(),
max_atomic_width: Some(0),
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 03b3cfd1e..67806d578 100644
--- a/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/riscv64gc_unknown_none_elf.rs
@@ -1,5 +1,5 @@
-use crate::spec::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
-use crate::spec::{Target, TargetOptions};
+use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
+use crate::spec::{RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +9,7 @@ pub fn target() -> Target {
arch: "riscv64".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
llvm_abiname: "lp64d".into(),
cpu: "generic-rv64".into(),
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 2a94c9dd2..f371e09be 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::{CodeModel, Target, TargetOptions};
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
+use crate::spec::{RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -9,7 +9,7 @@ pub fn target() -> Target {
arch: "riscv64".into(),
options: TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
cpu: "generic-rv64".into(),
max_atomic_width: Some(64),
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 8757bbed8..cda88de0e 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_gnu.rs
@@ -1,22 +1,23 @@
use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
- // FIXME: The data_layout string below and the ABI implementation in
- // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
- // Pass the -vector feature string to LLVM to respect this assumption.
+ // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
+ // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
+ // also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();
base.max_atomic_width = Some(64);
base.min_global_align = Some(16);
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "s390x-unknown-linux-gnu".into(),
pointer_width: 64,
- data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+ data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
arch: "s390x".into(),
options: base,
}
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 4c855271a..91e63aee5 100644
--- a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs
@@ -1,23 +1,24 @@
use crate::abi::Endian;
-use crate::spec::Target;
+use crate::spec::{StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.endian = Endian::Big;
// z10 is the oldest CPU supported by LLVM
base.cpu = "z10".into();
- // FIXME: The data_layout string below and the ABI implementation in
- // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI.
- // Pass the -vector feature string to LLVM to respect this assumption.
+ // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
+ // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
+ // also strip v128 from the data_layout below to match the older LLVM's expectation.
base.features = "-vector".into();
base.max_atomic_width = Some(64);
base.min_global_align = Some(16);
base.static_position_independent_executables = true;
+ base.stack_probes = StackProbeType::Inline;
Target {
llvm_target: "s390x-unknown-linux-musl".into(),
pointer_width: 64,
- data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".into(),
+ data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
arch: "s390x".into(),
options: base,
}
diff --git a/compiler/rustc_target/src/spec/solaris_base.rs b/compiler/rustc_target/src/spec/solaris_base.rs
index b7e8e8cf7..f97cdb4fb 100644
--- a/compiler/rustc_target/src/spec/solaris_base.rs
+++ b/compiler/rustc_target/src/spec/solaris_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{cvs, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, TargetOptions};
pub fn opts() -> TargetOptions {
TargetOptions {
@@ -7,7 +7,7 @@ pub fn opts() -> TargetOptions {
has_rpath: true,
families: cvs!["unix"],
is_like_solaris: true,
- linker_is_gnu: false,
+ linker_flavor: LinkerFlavor::Unix(Cc::Yes),
limit_rdylib_exports: false, // Linker doesn't support this
eh_frame_header: false,
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
index 836ab0e37..38ab066b0 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_netbsd.rs
@@ -1,10 +1,10 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::netbsd_base::opts();
base.cpu = "v9".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
Target {
diff --git a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
index 4a192df39..06a5f782a 100644
--- a/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/sparc64_unknown_openbsd.rs
@@ -1,11 +1,11 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::openbsd_base::opts();
base.endian = Endian::Big;
base.cpu = "v9".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
Target {
diff --git a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
index ea4fafa4b..12968abda 100644
--- a/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/sparc_unknown_linux_gnu.rs
@@ -1,12 +1,12 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.endian = Endian::Big;
base.cpu = "v9".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-mv8plus"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mv8plus"]);
Target {
llvm_target: "sparc-unknown-linux-gnu".into(),
diff --git a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
index aac09181a..440194ef2 100644
--- a/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/sparcv9_sun_solaris.rs
@@ -1,10 +1,10 @@
use crate::abi::Endian;
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Target};
pub fn target() -> Target {
let mut base = super::solaris_base::opts();
base.endian = Endian::Big;
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]);
// llvm calls this "v9"
base.cpu = "v9".into();
base.vendor = "sun".into();
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index 0af599916..172da0ed5 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -19,11 +19,13 @@ impl Target {
assert!(self.is_like_windows);
}
- // Check that default linker flavor and lld flavor are compatible
- // with some other key properties.
- assert_eq!(self.is_like_osx, matches!(self.lld_flavor, LldFlavor::Ld64));
- assert_eq!(self.is_like_msvc, matches!(self.lld_flavor, LldFlavor::Link));
- assert_eq!(self.is_like_wasm, matches!(self.lld_flavor, LldFlavor::Wasm));
+ // Check that default linker flavor is compatible with some other key properties.
+ assert_eq!(self.is_like_osx, matches!(self.linker_flavor, LinkerFlavor::Darwin(..)));
+ assert_eq!(self.is_like_msvc, matches!(self.linker_flavor, LinkerFlavor::Msvc(..)));
+ assert_eq!(
+ self.is_like_wasm && self.os != "emscripten",
+ matches!(self.linker_flavor, LinkerFlavor::WasmLld(..))
+ );
assert_eq!(self.os == "emscripten", matches!(self.linker_flavor, LinkerFlavor::EmCc));
assert_eq!(self.arch == "bpf", matches!(self.linker_flavor, LinkerFlavor::Bpf));
assert_eq!(self.arch == "nvptx64", matches!(self.linker_flavor, LinkerFlavor::Ptx));
@@ -38,44 +40,25 @@ impl Target {
for (&flavor, flavor_args) in args {
assert!(!flavor_args.is_empty());
// Check that flavors mentioned in link args are compatible with the default flavor.
- match (self.linker_flavor, self.lld_flavor) {
- (
- LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc,
- LldFlavor::Ld,
- ) => {
- assert_matches!(
- flavor,
- LinkerFlavor::Ld | LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Gcc
- )
- }
- (LinkerFlavor::Gcc, LldFlavor::Ld64) => {
- assert_matches!(
- flavor,
- LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Gcc
- )
+ match self.linker_flavor {
+ LinkerFlavor::Gnu(..) => {
+ assert_matches!(flavor, LinkerFlavor::Gnu(..));
}
- (LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link), LldFlavor::Link) => {
- assert_matches!(
- flavor,
- LinkerFlavor::Msvc | LinkerFlavor::Lld(LldFlavor::Link)
- )
+ LinkerFlavor::Darwin(..) => {
+ assert_matches!(flavor, LinkerFlavor::Darwin(..))
}
- (LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc, LldFlavor::Wasm) => {
- assert_matches!(
- flavor,
- LinkerFlavor::Lld(LldFlavor::Wasm) | LinkerFlavor::Gcc
- )
+ LinkerFlavor::WasmLld(..) => {
+ assert_matches!(flavor, LinkerFlavor::WasmLld(..))
}
- (LinkerFlavor::EmCc, LldFlavor::Wasm) => {
- assert_matches!(flavor, LinkerFlavor::EmCc)
+ LinkerFlavor::Unix(..) => {
+ assert_matches!(flavor, LinkerFlavor::Unix(..));
}
- (LinkerFlavor::Bpf, LldFlavor::Ld) => {
- assert_matches!(flavor, LinkerFlavor::Bpf)
+ LinkerFlavor::Msvc(..) => {
+ assert_matches!(flavor, LinkerFlavor::Msvc(..))
}
- (LinkerFlavor::Ptx, LldFlavor::Ld) => {
- assert_matches!(flavor, LinkerFlavor::Ptx)
+ LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {
+ assert_eq!(flavor, self.linker_flavor)
}
- flavors => unreachable!("unexpected flavor combination: {:?}", flavors),
}
// Check that link args for cc and non-cc versions of flavors are consistent.
@@ -88,25 +71,29 @@ impl Target {
}
}
};
+
match self.linker_flavor {
- LinkerFlavor::Gcc => match self.lld_flavor {
- LldFlavor::Ld => {
- check_noncc(LinkerFlavor::Ld);
- check_noncc(LinkerFlavor::Lld(LldFlavor::Ld));
- }
- LldFlavor::Ld64 => check_noncc(LinkerFlavor::Lld(LldFlavor::Ld64)),
- LldFlavor::Wasm => check_noncc(LinkerFlavor::Lld(LldFlavor::Wasm)),
- LldFlavor::Link => {}
- },
+ LinkerFlavor::Gnu(Cc::Yes, lld) => check_noncc(LinkerFlavor::Gnu(Cc::No, lld)),
+ LinkerFlavor::WasmLld(Cc::Yes) => check_noncc(LinkerFlavor::WasmLld(Cc::No)),
+ LinkerFlavor::Unix(Cc::Yes) => check_noncc(LinkerFlavor::Unix(Cc::No)),
_ => {}
}
}
// Check that link args for lld and non-lld versions of flavors are consistent.
- assert_eq!(args.get(&LinkerFlavor::Ld), args.get(&LinkerFlavor::Lld(LldFlavor::Ld)));
+ for cc in [Cc::No, Cc::Yes] {
+ assert_eq!(
+ args.get(&LinkerFlavor::Gnu(cc, Lld::No)),
+ args.get(&LinkerFlavor::Gnu(cc, Lld::Yes)),
+ );
+ assert_eq!(
+ args.get(&LinkerFlavor::Darwin(cc, Lld::No)),
+ args.get(&LinkerFlavor::Darwin(cc, Lld::Yes)),
+ );
+ }
assert_eq!(
- args.get(&LinkerFlavor::Msvc),
- args.get(&LinkerFlavor::Lld(LldFlavor::Link)),
+ args.get(&LinkerFlavor::Msvc(Lld::No)),
+ args.get(&LinkerFlavor::Msvc(Lld::Yes)),
);
}
diff --git a/compiler/rustc_target/src/spec/thumb_base.rs b/compiler/rustc_target/src/spec/thumb_base.rs
index 049142b89..000766c57 100644
--- a/compiler/rustc_target/src/spec/thumb_base.rs
+++ b/compiler/rustc_target/src/spec/thumb_base.rs
@@ -27,13 +27,12 @@
// differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
// build scripts / gcc flags.
-use crate::spec::TargetOptions;
-use crate::spec::{FramePointer, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, PanicStrategy, RelocModel, TargetOptions};
pub fn opts() -> TargetOptions {
// See rust-lang/rfcs#1645 for a discussion about these defaults
TargetOptions {
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
// In most cases, LLD is good enough
linker: Some("rust-lld".into()),
// Because these devices have very little resources having an unwinder is too onerous so we
diff --git a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
index bdaaed8b5..5a3e4c88d 100644
--- a/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv4t_none_eabi.rs
@@ -16,9 +16,8 @@
//! The default link script is very likely wrong, so you should use
//! `-Clink-arg=-Tmy_script.ld` to override that with a correct linker script.
-use crate::spec::{
- cvs, FramePointer, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions,
-};
+use crate::spec::{cvs, Cc, FramePointer, LinkerFlavor, Lld};
+use crate::spec::{PanicStrategy, RelocModel, Target, TargetOptions};
pub fn target() -> Target {
Target {
@@ -37,7 +36,7 @@ pub fn target() -> Target {
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
options: TargetOptions {
abi: "eabi".into(),
- linker_flavor: LinkerFlavor::Ld,
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No),
linker: Some("arm-none-eabi-ld".into()),
// extra args passed to the external assembler (assuming `arm-none-eabi-as`):
diff --git a/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs
new file mode 100644
index 000000000..021b0e0eb
--- /dev/null
+++ b/compiler/rustc_target/src/spec/thumbv5te_none_eabi.rs
@@ -0,0 +1,41 @@
+//! Targets the ARMv5TE, with code as `t32` code by default.
+
+use crate::spec::{cvs, FramePointer, Target, TargetOptions};
+
+pub fn target() -> Target {
+ Target {
+ llvm_target: "thumbv5te-none-eabi".into(),
+ pointer_width: 32,
+ arch: "arm".into(),
+ /* Data layout args are '-' separated:
+ * little endian
+ * stack is 64-bit aligned (EABI)
+ * pointers are 32-bit
+ * i64 must be 64-bit aligned (EABI)
+ * mangle names with ELF style
+ * native integers are 32-bit
+ * All other elements are default
+ */
+ data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
+
+ options: TargetOptions {
+ abi: "eabi".into(),
+ // extra args passed to the external assembler (assuming `arm-none-eabi-as`):
+ // * activate t32/a32 interworking
+ // * use arch ARMv5TE
+ // * use little-endian
+ asm_args: cvs!["-mthumb-interwork", "-march=armv5te", "-mlittle-endian",],
+ // minimum extra features, these cannot be disabled via -C
+ // Also force-enable 32-bit atomics, which allows the use of atomic load/store only.
+ // The resulting atomics are ABI incompatible with atomics backed by libatomic.
+ features: "+soft-float,+strict-align,+atomics-32".into(),
+ frame_pointer: FramePointer::MayOmit,
+ main_needs_argc_argv: false,
+ // don't have atomic compare-and-swap
+ atomic_cas: false,
+ has_thumb_interworking: true,
+
+ ..super::thumb_base::opts()
+ },
+ }
+}
diff --git a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
index 4d09d3a4d..f1be274f0 100644
--- a/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/thumbv7a_pc_windows_msvc.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions};
+use crate::spec::{LinkerFlavor, Lld, PanicStrategy, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::windows_msvc_base::opts();
@@ -9,7 +9,7 @@ pub fn target() -> Target {
// should be smart enough to insert branch islands only
// where necessary, but this is not the observed behavior.
// Disabling the LBR optimization works around the issue.
- base.add_pre_link_args(LinkerFlavor::Msvc, &["/OPT:NOLBR"]);
+ base.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/OPT:NOLBR"]);
Target {
llvm_target: "thumbv7a-pc-windows-msvc".into(),
diff --git a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
index 4cad9e183..8d80fcd5f 100644
--- a/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/thumbv7neon_linux_androideabi.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};
// This target if is for the Android v7a ABI in thumb mode with
// NEON unconditionally enabled and, therefore, with 32 FPU registers
@@ -10,7 +10,7 @@ use crate::spec::{LinkerFlavor, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::android_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-march=armv7-a"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
Target {
llvm_target: "armv7-none-linux-android".into(),
pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/uefi_msvc_base.rs b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
index 99af7d85e..8968d3c8f 100644
--- a/compiler/rustc_target/src/spec/uefi_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/uefi_msvc_base.rs
@@ -9,14 +9,13 @@
// the timer-interrupt. Device-drivers are required to use polling-based models. Furthermore, all
// code runs in the same environment, no process separation is supported.
-use crate::spec::{LinkerFlavor, LldFlavor, PanicStrategy};
-use crate::spec::{StackProbeType, TargetOptions};
+use crate::spec::{LinkerFlavor, Lld, PanicStrategy, StackProbeType, TargetOptions};
pub fn opts() -> TargetOptions {
let mut base = super::msvc_base::opts();
base.add_pre_link_args(
- LinkerFlavor::Msvc,
+ LinkerFlavor::Msvc(Lld::No),
&[
// Non-standard subsystems have no default entry-point in PE+ files. We have to define
// one. "efi_main" seems to be a common choice amongst other implementations and the
@@ -37,7 +36,7 @@ pub fn opts() -> TargetOptions {
TargetOptions {
os: "uefi".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+ linker_flavor: LinkerFlavor::Msvc(Lld::Yes),
disable_redzone: true,
exe_suffix: ".efi".into(),
allows_weak_linkage: false,
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
index 4e2927dd9..8dad941b5 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -10,14 +10,12 @@
//! This target is more or less managed by the Rust and WebAssembly Working
//! Group nowadays at <https://github.com/rustwasm>.
-use super::wasm_base;
-use super::{LinkerFlavor, LldFlavor, Target};
+use super::{wasm_base, Cc, LinkerFlavor, Target};
use crate::spec::abi::Abi;
pub fn target() -> Target {
let mut options = wasm_base::options();
options.os = "unknown".into();
- options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
// This is a default for backwards-compatibility with the original
// definition of this target oh-so-long-ago. Once the "wasm" ABI is
@@ -30,7 +28,7 @@ pub fn target() -> Target {
options.default_adjusted_cabi = Some(Abi::Wasm);
options.add_pre_link_args(
- LinkerFlavor::Lld(LldFlavor::Wasm),
+ LinkerFlavor::WasmLld(Cc::No),
&[
// For now this target just never has an entry symbol no matter the output
// type, so unconditionally pass this.
@@ -44,7 +42,7 @@ pub fn target() -> Target {
],
);
options.add_pre_link_args(
- LinkerFlavor::Gcc,
+ LinkerFlavor::WasmLld(Cc::Yes),
&[
// Make sure clang uses LLD as its linker and is configured appropriately
// otherwise
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
index 9c30487f4..93a956403 100644
--- a/compiler/rustc_target/src/spec/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -72,15 +72,13 @@
//! best we can with this target. Don't start relying on too much here unless
//! you know what you're getting in to!
-use super::wasm_base;
-use super::{crt_objects, LinkerFlavor, LldFlavor, Target};
+use super::{crt_objects, wasm_base, Cc, LinkerFlavor, Target};
pub fn target() -> Target {
let mut options = wasm_base::options();
options.os = "wasi".into();
- options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
- options.add_pre_link_args(LinkerFlavor::Gcc, &["--target=wasm32-wasi"]);
+ options.add_pre_link_args(LinkerFlavor::WasmLld(Cc::Yes), &["--target=wasm32-wasi"]);
options.pre_link_objects_self_contained = crt_objects::pre_wasi_self_contained();
options.post_link_objects_self_contained = crt_objects::post_wasi_self_contained();
diff --git a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
index 5211f7707..3fda398d2 100644
--- a/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm64_unknown_unknown.rs
@@ -7,16 +7,14 @@
//! the standard library is available, most of it returns an error immediately
//! (e.g. trying to create a TCP stream or something like that).
-use super::wasm_base;
-use super::{LinkerFlavor, LldFlavor, Target};
+use super::{wasm_base, Cc, LinkerFlavor, Target};
pub fn target() -> Target {
let mut options = wasm_base::options();
options.os = "unknown".into();
- options.linker_flavor = LinkerFlavor::Lld(LldFlavor::Wasm);
options.add_pre_link_args(
- LinkerFlavor::Lld(LldFlavor::Wasm),
+ LinkerFlavor::WasmLld(Cc::No),
&[
// For now this target just never has an entry symbol no matter the output
// type, so unconditionally pass this.
@@ -25,7 +23,7 @@ pub fn target() -> Target {
],
);
options.add_pre_link_args(
- LinkerFlavor::Gcc,
+ LinkerFlavor::WasmLld(Cc::Yes),
&[
// Make sure clang uses LLD as its linker and is configured appropriately
// otherwise
diff --git a/compiler/rustc_target/src/spec/wasm_base.rs b/compiler/rustc_target/src/spec/wasm_base.rs
index 28a07701e..528a84a8b 100644
--- a/compiler/rustc_target/src/spec/wasm_base.rs
+++ b/compiler/rustc_target/src/spec/wasm_base.rs
@@ -1,5 +1,5 @@
use super::crt_objects::LinkSelfContainedDefault;
-use super::{cvs, LinkerFlavor, LldFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
+use super::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel};
pub fn options() -> TargetOptions {
macro_rules! args {
@@ -49,8 +49,8 @@ pub fn options() -> TargetOptions {
};
}
- let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::Lld(LldFlavor::Wasm), args!(""));
- super::add_link_args(&mut pre_link_args, LinkerFlavor::Gcc, args!("-Wl,"));
+ let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
+ super::add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
TargetOptions {
is_like_wasm: true,
@@ -91,8 +91,7 @@ pub fn options() -> TargetOptions {
// we use the LLD shipped with the Rust toolchain by default
linker: Some("rust-lld".into()),
- lld_flavor: LldFlavor::Wasm,
- linker_is_gnu: false,
+ linker_flavor: LinkerFlavor::WasmLld(Cc::No),
pre_link_args,
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index 81d44a963..a32ca469b 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -1,10 +1,10 @@
use crate::spec::crt_objects::{self, LinkSelfContainedDefault};
-use crate::spec::{cvs, DebuginfoKind, LinkerFlavor, SplitDebuginfo, TargetOptions};
+use crate::spec::{cvs, Cc, DebuginfoKind, LinkerFlavor, Lld, SplitDebuginfo, TargetOptions};
use std::borrow::Cow;
pub fn opts() -> TargetOptions {
let mut pre_link_args = TargetOptions::link_args(
- LinkerFlavor::Ld,
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
// Enable ASLR
"--dynamicbase",
@@ -14,7 +14,7 @@ pub fn opts() -> TargetOptions {
);
super::add_link_args(
&mut pre_link_args,
- LinkerFlavor::Gcc,
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&[
// Tell GCC to avoid linker plugins, because we are not bundling
// them with Windows installer, and Rust does its own LTO anyways.
@@ -42,23 +42,33 @@ pub fn opts() -> TargetOptions {
"-luser32",
"-lkernel32",
];
- let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
- super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+ let mut late_link_args =
+ TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
+ super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
// If any of our crates are dynamically linked then we need to use
// the shared libgcc_s-dw2-1.dll. This is required to support
// unwinding across DLL boundaries.
let dynamic_unwind_libs = &["-lgcc_s"];
let mut late_link_args_dynamic =
- TargetOptions::link_args(LinkerFlavor::Ld, dynamic_unwind_libs);
- super::add_link_args(&mut late_link_args_dynamic, LinkerFlavor::Gcc, dynamic_unwind_libs);
+ TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), dynamic_unwind_libs);
+ super::add_link_args(
+ &mut late_link_args_dynamic,
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ dynamic_unwind_libs,
+ );
// If all of our crates are statically linked then we can get away
// with statically linking the libgcc unwinding code. This allows
// binaries to be redistributed without the libgcc_s-dw2-1.dll
// dependency, but unfortunately break unwinding across DLL
// boundaries when unwinding across FFI boundaries.
let static_unwind_libs = &["-lgcc_eh", "-l:libpthread.a"];
- let mut late_link_args_static = TargetOptions::link_args(LinkerFlavor::Ld, static_unwind_libs);
- super::add_link_args(&mut late_link_args_static, LinkerFlavor::Gcc, static_unwind_libs);
+ let mut late_link_args_static =
+ TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), static_unwind_libs);
+ super::add_link_args(
+ &mut late_link_args_static,
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ static_unwind_libs,
+ );
TargetOptions {
os: "windows".into(),
diff --git a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
index f30be2549..58210c75a 100644
--- a/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnullvm_base.rs
@@ -1,15 +1,17 @@
-use crate::spec::{cvs, LinkerFlavor, TargetOptions};
+use crate::spec::{cvs, Cc, LinkerFlavor, Lld, TargetOptions};
pub fn opts() -> TargetOptions {
// We cannot use `-nodefaultlibs` because compiler-rt has to be passed
// as a path since it's not added to linker search path by the default.
// There were attempts to make it behave like libgcc (so one can just use -l<name>)
// but LLVM maintainers rejected it: https://reviews.llvm.org/D51440
- let pre_link_args =
- TargetOptions::link_args(LinkerFlavor::Gcc, &["-nolibc", "--unwindlib=none"]);
+ let pre_link_args = TargetOptions::link_args(
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
+ &["-nolibc", "--unwindlib=none"],
+ );
// Order of `late_link_args*` does not matter with LLD.
let late_link_args = TargetOptions::link_args(
- LinkerFlavor::Gcc,
+ LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-lmingw32", "-lmingwex", "-lmsvcrt", "-lkernel32", "-luser32"],
);
diff --git a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
index fa69b919c..f30c33d99 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_gnu_base.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
+use crate::spec::{Cc, LinkArgs, LinkerFlavor, Lld, TargetOptions};
pub fn opts() -> TargetOptions {
let base = super::windows_gnu_base::opts();
@@ -15,8 +15,9 @@ pub fn opts() -> TargetOptions {
"-lmingwex",
"-lmingw32",
];
- let mut late_link_args = TargetOptions::link_args(LinkerFlavor::Ld, mingw_libs);
- super::add_link_args(&mut late_link_args, LinkerFlavor::Gcc, mingw_libs);
+ let mut late_link_args =
+ TargetOptions::link_args(LinkerFlavor::Gnu(Cc::No, Lld::No), mingw_libs);
+ super::add_link_args(&mut late_link_args, LinkerFlavor::Gnu(Cc::Yes, Lld::No), mingw_libs);
// Reset the flags back to empty until the FIXME above is addressed.
let late_link_args_dynamic = LinkArgs::new();
let late_link_args_static = LinkArgs::new();
diff --git a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
index f2573fc2d..8c942c59d 100644
--- a/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
+++ b/compiler/rustc_target/src/spec/windows_uwp_msvc_base.rs
@@ -1,11 +1,11 @@
-use crate::spec::{LinkerFlavor, TargetOptions};
+use crate::spec::{LinkerFlavor, Lld, TargetOptions};
pub fn opts() -> TargetOptions {
let mut opts = super::windows_msvc_base::opts();
opts.abi = "uwp".into();
opts.vendor = "uwp".into();
- opts.add_pre_link_args(LinkerFlavor::Msvc, &["/APPCONTAINER", "mincore.lib"]);
+ opts.add_pre_link_args(LinkerFlavor::Msvc(Lld::No), &["/APPCONTAINER", "mincore.lib"]);
opts
}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
index 176c9dd6b..087be1b95 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_darwin.rs
@@ -1,5 +1,5 @@
-use crate::spec::TargetOptions;
-use crate::spec::{FramePointer, LinkerFlavor, SanitizerSet, StackProbeType, Target};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
+use crate::spec::{StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let arch = "x86_64";
@@ -7,10 +7,9 @@ pub fn target() -> Target {
base.cpu = "core2".into();
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
base.frame_pointer = FramePointer::Always;
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
base.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
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 5e64ed0cf..e6143025d 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_ios.rs
@@ -13,8 +13,7 @@ pub fn target() -> Target {
arch: "x86_64".into(),
options: TargetOptions {
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
..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 2122bcd37..13259205a 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
@@ -1,11 +1,11 @@
use super::apple_sdk_base::{opts, Arch};
-use crate::spec::{LinkerFlavor, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let llvm_target = "x86_64-apple-ios13.0-macabi";
let mut base = opts("ios", Arch::X86_64_macabi);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-target", llvm_target]);
+ base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
Target {
llvm_target: llvm_target.into(),
@@ -15,8 +15,7 @@ pub fn target() -> Target {
arch: "x86_64".into(),
options: TargetOptions {
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
..base
},
}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
index a848c5a0a..3d54da086 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_tvos.rs
@@ -10,8 +10,7 @@ pub fn target() -> Target {
arch: "x86_64".into(),
options: TargetOptions {
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
..base
},
}
diff --git a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
index 4dff3c2f2..e499b1985 100644
--- a/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/x86_64_apple_watchos_sim.rs
@@ -15,8 +15,7 @@ pub fn target() -> Target {
arch: "x86_64".into(),
options: TargetOptions {
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
forces_embed_bitcode: true,
// Taken from a clang build on Xcode 11.4.1.
// These arguments are not actually invoked - they just have
diff --git a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
index 9d597ea2e..cba6fda19 100644
--- a/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
@@ -1,12 +1,10 @@
use std::borrow::Cow;
-use crate::spec::cvs;
-
-use super::{LinkerFlavor, LldFlavor, Target, TargetOptions};
+use super::{cvs, Cc, LinkerFlavor, Lld, Target, TargetOptions};
pub fn target() -> Target {
let pre_link_args = TargetOptions::link_args(
- LinkerFlavor::Ld,
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
&[
"-e",
"elf_entry",
@@ -61,7 +59,7 @@ pub fn target() -> Target {
env: "sgx".into(),
vendor: "fortanix".into(),
abi: "fortanix".into(),
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
max_atomic_width: Some(64),
cpu: "x86-64".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
index 4f88fc350..532dd6d07 100644
--- a/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/x86_64_fuchsia.rs
@@ -4,8 +4,7 @@ pub fn target() -> Target {
let mut base = super::fuchsia_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
Target {
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 6d19cf265..9c9137848 100644
--- a/compiler/rustc_target/src/spec/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/x86_64_linux_android.rs
@@ -1,4 +1,4 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::android_base::opts();
@@ -6,9 +6,8 @@ pub fn target() -> Target {
// https://developer.android.com/ndk/guides/abis.html#86-64
base.features = "+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-linux-android".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
index 0550b221f..cb62a8173 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_solaris.rs
@@ -1,13 +1,12 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::solaris_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]);
base.cpu = "x86-64".into();
base.vendor = "pc".into();
base.max_atomic_width = Some(64);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
Target {
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
index 59a8cffca..37feaa9db 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnu.rs
@@ -1,11 +1,14 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_gnu_base::opts();
base.cpu = "x86-64".into();
// Use high-entropy 64 bit address space for ASLR
- base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["-m", "i386pep", "--high-entropy-va"],
+ );
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
base.max_atomic_width = Some(64);
base.linker = Some("x86_64-w64-mingw32-gcc".into());
diff --git a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
index d3909b389..039bc2bd2 100644
--- a/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/x86_64_pc_windows_gnullvm.rs
@@ -1,9 +1,9 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_gnullvm_base::opts();
base.cpu = "x86-64".into();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
base.max_atomic_width = Some(64);
base.linker = Some("x86_64-w64-mingw32-clang".into());
diff --git a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
index cbe87589a..0f31ea86b 100644
--- a/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/x86_64_sun_solaris.rs
@@ -1,13 +1,12 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::solaris_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64"]);
base.cpu = "x86-64".into();
base.vendor = "sun".into();
base.max_atomic_width = Some(64);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-pc-solaris".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
index 746f64781..67ce3768d 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_dragonfly.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::dragonfly_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-unknown-dragonfly".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 b30784ed6..98988ab35 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_freebsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
base.supported_sanitizers =
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::MEMORY | SanitizerSet::THREAD;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
index d6d033629..9a7a3b501 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_haiku.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::haiku_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
// This option is required to build executables on Haiku x86_64
base.position_independent_executables = true;
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
index d31530161..fb1af33f8 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_hermit.rs
@@ -5,8 +5,7 @@ pub fn target() -> Target {
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
base.features = "+rdrnd,+rdseed".into();
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-unknown-hermit".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
index 9f19c3a2b..04a12a7bf 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_illumos.rs
@@ -1,8 +1,8 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, Target};
+use crate::spec::{Cc, LinkerFlavor, SanitizerSet, Target};
pub fn target() -> Target {
let mut base = super::illumos_base::opts();
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-std=c99"]);
+ base.add_pre_link_args(LinkerFlavor::Unix(Cc::Yes), &["-m64", "-std=c99"]);
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI;
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 956be0353..a91ab365b 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnu.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
base.static_position_independent_executables = true;
base.supported_sanitizers = SanitizerSet::ADDRESS
| SanitizerSet::CFI
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
index 140882747..626d5b480 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_gnux32.rs
@@ -1,13 +1,12 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_gnu_base::opts();
base.cpu = "x86-64".into();
base.abi = "x32".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-mx32"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-mx32"]);
+ base.stack_probes = StackProbeType::X86;
base.has_thread_local = false;
// BUG(GabrielMajeri): disabling the PLT on x86_64 Linux with x32 ABI
// breaks code gen. See LLVM bug 36743
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 87e7784d1..9087dc3df 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_linux_musl.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::linux_musl_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
base.static_position_independent_executables = true;
base.supported_sanitizers = SanitizerSet::ADDRESS
| SanitizerSet::CFI
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 d3a67619a..64ae425d8 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_netbsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, SanitizerSet, StackProbeType, Target, TargetOptions};
+use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let mut base = super::netbsd_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
base.supported_sanitizers = SanitizerSet::ADDRESS
| SanitizerSet::CFI
| SanitizerSet::LEAK
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 b9a345127..e4d33c2b8 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -4,19 +4,18 @@
// `target-cpu` compiler flags to opt-in more hardware-specific
// features.
-use super::{CodeModel, LinkerFlavor, LldFlavor, PanicStrategy};
+use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
use super::{RelroLevel, StackProbeType, Target, TargetOptions};
pub fn target() -> Target {
let opts = TargetOptions {
cpu: "x86-64".into(),
max_atomic_width: Some(64),
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- stack_probes: StackProbeType::Call,
+ stack_probes: StackProbeType::X86,
position_independent_executables: true,
static_position_independent_executables: true,
relro_level: RelroLevel::Full,
- linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+ linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
features:
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
index 593345a5f..ebd9636ff 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none_linuxkernel.rs
@@ -1,7 +1,7 @@
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
// generic Linux kernel options.
-use crate::spec::{CodeModel, LinkerFlavor, Target};
+use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::linux_kernel_base::opts();
@@ -10,7 +10,7 @@ pub fn target() -> Target {
base.features =
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
base.code_model = Some(CodeModel::Kernel);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
Target {
// FIXME: Some dispute, the linux-on-clang folks think this should use
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
index f50c6bcee..66b8e2022 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_openbsd.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::openbsd_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-unknown-openbsd".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
index 668ae9054..b47f15cf5 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_redox.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::redox_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
Target {
llvm_target: "x86_64-unknown-redox".into(),
diff --git a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
index 76d2013cf..c3eaa6939 100644
--- a/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/x86_64_uwp_windows_gnu.rs
@@ -1,11 +1,14 @@
-use crate::spec::{LinkerFlavor, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, Target};
pub fn target() -> Target {
let mut base = super::windows_uwp_gnu_base::opts();
base.cpu = "x86-64".into();
// Use high-entropy 64 bit address space for ASLR
- base.add_pre_link_args(LinkerFlavor::Ld, &["-m", "i386pep", "--high-entropy-va"]);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64", "-Wl,--high-entropy-va"]);
+ base.add_pre_link_args(
+ LinkerFlavor::Gnu(Cc::No, Lld::No),
+ &["-m", "i386pep", "--high-entropy-va"],
+ );
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64", "-Wl,--high-entropy-va"]);
base.max_atomic_width = Some(64);
Target {
diff --git a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
index 129897495..365ade6bc 100644
--- a/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/x86_64_wrs_vxworks.rs
@@ -1,12 +1,11 @@
-use crate::spec::{LinkerFlavor, StackProbeType, Target};
+use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target};
pub fn target() -> Target {
let mut base = super::vxworks_base::opts();
base.cpu = "x86-64".into();
base.max_atomic_width = Some(64);
- base.add_pre_link_args(LinkerFlavor::Gcc, &["-m64"]);
- // don't use probe-stack=inline-asm until rust#83139 and rust#84667 are resolved
- base.stack_probes = StackProbeType::Call;
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
+ base.stack_probes = StackProbeType::X86;
base.disable_redzone = true;
Target {
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 566f236f2..67613e1a4 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
rustc_parse_format = { path = "../rustc_parse_format" }
diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs
index 36ab8f3bd..61cfeec4b 100644
--- a/compiler/rustc_trait_selection/src/autoderef.rs
+++ b/compiler/rustc_trait_selection/src/autoderef.rs
@@ -25,7 +25,7 @@ struct AutoderefSnapshot<'tcx> {
pub struct Autoderef<'a, 'tcx> {
// Meta infos:
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
span: Span,
overloaded_span: Span,
body_id: hir::HirId,
@@ -94,7 +94,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
impl<'a, 'tcx> Autoderef<'a, 'tcx> {
pub fn new(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
span: Span,
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index ab0afc545..7f8705824 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,11 +1,11 @@
-use rustc_errors::{fluent, ErrorGuaranteed, Handler};
-use rustc_macros::SessionDiagnostic;
-use rustc_middle::ty::{PolyTraitRef, Ty, Unevaluated};
-use rustc_session::{Limit, SessionDiagnostic};
+use rustc_errors::{fluent, ErrorGuaranteed, Handler, IntoDiagnostic};
+use rustc_macros::Diagnostic;
+use rustc_middle::ty::{self, PolyTraitRef, Ty};
+use rustc_session::Limit;
use rustc_span::{Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(trait_selection::dump_vtable_entries)]
+#[derive(Diagnostic)]
+#[diag(trait_selection_dump_vtable_entries)]
pub struct DumpVTableEntries<'a> {
#[primary_span]
pub span: Span,
@@ -13,17 +13,17 @@ pub struct DumpVTableEntries<'a> {
pub entries: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(trait_selection::unable_to_construct_constant_value)]
+#[derive(Diagnostic)]
+#[diag(trait_selection_unable_to_construct_constant_value)]
pub struct UnableToConstructConstantValue<'a> {
#[primary_span]
pub span: Span,
- pub unevaluated: Unevaluated<'a>,
+ pub unevaluated: ty::UnevaluatedConst<'a>,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[help]
-#[diag(trait_selection::auto_deref_reached_recursion_limit, code = "E0055")]
+#[diag(trait_selection_auto_deref_reached_recursion_limit, code = "E0055")]
pub struct AutoDerefReachedRecursionLimit<'a> {
#[primary_span]
#[label]
@@ -33,24 +33,24 @@ pub struct AutoDerefReachedRecursionLimit<'a> {
pub crate_name: Symbol,
}
-#[derive(SessionDiagnostic)]
-#[diag(trait_selection::empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[derive(Diagnostic)]
+#[diag(trait_selection_empty_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct EmptyOnClauseInOnUnimplemented {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(trait_selection::invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
+#[derive(Diagnostic)]
+#[diag(trait_selection_invalid_on_clause_in_rustc_on_unimplemented, code = "E0232")]
pub struct InvalidOnClauseInOnUnimplemented {
#[primary_span]
#[label]
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(trait_selection::no_value_in_rustc_on_unimplemented, code = "E0232")]
+#[derive(Diagnostic)]
+#[diag(trait_selection_no_value_in_rustc_on_unimplemented, code = "E0232")]
#[note]
pub struct NoValueInOnUnimplemented {
#[primary_span]
@@ -66,12 +66,12 @@ pub struct NegativePositiveConflict<'a> {
pub positive_impl_span: Result<Span, Symbol>,
}
-impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
+impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> {
fn into_diagnostic(
self,
handler: &Handler,
) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> {
- let mut diag = handler.struct_err(fluent::trait_selection::negative_positive_conflict);
+ let mut diag = handler.struct_err(fluent::trait_selection_negative_positive_conflict);
diag.set_arg("trait_desc", self.trait_desc);
diag.set_arg(
"self_desc",
@@ -81,19 +81,19 @@ impl SessionDiagnostic<'_> for NegativePositiveConflict<'_> {
diag.code(rustc_errors::error_code!(E0751));
match self.negative_impl_span {
Ok(span) => {
- diag.span_label(span, fluent::trait_selection::negative_implementation_here);
+ diag.span_label(span, fluent::negative_implementation_here);
}
Err(cname) => {
- diag.note(fluent::trait_selection::negative_implementation_in_crate);
+ diag.note(fluent::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::trait_selection::positive_implementation_here);
+ diag.span_label(span, fluent::positive_implementation_here);
}
Err(cname) => {
- diag.note(fluent::trait_selection::positive_implementation_in_crate);
+ diag.note(fluent::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 ba403ab2d..a335f8e06 100644
--- a/compiler/rustc_trait_selection/src/infer.rs
+++ b/compiler/rustc_trait_selection/src/infer.rs
@@ -59,7 +59,7 @@ pub trait InferCtxtExt<'tcx> {
param_env: ty::ParamEnv<'tcx>,
) -> traits::EvaluationResult;
}
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
fn type_is_copy_modulo_regions(
&self,
param_env: ty::ParamEnv<'tcx>,
@@ -69,7 +69,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
let ty = self.resolve_vars_if_possible(ty);
if !(param_env, ty).needs_infer() {
- return ty.is_copy_modulo_regions(self.tcx.at(span), param_env);
+ return ty.is_copy_modulo_regions(self.tcx, param_env);
}
let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None);
@@ -142,7 +142,7 @@ pub trait InferCtxtBuilderExt<'tcx> {
fn enter_canonical_trait_query<K, R>(
&mut self,
canonical_key: &Canonical<'tcx, K>,
- operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+ operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
where
K: TypeFoldable<'tcx>,
@@ -170,25 +170,17 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
fn enter_canonical_trait_query<K, R>(
&mut self,
canonical_key: &Canonical<'tcx, K>,
- operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
+ operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>,
) -> Fallible<CanonicalizedQueryResponse<'tcx, R>>
where
K: TypeFoldable<'tcx>,
R: Debug + TypeFoldable<'tcx>,
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
{
- self.enter_with_canonical(
- DUMMY_SP,
- canonical_key,
- |ref infcx, key, canonical_inference_vars| {
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- let value = operation(infcx, &mut *fulfill_cx, key)?;
- infcx.make_canonicalized_query_response(
- canonical_inference_vars,
- value,
- &mut *fulfill_cx,
- )
- },
- )
+ let (ref infcx, key, canonical_inference_vars) =
+ self.build_with_canonical(DUMMY_SP, canonical_key);
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ let value = operation(infcx, &mut *fulfill_cx, key)?;
+ infcx.make_canonicalized_query_response(canonical_inference_vars, value, &mut *fulfill_cx)
}
}
diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs
index d35f74974..5d52aa075 100644
--- a/compiler/rustc_trait_selection/src/lib.rs
+++ b/compiler/rustc_trait_selection/src/lib.rs
@@ -16,9 +16,7 @@
#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(hash_drain_filter)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(if_let_guard)]
#![feature(never_type)]
#![feature(type_alias_impl_trait)]
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index bcdfa4f12..ed34ab95a 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -10,7 +10,7 @@ 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::{Region, RegionVid};
+use rustc_middle::ty::{PolyTraitRef, Region, RegionVid};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -66,13 +66,13 @@ impl<'tcx> AutoTraitFinder<'tcx> {
/// struct Foo<T> { data: Box<T> }
/// ```
///
- /// then this might return that Foo<T>: Send if T: Send (encoded in the AutoTraitResult type).
- /// The analysis attempts to account for custom impls as well as other complex cases. This
- /// result is intended for use by rustdoc and other such consumers.
+ /// then this might return that `Foo<T>: Send` if `T: Send` (encoded in the AutoTraitResult
+ /// type). The analysis attempts to account for custom impls as well as other complex cases.
+ /// This result is intended for use by rustdoc and other such consumers.
///
/// (Note that due to the coinductive nature of Send, the full and correct result is actually
/// quite simple to generate. That is, when a type has no custom impl, it is Send iff its field
- /// types are all Send. So, in our example, we might have that Foo<T>: Send if Box<T>: Send.
+ /// types are all Send. So, in our example, we might have that `Foo<T>: Send` if `Box<T>: Send`.
/// But this is often not the best way to present to the user.)
///
/// Warning: The API should be considered highly unstable, and it may be refactored or removed
@@ -90,143 +90,105 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let trait_pred = ty::Binder::dummy(trait_ref);
- let bail_out = tcx.infer_ctxt().enter(|infcx| {
- let mut selcx = SelectionContext::new(&infcx);
- let result = selcx.select(&Obligation::new(
- ObligationCause::dummy(),
- orig_env,
- trait_pred.to_poly_trait_predicate(),
- ));
-
- match result {
- Ok(Some(ImplSource::UserDefined(_))) => {
- debug!(
- "find_auto_trait_generics({:?}): \
- manual impl found, bailing out",
- trait_ref
- );
- return true;
- }
- _ => {}
+ let infcx = tcx.infer_ctxt().build();
+ let mut selcx = SelectionContext::new(&infcx);
+ for f in [
+ PolyTraitRef::to_poly_trait_predicate,
+ PolyTraitRef::to_poly_trait_predicate_negative_polarity,
+ ] {
+ let result =
+ selcx.select(&Obligation::new(ObligationCause::dummy(), orig_env, f(&trait_pred)));
+ if let Ok(Some(ImplSource::UserDefined(_))) = result {
+ debug!(
+ "find_auto_trait_generics({:?}): \
+ manual impl found, bailing out",
+ trait_ref
+ );
+ // If an explicit impl exists, it always takes priority over an auto impl
+ return AutoTraitResult::ExplicitImpl;
}
-
- let result = selcx.select(&Obligation::new(
- ObligationCause::dummy(),
- orig_env,
- trait_pred.to_poly_trait_predicate_negative_polarity(),
- ));
-
- match result {
- Ok(Some(ImplSource::UserDefined(_))) => {
- debug!(
- "find_auto_trait_generics({:?}): \
- manual impl found, bailing out",
- trait_ref
- );
- true
- }
- _ => false,
- }
- });
-
- // If an explicit impl exists, it always takes priority over an auto impl
- if bail_out {
- return AutoTraitResult::ExplicitImpl;
}
- tcx.infer_ctxt().enter(|infcx| {
- let mut fresh_preds = FxHashSet::default();
+ let infcx = tcx.infer_ctxt().build();
+ let mut fresh_preds = FxHashSet::default();
+
+ // Due to the way projections are handled by SelectionContext, we need to run
+ // evaluate_predicates twice: once on the original param env, and once on the result of
+ // the first evaluate_predicates call.
+ //
+ // The problem is this: most of rustc, including SelectionContext and traits::project,
+ // are designed to work with a concrete usage of a type (e.g., Vec<u8>
+ // fn<T>() { Vec<T> }. This information will generally never change - given
+ // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
+ // If we're unable to prove that 'T' implements a particular trait, we're done -
+ // there's nothing left to do but error out.
+ //
+ // However, synthesizing an auto trait impl works differently. Here, we start out with
+ // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
+ // with - and progressively discover the conditions we need to fulfill for it to
+ // implement a certain auto trait. This ends up breaking two assumptions made by trait
+ // selection and projection:
+ //
+ // * We can always cache the result of a particular trait selection for the lifetime of
+ // an InfCtxt
+ // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
+ // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
+ //
+ // We fix the first assumption by manually clearing out all of the InferCtxt's caches
+ // in between calls to SelectionContext.select. This allows us to keep all of the
+ // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
+ // them between calls.
+ //
+ // We fix the second assumption by reprocessing the result of our first call to
+ // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
+ // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
+ // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
+ // SelectionContext to return it back to us.
+
+ let Some((new_env, user_env)) = self.evaluate_predicates(
+ &infcx,
+ trait_did,
+ ty,
+ orig_env,
+ orig_env,
+ &mut fresh_preds,
+ false,
+ ) else {
+ return AutoTraitResult::NegativeImpl;
+ };
+
+ let (full_env, full_user_env) = self
+ .evaluate_predicates(&infcx, trait_did, ty, new_env, user_env, &mut fresh_preds, true)
+ .unwrap_or_else(|| {
+ panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
+ });
- // Due to the way projections are handled by SelectionContext, we need to run
- // evaluate_predicates twice: once on the original param env, and once on the result of
- // the first evaluate_predicates call.
- //
- // The problem is this: most of rustc, including SelectionContext and traits::project,
- // are designed to work with a concrete usage of a type (e.g., Vec<u8>
- // fn<T>() { Vec<T> }. This information will generally never change - given
- // the 'T' in fn<T>() { ... }, we'll never know anything else about 'T'.
- // If we're unable to prove that 'T' implements a particular trait, we're done -
- // there's nothing left to do but error out.
- //
- // However, synthesizing an auto trait impl works differently. Here, we start out with
- // a set of initial conditions - the ParamEnv of the struct/enum/union we're dealing
- // with - and progressively discover the conditions we need to fulfill for it to
- // implement a certain auto trait. This ends up breaking two assumptions made by trait
- // selection and projection:
- //
- // * We can always cache the result of a particular trait selection for the lifetime of
- // an InfCtxt
- // * Given a projection bound such as '<T as SomeTrait>::SomeItem = K', if 'T:
- // SomeTrait' doesn't hold, then we don't need to care about the 'SomeItem = K'
- //
- // We fix the first assumption by manually clearing out all of the InferCtxt's caches
- // in between calls to SelectionContext.select. This allows us to keep all of the
- // intermediate types we create bound to the 'tcx lifetime, rather than needing to lift
- // them between calls.
- //
- // We fix the second assumption by reprocessing the result of our first call to
- // evaluate_predicates. Using the example of '<T as SomeTrait>::SomeItem = K', our first
- // pass will pick up 'T: SomeTrait', but not 'SomeItem = K'. On our second pass,
- // traits::project will see that 'T: SomeTrait' is in our ParamEnv, allowing
- // SelectionContext to return it back to us.
-
- let Some((new_env, user_env)) = self.evaluate_predicates(
- &infcx,
- trait_did,
- ty,
- orig_env,
- orig_env,
- &mut fresh_preds,
- false,
- ) else {
- return AutoTraitResult::NegativeImpl;
- };
-
- let (full_env, full_user_env) = self
- .evaluate_predicates(
- &infcx,
- trait_did,
- ty,
- new_env,
- user_env,
- &mut fresh_preds,
- true,
- )
- .unwrap_or_else(|| {
- panic!("Failed to fully process: {:?} {:?} {:?}", ty, trait_did, orig_env)
- });
-
- debug!(
- "find_auto_trait_generics({:?}): fulfilling \
- with {:?}",
- trait_ref, full_env
- );
- infcx.clear_caches();
-
- // At this point, we already have all of the bounds we need. FulfillmentContext is used
- // to store all of the necessary region/lifetime bounds in the InferContext, as well as
- // an additional sanity check.
- let errors =
- super::fully_solve_bound(&infcx, ObligationCause::dummy(), full_env, ty, trait_did);
- if !errors.is_empty() {
- panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
- }
+ debug!(
+ "find_auto_trait_generics({:?}): fulfilling \
+ with {:?}",
+ trait_ref, full_env
+ );
+ infcx.clear_caches();
+
+ // At this point, we already have all of the bounds we need. FulfillmentContext is used
+ // to store all of the necessary region/lifetime bounds in the InferContext, as well as
+ // an additional sanity check.
+ let errors =
+ super::fully_solve_bound(&infcx, ObligationCause::dummy(), full_env, ty, trait_did);
+ if !errors.is_empty() {
+ panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
+ }
- infcx.process_registered_region_obligations(&Default::default(), full_env);
+ infcx.process_registered_region_obligations(&Default::default(), full_env);
- let region_data = infcx
- .inner
- .borrow_mut()
- .unwrap_region_constraints()
- .region_constraint_data()
- .clone();
+ let region_data =
+ infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();
- let vid_to_region = self.map_vid_to_region(&region_data);
+ let vid_to_region = self.map_vid_to_region(&region_data);
- let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
+ let info = AutoTraitInfo { full_user_env, region_data, vid_to_region };
- AutoTraitResult::PositiveImpl(auto_trait_callback(info))
- })
+ AutoTraitResult::PositiveImpl(auto_trait_callback(info))
}
}
@@ -272,7 +234,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
/// user.
fn evaluate_predicates(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
trait_did: DefId,
ty: Ty<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@@ -834,7 +796,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
let reported =
tcx.sess.emit_err(UnableToConstructConstantValue {
span: tcx.def_span(def_id),
- unevaluated: unevaluated.expand(),
+ unevaluated: unevaluated,
});
Err(ErrorHandled::Reported(reported))
}
@@ -877,7 +839,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
pub fn clean_pred(
&self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
p: ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> {
infcx.freshen(p)
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 9ef7ac9a8..81e1d6449 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -28,7 +28,7 @@ impl FulfillmentContext<'_> {
impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
fn normalize_projection_type(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
_param_env: ty::ParamEnv<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
_cause: ObligationCause<'tcx>,
@@ -38,7 +38,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
fn register_predicate_obligation(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>,
) {
assert!(!infcx.is_in_snapshot());
@@ -49,7 +49,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.obligations.insert(obligation);
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+ fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
{
let errors = self.select_where_possible(infcx);
@@ -71,10 +71,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
.collect()
}
- fn select_where_possible(
- &mut self,
- infcx: &InferCtxt<'_, 'tcx>,
- ) -> Vec<FulfillmentError<'tcx>> {
+ fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
assert!(!infcx.is_in_snapshot());
let mut errors = Vec::new();
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs
index 08adbcbd4..8a62bf015 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_trait_selection/src/traits/codegen.rs
@@ -4,10 +4,12 @@
// general routines.
use crate::infer::{DefiningAnchor, TyCtxtInferExt};
+use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::{
ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
Unimplemented,
};
+use rustc_infer::traits::FulfillmentErrorCode;
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt};
@@ -27,52 +29,61 @@ pub fn codegen_select_candidate<'tcx>(
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
- let mut infcx_builder =
- tcx.infer_ctxt().ignoring_regions().with_opaque_type_inference(DefiningAnchor::Bubble);
- infcx_builder.enter(|infcx| {
- //~^ HACK `Bubble` is required for
- // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
- let mut selcx = SelectionContext::new(&infcx);
+ let infcx = tcx
+ .infer_ctxt()
+ .ignoring_regions()
+ .with_opaque_type_inference(DefiningAnchor::Bubble)
+ .build();
+ //~^ HACK `Bubble` is required for
+ // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+ let mut selcx = SelectionContext::new(&infcx);
- let obligation_cause = ObligationCause::dummy();
- let obligation =
- Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
+ let obligation_cause = ObligationCause::dummy();
+ let obligation =
+ Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate());
- let selection = match selcx.select(&obligation) {
- Ok(Some(selection)) => selection,
- Ok(None) => return Err(CodegenObligationError::Ambiguity),
- Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
- Err(e) => {
- bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
- }
- };
+ let selection = match selcx.select(&obligation) {
+ Ok(Some(selection)) => selection,
+ Ok(None) => return Err(CodegenObligationError::Ambiguity),
+ Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
+ Err(e) => {
+ bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
+ }
+ };
- debug!(?selection);
+ debug!(?selection);
- // Currently, we use a fulfillment context to completely resolve
- // all nested obligations. This is because they can inform the
- // inference of the impl's type parameters.
- let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
- let impl_source = selection.map(|predicate| {
- fulfill_cx.register_predicate_obligation(&infcx, predicate);
- });
+ // Currently, we use a fulfillment context to completely resolve
+ // all nested obligations. This is because they can inform the
+ // inference of the impl's type parameters.
+ let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
+ let impl_source = selection.map(|predicate| {
+ fulfill_cx.register_predicate_obligation(&infcx, predicate);
+ });
- // In principle, we only need to do this so long as `impl_source`
- // contains unbound type parameters. It could be a slight
- // optimization to stop iterating early.
- let errors = fulfill_cx.select_all_or_error(&infcx);
- if !errors.is_empty() {
- return Err(CodegenObligationError::FulfillmentError);
+ // In principle, we only need to do this so long as `impl_source`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ // `rustc_monomorphize::collector` assumes there are no type errors.
+ // Cycle errors are the only post-monomorphization errors possible; emit them now so
+ // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
+ for err in errors {
+ if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+ infcx.err_ctxt().report_overflow_error_cycle(&cycle);
+ }
}
+ return Err(CodegenObligationError::FulfillmentError);
+ }
- let impl_source = infcx.resolve_vars_if_possible(impl_source);
- let impl_source = infcx.tcx.erase_regions(impl_source);
+ let impl_source = infcx.resolve_vars_if_possible(impl_source);
+ let impl_source = infcx.tcx.erase_regions(impl_source);
- // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
- // as they will get constrained elsewhere, too.
- // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+ // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
+ // as they will get constrained elsewhere, too.
+ // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- Ok(&*tcx.arena.alloc(impl_source))
- })
+ Ok(&*tcx.arena.alloc(impl_source))
}
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs
index 292787d4d..8aab75490 100644
--- a/compiler/rustc_trait_selection/src/traits/coherence.rs
+++ b/compiler/rustc_trait_selection/src/traits/coherence.rs
@@ -22,7 +22,6 @@ use rustc_infer::infer::{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::subst::Subst;
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitor};
use rustc_span::symbol::sym;
@@ -61,23 +60,17 @@ pub fn add_placeholder_note(err: &mut Diagnostic) {
);
}
-/// If there are types that satisfy both impls, invokes `on_overlap`
+/// If there are types that satisfy both impls, returns `Some`
/// with a suitably-freshened `ImplHeader` with those types
-/// substituted. Otherwise, invokes `no_overlap`.
-#[instrument(skip(tcx, skip_leak_check, on_overlap, no_overlap), level = "debug")]
-pub fn overlapping_impls<F1, F2, R>(
+/// substituted. Otherwise, returns `None`.
+#[instrument(skip(tcx, skip_leak_check), level = "debug")]
+pub fn overlapping_impls(
tcx: TyCtxt<'_>,
impl1_def_id: DefId,
impl2_def_id: DefId,
skip_leak_check: SkipLeakCheck,
overlap_mode: OverlapMode,
- on_overlap: F1,
- no_overlap: F2,
-) -> R
-where
- F1: FnOnce(OverlapResult<'_>) -> R,
- F2: FnOnce() -> R,
-{
+) -> Option<OverlapResult<'_>> {
// Before doing expensive operations like entering an inference context, do
// a quick check via fast_reject to tell if the impl headers could possibly
// unify.
@@ -98,28 +91,24 @@ where
if !may_overlap {
// Some types involved are definitely different, so the impls couldn't possibly overlap.
debug!("overlapping_impls: fast_reject early-exit");
- return no_overlap();
+ return None;
}
- let overlaps = tcx.infer_ctxt().enter(|infcx| {
- let selcx = &mut SelectionContext::intercrate(&infcx);
- overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some()
- });
-
+ let infcx = tcx.infer_ctxt().build();
+ let selcx = &mut SelectionContext::intercrate(&infcx);
+ let overlaps =
+ overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some();
if !overlaps {
- return no_overlap();
+ return None;
}
// In the case where we detect an error, run the check again, but
// this time tracking intercrate ambiguity causes for better
// diagnostics. (These take time and can lead to false errors.)
- tcx.infer_ctxt().enter(|infcx| {
- let selcx = &mut SelectionContext::intercrate(&infcx);
- selcx.enable_tracking_intercrate_ambiguity_causes();
- on_overlap(
- overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap(),
- )
- })
+ let infcx = tcx.infer_ctxt().build();
+ let selcx = &mut SelectionContext::intercrate(&infcx);
+ selcx.enable_tracking_intercrate_ambiguity_causes();
+ Some(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap())
}
fn with_fresh_ty_vars<'cx, 'tcx>(
@@ -168,7 +157,7 @@ fn overlap_within_probe<'cx, 'tcx>(
impl1_def_id: DefId,
impl2_def_id: DefId,
overlap_mode: OverlapMode,
- snapshot: &CombinedSnapshot<'_, 'tcx>,
+ snapshot: &CombinedSnapshot<'tcx>,
) -> Option<OverlapResult<'tcx>> {
let infcx = selcx.infcx();
@@ -198,7 +187,7 @@ fn overlap_within_probe<'cx, 'tcx>(
}
}
- // We disable the leak when when creating the `snapshot` by using
+ // We disable the leak when creating the `snapshot` by using
// `infcx.probe_maybe_disable_leak_check`.
if infcx.leak_check(true, snapshot).is_err() {
debug!("overlap: leak check failed");
@@ -299,37 +288,36 @@ fn negative_impl<'cx, 'tcx>(
let tcx = selcx.infcx().tcx;
// Create an infcx, taking the predicates of impl1 as assumptions:
- tcx.infer_ctxt().enter(|infcx| {
- // create a parameter environment corresponding to a (placeholder) instantiation of impl1
- let impl_env = tcx.param_env(impl1_def_id);
- let subject1 = match traits::fully_normalize(
- &infcx,
- ObligationCause::dummy(),
- impl_env,
- tcx.impl_subject(impl1_def_id),
- ) {
- Ok(s) => s,
- Err(err) => {
- tcx.sess.delay_span_bug(
- tcx.def_span(impl1_def_id),
- format!("failed to fully normalize {:?}: {:?}", impl1_def_id, err),
- );
- return false;
- }
- };
+ let infcx = tcx.infer_ctxt().build();
+ // create a parameter environment corresponding to a (placeholder) instantiation of impl1
+ let impl_env = tcx.param_env(impl1_def_id);
+ let subject1 = match traits::fully_normalize(
+ &infcx,
+ ObligationCause::dummy(),
+ impl_env,
+ tcx.impl_subject(impl1_def_id),
+ ) {
+ Ok(s) => s,
+ Err(err) => {
+ tcx.sess.delay_span_bug(
+ tcx.def_span(impl1_def_id),
+ format!("failed to fully normalize {:?}: {:?}", impl1_def_id, err),
+ );
+ return false;
+ }
+ };
- // Attempt to prove that impl2 applies, given all of the above.
- let selcx = &mut SelectionContext::new(&infcx);
- let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
- let (subject2, obligations) =
- impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
+ // Attempt to prove that impl2 applies, given all of the above.
+ let selcx = &mut SelectionContext::new(&infcx);
+ let impl2_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl2_def_id);
+ let (subject2, obligations) =
+ impl_subject_and_oblig(selcx, impl_env, impl2_def_id, impl2_substs);
- !equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
- })
+ !equate(&infcx, impl_env, subject1, subject2, obligations, impl1_def_id)
}
-fn equate<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
+fn equate<'tcx>(
+ infcx: &InferCtxt<'tcx>,
impl_env: ty::ParamEnv<'tcx>,
subject1: ImplSubject<'tcx>,
subject2: ImplSubject<'tcx>,
@@ -380,8 +368,8 @@ fn negative_impl_exists<'cx, 'tcx>(
}
#[instrument(level = "debug", skip(infcx))]
-fn resolve_negative_obligation<'cx, 'tcx>(
- infcx: InferCtxt<'cx, 'tcx>,
+fn resolve_negative_obligation<'tcx>(
+ infcx: InferCtxt<'tcx>,
o: &PredicateObligation<'tcx>,
body_def_id: DefId,
) -> bool {
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 5a213987e..84038625f 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -9,14 +9,12 @@
//! `thir_abstract_const` which can then be checked for structural equality with other
//! generic constants mentioned in the `caller_bounds` of the current environment.
use rustc_errors::ErrorGuaranteed;
-use rustc_hir::def::DefKind;
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::{
walk_abstract_const, AbstractConst, FailureKind, Node, NotConstEvaluatable,
};
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
-use rustc_session::lint;
use rustc_span::Span;
use std::iter;
@@ -101,7 +99,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
a_uv == b_uv
}
// FIXME(generic_const_exprs): We may want to either actually try
- // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like
+ // to evaluate `a_ct` and `b_ct` if they are fully concrete or something like
// this, for now we just return false here.
_ => false,
}
@@ -138,7 +136,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> {
#[instrument(skip(tcx), level = "debug")]
pub fn try_unify_abstract_consts<'tcx>(
tcx: TyCtxt<'tcx>,
- (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>),
+ (a, b): (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>),
param_env: ty::ParamEnv<'tcx>,
) -> bool {
(|| {
@@ -159,13 +157,22 @@ pub fn try_unify_abstract_consts<'tcx>(
/// Check if a given constant can be evaluated.
#[instrument(skip(infcx), level = "debug")]
-pub fn is_const_evaluatable<'cx, 'tcx>(
- infcx: &InferCtxt<'cx, 'tcx>,
- uv: ty::Unevaluated<'tcx, ()>,
+pub fn is_const_evaluatable<'tcx>(
+ infcx: &InferCtxt<'tcx>,
+ ct: ty::Const<'tcx>,
param_env: ty::ParamEnv<'tcx>,
span: Span,
) -> Result<(), NotConstEvaluatable> {
let tcx = infcx.tcx;
+ let uv = match ct.kind() {
+ ty::ConstKind::Unevaluated(uv) => uv,
+ ty::ConstKind::Param(_)
+ | ty::ConstKind::Bound(_, _)
+ | ty::ConstKind::Placeholder(_)
+ | ty::ConstKind::Value(_)
+ | ty::ConstKind::Error(_) => return Ok(()),
+ ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
+ };
if tcx.features().generic_const_exprs {
if let Some(ct) = AbstractConst::new(tcx, uv)? {
@@ -235,39 +242,25 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
.emit()
}
- Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
- NotConstEvaluatable::MentionsInfer
- } else if uv.has_param_types_or_consts() {
- NotConstEvaluatable::MentionsParam
- } else {
- let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
- NotConstEvaluatable::Error(guar)
- }),
+ Err(ErrorHandled::TooGeneric) => {
+ let err = if uv.has_non_region_infer() {
+ NotConstEvaluatable::MentionsInfer
+ } else if uv.has_non_region_param() {
+ NotConstEvaluatable::MentionsParam
+ } else {
+ let guar = infcx.tcx.sess.delay_span_bug(span, format!("Missing value for constant, but no error reported?"));
+ NotConstEvaluatable::Error(guar)
+ };
+
+ Err(err)
+ },
Err(ErrorHandled::Linted) => {
let reported =
infcx.tcx.sess.delay_span_bug(span, "constant in type had error reported as lint");
Err(NotConstEvaluatable::Error(reported))
}
Err(ErrorHandled::Reported(e)) => Err(NotConstEvaluatable::Error(e)),
- Ok(_) => {
- if uv.substs.has_param_types_or_consts() {
- assert!(matches!(infcx.tcx.def_kind(uv.def.did), DefKind::AnonConst));
- let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
-
- if mir_body.is_polymorphic {
- let Some(local_def_id) = uv.def.did.as_local() else { return Ok(()) };
- tcx.struct_span_lint_hir(
- lint::builtin::CONST_EVALUATABLE_UNCHECKED,
- tcx.hir().local_def_id_to_hir_id(local_def_id),
- span,
- |err| {
- err.build("cannot use constants which depend on generic parameters in types").emit();
- })
- }
- }
-
- Ok(())
- },
+ Ok(_) => Ok(()),
}
}
}
@@ -281,7 +274,7 @@ fn satisfied_from_param_env<'tcx>(
for pred in param_env.caller_bounds() {
match pred.kind().skip_binder() {
ty::PredicateKind::ConstEvaluatable(uv) => {
- if let Some(b_ct) = AbstractConst::new(tcx, uv)? {
+ if let Some(b_ct) = AbstractConst::from_const(tcx, uv)? {
let const_unify_ctxt = ConstUnifyCtxt { tcx, param_env };
// Try to unify with each subtree in the AbstractConst to allow for
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index dba4d4f69..e0c8deec9 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -41,16 +41,16 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
/// Used if you want to have pleasant experience when dealing
/// with obligations outside of hir or mir typeck.
pub struct ObligationCtxt<'a, 'tcx> {
- pub infcx: &'a InferCtxt<'a, 'tcx>,
+ pub infcx: &'a InferCtxt<'tcx>,
engine: RefCell<Box<dyn TraitEngine<'tcx>>>,
}
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
- pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx.tcx)) }
}
- pub fn new_in_snapshot(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+ pub fn new_in_snapshot(infcx: &'a InferCtxt<'tcx>) -> Self {
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new_in_snapshot(infcx.tcx)) }
}
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 efdb1ace1..1217d264a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2,10 +2,10 @@ pub mod on_unimplemented;
pub mod suggestions;
use super::{
- EvaluationResult, FulfillmentContext, FulfillmentError, FulfillmentErrorCode,
- MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
- OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
- PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
+ FulfillmentContext, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes,
+ Obligation, ObligationCause, ObligationCauseCode, OnUnimplementedDirective,
+ OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, PredicateObligation,
+ SelectionContext, SelectionError, TraitNotObjectSafe,
};
use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
@@ -22,6 +22,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_hir::GenericParam;
use rustc_hir::Item;
use rustc_hir::Node;
+use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::TypeTrace;
use rustc_infer::traits::TraitEngine;
use rustc_middle::traits::select::OverflowError;
@@ -32,6 +33,8 @@ use rustc_middle::ty::{
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
TypeVisitable,
};
+use rustc_session::Limit;
+use rustc_span::def_id::LOCAL_CRATE;
use rustc_span::symbol::{kw, sym};
use rustc_span::{ExpnKind, Span, DUMMY_SP};
use std::fmt;
@@ -41,8 +44,8 @@ use std::ops::ControlFlow;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::query::normalize::AtExt as _;
use crate::traits::specialize::to_pretty_impl_header;
-use on_unimplemented::InferCtxtExt as _;
-use suggestions::InferCtxtExt as _;
+use on_unimplemented::TypeErrCtxtExt as _;
+use suggestions::TypeErrCtxtExt as _;
pub use rustc_infer::traits::error_reporting::*;
@@ -63,6 +66,37 @@ pub struct ImplCandidate<'tcx> {
}
pub trait InferCtxtExt<'tcx> {
+ /// Given some node representing a fn-like thing in the HIR map,
+ /// returns a span and `ArgKind` information that describes the
+ /// arguments it expects. This can be supplied to
+ /// `report_arg_count_mismatch`.
+ fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>;
+
+ /// Reports an error when the number of arguments needed by a
+ /// trait match doesn't match the number that the expression
+ /// provides.
+ fn report_arg_count_mismatch(
+ &self,
+ span: Span,
+ found_span: Option<Span>,
+ expected_args: Vec<ArgKind>,
+ found_args: Vec<ArgKind>,
+ is_closure: bool,
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+
+ /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
+ /// in that order, and returns the generic type corresponding to the
+ /// argument of that trait (corresponding to the closure arguments).
+ fn type_implements_fn_trait(
+ &self,
+ param_env: ty::ParamEnv<'tcx>,
+ ty: ty::Binder<'tcx, Ty<'tcx>>,
+ constness: ty::BoundConstness,
+ polarity: ty::ImplPolarity,
+ ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
+}
+
+pub trait TypeErrCtxtExt<'tcx> {
fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
@@ -78,6 +112,8 @@ pub trait InferCtxtExt<'tcx> {
where
T: fmt::Display + TypeFoldable<'tcx>;
+ fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
+
fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
/// The `root_obligation` parameter should be the `root_obligation` field
@@ -90,12 +126,71 @@ pub trait InferCtxtExt<'tcx> {
error: &SelectionError<'tcx>,
fallback_has_occurred: bool,
);
+}
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Given some node representing a fn-like thing in the HIR map,
/// returns a span and `ArgKind` information that describes the
/// arguments it expects. This can be supplied to
/// `report_arg_count_mismatch`.
- fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)>;
+ fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)> {
+ let sm = self.tcx.sess.source_map();
+ let hir = self.tcx.hir();
+ Some(match node {
+ Node::Expr(&hir::Expr {
+ kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }),
+ ..
+ }) => (
+ fn_decl_span,
+ hir.body(body)
+ .params
+ .iter()
+ .map(|arg| {
+ if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
+ *arg.pat
+ {
+ Some(ArgKind::Tuple(
+ Some(span),
+ args.iter()
+ .map(|pat| {
+ sm.span_to_snippet(pat.span)
+ .ok()
+ .map(|snippet| (snippet, "_".to_owned()))
+ })
+ .collect::<Option<Vec<_>>>()?,
+ ))
+ } else {
+ let name = sm.span_to_snippet(arg.pat.span).ok()?;
+ Some(ArgKind::Arg(name, "_".to_owned()))
+ }
+ })
+ .collect::<Option<Vec<ArgKind>>>()?,
+ ),
+ Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
+ | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
+ | Node::TraitItem(&hir::TraitItem {
+ kind: hir::TraitItemKind::Fn(ref sig, _), ..
+ }) => (
+ sig.span,
+ sig.decl
+ .inputs
+ .iter()
+ .map(|arg| match arg.kind {
+ hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
+ Some(arg.span),
+ vec![("_".to_owned(), "_".to_owned()); tys.len()],
+ ),
+ _ => ArgKind::empty(),
+ })
+ .collect::<Vec<ArgKind>>(),
+ ),
+ Node::Ctor(ref variant_data) => {
+ let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
+ (span, vec![ArgKind::empty(); variant_data.fields().len()])
+ }
+ _ => panic!("non-FnLike node found: {:?}", node),
+ })
+ }
/// Reports an error when the number of arguments needed by a
/// trait match doesn't match the number that the expression
@@ -107,21 +202,175 @@ pub trait InferCtxtExt<'tcx> {
expected_args: Vec<ArgKind>,
found_args: Vec<ArgKind>,
is_closure: bool,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+ ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ let kind = if is_closure { "closure" } else { "function" };
+
+ let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
+ let arg_length = arguments.len();
+ let distinct = matches!(other, &[ArgKind::Tuple(..)]);
+ match (arg_length, arguments.get(0)) {
+ (1, Some(&ArgKind::Tuple(_, ref fields))) => {
+ format!("a single {}-tuple as argument", fields.len())
+ }
+ _ => format!(
+ "{} {}argument{}",
+ arg_length,
+ if distinct && arg_length > 1 { "distinct " } else { "" },
+ pluralize!(arg_length)
+ ),
+ }
+ };
+
+ let expected_str = args_str(&expected_args, &found_args);
+ let found_str = args_str(&found_args, &expected_args);
+
+ let mut err = struct_span_err!(
+ self.tcx.sess,
+ span,
+ E0593,
+ "{} is expected to take {}, but it takes {}",
+ kind,
+ expected_str,
+ found_str,
+ );
+
+ err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
+
+ if let Some(found_span) = found_span {
+ err.span_label(found_span, format!("takes {}", found_str));
+
+ // move |_| { ... }
+ // ^^^^^^^^-- def_span
+ //
+ // move |_| { ... }
+ // ^^^^^-- prefix
+ let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
+ // move |_| { ... }
+ // ^^^-- pipe_span
+ let pipe_span =
+ if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
+
+ // Suggest to take and ignore the arguments with expected_args_length `_`s if
+ // found arguments is empty (assume the user just wants to ignore args in this case).
+ // For example, if `expected_args_length` is 2, suggest `|_, _|`.
+ if found_args.is_empty() && is_closure {
+ let underscores = vec!["_"; expected_args.len()].join(", ");
+ err.span_suggestion_verbose(
+ pipe_span,
+ &format!(
+ "consider changing the closure to take and ignore the expected argument{}",
+ pluralize!(expected_args.len())
+ ),
+ format!("|{}|", underscores),
+ Applicability::MachineApplicable,
+ );
+ }
+
+ if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
+ if fields.len() == expected_args.len() {
+ let sugg = fields
+ .iter()
+ .map(|(name, _)| name.to_owned())
+ .collect::<Vec<String>>()
+ .join(", ");
+ err.span_suggestion_verbose(
+ found_span,
+ "change the closure to take multiple arguments instead of a single tuple",
+ format!("|{}|", sugg),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
+ && fields.len() == found_args.len()
+ && is_closure
+ {
+ let sugg = format!(
+ "|({}){}|",
+ found_args
+ .iter()
+ .map(|arg| match arg {
+ ArgKind::Arg(name, _) => name.to_owned(),
+ _ => "_".to_owned(),
+ })
+ .collect::<Vec<String>>()
+ .join(", "),
+ // add type annotations if available
+ if found_args.iter().any(|arg| match arg {
+ ArgKind::Arg(_, ty) => ty != "_",
+ _ => false,
+ }) {
+ format!(
+ ": ({})",
+ fields
+ .iter()
+ .map(|(_, ty)| ty.to_owned())
+ .collect::<Vec<String>>()
+ .join(", ")
+ )
+ } else {
+ String::new()
+ },
+ );
+ err.span_suggestion_verbose(
+ found_span,
+ "change the closure to accept a tuple instead of individual arguments",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
+ err
+ }
- /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce`
- /// in that order, and returns the generic type corresponding to the
- /// argument of that trait (corresponding to the closure arguments).
fn type_implements_fn_trait(
&self,
param_env: ty::ParamEnv<'tcx>,
ty: ty::Binder<'tcx, Ty<'tcx>>,
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
- ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>;
-}
+ ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
+ self.commit_if_ok(|_| {
+ for trait_def_id in [
+ self.tcx.lang_items().fn_trait(),
+ self.tcx.lang_items().fn_mut_trait(),
+ self.tcx.lang_items().fn_once_trait(),
+ ] {
+ let Some(trait_def_id) = trait_def_id else { continue };
+ // Make a fresh inference variable so we can determine what the substitutions
+ // of the trait are.
+ let var = self.next_ty_var(TypeVariableOrigin {
+ span: DUMMY_SP,
+ kind: TypeVariableOriginKind::MiscVariable,
+ });
+ let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
+ let obligation = Obligation::new(
+ ObligationCause::dummy(),
+ param_env,
+ ty.rebind(ty::TraitPredicate {
+ trait_ref: ty::TraitRef::new(trait_def_id, substs),
+ constness,
+ polarity,
+ })
+ .to_predicate(self.tcx),
+ );
+ let mut fulfill_cx = FulfillmentContext::new_in_snapshot();
+ fulfill_cx.register_predicate_obligation(self, obligation);
+ if fulfill_cx.select_all_or_error(self).is_empty() {
+ return Ok((
+ ty::ClosureKind::from_def_id(self.tcx, trait_def_id)
+ .expect("expected to map DefId to ClosureKind"),
+ ty.rebind(self.resolve_vars_if_possible(var)),
+ ));
+ }
+ }
-impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+ Err(())
+ })
+ }
+}
+impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
@@ -251,6 +500,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
bug!();
}
+ fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
+ let suggested_limit = match self.tcx.recursion_limit() {
+ Limit(0) => Limit(2),
+ limit => limit * 2,
+ };
+ err.help(&format!(
+ "consider increasing the recursion limit by adding a \
+ `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
+ suggested_limit,
+ self.tcx.crate_name(LOCAL_CRATE),
+ ));
+ }
+
/// Reports that a cycle was detected which led to overflow and halts
/// compilation. This is equivalent to `report_overflow_error` except
/// that we can give a more helpful error message (and, in particular,
@@ -498,10 +760,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() &&
- Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
+ Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() {
self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty);
}
+ let mut unsatisfied_const = false;
if trait_predicate.is_const_if_const() && obligation.param_env.is_const() {
let non_const_predicate = trait_ref.without_const();
let non_const_obligation = Obligation {
@@ -511,6 +774,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
recursion_depth: obligation.recursion_depth,
};
if self.predicate_may_hold(&non_const_obligation) {
+ unsatisfied_const = true;
err.span_note(
span,
&format!(
@@ -606,11 +870,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Try to report a help message
if is_fn_trait
&& let Ok((implemented_kind, params)) = self.type_implements_fn_trait(
- obligation.param_env,
- trait_ref.self_ty(),
- trait_predicate.skip_binder().constness,
- trait_predicate.skip_binder().polarity,
- )
+ obligation.param_env,
+ trait_ref.self_ty(),
+ trait_predicate.skip_binder().constness,
+ trait_predicate.skip_binder().polarity,
+ )
{
// If the type implements `Fn`, `FnMut`, or `FnOnce`, suppress the following
// suggestion to add trait bounds for the type, since we only typically implement
@@ -661,8 +925,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
);
}
}
- } else if !trait_ref.has_infer_types_or_consts()
- && self.predicate_can_apply(obligation.param_env, trait_ref)
+ } else if !trait_ref.has_non_region_infer()
+ && self.predicate_can_apply(obligation.param_env, trait_predicate)
{
// If a where-clause may be useful, remind the
// user that they can add it.
@@ -677,7 +941,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
None,
obligation.cause.body_id,
);
- } else if !suggested {
+ } else if !suggested && !unsatisfied_const {
// Can't show anything else useful, try to find similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
if !self.report_similar_impl_candidates(
@@ -840,12 +1104,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Additional context information explaining why the closure only implements
// a particular trait.
- if let Some(typeck_results) = self.in_progress_typeck_results {
+ if let Some(typeck_results) = &self.typeck_results {
let hir_id = self
.tcx
.hir()
.local_def_id_to_hir_id(closure_def_id.expect_local());
- let typeck_results = typeck_results.borrow();
match (found_kind, typeck_results.closure_kind_origins().get(hir_id)) {
(ty::ClosureKind::FnOnce, Some((span, place))) => {
err.span_label(
@@ -994,6 +1257,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
found_span,
found_trait_ref,
expected_trait_ref,
+ obligation.cause.code(),
)
} else {
let (closure_span, found) = found_did
@@ -1042,7 +1306,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
match obligation.predicate.kind().skip_binder() {
- ty::PredicateKind::ConstEvaluatable(uv) => {
+ ty::PredicateKind::ConstEvaluatable(ct) => {
+ let ty::ConstKind::Unevaluated(uv) = ct.kind() else {
+ bug!("const evaluatable failed for non-unevaluated const `{ct:?}`");
+ };
let mut err =
self.tcx.sess.struct_span_err(span, "unconstrained generic constant");
let const_span = self.tcx.def_span(uv.def.did);
@@ -1088,250 +1355,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err.emit();
}
-
- /// Given some node representing a fn-like thing in the HIR map,
- /// returns a span and `ArgKind` information that describes the
- /// arguments it expects. This can be supplied to
- /// `report_arg_count_mismatch`.
- fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Vec<ArgKind>)> {
- let sm = self.tcx.sess.source_map();
- let hir = self.tcx.hir();
- Some(match node {
- Node::Expr(&hir::Expr {
- kind: hir::ExprKind::Closure(&hir::Closure { body, fn_decl_span, .. }),
- ..
- }) => (
- fn_decl_span,
- hir.body(body)
- .params
- .iter()
- .map(|arg| {
- if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
- *arg.pat
- {
- Some(ArgKind::Tuple(
- Some(span),
- args.iter()
- .map(|pat| {
- sm.span_to_snippet(pat.span)
- .ok()
- .map(|snippet| (snippet, "_".to_owned()))
- })
- .collect::<Option<Vec<_>>>()?,
- ))
- } else {
- let name = sm.span_to_snippet(arg.pat.span).ok()?;
- Some(ArgKind::Arg(name, "_".to_owned()))
- }
- })
- .collect::<Option<Vec<ArgKind>>>()?,
- ),
- Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref sig, ..), .. })
- | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(ref sig, _), .. })
- | Node::TraitItem(&hir::TraitItem {
- kind: hir::TraitItemKind::Fn(ref sig, _), ..
- }) => (
- sig.span,
- sig.decl
- .inputs
- .iter()
- .map(|arg| match arg.kind {
- hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
- Some(arg.span),
- vec![("_".to_owned(), "_".to_owned()); tys.len()],
- ),
- _ => ArgKind::empty(),
- })
- .collect::<Vec<ArgKind>>(),
- ),
- Node::Ctor(ref variant_data) => {
- let span = variant_data.ctor_hir_id().map_or(DUMMY_SP, |id| hir.span(id));
- (span, vec![ArgKind::empty(); variant_data.fields().len()])
- }
- _ => panic!("non-FnLike node found: {:?}", node),
- })
- }
-
- /// Reports an error when the number of arguments needed by a
- /// trait match doesn't match the number that the expression
- /// provides.
- fn report_arg_count_mismatch(
- &self,
- span: Span,
- found_span: Option<Span>,
- expected_args: Vec<ArgKind>,
- found_args: Vec<ArgKind>,
- is_closure: bool,
- ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
- let kind = if is_closure { "closure" } else { "function" };
-
- let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
- let arg_length = arguments.len();
- let distinct = matches!(other, &[ArgKind::Tuple(..)]);
- match (arg_length, arguments.get(0)) {
- (1, Some(&ArgKind::Tuple(_, ref fields))) => {
- format!("a single {}-tuple as argument", fields.len())
- }
- _ => format!(
- "{} {}argument{}",
- arg_length,
- if distinct && arg_length > 1 { "distinct " } else { "" },
- pluralize!(arg_length)
- ),
- }
- };
-
- let expected_str = args_str(&expected_args, &found_args);
- let found_str = args_str(&found_args, &expected_args);
-
- let mut err = struct_span_err!(
- self.tcx.sess,
- span,
- E0593,
- "{} is expected to take {}, but it takes {}",
- kind,
- expected_str,
- found_str,
- );
-
- err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
-
- if let Some(found_span) = found_span {
- err.span_label(found_span, format!("takes {}", found_str));
-
- // move |_| { ... }
- // ^^^^^^^^-- def_span
- //
- // move |_| { ... }
- // ^^^^^-- prefix
- let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
- // move |_| { ... }
- // ^^^-- pipe_span
- let pipe_span =
- if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
-
- // Suggest to take and ignore the arguments with expected_args_length `_`s if
- // found arguments is empty (assume the user just wants to ignore args in this case).
- // For example, if `expected_args_length` is 2, suggest `|_, _|`.
- if found_args.is_empty() && is_closure {
- let underscores = vec!["_"; expected_args.len()].join(", ");
- err.span_suggestion_verbose(
- pipe_span,
- &format!(
- "consider changing the closure to take and ignore the expected argument{}",
- pluralize!(expected_args.len())
- ),
- format!("|{}|", underscores),
- Applicability::MachineApplicable,
- );
- }
-
- if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
- if fields.len() == expected_args.len() {
- let sugg = fields
- .iter()
- .map(|(name, _)| name.to_owned())
- .collect::<Vec<String>>()
- .join(", ");
- err.span_suggestion_verbose(
- found_span,
- "change the closure to take multiple arguments instead of a single tuple",
- format!("|{}|", sugg),
- Applicability::MachineApplicable,
- );
- }
- }
- if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..]
- && fields.len() == found_args.len()
- && is_closure
- {
- let sugg = format!(
- "|({}){}|",
- found_args
- .iter()
- .map(|arg| match arg {
- ArgKind::Arg(name, _) => name.to_owned(),
- _ => "_".to_owned(),
- })
- .collect::<Vec<String>>()
- .join(", "),
- // add type annotations if available
- if found_args.iter().any(|arg| match arg {
- ArgKind::Arg(_, ty) => ty != "_",
- _ => false,
- }) {
- format!(
- ": ({})",
- fields
- .iter()
- .map(|(_, ty)| ty.to_owned())
- .collect::<Vec<String>>()
- .join(", ")
- )
- } else {
- String::new()
- },
- );
- err.span_suggestion_verbose(
- found_span,
- "change the closure to accept a tuple instead of individual arguments",
- sugg,
- Applicability::MachineApplicable,
- );
- }
- }
-
- err
- }
-
- fn type_implements_fn_trait(
- &self,
- param_env: ty::ParamEnv<'tcx>,
- ty: ty::Binder<'tcx, Ty<'tcx>>,
- constness: ty::BoundConstness,
- polarity: ty::ImplPolarity,
- ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()> {
- self.commit_if_ok(|_| {
- for trait_def_id in [
- self.tcx.lang_items().fn_trait(),
- self.tcx.lang_items().fn_mut_trait(),
- self.tcx.lang_items().fn_once_trait(),
- ] {
- let Some(trait_def_id) = trait_def_id else { continue };
- // Make a fresh inference variable so we can determine what the substitutions
- // of the trait are.
- let var = self.next_ty_var(TypeVariableOrigin {
- span: DUMMY_SP,
- kind: TypeVariableOriginKind::MiscVariable,
- });
- let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]);
- let obligation = Obligation::new(
- ObligationCause::dummy(),
- param_env,
- ty.rebind(ty::TraitPredicate {
- trait_ref: ty::TraitRef::new(trait_def_id, substs),
- constness,
- polarity,
- })
- .to_predicate(self.tcx),
- );
- let mut fulfill_cx = FulfillmentContext::new_in_snapshot();
- fulfill_cx.register_predicate_obligation(self, obligation);
- if fulfill_cx.select_all_or_error(self).is_empty() {
- return Ok((
- ty::ClosureKind::from_def_id(self.tcx, trait_def_id)
- .expect("expected to map DefId to ClosureKind"),
- ty.rebind(self.resolve_vars_if_possible(var)),
- ));
- }
- }
-
- Err(())
- })
- }
}
-trait InferCtxtPrivExt<'hir, 'tcx> {
+trait InferCtxtPrivExt<'tcx> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
@@ -1412,7 +1438,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
fn predicate_can_apply(
&self,
param_env: ty::ParamEnv<'tcx>,
- pred: ty::PolyTraitRef<'tcx>,
+ pred: ty::PolyTraitPredicate<'tcx>,
) -> bool;
fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>);
@@ -1430,13 +1456,13 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
predicate: ty::Predicate<'tcx>,
);
- fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'hir>);
+ fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>);
fn maybe_indirection_for_unsized(
&self,
err: &mut Diagnostic,
- item: &'hir Item<'hir>,
- param: &'hir GenericParam<'hir>,
+ item: &'tcx Item<'tcx>,
+ param: &'tcx GenericParam<'tcx>,
) -> bool;
fn is_recursive_obligation(
@@ -1446,7 +1472,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
) -> bool;
}
-impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
+impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
@@ -1540,6 +1566,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
diag.emit();
}
+ FulfillmentErrorCode::CodeCycle(ref cycle) => {
+ self.report_overflow_error_cycle(cycle);
+ }
}
}
@@ -1636,7 +1665,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
..
})
| hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::TyAlias(ty),
+ kind: hir::ImplItemKind::Type(ty),
..
}),
) => Some((ty.span, format!("type mismatch resolving `{}`", predicate))),
@@ -1895,7 +1924,9 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// FIXME(compiler-errors): This could be generalized, both to
// be more granular, and probably look past other `#[fundamental]`
// types, too.
- self.tcx.visibility(def.did()).is_accessible_from(body_id.owner, self.tcx)
+ self.tcx
+ .visibility(def.did())
+ .is_accessible_from(body_id.owner.def_id, self.tcx)
} else {
true
}
@@ -1905,16 +1936,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
let normalize = |candidate| {
- self.tcx.infer_ctxt().enter(|ref infcx| {
- let normalized = infcx
- .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
- .normalize(candidate)
- .ok();
- match normalized {
- Some(normalized) => normalized.value,
- None => candidate,
- }
- })
+ let infcx = self.tcx.infer_ctxt().build();
+ infcx
+ .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
+ .normalize(candidate)
+ .map_or(candidate, |normalized| normalized.value)
};
// Sort impl candidates so that ordering is consistent for UI tests.
@@ -2088,7 +2114,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
// Pick the first substitution that still contains inference variables as the one
// we're going to emit an error for. If there are none (see above), fall back to
// a more general error.
- let subst = data.trait_ref.substs.iter().find(|s| s.has_infer_types_or_consts());
+ let subst = data.trait_ref.substs.iter().find(|s| s.has_non_region_infer());
let mut err = if let Some(subst) = subst {
self.emit_inference_failure_err(body_id, span, subst, ErrorCode::E0283, true)
@@ -2258,13 +2284,22 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
trait_impls.non_blanket_impls().len()
)
};
-
+ let mut suggestions = vec![(
+ trait_path_segment.ident.span.shrink_to_lo(),
+ format!("<{} as ", self.tcx.type_of(impl_def_id))
+ )];
+ if let Some(generic_arg) = trait_path_segment.args {
+ let between_span = trait_path_segment.ident.span.between(generic_arg.span_ext);
+ // get rid of :: between Trait and <type>
+ // must be '::' between them, otherwise the parser won't accept the code
+ suggestions.push((between_span, "".to_string(),));
+ suggestions.push((generic_arg.span_ext.shrink_to_hi(), format!(">")));
+ } else {
+ suggestions.push((trait_path_segment.ident.span.shrink_to_hi(), format!(">")));
+ }
err.multipart_suggestion(
message,
- vec![
- (trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
- (trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
- ],
+ suggestions,
Applicability::MaybeIncorrect
);
}
@@ -2309,7 +2344,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
.substs
.iter()
.chain(Some(data.term.into_arg()))
- .find(|g| g.has_infer_types_or_consts());
+ .find(|g| g.has_non_region_infer());
if let Some(subst) = subst {
let mut err = self.emit_inference_failure_err(
body_id,
@@ -2338,7 +2373,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
if predicate.references_error() || self.is_tainted_by_errors() {
return;
}
- let subst = data.substs.iter().find(|g| g.has_infer_types_or_consts());
+ let subst = data.walk().find(|g| g.is_non_region_infer());
if let Some(subst) = subst {
let err = self.emit_inference_failure_err(
body_id,
@@ -2478,10 +2513,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
fn predicate_can_apply(
&self,
param_env: ty::ParamEnv<'tcx>,
- pred: ty::PolyTraitRef<'tcx>,
+ pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
struct ParamToVarFolder<'a, 'tcx> {
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
}
@@ -2522,7 +2557,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
let obligation = Obligation::new(
ObligationCause::dummy(),
param_env,
- cleaned_pred.without_const().to_predicate(selcx.tcx()),
+ cleaned_pred.to_predicate(selcx.tcx()),
);
self.predicate_may_hold(&obligation)
@@ -2567,12 +2602,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
}
#[instrument(level = "debug", skip_all)]
- fn maybe_suggest_unsized_generics<'hir>(
- &self,
- err: &mut Diagnostic,
- span: Span,
- node: Node<'hir>,
- ) {
+ fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>) {
let Some(generics) = node.generics() else {
return;
};
@@ -2623,11 +2653,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
);
}
- fn maybe_indirection_for_unsized<'hir>(
+ fn maybe_indirection_for_unsized(
&self,
err: &mut Diagnostic,
- item: &'hir Item<'hir>,
- param: &'hir GenericParam<'hir>,
+ item: &Item<'tcx>,
+ param: &GenericParam<'tcx>,
) -> bool {
// Suggesting `T: ?Sized` is only valid in an ADT if `T` is only used in a
// borrow. `struct S<'a, T: ?Sized>(&'a T);` is valid, `struct S<T: ?Sized>(T);`
@@ -2727,82 +2757,6 @@ impl<'v> Visitor<'v> for FindTypeParam {
}
}
-pub fn recursive_type_with_infinite_size_error<'tcx>(
- tcx: TyCtxt<'tcx>,
- type_def_id: DefId,
- spans: Vec<(Span, Option<hir::HirId>)>,
-) {
- assert!(type_def_id.is_local());
- let span = tcx.def_span(type_def_id);
- let path = tcx.def_path_str(type_def_id);
- let mut err =
- struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
- err.span_label(span, "recursive type has infinite size");
- for &(span, _) in &spans {
- err.span_label(span, "recursive without indirection");
- }
- let msg = format!(
- "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
- path,
- );
- if spans.len() <= 4 {
- // FIXME(compiler-errors): This suggestion might be erroneous if Box is shadowed
- err.multipart_suggestion(
- &msg,
- spans
- .into_iter()
- .flat_map(|(span, field_id)| {
- if let Some(generic_span) = get_option_generic_from_field_id(tcx, field_id) {
- // If we match an `Option` and can grab the span of the Option's generic, then
- // suggest boxing the generic arg for a non-null niche optimization.
- vec![
- (generic_span.shrink_to_lo(), "Box<".to_string()),
- (generic_span.shrink_to_hi(), ">".to_string()),
- ]
- } else {
- vec![
- (span.shrink_to_lo(), "Box<".to_string()),
- (span.shrink_to_hi(), ">".to_string()),
- ]
- }
- })
- .collect(),
- Applicability::HasPlaceholders,
- );
- } else {
- err.help(&msg);
- }
- err.emit();
-}
-
-/// Extract the span for the generic type `T` of `Option<T>` in a field definition
-fn get_option_generic_from_field_id(tcx: TyCtxt<'_>, field_id: Option<hir::HirId>) -> Option<Span> {
- let node = tcx.hir().find(field_id?);
-
- // Expect a field from our field_id
- let Some(hir::Node::Field(field_def)) = node
- else { bug!("Expected HirId corresponding to FieldDef, found: {:?}", node) };
-
- // Match a type that is a simple QPath with no Self
- let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = &field_def.ty.kind
- else { return None };
-
- // Check if the path we're checking resolves to Option
- let hir::def::Res::Def(_, did) = path.res
- else { return None };
-
- // Bail if this path doesn't describe `::core::option::Option`
- if !tcx.is_diagnostic_item(sym::Option, did) {
- return None;
- }
-
- // Match a single generic arg in the 0th path segment
- let generic_arg = path.segments.last()?.args?.args.get(0)?;
-
- // Take the span out of the type, if it's a type
- if let hir::GenericArg::Type(generic_ty) = generic_arg { Some(generic_ty.span) } else { None }
-}
-
/// Summarizes information
#[derive(Clone)]
pub enum ArgKind {
@@ -2847,3 +2801,8 @@ impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
}
}
}
+
+pub enum DefIdOrName {
+ DefId(DefId),
+ Name(&'static str),
+}
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 e11a42201..5eef54c63 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
@@ -1,17 +1,17 @@
use super::{
ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation,
};
-use crate::infer::InferCtxt;
+use crate::infer::error_reporting::TypeErrCtxt;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, GenericParamDefKind};
use rustc_span::symbol::sym;
use std::iter;
use super::InferCtxtPrivExt;
-pub trait InferCtxtExt<'tcx> {
+pub trait TypeErrCtxtExt<'tcx> {
/*private*/
fn impl_similar_to(
&self,
@@ -29,7 +29,7 @@ pub trait InferCtxtExt<'tcx> {
) -> OnUnimplementedNote;
}
-impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn impl_similar_to(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
@@ -164,6 +164,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
flags.push((sym::from_desugaring, Some(format!("{:?}", k))));
}
+ if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
+ flags.push((sym::cause, Some("MainFunctionType".to_string())));
+ }
+
// Add all types without trimmed paths.
ty::print::with_no_trimmed_paths!({
let generics = self.tcx.generics_of(def_id);
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 13d9c1600..8c41d9d24 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1,5 +1,5 @@
use super::{
- EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
+ DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation,
SelectionContext,
};
@@ -7,6 +7,7 @@ use crate::autoderef::Autoderef;
use crate::infer::InferCtxt;
use crate::traits::normalize_to;
+use hir::def::CtorOf;
use hir::HirId;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -20,7 +21,9 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
use rustc_hir::lang_items::LangItem;
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
+use rustc_infer::infer::error_reporting::TypeErrCtxt;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::hir::map;
use rustc_middle::ty::{
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree,
@@ -28,9 +31,7 @@ use rustc_middle::ty::{
ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
};
use rustc_middle::ty::{TypeAndMut, TypeckResults};
-use rustc_session::Limit;
-use rustc_span::def_id::LOCAL_CRATE;
-use rustc_span::symbol::{kw, sym, Ident, Symbol};
+use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{BytePos, DesugaringKind, ExpnKind, Span, DUMMY_SP};
use rustc_target::spec::abi;
use std::fmt;
@@ -62,7 +63,7 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
// meet an obligation
fn try_get_upvar_span<F>(
&self,
- infer_context: &InferCtxt<'a, 'tcx>,
+ infer_context: &InferCtxt<'tcx>,
generator_did: DefId,
ty_matches: F,
) -> Option<GeneratorInteriorOrUpvar>
@@ -168,7 +169,7 @@ impl<'tcx, 'a> GeneratorData<'tcx, 'a> {
}
// This trait is public to expose the diagnostics methods to clippy.
-pub trait InferCtxtExt<'tcx> {
+pub trait TypeErrCtxtExt<'tcx> {
fn suggest_restricting_param_bound(
&self,
err: &mut Diagnostic,
@@ -255,8 +256,15 @@ pub trait InferCtxtExt<'tcx> {
found_span: Option<Span>,
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
+ cause: &ObligationCauseCode<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>;
+ fn note_conflicting_closure_bounds(
+ &self,
+ cause: &ObligationCauseCode<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+ );
+
fn suggest_fully_qualified_path(
&self,
err: &mut Diagnostic,
@@ -296,8 +304,6 @@ pub trait InferCtxtExt<'tcx> {
) where
T: fmt::Display;
- fn suggest_new_overflow_limit(&self, err: &mut Diagnostic);
-
/// Suggest to await before try: future? => future.await?
fn suggest_await_before_try(
&self,
@@ -461,7 +467,7 @@ fn suggest_restriction<'tcx>(
}
}
-impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
fn suggest_restricting_param_bound(
&self,
mut err: &mut Diagnostic,
@@ -659,7 +665,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
_ => {}
}
- hir_id = self.tcx.hir().local_def_id_to_hir_id(self.tcx.hir().get_parent_item(hir_id));
+ hir_id = self.tcx.hir().get_parent_item(hir_id).into();
}
}
@@ -675,9 +681,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// It only make sense when suggesting dereferences for arguments
let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
else { return false; };
- let Some(typeck_results) = self.in_progress_typeck_results
+ let Some(typeck_results) = &self.typeck_results
else { return false; };
- let typeck_results = typeck_results.borrow();
let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
else { return false; };
let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
@@ -809,74 +814,136 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err: &mut Diagnostic,
trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> bool {
- // Skipping binder here, remapping below
- let self_ty = trait_pred.self_ty().skip_binder();
-
- let (def_id, output_ty, callable) = match *self_ty.kind() {
- ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"),
- ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
- _ => return false,
- };
- let msg = format!("use parentheses to call the {}", callable);
+ if let ty::PredicateKind::Trait(trait_pred) = obligation.predicate.kind().skip_binder()
+ && Some(trait_pred.def_id()) == self.tcx.lang_items().sized_trait()
+ {
+ // Don't suggest calling to turn an unsized type into a sized type
+ return false;
+ }
- // "We should really create a single list of bound vars from the combined vars
- // from the predicate and function, but instead we just liberate the function bound vars"
- let output_ty = self.tcx.liberate_late_bound_regions(def_id, output_ty);
+ // This is duplicated from `extract_callable_info` in typeck, which
+ // relies on autoderef, so we can't use it here.
+ let found = trait_pred.self_ty().skip_binder().peel_refs();
+ let Some((def_id_or_name, output, inputs)) = (match *found.kind()
+ {
+ ty::FnPtr(fn_sig) => {
+ Some((DefIdOrName::Name("function pointer"), fn_sig.output(), fn_sig.inputs()))
+ }
+ ty::FnDef(def_id, _) => {
+ let fn_sig = found.fn_sig(self.tcx);
+ Some((DefIdOrName::DefId(def_id), fn_sig.output(), fn_sig.inputs()))
+ }
+ ty::Closure(def_id, substs) => {
+ let fn_sig = substs.as_closure().sig();
+ Some((
+ DefIdOrName::DefId(def_id),
+ fn_sig.output(),
+ fn_sig.inputs().map_bound(|inputs| &inputs[1..]),
+ ))
+ }
+ ty::Opaque(def_id, substs) => {
+ self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| {
+ if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder()
+ && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ // args tuple will always be substs[1]
+ && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+ {
+ Some((
+ DefIdOrName::DefId(def_id),
+ pred.kind().rebind(proj.term.ty().unwrap()),
+ pred.kind().rebind(args.as_slice()),
+ ))
+ } else {
+ None
+ }
+ })
+ }
+ ty::Dynamic(data, _, ty::Dyn) => {
+ data.iter().find_map(|pred| {
+ if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder()
+ && Some(proj.item_def_id) == self.tcx.lang_items().fn_once_output()
+ // for existential projection, substs are shifted over by 1
+ && let ty::Tuple(args) = proj.substs.type_at(0).kind()
+ {
+ Some((
+ DefIdOrName::Name("trait object"),
+ pred.rebind(proj.term.ty().unwrap()),
+ pred.rebind(args.as_slice()),
+ ))
+ } else {
+ None
+ }
+ })
+ }
+ ty::Param(_) => {
+ obligation.param_env.caller_bounds().iter().find_map(|pred| {
+ if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder()
+ && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output()
+ && proj.projection_ty.self_ty() == found
+ // args tuple will always be substs[1]
+ && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind()
+ {
+ Some((
+ DefIdOrName::Name("type parameter"),
+ pred.kind().rebind(proj.term.ty().unwrap()),
+ pred.kind().rebind(args.as_slice()),
+ ))
+ } else {
+ None
+ }
+ })
+ }
+ _ => None,
+ }) else { return false; };
+ let output = self.replace_bound_vars_with_fresh_vars(
+ obligation.cause.span,
+ LateBoundRegionConversionTime::FnCall,
+ output,
+ );
+ let inputs = inputs.skip_binder().iter().map(|ty| {
+ self.replace_bound_vars_with_fresh_vars(
+ obligation.cause.span,
+ LateBoundRegionConversionTime::FnCall,
+ inputs.rebind(*ty),
+ )
+ });
// Remapping bound vars here
- let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output_ty));
+ let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, output));
let new_obligation =
self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self);
-
- match self.evaluate_obligation(&new_obligation) {
- Ok(
- EvaluationResult::EvaluatedToOk
- | EvaluationResult::EvaluatedToOkModuloRegions
- | EvaluationResult::EvaluatedToOkModuloOpaqueTypes
- | EvaluationResult::EvaluatedToAmbig,
- ) => {}
- _ => return false,
+ if !self.predicate_must_hold_modulo_regions(&new_obligation) {
+ return false;
}
- let hir = self.tcx.hir();
+
// Get the name of the callable and the arguments to be used in the suggestion.
- let (snippet, sugg) = match hir.get_if_local(def_id) {
- Some(hir::Node::Expr(hir::Expr {
- kind: hir::ExprKind::Closure(hir::Closure { fn_decl, fn_decl_span, .. }),
- ..
- })) => {
- err.span_label(*fn_decl_span, "consider calling this closure");
- let Some(name) = self.get_closure_name(def_id, err, &msg) else {
- return false;
- };
- let args = fn_decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
- let sugg = format!("({})", args);
- (format!("{}{}", name, sugg), sugg)
- }
- Some(hir::Node::Item(hir::Item {
- ident,
- kind: hir::ItemKind::Fn(.., body_id),
- ..
- })) => {
- err.span_label(ident.span, "consider calling this function");
- let body = hir.body(*body_id);
- let args = body
- .params
- .iter()
- .map(|arg| match &arg.pat.kind {
- hir::PatKind::Binding(_, _, ident, None)
- // FIXME: provide a better suggestion when encountering `SelfLower`, it
- // should suggest a method call.
- if ident.name != kw::SelfLower => ident.to_string(),
- _ => "_".to_string(),
- })
- .collect::<Vec<_>>()
- .join(", ");
- let sugg = format!("({})", args);
- (format!("{}{}", ident, sugg), sugg)
- }
- _ => return false,
+ let hir = self.tcx.hir();
+
+ let msg = match def_id_or_name {
+ DefIdOrName::DefId(def_id) => match self.tcx.def_kind(def_id) {
+ DefKind::Ctor(CtorOf::Struct, _) => {
+ "use parentheses to construct this tuple struct".to_string()
+ }
+ DefKind::Ctor(CtorOf::Variant, _) => {
+ "use parentheses to construct this tuple variant".to_string()
+ }
+ kind => format!("use parentheses to call this {}", kind.descr(def_id)),
+ },
+ DefIdOrName::Name(name) => format!("use parentheses to call this {name}"),
};
+
+ let args = inputs
+ .map(|ty| {
+ if ty.is_suggestable(self.tcx, false) {
+ format!("/* {ty} */")
+ } else {
+ "/* value */".to_string()
+ }
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+
if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
&& obligation.cause.span.can_be_used_for_suggestions()
{
@@ -887,11 +954,36 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
err.span_suggestion_verbose(
obligation.cause.span.shrink_to_hi(),
&msg,
- sugg,
+ format!("({args})"),
Applicability::HasPlaceholders,
);
- } else {
- err.help(&format!("{}: `{}`", msg, snippet));
+ } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
+ let name = match hir.get_if_local(def_id) {
+ Some(hir::Node::Expr(hir::Expr {
+ kind: hir::ExprKind::Closure(hir::Closure { fn_decl_span, .. }),
+ ..
+ })) => {
+ err.span_label(*fn_decl_span, "consider calling this closure");
+ let Some(name) = self.get_closure_name(def_id, err, &msg) else {
+ return false;
+ };
+ name.to_string()
+ }
+ Some(hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(..), .. })) => {
+ err.span_label(ident.span, "consider calling this function");
+ ident.to_string()
+ }
+ Some(hir::Node::Ctor(..)) => {
+ let name = self.tcx.def_path_str(def_id);
+ err.span_label(
+ self.tcx.def_span(def_id),
+ format!("consider calling the constructor for `{}`", name),
+ );
+ name
+ }
+ _ => return false,
+ };
+ err.help(&format!("{msg}: `{name}({args})`"));
}
true
}
@@ -1176,8 +1268,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&format!("this call returns `{}`", pred.self_ty()),
);
}
- if let Some(typeck_results) =
- self.in_progress_typeck_results.map(|t| t.borrow())
+ if let Some(typeck_results) = &self.typeck_results
&& let ty = typeck_results.expr_ty_adjusted(base)
&& let ty::FnDef(def_id, _substs) = ty.kind()
&& let Some(hir::Node::Item(hir::Item { ident, span, vis_span, .. })) =
@@ -1231,7 +1322,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
return;
}
let trait_pred = self.resolve_vars_if_possible(trait_pred);
- if trait_pred.has_infer_types_or_consts() {
+ if trait_pred.has_non_region_infer() {
// Do not ICE while trying to find if a reborrow would succeed on a trait with
// unresolved bindings.
return;
@@ -1300,8 +1391,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
&& let Some(stmt) = blk.stmts.last()
&& let hir::StmtKind::Semi(expr) = stmt.kind
// Only suggest this if the expression behind the semicolon implements the predicate
- && let Some(typeck_results) = self.in_progress_typeck_results
- && let Some(ty) = typeck_results.borrow().expr_ty_opt(expr)
+ && let Some(typeck_results) = &self.typeck_results
+ && let Some(ty) = typeck_results.expr_ty_opt(expr)
&& self.predicate_may_hold(&self.mk_trait_obligation_with_new_self_ty(
obligation.param_env, trait_pred.map_bound(|trait_pred| (trait_pred, ty))
))
@@ -1390,7 +1481,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut visitor = ReturnsVisitor::default();
visitor.visit_body(&body);
- let typeck_results = self.in_progress_typeck_results.map(|t| t.borrow()).unwrap();
+ let typeck_results = self.typeck_results.as_ref().unwrap();
let Some(liberated_sig) = typeck_results.liberated_fn_sigs().get(fn_hir_id).copied() else { return false; };
let ret_types = visitor
@@ -1425,7 +1516,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let mut spans_and_needs_box = vec![];
match liberated_sig.output().kind() {
- ty::Dynamic(predicates, _, _) => {
+ ty::Dynamic(predicates, _, ty::Dyn) => {
let cause = ObligationCause::misc(ret_ty.span, fn_hir_id);
let param_env = ty::ParamEnv::empty();
@@ -1573,7 +1664,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Point at all the `return`s in the function as they have failed trait bounds.
let mut visitor = ReturnsVisitor::default();
visitor.visit_body(&body);
- let typeck_results = self.in_progress_typeck_results.map(|t| t.borrow()).unwrap();
+ let typeck_results = self.typeck_results.as_ref().unwrap();
for expr in &visitor.returns {
if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) {
let ty = self.resolve_vars_if_possible(returned_ty);
@@ -1589,9 +1680,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
found_span: Option<Span>,
found: ty::PolyTraitRef<'tcx>,
expected: ty::PolyTraitRef<'tcx>,
+ cause: &ObligationCauseCode<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
pub(crate) fn build_fn_sig_ty<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> Ty<'tcx> {
let inputs = trait_ref.skip_binder().substs.type_at(1);
@@ -1650,9 +1742,68 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let signature_kind = format!("{argument_kind} signature");
err.note_expected_found(&signature_kind, expected_str, &signature_kind, found_str);
+ self.note_conflicting_closure_bounds(cause, &mut err);
+
err
}
+ // Add a note if there are two `Fn`-family bounds that have conflicting argument
+ // requirements, which will always cause a closure to have a type error.
+ fn note_conflicting_closure_bounds(
+ &self,
+ cause: &ObligationCauseCode<'tcx>,
+ err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
+ ) {
+ // First, look for an `ExprBindingObligation`, which means we can get
+ // the unsubstituted predicate list of the called function. And check
+ // that the predicate that we failed to satisfy is a `Fn`-like trait.
+ if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = cause
+ && let predicates = self.tcx.predicates_of(def_id).instantiate_identity(self.tcx)
+ && let Some(pred) = predicates.predicates.get(*idx)
+ && let ty::PredicateKind::Trait(trait_pred) = pred.kind().skip_binder()
+ && ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id()).is_some()
+ {
+ let expected_self =
+ self.tcx.anonymize_late_bound_regions(pred.kind().rebind(trait_pred.self_ty()));
+ let expected_substs = self
+ .tcx
+ .anonymize_late_bound_regions(pred.kind().rebind(trait_pred.trait_ref.substs));
+
+ // Find another predicate whose self-type is equal to the expected self type,
+ // but whose substs don't match.
+ let other_pred = std::iter::zip(&predicates.predicates, &predicates.spans)
+ .enumerate()
+ .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() {
+ ty::PredicateKind::Trait(trait_pred)
+ if ty::ClosureKind::from_def_id(self.tcx, trait_pred.def_id())
+ .is_some()
+ && other_idx != idx
+ // Make sure that the self type matches
+ // (i.e. constraining this closure)
+ && expected_self
+ == self.tcx.anonymize_late_bound_regions(
+ pred.kind().rebind(trait_pred.self_ty()),
+ )
+ // But the substs don't match (i.e. incompatible args)
+ && expected_substs
+ != self.tcx.anonymize_late_bound_regions(
+ pred.kind().rebind(trait_pred.trait_ref.substs),
+ ) =>
+ {
+ true
+ }
+ _ => false,
+ });
+ // If we found one, then it's very likely the cause of the error.
+ if let Some((_, (_, other_pred_span))) = other_pred {
+ err.span_note(
+ *other_pred_span,
+ "closure inferred to have a different signature due to this bound",
+ );
+ }
+ }
+ }
+
fn suggest_fully_qualified_path(
&self,
err: &mut Diagnostic,
@@ -1841,12 +1992,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
let span = self.tcx.def_span(generator_did);
- let in_progress_typeck_results = self.in_progress_typeck_results.map(|t| t.borrow());
let generator_did_root = self.tcx.typeck_root_def_id(generator_did);
debug!(
?generator_did,
?generator_did_root,
- in_progress_typeck_results.hir_owner = ?in_progress_typeck_results.as_ref().map(|t| t.hir_owner),
+ typeck_results.hir_owner = ?self.typeck_results.as_ref().map(|t| t.hir_owner),
?span,
);
@@ -1901,7 +2051,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// type-checking; otherwise, get them by performing a query. This is needed to avoid
// cycles. If we can't use resolved types because the generator comes from another crate,
// we still provide a targeted error but without all the relevant spans.
- let generator_data: Option<GeneratorData<'tcx, '_>> = match &in_progress_typeck_results {
+ let generator_data: Option<GeneratorData<'tcx, '_>> = match &self.typeck_results {
Some(t) if t.hir_owner.to_def_id() == generator_did_root => {
Some(GeneratorData::Local(&t))
}
@@ -2707,19 +2857,18 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
if let Some(Node::Expr(expr @ hir::Expr { kind: hir::ExprKind::Block(..), .. })) =
hir.find(arg_hir_id)
{
- let in_progress_typeck_results =
- self.in_progress_typeck_results.map(|t| t.borrow());
let parent_id = hir.get_parent_item(arg_hir_id);
- let typeck_results: &TypeckResults<'tcx> = match &in_progress_typeck_results {
+ let typeck_results: &TypeckResults<'tcx> = match &self.typeck_results {
Some(t) if t.hir_owner == parent_id => t,
- _ => self.tcx.typeck(parent_id),
+ _ => self.tcx.typeck(parent_id.def_id),
};
- let ty = typeck_results.expr_ty_adjusted(expr);
- let span = expr.peel_blocks().span;
+ let expr = expr.peel_blocks();
+ let ty = typeck_results.expr_ty_adjusted_opt(expr).unwrap_or(tcx.ty_error());
+ let span = expr.span;
if Some(span) != err.span.primary_span() {
err.span_label(
span,
- &if ty.references_error() {
+ if ty.references_error() {
String::new()
} else {
format!("this tail expression is of type `{:?}`", ty)
@@ -2796,19 +2945,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
}
- fn suggest_new_overflow_limit(&self, err: &mut Diagnostic) {
- let suggested_limit = match self.tcx.recursion_limit() {
- Limit(0) => Limit(2),
- limit => limit * 2,
- };
- err.help(&format!(
- "consider increasing the recursion limit by adding a \
- `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
- suggested_limit,
- self.tcx.crate_name(LOCAL_CRATE),
- ));
- }
-
#[instrument(
level = "debug", skip(self, err), fields(trait_pred.self_ty = ?trait_pred.self_ty())
)]
@@ -2890,19 +3026,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span,
_ => return,
};
- match (
- trait_ref.skip_binder().self_ty().kind(),
- trait_ref.skip_binder().substs.type_at(1).kind(),
- ) {
- (ty::Float(_), ty::Infer(InferTy::IntVar(_))) => {
- err.span_suggestion_verbose(
- rhs_span.shrink_to_hi(),
- "consider using a floating-point literal by writing it with `.0`",
- ".0",
- Applicability::MaybeIncorrect,
- );
- }
- _ => {}
+ if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind()
+ && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind()
+ {
+ err.span_suggestion_verbose(
+ rhs_span.shrink_to_hi(),
+ "consider using a floating-point literal by writing it with `.0`",
+ ".0",
+ Applicability::MaybeIncorrect,
+ );
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index a81fef60a..a417e1440 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -25,10 +25,9 @@ use super::Unimplemented;
use super::{FulfillmentError, FulfillmentErrorCode};
use super::{ObligationCause, PredicateObligation};
-use crate::traits::error_reporting::InferCtxtExt as _;
use crate::traits::project::PolyProjectionObligation;
use crate::traits::project::ProjectionCacheKeyExt as _;
-use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
/// Note that we include both the `ParamEnv` and the `Predicate`,
@@ -103,7 +102,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
}
/// Attempts to select obligations using `selcx`.
- fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+ fn select(&mut self, selcx: SelectionContext<'a, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
let _enter = span.enter();
@@ -138,7 +137,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
#[instrument(level = "debug", skip(self, infcx, param_env, cause))]
fn normalize_projection_type(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
projection_ty: ty::ProjectionTy<'tcx>,
cause: ObligationCause<'tcx>,
@@ -166,7 +165,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
fn register_predicate_obligation(
&mut self,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>,
) {
// this helps to reduce duplicate errors, as well as making
@@ -183,7 +182,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
}
- fn select_all_or_error(&mut self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
+ fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
{
let errors = self.select_where_possible(infcx);
if !errors.is_empty() {
@@ -194,12 +193,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
self.predicates.to_errors(CodeAmbiguity).into_iter().map(to_fulfillment_error).collect()
}
- fn select_where_possible(
- &mut self,
- infcx: &InferCtxt<'_, 'tcx>,
- ) -> Vec<FulfillmentError<'tcx>> {
- let mut selcx = SelectionContext::new(infcx);
- self.select(&mut selcx)
+ fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
+ let selcx = SelectionContext::new(infcx);
+ self.select(selcx)
}
fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
@@ -211,8 +207,8 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
}
}
-struct FulfillProcessor<'a, 'b, 'tcx> {
- selcx: &'a mut SelectionContext<'b, 'tcx>,
+struct FulfillProcessor<'a, 'tcx> {
+ selcx: SelectionContext<'a, 'tcx>,
}
fn mk_pending(os: Vec<PredicateObligation<'_>>) -> Vec<PendingPredicateObligation<'_>> {
@@ -221,9 +217,10 @@ fn mk_pending(os: Vec<PredicateObligation<'_>>) -> Vec<PendingPredicateObligatio
.collect()
}
-impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
+impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
type Obligation = PendingPredicateObligation<'tcx>;
type Error = FulfillmentErrorCode<'tcx>;
+ type OUT = Outcome<Self::Obligation, Self::Error>;
/// Identifies whether a predicate obligation needs processing.
///
@@ -279,7 +276,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
debug!(?obligation, "pre-resolve");
- if obligation.predicate.has_infer_types_or_consts() {
+ if obligation.predicate.has_non_region_infer() {
obligation.predicate =
self.selcx.infcx().resolve_vars_if_possible(obligation.predicate);
}
@@ -291,7 +288,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
if obligation.predicate.has_projections() {
let mut obligations = Vec::new();
let predicate = crate::traits::project::try_normalize_with_depth_to(
- self.selcx,
+ &mut self.selcx,
obligation.param_env,
obligation.cause.clone(),
obligation.recursion_depth + 1,
@@ -358,7 +355,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}
ty::PredicateKind::RegionOutlives(data) => {
- if infcx.considering_regions || data.has_placeholders() {
+ if infcx.considering_regions {
infcx.region_outlives_predicate(&obligation.cause, Binder::dummy(data));
}
@@ -479,9 +476,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
Err(NotConstEvaluatable::MentionsInfer) => {
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend(
- uv.substs
- .iter()
- .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
+ uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
ProcessResult::Unchanged
}
@@ -495,19 +490,20 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
}
ty::PredicateKind::ConstEquate(c1, c2) => {
+ assert!(
+ self.selcx.tcx().features().generic_const_exprs,
+ "`ConstEquate` without a feature gate: {c1:?} {c2:?}",
+ );
debug!(?c1, ?c2, "equating consts");
- let tcx = self.selcx.tcx();
- if tcx.features().generic_const_exprs {
- // FIXME: we probably should only try to unify abstract constants
- // if the constants depend on generic parameters.
- //
- // Let's just see where this breaks :shrug:
- if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
- (c1.kind(), c2.kind())
- {
- if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
- return ProcessResult::Changed(vec![]);
- }
+ // FIXME: we probably should only try to unify abstract constants
+ // if the constants depend on generic parameters.
+ //
+ // Let's just see where this breaks :shrug:
+ if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
+ (c1.kind(), c2.kind())
+ {
+ if infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
+ return ProcessResult::Changed(vec![]);
}
}
@@ -569,7 +565,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
- if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
+ if c1.has_non_region_infer() || c2.has_non_region_infer() {
ProcessResult::Unchanged
} else {
// Two different constants using generic parameters ~> error.
@@ -594,19 +590,21 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
&mut self,
cycle: I,
_marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
- ) where
+ ) -> Result<(), FulfillmentErrorCode<'tcx>>
+ where
I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
{
if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
debug!("process_child_obligations: coinductive match");
+ Ok(())
} else {
let cycle: Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
- self.selcx.infcx().report_overflow_error_cycle(&cycle);
+ Err(FulfillmentErrorCode::CodeCycle(cycle))
}
}
}
-impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
+impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
#[instrument(level = "debug", skip(self, obligation, stalled_on))]
fn process_trait_obligation(
&mut self,
@@ -641,7 +639,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
// information about the types in the trait.
stalled_on.clear();
stalled_on.extend(substs_infer_vars(
- self.selcx,
+ &self.selcx,
trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
));
@@ -693,12 +691,12 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
}
}
- match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
+ match project::poly_project_and_unify_type(&mut self.selcx, &project_obligation) {
ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(os)),
ProjectAndUnifyResult::FailedNormalization => {
stalled_on.clear();
stalled_on.extend(substs_infer_vars(
- self.selcx,
+ &self.selcx,
project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
));
ProcessResult::Unchanged
@@ -716,7 +714,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
/// Returns the set of inference variables contained in `substs`.
fn substs_infer_vars<'a, 'tcx>(
- selcx: &mut SelectionContext<'a, 'tcx>,
+ selcx: &SelectionContext<'a, 'tcx>,
substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
selcx
@@ -724,11 +722,11 @@ fn substs_infer_vars<'a, 'tcx>(
.resolve_vars_if_possible(substs)
.skip_binder() // ok because this check doesn't care about regions
.iter()
- .filter(|arg| arg.has_infer_types_or_consts())
+ .filter(|arg| arg.has_non_region_infer())
.flat_map(|arg| {
let mut walker = arg.walk();
while let Some(c) = walker.next() {
- if !c.has_infer_types_or_consts() {
+ if !c.has_non_region_infer() {
walker.visited.remove(&c);
walker.skip_current_subtree();
}
diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs
index e1bd48ba8..be603c609 100644
--- a/compiler/rustc_trait_selection/src/traits/misc.rs
+++ b/compiler/rustc_trait_selection/src/traits/misc.rs
@@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
-use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::error_reporting::TypeErrCtxtExt;
#[derive(Clone)]
pub enum CopyImplementationError<'tcx> {
@@ -23,65 +23,64 @@ pub fn can_type_implement_copy<'tcx>(
parent_cause: ObligationCause<'tcx>,
) -> Result<(), CopyImplementationError<'tcx>> {
// FIXME: (@jroesch) float this code up
- tcx.infer_ctxt().enter(|infcx| {
- let (adt, substs) = match self_type.kind() {
- // These types used to have a builtin impl.
- // Now libcore provides that impl.
- ty::Uint(_)
- | ty::Int(_)
- | ty::Bool
- | ty::Float(_)
- | ty::Char
- | ty::RawPtr(..)
- | ty::Never
- | ty::Ref(_, _, hir::Mutability::Not)
- | ty::Array(..) => return Ok(()),
+ let infcx = tcx.infer_ctxt().build();
+ let (adt, substs) = match self_type.kind() {
+ // These types used to have a builtin impl.
+ // Now libcore provides that impl.
+ ty::Uint(_)
+ | ty::Int(_)
+ | ty::Bool
+ | ty::Float(_)
+ | ty::Char
+ | ty::RawPtr(..)
+ | ty::Never
+ | ty::Ref(_, _, hir::Mutability::Not)
+ | ty::Array(..) => return Ok(()),
- ty::Adt(adt, substs) => (adt, substs),
+ ty::Adt(adt, substs) => (adt, substs),
- _ => return Err(CopyImplementationError::NotAnAdt),
- };
+ _ => return Err(CopyImplementationError::NotAnAdt),
+ };
- let mut infringing = Vec::new();
- for variant in adt.variants() {
- for field in &variant.fields {
- let ty = field.ty(tcx, substs);
- if ty.references_error() {
- continue;
- }
- let span = tcx.def_span(field.did);
- // FIXME(compiler-errors): This gives us better spans for bad
- // projection types like in issue-50480.
- // If the ADT has substs, point to the cause we are given.
- // If it does not, then this field probably doesn't normalize
- // to begin with, and point to the bad field's span instead.
- let cause = if field
- .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
- .has_param_types_or_consts()
- {
- parent_cause.clone()
- } else {
- ObligationCause::dummy_with_span(span)
- };
- match traits::fully_normalize(&infcx, cause, param_env, ty) {
- Ok(ty) => {
- if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
- infringing.push((field, ty));
- }
- }
- Err(errors) => {
- infcx.report_fulfillment_errors(&errors, None, false);
- }
- };
+ let mut infringing = Vec::new();
+ for variant in adt.variants() {
+ for field in &variant.fields {
+ let ty = field.ty(tcx, substs);
+ if ty.references_error() {
+ continue;
}
+ let span = tcx.def_span(field.did);
+ // FIXME(compiler-errors): This gives us better spans for bad
+ // projection types like in issue-50480.
+ // If the ADT has substs, point to the cause we are given.
+ // If it does not, then this field probably doesn't normalize
+ // to begin with, and point to the bad field's span instead.
+ let cause = if field
+ .ty(tcx, traits::InternalSubsts::identity_for_item(tcx, adt.did()))
+ .has_non_region_param()
+ {
+ parent_cause.clone()
+ } else {
+ ObligationCause::dummy_with_span(span)
+ };
+ match traits::fully_normalize(&infcx, cause, param_env, ty) {
+ Ok(ty) => {
+ if !infcx.type_is_copy_modulo_regions(param_env, ty, span) {
+ infringing.push((field, ty));
+ }
+ }
+ Err(errors) => {
+ infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ }
+ };
}
- if !infringing.is_empty() {
- return Err(CopyImplementationError::InfrigingFields(infringing));
- }
- if adt.has_dtor(tcx) {
- return Err(CopyImplementationError::HasDestructor);
- }
+ }
+ if !infringing.is_empty() {
+ return Err(CopyImplementationError::InfrigingFields(infringing));
+ }
+ if adt.has_dtor(tcx) {
+ return Err(CopyImplementationError::HasDestructor);
+ }
- Ok(())
- })
+ Ok(())
}
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 40596078f..0bf54c096 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -26,7 +26,7 @@ pub mod wf;
use crate::errors::DumpVTableEntries;
use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
@@ -34,12 +34,11 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
- self, DefIdTree, GenericParamDefKind, Subst, ToPredicate, Ty, TyCtxt, TypeSuperVisitable,
- VtblEntry,
+ self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, VtblEntry,
};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_span::{sym, Span};
use smallvec::SmallVec;
@@ -130,7 +129,7 @@ pub fn predicates_for_generics<'tcx>(
move |(idx, (predicate, span))| Obligation {
cause: cause(idx, span),
recursion_depth: 0,
- param_env: param_env,
+ param_env,
predicate,
},
)
@@ -141,8 +140,8 @@ pub fn predicates_for_generics<'tcx>(
/// `bound` or is not known to meet bound (note that this is
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
-pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn type_known_to_meet_bound_modulo_regions<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
@@ -171,7 +170,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>(
result
);
- if result && ty.has_infer_types_or_consts() {
+ if result && ty.has_non_region_infer() {
// 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
@@ -235,54 +234,51 @@ fn do_normalize_predicates<'tcx>(
// by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when
// we move over to lazy normalization *anyway*.
- tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
- let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
- Ok(predicates) => predicates,
- Err(errors) => {
- let reported = infcx.report_fulfillment_errors(&errors, None, false);
- return Err(reported);
- }
- };
+ let infcx = tcx.infer_ctxt().ignoring_regions().build();
+ let predicates = match fully_normalize(&infcx, cause, elaborated_env, predicates) {
+ Ok(predicates) => predicates,
+ Err(errors) => {
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
+ return Err(reported);
+ }
+ };
- debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
+ debug!("do_normalize_predictes: normalized predicates = {:?}", predicates);
- // We can use the `elaborated_env` here; the region code only
- // cares about declarations like `'a: 'b`.
- let outlives_env = OutlivesEnvironment::new(elaborated_env);
+ // We can use the `elaborated_env` here; the region code only
+ // cares about declarations like `'a: 'b`.
+ let outlives_env = OutlivesEnvironment::new(elaborated_env);
+
+ // FIXME: It's very weird that we ignore region obligations but apparently
+ // still need to use `resolve_regions` as we need the resolved regions in
+ // the normalized predicates.
+ let errors = infcx.resolve_regions(&outlives_env);
+ if !errors.is_empty() {
+ tcx.sess.delay_span_bug(
+ span,
+ format!("failed region resolution while normalizing {elaborated_env:?}: {errors:?}"),
+ );
+ }
- // FIXME: It's very weird that we ignore region obligations but apparently
- // still need to use `resolve_regions` as we need the resolved regions in
- // the normalized predicates.
- let errors = infcx.resolve_regions(&outlives_env);
- if !errors.is_empty() {
- tcx.sess.delay_span_bug(
+ match infcx.fully_resolve(predicates) {
+ Ok(predicates) => Ok(predicates),
+ Err(fixup_err) => {
+ // If we encounter a fixup error, it means that some type
+ // variable wound up unconstrained. I actually don't know
+ // if this can happen, and I certainly don't expect it to
+ // happen often, but if it did happen it probably
+ // represents a legitimate failure due to some kind of
+ // unconstrained variable.
+ //
+ // @lcnr: Let's still ICE here for now. I want a test case
+ // for that.
+ span_bug!(
span,
- format!(
- "failed region resolution while normalizing {elaborated_env:?}: {errors:?}"
- ),
+ "inference variables in normalized parameter environment: {}",
+ fixup_err
);
}
-
- match infcx.fully_resolve(predicates) {
- Ok(predicates) => Ok(predicates),
- Err(fixup_err) => {
- // If we encounter a fixup error, it means that some type
- // variable wound up unconstrained. I actually don't know
- // if this can happen, and I certainly don't expect it to
- // happen often, but if it did happen it probably
- // represents a legitimate failure due to some kind of
- // unconstrained variable.
- //
- // @lcnr: Let's still ICE here for now. I want a test case
- // for that.
- span_bug!(
- span,
- "inference variables in normalized parameter environment: {}",
- fixup_err
- );
- }
- }
- })
+ }
}
// FIXME: this is gonna need to be removed ...
@@ -394,8 +390,8 @@ pub fn normalize_param_env_or_error<'tcx>(
}
/// Normalize a type and process all resulting obligations, returning any errors
-pub fn fully_normalize<'a, 'tcx, T>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn fully_normalize<'tcx, T>(
+ infcx: &InferCtxt<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
value: T,
@@ -430,8 +426,8 @@ where
/// Process an obligation (and any nested obligations that come from it) to
/// completion, returning any errors
-pub fn fully_solve_obligation<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn fully_solve_obligation<'tcx>(
+ infcx: &InferCtxt<'tcx>,
obligation: PredicateObligation<'tcx>,
) -> Vec<FulfillmentError<'tcx>> {
let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
@@ -441,8 +437,8 @@ pub fn fully_solve_obligation<'a, 'tcx>(
/// Process a set of obligations (and any nested obligations that come from them)
/// to completion
-pub fn fully_solve_obligations<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn fully_solve_obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
) -> Vec<FulfillmentError<'tcx>> {
let mut engine = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
@@ -453,8 +449,8 @@ pub fn fully_solve_obligations<'a, 'tcx>(
/// Process a bound (and any nested obligations that come from it) to completion.
/// This is a convenience function for traits that have no generic arguments, such
/// as auto traits, and builtin traits like Copy or Sized.
-pub fn fully_solve_bound<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn fully_solve_bound<'tcx>(
+ infcx: &InferCtxt<'tcx>,
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
@@ -474,21 +470,20 @@ pub fn impossible_predicates<'tcx>(
) -> bool {
debug!("impossible_predicates(predicates={:?})", predicates);
- let result = tcx.infer_ctxt().enter(|infcx| {
- let param_env = ty::ParamEnv::reveal_all();
- let ocx = ObligationCtxt::new(&infcx);
- let predicates = ocx.normalize(ObligationCause::dummy(), param_env, predicates);
- for predicate in predicates {
- let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
- ocx.register_obligation(obligation);
- }
- let errors = ocx.select_all_or_error();
+ let infcx = tcx.infer_ctxt().build();
+ let param_env = ty::ParamEnv::reveal_all();
+ let ocx = ObligationCtxt::new(&infcx);
+ let predicates = ocx.normalize(ObligationCause::dummy(), param_env, predicates);
+ for predicate in predicates {
+ let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+ ocx.register_obligation(obligation);
+ }
+ let errors = ocx.select_all_or_error();
- // Clean up after ourselves
- let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+ // Clean up after ourselves
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
- !errors.is_empty()
- });
+ let result = !errors.is_empty();
debug!("impossible_predicates = {:?}", result);
result
}
@@ -579,18 +574,16 @@ fn is_impossible_method<'tcx>(
}
});
- tcx.infer_ctxt().ignoring_regions().enter(|ref infcx| {
- for obligation in predicates_for_trait {
- // Ignore overflow error, to be conservative.
- if let Ok(result) = infcx.evaluate_obligation(&obligation)
- && !result.may_apply()
- {
- return true;
- }
+ let infcx = tcx.infer_ctxt().ignoring_regions().build();
+ for obligation in predicates_for_trait {
+ // Ignore overflow error, to be conservative.
+ if let Ok(result) = infcx.evaluate_obligation(&obligation)
+ && !result.may_apply()
+ {
+ return true;
}
-
- false
- })
+ }
+ false
}
#[derive(Clone, Debug)]
@@ -771,12 +764,9 @@ fn dump_vtable_entries<'tcx>(
});
}
-fn own_existential_vtable_entries<'tcx>(
- tcx: TyCtxt<'tcx>,
- trait_ref: ty::PolyExistentialTraitRef<'tcx>,
-) -> &'tcx [DefId] {
+fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
let trait_methods = tcx
- .associated_items(trait_ref.def_id())
+ .associated_items(trait_def_id)
.in_definition_order()
.filter(|item| item.kind == ty::AssocKind::Fn);
// Now list each method's DefId (for within its trait).
@@ -785,7 +775,7 @@ fn own_existential_vtable_entries<'tcx>(
let def_id = trait_method.def_id;
// Some methods cannot be called on an object; skip those.
- if !is_vtable_safe_method(tcx, trait_ref.def_id(), &trait_method) {
+ if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
debug!("own_existential_vtable_entry: not vtable safe");
return None;
}
@@ -817,7 +807,7 @@ fn vtable_entries<'tcx>(
// Lookup the shape of vtable for the trait.
let own_existential_entries =
- tcx.own_existential_vtable_entries(existential_trait_ref);
+ tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
let own_entries = own_existential_entries.iter().copied().map(|def_id| {
debug!("vtable_entries: trait_method={:?}", def_id);
@@ -953,10 +943,9 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
}),
);
- let implsrc = tcx.infer_ctxt().enter(|infcx| {
- let mut selcx = SelectionContext::new(&infcx);
- selcx.select(&obligation).unwrap()
- });
+ let infcx = tcx.infer_ctxt().build();
+ let mut selcx = SelectionContext::new(&infcx);
+ let implsrc = selcx.select(&obligation).unwrap();
let Some(ImplSource::TraitUpcasting(implsrc_traitcasting)) = implsrc else {
bug!();
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index f2779ce2d..0bb25a74d 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -8,20 +8,20 @@
//! - not reference the erased type `Self` except for in this receiver;
//! - not have generic type parameters.
-use super::elaborate_predicates;
+use super::{elaborate_predicates, elaborate_trait_ref};
use crate::infer::TyCtxtInferExt;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::{self, Obligation, ObligationCause};
use hir::def::DefKind;
-use rustc_errors::{FatalError, MultiSpan};
+use rustc_errors::{DelayDm, FatalError, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst};
-use rustc_middle::ty::subst::{GenericArg, InternalSubsts, Subst};
use rustc_middle::ty::{
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
+use rustc_middle::ty::{GenericArg, InternalSubsts};
use rustc_middle::ty::{Predicate, ToPredicate};
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
use rustc_span::symbol::Symbol;
@@ -164,37 +164,42 @@ fn lint_object_unsafe_trait(
) {
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
// It's also hard to get a use site span, so we use the method definition span.
- tcx.struct_span_lint_hir(WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, span, |lint| {
- let mut err = lint.build(&format!(
- "the trait `{}` cannot be made into an object",
- tcx.def_path_str(trait_def_id)
- ));
- let node = tcx.hir().get_if_local(trait_def_id);
- let mut spans = MultiSpan::from_span(span);
- if let Some(hir::Node::Item(item)) = node {
- spans.push_span_label(item.ident.span, "this trait cannot be made into an object...");
- spans.push_span_label(span, format!("...because {}", violation.error_msg()));
- } else {
- spans.push_span_label(
- span,
- format!(
- "the trait cannot be made into an object because {}",
- violation.error_msg()
- ),
+ tcx.struct_span_lint_hir(
+ WHERE_CLAUSES_OBJECT_SAFETY,
+ hir::CRATE_HIR_ID,
+ span,
+ DelayDm(|| format!("the trait `{}` cannot be made into an object", tcx.def_path_str(trait_def_id))),
+ |err| {
+ let node = tcx.hir().get_if_local(trait_def_id);
+ let mut spans = MultiSpan::from_span(span);
+ if let Some(hir::Node::Item(item)) = node {
+ spans.push_span_label(
+ item.ident.span,
+ "this trait cannot be made into an object...",
+ );
+ spans.push_span_label(span, format!("...because {}", violation.error_msg()));
+ } else {
+ spans.push_span_label(
+ span,
+ format!(
+ "the trait cannot be made into an object because {}",
+ violation.error_msg()
+ ),
+ );
+ };
+ err.span_note(
+ spans,
+ "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>",
);
- };
- err.span_note(
- spans,
- "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>",
- );
- if node.is_some() {
- // Only provide the help if its a local trait, otherwise it's not
- violation.solution(&mut err);
- }
- err.emit();
- });
+ if node.is_some() {
+ // Only provide the help if its a local trait, otherwise it's not
+ violation.solution(err);
+ }
+ err
+ },
+ );
}
fn sized_trait_bound_spans<'tcx>(
@@ -442,19 +447,6 @@ fn virtual_call_violation_for_method<'tcx>(
return Some(MethodViolationCode::Generic);
}
- 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))
- {
- return Some(MethodViolationCode::WhereClauseReferencesSelf);
- }
-
let receiver_ty = tcx.liberate_late_bound_regions(method.def_id, sig.input(0));
// Until `unsized_locals` is fully implemented, `self: Self` can't be dispatched on.
@@ -533,6 +525,21 @@ 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))
+ {
+ return Some(MethodViolationCode::WhereClauseReferencesSelf);
+ }
+
None
}
@@ -560,51 +567,44 @@ fn receiver_for_self_ty<'tcx>(
/// Creates the object type for the current trait. For example,
/// if the current trait is `Deref`, then this will be
/// `dyn Deref<Target = Self::Target> + 'static`.
+#[instrument(level = "trace", skip(tcx), ret)]
fn object_ty_for_trait<'tcx>(
tcx: TyCtxt<'tcx>,
trait_def_id: DefId,
lifetime: ty::Region<'tcx>,
) -> Ty<'tcx> {
- debug!("object_ty_for_trait: trait_def_id={:?}", trait_def_id);
-
let trait_ref = ty::TraitRef::identity(tcx, trait_def_id);
+ debug!(?trait_ref);
let trait_predicate = trait_ref.map_bound(|trait_ref| {
ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref))
});
-
- let mut associated_types = traits::supertraits(tcx, trait_ref)
- .flat_map(|super_trait_ref| {
- tcx.associated_items(super_trait_ref.def_id())
- .in_definition_order()
- .map(move |item| (super_trait_ref, item))
- })
- .filter(|(_, item)| item.kind == ty::AssocKind::Type)
- .collect::<Vec<_>>();
-
- // existential predicates need to be in a specific order
- associated_types.sort_by_cached_key(|(_, item)| tcx.def_path_hash(item.def_id));
-
- let projection_predicates = associated_types.into_iter().map(|(super_trait_ref, item)| {
- // We *can* get bound lifetimes here in cases like
- // `trait MyTrait: for<'s> OtherTrait<&'s T, Output=bool>`.
- super_trait_ref.map_bound(|super_trait_ref| {
- ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
- term: tcx.mk_projection(item.def_id, super_trait_ref.substs).into(),
- item_def_id: item.def_id,
- substs: super_trait_ref.substs,
- })
+ debug!(?trait_predicate);
+
+ let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref)
+ .filter_map(|obligation| {
+ debug!(?obligation);
+ let pred = obligation.predicate.to_opt_poly_projection_pred()?;
+ Some(pred.map_bound(|p| {
+ ty::ExistentialPredicate::Projection(ty::ExistentialProjection {
+ item_def_id: p.projection_ty.item_def_id,
+ substs: p.projection_ty.substs,
+ term: p.term,
+ })
+ }))
})
- });
+ .collect();
+ // NOTE: Since #37965, the existential predicates list has depended on the
+ // list of predicates to be sorted. This is mostly to enforce that the primary
+ // predicate comes first.
+ 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(projection_predicates));
-
- let object_ty = tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn);
-
- debug!("object_ty_for_trait: object_ty=`{}`", object_ty);
+ .mk_poly_existential_predicates(iter::once(trait_predicate).chain(elaborated_predicates));
+ debug!(?existential_predicates);
- object_ty
+ tcx.mk_dynamic(existential_predicates, lifetime, ty::Dyn)
}
/// Checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
@@ -729,10 +729,9 @@ fn receiver_is_dispatchable<'tcx>(
Obligation::new(ObligationCause::dummy(), param_env, predicate)
};
- tcx.infer_ctxt().enter(|ref infcx| {
- // the receiver is dispatchable iff the obligation holds
- infcx.predicate_must_hold_modulo_regions(&obligation)
- })
+ let infcx = tcx.infer_ctxt().build();
+ // the receiver is dispatchable iff the obligation holds
+ infcx.predicate_must_hold_modulo_regions(&obligation)
}
fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
@@ -838,21 +837,14 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
}
}
- fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
+ fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// Constants can only influence object safety if they reference `Self`.
// This is only possible for unevaluated constants, so we walk these here.
//
- // If `AbstractConst::new` returned an error we already failed compilation
+ // If `AbstractConst::from_const` returned an error we already failed compilation
// so we don't have to emit an additional error here.
- //
- // We currently recurse into abstract consts here but do not recurse in
- // `is_const_evaluatable`. This means that the object safety check is more
- // liberal than the const eval check.
- //
- // This shouldn't really matter though as we can't really use any
- // constants which are not considered const evaluatable.
use rustc_middle::ty::abstract_const::Node;
- if let Ok(Some(ct)) = AbstractConst::new(self.tcx, uv.shrink()) {
+ if let Ok(Some(ct)) = AbstractConst::from_const(self.tcx, ct) {
walk_abstract_const(self.tcx, ct, |node| match node.root(self.tcx) {
Node::Leaf(leaf) => self.visit_const(leaf),
Node::Cast(_, _, ty) => self.visit_ty(ty),
@@ -861,7 +853,7 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>(
}
})
} else {
- ControlFlow::CONTINUE
+ ct.super_visit_with(self)
}
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 3008dfcad..108dae092 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -26,7 +26,7 @@ pub trait InferCtxtExt<'a, 'tcx> {
) -> Bounds<'a, 'tcx>;
}
-impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
/// Implied bounds are region relationships that we deduce
/// automatically. The idea is that (e.g.) a caller must check that a
/// function's argument types are well-formed immediately before
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a25fb8543..e4284b9d3 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -18,7 +18,7 @@ use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey};
use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
-use crate::traits::error_reporting::InferCtxtExt as _;
+use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use crate::traits::select::ProjectionMatchesProjection;
use rustc_data_structures::sso::SsoHashSet;
@@ -30,7 +30,6 @@ use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
use rustc_middle::ty::DefIdTree;
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
@@ -63,7 +62,8 @@ enum ProjectionCandidate<'tcx> {
/// From a where-clause in the env or object type
ParamEnv(ty::PolyProjectionPredicate<'tcx>),
- /// From the definition of `Trait` when you have something like <<A as Trait>::B as Trait2>::C
+ /// From the definition of `Trait` when you have something like
+ /// `<<A as Trait>::B as Trait2>::C`.
TraitDef(ty::PolyProjectionPredicate<'tcx>),
/// Bounds specified on an object type
@@ -72,7 +72,15 @@ enum ProjectionCandidate<'tcx> {
/// From an "impl" (or a "pseudo-impl" returned by select)
Select(Selection<'tcx>),
- ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'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>>),
}
enum ProjectionCandidateSet<'tcx> {
@@ -256,7 +264,7 @@ fn project_and_unify_type<'cx, 'tcx>(
};
debug!(?normalized, ?obligations, "project_and_unify_type result");
let actual = obligation.predicate.term;
- // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
+ // For an example where this is necessary see src/test/ui/impl-trait/nested-return-type2.rs
// This allows users to omit re-mentioning all bounds on an associated type and just use an
// `impl Trait` for the assoc type to add more bounds.
let InferOk { value: actual, obligations: new } =
@@ -514,7 +522,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
self.param_env,
ty,
);
- self.selcx.infcx().report_overflow_error(&obligation, true);
+ self.selcx.infcx().err_ctxt().report_overflow_error(&obligation, true);
}
let substs = substs.fold_with(self);
@@ -557,21 +565,6 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
.flatten()
.unwrap_or_else(|| ty.super_fold_with(self).into())
};
- // For cases like #95134 we would like to catch overflows early
- // otherwise they slip away away and cause ICE.
- let recursion_limit = self.tcx().recursion_limit();
- if !recursion_limit.value_within_limit(self.depth)
- // HACK: Don't overflow when running cargo doc see #100991
- && !self.tcx().sess.opts.actually_rustdoc
- {
- let obligation = Obligation::with_depth(
- self.cause.clone(),
- recursion_limit.0,
- self.param_env,
- ty,
- );
- self.selcx.infcx().report_overflow_error(&obligation, true);
- }
debug!(
?self.depth,
?ty,
@@ -664,7 +657,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
}
pub struct BoundVarReplacer<'me, 'tcx> {
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
// These three maps track the bound variable that were replaced by placeholders. It might be
// nice to remove these since we already have the `kind` in the placeholder; we really just need
// the `var` (but we *could* bring that into scope if we were to track them as we pass them).
@@ -692,7 +685,7 @@ 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>>(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
value: T,
f: impl FnOnce(T) -> R,
@@ -718,7 +711,7 @@ impl<'me, 'tcx> BoundVarReplacer<'me, 'tcx> {
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
/// use a binding level above `universe_indices.len()`, we fail.
pub fn replace_bound_vars<T: TypeFoldable<'tcx>>(
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
universe_indices: &'me mut Vec<Option<ty::UniverseIndex>>,
value: T,
) -> (
@@ -838,7 +831,7 @@ impl<'tcx> TypeFolder<'tcx> for BoundVarReplacer<'_, 'tcx> {
// The inverse of `BoundVarReplacer`: replaces placeholders with the bound vars from which they came.
pub struct PlaceholderReplacer<'me, 'tcx> {
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
@@ -848,7 +841,7 @@ pub struct PlaceholderReplacer<'me, 'tcx> {
impl<'me, 'tcx> PlaceholderReplacer<'me, 'tcx> {
pub fn replace_placeholders<T: TypeFoldable<'tcx>>(
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
mapped_regions: BTreeMap<ty::PlaceholderRegion, ty::BoundRegion>,
mapped_types: BTreeMap<ty::PlaceholderType, ty::BoundTy>,
mapped_consts: BTreeMap<ty::PlaceholderConst<'tcx>, ty::BoundVar>,
@@ -1319,6 +1312,19 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let tcx = selcx.tcx();
if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_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.item_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 =
obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
@@ -1330,7 +1336,9 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
let _ =
selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
Ok(Some(super::ImplSource::UserDefined(data))) => {
- candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
+ candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
+ ImplTraitInTraitCandidate::Impl(data),
+ ));
Ok(())
}
Ok(None) => {
@@ -1368,7 +1376,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>(
);
}
-/// In the case of a nested projection like <<A as Foo>::FooT as Bar>::BarT, we may find
+/// In the case of a nested projection like `<<A as Foo>::FooT as Bar>::BarT`, we may find
/// that the definition of `Foo` has some clues:
///
/// ```ignore (illustrative)
@@ -1489,7 +1497,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
candidate_set.push_candidate(ctor(data));
if potentially_unnormalized_candidates
- && !obligation.predicate.has_infer_types_or_consts()
+ && !obligation.predicate.has_non_region_infer()
{
// HACK: Pick the first trait def candidate for a fully
// inferred predicate. This is to allow duplicates that
@@ -1751,8 +1759,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
super::ImplSource::AutoImpl(..)
| super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_)
- | super::ImplSource::ConstDestruct(_)
- | super::ImplSource::Tuple => {
+ | super::ImplSource::ConstDestruct(_) => {
// These traits have no associated types.
selcx.tcx().sess.delay_span_bug(
obligation.cause.span,
@@ -1793,9 +1800,18 @@ fn confirm_candidate<'cx, 'tcx>(
ProjectionCandidate::Select(impl_source) => {
confirm_select_candidate(selcx, obligation, impl_source)
}
- ProjectionCandidate::ImplTraitInTrait(data) => {
+ ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(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.item_def_id, obligation.predicate.substs)
+ .into(),
+ obligations: vec![],
+ },
};
// When checking for cycle during evaluation, we compare predicates with
@@ -1830,8 +1846,7 @@ fn confirm_select_candidate<'cx, 'tcx>(
| super::ImplSource::Builtin(..)
| super::ImplSource::TraitUpcasting(_)
| super::ImplSource::TraitAlias(..)
- | super::ImplSource::ConstDestruct(_)
- | super::ImplSource::Tuple => {
+ | super::ImplSource::ConstDestruct(_) => {
// we don't create Select candidates with this kind of resolution
span_bug!(
obligation.cause.span,
@@ -2142,15 +2157,15 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let identity_substs =
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
- let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
+ let kind = ty::ConstKind::Unevaluated(ty::UnevaluatedConst::new(did, identity_substs));
ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into())
} else {
ty.map_bound(|ty| ty.into())
};
- if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
+ 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 parameter counts",
+ "impl item and trait item have different parameters",
);
Progress { term: err.into(), obligations: nested }
} else {
@@ -2159,6 +2174,44 @@ 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_ty: &ty::AssocItem,
+ substs: ty::SubstsRef<'tcx>,
+) -> bool {
+ fn check_substs_compatible_inner<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ generics: &'tcx ty::Generics,
+ args: &'tcx [ty::GenericArg<'tcx>],
+ ) -> bool {
+ if generics.count() != args.len() {
+ return false;
+ }
+
+ let (parent_args, own_args) = args.split_at(generics.parent_count);
+
+ if let Some(parent) = generics.parent
+ && let parent_generics = tcx.generics_of(parent)
+ && !check_substs_compatible_inner(tcx, parent_generics, parent_args) {
+ return false;
+ }
+
+ for (param, arg) in std::iter::zip(&generics.params, own_args) {
+ match (&param.kind, arg.unpack()) {
+ (ty::GenericParamDefKind::Type { .. }, ty::GenericArgKind::Type(_))
+ | (ty::GenericParamDefKind::Lifetime, ty::GenericArgKind::Lifetime(_))
+ | (ty::GenericParamDefKind::Const { .. }, ty::GenericArgKind::Const(_)) => {}
+ _ => return false,
+ }
+ }
+
+ true
+ }
+
+ check_substs_compatible_inner(tcx, tcx.generics_of(assoc_ty.def_id), substs.as_slice())
+}
+
fn confirm_impl_trait_in_trait_candidate<'tcx>(
selcx: &mut SelectionContext<'_, 'tcx>,
obligation: &ProjectionTyObligation<'tcx>,
@@ -2175,8 +2228,21 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
return Progress { term: tcx.ty_error().into(), obligations };
}
+ // Use the default `impl Trait` for the trait, e.g., for a default trait body
+ if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
+ return Progress {
+ term: tcx
+ .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+ .into(),
+ obligations,
+ };
+ }
+
let impl_fn_def_id = leaf_def.item.def_id;
- let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs);
+ // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
+ // since `data.substs` are the impl substs.
+ let impl_fn_substs =
+ obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
let cause = ObligationCause::new(
obligation.cause.span,
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index 32669e23d..c84f128dd 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -31,7 +31,7 @@ pub trait InferCtxtExt<'tcx> {
) -> EvaluationResult;
}
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// Evaluates whether the predicate can be satisfied (by any means)
/// in the given `ParamEnv`.
fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 40acabf62..58e4597b7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -5,17 +5,16 @@
use crate::infer::at::At;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::{InferCtxt, InferOk};
-use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
-use rustc_middle::mir;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
+use rustc_span::DUMMY_SP;
use std::ops::ControlFlow;
@@ -155,7 +154,7 @@ impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
}
struct QueryNormalizer<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
cause: &'cx ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
obligations: Vec<PredicateObligation<'tcx>>,
@@ -214,7 +213,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
self.param_env,
ty,
);
- self.infcx.report_overflow_error(&obligation, true);
+ self.infcx.err_ctxt().report_overflow_error(&obligation, true);
}
let generic_ty = self.tcx().bound_type_of(def_id);
@@ -255,7 +254,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
- bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
+ // Rustdoc normalizes possibly not well-formed types, so only
+ // treat this as a bug if we're not in rustdoc.
+ if !tcx.sess.opts.actually_rustdoc {
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("unexpected ambiguity: {:?} {:?}", c_data, result),
+ );
+ }
+ return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
@@ -298,7 +305,15 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
let result = tcx.normalize_projection_ty(c_data)?;
// We don't expect ambiguity.
if result.is_ambiguous() {
- bug!("unexpected ambiguity: {:?} {:?}", c_data, result);
+ // Rustdoc normalizes possibly not well-formed types, so only
+ // treat this as a bug if we're not in rustdoc.
+ if !tcx.sess.opts.actually_rustdoc {
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("unexpected ambiguity: {:?} {:?}", c_data, result),
+ );
+ }
+ return Err(NoSolution);
}
let InferOk { value: result, obligations } =
self.infcx.instantiate_query_response_and_region_obligations(
@@ -348,31 +363,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
))
}
- fn try_fold_mir_const(
- &mut self,
- constant: mir::ConstantKind<'tcx>,
- ) -> Result<mir::ConstantKind<'tcx>, Self::Error> {
- Ok(match constant {
- mir::ConstantKind::Ty(c) => {
- let const_folded = c.try_super_fold_with(self)?;
- match const_folded.kind() {
- ty::ConstKind::Value(valtree) => {
- let tcx = self.infcx.tcx;
- let ty = const_folded.ty();
- let const_val = tcx.valtree_to_const_val((ty, valtree));
- debug!(?ty, ?valtree, ?const_val);
-
- mir::ConstantKind::Val(const_val, ty)
- }
- _ => mir::ConstantKind::Ty(const_folded),
- }
- }
- mir::ConstantKind::Val(_, _) | mir::ConstantKind::Unevaluated(..) => {
- constant.try_super_fold_with(self)?
- }
- })
- }
-
#[inline]
fn try_fold_predicate(
&mut self,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 18988861a..6bf3ed0d0 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -16,7 +16,7 @@ pub struct CustomTypeOp<F, G> {
impl<F, G> CustomTypeOp<F, G> {
pub fn new<'tcx, R>(closure: F, description: G) -> Self
where
- F: FnOnce(&InferCtxt<'_, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
+ F: FnOnce(&InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
G: Fn() -> String,
{
CustomTypeOp { closure, description }
@@ -25,7 +25,7 @@ impl<F, G> CustomTypeOp<F, G> {
impl<'tcx, F, R: fmt::Debug, G> super::TypeOp<'tcx> for CustomTypeOp<F, G>
where
- F: for<'a, 'cx> FnOnce(&'a InferCtxt<'cx, 'tcx>) -> Fallible<InferOk<'tcx, R>>,
+ F: for<'a, 'cx> FnOnce(&'a InferCtxt<'tcx>) -> Fallible<InferOk<'tcx, R>>,
G: Fn() -> String,
{
type Output = R;
@@ -36,7 +36,7 @@ where
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
- fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
if cfg!(debug_assertions) {
info!("fully_perform({:?})", self);
}
@@ -57,7 +57,7 @@ where
/// Executes `op` and then scrapes out all the "old style" region
/// constraints that result, creating query-region-constraints.
pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
op: impl FnOnce() -> Fallible<InferOk<'tcx, R>>,
) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> {
// During NLL, we expect that nobody will register region
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 8a7916570..29ae8ae6b 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
@@ -32,7 +32,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
- fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+ fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
}
/// The output from performing a type op
@@ -78,7 +78,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> Fallible<(
Self::QueryResponse,
@@ -120,7 +120,7 @@ where
type Output = Q::QueryResponse;
type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
- fn fully_perform(self, infcx: &InferCtxt<'_, 'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let mut region_constraints = QueryRegionConstraints::default();
let (output, error_info, mut obligations, _) =
Q::fully_perform_into(self, infcx, &mut region_constraints)?;
diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs
index 8148e2b78..8cf500a46 100644
--- a/compiler/rustc_trait_selection/src/traits/relationships.rs
+++ b/compiler/rustc_trait_selection/src/traits/relationships.rs
@@ -6,7 +6,7 @@ use rustc_middle::ty::{self, ToPredicate};
pub(crate) fn update<'tcx, T>(
engine: &mut T,
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
obligation: &PredicateObligation<'tcx>,
) where
T: TraitEngine<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index a80527f63..4c5bc3339 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -6,6 +6,7 @@
//!
//! [rustc dev guide]:https://rustc-dev-guide.rust-lang.org/traits/resolution.html#candidate-assembly
use hir::LangItem;
+use rustc_errors::DelayDm;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::traits::ObligationCause;
@@ -173,7 +174,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?stack, ?candidates, "winnowed to {} candidates", candidates.len());
- let needs_infer = stack.obligation.predicate.has_infer_types_or_consts();
+ let needs_infer = stack.obligation.predicate.has_non_region_infer();
// If there are STILL multiple candidates, we can further
// reduce the list by dropping duplicates -- including
@@ -362,7 +363,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.infcx
.probe(|_| self.match_projection_obligation_against_definition_bounds(obligation));
- candidates.vec.extend(result.into_iter().map(ProjectionCandidate));
+ candidates
+ .vec
+ .extend(result.into_iter().map(|(idx, constness)| ProjectionCandidate(idx, constness)));
}
/// Given an obligation like `<SomeTrait for T>`, searches the obligations that the caller
@@ -622,7 +625,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- _ => candidates.vec.push(AutoImplCandidate(def_id)),
+ _ => candidates.vec.push(AutoImplCandidate),
}
}
}
@@ -823,13 +826,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
DEREF_INTO_DYN_SUPERTRAIT,
obligation.cause.body_id,
obligation.cause.span,
- |lint| {
- lint.build(&format!(
- "`{}` implements `Deref` with supertrait `{}` as output",
- source,
- deref_output_ty
- )).emit();
- },
+ DelayDm(|| format!(
+ "`{}` implements `Deref` with supertrait `{}` as output",
+ source, deref_output_ty
+ )),
+ |lint| lint,
);
return;
}
@@ -888,11 +889,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
- if obligation.has_param_types_or_consts() {
+ if obligation.has_non_region_param() {
return;
}
- if obligation.has_infer_types_or_consts() {
+ if obligation.has_non_region_infer() {
candidates.ambiguous = true;
return;
}
@@ -913,7 +914,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let def_id = obligation.predicate.def_id();
if self.tcx().is_trait_alias(def_id) {
- candidates.vec.push(TraitAliasCandidate(def_id));
+ candidates.vec.push(TraitAliasCandidate);
}
}
@@ -1020,7 +1021,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx().shallow_resolve(obligation.self_ty().skip_binder());
match self_ty.kind() {
ty::Tuple(_) => {
- candidates.vec.push(TupleCandidate);
+ candidates.vec.push(BuiltinCandidate { has_nested: false });
}
ty::Infer(ty::TyVar(_)) => {
candidates.ambiguous = true;
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index d1deef784..ed22058c6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -11,9 +11,10 @@ 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::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef};
-use rustc_middle::ty::{self, GenericParamDefKind, Ty, TyCtxt};
-use rustc_middle::ty::{ToPolyTraitRef, ToPredicate};
+use rustc_middle::ty::{
+ self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
+ ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
+};
use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
@@ -63,15 +64,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::UserDefined(self.confirm_impl_candidate(obligation, impl_def_id))
}
- AutoImplCandidate(trait_def_id) => {
- let data = self.confirm_auto_impl_candidate(obligation, trait_def_id);
+ AutoImplCandidate => {
+ let data = self.confirm_auto_impl_candidate(obligation);
ImplSource::AutoImpl(data)
}
- ProjectionCandidate(idx) => {
+ ProjectionCandidate(idx, constness) => {
let obligations = self.confirm_projection_candidate(obligation, idx)?;
- // FIXME(jschievink): constness
- ImplSource::Param(obligations, ty::BoundConstness::NotConst)
+ ImplSource::Param(obligations, constness)
}
ObjectCandidate(idx) => {
@@ -100,8 +100,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
PointeeCandidate => ImplSource::Pointee(ImplSourcePointeeData),
- TraitAliasCandidate(alias_def_id) => {
- let data = self.confirm_trait_alias_candidate(obligation, alias_def_id);
+ TraitAliasCandidate => {
+ let data = self.confirm_trait_alias_candidate(obligation);
ImplSource::TraitAlias(data)
}
@@ -126,8 +126,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
ImplSource::ConstDestruct(data)
}
-
- TupleCandidate => ImplSource::Tuple,
};
if !obligation.predicate.is_const_if_const() {
@@ -290,8 +288,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let scope = type_at(2).skip_binder();
- let assume =
- rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3));
+ let Some(assume) =
+ rustc_transmute::Assume::from_const(self.infcx.tcx, obligation.param_env, const_at(3)) else {
+ return Err(Unimplemented);
+ };
let cause = obligation.cause.clone();
@@ -315,13 +315,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_auto_impl_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
- trait_def_id: DefId,
) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
- debug!(?obligation, ?trait_def_id, "confirm_auto_impl_candidate");
+ debug!(?obligation, "confirm_auto_impl_candidate");
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
let types = self.constituent_types_for_ty(self_ty);
- self.vtable_auto_impl(obligation, trait_def_id, types)
+ self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
}
/// See `confirm_auto_impl_candidate`.
@@ -619,17 +618,47 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
.map_bound(|(trait_ref, _)| trait_ref);
- let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+
+ // Confirm the `type Output: Sized;` bound that is present on `FnOnce`
+ let cause = obligation.derived_cause(BuiltinDerivedObligation);
+ // The binder on the Fn obligation is "less" important than the one on
+ // the signature, as evidenced by how we treat it during projection.
+ // The safe thing to do here is to liberate it, though, which should
+ // have no worse effect than skipping the binder here.
+ let liberated_fn_ty =
+ self.infcx.replace_bound_vars_with_placeholders(obligation.predicate.rebind(self_ty));
+ let output_ty = self
+ .infcx
+ .replace_bound_vars_with_placeholders(liberated_fn_ty.fn_sig(self.tcx()).output());
+ let output_ty = normalize_with_depth_to(
+ self,
+ obligation.param_env,
+ cause.clone(),
+ obligation.recursion_depth,
+ output_ty,
+ &mut nested,
+ );
+ let tr = ty::Binder::dummy(ty::TraitRef::new(
+ self.tcx().require_lang_item(LangItem::Sized, None),
+ self.tcx().mk_substs_trait(output_ty, &[]),
+ ));
+ nested.push(Obligation::new(
+ cause,
+ obligation.param_env,
+ tr.to_poly_trait_predicate().to_predicate(self.tcx()),
+ ));
+
Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
}
fn confirm_trait_alias_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
- alias_def_id: DefId,
) -> ImplSourceTraitAliasData<'tcx, PredicateObligation<'tcx>> {
- debug!(?obligation, ?alias_def_id, "confirm_trait_alias_candidate");
+ 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 trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
@@ -1196,6 +1225,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Never
| ty::Foreign(_) => {}
+ // `ManuallyDrop` is trivially drop
+ ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().manually_drop() => {}
+
// These types are built-in, so we can fast-track by registering
// nested predicates for their constituent type(s)
ty::Array(ty, _) | ty::Slice(ty) => {
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 75bd2c89f..9ebff4892 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -20,7 +20,7 @@ use super::{
};
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
-use crate::traits::error_reporting::InferCtxtExt;
+use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::ProjectAndUnifyResult;
use crate::traits::project::ProjectionCacheKeyExt;
use crate::traits::ProjectionCacheKey;
@@ -35,9 +35,8 @@ use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::fold::BottomUpFolder;
-use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate};
use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_span::symbol::sym;
@@ -94,7 +93,7 @@ impl IntercrateAmbiguityCause {
}
pub struct SelectionContext<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
/// Freshener used specifically for entries on the obligation
/// stack. This ensures that all entries on the stack at one time
@@ -215,7 +214,7 @@ enum BuiltinImplConditions<'tcx> {
}
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+ pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
SelectionContext {
infcx,
freshener: infcx.freshener_keep_static(),
@@ -225,28 +224,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
- SelectionContext {
- infcx,
- freshener: infcx.freshener_keep_static(),
- intercrate: true,
- intercrate_ambiguity_causes: None,
- query_mode: TraitQueryMode::Standard,
- }
+ pub fn intercrate(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
+ SelectionContext { intercrate: true, ..SelectionContext::new(infcx) }
}
pub fn with_query_mode(
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
query_mode: TraitQueryMode,
) -> SelectionContext<'cx, 'tcx> {
debug!(?query_mode, "with_query_mode");
- SelectionContext {
- infcx,
- freshener: infcx.freshener_keep_static(),
- intercrate: false,
- intercrate_ambiguity_causes: None,
- query_mode,
- }
+ SelectionContext { query_mode, ..SelectionContext::new(infcx) }
}
/// Enables tracking of intercrate ambiguity causes. See
@@ -266,7 +253,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.intercrate_ambiguity_causes.take().unwrap_or_default()
}
- pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+ pub fn infcx(&self) -> &'cx InferCtxt<'tcx> {
self.infcx
}
@@ -689,19 +676,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
ty::PredicateKind::ConstEquate(c1, c2) => {
+ assert!(
+ self.tcx().features().generic_const_exprs,
+ "`ConstEquate` without a feature gate: {c1:?} {c2:?}",
+ );
debug!(?c1, ?c2, "evaluate_predicate_recursively: equating consts");
- if self.tcx().features().generic_const_exprs {
- // FIXME: we probably should only try to unify abstract constants
- // if the constants depend on generic parameters.
- //
- // Let's just see where this breaks :shrug:
- if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
- (c1.kind(), c2.kind())
- {
- if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
- return Ok(EvaluatedToOk);
- }
+ // FIXME: we probably should only try to unify abstract constants
+ // if the constants depend on generic parameters.
+ //
+ // Let's just see where this breaks :shrug:
+ if let (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) =
+ (c1.kind(), c2.kind())
+ {
+ if self.infcx.try_unify_abstract_consts(a, b, obligation.param_env) {
+ return Ok(EvaluatedToOk);
}
}
@@ -741,7 +730,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
)
}
(Err(ErrorHandled::TooGeneric), _) | (_, Err(ErrorHandled::TooGeneric)) => {
- if c1.has_infer_types_or_consts() || c2.has_infer_types_or_consts() {
+ if c1.has_non_region_infer() || c2.has_non_region_infer() {
Ok(EvaluatedToAmbig)
} else {
// Two different constants using generic parameters ~> error.
@@ -839,7 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// must be met of course). One obvious case this comes up is
/// marker traits like `Send`. Think of a linked list:
///
- /// struct List<T> { data: T, next: Option<Box<List<T>>> }
+ /// struct List<T> { data: T, next: Option<Box<List<T>>> }
///
/// `Box<List<T>>` will be `Send` if `T` is `Send` and
/// `Option<Box<List<T>>>` is `Send`, and in turn
@@ -926,38 +915,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let unbound_input_types =
stack.fresh_trait_pred.skip_binder().trait_ref.substs.types().any(|ty| ty.is_fresh());
- if stack.obligation.polarity() != ty::ImplPolarity::Negative {
- // This check was an imperfect workaround for a bug in the old
- // intercrate mode; it should be removed when that goes away.
- if unbound_input_types && self.intercrate {
- debug!("evaluate_stack --> unbound argument, intercrate --> ambiguous",);
- // Heuristics: show the diagnostics when there are no candidates in crate.
- if self.intercrate_ambiguity_causes.is_some() {
- debug!("evaluate_stack: intercrate_ambiguity_causes is some");
- if let Ok(candidate_set) = self.assemble_candidates(stack) {
- if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
- let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
- let self_ty = trait_ref.self_ty();
- let cause = with_no_trimmed_paths!({
- IntercrateAmbiguityCause::DownstreamCrate {
- trait_desc: trait_ref.print_only_trait_path().to_string(),
- self_desc: if self_ty.has_concrete_skeleton() {
- Some(self_ty.to_string())
- } else {
- None
- },
- }
- });
-
- debug!(?cause, "evaluate_stack: pushing cause");
- self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause);
- }
- }
- }
- return Ok(EvaluatedToAmbig);
- }
- }
-
if unbound_input_types
&& stack.iter().skip(1).any(|prev| {
stack.obligation.param_env == prev.obligation.param_env
@@ -1140,7 +1097,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ErrorGuaranteed::unchecked_claim_error_was_emitted(),
));
}
- self.infcx.report_overflow_error(error_obligation, true);
+ self.infcx.err_ctxt().report_overflow_error(error_obligation, true);
}
TraitQueryMode::Canonical => {
return Err(OverflowError::Canonical);
@@ -1192,8 +1149,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplCandidate(def_id) if tcx.constness(def_id) == hir::Constness::Const => {}
// const param
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
+ // const projection
+ ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
// auto trait impl
- AutoImplCandidate(..) => {}
+ AutoImplCandidate => {}
// generator, this will raise error in other places
// or ignore error with const_async_blocks feature
GeneratorCandidate => {}
@@ -1399,7 +1358,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
- ) -> smallvec::SmallVec<[usize; 2]> {
+ ) -> 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);
@@ -1447,7 +1406,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => false,
}
}) {
- return Some(idx);
+ return Some((idx, pred.constness));
}
}
None
@@ -1563,7 +1522,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if !generics.params.is_empty()
&& obligation.predicate.substs[generics.parent_count..]
.iter()
- .any(|&p| p.has_infer_types_or_consts() && self.infcx.shallow_resolve(p) != p)
+ .any(|&p| p.has_non_region_infer() && self.infcx.shallow_resolve(p) != p)
{
ProjectionMatchesProjection::Ambiguous
} else {
@@ -1605,13 +1564,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
- // `DiscriminantKindCandidate`, `ConstDestructCandidate`, and `TupleCandidate`
+ // `DiscriminantKindCandidate`, `ConstDestructCandidate`
// to anything else.
//
// This is a fix for #53123 and prevents winnowing from accidentally extending the
// lifetime of a variable.
match (&other.candidate, &victim.candidate) {
- (_, AutoImplCandidate(..)) | (AutoImplCandidate(..), _) => {
+ (_, AutoImplCandidate) | (AutoImplCandidate, _) => {
bug!(
"default implementations shouldn't be recorded \
when there are other valid candidates"
@@ -1626,8 +1585,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
| PointeeCandidate
- | ConstDestructCandidate(_)
- | TupleCandidate,
+ | ConstDestructCandidate(_),
_,
) => true,
(
@@ -1635,8 +1593,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
BuiltinCandidate { has_nested: false }
| DiscriminantKindCandidate
| PointeeCandidate
- | ConstDestructCandidate(_)
- | TupleCandidate,
+ | ConstDestructCandidate(_),
) => false,
(ParamCandidate(other), ParamCandidate(victim)) => {
@@ -1681,11 +1638,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..)
+ | TraitAliasCandidate
| ObjectCandidate(_)
- | ProjectionCandidate(_),
+ | ProjectionCandidate(..),
) => !is_global(cand),
- (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
+ (ObjectCandidate(_) | ProjectionCandidate(..), ParamCandidate(ref cand)) => {
// Prefer these to a global where-clause bound
// (see issue #50825).
is_global(cand)
@@ -1699,7 +1656,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
ParamCandidate(ref cand),
) => {
// Prefer these to a global where-clause bound
@@ -1707,20 +1664,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
is_global(cand) && other.evaluation.must_apply_modulo_regions()
}
- (ProjectionCandidate(i), ProjectionCandidate(j))
+ (ProjectionCandidate(i, _), ProjectionCandidate(j, _))
| (ObjectCandidate(i), ObjectCandidate(j)) => {
// Arbitrarily pick the lower numbered candidate for backwards
// compatibility reasons. Don't let this affect inference.
i < j && !needs_infer
}
- (ObjectCandidate(_), ProjectionCandidate(_))
- | (ProjectionCandidate(_), ObjectCandidate(_)) => {
+ (ObjectCandidate(_), ProjectionCandidate(..))
+ | (ProjectionCandidate(..), ObjectCandidate(_)) => {
bug!("Have both object and projection candidate")
}
// Arbitrarily give projection and object candidates priority.
(
- ObjectCandidate(_) | ProjectionCandidate(_),
+ ObjectCandidate(_) | ProjectionCandidate(..),
ImplCandidate(..)
| ClosureCandidate
| GeneratorCandidate
@@ -1729,7 +1686,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
) => true,
(
@@ -1741,18 +1698,18 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { .. }
- | TraitAliasCandidate(..),
- ObjectCandidate(_) | ProjectionCandidate(_),
+ | TraitAliasCandidate,
+ ObjectCandidate(_) | ProjectionCandidate(..),
) => false,
(&ImplCandidate(other_def), &ImplCandidate(victim_def)) => {
// See if we can toss out `victim` based on specialization.
- // This requires us to know *for sure* that the `other` impl applies
- // i.e., `EvaluatedToOk`.
+ // While this requires us to know *for sure* that the `other` impl applies
+ // we still use modulo regions here.
//
- // FIXME(@lcnr): Using `modulo_regions` here seems kind of scary
- // to me but is required for `std` to compile, so I didn't change it
- // for now.
+ // This is fine as specialization currently assumes that specializing
+ // impls have to be always applicable, meaning that the only allowed
+ // region constraints may be constraints also present on the default impl.
let tcx = self.tcx();
if other.evaluation.must_apply_modulo_regions() {
if tcx.specializes((other_def, victim_def)) {
@@ -1822,7 +1779,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
ImplCandidate(_)
| ClosureCandidate
| GeneratorCandidate
@@ -1831,7 +1788,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinUnsizeCandidate
| TraitUpcastingUnsizeCandidate(_)
| BuiltinCandidate { has_nested: true }
- | TraitAliasCandidate(..),
+ | TraitAliasCandidate,
) => false,
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index 7d299e30a..c89165858 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -17,10 +17,10 @@ use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt};
use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause};
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder};
+use rustc_errors::{struct_span_err, DiagnosticBuilder, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, ImplSubject, TyCtxt};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
use rustc_session::lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS;
use rustc_span::{Span, DUMMY_SP};
@@ -73,8 +73,8 @@ pub struct OverlapError {
/// through associated type projection. We deal with such cases by using
/// *fulfillment* to relate the two impls, requiring that all projections are
/// resolved.
-pub fn translate_substs<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn translate_substs<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
source_impl: DefId,
source_substs: SubstsRef<'tcx>,
@@ -149,13 +149,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
// Create an infcx, taking the predicates of impl1 as assumptions:
- tcx.infer_ctxt().enter(|infcx| {
- let impl1_trait_ref = match traits::fully_normalize(
- &infcx,
- ObligationCause::dummy(),
- penv,
- impl1_trait_ref,
- ) {
+ let infcx = tcx.infer_ctxt().build();
+ let impl1_trait_ref =
+ match traits::fully_normalize(&infcx, ObligationCause::dummy(), penv, impl1_trait_ref) {
Ok(impl1_trait_ref) => impl1_trait_ref,
Err(_errors) => {
tcx.sess.delay_span_bug(
@@ -166,9 +162,8 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
}
};
- // Attempt to prove that impl2 applies, given all of the above.
- fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
- })
+ // Attempt to prove that impl2 applies, given all of the above.
+ fulfill_implication(&infcx, penv, impl1_trait_ref, impl2_def_id).is_ok()
}
/// Attempt to fulfill all obligations of `target_impl` after unification with
@@ -176,8 +171,8 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
/// generics of `target_impl`, including both those needed to unify with
/// `source_trait_ref` and those whose identity is determined via a where
/// clause in the impl.
-fn fulfill_implication<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+fn fulfill_implication<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
source_trait_ref: ty::TraitRef<'tcx>,
target_impl: DefId,
@@ -350,26 +345,12 @@ fn report_conflicting_impls(
// Work to be done after we've built the DiagnosticBuilder. We have to define it
// now because the struct_lint methods don't return back the DiagnosticBuilder
// that's passed in.
- fn decorate<G: EmissionGuarantee>(
+ fn decorate<'a, 'b, G: EmissionGuarantee>(
tcx: TyCtxt<'_>,
overlap: OverlapError,
- used_to_be_allowed: Option<FutureCompatOverlapErrorKind>,
impl_span: Span,
- err: LintDiagnosticBuilder<'_, G>,
- ) -> G {
- let msg = format!(
- "conflicting implementations of trait `{}`{}{}",
- overlap.trait_desc,
- overlap
- .self_desc
- .clone()
- .map_or_else(String::new, |ty| { format!(" for type `{}`", ty) }),
- match used_to_be_allowed {
- Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)",
- _ => "",
- }
- );
- let mut err = err.build(&msg);
+ err: &'b mut DiagnosticBuilder<'a, G>,
+ ) -> &'b mut DiagnosticBuilder<'a, G> {
match tcx.span_of_impl(overlap.with_impl) {
Ok(span) => {
err.span_label(span, "first implementation here");
@@ -384,7 +365,9 @@ fn report_conflicting_impls(
}
Err(cname) => {
let msg = match to_pretty_impl_header(tcx, overlap.with_impl) {
- Some(s) => format!("conflicting implementation in crate `{}`:\n- {}", cname, s),
+ Some(s) => {
+ format!("conflicting implementation in crate `{}`:\n- {}", cname, s)
+ }
None => format!("conflicting implementation in crate `{}`", cname),
};
err.note(&msg);
@@ -392,28 +375,33 @@ fn report_conflicting_impls(
}
for cause in &overlap.intercrate_ambiguity_causes {
- cause.add_intercrate_ambiguity_hint(&mut err);
+ cause.add_intercrate_ambiguity_hint(err);
}
if overlap.involves_placeholder {
- coherence::add_placeholder_note(&mut err);
+ coherence::add_placeholder_note(err);
}
- err.emit()
+ err
}
+ let msg = format!(
+ "conflicting implementations of trait `{}`{}{}",
+ overlap.trait_desc,
+ overlap.self_desc.as_deref().map_or_else(String::new, |ty| format!(" for type `{ty}`")),
+ match used_to_be_allowed {
+ Some(FutureCompatOverlapErrorKind::Issue33140) => ": (E0119)",
+ _ => "",
+ }
+ );
+
match used_to_be_allowed {
None => {
let reported = if overlap.with_impl.is_local()
|| tcx.orphan_check_impl(impl_def_id).is_ok()
{
- let err = struct_span_err!(tcx.sess, impl_span, E0119, "");
- Some(decorate(
- tcx,
- overlap,
- used_to_be_allowed,
- impl_span,
- LintDiagnosticBuilder::new(err),
- ))
+ let mut err = struct_span_err!(tcx.sess, impl_span, E0119, "{msg}",);
+ decorate(tcx, overlap, impl_span, &mut err);
+ Some(err.emit())
} else {
Some(tcx.sess.delay_span_bug(impl_span, "impl should have failed the orphan check"))
};
@@ -428,9 +416,8 @@ fn report_conflicting_impls(
lint,
tcx.hir().local_def_id_to_hir_id(impl_def_id),
impl_span,
- |ldb| {
- decorate(tcx, overlap, used_to_be_allowed, impl_span, ldb);
- },
+ msg,
+ |err| decorate(tcx, overlap, impl_span, err),
);
}
};
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 fcb73b43f..63f89a33e 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs
@@ -137,9 +137,8 @@ impl ChildrenExt<'_> for Children {
impl_def_id,
traits::SkipLeakCheck::default(),
overlap_mode,
- |_| true,
- || false,
- );
+ )
+ .is_some();
let error = create_overlap_error(overlap);
@@ -162,34 +161,29 @@ impl ChildrenExt<'_> for Children {
impl_def_id,
traits::SkipLeakCheck::Yes,
overlap_mode,
- |overlap| {
- if let Some(overlap_kind) =
- tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
- {
- match overlap_kind {
- ty::ImplOverlapKind::Permitted { marker: _ } => {}
- ty::ImplOverlapKind::Issue33140 => {
- *last_lint_mut = Some(FutureCompatOverlapError {
- error: create_overlap_error(overlap),
- kind: FutureCompatOverlapErrorKind::Issue33140,
- });
- }
+ )
+ .map_or(Ok((false, false)), |overlap| {
+ if let Some(overlap_kind) =
+ tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
+ {
+ match overlap_kind {
+ ty::ImplOverlapKind::Permitted { marker: _ } => {}
+ ty::ImplOverlapKind::Issue33140 => {
+ *last_lint_mut = Some(FutureCompatOverlapError {
+ error: create_overlap_error(overlap),
+ kind: FutureCompatOverlapErrorKind::Issue33140,
+ });
}
-
- return Ok((false, false));
}
- let le = tcx.specializes((impl_def_id, possible_sibling));
- let ge = tcx.specializes((possible_sibling, impl_def_id));
+ return Ok((false, false));
+ }
- if le == ge {
- report_overlap_error(overlap, last_lint_mut)
- } else {
- Ok((le, ge))
- }
- },
- || Ok((false, false)),
- )?;
+ let le = tcx.specializes((impl_def_id, possible_sibling));
+ let ge = tcx.specializes((possible_sibling, impl_def_id));
+
+ if le == ge { report_overlap_error(overlap, last_lint_mut) } else { Ok((le, ge)) }
+ })?;
if le && !ge {
debug!(
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 5829a0f92..932dbbb81 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -68,7 +68,7 @@ pub fn search_for_adt_const_param_violation<'tcx>(
/// Note that this does *not* recursively check if the substructure of `adt_ty`
/// implements the traits.
fn type_marked_structural<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
adt_ty: Ty<'tcx>,
cause: ObligationCause<'tcx>,
) -> bool {
@@ -265,9 +265,8 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
pub fn provide(providers: &mut Providers) {
providers.has_structural_eq_impls = |tcx, ty| {
- tcx.infer_ctxt().enter(|infcx| {
- let cause = ObligationCause::dummy();
- type_marked_structural(&infcx, ty, cause)
- })
+ let infcx = tcx.infer_ctxt().build();
+ let cause = ObligationCause::dummy();
+ type_marked_structural(&infcx, ty, cause)
};
}
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 0f5dff01c..ed47d2f83 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -5,8 +5,8 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{GenericArg, SubstsRef};
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
pub use rustc_infer::traits::{self, util::*};
@@ -268,10 +268,7 @@ pub fn count_own_vtable_entries<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
) -> usize {
- let existential_trait_ref =
- trait_ref.map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
- let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
- tcx.own_existential_vtable_entries(existential_trait_ref).len()
+ tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
}
/// Given an upcast trait object described by `object`, returns the
@@ -282,15 +279,10 @@ pub fn get_vtable_index_of_object_method<'tcx, N>(
object: &super::ImplSourceObjectData<'tcx, N>,
method_def_id: DefId,
) -> Option<usize> {
- let existential_trait_ref = object
- .upcast_trait_ref
- .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
- let existential_trait_ref = tcx.erase_regions(existential_trait_ref);
-
// Count number of methods preceding the one we are selecting and
// add them to the total offset.
if let Some(index) = tcx
- .own_existential_vtable_entries(existential_trait_ref)
+ .own_existential_vtable_entries(object.upcast_trait_ref.def_id())
.iter()
.copied()
.position(|def_id| def_id == method_def_id)
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 5ea28fb47..fc0a9f690 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -14,8 +14,8 @@ use std::iter;
/// inference variable, returns `None`, because we are not able to
/// make any progress at all. This is to prevent "livelock" where we
/// say "$0 is WF if $0 is WF".
-pub fn obligations<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
recursion_depth: usize,
@@ -79,8 +79,8 @@ pub fn obligations<'a, 'tcx>(
/// 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
/// if `Bar: Eq`.
-pub fn trait_obligations<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn trait_obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
trait_pred: &ty::TraitPredicate<'tcx>,
@@ -102,8 +102,8 @@ pub fn trait_obligations<'a, 'tcx>(
}
#[instrument(skip(infcx), ret)]
-pub fn predicate_obligations<'a, 'tcx>(
- infcx: &InferCtxt<'a, 'tcx>,
+pub fn predicate_obligations<'tcx>(
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId,
predicate: ty::Predicate<'tcx>,
@@ -148,13 +148,8 @@ pub fn predicate_obligations<'a, 'tcx>(
wf.compute(a.into());
wf.compute(b.into());
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
- let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
- wf.out.extend(obligations);
-
- for arg in uv.substs.iter() {
- wf.compute(arg);
- }
+ ty::PredicateKind::ConstEvaluatable(ct) => {
+ wf.compute(ct.into());
}
ty::PredicateKind::ConstEquate(c1, c2) => {
wf.compute(c1.into());
@@ -219,12 +214,14 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
trait_ref, item, cause, pred
);
let (items, impl_def_id) = match item {
- Some(hir::Item { kind: hir::ItemKind::Impl(impl_), def_id, .. }) => (impl_.items, *def_id),
+ Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => {
+ (impl_.items, *owner_id)
+ }
_ => return,
};
let fix_span =
|impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind {
- hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::TyAlias(ty) => ty.span,
+ hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span,
_ => impl_item_ref.span,
};
@@ -241,7 +238,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.item_def_id)
&& let Some(impl_item_span) = items
.iter()
- .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+ .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
.map(fix_span)
{
cause.span = impl_item_span;
@@ -256,7 +253,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
tcx.impl_item_implementor_ids(impl_def_id).get(&item_def_id)
&& let Some(impl_item_span) = items
.iter()
- .find(|item| item.id.def_id.to_def_id() == impl_item_id)
+ .find(|item| item.id.owner_id.to_def_id() == impl_item_id)
.map(fix_span)
{
cause.span = impl_item_span;
@@ -275,7 +272,7 @@ impl<'tcx> WfPredicates<'tcx> {
traits::ObligationCause::new(self.span, self.body_id, code)
}
- fn normalize(self, infcx: &InferCtxt<'_, 'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
+ fn normalize(self, infcx: &InferCtxt<'tcx>) -> Vec<traits::PredicateObligation<'tcx>> {
let cause = self.cause(traits::WellFormed(None));
let param_env = self.param_env;
let mut obligations = Vec::with_capacity(self.out.len());
@@ -392,7 +389,8 @@ impl<'tcx> WfPredicates<'tcx> {
// `i32: Clone`
// `i32: Copy`
// ]
- let obligations = self.nominal_obligations(data.item_def_id, data.substs);
+ // Projection types do not require const predicates.
+ let obligations = self.nominal_obligations_without_const(data.item_def_id, data.substs);
self.out.extend(obligations);
let tcx = self.tcx();
@@ -449,14 +447,14 @@ impl<'tcx> WfPredicates<'tcx> {
// obligations are handled by the parent (e.g. `ty::Ref`).
GenericArgKind::Lifetime(_) => continue,
- GenericArgKind::Const(constant) => {
- match constant.kind() {
+ GenericArgKind::Const(ct) => {
+ match ct.kind() {
ty::ConstKind::Unevaluated(uv) => {
let obligations = self.nominal_obligations(uv.def.did, uv.substs);
self.out.extend(obligations);
let predicate =
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv))
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
.to_predicate(self.tcx());
let cause = self.cause(traits::WellFormed(None));
self.out.push(traits::Obligation::with_depth(
@@ -473,7 +471,7 @@ impl<'tcx> WfPredicates<'tcx> {
cause,
self.recursion_depth,
self.param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(constant.into()))
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into()))
.to_predicate(self.tcx()),
));
}
@@ -549,7 +547,7 @@ impl<'tcx> WfPredicates<'tcx> {
}
ty::FnDef(did, substs) => {
- let obligations = self.nominal_obligations(did, substs);
+ let obligations = self.nominal_obligations_without_const(did, substs);
self.out.extend(obligations);
}
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index ff5ca0cbc..0de28b826 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -7,8 +7,8 @@
//! `crate::chalk::lowering` (to lower rustc types into Chalk types).
use rustc_middle::traits::ChalkRustInterner as RustInterner;
-use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
+use rustc_middle::ty::{InternalSubsts, SubstsRef};
use rustc_ast::ast;
use rustc_attr as attr;
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index a20de08b4..d5a8ca5ea 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -4,7 +4,7 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
use rustc_span::source_map::{Span, DUMMY_SP};
use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
@@ -27,128 +27,120 @@ fn dropck_outlives<'tcx>(
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
debug!("dropck_outlives(goal={:#?})", canonical_goal);
- tcx.infer_ctxt().enter_with_canonical(
- DUMMY_SP,
- &canonical_goal,
- |ref infcx, goal, canonical_inference_vars| {
- let tcx = infcx.tcx;
- let ParamEnvAnd { param_env, value: for_ty } = goal;
-
- let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
- // A stack of types left to process. Each round, we pop
- // something from the stack and invoke
- // `dtorck_constraint_for_ty`. This may produce new types that
- // have to be pushed on the stack. This continues until we have explored
- // all the reachable types from the type `for_ty`.
- //
- // Example: Imagine that we have the following code:
- //
- // ```rust
- // struct A {
- // value: B,
- // children: Vec<A>,
- // }
- //
- // struct B {
- // value: u32
- // }
- //
- // fn f() {
- // let a: A = ...;
- // ..
- // } // here, `a` is dropped
- // ```
- //
- // at the point where `a` is dropped, we need to figure out
- // which types inside of `a` contain region data that may be
- // accessed by any destructors in `a`. We begin by pushing `A`
- // onto the stack, as that is the type of `a`. We will then
- // invoke `dtorck_constraint_for_ty` which will expand `A`
- // into the types of its fields `(B, Vec<A>)`. These will get
- // pushed onto the stack. Eventually, expanding `Vec<A>` will
- // lead to us trying to push `A` a second time -- to prevent
- // infinite recursion, we notice that `A` was already pushed
- // once and stop.
- let mut ty_stack = vec![(for_ty, 0)];
-
- // Set used to detect infinite recursion.
- let mut ty_set = FxHashSet::default();
-
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
- let cause = ObligationCause::dummy();
- let mut constraints = DropckConstraint::empty();
- while let Some((ty, depth)) = ty_stack.pop() {
- debug!(
- "{} kinds, {} overflows, {} ty_stack",
- result.kinds.len(),
- result.overflows.len(),
- ty_stack.len()
- );
- dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
- // "outlives" represent types/regions that may be touched
- // by a destructor.
- result.kinds.append(&mut constraints.outlives);
- result.overflows.append(&mut constraints.overflows);
-
- // If we have even one overflow, we should stop trying to evaluate further --
- // chances are, the subsequent overflows for this evaluation won't provide useful
- // information and will just decrease the speed at which we can emit these errors
- // (since we'll be printing for just that much longer for the often enormous types
- // that result here).
- if !result.overflows.is_empty() {
- break;
- }
+ let (ref infcx, goal, canonical_inference_vars) =
+ tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
+ let tcx = infcx.tcx;
+ let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+ let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+ // A stack of types left to process. Each round, we pop
+ // something from the stack and invoke
+ // `dtorck_constraint_for_ty`. This may produce new types that
+ // have to be pushed on the stack. This continues until we have explored
+ // all the reachable types from the type `for_ty`.
+ //
+ // Example: Imagine that we have the following code:
+ //
+ // ```rust
+ // struct A {
+ // value: B,
+ // children: Vec<A>,
+ // }
+ //
+ // struct B {
+ // value: u32
+ // }
+ //
+ // fn f() {
+ // let a: A = ...;
+ // ..
+ // } // here, `a` is dropped
+ // ```
+ //
+ // at the point where `a` is dropped, we need to figure out
+ // which types inside of `a` contain region data that may be
+ // accessed by any destructors in `a`. We begin by pushing `A`
+ // onto the stack, as that is the type of `a`. We will then
+ // invoke `dtorck_constraint_for_ty` which will expand `A`
+ // into the types of its fields `(B, Vec<A>)`. These will get
+ // pushed onto the stack. Eventually, expanding `Vec<A>` will
+ // lead to us trying to push `A` a second time -- to prevent
+ // infinite recursion, we notice that `A` was already pushed
+ // once and stop.
+ let mut ty_stack = vec![(for_ty, 0)];
+
+ // Set used to detect infinite recursion.
+ let mut ty_set = FxHashSet::default();
+
+ let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+
+ let cause = ObligationCause::dummy();
+ let mut constraints = DropckConstraint::empty();
+ while let Some((ty, depth)) = ty_stack.pop() {
+ debug!(
+ "{} kinds, {} overflows, {} ty_stack",
+ result.kinds.len(),
+ result.overflows.len(),
+ ty_stack.len()
+ );
+ dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+ // "outlives" represent types/regions that may be touched
+ // by a destructor.
+ result.kinds.append(&mut constraints.outlives);
+ result.overflows.append(&mut constraints.overflows);
+
+ // If we have even one overflow, we should stop trying to evaluate further --
+ // chances are, the subsequent overflows for this evaluation won't provide useful
+ // information and will just decrease the speed at which we can emit these errors
+ // (since we'll be printing for just that much longer for the often enormous types
+ // that result here).
+ if !result.overflows.is_empty() {
+ break;
+ }
- // dtorck types are "types that will get dropped but which
- // do not themselves define a destructor", more or less. We have
- // to push them onto the stack to be expanded.
- for ty in constraints.dtorck_types.drain(..) {
- match infcx.at(&cause, param_env).normalize(ty) {
- Ok(Normalized { value: ty, obligations }) => {
- fulfill_cx.register_predicate_obligations(infcx, obligations);
-
- debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
- match ty.kind() {
- // All parameters live for the duration of the
- // function.
- ty::Param(..) => {}
-
- // A projection that we couldn't resolve - it
- // might have a destructor.
- ty::Projection(..) | ty::Opaque(..) => {
- result.kinds.push(ty.into());
- }
-
- _ => {
- if ty_set.insert(ty) {
- ty_stack.push((ty, depth + 1));
- }
- }
- }
+ // dtorck types are "types that will get dropped but which
+ // do not themselves define a destructor", more or less. We have
+ // to push them onto the stack to be expanded.
+ for ty in constraints.dtorck_types.drain(..) {
+ match infcx.at(&cause, param_env).normalize(ty) {
+ Ok(Normalized { value: ty, obligations }) => {
+ fulfill_cx.register_predicate_obligations(infcx, obligations);
+
+ debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+ match ty.kind() {
+ // All parameters live for the duration of the
+ // function.
+ ty::Param(..) => {}
+
+ // A projection that we couldn't resolve - it
+ // might have a destructor.
+ ty::Projection(..) | ty::Opaque(..) => {
+ result.kinds.push(ty.into());
}
- // We don't actually expect to fail to normalize.
- // That implies a WF error somewhere else.
- Err(NoSolution) => {
- return Err(NoSolution);
+ _ => {
+ if ty_set.insert(ty) {
+ ty_stack.push((ty, depth + 1));
+ }
}
}
}
+
+ // We don't actually expect to fail to normalize.
+ // That implies a WF error somewhere else.
+ Err(NoSolution) => {
+ return Err(NoSolution);
+ }
}
+ }
+ }
- debug!("dropck_outlives: result = {:#?}", result);
+ debug!("dropck_outlives: result = {:#?}", result);
- infcx.make_canonicalized_query_response(
- canonical_inference_vars,
- result,
- &mut *fulfill_cx,
- )
- },
- )
+ infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx)
}
/// Returns a set of constraints that needs to be satisfied in
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 49c9ba459..493d5de08 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -18,17 +18,15 @@ fn evaluate_obligation<'tcx>(
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
// HACK This bubble is required for this tests to pass:
// impl-trait/issue99642.rs
- tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_with_canonical(
- DUMMY_SP,
- &canonical_goal,
- |ref infcx, goal, _canonical_inference_vars| {
- debug!("evaluate_obligation: goal={:#?}", goal);
- let ParamEnvAnd { param_env, value: predicate } = goal;
+ let (ref infcx, goal, _canonical_inference_vars) = tcx
+ .infer_ctxt()
+ .with_opaque_type_inference(DefiningAnchor::Bubble)
+ .build_with_canonical(DUMMY_SP, &canonical_goal);
+ debug!("evaluate_obligation: goal={:#?}", goal);
+ let ParamEnvAnd { param_env, value: predicate } = goal;
- let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
- let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+ let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
+ let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
- selcx.evaluate_root_obligation(&obligation)
- },
- )
+ selcx.evaluate_root_obligation(&obligation)
}
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 691b79f10..7d36b9558 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -35,7 +35,7 @@ fn implied_outlives_bounds<'tcx>(
}
fn compute_implied_outlives_bounds<'tcx>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
@@ -79,7 +79,7 @@ fn compute_implied_outlives_bounds<'tcx>(
// implied bounds in some cases, mostly when dealing with projections.
fulfill_cx.register_predicate_obligations(
infcx,
- obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(),
+ obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
);
// From the full set of obligations, just filter down to the
@@ -156,6 +156,9 @@ fn implied_bounds_from_components<'tcx>(
Component::Region(r) => Some(OutlivesBound::RegionSubRegion(sub_region, r)),
Component::Param(p) => Some(OutlivesBound::RegionSubParam(sub_region, p)),
Component::Projection(p) => Some(OutlivesBound::RegionSubProjection(sub_region, p)),
+ Component::Opaque(def_id, substs) => {
+ Some(OutlivesBound::RegionSubOpaque(sub_region, def_id, substs))
+ }
Component::EscapingProjection(_) =>
// If the projection has escaping regions, don't
// try to infer any implied bounds even for its
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 2d39e973e..0da28737f 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -3,7 +3,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![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 5d394ed22..2da64d73d 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -18,9 +18,6 @@ pub(crate) fn provide(p: &mut Providers) {
try_normalize_after_erasing_regions(tcx, goal)
},
- try_normalize_mir_const_after_erasing_regions: |tcx, goal| {
- try_normalize_after_erasing_regions(tcx, goal)
- },
..*p
};
}
@@ -30,30 +27,29 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
goal: ParamEnvAnd<'tcx, T>,
) -> Result<T, NoSolution> {
let ParamEnvAnd { param_env, value } = goal;
- tcx.infer_ctxt().enter(|infcx| {
- let cause = ObligationCause::dummy();
- match infcx.at(&cause, param_env).normalize(value) {
- Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
- // We don't care about the `obligations`; they are
- // always only region relations, and we are about to
- // erase those anyway:
- debug_assert_eq!(
- normalized_obligations.iter().find(|p| not_outlives_predicate(p.predicate)),
- None,
- );
+ let infcx = tcx.infer_ctxt().build();
+ let cause = ObligationCause::dummy();
+ match infcx.at(&cause, param_env).normalize(value) {
+ Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
+ // We don't care about the `obligations`; they are
+ // always only region relations, and we are about to
+ // erase those anyway:
+ debug_assert_eq!(
+ normalized_obligations.iter().find(|p| not_outlives_predicate(p.predicate)),
+ None,
+ );
- let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
- // It's unclear when `resolve_vars` would have an effect in a
- // fresh `InferCtxt`. If this assert does trigger, it will give
- // us a test case.
- debug_assert_eq!(normalized_value, resolved_value);
- let erased = infcx.tcx.erase_regions(resolved_value);
- debug_assert!(!erased.needs_infer(), "{:?}", erased);
- Ok(erased)
- }
- Err(NoSolution) => Err(NoSolution),
+ let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
+ // It's unclear when `resolve_vars` would have an effect in a
+ // fresh `InferCtxt`. If this assert does trigger, it will give
+ // us a test case.
+ debug_assert_eq!(normalized_value, resolved_value);
+ let erased = infcx.tcx.erase_regions(resolved_value);
+ debug_assert!(!erased.needs_infer(), "{:?}", erased);
+ Ok(erased)
}
- })
+ Err(NoSolution) => Err(NoSolution),
+ }
}
fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index 1bb6506b3..bca7458ed 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -5,10 +5,10 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _};
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts};
use rustc_middle::ty::{
self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance,
};
+use rustc_middle::ty::{GenericArg, UserSelfTy, UserSubsts};
use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
@@ -51,7 +51,7 @@ fn type_op_ascribe_user_type<'tcx>(
/// this query can be re-run to better track the span of the obligation cause, and improve the error
/// message. Do not call directly unless you're in that very specific context.
pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
span: Option<Span>,
@@ -68,7 +68,7 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
}
struct AscribeUserTypeCx<'me, 'tcx> {
- infcx: &'me InferCtxt<'me, 'tcx>,
+ infcx: &'me InferCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
span: Span,
fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
@@ -210,7 +210,7 @@ fn type_op_eq<'tcx>(
}
fn type_op_normalize<'tcx, T>(
- infcx: &InferCtxt<'_, 'tcx>,
+ infcx: &InferCtxt<'tcx>,
fulfill_cx: &mut dyn TraitEngine<'tcx>,
key: ParamEnvAnd<'tcx, Normalize<T>>,
) -> Fallible<T>
@@ -285,7 +285,7 @@ fn type_op_prove_predicate<'tcx>(
/// this query can be re-run to better track the span of the obligation cause, and improve the error
/// message. Do not call directly unless you're in that very specific context.
pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>(
- infcx: &'a InferCtxt<'a, 'tcx>,
+ infcx: &'a InferCtxt<'tcx>,
fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
cause: ObligationCause<'tcx>,
diff --git a/compiler/rustc_transmute/src/layout/tree.rs b/compiler/rustc_transmute/src/layout/tree.rs
index 211c813b8..acd4fa63d 100644
--- a/compiler/rustc_transmute/src/layout/tree.rs
+++ b/compiler/rustc_transmute/src/layout/tree.rs
@@ -404,7 +404,7 @@ pub(crate) mod rustc {
.unwrap();
trace!(?discr_layout, "computed discriminant layout");
variant_layout = variant_layout.extend(discr_layout).unwrap().0;
- tree = tree.then(Self::from_disr(discr, tcx, layout_summary.discriminant_size));
+ tree = tree.then(Self::from_discr(discr, tcx, layout_summary.discriminant_size));
}
// Next come fields.
@@ -444,11 +444,21 @@ pub(crate) mod rustc {
Ok(tree)
}
- pub fn from_disr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self {
- // FIXME(@jswrenn): I'm certain this is missing needed endian nuance.
- let bytes = discr.val.to_ne_bytes();
- let bytes = &bytes[..size];
- Self::Seq(bytes.into_iter().copied().map(|b| Self::from_bits(b)).collect())
+ pub fn from_discr(discr: Discr<'tcx>, tcx: TyCtxt<'tcx>, size: usize) -> Self {
+ use rustc_target::abi::Endian;
+
+ let bytes: [u8; 16];
+ let bytes = match tcx.data_layout.endian {
+ Endian::Little => {
+ bytes = discr.val.to_le_bytes();
+ &bytes[..size]
+ }
+ Endian::Big => {
+ bytes = discr.val.to_be_bytes();
+ &bytes[bytes.len() - size..]
+ }
+ };
+ Self::Seq(bytes.iter().map(|&b| Self::from_bits(b)).collect())
}
}
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index 64cd70d36..f7cc94e53 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -80,11 +80,11 @@ mod rustc {
}
pub struct TransmuteTypeEnv<'cx, 'tcx> {
- infcx: &'cx InferCtxt<'cx, 'tcx>,
+ infcx: &'cx InferCtxt<'tcx>,
}
impl<'cx, 'tcx> TransmuteTypeEnv<'cx, 'tcx> {
- pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> Self {
+ pub fn new(infcx: &'cx InferCtxt<'tcx>) -> Self {
Self { infcx }
}
@@ -115,7 +115,7 @@ mod rustc {
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
c: Const<'tcx>,
- ) -> Self {
+ ) -> Option<Self> {
use rustc_middle::ty::ScalarInt;
use rustc_middle::ty::TypeVisitable;
use rustc_span::symbol::sym;
@@ -123,10 +123,15 @@ mod rustc {
let c = c.eval(tcx, param_env);
if let Some(err) = c.error_reported() {
- return Self { alignment: true, lifetimes: true, safety: true, validity: true };
+ return Some(Self {
+ alignment: true,
+ lifetimes: true,
+ safety: true,
+ validity: true,
+ });
}
- let adt_def = c.ty().ty_adt_def().expect("The given `Const` must be an ADT.");
+ let adt_def = c.ty().ty_adt_def()?;
assert_eq!(
tcx.require_lang_item(LangItem::TransmuteOpts, None),
@@ -148,12 +153,12 @@ mod rustc {
fields[field_idx].unwrap_leaf() == ScalarInt::TRUE
};
- Self {
+ Some(Self {
alignment: get_field(sym::alignment),
lifetimes: get_field(sym::lifetimes),
safety: get_field(sym::safety),
validity: get_field(sym::validity),
- }
+ })
}
}
}
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 52fbd3ae0..5e4ba4730 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -4,6 +4,8 @@ version = "0.0.0"
edition = "2021"
[dependencies]
+rand = "0.8.4"
+rand_xoshiro = "0.6.0"
tracing = "0.1"
rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
new file mode 100644
index 000000000..73c7eb699
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -0,0 +1,551 @@
+use rustc_hir as hir;
+use rustc_hir::lang_items::LangItem;
+use rustc_middle::ty::layout::{
+ fn_can_unwind, FnAbiError, HasParamEnv, HasTyCtxt, LayoutCx, LayoutOf, TyAndLayout,
+};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::config::OptLevel;
+use rustc_span::def_id::DefId;
+use rustc_target::abi::call::{
+ ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, Conv, FnAbi, PassMode, Reg, RegKind,
+};
+use rustc_target::abi::*;
+use rustc_target::spec::abi::Abi as SpecAbi;
+
+use std::iter;
+
+pub fn provide(providers: &mut ty::query::Providers) {
+ *providers = ty::query::Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
+}
+
+// NOTE(eddyb) this is private to avoid using it from outside of
+// `fn_abi_of_instance` - any other uses are either too high-level
+// for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
+// or should go through `FnAbi` instead, to avoid losing any
+// adjustments `fn_abi_of_instance` might be performing.
+#[tracing::instrument(level = "debug", skip(tcx, param_env))]
+fn fn_sig_for_fn_abi<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ instance: ty::Instance<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+) -> ty::PolyFnSig<'tcx> {
+ let ty = instance.ty(tcx, param_env);
+ match *ty.kind() {
+ ty::FnDef(..) => {
+ // HACK(davidtwco,eddyb): This is a workaround for polymorphization considering
+ // parameters unused if they show up in the signature, but not in the `mir::Body`
+ // (i.e. due to being inside a projection that got normalized, see
+ // `src/test/ui/polymorphization/normalized_sig_types.rs`), and codegen not keeping
+ // track of a polymorphization `ParamEnv` to allow normalizing later.
+ //
+ // 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)
+ .map_bound(|fn_sig| {
+ tcx.normalize_erasing_regions(tcx.param_env(def_id), fn_sig)
+ })
+ .subst(tcx, substs),
+ _ => unreachable!(),
+ };
+
+ if let ty::InstanceDef::VTableShim(..) = instance.def {
+ // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
+ 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
+ });
+ }
+ sig
+ }
+ ty::Closure(def_id, substs) => {
+ let sig = substs.as_closure().sig();
+
+ let bound_vars = tcx.mk_bound_variable_kinds(
+ sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
+ );
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind: ty::BoundRegionKind::BrEnv,
+ };
+ let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let env_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap();
+
+ let sig = sig.skip_binder();
+ ty::Binder::bind_with_vars(
+ tcx.mk_fn_sig(
+ iter::once(env_ty).chain(sig.inputs().iter().cloned()),
+ sig.output(),
+ sig.c_variadic,
+ sig.unsafety,
+ sig.abi,
+ ),
+ bound_vars,
+ )
+ }
+ ty::Generator(_, substs, _) => {
+ let sig = substs.as_generator().poly_sig();
+
+ let bound_vars = tcx.mk_bound_variable_kinds(
+ sig.bound_vars().iter().chain(iter::once(ty::BoundVariableKind::Region(ty::BrEnv))),
+ );
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_usize(bound_vars.len() - 1),
+ kind: ty::BoundRegionKind::BrEnv,
+ };
+ let env_region = ty::ReLateBound(ty::INNERMOST, br);
+ let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
+
+ 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 env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
+
+ let sig = sig.skip_binder();
+ let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+ let state_adt_ref = tcx.adt_def(state_did);
+ let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+ let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+ ty::Binder::bind_with_vars(
+ tcx.mk_fn_sig(
+ [env_ty, sig.resume_ty].iter(),
+ &ret_ty,
+ false,
+ hir::Unsafety::Normal,
+ rustc_target::spec::abi::Abi::Rust,
+ ),
+ bound_vars,
+ )
+ }
+ _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
+ }
+}
+
+#[inline]
+fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
+ use rustc_target::spec::abi::Abi::*;
+ match tcx.sess.target.adjust_abi(abi) {
+ RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust,
+ RustCold => Conv::RustCold,
+
+ // It's the ABI's job to select this, not ours.
+ System { .. } => bug!("system abi should be selected elsewhere"),
+ EfiApi => bug!("eficall abi should be selected elsewhere"),
+
+ Stdcall { .. } => Conv::X86Stdcall,
+ Fastcall { .. } => Conv::X86Fastcall,
+ Vectorcall { .. } => Conv::X86VectorCall,
+ Thiscall { .. } => Conv::X86ThisCall,
+ C { .. } => Conv::C,
+ Unadjusted => Conv::C,
+ Win64 { .. } => Conv::X86_64Win64,
+ SysV64 { .. } => Conv::X86_64SysV,
+ Aapcs { .. } => Conv::ArmAapcs,
+ CCmseNonSecureCall => Conv::CCmseNonSecureCall,
+ PtxKernel => Conv::PtxKernel,
+ Msp430Interrupt => Conv::Msp430Intr,
+ X86Interrupt => Conv::X86Intr,
+ AmdGpuKernel => Conv::AmdGpuKernel,
+ AvrInterrupt => Conv::AvrInterrupt,
+ AvrNonBlockingInterrupt => Conv::AvrNonBlockingInterrupt,
+ Wasm => Conv::C,
+
+ // These API constants ought to be more specific...
+ Cdecl { .. } => Conv::C,
+ }
+}
+
+fn fn_abi_of_fn_ptr<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ query: ty::ParamEnvAnd<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ let (param_env, (sig, extra_args)) = query.into_parts();
+
+ let cx = LayoutCx { tcx, param_env };
+ fn_abi_new_uncached(&cx, sig, extra_args, None, None, false)
+}
+
+fn fn_abi_of_instance<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ query: ty::ParamEnvAnd<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ let (param_env, (instance, extra_args)) = query.into_parts();
+
+ 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
+ };
+
+ fn_abi_new_uncached(
+ &LayoutCx { tcx, param_env },
+ sig,
+ extra_args,
+ caller_location,
+ Some(instance.def_id()),
+ matches!(instance.def, ty::InstanceDef::Virtual(..)),
+ )
+}
+
+// Handle safe Rust thin and fat pointers.
+fn adjust_for_rust_scalar<'tcx>(
+ cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
+ attrs: &mut ArgAttributes,
+ scalar: Scalar,
+ layout: TyAndLayout<'tcx>,
+ offset: Size,
+ is_return: bool,
+) {
+ // Booleans are always a noundef i1 that needs to be zero-extended.
+ if scalar.is_bool() {
+ attrs.ext(ArgExtension::Zext);
+ attrs.set(ArgAttribute::NoUndef);
+ return;
+ }
+
+ // Scalars which have invalid values cannot be undef.
+ if !scalar.is_always_valid(&cx) {
+ attrs.set(ArgAttribute::NoUndef);
+ }
+
+ // Only pointer types handled below.
+ let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
+
+ if !valid_range.contains(0) {
+ attrs.set(ArgAttribute::NonNull);
+ }
+
+ if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
+ 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.
+ attrs.pointee_size = match kind {
+ PointerKind::UniqueBorrowed
+ | PointerKind::UniqueBorrowedPinned
+ | PointerKind::Frozen => pointee.size,
+ PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+ };
+
+ // `Box`, `&T`, and `&mut T` cannot be undef.
+ // Note that this only applies to the value of the pointer itself;
+ // this attribute doesn't make it UB for the pointed-to data to be undef.
+ attrs.set(ArgAttribute::NoUndef);
+
+ // The aliasing rules for `Box<T>` are still not decided, but currently we emit
+ // `noalias` for it. This can be turned off using an unstable flag.
+ // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
+ let noalias_for_box = cx.tcx.sess.opts.unstable_opts.box_noalias.unwrap_or(true);
+
+ // `&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
+ //
+ // Due to past miscompiles in LLVM, we apply a separate NoAliasMutRef attribute
+ // for UniqueBorrowed arguments, so that the codegen backend can decide whether
+ // or not to actually emit the attribute. It can also be controlled with the
+ // `-Zmutable-noalias` debugging option.
+ let no_alias = match kind {
+ PointerKind::SharedMutable
+ | PointerKind::UniqueBorrowed
+ | PointerKind::UniqueBorrowedPinned => false,
+ PointerKind::UniqueOwned => noalias_for_box,
+ PointerKind::Frozen => !is_return,
+ };
+ if no_alias {
+ attrs.set(ArgAttribute::NoAlias);
+ }
+
+ if kind == PointerKind::Frozen && !is_return {
+ attrs.set(ArgAttribute::ReadOnly);
+ }
+
+ if kind == PointerKind::UniqueBorrowed && !is_return {
+ attrs.set(ArgAttribute::NoAliasMutRef);
+ }
+ }
+ }
+}
+
+// FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
+// arguments of this method, into a separate `struct`.
+#[tracing::instrument(level = "debug", skip(cx, caller_location, fn_def_id, force_thin_self_ptr))]
+fn fn_abi_new_uncached<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ sig: ty::PolyFnSig<'tcx>,
+ extra_args: &[Ty<'tcx>],
+ caller_location: Option<Ty<'tcx>>,
+ fn_def_id: Option<DefId>,
+ // FIXME(eddyb) replace this with something typed, like an `enum`.
+ force_thin_self_ptr: bool,
+) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> {
+ let sig = cx.tcx.normalize_erasing_late_bound_regions(cx.param_env, sig);
+
+ let conv = conv_from_spec_abi(cx.tcx(), sig.abi);
+
+ let mut inputs = sig.inputs();
+ let extra_args = if sig.abi == RustCall {
+ assert!(!sig.c_variadic && extra_args.is_empty());
+
+ if let Some(input) = sig.inputs().last() {
+ if let ty::Tuple(tupled_arguments) = input.kind() {
+ inputs = &sig.inputs()[0..sig.inputs().len() - 1];
+ tupled_arguments
+ } else {
+ bug!(
+ "argument to function with \"rust-call\" ABI \
+ is not a tuple"
+ );
+ }
+ } else {
+ bug!(
+ "argument to function with \"rust-call\" ABI \
+ is not a tuple"
+ );
+ }
+ } else {
+ assert!(sig.c_variadic || extra_args.is_empty());
+ extra_args
+ };
+
+ let target = &cx.tcx.sess.target;
+ let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc");
+ let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
+ let linux_s390x_gnu_like =
+ target.os == "linux" && target.arch == "s390x" && target_env_gnu_like;
+ let linux_sparc64_gnu_like =
+ target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like;
+ let linux_powerpc_gnu_like =
+ target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like;
+ use SpecAbi::*;
+ let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall);
+
+ let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, FnAbiError<'tcx>> {
+ let span = tracing::debug_span!("arg_of");
+ let _entered = span.enter();
+ let is_return = arg_idx.is_none();
+
+ let layout = cx.layout_of(ty)?;
+ let layout = if force_thin_self_ptr && arg_idx == Some(0) {
+ // Don't pass the vtable, it's not an argument of the virtual fn.
+ // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
+ // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
+ make_thin_self_ptr(cx, layout)
+ } else {
+ layout
+ };
+
+ let mut arg = ArgAbi::new(cx, layout, |layout, scalar, offset| {
+ let mut attrs = ArgAttributes::new();
+ adjust_for_rust_scalar(*cx, &mut attrs, scalar, *layout, offset, is_return);
+ attrs
+ });
+
+ if arg.layout.is_zst() {
+ // For some forsaken reason, x86_64-pc-windows-gnu
+ // doesn't ignore zero-sized struct arguments.
+ // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
+ if is_return
+ || rust_abi
+ || (!win_x64_gnu
+ && !linux_s390x_gnu_like
+ && !linux_sparc64_gnu_like
+ && !linux_powerpc_gnu_like)
+ {
+ arg.mode = PassMode::Ignore;
+ }
+ }
+
+ Ok(arg)
+ };
+
+ let mut fn_abi = FnAbi {
+ ret: arg_of(sig.output(), None)?,
+ args: inputs
+ .iter()
+ .copied()
+ .chain(extra_args.iter().copied())
+ .chain(caller_location)
+ .enumerate()
+ .map(|(i, ty)| arg_of(ty, Some(i)))
+ .collect::<Result<_, _>>()?,
+ c_variadic: sig.c_variadic,
+ fixed_count: inputs.len() as u32,
+ conv,
+ can_unwind: fn_can_unwind(cx.tcx(), fn_def_id, sig.abi),
+ };
+ fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi, fn_def_id)?;
+ debug!("fn_abi_new_uncached = {:?}", fn_abi);
+ Ok(cx.tcx.arena.alloc(fn_abi))
+}
+
+#[tracing::instrument(level = "trace", skip(cx))]
+fn fn_abi_adjust_for_abi<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
+ abi: SpecAbi,
+ fn_def_id: Option<DefId>,
+) -> Result<(), FnAbiError<'tcx>> {
+ if abi == SpecAbi::Unadjusted {
+ return Ok(());
+ }
+
+ if abi == SpecAbi::Rust
+ || abi == SpecAbi::RustCall
+ || abi == SpecAbi::RustIntrinsic
+ || abi == SpecAbi::PlatformIntrinsic
+ {
+ // Look up the deduced parameter attributes for this function, if we have its def ID and
+ // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
+ // as appropriate.
+ let deduced_param_attrs = if cx.tcx.sess.opts.optimize != OptLevel::No
+ && cx.tcx.sess.opts.incremental.is_none()
+ {
+ fn_def_id.map(|fn_def_id| cx.tcx.deduced_param_attrs(fn_def_id)).unwrap_or_default()
+ } else {
+ &[]
+ };
+
+ let fixup = |arg: &mut ArgAbi<'tcx, Ty<'tcx>>, arg_idx: Option<usize>| {
+ if arg.is_ignore() {
+ return;
+ }
+
+ match arg.layout.abi {
+ Abi::Aggregate { .. } => {}
+
+ // This is a fun case! The gist of what this is doing is
+ // that we want callers and callees to always agree on the
+ // ABI of how they pass SIMD arguments. If we were to *not*
+ // make these arguments indirect then they'd be immediates
+ // in LLVM, which means that they'd used whatever the
+ // appropriate ABI is for the callee and the caller. That
+ // means, for example, if the caller doesn't have AVX
+ // enabled but the callee does, then passing an AVX argument
+ // across this boundary would cause corrupt data to show up.
+ //
+ // This problem is fixed by unconditionally passing SIMD
+ // arguments through memory between callers and callees
+ // which should get them all to agree on ABI regardless of
+ // target feature sets. Some more information about this
+ // issue can be found in #44367.
+ //
+ // Note that the platform intrinsic ABI is exempt here as
+ // that's how we connect up to LLVM and it's unstable
+ // anyway, we control all calls to it in libstd.
+ Abi::Vector { .. }
+ if abi != SpecAbi::PlatformIntrinsic
+ && cx.tcx.sess.target.simd_types_indirect =>
+ {
+ arg.make_indirect();
+ return;
+ }
+
+ _ => return,
+ }
+
+ let size = arg.layout.size;
+ if arg.layout.is_unsized() || size > Pointer.size(cx) {
+ arg.make_indirect();
+ } else {
+ // We want to pass small aggregates as immediates, but using
+ // a LLVM aggregate type for this leads to bad optimizations,
+ // so we pick an appropriately sized integer type instead.
+ arg.cast_to(Reg { kind: RegKind::Integer, size });
+ }
+
+ // If we deduced that this parameter was read-only, add that to the attribute list now.
+ //
+ // The `readonly` parameter only applies to pointers, so we can only do this if the
+ // argument was passed indirectly. (If the argument is passed directly, it's an SSA
+ // value, so it's implicitly immutable.)
+ if let (Some(arg_idx), &mut PassMode::Indirect { ref mut attrs, .. }) =
+ (arg_idx, &mut arg.mode)
+ {
+ // The `deduced_param_attrs` list could be empty if this is a type of function
+ // we can't deduce any parameters for, so make sure the argument index is in
+ // bounds.
+ if let Some(deduced_param_attrs) = deduced_param_attrs.get(arg_idx) {
+ if deduced_param_attrs.read_only {
+ attrs.regular.insert(ArgAttribute::ReadOnly);
+ debug!("added deduced read-only attribute");
+ }
+ }
+ }
+ };
+
+ fixup(&mut fn_abi.ret, None);
+ for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
+ fixup(arg, Some(arg_idx));
+ }
+ } else {
+ fn_abi.adjust_for_foreign_abi(cx, abi)?;
+ }
+
+ Ok(())
+}
+
+#[tracing::instrument(level = "debug", skip(cx))]
+fn make_thin_self_ptr<'tcx>(
+ cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
+ layout: TyAndLayout<'tcx>,
+) -> TyAndLayout<'tcx> {
+ let tcx = cx.tcx();
+ let fat_pointer_ty = if layout.is_unsized() {
+ // unsized `self` is passed as a pointer to `self`
+ // FIXME (mikeyhew) change this to use &own if it is ever added to the language
+ tcx.mk_mut_ptr(layout.ty)
+ } else {
+ match layout.abi {
+ Abi::ScalarPair(..) | Abi::Scalar(..) => (),
+ _ => bug!("receiver type has unsupported layout: {:?}", layout),
+ }
+
+ // In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
+ // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
+ // elsewhere in the compiler as a method on a `dyn Trait`.
+ // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
+ // get a built-in pointer type
+ let mut fat_pointer_layout = layout;
+ 'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr()
+ && !fat_pointer_layout.ty.is_region_ptr()
+ {
+ for i in 0..fat_pointer_layout.fields.count() {
+ let field_layout = fat_pointer_layout.field(cx, i);
+
+ if !field_layout.is_zst() {
+ fat_pointer_layout = field_layout;
+ continue 'descend_newtypes;
+ }
+ }
+
+ bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout);
+ }
+
+ fat_pointer_layout.ty
+ };
+
+ // we now have a type like `*mut RcBox<dyn Trait>`
+ // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
+ // this is understood as a special case elsewhere in the compiler
+ let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit());
+
+ TyAndLayout {
+ ty: fat_pointer_ty,
+
+ // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
+ // should always work because the type is always `*mut ()`.
+ ..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
+ }
+}
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 515a73ead..424b52309 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -17,10 +17,10 @@ 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.def_id.to_def_id()),
+ 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.def_id.to_def_id()),
+ impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
),
hir::ItemKind::TraitAlias(..) => &[],
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
@@ -42,11 +42,11 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId
fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
let parent_def_id = tcx.hir().get_parent_item(id);
- let parent_item = tcx.hir().expect_item(parent_def_id);
+ let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
match parent_item.kind {
hir::ItemKind::Impl(ref impl_) => {
if let Some(impl_item_ref) =
- impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id)
+ impl_.items.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
{
let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
debug_assert_eq!(assoc_item.def_id, def_id);
@@ -56,7 +56,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
hir::ItemKind::Trait(.., ref trait_item_refs) => {
if let Some(trait_item_ref) =
- trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id)
+ trait_item_refs.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
{
let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
debug_assert_eq!(assoc_item.def_id, def_id);
@@ -75,7 +75,7 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
}
fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
- let def_id = trait_item_ref.id.def_id;
+ let owner_id = trait_item_ref.id.owner_id;
let (kind, has_self) = match trait_item_ref.kind {
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
@@ -85,15 +85,15 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
ty::AssocItem {
name: trait_item_ref.ident.name,
kind,
- def_id: def_id.to_def_id(),
- trait_item_def_id: Some(def_id.to_def_id()),
+ def_id: owner_id.to_def_id(),
+ trait_item_def_id: Some(owner_id.to_def_id()),
container: ty::TraitContainer,
fn_has_self_parameter: has_self,
}
}
fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
- let def_id = impl_item_ref.id.def_id;
+ let def_id = impl_item_ref.id.owner_id;
let (kind, has_self) = match impl_item_ref.kind {
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs
index cedc84d97..d3169b6d9 100644
--- a/compiler/rustc_ty_utils/src/common_traits.rs
+++ b/compiler/rustc_ty_utils/src/common_traits.rs
@@ -29,15 +29,8 @@ fn is_item_raw<'tcx>(
) -> bool {
let (param_env, ty) = query.into_parts();
let trait_def_id = tcx.require_lang_item(item, None);
- tcx.infer_ctxt().enter(|infcx| {
- traits::type_known_to_meet_bound_modulo_regions(
- &infcx,
- param_env,
- ty,
- trait_def_id,
- DUMMY_SP,
- )
- })
+ let infcx = tcx.infer_ctxt().build();
+ traits::type_known_to_meet_bound_modulo_regions(&infcx, param_env, ty, trait_def_id, DUMMY_SP)
}
pub(crate) fn provide(providers: &mut ty::query::Providers) {
diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs
index 44c4fc48d..e057bb668 100644
--- a/compiler/rustc_ty_utils/src/consts.rs
+++ b/compiler/rustc_ty_utils/src/consts.rs
@@ -135,30 +135,30 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
fn expr_is_poly(&mut self, expr: &thir::Expr<'tcx>) -> bool {
- if expr.ty.has_param_types_or_consts() {
+ if expr.ty.has_non_region_param() {
return true;
}
match expr.kind {
- thir::ExprKind::NamedConst { substs, .. } => substs.has_param_types_or_consts(),
+ thir::ExprKind::NamedConst { substs, .. } => substs.has_non_region_param(),
thir::ExprKind::ConstParam { .. } => true,
thir::ExprKind::Repeat { value, count } => {
self.visit_expr(&self.thir()[value]);
- count.has_param_types_or_consts()
+ count.has_non_region_param()
}
_ => false,
}
}
fn pat_is_poly(&mut self, pat: &thir::Pat<'tcx>) -> bool {
- if pat.ty.has_param_types_or_consts() {
+ if pat.ty.has_non_region_param() {
return true;
}
match pat.kind {
- thir::PatKind::Constant { value } => value.has_param_types_or_consts(),
+ thir::PatKind::Constant { value } => value.has_non_region_param(),
thir::PatKind::Range(box thir::PatRange { lo, hi, .. }) => {
- lo.has_param_types_or_consts() || hi.has_param_types_or_consts()
+ lo.has_non_region_param() || hi.has_non_region_param()
}
_ => false,
}
@@ -258,7 +258,8 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
self.nodes.push(Node::Leaf(ty::Const::from_value(self.tcx, val, node.ty)))
}
&ExprKind::NamedConst { def_id, substs, user_ty: _ } => {
- let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs);
+ let uneval =
+ ty::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs);
let constant = self
.tcx
diff --git a/compiler/rustc_ty_utils/src/errors.rs b/compiler/rustc_ty_utils/src/errors.rs
index 3a8ef96c9..c05eeb353 100644
--- a/compiler/rustc_ty_utils/src/errors.rs
+++ b/compiler/rustc_ty_utils/src/errors.rs
@@ -1,69 +1,69 @@
//! Errors emitted by ty_utils
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(ty_utils::needs_drop_overflow)]
+#[derive(Diagnostic)]
+#[diag(ty_utils_needs_drop_overflow)]
pub struct NeedsDropOverflow<'tcx> {
pub query_ty: Ty<'tcx>,
}
-#[derive(SessionDiagnostic)]
-#[diag(ty_utils::generic_constant_too_complex)]
+#[derive(Diagnostic)]
+#[diag(ty_utils_generic_constant_too_complex)]
#[help]
pub struct GenericConstantTooComplex {
#[primary_span]
pub span: Span,
- #[note(ty_utils::maybe_supported)]
+ #[note(maybe_supported)]
pub maybe_supported: Option<()>,
#[subdiagnostic]
pub sub: GenericConstantTooComplexSub,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum GenericConstantTooComplexSub {
- #[label(ty_utils::borrow_not_supported)]
+ #[label(ty_utils_borrow_not_supported)]
BorrowNotSupported(#[primary_span] Span),
- #[label(ty_utils::address_and_deref_not_supported)]
+ #[label(ty_utils_address_and_deref_not_supported)]
AddressAndDerefNotSupported(#[primary_span] Span),
- #[label(ty_utils::array_not_supported)]
+ #[label(ty_utils_array_not_supported)]
ArrayNotSupported(#[primary_span] Span),
- #[label(ty_utils::block_not_supported)]
+ #[label(ty_utils_block_not_supported)]
BlockNotSupported(#[primary_span] Span),
- #[label(ty_utils::never_to_any_not_supported)]
+ #[label(ty_utils_never_to_any_not_supported)]
NeverToAnyNotSupported(#[primary_span] Span),
- #[label(ty_utils::tuple_not_supported)]
+ #[label(ty_utils_tuple_not_supported)]
TupleNotSupported(#[primary_span] Span),
- #[label(ty_utils::index_not_supported)]
+ #[label(ty_utils_index_not_supported)]
IndexNotSupported(#[primary_span] Span),
- #[label(ty_utils::field_not_supported)]
+ #[label(ty_utils_field_not_supported)]
FieldNotSupported(#[primary_span] Span),
- #[label(ty_utils::const_block_not_supported)]
+ #[label(ty_utils_const_block_not_supported)]
ConstBlockNotSupported(#[primary_span] Span),
- #[label(ty_utils::adt_not_supported)]
+ #[label(ty_utils_adt_not_supported)]
AdtNotSupported(#[primary_span] Span),
- #[label(ty_utils::pointer_not_supported)]
+ #[label(ty_utils_pointer_not_supported)]
PointerNotSupported(#[primary_span] Span),
- #[label(ty_utils::yield_not_supported)]
+ #[label(ty_utils_yield_not_supported)]
YieldNotSupported(#[primary_span] Span),
- #[label(ty_utils::loop_not_supported)]
+ #[label(ty_utils_loop_not_supported)]
LoopNotSupported(#[primary_span] Span),
- #[label(ty_utils::box_not_supported)]
+ #[label(ty_utils_box_not_supported)]
BoxNotSupported(#[primary_span] Span),
- #[label(ty_utils::binary_not_supported)]
+ #[label(ty_utils_binary_not_supported)]
BinaryNotSupported(#[primary_span] Span),
- #[label(ty_utils::logical_op_not_supported)]
+ #[label(ty_utils_logical_op_not_supported)]
LogicalOpNotSupported(#[primary_span] Span),
- #[label(ty_utils::assign_not_supported)]
+ #[label(ty_utils_assign_not_supported)]
AssignNotSupported(#[primary_span] Span),
- #[label(ty_utils::closure_and_return_not_supported)]
+ #[label(ty_utils_closure_and_return_not_supported)]
ClosureAndReturnNotSupported(#[primary_span] Span),
- #[label(ty_utils::control_flow_not_supported)]
+ #[label(ty_utils_control_flow_not_supported)]
ControlFlowNotSupported(#[primary_span] Span),
- #[label(ty_utils::inline_asm_not_supported)]
+ #[label(ty_utils_inline_asm_not_supported)]
InlineAsmNotSupported(#[primary_span] Span),
- #[label(ty_utils::operation_not_supported)]
+ #[label(ty_utils_operation_not_supported)]
OperationNotSupported(#[primary_span] Span),
}
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 05738b6c4..6436713b3 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -4,7 +4,7 @@ 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_span::{sym, DUMMY_SP};
+use rustc_span::sym;
use rustc_trait_selection::traits;
use traits::{translate_substs, Reveal};
@@ -134,19 +134,17 @@ fn resolve_associated_item<'tcx>(
.unwrap_or_else(|| {
bug!("{:?} not found in {:?}", trait_item_id, impl_data.impl_def_id);
});
-
- let substs = tcx.infer_ctxt().enter(|infcx| {
- let param_env = param_env.with_reveal_all_normalized(tcx);
- let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
- let substs = translate_substs(
- &infcx,
- param_env,
- impl_data.impl_def_id,
- substs,
- leaf_def.defining_node,
- );
- infcx.tcx.erase_regions(substs)
- });
+ let infcx = tcx.infer_ctxt().build();
+ let param_env = param_env.with_reveal_all_normalized(tcx);
+ let substs = rcvr_substs.rebase_onto(tcx, trait_def_id, impl_data.substs);
+ let substs = translate_substs(
+ &infcx,
+ param_env,
+ impl_data.impl_def_id,
+ substs,
+ leaf_def.defining_node,
+ );
+ let substs = infcx.tcx.erase_regions(substs);
// Since this is a trait item, we need to see if the item is either a trait default item
// or a specialization because we can't resolve those unless we can `Reveal::All`.
@@ -171,9 +169,13 @@ fn resolve_associated_item<'tcx>(
return Ok(None);
}
- // If the item does not have a value, then we cannot return an instance.
+ // Any final impl is required to define all associated items.
if !leaf_def.item.defaultness(tcx).has_value() {
- return Ok(None);
+ let guard = tcx.sess.delay_span_bug(
+ tcx.def_span(leaf_def.item.def_id),
+ "missing value for assoc item in impl",
+ );
+ return Err(guard);
}
let substs = tcx.erase_regions(substs);
@@ -182,40 +184,14 @@ fn resolve_associated_item<'tcx>(
// a `trait` to an associated `const` definition in an `impl`, where
// the definition in the `impl` has the wrong type (for which an
// error has already been/will be emitted elsewhere).
- //
- // NB: this may be expensive, we try to skip it in all the cases where
- // we know the error would've been caught (e.g. in an upstream crate).
- //
- // A better approach might be to just introduce a query (returning
- // `Result<(), ErrorGuaranteed>`) for the check that `rustc_typeck`
- // performs (i.e. that the definition's type in the `impl` matches
- // the declaration in the `trait`), so that we can cheaply check
- // here if it failed, instead of approximating it.
if leaf_def.item.kind == ty::AssocKind::Const
&& trait_item_id != leaf_def.item.def_id
- && leaf_def.item.def_id.is_local()
+ && let Some(leaf_def_item) = leaf_def.item.def_id.as_local()
{
- let normalized_type_of = |def_id, substs| {
- tcx.subst_and_normalize_erasing_regions(substs, param_env, tcx.type_of(def_id))
- };
-
- let original_ty = normalized_type_of(trait_item_id, rcvr_substs);
- let resolved_ty = normalized_type_of(leaf_def.item.def_id, substs);
-
- if original_ty != resolved_ty {
- let msg = format!(
- "Instance::resolve: inconsistent associated `const` type: \
- was `{}: {}` but resolved to `{}: {}`",
- tcx.def_path_str_with_substs(trait_item_id, rcvr_substs),
- original_ty,
- tcx.def_path_str_with_substs(leaf_def.item.def_id, substs),
- resolved_ty,
- );
- let span = tcx.def_span(leaf_def.item.def_id);
- let reported = tcx.sess.delay_span_bug(span, &msg);
-
- return Err(reported);
- }
+ tcx.compare_assoc_const_impl_item_with_trait_item((
+ leaf_def_item,
+ trait_item_id,
+ ))?;
}
Some(ty::Instance::new(leaf_def.item.def_id, substs))
@@ -260,7 +236,7 @@ fn resolve_associated_item<'tcx>(
if name == sym::clone {
let self_ty = trait_ref.self_ty();
- let is_copy = self_ty.is_copy_modulo_regions(tcx.at(DUMMY_SP), param_env);
+ let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
match self_ty.kind() {
_ if is_copy => (),
ty::Generator(..)
@@ -291,8 +267,7 @@ fn resolve_associated_item<'tcx>(
| traits::ImplSource::DiscriminantKind(..)
| traits::ImplSource::Pointee(..)
| traits::ImplSource::TraitUpcasting(_)
- | traits::ImplSource::ConstDestruct(_)
- | traits::ImplSource::Tuple => None,
+ | traits::ImplSource::ConstDestruct(_) => None,
})
}
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
new file mode 100644
index 000000000..52ba0eee9
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -0,0 +1,1803 @@
+use rustc_hir as hir;
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::mir::{GeneratorLayout, GeneratorSavedLocal};
+use rustc_middle::ty::layout::{
+ IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
+};
+use rustc_middle::ty::{
+ self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+};
+use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
+use rustc_span::symbol::Symbol;
+use rustc_span::DUMMY_SP;
+use rustc_target::abi::*;
+
+use std::cmp::{self, Ordering};
+use std::iter;
+use std::num::NonZeroUsize;
+use std::ops::Bound;
+
+use rand::{seq::SliceRandom, SeedableRng};
+use rand_xoshiro::Xoshiro128StarStar;
+
+use crate::layout_sanity_check::sanity_check_layout;
+
+pub fn provide(providers: &mut ty::query::Providers) {
+ *providers = ty::query::Providers { layout_of, ..*providers };
+}
+
+#[instrument(skip(tcx, query), level = "debug")]
+fn layout_of<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
+) -> Result<TyAndLayout<'tcx>, LayoutError<'tcx>> {
+ let (param_env, ty) = query.into_parts();
+ debug!(?ty);
+
+ let param_env = param_env.with_reveal_all_normalized(tcx);
+ let unnormalized_ty = ty;
+
+ // FIXME: We might want to have two different versions of `layout_of`:
+ // One that can be called after typecheck has completed and can use
+ // `normalize_erasing_regions` here and another one that can be called
+ // before typecheck has completed and uses `try_normalize_erasing_regions`.
+ let ty = match tcx.try_normalize_erasing_regions(param_env, ty) {
+ Ok(t) => t,
+ Err(normalization_error) => {
+ return Err(LayoutError::NormalizationFailure(ty, normalization_error));
+ }
+ };
+
+ if ty != unnormalized_ty {
+ // Ensure this layout is also cached for the normalized type.
+ return tcx.layout_of(param_env.and(ty));
+ }
+
+ let cx = LayoutCx { tcx, param_env };
+
+ let layout = layout_of_uncached(&cx, ty)?;
+ let layout = TyAndLayout { ty, layout };
+
+ record_layout_for_printing(&cx, layout);
+
+ sanity_check_layout(&cx, &layout);
+
+ Ok(layout)
+}
+
+#[derive(Copy, Clone, Debug)]
+enum StructKind {
+ /// A tuple, closure, or univariant which cannot be coerced to unsized.
+ AlwaysSized,
+ /// A univariant, the last field of which may be coerced to unsized.
+ MaybeUnsized,
+ /// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
+ Prefixed(Size, Align),
+}
+
+// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
+// This is used to go between `memory_index` (source field order to memory order)
+// and `inverse_memory_index` (memory order to source field order).
+// See also `FieldsShape::Arbitrary::memory_index` for more details.
+// FIXME(eddyb) build a better abstraction for permutations, if possible.
+fn invert_mapping(map: &[u32]) -> Vec<u32> {
+ let mut inverse = vec![0; map.len()];
+ for i in 0..map.len() {
+ inverse[map[i] as usize] = i as u32;
+ }
+ inverse
+}
+
+fn scalar_pair<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
+ let dl = cx.data_layout();
+ let b_align = b.align(dl);
+ let align = a.align(dl).max(b_align).max(dl.aggregate_align);
+ let b_offset = a.size(dl).align_to(b_align.abi);
+ let size = (b_offset + b.size(dl)).align_to(align.abi);
+
+ // HACK(nox): We iter on `b` and then `a` because `max_by_key`
+ // returns the last maximum.
+ let largest_niche = Niche::from_scalar(dl, b_offset, b)
+ .into_iter()
+ .chain(Niche::from_scalar(dl, Size::ZERO, a))
+ .max_by_key(|niche| niche.available(dl));
+
+ LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Arbitrary {
+ offsets: vec![Size::ZERO, b_offset],
+ memory_index: vec![0, 1],
+ },
+ abi: Abi::ScalarPair(a, b),
+ largest_niche,
+ align,
+ size,
+ }
+}
+
+fn univariant_uninterned<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ ty: Ty<'tcx>,
+ fields: &[TyAndLayout<'_>],
+ repr: &ReprOptions,
+ kind: StructKind,
+) -> Result<LayoutS<'tcx>, LayoutError<'tcx>> {
+ let dl = cx.data_layout();
+ let pack = repr.pack;
+ if pack.is_some() && repr.align.is_some() {
+ cx.tcx.sess.delay_span_bug(DUMMY_SP, "struct cannot be packed and aligned");
+ return Err(LayoutError::Unknown(ty));
+ }
+
+ let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+
+ let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
+
+ let optimize = !repr.inhibit_struct_field_reordering_opt();
+ if optimize {
+ let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
+ let optimizing = &mut inverse_memory_index[..end];
+ let field_align = |f: &TyAndLayout<'_>| {
+ if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
+ };
+
+ // If `-Z randomize-layout` was enabled for the type definition we can shuffle
+ // the field ordering to try and catch some code making assumptions about layouts
+ // we don't guarantee
+ if repr.can_randomize_type_layout() {
+ // `ReprOptions.layout_seed` is a deterministic seed that we can use to
+ // randomize field ordering with
+ let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
+
+ // Shuffle the ordering of the fields
+ optimizing.shuffle(&mut rng);
+
+ // Otherwise we just leave things alone and actually optimize the type's fields
+ } else {
+ match kind {
+ StructKind::AlwaysSized | StructKind::MaybeUnsized => {
+ optimizing.sort_by_key(|&x| {
+ // Place ZSTs first to avoid "interesting offsets",
+ // especially with only one or two non-ZST fields.
+ let f = &fields[x as usize];
+ (!f.is_zst(), cmp::Reverse(field_align(f)))
+ });
+ }
+
+ StructKind::Prefixed(..) => {
+ // Sort in ascending alignment so that the layout stays optimal
+ // regardless of the prefix
+ optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
+ }
+ }
+
+ // FIXME(Kixiron): We can always shuffle fields within a given alignment class
+ // regardless of the status of `-Z randomize-layout`
+ }
+ }
+
+ // inverse_memory_index holds field indices by increasing memory offset.
+ // That is, if field 5 has offset 0, the first element of inverse_memory_index is 5.
+ // We now write field offsets to the corresponding offset slot;
+ // field 5 with offset 0 puts 0 in offsets[5].
+ // At the bottom of this function, we invert `inverse_memory_index` to
+ // produce `memory_index` (see `invert_mapping`).
+
+ let mut sized = true;
+ let mut offsets = vec![Size::ZERO; fields.len()];
+ let mut offset = Size::ZERO;
+ let mut largest_niche = None;
+ let mut largest_niche_available = 0;
+
+ if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
+ let prefix_align =
+ if let Some(pack) = pack { prefix_align.min(pack) } else { prefix_align };
+ align = align.max(AbiAndPrefAlign::new(prefix_align));
+ offset = prefix_size.align_to(prefix_align);
+ }
+
+ for &i in &inverse_memory_index {
+ let field = fields[i as usize];
+ if !sized {
+ cx.tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ &format!(
+ "univariant: field #{} of `{}` comes after unsized field",
+ offsets.len(),
+ ty
+ ),
+ );
+ }
+
+ if field.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))
+ } else {
+ field.align
+ };
+ offset = offset.align_to(field_align.abi);
+ align = align.max(field_align);
+
+ debug!("univariant offset: {:?} field: {:#?}", offset, field);
+ offsets[i as usize] = offset;
+
+ if let Some(mut niche) = field.largest_niche {
+ let available = niche.available(dl);
+ if available > largest_niche_available {
+ largest_niche_available = available;
+ niche.offset += offset;
+ largest_niche = Some(niche);
+ }
+ }
+
+ offset = offset.checked_add(field.size, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+ }
+
+ if let Some(repr_align) = repr.align {
+ align = align.max(AbiAndPrefAlign::new(repr_align));
+ }
+
+ debug!("univariant min_size: {:?}", offset);
+ let min_size = offset;
+
+ // As stated above, inverse_memory_index holds field indices by increasing offset.
+ // This makes it an already-sorted view of the offsets vec.
+ // To invert it, consider:
+ // If field 5 has offset 0, offsets[0] is 5, and memory_index[5] should be 0.
+ // Field 5 would be the first element, so memory_index is i:
+ // Note: if we didn't optimize, it's already right.
+
+ let memory_index =
+ if optimize { invert_mapping(&inverse_memory_index) } else { inverse_memory_index };
+
+ let size = min_size.align_to(align.abi);
+ let mut abi = Abi::Aggregate { sized };
+
+ // 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());
+
+ 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 {
+ 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;
+ }
+ // But scalar pairs are Rust-specific and get
+ // treated as aggregates by C ABIs anyway.
+ Abi::ScalarPair(..) => {
+ abi = field.abi;
+ }
+ _ => {}
+ }
+ }
+ }
+
+ // Two non-ZST fields, and they're both scalars.
+ (Some((i, a)), Some((j, b)), None) => {
+ 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] {
+ ((i, a), (j, b))
+ } else {
+ ((j, b), (i, a))
+ };
+ let pair = scalar_pair(cx, a, b);
+ let pair_offsets = match pair.fields {
+ FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+ assert_eq!(memory_index, &[0, 1]);
+ offsets
+ }
+ _ => bug!(),
+ };
+ if offsets[i] == pair_offsets[0]
+ && offsets[j] == pair_offsets[1]
+ && align == pair.align
+ && size == pair.size
+ {
+ // We can use `ScalarPair` only when it matches our
+ // already computed layout (including `#[repr(C)]`).
+ abi = pair.abi;
+ }
+ }
+ _ => {}
+ }
+ }
+
+ _ => {}
+ }
+ }
+
+ if fields.iter().any(|f| f.abi.is_uninhabited()) {
+ abi = Abi::Uninhabited;
+ }
+
+ Ok(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Arbitrary { offsets, memory_index },
+ abi,
+ largest_niche,
+ align,
+ size,
+ })
+}
+
+fn layout_of_uncached<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ ty: Ty<'tcx>,
+) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+ let tcx = cx.tcx;
+ let param_env = cx.param_env;
+ let dl = cx.data_layout();
+ let scalar_unit = |value: Primitive| {
+ let size = value.size(dl);
+ 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 univariant = |fields: &[TyAndLayout<'_>], repr: &ReprOptions, kind| {
+ Ok(tcx.intern_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(
+ cx,
+ Scalar::Initialized {
+ value: Int(I8, false),
+ valid_range: WrappingRange { start: 0, end: 1 },
+ },
+ )),
+ ty::Char => tcx.intern_layout(LayoutS::scalar(
+ cx,
+ Scalar::Initialized {
+ value: Int(I32, false),
+ valid_range: WrappingRange { start: 0, end: 0x10FFFF },
+ },
+ )),
+ ty::Int(ity) => scalar(Int(Integer::from_int_ty(dl, ity), true)),
+ ty::Uint(ity) => scalar(Int(Integer::from_uint_ty(dl, ity), false)),
+ ty::Float(fty) => scalar(match fty {
+ ty::FloatTy::F32 => F32,
+ ty::FloatTy::F64 => F64,
+ }),
+ ty::FnPtr(_) => {
+ let mut ptr = scalar_unit(Pointer);
+ ptr.valid_range_mut().start = 1;
+ tcx.intern_layout(LayoutS::scalar(cx, ptr))
+ }
+
+ // The never type.
+ ty::Never => tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Primitive,
+ abi: Abi::Uninhabited,
+ largest_niche: None,
+ align: dl.i8_align,
+ size: Size::ZERO,
+ }),
+
+ // Potentially-wide pointers.
+ ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
+ let mut data_ptr = scalar_unit(Pointer);
+ 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)));
+ }
+
+ let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
+ let metadata = match unsized_part.kind() {
+ ty::Foreign(..) => {
+ return Ok(tcx.intern_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);
+ vtable.valid_range_mut().start = 1;
+ vtable
+ }
+ _ => return Err(LayoutError::Unknown(unsized_part)),
+ };
+
+ // Effectively a (ptr, meta) tuple.
+ tcx.intern_layout(scalar_pair(cx, data_ptr, metadata))
+ }
+
+ ty::Dynamic(_, _, ty::DynStar) => {
+ let mut data = scalar_unit(Int(dl.ptr_sized_integer(), false));
+ data.valid_range_mut().start = 0;
+ let mut vtable = scalar_unit(Pointer);
+ vtable.valid_range_mut().start = 1;
+ tcx.intern_layout(scalar_pair(cx, data, vtable))
+ }
+
+ // Arrays and slices.
+ ty::Array(element, mut count) => {
+ if count.has_projections() {
+ count = tcx.normalize_erasing_regions(param_env, count);
+ if count.has_projections() {
+ return Err(LayoutError::Unknown(ty));
+ }
+ }
+
+ let count = count.try_eval_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))?;
+
+ let abi = if count != 0 && tcx.conservative_is_privately_uninhabited(param_env.and(ty))
+ {
+ Abi::Uninhabited
+ } else {
+ Abi::Aggregate { sized: true }
+ };
+
+ let largest_niche = if count != 0 { element.largest_niche } else { None };
+
+ tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Array { stride: element.size, count },
+ abi,
+ largest_niche,
+ align: element.align,
+ size,
+ })
+ }
+ ty::Slice(element) => {
+ let element = cx.layout_of(element)?;
+ tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Array { stride: element.size, count: 0 },
+ abi: Abi::Aggregate { sized: false },
+ largest_niche: None,
+ align: element.align,
+ size: Size::ZERO,
+ })
+ }
+ ty::Str => tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 },
+ abi: Abi::Aggregate { sized: false },
+ largest_niche: None,
+ align: dl.i8_align,
+ size: Size::ZERO,
+ }),
+
+ // Odd unit types.
+ ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
+ ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => {
+ let mut unit = univariant_uninterned(
+ cx,
+ ty,
+ &[],
+ &ReprOptions::default(),
+ StructKind::AlwaysSized,
+ )?;
+ match unit.abi {
+ Abi::Aggregate { ref mut sized } => *sized = false,
+ _ => bug!(),
+ }
+ tcx.intern_layout(unit)
+ }
+
+ ty::Generator(def_id, substs, _) => generator_layout(cx, ty, def_id, substs)?,
+
+ ty::Closure(_, ref substs) => {
+ let tys = substs.as_closure().upvar_tys();
+ univariant(
+ &tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ &ReprOptions::default(),
+ StructKind::AlwaysSized,
+ )?
+ }
+
+ ty::Tuple(tys) => {
+ let kind =
+ if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized };
+
+ univariant(
+ &tys.iter().map(|k| cx.layout_of(k)).collect::<Result<Vec<_>, _>>()?,
+ &ReprOptions::default(),
+ kind,
+ )?
+ }
+
+ // SIMD vector types.
+ ty::Adt(def, substs) if def.repr().simd() => {
+ if !def.is_struct() {
+ // Should have yielded E0517 by now.
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ "#[repr(simd)] was applied to an ADT that is not a struct",
+ );
+ return Err(LayoutError::Unknown(ty));
+ }
+
+ // Supported SIMD vectors are homogeneous ADTs with at least one field:
+ //
+ // * #[repr(simd)] struct S(T, T, T, T);
+ // * #[repr(simd)] struct S { x: T, y: T, z: T, w: T }
+ // * #[repr(simd)] struct S([T; 4])
+ //
+ // where T is a primitive scalar (integer/float/pointer).
+
+ // SIMD vectors with zero fields are not supported.
+ // (should be caught by typeck)
+ if def.non_enum_variant().fields.is_empty() {
+ tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
+ }
+
+ // Type of the first ADT field:
+ let f0_ty = def.non_enum_variant().fields[0].ty(tcx, substs);
+
+ // Heterogeneous SIMD vectors are not supported:
+ // (should be caught by typeck)
+ for fi in &def.non_enum_variant().fields {
+ if fi.ty(tcx, substs) != f0_ty {
+ tcx.sess.fatal(&format!("monomorphising heterogeneous SIMD type `{}`", ty));
+ }
+ }
+
+ // The element type and number of elements of the SIMD vector
+ // are obtained from:
+ //
+ // * the element type and length of the single array field, if
+ // the first field is of array type, or
+ //
+ // * the homogeneous field type and the number of fields.
+ let (e_ty, e_len, is_array) = if let ty::Array(e_ty, _) = f0_ty.kind() {
+ // First ADT field is an array:
+
+ // SIMD vectors with multiple array fields are not supported:
+ // (should be caught by typeck)
+ if def.non_enum_variant().fields.len() != 1 {
+ tcx.sess.fatal(&format!(
+ "monomorphising SIMD type `{}` with more than one array field",
+ ty
+ ));
+ }
+
+ // Extract the number of elements from the layout of the array field:
+ let FieldsShape::Array { count, .. } = cx.layout_of(f0_ty)?.layout.fields() else {
+ return Err(LayoutError::Unknown(ty));
+ };
+
+ (*e_ty, *count, true)
+ } else {
+ // First ADT field is not an array:
+ (f0_ty, def.non_enum_variant().fields.len() as _, false)
+ };
+
+ // SIMD vectors of zero length are not supported.
+ // Additionally, lengths are capped at 2^16 as a fixed maximum backends must
+ // support.
+ //
+ // Can't be caught in typeck if the array length is generic.
+ if e_len == 0 {
+ tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
+ } else if e_len > MAX_SIMD_LANES {
+ tcx.sess.fatal(&format!(
+ "monomorphising SIMD type `{}` of length greater than {}",
+ ty, MAX_SIMD_LANES,
+ ));
+ }
+
+ // Compute the ABI of the element type:
+ let e_ly = cx.layout_of(e_ty)?;
+ let Abi::Scalar(e_abi) = e_ly.abi else {
+ // This error isn't caught in typeck, e.g., if
+ // the element type of the vector is generic.
+ tcx.sess.fatal(&format!(
+ "monomorphising SIMD type `{}` with a non-primitive-scalar \
+ (integer/float/pointer) element type `{}`",
+ ty, e_ty
+ ))
+ };
+
+ // Compute the size and alignment of the vector:
+ let size = e_ly.size.checked_mul(e_len, dl).ok_or(LayoutError::SizeOverflow(ty))?;
+ let align = dl.vector_align(size);
+ let size = size.align_to(align.abi);
+
+ // Compute the placement of the vector fields:
+ let fields = if is_array {
+ FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] }
+ } else {
+ FieldsShape::Array { stride: e_ly.size, count: e_len }
+ };
+
+ tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index: VariantIdx::new(0) },
+ fields,
+ abi: Abi::Vector { element: e_abi, count: e_len },
+ largest_niche: e_ly.largest_niche,
+ size,
+ align,
+ })
+ }
+
+ // ADTs.
+ ty::Adt(def, substs) => {
+ // Cache the field layouts.
+ let variants = def
+ .variants()
+ .iter()
+ .map(|v| {
+ v.fields
+ .iter()
+ .map(|field| cx.layout_of(field.ty(tcx, substs)))
+ .collect::<Result<Vec<_>, _>>()
+ })
+ .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+
+ if def.is_union() {
+ if def.repr().pack.is_some() && def.repr().align.is_some() {
+ cx.tcx.sess.delay_span_bug(
+ tcx.def_span(def.did()),
+ "union cannot be packed and aligned",
+ );
+ return Err(LayoutError::Unknown(ty));
+ }
+
+ let mut align =
+ if def.repr().pack.is_some() { dl.i8_align } else { dl.aggregate_align };
+
+ if let Some(repr_align) = def.repr().align {
+ align = align.max(AbiAndPrefAlign::new(repr_align));
+ }
+
+ let optimize = !def.repr().inhibit_union_abi_opt();
+ let mut size = Size::ZERO;
+ let mut abi = Abi::Aggregate { sized: true };
+ let index = VariantIdx::new(0);
+ for field in &variants[index] {
+ assert!(!field.is_unsized());
+ align = align.max(field.align);
+
+ // If all non-ZST fields have the same ABI, forward this ABI
+ if optimize && !field.is_zst() {
+ // Discard valid range information and allow undef
+ 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 } => {
+ Abi::Vector { element: x.to_union(), count }
+ }
+ Abi::Uninhabited | Abi::Aggregate { .. } => {
+ Abi::Aggregate { sized: true }
+ }
+ };
+
+ if size == Size::ZERO {
+ // first non ZST: initialize 'abi'
+ abi = field_abi;
+ } else if abi != field_abi {
+ // different fields have different ABI: reset to Aggregate
+ abi = Abi::Aggregate { sized: true };
+ }
+ }
+
+ size = cmp::max(size, field.size);
+ }
+
+ if let Some(pack) = def.repr().pack {
+ align = align.min(AbiAndPrefAlign::new(pack));
+ }
+
+ return Ok(tcx.intern_layout(LayoutS {
+ variants: Variants::Single { index },
+ fields: FieldsShape::Union(
+ NonZeroUsize::new(variants[index].len()).ok_or(LayoutError::Unknown(ty))?,
+ ),
+ abi,
+ largest_niche: None,
+ align,
+ size: size.align_to(align.abi),
+ }));
+ }
+
+ // A variant is absent if it's uninhabited and only has ZST fields.
+ // Present uninhabited variants only require space for their fields,
+ // 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: &[TyAndLayout<'_>]| {
+ let uninhabited = fields.iter().any(|f| f.abi.is_uninhabited());
+ let is_zst = fields.iter().all(|f| f.is_zst());
+ uninhabited && is_zst
+ };
+ let (present_first, present_second) = {
+ let mut present_variants = variants
+ .iter_enumerated()
+ .filter_map(|(i, v)| if absent(v) { None } else { Some(i) });
+ (present_variants.next(), present_variants.next())
+ };
+ let present_first = match present_first {
+ Some(present_first) => present_first,
+ // Uninhabited because it has no variants, or only absent ones.
+ None if def.is_enum() => {
+ return Ok(tcx.layout_of(param_env.and(tcx.types.never))?.layout);
+ }
+ // If it's a struct, still compute a layout so that we can still compute the
+ // field offsets.
+ None => VariantIdx::new(0),
+ };
+
+ let is_struct = !def.is_enum() ||
+ // Only one variant is present.
+ (present_second.is_none() &&
+ // Representation optimizations are allowed.
+ !def.repr().inhibit_enum_layout_opt());
+ if is_struct {
+ // Struct, or univariant enum equivalent to a struct.
+ // (Typechecking will reject discriminant-sizing attrs.)
+
+ let v = present_first;
+ let kind = if def.is_enum() || variants[v].is_empty() {
+ StructKind::AlwaysSized
+ } else {
+ let param_env = tcx.param_env(def.did());
+ let last_field = def.variant(v).fields.last().unwrap();
+ let always_sized = tcx.type_of(last_field.did).is_sized(tcx, param_env);
+ if !always_sized { StructKind::MaybeUnsized } else { StructKind::AlwaysSized }
+ };
+
+ let mut st = univariant_uninterned(cx, ty, &variants[v], &def.repr(), kind)?;
+ st.variants = Variants::Single { index: v };
+
+ if def.is_unsafe_cell() {
+ let hide_niches = |scalar: &mut _| match scalar {
+ Scalar::Initialized { value, valid_range } => {
+ *valid_range = WrappingRange::full(value.size(dl))
+ }
+ // Already doesn't have any niches
+ Scalar::Union { .. } => {}
+ };
+ match &mut st.abi {
+ Abi::Uninhabited => {}
+ Abi::Scalar(scalar) => hide_niches(scalar),
+ Abi::ScalarPair(a, b) => {
+ hide_niches(a);
+ hide_niches(b);
+ }
+ Abi::Vector { element, count: _ } => hide_niches(element),
+ Abi::Aggregate { sized: _ } => {}
+ }
+ st.largest_niche = None;
+ return Ok(tcx.intern_layout(st));
+ }
+
+ let (start, end) = cx.tcx.layout_scalar_valid_range(def.did());
+ match st.abi {
+ Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
+ // the asserts ensure that we are not using the
+ // `#[rustc_layout_scalar_valid_range(n)]`
+ // attribute to widen the range of anything as that would probably
+ // result in UB somewhere
+ // FIXME(eddyb) the asserts are probably not needed,
+ // as larger validity ranges would result in missed
+ // optimizations, *not* wrongly assuming the inner
+ // value is valid. e.g. unions enlarge validity ranges,
+ // because the values may be uninitialized.
+ if let Bound::Included(start) = start {
+ // FIXME(eddyb) this might be incorrect - it doesn't
+ // account for wrap-around (end < start) ranges.
+ let valid_range = scalar.valid_range_mut();
+ assert!(valid_range.start <= start);
+ valid_range.start = start;
+ }
+ if let Bound::Included(end) = end {
+ // FIXME(eddyb) this might be incorrect - it doesn't
+ // account for wrap-around (end < start) ranges.
+ let valid_range = scalar.valid_range_mut();
+ assert!(valid_range.end >= end);
+ valid_range.end = end;
+ }
+
+ // Update `largest_niche` if we have introduced a larger niche.
+ let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
+ if let Some(niche) = niche {
+ match st.largest_niche {
+ Some(largest_niche) => {
+ // Replace the existing niche even if they're equal,
+ // because this one is at a lower offset.
+ if largest_niche.available(dl) <= niche.available(dl) {
+ st.largest_niche = Some(niche);
+ }
+ }
+ None => st.largest_niche = Some(niche),
+ }
+ }
+ }
+ _ => assert!(
+ start == Bound::Unbounded && end == Bound::Unbounded,
+ "nonscalar layout for layout_scalar_valid_range type {:?}: {:#?}",
+ def,
+ st,
+ ),
+ }
+
+ return Ok(tcx.intern_layout(st));
+ }
+
+ // At this point, we have handled all unions and
+ // structs. (We have also handled univariant enums
+ // that allow representation optimization.)
+ assert!(def.is_enum());
+
+ // Until we've decided whether to use the tagged or
+ // niche filling LayoutS, we don't want to intern the
+ // 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<'tcx> {
+ layout: LayoutS<'tcx>,
+ variants: IndexVec<VariantIdx, LayoutS<'tcx>>,
+ }
+
+ let calculate_niche_filling_layout =
+ || -> Result<Option<TmpLayout<'tcx>>, LayoutError<'tcx>> {
+ // The current code for niche-filling relies on variant indices
+ // instead of actual discriminants, so enums with
+ // explicit discriminants (RFC #2363) would misbehave.
+ if def.repr().inhibit_enum_layout_opt()
+ || def
+ .variants()
+ .iter_enumerated()
+ .any(|(i, v)| v.discr != ty::VariantDiscr::Relative(i.as_u32()))
+ {
+ return Ok(None);
+ }
+
+ if variants.len() < 2 {
+ return Ok(None);
+ }
+
+ let mut align = dl.aggregate_align;
+ let mut variant_layouts = variants
+ .iter_enumerated()
+ .map(|(j, v)| {
+ let mut st = univariant_uninterned(
+ cx,
+ ty,
+ v,
+ &def.repr(),
+ StructKind::AlwaysSized,
+ )?;
+ st.variants = Variants::Single { index: j };
+
+ align = align.max(st.align);
+
+ Ok(st)
+ })
+ .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+
+ let largest_variant_index = match variant_layouts
+ .iter_enumerated()
+ .max_by_key(|(_i, layout)| layout.size.bytes())
+ .map(|(i, _layout)| i)
+ {
+ None => return Ok(None),
+ Some(i) => i,
+ };
+
+ let all_indices = VariantIdx::new(0)..=VariantIdx::new(variants.len() - 1);
+ let needs_disc = |index: VariantIdx| {
+ index != largest_variant_index && !absent(&variants[index])
+ };
+ let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap()
+ ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap();
+
+ let count = niche_variants.size_hint().1.unwrap() as u128;
+
+ // Find the field with the largest niche
+ let (field_index, niche, (niche_start, niche_scalar)) = match variants
+ [largest_variant_index]
+ .iter()
+ .enumerate()
+ .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(cx, count)?)))
+ {
+ None => return Ok(None),
+ Some(x) => x,
+ };
+
+ let niche_offset = niche.offset
+ + variant_layouts[largest_variant_index].fields.offset(field_index);
+ let niche_size = niche.value.size(dl);
+ let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
+
+ let all_variants_fit =
+ variant_layouts.iter_enumerated_mut().all(|(i, layout)| {
+ if i == largest_variant_index {
+ return true;
+ }
+
+ layout.largest_niche = None;
+
+ if layout.size <= niche_offset {
+ // This variant will fit before the niche.
+ return true;
+ }
+
+ // Determine if it'll fit after the niche.
+ let this_align = layout.align.abi;
+ let this_offset = (niche_offset + niche_size).align_to(this_align);
+
+ if this_offset + layout.size > size {
+ return false;
+ }
+
+ // It'll fit, but we need to make some adjustments.
+ match layout.fields {
+ FieldsShape::Arbitrary { ref mut offsets, .. } => {
+ for (j, offset) in offsets.iter_mut().enumerate() {
+ if !variants[i][j].is_zst() {
+ *offset += this_offset;
+ }
+ }
+ }
+ _ => {
+ panic!("Layout of fields should be Arbitrary for variants")
+ }
+ }
+
+ // It can't be a Scalar or ScalarPair because the offset isn't 0.
+ if !layout.abi.is_uninhabited() {
+ layout.abi = Abi::Aggregate { sized: true };
+ }
+ layout.size += this_offset;
+
+ true
+ });
+
+ if !all_variants_fit {
+ return Ok(None);
+ }
+
+ let largest_niche = Niche::from_scalar(dl, niche_offset, niche_scalar);
+
+ let others_zst = variant_layouts
+ .iter_enumerated()
+ .all(|(i, layout)| i == largest_variant_index || layout.size == Size::ZERO);
+ let same_size = size == variant_layouts[largest_variant_index].size;
+ let same_align = align == variant_layouts[largest_variant_index].align;
+
+ let abi = if variant_layouts.iter().all(|v| v.abi.is_uninhabited()) {
+ Abi::Uninhabited
+ } else if same_size && same_align && others_zst {
+ match variant_layouts[largest_variant_index].abi {
+ // When the total alignment and size match, we can use the
+ // same ABI as the scalar variant with the reserved niche.
+ Abi::Scalar(_) => Abi::Scalar(niche_scalar),
+ Abi::ScalarPair(first, second) => {
+ // Only the niche is guaranteed to be initialised,
+ // so use union layouts for the other primitive.
+ if niche_offset == Size::ZERO {
+ Abi::ScalarPair(niche_scalar, second.to_union())
+ } else {
+ Abi::ScalarPair(first.to_union(), niche_scalar)
+ }
+ }
+ _ => Abi::Aggregate { sized: true },
+ }
+ } else {
+ Abi::Aggregate { sized: true }
+ };
+
+ let layout = LayoutS {
+ variants: Variants::Multiple {
+ tag: niche_scalar,
+ tag_encoding: TagEncoding::Niche {
+ untagged_variant: largest_variant_index,
+ niche_variants,
+ niche_start,
+ },
+ tag_field: 0,
+ variants: IndexVec::new(),
+ },
+ fields: FieldsShape::Arbitrary {
+ offsets: vec![niche_offset],
+ memory_index: vec![0],
+ },
+ abi,
+ largest_niche,
+ size,
+ align,
+ };
+
+ Ok(Some(TmpLayout { layout, variants: variant_layouts }))
+ };
+
+ let niche_filling_layout = calculate_niche_filling_layout()?;
+
+ let (mut min, mut max) = (i128::MAX, i128::MIN);
+ let discr_type = def.repr().discr_type();
+ let bits = Integer::from_attr(cx, discr_type).size().bits();
+ for (i, discr) in def.discriminants(tcx) {
+ if variants[i].iter().any(|f| f.abi.is_uninhabited()) {
+ continue;
+ }
+ let mut x = discr.val as i128;
+ if discr_type.is_signed() {
+ // sign extend the raw representation to be an i128
+ x = (x << (128 - bits)) >> (128 - bits);
+ }
+ if x < min {
+ min = x;
+ }
+ if x > max {
+ max = x;
+ }
+ }
+ // We might have no inhabited variants, so pretend there's at least one.
+ if (min, max) == (i128::MAX, i128::MIN) {
+ min = 0;
+ max = 0;
+ }
+ assert!(min <= max, "discriminant range is {}...{}", min, max);
+ let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr(), min, max);
+
+ let mut align = dl.aggregate_align;
+ let mut size = Size::ZERO;
+
+ // We're interested in the smallest alignment, so start large.
+ let mut start_align = Align::from_bytes(256).unwrap();
+ assert_eq!(Integer::for_align(dl, start_align), None);
+
+ // repr(C) on an enum tells us to make a (tag, union) layout,
+ // so we need to grow the prefix alignment to be at least
+ // the alignment of the union. (This value is used both for
+ // determining the alignment of the overall enum, and the
+ // determining the alignment of the payload after the tag.)
+ let mut prefix_align = min_ity.align(dl).abi;
+ if def.repr().c() {
+ for fields in &variants {
+ for field in fields {
+ prefix_align = prefix_align.max(field.align.abi);
+ }
+ }
+ }
+
+ // Create the set of structs that represent each variant.
+ let mut layout_variants = variants
+ .iter_enumerated()
+ .map(|(i, field_layouts)| {
+ let mut st = univariant_uninterned(
+ cx,
+ ty,
+ &field_layouts,
+ &def.repr(),
+ StructKind::Prefixed(min_ity.size(), prefix_align),
+ )?;
+ st.variants = Variants::Single { index: i };
+ // 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);
+ break;
+ }
+ }
+ size = cmp::max(size, st.size);
+ align = align.max(st.align);
+ Ok(st)
+ })
+ .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+
+ // Align the maximum variant size to the largest alignment.
+ size = size.align_to(align.abi);
+
+ if size.bytes() >= dl.obj_size_bound() {
+ return Err(LayoutError::SizeOverflow(ty));
+ }
+
+ let typeck_ity = Integer::from_attr(dl, def.repr().discr_type());
+ if typeck_ity < min_ity {
+ // It is a bug if Layout decided on a greater discriminant size than typeck for
+ // some reason at this point (based on values discriminant can take on). Mostly
+ // because this discriminant will be loaded, and then stored into variable of
+ // type calculated by typeck. Consider such case (a bug): typeck decided on
+ // byte-sized discriminant, but layout thinks we need a 16-bit to store all
+ // discriminant values. That would be a bug, because then, in codegen, in order
+ // to store this 16-bit discriminant into 8-bit sized temporary some of the
+ // space necessary to represent would have to be discarded (or layout is wrong
+ // on thinking it needs 16 bits)
+ bug!(
+ "layout decided on a larger discriminant type ({:?}) than typeck ({:?})",
+ min_ity,
+ typeck_ity
+ );
+ // However, it is fine to make discr type however large (as an optimisation)
+ // after this point – we’ll just truncate the value we load in codegen.
+ }
+
+ // Check to see if we should use a different type for the
+ // discriminant. We can safely use a type with the same size
+ // as the alignment of the first field of each variant.
+ // We increase the size of the discriminant to avoid LLVM copying
+ // padding when it doesn't need to. This normally causes unaligned
+ // load/stores and excessive memcpy/memset operations. By using a
+ // bigger integer size, LLVM can be sure about its contents and
+ // won't be so conservative.
+
+ // Use the initial field alignment
+ let mut ity = if def.repr().c() || def.repr().int.is_some() {
+ min_ity
+ } else {
+ Integer::for_align(dl, start_align).unwrap_or(min_ity)
+ };
+
+ // If the alignment is not larger than the chosen discriminant size,
+ // don't use the alignment as the final size.
+ if ity <= min_ity {
+ ity = min_ity;
+ } else {
+ // Patch up the variants' first few fields.
+ let old_ity_size = min_ity.size();
+ let new_ity_size = ity.size();
+ for variant in &mut layout_variants {
+ match variant.fields {
+ FieldsShape::Arbitrary { ref mut offsets, .. } => {
+ for i in offsets {
+ if *i <= old_ity_size {
+ assert_eq!(*i, old_ity_size);
+ *i = new_ity_size;
+ }
+ }
+ // We might be making the struct larger.
+ if variant.size <= old_ity_size {
+ variant.size = new_ity_size;
+ }
+ }
+ _ => bug!(),
+ }
+ }
+ }
+
+ let tag_mask = ity.size().unsigned_int_max();
+ let tag = Scalar::Initialized {
+ value: Int(ity, signed),
+ valid_range: WrappingRange {
+ start: (min as u128 & tag_mask),
+ end: (max as u128 & tag_mask),
+ },
+ };
+ let mut abi = Abi::Aggregate { sized: true };
+
+ if layout_variants.iter().all(|v| v.abi.is_uninhabited()) {
+ abi = Abi::Uninhabited;
+ } else if tag.size(dl) == size {
+ // Make sure we only use scalar layout when the enum is entirely its
+ // own tag (i.e. it has no padding nor any non-ZST variant fields).
+ abi = Abi::Scalar(tag);
+ } else {
+ // Try to use a ScalarPair for all tagged enums.
+ let mut common_prim = None;
+ let mut common_prim_initialized_in_all_variants = true;
+ for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
+ let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
+ bug!();
+ };
+ let mut fields = iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
+ let (field, offset) = match (fields.next(), fields.next()) {
+ (None, None) => {
+ common_prim_initialized_in_all_variants = false;
+ continue;
+ }
+ (Some(pair), None) => pair,
+ _ => {
+ common_prim = None;
+ break;
+ }
+ };
+ let prim = match field.abi {
+ Abi::Scalar(scalar) => {
+ common_prim_initialized_in_all_variants &=
+ matches!(scalar, Scalar::Initialized { .. });
+ scalar.primitive()
+ }
+ _ => {
+ common_prim = None;
+ break;
+ }
+ };
+ if let Some(pair) = common_prim {
+ // This is pretty conservative. We could go fancier
+ // by conflating things like i32 and u32, or even
+ // realising that (u8, u8) could just cohabit with
+ // u16 or even u32.
+ if pair != (prim, offset) {
+ common_prim = None;
+ break;
+ }
+ } else {
+ common_prim = Some((prim, offset));
+ }
+ }
+ if let Some((prim, offset)) = common_prim {
+ let prim_scalar = if common_prim_initialized_in_all_variants {
+ scalar_unit(prim)
+ } else {
+ // Common prim might be uninit.
+ Scalar::Union { value: prim }
+ };
+ let pair = scalar_pair(cx, tag, prim_scalar);
+ let pair_offsets = match pair.fields {
+ FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
+ assert_eq!(memory_index, &[0, 1]);
+ offsets
+ }
+ _ => bug!(),
+ };
+ if pair_offsets[0] == Size::ZERO
+ && pair_offsets[1] == *offset
+ && align == pair.align
+ && size == pair.size
+ {
+ // We can use `ScalarPair` only when it matches our
+ // already computed layout (including `#[repr(C)]`).
+ abi = pair.abi;
+ }
+ }
+ }
+
+ // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
+ // variants to ensure they are consistent. This is because a downcast is
+ // semantically a NOP, and thus should not affect layout.
+ if matches!(abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
+ for variant in &mut layout_variants {
+ // We only do this for variants with fields; the others are not accessed anyway.
+ // Also do not overwrite any already existing "clever" ABIs.
+ if variant.fields.count() > 0 && matches!(variant.abi, Abi::Aggregate { .. }) {
+ variant.abi = abi;
+ // Also need to bump up the size and alignment, so that the entire value fits in here.
+ variant.size = cmp::max(variant.size, size);
+ variant.align.abi = cmp::max(variant.align.abi, align.abi);
+ }
+ }
+ }
+
+ let largest_niche = Niche::from_scalar(dl, Size::ZERO, tag);
+
+ let tagged_layout = LayoutS {
+ variants: Variants::Multiple {
+ tag,
+ tag_encoding: TagEncoding::Direct,
+ tag_field: 0,
+ variants: IndexVec::new(),
+ },
+ fields: FieldsShape::Arbitrary { offsets: vec![Size::ZERO], memory_index: vec![0] },
+ largest_niche,
+ abi,
+ align,
+ size,
+ };
+
+ let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
+
+ let mut best_layout = match (tagged_layout, niche_filling_layout) {
+ (tl, Some(nl)) => {
+ // Pick the smaller layout; otherwise,
+ // pick the layout with the larger niche; otherwise,
+ // pick tagged as it has simpler codegen.
+ use Ordering::*;
+ 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,
+ _ => tl,
+ }
+ }
+ (tl, None) => tl,
+ };
+
+ // Now we can intern the variant layouts and store them in the enum layout.
+ best_layout.layout.variants = match best_layout.layout.variants {
+ Variants::Multiple { tag, tag_encoding, tag_field, .. } => Variants::Multiple {
+ tag,
+ tag_encoding,
+ tag_field,
+ variants: best_layout
+ .variants
+ .into_iter()
+ .map(|layout| tcx.intern_layout(layout))
+ .collect(),
+ },
+ _ => bug!(),
+ };
+
+ tcx.intern_layout(best_layout.layout)
+ }
+
+ // Types with no meaningful known layout.
+ ty::Projection(_) | ty::Opaque(..) => {
+ // NOTE(eddyb) `layout_of` query should've normalized these away,
+ // if that was possible, so there's no reason to try again here.
+ return Err(LayoutError::Unknown(ty));
+ }
+
+ ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
+ bug!("Layout::compute: unexpected type `{}`", ty)
+ }
+
+ ty::Bound(..) | ty::Param(_) | ty::Error(_) => {
+ return Err(LayoutError::Unknown(ty));
+ }
+ })
+}
+
+/// Overlap eligibility and variant assignment for each GeneratorSavedLocal.
+#[derive(Clone, Debug, PartialEq)]
+enum SavedLocalEligibility {
+ Unassigned,
+ Assigned(VariantIdx),
+ // FIXME: Use newtype_index so we aren't wasting bytes
+ Ineligible(Option<u32>),
+}
+
+// When laying out generators, we divide our saved local fields into two
+// categories: overlap-eligible and overlap-ineligible.
+//
+// Those fields which are ineligible for overlap go in a "prefix" at the
+// beginning of the layout, and always have space reserved for them.
+//
+// Overlap-eligible fields are only assigned to one variant, so we lay
+// those fields out for each variant and put them right after the
+// prefix.
+//
+// Finally, in the layout details, we point to the fields from the
+// variants they are assigned to. It is possible for some fields to be
+// included in multiple variants. No field ever "moves around" in the
+// layout; its offset is always the same.
+//
+// Also included in the layout are the upvars and the discriminant.
+// These are included as fields on the "outer" layout; they are not part
+// of any variant.
+
+/// Compute the eligibility and assignment of each local.
+fn generator_saved_local_eligibility<'tcx>(
+ info: &GeneratorLayout<'tcx>,
+) -> (BitSet<GeneratorSavedLocal>, IndexVec<GeneratorSavedLocal, SavedLocalEligibility>) {
+ use SavedLocalEligibility::*;
+
+ let mut assignments: IndexVec<GeneratorSavedLocal, SavedLocalEligibility> =
+ IndexVec::from_elem_n(Unassigned, info.field_tys.len());
+
+ // The saved locals not eligible for overlap. These will get
+ // "promoted" to the prefix of our generator.
+ let mut ineligible_locals = BitSet::new_empty(info.field_tys.len());
+
+ // Figure out which of our saved locals are fields in only
+ // one variant. The rest are deemed ineligible for overlap.
+ for (variant_index, fields) in info.variant_fields.iter_enumerated() {
+ for local in fields {
+ match assignments[*local] {
+ Unassigned => {
+ assignments[*local] = Assigned(variant_index);
+ }
+ Assigned(idx) => {
+ // We've already seen this local at another suspension
+ // point, so it is no longer a candidate.
+ trace!(
+ "removing local {:?} in >1 variant ({:?}, {:?})",
+ local,
+ variant_index,
+ idx
+ );
+ ineligible_locals.insert(*local);
+ assignments[*local] = Ineligible(None);
+ }
+ Ineligible(_) => {}
+ }
+ }
+ }
+
+ // Next, check every pair of eligible locals to see if they
+ // conflict.
+ for local_a in info.storage_conflicts.rows() {
+ let conflicts_a = info.storage_conflicts.count(local_a);
+ if ineligible_locals.contains(local_a) {
+ continue;
+ }
+
+ for local_b in info.storage_conflicts.iter(local_a) {
+ // local_a and local_b are storage live at the same time, therefore they
+ // cannot overlap in the generator layout. The only way to guarantee
+ // this is if they are in the same variant, or one is ineligible
+ // (which means it is stored in every variant).
+ if ineligible_locals.contains(local_b) || assignments[local_a] == assignments[local_b] {
+ continue;
+ }
+
+ // If they conflict, we will choose one to make ineligible.
+ // This is not always optimal; it's just a greedy heuristic that
+ // seems to produce good results most of the time.
+ let conflicts_b = info.storage_conflicts.count(local_b);
+ let (remove, other) =
+ if conflicts_a > conflicts_b { (local_a, local_b) } else { (local_b, local_a) };
+ ineligible_locals.insert(remove);
+ assignments[remove] = Ineligible(None);
+ trace!("removing local {:?} due to conflict with {:?}", remove, other);
+ }
+ }
+
+ // Count the number of variants in use. If only one of them, then it is
+ // impossible to overlap any locals in our layout. In this case it's
+ // always better to make the remaining locals ineligible, so we can
+ // lay them out with the other locals in the prefix and eliminate
+ // unnecessary padding bytes.
+ {
+ let mut used_variants = BitSet::new_empty(info.variant_fields.len());
+ for assignment in &assignments {
+ if let Assigned(idx) = assignment {
+ used_variants.insert(*idx);
+ }
+ }
+ if used_variants.count() < 2 {
+ for assignment in assignments.iter_mut() {
+ *assignment = Ineligible(None);
+ }
+ ineligible_locals.insert_all();
+ }
+ }
+
+ // Write down the order of our locals that will be promoted to the prefix.
+ {
+ for (idx, local) in ineligible_locals.iter().enumerate() {
+ assignments[local] = Ineligible(Some(idx as u32));
+ }
+ }
+ debug!("generator saved local assignments: {:?}", assignments);
+
+ (ineligible_locals, assignments)
+}
+
+/// Compute the full generator layout.
+fn generator_layout<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ ty: Ty<'tcx>,
+ def_id: hir::def_id::DefId,
+ substs: SubstsRef<'tcx>,
+) -> Result<Layout<'tcx>, LayoutError<'tcx>> {
+ use SavedLocalEligibility::*;
+ let tcx = cx.tcx;
+ let subst_field = |ty: Ty<'tcx>| EarlyBinder(ty).subst(tcx, substs);
+
+ let Some(info) = tcx.generator_layout(def_id) else {
+ return Err(LayoutError::Unknown(ty));
+ };
+ let (ineligible_locals, assignments) = generator_saved_local_eligibility(&info);
+
+ // Build a prefix layout, including "promoting" all ineligible
+ // locals as part of the prefix. We compute the layout of all of
+ // these fields at once to get optimal packing.
+ let tag_index = substs.as_generator().prefix_tys().count();
+
+ // `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 promoted_layouts = ineligible_locals
+ .iter()
+ .map(|local| subst_field(info.field_tys[local]))
+ .map(|ty| tcx.mk_maybe_uninit(ty))
+ .map(|ty| cx.layout_of(ty));
+ let prefix_layouts = substs
+ .as_generator()
+ .prefix_tys()
+ .map(|ty| cx.layout_of(ty))
+ .chain(iter::once(Ok(tag_layout)))
+ .chain(promoted_layouts)
+ .collect::<Result<Vec<_>, _>>()?;
+ let prefix = univariant_uninterned(
+ cx,
+ ty,
+ &prefix_layouts,
+ &ReprOptions::default(),
+ StructKind::AlwaysSized,
+ )?;
+
+ let (prefix_size, prefix_align) = (prefix.size, prefix.align);
+
+ // Split the prefix layout into the "outer" fields (upvars and
+ // discriminant) and the "promoted" fields. Promoted fields will
+ // get included in each variant that requested them in
+ // GeneratorLayout.
+ debug!("prefix = {:#?}", prefix);
+ let (outer_fields, promoted_offsets, promoted_memory_index) = match prefix.fields {
+ FieldsShape::Arbitrary { mut offsets, memory_index } => {
+ let mut inverse_memory_index = invert_mapping(&memory_index);
+
+ // "a" (`0..b_start`) and "b" (`b_start..`) correspond to
+ // "outer" and "promoted" fields respectively.
+ let b_start = (tag_index + 1) as u32;
+ let offsets_b = offsets.split_off(b_start as usize);
+ let offsets_a = offsets;
+
+ // Disentangle the "a" and "b" components of `inverse_memory_index`
+ // by preserving the order but keeping only one disjoint "half" each.
+ // FIXME(eddyb) build a better abstraction for permutations, if possible.
+ let inverse_memory_index_b: Vec<_> =
+ inverse_memory_index.iter().filter_map(|&i| i.checked_sub(b_start)).collect();
+ inverse_memory_index.retain(|&i| i < b_start);
+ let inverse_memory_index_a = inverse_memory_index;
+
+ // Since `inverse_memory_index_{a,b}` each only refer to their
+ // respective fields, they can be safely inverted
+ let memory_index_a = invert_mapping(&inverse_memory_index_a);
+ let memory_index_b = invert_mapping(&inverse_memory_index_b);
+
+ let outer_fields =
+ FieldsShape::Arbitrary { offsets: offsets_a, memory_index: memory_index_a };
+ (outer_fields, offsets_b, memory_index_b)
+ }
+ _ => bug!(),
+ };
+
+ let mut size = prefix.size;
+ let mut align = prefix.align;
+ let variants = info
+ .variant_fields
+ .iter_enumerated()
+ .map(|(index, variant_fields)| {
+ // Only include overlap-eligible fields when we compute our variant layout.
+ let variant_only_tys = variant_fields
+ .iter()
+ .filter(|local| match assignments[**local] {
+ Unassigned => bug!(),
+ Assigned(v) if v == index => true,
+ Assigned(_) => bug!("assignment does not match variant"),
+ Ineligible(_) => false,
+ })
+ .map(|local| subst_field(info.field_tys[*local]));
+
+ let mut variant = univariant_uninterned(
+ cx,
+ ty,
+ &variant_only_tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+ &ReprOptions::default(),
+ StructKind::Prefixed(prefix_size, prefix_align.abi),
+ )?;
+ variant.variants = Variants::Single { index };
+
+ let FieldsShape::Arbitrary { offsets, memory_index } = variant.fields else {
+ bug!();
+ };
+
+ // Now, stitch the promoted and variant-only fields back together in
+ // the order they are mentioned by our GeneratorLayout.
+ // Because we only use some subset (that can differ between variants)
+ // of the promoted fields, we can't just pick those elements of the
+ // `promoted_memory_index` (as we'd end up with gaps).
+ // So instead, we build an "inverse memory_index", as if all of the
+ // promoted fields were being used, but leave the elements not in the
+ // subset as `INVALID_FIELD_IDX`, which we can filter out later to
+ // obtain a valid (bijective) mapping.
+ const INVALID_FIELD_IDX: u32 = !0;
+ let mut combined_inverse_memory_index =
+ vec![INVALID_FIELD_IDX; promoted_memory_index.len() + memory_index.len()];
+ let mut offsets_and_memory_index = iter::zip(offsets, memory_index);
+ let combined_offsets = variant_fields
+ .iter()
+ .enumerate()
+ .map(|(i, local)| {
+ let (offset, memory_index) = match assignments[*local] {
+ Unassigned => bug!(),
+ Assigned(_) => {
+ let (offset, memory_index) = offsets_and_memory_index.next().unwrap();
+ (offset, promoted_memory_index.len() as u32 + memory_index)
+ }
+ Ineligible(field_idx) => {
+ let field_idx = field_idx.unwrap() as usize;
+ (promoted_offsets[field_idx], promoted_memory_index[field_idx])
+ }
+ };
+ combined_inverse_memory_index[memory_index as usize] = i as u32;
+ offset
+ })
+ .collect();
+
+ // Remove the unused slots and invert the mapping to obtain the
+ // combined `memory_index` (also see previous comment).
+ combined_inverse_memory_index.retain(|&i| i != INVALID_FIELD_IDX);
+ let combined_memory_index = invert_mapping(&combined_inverse_memory_index);
+
+ variant.fields = FieldsShape::Arbitrary {
+ offsets: combined_offsets,
+ memory_index: combined_memory_index,
+ };
+
+ size = size.max(variant.size);
+ align = align.max(variant.align);
+ Ok(tcx.intern_layout(variant))
+ })
+ .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
+
+ size = size.align_to(align.abi);
+
+ let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) {
+ Abi::Uninhabited
+ } else {
+ Abi::Aggregate { sized: true }
+ };
+
+ let layout = tcx.intern_layout(LayoutS {
+ variants: Variants::Multiple {
+ tag,
+ tag_encoding: TagEncoding::Direct,
+ tag_field: tag_index,
+ variants,
+ },
+ fields: outer_fields,
+ abi,
+ largest_niche: prefix.largest_niche,
+ size,
+ align,
+ });
+ debug!("generator layout ({:?}): {:#?}", ty, layout);
+ Ok(layout)
+}
+
+/// This is invoked by the `layout_of` query to record the final
+/// layout of each type.
+#[inline(always)]
+fn record_layout_for_printing<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, layout: TyAndLayout<'tcx>) {
+ // If we are running with `-Zprint-type-sizes`, maybe record layouts
+ // for dumping later.
+ if cx.tcx.sess.opts.unstable_opts.print_type_sizes {
+ record_layout_for_printing_outlined(cx, layout)
+ }
+}
+
+fn record_layout_for_printing_outlined<'tcx>(
+ cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+ layout: TyAndLayout<'tcx>,
+) {
+ // Ignore layouts that are done with non-empty environments or
+ // non-monomorphic layouts, as the user only wants to see the stuff
+ // resulting from the final codegen session.
+ if layout.ty.has_non_region_param() || !cx.param_env.caller_bounds().is_empty() {
+ return;
+ }
+
+ // (delay format until we actually need it)
+ let record = |kind, packed, opt_discr_size, variants| {
+ let type_desc = format!("{:?}", layout.ty);
+ cx.tcx.sess.code_stats.record_type_size(
+ kind,
+ type_desc,
+ layout.align.abi,
+ layout.size,
+ packed,
+ opt_discr_size,
+ variants,
+ );
+ };
+
+ let adt_def = match *layout.ty.kind() {
+ ty::Adt(ref adt_def, _) => {
+ debug!("print-type-size t: `{:?}` process adt", layout.ty);
+ adt_def
+ }
+
+ ty::Closure(..) => {
+ debug!("print-type-size t: `{:?}` record closure", layout.ty);
+ record(DataTypeKind::Closure, false, None, vec![]);
+ return;
+ }
+
+ _ => {
+ debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
+ return;
+ }
+ };
+
+ let adt_kind = adt_def.adt_kind();
+ let adt_packed = adt_def.repr().pack.is_some();
+
+ let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
+ let mut min_size = Size::ZERO;
+ let field_info: Vec<_> = flds
+ .iter()
+ .enumerate()
+ .map(|(i, &name)| {
+ let field_layout = layout.field(cx, i);
+ let offset = layout.fields.offset(i);
+ let field_end = offset + field_layout.size;
+ if min_size < field_end {
+ min_size = field_end;
+ }
+ FieldInfo {
+ name,
+ offset: offset.bytes(),
+ size: field_layout.size.bytes(),
+ align: field_layout.align.abi.bytes(),
+ }
+ })
+ .collect();
+
+ VariantInfo {
+ name: n,
+ kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact },
+ align: layout.align.abi.bytes(),
+ size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() },
+ fields: field_info,
+ }
+ };
+
+ match layout.variants {
+ Variants::Single { index } => {
+ if !adt_def.variants().is_empty() && layout.fields != FieldsShape::Primitive {
+ debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
+ let variant_def = &adt_def.variant(index);
+ let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
+ record(
+ adt_kind.into(),
+ adt_packed,
+ None,
+ vec![build_variant_info(Some(variant_def.name), &fields, layout)],
+ );
+ } else {
+ // (This case arises for *empty* enums; so give it
+ // zero variants.)
+ record(adt_kind.into(), adt_packed, None, vec![]);
+ }
+ }
+
+ Variants::Multiple { tag, ref tag_encoding, .. } => {
+ debug!(
+ "print-type-size `{:#?}` adt general variants def {}",
+ layout.ty,
+ adt_def.variants().len()
+ );
+ let variant_infos: Vec<_> = adt_def
+ .variants()
+ .iter_enumerated()
+ .map(|(i, variant_def)| {
+ let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
+ build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
+ })
+ .collect();
+ record(
+ adt_kind.into(),
+ adt_packed,
+ match tag_encoding {
+ TagEncoding::Direct => Some(tag.size(cx)),
+ _ => None,
+ },
+ variant_infos,
+ );
+ }
+ }
+}
diff --git a/compiler/rustc_middle/src/ty/layout_sanity_check.rs b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
index 87c85dcff..100926ad4 100644
--- a/compiler/rustc_middle/src/ty/layout_sanity_check.rs
+++ b/compiler/rustc_ty_utils/src/layout_sanity_check.rs
@@ -1,4 +1,4 @@
-use crate::ty::{
+use rustc_middle::ty::{
layout::{LayoutCx, TyAndLayout},
TyCtxt,
};
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 8524e57cb..cce5a79dd 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -5,13 +5,11 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
+#![feature(let_chains)]
#![feature(control_flow_enum)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(never_type)]
#![feature(box_patterns)]
#![recursion_limit = "256"]
-#![deny(rustc::untranslatable_diagnostic)]
-#![deny(rustc::diagnostic_outside_of_impl)]
#[macro_use]
extern crate rustc_middle;
@@ -20,22 +18,28 @@ extern crate tracing;
use rustc_middle::ty::query::Providers;
+mod abi;
mod assoc;
mod common_traits;
mod consts;
mod errors;
mod implied_bounds;
pub mod instance;
+mod layout;
+mod layout_sanity_check;
mod needs_drop;
pub mod representability;
mod ty;
pub fn provide(providers: &mut Providers) {
+ abi::provide(providers);
assoc::provide(providers);
common_traits::provide(providers);
consts::provide(providers);
implied_bounds::provide(providers);
+ layout::provide(providers);
needs_drop::provide(providers);
+ representability::provide(providers);
ty::provide(providers);
instance::provide(providers);
}
diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs
index ab5a3d8ae..024dcd591 100644
--- a/compiler/rustc_ty_utils/src/needs_drop.rs
+++ b/compiler/rustc_ty_utils/src/needs_drop.rs
@@ -2,7 +2,6 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
@@ -110,7 +109,7 @@ where
for component in components {
match *component.kind() {
- _ if component.is_copy_modulo_regions(tcx.at(DUMMY_SP), self.param_env) => (),
+ _ if component.is_copy_modulo_regions(tcx, self.param_env) => (),
ty::Closure(_, substs) => {
queue_type(self, substs.as_closure().tupled_upvars_ty());
@@ -265,7 +264,7 @@ fn adt_consider_insignificant_dtor<'tcx>(
if is_marked_insig {
// In some cases like `std::collections::HashMap` where the struct is a wrapper around
// a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies
- // outside stdlib, we might choose to still annotate the the wrapper (std HashMap) with
+ // outside stdlib, we might choose to still annotate the wrapper (std HashMap) with
// `rustc_insignificant_dtor`, even if the type itself doesn't have a `Drop` impl.
Some(DtorType::Insignificant)
} else if adt_def.destructor(tcx).is_some() {
diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs
index eded78916..7f48fb804 100644
--- a/compiler/rustc_ty_utils/src/representability.rs
+++ b/compiler/rustc_ty_utils/src/representability.rs
@@ -1,386 +1,119 @@
-//! Check whether a type is representable.
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir as hir;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_span::Span;
-use std::cmp;
+#![allow(rustc::untranslatable_diagnostic, rustc::diagnostic_outside_of_impl)]
-/// Describes whether a type is representable. For types that are not
-/// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
-/// distinguish between types that are recursive with themselves and types that
-/// contain a different recursive type. These cases can therefore be treated
-/// differently when reporting errors.
-///
-/// The ordering of the cases is significant. They are sorted so that cmp::max
-/// will keep the "more erroneous" of two values.
-#[derive(Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
-pub enum Representability {
- Representable,
- ContainsRecursive,
- /// Return a list of types that are included in themselves:
- /// the spans where they are self-included, and (if found)
- /// the HirId of the FieldDef that defines the self-inclusion.
- SelfRecursive(Vec<(Span, Option<hir::HirId>)>),
-}
+use rustc_hir::def::DefKind;
+use rustc_index::bit_set::BitSet;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self, Representability, Ty, TyCtxt};
+use rustc_span::def_id::{DefId, LocalDefId};
-/// Check whether a type is representable. This means it cannot contain unboxed
-/// structural recursion. This check is needed for structs and enums.
-pub fn ty_is_representable<'tcx>(
- tcx: TyCtxt<'tcx>,
- ty: Ty<'tcx>,
- sp: Span,
- field_id: Option<hir::HirId>,
-) -> Representability {
- debug!("is_type_representable: {:?}", ty);
- // To avoid a stack overflow when checking an enum variant or struct that
- // contains a different, structurally recursive type, maintain a stack of
- // seen types and check recursion for each of them (issues #3008, #3779,
- // #74224, #84611). `shadow_seen` contains the full stack and `seen` only
- // the one for the current type (e.g. if we have structs A and B, B contains
- // a field of type A, and we're currently looking at B, then `seen` will be
- // cleared when recursing to check A, but `shadow_seen` won't, so that we
- // can catch cases of mutual recursion where A also contains B).
- let mut seen: Vec<Ty<'_>> = Vec::new();
- let mut shadow_seen: Vec<ty::AdtDef<'tcx>> = Vec::new();
- let mut representable_cache = FxHashMap::default();
- let mut force_result = false;
- let r = is_type_structurally_recursive(
- tcx,
- &mut seen,
- &mut shadow_seen,
- &mut representable_cache,
- ty,
- sp,
- field_id,
- &mut force_result,
- );
- debug!("is_type_representable: {:?} is {:?}", ty, r);
- r
+pub fn provide(providers: &mut Providers) {
+ *providers =
+ Providers { representability, representability_adt_ty, params_in_repr, ..*providers };
}
-// Iterate until something non-representable is found
-fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representability {
- iter.fold(Representability::Representable, |r1, r2| match (r1, r2) {
- (Representability::SelfRecursive(v1), Representability::SelfRecursive(v2)) => {
- Representability::SelfRecursive(v1.into_iter().chain(v2).collect())
+macro_rules! rtry {
+ ($e:expr) => {
+ match $e {
+ e @ Representability::Infinite => return e,
+ Representability::Representable => {}
}
- (r1, r2) => cmp::max(r1, r2),
- })
+ };
}
-fn are_inner_types_recursive<'tcx>(
- tcx: TyCtxt<'tcx>,
- seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
- representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
- ty: Ty<'tcx>,
- sp: Span,
- field_id: Option<hir::HirId>,
- force_result: &mut bool,
-) -> Representability {
- debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen);
- match ty.kind() {
- ty::Tuple(fields) => {
- // Find non representable
- fold_repr(fields.iter().map(|ty| {
- is_type_structurally_recursive(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- ty,
- sp,
- field_id,
- force_result,
- )
- }))
- }
- // Fixed-length vectors.
- // FIXME(#11924) Behavior undecided for zero-length vectors.
- ty::Array(ty, _) => is_type_structurally_recursive(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- *ty,
- sp,
- field_id,
- force_result,
- ),
- ty::Adt(def, substs) => {
- // Find non representable fields with their spans
- fold_repr(def.all_fields().map(|field| {
- let ty = field.ty(tcx, substs);
- let (sp, field_id) = match field
- .did
- .as_local()
- .map(|id| tcx.hir().local_def_id_to_hir_id(id))
- .and_then(|id| tcx.hir().find(id))
- {
- Some(hir::Node::Field(field)) => (field.ty.span, Some(field.hir_id)),
- _ => (sp, field_id),
- };
-
- let mut result = None;
-
- // First, we check whether the field type per se is representable.
- // This catches cases as in #74224 and #84611. There is a special
- // case related to mutual recursion, though; consider this example:
- //
- // struct A<T> {
- // z: T,
- // x: B<T>,
- // }
- //
- // struct B<T> {
- // y: A<T>
- // }
- //
- // Here, without the following special case, both A and B are
- // ContainsRecursive, which is a problem because we only report
- // errors for SelfRecursive. We fix this by detecting this special
- // case (shadow_seen.first() is the type we are originally
- // interested in, and if we ever encounter the same AdtDef again,
- // we know that it must be SelfRecursive) and "forcibly" returning
- // SelfRecursive (by setting force_result, which tells the calling
- // invocations of are_inner_types_representable to forward the
- // result without adjusting).
- if shadow_seen.len() > seen.len() && shadow_seen.first() == Some(def) {
- *force_result = true;
- result = Some(Representability::SelfRecursive(vec![(sp, field_id)]));
- }
-
- if result == None {
- result = Some(Representability::Representable);
-
- // Now, we check whether the field types per se are representable, e.g.
- // for struct Foo { x: Option<Foo> }, we first check whether Option<_>
- // by itself is representable (which it is), and the nesting of Foo
- // will be detected later. This is necessary for #74224 and #84611.
-
- // If we have encountered an ADT definition that we have not seen
- // before (no need to check them twice), recurse to see whether that
- // definition is SelfRecursive. If so, we must be ContainsRecursive.
- if shadow_seen.len() > 1
- && !shadow_seen
- .iter()
- .take(shadow_seen.len() - 1)
- .any(|seen_def| seen_def == def)
- {
- let adt_def_id = def.did();
- let raw_adt_ty = tcx.type_of(adt_def_id);
- debug!("are_inner_types_recursive: checking nested type: {:?}", raw_adt_ty);
-
- // Check independently whether the ADT is SelfRecursive. If so,
- // we must be ContainsRecursive (except for the special case
- // mentioned above).
- let mut nested_seen: Vec<Ty<'_>> = vec![];
- result = Some(
- match is_type_structurally_recursive(
- tcx,
- &mut nested_seen,
- shadow_seen,
- representable_cache,
- raw_adt_ty,
- sp,
- field_id,
- force_result,
- ) {
- Representability::SelfRecursive(_) => {
- if *force_result {
- Representability::SelfRecursive(vec![(sp, field_id)])
- } else {
- Representability::ContainsRecursive
- }
- }
- x => x,
- },
- );
- }
-
- // We only enter the following block if the type looks representable
- // so far. This is necessary for cases such as this one (#74224):
- //
- // struct A<T> {
- // x: T,
- // y: A<A<T>>,
- // }
- //
- // struct B {
- // z: A<usize>
- // }
- //
- // When checking B, we recurse into A and check field y of type
- // A<A<usize>>. We haven't seen this exact type before, so we recurse
- // into A<A<usize>>, which contains, A<A<A<usize>>>, and so forth,
- // ad infinitum. We can prevent this from happening by first checking
- // A separately (the code above) and only checking for nested Bs if
- // A actually looks representable (which it wouldn't in this example).
- if result == Some(Representability::Representable) {
- // Now, even if the type is representable (e.g. Option<_>),
- // it might still contribute to a recursive type, e.g.:
- // struct Foo { x: Option<Option<Foo>> }
- // These cases are handled by passing the full `seen`
- // stack to is_type_structurally_recursive (instead of the
- // empty `nested_seen` above):
- result = Some(
- match is_type_structurally_recursive(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- ty,
- sp,
- field_id,
- force_result,
- ) {
- Representability::SelfRecursive(_) => {
- Representability::SelfRecursive(vec![(sp, field_id)])
- }
- x => x,
- },
- );
- }
+fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability {
+ match tcx.def_kind(def_id) {
+ DefKind::Struct | DefKind::Union | DefKind::Enum => {
+ let adt_def = tcx.adt_def(def_id);
+ for variant in adt_def.variants() {
+ for field in variant.fields.iter() {
+ rtry!(tcx.representability(field.did.expect_local()));
}
-
- result.unwrap()
- }))
- }
- ty::Closure(..) => {
- // this check is run on type definitions, so we don't expect
- // to see closure types
- bug!("requires check invoked on inapplicable type: {:?}", ty)
+ }
+ Representability::Representable
}
- _ => Representability::Representable,
+ DefKind::Field => representability_ty(tcx, tcx.type_of(def_id)),
+ def_kind => bug!("unexpected {def_kind:?}"),
}
}
-fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool {
+fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
match *ty.kind() {
- ty::Adt(ty_def, _) => ty_def == def,
- _ => false,
+ ty::Adt(..) => tcx.representability_adt_ty(ty),
+ // FIXME(#11924) allow zero-length arrays?
+ ty::Array(ty, _) => representability_ty(tcx, ty),
+ ty::Tuple(tys) => {
+ for ty in tys {
+ rtry!(representability_ty(tcx, ty));
+ }
+ Representability::Representable
+ }
+ _ => Representability::Representable,
}
}
-// Does the type `ty` directly (without indirection through a pointer)
-// contain any types on stack `seen`?
-fn is_type_structurally_recursive<'tcx>(
- tcx: TyCtxt<'tcx>,
- seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
- representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
- ty: Ty<'tcx>,
- sp: Span,
- field_id: Option<hir::HirId>,
- force_result: &mut bool,
-) -> Representability {
- debug!("is_type_structurally_recursive: {:?} {:?} {:?}", ty, sp, field_id);
- if let Some(representability) = representable_cache.get(&ty) {
- debug!(
- "is_type_structurally_recursive: {:?} {:?} {:?} - (cached) {:?}",
- ty, sp, field_id, representability
- );
- return representability.clone();
+/*
+The reason for this being a separate query is very subtle:
+Consider this infinitely sized struct: `struct Foo(Box<Foo>, Bar<Foo>)`:
+When calling representability(Foo), a query cycle will occur:
+ representability(Foo)
+ -> representability_adt_ty(Bar<Foo>)
+ -> representability(Foo)
+For the diagnostic output (in `Value::from_cycle_error`), we want to detect that
+the `Foo` in the *second* field of the struct is culpable. This requires
+traversing the HIR of the struct and calling `params_in_repr(Bar)`. But we can't
+call params_in_repr for a given type unless it is known to be representable.
+params_in_repr will cycle/panic on infinitely sized types. Looking at the query
+cycle above, we know that `Bar` is representable because
+representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is
+*not* in the cycle.
+*/
+fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability {
+ let ty::Adt(adt, substs) = ty.kind() else { bug!("expected adt") };
+ if let Some(def_id) = adt.did().as_local() {
+ rtry!(tcx.representability(def_id));
}
-
- let representability = is_type_structurally_recursive_inner(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- ty,
- sp,
- field_id,
- force_result,
- );
-
- representable_cache.insert(ty, representability.clone());
- representability
+ // At this point, we know that the item of the ADT type is representable;
+ // but the type parameters may cause a cycle with an upstream type
+ let params_in_repr = tcx.params_in_repr(adt.did());
+ for (i, subst) in substs.iter().enumerate() {
+ if let ty::GenericArgKind::Type(ty) = subst.unpack() {
+ if params_in_repr.contains(i as u32) {
+ rtry!(representability_ty(tcx, ty));
+ }
+ }
+ }
+ Representability::Representable
}
-fn is_type_structurally_recursive_inner<'tcx>(
- tcx: TyCtxt<'tcx>,
- seen: &mut Vec<Ty<'tcx>>,
- shadow_seen: &mut Vec<ty::AdtDef<'tcx>>,
- representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>,
- ty: Ty<'tcx>,
- sp: Span,
- field_id: Option<hir::HirId>,
- force_result: &mut bool,
-) -> Representability {
- match ty.kind() {
- ty::Adt(def, _) => {
- {
- debug!("is_type_structurally_recursive_inner: adt: {:?}, seen: {:?}", ty, seen);
-
- // Iterate through stack of previously seen types.
- let mut iter = seen.iter();
-
- // The first item in `seen` is the type we are actually curious about.
- // We want to return SelfRecursive if this type contains itself.
- // It is important that we DON'T take generic parameters into account
- // for this check, so that Bar<T> in this example counts as SelfRecursive:
- //
- // struct Foo;
- // struct Bar<T> { x: Bar<Foo> }
-
- if let Some(&seen_adt) = iter.next() {
- if same_adt(seen_adt, *def) {
- debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty);
- return Representability::SelfRecursive(vec![(sp, field_id)]);
- }
- }
-
- // We also need to know whether the first item contains other types
- // that are structurally recursive. If we don't catch this case, we
- // will recurse infinitely for some inputs.
- //
- // It is important that we DO take generic parameters into account
- // here, because nesting e.g. Options is allowed (as long as the
- // definition of Option doesn't itself include an Option field, which
- // would be a case of SelfRecursive above). The following, too, counts
- // as SelfRecursive:
- //
- // struct Foo { Option<Option<Foo>> }
+fn params_in_repr(tcx: TyCtxt<'_>, def_id: DefId) -> BitSet<u32> {
+ let adt_def = tcx.adt_def(def_id);
+ let generics = tcx.generics_of(def_id);
+ 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
+}
- for &seen_adt in iter {
- if ty == seen_adt {
- debug!("ContainsRecursive: {:?} contains {:?}", seen_adt, ty);
- return Representability::ContainsRecursive;
+fn params_in_repr_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, params_in_repr: &mut BitSet<u32>) {
+ match *ty.kind() {
+ ty::Adt(adt, substs) => {
+ let inner_params_in_repr = tcx.params_in_repr(adt.did());
+ for (i, subst) in substs.iter().enumerate() {
+ if let ty::GenericArgKind::Type(ty) = subst.unpack() {
+ if inner_params_in_repr.contains(i as u32) {
+ params_in_repr_ty(tcx, ty, params_in_repr);
}
}
}
-
- // For structs and enums, track all previously seen types by pushing them
- // onto the 'seen' stack.
- seen.push(ty);
- shadow_seen.push(*def);
- let out = are_inner_types_recursive(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- ty,
- sp,
- field_id,
- force_result,
- );
- shadow_seen.pop();
- seen.pop();
- out
}
- _ => {
- // No need to push in other cases.
- are_inner_types_recursive(
- tcx,
- seen,
- shadow_seen,
- representable_cache,
- ty,
- sp,
- field_id,
- force_result,
- )
+ ty::Array(ty, _) => params_in_repr_ty(tcx, ty, params_in_repr),
+ ty::Tuple(tys) => tys.iter().for_each(|ty| params_in_repr_ty(tcx, ty, params_in_repr)),
+ ty::Param(param) => {
+ params_in_repr.insert(param.index);
}
+ _ => {}
}
}
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 9266e4e3f..3eebb4ace 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -1,7 +1,6 @@
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
use rustc_trait_selection::traits;
@@ -86,9 +85,13 @@ fn impl_defaultness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Defaultness {
/// - a type parameter or projection whose Sizedness can't be known
/// - a tuple of type parameters or projections, if there are multiple
/// such.
-/// - an Error, if a type contained itself. The representability
-/// check should catch this case.
-fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstraint<'_> {
+/// - an Error, if a type is infinitely sized
+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()]);
+ }
+ }
let def = tcx.adt_def(def_id);
let result = tcx.mk_type_list(
@@ -100,7 +103,7 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AdtSizedConstrain
debug!("adt_sized_constraint: {:?} => {:?}", def, result);
- ty::AdtSizedConstraint(result)
+ result
}
/// See `ParamEnv` struct definition for details.
@@ -134,6 +137,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
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));
+ // FIXME(consts): This is not exactly in line with the constness query.
let constness = match hir_id {
Some(hir_id) => match tcx.hir().get(hir_id) {
hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
@@ -162,7 +166,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
}) => hir::Constness::Const,
hir::Node::ImplItem(hir::ImplItem {
- kind: hir::ImplItemKind::TyAlias(..) | hir::ImplItemKind::Fn(..),
+ kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
..
}) => {
let parent_hir_id = tcx.hir().get_parent_node(hir_id);
@@ -198,6 +202,10 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
_ => hir::Constness::NotConst,
},
+ // FIXME(consts): It's suspicious that a param-env for a foreign item
+ // will always have NotConst param-env, though we don't typically use
+ // that param-env for anything meaningful right now, so it's likely
+ // not an issue.
None => hir::Constness::NotConst,
};
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 5aa3cf017..c4008e9b6 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021"
[lib]
-doctest = false
[dependencies]
bitflags = "1.2.1"
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index da30344ef..7fbe78aa5 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -675,9 +675,9 @@ impl<CTX> HashStable<CTX> for InferTy {
use InferTy::*;
discriminant(self).hash_stable(ctx, hasher);
match self {
- TyVar(v) => v.as_u32().hash_stable(ctx, hasher),
- IntVar(v) => v.index.hash_stable(ctx, hasher),
- FloatVar(v) => v.index.hash_stable(ctx, hasher),
+ TyVar(_) | IntVar(_) | FloatVar(_) => {
+ panic!("type variables should not be hashed: {self:?}")
+ }
FreshTy(v) | FreshIntTy(v) | FreshFloatTy(v) => v.hash_stable(ctx, hasher),
}
}
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 6d54924e5..a4fb1480f 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -1332,8 +1332,8 @@ where
RePlaceholder(p) => {
p.hash_stable(hcx, hasher);
}
- ReVar(reg) => {
- reg.hash_stable(hcx, hasher);
+ ReVar(_) => {
+ panic!("region variables should not be hashed: {self:?}")
}
}
}
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
deleted file mode 100644
index d08c0d4db..000000000
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ /dev/null
@@ -1,594 +0,0 @@
-//! Check properties that are required by built-in traits and set
-//! up data structures required by type-checking/codegen.
-
-use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem};
-use rustc_errors::{struct_span_err, MultiSpan};
-use rustc_hir as hir;
-use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::lang_items::LangItem;
-use rustc_hir::ItemKind;
-use rustc_infer::infer;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::TyCtxtInferExt;
-use rustc_middle::ty::adjustment::CoerceUnsizedInfo;
-use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitable};
-use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
-use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError};
-use rustc_trait_selection::traits::predicate_for_trait_def;
-use rustc_trait_selection::traits::{self, ObligationCause};
-use std::collections::BTreeMap;
-
-pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) {
- let lang_items = tcx.lang_items();
- Checker { tcx, trait_def_id }
- .check(lang_items.drop_trait(), visit_implementation_of_drop)
- .check(lang_items.copy_trait(), visit_implementation_of_copy)
- .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized)
- .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn);
-}
-
-struct Checker<'tcx> {
- tcx: TyCtxt<'tcx>,
- trait_def_id: DefId,
-}
-
-impl<'tcx> Checker<'tcx> {
- fn check<F>(&self, trait_def_id: Option<DefId>, mut f: F) -> &Self
- where
- F: FnMut(TyCtxt<'tcx>, LocalDefId),
- {
- if Some(self.trait_def_id) == trait_def_id {
- for &impl_def_id in self.tcx.hir().trait_impls(self.trait_def_id) {
- f(self.tcx, impl_def_id);
- }
- }
- self
- }
-}
-
-fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
- // Destructors only work on local ADT types.
- match tcx.type_of(impl_did).kind() {
- ty::Adt(def, _) if def.did().is_local() => return,
- ty::Error(_) => return,
- _ => {}
- }
-
- let sp = match tcx.hir().expect_item(impl_did).kind {
- ItemKind::Impl(ref impl_) => impl_.self_ty.span,
- _ => bug!("expected Drop impl item"),
- };
-
- tcx.sess.emit_err(DropImplOnWrongItem { span: sp });
-}
-
-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);
- debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type);
-
- let span = tcx.hir().span(impl_hir_id);
- let param_env = tcx.param_env(impl_did);
- assert!(!self_type.has_escaping_bound_vars());
-
- debug!("visit_implementation_of_copy: self_type={:?} (free)", self_type);
-
- let cause = traits::ObligationCause::misc(span, impl_hir_id);
- match can_type_implement_copy(tcx, param_env, self_type, cause) {
- Ok(()) => {}
- Err(CopyImplementationError::InfrigingFields(fields)) => {
- let item = tcx.hir().expect_item(impl_did);
- let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref tr), .. }) = item.kind {
- tr.path.span
- } else {
- span
- };
-
- let mut err = struct_span_err!(
- tcx.sess,
- span,
- E0204,
- "the trait `Copy` may not be implemented for this type"
- );
-
- // We'll try to suggest constraining type parameters to fulfill the requirements of
- // their `Copy` implementation.
- let mut errors: BTreeMap<_, Vec<_>> = Default::default();
- let mut bounds = vec![];
-
- for (field, ty) in fields {
- let field_span = tcx.def_span(field.did);
- let field_ty_span = match tcx.hir().get_if_local(field.did) {
- Some(hir::Node::Field(field_def)) => field_def.ty.span,
- _ => field_span,
- };
- err.span_label(field_span, "this field does not implement `Copy`");
- // Spin up a new FulfillmentContext, so we can get the _precise_ reason
- // why this field does not implement Copy. This is useful because sometimes
- // it is not immediately clear why Copy is not implemented for a field, since
- // all we point at is the field itself.
- tcx.infer_ctxt().ignoring_regions().enter(|infcx| {
- for error in traits::fully_solve_bound(
- &infcx,
- traits::ObligationCause::dummy_with_span(field_ty_span),
- param_env,
- ty,
- tcx.lang_items().copy_trait().unwrap(),
- ) {
- let error_predicate = error.obligation.predicate;
- // Only note if it's not the root obligation, otherwise it's trivial and
- // should be self-explanatory (i.e. a field literally doesn't implement Copy).
-
- // FIXME: This error could be more descriptive, especially if the error_predicate
- // contains a foreign type or if it's a deeply nested type...
- if error_predicate != error.root_obligation.predicate {
- errors
- .entry((ty.to_string(), error_predicate.to_string()))
- .or_default()
- .push(error.obligation.cause.span);
- }
- if let ty::PredicateKind::Trait(ty::TraitPredicate {
- trait_ref,
- polarity: ty::ImplPolarity::Positive,
- ..
- }) = error_predicate.kind().skip_binder()
- {
- let ty = trait_ref.self_ty();
- if let ty::Param(_) = ty.kind() {
- bounds.push((
- format!("{ty}"),
- trait_ref.print_only_trait_path().to_string(),
- Some(trait_ref.def_id),
- ));
- }
- }
- }
- });
- }
- for ((ty, error_predicate), spans) in errors {
- let span: MultiSpan = spans.into();
- err.span_note(
- span,
- &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate),
- );
- }
- suggest_constraining_type_params(
- tcx,
- tcx.hir().get_generics(impl_did).expect("impls always have generics"),
- &mut err,
- bounds.iter().map(|(param, constraint, def_id)| {
- (param.as_str(), constraint.as_str(), *def_id)
- }),
- );
- err.emit();
- }
- Err(CopyImplementationError::NotAnAdt) => {
- let item = tcx.hir().expect_item(impl_did);
- let span =
- if let ItemKind::Impl(ref impl_) = item.kind { impl_.self_ty.span } else { span };
-
- tcx.sess.emit_err(CopyImplOnNonAdt { span });
- }
- Err(CopyImplementationError::HasDestructor) => {
- tcx.sess.emit_err(CopyImplOnTypeWithDtor { span });
- }
- }
-}
-
-fn visit_implementation_of_coerce_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) {
- debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did);
-
- // Just compute this for the side-effects, in particular reporting
- // errors; other parts of the code may demand it for the info of
- // course.
- let span = tcx.def_span(impl_did);
- tcx.at(span).coerce_unsized_info(impl_did);
-}
-
-fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, 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 dispatch_from_dyn_trait = tcx.require_lang_item(LangItem::DispatchFromDyn, Some(span));
-
- let source = tcx.type_of(impl_did);
- assert!(!source.has_escaping_bound_vars());
- let target = {
- let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
- assert_eq!(trait_ref.def_id, dispatch_from_dyn_trait);
-
- trait_ref.substs.type_at(1)
- };
-
- debug!("visit_implementation_of_dispatch_from_dyn: {:?} -> {:?}", source, target);
-
- let param_env = tcx.param_env(impl_did);
-
- let create_err = |msg: &str| struct_span_err!(tcx.sess, span, E0378, "{}", msg);
-
- tcx.infer_ctxt().enter(|infcx| {
- let cause = ObligationCause::misc(span, impl_hir_id);
-
- use rustc_type_ir::sty::TyKind::*;
- match (source.kind(), target.kind()) {
- (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b))
- if infcx.at(&cause, param_env).eq(r_a, *r_b).is_ok() && mutbl_a == *mutbl_b => {}
- (&RawPtr(tm_a), &RawPtr(tm_b)) if tm_a.mutbl == tm_b.mutbl => (),
- (&Adt(def_a, substs_a), &Adt(def_b, substs_b))
- if def_a.is_struct() && def_b.is_struct() =>
- {
- if def_a != def_b {
- let source_path = tcx.def_path_str(def_a.did());
- let target_path = tcx.def_path_str(def_b.did());
-
- create_err(&format!(
- "the trait `DispatchFromDyn` may only be implemented \
- for a coercion between structures with the same \
- definition; expected `{}`, found `{}`",
- source_path, target_path,
- ))
- .emit();
-
- return;
- }
-
- if def_a.repr().c() || def_a.repr().packed() {
- create_err(
- "structs implementing `DispatchFromDyn` may not have \
- `#[repr(packed)]` or `#[repr(C)]`",
- )
- .emit();
- }
-
- let fields = &def_a.non_enum_variant().fields;
-
- let coerced_fields = fields
- .iter()
- .filter(|field| {
- let ty_a = field.ty(tcx, substs_a);
- let ty_b = field.ty(tcx, substs_b);
-
- if let Ok(layout) = tcx.layout_of(param_env.and(ty_a)) {
- if layout.is_zst() && layout.align.abi.bytes() == 1 {
- // ignore ZST fields with alignment of 1 byte
- return false;
- }
- }
-
- if let Ok(ok) = infcx.at(&cause, param_env).eq(ty_a, ty_b) {
- if ok.obligations.is_empty() {
- create_err(
- "the trait `DispatchFromDyn` may only be implemented \
- for structs containing the field being coerced, \
- ZST fields with 1 byte alignment, and nothing else",
- )
- .note(&format!(
- "extra field `{}` of type `{}` is not allowed",
- field.name, ty_a,
- ))
- .emit();
-
- return false;
- }
- }
-
- return true;
- })
- .collect::<Vec<_>>();
-
- if coerced_fields.is_empty() {
- create_err(
- "the trait `DispatchFromDyn` may only be implemented \
- for a coercion between structures with a single field \
- being coerced, none found",
- )
- .emit();
- } else if coerced_fields.len() > 1 {
- create_err(
- "implementing the `DispatchFromDyn` trait requires multiple coercions",
- )
- .note(
- "the trait `DispatchFromDyn` may only be implemented \
- for a coercion between structures with a single field \
- being coerced",
- )
- .note(&format!(
- "currently, {} fields need coercions: {}",
- coerced_fields.len(),
- coerced_fields
- .iter()
- .map(|field| {
- format!(
- "`{}` (`{}` to `{}`)",
- field.name,
- field.ty(tcx, substs_a),
- field.ty(tcx, substs_b),
- )
- })
- .collect::<Vec<_>>()
- .join(", ")
- ))
- .emit();
- } else {
- let errors = traits::fully_solve_obligations(
- &infcx,
- coerced_fields.into_iter().map(|field| {
- predicate_for_trait_def(
- tcx,
- param_env,
- cause.clone(),
- dispatch_from_dyn_trait,
- 0,
- field.ty(tcx, substs_a),
- &[field.ty(tcx, substs_b).into()],
- )
- }),
- );
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- }
-
- // Finally, resolve all regions.
- let outlives_env = OutlivesEnvironment::new(param_env);
- infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
- }
- }
- _ => {
- create_err(
- "the trait `DispatchFromDyn` may only be implemented \
- for a coercion between structures",
- )
- .emit();
- }
- }
- })
-}
-
-pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo {
- debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
-
- // this provider should only get invoked for local def-ids
- let impl_did = impl_did.expect_local();
- let span = tcx.def_span(impl_did);
-
- let coerce_unsized_trait = tcx.require_lang_item(LangItem::CoerceUnsized, Some(span));
-
- let unsize_trait = tcx.lang_items().require(LangItem::Unsize).unwrap_or_else(|err| {
- tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err.to_string()));
- });
-
- let source = tcx.type_of(impl_did);
- let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
- assert_eq!(trait_ref.def_id, coerce_unsized_trait);
- let target = trait_ref.substs.type_at(1);
- debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target);
-
- let param_env = tcx.param_env(impl_did);
- assert!(!source.has_escaping_bound_vars());
-
- let err_info = CoerceUnsizedInfo { custom_kind: None };
-
- debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)", source, target);
-
- tcx.infer_ctxt().enter(|infcx| {
- let impl_hir_id = tcx.hir().local_def_id_to_hir_id(impl_did);
- let cause = ObligationCause::misc(span, impl_hir_id);
- let check_mutbl = |mt_a: ty::TypeAndMut<'tcx>,
- mt_b: ty::TypeAndMut<'tcx>,
- mk_ptr: &dyn Fn(Ty<'tcx>) -> Ty<'tcx>| {
- if (mt_a.mutbl, mt_b.mutbl) == (hir::Mutability::Not, hir::Mutability::Mut) {
- infcx
- .report_mismatched_types(
- &cause,
- mk_ptr(mt_b.ty),
- target,
- ty::error::TypeError::Mutability,
- )
- .emit();
- }
- (mt_a.ty, mt_b.ty, unsize_trait, None)
- };
- let (source, target, trait_def_id, kind) = match (source.kind(), target.kind()) {
- (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => {
- infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
- let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
- let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
- check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
- }
-
- (&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
- let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
- check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
- }
-
- (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
- check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
- }
-
- (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
- if def_a.is_struct() && def_b.is_struct() =>
- {
- if def_a != def_b {
- let source_path = tcx.def_path_str(def_a.did());
- let target_path = tcx.def_path_str(def_b.did());
- struct_span_err!(
- tcx.sess,
- span,
- E0377,
- "the trait `CoerceUnsized` may only be implemented \
- for a coercion between structures with the same \
- definition; expected `{}`, found `{}`",
- source_path,
- target_path
- )
- .emit();
- return err_info;
- }
-
- // 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>`,
- // which acts like a pointer to `U`, but carries along some extra data of type `T`:
- //
- // struct Foo<T, U> {
- // extra: T,
- // ptr: *mut U,
- // }
- //
- // We might have an impl that allows (e.g.) `Foo<T, [i32; 3]>` to be unsized
- // to `Foo<T, [i32]>`. That impl would look like:
- //
- // impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}
- //
- // Here `U = [i32; 3]` and `V = [i32]`. At runtime,
- // when this coercion occurs, we would be changing the
- // field `ptr` from a thin pointer of type `*mut [i32;
- // 3]` to a fat pointer of type `*mut [i32]` (with
- // extra data `3`). **The purpose of this check is to
- // make sure that we know how to do this conversion.**
- //
- // To check if this impl is legal, we would walk down
- // the fields of `Foo` and consider their types with
- // both substitutes. We are looking to find that
- // exactly one (non-phantom) field has changed its
- // type, which we will expect to be the pointer that
- // is becoming fat (we could probably generalize this
- // to multiple thin pointers of the same type becoming
- // fat, but we don't). In this case:
- //
- // - `extra` has type `T` before and type `T` after
- // - `ptr` has type `*mut U` before and type `*mut V` after
- //
- // Since just one field changed, we would then check
- // that `*mut U: CoerceUnsized<*mut V>` is implemented
- // (in other words, that we know how to do this
- // conversion). This will work out because `U:
- // Unsize<V>`, and we have a builtin rule that `*mut
- // U` can be coerced to `*mut V` if `U: Unsize<V>`.
- let fields = &def_a.non_enum_variant().fields;
- let diff_fields = fields
- .iter()
- .enumerate()
- .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() {
- // Ignore PhantomData fields
- return None;
- }
-
- // Ignore fields that aren't changed; it may
- // be that we could get away with subtyping or
- // something more accepting, but we use
- // equality because we want to be able to
- // perform this check without computing
- // variance where possible. (This is because
- // we may have to evaluate constraint
- // expressions in the course of execution.)
- // See e.g., #41936.
- if let Ok(ok) = infcx.at(&cause, param_env).eq(a, b) {
- if ok.obligations.is_empty() {
- return None;
- }
- }
-
- // Collect up all fields that were significantly changed
- // i.e., those that contain T in coerce_unsized T -> U
- Some((i, a, b))
- })
- .collect::<Vec<_>>();
-
- if diff_fields.is_empty() {
- struct_span_err!(
- tcx.sess,
- span,
- E0374,
- "the trait `CoerceUnsized` may only be implemented \
- for a coercion between structures with one field \
- being coerced, none found"
- )
- .emit();
- return err_info;
- } else if diff_fields.len() > 1 {
- let item = tcx.hir().expect_item(impl_did);
- let span = if let ItemKind::Impl(hir::Impl { of_trait: Some(ref t), .. }) =
- item.kind
- {
- t.path.span
- } else {
- tcx.def_span(impl_did)
- };
-
- struct_span_err!(
- tcx.sess,
- span,
- E0375,
- "implementing the trait \
- `CoerceUnsized` requires multiple \
- coercions"
- )
- .note(
- "`CoerceUnsized` may only be implemented for \
- a coercion between structures with one field being coerced",
- )
- .note(&format!(
- "currently, {} fields need coercions: {}",
- diff_fields.len(),
- diff_fields
- .iter()
- .map(|&(i, a, b)| {
- format!("`{}` (`{}` to `{}`)", fields[i].name, a, b)
- })
- .collect::<Vec<_>>()
- .join(", ")
- ))
- .span_label(span, "requires multiple coercions")
- .emit();
- return err_info;
- }
-
- let (i, a, b) = diff_fields[0];
- let kind = ty::adjustment::CustomCoerceUnsized::Struct(i);
- (a, b, coerce_unsized_trait, Some(kind))
- }
-
- _ => {
- struct_span_err!(
- tcx.sess,
- span,
- E0376,
- "the trait `CoerceUnsized` may only be implemented \
- for a coercion between structures"
- )
- .emit();
- return err_info;
- }
- };
-
- // Register an obligation for `A: Trait<B>`.
- let cause = traits::ObligationCause::misc(span, impl_hir_id);
- let predicate = predicate_for_trait_def(
- tcx,
- param_env,
- cause,
- trait_def_id,
- 0,
- source,
- &[target.into()],
- );
- let errors = traits::fully_solve_obligation(&infcx, predicate);
- if !errors.is_empty() {
- infcx.report_fulfillment_errors(&errors, None, false);
- }
-
- // Finally, resolve all regions.
- let outlives_env = OutlivesEnvironment::new(param_env);
- infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env);
-
- CoerceUnsizedInfo { custom_kind: kind }
- })
-}
diff --git a/config.toml.example b/config.toml.example
index a967d881b..a46813e4d 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -291,6 +291,10 @@ changelog-seen = 2
# on this runtime, such as `-C profile-generate` or `-C instrument-coverage`).
#profiler = false
+# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics.
+# Requires the LLVM submodule to be managed by bootstrap (i.e. not external).
+#optimized-compiler-builtins = false
+
# Indicates whether the native libraries linked into Cargo will be statically
# linked or not.
#cargo-native-static = false
@@ -521,6 +525,12 @@ changelog-seen = 2
# A descriptive string to be appended to `rustc --version` output, which is
# also used in places like debuginfo `DW_AT_producer`. This may be useful for
# supplementary build information, like distro-specific package versions.
+#
+# The Rust compiler will differentiate between versions of itself, including
+# based on this string, which means that if you wish to be compatible with
+# upstream Rust you need to set this to "". However, note that if you are not
+# actually compatible -- for example if you've backported patches that change
+# behavior -- this may lead to miscompilations or other bugs.
#description = <none> (string)
# The root location of the musl installation directory. The library directory
@@ -628,6 +638,11 @@ changelog-seen = 2
# If an explicit setting is given, it will be used for all parts of the codebase.
#new-symbol-mangling = true|false (see comment)
+# 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.
+#lto = "thin-local"
+
# =============================================================================
# Options for specific targets
#
diff --git a/git-commit-hash b/git-commit-hash
index 19793c62f..97604cf5d 100644
--- a/git-commit-hash
+++ b/git-commit-hash
@@ -1 +1 @@
-897e37553bba8b42751c67658967889d11ecd120 \ No newline at end of file
+69f9c33d71c871fc16ac445211281c6e7a340943 \ No newline at end of file
diff --git a/git-commit-info b/git-commit-info
new file mode 100644
index 000000000..4c08b5974
--- /dev/null
+++ b/git-commit-info
@@ -0,0 +1,3 @@
+69f9c33d71c871fc16ac445211281c6e7a340943
+69f9c33d7
+2022-12-12
diff --git a/library/alloc/benches/lib.rs b/library/alloc/benches/lib.rs
index 72ac897d4..d418965cd 100644
--- a/library/alloc/benches/lib.rs
+++ b/library/alloc/benches/lib.rs
@@ -3,7 +3,6 @@
#![cfg(not(target_os = "android"))]
#![feature(btree_drain_filter)]
#![feature(iter_next_chunk)]
-#![feature(map_first_last)]
#![feature(repr_simd)]
#![feature(slice_partition_dedup)]
#![feature(test)]
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 80b067812..8187517cc 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -28,16 +28,20 @@ extern "Rust" {
// The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them
// like `malloc`, `realloc`, and `free`, respectively.
#[rustc_allocator]
- #[rustc_allocator_nounwind]
+ #[cfg_attr(not(bootstrap), rustc_nounwind)]
+ #[cfg_attr(bootstrap, rustc_allocator_nounwind)]
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
#[rustc_deallocator]
- #[rustc_allocator_nounwind]
+ #[cfg_attr(not(bootstrap), rustc_nounwind)]
+ #[cfg_attr(bootstrap, rustc_allocator_nounwind)]
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
#[rustc_reallocator]
- #[rustc_allocator_nounwind]
+ #[cfg_attr(not(bootstrap), rustc_nounwind)]
+ #[cfg_attr(bootstrap, rustc_allocator_nounwind)]
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
#[rustc_allocator_zeroed]
- #[rustc_allocator_nounwind]
+ #[cfg_attr(not(bootstrap), rustc_nounwind)]
+ #[cfg_attr(bootstrap, rustc_allocator_nounwind)]
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
}
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index 904a53bb4..83a138559 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -21,7 +21,6 @@ use Cow::*;
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B>
where
B: ToOwned,
- <B as ToOwned>::Owned: 'a,
{
fn borrow(&self) -> &B {
&**self
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 65e323c9e..d6681a317 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -151,7 +151,6 @@ use core::async_iter::AsyncIterator;
use core::borrow;
use core::cmp::Ordering;
use core::convert::{From, TryFrom};
-#[cfg(not(bootstrap))]
use core::error::Error;
use core::fmt;
use core::future::Future;
@@ -176,7 +175,6 @@ use crate::borrow::Cow;
use crate::raw_vec::RawVec;
#[cfg(not(no_global_oom_handling))]
use crate::str::from_boxed_utf8_unchecked;
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
use crate::string::String;
#[cfg(not(no_global_oom_handling))]
@@ -1622,6 +1620,22 @@ impl<T, const N: usize> From<[T; N]> for Box<[T]> {
}
}
+/// Casts a boxed slice to a boxed array.
+///
+/// # Safety
+///
+/// `boxed_slice.len()` must be exactly `N`.
+unsafe fn boxed_slice_as_array_unchecked<T, A: Allocator, const N: usize>(
+ boxed_slice: Box<[T], A>,
+) -> Box<[T; N], A> {
+ debug_assert_eq!(boxed_slice.len(), N);
+
+ let (ptr, alloc) = Box::into_raw_with_allocator(boxed_slice);
+ // SAFETY: Pointer and allocator came from an existing box,
+ // and our safety condition requires that the length is exactly `N`
+ unsafe { Box::from_raw_in(ptr as *mut [T; N], alloc) }
+}
+
#[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
type Error = Box<[T]>;
@@ -1637,13 +1651,46 @@ impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]> {
/// `boxed_slice.len()` does not equal `N`.
fn try_from(boxed_slice: Box<[T]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == N {
- Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [T; N]) })
+ Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
} else {
Err(boxed_slice)
}
}
}
+#[cfg(not(no_global_oom_handling))]
+#[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")]
+impl<T, const N: usize> TryFrom<Vec<T>> for Box<[T; N]> {
+ type Error = Vec<T>;
+
+ /// Attempts to convert a `Vec<T>` into a `Box<[T; N]>`.
+ ///
+ /// Like [`Vec::into_boxed_slice`], this is in-place if `vec.capacity() == N`,
+ /// but will require a reallocation otherwise.
+ ///
+ /// # Errors
+ ///
+ /// Returns the original `Vec<T>` in the `Err` variant if
+ /// `boxed_slice.len()` does not equal `N`.
+ ///
+ /// # Examples
+ ///
+ /// This can be used with [`vec!`] to create an array on the heap:
+ ///
+ /// ```
+ /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap();
+ /// assert_eq!(state.len(), 100);
+ /// ```
+ fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
+ if vec.len() == N {
+ let boxed_slice = vec.into_boxed_slice();
+ Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) })
+ } else {
+ Err(vec)
+ }
+ }
+}
+
impl<A: Allocator> Box<dyn Any, A> {
/// Attempt to downcast the box to a concrete type.
///
@@ -2037,8 +2084,7 @@ impl<T: ?Sized, A: Allocator> AsMut<T> for Box<T, A> {
* could have a method to project a Pin<T> from it.
*/
#[stable(feature = "pin", since = "1.33.0")]
-#[rustc_const_unstable(feature = "const_box", issue = "92521")]
-impl<T: ?Sized, A: Allocator> const Unpin for Box<T, A> where A: 'static {}
+impl<T: ?Sized, A: Allocator> Unpin for Box<T, A> where A: 'static {}
#[unstable(feature = "generator_trait", issue = "43122")]
impl<G: ?Sized + Generator<R> + Unpin, R, A: Allocator> Generator<R> for Box<G, A>
@@ -2091,7 +2137,6 @@ impl<S: ?Sized + AsyncIterator + Unpin> AsyncIterator for Box<S> {
}
}
-#[cfg(not(bootstrap))]
impl dyn Error {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
@@ -2109,7 +2154,6 @@ impl dyn Error {
}
}
-#[cfg(not(bootstrap))]
impl dyn Error + Send {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
@@ -2124,7 +2168,6 @@ impl dyn Error + Send {
}
}
-#[cfg(not(bootstrap))]
impl dyn Error + Send + Sync {
#[inline]
#[stable(feature = "error_downcast", since = "1.3.0")]
@@ -2139,7 +2182,6 @@ impl dyn Error + Send + Sync {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
@@ -2173,7 +2215,6 @@ impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
@@ -2213,7 +2254,6 @@ impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync +
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl From<String> for Box<dyn Error + Send + Sync> {
@@ -2258,7 +2298,6 @@ impl From<String> for Box<dyn Error + Send + Sync> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "string_box_error", since = "1.6.0")]
impl From<String> for Box<dyn Error> {
@@ -2281,7 +2320,6 @@ impl From<String> for Box<dyn Error> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
@@ -2306,7 +2344,6 @@ impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "string_box_error", since = "1.6.0")]
impl From<&str> for Box<dyn Error> {
@@ -2329,7 +2366,6 @@ impl From<&str> for Box<dyn Error> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "cow_box_error", since = "1.22.0")]
impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
@@ -2352,7 +2388,6 @@ impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
}
}
-#[cfg(not(bootstrap))]
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "cow_box_error", since = "1.22.0")]
impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
@@ -2374,7 +2409,6 @@ impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "box_error", since = "1.8.0")]
impl<T: core::error::Error> core::error::Error for Box<T> {
#[allow(deprecated, deprecated_in_future)]
diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs
index 0a20c74b0..c477c4490 100644
--- a/library/alloc/src/boxed/thin.rs
+++ b/library/alloc/src/boxed/thin.rs
@@ -2,7 +2,6 @@
// https://github.com/matthieu-m/rfc2580/blob/b58d1d3cba0d4b5e859d3617ea2d0943aaa31329/examples/thin.rs
// by matthieu-m
use crate::alloc::{self, Layout, LayoutError};
-#[cfg(not(bootstrap))]
use core::error::Error;
use core::fmt::{self, Debug, Display, Formatter};
use core::marker::PhantomData;
@@ -274,7 +273,6 @@ impl<H> WithHeader<H> {
}
}
-#[cfg(not(bootstrap))]
#[unstable(feature = "thin_box", issue = "92791")]
impl<T: ?Sized + Error> Error for ThinBox<T> {
fn source(&self) -> Option<&(dyn Error + 'static)> {
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index cacbd54b6..8a7719347 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -580,7 +580,7 @@ impl<K, V> BTreeMap<K, V> {
/// map.insert(1, "a");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")]
#[must_use]
pub const fn new() -> BTreeMap<K, V> {
BTreeMap { root: None, length: 0, alloc: ManuallyDrop::new(Global), _marker: PhantomData }
@@ -703,7 +703,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Basic usage:
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -712,7 +711,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// map.insert(2, "a");
/// assert_eq!(map.first_key_value(), Some((&1, &"b")));
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn first_key_value(&self) -> Option<(&K, &V)>
where
K: Ord,
@@ -727,7 +726,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// # Examples
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -741,7 +739,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(*map.get(&1).unwrap(), "first");
/// assert_eq!(*map.get(&2).unwrap(), "b");
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V, A>>
where
K: Ord,
@@ -765,7 +763,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Draining elements in ascending order, while keeping a usable map each iteration.
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -776,7 +773,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// }
/// assert!(map.is_empty());
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn pop_first(&mut self) -> Option<(K, V)>
where
K: Ord,
@@ -792,7 +789,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Basic usage:
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -800,7 +796,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// map.insert(2, "a");
/// assert_eq!(map.last_key_value(), Some((&2, &"a")));
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn last_key_value(&self) -> Option<(&K, &V)>
where
K: Ord,
@@ -815,7 +811,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// # Examples
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -829,7 +824,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// assert_eq!(*map.get(&1).unwrap(), "a");
/// assert_eq!(*map.get(&2).unwrap(), "last");
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V, A>>
where
K: Ord,
@@ -853,7 +848,6 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Draining elements in descending order, while keeping a usable map each iteration.
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
@@ -864,7 +858,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// }
/// assert!(map.is_empty());
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn pop_last(&mut self) -> Option<(K, V)>
where
K: Ord,
@@ -1099,6 +1093,9 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// Moves all elements from `other` into `self`, leaving `other` empty.
///
+ /// If a key from `other` is already present in `self`, the respective
+ /// value from `self` will be overwritten with the respective value from `other`.
+ ///
/// # Examples
///
/// ```
@@ -1107,10 +1104,10 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// let mut a = BTreeMap::new();
/// a.insert(1, "a");
/// a.insert(2, "b");
- /// a.insert(3, "c");
+ /// a.insert(3, "c"); // Note: Key (3) also present in b.
///
/// let mut b = BTreeMap::new();
- /// b.insert(3, "d");
+ /// b.insert(3, "d"); // Note: Key (3) also present in a.
/// b.insert(4, "e");
/// b.insert(5, "f");
///
@@ -1121,7 +1118,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
///
/// assert_eq!(a[&1], "a");
/// assert_eq!(a[&2], "b");
- /// assert_eq!(a[&3], "d");
+ /// assert_eq!(a[&3], "d"); // Note: "c" has been overwritten.
/// assert_eq!(a[&4], "e");
/// assert_eq!(a[&5], "f");
/// ```
@@ -2392,7 +2389,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_unstable(
+ feature = "const_btree_len",
+ issue = "71835",
+ implied_by = "const_btree_new"
+ )]
pub const fn len(&self) -> usize {
self.length
}
@@ -2413,7 +2414,11 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_unstable(
+ feature = "const_btree_len",
+ issue = "71835",
+ implied_by = "const_btree_new"
+ )]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index cd7cdc192..370b58864 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -133,7 +133,6 @@ impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display
}
}
-#[cfg(not(bootstrap))]
#[unstable(feature = "map_try_insert", issue = "82766")]
impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error
for crate::collections::btree_map::OccupiedError<'a, K, V>
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index f1d2d3b30..da766b67a 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -206,9 +206,9 @@ impl<'a, K: 'a, V: 'a, Type> Clone for NodeRef<marker::Immut<'a>, K, V, Type> {
unsafe impl<BorrowType, K: Sync, V: Sync, Type> Sync for NodeRef<BorrowType, K, V, Type> {}
-unsafe impl<'a, K: Sync + 'a, V: Sync + 'a, Type> Send for NodeRef<marker::Immut<'a>, K, V, Type> {}
-unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::Mut<'a>, K, V, Type> {}
-unsafe impl<'a, K: Send + 'a, V: Send + 'a, Type> Send for NodeRef<marker::ValMut<'a>, K, V, Type> {}
+unsafe impl<K: Sync, V: Sync, Type> Send for NodeRef<marker::Immut<'_>, K, V, Type> {}
+unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Mut<'_>, K, V, Type> {}
+unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::ValMut<'_>, K, V, Type> {}
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Owned, K, V, Type> {}
unsafe impl<K: Send, V: Send, Type> Send for NodeRef<marker::Dying, K, V, Type> {}
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 2cfc08074..4ddb21192 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -343,7 +343,7 @@ impl<T> BTreeSet<T> {
/// let mut set: BTreeSet<i32> = BTreeSet::new();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")]
#[must_use]
pub const fn new() -> BTreeSet<T> {
BTreeSet { map: BTreeMap::new() }
@@ -786,7 +786,6 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// Basic usage:
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeSet;
///
/// let mut set = BTreeSet::new();
@@ -797,7 +796,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// assert_eq!(set.first(), Some(&1));
/// ```
#[must_use]
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn first(&self) -> Option<&T>
where
T: Ord,
@@ -813,7 +812,6 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// Basic usage:
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeSet;
///
/// let mut set = BTreeSet::new();
@@ -824,7 +822,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// assert_eq!(set.last(), Some(&2));
/// ```
#[must_use]
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn last(&self) -> Option<&T>
where
T: Ord,
@@ -838,7 +836,6 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// # Examples
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeSet;
///
/// let mut set = BTreeSet::new();
@@ -849,7 +846,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// }
/// assert!(set.is_empty());
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn pop_first(&mut self) -> Option<T>
where
T: Ord,
@@ -863,7 +860,6 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// # Examples
///
/// ```
- /// #![feature(map_first_last)]
/// use std::collections::BTreeSet;
///
/// let mut set = BTreeSet::new();
@@ -874,7 +870,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// }
/// assert!(set.is_empty());
/// ```
- #[unstable(feature = "map_first_last", issue = "62924")]
+ #[stable(feature = "map_first_last", since = "1.66.0")]
pub fn pop_last(&mut self) -> Option<T>
where
T: Ord,
@@ -1174,7 +1170,11 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_unstable(
+ feature = "const_btree_len",
+ issue = "71835",
+ implied_by = "const_btree_new"
+ )]
pub const fn len(&self) -> usize {
self.map.len()
}
@@ -1193,7 +1193,11 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_btree_new", issue = "71835")]
+ #[rustc_const_unstable(
+ feature = "const_btree_len",
+ issue = "71835",
+ implied_by = "const_btree_new"
+ )]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 6480fcaf9..f2f5dffc2 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -1613,7 +1613,7 @@ impl<'a, T> CursorMut<'a, T> {
None
} else {
// We can't point to the node that we pop. Copying the behavior of
- // `remove_current`, we move on the the next node in the sequence.
+ // `remove_current`, we move on to the next node in the sequence.
// If the list is of length 1 then we end pointing to the "ghost"
// node at index 0, which is expected.
if self.list.head == self.current {
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs
index 21d0def08..161a37573 100644
--- a/library/alloc/src/collections/mod.rs
+++ b/library/alloc/src/collections/mod.rs
@@ -153,6 +153,5 @@ trait SpecExtend<I: IntoIterator> {
fn spec_extend(&mut self, iter: I);
}
-#[cfg(not(bootstrap))]
#[stable(feature = "try_reserve", since = "1.57.0")]
impl core::error::Error for TryReserveError {}
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index e3f4deb08..2a57dad89 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -12,11 +12,17 @@ use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::{repeat_with, FromIterator};
use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop, MaybeUninit};
+use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::{Index, IndexMut, Range, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice;
+// This is used in a bunch of intra-doc links.
+// FIXME: For some reason, `#[cfg(doc)]` wasn't sufficient, resulting in
+// failures in linkchecker even though rustdoc built the docs just fine.
+#[allow(unused_imports)]
+use core::mem;
+
use crate::alloc::{Allocator, Global};
use crate::collections::TryReserveError;
use crate::collections::TryReserveErrorKind;
@@ -177,7 +183,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
/// Marginally more convenient
#[inline]
fn cap(&self) -> usize {
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// For zero sized types, we are always at maximum capacity
MAXIMUM_ZST_CAPACITY
} else {
@@ -3038,7 +3044,7 @@ impl<T, A: Allocator> From<Vec<T, A>> for VecDeque<T, A> {
/// `Vec<T>` came from `From<VecDeque<T>>` and hasn't been reallocated.
fn from(mut other: Vec<T, A>) -> Self {
let len = other.len();
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// There's no actual allocation for ZSTs to worry about capacity,
// but `VecDeque` can't handle as much length as `Vec`.
assert!(len < MAXIMUM_ZST_CAPACITY, "capacity overflow");
@@ -3124,7 +3130,7 @@ impl<T, const N: usize> From<[T; N]> for VecDeque<T> {
fn from(arr: [T; N]) -> Self {
let mut deq = VecDeque::with_capacity(N);
let arr = ManuallyDrop::new(arr);
- if mem::size_of::<T>() != 0 {
+ if !<T>::IS_ZST {
// SAFETY: VecDeque::with_capacity ensures that there is enough capacity.
unsafe {
ptr::copy_nonoverlapping(arr.as_ptr(), deq.ptr(), N);
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index aede6d54c..11bd4c4dc 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -1122,7 +1122,6 @@ impl CStr {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl core::error::Error for NulError {
#[allow(deprecated)]
@@ -1131,11 +1130,9 @@ impl core::error::Error for NulError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
impl core::error::Error for FromVecWithNulError {}
-#[cfg(not(bootstrap))]
#[stable(feature = "cstring_into", since = "1.7.0")]
impl core::error::Error for IntoStringError {
#[allow(deprecated)]
diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs
index ed398b566..799ce9d5d 100644
--- a/library/alloc/src/fmt.rs
+++ b/library/alloc/src/fmt.rs
@@ -327,7 +327,7 @@
//! - `text` must not contain any `'{'` or `'}'` characters,
//! - `ws` is any character for which [`char::is_whitespace`] returns `true`, has no semantic
//! meaning and is completely optional,
-//! - `integer` is a decimal integer that may contain leading zeroes and
+//! - `integer` is a decimal integer that may contain leading zeroes and must fit into an `usize` and
//! - `identifier` is an `IDENTIFIER_OR_KEYWORD` (not an `IDENTIFIER`) as defined by the [Rust language reference](https://doc.rust-lang.org/reference/identifiers.html).
//!
//! # Formatting traits
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 8619467c2..ce36b116f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -69,6 +69,8 @@
any(not(feature = "miri-test-libstd"), test, doctest),
no_global_oom_handling,
not(no_global_oom_handling),
+ not(no_rc),
+ not(no_sync),
target_has_atomic = "ptr"
))]
#![no_std]
@@ -97,7 +99,7 @@
#![feature(coerce_unsized)]
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
#![feature(const_box)]
-#![cfg_attr(not(no_global_oom_handling), feature(const_btree_new))]
+#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
#![feature(const_cow_is_borrowed)]
#![feature(const_convert)]
#![feature(const_size_of_val)]
@@ -109,10 +111,11 @@
#![feature(core_intrinsics)]
#![feature(const_eval_select)]
#![feature(const_pin)]
+#![feature(const_waker)]
#![feature(cstr_from_bytes_until_nul)]
#![feature(dispatch_from_dyn)]
-#![cfg_attr(not(bootstrap), feature(error_generic_member_access))]
-#![cfg_attr(not(bootstrap), feature(error_in_core))]
+#![feature(error_generic_member_access)]
+#![feature(error_in_core)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(fmt_internals)]
@@ -122,20 +125,21 @@
#![feature(iter_advance_by)]
#![feature(iter_next_chunk)]
#![feature(layout_for_ptr)]
-#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_uninit_array)]
+#![feature(maybe_uninit_uninit_array_transpose)]
#![cfg_attr(test, feature(new_uninit))]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(pattern)]
#![feature(pointer_byte_offsets)]
-#![cfg_attr(not(bootstrap), feature(provide_any))]
+#![feature(provide_any)]
#![feature(ptr_internals)]
#![feature(ptr_metadata)]
#![feature(ptr_sub_ptr)]
#![feature(receiver_trait)]
#![feature(saturating_int_impl)]
#![feature(set_ptr_value)]
+#![feature(sized_type_properties)]
#![feature(slice_from_ptr_range)]
#![feature(slice_group_by)]
#![feature(slice_ptr_get)]
@@ -169,7 +173,6 @@
#![cfg_attr(not(test), feature(generator_trait))]
#![feature(hashmap_internals)]
#![feature(lang_items)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(min_specialization)]
#![feature(negative_impls)]
#![feature(never_type)]
@@ -224,16 +227,17 @@ mod boxed {
}
pub mod borrow;
pub mod collections;
-#[cfg(not(no_global_oom_handling))]
+#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
pub mod ffi;
pub mod fmt;
+#[cfg(not(no_rc))]
pub mod rc;
pub mod slice;
pub mod str;
pub mod string;
-#[cfg(target_has_atomic = "ptr")]
+#[cfg(all(not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
pub mod sync;
-#[cfg(all(not(no_global_oom_handling), target_has_atomic = "ptr"))]
+#[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync), target_has_atomic = "ptr"))]
pub mod task;
#[cfg(test)]
mod tests;
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index b0f4529ab..5a10121bb 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -3,7 +3,7 @@
use core::alloc::LayoutError;
use core::cmp;
use core::intrinsics;
-use core::mem::{self, ManuallyDrop, MaybeUninit};
+use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::Drop;
use core::ptr::{self, NonNull, Unique};
use core::slice;
@@ -168,7 +168,7 @@ impl<T, A: Allocator> RawVec<T, A> {
#[cfg(not(no_global_oom_handling))]
fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self {
// Don't allocate here because `Drop` will not deallocate when `capacity` is 0.
- if mem::size_of::<T>() == 0 || capacity == 0 {
+ if T::IS_ZST || capacity == 0 {
Self::new_in(alloc)
} else {
// We avoid `unwrap_or_else` here because it bloats the amount of
@@ -229,7 +229,7 @@ impl<T, A: Allocator> RawVec<T, A> {
/// This will always be `usize::MAX` if `T` is zero-sized.
#[inline(always)]
pub fn capacity(&self) -> usize {
- if mem::size_of::<T>() == 0 { usize::MAX } else { self.cap }
+ if T::IS_ZST { usize::MAX } else { self.cap }
}
/// Returns a shared reference to the allocator backing this `RawVec`.
@@ -238,7 +238,7 @@ impl<T, A: Allocator> RawVec<T, A> {
}
fn current_memory(&self) -> Option<(NonNull<u8>, Layout)> {
- if mem::size_of::<T>() == 0 || self.cap == 0 {
+ if T::IS_ZST || self.cap == 0 {
None
} else {
// We have an allocated chunk of memory, so we can bypass runtime
@@ -380,7 +380,7 @@ impl<T, A: Allocator> RawVec<T, A> {
// This is ensured by the calling contexts.
debug_assert!(additional > 0);
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// Since we return a capacity of `usize::MAX` when `elem_size` is
// 0, getting to here necessarily means the `RawVec` is overfull.
return Err(CapacityOverflow.into());
@@ -406,7 +406,7 @@ impl<T, A: Allocator> RawVec<T, A> {
// `grow_amortized`, but this method is usually instantiated less often so
// it's less critical.
fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), TryReserveError> {
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// Since we return a capacity of `usize::MAX` when the type size is
// 0, getting to here necessarily means the `RawVec` is overfull.
return Err(CapacityOverflow.into());
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 6d247681c..006d813e5 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1110,8 +1110,8 @@ impl<T: ?Sized> Rc<T> {
#[inline]
#[stable(feature = "ptr_eq", since = "1.17.0")]
- /// Returns `true` if the two `Rc`s point to the same allocation
- /// (in a vein similar to [`ptr::eq`]).
+ /// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to
+ /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Examples
///
@@ -1386,7 +1386,7 @@ impl<T: ?Sized> Rc<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| mem.with_metadata_of(ptr as *mut RcBox<T>),
+ |mem| mem.with_metadata_of(ptr as *const RcBox<T>),
)
}
}
@@ -2419,9 +2419,9 @@ impl<T: ?Sized> Weak<T> {
}
}
- /// Returns `true` if the two `Weak`s point to the same allocation (similar to
- /// [`ptr::eq`]), or if both don't point to any allocation
- /// (because they were created with `Weak::new()`).
+ /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
+ /// both don't point to any allocation (because they were created with `Weak::new()`). See [that
+ /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Notes
///
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index bcd3f49e2..a5e7bf2a1 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -16,9 +16,7 @@ use core::borrow::{Borrow, BorrowMut};
#[cfg(not(no_global_oom_handling))]
use core::cmp::Ordering::{self, Less};
#[cfg(not(no_global_oom_handling))]
-use core::mem;
-#[cfg(not(no_global_oom_handling))]
-use core::mem::size_of;
+use core::mem::{self, SizedTypeProperties};
#[cfg(not(no_global_oom_handling))]
use core::ptr;
@@ -205,7 +203,7 @@ impl<T> [T] {
where
T: Ord,
{
- merge_sort(self, |a, b| a.lt(b));
+ merge_sort(self, T::lt);
}
/// Sorts the slice with a comparator function.
@@ -1018,7 +1016,7 @@ where
const MIN_RUN: usize = 10;
// Sorting has no meaningful behavior on zero-sized types.
- if size_of::<T>() == 0 {
+ if T::IS_ZST {
return;
}
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index f2448396c..c436adf70 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -44,7 +44,6 @@
#[cfg(not(no_global_oom_handling))]
use core::char::{decode_utf16, REPLACEMENT_CHARACTER};
-#[cfg(not(bootstrap))]
use core::error::Error;
use core::fmt;
use core::hash;
@@ -68,7 +67,7 @@ use core::str::Utf8Chunks;
use crate::borrow::{Cow, ToOwned};
use crate::boxed::Box;
use crate::collections::TryReserveError;
-use crate::str::{self, Chars, Utf8Error};
+use crate::str::{self, from_utf8_unchecked_mut, Chars, Utf8Error};
#[cfg(not(no_global_oom_handling))]
use crate::str::{from_boxed_utf8_unchecked, FromStr};
use crate::vec::Vec;
@@ -1850,6 +1849,35 @@ impl String {
let slice = self.vec.into_boxed_slice();
unsafe { from_boxed_utf8_unchecked(slice) }
}
+
+ /// Consumes and leaks the `String`, returning a mutable reference to the contents,
+ /// `&'static mut str`.
+ ///
+ /// This is mainly useful for data that lives for the remainder of
+ /// the program's life. Dropping the returned reference will cause a memory
+ /// leak.
+ ///
+ /// It does not reallocate or shrink the `String`,
+ /// so the leaked allocation may include unused capacity that is not part
+ /// of the returned slice.
+ ///
+ /// # Examples
+ ///
+ /// Simple usage:
+ ///
+ /// ```
+ /// #![feature(string_leak)]
+ ///
+ /// let x = String::from("bucket");
+ /// let static_ref: &'static mut str = x.leak();
+ /// assert_eq!(static_ref, "bucket");
+ /// ```
+ #[unstable(feature = "string_leak", issue = "102929")]
+ #[inline]
+ pub fn leak(self) -> &'static mut str {
+ let slice = self.vec.leak();
+ unsafe { from_utf8_unchecked_mut(slice) }
+ }
}
impl FromUtf8Error {
@@ -1941,7 +1969,6 @@ impl fmt::Display for FromUtf16Error {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for FromUtf8Error {
#[allow(deprecated)]
@@ -1950,7 +1977,6 @@ impl Error for FromUtf8Error {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for FromUtf16Error {
#[allow(deprecated)]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 4377edeee..81cd77074 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -3,6 +3,10 @@
//! Thread-safe reference-counting pointers.
//!
//! See the [`Arc<T>`][Arc] documentation for more details.
+//!
+//! **Note**: This module is only available on platforms that support atomic
+//! loads and stores of pointers. This may be detected at compile time using
+//! `#[cfg(target_has_atomic = "ptr")]`.
use core::any::Any;
use core::borrow;
@@ -82,6 +86,11 @@ macro_rules! acquire {
/// [`Mutex`][mutex], [`RwLock`][rwlock], or one of the [`Atomic`][atomic]
/// types.
///
+/// **Note**: This type is only available on platforms that support atomic
+/// loads and stores of pointers, which includes all platforms that support
+/// the `std` crate but not all those which only support [`alloc`](crate).
+/// This may be detected at compile time using `#[cfg(target_has_atomic = "ptr")]`.
+///
/// ## Thread Safety
///
/// Unlike [`Rc<T>`], `Arc<T>` uses atomic operations for its reference
@@ -1108,8 +1117,8 @@ impl<T: ?Sized> Arc<T> {
drop(Weak { ptr: self.ptr });
}
- /// Returns `true` if the two `Arc`s point to the same allocation
- /// (in a vein similar to [`ptr::eq`]).
+ /// Returns `true` if the two `Arc`s point to the same allocation in a vein similar to
+ /// [`ptr::eq`]. See [that function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Examples
///
@@ -1195,7 +1204,7 @@ impl<T: ?Sized> Arc<T> {
Self::allocate_for_layout(
Layout::for_value(&*ptr),
|layout| Global.allocate(layout),
- |mem| mem.with_metadata_of(ptr as *mut ArcInner<T>),
+ |mem| mem.with_metadata_of(ptr as *const ArcInner<T>),
)
}
}
@@ -1980,33 +1989,26 @@ impl<T: ?Sized> Weak<T> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add as this function should never take the reference count
// from zero to one.
- let inner = self.inner()?;
-
- // Relaxed load because any write of 0 that we can observe
- // leaves the field in a permanently zero state (so a
- // "stale" read of 0 is fine), and any other value is
- // confirmed via the CAS below.
- let mut n = inner.strong.load(Relaxed);
-
- loop {
- if n == 0 {
- return None;
- }
-
- // See comments in `Arc::clone` for why we do this (for `mem::forget`).
- if n > MAX_REFCOUNT {
- abort();
- }
-
+ self.inner()?
+ .strong
// Relaxed is fine for the failure case because we don't have any expectations about the new state.
// Acquire is necessary for the success case to synchronise with `Arc::new_cyclic`, when the inner
// value can be initialized after `Weak` references have already been created. In that case, we
// expect to observe the fully initialized value.
- match inner.strong.compare_exchange_weak(n, n + 1, Acquire, Relaxed) {
- Ok(_) => return Some(unsafe { Arc::from_inner(self.ptr) }), // null checked above
- Err(old) => n = old,
- }
- }
+ .fetch_update(Acquire, Relaxed, |n| {
+ // Any write of 0 we can observe leaves the field in permanently zero state.
+ if n == 0 {
+ return None;
+ }
+ // See comments in `Arc::clone` for why we do this (for `mem::forget`).
+ if n > MAX_REFCOUNT {
+ abort();
+ }
+ Some(n + 1)
+ })
+ .ok()
+ // null checked above
+ .map(|_| unsafe { Arc::from_inner(self.ptr) })
}
/// Gets the number of strong (`Arc`) pointers pointing to this allocation.
@@ -2067,9 +2069,9 @@ impl<T: ?Sized> Weak<T> {
}
}
- /// Returns `true` if the two `Weak`s point to the same allocation (similar to
- /// [`ptr::eq`]), or if both don't point to any allocation
- /// (because they were created with `Weak::new()`).
+ /// Returns `true` if the two `Weak`s point to the same allocation similar to [`ptr::eq`], or if
+ /// both don't point to any allocation (because they were created with `Weak::new()`). See [that
+ /// function][`ptr::eq`] for caveats when comparing `dyn Trait` pointers.
///
/// # Notes
///
@@ -2764,7 +2766,6 @@ fn data_offset_align(align: usize) -> usize {
layout.size() + layout.padding_needed_for(align)
}
-#[cfg(not(bootstrap))]
#[stable(feature = "arc_error", since = "1.52.0")]
impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
#[allow(deprecated, deprecated_in_future)]
diff --git a/library/alloc/src/task.rs b/library/alloc/src/task.rs
index 528ee4ff1..9d8e309a9 100644
--- a/library/alloc/src/task.rs
+++ b/library/alloc/src/task.rs
@@ -1,5 +1,11 @@
#![stable(feature = "wake_trait", since = "1.51.0")]
+
//! Types and Traits for working with asynchronous tasks.
+//!
+//! **Note**: This module is only available on platforms that support atomic
+//! loads and stores of pointers. This may be detected at compile time using
+//! `#[cfg(target_has_atomic = "ptr")]`.
+
use core::mem::ManuallyDrop;
use core::task::{RawWaker, RawWakerVTable, Waker};
diff --git a/library/alloc/src/vec/drain.rs b/library/alloc/src/vec/drain.rs
index 5b73906a1..541f99bcf 100644
--- a/library/alloc/src/vec/drain.rs
+++ b/library/alloc/src/vec/drain.rs
@@ -1,7 +1,7 @@
use crate::alloc::{Allocator, Global};
use core::fmt;
use core::iter::{FusedIterator, TrustedLen};
-use core::mem::{self, ManuallyDrop};
+use core::mem::{self, ManuallyDrop, SizedTypeProperties};
use core::ptr::{self, NonNull};
use core::slice::{self};
@@ -202,7 +202,7 @@ impl<T, A: Allocator> Drop for Drain<'_, T, A> {
let mut vec = self.vec;
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// ZSTs have no identity, so we don't need to move them around, we only need to drop the correct amount.
// this can be achieved by manipulating the Vec length instead of moving values out from `iter`.
unsafe {
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index b211421b2..87d61deb1 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -55,6 +55,9 @@
//! This is handled by the [`InPlaceDrop`] guard for sink items (`U`) and by
//! [`vec::IntoIter::forget_allocation_drop_remaining()`] for remaining source items (`T`).
//!
+//! If dropping any remaining source item (`T`) panics then [`InPlaceDstBufDrop`] will handle dropping
+//! the already collected sink items (`U`) and freeing the allocation.
+//!
//! [`vec::IntoIter::forget_allocation_drop_remaining()`]: super::IntoIter::forget_allocation_drop_remaining()
//!
//! # O(1) collect
@@ -135,10 +138,10 @@
//! vec.truncate(write_idx);
//! ```
use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce};
-use core::mem::{self, ManuallyDrop};
+use core::mem::{self, ManuallyDrop, SizedTypeProperties};
use core::ptr::{self};
-use super::{InPlaceDrop, SpecFromIter, SpecFromIterNested, Vec};
+use super::{InPlaceDrop, InPlaceDstBufDrop, SpecFromIter, SpecFromIterNested, Vec};
/// Specialization marker for collecting an iterator pipeline into a Vec while reusing the
/// source allocation, i.e. executing the pipeline in place.
@@ -154,7 +157,7 @@ where
default fn from_iter(mut iterator: I) -> Self {
// See "Layout constraints" section in the module documentation. We rely on const
// optimization here since these conditions currently cannot be expressed as trait bounds
- if mem::size_of::<T>() == 0
+ if T::IS_ZST
|| mem::size_of::<T>()
!= mem::size_of::<<<I as SourceIter>::Source as AsVecIntoIter>::Item>()
|| mem::align_of::<T>()
@@ -191,14 +194,17 @@ where
);
}
- // Drop any remaining values at the tail of the source but prevent drop of the allocation
- // itself once IntoIter goes out of scope.
- // If the drop panics then we also leak any elements collected into dst_buf.
+ // The ownership of the allocation and the new `T` values is temporarily moved into `dst_guard`.
+ // This is safe because `forget_allocation_drop_remaining` immediately forgets the allocation
+ // before any panic can occur in order to avoid any double free, and then proceeds to drop
+ // any remaining values at the tail of the source.
//
// Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
// contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
// module documenttation why this is ok anyway.
+ let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap };
src.forget_allocation_drop_remaining();
+ mem::forget(dst_guard);
let vec = unsafe { Vec::from_raw_parts(dst_buf, len, cap) };
diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs
index 1b1ef9130..25ca33c6a 100644
--- a/library/alloc/src/vec/in_place_drop.rs
+++ b/library/alloc/src/vec/in_place_drop.rs
@@ -22,3 +22,18 @@ impl<T> Drop for InPlaceDrop<T> {
}
}
}
+
+// A helper struct for in-place collection that drops the destination allocation and elements,
+// to avoid leaking them if some other destructor panics.
+pub(super) struct InPlaceDstBufDrop<T> {
+ pub(super) ptr: *mut T,
+ pub(super) len: usize,
+ pub(super) cap: usize,
+}
+
+impl<T> Drop for InPlaceDstBufDrop<T> {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe { super::Vec::from_raw_parts(self.ptr, self.len, self.cap) };
+ }
+}
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index b4157fd58..02cc7691a 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -8,7 +8,7 @@ use core::iter::{
FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce,
};
use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop, MaybeUninit};
+use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
#[cfg(not(no_global_oom_handling))]
use core::ops::Deref;
use core::ptr::{self, NonNull};
@@ -95,13 +95,16 @@ impl<T, A: Allocator> IntoIter<T, A> {
}
/// Drops remaining elements and relinquishes the backing allocation.
+ /// This method guarantees it won't panic before relinquishing
+ /// the backing allocation.
///
/// This is roughly equivalent to the following, but more efficient
///
/// ```
/// # let mut into_iter = Vec::<u8>::with_capacity(10).into_iter();
+ /// let mut into_iter = std::mem::replace(&mut into_iter, Vec::new().into_iter());
/// (&mut into_iter).for_each(core::mem::drop);
- /// unsafe { core::ptr::write(&mut into_iter, Vec::new().into_iter()); }
+ /// std::mem::forget(into_iter);
/// ```
///
/// This method is used by in-place iteration, refer to the vec::in_place_collect
@@ -118,6 +121,8 @@ impl<T, A: Allocator> IntoIter<T, A> {
self.ptr = self.buf.as_ptr();
self.end = self.buf.as_ptr();
+ // Dropping the remaining elements can panic, so this needs to be
+ // done only after updating the other fields.
unsafe {
ptr::drop_in_place(remaining);
}
@@ -149,7 +154,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
fn next(&mut self) -> Option<T> {
if self.ptr == self.end {
None
- } else if mem::size_of::<T>() == 0 {
+ } else if T::IS_ZST {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
@@ -167,7 +172,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- let exact = if mem::size_of::<T>() == 0 {
+ let exact = if T::IS_ZST {
self.end.addr().wrapping_sub(self.ptr.addr())
} else {
unsafe { self.end.sub_ptr(self.ptr) }
@@ -179,7 +184,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
let step_size = self.len().min(n);
let to_drop = ptr::slice_from_raw_parts_mut(self.ptr as *mut T, step_size);
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// SAFETY: due to unchecked casts of unsigned amounts to signed offsets the wraparound
// effectively results in unsigned pointers representing positions 0..usize::MAX,
// which is valid for ZSTs.
@@ -209,7 +214,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
let len = self.len();
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
if len < N {
self.forget_remaining_elements();
// Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct
@@ -218,7 +223,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
self.ptr = self.ptr.wrapping_byte_add(N);
// Safety: ditto
- return Ok(unsafe { MaybeUninit::array_assume_init(raw_ary) });
+ return Ok(unsafe { raw_ary.transpose().assume_init() });
}
if len < N {
@@ -236,7 +241,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
return unsafe {
ptr::copy_nonoverlapping(self.ptr, raw_ary.as_mut_ptr() as *mut T, N);
self.ptr = self.ptr.add(N);
- Ok(MaybeUninit::array_assume_init(raw_ary))
+ Ok(raw_ary.transpose().assume_init())
};
}
@@ -253,7 +258,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
// that `T: Copy` so reading elements from the buffer doesn't invalidate
// them for `Drop`.
unsafe {
- if mem::size_of::<T>() == 0 { mem::zeroed() } else { ptr::read(self.ptr.add(i)) }
+ if T::IS_ZST { mem::zeroed() } else { ptr::read(self.ptr.add(i)) }
}
}
}
@@ -264,7 +269,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
fn next_back(&mut self) -> Option<T> {
if self.end == self.ptr {
None
- } else if mem::size_of::<T>() == 0 {
+ } else if T::IS_ZST {
// See above for why 'ptr.offset' isn't used
self.end = self.end.wrapping_byte_sub(1);
@@ -280,7 +285,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
let step_size = self.len().min(n);
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// SAFETY: same as for advance_by()
self.end = self.end.wrapping_byte_sub(step_size);
} else {
diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs
index 2e025c8a4..8e652d676 100644
--- a/library/alloc/src/vec/is_zero.rs
+++ b/library/alloc/src/vec/is_zero.rs
@@ -160,3 +160,25 @@ unsafe impl<T: IsZero> IsZero for Saturating<T> {
self.0.is_zero()
}
}
+
+macro_rules! impl_for_optional_bool {
+ ($($t:ty,)+) => {$(
+ unsafe impl IsZero for $t {
+ #[inline]
+ fn is_zero(&self) -> bool {
+ // SAFETY: This is *not* a stable layout guarantee, but
+ // inside `core` we're allowed to rely on the current rustc
+ // behaviour that options of bools will be one byte with
+ // no padding, so long as they're nested less than 254 deep.
+ let raw: u8 = unsafe { core::mem::transmute(*self) };
+ raw == 0
+ }
+ }
+ )+};
+}
+impl_for_optional_bool! {
+ Option<bool>,
+ Option<Option<bool>>,
+ Option<Option<Option<bool>>>,
+ // Could go further, but not worth the metadata overhead
+}
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 60b36af5e..bbbdc3aa2 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -64,7 +64,7 @@ use core::iter;
#[cfg(not(no_global_oom_handling))]
use core::iter::FromIterator;
use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop, MaybeUninit};
+use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::ops::{self, Index, IndexMut, Range, RangeBounds};
use core::ptr::{self, NonNull};
use core::slice::{self, SliceIndex};
@@ -125,7 +125,7 @@ use self::set_len_on_drop::SetLenOnDrop;
mod set_len_on_drop;
#[cfg(not(no_global_oom_handling))]
-use self::in_place_drop::InPlaceDrop;
+use self::in_place_drop::{InPlaceDrop, InPlaceDstBufDrop};
#[cfg(not(no_global_oom_handling))]
mod in_place_drop;
@@ -483,15 +483,13 @@ impl<T> Vec<T> {
Self::with_capacity_in(capacity, Global)
}
- /// Creates a `Vec<T>` directly from the raw components of another vector.
+ /// Creates a `Vec<T>` directly from a pointer, a capacity, and a length.
///
/// # Safety
///
/// This is highly unsafe, due to the number of invariants that aren't
/// checked:
///
- /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
- /// (at least, it's highly likely to be incorrect if it wasn't).
/// * `T` needs to have the same alignment as what `ptr` was allocated with.
/// (`T` having a less strict alignment is not sufficient, the alignment really
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
@@ -500,6 +498,14 @@ impl<T> Vec<T> {
/// to be the same size as the pointer was allocated with. (Because similar to
/// alignment, [`dealloc`] must be called with the same layout `size`.)
/// * `length` needs to be less than or equal to `capacity`.
+ /// * The first `length` values must be properly initialized values of type `T`.
+ /// * `capacity` needs to be the capacity that the pointer was allocated with.
+ /// * The allocated size in bytes must be no larger than `isize::MAX`.
+ /// See the safety documentation of [`pointer::offset`].
+ ///
+ /// These requirements are always upheld by any `ptr` that has been allocated
+ /// via `Vec<T>`. Other allocation sources are allowed if the invariants are
+ /// upheld.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures. For example it is normally **not** safe
@@ -551,6 +557,32 @@ impl<T> Vec<T> {
/// assert_eq!(rebuilt, [4, 5, 6]);
/// }
/// ```
+ ///
+ /// Using memory that was allocated elsewhere:
+ ///
+ /// ```rust
+ /// #![feature(allocator_api)]
+ ///
+ /// use std::alloc::{AllocError, Allocator, Global, Layout};
+ ///
+ /// fn main() {
+ /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
+ ///
+ /// let vec = unsafe {
+ /// let mem = match Global.allocate(layout) {
+ /// Ok(mem) => mem.cast::<u32>().as_ptr(),
+ /// Err(AllocError) => return,
+ /// };
+ ///
+ /// mem.write(1_000_000);
+ ///
+ /// Vec::from_raw_parts_in(mem, 1, 16, Global)
+ /// };
+ ///
+ /// assert_eq!(vec, &[1_000_000]);
+ /// assert_eq!(vec.capacity(), 16);
+ /// }
+ /// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Self {
@@ -641,21 +673,30 @@ impl<T, A: Allocator> Vec<T, A> {
Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 }
}
- /// Creates a `Vec<T, A>` directly from the raw components of another vector.
+ /// Creates a `Vec<T, A>` directly from a pointer, a capacity, a length,
+ /// and an allocator.
///
/// # Safety
///
/// This is highly unsafe, due to the number of invariants that aren't
/// checked:
///
- /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
- /// (at least, it's highly likely to be incorrect if it wasn't).
- /// * `T` needs to have the same size and alignment as what `ptr` was allocated with.
+ /// * `T` needs to have the same alignment as what `ptr` was allocated with.
/// (`T` having a less strict alignment is not sufficient, the alignment really
/// needs to be equal to satisfy the [`dealloc`] requirement that memory must be
/// allocated and deallocated with the same layout.)
+ /// * The size of `T` times the `capacity` (ie. the allocated size in bytes) needs
+ /// to be the same size as the pointer was allocated with. (Because similar to
+ /// alignment, [`dealloc`] must be called with the same layout `size`.)
/// * `length` needs to be less than or equal to `capacity`.
- /// * `capacity` needs to be the capacity that the pointer was allocated with.
+ /// * The first `length` values must be properly initialized values of type `T`.
+ /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with.
+ /// * The allocated size in bytes must be no larger than `isize::MAX`.
+ /// See the safety documentation of [`pointer::offset`].
+ ///
+ /// These requirements are always upheld by any `ptr` that has been allocated
+ /// via `Vec<T, A>`. Other allocation sources are allowed if the invariants are
+ /// upheld.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal data structures. For example it is **not** safe
@@ -673,6 +714,7 @@ impl<T, A: Allocator> Vec<T, A> {
///
/// [`String`]: crate::string::String
/// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc
+ /// [*fit*]: crate::alloc::Allocator#memory-fitting
///
/// # Examples
///
@@ -711,6 +753,29 @@ impl<T, A: Allocator> Vec<T, A> {
/// assert_eq!(rebuilt, [4, 5, 6]);
/// }
/// ```
+ ///
+ /// Using memory that was allocated elsewhere:
+ ///
+ /// ```rust
+ /// use std::alloc::{alloc, Layout};
+ ///
+ /// fn main() {
+ /// let layout = Layout::array::<u32>(16).expect("overflow cannot happen");
+ /// let vec = unsafe {
+ /// let mem = alloc(layout).cast::<u32>();
+ /// if mem.is_null() {
+ /// return;
+ /// }
+ ///
+ /// mem.write(1_000_000);
+ ///
+ /// Vec::from_raw_parts(mem, 1, 16)
+ /// };
+ ///
+ /// assert_eq!(vec, &[1_000_000]);
+ /// assert_eq!(vec.capacity(), 16);
+ /// }
+ /// ```
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub unsafe fn from_raw_parts_in(ptr: *mut T, length: usize, capacity: usize, alloc: A) -> Self {
@@ -803,13 +868,14 @@ impl<T, A: Allocator> Vec<T, A> {
(ptr, len, capacity, alloc)
}
- /// Returns the number of elements the vector can hold without
+ /// Returns the total number of elements the vector can hold without
/// reallocating.
///
/// # Examples
///
/// ```
- /// let vec: Vec<i32> = Vec::with_capacity(10);
+ /// let mut vec: Vec<i32> = Vec::with_capacity(10);
+ /// vec.push(42);
/// assert_eq!(vec.capacity(), 10);
/// ```
#[inline]
@@ -1774,6 +1840,51 @@ impl<T, A: Allocator> Vec<T, A> {
}
}
+ /// Appends an element if there is sufficient spare capacity, otherwise an error is returned
+ /// with the element.
+ ///
+ /// Unlike [`push`] this method will not reallocate when there's insufficient capacity.
+ /// The caller should use [`reserve`] or [`try_reserve`] to ensure that there is enough capacity.
+ ///
+ /// [`push`]: Vec::push
+ /// [`reserve`]: Vec::reserve
+ /// [`try_reserve`]: Vec::try_reserve
+ ///
+ /// # Examples
+ ///
+ /// A manual, panic-free alternative to [`FromIterator`]:
+ ///
+ /// ```
+ /// #![feature(vec_push_within_capacity)]
+ ///
+ /// use std::collections::TryReserveError;
+ /// fn from_iter_fallible<T>(iter: impl Iterator<Item=T>) -> Result<Vec<T>, TryReserveError> {
+ /// let mut vec = Vec::new();
+ /// for value in iter {
+ /// if let Err(value) = vec.push_within_capacity(value) {
+ /// vec.try_reserve(1)?;
+ /// // this cannot fail, the previous line either returned or added at least 1 free slot
+ /// let _ = vec.push_within_capacity(value);
+ /// }
+ /// }
+ /// Ok(vec)
+ /// }
+ /// assert_eq!(from_iter_fallible(0..100), Ok(Vec::from_iter(0..100)));
+ /// ```
+ #[inline]
+ #[unstable(feature = "vec_push_within_capacity", issue = "100486")]
+ pub fn push_within_capacity(&mut self, value: T) -> Result<(), T> {
+ if self.len == self.buf.capacity() {
+ return Err(value);
+ }
+ unsafe {
+ let end = self.as_mut_ptr().add(self.len);
+ ptr::write(end, value);
+ self.len += 1;
+ }
+ Ok(())
+ }
+
/// Removes the last element from a vector and returns it, or [`None`] if it
/// is empty.
///
@@ -1889,9 +2000,7 @@ impl<T, A: Allocator> Vec<T, A> {
unsafe {
// set self.vec length's to start, to be safe in case Drain is leaked
self.set_len(start);
- // Use the borrow in the IterMut to indicate borrowing behavior of the
- // whole Drain iterator (like &mut T).
- let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().add(start), end - start);
+ let range_slice = slice::from_raw_parts(self.as_ptr().add(start), end - start);
Drain {
tail_start: end,
tail_len: len - end,
@@ -2083,7 +2192,6 @@ impl<T, A: Allocator> Vec<T, A> {
/// static_ref[0] += 1;
/// assert_eq!(static_ref, &[2, 2, 3]);
/// ```
- #[cfg(not(no_global_oom_handling))]
#[stable(feature = "vec_leak", since = "1.47.0")]
#[inline]
pub fn leak<'a>(self) -> &'a mut [T]
@@ -2347,7 +2455,7 @@ impl<T, A: Allocator, const N: usize> Vec<[T; N], A> {
#[unstable(feature = "slice_flatten", issue = "95629")]
pub fn into_flattened(self) -> Vec<T, A> {
let (ptr, len, cap, alloc) = self.into_raw_parts_with_alloc();
- let (new_len, new_cap) = if mem::size_of::<T>() == 0 {
+ let (new_len, new_cap) = if T::IS_ZST {
(len.checked_mul(N).expect("vec len overflow"), usize::MAX)
} else {
// SAFETY:
@@ -2677,7 +2785,7 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
let mut me = ManuallyDrop::new(self);
let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
let begin = me.as_mut_ptr();
- let end = if mem::size_of::<T>() == 0 {
+ let end = if T::IS_ZST {
begin.wrapping_byte_add(me.len())
} else {
begin.add(me.len()) as *const T
diff --git a/library/alloc/tests/autotraits.rs b/library/alloc/tests/autotraits.rs
new file mode 100644
index 000000000..8ff5f0abe
--- /dev/null
+++ b/library/alloc/tests/autotraits.rs
@@ -0,0 +1,293 @@
+fn require_sync<T: Sync>(_: T) {}
+fn require_send_sync<T: Send + Sync>(_: T) {}
+
+struct NotSend(*const ());
+unsafe impl Sync for NotSend {}
+
+#[test]
+fn test_btree_map() {
+ // Tests of this form are prone to https://github.com/rust-lang/rust/issues/64552.
+ //
+ // In theory the async block's future would be Send if the value we hold
+ // across the await point is Send, and Sync if the value we hold across the
+ // await point is Sync.
+ //
+ // We test autotraits in this convoluted way, instead of a straightforward
+ // `require_send_sync::<TypeIWantToTest>()`, because the interaction with
+ // generators exposes some current limitations in rustc's ability to prove a
+ // lifetime bound on the erased generator witness types. See the above link.
+ //
+ // A typical way this would surface in real code is:
+ //
+ // fn spawn<T: Future + Send>(_: T) {}
+ //
+ // async fn f() {
+ // let map = BTreeMap::<u32, Box<dyn Send + Sync>>::new();
+ // for _ in &map {
+ // async {}.await;
+ // }
+ // }
+ //
+ // fn main() {
+ // spawn(f());
+ // }
+ //
+ // where with some unintentionally overconstrained Send impls in liballoc's
+ // internals, the future might incorrectly not be Send even though every
+ // single type involved in the program is Send and Sync.
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ // Testing like this would not catch all issues that the above form catches.
+ require_send_sync(None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>);
+
+ require_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, u32, NotSend>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::BTreeMap<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<
+ alloc::collections::btree_map::DrainFilter<
+ '_,
+ &u32,
+ &u32,
+ fn(&&u32, &mut &u32) -> bool,
+ >,
+ >;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Entry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoIter<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoKeys<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IntoValues<&u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Iter<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::IterMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Keys<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::OccupiedEntry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::OccupiedError<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Range<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::RangeMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::VacantEntry<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::Values<'_, &u32, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_map::ValuesMut<'_, &u32, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_btree_set() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::BTreeSet<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Difference<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::DrainFilter<'_, &u32, fn(&&u32) -> bool>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Intersection<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Range<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::SymmetricDifference<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::btree_set::Union<'_, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_binary_heap() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::BinaryHeap<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::Drain<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::DrainSorted<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::IntoIterSorted<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::binary_heap::PeekMut<'_, &u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_linked_list() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::Cursor<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::CursorMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ // FIXME
+ /*
+ require_send_sync(async {
+ let _v =
+ None::<alloc::collections::linked_list::DrainFilter<'_, &u32, fn(&mut &u32) -> bool>>;
+ async {}.await;
+ });
+ */
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::IterMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::linked_list::LinkedList<&u32>>;
+ async {}.await;
+ });
+}
+
+#[test]
+fn test_vec_deque() {
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::Drain<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::IntoIter<&u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::Iter<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::IterMut<'_, &u32>>;
+ async {}.await;
+ });
+
+ require_send_sync(async {
+ let _v = None::<alloc::collections::vec_deque::VecDeque<&u32>>;
+ async {}.await;
+ });
+}
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 490c0d8f7..ffc5ca7a5 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -2,6 +2,7 @@
#![feature(alloc_layout_extra)]
#![feature(assert_matches)]
#![feature(box_syntax)]
+#![feature(btree_drain_filter)]
#![feature(cow_is_borrowed)]
#![feature(const_box)]
#![feature(const_convert)]
@@ -14,6 +15,8 @@
#![feature(core_intrinsics)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
+#![feature(linked_list_cursors)]
+#![feature(map_try_insert)]
#![feature(new_uninit)]
#![feature(pattern)]
#![feature(trusted_len)]
@@ -32,7 +35,7 @@
#![feature(slice_group_by)]
#![feature(slice_partition_dedup)]
#![feature(string_remove_matches)]
-#![feature(const_btree_new)]
+#![feature(const_btree_len)]
#![feature(const_default_impls)]
#![feature(const_trait_impl)]
#![feature(const_str_from_utf8)]
@@ -41,7 +44,6 @@
#![feature(pointer_is_aligned)]
#![feature(slice_flatten)]
#![feature(thin_box)]
-#![feature(bench_black_box)]
#![feature(strict_provenance)]
#![feature(once_cell)]
#![feature(drain_keep_rest)]
@@ -50,6 +52,7 @@ use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
mod arc;
+mod autotraits;
mod borrow;
mod boxed;
mod btree_set_hash;
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index f140fc414..e02711870 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1191,48 +1191,53 @@ fn test_from_iter_specialization_panic_during_iteration_drops() {
}
#[test]
-fn test_from_iter_specialization_panic_during_drop_leaks() {
- static mut DROP_COUNTER: usize = 0;
+fn test_from_iter_specialization_panic_during_drop_doesnt_leak() {
+ static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5];
+ static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2];
#[derive(Debug)]
- enum Droppable {
- DroppedTwice(Box<i32>),
- PanicOnDrop,
- }
+ struct Old(usize);
- impl Drop for Droppable {
+ impl Drop for Old {
fn drop(&mut self) {
- match self {
- Droppable::DroppedTwice(_) => {
- unsafe {
- DROP_COUNTER += 1;
- }
- println!("Dropping!")
- }
- Droppable::PanicOnDrop => {
- if !std::thread::panicking() {
- panic!();
- }
- }
+ unsafe {
+ DROP_COUNTER_OLD[self.0] += 1;
+ }
+
+ if self.0 == 3 {
+ panic!();
}
+
+ println!("Dropped Old: {}", self.0);
}
}
- let mut to_free: *mut Droppable = core::ptr::null_mut();
- let mut cap = 0;
+ #[derive(Debug)]
+ struct New(usize);
+
+ impl Drop for New {
+ fn drop(&mut self) {
+ unsafe {
+ DROP_COUNTER_NEW[self.0] += 1;
+ }
+
+ println!("Dropped New: {}", self.0);
+ }
+ }
let _ = std::panic::catch_unwind(AssertUnwindSafe(|| {
- let mut v = vec![Droppable::DroppedTwice(Box::new(123)), Droppable::PanicOnDrop];
- to_free = v.as_mut_ptr();
- cap = v.capacity();
- let _ = v.into_iter().take(0).collect::<Vec<_>>();
+ let v = vec![Old(0), Old(1), Old(2), Old(3), Old(4)];
+ let _ = v.into_iter().map(|x| New(x.0)).take(2).collect::<Vec<_>>();
}));
- assert_eq!(unsafe { DROP_COUNTER }, 1);
- // clean up the leak to keep miri happy
- unsafe {
- drop(Vec::from_raw_parts(to_free, 0, cap));
- }
+ assert_eq!(unsafe { DROP_COUNTER_OLD[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[1] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[2] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[3] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_OLD[4] }, 1);
+
+ assert_eq!(unsafe { DROP_COUNTER_NEW[0] }, 1);
+ assert_eq!(unsafe { DROP_COUNTER_NEW[1] }, 1);
}
// regression test for issue #85322. Peekable previously implemented InPlaceIterable,
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 0abe20e4c..38887f29a 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -1,4 +1,6 @@
use core::iter::*;
+use core::mem;
+use core::num::Wrapping;
use test::{black_box, Bencher};
#[bench]
@@ -364,6 +366,13 @@ fn bench_partial_cmp(b: &mut Bencher) {
}
#[bench]
+fn bench_chain_partial_cmp(b: &mut Bencher) {
+ b.iter(|| {
+ (0..50000).chain(50000..100000).map(black_box).partial_cmp((0..100000).map(black_box))
+ })
+}
+
+#[bench]
fn bench_lt(b: &mut Bencher) {
b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box)))
}
@@ -391,3 +400,21 @@ fn bench_trusted_random_access_adapters(b: &mut Bencher) {
acc
})
}
+
+/// Exercises the iter::Copied specialization for slice::Iter
+#[bench]
+fn bench_copied_array_chunks(b: &mut Bencher) {
+ let v = vec![1u8; 1024];
+
+ b.iter(|| {
+ black_box(&v)
+ .iter()
+ .copied()
+ .array_chunks::<{ mem::size_of::<u64>() }>()
+ .map(|ary| {
+ let d = u64::from_ne_bytes(ary);
+ Wrapping(d.rotate_left(7).wrapping_add(1))
+ })
+ .sum::<Wrapping<u64>>()
+ })
+}
diff --git a/library/core/benches/lib.rs b/library/core/benches/lib.rs
index a6c174d2f..1e462e3fc 100644
--- a/library/core/benches/lib.rs
+++ b/library/core/benches/lib.rs
@@ -4,6 +4,7 @@
#![feature(int_log)]
#![feature(test)]
#![feature(trusted_random_access)]
+#![feature(iter_array_chunks)]
extern crate test;
diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs
index f03502429..920e559cc 100644
--- a/library/core/src/alloc/layout.rs
+++ b/library/core/src/alloc/layout.rs
@@ -5,7 +5,6 @@
// Your performance intuition is useless. Run perf.
use crate::cmp;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
use crate::mem::{self, ValidAlign};
@@ -65,6 +64,7 @@ impl Layout {
#[stable(feature = "alloc_layout", since = "1.28.0")]
#[rustc_const_stable(feature = "const_alloc_layout_size_align", since = "1.50.0")]
#[inline]
+ #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutError> {
if !align.is_power_of_two() {
return Err(LayoutError);
@@ -114,6 +114,7 @@ impl Layout {
#[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")]
#[must_use]
#[inline]
+ #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
// SAFETY: the caller is required to uphold the preconditions.
unsafe { Layout { size, align: ValidAlign::new_unchecked(align) } }
@@ -134,6 +135,7 @@ impl Layout {
#[must_use = "this returns the minimum alignment, \
without modifying the layout"]
#[inline]
+ #[rustc_allow_const_fn_unstable(ptr_alignment_type)]
pub const fn align(&self) -> usize {
self.align.as_usize()
}
@@ -463,7 +465,6 @@ pub type LayoutErr = LayoutError;
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct LayoutError;
-#[cfg(not(bootstrap))]
#[stable(feature = "alloc_layout", since = "1.28.0")]
impl Error for LayoutError {}
diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs
index 94efa7666..a4bf6a853 100644
--- a/library/core/src/alloc/mod.rs
+++ b/library/core/src/alloc/mod.rs
@@ -21,7 +21,6 @@ pub use self::layout::LayoutErr;
#[stable(feature = "alloc_layout_error", since = "1.50.0")]
pub use self::layout::LayoutError;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
use crate::ptr::{self, NonNull};
@@ -34,7 +33,6 @@ use crate::ptr::{self, NonNull};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct AllocError;
-#[cfg(not(bootstrap))]
#[unstable(
feature = "allocator_api",
reason = "the precise API and guarantees it provides may be tweaked.",
@@ -107,6 +105,7 @@ impl fmt::Display for AllocError {
///
/// [*currently allocated*]: #currently-allocated-memory
#[unstable(feature = "allocator_api", issue = "32838")]
+#[const_trait]
pub unsafe trait Allocator {
/// Attempts to allocate a block of memory.
///
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index f4885ed9f..b91c63018 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -1,10 +1,10 @@
//! Defines the `IntoIter` owned iterator for arrays.
use crate::{
- cmp, fmt,
+ fmt,
iter::{self, ExactSizeIterator, FusedIterator, TrustedLen},
mem::{self, MaybeUninit},
- ops::Range,
+ ops::{IndexRange, Range},
ptr,
};
@@ -29,9 +29,10 @@ pub struct IntoIter<T, const N: usize> {
/// The elements in `data` that have not been yielded yet.
///
/// Invariants:
- /// - `alive.start <= alive.end`
/// - `alive.end <= N`
- alive: Range<usize>,
+ ///
+ /// (And the `IndexRange` type requires `alive.start <= alive.end`.)
+ alive: IndexRange,
}
// Note: the `#[rustc_skip_array_during_method_dispatch]` on `trait IntoIterator`
@@ -69,7 +70,7 @@ impl<T, const N: usize> IntoIterator for [T; N] {
// Until then, we can use `mem::transmute_copy` to create a bitwise copy
// as a different type, then forget `array` so that it is not dropped.
unsafe {
- let iter = IntoIter { data: mem::transmute_copy(&self), alive: 0..N };
+ let iter = IntoIter { data: mem::transmute_copy(&self), alive: IndexRange::zero_to(N) };
mem::forget(self);
iter
}
@@ -103,8 +104,7 @@ impl<T, const N: usize> IntoIter<T, N> {
///
/// ```
/// #![feature(array_into_iter_constructors)]
- ///
- /// #![feature(maybe_uninit_array_assume_init)]
+ /// #![feature(maybe_uninit_uninit_array_transpose)]
/// #![feature(maybe_uninit_uninit_array)]
/// use std::array::IntoIter;
/// use std::mem::MaybeUninit;
@@ -133,7 +133,7 @@ impl<T, const N: usize> IntoIter<T, N> {
/// }
///
/// // SAFETY: We've initialized all N items
- /// unsafe { Ok(MaybeUninit::array_assume_init(buffer)) }
+ /// unsafe { Ok(buffer.transpose().assume_init()) }
/// }
///
/// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap();
@@ -147,7 +147,9 @@ impl<T, const N: usize> IntoIter<T, N> {
buffer: [MaybeUninit<T>; N],
initialized: Range<usize>,
) -> Self {
- Self { data: buffer, alive: initialized }
+ // SAFETY: one of our safety conditions is that the range is canonical.
+ let alive = unsafe { IndexRange::new_unchecked(initialized.start, initialized.end) };
+ Self { data: buffer, alive }
}
/// Creates an iterator over `T` which returns no elements.
@@ -283,16 +285,11 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
}
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
- let len = self.len();
-
- // The number of elements to drop. Always in-bounds by construction.
- let delta = cmp::min(n, len);
+ let original_len = self.len();
- let range_to_drop = self.alive.start..(self.alive.start + delta);
-
- // Moving the start marks them as conceptually "dropped", so if anything
- // goes bad then our drop impl won't double-free them.
- self.alive.start += delta;
+ // This also moves the start, which marks them as conceptually "dropped",
+ // so if anything goes bad then our drop impl won't double-free them.
+ let range_to_drop = self.alive.take_prefix(n);
// SAFETY: These elements are currently initialized, so it's fine to drop them.
unsafe {
@@ -300,7 +297,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
}
- if n > len { Err(len) } else { Ok(()) }
+ if n > original_len { Err(original_len) } else { Ok(()) }
}
}
@@ -338,16 +335,11 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
}
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
- let len = self.len();
-
- // The number of elements to drop. Always in-bounds by construction.
- let delta = cmp::min(n, len);
-
- let range_to_drop = (self.alive.end - delta)..self.alive.end;
+ let original_len = self.len();
- // Moving the end marks them as conceptually "dropped", so if anything
- // goes bad then our drop impl won't double-free them.
- self.alive.end -= delta;
+ // This also moves the end, which marks them as conceptually "dropped",
+ // so if anything goes bad then our drop impl won't double-free them.
+ let range_to_drop = self.alive.take_suffix(n);
// SAFETY: These elements are currently initialized, so it's fine to drop them.
unsafe {
@@ -355,7 +347,7 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(slice));
}
- if n > len { Err(len) } else { Ok(()) }
+ if n > original_len { Err(original_len) } else { Ok(()) }
}
}
@@ -372,9 +364,7 @@ impl<T, const N: usize> Drop for IntoIter<T, N> {
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
fn len(&self) -> usize {
- // Will never underflow due to the invariant `alive.start <=
- // alive.end`.
- self.alive.end - self.alive.start
+ self.alive.len()
}
fn is_empty(&self) -> bool {
self.alive.is_empty()
@@ -396,14 +386,15 @@ impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
fn clone(&self) -> Self {
// Note, we don't really need to match the exact same alive range, so
// we can just clone into offset 0 regardless of where `self` is.
- let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };
+ let mut new = Self { data: MaybeUninit::uninit_array(), alive: IndexRange::zero_to(0) };
// Clone all alive elements.
for (src, dst) in iter::zip(self.as_slice(), &mut new.data) {
// Write a clone into the new array, then update its alive range.
// If cloning panics, we'll correctly drop the previous items.
dst.write(src.clone());
- new.alive.end += 1;
+ // This addition cannot overflow as we're iterating a slice
+ new.alive = IndexRange::zero_to(new.alive.end() + 1);
}
new
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 9effb3790..eae0e1c76 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -7,7 +7,6 @@
use crate::borrow::{Borrow, BorrowMut};
use crate::cmp::Ordering;
use crate::convert::{Infallible, TryFrom};
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
use crate::hash::{self, Hash};
@@ -33,6 +32,10 @@ pub use iter::IntoIter;
/// # Example
///
/// ```rust
+/// // type inference is helping us here, the way `from_fn` knows how many
+/// // elements to produce is the length of array down there: only arrays of
+/// // equal lengths can be compared, so the const generic parameter `N` is
+/// // inferred to be 5, thus creating array of 5 elements.
/// let array = core::array::from_fn(|i| i);
/// assert_eq!(array, [0, 1, 2, 3, 4]);
/// ```
@@ -121,7 +124,6 @@ impl fmt::Display for TryFromSliceError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "try_from", since = "1.34.0")]
impl Error for TryFromSliceError {
#[allow(deprecated)]
@@ -184,6 +186,18 @@ impl<T, const N: usize> const BorrowMut<[T]> for [T; N] {
}
}
+/// Tries to create an array `[T; N]` by copying from a slice `&[T]`. Succeeds if
+/// `slice.len() == N`.
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(bytes_head));
+///
+/// let bytes_tail: [u8; 2] = bytes[1..3].try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
+/// ```
#[stable(feature = "try_from", since = "1.34.0")]
impl<T, const N: usize> TryFrom<&[T]> for [T; N]
where
@@ -196,6 +210,18 @@ where
}
}
+/// Tries to create an array `[T; N]` by copying from a mutable slice `&mut [T]`.
+/// Succeeds if `slice.len() == N`.
+///
+/// ```
+/// let mut bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: [u8; 2] = <[u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(bytes_head));
+///
+/// let bytes_tail: [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(bytes_tail));
+/// ```
#[stable(feature = "try_from_mut_slice_to_array", since = "1.59.0")]
impl<T, const N: usize> TryFrom<&mut [T]> for [T; N]
where
@@ -208,6 +234,18 @@ where
}
}
+/// Tries to create an array ref `&[T; N]` from a slice ref `&[T]`. Succeeds if
+/// `slice.len() == N`.
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: &[u8; 2] = <&[u8; 2]>::try_from(&bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
+///
+/// let bytes_tail: &[u8; 2] = bytes[1..3].try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
+/// ```
#[stable(feature = "try_from", since = "1.34.0")]
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
type Error = TryFromSliceError;
@@ -223,6 +261,18 @@ impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
}
}
+/// Tries to create a mutable array ref `&mut [T; N]` from a mutable slice ref
+/// `&mut [T]`. Succeeds if `slice.len() == N`.
+///
+/// ```
+/// let mut bytes: [u8; 3] = [1, 0, 2];
+///
+/// let bytes_head: &mut [u8; 2] = <&mut [u8; 2]>::try_from(&mut bytes[0..2]).unwrap();
+/// assert_eq!(1, u16::from_le_bytes(*bytes_head));
+///
+/// let bytes_tail: &mut [u8; 2] = (&mut bytes[1..3]).try_into().unwrap();
+/// assert_eq!(512, u16::from_le_bytes(*bytes_tail));
+/// ```
#[stable(feature = "try_from", since = "1.34.0")]
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
type Error = TryFromSliceError;
@@ -386,7 +436,8 @@ impl<T: Copy> SpecArrayClone for T {
macro_rules! array_impl_default {
{$n:expr, $t:ident $($ts:ident)*} => {
#[stable(since = "1.4.0", feature = "array_default")]
- impl<T> Default for [T; $n] where T: Default {
+ #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+ impl<T> const Default for [T; $n] where T: ~const Default {
fn default() -> [T; $n] {
[$t::default(), $($ts::default()),*]
}
@@ -865,7 +916,7 @@ where
mem::forget(guard);
// SAFETY: All elements of the array were populated in the loop above.
- let output = unsafe { MaybeUninit::array_assume_init(array) };
+ let output = unsafe { array.transpose().assume_init() };
Ok(Try::from_output(output))
}
diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index 7667a6508..db1c505ba 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -18,6 +18,18 @@ impl bool {
/// assert_eq!(false.then_some(0), None);
/// assert_eq!(true.then_some(0), Some(0));
/// ```
+ ///
+ /// ```
+ /// let mut a = 0;
+ /// let mut function_with_side_effects = || { a += 1; };
+ ///
+ /// true.then_some(function_with_side_effects());
+ /// false.then_some(function_with_side_effects());
+ ///
+ /// // `a` is incremented twice because the value passed to `then_some` is
+ /// // evaluated eagerly.
+ /// assert_eq!(a, 2);
+ /// ```
#[stable(feature = "bool_to_option", since = "1.62.0")]
#[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")]
#[inline]
@@ -37,6 +49,17 @@ impl bool {
/// assert_eq!(false.then(|| 0), None);
/// assert_eq!(true.then(|| 0), Some(0));
/// ```
+ ///
+ /// ```
+ /// let mut a = 0;
+ ///
+ /// true.then(|| { a += 1; });
+ /// false.then(|| { a += 1; });
+ ///
+ /// // `a` is incremented once because the closure is evaluated lazily by
+ /// // `then`.
+ /// assert_eq!(a, 1);
+ /// ```
#[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
#[rustc_const_unstable(feature = "const_bool_to_option", issue = "91917")]
#[inline]
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index 8378611eb..fdd56cb4e 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -154,6 +154,7 @@
/// [`String`]: ../../std/string/struct.String.html
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Borrow"]
+#[const_trait]
pub trait Borrow<Borrowed: ?Sized> {
/// Immutably borrows from an owned value.
///
@@ -184,6 +185,7 @@ pub trait Borrow<Borrowed: ?Sized> {
/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
/// for more information on borrowing as another type.
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
/// Mutably borrows from an owned value.
///
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index fb4454c94..7bf32cb0d 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -405,6 +405,7 @@ impl<T> Cell<T> {
/// assert_eq!(cell.replace(10), 5);
/// assert_eq!(cell.get(), 10);
/// ```
+ #[inline]
#[stable(feature = "move_cell", since = "1.17.0")]
pub fn replace(&self, val: T) -> T {
// SAFETY: This can cause data races if called from a separate thread,
@@ -614,6 +615,7 @@ impl<T, const N: usize> Cell<[T; N]> {
/// A mutable memory location with dynamically checked borrow rules
///
/// See the [module-level documentation](self) for more.
+#[cfg_attr(not(test), rustc_diagnostic_item = "RefCell")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RefCell<T: ?Sized> {
borrow: Cell<BorrowFlag>,
@@ -1021,15 +1023,18 @@ impl<T: ?Sized> RefCell<T> {
/// Returns a mutable reference to the underlying data.
///
- /// This call borrows `RefCell` mutably (at compile-time) so there is no
- /// need for dynamic checks.
+ /// Since this method borrows `RefCell` mutably, it is statically guaranteed
+ /// that no borrows to the underlying data exist. The dynamic checks inherent
+ /// in [`borrow_mut`] and most other methods of `RefCell` are therefor
+ /// unnecessary.
///
- /// However be cautious: this method expects `self` to be mutable, which is
- /// generally not the case when using a `RefCell`. Take a look at the
- /// [`borrow_mut`] method instead if `self` isn't mutable.
+ /// This method can only be called if `RefCell` can be mutably borrowed,
+ /// which in general is only the case directly after the `RefCell` has
+ /// been created. In these situations, skipping the aforementioned dynamic
+ /// borrowing checks may yield better ergonomics and runtime-performance.
///
- /// Also, please be aware that this method is only for special circumstances and is usually
- /// not what you want. In case of doubt, use [`borrow_mut`] instead.
+ /// In most situations where `RefCell` is used, it can't be borrowed mutably.
+ /// Use [`borrow_mut`] to get mutable access to the underlying data then.
///
/// [`borrow_mut`]: RefCell::borrow_mut()
///
@@ -1811,6 +1816,61 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
///
/// [`.get_mut()`]: `UnsafeCell::get_mut`
///
+/// # Memory layout
+///
+/// `UnsafeCell<T>` has the same in-memory representation as its inner type `T`. A consequence
+/// of this guarantee is that it is possible to convert between `T` and `UnsafeCell<T>`.
+/// Special care has to be taken when converting a nested `T` inside of an `Outer<T>` type
+/// to an `Outer<UnsafeCell<T>>` type: this is not sound when the `Outer<T>` type enables [niche]
+/// optimizations. For example, the type `Option<NonNull<u8>>` is typically 8 bytes large on
+/// 64-bit platforms, but the type `Option<UnsafeCell<NonNull<u8>>>` takes up 16 bytes of space.
+/// Therefore this is not a valid conversion, despite `NonNull<u8>` and `UnsafeCell<NonNull<u8>>>`
+/// having the same memory layout. This is because `UnsafeCell` disables niche optimizations in
+/// order to avoid its interior mutability property from spreading from `T` into the `Outer` type,
+/// thus this can cause distortions in the type size in these cases.
+///
+/// Note that the only valid way to obtain a `*mut T` pointer to the contents of a
+/// _shared_ `UnsafeCell<T>` is through [`.get()`] or [`.raw_get()`]. A `&mut T` reference
+/// can be obtained by either dereferencing this pointer or by calling [`.get_mut()`]
+/// on an _exclusive_ `UnsafeCell<T>`. Even though `T` and `UnsafeCell<T>` have the
+/// same memory layout, the following is not allowed and undefined behavior:
+///
+/// ```rust,no_run
+/// # use std::cell::UnsafeCell;
+/// unsafe fn not_allowed<T>(ptr: &UnsafeCell<T>) -> &mut T {
+/// let t = ptr as *const UnsafeCell<T> as *mut T;
+/// // This is undefined behavior, because the `*mut T` pointer
+/// // was not obtained through `.get()` nor `.raw_get()`:
+/// unsafe { &mut *t }
+/// }
+/// ```
+///
+/// Instead, do this:
+///
+/// ```rust
+/// # use std::cell::UnsafeCell;
+/// // Safety: the caller must ensure that there are no references that
+/// // point to the *contents* of the `UnsafeCell`.
+/// unsafe fn get_mut<T>(ptr: &UnsafeCell<T>) -> &mut T {
+/// unsafe { &mut *ptr.get() }
+/// }
+/// ```
+///
+/// Coverting in the other direction from a `&mut T`
+/// to an `&UnsafeCell<T>` is allowed:
+///
+/// ```rust
+/// # use std::cell::UnsafeCell;
+/// fn get_shared<T>(ptr: &mut T) -> &UnsafeCell<T> {
+/// let t = ptr as *mut T as *const UnsafeCell<T>;
+/// // SAFETY: `T` and `UnsafeCell<T>` have the same memory layout
+/// unsafe { &*t }
+/// }
+/// ```
+///
+/// [niche]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#niche
+/// [`.raw_get()`]: `UnsafeCell::raw_get`
+///
/// # Examples
///
/// Here is an example showcasing how to soundly mutate the contents of an `UnsafeCell<_>` despite
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index dc8ea66cc..11f1c30f6 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -1,6 +1,5 @@
//! UTF-8 and UTF-16 decoding iterators
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
@@ -124,7 +123,6 @@ impl fmt::Display for DecodeUtf16Error {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "decode_utf16", since = "1.9.0")]
impl Error for DecodeUtf16Error {
#[allow(deprecated)]
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index b7a63b7c6..bb8359936 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -597,9 +597,14 @@ impl char {
/// Returns the number of 16-bit code units this `char` would need if
/// encoded in UTF-16.
///
+ /// That number of code units is always either 1 or 2, for unicode scalar values in
+ /// the [basic multilingual plane] or [supplementary planes] respectively.
+ ///
/// See the documentation for [`len_utf8()`] for more explanation of this
/// concept. This function is a mirror, but for UTF-16 instead of UTF-8.
///
+ /// [basic multilingual plane]: http://www.unicode.org/glossary/#basic_multilingual_plane
+ /// [supplementary planes]: http://www.unicode.org/glossary/#supplementary_planes
/// [`len_utf8()`]: #method.len_utf8
///
/// # Examples
@@ -1444,6 +1449,38 @@ impl char {
matches!(*self, '0'..='9')
}
+ /// Checks if the value is an ASCII octal digit:
+ /// U+0030 '0' ..= U+0037 '7'.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_ascii_octdigit)]
+ ///
+ /// let uppercase_a = 'A';
+ /// let a = 'a';
+ /// let zero = '0';
+ /// let seven = '7';
+ /// let nine = '9';
+ /// let percent = '%';
+ /// let lf = '\n';
+ ///
+ /// assert!(!uppercase_a.is_ascii_octdigit());
+ /// assert!(!a.is_ascii_octdigit());
+ /// assert!(zero.is_ascii_octdigit());
+ /// assert!(seven.is_ascii_octdigit());
+ /// assert!(!nine.is_ascii_octdigit());
+ /// assert!(!percent.is_ascii_octdigit());
+ /// assert!(!lf.is_ascii_octdigit());
+ /// ```
+ #[must_use]
+ #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
+ #[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
+ #[inline]
+ pub const fn is_ascii_octdigit(&self) -> bool {
+ matches!(*self, '0'..='7')
+ }
+
/// Checks if the value is an ASCII hexadecimal digit:
///
/// - U+0030 '0' ..= U+0039 '9', or
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 72d63ac4b..b34a71216 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -38,7 +38,6 @@ pub use self::methods::encode_utf16_raw;
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
pub use self::methods::encode_utf8_raw;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt::{self, Write};
use crate::iter::FusedIterator;
@@ -587,6 +586,5 @@ impl fmt::Display for TryFromCharError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "u8_from_char", since = "1.59.0")]
impl Error for TryFromCharError {}
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index d9f2d3d64..f0fa2e1d2 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -22,6 +22,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
+use crate::const_closure::ConstFnMutClosure;
use crate::marker::Destruct;
use crate::marker::StructuralPartialEq;
@@ -204,20 +205,10 @@ use self::Ordering::*;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "==")]
#[doc(alias = "!=")]
-#[cfg_attr(
- bootstrap,
- rustc_on_unimplemented(
- message = "can't compare `{Self}` with `{Rhs}`",
- label = "no implementation for `{Self} == {Rhs}`"
- )
-)]
-#[cfg_attr(
- not(bootstrap),
- rustc_on_unimplemented(
- message = "can't compare `{Self}` with `{Rhs}`",
- label = "no implementation for `{Self} == {Rhs}`",
- append_const_msg,
- )
+#[rustc_on_unimplemented(
+ message = "can't compare `{Self}` with `{Rhs}`",
+ label = "no implementation for `{Self} == {Rhs}`",
+ append_const_msg
)]
#[const_trait]
#[rustc_diagnostic_item = "PartialEq"]
@@ -1076,20 +1067,10 @@ impl const PartialOrd for Ordering {
#[doc(alias = "<")]
#[doc(alias = "<=")]
#[doc(alias = ">=")]
-#[cfg_attr(
- bootstrap,
- rustc_on_unimplemented(
- message = "can't compare `{Self}` with `{Rhs}`",
- label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
- )
-)]
-#[cfg_attr(
- not(bootstrap),
- rustc_on_unimplemented(
- message = "can't compare `{Self}` with `{Rhs}`",
- label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
- append_const_msg,
- )
+#[rustc_on_unimplemented(
+ message = "can't compare `{Self}` with `{Rhs}`",
+ label = "no implementation for `{Self} < {Rhs}` and `{Self} > {Rhs}`",
+ append_const_msg
)]
#[const_trait]
#[rustc_diagnostic_item = "PartialOrd"]
@@ -1242,7 +1223,12 @@ 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")]
-pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
+#[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,
+{
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v1,
Ordering::Greater => v2,
@@ -1264,8 +1250,24 @@ pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-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)))
+#[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,
+{
+ 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))
}
/// Compares and returns the maximum of two values.
@@ -1306,7 +1308,12 @@ 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")]
-pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
+#[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,
+{
match compare(&v1, &v2) {
Ordering::Less | Ordering::Equal => v2,
Ordering::Greater => v1,
@@ -1328,8 +1335,24 @@ pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
#[inline]
#[must_use]
#[stable(feature = "cmp_min_max_by", since = "1.53.0")]
-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)))
+#[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))
}
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
diff --git a/library/core/src/const_closure.rs b/library/core/src/const_closure.rs
new file mode 100644
index 000000000..9e9c02093
--- /dev/null
+++ b/library/core/src/const_closure.rs
@@ -0,0 +1,77 @@
+use crate::marker::Destruct;
+
+/// 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, 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, 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 05637c166..33493964b 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -25,6 +25,7 @@
//! # Generic Implementations
//!
//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
+//! (but not generally for all [dereferenceable types][core::ops::Deref])
//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
//! - [`From`] and [`Into`] are reflexive, which means that all types can
@@ -34,7 +35,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
use crate::hash::{Hash, Hasher};
@@ -110,10 +110,12 @@ pub const fn identity<T>(x: T) -> T {
/// If you need to do a costly conversion it is better to implement [`From`] with type
/// `&T` or write a custom function.
///
+/// # Relation to `Borrow`
+///
/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in a few aspects:
///
/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
-/// a reference or a value.
+/// a reference or a value. (See also note on `AsRef`'s reflexibility below.)
/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for a borrowed value are
/// equivalent to those of the owned value. For this reason, if you want to
/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
@@ -123,9 +125,66 @@ pub const fn identity<T>(x: T) -> T {
///
/// # Generic Implementations
///
-/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
-/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
-/// `&mut Foo` or `&&mut Foo`)
+/// `AsRef` auto-dereferences if the inner type is a reference or a mutable reference
+/// (e.g.: `foo.as_ref()` will work the same if `foo` has type `&mut Foo` or `&&mut Foo`).
+///
+/// Note that due to historic reasons, the above currently does not hold generally for all
+/// [dereferenceable types], e.g. `foo.as_ref()` will *not* work the same as
+/// `Box::new(foo).as_ref()`. Instead, many smart pointers provide an `as_ref` implementation which
+/// simply returns a reference to the [pointed-to value] (but do not perform a cheap
+/// reference-to-reference conversion for that value). However, [`AsRef::as_ref`] should not be
+/// used for the sole purpose of dereferencing; instead ['`Deref` coercion'] can be used:
+///
+/// [dereferenceable types]: core::ops::Deref
+/// [pointed-to value]: core::ops::Deref::Target
+/// ['`Deref` coercion']: core::ops::Deref#more-on-deref-coercion
+///
+/// ```
+/// let x = Box::new(5i32);
+/// // Avoid this:
+/// // let y: &i32 = x.as_ref();
+/// // Better just write:
+/// let y: &i32 = &x;
+/// ```
+///
+/// Types which implement [`Deref`] should consider implementing `AsRef<T>` as follows:
+///
+/// [`Deref`]: core::ops::Deref
+///
+/// ```
+/// # use core::ops::Deref;
+/// # struct SomeType;
+/// # impl Deref for SomeType {
+/// # type Target = [u8];
+/// # fn deref(&self) -> &[u8] {
+/// # &[]
+/// # }
+/// # }
+/// impl<T> AsRef<T> for SomeType
+/// where
+/// T: ?Sized,
+/// <SomeType as Deref>::Target: AsRef<T>,
+/// {
+/// fn as_ref(&self) -> &T {
+/// self.deref().as_ref()
+/// }
+/// }
+/// ```
+///
+/// # Reflexivity
+///
+/// Ideally, `AsRef` would be reflexive, i.e. there would be an `impl<T: ?Sized> AsRef<T> for T`
+/// with [`as_ref`] simply returning its argument unchanged.
+/// Such a blanket implementation is currently *not* provided due to technical restrictions of
+/// Rust's type system (it would be overlapping with another existing blanket implementation for
+/// `&T where T: AsRef<U>` which allows `AsRef` to auto-dereference, see "Generic Implementations"
+/// above).
+///
+/// [`as_ref`]: AsRef::as_ref
+///
+/// A trivial implementation of `AsRef<T> for T` must be added explicitly for a particular type `T`
+/// where needed or desired. Note, however, that not all types from `std` contain such an
+/// implementation, and those cannot be added by external code due to orphan rules.
///
/// # Examples
///
@@ -155,6 +214,7 @@ pub const fn identity<T>(x: T) -> T {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "AsRef")]
+#[const_trait]
pub trait AsRef<T: ?Sized> {
/// Converts this type into a shared reference of the (usually inferred) input type.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -172,31 +232,141 @@ pub trait AsRef<T: ?Sized> {
///
/// # Generic Implementations
///
-/// - `AsMut` auto-dereferences if the inner type is a mutable reference
-/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo`
-/// or `&mut &mut Foo`)
+/// `AsMut` auto-dereferences if the inner type is a mutable reference
+/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo` or `&mut &mut Foo`).
+///
+/// Note that due to historic reasons, the above currently does not hold generally for all
+/// [mutably dereferenceable types], e.g. `foo.as_mut()` will *not* work the same as
+/// `Box::new(foo).as_mut()`. Instead, many smart pointers provide an `as_mut` implementation which
+/// simply returns a reference to the [pointed-to value] (but do not perform a cheap
+/// reference-to-reference conversion for that value). However, [`AsMut::as_mut`] should not be
+/// used for the sole purpose of mutable dereferencing; instead ['`Deref` coercion'] can be used:
+///
+/// [mutably dereferenceable types]: core::ops::DerefMut
+/// [pointed-to value]: core::ops::Deref::Target
+/// ['`Deref` coercion']: core::ops::DerefMut#more-on-deref-coercion
+///
+/// ```
+/// let mut x = Box::new(5i32);
+/// // Avoid this:
+/// // let y: &mut i32 = x.as_mut();
+/// // Better just write:
+/// let y: &mut i32 = &mut x;
+/// ```
+///
+/// Types which implement [`DerefMut`] should consider to add an implementation of `AsMut<T>` as
+/// follows:
+///
+/// [`DerefMut`]: core::ops::DerefMut
+///
+/// ```
+/// # use core::ops::{Deref, DerefMut};
+/// # struct SomeType;
+/// # impl Deref for SomeType {
+/// # type Target = [u8];
+/// # fn deref(&self) -> &[u8] {
+/// # &[]
+/// # }
+/// # }
+/// # impl DerefMut for SomeType {
+/// # fn deref_mut(&mut self) -> &mut [u8] {
+/// # &mut []
+/// # }
+/// # }
+/// impl<T> AsMut<T> for SomeType
+/// where
+/// <SomeType as Deref>::Target: AsMut<T>,
+/// {
+/// fn as_mut(&mut self) -> &mut T {
+/// self.deref_mut().as_mut()
+/// }
+/// }
+/// ```
+///
+/// # Reflexivity
+///
+/// Ideally, `AsMut` would be reflexive, i.e. there would be an `impl<T: ?Sized> AsMut<T> for T`
+/// with [`as_mut`] simply returning its argument unchanged.
+/// Such a blanket implementation is currently *not* provided due to technical restrictions of
+/// Rust's type system (it would be overlapping with another existing blanket implementation for
+/// `&mut T where T: AsMut<U>` which allows `AsMut` to auto-dereference, see "Generic
+/// Implementations" above).
+///
+/// [`as_mut`]: AsMut::as_mut
+///
+/// A trivial implementation of `AsMut<T> for T` must be added explicitly for a particular type `T`
+/// where needed or desired. Note, however, that not all types from `std` contain such an
+/// implementation, and those cannot be added by external code due to orphan rules.
///
/// # Examples
///
-/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
-/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
-/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
-/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
-/// `&mut Box<u64>` as well:
+/// Using `AsMut` as trait bound for a generic function, we can accept all mutable references that
+/// can be converted to type `&mut T`. Unlike [dereference], which has a single [target type],
+/// there can be multiple implementations of `AsMut` for a type. In particular, `Vec<T>` implements
+/// both `AsMut<Vec<T>>` and `AsMut<[T]>`.
+///
+/// In the following, the example functions `caesar` and `null_terminate` provide a generic
+/// interface which work with any type that can be converted by cheap mutable-to-mutable conversion
+/// into a byte slice (`[u8]`) or byte vector (`Vec<u8>`), respectively.
+///
+/// [dereference]: core::ops::DerefMut
+/// [target type]: core::ops::Deref::Target
///
/// ```
-/// fn add_one<T: AsMut<u64>>(num: &mut T) {
-/// *num.as_mut() += 1;
+/// struct Document {
+/// info: String,
+/// content: Vec<u8>,
/// }
///
-/// let mut boxed_num = Box::new(0);
-/// add_one(&mut boxed_num);
-/// assert_eq!(*boxed_num, 1);
+/// impl<T: ?Sized> AsMut<T> for Document
+/// where
+/// Vec<u8>: AsMut<T>,
+/// {
+/// fn as_mut(&mut self) -> &mut T {
+/// self.content.as_mut()
+/// }
+/// }
+///
+/// fn caesar<T: AsMut<[u8]>>(data: &mut T, key: u8) {
+/// for byte in data.as_mut() {
+/// *byte = byte.wrapping_add(key);
+/// }
+/// }
+///
+/// fn null_terminate<T: AsMut<Vec<u8>>>(data: &mut T) {
+/// // Using a non-generic inner function, which contains most of the
+/// // functionality, helps to minimize monomorphization overhead.
+/// fn doit(data: &mut Vec<u8>) {
+/// let len = data.len();
+/// if len == 0 || data[len-1] != 0 {
+/// data.push(0);
+/// }
+/// }
+/// doit(data.as_mut());
+/// }
+///
+/// fn main() {
+/// let mut v: Vec<u8> = vec![1, 2, 3];
+/// caesar(&mut v, 5);
+/// assert_eq!(v, [6, 7, 8]);
+/// null_terminate(&mut v);
+/// assert_eq!(v, [6, 7, 8, 0]);
+/// let mut doc = Document {
+/// info: String::from("Example"),
+/// content: vec![17, 19, 8],
+/// };
+/// caesar(&mut doc, 1);
+/// assert_eq!(doc.content, [18, 20, 9]);
+/// null_terminate(&mut doc);
+/// assert_eq!(doc.content, [18, 20, 9, 0]);
+/// }
/// ```
///
-/// [`Box<T>`]: ../../std/boxed/struct.Box.html
+/// Note, however, that APIs don't need to be generic. In many cases taking a `&mut [u8]` or
+/// `&mut Vec<u8>`, for example, is the better choice (callers need to pass the correct type then).
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "AsMut")]
+#[const_trait]
pub trait AsMut<T: ?Sized> {
/// Converts this type into a mutable reference of the (usually inferred) input type.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -273,6 +443,7 @@ pub trait AsMut<T: ?Sized> {
/// [`Vec`]: ../../std/vec/struct.Vec.html
#[rustc_diagnostic_item = "Into"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait Into<T>: Sized {
/// Converts this type into the (usually inferred) input type.
#[must_use]
@@ -368,12 +539,13 @@ pub trait Into<T>: Sized {
all(_Self = "&str", T = "std::string::String"),
note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
))]
+#[const_trait]
pub trait From<T>: Sized {
/// Converts to this type from the input type.
#[lang = "from"]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- fn from(_: T) -> Self;
+ fn from(value: T) -> Self;
}
/// An attempted conversion that consumes `self`, which may or may not be
@@ -392,6 +564,7 @@ pub trait From<T>: Sized {
/// [`Into`], see there for details.
#[rustc_diagnostic_item = "TryInto"]
#[stable(feature = "try_from", since = "1.34.0")]
+#[const_trait]
pub trait TryInto<T>: Sized {
/// The type returned in the event of a conversion error.
#[stable(feature = "try_from", since = "1.34.0")]
@@ -436,7 +609,7 @@ pub trait TryInto<T>: Sized {
///
/// fn try_from(value: i32) -> Result<Self, Self::Error> {
/// if value <= 0 {
-/// Err("GreaterThanZero only accepts value superior than zero!")
+/// Err("GreaterThanZero only accepts values greater than zero!")
/// } else {
/// Ok(GreaterThanZero(value))
/// }
@@ -468,6 +641,7 @@ pub trait TryInto<T>: Sized {
/// [`try_from`]: TryFrom::try_from
#[rustc_diagnostic_item = "TryFrom"]
#[stable(feature = "try_from", since = "1.34.0")]
+#[const_trait]
pub trait TryFrom<T>: Sized {
/// The type returned in the event of a conversion error.
#[stable(feature = "try_from", since = "1.34.0")]
@@ -718,7 +892,6 @@ impl fmt::Display for Infallible {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "str_parse_error2", since = "1.8.0")]
impl Error for Infallible {
fn description(&self) -> &str {
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index b53cd6074..a5b4e9655 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -99,6 +99,7 @@
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Default")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Default: Sized {
/// Returns the "default value" for a type.
///
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 4a8efe15e..2738b4994 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -493,8 +493,8 @@ impl Error for crate::char::ParseCharError {
}
}
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for crate::time::FromFloatSecsError {}
+#[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 {
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 21f80ec02..8923f548a 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -221,9 +221,7 @@ impl CStr {
/// # Examples
///
/// ```ignore (extern-declaration)
- /// # fn main() {
- /// use std::ffi::CStr;
- /// use std::os::raw::c_char;
+ /// use std::ffi::{c_char, CStr};
///
/// extern "C" {
/// fn my_string() -> *const c_char;
@@ -233,14 +231,26 @@ impl CStr {
/// let slice = CStr::from_ptr(my_string());
/// println!("string returned: {}", slice.to_str().unwrap());
/// }
- /// # }
+ /// ```
+ ///
+ /// ```
+ /// #![feature(const_cstr_methods)]
+ ///
+ /// use std::ffi::{c_char, CStr};
+ ///
+ /// const HELLO_PTR: *const c_char = {
+ /// const BYTES: &[u8] = b"Hello, world!\0";
+ /// BYTES.as_ptr().cast()
+ /// };
+ /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
/// ```
///
/// [valid]: core::ptr#safety
#[inline]
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
- pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
+ #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
+ pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
// SAFETY: The caller has provided a pointer that points to a valid C
// string with a NUL terminator of size less than `isize::MAX`, whose
// content remain valid and doesn't change for the lifetime of the
@@ -252,13 +262,29 @@ impl CStr {
//
// The cast from c_char to u8 is ok because a c_char is always one byte.
unsafe {
- extern "C" {
- /// Provided by libc or compiler_builtins.
- fn strlen(s: *const c_char) -> usize;
+ const fn strlen_ct(s: *const c_char) -> usize {
+ let mut len = 0;
+
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
+ while unsafe { *s.add(len) } != 0 {
+ len += 1;
+ }
+
+ len
}
- let len = strlen(ptr);
- let ptr = ptr as *const u8;
- CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
+
+ fn strlen_rt(s: *const c_char) -> usize {
+ extern "C" {
+ /// Provided by libc or compiler_builtins.
+ fn strlen(s: *const c_char) -> usize;
+ }
+
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
+ unsafe { strlen(s) }
+ }
+
+ let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt);
+ Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1))
}
}
@@ -474,6 +500,34 @@ impl CStr {
self.inner.as_ptr()
}
+ /// Returns `true` if `self.to_bytes()` has a length of 0.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(cstr_is_empty)]
+ ///
+ /// use std::ffi::CStr;
+ /// # use std::ffi::FromBytesWithNulError;
+ ///
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Result<(), FromBytesWithNulError> {
+ /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?;
+ /// assert!(!cstr.is_empty());
+ ///
+ /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?;
+ /// assert!(empty_cstr.is_empty());
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "cstr_is_empty", issue = "102444")]
+ pub const fn is_empty(&self) -> bool {
+ // SAFETY: We know there is at least one byte; for empty strings it
+ // is the NUL terminator.
+ (unsafe { self.inner.get_unchecked(0) }) == &0
+ }
+
/// Converts this C string to a byte slice.
///
/// The returned slice will **not** contain the trailing nul terminator that this C
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 905212eb3..c8d285505 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -709,12 +709,19 @@ pub use macros::Debug;
/// Format trait for an empty format, `{}`.
///
+/// Implementing this trait for a type will automatically implement the
+/// [`ToString`][tostring] trait for the type, allowing the usage
+/// of the [`.to_string()`][tostring_function] method. Prefer implementing
+/// the `Display` trait for a type, rather than [`ToString`][tostring].
+///
/// `Display` is similar to [`Debug`], but `Display` is for user-facing
/// output, and so cannot be derived.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../../std/fmt/index.html
+/// [tostring]: ../../std/string/trait.ToString.html
+/// [tostring_function]: ../../std/string/trait.ToString.html#tymethod.to_string
///
/// # Examples
///
@@ -2603,7 +2610,7 @@ impl Debug for () {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Debug for PhantomData<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
- f.debug_struct("PhantomData").finish()
+ write!(f, "PhantomData<{}>", crate::any::type_name::<T>())
}
}
diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs
index 25789d37c..d8365ae9b 100644
--- a/library/core/src/fmt/num.rs
+++ b/library/core/src/fmt/num.rs
@@ -211,7 +211,7 @@ macro_rules! impl_Display {
fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
- let mut curr = buf.len() as isize;
+ let mut curr = buf.len();
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
@@ -228,7 +228,7 @@ macro_rules! impl_Display {
// eagerly decode 4 characters at a time
while n >= 10000 {
- let rem = (n % 10000) as isize;
+ let rem = (n % 10000) as usize;
n /= 10000;
let d1 = (rem / 100) << 1;
@@ -238,29 +238,29 @@ macro_rules! impl_Display {
// We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
// otherwise `curr < 0`. But then `n` was originally at least `10000^10`
// which is `10^40 > 2^128 > n`.
- ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d2), buf_ptr.add(curr + 2), 2);
}
// if we reach here numbers are <= 9999, so at most 4 chars long
- let mut n = n as isize; // possibly reduce 64bit math
+ let mut n = n as usize; // possibly reduce 64bit math
// decode 2 more chars, if > 2 chars
if n >= 100 {
let d1 = (n % 100) << 1;
n /= 100;
curr -= 2;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
// decode last 1 or 2 chars
if n < 10 {
curr -= 1;
- *buf_ptr.offset(curr) = (n as u8) + b'0';
+ *buf_ptr.add(curr) = (n as u8) + b'0';
} else {
let d1 = n << 1;
curr -= 2;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
}
@@ -268,7 +268,7 @@ macro_rules! impl_Display {
// UTF-8 since `DEC_DIGITS_LUT` is
let buf_slice = unsafe {
str::from_utf8_unchecked(
- slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
+ slice::from_raw_parts(buf_ptr.add(curr), buf.len() - curr))
};
f.pad_integral(is_nonnegative, "", buf_slice)
}
@@ -339,18 +339,18 @@ macro_rules! impl_Exp {
// Since `curr` always decreases by the number of digits copied, this means
// that `curr >= 0`.
let mut buf = [MaybeUninit::<u8>::uninit(); 40];
- let mut curr = buf.len() as isize; //index for buf
+ let mut curr = buf.len(); //index for buf
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
// decode 2 chars at a time
while n >= 100 {
- let d1 = ((n % 100) as isize) << 1;
+ let d1 = ((n % 100) as usize) << 1;
curr -= 2;
// SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
// `DEC_DIGITS_LUT` has a length of 200.
unsafe {
- ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1), buf_ptr.add(curr), 2);
}
n /= 100;
exponent += 2;
@@ -362,7 +362,7 @@ macro_rules! impl_Exp {
curr -= 1;
// SAFETY: Safe since `40 > curr >= 0` (see comment)
unsafe {
- *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
+ *buf_ptr.add(curr) = (n as u8 % 10_u8) + b'0';
}
n /= 10;
exponent += 1;
@@ -372,7 +372,7 @@ macro_rules! impl_Exp {
curr -= 1;
// SAFETY: Safe since `40 > curr >= 0`
unsafe {
- *buf_ptr.offset(curr) = b'.';
+ *buf_ptr.add(curr) = b'.';
}
}
@@ -380,10 +380,10 @@ macro_rules! impl_Exp {
let buf_slice = unsafe {
// decode last character
curr -= 1;
- *buf_ptr.offset(curr) = (n as u8) + b'0';
+ *buf_ptr.add(curr) = (n as u8) + b'0';
let len = buf.len() - curr as usize;
- slice::from_raw_parts(buf_ptr.offset(curr), len)
+ slice::from_raw_parts(buf_ptr.add(curr), len)
};
// stores 'e' (or 'E') and the up to 2-digit exponent
@@ -392,13 +392,13 @@ macro_rules! impl_Exp {
// SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
// is contained within `exp_buf` since `len <= 3`.
let exp_slice = unsafe {
- *exp_ptr.offset(0) = if upper { b'E' } else { b'e' };
+ *exp_ptr.add(0) = if upper { b'E' } else { b'e' };
let len = if exponent < 10 {
- *exp_ptr.offset(1) = (exponent as u8) + b'0';
+ *exp_ptr.add(1) = (exponent as u8) + b'0';
2
} else {
let off = exponent << 1;
- ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(off), exp_ptr.add(1), 2);
3
};
slice::from_raw_parts(exp_ptr, len)
@@ -479,7 +479,7 @@ mod imp {
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
-fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut isize) {
+fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut usize) {
let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
assert!(*curr > 19);
@@ -505,14 +505,14 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
*curr -= 16;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d5 as usize), buf_ptr.add(*curr + 8), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d6 as usize), buf_ptr.add(*curr + 10), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d7 as usize), buf_ptr.add(*curr + 12), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d8 as usize), buf_ptr.add(*curr + 14), 2);
}
if n >= 1e8 as u64 {
let to_parse = n % 1e8 as u64;
@@ -525,10 +525,10 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
let d4 = ((to_parse / 1e0 as u64) % 100) << 1;
*curr -= 8;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d3 as usize), buf_ptr.add(*curr + 4), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d4 as usize), buf_ptr.add(*curr + 6), 2);
}
// `n` < 1e8 < (1 << 32)
let mut n = n as u32;
@@ -540,8 +540,8 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
let d2 = (to_parse % 100) << 1;
*curr -= 4;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
- ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr + 0), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d2 as usize), buf_ptr.add(*curr + 2), 2);
}
// `n` < 1e4 < (1 << 16)
@@ -550,17 +550,17 @@ fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], cu
let d1 = (n % 100) << 1;
n /= 100;
*curr -= 2;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2);
}
// decode last 1 or 2 chars
if n < 10 {
*curr -= 1;
- *buf_ptr.offset(*curr) = (n as u8) + b'0';
+ *buf_ptr.add(*curr) = (n as u8) + b'0';
} else {
let d1 = n << 1;
*curr -= 2;
- ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
+ ptr::copy_nonoverlapping(lut_ptr.add(d1 as usize), buf_ptr.add(*curr), 2);
}
}
}
@@ -593,21 +593,21 @@ impl fmt::Display for i128 {
fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
- let mut curr = buf.len() as isize;
+ let mut curr = buf.len();
let (n, rem) = udiv_1e19(n);
parse_u64_into(rem, &mut buf, &mut curr);
if n != 0 {
// 0 pad up to point
- let target = (buf.len() - 19) as isize;
+ let target = buf.len() - 19;
// SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
// remaining since it has length 39
unsafe {
ptr::write_bytes(
- MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target),
+ MaybeUninit::slice_as_mut_ptr(&mut buf).add(target),
b'0',
- (curr - target) as usize,
+ curr - target,
);
}
curr = target;
@@ -616,16 +616,16 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
parse_u64_into(rem, &mut buf, &mut curr);
// Should this following branch be annotated with unlikely?
if n != 0 {
- let target = (buf.len() - 38) as isize;
+ let target = buf.len() - 38;
// The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
// buf `buf` is not used in this scope so we are good.
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
// SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
// There can only be at most 1 digit remaining.
unsafe {
- ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
+ ptr::write_bytes(buf_ptr.add(target), b'0', curr - target);
curr = target - 1;
- *buf_ptr.offset(curr) = (n as u8) + b'0';
+ *buf_ptr.add(curr) = (n as u8) + b'0';
}
}
}
@@ -634,8 +634,8 @@ fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::R
// UTF-8 since `DEC_DIGITS_LUT` is
let buf_slice = unsafe {
str::from_utf8_unchecked(slice::from_raw_parts(
- MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr),
- buf.len() - curr as usize,
+ MaybeUninit::slice_as_mut_ptr(&mut buf).add(curr),
+ buf.len() - curr,
))
};
f.pad_integral(is_nonnegative, "", buf_slice)
diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs
index 48f20f90a..a07b63fb6 100644
--- a/library/core/src/future/ready.rs
+++ b/library/core/src/future/ready.rs
@@ -24,6 +24,30 @@ impl<T> Future for Ready<T> {
}
}
+impl<T> Ready<T> {
+ /// Consumes the `Ready`, returning the wrapped value.
+ ///
+ /// # Panics
+ ///
+ /// Will panic if this [`Ready`] was already polled to completion.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ready_into_inner)]
+ /// use std::future;
+ ///
+ /// let a = future::ready(1);
+ /// assert_eq!(a.into_inner(), 1);
+ /// ```
+ #[unstable(feature = "ready_into_inner", issue = "101196")]
+ #[must_use]
+ #[inline]
+ pub fn into_inner(self) -> T {
+ self.0.expect("Called `into_inner()` on `Ready` after completion")
+ }
+}
+
/// Creates a future that is immediately ready with a value.
///
/// Futures created through this function are functionally similar to those
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 764e27962..c53175ba4 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -100,7 +100,10 @@ use crate::intrinsics;
pub const unsafe fn unreachable_unchecked() -> ! {
// SAFETY: the safety contract for `intrinsics::unreachable` must
// be upheld by the caller.
- unsafe { intrinsics::unreachable() }
+ unsafe {
+ intrinsics::assert_unsafe_precondition!("hint::unreachable_unchecked must never be reached", () => false);
+ intrinsics::unreachable()
+ }
}
/// Emits a machine instruction to signal the processor that it is running in
@@ -217,7 +220,7 @@ pub fn spin_loop() {
///
/// [`std::convert::identity`]: crate::convert::identity
#[inline]
-#[unstable(feature = "bench_black_box", issue = "64102")]
+#[stable(feature = "bench_black_box", since = "1.66.0")]
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
pub const fn black_box<T>(dummy: T) -> T {
crate::intrinsics::black_box(dummy)
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 11c75e2c9..1dc79afe8 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -54,8 +54,6 @@
)]
#![allow(missing_docs)]
-#[cfg(bootstrap)]
-use crate::marker::Destruct;
use crate::marker::DiscriminantKind;
use crate::mem;
@@ -790,6 +788,7 @@ extern "rust-intrinsic" {
/// uninitialized at that point in the control flow.
///
/// This intrinsic should not be used outside of the compiler.
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn rustc_peek<T>(_: T) -> T;
/// Aborts the execution of the process.
@@ -807,6 +806,7 @@ extern "rust-intrinsic" {
/// On Unix, the
/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or
/// `SIGBUS`. The precise behaviour is not guaranteed and not stable.
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn abort() -> !;
/// Informs the optimizer that this point in the code is not reachable,
@@ -845,6 +845,7 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn likely(b: bool) -> bool;
/// Hints to the compiler that branch condition is likely to be false.
@@ -859,6 +860,7 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_likely", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn unlikely(b: bool) -> bool;
/// Executes a breakpoint trap, for inspection by a debugger.
@@ -878,6 +880,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`core::mem::size_of`].
#[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn size_of<T>() -> usize;
/// The minimum alignment of a type.
@@ -889,6 +892,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`core::mem::align_of`].
#[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn min_align_of<T>() -> usize;
/// The preferred alignment of a type.
///
@@ -917,6 +921,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`core::any::type_name`].
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn type_name<T: ?Sized>() -> &'static str;
/// Gets an identifier which is globally unique to the specified type. This
@@ -930,6 +935,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`core::any::TypeId::of`].
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn type_id<T: ?Sized + 'static>() -> u64;
/// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
@@ -937,6 +943,7 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_stable(feature = "const_assert_type", since = "1.59.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn assert_inhabited<T>();
/// A guard for unsafe functions that cannot ever be executed if `T` does not permit
@@ -944,6 +951,7 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn assert_zero_valid<T>();
/// A guard for unsafe functions that cannot ever be executed if `T` has invalid
@@ -951,6 +959,7 @@ extern "rust-intrinsic" {
///
/// This intrinsic does not have a stable counterpart.
#[rustc_const_unstable(feature = "const_assert_type2", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn assert_uninit_valid<T>();
/// Gets a reference to a static `Location` indicating where it was called.
@@ -962,6 +971,7 @@ extern "rust-intrinsic" {
///
/// Consider using [`core::panic::Location::caller`] instead.
#[rustc_const_unstable(feature = "const_caller_location", issue = "76156")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn caller_location() -> &'static crate::panic::Location<'static>;
/// Moves a value out of scope without running drop glue.
@@ -974,6 +984,7 @@ extern "rust-intrinsic" {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_const_unstable(feature = "const_intrinsic_forget", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn forget<T: ?Sized>(_: T);
/// Reinterprets the bits of a value of one type as another type.
@@ -983,14 +994,14 @@ extern "rust-intrinsic" {
/// `transmute` is semantically equivalent to a bitwise move of one type
/// into another. It copies the bits from the source value into the
/// destination value, then forgets the original. Note that source and destination
- /// are passed by-value, which means if `T` or `U` contain padding, that padding
+ /// are passed by-value, which means if `Src` or `Dst` contain padding, that padding
/// is *not* guaranteed to be preserved by `transmute`.
///
/// Both the argument and the result must be [valid](../../nomicon/what-unsafe-does.html) at
/// their given type. Violating this condition leads to [undefined behavior][ub]. The compiler
/// will generate code *assuming that you, the programmer, ensure that there will never be
/// undefined behavior*. It is therefore your responsibility to guarantee that every value
- /// passed to `transmute` is valid at both types `T` and `U`. Failing to uphold this condition
+ /// passed to `transmute` is valid at both types `Src` and `Dst`. Failing to uphold this condition
/// may lead to unexpected and unstable compilation results. This makes `transmute` **incredibly
/// unsafe**. `transmute` should be the absolute last resort.
///
@@ -1001,7 +1012,7 @@ extern "rust-intrinsic" {
///
/// Because `transmute` is a by-value operation, alignment of the *transmuted values
/// themselves* is not a concern. As with any other function, the compiler already ensures
- /// both `T` and `U` are properly aligned. However, when transmuting values that *point
+ /// both `Src` and `Dst` are properly aligned. However, when transmuting values that *point
/// elsewhere* (such as pointers, references, boxes…), the caller has to ensure proper
/// alignment of the pointed-to values.
///
@@ -1237,7 +1248,7 @@ extern "rust-intrinsic" {
#[rustc_allowed_through_unstable_modules]
#[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
#[rustc_diagnostic_item = "transmute"]
- pub fn transmute<T, U>(e: T) -> U;
+ pub fn transmute<Src, Dst>(src: Src) -> Dst;
/// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
@@ -1253,6 +1264,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`mem::needs_drop`](crate::mem::needs_drop).
#[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn needs_drop<T: ?Sized>() -> bool;
/// Calculates the offset from a pointer.
@@ -1297,7 +1309,7 @@ extern "rust-intrinsic" {
/// any safety invariants.
///
/// Consider using [`pointer::mask`] instead.
- #[cfg(not(bootstrap))]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn ptr_mask<T>(ptr: *const T, mask: usize) -> *const T;
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
@@ -1489,6 +1501,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is
/// [`f32::min`]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn minnumf32(x: f32, y: f32) -> f32;
/// Returns the minimum of two `f64` values.
///
@@ -1499,6 +1512,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is
/// [`f64::min`]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn minnumf64(x: f64, y: f64) -> f64;
/// Returns the maximum of two `f32` values.
///
@@ -1509,6 +1523,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is
/// [`f32::max`]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn maxnumf32(x: f32, y: f32) -> f32;
/// Returns the maximum of two `f64` values.
///
@@ -1519,6 +1534,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is
/// [`f64::max`]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn maxnumf64(x: f64, y: f64) -> f64;
/// Copies the sign from `y` to `x` for `f32` values.
@@ -1639,6 +1655,7 @@ extern "rust-intrinsic" {
/// primitives via the `count_ones` method. For example,
/// [`u32::count_ones`]
#[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn ctpop<T: Copy>(x: T) -> T;
/// Returns the number of leading unset bits (zeroes) in an integer type `T`.
@@ -1676,6 +1693,7 @@ extern "rust-intrinsic" {
/// assert_eq!(num_leading, 16);
/// ```
#[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn ctlz<T: Copy>(x: T) -> T;
/// Like `ctlz`, but extra-unsafe as it returns `undef` when
@@ -1732,6 +1750,7 @@ extern "rust-intrinsic" {
/// assert_eq!(num_trailing, 16);
/// ```
#[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn cttz<T: Copy>(x: T) -> T;
/// Like `cttz`, but extra-unsafe as it returns `undef` when
@@ -1764,6 +1783,7 @@ extern "rust-intrinsic" {
/// primitives via the `swap_bytes` method. For example,
/// [`u32::swap_bytes`]
#[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn bswap<T: Copy>(x: T) -> T;
/// Reverses the bits in an integer type `T`.
@@ -1777,6 +1797,7 @@ extern "rust-intrinsic" {
/// primitives via the `reverse_bits` method. For example,
/// [`u32::reverse_bits`]
#[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn bitreverse<T: Copy>(x: T) -> T;
/// Performs checked integer addition.
@@ -1790,6 +1811,7 @@ extern "rust-intrinsic" {
/// primitives via the `overflowing_add` method. For example,
/// [`u32::overflowing_add`]
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
/// Performs checked integer subtraction
@@ -1803,6 +1825,7 @@ extern "rust-intrinsic" {
/// primitives via the `overflowing_sub` method. For example,
/// [`u32::overflowing_sub`]
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
/// Performs checked integer multiplication
@@ -1816,6 +1839,7 @@ extern "rust-intrinsic" {
/// primitives via the `overflowing_mul` method. For example,
/// [`u32::overflowing_mul`]
#[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
/// Performs an exact division, resulting in undefined behavior where
@@ -1890,6 +1914,7 @@ extern "rust-intrinsic" {
/// primitives via the `rotate_left` method. For example,
/// [`u32::rotate_left`]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn rotate_left<T: Copy>(x: T, y: T) -> T;
/// Performs rotate right.
@@ -1903,6 +1928,7 @@ extern "rust-intrinsic" {
/// primitives via the `rotate_right` method. For example,
/// [`u32::rotate_right`]
#[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
/// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
@@ -1916,6 +1942,7 @@ extern "rust-intrinsic" {
/// primitives via the `wrapping_add` method. For example,
/// [`u32::wrapping_add`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
/// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
///
@@ -1928,6 +1955,7 @@ extern "rust-intrinsic" {
/// primitives via the `wrapping_sub` method. For example,
/// [`u32::wrapping_sub`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
/// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
///
@@ -1940,6 +1968,7 @@ extern "rust-intrinsic" {
/// primitives via the `wrapping_mul` method. For example,
/// [`u32::wrapping_mul`]
#[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
/// Computes `a + b`, saturating at numeric bounds.
@@ -1953,6 +1982,7 @@ extern "rust-intrinsic" {
/// primitives via the `saturating_add` method. For example,
/// [`u32::saturating_add`]
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
/// Computes `a - b`, saturating at numeric bounds.
///
@@ -1965,6 +1995,7 @@ extern "rust-intrinsic" {
/// primitives via the `saturating_sub` method. For example,
/// [`u32::saturating_sub`]
#[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
/// Returns the value of the discriminant for the variant in 'v';
@@ -1977,6 +2008,7 @@ extern "rust-intrinsic" {
///
/// The stabilized version of this intrinsic is [`core::mem::discriminant`].
#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
/// Returns the number of variants of the type `T` cast to a `usize`;
@@ -1989,6 +2021,7 @@ extern "rust-intrinsic" {
///
/// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn variant_count<T>() -> usize;
/// Rust's "try catch" construct which invokes the function pointer `try_fn`
@@ -2022,17 +2055,9 @@ extern "rust-intrinsic" {
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
#[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
- #[cfg(not(bootstrap))]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn ptr_guaranteed_cmp<T>(ptr: *const T, other: *const T) -> u8;
- #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
- #[cfg(bootstrap)]
- pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
-
- #[rustc_const_unstable(feature = "const_raw_ptr_comparison", issue = "53020")]
- #[cfg(bootstrap)]
- pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
-
/// Allocates a block of memory at compile time.
/// At runtime, just returns a null pointer.
///
@@ -2081,6 +2106,7 @@ extern "rust-intrinsic" {
///
/// [`std::hint::black_box`]: crate::hint::black_box
#[rustc_const_unstable(feature = "const_black_box", issue = "none")]
+ #[cfg_attr(not(bootstrap), rustc_safe_intrinsic)]
pub fn black_box<T>(dummy: T) -> T;
/// `ptr` must point to a vtable.
@@ -2143,7 +2169,6 @@ extern "rust-intrinsic" {
/// `unreachable_unchecked` is actually being reached. The bug is in *crate A*,
/// which violates the principle that a `const fn` must behave the same at
/// compile-time and at run-time. The unsafe code in crate B is fine.
- #[cfg(not(bootstrap))]
#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
pub fn const_eval_select<ARG, F, G, RET>(arg: ARG, called_in_const: F, called_at_rt: G) -> RET
where
@@ -2178,15 +2203,17 @@ extern "rust-intrinsic" {
/// the occasional mistake, and this check should help them figure things out.
#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
macro_rules! assert_unsafe_precondition {
- ($([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => {
+ ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr) => {
if cfg!(debug_assertions) {
// allow non_snake_case to allow capturing const generics
#[allow(non_snake_case)]
#[inline(always)]
fn runtime$(<$($tt)*>)?($($i:$ty),*) {
if !$e {
- // abort instead of panicking to reduce impact on code size
- ::core::intrinsics::abort();
+ // don't unwind to reduce impact on code size
+ ::core::panicking::panic_str_nounwind(
+ concat!("unsafe precondition(s) violated: ", $name)
+ );
}
}
#[allow(non_snake_case)]
@@ -2204,6 +2231,16 @@ pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
!ptr.is_null() && ptr.is_aligned()
}
+/// Checks whether an allocation of `len` instances of `T` exceeds
+/// the maximum allowed allocation size.
+pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
+ let max_len = const {
+ let size = crate::mem::size_of::<T>();
+ if size == 0 { usize::MAX } else { isize::MAX as usize / size }
+ };
+ len <= max_len
+}
+
/// Checks whether the regions of memory starting at `src` and `dst` of size
/// `count * size_of::<T>()` do *not* overlap.
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
@@ -2216,16 +2253,6 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
diff >= size
}
-#[cfg(bootstrap)]
-pub const fn ptr_guaranteed_cmp(a: *const (), b: *const ()) -> u8 {
- match (ptr_guaranteed_eq(a, b), ptr_guaranteed_ne(a, b)) {
- (false, false) => 2,
- (true, false) => 1,
- (false, true) => 0,
- (true, true) => unreachable!(),
- }
-}
-
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source
/// and destination must *not* overlap.
///
@@ -2325,7 +2352,10 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
// SAFETY: the safety contract for `copy_nonoverlapping` must be
// upheld by the caller.
unsafe {
- assert_unsafe_precondition!([T](src: *const T, dst: *mut T, count: usize) =>
+ assert_unsafe_precondition!(
+ "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
+ and the specified memory ranges do not overlap",
+ [T](src: *const T, dst: *mut T, count: usize) =>
is_aligned_and_not_null(src)
&& is_aligned_and_not_null(dst)
&& is_nonoverlapping(src, dst, count)
@@ -2411,8 +2441,11 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
// SAFETY: the safety contract for `copy` must be upheld by the caller.
unsafe {
- assert_unsafe_precondition!([T](src: *const T, dst: *mut T) =>
- is_aligned_and_not_null(src) && is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::copy requires that both pointer arguments are aligned aligned and non-null",
+ [T](src: *const T, dst: *mut T) =>
+ is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
+ );
copy(src, dst, count)
}
}
@@ -2480,49 +2513,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
// SAFETY: the safety contract for `write_bytes` must be upheld by the caller.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::write_bytes requires that the destination pointer is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
write_bytes(dst, val, count)
}
}
-
-#[cfg(bootstrap)]
-#[unstable(
- feature = "const_eval_select",
- issue = "none",
- reason = "const_eval_select will never be stable"
-)]
-#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
-#[lang = "const_eval_select"]
-#[rustc_do_not_const_check]
-#[inline]
-pub const unsafe fn const_eval_select<ARG, F, G, RET>(
- arg: ARG,
- _called_in_const: F,
- called_at_rt: G,
-) -> RET
-where
- F: ~const FnOnce<ARG, Output = RET>,
- G: FnOnce<ARG, Output = RET> + ~const Destruct,
-{
- called_at_rt.call_once(arg)
-}
-
-#[cfg(bootstrap)]
-#[unstable(
- feature = "const_eval_select",
- issue = "none",
- reason = "const_eval_select will never be stable"
-)]
-#[rustc_const_unstable(feature = "const_eval_select", issue = "none")]
-#[lang = "const_eval_select_ct"]
-pub const unsafe fn const_eval_select_ct<ARG, F, G, RET>(
- arg: ARG,
- called_in_const: F,
- _called_at_rt: G,
-) -> RET
-where
- F: ~const FnOnce<ARG, Output = RET>,
- G: FnOnce<ARG, Output = RET> + ~const Destruct,
-{
- called_in_const.call_once(arg)
-}
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index 9b479a9f8..d4fb88610 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,6 +1,6 @@
use crate::array;
use crate::iter::{ByRefSized, FusedIterator, Iterator};
-use crate::ops::{ControlFlow, NeverShortCircuit, Try};
+use crate::ops::{ControlFlow, Try};
/// An iterator over `N` elements of the iterator at a time.
///
@@ -82,13 +82,7 @@ where
}
}
- fn fold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_fold(init, NeverShortCircuit::wrap_mut_2(f)).0
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")]
@@ -126,13 +120,7 @@ where
try { acc }
}
- fn rfold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_rfold(init, NeverShortCircuit::wrap_mut_2(f)).0
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
}
impl<I, const N: usize> ArrayChunks<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 477e7117c..1945e402f 100644
--- a/library/core/src/iter/adapters/by_ref_sized.rs
+++ b/library/core/src/iter/adapters/by_ref_sized.rs
@@ -1,4 +1,7 @@
-use crate::ops::{NeverShortCircuit, Try};
+use crate::{
+ const_closure::ConstFnMutClosure,
+ ops::{NeverShortCircuit, Try},
+};
/// Like `Iterator::by_ref`, but requiring `Sized` so it can forward generics.
///
@@ -36,12 +39,13 @@ impl<I: Iterator> Iterator for ByRefSized<'_, I> {
}
#[inline]
- fn fold<B, F>(self, init: B, f: F) -> B
+ fn fold<B, F>(self, init: B, mut 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, NeverShortCircuit::wrap_mut_2(f)).0
+ I::try_fold(self.0, init, ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp))
+ .0
}
#[inline]
@@ -72,12 +76,17 @@ impl<I: DoubleEndedIterator> DoubleEndedIterator for ByRefSized<'_, I> {
}
#[inline]
- fn rfold<B, F>(self, init: B, f: F) -> B
+ fn rfold<B, F>(self, init: B, mut 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, NeverShortCircuit::wrap_mut_2(f)).0
+ I::try_rfold(
+ self.0,
+ init,
+ ConstFnMutClosure::new(&mut f, NeverShortCircuit::wrap_mut_2_imp),
+ )
+ .0
}
#[inline]
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index f9bfd77d7..62d3afb81 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -2,7 +2,10 @@ use crate::iter::adapters::{
zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
use crate::iter::{FusedIterator, TrustedLen};
+use crate::mem::MaybeUninit;
+use crate::mem::SizedTypeProperties;
use crate::ops::Try;
+use crate::{array, ptr};
/// An iterator that copies the elements of an underlying iterator.
///
@@ -44,6 +47,15 @@ where
self.it.next().copied()
}
+ fn next_chunk<const N: usize>(
+ &mut self,
+ ) -> Result<[Self::Item; N], array::IntoIter<Self::Item, N>>
+ where
+ Self: Sized,
+ {
+ <I as SpecNextChunk<'_, N, T>>::spec_next_chunk(&mut self.it)
+ }
+
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
@@ -166,3 +178,65 @@ where
T: Copy,
{
}
+
+trait SpecNextChunk<'a, const N: usize, T: 'a>: Iterator<Item = &'a T>
+where
+ T: Copy,
+{
+ fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>>;
+}
+
+impl<'a, const N: usize, I, T: 'a> SpecNextChunk<'a, N, T> for I
+where
+ I: Iterator<Item = &'a T>,
+ T: Copy,
+{
+ default fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
+ array::iter_next_chunk(&mut self.map(|e| *e))
+ }
+}
+
+impl<'a, const N: usize, T: 'a> SpecNextChunk<'a, N, T> for crate::slice::Iter<'a, T>
+where
+ T: Copy,
+{
+ fn spec_next_chunk(&mut self) -> Result<[T; N], array::IntoIter<T, N>> {
+ let mut raw_array = MaybeUninit::uninit_array();
+
+ let len = self.len();
+
+ if T::IS_ZST {
+ if len < N {
+ let _ = self.advance_by(len);
+ // SAFETY: ZSTs can be conjured ex nihilo; only the amount has to be correct
+ return Err(unsafe { array::IntoIter::new_unchecked(raw_array, 0..len) });
+ }
+
+ let _ = self.advance_by(N);
+ // SAFETY: ditto
+ return Ok(unsafe { MaybeUninit::array_assume_init(raw_array) });
+ }
+
+ if len < N {
+ // SAFETY: `len` indicates that this many elements are available and we just checked that
+ // it fits into the array.
+ unsafe {
+ ptr::copy_nonoverlapping(
+ self.as_ref().as_ptr(),
+ raw_array.as_mut_ptr() as *mut T,
+ len,
+ );
+ let _ = self.advance_by(len);
+ return Err(array::IntoIter::new_unchecked(raw_array, 0..len));
+ }
+ }
+
+ // SAFETY: `len` is larger than the array size. Copy a fixed amount here to fully initialize
+ // the array.
+ unsafe {
+ ptr::copy_nonoverlapping(self.as_ref().as_ptr(), raw_array.as_mut_ptr() as *mut T, N);
+ let _ = self.advance_by(N);
+ Ok(MaybeUninit::array_assume_init(raw_array))
+ }
+ }
+}
diff --git a/library/core/src/iter/adapters/map_while.rs b/library/core/src/iter/adapters/map_while.rs
index 1e8d6bf3e..fbdeca4d4 100644
--- a/library/core/src/iter/adapters/map_while.rs
+++ b/library/core/src/iter/adapters/map_while.rs
@@ -64,19 +64,7 @@ where
.into_try()
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index bf4fabad3..8cc2b7cec 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1,5 +1,5 @@
use crate::iter::{InPlaceIterable, Iterator};
-use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try};
+use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
mod array_chunks;
mod by_ref_sized;
@@ -203,13 +203,7 @@ where
.into_try()
}
- fn fold<B, F>(mut self, init: B, fold: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/scan.rs b/library/core/src/iter/adapters/scan.rs
index 80bfd2231..62470512c 100644
--- a/library/core/src/iter/adapters/scan.rs
+++ b/library/core/src/iter/adapters/scan.rs
@@ -74,19 +74,7 @@ where
self.iter.try_fold(init, scan(state, f, fold)).into_try()
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[unstable(issue = "none", feature = "inplace_iteration")]
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
index dbf0ae9ec..c6334880d 100644
--- a/library/core/src/iter/adapters/skip.rs
+++ b/library/core/src/iter/adapters/skip.rs
@@ -206,17 +206,7 @@ where
if n == 0 { try { init } } else { self.iter.try_rfold(init, check(n, fold)).into_try() }
}
- fn rfold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<Acc, T>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, T) -> Result<Acc, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_rfold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
diff --git a/library/core/src/iter/adapters/take.rs b/library/core/src/iter/adapters/take.rs
index 2962e0104..58a0b9d7b 100644
--- a/library/core/src/iter/adapters/take.rs
+++ b/library/core/src/iter/adapters/take.rs
@@ -98,19 +98,7 @@ where
}
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
#[inline]
#[rustc_inherit_overflow_checks]
diff --git a/library/core/src/iter/adapters/take_while.rs b/library/core/src/iter/adapters/take_while.rs
index ded216da9..ec66dc3ae 100644
--- a/library/core/src/iter/adapters/take_while.rs
+++ b/library/core/src/iter/adapters/take_while.rs
@@ -94,19 +94,7 @@ where
}
}
- #[inline]
- fn fold<Acc, Fold>(mut self, init: Acc, fold: Fold) -> Acc
- where
- Self: Sized,
- Fold: FnMut(Acc, Self::Item) -> Acc,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(fold)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
}
#[stable(feature = "fused", since = "1.26.0")]
diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs
index 9514466bd..ef0f39782 100644
--- a/library/core/src/iter/mod.rs
+++ b/library/core/src/iter/mod.rs
@@ -352,6 +352,29 @@
#![stable(feature = "rust1", since = "1.0.0")]
+// This needs to be up here in order to be usable in the child modules
+macro_rules! impl_fold_via_try_fold {
+ (fold -> try_fold) => {
+ impl_fold_via_try_fold! { @internal fold -> try_fold }
+ };
+ (rfold -> try_rfold) => {
+ impl_fold_via_try_fold! { @internal rfold -> try_rfold }
+ };
+ (@internal $fold:ident -> $try_fold:ident) => {
+ #[inline]
+ fn $fold<AAA, FFF>(mut self, init: AAA, mut 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
+ }
+ };
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::traits::Iterator;
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index f7aeee8c9..ac7b389b1 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1150,19 +1150,7 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
self.spec_try_fold(init, f)
}
- #[inline]
- fn fold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_fold(init, ok(f)).unwrap()
- }
+ impl_fold_via_try_fold! { fold -> try_fold }
#[inline]
fn last(mut self) -> Option<A> {
@@ -1230,19 +1218,7 @@ impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
self.spec_try_rfold(init, f)
}
- #[inline]
- fn rfold<B, F>(mut self, init: B, f: F) -> B
- where
- Self: Sized,
- F: FnMut(B, Self::Item) -> B,
- {
- #[inline]
- fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
- move |acc, x| Ok(f(acc, x))
- }
-
- self.try_rfold(init, ok(f)).unwrap()
- }
+ impl_fold_via_try_fold! { rfold -> try_rfold }
}
// Safety: See above implementation for `ops::Range<A>`
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 12ca508be..e099700e3 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -228,6 +228,7 @@ pub trait FromIterator<A>: Sized {
#[rustc_diagnostic_item = "IntoIterator"]
#[rustc_skip_array_during_method_dispatch]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait IntoIterator {
/// The type of the elements being iterated over.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -263,7 +264,7 @@ pub trait IntoIterator {
#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<I: ~const Iterator> const IntoIterator for I {
+impl<I: Iterator> const IntoIterator for I {
type Item = I::Item;
type IntoIter = I;
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index b2d08f4b0..789a87968 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -692,7 +692,7 @@ pub trait Iterator {
/// assert_eq!(it.next(), Some(NotClone(99))); // The separator.
/// assert_eq!(it.next(), Some(NotClone(1))); // The next element from `v`.
/// assert_eq!(it.next(), Some(NotClone(99))); // The separator.
- /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from from `v`.
+ /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from `v`.
/// assert_eq!(it.next(), None); // The iterator is finished.
/// ```
///
@@ -2431,22 +2431,13 @@ pub trait Iterator {
///
/// # Example
///
- /// Find the maximum value:
- ///
/// ```
- /// fn find_max<I>(iter: I) -> Option<I::Item>
- /// where I: Iterator,
- /// I::Item: Ord,
- /// {
- /// iter.reduce(|accum, item| {
- /// if accum >= item { accum } else { item }
- /// })
- /// }
- /// let a = [10, 20, 5, -23, 0];
- /// let b: [u32; 0] = [];
+ /// let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap();
+ /// assert_eq!(reduced, 45);
///
- /// assert_eq!(find_max(a.iter()), Some(&20));
- /// assert_eq!(find_max(b.iter()), None);
+ /// // Which is equivalent to doing it with `fold`:
+ /// let folded: i32 = (1..10).fold(0, |acc, e| acc + e);
+ /// assert_eq!(reduced, folded);
/// ```
#[inline]
#[stable(feature = "iterator_fold_self", since = "1.51.0")]
@@ -2906,14 +2897,14 @@ pub trait Iterator {
/// Stopping at the first `true`:
///
/// ```
- /// let a = [1, 2, 3];
+ /// let a = [-1, 2, 3, 4];
///
/// let mut iter = a.iter();
///
- /// assert_eq!(iter.rposition(|&x| x == 2), Some(1));
+ /// assert_eq!(iter.rposition(|&x| x >= 2), Some(3));
///
/// // we can still use `iter`, as there are more elements.
- /// assert_eq!(iter.next(), Some(&1));
+ /// assert_eq!(iter.next(), Some(&-1));
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@@ -3461,36 +3452,27 @@ 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")]
- fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> Ordering
+ fn cmp_by<I, F>(self, other: I, cmp: F) -> Ordering
where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, I::Item) -> Ordering,
{
- let mut other = other.into_iter();
-
- loop {
- let x = match self.next() {
- None => {
- if other.next().is_none() {
- return Ordering::Equal;
- } else {
- return Ordering::Less;
- }
- }
- Some(val) => val,
- };
-
- let y = match other.next() {
- None => return Ordering::Greater,
- Some(val) => val,
- };
-
- match cmp(x, y) {
- Ordering::Equal => (),
- non_eq => return non_eq,
+ #[inline]
+ fn compare<X, Y, F>(mut cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Ordering>
+ where
+ F: FnMut(X, Y) -> Ordering,
+ {
+ move |x, y| match cmp(x, y) {
+ Ordering::Equal => ControlFlow::CONTINUE,
+ non_eq => ControlFlow::Break(non_eq),
}
}
+
+ match iter_compare(self, other.into_iter(), compare(cmp)) {
+ ControlFlow::Continue(ord) => ord,
+ ControlFlow::Break(ord) => ord,
+ }
}
/// [Lexicographically](Ord#lexicographical-comparison) compares the elements of this [`Iterator`] with those
@@ -3546,36 +3528,27 @@ pub trait Iterator {
/// );
/// ```
#[unstable(feature = "iter_order_by", issue = "64295")]
- fn partial_cmp_by<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering>
+ fn partial_cmp_by<I, F>(self, other: I, partial_cmp: F) -> Option<Ordering>
where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, I::Item) -> Option<Ordering>,
{
- let mut other = other.into_iter();
-
- loop {
- let x = match self.next() {
- None => {
- if other.next().is_none() {
- return Some(Ordering::Equal);
- } else {
- return Some(Ordering::Less);
- }
- }
- Some(val) => val,
- };
-
- let y = match other.next() {
- None => return Some(Ordering::Greater),
- Some(val) => val,
- };
-
- match partial_cmp(x, y) {
- Some(Ordering::Equal) => (),
- non_eq => return non_eq,
+ #[inline]
+ fn compare<X, Y, F>(mut partial_cmp: F) -> impl FnMut(X, Y) -> ControlFlow<Option<Ordering>>
+ where
+ F: FnMut(X, Y) -> Option<Ordering>,
+ {
+ move |x, y| match partial_cmp(x, y) {
+ Some(Ordering::Equal) => ControlFlow::CONTINUE,
+ non_eq => ControlFlow::Break(non_eq),
}
}
+
+ match iter_compare(self, other.into_iter(), compare(partial_cmp)) {
+ ControlFlow::Continue(ord) => Some(ord),
+ ControlFlow::Break(ord) => ord,
+ }
}
/// Determines if the elements of this [`Iterator`] are equal to those of
@@ -3613,29 +3586,26 @@ pub trait Iterator {
/// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y));
/// ```
#[unstable(feature = "iter_order_by", issue = "64295")]
- fn eq_by<I, F>(mut self, other: I, mut eq: F) -> bool
+ fn eq_by<I, F>(self, other: I, eq: F) -> bool
where
Self: Sized,
I: IntoIterator,
F: FnMut(Self::Item, I::Item) -> bool,
{
- let mut other = other.into_iter();
-
- loop {
- let x = match self.next() {
- None => return other.next().is_none(),
- Some(val) => val,
- };
-
- let y = match other.next() {
- None => return false,
- Some(val) => val,
- };
-
- if !eq(x, y) {
- return false;
+ #[inline]
+ fn compare<X, Y, F>(mut eq: F) -> impl FnMut(X, Y) -> ControlFlow<()>
+ where
+ F: FnMut(X, Y) -> bool,
+ {
+ move |x, y| {
+ if eq(x, y) { ControlFlow::CONTINUE } else { ControlFlow::BREAK }
}
}
+
+ match iter_compare(self, other.into_iter(), compare(eq)) {
+ ControlFlow::Continue(ord) => ord == Ordering::Equal,
+ ControlFlow::Break(()) => false,
+ }
}
/// Determines if the elements of this [`Iterator`] are unequal to those of
@@ -3860,6 +3830,46 @@ 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
+/// 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
+/// the iterators.
+///
+/// Isolates the logic shared by ['cmp_by'](Iterator::cmp_by),
+/// ['partial_cmp_by'](Iterator::partial_cmp_by), and ['eq_by'](Iterator::eq_by).
+#[inline]
+fn iter_compare<A, B, F, T>(mut a: A, mut b: B, f: F) -> ControlFlow<T, Ordering>
+where
+ A: Iterator,
+ B: Iterator,
+ F: FnMut(A::Item, B::Item) -> ControlFlow<T>,
+{
+ #[inline]
+ fn compare<'a, B, X, T>(
+ b: &'a mut B,
+ mut f: impl FnMut(X, B::Item) -> ControlFlow<T> + 'a,
+ ) -> impl FnMut(X) -> ControlFlow<ControlFlow<T, Ordering>> + 'a
+ where
+ B: Iterator,
+ {
+ move |x| match b.next() {
+ None => ControlFlow::Break(ControlFlow::Continue(Ordering::Greater)),
+ Some(y) => f(x, y).map_break(ControlFlow::Break),
+ }
+ }
+
+ match a.try_for_each(compare(&mut b, f)) {
+ ControlFlow::Continue(()) => ControlFlow::Continue(match b.next() {
+ None => Ordering::Equal,
+ Some(_) => Ordering::Less,
+ }),
+ ControlFlow::Break(x) => x,
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for &mut I {
type Item = I::Item;
diff --git a/library/core/src/lazy.rs b/library/core/src/lazy.rs
deleted file mode 100644
index f8c06c3f9..000000000
--- a/library/core/src/lazy.rs
+++ /dev/null
@@ -1 +0,0 @@
-//! Lazy values and one-time initialization of static data.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 5621d15c1..659409557 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -114,6 +114,7 @@
#![feature(const_fmt_arguments_new)]
#![feature(const_heap)]
#![feature(const_convert)]
+#![feature(const_index_range_slice_index)]
#![feature(const_inherent_unchecked_arith)]
#![feature(const_int_unchecked_arith)]
#![feature(const_intrinsic_forget)]
@@ -137,17 +138,21 @@
#![feature(const_size_of_val)]
#![feature(const_slice_from_raw_parts_mut)]
#![feature(const_slice_ptr_len)]
+#![feature(const_slice_split_at_mut)]
#![feature(const_str_from_utf8_unchecked_mut)]
#![feature(const_swap)]
#![feature(const_trait_impl)]
+#![feature(const_try)]
#![feature(const_type_id)]
#![feature(const_type_name)]
#![feature(const_default_impls)]
#![feature(const_unicode_case_lookup)]
#![feature(const_unsafecell_get_mut)]
+#![feature(const_waker)]
#![feature(core_panic)]
#![feature(duration_consts_float)]
#![feature(maybe_uninit_uninit_array)]
+#![feature(ptr_alignment_type)]
#![feature(ptr_metadata)]
#![feature(slice_ptr_get)]
#![feature(slice_split_at_unchecked)]
@@ -160,6 +165,7 @@
#![feature(const_slice_index)]
#![feature(const_is_char_boundary)]
#![feature(const_cstr_methods)]
+#![feature(is_ascii_octdigit)]
//
// Language features:
#![feature(abi_unadjusted)]
@@ -168,6 +174,7 @@
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(auto_traits)]
+#![feature(c_unwind)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
@@ -185,13 +192,13 @@
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(if_let_guard)]
+#![feature(inline_const)]
#![feature(intra_doc_pointers)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(macro_metavar_expr)]
#![feature(min_specialization)]
-#![feature(mixed_integer_ops)]
#![feature(must_not_suspend)]
#![feature(negative_impls)]
#![feature(never_type)]
@@ -205,12 +212,14 @@
#![feature(simd_ffi)]
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
+#![feature(target_feature_11)]
#![feature(trait_alias)]
#![feature(transparent_unions)]
#![feature(try_blocks)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
#![feature(asm_const)]
+#![feature(const_transmute_copy)]
//
// Target features:
#![feature(arm_target_feature)]
@@ -220,6 +229,7 @@
#![feature(hexagon_target_feature)]
#![feature(mips_target_feature)]
#![feature(powerpc_target_feature)]
+#![feature(riscv_target_feature)]
#![feature(rtm_target_feature)]
#![feature(sse4a_target_feature)]
#![feature(tbm_target_feature)]
@@ -306,7 +316,6 @@ pub mod clone;
pub mod cmp;
pub mod convert;
pub mod default;
-#[cfg(not(bootstrap))]
pub mod error;
pub mod marker;
pub mod ops;
@@ -323,8 +332,6 @@ pub mod cell;
pub mod char;
pub mod ffi;
pub mod iter;
-#[unstable(feature = "once_cell", issue = "74465")]
-pub mod lazy;
pub mod option;
pub mod panic;
pub mod panicking;
@@ -353,6 +360,8 @@ 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 b8239ed88..ae4ebf444 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -44,6 +44,12 @@ impl<T: ?Sized> !Send for *const T {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Send for *mut T {}
+// Most instances arise automatically, but this instance is needed to link up `T: Sync` with
+// `&T: Send` (and it also removes the unsound default instance `T Send` -> `&T: Send` that would
+// otherwise exist).
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<T: Sync + ?Sized> Send for &T {}
+
/// Types with a constant size known at compile time.
///
/// All type parameters have an implicit bound of `Sized`. The special syntax
@@ -81,6 +87,7 @@ impl<T: ?Sized> !Send for *mut T {}
/// ```
///
/// [trait object]: ../../book/ch17-02-trait-objects.html
+#[doc(alias = "?", alias = "?Sized")]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang = "sized"]
#[rustc_on_unimplemented(
@@ -482,64 +489,6 @@ impl<T: ?Sized> !Sync for *const T {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> !Sync for *mut T {}
-macro_rules! impls {
- ($t: ident) => {
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> Hash for $t<T> {
- #[inline]
- fn hash<H: Hasher>(&self, _: &mut H) {}
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> cmp::PartialEq for $t<T> {
- fn eq(&self, _other: &$t<T>) -> bool {
- true
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> cmp::Eq for $t<T> {}
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> cmp::PartialOrd for $t<T> {
- fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
- Option::Some(cmp::Ordering::Equal)
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> cmp::Ord for $t<T> {
- fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
- cmp::Ordering::Equal
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> Copy for $t<T> {}
-
- #[stable(feature = "rust1", since = "1.0.0")]
- impl<T: ?Sized> Clone for $t<T> {
- fn clone(&self) -> Self {
- Self
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
- impl<T: ?Sized> const Default for $t<T> {
- fn default() -> Self {
- Self
- }
- }
-
- #[unstable(feature = "structural_match", issue = "31434")]
- impl<T: ?Sized> StructuralPartialEq for $t<T> {}
-
- #[unstable(feature = "structural_match", issue = "31434")]
- impl<T: ?Sized> StructuralEq for $t<T> {}
- };
-}
-
/// Zero-sized type used to mark things that "act like" they own a `T`.
///
/// Adding a `PhantomData<T>` field to your type tells the compiler that your
@@ -677,15 +626,60 @@ macro_rules! impls {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct PhantomData<T: ?Sized>;
-impls! { PhantomData }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Hash for PhantomData<T> {
+ #[inline]
+ fn hash<H: Hasher>(&self, _: &mut H) {}
+}
-mod impls {
- #[stable(feature = "rust1", since = "1.0.0")]
- unsafe impl<T: Sync + ?Sized> Send for &T {}
- #[stable(feature = "rust1", since = "1.0.0")]
- unsafe impl<T: Send + ?Sized> Send for &mut T {}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> cmp::PartialEq for PhantomData<T> {
+ fn eq(&self, _other: &PhantomData<T>) -> bool {
+ true
+ }
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> cmp::Eq for PhantomData<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> cmp::PartialOrd for PhantomData<T> {
+ fn partial_cmp(&self, _other: &PhantomData<T>) -> Option<cmp::Ordering> {
+ Option::Some(cmp::Ordering::Equal)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> cmp::Ord for PhantomData<T> {
+ fn cmp(&self, _other: &PhantomData<T>) -> cmp::Ordering {
+ cmp::Ordering::Equal
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Copy for PhantomData<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Clone for PhantomData<T> {
+ fn clone(&self) -> Self {
+ Self
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+impl<T: ?Sized> const Default for PhantomData<T> {
+ fn default() -> Self {
+ Self
+ }
+}
+
+#[unstable(feature = "structural_match", issue = "31434")]
+impl<T: ?Sized> StructuralPartialEq for PhantomData<T> {}
+
+#[unstable(feature = "structural_match", issue = "31434")]
+impl<T: ?Sized> StructuralEq for PhantomData<T> {}
+
/// Compiler-internal trait used to indicate the type of enum discriminants.
///
/// This trait is automatically implemented for every type and does not add any
@@ -798,6 +792,7 @@ impl<T: ?Sized> Unpin for *mut T {}
#[unstable(feature = "const_trait_impl", issue = "67792")]
#[lang = "destruct"]
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
+#[const_trait]
pub trait Destruct {}
/// A marker for tuple types.
@@ -805,7 +800,7 @@ pub trait Destruct {}
/// The implementation of this trait is built-in and cannot be implemented
/// for any user type.
#[unstable(feature = "tuple_trait", issue = "none")]
-#[cfg_attr(not(bootstrap), lang = "tuple_trait")]
+#[lang = "tuple_trait"]
#[rustc_on_unimplemented(message = "`{Self}` is not a tuple")]
pub trait Tuple {}
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 2490c0767..7757c95de 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -146,7 +146,6 @@ use crate::slice;
///
/// ```
/// use std::mem::MaybeUninit;
-/// use std::ptr;
///
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
/// // safe because the type we are claiming to have initialized here is a
@@ -162,7 +161,7 @@ use crate::slice;
///
/// // For each item in the array, drop if we allocated it.
/// for elem in &mut data[0..data_len] {
-/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
+/// unsafe { elem.assume_init_drop(); }
/// }
/// ```
///
@@ -647,7 +646,7 @@ impl<T> MaybeUninit<T> {
/// implements the [`Copy`] trait or not. When using multiple copies of the
/// data (by calling `assume_init_read` multiple times, or first calling
/// `assume_init_read` and then [`assume_init`]), it is your responsibility
- /// to ensure that that data may indeed be duplicated.
+ /// to ensure that data may indeed be duplicated.
///
/// [inv]: #initialization-invariant
/// [`assume_init`]: MaybeUninit::assume_init
@@ -1284,3 +1283,42 @@ impl<T> MaybeUninit<T> {
}
}
}
+
+impl<T, const N: usize> MaybeUninit<[T; N]> {
+ /// Transposes a `MaybeUninit<[T; N]>` into a `[MaybeUninit<T>; N]`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(maybe_uninit_uninit_array_transpose)]
+ /// # use std::mem::MaybeUninit;
+ ///
+ /// let data: [MaybeUninit<u8>; 1000] = MaybeUninit::uninit().transpose();
+ /// ```
+ #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")]
+ #[inline]
+ pub const fn transpose(self) -> [MaybeUninit<T>; N] {
+ // SAFETY: T and MaybeUninit<T> have the same layout
+ unsafe { super::transmute_copy(&ManuallyDrop::new(self)) }
+ }
+}
+
+impl<T, const N: usize> [MaybeUninit<T>; N] {
+ /// Transposes a `[MaybeUninit<T>; N]` into a `MaybeUninit<[T; N]>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(maybe_uninit_uninit_array_transpose)]
+ /// # use std::mem::MaybeUninit;
+ ///
+ /// let data = [MaybeUninit::<u8>::uninit(); 1000];
+ /// let data: MaybeUninit<[u8; 1000]> = data.transpose();
+ /// ```
+ #[unstable(feature = "maybe_uninit_uninit_array_transpose", issue = "96097")]
+ #[inline]
+ pub const fn transpose(self) -> MaybeUninit<[T; N]> {
+ // SAFETY: T and MaybeUninit<T> have the same layout
+ unsafe { super::transmute_copy(&ManuallyDrop::new(self)) }
+ }
+}
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index d2dd2941d..9195da5a4 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -21,11 +21,10 @@ mod maybe_uninit;
#[stable(feature = "maybe_uninit", since = "1.36.0")]
pub use maybe_uninit::MaybeUninit;
-mod valid_align;
-// For now this type is left crate-local. It could potentially make sense to expose
-// it publicly, as it would be a nice parameter type for methods which need to take
-// alignment as a parameter, such as `Layout::padding_needed_for`.
-pub(crate) use valid_align::ValidAlign;
+// FIXME: This is left here for now to avoid complications around pending reverts.
+// Once <https://github.com/rust-lang/rust/issues/101899> is fully resolved,
+// this should be removed and the references in `alloc::Layout` updated.
+pub(crate) use ptr::Alignment as ValidAlign;
mod transmutability;
#[unstable(feature = "transmutability", issue = "99571")]
@@ -1009,18 +1008,18 @@ pub fn copy<T: Copy>(x: &T) -> T {
*x
}
-/// Interprets `src` as having type `&U`, and then reads `src` without moving
+/// Interprets `src` as having type `&Dst`, and then reads `src` without moving
/// the contained value.
///
-/// This function will unsafely assume the pointer `src` is valid for [`size_of::<U>`][size_of]
-/// bytes by transmuting `&T` to `&U` and then reading the `&U` (except that this is done in a way
-/// that is correct even when `&U` has stricter alignment requirements than `&T`). It will also
-/// unsafely create a copy of the contained value instead of moving out of `src`.
+/// This function will unsafely assume the pointer `src` is valid for [`size_of::<Dst>`][size_of]
+/// bytes by transmuting `&Src` to `&Dst` and then reading the `&Dst` (except that this is done
+/// in a way that is correct even when `&Dst` has stricter alignment requirements than `&Src`).
+/// It will also unsafely create a copy of the contained value instead of moving out of `src`.
///
-/// It is not a compile-time error if `T` and `U` have different sizes, but it
-/// is highly encouraged to only invoke this function where `T` and `U` have the
-/// same size. This function triggers [undefined behavior][ub] if `U` is larger than
-/// `T`.
+/// It is not a compile-time error if `Src` and `Dst` have different sizes, but it
+/// is highly encouraged to only invoke this function where `Src` and `Dst` have the
+/// same size. This function triggers [undefined behavior][ub] if `Dst` is larger than
+/// `Src`.
///
/// [ub]: ../../reference/behavior-considered-undefined.html
///
@@ -1053,19 +1052,22 @@ pub fn copy<T: Copy>(x: &T) -> T {
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
-pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
- assert!(size_of::<T>() >= size_of::<U>(), "cannot transmute_copy if U is larger than T");
+pub const unsafe fn transmute_copy<Src, Dst>(src: &Src) -> Dst {
+ assert!(
+ size_of::<Src>() >= size_of::<Dst>(),
+ "cannot transmute_copy if Dst is larger than Src"
+ );
- // If U has a higher alignment requirement, src might not be suitably aligned.
- if align_of::<U>() > align_of::<T>() {
+ // If Dst has a higher alignment requirement, src might not be suitably aligned.
+ if align_of::<Dst>() > align_of::<Src>() {
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
// The caller must guarantee that the actual transmutation is safe.
- unsafe { ptr::read_unaligned(src as *const T as *const U) }
+ unsafe { ptr::read_unaligned(src as *const Src as *const Dst) }
} else {
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.
- // We just checked that `src as *const U` was properly aligned.
+ // We just checked that `src as *const Dst` was properly aligned.
// The caller must guarantee that the actual transmutation is safe.
- unsafe { ptr::read(src as *const T as *const U) }
+ unsafe { ptr::read(src as *const Src as *const Dst) }
}
}
@@ -1178,3 +1180,44 @@ pub const fn discriminant<T>(v: &T) -> Discriminant<T> {
pub const fn variant_count<T>() -> usize {
intrinsics::variant_count::<T>()
}
+
+/// Provides associated constants for various useful properties of types,
+/// to give them a canonical form in our code and make them easier to read.
+///
+/// This is here only to simplify all the ZST checks we need in the library.
+/// It's not on a stabilization track right now.
+#[doc(hidden)]
+#[unstable(feature = "sized_type_properties", issue = "none")]
+pub trait SizedTypeProperties: Sized {
+ /// `true` if this type requires no storage.
+ /// `false` if its [size](size_of) is greater than zero.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(sized_type_properties)]
+ /// use core::mem::SizedTypeProperties;
+ ///
+ /// fn do_something_with<T>() {
+ /// if T::IS_ZST {
+ /// // ... special approach ...
+ /// } else {
+ /// // ... the normal thing ...
+ /// }
+ /// }
+ ///
+ /// struct MyUnit;
+ /// assert!(MyUnit::IS_ZST);
+ ///
+ /// // For negative checks, consider using UFCS to emphasize the negation
+ /// assert!(!<i32>::IS_ZST);
+ /// // As it can sometimes hide in the type otherwise
+ /// assert!(!String::IS_ZST);
+ /// ```
+ #[doc(hidden)]
+ #[unstable(feature = "sized_type_properties", issue = "none")]
+ const IS_ZST: bool = size_of::<Self>() == 0;
+}
+#[doc(hidden)]
+#[unstable(feature = "sized_type_properties", issue = "none")]
+impl<T> SizedTypeProperties for T {}
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index 87a378631..3b98efff2 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -4,7 +4,7 @@
/// any value of type `Self` are safely transmutable into a value of type `Dst`, in a given `Context`,
/// notwithstanding whatever safety checks you have asked the compiler to [`Assume`] are satisfied.
#[unstable(feature = "transmutability", issue = "99571")]
-#[cfg_attr(not(bootstrap), lang = "transmute_trait")]
+#[lang = "transmute_trait"]
#[rustc_on_unimplemented(
message = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`.",
label = "`{Src}` cannot be safely transmuted into `{Self}` in the defining scope of `{Context}`."
@@ -17,7 +17,7 @@ where
/// What transmutation safety conditions shall the compiler assume that *you* are checking?
#[unstable(feature = "transmutability", issue = "99571")]
-#[cfg_attr(not(bootstrap), lang = "transmute_opts")]
+#[lang = "transmute_opts"]
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct Assume {
/// When `true`, the compiler assumes that *you* are ensuring (either dynamically or statically) that
diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs
index 75405f471..9f7594460 100644
--- a/library/core/src/num/dec2flt/lemire.rs
+++ b/library/core/src/num/dec2flt/lemire.rs
@@ -6,7 +6,7 @@ use crate::num::dec2flt::table::{
LARGEST_POWER_OF_FIVE, POWER_OF_FIVE_128, SMALLEST_POWER_OF_FIVE,
};
-/// Compute a float using an extended-precision representation.
+/// Compute w * 10^q using an extended-precision float representation.
///
/// Fast conversion of a the significant digits and decimal exponent
/// a float to an extended representation with a binary float. This
@@ -76,7 +76,7 @@ pub fn compute_float<F: RawFloat>(q: i64, mut w: u64) -> BiasedFp {
return BiasedFp { f: mantissa, e: power2 };
}
// Need to handle rounding ties. Normally, we need to round up,
- // but if we fall right in between and and we have an even basis, we
+ // but if we fall right in between and we have an even basis, we
// need to round down.
//
// This will only occur if:
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index 1f6b40e5d..768dd8781 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -1,7 +1,6 @@
//! Error types for conversion to integral types.
use crate::convert::Infallible;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
@@ -147,7 +146,6 @@ impl fmt::Display for ParseIntError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseIntError {
#[allow(deprecated)]
@@ -156,7 +154,6 @@ impl Error for ParseIntError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "try_from", since = "1.34.0")]
impl Error for TryFromIntError {
#[allow(deprecated)]
diff --git a/library/core/src/num/flt2dec/strategy/grisu.rs b/library/core/src/num/flt2dec/strategy/grisu.rs
index a4cb51c62..ed3e0edaf 100644
--- a/library/core/src/num/flt2dec/strategy/grisu.rs
+++ b/library/core/src/num/flt2dec/strategy/grisu.rs
@@ -253,7 +253,6 @@ pub fn format_shortest_opt<'a>(
let delta1frac = delta1 & ((1 << e) - 1);
// render integral parts, while checking for the accuracy at each step.
- let mut kappa = max_kappa as i16;
let mut ten_kappa = max_ten_kappa; // 10^kappa
let mut remainder = plus1int; // digits yet to be rendered
loop {
@@ -290,12 +289,10 @@ pub fn format_shortest_opt<'a>(
// the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`.
if i > max_kappa as usize {
debug_assert_eq!(ten_kappa, 1);
- debug_assert_eq!(kappa, 0);
break;
}
// restore invariants
- kappa -= 1;
ten_kappa /= 10;
remainder = r;
}
@@ -338,7 +335,6 @@ pub fn format_shortest_opt<'a>(
}
// restore invariants
- kappa -= 1;
remainder = r;
}
diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs
index cc26c04a5..80472528f 100644
--- a/library/core/src/num/int_log10.rs
+++ b/library/core/src/num/int_log10.rs
@@ -1,5 +1,5 @@
/// These functions compute the integer logarithm of their type, assuming
-/// that someone has already checked that the the value is strictly positive.
+/// that someone has already checked that the value is strictly positive.
// 0 < val <= u8::MAX
#[inline]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index e7deb728d..914dca61b 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -464,12 +464,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -533,12 +532,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -654,7 +652,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")]
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")]
@@ -706,7 +703,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);")]
/// ```
@@ -822,7 +818,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);")]
/// ```
@@ -874,7 +869,7 @@ macro_rules! int_impl {
// Deal with the final bit of the exponent separately, since
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
- Some(try_opt!(acc.checked_mul(base)))
+ acc.checked_mul(base)
}
/// Saturating integer addition. Computes `self + rhs`, saturating at the numeric
@@ -907,12 +902,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -954,12 +948,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1030,7 +1023,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);")]
@@ -1089,7 +1081,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);")]
@@ -1135,12 +1126,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@@ -1176,12 +1166,11 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")]
#[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@@ -1504,7 +1493,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));")]
/// ```
@@ -1574,13 +1562,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1600,7 +1587,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")]
/// ```
@@ -1658,13 +1644,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1711,7 +1696,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));")]
/// ```
@@ -1774,7 +1758,6 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));")]
/// ```
@@ -2287,9 +2270,8 @@ macro_rules! int_impl {
///
/// # Panics
///
- /// When the number is negative, zero, or if the base is not at least 2; it
- /// panics in debug mode and the return value is 0 in release
- /// mode.
+ /// This function will panic if `self` is less than or equal to zero,
+ /// or if `base` is less then 2.
///
/// # Examples
///
@@ -2302,27 +2284,16 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog(self, base: Self) -> u32 {
- match self.checked_ilog(base) {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ assert!(base >= 2, "base of integer logarithm must be at least 2");
+ self.checked_ilog(base).expect("argument of integer logarithm must be positive")
}
/// Returns the base 2 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is negative or zero it panics in debug mode and the return value
- /// is 0 in release mode.
+ /// This function will panic if `self` is less than or equal to zero.
///
/// # Examples
///
@@ -2335,27 +2306,15 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog2(self) -> u32 {
- match self.checked_ilog2() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ self.checked_ilog2().expect("argument of integer logarithm must be positive")
}
/// Returns the base 10 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is negative or zero it panics in debug mode and the return value
- /// is 0 in release mode.
+ /// This function will panic if `self` is less than or equal to zero.
///
/// # Example
///
@@ -2368,19 +2327,8 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog10(self) -> u32 {
- match self.checked_ilog10() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ self.checked_ilog10().expect("argument of integer logarithm must be positive")
}
/// Returns the logarithm of the number with respect to an arbitrary base,
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index ab17aa0c8..311c5fa5b 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -3,7 +3,6 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::ascii;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::intrinsics;
use crate::mem;
@@ -59,7 +58,6 @@ pub use wrapping::Wrapping;
#[cfg(not(no_fp_fmt_parse))]
pub use dec2flt::ParseFloatError;
-#[cfg(not(bootstrap))]
#[cfg(not(no_fp_fmt_parse))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseFloatError {
@@ -113,6 +111,9 @@ macro_rules! widening_impl {
/// This returns the low-order (wrapping) bits and the high-order (overflow) bits
/// of the result as two separate values, in that order.
///
+ /// If you also need to add a carry to the wide result, then you want
+ /// [`Self::carrying_mul`] instead.
+ ///
/// # Examples
///
/// Basic usage:
@@ -148,6 +149,8 @@ macro_rules! widening_impl {
/// additional amount of overflow. This allows for chaining together multiple
/// multiplications to create "big integers" which represent larger values.
///
+ /// If you don't need the `carry`, then you can use [`Self::widening_mul`] instead.
+ ///
/// # Examples
///
/// Basic usage:
@@ -167,6 +170,31 @@ macro_rules! widening_impl {
)]
/// ```
///
+ /// This is the core operation needed for scalar multiplication when
+ /// implementing it for wider-than-native types.
+ ///
+ /// ```
+ /// #![feature(bigint_helper_methods)]
+ /// fn scalar_mul_eq(little_endian_digits: &mut Vec<u16>, multiplicand: u16) {
+ /// let mut carry = 0;
+ /// for d in little_endian_digits.iter_mut() {
+ /// (*d, carry) = d.carrying_mul(multiplicand, carry);
+ /// }
+ /// if carry != 0 {
+ /// little_endian_digits.push(carry);
+ /// }
+ /// }
+ ///
+ /// let mut v = vec![10, 20];
+ /// scalar_mul_eq(&mut v, 3);
+ /// assert_eq!(v, [30, 60]);
+ ///
+ /// assert_eq!(0x87654321_u64 * 0xFEED, 0x86D3D159E38D);
+ /// let mut v = vec![0x4321, 0x8765];
+ /// scalar_mul_eq(&mut v, 0xFEED);
+ /// assert_eq!(v, [0xE38D, 0xD159, 0x86D3]);
+ /// ```
+ ///
/// If `carry` is zero, this is similar to [`overflowing_mul`](Self::overflowing_mul),
/// except that it gives the value of the overflow instead of just whether one happened:
///
@@ -594,6 +622,38 @@ impl u8 {
matches!(*self, b'0'..=b'9')
}
+ /// Checks if the value is an ASCII octal digit:
+ /// U+0030 '0' ..= U+0037 '7'.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_ascii_octdigit)]
+ ///
+ /// let uppercase_a = b'A';
+ /// let a = b'a';
+ /// let zero = b'0';
+ /// let seven = b'7';
+ /// let nine = b'9';
+ /// let percent = b'%';
+ /// let lf = b'\n';
+ ///
+ /// assert!(!uppercase_a.is_ascii_octdigit());
+ /// assert!(!a.is_ascii_octdigit());
+ /// assert!(zero.is_ascii_octdigit());
+ /// assert!(seven.is_ascii_octdigit());
+ /// assert!(!nine.is_ascii_octdigit());
+ /// assert!(!percent.is_ascii_octdigit());
+ /// assert!(!lf.is_ascii_octdigit());
+ /// ```
+ #[must_use]
+ #[unstable(feature = "is_ascii_octdigit", issue = "101288")]
+ #[rustc_const_unstable(feature = "is_ascii_octdigit", issue = "101288")]
+ #[inline]
+ pub const fn is_ascii_octdigit(&self) -> bool {
+ matches!(*self, b'0'..=b'7')
+ }
+
/// Checks if the value is an ASCII hexadecimal digit:
///
/// - U+0030 '0' ..= U+0039 '9', or
@@ -948,8 +1008,8 @@ impl usize {
/// assert_eq!(num.classify(), FpCategory::Normal);
/// assert_eq!(inf.classify(), FpCategory::Infinite);
/// assert_eq!(zero.classify(), FpCategory::Zero);
-/// assert_eq!(nan.classify(), FpCategory::Nan);
/// assert_eq!(sub.classify(), FpCategory::Subnormal);
+/// assert_eq!(nan.classify(), FpCategory::Nan);
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 532a09736..6b6f3417f 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -56,7 +56,10 @@ macro_rules! nonzero_integers {
pub const unsafe fn new_unchecked(n: $Int) -> Self {
// SAFETY: this is guaranteed to be safe by the caller.
unsafe {
- core::intrinsics::assert_unsafe_precondition!((n: $Int) => n != 0);
+ core::intrinsics::assert_unsafe_precondition!(
+ concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument"),
+ (n: $Int) => n != 0
+ );
Self(n)
}
}
@@ -721,6 +724,160 @@ macro_rules! nonzero_signed_operations {
// SAFETY: absolute value of nonzero cannot yield zero values.
unsafe { $Uty::new_unchecked(self.get().unsigned_abs()) }
}
+
+ /// Returns `true` if `self` is negative and `false` if the
+ /// number is positive.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(nonzero_negation_ops)]
+ ///
+ #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Option<()> {
+ #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+ #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+ ///
+ /// assert!(neg_five.is_negative());
+ /// assert!(!pos_five.is_negative());
+ /// # Some(())
+ /// # }
+ /// ```
+ #[must_use]
+ #[inline]
+ #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+ pub const fn is_negative(self) -> bool {
+ self.get().is_negative()
+ }
+
+ /// Checked negation. Computes `-self`, returning `None` if `self == i32::MIN`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(nonzero_negation_ops)]
+ ///
+ #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Option<()> {
+ #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+ #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+ #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MIN)?;")]
+ ///
+ /// assert_eq!(pos_five.checked_neg(), Some(neg_five));
+ /// assert_eq!(min.checked_neg(), None);
+ /// # Some(())
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+ pub const fn checked_neg(self) -> Option<$Ty> {
+ if let Some(result) = self.get().checked_neg() {
+ // SAFETY: negation of nonzero cannot yield zero values.
+ return Some(unsafe { $Ty::new_unchecked(result) });
+ }
+ None
+ }
+
+ /// Negates self, overflowing if this is equal to the minimum value.
+ ///
+ #[doc = concat!("See [`", stringify!($Int), "::overflowing_neg`]")]
+ /// for documentation on overflow behaviour.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(nonzero_negation_ops)]
+ ///
+ #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Option<()> {
+ #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+ #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+ #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MIN)?;")]
+ ///
+ /// assert_eq!(pos_five.overflowing_neg(), (neg_five, false));
+ /// assert_eq!(min.overflowing_neg(), (min, true));
+ /// # Some(())
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+ pub const fn overflowing_neg(self) -> ($Ty, bool) {
+ let (result, overflow) = self.get().overflowing_neg();
+ // SAFETY: negation of nonzero cannot yield zero values.
+ ((unsafe { $Ty::new_unchecked(result) }), overflow)
+ }
+
+ /// Saturating negation. Computes `-self`, returning `MAX` if
+ /// `self == i32::MIN` instead of overflowing.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(nonzero_negation_ops)]
+ ///
+ #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Option<()> {
+ #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+ #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+ #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MIN)?;")]
+ #[doc = concat!("let min_plus_one = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MIN + 1)?;")]
+ #[doc = concat!("let max = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MAX)?;")]
+ ///
+ /// assert_eq!(pos_five.saturating_neg(), neg_five);
+ /// assert_eq!(min.saturating_neg(), max);
+ /// assert_eq!(max.saturating_neg(), min_plus_one);
+ /// # Some(())
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+ pub const fn saturating_neg(self) -> $Ty {
+ if let Some(result) = self.checked_neg() {
+ return result;
+ }
+ $Ty::MAX
+ }
+
+ /// Wrapping (modular) negation. Computes `-self`, wrapping around at the boundary
+ /// of the type.
+ ///
+ #[doc = concat!("See [`", stringify!($Int), "::wrapping_neg`]")]
+ /// for documentation on overflow behaviour.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// #![feature(nonzero_negation_ops)]
+ ///
+ #[doc = concat!("# use std::num::", stringify!($Ty), ";")]
+ /// # fn main() { test().unwrap(); }
+ /// # fn test() -> Option<()> {
+ #[doc = concat!("let pos_five = ", stringify!($Ty), "::new(5)?;")]
+ #[doc = concat!("let neg_five = ", stringify!($Ty), "::new(-5)?;")]
+ #[doc = concat!("let min = ", stringify!($Ty), "::new(",
+ stringify!($Int), "::MIN)?;")]
+ ///
+ /// assert_eq!(pos_five.wrapping_neg(), neg_five);
+ /// assert_eq!(min.wrapping_neg(), min);
+ /// # Some(())
+ /// # }
+ /// ```
+ #[inline]
+ #[unstable(feature = "nonzero_negation_ops", issue = "102443")]
+ pub const fn wrapping_neg(self) -> $Ty {
+ let result = self.get().wrapping_neg();
+ // SAFETY: negation of nonzero cannot yield zero values.
+ unsafe { $Ty::new_unchecked(result) }
+ }
}
)+
}
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 46fd7f2d0..335cc5124 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -474,13 +474,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -693,8 +692,7 @@ macro_rules! uint_impl {
///
/// # Panics
///
- /// When the number is zero, or if the base is not at least 2;
- /// it panics in debug mode and the return value is 0 in release mode.
+ /// This function will panic if `self` is zero, or if `base` is less then 2.
///
/// # Examples
///
@@ -707,27 +705,16 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog(self, base: Self) -> u32 {
- match self.checked_ilog(base) {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ assert!(base >= 2, "base of integer logarithm must be at least 2");
+ self.checked_ilog(base).expect("argument of integer logarithm must be positive")
}
/// Returns the base 2 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is zero it panics in debug mode and
- /// the return value is 0 in release mode.
+ /// This function will panic if `self` is zero.
///
/// # Examples
///
@@ -740,27 +727,15 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog2(self) -> u32 {
- match self.checked_ilog2() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ self.checked_ilog2().expect("argument of integer logarithm must be positive")
}
/// Returns the base 10 logarithm of the number, rounded down.
///
/// # Panics
///
- /// When the number is zero it panics in debug mode and the
- /// return value is 0 in release mode.
+ /// This function will panic if `self` is zero.
///
/// # Example
///
@@ -773,19 +748,8 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline]
#[track_caller]
- #[rustc_inherit_overflow_checks]
- #[allow(arithmetic_overflow)]
pub const fn ilog10(self) -> u32 {
- match self.checked_ilog10() {
- Some(n) => n,
- None => {
- // In debug builds, trigger a panic on None.
- // This should optimize completely out in release builds.
- let _ = Self::MAX + 1;
-
- 0
- },
- }
+ self.checked_ilog10().expect("argument of integer logarithm must be positive")
}
/// Returns the logarithm of the number with respect to an arbitrary base,
@@ -1026,7 +990,7 @@ macro_rules! uint_impl {
// squaring the base afterwards is not necessary and may cause a
// needless overflow.
- Some(try_opt!(acc.checked_mul(base)))
+ acc.checked_mul(base)
}
/// Saturating integer addition. Computes `self + rhs`, saturating at
@@ -1057,13 +1021,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1198,13 +1161,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1494,7 +1456,6 @@ macro_rules! uint_impl {
/// Basic usage
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")]
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")]
/// ```
@@ -1508,37 +1469,42 @@ macro_rules! uint_impl {
(a as Self, b)
}
- /// Calculates `self + rhs + carry` without the ability to overflow.
+ /// Calculates `self` + `rhs` + `carry` and returns a tuple containing
+ /// the sum and the output carry.
///
- /// Performs "ternary addition" which takes in an extra bit to add, and may return an
- /// additional bit of overflow. This allows for chaining together multiple additions
- /// to create "big integers" which represent larger values.
+ /// Performs "ternary addition" of two integer operands and a carry-in
+ /// bit, and returns an output integer and a carry-out bit. This allows
+ /// chaining together multiple additions to create a wider addition, and
+ /// can be useful for bignum addition.
///
#[doc = concat!("This can be thought of as a ", stringify!($BITS), "-bit \"full adder\", in the electronics sense.")]
///
- /// # Examples
+ /// If the input carry is false, this method is equivalent to
+ /// [`overflowing_add`](Self::overflowing_add), and the output carry is
+ /// equal to the overflow flag. Note that although carry and overflow
+ /// flags are similar for unsigned integers, they are different for
+ /// signed integers.
///
- /// Basic usage
+ /// # Examples
///
/// ```
/// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, false), (7, false));")]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".carrying_add(2, true), (8, false));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), (0, true));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(0, true), (0, true));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, true), (1, true));")]
- #[doc = concat!("assert_eq!(",
- stringify!($SelfT), "::MAX.carrying_add(", stringify!($SelfT), "::MAX, true), ",
- "(", stringify!($SelfT), "::MAX, true));"
- )]
- /// ```
///
- /// If `carry` is false, this method is equivalent to [`overflowing_add`](Self::overflowing_add):
+ #[doc = concat!("// 3 MAX (a = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+ #[doc = concat!("// + 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
+ /// // ---------
+ #[doc = concat!("// 9 6 (sum = 9 × 2^", stringify!($BITS), " + 6)")]
///
- /// ```
- /// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5_", stringify!($SelfT), ".carrying_add(2, false), 5_", stringify!($SelfT), ".overflowing_add(2));")]
- #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.carrying_add(1, false), ", stringify!($SelfT), "::MAX.overflowing_add(1));")]
+ #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (3, ", stringify!($SelfT), "::MAX);")]
+ #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")]
+ /// let carry0 = false;
+ ///
+ /// let (sum0, carry1) = a0.carrying_add(b0, carry0);
+ /// assert_eq!(carry1, true);
+ /// let (sum1, carry2) = a1.carrying_add(b1, carry1);
+ /// assert_eq!(carry2, false);
+ ///
+ /// assert_eq!((sum1, sum0), (9, 6));
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
@@ -1564,13 +1530,12 @@ macro_rules! uint_impl {
/// Basic usage:
///
/// ```
- /// # #![feature(mixed_integer_ops)]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")]
#[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")]
#[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")]
/// ```
- #[unstable(feature = "mixed_integer_ops", issue = "87840")]
- #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")]
+ #[stable(feature = "mixed_integer_ops", since = "1.66.0")]
+ #[rustc_const_stable(feature = "mixed_integer_ops", since = "1.66.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
@@ -1590,7 +1555,6 @@ macro_rules! uint_impl {
/// Basic usage
///
/// ```
- ///
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")]
#[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")]
/// ```
@@ -1604,22 +1568,35 @@ macro_rules! uint_impl {
(a as Self, b)
}
- /// Calculates `self - rhs - borrow` without the ability to overflow.
+ /// Calculates `self` &minus; `rhs` &minus; `borrow` and returns a tuple
+ /// containing the difference and the output borrow.
///
- /// Performs "ternary subtraction" which takes in an extra bit to subtract, and may return
- /// an additional bit of overflow. This allows for chaining together multiple subtractions
- /// to create "big integers" which represent larger values.
+ /// Performs "ternary subtraction" by subtracting both an integer
+ /// operand and a borrow-in bit from `self`, and returns an output
+ /// integer and a borrow-out bit. This allows chaining together multiple
+ /// subtractions to create a wider subtraction, and can be useful for
+ /// bignum subtraction.
///
/// # Examples
///
- /// Basic usage
- ///
/// ```
/// #![feature(bigint_helper_methods)]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, false), (3, false));")]
- #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".borrowing_sub(2, true), (2, false));")]
- #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, false), (", stringify!($SelfT), "::MAX, true));")]
- #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".borrowing_sub(1, true), (", stringify!($SelfT), "::MAX - 1, true));")]
+ ///
+ #[doc = concat!("// 9 6 (a = 9 × 2^", stringify!($BITS), " + 6)")]
+ #[doc = concat!("// - 5 7 (b = 5 × 2^", stringify!($BITS), " + 7)")]
+ /// // ---------
+ #[doc = concat!("// 3 MAX (diff = 3 × 2^", stringify!($BITS), " + 2^", stringify!($BITS), " - 1)")]
+ ///
+ #[doc = concat!("let (a1, a0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (9, 6);")]
+ #[doc = concat!("let (b1, b0): (", stringify!($SelfT), ", ", stringify!($SelfT), ") = (5, 7);")]
+ /// let borrow0 = false;
+ ///
+ /// let (diff0, borrow1) = a0.borrowing_sub(b0, borrow0);
+ /// assert_eq!(borrow1, true);
+ /// let (diff1, borrow2) = a1.borrowing_sub(b1, borrow1);
+ /// assert_eq!(borrow2, false);
+ ///
+ #[doc = concat!("assert_eq!((diff1, diff0), (3, ", stringify!($SelfT), "::MAX));")]
/// ```
#[unstable(feature = "bigint_helper_methods", issue = "85532")]
#[rustc_const_unstable(feature = "const_bigint_helper_methods", issue = "85532")]
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index e367be8c1..75c52d3ec 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -65,38 +65,15 @@
/// ```
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(
- bootstrap,
- rustc_on_unimplemented(
- on(
- all(_Self = "{integer}", Rhs = "{float}"),
- message = "cannot add a float to an integer",
- ),
- on(
- all(_Self = "{float}", Rhs = "{integer}"),
- message = "cannot add an integer to a float",
- ),
- message = "cannot add `{Rhs}` to `{Self}`",
- label = "no implementation for `{Self} + {Rhs}`"
- )
-)]
-#[cfg_attr(
- not(bootstrap),
- rustc_on_unimplemented(
- on(
- all(_Self = "{integer}", Rhs = "{float}"),
- message = "cannot add a float to an integer",
- ),
- on(
- all(_Self = "{float}", Rhs = "{integer}"),
- message = "cannot add an integer to a float",
- ),
- message = "cannot add `{Rhs}` to `{Self}`",
- label = "no implementation for `{Self} + {Rhs}`",
- append_const_msg,
- )
+#[rustc_on_unimplemented(
+ on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
+ on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
+ message = "cannot add `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} + {Rhs}`",
+ append_const_msg
)]
#[doc(alias = "+")]
+#[const_trait]
pub trait Add<Rhs = Self> {
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -201,9 +178,11 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
message = "cannot subtract `{Rhs}` from `{Self}`",
- label = "no implementation for `{Self} - {Rhs}`"
+ label = "no implementation for `{Self} - {Rhs}`",
+ append_const_msg
)]
#[doc(alias = "-")]
+#[const_trait]
pub trait Sub<Rhs = Self> {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -333,6 +312,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
label = "no implementation for `{Self} * {Rhs}`"
)]
#[doc(alias = "*")]
+#[const_trait]
pub trait Mul<Rhs = Self> {
/// The resulting type after applying the `*` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -466,6 +446,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
label = "no implementation for `{Self} / {Rhs}`"
)]
#[doc(alias = "/")]
+#[const_trait]
pub trait Div<Rhs = Self> {
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -568,6 +549,7 @@ div_impl_float! { f32 f64 }
label = "no implementation for `{Self} % {Rhs}`"
)]
#[doc(alias = "%")]
+#[const_trait]
pub trait Rem<Rhs = Self> {
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -682,6 +664,7 @@ rem_impl_float! { f32 f64 }
#[lang = "neg"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "-")]
+#[const_trait]
pub trait Neg {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -755,6 +738,7 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "+")]
#[doc(alias = "+=")]
+#[const_trait]
pub trait AddAssign<Rhs = Self> {
/// Performs the `+=` operation.
///
@@ -822,6 +806,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "-")]
#[doc(alias = "-=")]
+#[const_trait]
pub trait SubAssign<Rhs = Self> {
/// Performs the `-=` operation.
///
@@ -880,6 +865,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "*")]
#[doc(alias = "*=")]
+#[const_trait]
pub trait MulAssign<Rhs = Self> {
/// Performs the `*=` operation.
///
@@ -938,6 +924,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "/")]
#[doc(alias = "/=")]
+#[const_trait]
pub trait DivAssign<Rhs = Self> {
/// Performs the `/=` operation.
///
@@ -999,6 +986,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "%")]
#[doc(alias = "%=")]
+#[const_trait]
pub trait RemAssign<Rhs = Self> {
/// Performs the `%=` operation.
///
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 7c664226f..327009801 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -31,6 +31,7 @@
#[lang = "not"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "!")]
+#[const_trait]
pub trait Not {
/// The resulting type after applying the `!` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -143,6 +144,7 @@ impl const Not for ! {
message = "no implementation for `{Self} & {Rhs}`",
label = "no implementation for `{Self} & {Rhs}`"
)]
+#[const_trait]
pub trait BitAnd<Rhs = Self> {
/// The resulting type after applying the `&` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -244,6 +246,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} | {Rhs}`",
label = "no implementation for `{Self} | {Rhs}`"
)]
+#[const_trait]
pub trait BitOr<Rhs = Self> {
/// The resulting type after applying the `|` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -345,6 +348,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} ^ {Rhs}`",
label = "no implementation for `{Self} ^ {Rhs}`"
)]
+#[const_trait]
pub trait BitXor<Rhs = Self> {
/// The resulting type after applying the `^` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -445,6 +449,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} << {Rhs}`",
label = "no implementation for `{Self} << {Rhs}`"
)]
+#[const_trait]
pub trait Shl<Rhs = Self> {
/// The resulting type after applying the `<<` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -564,6 +569,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
message = "no implementation for `{Self} >> {Rhs}`",
label = "no implementation for `{Self} >> {Rhs}`"
)]
+#[const_trait]
pub trait Shr<Rhs = Self> {
/// The resulting type after applying the `>>` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -692,6 +698,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
message = "no implementation for `{Self} &= {Rhs}`",
label = "no implementation for `{Self} &= {Rhs}`"
)]
+#[const_trait]
pub trait BitAndAssign<Rhs = Self> {
/// Performs the `&=` operation.
///
@@ -764,6 +771,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} |= {Rhs}`",
label = "no implementation for `{Self} |= {Rhs}`"
)]
+#[const_trait]
pub trait BitOrAssign<Rhs = Self> {
/// Performs the `|=` operation.
///
@@ -836,6 +844,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} ^= {Rhs}`",
label = "no implementation for `{Self} ^= {Rhs}`"
)]
+#[const_trait]
pub trait BitXorAssign<Rhs = Self> {
/// Performs the `^=` operation.
///
@@ -906,6 +915,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} <<= {Rhs}`",
label = "no implementation for `{Self} <<= {Rhs}`"
)]
+#[const_trait]
pub trait ShlAssign<Rhs = Self> {
/// Performs the `<<=` operation.
///
@@ -989,6 +999,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
message = "no implementation for `{Self} >>= {Rhs}`",
label = "no implementation for `{Self} >>= {Rhs}`"
)]
+#[const_trait]
pub trait ShrAssign<Rhs = Self> {
/// Performs the `>>=` operation.
///
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index b1f5559dc..72ebe653c 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -95,7 +95,8 @@ pub enum ControlFlow<B, C = ()> {
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::Try for ControlFlow<B, C> {
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<B, C> const ops::Try for ControlFlow<B, C> {
type Output = C;
type Residual = ControlFlow<B, convert::Infallible>;
@@ -114,7 +115,8 @@ impl<B, C> ops::Try for ControlFlow<B, C> {
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::FromResidual for ControlFlow<B, C> {
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<B, C> const ops::FromResidual for ControlFlow<B, C> {
#[inline]
fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
match residual {
@@ -124,7 +126,8 @@ impl<B, C> ops::FromResidual for ControlFlow<B, C> {
}
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> {
type TryType = ControlFlow<B, C>;
}
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index d68932402..4f4c99c4a 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -61,6 +61,7 @@
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Deref"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Deref {
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -169,6 +170,7 @@ impl<T: ?Sized> const Deref for &mut T {
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait DerefMut: Deref {
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index de9ddb852..a2c3d978c 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -134,6 +134,7 @@
/// these types cannot have destructors.
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait Drop {
/// Executes the destructor for this type.
///
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index 8fdf22cf6..2e0a752c8 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -71,6 +71,7 @@
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Fn<Args>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -158,6 +159,7 @@ pub trait Fn<Args>: FnMut<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait FnMut<Args>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -237,6 +239,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait FnOnce<Args> {
/// The returned type after the call operator is used.
#[lang = "fn_once_output"]
diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs
index 3ebd6f8cd..fee4beb1e 100644
--- a/library/core/src/ops/generator.rs
+++ b/library/core/src/ops/generator.rs
@@ -83,7 +83,6 @@ pub trait Generator<R = ()> {
/// `return` statement or implicitly as the last expression of a generator
/// literal. For example futures would use this as `Result<T, E>` as it
/// represents a completed future.
- #[cfg_attr(bootstrap, lang = "generator_return")]
type Return;
/// Resumes the execution of this generator.
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index e2e569cb7..dd4e3ac1c 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -55,6 +55,7 @@
#[doc(alias = "]")]
#[doc(alias = "[")]
#[doc(alias = "[]")]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -163,6 +164,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
/// Performs the mutable indexing (`container[index]`) operation.
///
diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs
new file mode 100644
index 000000000..3e06776d2
--- /dev/null
+++ b/library/core/src/ops/index_range.rs
@@ -0,0 +1,171 @@
+use crate::intrinsics::{assert_unsafe_precondition, unchecked_add, unchecked_sub};
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Like a `Range<usize>`, but with a safety invariant that `start <= end`.
+///
+/// This means that `end - start` cannot overflow, allowing some μoptimizations.
+///
+/// (Normal `Range` code needs to handle degenerate ranges like `10..0`,
+/// which takes extra checks compared to only handling the canonical form.)
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub(crate) struct IndexRange {
+ start: usize,
+ end: usize,
+}
+
+impl IndexRange {
+ /// # Safety
+ /// - `start <= end`
+ #[inline]
+ pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self {
+ // SAFETY: comparisons on usize are pure
+ unsafe {
+ assert_unsafe_precondition!(
+ "IndexRange::new_unchecked requires `start <= end`",
+ (start: usize, end: usize) => start <= end
+ )
+ };
+ IndexRange { start, end }
+ }
+
+ #[inline]
+ pub const fn zero_to(end: usize) -> Self {
+ IndexRange { start: 0, end }
+ }
+
+ #[inline]
+ pub const fn start(&self) -> usize {
+ self.start
+ }
+
+ #[inline]
+ pub const fn end(&self) -> usize {
+ self.end
+ }
+
+ #[inline]
+ pub const fn len(&self) -> usize {
+ // SAFETY: By invariant, this cannot wrap
+ unsafe { unchecked_sub(self.end, self.start) }
+ }
+
+ /// # Safety
+ /// - Can only be called when `start < end`, aka when `len > 0`.
+ #[inline]
+ unsafe fn next_unchecked(&mut self) -> usize {
+ debug_assert!(self.start < self.end);
+
+ let value = self.start;
+ // SAFETY: The range isn't empty, so this cannot overflow
+ self.start = unsafe { unchecked_add(value, 1) };
+ value
+ }
+
+ /// # Safety
+ /// - Can only be called when `start < end`, aka when `len > 0`.
+ #[inline]
+ unsafe fn next_back_unchecked(&mut self) -> usize {
+ debug_assert!(self.start < self.end);
+
+ // SAFETY: The range isn't empty, so this cannot overflow
+ let value = unsafe { unchecked_sub(self.end, 1) };
+ self.end = value;
+ value
+ }
+
+ /// Removes the first `n` items from this range, returning them as an `IndexRange`.
+ /// If there are fewer than `n`, then the whole range is returned and
+ /// `self` is left empty.
+ ///
+ /// This is designed to help implement `Iterator::advance_by`.
+ #[inline]
+ pub fn take_prefix(&mut self, n: usize) -> Self {
+ let mid = if n <= self.len() {
+ // SAFETY: We just checked that this will be between start and end,
+ // and thus the addition cannot overflow.
+ unsafe { unchecked_add(self.start, n) }
+ } else {
+ self.end
+ };
+ let prefix = Self { start: self.start, end: mid };
+ self.start = mid;
+ prefix
+ }
+
+ /// Removes the last `n` items from this range, returning them as an `IndexRange`.
+ /// If there are fewer than `n`, then the whole range is returned and
+ /// `self` is left empty.
+ ///
+ /// This is designed to help implement `Iterator::advance_back_by`.
+ #[inline]
+ pub fn take_suffix(&mut self, n: usize) -> Self {
+ let mid = if n <= self.len() {
+ // SAFETY: We just checked that this will be between start and end,
+ // and thus the addition cannot overflow.
+ unsafe { unchecked_sub(self.end, n) }
+ } else {
+ self.start
+ };
+ let suffix = Self { start: mid, end: self.end };
+ self.end = mid;
+ suffix
+ }
+}
+
+impl Iterator for IndexRange {
+ type Item = usize;
+
+ #[inline]
+ fn next(&mut self) -> Option<usize> {
+ if self.len() > 0 {
+ // SAFETY: We just checked that the range is non-empty
+ unsafe { Some(self.next_unchecked()) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.len();
+ (len, Some(len))
+ }
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+ let original_len = self.len();
+ self.take_prefix(n);
+ if n > original_len { Err(original_len) } else { Ok(()) }
+ }
+}
+
+impl DoubleEndedIterator for IndexRange {
+ #[inline]
+ fn next_back(&mut self) -> Option<usize> {
+ if self.len() > 0 {
+ // SAFETY: We just checked that the range is non-empty
+ unsafe { Some(self.next_back_unchecked()) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+ let original_len = self.len();
+ self.take_suffix(n);
+ if n > original_len { Err(original_len) } else { Ok(()) }
+ }
+}
+
+impl ExactSizeIterator for IndexRange {
+ #[inline]
+ fn len(&self) -> usize {
+ self.len()
+ }
+}
+
+// SAFETY: Because we only deal in `usize`, our `len` is always perfect.
+unsafe impl TrustedLen for IndexRange {}
+
+impl FusedIterator for IndexRange {}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 31c1a1d09..a5e5b13b3 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -146,6 +146,7 @@ mod drop;
mod function;
mod generator;
mod index;
+mod index_range;
mod range;
mod try_trait;
mod unsize;
@@ -178,6 +179,8 @@ pub use self::index::{Index, IndexMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
+pub(crate) use self::index_range::IndexRange;
+
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 10f041344..84a690468 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -128,7 +128,8 @@ use crate::ops::ControlFlow;
)]
#[doc(alias = "?")]
#[lang = "Try"]
-pub trait Try: FromResidual {
+#[const_trait]
+pub trait Try: ~const FromResidual {
/// The type of the value produced by `?` when *not* short-circuiting.
#[unstable(feature = "try_trait_v2", issue = "84277")]
type Output;
@@ -222,7 +223,7 @@ pub trait Try: FromResidual {
/// Every `Try` type needs to be recreatable from its own associated
/// `Residual` type, but can also have additional `FromResidual` implementations
/// to support interconversion with other `Try` types.
-#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
+#[rustc_on_unimplemented(
on(
all(
from_desugaring = "QuestionMark",
@@ -301,89 +302,10 @@ pub trait Try: FromResidual {
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
parent_label = "this function should return `Result` or `Option` to accept `?`"
),
-))]
-#[cfg_attr(bootstrap, rustc_on_unimplemented(
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::result::Result<T, E>",
- R = "std::option::Option<std::convert::Infallible>"
- ),
- message = "the `?` operator can only be used on `Result`s, not `Option`s, \
- in {ItemContext} that returns `Result`",
- label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
- enclosing_scope = "this function returns a `Result`"
- ),
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::result::Result<T, E>",
- ),
- // There's a special error message in the trait selection code for
- // `From` in `?`, so this is not shown for result-in-result errors,
- // and thus it can be phrased more strongly than `ControlFlow`'s.
- message = "the `?` operator can only be used on `Result`s \
- in {ItemContext} that returns `Result`",
- label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `Result`"
- ),
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::option::Option<T>",
- R = "std::result::Result<T, E>",
- ),
- message = "the `?` operator can only be used on `Option`s, not `Result`s, \
- in {ItemContext} that returns `Option`",
- label = "use `.ok()?` if you want to discard the `{R}` error information",
- enclosing_scope = "this function returns an `Option`"
- ),
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::option::Option<T>",
- ),
- // `Option`-in-`Option` always works, as there's only one possible
- // residual, so this can also be phrased strongly.
- message = "the `?` operator can only be used on `Option`s \
- in {ItemContext} that returns `Option`",
- label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns an `Option`"
- ),
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::ops::ControlFlow<B, C>",
- R = "std::ops::ControlFlow<B, C>",
- ),
- message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
- can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
- label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `ControlFlow`",
- note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
- ),
- on(
- all(
- from_desugaring = "QuestionMark",
- _Self = "std::ops::ControlFlow<B, C>",
- // `R` is not a `ControlFlow`, as that case was matched previously
- ),
- message = "the `?` operator can only be used on `ControlFlow`s \
- in {ItemContext} that returns `ControlFlow`",
- label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `ControlFlow`",
- ),
- on(
- all(from_desugaring = "QuestionMark"),
- message = "the `?` operator can only be used in {ItemContext} \
- that returns `Result` or `Option` \
- (or another type that implements `{FromResidual}`)",
- label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
- enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
- ),
-))]
+)]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
+#[const_trait]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// Constructs the type from a compatible `Residual` type.
///
@@ -436,10 +358,11 @@ where
/// and in the other direction,
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+#[const_trait]
pub trait Residual<O> {
/// The "return" type of this meta-function.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
- type TryType: Try<Output = O, Residual = Self>;
+ type TryType: ~const Try<Output = O, Residual = Self>;
}
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
@@ -456,16 +379,19 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
pub(crate) struct NeverShortCircuit<T>(pub T);
impl<T> NeverShortCircuit<T> {
- /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
+ /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
#[inline]
- pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
- move |a, b| NeverShortCircuit(f(a, b))
+ 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(crate) enum NeverShortCircuitResidual {}
-impl<T> Try for NeverShortCircuit<T> {
+impl<T> const Try for NeverShortCircuit<T> {
type Output = T;
type Residual = NeverShortCircuitResidual;
@@ -480,14 +406,14 @@ impl<T> Try for NeverShortCircuit<T> {
}
}
-impl<T> FromResidual for NeverShortCircuit<T> {
+impl<T> const FromResidual for NeverShortCircuit<T> {
#[inline]
fn from_residual(never: NeverShortCircuitResidual) -> Self {
match never {}
}
}
-impl<T> Residual<T> for NeverShortCircuitResidual {
+impl<T> const Residual<T> for NeverShortCircuitResidual {
type TryType = NeverShortCircuit<T>;
}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 934175863..f284b4359 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -559,22 +559,25 @@ impl<T> Option<T> {
/// # Examples
///
/// ```
- /// #![feature(is_some_with)]
+ /// #![feature(is_some_and)]
///
/// let x: Option<u32> = Some(2);
- /// assert_eq!(x.is_some_and(|&x| x > 1), true);
+ /// assert_eq!(x.is_some_and(|x| x > 1), true);
///
/// let x: Option<u32> = Some(0);
- /// assert_eq!(x.is_some_and(|&x| x > 1), false);
+ /// assert_eq!(x.is_some_and(|x| x > 1), false);
///
/// let x: Option<u32> = None;
- /// assert_eq!(x.is_some_and(|&x| x > 1), false);
+ /// assert_eq!(x.is_some_and(|x| x > 1), false);
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "is_some_with", issue = "93050")]
- pub fn is_some_and(&self, f: impl FnOnce(&T) -> bool) -> bool {
- matches!(self, Some(x) if f(x))
+ #[unstable(feature = "is_some_and", issue = "93050")]
+ pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool {
+ match self {
+ None => false,
+ Some(x) => f(x),
+ }
}
/// Returns `true` if the option is a [`None`] value.
@@ -834,19 +837,12 @@ impl<T> Option<T> {
///
/// # Examples
///
- /// Converts a string to an integer, turning poorly-formed strings
- /// into 0 (the default value for integers). [`parse`] converts
- /// a string to any other type that implements [`FromStr`], returning
- /// [`None`] on error.
- ///
/// ```
- /// let good_year_from_input = "1909";
- /// let bad_year_from_input = "190blarg";
- /// let good_year = good_year_from_input.parse().ok().unwrap_or_default();
- /// let bad_year = bad_year_from_input.parse().ok().unwrap_or_default();
+ /// let x: Option<u32> = None;
+ /// let y: Option<u32> = Some(12);
///
- /// assert_eq!(1909, good_year);
- /// assert_eq!(0, bad_year);
+ /// assert_eq!(x.unwrap_or_default(), 0);
+ /// assert_eq!(y.unwrap_or_default(), 12);
/// ```
///
/// [default value]: Default::default
@@ -1717,8 +1713,6 @@ impl<T, U> Option<(T, U)> {
/// # Examples
///
/// ```
- /// #![feature(unzip_option)]
- ///
/// let x = Some((1, "hi"));
/// let y = None::<(u8, u32)>;
///
@@ -1726,8 +1720,13 @@ impl<T, U> Option<(T, U)> {
/// assert_eq!(y.unzip(), (None, None));
/// ```
#[inline]
- #[unstable(feature = "unzip_option", issue = "87800", reason = "recently added")]
- pub const fn unzip(self) -> (Option<T>, Option<U>) {
+ #[stable(feature = "unzip_option", since = "1.66.0")]
+ #[rustc_const_unstable(feature = "const_option", issue = "67441")]
+ pub const fn unzip(self) -> (Option<T>, Option<U>)
+ where
+ T: ~const Destruct,
+ U: ~const Destruct,
+ {
match self {
Some((a, b)) => (Some(a), Some(b)),
None => (None, None),
@@ -2321,7 +2320,8 @@ impl<T> ops::FromResidual<ops::Yeet<()>> for Option<T> {
}
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-impl<T> ops::Residual<T> for Option<convert::Infallible> {
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+impl<T> const ops::Residual<T> for Option<convert::Infallible> {
type TryType = Option<T>;
}
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index 8eefd9ff2..6dcf23dde 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -123,8 +123,9 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_hooks", since = "1.10.0")]
+ #[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[inline]
- pub fn file(&self) -> &str {
+ pub const fn file(&self) -> &str {
self.file
}
@@ -147,8 +148,9 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_hooks", since = "1.10.0")]
+ #[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[inline]
- pub fn line(&self) -> u32 {
+ pub const fn line(&self) -> u32 {
self.line
}
@@ -171,8 +173,9 @@ impl<'a> Location<'a> {
/// ```
#[must_use]
#[stable(feature = "panic_col", since = "1.25.0")]
+ #[rustc_const_unstable(feature = "const_location_fields", issue = "102911")]
#[inline]
- pub fn column(&self) -> u32 {
+ pub const fn column(&self) -> u32 {
self.col
}
}
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index d4afe0f53..a9de7c94e 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -29,6 +29,73 @@
use crate::fmt;
use crate::panic::{Location, PanicInfo};
+// First we define the two main entry points that all panics go through.
+// In the end both are just convenience wrappers around `panic_impl`.
+
+/// The entry point for panicking with a formatted message.
+///
+/// This is designed to reduce the amount of code required at the call
+/// site as much as possible (so that `panic!()` has as low an impact
+/// on (e.g.) the inlining of other functions as possible), by moving
+/// the actual formatting into this shared place.
+#[cold]
+// If panic_immediate_abort, inline the abort call,
+// otherwise avoid inlining because of it is cold path.
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[track_caller]
+#[lang = "panic_fmt"] // needed for const-evaluated panics
+#[rustc_do_not_const_check] // hooked by const-eval
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
+ if cfg!(feature = "panic_immediate_abort") {
+ super::intrinsics::abort()
+ }
+
+ // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
+ // that gets resolved to the `#[panic_handler]` function.
+ extern "Rust" {
+ #[lang = "panic_impl"]
+ fn panic_impl(pi: &PanicInfo<'_>) -> !;
+ }
+
+ let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
+
+ // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
+ unsafe { panic_impl(&pi) }
+}
+
+/// Like panic_fmt, but without unwinding and track_caller to reduce the impact on codesize.
+/// Also just works on `str`, as a `fmt::Arguments` needs more space to be passed.
+#[cold]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(bootstrap), rustc_nounwind)]
+#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
+pub fn panic_str_nounwind(msg: &'static str) -> ! {
+ if cfg!(feature = "panic_immediate_abort") {
+ super::intrinsics::abort()
+ }
+
+ // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
+ // that gets resolved to the `#[panic_handler]` function.
+ extern "Rust" {
+ #[lang = "panic_impl"]
+ fn panic_impl(pi: &PanicInfo<'_>) -> !;
+ }
+
+ // PanicInfo with the `can_unwind` flag set to false forces an abort.
+ let pieces = [msg];
+ let fmt = fmt::Arguments::new_v1(&pieces, &[]);
+ let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
+
+ // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
+ unsafe { panic_impl(&pi) }
+}
+
+// Next we define a bunch of higher-level wrappers that all bottom out in the two core functions
+// above.
+
/// The underlying implementation of libcore's `panic!` macro when no formatting is used.
#[cold]
// never inline unless panic_immediate_abort to avoid code
@@ -84,62 +151,17 @@ fn panic_bounds_check(index: usize, len: usize) -> ! {
panic!("index out of bounds: the len is {len} but the index is {index}")
}
-// This function is called directly by the codegen backend, and must not have
-// any extra arguments (including those synthesized by track_caller).
+/// Panic because we cannot unwind out of a function.
+///
+/// This function is called directly by the codegen backend, and must not have
+/// any extra arguments (including those synthesized by track_caller).
#[cold]
#[inline(never)]
#[lang = "panic_no_unwind"] // needed by codegen for panic in nounwind function
+#[cfg_attr(not(bootstrap), rustc_nounwind)]
+#[cfg_attr(bootstrap, rustc_allocator_nounwind)]
fn panic_no_unwind() -> ! {
- if cfg!(feature = "panic_immediate_abort") {
- super::intrinsics::abort()
- }
-
- // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
- // that gets resolved to the `#[panic_handler]` function.
- extern "Rust" {
- #[lang = "panic_impl"]
- fn panic_impl(pi: &PanicInfo<'_>) -> !;
- }
-
- // PanicInfo with the `can_unwind` flag set to false forces an abort.
- let fmt = format_args!("panic in a function that cannot unwind");
- let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false);
-
- // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
- unsafe { panic_impl(&pi) }
-}
-
-/// The entry point for panicking with a formatted message.
-///
-/// This is designed to reduce the amount of code required at the call
-/// site as much as possible (so that `panic!()` has as low an impact
-/// on (e.g.) the inlining of other functions as possible), by moving
-/// the actual formatting into this shared place.
-#[cold]
-// If panic_immediate_abort, inline the abort call,
-// otherwise avoid inlining because of it is cold path.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
-#[track_caller]
-#[lang = "panic_fmt"] // needed for const-evaluated panics
-#[rustc_do_not_const_check] // hooked by const-eval
-#[rustc_const_unstable(feature = "core_panic", issue = "none")]
-pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
- if cfg!(feature = "panic_immediate_abort") {
- super::intrinsics::abort()
- }
-
- // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call
- // that gets resolved to the `#[panic_handler]` function.
- extern "Rust" {
- #[lang = "panic_impl"]
- fn panic_impl(pi: &PanicInfo<'_>) -> !;
- }
-
- let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), true);
-
- // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call.
- unsafe { panic_impl(&pi) }
+ panic_str_nounwind("panic in a function that cannot unwind")
}
/// This function is used instead of panic_fmt in const eval.
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 242f44ade..331714a99 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -611,7 +611,19 @@ mod prim_pointer {}
///
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
/// an array. Indeed, this provides most of the API for working with arrays.
-/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// Slices have a dynamic size and do not coerce to arrays. Instead, use
+/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
+///
+/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
+/// array implementations) succeed if the input slice length is the same as the result
+/// array length. They optimize especially well when the optimizer can easily determine
+/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
+/// [TryFrom](crate::convert::TryFrom) returning:
+///
+/// - `[T; N]` copies from the slice's elements
+/// - `&[T; N]` references the original slice's elements
+/// - `&mut [T; N]` references the original slice's elements
///
/// You can move elements out of an array with a [slice pattern]. If you want
/// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
/// for x in &array { }
/// ```
///
+/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
+/// a slice:
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
+/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
+/// ```
+///
/// You can use a [slice pattern] to move elements out of an array:
///
/// ```
diff --git a/library/core/src/mem/valid_align.rs b/library/core/src/ptr/alignment.rs
index 32b2afb72..1390e09dd 100644
--- a/library/core/src/mem/valid_align.rs
+++ b/library/core/src/ptr/alignment.rs
@@ -1,4 +1,4 @@
-use crate::convert::TryFrom;
+use crate::convert::{TryFrom, TryInto};
use crate::intrinsics::assert_unsafe_precondition;
use crate::num::NonZeroUsize;
use crate::{cmp, fmt, hash, mem, num};
@@ -8,16 +8,62 @@ use crate::{cmp, fmt, hash, mem, num};
///
/// Note that particularly large alignments, while representable in this type,
/// are likely not to be supported by actual allocators and linkers.
-#[derive(Copy, Clone)]
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(transparent)]
-pub(crate) struct ValidAlign(ValidAlignEnum);
+pub struct Alignment(AlignmentEnum);
-// ValidAlign is `repr(usize)`, but via extra steps.
-const _: () = assert!(mem::size_of::<ValidAlign>() == mem::size_of::<usize>());
-const _: () = assert!(mem::align_of::<ValidAlign>() == mem::align_of::<usize>());
+// Alignment is `repr(usize)`, but via extra steps.
+const _: () = assert!(mem::size_of::<Alignment>() == mem::size_of::<usize>());
+const _: () = assert!(mem::align_of::<Alignment>() == mem::align_of::<usize>());
-impl ValidAlign {
- /// Creates a `ValidAlign` from a power-of-two `usize`.
+fn _alignment_can_be_structurally_matched(a: Alignment) -> bool {
+ matches!(a, Alignment::MIN)
+}
+
+impl Alignment {
+ /// The smallest possible alignment, 1.
+ ///
+ /// All addresses are always aligned at least this much.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ptr_alignment_type)]
+ /// use std::ptr::Alignment;
+ ///
+ /// assert_eq!(Alignment::MIN.as_usize(), 1);
+ /// ```
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+ pub const MIN: Self = Self(AlignmentEnum::_Align1Shl0);
+
+ /// Returns the alignment for a type.
+ ///
+ /// This provides the same numerical value as [`mem::align_of`],
+ /// but in an `Alignment` instead of a `usize.
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+ #[inline]
+ pub const fn of<T>() -> Self {
+ // SAFETY: rustc ensures that type alignment is always a power of two.
+ unsafe { Alignment::new_unchecked(mem::align_of::<T>()) }
+ }
+
+ /// Creates an `Alignment` from a `usize`, or returns `None` if it's
+ /// not a power of two.
+ ///
+ /// Note that `0` is not a power of two, nor a valid alignment.
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+ #[inline]
+ pub const fn new(align: usize) -> Option<Self> {
+ if align.is_power_of_two() {
+ // SAFETY: Just checked it only has one bit set
+ Some(unsafe { Self::new_unchecked(align) })
+ } else {
+ None
+ }
+ }
+
+ /// Creates an `Alignment` from a power-of-two `usize`.
///
/// # Safety
///
@@ -25,101 +71,120 @@ impl ValidAlign {
///
/// Equivalently, it must be `1 << exp` for some `exp` in `0..usize::BITS`.
/// It must *not* be zero.
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+ #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
- pub(crate) const unsafe fn new_unchecked(align: usize) -> Self {
+ pub const unsafe fn new_unchecked(align: usize) -> Self {
// SAFETY: Precondition passed to the caller.
- unsafe { assert_unsafe_precondition!((align: usize) => align.is_power_of_two()) };
+ unsafe {
+ assert_unsafe_precondition!(
+ "Alignment::new_unchecked requires a power of two",
+ (align: usize) => align.is_power_of_two()
+ )
+ };
// SAFETY: By precondition, this must be a power of two, and
// our variants encompass all possible powers of two.
- unsafe { mem::transmute::<usize, ValidAlign>(align) }
+ unsafe { mem::transmute::<usize, Alignment>(align) }
}
+ /// Returns the alignment as a [`usize`]
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
+ #[rustc_const_unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
- pub(crate) const fn as_usize(self) -> usize {
+ pub const fn as_usize(self) -> usize {
self.0 as usize
}
+ /// Returns the alignment as a [`NonZeroUsize`]
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
- pub(crate) const fn as_nonzero(self) -> NonZeroUsize {
+ pub const fn as_nonzero(self) -> NonZeroUsize {
// SAFETY: All the discriminants are non-zero.
unsafe { NonZeroUsize::new_unchecked(self.as_usize()) }
}
- /// Returns the base 2 logarithm of the alignment.
+ /// Returns the base-2 logarithm of the alignment.
///
/// This is always exact, as `self` represents a power of two.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(ptr_alignment_type)]
+ /// use std::ptr::Alignment;
+ ///
+ /// assert_eq!(Alignment::of::<u8>().log2(), 0);
+ /// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
+ /// ```
+ #[unstable(feature = "ptr_alignment_type", issue = "102070")]
#[inline]
- pub(crate) fn log2(self) -> u32 {
+ pub fn log2(self) -> u32 {
self.as_nonzero().trailing_zeros()
}
-
- /// Returns the alignment for a type.
- #[inline]
- pub(crate) fn of<T>() -> Self {
- // SAFETY: rustc ensures that type alignment is always a power of two.
- unsafe { ValidAlign::new_unchecked(mem::align_of::<T>()) }
- }
}
-impl fmt::Debug for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl fmt::Debug for Alignment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?} (1 << {:?})", self.as_nonzero(), self.log2())
}
}
-impl TryFrom<NonZeroUsize> for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl TryFrom<NonZeroUsize> for Alignment {
type Error = num::TryFromIntError;
#[inline]
- fn try_from(align: NonZeroUsize) -> Result<ValidAlign, Self::Error> {
- if align.is_power_of_two() {
- // SAFETY: Just checked for power-of-two
- unsafe { Ok(ValidAlign::new_unchecked(align.get())) }
- } else {
- Err(num::TryFromIntError(()))
- }
+ fn try_from(align: NonZeroUsize) -> Result<Alignment, Self::Error> {
+ align.get().try_into()
}
}
-impl TryFrom<usize> for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl TryFrom<usize> for Alignment {
type Error = num::TryFromIntError;
#[inline]
- fn try_from(align: usize) -> Result<ValidAlign, Self::Error> {
- if align.is_power_of_two() {
- // SAFETY: Just checked for power-of-two
- unsafe { Ok(ValidAlign::new_unchecked(align)) }
- } else {
- Err(num::TryFromIntError(()))
- }
+ fn try_from(align: usize) -> Result<Alignment, Self::Error> {
+ Self::new(align).ok_or(num::TryFromIntError(()))
}
}
-impl cmp::Eq for ValidAlign {}
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl From<Alignment> for NonZeroUsize {
+ #[inline]
+ fn from(align: Alignment) -> NonZeroUsize {
+ align.as_nonzero()
+ }
+}
-impl cmp::PartialEq for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl From<Alignment> for usize {
#[inline]
- fn eq(&self, other: &Self) -> bool {
- self.as_nonzero() == other.as_nonzero()
+ fn from(align: Alignment) -> usize {
+ align.as_usize()
}
}
-impl cmp::Ord for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::Ord for Alignment {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering {
self.as_nonzero().cmp(&other.as_nonzero())
}
}
-impl cmp::PartialOrd for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl cmp::PartialOrd for Alignment {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
-impl hash::Hash for ValidAlign {
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+impl hash::Hash for Alignment {
#[inline]
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.as_nonzero().hash(state)
@@ -127,15 +192,15 @@ impl hash::Hash for ValidAlign {
}
#[cfg(target_pointer_width = "16")]
-type ValidAlignEnum = ValidAlignEnum16;
+type AlignmentEnum = AlignmentEnum16;
#[cfg(target_pointer_width = "32")]
-type ValidAlignEnum = ValidAlignEnum32;
+type AlignmentEnum = AlignmentEnum32;
#[cfg(target_pointer_width = "64")]
-type ValidAlignEnum = ValidAlignEnum64;
+type AlignmentEnum = AlignmentEnum64;
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(u16)]
-enum ValidAlignEnum16 {
+enum AlignmentEnum16 {
_Align1Shl0 = 1 << 0,
_Align1Shl1 = 1 << 1,
_Align1Shl2 = 1 << 2,
@@ -154,9 +219,9 @@ enum ValidAlignEnum16 {
_Align1Shl15 = 1 << 15,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(u32)]
-enum ValidAlignEnum32 {
+enum AlignmentEnum32 {
_Align1Shl0 = 1 << 0,
_Align1Shl1 = 1 << 1,
_Align1Shl2 = 1 << 2,
@@ -191,9 +256,9 @@ enum ValidAlignEnum32 {
_Align1Shl31 = 1 << 31,
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(u64)]
-enum ValidAlignEnum64 {
+enum AlignmentEnum64 {
_Align1Shl0 = 1 << 0,
_Align1Shl1 = 1 << 1,
_Align1Shl2 = 1 << 2,
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 43e883b8b..5a083227b 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -568,7 +568,6 @@ impl<T: ?Sized> *const T {
///
/// For non-`Sized` pointees this operation changes only the data pointer,
/// leaving the metadata untouched.
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_mask", issue = "98290")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]
@@ -695,7 +694,7 @@ impl<T: ?Sized> *const T {
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// This computes the same value that [`offset_from`](#method.offset_from)
- /// would compute, but with the added precondition that that the offset is
+ /// 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()`,
/// but it provides slightly more information to the optimizer, which can
@@ -762,7 +761,10 @@ impl<T: ?Sized> *const T {
// SAFETY: The comparison has no side-effects, and the intrinsic
// does this check internally in the CTFE implementation.
unsafe {
- assert_unsafe_precondition!([T](this: *const T, origin: *const T) => this >= origin)
+ assert_unsafe_precondition!(
+ "ptr::sub_ptr requires `this >= origin`",
+ [T](this: *const T, origin: *const T) => this >= origin
+ )
};
let pointee_size = mem::size_of::<T>();
@@ -803,7 +805,7 @@ impl<T: ?Sized> *const T {
/// Returns whether two pointers are guaranteed to be inequal.
///
- /// At runtime this function behaves like `Some(self == other)`.
+ /// At runtime this function behaves like `Some(self != other)`.
/// However, in some contexts (e.g., compile-time evaluation),
/// it is not always possible to determine inequality of two pointers, so this function may
/// spuriously return `None` for pointers that later actually turn out to have its inequality known.
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 8865c834c..caa10f181 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -135,16 +135,16 @@ pub const fn from_raw_parts_mut<T: ?Sized>(
}
#[repr(C)]
-pub(crate) union PtrRepr<T: ?Sized> {
- pub(crate) const_ptr: *const T,
- pub(crate) mut_ptr: *mut T,
- pub(crate) components: PtrComponents<T>,
+union PtrRepr<T: ?Sized> {
+ const_ptr: *const T,
+ mut_ptr: *mut T,
+ components: PtrComponents<T>,
}
#[repr(C)]
-pub(crate) struct PtrComponents<T: ?Sized> {
- pub(crate) data_address: *const (),
- pub(crate) metadata: <T as Pointee>::Metadata,
+struct PtrComponents<T: ?Sized> {
+ data_address: *const (),
+ metadata: <T as Pointee>::Metadata,
}
// Manual impl needed to avoid `T: Copy` bound.
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index e976abed7..565c38d22 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -377,6 +377,10 @@ use crate::intrinsics::{
use crate::mem::{self, MaybeUninit};
+mod alignment;
+#[unstable(feature = "ptr_alignment_type", issue = "102070")]
+pub use alignment::Alignment;
+
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(inline)]
pub use crate::intrinsics::copy_nonoverlapping;
@@ -390,7 +394,6 @@ pub use crate::intrinsics::copy;
pub use crate::intrinsics::write_bytes;
mod metadata;
-pub(crate) use metadata::PtrRepr;
#[unstable(feature = "ptr_metadata", issue = "81513")]
pub use metadata::{from_raw_parts, from_raw_parts_mut, metadata, DynMetadata, Pointee, Thin};
@@ -578,12 +581,21 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
/// Convert an address back to a pointer, picking up a previously 'exposed' provenance.
///
/// This is equivalent to `addr as *const T`. The provenance of the returned pointer is that of *any*
-/// pointer that was previously passed to [`expose_addr`][pointer::expose_addr] or a `ptr as usize`
-/// cast. If there is no previously 'exposed' provenance that justifies the way this pointer will be
-/// used, the program has undefined behavior. Note that there is no algorithm that decides which
-/// provenance will be used. You can think of this as "guessing" the right provenance, and the guess
-/// will be "maximally in your favor", in the sense that if there is any way to avoid undefined
-/// behavior, then that is the guess that will be taken.
+/// pointer that was previously exposed by passing it to [`expose_addr`][pointer::expose_addr],
+/// or a `ptr as usize` cast. In addition, memory which is outside the control of the Rust abstract
+/// machine (MMIO registers, for example) is always considered to be exposed, so long as this memory
+/// is disjoint from memory that will be used by the abstract machine such as the stack, heap,
+/// and statics.
+///
+/// If there is no 'exposed' provenance that justifies the way this pointer will be used,
+/// the program has undefined behavior. In particular, the aliasing rules still apply: pointers
+/// and references that have been invalidated due to aliasing accesses cannot be used any more,
+/// even if they have been exposed!
+///
+/// Note that there is no algorithm that decides which provenance will be used. You can think of this
+/// as "guessing" the right provenance, and the guess will be "maximally in your favor", in the sense
+/// that if there is any way to avoid undefined behavior (while upholding all aliasing requirements),
+/// then that is the guess that will be taken.
///
/// On platforms with multiple address spaces, it is your responsibility to ensure that the
/// address makes sense in the address space that this pointer will be used with.
@@ -886,7 +898,10 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
// SAFETY: the caller must guarantee that `x` and `y` are
// valid for writes and properly aligned.
unsafe {
- assert_unsafe_precondition!([T](x: *mut T, y: *mut T, count: usize) =>
+ assert_unsafe_precondition!(
+ "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
+ and the specified memory ranges do not overlap",
+ [T](x: *mut T, y: *mut T, count: usize) =>
is_aligned_and_not_null(x)
&& is_aligned_and_not_null(y)
&& is_nonoverlapping(x, y, count)
@@ -983,7 +998,10 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
// and cannot overlap `src` since `dst` must point to a distinct
// allocated object.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::replace requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
mem::swap(&mut *dst, &mut src); // cannot overlap
}
src
@@ -1114,6 +1132,10 @@ pub const unsafe fn read<T>(src: *const T) -> T {
// Also, since we just wrote a valid value into `tmp`, it is guaranteed
// to be properly initialized.
unsafe {
+ assert_unsafe_precondition!(
+ "ptr::read requires that the pointer argument is aligned and non-null",
+ [T](src: *const T) => is_aligned_and_not_null(src)
+ );
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
tmp.assume_init()
}
@@ -1307,6 +1329,10 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
// `dst` cannot overlap `src` because the caller has mutable access
// to `dst` while `src` is owned by this function.
unsafe {
+ assert_unsafe_precondition!(
+ "ptr::write requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
copy_nonoverlapping(&src as *const T, dst, 1);
intrinsics::forget(src);
}
@@ -1470,7 +1496,10 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
pub unsafe fn read_volatile<T>(src: *const T) -> T {
// SAFETY: the caller must uphold the safety contract for `volatile_load`.
unsafe {
- assert_unsafe_precondition!([T](src: *const T) => is_aligned_and_not_null(src));
+ assert_unsafe_precondition!(
+ "ptr::read_volatile requires that the pointer argument is aligned and non-null",
+ [T](src: *const T) => is_aligned_and_not_null(src)
+ );
intrinsics::volatile_load(src)
}
}
@@ -1541,7 +1570,10 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
// SAFETY: the caller must uphold the safety contract for `volatile_store`.
unsafe {
- assert_unsafe_precondition!([T](dst: *mut T) => is_aligned_and_not_null(dst));
+ assert_unsafe_precondition!(
+ "ptr::write_volatile requires that the pointer argument is aligned and non-null",
+ [T](dst: *mut T) => is_aligned_and_not_null(dst)
+ );
intrinsics::volatile_store(dst, src);
}
}
@@ -1728,6 +1760,12 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
/// by their address rather than comparing the values they point to
/// (which is what the `PartialEq for &T` implementation does).
///
+/// When comparing wide pointers, both the address and the metadata are tested for equality.
+/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
+/// to values of the same underlying type can compare inequal (because vtables are duplicated in
+/// multiple codegen units), and pointers to values of *different* underlying type can compare equal
+/// (since identical vtables can be deduplicated within a codegen unit).
+///
/// # Examples
///
/// ```
@@ -1754,41 +1792,6 @@ pub(crate) unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usize {
/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
/// ```
-///
-/// Traits are also compared by their implementation:
-///
-/// ```
-/// #[repr(transparent)]
-/// struct Wrapper { member: i32 }
-///
-/// trait Trait {}
-/// impl Trait for Wrapper {}
-/// impl Trait for i32 {}
-///
-/// let wrapper = Wrapper { member: 10 };
-///
-/// // Pointers have equal addresses.
-/// assert!(std::ptr::eq(
-/// &wrapper as *const Wrapper as *const u8,
-/// &wrapper.member as *const i32 as *const u8
-/// ));
-///
-/// // Objects have equal addresses, but `Trait` has different implementations.
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait,
-/// &wrapper.member as &dyn Trait,
-/// ));
-/// assert!(!std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait,
-/// &wrapper.member as &dyn Trait as *const dyn Trait,
-/// ));
-///
-/// // Converting the reference to a `*const u8` compares by address.
-/// assert!(std::ptr::eq(
-/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
-/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
-/// ));
-/// ```
#[stable(feature = "ptr_eq", since = "1.17.0")]
#[inline]
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
@@ -1856,9 +1859,16 @@ macro_rules! maybe_fnptr_doc {
// Impls for function pointers
macro_rules! fnptr_impls_safety_abi {
($FnTy: ty, $($Arg: ident),*) => {
+ fnptr_impls_safety_abi! { #[stable(feature = "fnptr_impls", since = "1.4.0")] $FnTy, $($Arg),* }
+ };
+ (@c_unwind $FnTy: ty, $($Arg: ident),*) => {
+ #[cfg(not(bootstrap))]
+ fnptr_impls_safety_abi! { #[unstable(feature = "c_unwind", issue = "74990")] $FnTy, $($Arg),* }
+ };
+ (#[$meta:meta] $FnTy: ty, $($Arg: ident),*) => {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> PartialEq for $FnTy {
#[inline]
fn eq(&self, other: &Self) -> bool {
@@ -1869,13 +1879,13 @@ macro_rules! fnptr_impls_safety_abi {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> Eq for $FnTy {}
}
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
@@ -1886,7 +1896,7 @@ macro_rules! fnptr_impls_safety_abi {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> Ord for $FnTy {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
@@ -1897,7 +1907,7 @@ macro_rules! fnptr_impls_safety_abi {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
state.write_usize(*self as usize)
@@ -1907,7 +1917,7 @@ macro_rules! fnptr_impls_safety_abi {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::pointer_fmt_inner(*self as usize, f)
@@ -1917,7 +1927,7 @@ macro_rules! fnptr_impls_safety_abi {
maybe_fnptr_doc! {
$($Arg)* @
- #[stable(feature = "fnptr_impls", since = "1.4.0")]
+ #[$meta]
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::pointer_fmt_inner(*self as usize, f)
@@ -1932,16 +1942,22 @@ macro_rules! fnptr_impls_args {
fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
+ fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
+ fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
+ fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
+ fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
};
() => {
// No variadic functions with 0 parameters
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
+ fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn() -> Ret, }
fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
+ fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn() -> Ret, }
};
}
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index e277b8181..6764002bc 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -80,10 +80,14 @@ impl<T: ?Sized> *mut T {
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
- pub fn with_metadata_of<U>(self, mut val: *mut U) -> *mut U
+ pub fn with_metadata_of<U>(self, val: *const U) -> *mut U
where
U: ?Sized,
{
+ // Prepare in the type system that we will replace the pointer value with a mutable
+ // pointer, taking the mutable provenance from the `self` pointer.
+ let mut val = val as *mut U;
+ // Pointer to the pointer value within the value.
let target = &mut val as *mut *mut U as *mut *mut u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
@@ -584,7 +588,6 @@ impl<T: ?Sized> *mut T {
///
/// For non-`Sized` pointees this operation changes only the data pointer,
/// leaving the metadata untouched.
- #[cfg(not(bootstrap))]
#[unstable(feature = "ptr_mask", issue = "98290")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline(always)]
@@ -727,7 +730,7 @@ impl<T: ?Sized> *mut T {
/// Returns whether two pointers are guaranteed to be inequal.
///
- /// At runtime this function behaves like `Some(self == other)`.
+ /// At runtime this function behaves like `Some(self != other)`.
/// However, in some contexts (e.g., compile-time evaluation),
/// it is not always possible to determine inequality of two pointers, so this function may
/// spuriously return `None` for pointers that later actually turn out to have its inequality known.
@@ -868,7 +871,7 @@ impl<T: ?Sized> *mut T {
/// units of T: the distance in bytes is divided by `mem::size_of::<T>()`.
///
/// This computes the same value that [`offset_from`](#method.offset_from)
- /// would compute, but with the added precondition that that the offset is
+ /// 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()`,
/// but it provides slightly more information to the optimizer, which can
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index f3ef094cb..c18264d13 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -2,6 +2,7 @@ use crate::cmp::Ordering;
use crate::convert::From;
use crate::fmt;
use crate::hash;
+use crate::intrinsics::assert_unsafe_precondition;
use crate::marker::Unsize;
use crate::mem::{self, MaybeUninit};
use crate::num::NonZeroUsize;
@@ -195,7 +196,10 @@ impl<T: ?Sized> NonNull<T> {
#[inline]
pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
// SAFETY: the caller must guarantee that `ptr` is non-null.
- unsafe { NonNull { pointer: ptr as _ } }
+ unsafe {
+ assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null());
+ NonNull { pointer: ptr as _ }
+ }
}
/// Creates a new `NonNull` if `ptr` is non-null.
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 76eaa191f..3f33c5fd6 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -548,22 +548,25 @@ impl<T, E> Result<T, E> {
/// # Examples
///
/// ```
- /// #![feature(is_some_with)]
+ /// #![feature(is_some_and)]
///
/// let x: Result<u32, &str> = Ok(2);
- /// assert_eq!(x.is_ok_and(|&x| x > 1), true);
+ /// assert_eq!(x.is_ok_and(|x| x > 1), true);
///
/// let x: Result<u32, &str> = Ok(0);
- /// assert_eq!(x.is_ok_and(|&x| x > 1), false);
+ /// assert_eq!(x.is_ok_and(|x| x > 1), false);
///
/// let x: Result<u32, &str> = Err("hey");
- /// assert_eq!(x.is_ok_and(|&x| x > 1), false);
+ /// assert_eq!(x.is_ok_and(|x| x > 1), false);
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "is_some_with", issue = "93050")]
- pub fn is_ok_and(&self, f: impl FnOnce(&T) -> bool) -> bool {
- matches!(self, Ok(x) if f(x))
+ #[unstable(feature = "is_some_and", issue = "93050")]
+ pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
+ match self {
+ Err(_) => false,
+ Ok(x) => f(x),
+ }
}
/// Returns `true` if the result is [`Err`].
@@ -592,7 +595,7 @@ impl<T, E> Result<T, E> {
/// # Examples
///
/// ```
- /// #![feature(is_some_with)]
+ /// #![feature(is_some_and)]
/// use std::io::{Error, ErrorKind};
///
/// let x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, "!"));
@@ -606,9 +609,12 @@ impl<T, E> Result<T, E> {
/// ```
#[must_use]
#[inline]
- #[unstable(feature = "is_some_with", issue = "93050")]
- pub fn is_err_and(&self, f: impl FnOnce(&E) -> bool) -> bool {
- matches!(self, Err(x) if f(x))
+ #[unstable(feature = "is_some_and", issue = "93050")]
+ pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
+ match self {
+ Ok(_) => false,
+ Err(e) => f(e),
+ }
}
/////////////////////////////////////////////////////////////////////////
@@ -2066,9 +2072,6 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
/// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
#[inline]
fn from_iter<I: IntoIterator<Item = Result<A, E>>>(iter: I) -> Result<V, E> {
- // FIXME(#11084): This could be replaced with Iterator::scan when this
- // performance bug is closed.
-
iter::try_process(iter.into_iter(), |i| i.collect())
}
}
@@ -2116,6 +2119,7 @@ impl<T, E, F: From<E>> ops::FromResidual<ops::Yeet<E>> for Result<T, F> {
}
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-impl<T, E> ops::Residual<T> for Result<convert::Infallible, E> {
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+impl<T, E> const ops::Residual<T> for Result<convert::Infallible, E> {
type TryType = Result<T, E>;
}
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 3403a5a86..6d2f7330d 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -139,6 +139,8 @@ mod private_slice_index {
impl Sealed for ops::RangeToInclusive<usize> {}
#[stable(feature = "slice_index_with_ops_bound_pair", since = "1.53.0")]
impl Sealed for (ops::Bound<usize>, ops::Bound<usize>) {}
+
+ impl Sealed for ops::IndexRange {}
}
/// A helper trait used for indexing operations.
@@ -158,6 +160,7 @@ mod private_slice_index {
message = "the type `{T}` cannot be indexed by `{Self}`",
label = "slice indices are of type `usize` or ranges of `usize`"
)]
+#[const_trait]
pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
/// The output type returned by methods.
#[stable(feature = "slice_get_slice", since = "1.28.0")]
@@ -229,7 +232,10 @@ unsafe impl<T> const SliceIndex<[T]> for usize {
// `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
// so the call to `add` is safe.
unsafe {
- assert_unsafe_precondition!([T](this: usize, slice: *const [T]) => this < slice.len());
+ assert_unsafe_precondition!(
+ "slice::get_unchecked requires that the index is within the slice",
+ [T](this: usize, slice: *const [T]) => this < slice.len()
+ );
slice.as_ptr().add(self)
}
}
@@ -239,7 +245,10 @@ unsafe impl<T> const SliceIndex<[T]> for usize {
let this = self;
// SAFETY: see comments for `get_unchecked` above.
unsafe {
- assert_unsafe_precondition!([T](this: usize, slice: *mut [T]) => this < slice.len());
+ assert_unsafe_precondition!(
+ "slice::get_unchecked_mut requires that the index is within the slice",
+ [T](this: usize, slice: *mut [T]) => this < slice.len()
+ );
slice.as_mut_ptr().add(self)
}
}
@@ -257,6 +266,83 @@ unsafe impl<T> const SliceIndex<[T]> for usize {
}
}
+/// Because `IndexRange` guarantees `start <= end`, fewer checks are needed here
+/// than there are for a general `Range<usize>` (which might be `100..3`).
+#[rustc_const_unstable(feature = "const_index_range_slice_index", issue = "none")]
+unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
+ type Output = [T];
+
+ #[inline]
+ fn get(self, slice: &[T]) -> Option<&[T]> {
+ if self.end() <= slice.len() {
+ // SAFETY: `self` is checked to be valid and in bounds above.
+ unsafe { Some(&*self.get_unchecked(slice)) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn get_mut(self, slice: &mut [T]) -> Option<&mut [T]> {
+ if self.end() <= slice.len() {
+ // SAFETY: `self` is checked to be valid and in bounds above.
+ unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ unsafe fn get_unchecked(self, slice: *const [T]) -> *const [T] {
+ let end = self.end();
+ // SAFETY: the caller guarantees that `slice` is not dangling, so it
+ // cannot be longer than `isize::MAX`. They also guarantee that
+ // `self` is in bounds of `slice` so `self` cannot overflow an `isize`,
+ // so the call to `add` is safe.
+
+ unsafe {
+ assert_unsafe_precondition!(
+ "slice::get_unchecked requires that the index is within the slice",
+ [T](end: usize, slice: *const [T]) => end <= slice.len()
+ );
+ ptr::slice_from_raw_parts(slice.as_ptr().add(self.start()), self.len())
+ }
+ }
+
+ #[inline]
+ unsafe fn get_unchecked_mut(self, slice: *mut [T]) -> *mut [T] {
+ let end = self.end();
+ // SAFETY: see comments for `get_unchecked` above.
+ unsafe {
+ assert_unsafe_precondition!(
+ "slice::get_unchecked_mut requires that the index is within the slice",
+ [T](end: usize, slice: *mut [T]) => end <= slice.len()
+ );
+ ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start()), self.len())
+ }
+ }
+
+ #[inline]
+ fn index(self, slice: &[T]) -> &[T] {
+ if self.end() <= slice.len() {
+ // SAFETY: `self` is checked to be valid and in bounds above.
+ unsafe { &*self.get_unchecked(slice) }
+ } else {
+ slice_end_index_len_fail(self.end(), slice.len())
+ }
+ }
+
+ #[inline]
+ fn index_mut(self, slice: &mut [T]) -> &mut [T] {
+ if self.end() <= slice.len() {
+ // SAFETY: `self` is checked to be valid and in bounds above.
+ unsafe { &mut *self.get_unchecked_mut(slice) }
+ } else {
+ slice_end_index_len_fail(self.end(), slice.len())
+ }
+ }
+}
+
#[stable(feature = "slice_get_slice_impls", since = "1.15.0")]
#[rustc_const_unstable(feature = "const_slice_index", issue = "none")]
unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
@@ -291,8 +377,11 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
// so the call to `add` is safe.
unsafe {
- assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *const [T]) =>
- this.end >= this.start && this.end <= slice.len());
+ assert_unsafe_precondition!(
+ "slice::get_unchecked requires that the range is within the slice",
+ [T](this: ops::Range<usize>, slice: *const [T]) =>
+ this.end >= this.start && this.end <= slice.len()
+ );
ptr::slice_from_raw_parts(slice.as_ptr().add(self.start), self.end - self.start)
}
}
@@ -302,8 +391,11 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
let this = ops::Range { start: self.start, end: self.end };
// SAFETY: see comments for `get_unchecked` above.
unsafe {
- assert_unsafe_precondition!([T](this: ops::Range<usize>, slice: *mut [T]) =>
- this.end >= this.start && this.end <= slice.len());
+ assert_unsafe_precondition!(
+ "slice::get_unchecked_mut requires that the range is within the slice",
+ [T](this: ops::Range<usize>, slice: *mut [T]) =>
+ this.end >= this.start && this.end <= slice.len()
+ );
ptr::slice_from_raw_parts_mut(slice.as_mut_ptr().add(self.start), self.end - self.start)
}
}
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 395c56784..8a8962828 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -9,7 +9,7 @@ use crate::fmt;
use crate::intrinsics::{assume, exact_div, unchecked_sub};
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::marker::{PhantomData, Send, Sized, Sync};
-use crate::mem;
+use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZeroUsize;
use crate::ptr::NonNull;
@@ -91,11 +91,8 @@ impl<'a, T> Iter<'a, T> {
unsafe {
assume(!ptr.is_null());
- let end = if mem::size_of::<T>() == 0 {
- ptr.wrapping_byte_add(slice.len())
- } else {
- ptr.add(slice.len())
- };
+ let end =
+ if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) };
Self { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: PhantomData }
}
@@ -127,6 +124,7 @@ impl<'a, T> Iter<'a, T> {
/// ```
#[must_use]
#[stable(feature = "iter_to_slice", since = "1.4.0")]
+ #[inline]
pub fn as_slice(&self) -> &'a [T] {
self.make_slice()
}
@@ -146,6 +144,7 @@ iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Clone for Iter<'_, T> {
+ #[inline]
fn clone(&self) -> Self {
Iter { ptr: self.ptr, end: self.end, _marker: self._marker }
}
@@ -153,6 +152,7 @@ impl<T> Clone for Iter<'_, T> {
#[stable(feature = "slice_iter_as_ref", since = "1.13.0")]
impl<T> AsRef<[T]> for Iter<'_, T> {
+ #[inline]
fn as_ref(&self) -> &[T] {
self.as_slice()
}
@@ -227,11 +227,8 @@ impl<'a, T> IterMut<'a, T> {
unsafe {
assume(!ptr.is_null());
- let end = if mem::size_of::<T>() == 0 {
- ptr.wrapping_byte_add(slice.len())
- } else {
- ptr.add(slice.len())
- };
+ let end =
+ if T::IS_ZST { ptr.wrapping_byte_add(slice.len()) } else { ptr.add(slice.len()) };
Self { ptr: NonNull::new_unchecked(ptr), end, _marker: PhantomData }
}
@@ -303,6 +300,7 @@ impl<'a, T> IterMut<'a, T> {
/// ```
#[must_use]
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
+ #[inline]
pub fn as_slice(&self) -> &[T] {
self.make_slice()
}
@@ -351,6 +349,7 @@ impl<'a, T> IterMut<'a, T> {
#[stable(feature = "slice_iter_mut_as_slice", since = "1.53.0")]
impl<T> AsRef<[T]> for IterMut<'_, T> {
+ #[inline]
fn as_ref(&self) -> &[T] {
self.as_slice()
}
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 6c9e7574e..ce51d48e3 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -100,7 +100,7 @@ macro_rules! iterator {
// Unsafe because the offset must not exceed `self.len()`.
#[inline(always)]
unsafe fn pre_dec_end(&mut self, offset: usize) -> * $raw_mut T {
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
zst_shrink!(self, offset);
self.ptr.as_ptr()
} else {
@@ -140,7 +140,7 @@ macro_rules! iterator {
// since we check if the iterator is empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
- if mem::size_of::<T>() != 0 {
+ if !<T>::IS_ZST {
assume(!self.end.is_null());
}
if is_empty!(self) {
@@ -166,7 +166,7 @@ macro_rules! iterator {
fn nth(&mut self, n: usize) -> Option<$elem> {
if n >= len!(self) {
// This iterator is now empty.
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// We have to do it this way as `ptr` may never be 0, but `end`
// could be (due to wrapping).
self.end = self.ptr.as_ptr();
@@ -355,7 +355,7 @@ macro_rules! iterator {
// empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
- if mem::size_of::<T>() != 0 {
+ if !<T>::IS_ZST {
assume(!self.end.is_null());
}
if is_empty!(self) {
diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs
index 7de1f48e6..c848c2e18 100644
--- a/library/core/src/slice/memchr.rs
+++ b/library/core/src/slice/memchr.rs
@@ -141,8 +141,8 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
// SAFETY: offset starts at len - suffix.len(), as long as it is greater than
// min_aligned_offset (prefix.len()) the remaining distance is at least 2 * chunk_bytes.
unsafe {
- let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
- let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
+ let u = *(ptr.add(offset - 2 * chunk_bytes) as *const Chunk);
+ let v = *(ptr.add(offset - chunk_bytes) as *const Chunk);
// Break if there is a matching byte.
let zu = contains_zero_byte(u ^ repeated_x);
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 6a7150d29..4f1bb1734 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -9,7 +9,7 @@
use crate::cmp::Ordering::{self, Greater, Less};
use crate::intrinsics::{assert_unsafe_precondition, exact_div};
use crate::marker::Copy;
-use crate::mem;
+use crate::mem::{self, SizedTypeProperties};
use crate::num::NonZeroUsize;
use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds};
use crate::option::Option;
@@ -123,18 +123,11 @@ impl<T> [T] {
#[lang = "slice_len_fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_len", since = "1.39.0")]
+ #[rustc_allow_const_fn_unstable(ptr_metadata)]
#[inline]
#[must_use]
- // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
pub const fn len(&self) -> usize {
- // FIXME: Replace with `crate::ptr::metadata(self)` when that is const-stable.
- // As of this writing this causes a "Const-stable functions can only call other
- // const-stable functions" error.
-
- // SAFETY: Accessing the value from the `PtrRepr` union is safe since *const T
- // and PtrComponents<T> have the same memory layouts. Only std can make this
- // guarantee.
- unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
+ ptr::metadata(self)
}
/// Returns `true` if the slice has a length of 0.
@@ -660,7 +653,10 @@ impl<T> [T] {
let ptr = this.as_mut_ptr();
// SAFETY: caller has to guarantee that `a < self.len()` and `b < self.len()`
unsafe {
- assert_unsafe_precondition!([T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len());
+ assert_unsafe_precondition!(
+ "slice::swap_unchecked requires that the indices are within the slice",
+ [T](a: usize, b: usize, this: &mut [T]) => a < this.len() && b < this.len()
+ );
ptr::swap(ptr.add(a), ptr.add(b));
}
}
@@ -976,7 +972,10 @@ impl<T> [T] {
let this = self;
// SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
let new_len = unsafe {
- assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
+ assert_unsafe_precondition!(
+ "slice::as_chunks_unchecked requires `N != 0` and the slice to split exactly into `N`-element chunks",
+ [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0
+ );
exact_div(self.len(), N)
};
// SAFETY: We cast a slice of `new_len * N` elements into
@@ -1116,7 +1115,10 @@ impl<T> [T] {
let this = &*self;
// SAFETY: Caller must guarantee that `N` is nonzero and exactly divides the slice length
let new_len = unsafe {
- assert_unsafe_precondition!([T](this: &[T], N: usize) => N != 0 && this.len() % N == 0);
+ assert_unsafe_precondition!(
+ "slice::as_chunks_unchecked_mut requires `N != 0` and the slice to split exactly into `N`-element chunks",
+ [T](this: &[T], N: usize) => N != 0 && this.len() % N == 0
+ );
exact_div(this.len(), N)
};
// SAFETY: We cast a slice of `new_len * N` elements into
@@ -1580,7 +1582,8 @@ impl<T> [T] {
#[inline]
#[track_caller]
#[must_use]
- pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+ #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
+ pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
assert!(mid <= self.len());
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
// fulfills the requirements of `from_raw_parts_mut`.
@@ -1679,9 +1682,10 @@ impl<T> [T] {
/// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
/// ```
#[unstable(feature = "slice_split_at_unchecked", reason = "new API", issue = "76014")]
+ #[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
#[inline]
#[must_use]
- pub unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+ pub const unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
let len = self.len();
let ptr = self.as_mut_ptr();
@@ -1690,7 +1694,10 @@ impl<T> [T] {
// `[ptr; mid]` and `[mid; len]` are not overlapping, so returning a mutable reference
// is fine.
unsafe {
- assert_unsafe_precondition!((mid: usize, len: usize) => mid <= len);
+ assert_unsafe_precondition!(
+ "slice::split_at_mut_unchecked requires the index to be within the slice",
+ (mid: usize, len: usize) => mid <= len
+ );
(from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid))
}
}
@@ -2074,7 +2081,7 @@ impl<T> [T] {
SplitN::new(self.split(pred), n)
}
- /// Returns an iterator over subslices separated by elements that match
+ /// Returns an iterator over mutable subslices separated by elements that match
/// `pred`, limited to returning at most `n` items. The matched element is
/// not contained in the subslices.
///
@@ -2357,6 +2364,28 @@ impl<T> [T] {
/// assert!(match r { Ok(1..=4) => true, _ => false, });
/// ```
///
+ /// If you want to find that whole *range* of matching items, rather than
+ /// an arbitrary matching one, that can be done using [`partition_point`]:
+ /// ```
+ /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
+ ///
+ /// let low = s.partition_point(|x| x < &1);
+ /// assert_eq!(low, 1);
+ /// let high = s.partition_point(|x| x <= &1);
+ /// assert_eq!(high, 5);
+ /// let r = s.binary_search(&1);
+ /// assert!((low..high).contains(&r.unwrap()));
+ ///
+ /// assert!(s[..low].iter().all(|&x| x < 1));
+ /// assert!(s[low..high].iter().all(|&x| x == 1));
+ /// assert!(s[high..].iter().all(|&x| x > 1));
+ ///
+ /// // For something not found, the "range" of equal items is empty
+ /// assert_eq!(s.partition_point(|x| x < &11), 9);
+ /// assert_eq!(s.partition_point(|x| x <= &11), 9);
+ /// assert_eq!(s.binary_search(&11), Err(9));
+ /// ```
+ ///
/// If you want to insert an item to a sorted vector, while maintaining
/// sort order, consider using [`partition_point`]:
///
@@ -2424,15 +2453,20 @@ impl<T> [T] {
where
F: FnMut(&'a T) -> Ordering,
{
+ // INVARIANTS:
+ // - 0 <= left <= left + size = right <= self.len()
+ // - f returns Less for everything in self[..left]
+ // - f returns Greater for everything in self[right..]
let mut size = self.len();
let mut left = 0;
let mut right = size;
while left < right {
let mid = left + size / 2;
- // SAFETY: the call is made safe by the following invariants:
- // - `mid >= 0`
- // - `mid < size`: `mid` is limited by `[left; right)` bound.
+ // SAFETY: the while condition means `size` is strictly positive, so
+ // `size/2 < size`. Thus `left + size/2 < left + size`, which
+ // coupled with the `left + size <= self.len()` invariant means
+ // we have `left + size/2 < self.len()`, and this is in-bounds.
let cmp = f(unsafe { self.get_unchecked(mid) });
// The reason why we use if/else control flow rather than match
@@ -2450,6 +2484,10 @@ impl<T> [T] {
size = right - left;
}
+
+ // SAFETY: directly true from the overall invariant.
+ // Note that this is `<=`, unlike the assume in the `Ok` path.
+ unsafe { crate::intrinsics::assume(left <= self.len()) };
Err(left)
}
@@ -2540,7 +2578,7 @@ impl<T> [T] {
where
T: Ord,
{
- sort::quicksort(self, |a, b| a.lt(b));
+ sort::quicksort(self, T::lt);
}
/// Sorts the slice with a comparator function, but might not preserve the order of equal
@@ -2643,9 +2681,10 @@ impl<T> [T] {
/// 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 values: all elements less
- /// than the one at the given index, the value at the given index, and all elements greater than
- /// the one at the given index.
+ /// 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`.
///
/// # Current implementation
///
@@ -2679,8 +2718,7 @@ impl<T> [T] {
where
T: Ord,
{
- let mut f = |a: &T, b: &T| a.lt(b);
- sort::partition_at_index(self, index, &mut f)
+ sort::partition_at_index(self, index, T::lt)
}
/// Reorder the slice with a comparator function such that the element at `index` is at its
@@ -2690,10 +2728,11 @@ impl<T> [T] {
/// 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
- /// values: all elements less than the one at the given index, the value at the given index,
- /// and all elements greater than the one at the given index, using the provided comparator
- /// 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
+ /// the value of the element at `index`.
///
/// # Current implementation
///
@@ -2731,8 +2770,7 @@ impl<T> [T] {
where
F: FnMut(&T, &T) -> Ordering,
{
- let mut f = |a: &T, b: &T| compare(a, b) == Less;
- sort::partition_at_index(self, index, &mut f)
+ sort::partition_at_index(self, index, |a: &T, b: &T| compare(a, b) == Less)
}
/// Reorder the slice with a key extraction function such that the element at `index` is at its
@@ -2742,10 +2780,11 @@ impl<T> [T] {
/// 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
- /// values: all elements less than the one at the given index, the value at the given index, and
- /// all elements greater than the one at the given index, using the provided key extraction
- /// 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
+ /// the value of the element at `index`.
///
/// # Current implementation
///
@@ -2784,8 +2823,7 @@ impl<T> [T] {
F: FnMut(&T) -> K,
K: Ord,
{
- let mut g = |a: &T, b: &T| f(a).lt(&f(b));
- sort::partition_at_index(self, index, &mut g)
+ sort::partition_at_index(self, index, |a: &T, b: &T| f(a).lt(&f(b)))
}
/// Moves all consecutive repeated elements to the end of the slice according to the
@@ -3459,7 +3497,7 @@ impl<T> [T] {
#[must_use]
pub unsafe fn align_to<U>(&self) -> (&[T], &[U], &[T]) {
// Note that most of this function will be constant-evaluated,
- if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
+ if U::IS_ZST || T::IS_ZST {
// handle ZSTs specially, which is – don't handle them at all.
return (self, &[], &[]);
}
@@ -3520,7 +3558,7 @@ impl<T> [T] {
#[must_use]
pub unsafe fn align_to_mut<U>(&mut self) -> (&mut [T], &mut [U], &mut [T]) {
// Note that most of this function will be constant-evaluated,
- if mem::size_of::<U>() == 0 || mem::size_of::<T>() == 0 {
+ if U::IS_ZST || T::IS_ZST {
// handle ZSTs specially, which is – don't handle them at all.
return (self, &mut [], &mut []);
}
@@ -3776,6 +3814,16 @@ impl<T> [T] {
/// assert!(v[i..].iter().all(|&x| !(x < 5)));
/// ```
///
+ /// If all elements of the slice match the predicate, including if the slice
+ /// is empty, then the length of the slice will be returned:
+ ///
+ /// ```
+ /// let a = [2, 4, 8];
+ /// assert_eq!(a.partition_point(|x| x < &100), a.len());
+ /// let a: [i32; 0] = [];
+ /// assert_eq!(a.partition_point(|x| x < &100), 0);
+ /// ```
+ ///
/// If you want to insert an item to a sorted vector, while maintaining
/// sort order:
///
@@ -4066,7 +4114,7 @@ impl<T, const N: usize> [[T; N]] {
/// ```
#[unstable(feature = "slice_flatten", issue = "95629")]
pub fn flatten(&self) -> &[T] {
- let len = if crate::mem::size_of::<T>() == 0 {
+ let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")
} else {
// SAFETY: `self.len() * N` cannot overflow because `self` is
@@ -4104,7 +4152,7 @@ impl<T, const N: usize> [[T; N]] {
/// ```
#[unstable(feature = "slice_flatten", issue = "95629")]
pub fn flatten_mut(&mut self) -> &mut [T] {
- let len = if crate::mem::size_of::<T>() == 0 {
+ let len = if T::IS_ZST {
self.len().checked_mul(N).expect("slice len overflow")
} else {
// SAFETY: `self.len() * N` cannot overflow because `self` is
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index f1e8bc79b..052fd34d0 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -1,7 +1,9 @@
//! Free functions to create `&[T]` and `&mut [T]`.
use crate::array;
-use crate::intrinsics::{assert_unsafe_precondition, is_aligned_and_not_null};
+use crate::intrinsics::{
+ assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
+};
use crate::ops::Range;
use crate::ptr;
@@ -90,9 +92,10 @@ use crate::ptr;
pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts`.
unsafe {
- assert_unsafe_precondition!([T](data: *const T, len: usize) =>
- is_aligned_and_not_null(data)
- && crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
+ assert_unsafe_precondition!(
+ "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
+ [T](data: *const T, len: usize) => is_aligned_and_not_null(data)
+ && is_valid_allocation_size::<T>(len)
);
&*ptr::slice_from_raw_parts(data, len)
}
@@ -134,9 +137,10 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
// SAFETY: the caller must uphold the safety contract for `from_raw_parts_mut`.
unsafe {
- assert_unsafe_precondition!([T](data: *mut T, len: usize) =>
- is_aligned_and_not_null(data)
- && crate::mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize
+ assert_unsafe_precondition!(
+ "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
+ [T](data: *mut T, len: usize) => is_aligned_and_not_null(data)
+ && is_valid_allocation_size::<T>(len)
);
&mut *ptr::slice_from_raw_parts_mut(data, len)
}
@@ -188,6 +192,10 @@ pub const fn from_mut<T>(s: &mut T) -> &mut [T] {
///
/// Note that a range created from [`slice::as_ptr_range`] fulfills these requirements.
///
+/// # Panics
+///
+/// This function panics if `T` is a Zero-Sized Type (“ZST”).
+///
/// # Caveat
///
/// The lifetime for the returned slice is inferred from its usage. To
@@ -219,9 +227,15 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
}
-/// Performs the same functionality as [`from_ptr_range`], except that a
+/// Forms a mutable slice from a pointer range.
+///
+/// This is the same functionality as [`from_ptr_range`], except that a
/// mutable slice is returned.
///
+/// This function is useful for interacting with foreign interfaces which
+/// use two pointers to refer to a range of elements in memory, as is
+/// common in C++.
+///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
@@ -247,6 +261,18 @@ pub const unsafe fn from_ptr_range<'a, T>(range: Range<*const T>) -> &'a [T] {
///
/// Note that a range created from [`slice::as_mut_ptr_range`] fulfills these requirements.
///
+/// # Panics
+///
+/// This function panics if `T` is a Zero-Sized Type (“ZST”).
+///
+/// # Caveat
+///
+/// The lifetime for the returned slice is inferred from its usage. To
+/// prevent accidental misuse, it's suggested to tie the lifetime to whichever
+/// source lifetime is safe in the context, such as by providing a helper
+/// function taking the lifetime of a host value for the slice, or by explicit
+/// annotation.
+///
/// # Examples
///
/// ```
diff --git a/library/core/src/slice/rotate.rs b/library/core/src/slice/rotate.rs
index 4589c6c0f..fa8c238f8 100644
--- a/library/core/src/slice/rotate.rs
+++ b/library/core/src/slice/rotate.rs
@@ -1,5 +1,5 @@
use crate::cmp;
-use crate::mem::{self, MaybeUninit};
+use crate::mem::{self, MaybeUninit, SizedTypeProperties};
use crate::ptr;
/// Rotates the range `[mid-left, mid+right)` such that the element at `mid` becomes the first
@@ -63,7 +63,7 @@ use crate::ptr;
/// when `left < right` the swapping happens from the left instead.
pub unsafe fn ptr_rotate<T>(mut left: usize, mut mid: *mut T, mut right: usize) {
type BufType = [usize; 32];
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
return;
}
loop {
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index c6c03c0b0..87f77b7f2 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -7,7 +7,7 @@
//! stable sorting implementation.
use crate::cmp;
-use crate::mem::{self, MaybeUninit};
+use crate::mem::{self, MaybeUninit, SizedTypeProperties};
use crate::ptr;
/// When dropped, copies from `src` into `dest`.
@@ -813,7 +813,7 @@ where
F: FnMut(&T, &T) -> bool,
{
// Sorting has no meaningful behavior on zero-sized types.
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
return;
}
@@ -898,7 +898,7 @@ where
panic!("partition_at_index index {} greater than length of slice {}", index, v.len());
}
- if mem::size_of::<T>() == 0 {
+ if T::IS_ZST {
// Sorting has no meaningful behavior on zero-sized types. Do nothing.
} else if index == v.len() - 1 {
// Find max element and place it in the last position of the array. We're free to use
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index 343889b69..a11b5add4 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -1,6 +1,5 @@
//! Defines utf8 error type.
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt;
@@ -124,7 +123,6 @@ impl fmt::Display for Utf8Error {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for Utf8Error {
#[allow(deprecated)]
@@ -148,7 +146,6 @@ impl fmt::Display for ParseBoolError {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl Error for ParseBoolError {
#[allow(deprecated)]
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index f673aa2a4..fbc0fc397 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2642,5 +2642,4 @@ impl_fn_for_zst! {
}
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(bootstrap))]
impl !crate::error::Error for &str {}
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 031fb8e8b..ec2cb429e 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -267,7 +267,7 @@ pub unsafe trait Searcher<'a> {
/// The index ranges returned by this trait are not required
/// to exactly match those of the forward search in reverse.
///
-/// For the reason why this trait is marked unsafe, see them
+/// For the reason why this trait is marked unsafe, see the
/// parent trait [`Searcher`].
pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
/// Performs the next search step starting from the back.
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index e9649fc91..d3ed811b1 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -507,7 +507,6 @@ unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
///
/// ```
/// use std::str::FromStr;
-/// use std::num::ParseIntError;
///
/// #[derive(Debug, PartialEq)]
/// struct Point {
@@ -515,18 +514,21 @@ unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
/// y: i32
/// }
///
+/// #[derive(Debug, PartialEq, Eq)]
+/// struct ParsePointError;
+///
/// impl FromStr for Point {
-/// type Err = ParseIntError;
+/// type Err = ParsePointError;
///
/// fn from_str(s: &str) -> Result<Self, Self::Err> {
/// let (x, y) = s
/// .strip_prefix('(')
/// .and_then(|s| s.strip_suffix(')'))
/// .and_then(|s| s.split_once(','))
-/// .unwrap();
+/// .ok_or(ParsePointError)?;
///
-/// let x_fromstr = x.parse::<i32>()?;
-/// let y_fromstr = y.parse::<i32>()?;
+/// let x_fromstr = x.parse::<i32>().map_err(|_| ParsePointError)?;
+/// let y_fromstr = y.parse::<i32>().map_err(|_| ParsePointError)?;
///
/// Ok(Point { x: x_fromstr, y: y_fromstr })
/// }
@@ -538,6 +540,8 @@ unsafe impl const SliceIndex<str> for ops::RangeToInclusive<usize> {
/// // Implicit calls, through parse
/// assert_eq!("(1,2)".parse(), expected);
/// assert_eq!("(1,2)".parse::<Point>(), expected);
+/// // Invalid input string
+/// assert!(Point::from_str("(1 2)").is_err());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromStr: Sized {
@@ -573,8 +577,8 @@ impl FromStr for bool {
/// Parse a `bool` from a string.
///
- /// Yields a `Result<bool, ParseBoolError>`, because `s` may or may not
- /// actually be parseable.
+ /// The only accepted values are `"true"` and `"false"`. Any other input
+ /// will return an error.
///
/// # Examples
///
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 3c96290fc..edc68d6fa 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -294,7 +294,7 @@ impl AtomicBool {
/// ```
/// use std::sync::atomic::AtomicBool;
///
- /// let atomic_true = AtomicBool::new(true);
+ /// let atomic_true = AtomicBool::new(true);
/// let atomic_false = AtomicBool::new(false);
/// ```
#[inline]
@@ -955,6 +955,14 @@ impl AtomicBool {
/// **Note:** This method is only available on platforms that support atomic
/// operations on `u8`.
///
+ /// # Considerations
+ ///
+ /// This method is not magic; it is not provided by the hardware.
+ /// It is implemented in terms of [`AtomicBool::compare_exchange_weak`], and suffers from the same drawbacks.
+ /// In particular, this method will not circumvent the [ABA Problem].
+ ///
+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
+ ///
/// # Examples
///
/// ```rust
@@ -1171,7 +1179,7 @@ impl<T> AtomicPtr<T> {
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
- /// let some_ptr = AtomicPtr::new(ptr);
+ /// let some_ptr = AtomicPtr::new(ptr);
///
/// let value = some_ptr.load(Ordering::Relaxed);
/// ```
@@ -1198,7 +1206,7 @@ impl<T> AtomicPtr<T> {
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
- /// let some_ptr = AtomicPtr::new(ptr);
+ /// let some_ptr = AtomicPtr::new(ptr);
///
/// let other_ptr = &mut 10;
///
@@ -1230,7 +1238,7 @@ impl<T> AtomicPtr<T> {
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
- /// let some_ptr = AtomicPtr::new(ptr);
+ /// let some_ptr = AtomicPtr::new(ptr);
///
/// let other_ptr = &mut 10;
///
@@ -1282,9 +1290,9 @@ impl<T> AtomicPtr<T> {
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
- /// let some_ptr = AtomicPtr::new(ptr);
+ /// let some_ptr = AtomicPtr::new(ptr);
///
- /// let other_ptr = &mut 10;
+ /// let other_ptr = &mut 10;
///
/// let value = some_ptr.compare_and_swap(ptr, other_ptr, Ordering::Relaxed);
/// ```
@@ -1325,9 +1333,9 @@ impl<T> AtomicPtr<T> {
/// use std::sync::atomic::{AtomicPtr, Ordering};
///
/// let ptr = &mut 5;
- /// let some_ptr = AtomicPtr::new(ptr);
+ /// let some_ptr = AtomicPtr::new(ptr);
///
- /// let other_ptr = &mut 10;
+ /// let other_ptr = &mut 10;
///
/// let value = some_ptr.compare_exchange(ptr, other_ptr,
/// Ordering::SeqCst, Ordering::Relaxed);
@@ -1422,6 +1430,14 @@ impl<T> AtomicPtr<T> {
/// **Note:** This method is only available on platforms that support atomic
/// operations on pointers.
///
+ /// # Considerations
+ ///
+ /// This method is not magic; it is not provided by the hardware.
+ /// It is implemented in terms of [`AtomicPtr::compare_exchange_weak`], and suffers from the same drawbacks.
+ /// In particular, this method will not circumvent the [ABA Problem].
+ ///
+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
+ ///
/// # Examples
///
/// ```rust
@@ -1626,8 +1642,8 @@ impl<T> AtomicPtr<T> {
/// and the argument `val`, and stores a pointer with provenance of the
/// current pointer and the resulting address.
///
- /// This is equivalent equivalent to using [`map_addr`] to atomically
- /// perform `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged
+ /// This is equivalent to using [`map_addr`] to atomically perform
+ /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged
/// pointer schemes to atomically set tag bits.
///
/// **Caveat**: This operation returns the previous value. To compute the
@@ -1677,8 +1693,8 @@ impl<T> AtomicPtr<T> {
/// pointer, and the argument `val`, and stores a pointer with provenance of
/// the current pointer and the resulting address.
///
- /// This is equivalent equivalent to using [`map_addr`] to atomically
- /// perform `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged
+ /// This is equivalent to using [`map_addr`] to atomically perform
+ /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged
/// pointer schemes to atomically unset tag bits.
///
/// **Caveat**: This operation returns the previous value. To compute the
@@ -1727,8 +1743,8 @@ impl<T> AtomicPtr<T> {
/// pointer, and the argument `val`, and stores a pointer with provenance of
/// the current pointer and the resulting address.
///
- /// This is equivalent equivalent to using [`map_addr`] to atomically
- /// perform `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged
+ /// This is equivalent to using [`map_addr`] to atomically perform
+ /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged
/// pointer schemes to atomically toggle tag bits.
///
/// **Caveat**: This operation returns the previous value. To compute the
@@ -2510,6 +2526,16 @@ macro_rules! atomic_int {
/// **Note**: This method is only available on platforms that support atomic operations on
#[doc = concat!("[`", $s_int_type, "`].")]
///
+ /// # Considerations
+ ///
+ /// This method is not magic; it is not provided by the hardware.
+ /// It is implemented in terms of
+ #[doc = concat!("[`", stringify!($atomic_type), "::compare_exchange_weak`],")]
+ /// and suffers from the same drawbacks.
+ /// In particular, this method will not circumvent the [ABA Problem].
+ ///
+ /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
+ ///
/// # Examples
///
/// ```rust
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index a7519ab5a..c65c27500 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -100,6 +100,7 @@ impl<T: Sized> Exclusive<T> {
/// Wrap a value in an `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn new(t: T) -> Self {
Self { inner: t }
}
@@ -107,6 +108,7 @@ impl<T: Sized> Exclusive<T> {
/// Unwrap the value contained in the `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn into_inner(self) -> T {
self.inner
}
@@ -116,6 +118,7 @@ impl<T: ?Sized> Exclusive<T> {
/// Get exclusive access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn get_mut(&mut self) -> &mut T {
&mut self.inner
}
@@ -128,6 +131,7 @@ impl<T: ?Sized> Exclusive<T> {
/// produce _pinned_ access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
@@ -139,6 +143,7 @@ impl<T: ?Sized> Exclusive<T> {
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
// SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic
unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
@@ -149,6 +154,7 @@ impl<T: ?Sized> Exclusive<T> {
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
+ #[inline]
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
@@ -158,6 +164,7 @@ impl<T: ?Sized> Exclusive<T> {
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T> From<T> for Exclusive<T> {
+ #[inline]
fn from(t: T) -> Self {
Self::new(t)
}
@@ -166,7 +173,7 @@ impl<T> From<T> for Exclusive<T> {
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T: Future + ?Sized> Future for Exclusive<T> {
type Output = T::Output;
-
+ #[inline]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.get_pin_mut().poll(cx)
}
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 60ecc9c0b..0cff972df 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -186,17 +186,19 @@ pub struct Context<'a> {
impl<'a> Context<'a> {
/// Create a new `Context` from a [`&Waker`](Waker).
#[stable(feature = "futures_api", since = "1.36.0")]
+ #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[must_use]
#[inline]
- pub fn from_waker(waker: &'a Waker) -> Self {
+ pub const fn from_waker(waker: &'a Waker) -> Self {
Context { waker, _marker: PhantomData }
}
/// Returns a reference to the [`Waker`] for the current task.
#[stable(feature = "futures_api", since = "1.36.0")]
+ #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
#[must_use]
#[inline]
- pub fn waker(&self) -> &'a Waker {
+ pub const fn waker(&self) -> &'a Waker {
&self.waker
}
}
@@ -311,7 +313,8 @@ impl Waker {
#[inline]
#[must_use]
#[stable(feature = "futures_api", since = "1.36.0")]
- pub unsafe fn from_raw(waker: RawWaker) -> Waker {
+ #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
+ pub const unsafe fn from_raw(waker: RawWaker) -> Waker {
Waker { waker }
}
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 4f29ecc0f..ba1cb6efa 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -29,6 +29,20 @@ const NANOS_PER_MICRO: u32 = 1_000;
const MILLIS_PER_SEC: u64 = 1_000;
const MICROS_PER_SEC: u64 = 1_000_000;
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(0)]
+#[rustc_layout_scalar_valid_range_end(999_999_999)]
+struct Nanoseconds(u32);
+
+impl Default for Nanoseconds {
+ #[inline]
+ fn default() -> Self {
+ // SAFETY: 0 is within the valid range
+ unsafe { Nanoseconds(0) }
+ }
+}
+
/// A `Duration` type to represent a span of time, typically used for system
/// timeouts.
///
@@ -71,7 +85,7 @@ const MICROS_PER_SEC: u64 = 1_000_000;
#[cfg_attr(not(test), rustc_diagnostic_item = "Duration")]
pub struct Duration {
secs: u64,
- nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
+ nanos: Nanoseconds, // Always 0 <= nanos < NANOS_PER_SEC
}
impl Duration {
@@ -188,7 +202,8 @@ impl Duration {
None => panic!("overflow in Duration::new"),
};
let nanos = nanos % NANOS_PER_SEC;
- Duration { secs, nanos }
+ // SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range
+ Duration { secs, nanos: unsafe { Nanoseconds(nanos) } }
}
/// Creates a new `Duration` from the specified number of whole seconds.
@@ -208,7 +223,7 @@ impl Duration {
#[inline]
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
pub const fn from_secs(secs: u64) -> Duration {
- Duration { secs, nanos: 0 }
+ Duration::new(secs, 0)
}
/// Creates a new `Duration` from the specified number of milliseconds.
@@ -228,10 +243,7 @@ impl Duration {
#[inline]
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
pub const fn from_millis(millis: u64) -> Duration {
- Duration {
- secs: millis / MILLIS_PER_SEC,
- nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI,
- }
+ Duration::new(millis / MILLIS_PER_SEC, ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI)
}
/// Creates a new `Duration` from the specified number of microseconds.
@@ -251,10 +263,7 @@ impl Duration {
#[inline]
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
pub const fn from_micros(micros: u64) -> Duration {
- Duration {
- secs: micros / MICROS_PER_SEC,
- nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO,
- }
+ Duration::new(micros / MICROS_PER_SEC, ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO)
}
/// Creates a new `Duration` from the specified number of nanoseconds.
@@ -274,10 +283,7 @@ impl Duration {
#[inline]
#[rustc_const_stable(feature = "duration_consts", since = "1.32.0")]
pub const fn from_nanos(nanos: u64) -> Duration {
- Duration {
- secs: nanos / (NANOS_PER_SEC as u64),
- nanos: (nanos % (NANOS_PER_SEC as u64)) as u32,
- }
+ Duration::new(nanos / (NANOS_PER_SEC as u64), (nanos % (NANOS_PER_SEC as u64)) as u32)
}
/// Returns true if this `Duration` spans no time.
@@ -301,7 +307,7 @@ impl Duration {
#[rustc_const_stable(feature = "duration_zero", since = "1.53.0")]
#[inline]
pub const fn is_zero(&self) -> bool {
- self.secs == 0 && self.nanos == 0
+ self.secs == 0 && self.nanos.0 == 0
}
/// Returns the number of _whole_ seconds contained by this `Duration`.
@@ -352,7 +358,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn subsec_millis(&self) -> u32 {
- self.nanos / NANOS_PER_MILLI
+ self.nanos.0 / NANOS_PER_MILLI
}
/// Returns the fractional part of this `Duration`, in whole microseconds.
@@ -375,7 +381,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn subsec_micros(&self) -> u32 {
- self.nanos / NANOS_PER_MICRO
+ self.nanos.0 / NANOS_PER_MICRO
}
/// Returns the fractional part of this `Duration`, in nanoseconds.
@@ -398,7 +404,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn subsec_nanos(&self) -> u32 {
- self.nanos
+ self.nanos.0
}
/// Returns the total number of whole milliseconds contained by this `Duration`.
@@ -416,7 +422,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn as_millis(&self) -> u128 {
- self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128
+ self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128
}
/// Returns the total number of whole microseconds contained by this `Duration`.
@@ -434,7 +440,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn as_micros(&self) -> u128 {
- self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128
+ self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128
}
/// Returns the total number of nanoseconds contained by this `Duration`.
@@ -452,7 +458,7 @@ impl Duration {
#[must_use]
#[inline]
pub const fn as_nanos(&self) -> u128 {
- self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128
+ self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128
}
/// Checked `Duration` addition. Computes `self + other`, returning [`None`]
@@ -475,7 +481,7 @@ impl Duration {
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
- let mut nanos = self.nanos + rhs.nanos;
+ let mut nanos = self.nanos.0 + rhs.nanos.0;
if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC;
if let Some(new_secs) = secs.checked_add(1) {
@@ -485,7 +491,7 @@ impl Duration {
}
}
debug_assert!(nanos < NANOS_PER_SEC);
- Some(Duration { secs, nanos })
+ Some(Duration::new(secs, nanos))
} else {
None
}
@@ -535,16 +541,16 @@ impl Duration {
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
- let nanos = if self.nanos >= rhs.nanos {
- self.nanos - rhs.nanos
+ let nanos = if self.nanos.0 >= rhs.nanos.0 {
+ self.nanos.0 - rhs.nanos.0
} else if let Some(sub_secs) = secs.checked_sub(1) {
secs = sub_secs;
- self.nanos + NANOS_PER_SEC - rhs.nanos
+ self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0
} else {
return None;
};
debug_assert!(nanos < NANOS_PER_SEC);
- Some(Duration { secs, nanos })
+ Some(Duration::new(secs, nanos))
} else {
None
}
@@ -593,13 +599,13 @@ impl Duration {
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
// Multiply nanoseconds as u64, because it cannot overflow that way.
- let total_nanos = self.nanos as u64 * rhs as u64;
+ let total_nanos = self.nanos.0 as u64 * rhs as u64;
let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
if let Some(s) = self.secs.checked_mul(rhs as u64) {
if let Some(secs) = s.checked_add(extra_secs) {
debug_assert!(nanos < NANOS_PER_SEC);
- return Some(Duration { secs, nanos });
+ return Some(Duration::new(secs, nanos));
}
}
None
@@ -653,9 +659,9 @@ impl Duration {
let secs = self.secs / (rhs as u64);
let carry = self.secs - secs * (rhs as u64);
let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
- let nanos = self.nanos / rhs + (extra_nanos as u32);
+ let nanos = self.nanos.0 / rhs + (extra_nanos as u32);
debug_assert!(nanos < NANOS_PER_SEC);
- Some(Duration { secs, nanos })
+ Some(Duration::new(secs, nanos))
} else {
None
}
@@ -677,7 +683,7 @@ impl Duration {
#[inline]
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
pub const fn as_secs_f64(&self) -> f64 {
- (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
+ (self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64)
}
/// Returns the number of seconds contained by this `Duration` as `f32`.
@@ -696,7 +702,7 @@ impl Duration {
#[inline]
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
pub const fn as_secs_f32(&self) -> f32 {
- (self.secs as f32) + (self.nanos as f32) / (NANOS_PER_SEC as f32)
+ (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32)
}
/// Creates a new `Duration` from the specified number of seconds represented
@@ -987,13 +993,13 @@ macro_rules! sum_durations {
for entry in $iter {
total_secs =
total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations");
- total_nanos = match total_nanos.checked_add(entry.nanos as u64) {
+ total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) {
Some(n) => n,
None => {
total_secs = total_secs
.checked_add(total_nanos / NANOS_PER_SEC as u64)
.expect("overflow in iter::sum over durations");
- (total_nanos % NANOS_PER_SEC as u64) + entry.nanos as u64
+ (total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64
}
};
}
@@ -1001,7 +1007,7 @@ macro_rules! sum_durations {
.checked_add(total_nanos / NANOS_PER_SEC as u64)
.expect("overflow in iter::sum over durations");
total_nanos = total_nanos % NANOS_PER_SEC as u64;
- Duration { secs: total_secs, nanos: total_nanos as u32 }
+ Duration::new(total_secs, total_nanos as u32)
}};
}
@@ -1037,7 +1043,7 @@ impl fmt::Debug for Duration {
/// to the formatter's `width`, if specified.
fn fmt_decimal(
f: &mut fmt::Formatter<'_>,
- mut integer_part: u64,
+ integer_part: u64,
mut fractional_part: u32,
mut divisor: u32,
prefix: &str,
@@ -1069,7 +1075,7 @@ impl fmt::Debug for Duration {
// normal floating point numbers. However, we only need to do work
// when rounding up. This happens if the first digit of the
// remaining ones is >= 5.
- if fractional_part > 0 && fractional_part >= divisor * 5 {
+ let integer_part = if fractional_part > 0 && fractional_part >= divisor * 5 {
// Round up the number contained in the buffer. We go through
// the buffer backwards and keep track of the carry.
let mut rev_pos = pos;
@@ -1093,9 +1099,18 @@ impl fmt::Debug for Duration {
// the whole buffer to '0's and need to increment the integer
// part.
if carry {
- integer_part += 1;
+ // If `integer_part == u64::MAX` and precision < 9, any
+ // carry of the overflow during rounding of the
+ // `fractional_part` into the `integer_part` will cause the
+ // `integer_part` itself to overflow. Avoid this by using an
+ // `Option<u64>`, with `None` representing `u64::MAX + 1`.
+ integer_part.checked_add(1)
+ } else {
+ Some(integer_part)
}
- }
+ } else {
+ Some(integer_part)
+ };
// Determine the end of the buffer: if precision is set, we just
// use as many digits from the buffer (capped to 9). If it isn't
@@ -1105,7 +1120,12 @@ impl fmt::Debug for Duration {
// This closure emits the formatted duration without emitting any
// padding (padding is calculated below).
let emit_without_padding = |f: &mut fmt::Formatter<'_>| {
- write!(f, "{}{}", prefix, integer_part)?;
+ if let Some(integer_part) = integer_part {
+ write!(f, "{}{}", prefix, integer_part)?;
+ } else {
+ // u64::MAX + 1 == 18446744073709551616
+ write!(f, "{}18446744073709551616", prefix)?;
+ }
// Write the decimal point and the fractional part (if any).
if end > 0 {
@@ -1135,12 +1155,17 @@ impl fmt::Debug for Duration {
// 2. The postfix: can be "µs" so we have to count UTF8 characters.
let mut actual_w = prefix.len() + postfix.chars().count();
// 3. The integer part:
- if let Some(log) = integer_part.checked_ilog10() {
- // integer_part is > 0, so has length log10(x)+1
- actual_w += 1 + log as usize;
+ if let Some(integer_part) = integer_part {
+ if let Some(log) = integer_part.checked_ilog10() {
+ // integer_part is > 0, so has length log10(x)+1
+ actual_w += 1 + log as usize;
+ } else {
+ // integer_part is 0, so has length 1.
+ actual_w += 1;
+ }
} else {
- // integer_part is 0, so has length 1.
- actual_w += 1;
+ // integer_part is u64::MAX + 1, so has length 20
+ actual_w += 20;
}
// 4. The fractional part (if any):
if end > 0 {
@@ -1166,27 +1191,27 @@ impl fmt::Debug for Duration {
let prefix = if f.sign_plus() { "+" } else { "" };
if self.secs > 0 {
- fmt_decimal(f, self.secs, self.nanos, NANOS_PER_SEC / 10, prefix, "s")
- } else if self.nanos >= NANOS_PER_MILLI {
+ fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s")
+ } else if self.nanos.0 >= NANOS_PER_MILLI {
fmt_decimal(
f,
- (self.nanos / NANOS_PER_MILLI) as u64,
- self.nanos % NANOS_PER_MILLI,
+ (self.nanos.0 / NANOS_PER_MILLI) as u64,
+ self.nanos.0 % NANOS_PER_MILLI,
NANOS_PER_MILLI / 10,
prefix,
"ms",
)
- } else if self.nanos >= NANOS_PER_MICRO {
+ } else if self.nanos.0 >= NANOS_PER_MICRO {
fmt_decimal(
f,
- (self.nanos / NANOS_PER_MICRO) as u64,
- self.nanos % NANOS_PER_MICRO,
+ (self.nanos.0 / NANOS_PER_MICRO) as u64,
+ self.nanos.0 % NANOS_PER_MICRO,
NANOS_PER_MICRO / 10,
prefix,
"µs",
)
} else {
- fmt_decimal(f, self.nanos as u64, 0, 1, prefix, "ns")
+ fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns")
}
}
}
@@ -1200,7 +1225,6 @@ impl fmt::Debug for Duration {
/// # Example
///
/// ```
-/// #![feature(duration_checked_float)]
/// use std::time::Duration;
///
/// if let Err(e) = Duration::try_from_secs_f32(-1.0) {
@@ -1208,33 +1232,33 @@ impl fmt::Debug for Duration {
/// }
/// ```
#[derive(Debug, Clone, PartialEq, Eq)]
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-pub struct FromFloatSecsError {
- kind: FromFloatSecsErrorKind,
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+pub struct TryFromFloatSecsError {
+ kind: TryFromFloatSecsErrorKind,
}
-impl FromFloatSecsError {
+impl TryFromFloatSecsError {
const fn description(&self) -> &'static str {
match self.kind {
- FromFloatSecsErrorKind::Negative => {
+ TryFromFloatSecsErrorKind::Negative => {
"can not convert float seconds to Duration: value is negative"
}
- FromFloatSecsErrorKind::OverflowOrNan => {
+ TryFromFloatSecsErrorKind::OverflowOrNan => {
"can not convert float seconds to Duration: value is either too big or NaN"
}
}
}
}
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl fmt::Display for FromFloatSecsError {
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+impl fmt::Display for TryFromFloatSecsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.description().fmt(f)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
-enum FromFloatSecsErrorKind {
+enum TryFromFloatSecsErrorKind {
// Value is negative.
Negative,
// Value is either too big to be represented as `Duration` or `NaN`.
@@ -1254,8 +1278,8 @@ macro_rules! try_from_secs {
const MANT_MASK: $bits_ty = (1 << $mant_bits) - 1;
const EXP_MASK: $bits_ty = (1 << $exp_bits) - 1;
- if $secs.is_sign_negative() {
- return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::Negative });
+ if $secs < 0.0 {
+ return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::Negative });
}
let bits = $secs.to_bits();
@@ -1314,10 +1338,10 @@ macro_rules! try_from_secs {
let secs = u64::from(mant) << (exp - $mant_bits);
(secs, 0)
} else {
- return Err(FromFloatSecsError { kind: FromFloatSecsErrorKind::OverflowOrNan });
+ return Err(TryFromFloatSecsError { kind: TryFromFloatSecsErrorKind::OverflowOrNan });
};
- Ok(Duration { secs, nanos })
+ Ok(Duration::new(secs, nanos))
}};
}
@@ -1330,8 +1354,6 @@ impl Duration {
///
/// # Examples
/// ```
- /// #![feature(duration_checked_float)]
- ///
/// use std::time::Duration;
///
/// let res = Duration::try_from_secs_f32(0.0);
@@ -1379,9 +1401,10 @@ impl Duration {
/// let res = Duration::try_from_secs_f32(val);
/// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
/// ```
- #[unstable(feature = "duration_checked_float", issue = "83400")]
+ #[stable(feature = "duration_checked_float", since = "1.66.0")]
+ #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
#[inline]
- pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, FromFloatSecsError> {
+ pub const fn try_from_secs_f32(secs: f32) -> Result<Duration, TryFromFloatSecsError> {
try_from_secs!(
secs = secs,
mantissa_bits = 23,
@@ -1400,8 +1423,6 @@ impl Duration {
///
/// # Examples
/// ```
- /// #![feature(duration_checked_float)]
- ///
/// use std::time::Duration;
///
/// let res = Duration::try_from_secs_f64(0.0);
@@ -1457,9 +1478,10 @@ impl Duration {
/// let res = Duration::try_from_secs_f64(val);
/// assert_eq!(res, Ok(Duration::new(1, 2_929_688)));
/// ```
- #[unstable(feature = "duration_checked_float", issue = "83400")]
+ #[stable(feature = "duration_checked_float", since = "1.66.0")]
+ #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
#[inline]
- pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, FromFloatSecsError> {
+ pub const fn try_from_secs_f64(secs: f64) -> Result<Duration, TryFromFloatSecsError> {
try_from_secs!(
secs = secs,
mantissa_bits = 52,
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index aa8a2425b..fc91fe468 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -93,7 +93,8 @@ macro_rules! tuple_impls {
maybe_tuple_doc! {
$($T)+ @
#[stable(feature = "rust1", since = "1.0.0")]
- impl<$($T:Default),+> Default for ($($T,)+) {
+ #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
+ impl<$($T: ~const Default),+> const Default for ($($T,)+) {
#[inline]
fn default() -> ($($T,)+) {
($({ let x: $T = Default::default(); x},)+)
diff --git a/library/core/src/unicode/printable.rs b/library/core/src/unicode/printable.rs
index 31cf88a41..ffb18a5ba 100644
--- a/library/core/src/unicode/printable.rs
+++ b/library/core/src/unicode/printable.rs
@@ -54,7 +54,7 @@ pub(crate) fn is_printable(x: char) -> bool {
if 0x2a6e0 <= x && x < 0x2a700 {
return false;
}
- if 0x2b739 <= x && x < 0x2b740 {
+ if 0x2b73a <= x && x < 0x2b740 {
return false;
}
if 0x2b81e <= x && x < 0x2b820 {
@@ -69,7 +69,10 @@ pub(crate) fn is_printable(x: char) -> bool {
if 0x2fa1e <= x && x < 0x30000 {
return false;
}
- if 0x3134b <= x && x < 0xe0100 {
+ if 0x3134b <= x && x < 0x31350 {
+ return false;
+ }
+ if 0x323b0 <= x && x < 0xe0100 {
return false;
}
if 0xe01f0 <= x && x < 0x110000 {
@@ -92,7 +95,7 @@ const SINGLETONS0U: &[(u8, u8)] = &[
(0x0b, 25),
(0x0c, 26),
(0x0d, 16),
- (0x0e, 13),
+ (0x0e, 12),
(0x0f, 4),
(0x10, 3),
(0x12, 18),
@@ -142,24 +145,24 @@ const SINGLETONS0L: &[u8] = &[
0xe4, 0xe5, 0xf0, 0x0d, 0x11, 0x45, 0x49, 0x64,
0x65, 0x80, 0x84, 0xb2, 0xbc, 0xbe, 0xbf, 0xd5,
0xd7, 0xf0, 0xf1, 0x83, 0x85, 0x8b, 0xa4, 0xa6,
- 0xbe, 0xbf, 0xc5, 0xc7, 0xce, 0xcf, 0xda, 0xdb,
- 0x48, 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49,
- 0x4e, 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e,
- 0x8f, 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7,
- 0xd7, 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7,
- 0xfe, 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e,
- 0x1f, 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e,
- 0xae, 0xaf, 0x7f, 0xbb, 0xbc, 0x16, 0x17, 0x1e,
- 0x1f, 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c,
- 0x5e, 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc,
- 0xf0, 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75,
- 0x96, 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf,
- 0xc7, 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98,
- 0x30, 0x8f, 0x1f, 0xd2, 0xd4, 0xce, 0xff, 0x4e,
- 0x4f, 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27,
- 0x2f, 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f,
- 0x42, 0x45, 0x90, 0x91, 0x53, 0x67, 0x75, 0xc8,
- 0xc9, 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
+ 0xbe, 0xbf, 0xc5, 0xc7, 0xcf, 0xda, 0xdb, 0x48,
+ 0x98, 0xbd, 0xcd, 0xc6, 0xce, 0xcf, 0x49, 0x4e,
+ 0x4f, 0x57, 0x59, 0x5e, 0x5f, 0x89, 0x8e, 0x8f,
+ 0xb1, 0xb6, 0xb7, 0xbf, 0xc1, 0xc6, 0xc7, 0xd7,
+ 0x11, 0x16, 0x17, 0x5b, 0x5c, 0xf6, 0xf7, 0xfe,
+ 0xff, 0x80, 0x6d, 0x71, 0xde, 0xdf, 0x0e, 0x1f,
+ 0x6e, 0x6f, 0x1c, 0x1d, 0x5f, 0x7d, 0x7e, 0xae,
+ 0xaf, 0x7f, 0xbb, 0xbc, 0x16, 0x17, 0x1e, 0x1f,
+ 0x46, 0x47, 0x4e, 0x4f, 0x58, 0x5a, 0x5c, 0x5e,
+ 0x7e, 0x7f, 0xb5, 0xc5, 0xd4, 0xd5, 0xdc, 0xf0,
+ 0xf1, 0xf5, 0x72, 0x73, 0x8f, 0x74, 0x75, 0x96,
+ 0x26, 0x2e, 0x2f, 0xa7, 0xaf, 0xb7, 0xbf, 0xc7,
+ 0xcf, 0xd7, 0xdf, 0x9a, 0x40, 0x97, 0x98, 0x30,
+ 0x8f, 0x1f, 0xd2, 0xd4, 0xce, 0xff, 0x4e, 0x4f,
+ 0x5a, 0x5b, 0x07, 0x08, 0x0f, 0x10, 0x27, 0x2f,
+ 0xee, 0xef, 0x6e, 0x6f, 0x37, 0x3d, 0x3f, 0x42,
+ 0x45, 0x90, 0x91, 0x53, 0x67, 0x75, 0xc8, 0xc9,
+ 0xd0, 0xd1, 0xd8, 0xd9, 0xe7, 0xfe, 0xff,
];
#[rustfmt::skip]
const SINGLETONS1U: &[(u8, u8)] = &[
@@ -184,10 +187,12 @@ const SINGLETONS1U: &[(u8, u8)] = &[
(0x19, 13),
(0x1c, 5),
(0x1d, 8),
+ (0x1f, 1),
(0x24, 1),
(0x6a, 4),
(0x6b, 2),
(0xaf, 3),
+ (0xb1, 2),
(0xbc, 2),
(0xcf, 2),
(0xd1, 2),
@@ -203,7 +208,7 @@ const SINGLETONS1U: &[(u8, u8)] = &[
(0xee, 32),
(0xf0, 4),
(0xf8, 2),
- (0xfa, 2),
+ (0xfa, 3),
(0xfb, 1),
];
#[rustfmt::skip]
@@ -220,18 +225,19 @@ const SINGLETONS1L: &[u8] = &[
0x0a, 0x0b, 0x14, 0x17, 0x36, 0x39, 0x3a, 0xa8,
0xa9, 0xd8, 0xd9, 0x09, 0x37, 0x90, 0x91, 0xa8,
0x07, 0x0a, 0x3b, 0x3e, 0x66, 0x69, 0x8f, 0x92,
- 0x6f, 0x5f, 0xbf, 0xee, 0xef, 0x5a, 0x62, 0xf4,
- 0xfc, 0xff, 0x9a, 0x9b, 0x2e, 0x2f, 0x27, 0x28,
- 0x55, 0x9d, 0xa0, 0xa1, 0xa3, 0xa4, 0xa7, 0xa8,
- 0xad, 0xba, 0xbc, 0xc4, 0x06, 0x0b, 0x0c, 0x15,
- 0x1d, 0x3a, 0x3f, 0x45, 0x51, 0xa6, 0xa7, 0xcc,
- 0xcd, 0xa0, 0x07, 0x19, 0x1a, 0x22, 0x25, 0x3e,
- 0x3f, 0xe7, 0xec, 0xef, 0xff, 0xc5, 0xc6, 0x04,
- 0x20, 0x23, 0x25, 0x26, 0x28, 0x33, 0x38, 0x3a,
- 0x48, 0x4a, 0x4c, 0x50, 0x53, 0x55, 0x56, 0x58,
- 0x5a, 0x5c, 0x5e, 0x60, 0x63, 0x65, 0x66, 0x6b,
- 0x73, 0x78, 0x7d, 0x7f, 0x8a, 0xa4, 0xaa, 0xaf,
- 0xb0, 0xc0, 0xd0, 0xae, 0xaf, 0x6e, 0x6f, 0x93,
+ 0x11, 0x6f, 0x5f, 0xbf, 0xee, 0xef, 0x5a, 0x62,
+ 0xf4, 0xfc, 0xff, 0x53, 0x54, 0x9a, 0x9b, 0x2e,
+ 0x2f, 0x27, 0x28, 0x55, 0x9d, 0xa0, 0xa1, 0xa3,
+ 0xa4, 0xa7, 0xa8, 0xad, 0xba, 0xbc, 0xc4, 0x06,
+ 0x0b, 0x0c, 0x15, 0x1d, 0x3a, 0x3f, 0x45, 0x51,
+ 0xa6, 0xa7, 0xcc, 0xcd, 0xa0, 0x07, 0x19, 0x1a,
+ 0x22, 0x25, 0x3e, 0x3f, 0xe7, 0xec, 0xef, 0xff,
+ 0xc5, 0xc6, 0x04, 0x20, 0x23, 0x25, 0x26, 0x28,
+ 0x33, 0x38, 0x3a, 0x48, 0x4a, 0x4c, 0x50, 0x53,
+ 0x55, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x63,
+ 0x65, 0x66, 0x6b, 0x73, 0x78, 0x7d, 0x7f, 0x8a,
+ 0xa4, 0xaa, 0xaf, 0xb0, 0xc0, 0xd0, 0xae, 0xaf,
+ 0x6e, 0x6f, 0xbe, 0x93,
];
#[rustfmt::skip]
const NORMAL0: &[u8] = &[
@@ -272,7 +278,7 @@ const NORMAL0: &[u8] = &[
0x1b, 0x07,
0x57, 0x07,
0x02, 0x06,
- 0x16, 0x0d,
+ 0x17, 0x0c,
0x50, 0x04,
0x43, 0x03,
0x2d, 0x03,
@@ -424,8 +430,8 @@ const NORMAL1: &[u8] = &[
0x33, 0x07,
0x2e, 0x08,
0x0a, 0x81, 0x26,
- 0x52, 0x4e,
- 0x28, 0x08,
+ 0x52, 0x4b,
+ 0x2b, 0x08,
0x2a, 0x16,
0x1a, 0x26,
0x1c, 0x14,
@@ -438,7 +444,7 @@ const NORMAL1: &[u8] = &[
0x48, 0x08,
0x27, 0x09,
0x75, 0x0b,
- 0x3f, 0x41,
+ 0x42, 0x3e,
0x2a, 0x06,
0x3b, 0x05,
0x0a, 0x06,
@@ -464,7 +470,8 @@ const NORMAL1: &[u8] = &[
0x45, 0x1b,
0x48, 0x08,
0x53, 0x0d,
- 0x49, 0x81, 0x07,
+ 0x49, 0x07,
+ 0x0a, 0x80, 0xf6,
0x46, 0x0a,
0x1d, 0x03,
0x47, 0x49,
@@ -473,14 +480,17 @@ const NORMAL1: &[u8] = &[
0x0a, 0x06,
0x39, 0x07,
0x0a, 0x81, 0x36,
- 0x19, 0x80, 0xb7,
+ 0x19, 0x07,
+ 0x3b, 0x03,
+ 0x1c, 0x56,
0x01, 0x0f,
0x32, 0x0d,
0x83, 0x9b, 0x66,
0x75, 0x0b,
0x80, 0xc4, 0x8a, 0x4c,
0x63, 0x0d,
- 0x84, 0x2f, 0x8f, 0xd1,
+ 0x84, 0x30, 0x10,
+ 0x16, 0x8f, 0xaa,
0x82, 0x47, 0xa1, 0xb9,
0x82, 0x39, 0x07,
0x2a, 0x04,
@@ -498,8 +508,9 @@ const NORMAL1: &[u8] = &[
0x97, 0xf8, 0x08,
0x84, 0xd6, 0x2a,
0x09, 0xa2, 0xe7,
- 0x81, 0x33, 0x2d,
- 0x03, 0x11,
+ 0x81, 0x33, 0x0f,
+ 0x01, 0x1d,
+ 0x06, 0x0e,
0x04, 0x08,
0x81, 0x8c, 0x89, 0x04,
0x6b, 0x05,
@@ -511,21 +522,26 @@ const NORMAL1: &[u8] = &[
0x80, 0xf6, 0x0a,
0x73, 0x08,
0x70, 0x15,
- 0x46, 0x80, 0x9a,
+ 0x46, 0x7a,
+ 0x14, 0x0c,
0x14, 0x0c,
0x57, 0x09,
0x19, 0x80, 0x87,
0x81, 0x47, 0x03,
0x85, 0x42, 0x0f,
0x15, 0x84, 0x50,
- 0x1f, 0x80, 0xe1,
- 0x2b, 0x80, 0xd5,
+ 0x1f, 0x06,
+ 0x06, 0x80, 0xd5,
+ 0x2b, 0x05,
+ 0x3e, 0x21,
+ 0x01, 0x70,
0x2d, 0x03,
0x1a, 0x04,
0x02, 0x81, 0x40,
0x1f, 0x11,
0x3a, 0x05,
- 0x01, 0x84, 0xe0,
+ 0x01, 0x81, 0xd0,
+ 0x2a, 0x82, 0xe6,
0x80, 0xf7, 0x29,
0x4c, 0x04,
0x0a, 0x04,
@@ -546,11 +562,11 @@ const NORMAL1: &[u8] = &[
0x09, 0x07,
0x02, 0x0e,
0x06, 0x80, 0x9a,
- 0x83, 0xd8, 0x05,
- 0x10, 0x03,
+ 0x83, 0xd8, 0x04,
+ 0x11, 0x03,
0x0d, 0x03,
- 0x74, 0x0c,
- 0x59, 0x07,
+ 0x77, 0x04,
+ 0x5f, 0x06,
0x0c, 0x04,
0x01, 0x0f,
0x0c, 0x04,
@@ -559,15 +575,12 @@ const NORMAL1: &[u8] = &[
0x28, 0x08,
0x22, 0x4e,
0x81, 0x54, 0x0c,
- 0x15, 0x03,
- 0x05, 0x03,
- 0x07, 0x09,
0x1d, 0x03,
- 0x0b, 0x05,
- 0x06, 0x0a,
- 0x0a, 0x06,
- 0x08, 0x08,
- 0x07, 0x09,
+ 0x09, 0x07,
+ 0x36, 0x08,
+ 0x0e, 0x04,
+ 0x09, 0x07,
+ 0x09, 0x07,
0x80, 0xcb, 0x25,
0x0a, 0x84, 0x06,
];
diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs
index 7301da2af..bd69ca520 100644
--- a/library/core/src/unicode/unicode_data.rs
+++ b/library/core/src/unicode/unicode_data.rs
@@ -99,21 +99,21 @@ fn skip_search<const SOR: usize, const OFFSETS: usize>(
offset_idx % 2 == 1
}
-pub const UNICODE_VERSION: (u8, u8, u8) = (14, 0, 0);
+pub const UNICODE_VERSION: (u8, u8, u8) = (15, 0, 0);
#[rustfmt::skip]
pub mod alphabetic {
- static SHORT_OFFSET_RUNS: [u32; 51] = [
- 706, 33559113, 876615277, 956309270, 1166025910, 1314925568, 1319120901, 1398813696,
- 1449151936, 1451271309, 1455465997, 1463867300, 1652619520, 1663105646, 1665203518,
- 1711342208, 1797326647, 1891700352, 2044795904, 2397118176, 2485199770, 2495688592,
- 2506175535, 2512471040, 2514568775, 2516674560, 2518772281, 2520870464, 2552334328,
- 2583792854, 2587996144, 2594287907, 2608968444, 2621553664, 2623656960, 2644629158,
- 2722225920, 2770461328, 2808211424, 2816601600, 2850156848, 2988572672, 3001198304,
- 3003299641, 3007499938, 3015896033, 3020093440, 3022191134, 3024289792, 3026391883,
- 3029603147,
+ static SHORT_OFFSET_RUNS: [u32; 53] = [
+ 706, 33559113, 872420973, 952114966, 1161831606, 1310731264, 1314926597, 1394619392,
+ 1444957632, 1447077005, 1451271693, 1459672996, 1648425216, 1658911342, 1661009214,
+ 1707147904, 1793132343, 1887506048, 2040601600, 2392923872, 2481005466, 2504077200,
+ 2514564144, 2520859648, 2527151687, 2529257472, 2531355193, 2533453376, 2564917240,
+ 2596375766, 2600579056, 2606870819, 2621551356, 2642525184, 2644628480, 2665600678,
+ 2743197440, 2791432848, 2841765072, 2850154464, 2854350336, 2887905584, 3026321408,
+ 3038947040, 3041048378, 3045248674, 3053644769, 3057842176, 3059939870, 3062038528,
+ 3064140619, 3066241968, 3071550384,
];
- static OFFSETS: [u8; 1445] = [
+ static OFFSETS: [u8; 1465] = [
65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 0, 4, 12, 14, 5, 7, 1, 1, 1, 86, 1, 42,
5, 1, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 2, 1, 6, 41, 39,
14, 1, 1, 1, 2, 1, 2, 1, 1, 8, 27, 4, 4, 29, 11, 5, 56, 1, 7, 14, 102, 1, 8, 4, 8, 4, 3, 10,
@@ -123,50 +123,51 @@ pub mod alphabetic {
2, 1, 2, 4, 5, 4, 2, 2, 2, 4, 1, 7, 4, 1, 1, 17, 6, 11, 3, 1, 9, 1, 3, 1, 22, 1, 7, 1, 2, 1,
5, 3, 9, 1, 3, 1, 2, 3, 1, 15, 4, 21, 4, 4, 3, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2,
2, 2, 2, 9, 2, 4, 2, 1, 5, 13, 1, 16, 2, 1, 6, 3, 3, 1, 4, 3, 2, 1, 1, 1, 2, 3, 2, 3, 3, 3,
- 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 4, 1, 8, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2,
- 1, 3, 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4,
- 13, 2, 13, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24,
- 1, 9, 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1,
- 1, 1, 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 17, 6, 16, 1, 36, 67, 55,
- 1, 1, 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1,
- 4, 2, 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2,
- 17, 1, 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4,
- 1, 67, 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2,
- 20, 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3,
- 10, 36, 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2,
- 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1,
- 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2,
- 4, 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23,
- 9, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4,
- 86, 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10,
- 2, 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 64, 5, 2, 1, 1, 1, 5, 24, 20, 1, 33, 24, 52, 12,
- 68, 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1,
- 55, 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1,
- 43, 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1,
- 1, 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89,
- 3, 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3,
+ 12, 4, 5, 3, 3, 1, 3, 3, 1, 6, 1, 40, 13, 1, 3, 1, 23, 1, 16, 3, 8, 1, 3, 1, 3, 8, 2, 1, 3,
+ 2, 1, 2, 4, 28, 4, 1, 8, 1, 3, 1, 23, 1, 10, 1, 5, 3, 8, 1, 3, 1, 3, 8, 2, 6, 2, 1, 4, 13,
+ 3, 12, 13, 1, 3, 1, 41, 2, 8, 1, 3, 1, 3, 1, 1, 5, 4, 7, 5, 22, 6, 1, 3, 1, 18, 3, 24, 1, 9,
+ 1, 1, 2, 7, 8, 6, 1, 1, 1, 8, 18, 2, 13, 58, 5, 7, 6, 1, 51, 2, 1, 1, 1, 5, 1, 24, 1, 1, 1,
+ 19, 1, 3, 2, 5, 1, 1, 6, 1, 14, 4, 32, 1, 63, 8, 1, 36, 4, 19, 4, 16, 1, 36, 67, 55, 1, 1,
+ 2, 5, 16, 64, 10, 4, 2, 38, 1, 1, 5, 1, 2, 43, 1, 0, 1, 4, 2, 7, 1, 1, 1, 4, 2, 41, 1, 4, 2,
+ 33, 1, 4, 2, 7, 1, 1, 1, 4, 2, 15, 1, 57, 1, 4, 2, 67, 37, 16, 16, 86, 2, 6, 3, 0, 2, 17, 1,
+ 26, 5, 75, 3, 11, 7, 20, 11, 21, 12, 20, 12, 13, 1, 3, 1, 2, 12, 52, 2, 19, 14, 1, 4, 1, 67,
+ 89, 7, 43, 5, 70, 10, 31, 1, 12, 4, 9, 23, 30, 2, 5, 11, 44, 4, 26, 54, 28, 4, 63, 2, 20,
+ 50, 1, 23, 2, 11, 3, 49, 52, 1, 15, 1, 8, 51, 42, 2, 4, 10, 44, 1, 11, 14, 55, 22, 3, 10,
+ 36, 2, 9, 7, 43, 2, 3, 41, 4, 1, 6, 1, 2, 3, 1, 5, 192, 39, 14, 11, 0, 2, 6, 2, 38, 2, 6, 2,
+ 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13, 5, 3, 1, 7,
+ 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4, 1, 11, 2, 4,
+ 5, 5, 4, 1, 17, 41, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1, 2, 56, 7, 1, 16, 23, 9,
+ 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 32, 47, 1, 0, 3, 25, 9, 7, 5, 2, 5, 4, 86,
+ 6, 3, 1, 90, 1, 4, 5, 43, 1, 94, 17, 32, 48, 16, 0, 0, 64, 0, 67, 46, 2, 0, 3, 16, 10, 2,
+ 20, 47, 5, 8, 3, 113, 39, 9, 2, 103, 2, 64, 5, 2, 1, 1, 1, 5, 24, 20, 1, 33, 24, 52, 12, 68,
+ 1, 1, 44, 6, 3, 1, 1, 3, 10, 33, 5, 35, 13, 29, 3, 51, 1, 12, 15, 1, 16, 16, 10, 5, 1, 55,
+ 9, 14, 18, 23, 3, 69, 1, 1, 1, 1, 24, 3, 2, 16, 2, 4, 11, 6, 2, 6, 2, 6, 9, 7, 1, 7, 1, 43,
+ 1, 14, 6, 123, 21, 0, 12, 23, 4, 49, 0, 0, 2, 106, 38, 7, 12, 5, 5, 12, 1, 13, 1, 5, 1, 1,
+ 1, 2, 1, 2, 1, 108, 33, 0, 18, 64, 2, 54, 40, 12, 116, 5, 1, 135, 36, 26, 6, 26, 11, 89, 3,
+ 6, 2, 6, 2, 6, 2, 3, 35, 12, 1, 26, 1, 19, 1, 2, 1, 15, 2, 14, 34, 123, 69, 53, 0, 29, 3,
49, 47, 32, 13, 30, 5, 43, 5, 30, 2, 36, 4, 8, 1, 5, 42, 158, 18, 36, 4, 36, 4, 40, 8, 52,
12, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1, 7, 1, 2, 67, 0, 9, 22, 10, 8, 24, 6, 1, 42, 1,
9, 69, 6, 2, 1, 1, 44, 1, 2, 3, 1, 2, 23, 10, 23, 9, 31, 65, 19, 1, 2, 10, 22, 10, 26, 70,
56, 6, 2, 64, 4, 1, 2, 5, 8, 1, 3, 1, 29, 42, 29, 3, 29, 35, 8, 1, 28, 27, 54, 10, 22, 10,
19, 13, 18, 110, 73, 55, 51, 13, 51, 13, 40, 0, 42, 1, 2, 3, 2, 78, 29, 10, 1, 8, 22, 42,
- 18, 46, 21, 27, 23, 9, 70, 43, 5, 12, 55, 9, 1, 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64,
- 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 1, 65, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57,
+ 18, 46, 21, 27, 23, 9, 70, 43, 5, 10, 57, 9, 1, 13, 25, 23, 51, 17, 4, 8, 35, 3, 1, 9, 64,
+ 1, 4, 9, 2, 10, 1, 1, 1, 35, 18, 1, 34, 2, 1, 6, 4, 62, 7, 1, 1, 1, 4, 1, 15, 1, 10, 7, 57,
23, 4, 1, 8, 2, 2, 2, 22, 1, 7, 1, 2, 1, 5, 3, 8, 2, 2, 2, 2, 3, 1, 6, 1, 5, 7, 156, 66, 1,
3, 1, 4, 20, 3, 30, 66, 2, 2, 1, 1, 184, 54, 2, 7, 25, 6, 34, 63, 1, 1, 3, 1, 59, 54, 2, 1,
71, 27, 2, 14, 21, 7, 185, 57, 103, 64, 31, 8, 2, 1, 2, 8, 1, 2, 1, 30, 1, 2, 2, 2, 2, 4,
93, 8, 2, 46, 2, 6, 1, 1, 1, 2, 27, 51, 2, 10, 17, 72, 5, 1, 18, 73, 0, 9, 1, 45, 1, 7, 1,
1, 49, 30, 2, 22, 1, 14, 73, 7, 1, 2, 1, 44, 3, 1, 1, 2, 1, 3, 1, 1, 2, 2, 24, 6, 1, 2, 1,
- 37, 1, 2, 1, 4, 1, 1, 0, 23, 185, 1, 79, 0, 102, 111, 17, 196, 0, 97, 15, 0, 0, 0, 0, 0, 7,
- 31, 17, 79, 17, 30, 18, 48, 16, 4, 31, 21, 5, 19, 0, 64, 128, 75, 4, 57, 7, 17, 64, 2, 1, 1,
- 12, 2, 14, 0, 8, 0, 42, 9, 0, 4, 1, 7, 1, 2, 1, 0, 45, 3, 17, 4, 8, 0, 0, 107, 5, 13, 3, 9,
- 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1,
- 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1,
- 25, 1, 31, 1, 25, 1, 8, 0, 31, 225, 7, 1, 17, 2, 7, 1, 2, 1, 5, 213, 45, 10, 7, 16, 1, 0,
- 30, 18, 44, 0, 7, 1, 4, 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2,
- 1, 1, 10, 1, 4, 1, 1, 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 1, 2, 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26,
- 6, 26, 6, 26, 0, 0, 32, 0, 7, 222, 2, 0, 14, 0, 0, 0, 0, 0, 0,
+ 37, 1, 2, 1, 4, 1, 1, 0, 23, 9, 17, 1, 41, 3, 3, 111, 1, 79, 0, 102, 111, 17, 196, 0, 97,
+ 15, 0, 17, 6, 0, 0, 0, 0, 7, 31, 17, 79, 17, 30, 18, 48, 16, 4, 31, 21, 5, 19, 0, 64, 128,
+ 75, 4, 57, 7, 17, 64, 2, 1, 1, 12, 2, 14, 0, 8, 0, 42, 9, 0, 4, 1, 7, 1, 2, 1, 0, 15, 1, 29,
+ 3, 2, 1, 14, 4, 8, 0, 0, 107, 5, 13, 3, 9, 7, 10, 4, 1, 0, 85, 1, 71, 1, 2, 2, 1, 2, 2, 2,
+ 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2, 25,
+ 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 31, 6, 6, 213, 7, 1,
+ 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 112, 45, 10, 7, 16, 1, 0, 30, 18, 44, 0, 28, 0, 7, 1, 4,
+ 1, 2, 1, 15, 1, 197, 59, 68, 3, 1, 3, 1, 0, 4, 1, 27, 1, 2, 1, 1, 2, 1, 1, 10, 1, 4, 1, 1,
+ 1, 1, 6, 1, 4, 1, 1, 1, 1, 1, 1, 3, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2,
+ 4, 1, 7, 1, 4, 1, 4, 1, 1, 1, 10, 1, 17, 5, 3, 1, 5, 1, 17, 0, 26, 6, 26, 6, 26, 0, 0, 32,
+ 0, 6, 222, 2, 0, 14, 0, 0, 0, 0, 0, 5, 0, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
@@ -182,11 +183,11 @@ pub mod case_ignorable {
static SHORT_OFFSET_RUNS: [u32; 35] = [
688, 44045149, 572528402, 576724925, 807414908, 878718981, 903913493, 929080568, 933275148,
937491230, 1138818560, 1147208189, 1210124160, 1222707713, 1235291428, 1260457643,
- 1264654383, 1491147067, 1499536432, 1558257395, 1621177392, 1625385712, 1629581135,
- 1642180592, 1658961053, 1671548672, 1679937895, 1688328704, 1709301760, 1734467888,
- 1755439790, 1759635664, 1768027131, 1777205249, 1782514160,
+ 1264654383, 1499535675, 1507925040, 1566646003, 1629566000, 1650551536, 1658941263,
+ 1671540720, 1688321181, 1700908800, 1709298023, 1717688832, 1738661888, 1763828398,
+ 1797383403, 1805773008, 1809970171, 1819148289, 1824457200,
];
- static OFFSETS: [u8; 855] = [
+ static OFFSETS: [u8; 875] = [
39, 1, 6, 1, 11, 1, 35, 1, 1, 1, 71, 1, 4, 1, 1, 1, 4, 1, 2, 2, 0, 192, 4, 2, 4, 1, 9, 2,
1, 1, 251, 7, 207, 1, 5, 1, 49, 45, 1, 1, 1, 2, 1, 2, 1, 1, 44, 1, 11, 6, 10, 11, 1, 1, 35,
1, 10, 21, 16, 1, 101, 8, 1, 10, 1, 4, 33, 1, 1, 1, 30, 27, 91, 11, 58, 11, 4, 1, 2, 1, 24,
@@ -195,7 +196,7 @@ pub mod case_ignorable {
57, 1, 4, 5, 1, 2, 4, 1, 20, 2, 22, 6, 1, 1, 58, 1, 2, 1, 1, 4, 8, 1, 7, 2, 11, 2, 30, 1,
61, 1, 12, 1, 50, 1, 3, 1, 55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 6, 1,
5, 2, 20, 2, 28, 2, 57, 2, 4, 4, 8, 1, 20, 2, 29, 1, 72, 1, 7, 3, 1, 1, 90, 1, 2, 7, 11, 9,
- 98, 1, 2, 9, 9, 1, 1, 6, 74, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
+ 98, 1, 2, 9, 9, 1, 1, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 94, 1, 0, 3, 0, 3,
29, 2, 30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 3, 1, 5, 1, 45, 5, 51, 1, 65, 2, 34, 1, 118,
3, 4, 2, 9, 1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 39, 1, 8, 31,
@@ -209,15 +210,16 @@ pub mod case_ignorable {
1, 1, 27, 1, 14, 2, 5, 2, 1, 1, 100, 5, 9, 3, 121, 1, 2, 1, 4, 1, 0, 1, 147, 17, 0, 16, 3,
1, 12, 16, 34, 1, 2, 1, 169, 1, 7, 1, 6, 1, 11, 1, 35, 1, 1, 1, 47, 1, 45, 2, 67, 1, 21, 3,
0, 1, 226, 1, 149, 5, 0, 6, 1, 42, 1, 9, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2,
- 153, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1, 50, 3,
- 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 160, 1, 3, 8, 21, 2,
- 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2, 238, 4, 6, 2,
- 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 0,
- 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0,
- 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1,
- 0, 2, 0, 9, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17, 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0,
- 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7,
- 1, 17, 2, 7, 1, 2, 1, 5, 0, 14, 0, 1, 61, 4, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0,
+ 80, 3, 70, 11, 49, 4, 123, 1, 54, 15, 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 2, 1, 4, 1, 10, 1,
+ 50, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1,
+ 3, 8, 21, 2, 57, 2, 3, 1, 37, 7, 3, 5, 195, 8, 2, 3, 1, 1, 23, 1, 84, 6, 1, 1, 4, 2, 1, 2,
+ 238, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5,
+ 0, 9, 1, 2, 0, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46,
+ 13, 1, 2, 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2,
+ 3, 1, 1, 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 17, 6, 15, 0, 5, 59, 7, 9, 4, 0, 1, 63, 17,
+ 64, 2, 1, 2, 0, 4, 1, 7, 1, 2, 0, 2, 1, 4, 0, 46, 2, 23, 0, 3, 9, 16, 2, 7, 30, 4, 148, 3,
+ 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 5, 62, 33, 1, 160,
+ 14, 0, 1, 61, 4, 0, 5, 0, 7, 109, 8, 0, 5, 0, 1, 30, 96, 128, 240, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
@@ -230,24 +232,24 @@ pub mod case_ignorable {
#[rustfmt::skip]
pub mod cased {
- static SHORT_OFFSET_RUNS: [u32; 21] = [
+ static SHORT_OFFSET_RUNS: [u32; 22] = [
4256, 115348384, 136322176, 144711446, 163587254, 320875520, 325101120, 350268208,
392231680, 404815649, 413205504, 421595008, 467733632, 484513952, 492924480, 497144832,
- 501339814, 578936576, 627173632, 635564336, 640872842,
+ 501339814, 578936576, 627171376, 639756544, 643952944, 649261450,
];
- static OFFSETS: [u8; 311] = [
+ static OFFSETS: [u8; 315] = [
65, 26, 6, 26, 47, 1, 10, 1, 4, 1, 5, 23, 1, 31, 1, 195, 1, 4, 4, 208, 1, 36, 7, 2, 30, 5,
96, 1, 42, 4, 2, 2, 2, 4, 1, 1, 6, 1, 1, 3, 1, 1, 1, 20, 1, 83, 1, 139, 8, 166, 1, 38, 9,
- 41, 0, 38, 1, 1, 5, 1, 2, 43, 2, 3, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2,
+ 41, 0, 38, 1, 1, 5, 1, 2, 43, 1, 4, 0, 86, 2, 6, 0, 9, 7, 43, 2, 3, 64, 192, 64, 0, 2, 6, 2,
38, 2, 6, 2, 8, 1, 1, 1, 1, 1, 1, 1, 31, 2, 53, 1, 7, 1, 1, 3, 3, 1, 7, 3, 4, 2, 6, 4, 13,
5, 3, 1, 7, 116, 1, 13, 1, 16, 13, 101, 1, 4, 1, 2, 10, 1, 1, 3, 5, 6, 1, 1, 1, 1, 1, 1, 4,
1, 6, 4, 1, 2, 4, 5, 5, 4, 1, 17, 32, 3, 2, 0, 52, 0, 229, 6, 4, 3, 2, 12, 38, 1, 1, 5, 1,
- 0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 27, 2, 1, 3, 0, 43, 1, 13, 7, 80, 0,
+ 0, 46, 18, 30, 132, 102, 3, 4, 1, 59, 5, 2, 1, 1, 1, 5, 24, 5, 1, 3, 0, 43, 1, 14, 6, 80, 0,
7, 12, 5, 0, 26, 6, 26, 0, 80, 96, 36, 4, 36, 116, 11, 1, 15, 1, 7, 1, 2, 1, 11, 1, 15, 1,
7, 1, 2, 0, 1, 2, 3, 1, 42, 1, 9, 0, 51, 13, 51, 0, 64, 0, 64, 0, 85, 1, 71, 1, 2, 2, 1, 2,
2, 2, 4, 1, 12, 1, 1, 1, 7, 1, 65, 1, 4, 2, 8, 1, 7, 1, 28, 1, 4, 1, 5, 1, 1, 3, 7, 1, 0, 2,
- 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 0,
- 68, 0, 26, 6, 26, 6, 26, 0,
+ 25, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 31, 1, 25, 1, 8, 0, 10, 1, 20, 6, 6,
+ 0, 62, 0, 68, 0, 26, 6, 26, 6, 26, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
@@ -277,14 +279,14 @@ pub mod cc {
#[rustfmt::skip]
pub mod grapheme_extend {
- static SHORT_OFFSET_RUNS: [u32; 32] = [
+ static SHORT_OFFSET_RUNS: [u32; 33] = [
768, 2098307, 6292881, 10490717, 522196754, 526393356, 731917551, 740306986, 752920175,
761309186, 778107678, 908131840, 912326558, 920715773, 924912129, 937495844, 962662059,
- 966858799, 1205935152, 1277239027, 1340173040, 1344368463, 1352776861, 1365364480,
- 1369559397, 1377950208, 1407311872, 1432478000, 1453449902, 1457645776, 1466826784,
- 1476329968,
+ 966858799, 1214323760, 1285627635, 1348547648, 1369533168, 1377922895, 1386331293,
+ 1398918912, 1403113829, 1411504640, 1440866304, 1466032814, 1495393516, 1503783120,
+ 1508769824, 1518273008,
];
- static OFFSETS: [u8; 707] = [
+ static OFFSETS: [u8; 727] = [
0, 112, 0, 7, 0, 45, 1, 1, 1, 2, 1, 2, 1, 1, 72, 11, 48, 21, 16, 1, 101, 7, 2, 6, 2, 2, 1,
4, 35, 1, 30, 27, 91, 11, 58, 9, 9, 1, 24, 4, 1, 9, 1, 3, 1, 5, 43, 3, 60, 8, 42, 24, 1, 32,
55, 1, 1, 1, 4, 8, 4, 1, 3, 7, 10, 2, 29, 1, 58, 1, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 26, 1, 2,
@@ -292,7 +294,7 @@ pub mod grapheme_extend {
1, 1, 58, 1, 1, 2, 1, 4, 8, 1, 7, 3, 10, 2, 30, 1, 59, 1, 1, 1, 12, 1, 9, 1, 40, 1, 3, 1,
55, 1, 1, 3, 5, 3, 1, 4, 7, 2, 11, 2, 29, 1, 58, 1, 2, 1, 2, 1, 3, 1, 5, 2, 7, 2, 11, 2, 28,
2, 57, 2, 1, 1, 2, 4, 8, 1, 9, 1, 10, 2, 29, 1, 72, 1, 4, 1, 2, 3, 1, 1, 8, 1, 81, 1, 2, 7,
- 12, 8, 98, 1, 2, 9, 11, 6, 74, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
+ 12, 8, 98, 1, 2, 9, 11, 7, 73, 2, 27, 1, 1, 1, 1, 1, 55, 14, 1, 5, 1, 2, 5, 11, 1, 36, 9, 1,
102, 4, 1, 6, 1, 2, 2, 2, 25, 2, 4, 3, 16, 4, 13, 1, 2, 2, 6, 1, 15, 1, 0, 3, 0, 3, 29, 2,
30, 2, 30, 2, 64, 2, 1, 7, 8, 1, 2, 11, 9, 1, 45, 3, 1, 1, 117, 2, 34, 1, 118, 3, 4, 2, 9,
1, 6, 3, 219, 2, 2, 1, 58, 1, 1, 7, 1, 1, 1, 1, 2, 8, 6, 10, 2, 1, 48, 31, 49, 4, 48, 7, 1,
@@ -301,16 +303,17 @@ pub mod grapheme_extend {
4, 1, 10, 32, 2, 80, 2, 0, 1, 3, 1, 4, 1, 25, 2, 5, 1, 151, 2, 26, 18, 13, 1, 38, 8, 25, 11,
46, 3, 48, 1, 2, 4, 2, 2, 39, 1, 67, 6, 2, 2, 2, 2, 12, 1, 8, 1, 47, 1, 51, 1, 1, 3, 2, 2,
5, 2, 1, 1, 42, 2, 8, 1, 238, 1, 2, 1, 4, 1, 0, 1, 0, 16, 16, 16, 0, 2, 0, 1, 226, 1, 149,
- 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 153, 11, 49, 4, 123, 1, 54, 15, 41, 1,
- 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1, 95, 3,
- 2, 1, 1, 2, 6, 1, 160, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5, 195, 8, 2, 3,
- 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2, 27, 2, 85, 8, 2,
- 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1, 10, 2, 1, 1, 4,
- 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2, 0, 7, 1, 6, 1,
- 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1, 1, 0, 2, 0, 5,
- 59, 7, 0, 1, 63, 4, 81, 1, 0, 2, 0, 46, 2, 23, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3,
- 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1, 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 0, 7, 0, 1, 61, 4,
- 0, 7, 109, 7, 0, 96, 128, 240, 0,
+ 5, 0, 3, 1, 2, 5, 4, 40, 3, 4, 1, 165, 2, 0, 4, 0, 2, 80, 3, 70, 11, 49, 4, 123, 1, 54, 15,
+ 41, 1, 2, 2, 10, 3, 49, 4, 2, 2, 7, 1, 61, 3, 36, 5, 1, 8, 62, 1, 12, 2, 52, 9, 10, 4, 2, 1,
+ 95, 3, 2, 1, 1, 2, 6, 1, 2, 1, 157, 1, 3, 8, 21, 2, 57, 2, 1, 1, 1, 1, 22, 1, 14, 7, 3, 5,
+ 195, 8, 2, 3, 1, 1, 23, 1, 81, 1, 2, 6, 1, 1, 2, 1, 1, 2, 1, 2, 235, 1, 2, 4, 6, 2, 1, 2,
+ 27, 2, 85, 8, 2, 1, 1, 2, 106, 1, 1, 1, 2, 6, 1, 1, 101, 3, 2, 4, 1, 5, 0, 9, 1, 2, 245, 1,
+ 10, 2, 1, 1, 4, 1, 144, 4, 2, 2, 4, 1, 32, 10, 40, 6, 2, 4, 8, 1, 9, 6, 2, 3, 46, 13, 1, 2,
+ 0, 7, 1, 6, 1, 1, 82, 22, 2, 7, 1, 2, 1, 2, 122, 6, 3, 1, 1, 2, 1, 7, 1, 1, 72, 2, 3, 1, 1,
+ 1, 0, 2, 11, 2, 52, 5, 5, 1, 1, 1, 0, 1, 6, 15, 0, 5, 59, 7, 0, 1, 63, 4, 81, 1, 0, 2, 0,
+ 46, 2, 23, 0, 1, 1, 3, 4, 5, 8, 8, 2, 7, 30, 4, 148, 3, 0, 55, 4, 50, 8, 1, 14, 1, 22, 5, 1,
+ 15, 0, 7, 1, 17, 2, 7, 1, 2, 1, 5, 100, 1, 160, 7, 0, 1, 61, 4, 0, 4, 0, 7, 109, 7, 0, 96,
+ 128, 240, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
@@ -327,50 +330,52 @@ pub mod lowercase {
14, 17, 0, 0, 9, 0, 0, 12, 13, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 4, 1, 0, 15, 0, 8, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0,
- 3, 0, 0, 7,
+ 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0,
+ 3, 18, 0, 7,
];
- const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 19] = &[
+ const BITSET_INDEX_CHUNKS: &'static [[u8; 16]; 20] = &[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 14, 55, 0],
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0],
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 0, 0],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0],
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 42, 0, 50, 46, 48, 32],
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 43, 0, 51, 47, 49, 33],
[0, 0, 0, 0, 10, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [0, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26],
+ [0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27],
[0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [0, 0, 0, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [0, 0, 57, 0, 55, 55, 55, 0, 21, 21, 67, 21, 35, 24, 23, 36],
- [0, 5, 74, 0, 28, 15, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [0, 64, 33, 17, 22, 51, 52, 47, 45, 8, 34, 40, 0, 27, 13, 30],
- [11, 58, 0, 4, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 31, 0],
- [16, 25, 21, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [16, 49, 2, 20, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0],
- [63, 39, 54, 12, 73, 61, 18, 1, 6, 62, 71, 19, 68, 69, 3, 44],
+ [0, 0, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 0, 57, 0, 55, 55, 55, 0, 22, 22, 67, 22, 36, 25, 24, 37],
+ [0, 5, 68, 0, 29, 15, 73, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [0, 64, 34, 17, 23, 52, 53, 48, 46, 8, 35, 42, 0, 28, 13, 31],
+ [11, 58, 0, 6, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 32, 0],
+ [16, 26, 22, 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [16, 50, 2, 21, 66, 9, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [16, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [63, 41, 54, 12, 75, 61, 18, 1, 7, 62, 74, 20, 71, 72, 4, 45],
];
const BITSET_CANONICAL: &'static [u64; 55] = &[
0b0000000000000000000000000000000000000000000000000000000000000000,
0b1111111111111111110000000000000000000000000011111111111111111111,
0b1010101010101010101010101010101010101010101010101010100000000010,
+ 0b0000000000000111111111111111111111111111111111111111111111111111,
0b1111111111111111111111000000000000000000000000001111110111111111,
- 0b0000111111111111111111111111111111111111000000000000000000000000,
0b1000000000000010000000000000000000000000000000000000000000000000,
+ 0b0000111111111111111111111111111111111111000000000000000000000000,
0b0000111111111111111111111111110000000000000000000000000011111111,
- 0b0000000000000111111111111111111111111111111111111111111111111111,
0b1111111111111111111111111111111111111111111111111010101010000101,
0b1111111111111111111111111111111100000000000000000000000000000000,
0b1111111111111111111111111111110000000000000000000000000000000000,
0b1111111111111111111111110000000000000000000000000000000000000000,
0b1111111111111111111111000000000000000000000000001111111111101111,
0b1111111111111111111100000000000000000000000000010000000000000000,
- 0b1111111111111111000000011111111111110111111111111111111111111111,
+ 0b1111111111111111000000111111111111110111111111111111111111111111,
0b1111111111111111000000000000000000000000000000000100001111000000,
0b1111111111111111000000000000000000000000000000000000000000000000,
0b1111111101111111111111111111111110000000000000000000000000000000,
0b1111110000000000000000000000000011111111111111111111111111000000,
+ 0b1111011111111111111111111111111111111111111111110000000000000000,
0b1111000000000000000000000000001111110111111111111111111111111100,
0b1010101010101010101010101010101010101010101010101101010101010100,
0b1010101010101010101010101010101010101010101010101010101010101010,
@@ -384,16 +389,16 @@ pub mod lowercase {
0b0001101111111011111111111111101111111111100000000000000000000000,
0b0001100100101111101010101010101010101010111000110111111111111111,
0b0000011111111101111111111111111111111111111111111111111110111001,
- 0b0000011101000000000000000000000000000010101010100000010100001010,
+ 0b0000011101011100000000000000000000000010101010100000010100001010,
0b0000010000100000000001000000000000000000000000000000000000000000,
0b0000000111111111111111111111111111111111111011111111111111111111,
0b0000000011111111000000001111111100000000001111110000000011111111,
0b0000000011011100000000001111111100000000110011110000000011011100,
0b0000000000001000010100000001101010101010101010101010101010101010,
0b0000000000000000001000001011111111111111111111111111111111111111,
+ 0b0000000000000000000001111110000001111111111111111111101111111111,
0b0000000000000000000000001111111111111111110111111100000000000000,
0b0000000000000000000000000001111100000000000000000000000000000011,
- 0b0000000000000000000000000000000001111111111111111111101111111111,
0b0000000000000000000000000000000000111010101010101010101010101010,
0b0000000000000000000000000000000000000000111110000000000001111111,
0b0000000000000000000000000000000000000000000000000000101111110111,
@@ -405,13 +410,12 @@ pub mod lowercase {
0b1010101010101011101010101010100000000000000000000000000000000000,
0b1101010010101010101010101010101010101010101010101010101101010101,
0b1110011001010001001011010010101001001110001001000011000100101001,
- 0b1110011111111111111111111111111111111111111111110000000000000000,
0b1110101111000000000000000000000000001111111111111111111111111100,
];
- const BITSET_MAPPING: &'static [(u8, u8); 20] = &[
+ const BITSET_MAPPING: &'static [(u8, u8); 21] = &[
(0, 64), (1, 188), (1, 183), (1, 176), (1, 109), (1, 124), (1, 126), (1, 66), (1, 70),
- (1, 77), (2, 146), (2, 144), (2, 83), (3, 12), (3, 6), (4, 156), (4, 78), (5, 187),
- (6, 132), (7, 93),
+ (1, 77), (2, 146), (2, 144), (2, 83), (3, 93), (3, 147), (3, 133), (4, 12), (4, 6),
+ (5, 187), (6, 78), (7, 132),
];
#[rustc_const_unstable(feature = "const_unicode_case_lookup", issue = "101400")]
@@ -428,14 +432,14 @@ pub mod lowercase {
#[rustfmt::skip]
pub mod n {
- static SHORT_OFFSET_RUNS: [u32; 38] = [
+ static SHORT_OFFSET_RUNS: [u32; 39] = [
1632, 18876774, 31461440, 102765417, 111154926, 115349830, 132128880, 165684320, 186656630,
195046653, 199241735, 203436434, 216049184, 241215536, 249605104, 274792208, 278987015,
283181793, 295766104, 320933114, 383848032, 392238160, 434181712, 442570976, 455154768,
- 463544256, 476128256, 480340576, 484535936, 501338848, 505534414, 513925440, 518120176,
- 522315975, 526511217, 534900992, 555875312, 561183738,
+ 463544144, 476128256, 484534880, 488730240, 505533120, 509728718, 522314048, 526508784,
+ 530703600, 534898887, 539094129, 547483904, 568458224, 573766650,
];
- static OFFSETS: [u8; 269] = [
+ static OFFSETS: [u8; 275] = [
48, 10, 120, 2, 5, 1, 2, 3, 0, 10, 134, 10, 198, 10, 0, 10, 118, 10, 4, 6, 108, 10, 118,
10, 118, 10, 2, 6, 110, 13, 115, 10, 8, 7, 103, 10, 104, 7, 7, 19, 109, 10, 96, 10, 118, 10,
70, 20, 0, 10, 70, 10, 0, 20, 0, 3, 239, 10, 6, 10, 22, 10, 0, 10, 128, 11, 165, 10, 6, 10,
@@ -445,9 +449,9 @@ pub mod n {
29, 1, 8, 1, 134, 5, 202, 10, 0, 8, 25, 7, 39, 9, 75, 5, 22, 6, 160, 2, 2, 16, 2, 46, 64, 9,
52, 2, 30, 3, 75, 5, 104, 8, 24, 8, 41, 7, 0, 6, 48, 10, 0, 31, 158, 10, 42, 4, 112, 7, 134,
30, 128, 10, 60, 10, 144, 10, 7, 20, 251, 10, 0, 10, 118, 10, 0, 10, 102, 10, 102, 12, 0,
- 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 21, 0, 111, 0, 10, 86, 10, 134, 10, 1, 7, 0, 23, 0,
- 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4, 76, 45, 1, 15, 0, 13, 0,
- 10, 0,
+ 19, 93, 10, 0, 29, 227, 10, 70, 10, 0, 10, 102, 21, 0, 111, 0, 10, 86, 10, 134, 10, 1, 7, 0,
+ 23, 0, 20, 12, 20, 108, 25, 0, 50, 0, 10, 0, 10, 0, 10, 0, 9, 128, 10, 0, 59, 1, 3, 1, 4,
+ 76, 45, 1, 15, 0, 13, 0, 10, 0,
];
pub fn lookup(c: char) -> bool {
super::skip_search(
diff --git a/library/core/tests/ascii.rs b/library/core/tests/ascii.rs
index 6d2cf3e83..f5f2dd047 100644
--- a/library/core/tests/ascii.rs
+++ b/library/core/tests/ascii.rs
@@ -252,6 +252,23 @@ fn test_is_ascii_digit() {
}
#[test]
+fn test_is_ascii_octdigit() {
+ assert_all!(is_ascii_octdigit, "", "01234567");
+ assert_none!(
+ is_ascii_octdigit,
+ "abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOQPRSTUVWXYZ",
+ "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ " \t\n\x0c\r",
+ "\x00\x01\x02\x03\x04\x05\x06\x07",
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
+ "\x10\x11\x12\x13\x14\x15\x16\x17",
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
+ "\x7f",
+ );
+}
+
+#[test]
fn test_is_ascii_hexdigit() {
assert_all!(is_ascii_hexdigit, "", "0123456789", "abcdefABCDEF",);
assert_none!(
@@ -454,6 +471,7 @@ fn ascii_ctype_const() {
is_ascii_lowercase => [true, false, false, false, false];
is_ascii_alphanumeric => [true, true, true, false, false];
is_ascii_digit => [false, false, true, false, false];
+ is_ascii_octdigit => [false, false, false, false, false];
is_ascii_hexdigit => [true, true, true, false, false];
is_ascii_punctuation => [false, false, false, true, false];
is_ascii_graphic => [true, true, true, true, false];
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 4a0e162bc..51f858ade 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -2,12 +2,12 @@
#![feature(array_chunks)]
#![feature(array_methods)]
#![feature(array_windows)]
-#![feature(bench_black_box)]
#![feature(bigint_helper_methods)]
#![feature(cell_update)]
#![feature(const_assume)]
#![feature(const_black_box)]
#![feature(const_bool_to_option)]
+#![feature(const_caller_location)]
#![feature(const_cell_into_inner)]
#![feature(const_convert)]
#![feature(const_heap)]
@@ -21,6 +21,7 @@
#![feature(const_ptr_write)]
#![feature(const_trait_impl)]
#![feature(const_likely)]
+#![feature(const_location_fields)]
#![feature(core_intrinsics)]
#![feature(core_private_bignum)]
#![feature(core_private_diy_float)]
@@ -48,8 +49,8 @@
#![feature(slice_from_ptr_range)]
#![feature(split_as_slice)]
#![feature(maybe_uninit_uninit_array)]
-#![feature(maybe_uninit_array_assume_init)]
#![feature(maybe_uninit_write_slice)]
+#![feature(maybe_uninit_uninit_array_transpose)]
#![feature(min_specialization)]
#![feature(numfmt)]
#![feature(step_trait)]
@@ -74,6 +75,7 @@
#![feature(iterator_try_reduce)]
#![feature(const_mut_refs)]
#![feature(const_pin)]
+#![feature(const_waker)]
#![feature(never_type)]
#![feature(unwrap_infallible)]
#![feature(pointer_byte_offsets)]
@@ -93,13 +95,13 @@
#![feature(strict_provenance_atomic_ptr)]
#![feature(trusted_random_access)]
#![feature(unsize)]
-#![feature(unzip_option)]
#![feature(const_array_from_ref)]
#![feature(const_slice_from_ref)]
#![feature(waker_getters)]
#![feature(slice_flatten)]
#![feature(provide_any)]
#![feature(utf8_chunks)]
+#![feature(is_ascii_octdigit)]
#![deny(unsafe_op_in_unsafe_fn)]
extern crate test;
@@ -130,6 +132,7 @@ mod nonzero;
mod num;
mod ops;
mod option;
+mod panic;
mod pattern;
mod pin;
mod pin_macro;
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 6856d1a1f..0362e1c8a 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -130,7 +130,11 @@ fn test_transmute_copy_grow_panics() {
payload
.downcast::<&'static str>()
.and_then(|s| {
- if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) }
+ if *s == "cannot transmute_copy if Dst is larger than Src" {
+ Ok(s)
+ } else {
+ Err(s)
+ }
})
.unwrap_or_else(|p| panic::resume_unwind(p));
}
@@ -163,18 +167,18 @@ fn assume_init_good() {
#[test]
fn uninit_array_assume_init() {
- let mut array: [MaybeUninit<i16>; 5] = MaybeUninit::uninit_array();
+ let mut array = [MaybeUninit::<i16>::uninit(); 5];
array[0].write(3);
array[1].write(1);
array[2].write(4);
array[3].write(1);
array[4].write(5);
- let array = unsafe { MaybeUninit::array_assume_init(array) };
+ let array = unsafe { array.transpose().assume_init() };
assert_eq!(array, [3, 1, 4, 1, 5]);
- let [] = unsafe { MaybeUninit::<!>::array_assume_init([]) };
+ let [] = unsafe { [MaybeUninit::<!>::uninit(); 0].transpose().assume_init() };
}
#[test]
diff --git a/library/core/tests/num/int_log.rs b/library/core/tests/num/int_log.rs
index be203fb5c..a1edb1a51 100644
--- a/library/core/tests/num/int_log.rs
+++ b/library/core/tests/num/int_log.rs
@@ -164,3 +164,33 @@ fn ilog10_u64() {
fn ilog10_u128() {
ilog10_loop! { u128, 38 }
}
+
+#[test]
+#[should_panic(expected = "argument of integer logarithm must be positive")]
+fn ilog2_of_0_panic() {
+ let _ = 0u32.ilog2();
+}
+
+#[test]
+#[should_panic(expected = "argument of integer logarithm must be positive")]
+fn ilog10_of_0_panic() {
+ let _ = 0u32.ilog10();
+}
+
+#[test]
+#[should_panic(expected = "argument of integer logarithm must be positive")]
+fn ilog3_of_0_panic() {
+ let _ = 0u32.ilog(3);
+}
+
+#[test]
+#[should_panic(expected = "base of integer logarithm must be at least 2")]
+fn ilog0_of_1_panic() {
+ let _ = 1u32.ilog(0);
+}
+
+#[test]
+#[should_panic(expected = "base of integer logarithm must be at least 2")]
+fn ilog1_of_1_panic() {
+ let _ = 1u32.ilog(1);
+}
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 49580cdcc..c79e909e4 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -172,7 +172,7 @@ fn test_can_not_overflow() {
// Calcutate the string length for the smallest overflowing number:
let max_len_string = format_radix(num, base as u128);
- // Ensure that that string length is deemed to potentially overflow:
+ // Ensure that string length is deemed to potentially overflow:
assert!(can_overflow::<$t>(base, &max_len_string));
}
)*)
diff --git a/library/core/tests/num/wrapping.rs b/library/core/tests/num/wrapping.rs
index 8ded139a1..c5a719883 100644
--- a/library/core/tests/num/wrapping.rs
+++ b/library/core/tests/num/wrapping.rs
@@ -75,8 +75,6 @@ wrapping_test!(test_wrapping_u64, u64, u64::MIN, u64::MAX);
wrapping_test!(test_wrapping_u128, u128, u128::MIN, u128::MAX);
wrapping_test!(test_wrapping_usize, usize, usize::MIN, usize::MAX);
-// Don't warn about overflowing ops on 32-bit platforms
-#[cfg_attr(target_pointer_width = "32", allow(const_err))]
#[test]
fn wrapping_int_api() {
assert_eq!(i8::MAX.wrapping_add(1), i8::MIN);
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index 9f5e537dc..f36f7c268 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -57,6 +57,7 @@ fn test_get_resource() {
}
#[test]
+#[cfg_attr(not(bootstrap), allow(for_loops_over_fallibles))]
fn test_option_dance() {
let x = Some(());
let mut y = Some(5);
diff --git a/library/core/tests/panic.rs b/library/core/tests/panic.rs
new file mode 100644
index 000000000..24b6c56b3
--- /dev/null
+++ b/library/core/tests/panic.rs
@@ -0,0 +1 @@
+mod location;
diff --git a/library/core/tests/panic/location.rs b/library/core/tests/panic/location.rs
new file mode 100644
index 000000000..d20241d83
--- /dev/null
+++ b/library/core/tests/panic/location.rs
@@ -0,0 +1,31 @@
+use core::panic::Location;
+
+// Note: Some of the following tests depend on the source location,
+// so please be careful when editing this file.
+
+#[test]
+fn location_const_caller() {
+ const _CALLER_REFERENCE: &Location<'static> = Location::caller();
+ const _CALLER: Location<'static> = *Location::caller();
+}
+
+#[test]
+fn location_const_file() {
+ const CALLER: &Location<'static> = Location::caller();
+ const FILE: &str = CALLER.file();
+ assert_eq!(FILE, file!());
+}
+
+#[test]
+fn location_const_line() {
+ const CALLER: &Location<'static> = Location::caller();
+ const LINE: u32 = CALLER.line();
+ assert_eq!(LINE, 21);
+}
+
+#[test]
+fn location_const_column() {
+ const CALLER: &Location<'static> = Location::caller();
+ const COLUMN: u32 = CALLER.column();
+ assert_eq!(COLUMN, 40);
+}
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index b8f6fe696..9e1fbea79 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -1284,7 +1284,6 @@ fn test_windows_zip() {
}
#[test]
-#[allow(const_err)]
fn test_iter_ref_consistency() {
use std::fmt::Debug;
diff --git a/library/core/tests/task.rs b/library/core/tests/task.rs
index d71fef9e5..56be30e92 100644
--- a/library/core/tests/task.rs
+++ b/library/core/tests/task.rs
@@ -1,4 +1,4 @@
-use core::task::Poll;
+use core::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
#[test]
fn poll_const() {
@@ -12,3 +12,18 @@ fn poll_const() {
const IS_PENDING: bool = POLL.is_pending();
assert!(IS_PENDING);
}
+
+#[test]
+fn waker_const() {
+ const VOID_TABLE: RawWakerVTable = RawWakerVTable::new(|_| VOID_WAKER, |_| {}, |_| {}, |_| {});
+
+ const VOID_WAKER: RawWaker = RawWaker::new(&(), &VOID_TABLE);
+
+ static WAKER: Waker = unsafe { Waker::from_raw(VOID_WAKER) };
+
+ static CONTEXT: Context<'static> = Context::from_waker(&WAKER);
+
+ static WAKER_REF: &'static Waker = CONTEXT.waker();
+
+ WAKER_REF.wake_by_ref();
+}
diff --git a/library/core/tests/time.rs b/library/core/tests/time.rs
index fe2d2f241..a05128de4 100644
--- a/library/core/tests/time.rs
+++ b/library/core/tests/time.rs
@@ -197,9 +197,31 @@ fn correct_sum() {
#[test]
fn debug_formatting_extreme_values() {
assert_eq!(
- format!("{:?}", Duration::new(18_446_744_073_709_551_615, 123_456_789)),
+ format!("{:?}", Duration::new(u64::MAX, 123_456_789)),
"18446744073709551615.123456789s"
);
+ assert_eq!(format!("{:.0?}", Duration::MAX), "18446744073709551616s");
+ assert_eq!(format!("{:.0?}", Duration::new(u64::MAX, 500_000_000)), "18446744073709551616s");
+ assert_eq!(format!("{:.0?}", Duration::new(u64::MAX, 499_999_999)), "18446744073709551615s");
+ assert_eq!(
+ format!("{:.3?}", Duration::new(u64::MAX, 999_500_000)),
+ "18446744073709551616.000s"
+ );
+ assert_eq!(
+ format!("{:.3?}", Duration::new(u64::MAX, 999_499_999)),
+ "18446744073709551615.999s"
+ );
+ assert_eq!(
+ format!("{:.8?}", Duration::new(u64::MAX, 999_999_995)),
+ "18446744073709551616.00000000s"
+ );
+ assert_eq!(
+ format!("{:.8?}", Duration::new(u64::MAX, 999_999_994)),
+ "18446744073709551615.99999999s"
+ );
+ assert_eq!(format!("{:21.0?}", Duration::MAX), "18446744073709551616s");
+ assert_eq!(format!("{:22.0?}", Duration::MAX), "18446744073709551616s ");
+ assert_eq!(format!("{:24.0?}", Duration::MAX), "18446744073709551616s ");
}
#[test]
@@ -445,3 +467,11 @@ fn duration_const() {
const SATURATING_MUL: Duration = MAX.saturating_mul(2);
assert_eq!(SATURATING_MUL, MAX);
}
+
+#[test]
+fn from_neg_zero() {
+ assert_eq!(Duration::try_from_secs_f32(-0.0), Ok(Duration::ZERO));
+ assert_eq!(Duration::try_from_secs_f64(-0.0), Ok(Duration::ZERO));
+ assert_eq!(Duration::from_secs_f32(-0.0), Duration::ZERO);
+ assert_eq!(Duration::from_secs_f64(-0.0), Duration::ZERO);
+}
diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs
index 7c233c7c3..c6d423085 100644
--- a/library/panic_unwind/src/emcc.rs
+++ b/library/panic_unwind/src/emcc.rs
@@ -47,7 +47,12 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo {
name: b"rust_panic\0".as_ptr(),
};
+// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization.
+#[repr(C)]
struct Exception {
+ // See `gcc.rs` on why this is present. We already have a static here so just use it.
+ canary: *const TypeInfo,
+
// This is necessary because C++ code can capture our exception with
// std::exception_ptr and rethrow it multiple times, possibly even in
// another thread.
@@ -70,27 +75,38 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
let catch_data = &*(ptr as *mut CatchData);
let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception;
- let out = if catch_data.is_rust_panic {
- let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst);
- if was_caught {
- // Since cleanup() isn't allowed to panic, we just abort instead.
- intrinsics::abort();
- }
- (*adjusted_ptr).data.take().unwrap()
- } else {
+ if !catch_data.is_rust_panic {
super::__rust_foreign_exception();
- };
+ }
+
+ let canary = ptr::addr_of!((*adjusted_ptr).canary).read();
+ if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) {
+ super::__rust_foreign_exception();
+ }
+
+ let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst);
+ if was_caught {
+ // Since cleanup() isn't allowed to panic, we just abort instead.
+ intrinsics::abort();
+ }
+ let out = (*adjusted_ptr).data.take().unwrap();
__cxa_end_catch();
out
}
pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
- let sz = mem::size_of_val(&data);
- let exception = __cxa_allocate_exception(sz) as *mut Exception;
+ let exception = __cxa_allocate_exception(mem::size_of::<Exception>()) as *mut Exception;
if exception.is_null() {
return uw::_URC_FATAL_PHASE1_ERROR as u32;
}
- ptr::write(exception, Exception { caught: AtomicBool::new(false), data: Some(data) });
+ ptr::write(
+ exception,
+ Exception {
+ canary: &EXCEPTION_TYPE_INFO,
+ caught: AtomicBool::new(false),
+ data: Some(data),
+ },
+ );
__cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup);
}
diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 261404e87..0b7a873a6 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -38,12 +38,23 @@
use alloc::boxed::Box;
use core::any::Any;
+use core::ptr;
use unwind as uw;
+// In case where multiple copies of std exist in a single process,
+// we use address of this static variable to distinguish an exception raised by
+// this copy and some other copy (which needs to be treated as foreign exception).
+static CANARY: u8 = 0;
+
+// NOTE(nbdd0121)
+// Once `c_unwind` feature is stabilized, there will be ABI stability requirement
+// on this struct. The first two field must be `_Unwind_Exception` and `canary`,
+// as it may be accessed by a different version of the std with a different compiler.
#[repr(C)]
struct Exception {
_uwe: uw::_Unwind_Exception,
+ canary: *const u8,
cause: Box<dyn Any + Send>,
}
@@ -54,6 +65,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
exception_cleanup,
private: [0; uw::unwinder_private_data_size],
},
+ canary: &CANARY,
cause: data,
});
let exception_param = Box::into_raw(exception) as *mut uw::_Unwind_Exception;
@@ -75,10 +87,22 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<dyn Any + Send> {
if (*exception).exception_class != rust_exception_class() {
uw::_Unwind_DeleteException(exception);
super::__rust_foreign_exception();
- } else {
- let exception = Box::from_raw(exception as *mut Exception);
- exception.cause
}
+
+ let exception = exception.cast::<Exception>();
+ // Just access the canary field, avoid accessing the entire `Exception` as
+ // it can be a foreign Rust exception.
+ let canary = ptr::addr_of!((*exception).canary).read();
+ if !ptr::eq(canary, &CANARY) {
+ // A foreign Rust exception, treat it slightly differently from other
+ // foreign exceptions, because call into `_Unwind_DeleteException` will
+ // call into `__rust_drop_panic` which produces a confusing
+ // "Rust panic must be rethrown" message.
+ super::__rust_foreign_exception();
+ }
+
+ let exception = Box::from_raw(exception as *mut Exception);
+ exception.cause
}
// Rust's exception class identifier. This is used by personality routines to
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 1eb4f3789..7e7180a38 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -42,7 +42,8 @@ cfg_if::cfg_if! {
// L4Re is unix family but does not yet support unwinding.
#[path = "dummy.rs"]
mod real_imp;
- } else if #[cfg(target_env = "msvc")] {
+ } else if #[cfg(all(target_env = "msvc", not(target_arch = "arm")))] {
+ // LLVM does not support unwinding on 32 bit ARM msvc (thumbv7a-pc-windows-msvc)
#[path = "seh.rs"]
mod real_imp;
} else if #[cfg(any(
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 6b8d06568..651115a82 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -49,9 +49,15 @@
use alloc::boxed::Box;
use core::any::Any;
use core::mem::{self, ManuallyDrop};
+use core::ptr;
use libc::{c_int, c_uint, c_void};
+// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization.
+#[repr(C)]
struct Exception {
+ // See `gcc.rs` on why this is present. We already have a static here so just use it.
+ canary: *const _TypeDescriptor,
+
// This needs to be an Option because we catch the exception by reference
// and its destructor is executed by the C++ runtime. When we take the Box
// out of the exception, we need to leave the exception in a valid state
@@ -235,7 +241,7 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor {
macro_rules! define_cleanup {
($abi:tt $abi2:tt) => {
unsafe extern $abi fn exception_cleanup(e: *mut Exception) {
- if let Exception { data: Some(b) } = e.read() {
+ if let Exception { data: Some(b), .. } = e.read() {
drop(b);
super::__rust_drop_panic();
}
@@ -265,7 +271,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
// The ManuallyDrop is needed here since we don't want Exception to be
// dropped when unwinding. Instead it will be dropped by exception_cleanup
// which is invoked by the C++ runtime.
- let mut exception = ManuallyDrop::new(Exception { data: Some(data) });
+ let mut exception = ManuallyDrop::new(Exception { canary: &TYPE_DESCRIPTOR, data: Some(data) });
let throw_ptr = &mut exception as *mut _ as *mut _;
// This... may seems surprising, and justifiably so. On 32-bit MSVC the
@@ -321,8 +327,12 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
// __rust_try. This happens when a non-Rust foreign exception is caught.
if payload.is_null() {
super::__rust_foreign_exception();
- } else {
- let exception = &mut *(payload as *mut Exception);
- exception.data.take().unwrap()
}
+ let exception = payload as *mut Exception;
+ let canary = ptr::addr_of!((*exception).canary).read();
+ if !ptr::eq(canary, &TYPE_DESCRIPTOR) {
+ // A foreign Rust exception.
+ super::__rust_foreign_exception();
+ }
+ (*exception).data.take().unwrap()
}
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 4461b2180..506b2a773 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -223,10 +223,10 @@ pub(crate) use super::symbol::Symbol;
macro_rules! define_client_side {
($($name:ident {
- $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)*;)*
+ $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
}),* $(,)?) => {
$(impl $name {
- $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)* {
+ $(pub(crate) fn $method($($arg: $arg_ty),*) $(-> $ret_ty)? {
Bridge::with(|bridge| {
let mut buf = bridge.cached_buffer.take();
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 495c1c5ae..0d3fc2c52 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -533,7 +533,7 @@ impl Span {
other.resolved_at(*self)
}
- /// Compares to spans to see if they're equal.
+ /// Compares two spans to see if they're equal.
#[unstable(feature = "proc_macro_span", issue = "54725")]
pub fn eq(&self, other: &Span) -> bool {
self.0 == other.0
@@ -546,7 +546,7 @@ impl Span {
/// 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.
- #[unstable(feature = "proc_macro_span", issue = "54725")]
+ #[stable(feature = "proc_macro_source_text", since = "1.66.0")]
pub fn source_text(&self) -> Option<String> {
self.0.source_text()
}
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 324ecc804..bc10b12ec 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -11,11 +11,11 @@ crate-type = ["dylib", "rlib"]
[dependencies]
alloc = { path = "../alloc" }
-cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
+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.126", default-features = false, features = ['rustc-dep-of-std'] }
+libc = { version = "0.2.135", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.73" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 5cf6ec817..9cb74f951 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -14,8 +14,8 @@
//! Backtraces are attempted to be as accurate as possible, but no guarantees
//! are provided about the exact accuracy of a backtrace. Instruction pointers,
//! symbol names, filenames, line numbers, etc, may all be incorrect when
-//! reported. Accuracy is attempted on a best-effort basis, however, and bugs
-//! are always welcome to indicate areas of improvement!
+//! reported. Accuracy is attempted on a best-effort basis, however, any bug
+//! reports are always welcome to indicate areas of improvement!
//!
//! For most platforms a backtrace with a filename/line number requires that
//! programs be compiled with debug information. Without debug information
@@ -39,7 +39,7 @@
//! default. Its behavior is governed by two environment variables:
//!
//! * `RUST_LIB_BACKTRACE` - if this is set to `0` then `Backtrace::capture`
-//! will never capture a backtrace. Any other value this is set to will enable
+//! will never capture a backtrace. Any other value set will enable
//! `Backtrace::capture`.
//!
//! * `RUST_BACKTRACE` - if `RUST_LIB_BACKTRACE` is not set, then this variable
@@ -325,8 +325,7 @@ impl Backtrace {
// Capture a backtrace which start just before the function addressed by
// `ip`
fn create(ip: usize) -> Backtrace {
- // SAFETY: We don't attempt to lock this reentrantly.
- let _lock = unsafe { lock() };
+ let _lock = lock();
let mut frames = Vec::new();
let mut actual_start = None;
unsafe {
@@ -469,8 +468,7 @@ impl Capture {
// Use the global backtrace lock to synchronize this as it's a
// requirement of the `backtrace` crate, and then actually resolve
// everything.
- // SAFETY: We don't attempt to lock this reentrantly.
- let _lock = unsafe { lock() };
+ let _lock = lock();
for frame in self.frames.iter_mut() {
let symbols = &mut frame.symbols;
let frame = match &frame.frame {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 9845d1faf..708edc5de 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -9,7 +9,6 @@ use crate::borrow::Borrow;
use crate::cell::Cell;
use crate::collections::TryReserveError;
use crate::collections::TryReserveErrorKind;
-#[cfg(not(bootstrap))]
use crate::error::Error;
use crate::fmt::{self, Debug};
#[allow(deprecated)]
@@ -281,7 +280,8 @@ impl<K, V, S> HashMap<K, V, S> {
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
- pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
+ #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+ pub const fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
HashMap { base: base::HashMap::with_hasher(hash_builder) }
}
@@ -759,7 +759,7 @@ where
/// Tries to reserve capacity for at least `additional` more elements to be inserted
/// in the `HashMap`. The collection may reserve more space to speculatively
- /// avoid frequent reallocations. After calling `reserve`,
+ /// avoid frequent reallocations. After calling `try_reserve`,
/// capacity will be greater than or equal to `self.len() + additional` if
/// it returns `Ok(())`.
/// Does nothing if capacity is already sufficient.
@@ -2160,7 +2160,6 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> {
}
}
-#[cfg(not(bootstrap))]
#[unstable(feature = "map_try_insert", issue = "82766")]
impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> {
#[allow(deprecated)]
diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index cb3032719..65634f206 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -1115,3 +1115,9 @@ fn from_array() {
// that's a problem!
let _must_not_require_type_annotation = HashMap::from([(1, 2)]);
}
+
+#[test]
+fn const_with_hasher() {
+ const X: HashMap<(), (), ()> = HashMap::with_hasher(());
+ assert_eq!(X.len(), 0);
+}
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 5b6a415fa..cee884145 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -376,7 +376,8 @@ impl<T, S> HashSet<T, S> {
/// ```
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
- pub fn with_hasher(hasher: S) -> HashSet<T, S> {
+ #[rustc_const_unstable(feature = "const_collections_with_hasher", issue = "102575")]
+ pub const fn with_hasher(hasher: S) -> HashSet<T, S> {
HashSet { base: base::HashSet::with_hasher(hasher) }
}
@@ -461,7 +462,7 @@ where
/// Tries to reserve capacity for at least `additional` more elements to be inserted
/// in the `HashSet`. The collection may reserve more space to speculatively
- /// avoid frequent reallocations. After calling `reserve`,
+ /// avoid frequent reallocations. After calling `try_reserve`,
/// capacity will be greater than or equal to `self.len() + additional` if
/// it returns `Ok(())`.
/// Does nothing if capacity is already sufficient.
diff --git a/library/std/src/collections/hash/set/tests.rs b/library/std/src/collections/hash/set/tests.rs
index 233db276b..941a0450c 100644
--- a/library/std/src/collections/hash/set/tests.rs
+++ b/library/std/src/collections/hash/set/tests.rs
@@ -496,3 +496,9 @@ fn from_array() {
// that's a problem!
let _must_not_require_type_annotation = HashSet::from([1, 2]);
}
+
+#[test]
+fn const_with_hasher() {
+ const X: HashSet<(), ()> = HashSet::with_hasher(());
+ assert_eq!(X.len(), 0);
+}
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 463f71406..6eb7cbea6 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -603,7 +603,7 @@ pub fn home_dir() -> Option<PathBuf> {
/// # Platform-specific behavior
///
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
-/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
+/// set, otherwise for non-Android it returns `/tmp`. On Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index e45059595..05f8fd8de 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -4,242 +4,12 @@
#[cfg(test)]
mod tests;
-#[cfg(bootstrap)]
-use core::array;
-#[cfg(bootstrap)]
-use core::convert::Infallible;
-
-#[cfg(bootstrap)]
-use crate::alloc::{AllocError, LayoutError};
-#[cfg(bootstrap)]
-use crate::any::Demand;
-#[cfg(bootstrap)]
-use crate::any::{Provider, TypeId};
use crate::backtrace::Backtrace;
-#[cfg(bootstrap)]
-use crate::borrow::Cow;
-#[cfg(bootstrap)]
-use crate::cell;
-#[cfg(bootstrap)]
-use crate::char;
-#[cfg(bootstrap)]
-use crate::fmt::Debug;
-#[cfg(bootstrap)]
-use crate::fmt::Display;
use crate::fmt::{self, Write};
-#[cfg(bootstrap)]
-use crate::io;
-#[cfg(bootstrap)]
-use crate::mem::transmute;
-#[cfg(bootstrap)]
-use crate::num;
-#[cfg(bootstrap)]
-use crate::str;
-#[cfg(bootstrap)]
-use crate::string;
-#[cfg(bootstrap)]
-use crate::sync::Arc;
-#[cfg(bootstrap)]
-use crate::time;
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::error::Error;
-/// `Error` is a trait representing the basic expectations for error values,
-/// i.e., values of type `E` in [`Result<T, E>`].
-///
-/// Errors must describe themselves through the [`Display`] and [`Debug`]
-/// traits. Error messages are typically concise lowercase sentences without
-/// trailing punctuation:
-///
-/// ```
-/// let err = "NaN".parse::<u32>().unwrap_err();
-/// assert_eq!(err.to_string(), "invalid digit found in string");
-/// ```
-///
-/// Errors may provide cause information. [`Error::source()`] is generally
-/// used when errors cross "abstraction boundaries". If one module must report
-/// an error that is caused by an error from a lower-level module, it can allow
-/// accessing that error via [`Error::source()`]. This makes it possible for the
-/// high-level module to provide its own errors while also revealing some of the
-/// implementation for debugging.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Error")]
-#[cfg(bootstrap)]
-pub trait Error: Debug + Display {
- /// The lower-level source of this error, if any.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::fmt;
- ///
- /// #[derive(Debug)]
- /// struct SuperError {
- /// source: SuperErrorSideKick,
- /// }
- ///
- /// impl fmt::Display for SuperError {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "SuperError is here!")
- /// }
- /// }
- ///
- /// impl Error for SuperError {
- /// fn source(&self) -> Option<&(dyn Error + 'static)> {
- /// Some(&self.source)
- /// }
- /// }
- ///
- /// #[derive(Debug)]
- /// struct SuperErrorSideKick;
- ///
- /// impl fmt::Display for SuperErrorSideKick {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "SuperErrorSideKick is here!")
- /// }
- /// }
- ///
- /// impl Error for SuperErrorSideKick {}
- ///
- /// fn get_super_error() -> Result<(), SuperError> {
- /// Err(SuperError { source: SuperErrorSideKick })
- /// }
- ///
- /// fn main() {
- /// match get_super_error() {
- /// Err(e) => {
- /// println!("Error: {e}");
- /// println!("Caused by: {}", e.source().unwrap());
- /// }
- /// _ => println!("No error"),
- /// }
- /// }
- /// ```
- #[stable(feature = "error_source", since = "1.30.0")]
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- None
- }
-
- /// Gets the `TypeId` of `self`.
- #[doc(hidden)]
- #[unstable(
- feature = "error_type_id",
- reason = "this is memory-unsafe to override in user code",
- issue = "60784"
- )]
- fn type_id(&self, _: private::Internal) -> TypeId
- where
- Self: 'static,
- {
- TypeId::of::<Self>()
- }
-
- /// ```
- /// if let Err(e) = "xc".parse::<u32>() {
- /// // Print `e` itself, no need for description().
- /// eprintln!("Error: {e}");
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(since = "1.42.0", note = "use the Display impl or to_string()")]
- fn description(&self) -> &str {
- "description() is deprecated; use Display"
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(
- since = "1.33.0",
- note = "replaced by Error::source, which can support downcasting"
- )]
- #[allow(missing_docs)]
- fn cause(&self) -> Option<&dyn Error> {
- self.source()
- }
-
- /// Provides type based access to context intended for error reports.
- ///
- /// Used in conjunction with [`Demand::provide_value`] and [`Demand::provide_ref`] to extract
- /// references to member variables from `dyn Error` trait objects.
- ///
- /// # Example
- ///
- /// ```rust
- /// #![feature(provide_any)]
- /// #![feature(error_generic_member_access)]
- /// use core::fmt;
- /// use core::any::Demand;
- ///
- /// #[derive(Debug)]
- /// struct MyBacktrace {
- /// // ...
- /// }
- ///
- /// impl MyBacktrace {
- /// fn new() -> MyBacktrace {
- /// // ...
- /// # MyBacktrace {}
- /// }
- /// }
- ///
- /// #[derive(Debug)]
- /// struct SourceError {
- /// // ...
- /// }
- ///
- /// impl fmt::Display for SourceError {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "Example Source Error")
- /// }
- /// }
- ///
- /// impl std::error::Error for SourceError {}
- ///
- /// #[derive(Debug)]
- /// struct Error {
- /// source: SourceError,
- /// backtrace: MyBacktrace,
- /// }
- ///
- /// impl fmt::Display for Error {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "Example Error")
- /// }
- /// }
- ///
- /// impl std::error::Error for Error {
- /// fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- /// demand
- /// .provide_ref::<MyBacktrace>(&self.backtrace)
- /// .provide_ref::<dyn std::error::Error + 'static>(&self.source);
- /// }
- /// }
- ///
- /// fn main() {
- /// let backtrace = MyBacktrace::new();
- /// let source = SourceError {};
- /// let error = Error { source, backtrace };
- /// let dyn_error = &error as &dyn std::error::Error;
- /// let backtrace_ref = dyn_error.request_ref::<MyBacktrace>().unwrap();
- ///
- /// assert!(core::ptr::eq(&error.backtrace, backtrace_ref));
- /// }
- /// ```
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- #[allow(unused_variables)]
- fn provide<'a>(&'a self, demand: &mut Demand<'a>) {}
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "error_generic_member_access", issue = "99301")]
-impl<'b> Provider for dyn Error + 'b {
- fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- self.provide(demand)
- }
-}
-
mod private {
// This is a hack to prevent `type_id` from being overridden by `Error`
// implementations, since that can enable unsound downcasting.
@@ -248,799 +18,6 @@ mod private {
pub struct Internal;
}
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
- /// Converts a type of [`Error`] into a box of dyn [`Error`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::fmt;
- /// use std::mem;
- ///
- /// #[derive(Debug)]
- /// struct AnError;
- ///
- /// impl fmt::Display for AnError {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "An error")
- /// }
- /// }
- ///
- /// impl Error for AnError {}
- ///
- /// let an_error = AnError;
- /// assert!(0 == mem::size_of_val(&an_error));
- /// let a_boxed_error = Box::<dyn Error>::from(an_error);
- /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(err: E) -> Box<dyn Error + 'a> {
- Box::new(err)
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
- /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of
- /// dyn [`Error`] + [`Send`] + [`Sync`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::fmt;
- /// use std::mem;
- ///
- /// #[derive(Debug)]
- /// struct AnError;
- ///
- /// impl fmt::Display for AnError {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "An error")
- /// }
- /// }
- ///
- /// impl Error for AnError {}
- ///
- /// unsafe impl Send for AnError {}
- ///
- /// unsafe impl Sync for AnError {}
- ///
- /// let an_error = AnError;
- /// assert!(0 == mem::size_of_val(&an_error));
- /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(an_error);
- /// assert!(
- /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
- Box::new(err)
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl From<String> for Box<dyn Error + Send + Sync> {
- /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- ///
- /// let a_string_error = "a string error".to_string();
- /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_string_error);
- /// assert!(
- /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- #[inline]
- fn from(err: String) -> Box<dyn Error + Send + Sync> {
- struct StringError(String);
-
- impl Error for StringError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- &self.0
- }
- }
-
- impl Display for StringError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Display::fmt(&self.0, f)
- }
- }
-
- // Purposefully skip printing "StringError(..)"
- impl Debug for StringError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- Debug::fmt(&self.0, f)
- }
- }
-
- Box::new(StringError(err))
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "string_box_error", since = "1.6.0")]
-impl From<String> for Box<dyn Error> {
- /// Converts a [`String`] into a box of dyn [`Error`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- ///
- /// let a_string_error = "a string error".to_string();
- /// let a_boxed_error = Box::<dyn Error>::from(a_string_error);
- /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(str_err: String) -> Box<dyn Error> {
- let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
- let err2: Box<dyn Error> = err1;
- err2
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> From<&str> for Box<dyn Error + Send + Sync + 'a> {
- /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
- ///
- /// [`str`]: prim@str
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- ///
- /// let a_str_error = "a str error";
- /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_str_error);
- /// assert!(
- /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- #[inline]
- fn from(err: &str) -> Box<dyn Error + Send + Sync + 'a> {
- From::from(String::from(err))
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "string_box_error", since = "1.6.0")]
-impl From<&str> for Box<dyn Error> {
- /// Converts a [`str`] into a box of dyn [`Error`].
- ///
- /// [`str`]: prim@str
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- ///
- /// let a_str_error = "a str error";
- /// let a_boxed_error = Box::<dyn Error>::from(a_str_error);
- /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(err: &str) -> Box<dyn Error> {
- From::from(String::from(err))
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
- /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- /// use std::borrow::Cow;
- ///
- /// let a_cow_str_error = Cow::from("a str error");
- /// let a_boxed_error = Box::<dyn Error + Send + Sync>::from(a_cow_str_error);
- /// assert!(
- /// mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
- From::from(String::from(err))
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "cow_box_error", since = "1.22.0")]
-impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
- /// Converts a [`Cow`] into a box of dyn [`Error`].
- ///
- /// # Examples
- ///
- /// ```
- /// use std::error::Error;
- /// use std::mem;
- /// use std::borrow::Cow;
- ///
- /// let a_cow_str_error = Cow::from("a str error");
- /// let a_boxed_error = Box::<dyn Error>::from(a_cow_str_error);
- /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
- /// ```
- fn from(err: Cow<'a, str>) -> Box<dyn Error> {
- From::from(String::from(err))
- }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "never_type", issue = "35121")]
-impl Error for ! {}
-
-#[cfg(bootstrap)]
-#[unstable(
- feature = "allocator_api",
- reason = "the precise API and guarantees it provides may be tweaked.",
- issue = "32838"
-)]
-impl Error for AllocError {}
-
-#[cfg(bootstrap)]
-#[stable(feature = "alloc_layout", since = "1.28.0")]
-impl Error for LayoutError {}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for str::ParseBoolError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "failed to parse bool"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for str::Utf8Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-8: corrupt contents"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for num::ParseIntError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for num::TryFromIntError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for array::TryFromSliceError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for num::ParseFloatError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for string::FromUtf8Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-8"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for string::FromUtf16Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "invalid utf-16"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "str_parse_error2", since = "1.8.0")]
-impl Error for Infallible {
- fn description(&self) -> &str {
- match *self {}
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "decode_utf16", since = "1.9.0")]
-impl Error for char::DecodeUtf16Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "unpaired surrogate found"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "u8_from_char", since = "1.59.0")]
-impl Error for char::TryFromCharError {}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "map_try_insert", issue = "82766")]
-impl<'a, K: Debug + Ord, V: Debug> Error
- for crate::collections::btree_map::OccupiedError<'a, K, V>
-{
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "key already exists"
- }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "map_try_insert", issue = "82766")]
-impl<'a, K: Debug, V: Debug> Error for crate::collections::hash_map::OccupiedError<'a, K, V> {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "key already exists"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "box_error", since = "1.8.0")]
-impl<T: Error> Error for Box<T> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Error::description(&**self)
- }
-
- #[allow(deprecated)]
- fn cause(&self) -> Option<&dyn Error> {
- Error::cause(&**self)
- }
-
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Error::source(&**self)
- }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "thin_box", issue = "92791")]
-impl<T: ?Sized + crate::error::Error> crate::error::Error for crate::boxed::ThinBox<T> {
- fn source(&self) -> Option<&(dyn crate::error::Error + 'static)> {
- use core::ops::Deref;
- self.deref().source()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "error_by_ref", since = "1.51.0")]
-impl<'a, T: Error + ?Sized> Error for &'a T {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Error::description(&**self)
- }
-
- #[allow(deprecated)]
- fn cause(&self) -> Option<&dyn Error> {
- Error::cause(&**self)
- }
-
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Error::source(&**self)
- }
-
- fn provide<'b>(&'b self, demand: &mut Demand<'b>) {
- Error::provide(&**self, demand);
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "arc_error", since = "1.52.0")]
-impl<T: Error + ?Sized> Error for Arc<T> {
- #[allow(deprecated, deprecated_in_future)]
- fn description(&self) -> &str {
- Error::description(&**self)
- }
-
- #[allow(deprecated)]
- fn cause(&self) -> Option<&dyn Error> {
- Error::cause(&**self)
- }
-
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Error::source(&**self)
- }
-
- fn provide<'a>(&'a self, demand: &mut Demand<'a>) {
- Error::provide(&**self, demand);
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "fmt_error", since = "1.11.0")]
-impl Error for fmt::Error {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "an error occurred when formatting an argument"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for cell::BorrowError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "already mutably borrowed"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for cell::BorrowMutError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "already borrowed"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_from", since = "1.34.0")]
-impl Error for char::CharTryFromError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "converted integer out of range for `char`"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "char_from_str", since = "1.20.0")]
-impl Error for char::ParseCharError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "try_reserve", since = "1.57.0")]
-impl Error for alloc::collections::TryReserveError {}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-impl Error for time::FromFloatSecsError {}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for alloc::ffi::NulError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "nul byte found in data"
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl From<alloc::ffi::NulError> for io::Error {
- /// Converts a [`alloc::ffi::NulError`] into a [`io::Error`].
- fn from(_: alloc::ffi::NulError) -> io::Error {
- io::const_io_error!(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
- }
-}
-
-#[cfg(bootstrap)]
-#[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
-impl Error for core::ffi::FromBytesWithNulError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- self.__description()
- }
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")]
-impl Error for core::ffi::FromBytesUntilNulError {}
-
-#[cfg(bootstrap)]
-#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
-impl Error for alloc::ffi::FromVecWithNulError {}
-
-#[cfg(bootstrap)]
-#[stable(feature = "cstring_into", since = "1.7.0")]
-impl Error for alloc::ffi::IntoStringError {
- #[allow(deprecated)]
- fn description(&self) -> &str {
- "C string contained non-utf8 bytes"
- }
-
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Some(self.__source())
- }
-}
-
-#[cfg(bootstrap)]
-impl<'a> dyn Error + 'a {
- /// Request a reference of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_ref<T: ?Sized + 'static>(&'a self) -> Option<&'a T> {
- core::any::request_ref(self)
- }
-
- /// Request a value of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_value<T: 'static>(&'a self) -> Option<T> {
- core::any::request_value(self)
- }
-}
-
-// Copied from `any.rs`.
-#[cfg(bootstrap)]
-impl dyn Error + 'static {
- /// Returns `true` if the inner type is the same as `T`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn is<T: Error + 'static>(&self) -> bool {
- // Get `TypeId` of the type this function is instantiated with.
- let t = TypeId::of::<T>();
-
- // Get `TypeId` of the type in the trait object (`self`).
- let concrete = self.type_id(private::Internal);
-
- // Compare both `TypeId`s on equality.
- t == concrete
- }
-
- /// Returns some reference to the inner value if it is of type `T`, or
- /// `None` if it isn't.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
- if self.is::<T>() {
- unsafe { Some(&*(self as *const dyn Error as *const T)) }
- } else {
- None
- }
- }
-
- /// Returns some mutable reference to the inner value if it is of type `T`, or
- /// `None` if it isn't.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
- if self.is::<T>() {
- unsafe { Some(&mut *(self as *mut dyn Error as *mut T)) }
- } else {
- None
- }
- }
-}
-
-#[cfg(bootstrap)]
-impl dyn Error + 'static + Send {
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn is<T: Error + 'static>(&self) -> bool {
- <dyn Error + 'static>::is::<T>(self)
- }
-
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
- <dyn Error + 'static>::downcast_ref::<T>(self)
- }
-
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
- <dyn Error + 'static>::downcast_mut::<T>(self)
- }
-
- /// Request a reference of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
- <dyn Error>::request_ref(self)
- }
-
- /// Request a value of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_value<T: 'static>(&self) -> Option<T> {
- <dyn Error>::request_value(self)
- }
-}
-
-#[cfg(bootstrap)]
-impl dyn Error + 'static + Send + Sync {
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn is<T: Error + 'static>(&self) -> bool {
- <dyn Error + 'static>::is::<T>(self)
- }
-
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_ref<T: Error + 'static>(&self) -> Option<&T> {
- <dyn Error + 'static>::downcast_ref::<T>(self)
- }
-
- /// Forwards to the method defined on the type `dyn Error`.
- #[stable(feature = "error_downcast", since = "1.3.0")]
- #[inline]
- pub fn downcast_mut<T: Error + 'static>(&mut self) -> Option<&mut T> {
- <dyn Error + 'static>::downcast_mut::<T>(self)
- }
-
- /// Request a reference of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_ref<T: ?Sized + 'static>(&self) -> Option<&T> {
- <dyn Error>::request_ref(self)
- }
-
- /// Request a value of type `T` as context about this error.
- #[unstable(feature = "error_generic_member_access", issue = "99301")]
- pub fn request_value<T: 'static>(&self) -> Option<T> {
- <dyn Error>::request_value(self)
- }
-}
-
-#[cfg(bootstrap)]
-impl dyn Error {
- #[inline]
- #[stable(feature = "error_downcast", since = "1.3.0")]
- /// Attempts to downcast the box to a concrete type.
- pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error>> {
- if self.is::<T>() {
- unsafe {
- let raw: *mut dyn Error = Box::into_raw(self);
- Ok(Box::from_raw(raw as *mut T))
- }
- } else {
- Err(self)
- }
- }
-
- /// Returns an iterator starting with the current error and continuing with
- /// recursively calling [`Error::source`].
- ///
- /// If you want to omit the current error and only use its sources,
- /// use `skip(1)`.
- ///
- /// # Examples
- ///
- /// ```
- /// #![feature(error_iter)]
- /// use std::error::Error;
- /// use std::fmt;
- ///
- /// #[derive(Debug)]
- /// struct A;
- ///
- /// #[derive(Debug)]
- /// struct B(Option<Box<dyn Error + 'static>>);
- ///
- /// impl fmt::Display for A {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "A")
- /// }
- /// }
- ///
- /// impl fmt::Display for B {
- /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- /// write!(f, "B")
- /// }
- /// }
- ///
- /// impl Error for A {}
- ///
- /// impl Error for B {
- /// fn source(&self) -> Option<&(dyn Error + 'static)> {
- /// self.0.as_ref().map(|e| e.as_ref())
- /// }
- /// }
- ///
- /// let b = B(Some(Box::new(A)));
- ///
- /// // let err : Box<Error> = b.into(); // or
- /// let err = &b as &(dyn Error);
- ///
- /// let mut iter = err.sources();
- ///
- /// assert_eq!("B".to_string(), iter.next().unwrap().to_string());
- /// assert_eq!("A".to_string(), iter.next().unwrap().to_string());
- /// assert!(iter.next().is_none());
- /// assert!(iter.next().is_none());
- /// ```
- #[unstable(feature = "error_iter", issue = "58520")]
- #[inline]
- pub fn sources(&self) -> Sources<'_> {
- // You may think this method would be better in the Error trait, and you'd be right.
- // Unfortunately that doesn't work, not because of the object safety rules but because we
- // save a reference to self in Sources below as a trait object. If this method was
- // declared in Error, then self would have the type &T where T is some concrete type which
- // implements Error. We would need to coerce self to have type &dyn Error, but that requires
- // that Self has a known size (i.e., Self: Sized). We can't put that bound on Error
- // since that would forbid Error trait objects, and we can't put that bound on the method
- // because that means the method can't be called on trait objects (we'd also need the
- // 'static bound, but that isn't allowed because methods with bounds on Self other than
- // Sized are not object-safe). Requiring an Unsize bound is not backwards compatible.
-
- Sources { current: Some(self) }
- }
-}
-
-/// An iterator over an [`Error`] and its sources.
-///
-/// If you want to omit the initial error and only process
-/// its sources, use `skip(1)`.
-#[unstable(feature = "error_iter", issue = "58520")]
-#[derive(Clone, Debug)]
-#[cfg(bootstrap)]
-pub struct Sources<'a> {
- current: Option<&'a (dyn Error + 'static)>,
-}
-
-#[cfg(bootstrap)]
-#[unstable(feature = "error_iter", issue = "58520")]
-impl<'a> Iterator for Sources<'a> {
- type Item = &'a (dyn Error + 'static);
-
- fn next(&mut self) -> Option<Self::Item> {
- let current = self.current;
- self.current = self.current.and_then(Error::source);
- current
- }
-}
-
-#[cfg(bootstrap)]
-impl dyn Error + Send {
- #[inline]
- #[stable(feature = "error_downcast", since = "1.3.0")]
- /// Attempts to downcast the box to a concrete type.
- pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<dyn Error + Send>> {
- let err: Box<dyn Error> = self;
- <dyn Error>::downcast(err).map_err(|s| unsafe {
- // Reapply the `Send` marker.
- transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
- })
- }
-}
-
-#[cfg(bootstrap)]
-impl dyn Error + Send + Sync {
- #[inline]
- #[stable(feature = "error_downcast", since = "1.3.0")]
- /// Attempts to downcast the box to a concrete type.
- pub fn downcast<T: Error + 'static>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
- let err: Box<dyn Error> = self;
- <dyn Error>::downcast(err).map_err(|s| unsafe {
- // Reapply the `Send + Sync` marker.
- transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
- })
- }
-}
-
/// An error reporter that prints an error and its sources.
///
/// Report also exposes configuration options for formatting the error sources, either entirely on a
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index c6c78dc39..188ff00e1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1365,6 +1365,34 @@ impl FileTimes {
impl Permissions {
/// Returns `true` if these permissions describe a readonly (unwritable) file.
///
+ /// # Note
+ ///
+ /// This function does not take Access Control Lists (ACLs) or Unix group
+ /// membership into account.
+ ///
+ /// # Windows
+ ///
+ /// On Windows this returns [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
+ /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
+ /// but the user may still have permission to change this flag. If
+ /// `FILE_ATTRIBUTE_READONLY` is *not* set then writes may still fail due
+ /// to lack of write permission.
+ /// The behavior of this attribute for directories depends on the Windows
+ /// version.
+ ///
+ /// # Unix (including macOS)
+ ///
+ /// On Unix-based platforms this checks if *any* of the owner, group or others
+ /// write permission bits are set. It does not check if the current
+ /// user is in the file's assigned group. It also does not check ACLs.
+ /// Therefore even if this returns true you may not be able to write to the
+ /// file, and vice versa. The [`PermissionsExt`] trait gives direct access
+ /// to the permission bits but also does not read ACLs. If you need to
+ /// accurately know whether or not a file is writable use the `access()`
+ /// function from libc.
+ ///
+ /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
+ ///
/// # Examples
///
/// ```no_run
@@ -1390,8 +1418,40 @@ impl Permissions {
/// using the resulting `Permission` will update file permissions to allow
/// writing.
///
- /// This operation does **not** modify the filesystem. To modify the
- /// filesystem use the [`set_permissions`] function.
+ /// This operation does **not** modify the files attributes. This only
+ /// changes the in-memory value of these attributes for this `Permissions`
+ /// instance. To modify the files attributes use the [`set_permissions`]
+ /// function which commits these attribute changes to the file.
+ ///
+ /// # Note
+ ///
+ /// `set_readonly(false)` makes the file *world-writable* on Unix.
+ /// You can use the [`PermissionsExt`] trait on Unix to avoid this issue.
+ ///
+ /// It also does not take Access Control Lists (ACLs) or Unix group
+ /// membership into account.
+ ///
+ /// # Windows
+ ///
+ /// On Windows this sets or clears [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
+ /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
+ /// but the user may still have permission to change this flag. If
+ /// `FILE_ATTRIBUTE_READONLY` is *not* set then the write may still fail if
+ /// the user does not have permission to write to the file.
+ ///
+ /// In Windows 7 and earlier this attribute prevents deleting empty
+ /// directories. It does not prevent modifying the directory contents.
+ /// On later versions of Windows this attribute is ignored for directories.
+ ///
+ /// # Unix (including macOS)
+ ///
+ /// On Unix-based platforms this sets or clears the write access bit for
+ /// the owner, group *and* others, equivalent to `chmod a+w <file>`
+ /// or `chmod a-w <file>` respectively. The latter will grant write access
+ /// to all users! You can use the [`PermissionsExt`] trait on Unix
+ /// to avoid this issue.
+ ///
+ /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
///
/// # Examples
///
@@ -1405,7 +1465,8 @@ impl Permissions {
///
/// permissions.set_readonly(true);
///
- /// // filesystem doesn't change
+ /// // filesystem doesn't change, only the in memory state of the
+ /// // readonly permission
/// assert_eq!(false, metadata.permissions().readonly());
///
/// // just this particular `permissions`.
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index 29b09fcc5..3cabf2449 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -76,7 +76,6 @@ impl fmt::Debug for Error {
}
}
-#[cfg(not(bootstrap))]
#[stable(feature = "rust1", since = "1.0.0")]
impl From<alloc::ffi::NulError> for Error {
/// Converts a [`alloc::ffi::NulError`] into a [`Error`].
@@ -388,7 +387,7 @@ pub enum ErrorKind {
impl ErrorKind {
pub(crate) fn as_str(&self) -> &'static str {
use ErrorKind::*;
- // Strictly alphabetical, please. (Sadly rustfmt cannot do this yet.)
+ // tidy-alphabetical-start
match *self {
AddrInUse => "address in use",
AddrNotAvailable => "address not available",
@@ -432,6 +431,7 @@ impl ErrorKind {
WouldBlock => "operation would block",
WriteZero => "write zero",
}
+ // tidy-alphabetical-end
}
}
@@ -482,6 +482,7 @@ impl Error {
/// originate from the OS itself. The `error` argument is an arbitrary
/// payload which will be contained in this [`Error`].
///
+ /// Note that this function allocates memory on the heap.
/// If no extra payload is required, use the `From` conversion from
/// `ErrorKind`.
///
@@ -496,7 +497,7 @@ impl Error {
/// // errors can also be created from other errors
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
///
- /// // creating an error without payload
+ /// // creating an error without payload (and without memory allocation)
/// let eof_error = Error::from(ErrorKind::UnexpectedEof);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/error/tests.rs b/library/std/src/io/error/tests.rs
index c897a5e87..16c634e9a 100644
--- a/library/std/src/io/error/tests.rs
+++ b/library/std/src/io/error/tests.rs
@@ -86,7 +86,7 @@ fn test_errorkind_packing() {
assert_eq!(Error::from(ErrorKind::NotFound).kind(), ErrorKind::NotFound);
assert_eq!(Error::from(ErrorKind::PermissionDenied).kind(), ErrorKind::PermissionDenied);
assert_eq!(Error::from(ErrorKind::Uncategorized).kind(), ErrorKind::Uncategorized);
- // Check that the innards look like like what we want.
+ // Check that the innards look like what we want.
assert_matches!(
Error::from(ErrorKind::OutOfMemory).repr.data(),
ErrorData::Simple(ErrorKind::OutOfMemory),
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index eeace2c43..23a13523f 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -262,9 +262,12 @@ use crate::sys_common::memchr;
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
pub use self::buffered::WriterPanicked;
+pub(crate) use self::stdio::attempt_print_to_stderr;
#[unstable(feature = "internal_output_capture", issue = "none")]
#[doc(no_inline, hidden)]
pub use self::stdio::set_output_capture;
+#[unstable(feature = "is_terminal", issue = "98070")]
+pub use self::stdio::IsTerminal;
#[unstable(feature = "print_internals", issue = "none")]
pub use self::stdio::{_eprint, _print};
#[stable(feature = "rust1", since = "1.0.0")]
@@ -580,7 +583,7 @@ pub trait Read {
/// `n > buf.len()`.
///
/// No guarantees are provided about the contents of `buf` when this
- /// function is called, implementations cannot rely on any property of the
+ /// function is called, so implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that *implementations*
/// only write data to `buf` instead of reading its contents.
///
@@ -756,7 +759,7 @@ pub trait Read {
/// specified buffer `buf`.
///
/// No guarantees are provided about the contents of `buf` when this
- /// function is called, implementations cannot rely on any property of the
+ /// function is called, so implementations cannot rely on any property of the
/// contents of `buf` being true. It is recommended that implementations
/// only write data to `buf` instead of reading its contents. The
/// documentation on [`read`] has a more detailed explanation on this
diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index b1a84095f..4800eeda0 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -3,10 +3,10 @@
#[cfg(test)]
mod tests;
-use crate::cmp;
use crate::fmt::{self, Debug, Formatter};
use crate::io::{Result, Write};
use crate::mem::{self, MaybeUninit};
+use crate::{cmp, ptr};
/// A borrowed byte buffer which is incrementally filled and initialized.
///
@@ -250,8 +250,11 @@ impl<'a> BorrowedCursor<'a> {
/// Initializes all bytes in the cursor.
#[inline]
pub fn ensure_init(&mut self) -> &mut Self {
- for byte in self.uninit_mut() {
- byte.write(0);
+ let uninit = self.uninit_mut();
+ // SAFETY: 0 is a valid value for MaybeUninit<u8> and the length matches the allocation
+ // since it is comes from a slice reference.
+ unsafe {
+ ptr::write_bytes(uninit.as_mut_ptr(), 0, uninit.len());
}
self.buf.init = self.buf.capacity();
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 2dc12a18a..1141a957d 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -7,6 +7,7 @@ use crate::io::prelude::*;
use crate::cell::{Cell, RefCell};
use crate::fmt;
+use crate::fs::File;
use crate::io::{self, BufReader, IoSlice, IoSliceMut, LineWriter, Lines};
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock};
@@ -999,7 +1000,18 @@ fn print_to<T>(args: fmt::Arguments<'_>, global_s: fn() -> T, label: &str)
where
T: Write,
{
- if OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
+ if print_to_buffer_if_capture_used(args) {
+ // Successfully wrote to capture buffer.
+ return;
+ }
+
+ if let Err(e) = global_s().write_fmt(args) {
+ panic!("failed printing to {label}: {e}");
+ }
+}
+
+fn print_to_buffer_if_capture_used(args: fmt::Arguments<'_>) -> bool {
+ OUTPUT_CAPTURE_USED.load(Ordering::Relaxed)
&& OUTPUT_CAPTURE.try_with(|s| {
// Note that we completely remove a local sink to write to in case
// our printing recursively panics/prints, so the recursive
@@ -1009,16 +1021,49 @@ where
s.set(Some(w));
})
}) == Ok(Some(()))
- {
- // Successfully wrote to capture buffer.
+}
+
+/// Used by impl Termination for Result to print error after `main` or a test
+/// has returned. Should avoid panicking, although we can't help it if one of
+/// the Display impls inside args decides to.
+pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
+ if print_to_buffer_if_capture_used(args) {
return;
}
- if let Err(e) = global_s().write_fmt(args) {
- panic!("failed printing to {label}: {e}");
- }
+ // Ignore error if the write fails, for example because stderr is already
+ // closed. There is not much point panicking at this point.
+ let _ = stderr().write_fmt(args);
}
+/// Trait to determine if a descriptor/handle refers to a terminal/tty.
+#[unstable(feature = "is_terminal", issue = "98070")]
+pub trait IsTerminal: crate::sealed::Sealed {
+ /// Returns `true` if the descriptor/handle refers to a terminal/tty.
+ ///
+ /// On platforms where Rust does not know how to detect a terminal yet, this will return
+ /// `false`. This will also return `false` if an unexpected error occurred, such as from
+ /// passing an invalid file descriptor.
+ fn is_terminal(&self) -> bool;
+}
+
+macro_rules! impl_is_terminal {
+ ($($t:ty),*$(,)?) => {$(
+ #[unstable(feature = "sealed", issue = "none")]
+ impl crate::sealed::Sealed for $t {}
+
+ #[unstable(feature = "is_terminal", issue = "98070")]
+ impl IsTerminal for $t {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ crate::sys::io::is_terminal(self)
+ }
+ }
+ )*}
+}
+
+impl_is_terminal!(File, Stdin, StdinLock<'_>, Stdout, StdoutLock<'_>, Stderr, StderrLock<'_>);
+
#[unstable(
feature = "print_internals",
reason = "implementation detail which may disappear or be replaced at any time",
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index a4b0522b0..e35145c4a 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -1867,11 +1867,15 @@ mod type_keyword {}
/// Code or interfaces whose [memory safety] cannot be verified by the type
/// system.
///
-/// The `unsafe` keyword has two uses: to declare the existence of contracts the
-/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a
-/// programmer has checked that these contracts have been upheld (`unsafe {}`
-/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually
-/// exclusive, as can be seen in `unsafe fn`.
+/// The `unsafe` keyword has two uses:
+/// - to declare the existence of contracts the compiler can't check (`unsafe fn` and `unsafe
+/// trait`),
+/// - and to declare that a programmer has checked that these contracts have been upheld (`unsafe
+/// {}` and `unsafe impl`, but also `unsafe fn` -- see below).
+///
+/// They are not mutually exclusive, as can be seen in `unsafe fn`: the body of an `unsafe fn` is,
+/// by default, treated like an unsafe block. The `unsafe_op_in_unsafe_fn` lint can be enabled to
+/// change that.
///
/// # Unsafe abilities
///
@@ -1914,12 +1918,12 @@ mod type_keyword {}
/// - `unsafe impl`: the contract necessary to implement the trait has been
/// checked by the programmer and is guaranteed to be respected.
///
-/// `unsafe fn` also acts like an `unsafe {}` block
+/// By default, `unsafe fn` also acts like an `unsafe {}` block
/// around the code inside the function. This means it is not just a signal to
/// the caller, but also promises that the preconditions for the operations
-/// inside the function are upheld. Mixing these two meanings can be confusing
-/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when
-/// making `unsafe` operations.
+/// inside the function are upheld. Mixing these two meanings can be confusing, so the
+/// `unsafe_op_in_unsafe_fn` lint can be enabled to warn against that and require explicit unsafe
+/// blocks even inside `unsafe fn`.
///
/// See the [Rustnomicon] and the [Reference] for more information.
///
@@ -1987,13 +1991,16 @@ mod type_keyword {}
///
/// ```rust
/// # #![allow(dead_code)]
+/// #![deny(unsafe_op_in_unsafe_fn)]
+///
/// /// Dereference the given pointer.
/// ///
/// /// # Safety
/// ///
/// /// `ptr` must be aligned and must not be dangling.
/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 {
-/// *ptr
+/// // SAFETY: the caller is required to ensure that `ptr` is aligned and dereferenceable.
+/// unsafe { *ptr }
/// }
///
/// let a = 3;
@@ -2003,35 +2010,118 @@ mod type_keyword {}
/// unsafe { assert_eq!(*b, deref_unchecked(b)); };
/// ```
///
-/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This
-/// makes a guarantee to other `unsafe` code that the implementation satisfies
-/// the trait's safety contract. The [Send] and [Sync] traits are examples of
-/// this behaviour in the standard library.
+/// ## `unsafe` and traits
+///
+/// The interactions of `unsafe` and traits can be surprising, so let us contrast the
+/// two combinations of safe `fn` in `unsafe trait` and `unsafe fn` in safe trait using two
+/// examples:
+///
+/// ```rust
+/// /// # Safety
+/// ///
+/// /// `make_even` must return an even number.
+/// unsafe trait MakeEven {
+/// fn make_even(&self) -> i32;
+/// }
+///
+/// // SAFETY: Our `make_even` always returns something even.
+/// unsafe impl MakeEven for i32 {
+/// fn make_even(&self) -> i32 {
+/// self << 1
+/// }
+/// }
+///
+/// fn use_make_even(x: impl MakeEven) {
+/// if x.make_even() % 2 == 1 {
+/// // SAFETY: this can never happen, because all `MakeEven` implementations
+/// // ensure that `make_even` returns something even.
+/// unsafe { std::hint::unreachable_unchecked() };
+/// }
+/// }
+/// ```
+///
+/// Note how the safety contract of the trait is upheld by the implementation, and is itself used to
+/// uphold the safety contract of the unsafe function `unreachable_unchecked` called by
+/// `use_make_even`. `make_even` itself is a safe function because its *callers* do not have to
+/// worry about any contract, only the *implementation* of `MakeEven` is required to uphold a
+/// certain contract. `use_make_even` is safe because it can use the promise made by `MakeEven`
+/// implementations to uphold the safety contract of the `unsafe fn unreachable_unchecked` it calls.
+///
+/// It is also possible to have `unsafe fn` in a regular safe `trait`:
///
/// ```rust
-/// /// Implementors of this trait must guarantee an element is always
-/// /// accessible with index 3.
-/// unsafe trait ThreeIndexable<T> {
-/// /// Returns a reference to the element with index 3 in `&self`.
-/// fn three(&self) -> &T;
+/// # #![feature(never_type)]
+/// #![deny(unsafe_op_in_unsafe_fn)]
+///
+/// trait Indexable {
+/// const LEN: usize;
+///
+/// /// # Safety
+/// ///
+/// /// The caller must ensure that `idx < LEN`.
+/// unsafe fn idx_unchecked(&self, idx: usize) -> i32;
/// }
///
-/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe`
-/// // because the implementor must abide by a contract the compiler cannot
-/// // check but as a programmer we know there will always be a valid element
-/// // at index 3 to access.
-/// unsafe impl<T> ThreeIndexable<T> for [T; 4] {
-/// fn three(&self) -> &T {
-/// // SAFETY: implementing the trait means there always is an element
-/// // with index 3 accessible.
-/// unsafe { self.get_unchecked(3) }
+/// // The implementation for `i32` doesn't need to do any contract reasoning.
+/// impl Indexable for i32 {
+/// const LEN: usize = 1;
+///
+/// unsafe fn idx_unchecked(&self, idx: usize) -> i32 {
+/// debug_assert_eq!(idx, 0);
+/// *self
/// }
/// }
///
-/// let a = [1, 2, 4, 8];
-/// assert_eq!(a.three(), &8);
+/// // The implementation for arrays exploits the function contract to
+/// // make use of `get_unchecked` on slices and avoid a run-time check.
+/// impl Indexable for [i32; 42] {
+/// const LEN: usize = 42;
+///
+/// unsafe fn idx_unchecked(&self, idx: usize) -> i32 {
+/// // SAFETY: As per this trait's documentation, the caller ensures
+/// // that `idx < 42`.
+/// unsafe { *self.get_unchecked(idx) }
+/// }
+/// }
+///
+/// // The implementation for the never type declares a length of 0,
+/// // which means `idx_unchecked` can never be called.
+/// impl Indexable for ! {
+/// const LEN: usize = 0;
+///
+/// unsafe fn idx_unchecked(&self, idx: usize) -> i32 {
+/// // SAFETY: As per this trait's documentation, the caller ensures
+/// // that `idx < 0`, which is impossible, so this is dead code.
+/// unsafe { std::hint::unreachable_unchecked() }
+/// }
+/// }
+///
+/// fn use_indexable<I: Indexable>(x: I, idx: usize) -> i32 {
+/// if idx < I::LEN {
+/// // SAFETY: We have checked that `idx < I::LEN`.
+/// unsafe { x.idx_unchecked(idx) }
+/// } else {
+/// panic!("index out-of-bounds")
+/// }
+/// }
/// ```
///
+/// This time, `use_indexable` is safe because it uses a run-time check to discharge the safety
+/// contract of `idx_unchecked`. Implementing `Indexable` is safe because when writing
+/// `idx_unchecked`, we don't have to worry: our *callers* need to discharge a proof obligation
+/// (like `use_indexable` does), but the *implementation* of `get_unchecked` has no proof obligation
+/// to contend with. Of course, the implementation of `Indexable` may choose to call other unsafe
+/// operations, and then it needs an `unsafe` *block* to indicate it discharged the proof
+/// obligations of its callees. (We enabled `unsafe_op_in_unsafe_fn`, so the body of `idx_unchecked`
+/// is not implicitly an unsafe block.) For that purpose it can make use of the contract that all
+/// its callers must uphold -- the fact that `idx < LEN`.
+///
+/// Formally speaking, an `unsafe fn` in a trait is a function with *preconditions* that go beyond
+/// those encoded by the argument types (such as `idx < LEN`), whereas an `unsafe trait` can declare
+/// that some of its functions have *postconditions* that go beyond those encoded in the return type
+/// (such as returning an even integer). If a trait needs a function with both extra precondition
+/// and extra postcondition, then it needs an `unsafe fn` in an `unsafe trait`.
+///
/// [`extern`]: keyword.extern.html
/// [`trait`]: keyword.trait.html
/// [`static`]: keyword.static.html
@@ -2043,7 +2133,6 @@ mod type_keyword {}
/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
/// [Reference]: ../reference/unsafety.html
-/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585
/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696
mod unsafe_keyword {}
diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs
deleted file mode 100644
index f8c06c3f9..000000000
--- a/library/std/src/lazy.rs
+++ /dev/null
@@ -1 +0,0 @@
-//! Lazy values and one-time initialization of static data.
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index bc4f1b27c..385585dad 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -145,8 +145,8 @@
//! abstracting over differences in common platforms, most notably Windows and
//! Unix derivatives.
//!
-//! Common types of I/O, including [files], [TCP], [UDP], are defined in the
-//! [`io`], [`fs`], and [`net`] modules.
+//! Common types of I/O, including [files], [TCP], and [UDP], are defined in
+//! the [`io`], [`fs`], and [`net`] modules.
//!
//! The [`thread`] module contains Rust's threading abstractions. [`sync`]
//! contains further primitive shared memory types, including [`atomic`] and
@@ -251,11 +251,11 @@
#![feature(doc_notable_trait)]
#![feature(dropck_eyepatch)]
#![feature(exhaustive_patterns)]
+#![feature(if_let_guard)]
#![feature(intra_doc_pointers)]
-#![cfg_attr(bootstrap, feature(label_break_value))]
+#![feature(is_terminal)]
#![feature(lang_items)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(linkage)]
#![feature(link_cfg)]
#![feature(min_specialization)]
@@ -280,11 +280,10 @@
#![feature(core_intrinsics)]
#![feature(cstr_from_bytes_until_nul)]
#![feature(cstr_internals)]
-#![feature(duration_checked_float)]
#![feature(duration_constants)]
-#![cfg_attr(not(bootstrap), feature(error_generic_member_access))]
-#![cfg_attr(not(bootstrap), feature(error_in_core))]
-#![cfg_attr(not(bootstrap), feature(error_iter))]
+#![feature(error_generic_member_access)]
+#![feature(error_in_core)]
+#![feature(error_iter)]
#![feature(exact_size_is_empty)]
#![feature(exclusive_wrapper)]
#![feature(extend_one)]
@@ -293,10 +292,9 @@
#![feature(hasher_prefixfree_extras)]
#![feature(hashmap_internals)]
#![feature(int_error_internals)]
-#![feature(is_some_with)]
+#![feature(is_some_and)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_write_slice)]
-#![feature(mixed_integer_ops)]
#![feature(nonnull_slice_from_raw_parts)]
#![feature(panic_can_unwind)]
#![feature(panic_info_message)]
@@ -315,6 +313,7 @@
#![feature(strict_provenance)]
#![feature(maybe_uninit_uninit_array)]
#![feature(const_maybe_uninit_uninit_array)]
+#![feature(const_waker)]
//
// Library features (alloc):
#![feature(alloc_layout_extra)]
@@ -350,9 +349,9 @@
#![feature(trace_macros)]
//
// Only used in tests/benchmarks:
-#![feature(bench_black_box)]
//
// Only for const-ness:
+#![feature(const_collections_with_hasher)]
#![feature(const_io_structs)]
#![feature(const_ip)]
#![feature(const_ipv4)]
@@ -530,9 +529,6 @@ pub mod process;
pub mod sync;
pub mod time;
-#[unstable(feature = "once_cell", issue = "74465")]
-pub mod lazy;
-
// Pull in `std_float` crate into libstd. The contents of
// `std_float` are in a different repository: rust-lang/portable-simd.
#[path = "../../portable-simd/crates/std_float/src/lib.rs"]
diff --git a/library/std/src/os/fd/mod.rs b/library/std/src/os/fd/mod.rs
index a45694753..c6aa7c77d 100644
--- a/library/std/src/os/fd/mod.rs
+++ b/library/std/src/os/fd/mod.rs
@@ -1,16 +1,25 @@
//! Owned and borrowed Unix-like file descriptors.
+//!
+//! This module is supported on Unix platforms and WASI, which both use a
+//! similar file descriptor system for referencing OS resources.
#![stable(feature = "io_safety", since = "1.63.0")]
#![deny(unsafe_op_in_unsafe_fn)]
// `RawFd`, `AsRawFd`, etc.
-pub mod raw;
+mod raw;
// `OwnedFd`, `AsFd`, etc.
-pub mod owned;
+mod owned;
// Implementations for `AsRawFd` etc. for network types.
mod net;
#[cfg(test)]
mod tests;
+
+// Export the types and traits for the public API.
+#[unstable(feature = "os_fd", issue = "98699")]
+pub use owned::*;
+#[unstable(feature = "os_fd", issue = "98699")]
+pub use raw::*;
diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs
index 71e33fb9e..c16518577 100644
--- a/library/std/src/os/fd/owned.rs
+++ b/library/std/src/os/fd/owned.rs
@@ -6,6 +6,7 @@
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::fmt;
use crate::fs;
+use crate::io;
use crate::marker::PhantomData;
use crate::mem::forget;
#[cfg(not(any(target_arch = "wasm32", target_env = "sgx")))]
@@ -192,6 +193,23 @@ impl fmt::Debug for OwnedFd {
}
}
+macro_rules! impl_is_terminal {
+ ($($t:ty),*$(,)?) => {$(
+ #[unstable(feature = "sealed", issue = "none")]
+ impl crate::sealed::Sealed for $t {}
+
+ #[unstable(feature = "is_terminal", issue = "98070")]
+ impl crate::io::IsTerminal for $t {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ crate::sys::io::is_terminal(self)
+ }
+ }
+ )*}
+}
+
+impl_is_terminal!(BorrowedFd<'_>, OwnedFd);
+
/// A trait to borrow the file descriptor from an underlying object.
///
/// This is only available on unix platforms and must be imported in order to
@@ -206,10 +224,8 @@ pub trait AsFd {
/// ```rust,no_run
/// use std::fs::File;
/// # use std::io;
- /// # #[cfg(target_os = "wasi")]
- /// # use std::os::wasi::io::{AsFd, BorrowedFd};
- /// # #[cfg(unix)]
- /// # use std::os::unix::io::{AsFd, BorrowedFd};
+ /// # #[cfg(any(unix, target_os = "wasi"))]
+ /// # use std::os::fd::{AsFd, BorrowedFd};
///
/// let mut f = File::open("foo.txt")?;
/// # #[cfg(any(unix, target_os = "wasi"))]
@@ -387,3 +403,54 @@ impl<T: AsFd> AsFd for Box<T> {
(**self).as_fd()
}
}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl AsFd for io::Stdin {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ unsafe { BorrowedFd::borrow_raw(0) }
+ }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl<'a> AsFd for io::StdinLock<'a> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // SAFETY: user code should not close stdin out from under the standard library
+ unsafe { BorrowedFd::borrow_raw(0) }
+ }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl AsFd for io::Stdout {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ unsafe { BorrowedFd::borrow_raw(1) }
+ }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl<'a> AsFd for io::StdoutLock<'a> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // SAFETY: user code should not close stdout out from under the standard library
+ unsafe { BorrowedFd::borrow_raw(1) }
+ }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl AsFd for io::Stderr {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ unsafe { BorrowedFd::borrow_raw(2) }
+ }
+}
+
+#[stable(feature = "io_safety", since = "1.63.0")]
+impl<'a> AsFd for io::StderrLock<'a> {
+ #[inline]
+ fn as_fd(&self) -> BorrowedFd<'_> {
+ // SAFETY: user code should not close stderr out from under the standard library
+ unsafe { BorrowedFd::borrow_raw(2) }
+ }
+}
diff --git a/library/std/src/os/fd/raw.rs b/library/std/src/os/fd/raw.rs
index 1b3d11042..f92a05066 100644
--- a/library/std/src/os/fd/raw.rs
+++ b/library/std/src/os/fd/raw.rs
@@ -42,10 +42,8 @@ pub trait AsRawFd {
/// ```no_run
/// use std::fs::File;
/// # use std::io;
- /// #[cfg(unix)]
- /// use std::os::unix::io::{AsRawFd, RawFd};
- /// #[cfg(target_os = "wasi")]
- /// use std::os::wasi::io::{AsRawFd, RawFd};
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// use std::os::fd::{AsRawFd, RawFd};
///
/// let mut f = File::open("foo.txt")?;
/// // Note that `raw_fd` is only valid as long as `f` exists.
@@ -83,10 +81,8 @@ pub trait FromRawFd {
/// ```no_run
/// use std::fs::File;
/// # use std::io;
- /// #[cfg(unix)]
- /// use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
- /// #[cfg(target_os = "wasi")]
- /// use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd};
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// use std::os::fd::{FromRawFd, IntoRawFd, RawFd};
///
/// let f = File::open("foo.txt")?;
/// # #[cfg(any(unix, target_os = "wasi"))]
@@ -121,10 +117,8 @@ pub trait IntoRawFd {
/// ```no_run
/// use std::fs::File;
/// # use std::io;
- /// #[cfg(unix)]
- /// use std::os::unix::io::{IntoRawFd, RawFd};
- /// #[cfg(target_os = "wasi")]
- /// use std::os::wasi::io::{IntoRawFd, RawFd};
+ /// #[cfg(any(unix, target_os = "wasi"))]
+ /// use std::os::fd::{IntoRawFd, RawFd};
///
/// let f = File::open("foo.txt")?;
/// #[cfg(any(unix, target_os = "wasi"))]
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index 18c64b510..42773805c 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -145,9 +145,11 @@ pub mod solaris;
pub mod solid;
#[cfg(target_os = "vxworks")]
pub mod vxworks;
+#[cfg(target_os = "watchos")]
+pub(crate) mod watchos;
#[cfg(any(unix, target_os = "wasi", doc))]
-mod fd;
+pub mod fd;
#[cfg(any(target_os = "linux", target_os = "android", doc))]
mod net;
diff --git a/library/std/src/os/unix/io/fd.rs b/library/std/src/os/unix/io/fd.rs
deleted file mode 100644
index d4cb69645..000000000
--- a/library/std/src/os/unix/io/fd.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//! Owned and borrowed file descriptors.
-
-// Tests for this module
-#[cfg(test)]
-mod tests;
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-pub use crate::os::fd::owned::*;
diff --git a/library/std/src/os/unix/io/mod.rs b/library/std/src/os/unix/io/mod.rs
index 3ab5606f8..25b5dbff1 100644
--- a/library/std/src/os/unix/io/mod.rs
+++ b/library/std/src/os/unix/io/mod.rs
@@ -77,10 +77,9 @@
#![stable(feature = "rust1", since = "1.0.0")]
-mod fd;
-mod raw;
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-pub use fd::*;
#[stable(feature = "rust1", since = "1.0.0")]
-pub use raw::*;
+pub use crate::os::fd::*;
+
+// Tests for this module
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/os/unix/io/raw.rs b/library/std/src/os/unix/io/raw.rs
deleted file mode 100644
index a4d2ba797..000000000
--- a/library/std/src/os/unix/io/raw.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-//! Unix-specific extensions to general I/O primitives.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::os::fd::raw::*;
diff --git a/library/std/src/os/unix/io/fd/tests.rs b/library/std/src/os/unix/io/tests.rs
index 84d2a7a1a..84d2a7a1a 100644
--- a/library/std/src/os/unix/io/fd/tests.rs
+++ b/library/std/src/os/unix/io/tests.rs
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index 411cc0925..f97fa0fb0 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -73,6 +73,8 @@ mod platform {
pub use crate::os::solaris::*;
#[cfg(target_os = "vxworks")]
pub use crate::os::vxworks::*;
+ #[cfg(target_os = "watchos")]
+ pub use crate::os::watchos::*;
}
pub mod ffi;
diff --git a/library/std/src/os/wasi/io/fd.rs b/library/std/src/os/wasi/io/fd.rs
index 75703af6a..930aca887 100644
--- a/library/std/src/os/wasi/io/fd.rs
+++ b/library/std/src/os/wasi/io/fd.rs
@@ -1,10 +1,9 @@
//! Owned and borrowed file descriptors.
-#![stable(feature = "io_safety_wasi", since = "1.65.0")]
+#![unstable(feature = "wasi_ext", issue = "71213")]
// Tests for this module
#[cfg(test)]
mod tests;
-#[stable(feature = "io_safety_wasi", since = "1.65.0")]
pub use crate::os::fd::owned::*;
diff --git a/library/std/src/os/wasi/io/mod.rs b/library/std/src/os/wasi/io/mod.rs
index 4f5cfbf9a..57bd842a5 100644
--- a/library/std/src/os/wasi/io/mod.rs
+++ b/library/std/src/os/wasi/io/mod.rs
@@ -1,12 +1,6 @@
//! WASI-specific extensions to general I/O primitives.
-#![deny(unsafe_op_in_unsafe_fn)]
-#![stable(feature = "io_safety_wasi", since = "1.65.0")]
+#![stable(feature = "io_safety", since = "1.63.0")]
-mod fd;
-mod raw;
-
-#[stable(feature = "io_safety_wasi", since = "1.65.0")]
-pub use fd::*;
-#[stable(feature = "io_safety_wasi", since = "1.65.0")]
-pub use raw::*;
+#[stable(feature = "io_safety", since = "1.63.0")]
+pub use crate::os::fd::*;
diff --git a/library/std/src/os/wasi/io/raw.rs b/library/std/src/os/wasi/io/raw.rs
index 4ac792ee8..da3b36ada 100644
--- a/library/std/src/os/wasi/io/raw.rs
+++ b/library/std/src/os/wasi/io/raw.rs
@@ -1,6 +1,20 @@
//! WASI-specific extensions to general I/O primitives.
-#![stable(feature = "io_safety_wasi", since = "1.65.0")]
+#![unstable(feature = "wasi_ext", issue = "71213")]
-#[stable(feature = "io_safety_wasi", since = "1.65.0")]
+// NOTE: despite the fact that this module is unstable,
+// stable Rust had the capability to access the stable
+// re-exported items from os::fd::raw through this
+// unstable module.
+// In PR #95956 the stability checker was changed to check
+// all path segments of an item rather than just the last,
+// which caused the aforementioned stable usage to regress
+// (see issue #99502).
+// As a result, the items in os::fd::raw were given the
+// rustc_allowed_through_unstable_modules attribute.
+// No regression tests were added to ensure this property,
+// as CI is not configured to test wasm32-wasi.
+// If this module is stabilized,
+// you may want to remove those attributes
+// (assuming no other unstable modules need them).
pub use crate::os::fd::raw::*;
diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs
new file mode 100644
index 000000000..a14fe35a7
--- /dev/null
+++ b/library/std/src/os/watchos/fs.rs
@@ -0,0 +1,142 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::Metadata;
+use crate::sys_common::AsInner;
+
+#[allow(deprecated)]
+use crate::os::watchos::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+ /// Gain a reference to the underlying `stat` structure which contains
+ /// the raw information returned by the OS.
+ ///
+ /// The contents of the returned `stat` are **not** consistent across
+ /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
+ /// cross-Unix abstractions contained within the raw stat.
+ #[stable(feature = "metadata_ext", since = "1.1.0")]
+ #[deprecated(
+ since = "1.8.0",
+ note = "deprecated in favor of the accessor \
+ methods of this trait"
+ )]
+ #[allow(deprecated)]
+ fn as_raw_stat(&self) -> &raw::stat;
+
+ #[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_birthtime(&self) -> i64;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_birthtime_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_ext2", since = "1.8.0")]
+ fn st_flags(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_gen(&self) -> u32;
+ #[stable(feature = "metadata_ext2", since = "1.8.0")]
+ fn st_lspare(&self) -> u32;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+ #[allow(deprecated)]
+ fn as_raw_stat(&self) -> &raw::stat {
+ unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+ }
+ 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_atime as i64
+ }
+ fn st_atime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_atime_nsec as i64
+ }
+ fn st_mtime(&self) -> i64 {
+ self.as_inner().as_inner().st_mtime as i64
+ }
+ fn st_mtime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_mtime_nsec as i64
+ }
+ fn st_ctime(&self) -> i64 {
+ self.as_inner().as_inner().st_ctime as i64
+ }
+ fn st_ctime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_ctime_nsec as i64
+ }
+ fn st_birthtime(&self) -> i64 {
+ self.as_inner().as_inner().st_birthtime as i64
+ }
+ fn st_birthtime_nsec(&self) -> i64 {
+ self.as_inner().as_inner().st_birthtime_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
+ }
+ fn st_gen(&self) -> u32 {
+ self.as_inner().as_inner().st_gen as u32
+ }
+ fn st_flags(&self) -> u32 {
+ self.as_inner().as_inner().st_flags as u32
+ }
+ fn st_lspare(&self) -> u32 {
+ self.as_inner().as_inner().st_lspare as u32
+ }
+}
diff --git a/library/std/src/os/watchos/mod.rs b/library/std/src/os/watchos/mod.rs
new file mode 100644
index 000000000..cd6454ebb
--- /dev/null
+++ b/library/std/src/os/watchos/mod.rs
@@ -0,0 +1,6 @@
+//! watchOS-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub mod raw;
diff --git a/library/std/src/os/watchos/raw.rs b/library/std/src/os/watchos/raw.rs
new file mode 100644
index 000000000..630a533d9
--- /dev/null
+++ b/library/std/src/os/watchos/raw.rs
@@ -0,0 +1,83 @@
+//! watchOS-specific raw type definitions
+
+#![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_long;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = i64;
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = usize;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_dev: i32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mode: u16,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_nlink: u16,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ino: u64,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_uid: u32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_gid: u32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_rdev: i32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_atime: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_atime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mtime: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_mtime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ctime: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_ctime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_birthtime: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_birthtime_nsec: c_long,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_size: i64,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blocks: i64,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_blksize: i32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_flags: u32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_gen: u32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_lspare: i32,
+ #[stable(feature = "raw_ext", since = "1.1.0")]
+ pub st_qspare: [i64; 2],
+}
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index 16cc8fa27..1dfecc573 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -384,6 +384,23 @@ impl fmt::Debug for OwnedHandle {
}
}
+macro_rules! impl_is_terminal {
+ ($($t:ty),*$(,)?) => {$(
+ #[unstable(feature = "sealed", issue = "none")]
+ impl crate::sealed::Sealed for $t {}
+
+ #[unstable(feature = "is_terminal", issue = "98070")]
+ impl crate::io::IsTerminal for $t {
+ #[inline]
+ fn is_terminal(&self) -> bool {
+ crate::sys::io::is_terminal(self)
+ }
+ }
+ )*}
+}
+
+impl_is_terminal!(BorrowedHandle<'_>, OwnedHandle);
+
/// A trait to borrow the handle from an underlying object.
#[stable(feature = "io_safety", since = "1.63.0")]
pub trait AsHandle {
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 25c9201f2..d4976a469 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -18,9 +18,9 @@ use crate::intrinsics;
use crate::mem::{self, ManuallyDrop};
use crate::process;
use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::{PoisonError, RwLock};
use crate::sys::stdio::panic_output;
use crate::sys_common::backtrace;
-use crate::sys_common::rwlock::StaticRwLock;
use crate::sys_common::thread_info;
use crate::thread;
@@ -71,20 +71,29 @@ extern "C" fn __rust_foreign_exception() -> ! {
rtabort!("Rust cannot catch foreign exceptions");
}
-#[derive(Copy, Clone)]
enum Hook {
Default,
- Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
+ Custom(Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>),
}
impl Hook {
- fn custom(f: impl Fn(&PanicInfo<'_>) + 'static + Sync + Send) -> Self {
- Self::Custom(Box::into_raw(Box::new(f)))
+ #[inline]
+ fn into_box(self) -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
+ match self {
+ Hook::Default => Box::new(default_hook),
+ Hook::Custom(hook) => hook,
+ }
+ }
+}
+
+impl Default for Hook {
+ #[inline]
+ fn default() -> Hook {
+ Hook::Default
}
}
-static HOOK_LOCK: StaticRwLock = StaticRwLock::new();
-static mut HOOK: Hook = Hook::Default;
+static HOOK: RwLock<Hook> = RwLock::new(Hook::Default);
/// Registers a custom panic hook, replacing any that was previously registered.
///
@@ -125,24 +134,13 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
panic!("cannot modify the panic hook from a panicking thread");
}
- // SAFETY:
- //
- // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
- // - The argument of `Box::from_raw` is always a valid pointer that was created using
- // `Box::into_raw`.
- unsafe {
- let guard = HOOK_LOCK.write();
- let old_hook = HOOK;
- HOOK = Hook::Custom(Box::into_raw(hook));
- drop(guard);
-
- if let Hook::Custom(ptr) = old_hook {
- #[allow(unused_must_use)]
- {
- Box::from_raw(ptr);
- }
- }
- }
+ let new = Hook::Custom(hook);
+ let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+ let old = mem::replace(&mut *hook, new);
+ drop(hook);
+ // Only drop the old hook after releasing the lock to avoid deadlocking
+ // if its destructor panics.
+ drop(old);
}
/// Unregisters the current panic hook, returning it.
@@ -179,22 +177,11 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
panic!("cannot modify the panic hook from a panicking thread");
}
- // SAFETY:
- //
- // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
- // - The argument of `Box::from_raw` is always a valid pointer that was created using
- // `Box::into_raw`.
- unsafe {
- let guard = HOOK_LOCK.write();
- let hook = HOOK;
- HOOK = Hook::Default;
- drop(guard);
+ let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+ let old_hook = mem::take(&mut *hook);
+ drop(hook);
- match hook {
- Hook::Default => Box::new(default_hook),
- Hook::Custom(ptr) => Box::from_raw(ptr),
- }
- }
+ old_hook.into_box()
}
/// Atomic combination of [`take_hook`] and [`set_hook`]. Use this to replace the panic handler with
@@ -240,24 +227,9 @@ where
panic!("cannot modify the panic hook from a panicking thread");
}
- // SAFETY:
- //
- // - `HOOK` can only be modified while holding write access to `HOOK_LOCK`.
- // - The argument of `Box::from_raw` is always a valid pointer that was created using
- // `Box::into_raw`.
- unsafe {
- let guard = HOOK_LOCK.write();
- let old_hook = HOOK;
- HOOK = Hook::Default;
-
- let prev = match old_hook {
- Hook::Default => Box::new(default_hook),
- Hook::Custom(ptr) => Box::from_raw(ptr),
- };
-
- HOOK = Hook::custom(move |info| hook_fn(&prev, info));
- drop(guard);
- }
+ let mut hook = HOOK.write().unwrap_or_else(PoisonError::into_inner);
+ let prev = mem::take(&mut *hook).into_box();
+ *hook = Hook::Custom(Box::new(move |info| hook_fn(&prev, info)));
}
fn default_hook(info: &PanicInfo<'_>) {
@@ -328,7 +300,7 @@ pub mod panic_count {
thread_local! { static LOCAL_PANIC_COUNT: Cell<usize> = const { Cell::new(0) } }
// Sum of panic counts from all threads. The purpose of this is to have
- // a fast path in `is_zero` (which is used by `panicking`). In any particular
+ // a fast path in `count_is_zero` (which is used by `panicking`). In any particular
// thread, if that thread currently views `GLOBAL_PANIC_COUNT` as being zero,
// then `LOCAL_PANIC_COUNT` in that thread is zero. This invariant holds before
// and after increase and decrease, but not necessarily during their execution.
@@ -336,6 +308,14 @@ pub mod panic_count {
// Additionally, the top bit of GLOBAL_PANIC_COUNT (GLOBAL_ALWAYS_ABORT_FLAG)
// records whether panic::always_abort() has been called. This can only be
// set, never cleared.
+ // panic::always_abort() is usually called to prevent memory allocations done by
+ // the panic handling in the child created by `libc::fork`.
+ // Memory allocations performed in a child created with `libc::fork` are undefined
+ // behavior in most operating systems.
+ // Accessing LOCAL_PANIC_COUNT in a child created by `libc::fork` would lead to a memory
+ // allocation. Only GLOBAL_PANIC_COUNT can be accessed in this situation. This is
+ // sufficient because a child process will always have exactly one thread only.
+ // See also #85261 for details.
//
// This could be viewed as a struct containing a single bit and an n-1-bit
// value, but if we wrote it like that it would be more than a single word,
@@ -346,15 +326,26 @@ pub mod panic_count {
// panicking thread consumes at least 2 bytes of address space.
static GLOBAL_PANIC_COUNT: AtomicUsize = AtomicUsize::new(0);
+ // Return the state of the ALWAYS_ABORT_FLAG and number of panics.
+ //
+ // If ALWAYS_ABORT_FLAG is not set, the number is determined on a per-thread
+ // base (stored in LOCAL_PANIC_COUNT), i.e. it is the amount of recursive calls
+ // of the calling thread.
+ // If ALWAYS_ABORT_FLAG is set, the number equals the *global* number of panic
+ // calls. See above why LOCAL_PANIC_COUNT is not used.
pub fn increase() -> (bool, usize) {
- (
- GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed) & ALWAYS_ABORT_FLAG != 0,
+ let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed);
+ let must_abort = global_count & ALWAYS_ABORT_FLAG != 0;
+ let panics = if must_abort {
+ global_count & !ALWAYS_ABORT_FLAG
+ } else {
LOCAL_PANIC_COUNT.with(|c| {
let next = c.get() + 1;
c.set(next);
next
- }),
- )
+ })
+ };
+ (must_abort, panics)
}
pub fn decrease() {
@@ -397,7 +388,7 @@ pub mod panic_count {
}
// Slow path is in a separate function to reduce the amount of code
- // inlined from `is_zero`.
+ // inlined from `count_is_zero`.
#[inline(never)]
#[cold]
fn is_zero_slow_path() -> bool {
@@ -682,27 +673,26 @@ fn rust_panic_with_hook(
crate::sys::abort_internal();
}
- unsafe {
- let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
- let _guard = HOOK_LOCK.read();
- match HOOK {
- // Some platforms (like wasm) know that printing to stderr won't ever actually
- // print anything, and if that's the case we can skip the default
- // hook. Since string formatting happens lazily when calling `payload`
- // methods, this means we avoid formatting the string at all!
- // (The panic runtime might still call `payload.take_box()` though and trigger
- // formatting.)
- Hook::Default if panic_output().is_none() => {}
- Hook::Default => {
- info.set_payload(payload.get());
- default_hook(&info);
- }
- Hook::Custom(ptr) => {
- info.set_payload(payload.get());
- (*ptr)(&info);
- }
- };
- }
+ let mut info = PanicInfo::internal_constructor(message, location, can_unwind);
+ let hook = HOOK.read().unwrap_or_else(PoisonError::into_inner);
+ match *hook {
+ // Some platforms (like wasm) know that printing to stderr won't ever actually
+ // print anything, and if that's the case we can skip the default
+ // hook. Since string formatting happens lazily when calling `payload`
+ // methods, this means we avoid formatting the string at all!
+ // (The panic runtime might still call `payload.take_box()` though and trigger
+ // formatting.)
+ Hook::Default if panic_output().is_none() => {}
+ Hook::Default => {
+ info.set_payload(payload.get());
+ default_hook(&info);
+ }
+ Hook::Custom(ref hook) => {
+ info.set_payload(payload.get());
+ hook(&info);
+ }
+ };
+ drop(hook);
if panics > 1 || !can_unwind {
// If a thread panics while it's already unwinding then we
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 5dfeb517a..9d6328162 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2158,6 +2158,7 @@ impl Path {
/// assert_eq!(grand_parent.parent(), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "dirname")]
#[must_use]
pub fn parent(&self) -> Option<&Path> {
let mut comps = self.components();
@@ -2225,6 +2226,7 @@ impl Path {
/// assert_eq!(None, Path::new("/").file_name());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
+ #[doc(alias = "basename")]
#[must_use]
pub fn file_name(&self) -> Option<&OsStr> {
self.components().next_back().and_then(|p| match p {
@@ -2401,7 +2403,7 @@ impl Path {
self.file_name().map(split_file_at_dot).and_then(|(before, _after)| Some(before))
}
- /// Extracts the extension of [`self.file_name`], if possible.
+ /// Extracts the extension (without the leading dot) of [`self.file_name`], if possible.
///
/// The extension is:
///
diff --git a/library/std/src/personality/dwarf/eh.rs b/library/std/src/personality/dwarf/eh.rs
index 8799137b7..27b50c13b 100644
--- a/library/std/src/personality/dwarf/eh.rs
+++ b/library/std/src/personality/dwarf/eh.rs
@@ -98,9 +98,8 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
}
}
}
- // Ip is not present in the table. This should not happen... but it does: issue #35011.
- // So rather than returning EHAction::Terminate, we do this.
- Ok(EHAction::None)
+ // Ip is not present in the table. This indicates a nounwind call.
+ Ok(EHAction::Terminate)
} else {
// SjLj version:
// The "IP" is an index into the call-site table, with two exceptions:
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 242f44ade..331714a99 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -611,7 +611,19 @@ mod prim_pointer {}
///
/// Arrays coerce to [slices (`[T]`)][slice], so a slice method may be called on
/// an array. Indeed, this provides most of the API for working with arrays.
-/// Slices have a dynamic size and do not coerce to arrays.
+///
+/// Slices have a dynamic size and do not coerce to arrays. Instead, use
+/// `slice.try_into().unwrap()` or `<ArrayType>::try_from(slice).unwrap()`.
+///
+/// Array's `try_from(slice)` implementations (and the corresponding `slice.try_into()`
+/// array implementations) succeed if the input slice length is the same as the result
+/// array length. They optimize especially well when the optimizer can easily determine
+/// the slice length, e.g. `<[u8; 4]>::try_from(&slice[4..8]).unwrap()`. Array implements
+/// [TryFrom](crate::convert::TryFrom) returning:
+///
+/// - `[T; N]` copies from the slice's elements
+/// - `&[T; N]` references the original slice's elements
+/// - `&mut [T; N]` references the original slice's elements
///
/// You can move elements out of an array with a [slice pattern]. If you want
/// one element, see [`mem::replace`].
@@ -640,6 +652,15 @@ mod prim_pointer {}
/// for x in &array { }
/// ```
///
+/// You can use `<ArrayType>::try_from(slice)` or `slice.try_into()` to get an array from
+/// a slice:
+///
+/// ```
+/// let bytes: [u8; 3] = [1, 0, 2];
+/// assert_eq!(1, u16::from_le_bytes(<[u8; 2]>::try_from(&bytes[0..2]).unwrap()));
+/// assert_eq!(512, u16::from_le_bytes(bytes[1..3].try_into().unwrap()));
+/// ```
+///
/// You can use a [slice pattern] to move elements out of an array:
///
/// ```
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index d91d4fa64..400d25beb 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -1629,7 +1629,7 @@ impl ExitStatusError {
///
/// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`.
///
- /// Plain `code`, returning a plain integer, is provided because is is often more convenient.
+ /// Plain `code`, returning a plain integer, is provided because it is often more convenient.
/// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want
/// a type-level guarantee of nonzeroness.
///
@@ -2154,8 +2154,16 @@ pub fn id() -> u32 {
#[cfg_attr(not(test), lang = "termination")]
#[stable(feature = "termination_trait_lib", since = "1.61.0")]
#[rustc_on_unimplemented(
- message = "`main` has invalid return type `{Self}`",
- label = "`main` can only return types that implement `{Termination}`"
+ on(
+ all(not(bootstrap), cause = "MainFunctionType"),
+ message = "`main` has invalid return type `{Self}`",
+ label = "`main` can only return types that implement `{Termination}`"
+ ),
+ on(
+ bootstrap,
+ message = "`main` has invalid return type `{Self}`",
+ label = "`main` can only return types that implement `{Termination}`"
+ )
)]
pub trait Termination {
/// Is called to get the representation of the value as status code.
@@ -2200,9 +2208,7 @@ impl<T: Termination, E: fmt::Debug> Termination for Result<T, E> {
match self {
Ok(val) => val.report(),
Err(err) => {
- // Ignore error if the write fails, for example because stderr is
- // already closed. There is not much point panicking at this point.
- let _ = writeln!(io::stderr(), "Error: {err:?}");
+ io::attempt_print_to_stderr(format_args_nl!("Error: {err:?}"));
ExitCode::FAILURE
}
}
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 98f6cc7aa..9c2f0c1dd 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -89,7 +89,7 @@ macro_rules! rtunwrap {
// `src/tools/tidy/src/pal.rs` for more info. On all other platforms, `sigpipe`
// has a value, but its value is ignored.
//
-// Even though it is an `u8`, it only ever has 3 values. These are documented in
+// Even though it is an `u8`, it only ever has 4 values. These are documented in
// `compiler/rustc_session/src/config/sigpipe.rs`.
#[cfg_attr(test, allow(dead_code))]
unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
@@ -160,15 +160,12 @@ fn lang_start<T: crate::process::Termination + 'static>(
main: fn() -> T,
argc: isize,
argv: *const *const u8,
- #[cfg(not(bootstrap))] sigpipe: u8,
+ sigpipe: u8,
) -> isize {
let Ok(v) = lang_start_internal(
&move || crate::sys_common::backtrace::__rust_begin_short_backtrace(main).report().to_i32(),
argc,
argv,
- #[cfg(bootstrap)]
- 2, // Temporary inlining of sigpipe::DEFAULT until bootstrap stops being special
- #[cfg(not(bootstrap))]
sigpipe,
);
v
diff --git a/library/std/src/sync/mpsc/stream.rs b/library/std/src/sync/mpsc/stream.rs
index 4c3812c79..4592e9141 100644
--- a/library/std/src/sync/mpsc/stream.rs
+++ b/library/std/src/sync/mpsc/stream.rs
@@ -114,7 +114,7 @@ impl<T> Packet<T> {
match self.queue.producer_addition().cnt.fetch_add(1, Ordering::SeqCst) {
// As described in the mod's doc comment, -1 == wakeup
-1 => UpWoke(self.take_to_wake()),
- // As as described before, SPSC queues must be >= -2
+ // As described before, SPSC queues must be >= -2
-2 => UpSuccess,
// Be sure to preserve the disconnected state, and the return value
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index a7feea588..0f25417d6 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -3,99 +3,12 @@
//! This primitive is meant to be used to run one-time initialization. An
//! example use case would be for initializing an FFI library.
-// A "once" is a relatively simple primitive, and it's also typically provided
-// by the OS as well (see `pthread_once` or `InitOnceExecuteOnce`). The OS
-// primitives, however, tend to have surprising restrictions, such as the Unix
-// one doesn't allow an argument to be passed to the function.
-//
-// As a result, we end up implementing it ourselves in the standard library.
-// This also gives us the opportunity to optimize the implementation a bit which
-// should help the fast path on call sites. Consequently, let's explain how this
-// primitive works now!
-//
-// So to recap, the guarantees of a Once are that it will call the
-// initialization closure at most once, and it will never return until the one
-// that's running has finished running. This means that we need some form of
-// blocking here while the custom callback is running at the very least.
-// Additionally, we add on the restriction of **poisoning**. Whenever an
-// initialization closure panics, the Once enters a "poisoned" state which means
-// that all future calls will immediately panic as well.
-//
-// So to implement this, one might first reach for a `Mutex`, but those cannot
-// be put into a `static`. It also gets a lot harder with poisoning to figure
-// out when the mutex needs to be deallocated because it's not after the closure
-// finishes, but after the first successful closure finishes.
-//
-// All in all, this is instead implemented with atomics and lock-free
-// operations! Whee! Each `Once` has one word of atomic state, and this state is
-// CAS'd on to determine what to do. There are four possible state of a `Once`:
-//
-// * Incomplete - no initialization has run yet, and no thread is currently
-// using the Once.
-// * Poisoned - some thread has previously attempted to initialize the Once, but
-// it panicked, so the Once is now poisoned. There are no other
-// threads currently accessing this Once.
-// * Running - some thread is currently attempting to run initialization. It may
-// succeed, so all future threads need to wait for it to finish.
-// Note that this state is accompanied with a payload, described
-// below.
-// * Complete - initialization has completed and all future calls should finish
-// immediately.
-//
-// With 4 states we need 2 bits to encode this, and we use the remaining bits
-// in the word we have allocated as a queue of threads waiting for the thread
-// responsible for entering the RUNNING state. This queue is just a linked list
-// of Waiter nodes which is monotonically increasing in size. Each node is
-// allocated on the stack, and whenever the running closure finishes it will
-// consume the entire queue and notify all waiters they should try again.
-//
-// You'll find a few more details in the implementation, but that's the gist of
-// it!
-//
-// Atomic orderings:
-// When running `Once` we deal with multiple atomics:
-// `Once.state_and_queue` and an unknown number of `Waiter.signaled`.
-// * `state_and_queue` is used (1) as a state flag, (2) for synchronizing the
-// result of the `Once`, and (3) for synchronizing `Waiter` nodes.
-// - At the end of the `call_inner` function we have to make sure the result
-// of the `Once` is acquired. So every load which can be the only one to
-// load COMPLETED must have at least Acquire ordering, which means all
-// three of them.
-// - `WaiterQueue::Drop` is the only place that may store COMPLETED, and
-// must do so with Release ordering to make the result available.
-// - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and
-// needs to make the nodes available with Release ordering. The load in
-// its `compare_exchange` can be Relaxed because it only has to compare
-// the atomic, not to read other data.
-// - `WaiterQueue::Drop` must see the `Waiter` nodes, so it must load
-// `state_and_queue` with Acquire ordering.
-// - There is just one store where `state_and_queue` is used only as a
-// state flag, without having to synchronize data: switching the state
-// from INCOMPLETE to RUNNING in `call_inner`. This store can be Relaxed,
-// but the read has to be Acquire because of the requirements mentioned
-// above.
-// * `Waiter.signaled` is both used as a flag, and to protect a field with
-// interior mutability in `Waiter`. `Waiter.thread` is changed in
-// `WaiterQueue::Drop` which then sets `signaled` with Release ordering.
-// After `wait` loads `signaled` with Acquire and sees it is true, it needs to
-// see the changes to drop the `Waiter` struct correctly.
-// * There is one place where the two atomics `Once.state_and_queue` and
-// `Waiter.signaled` come together, and might be reordered by the compiler or
-// processor. Because both use Acquire ordering such a reordering is not
-// allowed, so no need for SeqCst.
-
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
-use crate::cell::Cell;
use crate::fmt;
-use crate::marker;
use crate::panic::{RefUnwindSafe, UnwindSafe};
-use crate::ptr;
-use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
-use crate::thread::{self, Thread};
-
-type Masked = ();
+use crate::sys_common::once as sys;
/// A synchronization primitive which can be used to run a one-time global
/// initialization. Useful for one-time initialization for FFI or related
@@ -114,19 +27,9 @@ type Masked = ();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Once {
- // `state_and_queue` is actually a pointer to a `Waiter` with extra state
- // bits, so we add the `PhantomData` appropriately.
- state_and_queue: AtomicPtr<Masked>,
- _marker: marker::PhantomData<*const Waiter>,
+ inner: sys::Once,
}
-// The `PhantomData` of a raw pointer removes these two auto traits, but we
-// enforce both below in the implementation so this should be safe to add.
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl Sync for Once {}
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl Send for Once {}
-
#[stable(feature = "sync_once_unwind_safe", since = "1.59.0")]
impl UnwindSafe for Once {}
@@ -136,10 +39,8 @@ impl RefUnwindSafe for Once {}
/// State yielded to [`Once::call_once_force()`]’s closure parameter. The state
/// can be used to query the poison status of the [`Once`].
#[stable(feature = "once_poison", since = "1.51.0")]
-#[derive(Debug)]
pub struct OnceState {
- poisoned: bool,
- set_state_on_drop_to: Cell<*mut Masked>,
+ pub(crate) inner: sys::OnceState,
}
/// Initialization value for static [`Once`] values.
@@ -159,38 +60,6 @@ pub struct OnceState {
)]
pub const ONCE_INIT: Once = Once::new();
-// Four states that a Once can be in, encoded into the lower bits of
-// `state_and_queue` in the Once structure.
-const INCOMPLETE: usize = 0x0;
-const POISONED: usize = 0x1;
-const RUNNING: usize = 0x2;
-const COMPLETE: usize = 0x3;
-
-// Mask to learn about the state. All other bits are the queue of waiters if
-// this is in the RUNNING state.
-const STATE_MASK: usize = 0x3;
-
-// Representation of a node in the linked list of waiters, used while in the
-// RUNNING state.
-// Note: `Waiter` can't hold a mutable pointer to the next thread, because then
-// `wait` would both hand out a mutable reference to its `Waiter` node, and keep
-// a shared reference to check `signaled`. Instead we hold shared references and
-// use interior mutability.
-#[repr(align(4))] // Ensure the two lower bits are free to use as state bits.
-struct Waiter {
- thread: Cell<Option<Thread>>,
- signaled: AtomicBool,
- next: *const Waiter,
-}
-
-// Head of a linked list of waiters.
-// Every node is a struct on the stack of a waiting thread.
-// Will wake up the waiters when it gets dropped, i.e. also on panic.
-struct WaiterQueue<'a> {
- state_and_queue: &'a AtomicPtr<Masked>,
- set_state_on_drop_to: *mut Masked,
-}
-
impl Once {
/// Creates a new `Once` value.
#[inline]
@@ -198,10 +67,7 @@ impl Once {
#[rustc_const_stable(feature = "const_once_new", since = "1.32.0")]
#[must_use]
pub const fn new() -> Once {
- Once {
- state_and_queue: AtomicPtr::new(ptr::invalid_mut(INCOMPLETE)),
- _marker: marker::PhantomData,
- }
+ Once { inner: sys::Once::new() }
}
/// Performs an initialization routine once and only once. The given closure
@@ -261,6 +127,7 @@ impl Once {
/// This is similar to [poisoning with mutexes][poison].
///
/// [poison]: struct.Mutex.html#poisoning
+ #[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[track_caller]
pub fn call_once<F>(&self, f: F)
@@ -268,12 +135,12 @@ impl Once {
F: FnOnce(),
{
// Fast path check
- if self.is_completed() {
+ if self.inner.is_completed() {
return;
}
let mut f = Some(f);
- self.call_inner(false, &mut |_| f.take().unwrap()());
+ self.inner.call(false, &mut |_| f.take().unwrap()());
}
/// Performs the same function as [`call_once()`] except ignores poisoning.
@@ -320,18 +187,19 @@ impl Once {
/// // once any success happens, we stop propagating the poison
/// INIT.call_once(|| {});
/// ```
+ #[inline]
#[stable(feature = "once_poison", since = "1.51.0")]
pub fn call_once_force<F>(&self, f: F)
where
F: FnOnce(&OnceState),
{
// Fast path check
- if self.is_completed() {
+ if self.inner.is_completed() {
return;
}
let mut f = Some(f);
- self.call_inner(true, &mut |p| f.take().unwrap()(p));
+ self.inner.call(true, &mut |p| f.take().unwrap()(p));
}
/// Returns `true` if some [`call_once()`] call has completed
@@ -378,119 +246,7 @@ impl Once {
#[stable(feature = "once_is_completed", since = "1.43.0")]
#[inline]
pub fn is_completed(&self) -> bool {
- // An `Acquire` load is enough because that makes all the initialization
- // operations visible to us, and, this being a fast path, weaker
- // ordering helps with performance. This `Acquire` synchronizes with
- // `Release` operations on the slow path.
- self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE
- }
-
- // This is a non-generic function to reduce the monomorphization cost of
- // using `call_once` (this isn't exactly a trivial or small implementation).
- //
- // Additionally, this is tagged with `#[cold]` as it should indeed be cold
- // and it helps let LLVM know that calls to this function should be off the
- // fast path. Essentially, this should help generate more straight line code
- // in LLVM.
- //
- // Finally, this takes an `FnMut` instead of a `FnOnce` because there's
- // currently no way to take an `FnOnce` and call it via virtual dispatch
- // without some allocation overhead.
- #[cold]
- #[track_caller]
- fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) {
- let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
- loop {
- match state_and_queue.addr() {
- COMPLETE => break,
- POISONED if !ignore_poisoning => {
- // Panic to propagate the poison.
- panic!("Once instance has previously been poisoned");
- }
- POISONED | INCOMPLETE => {
- // Try to register this thread as the one RUNNING.
- let exchange_result = self.state_and_queue.compare_exchange(
- state_and_queue,
- ptr::invalid_mut(RUNNING),
- Ordering::Acquire,
- Ordering::Acquire,
- );
- if let Err(old) = exchange_result {
- state_and_queue = old;
- continue;
- }
- // `waiter_queue` will manage other waiting threads, and
- // wake them up on drop.
- let mut waiter_queue = WaiterQueue {
- state_and_queue: &self.state_and_queue,
- set_state_on_drop_to: ptr::invalid_mut(POISONED),
- };
- // Run the initialization function, letting it know if we're
- // poisoned or not.
- let init_state = OnceState {
- poisoned: state_and_queue.addr() == POISONED,
- set_state_on_drop_to: Cell::new(ptr::invalid_mut(COMPLETE)),
- };
- init(&init_state);
- waiter_queue.set_state_on_drop_to = init_state.set_state_on_drop_to.get();
- break;
- }
- _ => {
- // All other values must be RUNNING with possibly a
- // pointer to the waiter queue in the more significant bits.
- assert!(state_and_queue.addr() & STATE_MASK == RUNNING);
- wait(&self.state_and_queue, state_and_queue);
- state_and_queue = self.state_and_queue.load(Ordering::Acquire);
- }
- }
- }
- }
-}
-
-fn wait(state_and_queue: &AtomicPtr<Masked>, mut current_state: *mut Masked) {
- // Note: the following code was carefully written to avoid creating a
- // mutable reference to `node` that gets aliased.
- loop {
- // Don't queue this thread if the status is no longer running,
- // otherwise we will not be woken up.
- if current_state.addr() & STATE_MASK != RUNNING {
- return;
- }
-
- // Create the node for our current thread.
- let node = Waiter {
- thread: Cell::new(Some(thread::current())),
- signaled: AtomicBool::new(false),
- next: current_state.with_addr(current_state.addr() & !STATE_MASK) as *const Waiter,
- };
- let me = &node as *const Waiter as *const Masked as *mut Masked;
-
- // Try to slide in the node at the head of the linked list, making sure
- // that another thread didn't just replace the head of the linked list.
- let exchange_result = state_and_queue.compare_exchange(
- current_state,
- me.with_addr(me.addr() | RUNNING),
- Ordering::Release,
- Ordering::Relaxed,
- );
- if let Err(old) = exchange_result {
- current_state = old;
- continue;
- }
-
- // We have enqueued ourselves, now lets wait.
- // It is important not to return before being signaled, otherwise we
- // would drop our `Waiter` node and leave a hole in the linked list
- // (and a dangling reference). Guard against spurious wakeups by
- // reparking ourselves until we are signaled.
- while !node.signaled.load(Ordering::Acquire) {
- // If the managing thread happens to signal and unpark us before we
- // can park ourselves, the result could be this thread never gets
- // unparked. Luckily `park` comes with the guarantee that if it got
- // an `unpark` just before on an unparked thread it does not park.
- thread::park();
- }
- break;
+ self.inner.is_completed()
}
}
@@ -501,37 +257,6 @@ impl fmt::Debug for Once {
}
}
-impl Drop for WaiterQueue<'_> {
- fn drop(&mut self) {
- // Swap out our state with however we finished.
- let state_and_queue =
- self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel);
-
- // We should only ever see an old state which was RUNNING.
- assert_eq!(state_and_queue.addr() & STATE_MASK, RUNNING);
-
- // Walk the entire linked list of waiters and wake them up (in lifo
- // order, last to register is first to wake up).
- unsafe {
- // Right after setting `node.signaled = true` the other thread may
- // free `node` if there happens to be has a spurious wakeup.
- // So we have to take out the `thread` field and copy the pointer to
- // `next` first.
- let mut queue =
- state_and_queue.with_addr(state_and_queue.addr() & !STATE_MASK) as *const Waiter;
- while !queue.is_null() {
- let next = (*queue).next;
- let thread = (*queue).thread.take().unwrap();
- (*queue).signaled.store(true, Ordering::Release);
- // ^- FIXME (maybe): This is another case of issue #55005
- // `store()` has a potentially dangling ref to `signaled`.
- queue = next;
- thread.unpark();
- }
- }
- }
-}
-
impl OnceState {
/// Returns `true` if the associated [`Once`] was poisoned prior to the
/// invocation of the closure passed to [`Once::call_once_force()`].
@@ -568,13 +293,22 @@ impl OnceState {
/// assert!(!state.is_poisoned());
/// });
#[stable(feature = "once_poison", since = "1.51.0")]
+ #[inline]
pub fn is_poisoned(&self) -> bool {
- self.poisoned
+ self.inner.is_poisoned()
}
/// Poison the associated [`Once`] without explicitly panicking.
- // NOTE: This is currently only exposed for the `lazy` module
+ // NOTE: This is currently only exposed for `OnceLock`.
+ #[inline]
pub(crate) fn poison(&self) {
- self.set_state_on_drop_to.set(ptr::invalid_mut(POISONED));
+ self.inner.poison();
+ }
+}
+
+#[stable(feature = "std_debug", since = "1.16.0")]
+impl fmt::Debug for OnceState {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("OnceState").field("poisoned", &self.is_poisoned()).finish()
}
}
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index 9ab781561..8b3877607 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -76,6 +76,7 @@ use crate::sys_common::rwlock as sys;
///
/// [`Mutex`]: super::Mutex
#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")]
pub struct RwLock<T: ?Sized> {
inner: sys::MovableRwLock,
poison: poison::Flag,
@@ -166,7 +167,7 @@ impl<T> RwLock<T> {
}
impl<T: ?Sized> RwLock<T> {
- /// Locks this rwlock with shared read access, blocking the current thread
+ /// Locks this `RwLock` with shared read access, blocking the current thread
/// until it can be acquired.
///
/// The calling thread will be blocked until there are no more writers which
@@ -180,9 +181,10 @@ impl<T: ?Sized> RwLock<T> {
///
/// # Errors
///
- /// This function will return an error if the RwLock is poisoned. An RwLock
- /// is poisoned whenever a writer panics while holding an exclusive lock.
- /// The failure will occur immediately after the lock has been acquired.
+ /// This function will return an error if the `RwLock` is poisoned. An
+ /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+ /// lock. The failure will occur immediately after the lock has been
+ /// acquired.
///
/// # Panics
///
@@ -214,7 +216,7 @@ impl<T: ?Sized> RwLock<T> {
}
}
- /// Attempts to acquire this rwlock with shared read access.
+ /// Attempts to acquire this `RwLock` with shared read access.
///
/// If the access could not be granted at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the shared access
@@ -227,13 +229,13 @@ impl<T: ?Sized> RwLock<T> {
///
/// # Errors
///
- /// This function will return the [`Poisoned`] error if the RwLock is poisoned.
- /// An RwLock is poisoned whenever a writer panics while holding an exclusive
- /// lock. `Poisoned` will only be returned if the lock would have otherwise been
- /// acquired.
+ /// This function will return the [`Poisoned`] error if the `RwLock` is
+ /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
+ /// an exclusive lock. `Poisoned` will only be returned if the lock would
+ /// have otherwise been acquired.
///
- /// This function will return the [`WouldBlock`] error if the RwLock could not
- /// be acquired because it was already locked exclusively.
+ /// This function will return the [`WouldBlock`] error if the `RwLock` could
+ /// not be acquired because it was already locked exclusively.
///
/// [`Poisoned`]: TryLockError::Poisoned
/// [`WouldBlock`]: TryLockError::WouldBlock
@@ -262,20 +264,20 @@ impl<T: ?Sized> RwLock<T> {
}
}
- /// Locks this rwlock with exclusive write access, blocking the current
+ /// Locks this `RwLock` with exclusive write access, blocking the current
/// thread until it can be acquired.
///
/// This function will not return while other writers or other readers
/// currently have access to the lock.
///
- /// Returns an RAII guard which will drop the write access of this rwlock
+ /// Returns an RAII guard which will drop the write access of this `RwLock`
/// when dropped.
///
/// # Errors
///
- /// This function will return an error if the RwLock is poisoned. An RwLock
- /// is poisoned whenever a writer panics while holding an exclusive lock.
- /// An error will be returned when the lock is acquired.
+ /// This function will return an error if the `RwLock` is poisoned. An
+ /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+ /// lock. An error will be returned when the lock is acquired.
///
/// # Panics
///
@@ -302,7 +304,7 @@ impl<T: ?Sized> RwLock<T> {
}
}
- /// Attempts to lock this rwlock with exclusive write access.
+ /// Attempts to lock this `RwLock` with exclusive write access.
///
/// If the lock could not be acquired at this time, then `Err` is returned.
/// Otherwise, an RAII guard is returned which will release the lock when
@@ -315,13 +317,13 @@ impl<T: ?Sized> RwLock<T> {
///
/// # Errors
///
- /// This function will return the [`Poisoned`] error if the RwLock is
- /// poisoned. An RwLock is poisoned whenever a writer panics while holding
- /// an exclusive lock. `Poisoned` will only be returned if the lock would have
- /// otherwise been acquired.
+ /// This function will return the [`Poisoned`] error if the `RwLock` is
+ /// poisoned. An `RwLock` is poisoned whenever a writer panics while holding
+ /// an exclusive lock. `Poisoned` will only be returned if the lock would
+ /// have otherwise been acquired.
///
- /// This function will return the [`WouldBlock`] error if the RwLock could not
- /// be acquired because it was already locked exclusively.
+ /// This function will return the [`WouldBlock`] error if the `RwLock` could
+ /// not be acquired because it was already locked exclusively.
///
/// [`Poisoned`]: TryLockError::Poisoned
/// [`WouldBlock`]: TryLockError::WouldBlock
@@ -421,10 +423,10 @@ impl<T: ?Sized> RwLock<T> {
///
/// # Errors
///
- /// This function will return an error if the RwLock is poisoned. An RwLock
- /// is poisoned whenever a writer panics while holding an exclusive lock. An
- /// error will only be returned if the lock would have otherwise been
- /// acquired.
+ /// This function will return an error if the `RwLock` is poisoned. An
+ /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+ /// lock. An error will only be returned if the lock would have otherwise
+ /// been acquired.
///
/// # Examples
///
@@ -454,10 +456,10 @@ impl<T: ?Sized> RwLock<T> {
///
/// # Errors
///
- /// This function will return an error if the RwLock is poisoned. An RwLock
- /// is poisoned whenever a writer panics while holding an exclusive lock. An
- /// error will only be returned if the lock would have otherwise been
- /// acquired.
+ /// This function will return an error if the `RwLock` is poisoned. An
+ /// `RwLock` is poisoned whenever a writer panics while holding an exclusive
+ /// lock. An error will only be returned if the lock would have otherwise
+ /// been acquired.
///
/// # Examples
///
diff --git a/library/std/src/sys/common/mod.rs b/library/std/src/sys/common/mod.rs
index ff64d2aa8..29fc0835d 100644
--- a/library/std/src/sys/common/mod.rs
+++ b/library/std/src/sys/common/mod.rs
@@ -11,3 +11,7 @@
#![allow(dead_code)]
pub mod alloc;
+pub mod small_c_string;
+
+#[cfg(test)]
+mod tests;
diff --git a/library/std/src/sys/common/small_c_string.rs b/library/std/src/sys/common/small_c_string.rs
new file mode 100644
index 000000000..01acd5191
--- /dev/null
+++ b/library/std/src/sys/common/small_c_string.rs
@@ -0,0 +1,58 @@
+use crate::ffi::{CStr, CString};
+use crate::mem::MaybeUninit;
+use crate::path::Path;
+use crate::slice;
+use crate::{io, ptr};
+
+// Make sure to stay under 4096 so the compiler doesn't insert a probe frame:
+// https://docs.rs/compiler_builtins/latest/compiler_builtins/probestack/index.html
+#[cfg(not(target_os = "espidf"))]
+const MAX_STACK_ALLOCATION: usize = 384;
+#[cfg(target_os = "espidf")]
+const MAX_STACK_ALLOCATION: usize = 32;
+
+const NUL_ERR: io::Error =
+ io::const_io_error!(io::ErrorKind::InvalidInput, "file name contained an unexpected NUL byte");
+
+#[inline]
+pub fn run_path_with_cstr<T, F>(path: &Path, f: F) -> io::Result<T>
+where
+ F: FnOnce(&CStr) -> io::Result<T>,
+{
+ run_with_cstr(path.as_os_str().bytes(), f)
+}
+
+#[inline]
+pub fn run_with_cstr<T, F>(bytes: &[u8], f: F) -> io::Result<T>
+where
+ F: FnOnce(&CStr) -> io::Result<T>,
+{
+ if bytes.len() >= MAX_STACK_ALLOCATION {
+ return run_with_cstr_allocating(bytes, f);
+ }
+
+ let mut buf = MaybeUninit::<[u8; MAX_STACK_ALLOCATION]>::uninit();
+ let buf_ptr = buf.as_mut_ptr() as *mut u8;
+
+ unsafe {
+ ptr::copy_nonoverlapping(bytes.as_ptr(), buf_ptr, bytes.len());
+ buf_ptr.add(bytes.len()).write(0);
+ }
+
+ match CStr::from_bytes_with_nul(unsafe { slice::from_raw_parts(buf_ptr, bytes.len() + 1) }) {
+ Ok(s) => f(s),
+ Err(_) => Err(NUL_ERR),
+ }
+}
+
+#[cold]
+#[inline(never)]
+fn run_with_cstr_allocating<T, F>(bytes: &[u8], f: F) -> io::Result<T>
+where
+ F: FnOnce(&CStr) -> io::Result<T>,
+{
+ match CString::new(bytes) {
+ Ok(s) => f(&s),
+ Err(_) => Err(NUL_ERR),
+ }
+}
diff --git a/library/std/src/sys/common/tests.rs b/library/std/src/sys/common/tests.rs
new file mode 100644
index 000000000..fb6f5d6af
--- /dev/null
+++ b/library/std/src/sys/common/tests.rs
@@ -0,0 +1,66 @@
+use crate::ffi::CString;
+use crate::hint::black_box;
+use crate::path::Path;
+use crate::sys::common::small_c_string::run_path_with_cstr;
+use core::iter::repeat;
+
+#[test]
+fn stack_allocation_works() {
+ let path = Path::new("abc");
+ let result = run_path_with_cstr(path, |p| {
+ assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+ Ok(42)
+ });
+ assert_eq!(result.unwrap(), 42);
+}
+
+#[test]
+fn stack_allocation_fails() {
+ let path = Path::new("ab\0");
+ assert!(run_path_with_cstr::<(), _>(path, |_| unreachable!()).is_err());
+}
+
+#[test]
+fn heap_allocation_works() {
+ let path = repeat("a").take(384).collect::<String>();
+ let path = Path::new(&path);
+ let result = run_path_with_cstr(path, |p| {
+ assert_eq!(p, &*CString::new(path.as_os_str().bytes()).unwrap());
+ Ok(42)
+ });
+ assert_eq!(result.unwrap(), 42);
+}
+
+#[test]
+fn heap_allocation_fails() {
+ let mut path = repeat("a").take(384).collect::<String>();
+ path.push('\0');
+ let path = Path::new(&path);
+ assert!(run_path_with_cstr::<(), _>(path, |_| unreachable!()).is_err());
+}
+
+#[bench]
+fn bench_stack_path_alloc(b: &mut test::Bencher) {
+ let path = repeat("a").take(383).collect::<String>();
+ let p = Path::new(&path);
+ b.iter(|| {
+ run_path_with_cstr(p, |cstr| {
+ black_box(cstr);
+ Ok(())
+ })
+ .unwrap();
+ });
+}
+
+#[bench]
+fn bench_heap_path_alloc(b: &mut test::Bencher) {
+ let path = repeat("a").take(384).collect::<String>();
+ let p = Path::new(&path);
+ b.iter(|| {
+ run_path_with_cstr(p, |cstr| {
+ black_box(cstr);
+ Ok(())
+ })
+ .unwrap();
+ });
+}
diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs
index 1c7e1dd8d..afcae6c90 100644
--- a/library/std/src/sys/hermit/args.rs
+++ b/library/std/src/sys/hermit/args.rs
@@ -1,20 +1,37 @@
-use crate::ffi::OsString;
+use crate::ffi::{c_char, CStr, OsString};
use crate::fmt;
+use crate::os::unix::ffi::OsStringExt;
+use crate::ptr;
+use crate::sync::atomic::{
+ AtomicIsize, AtomicPtr,
+ Ordering::{Acquire, Relaxed, Release},
+};
use crate::vec;
+static ARGC: AtomicIsize = AtomicIsize::new(0);
+static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut());
+
/// One-time global initialization.
pub unsafe fn init(argc: isize, argv: *const *const u8) {
- imp::init(argc, argv)
-}
-
-/// One-time global cleanup.
-pub unsafe fn cleanup() {
- imp::cleanup()
+ ARGC.store(argc, Relaxed);
+ // Use release ordering here to broadcast writes by the OS.
+ ARGV.store(argv as *mut *const u8, Release);
}
/// Returns the command line arguments
pub fn args() -> Args {
- imp::args()
+ // Synchronize with the store above.
+ let argv = ARGV.load(Acquire);
+ // If argv has not been initialized yet, do not return any arguments.
+ let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) };
+ let args: Vec<OsString> = (0..argc)
+ .map(|i| unsafe {
+ let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char);
+ OsStringExt::from_vec(cstr.to_bytes().to_vec())
+ })
+ .collect();
+
+ Args { iter: args.into_iter() }
}
pub struct Args {
@@ -51,44 +68,3 @@ impl DoubleEndedIterator for Args {
self.iter.next_back()
}
}
-
-mod imp {
- use super::Args;
- use crate::ffi::{CStr, OsString};
- use crate::os::unix::ffi::OsStringExt;
- use crate::ptr;
-
- use crate::sys_common::mutex::StaticMutex;
-
- static mut ARGC: isize = 0;
- static mut ARGV: *const *const u8 = ptr::null();
- static LOCK: StaticMutex = StaticMutex::new();
-
- pub unsafe fn init(argc: isize, argv: *const *const u8) {
- let _guard = LOCK.lock();
- ARGC = argc;
- ARGV = argv;
- }
-
- pub unsafe fn cleanup() {
- let _guard = LOCK.lock();
- ARGC = 0;
- ARGV = ptr::null();
- }
-
- pub fn args() -> Args {
- Args { iter: clone().into_iter() }
- }
-
- fn clone() -> Vec<OsString> {
- unsafe {
- let _guard = LOCK.lock();
- (0..ARGC)
- .map(|i| {
- let cstr = CStr::from_ptr(*ARGV.offset(i) as *const i8);
- OsStringExt::from_vec(cstr.to_bytes().to_vec())
- })
- .collect()
- }
- }
-}
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index f921839cf..af297ff1e 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -1,3 +1,4 @@
+use crate::convert::TryFrom;
use crate::ffi::{CStr, CString, OsString};
use crate::fmt;
use crate::hash::{Hash, Hasher};
@@ -5,6 +6,7 @@ use crate::io::{self, Error, ErrorKind};
use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
use crate::os::unix::ffi::OsStrExt;
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};
@@ -15,10 +17,6 @@ use crate::sys::unsupported;
pub use crate::sys_common::fs::{copy, try_exists};
//pub use crate::sys_common::fs::remove_dir_all;
-fn cstr(path: &Path) -> io::Result<CString> {
- Ok(CString::new(path.as_os_str().as_bytes())?)
-}
-
#[derive(Debug)]
pub struct File(FileDesc);
@@ -272,8 +270,7 @@ impl OpenOptions {
impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
- let path = cstr(path)?;
- File::open_c(&path, opts)
+ run_path_with_cstr(path, |path| File::open_c(&path, opts))
}
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
@@ -373,9 +370,7 @@ pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
}
pub fn unlink(path: &Path) -> io::Result<()> {
- let name = cstr(path)?;
- let _ = unsafe { cvt(abi::unlink(name.as_ptr()))? };
- Ok(())
+ run_path_with_cstr(path, |path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ()))
}
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 827d82900..e6534df89 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -106,9 +106,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
-pub unsafe fn cleanup() {
- args::cleanup();
-}
+pub unsafe fn cleanup() {}
#[cfg(not(test))]
#[no_mangle]
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index 167c918c9..c080c176a 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -22,7 +22,7 @@
#![allow(missing_debug_implementations)]
-mod common;
+pub mod common;
cfg_if::cfg_if! {
if #[cfg(unix)] {
diff --git a/library/std/src/sys/sgx/abi/tls/mod.rs b/library/std/src/sys/sgx/abi/tls/mod.rs
index 13d96e9a6..09c4ab3d3 100644
--- a/library/std/src/sys/sgx/abi/tls/mod.rs
+++ b/library/std/src/sys/sgx/abi/tls/mod.rs
@@ -111,6 +111,7 @@ impl Tls {
rtabort!("TLS limit exceeded")
};
TLS_DESTRUCTOR[index].store(dtor.map_or(0, |f| f as usize), Ordering::Relaxed);
+ unsafe { Self::current() }.data[index].set(ptr::null_mut());
Key::from_index(index)
}
diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
index 5409bd177..0d934318c 100644
--- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
@@ -316,9 +316,9 @@ where
// | small1 | Chunk smaller than 8 bytes
// +--------+
fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
- let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 };
- let small1_size = (len - small0_size as usize) % 8;
- let big_size = len - small0_size as usize - small1_size as usize;
+ let small0_size = if ptr.is_aligned_to(8) { 0 } else { 8 - ptr.addr() % 8 };
+ let small1_size = (len - small0_size) % 8;
+ let big_size = len - small0_size - small1_size;
(small0_size, big_size, small1_size)
}
@@ -364,8 +364,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
mfence
lfence
",
- val = in(reg_byte) *src.offset(off as isize),
- dst = in(reg) dst.offset(off as isize),
+ val = in(reg_byte) *src.add(off),
+ dst = in(reg) dst.add(off),
seg_sel = in(reg) &mut seg_sel,
options(nostack, att_syntax)
);
@@ -378,8 +378,8 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
assert!(is_enclave_range(src, len));
assert!(is_user_range(dst, len));
assert!(len < isize::MAX as usize);
- assert!(!(src as usize).overflowing_add(len).1);
- assert!(!(dst as usize).overflowing_add(len).1);
+ assert!(!src.addr().overflowing_add(len).1);
+ assert!(!dst.addr().overflowing_add(len).1);
if len < 8 {
// Can't align on 8 byte boundary: copy safely byte per byte
@@ -404,17 +404,17 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
unsafe {
// Copy small0
- copy_bytewise_to_userspace(src, dst, small0_size as _);
+ copy_bytewise_to_userspace(src, dst, small0_size);
// Copy big
- let big_src = src.offset(small0_size as _);
- let big_dst = dst.offset(small0_size as _);
- copy_quadwords(big_src as _, big_dst, big_size);
+ let big_src = src.add(small0_size);
+ let big_dst = dst.add(small0_size);
+ copy_quadwords(big_src, big_dst, big_size);
// Copy small1
- let small1_src = src.offset(big_size as isize + small0_size as isize);
- let small1_dst = dst.offset(big_size as isize + small0_size as isize);
- copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _);
+ let small1_src = src.add(big_size + small0_size);
+ let small1_dst = dst.add(big_size + small0_size);
+ copy_bytewise_to_userspace(small1_src, small1_dst, small1_size);
}
}
}
diff --git a/library/std/src/sys/sgx/thread_local_key.rs b/library/std/src/sys/sgx/thread_local_key.rs
index b21784475..c7a57d3a3 100644
--- a/library/std/src/sys/sgx/thread_local_key.rs
+++ b/library/std/src/sys/sgx/thread_local_key.rs
@@ -21,8 +21,3 @@ pub unsafe fn get(key: Key) -> *mut u8 {
pub unsafe fn destroy(key: Key) {
Tls::destroy(AbiKey::from_usize(key))
}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
- false
-}
diff --git a/library/std/src/sys/solid/fs.rs b/library/std/src/sys/solid/fs.rs
index 969222253..6c66b93a3 100644
--- a/library/std/src/sys/solid/fs.rs
+++ b/library/std/src/sys/solid/fs.rs
@@ -175,15 +175,19 @@ impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
fn next(&mut self) -> Option<io::Result<DirEntry>> {
- unsafe {
- let mut out_dirent = MaybeUninit::uninit();
- error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir(
+ let entry = unsafe {
+ let mut out_entry = MaybeUninit::uninit();
+ match error::SolidError::err_if_negative(abi::SOLID_FS_ReadDir(
self.inner.dirp,
- out_dirent.as_mut_ptr(),
- ))
- .ok()?;
- Some(Ok(DirEntry { entry: out_dirent.assume_init(), inner: Arc::clone(&self.inner) }))
- }
+ out_entry.as_mut_ptr(),
+ )) {
+ Ok(_) => out_entry.assume_init(),
+ Err(e) if e.as_raw() == abi::SOLID_ERR_NOTFOUND => return None,
+ Err(e) => return Some(Err(e.as_io_error())),
+ }
+ };
+
+ (entry.d_name[0] != 0).then(|| Ok(DirEntry { entry, inner: Arc::clone(&self.inner) }))
}
}
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index b5649d6e0..4906c6268 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -1,4 +1,5 @@
use super::unsupported;
+use crate::convert::TryFrom;
use crate::error::Error as StdError;
use crate::ffi::{CStr, CString, OsStr, OsString};
use crate::fmt;
@@ -8,7 +9,8 @@ use crate::os::{
solid::ffi::{OsStrExt, OsStringExt},
};
use crate::path::{self, PathBuf};
-use crate::sys_common::rwlock::StaticRwLock;
+use crate::sync::RwLock;
+use crate::sys::common::small_c_string::run_with_cstr;
use crate::vec;
use super::{error, itron, memchr};
@@ -78,7 +80,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
}
-static ENV_LOCK: StaticRwLock = StaticRwLock::new();
+static ENV_LOCK: RwLock<()> = RwLock::new(());
pub struct Env {
iter: vec::IntoIter<(OsString, OsString)>,
@@ -139,35 +141,33 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
- let k = CString::new(k.as_bytes()).ok()?;
- unsafe {
+ let s = run_with_cstr(k.as_bytes(), |k| {
let _guard = ENV_LOCK.read();
- let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
- if s.is_null() {
- None
- } else {
- Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
- }
+ Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
+ })
+ .ok()?;
+
+ if s.is_null() {
+ None
+ } else {
+ Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
- let k = CString::new(k.as_bytes())?;
- let v = CString::new(v.as_bytes())?;
-
- unsafe {
- let _guard = ENV_LOCK.write();
- cvt_env(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
- }
+ run_with_cstr(k.as_bytes(), |k| {
+ run_with_cstr(v.as_bytes(), |v| {
+ let _guard = ENV_LOCK.write();
+ cvt_env(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
+ })
+ })
}
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
- let nbuf = CString::new(n.as_bytes())?;
-
- unsafe {
+ run_with_cstr(n.as_bytes(), |nbuf| {
let _guard = ENV_LOCK.write();
- cvt_env(libc::unsetenv(nbuf.as_ptr())).map(drop)
- }
+ cvt_env(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
+ })
}
/// In kmclib, `setenv` and `unsetenv` don't always set `errno`, so this
diff --git a/library/std/src/sys/solid/thread_local_key.rs b/library/std/src/sys/solid/thread_local_key.rs
index b17521f70..b37bf9996 100644
--- a/library/std/src/sys/solid/thread_local_key.rs
+++ b/library/std/src/sys/solid/thread_local_key.rs
@@ -19,8 +19,3 @@ pub unsafe fn get(_key: Key) -> *mut u8 {
pub unsafe fn destroy(_key: Key) {
panic!("should not be used on the solid target");
}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
- panic!("should not be used on the solid target");
-}
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index cc347e358..37a49f2d7 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1,13 +1,26 @@
+// miri has some special hacks here that make things unused.
+#![cfg_attr(miri, allow(unused))]
+
use crate::os::unix::prelude::*;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
use crate::mem;
+#[cfg(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "solaris",
+ target_os = "fuchsia",
+ target_os = "redox",
+ target_os = "illumos"
+))]
+use crate::mem::MaybeUninit;
use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
use crate::path::{Path, PathBuf};
use crate::ptr;
use crate::sync::Arc;
+use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::fd::FileDesc;
use crate::sys::time::SystemTime;
use crate::sys::{cvt, cvt_r};
@@ -260,7 +273,7 @@ pub struct DirEntry {
// We need to store an owned copy of the entry name on platforms that use
// readdir() (not readdir_r()), because a) struct dirent may use a flexible
// array to store the name, b) it lives only until the next readdir() call.
- name: CString,
+ name: crate::ffi::CString,
}
// Define a minimal subset of fields we need from `dirent64`, especially since
@@ -313,8 +326,11 @@ pub struct FilePermissions {
mode: mode_t,
}
-#[derive(Copy, Clone)]
-pub struct FileTimes([libc::timespec; 2]);
+#[derive(Copy, Clone, Debug, Default)]
+pub struct FileTimes {
+ accessed: Option<SystemTime>,
+ modified: Option<SystemTime>,
+}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct FileType {
@@ -512,45 +528,11 @@ impl FilePermissions {
impl FileTimes {
pub fn set_accessed(&mut self, t: SystemTime) {
- self.0[0] = t.t.to_timespec().expect("Invalid system time");
+ self.accessed = Some(t);
}
pub fn set_modified(&mut self, t: SystemTime) {
- self.0[1] = t.t.to_timespec().expect("Invalid system time");
- }
-}
-
-struct TimespecDebugAdapter<'a>(&'a libc::timespec);
-
-impl fmt::Debug for TimespecDebugAdapter<'_> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("timespec")
- .field("tv_sec", &self.0.tv_sec)
- .field("tv_nsec", &self.0.tv_nsec)
- .finish()
- }
-}
-
-impl fmt::Debug for FileTimes {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.debug_struct("FileTimes")
- .field("accessed", &TimespecDebugAdapter(&self.0[0]))
- .field("modified", &TimespecDebugAdapter(&self.0[1]))
- .finish()
- }
-}
-
-impl Default for FileTimes {
- fn default() -> Self {
- // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return
- // an error in `set_times`.
- // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
- // the same as for Redox.
- #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))]
- let omit = libc::timespec { tv_sec: 0, tv_nsec: 0 };
- #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
- let omit = libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ };
- Self([omit; 2])
+ self.modified = Some(t);
}
}
@@ -614,33 +596,69 @@ impl Iterator for ReadDir {
};
}
- // Only d_reclen bytes of *entry_ptr are valid, so we can't just copy the
- // whole thing (#93384). Instead, copy everything except the name.
- let mut copy: dirent64 = mem::zeroed();
- // Can't dereference entry_ptr, so use the local entry to get
- // offsetof(struct dirent, d_name)
- let copy_bytes = &mut copy as *mut _ as *mut u8;
- let copy_name = &mut copy.d_name as *mut _ as *mut u8;
- let name_offset = copy_name.offset_from(copy_bytes) as usize;
- let entry_bytes = entry_ptr as *const u8;
- let entry_name = entry_bytes.add(name_offset);
- ptr::copy_nonoverlapping(entry_bytes, copy_bytes, name_offset);
+ // The dirent64 struct is a weird imaginary thing that isn't ever supposed
+ // to be worked with by value. Its trailing d_name field is declared
+ // variously as [c_char; 256] or [c_char; 1] on different systems but
+ // either way that size is meaningless; only the offset of d_name is
+ // meaningful. The dirent64 pointers that libc returns from readdir64 are
+ // allowed to point to allocations smaller _or_ LARGER than implied by the
+ // definition of the struct.
+ //
+ // As such, we need to be even more careful with dirent64 than if its
+ // contents were "simply" partially initialized data.
+ //
+ // Like for uninitialized contents, converting entry_ptr to `&dirent64`
+ // would not be legal. However, unique to dirent64 is that we don't even
+ // get to use `addr_of!((*entry_ptr).d_name)` because that operation
+ // requires the full extent of *entry_ptr to be in bounds of the same
+ // allocation, which is not necessarily the case here.
+ //
+ // Absent any other way to obtain a pointer to `(*entry_ptr).d_name`
+ // legally in Rust analogously to how it would be done in C, we instead
+ // need to make our own non-libc allocation that conforms to the weird
+ // imaginary definition of dirent64, and use that for a field offset
+ // computation.
+ macro_rules! offset_ptr {
+ ($entry_ptr:expr, $field:ident) => {{
+ const OFFSET: isize = {
+ let delusion = MaybeUninit::<dirent64>::uninit();
+ let entry_ptr = delusion.as_ptr();
+ unsafe {
+ ptr::addr_of!((*entry_ptr).$field)
+ .cast::<u8>()
+ .offset_from(entry_ptr.cast::<u8>())
+ }
+ };
+ if true {
+ // Cast to the same type determined by the else branch.
+ $entry_ptr.byte_offset(OFFSET).cast::<_>()
+ } else {
+ #[allow(deref_nullptr)]
+ {
+ ptr::addr_of!((*ptr::null::<dirent64>()).$field)
+ }
+ }
+ }};
+ }
+
+ // d_name is guaranteed to be null-terminated.
+ let name = CStr::from_ptr(offset_ptr!(entry_ptr, d_name).cast());
+ let name_bytes = name.to_bytes();
+ if name_bytes == b"." || name_bytes == b".." {
+ continue;
+ }
let entry = dirent64_min {
- d_ino: copy.d_ino as u64,
+ d_ino: *offset_ptr!(entry_ptr, d_ino) as u64,
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
- d_type: copy.d_type as u8,
+ d_type: *offset_ptr!(entry_ptr, d_type) as u8,
};
- let ret = DirEntry {
+ return Some(Ok(DirEntry {
entry,
- // d_name is guaranteed to be null-terminated.
- name: CStr::from_ptr(entry_name as *const _).to_owned(),
+ name: name.to_owned(),
dir: Arc::clone(&self.inner),
- };
- if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
- return Some(Ok(ret));
- }
+ }));
}
}
}
@@ -704,7 +722,10 @@ impl DirEntry {
self.file_name_os_str().to_os_string()
}
- #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))]
+ #[cfg(all(
+ any(target_os = "linux", target_os = "emscripten", target_os = "android"),
+ not(miri)
+ ))]
pub fn metadata(&self) -> io::Result<FileAttr> {
let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?;
let name = self.name_cstr().as_ptr();
@@ -725,7 +746,10 @@ impl DirEntry {
Ok(FileAttr::from_stat64(stat))
}
- #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))]
+ #[cfg(any(
+ not(any(target_os = "linux", target_os = "emscripten", target_os = "android")),
+ miri
+ ))]
pub fn metadata(&self) -> io::Result<FileAttr> {
lstat(&self.path())
}
@@ -829,7 +853,6 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox"
)))]
- #[cfg_attr(miri, allow(unused))]
fn name_cstr(&self) -> &CStr {
unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
}
@@ -841,7 +864,6 @@ impl DirEntry {
target_os = "fuchsia",
target_os = "redox"
))]
- #[cfg_attr(miri, allow(unused))]
fn name_cstr(&self) -> &CStr {
&self.name
}
@@ -931,8 +953,7 @@ impl OpenOptions {
impl File {
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
- let path = cstr(path)?;
- File::open_c(&path, opts)
+ run_path_with_cstr(path, |path| File::open_c(path, opts))
}
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
@@ -1084,6 +1105,17 @@ impl File {
}
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+ #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
+ let to_timespec = |time: Option<SystemTime>| {
+ match time {
+ Some(time) if let Some(ts) = time.t.to_timespec() => Ok(ts),
+ Some(time) if time > crate::sys::time::UNIX_EPOCH => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")),
+ Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too small to set as a file time")),
+ None => Ok(libc::timespec { tv_sec: 0, tv_nsec: libc::UTIME_OMIT as _ }),
+ }
+ };
+ #[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon")))]
+ let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
cfg_if::cfg_if! {
if #[cfg(any(target_os = "redox", target_os = "espidf", target_os = "horizon"))] {
// Redox doesn't appear to support `UTIME_OMIT`.
@@ -1099,7 +1131,7 @@ impl File {
cvt(unsafe {
weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
match futimens.get() {
- Some(futimens) => futimens(self.as_raw_fd(), times.0.as_ptr()),
+ Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
#[cfg(target_os = "macos")]
None => {
fn ts_to_tv(ts: &libc::timespec) -> libc::timeval {
@@ -1108,7 +1140,7 @@ impl File {
tv_usec: (ts.tv_nsec / 1000) as _
}
}
- let timevals = [ts_to_tv(&times.0[0]), ts_to_tv(&times.0[1])];
+ let timevals = [ts_to_tv(&times[0]), ts_to_tv(&times[1])];
libc::futimes(self.as_raw_fd(), timevals.as_ptr())
}
// futimes requires even newer Android.
@@ -1121,7 +1153,7 @@ impl File {
})?;
Ok(())
} else {
- cvt(unsafe { libc::futimens(self.as_raw_fd(), times.0.as_ptr()) })?;
+ cvt(unsafe { libc::futimens(self.as_raw_fd(), times.as_ptr()) })?;
Ok(())
}
}
@@ -1134,9 +1166,7 @@ impl DirBuilder {
}
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
- let p = cstr(p)?;
- cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) })?;
- Ok(())
+ run_path_with_cstr(p, |p| cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) }).map(|_| ()))
}
pub fn set_mode(&mut self, mode: u32) {
@@ -1144,10 +1174,6 @@ impl DirBuilder {
}
}
-fn cstr(path: &Path) -> io::Result<CString> {
- Ok(CString::new(path.as_os_str().as_bytes())?)
-}
-
impl AsInner<FileDesc> for File {
fn as_inner(&self) -> &FileDesc {
&self.0
@@ -1198,7 +1224,12 @@ impl FromRawFd for File {
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- #[cfg(any(target_os = "linux", target_os = "netbsd"))]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "solaris"
+ ))]
fn get_path(fd: c_int) -> Option<PathBuf> {
let mut p = PathBuf::from("/proc/self/fd");
p.push(&fd.to_string());
@@ -1253,14 +1284,23 @@ impl fmt::Debug for File {
target_os = "macos",
target_os = "vxworks",
all(target_os = "freebsd", target_arch = "x86_64"),
- target_os = "netbsd"
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "solaris"
)))]
fn get_path(_fd: c_int) -> Option<PathBuf> {
// FIXME(#24570): implement this for other Unix platforms
None
}
- #[cfg(any(target_os = "linux", target_os = "macos", target_os = "vxworks"))]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "vxworks"
+ ))]
fn get_mode(fd: c_int) -> Option<(bool, bool)> {
let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) };
if mode == -1 {
@@ -1274,7 +1314,14 @@ impl fmt::Debug for File {
}
}
- #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "vxworks")))]
+ #[cfg(not(any(
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "freebsd",
+ target_os = "netbsd",
+ target_os = "openbsd",
+ target_os = "vxworks"
+ )))]
fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
// FIXME(#24570): implement this for other Unix platforms
None
@@ -1293,173 +1340,170 @@ impl fmt::Debug for File {
}
}
-pub fn readdir(p: &Path) -> io::Result<ReadDir> {
- let root = p.to_path_buf();
- let p = cstr(p)?;
- unsafe {
- let ptr = libc::opendir(p.as_ptr());
- if ptr.is_null() {
- Err(Error::last_os_error())
- } else {
- let inner = InnerReadDir { dirp: Dir(ptr), root };
- Ok(ReadDir {
- inner: Arc::new(inner),
- #[cfg(not(any(
- target_os = "android",
- target_os = "linux",
- target_os = "solaris",
- target_os = "illumos",
- target_os = "fuchsia",
- target_os = "redox",
- )))]
- end_of_stream: false,
- })
- }
+pub fn readdir(path: &Path) -> io::Result<ReadDir> {
+ let ptr = run_path_with_cstr(path, |p| unsafe { Ok(libc::opendir(p.as_ptr())) })?;
+ if ptr.is_null() {
+ Err(Error::last_os_error())
+ } else {
+ let root = path.to_path_buf();
+ let inner = InnerReadDir { dirp: Dir(ptr), root };
+ Ok(ReadDir {
+ inner: Arc::new(inner),
+ #[cfg(not(any(
+ target_os = "android",
+ target_os = "linux",
+ target_os = "solaris",
+ target_os = "illumos",
+ target_os = "fuchsia",
+ target_os = "redox",
+ )))]
+ end_of_stream: false,
+ })
}
}
pub fn unlink(p: &Path) -> io::Result<()> {
- let p = cstr(p)?;
- cvt(unsafe { libc::unlink(p.as_ptr()) })?;
- Ok(())
+ run_path_with_cstr(p, |p| cvt(unsafe { libc::unlink(p.as_ptr()) }).map(|_| ()))
}
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- let old = cstr(old)?;
- let new = cstr(new)?;
- cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) })?;
- Ok(())
+ run_path_with_cstr(old, |old| {
+ run_path_with_cstr(new, |new| {
+ cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }).map(|_| ())
+ })
+ })
}
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
- let p = cstr(p)?;
- cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) })?;
- Ok(())
+ run_path_with_cstr(p, |p| cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }).map(|_| ()))
}
pub fn rmdir(p: &Path) -> io::Result<()> {
- let p = cstr(p)?;
- cvt(unsafe { libc::rmdir(p.as_ptr()) })?;
- Ok(())
+ run_path_with_cstr(p, |p| cvt(unsafe { libc::rmdir(p.as_ptr()) }).map(|_| ()))
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- let c_path = cstr(p)?;
- let p = c_path.as_ptr();
+ run_path_with_cstr(p, |c_path| {
+ let p = c_path.as_ptr();
- let mut buf = Vec::with_capacity(256);
+ let mut buf = Vec::with_capacity(256);
- loop {
- let buf_read =
- cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })? as usize;
+ loop {
+ let buf_read =
+ cvt(unsafe { libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity()) })?
+ as usize;
- unsafe {
- buf.set_len(buf_read);
- }
+ unsafe {
+ buf.set_len(buf_read);
+ }
- if buf_read != buf.capacity() {
- buf.shrink_to_fit();
+ if buf_read != buf.capacity() {
+ buf.shrink_to_fit();
- return Ok(PathBuf::from(OsString::from_vec(buf)));
- }
+ return Ok(PathBuf::from(OsString::from_vec(buf)));
+ }
- // Trigger the internal buffer resizing logic of `Vec` by requiring
- // more space than the current capacity. The length is guaranteed to be
- // the same as the capacity due to the if statement above.
- buf.reserve(1);
- }
+ // Trigger the internal buffer resizing logic of `Vec` by requiring
+ // more space than the current capacity. The length is guaranteed to be
+ // the same as the capacity due to the if statement above.
+ buf.reserve(1);
+ }
+ })
}
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
- let original = cstr(original)?;
- let link = cstr(link)?;
- cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) })?;
- Ok(())
+ run_path_with_cstr(original, |original| {
+ run_path_with_cstr(link, |link| {
+ cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) }).map(|_| ())
+ })
+ })
}
pub fn link(original: &Path, link: &Path) -> io::Result<()> {
- let original = cstr(original)?;
- let link = cstr(link)?;
- cfg_if::cfg_if! {
- if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon"))] {
- // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
- // it implementation-defined whether `link` follows symlinks, so rely on the
- // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
- // Android has `linkat` on newer versions, but we happen to know `link`
- // always has the correct behavior, so it's here as well.
- cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
- } else if #[cfg(target_os = "macos")] {
- // On MacOS, older versions (<=10.9) lack support for linkat while newer
- // versions have it. We want to use linkat if it is available, so we use weak!
- // to check. `linkat` is preferable to `link` because it gives us a flag to
- // specify how symlinks should be handled. We pass 0 as the flags argument,
- // meaning it shouldn't follow symlinks.
- weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
-
- if let Some(f) = linkat.get() {
- cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
- } else {
- cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
- };
- } else {
- // Where we can, use `linkat` instead of `link`; see the comment above
- // this one for details on why.
- cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
- }
- }
- Ok(())
+ run_path_with_cstr(original, |original| {
+ run_path_with_cstr(link, |link| {
+ cfg_if::cfg_if! {
+ if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android", target_os = "espidf", target_os = "horizon"))] {
+ // VxWorks, Redox and ESP-IDF lack `linkat`, so use `link` instead. POSIX leaves
+ // it implementation-defined whether `link` follows symlinks, so rely on the
+ // `symlink_hard_link` test in library/std/src/fs/tests.rs to check the behavior.
+ // Android has `linkat` on newer versions, but we happen to know `link`
+ // always has the correct behavior, so it's here as well.
+ cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+ } else if #[cfg(target_os = "macos")] {
+ // On MacOS, older versions (<=10.9) lack support for linkat while newer
+ // versions have it. We want to use linkat if it is available, so we use weak!
+ // to check. `linkat` is preferable to `link` because it gives us a flag to
+ // specify how symlinks should be handled. We pass 0 as the flags argument,
+ // meaning it shouldn't follow symlinks.
+ weak!(fn linkat(c_int, *const c_char, c_int, *const c_char, c_int) -> c_int);
+
+ if let Some(f) = linkat.get() {
+ cvt(unsafe { f(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+ } else {
+ cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
+ };
+ } else {
+ // Where we can, use `linkat` instead of `link`; see the comment above
+ // this one for details on why.
+ cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
+ }
+ }
+ Ok(())
+ })
+ })
}
pub fn stat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p)?;
-
- cfg_has_statx! {
- if let Some(ret) = unsafe { try_statx(
- libc::AT_FDCWD,
- p.as_ptr(),
- libc::AT_STATX_SYNC_AS_STAT,
- libc::STATX_ALL,
- ) } {
- return ret;
+ run_path_with_cstr(p, |p| {
+ cfg_has_statx! {
+ if let Some(ret) = unsafe { try_statx(
+ libc::AT_FDCWD,
+ p.as_ptr(),
+ libc::AT_STATX_SYNC_AS_STAT,
+ libc::STATX_ALL,
+ ) } {
+ return ret;
+ }
}
- }
- let mut stat: stat64 = unsafe { mem::zeroed() };
- cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
- Ok(FileAttr::from_stat64(stat))
+ let mut stat: stat64 = unsafe { mem::zeroed() };
+ cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?;
+ Ok(FileAttr::from_stat64(stat))
+ })
}
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p)?;
-
- cfg_has_statx! {
- if let Some(ret) = unsafe { try_statx(
- libc::AT_FDCWD,
- p.as_ptr(),
- libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
- libc::STATX_ALL,
- ) } {
- return ret;
+ run_path_with_cstr(p, |p| {
+ cfg_has_statx! {
+ if let Some(ret) = unsafe { try_statx(
+ libc::AT_FDCWD,
+ p.as_ptr(),
+ libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT,
+ libc::STATX_ALL,
+ ) } {
+ return ret;
+ }
}
- }
- let mut stat: stat64 = unsafe { mem::zeroed() };
- cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
- Ok(FileAttr::from_stat64(stat))
+ let mut stat: stat64 = unsafe { mem::zeroed() };
+ cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?;
+ Ok(FileAttr::from_stat64(stat))
+ })
}
pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
- let path = CString::new(p.as_os_str().as_bytes())?;
- let buf;
- unsafe {
- let r = libc::realpath(path.as_ptr(), ptr::null_mut());
- if r.is_null() {
- return Err(io::Error::last_os_error());
- }
- buf = CStr::from_ptr(r).to_bytes().to_vec();
- libc::free(r as *mut _);
+ let r = run_path_with_cstr(p, |path| unsafe {
+ Ok(libc::realpath(path.as_ptr(), ptr::null_mut()))
+ })?;
+ if r.is_null() {
+ return Err(io::Error::last_os_error());
}
- Ok(PathBuf::from(OsString::from_vec(buf)))
+ Ok(PathBuf::from(OsString::from_vec(unsafe {
+ let buf = CStr::from_ptr(r).to_bytes().to_vec();
+ libc::free(r as *mut _);
+ buf
+ })))
}
fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> {
@@ -1609,9 +1653,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
// Opportunistically attempt to create a copy-on-write clone of `from`
// using `fclonefileat`.
if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {
- let to = cstr(to)?;
- let clonefile_result =
- cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) });
+ let clonefile_result = run_path_with_cstr(to, |to| {
+ cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
+ });
match clonefile_result {
Ok(_) => return Ok(reader_metadata.len()),
Err(err) => match err.raw_os_error() {
@@ -1655,9 +1699,10 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
}
pub fn chown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
- let path = cstr(path)?;
- cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
- Ok(())
+ run_path_with_cstr(path, |path| {
+ cvt(unsafe { libc::chown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })
+ .map(|_| ())
+ })
}
pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
@@ -1666,16 +1711,15 @@ pub fn fchown(fd: c_int, uid: u32, gid: u32) -> io::Result<()> {
}
pub fn lchown(path: &Path, uid: u32, gid: u32) -> io::Result<()> {
- let path = cstr(path)?;
- cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })?;
- Ok(())
+ run_path_with_cstr(path, |path| {
+ cvt(unsafe { libc::lchown(path.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) })
+ .map(|_| ())
+ })
}
#[cfg(not(any(target_os = "fuchsia", target_os = "vxworks")))]
pub fn chroot(dir: &Path) -> io::Result<()> {
- let dir = cstr(dir)?;
- cvt(unsafe { libc::chroot(dir.as_ptr()) })?;
- Ok(())
+ run_path_with_cstr(dir, |dir| cvt(unsafe { libc::chroot(dir.as_ptr()) }).map(|_| ()))
}
pub use remove_dir_impl::remove_dir_all;
@@ -1689,13 +1733,14 @@ mod remove_dir_impl {
// Modern implementation using openat(), unlinkat() and fdopendir()
#[cfg(not(any(target_os = "redox", target_os = "espidf", target_os = "horizon", miri)))]
mod remove_dir_impl {
- use super::{cstr, lstat, Dir, DirEntry, InnerReadDir, ReadDir};
+ use super::{lstat, Dir, DirEntry, InnerReadDir, ReadDir};
use crate::ffi::CStr;
use crate::io;
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use crate::os::unix::prelude::{OwnedFd, RawFd};
use crate::path::{Path, PathBuf};
use crate::sync::Arc;
+ use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::{cvt, cvt_r};
#[cfg(not(all(target_os = "macos", not(target_arch = "aarch64")),))]
@@ -1862,7 +1907,7 @@ mod remove_dir_impl {
if attr.file_type().is_symlink() {
crate::fs::remove_file(p)
} else {
- remove_dir_all_recursive(None, &cstr(p)?)
+ run_path_with_cstr(p, |p| remove_dir_all_recursive(None, &p))
}
}
diff --git a/library/std/src/sys/unix/io.rs b/library/std/src/sys/unix/io.rs
index deb5ee76b..29c340dd3 100644
--- a/library/std/src/sys/unix/io.rs
+++ b/library/std/src/sys/unix/io.rs
@@ -1,4 +1,5 @@
use crate::marker::PhantomData;
+use crate::os::fd::{AsFd, AsRawFd};
use crate::slice;
use libc::{c_void, iovec};
@@ -74,3 +75,8 @@ impl<'a> IoSliceMut<'a> {
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}
+
+pub fn is_terminal(fd: &impl AsFd) -> bool {
+ let fd = fd.as_fd();
+ unsafe { libc::isatty(fd.as_raw_fd()) != 0 }
+}
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 8f7abb55e..94546ca09 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -20,7 +20,7 @@
//! Since those syscalls have requirements that cannot be fully checked in advance and
//! gathering additional information about file descriptors would require additional syscalls
//! anyway it simply attempts to use them one after another (guided by inaccurate hints) to
-//! figure out which one works and and falls back to the generic read-write copy loop if none of them
+//! figure out which one works and falls back to the generic read-write copy loop if none of them
//! does.
//! Once a working syscall is found for a pair of file descriptors it will be called in a loop
//! until the copy operation is completed.
diff --git a/library/std/src/sys/unix/locks/mod.rs b/library/std/src/sys/unix/locks/mod.rs
index f5f92f693..9bb314b70 100644
--- a/library/std/src/sys/unix/locks/mod.rs
+++ b/library/std/src/sys/unix/locks/mod.rs
@@ -11,21 +11,21 @@ cfg_if::cfg_if! {
mod futex_rwlock;
mod futex_condvar;
pub(crate) use futex_mutex::{Mutex, MovableMutex};
- pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+ pub(crate) use futex_rwlock::MovableRwLock;
pub(crate) use futex_condvar::MovableCondvar;
} else if #[cfg(target_os = "fuchsia")] {
mod fuchsia_mutex;
mod futex_rwlock;
mod futex_condvar;
pub(crate) use fuchsia_mutex::{Mutex, MovableMutex};
- pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+ pub(crate) use futex_rwlock::MovableRwLock;
pub(crate) use futex_condvar::MovableCondvar;
} else {
mod pthread_mutex;
mod pthread_rwlock;
mod pthread_condvar;
pub(crate) use pthread_mutex::{Mutex, MovableMutex};
- pub(crate) use pthread_rwlock::{RwLock, MovableRwLock};
+ pub(crate) use pthread_rwlock::MovableRwLock;
pub(crate) use pthread_condvar::MovableCondvar;
}
}
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index c84e292ea..9055a011c 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -163,17 +163,27 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
// See the other file for docs. NOTE: Make sure to keep them in
// sync!
mod sigpipe {
+ pub const DEFAULT: u8 = 0;
pub const INHERIT: u8 = 1;
pub const SIG_IGN: u8 = 2;
pub const SIG_DFL: u8 = 3;
}
- let handler = match sigpipe {
- sigpipe::INHERIT => None,
- sigpipe::SIG_IGN => Some(libc::SIG_IGN),
- sigpipe::SIG_DFL => Some(libc::SIG_DFL),
+ let (sigpipe_attr_specified, handler) = match sigpipe {
+ sigpipe::DEFAULT => (false, Some(libc::SIG_IGN)),
+ sigpipe::INHERIT => (true, None),
+ sigpipe::SIG_IGN => (true, Some(libc::SIG_IGN)),
+ sigpipe::SIG_DFL => (true, Some(libc::SIG_DFL)),
_ => unreachable!(),
};
+ // The bootstrap compiler doesn't know about sigpipe::DEFAULT, and always passes in
+ // SIG_IGN. This causes some tests to fail because they expect SIGPIPE to be reset to
+ // default on process spawning (which doesn't happen if #[unix_sigpipe] is specified).
+ // Since we can't differentiate between the cases here, treat SIG_IGN as DEFAULT
+ // unconditionally.
+ if sigpipe_attr_specified && !(cfg!(bootstrap) && sigpipe == sigpipe::SIG_IGN) {
+ UNIX_SIGPIPE_ATTR_SPECIFIED.store(true, crate::sync::atomic::Ordering::Relaxed);
+ }
if let Some(handler) = handler {
rtassert!(signal(libc::SIGPIPE, handler) != libc::SIG_ERR);
}
@@ -181,6 +191,26 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
}
+// This is set (up to once) in reset_sigpipe.
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "horizon"
+)))]
+static UNIX_SIGPIPE_ATTR_SPECIFIED: crate::sync::atomic::AtomicBool =
+ crate::sync::atomic::AtomicBool::new(false);
+
+#[cfg(not(any(
+ target_os = "espidf",
+ target_os = "emscripten",
+ target_os = "fuchsia",
+ target_os = "horizon"
+)))]
+pub(crate) fn unix_sigpipe_attr_specified() -> bool {
+ UNIX_SIGPIPE_ATTR_SPECIFIED.load(crate::sync::atomic::Ordering::Relaxed)
+}
+
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {
@@ -352,16 +382,12 @@ cfg_if::cfg_if! {
extern "C" {}
} else if #[cfg(target_os = "macos")] {
#[link(name = "System")]
- // res_init and friends require -lresolv on macOS/iOS.
- // See #41582 and https://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
- #[link(name = "resolv")]
extern "C" {}
} else if #[cfg(any(target_os = "ios", target_os = "watchos"))] {
#[link(name = "System")]
#[link(name = "objc")]
#[link(name = "Security", kind = "framework")]
#[link(name = "Foundation", kind = "framework")]
- #[link(name = "resolv")]
extern "C" {}
} else if #[cfg(target_os = "fuchsia")] {
#[link(name = "zircon")]
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 46545a083..2f2663db6 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -7,6 +7,7 @@ mod tests;
use crate::os::unix::prelude::*;
+use crate::convert::TryFrom;
use crate::error::Error as StdError;
use crate::ffi::{CStr, CString, OsStr, OsString};
use crate::fmt;
@@ -17,10 +18,11 @@ use crate::path::{self, PathBuf};
use crate::ptr;
use crate::slice;
use crate::str;
+use crate::sync::{PoisonError, RwLock};
+use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
use crate::sys::cvt;
use crate::sys::fd;
use crate::sys::memchr;
-use crate::sys_common::rwlock::{StaticRwLock, StaticRwLockReadGuard};
use crate::vec;
#[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
@@ -125,7 +127,9 @@ pub fn error_string(errno: i32) -> String {
}
let p = p as *const _;
- str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
+ // We can't always expect a UTF-8 environment. When we don't get that luxury,
+ // it's better to give a low-quality error message than none at all.
+ String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into()
}
}
@@ -168,12 +172,8 @@ pub fn chdir(p: &path::Path) -> io::Result<()> {
#[cfg(not(target_os = "espidf"))]
pub fn chdir(p: &path::Path) -> io::Result<()> {
- let p: &OsStr = p.as_ref();
- let p = CString::new(p.as_bytes())?;
- if unsafe { libc::chdir(p.as_ptr()) } != 0 {
- return Err(io::Error::last_os_error());
- }
- Ok(())
+ let result = run_path_with_cstr(p, |p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
+ if result == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }
}
pub struct SplitPaths<'a> {
@@ -501,10 +501,10 @@ pub unsafe fn environ() -> *mut *const *const c_char {
ptr::addr_of_mut!(environ)
}
-static ENV_LOCK: StaticRwLock = StaticRwLock::new();
+static ENV_LOCK: RwLock<()> = RwLock::new(());
-pub fn env_read_lock() -> StaticRwLockReadGuard {
- ENV_LOCK.read()
+pub fn env_read_lock() -> impl Drop {
+ ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
}
/// Returns a vector of (variable, value) byte-vector pairs for all the
@@ -546,35 +546,32 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> {
// environment variables with a nul byte can't be set, so their value is
// always None as well
- let k = CString::new(k.as_bytes()).ok()?;
- unsafe {
+ let s = run_with_cstr(k.as_bytes(), |k| {
let _guard = env_read_lock();
- let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
- if s.is_null() {
- None
- } else {
- Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
- }
+ Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
+ })
+ .ok()?;
+ if s.is_null() {
+ None
+ } else {
+ Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
- let k = CString::new(k.as_bytes())?;
- let v = CString::new(v.as_bytes())?;
-
- unsafe {
- let _guard = ENV_LOCK.write();
- cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
- }
+ run_with_cstr(k.as_bytes(), |k| {
+ run_with_cstr(v.as_bytes(), |v| {
+ let _guard = ENV_LOCK.write();
+ cvt(unsafe { libc::setenv(k.as_ptr(), v.as_ptr(), 1) }).map(drop)
+ })
+ })
}
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
- let nbuf = CString::new(n.as_bytes())?;
-
- unsafe {
+ run_with_cstr(n.as_bytes(), |nbuf| {
let _guard = ENV_LOCK.write();
- cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
- }
+ cvt(unsafe { libc::unsetenv(nbuf.as_ptr()) }).map(drop)
+ })
}
#[cfg(not(target_os = "espidf"))]
diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs
index 2834ee0ac..848adca78 100644
--- a/library/std/src/sys/unix/process/process_common.rs
+++ b/library/std/src/sys/unix/process/process_common.rs
@@ -39,10 +39,12 @@ cfg_if::cfg_if! {
// https://github.com/aosp-mirror/platform_bionic/blob/ad8dcd6023294b646e5a8288c0ed431b0845da49/libc/include/android/legacy_signal_inlines.h
cfg_if::cfg_if! {
if #[cfg(target_os = "android")] {
+ #[allow(dead_code)]
pub unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
set.write_bytes(0u8, 1);
return 0;
}
+
#[allow(dead_code)]
pub unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
use crate::{
diff --git a/library/std/src/sys/unix/process/process_common/tests.rs b/library/std/src/sys/unix/process/process_common/tests.rs
index d176b3401..03631e4e3 100644
--- a/library/std/src/sys/unix/process/process_common/tests.rs
+++ b/library/std/src/sys/unix/process/process_common/tests.rs
@@ -31,41 +31,54 @@ macro_rules! t {
ignore
)]
fn test_process_mask() {
- unsafe {
- // Test to make sure that a signal mask does not get inherited.
- let mut cmd = Command::new(OsStr::new("cat"));
-
- let mut set = mem::MaybeUninit::<libc::sigset_t>::uninit();
- let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
- t!(cvt(sigemptyset(set.as_mut_ptr())));
- t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
- t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
-
- cmd.stdin(Stdio::MakePipe);
- cmd.stdout(Stdio::MakePipe);
-
- let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true));
- let stdin_write = pipes.stdin.take().unwrap();
- let stdout_read = pipes.stdout.take().unwrap();
-
- t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
-
- t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
- // We need to wait until SIGINT is definitely delivered. The
- // easiest way is to write something to cat, and try to read it
- // back: if SIGINT is unmasked, it'll get delivered when cat is
- // next scheduled.
- let _ = stdin_write.write(b"Hello");
- drop(stdin_write);
-
- // Either EOF or failure (EPIPE) is okay.
- let mut buf = [0; 5];
- if let Ok(ret) = stdout_read.read(&mut buf) {
- assert_eq!(ret, 0);
+ // Test to make sure that a signal mask *does* get inherited.
+ fn test_inner(mut cmd: Command) {
+ unsafe {
+ let mut set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+ let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
+ t!(cvt(sigemptyset(set.as_mut_ptr())));
+ t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
+ t!(cvt_nz(libc::pthread_sigmask(
+ libc::SIG_SETMASK,
+ set.as_ptr(),
+ old_set.as_mut_ptr()
+ )));
+
+ cmd.stdin(Stdio::MakePipe);
+ cmd.stdout(Stdio::MakePipe);
+
+ let (mut cat, mut pipes) = t!(cmd.spawn(Stdio::Null, true));
+ let stdin_write = pipes.stdin.take().unwrap();
+ let stdout_read = pipes.stdout.take().unwrap();
+
+ t!(cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(), ptr::null_mut())));
+
+ t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));
+ // We need to wait until SIGINT is definitely delivered. The
+ // easiest way is to write something to cat, and try to read it
+ // back: if SIGINT is unmasked, it'll get delivered when cat is
+ // next scheduled.
+ let _ = stdin_write.write(b"Hello");
+ drop(stdin_write);
+
+ // Exactly 5 bytes should be read.
+ let mut buf = [0; 5];
+ let ret = t!(stdout_read.read(&mut buf));
+ assert_eq!(ret, 5);
+ assert_eq!(&buf, b"Hello");
+
+ t!(cat.wait());
}
-
- t!(cat.wait());
}
+
+ // A plain `Command::new` uses the posix_spawn path on many platforms.
+ let cmd = Command::new(OsStr::new("cat"));
+ test_inner(cmd);
+
+ // Specifying `pre_exec` forces the fork/exec path.
+ let mut cmd = Command::new(OsStr::new("cat"));
+ unsafe { cmd.pre_exec(Box::new(|| Ok(()))) };
+ test_inner(cmd);
}
#[test]
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index 73f5d3a61..66ea3db20 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -287,7 +287,7 @@ impl ExitStatus {
// SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't
// necessarily fit.
//
- // It seems to me that that the right answer would be to provide std::os::fuchsia with its
+ // It seems to me that the right answer would be to provide std::os::fuchsia with its
// own ExitStatusExt, rather that trying to provide a not very convincing imitation of
// Unix. Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia. But
// fixing this up that is beyond the scope of my efforts now.
diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs
index 26ae62817..56a805cef 100644
--- a/library/std/src/sys/unix/process/process_unix.rs
+++ b/library/std/src/sys/unix/process/process_unix.rs
@@ -2,7 +2,6 @@ use crate::fmt;
use crate::io::{self, Error, ErrorKind};
use crate::mem;
use crate::num::NonZeroI32;
-use crate::ptr;
use crate::sys;
use crate::sys::cvt;
use crate::sys::process::process_common::*;
@@ -310,7 +309,7 @@ impl Command {
//FIXME: Redox kernel does not support setgroups yet
#[cfg(not(target_os = "redox"))]
if libc::getuid() == 0 && self.get_groups().is_none() {
- cvt(libc::setgroups(0, ptr::null()))?;
+ cvt(libc::setgroups(0, crate::ptr::null()))?;
}
cvt(libc::setuid(u as uid_t))?;
}
@@ -326,30 +325,26 @@ impl Command {
// emscripten has no signal support.
#[cfg(not(target_os = "emscripten"))]
{
- use crate::mem::MaybeUninit;
- use crate::sys::cvt_nz;
- // Reset signal handling so the child process starts in a
- // standardized state. libstd ignores SIGPIPE, and signal-handling
- // libraries often set a mask. Child processes inherit ignored
- // signals and the signal mask from their parent, but most
- // UNIX programs do not reset these things on their own, so we
- // need to clean things up now to avoid confusing the program
- // we're about to run.
- let mut set = MaybeUninit::<libc::sigset_t>::uninit();
- cvt(sigemptyset(set.as_mut_ptr()))?;
- cvt_nz(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), ptr::null_mut()))?;
-
- #[cfg(target_os = "android")] // see issue #88585
- {
- let mut action: libc::sigaction = mem::zeroed();
- action.sa_sigaction = libc::SIG_DFL;
- cvt(libc::sigaction(libc::SIGPIPE, &action, ptr::null_mut()))?;
- }
- #[cfg(not(target_os = "android"))]
- {
- let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
- if ret == libc::SIG_ERR {
- return Err(io::Error::last_os_error());
+ // Inherit the signal mask from the parent rather than resetting it (i.e. do not call
+ // pthread_sigmask).
+
+ // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL.
+ // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility.
+ //
+ // #[unix_sigpipe] is an opportunity to change the default here.
+ if !crate::sys::unix_sigpipe_attr_specified() {
+ #[cfg(target_os = "android")] // see issue #88585
+ {
+ let mut action: libc::sigaction = mem::zeroed();
+ action.sa_sigaction = libc::SIG_DFL;
+ cvt(libc::sigaction(libc::SIGPIPE, &action, crate::ptr::null_mut()))?;
+ }
+ #[cfg(not(target_os = "android"))]
+ {
+ let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
+ if ret == libc::SIG_ERR {
+ return Err(io::Error::last_os_error());
+ }
}
}
}
@@ -411,7 +406,7 @@ impl Command {
envp: Option<&CStringArray>,
) -> io::Result<Option<Process>> {
use crate::mem::MaybeUninit;
- use crate::sys::{self, cvt_nz};
+ use crate::sys::{self, cvt_nz, unix_sigpipe_attr_specified};
if self.get_gid().is_some()
|| self.get_uid().is_some()
@@ -531,13 +526,24 @@ impl Command {
cvt_nz(libc::posix_spawnattr_setpgroup(attrs.0.as_mut_ptr(), pgroup))?;
}
- let mut set = MaybeUninit::<libc::sigset_t>::uninit();
- cvt(sigemptyset(set.as_mut_ptr()))?;
- cvt_nz(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(), set.as_ptr()))?;
- cvt(sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
- cvt_nz(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(), set.as_ptr()))?;
+ // Inherit the signal mask from this process rather than resetting it (i.e. do not call
+ // posix_spawnattr_setsigmask).
+
+ // If #[unix_sigpipe] is specified, don't reset SIGPIPE to SIG_DFL.
+ // If #[unix_sigpipe] is not specified, reset SIGPIPE to SIG_DFL for backward compatibility.
+ //
+ // #[unix_sigpipe] is an opportunity to change the default here.
+ if !unix_sigpipe_attr_specified() {
+ let mut default_set = MaybeUninit::<libc::sigset_t>::uninit();
+ cvt(sigemptyset(default_set.as_mut_ptr()))?;
+ cvt(sigaddset(default_set.as_mut_ptr(), libc::SIGPIPE))?;
+ cvt_nz(libc::posix_spawnattr_setsigdefault(
+ attrs.0.as_mut_ptr(),
+ default_set.as_ptr(),
+ ))?;
+ flags |= libc::POSIX_SPAWN_SETSIGDEF;
+ }
- flags |= libc::POSIX_SPAWN_SETSIGDEF | libc::POSIX_SPAWN_SETSIGMASK;
cvt_nz(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
// Make sure we synchronize access to the global `environ` resource
@@ -822,14 +828,14 @@ impl crate::os::linux::process::ChildExt for crate::process::Child {
self.handle
.pidfd
.as_ref()
- .ok_or_else(|| Error::new(ErrorKind::Other, "No pidfd was created."))
+ .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created."))
}
fn take_pidfd(&mut self) -> io::Result<PidFd> {
self.handle
.pidfd
.take()
- .ok_or_else(|| Error::new(ErrorKind::Other, "No pidfd was created."))
+ .ok_or_else(|| Error::new(ErrorKind::Uncategorized, "No pidfd was created."))
}
}
diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs
index 329f9433d..b3626c564 100644
--- a/library/std/src/sys/unix/stdio.rs
+++ b/library/std/src/sys/unix/stdio.rs
@@ -1,6 +1,6 @@
use crate::io::{self, IoSlice, IoSliceMut};
use crate::mem::ManuallyDrop;
-use crate::os::unix::io::{AsFd, BorrowedFd, FromRawFd};
+use crate::os::unix::io::FromRawFd;
use crate::sys::fd::FileDesc;
pub struct Stdin(());
@@ -91,51 +91,3 @@ pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
pub fn panic_output() -> Option<impl io::Write> {
Some(Stderr::new())
}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl AsFd for io::Stdin {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
- }
-}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl<'a> AsFd for io::StdinLock<'a> {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) }
- }
-}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl AsFd for io::Stdout {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
- }
-}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl<'a> AsFd for io::StdoutLock<'a> {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) }
- }
-}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl AsFd for io::Stderr {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
- }
-}
-
-#[stable(feature = "io_safety", since = "1.63.0")]
-impl<'a> AsFd for io::StderrLock<'a> {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) }
- }
-}
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index f6b627afc..c1d30dd9d 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -137,7 +137,9 @@ impl Thread {
unsafe {
// Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
let name = truncate_cstr(name, TASK_COMM_LEN);
- libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
+ let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
+ // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
+ debug_assert_eq!(res, 0);
}
}
@@ -152,20 +154,22 @@ impl Thread {
pub fn set_name(name: &CStr) {
unsafe {
let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
- libc::pthread_setname_np(name.as_ptr());
+ let res = libc::pthread_setname_np(name.as_ptr());
+ // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
+ debug_assert_eq!(res, 0);
}
}
#[cfg(target_os = "netbsd")]
pub fn set_name(name: &CStr) {
- use crate::ffi::CString;
- let cname = CString::new(&b"%s"[..]).unwrap();
unsafe {
- libc::pthread_setname_np(
+ let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice());
+ let res = libc::pthread_setname_np(
libc::pthread_self(),
cname.as_ptr(),
name.as_ptr() as *mut libc::c_void,
);
+ debug_assert_eq!(res, 0);
}
}
@@ -178,9 +182,8 @@ impl Thread {
}
if let Some(f) = pthread_setname_np.get() {
- unsafe {
- f(libc::pthread_self(), name.as_ptr());
- }
+ let res = unsafe { f(libc::pthread_self(), name.as_ptr()) };
+ debug_assert_eq!(res, 0);
}
}
@@ -785,6 +788,16 @@ pub mod guard {
const GUARD_PAGES: usize = 1;
let guard = guardaddr..guardaddr + GUARD_PAGES * page_size;
Some(guard)
+ } else if cfg!(target_os = "openbsd") {
+ // OpenBSD stack already includes a guard page, and stack is
+ // immutable.
+ //
+ // We'll just note where we expect rlimit to start
+ // faulting, so our handler can report "stack overflow", and
+ // trust that the kernel's own stack guard will work.
+ let stackptr = get_stack_start_aligned()?;
+ let stackaddr = stackptr.addr();
+ Some(stackaddr - page_size..stackaddr)
} else {
// Reallocate the last page of the stack.
// This ensures SIGBUS will be raised on
diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs
index 6e8be2a91..d7fd2130f 100644
--- a/library/std/src/sys/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/unix/thread_local_dtor.rs
@@ -17,6 +17,7 @@
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)
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;
diff --git a/library/std/src/sys/unix/thread_local_key.rs b/library/std/src/sys/unix/thread_local_key.rs
index 2c5b94b1e..2b2d079ee 100644
--- a/library/std/src/sys/unix/thread_local_key.rs
+++ b/library/std/src/sys/unix/thread_local_key.rs
@@ -27,8 +27,3 @@ pub unsafe fn destroy(key: Key) {
let r = libc::pthread_key_delete(key);
debug_assert_eq!(r, 0);
}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
- false
-}
diff --git a/library/std/src/sys/unix/thread_parker/darwin.rs b/library/std/src/sys/unix/thread_parker/darwin.rs
new file mode 100644
index 000000000..2f5356fe2
--- /dev/null
+++ b/library/std/src/sys/unix/thread_parker/darwin.rs
@@ -0,0 +1,131 @@
+//! Thread parking for Darwin-based systems.
+//!
+//! Darwin actually has futex syscalls (`__ulock_wait`/`__ulock_wake`), but they
+//! cannot be used in `std` because they are non-public (their use will lead to
+//! rejection from the App Store) and because they are only available starting
+//! with macOS version 10.12, even though the minimum target version is 10.7.
+//!
+//! Therefore, we need to look for other synchronization primitives. Luckily, Darwin
+//! supports semaphores, which allow us to implement the behaviour we need with
+//! only one primitive (as opposed to a mutex-condvar pair). We use the semaphore
+//! provided by libdispatch, as the underlying Mach semaphore is only dubiously
+//! public.
+
+use crate::pin::Pin;
+use crate::sync::atomic::{
+ AtomicI8,
+ Ordering::{Acquire, Release},
+};
+use crate::time::Duration;
+
+type dispatch_semaphore_t = *mut crate::ffi::c_void;
+type dispatch_time_t = u64;
+
+const DISPATCH_TIME_NOW: dispatch_time_t = 0;
+const DISPATCH_TIME_FOREVER: dispatch_time_t = !0;
+
+// Contained in libSystem.dylib, which is linked by default.
+extern "C" {
+ fn dispatch_time(when: dispatch_time_t, delta: i64) -> dispatch_time_t;
+ fn dispatch_semaphore_create(val: isize) -> dispatch_semaphore_t;
+ fn dispatch_semaphore_wait(dsema: dispatch_semaphore_t, timeout: dispatch_time_t) -> isize;
+ fn dispatch_semaphore_signal(dsema: dispatch_semaphore_t) -> isize;
+ fn dispatch_release(object: *mut crate::ffi::c_void);
+}
+
+const EMPTY: i8 = 0;
+const NOTIFIED: i8 = 1;
+const PARKED: i8 = -1;
+
+pub struct Parker {
+ semaphore: dispatch_semaphore_t,
+ state: AtomicI8,
+}
+
+unsafe impl Sync for Parker {}
+unsafe impl Send for Parker {}
+
+impl Parker {
+ pub unsafe fn new(parker: *mut Parker) {
+ let semaphore = dispatch_semaphore_create(0);
+ assert!(
+ !semaphore.is_null(),
+ "failed to create dispatch semaphore for thread synchronization"
+ );
+ parker.write(Parker { semaphore, state: AtomicI8::new(EMPTY) })
+ }
+
+ // Does not need `Pin`, but other implementation do.
+ pub unsafe fn park(self: Pin<&Self>) {
+ // The semaphore counter must be zero at this point, because unparking
+ // threads will not actually increase it until we signalled that we
+ // are waiting.
+
+ // Change NOTIFIED to EMPTY and EMPTY to PARKED.
+ if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+ return;
+ }
+
+ // Another thread may increase the semaphore counter from this point on.
+ // If it is faster than us, we will decrement it again immediately below.
+ // If we are faster, we wait.
+
+ // Ensure that the semaphore counter has actually been decremented, even
+ // if the call timed out for some reason.
+ while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
+
+ // At this point, the semaphore counter is zero again.
+
+ // We were definitely woken up, so we don't need to check the state.
+ // Still, we need to reset the state using a swap to observe the state
+ // change with acquire ordering.
+ self.state.swap(EMPTY, Acquire);
+ }
+
+ // Does not need `Pin`, but other implementation do.
+ pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+ if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+ return;
+ }
+
+ let nanos = dur.as_nanos().try_into().unwrap_or(i64::MAX);
+ let timeout = dispatch_time(DISPATCH_TIME_NOW, nanos);
+
+ let timeout = dispatch_semaphore_wait(self.semaphore, timeout) != 0;
+
+ let state = self.state.swap(EMPTY, Acquire);
+ if state == NOTIFIED && timeout {
+ // If the state was NOTIFIED but semaphore_wait returned without
+ // decrementing the count because of a timeout, it means another
+ // thread is about to call semaphore_signal. We must wait for that
+ // to happen to ensure the semaphore count is reset.
+ while dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER) != 0 {}
+ } else {
+ // Either a timeout occurred and we reset the state before any thread
+ // tried to wake us up, or we were woken up and reset the state,
+ // making sure to observe the state change with acquire ordering.
+ // Either way, the semaphore counter is now zero again.
+ }
+ }
+
+ // Does not need `Pin`, but other implementation do.
+ pub fn unpark(self: Pin<&Self>) {
+ let state = self.state.swap(NOTIFIED, Release);
+ if state == PARKED {
+ unsafe {
+ dispatch_semaphore_signal(self.semaphore);
+ }
+ }
+ }
+}
+
+impl Drop for Parker {
+ fn drop(&mut self) {
+ // SAFETY:
+ // We always ensure that the semaphore count is reset, so this will
+ // never cause an exception.
+ unsafe {
+ dispatch_release(self.semaphore);
+ }
+ }
+}
diff --git a/library/std/src/sys/unix/thread_parker/mod.rs b/library/std/src/sys/unix/thread_parker/mod.rs
index e2453580d..35f1e68a8 100644
--- a/library/std/src/sys/unix/thread_parker/mod.rs
+++ b/library/std/src/sys/unix/thread_parker/mod.rs
@@ -11,7 +11,18 @@
)))]
cfg_if::cfg_if! {
- if #[cfg(target_os = "netbsd")] {
+ if #[cfg(all(
+ any(
+ target_os = "macos",
+ target_os = "ios",
+ target_os = "watchos",
+ target_os = "tvos",
+ ),
+ not(miri),
+ ))] {
+ mod darwin;
+ pub use darwin::Parker;
+ } else if #[cfg(target_os = "netbsd")] {
mod netbsd;
pub use netbsd::Parker;
} else {
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index dff973f59..cca9c6767 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -7,6 +7,12 @@ const NSEC_PER_SEC: u64 = 1_000_000_000;
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(0)]
+#[rustc_layout_scalar_valid_range_end(999_999_999)]
+struct Nanoseconds(u32);
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SystemTime {
pub(in crate::sys::unix) t: Timespec,
}
@@ -14,7 +20,7 @@ pub struct SystemTime {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(in crate::sys::unix) struct Timespec {
tv_sec: i64,
- tv_nsec: i64,
+ tv_nsec: Nanoseconds,
}
impl SystemTime {
@@ -46,18 +52,20 @@ impl fmt::Debug for SystemTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SystemTime")
.field("tv_sec", &self.t.tv_sec)
- .field("tv_nsec", &self.t.tv_nsec)
+ .field("tv_nsec", &self.t.tv_nsec.0)
.finish()
}
}
impl Timespec {
pub const fn zero() -> Timespec {
- Timespec { tv_sec: 0, tv_nsec: 0 }
+ Timespec::new(0, 0)
}
- fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
- Timespec { tv_sec, tv_nsec }
+ const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
+ assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
+ // SAFETY: The assert above checks tv_nsec is within the valid range
+ Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } }
}
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
@@ -75,12 +83,12 @@ impl Timespec {
//
// Ideally this code could be rearranged such that it more
// directly expresses the lower-cost behavior we want from it.
- let (secs, nsec) = if self.tv_nsec >= other.tv_nsec {
- ((self.tv_sec - other.tv_sec) as u64, (self.tv_nsec - other.tv_nsec) as u32)
+ let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 {
+ ((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0)
} else {
(
(self.tv_sec - other.tv_sec - 1) as u64,
- self.tv_nsec as u32 + (NSEC_PER_SEC as u32) - other.tv_nsec as u32,
+ self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0,
)
};
@@ -102,7 +110,7 @@ impl Timespec {
// Nano calculations can't overflow because nanos are <1B which fit
// in a u32.
- let mut nsec = other.subsec_nanos() + self.tv_nsec as u32;
+ let mut nsec = other.subsec_nanos() + self.tv_nsec.0;
if nsec >= NSEC_PER_SEC as u32 {
nsec -= NSEC_PER_SEC as u32;
secs = secs.checked_add(1)?;
@@ -118,7 +126,7 @@ impl Timespec {
.and_then(|secs| self.tv_sec.checked_sub(secs))?;
// Similar to above, nanos can't overflow.
- let mut nsec = self.tv_nsec as i32 - other.subsec_nanos() as i32;
+ let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32;
if nsec < 0 {
nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1)?;
@@ -130,7 +138,7 @@ impl Timespec {
pub fn to_timespec(&self) -> Option<libc::timespec> {
Some(libc::timespec {
tv_sec: self.tv_sec.try_into().ok()?,
- tv_nsec: self.tv_nsec.try_into().ok()?,
+ tv_nsec: self.tv_nsec.0.try_into().ok()?,
})
}
}
@@ -293,7 +301,7 @@ mod inner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Instant")
.field("tv_sec", &self.t.tv_sec)
- .field("tv_nsec", &self.t.tv_nsec)
+ .field("tv_nsec", &self.t.tv_nsec.0)
.finish()
}
}
@@ -334,7 +342,7 @@ mod inner {
let mut t = MaybeUninit::uninit();
cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap();
let t = unsafe { t.assume_init() };
- return Timespec { tv_sec: t.tv_sec, tv_nsec: t.tv_nsec as i64 };
+ return Timespec::new(t.tv_sec, t.tv_nsec as i64);
}
}
diff --git a/library/std/src/sys/unsupported/io.rs b/library/std/src/sys/unsupported/io.rs
index d5f475b43..82610ffab 100644
--- a/library/std/src/sys/unsupported/io.rs
+++ b/library/std/src/sys/unsupported/io.rs
@@ -45,3 +45,7 @@ impl<'a> IoSliceMut<'a> {
self.0
}
}
+
+pub fn is_terminal<T>(_: &T) -> bool {
+ false
+}
diff --git a/library/std/src/sys/unsupported/locks/condvar.rs b/library/std/src/sys/unsupported/locks/condvar.rs
index e703fd0d2..527a26a12 100644
--- a/library/std/src/sys/unsupported/locks/condvar.rs
+++ b/library/std/src/sys/unsupported/locks/condvar.rs
@@ -7,6 +7,7 @@ pub type MovableCondvar = Condvar;
impl Condvar {
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Condvar {
Condvar {}
}
diff --git a/library/std/src/sys/unsupported/locks/mod.rs b/library/std/src/sys/unsupported/locks/mod.rs
index d412ff152..602a2d623 100644
--- a/library/std/src/sys/unsupported/locks/mod.rs
+++ b/library/std/src/sys/unsupported/locks/mod.rs
@@ -3,4 +3,4 @@ mod mutex;
mod rwlock;
pub use condvar::{Condvar, MovableCondvar};
pub use mutex::{MovableMutex, Mutex};
-pub use rwlock::{MovableRwLock, RwLock};
+pub use rwlock::MovableRwLock;
diff --git a/library/std/src/sys/unsupported/locks/mutex.rs b/library/std/src/sys/unsupported/locks/mutex.rs
index 2be0b34b9..87ea475c6 100644
--- a/library/std/src/sys/unsupported/locks/mutex.rs
+++ b/library/std/src/sys/unsupported/locks/mutex.rs
@@ -12,6 +12,7 @@ unsafe impl Sync for Mutex {} // no threads on this platform
impl Mutex {
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Mutex {
Mutex { locked: Cell::new(false) }
}
diff --git a/library/std/src/sys/unsupported/locks/rwlock.rs b/library/std/src/sys/unsupported/locks/rwlock.rs
index aca5fb715..5292691b9 100644
--- a/library/std/src/sys/unsupported/locks/rwlock.rs
+++ b/library/std/src/sys/unsupported/locks/rwlock.rs
@@ -12,6 +12,7 @@ unsafe impl Sync for RwLock {} // no threads on this platform
impl RwLock {
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> RwLock {
RwLock { mode: Cell::new(0) }
}
diff --git a/library/std/src/sys/unsupported/thread_local_dtor.rs b/library/std/src/sys/unsupported/thread_local_dtor.rs
index 85d660983..84660ea58 100644
--- a/library/std/src/sys/unsupported/thread_local_dtor.rs
+++ b/library/std/src/sys/unsupported/thread_local_dtor.rs
@@ -1,5 +1,6 @@
#![unstable(feature = "thread_local_internals", issue = "none")]
+#[cfg_attr(target_family = "wasm", allow(unused))] // unused on wasm32-unknown-unknown
pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern "C" fn(*mut u8)) {
// FIXME: right now there is no concept of "thread exit", but this is likely
// going to show up at some point in the form of an exported symbol that the
diff --git a/library/std/src/sys/unsupported/thread_local_key.rs b/library/std/src/sys/unsupported/thread_local_key.rs
index c31b61cbf..b6e5e4cd2 100644
--- a/library/std/src/sys/unsupported/thread_local_key.rs
+++ b/library/std/src/sys/unsupported/thread_local_key.rs
@@ -19,8 +19,3 @@ pub unsafe fn get(_key: Key) -> *mut u8 {
pub unsafe fn destroy(_key: Key) {
panic!("should not be used on this target");
}
-
-#[inline]
-pub fn requires_synchronized_create() -> bool {
- panic!("should not be used on this target");
-}
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 510cf36b1..d4866bbc3 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -1,7 +1,7 @@
#![deny(unsafe_op_in_unsafe_fn)]
use super::fd::WasiFd;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
use crate::iter;
@@ -12,6 +12,7 @@ use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd
use crate::path::{Path, PathBuf};
use crate::ptr;
use crate::sync::Arc;
+use crate::sys::common::small_c_string::run_path_with_cstr;
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -65,8 +66,8 @@ pub struct FilePermissions {
#[derive(Copy, Clone, Debug, Default)]
pub struct FileTimes {
- accessed: Option<wasi::Timestamp>,
- modified: Option<wasi::Timestamp>,
+ accessed: Option<SystemTime>,
+ modified: Option<SystemTime>,
}
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
@@ -120,11 +121,11 @@ impl FilePermissions {
impl FileTimes {
pub fn set_accessed(&mut self, t: SystemTime) {
- self.accessed = Some(t.to_wasi_timestamp_or_panic());
+ self.accessed = Some(t);
}
pub fn set_modified(&mut self, t: SystemTime) {
- self.modified = Some(t.to_wasi_timestamp_or_panic());
+ self.modified = Some(t);
}
}
@@ -476,9 +477,16 @@ impl File {
}
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
+ let to_timestamp = |time: Option<SystemTime>| {
+ match time {
+ Some(time) if let Some(ts) = time.to_wasi_timestamp() => Ok(ts),
+ Some(_) => Err(io::const_io_error!(io::ErrorKind::InvalidInput, "timestamp is too large to set as a file time")),
+ None => Ok(0),
+ }
+ };
self.fd.filestat_set_times(
- times.accessed.unwrap_or(0),
- times.modified.unwrap_or(0),
+ to_timestamp(times.accessed)?,
+ to_timestamp(times.modified)?,
times.accessed.map_or(0, |_| wasi::FSTFLAGS_ATIM)
| times.modified.map_or(0, |_| wasi::FSTFLAGS_MTIM),
)
@@ -687,51 +695,52 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
/// Note that this can fail if `p` doesn't look like it can be opened relative
/// to any pre-opened file descriptor.
fn open_parent(p: &Path) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
- let p = CString::new(p.as_os_str().as_bytes())?;
- let mut buf = Vec::<u8>::with_capacity(512);
- loop {
- unsafe {
- let mut relative_path = buf.as_ptr().cast();
- let mut abs_prefix = ptr::null();
- let fd = __wasilibc_find_relpath(
- p.as_ptr(),
- &mut abs_prefix,
- &mut relative_path,
- buf.capacity(),
- );
- if fd == -1 {
- if io::Error::last_os_error().raw_os_error() == Some(libc::ENOMEM) {
- // Trigger the internal buffer resizing logic of `Vec` by requiring
- // more space than the current capacity.
- let cap = buf.capacity();
- buf.set_len(cap);
- buf.reserve(1);
- continue;
- }
- let msg = format!(
- "failed to find a pre-opened file descriptor \
- through which {:?} could be opened",
- p
+ run_path_with_cstr(p, |p| {
+ let mut buf = Vec::<u8>::with_capacity(512);
+ loop {
+ unsafe {
+ let mut relative_path = buf.as_ptr().cast();
+ let mut abs_prefix = ptr::null();
+ let fd = __wasilibc_find_relpath(
+ p.as_ptr(),
+ &mut abs_prefix,
+ &mut relative_path,
+ buf.capacity(),
);
- return Err(io::Error::new(io::ErrorKind::Uncategorized, msg));
- }
- let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
+ if fd == -1 {
+ if io::Error::last_os_error().raw_os_error() == Some(libc::ENOMEM) {
+ // Trigger the internal buffer resizing logic of `Vec` by requiring
+ // more space than the current capacity.
+ let cap = buf.capacity();
+ buf.set_len(cap);
+ buf.reserve(1);
+ continue;
+ }
+ let msg = format!(
+ "failed to find a pre-opened file descriptor \
+ through which {:?} could be opened",
+ p
+ );
+ return Err(io::Error::new(io::ErrorKind::Uncategorized, msg));
+ }
+ let relative = CStr::from_ptr(relative_path).to_bytes().to_vec();
- return Ok((
- ManuallyDrop::new(WasiFd::from_raw_fd(fd as c_int)),
- PathBuf::from(OsString::from_vec(relative)),
- ));
+ return Ok((
+ ManuallyDrop::new(WasiFd::from_raw_fd(fd as c_int)),
+ PathBuf::from(OsString::from_vec(relative)),
+ ));
+ }
}
- }
- extern "C" {
- pub fn __wasilibc_find_relpath(
- path: *const libc::c_char,
- abs_prefix: *mut *const libc::c_char,
- relative_path: *mut *const libc::c_char,
- relative_path_len: libc::size_t,
- ) -> libc::c_int;
- }
+ extern "C" {
+ pub fn __wasilibc_find_relpath(
+ path: *const libc::c_char,
+ abs_prefix: *mut *const libc::c_char,
+ relative_path: *mut *const libc::c_char,
+ relative_path_len: libc::size_t,
+ ) -> libc::c_int;
+ }
+ })
}
pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
diff --git a/library/std/src/sys/wasi/io.rs b/library/std/src/sys/wasi/io.rs
index ee017d13a..2cd45df88 100644
--- a/library/std/src/sys/wasi/io.rs
+++ b/library/std/src/sys/wasi/io.rs
@@ -1,6 +1,7 @@
#![deny(unsafe_op_in_unsafe_fn)]
use crate::marker::PhantomData;
+use crate::os::fd::{AsFd, AsRawFd};
use crate::slice;
#[derive(Copy, Clone)]
@@ -71,3 +72,8 @@ impl<'a> IoSliceMut<'a> {
unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.buf_len) }
}
}
+
+pub fn is_terminal(fd: &impl AsFd) -> bool {
+ let fd = fd.as_fd();
+ unsafe { libc::isatty(fd.as_raw_fd()) != 0 }
+}
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index 683a07a34..c8c47763a 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -25,6 +25,9 @@ pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;
+#[allow(unused)]
+#[path = "../wasm/atomics/futex.rs"]
+pub mod futex;
pub mod io;
#[path = "../unsupported/locks/mod.rs"]
pub mod locks;
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index c5229a188..f5513e999 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -1,14 +1,15 @@
#![deny(unsafe_op_in_unsafe_fn)]
-use crate::any::Any;
use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
+use crate::ops::Drop;
use crate::os::wasi::prelude::*;
use crate::path::{self, PathBuf};
use crate::str;
+use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
use crate::sys::memchr;
use crate::sys::unsupported;
use crate::vec;
@@ -23,10 +24,26 @@ mod libc {
}
}
-#[cfg(not(target_feature = "atomics"))]
-pub unsafe fn env_lock() -> impl Any {
- // No need for a lock if we're single-threaded, but this function will need
- // to get implemented for multi-threaded scenarios
+cfg_if::cfg_if! {
+ if #[cfg(target_feature = "atomics")] {
+ // Access to the environment must be protected by a lock in multi-threaded scenarios.
+ use crate::sync::{PoisonError, RwLock};
+ static ENV_LOCK: RwLock<()> = RwLock::new(());
+ pub fn env_read_lock() -> impl Drop {
+ ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+ }
+ pub fn env_write_lock() -> impl Drop {
+ ENV_LOCK.write().unwrap_or_else(PoisonError::into_inner)
+ }
+ } else {
+ // No need for a lock if we are single-threaded.
+ pub fn env_read_lock() -> impl Drop {
+ Box::new(())
+ }
+ pub fn env_write_lock() -> impl Drop {
+ Box::new(())
+ }
+ }
}
pub fn errno() -> i32 {
@@ -77,13 +94,10 @@ pub fn getcwd() -> io::Result<PathBuf> {
}
pub fn chdir(p: &path::Path) -> io::Result<()> {
- let p: &OsStr = p.as_ref();
- let p = CString::new(p.as_bytes())?;
- unsafe {
- match libc::chdir(p.as_ptr()) == (0 as libc::c_int) {
- true => Ok(()),
- false => Err(io::Error::last_os_error()),
- }
+ let result = run_path_with_cstr(p, |p| unsafe { Ok(libc::chdir(p.as_ptr())) })?;
+ match result == (0 as libc::c_int) {
+ true => Ok(()),
+ false => Err(io::Error::last_os_error()),
}
}
@@ -146,7 +160,7 @@ impl Iterator for Env {
pub fn env() -> Env {
unsafe {
- let _guard = env_lock();
+ let _guard = env_read_lock();
let mut environ = libc::environ;
let mut result = Vec::new();
if !environ.is_null() {
@@ -176,35 +190,32 @@ pub fn env() -> Env {
}
pub fn getenv(k: &OsStr) -> Option<OsString> {
- let k = CString::new(k.as_bytes()).ok()?;
- unsafe {
- let _guard = env_lock();
- let s = libc::getenv(k.as_ptr()) as *const libc::c_char;
- if s.is_null() {
- None
- } else {
- Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
- }
+ let s = run_with_cstr(k.as_bytes(), |k| unsafe {
+ let _guard = env_read_lock();
+ Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
+ })
+ .ok()?;
+ if s.is_null() {
+ None
+ } else {
+ Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
}
}
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
- let k = CString::new(k.as_bytes())?;
- let v = CString::new(v.as_bytes())?;
-
- unsafe {
- let _guard = env_lock();
- cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
- }
+ run_with_cstr(k.as_bytes(), |k| {
+ run_with_cstr(v.as_bytes(), |v| unsafe {
+ let _guard = env_write_lock();
+ cvt(libc::setenv(k.as_ptr(), v.as_ptr(), 1)).map(drop)
+ })
+ })
}
pub fn unsetenv(n: &OsStr) -> io::Result<()> {
- let nbuf = CString::new(n.as_bytes())?;
-
- unsafe {
- let _guard = env_lock();
+ run_with_cstr(n.as_bytes(), |nbuf| unsafe {
+ let _guard = env_write_lock();
cvt(libc::unsetenv(nbuf.as_ptr())).map(drop)
- }
+ })
}
pub fn temp_dir() -> PathBuf {
diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs
index d2081771b..4cc0e4ed5 100644
--- a/library/std/src/sys/wasi/stdio.rs
+++ b/library/std/src/sys/wasi/stdio.rs
@@ -4,7 +4,7 @@ use super::fd::WasiFd;
use crate::io::{self, IoSlice, IoSliceMut};
use crate::mem::ManuallyDrop;
use crate::os::raw;
-use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd};
+use crate::os::wasi::io::{AsRawFd, FromRawFd};
pub struct Stdin;
pub struct Stdout;
@@ -23,13 +23,6 @@ impl AsRawFd for Stdin {
}
}
-impl AsFd for Stdin {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(0) }
- }
-}
-
impl io::Read for Stdin {
fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
self.read_vectored(&mut [IoSliceMut::new(data)])
@@ -58,13 +51,6 @@ impl AsRawFd for Stdout {
}
}
-impl AsFd for Stdout {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(1) }
- }
-}
-
impl io::Write for Stdout {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.write_vectored(&[IoSlice::new(data)])
@@ -96,13 +82,6 @@ impl AsRawFd for Stderr {
}
}
-impl AsFd for Stderr {
- #[inline]
- fn as_fd(&self) -> BorrowedFd<'_> {
- unsafe { BorrowedFd::borrow_raw(2) }
- }
-}
-
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.write_vectored(&[IoSlice::new(data)])
diff --git a/library/std/src/sys/wasi/time.rs b/library/std/src/sys/wasi/time.rs
index 3d326e491..016b06efb 100644
--- a/library/std/src/sys/wasi/time.rs
+++ b/library/std/src/sys/wasi/time.rs
@@ -47,8 +47,8 @@ impl SystemTime {
SystemTime(Duration::from_nanos(ts))
}
- pub fn to_wasi_timestamp_or_panic(&self) -> wasi::Timestamp {
- self.0.as_nanos().try_into().expect("time does not fit in WASI timestamp")
+ pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
+ self.0.as_nanos().try_into().ok()
}
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 4159efe2a..93838390b 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -57,7 +57,7 @@ cfg_if::cfg_if! {
mod futex_rwlock;
pub(crate) use futex_condvar::{Condvar, MovableCondvar};
pub(crate) use futex_mutex::{Mutex, MovableMutex};
- pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
+ pub(crate) use futex_rwlock::MovableRwLock;
}
#[path = "atomics/futex.rs"]
pub mod futex;
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 89d0ab59b..be6fc2ebb 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -71,6 +71,7 @@ pub type BCRYPT_ALG_HANDLE = LPVOID;
pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
pub type PLARGE_INTEGER = *mut c_longlong;
pub type PSRWLOCK = *mut SRWLOCK;
+pub type LPINIT_ONCE = *mut INIT_ONCE;
pub type SOCKET = crate::os::windows::raw::SOCKET;
pub type socklen_t = c_int;
@@ -126,6 +127,10 @@ pub const SECURITY_SQOS_PRESENT: DWORD = 0x00100000;
pub const FIONBIO: c_ulong = 0x8004667e;
+pub const MAX_PATH: usize = 260;
+
+pub const FILE_TYPE_PIPE: u32 = 3;
+
#[repr(C)]
#[derive(Copy)]
pub struct WIN32_FIND_DATAW {
@@ -194,6 +199,9 @@ pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;
pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { ptr: ptr::null_mut() };
pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: ptr::null_mut() };
+pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { ptr: ptr::null_mut() };
+
+pub const INIT_ONCE_INIT_FAILED: DWORD = 0x00000004;
pub const DETACHED_PROCESS: DWORD = 0x00000008;
pub const CREATE_NEW_PROCESS_GROUP: DWORD = 0x00000200;
@@ -279,7 +287,6 @@ pub const STATUS_INVALID_PARAMETER: NTSTATUS = 0xc000000d_u32 as _;
pub const STATUS_PENDING: NTSTATUS = 0x103 as _;
pub const STATUS_END_OF_FILE: NTSTATUS = 0xC0000011_u32 as _;
pub const STATUS_NOT_IMPLEMENTED: NTSTATUS = 0xC0000002_u32 as _;
-pub const STATUS_NOT_SUPPORTED: NTSTATUS = 0xC00000BB_u32 as _;
// Equivalent to the `NT_SUCCESS` C preprocessor macro.
// See: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-ntstatus-values
@@ -289,6 +296,7 @@ pub fn nt_success(status: NTSTATUS) -> bool {
// "RNG\0"
pub const BCRYPT_RNG_ALGORITHM: &[u16] = &[b'R' as u16, b'N' as u16, b'G' as u16, 0];
+pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002;
#[repr(C)]
pub struct UNICODE_STRING {
@@ -535,6 +543,12 @@ pub struct SYMBOLIC_LINK_REPARSE_BUFFER {
/// 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,
pub SubstituteNameLength: c_ushort,
@@ -565,6 +579,10 @@ pub struct CONDITION_VARIABLE {
pub struct SRWLOCK {
pub ptr: LPVOID,
}
+#[repr(C)]
+pub struct INIT_ONCE {
+ pub ptr: LPVOID,
+}
#[repr(C)]
pub struct REPARSE_MOUNTPOINT_DATA_BUFFER {
@@ -817,10 +835,6 @@ if #[cfg(not(target_vendor = "uwp"))] {
#[link(name = "advapi32")]
extern "system" {
- // Forbidden when targeting UWP
- #[link_name = "SystemFunction036"]
- pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
-
// Allowed but unused by UWP
pub fn OpenProcessToken(
ProcessHandle: HANDLE,
@@ -959,6 +973,7 @@ extern "system" {
pub fn TlsAlloc() -> DWORD;
pub fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
pub fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
+ pub fn TlsFree(dwTlsIndex: DWORD) -> BOOL;
pub fn GetLastError() -> DWORD;
pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL;
pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL;
@@ -1101,6 +1116,7 @@ extern "system" {
lpFileInformation: LPVOID,
dwBufferSize: DWORD,
) -> BOOL;
+ pub fn GetFileType(hfile: HANDLE) -> DWORD;
pub fn SleepConditionVariableSRW(
ConditionVariable: PCONDITION_VARIABLE,
SRWLock: PSRWLOCK,
@@ -1118,6 +1134,14 @@ extern "system" {
pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
+ pub fn InitOnceBeginInitialize(
+ lpInitOnce: LPINIT_ONCE,
+ dwFlags: DWORD,
+ fPending: LPBOOL,
+ lpContext: *mut LPVOID,
+ ) -> BOOL;
+ pub fn InitOnceComplete(lpInitOnce: LPINIT_ONCE, dwFlags: DWORD, lpContext: LPVOID) -> BOOL;
+
pub fn CompareStringOrdinal(
lpString1: LPCWSTR,
cchCount1: c_int,
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 155d0297e..378098038 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1,5 +1,6 @@
use crate::os::windows::prelude::*;
+use crate::borrow::Cow;
use crate::ffi::OsString;
use crate::fmt;
use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom};
@@ -572,6 +573,14 @@ impl File {
"Cannot set file timestamp to 0",
));
}
+ let is_max =
+ |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX;
+ if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) {
+ return Err(io::const_io_error!(
+ io::ErrorKind::InvalidInput,
+ "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF",
+ ));
+ }
cvt(unsafe {
c::SetFileTime(self.as_handle(), None, times.accessed.as_ref(), times.modified.as_ref())
})?;
@@ -711,7 +720,7 @@ impl<'a> DirBuffIter<'a> {
}
}
impl<'a> Iterator for DirBuffIter<'a> {
- type Item = (&'a [u16], bool);
+ type Item = (Cow<'a, [u16]>, bool);
fn next(&mut self) -> Option<Self::Item> {
use crate::mem::size_of;
let buffer = &self.buffer?[self.cursor..];
@@ -726,15 +735,19 @@ impl<'a> Iterator for DirBuffIter<'a> {
// `FileNameLength` bytes)
let (name, is_directory, next_entry) = unsafe {
let info = buffer.as_ptr().cast::<c::FILE_ID_BOTH_DIR_INFO>();
- // Guaranteed to be aligned in documentation for
+ // While this is guaranteed to be aligned in documentation for
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_id_both_dir_info
- assert!(info.is_aligned());
- let next_entry = (*info).NextEntryOffset as usize;
- let name = crate::slice::from_raw_parts(
+ // it does not seem that reality is so kind, and assuming this
+ // caused crashes in some cases (https://github.com/rust-lang/rust/issues/104530)
+ // presumably, this can be blamed on buggy filesystem drivers, but who knows.
+ let next_entry = ptr::addr_of!((*info).NextEntryOffset).read_unaligned() as usize;
+ let length = ptr::addr_of!((*info).FileNameLength).read_unaligned() as usize;
+ let attrs = ptr::addr_of!((*info).FileAttributes).read_unaligned();
+ let name = from_maybe_unaligned(
ptr::addr_of!((*info).FileName).cast::<u16>(),
- (*info).FileNameLength as usize / size_of::<u16>(),
+ length / size_of::<u16>(),
);
- let is_directory = ((*info).FileAttributes & c::FILE_ATTRIBUTE_DIRECTORY) != 0;
+ let is_directory = (attrs & c::FILE_ATTRIBUTE_DIRECTORY) != 0;
(name, is_directory, next_entry)
};
@@ -747,13 +760,21 @@ impl<'a> Iterator for DirBuffIter<'a> {
// Skip `.` and `..` pseudo entries.
const DOT: u16 = b'.' as u16;
- match name {
+ match &name[..] {
[DOT] | [DOT, DOT] => self.next(),
_ => Some((name, is_directory)),
}
}
}
+unsafe fn from_maybe_unaligned<'a>(p: *const u16, len: usize) -> Cow<'a, [u16]> {
+ if p.is_aligned() {
+ Cow::Borrowed(crate::slice::from_raw_parts(p, len))
+ } else {
+ Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect())
+ }
+}
+
/// Open a link relative to the parent directory, ensure no symlinks are followed.
fn open_link_no_reparse(parent: &File, name: &[u16], access: u32) -> io::Result<File> {
// This is implemented using the lower level `NtCreateFile` function as
@@ -1109,13 +1130,13 @@ fn remove_dir_all_iterative(f: &File, delete: fn(&File) -> io::Result<()>) -> io
if is_directory {
let child_dir = open_link_no_reparse(
&dir,
- name,
+ &name,
c::SYNCHRONIZE | c::DELETE | c::FILE_LIST_DIRECTORY,
)?;
dirlist.push(child_dir);
} else {
for i in 1..=MAX_RETRIES {
- let result = open_link_no_reparse(&dir, name, c::SYNCHRONIZE | c::DELETE);
+ let result = open_link_no_reparse(&dir, &name, c::SYNCHRONIZE | c::DELETE);
match result {
Ok(f) => delete(&f)?,
// Already deleted, so skip.
diff --git a/library/std/src/sys/windows/io.rs b/library/std/src/sys/windows/io.rs
index fb06df1f8..2cc34c986 100644
--- a/library/std/src/sys/windows/io.rs
+++ b/library/std/src/sys/windows/io.rs
@@ -1,6 +1,10 @@
use crate::marker::PhantomData;
+use crate::mem::size_of;
+use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
use crate::slice;
-use crate::sys::c;
+use crate::sys::{c, Align8};
+use core;
+use libc;
#[derive(Copy, Clone)]
#[repr(transparent)]
@@ -78,3 +82,73 @@ impl<'a> IoSliceMut<'a> {
unsafe { slice::from_raw_parts_mut(self.vec.buf as *mut u8, self.vec.len as usize) }
}
}
+
+pub fn is_terminal(h: &impl AsHandle) -> bool {
+ unsafe { handle_is_console(h.as_handle()) }
+}
+
+unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
+ let handle = handle.as_raw_handle();
+
+ // A null handle means the process has no console.
+ if handle.is_null() {
+ return false;
+ }
+
+ let mut out = 0;
+ if c::GetConsoleMode(handle, &mut out) != 0 {
+ // False positives aren't possible. If we got a console then we definitely have a console.
+ return true;
+ }
+
+ // At this point, we *could* have a false negative. We can determine that this is a true
+ // negative if we can detect the presence of a console on any of the standard I/O streams. If
+ // another stream has a console, then we know we're in a Windows console and can therefore
+ // trust the negative.
+ for std_handle in [c::STD_INPUT_HANDLE, c::STD_OUTPUT_HANDLE, c::STD_ERROR_HANDLE] {
+ let std_handle = c::GetStdHandle(std_handle);
+ if !std_handle.is_null()
+ && std_handle != handle
+ && c::GetConsoleMode(std_handle, &mut out) != 0
+ {
+ return false;
+ }
+ }
+
+ // Otherwise, we fall back to an msys hack to see if we can detect the presence of a pty.
+ msys_tty_on(handle)
+}
+
+unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
+ // Early return if the handle is not a pipe.
+ if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
+ 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]);
+ let res = c::GetFileInformationByHandleEx(
+ handle,
+ c::FileNameInfo,
+ name_info_bytes.0.as_mut_ptr() as *mut libc::c_void,
+ SIZE 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);
+ let name = String::from_utf16_lossy(s);
+ // Get the file name only.
+ let name = name.rsplit('\\').next().unwrap_or(&name);
+ // This checks whether 'pty' exists in the file name, which indicates that
+ // a pseudo-terminal is attached. To mitigate against false positives
+ // (e.g., an actual file name that contains 'pty'), we also require that
+ // the file name begins with either the strings 'msys-' or 'cygwin-'.)
+ let is_msys = name.starts_with("msys-") || name.starts_with("cygwin-");
+ let is_pty = name.contains("-pty");
+ is_msys && is_pty
+}
diff --git a/library/std/src/sys/windows/locks/mod.rs b/library/std/src/sys/windows/locks/mod.rs
index d412ff152..602a2d623 100644
--- a/library/std/src/sys/windows/locks/mod.rs
+++ b/library/std/src/sys/windows/locks/mod.rs
@@ -3,4 +3,4 @@ mod mutex;
mod rwlock;
pub use condvar::{Condvar, MovableCondvar};
pub use mutex::{MovableMutex, Mutex};
-pub use rwlock::{MovableRwLock, RwLock};
+pub use rwlock::MovableRwLock;
diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs
index 02d5af471..9cbb4ef19 100644
--- a/library/std/src/sys/windows/process.rs
+++ b/library/std/src/sys/windows/process.rs
@@ -16,6 +16,7 @@ use crate::os::windows::ffi::{OsStrExt, OsStringExt};
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle};
use crate::path::{Path, PathBuf};
use crate::ptr;
+use crate::sync::Mutex;
use crate::sys::args::{self, Arg};
use crate::sys::c;
use crate::sys::c::NonZeroDWORD;
@@ -25,7 +26,6 @@ use crate::sys::handle::Handle;
use crate::sys::path;
use crate::sys::pipe::{self, AnonPipe};
use crate::sys::stdio;
-use crate::sys_common::mutex::StaticMutex;
use crate::sys_common::process::{CommandEnv, CommandEnvs};
use crate::sys_common::IntoInner;
@@ -301,9 +301,9 @@ impl Command {
//
// For more information, msdn also has an article about this race:
// https://support.microsoft.com/kb/315939
- static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new();
+ static CREATE_PROCESS_LOCK: Mutex<()> = Mutex::new(());
- let _guard = unsafe { CREATE_PROCESS_LOCK.lock() };
+ let _guard = CREATE_PROCESS_LOCK.lock();
let mut pipes = StdioPipes { stdin: None, stdout: None, stderr: None };
let null = Stdio::Null;
diff --git a/library/std/src/sys/windows/rand.rs b/library/std/src/sys/windows/rand.rs
index d6cd8f802..b5a49489d 100644
--- a/library/std/src/sys/windows/rand.rs
+++ b/library/std/src/sys/windows/rand.rs
@@ -13,15 +13,12 @@
//! but significant number of users to experience panics caused by a failure of
//! this function. See [#94098].
//!
-//! The current version changes this to use the `BCRYPT_RNG_ALG_HANDLE`
-//! [Pseudo-handle], which gets the default RNG algorithm without querying the
-//! system preference thus hopefully avoiding the previous issue.
-//! This is only supported on Windows 10+ so a fallback is used for older versions.
+//! The current version falls back to using `BCryptOpenAlgorithmProvider` if
+//! `BCRYPT_USE_SYSTEM_PREFERRED_RNG` fails for any reason.
//!
//! [#94098]: https://github.com/rust-lang/rust/issues/94098
//! [`RtlGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
//! [`BCryptGenRandom`]: https://docs.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptgenrandom
-//! [Pseudo-handle]: https://docs.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-pseudo-handles
use crate::mem;
use crate::ptr;
use crate::sys::c;
@@ -33,37 +30,35 @@ use crate::sys::c;
/// [`HashMap`]: crate::collections::HashMap
/// [`RandomState`]: crate::collections::hash_map::RandomState
pub fn hashmap_random_keys() -> (u64, u64) {
- Rng::open().and_then(|rng| rng.gen_random_keys()).unwrap_or_else(fallback_rng)
+ Rng::SYSTEM.gen_random_keys().unwrap_or_else(fallback_rng)
}
-struct Rng(c::BCRYPT_ALG_HANDLE);
+struct Rng {
+ algorithm: c::BCRYPT_ALG_HANDLE,
+ flags: u32,
+}
impl Rng {
- #[cfg(miri)]
- fn open() -> Result<Self, c::NTSTATUS> {
- const BCRYPT_RNG_ALG_HANDLE: c::BCRYPT_ALG_HANDLE = ptr::invalid_mut(0x81);
- let _ = (
- c::BCryptOpenAlgorithmProvider,
- c::BCryptCloseAlgorithmProvider,
- c::BCRYPT_RNG_ALGORITHM,
- c::STATUS_NOT_SUPPORTED,
- );
- Ok(Self(BCRYPT_RNG_ALG_HANDLE))
+ const SYSTEM: Self = unsafe { Self::new(ptr::null_mut(), c::BCRYPT_USE_SYSTEM_PREFERRED_RNG) };
+
+ /// Create the RNG from an existing algorithm handle.
+ ///
+ /// # Safety
+ ///
+ /// The handle must either be null or a valid algorithm handle.
+ const unsafe fn new(algorithm: c::BCRYPT_ALG_HANDLE, flags: u32) -> Self {
+ Self { algorithm, flags }
}
- #[cfg(not(miri))]
- // Open a handle to the RNG algorithm.
+
+ /// Open a handle to the RNG algorithm.
fn open() -> Result<Self, c::NTSTATUS> {
use crate::sync::atomic::AtomicPtr;
use crate::sync::atomic::Ordering::{Acquire, Release};
- const ERROR_VALUE: c::LPVOID = ptr::invalid_mut(usize::MAX);
// An atomic is used so we don't need to reopen the handle every time.
static HANDLE: AtomicPtr<crate::ffi::c_void> = AtomicPtr::new(ptr::null_mut());
let mut handle = HANDLE.load(Acquire);
- // We use a sentinel value to designate an error occurred last time.
- if handle == ERROR_VALUE {
- Err(c::STATUS_NOT_SUPPORTED)
- } else if handle.is_null() {
+ if handle.is_null() {
let status = unsafe {
c::BCryptOpenAlgorithmProvider(
&mut handle,
@@ -80,13 +75,12 @@ impl Rng {
unsafe { c::BCryptCloseAlgorithmProvider(handle, 0) };
handle = previous_handle;
}
- Ok(Self(handle))
+ Ok(unsafe { Self::new(handle, 0) })
} else {
- HANDLE.store(ERROR_VALUE, Release);
Err(status)
}
} else {
- Ok(Self(handle))
+ Ok(unsafe { Self::new(handle, 0) })
}
}
@@ -94,33 +88,19 @@ impl Rng {
let mut v = (0, 0);
let status = unsafe {
let size = mem::size_of_val(&v).try_into().unwrap();
- c::BCryptGenRandom(self.0, ptr::addr_of_mut!(v).cast(), size, 0)
+ c::BCryptGenRandom(self.algorithm, ptr::addr_of_mut!(v).cast(), size, self.flags)
};
if c::nt_success(status) { Ok(v) } else { Err(status) }
}
}
-/// Generate random numbers using the fallback RNG function (RtlGenRandom)
-#[cfg(not(target_vendor = "uwp"))]
+/// Generate random numbers using the fallback RNG function
#[inline(never)]
fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
- let mut v = (0, 0);
- let ret =
- unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
-
- if ret != 0 {
- v
- } else {
- panic!(
- "RNG broken: {rng_status:#x}, fallback RNG broken: {}",
- crate::io::Error::last_os_error()
- )
+ match Rng::open().and_then(|rng| rng.gen_random_keys()) {
+ Ok(keys) => keys,
+ Err(status) => {
+ panic!("RNG broken: {rng_status:#x}, fallback RNG broken: {status:#x}")
+ }
}
}
-
-/// We can't use RtlGenRandom with UWP, so there is no fallback
-#[cfg(target_vendor = "uwp")]
-#[inline(never)]
-fn fallback_rng(rng_status: c::NTSTATUS) -> (u64, u64) {
- panic!("RNG broken: {rng_status:#x} fallback RNG broken: RtlGenRandom() not supported on UWP");
-}
diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs
index ec670238e..17628b757 100644
--- a/library/std/src/sys/windows/thread_local_key.rs
+++ b/library/std/src/sys/windows/thread_local_key.rs
@@ -1,11 +1,16 @@
-use crate::mem::ManuallyDrop;
+use crate::cell::UnsafeCell;
use crate::ptr;
-use crate::sync::atomic::AtomicPtr;
-use crate::sync::atomic::Ordering::SeqCst;
+use crate::sync::atomic::{
+ AtomicPtr, AtomicU32,
+ Ordering::{AcqRel, Acquire, Relaxed, Release},
+};
use crate::sys::c;
-pub type Key = c::DWORD;
-pub type Dtor = unsafe extern "C" fn(*mut u8);
+#[cfg(test)]
+mod tests;
+
+type Key = c::DWORD;
+type Dtor = unsafe extern "C" fn(*mut u8);
// Turns out, like pretty much everything, Windows is pretty close the
// functionality that Unix provides, but slightly different! In the case of
@@ -22,60 +27,109 @@ pub type Dtor = unsafe extern "C" fn(*mut u8);
// To accomplish this feat, we perform a number of threads, all contained
// within this module:
//
-// * All TLS destructors are tracked by *us*, not the windows runtime. This
+// * All TLS destructors are tracked by *us*, not the Windows runtime. This
// means that we have a global list of destructors for each TLS key that
// we know about.
// * When a thread exits, we run over the entire list and run dtors for all
// non-null keys. This attempts to match Unix semantics in this regard.
//
-// This ends up having the overhead of using a global list, having some
-// locks here and there, and in general just adding some more code bloat. We
-// attempt to optimize runtime by forgetting keys that don't have
-// destructors, but this only gets us so far.
-//
// For more details and nitty-gritty, see the code sections below!
//
// [1]: https://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
-// [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base
-// /threading/thread_local_storage_win.cc#L42
+// [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base/threading/thread_local_storage_win.cc#L42
-// -------------------------------------------------------------------------
-// Native bindings
-//
-// This section is just raw bindings to the native functions that Windows
-// provides, There's a few extra calls to deal with destructors.
+pub struct StaticKey {
+ /// The key value shifted up by one. Since TLS_OUT_OF_INDEXES == DWORD::MAX
+ /// is not a valid key value, this allows us to use zero as sentinel value
+ /// without risking overflow.
+ key: AtomicU32,
+ dtor: Option<Dtor>,
+ next: AtomicPtr<StaticKey>,
+ /// Currently, destructors cannot be unregistered, so we cannot use racy
+ /// initialization for keys. Instead, we need synchronize initialization.
+ /// Use the Windows-provided `Once` since it does not require TLS.
+ once: UnsafeCell<c::INIT_ONCE>,
+}
-#[inline]
-pub unsafe fn create(dtor: Option<Dtor>) -> Key {
- let key = c::TlsAlloc();
- assert!(key != c::TLS_OUT_OF_INDEXES);
- if let Some(f) = dtor {
- register_dtor(key, f);
+impl StaticKey {
+ #[inline]
+ pub const fn new(dtor: Option<Dtor>) -> StaticKey {
+ StaticKey {
+ key: AtomicU32::new(0),
+ dtor,
+ next: AtomicPtr::new(ptr::null_mut()),
+ once: UnsafeCell::new(c::INIT_ONCE_STATIC_INIT),
+ }
}
- key
-}
-#[inline]
-pub unsafe fn set(key: Key, value: *mut u8) {
- let r = c::TlsSetValue(key, value as c::LPVOID);
- debug_assert!(r != 0);
-}
+ #[inline]
+ pub unsafe fn set(&'static self, val: *mut u8) {
+ let r = c::TlsSetValue(self.key(), val.cast());
+ debug_assert_eq!(r, c::TRUE);
+ }
-#[inline]
-pub unsafe fn get(key: Key) -> *mut u8 {
- c::TlsGetValue(key) as *mut u8
-}
+ #[inline]
+ pub unsafe fn get(&'static self) -> *mut u8 {
+ c::TlsGetValue(self.key()).cast()
+ }
-#[inline]
-pub unsafe fn destroy(_key: Key) {
- rtabort!("can't destroy tls keys on windows")
-}
+ #[inline]
+ unsafe fn key(&'static self) -> Key {
+ match self.key.load(Acquire) {
+ 0 => self.init(),
+ key => key - 1,
+ }
+ }
+
+ #[cold]
+ unsafe fn init(&'static self) -> Key {
+ if self.dtor.is_some() {
+ let mut pending = c::FALSE;
+ let r = c::InitOnceBeginInitialize(self.once.get(), 0, &mut pending, ptr::null_mut());
+ assert_eq!(r, c::TRUE);
-#[inline]
-pub fn requires_synchronized_create() -> bool {
- true
+ if pending == c::FALSE {
+ // Some other thread initialized the key, load it.
+ self.key.load(Relaxed) - 1
+ } else {
+ let key = c::TlsAlloc();
+ if key == c::TLS_OUT_OF_INDEXES {
+ // Wakeup the waiting threads before panicking to avoid deadlock.
+ c::InitOnceComplete(self.once.get(), c::INIT_ONCE_INIT_FAILED, ptr::null_mut());
+ panic!("out of TLS indexes");
+ }
+
+ self.key.store(key + 1, Release);
+ register_dtor(self);
+
+ let r = c::InitOnceComplete(self.once.get(), 0, ptr::null_mut());
+ debug_assert_eq!(r, c::TRUE);
+
+ key
+ }
+ } else {
+ // If there is no destructor to clean up, we can use racy initialization.
+
+ let key = c::TlsAlloc();
+ assert_ne!(key, c::TLS_OUT_OF_INDEXES, "out of TLS indexes");
+
+ match self.key.compare_exchange(0, key + 1, AcqRel, Acquire) {
+ Ok(_) => key,
+ Err(new) => {
+ // Some other thread completed initialization first, so destroy
+ // our key and use theirs.
+ let r = c::TlsFree(key);
+ debug_assert_eq!(r, c::TRUE);
+ new - 1
+ }
+ }
+ }
+ }
}
+unsafe impl Send for StaticKey {}
+unsafe impl Sync for StaticKey {}
+
// -------------------------------------------------------------------------
// Dtor registration
//
@@ -96,29 +150,21 @@ pub fn requires_synchronized_create() -> bool {
// Typically processes have a statically known set of TLS keys which is pretty
// small, and we'd want to keep this memory alive for the whole process anyway
// really.
-//
-// Perhaps one day we can fold the `Box` here into a static allocation,
-// expanding the `StaticKey` structure to contain not only a slot for the TLS
-// key but also a slot for the destructor queue on windows. An optimization for
-// another day!
-
-static DTORS: AtomicPtr<Node> = AtomicPtr::new(ptr::null_mut());
-
-struct Node {
- dtor: Dtor,
- key: Key,
- next: *mut Node,
-}
-unsafe fn register_dtor(key: Key, dtor: Dtor) {
- let mut node = ManuallyDrop::new(Box::new(Node { key, dtor, next: ptr::null_mut() }));
+static DTORS: AtomicPtr<StaticKey> = AtomicPtr::new(ptr::null_mut());
- let mut head = DTORS.load(SeqCst);
+/// Should only be called once per key, otherwise loops or breaks may occur in
+/// the linked list.
+unsafe fn register_dtor(key: &'static StaticKey) {
+ let this = <*const StaticKey>::cast_mut(key);
+ // Use acquire ordering to pass along the changes done by the previously
+ // registered keys when we store the new head with release ordering.
+ let mut head = DTORS.load(Acquire);
loop {
- node.next = head;
- match DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) {
- Ok(_) => return, // nothing to drop, we successfully added the node to the list
- Err(cur) => head = cur,
+ key.next.store(head, Relaxed);
+ match DTORS.compare_exchange_weak(head, this, Release, Acquire) {
+ Ok(_) => break,
+ Err(new) => head = new,
}
}
}
@@ -214,25 +260,29 @@ unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv:
unsafe fn reference_tls_used() {}
}
-#[allow(dead_code)] // actually called above
+#[allow(dead_code)] // actually called below
unsafe fn run_dtors() {
- let mut any_run = true;
for _ in 0..5 {
- if !any_run {
- break;
- }
- any_run = false;
- let mut cur = DTORS.load(SeqCst);
+ let mut any_run = false;
+
+ // Use acquire ordering to observe key initialization.
+ let mut cur = DTORS.load(Acquire);
while !cur.is_null() {
- let ptr = c::TlsGetValue((*cur).key);
+ let key = (*cur).key.load(Relaxed) - 1;
+ let dtor = (*cur).dtor.unwrap();
+ let ptr = c::TlsGetValue(key);
if !ptr.is_null() {
- c::TlsSetValue((*cur).key, ptr::null_mut());
- ((*cur).dtor)(ptr as *mut _);
+ c::TlsSetValue(key, ptr::null_mut());
+ dtor(ptr as *mut _);
any_run = true;
}
- cur = (*cur).next;
+ cur = (*cur).next.load(Relaxed);
+ }
+
+ if !any_run {
+ break;
}
}
}
diff --git a/library/std/src/sys/windows/thread_local_key/tests.rs b/library/std/src/sys/windows/thread_local_key/tests.rs
new file mode 100644
index 000000000..c95f383fb
--- /dev/null
+++ b/library/std/src/sys/windows/thread_local_key/tests.rs
@@ -0,0 +1,53 @@
+use super::StaticKey;
+use crate::ptr;
+
+#[test]
+fn smoke() {
+ static K1: StaticKey = StaticKey::new(None);
+ static K2: StaticKey = StaticKey::new(None);
+
+ unsafe {
+ assert!(K1.get().is_null());
+ assert!(K2.get().is_null());
+ K1.set(ptr::invalid_mut(1));
+ K2.set(ptr::invalid_mut(2));
+ assert_eq!(K1.get() as usize, 1);
+ assert_eq!(K2.get() as usize, 2);
+ }
+}
+
+#[test]
+fn destructors() {
+ use crate::mem::ManuallyDrop;
+ use crate::sync::Arc;
+ use crate::thread;
+
+ unsafe extern "C" fn destruct(ptr: *mut u8) {
+ drop(Arc::from_raw(ptr as *const ()));
+ }
+
+ static KEY: StaticKey = StaticKey::new(Some(destruct));
+
+ let shared1 = Arc::new(());
+ let shared2 = Arc::clone(&shared1);
+
+ unsafe {
+ assert!(KEY.get().is_null());
+ KEY.set(Arc::into_raw(shared1) as *mut u8);
+ }
+
+ thread::spawn(move || unsafe {
+ assert!(KEY.get().is_null());
+ KEY.set(Arc::into_raw(shared2) as *mut u8);
+ })
+ .join()
+ .unwrap();
+
+ // Leak the Arc, let the TLS destructor clean it up.
+ let shared1 = unsafe { ManuallyDrop::new(Arc::from_raw(KEY.get() as *const ())) };
+ assert_eq!(
+ Arc::strong_count(&shared1),
+ 1,
+ "destructor should have dropped the other reference on thread exit"
+ );
+}
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 31164afdc..8807077cb 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -7,15 +7,14 @@ use crate::fmt;
use crate::io;
use crate::io::prelude::*;
use crate::path::{self, Path, PathBuf};
-use crate::sys_common::mutex::StaticMutex;
+use crate::sync::{Mutex, PoisonError};
/// Max number of frames to print.
const MAX_NB_FRAMES: usize = 100;
-// SAFETY: Don't attempt to lock this reentrantly.
-pub unsafe fn lock() -> impl Drop {
- static LOCK: StaticMutex = StaticMutex::new();
- LOCK.lock()
+pub fn lock() -> impl Drop {
+ static LOCK: Mutex<()> = Mutex::new(());
+ LOCK.lock().unwrap_or_else(PoisonError::into_inner)
}
/// Prints the current backtrace.
diff --git a/library/std/src/sys_common/condvar.rs b/library/std/src/sys_common/condvar.rs
index f3ac1061b..8bc5b2411 100644
--- a/library/std/src/sys_common/condvar.rs
+++ b/library/std/src/sys_common/condvar.rs
@@ -15,6 +15,7 @@ pub struct Condvar {
impl Condvar {
/// Creates a new condition variable for use.
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Self {
Self { inner: imp::MovableCondvar::new(), check: CondvarCheck::new() }
}
diff --git a/library/std/src/sys_common/condvar/check.rs b/library/std/src/sys_common/condvar/check.rs
index ce8f36704..4ac9e62bf 100644
--- a/library/std/src/sys_common/condvar/check.rs
+++ b/library/std/src/sys_common/condvar/check.rs
@@ -50,6 +50,7 @@ pub struct NoCheck;
#[allow(dead_code)]
impl NoCheck {
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Self {
Self
}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 80f56bf75..8c19f9332 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -27,17 +27,25 @@ pub mod io;
pub mod lazy_box;
pub mod memchr;
pub mod mutex;
+pub mod once;
pub mod process;
pub mod remutex;
pub mod rwlock;
pub mod thread;
pub mod thread_info;
pub mod thread_local_dtor;
-pub mod thread_local_key;
pub mod thread_parker;
pub mod wtf8;
cfg_if::cfg_if! {
+ if #[cfg(target_os = "windows")] {
+ pub use crate::sys::thread_local_key;
+ } else {
+ pub mod thread_local_key;
+ }
+}
+
+cfg_if::cfg_if! {
if #[cfg(any(target_os = "l4re",
target_os = "hermit",
feature = "restricted-std",
diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs
index 48479f5bd..98046f20f 100644
--- a/library/std/src/sys_common/mutex.rs
+++ b/library/std/src/sys_common/mutex.rs
@@ -1,49 +1,5 @@
use crate::sys::locks as imp;
-/// An OS-based mutual exclusion lock, meant for use in static variables.
-///
-/// This mutex has a const constructor ([`StaticMutex::new`]), does not
-/// implement `Drop` to cleanup resources, and causes UB when used reentrantly.
-///
-/// This mutex does not implement poisoning.
-///
-/// This is a wrapper around `imp::Mutex` that does *not* call `init()` and
-/// `destroy()`.
-pub struct StaticMutex(imp::Mutex);
-
-unsafe impl Sync for StaticMutex {}
-
-impl StaticMutex {
- /// Creates a new mutex for use.
- #[inline]
- pub const fn new() -> Self {
- Self(imp::Mutex::new())
- }
-
- /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex
- /// will be unlocked.
- ///
- /// It is undefined behaviour to call this function while locked by the
- /// same thread.
- #[inline]
- pub unsafe fn lock(&'static self) -> StaticMutexGuard {
- self.0.lock();
- StaticMutexGuard(&self.0)
- }
-}
-
-#[must_use]
-pub struct StaticMutexGuard(&'static imp::Mutex);
-
-impl Drop for StaticMutexGuard {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- self.0.unlock();
- }
- }
-}
-
/// An OS-based mutual exclusion lock.
///
/// This mutex cleans up its resources in its `Drop` implementation, may safely
@@ -61,6 +17,7 @@ unsafe impl Sync for MovableMutex {}
impl MovableMutex {
/// Creates a new mutex.
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Self {
Self(imp::MovableMutex::new())
}
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 3ad802afa..fad4a6333 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -2,12 +2,13 @@
mod tests;
use crate::cmp;
-use crate::ffi::CString;
+use crate::convert::{TryFrom, TryInto};
use crate::fmt;
use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
use crate::mem;
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
use crate::ptr;
+use crate::sys::common::small_c_string::run_with_cstr;
use crate::sys::net::netc as c;
use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -197,14 +198,15 @@ impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
init();
- let c_host = CString::new(host)?;
- let mut hints: c::addrinfo = unsafe { mem::zeroed() };
- hints.ai_socktype = c::SOCK_STREAM;
- let mut res = ptr::null_mut();
- unsafe {
- cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
- .map(|_| LookupHost { original: res, cur: res, port })
- }
+ run_with_cstr(host.as_bytes(), |c_host| {
+ let mut hints: c::addrinfo = unsafe { mem::zeroed() };
+ hints.ai_socktype = c::SOCK_STREAM;
+ let mut res = ptr::null_mut();
+ unsafe {
+ cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
+ .map(|_| LookupHost { original: res, cur: res, port })
+ }
+ })
}
}
diff --git a/library/std/src/sys_common/once/futex.rs b/library/std/src/sys_common/once/futex.rs
new file mode 100644
index 000000000..5c7e6c013
--- /dev/null
+++ b/library/std/src/sys_common/once/futex.rs
@@ -0,0 +1,134 @@
+use crate::cell::Cell;
+use crate::sync as public;
+use crate::sync::atomic::{
+ AtomicU32,
+ Ordering::{Acquire, Relaxed, Release},
+};
+use crate::sys::futex::{futex_wait, futex_wake_all};
+
+// On some platforms, the OS is very nice and handles the waiter queue for us.
+// This means we only need one atomic value with 5 states:
+
+/// No initialization has run yet, and no thread is currently using the Once.
+const INCOMPLETE: u32 = 0;
+/// Some thread has previously attempted to initialize the Once, but it panicked,
+/// so the Once is now poisoned. There are no other threads currently accessing
+/// this Once.
+const POISONED: u32 = 1;
+/// Some thread is currently attempting to run initialization. It may succeed,
+/// so all future threads need to wait for it to finish.
+const RUNNING: u32 = 2;
+/// Some thread is currently attempting to run initialization and there are threads
+/// waiting for it to finish.
+const QUEUED: u32 = 3;
+/// Initialization has completed and all future calls should finish immediately.
+const COMPLETE: u32 = 4;
+
+// Threads wait by setting the state to QUEUED and calling `futex_wait` on the state
+// variable. When the running thread finishes, it will wake all waiting threads using
+// `futex_wake_all`.
+
+pub struct OnceState {
+ poisoned: bool,
+ set_state_to: Cell<u32>,
+}
+
+impl OnceState {
+ #[inline]
+ pub fn is_poisoned(&self) -> bool {
+ self.poisoned
+ }
+
+ #[inline]
+ pub fn poison(&self) {
+ self.set_state_to.set(POISONED);
+ }
+}
+
+struct CompletionGuard<'a> {
+ state: &'a AtomicU32,
+ set_state_on_drop_to: u32,
+}
+
+impl<'a> Drop for CompletionGuard<'a> {
+ fn drop(&mut self) {
+ // Use release ordering to propagate changes to all threads checking
+ // up on the Once. `futex_wake_all` does its own synchronization, hence
+ // we do not need `AcqRel`.
+ if self.state.swap(self.set_state_on_drop_to, Release) == QUEUED {
+ futex_wake_all(&self.state);
+ }
+ }
+}
+
+pub struct Once {
+ state: AtomicU32,
+}
+
+impl Once {
+ #[inline]
+ pub const fn new() -> Once {
+ Once { state: AtomicU32::new(INCOMPLETE) }
+ }
+
+ #[inline]
+ pub fn is_completed(&self) -> bool {
+ // Use acquire ordering to make all initialization changes visible to the
+ // current thread.
+ self.state.load(Acquire) == COMPLETE
+ }
+
+ // 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.
+ #[cold]
+ #[track_caller]
+ pub fn call(&self, ignore_poisoning: bool, f: &mut impl FnMut(&public::OnceState)) {
+ let mut state = self.state.load(Acquire);
+ loop {
+ match state {
+ POISONED if !ignore_poisoning => {
+ // Panic to propagate the poison.
+ panic!("Once instance has previously been poisoned");
+ }
+ INCOMPLETE | POISONED => {
+ // Try to register the current thread as the one running.
+ if let Err(new) =
+ self.state.compare_exchange_weak(state, RUNNING, Acquire, Acquire)
+ {
+ state = new;
+ continue;
+ }
+ // `waiter_queue` will manage other waiting threads, and
+ // wake them up on drop.
+ let mut waiter_queue =
+ CompletionGuard { state: &self.state, set_state_on_drop_to: POISONED };
+ // Run the function, letting it know if we're poisoned or not.
+ let f_state = public::OnceState {
+ inner: OnceState {
+ poisoned: state == POISONED,
+ set_state_to: Cell::new(COMPLETE),
+ },
+ };
+ f(&f_state);
+ waiter_queue.set_state_on_drop_to = f_state.inner.set_state_to.get();
+ return;
+ }
+ RUNNING | QUEUED => {
+ // Set the state to QUEUED if it is not already.
+ if state == RUNNING
+ && let Err(new) = self.state.compare_exchange_weak(RUNNING, QUEUED, Relaxed, Acquire)
+ {
+ state = new;
+ continue;
+ }
+
+ futex_wait(&self.state, QUEUED, None);
+ state = self.state.load(Acquire);
+ }
+ COMPLETE => return,
+ _ => unreachable!("state is never set to invalid values"),
+ }
+ }
+ }
+}
diff --git a/library/std/src/sys_common/once/generic.rs b/library/std/src/sys_common/once/generic.rs
new file mode 100644
index 000000000..acf5f2471
--- /dev/null
+++ b/library/std/src/sys_common/once/generic.rs
@@ -0,0 +1,282 @@
+// Each `Once` has one word of atomic state, and this state is CAS'd on to
+// determine what to do. There are four possible state of a `Once`:
+//
+// * Incomplete - no initialization has run yet, and no thread is currently
+// using the Once.
+// * Poisoned - some thread has previously attempted to initialize the Once, but
+// it panicked, so the Once is now poisoned. There are no other
+// threads currently accessing this Once.
+// * Running - some thread is currently attempting to run initialization. It may
+// succeed, so all future threads need to wait for it to finish.
+// Note that this state is accompanied with a payload, described
+// below.
+// * Complete - initialization has completed and all future calls should finish
+// immediately.
+//
+// With 4 states we need 2 bits to encode this, and we use the remaining bits
+// in the word we have allocated as a queue of threads waiting for the thread
+// responsible for entering the RUNNING state. This queue is just a linked list
+// of Waiter nodes which is monotonically increasing in size. Each node is
+// allocated on the stack, and whenever the running closure finishes it will
+// consume the entire queue and notify all waiters they should try again.
+//
+// You'll find a few more details in the implementation, but that's the gist of
+// it!
+//
+// Atomic orderings:
+// When running `Once` we deal with multiple atomics:
+// `Once.state_and_queue` and an unknown number of `Waiter.signaled`.
+// * `state_and_queue` is used (1) as a state flag, (2) for synchronizing the
+// result of the `Once`, and (3) for synchronizing `Waiter` nodes.
+// - At the end of the `call` function we have to make sure the result
+// of the `Once` is acquired. So every load which can be the only one to
+// load COMPLETED must have at least acquire ordering, which means all
+// three of them.
+// - `WaiterQueue::drop` is the only place that may store COMPLETED, and
+// must do so with release ordering to make the result available.
+// - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and
+// needs to make the nodes available with release ordering. The load in
+// its `compare_exchange` can be relaxed because it only has to compare
+// the atomic, not to read other data.
+// - `WaiterQueue::drop` must see the `Waiter` nodes, so it must load
+// `state_and_queue` with acquire ordering.
+// - There is just one store where `state_and_queue` is used only as a
+// state flag, without having to synchronize data: switching the state
+// from INCOMPLETE to RUNNING in `call`. This store can be Relaxed,
+// but the read has to be Acquire because of the requirements mentioned
+// above.
+// * `Waiter.signaled` is both used as a flag, and to protect a field with
+// interior mutability in `Waiter`. `Waiter.thread` is changed in
+// `WaiterQueue::drop` which then sets `signaled` with release ordering.
+// After `wait` loads `signaled` with acquire ordering and sees it is true,
+// it needs to see the changes to drop the `Waiter` struct correctly.
+// * There is one place where the two atomics `Once.state_and_queue` and
+// `Waiter.signaled` come together, and might be reordered by the compiler or
+// processor. Because both use acquire ordering such a reordering is not
+// allowed, so no need for `SeqCst`.
+
+use crate::cell::Cell;
+use crate::fmt;
+use crate::ptr;
+use crate::sync as public;
+use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
+use crate::thread::{self, Thread};
+
+type Masked = ();
+
+pub struct Once {
+ state_and_queue: AtomicPtr<Masked>,
+}
+
+pub struct OnceState {
+ poisoned: bool,
+ set_state_on_drop_to: Cell<*mut Masked>,
+}
+
+// Four states that a Once can be in, encoded into the lower bits of
+// `state_and_queue` in the Once structure.
+const INCOMPLETE: usize = 0x0;
+const POISONED: usize = 0x1;
+const RUNNING: usize = 0x2;
+const COMPLETE: usize = 0x3;
+
+// Mask to learn about the state. All other bits are the queue of waiters if
+// this is in the RUNNING state.
+const STATE_MASK: usize = 0x3;
+
+// Representation of a node in the linked list of waiters, used while in the
+// RUNNING state.
+// Note: `Waiter` can't hold a mutable pointer to the next thread, because then
+// `wait` would both hand out a mutable reference to its `Waiter` node, and keep
+// a shared reference to check `signaled`. Instead we hold shared references and
+// use interior mutability.
+#[repr(align(4))] // Ensure the two lower bits are free to use as state bits.
+struct Waiter {
+ thread: Cell<Option<Thread>>,
+ signaled: AtomicBool,
+ next: *const Waiter,
+}
+
+// Head of a linked list of waiters.
+// Every node is a struct on the stack of a waiting thread.
+// Will wake up the waiters when it gets dropped, i.e. also on panic.
+struct WaiterQueue<'a> {
+ state_and_queue: &'a AtomicPtr<Masked>,
+ set_state_on_drop_to: *mut Masked,
+}
+
+impl Once {
+ #[inline]
+ pub const fn new() -> Once {
+ Once { state_and_queue: AtomicPtr::new(ptr::invalid_mut(INCOMPLETE)) }
+ }
+
+ #[inline]
+ pub fn is_completed(&self) -> bool {
+ // An `Acquire` load is enough because that makes all the initialization
+ // operations visible to us, and, this being a fast path, weaker
+ // ordering helps with performance. This `Acquire` synchronizes with
+ // `Release` operations on the slow path.
+ self.state_and_queue.load(Ordering::Acquire).addr() == COMPLETE
+ }
+
+ // This is a non-generic function to reduce the monomorphization cost of
+ // using `call_once` (this isn't exactly a trivial or small implementation).
+ //
+ // Additionally, this is tagged with `#[cold]` as it should indeed be cold
+ // and it helps let LLVM know that calls to this function should be off the
+ // fast path. Essentially, this should help generate more straight line code
+ // in LLVM.
+ //
+ // Finally, this takes an `FnMut` instead of a `FnOnce` because there's
+ // currently no way to take an `FnOnce` and call it via virtual dispatch
+ // without some allocation overhead.
+ #[cold]
+ #[track_caller]
+ pub fn call(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&public::OnceState)) {
+ let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
+ loop {
+ match state_and_queue.addr() {
+ COMPLETE => break,
+ POISONED if !ignore_poisoning => {
+ // Panic to propagate the poison.
+ panic!("Once instance has previously been poisoned");
+ }
+ POISONED | INCOMPLETE => {
+ // Try to register this thread as the one RUNNING.
+ let exchange_result = self.state_and_queue.compare_exchange(
+ state_and_queue,
+ ptr::invalid_mut(RUNNING),
+ Ordering::Acquire,
+ Ordering::Acquire,
+ );
+ if let Err(old) = exchange_result {
+ state_and_queue = old;
+ continue;
+ }
+ // `waiter_queue` will manage other waiting threads, and
+ // wake them up on drop.
+ let mut waiter_queue = WaiterQueue {
+ state_and_queue: &self.state_and_queue,
+ set_state_on_drop_to: ptr::invalid_mut(POISONED),
+ };
+ // Run the initialization function, letting it know if we're
+ // poisoned or not.
+ let init_state = public::OnceState {
+ inner: OnceState {
+ poisoned: state_and_queue.addr() == POISONED,
+ set_state_on_drop_to: Cell::new(ptr::invalid_mut(COMPLETE)),
+ },
+ };
+ init(&init_state);
+ waiter_queue.set_state_on_drop_to = init_state.inner.set_state_on_drop_to.get();
+ break;
+ }
+ _ => {
+ // All other values must be RUNNING with possibly a
+ // pointer to the waiter queue in the more significant bits.
+ assert!(state_and_queue.addr() & STATE_MASK == RUNNING);
+ wait(&self.state_and_queue, state_and_queue);
+ state_and_queue = self.state_and_queue.load(Ordering::Acquire);
+ }
+ }
+ }
+ }
+}
+
+fn wait(state_and_queue: &AtomicPtr<Masked>, mut current_state: *mut Masked) {
+ // Note: the following code was carefully written to avoid creating a
+ // mutable reference to `node` that gets aliased.
+ loop {
+ // Don't queue this thread if the status is no longer running,
+ // otherwise we will not be woken up.
+ if current_state.addr() & STATE_MASK != RUNNING {
+ return;
+ }
+
+ // Create the node for our current thread.
+ let node = Waiter {
+ thread: Cell::new(Some(thread::current())),
+ signaled: AtomicBool::new(false),
+ next: current_state.with_addr(current_state.addr() & !STATE_MASK) as *const Waiter,
+ };
+ let me = &node as *const Waiter as *const Masked as *mut Masked;
+
+ // Try to slide in the node at the head of the linked list, making sure
+ // that another thread didn't just replace the head of the linked list.
+ let exchange_result = state_and_queue.compare_exchange(
+ current_state,
+ me.with_addr(me.addr() | RUNNING),
+ Ordering::Release,
+ Ordering::Relaxed,
+ );
+ if let Err(old) = exchange_result {
+ current_state = old;
+ continue;
+ }
+
+ // We have enqueued ourselves, now lets wait.
+ // It is important not to return before being signaled, otherwise we
+ // would drop our `Waiter` node and leave a hole in the linked list
+ // (and a dangling reference). Guard against spurious wakeups by
+ // reparking ourselves until we are signaled.
+ while !node.signaled.load(Ordering::Acquire) {
+ // If the managing thread happens to signal and unpark us before we
+ // can park ourselves, the result could be this thread never gets
+ // unparked. Luckily `park` comes with the guarantee that if it got
+ // an `unpark` just before on an unparked thread it does not park.
+ thread::park();
+ }
+ break;
+ }
+}
+
+#[stable(feature = "std_debug", since = "1.16.0")]
+impl fmt::Debug for Once {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("Once").finish_non_exhaustive()
+ }
+}
+
+impl Drop for WaiterQueue<'_> {
+ fn drop(&mut self) {
+ // Swap out our state with however we finished.
+ let state_and_queue =
+ self.state_and_queue.swap(self.set_state_on_drop_to, Ordering::AcqRel);
+
+ // We should only ever see an old state which was RUNNING.
+ assert_eq!(state_and_queue.addr() & STATE_MASK, RUNNING);
+
+ // Walk the entire linked list of waiters and wake them up (in lifo
+ // order, last to register is first to wake up).
+ unsafe {
+ // Right after setting `node.signaled = true` the other thread may
+ // free `node` if there happens to be has a spurious wakeup.
+ // So we have to take out the `thread` field and copy the pointer to
+ // `next` first.
+ let mut queue =
+ state_and_queue.with_addr(state_and_queue.addr() & !STATE_MASK) as *const Waiter;
+ while !queue.is_null() {
+ let next = (*queue).next;
+ let thread = (*queue).thread.take().unwrap();
+ (*queue).signaled.store(true, Ordering::Release);
+ // ^- FIXME (maybe): This is another case of issue #55005
+ // `store()` has a potentially dangling ref to `signaled`.
+ queue = next;
+ thread.unpark();
+ }
+ }
+ }
+}
+
+impl OnceState {
+ #[inline]
+ pub fn is_poisoned(&self) -> bool {
+ self.poisoned
+ }
+
+ #[inline]
+ pub fn poison(&self) {
+ self.set_state_on_drop_to.set(ptr::invalid_mut(POISONED));
+ }
+}
diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys_common/once/mod.rs
new file mode 100644
index 000000000..8742e68cc
--- /dev/null
+++ b/library/std/src/sys_common/once/mod.rs
@@ -0,0 +1,43 @@
+// A "once" is a relatively simple primitive, and it's also typically provided
+// by the OS as well (see `pthread_once` or `InitOnceExecuteOnce`). The OS
+// primitives, however, tend to have surprising restrictions, such as the Unix
+// one doesn't allow an argument to be passed to the function.
+//
+// As a result, we end up implementing it ourselves in the standard library.
+// This also gives us the opportunity to optimize the implementation a bit which
+// should help the fast path on call sites.
+//
+// So to recap, the guarantees of a Once are that it will call the
+// initialization closure at most once, and it will never return until the one
+// that's running has finished running. This means that we need some form of
+// blocking here while the custom callback is running at the very least.
+// Additionally, we add on the restriction of **poisoning**. Whenever an
+// initialization closure panics, the Once enters a "poisoned" state which means
+// that all future calls will immediately panic as well.
+//
+// So to implement this, one might first reach for a `Mutex`, but those cannot
+// be put into a `static`. It also gets a lot harder with poisoning to figure
+// out when the mutex needs to be deallocated because it's not after the closure
+// finishes, but after the first successful closure finishes.
+//
+// All in all, this is instead implemented with atomics and lock-free
+// operations! Whee!
+
+cfg_if::cfg_if! {
+ if #[cfg(any(
+ target_os = "linux",
+ target_os = "android",
+ all(target_arch = "wasm32", target_feature = "atomics"),
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "dragonfly",
+ target_os = "fuchsia",
+ target_os = "hermit",
+ ))] {
+ mod futex;
+ pub use futex::{Once, OnceState};
+ } else {
+ mod generic;
+ pub use generic::{Once, OnceState};
+ }
+}
diff --git a/library/std/src/sys_common/rwlock.rs b/library/std/src/sys_common/rwlock.rs
index ba56f3a8f..042981dac 100644
--- a/library/std/src/sys_common/rwlock.rs
+++ b/library/std/src/sys_common/rwlock.rs
@@ -1,65 +1,5 @@
use crate::sys::locks as imp;
-/// An OS-based reader-writer lock, meant for use in static variables.
-///
-/// This rwlock does not implement poisoning.
-///
-/// This rwlock has a const constructor ([`StaticRwLock::new`]), does not
-/// implement `Drop` to cleanup resources.
-pub struct StaticRwLock(imp::RwLock);
-
-impl StaticRwLock {
- /// Creates a new rwlock for use.
- #[inline]
- pub const fn new() -> Self {
- Self(imp::RwLock::new())
- }
-
- /// Acquires shared access to the underlying lock, blocking the current
- /// thread to do so.
- ///
- /// The lock is automatically unlocked when the returned guard is dropped.
- #[inline]
- pub fn read(&'static self) -> StaticRwLockReadGuard {
- unsafe { self.0.read() };
- StaticRwLockReadGuard(&self.0)
- }
-
- /// Acquires write access to the underlying lock, blocking the current thread
- /// to do so.
- ///
- /// The lock is automatically unlocked when the returned guard is dropped.
- #[inline]
- pub fn write(&'static self) -> StaticRwLockWriteGuard {
- unsafe { self.0.write() };
- StaticRwLockWriteGuard(&self.0)
- }
-}
-
-#[must_use]
-pub struct StaticRwLockReadGuard(&'static imp::RwLock);
-
-impl Drop for StaticRwLockReadGuard {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- self.0.read_unlock();
- }
- }
-}
-
-#[must_use]
-pub struct StaticRwLockWriteGuard(&'static imp::RwLock);
-
-impl Drop for StaticRwLockWriteGuard {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- self.0.write_unlock();
- }
- }
-}
-
/// An OS-based reader-writer lock.
///
/// This rwlock cleans up its resources in its `Drop` implementation and may
@@ -75,6 +15,7 @@ pub struct MovableRwLock(imp::MovableRwLock);
impl MovableRwLock {
/// Creates a new reader-writer lock for use.
#[inline]
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Self {
Self(imp::MovableRwLock::new())
}
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 032bf604d..747579f17 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -53,7 +53,6 @@ mod tests;
use crate::sync::atomic::{self, AtomicUsize, Ordering};
use crate::sys::thread_local_key as imp;
-use crate::sys_common::mutex::StaticMutex;
/// A type for TLS keys that are statically allocated.
///
@@ -151,25 +150,6 @@ impl StaticKey {
}
unsafe fn lazy_init(&self) -> usize {
- // Currently the Windows implementation of TLS is pretty hairy, and
- // it greatly simplifies creation if we just synchronize everything.
- //
- // Additionally a 0-index of a tls key hasn't been seen on windows, so
- // we just simplify the whole branch.
- if imp::requires_synchronized_create() {
- // We never call `INIT_LOCK.init()`, so it is UB to attempt to
- // acquire this mutex reentrantly!
- static INIT_LOCK: StaticMutex = StaticMutex::new();
- let _guard = INIT_LOCK.lock();
- let mut key = self.key.load(Ordering::SeqCst);
- if key == 0 {
- key = imp::create(self.dtor) as usize;
- self.key.store(key, Ordering::SeqCst);
- }
- rtassert!(key != 0);
- return key;
- }
-
// POSIX allows the key created here to be 0, but the compare_exchange
// below relies on using 0 as a sentinel value to check who won the
// race to set the shared TLS key. As far as I know, there is no
@@ -232,8 +212,6 @@ impl Key {
impl Drop for Key {
fn drop(&mut self) {
- // Right now Windows doesn't support TLS key destruction, but this also
- // isn't used anywhere other than tests, so just leak the TLS key.
- // unsafe { imp::destroy(self.key) }
+ unsafe { imp::destroy(self.key) }
}
}
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 8aedfc4a6..5d267891b 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -95,6 +95,7 @@ use crate::fmt;
/// [loader lock]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-best-practices
/// [`JoinHandle::join`]: crate::thread::JoinHandle::join
/// [`with`]: LocalKey::with
+#[cfg_attr(not(test), rustc_diagnostic_item = "LocalKey")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct LocalKey<T: 'static> {
// This outer `LocalKey<T>` type is what's going to be stored in statics,
@@ -900,7 +901,7 @@ pub mod statik {
}
#[doc(hidden)]
-#[cfg(target_thread_local)]
+#[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics"))),))]
pub mod fast {
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
@@ -1036,7 +1037,10 @@ pub mod fast {
}
#[doc(hidden)]
-#[cfg(not(target_thread_local))]
+#[cfg(all(
+ not(target_thread_local),
+ not(all(target_family = "wasm", not(target_feature = "atomics"))),
+))]
pub mod os {
use super::lazy::LazyKeyInner;
use crate::cell::Cell;
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index ceea6986e..05023df1b 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -150,6 +150,8 @@
#![stable(feature = "rust1", since = "1.0.0")]
#![deny(unsafe_op_in_unsafe_fn)]
+// Under `test`, `__FastLocalKeyInner` seems unused.
+#![cfg_attr(test, allow(dead_code))]
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;
@@ -160,7 +162,7 @@ use crate::ffi::{CStr, CString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
-use crate::mem;
+use crate::mem::{self, forget};
use crate::num::NonZeroU64;
use crate::num::NonZeroUsize;
use crate::panic;
@@ -192,32 +194,40 @@ pub use scoped::{scope, Scope, ScopedJoinHandle};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::local::{AccessError, LocalKey};
-// Select the type used by the thread_local! macro to access TLS keys. There
-// are three types: "static", "fast", "OS". The "OS" thread local key
+// Provide the type used by the thread_local! macro to access TLS keys. This
+// needs to be kept in sync with the macro itself (in `local.rs`).
+// There are three types: "static", "fast", "OS". The "OS" thread local key
// type is accessed via platform-specific API calls and is slow, while the "fast"
// key type is accessed via code generated via LLVM, where TLS keys are set up
// by the elf linker. "static" is for single-threaded platforms where a global
// static is sufficient.
#[unstable(feature = "libstd_thread_internals", issue = "none")]
-#[cfg(target_thread_local)]
#[cfg(not(test))]
+#[cfg(all(
+ target_thread_local,
+ not(all(target_family = "wasm", not(target_feature = "atomics"))),
+))]
#[doc(hidden)]
pub use self::local::fast::Key as __FastLocalKeyInner;
-#[unstable(feature = "libstd_thread_internals", issue = "none")]
-#[cfg(target_thread_local)]
-#[cfg(test)] // when building for tests, use real std's key
-pub use realstd::thread::__FastLocalKeyInner;
+// when building for tests, use real std's type
#[unstable(feature = "libstd_thread_internals", issue = "none")]
-#[cfg(target_thread_local)]
#[cfg(test)]
-pub use self::local::fast::Key as __FastLocalKeyInnerUnused; // we import this anyway to silence 'unused' warnings
+#[cfg(all(
+ target_thread_local,
+ not(all(target_family = "wasm", not(target_feature = "atomics"))),
+))]
+pub use realstd::thread::__FastLocalKeyInner;
#[unstable(feature = "libstd_thread_internals", issue = "none")]
+#[cfg(all(
+ not(target_thread_local),
+ not(all(target_family = "wasm", not(target_feature = "atomics"))),
+))]
#[doc(hidden)]
-#[cfg(not(target_thread_local))]
pub use self::local::os::Key as __OsLocalKeyInner;
+
#[unstable(feature = "libstd_thread_internals", issue = "none")]
#[cfg(all(target_family = "wasm", not(target_feature = "atomics")))]
#[doc(hidden)]
@@ -499,6 +509,31 @@ impl Builder {
let output_capture = crate::io::set_output_capture(None);
crate::io::set_output_capture(output_capture.clone());
+ // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*.
+ // See <https://github.com/rust-lang/rust/issues/101983> for more details.
+ // To prevent leaks we use a wrapper that drops its contents.
+ #[repr(transparent)]
+ struct MaybeDangling<T>(mem::MaybeUninit<T>);
+ impl<T> MaybeDangling<T> {
+ fn new(x: T) -> Self {
+ MaybeDangling(mem::MaybeUninit::new(x))
+ }
+ fn into_inner(self) -> T {
+ // SAFETY: we are always initiailized.
+ let ret = unsafe { self.0.assume_init_read() };
+ // Make sure we don't drop.
+ mem::forget(self);
+ ret
+ }
+ }
+ impl<T> Drop for MaybeDangling<T> {
+ fn drop(&mut self) {
+ // SAFETY: we are always initiailized.
+ unsafe { self.0.assume_init_drop() };
+ }
+ }
+
+ let f = MaybeDangling::new(f);
let main = move || {
if let Some(name) = their_thread.cname() {
imp::Thread::set_name(name);
@@ -506,6 +541,8 @@ impl Builder {
crate::io::set_output_capture(output_capture);
+ // SAFETY: we constructed `f` initialized.
+ let f = f.into_inner();
// SAFETY: the stack guard passed is the one for the current thread.
// This means the current thread's stack and the new thread's stack
// are properly set and protected from each other.
@@ -518,6 +555,12 @@ impl Builder {
// same `JoinInner` as this closure meaning the mutation will be
// safe (not modify it and affect a value far away).
unsafe { *their_packet.result.get() = Some(try_result) };
+ // Here `their_packet` gets dropped, and if this is the last `Arc` for that packet that
+ // will call `decrement_num_running_threads` and therefore signal that this thread is
+ // done.
+ drop(their_packet);
+ // Here, the lifetime `'a` and even `'scope` can end. `main` keeps running for a bit
+ // after that before returning itself.
};
if let Some(scope_data) = &my_packet.scope {
@@ -779,6 +822,8 @@ pub fn panicking() -> bool {
panicking::panicking()
}
+/// Use [`sleep`].
+///
/// Puts the current thread to sleep for at least the specified amount of time.
///
/// The thread may sleep longer than the duration specified due to scheduling
@@ -849,10 +894,22 @@ pub fn sleep(dur: Duration) {
imp::Thread::sleep(dur)
}
+/// Used to ensure that `park` and `park_timeout` do not unwind, as that can
+/// cause undefined behaviour if not handled correctly (see #102398 for context).
+struct PanicGuard;
+
+impl Drop for PanicGuard {
+ fn drop(&mut self) {
+ rtabort!("an irrecoverable error occurred while synchronizing threads")
+ }
+}
+
/// Blocks unless or until the current thread's token is made available.
///
/// A call to `park` does not guarantee that the thread will remain parked
-/// forever, and callers should be prepared for this possibility.
+/// forever, and callers should be prepared for this possibility. However,
+/// it is guaranteed that this function will not panic (it may abort the
+/// process if the implementation encounters some rare errors).
///
/// # park and unpark
///
@@ -937,10 +994,13 @@ pub fn sleep(dur: Duration) {
/// [`thread::park_timeout`]: park_timeout
#[stable(feature = "rust1", since = "1.0.0")]
pub fn park() {
+ let guard = PanicGuard;
// SAFETY: park_timeout is called on the parker owned by this thread.
unsafe {
current().inner.as_ref().parker().park();
}
+ // No panic occurred, do not abort.
+ forget(guard);
}
/// Use [`park_timeout`].
@@ -1001,10 +1061,13 @@ pub fn park_timeout_ms(ms: u32) {
/// ```
#[stable(feature = "park_timeout", since = "1.4.0")]
pub fn park_timeout(dur: Duration) {
+ let guard = PanicGuard;
// SAFETY: park_timeout is called on the parker owned by this thread.
unsafe {
current().inner.as_ref().parker().park_timeout(dur);
}
+ // No panic occurred, do not abort.
+ forget(guard);
}
////////////////////////////////////////////////////////////////////////////////
@@ -1065,24 +1128,21 @@ impl ThreadId {
}
}
} else {
- use crate::sys_common::mutex::StaticMutex;
+ use crate::sync::{Mutex, PoisonError};
- // It is UB to attempt to acquire this mutex reentrantly!
- static GUARD: StaticMutex = StaticMutex::new();
- static mut COUNTER: u64 = 0;
+ static COUNTER: Mutex<u64> = Mutex::new(0);
- unsafe {
- let guard = GUARD.lock();
+ let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
+ let Some(id) = counter.checked_add(1) else {
+ // in case the panic handler ends up calling `ThreadId::new()`,
+ // avoid reentrant lock acquire.
+ drop(counter);
+ exhausted();
+ };
- let Some(id) = COUNTER.checked_add(1) else {
- drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
- exhausted();
- };
-
- COUNTER = id;
- drop(guard);
- ThreadId(NonZeroU64::new(id).unwrap())
- }
+ *counter = id;
+ drop(counter);
+ ThreadId(NonZeroU64::new(id).unwrap())
}
}
}
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 777964f04..6c9ce6fa0 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -276,6 +276,28 @@ fn test_try_panic_any_message_unit_struct() {
}
#[test]
+fn test_park_unpark_before() {
+ for _ in 0..10 {
+ thread::current().unpark();
+ thread::park();
+ }
+}
+
+#[test]
+fn test_park_unpark_called_other_thread() {
+ for _ in 0..10 {
+ let th = thread::current();
+
+ let _guard = thread::spawn(move || {
+ super::sleep(Duration::from_millis(50));
+ th.unpark();
+ });
+
+ thread::park();
+ }
+}
+
+#[test]
fn test_park_timeout_unpark_before() {
for _ in 0..10 {
thread::current().unpark();
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 759a59e1f..ecd06ebf7 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -43,8 +43,8 @@ use crate::sys_common::{FromInner, IntoInner};
#[stable(feature = "time", since = "1.3.0")]
pub use core::time::Duration;
-#[unstable(feature = "duration_checked_float", issue = "83400")]
-pub use core::time::FromFloatSecsError;
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+pub use core::time::TryFromFloatSecsError;
/// A measurement of a monotonically nondecreasing clock.
/// Opaque and useful only with [`Duration`].
@@ -356,7 +356,7 @@ impl Instant {
///
/// # Panics
///
- /// Previous rust versions panicked when self was earlier than the current time. Currently this
+ /// Previous rust versions panicked when the current time was earlier than self. Currently this
/// method returns a Duration of zero in that case. Future versions may reintroduce the panic.
/// See [Monotonicity].
///
diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs
index a57a52d9b..02c076f1b 100644
--- a/library/std/tests/run-time-detect.rs
+++ b/library/std/tests/run-time-detect.rs
@@ -14,77 +14,85 @@
#[cfg(all(target_arch = "arm", any(target_os = "linux", target_os = "android")))]
fn arm_linux() {
use std::arch::is_arm_feature_detected;
+ // tidy-alphabetical-start
+ println!("aes: {}", is_arm_feature_detected!("aes"));
+ println!("crc: {}", is_arm_feature_detected!("crc"));
+ println!("crypto: {}", is_arm_feature_detected!("crypto"));
println!("neon: {}", is_arm_feature_detected!("neon"));
println!("pmull: {}", is_arm_feature_detected!("pmull"));
- println!("crypto: {}", is_arm_feature_detected!("crypto"));
- println!("crc: {}", is_arm_feature_detected!("crc"));
- println!("aes: {}", is_arm_feature_detected!("aes"));
println!("sha2: {}", is_arm_feature_detected!("sha2"));
+ // tidy-alphabetical-end
}
#[test]
#[cfg(all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")))]
fn aarch64_linux() {
use std::arch::is_aarch64_feature_detected;
- println!("neon: {}", is_aarch64_feature_detected!("neon"));
+ // tidy-alphabetical-start
+ println!("aes: {}", is_aarch64_feature_detected!("aes"));
println!("asimd: {}", is_aarch64_feature_detected!("asimd"));
- println!("pmull: {}", is_aarch64_feature_detected!("pmull"));
- println!("fp16: {}", is_aarch64_feature_detected!("fp16"));
- println!("sve: {}", is_aarch64_feature_detected!("sve"));
+ println!("bf16: {}", is_aarch64_feature_detected!("bf16"));
+ println!("bti: {}", is_aarch64_feature_detected!("bti"));
println!("crc: {}", is_aarch64_feature_detected!("crc"));
- println!("lse: {}", is_aarch64_feature_detected!("lse"));
- println!("lse2: {}", is_aarch64_feature_detected!("lse2"));
- println!("rdm: {}", is_aarch64_feature_detected!("rdm"));
- println!("rcpc: {}", is_aarch64_feature_detected!("rcpc"));
- println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2"));
+ println!("dit: {}", is_aarch64_feature_detected!("dit"));
println!("dotprod: {}", is_aarch64_feature_detected!("dotprod"));
- println!("tme: {}", is_aarch64_feature_detected!("tme"));
+ println!("dpb2: {}", is_aarch64_feature_detected!("dpb2"));
+ println!("dpb: {}", is_aarch64_feature_detected!("dpb"));
+ println!("f32mm: {}", is_aarch64_feature_detected!("f32mm"));
+ println!("f64mm: {}", is_aarch64_feature_detected!("f64mm"));
+ println!("fcma: {}", is_aarch64_feature_detected!("fcma"));
println!("fhm: {}", is_aarch64_feature_detected!("fhm"));
- println!("dit: {}", is_aarch64_feature_detected!("dit"));
println!("flagm: {}", is_aarch64_feature_detected!("flagm"));
- println!("ssbs: {}", is_aarch64_feature_detected!("ssbs"));
- println!("sb: {}", is_aarch64_feature_detected!("sb"));
- println!("paca: {}", is_aarch64_feature_detected!("paca"));
- println!("pacg: {}", is_aarch64_feature_detected!("pacg"));
- println!("dpb: {}", is_aarch64_feature_detected!("dpb"));
- println!("dpb2: {}", is_aarch64_feature_detected!("dpb2"));
- println!("sve2: {}", is_aarch64_feature_detected!("sve2"));
- println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes"));
- println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4"));
- println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3"));
- println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm"));
+ println!("fp16: {}", is_aarch64_feature_detected!("fp16"));
println!("frintts: {}", is_aarch64_feature_detected!("frintts"));
println!("i8mm: {}", is_aarch64_feature_detected!("i8mm"));
- println!("f32mm: {}", is_aarch64_feature_detected!("f32mm"));
- println!("f64mm: {}", is_aarch64_feature_detected!("f64mm"));
- println!("bf16: {}", is_aarch64_feature_detected!("bf16"));
- println!("rand: {}", is_aarch64_feature_detected!("rand"));
- println!("bti: {}", is_aarch64_feature_detected!("bti"));
- println!("mte: {}", is_aarch64_feature_detected!("mte"));
println!("jsconv: {}", is_aarch64_feature_detected!("jsconv"));
- println!("fcma: {}", is_aarch64_feature_detected!("fcma"));
- println!("aes: {}", is_aarch64_feature_detected!("aes"));
+ println!("lse2: {}", is_aarch64_feature_detected!("lse2"));
+ println!("lse: {}", is_aarch64_feature_detected!("lse"));
+ println!("mte: {}", is_aarch64_feature_detected!("mte"));
+ println!("neon: {}", is_aarch64_feature_detected!("neon"));
+ println!("paca: {}", is_aarch64_feature_detected!("paca"));
+ println!("pacg: {}", is_aarch64_feature_detected!("pacg"));
+ println!("pmull: {}", is_aarch64_feature_detected!("pmull"));
+ println!("rand: {}", is_aarch64_feature_detected!("rand"));
+ println!("rcpc2: {}", is_aarch64_feature_detected!("rcpc2"));
+ println!("rcpc: {}", is_aarch64_feature_detected!("rcpc"));
+ println!("rdm: {}", is_aarch64_feature_detected!("rdm"));
+ println!("sb: {}", is_aarch64_feature_detected!("sb"));
println!("sha2: {}", is_aarch64_feature_detected!("sha2"));
println!("sha3: {}", is_aarch64_feature_detected!("sha3"));
println!("sm4: {}", is_aarch64_feature_detected!("sm4"));
+ println!("ssbs: {}", is_aarch64_feature_detected!("ssbs"));
+ println!("sve2-aes: {}", is_aarch64_feature_detected!("sve2-aes"));
+ println!("sve2-bitperm: {}", is_aarch64_feature_detected!("sve2-bitperm"));
+ println!("sve2-sha3: {}", is_aarch64_feature_detected!("sve2-sha3"));
+ println!("sve2-sm4: {}", is_aarch64_feature_detected!("sve2-sm4"));
+ println!("sve2: {}", is_aarch64_feature_detected!("sve2"));
+ println!("sve: {}", is_aarch64_feature_detected!("sve"));
+ println!("tme: {}", is_aarch64_feature_detected!("tme"));
+ // tidy-alphabetical-end
}
#[test]
#[cfg(all(target_arch = "powerpc", target_os = "linux"))]
fn powerpc_linux() {
use std::arch::is_powerpc_feature_detected;
+ // tidy-alphabetical-start
println!("altivec: {}", is_powerpc_feature_detected!("altivec"));
- println!("vsx: {}", is_powerpc_feature_detected!("vsx"));
println!("power8: {}", is_powerpc_feature_detected!("power8"));
+ println!("vsx: {}", is_powerpc_feature_detected!("vsx"));
+ // tidy-alphabetical-end
}
#[test]
#[cfg(all(target_arch = "powerpc64", target_os = "linux"))]
fn powerpc64_linux() {
use std::arch::is_powerpc64_feature_detected;
+ // tidy-alphabetical-start
println!("altivec: {}", is_powerpc64_feature_detected!("altivec"));
- println!("vsx: {}", is_powerpc64_feature_detected!("vsx"));
println!("power8: {}", is_powerpc64_feature_detected!("power8"));
+ println!("vsx: {}", is_powerpc64_feature_detected!("vsx"));
+ // tidy-alphabetical-end
}
#[test]
@@ -102,9 +110,9 @@ fn x86_all() {
// the below is in alphabetical order and matches
// the order of X86_ALLOWED_FEATURES in rustc_codegen_ssa's target_features.rs
+ // tidy-alphabetical-start
println!("adx: {:?}", is_x86_feature_detected!("adx"));
println!("aes: {:?}", is_x86_feature_detected!("aes"));
- println!("avx: {:?}", is_x86_feature_detected!("avx"));
println!("avx2: {:?}", is_x86_feature_detected!("avx2"));
println!("avx512bf16: {:?}", is_x86_feature_detected!("avx512bf16"));
println!("avx512bitalg: {:?}", is_x86_feature_detected!("avx512bitalg"));
@@ -117,13 +125,14 @@ fn x86_all() {
println!("avx512ifma: {:?}", is_x86_feature_detected!("avx512ifma"));
println!("avx512pf: {:?}", is_x86_feature_detected!("avx512pf"));
println!("avx512vaes: {:?}", is_x86_feature_detected!("avx512vaes"));
- println!("avx512vbmi: {:?}", is_x86_feature_detected!("avx512vbmi"));
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"));
println!("bmi2: {:?}", is_x86_feature_detected!("bmi2"));
println!("cmpxchg16b: {:?}", is_x86_feature_detected!("cmpxchg16b"));
@@ -138,16 +147,17 @@ fn x86_all() {
println!("rdseed: {:?}", is_x86_feature_detected!("rdseed"));
println!("rtm: {:?}", is_x86_feature_detected!("rtm"));
println!("sha: {:?}", is_x86_feature_detected!("sha"));
- println!("sse: {:?}", is_x86_feature_detected!("sse"));
println!("sse2: {:?}", is_x86_feature_detected!("sse2"));
println!("sse3: {:?}", is_x86_feature_detected!("sse3"));
println!("sse4.1: {:?}", is_x86_feature_detected!("sse4.1"));
println!("sse4.2: {:?}", is_x86_feature_detected!("sse4.2"));
println!("sse4a: {:?}", is_x86_feature_detected!("sse4a"));
+ println!("sse: {:?}", is_x86_feature_detected!("sse"));
println!("ssse3: {:?}", is_x86_feature_detected!("ssse3"));
println!("tbm: {:?}", is_x86_feature_detected!("tbm"));
println!("xsave: {:?}", is_x86_feature_detected!("xsave"));
println!("xsavec: {:?}", is_x86_feature_detected!("xsavec"));
println!("xsaveopt: {:?}", is_x86_feature_detected!("xsaveopt"));
println!("xsaves: {:?}", is_x86_feature_detected!("xsaves"));
+ // tidy-alphabetical-end
}
diff --git a/library/stdarch/ci/android-install-sdk.sh b/library/stdarch/ci/android-install-sdk.sh
index 1beeb312a..3383dcb7f 100644
--- a/library/stdarch/ci/android-install-sdk.sh
+++ b/library/stdarch/ci/android-install-sdk.sh
@@ -19,8 +19,8 @@ set -ex
# which apparently magically accepts the licenses.
mkdir sdk
-curl --retry 5 https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip -O
-unzip -d sdk sdk-tools-linux-3859397.zip
+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)
diff --git a/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile b/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile
index 27bde89c5..6cf9b5061 100644
--- a/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile
+++ b/library/stdarch/ci/docker/aarch64-linux-android/Dockerfile
@@ -1,17 +1,16 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
-RUN dpkg --add-architecture i386 && \
- apt-get update && \
+RUN apt-get update && \
apt-get install -y --no-install-recommends \
file \
make \
curl \
ca-certificates \
- python \
+ python-is-python3 \
unzip \
expect \
- openjdk-9-jre \
- libstdc++6:i386 \
+ openjdk-8-jre \
+ libstdc++6-i386-cross \
libpulse0 \
gcc \
libc6-dev
diff --git a/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile b/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile
index 995a9e30e..fb1a0cecf 100644
--- a/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile
+++ b/library/stdarch/ci/docker/arm-linux-androideabi/Dockerfile
@@ -1,17 +1,16 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
-RUN dpkg --add-architecture i386 && \
- apt-get update && \
+RUN apt-get update && \
apt-get install -y --no-install-recommends \
file \
make \
curl \
ca-certificates \
- python \
+ python-is-python3 \
unzip \
expect \
- openjdk-9-jre \
- libstdc++6:i386 \
+ openjdk-8-jre \
+ libstdc++6-i386-cross \
libpulse0 \
gcc \
libc6-dev
diff --git a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile b/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile
index c2830b15f..82119be74 100644
--- a/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile
+++ b/library/stdarch/ci/docker/x86_64-linux-android/Dockerfile
@@ -1,4 +1,4 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y --no-install-recommends \
@@ -6,7 +6,7 @@ RUN apt-get update && \
curl \
gcc \
libc-dev \
- python \
+ python-is-python3 \
unzip \
file \
make
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 043f7ed51..0559aea83 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
@@ -12461,30 +12461,30 @@ mod tests {
}
#[simd_test(enable = "neon,i8mm")]
unsafe fn test_vmmlaq_s32() {
- let a: i32x4 = i32x4::new(1, 3, 4, 9);
- let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
- let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
- let e: i32x4 = i32x4::new(1, 2, 3, 4);
+ let a = i32x4::new(1, 3, 4, -0x10000);
+ let b = i8x16::new(1, 21, 31, 14, 5, 6, -128, 8, 9, 13, 15, 12, 13, -1, 20, 16);
+ let c = i8x16::new(12, 22, 3, 4, -1, 56, 7, 8, 91, 10, -128, 15, 13, 14, 17, 16);
+ let e = i32x4::new(123, -5353, 690, -65576);
let r: i32x4 = transmute(vmmlaq_s32(transmute(a), transmute(b), transmute(c)));
assert_eq!(r, e);
}
#[simd_test(enable = "neon,i8mm")]
unsafe fn test_vmmlaq_u32() {
- let a: u32x4 = u32x4::new(1, 3, 4, 9);
- let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
- let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
- let e: u32x4 = u32x4::new(1, 2, 3, 4);
+ let a = u32x4::new(1, 3, 4, 0xffff0000);
+ let b = u8x16::new(1, 21, 31, 14, 5, 6, 128, 8, 9, 13, 15, 12, 13, 255, 20, 16);
+ let c = u8x16::new(12, 22, 3, 4, 255, 56, 7, 8, 91, 10, 128, 15, 13, 14, 17, 16);
+ let e = u32x4::new(3195, 6935, 18354, 4294909144);
let r: u32x4 = transmute(vmmlaq_u32(transmute(a), transmute(b), transmute(c)));
assert_eq!(r, e);
}
#[simd_test(enable = "neon,i8mm")]
unsafe fn test_vusmmlaq_s32() {
- let a: i32x4 = i32x4::new(1, 3, 4, 9);
- let b: i8x16 = i8x16::new(1, 21, 31, 14, 5, 6, 17, 8, 9, 13, 15, 12, 13, 19, 20, 16);
- let c: i8x16 = i8x16::new(12, 22, 3, 4, 5, 56, 7, 8, 91, 10, 11, 15, 13, 14, 17, 16);
- let e: i32x4 = i32x4::new(1, 2, 3, 4);
+ let a = i32x4::new(1, 3, 4, -0x10000);
+ let b = u8x16::new(1, 21, 31, 14, 5, 6, 128, 8, 9, 13, 15, 12, 13, 255, 20, 16);
+ let c = i8x16::new(12, 22, 3, 4, -1, 56, 7, 8, 91, 10, -128, 15, 13, 14, 17, 16);
+ let e = i32x4::new(1915, -1001, 15026, -61992);
let r: i32x4 = transmute(vusmmlaq_s32(transmute(a), transmute(b), transmute(c)));
assert_eq!(r, e);
}
diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs
index 9240d0e84..5a9727a0a 100644
--- a/library/stdarch/crates/core_arch/src/lib.rs
+++ b/library/stdarch/crates/core_arch/src/lib.rs
@@ -19,6 +19,7 @@
doc_cfg,
tbm_target_feature,
sse4a_target_feature,
+ riscv_target_feature,
arm_target_feature,
cmpxchg16b_target_feature,
avx512_target_feature,
@@ -30,8 +31,8 @@
f16c_target_feature,
allow_internal_unstable,
decl_macro,
- bench_black_box,
- asm_const
+ asm_const,
+ target_feature_11
)]
#![cfg_attr(test, feature(test, abi_vectorcall))]
#![deny(clippy::missing_inline_in_public_items)]
diff --git a/library/stdarch/crates/core_arch/src/macros.rs b/library/stdarch/crates/core_arch/src/macros.rs
index 1e6a3f405..1c917c52b 100644
--- a/library/stdarch/crates/core_arch/src/macros.rs
+++ b/library/stdarch/crates/core_arch/src/macros.rs
@@ -101,11 +101,11 @@ macro_rules! simd_shuffle2 {
const IDX: [u32; 2] = $idx;
}
- simd_shuffle2($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 2] = $idx;
- simd_shuffle2($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
@@ -117,11 +117,11 @@ macro_rules! simd_shuffle4 {
const IDX: [u32; 4] = $idx;
}
- simd_shuffle4($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 4] = $idx;
- simd_shuffle4($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
@@ -133,11 +133,11 @@ macro_rules! simd_shuffle8 {
const IDX: [u32; 8] = $idx;
}
- simd_shuffle8($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 8] = $idx;
- simd_shuffle8($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
@@ -149,11 +149,11 @@ macro_rules! simd_shuffle16 {
const IDX: [u32; 16] = $idx;
}
- simd_shuffle16($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 16] = $idx;
- simd_shuffle16($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
@@ -165,11 +165,11 @@ macro_rules! simd_shuffle32 {
const IDX: [u32; 32] = $idx;
}
- simd_shuffle32($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 32] = $idx;
- simd_shuffle32($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
@@ -181,10 +181,10 @@ macro_rules! simd_shuffle64 {
const IDX: [u32; 64] = $idx;
}
- simd_shuffle64($x, $y, ConstParam::<$($imm),+>::IDX)
+ simd_shuffle($x, $y, ConstParam::<$($imm),+>::IDX)
}};
($x:expr, $y:expr, $idx:expr $(,)?) => {{
const IDX: [u32; 64] = $idx;
- simd_shuffle64($x, $y, IDX)
+ simd_shuffle($x, $y, IDX)
}};
}
diff --git a/library/stdarch/crates/core_arch/src/mod.rs b/library/stdarch/crates/core_arch/src/mod.rs
index 20751eeec..2f7af22cb 100644
--- a/library/stdarch/crates/core_arch/src/mod.rs
+++ b/library/stdarch/crates/core_arch/src/mod.rs
@@ -3,6 +3,9 @@
#[macro_use]
mod macros;
+#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))]
+mod riscv_shared;
+
#[cfg(any(target_arch = "arm", target_arch = "aarch64", doc))]
mod arm_shared;
@@ -276,10 +279,6 @@ mod aarch64;
#[doc(cfg(any(target_arch = "arm")))]
mod arm;
-#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", doc))]
-#[doc(cfg(any(target_arch = "riscv32", target_arch = "riscv64")))]
-mod riscv_shared;
-
#[cfg(any(target_arch = "riscv64", doc))]
#[doc(cfg(any(target_arch = "riscv64")))]
mod riscv64;
diff --git a/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
index 347735df1..0e35fe1f1 100644
--- a/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
+++ b/library/stdarch/crates/core_arch/src/riscv_shared/mod.rs
@@ -1,4 +1,7 @@
//! Shared RISC-V intrinsics
+mod p;
+
+pub use p::*;
use crate::arch::asm;
@@ -469,6 +472,17 @@ pub unsafe fn hinval_gvma_vmid(vmid: usize) {
asm!(".insn r 0x73, 0, 0x33, x0, x0, {}", in(reg) vmid, options(nostack))
}
+/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
+///
+/// This instruction invalidates any address-translation cache entries that an
+/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
+///
+/// This fence specifies all guest physical addresses and all virtual machines.
+#[inline]
+pub unsafe fn hinval_gvma_all() {
+ asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack))
+}
+
/// Reads the floating-point control and status register `fcsr`
///
/// Register `fcsr` is a 32-bit read/write register that selects the dynamic rounding mode
@@ -574,17 +588,6 @@ pub fn fsflags(value: u32) -> u32 {
original
}
-/// Invalidate hypervisor translation cache for all virtual machines and guest physical addresses
-///
-/// This instruction invalidates any address-translation cache entries that an
-/// `HFENCE.GVMA` instruction with the same values of `gaddr` and `vmid` would invalidate.
-///
-/// This fence specifies all guest physical addresses and all virtual machines.
-#[inline]
-pub unsafe fn hinval_gvma_all() {
- asm!(".insn r 0x73, 0, 0x33, x0, x0, x0", options(nostack))
-}
-
/// `P0` transformation function as is used in the SM3 hash algorithm
///
/// This function is included in `Zksh` extension. It's defined as:
@@ -602,12 +605,10 @@ pub unsafe fn hinval_gvma_all() {
/// According to RISC-V Cryptography Extensions, Volume I, the execution latency of
/// this instruction must always be independent from the data it operates on.
#[inline]
+#[target_feature(enable = "zksh")]
pub fn sm3p0(x: u32) -> u32 {
let ans: u32;
- unsafe {
- // asm!("sm3p0 {}, {}", out(reg) ans, in(reg) x, options(nomem, nostack))
- asm!(".insn i 0x13, 0x1, {}, {}, 0x108", out(reg) ans, in(reg) x, options(nomem, nostack))
- };
+ unsafe { asm!("sm3p0 {}, {}", lateout(reg) ans, in(reg) x, options(pure, nomem, nostack)) };
ans
}
@@ -634,12 +635,10 @@ pub fn sm3p0(x: u32) -> u32 {
/// According to RISC-V Cryptography Extensions, Volume I, the execution latency of
/// this instruction must always be independent from the data it operates on.
#[inline]
+#[target_feature(enable = "zksh")]
pub fn sm3p1(x: u32) -> u32 {
let ans: u32;
- unsafe {
- // asm!("sm3p1 {}, {}", out(reg) ans, in(reg) x, options(nomem, nostack))
- asm!(".insn i 0x13, 0x1, {}, {}, 0x109", out(reg) ans, in(reg) x, options(nomem, nostack))
- };
+ unsafe { asm!("sm3p1 {}, {}", lateout(reg) ans, in(reg) x, options(pure, nomem, nostack)) };
ans
}
@@ -674,33 +673,28 @@ pub fn sm3p1(x: u32) -> u32 {
/// It can be implemented by `sm4ed` instruction like:
///
/// ```no_run
+/// # #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
+/// # fn round_function(x0: u32, x1: u32, x2: u32, x3: u32, rk: u32) -> u32 {
+/// # #[cfg(target_arch = "riscv32")] use core::arch::riscv32::sm4ed;
+/// # #[cfg(target_arch = "riscv64")] use core::arch::riscv64::sm4ed;
/// let a = x1 ^ x2 ^ x3 ^ rk;
/// let c0 = sm4ed::<0>(x0, a);
/// let c1 = sm4ed::<1>(c0, a); // c1 represents c[0..=1], etc.
/// let c2 = sm4ed::<2>(c1, a);
/// let c3 = sm4ed::<3>(c2, a);
/// return c3; // c3 represents c[0..=3]
+/// # }
/// ```
///
/// According to RISC-V Cryptography Extensions, Volume I, the execution latency of
/// this instruction must always be independent from the data it operates on.
+#[inline]
+#[target_feature(enable = "zksed")]
pub fn sm4ed<const BS: u8>(x: u32, a: u32) -> u32 {
static_assert!(BS: u8 where BS <= 3);
let ans: u32;
- match BS {
- 0 => unsafe {
- asm!(".insn r 0x33, 0, 0x18, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) a, options(nomem, nostack))
- },
- 1 => unsafe {
- asm!(".insn r 0x33, 0, 0x38, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) a, options(nomem, nostack))
- },
- 2 => unsafe {
- asm!(".insn r 0x33, 0, 0x58, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) a, options(nomem, nostack))
- },
- 3 => unsafe {
- asm!(".insn r 0x33, 0, 0x78, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) a, options(nomem, nostack))
- },
- _ => unreachable!(),
+ unsafe {
+ asm!("sm4ed {}, {}, {}, {}", lateout(reg) ans, in(reg) x, in(reg) a, const BS, options(pure, nomem, nostack))
};
ans
}
@@ -739,33 +733,28 @@ pub fn sm4ed<const BS: u8>(x: u32, a: u32) -> u32 {
/// Hence, the key schedule operation can be implemented by `sm4ks` instruction like:
///
/// ```no_run
+/// # #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
+/// # fn key_schedule(k0: u32, k1: u32, k2: u32, k3: u32, ck_i: u32) -> u32 {
+/// # #[cfg(target_arch = "riscv32")] use core::arch::riscv32::sm4ks;
+/// # #[cfg(target_arch = "riscv64")] use core::arch::riscv64::sm4ks;
/// let k = k1 ^ k2 ^ k3 ^ ck_i;
/// let c0 = sm4ks::<0>(k0, k);
/// let c1 = sm4ks::<1>(c0, k); // c1 represents c[0..=1], etc.
/// let c2 = sm4ks::<2>(c1, k);
/// let c3 = sm4ks::<3>(c2, k);
/// return c3; // c3 represents c[0..=3]
+/// # }
/// ```
///
/// According to RISC-V Cryptography Extensions, Volume I, the execution latency of
/// this instruction must always be independent from the data it operates on.
+#[inline]
+#[target_feature(enable = "zksed")]
pub fn sm4ks<const BS: u8>(x: u32, k: u32) -> u32 {
static_assert!(BS: u8 where BS <= 3);
let ans: u32;
- match BS {
- 0 => unsafe {
- asm!(".insn r 0x33, 0, 0x1A, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) k, options(nomem, nostack))
- },
- 1 => unsafe {
- asm!(".insn r 0x33, 0, 0x3A, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) k, options(nomem, nostack))
- },
- 2 => unsafe {
- asm!(".insn r 0x33, 0, 0x5A, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) k, options(nomem, nostack))
- },
- 3 => unsafe {
- asm!(".insn r 0x33, 0, 0x7A, {}, {}, {}", out(reg) ans, in(reg) x, in(reg) k, options(nomem, nostack))
- },
- _ => unreachable!(),
+ unsafe {
+ asm!("sm4ks {}, {}, {}, {}", lateout(reg) ans, in(reg) x, in(reg) k, const BS, options(pure, nomem, nostack))
};
ans
}
diff --git a/library/stdarch/crates/core_arch/src/riscv_shared/p.rs b/library/stdarch/crates/core_arch/src/riscv_shared/p.rs
new file mode 100644
index 000000000..a26044aee
--- /dev/null
+++ b/library/stdarch/crates/core_arch/src/riscv_shared/p.rs
@@ -0,0 +1,1061 @@
+//! RISC-V Packed SIMD intrinsics; shared part.
+//!
+//! RV64 only part is placed in riscv64 folder.
+use crate::arch::asm;
+
+/// Adds packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn add16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x20, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the sum of packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn radd16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x00, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the sum of packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn uradd16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x10, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kadd16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x08, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukadd16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x18, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn sub16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x21, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the subtraction result of packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn rsub16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x01, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the subtraction result of packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn ursub16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x11, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn ksub16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x09, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn uksub16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x19, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross adds and subtracts packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn cras16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x22, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross halves of adds and subtracts packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn rcras16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x02, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross halves of adds and subtracts packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn urcras16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x12, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross adds and subtracts packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kcras16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross adds and subtracts packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukcras16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross subtracts and adds packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn crsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x23, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross halves of subtracts and adds packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn rcrsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x03, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross halves of subtracts and adds packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn urcrsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x13, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross subtracts and adds packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kcrsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Cross subtracts and adds packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukcrsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight adds and subtracts packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn stas16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x7A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight halves of adds and subtracts packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn rstas16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x5A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight halves of adds and subtracts packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn urstas16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x6A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight adds and subtracts packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kstas16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x62, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight adds and subtracts packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukstas16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x72, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight subtracts and adds packed 16-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn stsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x7B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight halves of subtracts and adds packed 16-bit signed numbers, dropping least bits
+#[inline]
+pub fn rstsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x5B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight halves of subtracts and adds packed 16-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn urstsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x6B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight subtracts and adds packed 16-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kstsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x63, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Straight subtracts and adds packed 16-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukstsa16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x73, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds packed 8-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn add8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x24, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the sum of packed 8-bit signed numbers, dropping least bits
+#[inline]
+pub fn radd8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x04, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the sum of packed 8-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn uradd8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x14, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds packed 8-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn kadd8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0C, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds packed 8-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn ukadd8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1C, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 8-bit signed numbers, discarding overflow bits
+#[inline]
+pub fn sub8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x25, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the subtraction result of packed 8-bit signed numbers, dropping least bits
+#[inline]
+pub fn rsub8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x05, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Halves the subtraction result of packed 8-bit unsigned numbers, dropping least bits
+#[inline]
+pub fn ursub8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x15, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 8-bit signed numbers, saturating at the numeric bounds
+#[inline]
+pub fn ksub8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0D, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts packed 8-bit unsigned numbers, saturating at the numeric bounds
+#[inline]
+pub fn uksub8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1D, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Arithmetic right shift packed 16-bit elements without rounding up
+#[inline]
+pub fn sra16(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x28, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Arithmetic right shift packed 16-bit elements with rounding up
+#[inline]
+pub fn sra16u(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x30, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical right shift packed 16-bit elements without rounding up
+#[inline]
+pub fn srl16(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x29, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical right shift packed 16-bit elements with rounding up
+#[inline]
+pub fn srl16u(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x31, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical left shift packed 16-bit elements, discarding overflow bits
+#[inline]
+pub fn sll16(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical left shift packed 16-bit elements, saturating at the numeric bounds
+#[inline]
+pub fn ksll16(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x32, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical saturating left then arithmetic right shift packed 16-bit elements
+#[inline]
+pub fn kslra16(a: usize, b: i32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical saturating left then arithmetic right shift packed 16-bit elements
+#[inline]
+pub fn kslra16u(a: usize, b: i32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x33, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Arithmetic right shift packed 8-bit elements without rounding up
+#[inline]
+pub fn sra8(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2C, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Arithmetic right shift packed 8-bit elements with rounding up
+#[inline]
+pub fn sra8u(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x34, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical right shift packed 8-bit elements without rounding up
+#[inline]
+pub fn srl8(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2D, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical right shift packed 8-bit elements with rounding up
+#[inline]
+pub fn srl8u(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x35, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical left shift packed 8-bit elements, discarding overflow bits
+#[inline]
+pub fn sll8(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2E, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical left shift packed 8-bit elements, saturating at the numeric bounds
+#[inline]
+pub fn ksll8(a: usize, b: u32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x36, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical saturating left then arithmetic right shift packed 8-bit elements
+#[inline]
+pub fn kslra8(a: usize, b: i32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x2F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Logical saturating left then arithmetic right shift packed 8-bit elements
+#[inline]
+pub fn kslra8u(a: usize, b: i32) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x37, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare equality for packed 16-bit elements
+#[inline]
+pub fn cmpeq16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x26, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 16-bit packed signed integers are less than the others
+#[inline]
+pub fn scmplt16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x06, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 16-bit packed signed integers are less than or equal to the others
+#[inline]
+pub fn scmple16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0E, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 16-bit packed unsigned integers are less than the others
+#[inline]
+pub fn ucmplt16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x16, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 16-bit packed unsigned integers are less than or equal to the others
+#[inline]
+pub fn ucmple16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1E, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare equality for packed 8-bit elements
+#[inline]
+pub fn cmpeq8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x27, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 8-bit packed signed integers are less than the others
+#[inline]
+pub fn scmplt8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x07, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 8-bit packed signed integers are less than or equal to the others
+#[inline]
+pub fn scmple8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 8-bit packed unsigned integers are less than the others
+#[inline]
+pub fn ucmplt8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x17, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Compare whether 8-bit packed unsigned integers are less than or equal to the others
+#[inline]
+pub fn ucmple8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x1F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get minimum values from 16-bit packed signed integers
+#[inline]
+pub fn smin16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x40, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get minimum values from 16-bit packed unsigned integers
+#[inline]
+pub fn umin16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x48, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get maximum values from 16-bit packed signed integers
+#[inline]
+pub fn smax16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x41, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get maximum values from 16-bit packed unsigned integers
+#[inline]
+pub fn umax16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x49, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/* todo: sclip16, uclip16 */
+
+/// Compute the absolute value of packed 16-bit signed integers
+#[inline]
+pub fn kabs16(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAD1", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of redundant sign bits of the packed 16-bit elements
+#[inline]
+pub fn clrs16(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAE8", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of leading zero bits of the packed 16-bit elements
+#[inline]
+pub fn clz16(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAE9", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Swap the 16-bit halfwords within each 32-bit word of a register
+#[inline]
+pub fn swap16(a: usize) -> usize {
+ let value: usize;
+ // this instruction is an alias for `pkbt rd, rs1, rs1`.
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x0F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get minimum values from 8-bit packed signed integers
+#[inline]
+pub fn smin8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x44, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get minimum values from 8-bit packed unsigned integers
+#[inline]
+pub fn umin8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x4C, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get maximum values from 8-bit packed signed integers
+#[inline]
+pub fn smax8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x45, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Get maximum values from 8-bit packed unsigned integers
+#[inline]
+pub fn umax8(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x4D, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/* todo: sclip8, uclip8 */
+
+/// Compute the absolute value of packed 8-bit signed integers
+#[inline]
+pub fn kabs8(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAD0", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of redundant sign bits of the packed 8-bit elements
+#[inline]
+pub fn clrs8(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAE0", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of leading zero bits of the packed 8-bit elements
+#[inline]
+pub fn clz8(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAE1", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Swap the 8-bit bytes within each 16-bit halfword of a register.
+#[inline]
+pub fn swap8(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAD8", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack first and zeroth into two 16-bit signed halfwords in each 32-bit chunk
+#[inline]
+pub fn sunpkd810(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAC8", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack second and zeroth into two 16-bit signed halfwords in each 32-bit chunk
+#[inline]
+pub fn sunpkd820(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAC9", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and zeroth into two 16-bit signed halfwords in each 32-bit chunk
+#[inline]
+pub fn sunpkd830(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACA", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and first into two 16-bit signed halfwords in each 32-bit chunk
+#[inline]
+pub fn sunpkd831(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACB", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and second into two 16-bit signed halfwords in each 32-bit chunk
+#[inline]
+pub fn sunpkd832(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAD3", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack first and zeroth into two 16-bit unsigned halfwords in each 32-bit chunk
+#[inline]
+pub fn zunpkd810(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACC", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack second and zeroth into two 16-bit unsigned halfwords in each 32-bit chunk
+#[inline]
+pub fn zunpkd820(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACD", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and zeroth into two 16-bit unsigned halfwords in each 32-bit chunk
+#[inline]
+pub fn zunpkd830(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACE", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and first into two 16-bit unsigned halfwords in each 32-bit chunk
+#[inline]
+pub fn zunpkd831(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xACF", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Unpack third and second into two 16-bit unsigned halfwords in each 32-bit chunk
+#[inline]
+pub fn zunpkd832(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAD7", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+// todo: pkbb16, pktt16
+
+/// Pack two 16-bit data from bottom and top half from 32-bit chunks
+#[inline]
+pub fn pkbt16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x0F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Pack two 16-bit data from top and bottom half from 32-bit chunks
+#[inline]
+pub fn pktb16(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x1F, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of redundant sign bits of the packed 32-bit elements
+#[inline]
+pub fn clrs32(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAF8", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Count the number of leading zero bits of the packed 32-bit elements
+#[inline]
+pub fn clz32(a: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn i 0x77, 0x0, {}, {}, 0xAF9", lateout(reg) value, in(reg) a, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Calculate the sum of absolute difference of unsigned 8-bit data elements
+#[inline]
+pub fn pbsad(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x7E, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Calculate and accumulate the sum of absolute difference of unsigned 8-bit data elements
+#[inline]
+pub fn pbsada(t: usize, a: usize, b: usize) -> usize {
+ let mut value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x7F, {}, {}, {}", inlateout(reg) t => value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Multiply signed 8-bit elements and add 16-bit elements on results for packed 32-bit chunks
+#[inline]
+pub fn smaqa(t: usize, a: usize, b: usize) -> usize {
+ let mut value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x64, {}, {}, {}", inlateout(reg) t => value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Multiply unsigned 8-bit elements and add 16-bit elements on results for packed 32-bit chunks
+#[inline]
+pub fn umaqa(t: usize, a: usize, b: usize) -> usize {
+ let mut value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x66, {}, {}, {}", inlateout(reg) t => value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Multiply signed to unsigned 8-bit and add 16-bit elements on results for packed 32-bit chunks
+#[inline]
+pub fn smaqasu(t: usize, a: usize, b: usize) -> usize {
+ let mut value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x0, 0x65, {}, {}, {}", inlateout(reg) t => value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds signed lower 16-bit content of two registers with Q15 saturation
+#[inline]
+pub fn kaddh(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x02, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts signed lower 16-bit content of two registers with Q15 saturation
+#[inline]
+pub fn ksubh(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x03, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Adds signed lower 16-bit content of two registers with U16 saturation
+#[inline]
+pub fn ukaddh(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x0A, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
+
+/// Subtracts signed lower 16-bit content of two registers with U16 saturation
+#[inline]
+pub fn uksubh(a: usize, b: usize) -> usize {
+ let value: usize;
+ unsafe {
+ asm!(".insn r 0x77, 0x1, 0x0B, {}, {}, {}", lateout(reg) value, in(reg) a, in(reg) b, options(pure, nomem, nostack))
+ }
+ value
+}
diff --git a/library/stdarch/crates/core_arch/src/simd_llvm.rs b/library/stdarch/crates/core_arch/src/simd_llvm.rs
index 1970e5c69..decdecaaf 100644
--- a/library/stdarch/crates/core_arch/src/simd_llvm.rs
+++ b/library/stdarch/crates/core_arch/src/simd_llvm.rs
@@ -9,13 +9,7 @@ extern "platform-intrinsic" {
pub fn simd_gt<T, U>(x: T, y: T) -> U;
pub fn simd_ge<T, U>(x: T, y: T) -> U;
- pub fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
- pub fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
- pub fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
- pub fn simd_shuffle16<T, U>(x: T, y: T, idx: [u32; 16]) -> U;
- pub fn simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U;
- pub fn simd_shuffle64<T, U>(x: T, y: T, idx: [u32; 64]) -> U;
- pub fn simd_shuffle128<T, U>(x: T, y: T, idx: [u32; 128]) -> U;
+ pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
#[rustc_const_unstable(feature = "const_simd_insert", issue = "none")]
pub fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T;
diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs
index 24f9c0301..16add3dbb 100644
--- a/library/stdarch/crates/core_arch/src/x86/avx2.rs
+++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs
@@ -2001,7 +2001,7 @@ 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 {
- pmovmskb(a.as_i8x32())
+ simd_bitmask::<_, u32>(a.as_i8x32()) as i32
}
/// Computes the sum of absolute differences (SADs) of quadruplets of unsigned
@@ -3642,8 +3642,6 @@ extern "C" {
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.pmovmskb"]
- fn pmovmskb(a: i8x32) -> i32;
#[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/cpuid.rs b/library/stdarch/crates/core_arch/src/x86/cpuid.rs
index 6b90295ef..2624e8bdf 100644
--- a/library/stdarch/crates/core_arch/src/x86/cpuid.rs
+++ b/library/stdarch/crates/core_arch/src/x86/cpuid.rs
@@ -62,27 +62,27 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult {
#[cfg(target_arch = "x86")]
{
asm!(
- "movl %ebx, {0}",
+ "mov {0}, ebx",
"cpuid",
- "xchgl %ebx, {0}",
- lateout(reg) ebx,
- inlateout("eax") leaf => eax,
- inlateout("ecx") sub_leaf => ecx,
- lateout("edx") edx,
- options(nostack, preserves_flags, att_syntax),
+ "xchg {0}, ebx",
+ out(reg) ebx,
+ inout("eax") leaf => eax,
+ inout("ecx") sub_leaf => ecx,
+ out("edx") edx,
+ options(nostack, preserves_flags),
);
}
#[cfg(target_arch = "x86_64")]
{
asm!(
- "movq %rbx, {0:r}",
+ "mov {0:r}, rbx",
"cpuid",
- "xchgq %rbx, {0:r}",
- lateout(reg) ebx,
- inlateout("eax") leaf => eax,
- inlateout("ecx") sub_leaf => ecx,
- lateout("edx") edx,
- options(nostack, preserves_flags, att_syntax),
+ "xchg {0:r}, rbx",
+ out(reg) ebx,
+ inout("eax") leaf => eax,
+ inout("ecx") sub_leaf => ecx,
+ out("edx") edx,
+ options(nostack, preserves_flags),
);
}
CpuidResult { eax, ebx, ecx, edx }
diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs
index 547bfe67d..6b50e95b2 100644
--- a/library/stdarch/crates/core_arch/src/x86/mod.rs
+++ b/library/stdarch/crates/core_arch/src/x86/mod.rs
@@ -306,7 +306,7 @@ types! {
/// 256-bit wide set of 16 'u16' types, x86-specific
///
- /// This type is the same as the `__m128bh` type defined by Intel,
+ /// This type is the same as the `__m256bh` type defined by Intel,
/// representing a 256-bit SIMD register which internally is consisted of
/// 16 packed `u16` instances. Its purpose is for bf16 related intrinsic
/// implementations.
@@ -317,7 +317,7 @@ types! {
/// 512-bit wide set of 32 'u16' types, x86-specific
///
- /// This type is the same as the `__m128bh` type defined by Intel,
+ /// This type is the same as the `__m512bh` type defined by Intel,
/// representing a 512-bit SIMD register which internally is consisted of
/// 32 packed `u16` instances. Its purpose is for bf16 related intrinsic
/// implementations.
diff --git a/library/stdarch/crates/core_arch/src/x86/sse2.rs b/library/stdarch/crates/core_arch/src/x86/sse2.rs
index d82b8641f..3e79b3539 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse2.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse2.rs
@@ -1378,7 +1378,7 @@ 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 {
- pmovmskb(a.as_i8x16())
+ simd_bitmask::<_, u16>(a.as_i8x16()) as u32 as i32
}
/// Shuffles 32-bit integers in `a` using the control in `IMM8`.
@@ -2856,8 +2856,6 @@ extern "C" {
fn packssdw(a: i32x4, b: i32x4) -> i16x8;
#[link_name = "llvm.x86.sse2.packuswb.128"]
fn packuswb(a: i16x8, b: i16x8) -> u8x16;
- #[link_name = "llvm.x86.sse2.pmovmskb.128"]
- fn pmovmskb(a: i8x16) -> i32;
#[link_name = "llvm.x86.sse2.max.sd"]
fn maxsd(a: __m128d, b: __m128d) -> __m128d;
#[link_name = "llvm.x86.sse2.max.pd"]
diff --git a/library/stdarch/crates/core_arch/src/x86/sse3.rs b/library/stdarch/crates/core_arch/src/x86/sse3.rs
index ab0dd38fe..61f8a4e78 100644
--- a/library/stdarch/crates/core_arch/src/x86/sse3.rs
+++ b/library/stdarch/crates/core_arch/src/x86/sse3.rs
@@ -1,11 +1,7 @@
//! Streaming SIMD Extensions 3 (SSE3)
use crate::{
- core_arch::{
- simd::*,
- simd_llvm::{simd_shuffle2, simd_shuffle4},
- x86::*,
- },
+ core_arch::{simd::*, simd_llvm::simd_shuffle, x86::*},
mem::transmute,
};
diff --git a/library/stdarch/crates/std_detect/Cargo.toml b/library/stdarch/crates/std_detect/Cargo.toml
index 1ca0d9c5d..3a482564e 100644
--- a/library/stdarch/crates/std_detect/Cargo.toml
+++ b/library/stdarch/crates/std_detect/Cargo.toml
@@ -22,7 +22,7 @@ maintenance = { status = "experimental" }
[dependencies]
libc = { version = "0.2", optional = true, default-features = false }
-cfg-if = "0.1.10"
+cfg-if = "1.0.0"
# When built as part of libstd
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
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 b6a2e5218..6c79ba86d 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
@@ -23,58 +23,62 @@ pub(crate) fn detect_features() -> cache::Initializer {
/// The names match those used for cpuinfo.
///
/// [hwcap]: https://github.com/torvalds/linux/blob/master/arch/arm64/include/uapi/asm/hwcap.h
+#[derive(Debug, Default, PartialEq)]
struct AtHwcap {
- fp: bool, // 0
- asimd: bool, // 1
- // evtstrm: bool, // 2 No LLVM support
- aes: bool, // 3
- pmull: bool, // 4
- sha1: bool, // 5
- sha2: bool, // 6
- crc32: bool, // 7
- atomics: bool, // 8
- fphp: bool, // 9
- asimdhp: bool, // 10
- // cpuid: bool, // 11 No LLVM support
- asimdrdm: bool, // 12
- jscvt: bool, // 13
- fcma: bool, // 14
- lrcpc: bool, // 15
- dcpop: bool, // 16
- sha3: bool, // 17
- sm3: bool, // 18
- sm4: bool, // 19
- asimddp: bool, // 20
- sha512: bool, // 21
- sve: bool, // 22
- fhm: bool, // 23
- dit: bool, // 24
- uscat: bool, // 25
- ilrcpc: bool, // 26
- flagm: bool, // 27
- ssbs: bool, // 28
- sb: bool, // 29
- paca: bool, // 30
- pacg: bool, // 31
- dcpodp: bool, // 32
- sve2: bool, // 33
- sveaes: bool, // 34
- // svepmull: bool, // 35 No LLVM support
- svebitperm: bool, // 36
- svesha3: bool, // 37
- svesm4: bool, // 38
- // flagm2: bool, // 39 No LLVM support
- frint: bool, // 40
- // svei8mm: bool, // 41 See i8mm feature
- svef32mm: bool, // 42
- svef64mm: bool, // 43
- // svebf16: bool, // 44 See bf16 feature
- i8mm: bool, // 45
- bf16: bool, // 46
- // dgh: bool, // 47 No LLVM support
- rng: bool, // 48
- bti: bool, // 49
- mte: bool, // 50
+ // AT_HWCAP
+ fp: bool,
+ asimd: bool,
+ // evtstrm: No LLVM support.
+ aes: bool,
+ pmull: bool,
+ sha1: bool,
+ sha2: bool,
+ crc32: bool,
+ atomics: bool,
+ fphp: bool,
+ asimdhp: bool,
+ // cpuid: No LLVM support.
+ asimdrdm: bool,
+ jscvt: bool,
+ fcma: bool,
+ lrcpc: bool,
+ dcpop: bool,
+ sha3: bool,
+ sm3: bool,
+ sm4: bool,
+ asimddp: bool,
+ sha512: bool,
+ sve: bool,
+ fhm: bool,
+ dit: bool,
+ uscat: bool,
+ ilrcpc: bool,
+ flagm: bool,
+ ssbs: bool,
+ sb: bool,
+ paca: bool,
+ pacg: bool,
+
+ // AT_HWCAP2
+ dcpodp: bool,
+ sve2: bool,
+ sveaes: bool,
+ // svepmull: No LLVM support.
+ svebitperm: bool,
+ svesha3: bool,
+ svesm4: bool,
+ // flagm2: No LLVM support.
+ frint: bool,
+ // svei8mm: See i8mm feature.
+ svef32mm: bool,
+ svef64mm: bool,
+ // svebf16: See bf16 feature.
+ i8mm: bool,
+ bf16: bool,
+ // dgh: No LLVM support.
+ rng: bool,
+ bti: bool,
+ mte: bool,
}
impl From<auxvec::AuxVec> for AtHwcap {
@@ -113,25 +117,25 @@ impl From<auxvec::AuxVec> for AtHwcap {
sb: bit::test(auxv.hwcap, 29),
paca: bit::test(auxv.hwcap, 30),
pacg: bit::test(auxv.hwcap, 31),
- dcpodp: bit::test(auxv.hwcap, 32),
- sve2: bit::test(auxv.hwcap, 33),
- sveaes: bit::test(auxv.hwcap, 34),
- // svepmull: bit::test(auxv.hwcap, 35),
- svebitperm: bit::test(auxv.hwcap, 36),
- svesha3: bit::test(auxv.hwcap, 37),
- svesm4: bit::test(auxv.hwcap, 38),
- // flagm2: bit::test(auxv.hwcap, 39),
- frint: bit::test(auxv.hwcap, 40),
- // svei8mm: bit::test(auxv.hwcap, 41),
- svef32mm: bit::test(auxv.hwcap, 42),
- svef64mm: bit::test(auxv.hwcap, 43),
- // svebf16: bit::test(auxv.hwcap, 44),
- i8mm: bit::test(auxv.hwcap, 45),
- bf16: bit::test(auxv.hwcap, 46),
- // dgh: bit::test(auxv.hwcap, 47),
- rng: bit::test(auxv.hwcap, 48),
- bti: bit::test(auxv.hwcap, 49),
- mte: bit::test(auxv.hwcap, 50),
+ dcpodp: bit::test(auxv.hwcap2, 0),
+ sve2: bit::test(auxv.hwcap2, 1),
+ sveaes: bit::test(auxv.hwcap2, 2),
+ // svepmull: bit::test(auxv.hwcap2, 3),
+ svebitperm: bit::test(auxv.hwcap2, 4),
+ svesha3: bit::test(auxv.hwcap2, 5),
+ svesm4: bit::test(auxv.hwcap2, 6),
+ // flagm2: bit::test(auxv.hwcap2, 7),
+ frint: bit::test(auxv.hwcap2, 8),
+ // svei8mm: bit::test(auxv.hwcap2, 9),
+ svef32mm: bit::test(auxv.hwcap2, 10),
+ svef64mm: bit::test(auxv.hwcap2, 11),
+ // svebf16: bit::test(auxv.hwcap2, 12),
+ i8mm: bit::test(auxv.hwcap2, 13),
+ bf16: bit::test(auxv.hwcap2, 14),
+ // dgh: bit::test(auxv.hwcap2, 15),
+ rng: bit::test(auxv.hwcap2, 16),
+ bti: bit::test(auxv.hwcap2, 17),
+ mte: bit::test(auxv.hwcap2, 18),
}
}
}
@@ -288,3 +292,86 @@ impl AtHwcap {
value
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[cfg(feature = "std_detect_file_io")]
+ mod auxv_from_file {
+ use super::auxvec::auxv_from_file;
+ use super::*;
+ // The baseline hwcaps used in the (artificial) auxv test files.
+ fn baseline_hwcaps() -> AtHwcap {
+ AtHwcap {
+ fp: true,
+ asimd: true,
+ aes: true,
+ pmull: true,
+ sha1: true,
+ sha2: true,
+ crc32: true,
+ atomics: true,
+ fphp: true,
+ asimdhp: true,
+ asimdrdm: true,
+ lrcpc: true,
+ dcpop: true,
+ asimddp: true,
+ ssbs: true,
+ ..AtHwcap::default()
+ }
+ }
+
+ #[test]
+ fn linux_empty_hwcap2_aarch64() {
+ let file = concat!(
+ env!("CARGO_MANIFEST_DIR"),
+ "/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv"
+ );
+ println!("file: {}", file);
+ let v = auxv_from_file(file).unwrap();
+ println!("HWCAP : 0x{:0x}", v.hwcap);
+ println!("HWCAP2: 0x{:0x}", v.hwcap2);
+ assert_eq!(AtHwcap::from(v), baseline_hwcaps());
+ }
+ #[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);
+ let v = auxv_from_file(file).unwrap();
+ println!("HWCAP : 0x{:0x}", v.hwcap);
+ println!("HWCAP2: 0x{:0x}", v.hwcap2);
+ assert_eq!(AtHwcap::from(v), baseline_hwcaps());
+ }
+ #[test]
+ fn linux_hwcap2_aarch64() {
+ let file = concat!(
+ env!("CARGO_MANIFEST_DIR"),
+ "/src/detect/test_data/linux-hwcap2-aarch64.auxv"
+ );
+ println!("file: {}", file);
+ let v = auxv_from_file(file).unwrap();
+ println!("HWCAP : 0x{:0x}", v.hwcap);
+ println!("HWCAP2: 0x{:0x}", v.hwcap2);
+ assert_eq!(
+ AtHwcap::from(v),
+ AtHwcap {
+ // Some other HWCAP bits.
+ paca: true,
+ pacg: true,
+ // HWCAP2-only bits.
+ dcpodp: true,
+ frint: true,
+ rng: true,
+ bti: true,
+ mte: true,
+ ..baseline_hwcaps()
+ }
+ );
+ }
+ }
+}
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 e6447d0cd..c903903bd 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
@@ -7,6 +7,7 @@ pub(crate) const AT_NULL: usize = 0;
pub(crate) const AT_HWCAP: usize = 16;
/// Key to access the CPU Hardware capabilities 2 bitfield.
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
@@ -21,6 +22,7 @@ pub(crate) const AT_HWCAP2: usize = 26;
pub(crate) struct AuxVec {
pub hwcap: usize,
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
@@ -64,13 +66,14 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
if let Ok(hwcap) = getauxval(AT_HWCAP) {
// Targets with only AT_HWCAP:
#[cfg(any(
- target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "mips",
target_arch = "mips64"
))]
{
+ // Zero could indicate that no features were detected, but it's also used to
+ // indicate an error. In either case, try the fallback.
if hwcap != 0 {
return Ok(AuxVec { hwcap });
}
@@ -78,13 +81,18 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
// Targets with AT_HWCAP and AT_HWCAP2:
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
))]
{
if let Ok(hwcap2) = getauxval(AT_HWCAP2) {
- if hwcap != 0 && hwcap2 != 0 {
+ // Zero could indicate that no features were detected, but it's also used to
+ // indicate an error. In particular, on many platforms AT_HWCAP2 will be
+ // legitimately zero, since it contains the most recent feature flags. Use the
+ // fallback only if no features were detected at all.
+ if hwcap != 0 || hwcap2 != 0 {
return Ok(AuxVec { hwcap, hwcap2 });
}
}
@@ -97,7 +105,6 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
{
// Targets with only AT_HWCAP:
#[cfg(any(
- target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "mips",
@@ -105,6 +112,8 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
))]
{
let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize };
+ // Zero could indicate that no features were detected, but it's also used to indicate
+ // an error. In either case, try the fallback.
if hwcap != 0 {
return Ok(AuxVec { hwcap });
}
@@ -112,6 +121,7 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
// Targets with AT_HWCAP and AT_HWCAP2:
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
@@ -119,7 +129,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
{
let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize };
let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2 as libc::c_ulong) as usize };
- if hwcap != 0 && hwcap2 != 0 {
+ // Zero could indicate that no features were detected, but it's also used to indicate
+ // an error. In particular, on many platforms AT_HWCAP2 will be legitimately zero,
+ // since it contains the most recent feature flags. Use the fallback only if no
+ // features were detected at all.
+ if hwcap != 0 || hwcap2 != 0 {
return Ok(AuxVec { hwcap, hwcap2 });
}
}
@@ -158,7 +172,7 @@ fn getauxval(key: usize) -> Result<usize, ()> {
/// Tries to read the auxiliary vector from the `file`. If this fails, this
/// function returns `Err`.
#[cfg(feature = "std_detect_file_io")]
-fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
+pub(super) fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
let file = super::read_file(file)?;
// See <https://github.com/torvalds/linux/blob/v3.19/include/uapi/linux/auxvec.h>.
@@ -181,7 +195,6 @@ fn auxv_from_file(file: &str) -> Result<AuxVec, ()> {
fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
// Targets with only AT_HWCAP:
#[cfg(any(
- target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "mips",
@@ -198,23 +211,25 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
}
// Targets with AT_HWCAP and AT_HWCAP2:
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
))]
{
let mut hwcap = None;
- let mut hwcap2 = None;
+ // For some platforms, AT_HWCAP2 was added recently, so let it default to zero.
+ let mut hwcap2 = 0;
for el in buf.chunks(2) {
match el[0] {
AT_NULL => break,
AT_HWCAP => hwcap = Some(el[1]),
- AT_HWCAP2 => hwcap2 = Some(el[1]),
+ AT_HWCAP2 => hwcap2 = el[1],
_ => (),
}
}
- if let (Some(hwcap), Some(hwcap2)) = (hwcap, hwcap2) {
+ if let Some(hwcap) = hwcap {
return Ok(AuxVec { hwcap, hwcap2 });
}
}
@@ -256,7 +271,6 @@ mod tests {
// FIXME: on mips/mips64 getauxval returns 0, and /proc/self/auxv
// does not always contain the AT_HWCAP key under qemu.
#[cfg(any(
- target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
@@ -271,6 +285,7 @@ mod tests {
// Targets with AT_HWCAP and AT_HWCAP2:
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
@@ -305,24 +320,31 @@ mod tests {
}
#[test]
- #[should_panic]
fn linux_macos_vb() {
let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/macos-virtualbox-linux-x86-4850HQ.auxv");
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();
- // this file is incomplete (contains hwcap but not hwcap2), we
- // want to fall back to /proc/cpuinfo in this case, so
- // reading should fail. assert_eq!(v.hwcap, 126614527);
- // assert_eq!(v.hwcap2, 0);
- let _ = v;
+ assert_eq!(v.hwcap, 126614527);
+ assert_eq!(v.hwcap2, 0);
}
} else if #[cfg(target_arch = "aarch64")] {
#[test]
- fn linux_x64() {
- let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-x64-i7-6850k.auxv");
+ fn linux_artificial_aarch64() {
+ let file = concat!(env!("CARGO_MANIFEST_DIR"), "/src/detect/test_data/linux-artificial-aarch64.auxv");
println!("file: {}", file);
let v = auxv_from_file(file).unwrap();
- assert_eq!(v.hwcap, 3219913727);
+ assert_eq!(v.hwcap, 0x0123456789abcdef);
+ assert_eq!(v.hwcap2, 0x02468ace13579bdf);
+ }
+ #[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);
+ 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);
+ assert_eq!(v.hwcap2, 0);
}
}
}
@@ -353,6 +375,7 @@ mod tests {
// Targets with AT_HWCAP and AT_HWCAP2:
#[cfg(any(
+ target_arch = "aarch64",
target_arch = "arm",
target_arch = "powerpc",
target_arch = "powerpc64"
diff --git a/library/stdarch/crates/std_detect/src/detect/test_data/linux-artificial-aarch64.auxv b/library/stdarch/crates/std_detect/src/detect/test_data/linux-artificial-aarch64.auxv
new file mode 100644
index 000000000..ec826afcf
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/test_data/linux-artificial-aarch64.auxv
Binary files differ
diff --git a/library/stdarch/crates/std_detect/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv b/library/stdarch/crates/std_detect/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv
new file mode 100644
index 000000000..95537b73f
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/test_data/linux-empty-hwcap2-aarch64.auxv
Binary files differ
diff --git a/library/stdarch/crates/std_detect/src/detect/test_data/linux-hwcap2-aarch64.auxv b/library/stdarch/crates/std_detect/src/detect/test_data/linux-hwcap2-aarch64.auxv
new file mode 100644
index 000000000..1d87264b2
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/test_data/linux-hwcap2-aarch64.auxv
Binary files differ
diff --git a/library/stdarch/crates/std_detect/src/detect/test_data/linux-no-hwcap2-aarch64.auxv b/library/stdarch/crates/std_detect/src/detect/test_data/linux-no-hwcap2-aarch64.auxv
new file mode 100644
index 000000000..35f01cc76
--- /dev/null
+++ b/library/stdarch/crates/std_detect/src/detect/test_data/linux-no-hwcap2-aarch64.auxv
Binary files differ
diff --git a/library/stdarch/crates/std_detect/src/detect/test_data/linux-x64-i7-6850k.auxv b/library/stdarch/crates/std_detect/src/detect/test_data/linux-x64-i7-6850k.auxv
deleted file mode 100644
index 6afe1b3b4..000000000
--- a/library/stdarch/crates/std_detect/src/detect/test_data/linux-x64-i7-6850k.auxv
+++ /dev/null
Binary files differ
diff --git a/library/stdarch/crates/stdarch-test/Cargo.toml b/library/stdarch/crates/stdarch-test/Cargo.toml
index 9ac1057be..012b4e959 100644
--- a/library/stdarch/crates/stdarch-test/Cargo.toml
+++ b/library/stdarch/crates/stdarch-test/Cargo.toml
@@ -10,7 +10,7 @@ simd-test-macro = { path = "../simd-test-macro" }
cc = "1.0"
lazy_static = "1.0"
rustc-demangle = "0.1.8"
-cfg-if = "0.1"
+cfg-if = "1.0"
# We use a crates.io dependency to disassemble wasm binaries to look for
# instructions for `#[assert_instr]`. Note that we use an `=` dependency here
diff --git a/library/stdarch/crates/stdarch-test/src/lib.rs b/library/stdarch/crates/stdarch-test/src/lib.rs
index 078736c66..eba17771c 100644
--- a/library/stdarch/crates/stdarch-test/src/lib.rs
+++ b/library/stdarch/crates/stdarch-test/src/lib.rs
@@ -3,7 +3,6 @@
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.
-#![feature(bench_black_box)] // For black_box
#![deny(rust_2018_idioms)]
#![allow(clippy::missing_docs_in_private_items, clippy::print_stdout)]
diff --git a/library/test/src/bench.rs b/library/test/src/bench.rs
index 7869ba2c0..23925e6ea 100644
--- a/library/test/src/bench.rs
+++ b/library/test/src/bench.rs
@@ -49,12 +49,12 @@ impl Bencher {
self.summary = Some(iter(&mut inner));
}
- pub fn bench<F>(&mut self, mut f: F) -> Option<stats::Summary>
+ pub fn bench<F>(&mut self, mut f: F) -> Result<Option<stats::Summary>, String>
where
- F: FnMut(&mut Bencher),
+ F: FnMut(&mut Bencher) -> Result<(), String>,
{
- f(self);
- self.summary
+ let result = f(self);
+ result.map(|_| self.summary)
}
}
@@ -195,7 +195,7 @@ pub fn benchmark<F>(
nocapture: bool,
f: F,
) where
- F: FnMut(&mut Bencher),
+ F: FnMut(&mut Bencher) -> Result<(), String>,
{
let mut bs = Bencher { mode: BenchMode::Auto, summary: None, bytes: 0 };
@@ -211,14 +211,14 @@ pub fn benchmark<F>(
let test_result = match result {
//bs.bench(f) {
- Ok(Some(ns_iter_summ)) => {
+ Ok(Ok(Some(ns_iter_summ))) => {
let ns_iter = cmp::max(ns_iter_summ.median as u64, 1);
let mb_s = bs.bytes * 1000 / ns_iter;
let bs = BenchSamples { ns_iter_summ, mb_s: mb_s as usize };
TestResult::TrBench(bs)
}
- Ok(None) => {
+ Ok(Ok(None)) => {
// iter not called, so no data.
// FIXME: error in this case?
let samples: &mut [f64] = &mut [0.0_f64; 1];
@@ -226,6 +226,7 @@ pub fn benchmark<F>(
TestResult::TrBench(bs)
}
Err(_) => TestResult::TrFailed,
+ Ok(Err(_)) => TestResult::TrFailed,
};
let stdout = data.lock().unwrap().to_vec();
@@ -233,10 +234,10 @@ pub fn benchmark<F>(
monitor_ch.send(message).unwrap();
}
-pub fn run_once<F>(f: F)
+pub fn run_once<F>(f: F) -> Result<(), String>
where
- F: FnMut(&mut Bencher),
+ F: FnMut(&mut Bencher) -> Result<(), String>,
{
let mut bs = Bencher { mode: BenchMode::Single, summary: None, bytes: 0 };
- bs.bench(f);
+ bs.bench(f).map(|_| ())
}
diff --git a/library/test/src/cli.rs b/library/test/src/cli.rs
index f981b9c49..8be32183f 100644
--- a/library/test/src/cli.rs
+++ b/library/test/src/cli.rs
@@ -3,9 +3,9 @@
use std::env;
use std::path::PathBuf;
-use super::helpers::isatty;
use super::options::{ColorConfig, Options, OutputFormat, RunIgnored};
use super::time::TestTimeOptions;
+use std::io::{self, IsTerminal};
#[derive(Debug)]
pub struct TestOpts {
@@ -32,7 +32,7 @@ pub struct TestOpts {
impl TestOpts {
pub fn use_color(&self) -> bool {
match self.color {
- ColorConfig::AutoColor => !self.nocapture && isatty::stdout_isatty(),
+ ColorConfig::AutoColor => !self.nocapture && io::stdout().is_terminal(),
ColorConfig::AlwaysColor => true,
ColorConfig::NeverColor => false,
}
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index e9dda9896..b1270c272 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -147,7 +147,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Res
let mut ntest = 0;
let mut nbench = 0;
- for test in filter_tests(&opts, tests) {
+ for test in filter_tests(&opts, tests).into_iter() {
use crate::TestFn::*;
let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test;
diff --git a/library/test/src/helpers/isatty.rs b/library/test/src/helpers/isatty.rs
deleted file mode 100644
index 874ecc376..000000000
--- a/library/test/src/helpers/isatty.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-//! Helper module which provides a function to test
-//! if stdout is a tty.
-
-cfg_if::cfg_if! {
- if #[cfg(unix)] {
- pub fn stdout_isatty() -> bool {
- unsafe { libc::isatty(libc::STDOUT_FILENO) != 0 }
- }
- } else if #[cfg(windows)] {
- pub fn stdout_isatty() -> bool {
- type DWORD = u32;
- type BOOL = i32;
- type HANDLE = *mut u8;
- type LPDWORD = *mut u32;
- const STD_OUTPUT_HANDLE: DWORD = -11i32 as DWORD;
- extern "system" {
- fn GetStdHandle(which: DWORD) -> HANDLE;
- fn GetConsoleMode(hConsoleHandle: HANDLE, lpMode: LPDWORD) -> BOOL;
- }
- unsafe {
- let handle = GetStdHandle(STD_OUTPUT_HANDLE);
- let mut out = 0;
- GetConsoleMode(handle, &mut out) != 0
- }
- }
- } else {
- // FIXME: Implement isatty on SGX
- pub fn stdout_isatty() -> bool {
- false
- }
- }
-}
diff --git a/library/test/src/helpers/mod.rs b/library/test/src/helpers/mod.rs
index 049cadf86..6f366a911 100644
--- a/library/test/src/helpers/mod.rs
+++ b/library/test/src/helpers/mod.rs
@@ -3,6 +3,5 @@
pub mod concurrency;
pub mod exit_code;
-pub mod isatty;
pub mod metrics;
pub mod shuffle;
diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs
index 3b7193adc..141f16d17 100644
--- a/library/test/src/lib.rs
+++ b/library/test/src/lib.rs
@@ -6,7 +6,8 @@
//! benchmarks themselves) should be done via the `#[test]` and
//! `#[bench]` attributes.
//!
-//! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more details.
+//! See the [Testing Chapter](../book/ch11-00-testing.html) of the book for more
+//! details.
// Currently, not much of this is meant for users. It is intended to
// support the simplest interface possible for representing and
@@ -15,10 +16,11 @@
#![unstable(feature = "test", issue = "50297")]
#![doc(test(attr(deny(warnings))))]
-#![feature(bench_black_box)]
#![feature(internal_output_capture)]
+#![feature(is_terminal)]
#![feature(staged_api)]
#![feature(process_exitcode_internals)]
+#![feature(panic_can_unwind)]
#![feature(test)]
// Public reexports
@@ -53,6 +55,7 @@ use std::{
collections::VecDeque,
env, io,
io::prelude::Write,
+ mem::ManuallyDrop,
panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo},
process::{self, Command, Termination},
sync::mpsc::{channel, Sender},
@@ -77,6 +80,7 @@ mod types;
#[cfg(test)]
mod tests;
+use core::any::Any;
use event::{CompletedTest, TestEvent};
use helpers::concurrency::get_concurrency;
use helpers::exit_code::get_exit_code;
@@ -110,6 +114,29 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
process::exit(ERROR_EXIT_CODE);
}
} else {
+ if !opts.nocapture {
+ // If we encounter a non-unwinding panic, flush any captured output from the current test,
+ // and stop capturing output to ensure that the non-unwinding panic message is visible.
+ // We also acquire the locks for both output streams to prevent output from other threads
+ // from interleaving with the panic message or appearing after it.
+ let builtin_panic_hook = panic::take_hook();
+ let hook = Box::new({
+ move |info: &'_ PanicInfo<'_>| {
+ if !info.can_unwind() {
+ std::mem::forget(std::io::stderr().lock());
+ let mut stdout = ManuallyDrop::new(std::io::stdout().lock());
+ if let Some(captured) = io::set_output_capture(None) {
+ if let Ok(data) = captured.lock() {
+ let _ = stdout.write_all(&data);
+ let _ = stdout.flush();
+ }
+ }
+ }
+ builtin_panic_hook(info);
+ }
+ });
+ panic::set_hook(hook);
+ }
match console::run_tests_console(&opts, tests) {
Ok(true) => {}
Ok(false) => process::exit(ERROR_EXIT_CODE),
@@ -176,17 +203,20 @@ fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
}
}
-/// Invoked when unit tests terminate. Should panic if the unit
-/// Tests is considered a failure. By default, invokes `report()`
-/// and checks for a `0` result.
-pub fn assert_test_result<T: Termination>(result: T) {
+/// Invoked when unit tests terminate. Returns `Result::Err` if the test is
+/// 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();
- assert_eq!(
- code, 0,
- "the test returned a termination value with a non-zero status code ({}) \
- which indicates a failure",
- code
- );
+ if code == 0 {
+ Ok(())
+ } else {
+ Err(format!(
+ "the test returned a termination value with a non-zero status code \
+ ({}) which indicates a failure",
+ code
+ ))
+ }
}
pub fn run_tests<F>(
@@ -242,7 +272,7 @@ where
let event = TestEvent::TeFiltered(filtered_descs, shuffle_seed);
notify_about_test_event(event)?;
- let (filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
+ let (mut filtered_tests, filtered_benchs): (Vec<_>, _) = filtered_tests
.into_iter()
.enumerate()
.map(|(i, e)| (TestId(i), e))
@@ -250,12 +280,12 @@ where
let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
- let mut remaining = filtered_tests;
if let Some(shuffle_seed) = shuffle_seed {
- shuffle_tests(shuffle_seed, &mut remaining);
- } else {
- remaining.reverse();
+ shuffle_tests(shuffle_seed, &mut filtered_tests);
}
+ // Store the tests in a VecDeque so we can efficiently remove the first element to run the
+ // tests in the order they were passed (unless shuffled).
+ let mut remaining = VecDeque::from(filtered_tests);
let mut pending = 0;
let (tx, rx) = channel::<CompletedTest>();
@@ -295,7 +325,7 @@ where
if concurrency == 1 {
while !remaining.is_empty() {
- let (id, test) = remaining.pop().unwrap();
+ let (id, test) = remaining.pop_front().unwrap();
let event = TestEvent::TeWait(test.desc.clone());
notify_about_test_event(event)?;
let join_handle =
@@ -309,7 +339,7 @@ where
} else {
while pending > 0 || !remaining.is_empty() {
while pending < concurrency && !remaining.is_empty() {
- let (id, test) = remaining.pop().unwrap();
+ let (id, test) = remaining.pop_front().unwrap();
let timeout = time::get_default_test_timeout();
let desc = test.desc.clone();
@@ -421,9 +451,6 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
RunIgnored::No => {}
}
- // Sort the tests alphabetically
- filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
-
filtered
}
@@ -479,7 +506,7 @@ pub fn run_test(
id: TestId,
desc: TestDesc,
monitor_ch: Sender<CompletedTest>,
- testfn: Box<dyn FnOnce() + Send>,
+ testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
opts: TestRunOpts,
) -> Option<thread::JoinHandle<()>> {
let concurrency = opts.concurrency;
@@ -568,11 +595,11 @@ pub fn run_test(
/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`.
#[inline(never)]
-fn __rust_begin_short_backtrace<F: FnOnce()>(f: F) {
- f();
+fn __rust_begin_short_backtrace<T, F: FnOnce() -> T>(f: F) -> T {
+ let result = f();
// prevent this frame from being tail-call optimised away
- black_box(());
+ black_box(result)
}
fn run_test_in_process(
@@ -580,7 +607,7 @@ fn run_test_in_process(
desc: TestDesc,
nocapture: bool,
report_time: bool,
- testfn: Box<dyn FnOnce() + Send>,
+ testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
monitor_ch: Sender<CompletedTest>,
time_opts: Option<time::TestTimeOptions>,
) {
@@ -592,7 +619,7 @@ fn run_test_in_process(
}
let start = report_time.then(Instant::now);
- let result = catch_unwind(AssertUnwindSafe(testfn));
+ let result = fold_err(catch_unwind(AssertUnwindSafe(testfn)));
let exec_time = start.map(|start| {
let duration = start.elapsed();
TestExecTime(duration)
@@ -609,6 +636,19 @@ fn run_test_in_process(
monitor_ch.send(message).unwrap();
}
+fn fold_err<T, E>(
+ result: Result<Result<T, E>, Box<dyn Any + Send>>,
+) -> Result<T, Box<dyn Any + Send>>
+where
+ E: Send + 'static,
+{
+ match result {
+ Ok(Err(e)) => Err(Box::new(e)),
+ Ok(Ok(v)) => Ok(v),
+ Err(e) => Err(e),
+ }
+}
+
fn spawn_test_subprocess(
id: TestId,
desc: TestDesc,
@@ -664,7 +704,10 @@ fn spawn_test_subprocess(
monitor_ch.send(message).unwrap();
}
-fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box<dyn FnOnce() + Send>) -> ! {
+fn run_test_in_spawned_subprocess(
+ desc: TestDesc,
+ testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
+) -> ! {
let builtin_panic_hook = panic::take_hook();
let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
let test_result = match panic_info {
@@ -690,7 +733,9 @@ fn run_test_in_spawned_subprocess(desc: TestDesc, testfn: Box<dyn FnOnce() + Sen
});
let record_result2 = record_result.clone();
panic::set_hook(Box::new(move |info| record_result2(Some(&info))));
- testfn();
+ if let Err(message) = testfn() {
+ panic!("{}", message);
+ }
record_result(None);
unreachable!("panic=abort callback should have exited the process")
}
diff --git a/library/test/src/term.rs b/library/test/src/term.rs
index b256ab7b8..a14b0d4f5 100644
--- a/library/test/src/term.rs
+++ b/library/test/src/term.rs
@@ -39,7 +39,7 @@ pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
pub(crate) fn stdout() -> Option<Box<StdoutTerminal>> {
TerminfoTerminal::new(io::stdout())
.map(|t| Box::new(t) as Box<StdoutTerminal>)
- .or_else(|| WinConsole::new(io::stdout()).ok().map(|t| Box::new(t) as Box<StdoutTerminal>))
+ .or_else(|| Some(Box::new(WinConsole::new(io::stdout())) as Box<StdoutTerminal>))
}
/// Terminal color definitions
diff --git a/library/test/src/term/win.rs b/library/test/src/term/win.rs
index 4bdbd6ee7..55020141a 100644
--- a/library/test/src/term/win.rs
+++ b/library/test/src/term/win.rs
@@ -113,8 +113,7 @@ impl<T: Write + Send + 'static> WinConsole<T> {
}
}
- /// Returns `None` whenever the terminal cannot be created for some reason.
- pub(crate) fn new(out: T) -> io::Result<WinConsole<T>> {
+ pub(crate) fn new(out: T) -> WinConsole<T> {
use std::mem::MaybeUninit;
let fg;
@@ -132,13 +131,13 @@ impl<T: Write + Send + 'static> WinConsole<T> {
bg = color::BLACK;
}
}
- Ok(WinConsole {
+ WinConsole {
buf: out,
def_foreground: fg,
def_background: bg,
foreground: fg,
background: bg,
- })
+ }
}
}
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 0b81aff59..b54be64ef 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -67,7 +67,7 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
no_run: false,
test_type: TestType::Unknown,
},
- testfn: DynTestFn(Box::new(move || {})),
+ testfn: DynTestFn(Box::new(move || Ok(()))),
},
TestDescAndFn {
desc: TestDesc {
@@ -79,14 +79,14 @@ fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
no_run: false,
test_type: TestType::Unknown,
},
- testfn: DynTestFn(Box::new(move || {})),
+ testfn: DynTestFn(Box::new(move || Ok(()))),
},
]
}
#[test]
pub fn do_not_run_ignored_tests() {
- fn f() {
+ fn f() -> Result<(), String> {
panic!();
}
let desc = TestDescAndFn {
@@ -109,7 +109,9 @@ pub fn do_not_run_ignored_tests() {
#[test]
pub fn ignored_tests_result_in_ignored() {
- fn f() {}
+ fn f() -> Result<(), String> {
+ Ok(())
+ }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
@@ -132,7 +134,7 @@ pub fn ignored_tests_result_in_ignored() {
#[test]
#[cfg(not(target_os = "emscripten"))]
fn test_should_panic() {
- fn f() {
+ fn f() -> Result<(), String> {
panic!();
}
let desc = TestDescAndFn {
@@ -157,7 +159,7 @@ fn test_should_panic() {
#[test]
#[cfg(not(target_os = "emscripten"))]
fn test_should_panic_good_message() {
- fn f() {
+ fn f() -> Result<(), String> {
panic!("an error message");
}
let desc = TestDescAndFn {
@@ -183,7 +185,7 @@ fn test_should_panic_good_message() {
#[cfg(not(target_os = "emscripten"))]
fn test_should_panic_bad_message() {
use crate::tests::TrFailedMsg;
- fn f() {
+ fn f() -> Result<(), String> {
panic!("an error message");
}
let expected = "foobar";
@@ -214,7 +216,7 @@ fn test_should_panic_bad_message() {
fn test_should_panic_non_string_message_type() {
use crate::tests::TrFailedMsg;
use std::any::TypeId;
- fn f() {
+ fn f() -> Result<(), String> {
std::panic::panic_any(1i32);
}
let expected = "foobar";
@@ -249,7 +251,9 @@ fn test_should_panic_but_succeeds() {
let should_panic_variants = [ShouldPanic::Yes, ShouldPanic::YesWithMessage("error message")];
for &should_panic in should_panic_variants.iter() {
- fn f() {}
+ fn f() -> Result<(), String> {
+ Ok(())
+ }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
@@ -283,7 +287,9 @@ fn test_should_panic_but_succeeds() {
}
fn report_time_test_template(report_time: bool) -> Option<TestExecTime> {
- fn f() {}
+ fn f() -> Result<(), String> {
+ Ok(())
+ }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
@@ -318,7 +324,9 @@ fn test_should_report_time() {
}
fn time_test_failure_template(test_type: TestType) -> TestResult {
- fn f() {}
+ fn f() -> Result<(), String> {
+ Ok(())
+ }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
@@ -480,7 +488,7 @@ pub fn exclude_should_panic_option() {
no_run: false,
test_type: TestType::Unknown,
},
- testfn: DynTestFn(Box::new(move || {})),
+ testfn: DynTestFn(Box::new(move || Ok(()))),
});
let filtered = filter_tests(&opts, tests);
@@ -504,7 +512,7 @@ pub fn exact_filter_match() {
no_run: false,
test_type: TestType::Unknown,
},
- testfn: DynTestFn(Box::new(move || {})),
+ testfn: DynTestFn(Box::new(move || Ok(()))),
})
.collect()
}
@@ -580,7 +588,9 @@ fn sample_tests() -> Vec<TestDescAndFn> {
"test::run_include_ignored_option".to_string(),
"test::sort_tests".to_string(),
];
- fn testfn() {}
+ fn testfn() -> Result<(), String> {
+ Ok(())
+ }
let mut tests = Vec::new();
for name in &names {
let test = TestDescAndFn {
@@ -601,33 +611,6 @@ fn sample_tests() -> Vec<TestDescAndFn> {
}
#[test]
-pub fn sort_tests() {
- let mut opts = TestOpts::new();
- opts.run_tests = true;
-
- let tests = sample_tests();
- let filtered = filter_tests(&opts, tests);
-
- let expected = vec![
- "isize::test_pow".to_string(),
- "isize::test_to_str".to_string(),
- "sha1::test".to_string(),
- "test::do_not_run_ignored_tests".to_string(),
- "test::filter_for_ignored_option".to_string(),
- "test::first_free_arg_should_be_a_filter".to_string(),
- "test::ignored_tests_result_in_ignored".to_string(),
- "test::parse_ignored_flag".to_string(),
- "test::parse_include_ignored_flag".to_string(),
- "test::run_include_ignored_option".to_string(),
- "test::sort_tests".to_string(),
- ];
-
- for (a, b) in expected.iter().zip(filtered) {
- assert_eq!(*a, b.desc.name.to_string());
- }
-}
-
-#[test]
pub fn shuffle_tests() {
let mut opts = TestOpts::new();
opts.shuffle = true;
@@ -717,21 +700,26 @@ pub fn test_metricmap_compare() {
#[test]
pub fn test_bench_once_no_iter() {
- fn f(_: &mut Bencher) {}
- bench::run_once(f);
+ fn f(_: &mut Bencher) -> Result<(), String> {
+ Ok(())
+ }
+ bench::run_once(f).unwrap();
}
#[test]
pub fn test_bench_once_iter() {
- fn f(b: &mut Bencher) {
- b.iter(|| {})
+ fn f(b: &mut Bencher) -> Result<(), String> {
+ b.iter(|| {});
+ Ok(())
}
- bench::run_once(f);
+ bench::run_once(f).unwrap();
}
#[test]
pub fn test_bench_no_iter() {
- fn f(_: &mut Bencher) {}
+ fn f(_: &mut Bencher) -> Result<(), String> {
+ Ok(())
+ }
let (tx, rx) = channel();
@@ -751,8 +739,9 @@ pub fn test_bench_no_iter() {
#[test]
pub fn test_bench_iter() {
- fn f(b: &mut Bencher) {
- b.iter(|| {})
+ fn f(b: &mut Bencher) -> Result<(), String> {
+ b.iter(|| {});
+ Ok(())
}
let (tx, rx) = channel();
@@ -821,3 +810,33 @@ fn should_sort_failures_before_printing_them() {
let bpos = s.find("b").unwrap();
assert!(apos < bpos);
}
+
+#[test]
+#[cfg(not(target_os = "emscripten"))]
+fn test_dyn_bench_returning_err_fails_when_run_as_test() {
+ fn f(_: &mut Bencher) -> Result<(), String> {
+ Result::Err("An error".into())
+ }
+ let desc = TestDescAndFn {
+ desc: TestDesc {
+ name: StaticTestName("whatever"),
+ ignore: false,
+ ignore_message: None,
+ should_panic: ShouldPanic::No,
+ compile_fail: false,
+ no_run: false,
+ test_type: TestType::Unknown,
+ },
+ testfn: DynBenchFn(Box::new(f)),
+ };
+ let (tx, rx) = channel();
+ let notify = move |event: TestEvent| {
+ if let TestEvent::TeResult(result) = event {
+ tx.send(result).unwrap();
+ }
+ Ok(())
+ };
+ run_tests(&TestOpts { run_tests: true, ..TestOpts::new() }, vec![desc], notify).unwrap();
+ let result = rx.recv().unwrap().result;
+ assert_eq!(result, TrFailed);
+}
diff --git a/library/test/src/types.rs b/library/test/src/types.rs
index ffb1efe18..888afff79 100644
--- a/library/test/src/types.rs
+++ b/library/test/src/types.rs
@@ -75,14 +75,15 @@ impl fmt::Display for TestName {
}
// A function that runs a test. If the function returns successfully,
-// the test succeeds; if the function panics then the test fails. We
-// may need to come up with a more clever definition of test in order
-// to support isolation of tests into threads.
+// the test succeeds; if the function panics or returns Result::Err
+// then the test fails. We may need to come up with a more clever
+// definition of test in order to support isolation of tests into
+// threads.
pub enum TestFn {
- StaticTestFn(fn()),
- StaticBenchFn(fn(&mut Bencher)),
- DynTestFn(Box<dyn FnOnce() + Send>),
- DynBenchFn(Box<dyn Fn(&mut Bencher) + Send>),
+ StaticTestFn(fn() -> Result<(), String>),
+ StaticBenchFn(fn(&mut Bencher) -> Result<(), String>),
+ DynTestFn(Box<dyn FnOnce() -> Result<(), String> + Send>),
+ DynBenchFn(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
}
impl TestFn {
diff --git a/src/README.md b/src/README.md
index 3d2e6acd5..90ab80269 100644
--- a/src/README.md
+++ b/src/README.md
@@ -2,7 +2,7 @@ This directory contains the source code of the rust project, including:
- The test suite
- The bootstrapping build system
-- Various submodules for tools, like cargo, miri, etc.
+- Various submodules for tools, like cargo, etc.
For more information on how various parts of the compiler work, see the [rustc dev guide].
diff --git a/src/bootstrap/CHANGELOG.md b/src/bootstrap/CHANGELOG.md
index 85afc1f5f..64b74ecc9 100644
--- a/src/bootstrap/CHANGELOG.md
+++ b/src/bootstrap/CHANGELOG.md
@@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Change the names for `dist` commands to match the component they generate. [#90684](https://github.com/rust-lang/rust/pull/90684)
- The `build.fast-submodules` option has been removed. Fast submodule checkouts are enabled unconditionally. Automatic submodule handling can still be disabled with `build.submodules = false`.
- Several unsupported `./configure` options have been removed: `optimize`, `parallel-compiler`. These can still be enabled with `--set`, although it isn't recommended.
+- `remote-test-server`'s `verbose` argument has been removed in favor of the `--verbose` flag
+- `remote-test-server`'s `remote` argument has been removed in favor of the `--bind` flag. Use `--bind 0.0.0.0:12345` to replicate the behavior of the `remote` argument.
### Non-breaking changes
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 84c06fdce..baecca44c 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -445,9 +445,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.39"
+version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
+checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
"unicode-ident",
]
@@ -596,9 +596,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.95"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index a2e596bf4..985727bdd 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -1,7 +1,7 @@
# rustbuild - Bootstrapping Rust
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
+is bootstrapped and in general, some of the technical details of the build
system.
## Using rustbuild
@@ -12,7 +12,7 @@ The rustbuild build system has a primary entry point, a top level `x.py` script:
$ python ./x.py build
```
-Note that if you're on Unix you should be able to execute the script directly:
+Note that if you're on Unix, you should be able to execute the script directly:
```sh
$ ./x.py build
@@ -20,8 +20,8 @@ $ ./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` - a general purpose command for compiling code. Alone, `build` will
+ bootstrap the entire compiler, and otherwise, arguments passed indicate what to
build. For example:
```
@@ -38,7 +38,7 @@ The script accepts commands, flags, and arguments to determine what to do:
./x.py build --stage 0 library/test
```
- If files are dirty that would normally be rebuilt from stage 0, that can be
+ 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:
@@ -47,8 +47,8 @@ The script accepts commands, flags, and arguments to determine what to do:
./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
+* `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:
```
@@ -75,7 +75,7 @@ The script accepts commands, flags, and arguments to determine what to do:
./x.py test src/doc
```
-* `doc` - a command for building documentation. Like above can take arguments
+* `doc` - a command for building documentation. Like above, can take arguments
for what to document.
## Configuring rustbuild
@@ -110,12 +110,12 @@ compiler. What actually happens when you invoke rustbuild is:
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 (compilers exist for example), and then start building the
+ sanity checks (whether compilers exist, for example), and then start building the
stage0 artifacts.
-3. The stage0 `cargo` downloaded earlier is used to build the standard library
+3. The stage0 `cargo`, downloaded earlier, is used to build the standard library
and the compiler, and then these binaries are then copied to the `stage1`
directory. That compiler is then used to generate the stage1 artifacts which
- are then copied to the stage2 directory, and then finally the stage2
+ are then copied to the stage2 directory, and then finally, the stage2
artifacts are generated using that compiler.
The goal of each stage is to (a) leverage Cargo as much as possible and failing
@@ -149,7 +149,7 @@ like this:
build/
# Location where the stage0 compiler downloads are all cached. This directory
- # only contains the tarballs themselves as they're extracted elsewhere.
+ # only contains the tarballs themselves, as they're extracted elsewhere.
cache/
2015-12-19/
2016-01-15/
@@ -172,10 +172,10 @@ build/
# hand.
x86_64-unknown-linux-gnu/
- # The build artifacts for the `compiler-rt` library for the target this
- # folder is under. The exact layout here will likely depend on the platform,
- # and this is also built with CMake so the build system is also likely
- # different.
+ # The build artifacts for the `compiler-rt` library for the target that
+ # this folder is under. The exact layout here will likely depend on the
+ # platform, and this is also built with CMake, so the build system is
+ # also likely different.
compiler-rt/
build/
@@ -183,11 +183,11 @@ build/
llvm/
# build folder (e.g. the platform-specific build system). Like with
- # compiler-rt this is compiled with CMake
+ # compiler-rt, this is compiled with CMake
build/
# Installation of LLVM. Note that we run the equivalent of 'make install'
- # for LLVM to setup these folders.
+ # for LLVM, to setup these folders.
bin/
lib/
include/
@@ -206,18 +206,18 @@ build/
# Location where the stage0 Cargo and Rust compiler are unpacked. This
# directory is purely an extracted and overlaid tarball of these two (done
- # by the bootstrapy python script). In theory the build system does not
+ # by the bootstrap python script). In theory, the build system does not
# modify anything under this directory afterwards.
stage0/
- # These to build directories are the cargo output directories for builds of
- # the standard library and compiler, respectively. Internally these may also
+ # These to-build directories are the cargo output directories for builds of
+ # the standard library and compiler, respectively. Internally, these may also
# have other target directories, which represent artifacts being compiled
# from the host to the specified target.
#
# Essentially, each of these directories is filled in by one `cargo`
# invocation. The build system instruments calling Cargo in the right order
- # with the right variables to ensure these are filled in correctly.
+ # with the right variables to ensure that these are filled in correctly.
stageN-std/
stageN-test/
stageN-rustc/
@@ -232,8 +232,8 @@ build/
# being compiled (e.g. after libstd has been built), *this* is used as the
# sysroot for the stage0 compiler being run.
#
- # Basically this directory is just a temporary artifact use to configure the
- # stage0 compiler to ensure that the libstd we just built is used to
+ # Basically, this directory is just a temporary artifact used to configure the
+ # stage0 compiler to ensure that the libstd that we just built is used to
# compile the stage1 compiler.
stage0-sysroot/lib/
@@ -242,7 +242,7 @@ 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, there is no extra build output in these directories.
stage1/
stage2/
stage3/
@@ -265,14 +265,14 @@ structure here serves two goals:
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
+ 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!
+parallel with a number of rustc artifacts, but in theory, the loss isn't too bad!
## Build tools
@@ -285,13 +285,13 @@ 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.
+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.
+excessively confusing, please open an issue on this, and we'll try to get it
+documented or simplified, pronto.
-First up, you'll probably want to read over the documentation above as that'll
+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.
@@ -326,7 +326,7 @@ 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
+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.
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index e96f8b0d3..776d73b98 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -67,7 +67,7 @@ fn main() {
if target == "all"
|| target.into_string().unwrap().split(',').any(|c| c.trim() == crate_name)
{
- cmd.arg("-Ztime");
+ cmd.arg("-Ztime-passes");
}
}
}
diff --git a/src/bootstrap/bolt.rs b/src/bootstrap/bolt.rs
new file mode 100644
index 000000000..ea37cd470
--- /dev/null
+++ b/src/bootstrap/bolt.rs
@@ -0,0 +1,71 @@
+use std::path::Path;
+use std::process::Command;
+
+/// Uses the `llvm-bolt` binary to instrument the binary/library at the given `path` with BOLT.
+/// When the instrumented artifact is executed, it will generate BOLT profiles into
+/// `/tmp/prof.fdata.<pid>.fdata`.
+pub fn instrument_with_bolt_inplace(path: &Path) {
+ let dir = std::env::temp_dir();
+ let instrumented_path = dir.join("instrumented.so");
+
+ let status = Command::new("llvm-bolt")
+ .arg("-instrument")
+ .arg(&path)
+ // Make sure that each process will write its profiles into a separate file
+ .arg("--instrumentation-file-append-pid")
+ .arg("-o")
+ .arg(&instrumented_path)
+ .status()
+ .expect("Could not instrument artifact using BOLT");
+
+ if !status.success() {
+ panic!("Could not instrument {} with BOLT, exit code {:?}", path.display(), status.code());
+ }
+
+ std::fs::copy(&instrumented_path, path).expect("Cannot copy instrumented artifact");
+ std::fs::remove_file(instrumented_path).expect("Cannot delete instrumented artifact");
+}
+
+/// Uses the `llvm-bolt` binary to optimize the binary/library at the given `path` with BOLT,
+/// using merged profiles from `profile_path`.
+///
+/// The recorded profiles have to be merged using the `merge-fdata` tool from LLVM and the merged
+/// profile path should be then passed to this function.
+pub fn optimize_library_with_bolt_inplace(path: &Path, profile_path: &Path) {
+ let dir = std::env::temp_dir();
+ let optimized_path = dir.join("optimized.so");
+
+ let status = Command::new("llvm-bolt")
+ .arg(&path)
+ .arg("-data")
+ .arg(&profile_path)
+ .arg("-o")
+ .arg(&optimized_path)
+ // Reorder basic blocks within functions
+ .arg("-reorder-blocks=ext-tsp")
+ // Reorder functions within the binary
+ .arg("-reorder-functions=hfsort+")
+ // Split function code into hot and code regions
+ .arg("-split-functions=2")
+ // Split as many basic blocks as possible
+ .arg("-split-all-cold")
+ // Move jump tables to a separate section
+ .arg("-jump-tables=move")
+ // Use GNU_STACK program header for new segment (workaround for issues with strip/objcopy)
+ .arg("-use-gnu-stack")
+ // Fold functions with identical code
+ .arg("-icf=1")
+ // Update DWARF debug info in the final binary
+ .arg("-update-debug-sections")
+ // Print optimization statistics
+ .arg("-dyno-stats")
+ .status()
+ .expect("Could not optimize artifact using BOLT");
+
+ if !status.success() {
+ panic!("Could not optimize {} with BOLT, exit code {:?}", path.display(), status.code());
+ }
+
+ std::fs::copy(&optimized_path, path).expect("Cannot copy optimized artifact");
+ std::fs::remove_file(optimized_path).expect("Cannot delete optimized artifact");
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index cc08ae5f9..57128685d 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -732,9 +732,19 @@ class RustBuild(object):
(os.pathsep + env["LIBRARY_PATH"]) \
if "LIBRARY_PATH" in env else ""
+ # Export Stage0 snapshot compiler related env variables
+ build_section = "target.{}".format(self.build)
+ host_triple_sanitized = self.build.replace("-", "_")
+ var_data = {
+ "CC": "cc", "CXX": "cxx", "LD": "linker", "AR": "ar", "RANLIB": "ranlib"
+ }
+ for var_name, toml_key in var_data.items():
+ toml_val = self.get_toml(toml_key, build_section)
+ if toml_val != None:
+ env["{}_{}".format(var_name, host_triple_sanitized)] = toml_val
+
# preserve existing RUSTFLAGS
env.setdefault("RUSTFLAGS", "")
- build_section = "target.{}".format(self.build)
target_features = []
if self.get_toml("crt-static", build_section) == "true":
target_features += ["+crt-static"]
@@ -742,9 +752,6 @@ class RustBuild(object):
target_features += ["-crt-static"]
if target_features:
env["RUSTFLAGS"] += " -C target-feature=" + (",".join(target_features))
- target_linker = self.get_toml("linker", build_section)
- 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":
@@ -771,7 +778,8 @@ class RustBuild(object):
elif color == "never":
args.append("--color=never")
- run(args, env=env, verbose=self.verbose)
+ # Run this from the source directory so cargo finds .cargo/config
+ run(args, env=env, verbose=self.verbose, cwd=self.rust_root)
def build_triple(self):
"""Build triple as in LLVM
diff --git a/src/bootstrap/build.rs b/src/bootstrap/build.rs
index ab34d5c1e..cd1f41802 100644
--- a/src/bootstrap/build.rs
+++ b/src/bootstrap/build.rs
@@ -1,43 +1,7 @@
-use env::consts::{EXE_EXTENSION, EXE_SUFFIX};
use std::env;
-use std::ffi::OsString;
-use std::path::PathBuf;
-
-/// Given an executable called `name`, return the filename for the
-/// executable for a particular target.
-pub fn exe(name: &PathBuf) -> PathBuf {
- if EXE_EXTENSION != "" && name.extension() != Some(EXE_EXTENSION.as_ref()) {
- let mut name: OsString = name.clone().into();
- name.push(EXE_SUFFIX);
- name.into()
- } else {
- name.clone()
- }
-}
fn main() {
let host = env::var("HOST").unwrap();
println!("cargo:rerun-if-changed=build.rs");
- println!("cargo:rerun-if-env-changed=RUSTC");
println!("cargo:rustc-env=BUILD_TRIPLE={}", host);
-
- // This may not be a canonicalized path.
- let mut rustc = PathBuf::from(env::var_os("RUSTC").unwrap());
-
- if rustc.is_relative() {
- println!("cargo:rerun-if-env-changed=PATH");
- for dir in env::split_paths(&env::var_os("PATH").unwrap_or_default()) {
- let absolute = dir.join(&exe(&rustc));
- if absolute.exists() {
- rustc = absolute;
- break;
- }
- }
- }
- assert!(rustc.is_absolute());
-
- // FIXME: if the path is not utf-8, this is going to break. Unfortunately
- // Cargo doesn't have a way for us to specify non-utf-8 paths easily, so
- // we'll need to invent some encoding scheme if this becomes a problem.
- println!("cargo:rustc-env=RUSTC={}", rustc.to_str().unwrap());
}
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 14e8ebd68..8b144f146 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -704,10 +704,12 @@ impl<'a> Builder<'a> {
doc::Miri,
doc::EmbeddedBook,
doc::EditionGuide,
+ doc::StyleGuide,
),
Kind::Dist => describe!(
dist::Docs,
dist::RustcDocs,
+ dist::JsonDocs,
dist::Mingw,
dist::Rustc,
dist::Std,
@@ -723,6 +725,7 @@ impl<'a> Builder<'a> {
dist::Miri,
dist::LlvmTools,
dist::RustDev,
+ dist::Bootstrap,
dist::Extended,
// It seems that PlainSourceTarball somehow changes how some of the tools
// perceive their dependencies (see #93033) which would invalidate fingerprints
@@ -1325,6 +1328,9 @@ impl<'a> Builder<'a> {
) -> Cargo {
let mut cargo = Command::new(&self.initial_cargo);
let out_dir = self.stage_out(compiler, mode);
+ // Run cargo from the source root so it can find .cargo/config.
+ // This matters when using vendoring and the working directory is outside the repository.
+ cargo.current_dir(&self.src);
// Codegen backends are not yet tracked by -Zbinary-dep-depinfo,
// so we need to explicitly clear out if they've been updated.
@@ -1552,13 +1558,12 @@ impl<'a> Builder<'a> {
match mode {
Mode::ToolBootstrap => {
// Restrict the allowed features to those passed by rustbuild, so we don't depend on nightly accidentally.
- // HACK: because anyhow does feature detection in build.rs, we need to allow the backtrace feature too.
- rustflags.arg("-Zallow-features=binary-dep-depinfo,backtrace");
+ rustflags.arg("-Zallow-features=binary-dep-depinfo");
}
Mode::ToolStd => {
// Right now this is just compiletest and a few other tools that build on stable.
// Allow them to use `feature(test)`, but nothing else.
- rustflags.arg("-Zallow-features=binary-dep-depinfo,test,backtrace,proc_macro_internals,proc_macro_diagnostic,proc_macro_span");
+ rustflags.arg("-Zallow-features=binary-dep-depinfo,test,proc_macro_internals,proc_macro_diagnostic,proc_macro_span");
}
Mode::Std | Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {}
}
@@ -1940,25 +1945,26 @@ impl<'a> Builder<'a> {
_ => s.display().to_string(),
}
};
+ let triple_underscored = target.triple.replace("-", "_");
let cc = ccacheify(&self.cc(target));
- cargo.env(format!("CC_{}", target.triple), &cc);
+ cargo.env(format!("CC_{}", triple_underscored), &cc);
let cflags = self.cflags(target, GitRepo::Rustc, CLang::C).join(" ");
- cargo.env(format!("CFLAGS_{}", target.triple), &cflags);
+ cargo.env(format!("CFLAGS_{}", triple_underscored), &cflags);
if let Some(ar) = self.ar(target) {
let ranlib = format!("{} s", ar.display());
cargo
- .env(format!("AR_{}", target.triple), ar)
- .env(format!("RANLIB_{}", target.triple), ranlib);
+ .env(format!("AR_{}", triple_underscored), ar)
+ .env(format!("RANLIB_{}", triple_underscored), ranlib);
}
if let Ok(cxx) = self.cxx(target) {
let cxx = ccacheify(&cxx);
let cxxflags = self.cflags(target, GitRepo::Rustc, CLang::Cxx).join(" ");
cargo
- .env(format!("CXX_{}", target.triple), &cxx)
- .env(format!("CXXFLAGS_{}", target.triple), cxxflags);
+ .env(format!("CXX_{}", triple_underscored), &cxx)
+ .env(format!("CXXFLAGS_{}", triple_underscored), cxxflags);
}
}
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 280eba75f..88bbcc93d 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -236,7 +236,7 @@ mod defaults {
fn doc_default() {
let mut config = configure("doc", &["A"], &["A"]);
config.compiler_docs = true;
- config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+ config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
let mut cache = run_build(&[], config);
let a = TargetSelection::from_user("A");
@@ -587,7 +587,7 @@ mod dist {
fn doc_ci() {
let mut config = configure(&["A"], &["A"]);
config.compiler_docs = true;
- config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
+ config.cmd = Subcommand::Doc { paths: Vec::new(), open: false, json: false };
let build = Build::new(config);
let mut builder = Builder::new(&build);
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 1932a0017..258352a21 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -5,10 +5,12 @@
//! `package_vers`, and otherwise indicating to the compiler what it should
//! print out as part of its version information.
+use std::fs;
use std::path::Path;
use std::process::Command;
use crate::util::output;
+use crate::util::t;
use crate::Build;
pub enum GitInfo {
@@ -18,19 +20,25 @@ pub enum GitInfo {
/// If the info should be used (`ignore_git` is false), this will be
/// `Some`, otherwise it will be `None`.
Present(Option<Info>),
+ /// This is not a git repostory, but the info can be fetched from the
+ /// `git-commit-info` file.
+ RecordedForTarball(Info),
}
pub struct Info {
- commit_date: String,
- sha: String,
- short_sha: String,
+ pub commit_date: String,
+ pub sha: String,
+ pub short_sha: String,
}
impl GitInfo {
pub fn new(ignore_git: bool, dir: &Path) -> GitInfo {
// See if this even begins to look like a git dir
if !dir.join(".git").exists() {
- return GitInfo::Absent;
+ match read_commit_info_file(dir) {
+ Some(info) => return GitInfo::RecordedForTarball(info),
+ None => return GitInfo::Absent,
+ }
}
// Make sure git commands work
@@ -65,10 +73,11 @@ impl GitInfo {
}))
}
- fn info(&self) -> Option<&Info> {
+ pub fn info(&self) -> Option<&Info> {
match self {
- GitInfo::Present(info) => info.as_ref(),
GitInfo::Absent => None,
+ GitInfo::Present(info) => info.as_ref(),
+ GitInfo::RecordedForTarball(info) => Some(info),
}
}
@@ -96,10 +105,53 @@ impl GitInfo {
version
}
- pub fn is_git(&self) -> bool {
+ /// Returns whether this directory has a `.git` directory which should be managed by bootstrap.
+ pub fn is_managed_git_subrepository(&self) -> bool {
match self {
- GitInfo::Absent => false,
+ GitInfo::Absent | GitInfo::RecordedForTarball(_) => false,
GitInfo::Present(_) => true,
}
}
+
+ /// Returns whether this is being built from a tarball.
+ pub fn is_from_tarball(&self) -> bool {
+ match self {
+ GitInfo::Absent | GitInfo::Present(_) => false,
+ GitInfo::RecordedForTarball(_) => true,
+ }
+ }
+}
+
+/// Read the commit information from the `git-commit-info` file given the
+/// project root.
+pub fn read_commit_info_file(root: &Path) -> Option<Info> {
+ if let Ok(contents) = fs::read_to_string(root.join("git-commit-info")) {
+ let mut lines = contents.lines();
+ let sha = lines.next();
+ let short_sha = lines.next();
+ let commit_date = lines.next();
+ let info = match (commit_date, sha, short_sha) {
+ (Some(commit_date), Some(sha), Some(short_sha)) => Info {
+ commit_date: commit_date.to_owned(),
+ sha: sha.to_owned(),
+ short_sha: short_sha.to_owned(),
+ },
+ _ => panic!("the `git-comit-info` file is malformed"),
+ };
+ Some(info)
+ } else {
+ None
+ }
+}
+
+/// Write the commit information to the `git-commit-info` file given the project
+/// root.
+pub fn write_commit_info_file(root: &Path, info: &Info) {
+ let commit_info = format!("{}\n{}\n{}\n", info.sha, info.short_sha, info.commit_date);
+ t!(fs::write(root.join("git-commit-info"), &commit_info));
+}
+
+/// Write the commit hash to the `git-commit-hash` file given the project root.
+pub fn write_commit_hash_file(root: &Path, sha: &str) {
+ t!(fs::write(root.join("git-commit-hash"), sha));
}
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index 5c085bedf..229851238 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -456,6 +456,8 @@ tool_check_step!(Rustdoc, "src/tools/rustdoc", "src/librustdoc", SourceType::InT
// behavior, treat it as in-tree so that any new warnings in clippy will be
// rejected.
tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);
+// Miri on the other hand is treated as out of tree, since InTree also causes it to
+// be run as part of `check`, which can fail on platforms which libffi-sys has no support for.
tool_check_step!(Miri, "src/tools/miri", SourceType::Submodule);
tool_check_step!(Rls, "src/tools/rls", SourceType::InTree);
tool_check_step!(Rustfmt, "src/tools/rustfmt", SourceType::InTree);
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index c13e83f6c..e02a10b81 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -21,7 +21,7 @@ use serde::Deserialize;
use crate::builder::Cargo;
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
-use crate::config::{LlvmLibunwind, TargetSelection};
+use crate::config::{LlvmLibunwind, RustcLto, TargetSelection};
use crate::dist;
use crate::native;
use crate::tool::SourceType;
@@ -299,9 +299,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// Determine if we're going to compile in optimized C intrinsics to
// the `compiler-builtins` crate. These intrinsics live in LLVM's
- // `compiler-rt` repository, but our `src/llvm-project` submodule isn't
- // always checked out, so we need to conditionally look for this. (e.g. if
- // an external LLVM is used we skip the LLVM submodule checkout).
+ // `compiler-rt` repository.
//
// Note that this shouldn't affect the correctness of `compiler-builtins`,
// but only its speed. Some intrinsics in C haven't been translated to Rust
@@ -312,8 +310,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// If `compiler-rt` is available ensure that the `c` feature of the
// `compiler-builtins` crate is enabled and it's configured to learn where
// `compiler-rt` is located.
- let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
- let compiler_builtins_c_feature = if compiler_builtins_root.exists() {
+ let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins {
+ if !builder.is_rust_llvm(target) {
+ panic!(
+ "need a managed LLVM submodule for optimized intrinsics support; unset `llvm-config` or `optimized-compiler-builtins`"
+ );
+ }
+
+ builder.update_submodule(&Path::new("src").join("llvm-project"));
+ let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
// Note that `libprofiler_builtins/build.rs` also computes this so if
// you're changing something here please also change that.
cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
@@ -459,7 +464,7 @@ fn copy_sanitizers(
builder.copy(&runtime.path, &dst);
if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" {
- // Update the library’s install name to reflect that it has has been renamed.
+ // 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,
// so we will sign it again.
@@ -696,6 +701,28 @@ impl Step for Rustc {
));
}
+ // cfg(bootstrap): remove if condition once the bootstrap compiler supports dylib LTO
+ if compiler.stage != 0 {
+ match builder.config.rust_lto {
+ RustcLto::Thin | RustcLto::Fat => {
+ // Since using LTO for optimizing dylibs is currently experimental,
+ // we need to pass -Zdylib-lto.
+ cargo.rustflag("-Zdylib-lto");
+ // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when
+ // compiling dylibs (and their dependencies), even when LTO is enabled for the
+ // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here.
+ let lto_type = match builder.config.rust_lto {
+ RustcLto::Thin => "thin",
+ RustcLto::Fat => "fat",
+ _ => unreachable!(),
+ };
+ cargo.rustflag(&format!("-Clto={}", lto_type));
+ cargo.rustflag("-Cembed-bitcode=yes");
+ }
+ RustcLto::ThinLocal => { /* Do nothing, this is the default */ }
+ }
+ }
+
builder.info(&format!(
"Building stage{} compiler artifacts ({} -> {})",
compiler.stage, &compiler.host, target
@@ -1099,10 +1126,13 @@ impl Step for Sysroot {
/// 1-3.
fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
let compiler = self.compiler;
+ let host_dir = builder.out.join(&compiler.host.triple);
let sysroot = if compiler.stage == 0 {
- builder.out.join(&compiler.host.triple).join("stage0-sysroot")
+ host_dir.join("stage0-sysroot")
+ } else if builder.download_rustc() {
+ host_dir.join("ci-rustc-sysroot")
} else {
- builder.out.join(&compiler.host.triple).join(format!("stage{}", compiler.stage))
+ host_dir.join(format!("stage{}", compiler.stage))
};
let _ = fs::remove_dir_all(&sysroot);
t!(fs::create_dir_all(&sysroot));
@@ -1113,6 +1143,11 @@ impl Step for Sysroot {
builder.config.build, compiler.host,
"Cross-compiling is not yet supported with `download-rustc`",
);
+
+ // #102002, cleanup stage1 and stage0-sysroot folders when using download-rustc so people don't use old versions of the toolchain by accident.
+ let _ = fs::remove_dir_all(host_dir.join("stage1"));
+ let _ = fs::remove_dir_all(host_dir.join("stage0-sysroot"));
+
// Copy the compiler into the correct sysroot.
let ci_rustc_dir =
builder.config.out.join(&*builder.config.build.triple).join("ci-rustc");
@@ -1142,6 +1177,20 @@ impl Step for Sysroot {
);
}
}
+ // Same for the rustc-src component.
+ let sysroot_lib_rustlib_rustcsrc = sysroot.join("lib/rustlib/rustc-src");
+ t!(fs::create_dir_all(&sysroot_lib_rustlib_rustcsrc));
+ let sysroot_lib_rustlib_rustcsrc_rust = sysroot_lib_rustlib_rustcsrc.join("rust");
+ if let Err(e) =
+ symlink_dir(&builder.config, &builder.src, &sysroot_lib_rustlib_rustcsrc_rust)
+ {
+ eprintln!(
+ "warning: creating symbolic link `{}` to `{}` failed with {}",
+ sysroot_lib_rustlib_rustcsrc_rust.display(),
+ builder.src.display(),
+ e,
+ );
+ }
INTERNER.intern_path(sysroot)
}
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index f1a150e0f..a8c403675 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -73,6 +73,8 @@ pub struct Config {
pub color: Color,
pub patch_binaries_for_nix: bool,
pub stage0_metadata: Stage0Metadata,
+ /// Whether to use the `c` feature of the `compiler_builtins` crate.
+ pub optimized_compiler_builtins: bool,
pub on_fail: Option<String>,
pub stage: u32,
@@ -156,9 +158,12 @@ pub struct Config {
pub rust_new_symbol_mangling: Option<bool>,
pub rust_profile_use: Option<String>,
pub rust_profile_generate: Option<String>,
+ pub rust_lto: RustcLto,
pub llvm_profile_use: Option<String>,
pub llvm_profile_generate: bool,
pub llvm_libunwind_default: Option<LlvmLibunwind>,
+ pub llvm_bolt_profile_generate: bool,
+ pub llvm_bolt_profile_use: Option<String>,
pub build: TargetSelection,
pub hosts: Vec<TargetSelection>,
@@ -315,6 +320,28 @@ impl SplitDebuginfo {
}
}
+/// LTO mode used for compiling rustc itself.
+#[derive(Default, Clone)]
+pub enum RustcLto {
+ #[default]
+ ThinLocal,
+ Thin,
+ Fat,
+}
+
+impl std::str::FromStr for RustcLto {
+ type Err = String;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "thin-local" => Ok(RustcLto::ThinLocal),
+ "thin" => Ok(RustcLto::Thin),
+ "fat" => Ok(RustcLto::Fat),
+ _ => Err(format!("Invalid value for rustc LTO: {}", s)),
+ }
+ }
+}
+
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TargetSelection {
pub triple: Interned<String>,
@@ -597,6 +624,7 @@ define_config! {
bench_stage: Option<u32> = "bench-stage",
patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix",
metrics: Option<bool> = "metrics",
+ optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
}
}
@@ -721,6 +749,7 @@ define_config! {
profile_use: Option<String> = "profile-use",
// ignored; this is set from an env var set by bootstrap.py
download_rustc: Option<StringOrBool> = "download-rustc",
+ lto: Option<String> = "lto",
}
}
@@ -772,21 +801,20 @@ impl Config {
// set by build.rs
config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
+
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
// Undo `src/bootstrap`
config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned();
config.out = PathBuf::from("build");
- config.initial_cargo = PathBuf::from(env!("CARGO"));
- config.initial_rustc = PathBuf::from(env!("RUSTC"));
-
config
}
pub fn parse(args: &[String]) -> Config {
let flags = Flags::parse(&args);
-
let mut config = Config::default_opts();
+
+ // Set flags.
config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect();
config.include_default_paths = flags.include_default_paths;
config.rustc_error_format = flags.rustc_error_format;
@@ -804,8 +832,68 @@ impl Config {
}
config.llvm_profile_use = flags.llvm_profile_use;
config.llvm_profile_generate = flags.llvm_profile_generate;
+ config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate;
+ config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use;
+
+ if config.llvm_bolt_profile_generate && config.llvm_bolt_profile_use.is_some() {
+ eprintln!(
+ "Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time"
+ );
+ crate::detail_exit(1);
+ }
+
+ // Infer the rest of the configuration.
+
+ // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary,
+ // running on a completely machine from where it was compiled.
+ let mut cmd = Command::new("git");
+ // NOTE: we cannot support running from outside the repository because the only path we have available
+ // is set at compile time, which can be wrong if bootstrap was downloaded from source.
+ // We still support running outside the repository if we find we aren't in a git directory.
+ cmd.arg("rev-parse").arg("--show-toplevel");
+ // Discard stderr because we expect this to fail when building from a tarball.
+ let output = cmd
+ .stderr(std::process::Stdio::null())
+ .output()
+ .ok()
+ .and_then(|output| if output.status.success() { Some(output) } else { None });
+ if let Some(output) = output {
+ let git_root = String::from_utf8(output.stdout).unwrap();
+ // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes.
+ let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap();
+ let s = git_root.to_str().unwrap();
+
+ // Bootstrap is quite bad at handling /? in front of paths
+ let src = match s.strip_prefix("\\\\?\\") {
+ Some(p) => PathBuf::from(p),
+ None => PathBuf::from(git_root),
+ };
+ // If this doesn't have at least `stage0.json`, we guessed wrong. This can happen when,
+ // for example, the build directory is inside of another unrelated git directory.
+ // In that case keep the original `CARGO_MANIFEST_DIR` handling.
+ //
+ // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside
+ // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1.
+ if src.join("src").join("stage0.json").exists() {
+ config.src = src;
+ }
+ } else {
+ // We're building from a tarball, not git sources.
+ // We don't support pre-downloaded bootstrap in this case.
+ }
+
+ if cfg!(test) {
+ // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly.
+ config.out = Path::new(
+ &env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"),
+ )
+ .parent()
+ .unwrap()
+ .to_path_buf();
+ }
let stage0_json = t!(std::fs::read(&config.src.join("src").join("stage0.json")));
+
config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
#[cfg(test)]
@@ -861,7 +949,6 @@ impl Config {
let build = toml.build.unwrap_or_default();
- set(&mut config.initial_rustc, build.rustc.map(PathBuf::from));
set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
// NOTE: Bootstrap spawns various commands with different working directories.
// To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
@@ -870,6 +957,16 @@ impl Config {
config.out = crate::util::absolute(&config.out);
}
+ config.initial_rustc = build
+ .rustc
+ .map(PathBuf::from)
+ .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc"));
+ config.initial_cargo = build
+ .cargo
+ .map(PathBuf::from)
+ .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/cargo"));
+
+ // NOTE: it's important this comes *after* we set `initial_rustc` just above.
if config.dry_run {
let dir = config.out.join("tmp-dry-run");
t!(fs::create_dir_all(&dir));
@@ -916,6 +1013,7 @@ impl Config {
set(&mut config.print_step_timings, build.print_step_timings);
set(&mut config.print_step_rusage, build.print_step_rusage);
set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix);
+ set(&mut config.optimized_compiler_builtins, build.optimized_compiler_builtins);
config.verbose = cmp::max(config.verbose, flags.verbose);
@@ -1099,6 +1197,12 @@ impl Config {
config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
config.download_rustc_commit = download_ci_rustc_commit(&config, rust.download_rustc);
+
+ config.rust_lto = rust
+ .lto
+ .as_deref()
+ .map(|value| RustcLto::from_str(value).unwrap())
+ .unwrap_or_default();
} else {
config.rust_profile_use = flags.rust_profile_use;
config.rust_profile_generate = flags.rust_profile_generate;
@@ -1280,20 +1384,21 @@ impl Config {
git
}
- pub(crate) fn artifact_version_part(&self, commit: &str) -> String {
- let mut channel = self.git();
- channel.arg("show").arg(format!("{}:src/ci/channel", commit));
- let channel = output(&mut channel);
-
- let mut version = self.git();
- version.arg("show").arg(format!("{}:src/version", commit));
- let version = output(&mut version);
-
- match channel.trim() {
- "stable" => version.trim().to_owned(),
- "beta" => channel.trim().to_owned(),
- "nightly" => channel.trim().to_owned(),
- other => unreachable!("{:?} is not recognized as a valid channel", other),
+ pub(crate) fn artifact_channel(&self, builder: &Builder<'_>, commit: &str) -> String {
+ if builder.rust_info.is_managed_git_subrepository() {
+ let mut channel = self.git();
+ channel.arg("show").arg(format!("{}:src/ci/channel", commit));
+ let channel = output(&mut channel);
+ channel.trim().to_owned()
+ } else if let Ok(channel) = fs::read_to_string(builder.src.join("src/ci/channel")) {
+ channel.trim().to_owned()
+ } else {
+ let src = builder.src.display();
+ eprintln!("error: failed to determine artifact channel");
+ eprintln!(
+ "help: either use git or ensure that {src}/src/ci/channel contains the name of the channel to use"
+ );
+ panic!();
}
}
@@ -1431,7 +1536,7 @@ impl Config {
}
pub fn submodules(&self, rust_info: &GitInfo) -> bool {
- self.submodules.unwrap_or(rust_info.is_git())
+ self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
}
}
@@ -1536,7 +1641,7 @@ fn maybe_download_rustfmt(builder: &Builder<'_>) -> Option<PathBuf> {
fn download_ci_rustc(builder: &Builder<'_>, commit: &str) {
builder.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
- let version = builder.config.artifact_version_part(commit);
+ let channel = builder.config.artifact_channel(builder, commit);
let host = builder.config.build.triple;
let bin_root = builder.out.join(host).join("ci-rustc");
let rustc_stamp = bin_root.join(".rustc-stamp");
@@ -1545,13 +1650,13 @@ fn download_ci_rustc(builder: &Builder<'_>, commit: &str) {
if bin_root.exists() {
t!(fs::remove_dir_all(&bin_root));
}
- let filename = format!("rust-std-{version}-{host}.tar.xz");
+ let filename = format!("rust-std-{channel}-{host}.tar.xz");
let pattern = format!("rust-std-{host}");
download_ci_component(builder, filename, &pattern, commit);
- let filename = format!("rustc-{version}-{host}.tar.xz");
+ let filename = format!("rustc-{channel}-{host}.tar.xz");
download_ci_component(builder, filename, "rustc", commit);
// download-rustc doesn't need its own cargo, it can just use beta's.
- let filename = format!("rustc-dev-{version}-{host}.tar.xz");
+ let filename = format!("rustc-dev-{channel}-{host}.tar.xz");
download_ci_component(builder, filename, "rustc-dev", commit);
builder.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 1a59b3958..12585e80e 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -16,6 +16,7 @@ use std::process::Command;
use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::{Interned, INTERNER};
+use crate::channel;
use crate::compile;
use crate::config::TargetSelection;
use crate::tarball::{GeneratedTarball, OverlayKind, Tarball};
@@ -35,18 +36,6 @@ pub fn tmpdir(builder: &Builder<'_>) -> PathBuf {
builder.out.join("tmp/dist")
}
-fn missing_tool(tool_name: &str, skip: bool) {
- if skip {
- println!("Unable to build {}, skipping dist", tool_name)
- } else {
- let help = "note: not all tools are available on all nightlies\nhelp: see https://forge.rust-lang.org/infra/toolstate.html for more information";
- panic!(
- "Unable to build submodule tool {} (use `missing-tools = true` to ignore this failure)\n{}",
- tool_name, help
- )
- }
-}
-
fn should_build_extended_tool(builder: &Builder<'_>, tool: &str) -> bool {
if !builder.config.extended {
return false;
@@ -87,6 +76,39 @@ impl Step for Docs {
}
}
+#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct JsonDocs {
+ pub host: TargetSelection,
+}
+
+impl Step for JsonDocs {
+ type Output = Option<GeneratedTarball>;
+ const DEFAULT: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ let default = run.builder.config.docs;
+ run.alias("rust-docs-json").default_condition(default)
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(JsonDocs { host: run.target });
+ }
+
+ /// Builds the `rust-docs-json` installer component.
+ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
+ let host = self.host;
+ builder.ensure(crate::doc::JsonStd { stage: builder.top_stage, target: host });
+
+ let dest = "share/doc/rust/json";
+
+ let mut tarball = Tarball::new(builder, "rust-docs-json", &host.triple);
+ tarball.set_product_name("Rust Documentation In JSON Format");
+ tarball.is_preview(true);
+ tarball.add_bulk_dir(&builder.json_doc_out(host), dest);
+ Some(tarball.generate())
+ }
+}
+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustcDocs {
pub host: TargetSelection,
@@ -897,12 +919,13 @@ impl Step for PlainSourceTarball {
// Create the version file
builder.create(&plain_dst_src.join("version"), &builder.rust_version());
- if let Some(sha) = builder.rust_sha() {
- builder.create(&plain_dst_src.join("git-commit-hash"), &sha);
+ if let Some(info) = builder.rust_info.info() {
+ channel::write_commit_hash_file(&plain_dst_src, &info.sha);
+ channel::write_commit_info_file(&plain_dst_src, info);
}
// If we're building from git sources, we need to vendor a complete distribution.
- if builder.rust_info.is_git() {
+ if builder.rust_info.is_managed_git_subrepository() {
// Ensure we have the submodules checked out.
builder.update_submodule(Path::new("src/tools/rust-analyzer"));
@@ -1170,18 +1193,9 @@ impl Step for Miri {
let compiler = self.compiler;
let target = self.target;
- let miri = builder
- .ensure(tool::Miri { compiler, target, extra_features: Vec::new() })
- .or_else(|| {
- missing_tool("miri", builder.build.config.missing_tools);
- None
- })?;
- let cargomiri = builder
- .ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })
- .or_else(|| {
- missing_tool("cargo miri", builder.build.config.missing_tools);
- None
- })?;
+ let miri = builder.ensure(tool::Miri { compiler, target, extra_features: Vec::new() })?;
+ let cargomiri =
+ builder.ensure(tool::CargoMiri { compiler, target, extra_features: Vec::new() })?;
let mut tarball = Tarball::new(builder, "miri", &target.triple);
tarball.set_overlay(OverlayKind::Miri);
@@ -1353,6 +1367,7 @@ impl Step for Extended {
}
add_component!("rust-docs" => Docs { host: target });
+ add_component!("rust-json-docs" => JsonDocs { host: target });
add_component!("rust-demangler"=> RustDemangler { compiler, target });
add_component!("cargo" => Cargo { compiler, target });
add_component!("rustfmt" => Rustfmt { compiler, target });
@@ -1412,7 +1427,7 @@ impl Step for Extended {
let xform = |p: &Path| {
let mut contents = t!(fs::read_to_string(p));
- for tool in &["rust-demangler", "rust-analyzer", "miri", "rustfmt"] {
+ for tool in &["rust-demangler", "miri"] {
if !built_tools.contains(tool) {
contents = filter(&contents, tool);
}
@@ -1452,7 +1467,8 @@ impl Step for Extended {
prepare("rust-std");
prepare("rust-analysis");
prepare("clippy");
- for tool in &["rust-docs", "rust-demangler", "rust-analyzer", "miri"] {
+ prepare("rust-analyzer");
+ for tool in &["rust-docs", "rust-demangler", "miri"] {
if built_tools.contains(tool) {
prepare(tool);
}
@@ -1511,7 +1527,8 @@ impl Step for Extended {
prepare("rust-docs");
prepare("rust-std");
prepare("clippy");
- for tool in &["rust-demangler", "rust-analyzer", "miri"] {
+ prepare("rust-analyzer");
+ for tool in &["rust-demangler", "miri"] {
if built_tools.contains(tool) {
prepare(tool);
}
@@ -1595,25 +1612,23 @@ impl Step for Extended {
.arg("-out")
.arg(exe.join("StdGroup.wxs")),
);
- if built_tools.contains("rust-analyzer") {
- builder.run(
- Command::new(&heat)
- .current_dir(&exe)
- .arg("dir")
- .arg("rust-analyzer")
- .args(&heat_flags)
- .arg("-cg")
- .arg("RustAnalyzerGroup")
- .arg("-dr")
- .arg("RustAnalyzer")
- .arg("-var")
- .arg("var.RustAnalyzerDir")
- .arg("-out")
- .arg(exe.join("RustAnalyzerGroup.wxs"))
- .arg("-t")
- .arg(etc.join("msi/remove-duplicates.xsl")),
- );
- }
+ builder.run(
+ Command::new(&heat)
+ .current_dir(&exe)
+ .arg("dir")
+ .arg("rust-analyzer")
+ .args(&heat_flags)
+ .arg("-cg")
+ .arg("RustAnalyzerGroup")
+ .arg("-dr")
+ .arg("RustAnalyzer")
+ .arg("-var")
+ .arg("var.RustAnalyzerDir")
+ .arg("-out")
+ .arg(exe.join("RustAnalyzerGroup.wxs"))
+ .arg("-t")
+ .arg(etc.join("msi/remove-duplicates.xsl")),
+ );
builder.run(
Command::new(&heat)
.current_dir(&exe)
@@ -1745,15 +1760,15 @@ impl Step for Extended {
candle("CargoGroup.wxs".as_ref());
candle("StdGroup.wxs".as_ref());
candle("ClippyGroup.wxs".as_ref());
+ if built_tools.contains("miri") {
+ candle("MiriGroup.wxs".as_ref());
+ }
if built_tools.contains("rust-demangler") {
candle("RustDemanglerGroup.wxs".as_ref());
}
if built_tools.contains("rust-analyzer") {
candle("RustAnalyzerGroup.wxs".as_ref());
}
- if built_tools.contains("miri") {
- candle("MiriGroup.wxs".as_ref());
- }
candle("AnalysisGroup.wxs".as_ref());
if target.ends_with("windows-gnu") {
@@ -1785,15 +1800,15 @@ impl Step for Extended {
.arg("ClippyGroup.wixobj")
.current_dir(&exe);
+ if built_tools.contains("miri") {
+ cmd.arg("MiriGroup.wixobj");
+ }
if built_tools.contains("rust-analyzer") {
cmd.arg("RustAnalyzerGroup.wixobj");
}
if built_tools.contains("rust-demangler") {
cmd.arg("RustDemanglerGroup.wixobj");
}
- if built_tools.contains("miri") {
- cmd.arg("MiriGroup.wixobj");
- }
if target.ends_with("windows-gnu") {
cmd.arg("GccGroup.wixobj");
@@ -1838,23 +1853,21 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
///
/// Returns whether the files were actually copied.
fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
- if let Some(config) = builder.config.target_config.get(&target) {
- if config.llvm_config.is_some() && !builder.config.llvm_from_ci {
- // If the LLVM was externally provided, then we don't currently copy
- // artifacts into the sysroot. This is not necessarily the right
- // choice (in particular, it will require the LLVM dylib to be in
- // the linker's load path at runtime), but the common use case for
- // external LLVMs is distribution provided LLVMs, and in that case
- // they're usually in the standard search path (e.g., /usr/lib) and
- // copying them here is going to cause problems as we may end up
- // with the wrong files and isn't what distributions want.
- //
- // This behavior may be revisited in the future though.
- //
- // If the LLVM is coming from ourselves (just from CI) though, we
- // still want to install it, as it otherwise won't be available.
- return false;
- }
+ if !builder.is_rust_llvm(target) {
+ // If the LLVM was externally provided, then we don't currently copy
+ // artifacts into the sysroot. This is not necessarily the right
+ // choice (in particular, it will require the LLVM dylib to be in
+ // the linker's load path at runtime), but the common use case for
+ // external LLVMs is distribution provided LLVMs, and in that case
+ // they're usually in the standard search path (e.g., /usr/lib) and
+ // copying them here is going to cause problems as we may end up
+ // with the wrong files and isn't what distributions want.
+ //
+ // This behavior may be revisited in the future though.
+ //
+ // If the LLVM is coming from ourselves (just from CI) though, we
+ // still want to install it, as it otherwise won't be available.
+ return false;
}
// On macOS, rustc (and LLVM tools) link to an unversioned libLLVM.dylib
@@ -1873,7 +1886,7 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir
let mut cmd = Command::new(llvm_config);
cmd.arg("--libfiles");
builder.verbose(&format!("running {:?}", cmd));
- let files = output(&mut cmd);
+ let files = if builder.config.dry_run { "".into() } else { output(&mut cmd) };
let build_llvm_out = &builder.llvm_out(builder.config.build);
let target_llvm_out = &builder.llvm_out(target);
for file in files.trim_end().split(' ') {
@@ -2020,6 +2033,8 @@ impl Step for RustDev {
"llvm-dwp",
"llvm-nm",
"llvm-dwarfdump",
+ "llvm-dis",
+ "llvm-tblgen",
] {
tarball.add_file(src_bindir.join(exe(bin, target)), "bin", 0o755);
}
@@ -2050,6 +2065,41 @@ impl Step for RustDev {
}
}
+// Tarball intended for internal consumption to ease rustc/std development.
+//
+// Should not be considered stable by end users.
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Bootstrap {
+ pub target: TargetSelection,
+}
+
+impl Step for Bootstrap {
+ type Output = Option<GeneratedTarball>;
+ const DEFAULT: bool = false;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.alias("bootstrap")
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(Bootstrap { target: run.target });
+ }
+
+ fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
+ let target = self.target;
+
+ let tarball = Tarball::new(builder, "bootstrap", &target.triple);
+
+ let bootstrap_outdir = &builder.bootstrap_out;
+ for file in &["bootstrap", "llvm-config-wrapper", "rustc", "rustdoc", "sccache-plus-cl"] {
+ tarball.add_file(bootstrap_outdir.join(exe(file, target)), "bootstrap/bin", 0o755);
+ }
+
+ Some(tarball.generate())
+ }
+}
+
/// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the
/// release process to avoid cloning the monorepo and building stuff.
///
@@ -2115,6 +2165,10 @@ impl Step for ReproducibleArtifacts {
tarball.add_file(path, ".", 0o644);
added_anything = true;
}
+ if let Some(path) = builder.config.llvm_bolt_profile_use.as_ref() {
+ tarball.add_file(path, ".", 0o644);
+ added_anything = true;
+ }
if added_anything { Some(tarball.generate()) } else { None }
}
}
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index f909ecc0a..ea06caf9c 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -7,6 +7,7 @@
//! Everything here is basically just a shim around calling either `rustbook` or
//! `rustdoc`.
+use std::ffi::OsStr;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
@@ -81,6 +82,7 @@ book!(
Reference, "src/doc/reference", "reference", submodule;
RustByExample, "src/doc/rust-by-example", "rust-by-example", submodule;
RustdocBook, "src/doc/rustdoc", "rustdoc";
+ StyleGuide, "src/doc/style-guide", "style-guide";
);
fn open(builder: &Builder<'_>, path: impl AsRef<Path>) {
@@ -226,7 +228,7 @@ impl Step for TheBook {
}
// build the version info page and CSS
- builder.ensure(Standalone { compiler, target });
+ let shared_assets = builder.ensure(SharedAssets { target });
// build the redirect pages
builder.info(&format!("Documenting book redirect pages ({})", target));
@@ -235,7 +237,7 @@ impl Step for TheBook {
let path = file.path();
let path = path.to_str().unwrap();
- invoke_rustdoc(builder, compiler, target, path);
+ invoke_rustdoc(builder, compiler, &shared_assets, target, path);
}
if builder.was_invoked_explicitly::<Self>(Kind::Doc) {
@@ -249,6 +251,7 @@ impl Step for TheBook {
fn invoke_rustdoc(
builder: &Builder<'_>,
compiler: Compiler,
+ shared_assets: &SharedAssetsPaths,
target: TargetSelection,
markdown: &str,
) {
@@ -258,7 +261,6 @@ fn invoke_rustdoc(
let header = builder.src.join("src/doc/redirect.inc");
let footer = builder.src.join("src/doc/footer.inc");
- let version_info = out.join("version_info.html");
let mut cmd = builder.rustdoc_cmd(compiler);
@@ -267,7 +269,7 @@ fn invoke_rustdoc(
cmd.arg("--html-after-content")
.arg(&footer)
.arg("--html-before-content")
- .arg(&version_info)
+ .arg(&shared_assets.version_info)
.arg("--html-in-header")
.arg(&header)
.arg("--markdown-no-toc")
@@ -298,7 +300,7 @@ impl Step for Standalone {
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("src/doc").default_condition(builder.config.docs)
+ run.path("src/doc").alias("standalone").default_condition(builder.config.docs)
}
fn make_run(run: RunConfig<'_>) {
@@ -323,21 +325,11 @@ impl Step for Standalone {
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
+ let version_info = builder.ensure(SharedAssets { target: self.target }).version_info;
+
let favicon = builder.src.join("src/doc/favicon.inc");
let footer = builder.src.join("src/doc/footer.inc");
let full_toc = builder.src.join("src/doc/full-toc.inc");
- t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
-
- let version_input = builder.src.join("src/doc/version_info.html.template");
- let version_info = out.join("version_info.html");
-
- if !builder.config.dry_run && !up_to_date(&version_input, &version_info) {
- let info = t!(fs::read_to_string(&version_input))
- .replace("VERSION", &builder.rust_release())
- .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or(""))
- .replace("STAMP", builder.rust_info.sha().unwrap_or(""));
- t!(fs::write(&version_info, &info));
- }
for file in t!(fs::read_dir(builder.src.join("src/doc"))) {
let file = t!(file);
@@ -383,15 +375,9 @@ impl Step for Standalone {
}
if filename == "not_found.md" {
- cmd.arg("--markdown-css")
- .arg(format!("https://doc.rust-lang.org/rustdoc{}.css", &builder.version))
- .arg("--markdown-css")
- .arg("https://doc.rust-lang.org/rust.css");
+ cmd.arg("--markdown-css").arg("https://doc.rust-lang.org/rust.css");
} else {
- cmd.arg("--markdown-css")
- .arg(format!("rustdoc{}.css", &builder.version))
- .arg("--markdown-css")
- .arg("rust.css");
+ cmd.arg("--markdown-css").arg("rust.css");
}
builder.run(&mut cmd);
}
@@ -405,6 +391,45 @@ impl Step for Standalone {
}
}
+#[derive(Debug, Clone)]
+pub struct SharedAssetsPaths {
+ pub version_info: PathBuf,
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct SharedAssets {
+ target: TargetSelection,
+}
+
+impl Step for SharedAssets {
+ type Output = SharedAssetsPaths;
+ const DEFAULT: bool = false;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ // Other tasks depend on this, no need to execute it on its own
+ run.never()
+ }
+
+ // Generate shared resources used by other pieces of documentation.
+ fn run(self, builder: &Builder<'_>) -> Self::Output {
+ let out = builder.doc_out(self.target);
+
+ let version_input = builder.src.join("src").join("doc").join("version_info.html.template");
+ let version_info = out.join("version_info.html");
+ if !builder.config.dry_run && !up_to_date(&version_input, &version_info) {
+ let info = t!(fs::read_to_string(&version_input))
+ .replace("VERSION", &builder.rust_release())
+ .replace("SHORT_HASH", builder.rust_info.sha_short().unwrap_or(""))
+ .replace("STAMP", builder.rust_info.sha().unwrap_or(""));
+ t!(fs::write(&version_info, &info));
+ }
+
+ builder.copy(&builder.src.join("src").join("doc").join("rust.css"), &out.join("rust.css"));
+
+ SharedAssetsPaths { version_info }
+ }
+}
+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Std {
pub stage: u32,
@@ -431,49 +456,25 @@ impl Step for Std {
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let target = self.target;
- builder.info(&format!("Documenting stage{} std ({})", stage, target));
- if builder.no_std(target) == Some(true) {
- panic!(
- "building std documentation for no_std target {target} is not supported\n\
- Set `docs = false` in the config to disable documentation."
- );
- }
let out = builder.doc_out(target);
t!(fs::create_dir_all(&out));
- let compiler = builder.compiler(stage, builder.config.build);
-
- let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
-
- t!(fs::copy(builder.src.join("src/doc/rust.css"), out.join("rust.css")));
-
- let run_cargo_rustdoc_for = |package: &str| {
- let mut cargo =
- builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
- compile::std_cargo(builder, target, compiler.stage, &mut cargo);
- cargo
- .arg("-p")
- .arg(package)
- .arg("-Zskip-rustdoc-fingerprint")
- .arg("--")
- .arg("--markdown-css")
- .arg("rust.css")
- .arg("--markdown-no-toc")
- .arg("-Z")
- .arg("unstable-options")
- .arg("--resource-suffix")
- .arg(&builder.version)
- .arg("--index-page")
- .arg(&builder.src.join("src/doc/index.md"));
+ builder.ensure(SharedAssets { target: self.target });
- if !builder.config.docs_minification {
- cargo.arg("--disable-minification");
- }
+ let index_page = builder.src.join("src/doc/index.md").into_os_string();
+ let mut extra_args = vec![
+ OsStr::new("--markdown-css"),
+ OsStr::new("rust.css"),
+ OsStr::new("--markdown-no-toc"),
+ OsStr::new("--index-page"),
+ &index_page,
+ ];
- builder.run(&mut cargo.into());
- };
+ if !builder.config.docs_minification {
+ extra_args.push(OsStr::new("--disable-minification"));
+ }
- let paths = builder
+ let requested_crates = builder
.paths
.iter()
.map(components_simplified)
@@ -491,30 +492,20 @@ impl Step for Std {
})
.collect::<Vec<_>>();
- // Only build the following crates. While we could just iterate over the
- // folder structure, that would also build internal crates that we do
- // not want to show in documentation. These crates will later be visited
- // by the rustc step, so internal documentation will show them.
- //
- // Note that the order here is important! The crates need to be
- // processed starting from the leaves, otherwise rustdoc will not
- // create correct links between crates because rustdoc depends on the
- // existence of the output directories to know if it should be a local
- // or remote link.
- let krates = ["core", "alloc", "std", "proc_macro", "test"];
- for krate in &krates {
- run_cargo_rustdoc_for(krate);
- if paths.iter().any(|p| p == krate) {
- // No need to document more of the libraries if we have the one we want.
- break;
- }
- }
- builder.cp_r(&out_dir, &out);
+ doc_std(
+ builder,
+ DocumentationFormat::HTML,
+ stage,
+ target,
+ &out,
+ &extra_args,
+ &requested_crates,
+ );
// Look for library/std, library/core etc in the `x.py doc` arguments and
// open the corresponding rendered docs.
- for requested_crate in paths {
- if krates.iter().any(|k| *k == requested_crate.as_str()) {
+ for requested_crate in requested_crates {
+ if STD_PUBLIC_CRATES.iter().any(|k| *k == requested_crate.as_str()) {
let index = out.join(requested_crate).join("index.html");
open(builder, &index);
}
@@ -523,6 +514,134 @@ impl Step for Std {
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct JsonStd {
+ pub stage: u32,
+ pub target: TargetSelection,
+}
+
+impl Step for JsonStd {
+ type Output = ();
+ const DEFAULT: bool = false;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ let default = run.builder.config.docs && run.builder.config.cmd.json();
+ run.all_krates("test").path("library").default_condition(default)
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ run.builder.ensure(Std { stage: run.builder.top_stage, target: run.target });
+ }
+
+ /// Build JSON documentation for the standard library crates.
+ ///
+ /// This is largely just a wrapper around `cargo doc`.
+ fn run(self, builder: &Builder<'_>) {
+ let stage = self.stage;
+ let target = self.target;
+ let out = builder.json_doc_out(target);
+ t!(fs::create_dir_all(&out));
+ let extra_args = [OsStr::new("--output-format"), OsStr::new("json")];
+ doc_std(builder, DocumentationFormat::JSON, stage, target, &out, &extra_args, &[])
+ }
+}
+
+/// Name of the crates that are visible to consumers of the standard library.
+/// Documentation for internal crates is handled by the rustc step, so internal crates will show
+/// up there.
+///
+/// Order here is important!
+/// Crates need to be processed starting from the leaves, otherwise rustdoc will not
+/// create correct links between crates because rustdoc depends on the
+/// existence of the output directories to know if it should be a local
+/// or remote link.
+const STD_PUBLIC_CRATES: [&str; 5] = ["core", "alloc", "std", "proc_macro", "test"];
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+enum DocumentationFormat {
+ HTML,
+ JSON,
+}
+
+impl DocumentationFormat {
+ fn as_str(&self) -> &str {
+ match self {
+ DocumentationFormat::HTML => "HTML",
+ DocumentationFormat::JSON => "JSON",
+ }
+ }
+}
+
+/// Build the documentation for public standard library crates.
+///
+/// `requested_crates` can be used to build only a subset of the crates. If empty, all crates will
+/// be built.
+fn doc_std(
+ builder: &Builder<'_>,
+ format: DocumentationFormat,
+ stage: u32,
+ target: TargetSelection,
+ out: &Path,
+ extra_args: &[&OsStr],
+ requested_crates: &[String],
+) {
+ builder.info(&format!(
+ "Documenting stage{} std ({}) in {} format",
+ stage,
+ target,
+ format.as_str()
+ ));
+ if builder.no_std(target) == Some(true) {
+ panic!(
+ "building std documentation for no_std target {target} is not supported\n\
+ Set `docs = false` in the config to disable documentation."
+ );
+ }
+ let compiler = builder.compiler(stage, builder.config.build);
+ // This is directory where the compiler will place the output of the command.
+ // We will then copy the files from this directory into the final `out` directory, the specified
+ // as a function parameter.
+ let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc");
+ // `cargo` uses the same directory for both JSON docs and HTML docs.
+ // This could lead to cross-contamination when copying files into the specified `out` directory.
+ // For example:
+ // ```bash
+ // x doc std
+ // x doc std --json
+ // ```
+ // could lead to HTML docs being copied into the JSON docs output directory.
+ // To avoid this issue, we clean the doc folder before invoking `cargo`.
+ if out_dir.exists() {
+ builder.remove_dir(&out_dir);
+ }
+
+ let run_cargo_rustdoc_for = |package: &str| {
+ let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustdoc");
+ compile::std_cargo(builder, target, compiler.stage, &mut cargo);
+ cargo
+ .arg("-p")
+ .arg(package)
+ .arg("-Zskip-rustdoc-fingerprint")
+ .arg("--")
+ .arg("-Z")
+ .arg("unstable-options")
+ .arg("--resource-suffix")
+ .arg(&builder.version)
+ .args(extra_args);
+ builder.run(&mut cargo.into());
+ };
+
+ for krate in STD_PUBLIC_CRATES {
+ run_cargo_rustdoc_for(krate);
+ if requested_crates.iter().any(|p| p == krate) {
+ // No need to document more of the libraries if we have the one we want.
+ break;
+ }
+ }
+
+ builder.cp_r(&out_dir, &out);
+}
+
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustc {
pub stage: u32,
pub target: TargetSelection,
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index 19504a51a..d19a1ae95 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-llvm` configuration download
a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
-Last change is for: https://github.com/rust-lang/rust/pull/96867
+Last change is for: https://github.com/rust-lang/rust/pull/102790
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index 789da7481..ee341a353 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -78,6 +78,8 @@ pub struct Flags {
//
// llvm_out/build/profiles/ is the location this writes to.
pub llvm_profile_generate: bool,
+ pub llvm_bolt_profile_generate: bool,
+ pub llvm_bolt_profile_use: Option<String>,
}
#[derive(Debug)]
@@ -107,6 +109,7 @@ pub enum Subcommand {
Doc {
paths: Vec<PathBuf>,
open: bool,
+ json: bool,
},
Test {
paths: Vec<PathBuf>,
@@ -254,6 +257,8 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
opts.optmulti("D", "", "deny certain clippy lints", "OPT");
opts.optmulti("W", "", "warn about certain clippy lints", "OPT");
opts.optmulti("F", "", "forbid certain clippy lints", "OPT");
+ opts.optflag("", "llvm-bolt-profile-generate", "generate BOLT profile for LLVM build");
+ opts.optopt("", "llvm-bolt-profile-use", "use BOLT profile for LLVM build", "PROFILE");
// We can't use getopt to parse the options until we have completed specifying which
// options are valid, but under the current implementation, some options are conditional on
@@ -325,6 +330,11 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`",
}
Kind::Doc => {
opts.optflag("", "open", "open the docs in a browser");
+ opts.optflag(
+ "",
+ "json",
+ "render the documentation in JSON format in addition to the usual HTML format",
+ );
}
Kind::Clean => {
opts.optflag("", "all", "clean all build artifacts");
@@ -493,6 +503,7 @@ Arguments:
./x.py doc src/doc/book
./x.py doc src/doc/nomicon
./x.py doc src/doc/book library/std
+ ./x.py doc library/std --json
./x.py doc library/std --open
If no arguments are passed then everything is documented:
@@ -581,7 +592,11 @@ Arguments:
},
},
Kind::Bench => Subcommand::Bench { paths, test_args: matches.opt_strs("test-args") },
- Kind::Doc => Subcommand::Doc { paths, open: matches.opt_present("open") },
+ Kind::Doc => Subcommand::Doc {
+ paths,
+ open: matches.opt_present("open"),
+ json: matches.opt_present("json"),
+ },
Kind::Clean => {
if !paths.is_empty() {
println!("\nclean does not take a path argument\n");
@@ -680,6 +695,8 @@ Arguments:
rust_profile_generate: matches.opt_str("rust-profile-generate"),
llvm_profile_use: matches.opt_str("llvm-profile-use"),
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"),
}
}
}
@@ -787,6 +804,13 @@ impl Subcommand {
_ => false,
}
}
+
+ pub fn json(&self) -> bool {
+ match *self {
+ Subcommand::Doc { json, .. } => json,
+ _ => false,
+ }
+ }
}
fn split(s: &[String]) -> Vec<String> {
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index d34aa15c5..7672b7c91 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -200,13 +200,10 @@ install!((self, builder, _config),
install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
};
Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
- if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
- install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
- } else {
- builder.info(
- &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
- );
- }
+ let tarball = builder
+ .ensure(dist::Miri { compiler: self.compiler, target: self.target })
+ .expect("missing miri");
+ install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
};
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index cc0cf12bd..7e70e99bb 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -122,6 +122,7 @@ use crate::util::{
check_run, exe, libdir, mtime, output, run, run_suppressed, try_run, try_run_suppressed, CiEnv,
};
+mod bolt;
mod builder;
mod cache;
mod cc_detect;
@@ -198,9 +199,12 @@ 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::Codegen), "parallel_compiler", None),
(Some(Mode::Std), "stdarch_intel_sde", None),
(Some(Mode::Std), "no_fp_fmt_parse", None),
(Some(Mode::Std), "no_global_oom_handling", None),
+ (Some(Mode::Std), "no_rc", None),
+ (Some(Mode::Std), "no_sync", None),
(Some(Mode::Std), "freebsd12", None),
(Some(Mode::Std), "backtrace_in_libstd", None),
/* Extra values not defined in the built-in targets yet, but used in std */
@@ -226,6 +230,8 @@ 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),
];
/// A structure representing a Rust compiler.
@@ -395,7 +401,7 @@ impl Build {
/// line and the filesystem `config`.
///
/// By default all build output will be placed in the current directory.
- pub fn new(config: Config) -> Build {
+ pub fn new(mut config: Config) -> Build {
let src = config.src.clone();
let out = config.out.clone();
@@ -456,19 +462,22 @@ impl Build {
.expect("failed to read src/version");
let version = version.trim();
- let bootstrap_out = if std::env::var("BOOTSTRAP_PYTHON").is_ok() {
- out.join("bootstrap").join("debug")
- } else {
- let workspace_target_dir = std::env::var("CARGO_TARGET_DIR")
- .map(PathBuf::from)
- .unwrap_or_else(|_| src.join("target"));
- let bootstrap_out = workspace_target_dir.join("debug");
- if !bootstrap_out.join("rustc").exists() && !cfg!(test) {
- // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented
- panic!("run `cargo build --bins` before `cargo run`")
- }
- bootstrap_out
- };
+ let bootstrap_out = std::env::current_exe()
+ .expect("could not determine path to running process")
+ .parent()
+ .unwrap()
+ .to_path_buf();
+ if !bootstrap_out.join(exe("rustc", config.build)).exists() && !cfg!(test) {
+ // this restriction can be lifted whenever https://github.com/rust-lang/rfcs/pull/3028 is implemented
+ panic!(
+ "`rustc` not found in {}, run `cargo build --bins` before `cargo run`",
+ bootstrap_out.display()
+ )
+ }
+
+ if rust_info.is_from_tarball() && config.description.is_none() {
+ config.description = Some("built from a source tarball".to_owned());
+ }
let mut build = Build {
initial_rustc: config.initial_rustc.clone(),
@@ -540,13 +549,8 @@ impl Build {
// Make sure we update these before gathering metadata so we don't get an error about missing
// Cargo.toml files.
- let rust_submodules = [
- "src/tools/rust-installer",
- "src/tools/cargo",
- "src/tools/miri",
- "library/backtrace",
- "library/stdarch",
- ];
+ let rust_submodules =
+ ["src/tools/rust-installer", "src/tools/cargo", "library/backtrace", "library/stdarch"];
for s in rust_submodules {
build.update_submodule(Path::new(s));
}
@@ -574,7 +578,9 @@ impl Build {
// NOTE: The check for the empty directory is here because when running x.py the first time,
// the submodule won't be checked out. Check it out now so we can build it.
- if !channel::GitInfo::new(false, &absolute_path).is_git() && !dir_is_empty(&absolute_path) {
+ if !channel::GitInfo::new(false, &absolute_path).is_managed_git_subrepository()
+ && !dir_is_empty(&absolute_path)
+ {
return;
}
@@ -645,7 +651,7 @@ impl Build {
// Sample output: `submodule.src/rust-installer.path src/tools/rust-installer`
let submodule = Path::new(line.splitn(2, ' ').nth(1).unwrap());
// Don't update the submodule unless it's already been cloned.
- if channel::GitInfo::new(false, submodule).is_git() {
+ if channel::GitInfo::new(false, submodule).is_managed_git_subrepository() {
self.update_submodule(submodule);
}
}
@@ -671,6 +677,9 @@ impl Build {
return setup::setup(&self.config, *profile);
}
+ // Download rustfmt early so that it can be used in rust-analyzer configs.
+ let _ = &builder::Builder::new(&self).initial_rustfmt();
+
{
let builder = builder::Builder::new(&self);
if let Some(path) = builder.paths.get(0) {
@@ -825,6 +834,11 @@ impl Build {
self.out.join(&*target.triple).join("doc")
}
+ /// Output directory for all JSON-formatted documentation for a target
+ fn json_doc_out(&self, target: TargetSelection) -> PathBuf {
+ self.out.join(&*target.triple).join("json-doc")
+ }
+
fn test_out(&self, target: TargetSelection) -> PathBuf {
self.out.join(&*target.triple).join("test")
}
@@ -1253,7 +1267,7 @@ impl Build {
match &self.config.channel[..] {
"stable" => num.to_string(),
"beta" => {
- if self.rust_info.is_git() && !self.config.ignore_git {
+ if self.rust_info.is_managed_git_subrepository() && !self.config.ignore_git {
format!("{}-beta.{}", num, self.beta_prerelease_version())
} else {
format!("{}-beta", num)
@@ -1307,10 +1321,6 @@ impl Build {
self.package_vers(&self.version)
}
- fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool {
- target.contains("linux-gnu") || target.contains("apple-darwin")
- }
-
/// Returns the `version` string associated with this compiler for Rust
/// itself.
///
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index fc3bfaf1b..2f856c276 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -16,7 +16,9 @@ use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
+use crate::bolt::{instrument_with_bolt_inplace, optimize_library_with_bolt_inplace};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::channel;
use crate::config::TargetSelection;
use crate::util::get_clang_cl_resource_dir;
use crate::util::{self, exe, output, program_out_of_date, t, up_to_date};
@@ -115,24 +117,29 @@ pub fn prebuilt_llvm_config(
}
/// This retrieves the LLVM sha we *want* to use, according to git history.
-pub(crate) fn detect_llvm_sha(config: &crate::config::Config) -> String {
- let mut rev_list = config.git();
- rev_list.args(&[
- PathBuf::from("rev-list"),
- format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
- "-n1".into(),
- "--first-parent".into(),
- "HEAD".into(),
- "--".into(),
- config.src.join("src/llvm-project"),
- config.src.join("src/bootstrap/download-ci-llvm-stamp"),
- // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
- config.src.join("src/version"),
- ]);
- let llvm_sha = output(&mut rev_list);
- let llvm_sha = llvm_sha.trim();
-
- if llvm_sha == "" {
+pub(crate) fn detect_llvm_sha(config: &crate::config::Config, is_git: bool) -> String {
+ let llvm_sha = if is_git {
+ let mut rev_list = config.git();
+ rev_list.args(&[
+ PathBuf::from("rev-list"),
+ format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
+ "-n1".into(),
+ "--first-parent".into(),
+ "HEAD".into(),
+ "--".into(),
+ config.src.join("src/llvm-project"),
+ config.src.join("src/bootstrap/download-ci-llvm-stamp"),
+ // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
+ config.src.join("src/version"),
+ ]);
+ output(&mut rev_list).trim().to_owned()
+ } else if let Some(info) = channel::read_commit_info_file(&config.src) {
+ info.sha.trim().to_owned()
+ } else {
+ "".to_owned()
+ };
+
+ if &llvm_sha == "" {
eprintln!("error: could not find commit hash for downloading LLVM");
eprintln!("help: maybe your repository history is too shallow?");
eprintln!("help: consider disabling `download-ci-llvm`");
@@ -140,7 +147,7 @@ pub(crate) fn detect_llvm_sha(config: &crate::config::Config) -> String {
panic!();
}
- llvm_sha.to_owned()
+ llvm_sha
}
/// Returns whether the CI-found LLVM is currently usable.
@@ -194,7 +201,9 @@ pub(crate) fn is_ci_llvm_available(config: &crate::config::Config, asserts: bool
}
if crate::util::CiEnv::is_ci() {
- let llvm_sha = detect_llvm_sha(config);
+ // 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 {
@@ -215,7 +224,7 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
}
let llvm_root = config.ci_llvm_root();
let llvm_stamp = llvm_root.join(".llvm-stamp");
- let llvm_sha = detect_llvm_sha(&config);
+ let llvm_sha = detect_llvm_sha(&config, builder.rust_info.is_managed_git_subrepository());
let key = format!("{}{}", llvm_sha, config.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !config.dry_run {
download_ci_llvm(builder, &llvm_sha);
@@ -260,8 +269,8 @@ fn download_ci_llvm(builder: &Builder<'_>, llvm_sha: &str) {
} else {
&builder.config.stage0_metadata.config.artifacts_server
};
- let version = builder.config.artifact_version_part(llvm_sha);
- let filename = format!("rust-dev-{}-{}.tar.xz", version, builder.build.build.triple);
+ let channel = builder.config.artifact_channel(builder, llvm_sha);
+ let filename = format!("rust-dev-{}-{}.tar.xz", channel, builder.build.build.triple);
let tarball = rustc_cache.join(&filename);
if !tarball.exists() {
let help_on_error = "error: failed to download llvm from ci
@@ -395,6 +404,12 @@ impl Step for Llvm {
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
cfg.define("LLVM_PROFDATA_FILE", &path);
}
+ if builder.config.llvm_bolt_profile_generate
+ || builder.config.llvm_bolt_profile_use.is_some()
+ {
+ // Relocations are required for BOLT to work.
+ ldflags.push_all("-Wl,-q");
+ }
// Disable zstd to avoid a dependency on libzstd.so.
cfg.define("LLVM_ENABLE_ZSTD", "OFF");
@@ -423,12 +438,7 @@ impl Step for Llvm {
// which saves both memory during parallel links and overall disk space
// for the tools. We don't do this on every platform as it doesn't work
// equally well everywhere.
- //
- // If we're not linking rustc to a dynamic LLVM, though, then don't link
- // tools to it.
- let llvm_link_shared =
- builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared();
- if llvm_link_shared {
+ if builder.llvm_link_shared() {
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
}
@@ -494,18 +504,18 @@ impl Step for Llvm {
// https://llvm.org/docs/HowToCrossCompileLLVM.html
if target != builder.config.build {
- builder.ensure(Llvm { target: builder.config.build });
- // FIXME: if the llvm root for the build triple is overridden then we
- // should use llvm-tblgen from there, also should verify that it
- // actually exists most of the time in normal installs of LLVM.
- let host_bin = builder.llvm_out(builder.config.build).join("bin");
- cfg.define("LLVM_TABLEGEN", host_bin.join("llvm-tblgen").with_extension(EXE_EXTENSION));
- // LLVM_NM is required for cross compiling using MSVC
- cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION));
- cfg.define(
- "LLVM_CONFIG_PATH",
- host_bin.join("llvm-config").with_extension(EXE_EXTENSION),
- );
+ let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+ if !builder.config.dry_run {
+ let llvm_bindir = output(Command::new(&llvm_config).arg("--bindir"));
+ let host_bin = Path::new(llvm_bindir.trim());
+ cfg.define(
+ "LLVM_TABLEGEN",
+ host_bin.join("llvm-tblgen").with_extension(EXE_EXTENSION),
+ );
+ // LLVM_NM is required for cross compiling using MSVC
+ cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION));
+ }
+ cfg.define("LLVM_CONFIG_PATH", llvm_config);
if builder.config.llvm_clang {
let build_bin = builder.llvm_out(builder.config.build).join("build").join("bin");
let clang_tblgen = build_bin.join("clang-tblgen").with_extension(EXE_EXTENSION);
@@ -553,7 +563,7 @@ impl Step for Llvm {
// libLLVM.dylib will be built. However, llvm-config will still look
// for a versioned path like libLLVM-14.dylib. Manually create a symbolic
// link to make llvm-config happy.
- if llvm_link_shared && target.contains("apple-darwin") {
+ if builder.llvm_link_shared() && target.contains("apple-darwin") {
let mut cmd = Command::new(&build_llvm_config);
let version = output(cmd.arg("--version"));
let major = version.split('.').next().unwrap();
@@ -568,12 +578,34 @@ impl Step for Llvm {
}
}
+ // After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file
+ // in place. This is fine, because currently we do not support incrementally rebuilding
+ // LLVM after a configuration change, so to rebuild it the build files have to be removed,
+ // which will also remove these modified files.
+ if builder.config.llvm_bolt_profile_generate {
+ instrument_with_bolt_inplace(&get_built_llvm_lib_path(&build_llvm_config));
+ }
+ if let Some(path) = &builder.config.llvm_bolt_profile_use {
+ optimize_library_with_bolt_inplace(
+ &get_built_llvm_lib_path(&build_llvm_config),
+ &Path::new(path),
+ );
+ }
+
t!(stamp.write());
build_llvm_config
}
}
+/// Returns path to a built LLVM library (libLLVM.so).
+/// Assumes that we have built LLVM into a single library file.
+fn get_built_llvm_lib_path(llvm_config_path: &Path) -> PathBuf {
+ let mut cmd = Command::new(llvm_config_path);
+ cmd.arg("--libfiles");
+ PathBuf::from(output(&mut cmd).trim())
+}
+
fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
if !builder.config.llvm_version_check {
return;
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index cae41286f..e90551725 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -74,7 +74,7 @@ pub fn check(build: &mut Build) {
let mut cmd_finder = Finder::new();
// If we've got a git directory we're gonna need git to update
// submodules and learn about various other aspects.
- if build.rust_info.is_git() {
+ if build.rust_info.is_managed_git_subrepository() {
cmd_finder.must_have("git");
}
diff --git a/src/bootstrap/tarball.rs b/src/bootstrap/tarball.rs
index e30067a5c..d999b6c15 100644
--- a/src/bootstrap/tarball.rs
+++ b/src/bootstrap/tarball.rs
@@ -4,6 +4,7 @@ use std::{
};
use crate::builder::Builder;
+use crate::channel;
use crate::util::t;
#[derive(Copy, Clone)]
@@ -297,8 +298,9 @@ impl<'a> Tarball<'a> {
fn run(self, build_cli: impl FnOnce(&Tarball<'a>, &mut Command)) -> GeneratedTarball {
t!(std::fs::create_dir_all(&self.overlay_dir));
self.builder.create(&self.overlay_dir.join("version"), &self.overlay.version(self.builder));
- if let Some(sha) = self.builder.rust_sha() {
- self.builder.create(&self.overlay_dir.join("git-commit-hash"), &sha);
+ if let Some(info) = self.builder.rust_info.info() {
+ channel::write_commit_hash_file(&self.overlay_dir, &info.sha);
+ channel::write_commit_info_file(&self.overlay_dir, info);
}
for file in self.overlay.legal_and_readme() {
self.builder.install(&self.builder.src.join(file), &self.overlay_dir, 0o644);
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index dd41f8453..791c35c36 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -23,7 +23,7 @@ use crate::toolstate::ToolState;
use crate::util::{self, add_link_lib_path, dylib_path, dylib_path_var, output, t};
use crate::{envify, CLang, DocTests, GitRepo, Mode};
-const ADB_TEST_DIR: &str = "/data/tmp/work";
+const ADB_TEST_DIR: &str = "/data/local/tmp/work";
/// The two modes of the test runner; tests or benchmarks.
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
@@ -461,139 +461,158 @@ impl Step for RustDemangler {
pub struct Miri {
stage: u32,
host: TargetSelection,
+ target: TargetSelection,
}
impl Step for Miri {
type Output = ();
- const ONLY_HOSTS: bool = true;
+ const ONLY_HOSTS: bool = false;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/miri")
}
fn make_run(run: RunConfig<'_>) {
- run.builder.ensure(Miri { stage: run.builder.top_stage, host: run.target });
+ run.builder.ensure(Miri {
+ stage: run.builder.top_stage,
+ host: run.build_triple(),
+ target: run.target,
+ });
}
/// Runs `cargo test` for miri.
fn run(self, builder: &Builder<'_>) {
let stage = self.stage;
let host = self.host;
+ let target = self.target;
let compiler = builder.compiler(stage, host);
// We need the stdlib for the *next* stage, as it was built with this compiler that also built Miri.
// Except if we are at stage 2, the bootstrap loop is complete and we can stick with our current stage.
let compiler_std = builder.compiler(if stage < 2 { stage + 1 } else { stage }, host);
- let miri =
- builder.ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() });
- let cargo_miri = builder.ensure(tool::CargoMiri {
- compiler,
- target: self.host,
- extra_features: Vec::new(),
- });
+ let miri = builder
+ .ensure(tool::Miri { compiler, target: self.host, extra_features: Vec::new() })
+ .expect("in-tree tool");
+ let _cargo_miri = builder
+ .ensure(tool::CargoMiri { compiler, target: self.host, extra_features: Vec::new() })
+ .expect("in-tree tool");
// The stdlib we need might be at a different stage. And just asking for the
// sysroot does not seem to populate it, so we do that first.
builder.ensure(compile::Std::new(compiler_std, host));
let sysroot = builder.sysroot(compiler_std);
- if let (Some(miri), Some(_cargo_miri)) = (miri, cargo_miri) {
- let mut cargo =
- builder.cargo(compiler, Mode::ToolRustc, SourceType::Submodule, host, "install");
- cargo.arg("xargo");
- // Configure `cargo install` path. cargo adds a `bin/`.
- cargo.env("CARGO_INSTALL_ROOT", &builder.out);
-
- let mut cargo = Command::from(cargo);
- if !try_run(builder, &mut cargo) {
- return;
- }
- // # Run `cargo miri setup`.
- let mut cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolRustc,
- host,
- "run",
- "src/tools/miri/cargo-miri",
- SourceType::Submodule,
- &[],
- );
- cargo.add_rustc_lib_path(builder, compiler);
- cargo.arg("--").arg("miri").arg("setup");
-
- // Tell `cargo miri setup` where to find the sources.
- cargo.env("XARGO_RUST_SRC", builder.src.join("library"));
- // Tell it where to find Miri.
- cargo.env("MIRI", &miri);
- // Debug things.
- cargo.env("RUST_BACKTRACE", "1");
- // Let cargo-miri know where xargo ended up.
- cargo.env("XARGO_CHECK", builder.out.join("bin").join("xargo-check"));
-
- let mut cargo = Command::from(cargo);
- if !try_run(builder, &mut cargo) {
- return;
- }
+ // # Run `cargo miri setup` for the given target.
+ let mut cargo = tool::prepare_tool_cargo(
+ builder,
+ compiler,
+ Mode::ToolRustc,
+ host,
+ "run",
+ "src/tools/miri/cargo-miri",
+ SourceType::Submodule,
+ &[],
+ );
+ cargo.add_rustc_lib_path(builder, compiler);
+ cargo.arg("--").arg("miri").arg("setup");
+ cargo.arg("--target").arg(target.rustc_target_arg());
+
+ // Tell `cargo miri setup` where to find the sources.
+ cargo.env("MIRI_LIB_SRC", builder.src.join("library"));
+ // Tell it where to find Miri.
+ cargo.env("MIRI", &miri);
+ // Debug things.
+ cargo.env("RUST_BACKTRACE", "1");
+
+ let mut cargo = Command::from(cargo);
+ builder.run(&mut cargo);
+
+ // # Determine where Miri put its sysroot.
+ // To this end, we run `cargo miri setup --print-sysroot` and capture the output.
+ // (We do this separately from the above so that when the setup actually
+ // happens we get some output.)
+ // We re-use the `cargo` from above.
+ cargo.arg("--print-sysroot");
+
+ // FIXME: Is there a way in which we can re-use the usual `run` helpers?
+ let miri_sysroot = if builder.config.dry_run {
+ String::new()
+ } else {
+ builder.verbose(&format!("running: {:?}", cargo));
+ let out =
+ cargo.output().expect("We already ran `cargo miri setup` before and that worked");
+ assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
+ // Output is "<sysroot>\n".
+ let stdout = String::from_utf8(out.stdout)
+ .expect("`cargo miri setup` stdout is not valid UTF-8");
+ let sysroot = stdout.trim_end();
+ builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot));
+ sysroot.to_owned()
+ };
- // # Determine where Miri put its sysroot.
- // To this end, we run `cargo miri setup --print-sysroot` and capture the output.
- // (We do this separately from the above so that when the setup actually
- // happens we get some output.)
- // We re-use the `cargo` from above.
- cargo.arg("--print-sysroot");
-
- // FIXME: Is there a way in which we can re-use the usual `run` helpers?
- let miri_sysroot = if builder.config.dry_run {
- String::new()
- } else {
- builder.verbose(&format!("running: {:?}", cargo));
- let out = cargo
- .output()
- .expect("We already ran `cargo miri setup` before and that worked");
- assert!(out.status.success(), "`cargo miri setup` returned with non-0 exit code");
- // Output is "<sysroot>\n".
- let stdout = String::from_utf8(out.stdout)
- .expect("`cargo miri setup` stdout is not valid UTF-8");
- let sysroot = stdout.trim_end();
- builder.verbose(&format!("`cargo miri setup --print-sysroot` said: {:?}", sysroot));
- sysroot.to_owned()
- };
-
- // # Run `cargo test`.
- let mut cargo = tool::prepare_tool_cargo(
- builder,
- compiler,
- Mode::ToolRustc,
- host,
- "test",
- "src/tools/miri",
- SourceType::Submodule,
- &[],
- );
- cargo.add_rustc_lib_path(builder, compiler);
-
- // miri tests need to know about the stage sysroot
- cargo.env("MIRI_SYSROOT", miri_sysroot);
- cargo.env("MIRI_HOST_SYSROOT", sysroot);
- cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
- cargo.env("MIRI", miri);
- // propagate --bless
- if builder.config.cmd.bless() {
- cargo.env("MIRI_BLESS", "Gesundheit");
- }
+ // # Run `cargo test`.
+ let mut cargo = tool::prepare_tool_cargo(
+ builder,
+ compiler,
+ Mode::ToolRustc,
+ host,
+ "test",
+ "src/tools/miri",
+ SourceType::Submodule,
+ &[],
+ );
+ cargo.add_rustc_lib_path(builder, compiler);
- cargo.arg("--").args(builder.config.cmd.test_args());
+ // miri tests need to know about the stage sysroot
+ cargo.env("MIRI_SYSROOT", &miri_sysroot);
+ cargo.env("MIRI_HOST_SYSROOT", sysroot);
+ cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
+ cargo.env("MIRI", &miri);
+ // propagate --bless
+ if builder.config.cmd.bless() {
+ cargo.env("MIRI_BLESS", "Gesundheit");
+ }
- let mut cargo = Command::from(cargo);
- if !try_run(builder, &mut cargo) {
- return;
- }
+ // Set the target.
+ cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
+ // Forward test filters.
+ cargo.arg("--").args(builder.config.cmd.test_args());
- // # Done!
- builder.save_toolstate("miri", ToolState::TestPass);
- } else {
- eprintln!("failed to test miri: could not build");
- }
+ let mut cargo = Command::from(cargo);
+ builder.run(&mut cargo);
+
+ // # Run `cargo miri test`.
+ // This is just a smoke test (Miri's own CI invokes this in a bunch of different ways and ensures
+ // that we get the desired output), but that is sufficient to make sure that the libtest harness
+ // itself executes properly under Miri.
+ let mut cargo = tool::prepare_tool_cargo(
+ builder,
+ compiler,
+ Mode::ToolRustc,
+ host,
+ "run",
+ "src/tools/miri/cargo-miri",
+ SourceType::Submodule,
+ &[],
+ );
+ cargo.add_rustc_lib_path(builder, compiler);
+ cargo.arg("--").arg("miri").arg("test");
+ cargo
+ .arg("--manifest-path")
+ .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
+ cargo.arg("--target").arg(target.rustc_target_arg());
+ cargo.arg("--tests"); // don't run doctests, they are too confused by the staging
+ cargo.arg("--").args(builder.config.cmd.test_args());
+
+ // Tell `cargo miri` where to find things.
+ cargo.env("MIRI_SYSROOT", &miri_sysroot);
+ cargo.env("MIRI_HOST_SYSROOT", sysroot);
+ cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler));
+ cargo.env("MIRI", &miri);
+ // Debug things.
+ cargo.env("RUST_BACKTRACE", "1");
+
+ let mut cargo = Command::from(cargo);
+ builder.run(&mut cargo);
}
}
@@ -1400,7 +1419,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
}
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
- flags.push(builder.config.cmd.rustc_args().join(" "));
+ flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string()));
if let Some(linker) = builder.linker(target) {
cmd.arg("--linker").arg(linker);
@@ -1409,12 +1428,16 @@ note: if you're sure you want to do this, please open an issue as to why. In the
let mut hostflags = flags.clone();
hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
hostflags.extend(builder.lld_flags(compiler.host));
- cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
+ for flag in hostflags {
+ cmd.arg("--host-rustcflags").arg(flag);
+ }
let mut targetflags = flags;
targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
targetflags.extend(builder.lld_flags(target));
- cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
+ for flag in targetflags {
+ cmd.arg("--target-rustcflags").arg(flag);
+ }
cmd.arg("--python").arg(builder.python());
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index 7d4ed24b6..eec74b267 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -698,7 +698,7 @@ pub struct RustAnalyzer {
impl Step for RustAnalyzer {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
- const ONLY_HOSTS: bool = false;
+ const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
@@ -742,18 +742,22 @@ pub struct RustAnalyzerProcMacroSrv {
impl Step for RustAnalyzerProcMacroSrv {
type Output = Option<PathBuf>;
const DEFAULT: bool = true;
- const ONLY_HOSTS: bool = false;
+ const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
let builder = run.builder;
- run.path("src/tools/rust-analyzer").default_condition(
- builder.config.extended
- && builder
- .config
- .tools
- .as_ref()
- .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")),
- )
+
+ // 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.extended
+ && 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<'_>) {
@@ -764,7 +768,7 @@ impl Step for RustAnalyzerProcMacroSrv {
}
fn run(self, builder: &Builder<'_>) -> Option<PathBuf> {
- builder.ensure(ToolBuild {
+ let path = builder.ensure(ToolBuild {
compiler: self.compiler,
target: self.target,
tool: "rust-analyzer-proc-macro-srv",
@@ -773,7 +777,15 @@ impl Step for RustAnalyzerProcMacroSrv {
extra_features: vec!["proc-macro-srv/sysroot-abi".to_owned()],
is_optional_tool: false,
source_type: SourceType::InTree,
- })
+ })?;
+
+ // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
+ // so that r-a can use it.
+ let libexec_path = builder.sysroot(self.compiler).join("libexec");
+ t!(fs::create_dir_all(&libexec_path));
+ builder.copy(&path, &libexec_path.join("rust-analyzer-proc-macro-srv"));
+
+ Some(path)
}
}
@@ -856,12 +868,12 @@ tool_extended!((self, builder),
Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true, in_tree=true, {};
CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true, in_tree=true, {};
Clippy, "src/tools/clippy", "clippy-driver", stable=true, in_tree=true, {};
- Miri, "src/tools/miri", "miri", stable=false, {};
- CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, {};
- Rls, "src/tools/rls", "rls", stable=true, {};
+ Miri, "src/tools/miri", "miri", stable=false, in_tree=true, {};
+ CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri", stable=false, in_tree=true, {};
// FIXME: tool_std is not quite right, we shouldn't allow nightly features.
// But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0,
// and this is close enough for now.
+ Rls, "src/tools/rls", "rls", stable=true, in_tree=true, tool_std=true, {};
RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, in_tree=true, tool_std=true, {};
Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, in_tree=true, {};
);
diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs
index f3a6759ab..1a1774432 100644
--- a/src/bootstrap/toolstate.rs
+++ b/src/bootstrap/toolstate.rs
@@ -77,7 +77,6 @@ static STABLE_TOOLS: &[(&str, &str)] = &[
// though, as otherwise we will be unable to file an issue if they start
// failing.
static NIGHTLY_TOOLS: &[(&str, &str)] = &[
- ("miri", "src/tools/miri"),
("embedded-book", "src/doc/embedded-book"),
// ("rustc-dev-guide", "src/doc/rustc-dev-guide"),
];
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index b71a348ab..ea236bee5 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -230,6 +230,112 @@ For targets: `aarch64-unknown-linux-gnu`
- C compiler > gcc version = 8.3.0
- C compiler > C++ = ENABLE -- to cross compile LLVM
+### `i586-linux-gnu.config`
+
+For targets: `i586-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Patches origin = Bundled only
+- Target options > Target Architecture = x86
+- Target options > Architecture level = i586
+- Target options > Target CFLAGS = -Wa,-mrelax-relocations=no
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 3.2.101
+- Binary utilities > Version of binutils = 2.32
+- Binary utilities > binutils extra config = --enable-compressed-debug-sections=none -- (\*)
+- C-library > glibc version = 2.17.0
+- C compiler > gcc version = 8.3.0
+- C compiler > C++ = ENABLE
+
+(\*) Compressed debug is enabled by default for gas (assembly) on Linux/x86 targets,
+ but that makes our `compiler_builtins` incompatible with binutils < 2.32.
+
+### `mips-linux-gnu.config`
+
+For targets: `mips-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = o32
+- Target options > Endianness = Big endian
+- Target options > Bitness = 32-bit
+- Target options > Architecture level = mips32r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mipsel-linux-gnu.config`
+
+For targets: `mipsel-unknown-linux-gnu`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = o32
+- Target options > Endianness = Little endian
+- Target options > Bitness = 32-bit
+- Target options > Architecture level = mips32r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > gcc extra config = --with-fp-32=xx --with-odd-spreg-32=no
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mips64-linux-gnu.config`
+
+For targets: `mips64-unknown-linux-gnuabi64`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = n64
+- Target options > Endianness = Big endian
+- Target options > Bitness = 64-bit
+- Target options > Architecture level = mips64r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
+### `mips64el-linux-gnu.config`
+
+For targets: `mips64el-unknown-linux-gnuabi64`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Path and misc options > Patches origin = Bundled, then local
+- Path and misc options > Local patch directory = /tmp/patches
+- Target options > Target Architecture = mips
+- Target options > ABI = n64
+- Target options > Endianness = Little endian
+- Target options > Bitness = 64-bit
+- Target options > Architecture level = mips64r2
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 4.4.174
+- Binary utilities > Version of binutils = 2.32
+- C-library > glibc version = 2.23
+- C compiler > gcc version = 8.3.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
### `powerpc-linux-gnu.config`
For targets: `powerpc-unknown-linux-gnu`
diff --git a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile
index 5ddd3f180..637b5fa22 100644
--- a/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile
+++ b/src/ci/docker/host-x86_64/disabled/dist-x86_64-haiku/Dockerfile
@@ -47,4 +47,6 @@ ENV RUST_CONFIGURE_ARGS --disable-jemalloc \
--set=$TARGET.cc=x86_64-unknown-haiku-gcc \
--set=$TARGET.cxx=x86_64-unknown-haiku-g++ \
--set=$TARGET.llvm-config=/bin/llvm-config-haiku
+ENV EXTERNAL_LLVM 1
+
ENV SCRIPT python3 ../x.py dist --host=$HOST --target=$HOST
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
index b0d65428e..26eb69f2e 100644
--- a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/Dockerfile
@@ -1,5 +1,6 @@
-FROM ubuntu:16.04
+FROM ubuntu:22.04
+ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
g++-multilib \
make \
@@ -17,6 +18,25 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
libssl-dev \
pkg-config
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config \
+ host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh \
+ /tmp/
+RUN su rustbuild -c ./build-i586-gnu-toolchain.sh
+ENV PATH=$PATH:/x-tools/i586-unknown-linux-gnu/bin
+ENV \
+ CC_i586_unknown_linux_gnu=i586-unknown-linux-gnu-gcc \
+ AR_i586_unknown_linux_gnu=i586-unknown-linux-gnu-ar
+
WORKDIR /build/
COPY scripts/musl.sh /build/
RUN CC=gcc CFLAGS="-m32 -Wa,-mrelax-relocations=no" \
@@ -27,17 +47,20 @@ RUN CC=gcc CFLAGS="-m32 -Wa,-mrelax-relocations=no" \
bash musl.sh i586 --target=i586 && \
rm -rf /build
+# FIXME: musl really shouldn't be linking libgcc_s.so, as it's linked to glibc,
+# but it's required by src/test/ui/proc-macro/crt-static.rs. Ubuntu:16.04 gcc-5
+# had libgcc_s.so as a symlink to the absolute libgcc_s.so.1, but now it's an
+# ld-script that expects to find libgcc_s.so.1 in the library search path.
+# See also https://github.com/rust-lang/rust/issues/82521
+RUN ln -s /usr/lib32/libgcc_s.so.1 /musl-i686/lib/
+
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
-
ENV RUST_CONFIGURE_ARGS \
--musl-root-i586=/musl-i586 \
--musl-root-i686=/musl-i686 \
- --disable-docs \
- --set llvm.allow-old-toolchain
+ --disable-docs
# Newer binutils broke things on some vms/distros (i.e., linking against
# unknown relocs disabled by the following flag), so we need to go out of our
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh
new file mode 100755
index 000000000..ceab60cfb
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/build-i586-gnu-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/build.log
+ rm /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ set -x
+}
+
+mkdir build
+cd build
+cp ../i586-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config
new file mode 100644
index 000000000..cdbd52d23
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-i586-gnu-i586-i686-musl/i586-linux-gnu.config
@@ -0,0 +1,726 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+CT_PATCH_BUNDLED=y
+# CT_PATCH_BUNDLED_LOCAL is not set
+CT_PATCH_ORDER="bundled"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+# CT_ARCH_MIPS is not set
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+CT_ARCH_X86=y
+# CT_ARCH_XTENSA is not set
+CT_ARCH="x86"
+CT_ARCH_CHOICE_KSYM="X86"
+CT_ARCH_CPU=""
+CT_ARCH_TUNE=""
+CT_ARCH_X86_SHOW=y
+
+#
+# Options for x86
+#
+CT_ARCH_X86_PKG_KSYM=""
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_CPU=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_ARCH="i586"
+CT_TARGET_CFLAGS="-Wa,-mrelax-relocations=no"
+CT_TARGET_LDFLAGS=""
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+# CT_LINUX_V_4_4 is not set
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+CT_LINUX_V_3_2=y
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="3.2.101"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_3_7_or_older=y
+CT_LINUX_older_than_3_7=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_GOLD_SUPPORTS_ARCH=y
+CT_BINUTILS_GOLD_SUPPORT=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+# CT_BINUTILS_LINKER_LD_GOLD is not set
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY="--enable-compressed-debug-sections=none"
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+# CT_GLIBC_V_2_23 is not set
+# CT_GLIBC_V_2_19 is not set
+CT_GLIBC_V_2_17=y
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.17"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_older_than_2_23=y
+CT_GLIBC_2_20_or_older=y
+CT_GLIBC_older_than_2_20=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_2_17_or_older=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_NPTL_ADDON=y
+CT_GLIBC_HAS_PORTS_ADDON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+CT_GLIBC_USE_NPTL_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="3.2.101"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+CT_CC_GCC_LIBMPX=y
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="https://ci-mirrors.rust-lang.org/rustc"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
index 948fa40dd..eb511b321 100644
--- a/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/Dockerfile
@@ -1,31 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++ \
- make \
- ninja-build \
- file \
- curl \
- ca-certificates \
- python3 \
- git \
- cmake \
- sudo \
- gdb \
- xz-utils \
- g++-mips-linux-gnu \
- libssl-dev \
- pkg-config
+FROM ubuntu:22.04
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips-linux/mips-linux-gnu.config host-x86_64/dist-mips-linux/build-mips-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips-toolchain.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips-unknown-linux-gnu/bin
+
+ENV \
+ CC_mips_unknown_linux_gnu=mips-unknown-linux-gnu-gcc \
+ AR_mips_unknown_linux_gnu=mips-unknown-linux-gnu-ar \
+ CXX_mips_unknown_linux_gnu=mips-unknown-linux-gnu-g++
ENV HOSTS=mips-unknown-linux-gnu
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
new file mode 100755
index 000000000..32612cf68
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/build-mips-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/build.log
+ rm /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ set -x
+}
+
+mkdir build
+cd build
+cp ../mips-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
new file mode 100644
index 000000000..575584ef0
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/mips-linux-gnu.config
@@ -0,0 +1,740 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+CT_ARCH_mips_o32=y
+CT_ARCH_mips_ABI="32"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+CT_ARCH_BE=y
+# CT_ARCH_LE is not set
+CT_ARCH_ENDIAN="big"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips32r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch
new file mode 100644
index 000000000..393084df3
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0001-MIPS-SPARC-fix-wrong-vfork-aliases-in-libpthread.so.patch
@@ -0,0 +1,44 @@
+From 43c2948756bb6e144c7b871e827bba37d61ad3a3 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Sat, 18 Jun 2016 19:11:23 +0200
+Subject: [PATCH 1/2] MIPS, SPARC: fix wrong vfork aliases in libpthread.so
+
+With recent binutils versions the GNU libc fails to build on at least
+MISP and SPARC, with this kind of error:
+
+ /home/aurel32/glibc/glibc-build/nptl/libpthread.so:(*IND*+0x0): multiple definition of `vfork@GLIBC_2.0'
+ /home/aurel32/glibc/glibc-build/nptl/libpthread.so::(.text+0xee50): first defined here
+
+It appears that on these architectures pt-vfork.S includes vfork.S
+(through the alpha version of pt-vfork.S) and that the __vfork aliases
+are not conditionalized on IS_IN (libc) like on other architectures.
+Therefore the aliases are also wrongly included in libpthread.so.
+
+Fix this by properly conditionalizing the aliases like on other
+architectures.
+
+Changelog:
+ * sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Conditionalize
+ hidden_def, weak_alias and strong_alias on [IS_IN (libc)].
+ * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
+---
+ sysdeps/unix/sysv/linux/mips/vfork.S | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S
+index 8c6615143708..c0c0ce699159 100644
+--- a/sysdeps/unix/sysv/linux/mips/vfork.S
++++ b/sysdeps/unix/sysv/linux/mips/vfork.S
+@@ -106,6 +106,8 @@ L(error):
+ #endif
+ END(__vfork)
+
++#if IS_IN (libc)
+ libc_hidden_def(__vfork)
+ weak_alias (__vfork, vfork)
+ strong_alias (__vfork, __libc_vfork)
++#endif
+--
+2.37.3
+
diff --git a/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch
new file mode 100644
index 000000000..e28c7ae99
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips-linux/patches/glibc/2.23/0002-MIPS-SPARC-more-fixes-to-the-vfork-aliases-in-libpth.patch
@@ -0,0 +1,63 @@
+From b87c1ec3fa398646f042a68f0ce0f7d09c1348c7 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Tue, 21 Jun 2016 23:59:37 +0200
+Subject: [PATCH 2/2] MIPS, SPARC: more fixes to the vfork aliases in
+ libpthread.so
+
+Commit 43c29487 tried to fix the vfork aliases in libpthread.so on MIPS
+and SPARC, but failed to do it correctly, introducing an ABI change.
+
+This patch does the remaining changes needed to align the MIPS and SPARC
+vfork implementations with the other architectures. That way the the
+alpha version of pt-vfork.S works correctly for MIPS and SPARC. The
+changes for alpha were done in 82aab97c.
+
+Changelog:
+ * sysdeps/unix/sysv/linux/mips/vfork.S (__vfork): Rename into
+ __libc_vfork.
+ (__vfork) [IS_IN (libc)]: Remove alias.
+ (__libc_vfork) [IS_IN (libc)]: Define as an alias.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise.
+---
+ sysdeps/unix/sysv/linux/mips/vfork.S | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/mips/vfork.S b/sysdeps/unix/sysv/linux/mips/vfork.S
+index c0c0ce699159..1867c8626ebe 100644
+--- a/sysdeps/unix/sysv/linux/mips/vfork.S
++++ b/sysdeps/unix/sysv/linux/mips/vfork.S
+@@ -31,13 +31,13 @@
+ LOCALSZ= 1
+ FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
+ GPOFF= FRAMESZ-(1*SZREG)
+-NESTED(__vfork,FRAMESZ,sp)
++NESTED(__libc_vfork,FRAMESZ,sp)
+ #ifdef __PIC__
+ SETUP_GP
+ #endif
+ PTR_SUBU sp, FRAMESZ
+ cfi_adjust_cfa_offset (FRAMESZ)
+- SETUP_GP64_REG (a5, __vfork)
++ SETUP_GP64_REG (a5, __libc_vfork)
+ #ifdef __PIC__
+ SAVE_GP (GPOFF)
+ #endif
+@@ -104,10 +104,10 @@ L(error):
+ RESTORE_GP64_REG
+ j __syscall_error
+ #endif
+- END(__vfork)
++ END(__libc_vfork)
+
+ #if IS_IN (libc)
+-libc_hidden_def(__vfork)
+-weak_alias (__vfork, vfork)
+-strong_alias (__vfork, __libc_vfork)
++weak_alias (__libc_vfork, vfork)
++strong_alias (__libc_vfork, __vfork)
++libc_hidden_def (__vfork)
+ #endif
+--
+2.37.3
+
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
index fd15dbd22..de862e1df 100644
--- a/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/Dockerfile
@@ -1,30 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++ \
- make \
- ninja-build \
- file \
- curl \
- ca-certificates \
- python3 \
- git \
- cmake \
- sudo \
- gdb \
- xz-utils \
- g++-mips64-linux-gnuabi64 \
- libssl-dev \
- pkg-config
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips64-linux/mips64-linux-gnu.config host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips64-toolchain.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips64-unknown-linux-gnu/bin
+
+ENV \
+ CC_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-gcc \
+ AR_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-ar \
+ CXX_mips64_unknown_linux_gnuabi64=mips64-unknown-linux-gnu-g++
ENV HOSTS=mips64-unknown-linux-gnuabi64
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
new file mode 100755
index 000000000..f554a5f47
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/build-mips64-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/build.log
+ rm /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ set -x
+}
+
+mkdir build
+cd build
+cp ../mips64-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
new file mode 100644
index 000000000..4b1efe24a
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64-linux/mips64-linux-gnu.config
@@ -0,0 +1,741 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+# CT_ARCH_mips_n32 is not set
+CT_ARCH_mips_n64=y
+CT_ARCH_mips_ABI="64"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+CT_ARCH_BE=y
+# CT_ARCH_LE is not set
+CT_ARCH_ENDIAN="big"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips64r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
index 376bdfb4a..b90950f73 100644
--- a/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/Dockerfile
@@ -1,31 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++ \
- make \
- ninja-build \
- file \
- curl \
- ca-certificates \
- python3 \
- git \
- cmake \
- sudo \
- gdb \
- xz-utils \
- g++-mips64el-linux-gnuabi64 \
- libssl-dev \
- pkg-config
+FROM ubuntu:22.04
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mips64el-toolchain.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mips64el-unknown-linux-gnu/bin
+
+ENV \
+ CC_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-gcc \
+ AR_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-ar \
+ CXX_mips64el_unknown_linux_gnuabi64=mips64el-unknown-linux-gnu-g++
ENV HOSTS=mips64el-unknown-linux-gnuabi64
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh b/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
new file mode 100755
index 000000000..1ad406800
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/build-mips64el-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/build.log
+ rm /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ set -x
+}
+
+mkdir build
+cd build
+cp ../mips64el-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
new file mode 100644
index 000000000..baff944cf
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mips64el-linux/mips64el-linux-gnu.config
@@ -0,0 +1,741 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+# CT_ARCH_mips_n32 is not set
+CT_ARCH_mips_n64=y
+CT_ARCH_mips_ABI="64"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_ENDIAN="little"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=64
+# CT_ARCH_32 is not set
+CT_ARCH_64=y
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips64r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
index 70c8b2a96..6cc2de5e4 100644
--- a/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/Dockerfile
@@ -1,30 +1,30 @@
-FROM ubuntu:16.04
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
- g++ \
- make \
- ninja-build \
- file \
- curl \
- ca-certificates \
- python3 \
- git \
- cmake \
- sudo \
- gdb \
- xz-utils \
- g++-mipsel-linux-gnu \
- libssl-dev \
- pkg-config
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-1.24.sh /scripts/
+RUN sh /scripts/crosstool-ng-1.24.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY host-x86_64/dist-mips-linux/patches/ /tmp/patches/
+COPY host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh /tmp/
+RUN su rustbuild -c ./build-mipsel-toolchain.sh
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
-COPY scripts/cmake.sh /scripts/
-RUN /scripts/cmake.sh
+ENV PATH=$PATH:/x-tools/mipsel-unknown-linux-gnu/bin
+
+ENV \
+ CC_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-gcc \
+ AR_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-ar \
+ CXX_mipsel_unknown_linux_gnu=mipsel-unknown-linux-gnu-g++
ENV HOSTS=mipsel-unknown-linux-gnu
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs \
- --set llvm.allow-old-toolchain
+ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh b/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
new file mode 100755
index 000000000..598e48933
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/build-mipsel-toolchain.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+set -ex
+
+hide_output() {
+ set +x
+ on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+ trap "$on_err" ERR
+ bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+ PING_LOOP_PID=$!
+ "$@" &> /tmp/build.log
+ rm /tmp/build.log
+ trap - ERR
+ kill $PING_LOOP_PID
+ set -x
+}
+
+mkdir build
+cd build
+cp ../mipsel-linux-gnu.config .config
+hide_output ct-ng build
+cd ..
+rm -rf build
diff --git a/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
new file mode 100644
index 000000000..adb2da7dd
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-mipsel-linux/mipsel-linux-gnu.config
@@ -0,0 +1,740 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# crosstool-NG Configuration
+#
+CT_CONFIGURE_has_static_link=y
+CT_CONFIGURE_has_cxx11=y
+CT_CONFIGURE_has_wget=y
+CT_CONFIGURE_has_curl=y
+CT_CONFIGURE_has_make_3_81_or_newer=y
+CT_CONFIGURE_has_make_4_0_or_newer=y
+CT_CONFIGURE_has_libtool_2_4_or_newer=y
+CT_CONFIGURE_has_libtoolize_2_4_or_newer=y
+CT_CONFIGURE_has_autoconf_2_65_or_newer=y
+CT_CONFIGURE_has_autoreconf_2_65_or_newer=y
+CT_CONFIGURE_has_automake_1_15_or_newer=y
+CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y
+CT_CONFIGURE_has_python_3_4_or_newer=y
+CT_CONFIGURE_has_bison_2_7_or_newer=y
+CT_CONFIGURE_has_python=y
+CT_CONFIGURE_has_git=y
+CT_CONFIGURE_has_md5sum=y
+CT_CONFIGURE_has_sha1sum=y
+CT_CONFIGURE_has_sha256sum=y
+CT_CONFIGURE_has_sha512sum=y
+CT_CONFIGURE_has_install_with_strip_program=y
+CT_CONFIG_VERSION_CURRENT="3"
+CT_CONFIG_VERSION="3"
+CT_MODULES=y
+
+#
+# Paths and misc options
+#
+
+#
+# crosstool-NG behavior
+#
+# CT_OBSOLETE is not set
+# CT_EXPERIMENTAL is not set
+# CT_DEBUG_CT is not set
+
+#
+# Paths
+#
+CT_LOCAL_TARBALLS_DIR="${HOME}/src"
+CT_SAVE_TARBALLS=y
+# CT_TARBALLS_BUILDROOT_LAYOUT is not set
+CT_WORK_DIR="${CT_TOP_DIR}/.build"
+CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}"
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_RM_RF_PREFIX_DIR=y
+CT_REMOVE_DOCS=y
+CT_INSTALL_LICENSES=y
+CT_PREFIX_DIR_RO=y
+CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y
+# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set
+
+#
+# Downloading
+#
+CT_DOWNLOAD_AGENT_WGET=y
+# CT_DOWNLOAD_AGENT_CURL is not set
+# CT_DOWNLOAD_AGENT_NONE is not set
+# CT_FORBID_DOWNLOAD is not set
+# CT_FORCE_DOWNLOAD is not set
+CT_CONNECT_TIMEOUT=10
+CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary"
+# CT_ONLY_DOWNLOAD is not set
+CT_USE_MIRROR=y
+# CT_FORCE_MIRROR is not set
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_VERIFY_DOWNLOAD_DIGEST=y
+CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set
+# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set
+CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512"
+# CT_VERIFY_DOWNLOAD_SIGNATURE is not set
+
+#
+# Extracting
+#
+# CT_FORCE_EXTRACT is not set
+CT_OVERRIDE_CONFIG_GUESS_SUB=y
+# CT_ONLY_EXTRACT is not set
+# CT_PATCH_BUNDLED is not set
+CT_PATCH_BUNDLED_LOCAL=y
+CT_PATCH_ORDER="bundled,local"
+CT_PATCH_USE_LOCAL=y
+CT_LOCAL_PATCH_DIR="/tmp/patches"
+
+#
+# Build behavior
+#
+CT_PARALLEL_JOBS=0
+CT_LOAD=""
+CT_USE_PIPES=y
+CT_EXTRA_CFLAGS_FOR_BUILD=""
+CT_EXTRA_LDFLAGS_FOR_BUILD=""
+CT_EXTRA_CFLAGS_FOR_HOST=""
+CT_EXTRA_LDFLAGS_FOR_HOST=""
+# CT_CONFIG_SHELL_SH is not set
+# CT_CONFIG_SHELL_ASH is not set
+CT_CONFIG_SHELL_BASH=y
+# CT_CONFIG_SHELL_CUSTOM is not set
+CT_CONFIG_SHELL="${bash}"
+
+#
+# Logging
+#
+# CT_LOG_ERROR is not set
+# CT_LOG_WARN is not set
+# CT_LOG_INFO is not set
+CT_LOG_EXTRA=y
+# CT_LOG_ALL is not set
+# CT_LOG_DEBUG is not set
+CT_LOG_LEVEL_MAX="EXTRA"
+# CT_LOG_SEE_TOOLS_WARN is not set
+CT_LOG_PROGRESS_BAR=y
+CT_LOG_TO_FILE=y
+CT_LOG_FILE_COMPRESS=y
+
+#
+# Target options
+#
+# CT_ARCH_ALPHA is not set
+# CT_ARCH_ARC is not set
+# CT_ARCH_ARM is not set
+# CT_ARCH_AVR is not set
+# CT_ARCH_M68K is not set
+CT_ARCH_MIPS=y
+# CT_ARCH_NIOS2 is not set
+# CT_ARCH_POWERPC is not set
+# CT_ARCH_S390 is not set
+# CT_ARCH_SH is not set
+# CT_ARCH_SPARC is not set
+# CT_ARCH_X86 is not set
+# CT_ARCH_XTENSA is not set
+CT_ARCH="mips"
+CT_ARCH_CHOICE_KSYM="MIPS"
+CT_ARCH_TUNE=""
+CT_ARCH_MIPS_SHOW=y
+
+#
+# Options for mips
+#
+CT_ARCH_MIPS_PKG_KSYM=""
+CT_ARCH_mips_o32=y
+CT_ARCH_mips_ABI="32"
+CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA"
+CT_ARCH_SUFFIX=""
+# CT_OMIT_TARGET_VENDOR is not set
+
+#
+# Generic target options
+#
+# CT_MULTILIB is not set
+CT_DEMULTILIB=y
+CT_ARCH_USE_MMU=y
+CT_ARCH_SUPPORTS_EITHER_ENDIAN=y
+CT_ARCH_DEFAULT_BE=y
+# CT_ARCH_BE is not set
+CT_ARCH_LE=y
+CT_ARCH_ENDIAN="little"
+CT_ARCH_SUPPORTS_32=y
+CT_ARCH_SUPPORTS_64=y
+CT_ARCH_DEFAULT_32=y
+CT_ARCH_BITNESS=32
+CT_ARCH_32=y
+# CT_ARCH_64 is not set
+
+#
+# Target optimisations
+#
+CT_ARCH_SUPPORTS_WITH_ARCH=y
+CT_ARCH_SUPPORTS_WITH_TUNE=y
+CT_ARCH_SUPPORTS_WITH_FLOAT=y
+CT_ARCH_ARCH="mips32r2"
+CT_ARCH_FLOAT_AUTO=y
+# CT_ARCH_FLOAT_HW is not set
+# CT_ARCH_FLOAT_SW is not set
+CT_TARGET_CFLAGS=""
+CT_TARGET_LDFLAGS=""
+CT_ARCH_FLOAT="auto"
+
+#
+# Toolchain options
+#
+
+#
+# General toolchain options
+#
+CT_FORCE_SYSROOT=y
+CT_USE_SYSROOT=y
+CT_SYSROOT_NAME="sysroot"
+CT_SYSROOT_DIR_PREFIX=""
+CT_WANTS_STATIC_LINK=y
+CT_WANTS_STATIC_LINK_CXX=y
+# CT_STATIC_TOOLCHAIN is not set
+CT_SHOW_CT_VERSION=y
+CT_TOOLCHAIN_PKGVERSION=""
+CT_TOOLCHAIN_BUGURL=""
+
+#
+# Tuple completion and aliasing
+#
+CT_TARGET_VENDOR="unknown"
+CT_TARGET_ALIAS_SED_EXPR=""
+CT_TARGET_ALIAS=""
+
+#
+# Toolchain type
+#
+CT_CROSS=y
+# CT_CANADIAN is not set
+CT_TOOLCHAIN_TYPE="cross"
+
+#
+# Build system
+#
+CT_BUILD=""
+CT_BUILD_PREFIX=""
+CT_BUILD_SUFFIX=""
+
+#
+# Misc options
+#
+# CT_TOOLCHAIN_ENABLE_NLS is not set
+
+#
+# Operating System
+#
+CT_KERNEL_SUPPORTS_SHARED_LIBS=y
+# CT_KERNEL_BARE_METAL is not set
+CT_KERNEL_LINUX=y
+CT_KERNEL="linux"
+CT_KERNEL_CHOICE_KSYM="LINUX"
+CT_KERNEL_LINUX_SHOW=y
+
+#
+# Options for linux
+#
+CT_KERNEL_LINUX_PKG_KSYM="LINUX"
+CT_LINUX_DIR_NAME="linux"
+CT_LINUX_PKG_NAME="linux"
+CT_LINUX_SRC_RELEASE=y
+CT_LINUX_PATCH_ORDER="global"
+# CT_LINUX_V_4_20 is not set
+# CT_LINUX_V_4_19 is not set
+# CT_LINUX_V_4_18 is not set
+# CT_LINUX_V_4_17 is not set
+# CT_LINUX_V_4_16 is not set
+# CT_LINUX_V_4_15 is not set
+# CT_LINUX_V_4_14 is not set
+# CT_LINUX_V_4_13 is not set
+# CT_LINUX_V_4_12 is not set
+# CT_LINUX_V_4_11 is not set
+# CT_LINUX_V_4_10 is not set
+# CT_LINUX_V_4_9 is not set
+CT_LINUX_V_4_4=y
+# CT_LINUX_V_4_1 is not set
+# CT_LINUX_V_3_16 is not set
+# CT_LINUX_V_3_13 is not set
+# CT_LINUX_V_3_12 is not set
+# CT_LINUX_V_3_10 is not set
+# CT_LINUX_V_3_4 is not set
+# CT_LINUX_V_3_2 is not set
+# CT_LINUX_V_2_6_32 is not set
+# CT_LINUX_NO_VERSIONS is not set
+CT_LINUX_VERSION="4.4.174"
+CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})"
+CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign"
+CT_LINUX_4_8_or_older=y
+CT_LINUX_older_than_4_8=y
+CT_LINUX_later_than_3_7=y
+CT_LINUX_3_7_or_later=y
+CT_LINUX_later_than_3_2=y
+CT_LINUX_3_2_or_later=y
+CT_KERNEL_LINUX_VERBOSITY_0=y
+# CT_KERNEL_LINUX_VERBOSITY_1 is not set
+# CT_KERNEL_LINUX_VERBOSITY_2 is not set
+CT_KERNEL_LINUX_VERBOSE_LEVEL=0
+CT_KERNEL_LINUX_INSTALL_CHECK=y
+CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS"
+
+#
+# Common kernel options
+#
+CT_SHARED_LIBS=y
+
+#
+# Binary utilities
+#
+CT_ARCH_BINFMT_ELF=y
+CT_BINUTILS_BINUTILS=y
+CT_BINUTILS="binutils"
+CT_BINUTILS_CHOICE_KSYM="BINUTILS"
+CT_BINUTILS_BINUTILS_SHOW=y
+
+#
+# Options for binutils
+#
+CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS"
+CT_BINUTILS_DIR_NAME="binutils"
+CT_BINUTILS_USE_GNU=y
+CT_BINUTILS_USE="BINUTILS"
+CT_BINUTILS_PKG_NAME="binutils"
+CT_BINUTILS_SRC_RELEASE=y
+CT_BINUTILS_PATCH_ORDER="global"
+CT_BINUTILS_V_2_32=y
+# CT_BINUTILS_V_2_31 is not set
+# CT_BINUTILS_V_2_30 is not set
+# CT_BINUTILS_V_2_29 is not set
+# CT_BINUTILS_V_2_28 is not set
+# CT_BINUTILS_V_2_27 is not set
+# CT_BINUTILS_V_2_26 is not set
+# CT_BINUTILS_NO_VERSIONS is not set
+CT_BINUTILS_VERSION="2.32"
+CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)"
+CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig"
+CT_BINUTILS_later_than_2_30=y
+CT_BINUTILS_2_30_or_later=y
+CT_BINUTILS_later_than_2_27=y
+CT_BINUTILS_2_27_or_later=y
+CT_BINUTILS_later_than_2_25=y
+CT_BINUTILS_2_25_or_later=y
+CT_BINUTILS_later_than_2_23=y
+CT_BINUTILS_2_23_or_later=y
+
+#
+# GNU binutils
+#
+CT_BINUTILS_HAS_HASH_STYLE=y
+CT_BINUTILS_HAS_GOLD=y
+CT_BINUTILS_HAS_PLUGINS=y
+CT_BINUTILS_HAS_PKGVERSION_BUGURL=y
+CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y
+CT_BINUTILS_LINKER_LD=y
+CT_BINUTILS_LINKERS_LIST="ld"
+CT_BINUTILS_LINKER_DEFAULT="bfd"
+# CT_BINUTILS_PLUGINS is not set
+CT_BINUTILS_RELRO=m
+CT_BINUTILS_EXTRA_CONFIG_ARRAY=""
+# CT_BINUTILS_FOR_TARGET is not set
+CT_ALL_BINUTILS_CHOICES="BINUTILS"
+
+#
+# C-library
+#
+CT_LIBC_GLIBC=y
+# CT_LIBC_UCLIBC is not set
+CT_LIBC="glibc"
+CT_LIBC_CHOICE_KSYM="GLIBC"
+CT_THREADS="nptl"
+CT_LIBC_GLIBC_SHOW=y
+
+#
+# Options for glibc
+#
+CT_LIBC_GLIBC_PKG_KSYM="GLIBC"
+CT_GLIBC_DIR_NAME="glibc"
+CT_GLIBC_USE_GNU=y
+CT_GLIBC_USE="GLIBC"
+CT_GLIBC_PKG_NAME="glibc"
+CT_GLIBC_SRC_RELEASE=y
+CT_GLIBC_PATCH_ORDER="global"
+# CT_GLIBC_V_2_29 is not set
+# CT_GLIBC_V_2_28 is not set
+# CT_GLIBC_V_2_27 is not set
+# CT_GLIBC_V_2_26 is not set
+# CT_GLIBC_V_2_25 is not set
+# CT_GLIBC_V_2_24 is not set
+CT_GLIBC_V_2_23=y
+# CT_GLIBC_V_2_19 is not set
+# CT_GLIBC_V_2_17 is not set
+# CT_GLIBC_V_2_12_1 is not set
+# CT_GLIBC_NO_VERSIONS is not set
+CT_GLIBC_VERSION="2.23"
+CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)"
+CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_GLIBC_SIGNATURE_FORMAT="packed/.sig"
+CT_GLIBC_2_29_or_older=y
+CT_GLIBC_older_than_2_29=y
+CT_GLIBC_2_27_or_older=y
+CT_GLIBC_older_than_2_27=y
+CT_GLIBC_2_26_or_older=y
+CT_GLIBC_older_than_2_26=y
+CT_GLIBC_2_25_or_older=y
+CT_GLIBC_older_than_2_25=y
+CT_GLIBC_2_24_or_older=y
+CT_GLIBC_older_than_2_24=y
+CT_GLIBC_2_23_or_later=y
+CT_GLIBC_2_23_or_older=y
+CT_GLIBC_later_than_2_20=y
+CT_GLIBC_2_20_or_later=y
+CT_GLIBC_later_than_2_17=y
+CT_GLIBC_2_17_or_later=y
+CT_GLIBC_later_than_2_14=y
+CT_GLIBC_2_14_or_later=y
+CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y
+CT_GLIBC_DEP_BINUTILS=y
+CT_GLIBC_DEP_GCC=y
+CT_GLIBC_DEP_PYTHON=y
+CT_GLIBC_HAS_LIBIDN_ADDON=y
+# CT_GLIBC_USE_LIBIDN_ADDON is not set
+CT_GLIBC_NO_SPARC_V8=y
+CT_GLIBC_HAS_OBSOLETE_RPC=y
+CT_GLIBC_EXTRA_CONFIG_ARRAY=""
+CT_GLIBC_CONFIGPARMS=""
+CT_GLIBC_EXTRA_CFLAGS=""
+CT_GLIBC_ENABLE_OBSOLETE_RPC=y
+# CT_GLIBC_DISABLE_VERSIONING is not set
+CT_GLIBC_OLDEST_ABI=""
+CT_GLIBC_FORCE_UNWIND=y
+# CT_GLIBC_LOCALES is not set
+# CT_GLIBC_KERNEL_VERSION_NONE is not set
+CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y
+# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set
+CT_GLIBC_MIN_KERNEL="4.4.174"
+CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC"
+CT_LIBC_SUPPORT_THREADS_ANY=y
+CT_LIBC_SUPPORT_THREADS_NATIVE=y
+
+#
+# Common C library options
+#
+CT_THREADS_NATIVE=y
+# CT_CREATE_LDSO_CONF is not set
+CT_LIBC_XLDD=y
+
+#
+# C compiler
+#
+CT_CC_CORE_PASSES_NEEDED=y
+CT_CC_CORE_PASS_1_NEEDED=y
+CT_CC_CORE_PASS_2_NEEDED=y
+CT_CC_SUPPORT_CXX=y
+CT_CC_SUPPORT_FORTRAN=y
+CT_CC_SUPPORT_ADA=y
+CT_CC_SUPPORT_OBJC=y
+CT_CC_SUPPORT_OBJCXX=y
+CT_CC_SUPPORT_GOLANG=y
+CT_CC_GCC=y
+CT_CC="gcc"
+CT_CC_CHOICE_KSYM="GCC"
+CT_CC_GCC_SHOW=y
+
+#
+# Options for gcc
+#
+CT_CC_GCC_PKG_KSYM="GCC"
+CT_GCC_DIR_NAME="gcc"
+CT_GCC_USE_GNU=y
+CT_GCC_USE="GCC"
+CT_GCC_PKG_NAME="gcc"
+CT_GCC_SRC_RELEASE=y
+CT_GCC_PATCH_ORDER="global"
+CT_GCC_V_8=y
+# CT_GCC_V_7 is not set
+# CT_GCC_V_6 is not set
+# CT_GCC_V_5 is not set
+# CT_GCC_V_4_9 is not set
+# CT_GCC_NO_VERSIONS is not set
+CT_GCC_VERSION="8.3.0"
+CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})"
+CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_GCC_SIGNATURE_FORMAT=""
+CT_GCC_later_than_7=y
+CT_GCC_7_or_later=y
+CT_GCC_later_than_6=y
+CT_GCC_6_or_later=y
+CT_GCC_later_than_5=y
+CT_GCC_5_or_later=y
+CT_GCC_later_than_4_9=y
+CT_GCC_4_9_or_later=y
+CT_GCC_later_than_4_8=y
+CT_GCC_4_8_or_later=y
+CT_CC_GCC_HAS_LIBMPX=y
+CT_CC_GCC_ENABLE_CXX_FLAGS=""
+CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY=""
+CT_CC_GCC_EXTRA_CONFIG_ARRAY="--with-fp-32=xx --with-odd-spreg-32=no"
+CT_CC_GCC_STATIC_LIBSTDCXX=y
+# CT_CC_GCC_SYSTEM_ZLIB is not set
+CT_CC_GCC_CONFIG_TLS=m
+
+#
+# Optimisation features
+#
+CT_CC_GCC_USE_GRAPHITE=y
+CT_CC_GCC_USE_LTO=y
+
+#
+# Settings for libraries running on target
+#
+CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y
+# CT_CC_GCC_LIBMUDFLAP is not set
+# CT_CC_GCC_LIBGOMP is not set
+# CT_CC_GCC_LIBSSP is not set
+# CT_CC_GCC_LIBQUADMATH is not set
+# CT_CC_GCC_LIBSANITIZER is not set
+
+#
+# Misc. obscure options.
+#
+CT_CC_CXA_ATEXIT=y
+# CT_CC_GCC_DISABLE_PCH is not set
+CT_CC_GCC_SJLJ_EXCEPTIONS=m
+CT_CC_GCC_LDBL_128=m
+# CT_CC_GCC_BUILD_ID is not set
+CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y
+# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set
+# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set
+# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set
+CT_CC_GCC_LNK_HASH_STYLE=""
+CT_CC_GCC_DEC_FLOAT_AUTO=y
+# CT_CC_GCC_DEC_FLOAT_BID is not set
+# CT_CC_GCC_DEC_FLOAT_DPD is not set
+# CT_CC_GCC_DEC_FLOATS_NO is not set
+CT_CC_GCC_HAS_ARCH_OPTIONS=y
+
+#
+# archictecture-specific options
+#
+CT_CC_GCC_mips_llsc=m
+CT_CC_GCC_mips_synci=m
+# CT_CC_GCC_mips_plt is not set
+CT_ALL_CC_CHOICES="GCC"
+
+#
+# Additional supported languages:
+#
+CT_CC_LANG_CXX=y
+# CT_CC_LANG_FORTRAN is not set
+
+#
+# Debug facilities
+#
+# CT_DEBUG_DUMA is not set
+# CT_DEBUG_GDB is not set
+# CT_DEBUG_LTRACE is not set
+# CT_DEBUG_STRACE is not set
+CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE"
+
+#
+# Companion libraries
+#
+# CT_COMPLIBS_CHECK is not set
+# CT_COMP_LIBS_CLOOG is not set
+# CT_COMP_LIBS_EXPAT is not set
+CT_COMP_LIBS_GETTEXT=y
+CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT"
+CT_GETTEXT_DIR_NAME="gettext"
+CT_GETTEXT_PKG_NAME="gettext"
+CT_GETTEXT_SRC_RELEASE=y
+CT_GETTEXT_PATCH_ORDER="global"
+CT_GETTEXT_V_0_19_8_1=y
+# CT_GETTEXT_NO_VERSIONS is not set
+CT_GETTEXT_VERSION="0.19.8.1"
+CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)"
+CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz"
+CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_GMP=y
+CT_COMP_LIBS_GMP_PKG_KSYM="GMP"
+CT_GMP_DIR_NAME="gmp"
+CT_GMP_PKG_NAME="gmp"
+CT_GMP_SRC_RELEASE=y
+CT_GMP_PATCH_ORDER="global"
+CT_GMP_V_6_1=y
+# CT_GMP_NO_VERSIONS is not set
+CT_GMP_VERSION="6.1.2"
+CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)"
+CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2"
+CT_GMP_SIGNATURE_FORMAT="packed/.sig"
+CT_GMP_later_than_5_1_0=y
+CT_GMP_5_1_0_or_later=y
+CT_GMP_later_than_5_0_0=y
+CT_GMP_5_0_0_or_later=y
+CT_GMP_REQUIRE_5_0_0_or_later=y
+CT_COMP_LIBS_ISL=y
+CT_COMP_LIBS_ISL_PKG_KSYM="ISL"
+CT_ISL_DIR_NAME="isl"
+CT_ISL_PKG_NAME="isl"
+CT_ISL_SRC_RELEASE=y
+CT_ISL_PATCH_ORDER="global"
+CT_ISL_V_0_20=y
+# CT_ISL_V_0_19 is not set
+# CT_ISL_V_0_18 is not set
+# CT_ISL_V_0_17 is not set
+# CT_ISL_V_0_16 is not set
+# CT_ISL_V_0_15 is not set
+# CT_ISL_NO_VERSIONS is not set
+CT_ISL_VERSION="0.20"
+CT_ISL_MIRRORS="http://isl.gforge.inria.fr"
+CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz"
+CT_ISL_SIGNATURE_FORMAT=""
+CT_ISL_later_than_0_18=y
+CT_ISL_0_18_or_later=y
+CT_ISL_later_than_0_15=y
+CT_ISL_0_15_or_later=y
+CT_ISL_REQUIRE_0_15_or_later=y
+CT_ISL_later_than_0_14=y
+CT_ISL_0_14_or_later=y
+CT_ISL_REQUIRE_0_14_or_later=y
+CT_ISL_later_than_0_13=y
+CT_ISL_0_13_or_later=y
+CT_ISL_later_than_0_12=y
+CT_ISL_0_12_or_later=y
+CT_ISL_REQUIRE_0_12_or_later=y
+# CT_COMP_LIBS_LIBELF is not set
+CT_COMP_LIBS_LIBICONV=y
+CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV"
+CT_LIBICONV_DIR_NAME="libiconv"
+CT_LIBICONV_PKG_NAME="libiconv"
+CT_LIBICONV_SRC_RELEASE=y
+CT_LIBICONV_PATCH_ORDER="global"
+CT_LIBICONV_V_1_15=y
+# CT_LIBICONV_NO_VERSIONS is not set
+CT_LIBICONV_VERSION="1.15"
+CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)"
+CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz"
+CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig"
+CT_COMP_LIBS_MPC=y
+CT_COMP_LIBS_MPC_PKG_KSYM="MPC"
+CT_MPC_DIR_NAME="mpc"
+CT_MPC_PKG_NAME="mpc"
+CT_MPC_SRC_RELEASE=y
+CT_MPC_PATCH_ORDER="global"
+CT_MPC_V_1_1=y
+# CT_MPC_V_1_0 is not set
+# CT_MPC_NO_VERSIONS is not set
+CT_MPC_VERSION="1.1.0"
+CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)"
+CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPC_ARCHIVE_FORMATS=".tar.gz"
+CT_MPC_SIGNATURE_FORMAT="packed/.sig"
+CT_MPC_1_1_0_or_later=y
+CT_MPC_1_1_0_or_older=y
+CT_COMP_LIBS_MPFR=y
+CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR"
+CT_MPFR_DIR_NAME="mpfr"
+CT_MPFR_PKG_NAME="mpfr"
+CT_MPFR_SRC_RELEASE=y
+CT_MPFR_PATCH_ORDER="global"
+CT_MPFR_V_4_0=y
+# CT_MPFR_V_3_1 is not set
+# CT_MPFR_NO_VERSIONS is not set
+CT_MPFR_VERSION="4.0.2"
+CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)"
+CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip"
+CT_MPFR_SIGNATURE_FORMAT="packed/.asc"
+CT_MPFR_later_than_4_0_0=y
+CT_MPFR_4_0_0_or_later=y
+CT_MPFR_later_than_3_0_0=y
+CT_MPFR_3_0_0_or_later=y
+CT_MPFR_REQUIRE_3_0_0_or_later=y
+CT_COMP_LIBS_NCURSES=y
+CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES"
+CT_NCURSES_DIR_NAME="ncurses"
+CT_NCURSES_PKG_NAME="ncurses"
+CT_NCURSES_SRC_RELEASE=y
+CT_NCURSES_PATCH_ORDER="global"
+CT_NCURSES_V_6_1=y
+# CT_NCURSES_V_6_0 is not set
+# CT_NCURSES_NO_VERSIONS is not set
+CT_NCURSES_VERSION="6.1"
+CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)"
+CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_NCURSES_ARCHIVE_FORMATS=".tar.gz"
+CT_NCURSES_SIGNATURE_FORMAT="packed/.sig"
+CT_NCURSES_HOST_CONFIG_ARGS=""
+CT_NCURSES_HOST_DISABLE_DB=y
+CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100"
+CT_NCURSES_TARGET_CONFIG_ARGS=""
+# CT_NCURSES_TARGET_DISABLE_DB is not set
+CT_NCURSES_TARGET_FALLBACKS=""
+CT_COMP_LIBS_ZLIB=y
+CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB"
+CT_ZLIB_DIR_NAME="zlib"
+CT_ZLIB_PKG_NAME="zlib"
+CT_ZLIB_SRC_RELEASE=y
+CT_ZLIB_PATCH_ORDER="global"
+CT_ZLIB_V_1_2_11=y
+# CT_ZLIB_NO_VERSIONS is not set
+CT_ZLIB_VERSION="1.2.11"
+CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}"
+CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}"
+CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz"
+CT_ZLIB_SIGNATURE_FORMAT="packed/.asc"
+CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB"
+CT_LIBICONV_NEEDED=y
+CT_GETTEXT_NEEDED=y
+CT_GMP_NEEDED=y
+CT_MPFR_NEEDED=y
+CT_ISL_NEEDED=y
+CT_MPC_NEEDED=y
+CT_NCURSES_NEEDED=y
+CT_ZLIB_NEEDED=y
+CT_LIBICONV=y
+CT_GETTEXT=y
+CT_GMP=y
+CT_MPFR=y
+CT_ISL=y
+CT_MPC=y
+CT_NCURSES=y
+CT_ZLIB=y
+
+#
+# Companion tools
+#
+# CT_COMP_TOOLS_FOR_HOST is not set
+# CT_COMP_TOOLS_AUTOCONF is not set
+# CT_COMP_TOOLS_AUTOMAKE is not set
+# CT_COMP_TOOLS_BISON is not set
+# CT_COMP_TOOLS_DTC is not set
+# CT_COMP_TOOLS_LIBTOOL is not set
+# CT_COMP_TOOLS_M4 is not set
+# CT_COMP_TOOLS_MAKE is not set
+CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE"
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 126c292b3..8250ec0c3 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -129,4 +129,6 @@ ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
--set target.wasm32-wasi.wasi-root=/wasm32-wasi \
--musl-root-armv7=/musl-armv7
+ENV EXTERNAL_LLVM 1
+
ENV SCRIPT python3 ../x.py dist --host='' --target $TARGETS
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 973c43072..423aba06c 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
@@ -78,11 +78,12 @@ ENV RUST_CONFIGURE_ARGS \
--set llvm.thin-lto=true \
--set llvm.ninja=false \
--set rust.jemalloc \
- --set rust.use-lld=true
+ --set rust.use-lld=true \
+ --set rust.lto=thin
ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \
--host $HOSTS --target $HOSTS \
--include-default-paths \
- build-manifest
+ build-manifest bootstrap
ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
# This is the only builder which will create source tarballs
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
index fa780e1e4..9abfd4e97 100755
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-clang.sh
@@ -22,7 +22,7 @@ INC="/rustroot/include:/usr/include"
# We need compiler-rt for the profile runtime (used later to PGO the LLVM build)
# but sanitizers aren't currently building. Since we don't need those, just
-# disable them.
+# disable them. BOLT is used for optimizing LLVM.
hide_output \
cmake ../llvm \
-DCMAKE_C_COMPILER=/rustroot/bin/gcc \
@@ -36,7 +36,7 @@ hide_output \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
- -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \
+ -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt;bolt" \
-DC_INCLUDE_DIRS="$INC"
hide_output make -j$(nproc)
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
index 23f2215c2..1289f116f 100644
--- 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
@@ -29,6 +29,7 @@ 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
+ENV EXTERNAL_LLVM 1
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
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-13/Dockerfile
index 8f6831bc5..4b89a72ba 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-13/Dockerfile
@@ -40,6 +40,7 @@ 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
+ENV EXTERNAL_LLVM 1
# Using llvm-link-shared due to libffi issues -- see #34486
ENV RUST_CONFIGURE_ARGS \
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 2774f8587..cc96715b2 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.10.0 \ No newline at end of file
+0.12.7 \ No newline at end of file
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
index 0fb8f41a7..80a066cac 100755
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh
@@ -4,7 +4,7 @@ set -eu
X_PY="$1"
-# Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
+# Try to test the toolstate-tracked tools and store the build/test success in the TOOLSTATE_FILE.
set +e
python3 "$X_PY" test --stage 2 --no-fail-fast \
@@ -14,12 +14,19 @@ python3 "$X_PY" test --stage 2 --no-fail-fast \
src/doc/rust-by-example \
src/doc/embedded-book \
src/doc/edition-guide \
- src/tools/miri \
set -e
# debugging: print out the saved toolstates
cat /tmp/toolstate/toolstates.json
+
+# Test remaining tools that must pass.
python3 "$X_PY" test --stage 2 check-tools
python3 "$X_PY" test --stage 2 src/tools/clippy
python3 "$X_PY" test --stage 2 src/tools/rustfmt
+python3 "$X_PY" test --stage 2 src/tools/miri
+# We natively run this script on x86_64-unknown-linux-gnu and x86_64-pc-windows-msvc.
+# Also cover some other targets (on both of these hosts) via cross-testing.
+python3 "$X_PY" test --stage 2 src/tools/miri --target i686-pc-windows-msvc
+#FIXME(https://github.com/rust-lang/rust/issues/103519): macOS testing is currently disabled
+# python3 "$X_PY" test --stage 2 src/tools/miri --target aarch64-apple-darwin
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 6e4b0b0c2..10de2e8d5 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -153,6 +153,10 @@ x--expand-yaml-anchors--remove:
run: src/ci/scripts/install-sccache.sh
<<: *step
+ - name: select Xcode
+ run: src/ci/scripts/select-xcode.sh
+ <<: *step
+
- name: install clang
run: src/ci/scripts/install-clang.sh
<<: *step
@@ -264,6 +268,9 @@ on:
branches:
- "**"
+permissions:
+ contents: read
+
defaults:
run:
# On Linux, macOS, and Windows, use the system-provided bash as the default
@@ -273,6 +280,8 @@ defaults:
jobs:
pr:
+ permissions:
+ actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
<<: *base-ci-job
name: PR
env:
@@ -286,13 +295,15 @@ jobs:
- name: x86_64-gnu-llvm-13
<<: *job-linux-xl
-
+
- name: x86_64-gnu-tools
env:
CI_ONLY_WHEN_SUBMODULES_CHANGED: 1
<<: *job-linux-xl
auto:
+ permissions:
+ actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
<<: *base-ci-job
name: auto
env:
@@ -455,10 +466,11 @@ jobs:
- name: dist-x86_64-apple
env:
- SCRIPT: ./x.py dist --host=x86_64-apple-darwin --target=x86_64-apple-darwin
+ SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
+ SELECT_XCODE: /Applications/Xcode_13.4.1.app
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
@@ -467,10 +479,11 @@ jobs:
- name: dist-apple-various
env:
- SCRIPT: ./x.py dist --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim
+ SCRIPT: ./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim
RUST_CONFIGURE_ARGS: --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
+ SELECT_XCODE: /Applications/Xcode_13.4.1.app
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
@@ -478,10 +491,11 @@ jobs:
- name: dist-x86_64-apple-alt
env:
- SCRIPT: ./x.py dist
+ SCRIPT: ./x.py dist bootstrap --include-default-paths
RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
MACOSX_DEPLOYMENT_TARGET: 10.7
+ SELECT_XCODE: /Applications/Xcode_13.4.1.app
NO_LLVM_ASSERTIONS: 1
NO_DEBUG_ASSERTIONS: 1
NO_OVERFLOW_CHECKS: 1
@@ -508,7 +522,7 @@ jobs:
# This target only needs to support 11.0 and up as nothing else supports the hardware
- name: dist-aarch64-apple
env:
- SCRIPT: ./x.py dist --stage 2
+ SCRIPT: ./x.py dist bootstrap --include-default-paths --stage 2
RUST_CONFIGURE_ARGS: >-
--build=x86_64-apple-darwin
--host=aarch64-apple-darwin
@@ -520,6 +534,7 @@ jobs:
--set rust.jemalloc
--set llvm.ninja=false
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+ SELECT_XCODE: /Applications/Xcode_13.4.1.app
USE_XCODE_CLANG: 1
MACOSX_DEPLOYMENT_TARGET: 11.0
MACOSX_STD_DEPLOYMENT_TARGET: 11.0
@@ -652,7 +667,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
+ SCRIPT: PGO_HOST=x86_64-pc-windows-msvc src/ci/pgo.sh python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-windows-xl
@@ -664,7 +679,7 @@ jobs:
--target=i686-pc-windows-msvc,i586-pc-windows-msvc
--enable-full-tools
--enable-profiler
- SCRIPT: python x.py dist
+ SCRIPT: python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-windows-xl
@@ -675,7 +690,7 @@ jobs:
--host=aarch64-pc-windows-msvc
--enable-full-tools
--enable-profiler
- SCRIPT: python x.py dist
+ SCRIPT: python x.py dist bootstrap --include-default-paths
DIST_REQUIRE_ALL_TOOLS: 1
# Hack around this SDK version, because it doesn't work with clang.
# See https://github.com/rust-lang/rust/issues/88796
@@ -692,14 +707,14 @@ jobs:
# We are intentionally allowing an old toolchain on this builder (and that's
# incompatible with LLVM downloads today).
NO_DOWNLOAD_CI_LLVM: 1
- SCRIPT: python x.py dist
+ SCRIPT: python x.py dist bootstrap --include-default-paths
CUSTOM_MINGW: 1
DIST_REQUIRE_ALL_TOOLS: 1
<<: *job-windows-xl
- name: dist-x86_64-mingw
env:
- SCRIPT: python x.py dist
+ SCRIPT: python x.py dist bootstrap --include-default-paths
RUST_CONFIGURE_ARGS: >-
--build=x86_64-pc-windows-gnu
--enable-full-tools
@@ -715,10 +730,12 @@ jobs:
- name: dist-x86_64-msvc-alt
env:
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler
- SCRIPT: python x.py dist
+ SCRIPT: python x.py dist bootstrap --include-default-paths
<<: *job-windows-xl
try:
+ permissions:
+ actions: write # for rust-lang/simpleinfra/github-actions/cancel-outdated-builds
<<: *base-ci-job
name: try
env:
diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh
index b60b7868d..cbe32920a 100755
--- a/src/ci/pgo.sh
+++ b/src/ci/pgo.sh
@@ -190,11 +190,40 @@ rm -r $RUSTC_PROFILE_DIRECTORY_ROOT
# directories ourselves.
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}
+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
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 9a247fb60..9d98ce224 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -69,6 +69,11 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.codegen-units-std=1"
# space required for CI artifacts.
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --dist-compression-formats=xz"
+# Enable the `c` feature for compiler_builtins, but only when the `compiler-rt` source is available.
+if [ "$EXTERNAL_LLVM" = "" ]; then
+ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.optimized-compiler-builtins"
+fi
+
if [ "$DIST_SRC" = "" ]; then
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src"
fi
diff --git a/src/ci/scripts/select-xcode.sh b/src/ci/scripts/select-xcode.sh
new file mode 100755
index 000000000..3b9c77d42
--- /dev/null
+++ b/src/ci/scripts/select-xcode.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# This script selects the Xcode instance to use.
+
+set -euo pipefail
+IFS=$'\n\t'
+
+source "$(cd "$(dirname "$0")" && pwd)/../shared.sh"
+
+if isMacOS; then
+ if [[ -s "${SELECT_XCODE-}" ]]; then
+ sudo xcode-select -s "${SELECT_XCODE}"
+ fi
+fi
diff --git a/src/ci/scripts/should-skip-this.sh b/src/ci/scripts/should-skip-this.sh
index c863f1b68..a8a189931 100755
--- a/src/ci/scripts/should-skip-this.sh
+++ b/src/ci/scripts/should-skip-this.sh
@@ -18,10 +18,14 @@ if [[ -n "${CI_ONLY_WHEN_SUBMODULES_CHANGED-}" ]]; then
# Submodules pseudo-files inside git have the 160000 permissions, so when
# those files are present in the diff a submodule was updated.
echo "Submodules were updated"
- elif ! git diff --quiet "$BASE_COMMIT" -- src/tools/clippy src/tools/rustfmt; then
+ 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.
- echo "Clippy or rustfmt subtrees were updated"
+ # 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" -- \
src/test/rustdoc-gui \
src/librustdoc \
diff --git a/src/doc/book/ADMIN_TASKS.md b/src/doc/book/ADMIN_TASKS.md
index 7c152577f..2a92eefd2 100644
--- a/src/doc/book/ADMIN_TASKS.md
+++ b/src/doc/book/ADMIN_TASKS.md
@@ -113,7 +113,12 @@ To check, say, updating `mdbook` or changing the way files get included:
## Produce markdown from docx for diffing
-- TODO Carol to document this next time she does it
+- Save the docx file to `tmp/chapterXX.docx`.
+- In Word, go to the review tab, choose "Accept all changes and stop tracking"
+- Save the docx again and close Word
+- Run `./tools/doc-to-md.sh`
+- This should write `nostarch/chapterXX.md`. Adjust the XSL in
+ `tools/doc-to-md.xsl` and run `./tools/doc-to-md.sh` again if needed.
## Generate Graphviz dot
diff --git a/src/doc/book/TODO.md b/src/doc/book/TODO.md
new file mode 100644
index 000000000..b61f85314
--- /dev/null
+++ b/src/doc/book/TODO.md
@@ -0,0 +1,17 @@
+# In each chapter
+
+- [ ] Manual regeneration
+- [ ] Check for upstream changes from last snapshot
+- [ ] Propagate updated output to docx
+- [ ] Extract docx and check diff
+- [ ] Answer all comments
+- [ ] Check cross references
+- [ ] Check indentation of --snip--
+- [ ] Numbered lines, Gray out unchanged lines
+- [ ] Check line wrapping
+- [ ] Check for unneeded command/compiling/running output
+- [ ] Check println style and error messages
+- [ ] Add alt text to images
+- [ ] Index tags
+ - [ ] search for "convention" conventions:naming:of blah
+ - [ ] check for double spaces, spaces at the end of paragraphs
diff --git a/src/doc/book/ci/dictionary.txt b/src/doc/book/ci/dictionary.txt
index 3fe25ff52..9eb695d5b 100644
--- a/src/doc/book/ci/dictionary.txt
+++ b/src/doc/book/ci/dictionary.txt
@@ -537,6 +537,7 @@ uncommenting
unevaluated
Uninstalling
uninstall
+unittests
unix
unpopulated
unoptimized
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock
index 0a2f222c2..edc20385b 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -8,9 +10,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
-version = "0.2.2"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
@@ -26,33 +28,32 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.86"
+version = "0.2.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
+checksum = "505e71a4706fa491e9b1b55f51b95d4037d0821ee40131190475f692b35b009b"
[[package]]
name = "ppv-lite86"
-version = "0.2.10"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
name = "rand_chacha"
-version = "0.3.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@@ -60,24 +61,15 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom",
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
+version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-03/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-04/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
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 62fe8327f..fbc0cec33 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
@@ -5,7 +5,7 @@ $ cargo build
Compiling ppv-lite86 v0.2.10
Compiling rand_core v0.6.2
Compiling rand_chacha v0.3.0
- Compiling rand v0.8.3
+ Compiling rand v0.8.5
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
error[E0308]: mismatched types
--> src/main.rs:22:21
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-05/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/listing-02-06/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-04-looping/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml
+++ b/src/doc/book/listings/ch02-guessing-game-tutorial/no-listing-05-quitting/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs
index 9d3b4813b..77c716c14 100644
--- a/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs
+++ b/src/doc/book/listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs
@@ -10,7 +10,7 @@ fn main() {
// division
let quotient = 56.7 / 32.2;
- let floored = 2 / 3; // Results in 0
+ let truncated = -5 / 3; // Results in -1
// remainder
let remainder = 43 % 5;
diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock
+++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml
index 15b3fffca..d508e9578 100644
--- a/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml
+++ b/src/doc/book/listings/ch07-managing-growing-projects/listing-07-18/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock
+++ b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml
index cc63f6f02..7eda67aea 100644
--- a/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml
+++ b/src/doc/book/listings/ch07-managing-growing-projects/no-listing-01-use-std-unnested/Cargo.toml
@@ -6,4 +6,4 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-04/src/main.rs b/src/doc/book/listings/ch08-common-collections/listing-08-04/src/main.rs
index fa4e090d5..fca332de6 100644
--- a/src/doc/book/listings/ch08-common-collections/listing-08-04/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/listing-08-04/src/main.rs
@@ -3,11 +3,11 @@ fn main() {
let v = vec![1, 2, 3, 4, 5];
let third: &i32 = &v[2];
- println!("The third element is {}", third);
+ println!("The third element is {third}");
let third: Option<&i32> = v.get(2);
match third {
- Some(third) => println!("The third element is {}", third),
+ Some(third) => println!("The third element is {third}"),
None => println!("There is no third element."),
}
// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-06/src/main.rs b/src/doc/book/listings/ch08-common-collections/listing-08-06/src/main.rs
index 1b42274a6..653ac27b0 100644
--- a/src/doc/book/listings/ch08-common-collections/listing-08-06/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/listing-08-06/src/main.rs
@@ -6,6 +6,6 @@ fn main() {
v.push(6);
- println!("The first element is: {}", first);
+ println!("The first element is: {first}");
// ANCHOR_END: here
}
diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-07/src/main.rs b/src/doc/book/listings/ch08-common-collections/listing-08-07/src/main.rs
index 38b97784b..aebf855a9 100644
--- a/src/doc/book/listings/ch08-common-collections/listing-08-07/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/listing-08-07/src/main.rs
@@ -2,7 +2,7 @@ fn main() {
// ANCHOR: here
let v = vec![100, 32, 57];
for i in &v {
- println!("{}", i);
+ println!("{i}");
}
// ANCHOR_END: here
}
diff --git a/src/doc/book/listings/ch08-common-collections/listing-08-16/src/main.rs b/src/doc/book/listings/ch08-common-collections/listing-08-16/src/main.rs
index 8938dc143..db57cddba 100644
--- a/src/doc/book/listings/ch08-common-collections/listing-08-16/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/listing-08-16/src/main.rs
@@ -3,6 +3,6 @@ fn main() {
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
- println!("s2 is {}", s2);
+ println!("s2 is {s2}");
// ANCHOR_END: here
}
diff --git a/src/doc/book/listings/ch08-common-collections/no-listing-02-format/src/main.rs b/src/doc/book/listings/ch08-common-collections/no-listing-02-format/src/main.rs
index 4a38e63d2..db408e2b7 100644
--- a/src/doc/book/listings/ch08-common-collections/no-listing-02-format/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/no-listing-02-format/src/main.rs
@@ -4,6 +4,6 @@ fn main() {
let s2 = String::from("tac");
let s3 = String::from("toe");
- let s = format!("{}-{}-{}", s1, s2, s3);
+ let s = format!("{s1}-{s2}-{s3}");
// ANCHOR_END: here
}
diff --git a/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs b/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs
index 2e7dc02e6..bb13c86f1 100644
--- a/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs
+++ b/src/doc/book/listings/ch08-common-collections/no-listing-03-iterate-over-hashmap/src/main.rs
@@ -8,7 +8,7 @@ fn main() {
scores.insert(String::from("Yellow"), 50);
for (key, value) in &scores {
- println!("{}: {}", key, value);
+ println!("{key}: {value}");
}
// ANCHOR_END: here
}
diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-07/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-07/src/main.rs
index f4564f670..0295949d2 100644
--- a/src/doc/book/listings/ch09-error-handling/listing-09-07/src/main.rs
+++ b/src/doc/book/listings/ch09-error-handling/listing-09-07/src/main.rs
@@ -1,7 +1,6 @@
// ANCHOR: here
use std::fs::File;
-use std::io;
-use std::io::Read;
+use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username_file = File::open("hello.txt")?;
diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-08/src/main.rs b/src/doc/book/listings/ch09-error-handling/listing-09-08/src/main.rs
index c3c6e23ef..ca672caad 100644
--- a/src/doc/book/listings/ch09-error-handling/listing-09-08/src/main.rs
+++ b/src/doc/book/listings/ch09-error-handling/listing-09-08/src/main.rs
@@ -1,7 +1,6 @@
// ANCHOR: here
use std::fs::File;
-use std::io;
-use std::io::Read;
+use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username = String::new();
diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock
+++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml
index 15b3fffca..d508e9578 100644
--- a/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml
+++ b/src/doc/book/listings/ch09-error-handling/listing-09-13/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock
index 0a2f222c2..2ae9e459e 100644
--- a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock
+++ b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -38,14 +40,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -68,15 +69,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml
index 15b3fffca..d508e9578 100644
--- a/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml
+++ b/src/doc/book/listings/ch09-error-handling/no-listing-09-guess-out-of-range/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock
index d37189b33..8b8c69d33 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock
+++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.lock
@@ -1,6 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "adder"
version = "0.1.0"
-
diff --git a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml
index e61cb12e3..b7d36d44c 100644
--- a/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml
+++ b/src/doc/book/listings/ch11-writing-automated-tests/listing-11-01/Cargo.toml
@@ -3,4 +3,6 @@ name = "adder"
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/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock
index eec3a9e4b..bf6974b58 100644
--- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock
+++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "add_one"
version = "0.1.0"
@@ -45,14 +47,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -75,15 +76,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml
index fd4942ace..bc758bd88 100644
--- a/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml
+++ b/src/doc/book/listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock
index eec3a9e4b..bf6974b58 100644
--- a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock
+++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "add_one"
version = "0.1.0"
@@ -45,14 +47,13 @@ checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
[[package]]
name = "rand"
-version = "0.8.3"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
- "rand_hc",
]
[[package]]
@@ -75,15 +76,6 @@ dependencies = [
]
[[package]]
-name = "rand_hc"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml
index fd4942ace..bc758bd88 100644
--- a/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml
+++ b/src/doc/book/listings/ch14-more-about-cargo/output-only-03-use-rand/add/add_one/Cargo.toml
@@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs
index 8d445d9b9..b71da9a37 100644
--- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs
+++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-14/src/main.rs
@@ -8,9 +8,11 @@ fn main() {
let p = Point { x: 0, y: 7 };
match p {
- Point { x, y: 0 } => println!("On the x axis at {}", x),
- Point { x: 0, y } => println!("On the y axis at {}", y),
- Point { x, y } => println!("On neither axis: ({}, {})", x, y),
+ Point { x, y: 0 } => println!("On the x axis at {x}"),
+ Point { x: 0, y } => println!("On the y axis at {y}"),
+ Point { x, y } => {
+ println!("On neither axis: ({x}, {y})");
+ }
}
}
// ANCHOR_END: here
diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs
index 9b8dac193..4ddef0aaf 100644
--- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs
+++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-15/src/main.rs
@@ -10,18 +10,18 @@ fn main() {
match msg {
Message::Quit => {
- println!("The Quit variant has no data to destructure.")
+ println!("The Quit variant has no data to destructure.");
}
Message::Move { x, y } => {
println!(
- "Move in the x direction {} and in the y direction {}",
- x, y
+ "Move in the x direction {x} and in the y direction {y}"
);
}
- Message::Write(text) => println!("Text message: {}", text),
+ Message::Write(text) => {
+ println!("Text message: {text}");
+ }
Message::ChangeColor(r, g, b) => println!(
- "Change the color to red {}, green {}, and blue {}",
- r, g, b
+ "Change the color to red {r}, green {g}, and blue {b}",
),
}
}
diff --git a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs
index ed6a20bf4..4c958601b 100644
--- a/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs
+++ b/src/doc/book/listings/ch18-patterns-and-matching/listing-18-16/src/main.rs
@@ -14,13 +14,11 @@ fn main() {
let msg = Message::ChangeColor(Color::Hsv(0, 160, 255));
match msg {
- Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
- "Change the color to red {}, green {}, and blue {}",
- r, g, b
- ),
+ Message::ChangeColor(Color::Rgb(r, g, b)) => {
+ println!("Change color to red {r}, green {g}, and blue {b}");
+ }
Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
- "Change the color to hue {}, saturation {}, and value {}",
- h, s, v
+ "Change color to hue {h}, saturation {s}, value {v}"
),
_ => (),
}
diff --git a/src/doc/book/nostarch/acknowledgments.md b/src/doc/book/nostarch/acknowledgments.md
index 89d4adffc..c29cb712a 100644
--- a/src/doc/book/nostarch/acknowledgments.md
+++ b/src/doc/book/nostarch/acknowledgments.md
@@ -12,8 +12,6 @@ Karen Rustad Tölva for the cover art. Thank you to our team at No Starch,
including Bill Pollock, Liz Chadwick, and Janelle Ludowise, for improving this
book and bringing it to print.
-<!--Insert Steve's acknowledgements here -->
-
Carol is grateful for the opportunity to work on this book. She thanks her
family for their constant love and support, especially her husband Jake
Goulding and her daughter Vivian.
diff --git a/src/doc/book/nostarch/appendix.md b/src/doc/book/nostarch/appendix.md
index 1722a9345..98432a1da 100644
--- a/src/doc/book/nostarch/appendix.md
+++ b/src/doc/book/nostarch/appendix.md
@@ -8,77 +8,67 @@ directory, so all fixes need to be made in `/src/`.
## Appendix A: Keywords
-The following list contains keywords that are reserved for current or future
+The following lists contain keywords that are reserved for current or future
use by the Rust language. As such, they cannot be used as identifiers (except
-as raw identifiers as we’ll discuss in the “Raw Identifiers” section).
-Identifiers are names of functions, variables, parameters, struct fields,
+as raw identifiers, as we’ll discuss in “Raw Identifiers” on page XX).
+*Identifiers* are names of functions, variables, parameters, struct fields,
modules, crates, constants, macros, static values, attributes, types, traits,
or lifetimes.
-### Keywords Currently in Use
+## Keywords Currently in Use
The following is a list of keywords currently in use, with their functionality
described.
-* `as` - perform primitive casting, disambiguate the specific trait containing
- an item, or rename items in `use` statements
-
-<!-- `extern crate` is a bit old. Not sure if it needs a mention
-/JT -->
-<!-- good call, took it out /Carol -->
-
-* `async` - return a `Future` instead of blocking the current thread
-* `await` - suspend execution until the result of a `Future` is ready
-* `break` - exit a loop immediately
-* `const` - define constant items or constant raw pointers
-* `continue` - continue to the next loop iteration
-* `crate` - in a module path, refers to the crate root
-<!-- these days `crate` is mostly just used as part of the module path
-/JT -->
-<!-- fixed! /Carol -->
-
-* `dyn` - dynamic dispatch to a trait object
-* `else` - fallback for `if` and `if let` control flow constructs
-* `enum` - define an enumeration
-* `extern` - link an external function or variable
-<!-- `extern crate` is a bit out of date
-/JT -->
-<!-- fixed! /Carol -->
-
-* `false` - Boolean false literal
-* `fn` - define a function or the function pointer type
-* `for` - loop over items from an iterator, implement a trait, or specify a
- higher-ranked lifetime
-* `if` - branch based on the result of a conditional expression
-* `impl` - implement inherent or trait functionality
-* `in` - part of `for` loop syntax
-* `let` - bind a variable
-* `loop` - loop unconditionally
-* `match` - match a value to patterns
-* `mod` - define a module
-* `move` - make a closure take ownership of all its captures
-* `mut` - denote mutability in references, raw pointers, or pattern bindings
-* `pub` - denote public visibility in struct fields, `impl` blocks, or modules
-* `ref` - bind by reference
-* `return` - return from function
-* `Self` - a type alias for the type we are defining or implementing
-* `self` - method subject or current module
-* `static` - global variable or lifetime lasting the entire program execution
-* `struct` - define a structure
-* `super` - parent module of the current module
-* `trait` - define a trait
-* `true` - Boolean true literal
-* `type` - define a type alias or associated type
-* `union` - define a union; is only a keyword when used in a union declaration
-* `unsafe` - denote unsafe code, functions, traits, or implementations
-* `use` - bring symbols into scope
-* `where` - denote clauses that constrain a type
-* `while` - loop conditionally based on the result of an expression
-
-### Keywords Reserved for Future Use
+* **`as` **: perform primitive casting, disambiguate the specific trait
+containing an item, or rename items in `use` statements
+* **`async` **: return a `Future` instead of blocking the current thread
+* **`await` **: suspend execution until the result of a `Future` is ready
+* **`break` **: exit a loop immediately
+* **`const` **: define constant items or constant raw pointers
+* **`continue` **: continue to the next loop iteration
+* **`crate` **: in a module path, refers to the crate root
+* **`dyn` **: dynamic dispatch to a trait object
+* **`else` **: fallback for `if` and `if let` control flow constructs
+* **`enum` **: define an enumeration
+* **`extern` **: link an external function or variable
+* **`false` **: Boolean false literal
+* **`fn` **: define a function or the function pointer type
+* **`for` **: loop over items from an iterator, implement a trait, or specify a
+higher-ranked lifetime
+* **`if` **: branch based on the result of a conditional expression
+* **`impl` **: implement inherent or trait functionality
+* **`in` **: part of `for` loop syntax
+* **`let` **: bind a variable
+* **`loop` **: loop unconditionally
+* **`match` **: match a value to patterns
+* **`mod` **: define a module
+* **`move` **: make a closure take ownership of all its captures
+* **`mut` **: denote mutability in references, raw pointers, or pattern bindings
+* **`pub` **: denote public visibility in struct fields, `impl` blocks, or
+modules
+* **`ref` **: bind by reference
+* **`return` **: return from function
+* **`Self` **: a type alias for the type we are defining or implementing
+* **`self` **: method subject or current module
+* **`static` **: global variable or lifetime lasting the entire program
+execution
+* **`struct` **: define a structure
+* **`super` **: parent module of the current module
+* **`trait` **: define a trait
+* **`true` **: Boolean true literal
+* **`type` **: define a type alias or associated type
+* **`union` **: define a union; is a keyword only when used in a union
+declaration
+* **`unsafe` **: denote unsafe code, functions, traits, or implementations
+* **`use` **: bring symbols into scope
+* **`where` **: denote clauses that constrain a type
+* **`while` **: loop conditionally based on the result of an expression
+
+## Keywords Reserved for Future Use
The following keywords do not yet have any functionality but are reserved by
-Rust for potential future use.
+Rust for potential future use:
* `abstract`
* `become`
@@ -94,7 +84,7 @@ Rust for potential future use.
* `virtual`
* `yield`
-### Raw Identifiers
+## Raw Identifiers
*Raw identifiers* are the syntax that lets you use keywords where they wouldn’t
normally be allowed. You use a raw identifier by prefixing a keyword with `r#`.
@@ -145,10 +135,10 @@ choose identifier names, as well as lets us integrate with programs written in
a language where these words aren’t keywords. In addition, raw identifiers
allow you to use libraries written in a different Rust edition than your crate
uses. For example, `try` isn’t a keyword in the 2015 edition but is in the 2018
-edition. If you depend on a library that’s written using the 2015 edition and
-has a `try` function, you’ll need to use the raw identifier syntax, `r#try` in
-this case, to call that function from your 2018 edition code. See Appendix E
-for more information on editions.
+and 2021 editions. If you depend on a library that is written using the 2015
+edition and has a `try` function, you’ll need to use the raw identifier syntax,
+`r#try` in this case, to call that function from your 2021 edition code. See
+Appendix E for more information on editions.
## Appendix B: Operators and Symbols
@@ -156,7 +146,7 @@ This appendix contains a glossary of Rust’s syntax, including operators and
other symbols that appear by themselves or in the context of paths, generics,
trait bounds, macros, attributes, comments, tuples, and brackets.
-### Operators
+## Operators
Table B-1 contains the operators in Rust, an example of how the operator would
appear in context, a short explanation, and whether that operator is
@@ -166,66 +156,72 @@ overload that operator is listed.
Table B-1: Operators
| Operator | Example | Explanation | Overloadable? |
-|----------|---------|-------------|---------------|
-| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | Macro expansion | |
+|---|---|---|---|
+| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | Macro expansion | |
| `!` | `!expr` | Bitwise or logical complement | `Not` |
| `!=` | `expr != expr` | Nonequality comparison | `PartialEq` |
-| `%` | `expr % expr` | Arithmetic remainder | `Rem` |
+| `% | `expr % expr` | Arithmetic remainder | `Rem` |
| `%=` | `var %= expr` | Arithmetic remainder and assignment | `RemAssign` |
-| `&` | `&expr`, `&mut expr` | Borrow | |
-| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | Borrowed pointer type | |
+| `& | `&expr`, `&mut expr` | Borrow | |
+| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | Borrowed pointer
+type | |
| `&` | `expr & expr` | Bitwise AND | `BitAnd` |
| `&=` | `var &= expr` | Bitwise AND and assignment | `BitAndAssign` |
-| `&&` | `expr && expr` | Short-circuiting logical AND | |
-| `*` | `expr * expr` | Arithmetic multiplication | `Mul` |
-| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign` |
+| `&&` | `expr && expr` | Short-circuiting logical AND | |
+| `* | `expr * expr` | Arithmetic multiplication | `Mul` |
+| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign`
+|
| `*` | `*expr` | Dereference | `Deref` |
-| `*` | `*const type`, `*mut type` | Raw pointer | |
-| `+` | `trait + trait`, `'a + trait` | Compound type constraint | |
-| `+` | `expr + expr` | Arithmetic addition | `Add` |
+| `*` | `*const type`, `*mut type | Raw pointer | |
+| `+ | `trait + trait`, `'a + trait` | Compound type constraint | |
+| `+ | `expr + expr` | Arithmetic addition | `Add` |
| `+=` | `var += expr` | Arithmetic addition and assignment | `AddAssign` |
-| `,` | `expr, expr` | Argument and element separator | |
-| `-` | `- expr` | Arithmetic negation | `Neg` |
-| `-` | `expr - expr` | Arithmetic subtraction | `Sub` |
+| `,` | `expr, expr` | Argument and element separator | |
+| `- | `- expr` | Arithmetic negation | `Neg` |
+| `- | `expr - expr` | Arithmetic subtraction | `Sub` |
| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` |
-| `->` | `fn(...) -> type`, <code>&vert;...&vert; -> type</code> | Function and closure return type | |
-| `.` | `expr.ident` | Member access | |
-| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal | `PartialOrd` |
-| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal | `PartialOrd` |
-| `..` | `..expr` | Struct literal update syntax | |
-| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern binding | |
-| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern: inclusive range pattern | |
-| `/` | `expr / expr` | Arithmetic division | `Div` |
+| `-> | `fn(...) -> type`, `|…| -> type` | Function and closure return type | |
+| `. | `expr.ident` | Member access | |
+| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal
+| `PartialOrd` |
+| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal |
+`PartialOrd` |
+| `..` | `..expr` | Struct literal update syntax | |
+| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern
+binding | |
+| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern:
+inclusive range pattern | |
+| `/ | `expr / expr` | Arithmetic division | `Div` |
| `/=` | `var /= expr` | Arithmetic division and assignment | `DivAssign` |
-| `:` | `pat: type`, `ident: type` | Constraints | |
-| `:` | `ident: expr` | Struct field initializer | |
-| `:` | `'a: loop {...}` | Loop label | |
-| `;` | `expr;` | Statement and item terminator | |
-| `;` | `[...; len]` | Part of fixed-size array syntax | |
+| `: | `pat: type`, `ident: type` | Constraints | |
+| `:` | `ident: expr` | Struct field initializer | |
+| `:` | `'a: loop {...}` | Loop label | |
+| `; | `expr;` | Statement and item terminator | |
+| `;` | `[...; len]` | Part of fixed-size array syntax | |
| `<<` | `expr << expr` | Left-shift | `Shl` |
| `<<=` | `var <<= expr` | Left-shift and assignment | `ShlAssign` |
| `<` | `expr < expr` | Less than comparison | `PartialOrd` |
| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` |
-| `=` | `var = expr`, `ident = type` | Assignment/equivalence | |
+| `=` | `var = expr`, `ident = type` | Assignment/equivalence | |
| `==` | `expr == expr` | Equality comparison | `PartialEq` |
-| `=>` | `pat => expr` | Part of match arm syntax | |
+| `=>` | `pat => expr` | Part of match arm syntax | |
| `>` | `expr > expr` | Greater than comparison | `PartialOrd` |
| `>=` | `expr >= expr` | Greater than or equal to comparison | `PartialOrd` |
| `>>` | `expr >> expr` | Right-shift | `Shr` |
| `>>=` | `var >>= expr` | Right-shift and assignment | `ShrAssign` |
-| `@` | `ident @ pat` | Pattern binding | |
+| `@ | `ident @ pat` | Pattern binding | |
| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` |
| `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` |
-| <code>&vert;</code> | <code>pat &vert; pat</code> | Pattern alternatives | |
-| <code>&vert;</code> | <code>expr &vert; expr</code> | Bitwise OR | `BitOr` |
-| <code>&vert;=</code> | <code>var &vert;= expr</code> | Bitwise OR and assignment | `BitOrAssign` |
-| <code>&vert;&vert;</code> | <code>expr &vert;&vert; expr</code> | Short-circuiting logical OR | |
-| `?` | `expr?` | Error propagation | |
+| `| | `pat | pat` | Pattern alternatives | |
+| `|` | `expr | expr` | Bitwise OR | `BitOr` |
+| `|=` | `var |= expr` | Bitwise OR and assignment | `BitOrAssign` |
+| `||` | `expr || expr` | Short-circuiting logical OR | |
+| `? | `expr?` | Error propagation | |
-### Non-operator Symbols
+## Non-operator Symbols
-The following list contains all symbols that don’t function as operators;
-that is, they don’t behave like a function or method call.
+The following tables contain all symbols that don’t function as operators; that
+is, they don’t behave like a function or method call.
Table B-2 shows symbols that appear on their own and are valid in a variety of
locations.
@@ -233,18 +229,22 @@ locations.
Table B-2: Stand-Alone Syntax
| Symbol | Explanation |
-|--------|-------------|
-| `'ident` | Named lifetime or loop label |
-| `...u8`, `...i32`, `...f64`, `...usize`, etc. | Numeric literal of specific type |
-| `"..."` | String literal |
-| `r"..."`, `r#"..."#`, `r##"..."##`, etc. | Raw string literal, escape characters not processed |
-| `b"..."` | Byte string literal; constructs an array of bytes instead of a string |
-| `br"..."`, `br#"..."#`, `br##"..."##`, etc. | Raw byte string literal, combination of raw and byte string literal |
-| `'...'` | Character literal |
-| `b'...'` | ASCII byte literal |
-| <code>&vert;...&vert; expr</code> | Closure |
-| `!` | Always empty bottom type for diverging functions |
-| `_` | “Ignored” pattern binding; also used to make integer literals readable |
+|---|---|
+| `'ident | Named lifetime or loop label |
+| `...u8`, `...i32`, `...f64`, `...usize`, and so on | Numeric literal of
+specific type |
+| `"..." | String literal |
+| `r"..."`, `r#"..."#`, `r##"..."##`, and so on | Raw string literal; escape
+characters not processed |
+| `b"..."` | Byte string literal; constructs an array of bytes instead of a
+string |
+| `br"..."`, `br#"..."#`, `br##"..."##`, and so on | Raw byte string literal;
+combination of raw and byte string literal |
+| `'...' | Character literal |
+| `b'...' | ASCII byte literal |
+| `|…| expr | Closure |
+| `! | Always-empty bottom type for diverging functions |
+| `_ | “Ignored” pattern binding; also used to make integer literals readable |
Table B-3 shows symbols that appear in the context of a path through the module
hierarchy to an item.
@@ -252,16 +252,23 @@ hierarchy to an item.
Table B-3: Path-Related Syntax
| Symbol | Explanation |
-|--------|-------------|
-| `ident::ident` | Namespace path |
-| `::path` | Path relative to the crate root (i.e., an explicitly absolute path) |
-| `self::path` | Path relative to the current module (i.e., an explicitly relative path).
+|---|---|
+| `ident::ident | Namespace path |
+| `::path` | Path relative to the crate root (that is, an explicitly absolute
+path) |
+| `self::path` | Path relative to the current module (that is, an explicitly
+relative path) |
| `super::path` | Path relative to the parent of the current module |
-| `type::ident`, `<type as trait>::ident` | Associated constants, functions, and types |
-| `<type>::...` | Associated item for a type that cannot be directly named (e.g., `<&T>::...`, `<[T]>::...`, etc.) |
-| `trait::method(...)` | Disambiguating a method call by naming the trait that defines it |
-| `type::method(...)` | Disambiguating a method call by naming the type for which it’s defined |
-| `<type as trait>::method(...)` | Disambiguating a method call by naming the trait and type |
+| `type::ident`, `<type as trait>::ident | Associated constants, functions, and
+types |
+| `<type>::...` | Associated item for a type that cannot be directly named (for
+example, `<&T>::...`, `<[T]>::...`, and so on) |
+| `trait::method(...)` | Disambiguating a method call by naming the trait that
+defines it |
+| `type::method(...)` | Disambiguating a method call by naming the type for
+which it’s defined |
+| `<type as trait>::method(...)` | Disambiguating a method call by naming the
+trait and type |
Table B-4 shows symbols that appear in the context of using generic type
parameters.
@@ -269,15 +276,19 @@ parameters.
Table B-4: Generics
| Symbol | Explanation |
-|--------|-------------|
-| `path<...>` | Specifies parameters to generic type in a type (e.g., `Vec<u8>`) |
-| `path::<...>`, `method::<...>` | Specifies parameters to generic type, function, or method in an expression; often referred to as turbofish (e.g., `"42".parse::<i32>()`) |
+|---|---|
+| `path<...>` | Specifies parameters to a generic type in a type (for example,
+`Vec<u8>`) |
+| `path::<...>, method::<...>` | Specifies parameters to a generic type,
+function, or method in an expression; often referred to as turbofish (for
+example, `"42".parse::<i32>()`) |
| `fn ident<...> ...` | Define generic function |
| `struct ident<...> ...` | Define generic structure |
| `enum ident<...> ...` | Define generic enumeration |
| `impl<...> ...` | Define generic implementation |
| `for<...> type` | Higher-ranked lifetime bounds |
-| `type<ident=type>` | A generic type where one or more associated types have specific assignments (e.g., `Iterator<Item=T>`) |
+| `type<ident=type>` | A generic type where one or more associated types have
+specific assignments (for example, `Iterator<Item=T>`) |
Table B-5 shows symbols that appear in the context of constraining generic type
parameters with trait bounds.
@@ -285,10 +296,12 @@ parameters with trait bounds.
Table B-5: Trait Bound Constraints
| Symbol | Explanation |
-|--------|-------------|
-| `T: U` | Generic parameter `T` constrained to types that implement `U` |
-| `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type cannot transitively contain any references with lifetimes shorter than `'a`) |
-| `T: 'static` | Generic type `T` contains no borrowed references other than `'static` ones |
+|---|---|
+| T: U` | Generic parameter `T` constrained to types that implement `U` |
+| `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type
+cannot transitively contain any references with lifetimes shorter than `'a`) |
+| `T: 'static` | Generic type `T` contains no borrowed references other than
+`'static` ones |
| `'b: 'a` | Generic lifetime `'b` must outlive lifetime `'a` |
| `T: ?Sized` | Allow generic type parameter to be a dynamically sized type |
| `'a + trait`, `trait + trait` | Compound type constraint |
@@ -299,7 +312,7 @@ macros and specifying attributes on an item.
Table B-6: Macros and Attributes
| Symbol | Explanation |
-|--------|-------------|
+|---|---|
| `#[meta]` | Outer attribute |
| `#![meta]` | Inner attribute |
| `$ident` | Macro substitution |
@@ -312,7 +325,7 @@ Table B-7 shows symbols that create comments.
Table B-7: Comments
| Symbol | Explanation |
-|--------|-------------|
+|---|---|
| `//` | Line comment |
| `//!` | Inner line doc comment |
| `///` | Outer line doc comment |
@@ -325,22 +338,23 @@ Table B-8 shows symbols that appear in the context of using tuples.
Table B-8: Tuples
| Symbol | Explanation |
-|--------|-------------|
-| `()` | Empty tuple (aka unit), both literal and type |
+|---|---|
+| `() | Empty tuple (aka unit), both literal and type |
| `(expr)` | Parenthesized expression |
| `(expr,)` | Single-element tuple expression |
| `(type,)` | Single-element tuple type |
| `(expr, ...)` | Tuple expression |
| `(type, ...)` | Tuple type |
-| `expr(expr, ...)` | Function call expression; also used to initialize tuple `struct`s and tuple `enum` variants |
-| `expr.0`, `expr.1`, etc. | Tuple indexing |
+| `expr(expr, ...)` | Function call expression; also used to initialize tuple
+`struct`s and tuple `enum` variants |
+| `expr.0`, `expr.1`, and so on | Tuple indexing |
-Table B-9 shows the contexts in which curly braces are used.
+Table B-9 shows the contexts in which curly brackets are used.
Table B-9: Curly Brackets
| Context | Explanation |
-|---------|-------------|
+|---|---|
| `{...}` | Block expression |
| `Type {...}` | `struct` literal |
@@ -349,12 +363,14 @@ Table B-10 shows the contexts in which square brackets are used.
Table B-10: Square Brackets
| Context | Explanation |
-|---------|-------------|
+|---|---|
| `[...]` | Array literal |
| `[expr; len]` | Array literal containing `len` copies of `expr` |
| `[type; len]` | Array type containing `len` instances of `type` |
-| `expr[expr]` | Collection indexing. Overloadable (`Index`, `IndexMut`) |
-| `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | Collection indexing pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, or `RangeFull` as the “index” |
+| `expr[expr]` | Collection indexing; overloadable (`Index`, `IndexMut`) |
+| `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | Collection indexing
+pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, or
+`RangeFull` as the “index” |
## Appendix C: Derivable Traits
@@ -373,14 +389,13 @@ library that you can use with `derive`. Each section covers:
* Examples of operations that require the trait
If you want different behavior from that provided by the `derive` attribute,
-consult the standard library documentation for each trait for details of how to
+consult the standard library documentation for each trait for details on how to
manually implement them.
-These traits listed here are the only ones defined by the standard library that
-can be implemented on your types using `derive`.
-Other traits defined in the standard library don’t have sensible default
-behavior, so it’s up to you to implement them in the way that makes sense for
-what you’re trying to accomplish.
+The traits listed here are the only ones defined by the standard library that
+can be implemented on your types using `derive`. Other traits defined in the
+standard library don’t have sensible default behavior, so it’s up to you to
+implement them in the way that makes sense for what you’re trying to accomplish.
An example of a trait that can’t be derived is `Display`, which handles
formatting for end users. You should always consider the appropriate way to
@@ -391,11 +406,10 @@ it can’t provide appropriate default behavior for you.
The list of derivable traits provided in this appendix is not comprehensive:
libraries can implement `derive` for their own traits, making the list of
-traits you can use `derive` with truly open-ended. Implementing `derive`
-involves using a procedural macro, which is covered in the
-“Macros” section of Chapter 19.
+traits you can use `derive` with truly open ended. Implementing `derive`
+involves using a procedural macro, which is covered in “Macros” on page XX.
-### `Debug` for Programmer Output
+## Debug for Programmer Output
The `Debug` trait enables debug formatting in format strings, which you
indicate by adding `:?` within `{}` placeholders.
@@ -404,11 +418,12 @@ The `Debug` trait allows you to print instances of a type for debugging
purposes, so you and other programmers using your type can inspect an instance
at a particular point in a program’s execution.
-The `Debug` trait is required, for example, in use of the `assert_eq!` macro.
-This macro prints the values of instances given as arguments if the equality
-assertion fails so programmers can see why the two instances weren’t equal.
+The `Debug` trait is required, for example, in the use of the `assert_eq!`
+macro. This macro prints the values of instances given as arguments if the
+equality assertion fails so programmers can see why the two instances weren’t
+equal.
-### `PartialEq` and `Eq` for Equality Comparisons
+## PartialEq and Eq for Equality Comparisons
The `PartialEq` trait allows you to compare instances of a type to check for
equality and enables use of the `==` and `!=` operators.
@@ -425,14 +440,14 @@ for equality.
The `Eq` trait has no methods. Its purpose is to signal that for every value of
the annotated type, the value is equal to itself. The `Eq` trait can only be
applied to types that also implement `PartialEq`, although not all types that
-implement `PartialEq` can implement `Eq`. One example of this is floating point
-number types: the implementation of floating point numbers states that two
+implement `PartialEq` can implement `Eq`. One example of this is floating-point
+number types: the implementation of floating-point numbers states that two
instances of the not-a-number (`NaN`) value are not equal to each other.
-An example of when `Eq` is required is for keys in a `HashMap<K, V>` so the
-`HashMap<K, V>` can tell whether two keys are the same.
+An example of when `Eq` is required is for keys in a `HashMap<K, V>` so that
+the `HashMap<K, V>` can tell whether two keys are the same.
-### `PartialOrd` and `Ord` for Ordering Comparisons
+## PartialOrd and Ord for Ordering Comparisons
The `PartialOrd` trait allows you to compare instances of a type for sorting
purposes. A type that implements `PartialOrd` can be used with the `<`, `>`,
@@ -443,8 +458,8 @@ Deriving `PartialOrd` implements the `partial_cmp` method, which returns an
`Option<Ordering>` that will be `None` when the values given don’t produce an
ordering. An example of a value that doesn’t produce an ordering, even though
most values of that type can be compared, is the not-a-number (`NaN`) floating
-point value. Calling `partial_cmp` with any floating point number and the `NaN`
-floating point value will return `None`.
+point value. Calling `partial_cmp` with any floating-point number and the `NaN`
+floating-point value will return `None`.
When derived on structs, `PartialOrd` compares two instances by comparing the
value in each field in the order in which the fields appear in the struct
@@ -466,12 +481,12 @@ implementation for `partial_cmp` does with `PartialOrd`.
An example of when `Ord` is required is when storing values in a `BTreeSet<T>`,
a data structure that stores data based on the sort order of the values.
-### `Clone` and `Copy` for Duplicating Values
+## Clone and Copy for Duplicating Values
The `Clone` trait allows you to explicitly create a deep copy of a value, and
the duplication process might involve running arbitrary code and copying heap
-data. See the “Ways Variables and Data Interact: Clone” section in Chapter 4
-for more information on `Clone`.
+data. See “Variables and Data Interacting with Clone” on page XX for more
+information on `Clone`.
Deriving `Clone` implements the `clone` method, which when implemented for the
whole type, calls `clone` on each of the parts of the type. This means all the
@@ -480,11 +495,11 @@ fields or values in the type must also implement `Clone` to derive `Clone`.
An example of when `Clone` is required is when calling the `to_vec` method on a
slice. The slice doesn’t own the type instances it contains, but the vector
returned from `to_vec` will need to own its instances, so `to_vec` calls
-`clone` on each item. Thus, the type stored in the slice must implement `Clone`.
+`clone` on each item. Thus the type stored in the slice must implement `Clone`.
The `Copy` trait allows you to duplicate a value by only copying bits stored on
-the stack; no arbitrary code is necessary. See the “Stack-Only Data: Copy”
-section in Chapter 4 for more information on `Copy`.
+the stack; no arbitrary code is necessary. See “Stack-Only Data: Copy” on page
+XX for more information on `Copy`.
The `Copy` trait doesn’t define any methods to prevent programmers from
overloading those methods and violating the assumption that no arbitrary code
@@ -492,7 +507,7 @@ is being run. That way, all programmers can assume that copying a value will be
very fast.
You can derive `Copy` on any type whose parts all implement `Copy`. A type that
-implements `Copy` must also implement `Clone`, because a type that implements
+implements `Copy` must also implement `Clone` because a type that implements
`Copy` has a trivial implementation of `Clone` that performs the same task as
`Copy`.
@@ -503,7 +518,7 @@ the code more concise.
Everything possible with `Copy` you can also accomplish with `Clone`, but the
code might be slower or have to use `clone` in places.
-### `Hash` for Mapping a Value to a Value of Fixed Size
+## Hash for Mapping a Value to a Value of Fixed Size
The `Hash` trait allows you to take an instance of a type of arbitrary size and
map that instance to a value of fixed size using a hash function. Deriving
@@ -514,7 +529,7 @@ meaning all fields or values must also implement `Hash` to derive `Hash`.
An example of when `Hash` is required is in storing keys in a `HashMap<K, V>`
to store data efficiently.
-### `Default` for Default Values
+## Default for Default Values
The `Default` trait allows you to create a default value for a type. Deriving
`Default` implements the `default` function. The derived implementation of the
@@ -523,9 +538,9 @@ meaning all fields or values in the type must also implement `Default` to
derive `Default`.
The `Default::default` function is commonly used in combination with the struct
-update syntax discussed in the “Creating Instances From Other Instances With
-Struct Update Syntax” section in Chapter 5. You can customize a few fields of a
-struct and then set and use a default value for the rest of the fields by using
+update syntax discussed in “Creating Instances from Other Instances with Struct
+Update Syntax” on page XX. You can customize a few fields of a struct and then
+set and use a default value for the rest of the fields by using
`..Default::default()`.
The `Default` trait is required when you use the method `unwrap_or_default` on
@@ -533,26 +548,23 @@ The `Default` trait is required when you use the method `unwrap_or_default` on
`unwrap_or_default` will return the result of `Default::default` for the type
`T` stored in the `Option<T>`.
-## Appendix D - Useful Development Tools
+## Appendix D: Useful Development Tools
In this appendix, we talk about some useful development tools that the Rust
project provides. We’ll look at automatic formatting, quick ways to apply
warning fixes, a linter, and integrating with IDEs.
-### Automatic Formatting with `rustfmt`
+## Automatic Formatting with rustfmt
The `rustfmt` tool reformats your code according to the community code style.
Many collaborative projects use `rustfmt` to prevent arguments about which
style to use when writing Rust: everyone formats their code using the tool.
-To install `rustfmt`, enter the following:
-
-```
-$ rustup component add rustfmt
-```
-
-This command gives you `rustfmt` and `cargo-fmt`, similar to how Rust gives you
-both `rustc` and `cargo`. To format any Cargo project, enter the following:
+Rust installations include `rustfmt` by default, so you should already have the
+programs `rustfmt` and `cargo-fmt` on your system. These two commands are
+analagous to `rustc` and `cargo` in that `rustfmt` allows finer-grained control
+and `cargo-fmt` understands conventions of a project that uses Cargo. To format
+any Cargo project, enter the following:
```
$ cargo fmt
@@ -562,13 +574,12 @@ Running this command reformats all the Rust code in the current crate. This
should only change the code style, not the code semantics. For more information
on `rustfmt`, see its documentation at *https://github.com/rust-lang/rustfmt*.
+## Fix Your Code with rustfix
-### Fix Your Code with `rustfix`
-
-The rustfix tool is included with Rust installations and can automatically fix
-compiler warnings that have a clear way to correct the problem that’s likely
-what you want. It’s likely you’ve seen compiler warnings before. For example,
-consider this code:
+The `rustfix` tool is included with Rust installations and can automatically
+fix compiler warnings that have a clear way to correct the problem that’s
+likely what you want. You’ve probably seen compiler warnings before. For
+example, consider this code:
Filename: src/main.rs
@@ -631,16 +642,11 @@ The `for` loop variable is now named `_i`, and the warning no longer appears.
You can also use the `cargo fix` command to transition your code between
different Rust editions. Editions are covered in Appendix E.
-### More Lints with Clippy
+## More Lints with Clippy
The Clippy tool is a collection of lints to analyze your code so you can catch
-common mistakes and improve your Rust code.
-
-To install Clippy, enter the following:
-
-```
-$ rustup component add clippy
-```
+common mistakes and improve your Rust code. Clippy is included with standard
+Rust installations.
To run Clippy’s lints on any Cargo project, enter the following:
@@ -664,14 +670,16 @@ fn main() {
Running `cargo clippy` on this project results in this error:
```
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
--> src/main.rs:2:13
|
2 | let x = 3.1415;
| ^^^^^^
|
- = note: #[deny(clippy::approx_constant)] on by default
- = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant
+ = note: `#[deny(clippy::approx_constant)]` on by default
+ = help: consider using the constant directly
+ = help: for further information visit https://rust-lang.github.io/rust-
+clippy/master/index.html#approx_constant
```
This error lets you know that Rust already has a more precise `PI` constant
@@ -690,23 +698,24 @@ fn main() {
}
```
-For more information on Clippy, see its documentation at *https://github.com/rust-lang/rust-clippy*.
+For more information on Clippy, see its documentation at
+*https://github.com/rust-lang/rust-clippy**.*
-### IDE Integration Using `rust-analyzer`
+## IDE Integration Using rust-analyzer
-To help IDE integration, the Rust community recommends using `rust-analyzer`.
-This tool is a set of compiler-centric utilities that speaks the Language
-Server Protocol, which is a specification for IDEs and programming languages to
-communicate with each other. Different clients can use `rust-analyzer`, such as
-the Rust analyzer plug-in for Visual Studio Code at
+To help with IDE integration, the Rust community recommends using
+`rust-analyzer`. This tool is a set of compiler-centric utilities that speak
+Language Server Protocol, which is a specification for IDEs and programming
+languages to communicate with each other. Different clients can use
+`rust-analyzer`, such as the Rust analyzer plug-in for Visual Studio Code at
*https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer*.
Visit the `rust-analyzer` project’s home page at
*https://rust-analyzer.github.io* for installation instructions, then install
the language server support in your particular IDE. Your IDE will gain
-abilities such as autocompletion, jump to definition, and inline errors.
+capabilities such as autocompletion, jump to definition, and inline errors
-## Appendix E - Editions
+## Appendix E: Editions
In Chapter 1, you saw that `cargo new` adds a bit of metadata to your
*Cargo.toml* file about an edition. This appendix talks about what that means!
@@ -726,11 +735,11 @@ six-week release process.
Editions serve different purposes for different people:
* For active Rust users, a new edition brings together incremental changes into
- an easy-to-understand package.
+an easy-to-understand package.
* For non-users, a new edition signals that some major advancements have
- landed, which might make Rust worth another look.
+landed, which might make Rust worth another look.
* For those developing Rust, a new edition provides a rallying point for the
- project as a whole.
+project as a whole.
At the time of this writing, three Rust editions are available: Rust 2015, Rust
2018, and Rust 2021. This book is written using Rust 2021 edition idioms.
@@ -759,7 +768,8 @@ made. However, in some cases, mainly when new keywords are added, some new
features might only be available in later editions. You will need to switch
editions if you want to take advantage of such features.
-For more details, the *Edition
-Guide* at *https://doc.rust-lang.org/stable/edition-guide/* is a complete book
-about editions that enumerates the differences between editions and explains
-how to automatically upgrade your code to a new edition via `cargo fix`.
+For more details, *The* *Edition Guide* at
+*https://doc.rust-lang.org/stable/edition-guide* is a complete book about
+editions that enumerates the differences between editions and explains how to
+automatically upgrade your code to a new edition via `cargo fix`.
+
diff --git a/src/doc/book/nostarch/appendix_a.md b/src/doc/book/nostarch/appendix_a.md
new file mode 100644
index 000000000..ca3883be4
--- /dev/null
+++ b/src/doc/book/nostarch/appendix_a.md
@@ -0,0 +1,142 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+
+[TOC]
+
+## Appendix A: Keywords
+
+The following lists contain keywords that are reserved for current or future
+use by the Rust language. As such, they cannot be used as identifiers (except
+as raw identifiers, as we’ll discuss in “Raw Identifiers” on page XX).
+*Identifiers* are names of functions, variables, parameters, struct fields,
+modules, crates, constants, macros, static values, attributes, types, traits,
+or lifetimes.
+
+## Keywords Currently in Use
+
+The following is a list of keywords currently in use, with their functionality
+described.
+
+* **`as` **: perform primitive casting, disambiguate the specific trait
+containing an item, or rename items in `use` statements
+* **`async` **: return a `Future` instead of blocking the current thread
+* **`await` **: suspend execution until the result of a `Future` is ready
+* **`break` **: exit a loop immediately
+* **`const` **: define constant items or constant raw pointers
+* **`continue` **: continue to the next loop iteration
+* **`crate` **: in a module path, refers to the crate root
+* **`dyn` **: dynamic dispatch to a trait object
+* **`else` **: fallback for `if` and `if let` control flow constructs
+* **`enum` **: define an enumeration
+* **`extern` **: link an external function or variable
+* **`false` **: Boolean false literal
+* **`fn` **: define a function or the function pointer type
+* **`for` **: loop over items from an iterator, implement a trait, or specify a
+higher-ranked lifetime
+* **`if` **: branch based on the result of a conditional expression
+* **`impl` **: implement inherent or trait functionality
+* **`in` **: part of `for` loop syntax
+* **`let` **: bind a variable
+* **`loop` **: loop unconditionally
+* **`match` **: match a value to patterns
+* **`mod` **: define a module
+* **`move` **: make a closure take ownership of all its captures
+* **`mut` **: denote mutability in references, raw pointers, or pattern bindings
+* **`pub` **: denote public visibility in struct fields, `impl` blocks, or
+modules
+* **`ref` **: bind by reference
+* **`return` **: return from function
+* **`Self` **: a type alias for the type we are defining or implementing
+* **`self` **: method subject or current module
+* **`static` **: global variable or lifetime lasting the entire program
+execution
+* **`struct` **: define a structure
+* **`super` **: parent module of the current module
+* **`trait` **: define a trait
+* **`true` **: Boolean true literal
+* **`type` **: define a type alias or associated type
+* **`union` **: define a union; is a keyword only when used in a union
+declaration
+* **`unsafe` **: denote unsafe code, functions, traits, or implementations
+* **`use` **: bring symbols into scope
+* **`where` **: denote clauses that constrain a type
+* **`while` **: loop conditionally based on the result of an expression
+
+## Keywords Reserved for Future Use
+
+The following keywords do not yet have any functionality but are reserved by
+Rust for potential future use:
+
+* `abstract`
+* `become`
+* `box`
+* `do`
+* `final`
+* `macro`
+* `override`
+* `priv`
+* `try`
+* `typeof`
+* `unsized`
+* `virtual`
+* `yield`
+
+## Raw Identifiers
+
+*Raw identifiers* are the syntax that lets you use keywords where they wouldn’t
+normally be allowed. You use a raw identifier by prefixing a keyword with `r#`.
+
+For example, `match` is a keyword. If you try to compile the following function
+that uses `match` as its name:
+
+Filename: src/main.rs
+
+```
+fn match(needle: &str, haystack: &str) -> bool {
+ haystack.contains(needle)
+}
+```
+
+you’ll get this error:
+
+```
+error: expected identifier, found keyword `match`
+ --> src/main.rs:4:4
+ |
+4 | fn match(needle: &str, haystack: &str) -> bool {
+ | ^^^^^ expected identifier, found keyword
+```
+
+The error shows that you can’t use the keyword `match` as the function
+identifier. To use `match` as a function name, you need to use the raw
+identifier syntax, like this:
+
+Filename: src/main.rs
+
+```
+fn r#match(needle: &str, haystack: &str) -> bool {
+ haystack.contains(needle)
+}
+
+fn main() {
+ assert!(r#match("foo", "foobar"));
+}
+```
+
+This code will compile without any errors. Note the `r#` prefix on the function
+name in its definition as well as where the function is called in `main`.
+
+Raw identifiers allow you to use any word you choose as an identifier, even if
+that word happens to be a reserved keyword. This gives us more freedom to
+choose identifier names, as well as lets us integrate with programs written in
+a language where these words aren’t keywords. In addition, raw identifiers
+allow you to use libraries written in a different Rust edition than your crate
+uses. For example, `try` isn’t a keyword in the 2015 edition but is in the 2018
+and 2021 editions. If you depend on a library that is written using the 2015
+edition and has a `try` function, you’ll need to use the raw identifier syntax,
+`r#try` in this case, to call that function from your 2021 edition code. See
+Appendix E for more information on editions.
+
diff --git a/src/doc/book/nostarch/appendix_b.md b/src/doc/book/nostarch/appendix_b.md
new file mode 100644
index 000000000..236608b6d
--- /dev/null
+++ b/src/doc/book/nostarch/appendix_b.md
@@ -0,0 +1,241 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+
+[TOC]
+
+## Appendix B: Operators and Symbols
+
+This appendix contains a glossary of Rust’s syntax, including operators and
+other symbols that appear by themselves or in the context of paths, generics,
+trait bounds, macros, attributes, comments, tuples, and brackets.
+
+## Operators
+
+Table B-1 contains the operators in Rust, an example of how the operator would
+appear in context, a short explanation, and whether that operator is
+overloadable. If an operator is overloadable, the relevant trait to use to
+overload that operator is listed.
+
+Table B-1: Operators
+
+| Operator | Example | Explanation | Overloadable? |
+|---|---|---|---|
+| `!` | `ident!(...)`, `ident!{...}`, `ident![...]` | Macro expansion | |
+| `!` | `!expr` | Bitwise or logical complement | `Not` |
+| `!=` | `expr != expr` | Nonequality comparison | `PartialEq` |
+| `%` | `expr % expr` | Arithmetic remainder | `Rem` |
+| `%=` | `var %= expr` | Arithmetic remainder and assignment | `RemAssign` |
+| `&` | `&expr`, `&mut expr` | Borrow | |
+| `&` | `&type`, `&mut type`, `&'a type`, `&'a mut type` | Borrowed pointer
+type | |
+| `&` | `expr & expr` | Bitwise AND | `BitAnd` |
+| `&=` | `var &= expr` | Bitwise AND and assignment | `BitAndAssign` |
+| `&&` | `expr && expr` | Short-circuiting logical AND | |
+| `*` | `expr * expr` | Arithmetic multiplication | `Mul` |
+| `*=` | `var *= expr` | Arithmetic multiplication and assignment | `MulAssign`
+|
+| `*` | `*expr` | Dereference | `Deref` |
+| `*` | `*const type`, `*mut type` | Raw pointer | |
+| `+` | `trait + trait`, `'a + trait` | Compound type constraint | |
+| `+` | `expr + expr` | Arithmetic addition | `Add` |
+| `+=` | `var += expr` | Arithmetic addition and assignment | `AddAssign` |
+| `,` | `expr, expr` | Argument and element separator | |
+| `-` | `- expr` | Arithmetic negation | `Neg` |
+| `-` | `expr - expr` | Arithmetic subtraction | `Sub` |
+| `-=` | `var -= expr` | Arithmetic subtraction and assignment | `SubAssign` |
+| `->` | `fn(...) -> type`, `|…| -> type` | Function and closure return type |
+|
+| `. | `expr.ident` | Member access | |
+| `..` | `..`, `expr..`, `..expr`, `expr..expr` | Right-exclusive range literal
+| `PartialOrd` |
+| `..=` | `..=expr`, `expr..=expr` | Right-inclusive range literal |
+`PartialOrd` |
+| `..` | `..expr` | Struct literal update syntax | |
+| `..` | `variant(x, ..)`, `struct_type { x, .. }` | “And the rest” pattern
+binding | |
+| `...` | `expr...expr` | (Deprecated, use `..=` instead) In a pattern:
+inclusive range pattern | |
+| `/` | `expr / expr` | Arithmetic division | `Div` |
+| `/=` | `var /= expr` | Arithmetic division and assignment | `DivAssign` |
+| `: | `pat: type`, `ident: type` | Constraints | |
+| `:` | `ident: expr` | Struct field initializer | |
+| `:` | `'a: loop {...}` | Loop label | |
+| `;` | `expr;` | Statement and item terminator | |
+| `;` | `[...; len]` | Part of fixed-size array syntax | |
+| `<<` | `expr << expr` | Left-shift | `Shl` |
+| `<<=` | `var <<= expr` | Left-shift and assignment | `ShlAssign` |
+| `<` | `expr < expr` | Less than comparison | `PartialOrd` |
+| `<=` | `expr <= expr` | Less than or equal to comparison | `PartialOrd` |
+| `=` | `var = expr`, `ident = type` | Assignment/equivalence | |
+| `==` | `expr == expr` | Equality comparison | `PartialEq` |
+| `=>` | `pat => expr` | Part of match arm syntax | |
+| `>` | `expr > expr` | Greater than comparison | `PartialOrd` |
+| `>=` | `expr >= expr` | Greater than or equal to comparison | `PartialOrd` |
+| `>>` | `expr >> expr` | Right-shift | `Shr` |
+| `>>=` | `var >>= expr` | Right-shift and assignment | `ShrAssign` |
+| `@` | `ident @ pat` | Pattern binding | |
+| `^` | `expr ^ expr` | Bitwise exclusive OR | `BitXor` |
+| `^=` | `var ^= expr` | Bitwise exclusive OR and assignment | `BitXorAssign` |
+| `|` | `pat | pat` | Pattern alternatives | |
+| `|` | `expr | expr` | Bitwise OR | `BitOr` |
+| `|=` | `var |= expr` | Bitwise OR and assignment | `BitOrAssign` |
+| `||` | `expr || expr` | Short-circuiting logical OR | |
+| `?` | `expr?` | Error propagation | |
+
+## Non-operator Symbols
+
+The following tables contain all symbols that don’t function as operators; that
+is, they don’t behave like a function or method call.
+
+Table B-2 shows symbols that appear on their own and are valid in a variety of
+locations.
+
+Table B-2: Stand-Alone Syntax
+
+| Symbol | Explanation |
+|---|---|
+| `'ident` | Named lifetime or loop label |
+| `...u8`, `...i32`, `...f64`, `...usize`, and so on | Numeric literal of
+specific type |
+| `"..."` | String literal |
+| `r"..."`, `r#"..."#`, `r##"..."##`, and so on | Raw string literal; escape
+characters not processed |
+| `b"..."` | Byte string literal; constructs an array of bytes instead of a
+string |
+| `br"..."`, `br#"..."#`, `br##"..."##`, and so on | Raw byte string literal;
+combination of raw and byte string literal |
+| `'...'` | Character literal |
+| `b'...'` | ASCII byte literal |
+| `|…| expr` | Closure |
+| `!` | Always-empty bottom type for diverging functions |
+| `_` | “Ignored” pattern binding; also used to make integer literals readable |
+
+Table B-3 shows symbols that appear in the context of a path through the module
+hierarchy to an item.
+
+Table B-3: Path-Related Syntax
+
+| Symbol | Explanation |
+|---|---|
+| `ident::ident` | Namespace path |
+| `::path` | Path relative to the crate root (that is, an explicitly absolute
+path) |
+| `self::path` | Path relative to the current module (that is, an explicitly
+relative path) |
+| `super::path` | Path relative to the parent of the current module |
+| `type::ident`, `<type as trait>::ident` | Associated constants, functions,
+and types |
+| `<type>::...` | Associated item for a type that cannot be directly named (for
+example, `<&T>::...`, `<[T]>::...`, and so on) |
+| `trait::method(...)` | Disambiguating a method call by naming the trait that
+defines it |
+| `type::method(...)` | Disambiguating a method call by naming the type for
+which it’s defined |
+| `<type as trait>::method(...)` | Disambiguating a method call by naming the
+trait and type |
+
+Table B-4 shows symbols that appear in the context of using generic type
+parameters.
+
+Table B-4: Generics
+
+| Symbol | Explanation |
+|---|---|
+| `path<...>` | Specifies parameters to a generic type in a type (for example,
+`Vec<u8>`) |
+| `path::<...>, method::<...>` | Specifies parameters to a generic type,
+function, or method in an expression; often referred to as turbofish (for
+example, `"42".parse::<i32>()`) |
+| `fn ident<...> ...` | Define generic function |
+| `struct ident<...> ...` | Define generic structure |
+| `enum ident<...> ...` | Define generic enumeration |
+| `impl<...> ...` | Define generic implementation |
+| `for<...> type` | Higher-ranked lifetime bounds |
+| `type<ident=type>` | A generic type where one or more associated types have
+specific assignments (for example, `Iterator<Item=T>`) |
+
+Table B-5 shows symbols that appear in the context of constraining generic type
+parameters with trait bounds.
+
+Table B-5: Trait Bound Constraints
+
+| Symbol | Explanation |
+|---|---|
+| T: U` | Generic parameter `T` constrained to types that implement `U` |
+| `T: 'a` | Generic type `T` must outlive lifetime `'a` (meaning the type
+cannot transitively contain any references with lifetimes shorter than `'a`) |
+| `T: 'static` | Generic type `T` contains no borrowed references other than
+`'static` ones |
+| `'b: 'a` | Generic lifetime `'b` must outlive lifetime `'a` |
+| `T: ?Sized` | Allow generic type parameter to be a dynamically sized type |
+| `'a + trait`, `trait + trait` | Compound type constraint |
+
+Table B-6 shows symbols that appear in the context of calling or defining
+macros and specifying attributes on an item.
+
+Table B-6: Macros and Attributes
+
+| Symbol | Explanation |
+|---|---|
+| `#[meta]` | Outer attribute |
+| `#![meta]` | Inner attribute |
+| `$ident` | Macro substitution |
+| `$ident:kind` | Macro capture |
+| `$(…)…` | Macro repetition |
+| `ident!(...)`, `ident!{...}`, `ident![...]` | Macro invocation |
+
+Table B-7 shows symbols that create comments.
+
+Table B-7: Comments
+
+| Symbol | Explanation |
+|---|---|
+| `//` | Line comment |
+| `//!` | Inner line doc comment |
+| `///` | Outer line doc comment |
+| `/*...*/` | Block comment |
+| `/*!...*/` | Inner block doc comment |
+| `/**...*/` | Outer block doc comment |
+
+Table B-8 shows symbols that appear in the context of using tuples.
+
+Table B-8: Tuples
+
+| Symbol | Explanation |
+|---|---|
+| `()` | Empty tuple (aka unit), both literal and type |
+| `(expr)` | Parenthesized expression |
+| `(expr,)` | Single-element tuple expression |
+| `(type,)` | Single-element tuple type |
+| `(expr, ...)` | Tuple expression |
+| `(type, ...)` | Tuple type |
+| `expr(expr, ...)` | Function call expression; also used to initialize tuple
+`struct`s and tuple `enum` variants |
+| `expr.0`, `expr.1`, and so on | Tuple indexing |
+
+Table B-9 shows the contexts in which curly brackets are used.
+
+Table B-9: Curly Brackets
+
+| Context | Explanation |
+|---|---|
+| `{...}` | Block expression |
+| `Type {...}` | `struct` literal |
+
+Table B-10 shows the contexts in which square brackets are used.
+
+Table B-10: Square Brackets
+
+| Context | Explanation |
+|---|---|
+| `[...]` | Array literal |
+| `[expr; len]` | Array literal containing `len` copies of `expr` |
+| `[type; len]` | Array type containing `len` instances of `type` |
+| `expr[expr]` | Collection indexing; overloadable (`Index`, `IndexMut`) |
+| `expr[..]`, `expr[a..]`, `expr[..b]`, `expr[a..b]` | Collection indexing
+pretending to be collection slicing, using `Range`, `RangeFrom`, `RangeTo`, or
+`RangeFull` as the “index” |
+
diff --git a/src/doc/book/nostarch/appendix_c.md b/src/doc/book/nostarch/appendix_c.md
new file mode 100644
index 000000000..53131eb5f
--- /dev/null
+++ b/src/doc/book/nostarch/appendix_c.md
@@ -0,0 +1,184 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+
+[TOC]
+
+## Appendix C: Derivable Traits
+
+In various places in the book, we’ve discussed the `derive` attribute, which
+you can apply to a struct or enum definition. The `derive` attribute generates
+code that will implement a trait with its own default implementation on the
+type you’ve annotated with the `derive` syntax.
+
+In this appendix, we provide a reference of all the traits in the standard
+library that you can use with `derive`. Each section covers:
+
+* What operators and methods deriving this trait will enable
+* What the implementation of the trait provided by `derive` does
+* What implementing the trait signifies about the type
+* The conditions in which you’re allowed or not allowed to implement the trait
+* Examples of operations that require the trait
+
+If you want different behavior from that provided by the `derive` attribute,
+consult the standard library documentation for each trait for details on how to
+manually implement them.
+
+The traits listed here are the only ones defined by the standard library that
+can be implemented on your types using `derive`. Other traits defined in the
+standard library don’t have sensible default behavior, so it’s up to you to
+implement them in the way that makes sense for what you’re trying to accomplish.
+
+An example of a trait that can’t be derived is `Display`, which handles
+formatting for end users. You should always consider the appropriate way to
+display a type to an end user. What parts of the type should an end user be
+allowed to see? What parts would they find relevant? What format of the data
+would be most relevant to them? The Rust compiler doesn’t have this insight, so
+it can’t provide appropriate default behavior for you.
+
+The list of derivable traits provided in this appendix is not comprehensive:
+libraries can implement `derive` for their own traits, making the list of
+traits you can use `derive` with truly open ended. Implementing `derive`
+involves using a procedural macro, which is covered in “Macros” on page XX.
+
+## Debug for Programmer Output
+
+The `Debug` trait enables debug formatting in format strings, which you
+indicate by adding `:?` within `{}` placeholders.
+
+The `Debug` trait allows you to print instances of a type for debugging
+purposes, so you and other programmers using your type can inspect an instance
+at a particular point in a program’s execution.
+
+The `Debug` trait is required, for example, in the use of the `assert_eq!`
+macro. This macro prints the values of instances given as arguments if the
+equality assertion fails so programmers can see why the two instances weren’t
+equal.
+
+## PartialEq and Eq for Equality Comparisons
+
+The `PartialEq` trait allows you to compare instances of a type to check for
+equality and enables use of the `==` and `!=` operators.
+
+Deriving `PartialEq` implements the `eq` method. When `PartialEq` is derived on
+structs, two instances are equal only if *all* fields are equal, and the
+instances are not equal if any fields are not equal. When derived on enums,
+each variant is equal to itself and not equal to the other variants.
+
+The `PartialEq` trait is required, for example, with the use of the
+`assert_eq!` macro, which needs to be able to compare two instances of a type
+for equality.
+
+The `Eq` trait has no methods. Its purpose is to signal that for every value of
+the annotated type, the value is equal to itself. The `Eq` trait can only be
+applied to types that also implement `PartialEq`, although not all types that
+implement `PartialEq` can implement `Eq`. One example of this is floating-point
+number types: the implementation of floating-point numbers states that two
+instances of the not-a-number (`NaN`) value are not equal to each other.
+
+An example of when `Eq` is required is for keys in a `HashMap<K, V>` so that
+the `HashMap<K, V>` can tell whether two keys are the same.
+
+## PartialOrd and Ord for Ordering Comparisons
+
+The `PartialOrd` trait allows you to compare instances of a type for sorting
+purposes. A type that implements `PartialOrd` can be used with the `<`, `>`,
+`<=`, and `>=` operators. You can only apply the `PartialOrd` trait to types
+that also implement `PartialEq`.
+
+Deriving `PartialOrd` implements the `partial_cmp` method, which returns an
+`Option<Ordering>` that will be `None` when the values given don’t produce an
+ordering. An example of a value that doesn’t produce an ordering, even though
+most values of that type can be compared, is the not-a-number (`NaN`) floating
+point value. Calling `partial_cmp` with any floating-point number and the `NaN`
+floating-point value will return `None`.
+
+When derived on structs, `PartialOrd` compares two instances by comparing the
+value in each field in the order in which the fields appear in the struct
+definition. When derived on enums, variants of the enum declared earlier in the
+enum definition are considered less than the variants listed later.
+
+The `PartialOrd` trait is required, for example, for the `gen_range` method
+from the `rand` crate that generates a random value in the range specified by a
+range expression.
+
+The `Ord` trait allows you to know that for any two values of the annotated
+type, a valid ordering will exist. The `Ord` trait implements the `cmp` method,
+which returns an `Ordering` rather than an `Option<Ordering>` because a valid
+ordering will always be possible. You can only apply the `Ord` trait to types
+that also implement `PartialOrd` and `Eq` (and `Eq` requires `PartialEq`). When
+derived on structs and enums, `cmp` behaves the same way as the derived
+implementation for `partial_cmp` does with `PartialOrd`.
+
+An example of when `Ord` is required is when storing values in a `BTreeSet<T>`,
+a data structure that stores data based on the sort order of the values.
+
+## Clone and Copy for Duplicating Values
+
+The `Clone` trait allows you to explicitly create a deep copy of a value, and
+the duplication process might involve running arbitrary code and copying heap
+data. See “Variables and Data Interacting with Clone” on page XX for more
+information on `Clone`.
+
+Deriving `Clone` implements the `clone` method, which when implemented for the
+whole type, calls `clone` on each of the parts of the type. This means all the
+fields or values in the type must also implement `Clone` to derive `Clone`.
+
+An example of when `Clone` is required is when calling the `to_vec` method on a
+slice. The slice doesn’t own the type instances it contains, but the vector
+returned from `to_vec` will need to own its instances, so `to_vec` calls
+`clone` on each item. Thus the type stored in the slice must implement `Clone`.
+
+The `Copy` trait allows you to duplicate a value by only copying bits stored on
+the stack; no arbitrary code is necessary. See “Stack-Only Data: Copy” on page
+XX for more information on `Copy`.
+
+The `Copy` trait doesn’t define any methods to prevent programmers from
+overloading those methods and violating the assumption that no arbitrary code
+is being run. That way, all programmers can assume that copying a value will be
+very fast.
+
+You can derive `Copy` on any type whose parts all implement `Copy`. A type that
+implements `Copy` must also implement `Clone` because a type that implements
+`Copy` has a trivial implementation of `Clone` that performs the same task as
+`Copy`.
+
+The `Copy` trait is rarely required; types that implement `Copy` have
+optimizations available, meaning you don’t have to call `clone`, which makes
+the code more concise.
+
+Everything possible with `Copy` you can also accomplish with `Clone`, but the
+code might be slower or have to use `clone` in places.
+
+## Hash for Mapping a Value to a Value of Fixed Size
+
+The `Hash` trait allows you to take an instance of a type of arbitrary size and
+map that instance to a value of fixed size using a hash function. Deriving
+`Hash` implements the `hash` method. The derived implementation of the `hash`
+method combines the result of calling `hash` on each of the parts of the type,
+meaning all fields or values must also implement `Hash` to derive `Hash`.
+
+An example of when `Hash` is required is in storing keys in a `HashMap<K, V>`
+to store data efficiently.
+
+## Default for Default Values
+
+The `Default` trait allows you to create a default value for a type. Deriving
+`Default` implements the `default` function. The derived implementation of the
+`default` function calls the `default` function on each part of the type,
+meaning all fields or values in the type must also implement `Default` to
+derive `Default`.
+
+The `Default::default` function is commonly used in combination with the struct
+update syntax discussed in “Creating Instances from Other Instances with Struct
+Update Syntax” on page XX. You can customize a few fields of a struct and then
+set and use a default value for the rest of the fields by using
+`..Default::default()`.
+
+The `Default` trait is required when you use the method `unwrap_or_default` on
+`Option<T>` instances, for example. If the `Option<T>` is `None`, the method
+`unwrap_or_default` will return the result of `Default::default` for the type
+`T` stored in the `Option<T>`.
+
diff --git a/src/doc/book/nostarch/appendix_d.md b/src/doc/book/nostarch/appendix_d.md
new file mode 100644
index 000000000..96b73e954
--- /dev/null
+++ b/src/doc/book/nostarch/appendix_d.md
@@ -0,0 +1,175 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+
+[TOC]
+
+## Appendix D: Useful Development Tools
+
+In this appendix, we talk about some useful development tools that the Rust
+project provides. We’ll look at automatic formatting, quick ways to apply
+warning fixes, a linter, and integrating with IDEs.
+
+## Automatic Formatting with rustfmt
+
+The `rustfmt` tool reformats your code according to the community code style.
+Many collaborative projects use `rustfmt` to prevent arguments about which
+style to use when writing Rust: everyone formats their code using the tool.
+
+Rust installations include `rustfmt` by default, so you should already have the
+programs `rustfmt` and `cargo-fmt` on your system. These two commands are
+analagous to `rustc` and `cargo` in that `rustfmt` allows finer-grained control
+and `cargo-fmt` understands conventions of a project that uses Cargo. To format
+any Cargo project, enter the following:
+
+```
+$ cargo fmt
+```
+
+Running this command reformats all the Rust code in the current crate. This
+should only change the code style, not the code semantics. For more information
+on `rustfmt`, see its documentation at *https://github.com/rust-lang/rustfmt*.
+
+## Fix Your Code with rustfix
+
+The `rustfix` tool is included with Rust installations and can automatically
+fix compiler warnings that have a clear way to correct the problem that’s
+likely what you want. You’ve probably seen compiler warnings before. For
+example, consider this code:
+
+Filename: src/main.rs
+
+```
+fn do_something() {}
+
+fn main() {
+ for i in 0..100 {
+ do_something();
+ }
+}
+```
+
+Here, we’re calling the `do_something` function 100 times, but we never use the
+variable `i` in the body of the `for` loop. Rust warns us about that:
+
+```
+$ cargo build
+ Compiling myprogram v0.1.0 (file:///projects/myprogram)
+warning: unused variable: `i`
+ --> src/main.rs:4:9
+ |
+4 | for i in 0..100 {
+ | ^ help: consider using `_i` instead
+ |
+ = note: #[warn(unused_variables)] on by default
+
+ Finished dev [unoptimized + debuginfo] target(s) in 0.50s
+```
+
+The warning suggests that we use `_i` as a name instead: the underscore
+indicates that we intend for this variable to be unused. We can automatically
+apply that suggestion using the `rustfix` tool by running the command `cargo
+fix`:
+
+```
+$ cargo fix
+ Checking myprogram v0.1.0 (file:///projects/myprogram)
+ Fixing src/main.rs (1 fix)
+ Finished dev [unoptimized + debuginfo] target(s) in 0.59s
+```
+
+When we look at *src/main.rs* again, we’ll see that `cargo fix` has changed the
+code:
+
+Filename: src/main.rs
+
+```
+fn do_something() {}
+
+fn main() {
+ for _i in 0..100 {
+ do_something();
+ }
+}
+```
+
+The `for` loop variable is now named `_i`, and the warning no longer appears.
+
+You can also use the `cargo fix` command to transition your code between
+different Rust editions. Editions are covered in Appendix E.
+
+## More Lints with Clippy
+
+The Clippy tool is a collection of lints to analyze your code so you can catch
+common mistakes and improve your Rust code. Clippy is included with standard
+Rust installations.
+
+To run Clippy’s lints on any Cargo project, enter the following:
+
+```
+$ cargo clippy
+```
+
+For example, say you write a program that uses an approximation of a
+mathematical constant, such as pi, as this program does:
+
+Filename: src/main.rs
+
+```
+fn main() {
+ let x = 3.1415;
+ let r = 8.0;
+ println!("the area of the circle is {}", x * r * r);
+}
+```
+
+Running `cargo clippy` on this project results in this error:
+
+```
+error: approximate value of `f{32, 64}::consts::PI` found
+ --> src/main.rs:2:13
+ |
+2 | let x = 3.1415;
+ | ^^^^^^
+ |
+ = note: `#[deny(clippy::approx_constant)]` on by default
+ = help: consider using the constant directly
+ = help: for further information visit https://rust-lang.github.io/rust-
+clippy/master/index.html#approx_constant
+```
+
+This error lets you know that Rust already has a more precise `PI` constant
+defined, and that your program would be more correct if you used the constant
+instead. You would then change your code to use the `PI` constant.
+
+The following code doesn’t result in any errors or warnings from Clippy:
+
+Filename: src/main.rs
+
+```
+fn main() {
+ let x = std::f64::consts::PI;
+ let r = 8.0;
+ println!("the area of the circle is {}", x * r * r);
+}
+```
+
+For more information on Clippy, see its documentation at
+*https://github.com/rust-lang/rust-clippy**.*
+
+## IDE Integration Using rust-analyzer
+
+To help with IDE integration, the Rust community recommends using
+`rust-analyzer`. This tool is a set of compiler-centric utilities that speak
+Language Server Protocol, which is a specification for IDEs and programming
+languages to communicate with each other. Different clients can use
+`rust-analyzer`, such as the Rust analyzer plug-in for Visual Studio Code at
+*https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer*.
+
+Visit the `rust-analyzer` project’s home page at
+*https://rust-analyzer.github.io* for installation instructions, then install
+the language server support in your particular IDE. Your IDE will gain
+capabilities such as autocompletion, jump to definition, and inline errors
+
diff --git a/src/doc/book/nostarch/appendix_e.md b/src/doc/book/nostarch/appendix_e.md
new file mode 100644
index 000000000..ddb12b782
--- /dev/null
+++ b/src/doc/book/nostarch/appendix_e.md
@@ -0,0 +1,66 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+
+[TOC]
+
+## Appendix E: Editions
+
+In Chapter 1, you saw that `cargo new` adds a bit of metadata to your
+*Cargo.toml* file about an edition. This appendix talks about what that means!
+
+The Rust language and compiler have a six-week release cycle, meaning users get
+a constant stream of new features. Other programming languages release larger
+changes less often; Rust releases smaller updates more frequently. After a
+while, all of these tiny changes add up. But from release to release, it can be
+difficult to look back and say, “Wow, between Rust 1.10 and Rust 1.31, Rust has
+changed a lot!”
+
+Every two or three years, the Rust team produces a new Rust *edition*. Each
+edition brings together the features that have landed into a clear package with
+fully updated documentation and tooling. New editions ship as part of the usual
+six-week release process.
+
+Editions serve different purposes for different people:
+
+* For active Rust users, a new edition brings together incremental changes into
+an easy-to-understand package.
+* For non-users, a new edition signals that some major advancements have
+landed, which might make Rust worth another look.
+* For those developing Rust, a new edition provides a rallying point for the
+project as a whole.
+
+At the time of this writing, three Rust editions are available: Rust 2015, Rust
+2018, and Rust 2021. This book is written using Rust 2021 edition idioms.
+
+The `edition` key in *Cargo.toml* indicates which edition the compiler should
+use for your code. If the key doesn’t exist, Rust uses `2015` as the edition
+value for backward compatibility reasons.
+
+Each project can opt in to an edition other than the default 2015 edition.
+Editions can contain incompatible changes, such as including a new keyword that
+conflicts with identifiers in code. However, unless you opt in to those
+changes, your code will continue to compile even as you upgrade the Rust
+compiler version you use.
+
+All Rust compiler versions support any edition that existed prior to that
+compiler’s release, and they can link crates of any supported editions
+together. Edition changes only affect the way the compiler initially parses
+code. Therefore, if you’re using Rust 2015 and one of your dependencies uses
+Rust 2018, your project will compile and be able to use that dependency. The
+opposite situation, where your project uses Rust 2018 and a dependency uses
+Rust 2015, works as well.
+
+To be clear: most features will be available on all editions. Developers using
+any Rust edition will continue to see improvements as new stable releases are
+made. However, in some cases, mainly when new keywords are added, some new
+features might only be available in later editions. You will need to switch
+editions if you want to take advantage of such features.
+
+For more details, *The* *Edition Guide* at
+*https://doc.rust-lang.org/stable/edition-guide* is a complete book about
+editions that enumerates the differences between editions and explains how to
+automatically upgrade your code to a new edition via `cargo fix`.
+
diff --git a/src/doc/book/nostarch/bio.md b/src/doc/book/nostarch/bio.md
index cbb2bd4bb..38b0508bc 100644
--- a/src/doc/book/nostarch/bio.md
+++ b/src/doc/book/nostarch/bio.md
@@ -1,5 +1,6 @@
# About the Authors
-<!--Insert Steve's bio here -->
-
-Carol Nichols is a member of the Rust Crates.io Team and a former member of the Rust Core Team. She’s a co-founder of Integer 32, LLC, the world’s first Rust-focused software consultancy. Nichols has also organized the Rust Belt Rust Conference. \ No newline at end of file
+Carol Nichols is a member of the Rust Crates.io Team and a former member of the
+Rust Core Team. She’s a co-founder of Integer 32, LLC, the world’s first
+Rust-focused software consultancy. Nichols has also organized the Rust Belt
+Rust Conference.
diff --git a/src/doc/book/nostarch/chapter01.md b/src/doc/book/nostarch/chapter01.md
index 87848b66f..3379b14f2 100644
--- a/src/doc/book/nostarch/chapter01.md
+++ b/src/doc/book/nostarch/chapter01.md
@@ -21,28 +21,28 @@ The first step is to install Rust. We’ll download Rust through `rustup`, a
command line tool for managing Rust versions and associated tools. You’ll need
an internet connection for the download.
-> Note: If you prefer not to use `rustup` for some reason, please see the
-> Other Rust Installation Methods page at
-> *https://forge.rust-lang.org/infra/other-installation-methods.html* for more
-> options.
+> Note: If you prefer not to use `rustup` for some reason, please see the Other
+Rust Installation Methods page at
+*https://forge.rust-lang.org/infra/other-installation-methods.html* for more
+options.
The following steps install the latest stable version of the Rust compiler.
Rust’s stability guarantees ensure that all the examples in the book that
compile will continue to compile with newer Rust versions. The output might
-differ slightly between versions, because Rust often improves error messages
-and warnings. In other words, any newer, stable version of Rust you install
-using these steps should work as expected with the content of this book.
+differ slightly between versions because Rust often improves error messages and
+warnings. In other words, any newer, stable version of Rust you install using
+these steps should work as expected with the content of this book.
> ### Command Line Notation
>
> In this chapter and throughout the book, we’ll show some commands used in the
-> terminal. Lines that you should enter in a terminal all start with `$`. You
-> don’t need to type in the `$` character; it’s the command line prompt shown
-> to indicate the start of each command. Lines that don’t start with `$`
-> typically show the output of the previous command. Additionally,
-> PowerShell-specific examples will use `>` rather than `$`.
+terminal. Lines that you should enter in a terminal all start with `$`. You
+don’t need to type the `$` character; it’s the command line prompt shown to
+indicate the start of each command. Lines that don’t start with `$` typically
+show the output of the previous command. Additionally, PowerShell-specific
+examples will use `>` rather than `$`.
-### Installing `rustup` on Linux or macOS
+### Installing rustup on Linux or macOS
If you’re using Linux or macOS, open a terminal and enter the following command:
@@ -74,7 +74,7 @@ Linux users should generally install GCC or Clang, according to their
distribution’s documentation. For example, if you use Ubuntu, you can install
the `build-essential` package.
-### Installing `rustup` on Windows
+### Installing rustup on Windows
On Windows, go to *https://www.rust-lang.org/tools/install* and follow the
instructions for installing Rust. At some point in the installation, you’ll
@@ -82,18 +82,13 @@ receive a message explaining that you’ll also need the MSVC build tools for
Visual Studio 2013 or later.
To acquire the build tools, you’ll need to install Visual Studio 2022 from
-*https://visualstudio.microsoft.com/downloads/*. When asked which workloads to
+*https://visualstudio.microsoft.com/downloads*. When asked which workloads to
install, include:
-- “Desktop Development with C++”
-- The Windows 10 or 11 SDK
-- The English language pack component, along with any other language pack of
- your choosing
-
-<!-- Liz: We do want to recommend the English language pack along with whatever
-other languages the reader speaks-- otherwise, sometimes error messages are
-printed strangely
-https://github.com/rust-lang/rust/issues/35785#issuecomment-735051657 /Carol -->
+* “Desktop Development with C++”
+* The Windows 10 or 11 SDK
+* The English language pack component, along with any other language pack of
+your choosing
The rest of this book uses commands that work in both *cmd.exe* and PowerShell.
If there are specific differences, we’ll explain which to use.
@@ -108,7 +103,7 @@ $ rustc --version
```
You should see the version number, commit hash, and commit date for the latest
-stable version that has been released in the following format:
+stable version that has been released, in the following format:
```
rustc x.y.z (abcabcabc yyyy-mm-dd)
@@ -133,25 +128,18 @@ In PowerShell, use:
In Linux and macOS, use:
```
-echo $PATH
+$ echo $PATH
```
If that’s all correct and Rust still isn’t working, there are a number of
-places you can get help. The easiest is the #beginners channel on the official
-Rust Discord at *https://discord.gg/rust-lang*. There, you can chat with other
-Rustaceans (a silly nickname we call ourselves) who can help you out. Other
-great resources include the Users forum at *https://users.rust-lang.org/* and
-Stack Overflow at *https://stackoverflow.com/questions/tagged/rust*.
-
-<!-- `echo %PATH%` will work for cmd. PowerShell would use `echo $env:Path`.
-Bash would use `echo $PATH` /JT -->
-<!-- I've added these instructions above /Carol -->
+places you can get help. Find out how to get in touch with other Rustaceans (a
+silly nickname we call ourselves) on the community page at
+*https://www.rust-lang.org/community*.
### Updating and Uninstalling
-Once Rust is installed via `rustup`, when a new version of Rust is released,
-updating to the latest version is easy. From your shell, run the following
-update script:
+Once Rust is installed via `rustup`, updating to a newly released version is
+easy. From your shell, run the following update script:
```
$ rustup update
@@ -166,9 +154,9 @@ $ rustup self uninstall
### Local Documentation
-The installation of Rust also includes a local copy of the documentation, so
-you can read it offline. Run `rustup doc` to open the local documentation in
-your browser.
+The installation of Rust also includes a local copy of the documentation so
+that you can read it offline. Run `rustup doc` to open the local documentation
+in your browser.
Any time a type or function is provided by the standard library and you’re not
sure what it does or how to use it, use the application programming interface
@@ -176,17 +164,17 @@ sure what it does or how to use it, use the application programming interface
## Hello, World!
-Now that you’ve installed Rust, let’s write your first Rust program. It’s
-traditional when learning a new language to write a little program that prints
-the text `Hello, world!` to the screen, so we’ll do the same here!
+Now that you’ve installed Rust, it’s time to write your first Rust program.
+It’s traditional when learning a new language to write a little program that
+prints the text `Hello, world!` to the screen, so we’ll do the same here!
> Note: This book assumes basic familiarity with the command line. Rust makes
-> no specific demands about your editing or tooling or where your code lives, so
-> if you prefer to use an integrated development environment (IDE) instead of
-> the command line, feel free to use your favorite IDE. Many IDEs now have some
-> degree of Rust support; check the IDE’s documentation for details. The Rust
-> team has been focusing on enabling great IDE support via `rust-analyzer`. See
-> Appendix D for more details!
+no specific demands about your editing or tooling or where your code lives, so
+if you prefer to use an integrated development environment (IDE) instead of the
+command line, feel free to use your favorite IDE. Many IDEs now have some
+degree of Rust support; check the IDE’s documentation for details. The Rust
+team has been focusing on enabling great IDE support via `rust-analyzer`. See
+Appendix D for more details.
### Creating a Project Directory
@@ -254,8 +242,8 @@ Hello, world!
```
Regardless of your operating system, the string `Hello, world!` should print to
-the terminal. If you don’t see this output, refer back to the “Troubleshooting”
-part of the Installation section for ways to get help.
+the terminal. If you don’t see this output, refer back to “Troubleshooting” on
+page XX for ways to get help.
If `Hello, world!` did print, congratulations! You’ve officially written a Rust
program. That makes you a Rust programmer—welcome!
@@ -281,10 +269,10 @@ function bodies. It’s good style to place the opening curly bracket on the sam
line as the function declaration, adding one space in between.
> Note: If you want to stick to a standard style across Rust projects, you can
-> use an automatic formatter tool called `rustfmt` to format your code in a
-> particular style (more on `rustfmt` in Appendix D). The Rust team has
-> included this tool with the standard Rust distribution, like `rustc`, so it
-> should already be installed on your computer!
+use an automatic formatter tool called `rustfmt` to format your code in a
+particular style (more on `rustfmt` in Appendix D). The Rust team has included
+this tool with the standard Rust distribution, as `rustc` is, so it should
+already be installed on your computer!
The body of the `main` function holds the following code:
@@ -300,7 +288,7 @@ First, Rust style is to indent with four spaces, not a tab.
Second, `println!` calls a Rust macro. If it had called a function instead, it
would be entered as `println` (without the `!`). We’ll discuss Rust macros in
more detail in Chapter 19. For now, you just need to know that using a `!`
-means that you’re calling a macro instead of a normal function, and that macros
+means that you’re calling a macro instead of a normal function and that macros
don’t always follow the same rules as functions.
Third, you see the `"Hello, world!"` string. We pass this string as an argument
@@ -327,16 +315,16 @@ If you have a C or C++ background, you’ll notice that this is similar to `gcc`
or `clang`. After compiling successfully, Rust outputs a binary executable.
On Linux, macOS, and PowerShell on Windows, you can see the executable by
-entering the `ls` command in your shell. On Linux and macOS, you’ll see two
-files. With PowerShell on Windows, you’ll see the same three files that you
-would see using CMD.
+entering the `ls` command in your shell:
```
$ ls
main main.rs
```
-With CMD on Windows, you would enter the following:
+On Linux and macOS, you’ll see two files. With PowerShell on Windows, you’ll
+see the same three files that you would see using CMD. With CMD on Windows, you
+would enter the following:
```
> dir /B %= the /B option says to only show the file names =%
@@ -387,9 +375,9 @@ using Cargo, adding dependencies will be much easier to do.
Because the vast majority of Rust projects use Cargo, the rest of this book
assumes that you’re using Cargo too. Cargo comes installed with Rust if you
-used the official installers discussed in the “Installation” section. If you
+used the official installers discussed in “Installation” on page XX. If you
installed Rust through some other means, check whether Cargo is installed by
-entering the following into your terminal:
+entering the following in your terminal:
```
$ cargo --version
@@ -402,9 +390,9 @@ determine how to install Cargo separately.
### Creating a Project with Cargo
Let’s create a new project using Cargo and look at how it differs from our
-original “Hello, world!” project. Navigate back to your *projects* directory (or
-wherever you decided to store your code). Then, on any operating system, run
-the following:
+original “Hello, world!” project. Navigate back to your *projects* directory
+(or wherever you decided to store your code). Then, on any operating system,
+run the following:
```
$ cargo new hello_cargo
@@ -424,8 +412,8 @@ Git files won’t be generated if you run `cargo new` within an existing Git
repository; you can override this behavior by using `cargo new --vcs=git`.
> Note: Git is a common version control system. You can change `cargo new` to
-> use a different version control system or no version control system by using
-> the `--vcs` flag. Run `cargo new --help` to see the available options.
+use a different version control system or no version control system by using
+the `--vcs` flag. Run `cargo new --help` to see the available options.
Open *Cargo.toml* in your text editor of choice. It should look similar to the
code in Listing 1-2.
@@ -471,7 +459,7 @@ fn main() {
Cargo has generated a “Hello, world!” program for you, just like the one we
wrote in Listing 1-1! So far, the differences between our project and the
-project Cargo generated are that Cargo placed the code in the *src* directory,
+project Cargo generated are that Cargo placed the code in the *src* directory
and we have a *Cargo.toml* configuration file in the top directory.
Cargo expects your source files to live inside the *src* directory. The
@@ -499,21 +487,6 @@ $ cargo build
This command creates an executable file in *target/debug/hello_cargo* (or
*target\debug\hello_cargo.exe* on Windows) rather than in your current
-<!-- why does it put it in a debug folder? Interesting to know, because it seems
-laborious to have to enter the whole path to run the executable /LC -->
-<!-- Because `build` uses debug settings by default, and the compiler tries to
-make it clear that this isn't a release build by storing it in the `debug`
-path. Most people use `cargo run` instead, which is what we show in a few
-paragraphs. We talk about building for release mode in the next section; do you
-think it needs to be mentioned here too? I think it would be somewhat
-distracting and repetitive to get into that right here... /Carol -->
-<!-- JT, what do you think? I don't want to get into the weeds... but will the
-reader be wondering? /LC -->
-<!-- I think we could quickly mention that because the default build is a debug
-build, cargo will put the binary in the debug directory. If we created a release
-build, it would put it in the release directory. Looks like we do mention this
-later /JT -->
-<!-- I've added a sentence here along the lines of what JT suggested /Carol -->
directory. Because the default build is a debug build, Cargo puts the binary in
a directory named *debug*. You can run the executable with this command:
@@ -531,7 +504,7 @@ manages its contents for you.
We just built a project with `cargo build` and ran it with
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile the
-code and then run the resulting executable all in one command:
+code and then run the resultant executable all in one command:
```
$ cargo run
@@ -568,7 +541,7 @@ $ cargo check
```
Why would you not want an executable? Often, `cargo check` is much faster than
-`cargo build`, because it skips the step of producing an executable. If you’re
+`cargo build` because it skips the step of producing an executable. If you’re
continually checking your work while writing the code, using `cargo check` will
speed up the process of letting you know if your project is still compiling! As
such, many Rustaceans run `cargo check` periodically as they write their
@@ -581,9 +554,9 @@ Let’s recap what we’ve learned so far about Cargo:
* We can build a project using `cargo build`.
* We can build and run a project in one step using `cargo run`.
* We can build a project without producing a binary to check for errors using
- `cargo check`.
+`cargo check`.
* Instead of saving the result of the build in the same directory as our code,
- Cargo stores it in the *target/debug* directory.
+Cargo stores it in the *target/debug* directory.
An additional advantage of using Cargo is that the commands are the same no
matter which operating system you’re working on. So, at this point, we’ll no
@@ -609,10 +582,6 @@ With simple projects, Cargo doesn’t provide a lot of value over just using
Once programs grow to multiple files or need a dependency, it’s much easier to
let Cargo coordinate the build.
-<!-- I think once you go add a second file or add a single dependency, you
-already want to move to cargo imho. /JT -->
-<!-- Updated above! /Carol -->
-
Even though the `hello_cargo` project is simple, it now uses much of the real
tooling you’ll use in the rest of your Rust career. In fact, to work on any
existing projects, you can use the following commands to check out the code
@@ -624,7 +593,8 @@ $ cd someproject
$ cargo build
```
-For more information about Cargo, check out its documentation at *https://doc.rust-lang.org/cargo/*.
+For more information about Cargo, check out its documentation at
+*https://doc.rust-lang.org/cargo*.
## Summary
@@ -642,8 +612,3 @@ and writing Rust code. So, in Chapter 2, we’ll build a guessing game program.
If you would rather start by learning how common programming concepts work in
Rust, see Chapter 3 and then return to Chapter 2.
-<!-- Question for Carol: Do we want to mention IDE support? Rust Analyzer is
-pretty good these days. /JT -->
-<!-- I don't want to make the reader feel like they *have* to stop at this
-point and set up their IDE (or use an unfamiliar IDE); I did add a sentence to
-the note about IDEs pointing to Appendix D for more info on Rust Analyzer. -->
diff --git a/src/doc/book/nostarch/chapter02.md b/src/doc/book/nostarch/chapter02.md
index b7986c0de..b01770dc5 100644
--- a/src/doc/book/nostarch/chapter02.md
+++ b/src/doc/book/nostarch/chapter02.md
@@ -11,8 +11,8 @@ directory, so all fixes need to be made in `/src/`.
Let’s jump into Rust by working through a hands-on project together! This
chapter introduces you to a few common Rust concepts by showing you how to use
them in a real program. You’ll learn about `let`, `match`, methods, associated
-functions, using external crates, and more! In the following chapters, we’ll
-explore these ideas in more detail. In this chapter, you’ll practice the
+functions, external crates, and more! In the following chapters, we’ll explore
+these ideas in more detail. In this chapter, you’ll just practice the
fundamentals.
We’ll implement a classic beginner programming problem: a guessing game. Here’s
@@ -45,14 +45,12 @@ name = "guessing_game"
version = "0.1.0"
edition = "2021"
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+# See more keys and their definitions at
+https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
```
-<!--- We should move to the 2021 edition. /JT --->
-<!-- Totally right, done! /Carol -->
-
As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for
you. Check out the *src/main.rs* file:
@@ -108,27 +106,21 @@ fn main() {
}
```
-<!--- Style question, should we switch to the more recent style of:
-```
- println!("You guessed: {guess}");
-```
-/JT --->
-<!-- Good call, I'll switch these throughout as I edit after TR. /Carol -->
-
Listing 2-1: Code that gets a guess from the user and prints it
This code contains a lot of information, so let’s go over it line by line. To
obtain user input and then print the result as output, we need to bring the
-`io` input/output library into scope. The `io` library comes from the
-standard library, known as `std`:
+`io` input/output library into scope. The `io` library comes from the standard
+library, known as `std`:
```
use std::io;
```
-By default, Rust has a set of items defined in the standard library that it brings
-into the scope of every program. This set is called the *prelude*, and you can
-see everything in it at *https://doc.rust-lang.org/std/prelude/index.html*.
+By default, Rust has a set of items defined in the standard library that it
+brings into the scope of every program. This set is called the *prelude*, and
+you can see everything in it at
+*https://doc.rust-lang.org/std/prelude/index.html*.
If a type you want to use isn’t in the prelude, you have to bring that type
into scope explicitly with a `use` statement. Using the `std::io` library
@@ -142,21 +134,16 @@ program:
fn main() {
```
-The `fn` syntax declares a new function, the parentheses, `()`, indicate there
-are no parameters, and the curly bracket, `{`, starts the body of the function.
+The `fn` syntax declares a new function; the parentheses, `()`, indicate there
+are no parameters; and the curly bracket, `{`, starts the body of the function.
As you also learned in Chapter 1, `println!` is a macro that prints a string to
the screen:
-<!--- Not sure if we want to go into it just yet, but `println!` formats a string
-and then prints the resulting string to stdout (which is often, but not always
-the screen). /JT --->
-<!-- Yeah, I want to gloss over that for now. Leaving this as-is. /Carol -->
-
```
- println!("Guess the number!");
+println!("Guess the number!");
- println!("Please input your guess.");
+println!("Please input your guess.");
```
This code is printing a prompt stating what the game is and requesting input
@@ -167,7 +154,7 @@ from the user.
Next, we’ll create a *variable* to store the user input, like this:
```
- let mut guess = String::new();
+let mut guess = String::new();
```
Now the program is getting interesting! There’s a lot going on in this little
@@ -179,15 +166,9 @@ let apples = 5;
This line creates a new variable named `apples` and binds it to the value 5. In
Rust, variables are immutable by default, meaning once we give the variable a
-value, the value won't change. We’ll be discussing this concept in detail in
-the “Variables and Mutability” section in Chapter 3. To make a variable
-mutable, we add `mut` before the variable name:
-
-<!--- Do we want to give a quick word about what "mutable" means? Folks who grab
-this book but aren't familiar with some of the technical programming language terms
-might need something like "variable are immutable by default, meaning once we give
-the variable its value, it won't change". /JT --->
-<!-- Sounds good, made that change /Carol -->
+value, the value won’t change. We’ll be discussing this concept in detail in
+“Variables and Mutability” on page XX. To make a variable mutable, we add `mut`
+before the variable name:
```
let apples = 5; // immutable
@@ -195,12 +176,12 @@ let mut bananas = 5; // mutable
```
> Note: The `//` syntax starts a comment that continues until the end of the
-> line. Rust ignores everything in comments. We’ll discuss comments in more
-> detail in Chapter 3.
+line. Rust ignores everything in comments. We’ll discuss comments in more
+detail in Chapter 3.
Returning to the guessing game program, you now know that `let mut guess` will
introduce a mutable variable named `guess`. The equal sign (`=`) tells Rust we
-want to bind something to the variable now. On the right of the equals sign is
+want to bind something to the variable now. On the right of the equal sign is
the value that `guess` is bound to, which is the result of calling
`String::new`, a function that returns a new instance of a `String`. `String`
is a string type provided by the standard library that is a growable, UTF-8
@@ -209,15 +190,9 @@ encoded bit of text.
The `::` syntax in the `::new` line indicates that `new` is an associated
function of the `String` type. An *associated function* is a function that’s
implemented on a type, in this case `String`. This `new` function creates a
-new, empty string. You’ll find a `new` function on many types, because it’s a
+new, empty string. You’ll find a `new` function on many types because it’s a
common name for a function that makes a new value of some kind.
-<!--- For some readers, we might want to say "If you've used languages with
-static methods, associated function work very similarly" or something along
-those lines. /JT --->
-<!-- I don't think that's helpful enough for all readers to include here, given
-that we're trying to make the book mostly background-agnostic. /Carol -->
-
In full, the `let mut guess = String::new();` line has created a mutable
variable that is currently bound to a new, empty instance of a `String`. Whew!
@@ -229,11 +204,11 @@ the `stdin` function from the `io` module, which will allow us to handle user
input:
```
- io::stdin()
- .read_line(&mut guess)
+io::stdin()
+ .read_line(&mut guess)
```
-If we hadn’t imported the `io` library with `use std::io` at the beginning of
+If we hadn’t imported the `io` library with `use std::io;` at the beginning of
the program, we could still use the function by writing this function call as
`std::io::stdin`. The `stdin` function returns an instance of `std::io::Stdin`,
which is a type that represents a handle to the standard input for your
@@ -252,27 +227,19 @@ let multiple parts of your code access one piece of data without needing to
copy that data into memory multiple times. References are a complex feature,
and one of Rust’s major advantages is how safe and easy it is to use
references. You don’t need to know a lot of those details to finish this
-program. For now, all you need to know is that like variables, references are
+program. For now, all you need to know is that, like variables, references are
immutable by default. Hence, you need to write `&mut guess` rather than
`&guess` to make it mutable. (Chapter 4 will explain references more
thoroughly.)
-### Handling Potential Failure with the `Result` Type
+### Handling Potential Failure with Result
We’re still working on this line of code. We’re now discussing a third line of
text, but note that it’s still part of a single logical line of code. The next
part is this method:
-<!--- in the program this is the second line of code -- do you mean the third
-section of this line? -->
-<!-- This is still discussing the code in Listing 2-1, and is going to talk
-about the third line, if you're counting the lines of the page, of this logical
-line of code, where logical lines of code are ended with semicolons. Do you
-have suggestions on how to make that clearer? /Carol -->
-<!--- Ashley, does this all track now? /LC --->
-
```
- .expect("Failed to read line");
+.expect("Failed to read line");
```
We could have written this code as:
@@ -291,17 +258,10 @@ we pass to it, but it also returns a `Result` value. `Result` is an
*enumeration*, often called an *enum*, which is a type that can be in one of
multiple possible states. We call each possible state a *variant*.
-<!--- Typo above: possibilities /JT --->
-<!--- Personally, I think the above paragraph might be introducing a little too
-much all at once. You might be able to shorten it to: "`Result` is an *enumeration*,
-often called an *enum*, which is a type that can be in one of multiple possible
-states. We call each possible state a *variant*. /JT --->
-<!-- I like it, made that change /Carol -->
-
Chapter 6 will cover enums in more detail. The purpose of these `Result` types
is to encode error-handling information.
-`Result`'s variants are `Ok` and `Err`. The `Ok` variant indicates the
+`Result`’s variants are `Ok` and `Err`. The `Ok` variant indicates the
operation was successful, and inside `Ok` is the successfully generated value.
The `Err` variant means the operation failed, and `Err` contains information
about how or why the operation failed.
@@ -337,38 +297,36 @@ warning: `guessing_game` (bin "guessing_game") generated 1 warning
Rust warns that you haven’t used the `Result` value returned from `read_line`,
indicating that the program hasn’t handled a possible error.
-The right way to suppress the warning is to actually write error handling, but
-in our case we just want to crash this program when a problem occurs, so we can
-use `expect`. You’ll learn about recovering from errors in Chapter 9.
+The right way to suppress the warning is to actually write error-handling code,
+but in our case we just want to crash this program when a problem occurs, so we
+can use `expect`. You’ll learn about recovering from errors in Chapter 9.
-### Printing Values with `println!` Placeholders
+### Printing Values with println! Placeholders
Aside from the closing curly bracket, there’s only one more line to discuss in
the code so far:
```
- println!("You guessed: {guess}");
+println!("You guessed: {guess}");
```
-<!--- Ditto with using the `{guess}` style in this line. /JT --->
-
This line prints the string that now contains the user’s input. The `{}` set of
curly brackets is a placeholder: think of `{}` as little crab pincers that hold
-a value in place. You can print more than one value using curly brackets: the
-first set of curly brackets holds the first value listed after the format
-string, the second set holds the second value, and so on. Printing multiple
-values in one call to `println!` would look like this:
+a value in place. When printing the value of a variable, the variable name can
+go inside the curly brackets. When printing the result of evaluating an
+expression, place empty curly brackets in the format string, then follow the
+format string with a comma-separated list of expressions to print in each empty
+curly bracket placeholder in the same order. Printing a variable and the result
+of an expression in one call to `println!` would look like this:
```
let x = 5;
let y = 10;
-println!("x = {x} and y = {y}");
+println!("x = {x} and y + 2 = {}", y + 2);
```
-<!--- And `println!("x = {x} and y = {y}");` in this example. /JT --->
-<!-- Done! /Carol -->
-This code would print `x = 5 and y = 10`.
+This code would print `x = 5 and y = 12`.
### Testing the First Part
@@ -401,43 +359,36 @@ library. However, the Rust team does provide a `rand` crate at
Remember that a crate is a collection of Rust source code files. The project
we’ve been building is a *binary crate*, which is an executable. The `rand`
-crate is a *library crate*, which contains code intended to be used in other
-programs and can't be executed on its own.
-
-<!--- Nit: ", and" followed by incomplete sentence. /JT --->
-<!-- Fixed /Carol -->
+crate is a *library crate*, which contains code that is intended to be used in
+other programs and can’t be executed on its own.
Cargo’s coordination of external crates is where Cargo really shines. Before we
can write code that uses `rand`, we need to modify the *Cargo.toml* file to
include the `rand` crate as a dependency. Open that file now and add the
-following line to the bottom beneath the `[dependencies]` section header that
+following line to the bottom, beneath the `[dependencies]` section header that
Cargo created for you. Be sure to specify `rand` exactly as we have here, with
-this version number, or the code examples in this tutorial may not work.
+this version number, or the code examples in this tutorial may not work:
Filename: Cargo.toml
```
-rand = "0.8.3"
+[dependencies]
+rand = "0.8.5"
```
-<!--- 0.8.5 is the current latest. /JT --->
-<!-- I will update this version to whatever is latest once we're in Word; there
-could be another version between now and then. If it's another 0.8.x version,
-it doesn't really matter in any case. /Carol -->
In the *Cargo.toml* file, everything that follows a header is part of that
section that continues until another section starts. In `[dependencies]` you
tell Cargo which external crates your project depends on and which versions of
those crates you require. In this case, we specify the `rand` crate with the
-semantic version specifier `0.8.3`. Cargo understands Semantic Versioning
+semantic version specifier `0.8.5`. Cargo understands Semantic Versioning
(sometimes called *SemVer*), which is a standard for writing version numbers.
-The number `0.8.3` is actually shorthand for `^0.8.3`, which means any version
-that is at least `0.8.3` but below `0.9.0`.
+The specifier `0.8.5` is actually shorthand for `^0.8.5`, which means any
+version that is at least 0.8.5 but below 0.9.0.
Cargo considers these versions to have public APIs compatible with version
-`0.8.3`, and this specification ensures you’ll get the latest patch release
-that will still compile with the code in this chapter. Any version `0.9.0` or
-greater is not guaranteed to have the same API as what the following examples
-use.
+0.8.5, and this specification ensures you’ll get the latest patch release that
+will still compile with the code in this chapter. Any version 0.9.0 or greater
+is not guaranteed to have the same API as what the following examples use.
Now, without changing any of the code, let’s build the project, as shown in
Listing 2-2.
@@ -445,48 +396,34 @@ Listing 2-2.
```
$ cargo build
Updating crates.io index
- Downloaded rand v0.8.3
- Downloaded libc v0.2.86
- Downloaded getrandom v0.2.2
+ Downloaded rand v0.8.5
+ Downloaded libc v0.2.127
+ Downloaded getrandom v0.2.7
Downloaded cfg-if v1.0.0
- Downloaded ppv-lite86 v0.2.10
- Downloaded rand_chacha v0.3.0
- Downloaded rand_core v0.6.2
- Compiling rand_core v0.6.2
- Compiling libc v0.2.86
- Compiling getrandom v0.2.2
- Compiling cfg-if v1.0.0
- Compiling ppv-lite86 v0.2.10
- Compiling rand_chacha v0.3.0
- Compiling rand v0.8.3
- Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 2.53s
-```
-<!--- If we feel like refreshing this, here's what I saw today:
-
+ Downloaded ppv-lite86 v0.2.16
+ Downloaded rand_chacha v0.3.1
+ Downloaded rand_core v0.6.3
+ Compiling rand_core v0.6.3
+ Compiling libc v0.2.127
+ Compiling getrandom v0.2.7
Compiling cfg-if v1.0.0
Compiling ppv-lite86 v0.2.16
- Compiling libc v0.2.120
- Compiling getrandom v0.2.5
- Compiling rand_core v0.6.3
Compiling rand_chacha v0.3.1
Compiling rand v0.8.5
- Compiling guessing_game v0.1.0 (/Users/jt/Source/book/guessing_game)
- Finished dev [unoptimized + debuginfo] target(s) in 1.50s
-
-/JT --->
-<!-- I will refresh this when we're in Word /Carol -->
+ Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
+ Finished dev [unoptimized + debuginfo] target(s) in 2.53s
+```
-Listing 2-2: The output from running `cargo build` after adding the rand crate
-as a dependency
+Listing 2-2: The output from running `cargo build` after adding the `rand`
+crate as a dependency
You may see different version numbers (but they will all be compatible with the
-code, thanks to SemVer!), different lines (depending on the operating system),
-and the lines may be in a different order.
+code, thanks to SemVer!) and different lines (depending on the operating
+system), and the lines may be in a different order.
When we include an external dependency, Cargo fetches the latest versions of
everything that dependency needs from the *registry*, which is a copy of data
-from Crates.io at *https://crates.io/*. Crates.io is where people in the Rust
+from Crates.io at *https://crates.io*. Crates.io is where people in the Rust
ecosystem post their open source Rust projects for others to use.
After updating the registry, Cargo checks the `[dependencies]` section and
@@ -502,8 +439,8 @@ about them in your *Cargo.toml* file. Cargo also knows that you haven’t change
anything about your code, so it doesn’t recompile that either. With nothing to
do, it simply exits.
-If you open up the *src/main.rs* file, make a trivial change, and then save it
-and build again, you’ll only see two lines of output:
+If you open the *src/main.rs* file, make a trivial change, and then save it and
+build again, you’ll only see two lines of output:
```
$ cargo build
@@ -511,42 +448,30 @@ $ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
```
-These lines show Cargo only updates the build with your tiny change to the
+These lines show that Cargo only updates the build with your tiny change to the
*src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can
reuse what it has already downloaded and compiled for those.
-#### Ensuring Reproducible Builds with the *Cargo.lock* File
+#### Ensuring Reproducible Builds with the Cargo.lock File
Cargo has a mechanism that ensures you can rebuild the same artifact every time
you or anyone else builds your code: Cargo will use only the versions of the
dependencies you specified until you indicate otherwise. For example, say that
-next week version 0.8.4 of the `rand` crate comes out, and that version
+next week version 0.8.6 of the `rand` crate comes out, and that version
contains an important bug fix, but it also contains a regression that will
break your code. To handle this, Rust creates the *Cargo.lock* file the first
time you run `cargo build`, so we now have this in the *guessing_game*
directory.
-<!--- If we bump version numbers, we should bump above and below also. /JT --->
-<!-- Yup, will do in Word! /Carol -->
-
-When you build a project for the first time, Cargo figures out all the
-versions of the dependencies that fit the criteria and then writes them to
-the *Cargo.lock* file. When you build your project in the future, Cargo will
-see that the *Cargo.lock* file exists and use the versions specified there
+When you build a project for the first time, Cargo figures out all the versions
+of the dependencies that fit the criteria and then writes them to the
+*Cargo.lock* file. When you build your project in the future, Cargo will see
+that the *Cargo.lock* file exists and will use the versions specified there
rather than doing all the work of figuring out versions again. This lets you
have a reproducible build automatically. In other words, your project will
-remain at `0.8.3` until you explicitly upgrade, thanks to the *Cargo.lock*
-file. Because the *Cargo.lock* file is important for reproducible builds, it's
-often checked into source control with the rest of the code in your project.
-
-<!--- We could mention that because Cargo.lock is important for reproducible
-builds, they're often checked into source control alongside the Cargo.toml and
-the rest of the code of your project. /JT --->
-<!-- Liz, is this sentence ok even though we don't really talk about source
-control or what it is anywhere else in the book? I don't really want to get
-into it, but at this point I think it's a fair assumption that developers know
-what "source control" is. If you disagree, this sentence can come back out.
-/Carol -->
+remain at 0.8.5 until you explicitly upgrade, thanks to the *Cargo.lock* file.
+Because the *Cargo.lock* file is important for reproducible builds, it’s often
+checked into source control with the rest of the code in your project.
#### Updating a Crate to Get a New Version
@@ -554,24 +479,20 @@ When you *do* want to update a crate, Cargo provides the command `update`,
which will ignore the *Cargo.lock* file and figure out all the latest versions
that fit your specifications in *Cargo.toml*. Cargo will then write those
versions to the *Cargo.lock* file. Otherwise, by default, Cargo will only look
-for versions greater than `0.8.3` and less than `0.9.0`. If the `rand` crate
-has released the two new versions `0.8.4` and `0.9.0` you would see the
-following if you ran `cargo update`:
+for versions greater than 0.8.5 and less than 0.9.0. If the `rand` crate has
+released the two new versions 0.8.6 and 0.9.0, you would see the following if
+you ran `cargo update`:
```
$ cargo update
Updating crates.io index
- Updating rand v0.8.3 -> v0.8.4
+ Updating rand v0.8.5 -> v0.8.6
```
-Cargo ignores the `0.9.0` release. At this point, you would also notice a
-change in your *Cargo.lock* file noting that the version of the `rand` crate
-you are now using is `0.8.4`. To use `rand` version `0.9.0` or any version in
-the `0.9.x` series, you’d have to update the *Cargo.toml* file to look like
-this instead:
-
-<!--- Typo first line: release. /JT --->
-<!-- Fixed /Carol -->
+Cargo ignores the 0.9.0 release. At this point, you would also notice a change
+in your *Cargo.lock* file noting that the version of the `rand` crate you are
+now using is 0.8.6. To use `rand` version 0.9.0 or any version in the 0.9.*x*
+series, you’d have to update the *Cargo.toml* file to look like this instead:
```
[dependencies]
@@ -582,7 +503,7 @@ The next time you run `cargo build`, Cargo will update the registry of crates
available and reevaluate your `rand` requirements according to the new version
you have specified.
-There’s a lot more to say about Cargo and its ecosystem which we’ll discuss in
+There’s a lot more to say about Cargo and its ecosystem, which we’ll discuss in
Chapter 14, but for now, that’s all you need to know. Cargo makes it very easy
to reuse libraries, so Rustaceans are able to write smaller projects that are
assembled from a number of packages.
@@ -596,14 +517,14 @@ Filename: src/main.rs
```
use std::io;
-[1]use rand::Rng;
+1 use rand::Rng;
fn main() {
println!("Guess the number!");
- [2] let secret_number = rand::thread_rng().gen_range(1..=100);
+ 2 let secret_number = rand::thread_rng().gen_range(1..=100);
- [3] println!("The secret number is: {secret_number}");
+ 3 println!("The secret number is: {secret_number}");
println!("Please input your guess.");
@@ -617,50 +538,35 @@ fn main() {
}
```
-<!--- Same style suggestion re: `{secret_number}`. /JT --->
-<!--- Thought: for first-time readability, we could use `1..=100` in the above
-and let people know later this is equivalent to `1..101` later. We say a number
-between 1 and 100, so we could show the syntax equivalent of that description.
-/JT --->
-<!-- I'm into both these suggestions! /Carol -->
-
Listing 2-3: Adding code to generate a random number
-<!--- I can't remember how we handled wingdings in markdown before... I don't
-have those files on this machine. I've just used [x] for now, does that work?
-Then we'll replace them when we convert to Word /LC --->
-<!-- I don't think we added the wingdings at all until we moved to Word. For
-code listings that are the same as the last printing version, I'd definitely
-like to keep the wingdings the way they were. Using the brackets with numbers
-as you have here works fine! /Carol -->
-
-First, we add the line `use rand::Rng` [1]. The `Rng` trait defines methods
+First we add the line `use rand::Rng;` [1]. The `Rng` trait defines methods
that random number generators implement, and this trait must be in scope for us
to use those methods. Chapter 10 will cover traits in detail.
Next, we’re adding two lines in the middle. In the first line [2], we call the
`rand::thread_rng` function that gives us the particular random number
-generator that we’re going to use: one that is local to the current thread of
-execution and seeded by the operating system. Then we call the `gen_range`
+generator we’re going to use: one that is local to the current thread of
+execution and is seeded by the operating system. Then we call the `gen_range`
method on the random number generator. This method is defined by the `Rng`
-trait that we brought into scope with the `use rand::Rng` statement. The
+trait that we brought into scope with the `use rand::Rng;` statement. The
`gen_range` method takes a range expression as an argument and generates a
random number in the range. The kind of range expression we’re using here takes
the form `start..=end` and is inclusive on the lower and upper bounds, so we
need to specify `1..=100` to request a number between 1 and 100.
> Note: You won’t just know which traits to use and which methods and functions
-> to call from a crate, so each crate has documentation with instructions for
-> using it. Another neat feature of Cargo is that running the `cargo
-> doc --open` command will build documentation provided by all of your
-> dependencies locally and open it in your browser. If you’re interested in
-> other functionality in the `rand` crate, for example, run `cargo doc --open`
-> and click `rand` in the sidebar on the left.
-
-The second new line [3] prints the secret number. This is useful while
-we’re developing the program to be able to test it, but we’ll delete it from
-the final version. It’s not much of a game if the program prints the answer as
-soon as it starts!
+to call from a crate, so each crate has documentation with instructions for
+using it. Another neat feature of Cargo is that running the `cargo doc --open`
+command will build documentation provided by all your dependencies locally and
+open it in your browser. If you’re interested in other functionality in the
+`rand` crate, for example, run `cargo doc --open` and click `rand` in the
+sidebar on the left.
+
+The second new line [3] prints the secret number. This is useful while we’re
+developing the program to be able to test it, but we’ll delete it from the
+final version. It’s not much of a game if the program prints the answer as soon
+as it starts!
Try running the program a few times:
@@ -691,22 +597,22 @@ You should get different random numbers, and they should all be numbers between
## Comparing the Guess to the Secret Number
Now that we have user input and a random number, we can compare them. That step
-is shown in Listing 2-4. Note that this code won’t compile quite yet, as we
-will explain.
+is shown in Listing 2-4. Note that this code won’t compile just yet, as we will
+explain.
Filename: src/main.rs
```
use rand::Rng;
-[1]use std::cmp::Ordering;
+1 use std::cmp::Ordering;
use std::io;
fn main() {
- // --snip--
+ --snip--
println!("You guessed: {guess}");
- match[2] guess.cmp(&secret_number)[3] {
+ 2 match guess.3 cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
@@ -724,7 +630,7 @@ the three outcomes that are possible when you compare two values.
Then we add five new lines at the bottom that use the `Ordering` type. The
`cmp` method [3] compares two values and can be called on anything that can be
compared. It takes a reference to whatever you want to compare with: here it’s
-comparing the `guess` to the `secret_number`. Then it returns a variant of the
+comparing `guess` to `secret_number`. Then it returns a variant of the
`Ordering` enum we brought into scope with the `use` statement. We use a
`match` expression [2] to decide what to do next based on which variant of
`Ordering` was returned from the call to `cmp` with the values in `guess` and
@@ -734,14 +640,16 @@ A `match` expression is made up of *arms*. An arm consists of a *pattern* to
match against, and the code that should be run if the value given to `match`
fits that arm’s pattern. Rust takes the value given to `match` and looks
through each arm’s pattern in turn. Patterns and the `match` construct are
-powerful Rust features that let you express a variety of situations your code
-might encounter and make sure that you handle them all. These features will be
+powerful Rust features: they let you express a variety of situations your code
+might encounter and they make sure you handle them all. These features will be
covered in detail in Chapter 6 and Chapter 18, respectively.
Let’s walk through an example with the `match` expression we use here. Say that
the user has guessed 50 and the randomly generated secret number this time is
-38. When the code compares 50 to 38, the `cmp` method will return
-`Ordering::Greater`, because 50 is greater than 38. The `match` expression gets
+38.
+
+When the code compares 50 to 38, the `cmp` method will return
+`Ordering::Greater` because 50 is greater than 38. The `match` expression gets
the `Ordering::Greater` value and starts checking each arm’s pattern. It looks
at the first arm’s pattern, `Ordering::Less`, and sees that the value
`Ordering::Greater` does not match `Ordering::Less`, so it ignores the code in
@@ -751,11 +659,6 @@ code in that arm will execute and print `Too big!` to the screen. The `match`
expression ends after the first successful match, so it won’t look at the last
arm in this scenario.
-<!--- Since `match` always ends after the first successful match, we might want
-to just say that directly: "The `match` expression ends after the first successful
-match, so it won't look at the last arm in this scenario". /JT --->
-<!-- Sounds good, done! /Carol -->
-
However, the code in Listing 2-4 won’t compile yet. Let’s try it:
```
@@ -782,85 +685,79 @@ an `i32`, which is the type of `secret_number` unless you add type information
elsewhere that would cause Rust to infer a different numerical type. The reason
for the error is that Rust cannot compare a string and a number type.
-<!--- Typo: Unless otherwise specified. /JT --->
-<!-- Fixed /Carol -->
-
Ultimately, we want to convert the `String` the program reads as input into a
-real number type so we can compare it numerically to the secret number. We do so
-by adding this line to the `main` function body:
+real number type so we can compare it numerically to the secret number. We do
+so by adding this line to the `main` function body:
Filename: src/main.rs
```
- // --snip--
+--snip--
- let mut guess = String::new();
+let mut guess = String::new();
- io::stdin()
- .read_line(&mut guess)
- .expect("Failed to read line");
+io::stdin()
+ .read_line(&mut guess)
+ .expect("Failed to read line");
- let guess: u32 = guess.trim().parse().expect("Please type a number!");
+let guess: u32 = guess
+ .trim()
+ .parse()
+ .expect("Please type a number!");
- println!("You guessed: {guess}");
+println!("You guessed: {guess}");
- match guess.cmp(&secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
+match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => println!("You win!"),
+}
```
We create a variable named `guess`. But wait, doesn’t the program already have
-a variable named `guess`? It does, but helpfully Rust allows us to *shadow* the
-previous value of `guess` with a new one. Shadowing lets us reuse the `guess`
+a variable named `guess`? It does, but helpfully Rust allows us to shadow the
+previous value of `guess` with a new one. *Shadowing* lets us reuse the `guess`
variable name rather than forcing us to create two unique variables, such as
-`guess_str` and `guess` for example. We’ll cover this in more detail in Chapter
-3, but for now know that this feature is often used when you want to convert a
-value from one type to another type.
+`guess_str` and `guess`, for example. We’ll cover this in more detail in
+Chapter 3, but for now, know that this feature is often used when you want to
+convert a value from one type to another type.
We bind this new variable to the expression `guess.trim().parse()`. The `guess`
in the expression refers to the original `guess` variable that contained the
input as a string. The `trim` method on a `String` instance will eliminate any
whitespace at the beginning and end, which we must do to be able to compare the
string to the `u32`, which can only contain numerical data. The user must press
-<span class="keystroke">enter</span> to satisfy `read_line` and input their
-guess, which adds a newline character to the string. For example, if the user
-types <span class="keystroke">5</span> and presses <span
-class="keystroke">enter</span>, `guess` looks like this: `5\n`. The `\n`
-represents “newline”. (On Windows, pressing <span
-class="keystroke">enter</span> results in a carriage return and a newline,
-`\r\n`). The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`.
+enter to satisfy `read_line` and input their guess, which adds a newline
+character to the string. For example, if the user types `5` and presses enter,
+`guess` looks like this: `5\n`. The `\n` represents “newline.” (On Windows,
+pressing enter results in a carriage return and a newline, `\r\n`.) The `trim`
+method eliminates `\n` or `\r\n`, resulting in just `5`.
The `parse` method on strings converts a string to another type. Here, we use
it to convert from a string to a number. We need to tell Rust the exact number
type we want by using `let guess: u32`. The colon (`:`) after `guess` tells
Rust we’ll annotate the variable’s type. Rust has a few built-in number types;
the `u32` seen here is an unsigned, 32-bit integer. It’s a good default choice
-for a small positive number. You’ll learn about other number types in Chapter
-3. Additionally, the `u32` annotation in this example program and the
-comparison with `secret_number` means that Rust will infer that `secret_number`
-should be a `u32` as well. So now the comparison will be between two values of
-the same type!
+for a small positive number. You’ll learn about other number types in Chapter 3.
-<!--- More correct to say "The `parse` method converts a string to another type.
-Here, we use it to convert from a string to a number." You can use `parse` to
-convert to non-numeric types also. /JT --->
-<!-- Great catch, fixed! /Carol -->
+Additionally, the `u32` annotation in this example program and the comparison
+with `secret_number` means Rust will infer that `secret_number` should be a
+`u32` as well. So now the comparison will be between two values of the same
+type!
The `parse` method will only work on characters that can logically be converted
into numbers and so can easily cause errors. If, for example, the string
-contained `A👍%`, there would be no way to convert that to a number. Because it
-might fail, the `parse` method returns a `Result` type, much as the `read_line`
-method does (discussed earlier in “Handling Potential Failure with the `Result`
-Type”). We’ll treat this `Result` the same way by using the `expect` method
-again. If `parse` returns an `Err` `Result` variant because it couldn’t create
-a number from the string, the `expect` call will crash the game and print the
-message we give it. If `parse` can successfully convert the string to a number,
-it will return the `Ok` variant of `Result`, and `expect` will return the
-number that we want from the `Ok` value.
+contained `A`👍`%`, there would be no way to convert that to a number. Because
+it might fail, the `parse` method returns a `Result` type, much as the
+`read_line` method does (discussed earlier in “Handling Potential Failure with
+Result” on page XX). We’ll treat this `Result` the same way by using the
+`expect` method again. If `parse` returns an `Err` `Result` variant because it
+couldn’t create a number from the string, the `expect` call will crash the game
+and print the message we give it. If `parse` can successfully convert the
+string to a number, it will return the `Ok` variant of `Result`, and `expect`
+will return the number that we want from the `Ok` value.
-Let’s run the program now!
+Let’s run the program now:
```
$ cargo run
@@ -891,20 +788,19 @@ more chances at guessing the number:
Filename: src/main.rs
```
- // --snip--
+--snip--
- println!("The secret number is: {secret_number}");
+println!("The secret number is: {secret_number}");
- loop {
- println!("Please input your guess.");
+loop {
+ println!("Please input your guess.");
- // --snip--
+ --snip--
- match guess.cmp(&secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => println!("You win!"),
- }
+ match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => println!("You win!"),
}
}
```
@@ -915,11 +811,10 @@ and run the program again. The program will now ask for another guess forever,
which actually introduces a new problem. It doesn’t seem like the user can quit!
The user could always interrupt the program by using the keyboard shortcut
-<span class="keystroke">ctrl-c</span>. But there’s another way to escape this
-insatiable monster, as mentioned in the `parse` discussion in “Comparing the
-Guess to the Secret Number”: if the user enters a non-number answer, the
-program will crash. We can take advantage of that to allow the user to quit, as
-shown here:
+ctrl-C. But there’s another way to escape this insatiable monster, as mentioned
+in the `parse` discussion in “Comparing the Guess to the Secret Number” on page
+XX: if the user enters a non-number answer, the program will crash. We can take
+advantage of that to allow the user to quit, as shown here:
```
$ cargo run
@@ -942,12 +837,13 @@ You guessed: 59
You win!
Please input your guess.
quit
-thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/main.rs:28:47
+thread 'main' panicked at 'Please type a number!: ParseIntError
+{ kind: InvalidDigit }', src/main.rs:28:47
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
-Typing `quit` will quit the game, but as you’ll notice so will entering any
-other non-number input. This is suboptimal to say the least; we want the game
+Typing `quit` will quit the game, but as you’ll notice, so will entering any
+other non-number input. This is suboptimal, to say the least; we want the game
to also stop when the correct number is guessed.
### Quitting After a Correct Guess
@@ -957,16 +853,14 @@ Let’s program the game to quit when the user wins by adding a `break` statemen
Filename: src/main.rs
```
- // --snip--
+--snip--
- match guess.cmp(&secret_number) {
- Ordering::Less => println!("Too small!"),
- Ordering::Greater => println!("Too big!"),
- Ordering::Equal => {
- println!("You win!");
- break;
- }
- }
+match guess.cmp(&secret_number) {
+ Ordering::Less => println!("Too small!"),
+ Ordering::Greater => println!("Too big!"),
+ Ordering::Equal => {
+ println!("You win!");
+ break;
}
}
```
@@ -985,20 +879,20 @@ is converted from a `String` to a `u32`, as shown in Listing 2-5.
Filename: src/main.rs
```
- // --snip--
+--snip--
- io::stdin()
- .read_line(&mut guess)
- .expect("Failed to read line");
+io::stdin()
+ .read_line(&mut guess)
+ .expect("Failed to read line");
- let guess: u32 = match guess.trim().parse() {
- Ok(num) => num,
- Err(_) => continue,
- };
+let guess: u32 = match guess.trim().parse() {
+ Ok(num) => num,
+ Err(_) => continue,
+};
- println!("You guessed: {guess}");
+println!("You guessed: {guess}");
- // --snip--
+--snip--
```
Listing 2-5: Ignoring a non-number guess and asking for another guess instead
@@ -1011,7 +905,7 @@ a `match` expression here, as we did with the `Ordering` result of the `cmp`
method.
If `parse` is able to successfully turn the string into a number, it will
-return an `Ok` value that contains the resulting number. That `Ok` value will
+return an `Ok` value that contains the resultant number. That `Ok` value will
match the first arm’s pattern, and the `match` expression will just return the
`num` value that `parse` produced and put inside the `Ok` value. That number
will end up right where we want it in the new `guess` variable we’re creating.
@@ -1098,10 +992,10 @@ fn main() {
Listing 2-6: Complete guessing game code
-## Summary
-
At this point, you’ve successfully built the guessing game. Congratulations!
+## Summary
+
This project was a hands-on way to introduce you to many new Rust concepts:
`let`, `match`, functions, the use of external crates, and more. In the next
few chapters, you’ll learn about these concepts in more detail. Chapter 3
@@ -1109,3 +1003,4 @@ covers concepts that most programming languages have, such as variables, data
types, and functions, and shows how to use them in Rust. Chapter 4 explores
ownership, a feature that makes Rust different from other languages. Chapter 5
discusses structs and method syntax, and Chapter 6 explains how enums work.
+
diff --git a/src/doc/book/nostarch/chapter03.md b/src/doc/book/nostarch/chapter03.md
index 281f31d33..249032fd7 100644
--- a/src/doc/book/nostarch/chapter03.md
+++ b/src/doc/book/nostarch/chapter03.md
@@ -18,19 +18,19 @@ Specifically, you’ll learn about variables, basic types, functions, comments,
and control flow. These foundations will be in every Rust program, and learning
them early will give you a strong core to start from.
-> #### Keywords
+> ### Keywords
>
-> The Rust language has a set of *keywords* that are reserved for use by
-> the language only, much as in other languages. Keep in mind that you cannot
-> use these words as names of variables or functions. Most of the keywords have
-> special meanings, and you’ll be using them to do various tasks in your Rust
-> programs; a few have no current functionality associated with them but have
-> been reserved for functionality that might be added to Rust in the future. You
-> can find a list of the keywords in Appendix A.
+> The Rust language has a set of *keywords* that are reserved for use by the
+language only, much as in other languages. Keep in mind that you cannot use
+these words as names of variables or functions. Most of the keywords have
+special meanings, and you’ll be using them to do various tasks in your Rust
+programs; a few have no current functionality associated with them but have
+been reserved for functionality that might be added to Rust in the future. You
+can find a list of the keywords in Appendix A.
## Variables and Mutability
-As mentioned in the “Storing Values with Variables” section, by default
+As mentioned in “Storing Values with Variables” on page XX, by default,
variables are immutable. This is one of many nudges Rust gives you to write
your code in a way that takes advantage of the safety and easy concurrency that
Rust offers. However, you still have the option to make your variables mutable.
@@ -38,12 +38,11 @@ Let’s explore how and why Rust encourages you to favor immutability and why
sometimes you might want to opt out.
When a variable is immutable, once a value is bound to a name, you can’t change
-that value. To illustrate this, let’s generate a new project called *variables*
-in your *projects* directory by using `cargo new variables`.
+that value. To illustrate this, generate a new project called *variables* in
+your *projects* directory by using `cargo new variables`.
Then, in your new *variables* directory, open *src/main.rs* and replace its
-code with the following code. This code won’t compile just yet, we’ll first
-examine the immutability error.
+code with the following code, which won’t compile just yet:
Filename: src/main.rs
@@ -56,8 +55,8 @@ fn main() {
}
```
-Save and run the program using `cargo run`. You should receive an error
-message, as shown in this output:
+Save and run the program using `cargo run`. You should receive an error message
+regarding an immutability error, as shown in this output:
```
$ cargo run
@@ -80,9 +79,8 @@ Compiler errors can be frustrating, but really they only mean your program
isn’t safely doing what you want it to do yet; they do *not* mean that you’re
not a good programmer! Experienced Rustaceans still get compiler errors.
-The error message indicates that the cause of the error is that you `` cannot
-assign twice to immutable variable `x` ``, because you tried to assign a second
-value to the immutable `x` variable.
+You received the error message `cannot assign twice to immutable variable `x``
+because you tried to assign a second value to the immutable `x` variable.
It’s important that we get compile-time errors when we attempt to change a
value that’s designated as immutable because this very situation can lead to
@@ -91,15 +89,15 @@ never change and another part of our code changes that value, it’s possible
that the first part of the code won’t do what it was designed to do. The cause
of this kind of bug can be difficult to track down after the fact, especially
when the second piece of code changes the value only *sometimes*. The Rust
-compiler guarantees that when you state a value won’t change, it really won’t
-change, so you don’t have to keep track of it yourself. Your code is thus
+compiler guarantees that when you state that a value won’t change, it really
+won’t change, so you don’t have to keep track of it yourself. Your code is thus
easier to reason through.
But mutability can be very useful, and can make code more convenient to write.
-Variables are immutable only by default; as you did in Chapter 2, you can make
-them mutable by adding `mut` in front of the variable name. Adding `mut` also
-conveys intent to future readers of the code by indicating that other parts of
-the code will be changing this variable’s value.
+Although variables are immutable by default, you can make them mutable by
+adding `mut` in front of the variable name as you did in Chapter 2. Adding
+`mut` also conveys intent to future readers of the code by indicating that
+other parts of the code will be changing this variable’s value.
For example, let’s change *src/main.rs* to the following:
@@ -125,18 +123,10 @@ The value of x is: 5
The value of x is: 6
```
-We’re allowed to change the value bound to `x` from `5` to `6` when `mut`
-is used. Ultimately, deciding whether to use mutability or not is up to you and
+We’re allowed to change the value bound to `x` from `5` to `6` when `mut` is
+used. Ultimately, deciding whether to use mutability or not is up to you and
depends on what you think is clearest in that particular situation.
-<!--- Just to voice some thoughts here: there's a kind of bad pattern I see sometimes
-with the Rust dev mindset around performance. In my experience it happens maybe less
-often than you'd think that cloning shows up in the profile as a performance hit. I
-wonder if we should maybe tone down or remove the discussion of performance above
-because it's far stronger for the developer to pick a clear representation for their
-program and then improve performance after they've found that model. /JT --->
-<!-- Ok, I've removed the discussion of performance here. Good call. /Carol -->
-
### Constants
Like immutable variables, *constants* are values that are bound to a name and
@@ -146,9 +136,9 @@ and variables.
First, you aren’t allowed to use `mut` with constants. Constants aren’t just
immutable by default—they’re always immutable. You declare constants using the
`const` keyword instead of the `let` keyword, and the type of the value *must*
-be annotated. We’re about to cover types and type annotations in the next
-section, “Data Types,” so don’t worry about the details right now. Just know
-that you must always annotate the type.
+be annotated. We’ll cover types and type annotations in “Data Types” on page
+XX, so don’t worry about the details right now. Just know that you must always
+annotate the type.
Constants can be declared in any scope, including the global scope, which makes
them useful for values that many parts of code need to know about.
@@ -169,15 +159,15 @@ program). Rust’s naming convention for constants is to use all uppercase with
underscores between words. The compiler is able to evaluate a limited set of
operations at compile time, which lets us choose to write out this value in a
way that’s easier to understand and verify, rather than setting this constant
-to the value 10,800. See the Rust Reference’s section on constant evaluation at
-*https://doc.rust-lang.org/reference/const_eval.html* for more information on
-what operations can be used when declaring constants.
+to the value `10,800`. See the Rust Reference’s section on constant evaluation
+at *https://doc.rust-lang.org/reference/const_eval.html* for more information
+on what operations can be used when declaring constants.
-Constants are valid for the entire time a program runs, within the scope they
-were declared in. This property makes constants useful for values in your
-application domain that multiple parts of the program might need to know about,
-such as the maximum number of points any player of a game is allowed to earn or
-the speed of light.
+Constants are valid for the entire time a program runs, within the scope in
+which they were declared. This property makes constants useful for values in
+your application domain that multiple parts of the program might need to know
+about, such as the maximum number of points any player of a game is allowed to
+earn, or the speed of light.
Naming hardcoded values used throughout your program as constants is useful in
conveying the meaning of that value to future maintainers of the code. It also
@@ -195,21 +185,6 @@ variable name to itself until either it itself is shadowed or the scope ends.
We can shadow a variable by using the same variable’s name and repeating the
use of the `let` keyword as follows:
-<!--- A potential reword of the above for clarity:
-
-As you saw in the guessing game tutorial in Chapter 2, you can declare a new
-variable with the same name as a previous variable. Rustaceans say that the
-first variable is *shadowed* by the second, which means that the second
-variable is what the compiler will see when you use the name of the variable.
-In effect, the second variable overshadows the first, taking any uses of the
-variable name to itself until either it itself is shadowed or the scope ends.
-We can shadow a variable by using the same variable’s name and repeating the
-use of the `let` keyword as follows:
-
-/JT --->
-<!-- Sounds good to me, I've made the change to JT's version. What do you
-think, Liz? /Carol -->
-
Filename: src/main.rs
```
@@ -226,17 +201,6 @@ fn main() {
println!("The value of x is: {x}");
}
```
-<!--- We haven't really introduced block scoping yet. I know we're starting
-with variables, but I wonder if we should introduce scopes before shadowing,
-or explain that each block has its own set of variables.
-/JT --->
-<!-- Chapter 4 goes into scopes in more detail. I feel like block scoping is a
-pretty common programming concept, and the behavior of scopes in Rust that
-we're demonstrating here is the same behavior as scopes have in most other
-common programming languages. I don't recall getting comments from readers
-being confused about scopes at this point. I added a small phrase in the next
-paragraph that the curly brackets are creating a new scope... do you think
-that's enough, Liz? /Carol -->
This program first binds `x` to a value of `5`. Then it creates a new variable
`x` by repeating `let x =`, taking the original value and adding `1` so the
@@ -246,10 +210,6 @@ variable, multiplying the previous value by `2` to give `x` a value of `12`.
When that scope is over, the inner shadowing ends and `x` returns to being `6`.
When we run this program, it will output the following:
-<!--- I lean towards reiterating that each `let x` is creating a new variable.
-/JT -->
-<!-- I've added a few mentions to that effect in the previous paragraph, what do you think, Liz? /Carol -->
-
```
$ cargo run
Compiling variables v0.1.0 (file:///projects/variables)
@@ -259,46 +219,21 @@ The value of x in the inner scope is: 12
The value of x is: 6
```
-Shadowing is different from marking a variable as `mut`, because we’ll get a
+Shadowing is different from marking a variable as `mut` because we’ll get a
compile-time error if we accidentally try to reassign to this variable without
using the `let` keyword. By using `let`, we can perform a few transformations
on a value but have the variable be immutable after those transformations have
been completed.
-<!--- so, to be clear, we're not overwriting the variable, so when the
-shadowing variable goes out of scope the earlier variables become visible to
-the compiler? --->
-<!-- Well, we *are* overwriting it *in the inner scope* -- there's no way to
-access the original value from the outer scope within the inner scope after
-the shadowing. But yes, shadowing only applies to the scope it happens in,
-which is what this example illustrates. Is there something that could be
-made clearer? /Carol -->
-<!-- JT, what do you think, is this clear enough as is or is there some way to clarify in the text? /LC -->
-<!--- I made a couple notes above trying to see if we could tease out a good
-explanation. Shadowing is effectively creating new variables and then these
-variables get a kind of "higher priority" when you look up the same variable
-name. Shadowing priority is kind of a "most recent wins", and it stays until
-that variable is shadowed by a following one or that variable goes out of scope.
-/JT -->
-
The other difference between `mut` and shadowing is that because we’re
effectively creating a new variable when we use the `let` keyword again, we can
change the type of the value but reuse the same name. For example, say our
program asks a user to show how many spaces they want between some text by
inputting space characters, and then we want to store that input as a number:
-<!--- Question: the further I read, the more I wonder if we should put the shadowing
-stuff later. Is it valuable here as a kind of "building the right mental model" or
-are we using up too much of our complexity budget for building that mental model
-relatively early in the journey? Once we're introducing shadowing into new types
-we're getting relatively deep into Rust-specific coding patterns /JT -->
-<!-- I think it's important to address this here because shadowing is extremely
-common in idiomatic Rust code, but can be unfamiliar. I'm not sure where it
-would be appropriate to address if not here. /Carol -->
-
```
- let spaces = " ";
- let spaces = spaces.len();
+let spaces = " ";
+let spaces = spaces.len();
```
The first `spaces` variable is a string type and the second `spaces` variable
@@ -308,8 +243,8 @@ the simpler `spaces` name. However, if we try to use `mut` for this, as shown
here, we’ll get a compile-time error:
```
- let mut spaces = " ";
- spaces = spaces.len();
+let mut spaces = " ";
+spaces = spaces.len();
```
The error says we’re not allowed to mutate a variable’s type:
@@ -339,20 +274,16 @@ Keep in mind that Rust is a *statically typed* language, which means that it
must know the types of all variables at compile time. The compiler can usually
infer what type we want to use based on the value and how we use it. In cases
when many types are possible, such as when we converted a `String` to a numeric
-type using `parse` in the “Comparing the Guess to the Secret Number” section in
-Chapter 2, we must add a type annotation, like this:
+type using `parse` in “Comparing the Guess to the Secret Number” on page XX, we
+must add a type annotation, like this:
```
let guess: u32 = "42".parse().expect("Not a number!");
```
-If we don’t add the `: u32` type annotation above, Rust will display the
-following error, which means the compiler needs more information from us to
-know which type we want to use:
-
-<!--- To help visual parsing, you might want to say "If we don't add the `: u32` type
-annotation above... /JT --->
-<!-- Done /Carol -->
+If we don’t add the `: u32` type annotation shown in the preceding code, Rust
+will display the following error, which means the compiler needs more
+information from us to know which type we want to use:
```
$ cargo build
@@ -377,20 +308,20 @@ these from other programming languages. Let’s jump into how they work in Rust.
An *integer* is a number without a fractional component. We used one integer
type in Chapter 2, the `u32` type. This type declaration indicates that the
value it’s associated with should be an unsigned integer (signed integer types
-start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows
+start with `i` instead of `u`) that takes up 32 bits of space. Table 3-1 shows
the built-in integer types in Rust. We can use any of these variants to declare
the type of an integer value.
Table 3-1: Integer Types in Rust
-| Length | Signed | Unsigned |
-|---------|---------|----------|
-| 8-bit | `i8` | `u8` |
-| 16-bit | `i16` | `u16` |
-| 32-bit | `i32` | `u32` |
-| 64-bit | `i64` | `u64` |
-| 128-bit | `i128` | `u128` |
-| arch | `isize` | `usize` |
+| Length | Signed | Unsigned |
+|---|---|---|
+| 8-bit | `i8` | `u8` |
+| 16-bit | `i16` | `u16` |
+| 32-bit | `i32` | `u32` |
+| 64-bit | `i64` | `u64` |
+| 128-bit | `i128` | `u128` |
+| arch | `isize` | `usize` |
Each variant can be either signed or unsigned and has an explicit size.
*Signed* and *unsigned* refer to whether it’s possible for the number to be
@@ -420,55 +351,54 @@ have the same value as if you had specified `1000`.
Table 3-2: Integer Literals in Rust
-| Number literals | Example |
-|------------------|---------------|
-| Decimal | `98_222` |
-| Hex | `0xff` |
-| Octal | `0o77` |
-| Binary | `0b1111_0000` |
-| Byte (`u8` only) | `b'A'` |
+| Number literals | Example |
+|---|---|
+| Decimal | `98_222` |
+| Hex | `0xff` |
+| Octal | `0o77` |
+| Binary | `0b1111_0000` |
+| Byte (`u8` only) | `b'A'` |
So how do you know which type of integer to use? If you’re unsure, Rust’s
defaults are generally good places to start: integer types default to `i32`.
The primary situation in which you’d use `isize` or `usize` is when indexing
some sort of collection.
-> ##### Integer Overflow
+> ### Integer Overflow
>
> Let’s say you have a variable of type `u8` that can hold values between 0 and
-> 255. If you try to change the variable to a value outside of that range, such
-> as 256, *integer overflow* will occur, which can result in one of two
-> behaviors. When you’re compiling in debug mode, Rust includes checks for
-> integer overflow that cause your program to *panic* at runtime if this
-> behavior occurs. Rust uses the term panicking when a program exits with an
-> error; we’ll discuss panics in more depth in the “Unrecoverable Errors with
-> `panic!`” section in Chapter 9.
+255. If you try to change the variable to a value outside that range, such as
+256, *integer overflow* will occur, which can result in one of two behaviors.
+When you’re compiling in debug mode, Rust includes checks for integer overflow
+that cause your program to *panic* at runtime if this behavior occurs. Rust
+uses the term *panicking* when a program exits with an error; we’ll discuss
+panics in more depth in “Unrecoverable Errors with panic!” on page XX.
>
> When you’re compiling in release mode with the `--release` flag, Rust does
-> *not* include checks for integer overflow that cause panics. Instead, if
-> overflow occurs, Rust performs *two’s complement wrapping*. In short, values
-> greater than the maximum value the type can hold “wrap around” to the minimum
-> of the values the type can hold. In the case of a `u8`, the value 256 becomes
-> 0, the value 257 becomes 1, and so on. The program won’t panic, but the
-> variable will have a value that probably isn’t what you were expecting it to
-> have. Relying on integer overflow’s wrapping behavior is considered an error.
+*not* include checks for integer overflow that cause panics. Instead, if
+overflow occurs, Rust performs *two’s complement wrapping*. In short, values
+greater than the maximum value the type can hold “wrap around” to the minimum
+of the values the type can hold. In the case of a `u8`, the value 256 becomes
+0, the value 257 becomes 1, and so on. The program won’t panic, but the
+variable will have a value that probably isn’t what you were expecting it to
+have. Relying on integer overflow’s wrapping behavior is considered an error.
>
> To explicitly handle the possibility of overflow, you can use these families
-> of methods provided by the standard library for primitive numeric types:
+of methods provided by the standard library for primitive numeric types:
>
-> - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`
-> - Return the `None` value if there is overflow with the `checked_*` methods
-> - Return the value and a boolean indicating whether there was overflow with
-> the `overflowing_*` methods
-> - Saturate at the value’s minimum or maximum values with `saturating_*`
-> methods
+> * Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`.
+> * Return the `None` value if there is overflow with the `checked_*` methods.
+> * Return the value and a boolean indicating whether there was overflow with
+the `overflowing_*` methods.
+> * Saturate at the value’s minimum or maximum values with the `saturating_*`
+methods.
#### Floating-Point Types
Rust also has two primitive types for *floating-point numbers*, which are
numbers with decimal points. Rust’s floating-point types are `f32` and `f64`,
which are 32 bits and 64 bits in size, respectively. The default type is `f64`
-because on modern CPUs it’s roughly the same speed as `f32` but is capable of
+because on modern CPUs, it’s roughly the same speed as `f32` but is capable of
more precision. All floating-point types are signed.
Here’s an example that shows floating-point numbers in action:
@@ -488,9 +418,9 @@ Floating-point numbers are represented according to the IEEE-754 standard. The
#### Numeric Operations
-Rust supports the basic mathematical operations you’d expect for all of the
-number types: addition, subtraction, multiplication, division, and remainder.
-Integer division rounds down to the nearest integer. The following code shows
+Rust supports the basic mathematical operations you’d expect for all the number
+types: addition, subtraction, multiplication, division, and remainder. Integer
+division truncates toward zero to the nearest integer. The following code shows
how you’d use each numeric operation in a `let` statement:
Filename: src/main.rs
@@ -508,7 +438,7 @@ fn main() {
// division
let quotient = 56.7 / 32.2;
- let floored = 2 / 3; // Results in 0
+ let truncated = -5 / 3; // Results in -1
// remainder
let remainder = 43 % 5;
@@ -536,12 +466,12 @@ fn main() {
```
The main way to use Boolean values is through conditionals, such as an `if`
-expression. We’ll cover how `if` expressions work in Rust in the “Control
-Flow” section.
+expression. We’ll cover how `if` expressions work in Rust in “Control Flow” on
+page XX.
#### The Character Type
-Rust’s `char` type is the language’s most primitive alphabetic type. Here’s
+Rust’s `char` type is the language’s most primitive alphabetic type. Here are
some examples of declaring `char` values:
Filename: src/main.rs
@@ -563,7 +493,7 @@ Values range from `U+0000` to `U+D7FF` and `U+E000` to `U+10FFFF` inclusive.
However, a “character” isn’t really a concept in Unicode, so your human
intuition for what a “character” is may not match up with what a `char` is in
Rust. We’ll discuss this topic in detail in “Storing UTF-8 Encoded Text with
-Strings” in Chapter 8.
+Strings” on page XX.
### Compound Types
@@ -572,9 +502,9 @@ primitive compound types: tuples and arrays.
#### The Tuple Type
-A tuple is a general way of grouping together a number of values with a variety
-of types into one compound type. Tuples have a fixed length: once declared,
-they cannot grow or shrink in size.
+A *tuple* is a general way of grouping together a number of values with a
+variety of types into one compound type. Tuples have a fixed length: once
+declared, they cannot grow or shrink in size.
We create a tuple by writing a comma-separated list of values inside
parentheses. Each position in the tuple has a type, and the types of the
@@ -589,7 +519,7 @@ fn main() {
}
```
-The variable `tup` binds to the entire tuple, because a tuple is considered a
+The variable `tup` binds to the entire tuple because a tuple is considered a
single compound element. To get the individual values out of a tuple, we can
use pattern matching to destructure a tuple value, like this:
@@ -607,7 +537,7 @@ fn main() {
This program first creates a tuple and binds it to the variable `tup`. It then
uses a pattern with `let` to take `tup` and turn it into three separate
-variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks
+variables, `x`, `y`, and `z`. This is called *destructuring* because it breaks
the single tuple into three parts. Finally, the program prints the value of
`y`, which is `6.4`.
@@ -632,28 +562,11 @@ This program creates the tuple `x` and then accesses each element of the tuple
using their respective indices. As with most programming languages, the first
index in a tuple is 0.
-<!--- Indexing into a tuple using a constant, just like accessing a field of a struct,
-I think is maybe a more natural way to think of this than thinking of `x.0`, `x.1`, etc
-as separate variables. In the struct case, we don't think of each field as a separate
-variable, but instead that there's a path to get to the contained values that can be
-used and checked at compile time. /JT --->
-<!-- I think JT was actually confused with what this paragraph was trying to
-say, it was explaining that this particular example created new variables and
-bound them to the values of the tuple elements, not that the tuple elements
-*were* separate variables, so I've reworded this paragraph. Please check that
-this makes sense, Liz! /Carol -->
-
The tuple without any values has a special name, *unit*. This value and its
corresponding type are both written `()` and represent an empty value or an
empty return type. Expressions implicitly return the unit value if they don’t
return any other value.
-<!--- It's trick to see the difference between `()` and `()`. Maybe we can say: "The
-tuple without any values has a special name, *unit*. This value, and its corresponding
-type -- also written `()` -- represent an empty value or an empty return type." /JT --->
-<!-- I've tried to clear this up, but didn't take JT's suggestion exactly,
-there were too many subphrases in my opinion /Carol -->
-
#### The Array Type
Another way to have a collection of multiple values is with an *array*. Unlike
@@ -674,7 +587,7 @@ fn main() {
Arrays are useful when you want your data allocated on the stack rather than
the heap (we will discuss the stack and the heap more in Chapter 4) or when you
want to ensure you always have a fixed number of elements. An array isn’t as
-flexible as the vector type, though. A vector is a similar collection type
+flexible as the vector type, though. A *vector* is a similar collection type
provided by the standard library that *is* allowed to grow or shrink in size.
If you’re unsure whether to use an array or a vector, chances are you should
use a vector. Chapter 8 discusses vectors in more detail.
@@ -711,7 +624,7 @@ The array named `a` will contain `5` elements that will all be set to the value
`3` initially. This is the same as writing `let a = [3, 3, 3, 3, 3];` but in a
more concise way.
-##### Accessing Array Elements
+#### Accessing Array Elements
An array is a single chunk of memory of a known, fixed size that can be
allocated on the stack. You can access elements of an array using indexing,
@@ -728,11 +641,11 @@ fn main() {
}
```
-In this example, the variable named `first` will get the value `1`, because
-that is the value at index `[0]` in the array. The variable named `second` will
-get the value `2` from index `[1]` in the array.
+In this example, the variable named `first` will get the value `1` because that
+is the value at index `[0]` in the array. The variable named `second` will get
+the value `2` from index `[1]` in the array.
-##### Invalid Array Element Access
+#### Invalid Array Element Access
Let’s see what happens if you try to access an element of an array that is past
the end of the array. Say you run this code, similar to the guessing game in
@@ -768,12 +681,13 @@ fn main() {
```
This code compiles successfully. If you run this code using `cargo run` and
-enter 0, 1, 2, 3, or 4, the program will print out the corresponding value at
-that index in the array. If you instead enter a number past the end of the
-array, such as 10, you’ll see output like this:
+enter `0`, `1`, `2`, `3`, or `4`, the program will print out the corresponding
+value at that index in the array. If you instead enter a number past the end of
+the array, such as `10`, you’ll see output like this:
```
-thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19
+thread 'main' panicked at 'index out of bounds: the len is 5 but the index is
+10', src/main.rs:19:19
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
@@ -793,13 +707,6 @@ kind of error by immediately exiting instead of allowing the memory access and
continuing. Chapter 9 discusses more of Rust’s error handling and how you can
write readable, safe code that neither panics nor allows invalid memory access.
-<!--- I get the idea, though I'm feeling a little uneasy with leaving the reader
-thinking "panic > invalid access" as the end of the story. Maybe we can tag something
-on to the end: "Chapter 9 discusses more of Rust's error handling, and how you can
-write readable, safe code that doesn't panic and doesn't allow invalid memory access.
-/JT --->
-<!-- I've incorporated JT's suggestion with a bit of rewording above /Carol -->
-
## Functions
Functions are prevalent in Rust code. You’ve already seen one of the most
@@ -836,14 +743,6 @@ called from inside the `main` function. Note that we defined `another_function`
as well. Rust doesn’t care where you define your functions, only that they’re
defined somewhere in a scope that can be seen by the caller.
-<!--- nit: Rust does want the functions in a place the caller can see. If they're
-not in scope, Rust won't let the program build. Maybe we can say:
-"only that they're defined somewhere the caller can see them".
-or alt: "only that they're defined somewhere in a scope that can be seen by the
-caller"
-/JT --->
-<!-- Done! /Carol -->
-
Let’s start a new binary project named *functions* to explore functions
further. Place the `another_function` example in *src/main.rs* and run it. You
should see the following output:
@@ -858,8 +757,8 @@ Another function.
```
The lines execute in the order in which they appear in the `main` function.
-First, the “Hello, world!” message prints, and then `another_function` is
-called and its message is printed.
+First the “Hello, world!” message prints, and then `another_function` is called
+and its message is printed.
### Parameters
@@ -885,9 +784,6 @@ fn another_function(x: i32) {
}
```
-<!--- nit: might want to use `{x}` /JT --->
-<!-- Done! /Carol -->
-
Try running this program; you should get the following output:
```
@@ -909,9 +805,6 @@ definitions means the compiler almost never needs you to use them elsewhere in
the code to figure out what type you mean. The compiler is also able to give
more helpful error messages if it knows what types the function expects.
-<!--- Also helps give much better error messages /JT --->
-<!-- Added a note! /Carol -->
-
When defining multiple parameters, separate the parameter declarations with
commas, like this:
@@ -957,19 +850,14 @@ understand. Other languages don’t have the same distinctions, so let’s look
what statements and expressions are and how their differences affect the bodies
of functions.
-*Statements* are instructions that perform some action and do not return a
-value. *Expressions* evaluate to a resulting value. Let’s look at some examples.
+* **Statements **: are instructions that perform some action and do not return
+a value.
+* **Expressions **: evaluate to a resultant value. Let’s look at some examples.
We’ve actually already used statements and expressions. Creating a variable and
assigning a value to it with the `let` keyword is a statement. In Listing 3-1,
`let y = 6;` is a statement.
-<!--- To help clarify how they're related, we could say that "`let y = 6;`" is a
-statement, and the `6` being assigned to `y` is an expression. edit: I see we
-say this later, just thought it might be a little nicer to give an examples of
-each just following their definition. /JT --->
-<!-- I think I'm going to leave this as-is /Carol -->
-
Filename: src/main.rs
```
@@ -1007,33 +895,16 @@ error: expected expression, found statement (`let`)
|
= note: variable declaration using `let` is a statement
-error[E0658]: `let` expressions in this position are experimental
+error[E0658]: `let` expressions in this position are unstable
--> src/main.rs:2:14
|
2 | let x = (let y = 6);
| ^^^^^^^^^
|
- = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for more information
- = help: you can write `matches!(<expr>, <pattern>)` instead of `let <pattern> = <expr>`
-
-warning: unnecessary parentheses around assigned value
- --> src/main.rs:2:13
- |
-2 | let x = (let y = 6);
- | ^ ^
- |
- = note: `#[warn(unused_parens)]` on by default
-help: remove these parentheses
- |
-2 - let x = (let y = 6);
-2 + let x = let y = 6;
- |
+ = note: see issue #53667 <https://github.com/rust-lang/rust/issues/53667> for
+more information
```
-<!--- The errors in more recent Rust look slightly different here, if we want
-to update before publication. /JT --->
-<!-- Updated here and I will also check when we're in Word /Carol -->
-
The `let y = 6` statement does not return a value, so there isn’t anything for
`x` to bind to. This is different from what happens in other languages, such as
C and Ruby, where the assignment returns the value of the assignment. In those
@@ -1052,30 +923,22 @@ Filename: src/main.rs
```
fn main() {
- let y = {
+ 1 let y = {2
let x = 3;
- x + 1
+ 3 x + 1
};
println!("The value of y is: {y}");
}
```
-This expression:
-
-```
-{
- let x = 3;
- x + 1
-}
-```
-
-is a block that, in this case, evaluates to `4`. That value gets bound to `y`
-as part of the `let` statement. Note that the `x + 1` line doesn’t have a
-semicolon at the end, unlike most of the lines you’ve seen so far. Expressions
-do not include ending semicolons. If you add a semicolon to the end of an
-expression, you turn it into a statement, and it will then not return a value.
-Keep this in mind as you explore function return values and expressions next.
+The expression [2] is a block that, in this case, evaluates to `4`. That value
+gets bound to `y` as part of the `let` statement [1]. Note the line without a
+semicolon at the end [3], which is unlike most of the lines you’ve seen so far.
+Expressions do not include ending semicolons. If you add a semicolon to the end
+of an expression, you turn it into a statement, and it will then not return a
+value. Keep this in mind as you explore function return values and expressions
+next.
### Functions with Return Values
@@ -1128,10 +991,6 @@ Second, the `five` function has no parameters and defines the type of the
return value, but the body of the function is a lonely `5` with no semicolon
because it’s an expression whose value we want to return.
-<!--- If you want, you could point out that the `println!` line that main ends
-on is a statement, hence why main doesn't have a return value. /JT --->
-<!-- I don't think I want to :) /Carol -->
-
Let’s look at another example:
Filename: src/main.rs
@@ -1150,7 +1009,7 @@ fn plus_one(x: i32) -> i32 {
Running this code will print `The value of x is: 6`. But if we place a
semicolon at the end of the line containing `x + 1`, changing it from an
-expression to a statement, we’ll get an error.
+expression to a statement, we’ll get an error:
Filename: src/main.rs
@@ -1179,10 +1038,10 @@ error[E0308]: mismatched types
| |
| implicitly returns `()` as its body has no tail or `return` expression
8 | x + 1;
- | - help: consider removing this semicolon
+ | - help: remove this semicolon
```
-The main error message, “mismatched types,” reveals the core issue with this
+The main error message, `mismatched types`, reveals the core issue with this
code. The definition of the function `plus_one` says that it will return an
`i32`, but statements don’t evaluate to a value, which is expressed by `()`,
the unit type. Therefore, nothing is returned, which contradicts the function
@@ -1236,16 +1095,16 @@ fn main() {
```
Rust also has another kind of comment, documentation comments, which we’ll
-discuss in the “Publishing a Crate to Crates.io” section of Chapter 14.
+discuss in “Publishing a Crate to Crates.io” on page XX.
## Control Flow
-The ability to run some code depending on if a condition is true, or run some
-code repeatedly while a condition is true, are basic building blocks in most
-programming languages. The most common constructs that let you control the flow
-of execution of Rust code are `if` expressions and loops.
+The ability to run some code depending on whether a condition is `true` and to
+run some code repeatedly while a condition is `true` are basic building blocks
+in most programming languages. The most common constructs that let you control
+the flow of execution of Rust code are `if` expressions and loops.
-### `if` Expressions
+### if Expressions
An `if` expression allows you to branch your code depending on conditions. You
provide a condition and then state, “If this condition is met, run this block
@@ -1270,16 +1129,16 @@ fn main() {
All `if` expressions start with the keyword `if`, followed by a condition. In
this case, the condition checks whether or not the variable `number` has a
-value less than 5. We place the block of code to execute if the condition is true
-immediately after the condition inside curly brackets. Blocks of code
+value less than 5. We place the block of code to execute if the condition is
+`true` immediately after the condition inside curly brackets. Blocks of code
associated with the conditions in `if` expressions are sometimes called *arms*,
-just like the arms in `match` expressions that we discussed in the “Comparing
-the Guess to the Secret Number” section of Chapter 2.
+just like the arms in `match` expressions that we discussed in “Comparing the
+Guess to the Secret Number” on page XX.
-Optionally, we can also include an `else` expression, which we chose
-to do here, to give the program an alternative block of code to execute should
-the condition evaluate to false. If you don’t provide an `else` expression and
-the condition is false, the program will just skip the `if` block and move on
+Optionally, we can also include an `else` expression, which we chose to do
+here, to give the program an alternative block of code to execute should the
+condition evaluate to `false`. If you don’t provide an `else` expression and
+the condition is `false`, the program will just skip the `if` block and move on
to the next bit of code.
Try running this code; you should see the following output:
@@ -1359,7 +1218,7 @@ fn main() {
Running this code will print `number was something other than zero`.
-#### Handling Multiple Conditions with `else if`
+#### Handling Multiple Conditions with else if
You can use multiple conditions by combining `if` and `else` in an `else if`
expression. For example:
@@ -1394,17 +1253,17 @@ number is divisible by 3
```
When this program executes, it checks each `if` expression in turn and executes
-the first body for which the condition holds true. Note that even though 6 is
-divisible by 2, we don’t see the output `number is divisible by 2`, nor do we
-see the `number is not divisible by 4, 3, or 2` text from the `else` block.
-That’s because Rust only executes the block for the first true condition, and
-once it finds one, it doesn’t even check the rest.
+the first body for which the condition evaluates to `true`. Note that even
+though 6 is divisible by 2, we don’t see the output `number is divisible by 2`,
+nor do we see the `number is not divisible by 4, 3, or 2` text from the `else`
+block. That’s because Rust only executes the block for the first `true`
+condition, and once it finds one, it doesn’t even check the rest.
Using too many `else if` expressions can clutter your code, so if you have more
than one, you might want to refactor your code. Chapter 6 describes a powerful
Rust branching construct called `match` for these cases.
-#### Using `if` in a `let` Statement
+#### Using if in a let Statement
Because `if` is an expression, we can use it on the right side of a `let`
statement to assign the outcome to a variable, as in Listing 3-2.
@@ -1420,19 +1279,8 @@ fn main() {
}
```
-<!--- Style nit: `{number}`. /JT --->
-<!-- Fixed! /Carol -->
-
Listing 3-2: Assigning the result of an `if` expression to a variable
-<!--- I was wondering when listings got numbered and when they didn't. Many of
-the above don't get a number a title, though maybe it'd help readability? /JT --->
-<!-- Liz: Chapter 3 doesn't have many listing numbers because on the first
-round of printing, we hadn't really figured out what we were doing with listing
-numbers yet. I'm happy to add more listing numbers in Chapter 3, but it'll take
-me some time to go through and add appropriate captions, check cross
-references, etc. Let me know if you'd like me to spend that time. /Carol -->
-
The `number` variable will be bound to a value based on the outcome of the `if`
expression. Run this code to see what happens:
@@ -1475,7 +1323,8 @@ error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:4:44
|
4 | let number = if condition { 5 } else { "six" };
- | - ^^^^^ expected integer, found `&str`
+ | - ^^^^^ expected integer, found
+`&str`
| |
| expected because of this
```
@@ -1493,12 +1342,12 @@ if it had to keep track of multiple hypothetical types for any variable.
It’s often useful to execute a block of code more than once. For this task,
Rust provides several *loops*, which will run through the code inside the loop
-body to the end and then start immediately back at the beginning. To
-experiment with loops, let’s make a new project called *loops*.
+body to the end and then start immediately back at the beginning. To experiment
+with loops, let’s make a new project called *loops*.
Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one.
-#### Repeating Code with `loop`
+#### Repeating Code with loop
The `loop` keyword tells Rust to execute a block of code over and over again
forever or until you explicitly tell it to stop.
@@ -1517,9 +1366,9 @@ fn main() {
```
When we run this program, we’ll see `again!` printed over and over continuously
-until we stop the program manually. Most terminals support the keyboard shortcut
-<span class="keystroke">ctrl-c</span> to interrupt a program that is stuck in
-a continual loop. Give it a try:
+until we stop the program manually. Most terminals support the keyboard
+shortcut ctrl-C to interrupt a program that is stuck in a continual loop. Give
+it a try:
```
$ cargo run
@@ -1533,25 +1382,20 @@ again!
^Cagain!
```
-The symbol `^C` represents where you pressed <span class="keystroke">ctrl-c
-</span>. You may or may not see the word `again!` printed after the `^C`,
-depending on where the code was in the loop when it received the interrupt
-signal.
+The symbol `^C` represents where you pressed ctrl-C. You may or may not see the
+word `again!` printed after the `^C`, depending on where the code was in the
+loop when it received the interrupt signal.
Fortunately, Rust also provides a way to break out of a loop using code. You
can place the `break` keyword within the loop to tell the program when to stop
-executing the loop. Recall that we did this in the guessing game in the
-“Quitting After a Correct Guess” section of Chapter 2 to exit the program when
-the user won the game by guessing the correct number.
+executing the loop. Recall that we did this in the guessing game in “Quitting
+After a Correct Guess” on page XX to exit the program when the user won the
+game by guessing the correct number.
We also used `continue` in the guessing game, which in a loop tells the program
to skip over any remaining code in this iteration of the loop and go to the
next iteration.
-<!--- Before you show loop labels below, you might want to give a code example
-of using `break` to break a loop. /JT --->
-<!-- I've rearranged the sections to take this suggestion here /Carol -->
-
#### Returning Values from Loops
One of the uses of a `loop` is to retry an operation you know might fail, such
@@ -1580,20 +1424,18 @@ fn main() {
Before the loop, we declare a variable named `counter` and initialize it to
`0`. Then we declare a variable named `result` to hold the value returned from
the loop. On every iteration of the loop, we add `1` to the `counter` variable,
-and then check whether the counter is equal to `10`. When it is, we use the
+and then check whether the `counter` is equal to `10`. When it is, we use the
`break` keyword with the value `counter * 2`. After the loop, we use a
semicolon to end the statement that assigns the value to `result`. Finally, we
-print the value in `result`, which in this case is 20.
+print the value in `result`, which in this case is `20`.
#### Loop Labels to Disambiguate Between Multiple Loops
-<!-- Liz: New heading for this section, what do you think? /Carol -->
-
If you have loops within loops, `break` and `continue` apply to the innermost
-loop at that point. You can optionally specify a *loop label* on a loop that we
-can then use with `break` or `continue` to specify that those keywords apply to
-the labeled loop instead of the innermost loop. Loop labels must begin with a
-single quote. Here’s an example with two nested loops:
+loop at that point. You can optionally specify a *loop label* on a loop that
+you can then use with `break` or `continue` to specify that those keywords
+apply to the labeled loop instead of the innermost loop. Loop labels must begin
+with a single quote. Here’s an example with two nested loops:
```
fn main() {
@@ -1639,10 +1481,10 @@ remaining = 10
End count = 2
```
-#### Conditional Loops with `while`
+#### Conditional Loops with while
A program will often need to evaluate a condition within a loop. While the
-condition is true, the loop runs. When the condition ceases to be true, the
+condition is `true`, the loop runs. When the condition ceases to be `true`, the
program calls `break`, stopping the loop. It’s possible to implement behavior
like this using a combination of `loop`, `if`, `else`, and `break`; you could
try that now in a program, if you’d like. However, this pattern is so common
@@ -1666,13 +1508,14 @@ fn main() {
}
```
-Listing 3-3: Using a `while` loop to run code while a condition holds true
+Listing 3-3: Using a `while` loop to run code while a condition evaluates to
+`true`
This construct eliminates a lot of nesting that would be necessary if you used
-`loop`, `if`, `else`, and `break`, and it’s clearer. While a condition holds
-true, the code runs; otherwise, it exits the loop.
+`loop`, `if`, `else`, and `break`, and it’s clearer. While a condition
+evaluates to `true`, the code runs; otherwise, it exits the loop.
-#### Looping Through a Collection with `for`
+#### Looping Through a Collection with for
You can choose to use the `while` construct to loop over the elements of a
collection, such as an array. For example, the loop in Listing 3-4 prints each
@@ -1697,8 +1540,8 @@ Listing 3-4: Looping through each element of a collection using a `while` loop
Here, the code counts up through the elements in the array. It starts at index
`0`, and then loops until it reaches the final index in the array (that is,
-when `index < 5` is no longer true). Running this code will print every element
-in the array:
+when `index < 5` is no longer `true`). Running this code will print every
+element in the array:
```
$ cargo run
@@ -1717,8 +1560,8 @@ will reach a value of `5` at some point, the loop stops executing before trying
to fetch a sixth value from the array.
However, this approach is error prone; we could cause the program to panic if
-the index value or test condition are incorrect. For example, if you changed
-the definition of the `a` array to have four elements but forgot to update the
+the index value or test condition is incorrect. For example, if you changed the
+definition of the `a` array to have four elements but forgot to update the
condition to `while index < 4`, the code would panic. It’s also slow, because
the compiler adds runtime code to perform the conditional check of whether the
index is within the bounds of the array on every iteration through the loop.
@@ -1775,15 +1618,16 @@ This code is a bit nicer, isn’t it?
## Summary
-You made it! That was a sizable chapter: you learned about variables, scalar
-and compound data types, functions, comments, `if` expressions, and loops!
-To practice with the concepts discussed in this chapter, try building
-programs to do the following:
+You made it! This was a sizable chapter: you learned about variables, scalar
+and compound data types, functions, comments, `if` expressions, and loops! To
+practice with the concepts discussed in this chapter, try building programs to
+do the following:
* Convert temperatures between Fahrenheit and Celsius.
-* Generate the nth Fibonacci number.
+* Generate the *n*th Fibonacci number.
* Print the lyrics to the Christmas carol “The Twelve Days of Christmas,”
- taking advantage of the repetition in the song.
+taking advantage of the repetition in the song.
When you’re ready to move on, we’ll talk about a concept in Rust that *doesn’t*
commonly exist in other programming languages: ownership.
+
diff --git a/src/doc/book/nostarch/chapter04.md b/src/doc/book/nostarch/chapter04.md
index cbcad103e..11f7f4944 100644
--- a/src/doc/book/nostarch/chapter04.md
+++ b/src/doc/book/nostarch/chapter04.md
@@ -16,21 +16,15 @@ features: borrowing, slices, and how Rust lays data out in memory.
## What Is Ownership?
-*Ownership* is a set of rules that governs how a Rust program manages memory.
+*Ownership* is a set of rules that govern how a Rust program manages memory.
All programs have to manage the way they use a computer’s memory while running.
-Some languages have garbage collection that regularly looks for no-longer used
+Some languages have garbage collection that regularly looks for no-longer-used
memory as the program runs; in other languages, the programmer must explicitly
allocate and free the memory. Rust uses a third approach: memory is managed
through a system of ownership with a set of rules that the compiler checks. If
any of the rules are violated, the program won’t compile. None of the features
of ownership will slow down your program while it’s running.
-<!--- Minor nit: garbage collection isn't constant, it happens at times specified
-by the collection algorithm. Maybe "Some languages have garbage collection that
-regularly looks for no-longer used memory as the program runs."
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
Because ownership is a new concept for many programmers, it does take some time
to get used to. The good news is that the more experienced you become with Rust
and the rules of the ownership system, the easier you’ll find it to naturally
@@ -44,92 +38,63 @@ strings.
> ### The Stack and the Heap
>
> Many programming languages don’t require you to think about the stack and the
-> heap very often. But in a systems programming language like Rust, whether a
-> value is on the stack or the heap affects how the language behaves and why
-> you have to make certain decisions. Parts of ownership will be described in
-> relation to the stack and the heap later in this chapter, so here is a brief
-> explanation in preparation.
+heap very often. But in a systems programming language like Rust, whether a
+value is on the stack or the heap affects how the language behaves and why you
+have to make certain decisions. Parts of ownership will be described in
+relation to the stack and the heap later in this chapter, so here is a brief
+explanation in preparation.
>
> Both the stack and the heap are parts of memory available to your code to use
-> at runtime, but they are structured in different ways. The stack stores
-> values in the order it gets them and removes the values in the opposite
-> order. This is referred to as *last in, first out*. Think of a stack of
-> plates: when you add more plates, you put them on top of the pile, and when
-> you need a plate, you take one off the top. Adding or removing plates from
-> the middle or bottom wouldn’t work as well! Adding data is called *pushing
-> onto the stack*, and removing data is called *popping off the stack*. All
-> data stored on the stack must have a known, fixed size. Data with an unknown
-> size at compile time or a size that might change must be stored on the heap
-> instead.
+at runtime, but they are structured in different ways. The stack stores values
+in the order it gets them and removes the values in the opposite order. This is
+referred to as *last in, first out*. Think of a stack of plates: when you add
+more plates, you put them on top of the pile, and when you need a plate, you
+take one off the top. Adding or removing plates from the middle or bottom
+wouldn’t work as well! Adding data is called *pushing onto the stack*, and
+removing data is called *popping off the stack*. All data stored on the stack
+must have a known, fixed size. Data with an unknown size at compile time or a
+size that might change must be stored on the heap instead.
>
> The heap is less organized: when you put data on the heap, you request a
-> certain amount of space. The memory allocator finds an empty spot in the heap
-> that is big enough, marks it as being in use, and returns a *pointer*, which
-> is the address of that location. This process is called *allocating on the
-> heap* and is sometimes abbreviated as just *allocating* (pushing values onto
-> the stack is not considered allocating). Because the pointer to the heap is a
-> known, fixed size, you can store the pointer on the stack, but when you want
-> the actual data, you must follow the pointer. Think of being seated at a
-> restaurant. When you enter, you state the number of people in your group, and
-> the staff finds an empty table that fits everyone and leads you there. If
-> someone in your group comes late, they can ask where you’ve been seated to
-> find you.
+certain amount of space. The memory allocator finds an empty spot in the heap
+that is big enough, marks it as being in use, and returns a *pointer*, which is
+the address of that location. This process is called *allocating on the heap*
+and is sometimes abbreviated as just *allocating* (pushing values onto the
+stack is not considered allocating). Because the pointer to the heap is a
+known, fixed size, you can store the pointer on the stack, but when you want
+the actual data, you must follow the pointer. Think of being seated at a
+restaurant. When you enter, you state the number of people in your group, and
+the host finds an empty table that fits everyone and leads you there. If
+someone in your group comes late, they can ask where you’ve been seated to find
+you.
>
> Pushing to the stack is faster than allocating on the heap because the
-> allocator never has to search for a place to store new data; that location is
-> always at the top of the stack. Comparatively, allocating space on the heap
-> requires more work, because the allocator must first find a big enough space
-> to hold the data and then perform bookkeeping to prepare for the next
-> allocation.
-
-<!--- Minor nit: not sure if worth clarifying but thought I'd mention - performance
-for heap allocation I think isn't as much the time spent in the allocator but that
-you have to spend time asking the system for memory. Custom allocators still have to
-do the allocation step but try to avoid the system step where possible.
-/JT --->
-<!-- I think this is a bit in the weeds, not making any change here /Carol -->
-
+allocator never has to search for a place to store new data; that location is
+always at the top of the stack. Comparatively, allocating space on the heap
+requires more work because the allocator must first find a big enough space to
+hold the data and then perform bookkeeping to prepare for the next allocation.
+>
> Accessing data in the heap is slower than accessing data on the stack because
-> you have to follow a pointer to get there. Contemporary processors are faster
-> if they jump around less in memory. Continuing the analogy, consider a server
-> at a restaurant taking orders from many tables. It’s most efficient to get
-> all the orders at one table before moving on to the next table. Taking an
-> order from table A, then an order from table B, then one from A again, and
-> then one from B again would be a much slower process. By the same token, a
-> processor can do its job better if it works on data that’s close to other
-> data (as it is on the stack) rather than farther away (as it can be on the
-> heap).
-
-<!--- I don't quite understand the last sentence. If you allocate enough to create
-virtual memory, sure. But modern systems you're probably safe for most things? Also,
-if we're contrasting against something like the heap, just having the ability to allocate
-large space is probably a big benefit of the heap rather than a drawback. IMHO I'd probably
-just drop the last sentence.
-/JT --->
-<!-- Done! /Carol -->
-
+you have to follow a pointer to get there. Contemporary processors are faster
+if they jump around less in memory. Continuing the analogy, consider a server
+at a restaurant taking orders from many tables. It’s most efficient to get all
+the orders at one table before moving on to the next table. Taking an order
+from table A, then an order from table B, then one from A again, and then one
+from B again would be a much slower process. By the same token, a processor can
+do its job better if it works on data that’s close to other data (as it is on
+the stack) rather than farther away (as it can be on the heap).
>
> When your code calls a function, the values passed into the function
-> (including, potentially, pointers to data on the heap) and the function’s
-> local variables get pushed onto the stack. When the function is over, those
-> values get popped off the stack.
-
-<!--- Some calling conventions don't always use the stack for parameters.
-For example, Windows x64 calling convention puts the first 4 arguments into
-registers, and only puts args 5 and later on the stack. Ditto for the return
-value. If it can fit in a register, x64 will use that instead of the stack:
-
-https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#parameter-passing
-/JT --->
-<!-- I think this is a bit in the weeds, not making any change here /Carol -->
-
+(including, potentially, pointers to data on the heap) and the function’s local
+variables get pushed onto the stack. When the function is over, those values
+get popped off the stack.
>
> Keeping track of what parts of code are using what data on the heap,
-> minimizing the amount of duplicate data on the heap, and cleaning up unused
-> data on the heap so you don’t run out of space are all problems that ownership
-> addresses. Once you understand ownership, you won’t need to think about the
-> stack and the heap very often, but knowing that the main purpose of ownership
-> is to manage heap data can help explain why it works the way it does.
+minimizing the amount of duplicate data on the heap, and cleaning up unused
+data on the heap so you don’t run out of space are all problems that ownership
+addresses. Once you understand ownership, you won’t need to think about the
+stack and the heap very often, but knowing that the main purpose of ownership
+is to manage heap data can help explain why it works the way it does.
### Ownership Rules
@@ -140,14 +105,6 @@ work through the examples that illustrate them:
* There can only be one owner at a time.
* When the owner goes out of scope, the value will be dropped.
-<!--- Maybe splitting hairs, but for the first bullet I'd say:
-"Each value in Rust has an *owner*".
-
-If we say variables here, and then find out later that, for example, structs can
-also be owners, this gets a bit mirky.
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
### Variable Scope
Now that we’re past basic Rust syntax, we won’t include all the `fn main() {`
@@ -170,8 +127,8 @@ which it’s declared until the end of the current *scope*. Listing 4-1 shows a
program with comments annotating where the variable `s` would be valid.
```
-{ // s is not valid here, it’s not yet declared
- let s = "hello"; // s is valid from this point forward.
+{ // s is not valid here, since it's not yet declared
+ let s = "hello"; // s is valid from this point forward
// do stuff with s
} // this scope is now over, and s is no longer valid
@@ -181,23 +138,23 @@ Listing 4-1: A variable and the scope in which it is valid
In other words, there are two important points in time here:
-* When `s` comes *into scope*, it is valid.
-* It remains valid until it goes *out of scope*.
+* When `s` comes *into* scope, it is valid.
+* It remains valid until it goes *out of* scope.
At this point, the relationship between scopes and when variables are valid is
similar to that in other programming languages. Now we’ll build on top of this
understanding by introducing the `String` type.
-### The `String` Type
+### The String Type
To illustrate the rules of ownership, we need a data type that is more complex
-than those we covered in the “Data Types” section of Chapter 3. The types
-covered previously are all a known size, can be stored on the stack and popped
-off the stack when their scope is over, and can be quickly and trivially copied
-to make a new, independent instance if another part of code needs to use the
-same value in a different scope. But we want to look at data that is stored on
-the heap and explore how Rust knows when to clean up that data, and the
-`String` type is a great example.
+than those we covered in “Data Types” on page XX. The types covered previously
+are of a known size, can be stored on the stack and popped off the stack when
+their scope is over, and can be quickly and trivially copied to make a new,
+independent instance if another part of code needs to use the same value in a
+different scope. But we want to look at data that is stored on the heap and
+explore how Rust knows when to clean up that data, and the `String` type is a
+great example.
We’ll concentrate on the parts of `String` that relate to ownership. These
aspects also apply to other complex data types, whether they are provided by
@@ -220,9 +177,9 @@ let s = String::from("hello");
The double colon `::` operator allows us to namespace this particular `from`
function under the `String` type rather than using some sort of name like
-`string_from`. We’ll discuss this syntax more in the “Method Syntax” section of
-Chapter 5 and when we talk about namespacing with modules in “Paths for
-Referring to an Item in the Module Tree” in Chapter 7.
+`string_from`. We’ll discuss this syntax more in “Method Syntax” on page XX,
+and when we talk about namespacing with modules in “Paths for Referring to an
+Item in the Module Tree” on page XX.
This kind of string *can* be mutated:
@@ -231,11 +188,11 @@ let mut s = String::from("hello");
s.push_str(", world!"); // push_str() appends a literal to a String
-println!("{}", s); // This will print `hello, world!`
+println!("{s}"); // This will print `hello, world!`
```
So, what’s the difference here? Why can `String` be mutated but literals
-cannot? The difference is how these two types deal with memory.
+cannot? The difference is in how these two types deal with memory.
### Memory and Allocation
@@ -251,8 +208,8 @@ we need to allocate an amount of memory on the heap, unknown at compile time,
to hold the contents. This means:
* The memory must be requested from the memory allocator at runtime.
-* We need a way of returning this memory to the allocator when we’re
- done with our `String`.
+* We need a way of returning this memory to the allocator when we’re done with
+our `String`.
That first part is done by us: when we call `String::from`, its implementation
requests the memory it needs. This is pretty much universal in programming
@@ -261,19 +218,13 @@ languages.
However, the second part is different. In languages with a *garbage collector
(GC)*, the GC keeps track of and cleans up memory that isn’t being used
anymore, and we don’t need to think about it. In most languages without a GC,
-it’s our responsibility to identify when memory is no longer being used and
+it’s our responsibility to identify when memory is no longer being used and to
call code to explicitly free it, just as we did to request it. Doing this
correctly has historically been a difficult programming problem. If we forget,
we’ll waste memory. If we do it too early, we’ll have an invalid variable. If
we do it twice, that’s a bug too. We need to pair exactly one `allocate` with
exactly one `free`.
-<!--- The phrase "explicitly return it" gives a connotation in programming of
-returning a value to a caller rather than the more casual returning it to the OS.
-Maybe we can say "explicitly delete it" or "explicitly free it".
-/JT --->
-<!-- Changed "return" to "free" /Carol -->
-
Rust takes a different path: the memory is automatically returned once the
variable that owns it goes out of scope. Here’s a version of our scope example
from Listing 4-1 using a `String` instead of a string literal:
@@ -294,23 +245,23 @@ and it’s where the author of `String` can put the code to return the memory.
Rust calls `drop` automatically at the closing curly bracket.
> Note: In C++, this pattern of deallocating resources at the end of an item’s
-> lifetime is sometimes called *Resource Acquisition Is Initialization (RAII)*.
-> The `drop` function in Rust will be familiar to you if you’ve used RAII
-> patterns.
+lifetime is sometimes called *Resource Acquisition Is Initialization* *(RAII)*.
+The `drop` function in Rust will be familiar to you if you’ve used RAII
+patterns.
This pattern has a profound impact on the way Rust code is written. It may seem
simple right now, but the behavior of code can be unexpected in more
complicated situations when we want to have multiple variables use the data
we’ve allocated on the heap. Let’s explore some of those situations now.
-#### Ways Variables and Data Interact: Move
+#### Variables and Data Interacting with Move
Multiple variables can interact with the same data in different ways in Rust.
Let’s look at an example using an integer in Listing 4-2.
```
- let x = 5;
- let y = x;
+let x = 5;
+let y = x;
```
Listing 4-2: Assigning the integer value of variable `x` to `y`
@@ -324,8 +275,8 @@ onto the stack.
Now let’s look at the `String` version:
```
- let s1 = String::from("hello");
- let s2 = s1;
+let s1 = String::from("hello");
+let s2 = s1;
```
This looks very similar, so we might assume that the way it works would be the
@@ -338,38 +289,20 @@ the memory that holds the contents of the string, a length, and a capacity.
This group of data is stored on the stack. On the right is the memory on the
heap that holds the contents.
-<img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" />
-
-<!--- This might be me being a bit nitpicky - when you show what the string looks like
-in memory, we're showing indices for data pointed to by ptr. I have a bit of a knee-jerk
-reaction here since we don't think of strings has having indices in Rust (because of UTF-8)
-Not sure if it's well enough alone, or if it might be better for the ptr to point at
-at cells of memory without giving them indices.
-
-Something like:
-
-[ptr | --] -> [h][e][l][l][o]
-[len | 5]
-[capacity | 5]
-/JT --->
-<!-- I think this is a bit in the weeds, not making any change here /Carol -->
-
-Figure 4-1: Representation in memory of a `String` holding the value `"hello"`
+Figure 4-1: Representation in memory of a `String` holding the value `"hello"`
bound to `s1`
-The length is how much memory, in bytes, the contents of the `String` is
+The length is how much memory, in bytes, the contents of the `String` are
currently using. The capacity is the total amount of memory, in bytes, that the
-`String` has received from the allocator. The difference between length
-and capacity matters, but not in this context, so for now, it’s fine to ignore
-the capacity.
+`String` has received from the allocator. The difference between length and
+capacity matters, but not in this context, so for now, it’s fine to ignore the
+capacity.
When we assign `s1` to `s2`, the `String` data is copied, meaning we copy the
pointer, the length, and the capacity that are on the stack. We do not copy the
data on the heap that the pointer refers to. In other words, the data
representation in memory looks like Figure 4-2.
-<img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" />
-
Figure 4-2: Representation in memory of the variable `s2` that has a copy of
the pointer, length, and capacity of `s1`
@@ -378,8 +311,6 @@ look like if Rust instead copied the heap data as well. If Rust did this, the
operation `s2 = s1` could be very expensive in terms of runtime performance if
the data on the heap were large.
-<img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" />
-
Figure 4-3: Another possibility for what `s2 = s1` might do if Rust copied the
heap data as well
@@ -391,7 +322,7 @@ same memory. This is known as a *double free* error and is one of the memory
safety bugs we mentioned previously. Freeing memory twice can lead to memory
corruption, which can potentially lead to security vulnerabilities.
-To ensure memory safety, after the line `let s2 = s1`, Rust considers `s1` as
+To ensure memory safety, after the line `let s2 = s1;`, Rust considers `s1` as
no longer valid. Therefore, Rust doesn’t need to free anything when `s1` goes
out of scope. Check out what happens when you try to use `s1` after `s2` is
created; it won’t work:
@@ -400,7 +331,7 @@ created; it won’t work:
let s1 = String::from("hello");
let s2 = s1;
-println!("{}, world!", s1);
+println!("{s1}, world!");
```
You’ll get an error like this because Rust prevents you from using the
@@ -411,33 +342,32 @@ error[E0382]: borrow of moved value: `s1`
--> src/main.rs:5:28
|
2 | let s1 = String::from("hello");
- | -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
+ | -- move occurs because `s1` has type `String`, which
+ does not implement the `Copy` trait
3 | let s2 = s1;
| -- value moved here
4 |
-5 | println!("{}, world!", s1);
- | ^^ value borrowed here after move
+5 | println!("{s1}, world!");
+ | ^^ value borrowed here after move
```
If you’ve heard the terms *shallow copy* and *deep copy* while working with
other languages, the concept of copying the pointer, length, and capacity
without copying the data probably sounds like making a shallow copy. But
-because Rust also invalidates the first variable, instead of calling it a
-shallow copy, it’s known as a *move*. In this example, we would say that
-`s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4.
-
-<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />
+because Rust also invalidates the first variable, instead of being called a
+shallow copy, it’s known as a *move*. In this example, we would say that `s1`
+was *moved* into `s2`. So, what actually happens is shown in Figure 4-4.
Figure 4-4: Representation in memory after `s1` has been invalidated
-That solves our problem! With only `s2` valid, when it goes out of scope, it
+That solves our problem! With only `s2` valid, when it goes out of scope it
alone will free the memory, and we’re done.
In addition, there’s a design choice that’s implied by this: Rust will never
automatically create “deep” copies of your data. Therefore, any *automatic*
copying can be assumed to be inexpensive in terms of runtime performance.
-#### Ways Variables and Data Interact: Clone
+#### Variables and Data Interacting with Clone
If we *do* want to deeply copy the heap data of the `String`, not just the
stack data, we can use a common method called `clone`. We’ll discuss method
@@ -450,7 +380,7 @@ Here’s an example of the `clone` method in action:
let s1 = String::from("hello");
let s2 = s1.clone();
-println!("s1 = {}, s2 = {}", s1, s2);
+println!("s1 = {s1}, s2 = {s2}");
```
This works just fine and explicitly produces the behavior shown in Figure 4-3,
@@ -462,14 +392,14 @@ different is going on.
#### Stack-Only Data: Copy
-There’s another wrinkle we haven’t talked about yet. This code using integers –
-part of which was shown in Listing 4-2 – works and is valid:
+There’s another wrinkle we haven’t talked about yet. This code using
+integers—part of which was shown in Listing 4-2—works and is valid:
```
let x = 5;
let y = x;
-println!("x = {}, y = {}", x, y);
+println!("x = {x}, y = {y}");
```
But this code seems to contradict what we just learned: we don’t have a call to
@@ -480,7 +410,7 @@ time are stored entirely on the stack, so copies of the actual values are quick
to make. That means there’s no reason we would want to prevent `x` from being
valid after we create the variable `y`. In other words, there’s no difference
between deep and shallow copying here, so calling `clone` wouldn’t do anything
-different from the usual shallow copying and we can leave it out.
+different from the usual shallow copying, and we can leave it out.
Rust has a special annotation called the `Copy` trait that we can place on
types that are stored on the stack, as integers are (we’ll talk more about
@@ -488,29 +418,13 @@ traits in Chapter 10). If a type implements the `Copy` trait, variables that
use it do not move, but rather are trivially copied, making them still valid
after assignment to another variable.
-<!--- an older variable that uses that type, we mean? /LC --->
-<!-- I removed "older" here, I don't think that was quite right-- this sentence
-is trying to describe the line `let y = x` where the variable `x` is assigned
-to `y`. The variables must be the same type because they're getting the same
-value, so "that uses that type" isn't relevant. Let me know if there's any
-aspects that are still confusing here. /Carol -->
-<!-- JT, is this all clear in the text? /LC -->
-<!--- I think this is fine. When I teach it, I tend to stress *move* and *copy*
-so that they can build up that framework. So my slight tweak to the above might
-be:
-
-"If a type implements the `Copy` trait, variables that use it do not move but rather are
-trivially copied, making them still valid after assignment to another variable."
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
Rust won’t let us annotate a type with `Copy` if the type, or any of its parts,
has implemented the `Drop` trait. If the type needs something special to happen
when the value goes out of scope and we add the `Copy` annotation to that type,
we’ll get a compile-time error. To learn about how to add the `Copy` annotation
-to your type to implement the trait, see “Derivable Traits” in Appendix C.
+to your type to implement the trait, see “Derivable Traits” on page XX.
-So what types implement the `Copy` trait? You can check the documentation for
+So, what types implement the `Copy` trait? You can check the documentation for
the given type to be sure, but as a general rule, any group of simple scalar
values can implement `Copy`, and nothing that requires allocation or is some
form of resource can implement `Copy`. Here are some of the types that
@@ -518,10 +432,10 @@ implement `Copy`:
* All the integer types, such as `u32`.
* The Boolean type, `bool`, with values `true` and `false`.
-* All the floating point types, such as `f64`.
+* All the floating-point types, such as `f64`.
* The character type, `char`.
* Tuples, if they only contain types that also implement `Copy`. For example,
- `(i32, i32)` implements `Copy`, but `(i32, String)` does not.
+`(i32, i32)` implements `Copy`, but `(i32, String)` does not.
### Ownership and Functions
@@ -530,9 +444,8 @@ assigning a value to a variable. Passing a variable to a function will move or
copy, just as assignment does. Listing 4-3 has an example with some annotations
showing where variables go into and out of scope.
-Filename: src/main.rs
-
```
+// src/main.rs
fn main() {
let s = String::from("hello"); // s comes into scope
@@ -545,17 +458,17 @@ fn main() {
// but i32 is Copy, so it's okay to still
// use x afterward
-} // Here, x goes out of scope, then s. But because s's value was moved, nothing
- // special happens.
+} // Here, x goes out of scope, then s. However, because s's value was moved,
+ // nothing special happens
fn takes_ownership(some_string: String) { // some_string comes into scope
- println!("{}", some_string);
+ println!("{some_string}");
} // Here, some_string goes out of scope and `drop` is called. The backing
- // memory is freed.
+ // memory is freed
fn makes_copy(some_integer: i32) { // some_integer comes into scope
- println!("{}", some_integer);
-} // Here, some_integer goes out of scope. Nothing special happens.
+ println!("{some_integer}");
+} // Here, some_integer goes out of scope. Nothing special happens
```
Listing 4-3: Functions with ownership and scope annotated
@@ -567,13 +480,12 @@ the ownership rules prevent you from doing so.
### Return Values and Scope
-Returning values can also transfer ownership. Listing 4-4 shows an example
-of a function that returns some value, with similar annotations as those in
-Listing 4-3.
-
-Filename: src/main.rs
+Returning values can also transfer ownership. Listing 4-4 shows an example of a
+function that returns some value, with similar annotations as those in Listing
+4-3.
```
+// src/main.rs
fn main() {
let s1 = gives_ownership(); // gives_ownership moves its return
// value into s1
@@ -584,7 +496,7 @@ fn main() {
// takes_and_gives_back, which also
// moves its return value into s3
} // Here, s3 goes out of scope and is dropped. s2 was moved, so nothing
- // happens. s1 goes out of scope and is dropped.
+ // happens. s1 goes out of scope and is dropped
fn gives_ownership() -> String { // gives_ownership will move its
// return value into the function
@@ -597,7 +509,7 @@ fn gives_ownership() -> String { // gives_ownership will move its
// function
}
-// This function takes a String and returns one
+// This function takes a String and returns a String
fn takes_and_gives_back(a_string: String) -> String { // a_string comes into
// scope
@@ -628,7 +540,7 @@ fn main() {
let (s2, len) = calculate_length(s1);
- println!("The length of '{}' is {}.", s2, len);
+ println!("The length of '{s2}' is {len}.");
}
fn calculate_length(s: String) -> (String, usize) {
@@ -655,12 +567,6 @@ the data stored at that address; that data is owned by some other variable.
Unlike a pointer, a reference is guaranteed to point to a valid value of a
particular type for the life of that reference.
-<!--- Possible wording tweak: "a reference is guaranteed to point to a valid value of a
-particular type for the life of that reference" or "a reference is always guaranteed
-to point to a valid value of a particular type"
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
Here is how you would define and use a `calculate_length` function that has a
reference to an object as a parameter instead of taking ownership of the value:
@@ -672,7 +578,7 @@ fn main() {
let len = calculate_length(&s1);
- println!("The length of '{}' is {}.", s1, len);
+ println!("The length of '{s1}' is {len}.");
}
fn calculate_length(s: &String) -> usize {
@@ -686,14 +592,12 @@ function return value is gone. Second, note that we pass `&s1` into
`String`. These ampersands represent *references*, and they allow you to refer
to some value without taking ownership of it. Figure 4-5 depicts this concept.
-<img alt="&String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
-
Figure 4-5: A diagram of `&String s` pointing at `String s1`
> Note: The opposite of referencing by using `&` is *dereferencing*, which is
-> accomplished with the dereference operator, `*`. We’ll see some uses of the
-> dereference operator in Chapter 8 and discuss details of dereferencing in
-> Chapter 15.
+accomplished with the dereference operator, `*`. We’ll see some uses of the
+dereference operator in Chapter 8 and discuss details of dereferencing in
+Chapter 15.
Let’s take a closer look at the function call here:
@@ -714,12 +618,12 @@ the parameter `s` is a reference. Let’s add some explanatory annotations:
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // Here, s goes out of scope. But because it does not have ownership of what
- // it refers to, it is not dropped.
+ // it refers to, the String is not dropped
```
The scope in which the variable `s` is valid is the same as any function
parameter’s scope, but the value pointed to by the reference is not dropped
-when `s` stops being used because `s` doesn’t have ownership. When functions
+when `s` stops being used, because `s` doesn’t have ownership. When functions
have references as parameters instead of the actual values, we won’t need to
return the values in order to give back ownership, because we never had
ownership.
@@ -728,7 +632,7 @@ We call the action of creating a reference *borrowing*. As in real life, if a
person owns something, you can borrow it from them. When you’re done, you have
to give it back. You don’t own it.
-So what happens if we try to modify something we’re borrowing? Try the code in
+So, what happens if we try to modify something we’re borrowing? Try the code in
Listing 4-6. Spoiler alert: it doesn’t work!
Filename: src/main.rs
@@ -750,13 +654,16 @@ Listing 4-6: Attempting to modify a borrowed value
Here’s the error:
```
-error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
+error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&`
+reference
--> src/main.rs:8:5
|
7 | fn change(some_string: &String) {
- | ------- help: consider changing this to be a mutable reference: `&mut String`
+ | ------- help: consider changing this to be a mutable
+reference: `&mut String`
8 | some_string.push_str(", world");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so
+the data it refers to cannot be borrowed as mutable
```
Just as variables are immutable by default, so are references. We’re not
@@ -781,7 +688,7 @@ fn change(some_string: &mut String) {
}
```
-First, we change `s` to be `mut`. Then we create a mutable reference with `&mut
+First we change `s` to be `mut`. Then we create a mutable reference with `&mut
s` where we call the `change` function, and update the function signature to
accept a mutable reference with `some_string: &mut String`. This makes it very
clear that the `change` function will mutate the value it borrows.
@@ -790,22 +697,15 @@ Mutable references have one big restriction: if you have a mutable reference to
a value, you can have no other references to that value. This code that
attempts to create two mutable references to `s` will fail:
-<!--- Clarification: "Mutable references have one big restriction: if you have a
-mutable reference to a value, you can have no other references to that value."
-This covers both not having two mutable references and having a mutable references
-and an immutable reference to the same value.
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
Filename: src/main.rs
```
- let mut s = String::from("hello");
+let mut s = String::from("hello");
- let r1 = &mut s;
- let r2 = &mut s;
+let r1 = &mut s;
+let r2 = &mut s;
- println!("{}, {}", r1, r2);
+println!("{r1}, {r2}");
```
Here’s the error:
@@ -819,8 +719,8 @@ error[E0499]: cannot borrow `s` as mutable more than once at a time
5 | let r2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
6 |
-7 | println!("{}, {}", r1, r2);
- | -- first borrow later used here
+7 | println!("{r1}, {r2}");
+ | -- first borrow later used here
```
This error says that this code is invalid because we cannot borrow `s` as
@@ -831,7 +731,7 @@ in `r2` that borrows the same data as `r1`.
The restriction preventing multiple mutable references to the same data at the
same time allows for mutation but in a very controlled fashion. It’s something
-that new Rustaceans struggle with, because most languages let you mutate
+that new Rustaceans struggle with because most languages let you mutate
whenever you’d like. The benefit of having this restriction is that Rust can
prevent data races at compile time. A *data race* is similar to a race
condition and happens when these three behaviors occur:
@@ -841,8 +741,8 @@ condition and happens when these three behaviors occur:
* There’s no mechanism being used to synchronize access to the data.
Data races cause undefined behavior and can be difficult to diagnose and fix
-when you’re trying to track them down at runtime; Rust prevents this problem
-by refusing to compile code with data races!
+when you’re trying to track them down at runtime; Rust prevents this problem by
+refusing to compile code with data races!
As always, we can use curly brackets to create a new scope, allowing for
multiple mutable references, just not *simultaneous* ones:
@@ -852,7 +752,7 @@ let mut s = String::from("hello");
{
let r1 = &mut s;
-} // r1 goes out of scope here, so we can make a new reference with no problems.
+} // r1 goes out of scope here, so we can make a new reference with no problems
let r2 = &mut s;
```
@@ -867,13 +767,14 @@ let r1 = &s; // no problem
let r2 = &s; // no problem
let r3 = &mut s; // BIG PROBLEM
-println!("{}, {}, and {}", r1, r2, r3);
+println!("{r1}, {r2}, and {r3}");
```
Here’s the error:
```
-error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
+error[E0502]: cannot borrow `s` as mutable because it is also borrowed as
+immutable
--> src/main.rs:6:14
|
4 | let r1 = &s; // no problem
@@ -882,8 +783,8 @@ error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immuta
6 | let r3 = &mut s; // BIG PROBLEM
| ^^^^^^ mutable borrow occurs here
7 |
-8 | println!("{}, {}, and {}", r1, r2, r3);
- | -- immutable borrow later used here
+8 | println!("{r1}, {r2}, and {r3}");
+ | -- immutable borrow later used here
```
Whew! We *also* cannot have a mutable reference while we have an immutable one
@@ -904,20 +805,18 @@ let mut s = String::from("hello");
let r1 = &s; // no problem
let r2 = &s; // no problem
-println!("{} and {}", r1, r2);
+println!("{r1} and {r2}");
// variables r1 and r2 will not be used after this point
let r3 = &mut s; // no problem
-println!("{}", r3);
+println!("{r3}");
```
The scopes of the immutable references `r1` and `r2` end after the `println!`
where they are last used, which is before the mutable reference `r3` is
-created. These scopes don’t overlap, so this code is allowed. The ability of
-the compiler to tell that a reference is no longer being used at a point before
-the end of the scope is called *Non-Lexical Lifetimes* (NLL for short), and you
-can read more about it in The Edition Guide at
-*https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.html*.
+created. These scopes don’t overlap, so this code is allowed: the compiler can
+tell that the reference is no longer being used at a point before the end of
+the scope.
Even though borrowing errors may be frustrating at times, remember that it’s
the Rust compiler pointing out a potential bug early (at compile time rather
@@ -927,9 +826,9 @@ have to track down why your data isn’t what you thought it was.
### Dangling References
In languages with pointers, it’s easy to erroneously create a *dangling
-pointer*--a pointer that references a location in memory that may have been
-given to someone else--by freeing some memory while preserving a pointer to
-that memory. In Rust, by contrast, the compiler guarantees that references will
+pointer*—a pointer that references a location in memory that may have been
+given to someone else—by freeing some memory while preserving a pointer to that
+memory. In Rust, by contrast, the compiler guarantees that references will
never be dangling references: if you have a reference to some data, the
compiler will ensure that the data will not go out of scope before the
reference to the data does.
@@ -960,7 +859,8 @@ error[E0106]: missing lifetime specifier
5 | fn dangle() -> &String {
| ^ expected named lifetime parameter
|
- = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+ = help: this function's return type contains a borrowed value,
+but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
5 | fn dangle() -> &'static String {
@@ -972,22 +872,21 @@ discuss lifetimes in detail in Chapter 10. But, if you disregard the parts
about lifetimes, the message does contain the key to why this code is a problem:
```
-this function's return type contains a borrowed value, but there is no value
-for it to be borrowed from
+this function's return type contains a borrowed value, but there
+is no value for it to be borrowed from
```
Let’s take a closer look at exactly what’s happening at each stage of our
`dangle` code:
-Filename: src/main.rs
-
```
+// src/main.rs
fn dangle() -> &String { // dangle returns a reference to a String
let s = String::from("hello"); // s is a new String
&s // we return a reference to the String, s
-} // Here, s goes out of scope, and is dropped. Its memory goes away.
+} // Here, s goes out of scope and is dropped, so its memory goes away
// Danger!
```
@@ -1014,7 +913,7 @@ deallocated.
Let’s recap what we’ve discussed about references:
* At any given time, you can have *either* one mutable reference *or* any
- number of immutable references.
+number of immutable references.
* References must always be valid.
Next, we’ll look at a different kind of reference: slices.
@@ -1030,12 +929,6 @@ words separated by spaces and returns the first word it finds in that string.
If the function doesn’t find a space in the string, the whole string must be
one word, so the entire string should be returned.
-<!--- Do we want to clarify this is for words separated by spaces?
-Not all languages use spaces to separate words:
-https://www.w3.org/International/articles/typography/linebreak.en#whatisword
-/JT --->
-<!-- Took this suggestion! /Carol -->
-
Let’s work through how we’d write the signature of this function without using
slices, to understand the problem that slices will solve:
@@ -1052,15 +945,15 @@ Filename: src/main.rs
```
fn first_word(s: &String) -> usize {
- [1] let bytes = s.as_bytes();
+ 1 let bytes = s.as_bytes();
- for (i, &item)[2] in bytes.iter()[3].enumerate() {
- [4] if item == b' ' {
+ for (2 i, &item) in 3 bytes.iter().enumerate() {
+ 4 if item == b' ' {
return i;
}
}
- [5] s.len()
+ 5 s.len()
}
```
@@ -1071,13 +964,13 @@ Because we need to go through the `String` element by element and check whether
a value is a space, we’ll convert our `String` to an array of bytes using the
`as_bytes` method [1].
-Next, we create an iterator over the array of bytes using the `iter` method [3].
-We’ll discuss iterators in more detail in Chapter 13. For now, know that `iter`
-is a method that returns each element in a collection and that `enumerate`
-wraps the result of `iter` and returns each element as part of a tuple instead.
-The first element of the tuple returned from `enumerate` is the index, and the
-second element is a reference to the element. This is a bit more convenient
-than calculating the index ourselves.
+Next, we create an iterator over the array of bytes using the `iter` method
+[3]. We’ll discuss iterators in more detail in Chapter 13. For now, know that
+`iter` is a method that returns each element in a collection and that
+`enumerate` wraps the result of `iter` and returns each element as part of a
+tuple instead. The first element of the tuple returned from `enumerate` is the
+index, and the second element is a reference to the element. This is a bit more
+convenient than calculating the index ourselves.
Because the `enumerate` method returns a tuple, we can use patterns to
destructure that tuple. We’ll be discussing patterns more in Chapter 6. In the
@@ -1096,9 +989,8 @@ because it’s a separate value from the `String`, there’s no guarantee that i
will still be valid in the future. Consider the program in Listing 4-8 that
uses the `first_word` function from Listing 4-7.
-Filename: src/main.rs
-
```
+// src/main.rs
fn main() {
let mut s = String::from("hello world");
@@ -1130,8 +1022,8 @@ fn second_word(s: &String) -> (usize, usize) {
Now we’re tracking a starting *and* an ending index, and we have even more
values that were calculated from data in a particular state but aren’t tied to
-that state at all. We have three unrelated variables floating around that
-need to be kept in sync.
+that state at all. We have three unrelated variables floating around that need
+to be kept in sync.
Luckily, Rust has a solution to this problem: string slices.
@@ -1140,10 +1032,10 @@ Luckily, Rust has a solution to this problem: string slices.
A *string slice* is a reference to part of a `String`, and it looks like this:
```
- let s = String::from("hello world");
+let s = String::from("hello world");
- let hello = &s[0..5];
- let world = &s[6..11];
+let hello = &s[0..5];
+let world = &s[6..11];
```
Rather than a reference to the entire `String`, `hello` is a reference to a
@@ -1152,17 +1044,15 @@ using a range within brackets by specifying `[starting_index..ending_index]`,
where `starting_index` is the first position in the slice and `ending_index` is
one more than the last position in the slice. Internally, the slice data
structure stores the starting position and the length of the slice, which
-corresponds to `ending_index` minus `starting_index`. So in the case of `let
+corresponds to `ending_index` minus `starting_index`. So, in the case of `let
world = &s[6..11];`, `world` would be a slice that contains a pointer to the
-byte at index 6 of `s` with a length value of 5.
+byte at index 6 of `s` with a length value of `5`.
Figure 4-6 shows this in a diagram.
-<img alt="world containing a pointer to the byte at index 6 of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />
-
Figure 4-6: String slice referring to part of a `String`
-With Rust’s `..` range syntax, if you want to start at index zero, you can drop
+With Rust’s `..` range syntax, if you want to start at index 0, you can drop
the value before the two periods. In other words, these are equal:
```
@@ -1197,11 +1087,11 @@ let slice = &s[..];
```
> Note: String slice range indices must occur at valid UTF-8 character
-> boundaries. If you attempt to create a string slice in the middle of a
-> multibyte character, your program will exit with an error. For the purposes
-> of introducing string slices, we are assuming ASCII only in this section; a
-> more thorough discussion of UTF-8 handling is in the “Storing UTF-8 Encoded
-> Text with Strings” section of Chapter 8.
+boundaries. If you attempt to create a string slice in the middle of a
+multibyte character, your program will exit with an error. For the purposes of
+introducing string slices, we are assuming ASCII only in this section; a more
+thorough discussion of UTF-8 handling is in “Storing UTF-8 Encoded Text with
+Strings” on page XX.
With all this information in mind, let’s rewrite `first_word` to return a
slice. The type that signifies “string slice” is written as `&str`:
@@ -1222,10 +1112,10 @@ fn first_word(s: &String) -> &str {
}
```
-We get the index for the end of the word in the same way as we did in Listing
-4-7, by looking for the first occurrence of a space. When we find a space, we
-return a string slice using the start of the string and the index of the space
-as the starting and ending indices.
+We get the index for the end of the word the same way we did in Listing 4-7, by
+looking for the first occurrence of a space. When we find a space, we return a
+string slice using the start of the string and the index of the space as the
+starting and ending indices.
Now when we call `first_word`, we get back a single value that is tied to the
underlying data. The value is made up of a reference to the starting point of
@@ -1237,7 +1127,7 @@ Returning a slice would also work for a `second_word` function:
fn second_word(s: &String) -> &str {
```
-We now have a straightforward API that’s much harder to mess up, because the
+We now have a straightforward API that’s much harder to mess up because the
compiler will ensure the references into the `String` remain valid. Remember
the bug in the program in Listing 4-8, when we got the index to the end of the
first word but then cleared the string so our index was invalid? That code was
@@ -1257,7 +1147,7 @@ fn main() {
s.clear(); // error!
- println!("the first word is: {}", word);
+ println!("the first word is: {word}");
}
```
@@ -1274,8 +1164,8 @@ immutable
18 | s.clear(); // error!
| ^^^^^^^^^ mutable borrow occurs here
19 |
-20 | println!("the first word is: {}", word);
- | ---- immutable borrow later used here
+20 | println!("the first word is: {word}");
+ | ---- immutable borrow later used here
```
Recall from the borrowing rules that if we have an immutable reference to
@@ -1287,7 +1177,7 @@ reference in `clear` and the immutable reference in `word` from existing at the
same time, and compilation fails. Not only has Rust made our API easier to use,
but it has also eliminated an entire class of errors at compile time!
-#### String Literals Are Slices
+#### String Literals as Slices
Recall that we talked about string literals being stored inside the binary. Now
that we know about slices, we can properly understand string literals:
@@ -1323,9 +1213,10 @@ the type of the `s` parameter
If we have a string slice, we can pass that directly. If we have a `String`, we
can pass a slice of the `String` or a reference to the `String`. This
flexibility takes advantage of *deref coercions*, a feature we will cover in
-the “Implicit Deref Coercions with Functions and Methods” section of Chapter
-15. Defining a function to take a string slice instead of a reference to a
-`String` makes our API more general and useful without losing any functionality:
+“Implicit Deref Coercions with Functions and Methods” on page XX.
+
+Defining a function to take a string slice instead of a reference to a `String`
+makes our API more general and useful without losing any functionality:
Filename: src/main.rs
@@ -1333,16 +1224,18 @@ Filename: src/main.rs
fn main() {
let my_string = String::from("hello world");
- // `first_word` works on slices of `String`s, whether partial or whole
+ // `first_word` works on slices of `String`s, whether partial
+ // or whole
let word = first_word(&my_string[0..6]);
let word = first_word(&my_string[..]);
- // `first_word` also works on references to `String`s, which are equivalent
- // to whole slices of `String`s
+ // `first_word` also works on references to `String`s, which
+ // are equivalent to whole slices of `String`s
let word = first_word(&my_string);
let my_string_literal = "hello world";
- // `first_word` works on slices of string literals, whether partial or whole
+ // `first_word` works on slices of string literals,
+ // whether partial or whole
let word = first_word(&my_string_literal[0..6]);
let word = first_word(&my_string_literal[..]);
@@ -1355,14 +1248,14 @@ fn main() {
### Other Slices
String slices, as you might imagine, are specific to strings. But there’s a
-more general slice type, too. Consider this array:
+more general slice type too. Consider this array:
```
let a = [1, 2, 3, 4, 5];
```
-Just as we might want to refer to a part of a string, we might want to refer
-to part of an array. We’d do so like this:
+Just as we might want to refer to part of a string, we might want to refer to
+part of an array. We’d do so like this:
```
let a = [1, 2, 3, 4, 5];
@@ -1388,3 +1281,4 @@ means you don’t have to write and debug extra code to get this control.
Ownership affects how lots of other parts of Rust work, so we’ll talk about
these concepts further throughout the rest of the book. Let’s move on to
Chapter 5 and look at grouping pieces of data together in a `struct`.
+
diff --git a/src/doc/book/nostarch/chapter05.md b/src/doc/book/nostarch/chapter05.md
index 356ba82af..9881a3b74 100644
--- a/src/doc/book/nostarch/chapter05.md
+++ b/src/doc/book/nostarch/chapter05.md
@@ -19,16 +19,16 @@ We’ll demonstrate how to define and instantiate structs. We’ll discuss how t
define associated functions, especially the kind of associated functions called
*methods*, to specify behavior associated with a struct type. Structs and enums
(discussed in Chapter 6) are the building blocks for creating new types in your
-program’s domain to take full advantage of Rust’s compile time type checking.
+program’s domain to take full advantage of Rust’s compile-time type checking.
## Defining and Instantiating Structs
-Structs are similar to tuples, discussed in “The Tuple Type” section, in that
-both hold multiple related values. Like tuples, the pieces of a struct can be
-different types. Unlike with tuples, in a struct you’ll name each piece of data
-so it’s clear what the values mean. Adding these names means that structs are
-more flexible than tuples: you don’t have to rely on the order of the data to
-specify or access the values of an instance.
+Structs are similar to tuples, discussed in “The Tuple Type” on page XX, in
+that both hold multiple related values. Like tuples, the pieces of a struct can
+be different types. Unlike with tuples, in a struct you’ll name each piece of
+data so it’s clear what the values mean. Adding these names means that structs
+are more flexible than tuples: you don’t have to rely on the order of the data
+to specify or access the values of an instance.
To define a struct, we enter the keyword `struct` and name the entire struct. A
struct’s name should describe the significance of the pieces of data being
@@ -36,6 +36,8 @@ grouped together. Then, inside curly brackets, we define the names and types of
the pieces of data, which we call *fields*. For example, Listing 5-1 shows a
struct that stores information about a user account.
+Filename: src/main.rs
+
```
struct User {
active: bool,
@@ -49,20 +51,22 @@ Listing 5-1: A `User` struct definition
To use a struct after we’ve defined it, we create an *instance* of that struct
by specifying concrete values for each of the fields. We create an instance by
-stating the name of the struct and then add curly brackets containing `key:
-value` pairs, where the keys are the names of the fields and the values are the
+stating the name of the struct and then add curly brackets containing key:
+value pairs, where the keys are the names of the fields and the values are the
data we want to store in those fields. We don’t have to specify the fields in
the same order in which we declared them in the struct. In other words, the
struct definition is like a general template for the type, and instances fill
in that template with particular data to create values of the type. For
example, we can declare a particular user as shown in Listing 5-2.
+Filename: src/main.rs
+
```
fn main() {
let user1 = User {
- email: String::from("someone@example.com"),
- username: String::from("someusername123"),
active: true,
+ username: String::from("someusername123"),
+ email: String::from("someone@example.com"),
sign_in_count: 1,
};
}
@@ -76,19 +80,14 @@ mutable, we can change a value by using the dot notation and assigning into a
particular field. Listing 5-3 shows how to change the value in the `email`
field of a mutable `User` instance.
-<!--- Do we want to mention that `user1.email` will move the field? We can't
-just use `user1.email` multiple times re: "wherever we wanted
-to use this value"
-/JT --->
-<!-- I don't really want to mention that, but I did reword to avoid the
-implication that we can use the value wherever we wanted to. /Carol -->
+Filename: src/main.rs
```
fn main() {
let mut user1 = User {
- email: String::from("someone@example.com"),
- username: String::from("someusername123"),
active: true,
+ username: String::from("someusername123"),
+ email: String::from("someone@example.com"),
sign_in_count: 1,
};
@@ -110,9 +109,9 @@ the `sign_in_count` gets a value of `1`.
```
fn build_user(email: String, username: String) -> User {
User {
- email: email,
- username: username,
active: true,
+ username: username,
+ email: email,
sign_in_count: 1,
}
}
@@ -130,22 +129,22 @@ would get even more annoying. Luckily, there’s a convenient shorthand!
Because the parameter names and the struct field names are exactly the same in
Listing 5-4, we can use the *field init shorthand* syntax to rewrite
-`build_user` so that it behaves exactly the same but doesn’t have the
-repetition of `email` and `username`, as shown in Listing 5-5.
+`build_user` so it behaves exactly the same but doesn’t have the repetition of
+`username` and `email`, as shown in Listing 5-5.
```
fn build_user(email: String, username: String) -> User {
User {
- email,
- username,
active: true,
+ username,
+ email,
sign_in_count: 1,
}
}
```
Listing 5-5: A `build_user` function that uses field init shorthand because the
-`email` and `username` parameters have the same name as struct fields
+`username` and `email` parameters have the same name as struct fields
Here, we’re creating a new instance of the `User` struct, which has a field
named `email`. We want to set the `email` field’s value to the value in the
@@ -153,7 +152,7 @@ named `email`. We want to set the `email` field’s value to the value in the
the `email` parameter have the same name, we only need to write `email` rather
than `email: email`.
-### Creating Instances From Other Instances With Struct Update Syntax
+### Creating Instances from Other Instances with Struct Update Syntax
It’s often useful to create a new instance of a struct that includes most of
the values from another instance, but changes some. You can do this using
@@ -163,9 +162,11 @@ First, in Listing 5-6 we show how to create a new `User` instance in `user2`
regularly, without the update syntax. We set a new value for `email` but
otherwise use the same values from `user1` that we created in Listing 5-2.
+Filename: src/main.rs
+
```
fn main() {
- // --snip--
+ --snip--
let user2 = User {
active: user1.active,
@@ -182,9 +183,12 @@ Using struct update syntax, we can achieve the same effect with less code, as
shown in Listing 5-7. The syntax `..` specifies that the remaining fields not
explicitly set should have the same value as the fields in the given instance.
+Filename: src/main.rs
+
```
fn main() {
- // --snip--
+ --snip--
+
let user2 = User {
email: String::from("another@example.com"),
@@ -194,7 +198,7 @@ fn main() {
```
Listing 5-7: Using struct update syntax to set a new `email` value for a `User`
-instance but use the rest of the values from `user1`
+instance but to use the rest of the values from `user1`
The code in Listing 5-7 also creates an instance in `user2` that has a
different value for `email` but has the same values for the `username`,
@@ -204,33 +208,30 @@ corresponding fields in `user1`, but we can choose to specify values for as
many fields as we want in any order, regardless of the order of the fields in
the struct’s definition.
-Note that the struct update syntax uses `=` like an assignment; this is
-because it moves the data, just as we saw in the “Ways Variables and Data
-Interact: Move” section. In this example, we can no longer use `user1` after
-creating `user2` because the `String` in the `username` field of `user1` was
-moved into `user2`. If we had given `user2` new `String` values for both
-`email` and `username`, and thus only used the `active` and `sign_in_count`
-values from `user1`, then `user1` would still be valid after creating `user2`.
-The types of `active` and `sign_in_count` are types that implement the `Copy`
-trait, so the behavior we discussed in the “Stack-Only Data: Copy” section
-would apply.
-
-<!--- Misspelled "assignment" above.
-/JT --->
-<!-- Fixed! /Carol -->
-
-### Using Tuple Structs without Named Fields to Create Different Types
-
-Rust also supports structs that look similar to tuples, called *tuple
-structs*. Tuple structs have the added meaning the struct name provides but
-don’t have names associated with their fields; rather, they just have the types
-of the fields. Tuple structs are useful when you want to give the whole tuple a
-name and make the tuple a different type from other tuples, and when naming each
+Note that the struct update syntax uses `=` like an assignment; this is because
+it moves the data, just as we saw in “Variables and Data Interacting with Move”
+on page XX. In this example, we can no longer use `user1` after creating
+`user2` because the `String` in the `username` field of `user1` was moved into
+`user2`. If we had given `user2` new `String` values for both `email` and
+`username`, and thus only used the `active` and `sign_in_count` values from
+`user1`, then `user1` would still be valid after creating `user2`. Both
+`active` and `sign_in_count` are types that implement the `Copy` trait, so the
+behavior we discussed in “Stack-Only Data: Copy” on page XX would apply.
+
+### Using Tuple Structs Without Named Fields to Create Different Types
+
+Rust also supports structs that look similar to tuples, called *tuple structs*.
+Tuple structs have the added meaning the struct name provides but don’t have
+names associated with their fields; rather, they just have the types of the
+fields. Tuple structs are useful when you want to give the whole tuple a name
+and make the tuple a different type from other tuples, and when naming each
field as in a regular struct would be verbose or redundant.
To define a tuple struct, start with the `struct` keyword and the struct name
-followed by the types in the tuple. For example, here we define and use
-two tuple structs named `Color` and `Point`:
+followed by the types in the tuple. For example, here we define and use two
+tuple structs named `Color` and `Point`:
+
+Filename: src/main.rs
```
struct Color(i32, i32, i32);
@@ -242,7 +243,7 @@ fn main() {
}
```
-Note that the `black` and `origin` values are different types, because they’re
+Note that the `black` and `origin` values are different types because they’re
instances of different tuple structs. Each struct you define is its own type,
even though the fields within the struct might have the same types. For
example, a function that takes a parameter of type `Color` cannot take a
@@ -251,30 +252,17 @@ values. Otherwise, tuple struct instances are similar to tuples in that you can
destructure them into their individual pieces, and you can use a `.` followed
by the index to access an individual value.
-<!--- The last line above feels a bit misleading. There are related
-restrictions on tuple structs that don't apply to tuples.
-
-One example is you can't create a tuple struct with a tuple.
-```
-struct Color(i32, i32, i32);
-
-fn main() {
- let x: Color = (1, 2, 3);
-}
-```
-
-You can't pass a tuple struct to something that expects a tuple, either.
-/JT --->
-<!-- I've reworded to avoid that implication /Carol -->
-
### Unit-Like Structs Without Any Fields
You can also define structs that don’t have any fields! These are called
*unit-like structs* because they behave similarly to `()`, the unit type that
-we mentioned in “The Tuple Type” section. Unit-like structs can be useful when
-you need to implement a trait on some type but don’t have any data that you
-want to store in the type itself. We’ll discuss traits in Chapter 10. Here’s an
-example of declaring and instantiating a unit struct named `AlwaysEqual`:
+we mentioned in “The Tuple Type” on page XX. Unit-like structs can be useful
+when you need to implement a trait on some type but don’t have any data that
+you want to store in the type itself. We’ll discuss traits in Chapter 10.
+Here’s an example of declaring and instantiating a unit struct named
+`AlwaysEqual`:
+
+Filename: src/main.rs
```
struct AlwaysEqual;
@@ -284,8 +272,8 @@ fn main() {
}
```
-To define `AlwaysEqual`, we use the `struct` keyword, the name we want, then a
-semicolon. No need for curly brackets or parentheses! Then we can get an
+To define `AlwaysEqual`, we use the `struct` keyword, the name we want, and
+then a semicolon. No need for curly brackets or parentheses! Then we can get an
instance of `AlwaysEqual` in the `subject` variable in a similar way: using the
name we defined, without any curly brackets or parentheses. Imagine that later
we’ll implement behavior for this type such that every instance of
@@ -297,31 +285,30 @@ implement them on any type, including unit-like structs.
> ### Ownership of Struct Data
>
> In the `User` struct definition in Listing 5-1, we used the owned `String`
-> type rather than the `&str` string slice type. This is a deliberate choice
-> because we want each instance of this struct to own all of its data and for
-> that data to be valid for as long as the entire struct is valid.
+type rather than the `&str` string slice type. This is a deliberate choice
+because we want each instance of this struct to own all of its data and for
+that data to be valid for as long as the entire struct is valid.
>
> It’s also possible for structs to store references to data owned by something
-> else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll
-> discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct
-> is valid for as long as the struct is. Let’s say you try to store a reference
-> in a struct without specifying lifetimes, like the following; this won’t work:
->
-> Filename: src/main.rs
+else, but to do so requires the use of *lifetimes*, a Rust feature that we’ll
+discuss in Chapter 10. Lifetimes ensure that the data referenced by a struct is
+valid for as long as the struct is. Let’s say you try to store a reference in a
+struct without specifying lifetimes, like the following in *src/main.rs*; this
+won’t work:
>
> ```
> struct User {
+> active: bool,
> username: &str,
> email: &str,
> sign_in_count: u64,
-> active: bool,
> }
>
> fn main() {
> let user1 = User {
-> email: "someone@example.com",
-> username: "someusername123",
> active: true,
+> username: "someusername123",
+> email: "someone@example.com",
> sign_in_count: 1,
> };
> }
@@ -330,7 +317,7 @@ implement them on any type, including unit-like structs.
> The compiler will complain that it needs lifetime specifiers:
>
> ```
-> $ cargo run
+> $ `cargo run`
> Compiling structs v0.1.0 (file:///projects/structs)
> error[E0106]: missing lifetime specifier
> --> src/main.rs:3:15
@@ -361,8 +348,8 @@ implement them on any type, including unit-like structs.
> ```
>
> In Chapter 10, we’ll discuss how to fix these errors so you can store
-> references in structs, but for now, we’ll fix errors like these using owned
-> types like `String` instead of references like `&str`.
+references in structs, but for now, we’ll fix errors like these using owned
+types like `String` instead of references like `&str`.
## An Example Program Using Structs
@@ -399,10 +386,6 @@ and height variables
Now, run this program using `cargo run`:
```
-$ cargo run
- Compiling rectangles v0.1.0 (file:///projects/rectangles)
- Finished dev [unoptimized + debuginfo] target(s) in 0.42s
- Running `target/debug/rectangles`
The area of the rectangle is 1500 square pixels.
```
@@ -417,10 +400,10 @@ fn area(width: u32, height: u32) -> u32 {
```
The `area` function is supposed to calculate the area of one rectangle, but the
-function we wrote has two parameters, and it's not clear anywhere in our
+function we wrote has two parameters, and it’s not clear anywhere in our
program that the parameters are related. It would be more readable and more
manageable to group width and height together. We’ve already discussed one way
-we might do that in “The Tuple Type” section of Chapter 3: by using tuples.
+we might do that in “The Tuple Type” on page XX: by using tuples.
### Refactoring with Tuples
@@ -434,21 +417,21 @@ fn main() {
println!(
"The area of the rectangle is {} square pixels.",
- area(rect1)
+ 1 area(rect1)
);
}
fn area(dimensions: (u32, u32)) -> u32 {
- dimensions.0 * dimensions.1
+ 2 dimensions.0 * dimensions.1
}
```
Listing 5-9: Specifying the width and height of the rectangle with a tuple
In one way, this program is better. Tuples let us add a bit of structure, and
-we’re now passing just one argument. But in another way, this version is less
-clear: tuples don’t name their elements, so we have to index into the parts of
-the tuple, making our calculation less obvious.
+we’re now passing just one argument [1]. But in another way, this version is
+less clear: tuples don’t name their elements, so we have to index into the
+parts of the tuple [2], making our calculation less obvious.
Mixing up the width and height wouldn’t matter for the area calculation, but if
we want to draw the rectangle on the screen, it would matter! We would have to
@@ -466,13 +449,13 @@ parts, as shown in Listing 5-10.
Filename: src/main.rs
```
-struct Rectangle {
- width: u32,
+1 struct Rectangle {
+ 2 width: u32,
height: u32,
}
fn main() {
- let rect1 = Rectangle {
+ 3 let rect1 = Rectangle {
width: 30,
height: 50,
};
@@ -483,27 +466,27 @@ fn main() {
);
}
-fn area(rectangle: &Rectangle) -> u32 {
- rectangle.width * rectangle.height
+4 fn area(rectangle: &Rectangle) -> u32 {
+ 5 rectangle.width * rectangle.height
}
```
Listing 5-10: Defining a `Rectangle` struct
-Here we’ve defined a struct and named it `Rectangle`. Inside the curly
+Here, we’ve defined a struct and named it `Rectangle` [1]. Inside the curly
brackets, we defined the fields as `width` and `height`, both of which have
-type `u32`. Then in `main`, we created a particular instance of `Rectangle`
-that has a width of 30 and a height of 50.
+type `u32` [2]. Then, in `main`, we created a particular instance of
+`Rectangle` that has a width of `30` and a height of `50` [3].
Our `area` function is now defined with one parameter, which we’ve named
-`rectangle`, whose type is an immutable borrow of a struct `Rectangle`
-instance. As mentioned in Chapter 4, we want to borrow the struct rather than
-take ownership of it. This way, `main` retains its ownership and can continue
-using `rect1`, which is the reason we use the `&` in the function signature and
-where we call the function.
+`rectangle`, whose type is an immutable borrow of a struct `Rectangle` instance
+[4]. As mentioned in Chapter 4, we want to borrow the struct rather than take
+ownership of it. This way, `main` retains its ownership and can continue using
+`rect1`, which is the reason we use the `&` in the function signature and where
+we call the function.
The `area` function accesses the `width` and `height` fields of the `Rectangle`
-instance (note that accessing fields of a borrowed struct instance does not
+instance [5] (note that accessing fields of a borrowed struct instance does not
move the field values, which is why you often see borrows of structs). Our
function signature for `area` now says exactly what we mean: calculate the area
of `Rectangle`, using its `width` and `height` fields. This conveys that the
@@ -511,14 +494,6 @@ width and height are related to each other, and it gives descriptive names to
the values rather than using the tuple index values of `0` and `1`. This is a
win for clarity.
-<!--- Tying to my comment above about `user1.email` moving that field: we should
-take a minute here and explain that accessing fields on a borrowed struct does
-not move them, and why you often see borrows of structs.
-/JT --->
-<!-- I've added a note in the paragraph above; I haven't really seen people
-struggle with that concept though so I don't want to spend too much time on it
-/Carol -->
-
### Adding Useful Functionality with Derived Traits
It’d be useful to be able to print an instance of `Rectangle` while we’re
@@ -555,7 +530,7 @@ error[E0277]: `Rectangle` doesn't implement `std::fmt::Display`
The `println!` macro can do many kinds of formatting, and by default, the curly
brackets tell `println!` to use formatting known as `Display`: output intended
for direct end user consumption. The primitive types we’ve seen so far
-implement `Display` by default, because there’s only one way you’d want to show
+implement `Display` by default because there’s only one way you’d want to show
a `1` or any other primitive type to a user. But with structs, the way
`println!` should format the output is less clear because there are more
display possibilities: Do you want commas or not? Do you want to print the
@@ -567,7 +542,8 @@ If we continue reading the errors, we’ll find this helpful note:
```
= help: the trait `std::fmt::Display` is not implemented for `Rectangle`
-= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+= note: in format strings you may be able to use `{:?}` (or {:#?} for
+pretty-print) instead
```
Let’s try it! The `println!` macro call will now look like `println!("rect1 is
@@ -620,24 +596,16 @@ Now when we run the program, we won’t get any errors, and we’ll see the
following output:
```
-$ cargo run
- Compiling rectangles v0.1.0 (file:///projects/rectangles)
- Finished dev [unoptimized + debuginfo] target(s) in 0.48s
- Running `target/debug/rectangles`
rect1 is Rectangle { width: 30, height: 50 }
```
Nice! It’s not the prettiest output, but it shows the values of all the fields
for this instance, which would definitely help during debugging. When we have
larger structs, it’s useful to have output that’s a bit easier to read; in
-those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string.
-In this example, using the `{:#?}` style will output:
+those cases, we can use `{:#?}` instead of `{:?}` in the `println!` string. In
+this example, using the `{:#?}` style will output the following:
```
-$ cargo run
- Compiling rectangles v0.1.0 (file:///projects/rectangles)
- Finished dev [unoptimized + debuginfo] target(s) in 0.48s
- Running `target/debug/rectangles`
rect1 is Rectangle {
width: 30,
height: 50,
@@ -645,20 +613,22 @@ rect1 is Rectangle {
```
Another way to print out a value using the `Debug` format is to use the `dbg!`
-macro, which takes ownership of an expression (as opposed to `println!` that
+macro, which takes ownership of an expression (as opposed to `println!`, which
takes a reference), prints the file and line number of where that `dbg!` macro
-call occurs in your code along with the resulting value of that expression, and
+call occurs in your code along with the resultant value of that expression, and
returns ownership of the value.
> Note: Calling the `dbg!` macro prints to the standard error console stream
-> (`stderr`), as opposed to `println!` which prints to the standard output
-> console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the
-> “Writing Error Messages to Standard Error Instead of Standard Output” section
-> in Chapter 12.
+(`stderr`), as opposed to `println!`, which prints to the standard output
+console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in
+“Writing Error Messages to Standard Error Instead of Standard Output” on page
+XX.
Here’s an example where we’re interested in the value that gets assigned to the
`width` field, as well as the value of the whole struct in `rect1`:
+Filename: src/main.rs
+
```
#[derive(Debug)]
struct Rectangle {
@@ -669,31 +639,21 @@ struct Rectangle {
fn main() {
let scale = 2;
let rect1 = Rectangle {
- width: dbg!(30 * scale),
+ 1 width: dbg!(30 * scale),
height: 50,
};
- dbg!(&rect1);
+ 2 dbg!(&rect1);
}
```
-We can put `dbg!` around the expression `30 * scale` and, because `dbg!`
+We can put `dbg!` around the expression `30 * scale` [1] and, because `dbg!`
returns ownership of the expression’s value, the `width` field will get the
same value as if we didn’t have the `dbg!` call there. We don’t want `dbg!` to
-take ownership of `rect1`, so we use a reference to `rect1` in the next call.
-Here’s what the output of this example looks like:
-
-<!--- is it worth calling out that println! doesn't have the dbg! shortcoming
-of taking ownership?
-/JT --->
-<!-- I added a note in the paragraph above that starts with "Another way to
-print out a value" /Carol -->
+take ownership of `rect1`, so we use a reference to `rect1` in the next call
+[2]. Here’s what the output of this example looks like:
```
-$ cargo run
- Compiling rectangles v0.1.0 (file:///projects/rectangles)
- Finished dev [unoptimized + debuginfo] target(s) in 0.61s
- Running `target/debug/rectangles`
[src/main.rs:10] 30 * scale = 60
[src/main.rs:14] &rect1 = Rectangle {
width: 60,
@@ -701,13 +661,13 @@ $ cargo run
}
```
-We can see the first bit of output came from *src/main.rs* line 10, where we’re
-debugging the expression `30 * scale`, and its resulting value is 60 (the
-`Debug` formatting implemented for integers is to print only their value). The
-`dbg!` call on line 14 of *src/main.rs* outputs the value of `&rect1`, which is
-the `Rectangle` struct. This output uses the pretty `Debug` formatting of the
-`Rectangle` type. The `dbg!` macro can be really helpful when you’re trying to
-figure out what your code is doing!
+We can see the first bit of output came from [1] where we’re debugging the
+expression `30 * scale`, and its resultant value is `60` (the `Debug`
+formatting implemented for integers is to print only their value). The `dbg!`
+call at [2] outputs the value of `&rect1`, which is the `Rectangle` struct.
+This output uses the pretty `Debug` formatting of the `Rectangle` type. The
+`dbg!` macro can be really helpful when you’re trying to figure out what your
+code is doing!
In addition to the `Debug` trait, Rust has provided a number of traits for us
to use with the `derive` attribute that can add useful behavior to our custom
@@ -718,10 +678,10 @@ your own traits in Chapter 10. There are also many attributes other than
Reference at *https://doc.rust-lang.org/reference/attributes.html*.
Our `area` function is very specific: it only computes the area of rectangles.
-It would be helpful to tie this behavior more closely to our `Rectangle`
-struct, because it won’t work with any other type. Let’s look at how we can
-continue to refactor this code by turning the `area` function into an `area`
-*method* defined on our `Rectangle` type.
+It would be helpful to tie this behavior more closely to our `Rectangle` struct
+because it won’t work with any other type. Let’s look at how we can continue to
+refactor this code by turning the `area` function into an `area` *method*
+defined on our `Rectangle` type.
## Method Syntax
@@ -729,18 +689,9 @@ continue to refactor this code by turning the `area` function into an `area`
name, they can have parameters and a return value, and they contain some code
that’s run when the method is called from somewhere else. Unlike functions,
methods are defined within the context of a struct (or an enum or a trait
-object, which we cover in Chapters 6 and 17, respectively), and their first
-parameter is always `self`, which represents the instance of the struct the
-method is being called on.
-
-<!--- minor nit: some folks call the non-self functions in an `impl`
-"static methods" as a nod to OO languages that do the same. For folks
-from that background, we may want to call out that instance methods always
-have `self` and methods on the type do not.
-/JT --->
-<!-- This paragraph already says "their first parameter is always `self`", and
-we get into associated functions in just a bit. I don't want to distract with
-that info here; not changing anything at this spot. /Carol -->
+object, which we cover in Chapter 6 and Chapter 17, respectively), and their
+first parameter is always `self`, which represents the instance of the struct
+the method is being called on.
### Defining Methods
@@ -757,8 +708,8 @@ struct Rectangle {
height: u32,
}
-impl Rectangle {
- fn area(&self) -> u32 {
+1 impl Rectangle {
+ 2 fn area(&self) -> u32 {
self.width * self.height
}
}
@@ -771,7 +722,7 @@ fn main() {
println!(
"The area of the rectangle is {} square pixels.",
- rect1.area()
+ 3 rect1.area()
);
}
```
@@ -779,14 +730,14 @@ fn main() {
Listing 5-13: Defining an `area` method on the `Rectangle` struct
To define the function within the context of `Rectangle`, we start an `impl`
-(implementation) block for `Rectangle`. Everything within this `impl` block
+(implementation) block for `Rectangle` [1]. Everything within this `impl` block
will be associated with the `Rectangle` type. Then we move the `area` function
-within the `impl` curly brackets and change the first (and in this case, only)
-parameter to be `self` in the signature and everywhere within the body. In
-`main`, where we called the `area` function and passed `rect1` as an argument,
-we can instead use *method syntax* to call the `area` method on our `Rectangle`
-instance. The method syntax goes after an instance: we add a dot followed by
-the method name, parentheses, and any arguments.
+within the `impl` curly brackets [2] and change the first (and in this case,
+only) parameter to be `self` in the signature and everywhere within the body.
+In `main`, where we called the `area` function and passed `rect1` as an
+argument, we can instead use *method syntax* to call the `area` method on our
+`Rectangle` instance [3]. The method syntax goes after an instance: we add a
+dot followed by the method name, parentheses, and any arguments.
In the signature for `area`, we use `&self` instead of `rectangle: &Rectangle`.
The `&self` is actually short for `self: &Self`. Within an `impl` block, the
@@ -794,28 +745,30 @@ type `Self` is an alias for the type that the `impl` block is for. Methods must
have a parameter named `self` of type `Self` for their first parameter, so Rust
lets you abbreviate this with only the name `self` in the first parameter spot.
Note that we still need to use the `&` in front of the `self` shorthand to
-indicate this method borrows the `Self` instance, just as we did in `rectangle:
-&Rectangle`. Methods can take ownership of `self`, borrow `self` immutably as
-we’ve done here, or borrow `self` mutably, just as they can any other parameter.
-
-We’ve chosen `&self` here for the same reason we used `&Rectangle` in the
-function version: we don’t want to take ownership, and we just want to read the
-data in the struct, not write to it. If we wanted to change the instance that
-we’ve called the method on as part of what the method does, we’d use `&mut
-self` as the first parameter. Having a method that takes ownership of the
-instance by using just `self` as the first parameter is rare; this technique is
-usually used when the method transforms `self` into something else and you want
-to prevent the caller from using the original instance after the transformation.
-
-The main reason for using methods instead of functions, in addition to providing
-method syntax and not having to repeat the type of `self` in every method’s
-signature, is for organization. We’ve put all the things we can do with an
-instance of a type in one `impl` block rather than making future users of our
-code search for capabilities of `Rectangle` in various places in the library we
-provide.
+indicate that this method borrows the `Self` instance, just as we did in
+`rectangle: &Rectangle`. Methods can take ownership of `self`, borrow `self`
+immutably, as we’ve done here, or borrow `self` mutably, just as they can any
+other parameter.
+
+We chose `&self` here for the same reason we used `&Rectangle` in the function
+version: we don’t want to take ownership, and we just want to read the data in
+the struct, not write to it. If we wanted to change the instance that we’ve
+called the method on as part of what the method does, we’d use `&mut self` as
+the first parameter. Having a method that takes ownership of the instance by
+using just `self` as the first parameter is rare; this technique is usually
+used when the method transforms `self` into something else and you want to
+prevent the caller from using the original instance after the transformation.
+
+The main reason for using methods instead of functions, in addition to
+providing method syntax and not having to repeat the type of `self` in every
+method’s signature, is for organization. We’ve put all the things we can do
+with an instance of a type in one `impl` block rather than making future users
+of our code search for capabilities of `Rectangle` in various places in the
+library we provide.
Note that we can choose to give a method the same name as one of the struct’s
-fields. For example, we can define a method on `Rectangle` also named `width`:
+fields. For example, we can define a method on `Rectangle` that is also named
+`width`:
Filename: src/main.rs
@@ -833,42 +786,45 @@ fn main() {
};
if rect1.width() {
- println!("The rectangle has a nonzero width; it is {}", rect1.width);
+ println!(
+ "The rectangle has a nonzero width; it is {}",
+ rect1.width
+ );
}
}
```
Here, we’re choosing to make the `width` method return `true` if the value in
-the instance’s `width` field is greater than 0, and `false` if the value is 0:
-we can use a field within a method of the same name for any purpose. In `main`,
-when we follow `rect1.width` with parentheses, Rust knows we mean the method
-`width`. When we don’t use parentheses, Rust knows we mean the field `width`.
+the instance’s `width` field is greater than `0` and `false` if the value is
+`0`: we can use a field within a method of the same name for any purpose. In
+`main`, when we follow `rect1.width` with parentheses, Rust knows we mean the
+method `width`. When we don’t use parentheses, Rust knows we mean the field
+`width`.
Often, but not always, when we give methods with the same name as a field we
want it to only return the value in the field and do nothing else. Methods like
this are called *getters*, and Rust does not implement them automatically for
struct fields as some other languages do. Getters are useful because you can
-make the field private but the method public and thus enable read-only access
-to that field as part of the type’s public API. We will be discussing what
-public and private are and how to designate a field or method as public or
-private in Chapter 7.
+make the field private but the method public, and thus enable read-only access
+to that field as part of the type’s public API. We will discuss what public and
+private are and how to designate a field or method as public or private in
+Chapter 7.
-> ### Where’s the `->` Operator?
+> ### Where’s the -> Operator?
>
> In C and C++, two different operators are used for calling methods: you use
-> `.` if you’re calling a method on the object directly and `->` if you’re
-> calling the method on a pointer to the object and need to dereference the
-> pointer first. In other words, if `object` is a pointer,
-> `object->something()` is similar to `(*object).something()`.
+`.` if you’re calling a method on the object directly and `->` if you’re
+calling the method on a pointer to the object and need to dereference the
+pointer first. In other words, if `object` is a pointer,
+`object->`something`()` is similar to `(*object).`something`()`.
>
> Rust doesn’t have an equivalent to the `->` operator; instead, Rust has a
-> feature called *automatic referencing and dereferencing*. Calling methods is
-> one of the few places in Rust that has this behavior.
->
-> Here’s how it works: when you call a method with `object.something()`, Rust
-> automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of
-> the method. In other words, the following are the same:
+feature called *automatic referencing and dereferencing*. Calling methods is
+one of the few places in Rust that has this behavior.
>
+> Here’s how it works: when you call a method with `object.`something`()`, Rust
+automatically adds in `&`, `&mut`, or `*` so `object` matches the signature of
+the method. In other words, the following are the same:
>
> ```
> p1.distance(&p2);
@@ -876,20 +832,20 @@ private in Chapter 7.
> ```
>
> The first one looks much cleaner. This automatic referencing behavior works
-> because methods have a clear receiver—the type of `self`. Given the receiver
-> and name of a method, Rust can figure out definitively whether the method is
-> reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact
-> that Rust makes borrowing implicit for method receivers is a big part of
-> making ownership ergonomic in practice.
+because methods have a clear receiver—the type of `self`. Given the receiver
+and name of a method, Rust can figure out definitively whether the method is
+reading (`&self`), mutating (`&mut self`), or consuming (`self`). The fact that
+Rust makes borrowing implicit for method receivers is a big part of making
+ownership ergonomic in practice.
### Methods with More Parameters
Let’s practice using methods by implementing a second method on the `Rectangle`
-struct. This time, we want an instance of `Rectangle` to take another instance
+struct. This time we want an instance of `Rectangle` to take another instance
of `Rectangle` and return `true` if the second `Rectangle` can fit completely
-within `self` (the first `Rectangle`); otherwise it should return `false`. That
-is, once we’ve defined the `can_hold` method, we want to be able to write the
-program shown in Listing 5-14.
+within `self` (the first `Rectangle`); otherwise, it should return `false`.
+That is, once we’ve defined the `can_hold` method, we want to be able to write
+the program shown in Listing 5-14.
Filename: src/main.rs
@@ -915,8 +871,8 @@ fn main() {
Listing 5-14: Using the as-yet-unwritten `can_hold` method
-And the expected output would look like the following, because both dimensions
-of `rect2` are smaller than the dimensions of `rect1` but `rect3` is wider than
+The expected output would look like the following because both dimensions of
+`rect2` are smaller than the dimensions of `rect1`, but `rect3` is wider than
`rect1`:
```
@@ -934,7 +890,7 @@ read `rect2` (rather than write, which would mean we’d need a mutable borrow),
and we want `main` to retain ownership of `rect2` so we can use it again after
calling the `can_hold` method. The return value of `can_hold` will be a
Boolean, and the implementation will check whether the width and height of
-`self` are both greater than the width and height of the other `Rectangle`,
+`self` are greater than the width and height of the other `Rectangle`,
respectively. Let’s add the new `can_hold` method to the `impl` block from
Listing 5-13, shown in Listing 5-15.
@@ -981,8 +937,8 @@ Filename: src/main.rs
```
impl Rectangle {
- fn square(size: u32) -> Self [1] {
- Self [2] {
+ fn square(size: u32) -> 1 Self {
+ 2 Self {
width: size,
height: size,
}
@@ -999,17 +955,11 @@ To call this associated function, we use the `::` syntax with the struct name;
the struct: the `::` syntax is used for both associated functions and
namespaces created by modules. We’ll discuss modules in Chapter 7.
-<!--- Should we mention the most common associated function is `new`? And that
-new isn't built into the language.
-/JT --->
-<!-- I've added a note as such above to the paragraph that starts with
-"Associated functions that aren’t methods" /Carol -->
-
-### Multiple `impl` Blocks
+### Multiple impl Blocks
Each struct is allowed to have multiple `impl` blocks. For example, Listing
-5-15 is equivalent to the code shown in Listing 5-16, which has each method
-in its own `impl` block.
+5-15 is equivalent to the code shown in Listing 5-16, which has each method in
+its own `impl` block.
```
impl Rectangle {
@@ -1043,31 +993,3 @@ structs have.
But structs aren’t the only way you can create custom types: let’s turn to
Rust’s enum feature to add another tool to your toolbox.
-<!--- We don't mention that you can only use `impl` in the same crate as the
-type it's created in, otherwise you could use `impl` and add methods on types
-that come from other people (which you can't do, unless you make a trait to
-attach them to)
-
-Another thing we may want to mention is that `Self` inside of an `impl` refers
-to the type being impl'd. So you might write the above:
-
-```
-impl Rectangle {
- fn square(size: u32) -> Self {
- Self {
- width: size,
- height: size,
- }
- }
-}
-```
-which is often a bit more ergonomic.
-
-/JT --->
-<!-- I've changed the `square` example to use `Self` and added some wingdings
-and notes explaining that. I don't really want to get into the restrictions on
-`impl` on types defined in another crate, because we haven't covered traits
-yet. Traits let you do `impl Trait for OtherCrateType` in some circumstances,
-so I don't want to say "you can't use an `impl` block on types from other
-crates" because I'd have to allude to traits or potentially give the reader the
-wrong impression. We get into these restrictions in chapter 10. -->
diff --git a/src/doc/book/nostarch/chapter06.md b/src/doc/book/nostarch/chapter06.md
index 47b51b5a1..ea4328bea 100644
--- a/src/doc/book/nostarch/chapter06.md
+++ b/src/doc/book/nostarch/chapter06.md
@@ -8,8 +8,8 @@ directory, so all fixes need to be made in `/src/`.
# Enums and Pattern Matching
-In this chapter we’ll look at *enumerations*, also referred to as *enums*.
-Enums allow you to define a type by enumerating its possible *variants*. First,
+In this chapter, we’ll look at *enumerations*, also referred to as *enums*.
+Enums allow you to define a type by enumerating its possible *variants*. First
we’ll define and use an enum to show how an enum can encode meaning along with
data. Next, we’ll explore a particularly useful enum, called `Option`, which
expresses that a value can be either something or nothing. Then we’ll look at
@@ -18,37 +18,8 @@ code for different values of an enum. Finally, we’ll cover how the `if let`
construct is another convenient and concise idiom available to handle enums in
your code.
-<!--- The above about algebraic data types feels pretty niche. Should it get
-the "expert aside" treatment that some of the early texts gets? /JT --->
-<!-- I decided to just remove the paragraph this comment was about. /Carol -->
-
## Defining an Enum
-<!--- I added this first line, it seems like this is what we're saying? Maybe
-summarize what enums are better suited for: when you know all possible outcomes
-and that the outcomes must be distinct from each other? I was hoping to
-generalize their usage early. Edit: reading on, I can see that might be tricky,
-so ignore this if so! /LC --->
-<!-- I made a slight edit to the first line here, what do you think? I don't
-think "enums are an alternative to structs" was quite right, because that
-sounded like in any situation, you could choose either enum or struct according
-to your preferences, but what I'd like the reader to come away with is that
-some situations are better expressed with enums; others with structs. /Carol -->
-<!-- I think this makes sense! I wonder if there's more we could add to give an
-idea of why we're contrasting them with structs, to give the reader a point of
-reference. What do you think JT? Would more explanation here be redundant? /LC
--->
-<!--- Here's my try for a framing, using our earlier Rectangle example:
-Where structs give you a way of grouping together related fields and data, like
-a `Rectangle` with its `width` and `height`, we don't yet have a way of saying
-a values is one of a possible set of values. For example, we may want to say
-that Rectangle is one of a set of possible shapes. To do this, Rust allows us
-to encode these possibilities as an enum. Let's look at...
-/JT --->
-<!-- I've generally taken JT's suggestion with a few edits. I'm a little
-concerned that we won't ever actually make a `Shape` enum with variants
-`Rectangle`, `Circle`, and `Triangle`? Is that a problem, Liz? /Carol -->
-
Where structs give you a way of grouping together related fields and data, like
a `Rectangle` with its `width` and `height`, enums give you a way of saying a
value is one of a possible set of values. For example, we may want to say that
@@ -64,7 +35,7 @@ variants, which is where enumeration gets its name.
Any IP address can be either a version four or a version six address, but not
both at the same time. That property of IP addresses makes the enum data
-structure appropriate, because an enum value can only be one of its variants.
+structure appropriate because an enum value can only be one of its variants.
Both version four and version six addresses are still fundamentally IP
addresses, so they should be treated as the same type when the code is handling
situations that apply to any kind of IP address.
@@ -114,22 +85,22 @@ Chapter 5, you might be tempted to tackle this problem with structs as shown in
Listing 6-1.
```
-enum IpAddrKind {
+1 enum IpAddrKind {
V4,
V6,
}
-struct IpAddr {
- kind: IpAddrKind,
- address: String,
+2 struct IpAddr {
+ 3 kind: IpAddrKind,
+ 4 address: String,
}
-let home = IpAddr {
+5 let home = IpAddr {
kind: IpAddrKind::V4,
address: String::from("127.0.0.1"),
};
-let loopback = IpAddr {
+6 let loopback = IpAddr {
kind: IpAddrKind::V6,
address: String::from("::1"),
};
@@ -138,14 +109,14 @@ let loopback = IpAddr {
Listing 6-1: Storing the data and `IpAddrKind` variant of an IP address using a
`struct`
-Here, we’ve defined a struct `IpAddr` that has two fields: a `kind` field that
-is of type `IpAddrKind` (the enum we defined previously) and an `address` field
-of type `String`. We have two instances of this struct. The first is `home`,
-and it has the value `IpAddrKind::V4` as its `kind` with associated address
-data of `127.0.0.1`. The second instance is `loopback`. It has the other
-variant of `IpAddrKind` as its `kind` value, `V6`, and has address `::1`
-associated with it. We’ve used a struct to bundle the `kind` and `address`
-values together, so now the variant is associated with the value.
+Here, we’ve defined a struct `IpAddr` [2] that has two fields: a `kind` field
+[3] that is of type `IpAddrKind` (the enum we defined previously [1]) and an
+`address` field [4] of type `String`. We have two instances of this struct. The
+first is `home` [5], and it has the value `IpAddrKind::V4` as its `kind` with
+associated address data of `127.0.0.1`. The second instance is `loopback` [6].
+It has the other variant of `IpAddrKind` as its `kind` value, `V6`, and has
+address `::1` associated with it. We’ve used a struct to bundle the `kind` and
+`address` values together, so now the variant is associated with the value.
However, representing the same concept using just an enum is more concise:
rather than an enum inside a struct, we can put data directly into each enum
@@ -164,7 +135,7 @@ let loopback = IpAddr::V6(String::from("::1"));
```
We attach data to each variant of the enum directly, so there is no need for an
-extra struct. Here it’s also easier to see another detail of how enums work:
+extra struct. Here, it’s also easier to see another detail of how enums work:
the name of each enum variant that we define also becomes a function that
constructs an instance of the enum. That is, `IpAddr::V4()` is a function call
that takes a `String` argument and returns an instance of the `IpAddr` type. We
@@ -172,7 +143,7 @@ automatically get this constructor function defined as a result of defining the
enum.
There’s another advantage to using an enum rather than a struct: each variant
-can have different types and amounts of associated data. Version four type IP
+can have different types and amounts of associated data. Version four IP
addresses will always have four numeric components that will have values
between 0 and 255. If we wanted to store `V4` addresses as four `u8` values but
still express `V6` addresses as one `String` value, we wouldn’t be able to with
@@ -199,11 +170,11 @@ different structs, which are defined differently for each variant:
```
struct Ipv4Addr {
- // --snip--
+ --snip--
}
struct Ipv6Addr {
- // --snip--
+ --snip--
}
enum IpAddr {
@@ -240,7 +211,7 @@ types of values
This enum has four variants with different types:
* `Quit` has no data associated with it at all.
-* `Move` has named fields like a struct does.
+* `Move` has named fields, like a struct does.
* `Write` includes a single `String`.
* `ChangeColor` includes three `i32` values.
@@ -260,16 +231,10 @@ struct WriteMessage(String); // tuple struct
struct ChangeColorMessage(i32, i32, i32); // tuple struct
```
-But if we used the different structs, which each have their own type, we
+But if we used the different structs, each of which has its own type, we
couldn’t as easily define a function to take any of these kinds of messages as
we could with the `Message` enum defined in Listing 6-2, which is a single type.
-<!--- We're also hinting at pattern matching complexity if we use the struct
-method. Should we call it out and mention the pattern matching chapter?
-/JT --->
-<!-- If readers don't have experience with pattern matching, I don't think this
-will resonate with them, so I'm not going to mention it here. /Carol -->
-
There is one more similarity between enums and structs: just as we’re able to
define methods on structs using `impl`, we’re also able to define methods on
enums. Here’s a method named `call` that we could define on our `Message` enum:
@@ -277,34 +242,34 @@ enums. Here’s a method named `call` that we could define on our `Message` enum
```
impl Message {
fn call(&self) {
- // method body would be defined here
+ 1 // method body would be defined here
}
}
-let m = Message::Write(String::from("hello"));
+2 let m = Message::Write(String::from("hello"));
m.call();
```
The body of the method would use `self` to get the value that we called the
-method on. In this example, we’ve created a variable `m` that has the value
+method on. In this example, we’ve created a variable `m` [2] that has the value
`Message::Write(String::from("hello"))`, and that is what `self` will be in the
-body of the `call` method when `m.call()` runs.
+body of the `call` method [1] when `m.call()` runs.
Let’s look at another enum in the standard library that is very common and
useful: `Option`.
-### The `Option` Enum and Its Advantages Over Null Values
+### The Option Enum and Its Advantages Over Null Values
This section explores a case study of `Option`, which is another enum defined
by the standard library. The `Option` type encodes the very common scenario in
which a value could be something or it could be nothing.
-For example, if you request the first of a list containing items, you would get
-a value. If you request the first item of an empty list, you would get nothing.
-Expressing this concept in terms of the type system means the compiler can
-check whether you’ve handled all the cases you should be handling; this
-functionality can prevent bugs that are extremely common in other programming
-languages.
+For example, if you request the first item in a list containing multiple items,
+you would get a value. If you request the first item in an empty list, you
+would get nothing. Expressing this concept in terms of the type system means
+the compiler can check whether you’ve handled all the cases you should be
+handling; this functionality can prevent bugs that are extremely common in
+other programming languages.
Programming language design is often thought of in terms of which features you
include, but the features you exclude are important too. Rust doesn’t have the
@@ -316,17 +281,16 @@ In his 2009 presentation “Null References: The Billion Dollar Mistake,” Tony
Hoare, the inventor of null, has this to say:
> I call it my billion-dollar mistake. At that time, I was designing the first
-> comprehensive type system for references in an object-oriented language. My
-> goal was to ensure that all use of references should be absolutely safe, with
-> checking performed automatically by the compiler. But I couldn’t resist the
-> temptation to put in a null reference, simply because it was so easy to
-> implement. This has led to innumerable errors, vulnerabilities, and system
-> crashes, which have probably caused a billion dollars of pain and damage in
-> the last forty years.
-
-The problem with null values is that if you try to use a null value as a
-not-null value, you’ll get an error of some kind. Because this null or not-null
-property is pervasive, it’s extremely easy to make this kind of error.
+comprehensive type system for references in an object-oriented language. My
+goal was to ensure that all use of references should be absolutely safe, with
+checking performed automatically by the compiler. But I couldn’t resist the
+temptation to put in a null reference, simply because it was so easy to
+implement. This has led to innumerable errors, vulnerabilities, and system
+crashes, which have probably caused a billion dollars of pain and damage in the
+last forty years.The problem with null values is that if you try to use a null
+value as a not-null value, you’ll get an error of some kind. Because this null
+or not-null property is pervasive, it’s extremely easy to make this kind of
+error.
However, the concept that null is trying to express is still a useful one: a
null is a value that is currently invalid or absent for some reason.
@@ -334,8 +298,7 @@ null is a value that is currently invalid or absent for some reason.
The problem isn’t really with the concept but with the particular
implementation. As such, Rust does not have nulls, but it does have an enum
that can encode the concept of a value being present or absent. This enum is
-`Option<T>`, and it is defined by the standard library
-as follows:
+`Option<T>`, and it is defined by the standard library as follows:
```
enum Option<T> {
@@ -352,11 +315,11 @@ prefix. The `Option<T>` enum is still just a regular enum, and `Some(T)` and
The `<T>` syntax is a feature of Rust we haven’t talked about yet. It’s a
generic type parameter, and we’ll cover generics in more detail in Chapter 10.
-For now, all you need to know is that `<T>` means the `Some` variant of the
-`Option` enum can hold one piece of data of any type, and that each concrete
-type that gets used in place of `T` makes the overall `Option<T>` type a
-different type. Here are some examples of using `Option` values to hold number
-types and string types:
+For now, all you need to know is that `<T>` means that the `Some` variant of
+the `Option` enum can hold one piece of data of any type, and that each
+concrete type that gets used in place of `T` makes the overall `Option<T>` type
+a different type. Here are some examples of using `Option` values to hold
+number types and string types:
```
let some_number = Some(5);
@@ -365,26 +328,6 @@ let some_char = Some('e');
let absent_number: Option<i32> = None;
```
-<!--- I would maybe do the above more explicitly as:
-
-"
-```
-let some_number = Some(5);
-
-let some_number2: Option<i32> = Some(5);
-```
-The types of `some_number` and `some_number2` in the above are identical.
-"
-
-Using `Some("a string")` we're going to open the door to references in
-generic positions (which we still need to build up to). We talk a little about
-Option<&str> below, but I don't think it helps explain the enum concept.
-
-/JT --->
-<!-- I changed the above to use `char` rather than string slice, but we're
-trying to show that options holding different types are themselves different
-types below, so I didn't want to make them both `i32`. /Carol -->
-
The type of `some_number` is `Option<i32>`. The type of `some_char` is
`Option<char>`, which is a different type. Rust can infer these types because
we’ve specified a value inside the `Some` variant. For `absent_number`, Rust
@@ -394,13 +337,13 @@ type that the corresponding `Some` variant will hold by looking only at a
`Option<i32>`.
When we have a `Some` value, we know that a value is present and the value is
-held within the `Some`. When we have a `None` value, in some sense, it means
-the same thing as null: we don’t have a valid value. So why is having
-`Option<T>` any better than having null?
+held within the `Some`. When we have a `None` value, in some sense it means the
+same thing as null: we don’t have a valid value. So why is having `Option<T>`
+any better than having null?
In short, because `Option<T>` and `T` (where `T` can be any type) are different
types, the compiler won’t let us use an `Option<T>` value as if it were
-definitely a valid value. For example, this code won’t compile because it’s
+definitely a valid value. For example, this code won’t compile, because it’s
trying to add an `i8` to an `Option<i8>`:
```
@@ -410,11 +353,9 @@ let y: Option<i8> = Some(5);
let sum = x + y;
```
-If we run this code, we get an error message like this:
+If we run this code, we get an error message like this one:
```
-$ cargo run
- Compiling enums v0.1.0 (file:///projects/enums)
error[E0277]: cannot add `Option<i8>` to `i8`
--> src/main.rs:5:17
|
@@ -435,8 +376,7 @@ using the value.
In other words, you have to convert an `Option<T>` to a `T` before you can
perform `T` operations with it. Generally, this helps catch one of the most
-common issues with null: assuming that something isn’t null when it actually
-is.
+common issues with null: assuming that something isn’t null when it actually is.
Eliminating the risk of incorrectly assuming a not-null value helps you to be
more confident in your code. In order to have a value that can possibly be
@@ -447,30 +387,30 @@ when the value is null. Everywhere that a value has a type that isn’t an
deliberate design decision for Rust to limit null’s pervasiveness and increase
the safety of Rust code.
-So, how do you get the `T` value out of a `Some` variant when you have a value
-of type `Option<T>` so you can use that value? The `Option<T>` enum has a large
-number of methods that are useful in a variety of situations; you can check
-them out in its documentation. Becoming familiar with the methods on
+So how do you get the `T` value out of a `Some` variant when you have a value
+of type `Option<T>` so that you can use that value? The `Option<T>` enum has a
+large number of methods that are useful in a variety of situations; you can
+check them out in its documentation. Becoming familiar with the methods on
`Option<T>` will be extremely useful in your journey with Rust.
In general, in order to use an `Option<T>` value, you want to have code that
will handle each variant. You want some code that will run only when you have a
`Some(T)` value, and this code is allowed to use the inner `T`. You want some
-other code to run if you have a `None` value, and that code doesn’t have a `T`
-value available. The `match` expression is a control flow construct that does
-just this when used with enums: it will run different code depending on which
-variant of the enum it has, and that code can use the data inside the matching
-value.
-
-## The `match` Control Flow Construct
-
-Rust has an extremely powerful control flow construct called `match` that allows
-you to compare a value against a series of patterns and then execute code based
-on which pattern matches. Patterns can be made up of literal values, variable
-names, wildcards, and many other things; Chapter 18 covers all the different
-kinds of patterns and what they do. The power of `match` comes from the
-expressiveness of the patterns and the fact that the compiler confirms that all
-possible cases are handled.
+other code to run only if you have a `None` value, and that code doesn’t have a
+`T` value available. The `match` expression is a control flow construct that
+does just this when used with enums: it will run different code depending on
+which variant of the enum it has, and that code can use the data inside the
+matching value.
+
+## The match Control Flow Construct
+
+Rust has an extremely powerful control flow construct called `match` that
+allows you to compare a value against a series of patterns and then execute
+code based on which pattern matches. Patterns can be made up of literal values,
+variable names, wildcards, and many other things; Chapter 18 covers all the
+different kinds of patterns and what they do. The power of `match` comes from
+the expressiveness of the patterns and the fact that the compiler confirms that
+all possible cases are handled.
Think of a `match` expression as being like a coin-sorting machine: coins slide
down a track with variously sized holes along it, and each coin falls through
@@ -479,12 +419,12 @@ through each pattern in a `match`, and at the first pattern the value “fits,
the value falls into the associated code block to be used during execution.
Speaking of coins, let’s use them as an example using `match`! We can write a
-function that takes an unknown United States coin and, in a similar way as the
-counting machine, determines which coin it is and return its value in cents, as
-shown here in Listing 6-3.
+function that takes an unknown US coin and, in a similar way as the counting
+machine, determines which coin it is and returns its value in cents, as shown
+in Listing 6-3.
```
-[1]enum Coin {
+1 enum Coin {
Penny,
Nickel,
Dime,
@@ -492,8 +432,8 @@ shown here in Listing 6-3.
}
fn value_in_cents(coin: Coin) -> u8 {
- match coin {
- Coin::Penny => 1,
+ 2 match coin {
+ 3 Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter => 25,
@@ -504,36 +444,29 @@ fn value_in_cents(coin: Coin) -> u8 {
Listing 6-3: An enum and a `match` expression that has the variants of the enum
as its patterns
-Let’s break down the `match` in the `value_in_cents` function. First, we list
+Let’s break down the `match` in the `value_in_cents` function. First we list
the `match` keyword followed by an expression, which in this case is the value
-`coin`. This seems very similar to an expression used with `if`, but there’s a
-big difference: with `if`, the expression needs to return a Boolean value, but
-here, it can return any type. The type of `coin` in this example is the `Coin`
-enum that we defined at [1].
+`coin` [2]. This seems very similar to an expression used with `if`, but
+there’s a big difference: with `if`, the expression needs to return a Boolean
+value, but here it can return any type. The type of `coin` in this example is
+the `Coin` enum that we defined at [1].
Next are the `match` arms. An arm has two parts: a pattern and some code. The
first arm here has a pattern that is the value `Coin::Penny` and then the `=>`
-operator that separates the pattern and the code to run. The code in this case
-is just the value `1`. Each arm is separated from the next with a comma.
+operator that separates the pattern and the code to run [3]. The code in this
+case is just the value `1`. Each arm is separated from the next with a comma.
-<!--- Tiny nit, though not sure how to phrase it. Arms are separated by commas
-in this example, though if you use blocks instead of simple values you won't use
-commas. We see this happen in the next example.
-/JT --->
-<!-- I clarified in the paragraph before the next example. You *can* use commas
-even if there's curly brackets, but people don't usually. /Carol -->
-
-When the `match` expression executes, it compares the resulting value against
+When the `match` expression executes, it compares the resultant value against
the pattern of each arm, in order. If a pattern matches the value, the code
associated with that pattern is executed. If that pattern doesn’t match the
value, execution continues to the next arm, much as in a coin-sorting machine.
We can have as many arms as we need: in Listing 6-3, our `match` has four arms.
-The code associated with each arm is an expression, and the resulting value of
+The code associated with each arm is an expression, and the resultant value of
the expression in the matching arm is the value that gets returned for the
entire `match` expression.
-We don't typically use curly brackets if the match arm code is short, as it is
+We don’t typically use curly brackets if the match arm code is short, as it is
in Listing 6-3 where each arm just returns a value. If you want to run multiple
lines of code in a match arm, you must use curly brackets, and the comma
following the arm is then optional. For example, the following code prints
@@ -554,7 +487,7 @@ fn value_in_cents(coin: Coin) -> u8 {
}
```
-### Patterns that Bind to Values
+### Patterns That Bind to Values
Another useful feature of match arms is that they can bind to the parts of the
values that match the pattern. This is how we can extract values out of enum
@@ -564,15 +497,15 @@ As an example, let’s change one of our enum variants to hold data inside it.
From 1999 through 2008, the United States minted quarters with different
designs for each of the 50 states on one side. No other coins got state
designs, so only quarters have this extra value. We can add this information to
-our `enum` by changing the `Quarter` variant to include a `UsState` value stored
-inside it, which we’ve done here in Listing 6-4.
+our `enum` by changing the `Quarter` variant to include a `UsState` value
+stored inside it, which we’ve done in Listing 6-4.
```
#[derive(Debug)] // so we can inspect the state in a minute
enum UsState {
Alabama,
Alaska,
- // --snip--
+ --snip--
}
enum Coin {
@@ -588,8 +521,8 @@ Listing 6-4: A `Coin` enum in which the `Quarter` variant also holds a
Let’s imagine that a friend is trying to collect all 50 state quarters. While
we sort our loose change by coin type, we’ll also call out the name of the
-state associated with each quarter so if it’s one our friend doesn’t have, they
-can add it to their collection.
+state associated with each quarter so that if it’s one our friend doesn’t have,
+they can add it to their collection.
In the match expression for this code, we add a variable called `state` to the
pattern that matches values of the variant `Coin::Quarter`. When a
@@ -617,13 +550,13 @@ that point, the binding for `state` will be the value `UsState::Alaska`. We can
then use that binding in the `println!` expression, thus getting the inner
state value out of the `Coin` enum variant for `Quarter`.
-### Matching with `Option<T>`
+### Matching with Option<T>
In the previous section, we wanted to get the inner `T` value out of the `Some`
-case when using `Option<T>`; we can also handle `Option<T>` using `match` as we
-did with the `Coin` enum! Instead of comparing coins, we’ll compare the
-variants of `Option<T>`, but the way that the `match` expression works remains
-the same.
+case when using `Option<T>`; we can also handle `Option<T>` using `match`, as
+we did with the `Coin` enum! Instead of comparing coins, we’ll compare the
+variants of `Option<T>`, but the way the `match` expression works remains the
+same.
Let’s say we want to write a function that takes an `Option<i32>` and, if
there’s a value inside, adds 1 to that value. If there isn’t a value inside,
@@ -636,44 +569,40 @@ Listing 6-5.
```
fn plus_one(x: Option<i32>) -> Option<i32> {
match x {
- None => None,
- Some(i) => Some(i + 1),
+ 1 None => None,
+ 2 Some(i) => Some(i + 1),
}
}
let five = Some(5);
-let six = plus_one(five);
-let none = plus_one(None);
+let six = plus_one(five); 3
+let none = plus_one(None); 4
```
Listing 6-5: A function that uses a `match` expression on an `Option<i32>`
Let’s examine the first execution of `plus_one` in more detail. When we call
-`plus_one(five)`, the variable `x` in the body of `plus_one` will have the
-value `Some(5)`. We then compare that against each match arm.
+`plus_one(five)` [3], the variable `x` in the body of `plus_one` will have the
+value `Some(5)`. We then compare that against each match arm:
```
None => None,
```
-The `Some(5)` value doesn’t match the pattern `None`, so we continue to the
-next arm.
+The `Some(5)` value doesn’t match the pattern `None` [1], so we continue to the
+next arm:
```
Some(i) => Some(i + 1),
```
-Does `Some(5)` match `Some(i)`? Why yes it does! We have the same variant. The
-`i` binds to the value contained in `Some`, so `i` takes the value `5`. The
+Does `Some(5)` match `Some(i)` [2]? Why yes, it does! We have the same variant.
+The `i` binds to the value contained in `Some`, so `i` takes the value `5`. The
code in the match arm is then executed, so we add 1 to the value of `i` and
create a new `Some` value with our total `6` inside.
Now let’s consider the second call of `plus_one` in Listing 6-5, where `x` is
-`None`. We enter the `match` and compare to the first arm.
-
-```
-None => None,
-```
+`None` [4]. We enter the `match` and compare to the first arm [1].
It matches! There’s no value to add to, so the program stops and returns the
`None` value on the right side of `=>`. Because the first arm matched, no other
@@ -704,26 +633,31 @@ a bug Rust knows how to catch. If we try to compile this code, we’ll get this
error:
```
-$ cargo run
- Compiling enums v0.1.0 (file:///projects/enums)
error[E0004]: non-exhaustive patterns: `None` not covered
- --> src/main.rs:3:15
+ --> src/main.rs:3:15
+ |
+3 | match x {
+ | ^ pattern `None` not covered
+ |
+ note: `Option<i32>` defined here
+ = 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
|
-3 | match x {
- | ^ pattern `None` not covered
+4 ~ Some(i) => Some(i + 1),
+5 ~ None => todo!(),
|
- = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms
- = note: the matched value is of type `Option<i32>`
```
-Rust knows that we didn’t cover every possible case and even knows which
+Rust knows that we didn’t cover every possible case, and even knows which
pattern we forgot! Matches in Rust are *exhaustive*: we must exhaust every last
possibility in order for the code to be valid. Especially in the case of
`Option<T>`, when Rust prevents us from forgetting to explicitly handle the
`None` case, it protects us from assuming that we have a value when we might
have null, thus making the billion-dollar mistake discussed earlier impossible.
-### Catch-all Patterns and the `_` Placeholder
+### Catch-all Patterns and the _ Placeholder
Using enums, we can also take special actions for a few particular values, but
for all other values take one default action. Imagine we’re implementing a game
@@ -740,7 +674,7 @@ let dice_roll = 9;
match dice_roll {
3 => add_fancy_hat(),
7 => remove_fancy_hat(),
- other => move_player(other),
+ 1 other => move_player(other),
}
fn add_fancy_hat() {}
@@ -748,10 +682,10 @@ fn remove_fancy_hat() {}
fn move_player(num_spaces: u8) {}
```
-For the first two arms, the patterns are the literal values 3 and 7. For the
-last arm that covers every other possible value, the pattern is the variable
-we’ve chosen to name `other`. The code that runs for the `other` arm uses the
-variable by passing it to the `move_player` function.
+For the first two arms, the patterns are the literal values `3` and `7`. For
+the last arm that covers every other possible value, the pattern is the
+variable we’ve chosen to name `other` [1]. The code that runs for the `other`
+arm uses the variable by passing it to the `move_player` function.
This code compiles, even though we haven’t listed all the possible values a
`u8` can have, because the last pattern will match all values not specifically
@@ -785,10 +719,10 @@ fn reroll() {}
This example also meets the exhaustiveness requirement because we’re explicitly
ignoring all other values in the last arm; we haven’t forgotten anything.
-Finally, we’ll change the rules of the game one more time, so that nothing else
+Finally, we’ll change the rules of the game one more time so that nothing else
happens on your turn if you roll anything other than a 3 or a 7. We can express
that by using the unit value (the empty tuple type we mentioned in “The Tuple
-Type” section) as the code that goes with the `_` arm:
+Type” on page XX) as the code that goes with the `_` arm:
```
let dice_roll = 9;
@@ -810,17 +744,18 @@ There’s more about patterns and matching that we’ll cover in Chapter 18. For
now, we’re going to move on to the `if let` syntax, which can be useful in
situations where the `match` expression is a bit wordy.
-## Concise Control Flow with `if let`
+## Concise Control Flow with if let
The `if let` syntax lets you combine `if` and `let` into a less verbose way to
handle values that match one pattern while ignoring the rest. Consider the
-program in Listing 6-6 that matches on an `Option<u8>` value in the `config_max`
-variable but only wants to execute code if the value is the `Some` variant.
+program in Listing 6-6 that matches on an `Option<u8>` value in the
+`config_max` variable but only wants to execute code if the value is the `Some`
+variant.
```
let config_max = Some(3u8);
match config_max {
- Some(max) => println!("The maximum is configured to be {}", max),
+ Some(max) => println!("The maximum is configured to be {max}"),
_ => (),
}
```
@@ -840,7 +775,7 @@ code behaves the same as the `match` in Listing 6-6:
```
let config_max = Some(3u8);
if let Some(max) = config_max {
- println!("The maximum is configured to be {}", max);
+ println!("The maximum is configured to be {max}");
}
```
@@ -848,7 +783,7 @@ The syntax `if let` takes a pattern and an expression separated by an equal
sign. It works the same way as a `match`, where the expression is given to the
`match` and the pattern is its first arm. In this case, the pattern is
`Some(max)`, and the `max` binds to the value inside the `Some`. We can then
-use `max` in the body of the `if let` block in the same way as we used `max` in
+use `max` in the body of the `if let` block in the same way we used `max` in
the corresponding `match` arm. The code in the `if let` block isn’t run if the
value doesn’t match the pattern.
@@ -867,7 +802,7 @@ We can include an `else` with an `if let`. The block of code that goes with the
`Coin` enum definition in Listing 6-4, where the `Quarter` variant also held a
`UsState` value. If we wanted to count all non-quarter coins we see while also
announcing the state of the quarters, we could do that with a `match`
-expression like this:
+expression, like this:
```
let mut count = 0;
@@ -877,7 +812,7 @@ match coin {
}
```
-Or we could use an `if let` and `else` expression like this:
+Or we could use an `if let` and `else` expression, like this:
```
let mut count = 0;
@@ -901,19 +836,10 @@ values, depending on how many cases you need to handle.
Your Rust programs can now express concepts in your domain using structs and
enums. Creating custom types to use in your API ensures type safety: the
-compiler will make certain your functions get only values of the type each
+compiler will make certain your functions only get values of the type each
function expects.
In order to provide a well-organized API to your users that is straightforward
to use and only exposes exactly what your users will need, let’s now turn to
Rust’s modules.
-<!--- I'm of two minds whether `?` should squeeze in here? We talk about `if
-let` but then switch topics next chapter and talk about modules. In the wild,
-I'd bet `?` would be as common, perhaps more common, than `if let`.
-
-But I'll defer to your pedagogy plan. Just wanted to share the thought.
-/JT --->
-<!-- Yeah introducing `?` here would be a big change; I don't want to talk
-about that until we've talked about `Result` even though you can use `?` on
-`Option` now, because `?` is still way more common with `Result`. /Carol -->
diff --git a/src/doc/book/nostarch/chapter07.md b/src/doc/book/nostarch/chapter07.md
index 32a9eb2fb..8b2dce777 100644
--- a/src/doc/book/nostarch/chapter07.md
+++ b/src/doc/book/nostarch/chapter07.md
@@ -20,7 +20,7 @@ optionally one library crate. As a package grows, you can extract parts into
separate crates that become external dependencies. This chapter covers all
these techniques. For very large projects comprising a set of interrelated
packages that evolve together, Cargo provides *workspaces*, which we’ll cover
-in the “Cargo Workspaces” section in Chapter 14.
+in “Cargo Workspaces” on page XX.
We’ll also discuss encapsulating implementation details, which lets you reuse
code at a higher level: once you’ve implemented an operation, other code can
@@ -43,11 +43,11 @@ organization, including which details are exposed, which details are private,
and what names are in each scope in your programs. These features, sometimes
collectively referred to as the *module system*, include:
-* **Packages:** A Cargo feature that lets you build, test, and share crates
-* **Crates:** A tree of modules that produces a library or executable
-* **Modules** and **use:** Let you control the organization, scope, and
- privacy of paths
-* **Paths:** A way of naming an item, such as a struct, function, or module
+* **Packages **: A Cargo feature that lets you build, test, and share crates
+* **Crates**: A tree of modules that produces a library or executable
+* **Modules and use**: Let you control the organization, scope, and privacy of
+paths
+* **Paths **: A way of naming an item, such as a struct, function, or module
In this chapter, we’ll cover all these features, discuss how they interact, and
explain how to use them to manage scope. By the end, you should have a solid
@@ -57,37 +57,16 @@ understanding of the module system and be able to work with scopes like a pro!
The first parts of the module system we’ll cover are packages and crates.
-<!-- Do you have a general definition of a crate we can add, or is it too
-dependent on whether it's a binary or library crate? /LC -->
-<!-- I've struggled to come up with something that isn't just "smaller than a
-package but bigger than a module"... "reusable" or "what you specify as a
-dependency" only applies to library crates... this definition I've added here
-gets a little bit into how the compiler sees crates, which might be too much
-detail? What do you think about this next paragraph? /Carol -->
-<!-- JT, what do you think? /LC -->
-<!-- I think this works.
-
-Carol - I'm wondering a bit if "packages" above helps the reader build the
-mental model or if it's kind of an implementation detail for cargo (we could
-say we "package crates"). You're definitely the expert here, but I wonder if we
-can simplify down to Crates/Modules/Paths and mention that we'll introduce some
-of the techniques the tooling uses to work with these later. /JT -->
-<!-- I feel like we need to explain the `[package]` section in *Cargo.toml*,
-and explain what the container is when you have a library and one or more
-binaries in one directory, and that's a package. It is a little weird because
-people hardly ever talk in terms of packages, only in terms of crates, but I
-think it's better to have the discussion of package here. /Carol -->
-
A *crate* is the smallest amount of code that the Rust compiler considers at a
time. Even if you run `rustc` rather than `cargo` and pass a single source code
-file (as we did all the way back in the “Writing and Running a Rust Program”
-section of Chapter 1), the compiler considers that file to be a crate. Crates
-can contain modules, and the modules may be defined in other files that get
-compiled with the crate, as we’ll see in the coming sections.
+file (as we did all the way back in “Writing and Running a Rust Program” on
+page XX), the compiler considers that file to be a crate. Crates can contain
+modules, and the modules may be defined in other files that get compiled with
+the crate, as we’ll see in the coming sections.
A crate can come in one of two forms: a binary crate or a library crate.
*Binary crates* are programs you can compile to an executable that you can run,
-such as a command-line program or a server. Each must have a function called
+such as a command line program or a server. Each must have a function called
`main` that defines what happens when the executable runs. All the crates we’ve
created so far have been binary crates.
@@ -95,27 +74,28 @@ created so far have been binary crates.
executable. Instead, they define functionality intended to be shared with
multiple projects. For example, the `rand` crate we used in Chapter 2 provides
functionality that generates random numbers. Most of the time when Rustaceans
-say “crate”, they mean library crate, and they use “crate” interchangeably with
-the general programming concept of a “library".
+say “crate,” they mean library crate, and they use “crate” interchangeably with
+the general programming concept of a “library.”
The *crate root* is a source file that the Rust compiler starts from and makes
-up the root module of your crate (we’ll explain modules in depth in the
-“Defining Modules to Control Scope and Privacy” section).
+up the root module of your crate (we’ll explain modules in depth in “Defining
+Modules to Control Scope and Privacy” on page XX).
A *package* is a bundle of one or more crates that provides a set of
functionality. A package contains a *Cargo.toml* file that describes how to
build those crates. Cargo is actually a package that contains the binary crate
-for the command-line tool you’ve been using to build your code. The Cargo
+for the command line tool you’ve been using to build your code. The Cargo
package also contains a library crate that the binary crate depends on. Other
projects can depend on the Cargo library crate to use the same logic the Cargo
-command-line tool uses.
+command line tool uses.
-A package can contain as many binary crates as you like, but at most only one
+A crate can come in one of two forms: a binary crate or a library crate. A
+package can contain as many binary crates as you like, but at most only one
library crate. A package must contain at least one crate, whether that’s a
library or binary crate.
-Let’s walk through what happens when we create a package. First, we enter the
-command `cargo new`:
+Let’s walk through what happens when we create a package. First we enter the
+command `cargo new my-project`:
```
$ cargo new my-project
@@ -127,19 +107,15 @@ $ ls my-project/src
main.rs
```
-<!-- I can't remember if we warned folks we were going to use unix commands. May
-want to throw in the Windows command here too, so they feel welcome. /JT -->
-<!-- I don't think JT has seen chapter 1 yet, we address that there /Carol -->
-
-After we run `cargo new`, we use `ls` to see what Cargo creates. In the project
-directory, there’s a *Cargo.toml* file, giving us a package. There’s also a
-*src* directory that contains *main.rs*. Open *Cargo.toml* in your text editor,
-and note there’s no mention of *src/main.rs*. Cargo follows a convention that
-*src/main.rs* is the crate root of a binary crate with the same name as the
-package. Likewise, Cargo knows that if the package directory contains
-*src/lib.rs*, the package contains a library crate with the same name as the
-package, and *src/lib.rs* is its crate root. Cargo passes the crate root files
-to `rustc` to build the library or binary.
+After we run `cargo new my-project`, we use `ls` to see what Cargo creates. In
+the project directory, there’s a *Cargo.toml* file, giving us a package.
+There’s also a *src* directory that contains *main.rs*. Open *Cargo.toml* in
+your text editor, and note there’s no mention of *src/main.rs*. Cargo follows a
+convention that *src/main.rs* is the crate root of a binary crate with the same
+name as the package. Likewise, Cargo knows that if the package directory
+contains *src/lib.rs*, the package contains a library crate with the same name
+as the package, and *src/lib.rs* is its crate root. Cargo passes the crate root
+files to `rustc` to build the library or binary.
Here, we have a package that only contains *src/main.rs*, meaning it only
contains a binary crate named `my-project`. If a package contains *src/main.rs*
@@ -147,154 +123,103 @@ and *src/lib.rs*, it has two crates: a binary and a library, both with the same
name as the package. A package can have multiple binary crates by placing files
in the *src/bin* directory: each file will be a separate binary crate.
-## Defining Modules to Control Scope and Privacy
-
-In this section, we’ll talk about modules and other parts of the module system,
-namely *paths* that allow you to name items; the `use` keyword that brings a
-path into scope; and the `pub` keyword to make items public. We’ll also discuss
-the `as` keyword, external packages, and the glob operator.
-
-First, we’re going to start with a list of rules for easy reference when you’re
-organizing your code in the future. Then we’ll explain each of the rules in
-detail.
-
-### Modules Cheat Sheet
-
-<!--WHEN TRANSFERRED TO WORD, DECIDE ON BOX OR NOT -->
-
-Here we provide a quick reference on how modules, paths, the `use` keyword, and
-the `pub` keyword work in the compiler, and how most developers organize their
-code. We’ll be going through examples of each of these rules throughout this
-chapter, but this is a great place to refer to as a reminder of how modules
-work.
-
-- **Start from the crate root**: When compiling a crate, the compiler first
- looks in the crate root file (usually *src/lib.rs* for a library crate or
- *src/main.rs* for a binary crate) for code to compile.
- <!-- I may be asking a silly question here... but what is the compiler looking
- for in the crate root file? just things to start compiling? /LC -->
- <!-- That's exactly it-- it's the starting point of compilation, and the
- compiler will only find files if they're connected to the crate root somehow.
- Do you think that should be mentioned here? Is there something about this
- explanation that would make you feel more confident about the concept? /Carol
- -->
- <!-- I've added "for things to compile" -- I wanted to make sure the reader
- knew they weren't missing anything, that there wasn't a particular thing
- being looked for that the reader wasn't aware of /LC -->
- <!-- I changed "things" to "code" to be more precise /Carol -->
-- **Declaring modules**: In the crate root file, you can declare new modules;
-say, you declare a “garden” module with `mod garden;`. The compiler will look
+> ### Modules Cheat Sheet
+>
+> Before we get to the details of modules and paths, here we provide a quick
+reference on how modules, paths, the `use` keyword, and the `pub` keyword work
+in the compiler, and how most developers organize their code. We’ll be going
+through examples of each of these rules throughout this chapter, but this is a
+great place to refer to as a reminder of how modules work.
+>
+> * **Start from the crate root**: When compiling a crate, the compiler first
+looks in the crate root file (usually *src/lib.rs* for a library crate or
+*src/main.rs* for a binary crate) for code to compile.
+> * **Declaring modules**: In the crate root file, you can declare new modules;
+say you declare a “garden” module with `mod garden;`. The compiler will look
for the module’s code in these places:
-
- - Inline, within curly brackets that replace the semicolon following `mod
- garden`
- <!-- instead of or after the semicolon? Or is all of this instead of a
- semicolon? /LC -->
- <!-- Curly brackets and everything within them instead of the semicolon.
- I'm not sure a pithy way to make that distinction clearer? /Carol -->
- <!-- JT, would "Inline, within curly brackets that replace the semicolon
- following `mod garden` be clearer/accurate? /LC -->
- <!-- I wonder if we should order it where this cheatsheet happens after
- we show more examples. Most of the time, you'll use the `mod` keyword to
- pull files in as you refactor out into separate files. Sometimes you'll use
- it for those key cases, like grouping tests. Showing those examples and then
- going into the resolution may be a bit easier.
-
- To your question - I think of this as something that could be more of
- a warning. If you want to use `mod foo`, then be sure you haven't already
- declared a module called that in the current file. If you do, the compiler
- will see it first before it looks for a file with that name. /JT -->
- <!-- I feel pretty strongly that the cheat sheet needs to go first, so that
- after a reader's first time through the book, when they go back to the
- modules chapter to try and figure out why their modules aren't working,
- they get this first rather than having to read through or skip through the
- examples when they're already frustrated.
-
- I also don't feel like the "warning" way of talking about this belongs
- here. I almost added a section called "common mistakes" or "pitfalls" or
- "troubleshooting", and I think talking about what you *don't* want to do
- would belong there...
-
- Liz, I'm fine with your suggested wording and I've made that change. /Carol
- -->
-
- - In the file *src/garden.rs*
- - In the file *src/garden/mod.rs*
-- **Declaring submodules**: In any file other than the crate root, you can
- declare submodules. For example, you might declare `mod vegetables;` in
- *src/garden.rs*. The compiler will look for the submodule’s code within the
- directory named for the parent module in these places:
- - Inline, directly following `mod vegetables`, within curly brackets instead
- of the semicolon
- - In the file *src/garden/vegetables.rs*
- - In the file *src/garden/vegetables/mod.rs*
-- **Paths to code in modules**: Once a module is part of your crate, you can
- refer to code in that module from anywhere else in that same crate, as long
- as the privacy rules allow, using the path to the code. For example, an
- `Asparagus` type in the garden vegetables module would be found at
- `crate::garden::vegetables::Asparagus`.
-- **Private vs public**: Code within a module is private from its parent
- modules by default. To make a module public, declare it with `pub mod`
- instead of `mod`. To make items within a public module public as well, use
- `pub` before their declarations.
-- **The `use` keyword**: Within a scope, the `use` keyword creates shortcuts to
- items to reduce repetition of long paths. In any scope that can refer to
- `crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
- crate::garden::vegetables::Asparagus;` and from then on you only need to
- write `Asparagus` to make use of that type in the scope.
-
-Here we create a binary crate named `backyard` that illustrates these rules. The
-crate’s directory, also named `backyard`, contains these files and directories:
-
-```
-backyard
-├── Cargo.lock
-├── Cargo.toml
-└── src
- ├── garden
- │   └── vegetables.rs
- ├── garden.rs
- └── main.rs
-```
-
-The crate root file in this case is *src/main.rs*, and it contains:
-
-Filename: src/main.rs
-
-```
-use crate::garden::vegetables::Asparagus;
-
-pub mod garden;
-
-fn main() {
- let plant = Asparagus {};
- println!("I'm growing {:?}!", plant);
-}
-```
-
-The `pub mod garden;` line tells the compiler to include the code it finds in
+>
+> * Inline, within curly brackets that replace the semicolon following `mod
+garden`
+> * In the file *src/garden.rs.*
+> * In the file *src/garden/mod.rs*
+> * **Declaring submodules**: In any file other than the crate root, you can
+declare submodules. For example, you might declare `mod vegetables;` in
+*src/garden.rs*. The compiler will look for the submodule’s code within the
+directory named for the parent module in these places:
+>
+> * Inline, directly following `mod vegetables`, within curly brackets instead
+of the semicolon
+> * In the file *src/garden/vegetables.rs*
+> * In the file *src/garden/vegetables/mod.rs*
+> * **Paths to code in modules**: Once a module is part of your crate, you can
+refer to code in that module from anywhere else in that same crate, as long as
+the privacy rules allow, using the path to the code. For example, an
+`Asparagus` type in the garden vegetables module would be found at
+`crate::garden::vegetables::Asparagus`.
+> * **Private vs. public**: Code within a module is private from its parent
+modules by default. To make a module public, declare it with `pub mod` instead
+of `mod`. To make items within a public module public as well, use `pub` before
+their declarations.
+> * **The use keyword**: Within a scope, the `use` keyword creates shortcuts to
+items to reduce repetition of long paths. In any scope that can refer to
+`crate::garden::vegetables::Asparagus`, you can create a shortcut with `use
+crate::garden::vegetables::Asparagus;` and from then on you only need to write
+`Asparagus` to make use of that type in the scope.
+>
+> Here, we create a binary crate named `backyard` that illustrates these rules.
+The crate’s directory, also named `backyard`, contains these files and
+directories:
+>
+> ```
+> backyard
+> ├── Cargo.lock
+> ├── Cargo.toml
+> └── src
+> ├── garden
+> │ └── vegetables.rs
+> ├── garden.rs
+> └── main.rs
+> ```
+>
+> The crate root file in this case is *src/main.rs*, and it contains:
+>
+> ```
+> use crate::garden::vegetables::Asparagus;
+>
+> pub mod garden;
+>
+> fn main() {
+> let plant = Asparagus {};
+> println!("I'm growing {:?}!", plant);
+> }
+> ```
+>
+> The `pub mod garden;` line tells the compiler to include the code it finds in
*src/garden.rs*, which is:
-
-Filename: src/garden.rs
-
-```
-pub mod vegetables;
-```
-
-Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
+>
+> ```
+> pub mod vegetables;
+> ```
+>
+> Here, `pub mod vegetables;` means the code in *src/garden/vegetables.rs* is
included too. That code is:
+>
+> ```
+> #[derive(Debug)]
+> pub struct Asparagus {}
+> ```
+>
+> Now let’s get into the details of these rules and demonstrate them in action!
-```
-#[derive(Debug)]
-pub struct Asparagus {}
-```
-
-Now let’s get into the details of these rules and demonstrate them in action!
+## Defining Modules to Control Scope and Privacy
-### Grouping Related Code in Modules
+In this section, we’ll talk about modules and other parts of the module system,
+namely *paths*, which allow you to name items; the `use` keyword that brings a
+path into scope; and the `pub` keyword to make items public. We’ll also discuss
+the `as` keyword, external packages, and the glob operator.
*Modules* let us organize code within a crate for readability and easy reuse.
-Modules also allow us to control the *privacy* of items, because code within a
+Modules also allow us to control the *privacy* of items because code within a
module is private by default. Private items are internal implementation details
not available for outside use. We can choose to make modules and the items
within them public, which exposes them to allow external code to use and depend
@@ -302,7 +227,7 @@ on them.
As an example, let’s write a library crate that provides the functionality of a
restaurant. We’ll define the signatures of functions but leave their bodies
-empty to concentrate on the organization of the code, rather than the
+empty to concentrate on the organization of the code rather than the
implementation of a restaurant.
In the restaurant industry, some parts of a restaurant are referred to as
@@ -313,9 +238,10 @@ chefs and cooks work in the kitchen, dishwashers clean up, and managers do
administrative work.
To structure our crate in this way, we can organize its functions into nested
-modules. Create a new library named `restaurant` by running `cargo new --lib
-restaurant`; then enter the code in Listing 7-1 into *src/lib.rs* to define
-some modules and function signatures. Here’s the front of house section:
+modules. Create a new library named `restaurant` by running `cargo new
+restaurant --lib`. Then enter the code in Listing 7-1 into *src/lib.rs* to
+define some modules and function signatures; this code is the front of house
+section.
Filename: src/lib.rs
@@ -374,13 +300,13 @@ crate
Listing 7-2: The module tree for the code in Listing 7-1
-This tree shows how some of the modules nest inside one another; for example,
+This tree shows how some of the modules nest inside other modules; for example,
`hosting` nests inside `front_of_house`. The tree also shows that some modules
-are *siblings* to each other, meaning they’re defined in the same module;
-`hosting` and `serving` are siblings defined within `front_of_house`. If module
-A is contained inside module B, we say that module A is the *child* of module B
-and that module B is the *parent* of module A. Notice that the entire module
-tree is rooted under the implicit module named `crate`.
+are *siblings*, meaning they’re defined in the same module; `hosting` and
+`serving` are siblings defined within `front_of_house`. If module A is
+contained inside module B, we say that module A is the *child* of module B and
+that module B is the *parent* of module A. Notice that the entire module tree
+is rooted under the implicit module named `crate`.
The module tree might remind you of the filesystem’s directory tree on your
computer; this is a very apt comparison! Just like directories in a filesystem,
@@ -395,28 +321,27 @@ know its path.
A path can take two forms:
-* An *absolute path* is the full path starting from a crate root; for code
- from an external crate, the absolute path begins with the crate name, and for
- code from the current crate, it starts with the literal `crate`.
+* An *absolute path* is the full path starting from a crate root; for code from
+an external crate, the absolute path begins with the crate name, and for code
+from the current crate, it starts with the literal `crate`.
* A *relative path* starts from the current module and uses `self`, `super`, or
- an identifier in the current module.
+an identifier in the current module.
Both absolute and relative paths are followed by one or more identifiers
separated by double colons (`::`).
Returning to Listing 7-1, say we want to call the `add_to_waitlist` function.
This is the same as asking: what’s the path of the `add_to_waitlist` function?
-Listing 7-3 contains Listing 7-1 with some of the modules and functions
-removed.
+Listing 7-3 contains Listing 7-1 with some of the modules and functions removed.
-We’ll show two ways to call the `add_to_waitlist` function from a new function
-`eat_at_restaurant` defined in the crate root. These paths are correct, but
+We’ll show two ways to call the `add_to_waitlist` function from a new function,
+`eat_at_restaurant`, defined in the crate root. These paths are correct, but
there’s another problem remaining that will prevent this example from compiling
-as-is. We’ll explain why in a bit.
+as is. We’ll explain why in a bit.
The `eat_at_restaurant` function is part of our library crate’s public API, so
-we mark it with the `pub` keyword. In the “Exposing Paths with the `pub`
-Keyword” section, we’ll go into more detail about `pub`.
+we mark it with the `pub` keyword. In “Exposing Paths with the pub Keyword” on
+page XX, we’ll go into more detail about `pub`.
Filename: src/lib.rs
@@ -436,10 +361,6 @@ pub fn eat_at_restaurant() {
}
```
-<!-- We should probably let the reader know the above is expected to fail a
-little earlier. /JT -->
-<!-- I've rearranged a bit /Carol -->
-
Listing 7-3: Calling the `add_to_waitlist` function using absolute and relative
paths
@@ -460,20 +381,20 @@ filesystem equivalent would be using the path
that the path is relative.
Choosing whether to use a relative or absolute path is a decision you’ll make
-based on your project, and depends on whether you’re more likely to move item
-definition code separately from or together with the code that uses the item.
-For example, if we move the `front_of_house` module and the `eat_at_restaurant`
-function into a module named `customer_experience`, we’d need to update the
-absolute path to `add_to_waitlist`, but the relative path would still be valid.
-However, if we moved the `eat_at_restaurant` function separately into a module
-named `dining`, the absolute path to the `add_to_waitlist` call would stay the
-same, but the relative path would need to be updated.
-
-Our preference in general is to specify absolute paths because it’s more likely
-we’ll want to move code definitions and item calls independently of each other.
+based on your project, and it depends on whether you’re more likely to move
+item definition code separately from or together with the code that uses the
+item. For example, if we moved the `front_of_house` module and the
+`eat_at_restaurant` function into a module named `customer_experience`, we’d
+need to update the absolute path to `add_to_waitlist`, but the relative path
+would still be valid. However, if we moved the `eat_at_restaurant` function
+separately into a module named `dining`, the absolute path to the
+`add_to_waitlist` call would stay the same, but the relative path would need to
+be updated. Our preference in general is to specify absolute paths because it’s
+more likely we’ll want to move code definitions and item calls independently of
+each other.
Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
-error we get is shown in Listing 7-4.
+errors we get are shown in Listing 7-4.
```
$ cargo build
@@ -526,7 +447,7 @@ inner code you can change without breaking outer code. However, Rust does give
you the option to expose inner parts of child modules’ code to outer ancestor
modules by using the `pub` keyword to make an item public.
-### Exposing Paths with the `pub` Keyword
+### Exposing Paths with the pub Keyword
Let’s return to the error in Listing 7-4 that told us the `hosting` module is
private. We want the `eat_at_restaurant` function in the parent module to have
@@ -542,20 +463,14 @@ mod front_of_house {
}
}
-pub fn eat_at_restaurant() {
- // Absolute path
- crate::front_of_house::hosting::add_to_waitlist();
-
- // Relative path
- front_of_house::hosting::add_to_waitlist();
-}
+--snip--
```
Listing 7-5: Declaring the `hosting` module as `pub` to use it from
`eat_at_restaurant`
-Unfortunately, the code in Listing 7-5 still results in an error, as shown in
-Listing 7-6.
+Unfortunately, the code in Listing 7-5 still results in compiler errors, as
+shown in Listing 7-6.
```
$ cargo build
@@ -612,17 +527,11 @@ mod front_of_house {
}
}
-pub fn eat_at_restaurant() {
- // Absolute path
- crate::front_of_house::hosting::add_to_waitlist();
-
- // Relative path
- front_of_house::hosting::add_to_waitlist();
-}
+--snip--
```
Listing 7-7: Adding the `pub` keyword to `mod hosting` and `fn add_to_waitlist`
-lets us call the function from `eat_at_restaurant`
+lets us call the function from `eat_at_restaurant`.
Now the code will compile! To see why adding the `pub` keyword lets us use
these paths in `add_to_waitlist` with respect to the privacy rules, let’s look
@@ -650,48 +559,45 @@ If you plan on sharing your library crate so other projects can use your code,
your public API is your contract with users of your crate that determines how
they can interact with your code. There are many considerations around managing
changes to your public API to make it easier for people to depend on your
-crate. These considerations are out of the scope of this book; if you’re
-interested in this topic, see The Rust API Guidelines at
-*https://rust-lang.github.io/api-guidelines/*.
-
+crate. These considerations are beyond the scope of this book; if you’re
+interested in this topic, see the Rust API Guidelines at
+*https://rust-lang.github.io/api-guidelines*.
-> #### Best Practices for Packages with a Binary and a Library
+> ### Best Practices for Packages with a Binary and a Library
>
-> We mentioned a package can contain both a *src/main.rs* binary crate root as
-> well as a *src/lib.rs* library crate root, and both crates will have the
-> package name by default. Typically, packages with this pattern of containing
-> both a library and a binary crate will have just
-> enough code in the binary crate to start an executable that calls code with
-> the library crate. This lets other projects benefit from the most
-> functionality that the package provides, because the library crate’s code can
-> be shared.
+> We mentioned that a package can contain both a *src/main.rs* binary crate
+root as well as a *src/lib.rs* library crate root, and both crates will have
+the package name by default. Typically, packages with this pattern of
+containing both a library and a binary crate will have just enough code in the
+binary crate to start an executable that calls code with the library crate.
+This lets other projects benefit from the most functionality that the package
+provides because the library crate’s code can be shared.
>
> The module tree should be defined in *src/lib.rs*. Then, any public items can
-> be used in the binary crate by starting paths with the name of the package.
-> The binary crate becomes a user of the library crate just like a completely
-> external crate would use the library crate: it can only use the public API.
-> This helps you design a good API; not only are you the author, you’re also a
-> client!
+be used in the binary crate by starting paths with the name of the package. The
+binary crate becomes a user of the library crate just like a completely
+external crate would use the library crate: it can only use the public API.
+This helps you design a good API; not only are you the author, you’re also a
+client!
>
-> In Chapter 12, we’ll demonstrate this organizational practice with a
-> command-line program that will contain both a binary crate and a library
-> crate.
+> In Chapter 12, we’ll demonstrate this organizational practice with a command
+line program that will contain both a binary crate and a library crate.
-### Starting Relative Paths with `super`
+### Starting Relative Paths with super
We can construct relative paths that begin in the parent module, rather than
the current module or the crate root, by using `super` at the start of the
path. This is like starting a filesystem path with the `..` syntax. Using
`super` allows us to reference an item that we know is in the parent module,
which can make rearranging the module tree easier when the module is closely
-related to the parent, but the parent might be moved elsewhere in the module
+related to the parent but the parent might be moved elsewhere in the module
tree someday.
Consider the code in Listing 7-8 that models the situation in which a chef
fixes an incorrect order and personally brings it out to the customer. The
function `fix_incorrect_order` defined in the `back_of_house` module calls the
function `deliver_order` defined in the parent module by specifying the path to
-`deliver_order` starting with `super`:
+`deliver_order`, starting with `super`.
Filename: src/lib.rs
@@ -722,7 +628,7 @@ code gets moved to a different module.
### Making Structs and Enums Public
We can also use `pub` to designate structs and enums as public, but there are a
-few details extra to the usage of `pub` with structs and enums. If we use `pub`
+few extra details to the usage of `pub` with structs and enums. If we use `pub`
before a struct definition, we make the struct public, but the struct’s fields
will still be private. We can make each field public or not on a case-by-case
basis. In Listing 7-9, we’ve defined a public `back_of_house::Breakfast` struct
@@ -758,8 +664,9 @@ pub fn eat_at_restaurant() {
meal.toast = String::from("Wheat");
println!("I'd like {} toast please", meal.toast);
- // The next line won't compile if we uncomment it; we're not allowed
- // to see or modify the seasonal fruit that comes with the meal
+ // The next line won't compile if we uncomment it; we're not
+ // allowed to see or modify the seasonal fruit that comes
+ // with the meal
// meal.seasonal_fruit = String::from("blueberries");
}
```
@@ -769,7 +676,7 @@ Listing 7-9: A struct with some public fields and some private fields
Because the `toast` field in the `back_of_house::Breakfast` struct is public,
in `eat_at_restaurant` we can write and read to the `toast` field using dot
notation. Notice that we can’t use the `seasonal_fruit` field in
-`eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
+`eat_at_restaurant`, because `seasonal_fruit` is private. Try uncommenting the
line modifying the `seasonal_fruit` field value to see what error you get!
Also, note that because `back_of_house::Breakfast` has a private field, the
@@ -798,7 +705,7 @@ pub fn eat_at_restaurant() {
}
```
-Listing 7-10: Designating an enum as public makes all its variants public
+Listing 7-10: Designating an enum as public makes all its variants public.
Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
variants in `eat_at_restaurant`.
@@ -813,7 +720,7 @@ There’s one more situation involving `pub` that we haven’t covered, and that
our last module system feature: the `use` keyword. We’ll cover `use` by itself
first, and then we’ll show how to combine `pub` and `use`.
-## Bringing Paths into Scope with the `use` Keyword
+## Bringing Paths into Scope with the use Keyword
Having to write out the paths to call functions can feel inconvenient and
repetitive. In Listing 7-7, whether we chose the absolute or relative path to
@@ -854,7 +761,7 @@ also check privacy, like any other paths.
Note that `use` only creates the shortcut for the particular scope in which the
`use` occurs. Listing 7-12 moves the `eat_at_restaurant` function into a new
child module named `customer`, which is then a different scope than the `use`
-statement, so the function body won’t compile:
+statement, so the function body won’t compile.
Filename: src/lib.rs
@@ -874,7 +781,7 @@ mod customer {
}
```
-Listing 7-12: A `use` statement only applies in the scope it’s in
+Listing 7-12: A `use` statement only applies in the scope it’s in.
The compiler error shows that the shortcut no longer applies within the
`customer` module:
@@ -900,11 +807,11 @@ fix this problem, move the `use` within the `customer` module too, or reference
the shortcut in the parent module with `super::hosting` within the child
`customer` module.
-### Creating Idiomatic `use` Paths
+### Creating Idiomatic use Paths
In Listing 7-11, you might have wondered why we specified `use
crate::front_of_house::hosting` and then called `hosting::add_to_waitlist` in
-`eat_at_restaurant` rather than specifying the `use` path all the way out to
+`eat_at_restaurant`, rather than specifying the `use` path all the way out to
the `add_to_waitlist` function to achieve the same result, as in Listing 7-13.
Filename: src/lib.rs
@@ -926,9 +833,9 @@ pub fn eat_at_restaurant() {
Listing 7-13: Bringing the `add_to_waitlist` function into scope with `use`,
which is unidiomatic
-Although both Listing 7-11 and 7-13 accomplish the same task, Listing 7-11 is
-the idiomatic way to bring a function into scope with `use`. Bringing the
-function’s parent module into scope with `use` means we have to specify the
+Although both Listing 7-11 and Listing 7-13 accomplish the same task, Listing
+7-11 is the idiomatic way to bring a function into scope with `use`. Bringing
+the function’s parent module into scope with `use` means we have to specify the
parent module when calling the function. Specifying the parent module when
calling the function makes it clear that the function isn’t locally defined
while still minimizing repetition of the full path. The code in Listing 7-13 is
@@ -958,7 +865,7 @@ emerged, and folks have gotten used to reading and writing Rust code this way.
The exception to this idiom is if we’re bringing two items with the same name
into scope with `use` statements, because Rust doesn’t allow that. Listing 7-15
shows how to bring two `Result` types into scope that have the same name but
-different parent modules and how to refer to them.
+different parent modules, and how to refer to them.
Filename: src/lib.rs
@@ -967,11 +874,11 @@ use std::fmt;
use std::io;
fn function1() -> fmt::Result {
- // --snip--
+ --snip--
}
fn function2() -> io::Result<()> {
- // --snip--
+ --snip--
}
```
@@ -980,10 +887,10 @@ requires using their parent modules.
As you can see, using the parent modules distinguishes the two `Result` types.
If instead we specified `use std::fmt::Result` and `use std::io::Result`, we’d
-have two `Result` types in the same scope and Rust wouldn’t know which one we
+have two `Result` types in the same scope, and Rust wouldn’t know which one we
meant when we used `Result`.
-### Providing New Names with the `as` Keyword
+### Providing New Names with the as Keyword
There’s another solution to the problem of bringing two types of the same name
into the same scope with `use`: after the path, we can specify `as` and a new
@@ -997,11 +904,11 @@ use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
- // --snip--
+ --snip--
}
fn function2() -> IoResult<()> {
- // --snip--
+ --snip--
}
```
@@ -1012,13 +919,13 @@ In the second `use` statement, we chose the new name `IoResult` for the
that we’ve also brought into scope. Listing 7-15 and Listing 7-16 are
considered idiomatic, so the choice is up to you!
-### Re-exporting Names with `pub use`
+### Re-exporting Names with pub use
When we bring a name into scope with the `use` keyword, the name available in
the new scope is private. To enable the code that calls our code to refer to
that name as if it had been defined in that code’s scope, we can combine `pub`
-and `use`. This technique is called *re-exporting* because we’re bringing
-an item into scope but also making that item available for others to bring into
+and `use`. This technique is called *re-exporting* because we’re bringing an
+item into scope but also making that item available for others to bring into
their scope.
Listing 7-17 shows the code in Listing 7-11 with `use` in the root module
@@ -1047,7 +954,7 @@ Before this change, external code would have to call the `add_to_waitlist`
function by using the path
`restaurant::front_of_house::hosting::add_to_waitlist()`. Now that this `pub
use` has re-exported the `hosting` module from the root module, external code
-can now use the path `restaurant::hosting::add_to_waitlist()` instead.
+can use the path `restaurant::hosting::add_to_waitlist()` instead.
Re-exporting is useful when the internal structure of your code is different
from how programmers calling your code would think about the domain. For
@@ -1057,8 +964,8 @@ probably won’t think about the parts of the restaurant in those terms. With
`pub use`, we can write our code with one structure but expose a different
structure. Doing so makes our library well organized for programmers working on
the library and programmers calling the library. We’ll look at another example
-of `pub use` and how it affects your crate’s documentation in the “Exporting a
-Convenient Public API with `pub use`” section of Chapter 14.
+of `pub use` and how it affects your crate’s documentation in “Exporting a
+Convenient Public API with pub use” on page XX.
### Using External Packages
@@ -1069,29 +976,29 @@ added this line to *Cargo.toml*:
Filename: Cargo.toml
```
-rand = "0.8.3"
+rand = "0.8.5"
```
Adding `rand` as a dependency in *Cargo.toml* tells Cargo to download the
-`rand` package and any dependencies from *https://crates.io/* and make `rand`
+`rand` package and any dependencies from *https://crates.io*, and make `rand`
available to our project.
Then, to bring `rand` definitions into the scope of our package, we added a
`use` line starting with the name of the crate, `rand`, and listed the items we
-wanted to bring into scope. Recall that in the “Generating a Random Number”
-section in Chapter 2, we brought the `Rng` trait into scope and called the
-`rand::thread_rng` function:
+wanted to bring into scope. Recall that in “Generating a Random Number” on page
+XX, we brought the `Rng` trait into scope and called the `rand::thread_rng`
+function:
```
use rand::Rng;
fn main() {
- let secret_number = rand::thread_rng().gen_range(1..101);
+ let secret_number = rand::thread_rng().gen_range(1..=100);
}
```
Members of the Rust community have made many packages available at
-*https://crates.io/*, and pulling any of them into your package involves these
+*https://crates.io*, and pulling any of them into your package involves these
same steps: listing them in your package’s *Cargo.toml* file and using `use` to
bring items from their crates into scope.
@@ -1108,20 +1015,20 @@ use std::collections::HashMap;
This is an absolute path starting with `std`, the name of the standard library
crate.
-### Using Nested Paths to Clean Up Large `use` Lists
+### Using Nested Paths to Clean Up Large use Lists
-If we’re using multiple items defined in the same crate or same module,
-listing each item on its own line can take up a lot of vertical space in our
-files. For example, these two `use` statements we had in the Guessing Game in
-Listing 2-4 bring items from `std` into scope:
+If we’re using multiple items defined in the same crate or same module, listing
+each item on its own line can take up a lot of vertical space in our files. For
+example, these two `use` statements we had in the guessing game in Listing 2-4
+bring items from `std` into scope:
Filename: src/main.rs
```
-// --snip--
+--snip--
use std::cmp::Ordering;
use std::io;
-// --snip--
+--snip--
```
Instead, we can use nested paths to bring the same items into scope in one
@@ -1132,9 +1039,9 @@ differ, as shown in Listing 7-18.
Filename: src/main.rs
```
-// --snip--
+--snip--
use std::{cmp::Ordering, io};
-// --snip--
+--snip--
```
Listing 7-18: Specifying a nested path to bring multiple items with the same
@@ -1187,10 +1094,9 @@ harder to tell what names are in scope and where a name used in your program
was defined.
The glob operator is often used when testing to bring everything under test
-into the `tests` module; we’ll talk about that in the “How to Write Tests”
-section in Chapter 11. The glob operator is also sometimes used as part of the
-prelude pattern: see the standard library documentation for more information on
-that pattern.
+into the `tests` module; we’ll talk about that in “How to Write Tests” on page
+XX. The glob operator is also sometimes used as part of the prelude pattern:
+see the standard library documentation for more information on that pattern.
## Separating Modules into Different Files
@@ -1204,7 +1110,7 @@ modules defined in the crate root file. In this case, the crate root file is
*src/lib.rs*, but this procedure also works with binary crates whose crate root
file is *src/main.rs*.
-First, we’ll extract the `front_of_house` module to its own file. Remove the
+First we’ll extract the `front_of_house` module to its own file. Remove the
code inside the curly brackets for the `front_of_house` module, leaving only
the `mod front_of_house;` declaration, so that *src/lib.rs* contains the code
shown in Listing 7-21. Note that this won’t compile until we create the
@@ -1245,18 +1151,17 @@ Note that you only need to load a file using a `mod` declaration *once* in your
module tree. Once the compiler knows the file is part of the project (and knows
where in the module tree the code resides because of where you’ve put the `mod`
statement), other files in your project should refer to the loaded file’s code
-using a path to where it was declared, as covered in the “Paths for Referring
-to an Item in the Module Tree” section. In other words, `mod` is *not* an
+using a path to where it was declared, as covered in “Paths for Referring to an
+Item in the Module Tree” on page XX. In other words, `mod` is *not* an
“include” operation that you may have seen in other programming languages.
-Next, we’ll extract the `hosting` module to its own file. The process
-is a bit different because `hosting` is a child module of `front_of_house`, not
-of the root module. We’ll place the file for `hosting` in a new directory that
-will be named for its ancestors in the module tree, in this case
-*src/front_of_house/*.
+Next, we’ll extract the `hosting` module to its own file. The process is a bit
+different because `hosting` is a child module of `front_of_house`, not of the
+root module. We’ll place the file for `hosting` in a new directory that will be
+named for its ancestors in the module tree, in this case *src/front_of_house*.
-To start moving `hosting`, we change *src/front_of_house.rs* to contain only the
-declaration of the `hosting` module:
+To start moving `hosting`, we change *src/front_of_house.rs* to contain only
+the declaration of the `hosting` module:
Filename: src/front_of_house.rs
@@ -1264,7 +1169,7 @@ Filename: src/front_of_house.rs
pub mod hosting;
```
-Then we create a *src/front_of_house* directory and a file *hosting.rs* to
+Then we create a *src/front_of_house* directory and a *hosting.rs* file to
contain the definitions made in the `hosting` module:
Filename: src/front_of_house/hosting.rs
@@ -1275,34 +1180,33 @@ pub fn add_to_waitlist() {}
If we instead put *hosting.rs* in the *src* directory, the compiler would
expect the *hosting.rs* code to be in a `hosting` module declared in the crate
-root, and not delcared as a child of the `front_of_house` module. The
-compiler’s rules for which files to check for which modules’ code means the
+root, and not declared as a child of the `front_of_house` module. The
+compiler’s rules for which files to check for which modules’ code mean the
directories and files more closely match the module tree.
-
> ### Alternate File Paths
>
> So far we’ve covered the most idiomatic file paths the Rust compiler uses,
-> but Rust also supports an older style of file path. For a module named
-> `front_of_house` declared in the crate root, the compiler will look for the
-> module’s code in:
+but Rust also supports an older style of file path. For a module named
+`front_of_house` declared in the crate root, the compiler will look for the
+module’s code in:
>
> * *src/front_of_house.rs* (what we covered)
> * *src/front_of_house/mod.rs* (older style, still supported path)
>
> For a module named `hosting` that is a submodule of `front_of_house`, the
-> compiler will look for the module’s code in:
+compiler will look for the module’s code in:
>
> * *src/front_of_house/hosting.rs* (what we covered)
> * *src/front_of_house/hosting/mod.rs* (older style, still supported path)
>
-> If you use both styles for the same module, you’ll get a compiler error. Using
-> a mix of both styles for different modules in the same project is allowed, but
-> might be confusing for people navigating your project.
+> If you use both styles for the same module, you’ll get a compiler error.
+Using a mix of both styles for different modules in the same project is
+allowed, but might be confusing for people navigating your project.
>
> The main downside to the style that uses files named *mod.rs* is that your
-> project can end up with many files named *mod.rs*, which can get confusing
-> when you have them open in your editor at the same time.
+project can end up with many files named *mod.rs*, which can get confusing when
+you have them open in your editor at the same time.
We’ve moved each module’s code to a separate file, and the module tree remains
the same. The function calls in `eat_at_restaurant` will work without any
@@ -1317,8 +1221,8 @@ that module.
## Summary
-Rust lets you split a package into multiple crates and a crate into modules
-so you can refer to items defined in one module from another module. You can do
+Rust lets you split a package into multiple crates and a crate into modules so
+you can refer to items defined in one module from another module. You can do
this by specifying absolute or relative paths. These paths can be brought into
scope with a `use` statement so you can use a shorter path for multiple uses of
the item in that scope. Module code is private by default, but you can make
@@ -1326,3 +1230,4 @@ definitions public by adding the `pub` keyword.
In the next chapter, we’ll look at some collection data structures in the
standard library that you can use in your neatly organized code.
+
diff --git a/src/doc/book/nostarch/chapter08.md b/src/doc/book/nostarch/chapter08.md
index 1c7968c99..c44ebd8f7 100644
--- a/src/doc/book/nostarch/chapter08.md
+++ b/src/doc/book/nostarch/chapter08.md
@@ -20,9 +20,9 @@ collections that are used very often in Rust programs:
* A *vector* allows you to store a variable number of values next to each other.
* A *string* is a collection of characters. We’ve mentioned the `String` type
- previously, but in this chapter we’ll talk about it in depth.
-* A *hash map* allows you to associate a value with a particular key. It’s a
- particular implementation of the more general data structure called a *map*.
+previously, but in this chapter we’ll talk about it in depth.
+* A *hash map* allows you to associate a value with a specific key. It’s a
+particular implementation of the more general data structure called a *map*.
To learn about the other kinds of collections provided by the standard library,
see the documentation at *https://doc.rust-lang.org/std/collections/index.html*.
@@ -63,8 +63,8 @@ the type of value you want to store, so you rarely need to do this type
annotation. Rust conveniently provides the `vec!` macro, which will create a
new vector that holds the values you give it. Listing 8-2 creates a new
`Vec<i32>` that holds the values `1`, `2`, and `3`. The integer type is `i32`
-because that’s the default integer type, as we discussed in the “Data Types”
-section of Chapter 3.
+because that’s the default integer type, as we discussed in “Data Types” on
+page XX.
```
let v = vec![1, 2, 3];
@@ -97,26 +97,9 @@ make it mutable using the `mut` keyword, as discussed in Chapter 3. The numbers
we place inside are all of type `i32`, and Rust infers this from the data, so
we don’t need the `Vec<i32>` annotation.
-<!--
-I think people from other languages may get stuck a bit here because this is
-the first time (I think?) that we're showing a hindley-milner style type
-inference in action (rather than using the initializer to infer the type).
-
-Should we show the definition for `push`? That'd let us tie together the method
-call, mutable reference to self drawing on the `impl` we saw in earlier
-chapters and help to explain a little why the above works without having to
-annotate the type of the Vec.
-/JT --->
-<!-- I think readers would be more confused showing the definition of `push`
-here because we haven't covered generics yet. I haven't gotten comments about
-people being confused at this point (which doesn't mean they aren't), but
-personally when I learned this, it made sense to me that the type of the vector
-would be known from what I put in it. I'm leaning towards not elaborating here.
-/Carol -->
-
### Reading Elements of Vectors
-There are two ways to reference a value stored in a vector: via indexing or
+There are two ways to reference a value stored in a vector: via indexing or by
using the `get` method. In the following examples, we’ve annotated the types of
the values that are returned from these functions for extra clarity.
@@ -126,18 +109,18 @@ syntax and the `get` method.
```
let v = vec![1, 2, 3, 4, 5];
-[1] let third: &i32 = &v[2];
-println!("The third element is {}", third);
+1 let third: &i32 = &v[2];
+println!("The third element is {third}");
-[2] let third: Option<&i32> = v.get(2);
+2 let third: Option<&i32> = v.get(2);
match third {
- Some(third) => println!("The third element is {}", third),
+ Some(third) => println!("The third element is {third}"),
None => println!("There is no third element."),
}
```
-Listing 8-4: Using indexing syntax or the `get` method to access an item in a
-vector
+Listing 8-4: Using indexing syntax and using the `get` method to access an item
+in a vector
Note a few details here. We use the index value of `2` to get the third element
[1] because vectors are indexed by number, starting at zero. Using `&` and `[]`
@@ -145,18 +128,11 @@ gives us a reference to the element at the index value. When we use the `get`
method with the index passed as an argument [2], we get an `Option<&T>` that we
can use with `match`.
-<!---
-I think it should be "Second, we get the third element by using both `&` and
-`[]`"
-/JT --->
-<!-- No, it shouldn't, but I reworded this whole paragraph and added wingdings
-because it was unclear /Carol -->
-
-The reason Rust provides these two ways to reference an element is so you can
-choose how the program behaves when you try to use an index value outside the
-range of existing elements. As an example, let’s see what happens when we have
-a vector of five elements and then we try to access an element at index 100
-with each technique, as shown in Listing 8-5.
+Rust provides these two ways to reference an element so you can choose how the
+program behaves when you try to use an index value outside the range of
+existing elements. As an example, let’s see what happens when we have a vector
+of five elements and then we try to access an element at index 100 with each
+technique, as shown in Listing 8-5.
```
let v = vec![1, 2, 3, 4, 5];
@@ -191,7 +167,7 @@ rule that states you can’t have mutable and immutable references in the same
scope. That rule applies in Listing 8-6, where we hold an immutable reference
to the first element in a vector and try to add an element to the end. This
program won’t work if we also try to refer to that element later in the
-function:
+function.
```
let mut v = vec![1, 2, 3, 4, 5];
@@ -200,7 +176,7 @@ let first = &v[0];
v.push(6);
-println!("The first element is: {}", first);
+println!("The first element is: {first}");
```
Listing 8-6: Attempting to add an element to a vector while holding a reference
@@ -209,6 +185,8 @@ to an item
Compiling this code will result in this error:
```
+error[E0502]: cannot borrow `v` as mutable because it is also borrowed as
+immutable
--> src/main.rs:6:5
|
4 | let first = &v[0];
@@ -217,8 +195,8 @@ Compiling this code will result in this error:
6 | v.push(6);
| ^^^^^^^^^ mutable borrow occurs here
7 |
-8 | println!("The first element is: {}", first);
- | ----- immutable borrow later used here
+8 | println!("The first element is: {first}");
+ | ----- immutable borrow later used here
```
The code in Listing 8-6 might look like it should work: why should a reference
@@ -232,9 +210,9 @@ pointing to deallocated memory. The borrowing rules prevent programs from
ending up in that situation.
> Note: For more on the implementation details of the `Vec<T>` type, see “The
-> Rustonomicon” at *https://doc.rust-lang.org/nomicon/vec/vec.html*.
+Rustonomicon” at *https://doc.rust-lang.org/nomicon/vec/vec.html*.
-### Iterating over the Values in a Vector
+### Iterating Over the Values in a Vector
To access each element in a vector in turn, we would iterate through all of the
elements rather than use indices to access one at a time. Listing 8-7 shows how
@@ -244,7 +222,7 @@ to use a `for` loop to get immutable references to each element in a vector of
```
let v = vec![100, 32, 57];
for i in &v {
- println!("{}", i);
+ println!("{i}");
}
```
@@ -265,10 +243,9 @@ for i in &mut v {
Listing 8-8: Iterating over mutable references to elements in a vector
To change the value that the mutable reference refers to, we have to use the
-`*` dereference operator to get to the value in `i` before we can use the
-`+=` operator. We’ll talk more about the dereference operator in the
-“Following the Pointer to the Value with the Dereference Operator”
-section of Chapter 15.
+`*` dereference operator to get to the value in `i` before we can use the `+=`
+operator. We’ll talk more about the dereference operator in “Following the
+Pointer to the Value” on page XX.
Iterating over a vector, whether immutably or mutably, is safe because of the
borrow checker’s rules. If we attempted to insert or remove items in the `for`
@@ -277,37 +254,13 @@ similar to the one we got with the code in Listing 8-6. The reference to the
vector that the `for` loop holds prevents simultaneous modification of the
whole vector.
-<!--
-Maybe worth a mention: the above use of the mutable reference while you iterate
-is perfectly safe because there's no changing that's happening to the vector
-that would invalidate the iterator. But, if you wanted to iterate the vector
-while also trying to remove or insert elements, you'd get an error. For example:
-
-```
-let mut v = vec![100, 32, 57];
-for i in &mut v {
- *i += 50;
- if *i > 100 {
- v.push(10); // <-- a second mutable reference is needed and will fail to compile
- }
-}
-```
-
-Things like this help Rust prevent some classic C++ issues where people didn't
-think about the implications of growing/shrinking a container while iterating
-over it.
-/JT --->
-<!-- I thought Listing 8-6 covered this, but I can see how driving home the
-connection with iteration as well is worthwhile so I added a paragraph just
-before this comment. Please check for clarity Liz! /Carol -->
-
### Using an Enum to Store Multiple Types
-Vectors can only store values that are the same type. This can be inconvenient;
-there are definitely use cases for needing to store a list of items of
-different types. Fortunately, the variants of an enum are defined under the
-same enum type, so when we need one type to represent elements of different
-types, we can define and use an enum!
+Vectors can only store values that are of the same type. This can be
+inconvenient; there are definitely use cases for needing to store a list of
+items of different types. Fortunately, the variants of an enum are defined
+under the same enum type, so when we need one type to represent elements of
+different types, we can define and use an enum!
For example, say we want to get values from a row in a spreadsheet in which
some of the columns in the row contain integers, some floating-point numbers,
@@ -330,8 +283,7 @@ let row = vec![
];
```
-Listing 8-9: Defining an `enum` to store values of different types in one
-vector
+Listing 8-9: Defining an `enum` to store values of different types in one vector
Rust needs to know what types will be in the vector at compile time so it knows
exactly how much memory on the heap will be needed to store each element. We
@@ -346,7 +298,7 @@ store in a vector, the enum technique won’t work. Instead, you can use a trait
object, which we’ll cover in Chapter 17.
Now that we’ve discussed some of the most common ways to use vectors, be sure
-to review the API documentation for all the many useful methods defined on
+to review the API documentation for all of the many useful methods defined on
`Vec<T>` by the standard library. For example, in addition to `push`, a `pop`
method removes and returns the last element.
@@ -372,19 +324,6 @@ valid.
Let’s move on to the next collection type: `String`!
-<!--
-nit: I think "meaning the integers it holds will be cleaned up" reads a little
-better
-
-nit #2: imho dropping isn't as imports when you start using vectors as reading
-elements from the vector. Is it better for training to mention it here, or
-would it be possible to move it later?
-/JT -->
-<!-- Took both nit suggestions-- reworded for nit #1 and moved this section to
-the end of the Vec section (and renumbered the listings) for nit #2. Liz,
-please check to make sure I didn't miss anything in the way the Vec section
-flows now! /Carol -->
-
## Storing UTF-8 Encoded Text with Strings
We talked about strings in Chapter 4, but we’ll look at them in more depth now.
@@ -420,22 +359,10 @@ of those types. Although this section is largely about `String`, both types are
used heavily in Rust’s standard library, and both `String` and string slices
are UTF-8 encoded.
-<!---
-I'm wondering if listing the above makes it a bit more cumbersome. In effect,
-out of gate we're saying there are a lot of different string types.
-
-But perhaps we could focus on String and &str here and let them learn about
-CString/CStr when doing FFI and OsString/OsStr when they work on paths?
-Basically, I'm wondering if we should cut down on the concept count and let
-them come across those alternate strings more naturally.
-/JT --->
-<!-- I'm ok with that! I removed the paragraph talking about the other, rarer
-string types. /Carol -->
-
### Creating a New String
Many of the same operations available with `Vec<T>` are available with `String`
-as well, because `String` is actually implemented as a wrapper around a vector
+as well because `String` is actually implemented as a wrapper around a vector
of bytes with some extra guarantees, restrictions, and capabilities. An example
of a function that works the same way with `Vec<T>` and `String` is the `new`
function to create an instance, shown in Listing 8-11.
@@ -446,9 +373,9 @@ let mut s = String::new();
Listing 8-11: Creating a new, empty `String`
-This line creates a new empty string called `s`, which we can then load data
-into. Often, we’ll have some initial data that we want to start the string
-with. For that, we use the `to_string` method, which is available on any type
+This line creates a new, empty string called `s`, into which we can then load
+data. Often, we’ll have some initial data with which we want to start the
+string. For that, we use the `to_string` method, which is available on any type
that implements the `Display` trait, as string literals do. Listing 8-12 shows
two examples.
@@ -467,7 +394,7 @@ literal
This code creates a string containing `initial contents`.
We can also use the function `String::from` to create a `String` from a string
-literal. The code in Listing 8-13 is equivalent to the code from Listing 8-12
+literal. The code in Listing 8-13 is equivalent to the code in Listing 8-12
that uses `to_string`.
```
@@ -480,7 +407,7 @@ string literal
Because strings are used for so many things, we can use many different generic
APIs for strings, providing us with a lot of options. Some of them can seem
redundant, but they all have their place! In this case, `String::from` and
-`to_string` do the same thing, so which you choose is a matter of style and
+`to_string` do the same thing, so which one you choose is a matter of style and
readability.
Remember that strings are UTF-8 encoded, so we can include any properly encoded
@@ -510,7 +437,7 @@ A `String` can grow in size and its contents can change, just like the contents
of a `Vec<T>`, if you push more data into it. In addition, you can conveniently
use the `+` operator or the `format!` macro to concatenate `String` values.
-#### Appending to a String with `push_str` and `push`
+#### Appending to a String with push_str and push
We can grow a `String` by using the `push_str` method to append a string slice,
as shown in Listing 8-15.
@@ -531,7 +458,7 @@ parameter. For example, in the code in Listing 8-16, we want to be able to use
let mut s1 = String::from("foo");
let s2 = "bar";
s1.push_str(s2);
-println!("s2 is {}", s2);
+println!("s2 is {s2}");
```
Listing 8-16: Using a string slice after appending its contents to a `String`
@@ -540,7 +467,7 @@ If the `push_str` method took ownership of `s2`, we wouldn’t be able to print
its value on the last line. However, this code works as we’d expect!
The `push` method takes a single character as a parameter and adds it to the
-`String`. Listing 8-17 adds the letter "l" to a `String` using the `push`
+`String`. Listing 8-17 adds the letter *l* to a `String` using the `push`
method.
```
@@ -552,7 +479,7 @@ Listing 8-17: Adding one character to a `String` value using `push`
As a result, `s` will contain `lol`.
-#### Concatenation with the `+` Operator or the `format!` Macro
+#### Concatenation with the + Operator or the format! Macro
Often, you’ll want to combine two existing strings. One way to do so is to use
the `+` operator, as shown in Listing 8-18.
@@ -579,8 +506,8 @@ fn add(self, s: &str) -> String {
In the standard library, you’ll see `add` defined using generics and associated
types. Here, we’ve substituted in concrete types, which is what happens when we
call this method with `String` values. We’ll discuss generics in Chapter 10.
-This signature gives us the clues we need to understand the tricky bits of the
-`+` operator.
+This signature gives us the clues we need in order to understand the tricky
+bits of the `+` operator.
First, `s2` has an `&`, meaning that we’re adding a *reference* of the second
string to the first string. This is because of the `s` parameter in the `add`
@@ -588,29 +515,6 @@ function: we can only add a `&str` to a `String`; we can’t add two `String`
values together. But wait—the type of `&s2` is `&String`, not `&str`, as
specified in the second parameter to `add`. So why does Listing 8-18 compile?
-<!--
-The above isn't quite right - the trait for ops::Add uses an Rhs associated type
-instead of using T for both lhs and rhs.
-
-```
-pub trait Add<Rhs = Self> {
- type Output;
- fn add(self, rhs: Rhs) -> Self::Output;
-}
-```
-
-The implementation of Add for String fills in Rhs with the slice:
-
-```
-impl<'_> Add<&'_ str> for String
-```
-
-Not sure if it's better to fix the description and not have deref coercion
-discussion following, or fix the example so you can have the coercion
-discussion.
-/JT --->
-<!-- I've made an edit above to address this /Carol -->
-
The reason we’re able to use `&s2` in the call to `add` is that the compiler
can *coerce* the `&String` argument into a `&str`. When we call the `add`
method, Rust uses a *deref coercion*, which here turns `&s2` into `&s2[..]`.
@@ -618,13 +522,13 @@ We’ll discuss deref coercion in more depth in Chapter 15. Because `add` does
not take ownership of the `s` parameter, `s2` will still be a valid `String`
after this operation.
-Second, we can see in the signature that `add` takes ownership of `self`,
+Second, we can see in the signature that `add` takes ownership of `self`
because `self` does *not* have an `&`. This means `s1` in Listing 8-18 will be
-moved into the `add` call and will no longer be valid after that. So although
+moved into the `add` call and will no longer be valid after that. So, although
`let s3 = s1 + &s2;` looks like it will copy both strings and create a new one,
this statement actually takes ownership of `s1`, appends a copy of the contents
of `s2`, and then returns ownership of the result. In other words, it looks
-like it’s making a lot of copies but isn’t; the implementation is more
+like it’s making a lot of copies, but it isn’t; the implementation is more
efficient than copying.
If we need to concatenate multiple strings, the behavior of the `+` operator
@@ -639,15 +543,15 @@ let s = s1 + "-" + &s2 + "-" + &s3;
```
At this point, `s` will be `tic-tac-toe`. With all of the `+` and `"`
-characters, it’s difficult to see what’s going on. For more complicated string
-combining, we can instead use the `format!` macro:
+characters, it’s difficult to see what’s going on. For combining strings in
+more complicated ways, we can instead use the `format!` macro:
```
let s1 = String::from("tic");
let s2 = String::from("tac");
let s3 = String::from("toe");
-let s = format!("{}-{}-{}", s1, s2, s3);
+let s = format!("{s1}-{s2}-{s3}");
```
This code also sets `s` to `tic-tac-toe`. The `format!` macro works like
@@ -668,7 +572,7 @@ let s1 = String::from("hello");
let h = s1[0];
```
-Listing 8-19: Attempting to use indexing syntax with a String
+Listing 8-19: Attempting to use indexing syntax with a `String`
This code will result in the following error:
@@ -679,7 +583,8 @@ error[E0277]: the type `String` cannot be indexed by `{integer}`
3 | let h = s1[0];
| ^^^^^ `String` cannot be indexed by `{integer}`
|
- = help: the trait `Index<{integer}>` is not implemented for `String`
+ = help: the trait `Index<{integer}>` is not implemented for
+`String`
```
The error and the note tell the story: Rust strings don’t support indexing. But
@@ -695,20 +600,21 @@ encoded UTF-8 example strings from Listing 8-14. First, this one:
let hello = String::from("Hola");
```
-In this case, `len` will be 4, which means the vector storing the string “Hola”
-is 4 bytes long. Each of these letters takes 1 byte when encoded in UTF-8. The
-following line, however, may surprise you. (Note that this string begins with
-the capital Cyrillic letter Ze, not the Arabic number 3.)
+In this case, `len` will be `4`, which means the vector storing the string
+`"Hola"` is 4 bytes long. Each of these letters takes one byte when encoded in
+UTF-8. The following line, however, may surprise you (note that this string
+begins with the capital Cyrillic letter *Ze*, not the Arabic number 3):
```
let hello = String::from("Здравствуйте");
```
-Asked how long the string is, you might say 12. In fact, Rust’s answer is 24:
-that’s the number of bytes it takes to encode “Здравствуйте” in UTF-8, because
-each Unicode scalar value in that string takes 2 bytes of storage. Therefore,
-an index into the string’s bytes will not always correlate to a valid Unicode
-scalar value. To demonstrate, consider this invalid Rust code:
+If you were asked how long the string is, you might say 12. In fact, Rust’s
+answer is 24: that’s the number of bytes it takes to encode “Здравствуйте” in
+UTF-8, because each Unicode scalar value in that string takes 2 bytes of
+storage. Therefore, an index into the string’s bytes will not always correlate
+to a valid Unicode scalar value. To demonstrate, consider this invalid Rust
+code:
```
let hello = "Здравствуйте";
@@ -738,8 +644,8 @@ If we look at the Hindi word “नमस्ते” written in the Devanagari
stored as a vector of `u8` values that looks like this:
```
-[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164,
-224, 165, 135]
+[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224,
+164, 164, 224, 165, 135]
```
That’s 18 bytes and is how computers ultimately store this data. If we look at
@@ -785,8 +691,8 @@ let hello = "Здравствуйте";
let s = &hello[0..4];
```
-Here, `s` will be a `&str` that contains the first 4 bytes of the string.
-Earlier, we mentioned that each of these characters was 2 bytes, which means
+Here, `s` will be a `&str` that contains the first four bytes of the string.
+Earlier, we mentioned that each of these characters was two bytes, which means
`s` will be `Зд`.
If we were to try to slice only part of a character’s bytes with something like
@@ -794,55 +700,29 @@ If we were to try to slice only part of a character’s bytes with something lik
index were accessed in a vector:
```
-thread 'main' panicked at 'byte index 1 is not a char boundary; it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/main.rs:4:14
+thread 'main' panicked at 'byte index 1 is not a char boundary;
+it is inside 'З' (bytes 0..2) of `Здравствуйте`', src/main.rs:4:14
```
-You should use ranges to create string slices with caution, because doing so
-can crash your program.
+You should use caution when creating string slices with ranges, because doing
+so can crash your program.
### Methods for Iterating Over Strings
-<!--- is there a reason this comes after how to slice, rather than after the
-discussion on why we can't directly index into a string? /LC --->
-<!-- I think the idea was that we show this progression of from worst technique
-to best:
-
-1. direct indexing, which doesn't compile
-2. slicing with a range, which looks similar to indexing, which does compile
-but might panic at runtime
-3. iterating over chars or bytes, which compiles and won't panic
-
-Do you have suggestions on making this clearer? I've tried to add a bit at the
-beginning of this section /Carol
--->
-<!-- JT, what do you think -- is this ordering clear to you? /LC -->
-<!---
-I'm okay with the current order - I think showing why it's bad, what's close to
-what you try first, and then finally the idiomatic Rust solution reads okay.
-
-One tiny nit, for flow, would be to use the Cyrillic example first here to show
-how `.chars()` works well for it and then mention that for more complex
-scripts, like Hindi, you'll need to use the more full-featured string handling
-you find on crates.io.
-/JT --->
-<!-- I've taken JT's suggestion here to use part of the Cyrillic string, then
-mention you'll need a crate to correctly get the grapheme clusters for Hindi
-/Carol -->
-
The best way to operate on pieces of strings is to be explicit about whether
you want characters or bytes. For individual Unicode scalar values, use the
-`chars` method. Calling `chars` on “Зд” separates out and returns two values
-of type `char`, and you can iterate over the result to access each element:
+`chars` method. Calling `chars` on “Зд” separates out and returns two values of
+type `char`, and you can iterate over the result to access each element:
-```rust
+```
for c in "Зд".chars() {
- println!("{}", c);
+ println!("{c}");
}
```
This code will print the following:
-```text
+```
З
д
```
@@ -850,15 +730,15 @@ This code will print the following:
Alternatively, the `bytes` method returns each raw byte, which might be
appropriate for your domain:
-```rust
+```
for b in "Зд".bytes() {
- println!("{}", b);
+ println!("{b}");
}
```
This code will print the four bytes that make up this string:
-```text
+```
208
151
208
@@ -866,41 +746,19 @@ This code will print the four bytes that make up this string:
```
But be sure to remember that valid Unicode scalar values may be made up of more
-than 1 byte.
+than one byte.
-Getting grapheme clusters from strings as with the Devanagari script is
+Getting grapheme clusters from strings, as with the Devanagari script, is
complex, so this functionality is not provided by the standard library. Crates
-are available on *https://crates.io/* if this is the functionality you need.
+are available at *https://crates.io* if this is the functionality you need.
### Strings Are Not So Simple
-<!---
-Because Strings are quite complicated, and have complications that are all
-their own and unlike any other containers, I wonder if maybe this chapter
-should be two different chapters with one specifically being about strings,
-string slices, chars, and related?
-/JT --->
-<!-- I don't think I want to make that big of a change at this point... the
-original idea was to compare and contrast the different containers, perhaps
-that's not serving its purpose as well as a chapter split could... I'll think
-about this for the next major revision. /Carol -->
-
-<!---
-We don't talk about searching in a string. Feels like it could use an example
-or two?
-/JT --->
-<!-- To address this suggestion and a bit of the previous suggestion as well, I
-changed the first paragraph in the "Creating a New String" section to mention
-that a `String` is implemented using a `Vec`. Then, to echo the last paragraph
-before the "Dropping a Vector Drops Its Elements" section, I've added some text
-here to again urge the reader to check out the standard library documentation
-for more functionality. /Carol -->
-
To summarize, strings are complicated. Different programming languages make
different choices about how to present this complexity to the programmer. Rust
has chosen to make the correct handling of `String` data the default behavior
for all Rust programs, which means programmers have to put more thought into
-handling UTF-8 data upfront. This trade-off exposes more of the complexity of
+handling UTF-8 data up front. This trade-off exposes more of the complexity of
strings than is apparent in other programming languages, but it prevents you
from having to handle errors involving non-ASCII characters later in your
development life cycle.
@@ -916,11 +774,11 @@ Let’s switch to something a bit less complex: hash maps!
## Storing Keys with Associated Values in Hash Maps
The last of our common collections is the *hash map*. The type `HashMap<K, V>`
-stores a mapping of keys of type `K` to values of type `V` using a
-*hashing function*, which determines how it places these keys and values into
-memory. Many programming languages support this kind of data structure, but
-they often use a different name, such as hash, map, object, hash table,
-dictionary, or associative array, just to name a few.
+stores a mapping of keys of type `K` to values of type `V` using a *hashing
+function*, which determines how it places these keys and values into memory.
+Many programming languages support this kind of data structure, but they often
+use a different name, such as *hash*, *map*, *object*, *hash table*,
+*dictionary*, or *associative array*, just to name a few.
Hash maps are useful when you want to look up data not by using an index, as
you can with vectors, but by using a key that can be of any type. For example,
@@ -934,7 +792,7 @@ As always, check the standard library documentation for more information.
### Creating a New Hash Map
-One way to create an empty hash map is using `new` and adding elements with
+One way to create an empty hash map is to use `new` and to add elements with
`insert`. In Listing 8-20, we’re keeping track of the scores of two teams whose
names are *Blue* and *Yellow*. The Blue team starts with 10 points, and the
Yellow team starts with 50.
@@ -958,25 +816,11 @@ standard library; there’s no built-in macro to construct them, for example.
Just like vectors, hash maps store their data on the heap. This `HashMap` has
keys of type `String` and values of type `i32`. Like vectors, hash maps are
-homogeneous: all of the keys must have the same type as each other, and all of
-the values must have the same type.
-
-<!---
-I'm not sure I've seen this in the wild? I'm tempted to say to skip the zip
-example for flow and go from creating the hash map to working with its
-contents.
-/JT --->
-<!-- Cut Listing 8-21 and renumbered! /Carol -->
+homogeneous: all of the keys must have the same type, and all of the values
+must have the same type.
### Accessing Values in a Hash Map
-<!---
-For flow, would it make sense for this section to follow creating the hash map?
-That way we introduce a useful concept and also continue the teams example.
-/JT --->
-<!-- Ok, I've switched the order of "Accessing Values in a Hash Map" and "Hash
-Maps and Ownership" and renumbered! Does this still make sense Liz? /Carol -->
-
We can get a value out of the hash map by providing its key to the `get`
method, as shown in Listing 8-21.
@@ -989,7 +833,7 @@ scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
let team_name = String::from("Blue");
-let score = scores.get(&team_name).unwrap_or(0);
+let score = scores.get(&team_name).copied().unwrap_or(0);
```
Listing 8-21: Accessing the score for the Blue team stored in the hash map
@@ -997,17 +841,11 @@ Listing 8-21: Accessing the score for the Blue team stored in the hash map
Here, `score` will have the value that’s associated with the Blue team, and the
result will be `10`. The `get` method returns an `Option<&V>`; if there’s no
value for that key in the hash map, `get` will return `None`. This program
-handles the `Option` by calling `unwrap_or` to set `score` to zero if `scores`
-doesn’t have an entry for the key.
-
-<!---
-Should there be a quick example here to show handling Some/None again before
-we move on to iteration?
-/JT --->
-<!-- I've changed the code in Listing 8-21 a bit to actually handle the
-`Option` instead of referencing chapter 6, what do you think Liz? /Carol -->
+handles the `Option` by calling `copied` to get an `Option<i32>` rather than an
+`Option<&i32>`, then `unwrap_or` to set `score` to zero if `scores` doesn’t
+have an entry for the key.
-We can iterate over each key/value pair in a hash map in a similar manner as we
+We can iterate over each key–value pair in a hash map in a similar manner as we
do with vectors, using a `for` loop:
```
@@ -1019,7 +857,7 @@ scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);
for (key, value) in &scores {
- println!("{}: {}", key, value);
+ println!("{key}: {value}");
}
```
@@ -1044,8 +882,8 @@ let field_value = String::from("Blue");
let mut map = HashMap::new();
map.insert(field_name, field_value);
-// field_name and field_value are invalid at this point, try using them and
-// see what compiler error you get!
+// field_name and field_value are invalid at this point, try
+// using them and see what compiler error you get!
```
Listing 8-22: Showing that keys and values are owned by the hash map once
@@ -1057,40 +895,14 @@ they’ve been moved into the hash map with the call to `insert`.
If we insert references to values into the hash map, the values won’t be moved
into the hash map. The values that the references point to must be valid for at
least as long as the hash map is valid. We’ll talk more about these issues in
-the “Validating References with Lifetimes” section in Chapter 10.
+“Validating References with Lifetimes” on page XX.
### Updating a Hash Map
Although the number of key and value pairs is growable, each unique key can
only have one value associated with it at a time (but not vice versa: for
-example, both the Blue team and the Yellow team could have value 10 stored in
-the `scores` hash map).
-<!--- And vice versa? /LC --->
-<!-- No, you could have a hashmap that has ("Blue", 10) and ("Yellow", 10) for
-example. Stating this here feels a bit off topic for updating the value of an
-existing key, though, I'm not sure how to work it in. Do you think that's
-important enough to state here? If so, do you have suggestions on how to do it
-without distracting from the main point of this section? /Carol -->
-<!-- It may not be important enough, what do you think JT? /LC -->
-<!---
-I think it's maybe worth calling out. Something you could use to drive
-this home is the `.entry()` call. This makes it clear that for any key there's
-one cell (or entry) that you're updating in the hash map. I see we use it
-later, though worth a thought if bringing it earlier helps?
-/JT --->
-<!-- I've added a short sentence here, but every time I try to add something
-more, I end up getting tangled in saying things like "key value" as opposed to
-"value value", which is terrible... or I worry about misleading readers into
-thinking that you can't use a `Vec<T>` as a HashMap value type, which you
-totally can to store multiple "values" in one vector "value", which you totally
-can, it's just a little more complicated. Or I try to say "multiple keys can
-have the same value" which sounds like it could imply that there would be a
-*shared* value stored in the HashMap, which wouldn't be the case, there would
-be two separate allocations that would happen to have the same value... I just
-haven't heard a reader wondering if each value can only have one key with it
-before (which doesn't mean they haven't wondered it, I just haven't heard of
-it) so I don't want to lead readers astray if they weren't already going that
-direction? What do you think about what's here now, Liz? /Carol -->
+example, both the Blue team and the Yellow team could have the value `10`
+stored in the `scores` hash map).
When you want to change the data in a hash map, you have to decide how to
handle the case when a key already has a value assigned. You could replace the
@@ -1104,7 +916,7 @@ new value. Let’s look at how to do each of these!
If we insert a key and a value into a hash map and then insert that same key
with a different value, the value associated with that key will be replaced.
Even though the code in Listing 8-23 calls `insert` twice, the hash map will
-only contain one key/value pair because we’re inserting the value for the Blue
+only contain one key–value pair because we’re inserting the value for the Blue
team’s key both times.
```
@@ -1125,47 +937,16 @@ overwritten.
#### Adding a Key and Value Only If a Key Isn’t Present
-<!--- to be clear, are we talking about default values here, or just checking
-for an existing value before allowing insertion of a value? /LC--->
-<!-- I'm not sure what you mean exactly. Checking for an existing value before
-allowing insertion of a value can be used to insert whatever value would mean
-"default" in your program, or it can be used to insert some other value that
-you wouldn't call a default. That is, in Listing 8-25, would you call 50 a
-default value or no? (I don't think we've given enough information about what
-the program is ultimately trying to do to tell if 50 is a default or not, and I
-don't think it matters, but I am interested to know if there's something I'm
-missing that you're trying to get at). Can you elaborate on what was confusing
-and perhaps propose wording that would have cleared this up for you, and I can
-fix if needed? /Carol-->
-<!-- I suppose what I'm asking is whether a value is inserted from the started
-as a default value and then updated, meaning the key never has no value, or
-whether we're only allowing insertion of a value if there isn't already a
-value. I think it's the latter and maybe that's clear enough as is! JT, what do
-you think? /LC -->
-<!---
-I think the idea is generally right, we're going to insert the value if the
-key is not already in the hash map. Maybe the title could be:
-
-"Adding a key and value only if a key isn't present"
-
-Worth a note: I think "default" values are a bit of a loaded term in Rust. If
-we use it, we may confuse people later if we they come across `Default`, which
-is the default value of a type (like 0 is for i64, via `i64::default()`)
-/JT --->
-<!-- Ok, I've taken JT's suggestion for the section title and tried to reword
-the text here a bit; is this clearer, Liz? I share JT's concern about using the
-word "default"... /Carol -->
-
It’s common to check whether a particular key already exists in the hash map
-with a value then take the following actions: if the key does exist in the hash
-map, the existing value should remain the way it is. If the key doesn’t exist,
-insert it and a value for it.
+with a value and then to take the following actions: if the key does exist in
+the hash map, the existing value should remain the way it is; if the key
+doesn’t exist, insert it and a value for it.
Hash maps have a special API for this called `entry` that takes the key you
want to check as a parameter. The return value of the `entry` method is an enum
called `Entry` that represents a value that might or might not exist. Let’s say
we want to check whether the key for the Yellow team has a value associated
-with it. If it doesn’t, we want to insert the value 50, and the same for the
+with it. If it doesn’t, we want to insert the value `50`, and the same for the
Blue team. Using the `entry` API, the code looks like Listing 8-24.
```
@@ -1184,16 +965,16 @@ Listing 8-24: Using the `entry` method to only insert if the key does not
already have a value
The `or_insert` method on `Entry` is defined to return a mutable reference to
-the value for the corresponding `Entry` key if that key exists, and if not,
+the value for the corresponding `Entry` key if that key exists, and if not, it
inserts the parameter as the new value for this key and returns a mutable
reference to the new value. This technique is much cleaner than writing the
logic ourselves and, in addition, plays more nicely with the borrow checker.
Running the code in Listing 8-24 will print `{"Yellow": 50, "Blue": 10}`. The
first call to `entry` will insert the key for the Yellow team with the value
-50 because the Yellow team doesn’t have a value already. The second call to
+`50` because the Yellow team doesn’t have a value already. The second call to
`entry` will not change the hash map because the Blue team already has the
-value 10.
+value `10`.
#### Updating a Value Based on the Old Value
@@ -1202,7 +983,7 @@ update it based on the old value. For instance, Listing 8-25 shows code that
counts how many times each word appears in some text. We use a hash map with
the words as keys and increment the value to keep track of how many times we’ve
seen that word. If it’s the first time we’ve seen a word, we’ll first insert
-the value 0.
+the value `0`.
```
use std::collections::HashMap;
@@ -1223,37 +1004,29 @@ Listing 8-25: Counting occurrences of words using a hash map that stores words
and counts
This code will print `{"world": 2, "hello": 1, "wonderful": 1}`. You might see
-the same key/value pairs printed in a different order: recall from the
-“Accessing Values in a Hash Map” section that iterating over a hash map happens
-in an arbitrary order.
+the same key–value pairs printed in a different order: recall from “Accessing
+Values in a Hash Map” on page XX that iterating over a hash map happens in an
+arbitrary order.
-The `split_whitespace` method returns an iterator over sub-slices, separated by
+The `split_whitespace` method returns an iterator over subslices, separated by
whitespace, of the value in `text`. The `or_insert` method returns a mutable
-reference (`&mut V`) to the value for the specified key. Here we store that
+reference (`&mut V`) to the value for the specified key. Here, we store that
mutable reference in the `count` variable, so in order to assign to that value,
we must first dereference `count` using the asterisk (`*`). The mutable
reference goes out of scope at the end of the `for` loop, so all of these
changes are safe and allowed by the borrowing rules.
-<!---
-Running the above gave me `{"world": 2, "wonderful": 1, "hello": 1}` so the key
-order may not be deterministic or may change based on changes to the hashing
-function in the std lib.
-/JT --->
-<!-- I've added a note that getting a different order is perfectly normal
-/Carol -->
-
### Hashing Functions
By default, `HashMap` uses a hashing function called *SipHash* that can provide
-resistance to Denial of Service (DoS) attacks involving hash tables. This is
+resistance to denial-of-service (DoS) attacks involving hash tables. This is
not the fastest hashing algorithm available, but the trade-off for better
security that comes with the drop in performance is worth it. If you profile
your code and find that the default hash function is too slow for your
purposes, you can switch to another function by specifying a different hasher.
A *hasher* is a type that implements the `BuildHasher` trait. We’ll talk about
traits and how to implement them in Chapter 10. You don’t necessarily have to
-implement your own hasher from scratch; *https://crates.io/* has libraries
+implement your own hasher from scratch; *https://crates.io* has libraries
shared by other Rust users that provide hashers implementing many common
hashing algorithms.
@@ -1263,22 +1036,22 @@ Vectors, strings, and hash maps will provide a large amount of functionality
necessary in programs when you need to store, access, and modify data. Here are
some exercises you should now be equipped to solve:
-* Given a list of integers, use a vector and return the median (when sorted,
- the value in the middle position) and mode (the value that occurs most often;
- a hash map will be helpful here) of the list.
-* Convert strings to pig latin. The first consonant of each word is moved to
- the end of the word and “ay” is added, so “first” becomes “irst-fay.” Words
- that start with a vowel have “hay” added to the end instead (“apple” becomes
- “apple-hay”). Keep in mind the details about UTF-8 encoding!
-* Using a hash map and vectors, create a text interface to allow a user to add
- employee names to a department in a company. For example, “Add Sally to
- Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all
- people in a department or all people in the company by department, sorted
- alphabetically.
+1. Given a list of integers, use a vector and return the median (when sorted,
+the value in the middle position) and mode (the value that occurs most often; a
+hash map will be helpful here) of the list.
+1. Convert strings to pig latin. The first consonant of each word is moved to
+the end of the word and *ay* is added, so *first* becomes *irst-fay*. Words
+that start with a vowel have *hay* added to the end instead (*apple* becomes
+*apple-hay*). Keep in mind the details about UTF-8 encoding!
+1. Using a hash map and vectors, create a text interface to allow a user to add
+employee names to a department in a company; for example, “Add Sally to
+Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all
+people in a department or all people in the company by department, sorted
+alphabetically.
The standard library API documentation describes methods that vectors, strings,
and hash maps have that will be helpful for these exercises!
-We’re getting into more complex programs in which operations can fail, so, it’s
+We’re getting into more complex programs in which operations can fail, so it’s
a perfect time to discuss error handling. We’ll do that next!
diff --git a/src/doc/book/nostarch/chapter09.md b/src/doc/book/nostarch/chapter09.md
index 693dc1be0..4aa81123f 100644
--- a/src/doc/book/nostarch/chapter09.md
+++ b/src/doc/book/nostarch/chapter09.md
@@ -18,7 +18,7 @@ deployed your code to production!
Rust groups errors into two major categories: *recoverable* and *unrecoverable*
errors. For a recoverable error, such as a *file not found* error, we most
likely just want to report the problem to the user and retry the operation.
-Unrecoverable errors are always symptoms of bugs, like trying to access a
+Unrecoverable errors are always symptoms of bugs, such as trying to access a
location beyond the end of an array, and so we want to immediately stop the
program.
@@ -31,9 +31,9 @@ about returning `Result<T, E>` values. Additionally, we’ll explore
considerations when deciding whether to try to recover from an error or to stop
execution.
-## Unrecoverable Errors with `panic!`
+## Unrecoverable Errors with panic!
-Sometimes, bad things happen in your code, and there’s nothing you can do about
+Sometimes bad things happen in your code, and there’s nothing you can do about
it. In these cases, Rust has the `panic!` macro. There are two ways to cause a
panic in practice: by taking an action that causes our code to panic (such as
accessing an array past the end) or by explicitly calling the `panic!` macro.
@@ -42,39 +42,22 @@ print a failure message, unwind, clean up the stack, and quit. Via an
environment variable, you can also have Rust display the call stack when a
panic occurs to make it easier to track down the source of the panic.
-<!-- does Rust invoke the panic, or do we? Or sometimes it can be either? /LC --->
-<!-- We will have done *something* through a combination of the code we've
-written and the data the program gets at runtime. It *might* involve us
-literally typing `panic!` into our code, or it might be part of Rust that we're
-using that calls `panic!` for us because of something else we've done. Does
-that make sense? I've tried to clarify the last sentence a bit here /Carol -->
-<!---
-One way we could explain it is to say there are two ways to cause a panic in
-practice: by doing an action that causes our code to panic, like accessing an
-array past the end or dividing by zero, or by explicitly calling the `panic!`
-macro. In both cases, we cause a panic in our application. By default, these
-panics will unwind and clean up the stack. Via an environment setting, you can
-also have Rust display the call stack when a panic occurs to make it easier to
-track down the source of the panic.
-/JT --->
-<!-- I've taken JT's suggestion with some edits in the paragraph above /Carol
--->
> ### Unwinding the Stack or Aborting in Response to a Panic
>
-> By default, when a panic occurs, the program starts *unwinding*, which
-> means Rust walks back up the stack and cleans up the data from each function
-> it encounters. However, this walking back and cleanup is a lot of work. Rust,
-> therefore, allows you to choose the alternative of immediately *aborting*,
-> which ends the program without cleaning up.
+> By default, when a panic occurs the program starts *unwinding*, which means
+Rust walks back up the stack and cleans up the data from each function it
+encounters. However, walking back and cleaning up is a lot of work. Rust,
+therefore, allows you to choose the alternative of immediately *aborting*,
+which ends the program without cleaning up.
>
-> Memory that the program was using will then need to be cleaned
-> up by the operating system. If in your project you need to make the resulting
-> binary as small as possible, you can switch from unwinding to aborting upon a
-> panic by adding `panic = 'abort'` to the appropriate `[profile]` sections in
-> your *Cargo.toml* file. For example, if you want to abort on panic in release
-> mode, add this:
+> Memory that the program was using will then need to be cleaned up by the
+operating system. If in your project you need to make the resultant binary as
+small as possible, you can switch from unwinding to aborting upon a panic by
+adding `panic = 'abort'` to the appropriate `[profile]` sections in your
+*Cargo.toml* file. For example, if you want to abort on panic in release mode,
+add this:
>
-> ```toml
+> ```
> [profile.release]
> panic = 'abort'
> ```
@@ -93,7 +76,8 @@ When you run the program, you’ll see something like this:
```
thread 'main' panicked at 'crash and burn', src/main.rs:2:5
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
```
The call to `panic!` causes the error message contained in the last two lines.
@@ -105,17 +89,14 @@ In this case, the line indicated is part of our code, and if we go to that
line, we see the `panic!` macro call. In other cases, the `panic!` call might
be in code that our code calls, and the filename and line number reported by
the error message will be someone else’s code where the `panic!` macro is
-called, not the line of our code that eventually led to the `panic!` call. We
-can use the backtrace of the functions the `panic!` call came from to figure
-out the part of our code that is causing the problem. We’ll discuss backtraces
-in more detail next.
-
-### Using a `panic!` Backtrace
+called, not the line of our code that eventually led to the `panic!` call.
-Let’s look at another example to see what it’s like when a `panic!` call comes
-from a library because of a bug in our code instead of from our code calling
-the macro directly. Listing 9-1 has some code that attempts to access an
-index in a vector beyond the range of valid indexes.
+We can use the backtrace of the functions the `panic!` call came from to figure
+out the part of our code that is causing the problem. To understand how to use
+a `panic!` backtrace, let’s look at another example and see what it’s like when
+a `panic!` call comes from a library because of a bug in our code instead of
+from our code calling the macro directly. Listing 9-1 has some code that
+attempts to access an index in a vector beyond the range of valid indexes.
Filename: src/main.rs
@@ -131,10 +112,10 @@ Listing 9-1: Attempting to access an element beyond the end of a vector, which
will cause a call to `panic!`
Here, we’re attempting to access the 100th element of our vector (which is at
-index 99 because indexing starts at zero), but the vector has only 3 elements.
-In this situation, Rust will panic. Using `[]` is supposed to return an
-element, but if you pass an invalid index, there’s no element that Rust could
-return here that would be correct.
+index 99 because indexing starts at zero), but the vector has only three
+elements. In this situation, Rust will panic. Using `[]` is supposed to return
+an element, but if you pass an invalid index, there’s no element that Rust
+could return here that would be correct.
In C, attempting to read beyond the end of a data structure is undefined
behavior. You might get whatever is at the location in memory that would
@@ -149,44 +130,55 @@ element at an index that doesn’t exist, Rust will stop execution and refuse to
continue. Let’s try it and see:
```
-thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
+thread 'main' panicked at 'index out of bounds: the len is 3 but the index is
+99', src/main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
-This error points at line 4 of our `main.rs` where we attempt to access index
-99. The next note line tells us that we can set the `RUST_BACKTRACE`
-environment variable to get a backtrace of exactly what happened to cause the
-error. A *backtrace* is a list of all the functions that have been called to
-get to this point. Backtraces in Rust work as they do in other languages: the
-key to reading the backtrace is to start from the top and read until you see
-files you wrote. That’s the spot where the problem originated. The lines above
-that spot are code that your code has called; the lines below are code that
-called your code. These before-and-after lines might include core Rust code,
-standard library code, or crates that you’re using. Let’s try getting a
-backtrace by setting the `RUST_BACKTRACE` environment variable to any value
-except 0. Listing 9-2 shows output similar to what you’ll see.
+This error points at line 4 of our *main.rs* where we attempt to access `index`.
+
+The `note:` line tells us that we can set the `RUST_BACKTRACE` environment
+variable to get a backtrace of exactly what happened to cause the error. A
+*backtrace* is a list of all the functions that have been called to get to this
+point. Backtraces in Rust work as they do in other languages: the key to
+reading the backtrace is to start from the top and read until you see files you
+wrote. That’s the spot where the problem originated. The lines above that spot
+are code that your code has called; the lines below are code that called your
+code. These before-and-after lines might include core Rust code, standard
+library code, or crates that you’re using. Let’s try getting a backtrace by
+setting the `RUST_BACKTRACE` environment variable to any value except `0`.
+Listing 9-2 shows output similar to what you’ll see.
```
$ RUST_BACKTRACE=1 cargo run
-thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
+thread 'main' panicked at 'index out of bounds: the len is 3 but the index is
+99', src/main.rs:4:5
stack backtrace:
0: rust_begin_unwind
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std
+/src/panicking.rs:584:5
1: core::panicking::panic_fmt
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core
+/src/panicking.rs:142:14
2: core::panicking::panic_bounds_check
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:62
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core
+/src/panicking.rs:84:5
3: <usize as core::slice::index::SliceIndex<[T]>>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:255
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core
+/src/slice/index.rs:242:10
4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:15
- 5: <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/alloc/src/vec.rs:1982
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core
+/src/slice/index.rs:18:9
+ 5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc
+/src/vec/mod.rs:2591:9
6: panic::main
- at ./src/main.rs:4
+ at ./src/main.rs:4:5
7: core::ops::function::FnOnce::call_once
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227
-note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core
+/src/ops/function.rs:248:5
+note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose
+backtrace.
```
Listing 9-2: The backtrace generated by a call to `panic!` displayed when the
@@ -208,21 +200,19 @@ panics in the future, you’ll need to figure out what action the code is taking
with what values to cause the panic and what the code should do instead.
We’ll come back to `panic!` and when we should and should not use `panic!` to
-handle error conditions in the “To `panic!` or Not to `panic!`” section later
-in this chapter. Next, we’ll look at how to recover from an error using
-`Result`.
+handle error conditions in “To panic! or Not to panic!” on page XX. Next, we’ll
+look at how to recover from an error using `Result`.
-## Recoverable Errors with `Result`
+## Recoverable Errors with Result
Most errors aren’t serious enough to require the program to stop entirely.
-Sometimes, when a function fails, it’s for a reason that you can easily
-interpret and respond to. For example, if you try to open a file and that
-operation fails because the file doesn’t exist, you might want to create the
-file instead of terminating the process.
+Sometimes when a function fails it’s for a reason that you can easily interpret
+and respond to. For example, if you try to open a file and that operation fails
+because the file doesn’t exist, you might want to create the file instead of
+terminating the process.
-Recall from “Handling Potential Failure with the `Result` Type” in Chapter 2
-that the `Result` enum is defined as having two variants, `Ok` and `Err`, as
-follows:
+Recall from “Handling Potential Failure with Result” on page XX that the
+`Result` enum is defined as having two variants, `Ok` and `Err`, as follows:
```
enum Result<T, E> {
@@ -237,7 +227,7 @@ the type of the value that will be returned in a success case within the `Ok`
variant, and `E` represents the type of the error that will be returned in a
failure case within the `Err` variant. Because `Result` has these generic type
parameters, we can use the `Result` type and the functions defined on it in
-many different situations where the successful value and error value we want to
+many different situations where the success value and error value we want to
return may differ.
Let’s call a function that returns a `Result` value because the function could
@@ -255,18 +245,6 @@ fn main() {
Listing 9-3: Opening a file
-<!---
-This brings up an interesting point - should we teach them to install
-rust-analyzer in the setup instructions? If so, then we can tell them to mouse
-over the name of what they want the typename of. The "assign something to i32 to
-have rustc tell you what it is" feels a bit like old style Rust.
-/JT --->
-<!-- I somewhat disagree here; not everyone uses IDE plugins. I'll see what JT
-says about mentioning rust-analyzer in chapter 1 rather than in the appendix...
-I am in favor of making the book shorter, though, so I've removed the parts
-about asking the compiler what the type of something is by deliberately
-annotating with the wrong type. /Carol -->
-
The return type of `File::open` is a `Result<T, E>`. The generic parameter `T`
has been filled in by the implementation of `File::open` with the type of the
success value, `std::fs::File`, which is a file handle. The type of `E` used in
@@ -282,7 +260,7 @@ In the case where `File::open` succeeds, the value in the variable
`greeting_file_result` will be an instance of `Ok` that contains a file handle.
In the case where it fails, the value in `greeting_file_result` will be an
instance of `Err` that contains more information about the kind of error that
-happened.
+occurred.
We need to add to the code in Listing 9-3 to take different actions depending
on the value `File::open` returns. Listing 9-4 shows one way to handle the
@@ -299,7 +277,9 @@ fn main() {
let greeting_file = match greeting_file_result {
Ok(file) => file,
- Err(error) => panic!("Problem opening the file: {:?}", error),
+ Err(error) => {
+ panic!("Problem opening the file: {:?}", error);
+ }
};
}
```
@@ -322,7 +302,9 @@ there’s no file named *hello.txt* in our current directory and we run this
code, we’ll see the following output from the `panic!` macro:
```
-thread 'main' panicked at 'Problem opening the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:8:23
+thread 'main' panicked at 'Problem opening the file: Os { code:
+ 2, kind: NotFound, message: "No such file or directory" }',
+src/main.rs:8:23
```
As usual, this output tells us exactly what has gone wrong.
@@ -330,11 +312,11 @@ As usual, this output tells us exactly what has gone wrong.
### Matching on Different Errors
The code in Listing 9-4 will `panic!` no matter why `File::open` failed.
-However, we want to take different actions for different failure reasons: if
+However, we want to take different actions for different failure reasons. If
`File::open` failed because the file doesn’t exist, we want to create the file
and return the handle to the new file. If `File::open` failed for any other
reason—for example, because we didn’t have permission to open the file—we still
-want the code to `panic!` in the same way as it did in Listing 9-4. For this we
+want the code to `panic!` in the same way it did in Listing 9-4. For this, we
add an inner `match` expression, shown in Listing 9-5.
Filename: src/main.rs
@@ -349,14 +331,22 @@ fn main() {
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => match error.kind() {
- ErrorKind::NotFound => match File::create("hello.txt") {
- Ok(fc) => fc,
- Err(e) => panic!("Problem creating the file: {:?}", e),
+ ErrorKind::NotFound => {
+ match File::create("hello.txt") {
+ Ok(fc) => fc,
+ Err(e) => panic!(
+ "Problem creating the file: {:?}",
+ e
+ ),
+ }
}
other_error => {
- panic!("Problem opening the file: {:?}", other_error);
+ panic!(
+ "Problem opening the file: {:?}",
+ other_error
+ );
}
- }
+ },
};
}
```
@@ -380,40 +370,41 @@ file can’t be created, a different error message is printed. The second arm of
the outer `match` stays the same, so the program panics on any error besides
the missing file error.
-> ### Alternatives to Using `match` with `Result<T, E>`
->
-> That’s a lot of `match`! The `match` expression is very useful but also very
-> much a primitive. In Chapter 13, you’ll learn about closures, which are used
-> with many of the methods defined on `Result<T, E>`. These methods can be more
-> concise than using `match` when handling `Result<T, E>` values in your code.
+#### Alternatives to Using match with Result<T, E>
-> For example, here’s another way to write the same logic as shown in Listing
-> 9-5, this time using closures and the `unwrap_or_else` method:
->
-> ```
-> use std::fs::File;
-> use std::io::ErrorKind;
->
-> fn main() {
-> let greeting_file = File::open("hello.txt").unwrap_or_else(|error| {
-> if error.kind() == ErrorKind::NotFound {
-> File::create("hello.txt").unwrap_or_else(|error| {
-> panic!("Problem creating the file: {:?}", error);
-> })
-> } else {
-> panic!("Problem opening the file: {:?}", error);
-> }
-> });
-> }
-> ```
->
-> Although this code has the same behavior as Listing 9-5, it doesn’t contain
-> any `match` expressions and is cleaner to read. Come back to this example
-> after you’ve read Chapter 13, and look up the `unwrap_or_else` method in the
-> standard library documentation. Many more of these methods can clean up huge
-> nested `match` expressions when you’re dealing with errors.
+That’s a lot of `match`! The `match` expression is very useful but also very
+much a primitive. In Chapter 13, you’ll learn about closures, which are used
+with many of the methods defined on `Result<T, E>`. These methods can be more
+concise than using `match` when handling `Result<T, E>` values in your code.
-### Shortcuts for Panic on Error: `unwrap` and `expect`
+For example, here’s another way to write the same logic as shown in Listing
+9-5, this time using closures and the `unwrap_or_else` method:
+
+```
+// src/main.rs
+use std::fs::File;
+use std::io::ErrorKind;
+
+fn main() {
+ let greeting_file = File::open("hello.txt").unwrap_or_else(|error| {
+ if error.kind() == ErrorKind::NotFound {
+ File::create("hello.txt").unwrap_or_else(|error| {
+ panic!("Problem creating the file: {:?}", error);
+ })
+ } else {
+ panic!("Problem opening the file: {:?}", error);
+ }
+ });
+}
+```
+
+Although this code has the same behavior as Listing 9-5, it doesn’t contain any
+`match` expressions and is cleaner to read. Come back to this example after
+you’ve read Chapter 13, and look up the `unwrap_or_else` method in the standard
+library documentation. Many more of these methods can clean up huge nested
+`match` expressions when you’re dealing with errors.
+
+#### Shortcuts for Panic on Error: unwrap and expect
Using `match` works well enough, but it can be a bit verbose and doesn’t always
communicate intent well. The `Result<T, E>` type has many helper methods
@@ -437,20 +428,11 @@ If we run this code without a *hello.txt* file, we’ll see an error message fro
the `panic!` call that the `unwrap` method makes:
```
-thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error {
-repr: Os { code: 2, message: "No such file or directory" } }',
-src/libcore/result.rs:906:4
+thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os {
+code: 2, kind: NotFound, message: "No such file or directory" }',
+src/main.rs:4:49
```
-<!---
-More recent rustc versions give a bit better error here (specifically the location):
-
-thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
-Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:4:37
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-/JT --->
-<!-- I'll update the error output when we're in Word /Carol -->
-
Similarly, the `expect` method lets us also choose the `panic!` error message.
Using `expect` instead of `unwrap` and providing good error messages can convey
your intent and make tracking down the source of a panic easier. The syntax of
@@ -473,36 +455,20 @@ will be the parameter that we pass to `expect`, rather than the default
`panic!` message that `unwrap` uses. Here’s what it looks like:
```
-thread 'main' panicked at 'hello.txt should be included in this project: Error { repr: Os { code:
-2, message: "No such file or directory" } }', src/libcore/result.rs:906:4
+thread 'main' panicked at 'hello.txt should be included in this project: Os {
+code: 2, kind: NotFound, message: "No such file or directory" }',
+src/main.rs:5:10
```
-<!---
-Ditto with the above:
-
-thread 'main' panicked at 'Failed to open hello.txt: Os { code: 2, kind: NotFound,
-message: "No such file or directory" }', src/main.rs:4:37
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-/JT --->
-<!-- I'll update the error output when we're in Word /Carol -->
-
In production-quality code, most Rustaceans choose `expect` rather than
`unwrap` and give more context about why the operation is expected to always
succeed. That way, if your assumptions are ever proven wrong, you have more
information to use in debugging.
-<!---
-Now that `unwrap` and `expect` give an improved file location, we may not
-need the paragraph above.
-/JT --->
-<!-- I've changed the paragraph above, as well as the text in the examaple
-usage of `expect`, to better reflect current best practices and the reasons for
-them. /Carol -->
-
### Propagating Errors
When a function’s implementation calls something that might fail, instead of
-handling the error within the function itself, you can return the error to the
+handling the error within the function itself you can return the error to the
calling code so that it can decide what to do. This is known as *propagating*
the error and gives more control to the calling code, where there might be more
information or logic that dictates how the error should be handled than what
@@ -518,19 +484,19 @@ Filename: src/main.rs
use std::fs::File;
use std::io::{self, Read};
-fn read_username_from_file() -> Result<String, io::Error> [1] {
- let username_file_result = File::open("hello.txt"); [2]
+1 fn read_username_from_file() -> Result<String, io::Error> {
+ 2 let username_file_result = File::open("hello.txt");
- let mut username_file [3] = match username_file_result {
- Ok(file) => file, [4]
- Err(e) => return Err(e), [5]
+ 3 let mut username_file = match username_file_result {
+ 4 Ok(file) => file,
+ 5 Err(e) => return Err(e),
};
- let mut username = String::new(); [6]
+ 6 let mut username = String::new();
- match username_file.read_to_string(&mut username) [7] {
- Ok(_) => Ok(username), [8]
- Err(e) => Err(e), [9]
+ 7 match username_file.read_to_string(&mut username) {
+ 8 Ok(_) => Ok(username),
+ 9 Err(e) => Err(e),
}
}
```
@@ -541,12 +507,12 @@ This function can be written in a much shorter way, but we’re going to start b
doing a lot of it manually in order to explore error handling; at the end,
we’ll show the shorter way. Let’s look at the return type of the function
first: `Result<String, io::Error>` [1]. This means the function is returning a
-value of the type `Result<T, E>` where the generic parameter `T` has been
-filled in with the concrete type `String`, and the generic type `E` has been
+value of the type `Result<T, E>`, where the generic parameter `T` has been
+filled in with the concrete type `String` and the generic type `E` has been
filled in with the concrete type `io::Error`.
If this function succeeds without any problems, the code that calls this
-function will receive an `Ok` value that holds a `String`—the username that
+function will receive an `Ok` value that holds a `String`—the `username` that
this function read from the file [8]. If this function encounters any problems,
the calling code will receive an `Err` value that holds an instance of
`io::Error` that contains more information about what the problems were. We
@@ -564,9 +530,9 @@ function continues. In the `Err` case, instead of calling `panic!`, we use the
error value from `File::open`, now in the pattern variable `e`, back to the
calling code as this function’s error value [5].
-So if we have a file handle in `username_file`, the function then creates a new
-`String` in variable `username` [6] and calls the `read_to_string` method on
-the file handle in `username_file` to read the contents of the file into
+So, if we have a file handle in `username_file`, the function then creates a
+new `String` in variable `username` [6] and calls the `read_to_string` method
+on the file handle in `username_file` to read the contents of the file into
`username` [7]. The `read_to_string` method also returns a `Result` because it
might fail, even though `File::open` succeeded. So we need another `match` to
handle that `Result`: if `read_to_string` succeeds, then our function has
@@ -576,20 +542,6 @@ same way that we returned the error value in the `match` that handled the
return value of `File::open`. However, we don’t need to explicitly say
`return`, because this is the last expression in the function [9].
-<!---
-Style nit: I'm finding the above two paragraphs a bit difficult to read
-comfortably. I think one issue is that we're using a handful of single letter
-variable names while also trying to walk someone through an explanation of
-multiple concepts.
-
-Maybe just me? But feels like the above example might be explained a bit better
-if we used more complete variable names so the explanation could have a better
-flow (without trying to remember what each of the single-letter variables meant)
-/JT --->
-<!-- Totally valid! I've changed the variable names in this, previous, and
-following examples, broke up these paragraphs a bit, and added wingdings.
-/Carol -->
-
The code that calls this code will then handle getting either an `Ok` value
that contains a username or an `Err` value that contains an `io::Error`. It’s
up to the calling code to decide what to do with those values. If the calling
@@ -602,18 +554,17 @@ it to handle appropriately.
This pattern of propagating errors is so common in Rust that Rust provides the
question mark operator `?` to make this easier.
-#### A Shortcut for Propagating Errors: the `?` Operator
+#### A Shortcut for Propagating Errors: The ? Operator
Listing 9-7 shows an implementation of `read_username_from_file` that has the
-same functionality as in Listing 9-6, but this implementation uses the
-`?` operator.
+same functionality as in Listing 9-6, but this implementation uses the `?`
+operator.
Filename: src/main.rs
```
use std::fs::File;
-use std::io;
-use std::io::Read;
+use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username_file = File::open("hello.txt")?;
@@ -651,13 +602,6 @@ define `impl From<io::Error> for OurError` to construct an instance of
`read_username_from_file` will call `from` and convert the error types without
needing to add any more code to the function.
-<!---
-It's a bit fuzzy what `impl From<OtherError> for ReturnedError` means. We may
-want to use a more concrete example, like: `impl From<OurError> for io::Error`.
-/JT --->
-<!-- I've added a more concrete example here, but converting the other way,
-which I think is more likely in production code /Carol -->
-
In the context of Listing 9-7, the `?` at the end of the `File::open` call will
return the value inside an `Ok` to the variable `username_file`. If an error
occurs, the `?` operator will return early out of the whole function and give
@@ -672,8 +616,7 @@ Filename: src/main.rs
```
use std::fs::File;
-use std::io;
-use std::io::Read;
+use std::io::{self, Read};
fn read_username_from_file() -> Result<String, io::Error> {
let mut username = String::new();
@@ -718,7 +661,7 @@ into that `String`, and returns it. Of course, using `fs::read_to_string`
doesn’t give us the opportunity to explain all the error handling, so we did it
the longer way first.
-#### Where The `?` Operator Can Be Used
+#### Where the ? Operator Can Be Used
The `?` operator can only be used in functions whose return type is compatible
with the value the `?` is used on. This is because the `?` operator is defined
@@ -729,8 +672,8 @@ as the `match` expression we defined in Listing 9-6. In Listing 9-6, the
it’s compatible with this `return`.
In Listing 9-10, let’s look at the error we’ll get if we use the `?` operator
-in a `main` function with a return type incompatible with the type of the value
-we use `?` on:
+in a `main` function with a return type that is incompatible with the type of
+the value we use `?` on.
Filename: src/main.rs
@@ -743,7 +686,7 @@ fn main() {
```
Listing 9-10: Attempting to use the `?` in the `main` function that returns
-`()` won’t compile
+`()` won’t compile.
This code opens a file, which might fail. The `?` operator follows the `Result`
value returned by `File::open`, but this `main` function has the return type of
@@ -751,15 +694,19 @@ value returned by `File::open`, but this `main` function has the return type of
message:
```
-error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)
- --> src/main.rs:4:36
- |
-3 | / fn main() {
-4 | | let f = File::open("hello.txt")?;
- | | ^ cannot use the `?` operator in a function that returns `()`
-5 | | }
- | |_- this function should return `Result` or `Option` to accept `?`
- |
+error[E0277]: the `?` operator can only be used in a function that returns
+`Result` or `Option` (or another type that implements `FromResidual`)
+ --> src/main.rs:4:48
+ |
+3 | / fn main() {
+4 | | let greeting_file = File::open("hello.txt")?;
+ | | ^ cannot use the `?`
+operator in a function that returns `()`
+5 | | }
+ | |_- this function should return `Result` or `Option` to accept `?`
+ |
+ = help: the trait `FromResidual<Result<Infallible, std::io::Error>>` is not
+implemented for `()`
```
This error points out that we’re only allowed to use the `?` operator in a
@@ -768,9 +715,9 @@ function that returns `Result`, `Option`, or another type that implements
To fix the error, you have two choices. One choice is to change the return type
of your function to be compatible with the value you’re using the `?` operator
-on as long as you have no restrictions preventing that. The other technique is
-to use a `match` or one of the `Result<T, E>` methods to handle the `Result<T,
-E>` in whatever way is appropriate.
+on as long as you have no restrictions preventing that. The other choice is to
+use a `match` or one of the `Result<T, E>` methods to handle the `Result<T, E>`
+in whatever way is appropriate.
The error message also mentioned that `?` can be used with `Option<T>` values
as well. As with using `?` on `Result`, you can only use `?` on `Option` in a
@@ -778,9 +725,9 @@ function that returns an `Option`. The behavior of the `?` operator when called
on an `Option<T>` is similar to its behavior when called on a `Result<T, E>`:
if the value is `None`, the `None` will be returned early from the function at
that point. If the value is `Some`, the value inside the `Some` is the
-resulting value of the expression and the function continues. Listing 9-11 has
+resultant value of the expression, and the function continues. Listing 9-11 has
an example of a function that finds the last character of the first line in the
-given text:
+given text.
```
fn last_char_of_first_line(text: &str) -> Option<char> {
@@ -804,7 +751,7 @@ The `?` extracts the string slice, and we can call `chars` on that string slice
to get an iterator of its characters. We’re interested in the last character in
this first line, so we call `last` to return the last item in the iterator.
This is an `Option` because it’s possible that the first line is the empty
-string, for example if `text` starts with a blank line but has characters on
+string; for example, if `text` starts with a blank line but has characters on
other lines, as in `"\nhi"`. However, if there is a last character on the first
line, it will be returned in the `Some` variant. The `?` operator in the middle
gives us a concise way to express this logic, allowing us to implement the
@@ -819,14 +766,16 @@ you can use methods like the `ok` method on `Result` or the `ok_or` method on
`Option` to do the conversion explicitly.
So far, all the `main` functions we’ve used return `()`. The `main` function is
-special because it’s the entry and exit point of executable programs, and there
-are restrictions on what its return type can be for the programs to behave as
-expected.
+special because it’s the entry point and exit point of an executable program,
+and there are restrictions on what its return type can be for the program to
+behave as expected.
-Luckily, `main` can also return a `Result<(), E>`. Listing 9-12 has the
-code from Listing 9-10 but we’ve changed the return type of `main` to be
+Luckily, `main` can also return a `Result<(), E>`. Listing 9-12 has the code
+from Listing 9-10, but we’ve changed the return type of `main` to be
`Result<(), Box<dyn Error>>` and added a return value `Ok(())` to the end. This
-code will now compile:
+code will now compile.
+
+Filename: src/main.rs
```
use std::error::Error;
@@ -839,51 +788,36 @@ fn main() -> Result<(), Box<dyn Error>> {
}
```
-<!---
-The move to `Box<dyn Error>` isn't unexpected for an experienced Rust
-developer, but I wonder if we should keep `std::io::Error` here to keep with
-the flow of the previous examples?
-
-I think my instinct was to mention this since we don't use the flexibility
-the trait object gives us. Instead, we switch to explaining how exit codes
-work with Result values.
-/JT --->
-<!-- The idea here was to give the reader code that will work in the future no
-matter what errors they're trying to return from main. If we put in
-std::io::Error, it'll work for this example, but probably not in the reader's
-own projects. I've added a sentence to the end of the paragraph after Listing
-9-12's caption to explain this thinking. /Carol -->
-
Listing 9-12: Changing `main` to return `Result<(), E>` allows the use of the
-`?` operator on `Result` values
-
-The `Box<dyn Error>` type is a *trait object*, which we’ll talk about in the
-“Using Trait Objects that Allow for Values of Different Types” section in
-Chapter 17. For now, you can read `Box<dyn Error>` to mean “any kind of error.”
-Using `?` on a `Result` value in a `main` function with the error type `Box<dyn
-Error>` is allowed, because it allows any `Err` value to be returned early.
-Even though the body of this `main` function will only ever return errors of
-type `std::io::Error`, by specifying `Box<dyn Error>`, this signature will
-continue to be correct even if more code that returns other errors is added to
-the body of `main`.
-
-When a `main` function returns a `Result<(), E>`, the executable will
-exit with a value of `0` if `main` returns `Ok(())` and will exit with a
-nonzero value if `main` returns an `Err` value. Executables written in C return
-integers when they exit: programs that exit successfully return the integer
-`0`, and programs that error return some integer other than `0`. Rust also
-returns integers from executables to be compatible with this convention.
+`?` operator on `Result` values.
+
+The `Box<dyn Error>` type is a *trait object*, which we’ll talk about in “Using
+Trait Objects That Allow for Values of Different Types” on page XX. For now,
+you can read `Box<dyn Error>` to mean “any kind of error.” Using `?` on a
+`Result` value in a `main` function with the error type `Box<dyn Error>` is
+allowed because it allows any `Err` value to be returned early. Even though the
+body of this `main` function will only ever return errors of type
+`std::io::Error`, by specifying `Box<dyn Error>`, this signature will continue
+to be correct even if more code that returns other errors is added to the body
+of `main`.
+
+When a `main` function returns a `Result<(), E>`, the executable will exit with
+a value of `0` if `main` returns `Ok(())` and will exit with a nonzero value if
+`main` returns an `Err` value. Executables written in C return integers when
+they exit: programs that exit successfully return the integer `0`, and programs
+that error return some integer other than `0`. Rust also returns integers from
+executables to be compatible with this convention.
The `main` function may return any types that implement the
`std::process::Termination` trait, which contains a function `report` that
-returns an `ExitCode` Consult the standard library documentation for more
+returns an `ExitCode`. Consult the standard library documentation for more
information on implementing the `Termination` trait for your own types.
Now that we’ve discussed the details of calling `panic!` or returning `Result`,
let’s return to the topic of how to decide which is appropriate to use in which
cases.
-## To `panic!` or Not to `panic!`
+## To panic! or Not to panic!
So how do you decide when you should call `panic!` and when you should return
`Result`? When code panics, there’s no way to recover. You could call `panic!`
@@ -904,11 +838,11 @@ some general guidelines on how to decide whether to panic in library code.
### Examples, Prototype Code, and Tests
-When you’re writing an example to illustrate some concept, also including robust
-error-handling code can make the example less clear. In
-examples, it’s understood that a call to a method like `unwrap` that could
-panic is meant as a placeholder for the way you’d want your application to
-handle errors, which can differ based on what the rest of your code is doing.
+When you’re writing an example to illustrate some concept, also including
+robust error-handling code can make the example less clear. In examples, it’s
+understood that a call to a method like `unwrap` that could panic is meant as a
+placeholder for the way you’d want your application to handle errors, which can
+differ based on what the rest of your code is doing.
Similarly, the `unwrap` and `expect` methods are very handy when prototyping,
before you’re ready to decide how to handle errors. They leave clear markers in
@@ -931,17 +865,6 @@ that you’ll never have an `Err` variant, it’s perfectly acceptable to call
`unwrap`, and even better to document the reason you think you’ll never have an
`Err` variant in the `expect` text. Here’s an example:
-<!---
-Some Rust devs may have a nuanced take on the above, myself included. I'd say
-you'd be safer to use `.expect(...)` and put as the argument the reason why it
-should never fail. If, in the future it ever *does* fail for some reason
-(probably as a result of many code fixes over time), then you've got a message
-to start with telling you what the original expectation was.
-/JT --->
-<!-- I agree with this and reinforcing this best practice; I've changed the
-`unwrap` to `expect` and demonstrated a good message. I still don't want to
-shame people too much for using `unwrap`, though. /Carol -->
-
```
use std::net::IpAddr;
@@ -960,25 +883,24 @@ valid IP address. If the IP address string came from a user rather than being
hardcoded into the program and therefore *did* have a possibility of failure,
we’d definitely want to handle the `Result` in a more robust way instead.
Mentioning the assumption that this IP address is hardcoded will prompt us to
-change `expect` to better error handling code if in the future, we need to get
+change `expect` to better error-handling code if, in the future, we need to get
the IP address from some other source instead.
### Guidelines for Error Handling
-It’s advisable to have your code panic when it’s possible that your code
-could end up in a bad state. In this context, a *bad state* is when some
-assumption, guarantee, contract, or invariant has been broken, such as when
-invalid values, contradictory values, or missing values are passed to your
-code—plus one or more of the following:
+It’s advisable to have your code panic when it’s possible that your code could
+end up in a bad state. In this context, a *bad state* is when some assumption,
+guarantee, contract, or invariant has been broken, such as when invalid values,
+contradictory values, or missing values are passed to your code—plus one or
+more of the following:
* The bad state is something that is unexpected, as opposed to something that
- will likely happen occasionally, like a user entering data in the wrong
- format.
+will likely happen occasionally, like a user entering data in the wrong format.
* Your code after this point needs to rely on not being in this bad state,
- rather than checking for the problem at every step.
+rather than checking for the problem at every step.
* There’s not a good way to encode this information in the types you use. We’ll
- work through an example of what we mean in the “Encoding States and Behavior
- as Types” section of Chapter 17.
+work through an example of what we mean in “Encoding States and Behavior as
+Types” on page XX.
If someone calls your code and passes in values that don’t make sense, it’s
best to return an error if you can so the user of the library can decide what
@@ -989,24 +911,6 @@ development. Similarly, `panic!` is often appropriate if you’re calling
external code that is out of your control and it returns an invalid state that
you have no way of fixing.
-<!---
-Disagree a bit with the above. I don't think libraries should ever panic. They
-should always be written defensively so they can be used in a broader range of
-applications, which include applications where crashing could result in data
-loss.
-
-Rather than crashing, libraries can encode the reasons they failed based on the
-user's input into an error that can be returned to the user.
-
-In practice, the only time the application should absolutely crash is if
-continuing could bring harm to the user's machine, their data, filesystem, and
-so on. Otherwise, the user should just be given a warning that the operation
-couldn't be completed successfully, so they can take their next action. If we
-crash, unfortunately the user never gets that choice.
-/JT --->
-<!-- I think we actually agree here but the original text wasn't clear enough;
-I've edited. /Carol -->
-
However, when failure is expected, it’s more appropriate to return a `Result`
than to make a `panic!` call. Examples include a parser being given malformed
data or an HTTP request returning a status that indicates you have hit a rate
@@ -1022,25 +926,12 @@ an out-of-bounds memory access: trying to access memory that doesn’t belong to
the current data structure is a common security problem. Functions often have
*contracts*: their behavior is only guaranteed if the inputs meet particular
requirements. Panicking when the contract is violated makes sense because a
-contract violation always indicates a caller-side bug and it’s not a kind of
+contract violation always indicates a caller-side bug, and it’s not a kind of
error you want the calling code to have to explicitly handle. In fact, there’s
no reasonable way for calling code to recover; the calling *programmers* need
to fix the code. Contracts for a function, especially when a violation will
cause a panic, should be explained in the API documentation for the function.
-<!---
-The wording of the first sentence in the above paragraph reads like we should
-panic on invalid data, but in the previous paragraph we say malformed data
-should be a `Result`. The rest makes sense, where the spirit of when the stdlib
-panics is less about invalid data and more about when the user will be put at
-risk.
-/JT --->
-<!-- I think we were trying to draw a distinction between "malformed" and
-"invalid" values that perhaps wasn't very clear. I've tried to clarify by
-adding "could put a user at risk", but I don't really want to get into the
-specifics of this because only a subset of readers will be writing code like
-this... /Carol -->
-
However, having lots of error checks in all of your functions would be verbose
and annoying. Fortunately, you can use Rust’s type system (and thus the type
checking done by the compiler) to do many of the checks for you. If your
@@ -1064,16 +955,18 @@ numbers before checking it against our secret number; we only validated that
the guess was positive. In this case, the consequences were not very dire: our
output of “Too high” or “Too low” would still be correct. But it would be a
useful enhancement to guide the user toward valid guesses and have different
-behavior when a user guesses a number that’s out of range versus when a user
-types, for example, letters instead.
+behavior when the user guesses a number that’s out of range versus when the
+user types, for example, letters instead.
One way to do this would be to parse the guess as an `i32` instead of only a
`u32` to allow potentially negative numbers, and then add a check for the
number being in range, like so:
+Filename: src/main.rs
+
```
loop {
- // --snip--
+ --snip--
let guess: i32 = match guess.trim().parse() {
Ok(num) => num,
@@ -1086,7 +979,7 @@ loop {
}
match guess.cmp(&secret_number) {
- // --snip--
+ --snip--
}
```
@@ -1096,7 +989,7 @@ and ask for another guess. After the `if` expression, we can proceed with the
comparisons between `guess` and the secret number knowing that `guess` is
between 1 and 100.
-However, this is not an ideal solution: if it was absolutely critical that the
+However, this is not an ideal solution: if it were absolutely critical that the
program only operated on values between 1 and 100, and it had many functions
with this requirement, having a check like this in every function would be
tedious (and might impact performance).
@@ -1108,71 +1001,60 @@ confidently use the values they receive. Listing 9-13 shows one way to define a
`Guess` type that will only create an instance of `Guess` if the `new` function
receives a value between 1 and 100.
+Filename: src/lib.rs
+
```
-pub struct Guess {
+1 pub struct Guess {
value: i32,
}
impl Guess {
- pub fn new(value: i32) -> Guess {
- if value < 1 || value > 100 {
- panic!("Guess value must be between 1 and 100, got {}.", value);
+ 2 pub fn new(value: i32) -> Guess {
+ 3 if value < 1 || value > 100 {
+ 4 panic!(
+ "Guess value must be between 1 and 100, got {}.",
+ value
+ );
}
- Guess { value }
+ 5 Guess { value }
}
- pub fn value(&self) -> i32 {
+ 6 pub fn value(&self) -> i32 {
self.value
}
}
```
-<!---
-The above example feels a bit off to me. We talk earlier about user input being
-a prime candidate for recoverable errors, and then we talk about encoding only
-proper states in the type system. But this examples seems to work with user
-input and panic if it's not correct, rather than using recoverable errors or
-encoding the state into the type.
-
-Maybe you could have them guess rock/paper/scissors and encode the
-rock/paper/scissor as three enum values, and if they type something outside of
-that, we don't allow it. Otherwise we create an enum of that value.
-/JT --->
-<!-- The point about this listing panicking is valid, but I disagree a little.
-I think this is encoding only valid states into the type system. Also, Chapter
-11 builds on this example to show how to use `should_panic`, so I'm going to
-leave this the way it is. /Carol -->
-
Listing 9-13: A `Guess` type that will only continue with values between 1 and
100
-First, we define a struct named `Guess` that has a field named `value` that
-holds an `i32`. This is where the number will be stored.
+First we define a struct named `Guess` that has a field named `value` that
+holds an `i32` [1]. This is where the number will be stored.
Then we implement an associated function named `new` on `Guess` that creates
-instances of `Guess` values. The `new` function is defined to have one
+instances of `Guess` values [2]. The `new` function is defined to have one
parameter named `value` of type `i32` and to return a `Guess`. The code in the
-body of the `new` function tests `value` to make sure it’s between 1 and 100.
-If `value` doesn’t pass this test, we make a `panic!` call, which will alert
-the programmer who is writing the calling code that they have a bug they need
-to fix, because creating a `Guess` with a `value` outside this range would
+body of the `new` function tests `value` to make sure it’s between 1 and 100
+[3]. If `value` doesn’t pass this test, we make a `panic!` call [4], which will
+alert the programmer who is writing the calling code that they have a bug they
+need to fix, because creating a `Guess` with a `value` outside this range would
violate the contract that `Guess::new` is relying on. The conditions in which
`Guess::new` might panic should be discussed in its public-facing API
documentation; we’ll cover documentation conventions indicating the possibility
of a `panic!` in the API documentation that you create in Chapter 14. If
`value` does pass the test, we create a new `Guess` with its `value` field set
-to the `value` parameter and return the `Guess`.
+to the `value` parameter and return the `Guess` [5].
Next, we implement a method named `value` that borrows `self`, doesn’t have any
-other parameters, and returns an `i32`. This kind of method is sometimes called
-a *getter*, because its purpose is to get some data from its fields and return
-it. This public method is necessary because the `value` field of the `Guess`
-struct is private. It’s important that the `value` field be private so code
-using the `Guess` struct is not allowed to set `value` directly: code outside
-the module *must* use the `Guess::new` function to create an instance of
-`Guess`, thereby ensuring there’s no way for a `Guess` to have a `value` that
-hasn’t been checked by the conditions in the `Guess::new` function.
+other parameters, and returns an `i32` [6]. This kind of method is sometimes
+called a *getter* because its purpose is to get some data from its fields and
+return it. This public method is necessary because the `value` field of the
+`Guess` struct is private. It’s important that the `value` field be private so
+code using the `Guess` struct is not allowed to set `value` directly: code
+outside the module *must* use the `Guess::new` function to create an instance
+of `Guess`, thereby ensuring there’s no way for a `Guess` to have a `value`
+that hasn’t been checked by the conditions in the `Guess::new` function.
A function that has a parameter or returns only numbers between 1 and 100 could
then declare in its signature that it takes or returns a `Guess` rather than an
@@ -1180,7 +1062,7 @@ then declare in its signature that it takes or returns a `Guess` rather than an
## Summary
-Rust’s error handling features are designed to help you write more robust code.
+Rust’s error-handling features are designed to help you write more robust code.
The `panic!` macro signals that your program is in a state it can’t handle and
lets you tell the process to stop instead of trying to proceed with invalid or
incorrect values. The `Result` enum uses Rust’s type system to indicate that
@@ -1193,17 +1075,3 @@ Now that you’ve seen useful ways that the standard library uses generics with
the `Option` and `Result` enums, we’ll talk about how generics work and how you
can use them in your code.
-<!---
-A meta comment: the coverage of `panic!` here feels helpful in terms of giving
-a more complete understanding of Rust, but in practice (and this may depend
-on domain), using `panic!` should be a fairly limited thing.
-
-Something I noticed we don't touch on but may want to is panic hooks, as
-unrecoverable errors isn't exactly true. You can recover from an unwinding
-panic if you need to code defensively against, say, a dependency panicking and
-you don't want your app to go down as a result.
-/JT --->
-<!-- Yeahhh I don't want to mention panic hooks, one because I don't think most
-people will need to think about them or implement one, and two because a subset
-of people will look at that and think "oh look, exception handling!" which...
-is not what it's for. /Carol -->
diff --git a/src/doc/book/nostarch/chapter10.md b/src/doc/book/nostarch/chapter10.md
index 2030c335e..bb8919d79 100644
--- a/src/doc/book/nostarch/chapter10.md
+++ b/src/doc/book/nostarch/chapter10.md
@@ -15,13 +15,13 @@ how they relate to other generics without knowing what will be in their place
when compiling and running the code.
Functions can take parameters of some generic type, instead of a concrete type
-like `i32` or `String`, in the same way a function takes parameters with
-unknown values to run the same code on multiple concrete values. In fact, we’ve
-already used generics in Chapter 6 with `Option<T>`, Chapter 8 with `Vec<T>`
-and `HashMap<K, V>`, and Chapter 9 with `Result<T, E>`. In this chapter, you’ll
+like `i32` or `String`, in the same way they take parameters with unknown
+values to run the same code on multiple concrete values. In fact, we’ve already
+used generics in Chapter 6 with `Option<T>`, in Chapter 8 with `Vec<T>` and
+`HashMap<K, V>`, and in Chapter 9 with `Result<T, E>`. In this chapter, you’ll
explore how to define your own types, functions, and methods with generics!
-First, we’ll review how to extract a function to reduce code duplication. We’ll
+First we’ll review how to extract a function to reduce code duplication. We’ll
then use the same technique to make a generic function from two functions that
differ only in the types of their parameters. We’ll also explain how to use
generic types in struct and enum definitions.
@@ -39,47 +39,47 @@ help.
## Removing Duplication by Extracting a Function
Generics allow us to replace specific types with a placeholder that represents
-multiple types to remove code duplication.
-Before diving into generics syntax, then, let’s first look at how to remove
-duplication in a way that doesn’t involve generic types by extracting a
-function that replaces specific values with a placeholder that represents
-multiple values. Then we’ll apply the same technique to extract a generic
-function! By looking at how to recognize duplicated code you can extract into a
-function, you’ll start to recognize duplicated code that can use generics.
+multiple types to remove code duplication. Before diving into generics syntax,
+let’s first look at how to remove duplication in a way that doesn’t involve
+generic types by extracting a function that replaces specific values with a
+placeholder that represents multiple values. Then we’ll apply the same
+technique to extract a generic function! By looking at how to recognize
+duplicated code you can extract into a function, you’ll start to recognize
+duplicated code that can use generics.
-We begin with the short program in Listing 10-1 that finds the largest number
-in a list.
+We’ll begin with the short program in Listing 10-1 that finds the largest
+number in a list.
Filename: src/main.rs
```
fn main() {
- let number_list = vec![34, 50, 25, 100, 65];
+ 1 let number_list = vec![34, 50, 25, 100, 65];
- let mut largest = &number_list[0];
+ 2 let mut largest = &number_list[0];
- for number in &number_list {
- if number > largest {
- largest = number;
+ 3 for number in &number_list {
+ 4 if number > largest {
+ 5 largest = number;
}
}
- println!("The largest number is {}", largest);
+ println!("The largest number is {largest}");
}
```
Listing 10-1: Finding the largest number in a list of numbers
-We store a list of integers in the variable `number_list` and place a reference
-to the first number in the list in a variable named `largest`. We then iterate
-through all the numbers in the list, and if the current number is greater than
-the number stored in `largest`, replace the reference in that variable.
-However, if the current number is less than or equal to the largest number seen
-so far, the variable doesn’t change, and the code moves on to the next number
-in the list. After considering all the numbers in the list, `largest` should
-refer to the largest number, which in this case is 100.
+We store a list of integers in the variable `number_list` [1] and place a
+reference to the first number in the list in a variable named `largest` [2]. We
+then iterate through all the numbers in the list [3], and if the current number
+is greater than the number stored in `largest` [4], we replace the reference in
+that variable [5]. However, if the current number is less than or equal to the
+largest number seen so far, the variable doesn’t change, and the code moves on
+to the next number in the list. After considering all the numbers in the list,
+`largest` should refer to the largest number, which in this case is 100.
-We've now been tasked with finding the largest number in two different lists of
+We’ve now been tasked with finding the largest number in two different lists of
numbers. To do so, we can choose to duplicate the code in Listing 10-1 and use
the same logic at two different places in the program, as shown in Listing 10-2.
@@ -97,7 +97,7 @@ fn main() {
}
}
- println!("The largest number is {}", largest);
+ println!("The largest number is {largest}");
let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
@@ -109,7 +109,7 @@ fn main() {
}
}
- println!("The largest number is {}", largest);
+ println!("The largest number is {largest}");
}
```
@@ -148,12 +148,12 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
- println!("The largest number is {}", result);
+ println!("The largest number is {result}");
let number_list = vec![102, 34, 6000, 89, 54, 2, 43, 8];
let result = largest(&number_list);
- println!("The largest number is {}", result);
+ println!("The largest number is {result}");
}
```
@@ -161,22 +161,15 @@ Listing 10-3: Abstracted code to find the largest number in two lists
The `largest` function has a parameter called `list`, which represents any
concrete slice of `i32` values we might pass into the function. As a result,
-when we call the function, the code runs on the specific values that we pass
-in.
+when we call the function, the code runs on the specific values that we pass in.
In summary, here are the steps we took to change the code from Listing 10-2 to
Listing 10-3:
-<!---
-"In summary"?
-/JT --->
-<!-- I believe "In sum" to be fine, but other people have been confused by it
-as well, so I'm ok changing it. /Carol -->
-
1. Identify duplicate code.
-2. Extract the duplicate code into the body of the function and specify the
- inputs and return values of that code in the function signature.
-3. Update the two instances of duplicated code to call the function instead.
+1. Extract the duplicate code into the body of the function, and specify the
+inputs and return values of that code in the function signature.
+1. Update the two instances of duplicated code to call the function instead.
Next, we’ll use these same steps with generics to reduce code duplication. In
the same way that the function body can operate on an abstract `list` instead
@@ -201,7 +194,7 @@ parameters and return value. Doing so makes our code more flexible and provides
more functionality to callers of our function while preventing code duplication.
Continuing with our `largest` function, Listing 10-4 shows two functions that
-both find the largest value in a slice. We'll then combine these into a single
+both find the largest value in a slice. We’ll then combine these into a single
function that uses generics.
Filename: src/main.rs
@@ -235,16 +228,16 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest_i32(&number_list);
- println!("The largest number is {}", result);
+ println!("The largest number is {result}");
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest_char(&char_list);
- println!("The largest char is {}", result);
+ println!("The largest char is {result}");
}
```
-Listing 10-4: Two functions that differ only in their names and the types in
+Listing 10-4: Two functions that differ only in their names and in the types in
their signatures
The `largest_i32` function is the one we extracted in Listing 10-3 that finds
@@ -255,16 +248,16 @@ 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, 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 one letter, and
+Rust’s type-naming convention is CamelCase. Short for *type*, `T` is the
+default choice of most Rust programmers.
When we use a parameter in the body of the function, we have to declare the
parameter name in the signature so the compiler knows what that name means.
Similarly, when we use a type parameter name in a function signature, we have
to declare the type parameter name before we use it. To define the generic
-`largest` function, place type name declarations inside angle brackets, `<>`,
-between the name of the function and the parameter list, like this:
+`largest` function, we place type name declarations inside angle brackets,
+`<>`, between the name of the function and the parameter list, like this:
```
fn largest<T>(list: &[T]) -> &T {
@@ -299,33 +292,33 @@ fn main() {
let number_list = vec![34, 50, 25, 100, 65];
let result = largest(&number_list);
- println!("The largest number is {}", result);
+ println!("The largest number is {result}");
let char_list = vec!['y', 'm', 'a', 'q'];
let result = largest(&char_list);
- println!("The largest char is {}", result);
+ println!("The largest char is {result}");
}
```
Listing 10-5: The `largest` function using generic type parameters; this
-doesn’t yet compile yet
+doesn’t compile yet
If we compile this code right now, we’ll get this error:
```
-error[E0369]: binary operation `>` cannot be applied to type `T`
+error[E0369]: binary operation `>` cannot be applied to type `&T`
--> src/main.rs:5:17
|
5 | if item > largest {
- | ---- ^ ------- T
+ | ---- ^ ------- &T
| |
- | T
+ | &T
|
help: consider restricting type parameter `T`
|
-1 | fn largest<T: std::cmp::PartialOrd>(list: &[T]) -> T {
- | ^^^^^^^^^^^^^^^^^^^^^^
+1 | fn largest<T: std::cmp::PartialOrd>(list: &[T]) -> &T {
+ | ++++++++++++++++++++++
```
The help text mentions `std::cmp::PartialOrd`, which is a *trait*, and we’re
@@ -334,31 +327,11 @@ states that the body of `largest` won’t work for all possible types that `T`
could be. Because we want to compare values of type `T` in the body, we can
only use types whose values can be ordered. To enable comparisons, the standard
library has the `std::cmp::PartialOrd` trait that you can implement on types
-(see Appendix C for more on this trait). By following the help text's
+(see Appendix C for more on this trait). By following the help text’s
suggestion, we restrict the types valid for `T` to only those that implement
`PartialOrd` and this example will compile, because the standard library
implements `PartialOrd` on both `i32` and `char`.
-<!---
-The wording at the end of the above paragraph feels a little odd. For the
-"You’ll learn how to specify that a generic type has a particular trait in the
-“Traits as Parameters” section." -- the error message above tells you how to
-maybe fix it.
-
-Well, it *could* fix it but the way the example is written adds multiple
-constraints.
-
-Do we want to leave this example unfinished and move onto other topics for a
-bit or revise the example so it's more self-contained, allowing the compiler to
-help us and later revisit after we've learned more?
-/JT --->
-<!-- I've modified the example and explanation just slightly so that only
-adding the `PartialOrd` trait as suggested here will fix it completely, perhaps
-leaving the reader hanging a little bit less. It's really hard to teach
-generics and trait bounds, though, because you can't do much with generics
-unless you have trait bounds too (and can't learn why you'd want trait bounds
-without knowing about generics). /Carol -->
-
### In Struct Definitions
We can also define structs to use a generic type parameter in one or more
@@ -368,9 +341,9 @@ fields using the `<>` syntax. Listing 10-6 defines a `Point<T>` struct to hold
Filename: src/main.rs
```
-struct Point<T> {
- x: T,
- y: T,
+1 struct Point<T> {
+ 2 x: T,
+ 3 y: T,
}
fn main() {
@@ -382,9 +355,10 @@ fn main() {
Listing 10-6: A `Point<T>` struct that holds `x` and `y` values of type `T`
The syntax for using generics in struct definitions is similar to that used in
-function definitions. First, we declare the name of the type parameter inside
-angle brackets just after the name of the struct. Then we use the generic type
-in the struct definition where we would otherwise specify concrete data types.
+function definitions. First we declare the name of the type parameter inside
+angle brackets just after the name of the struct [1]. Then we use the generic
+type in the struct definition where we would otherwise specify concrete data
+types [23].
Note that because we’ve used only one generic type to define `Point<T>`, this
definition says that the `Point<T>` struct is generic over some type `T`, and
@@ -408,42 +382,18 @@ fn main() {
Listing 10-7: The fields `x` and `y` must be the same type because both have
the same generic data type `T`.
-In this example, when we assign the integer value 5 to `x`, we let the compiler
-know that the generic type `T` will be an integer for this instance of
-`Point<T>`. Then when we specify 4.0 for `y`, which we’ve defined to have the
+In this example, when we assign the integer value `5` to `x`, we let the
+compiler know that the generic type `T` will be an integer for this instance of
+`Point<T>`. Then when we specify `4.0` for `y`, which we’ve defined to have the
same type as `x`, we’ll get a type mismatch error like this:
-<!---
-Not sure how or where we might want to call this out, but this is also how
-type inference in Rust works. If we don't know the type, we look for how it's
-used. That fresh type becomes a concrete type, and any use after that which
-is different than we expect becomes an error.
-
-fn main() {
- let mut x;
-
- x = 5;
- x = 4.0;
-}
-
-Also gives:
- |
-2 | let mut x;
- | ----- expected due to the type of this binding
-...
-5 | x = 4.0;
- | ^^^ expected integer, found floating-point number
-
-/JT --->
-<!-- Yeah, it's kind of neat trivia, but doesn't really fit here I don't think.
-/Carol -->
-
```
error[E0308]: mismatched types
--> src/main.rs:7:38
|
7 | let wont_work = Point { x: 5, y: 4.0 };
- | ^^^ expected integer, found floating-point number
+ | ^^^ expected integer, found floating-
+point number
```
To define a `Point` struct where `x` and `y` are both generics but could have
@@ -471,7 +421,7 @@ values of different types
Now all the instances of `Point` shown are allowed! You can use as many generic
type parameters in a definition as you want, but using more than a few makes
-your code hard to read. If you're finding you need lots of generic types in
+your code hard to read. If you’re finding you need lots of generic types in
your code, it could indicate that your code needs restructuring into smaller
pieces.
@@ -521,7 +471,7 @@ avoid duplication by using generic types instead.
### In Method Definitions
We can implement methods on structs and enums (as we did in Chapter 5) and use
-generic types in their definitions, too. Listing 10-9 shows the `Point<T>`
+generic types in their definitions too. Listing 10-9 shows the `Point<T>`
struct we defined in Listing 10-6 with a method named `x` implemented on it.
Filename: src/main.rs
@@ -545,16 +495,6 @@ fn main() {
}
```
-<!---
-
-The above code gives a warning for the unused `y`. Maybe we can print both
-`x` and `y`?
-
-/JT --->
-<!-- In general, I'm not worried about unused code warnings, there's a lot of
-examples that have unused code because they're small examples. I don't think
-there's much value in adding a method and printing `y` as well. /Carol -->
-
Listing 10-9: Implementing a method named `x` on the `Point<T>` struct that
will return a reference to the `x` field of type `T`
@@ -593,7 +533,7 @@ This code means the type `Point<f32>` will have a `distance_from_origin`
method; other instances of `Point<T>` where `T` is not of type `f32` will not
have this method defined. The method measures how far our point is from the
point at coordinates (0.0, 0.0) and uses mathematical operations that are
-available only for floating point types.
+available only for floating-point types.
Generic type parameters in a struct definition aren’t always the same as those
you use in that same struct’s method signatures. Listing 10-11 uses the generic
@@ -610,8 +550,11 @@ struct Point<X1, Y1> {
y: Y1,
}
-impl<X1, Y1> Point<X1, Y1> {
- fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {
+1 impl<X1, Y1> Point<X1, Y1> {
+ 2 fn mixup<X2, Y2>(
+ self,
+ other: Point<X2, Y2>,
+ ) -> Point<X1, Y2> {
Point {
x: self.x,
y: other.y,
@@ -620,12 +563,12 @@ impl<X1, Y1> Point<X1, Y1> {
}
fn main() {
- let p1 = Point { x: 5, y: 10.4 };
- let p2 = Point { x: "Hello", y: 'c' };
+ 3 let p1 = Point { x: 5, y: 10.4 };
+ 4 let p2 = Point { x: "Hello", y: 'c' };
- let p3 = p1.mixup(p2);
+ 5 let p3 = p1.mixup(p2);
- println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
+ 6 println!("p3.x = {}, p3.y = {}", p3.x, p3.y);
}
```
@@ -633,25 +576,25 @@ Listing 10-11: A method that uses generic types different from its struct’s
definition
In `main`, we’ve defined a `Point` that has an `i32` for `x` (with value `5`)
-and an `f64` for `y` (with value `10.4`). The `p2` variable is a `Point` struct
-that has a string slice for `x` (with value `"Hello"`) and a `char` for `y`
-(with value `c`). Calling `mixup` on `p1` with the argument `p2` gives us `p3`,
-which will have an `i32` for `x`, because `x` came from `p1`. The `p3` variable
-will have a `char` for `y`, because `y` came from `p2`. The `println!` macro
-call will print `p3.x = 5, p3.y = c`.
+and an `f64` for `y` (with value `10.4` [3]). The `p2` variable is a `Point`
+struct that has a string slice for `x` (with value `"Hello"`) and a `char` for
+`y` (with value `c` [4]). Calling `mixup` on `p1` with the argument `p2` gives
+us `p3` [5], which will have an `i32` for `x` because `x` came from `p1`. The
+`p3` variable will have a `char` for `y` because `y` came from `p2`. The
+`println!` macro call [6] will print `p3.x = 5, p3.y = c`.
The purpose of this example is to demonstrate a situation in which some generic
parameters are declared with `impl` and some are declared with the method
definition. Here, the generic parameters `X1` and `Y1` are declared after
-`impl` because they go with the struct definition. The generic parameters `X2`
-and `Y2` are declared after `fn mixup`, because they’re only relevant to the
-method.
+`impl` [1] because they go with the struct definition. The generic parameters
+`X2` and `Y2` are declared after `fn mixup` [2] because they’re only relevant
+to the 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 run any
-slower than it would with concrete types.
+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
generics at compile time. *Monomorphization* is the process of turning generic
@@ -676,15 +619,6 @@ is `f64`. As such, it expands the generic definition of `Option<T>` into two
definitions specialized to `i32` and `f64`, thereby replacing the generic
definition with the specific ones.
-<!---
-
-We may want to be clear in the above it doesn't actually do this, as you
-wouldn't be able to write `enum Option_i32` in your code as it would clash.
-
-/JT --->
-<!-- I've reworded the last sentence in the above paragraph and the next
-sentence to hopefully sidestep the issue JT pointed out. /Carol -->
-
The monomorphized version of the code looks similar to the following (the
compiler uses different names than what we’re using here for illustration):
@@ -716,13 +650,13 @@ at runtime.
## Traits: Defining Shared Behavior
-A *trait* defines functionality a particular type has and can share with other
-types. We can use traits to define shared behavior in an abstract way. We can
-use *trait bounds* to specify that a generic type can be any type that has
+A *trait* defines the functionality a particular type has and can share with
+other types. We can use traits to define shared behavior in an abstract way. We
+can use *trait bounds* to specify that a generic type can be any type that has
certain behavior.
> Note: Traits are similar to a feature often called *interfaces* in other
-> languages, although with some differences.
+languages, although with some differences.
### Defining a Trait
@@ -733,15 +667,15 @@ define a set of behaviors necessary to accomplish some purpose.
For example, let’s say we have multiple structs that hold various kinds and
amounts of text: a `NewsArticle` struct that holds a news story filed in a
-particular location and a `Tweet` that can have at most 280 characters along
+particular location and a `Tweet` that can have, at most, 280 characters along
with metadata that indicates whether it was a new tweet, a retweet, or a reply
to another tweet.
We want to make a media aggregator library crate named `aggregator` that can
display summaries of data that might be stored in a `NewsArticle` or `Tweet`
-instance. To do this, we need a summary from each type, and we’ll request
-that summary by calling a `summarize` method on an instance. Listing 10-12
-shows the definition of a public `Summary` trait that expresses this behavior.
+instance. To do this, we need a summary from each type, and we’ll request that
+summary by calling a `summarize` method on an instance. Listing 10-12 shows the
+definition of a public `Summary` trait that expresses this behavior.
Filename: src/lib.rs
@@ -755,7 +689,7 @@ Listing 10-12: A `Summary` trait that consists of the behavior provided by a
`summarize` method
Here, we declare a trait using the `trait` keyword and then the trait’s name,
-which is `Summary` in this case. We’ve also declared the trait as `pub` so that
+which is `Summary` in this case. We also declare the trait as `pub` so that
crates depending on this crate can make use of this trait too, as we’ll see in
a few examples. Inside the curly brackets, we declare the method signatures
that describe the behaviors of the types that implement this trait, which in
@@ -768,7 +702,7 @@ that any type that has the `Summary` trait will have the method `summarize`
defined with this signature exactly.
A trait can have multiple methods in its body: the method signatures are listed
-one per line and each line ends in a semicolon.
+one per line, and each line ends in a semicolon.
### Implementing a Trait on a Type
@@ -777,7 +711,7 @@ we can implement it on the types in our media aggregator. Listing 10-13 shows
an implementation of the `Summary` trait on the `NewsArticle` struct that uses
the headline, the author, and the location to create the return value of
`summarize`. For the `Tweet` struct, we define `summarize` as the username
-followed by the entire text of the tweet, assuming that tweet content is
+followed by the entire text of the tweet, assuming that the tweet content is
already limited to 280 characters.
Filename: src/lib.rs
@@ -792,7 +726,12 @@ pub struct NewsArticle {
impl Summary for NewsArticle {
fn summarize(&self) -> String {
- format!("{}, by {} ({})", self.headline, self.author, self.location)
+ format!(
+ "{}, by {} ({})",
+ self.headline,
+ self.author,
+ self.location
+ )
}
}
@@ -821,8 +760,6 @@ that the trait definition has defined. Instead of adding a semicolon after each
signature, we use curly brackets and fill in the method body with the specific
behavior that we want the methods of the trait to have for the particular type.
-<!-- NOTE TO ADD SOME NUMBER INDICATORS HERE IN THE WORD FILES -->
-
Now that the library has implemented the `Summary` trait on `NewsArticle` and
`Tweet`, users of the crate can call the trait methods on instances of
`NewsArticle` and `Tweet` in the same way we call regular methods. The only
@@ -852,23 +789,23 @@ know, people`.
Other crates that depend on the `aggregator` crate can also bring the `Summary`
trait into scope to implement `Summary` on their own types. One restriction to
-note is that we can implement a trait on a type only if at least one of the
-trait or the type is local to our crate. For example, we can implement standard
+note is that we can implement a trait on a type only if either the trait or the
+type, or both, are local to our crate. For example, we can implement standard
library traits like `Display` on a custom type like `Tweet` as part of our
-`aggregator` crate functionality, because the type `Tweet` is local to our
+`aggregator` crate functionality because the type `Tweet` is local to our
`aggregator` crate. We can also implement `Summary` on `Vec<T>` in our
-`aggregator` crate, because the trait `Summary` is local to our `aggregator`
+`aggregator` crate because the trait `Summary` is local to our `aggregator`
crate.
But we can’t implement external traits on external types. For example, we can’t
-implement the `Display` trait on `Vec<T>` within our `aggregator` crate,
-because `Display` and `Vec<T>` are both defined in the standard library and
-aren’t local to our `aggregator` crate. This restriction is part of a property
-called *coherence*, and more specifically the *orphan rule*, so named because
-the parent type is not present. This rule ensures that other people’s code
-can’t break your code and vice versa. Without the rule, two crates could
-implement the same trait for the same type, and Rust wouldn’t know which
-implementation to use.
+implement the `Display` trait on `Vec<T>` within our `aggregator` crate because
+`Display` and `Vec<T>` are both defined in the standard library and aren’t
+local to our `aggregator` crate. This restriction is part of a property called
+*coherence*, and more specifically the *orphan rule*, so named because the
+parent type is not present. This rule ensures that other people’s code can’t
+break your code and vice versa. Without the rule, two crates could implement
+the same trait for the same type, and Rust wouldn’t know which implementation
+to use.
### Default Implementations
@@ -877,7 +814,7 @@ in a trait instead of requiring implementations for all methods on every type.
Then, as we implement the trait on a particular type, we can keep or override
each method’s default behavior.
-In Listing 10-14 we specify a default string for the `summarize` method of the
+In Listing 10-14, we specify a default string for the `summarize` method of the
`Summary` trait instead of only defining the method signature, as we did in
Listing 10-12.
@@ -891,8 +828,8 @@ pub trait Summary {
}
```
-Listing 10-14: Defining a `Summary` trait with a default implementation of
-the `summarize` method
+Listing 10-14: Defining a `Summary` trait with a default implementation of the
+`summarize` method
To use a default implementation to summarize instances of `NewsArticle`, we
specify an empty `impl` block with `impl Summary for NewsArticle {}`.
@@ -904,7 +841,9 @@ the `summarize` method on an instance of `NewsArticle`, like this:
```
let article = NewsArticle {
- headline: String::from("Penguins win the Stanley Cup Championship!"),
+ headline: String::from(
+ "Penguins win the Stanley Cup Championship!"
+ ),
location: String::from("Pittsburgh, PA, USA"),
author: String::from("Iceburgh"),
content: String::from(
@@ -936,7 +875,10 @@ pub trait Summary {
fn summarize_author(&self) -> String;
fn summarize(&self) -> String {
- format!("(Read more from {}...)", self.summarize_author())
+ format!(
+ "(Read more from {}...)",
+ self.summarize_author()
+ )
}
}
```
@@ -956,7 +898,8 @@ After we define `summarize_author`, we can call `summarize` on instances of the
`Tweet` struct, and the default implementation of `summarize` will call the
definition of `summarize_author` that we’ve provided. Because we’ve implemented
`summarize_author`, the `Summary` trait has given us the behavior of the
-`summarize` method without requiring us to write any more code.
+`summarize` method without requiring us to write any more code. Here’s what
+that looks like:
```
let tweet = Tweet {
@@ -979,7 +922,7 @@ overriding implementation of that same method.
### Traits as Parameters
Now that you know how to define and implement traits, we can explore how to use
-traits to define functions that accept many different types. We'll use the
+traits to define functions that accept many different types. We’ll use the
`Summary` trait we implemented on the `NewsArticle` and `Tweet` types in
Listing 10-13 to define a `notify` function that calls the `summarize` method
on its `item` parameter, which is of some type that implements the `Summary`
@@ -1036,7 +979,7 @@ The generic type `T` specified as the type of the `item1` and `item2`
parameters constrains the function such that the concrete type of the value
passed as an argument for `item1` and `item2` must be the same.
-#### Specifying Multiple Trait Bounds with the `+` Syntax
+#### Specifying Multiple Trait Bounds with the + Syntax
We can also specify more than one trait bound. Say we wanted `notify` to use
display formatting as well as `summarize` on `item`: we specify in the `notify`
@@ -1056,14 +999,14 @@ pub fn notify<T: Summary + Display>(item: &T) {
With the two trait bounds specified, the body of `notify` can call `summarize`
and use `{}` to format `item`.
-#### Clearer Trait Bounds with `where` Clauses
+#### Clearer Trait Bounds with where Clauses
Using too many trait bounds has its downsides. Each generic has its own trait
bounds, so functions with multiple generic type parameters can contain lots of
trait bound information between the function’s name and its parameter list,
making the function signature hard to read. For this reason, Rust has alternate
syntax for specifying trait bounds inside a `where` clause after the function
-signature. So instead of writing this:
+signature. So, instead of writing this:
```
fn some_function<T: Display + Clone, U: Clone + Debug>(t: &T, u: &U) -> i32 {
@@ -1073,8 +1016,9 @@ we can use a `where` clause, like this:
```
fn some_function<T, U>(t: &T, u: &U) -> i32
- where T: Display + Clone,
- U: Clone + Debug
+where
+ T: Display + Clone,
+ U: Clone + Debug,
{
```
@@ -1082,7 +1026,7 @@ This function’s signature is less cluttered: the function name, parameter list
and return type are close together, similar to a function without lots of trait
bounds.
-### Returning Types that Implement Traits
+### Returning Types That Implement Traits
We can also use the `impl Trait` syntax in the return position to return a
value of some type that implements a trait, as shown here:
@@ -1145,22 +1089,17 @@ fn returns_summarizable(switch: bool) -> impl Summary {
Returning either a `NewsArticle` or a `Tweet` isn’t allowed due to restrictions
around how the `impl Trait` syntax is implemented in the compiler. We’ll cover
-how to write a function with this behavior in the “Using Trait Objects That
-Allow for Values of Different Types” section of Chapter 17.
-
-<!-- I've removed the whole "Fixing the `largest` Function with Trait Bounds"
-section now that the example is slightly different and adding the one trait
-bound as the compiler suggests fixed Listing 10-5 earlier. I've also renumbered
-the following listings. /Carol-->
+how to write a function with this behavior in “Using Trait Objects That Allow
+for Values of Different Types” on page XX.
### Using Trait Bounds to Conditionally Implement Methods
By using a trait bound with an `impl` block that uses generic type parameters,
we can implement methods conditionally for types that implement the specified
traits. For example, the type `Pair<T>` in Listing 10-15 always implements the
-`new` function to return a new instance of `Pair<T>` (recall from the “Defining
-Methods” section of Chapter 5 that `Self` is a type alias for the type of the
-`impl` block, which in this case is `Pair<T>`). But in the next `impl` block,
+`new` function to return a new instance of `Pair<T>` (recall from “Defining
+Methods” on page XX that `Self` is a type alias for the type of the `impl`
+block, which in this case is `Pair<T>`). But in the next `impl` block,
`Pair<T>` only implements the `cmp_display` method if its inner type `T`
implements the `PartialOrd` trait that enables comparison *and* the `Display`
trait that enables printing.
@@ -1197,14 +1136,14 @@ on trait bounds
We can also conditionally implement a trait for any type that implements
another trait. Implementations of a trait on any type that satisfies the trait
-bounds are called *blanket implementations* and are extensively used in the
+bounds are called *blanket implementations* and are used extensively in the
Rust standard library. For example, the standard library implements the
`ToString` trait on any type that implements the `Display` trait. The `impl`
block in the standard library looks similar to this code:
```
impl<T: Display> ToString for T {
- // --snip--
+ --snip--
}
```
@@ -1225,48 +1164,27 @@ reduce duplication but also specify to the compiler that we want the generic
type to have particular behavior. The compiler can then use the trait bound
information to check that all the concrete types used with our code provide the
correct behavior. In dynamically typed languages, we would get an error at
-runtime if we called a method on a type which didn’t define the method. But Rust
-moves these errors to compile time so we’re forced to fix the problems before
-our code is even able to run. Additionally, we don’t have to write code that
-checks for behavior at runtime because we’ve already checked at compile time.
-Doing so improves performance without having to give up the flexibility of
-generics.
+runtime if we called a method on a type which didn’t define the method. But
+Rust moves these errors to compile time so we’re forced to fix the problems
+before our code is even able to run. Additionally, we don’t have to write code
+that checks for behavior at runtime because we’ve already checked at compile
+time. Doing so improves performance without having to give up the flexibility
+of generics.
## Validating References with Lifetimes
-<!---
-
-meta comment: this chapter is already pretty hefty. We just went through both
-generics and a whirlwind tour of traits. Lifetimes, while related to generics,
-feel like you might want to give a five minute break between them, let those
-sink in, and then pick up this topic.
-
-I noticed a couple topics we may want to touch on above for a bit of
-completeness:
-
-* A closer look at how From/Into work and how they relate to each other.
-* Using traits to specialize what you do when returning values.
- i.e., Why does `let four: u32 = "4".parse().unwrap();` work?
-* Turbofish
-
-/JT --->
-<!-- These comments are totally valid, but seeing as this revision is already
-dragging on later than we were hoping, I don't really want to do large scale
-reorganization at this point. /Carol -->
-
Lifetimes are another kind of generic that we’ve already been using. Rather
than ensuring that a type has the behavior we want, lifetimes ensure that
references are valid as long as we need them to be.
-One detail we didn’t discuss in the “References and Borrowing” section in
-Chapter 4 is that every reference in Rust has a *lifetime*, which is the scope
-for which that reference is valid. Most of the time, lifetimes are implicit and
-inferred, just like most of the time, types are inferred. We only must annotate
-types when multiple types are possible. In a similar way, we must annotate
-lifetimes when the lifetimes of references could be related in a few different
-ways. Rust requires us to annotate the relationships using generic lifetime
-parameters to ensure the actual references used at runtime will definitely be
-valid.
+One detail we didn’t discuss in “References and Borrowing” on page XX is that
+every reference in Rust has a *lifetime*, which is the scope for which that
+reference is valid. Most of the time, lifetimes are implicit and inferred, just
+like most of the time, types are inferred. We must annotate types only when
+multiple types are possible. In a similar way, we must annotate lifetimes when
+the lifetimes of references could be related in a few different ways. Rust
+requires us to annotate the relationships using generic lifetime parameters to
+ensure the actual references used at runtime will definitely be valid.
Annotating lifetimes is not even a concept most other programming languages
have, so this is going to feel unfamiliar. Although we won’t cover lifetimes in
@@ -1282,32 +1200,32 @@ scope.
```
fn main() {
- let r;
+ 1 let r;
{
- let x = 5;
- r = &x;
- }
+ 2 let x = 5;
+ 3 r = &x;
+ 4 }
- println!("r: {}", r);
+ 5 println!("r: {r}");
}
```
Listing 10-16: An attempt to use a reference whose value has gone out of scope
-> Note: The examples in Listings 10-16, 10-17, and 10-23 declare variables
-> without giving them an initial value, so the variable name exists in the
-> outer scope. At first glance, this might appear to be in conflict with Rust’s
-> having no null values. However, if we try to use a variable before giving it
-> a value, we’ll get a compile-time error, which shows that Rust indeed does
-> not allow null values.
+> Note: The examples in Listing 10-16, 10-17, and 10-23 declare variables
+without giving them an initial value, so the variable name exists in the outer
+scope. At first glance, this might appear to be in conflict with Rust’s having
+no null values. However, if we try to use a variable before giving it a value,
+we’ll get a compile-time error, which shows that Rust indeed does not allow
+null values.
-The outer scope declares a variable named `r` with no initial value, and the
-inner scope declares a variable named `x` with the initial value of 5. Inside
-the inner scope, we attempt to set the value of `r` as a reference to `x`. Then
-the inner scope ends, and we attempt to print the value in `r`. This code won’t
-compile because the value `r` is referring to has gone out of scope before we
-try to use it. Here is the error message:
+The outer scope declares a variable named `r` with no initial value [1], and
+the inner scope declares a variable named `x` with the initial value of `5`
+[2]. Inside the inner scope, we attempt to set the value of `r` as a reference
+to `x` [3]. Then the inner scope ends [4], and we attempt to print the value in
+`r` [5]. This code won’t compile because the value that `r` is referring to has
+gone out of scope before we try to use it. Here is the error message:
```
error[E0597]: `x` does not live long enough
@@ -1318,17 +1236,17 @@ error[E0597]: `x` does not live long enough
7 | }
| - `x` dropped here while still borrowed
8 |
-9 | println!("r: {}", r);
- | - borrow later used here
+9 | println!("r: {r}");
+ | - borrow later used here
```
-The variable `x` doesn’t “live long enough.” The reason is that `x` will be out
-of scope when the inner scope ends on line 7. But `r` is still valid for the
-outer scope; because its scope is larger, we say that it “lives longer.” If
-Rust allowed this code to work, `r` would be referencing memory that was
-deallocated when `x` went out of scope, and anything we tried to do with `r`
-wouldn’t work correctly. So how does Rust determine that this code is invalid?
-It uses a borrow checker.
+The error message says that the variable `x` “does not live long enough.” The
+reason is that `x` will be out of scope when the inner scope ends on line 7.
+But `r` is still valid for the outer scope; because its scope is larger, we say
+that it “lives longer.” If Rust allowed this code to work, `r` would be
+referencing memory that was deallocated when `x` went out of scope, and
+anything we tried to do with `r` wouldn’t work correctly. So how does Rust
+determine that this code is invalid? It uses a borrow checker.
### The Borrow Checker
@@ -1345,7 +1263,7 @@ fn main() {
r = &x; // | |
} // -+ |
// |
- println!("r: {}", r); // |
+ println!("r: {r}"); // |
} // ---------+
```
@@ -1359,7 +1277,7 @@ lifetimes and sees that `r` has a lifetime of `'a` but that it refers to memory
with a lifetime of `'b`. The program is rejected because `'b` is shorter than
`'a`: the subject of the reference doesn’t live as long as the reference.
-Listing 10-18 fixes the code so it doesn’t have a dangling reference and
+Listing 10-18 fixes the code so it doesn’t have a dangling reference and it
compiles without any errors.
```
@@ -1368,7 +1286,7 @@ fn main() {
// |
let r = &x; // --+-- 'a |
// | |
- println!("r: {}", r); // | |
+ println!("r: {r}"); // | |
// --+ |
} // ----------+
```
@@ -1399,7 +1317,7 @@ fn main() {
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
- println!("The longest string is {}", result);
+ println!("The longest string is {result}");
}
```
@@ -1408,9 +1326,9 @@ longer of two string slices
Note that we want the function to take string slices, which are references,
rather than strings, because we don’t want the `longest` function to take
-ownership of its parameters. Refer to the “String Slices as Parameters” section
-in Chapter 4 for more discussion about why the parameters we use in Listing
-10-19 are the ones we want.
+ownership of its parameters. Refer to “String Slices as Parameters” on page XX
+for more discussion about why the parameters we use in Listing 10-19 are the
+ones we want.
If we try to implement the `longest` function as shown in Listing 10-20, it
won’t compile.
@@ -1439,11 +1357,12 @@ error[E0106]: missing lifetime specifier
9 | fn longest(x: &str, y: &str) -> &str {
| ---- ---- ^ expected named lifetime parameter
|
- = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y`
+ = help: this function's return type contains a borrowed value,
+but the signature does not say whether it is borrowed from `x` or `y`
help: consider introducing a named lifetime parameter
|
9 | fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
- | ^^^^ ^^^^^^^ ^^^^^^^ ^^^
+ | ++++ ++ ++ ++
```
The help text reveals that the return type needs a generic lifetime parameter
@@ -1487,25 +1406,16 @@ reference to an `i32` that also has the lifetime `'a`.
&'a mut i32 // a mutable reference with an explicit lifetime
```
-One lifetime annotation by itself doesn’t have much meaning, because the
+One lifetime annotation by itself doesn’t have much meaning because the
annotations are meant to tell Rust how generic lifetime parameters of multiple
references relate to each other. Let’s examine how the lifetime annotations
relate to each other in the context of the `longest` function.
-<!---
-
-The above description is a little hard to follow with a code example.
-
-/JT --->
-<!-- Rather than fleshing out the code that goes with this description, I've
-moved some of the description to the next section to go with the code example
-there. /Carol -->
-
### Lifetime Annotations in Function Signatures
To use lifetime annotations in function signatures, we need to declare the
generic *lifetime* parameters inside angle brackets between the function name
-and the parameter list, just as we did with generic *type* parameters
+and the parameter list, just as we did with generic *type* parameters.
We want the signature to express the following constraint: the returned
reference will be valid as long as both the parameters are valid. This is the
@@ -1579,7 +1489,7 @@ fn main() {
{
let string2 = String::from("xyz");
let result = longest(string1.as_str(), string2.as_str());
- println!("The longest string is {}", result);
+ println!("The longest string is {result}");
}
}
```
@@ -1589,7 +1499,7 @@ that have different concrete lifetimes
In this example, `string1` is valid until the end of the outer scope, `string2`
is valid until the end of the inner scope, and `result` references something
-that is valid until the end of the inner scope. Run this code, and you’ll see
+that is valid until the end of the inner scope. Run this code and you’ll see
that the borrow checker approves; it will compile and print `The longest string
is long string is long`.
@@ -1611,7 +1521,7 @@ fn main() {
let string2 = String::from("xyz");
result = longest(string1.as_str(), string2.as_str());
}
- println!("The longest string is {}", result);
+ println!("The longest string is {result}");
}
```
@@ -1624,11 +1534,12 @@ error[E0597]: `string2` does not live long enough
--> src/main.rs:6:44
|
6 | result = longest(string1.as_str(), string2.as_str());
- | ^^^^^^^ borrowed value does not live long enough
+ | ^^^^^^^^^^^^^^^^ borrowed value
+does not live long enough
7 | }
| - `string2` dropped here while still borrowed
-8 | println!("The longest string is {}", result);
- | ------ borrow later used here
+8 | println!("The longest string is {result}");
+ | ------ borrow later used here
```
The error shows that for `result` to be valid for the `println!` statement,
@@ -1637,7 +1548,7 @@ this because we annotated the lifetimes of the function parameters and return
values using the same lifetime parameter `'a`.
As humans, we can look at this code and see that `string1` is longer than
-`string2` and therefore `result` will contain a reference to `string1`.
+`string2`, and therefore, `result` will contain a reference to `string1`.
Because `string1` has not gone out of scope yet, a reference to `string1` will
still be valid for the `println!` statement. However, the compiler can’t see
that the reference is valid in this case. We’ve told Rust that the lifetime of
@@ -1693,14 +1604,12 @@ lifetime is not related to the lifetime of the parameters at all. Here is the
error message we get:
```
-error[E0515]: cannot return value referencing local variable `result`
+error[E0515]: cannot return reference to local variable `result`
--> src/main.rs:11:5
|
11 | result.as_str()
- | ------^^^^^^^^^
- | |
- | returns a value referencing data owned by the current function
- | `result` is borrowed here
+ | ^^^^^^^^^^^^^^^ returns a reference to data owned by the
+current function
```
The problem is that `result` goes out of scope and gets cleaned up at the end
@@ -1718,29 +1627,27 @@ would create dangling pointers or otherwise violate memory safety.
### Lifetime Annotations in Struct Definitions
-So far, the structs we’ve defined all hold owned types. We can define structs to
-hold references, but in that case we would need to add a lifetime annotation on
-every reference in the struct’s definition. Listing 10-24 has a struct named
+So far, the structs we’ve defined all hold owned types. We can define structs
+to hold references, but in that case we would need to add a lifetime annotation
+on every reference in the struct’s definition. Listing 10-24 has a struct named
`ImportantExcerpt` that holds a string slice.
-<!---
-
-nit: "So far, the structs we've *defined* all hold owned types"
-
-/JT --->
-<!-- Fixed! /Carol -->
-
Filename: src/main.rs
```
-struct ImportantExcerpt<'a> {
- part: &'a str,
+1 struct ImportantExcerpt<'a> {
+ 2 part: &'a str,
}
fn main() {
- let novel = String::from("Call me Ishmael. Some years ago...");
- let first_sentence = novel.split('.').next().expect("Could not find a '.'");
- let i = ImportantExcerpt {
+ 3 let novel = String::from(
+ "Call me Ishmael. Some years ago..."
+ );
+ 4 let first_sentence = novel
+ .split('.')
+ .next()
+ .expect("Could not find a '.'");
+ 5 let i = ImportantExcerpt {
part: first_sentence,
};
}
@@ -1749,25 +1656,25 @@ fn main() {
Listing 10-24: A struct that holds a reference, requiring a lifetime annotation
This struct has the single field `part` that holds a string slice, which is a
-reference. As with generic data types, we declare the name of the generic
+reference [2]. As with generic data types, we declare the name of the generic
lifetime parameter inside angle brackets after the name of the struct so we can
-use the lifetime parameter in the body of the struct definition. This
+use the lifetime parameter in the body of the struct definition [1]. This
annotation means an instance of `ImportantExcerpt` can’t outlive the reference
it holds in its `part` field.
The `main` function here creates an instance of the `ImportantExcerpt` struct
-that holds a reference to the first sentence of the `String` owned by the
-variable `novel`. The data in `novel` exists before the `ImportantExcerpt`
-instance is created. In addition, `novel` doesn’t go out of scope until after
-the `ImportantExcerpt` goes out of scope, so the reference in the
-`ImportantExcerpt` instance is valid.
+[5] that holds a reference to the first sentence of the `String` [4] owned by
+the variable `novel` [3]. The data in `novel` exists before the
+`ImportantExcerpt` instance is created. In addition, `novel` doesn’t go out of
+scope until after the `ImportantExcerpt` goes out of scope, so the reference in
+the `ImportantExcerpt` instance is valid.
### Lifetime Elision
You’ve learned that every reference has a lifetime and that you need to specify
-lifetime parameters for functions or structs that use references. However, in
-Chapter 4 we had a function in Listing 4-9, shown again in Listing 10-25, that
-compiled without lifetime annotations.
+lifetime parameters for functions or structs that use references. However, we
+had a function in Listing 4-9, shown again in Listing 10-25, that compiled
+without lifetime annotations.
Filename: src/lib.rs
@@ -1830,8 +1737,8 @@ which it can’t figure out lifetimes, the compiler will stop with an error.
These rules apply to `fn` definitions as well as `impl` blocks.
The first rule is that the compiler assigns a lifetime parameter to each
-parameter that’s a reference. In other words, a function with one parameter gets
-one lifetime parameter: `fn foo<'a>(x: &'a i32)`; a function with two
+parameter that’s a reference. In other words, a function with one parameter
+gets one lifetime parameter: `fn foo<'a>(x: &'a i32)`; a function with two
parameters gets two separate lifetime parameters: `fn foo<'a, 'b>(x: &'a i32,
y: &'b i32)`; and so on.
@@ -1907,7 +1814,7 @@ use the lifetime parameters depends on whether they’re related to the struct
fields or the method parameters and return values.
Lifetime names for struct fields always need to be declared after the `impl`
-keyword and then used after the struct’s name, because those lifetimes are part
+keyword and then used after the struct’s name because those lifetimes are part
of the struct’s type.
In method signatures inside the `impl` block, references might be tied to the
@@ -1916,7 +1823,7 @@ addition, the lifetime elision rules often make it so that lifetime annotations
aren’t necessary in method signatures. Let’s look at some examples using the
struct named `ImportantExcerpt` that we defined in Listing 10-24.
-First, we’ll use a method named `level` whose only parameter is a reference to
+First we’ll use a method named `level` whose only parameter is a reference to
`self` and whose return value is an `i32`, which is not a reference to anything:
```
@@ -1936,7 +1843,7 @@ Here is an example where the third lifetime elision rule applies:
```
impl<'a> ImportantExcerpt<'a> {
fn announce_and_return_part(&self, announcement: &str) -> &str {
- println!("Attention please: {}", announcement);
+ println!("Attention please: {announcement}");
self.part
}
}
@@ -1957,9 +1864,8 @@ string literals have the `'static` lifetime, which we can annotate as follows:
let s: &'static str = "I have a static lifetime.";
```
-The text of this string is stored directly in the program’s binary, which
-is always available. Therefore, the lifetime of all string literals is
-`'static`.
+The text of this string is stored directly in the program’s binary, which is
+always available. Therefore, the lifetime of all string literals is `'static`.
You might see suggestions to use the `'static` lifetime in error messages. But
before specifying `'static` as the lifetime for a reference, think about
@@ -1967,7 +1873,7 @@ whether the reference you have actually lives the entire lifetime of your
program or not, and whether you want it to. Most of the time, an error message
suggesting the `'static` lifetime results from attempting to create a dangling
reference or a mismatch of the available lifetimes. In such cases, the solution
-is fixing those problems, not specifying the `'static` lifetime.
+is to fix those problems, not to specify the `'static` lifetime.
## Generic Type Parameters, Trait Bounds, and Lifetimes Together
@@ -1985,7 +1891,7 @@ fn longest_with_an_announcement<'a, T>(
where
T: Display,
{
- println!("Announcement! {}", ann);
+ println!("Announcement! {ann}");
if x.len() > y.len() {
x
} else {
@@ -2021,3 +1927,4 @@ that you will only need in very advanced scenarios; for those, you should read
the Rust Reference at *https://doc.rust-lang.org/reference/trait-bounds.html*.
But next, you’ll learn how to write tests in Rust so you can make sure your
code is working the way it should.
+
diff --git a/src/doc/book/nostarch/chapter11.md b/src/doc/book/nostarch/chapter11.md
index ea4ffe5bf..cf909d70c 100644
--- a/src/doc/book/nostarch/chapter11.md
+++ b/src/doc/book/nostarch/chapter11.md
@@ -33,11 +33,12 @@ We can write tests that assert, for example, that when we pass `3` to the
we make changes to our code to make sure any existing correct behavior has not
changed.
-Testing is a complex skill: although we can’t cover every detail about how to
-write good tests in one chapter, we’ll discuss the mechanics of Rust’s testing
-facilities. We’ll talk about the annotations and macros available to you when
-writing your tests, the default behavior and options provided for running your
-tests, and how to organize tests into unit tests and integration tests.
+Testing is a complex skill: although we can’t cover in one chapter every detail
+about how to write good tests, in this chapter we will discuss the mechanics of
+Rust’s testing facilities. We’ll talk about the annotations and macros
+available to you when writing your tests, the default behavior and options
+provided for running your tests, and how to organize tests into unit tests and
+integration tests.
## How to Write Tests
@@ -45,9 +46,9 @@ Tests are Rust functions that verify that the non-test code is functioning in
the expected manner. The bodies of test functions typically perform these three
actions:
-1. Set up any needed data or state.
-2. Run the code you want to test.
-3. Assert the results are what you expect.
+* Set up any needed data or state.
+* Run the code you want to test.
+* Assert that the results are what you expect.
Let’s look at the features Rust provides specifically for writing tests that
take these actions, which include the `test` attribute, a few macros, and the
@@ -60,8 +61,8 @@ attribute. Attributes are metadata about pieces of Rust code; one example is
the `derive` attribute we used with structs in Chapter 5. To change a function
into a test function, add `#[test]` on the line before `fn`. When you run your
tests with the `cargo test` command, Rust builds a test runner binary that runs
-the annotated functions and reports on whether each
-test function passes or fails.
+the annotated functions and reports on whether each test function passes or
+fails.
Whenever we make a new library project with Cargo, a test module with a test
function in it is automatically generated for us. This module gives you a
@@ -89,10 +90,10 @@ Filename: src/lib.rs
```
#[cfg(test)]
mod tests {
-[1] #[test]
+ 1 #[test]
fn it_works() {
let result = 2 + 2;
- [2] assert_eq!(result, 4);
+ 2 assert_eq!(result, 4);
}
}
```
@@ -119,19 +120,21 @@ The `cargo test` command runs all tests in our project, as shown in Listing
$ cargo test
Compiling adder v0.1.0 (file:///projects/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.57s
- Running unittests (target/debug/deps/adder-92948b65e88960b4)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+92948b65e88960b4)
-[1] running 1 test
-[2] test tests::it_works ... ok
+1 running 1 test
+2 test tests::it_works ... ok
-[3] test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+3 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
-[4] Doc-tests adder
+ 4 Doc-tests adder
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
-
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Listing 11-2: The output from running the automatically generated test
@@ -143,13 +146,12 @@ ok.` [3] means that all the tests passed, and the portion that reads `1 passed;
0 failed` totals the number of tests that passed or failed.
It’s possible to mark a test as ignored so it doesn’t run in a particular
-instance; we’ll cover that in the “Ignoring Some Tests Unless Specifically
-Requested” section later in this chapter. Because we haven’t done that here,
-the summary shows `0 ignored`. We can also pass an argument to the `cargo test`
-command to run only tests whose name matches a string; this is called *filtering*
-and we’ll cover that in the “Running a Subset of Tests by Name” section.
-Here we haven’t filtered the tests being run, so the end of the summary shows `0
-filtered out`.
+instance; we’ll cover that in “Ignoring Some Tests Unless Specifically
+Requested” on page XX. Because we haven’t done that here, the summary shows `0
+ignored`. We can also pass an argument to the `cargo test` command to run only
+tests whose name matches a string; this is called *filtering* and we’ll cover
+it in “Running a Subset of Tests by Name” on page XX. Here we haven’t filtered
+the tests being run, so the end of the summary shows `0 filtered out`.
The `0 measured` statistic is for benchmark tests that measure performance.
Benchmark tests are, as of this writing, only available in nightly Rust. See
@@ -161,10 +163,10 @@ The next part of the test output starting at `Doc-tests adder` [4] is for the
results of any documentation tests. We don’t have any documentation tests yet,
but Rust can compile any code examples that appear in our API documentation.
This feature helps keep your docs and your code in sync! We’ll discuss how to
-write documentation tests in the “Documentation Comments as Tests” section of
-Chapter 14. For now, we’ll ignore the `Doc-tests` output.
+write documentation tests in “Documentation Comments as Tests” on page XX. For
+now, we’ll ignore the `Doc-tests` output.
-Let’s start to customize the test to our own needs. First change the name of
+Let’s start to customize the test to our own needs. First, change the name of
the `it_works` function to a different name, such as `exploration`, like so:
Filename: src/lib.rs
@@ -174,7 +176,8 @@ Filename: src/lib.rs
mod tests {
#[test]
fn exploration() {
- assert_eq!(2 + 2, 4);
+ let result = 2 + 2;
+ assert_eq!(result, 4);
}
}
```
@@ -186,7 +189,8 @@ Then run `cargo test` again. The output now shows `exploration` instead of
running 1 test
test tests::exploration ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Now we’ll add another test, but this time we’ll make a test that fails! Tests
@@ -222,18 +226,20 @@ Run the tests again using `cargo test`. The output should look like Listing
```
running 2 tests
test tests::exploration ... ok
-[1] test tests::another ... FAILED
+1 test tests::another ... FAILED
-[2] failures:
+2 failures:
---- tests::another stdout ----
thread 'main' panicked at 'Make this test fail', src/lib.rs:10:9
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
-[3] failures:
+3 failures:
tests::another
-[4] test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+4 test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
error: test failed, to rerun pass '--lib'
```
@@ -248,7 +254,7 @@ line 10 in the *src/lib.rs* file. The next section [3] lists just the names of
all the failing tests, which is useful when there are lots of tests and lots of
detailed failing test output. We can use the name of a failing test to run just
that test to more easily debug it; we’ll talk more about ways to run tests in
-the “Controlling How Tests Are Run” section.
+“Controlling How Tests Are Run” on page XX.
The summary line displays at the end [4]: overall, our test result is `FAILED`.
We had one test pass and one test fail.
@@ -256,7 +262,7 @@ We had one test pass and one test fail.
Now that you’ve seen what the test results look like in different scenarios,
let’s look at some macros other than `panic!` that are useful in tests.
-### Checking Results with the `assert!` Macro
+### Checking Results with the assert! Macro
The `assert!` macro, provided by the standard library, is useful when you want
to ensure that some condition in a test evaluates to `true`. We give the
@@ -265,9 +271,9 @@ to ensure that some condition in a test evaluates to `true`. We give the
`assert!` macro calls `panic!` to cause the test to fail. Using the `assert!`
macro helps us check that our code is functioning in the way we intend.
-In Chapter 5, Listing 5-15, we used a `Rectangle` struct and a `can_hold`
-method, which are repeated here in Listing 11-5. Let’s put this code in the
-*src/lib.rs* file, then write some tests for it using the `assert!` macro.
+In Listing 5-15, we used a `Rectangle` struct and a `can_hold` method, which
+are repeated here in Listing 11-5. Let’s put this code in the *src/lib.rs*
+file, then write some tests for it using the `assert!` macro.
Filename: src/lib.rs
@@ -299,11 +305,11 @@ Filename: src/lib.rs
```
#[cfg(test)]
mod tests {
-[1] use super::*;
+ 1 use super::*;
#[test]
-[2] fn larger_can_hold_smaller() {
- [3] let larger = Rectangle {
+ 2 fn larger_can_hold_smaller() {
+ 3 let larger = Rectangle {
width: 8,
height: 7,
};
@@ -312,7 +318,7 @@ mod tests {
height: 1,
};
- [4] assert!(larger.can_hold(&smaller));
+ 4 assert!(larger.can_hold(&smaller));
}
}
```
@@ -322,11 +328,11 @@ indeed hold a smaller rectangle
Note that we’ve added a new line inside the `tests` module: `use super::*;`
[1]. The `tests` module is a regular module that follows the usual visibility
-rules we covered in Chapter 7 in the “Paths for Referring to an Item in the
-Module Tree” section. Because the `tests` module is an inner module, we need to
-bring the code under test in the outer module into the scope of the inner
-module. We use a glob here so anything we define in the outer module is
-available to this `tests` module.
+rules we covered in “Paths for Referring to an Item in the Module Tree” on page
+XX. Because the `tests` module is an inner module, we need to bring the code
+under test in the outer module into the scope of the inner module. We use a
+glob here, so anything we define in the outer module is available to this
+`tests` module.
We’ve named our test `larger_can_hold_smaller` [2], and we’ve created the two
`Rectangle` instances that we need [3]. Then we called the `assert!` macro and
@@ -338,7 +344,8 @@ out!
running 1 test
test tests::larger_can_hold_smaller ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
It does pass! Let’s add another test, this time asserting that a smaller
@@ -353,7 +360,7 @@ mod tests {
#[test]
fn larger_can_hold_smaller() {
- // --snip--
+ --snip--
}
#[test]
@@ -381,7 +388,8 @@ running 2 tests
test tests::larger_can_hold_smaller ... ok
test tests::smaller_cannot_hold_larger ... ok
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Two tests that pass! Now let’s see what happens to our test results when we
@@ -390,7 +398,8 @@ method by replacing the greater-than sign with a less-than sign when it
compares the widths:
```
-// --snip--
+--snip--
+
impl Rectangle {
fn can_hold(&self, other: &Rectangle) -> bool {
self.width < other.width && self.height > other.height
@@ -408,26 +417,29 @@ test tests::larger_can_hold_smaller ... FAILED
failures:
---- tests::larger_can_hold_smaller stdout ----
-thread 'main' 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
+thread 'main' 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
failures:
tests::larger_can_hold_smaller
-test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
-Our tests caught the bug! Because `larger.width` is 8 and `smaller.width` is
-5, the comparison of the widths in `can_hold` now returns `false`: 8 is not
+Our tests caught the bug! Because `larger.width` is `8` and `smaller.width` is
+`5`, the comparison of the widths in `can_hold` now returns `false`: 8 is not
less than 5.
-### Testing Equality with the `assert_eq!` and `assert_ne!` Macros
+### Testing Equality with the assert_eq! and assert_ne! Macros
A common way to verify functionality is to test for equality between the result
of the code under test and the value you expect the code to return. You could
-do this using the `assert!` macro and passing it an expression using the `==`
-operator. However, this is such a common test that the standard library
+do this by using the `assert!` macro and passing it an expression using the
+`==` operator. However, this is such a common test that the standard library
provides a pair of macros—`assert_eq!` and `assert_ne!`—to perform this test
more conveniently. These macros compare two arguments for equality or
inequality, respectively. They’ll also print the two values if the assertion
@@ -464,7 +476,8 @@ Let’s check that it passes!
running 1 test
test tests::it_adds_two ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
We pass `4` as the argument to `assert_eq!`, which is equal to the result of
@@ -489,23 +502,25 @@ test tests::it_adds_two ... FAILED
failures:
---- tests::it_adds_two stdout ----
-[1] thread 'main' panicked at 'assertion failed: `(left == right)`
-[2] left: `4`,
-[3] right: `5`', src/lib.rs:11:9
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+1 thread 'main' panicked at 'assertion failed: `(left == right)`
+2 left: `4`,
+3 right: `5`', src/lib.rs:11:9
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
failures:
tests::it_adds_two
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Our test caught the bug! The `it_adds_two` test failed, and the message tells
-us that the assertion that fails was `` assertion failed: `(left == right)` ``
-[1] and what the `left` [2] and `right` [3] values are. This message helps us
-start debugging: the `left` argument was `4` but the `right` argument, where we
-had `add_two(2)`, was `5`. You can imagine that this would be especially
-helpful when we have a lot of tests going on.
+us that the assertion that failed was `assertion failed: `(left == right)`` [1]
+and what the `left` [2] and `right` [3] values are. This message helps us start
+debugging: the `left` argument was `4` but the `right` argument, where we had
+`add_two(2)`, was `5`. You can imagine that this would be especially helpful
+when we have a lot of tests going on.
Note that in some languages and test frameworks, the parameters to equality
assertion functions are called `expected` and `actual`, and the order in which
@@ -513,7 +528,7 @@ we specify the arguments matters. However, in Rust, they’re called `left` and
`right`, and the order in which we specify the value we expect and the value
the code produces doesn’t matter. We could write the assertion in this test as
`assert_eq!(add_two(2), 4)`, which would result in the same failure message
-that displays `` assertion failed: `(left == right)` ``.
+that displays `assertion failed: `(left == right)``.
The `assert_ne!` macro will pass if the two values we give it are not equal and
fail if they’re equal. This macro is most useful for cases when we’re not sure
@@ -531,21 +546,20 @@ the standard library types implement these traits. For structs and enums that
you define yourself, you’ll need to implement `PartialEq` to assert equality of
those types. You’ll also need to implement `Debug` to print the values when the
assertion fails. Because both traits are derivable traits, as mentioned in
-Listing 5-12 in Chapter 5, this is usually as straightforward as adding the
+Listing 5-12, this is usually as straightforward as adding the
`#[derive(PartialEq, Debug)]` annotation to your struct or enum definition. See
-Appendix C, “Derivable Traits,” for more details about these and other
-derivable traits.
+Appendix C for more details about these and other derivable traits.
### Adding Custom Failure Messages
You can also add a custom message to be printed with the failure message as
optional arguments to the `assert!`, `assert_eq!`, and `assert_ne!` macros. Any
arguments specified after the required arguments are passed along to the
-`format!` macro (discussed in Chapter 8 in the “Concatenation with the `+`
-Operator or the `format!` Macro” section), so you can pass a format string that
-contains `{}` placeholders and values to go in those placeholders. Custom
-messages are useful for documenting what an assertion means; when a test fails,
-you’ll have a better idea of what the problem is with the code.
+`format!` macro (discussed in “Concatenation with the + Operator or the format!
+Macro” on page XX), so you can pass a format string that contains `{}`
+placeholders and values to go in those placeholders. Custom messages are useful
+for documenting what an assertion means; when a test fails, you’ll have a
+better idea of what the problem is with the code.
For example, let’s say we have a function that greets people by name and we
want to test that the name we pass into the function appears in the output:
@@ -554,7 +568,7 @@ Filename: src/lib.rs
```
pub fn greeting(name: &str) -> String {
- format!("Hello {}!", name)
+ format!("Hello {name}!")
}
#[cfg(test)]
@@ -594,8 +608,10 @@ 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
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'assertion failed:
+result.contains(\"Carol\")', src/lib.rs:12:9
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
failures:
@@ -614,8 +630,7 @@ fn greeting_contains_name() {
let result = greeting("Carol");
assert!(
result.contains("Carol"),
- "Greeting did not contain name, value was `{}`",
- result
+ "Greeting did not contain name, value was `{result}`"
);
}
```
@@ -624,21 +639,23 @@ Now when we run the test, we’ll get a more informative error message:
```
---- tests::greeting_contains_name stdout ----
-thread 'main' 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
+thread 'main' 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
```
We can see the value we actually got in the test output, which would help us
debug what happened instead of what we were expecting to happen.
-### Checking for Panics with `should_panic`
+### Checking for Panics with should_panic
In addition to checking return values, it’s important to check that our code
handles error conditions as we expect. For example, consider the `Guess` type
-that we created in Chapter 9, Listing 9-13. Other code that uses `Guess`
-depends on the guarantee that `Guess` instances will contain only values
-between 1 and 100. We can write a test that ensures that attempting to create a
-`Guess` instance with a value outside that range panics.
+that we created in Listing 9-13. Other code that uses `Guess` depends on the
+guarantee that `Guess` instances will contain only values between 1 and 100. We
+can write a test that ensures that attempting to create a `Guess` instance with
+a value outside that range panics.
We do this by adding the attribute `should_panic` to our test function. The
test passes if the code inside the function panics; the test fails if the code
@@ -647,9 +664,8 @@ inside the function doesn’t panic.
Listing 11-8 shows a test that checks that the error conditions of `Guess::new`
happen when we expect them to.
-Filename: src/lib.rs
-
```
+// src/lib.rs
pub struct Guess {
value: i32,
}
@@ -657,7 +673,10 @@ pub struct Guess {
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 || value > 100 {
- panic!("Guess value must be between 1 and 100, got {}.", value);
+ panic!(
+ "Guess value must be between 1 and 100, got {}.",
+ value
+ );
}
Guess { value }
@@ -676,7 +695,7 @@ mod tests {
}
```
-Listing 11-8: Testing that a condition will cause a `panic!`
+Listing 11-8: Testing that a condition will cause a panic!
We place the `#[should_panic]` attribute after the `#[test]` attribute and
before the test function it applies to. Let’s look at the result when this test
@@ -686,18 +705,24 @@ passes:
running 1 test
test tests::greater_than_100 - should panic ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Looks good! Now let’s introduce a bug in our code by removing the condition
that the `new` function will panic if the value is greater than 100:
```
-// --snip--
+// src/lib.rs
+--snip--
+
impl Guess {
pub fn new(value: i32) -> Guess {
if value < 1 {
- panic!("Guess value must be between 1 and 100, got {}.", value);
+ panic!(
+ "Guess value must be between 1 and 100, got {}.",
+ value
+ );
}
Guess { value }
@@ -719,7 +744,8 @@ note: test did not panic as expected
failures:
tests::greater_than_100
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
We don’t get a very helpful message in this case, but when we look at the test
@@ -735,10 +761,9 @@ consider the modified code for `Guess` in Listing 11-9 where the `new` function
panics with different messages depending on whether the value is too small or
too large.
-Filename: src/lib.rs
-
```
-// --snip--
+// src/lib.rs
+--snip--
impl Guess {
pub fn new(value: i32) -> Guess {
@@ -777,32 +802,30 @@ This test will pass because the value we put in the `should_panic` attribute’s
`expected` parameter is a substring of the message that the `Guess::new`
function panics with. We could have specified the entire panic message that we
expect, which in this case would be `Guess value must be less than or equal to
-100, got 200.` What you choose to specify depends on how much of the panic
+100, got 200`. What you choose to specify depends on how much of the panic
message is unique or dynamic and how precise you want your test to be. In this
case, a substring of the panic message is enough to ensure that the code in the
test function executes the `else if value > 100` case.
-<!---
-We may want to make extra clear above that `expected` here means substring. I
-think many people would assume equality rather than substring like the
-expected/actual of unit tests.
-
-(let alone how .expect(..) works. It seems we use the word expect in different
-ways around the language/library )
-/JT --->
-<!-- I've changed the example to be more clearly a substring specified, and
-changed the caption as well. Hope that makes it extra clear! /Carol -->
-
To see what happens when a `should_panic` test with an `expected` message
fails, let’s again introduce a bug into our code by swapping the bodies of the
`if value < 1` and the `else if value > 100` blocks:
```
+// src/lib.rs
+--snip--
if value < 1 {
- panic!("Guess value must be less than or equal to 100, got {}.", value);
+ panic!(
+ "Guess value must be less than or equal to 100, got {}.",
+ value
+ );
} else if value > 100 {
- panic!("Guess value must be greater than or equal to 1, got {}.", value);
+ panic!(
+ "Guess value must be greater than or equal to 1, got {}.",
+ value
+ );
}
+--snip--
```
This time when we run the `should_panic` test, it will fail:
@@ -814,30 +837,35 @@ 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 'main' 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."`,
+ panic message: `"Guess value must be greater than or equal to 1, got
+200."`,
expected substring: `"less than or equal to 100"`
failures:
tests::greater_than_100
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
```
The failure message indicates that this test did indeed panic as we expected,
but the panic message did not include the expected string `'Guess value must be
less than or equal to 100'`. The panic message that we did get in this case was
-`Guess value must be greater than or equal to 1, got 200.` Now we can start
+`Guess value must be greater than or equal to 1, got 200`. Now we can start
figuring out where our bug is!
-### Using `Result<T, E>` in Tests
+### Using Result<T, E> in Tests
Our tests so far all panic when they fail. We can also write tests that use
`Result<T, E>`! Here’s the test from Listing 11-1, rewritten to use `Result<T,
E>` and return an `Err` instead of panicking:
+Filename: src/lib.rs
+
```
#[cfg(test)]
mod tests {
@@ -872,15 +900,15 @@ test`.
## Controlling How Tests Are Run
-Just as `cargo run` compiles your code and then runs the resulting binary,
-`cargo test` compiles your code in test mode and runs the resulting test
+Just as `cargo run` compiles your code and then runs the resultant binary,
+`cargo test` compiles your code in test mode and runs the resultant test
binary. The default behavior of the binary produced by `cargo test` is to run
all the tests in parallel and capture output generated during test runs,
preventing the output from being displayed and making it easier to read the
output related to the test results. You can, however, specify command line
options to change this default behavior.
-Some command line options go to `cargo test`, and some go to the resulting test
+Some command line options go to `cargo test`, and some go to the resultant test
binary. To separate these two types of arguments, you list the arguments that
go to `cargo test` followed by the separator `--` and then the ones that go to
the test binary. Running `cargo test --help` displays the options you can use
@@ -934,7 +962,7 @@ Filename: src/lib.rs
```
fn prints_and_returns_10(a: i32) -> i32 {
- println!("I got the value {}", a);
+ println!("I got the value {a}");
10
}
@@ -968,16 +996,18 @@ test tests::this_test_will_fail ... FAILED
failures:
---- tests::this_test_will_fail stdout ----
-[1] I got the value 8
+1 I got the value 8
thread 'main' 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
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
failures:
tests::this_test_will_fail
-test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Note that nowhere in this output do we see `I got the value 4`, which is
@@ -986,8 +1016,8 @@ output from the test that failed, `I got the value 8` [1], appears in the
section of the test summary output, which also shows the cause of the test
failure.
-If we want to see printed values for passing tests as well, we can tell Rust
-to also show the output of successful tests with `--show-output`.
+If we want to see printed values for passing tests as well, we can tell Rust to
+also show the output of successful tests with `--show-output`:
```
$ cargo test -- --show-output
@@ -1017,12 +1047,14 @@ I got the value 8
thread 'main' 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
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
failures:
tests::this_test_will_fail
-test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
### Running a Subset of Tests by Name
@@ -1074,7 +1106,8 @@ test tests::add_three_and_two ... ok
test tests::add_two_and_two ... ok
test tests::one_hundred ... ok
-test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
#### Running Single Tests
@@ -1085,12 +1118,14 @@ We can pass the name of any test function to `cargo test` to run only that test:
$ cargo test one_hundred
Compiling adder v0.1.0 (file:///projects/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.69s
- Running unittests (target/debug/deps/adder-92948b65e88960b4)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+92948b65e88960b4)
running 1 test
test tests::one_hundred ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2
+filtered out; finished in 0.00s
```
Only the test with the name `one_hundred` ran; the other two tests didn’t match
@@ -1110,13 +1145,15 @@ run those two by running `cargo test add`:
$ cargo test add
Compiling adder v0.1.0 (file:///projects/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.61s
- Running unittests (target/debug/deps/adder-92948b65e88960b4)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+92948b65e88960b4)
running 2 tests
test tests::add_three_and_two ... ok
test tests::add_two_and_two ... ok
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1
+filtered out; finished in 0.00s
```
This command ran all tests with `add` in the name and filtered out the test
@@ -1137,7 +1174,8 @@ Filename: src/lib.rs
```
#[test]
fn it_works() {
- assert_eq!(2 + 2, 4);
+ let result = 2 + 2;
+ assert_eq!(result, 4);
}
#[test]
@@ -1147,20 +1185,22 @@ fn expensive_test() {
}
```
-After `#[test]` we add the `#[ignore]` line to the test we want to exclude. Now
-when we run our tests, `it_works` runs, but `expensive_test` doesn’t:
+After `#[test]`, we add the `#[ignore]` line to the test we want to exclude.
+Now when we run our tests, `it_works` runs, but `expensive_test` doesn’t:
```
$ cargo test
Compiling adder v0.1.0 (file:///projects/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.60s
- Running unittests (target/debug/deps/adder-92948b65e88960b4)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+92948b65e88960b4)
running 2 tests
test expensive_test ... ignored
test it_works ... ok
-test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
The `expensive_test` function is listed as `ignored`. If we want to run only
@@ -1169,19 +1209,21 @@ the ignored tests, we can use `cargo test -- --ignored`:
```
$ cargo test -- --ignored
Finished test [unoptimized + debuginfo] target(s) in 0.61s
- Running unittests (target/debug/deps/adder-92948b65e88960b4)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+92948b65e88960b4)
running 1 test
test expensive_test ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1
+filtered out; finished in 0.00s
```
By controlling which tests run, you can make sure your `cargo test` results
-will be fast. When you’re at a point where it makes sense to check the results
-of the `ignored` tests and you have time to wait for the results, you can run
-`cargo test -- --ignored` instead. If you want to run all tests whether they’re
-ignored or not, you can run `cargo test -- --include-ignored`.
+will be returned quickly. When you’re at a point where it makes sense to check
+the results of the `ignored` tests and you have time to wait for the results,
+you can run `cargo test -- --ignored` instead. If you want to run all tests
+whether they’re ignored or not, you can run `cargo test -- --include-ignored`.
## Test Organization
@@ -1206,16 +1248,16 @@ code that they’re testing. The convention is to create a module named `tests`
in each file to contain the test functions and to annotate the module with
`cfg(test)`.
-#### The Tests Module and `#[cfg(test)]`
+#### The Tests Module and #[cfg(test)]
-The `#[cfg(test)]` annotation on the tests module tells Rust to compile and run
-the test code only when you run `cargo test`, not when you run `cargo build`.
-This saves compile time when you only want to build the library and saves space
-in the resulting compiled artifact because the tests are not included. You’ll
-see that because integration tests go in a different directory, they don’t need
-the `#[cfg(test)]` annotation. However, because unit tests go in the same files
-as the code, you’ll use `#[cfg(test)]` to specify that they shouldn’t be
-included in the compiled result.
+The `#[cfg(test)]` annotation on the `tests` module tells Rust to compile and
+run the test code only when you run `cargo test`, not when you run `cargo
+build`. This saves compile time when you only want to build the library and
+saves space in the resultant compiled artifact because the tests are not
+included. You’ll see that because integration tests go in a different
+directory, they don’t need the `#[cfg(test)]` annotation. However, because unit
+tests go in the same files as the code, you’ll use `#[cfg(test)]` to specify
+that they shouldn’t be included in the compiled result.
Recall that when we generated the new `adder` project in the first section of
this chapter, Cargo generated this code for us:
@@ -1227,12 +1269,13 @@ Filename: src/lib.rs
mod tests {
#[test]
fn it_works() {
- assert_eq!(2 + 2, 4);
+ let result = 2 + 2;
+ assert_eq!(result, 4);
}
}
```
-This code is the automatically generated test module. The attribute `cfg`
+This code is the automatically generated `tests` module. The attribute `cfg`
stands for *configuration* and tells Rust that the following item should only
be included given a certain configuration option. In this case, the
configuration option is `test`, which is provided by Rust for compiling and
@@ -1275,7 +1318,7 @@ Listing 11-12: Testing a private function
Note that the `internal_adder` function is not marked as `pub`. Tests are just
Rust code, and the `tests` module is just another module. As we discussed in
-the “Paths for Referring to an Item in the Module Tree” section, items in child
+“Paths for Referring to an Item in the Module Tree” on page XX, items in child
modules can use the items in their ancestor modules. In this test, we bring all
of the `test` module’s parent’s items into scope with `use super::*`, and then
the test can call `internal_adder`. If you don’t think private functions should
@@ -1291,7 +1334,7 @@ work correctly on their own could have problems when integrated, so test
coverage of the integrated code is important as well. To create integration
tests, you first need a *tests* directory.
-#### The *tests* Directory
+#### The tests Directory
We create a *tests* directory at the top level of our project directory, next
to *src*. Cargo knows to look for integration test files in this directory. We
@@ -1307,12 +1350,12 @@ adder
├── Cargo.lock
├── Cargo.toml
├── src
-│   └── lib.rs
+│ └── lib.rs
└── tests
└── integration_test.rs
```
-Enter the code in Listing 11-13 into the *tests/integration_test.rs* file:
+Enter the code in Listing 11-13 into the *tests/integration_test.rs* file.
Filename: tests/integration_test.rs
@@ -1327,37 +1370,42 @@ fn it_adds_two() {
Listing 11-13: An integration test of a function in the `adder` crate
-Each file in the `tests` directory is a separate crate, so we need to bring our
-library into each test crate’s scope. For that reason we add `use adder` at the
-top of the code, which we didn’t need in the unit tests.
+Each file in the *tests* directory is a separate crate, so we need to bring our
+library into each test crate’s scope. For that reason we add `use adder;` at
+the top of the code, which we didn’t need in the unit tests.
We don’t need to annotate any code in *tests/integration_test.rs* with
-`#[cfg(test)]`. Cargo treats the `tests` directory specially and compiles files
+`#[cfg(test)]`. Cargo treats the *tests* directory specially and compiles files
in this directory only when we run `cargo test`. Run `cargo test` now:
```
$ cargo test
Compiling adder v0.1.0 (file:///projects/adder)
Finished test [unoptimized + debuginfo] target(s) in 1.31s
- Running unittests (target/debug/deps/adder-1082c4b063a8fbe6)
+ Running unittests src/lib.rs (target/debug/deps/adder-
+1082c4b063a8fbe6)
-[1] running 1 test
+1 running 1 test
test tests::internal ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
- [2] Running tests/integration_test.rs (target/debug/deps/integration_test-1082c4b063a8fbe6)
+ 2 Running tests/integration_test.rs
+(target/debug/deps/integration_test-1082c4b063a8fbe6)
running 1 test
-[3] test it_adds_two ... ok
+3 test it_adds_two ... ok
-[4] test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+4 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
Doc-tests adder
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
The three sections of output include the unit tests, the integration test, and
@@ -1386,12 +1434,14 @@ followed by the name of the file:
```
$ cargo test --test integration_test
Finished test [unoptimized + debuginfo] target(s) in 0.64s
- Running tests/integration_test.rs (target/debug/deps/integration_test-82e7799c1bc62298)
+ Running tests/integration_test.rs
+(target/debug/deps/integration_test-82e7799c1bc62298)
running 1 test
test it_adds_two ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
This command runs only the tests in the *tests/integration_test.rs* file.
@@ -1409,11 +1459,11 @@ regarding how to separate code into modules and files.
The different behavior of *tests* directory files is most noticeable when you
have a set of helper functions to use in multiple integration test files and
-you try to follow the steps in the “Separating Modules into Different Files”
-section of Chapter 7 to extract them into a common module. For example, if we
-create *tests/common.rs* and place a function named `setup` in it, we can add
-some code to `setup` that we want to call from multiple test functions in
-multiple test files:
+you try to follow the steps in “Separating Modules into Different Files” on
+page XX to extract them into a common module. For example, if we create
+*tests/common.rs* and place a function named `setup` in it, we can add some
+code to `setup` that we want to call from multiple test functions in multiple
+test files:
Filename: tests/common.rs
@@ -1431,53 +1481,58 @@ did we call the `setup` function from anywhere:
running 1 test
test tests::internal ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
- Running tests/common.rs (target/debug/deps/common-92948b65e88960b4)
+ Running tests/common.rs (target/debug/deps/common-
+92948b65e88960b4)
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
- Running tests/integration_test.rs (target/debug/deps/integration_test-92948b65e88960b4)
+ Running tests/integration_test.rs
+(target/debug/deps/integration_test-92948b65e88960b4)
running 1 test
test it_adds_two ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
Doc-tests adder
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Having `common` appear in the test results with `running 0 tests` displayed for
it is not what we wanted. We just wanted to share some code with the other
-integration test files.
-To avoid having `common` appear in the test output, instead of creating
-*tests/common.rs*, we’ll create *tests/common/mod.rs*. The project directory
-now looks like this:
+integration test files. To avoid having `common` appear in the test output,
+instead of creating *tests/common.rs*, we’ll create *tests/common/mod.rs*. The
+project directory now looks like this:
```
├── Cargo.lock
├── Cargo.toml
├── src
-│   └── lib.rs
+│ └── lib.rs
└── tests
├── common
- │   └── mod.rs
+ │ └── mod.rs
└── integration_test.rs
```
This is the older naming convention that Rust also understands that we
-mentioned in the “Alternate File Paths” section of Chapter 7. Naming the file
-this way tells Rust not to treat the `common` module as an integration test
-file. When we move the `setup` function code into *tests/common/mod.rs* and
-delete the *tests/common.rs* file, the section in the test output will no
-longer appear. Files in subdirectories of the *tests* directory don’t get
-compiled as separate crates or have sections in the test output.
+mentioned in “Alternate File Paths” on page XX. Naming the file this way tells
+Rust not to treat the `common` module as an integration test file. When we move
+the `setup` function code into *tests/common/mod.rs* and delete the
+*tests/common.rs* file, the section in the test output will no longer appear.
+Files in subdirectories of the *tests* directory don’t get compiled as separate
+crates or have sections in the test output.
After we’ve created *tests/common/mod.rs*, we can use it from any of the
integration test files as a module. Here’s an example of calling the `setup`
@@ -1498,7 +1553,7 @@ fn it_adds_two() {
```
Note that the `mod common;` declaration is the same as the module declaration
-we demonstrated in Listing 7-21. Then in the test function, we can call the
+we demonstrated in Listing 7-21. Then, in the test function, we can call the
`common::setup()` function.
#### Integration Tests for Binary Crates
@@ -1512,10 +1567,9 @@ crates can use; binary crates are meant to be run on their own.
This is one of the reasons Rust projects that provide a binary have a
straightforward *src/main.rs* file that calls logic that lives in the
*src/lib.rs* file. Using that structure, integration tests *can* test the
-library crate with `use` to make the important functionality available.
-If the important functionality works, the small amount of code in the
-*src/main.rs* file will work as well, and that small amount of code doesn’t
-need to be tested.
+library crate with `use` to make the important functionality available. If the
+important functionality works, the small amount of code in the *src/main.rs*
+file will work as well, and that small amount of code doesn’t need to be tested.
## Summary
@@ -1531,11 +1585,3 @@ reduce logic bugs having to do with how your code is expected to behave.
Let’s combine the knowledge you learned in this chapter and in previous
chapters to work on a project!
-<!---
-We hint at doc tests but don't cover them. Should we have a section in this
-chapter about that? They're pretty handy.
-/JT --->
-<!-- We cover that in chapter 14, and there's a forward reference to that in
-"The Anatomy of a Test Function" section. I don't actually think most Rust
-developers will write doc tests; they're the most useful when writing open
-source libraries, which I think only a minority of developers do. /Carol -->
diff --git a/src/doc/book/nostarch/chapter12.md b/src/doc/book/nostarch/chapter12.md
index 950b2e999..86e986173 100644
--- a/src/doc/book/nostarch/chapter12.md
+++ b/src/doc/book/nostarch/chapter12.md
@@ -26,8 +26,8 @@ Along the way, we’ll show how to make our command line tool use the terminal
features that many other command line tools use. We’ll read the value of an
environment variable to allow the user to configure the behavior of our tool.
We’ll also print error messages to the standard error console stream (`stderr`)
-instead of standard output (`stdout`), so, for example, the user can redirect
-successful output to a file while still seeing error messages onscreen.
+instead of standard output (`stdout`) so that, for example, the user can
+redirect successful output to a file while still seeing error messages onscreen.
One Rust community member, Andrew Gallant, has already created a fully
featured, very fast version of `grep`, called `ripgrep`. By comparison, our
@@ -37,14 +37,14 @@ background knowledge you need to understand a real-world project such as
Our `grep` project will combine a number of concepts you’ve learned so far:
-* Organizing code (using what you learned about modules in Chapter 7)
-* Using vectors and strings (collections, Chapter 8)
+* Organizing code (Chapter 7)
+* Using vectors and strings (Chapter 8)
* Handling errors (Chapter 9)
* Using traits and lifetimes where appropriate (Chapter 10)
* Writing tests (Chapter 11)
We’ll also briefly introduce closures, iterators, and trait objects, which
-Chapters 13 and 17 will cover in detail.
+Chapter 13 and Chapter 17 will cover in detail.
## Accepting Command Line Arguments
@@ -69,8 +69,8 @@ $ cargo run -- searchstring example-filename.txt
```
Right now, the program generated by `cargo new` cannot process arguments we
-give it. Some existing libraries on *https://crates.io/* can help with writing
-a program that accepts command line arguments, but because you’re just learning
+give it. Some existing libraries on *https://crates.io* can help with writing a
+program that accepts command line arguments, but because you’re just learning
this concept, let’s implement this capability ourselves.
### Reading the Argument Values
@@ -85,7 +85,7 @@ collection, such as a vector, that contains all the elements the iterator
produces.
The code in Listing 12-1 allows your `minigrep` program to read any command
-line arguments passed to it and then collect the values into a vector.
+line arguments passed to it, and then collect the values into a vector.
Filename: src/main.rs
@@ -101,7 +101,7 @@ fn main() {
Listing 12-1: Collecting the command line arguments into a vector and printing
them
-First, we bring the `std::env` module into scope with a `use` statement so we
+First we bring the `std::env` module into scope with a `use` statement so we
can use its `args` function. Notice that the `std::env::args` function is
nested in two levels of modules. As we discussed in Chapter 7, in cases where
the desired function is nested in more than one module, we’ve chosen to bring
@@ -111,20 +111,20 @@ adding `use std::env::args` and then calling the function with just `args`,
because `args` might easily be mistaken for a function that’s defined in the
current module.
-> ### The `args` Function and Invalid Unicode
+> ### The args Function and Invalid Unicode
>
> Note that `std::env::args` will panic if any argument contains invalid
-> Unicode. If your program needs to accept arguments containing invalid
-> Unicode, use `std::env::args_os` instead. That function returns an iterator
-> that produces `OsString` values instead of `String` values. We’ve chosen to
-> use `std::env::args` here for simplicity, because `OsString` values differ
-> per platform and are more complex to work with than `String` values.
+Unicode. If your program needs to accept arguments containing invalid Unicode,
+use `std::env::args_os` instead. That function returns an iterator that
+produces `OsString` values instead of `String` values. We’ve chosen to use
+`std::env::args` here for simplicity because `OsString` values differ per
+platform and are more complex to work with than `String` values.
On the first line of `main`, we call `env::args`, and we immediately use
`collect` to turn the iterator into a vector containing all the values produced
by the iterator. We can use the `collect` function to create many kinds of
collections, so we explicitly annotate the type of `args` to specify that we
-want a vector of strings. Although we very rarely need to annotate types in
+want a vector of strings. Although you very rarely need to annotate types in
Rust, `collect` is one function you do often need to annotate because Rust
isn’t able to infer the kind of collection you want.
@@ -137,9 +137,6 @@ $ cargo run
[src/main.rs:5] args = [
"target/debug/minigrep",
]
-```
-
-```
$ cargo run -- needle haystack
--snip--
[src/main.rs:5] args = [
@@ -153,8 +150,8 @@ Notice that the first value in the vector is `"target/debug/minigrep"`, which
is the name of our binary. This matches the behavior of the arguments list in
C, letting programs use the name by which they were invoked in their execution.
It’s often convenient to have access to the program name in case you want to
-print it in messages or change behavior of the program based on what command
-line alias was used to invoke the program. But for the purposes of this
+print it in messages or change the behavior of the program based on what
+command line alias was used to invoke the program. But for the purposes of this
chapter, we’ll ignore it and save only the two arguments we need.
### Saving the Argument Values in Variables
@@ -184,7 +181,7 @@ Listing 12-2: Creating variables to hold the query argument and file path
argument
As we saw when we printed the vector, the program’s name takes up the first
-value in the vector at `args[0]`, so we’re starting arguments at index `1`. The
+value in the vector at `args[0]`, so we’re starting arguments at index 1. The
first argument `minigrep` takes is the string we’re searching for, so we put a
reference to the first argument in the variable `query`. The second argument
will be the file path, so we put a reference to the second argument in the
@@ -212,7 +209,7 @@ capabilities instead.
## Reading a File
Now we’ll add functionality to read the file specified in the `file_path`
-argument. First, we need a sample file to test it with: we’ll use a file with a
+argument. First we need a sample file to test it with: we’ll use a file with a
small amount of text over multiple lines with some repeated words. Listing 12-3
has an Emily Dickinson poem that will work well! Create a file called
*poem.txt* at the root level of your project, and enter the poem “I’m Nobody!
@@ -232,7 +229,7 @@ To tell your name the livelong day
To an admiring bog!
```
-Listing 12-3: A poem by Emily Dickinson makes a good test case
+Listing 12-3: A poem by Emily Dickinson makes a good test case.
With the text in place, edit *src/main.rs* and add code to read the file, as
shown in Listing 12-4.
@@ -241,26 +238,26 @@ Filename: src/main.rs
```
use std::env;
-[1] use std::fs;
+1 use std::fs;
fn main() {
- // --snip--
+ --snip--
println!("In file {}", file_path);
- [2] let contents = fs::read_to_string(file_path)
+ 2 let contents = fs::read_to_string(file_path)
.expect("Should have been able to read the file");
- [3] println!("With text:\n{contents}");
+ 3 println!("With text:\n{contents}");
}
```
Listing 12-4: Reading the contents of the file specified by the second argument
-First, we bring in a relevant part of the standard library with a `use`
+First we bring in a relevant part of the standard library with a `use`
statement: we need `std::fs` to handle files [1].
In `main`, the new statement `fs::read_to_string` takes the `file_path`, opens
-that file, and returns a `std::io::Result<String>` of the file’s contents [2].
+that file, and returns an `std::io::Result<String>` of the file’s contents [2].
After that, we again add a temporary `println!` statement that prints the value
of `contents` after the file is read, so we can check that the program is
@@ -295,9 +292,9 @@ responsibilities: generally, functions are clearer and easier to maintain if
each function is responsible for only one idea. The other problem is that we’re
not handling errors as well as we could. The program is still small, so these
flaws aren’t a big problem, but as the program grows, it will be harder to fix
-them cleanly. It’s good practice to begin refactoring early on when developing
-a program, because it’s much easier to refactor smaller amounts of code. We’ll
-do that next.
+them cleanly. It’s a good practice to begin refactoring early on when
+developing a program because it’s much easier to refactor smaller amounts of
+code. We’ll do that next.
## Refactoring to Improve Modularity and Error Handling
@@ -342,12 +339,12 @@ community has developed guidelines for splitting the separate concerns of a
binary program when `main` starts getting large. This process has the following
steps:
-* Split your program into a *main.rs* and a *lib.rs* and move your program’s
- logic to *lib.rs*.
+* Split your program into a *main.rs* file and a *lib.rs* file and move your
+program’s logic to *lib.rs*.
* As long as your command line parsing logic is small, it can remain in
- *main.rs*.
+*main.rs*.
* When the command line parsing logic starts getting complicated, extract it
- from *main.rs* and move it to *lib.rs*.
+from *main.rs* and move it to *lib.rs*.
The responsibilities that remain in the `main` function after this process
should be limited to the following:
@@ -358,7 +355,7 @@ should be limited to the following:
* Handling the error if `run` returns an error
This pattern is about separating concerns: *main.rs* handles running the
-program, and *lib.rs* handles all the logic of the task at hand. Because you
+program and *lib.rs* handles all the logic of the task at hand. Because you
can’t test the `main` function directly, this structure lets you test all of
your program’s logic by moving it into functions in *lib.rs*. The code that
remains in *main.rs* will be small enough to verify its correctness by reading
@@ -368,7 +365,7 @@ it. Let’s rework our program by following this process.
We’ll extract the functionality for parsing arguments into a function that
`main` will call to prepare for moving the command line parsing logic to
-*src/lib.rs*. Listing 12-5 shows the new start of `main` that calls a new
+src/lib.rs*. Listing 12-5 shows the new start of `main` that calls a new
function `parse_config`, which we’ll define in *src/main.rs* for the moment.
Filename: src/main.rs
@@ -379,7 +376,7 @@ fn main() {
let (query, file_path) = parse_config(&args);
- // --snip--
+ --snip--
}
fn parse_config(args: &[String]) -> (&str, &str) {
@@ -431,25 +428,25 @@ Filename: src/main.rs
fn main() {
let args: Vec<String> = env::args().collect();
- [1] let config = parse_config(&args);
+ 1 let config = parse_config(&args);
- println!("Searching for {}", config.query[2]);
- println!("In file {}", config.file_path[3]);
+ println!("Searching for {}", 2 config.query);
+ println!("In file {}", 3 config.file_path);
- let contents = fs::read_to_string(config.file_path[4])
+ let contents = fs::read_to_string(4 config.file_path)
.expect("Should have been able to read the file");
- // --snip--
+ --snip--
}
-[5] struct Config {
+5 struct Config {
query: String,
file_path: String,
}
-[6] fn parse_config(args: &[String]) -> Config {
- [7] let query = args[1].clone();
- [8] let file_path = args[2].clone();
+6 fn parse_config(args: &[String]) -> Config {
+ 7 let query = args[1].clone();
+ 8 let file_path = args[2].clone();
Config { query, file_path }
}
@@ -459,8 +456,8 @@ Listing 12-6: Refactoring `parse_config` to return an instance of a `Config`
struct
We’ve added a struct named `Config` defined to have fields named `query` and
-`file_path` [5]. The signature of `parse_config` now indicates that it returns a
-`Config` value [6]. In the body of `parse_config`, where we used to return
+`file_path` [5]. The signature of `parse_config` now indicates that it returns
+a `Config` value [6]. In the body of `parse_config`, where we used to return
string slices that reference `String` values in `args`, we now define `Config`
to contain owned `String` values. The `args` variable in `main` is the owner of
the argument values and is only letting the `parse_config` function borrow
@@ -469,44 +466,43 @@ ownership of the values in `args`.
There are a number of ways we could manage the `String` data; the easiest,
though somewhat inefficient, route is to call the `clone` method on the values
-[7][8]. This will make a full copy of the data for the `Config` instance to
+[7] [8]. This will make a full copy of the data for the `Config` instance to
own, which takes more time and memory than storing a reference to the string
data. However, cloning the data also makes our code very straightforward
because we don’t have to manage the lifetimes of the references; in this
circumstance, giving up a little performance to gain simplicity is a worthwhile
trade-off.
-> ### The Trade-Offs of Using `clone`
+> ### The Trade-Offs of Using clone
>
> There’s a tendency among many Rustaceans to avoid using `clone` to fix
-> ownership problems because of its runtime cost. In
-> Chapter 13, you’ll learn how to use more efficient
-> methods in this type of situation. But for now, it’s okay to copy a few
-> strings to continue making progress because you’ll make these copies only
-> once and your file path and query string are very small. It’s better to have
-> a working program that’s a bit inefficient than to try to hyperoptimize code
-> on your first pass. As you become more experienced with Rust, it’ll be
-> easier to start with the most efficient solution, but for now, it’s
-> perfectly acceptable to call `clone`.
+ownership problems because of its runtime cost. In Chapter 13, you’ll learn how
+to use more efficient methods in this type of situation. But for now, it’s okay
+to copy a few strings to continue making progress because you’ll make these
+copies only once and your file path and query string are very small. It’s
+better to have a working program that’s a bit inefficient than to try to
+hyperoptimize code on your first pass. As you become more experienced with
+Rust, it’ll be easier to start with the most efficient solution, but for now,
+it’s perfectly acceptable to call `clone`.
We’ve updated `main` so it places the instance of `Config` returned by
`parse_config` into a variable named `config` [1], and we updated the code that
previously used the separate `query` and `file_path` variables so it now uses
-the fields on the `Config` struct instead [2][3][4].
+the fields on the `Config` struct instead [2] [3] [4].
Now our code more clearly conveys that `query` and `file_path` are related and
that their purpose is to configure how the program will work. Any code that
uses these values knows to find them in the `config` instance in the fields
named for their purpose.
-#### Creating a Constructor for `Config`
+#### Creating a Constructor for Config
So far, we’ve extracted the logic responsible for parsing the command line
arguments from `main` and placed it in the `parse_config` function. Doing so
-helped us to see that the `query` and `file_path` values were related and that
+helped us see that the `query` and `file_path` values were related, and that
relationship should be conveyed in our code. We then added a `Config` struct to
-name the related purpose of `query` and `file_path` and to be able to return the
-values’ names as struct field names from the `parse_config` function.
+name the related purpose of `query` and `file_path` and to be able to return
+the values’ names as struct field names from the `parse_config` function.
So now that the purpose of the `parse_config` function is to create a `Config`
instance, we can change `parse_config` from a plain function to a function
@@ -523,15 +519,15 @@ Filename: src/main.rs
fn main() {
let args: Vec<String> = env::args().collect();
- [1] let config = Config::new(&args);
+ 1 let config = Config::new(&args);
- // --snip--
+ --snip--
}
-// --snip--
+--snip--
-[2] impl Config {
- [3] fn new(args: &[String]) -> Config {
+2 impl Config {
+ 3 fn new(args: &[String]) -> Config {
let query = args[1].clone();
let file_path = args[2].clone();
@@ -559,8 +555,10 @@ $ cargo run
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep`
-thread 'main' panicked at 'index out of bounds: the len is 1 but the index is 1', src/main.rs:27:21
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'index out of bounds: the len is 1 but
+the index is 1', src/main.rs:27:21
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
```
The line `index out of bounds: the len is 1 but the index is 1` is an error
@@ -570,18 +568,18 @@ they should do instead. Let’s fix that now.
#### Improving the Error Message
In Listing 12-8, we add a check in the `new` function that will verify that the
-slice is long enough before accessing index 1 and 2. If the slice isn’t long
-enough, the program panics and displays a better error message.
+slice is long enough before accessing index 1 and index 2. If the slice isn’t
+long enough, the program panics and displays a better error message.
Filename: src/main.rs
```
-// --snip--
+--snip--
fn new(args: &[String]) -> Config {
if args.len() < 3 {
panic!("not enough arguments");
}
- // --snip--
+ --snip--
```
Listing 12-8: Adding a check for the number of arguments
@@ -589,9 +587,9 @@ Listing 12-8: Adding a check for the number of arguments
This code is similar to the `Guess::new` function we wrote in Listing 9-13,
where we called `panic!` when the `value` argument was out of the range of
valid values. Instead of checking for a range of values here, we’re checking
-that the length of `args` is at least 3 and the rest of the function can
+that the length of `args` is at least `3` and the rest of the function can
operate under the assumption that this condition has been met. If `args` has
-fewer than three items, this condition will be true, and we call the `panic!`
+fewer than three items, this condition will be `true`, and we call the `panic!`
macro to end the program immediately.
With these extra few lines of code in `new`, let’s run the program without any
@@ -602,19 +600,21 @@ $ cargo run
Compiling minigrep v0.1.0 (file:///projects/minigrep)
Finished dev [unoptimized + debuginfo] target(s) in 0.0s
Running `target/debug/minigrep`
-thread 'main' panicked at 'not enough arguments', src/main.rs:26:13
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'not enough arguments',
+src/main.rs:26:13
+note: run with `RUST_BACKTRACE=1` environment variable to display
+a backtrace
```
This output is better: we now have a reasonable error message. However, we also
-have extraneous information we don’t want to give to our users. Perhaps using
-the technique we used in Listing 9-13 isn’t the best to use here: a call to
+have extraneous information we don’t want to give to our users. Perhaps the
+technique we used in Listing 9-13 isn’t the best one to use here: a call to
`panic!` is more appropriate for a programming problem than a usage problem, as
discussed in Chapter 9. Instead, we’ll use the other technique you learned
about in Chapter 9—returning a `Result` that indicates either success or an
error.
-#### Returning a `Result` Instead of Calling `panic!`
+#### Returning a Result Instead of Calling panic!
We can instead return a `Result` value that will contain a `Config` instance in
the successful case and will describe the problem in the error case. We’re also
@@ -650,7 +650,7 @@ impl Config {
Listing 12-9: Returning a `Result` from `Config::build`
Our `build` function returns a `Result` with a `Config` instance in the success
-case and a `&'static str` in the error case. Our error values will always be
+case and an `&'static str` in the error case. Our error values will always be
string literals that have the `'static` lifetime.
We’ve made two changes in the body of the function: instead of calling `panic!`
@@ -662,7 +662,7 @@ Returning an `Err` value from `Config::build` allows the `main` function to
handle the `Result` value returned from the `build` function and exit the
process more cleanly in the error case.
-#### Calling `Config::build` and Handling Errors
+#### Calling Config::build and Handling Errors
To handle the error case and print a user-friendly message, we need to update
`main` to handle the `Result` being returned by `Config::build`, as shown in
@@ -674,17 +674,17 @@ called our program that the program exited with an error state.
Filename: src/main.rs
```
-[1] use std::process;
+1 use std::process;
fn main() {
let args: Vec<String> = env::args().collect();
- [2] let config = Config::build(&args).unwrap_or_else([3]|err[4]| {
- [5] println!("Problem parsing arguments: {err}");
- [6] process::exit(1);
+ 2 let config = Config::build(&args).3 unwrap_or_else(|4 err| {
+ 5 println!("Problem parsing arguments: {err}");
+ 6 process::exit(1);
});
- // --snip--
+ --snip--
```
Listing 12-10: Exiting with an error code if building a `Config` fails
@@ -693,11 +693,11 @@ In this listing, we’ve used a method we haven’t covered in detail yet:
`unwrap_or_else`, which is defined on `Result<T, E>` by the standard library
[2]. Using `unwrap_or_else` allows us to define some custom, non-`panic!` error
handling. If the `Result` is an `Ok` value, this method’s behavior is similar
-to `unwrap`: it returns the inner value `Ok` is wrapping. However, if the value
-is an `Err` value, this method calls the code in the *closure*, which is an
-anonymous function we define and pass as an argument to `unwrap_or_else` [3].
-We’ll cover closures in more detail in Chapter 13. For now, you just need to
-know that `unwrap_or_else` will pass the inner value of the `Err`, which in
+to `unwrap`: it returns the inner value that `Ok` is wrapping. However, if the
+value is an `Err` value, this method calls the code in the *closure*, which is
+an anonymous function we define and pass as an argument to `unwrap_or_else`
+[3]. We’ll cover closures in more detail in Chapter 13. For now, you just need
+to know that `unwrap_or_else` will pass the inner value of the `Err`, which in
this case is the static string `"not enough arguments"` that we added in
Listing 12-9, to our closure in the argument `err` that appears between the
vertical pipes [4]. The code in the closure can then use the `err` value when
@@ -721,12 +721,12 @@ Problem parsing arguments: not enough arguments
Great! This output is much friendlier for our users.
-### Extracting Logic from `main`
+### Extracting Logic from main
Now that we’ve finished refactoring the configuration parsing, let’s turn to
the program’s logic. As we stated in “Separation of Concerns for Binary
-Projects”, we’ll extract a function named `run` that will hold all the logic
-currently in the `main` function that isn’t involved with setting up
+Projects” on page XX, we’ll extract a function named `run` that will hold all
+the logic currently in the `main` function that isn’t involved with setting up
configuration or handling errors. When we’re done, `main` will be concise and
easy to verify by inspection, and we’ll be able to write tests for all the
other logic.
@@ -739,7 +739,7 @@ Filename: src/main.rs
```
fn main() {
- // --snip--
+ --snip--
println!("Searching for {}", config.query);
println!("In file {}", config.file_path);
@@ -754,7 +754,7 @@ fn run(config: Config) {
println!("With text:\n{contents}");
}
-// --snip--
+--snip--
```
Listing 12-11: Extracting a `run` function containing the rest of the program
@@ -764,7 +764,7 @@ The `run` function now contains all the remaining logic from `main`, starting
from reading the file. The `run` function takes the `Config` instance as an
argument.
-#### Returning Errors from the `run` Function
+#### Returning Errors from the run Function
With the remaining program logic separated into the `run` function, we can
improve the error handling, as we did with `Config::build` in Listing 12-9.
@@ -777,25 +777,25 @@ signature and body of `run`.
Filename: src/main.rs
```
-[1] use std::error::Error;
+1 use std::error::Error;
-// --snip--
+--snip--
-[2] fn run(config: Config) -> Result<(), Box<dyn Error>> {
- let contents = fs::read_to_string(config.file_path)?[3];
+2 fn run(config: Config) -> Result<(), Box<dyn Error>> {
+ let contents = fs::read_to_string(config.file_path)3 ?;
println!("With text:\n{contents}");
- [4] Ok(())
+ 4 Ok(())
}
```
Listing 12-12: Changing the `run` function to return `Result`
We’ve made three significant changes here. First, we changed the return type of
-the `run` function to `Result<(), Box<dyn Error>>` [2]. This function previously
-returned the unit type, `()`, and we keep that as the value returned in the
-`Ok` case.
+the `run` function to `Result<(), Box<dyn Error>>` [2]. This function
+previously returned the unit type, `()`, and we keep that as the value returned
+in the `Ok` case.
For the error type, we used the *trait object* `Box<dyn Error>` (and we’ve
brought `std::error::Error` into scope with a `use` statement at the top [1]).
@@ -803,7 +803,7 @@ We’ll cover trait objects in Chapter 17. For now, just know that `Box<dyn
Error>` means the function will return a type that implements the `Error`
trait, but we don’t have to specify what particular type the return value will
be. This gives us flexibility to return error values that may be of different
-types in different error cases. The `dyn` keyword is short for “dynamic.”
+types in different error cases. The `dyn` keyword is short for *dynamic*.
Second, we’ve removed the call to `expect` in favor of the `?` operator [3], as
we talked about in Chapter 9. Rather than `panic!` on an error, `?` will return
@@ -826,7 +826,8 @@ warning: unused `Result` that must be used
| ^^^^^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
- = note: this `Result` may be an `Err` variant, which should be handled
+ = note: this `Result` may be an `Err` variant, which should be
+handled
```
Rust tells us that our code ignored the `Result` value and the `Result` value
@@ -834,7 +835,7 @@ might indicate that an error occurred. But we’re not checking to see whether o
not there was an error, and the compiler reminds us that we probably meant to
have some error-handling code here! Let’s rectify that problem now.
-#### Handling Errors Returned from `run` in `main`
+#### Handling Errors Returned from run in main
We’ll check for errors and handle them using a technique similar to one we used
with `Config::build` in Listing 12-10, but with a slight difference:
@@ -843,7 +844,7 @@ Filename: src/main.rs
```
fn main() {
- // --snip--
+ --snip--
println!("Searching for {}", config.query);
println!("In file {}", config.file_path);
@@ -856,11 +857,11 @@ fn main() {
```
We use `if let` rather than `unwrap_or_else` to check whether `run` returns an
-`Err` value and call `process::exit(1)` if it does. The `run` function doesn’t
-return a value that we want to `unwrap` in the same way that `Config::build`
-returns the `Config` instance. Because `run` returns `()` in the success case,
-we only care about detecting an error, so we don’t need `unwrap_or_else` to
-return the unwrapped value, which would only be `()`.
+`Err` value and to call `process::exit(1)` if it does. The `run` function
+doesn’t return a value that we want to `unwrap` in the same way that
+`Config::build` returns the `Config` instance. Because `run` returns `()` in
+the success case, we only care about detecting an error, so we don’t need
+`unwrap_or_else` to return the unwrapped value, which would only be `()`.
The bodies of the `if let` and the `unwrap_or_else` functions are the same in
both cases: we print the error and exit.
@@ -868,10 +869,10 @@ both cases: we print the error and exit.
### Splitting Code into a Library Crate
Our `minigrep` project is looking good so far! Now we’ll split the
-*src/main.rs* file and put some code into the *src/lib.rs* file. That way we
+*src/main.rs* file and put some code into the *src/lib.rs* file. That way, we
can test the code and have a *src/main.rs* file with fewer responsibilities.
-Let’s move all the code that isn’t the `main` function from *src/main.rs* to
+Let’s move all the code that isn’t in the `main` function from *src/main.rs* to
*src/lib.rs*:
* The `run` function definition
@@ -895,13 +896,15 @@ pub struct Config {
}
impl Config {
- pub fn build(args: &[String]) -> Result<Config, &'static str> {
- // --snip--
+ pub fn build(
+ args: &[String],
+ ) -> Result<Config, &'static str> {
+ --snip--
}
}
pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
- // --snip--
+ --snip--
}
```
@@ -923,9 +926,9 @@ use std::process;
use minigrep::Config;
fn main() {
- // --snip--
+ --snip--
if let Err(e) = minigrep::run(config) {
- // --snip--
+ --snip--
}
}
```
@@ -935,8 +938,7 @@ Listing 12-14: Using the `minigrep` library crate in *src/main.rs*
We add a `use minigrep::Config` line to bring the `Config` type from the
library crate into the binary crate’s scope, and we prefix the `run` function
with our crate name. Now all the functionality should be connected and should
-work. Run the program with `cargo run` and make sure everything works
-correctly.
+work. Run the program with `cargo run` and make sure everything works correctly.
Whew! That was a lot of work, but we’ve set ourselves up for success in the
future. Now it’s much easier to handle errors, and we’ve made the code more
@@ -954,21 +956,21 @@ for the core functionality of our code. We can call functions directly with
various arguments and check return values without having to call our binary
from the command line.
-In this section, we’ll add the searching logic to the `minigrep` program
-using the test-driven development (TDD) process with the following steps:
+In this section, we’ll add the searching logic to the `minigrep` program using
+the test-driven development (TDD) process with the following steps:
1. Write a test that fails and run it to make sure it fails for the reason you
- expect.
-2. Write or modify just enough code to make the new test pass.
-3. Refactor the code you just added or changed and make sure the tests
- continue to pass.
-4. Repeat from step 1!
+expect.
+1. Write or modify just enough code to make the new test pass.
+1. Refactor the code you just added or changed and make sure the tests continue
+to pass.
+1. Repeat from step 1!
Though it’s just one of many ways to write software, TDD can help drive code
design. Writing the test before you write the code that makes the test pass
helps to maintain high test coverage throughout the process.
-We’ll test drive the implementation of the functionality that will actually do
+We’ll test-drive the implementation of the functionality that will actually do
the searching for the query string in the file contents and produce a list of
lines that match the query. We’ll add this functionality in a function called
`search`.
@@ -977,11 +979,11 @@ lines that match the query. We’ll add this functionality in a function called
Because we don’t need them anymore, let’s remove the `println!` statements from
*src/lib.rs* and *src/main.rs* that we used to check the program’s behavior.
-Then, in *src/lib.rs*, add a `tests` module with a test function, as we did in
-Chapter 11. The test function specifies the behavior we want the `search`
-function to have: it will take a query and the text to search, and it will
-return only the lines from the text that contain the query. Listing 12-15 shows
-this test, which won’t compile yet.
+Then, in *src/lib.rs*, we’ll add a `tests` module with a test function, as we
+did in Chapter 11. The test function specifies the behavior we want the
+`search` function to have: it will take a query and the text to search, and it
+will return only the lines from the text that contain the query. Listing 12-15
+shows this test, which won’t compile yet.
Filename: src/lib.rs
@@ -998,7 +1000,10 @@ Rust:
safe, fast, productive.
Pick three.";
- assert_eq!(vec!["safe, fast, productive."], search(query, contents));
+ assert_eq!(
+ vec!["safe, fast, productive."],
+ search(query, contents)
+ );
}
}
```
@@ -1006,7 +1011,7 @@ Pick three.";
Listing 12-15: Creating a failing test for the `search` function we wish we had
This test searches for the string `"duct"`. The text we’re searching is three
-lines, only one of which contains `"duct"` (Note that the backslash after the
+lines, only one of which contains `"duct"` (note that the backslash after the
opening double quote tells Rust not to put a newline character at the beginning
of the contents of this string literal). We assert that the value returned from
the `search` function contains only the line we expect.
@@ -1017,12 +1022,15 @@ principles, we’ll add just enough code to get the test to compile and run by
adding a definition of the `search` function that always returns an empty
vector, as shown in Listing 12-16. Then the test should compile and fail
because an empty vector doesn’t match a vector containing the line `"safe,
-fast, productive."`
+fast, productive."`.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
vec![]
}
```
@@ -1049,16 +1057,24 @@ get this error:
```
error[E0106]: missing lifetime specifier
- --> src/lib.rs:28:51
+ --> src/lib.rs:31:10
|
-28 | pub fn search(query: &str, contents: &str) -> Vec<&str> {
- | ---- ---- ^ expected named lifetime parameter
+29 | query: &str,
+ | ----
+30 | contents: &str,
+ | ----
+31 | ) -> Vec<&str> {
+ | ^ expected named lifetime parameter
|
- = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `query` or `contents`
+ = help: this function's return type contains a borrowed value, but the
+signature does not say whether it is borrowed from `query` or `contents`
help: consider introducing a named lifetime parameter
|
-28 | pub fn search<'a>(query: &'a str, contents: &'a str) -> Vec<&'a str> {
- | ++++ ++ ++ ++
+28 ~ pub fn search<'a>(
+29 ~ query: &'a str,
+30 ~ contents: &'a str,
+31 ~ ) -> Vec<&'a str> {
+ |
```
Rust can’t possibly know which of the two arguments we need, so we need to tell
@@ -1069,8 +1085,8 @@ syntax.
Other programming languages don’t require you to connect arguments to return
values in the signature, but this practice will get easier over time. You might
-want to compare this example with the “Validating References with Lifetimes”
-section in Chapter 10.
+want to compare this example with the examples in “Validating References with
+Lifetimes” on page XX.
Now let’s run the test:
@@ -1086,16 +1102,17 @@ 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
+ right: `[]`', src/lib.rs:47:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::one_result
-test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
error: test failed, to rerun pass '--lib'
```
@@ -1107,24 +1124,27 @@ Great, the test fails, exactly as we expected. Let’s get the test to pass!
Currently, our test is failing because we always return an empty vector. To fix
that and implement `search`, our program needs to follow these steps:
-* Iterate through each line of the contents.
-* Check whether the line contains our query string.
-* If it does, add it to the list of values we’re returning.
-* If it doesn’t, do nothing.
-* Return the list of results that match.
+1. Iterate through each line of the contents.
+1. Check whether the line contains our query string.
+1. If it does, add it to the list of values we’re returning.
+1. If it doesn’t, do nothing.
+1. Return the list of results that match.
Let’s work through each step, starting with iterating through lines.
-#### Iterating Through Lines with the `lines` Method
+#### Iterating Through Lines with the lines Method
Rust has a helpful method to handle line-by-line iteration of strings,
-conveniently named `lines`, that works as shown in Listing 12-17. Note this
-won’t compile yet.
+conveniently named `lines`, that works as shown in Listing 12-17. Note that
+this won’t compile yet.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
for line in contents.lines() {
// do something with line
}
@@ -1143,12 +1163,15 @@ in a collection.
Next, we’ll check whether the current line contains our query string.
Fortunately, strings have a helpful method named `contains` that does this for
us! Add a call to the `contains` method in the `search` function, as shown in
-Listing 12-18. Note this still won’t compile yet.
+Listing 12-18. Note that this still won’t compile yet.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
for line in contents.lines() {
if line.contains(query) {
// do something with line
@@ -1160,8 +1183,8 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
Listing 12-18: Adding functionality to see whether the line contains the string
in `query`
-At the moment, we’re building up functionality. To get it to compile, we need
-to return a value from the body as we indicated we would in the function
+At the moment, we’re building up functionality. To get the code to compile, we
+need to return a value from the body as we indicated we would in the function
signature.
#### Storing Matching Lines
@@ -1174,7 +1197,10 @@ we return the vector, as shown in Listing 12-19.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
let mut results = Vec::new();
for line in contents.lines() {
@@ -1198,7 +1224,8 @@ $ cargo test
running 1 test
test tests::one_result ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Our test passed, so we know it works!
@@ -1210,7 +1237,7 @@ but it doesn’t take advantage of some useful features of iterators. We’ll
return to this example in Chapter 13, where we’ll explore iterators in detail,
and look at how to improve it.
-#### Using the `search` Function in the `run` Function
+#### Using the search Function in the run Function
Now that the `search` function is working and tested, we need to call `search`
from our `run` function. We need to pass the `config.query` value and the
@@ -1234,7 +1261,7 @@ pub fn run(config: Config) -> Result<(), Box<dyn Error>> {
We’re still using a `for` loop to return each line from `search` and print it.
Now the entire program should work! Let’s try it out, first with a word that
-should return exactly one line from the Emily Dickinson poem, “frog”:
+should return exactly one line from the Emily Dickinson poem: *frog*.
```
$ cargo run -- frog poem.txt
@@ -1244,7 +1271,7 @@ $ cargo run -- frog poem.txt
How public, like a frog
```
-Cool! Now let’s try a word that will match multiple lines, like “body”:
+Cool! Now let’s try a word that will match multiple lines, like *body*:
```
$ cargo run -- body poem.txt
@@ -1256,7 +1283,7 @@ How dreary to be somebody!
```
And finally, let’s make sure that we don’t get any lines when we search for a
-word that isn’t anywhere in the poem, such as “monomorphization”:
+word that isn’t anywhere in the poem, such as *monomorphization*:
```
$ cargo run -- monomorphization poem.txt
@@ -1281,7 +1308,7 @@ users enter it each time they want it to apply, but by instead making it an
environment variable, we allow our users to set the environment variable once
and have all their searches be case insensitive in that terminal session.
-### Writing a Failing Test for the Case-Insensitive `search` Function
+### Writing a Failing Test for the Case-Insensitive search Function
We first add a new `search_case_insensitive` function that will be called when
the environment variable has a value. We’ll continue to follow the TDD process,
@@ -1306,7 +1333,10 @@ safe, fast, productive.
Pick three.
Duct tape.";
- assert_eq!(vec!["safe, fast, productive."], search(query, contents));
+ assert_eq!(
+ vec!["safe, fast, productive."],
+ search(query, contents)
+ );
}
#[test]
@@ -1330,7 +1360,7 @@ Listing 12-20: Adding a new failing test for the case-insensitive function
we’re about to add
Note that we’ve edited the old test’s `contents` too. We’ve added a new line
-with the text `"Duct tape."` using a capital D that shouldn’t match the query
+with the text `"Duct tape."` using a capital *D* that shouldn’t match the query
`"duct"` when we’re searching in a case-sensitive manner. Changing the old test
in this way helps ensure that we don’t accidentally break the case-sensitive
search functionality that we’ve already implemented. This test should pass now
@@ -1338,18 +1368,18 @@ and should continue to pass as we work on the case-insensitive search.
The new test for the case-*insensitive* search uses `"rUsT"` as its query. In
the `search_case_insensitive` function we’re about to add, the query `"rUsT"`
-should match the line containing `"Rust:"` with a capital R and match the line
-`"Trust me."` even though both have different casing from the query. This is
-our failing test, and it will fail to compile because we haven’t yet defined
+should match the line containing `"Rust:"` with a capital *R* and match the
+line `"Trust me."` even though both have different casing from the query. This
+is our failing test, and it will fail to compile because we haven’t yet defined
the `search_case_insensitive` function. Feel free to add a skeleton
implementation that always returns an empty vector, similar to the way we did
for the `search` function in Listing 12-16 to see the test compile and fail.
-### Implementing the `search_case_insensitive` Function
+### Implementing the search_case_insensitive Function
The `search_case_insensitive` function, shown in Listing 12-21, will be almost
the same as the `search` function. The only difference is that we’ll lowercase
-the `query` and each `line` so whatever the case of the input arguments,
+the `query` and each `line` so that whatever the case of the input arguments,
they’ll be the same case when we check whether the line contains the query.
Filename: src/lib.rs
@@ -1359,11 +1389,11 @@ pub fn search_case_insensitive<'a>(
query: &str,
contents: &'a str,
) -> Vec<&'a str> {
- [1] let query = query.to_lowercase();
+ 1 let query = query.to_lowercase();
let mut results = Vec::new();
for line in contents.lines() {
- if line.to_lowercase()[2].contains(&query[3]) {
+ if 2 line.to_lowercase().contains(3 &query) {
results.push(line);
}
}
@@ -1375,8 +1405,8 @@ pub fn search_case_insensitive<'a>(
Listing 12-21: Defining the `search_case_insensitive` function to lowercase the
query and the line before comparing them
-First, we lowercase the `query` string and store it in a shadowed variable with
-the same name [1]. Calling `to_lowercase` on the query is necessary so no
+First we lowercase the `query` string and store it in a shadowed variable with
+the same name [1]. Calling `to_lowercase` on the query is necessary so that no
matter whether the user’s query is `"rust"`, `"RUST"`, `"Rust"`, or `"rUsT"`,
we’ll treat the query as if it were `"rust"` and be insensitive to the case.
While `to_lowercase` will handle basic Unicode, it won’t be 100% accurate. If
@@ -1384,7 +1414,7 @@ we were writing a real application, we’d want to do a bit more work here, but
this section is about environment variables, not Unicode, so we’ll leave it at
that here.
-Note that `query` is now a `String` rather than a string slice, because calling
+Note that `query` is now a `String` rather than a string slice because calling
`to_lowercase` creates new data rather than referencing existing data. Say the
query is `"rUsT"`, as an example: that string slice doesn’t contain a lowercase
`u` or `t` for us to use, so we have to allocate a new `String` containing
@@ -1403,14 +1433,15 @@ running 2 tests
test tests::case_insensitive ... ok
test tests::case_sensitive ... ok
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.00s
```
Great! They passed. Now, let’s call the new `search_case_insensitive` function
-from the `run` function. First, we’ll add a configuration option to the
-`Config` struct to switch between case-sensitive and case-insensitive search.
-Adding this field will cause compiler errors because we aren’t initializing
-this field anywhere yet:
+from the `run` function. First we’ll add a configuration option to the `Config`
+struct to switch between case-sensitive and case-insensitive search. Adding
+this field will cause compiler errors because we aren’t initializing this field
+anywhere yet:
Filename: src/lib.rs
@@ -1461,10 +1492,12 @@ Filename: src/lib.rs
```
use std::env;
-// --snip--
+--snip--
impl Config {
- pub fn build(args: &[String]) -> Result<Config, &'static str> {
+ pub fn build(
+ args: &[String]
+ ) -> Result<Config, &'static str> {
if args.len() < 3 {
return Err("not enough arguments");
}
@@ -1486,7 +1519,7 @@ impl Config {
Listing 12-23: Checking for any value in an environment variable named
`IGNORE_CASE`
-Here, we create a new variable `ignore_case`. To set its value, we call the
+Here, we create a new variable, `ignore_case`. To set its value, we call the
`env::var` function and pass it the name of the `IGNORE_CASE` environment
variable. The `env::var` function returns a `Result` that will be the
successful `Ok` variant that contains the value of the environment variable if
@@ -1496,7 +1529,7 @@ if the environment variable is not set.
We’re using the `is_ok` method on the `Result` to check whether the environment
variable is set, which means the program should do a case-insensitive search.
If the `IGNORE_CASE` environment variable isn’t set to anything, `is_ok` will
-return false and the program will perform a case-sensitive search. We don’t
+return `false` and the program will perform a case-sensitive search. We don’t
care about the *value* of the environment variable, just whether it’s set or
unset, so we’re checking `is_ok` rather than using `unwrap`, `expect`, or any
of the other methods we’ve seen on `Result`.
@@ -1505,9 +1538,9 @@ We pass the value in the `ignore_case` variable to the `Config` instance so the
`run` function can read that value and decide whether to call
`search_case_insensitive` or `search`, as we implemented in Listing 12-22.
-Let’s give it a try! First, we’ll run our program without the environment
+Let’s give it a try! First we’ll run our program without the environment
variable set and with the query `to`, which should match any line that contains
-the word “to” in all lowercase:
+the word *to* in all lowercase:
```
$ cargo run -- to poem.txt
@@ -1518,8 +1551,8 @@ Are you nobody, too?
How dreary to be somebody!
```
-Looks like that still works! Now, let’s run the program with `IGNORE_CASE`
-set to `1` but with the same query `to`.
+Looks like that still works! Now let’s run the program with `IGNORE_CASE` set
+to `1` but with the same query `to`:
```
$ IGNORE_CASE=1 cargo run -- to poem.txt
@@ -1532,14 +1565,14 @@ run the program as separate commands:
PS> $Env:IGNORE_CASE=1; cargo run -- to poem.txt
```
-This will make `IGNORE_CASE` persist for the remainder of your shell
-session. It can be unset with the `Remove-Item` cmdlet:
+This will make `IGNORE_CASE` persist for the remainder of your shell session.
+It can be unset with the `Remove-Item` cmdlet:
```
PS> Remove-Item Env:IGNORE_CASE
```
-We should get lines that contain “to” that might have uppercase letters:
+We should get lines that contain *to* that might have uppercase letters:
```
Are you nobody, too?
@@ -1548,7 +1581,7 @@ To tell your name the livelong day
To an admiring bog!
```
-Excellent, we also got lines containing “To”! Our `minigrep` program can now do
+Excellent, we also got lines containing *To*! Our `minigrep` program can now do
case-insensitive searching controlled by an environment variable. Now you know
how to manage options set using either command line arguments or environment
variables.
@@ -1573,12 +1606,12 @@ error messages. This distinction enables users to choose to direct the
successful output of a program to a file but still print error messages to the
screen.
-The `println!` macro is only capable of printing to standard output, so we
-have to use something else to print to standard error.
+The `println!` macro is only capable of printing to standard output, so we have
+to use something else to print to standard error.
### Checking Where Errors Are Written
-First, let’s observe how the content printed by `minigrep` is currently being
+First let’s observe how the content printed by `minigrep` is currently being
written to standard output, including any error messages we want to write to
standard error instead. We’ll do that by redirecting the standard output stream
to a file while intentionally causing an error. We won’t redirect the standard
@@ -1587,7 +1620,7 @@ the screen.
Command line programs are expected to send error messages to the standard error
stream so we can still see error messages on the screen even if we redirect the
-standard output stream to a file. Our program is not currently well-behaved:
+standard output stream to a file. Our program is not currently well behaved:
we’re about to see that it saves the error message output to a file instead!
To demonstrate this behavior, we’ll run the program with `>` and the file path,
@@ -1684,3 +1717,4 @@ well tested.
Next, we’ll explore some Rust features that were influenced by functional
languages: closures and iterators.
+
diff --git a/src/doc/book/nostarch/chapter13.md b/src/doc/book/nostarch/chapter13.md
index 8f7717ccb..52c1f5f97 100644
--- a/src/doc/book/nostarch/chapter13.md
+++ b/src/doc/book/nostarch/chapter13.md
@@ -23,15 +23,15 @@ More specifically, we’ll cover:
* *Closures*, a function-like construct you can store in a variable
* *Iterators*, a way of processing a series of elements
* How to use closures and iterators to improve the I/O project in Chapter 12
-* The performance of closures and iterators (Spoiler alert: they’re faster than
- you might think!)
+* The performance of closures and iterators (spoiler alert: they’re faster than
+you might think!)
We’ve already covered some other Rust features, such as pattern matching and
enums, that are also influenced by the functional style. Because mastering
closures and iterators is an important part of writing idiomatic, fast Rust
code, we’ll devote this entire chapter to them.
-## Closures: Anonymous Functions that Capture Their Environment
+## Closures: Anonymous Functions That Capture Their Environment
Rust’s closures are anonymous functions you can save in a variable or pass as
arguments to other functions. You can create the closure in one place and then
@@ -43,8 +43,8 @@ customization.
### Capturing the Environment with Closures
We’ll first examine how we can use closures to capture values from the
-environment they’re defined in for later use. Here’s the scenario: Every so
-often, our t-shirt company gives away an exclusive, limited-edition shirt to
+environment they’re defined in for later use. Here’s the scenario: every so
+often, our T-shirt company gives away an exclusive, limited-edition shirt to
someone on our mailing list as a promotion. People on the mailing list can
optionally add their favorite color to their profile. If the person chosen for
a free shirt has their favorite color set, they get that color shirt. If the
@@ -56,9 +56,9 @@ enum called `ShirtColor` that has the variants `Red` and `Blue` (limiting the
number of colors available for simplicity). We represent the company’s
inventory with an `Inventory` struct that has a field named `shirts` that
contains a `Vec<ShirtColor>` representing the shirt colors currently in stock.
-The method `giveaway` defined on `Inventory` gets the optional shirt
-color preference of the free shirt winner, and returns the shirt color the
-person will get. This setup is shown in Listing 13-1:
+The method `giveaway` defined on `Inventory` gets the optional shirt color
+preference of the free-shirt winner, and returns the shirt color the person
+will get. This setup is shown in Listing 13-1.
Filename: src/main.rs
@@ -74,8 +74,11 @@ struct Inventory {
}
impl Inventory {
- fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
- user_preference.unwrap_or_else(|| self.most_stocked()) [1]
+ fn giveaway(
+ &self,
+ user_preference: Option<ShirtColor>,
+ ) -> ShirtColor {
+ 1 user_preference.unwrap_or_else(|| self.most_stocked())
}
fn most_stocked(&self) -> ShirtColor {
@@ -98,18 +101,22 @@ impl Inventory {
fn main() {
let store = Inventory {
- shirts: vec![ShirtColor::Blue, ShirtColor::Red, ShirtColor::Blue], [2]
+ 2 shirts: vec![
+ ShirtColor::Blue,
+ ShirtColor::Red,
+ ShirtColor::Blue,
+ ],
};
let user_pref1 = Some(ShirtColor::Red);
- let giveaway1 = store.giveaway(user_pref1); [3]
+ 3 let giveaway1 = store.giveaway(user_pref1);
println!(
"The user with preference {:?} gets {:?}",
user_pref1, giveaway1
);
let user_pref2 = None;
- let giveaway2 = store.giveaway(user_pref2); [4]
+ 4 let giveaway2 = store.giveaway(user_pref2);
println!(
"The user with preference {:?} gets {:?}",
user_pref2, giveaway2
@@ -125,11 +132,11 @@ method for a user with a preference for a red shirt [3] and a user without any
preference [4].
Again, this code could be implemented in many ways, and here, to focus on
-closures, we’ve stuck to concepts you’ve already learned except for the body of
-the `giveaway` method that uses a closure. In the `giveaway` method, we get the
-user preference as a parameter of type `Option<ShirtColor>` and call the
-`unwrap_or_else` method on `user_preference` [1]. The `unwrap_or_else` method on
-`Option<T>` is defined by the standard library. It takes one argument: a
+closures, we’ve stuck to concepts you’ve already learned, except for the body
+of the `giveaway` method that uses a closure. In the `giveaway` method, we get
+the user preference as a parameter of type `Option<ShirtColor>` and call the
+`unwrap_or_else` method on `user_preference` [1]. The `unwrap_or_else` method
+on `Option<T>` is defined by the standard library. It takes one argument: a
closure without any arguments that returns a value `T` (the same type stored in
the `Some` variant of the `Option<T>`, in this case `ShirtColor`). If the
`Option<T>` is the `Some` variant, `unwrap_or_else` returns the value from
@@ -138,18 +145,14 @@ calls the closure and returns the value returned by the closure.
We specify the closure expression `|| self.most_stocked()` as the argument to
`unwrap_or_else`. This is a closure that takes no parameters itself (if the
-closure had parameters, they would appear between the two vertical bars). The
+closure had parameters, they would appear between the two vertical pipes). The
body of the closure calls `self.most_stocked()`. We’re defining the closure
here, and the implementation of `unwrap_or_else` will evaluate the closure
later if the result is needed.
-Running this code prints:
+Running this code prints the following:
```
-$ cargo run
- Compiling shirt-company v0.1.0 (file:///projects/shirt-company)
- Finished dev [unoptimized + debuginfo] target(s) in 0.27s
- Running `target/debug/shirt-company`
The user with preference Some(Red) gets Red
The user with preference None gets Blue
```
@@ -184,7 +187,7 @@ explicitness and clarity at the cost of being more verbose than is strictly
necessary. Annotating the types for a closure would look like the definition
shown in Listing 13-2. In this example, we’re defining a closure and storing it
in a variable rather than defining the closure in the spot we pass it as an
-argument as we did in Listing 13-1.
+argument, as we did in Listing 13-1.
Filename: src/main.rs
@@ -200,11 +203,11 @@ Listing 13-2: Adding optional type annotations of the parameter and return
value types in the closure
With type annotations added, the syntax of closures looks more similar to the
-syntax of functions. Here we define a function that adds 1 to its parameter and
-a closure that has the same behavior, for comparison. We’ve added some spaces
-to line up the relevant parts. This illustrates how closure syntax is similar
-to function syntax except for the use of pipes and the amount of syntax that is
-optional:
+syntax of functions. Here, we define a function that adds 1 to its parameter
+and a closure that has the same behavior, for comparison. We’ve added some
+spaces to line up the relevant parts. This illustrates how closure syntax is
+similar to function syntax except for the use of pipes and the amount of syntax
+that is optional:
```
fn add_one_v1 (x: u32) -> u32 { x + 1 }
@@ -213,13 +216,13 @@ let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1 ;
```
-The first line shows a function definition, and the second line shows a fully
+The first line shows a function definition and the second line shows a fully
annotated closure definition. In the third line, we remove the type annotations
-from the closure definition. In the fourth line, we remove the brackets, which
-are optional because the closure body has only one expression. These are all
-valid definitions that will produce the same behavior when they’re called. The
-`add_one_v3` and `add_one_v4` lines require the closures to be evaluated to be
-able to compile because the types will be inferred from their usage. This is
+from the closure definition. In the fourth line, we remove the curly brackets,
+which are optional because the closure body has only one expression. These are
+all valid definitions that will produce the same behavior when they’re called.
+The `add_one_v3` and `add_one_v4` lines require the closures to be evaluated to
+be able to compile because the types will be inferred from their usage. This is
similar to `let v = Vec::new();` needing either type annotations or values of
some type to be inserted into the `Vec` for Rust to be able to infer the type.
@@ -251,7 +254,8 @@ error[E0308]: mismatched types
--> src/main.rs:5:29
|
5 | let n = example_closure(5);
- | ^- help: try using a conversion method: `.to_string()`
+ | ^- help: try using a conversion method:
+`.to_string()`
| |
| expected struct `String`, found integer
```
@@ -271,7 +275,7 @@ captured values.
In Listing 13-4, we define a closure that captures an immutable reference to
the vector named `list` because it only needs an immutable reference to print
-the value:
+the value.
Filename: src/main.rs
@@ -280,10 +284,10 @@ fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
- [1] let only_borrows = || println!("From closure: {:?}", list);
+ 1 let only_borrows = || println!("From closure: {:?}", list);
println!("Before calling closure: {:?}", list);
- only_borrows(); [2]
+ 2 only_borrows();
println!("After calling closure: {:?}", list);
}
```
@@ -308,7 +312,7 @@ After calling closure: [1, 2, 3]
```
Next, in Listing 13-5, we change the closure body so that it adds an element to
-the `list` vector. The closure now captures a mutable reference:
+the `list` vector. The closure now captures a mutable reference.
Filename: src/main.rs
@@ -350,7 +354,7 @@ the data so that it’s owned by the new thread. We’ll discuss threads and why
you would want to use them in detail in Chapter 16 when we talk about
concurrency, but for now, let’s briefly explore spawning a new thread using a
closure that needs the `move` keyword. Listing 13-6 shows Listing 13-4 modified
-to print the vector in a new thread rather than in the main thread:
+to print the vector in a new thread rather than in the main thread.
Filename: src/main.rs
@@ -361,8 +365,8 @@ fn main() {
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
- [1] thread::spawn(move || {
- [2] println!("From thread: {:?}", list)
+ 1 thread::spawn(move || {
+ 2 println!("From thread: {:?}", list)
}).join().unwrap();
}
```
@@ -372,29 +376,30 @@ ownership of `list`
We spawn a new thread, giving the thread a closure to run as an argument. The
closure body prints out the list. In Listing 13-4, the closure only captured
-`list` using an immutable reference because that's the least amount of access
+`list` using an immutable reference because that’s the least amount of access
to `list` needed to print it. In this example, even though the closure body
-still only needs an immutable reference, we need to specify that `list` should
-be moved into the closure by putting the `move` keyword at the beginning of the
-closure definition. The new thread might finish before the rest of the main
-thread finishes, or the main thread might finish first. If the main thread
-maintained ownership of `list` but ended before the new thread did and dropped
-`list`, the immutable reference in the thread would be invalid. Therefore, the
-compiler requires that `list` be moved into the closure given to the new thread
-so the reference will be valid. Try removing the `move` keyword or using `list`
-in the main thread after the closure is defined to see what compiler errors you
-get!
-
-### Moving Captured Values Out of Closures and the `Fn` Traits
+still only needs an immutable reference [2], we need to specify that `list`
+should be moved into the closure by putting the `move` keyword [1] at the
+beginning of the closure definition. The new thread might finish before the
+rest of the main thread finishes, or the main thread might finish first. If the
+main thread maintains ownership of `list` but ends before the new thread and
+drops `list`, the immutable reference in the thread would be invalid.
+Therefore, the compiler requires that `list` be moved into the closure given to
+the new thread so the reference will be valid. Try removing the `move` keyword
+or using `list` in the main thread after the closure is defined to see what
+compiler errors you get!
+
+### Moving Captured Values Out of Closures and the Fn Traits
Once a closure has captured a reference or captured ownership of a value from
the environment where the closure is defined (thus affecting what, if anything,
is moved *into* the closure), the code in the body of the closure defines what
happens to the references or values when the closure is evaluated later (thus
-affecting what, if anything, is moved *out of* the closure). A closure body can
-do any of the following: move a captured value out of the closure, mutate the
-captured value, neither move nor mutate the value, or capture nothing from the
-environment to begin with.
+affecting what, if anything, is moved *out of* the closure).
+
+A closure body can do any of the following: move a captured value out of the
+closure, mutate the captured value, neither move nor mutate the value, or
+capture nothing from the environment to begin with.
The way a closure captures and handles values from the environment affects
which traits the closure implements, and traits are how functions and structs
@@ -402,18 +407,18 @@ can specify what kinds of closures they can use. Closures will automatically
implement one, two, or all three of these `Fn` traits, in an additive fashion,
depending on how the closure’s body handles the values:
-1. `FnOnce` applies to closures that can be called once. All closures implement
- at least this trait, because all closures can be called. A closure that
- moves captured values out of its body will only implement `FnOnce` and none
- of the other `Fn` traits, because it can only be called once.
-2. `FnMut` applies to closures that don’t move captured values out of their
- body, but that might mutate the captured values. These closures can be
- called more than once.
-3. `Fn` applies to closures that don’t move captured values out of their body
- and that don’t mutate captured values, as well as closures that capture
- nothing from their environment. These closures can be called more than once
- without mutating their environment, which is important in cases such as
- calling a closure multiple times concurrently.
+* `FnOnce` applies to closures that can be called once. All closures implement
+at least this trait because all closures can be called. A closure that moves
+captured values out of its body will only implement `FnOnce` and none of the
+other `Fn` traits because it can only be called once.
+* `FnMut` applies to closures that don’t move captured values out of their
+body, but that might mutate the captured values. These closures can be called
+more than once.
+* `Fn` applies to closures that don’t move captured values out of their body
+and that don’t mutate captured values, as well as closures that capture nothing
+from their environment. These closures can be called more than once without
+mutating their environment, which is important in cases such as calling a
+closure multiple times concurrently.
Let’s look at the definition of the `unwrap_or_else` method on `Option<T>` that
we used in Listing 13-1:
@@ -444,27 +449,27 @@ the closure we provide when calling `unwrap_or_else`.
The trait bound specified on the generic type `F` is `FnOnce() -> T`, which
means `F` must be able to be called once, take no arguments, and return a `T`.
Using `FnOnce` in the trait bound expresses the constraint that
-`unwrap_or_else` is only going to call `f` at most one time. In the body of
+`unwrap_or_else` is only going to call `f` one time, at most. In the body of
`unwrap_or_else`, we can see that if the `Option` is `Some`, `f` won’t be
called. If the `Option` is `None`, `f` will be called once. Because all
-closures implement `FnOnce`, `unwrap_or_else` accepts the most different kinds
-of closures and is as flexible as it can be.
+closures implement `FnOnce`, `unwrap_or_else` accepts the largest variety of
+closures and is as flexible as it can be.
> Note: Functions can implement all three of the `Fn` traits too. If what we
-> want to do doesn’t require capturing a value from the environment, we can use
-> the name of a function rather than a closure where we need something that
-> implements one of the `Fn` traits. For example, on an `Option<Vec<T>>` value,
-> we could call `unwrap_or_else(Vec::new)` to get a new, empty vector if the
-> value is `None`.
+want to do doesn’t require capturing a value from the environment, we can use
+the name of a function rather than a closure where we need something that
+implements one of the `Fn` traits. For example, on an `Option<Vec<T>>` value,
+we could call `unwrap_or_else(Vec::new)` to get a new, empty vector if the
+value is `None`.
-Now let’s look at the standard library method `sort_by_key` defined on slices,
+Now let’s look at the standard library method `sort_by_key`, defined on slices,
to see how that differs from `unwrap_or_else` and why `sort_by_key` uses
`FnMut` instead of `FnOnce` for the trait bound. The closure gets one argument
in the form of a reference to the current item in the slice being considered,
and returns a value of type `K` that can be ordered. This function is useful
when you want to sort a slice by a particular attribute of each item. In
Listing 13-7, we have a list of `Rectangle` instances and we use `sort_by_key`
-to order them by their `width` attribute from low to high:
+to order them by their `width` attribute from low to high.
Filename: src/main.rs
@@ -510,21 +515,17 @@ This code prints:
The reason `sort_by_key` is defined to take an `FnMut` closure is that it calls
the closure multiple times: once for each item in the slice. The closure `|r|
-r.width` doesn’t capture, mutate, or move out anything from its environment, so
+r.width` doesn’t capture, mutate, or move anything out from its environment, so
it meets the trait bound requirements.
In contrast, Listing 13-8 shows an example of a closure that implements just
the `FnOnce` trait, because it moves a value out of the environment. The
-compiler won’t let us use this closure with `sort_by_key`:
+compiler won’t let us use this closure with `sort_by_key`.
Filename: src/main.rs
```
-#[derive(Debug)]
-struct Rectangle {
- width: u32,
- height: u32,
-}
+--snip--
fn main() {
let mut list = [
@@ -549,7 +550,7 @@ Listing 13-8: Attempting to use an `FnOnce` closure with `sort_by_key`
This is a contrived, convoluted way (that doesn’t work) to try and count the
number of times `sort_by_key` gets called when sorting `list`. This code
attempts to do this counting by pushing `value`—a `String` from the closure’s
-environment—into the `sort_operations` vector. The closure captures `value`
+environment—into the `sort_operations` vector. The closure captures `value` and
then moves `value` out of the closure by transferring ownership of `value` to
the `sort_operations` vector. This closure can be called once; trying to call
it a second time wouldn’t work because `value` would no longer be in the
@@ -559,7 +560,8 @@ that `value` can’t be moved out of the closure because the closure must
implement `FnMut`:
```
-error[E0507]: cannot move out of `value`, a captured variable in an `FnMut` closure
+error[E0507]: cannot move out of `value`, a captured variable in an `FnMut`
+closure
--> src/main.rs:18:30
|
15 | let value = String::from("by key called");
@@ -568,7 +570,8 @@ error[E0507]: cannot move out of `value`, a captured variable in an `FnMut` clos
17 | list.sort_by_key(|r| {
| ______________________-
18 | | sort_operations.push(value);
- | | ^^^^^ move occurs because `value` has type `String`, which does not implement the `Copy` trait
+ | | ^^^^^ move occurs because `value` has
+type `String`, which does not implement the `Copy` trait
19 | | r.width
20 | | });
| |_____- captured by this `FnMut` closure
@@ -576,39 +579,33 @@ error[E0507]: cannot move out of `value`, a captured variable in an `FnMut` clos
The error points to the line in the closure body that moves `value` out of the
environment. To fix this, we need to change the closure body so that it doesn’t
-move values out of the environment. To count the number of times `sort_by_key`
-is called, keeping a counter in the environment and incrementing its value in
-the closure body is a more straightforward way to calculate that. The closure
-in Listing 13-9 works with `sort_by_key` because it is only capturing a mutable
-reference to the `num_sort_operations` counter and can therefore be called more
-than once:
+move values out of the environment. Keeping a counter in the environment and
+incrementing its value in the closure body is a more straightforward way to
+count the number of times `sort_by_key` is called. The closure in Listing 13-9
+works with `sort_by_key` because it is only capturing a mutable reference to
+the `num_sort_operations` counter and can therefore be called more than once.
Filename: src/main.rs
```
-#[derive(Debug)]
-struct Rectangle {
- width: u32,
- height: u32,
-}
+--snip--
fn main() {
- let mut list = [
- Rectangle { width: 10, height: 1 },
- Rectangle { width: 3, height: 5 },
- Rectangle { width: 7, height: 12 },
- ];
+ --snip--
let mut num_sort_operations = 0;
list.sort_by_key(|r| {
num_sort_operations += 1;
r.width
});
- println!("{:#?}, sorted in {num_sort_operations} operations", list);
+ println!(
+ "{:#?}, sorted in {num_sort_operations} operations",
+ list
+ );
}
```
-Listing 13-9: Using an `FnMut` closure with `sort_by_key` is allowed
+Listing 13-9: Using an `FnMut` closure with `sort_by_key` is allowed.
The `Fn` traits are important when defining or using functions or types that
make use of closures. In the next section, we’ll discuss iterators. Many
@@ -637,10 +634,10 @@ let v1_iter = v1.iter();
Listing 13-10: Creating an iterator
The iterator is stored in the `v1_iter` variable. Once we’ve created an
-iterator, we can use it in a variety of ways. In Listing 3-5 in Chapter 3, we
-iterated over an array using a `for` loop to execute some code on each of its
-items. Under the hood this implicitly created and then consumed an iterator,
-but we glossed over how exactly that works until now.
+iterator, we can use it in a variety of ways. In Listing 3-5, we iterated over
+an array using a `for` loop to execute some code on each of its items. Under
+the hood, this implicitly created and then consumed an iterator, but we glossed
+over how exactly that works until now.
In the example in Listing 13-11, we separate the creation of the iterator from
the use of the iterator in the `for` loop. When the `for` loop is called using
@@ -653,7 +650,7 @@ let v1 = vec![1, 2, 3];
let v1_iter = v1.iter();
for val in v1_iter {
- println!("Got: {}", val);
+ println!("Got: {val}");
}
```
@@ -665,12 +662,12 @@ you would likely write this same functionality by starting a variable at index
incrementing the variable value in a loop until it reached the total number of
items in the vector.
-Iterators handle all that logic for you, cutting down on repetitive code you
+Iterators handle all of that logic for you, cutting down on repetitive code you
could potentially mess up. Iterators give you more flexibility to use the same
logic with many different kinds of sequences, not just data structures you can
index into, like vectors. Let’s examine how iterators do that.
-### The `Iterator` Trait and the `next` Method
+### The Iterator Trait and the next Method
All iterators implement a trait named `Iterator` that is defined in the
standard library. The definition of the trait looks like this:
@@ -685,7 +682,7 @@ pub trait Iterator {
}
```
-Notice this definition uses some new syntax: `type Item` and `Self::Item`,
+Notice that this definition uses some new syntax: `type Item` and `Self::Item`,
which are defining an *associated type* with this trait. We’ll talk about
associated types in depth in Chapter 19. For now, all you need to know is that
this code says implementing the `Iterator` trait requires that you also define
@@ -694,8 +691,8 @@ method. In other words, the `Item` type will be the type returned from the
iterator.
The `Iterator` trait only requires implementors to define one method: the
-`next` method, which returns one item of the iterator at a time wrapped in
-`Some` and, when iteration is over, returns `None`.
+`next` method, which returns one item of the iterator at a time, wrapped in
+`Some`, and, when iteration is over, returns `None`.
We can call the `next` method on iterators directly; Listing 13-12 demonstrates
what values are returned from repeated calls to `next` on the iterator created
@@ -733,7 +730,7 @@ ownership of `v1` and returns owned values, we can call `into_iter` instead of
`iter`. Similarly, if we want to iterate over mutable references, we can call
`iter_mut` instead of `iter`.
-### Methods that Consume the Iterator
+### Methods That Consume the Iterator
The `Iterator` trait has a number of different methods with default
implementations provided by the standard library; you can find out about these
@@ -742,12 +739,12 @@ trait. Some of these methods call the `next` method in their definition, which
is why you’re required to implement the `next` method when implementing the
`Iterator` trait.
-Methods that call `next` are called *consuming adaptors*, because calling them
+Methods that call `next` are called *consuming adapters* because calling them
uses up the iterator. One example is the `sum` method, which takes ownership of
the iterator and iterates through the items by repeatedly calling `next`, thus
consuming the iterator. As it iterates through, it adds each item to a running
total and returns the total when iteration is complete. Listing 13-13 has a
-test illustrating a use of the `sum` method:
+test illustrating a use of the `sum` method.
Filename: src/lib.rs
@@ -770,17 +767,17 @@ iterator
We aren’t allowed to use `v1_iter` after the call to `sum` because `sum` takes
ownership of the iterator we call it on.
-### Methods that Produce Other Iterators
+### Methods That Produce Other Iterators
-*Iterator adaptors* are methods defined on the `Iterator` trait that don’t
+*Iterator adapters* are methods defined on the `Iterator` trait that don’t
consume the iterator. Instead, they produce different iterators by changing
some aspect of the original iterator.
-Listing 13-17 shows an example of calling the iterator adaptor method `map`,
+Listing 13-14 shows an example of calling the iterator adapter method `map`,
which takes a closure to call on each item as the items are iterated through.
The `map` method returns a new iterator that produces the modified items. The
closure here creates a new iterator in which each item from the vector will be
-incremented by 1:
+incremented by 1.
Filename: src/main.rs
@@ -790,7 +787,7 @@ let v1: Vec<i32> = vec![1, 2, 3];
v1.iter().map(|x| x + 1);
```
-Listing 13-14: Calling the iterator adaptor `map` to create a new iterator
+Listing 13-14: Calling the iterator adapter `map` to create a new iterator
However, this code produces a warning:
@@ -806,17 +803,16 @@ warning: unused `Map` that must be used
```
The code in Listing 13-14 doesn’t do anything; the closure we’ve specified
-never gets called. The warning reminds us why: iterator adaptors are lazy, and
+never gets called. The warning reminds us why: iterator adapters are lazy, and
we need to consume the iterator here.
To fix this warning and consume the iterator, we’ll use the `collect` method,
-which we used in Chapter 12 with `env::args` in Listing 12-1. This method
-consumes the iterator and collects the resulting values into a collection data
-type.
+which we used with `env::args` in Listing 12-1. This method consumes the
+iterator and collects the resultant values into a collection data type.
-In Listing 13-15, we collect the results of iterating over the iterator that’s
-returned from the call to `map` into a vector. This vector will end up
-containing each item from the original vector incremented by 1.
+In Listing 13-15, we collect into a vector the results of iterating over the
+iterator that’s returned from the call to `map`. This vector will end up
+containing each item from the original vector, incremented by 1.
Filename: src/main.rs
@@ -828,7 +824,7 @@ let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);
```
-Listing 13-15: Calling the `map` method to create a new iterator and then
+Listing 13-15: Calling the `map` method to create a new iterator, and then
calling the `collect` method to consume the new iterator and create a vector
Because `map` takes a closure, we can specify any operation we want to perform
@@ -836,11 +832,11 @@ on each item. This is a great example of how closures let you customize some
behavior while reusing the iteration behavior that the `Iterator` trait
provides.
-You can chain multiple calls to iterator adaptors to perform complex actions in
+You can chain multiple calls to iterator adapters to perform complex actions in
a readable way. But because all iterators are lazy, you have to call one of the
-consuming adaptor methods to get results from calls to iterator adaptors.
+consuming adapter methods to get results from calls to iterator adapters.
-### Using Closures that Capture Their Environment
+### Using Closures That Capture Their Environment
Many iterator adapters take closures as arguments, and commonly the closures
we’ll specify as arguments to iterator adapters will be closures that capture
@@ -915,18 +911,18 @@ The `shoes_in_size` function takes ownership of a vector of shoes and a shoe
size as parameters. It returns a vector containing only shoes of the specified
size.
-In the body of `shoes_in_size`, we call `into_iter` to create an iterator
-that takes ownership of the vector. Then we call `filter` to adapt that
-iterator into a new iterator that only contains elements for which the closure
-returns `true`.
+In the body of `shoes_in_size`, we call `into_iter` to create an iterator that
+takes ownership of the vector. Then we call `filter` to adapt that iterator
+into a new iterator that only contains elements for which the closure returns
+`true`.
The closure captures the `shoe_size` parameter from the environment and
compares the value with each shoe’s size, keeping only shoes of the size
specified. Finally, calling `collect` gathers the values returned by the
adapted iterator into a vector that’s returned by the function.
-The test shows that when we call `shoes_in_size`, we get back only shoes
-that have the same size as the value we specified.
+The test shows that when we call `shoes_in_size`, we get back only shoes that
+have the same size as the value we specified.
## Improving Our I/O Project
@@ -935,19 +931,21 @@ Chapter 12 by using iterators to make places in the code clearer and more
concise. Let’s look at how iterators can improve our implementation of the
`Config::build` function and the `search` function.
-### Removing a `clone` Using an Iterator
+### Removing a clone Using an Iterator
In Listing 12-6, we added code that took a slice of `String` values and created
an instance of the `Config` struct by indexing into the slice and cloning the
values, allowing the `Config` struct to own those values. In Listing 13-17,
we’ve reproduced the implementation of the `Config::build` function as it was
-in Listing 12-23:
+in Listing 12-23.
Filename: src/lib.rs
```
impl Config {
- pub fn build(args: &[String]) -> Result<Config, &'static str> {
+ pub fn build(
+ args: &[String]
+ ) -> Result<Config, &'static str> {
if args.len() < 3 {
return Err("not enough arguments");
}
@@ -1001,7 +999,7 @@ fn main() {
process::exit(1);
});
- // --snip--
+ --snip--
}
```
@@ -1013,12 +1011,13 @@ Filename: src/main.rs
```
fn main() {
- let config = Config::build(env::args()).unwrap_or_else(|err| {
- eprintln!("Problem parsing arguments: {err}");
- process::exit(1);
- });
+ let config =
+ Config::build(env::args()).unwrap_or_else(|err| {
+ eprintln!("Problem parsing arguments: {err}");
+ process::exit(1);
+ });
- // --snip--
+ --snip--
}
```
@@ -1031,8 +1030,8 @@ we’re passing ownership of the iterator returned from `env::args` to
Next, we need to update the definition of `Config::build`. In your I/O
project’s *src/lib.rs* file, let’s change the signature of `Config::build` to
-look like Listing 13-19. This still won’t compile because we need to update the
-function body.
+look like Listing 13-19. This still won’t compile, because we need to update
+the function body.
Filename: src/lib.rs
@@ -1041,7 +1040,7 @@ impl Config {
pub fn build(
mut args: impl Iterator<Item = String>,
) -> Result<Config, &'static str> {
- // --snip--
+ --snip--
```
Listing 13-19: Updating the signature of `Config::build` to expect an iterator
@@ -1053,18 +1052,18 @@ the `Iterator` trait and returns `String` values.
We’ve updated the signature of the `Config::build` function so the parameter
`args` has a generic type with the trait bounds `impl Iterator<Item = String>`
instead of `&[String]`. This usage of the `impl Trait` syntax we discussed in
-the “Traits as Parameters” section of Chapter 10 means that `args` can be any
-type that implements the `Iterator` type and returns `String` items.
+“Traits as Parameters” on page XX means that `args` can be any type that
+implements the `Iterator` type and returns `String` items.
Because we’re taking ownership of `args` and we’ll be mutating `args` by
iterating over it, we can add the `mut` keyword into the specification of the
`args` parameter to make it mutable.
-#### Using `Iterator` Trait Methods Instead of Indexing
+#### Using Iterator Trait Methods Instead of Indexing
Next, we’ll fix the body of `Config::build`. Because `args` implements the
`Iterator` trait, we know we can call the `next` method on it! Listing 13-20
-updates the code from Listing 12-23 to use the `next` method:
+updates the code from Listing 12-23 to use the `next` method.
Filename: src/lib.rs
@@ -1100,21 +1099,24 @@ Listing 13-20: Changing the body of `Config::build` to use iterator methods
Remember that the first value in the return value of `env::args` is the name of
the program. We want to ignore that and get to the next value, so first we call
-`next` and do nothing with the return value. Second, we call `next` to get the
-value we want to put in the `query` field of `Config`. If `next` returns a
+`next` and do nothing with the return value. Then we call `next` to get the
+value we want to put in the `query` field of `Config`. If `next` returns
`Some`, we use a `match` to extract the value. If it returns `None`, it means
not enough arguments were given and we return early with an `Err` value. We do
the same thing for the `filename` value.
-### Making Code Clearer with Iterator Adaptors
+### Making Code Clearer with Iterator Adapters
We can also take advantage of iterators in the `search` function in our I/O
-project, which is reproduced here in Listing 13-21 as it was in Listing 12-19:
+project, which is reproduced here in Listing 13-21 as it was in Listing 12-19.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
let mut results = Vec::new();
for line in contents.lines() {
@@ -1129,17 +1131,20 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
Listing 13-21: The implementation of the `search` function from Listing 12-19
-We can write this code in a more concise way using iterator adaptor methods.
+We can write this code in a more concise way using iterator adapter methods.
Doing so also lets us avoid having a mutable intermediate `results` vector. The
functional programming style prefers to minimize the amount of mutable state to
make code clearer. Removing the mutable state might enable a future enhancement
-to make searching happen in parallel, because we wouldn’t have to manage
-concurrent access to the `results` vector. Listing 13-22 shows this change:
+to make searching happen in parallel because we wouldn’t have to manage
+concurrent access to the `results` vector. Listing 13-22 shows this change.
Filename: src/lib.rs
```
-pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
+pub fn search<'a>(
+ query: &str,
+ contents: &'a str,
+) -> Vec<&'a str> {
contents
.lines()
.filter(|line| line.contains(query))
@@ -1147,24 +1152,23 @@ pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
}
```
-Listing 13-22: Using iterator adaptor methods in the implementation of the
+Listing 13-22: Using iterator adapter methods in the implementation of the
`search` function
Recall that the purpose of the `search` function is to return all lines in
`contents` that contain the `query`. Similar to the `filter` example in Listing
-13-16, this code uses the `filter` adaptor to keep only the lines that
-`line.contains(query)` returns `true` for. We then collect the matching lines
-into another vector with `collect`. Much simpler! Feel free to make the same
-change to use iterator methods in the `search_case_insensitive` function as
-well.
+13-16, this code uses the `filter` adapter to keep only the lines for which
+`line.contains(query)` returns `true`. We then collect the matching lines into
+another vector with `collect`. Much simpler! Feel free to make the same change
+to use iterator methods in the `search_case_insensitive` function as well.
-### Choosing Between Loops or Iterators
+### Choosing Between Loops and Iterators
The next logical question is which style you should choose in your own code and
why: the original implementation in Listing 13-21 or the version using
iterators in Listing 13-22. Most Rust programmers prefer to use the iterator
style. It’s a bit tougher to get the hang of at first, but once you get a feel
-for the various iterator adaptors and what they do, iterators can be easier to
+for the various iterator adapters and what they do, iterators can be easier to
understand. Instead of fiddling with the various bits of looping and building
new vectors, the code focuses on the high-level objective of the loop. This
abstracts away some of the commonplace code so it’s easier to see the concepts
@@ -1172,8 +1176,7 @@ that are unique to this code, such as the filtering condition each element in
the iterator must pass.
But are the two implementations truly equivalent? The intuitive assumption
-might be that the more low-level loop will be faster. Let’s talk about
-performance.
+might be that the lower-level loop will be faster. Let’s talk about performance.
## Comparing Performance: Loops vs. Iterators
@@ -1192,8 +1195,8 @@ test bench_search_iter ... bench: 19,234,900 ns/iter (+/- 657,200)
```
The iterator version was slightly faster! We won’t explain the benchmark code
-here, because the point is not to prove that the two versions are equivalent
-but to get a general sense of how these two implementations compare
+here because the point is not to prove that the two versions are equivalent but
+to get a general sense of how these two implementations compare
performance-wise.
For a more comprehensive benchmark, you should check using various texts of
@@ -1201,24 +1204,22 @@ various sizes as the `contents`, different words and words of different lengths
as the `query`, and all kinds of other variations. The point is this:
iterators, although a high-level abstraction, get compiled down to roughly the
same code as if you’d written the lower-level code yourself. Iterators are one
-of Rust’s *zero-cost abstractions*, by which we mean using the abstraction
+of Rust’s *zero-cost abstractions*, by which we mean that using the abstraction
imposes no additional runtime overhead. This is analogous to how Bjarne
Stroustrup, the original designer and implementor of C++, defines
*zero-overhead* in “Foundations of C++” (2012):
> In general, C++ implementations obey the zero-overhead principle: What you
-> don’t use, you don’t pay for. And further: What you do use, you couldn’t hand
-> code any better.
-
-As another example, the following code is taken from an audio decoder. The
-decoding algorithm uses the linear prediction mathematical operation to
-estimate future values based on a linear function of the previous samples. This
-code uses an iterator chain to do some math on three variables in scope: a
-`buffer` slice of data, an array of 12 `coefficients`, and an amount by which
-to shift data in `qlp_shift`. We’ve declared the variables within this example
-but not given them any values; although this code doesn’t have much meaning
-outside of its context, it’s still a concise, real-world example of how Rust
-translates high-level ideas to low-level code.
+don’t use, you don’t pay for. And further: What you do use, you couldn’t hand
+code any better.As another example, the following code is taken from an audio
+decoder. The decoding algorithm uses the linear prediction mathematical
+operation to estimate future values based on a linear function of the previous
+samples. This code uses an iterator chain to do some math on three variables in
+scope: a `buffer` slice of data, an array of 12 `coefficients`, and an amount
+by which to shift data in `qlp_shift`. We’ve declared the variables within this
+example but not given them any values; although this code doesn’t have much
+meaning outside of its context, it’s still a concise, real-world example of how
+Rust translates high-level ideas to low-level code.
```
let buffer: &mut [i32];
@@ -1237,12 +1238,12 @@ for i in 12..buffer.len() {
To calculate the value of `prediction`, this code iterates through each of the
12 values in `coefficients` and uses the `zip` method to pair the coefficient
-values with the previous 12 values in `buffer`. Then, for each pair, we
-multiply the values together, sum all the results, and shift the bits in the
-sum `qlp_shift` bits to the right.
+values with the previous 12 values in `buffer`. Then, for each pair, it
+multiplies the values together, sums all the results, and shifts the bits in
+the sum `qlp_shift` bits to the right.
Calculations in applications like audio decoders often prioritize performance
-most highly. Here, we’re creating an iterator, using two adaptors, and then
+most highly. Here, we’re creating an iterator, using two adapters, and then
consuming the value. What assembly code would this Rust code compile to? Well,
as of this writing, it compiles down to the same assembly you’d write by hand.
There’s no loop at all corresponding to the iteration over the values in
@@ -1253,7 +1254,7 @@ the loop.
All of the coefficients get stored in registers, which means accessing the
values is very fast. There are no bounds checks on the array access at runtime.
-All these optimizations that Rust is able to apply make the resulting code
+All of these optimizations that Rust is able to apply make the resultant code
extremely efficient. Now that you know this, you can use iterators and closures
without fear! They make code seem like it’s higher level but don’t impose a
runtime performance penalty for doing so.
@@ -1269,3 +1270,4 @@ Rust’s goal to strive to provide zero-cost abstractions.
Now that we’ve improved the expressiveness of our I/O project, let’s look at
some more features of `cargo` that will help us share the project with the
world.
+
diff --git a/src/doc/book/nostarch/chapter14.md b/src/doc/book/nostarch/chapter14.md
index 076410232..f5f2be719 100644
--- a/src/doc/book/nostarch/chapter14.md
+++ b/src/doc/book/nostarch/chapter14.md
@@ -8,19 +8,19 @@ directory, so all fixes need to be made in `/src/`.
# More About Cargo and Crates.io
-So far we’ve used only the most basic features of Cargo to build, run, and test
-our code, but it can do a lot more. In this chapter, we’ll discuss some of its
-other, more advanced features to show you how to do the following:
+So far, we’ve used only the most basic features of Cargo to build, run, and
+test our code, but it can do a lot more. In this chapter, we’ll discuss some of
+its other, more advanced features to show you how to do the following:
-* Customize your build through release profiles
-* Publish libraries on *https://crates.io/*
-* Organize large projects with workspaces
-* Install binaries from *https://crates.io/*
-* Extend Cargo using custom commands
+* Customize your build through release profiles.
+* Publish libraries on *https://crates.i**o*.
+* Organize large projects with workspaces.
+* Install binaries from *https://crates.io*.
+* Extend Cargo using custom commands.
Cargo can do even more than the functionality we cover in this chapter, so for
a full explanation of all its features, see its documentation at
-*https://doc.rust-lang.org/cargo/*.
+*https://doc.rust-lang.org/cargo*.
## Customizing Builds with Release Profiles
@@ -30,7 +30,7 @@ various options for compiling code. Each profile is configured independently of
the others.
Cargo has two main profiles: the `dev` profile Cargo uses when you run `cargo
-build` and the `release` profile Cargo uses when you run `cargo build
+build`, and the `release` profile Cargo uses when you run `cargo build
--release`. The `dev` profile is defined with good defaults for development,
and the `release` profile has good defaults for release builds.
@@ -45,7 +45,7 @@ $ cargo build --release
The `dev` and `release` are these different profiles used by the compiler.
-Cargo has default settings for each of the profiles that apply when you haven't
+Cargo has default settings for each of the profiles that apply when you haven’t
explicitly added any `[profile.*]` sections in the project’s *Cargo.toml* file.
By adding `[profile.*]` sections for any profile you want to customize, you
override any subset of the default settings. For example, here are the default
@@ -64,7 +64,7 @@ opt-level = 3
The `opt-level` setting controls the number of optimizations Rust will apply to
your code, with a range of 0 to 3. Applying more optimizations extends
compiling time, so if you’re in development and compiling your code often,
-you’ll want fewer optimizations to compile faster even if the resulting code
+you’ll want fewer optimizations to compile faster even if the resultant code
runs slower. The default `opt-level` for `dev` is therefore `0`. When you’re
ready to release your code, it’s best to spend more time compiling. You’ll only
compile in release mode once, but you’ll run the compiled program many times,
@@ -89,11 +89,12 @@ Cargo will use the defaults for the `dev` profile plus our customization to
optimizations than the default, but not as many as in a release build.
For the full list of configuration options and defaults for each profile, see
-Cargo’s documentation at *https://doc.rust-lang.org/cargo/reference/profiles.html*.
+Cargo’s documentation at
+*https://doc.rust-lang.org/cargo/reference/profiles.html*.
## Publishing a Crate to Crates.io
-We’ve used packages from *https://crates.io/* as dependencies of our project,
+We’ve used packages from *https://crates.io* as dependencies of our project,
but you can also share your code with other people by publishing your own
packages. The crate registry at *https://crates.io* distributes the source code
of your packages, so it primarily hosts code that is open source.
@@ -120,7 +121,7 @@ for an `add_one` function in a crate named `my_crate`.
Filename: src/lib.rs
-````
+```
/// Adds one to the number given.
///
/// # Examples
@@ -134,17 +135,10 @@ Filename: src/lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
-````
+```
Listing 14-1: A documentation comment for a function
-<!-- I removed two sets of ``` here because it was inverting the text and code
-formatting, but you may want to check that I have't changed meaning in the
-code! /LC -->
-<!-- Yeah, those need to be in there. It's definitely weird that it's a code
-block inside of a code block-- I think I've fixed it by adding more ` around
-the outer block, but I'll check it again when we're in Word. /Carol -->
-
Here, we give a description of what the `add_one` function does, start a
section with the heading `Examples`, and then provide code that demonstrates
how to use the `add_one` function. We can generate the HTML documentation from
@@ -156,9 +150,7 @@ For convenience, running `cargo doc --open` will build the HTML for your
current crate’s documentation (as well as the documentation for all of your
crate’s dependencies) and open the result in a web browser. Navigate to the
`add_one` function and you’ll see how the text in the documentation comments is
-rendered, as shown in Figure 14-1:
-
-<img alt="Rendered HTML documentation for the `add_one` function of `my_crate`" src="img/trpl14-01.png" class="center" />
+rendered, as shown in Figure 14-1.
Figure 14-1: HTML documentation for the `add_one` function
@@ -168,16 +160,16 @@ We used the `# Examples` Markdown heading in Listing 14-1 to create a section
in the HTML with the title “Examples.” Here are some other sections that crate
authors commonly use in their documentation:
-* **Panics**: The scenarios in which the function being documented could
- panic. Callers of the function who don’t want their programs to panic should
- make sure they don’t call the function in these situations.
+* **Panics**: The scenarios in which the function being documented could panic.
+Callers of the function who don’t want their programs to panic should make sure
+they don’t call the function in these situations.
* **Errors**: If the function returns a `Result`, describing the kinds of
- errors that might occur and what conditions might cause those errors to be
- returned can be helpful to callers so they can write code to handle the
- different kinds of errors in different ways.
+errors that might occur and what conditions might cause those errors to be
+returned can be helpful to callers so they can write code to handle the
+different kinds of errors in different ways.
* **Safety**: If the function is `unsafe` to call (we discuss unsafety in
- Chapter 19), there should be a section explaining why the function is unsafe
- and covering the invariants that the function expects callers to uphold.
+Chapter 19), there should be a section explaining why the function is unsafe
+and covering the invariants that the function expects callers to uphold.
Most documentation comments don’t need all of these sections, but this is a
good checklist to remind you of the aspects of your code users will be
@@ -191,7 +183,8 @@ test` will run the code examples in your documentation as tests! Nothing is
better than documentation with examples. But nothing is worse than examples
that don’t work because the code has changed since the documentation was
written. If we run `cargo test` with the documentation for the `add_one`
-function from Listing 14-1, we will see a section in the test results like this:
+function from Listing 14-1, we will see a section in the test results that
+looks like this:
```
Doc-tests my_crate
@@ -199,35 +192,36 @@ function from Listing 14-1, we will see a section in the test results like this:
running 1 test
test src/lib.rs - add_one (line 5) ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0
+filtered out; finished in 0.27s
```
-Now if we change either the function or the example so the `assert_eq!` in the
+Now, if we change either the function or the example so the `assert_eq!` in the
example panics and run `cargo test` again, we’ll see that the doc tests catch
that the example and the code are out of sync with each other!
#### Commenting Contained Items
-The style of doc comment `//!` adds documentation to the item that contains the
-comments rather than to the items following the comments. We typically use
+The doc comment `//!` adds documentation to the item that *contains* the
+comments rather than to the items *following* the comments. We typically use
these doc comments inside the crate root file (*src/lib.rs* by convention) or
inside a module to document the crate or the module as a whole.
For example, to add documentation that describes the purpose of the `my_crate`
crate that contains the `add_one` function, we add documentation comments that
start with `//!` to the beginning of the *src/lib.rs* file, as shown in Listing
-14-2:
+14-2.
Filename: src/lib.rs
```
//! # My Crate
//!
-//! `my_crate` is a collection of utilities to make performing certain
-//! calculations more convenient.
+//! `my_crate` is a collection of utilities to make performing
+//! certain calculations more convenient.
/// Adds one to the number given.
-// --snip--
+--snip--
```
Listing 14-2: Documentation for the `my_crate` crate as a whole
@@ -238,11 +232,9 @@ that contains this comment rather than an item that follows this comment. In
this case, that item is the *src/lib.rs* file, which is the crate root. These
comments describe the entire crate.
-When we run `cargo doc --open`, these comments will display on the front
-page of the documentation for `my_crate` above the list of public items in the
-crate, as shown in Figure 14-2:
-
-<img alt="Rendered HTML documentation with a comment for the crate as a whole" src="img/trpl14-02.png" class="center" />
+When we run `cargo doc --open`, these comments will display on the front page
+of the documentation for `my_crate` above the list of public items in the
+crate, as shown in Figure 14-2.
Figure 14-2: Rendered documentation for `my_crate`, including the comment
describing the crate as a whole
@@ -251,7 +243,7 @@ Documentation comments within items are useful for describing crates and
modules especially. Use them to explain the overall purpose of the container to
help your users understand the crate’s organization.
-### Exporting a Convenient Public API with `pub use`
+### Exporting a Convenient Public API with pub use
The structure of your public API is a major consideration when publishing a
crate. People who use your crate are less familiar with the structure than you
@@ -259,26 +251,26 @@ are and might have difficulty finding the pieces they want to use if your crate
has a large module hierarchy.
In Chapter 7, we covered how to make items public using the `pub` keyword, and
-bring items into a scope with the `use` keyword. However, the structure that
-makes sense to you while you’re developing a crate might not be very convenient
-for your users. You might want to organize your structs in a hierarchy
-containing multiple levels, but then people who want to use a type you’ve
-defined deep in the hierarchy might have trouble finding out that type exists.
-They might also be annoyed at having to enter `use`
-`my_crate::some_module::another_module::UsefulType;` rather than `use`
-`my_crate::UsefulType;`.
+how to bring items into a scope with the `use` keyword. However, the structure
+that makes sense to you while you’re developing a crate might not be very
+convenient for your users. You might want to organize your structs in a
+hierarchy containing multiple levels, but then people who want to use a type
+you’ve defined deep in the hierarchy might have trouble finding out that type
+exists. They might also be annoyed at having to enter `use`
+`my_crate::`some_module`::`another_module`::`UsefulType`;` rather than `use`
+`my_crate::`UsefulType`;`.
The good news is that if the structure *isn’t* convenient for others to use
from another library, you don’t have to rearrange your internal organization:
instead, you can re-export items to make a public structure that’s different
-from your private structure by using `pub use`. Re-exporting takes a public
+from your private structure by using `pub use`. *Re-exporting* takes a public
item in one location and makes it public in another location, as if it were
defined in the other location instead.
For example, say we made a library named `art` for modeling artistic concepts.
Within this library are two modules: a `kinds` module containing two enums
named `PrimaryColor` and `SecondaryColor` and a `utils` module containing a
-function named `mix`, as shown in Listing 14-3:
+function named `mix`, as shown in Listing 14-3.
Filename: src/lib.rs
@@ -308,8 +300,11 @@ pub mod utils {
/// Combines two primary colors in equal amounts to create
/// a secondary color.
- pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
- // --snip--
+ pub fn mix(
+ c1: PrimaryColor,
+ c2: PrimaryColor,
+ ) -> SecondaryColor {
+ --snip--
}
}
```
@@ -318,9 +313,7 @@ Listing 14-3: An `art` library with items organized into `kinds` and `utils`
modules
Figure 14-3 shows what the front page of the documentation for this crate
-generated by `cargo doc` would look like:
-
-<img alt="Rendered documentation for the `art` crate that lists the `kinds` and `utils` modules" src="img/trpl14-03.png" class="center" />
+generated by `cargo doc` would look like.
Figure 14-3: Front page of the documentation for `art` that lists the `kinds`
and `utils` modules
@@ -332,7 +325,7 @@ see them.
Another crate that depends on this library would need `use` statements that
bring the items from `art` into scope, specifying the module structure that’s
currently defined. Listing 14-4 shows an example of a crate that uses the
-`PrimaryColor` and `mix` items from the `art` crate:
+`PrimaryColor` and `mix` items from the `art` crate.
Filename: src/main.rs
@@ -361,7 +354,7 @@ module names in the `use` statements.
To remove the internal organization from the public API, we can modify the
`art` crate code in Listing 14-3 to add `pub use` statements to re-export the
-items at the top level, as shown in Listing 14-5:
+items at the top level, as shown in Listing 14-5.
Filename: src/lib.rs
@@ -375,37 +368,26 @@ pub use self::kinds::SecondaryColor;
pub use self::utils::mix;
pub mod kinds {
- // --snip--
+ --snip--
}
pub mod utils {
- // --snip--
+ --snip--
}
```
-<!-- The example feels a tiny bit awkward. If you're
-going to use `pub use`, in my experience it's probably going
-to happen when you're pulling in definitions from sub-crates.
-In this one, we create modules that we export and also
-re-export symbols from those same modules. In practice,
-you'd probably use sub-crates or move the definitions around. /JT -->
-<!-- I don't want to get into sub-crates here, but I've added a sentence about
-this common usage in the second-to-last paragraph of this section. /Carol -->
-
Listing 14-5: Adding `pub use` statements to re-export items
The API documentation that `cargo doc` generates for this crate will now list
and link re-exports on the front page, as shown in Figure 14-4, making the
`PrimaryColor` and `SecondaryColor` types and the `mix` function easier to find.
-<img alt="Rendered documentation for the `art` crate with the re-exports on the front page" src="img/trpl14-04.png" class="center" />
-
-Figure 14-4: The front page of the documentation for `art`
-that lists the re-exports
+Figure 14-4: The front page of the documentation for `art` that lists the
+re-exports
The `art` crate users can still see and use the internal structure from Listing
14-3 as demonstrated in Listing 14-4, or they can use the more convenient
-structure in Listing 14-5, as shown in Listing 14-6:
+structure in Listing 14-5, as shown in Listing 14-6.
Filename: src/main.rs
@@ -414,7 +396,7 @@ use art::mix;
use art::PrimaryColor;
fn main() {
- // --snip--
+ --snip--
}
```
@@ -423,7 +405,7 @@ Listing 14-6: A program using the re-exported items from the `art` crate
In cases where there are many nested modules, re-exporting the types at the top
level with `pub use` can make a significant difference in the experience of
people who use the crate. Another common use of `pub use` is to re-export
-definitions of a dependency in the current crate to make that crate's
+definitions of a dependency in the current crate to make that crate’s
definitions part of your crate’s public API.
Creating a useful public API structure is more of an art than a science, and
@@ -436,11 +418,11 @@ differs from their public API.
### Setting Up a Crates.io Account
Before you can publish any crates, you need to create an account on
-*https://crates.io/* and get an API token. To do so, visit the home page at
-*https://crates.io/* and log in via a GitHub account. (The GitHub account is
+*https://crates.io* and get an API token. To do so, visit the home page at
+*https://crates.io* and log in via a GitHub account. (The GitHub account is
currently a requirement, but the site might support other ways of creating an
account in the future.) Once you’re logged in, visit your account settings at
-*https://crates.io/me/* and retrieve your API key. Then run the `cargo login`
+*https://crates.io/me* and retrieve your API key. Then run the `cargo login`
command with your API key, like this:
```
@@ -450,7 +432,7 @@ $ cargo login abcdefghijklmnopqrstuvwxyz012345
This command will inform Cargo of your API token and store it locally in
*~/.cargo/credentials*. Note that this token is a *secret*: do not share it
with anyone else. If you do share it with anyone for any reason, you should
-revoke it and generate a new token on *https://crates.io/*.
+revoke it and generate a new token on *https://crates.io*.
### Adding Metadata to a New Crate
@@ -460,7 +442,7 @@ file.
Your crate will need a unique name. While you’re working on a crate locally,
you can name a crate whatever you’d like. However, crate names on
-*https://crates.io/* are allocated on a first-come, first-served basis. Once a
+*https://crates.io* are allocated on a first-come, first-served basis. Once a
crate name is taken, no one else can publish a crate with that name. Before
attempting to publish a crate, search for the name you want to use. If the name
has been used, you will need to find another name and edit the `name` field in
@@ -480,22 +462,26 @@ the crate at this point, you’ll get a warning and then an error:
```
$ cargo publish
Updating crates.io index
-warning: manifest has no description, license, license-file, documentation, homepage or repository.
-See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
+warning: manifest has no description, license, license-file, documentation,
+homepage or repository.
+See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata
+for more info.
--snip--
error: failed to publish to registry at https://crates.io
Caused by:
- the remote server responded with an error: missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata
-```
-
-This errors because you’re missing some crucial information: a description and
-license are required so people will know what your crate does and under what
-terms they can use it. In *Cargo.toml*, add a description that's just a
-sentence or two, because it will appear with your crate in search results. For
-the `license` field, you need to give a *license identifier value*. The Linux
-Foundation’s Software Package Data Exchange (SPDX) at
-*http://spdx.org/licenses/* lists the identifiers you can use for this value.
+ the remote server responded with an error: missing or empty metadata fields:
+description, license. Please see https://doc.rust-
+lang.org/cargo/reference/manifest.html for how to upload metadata
+```
+
+This results in an error because you’re missing some crucial information: a
+description and license are required so people will know what your crate does
+and under what terms they can use it. In *Cargo.toml*, add a description that’s
+just a sentence or two, because it will appear with your crate in search
+results. For the `license` field, you need to give a *license identifier
+value*. The Linux Foundation’s Software Package Data Exchange (SPDX) at
+*http://spdx.org/licenses* lists the identifiers you can use for this value.
For example, to specify that you’ve licensed your crate using the MIT License,
add the `MIT` identifier:
@@ -528,27 +514,28 @@ Filename: Cargo.toml
name = "guessing_game"
version = "0.1.0"
edition = "2021"
-description = "A fun game where you guess what number the computer has chosen."
+description = "A fun game where you guess what number the
+computer has chosen."
license = "MIT OR Apache-2.0"
[dependencies]
```
-Cargo’s documentation at *https://doc.rust-lang.org/cargo/* describes other
-metadata you can specify to ensure others can discover and use your crate more
-easily.
+Cargo’s documentation at *https://doc.rust-lang.org/cargo* describes other
+metadata you can specify to ensure that others can discover and use your crate
+more easily.
### Publishing to Crates.io
Now that you’ve created an account, saved your API token, chosen a name for
your crate, and specified the required metadata, you’re ready to publish!
-Publishing a crate uploads a specific version to *https://crates.io/* for
-others to use.
+Publishing a crate uploads a specific version to *https://crates.io* for others
+to use.
Be careful, because a publish is *permanent*. The version can never be
-overwritten, and the code cannot be deleted. One major goal of crates.io is to
+overwritten, and the code cannot be deleted. One major goal of Crates.io is to
act as a permanent archive of code so that builds of all projects that depend
-on crates from *https://crates.io/* will continue to work. Allowing version
+on crates from *https://crates.io* will continue to work. Allowing version
deletions would make fulfilling that goal impossible. However, there is no
limit to the number of crate versions you can publish.
@@ -572,53 +559,33 @@ anyone can easily add your crate as a dependency of their project.
When you’ve made changes to your crate and are ready to release a new version,
you change the `version` value specified in your *Cargo.toml* file and
-republish. Use the Semantic Versioning rules at *http://semver.org/* to decide
-what an appropriate next version number is based on the kinds of changes you’ve
-made. Then run `cargo publish` to upload the new version.
+republish. Use the Semantic Versioning rules at *http://semver.org* to decide
+what an appropriate next version number is, based on the kinds of changes
+you’ve made. Then run `cargo publish` to upload the new version.
-### Deprecating Versions from Crates.io with `cargo yank`
+### Deprecating Versions from Crates.io with cargo yank
Although you can’t remove previous versions of a crate, you can prevent any
future projects from adding them as a new dependency. This is useful when a
crate version is broken for one reason or another. In such situations, Cargo
-supports *yanking* a crate version.
+supports yanking a crate version.
-Yanking a version prevents new projects from depending on that version while
+*Yanking* a version prevents new projects from depending on that version while
allowing all existing projects that depend on it to continue. Essentially, a
yank means that all projects with a *Cargo.lock* will not break, and any future
*Cargo.lock* files generated will not use the yanked version.
To yank a version of a crate, in the directory of the crate that you’ve
previously published, run `cargo yank` and specify which version you want to
-yank. For example, if we've published a crate named `guessing_game` version
-1.0.1 and we want to yank it, in the project directory for `guessing_game` we'd
+yank. For example, if we’ve published a crate named `guessing_game` version
+1.0.1 and we want to yank it, in the project directory for `guessing_game` we’d
run:
```
$ cargo yank --vers 1.0.1
Updating crates.io index
- Yank guessing_game:1.0.1
-```
-
-<!-- so we run this on a crate, then load that crate onto crates.io? Or does
-this go in a file that's part of the new crate version? /LC -->
-<!-- No, this is a command to run in the directory of a crate that has already
-been published to crates.io. Do you have suggestions on how to make this
-clearer? I've tried a bit above /Carol -->
-<!-- Ah, I see! I think this is clear. JT, does this read okay to you? /LC -->
-<!-- I think this makes sense. Maybe you could make it clear in the example
-that you're in the project directory?
-
-```
-my_project> cargo yank --vers 1.0.1
+ Yank guessing_game@1.0.1
```
-and then show the message that cargo returns when the version is yanked to
-help key them in.
-/JT -->
-<!-- We haven't used that notation anywhere else in the book, of showing the
-current directory in the prompt. I think showing the output is a good idea
-though, so I've added that above and made the introduction to the scenario more
-concrete. /Carol-->
By adding `--undo` to the command, you can also undo a yank and allow projects
to start depending on a version again:
@@ -626,7 +593,7 @@ to start depending on a version again:
```
$ cargo yank --vers 1.0.1 --undo
Updating crates.io index
- Unyank guessing_game_:1.0.1
+ Unyank guessing_game@1.0.1
```
A yank *does not* delete any code. It cannot, for example, delete accidentally
@@ -645,10 +612,10 @@ help manage multiple related packages that are developed in tandem.
A *workspace* is a set of packages that share the same *Cargo.lock* and output
directory. Let’s make a project using a workspace—we’ll use trivial code so we
can concentrate on the structure of the workspace. There are multiple ways to
-structure a workspace, so we'll just show one common way. We’ll have a
+structure a workspace, so we’ll just show one common way. We’ll have a
workspace containing a binary and two libraries. The binary, which will provide
the main functionality, will depend on the two libraries. One library will
-provide an `add_one` function, and a second library an `add_two` function.
+provide an `add_one` function and the other library an `add_two` function.
These three crates will be part of the same workspace. We’ll start by creating
a new directory for the workspace:
@@ -663,14 +630,6 @@ Instead, it will start with a `[workspace]` section that will allow us to add
members to the workspace by specifying the path to the package with our binary
crate; in this case, that path is *adder*:
-<!-- You can have metadata in the top-level Cargo.toml along with the
-`[workspace]` section. We use this in Nushell, for example:
-
-https://github.com/nushell/nushell/blob/main/Cargo.toml
-
- /JT -->
-<!-- Fixed! /Carol -->
-
Filename: Cargo.toml
```
@@ -764,8 +723,8 @@ pub fn add_one(x: i32) -> i32 {
```
Now we can have the `adder` package with our binary depend on the `add_one`
-package that has our library. First, we’ll need to add a path dependency on
-`add_one` to *adder/Cargo.toml*.
+package that has our library. First we’ll need to add a path dependency on
+`add_one` to *adder/Cargo.toml*:
Filename: adder/Cargo.toml
@@ -808,9 +767,9 @@ $ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 0.68s
```
-To run the binary crate from the *add* directory, we can specify which
-package in the workspace we want to run by using the `-p` argument and the
-package name with `cargo run`:
+To run the binary crate from the *add* directory, we can specify which package
+in the workspace we want to run by using the `-p` argument and the package name
+with `cargo run`:
```
$ cargo run -p adder
@@ -837,7 +796,7 @@ Filename: add_one/Cargo.toml
```
[dependencies]
-rand = "0.8.3"
+rand = "0.8.5"
```
We can now add `use rand;` to the *add_one/src/lib.rs* file, and building the
@@ -848,20 +807,10 @@ referring to the `rand` we brought into scope:
```
$ cargo build
Updating crates.io index
- Downloaded rand v0.8.3
+ Downloaded rand v0.8.5
--snip--
- Compiling rand v0.8.3
+ Compiling rand v0.8.5
Compiling add_one v0.1.0 (file:///projects/add/add_one)
-warning: unused import: `rand`
- --> add_one/src/lib.rs:1:5
- |
-1 | use rand;
- | ^^^^
- |
- = note: `#[warn(unused_imports)]` on by default
-
-warning: 1 warning emitted
-
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 10.18s
```
@@ -874,7 +823,7 @@ to the *adder/src/main.rs* file for the `adder` package, we’ll get an error:
```
$ cargo build
- --snip--
+ --snip--
Compiling adder v0.1.0 (file:///projects/add/adder)
error[E0432]: unresolved import `rand`
--> adder/src/main.rs:2:5
@@ -923,24 +872,27 @@ $ cargo test
Compiling add_one v0.1.0 (file:///projects/add/add_one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.27s
- Running target/debug/deps/add_one-f0253159197f7841
+ Running unittests src/lib.rs (target/debug/deps/add_one-f0253159197f7841)
running 1 test
test tests::it_works ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
- Running target/debug/deps/adder-49979ff40686fa8e
+ Running unittests src/main.rs (target/debug/deps/adder-49979ff40686fa8e)
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
Doc-tests add_one
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
```
The first section of the output shows that the `it_works` test in the `add_one`
@@ -955,24 +907,26 @@ we want to test:
```
$ cargo test -p add_one
Finished test [unoptimized + debuginfo] target(s) in 0.00s
- Running target/debug/deps/add_one-b3235fea9a156f74
+ Running unittests src/lib.rs (target/debug/deps/add_one-b3235fea9a156f74)
running 1 test
test tests::it_works ... ok
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
Doc-tests add_one
running 0 tests
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;
+finished in 0.00s
```
This output shows `cargo test` only ran the tests for the `add_one` crate and
didn’t run the `adder` crate tests.
-If you publish the crates in the workspace to *https://crates.io/*, each crate
+If you publish the crates in the workspace to *https://crates.io*, each crate
in the workspace will need to be published separately. Like `cargo test`, we
can publish a particular crate in our workspace by using the `-p` flag and
specifying the name of the crate we want to publish.
@@ -980,17 +934,17 @@ specifying the name of the crate we want to publish.
For additional practice, add an `add_two` crate to this workspace in a similar
way as the `add_one` crate!
-As your project grows, consider using a workspace: it’s easier to understand
-smaller, individual components than one big blob of code. Furthermore, keeping
-the crates in a workspace can make coordination between crates easier if they
-are often changed at the same time.
+As your project grows, consider using a workspace: it provides
+easier-to-understand, smaller, individual components than one big blob of code.
+Furthermore, keeping the crates in a workspace can make coordination between
+crates easier if they are often changed at the same time.
-## Installing Binaries with `cargo install`
+## Installing Binaries with cargo install
The `cargo install` command allows you to install and use binary crates
locally. This isn’t intended to replace system packages; it’s meant to be a
convenient way for Rust developers to install tools that others have shared on
-*https://crates.io/*. Note that you can only install packages that have binary
+*https://crates.io*. Note that you can only install packages that have binary
targets. A *binary target* is the runnable program that is created if the crate
has a *src/main.rs* file or another file specified as a binary, as opposed to a
library target that isn’t runnable on its own but is suitable for including
@@ -1010,35 +964,36 @@ can run the following:
```
$ cargo install ripgrep
Updating crates.io index
- Downloaded ripgrep v11.0.2
+ Downloaded ripgrep v13.0.0
Downloaded 1 crate (243.3 KB) in 0.88s
- Installing ripgrep v11.0.2
---snip--
- Compiling ripgrep v11.0.2
+ Installing ripgrep v13.0.0
+ --snip--
+ Compiling ripgrep v13.0.0
Finished release [optimized + debuginfo] target(s) in 3m 10s
Installing ~/.cargo/bin/rg
- Installed package `ripgrep v11.0.2` (executable `rg`)
+ Installed package `ripgrep v13.0.0` (executable `rg`)
```
The second-to-last line of the output shows the location and the name of the
installed binary, which in the case of `ripgrep` is `rg`. As long as the
installation directory is in your `$PATH`, as mentioned previously, you can
-then run `rg --help` and start using a faster, rustier tool for searching files!
+then run `rg --help` and start using a faster, Rustier tool for searching files!
## Extending Cargo with Custom Commands
Cargo is designed so you can extend it with new subcommands without having to
-modify Cargo. If a binary in your `$PATH` is named `cargo-something`, you can
-run it as if it was a Cargo subcommand by running `cargo something`. Custom
+modify it. If a binary in your `$PATH` is named `cargo-something`, you can run
+it as if it were a Cargo subcommand by running `cargo something`. Custom
commands like this are also listed when you run `cargo --list`. Being able to
use `cargo install` to install extensions and then run them just like the
-built-in Cargo tools is a super convenient benefit of Cargo’s design!
+built-in Cargo tools is a super-convenient benefit of Cargo’s design!
## Summary
-Sharing code with Cargo and *https://crates.io/* is part of what makes the Rust
+Sharing code with Cargo and *https://crates.io* is part of what makes the Rust
ecosystem useful for many different tasks. Rust’s standard library is small and
stable, but crates are easy to share, use, and improve on a timeline different
from that of the language. Don’t be shy about sharing code that’s useful to you
-on *https://crates.io/*; it’s likely that it will be useful to someone else as
+on *https://crates.io*; it’s likely that it will be useful to someone else as
well!
+
diff --git a/src/doc/book/nostarch/chapter15.md b/src/doc/book/nostarch/chapter15.md
index 166277fab..c0e847da1 100644
--- a/src/doc/book/nostarch/chapter15.md
+++ b/src/doc/book/nostarch/chapter15.md
@@ -13,34 +13,34 @@ memory. This address refers to, or “points at,” some other data. The most
common kind of pointer in Rust is a reference, which you learned about in
Chapter 4. References are indicated by the `&` symbol and borrow the value they
point to. They don’t have any special capabilities other than referring to
-data, and have no overhead.
+data, and they have no overhead.
*Smart pointers*, on the other hand, are data structures that act like a
pointer but also have additional metadata and capabilities. The concept of
smart pointers isn’t unique to Rust: smart pointers originated in C++ and exist
in other languages as well. Rust has a variety of smart pointers defined in the
standard library that provide functionality beyond that provided by references.
-To explore the general concept, we'll look at a couple of different examples of
+To explore the general concept, we’ll look at a couple of different examples of
smart pointers, including a *reference counting* smart pointer type. This
pointer enables you to allow data to have multiple owners by keeping track of
the number of owners and, when no owners remain, cleaning up the data.
Rust, with its concept of ownership and borrowing, has an additional difference
between references and smart pointers: while references only borrow data, in
-many cases, smart pointers *own* the data they point to.
+many cases smart pointers *own* the data they point to.
-Though we didn't call them as such at the time, we’ve already encountered a few
+Though we didn’t call them as such at the time, we’ve already encountered a few
smart pointers in this book, including `String` and `Vec<T>` in Chapter 8. Both
-these types count as smart pointers because they own some memory and allow you
-to manipulate it. They also have metadata and extra capabilities or guarantees.
-`String`, for example, stores its capacity as metadata and has the extra
-ability to ensure its data will always be valid UTF-8.
+of these types count as smart pointers because they own some memory and allow
+you to manipulate it. They also have metadata and extra capabilities or
+guarantees. `String`, for example, stores its capacity as metadata and has the
+extra ability to ensure its data will always be valid UTF-8.
Smart pointers are usually implemented using structs. Unlike an ordinary
struct, smart pointers implement the `Deref` and `Drop` traits. The `Deref`
trait allows an instance of the smart pointer struct to behave like a reference
so you can write your code to work with either references or smart pointers.
-The `Drop` trait allows you to customize the code that's run when an instance
+The `Drop` trait allows you to customize the code that’s run when an instance
of the smart pointer goes out of scope. In this chapter, we’ll discuss both
traits and demonstrate why they’re important to smart pointers.
@@ -49,10 +49,10 @@ frequently in Rust, this chapter won’t cover every existing smart pointer. Man
libraries have their own smart pointers, and you can even write your own. We’ll
cover the most common smart pointers in the standard library:
-* `Box<T>` for allocating values on the heap
+* `Box<T>`, for allocating values on the heap
* `Rc<T>`, a reference counting type that enables multiple ownership
* `Ref<T>` and `RefMut<T>`, accessed through `RefCell<T>`, a type that enforces
- the borrowing rules at runtime instead of compile time
+the borrowing rules at runtime instead of compile time
In addition, we’ll cover the *interior mutability* pattern where an immutable
type exposes an API for mutating an interior value. We’ll also discuss
@@ -60,7 +60,7 @@ type exposes an API for mutating an interior value. We’ll also discuss
Let’s dive in!
-## Using `Box<T>` to Point to Data on the Heap
+## Using Box<T> to Point to Data on the Heap
The most straightforward smart pointer is a *box*, whose type is written
`Box<T>`. Boxes allow you to store data on the heap rather than the stack. What
@@ -72,35 +72,35 @@ heap instead of on the stack. But they don’t have many extra capabilities
either. You’ll use them most often in these situations:
* When you have a type whose size can’t be known at compile time and you want
- to use a value of that type in a context that requires an exact size
+to use a value of that type in a context that requires an exact size
* When you have a large amount of data and you want to transfer ownership but
- ensure the data won’t be copied when you do so
+ensure the data won’t be copied when you do so
* When you want to own a value and you care only that it’s a type that
- implements a particular trait rather than being of a specific type
+implements a particular trait rather than being of a specific type
-We’ll demonstrate the first situation in the “Enabling Recursive Types with
-Boxes” section. In the second case, transferring ownership of a large amount of
+We’ll demonstrate the first situation in “Enabling Recursive Types with Boxes”
+on page XX. In the second case, transferring ownership of a large amount of
data can take a long time because the data is copied around on the stack. To
improve performance in this situation, we can store the large amount of data on
the heap in a box. Then, only the small amount of pointer data is copied around
on the stack, while the data it references stays in one place on the heap. The
-third case is known as a *trait object*, and Chapter 17 devotes an entire
-section, “Using Trait Objects That Allow for Values of Different Types,” just
-to that topic. So what you learn here you’ll apply again in Chapter 17!
+third case is known as a *trait object*, and “Using Trait Objects That Allow
+for Values of Different Types” on page XX is devoted to that topic. So what you
+learn here you’ll apply again in that section!
-### Using a `Box<T>` to Store Data on the Heap
+### Using Box<T> to Store Data on the Heap
Before we discuss the heap storage use case for `Box<T>`, we’ll cover the
syntax and how to interact with values stored within a `Box<T>`.
-Listing 15-1 shows how to use a box to store an `i32` value on the heap:
+Listing 15-1 shows how to use a box to store an `i32` value on the heap.
Filename: src/main.rs
```
fn main() {
let b = Box::new(5);
- println!("b = {}", b);
+ println!("b = {b}");
}
```
@@ -118,34 +118,34 @@ Putting a single value on the heap isn’t very useful, so you won’t use boxes
themselves in this way very often. Having values like a single `i32` on the
stack, where they’re stored by default, is more appropriate in the majority of
situations. Let’s look at a case where boxes allow us to define types that we
-wouldn’t be allowed to if we didn’t have boxes.
+wouldn’t be allowed to define if we didn’t have boxes.
### Enabling Recursive Types with Boxes
-A value of *recursive type* can have another value of the same type as part of
-itself. Recursive types pose an issue because at compile time Rust needs to
+A value of a *recursive type* can have another value of the same type as part
+of itself. Recursive types pose an issue because at compile time Rust needs to
know how much space a type takes up. However, the nesting of values of
recursive types could theoretically continue infinitely, so Rust can’t know how
much space the value needs. Because boxes have a known size, we can enable
recursive types by inserting a box in the recursive type definition.
-As an example of a recursive type, let’s explore the *cons list*. This is a data
-type commonly found in functional programming languages. The cons list type
-we’ll define is straightforward except for the recursion; therefore, the
+As an example of a recursive type, let’s explore the *cons list*. This is a
+data type commonly found in functional programming languages. The cons list
+type we’ll define is straightforward except for the recursion; therefore, the
concepts in the example we’ll work with will be useful any time you get into
more complex situations involving recursive types.
#### More Information About the Cons List
A *cons list* is a data structure that comes from the Lisp programming language
-and its dialects and is made up of nested pairs, and is the Lisp version of a
-linked list. Its name comes from the `cons` function (short for “construct
-function”) in Lisp that constructs a new pair from its two arguments. By
+and its dialects, is made up of nested pairs, and is the Lisp version of a
+linked list. Its name comes from the `cons` function (short for *construct
+function*) in Lisp that constructs a new pair from its two arguments. By
calling `cons` on a pair consisting of a value and another pair, we can
construct cons lists made up of recursive pairs.
-For example, here's a pseudocode representation of a cons list containing the
-list 1, 2, 3 with each pair in parentheses:
+For example, here’s a pseudocode representation of a cons list containing the
+list `1, 2, 3` with each pair in parentheses:
```
(1, (2, (3, Nil)))
@@ -181,16 +181,18 @@ Listing 15-2: The first attempt at defining an enum to represent a cons list
data structure of `i32` values
> Note: We’re implementing a cons list that holds only `i32` values for the
-> purposes of this example. We could have implemented it using generics, as we
-> discussed in Chapter 10, to define a cons list type that could store values of
-> any type.
+purposes of this example. We could have implemented it using generics, as we
+discussed in Chapter 10, to define a cons list type that could store values of
+any type.
Using the `List` type to store the list `1, 2, 3` would look like the code in
-Listing 15-3:
+Listing 15-3.
Filename: src/main.rs
```
+--snip--
+
use crate::List::{Cons, Nil};
fn main() {
@@ -206,7 +208,7 @@ is one more `Cons` value that holds `3` and a `List` value, which is finally
`Nil`, the non-recursive variant that signals the end of the list.
If we try to compile the code in Listing 15-3, we get the error shown in
-Listing 15-4:
+Listing 15-4.
```
error[E0072]: recursive type `List` has infinite size
@@ -217,7 +219,11 @@ error[E0072]: recursive type `List` 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 make `List`
+representable
+ |
+2 | Cons(i32, Box<List>),
+ | ++++ +
```
Listing 15-4: The error we get when attempting to define a recursive enum
@@ -225,7 +231,7 @@ Listing 15-4: The error we get when attempting to define a recursive enum
The error shows this type “has infinite size.” The reason is that we’ve defined
`List` with a variant that is recursive: it holds another value of itself
directly. As a result, Rust can’t figure out how much space it needs to store a
-`List` value. Let’s break down why we get this error. First, we'll look at how
+`List` value. Let’s break down why we get this error. First we’ll look at how
Rust decides how much space it needs to store a value of a non-recursive type.
#### Computing the Size of a Non-Recursive Type
@@ -258,23 +264,22 @@ type needs, the compiler looks at the variants, starting with the `Cons`
variant. The `Cons` variant holds a value of type `i32` and a value of type
`List`, and this process continues infinitely, as shown in Figure 15-1.
-<img alt="An infinite Cons list" src="img/trpl15-01.svg" class="center" style="width: 50%;" />
-
Figure 15-1: An infinite `List` consisting of infinite `Cons` variants
-#### Using `Box<T>` to Get a Recursive Type with a Known Size
+#### Using Box<T> to Get a Recursive Type with a Known Size
Because Rust can’t figure out how much space to allocate for recursively
defined types, the compiler gives an error with this helpful suggestion:
```
-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 make `List`
+representable
|
2 | Cons(i32, Box<List>),
- | ^^^^ ^
+ | ++++ +
```
-In this suggestion, “indirection” means that instead of storing a value
+In this suggestion, *indirection* means that instead of storing a value
directly, we should change the data structure to store the value indirectly by
storing a pointer to the value instead.
@@ -288,7 +293,7 @@ this implementation is now more like placing the items next to one another
rather than inside one another.
We can change the definition of the `List` enum in Listing 15-2 and the usage
-of the `List` in Listing 15-3 to the code in Listing 15-5, which will compile:
+of the `List` in Listing 15-3 to the code in Listing 15-5, which will compile.
Filename: src/main.rs
@@ -301,31 +306,38 @@ enum List {
use crate::List::{Cons, Nil};
fn main() {
- let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
+ let list = Cons(
+ 1,
+ Box::new(Cons(
+ 2,
+ Box::new(Cons(
+ 3,
+ Box::new(Nil)
+ ))
+ ))
+ );
}
```
Listing 15-5: Definition of `List` that uses `Box<T>` in order to have a known
size
-The `Cons` variant needs the size of an `i32` plus the space to store the
-box’s pointer data. The `Nil` variant stores no values, so it needs less space
-than the `Cons` variant. We now know that any `List` value will take up the
-size of an `i32` plus the size of a box’s pointer data. By using a box, we’ve
-broken the infinite, recursive chain, so the compiler can figure out the size
-it needs to store a `List` value. Figure 15-2 shows what the `Cons` variant
-looks like now.
+The `Cons` variant needs the size of an `i32` plus the space to store the box’s
+pointer data. The `Nil` variant stores no values, so it needs less space than
+the `Cons` variant. We now know that any `List` value will take up the size of
+an `i32` plus the size of a box’s pointer data. By using a box, we’ve broken
+the infinite, recursive chain, so the compiler can figure out the size it needs
+to store a `List` value. Figure 15-2 shows what the `Cons` variant looks like
+now.
-<img alt="A finite Cons list" src="img/trpl15-02.svg" class="center" />
-
-Figure 15-2: A `List` that is not infinitely sized because `Cons` holds a `Box`
+Figure 15-2: A `List` that is not infinitely sized, because `Cons` holds a `Box`
Boxes provide only the indirection and heap allocation; they don’t have any
other special capabilities, like those we’ll see with the other smart pointer
types. They also don’t have the performance overhead that these special
capabilities incur, so they can be useful in cases like the cons list where the
indirection is the only feature we need. We’ll look at more use cases for boxes
-in Chapter 17, too.
+in Chapter 17.
The `Box<T>` type is a smart pointer because it implements the `Deref` trait,
which allows `Box<T>` values to be treated like references. When a `Box<T>`
@@ -335,7 +347,7 @@ even more important to the functionality provided by the other smart pointer
types we’ll discuss in the rest of this chapter. Let’s explore these two traits
in more detail.
-## Treating Smart Pointers Like Regular References with the `Deref` Trait
+## Treating Smart Pointers Like Regular References with Deref
Implementing the `Deref` trait allows you to customize the behavior of the
*dereference operator* `*` (not to be confused with the multiplication or glob
@@ -347,31 +359,31 @@ Let’s first look at how the dereference operator works with regular references
Then we’ll try to define a custom type that behaves like `Box<T>`, and see why
the dereference operator doesn’t work like a reference on our newly defined
type. We’ll explore how implementing the `Deref` trait makes it possible for
-smart pointers to work in ways similar to references. Then we’ll look at
-Rust’s *deref coercion* feature and how it lets us work with either references
-or smart pointers.
+smart pointers to work in ways similar to references. Then we’ll look at Rust’s
+*deref coercion* feature and how it lets us work with either references or
+smart pointers.
-> Note: there’s one big difference between the `MyBox<T>` type we’re about to
-> build and the real `Box<T>`: our version will not store its data on the heap.
-> We are focusing this example on `Deref`, so where the data is actually stored
-> is less important than the pointer-like behavior.
+> Note: There’s one big difference between the `MyBox<T>` type we’re about to
+build and the real `Box<T>`: our version will not store its data on the heap.
+We are focusing this example on `Deref`, so where the data is actually stored
+is less important than the pointer-like behavior.
### Following the Pointer to the Value
A regular reference is a type of pointer, and one way to think of a pointer is
as an arrow to a value stored somewhere else. In Listing 15-6, we create a
reference to an `i32` value and then use the dereference operator to follow the
-reference to the value:
+reference to the value.
Filename: src/main.rs
```
fn main() {
- [1] let x = 5;
- [2] let y = &x;
+ 1 let x = 5;
+ 2 let y = &x;
- [3] assert_eq!(5, x);
- [4] assert_eq!(5, *y);
+ 3 assert_eq!(5, x);
+ 4 assert_eq!(5, *y);
}
```
@@ -393,31 +405,33 @@ error[E0277]: can't compare `{integer}` with `&{integer}`
--> src/main.rs:6:5
|
6 | assert_eq!(5, y);
- | ^^^^^^^^^^^^^^^^ no implementation for `{integer} == &{integer}`
+ | ^^^^^^^^^^^^^^^^ no implementation for `{integer} ==
+&{integer}`
|
- = help: the trait `PartialEq<&{integer}>` is not implemented for `{integer}`
+ = help: the trait `PartialEq<&{integer}>` is not implemented
+for `{integer}`
```
Comparing a number and a reference to a number isn’t allowed because they’re
different types. We must use the dereference operator to follow the reference
to the value it’s pointing to.
-### Using `Box<T>` Like a Reference
+### Using Box<T> Like a Reference
We can rewrite the code in Listing 15-6 to use a `Box<T>` instead of a
reference; the dereference operator used on the `Box<T>` in Listing 15-7
functions in the same way as the dereference operator used on the reference in
-Listing 15-6:
+Listing 15-6.
Filename: src/main.rs
```
fn main() {
let x = 5;
- [1] let y = Box::new(x);
+ 1 let y = Box::new(x);
assert_eq!(5, x);
- [2] assert_eq!(5, *y);
+ 2 assert_eq!(5, *y);
}
```
@@ -445,18 +459,18 @@ Listing 15-8 defines a `MyBox<T>` type in the same way. We’ll also define a
Filename: src/main.rs
```
-[1] struct MyBox<T>(T);
+ 1 struct MyBox<T>(T);
impl<T> MyBox<T> {
- [2] fn new(x: T) -> MyBox<T> {
- [3] MyBox(x)
+ 2 fn new(x: T) -> MyBox<T> {
+ 3 MyBox(x)
}
}
```
Listing 15-8: Defining a `MyBox<T>` type
-We define a struct named `MyBox` and declare a generic parameter `T` [1],
+We define a struct named `MyBox` and declare a generic parameter `T` [1]
because we want our type to hold values of any type. The `MyBox` type is a
tuple struct with one element of type `T`. The `MyBox::new` function takes one
parameter of type `T` [2] and returns a `MyBox` instance that holds the value
@@ -482,7 +496,7 @@ fn main() {
Listing 15-9: Attempting to use `MyBox<T>` in the same way we used references
and `Box<T>`
-Here’s the resulting compilation error:
+Here’s the resultant compilation error:
```
error[E0614]: type `MyBox<{integer}>` cannot be dereferenced
@@ -496,14 +510,14 @@ Our `MyBox<T>` type can’t be dereferenced because we haven’t implemented tha
ability on our type. To enable dereferencing with the `*` operator, we
implement the `Deref` trait.
-### Treating a Type Like a Reference by Implementing the `Deref` Trait
+### Implementing the Deref Trait
-As discussed in the “Implementing a Trait on a Type” section of Chapter 10, to
-implement a trait, we need to provide implementations for the trait’s required
-methods. The `Deref` trait, provided by the standard library, requires us to
-implement one method named `deref` that borrows `self` and returns a reference
-to the inner data. Listing 15-10 contains an implementation of `Deref` to add
-to the definition of `MyBox`:
+As discussed in “Implementing a Trait on a Type” on page XX, to implement a
+trait we need to provide implementations for the trait’s required methods. The
+`Deref` trait, provided by the standard library, requires us to implement one
+method named `deref` that borrows `self` and returns a reference to the inner
+data. Listing 15-10 contains an implementation of `Deref` to add to the
+definition of `MyBox``<T>`.
Filename: src/main.rs
@@ -511,10 +525,10 @@ Filename: src/main.rs
use std::ops::Deref;
impl<T> Deref for MyBox<T> {
- [1] type Target = T;
+ 1 type Target = T;
fn deref(&self) -> &Self::Target {
- [2] &self.0
+ 2 &self.0
}
}
```
@@ -528,10 +542,10 @@ them in more detail in Chapter 19.
We fill in the body of the `deref` method with `&self.0` so `deref` returns a
reference to the value we want to access with the `*` operator [2]; recall from
-the “Using Tuple Structs without Named Fields to Create Different Types”
-section of Chapter 5 that `.0` accesses the first value in a tuple struct. The
-`main` function in Listing 15-9 that calls `*` on the `MyBox<T>` value now
-compiles, and the assertions pass!
+“Using Tuple Structs Without Named Fields to Create Different Types” on page XX
+that `.0` accesses the first value in a tuple struct. The `main` function in
+Listing 15-9 that calls `*` on the `MyBox<T>` value now compiles, and the
+assertions pass!
Without the `Deref` trait, the compiler can only dereference `&` references.
The `deref` method gives the compiler the ability to take a value of any type
@@ -553,7 +567,7 @@ identically whether we have a regular reference or a type that implements
The reason the `deref` method returns a reference to a value, and that the
plain dereference outside the parentheses in `*(y.deref())` is still necessary,
-is to do with the ownership system. If the `deref` method returned the value
+has to do with the ownership system. If the `deref` method returned the value
directly instead of a reference to the value, the value would be moved out of
`self`. We don’t want to take ownership of the inner value inside `MyBox<T>` in
this case or in most cases where we use the dereference operator.
@@ -584,7 +598,7 @@ can work for either references or smart pointers.
To see deref coercion in action, let’s use the `MyBox<T>` type we defined in
Listing 15-8 as well as the implementation of `Deref` that we added in Listing
15-10. Listing 15-11 shows the definition of a function that has a string slice
-parameter:
+parameter.
Filename: src/main.rs
@@ -597,8 +611,8 @@ fn hello(name: &str) {
Listing 15-11: A `hello` function that has the parameter `name` of type `&str`
We can call the `hello` function with a string slice as an argument, such as
-`hello("Rust");` for example. Deref coercion makes it possible to call `hello`
-with a reference to a value of type `MyBox<String>`, as shown in Listing 15-12:
+`hello("Rust");`, for example. Deref coercion makes it possible to call `hello`
+with a reference to a value of type `MyBox<String>`, as shown in Listing 15-12.
Filename: src/main.rs
@@ -661,10 +675,10 @@ cases:
* From `&mut T` to `&mut U` when `T: DerefMut<Target=U>`
* From `&mut T` to `&U` when `T: Deref<Target=U>`
-The first two cases are the same as each other except that the second
-implements mutability. The first case states that if you have a `&T`, and `T`
-implements `Deref` to some type `U`, you can get a `&U` transparently. The
-second case states that the same deref coercion happens for mutable references.
+The first two cases are the same except that the second implements mutability.
+The first case states that if you have a `&T`, and `T` implements `Deref` to
+some type `U`, you can get a `&U` transparently. The second case states that
+the same deref coercion happens for mutable references.
The third case is trickier: Rust will also coerce a mutable reference to an
immutable one. But the reverse is *not* possible: immutable references will
@@ -678,12 +692,12 @@ the borrowing rules don’t guarantee that. Therefore, Rust can’t make the
assumption that converting an immutable reference to a mutable reference is
possible.
-## Running Code on Cleanup with the `Drop` Trait
+## Running Code on Cleanup with the Drop Trait
The second trait important to the smart pointer pattern is `Drop`, which lets
you customize what happens when a value is about to go out of scope. You can
-provide an implementation for the `Drop` trait on any type, and that code
-can be used to release resources like files or network connections.
+provide an implementation for the `Drop` trait on any type, and that code can
+be used to release resources like files or network connections.
We’re introducing `Drop` in the context of smart pointers because the
functionality of the `Drop` trait is almost always used when implementing a
@@ -692,7 +706,7 @@ space on the heap that the box points to.
In some languages, for some types, the programmer must call code to free memory
or resources every time they finish using an instance of those types. Examples
-include file handles, sockets, or locks. If they forget, the system might
+include file handles, sockets, and locks. If they forget, the system might
become overloaded and crash. In Rust, you can specify that a particular bit of
code be run whenever a value goes out of scope, and the compiler will insert
this code automatically. As a result, you don’t need to be careful about
@@ -706,7 +720,7 @@ let’s implement `drop` with `println!` statements for now.
Listing 15-14 shows a `CustomSmartPointer` struct whose only custom
functionality is that it will print `Dropping CustomSmartPointer!` when the
-instance goes out of scope, to show when Rust runs the `drop` function.
+instance goes out of scope, to show when Rust runs the `drop` method.
Filename: src/main.rs
@@ -715,21 +729,24 @@ struct CustomSmartPointer {
data: String,
}
-[1] impl Drop for CustomSmartPointer {
+1 impl Drop for CustomSmartPointer {
fn drop(&mut self) {
- [2] println!("Dropping CustomSmartPointer with data `{}`!", self.data);
+ 2 println!(
+ "Dropping CustomSmartPointer with data `{}`!",
+ self.data
+ );
}
}
fn main() {
- [3] let c = CustomSmartPointer {
+ 3 let c = CustomSmartPointer {
data: String::from("my stuff"),
};
- [4] let d = CustomSmartPointer {
+ 4 let d = CustomSmartPointer {
data: String::from("other stuff"),
};
- [5] println!("CustomSmartPointers created.");
-[6] }
+ 5 println!("CustomSmartPointers created.");
+6 }
```
Listing 15-14: A `CustomSmartPointer` struct that implements the `Drop` trait
@@ -738,12 +755,12 @@ where we would put our cleanup code
The `Drop` trait is included in the prelude, so we don’t need to bring it into
scope. We implement the `Drop` trait on `CustomSmartPointer` [1] and provide an
implementation for the `drop` method that calls `println!` [2]. The body of the
-`drop` function is where you would place any logic that you wanted to run when
-an instance of your type goes out of scope. We’re printing some text here to
+`drop` method is where you would place any logic that you wanted to run when an
+instance of your type goes out of scope. We’re printing some text here to
demonstrate visually when Rust will call `drop`.
-In `main`, we create two instances of `CustomSmartPointer` [3][4] and then
-print `CustomSmartPointers created` [5]. At the end of `main` [6], our
+In `main`, we create two instances of `CustomSmartPointer` at [3] and [4] and
+then print `CustomSmartPointers created` [5]. At the end of `main` [6], our
instances of `CustomSmartPointer` will go out of scope, and Rust will call the
code we put in the `drop` method [2], printing our final message. Note that we
didn’t need to call the `drop` method explicitly.
@@ -758,26 +775,24 @@ Dropping CustomSmartPointer with data `my stuff`!
Rust automatically called `drop` for us when our instances went out of scope,
calling the code we specified. Variables are dropped in the reverse order of
-their creation, so `d` was dropped before `c`. This example's purpose is to
+their creation, so `d` was dropped before `c`. This example’s purpose is to
give you a visual guide to how the `drop` method works; usually you would
specify the cleanup code that your type needs to run rather than a print
message.
-### Dropping a Value Early with `std::mem::drop`
-
Unfortunately, it’s not straightforward to disable the automatic `drop`
functionality. Disabling `drop` isn’t usually necessary; the whole point of the
`Drop` trait is that it’s taken care of automatically. Occasionally, however,
you might want to clean up a value early. One example is when using smart
pointers that manage locks: you might want to force the `drop` method that
releases the lock so that other code in the same scope can acquire the lock.
-Rust doesn’t let you call the `Drop` trait’s `drop` method manually; instead
+Rust doesn’t let you call the `Drop` trait’s `drop` method manually; instead,
you have to call the `std::mem::drop` function provided by the standard library
if you want to force a value to be dropped before the end of its scope.
If we try to call the `Drop` trait’s `drop` method manually by modifying the
`main` function from Listing 15-14, as shown in Listing 15-15, we’ll get a
-compiler error:
+compiler error.
Filename: src/main.rs
@@ -788,7 +803,9 @@ fn main() {
};
println!("CustomSmartPointer created.");
c.drop();
- println!("CustomSmartPointer dropped before the end of main.");
+ println!(
+ "CustomSmartPointer dropped before the end of main."
+ );
}
```
@@ -805,6 +822,7 @@ error[E0040]: explicit use of destructor method
| --^^^^--
| | |
| | explicit destructor calls not allowed
+ | help: consider using `drop` function: `drop(c)`
```
This error message states that we’re not allowed to explicitly call `drop`. The
@@ -823,9 +841,9 @@ scope, and we can’t call the `drop` method explicitly. So, if we need to force
a value to be cleaned up early, we use the `std::mem::drop` function.
The `std::mem::drop` function is different from the `drop` method in the `Drop`
-trait. We call it by passing as an argument the value we want to force drop.
+trait. We call it by passing as an argument the value we want to force-drop.
The function is in the prelude, so we can modify `main` in Listing 15-15 to
-call the `drop` function, as shown in Listing 15-16:
+call the `drop` function, as shown in Listing 15-16.
Filename: src/main.rs
@@ -836,7 +854,9 @@ fn main() {
};
println!("CustomSmartPointer created.");
drop(c);
- println!("CustomSmartPointer dropped before the end of main.");
+ println!(
+ "CustomSmartPointer dropped before the end of main."
+ );
}
```
@@ -851,7 +871,7 @@ Dropping CustomSmartPointer with data `some data`!
CustomSmartPointer dropped before the end of main.
```
-The text ```Dropping CustomSmartPointer with data `some data`!``` is printed
+The text `Dropping CustomSmartPointer with data `some data`!` is printed
between the `CustomSmartPointer created.` and `CustomSmartPointer dropped
before the end of main.` text, showing that the `drop` method code is called to
drop `c` at that point.
@@ -870,7 +890,7 @@ Now that we’ve examined `Box<T>` and some of the characteristics of smart
pointers, let’s look at a few other smart pointers defined in the standard
library.
-## `Rc<T>`, the Reference Counted Smart Pointer
+## Rc<T>, the Reference Counted Smart Pointer
In the majority of cases, ownership is clear: you know exactly which variable
owns a given value. However, there are cases when a single value might have
@@ -889,7 +909,7 @@ Imagine `Rc<T>` as a TV in a family room. When one person enters to watch TV,
they turn it on. Others can come into the room and watch the TV. When the last
person leaves the room, they turn off the TV because it’s no longer being used.
If someone turns off the TV while others are still watching it, there would be
-uproar from the remaining TV watchers!
+an uproar from the remaining TV watchers!
We use the `Rc<T>` type when we want to allocate some data on the heap for
multiple parts of our program to read and we can’t determine at compile time
@@ -901,23 +921,21 @@ Note that `Rc<T>` is only for use in single-threaded scenarios. When we discuss
concurrency in Chapter 16, we’ll cover how to do reference counting in
multithreaded programs.
-### Using `Rc<T>` to Share Data
+### Using Rc<T> to Share Data
Let’s return to our cons list example in Listing 15-5. Recall that we defined
it using `Box<T>`. This time, we’ll create two lists that both share ownership
-of a third list. Conceptually, this looks similar to Figure 15-3:
-
-<img alt="Two lists that share ownership of a third list" src="img/trpl15-03.svg" class="center" />
+of a third list. Conceptually, this looks similar to Figure 15-3.
Figure 15-3: Two lists, `b` and `c`, sharing ownership of a third list, `a`
-We’ll create list `a` that contains 5 and then 10. Then we’ll make two more
-lists: `b` that starts with 3 and `c` that starts with 4. Both `b` and `c`
-lists will then continue on to the first `a` list containing 5 and 10. In other
-words, both lists will share the first list containing 5 and 10.
+We’ll create list `a` that contains `5` and then `10`. Then we’ll make two more
+lists: `b` that starts with `3` and `c` that starts with `4`. Both `b` and `c`
+lists will then continue on to the first `a` list containing `5` and `10`. In
+other words, both lists will share the first list containing `5` and `10`.
Trying to implement this scenario using our definition of `List` with `Box<T>`
-won’t work, as shown in Listing 15-17:
+won’t work, as shown in Listing 15-17.
Filename: src/main.rs
@@ -931,13 +949,13 @@ use crate::List::{Cons, Nil};
fn main() {
let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
-[1] let b = Cons(3, Box::new(a));
-[2] let c = Cons(4, Box::new(a));
+ 1 let b = Cons(3, Box::new(a));
+ 2 let c = Cons(4, Box::new(a));
}
```
-Listing 15-17: Demonstrating we’re not allowed to have two lists using `Box<T>`
-that try to share ownership of a third list
+Listing 15-17: Demonstrating that we’re not allowed to have two lists using
+`Box<T>` that try to share ownership of a third list
When we compile this code, we get this error:
@@ -946,7 +964,8 @@ error[E0382]: use of moved value: `a`
--> src/main.rs:11:30
|
9 | let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
- | - move occurs because `a` has type `List`, which does not implement the `Copy` trait
+ | - move occurs because `a` has type `List`, which
+does not implement the `Copy` trait
10 | let b = Cons(3, Box::new(a));
| - value moved here
11 | let c = Cons(4, Box::new(a));
@@ -983,22 +1002,22 @@ enum List {
}
use crate::List::{Cons, Nil};
-[1] use std::rc::Rc;
+1 use std::rc::Rc;
fn main() {
-[2] let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
-[3] let b = Cons(3, Rc::clone(&a));
-[4] let c = Cons(4, Rc::clone(&a));
+ 2 let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
+ 3 let b = Cons(3, Rc::clone(&a));
+ 4 let c = Cons(4, Rc::clone(&a));
}
```
Listing 15-18: A definition of `List` that uses `Rc<T>`
We need to add a `use` statement to bring `Rc<T>` into scope [1] because it’s
-not in the prelude. In `main`, we create the list holding 5 and 10 and store it
-in a new `Rc<List>` in `a` [2]. Then when we create `b` [3] and `c` [4], we
-call the `Rc::clone` function and pass a reference to the `Rc<List>` in `a` as
-an argument.
+not in the prelude. In `main`, we create the list holding `5` and `10` and
+store it in a new `Rc<List>` in `a` [2]. Then, when we create `b` [3] and `c`
+[4], we call the `Rc::clone` function and pass a reference to the `Rc<List>` in
+`a` as an argument.
We could have called `a.clone()` rather than `Rc::clone(&a)`, but Rust’s
convention is to use `Rc::clone` in this case. The implementation of
@@ -1011,7 +1030,7 @@ increase the reference count. When looking for performance problems in the
code, we only need to consider the deep-copy clones and can disregard calls to
`Rc::clone`.
-### Cloning an `Rc<T>` Increases the Reference Count
+### Cloning an Rc<T> Increases the Reference Count
Let’s change our working example in Listing 15-18 so we can see the reference
counts changing as we create and drop references to the `Rc<List>` in `a`.
@@ -1022,16 +1041,30 @@ then we can see how the reference count changes when `c` goes out of scope.
Filename: src/main.rs
```
+--snip--
+
fn main() {
let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
- println!("count after creating a = {}", Rc::strong_count(&a));
+ println!(
+ "count after creating a = {}",
+ Rc::strong_count(&a)
+ );
let b = Cons(3, Rc::clone(&a));
- println!("count after creating b = {}", Rc::strong_count(&a));
+ println!(
+ "count after creating b = {}",
+ Rc::strong_count(&a)
+ );
{
let c = Cons(4, Rc::clone(&a));
- println!("count after creating c = {}", Rc::strong_count(&a));
+ println!(
+ "count after creating c = {}",
+ Rc::strong_count(&a)
+ );
}
- println!("count after c goes out of scope = {}", Rc::strong_count(&a));
+ println!(
+ "count after c goes out of scope = {}",
+ Rc::strong_count(&a)
+ );
}
```
@@ -1040,8 +1073,8 @@ Listing 15-19: Printing the reference count
At each point in the program where the reference count changes, we print the
reference count, which we get by calling the `Rc::strong_count` function. This
function is named `strong_count` rather than `count` because the `Rc<T>` type
-also has a `weak_count`; we’ll see what `weak_count` is used for in the
-“Preventing Reference Cycles: Turning an `Rc<T>` into a `Weak<T>`” section.
+also has a `weak_count`; we’ll see what `weak_count` is used for in “Preventing
+Reference Cycles Using Weak<T>” on page XX.
This code prints the following:
@@ -1074,7 +1107,7 @@ section, we’ll discuss the interior mutability pattern and the `RefCell<T>`
type that you can use in conjunction with an `Rc<T>` to work with this
immutability restriction.
-## `RefCell<T>` and the Interior Mutability Pattern
+## RefCell<T> and the Interior Mutability Pattern
*Interior mutability* is a design pattern in Rust that allows you to mutate
data even when there are immutable references to that data; normally, this
@@ -1092,14 +1125,14 @@ safe API, and the outer type is still immutable.
Let’s explore this concept by looking at the `RefCell<T>` type that follows the
interior mutability pattern.
-### Enforcing Borrowing Rules at Runtime with `RefCell<T>`
+### Enforcing Borrowing Rules at Runtime with RefCell<T>
Unlike `Rc<T>`, the `RefCell<T>` type represents single ownership over the data
-it holds. So, what makes `RefCell<T>` different from a type like `Box<T>`?
+it holds. So what makes `RefCell<T>` different from a type like `Box<T>`?
Recall the borrowing rules you learned in Chapter 4:
-* At any given time, you can have *either* (but not both) one mutable reference
- or any number of immutable references.
+* At any given time, you can have *either* one mutable reference or any number
+of immutable references (but not both).
* References must always be valid.
With references and `Box<T>`, the borrowing rules’ invariants are enforced at
@@ -1137,13 +1170,13 @@ multithreaded program in Chapter 16.
Here is a recap of the reasons to choose `Box<T>`, `Rc<T>`, or `RefCell<T>`:
* `Rc<T>` enables multiple owners of the same data; `Box<T>` and `RefCell<T>`
- have single owners.
+have single owners.
* `Box<T>` allows immutable or mutable borrows checked at compile time; `Rc<T>`
- allows only immutable borrows checked at compile time; `RefCell<T>` allows
- immutable or mutable borrows checked at runtime.
+allows only immutable borrows checked at compile time; `RefCell<T>` allows
+immutable or mutable borrows checked at runtime.
* Because `RefCell<T>` allows mutable borrows checked at runtime, you can
- mutate the value inside the `RefCell<T>` even when the `RefCell<T>` is
- immutable.
+mutate the value inside the `RefCell<T>` even when the `RefCell<T>` is
+immutable.
Mutating the value inside an immutable value is the *interior mutability*
pattern. Let’s look at a situation in which interior mutability is useful and
@@ -1154,6 +1187,8 @@ examine how it’s possible.
A consequence of the borrowing rules is that when you have an immutable value,
you can’t borrow it mutably. For example, this code won’t compile:
+Filename: src/main.rs
+
```
fn main() {
let x = 5;
@@ -1164,7 +1199,8 @@ fn main() {
If you tried to compile this code, you’d get the following error:
```
-error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
+error[E0596]: cannot borrow `x` as mutable, as it is not declared
+as mutable
--> src/main.rs:3:13
|
2 | let x = 5;
@@ -1188,13 +1224,13 @@ an immutable value and see why that is useful.
#### A Use Case for Interior Mutability: Mock Objects
Sometimes during testing a programmer will use a type in place of another type,
-in order to observe particular behavior and assert it's implemented correctly.
-This placeholder type is called a *test double*. Think of it in the sense of a
-"stunt double" in filmmaking, where a person steps in and substitutes for an
-actor to do a particular tricky scene. Test doubles stand in for other types
-when we're running tests. *Mock objects* are specific types of test doubles
-that record what happens during a test so you can assert that the correct
-actions took place.
+in order to observe particular behavior and assert that it’s implemented
+correctly. This placeholder type is called a *test double*. Think of it in the
+sense of a stunt double in filmmaking, where a person steps in and substitutes
+for an actor to do a particularly tricky scene. Test doubles stand in for other
+types when we’re running tests. *Mock objects* are specific types of test
+doubles that record what happens during a test so you can assert that the
+correct actions took place.
Rust doesn’t have objects in the same sense as other languages have objects,
and Rust doesn’t have mock object functionality built into the standard library
@@ -1210,15 +1246,15 @@ Our library will only provide the functionality of tracking how close to the
maximum a value is and what the messages should be at what times. Applications
that use our library will be expected to provide the mechanism for sending the
messages: the application could put a message in the application, send an
-email, send a text message, or something else. The library doesn’t need to know
-that detail. All it needs is something that implements a trait we’ll provide
-called `Messenger`. Listing 15-20 shows the library code:
+email, send a text message, or do something else. The library doesn’t need to
+know that detail. All it needs is something that implements a trait we’ll
+provide called `Messenger`. Listing 15-20 shows the library code.
Filename: src/lib.rs
```
pub trait Messenger {
-[1] fn send(&self, msg: &str);
+ 1 fn send(&self, msg: &str);
}
pub struct LimitTracker<'a, T: Messenger> {
@@ -1231,7 +1267,10 @@ impl<'a, T> LimitTracker<'a, T>
where
T: Messenger,
{
- pub fn new(messenger: &'a T, max: usize) -> LimitTracker<'a, T> {
+ pub fn new(
+ messenger: &'a T,
+ max: usize
+ ) -> LimitTracker<'a, T> {
LimitTracker {
messenger,
value: 0,
@@ -1239,19 +1278,21 @@ where
}
}
-[2] pub fn set_value(&mut self, value: usize) {
+ 2 pub fn set_value(&mut self, value: usize) {
self.value = value;
- let percentage_of_max = self.value as f64 / self.max as f64;
+ let percentage_of_max =
+ self.value as f64 / self.max as f64;
if percentage_of_max >= 1.0 {
- self.messenger.send("Error: You are over your quota!");
+ self.messenger
+ .send("Error: You are over your quota!");
} else if percentage_of_max >= 0.9 {
self.messenger
- .send("Urgent warning: You've used up over 90% of your quota!");
+ .send("Urgent: You're at 90% of your quota!");
} else if percentage_of_max >= 0.75 {
self.messenger
- .send("Warning: You've used up over 75% of your quota!");
+ .send("Warning: You're at 75% of your quota!");
}
}
}
@@ -1269,7 +1310,7 @@ part is that we want to test the behavior of the `set_value` method on the
but `set_value` doesn’t return anything for us to make assertions on. We want
to be able to say that if we create a `LimitTracker` with something that
implements the `Messenger` trait and a particular value for `max`, when we pass
-different numbers for `value`, the messenger is told to send the appropriate
+different numbers for `value` the messenger is told to send the appropriate
messages.
We need a mock object that, instead of sending an email or text message when we
@@ -1277,7 +1318,7 @@ call `send`, will only keep track of the messages it’s told to send. We can
create a new instance of the mock object, create a `LimitTracker` that uses the
mock object, call the `set_value` method on `LimitTracker`, and then check that
the mock object has the messages we expect. Listing 15-21 shows an attempt to
-implement a mock object to do just that, but the borrow checker won’t allow it:
+implement a mock object to do just that, but the borrow checker won’t allow it.
Filename: src/lib.rs
@@ -1286,28 +1327,31 @@ Filename: src/lib.rs
mod tests {
use super::*;
- [1] struct MockMessenger {
- [2] sent_messages: Vec<String>,
+ 1 struct MockMessenger {
+ 2 sent_messages: Vec<String>,
}
impl MockMessenger {
- [3] fn new() -> MockMessenger {
+ 3 fn new() -> MockMessenger {
MockMessenger {
sent_messages: vec![],
}
}
}
- [4] impl Messenger for MockMessenger {
+ 4 impl Messenger for MockMessenger {
fn send(&self, message: &str) {
- [5] self.sent_messages.push(String::from(message));
+ 5 self.sent_messages.push(String::from(message));
}
}
#[test]
- [6] fn it_sends_an_over_75_percent_warning_message() {
+ 6 fn it_sends_an_over_75_percent_warning_message() {
let mock_messenger = MockMessenger::new();
- let mut limit_tracker = LimitTracker::new(&mock_messenger, 100);
+ let mut limit_tracker = LimitTracker::new(
+ &mock_messenger,
+ 100
+ );
limit_tracker.set_value(80);
@@ -1329,37 +1373,40 @@ we can give a `MockMessenger` to a `LimitTracker`. In the definition of the
the `MockMessenger` list of `sent_messages`.
In the test, we’re testing what happens when the `LimitTracker` is told to set
-`value` to something that is more than 75 percent of the `max` value [6].
-First, we create a new `MockMessenger`, which will start with an empty list of
+`value` to something that is more than 75 percent of the `max` value [6]. First
+we create a new `MockMessenger`, which will start with an empty list of
messages. Then we create a new `LimitTracker` and give it a reference to the
-new `MockMessenger` and a `max` value of 100. We call the `set_value` method on
-the `LimitTracker` with a value of 80, which is more than 75 percent of 100.
-Then we assert that the list of messages that the `MockMessenger` is keeping
-track of should now have one message in it.
+new `MockMessenger` and a `max` value of `100`. We call the `set_value` method
+on the `LimitTracker` with a value of `80`, which is more than 75 percent of
+100. Then we assert that the list of messages that the `MockMessenger` is
+keeping track of should now have one message in it.
However, there’s one problem with this test, as shown here:
```
-error[E0596]: cannot borrow `self.sent_messages` as mutable, as it is behind a `&` reference
+error[E0596]: cannot borrow `self.sent_messages` as mutable, as it is behind a
+`&` reference
--> src/lib.rs:58:13
|
2 | fn send(&self, msg: &str);
- | ----- help: consider changing that to be a mutable reference: `&mut self`
+ | ----- help: consider changing that to be a mutable reference:
+`&mut self`
...
58 | self.sent_messages.push(String::from(message));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a
+`&` reference, so the data it refers to cannot be borrowed as mutable
```
-We can’t modify the `MockMessenger` to keep track of the messages, because the
+We can’t modify the `MockMessenger` to keep track of the messages because the
`send` method takes an immutable reference to `self`. We also can’t take the
-suggestion from the error text to use `&mut self` instead, because then the
+suggestion from the error text to use `&mut self` instead because then the
signature of `send` wouldn’t match the signature in the `Messenger` trait
-definition (feel free to try and see what error message you get).
+definition (feel free to try it and see what error message you get).
This is a situation in which interior mutability can help! We’ll store the
-`sent_messages` within a `RefCell<T>`, and then the `send` method will be
-able to modify `sent_messages` to store the messages we’ve seen. Listing 15-22
-shows what that looks like:
+`sent_messages` within a `RefCell<T>`, and then the `send` method will be able
+to modify `sent_messages` to store the messages we’ve seen. Listing 15-22 shows
+what that looks like.
Filename: src/lib.rs
@@ -1370,28 +1417,33 @@ mod tests {
use std::cell::RefCell;
struct MockMessenger {
- [1] sent_messages: RefCell<Vec<String>>,
+ 1 sent_messages: RefCell<Vec<String>>,
}
impl MockMessenger {
fn new() -> MockMessenger {
MockMessenger {
- sent_messages: RefCell::new(vec![]) [2],
+ 2 sent_messages: RefCell::new(vec![]),
}
}
}
impl Messenger for MockMessenger {
fn send(&self, message: &str) {
- [3] self.sent_messages.borrow_mut().push(String::from(message));
+ self.sent_messages
+ 3 .borrow_mut()
+ .push(String::from(message));
}
}
#[test]
fn it_sends_an_over_75_percent_warning_message() {
- // --snip--
+ --snip--
- [4] assert_eq!(mock_messenger.sent_messages.borrow().len(), 1);
+ assert_eq!(
+ 4 mock_messenger.sent_messages.borrow().len(),
+ 1
+ );
}
}
```
@@ -1406,9 +1458,9 @@ instance around the empty vector [2].
For the implementation of the `send` method, the first parameter is still an
immutable borrow of `self`, which matches the trait definition. We call
`borrow_mut` on the `RefCell<Vec<String>>` in `self.sent_messages` [3] to get a
-mutable reference to the value inside the `RefCell<Vec<String>>`, which is
-the vector. Then we can call `push` on the mutable reference to the vector to
-keep track of the messages sent during the test.
+mutable reference to the value inside the `RefCell<Vec<String>>`, which is the
+vector. Then we can call `push` on the mutable reference to the vector to keep
+track of the messages sent during the test.
The last change we have to make is in the assertion: to see how many items are
in the inner vector, we call `borrow` on the `RefCell<Vec<String>>` to get an
@@ -1416,7 +1468,7 @@ immutable reference to the vector [4].
Now that you’ve seen how to use `RefCell<T>`, let’s dig into how it works!
-#### Keeping Track of Borrows at Runtime with `RefCell<T>`
+#### Keeping Track of Borrows at Runtime with RefCell<T>
When creating immutable and mutable references, we use the `&` and `&mut`
syntax, respectively. With `RefCell<T>`, we use the `borrow` and `borrow_mut`
@@ -1428,7 +1480,7 @@ can treat them like regular references.
The `RefCell<T>` keeps track of how many `Ref<T>` and `RefMut<T>` smart
pointers are currently active. Every time we call `borrow`, the `RefCell<T>`
increases its count of how many immutable borrows are active. When a `Ref<T>`
-value goes out of scope, the count of immutable borrows goes down by one. Just
+value goes out of scope, the count of immutable borrows goes down by 1. Just
like the compile-time borrowing rules, `RefCell<T>` lets us have many immutable
borrows or one mutable borrow at any point in time.
@@ -1442,15 +1494,15 @@ at runtime.
Filename: src/lib.rs
```
- impl Messenger for MockMessenger {
- fn send(&self, message: &str) {
- let mut one_borrow = self.sent_messages.borrow_mut();
- let mut two_borrow = self.sent_messages.borrow_mut();
+impl Messenger for MockMessenger {
+ fn send(&self, message: &str) {
+ let mut one_borrow = self.sent_messages.borrow_mut();
+ let mut two_borrow = self.sent_messages.borrow_mut();
- one_borrow.push(String::from(message));
- two_borrow.push(String::from(message));
- }
+ one_borrow.push(String::from(message));
+ two_borrow.push(String::from(message));
}
+}
```
Listing 15-23: Creating two mutable references in the same scope to see that
@@ -1473,7 +1525,7 @@ BorrowMutError`. This is how `RefCell<T>` handles violations of the borrowing
rules at runtime.
Choosing to catch borrowing errors at runtime rather than compile time, as
-we've done here, means you'd potentially be finding mistakes in your code later
+we’ve done here, means you’d potentially be finding mistakes in your code later
in the development process: possibly not until your code was deployed to
production. Also, your code would incur a small runtime performance penalty as
a result of keeping track of the borrows at runtime rather than compile time.
@@ -1483,7 +1535,7 @@ in a context where only immutable values are allowed. You can use `RefCell<T>`
despite its trade-offs to get more functionality than regular references
provide.
-### Having Multiple Owners of Mutable Data by Combining `Rc<T>` and `RefCell<T>`
+### Allowing Multiple Owners of Mutable Data with Rc<T> and RefCell<T>
A common way to use `RefCell<T>` is in combination with `Rc<T>`. Recall that
`Rc<T>` lets you have multiple owners of some data, but it only gives immutable
@@ -1493,10 +1545,10 @@ get a value that can have multiple owners *and* that you can mutate!
For example, recall the cons list example in Listing 15-18 where we used
`Rc<T>` to allow multiple lists to share ownership of another list. Because
`Rc<T>` holds only immutable values, we can’t change any of the values in the
-list once we’ve created them. Let’s add in `RefCell<T>` to gain the ability to
+list once we’ve created them. Let’s add in `RefCell<T>` for its ability to
change the values in the lists. Listing 15-24 shows that by using a
`RefCell<T>` in the `Cons` definition, we can modify the value stored in all
-the lists:
+the lists.
Filename: src/main.rs
@@ -1512,14 +1564,14 @@ use std::cell::RefCell;
use std::rc::Rc;
fn main() {
- [1] let value = Rc::new(RefCell::new(5));
+ 1 let value = Rc::new(RefCell::new(5));
- [2] let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
+ 2 let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));
- [3] *value.borrow_mut() += 10;
+ 3 *value.borrow_mut() += 10;
println!("a after = {:?}", a);
println!("b after = {:?}", b);
@@ -1541,13 +1593,13 @@ can both refer to `a`, which is what we did in Listing 15-18.
After we’ve created the lists in `a`, `b`, and `c`, we want to add 10 to the
value in `value` [3]. We do this by calling `borrow_mut` on `value`, which uses
-the automatic dereferencing feature we discussed in Chapter 5 (see the section
-“Where’s the `->` Operator?”) to dereference the `Rc<T>` to the inner
-`RefCell<T>` value. The `borrow_mut` method returns a `RefMut<T>` smart
-pointer, and we use the dereference operator on it and change the inner value.
+the automatic dereferencing feature we discussed in “Where’s the -> Operator?”
+on page XX to dereference the `Rc<T>` to the inner `RefCell<T>` value. The
+`borrow_mut` method returns a `RefMut<T>` smart pointer, and we use the
+dereference operator on it and change the inner value.
When we print `a`, `b`, and `c`, we can see that they all have the modified
-value of 15 rather than 5:
+value of `15` rather than `5`:
```
a after = Cons(RefCell { value: 15 }, Nil)
@@ -1561,7 +1613,7 @@ access to its interior mutability so we can modify our data when we need to.
The runtime checks of the borrowing rules protect us from data races, and it’s
sometimes worth trading a bit of speed for this flexibility in our data
structures. Note that `RefCell<T>` does not work for multithreaded code!
-`Mutex<T>` is the thread-safe version of `RefCell<T>` and we’ll discuss
+`Mutex<T>` is the thread-safe version of `RefCell<T>`, and we’ll discuss
`Mutex<T>` in Chapter 16.
## Reference Cycles Can Leak Memory
@@ -1579,7 +1631,7 @@ will never be dropped.
Let’s look at how a reference cycle might happen and how to prevent it,
starting with the definition of the `List` enum and a `tail` method in Listing
-15-25:
+15-25.
Filename: src/main.rs
@@ -1590,12 +1642,12 @@ use std::rc::Rc;
#[derive(Debug)]
enum List {
- [1] Cons(i32, RefCell<Rc<List>>),
+ 1 Cons(i32, RefCell<Rc<List>>),
Nil,
}
impl List {
- [2] fn tail(&self) -> Option<&RefCell<Rc<List>>> {
+ 2 fn tail(&self) -> Option<&RefCell<Rc<List>>> {
match self {
Cons(_, item) => Some(item),
Nil => None,
@@ -1610,9 +1662,9 @@ modify what a `Cons` variant is referring to
We’re using another variation of the `List` definition from Listing 15-5. The
second element in the `Cons` variant is now `RefCell<Rc<List>>` [1], meaning
that instead of having the ability to modify the `i32` value as we did in
-Listing 15-24, we want to modify the `List` value a `Cons` variant is
-pointing to. We’re also adding a `tail` method [2] to make it convenient for us
-to access the second item if we have a `Cons` variant.
+Listing 15-24, we want to modify the `List` value a `Cons` variant is pointing
+to. We’re also adding a `tail` method [2] to make it convenient for us to
+access the second item if we have a `Cons` variant.
In Listing 15-26, we’re adding a `main` function that uses the definitions in
Listing 15-25. This code creates a list in `a` and a list in `b` that points to
@@ -1624,23 +1676,32 @@ Filename: src/main.rs
```
fn main() {
- [1] let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
+ 1 let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));
println!("a initial rc count = {}", Rc::strong_count(&a));
println!("a next item = {:?}", a.tail());
- [2] let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
+ 2 let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a))));
- println!("a rc count after b creation = {}", Rc::strong_count(&a));
+ println!(
+ "a rc count after b creation = {}",
+ Rc::strong_count(&a)
+ );
println!("b initial rc count = {}", Rc::strong_count(&b));
println!("b next item = {:?}", b.tail());
- [3] if let Some(link) = a.tail() {
- [4] *link.borrow_mut() = Rc::clone(&b);
+ 3 if let Some(link) = a.tail() {
+ 4 *link.borrow_mut() = Rc::clone(&b);
}
- println!("b rc count after changing a = {}", Rc::strong_count(&b));
- println!("a rc count after changing a = {}", Rc::strong_count(&a));
+ println!(
+ "b rc count after changing a = {}",
+ Rc::strong_count(&b)
+ );
+ println!(
+ "a rc count after changing a = {}",
+ Rc::strong_count(&a)
+ );
// Uncomment the next line to see that we have a cycle;
// it will overflow the stack
@@ -1653,8 +1714,8 @@ other
We create an `Rc<List>` instance holding a `List` value in the variable `a`
with an initial list of `5, Nil` [1]. We then create an `Rc<List>` instance
-holding another `List` value in the variable `b` that contains the value 10 and
-points to the list in `a` [2].
+holding another `List` value in the variable `b` that contains the value `10`
+and points to the list in `a` [2].
We modify `a` so it points to `b` instead of `Nil`, creating a cycle. We do
that by using the `tail` method to get a reference to the `RefCell<Rc<List>>`
@@ -1675,30 +1736,28 @@ b rc count after changing a = 2
a rc count after changing a = 2
```
-The reference count of the `Rc<List>` instances in both `a` and `b` are 2 after
+The reference count of the `Rc<List>` instances in both `a` and `b` is 2 after
we change the list in `a` to point to `b`. At the end of `main`, Rust drops the
-variable `b`, which decreases the reference count of the `b` `Rc<List>` instance
-from 2 to 1. The memory that `Rc<List>` has on the heap won’t be dropped at
-this point, because its reference count is 1, not 0. Then Rust drops `a`, which
-decreases the reference count of the `a` `Rc<List>` instance from 2 to 1 as
-well. This instance’s memory can’t be dropped either, because the other
+variable `b`, which decreases the reference count of the `b` `Rc<List>`
+instance from 2 to 1. The memory that `Rc<List>` has on the heap won’t be
+dropped at this point because its reference count is 1, not 0. Then Rust drops
+`a`, which decreases the reference count of the `a` `Rc<List>` instance from 2
+to 1 as well. This instance’s memory can’t be dropped either, because the other
`Rc<List>` instance still refers to it. The memory allocated to the list will
remain uncollected forever. To visualize this reference cycle, we’ve created a
diagram in Figure 15-4.
-<img alt="Reference cycle of lists" src="img/trpl15-04.svg" class="center" />
-
Figure 15-4: A reference cycle of lists `a` and `b` pointing to each other
If you uncomment the last `println!` and run the program, Rust will try to
print this cycle with `a` pointing to `b` pointing to `a` and so forth until it
overflows the stack.
-Compared to a real-world program, the consequences creating a reference cycle
-in this example aren’t very dire: right after we create the reference cycle,
-the program ends. However, if a more complex program allocated lots of memory
-in a cycle and held onto it for a long time, the program would use more memory
-than it needed and might overwhelm the system, causing it to run out of
+Compared to a real-world program, the consequences of creating a reference
+cycle in this example aren’t very dire: right after we create the reference
+cycle, the program ends. However, if a more complex program allocated lots of
+memory in a cycle and held onto it for a long time, the program would use more
+memory than it needed and might overwhelm the system, causing it to run out of
available memory.
Creating reference cycles is not easily done, but it’s not impossible either.
@@ -1719,7 +1778,7 @@ Let’s look at an example using graphs made up of parent nodes and child nodes
to see when non-ownership relationships are an appropriate way to prevent
reference cycles.
-### Preventing Reference Cycles: Turning an `Rc<T>` into a `Weak<T>`
+### Preventing Reference Cycles Using Weak<T>
So far, we’ve demonstrated that calling `Rc::clone` increases the
`strong_count` of an `Rc<T>` instance, and an `Rc<T>` instance is only cleaned
@@ -1727,7 +1786,7 @@ up if its `strong_count` is 0. You can also create a *weak reference* to the
value within an `Rc<T>` instance by calling `Rc::downgrade` and passing a
reference to the `Rc<T>`. Strong references are how you can share ownership of
an `Rc<T>` instance. Weak references don’t express an ownership relationship,
-and their count doesn't affect when an `Rc<T>` instance is cleaned up. They
+and their count doesn’t affect when an `Rc<T>` instance is cleaned up. They
won’t cause a reference cycle because any cycle involving some weak references
will be broken once the strong reference count of values involved is 0.
@@ -1739,7 +1798,7 @@ Instead of increasing the `strong_count` in the `Rc<T>` instance by 1, calling
`Rc<T>` instance to be cleaned up.
Because the value that `Weak<T>` references might have been dropped, to do
-anything with the value that a `Weak<T>` is pointing to, you must make sure the
+anything with the value that a `Weak<T>` is pointing to you must make sure the
value still exists. Do this by calling the `upgrade` method on a `Weak<T>`
instance, which will return an `Option<Rc<T>>`. You’ll get a result of `Some`
if the `Rc<T>` value has not been dropped yet and a result of `None` if the
@@ -1751,7 +1810,7 @@ As an example, rather than using a list whose items know only about the next
item, we’ll create a tree whose items know about their children items *and*
their parent items.
-#### Creating a Tree Data Structure: a `Node` with Child Nodes
+#### Creating a Tree Data Structure: A Node with Child Nodes
To start, we’ll build a tree with nodes that know about their child nodes.
We’ll create a struct named `Node` that holds its own `i32` value as well as
@@ -1777,8 +1836,8 @@ modify which nodes are children of another node, so we have a `RefCell<T>` in
`children` around the `Vec<Rc<Node>>`.
Next, we’ll use our struct definition and create one `Node` instance named
-`leaf` with the value 3 and no children, and another instance named `branch`
-with the value 5 and `leaf` as one of its children, as shown in Listing 15-27:
+`leaf` with the value `3` and no children, and another instance named `branch`
+with the value `5` and `leaf` as one of its children, as shown in Listing 15-27.
Filename: src/main.rs
@@ -1810,7 +1869,7 @@ parent. We’ll do that next.
To make the child node aware of its parent, we need to add a `parent` field to
our `Node` struct definition. The trouble is in deciding what the type of
-`parent` should be. We know it can’t contain an `Rc<T>`, because that would
+`parent` should be. We know it can’t contain an `Rc<T>` because that would
create a reference cycle with `leaf.parent` pointing to `branch` and
`branch.children` pointing to `leaf`, which would cause their `strong_count`
values to never be 0.
@@ -1820,7 +1879,7 @@ children: if a parent node is dropped, its child nodes should be dropped as
well. However, a child should not own its parent: if we drop a child node, the
parent should still exist. This is a case for weak references!
-So instead of `Rc<T>`, we’ll make the type of `parent` use `Weak<T>`,
+So, instead of `Rc<T>`, we’ll make the type of `parent` use `Weak<T>`,
specifically a `RefCell<Weak<Node>>`. Now our `Node` struct definition looks
like this:
@@ -1838,35 +1897,41 @@ struct Node {
}
```
-A node will be able to refer to its parent node but doesn’t own its parent.
-In Listing 15-28, we update `main` to use this new definition so the `leaf`
-node will have a way to refer to its parent, `branch`:
+A node will be able to refer to its parent node but doesn’t own its parent. In
+Listing 15-28, we update `main` to use this new definition so the `leaf` node
+will have a way to refer to its parent, `branch`.
-Filename: src/main.rs
+Filename: src/main.rs
```
fn main() {
let leaf = Rc::new(Node {
value: 3,
- [1] parent: RefCell::new(Weak::new()),
+ 1 parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![]),
});
- [2] println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
+ 2 println!(
+ "leaf parent = {:?}",
+ leaf.parent.borrow().upgrade()
+ );
let branch = Rc::new(Node {
value: 5,
- [3] parent: RefCell::new(Weak::new()),
+ 3 parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![Rc::clone(&leaf)]),
});
- [4] *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
+ 4 *leaf.parent.borrow_mut() = Rc::downgrade(&branch);
- [5] println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
+ 5 println!(
+ "leaf parent = {:?}",
+ leaf.parent.borrow().upgrade()
+ );
}
```
-Listing 15-28: A `leaf` node with a weak reference to its parent node `branch`
+Listing 15-28: A `leaf` node with a weak reference to its parent node, `branch`
Creating the `leaf` node looks similar to Listing 15-27 with the exception of
the `parent` field: `leaf` starts out without a parent, so we create a new,
@@ -1881,13 +1946,13 @@ leaf parent = None
```
When we create the `branch` node, it will also have a new `Weak<Node>`
-reference in the `parent` field [3], because `branch` doesn’t have a parent
+reference in the `parent` field [3] because `branch` doesn’t have a parent
node. We still have `leaf` as one of the children of `branch`. Once we have the
`Node` instance in `branch`, we can modify `leaf` to give it a `Weak<Node>`
reference to its parent [4]. We use the `borrow_mut` method on the
`RefCell<Weak<Node>>` in the `parent` field of `leaf`, and then we use the
`Rc::downgrade` function to create a `Weak<Node>` reference to `branch` from
-the `Rc<Node>` in `branch.`
+the `Rc<Node>` in `branch`.
When we print the parent of `leaf` again [5], this time we’ll get a `Some`
variant holding `branch`: now `leaf` can access its parent! When we print
@@ -1904,13 +1969,13 @@ The lack of infinite output indicates that this code didn’t create a reference
cycle. We can also tell this by looking at the values we get from calling
`Rc::strong_count` and `Rc::weak_count`.
-#### Visualizing Changes to `strong_count` and `weak_count`
+#### Visualizing Changes to strong_count and weak_count
Let’s look at how the `strong_count` and `weak_count` values of the `Rc<Node>`
instances change by creating a new inner scope and moving the creation of
`branch` into that scope. By doing so, we can see what happens when `branch` is
created and then dropped when it goes out of scope. The modifications are shown
-in Listing 15-29:
+in Listing 15-29.
Filename: src/main.rs
@@ -1922,13 +1987,13 @@ fn main() {
children: RefCell::new(vec![]),
});
- [1] println!(
+ 1 println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf),
);
- [2] {
+ 2 {
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
@@ -1937,21 +2002,24 @@ fn main() {
*leaf.parent.borrow_mut() = Rc::downgrade(&branch);
- [3] println!(
+ 3 println!(
"branch strong = {}, weak = {}",
Rc::strong_count(&branch),
Rc::weak_count(&branch),
);
- [4] println!(
+ 4 println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf),
);
- [5] }
+ 5 }
- [6] println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
- [7] println!(
+ 6 println!(
+ "leaf parent = {:?}",
+ leaf.parent.borrow().upgrade()
+ );
+ 7 println!(
"leaf strong = {}, weak = {}",
Rc::strong_count(&leaf),
Rc::weak_count(&leaf),
@@ -1967,7 +2035,7 @@ count of 0 [1]. In the inner scope [2], we create `branch` and associate it
with `leaf`, at which point when we print the counts [3], the `Rc<Node>` in
`branch` will have a strong count of 1 and a weak count of 1 (for `leaf.parent`
pointing to `branch` with a `Weak<Node>`). When we print the counts in `leaf`
-[4], we’ll see it will have a strong count of 2, because `branch` now has a
+[4], we’ll see it will have a strong count of 2 because `branch` now has a
clone of the `Rc<Node>` of `leaf` stored in `branch.children`, but will still
have a weak count of 0.
@@ -1978,7 +2046,7 @@ don’t get any memory leaks!
If we try to access the parent of `leaf` after the end of the scope, we’ll get
`None` again [6]. At the end of the program [7], the `Rc<Node>` in `leaf` has a
-strong count of 1 and a weak count of 0, because the variable `leaf` is now the
+strong count of 1 and a weak count of 0 because the variable `leaf` is now the
only reference to the `Rc<Node>` again.
All of the logic that manages the counts and value dropping is built into
@@ -2005,7 +2073,8 @@ memory leaks and how to prevent them using `Weak<T>`.
If this chapter has piqued your interest and you want to implement your own
smart pointers, check out “The Rustonomicon” at
-*https://doc.rust-lang.org/stable/nomicon/* for more useful information.
+*https://doc.rust-lang.org/stable/nomicon* for more useful information.
Next, we’ll talk about concurrency in Rust. You’ll even learn about a few new
smart pointers.
+
diff --git a/src/doc/book/nostarch/chapter16.md b/src/doc/book/nostarch/chapter16.md
index 1f404f84d..7c5389e4f 100644
--- a/src/doc/book/nostarch/chapter16.md
+++ b/src/doc/book/nostarch/chapter16.md
@@ -16,30 +16,6 @@ computers take advantage of their multiple processors. Historically,
programming in these contexts has been difficult and error prone: Rust hopes to
change that.
-<!-- Concurrent programming isn't necessarily helped by having multiple
-processors. How I've been teaching it is to distinguish the two by their
-workload: concurrent programming serves the needs of I/O-bound workloads and
-parallel programming serves the needs of CPU-bound workloads. If you give
-CPU bound workloads more CPUs, you have the opportunity to possibly go faster
-(assuming sufficient parallelism in the code). For I/O-bound workloads,
-rather than the need to have multiple processors, you need to be able to
-get as many I/O requests in flight and being processed as you can. This
-allows more I/O requests, and as a result better throughput/response time
-on those I/O requests.
-
-We could introduce these concepts and then simplify like we do in a bit to
-say that the design considerations of Rust allow both concurrency and
-parallelism to be done safely (...and for the remainder of the chapter talk
-about those design considerations rather than the specifics for either
-concurrency or parallelism) /JT -->
-<!-- I really don't want to get in the weeds on this because there are many
-other books and resources about concurrency and parallelism because these
-concepts aren't Rust specific. I want this to feel accessible to programmers
-who have never even considered whether their programs are I/O or CPU bound,
-because those are the types of programmers we want to empower (and make them
-feel empowered to create concurrent and/or parallel code) through Rust. So I'm
-deliberately choosing not to change anything here. /Carol -->
-
Initially, the Rust team thought that ensuring memory safety and preventing
concurrency problems were two separate challenges to be solved with different
methods. Over time, the team discovered that the ownership and type systems are
@@ -55,16 +31,16 @@ shipped to production. We’ve nicknamed this aspect of Rust *fearless*
subtle bugs and is easy to refactor without introducing new bugs.
> Note: For simplicity’s sake, we’ll refer to many of the problems as
-> *concurrent* rather than being more precise by saying *concurrent and/or
-> parallel*. If this book were about concurrency and/or parallelism, we’d be
-> more specific. For this chapter, please mentally substitute *concurrent
-> and/or parallel* whenever we use *concurrent*.
+*concurrent* rather than being more precise by saying *concurrent and/or
+parallel*. If this book were about concurrency and/or parallelism, we’d be more
+specific. For this chapter, please mentally substitute *concurrent and/or
+parallel* whenever we use *concurrent*.
Many languages are dogmatic about the solutions they offer for handling
concurrent problems. For example, Erlang has elegant functionality for
message-passing concurrency but has only obscure ways to share state between
threads. Supporting only a subset of possible solutions is a reasonable
-strategy for higher-level languages, because a higher-level language promises
+strategy for higher-level languages because a higher-level language promises
benefits from giving up some control to gain abstractions. However, lower-level
languages are expected to provide the solution with the best performance in any
given situation and have fewer abstractions over the hardware. Therefore, Rust
@@ -76,9 +52,9 @@ Here are the topics we’ll cover in this chapter:
* How to create threads to run multiple pieces of code at the same time
* *Message-passing* concurrency, where channels send messages between threads
* *Shared-state* concurrency, where multiple threads have access to some piece
- of data
+of data
* The `Sync` and `Send` traits, which extend Rust’s concurrency guarantees to
- user-defined types as well as types provided by the standard library
+user-defined types as well as types provided by the standard library
## Using Threads to Run Code Simultaneously
@@ -96,11 +72,11 @@ order in which parts of your code on different threads will run. This can lead
to problems, such as:
* Race conditions, where threads are accessing data or resources in an
- inconsistent order
+inconsistent order
* Deadlocks, where two threads are waiting for each other, preventing both
- threads from continuing
+threads from continuing
* Bugs that happen only in certain situations and are hard to reproduce and fix
- reliably
+reliably
Rust attempts to mitigate the negative effects of using threads, but
programming in a multithreaded context still takes careful thought and requires
@@ -112,14 +88,14 @@ operating systems provide an API the language can call for creating new
threads. The Rust standard library uses a *1:1* model of thread implementation,
whereby a program uses one operating system thread per one language thread.
There are crates that implement other models of threading that make different
-tradeoffs to the 1:1 model.
+trade-offs to the 1:1 model.
-### Creating a New Thread with `spawn`
+### Creating a New Thread with spawn
To create a new thread, we call the `thread::spawn` function and pass it a
closure (we talked about closures in Chapter 13) containing the code we want to
run in the new thread. The example in Listing 16-1 prints some text from a main
-thread and other text from a new thread:
+thread and other text from a new thread.
Filename: src/main.rs
@@ -130,13 +106,13 @@ use std::time::Duration;
fn main() {
thread::spawn(|| {
for i in 1..10 {
- println!("hi number {} from the spawned thread!", i);
+ println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
- println!("hi number {} from the main thread!", i);
+ println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}
}
@@ -174,19 +150,20 @@ If you run this code and only see output from the main thread, or don’t see an
overlap, try increasing the numbers in the ranges to create more opportunities
for the operating system to switch between the threads.
-### Waiting for All Threads to Finish Using `join` Handles
+### Waiting for All Threads to Finish Using join Handles
The code in Listing 16-1 not only stops the spawned thread prematurely most of
the time due to the main thread ending, but because there is no guarantee on
the order in which threads run, we also can’t guarantee that the spawned thread
will get to run at all!
-We can fix the problem of the spawned thread not running or ending prematurely
-by saving the return value of `thread::spawn` in a variable. The return type of
-`thread::spawn` is `JoinHandle`. A `JoinHandle` is an owned value that, when we
-call the `join` method on it, will wait for its thread to finish. Listing 16-2
-shows how to use the `JoinHandle` of the thread we created in Listing 16-1 and
-call `join` to make sure the spawned thread finishes before `main` exits:
+We can fix the problem of the spawned thread not running or of it ending
+prematurely by saving the return value of `thread::spawn` in a variable. The
+return type of `thread::spawn` is `JoinHandle<T>`. A `JoinHandle<T>` is an
+owned value that, when we call the `join` method on it, will wait for its
+thread to finish. Listing 16-2 shows how to use the `JoinHandle<T>` of the
+thread we created in Listing 16-1 and call `join` to make sure the spawned
+thread finishes before `main` exits.
Filename: src/main.rs
@@ -197,13 +174,13 @@ use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
- println!("hi number {} from the spawned thread!", i);
+ println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
for i in 1..5 {
- println!("hi number {} from the main thread!", i);
+ println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}
@@ -211,7 +188,7 @@ fn main() {
}
```
-Listing 16-2: Saving a `JoinHandle` from `thread::spawn` to guarantee the
+Listing 16-2: Saving a `JoinHandle<T>` from `thread::spawn` to guarantee the
thread is run to completion
Calling `join` on the handle blocks the thread currently running until the
@@ -251,7 +228,7 @@ use std::time::Duration;
fn main() {
let handle = thread::spawn(|| {
for i in 1..10 {
- println!("hi number {} from the spawned thread!", i);
+ println!("hi number {i} from the spawned thread!");
thread::sleep(Duration::from_millis(1));
}
});
@@ -259,7 +236,7 @@ fn main() {
handle.join().unwrap();
for i in 1..5 {
- println!("hi number {} from the main thread!", i);
+ println!("hi number {i} from the main thread!");
thread::sleep(Duration::from_millis(1));
}
}
@@ -287,21 +264,21 @@ hi number 4 from the main thread!
Small details, such as where `join` is called, can affect whether or not your
threads run at the same time.
-### Using `move` Closures with Threads
+### Using move Closures with Threads
-We'll often use the `move` keyword with closures passed to `thread::spawn`
+We’ll often use the `move` keyword with closures passed to `thread::spawn`
because the closure will then take ownership of the values it uses from the
environment, thus transferring ownership of those values from one thread to
-another. In the “Capturing the Environment with Closures” section of Chapter
-13, we discussed `move` in the context of closures. Now, we’ll concentrate more
-on the interaction between `move` and `thread::spawn`.
+another. In “Capturing the Environment with Closures” on page XX, we discussed
+`move` in the context of closures. Now we’ll concentrate more on the
+interaction between `move` and `thread::spawn`.
Notice in Listing 16-1 that the closure we pass to `thread::spawn` takes no
arguments: we’re not using any data from the main thread in the spawned
thread’s code. To use data from the main thread in the spawned thread, the
spawned thread’s closure must capture the values it needs. Listing 16-3 shows
an attempt to create a vector in the main thread and use it in the spawned
-thread. However, this won’t yet work, as you’ll see in a moment.
+thread. However, this won’t work yet, as you’ll see in a moment.
Filename: src/main.rs
@@ -328,7 +305,8 @@ should be able to access `v` inside that new thread. But when we compile this
example, we get the following error:
```
-error[E0373]: closure may outlive the current function, but it borrows `v`, which is owned by the current function
+error[E0373]: closure may outlive the current function, but it borrows `v`,
+which is owned by the current function
--> src/main.rs:6:32
|
6 | let handle = thread::spawn(|| {
@@ -344,7 +322,8 @@ note: function requires argument type to outlive `'static`
7 | | println!("Here's a vector: {:?}", v);
8 | | });
| |______^
-help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
+help: to force the closure to take ownership of `v` (and any other referenced
+variables), use the `move` keyword
|
6 | let handle = thread::spawn(move || {
| ++++
@@ -352,11 +331,11 @@ help: to force the closure to take ownership of `v` (and any other referenced va
Rust *infers* how to capture `v`, and because `println!` only needs a reference
to `v`, the closure tries to borrow `v`. However, there’s a problem: Rust can’t
-tell how long the spawned thread will run, so it doesn’t know if the reference
-to `v` will always be valid.
+tell how long the spawned thread will run, so it doesn’t know whether the
+reference to `v` will always be valid.
Listing 16-4 provides a scenario that’s more likely to have a reference to `v`
-that won’t be valid:
+that won’t be valid.
Filename: src/main.rs
@@ -379,10 +358,10 @@ fn main() {
Listing 16-4: A thread with a closure that attempts to capture a reference to
`v` from a main thread that drops `v`
-If Rust allowed us to run this code, there’s a possibility the spawned thread
-would be immediately put in the background without running at all. The spawned
-thread has a reference to `v` inside, but the main thread immediately drops
-`v`, using the `drop` function we discussed in Chapter 15. Then, when the
+If Rust allowed us to run this code, there’s a possibility that the spawned
+thread would be immediately put in the background without running at all. The
+spawned thread has a reference to `v` inside, but the main thread immediately
+drops `v`, using the `drop` function we discussed in Chapter 15. Then, when the
spawned thread starts to execute, `v` is no longer valid, so a reference to it
is also invalid. Oh no!
@@ -390,7 +369,8 @@ To fix the compiler error in Listing 16-3, we can use the error message’s
advice:
```
-help: to force the closure to take ownership of `v` (and any other referenced variables), use the `move` keyword
+help: to force the closure to take ownership of `v` (and any other referenced
+variables), use the `move` keyword
|
6 | let handle = thread::spawn(move || {
| ++++
@@ -399,7 +379,7 @@ help: to force the closure to take ownership of `v` (and any other referenced va
By adding the `move` keyword before the closure, we force the closure to take
ownership of the values it’s using rather than allowing Rust to infer that it
should borrow the values. The modification to Listing 16-3 shown in Listing
-16-5 will compile and run as we intend:
+16-5 will compile and run as we intend.
Filename: src/main.rs
@@ -432,12 +412,14 @@ error[E0382]: use of moved value: `v`
--> src/main.rs:10:10
|
4 | let v = vec![1, 2, 3];
- | - move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
+ | - move occurs because `v` has type `Vec<i32>`, which does not
+implement the `Copy` trait
5 |
6 | let handle = thread::spawn(move || {
| ------- value moved into closure here
7 | println!("Here's a vector: {:?}", v);
- | - variable moved due to use in closure
+ | - variable moved due to use in
+closure
...
10 | drop(v); // oh no!
| ^ value used here after move
@@ -453,38 +435,18 @@ rules when we try to use `v` in the main thread. The `move` keyword overrides
Rust’s conservative default of borrowing; it doesn’t let us violate the
ownership rules.
-With a basic understanding of threads and the thread API, let’s look at what we
-can *do* with threads.
+Now that we’ve covered what threads are and the methods supplied by the thread
+API, let’s look at some situations in which we can use threads.
## Using Message Passing to Transfer Data Between Threads
One increasingly popular approach to ensuring safe concurrency is *message
passing*, where threads or actors communicate by sending each other messages
-containing data. Here’s the idea in a slogan from the Go language
-documentation at *https://golang.org/doc/effective_go.html#concurrency*:
-“Do not communicate by sharing memory; instead, share memory by communicating.”
-
-<!-- are they communicating to decide which thread should be running, or by
-"communicate" do we just mean sharing data? /LC -->
-<!-- Just sharing data. Is there something that should be clarified here? I'm
-not sure what to do because this paragraph doesn't mention deciding which
-thread should be running, it only mentions sharing data, so I'm not sure where
-the possible confusion is coming from. /Carol -->
-<!-- JT, if this will be already obvious to a reader, no changes needed. I just
-wanted to ensure there was no potential confusion around what is being
-communicated /LC -->
-<!-- I like that we want to give a shout-out to Go's thinking process when
-we align, though I made a bit of a face reading the quote. "Share memory" is a
-such a loaded concept that I think people might stumble a bit over the play on
-the technical words.
-
-Funnily the next line following that quote in the Go book is:
-
-"This approach can be taken too far." :D
-/JT -->
-<!-- I think this means JT is fine leaving this the way it is! /Carol -->
-
-To accomplish message-sending concurrency, Rust's standard library provides an
+containing data. Here’s the idea in a slogan from the Go language documentation
+at *https://golang.org/doc/effective_go.html#concurrency*: “Do not communicate
+by sharing memory; instead, share memory by communicating.”
+
+To accomplish message-sending concurrency, Rust’s standard library provides an
implementation of *channels*. A channel is a general programming concept by
which data is sent from one thread to another.
@@ -493,7 +455,7 @@ water, such as a stream or a river. If you put something like a rubber duck
into a river, it will travel downstream to the end of the waterway.
A channel has two halves: a transmitter and a receiver. The transmitter half is
-the upstream location where you put rubber ducks into the river, and the
+the upstream location where you put the rubber duck into the river, and the
receiver half is where the rubber duck ends up downstream. One part of your
code calls methods on the transmitter with the data you want to send, and
another part checks the receiving end for arriving messages. A channel is said
@@ -503,9 +465,9 @@ Here, we’ll work up to a program that has one thread to generate values and
send them down a channel, and another thread that will receive the values and
print them out. We’ll be sending simple values between threads using a channel
to illustrate the feature. Once you’re familiar with the technique, you could
-use channels for any threads that needs to communicate between each other, such
-as a chat system or a system where many threads perform parts of a calculation
-and send the parts to one thread that aggregates the results.
+use channels for any threads that need to communicate with each other, such as
+a chat system or a system where many threads perform parts of a calculation and
+send the parts to one thread that aggregates the results.
First, in Listing 16-6, we’ll create a channel but not do anything with it.
Note that this won’t compile yet because Rust can’t tell what type of values we
@@ -533,14 +495,14 @@ producer for now, but we’ll add multiple producers when we get this example
working.
The `mpsc::channel` function returns a tuple, the first element of which is the
-sending end--the transmitter--and the second element is the receiving end--the
-receiver. The abbreviations `tx` and `rx` are traditionally used in many fields
-for *transmitter* and *receiver* respectively, so we name our variables as such
-to indicate each end. We’re using a `let` statement with a pattern that
-destructures the tuples; we’ll discuss the use of patterns in `let` statements
-and destructuring in Chapter 18. For now, know that using a `let` statement
-this way is a convenient approach to extract the pieces of the tuple returned
-by `mpsc::channel`.
+sending end—the transmitter—and the second element of which is the receiving
+end—the receiver. The abbreviations `tx` and `rx` are traditionally used in
+many fields for *transmitter* and *receiver*, respectively, so we name our
+variables as such to indicate each end. We’re using a `let` statement with a
+pattern that destructures the tuples; we’ll discuss the use of patterns in
+`let` statements and destructuring in Chapter 18. For now, know that using a
+`let` statement in this way is a convenient approach to extract the pieces of
+the tuple returned by `mpsc::channel`.
Let’s move the transmitting end into a spawned thread and have it send one
string so the spawned thread is communicating with the main thread, as shown in
@@ -563,18 +525,18 @@ fn main() {
}
```
-Listing 16-7: Moving `tx` to a spawned thread and sending “hi”
+Listing 16-7: Moving `tx` to a spawned thread and sending `"hi"`
Again, we’re using `thread::spawn` to create a new thread and then using `move`
to move `tx` into the closure so the spawned thread owns `tx`. The spawned
thread needs to own the transmitter to be able to send messages through the
channel.
-The transmitter has a `send` method that takes the value we want to send.
-The `send` method returns a `Result<T, E>` type, so if the receiver has
-already been dropped and there’s nowhere to send a value, the send operation
-will return an error. In this example, we’re calling `unwrap` to panic in case
-of an error. But in a real application, we would handle it properly: return to
+The transmitter has a `send` method that takes the value we want to send. The
+`send` method returns a `Result<T, E>` type, so if the receiver has already
+been dropped and there’s nowhere to send a value, the send operation will
+return an error. In this example, we’re calling `unwrap` to panic in case of an
+error. But in a real application, we would handle it properly: return to
Chapter 9 to review strategies for proper error handling.
In Listing 16-8, we’ll get the value from the receiver in the main thread. This
@@ -596,11 +558,11 @@ fn main() {
});
let received = rx.recv().unwrap();
- println!("Got: {}", received);
+ println!("Got: {received}");
}
```
-Listing 16-8: Receiving the value “hi” in the main thread and printing it
+Listing 16-8: Receiving the value `"hi"` in the main thread and printing it
The receiver has two useful methods: `recv` and `try_recv`. We’re using `recv`,
short for *receive*, which will block the main thread’s execution and wait
@@ -637,7 +599,7 @@ advantage of thinking about ownership throughout your Rust programs. Let’s do
an experiment to show how channels and ownership work together to prevent
problems: we’ll try to use a `val` value in the spawned thread *after* we’ve
sent it down the channel. Try compiling the code in Listing 16-9 to see why
-this code isn’t allowed:
+this code isn’t allowed.
Filename: src/main.rs
@@ -651,11 +613,11 @@ fn main() {
thread::spawn(move || {
let val = String::from("hi");
tx.send(val).unwrap();
- println!("val is {}", val);
+ println!("val is {val}");
});
let received = rx.recv().unwrap();
- println!("Got: {}", received);
+ println!("Got: {received}");
}
```
@@ -673,15 +635,16 @@ error[E0382]: borrow of moved value: `val`
--> src/main.rs:10:31
|
8 | let val = String::from("hi");
- | --- move occurs because `val` has type `String`, which does not implement the `Copy` trait
+ | --- move occurs because `val` has type `String`, which does
+not implement the `Copy` trait
9 | tx.send(val).unwrap();
| --- value moved here
-10 | println!("val is {}", val);
- | ^^^ value borrowed here after move
+10 | println!("val is {val}");
+ | ^^^ value borrowed here after move
```
-Our concurrency mistake has caused a compile time error. The `send` function
-takes ownership of its parameter, and when the value is moved, the receiver
+Our concurrency mistake has caused a compile-time error. The `send` function
+takes ownership of its parameter, and when the value is moved the receiver
takes ownership of it. This stops us from accidentally using the value again
after sending it; the ownership system checks that everything is okay.
@@ -718,24 +681,24 @@ fn main() {
});
for received in rx {
- println!("Got: {}", received);
+ println!("Got: {received}");
}
}
```
-Listing 16-10: Sending multiple messages and pausing between each
+Listing 16-10: Sending multiple messages and pausing between each one
This time, the spawned thread has a vector of strings that we want to send to
the main thread. We iterate over them, sending each individually, and pause
between each by calling the `thread::sleep` function with a `Duration` value of
-1 second.
+one second.
In the main thread, we’re not calling the `recv` function explicitly anymore:
instead, we’re treating `rx` as an iterator. For each value received, we’re
printing it. When the channel is closed, iteration will end.
When running the code in Listing 16-10, you should see the following output
-with a 1-second pause in between each line:
+with a one-second pause in between each line:
```
Got: hi
@@ -750,52 +713,52 @@ the spawned thread.
### Creating Multiple Producers by Cloning the Transmitter
-Earlier we mentioned that `mpsc` was an acronym for *multiple producer,
-single consumer*. Let’s put `mpsc` to use and expand the code in Listing 16-10
-to create multiple threads that all send values to the same receiver. We can do
-so by cloning the transmitter, as shown in Listing 16-11:
+Earlier we mentioned that `mpsc` was an acronym for *multiple producer, single
+consumer*. Let’s put `mpsc` to use and expand the code in Listing 16-10 to
+create multiple threads that all send values to the same receiver. We can do so
+by cloning the transmitter, as shown in Listing 16-11.
Filename: src/main.rs
```
- // --snip--
-
- let (tx, rx) = mpsc::channel();
-
- let tx1 = tx.clone();
- thread::spawn(move || {
- let vals = vec![
- String::from("hi"),
- String::from("from"),
- String::from("the"),
- String::from("thread"),
- ];
-
- for val in vals {
- tx1.send(val).unwrap();
- thread::sleep(Duration::from_secs(1));
- }
- });
+--snip--
+
+let (tx, rx) = mpsc::channel();
+
+let tx1 = tx.clone();
+thread::spawn(move || {
+ let vals = vec![
+ String::from("hi"),
+ String::from("from"),
+ String::from("the"),
+ String::from("thread"),
+ ];
+
+ for val in vals {
+ tx1.send(val).unwrap();
+ thread::sleep(Duration::from_secs(1));
+ }
+});
- thread::spawn(move || {
- let vals = vec![
- String::from("more"),
- String::from("messages"),
- String::from("for"),
- String::from("you"),
- ];
+thread::spawn(move || {
+ let vals = vec![
+ String::from("more"),
+ String::from("messages"),
+ String::from("for"),
+ String::from("you"),
+ ];
- for val in vals {
- tx.send(val).unwrap();
- thread::sleep(Duration::from_secs(1));
- }
- });
-
- for received in rx {
- println!("Got: {}", received);
+ for val in vals {
+ tx.send(val).unwrap();
+ thread::sleep(Duration::from_secs(1));
}
+});
+
+for received in rx {
+ println!("Got: {received}");
+}
- // --snip--
+--snip--
```
Listing 16-11: Sending multiple messages from multiple producers
@@ -828,22 +791,17 @@ concurrency.
## Shared-State Concurrency
-Message passing is a fine way of handling concurrency, but it’s not the only
-one. Another method would be for multiple threads to access the same shared
-data. Consider this part of the slogan from the Go language documentation
-again: “do not communicate by sharing memory.”
-
-<!-- NB: if we decide to do anything with the Go quote above, we also
-reference it here.
-/JT -->
-<!-- Also not changing anything here. /Carol -->
+Message passing is a fine way to handle concurrency, but it’s not the only way.
+Another method would be for multiple threads to access the same shared data.
+Consider this part of the slogan from the Go language documentation again: “Do
+not communicate by sharing memory.”
What would communicating by sharing memory look like? In addition, why would
message-passing enthusiasts caution not to use memory sharing?
-In a way, channels in any programming language are similar to single ownership,
+In a way, channels in any programming language are similar to single ownership
because once you transfer a value down a channel, you should no longer use that
-value. Shared memory concurrency is like multiple ownership: multiple threads
+value. Shared-memory concurrency is like multiple ownership: multiple threads
can access the same memory location at the same time. As you saw in Chapter 15,
where smart pointers made multiple ownership possible, multiple ownership can
add complexity because these different owners need managing. Rust’s type system
@@ -853,7 +811,7 @@ for shared memory.
### Using Mutexes to Allow Access to Data from One Thread at a Time
-*Mutex* is an abbreviation for *mutual exclusion*, as in, a mutex allows only
+*Mutex* is an abbreviation for *mutual exclusion*, as in a mutex allows only
one thread to access some data at any given time. To access the data in a
mutex, a thread must first signal that it wants access by asking to acquire the
mutex’s *lock*. The lock is a data structure that is part of the mutex that
@@ -863,9 +821,9 @@ mutex is described as *guarding* the data it holds via the locking system.
Mutexes have a reputation for being difficult to use because you have to
remember two rules:
-* You must attempt to acquire the lock before using the data.
-* When you’re done with the data that the mutex guards, you must unlock the
- data so other threads can acquire the lock.
+1. You must attempt to acquire the lock before using the data.
+1. When you’re done with the data that the mutex guards, you must unlock the
+data so other threads can acquire the lock.
For a real-world metaphor for a mutex, imagine a panel discussion at a
conference with only one microphone. Before a panelist can speak, they have to
@@ -880,10 +838,10 @@ Management of mutexes can be incredibly tricky to get right, which is why so
many people are enthusiastic about channels. However, thanks to Rust’s type
system and ownership rules, you can’t get locking and unlocking wrong.
-#### The API of `Mutex<T>`
+#### The API of Mutex<T>
As an example of how to use a mutex, let’s start by using a mutex in a
-single-threaded context, as shown in Listing 16-12:
+single-threaded context, as shown in Listing 16-12.
Filename: src/main.rs
@@ -891,14 +849,14 @@ Filename: src/main.rs
use std::sync::Mutex;
fn main() {
- [1] let m = Mutex::new(5);
+ 1 let m = Mutex::new(5);
{
- [2] let mut num = m.lock().unwrap();
- [3] *num = 6;
- [4] }
+ 2 let mut num = m.lock().unwrap();
+ 3 *num = 6;
+ 4 }
- [5] println!("m = {:?}", m);
+ 5 println!("m = {:?}", m);
}
```
@@ -928,19 +886,19 @@ pointer implements `Deref` to point at our inner data; the smart pointer also
has a `Drop` implementation that releases the lock automatically when a
`MutexGuard` goes out of scope, which happens at the end of the inner scope
[4]. As a result, we don’t risk forgetting to release the lock and blocking the
-mutex from being used by other threads, because the lock release happens
+mutex from being used by other threads because the lock release happens
automatically.
After dropping the lock, we can print the mutex value and see that we were able
-to change the inner `i32` to 6 [5].
+to change the inner `i32` to `6` [5].
-#### Sharing a `Mutex<T>` Between Multiple Threads
+#### Sharing a Mutex<T> Between Multiple Threads
-Now, let’s try to share a value between multiple threads using `Mutex<T>`.
-We’ll spin up 10 threads and have them each increment a counter value by 1, so
-the counter goes from 0 to 10. The next example in Listing 16-13 will have
-a compiler error, and we’ll use that error to learn more about using
-`Mutex<T>` and how Rust helps us use it correctly.
+Now let’s try to share a value between multiple threads using `Mutex<T>`. We’ll
+spin up 10 threads and have them each increment a counter value by 1, so the
+counter goes from 0 to 10. The example in Listing 16-13 will have a compiler
+error, and we’ll use that error to learn more about using `Mutex<T>` and how
+Rust helps us use it correctly.
Filename: src/main.rs
@@ -949,27 +907,27 @@ use std::sync::Mutex;
use std::thread;
fn main() {
- [1] let counter = Mutex::new(0);
+ 1 let counter = Mutex::new(0);
let mut handles = vec![];
- [2] for _ in 0..10 {
- [3] let handle = thread::spawn(move || {
- [4] let mut num = counter.lock().unwrap();
+ 2 for _ in 0..10 {
+ 3 let handle = thread::spawn(move || {
+ 4 let mut num = counter.lock().unwrap();
- [5] *num += 1;
+ 5 *num += 1;
});
- [6] handles.push(handle);
+ 6 handles.push(handle);
}
for handle in handles {
- [7] handle.join().unwrap();
+ 7 handle.join().unwrap();
}
- [8] println!("Result: {}", *counter.lock().unwrap());
+ 8 println!("Result: {}", *counter.lock().unwrap());
}
```
-Listing 16-13: Ten threads each increment a counter guarded by a `Mutex<T>`
+Listing 16-13: Ten threads, each incrementing a counter guarded by a `Mutex<T>`
We create a `counter` variable to hold an `i32` inside a `Mutex<T>` [1], as we
did in Listing 16-12. Next, we create 10 threads by iterating over a range of
@@ -991,22 +949,24 @@ error[E0382]: use of moved value: `counter`
--> src/main.rs:9:36
|
5 | let counter = Mutex::new(0);
- | ------- move occurs because `counter` has type `Mutex<i32>`, which does not implement the `Copy` trait
+ | ------- move occurs because `counter` has type `Mutex<i32>`, which
+does not implement the `Copy` trait
...
9 | let handle = thread::spawn(move || {
- | ^^^^^^^ value moved into closure here, in previous iteration of loop
+ | ^^^^^^^ value moved into closure here,
+in previous iteration of loop
10 | let mut num = counter.lock().unwrap();
| ------- use occurs due to use in closure
```
The error message states that the `counter` value was moved in the previous
-iteration of the loop. Rust is telling us that we can’t move the ownership
-of lock `counter` into multiple threads. Let’s fix the compiler error with a
+iteration of the loop. Rust is telling us that we can’t move the ownership of
+lock `counter` into multiple threads. Let’s fix the compiler error with the
multiple-ownership method we discussed in Chapter 15.
#### Multiple Ownership with Multiple Threads
-In Chapter 15, we gave a value multiple owners by using the smart pointer
+In Chapter 15, we gave a value to multiple owners by using the smart pointer
`Rc<T>` to create a reference counted value. Let’s do the same here and see
what happens. We’ll wrap the `Mutex<T>` in `Rc<T>` in Listing 16-14 and clone
the `Rc<T>` before moving ownership to the thread.
@@ -1043,33 +1003,36 @@ fn main() {
Listing 16-14: Attempting to use `Rc<T>` to allow multiple threads to own the
`Mutex<T>`
-Once again, we compile and get... different errors! The compiler is teaching us
-a lot.
+Once again, we compile and get… different errors! The compiler is teaching us a
+lot.
```
-[1] error[E0277]: `Rc<Mutex<i32>>` cannot be sent between threads safely
+error[E0277]: `Rc<Mutex<i32>>` cannot be sent between threads safely 1
--> src/main.rs:11:22
|
11 | let handle = thread::spawn(move || {
| ______________________^^^^^^^^^^^^^_-
| | |
- | | `Rc<Mutex<i32>>` cannot be sent between threads safely
+ | | `Rc<Mutex<i32>>` cannot be sent between threads
+safely
12 | | let mut num = counter.lock().unwrap();
13 | |
14 | | *num += 1;
15 | | });
| |_________- within this `[closure@src/main.rs:11:36: 15:10]`
|
-[2] = help: within `[closure@src/main.rs:11:36: 15:10]`, the trait `Send` is not implemented for `Rc<Mutex<i32>>`
- = note: required because it appears within the type `[closure@src/main.rs:11:36: 15:10]`
+= help: within `[closure@src/main.rs:11:36: 15:10]`, the trait `Send` is not
+implemented for `Rc<Mutex<i32>>` 2
+ = note: required because it appears within the type
+`[closure@src/main.rs:11:36: 15:10]`
note: required by a bound in `spawn`
```
Wow, that error message is very wordy! Here’s the important part to focus on:
-`` `Rc<Mutex<i32>>` cannot be sent between threads safely `` [1]. The compiler
-is also telling us the reason why: ``the trait `Send` is not implemented for
-`Rc<Mutex<i32>>` `` [2]. We’ll talk about `Send` in the next section: it’s one
-of the traits that ensures the types we use with threads are meant for use in
+``Rc<Mutex<i32>>` cannot be sent between threads safely` [1]. The compiler is
+also telling us the reason why: `the trait `Send` is not implemented for
+`Rc<Mutex<i32>>`` [2]. We’ll talk about `Send` in the next section: it’s one of
+the traits that ensures the types we use with threads are meant for use in
concurrent situations.
Unfortunately, `Rc<T>` is not safe to share across threads. When `Rc<T>`
@@ -1081,7 +1044,7 @@ could in turn lead to memory leaks or a value being dropped before we’re done
with it. What we need is a type exactly like `Rc<T>` but one that makes changes
to the reference count in a thread-safe way.
-#### Atomic Reference Counting with `Arc<T>`
+#### Atomic Reference Counting with Arc<T>
Fortunately, `Arc<T>` *is* a type like `Rc<T>` that is safe to use in
concurrent situations. The *a* stands for *atomic*, meaning it’s an *atomically
@@ -1100,7 +1063,7 @@ guarantees atomics provide.
Let’s return to our example: `Arc<T>` and `Rc<T>` have the same API, so we fix
our program by changing the `use` line, the call to `new`, and the call to
-`clone`. The code in Listing 16-15 will finally compile and run:
+`clone`. The code in Listing 16-15 will finally compile and run.
Filename: src/main.rs
@@ -1152,12 +1115,7 @@ standard library. These types provide safe, concurrent, atomic access to
primitive types. We chose to use `Mutex<T>` with a primitive type for this
example so we could concentrate on how `Mutex<T>` works.
-<!-- Do we want to mention that for simple counters we have simpler types in
-the standard library? (eg, AtomicI64 for the above)
-/JT -->
-<!-- Done! /Carol-->
-
-### Similarities Between `RefCell<T>`/`Rc<T>` and `Mutex<T>`/`Arc<T>`
+### Similarities Between RefCell<T>/Rc<T> and Mutex<T>/Arc<T>
You might have noticed that `counter` is immutable but we could get a mutable
reference to the value inside it; this means `Mutex<T>` provides interior
@@ -1180,7 +1138,7 @@ useful information.
We’ll round out this chapter by talking about the `Send` and `Sync` traits and
how we can use them with custom types.
-## Extensible Concurrency with the `Sync` and `Send` Traits
+## Extensible Concurrency with the Send and Sync Traits
Interestingly, the Rust language has *very* few concurrency features. Almost
every concurrency feature we’ve talked about so far in this chapter has been
@@ -1189,9 +1147,9 @@ concurrency are not limited to the language or the standard library; you can
write your own concurrency features or use those written by others.
However, two concurrency concepts are embedded in the language: the
-`std::marker` traits `Sync` and `Send`.
+`std::marker` traits `Send` and `Sync` .
-### Allowing Transference of Ownership Between Threads with `Send`
+### Allowing Transference of Ownership Between Threads with Send
The `Send` marker trait indicates that ownership of values of the type
implementing `Send` can be transferred between threads. Almost every Rust type
@@ -1204,15 +1162,15 @@ performance penalty.
Therefore, Rust’s type system and trait bounds ensure that you can never
accidentally send an `Rc<T>` value across threads unsafely. When we tried to do
-this in Listing 16-14, we got the error `the trait Send is not implemented for
-Rc<Mutex<i32>>`. When we switched to `Arc<T>`, which is `Send`, the code
+this in Listing 16-14, we got the error `the trait `Send` is not implemented
+for `Rc<Mutex<i32>>``. When we switched to `Arc<T>`, which is `Send`, the code
compiled.
Any type composed entirely of `Send` types is automatically marked as `Send` as
well. Almost all primitive types are `Send`, aside from raw pointers, which
we’ll discuss in Chapter 19.
-### Allowing Access from Multiple Threads with `Sync`
+### Allowing Access from Multiple Threads with Sync
The `Sync` marker trait indicates that it is safe for the type implementing
`Sync` to be referenced from multiple threads. In other words, any type `T` is
@@ -1225,10 +1183,9 @@ The smart pointer `Rc<T>` is also not `Sync` for the same reasons that it’s no
family of related `Cell<T>` types are not `Sync`. The implementation of borrow
checking that `RefCell<T>` does at runtime is not thread-safe. The smart
pointer `Mutex<T>` is `Sync` and can be used to share access with multiple
-threads as you saw in the “Sharing a `Mutex<T>` Between Multiple
-Threads” section.
+threads, as you saw in “Sharing a Mutex<T> Between Multiple Threads” on page XX.
-### Implementing `Send` and `Sync` Manually Is Unsafe
+### Implementing Send and Sync Manually Is Unsafe
Because types that are made up of `Send` and `Sync` traits are automatically
also `Send` and `Sync`, we don’t have to implement those traits manually. As
@@ -1239,7 +1196,7 @@ Manually implementing these traits involves implementing unsafe Rust code.
We’ll talk about using unsafe Rust code in Chapter 19; for now, the important
information is that building new concurrent types not made up of `Send` and
`Sync` parts requires careful thought to uphold the safety guarantees. “The
-Rustonomicon” at *https://doc.rust-lang.org/stable/nomicon/* has more
+Rustonomicon” at *https://doc.rust-lang.org/stable/nomicon* has more
information about these guarantees and how to uphold them.
## Summary
@@ -1266,3 +1223,4 @@ go forth and make your programs concurrent, fearlessly!
Next, we’ll talk about idiomatic ways to model problems and structure solutions
as your Rust programs get bigger. In addition, we’ll discuss how Rust’s idioms
relate to those you might be familiar with from object-oriented programming.
+
diff --git a/src/doc/book/nostarch/chapter17.md b/src/doc/book/nostarch/chapter17.md
index f13b1484a..946d20a11 100644
--- a/src/doc/book/nostarch/chapter17.md
+++ b/src/doc/book/nostarch/chapter17.md
@@ -6,29 +6,24 @@ directory, so all fixes need to be made in `/src/`.
[TOC]
-# Object-Oriented Programming Features of Rust
+# Object-Oriented Programming Features
Object-oriented programming (OOP) is a way of modeling programs. Objects as a
programmatic concept were introduced in the programming language Simula in the
1960s. Those objects influenced Alan Kay’s programming architecture in which
objects pass messages to each other. To describe this architecture, he coined
the term *object-oriented programming* in 1967. Many competing definitions
-describe what OOP is, and by some of these definitions Rust is object-oriented,
+describe what OOP is, and by some of these definitions Rust is object oriented
but by others it is not. In this chapter, we’ll explore certain characteristics
-that are commonly considered object-oriented and how those characteristics
+that are commonly considered object oriented and how those characteristics
translate to idiomatic Rust. We’ll then show you how to implement an
object-oriented design pattern in Rust and discuss the trade-offs of doing so
versus implementing a solution using some of Rust’s strengths instead.
-<!-- Nit: we should probably use "object-oriented" throughout, rather using both
-"object-oriented" and "object oriented"
-/JT -->
-<!-- Done! /Carol -->
-
## Characteristics of Object-Oriented Languages
There is no consensus in the programming community about what features a
-language must have to be considered object-oriented. Rust is influenced by many
+language must have to be considered object oriented. Rust is influenced by many
programming paradigms, including OOP; for example, we explored the features
that came from functional programming in Chapter 13. Arguably, OOP languages
share certain common characteristics, namely objects, encapsulation, and
@@ -38,20 +33,20 @@ Rust supports it.
### Objects Contain Data and Behavior
The book *Design Patterns: Elements of Reusable Object-Oriented Software* by
-Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley
-Professional, 1994), colloquially referred to as *The Gang of Four* book, is a
-catalog of object-oriented design patterns. It defines OOP this way:
+Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (Addison-Wesley,
+1994), colloquially referred to as *The Gang of Four* book, is a catalog of
+object-oriented design patterns. It defines OOP in this way:
-> Object-oriented programs are made up of objects. An *object* packages both
-> data and the procedures that operate on that data. The procedures are
-> typically called *methods* or *operations*.
+Object-oriented programs are made up of objects. An *object* packages both data
+and the procedures that operate on that data. The procedures are typically
+called *methods* or *operations*.
-Using this definition, Rust is object-oriented: structs and enums have data,
+Using this definition, Rust is object oriented: structs and enums have data,
and `impl` blocks provide methods on structs and enums. Even though structs and
enums with methods aren’t *called* objects, they provide the same
functionality, according to the Gang of Four’s definition of objects.
-### Encapsulation that Hides Implementation Details
+### Encapsulation That Hides Implementation Details
Another aspect commonly associated with OOP is the idea of *encapsulation*,
which means that the implementation details of an object aren’t accessible to
@@ -66,10 +61,10 @@ keyword to decide which modules, types, functions, and methods in our code
should be public, and by default everything else is private. For example, we
can define a struct `AveragedCollection` that has a field containing a vector
of `i32` values. The struct can also have a field that contains the average of
-the values in the vector, meaning the average doesn’t have to be computed
-on demand whenever anyone needs it. In other words, `AveragedCollection` will
+the values in the vector, meaning the average doesn’t have to be computed on
+demand whenever anyone needs it. In other words, `AveragedCollection` will
cache the calculated average for us. Listing 17-1 has the definition of the
-`AveragedCollection` struct:
+`AveragedCollection` struct.
Filename: src/lib.rs
@@ -87,7 +82,7 @@ The struct is marked `pub` so that other code can use it, but the fields within
the struct remain private. This is important in this case because we want to
ensure that whenever a value is added or removed from the list, the average is
also updated. We do this by implementing `add`, `remove`, and `average` methods
-on the struct, as shown in Listing 17-2:
+on the struct, as shown in Listing 17-2.
Filename: src/lib.rs
@@ -120,18 +115,12 @@ impl AveragedCollection {
}
```
-<!-- The above example will crash with a division by zero if you call it at
-any time when it's empty. Not sure if we want to fix, but thought I'd point
-it out.
-/JT -->
-<!-- It actually won't because f64 / 0 is NaN, not a panic /Carol -->
-
Listing 17-2: Implementations of the public methods `add`, `remove`, and
`average` on `AveragedCollection`
The public methods `add`, `remove`, and `average` are the only ways to access
-or modify data in an instance of `AveragedCollection`. When an item is added
-to `list` using the `add` method or removed using the `remove` method, the
+or modify data in an instance of `AveragedCollection`. When an item is added to
+`list` using the `add` method or removed using the `remove` method, the
implementations of each call the private `update_average` method that handles
updating the `average` field as well.
@@ -145,15 +134,15 @@ Because we’ve encapsulated the implementation details of the struct
`AveragedCollection`, we can easily change aspects, such as the data structure,
in the future. For instance, we could use a `HashSet<i32>` instead of a
`Vec<i32>` for the `list` field. As long as the signatures of the `add`,
-`remove`, and `average` public methods stay the same, code using
+`remove`, and `average` public methods stayed the same, code using
`AveragedCollection` wouldn’t need to change. If we made `list` public instead,
this wouldn’t necessarily be the case: `HashSet<i32>` and `Vec<i32>` have
different methods for adding and removing items, so the external code would
likely have to change if it were modifying `list` directly.
-If encapsulation is a required aspect for a language to be considered
-object-oriented, then Rust meets that requirement. The option to use `pub` or
-not for different parts of code enables encapsulation of implementation details.
+If encapsulation is a required aspect for a language to be considered object
+oriented, then Rust meets that requirement. The option to use `pub` or not for
+different parts of code enables encapsulation of implementation details.
### Inheritance as a Type System and as Code Sharing
@@ -161,8 +150,8 @@ not for different parts of code enables encapsulation of implementation details.
another object’s definition, thus gaining the parent object’s data and behavior
without you having to define them again.
-If a language must have inheritance to be an object-oriented language, then
-Rust is not one. There is no way to define a struct that inherits the parent
+If a language must have inheritance to be object oriented, then Rust is not
+such a language. There is no way to define a struct that inherits the parent
struct’s fields and method implementations without using a macro.
However, if you’re used to having inheritance in your programming toolbox, you
@@ -182,22 +171,6 @@ also override the default implementation of the `summarize` method when we
implement the `Summary` trait, which is similar to a child class overriding the
implementation of a method inherited from a parent class.
-<!-- I'm a bit uncomfortable with the above. I think it's more honest to say
-that Rust doesn't support inheritance unless you use a macro. Saying to use
-the trait system to an OO programmer is going to leave them pretty confused, as
-traits lack of the basics of inheritance: you can't use and modify state, you
-have to use a surrogate type to hold the trait implementation, you can't
-instantiate, and so on.
-
-The example that came to mind: trying to teach OO programmers who want to
-build a UI library with traditional OO techniques using the trait system.
-It's unfortunately not going to work very well, if at all.
-
-A trait's main focus is polymorphism and not inheritance. It's probably
-better for folks coming from OO backgrounds if we just come out and say it, tbh.
-/JT -->
-<!-- I agree, and I've made some edits to the paragraphs above /Carol -->
-
The other reason to use inheritance relates to the type system: to enable a
child type to be used in the same places as the parent type. This is also
called *polymorphism*, which means that you can substitute multiple objects for
@@ -206,12 +179,12 @@ each other at runtime if they share certain characteristics.
> ### Polymorphism
>
> To many people, polymorphism is synonymous with inheritance. But it’s
-> actually a more general concept that refers to code that can work with data
-> of multiple types. For inheritance, those types are generally subclasses.
+actually a more general concept that refers to code that can work with data of
+multiple types. For inheritance, those types are generally subclasses.
>
> Rust instead uses generics to abstract over different possible types and
-> trait bounds to impose constraints on what those types must provide. This is
-> sometimes called *bounded parametric polymorphism*.
+trait bounds to impose constraints on what those types must provide. This is
+sometimes called *bounded parametric polymorphism*.
Inheritance has recently fallen out of favor as a programming design solution
in many programming languages because it’s often at risk of sharing more code
@@ -223,15 +196,6 @@ apply to the subclass. In addition, some languages will only allow single
inheritance (meaning a subclass can only inherit from one class), further
restricting the flexibility of a program’s design.
-<!-- Nit - "inherit from one class" and "single-inheritance" read a bit
-differently to me. Saying you inherit from only one class almost makes it sound
-like that the class you inherit from can't have a parent. Probably minor, just
-made me read that sentence a couple times.
-/JT -->
-<!-- I've included the term "single inheritance" above (it appears that usually
-it's not hyphenated) but kept what was there as an explanation in case the
-reader isn't familiar. /Carol -->
-
For these reasons, Rust takes the different approach of using trait objects
instead of inheritance. Let’s look at how trait objects enable polymorphism in
Rust.
@@ -239,7 +203,7 @@ Rust.
## Using Trait Objects That Allow for Values of Different Types
In Chapter 8, we mentioned that one limitation of vectors is that they can
-store elements of only one type. We created a workaround in Listing 8-10 where
+store elements of only one type. We created a workaround in Listing 8-9 where
we defined a `SpreadsheetCell` enum that had variants to hold integers, floats,
and text. This meant we could store different types of data in each cell and
still have a vector that represented a row of cells. This is a perfectly good
@@ -257,7 +221,7 @@ some types for people to use, such as `Button` or `TextField`. In addition,
instance, one programmer might add an `Image` and another might add a
`SelectBox`.
-We won’t implement a fully fledged GUI library for this example but will show
+We won’t implement a full-fledged GUI library for this example but will show
how the pieces would fit together. At the time of writing the library, we can’t
know and define all the types other programmers might want to create. But we do
know that `gui` needs to keep track of many values of different types, and it
@@ -283,12 +247,12 @@ implementing our specified trait and a table used to look up trait methods on
that type at runtime. We create a trait object by specifying some sort of
pointer, such as a `&` reference or a `Box<T>` smart pointer, then the `dyn`
keyword, and then specifying the relevant trait. (We’ll talk about the reason
-trait objects must use a pointer in Chapter 19 in the section “Dynamically
-Sized Types and the `Sized` Trait.”) We can use trait objects in place of a
-generic or concrete type. Wherever we use a trait object, Rust’s type system
-will ensure at compile time that any value used in that context will implement
-the trait object’s trait. Consequently, we don’t need to know all the possible
-types at compile time.
+trait objects must use a pointer in “Dynamically Sized Types and the Sized
+Trait” on page XX.) We can use trait objects in place of a generic or concrete
+type. Wherever we use a trait object, Rust’s type system will ensure at compile
+time that any value used in that context will implement the trait object’s
+trait. Consequently, we don’t need to know all the possible types at compile
+time.
We’ve mentioned that, in Rust, we refrain from calling structs and enums
“objects” to distinguish them from other languages’ objects. In a struct or
@@ -302,7 +266,7 @@ languages: their specific purpose is to allow abstraction across common
behavior.
Listing 17-3 shows how to define a trait named `Draw` with one method named
-`draw`:
+`draw`.
Filename: src/lib.rs
@@ -317,8 +281,8 @@ Listing 17-3: Definition of the `Draw` trait
This syntax should look familiar from our discussions on how to define traits
in Chapter 10. Next comes some new syntax: Listing 17-4 defines a struct named
`Screen` that holds a vector named `components`. This vector is of type
-`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside
-a `Box` that implements the `Draw` trait.
+`Box<dyn Draw>`, which is a trait object; it’s a stand-in for any type inside a
+`Box` that implements the `Draw` trait.
Filename: src/lib.rs
@@ -332,7 +296,7 @@ Listing 17-4: Definition of the `Screen` struct with a `components` field
holding a vector of trait objects that implement the `Draw` trait
On the `Screen` struct, we’ll define a method named `run` that will call the
-`draw` method on each of its `components`, as shown in Listing 17-5:
+`draw` method on each of its `components`, as shown in Listing 17-5.
Filename: src/lib.rs
@@ -353,8 +317,8 @@ This works differently from defining a struct that uses a generic type
parameter with trait bounds. A generic type parameter can only be substituted
with one concrete type at a time, whereas trait objects allow for multiple
concrete types to fill in for the trait object at runtime. For example, we
-could have defined the `Screen` struct using a generic type and a trait bound
-as in Listing 17-6:
+could have defined the `Screen` struct using a generic type and a trait bound,
+as in Listing 17-6.
Filename: src/lib.rs
@@ -394,7 +358,7 @@ Now we’ll add some types that implement the `Draw` trait. We’ll provide the
`Button` type. Again, actually implementing a GUI library is beyond the scope
of this book, so the `draw` method won’t have any useful implementation in its
body. To imagine what the implementation might look like, a `Button` struct
-might have fields for `width`, `height`, and `label`, as shown in Listing 17-7:
+might have fields for `width`, `height`, and `label`, as shown in Listing 17-7.
Filename: src/lib.rs
@@ -425,8 +389,8 @@ happens when a user clicks the button. These kinds of methods won’t apply to
types like `TextField`.
If someone using our library decides to implement a `SelectBox` struct that has
-`width`, `height`, and `options` fields, they implement the `Draw` trait on the
-`SelectBox` type as well, as shown in Listing 17-8:
+`width`, `height`, and `options` fields, they would implement the `Draw` trait
+on the `SelectBox` type as well, as shown in Listing 17-8.
Filename: src/main.rs
@@ -453,7 +417,7 @@ Our library’s user can now write their `main` function to create a `Screen`
instance. To the `Screen` instance, they can add a `SelectBox` and a `Button`
by putting each in a `Box<T>` to become a trait object. They can then call the
`run` method on the `Screen` instance, which will call `draw` on each of the
-components. Listing 17-9 shows this implementation:
+components. Listing 17-9 shows this implementation.
Filename: src/main.rs
@@ -484,12 +448,6 @@ fn main() {
}
```
-<!-- I'd forgotten the UI components were in this chapter. To close on the
-thought from earlier: we don't use any inheritance in our example, only
-polymorphism. This probably is a vote for my earlier suggestion.
-/JT -->
-<!-- I indeed took the earlier suggestion. /Carol -->
-
Listing 17-9: Using trait objects to store values of different types that
implement the same trait
@@ -500,9 +458,9 @@ means it implements the `draw` method.
This concept—of being concerned only with the messages a value responds to
rather than the value’s concrete type—is similar to the concept of *duck
-typing* in dynamically typed languages: if it walks like a duck and quacks
-like a duck, then it must be a duck! In the implementation of `run` on `Screen`
-in Listing 17-5, `run` doesn’t need to know what the concrete type of each
+typing* in dynamically typed languages: if it walks like a duck and quacks like
+a duck, then it must be a duck! In the implementation of `run` on `Screen` in
+Listing 17-5, `run` doesn’t need to know what the concrete type of each
component is. It doesn’t check whether a component is an instance of a `Button`
or a `SelectBox`, it just calls the `draw` method on the component. By
specifying `Box<dyn Draw>` as the type of the values in the `components`
@@ -516,7 +474,7 @@ if a value doesn’t implement a method but we call it anyway. Rust won’t comp
our code if the values don’t implement the traits that the trait objects need.
For example, Listing 17-10 shows what happens if we try to create a `Screen`
-with a `String` as a component:
+with a `String` as a component.
Filename: src/main.rs
@@ -532,8 +490,8 @@ fn main() {
}
```
-Listing 17-10: Attempting to use a type that doesn’t
-implement the trait object’s trait
+Listing 17-10: Attempting to use a type that doesn’t implement the trait
+object’s trait
We’ll get this error because `String` doesn’t implement the `Draw` trait:
@@ -542,27 +500,28 @@ error[E0277]: the trait bound `String: Draw` is not satisfied
--> src/main.rs:5:26
|
5 | components: vec![Box::new(String::from("Hi"))],
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is not implemented for `String`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Draw` is
+not implemented for `String`
|
= note: required for the cast to the object type `dyn Draw`
```
-This error lets us know that either we’re passing something to `Screen` we
-didn’t mean to pass and so should pass a different type or we should implement
+This error lets us know that either we’re passing something to `Screen` that we
+didn’t mean to pass and so should pass a different type, or we should implement
`Draw` on `String` so that `Screen` is able to call `draw` on it.
### Trait Objects Perform Dynamic Dispatch
-Recall in the “Performance of Code Using Generics” section in Chapter 10 our
-discussion on the monomorphization process performed by the compiler when we
-use trait bounds on generics: the compiler generates nongeneric implementations
-of functions and methods for each concrete type that we use in place of a
-generic type parameter. The code that results from monomorphization is doing
-*static dispatch*, which is when the compiler knows what method you’re calling
-at compile time. This is opposed to *dynamic dispatch*, which is when the
-compiler can’t tell at compile time which method you’re calling. In dynamic
-dispatch cases, the compiler emits code that at runtime will figure out which
-method to call.
+Recall in “Performance of Code Using Generics” on page XX our discussion on the
+monomorphization process performed by the compiler when we use trait bounds on
+generics: the compiler generates nongeneric implementations of functions and
+methods for each concrete type that we use in place of a generic type
+parameter. The code that results from monomorphization is doing *static
+dispatch*, which is when the compiler knows what method you’re calling at
+compile time. This is opposed to *dynamic dispatch*, which is when the compiler
+can’t tell at compile time which method you’re calling. In dynamic dispatch
+cases, the compiler emits code that at runtime will figure out which method to
+call.
When we use trait objects, Rust must use dynamic dispatch. The compiler doesn’t
know all the types that might be used with the code that’s using trait objects,
@@ -581,26 +540,13 @@ pattern is that we define a set of states a value can have internally. The
states are represented by a set of *state objects*, and the value’s behavior
changes based on its state. We’re going to work through an example of a blog
post struct that has a field to hold its state, which will be a state object
-from the set "draft", "review", or "published".
-<!-- can you give a quick example here, something we could visualize? are we
-saying "we define a set of states a value can have as state objects...."? /LC
--->
-<!-- What do you think about this, hinting at the coming example quickly? It
-felt weird to introduce something different only to switch gears in a few
-paragraphs, so is moving the example's introduction here ok? /Carol -->
-<!-- JT, what do you think? /LC -->
-<!-- Seems okay. My one thought coming to the end of the paragraph was "is
-this better than using an enum?" Not sure if we want to sidebar a bit on
-why we chose traits over enums, but some readers might be curious.
-/JT -->
-<!-- I've added a box later titled "Why Not An Enum?" to address this -- I
-think that makes a nice exercise for the reader :) /Carol -->
-
-The state objects share functionality: in Rust, of course, we use
-structs and traits rather than objects and inheritance. Each state object is
-responsible for its own behavior and for governing when it should change into
-another state. The value that holds a state object knows nothing about the
-different behavior of the states or when to transition between states.
+from the set “draft,” “review,” or “published.”
+
+The state objects share functionality: in Rust, of course, we use structs and
+traits rather than objects and inheritance. Each state object is responsible
+for its own behavior and for governing when it should change into another
+state. The value that holds a state object knows nothing about the different
+behavior of the states or when to transition between states.
The advantage of using the state pattern is that, when the business
requirements of the program change, we won’t need to change the code of the
@@ -608,18 +554,18 @@ value holding the state or the code that uses the value. We’ll only need to
update the code inside one of the state objects to change its rules or perhaps
add more state objects.
-First, we’re going to implement the state pattern in a more traditional
+First we’re going to implement the state pattern in a more traditional
object-oriented way, then we’ll use an approach that’s a bit more natural in
-Rust. Let’s dig in to incrementally implementing a blog post workflow using the
+Rust. Let’s dig in to incrementally implement a blog post workflow using the
state pattern.
The final functionality will look like this:
1. A blog post starts as an empty draft.
-2. When the draft is done, a review of the post is requested.
-3. When the post is approved, it gets published.
-4. Only published blog posts return content to print, so unapproved posts can’t
- accidentally be published.
+1. When the draft is done, a review of the post is requested.
+1. When the post is approved, it gets published.
+1. Only published blog posts return content to print, so unapproved posts can’t
+accidentally be published.
Any other changes attempted on a post should have no effect. For example, if we
try to approve a draft blog post before we’ve requested a review, the post
@@ -635,16 +581,16 @@ Filename: src/main.rs
use blog::Post;
fn main() {
- [1] let mut post = Post::new();
+ 1 let mut post = Post::new();
- [2] post.add_text("I ate a salad for lunch today");
- [3] assert_eq!("", post.content());
+ 2 post.add_text("I ate a salad for lunch today");
+ 3 assert_eq!("", post.content());
- [4] post.request_review();
- [5] assert_eq!("", post.content());
+ 4 post.request_review();
+ 5 assert_eq!("", post.content());
- [6] post.approve();
- [7] assert_eq!("I ate a salad for lunch today", post.content());
+ 6 post.approve();
+ 7 assert_eq!("I ate a salad for lunch today", post.content());
}
```
@@ -667,13 +613,13 @@ post will be returned when `content` is called [7].
Notice that the only type we’re interacting with from the crate is the `Post`
type. This type will use the state pattern and will hold a value that will be
one of three state objects representing the various states a post can be
-in—draft, waiting for review, or published. Changing from one state to another
-will be managed internally within the `Post` type. The states change in
-response to the methods called by our library’s users on the `Post` instance,
-but they don’t have to manage the state changes directly. Also, users can’t
-make a mistake with the states, like publishing a post before it’s reviewed.
+in—draft, review, or published. Changing from one state to another will be
+managed internally within the `Post` type. The states change in response to the
+methods called by our library’s users on the `Post` instance, but they don’t
+have to manage the state changes directly. Also, users can’t make a mistake
+with the states, such as publishing a post before it’s reviewed.
-### Defining `Post` and Creating a New Instance in the Draft State
+### Defining Post and Creating a New Instance in the Draft State
Let’s get started on the implementation of the library! We know we need a
public `Post` struct that holds some content, so we’ll start with the
@@ -681,22 +627,6 @@ definition of the struct and an associated public `new` function to create an
instance of `Post`, as shown in Listing 17-12. We’ll also make a private
`State` trait that will define the behavior that all state objects for a `Post`
must have.
-<!-- JT, I had a few questions here about what the state objects and state
-traits are doing. I'd appreciate your view on whether this all reads well with
-nothing missing! /LC -->
-<!-- Seems okay. If you're going to try to use a traditional OO approach in
-Rust, it'll have a bit of this style. I'm glad we include something that's a
-bit more Rust-y at the end of the chapter.
-
-What I might suggest is that we give the reader a bit of a roadmap here to say
-that we're going to explore two solutions to this problem. The first, a more
-traditional approach encoded into Rust, and the second, an approach that's more
-natural to Rust.
-/JT -->
-<!-- Great idea! I've added a bit in the introduction of this section above --
-"First, we’re going to implement the state pattern in a more traditional
-object-oriented way, then we’ll use an approach that’s a bit more natural in
-Rust." /Carol -->
Then `Post` will hold a trait object of `Box<dyn State>` inside an `Option<T>`
in a private field named `state` to hold the state object. You’ll see why the
@@ -713,8 +643,8 @@ pub struct Post {
impl Post {
pub fn new() -> Post {
Post {
- [1] state: Some(Box::new(Draft {})),
- [2] content: String::new(),
+ 1 state: Some(Box::new(Draft {})),
+ 2 content: String::new(),
}
}
}
@@ -737,9 +667,9 @@ want a post to start in.
When we create a new `Post`, we set its `state` field to a `Some` value that
holds a `Box` [1]. This `Box` points to a new instance of the `Draft` struct.
-This ensures whenever we create a new instance of `Post`, it will start out as
-a draft. Because the `state` field of `Post` is private, there is no way to
-create a `Post` in any other state! In the `Post::new` function, we set the
+This ensures that whenever we create a new instance of `Post`, it will start
+out as a draft. Because the `state` field of `Post` is private, there is no way
+to create a `Post` in any other state! In the `Post::new` function, we set the
`content` field to a new, empty `String` [2].
### Storing the Text of the Post Content
@@ -750,13 +680,13 @@ blog post. We implement this as a method, rather than exposing the `content`
field as `pub`, so that later we can implement a method that will control how
the `content` field’s data is read. The `add_text` method is pretty
straightforward, so let’s add the implementation in Listing 17-13 to the `impl
-Post` block:
+Post` block.
Filename: src/lib.rs
```
impl Post {
- // --snip--
+ --snip--
pub fn add_text(&mut self, text: &str) {
self.content.push_str(text);
}
@@ -766,7 +696,7 @@ impl Post {
Listing 17-13: Implementing the `add_text` method to add text to a post’s
`content`
-The `add_text` method takes a mutable reference to `self`, because we’re
+The `add_text` method takes a mutable reference to `self` because we’re
changing the `Post` instance that we’re calling `add_text` on. We then call
`push_str` on the `String` in `content` and pass the `text` argument to add to
the saved `content`. This behavior doesn’t depend on the state the post is in,
@@ -783,13 +713,13 @@ implement the `content` method with the simplest thing that will fulfill this
requirement: always returning an empty string slice. We’ll change this later
once we implement the ability to change a post’s state so it can be published.
So far, posts can only be in the draft state, so the post content should always
-be empty. Listing 17-14 shows this placeholder implementation:
+be empty. Listing 17-14 shows this placeholder implementation.
Filename: src/lib.rs
```
impl Post {
- // --snip--
+ --snip--
pub fn content(&self) -> &str {
""
}
@@ -802,32 +732,32 @@ Listing 17-14: Adding a placeholder implementation for the `content` method on
With this added `content` method, everything in Listing 17-11 up to the line at
[3] works as intended.
-### Requesting a Review of the Post Changes Its State
+### Requesting a Review Changes the Post’s State
Next, we need to add functionality to request a review of a post, which should
-change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code:
+change its state from `Draft` to `PendingReview`. Listing 17-15 shows this code.
Filename: src/lib.rs
```
impl Post {
- // --snip--
- [1] pub fn request_review(&mut self) {
- [2] if let Some(s) = self.state.take() {
- [3] self.state = Some(s.request_review())
+ --snip--
+ 1 pub fn request_review(&mut self) {
+ 2 if let Some(s) = self.state.take() {
+ 3 self.state = Some(s.request_review())
}
}
}
trait State {
- [4] fn request_review(self: Box<Self>) -> Box<dyn State>;
+ 4 fn request_review(self: Box<Self>) -> Box<dyn State>;
}
struct Draft {}
impl State for Draft {
fn request_review(self: Box<Self>) -> Box<dyn State> {
- [5] Box::new(PendingReview {})
+ 5 Box::new(PendingReview {})
}
}
@@ -835,7 +765,7 @@ struct PendingReview {}
impl State for PendingReview {
fn request_review(self: Box<Self>) -> Box<dyn State> {
- [6] self
+ 6 self
}
}
```
@@ -859,7 +789,7 @@ ownership of `Box<Self>`, invalidating the old state so the state value of the
To consume the old state, the `request_review` method needs to take ownership
of the state value. This is where the `Option` in the `state` field of `Post`
comes in: we call the `take` method to take the `Some` value out of the `state`
-field and leave a `None` in its place, because Rust doesn’t let us have
+field and leave a `None` in its place because Rust doesn’t let us have
unpopulated fields in structs [2]. This lets us move the `state` value out of
`Post` rather than borrowing it. Then we’ll set the post’s `state` value to the
result of this operation.
@@ -872,7 +802,7 @@ we’ve transformed it into a new state.
The `request_review` method on `Draft` returns a new, boxed instance of a new
`PendingReview` struct [5], which represents the state when a post is waiting
for a review. The `PendingReview` struct also implements the `request_review`
-method but doesn’t do any transformations. Rather, it returns itself [6],
+method but doesn’t do any transformations. Rather, it returns itself [6]
because when we request a review on a post already in the `PendingReview`
state, it should stay in the `PendingReview` state.
@@ -885,17 +815,17 @@ slice. We can now have a `Post` in the `PendingReview` state as well as in the
`Draft` state, but we want the same behavior in the `PendingReview` state.
Listing 17-11 now works up to the line at [5]!
-### Adding `approve` to Change the Behavior of `content`
+### Adding approve to Change the Behavior of content
The `approve` method will be similar to the `request_review` method: it will
set `state` to the value that the current state says it should have when that
-state is approved, as shown in Listing 17-16:
+state is approved, as shown in Listing 17-16.
Filename: src/lib.rs
```
impl Post {
- // --snip--
+ --snip--
pub fn approve(&mut self) {
if let Some(s) = self.state.take() {
self.state = Some(s.approve())
@@ -911,18 +841,18 @@ trait State {
struct Draft {}
impl State for Draft {
- // --snip--
+ --snip--
fn approve(self: Box<Self>) -> Box<dyn State> {
- [1] self
+ 1 self
}
}
struct PendingReview {}
impl State for PendingReview {
- // --snip--
+ --snip--
fn approve(self: Box<Self>) -> Box<dyn State> {
- [2] Box::new(Published {})
+ 2 Box::new(Published {})
}
}
@@ -949,33 +879,33 @@ Similar to the way `request_review` on `PendingReview` works, if we call the
return `self` [1]. When we call `approve` on `PendingReview`, it returns a new,
boxed instance of the `Published` struct [2]. The `Published` struct implements
the `State` trait, and for both the `request_review` method and the `approve`
-method, it returns itself, because the post should stay in the `Published`
-state in those cases.
+method, it returns itself because the post should stay in the `Published` state
+in those cases.
Now we need to update the `content` method on `Post`. We want the value
returned from `content` to depend on the current state of the `Post`, so we’re
going to have the `Post` delegate to a `content` method defined on its `state`,
-as shown in Listing 17-17:
+as shown in Listing 17-17.
Filename: src/lib.rs
```
impl Post {
- // --snip--
+ --snip--
pub fn content(&self) -> &str {
self.state.as_ref().unwrap().content(self)
}
- // --snip--
+ --snip--
}
```
Listing 17-17: Updating the `content` method on `Post` to delegate to a
`content` method on `State`
-Because the goal is to keep all these rules inside the structs that implement
-`State`, we call a `content` method on the value in `state` and pass the post
-instance (that is, `self`) as an argument. Then we return the value that’s
-returned from using the `content` method on the `state` value.
+Because the goal is to keep all of these rules inside the structs that
+implement `State`, we call a `content` method on the value in `state` and pass
+the post instance (that is, `self`) as an argument. Then we return the value
+that’s returned from using the `content` method on the `state` value.
We call the `as_ref` method on the `Option` because we want a reference to the
value inside the `Option` rather than ownership of the value. Because `state`
@@ -983,37 +913,37 @@ is an `Option<Box<dyn State>>`, when we call `as_ref`, an `Option<&Box<dyn
State>>` is returned. If we didn’t call `as_ref`, we would get an error because
we can’t move `state` out of the borrowed `&self` of the function parameter.
-We then call the `unwrap` method, which we know will never panic, because we
+We then call the `unwrap` method, which we know will never panic because we
know the methods on `Post` ensure that `state` will always contain a `Some`
value when those methods are done. This is one of the cases we talked about in
-the “Cases In Which You Have More Information Than the Compiler” section of
-Chapter 9 when we know that a `None` value is never possible, even though the
-compiler isn’t able to understand that.
+“Cases in Which You Have More Information Than the Compiler” on page XX when we
+know that a `None` value is never possible, even though the compiler isn’t able
+to understand that.
At this point, when we call `content` on the `&Box<dyn State>`, deref coercion
will take effect on the `&` and the `Box` so the `content` method will
ultimately be called on the type that implements the `State` trait. That means
we need to add `content` to the `State` trait definition, and that is where
we’ll put the logic for what content to return depending on which state we
-have, as shown in Listing 17-18:
+have, as shown in Listing 17-18.
Filename: src/lib.rs
```
trait State {
- // --snip--
+ --snip--
fn content<'a>(&self, post: &'a Post) -> &'a str {
- [1] ""
+ 1 ""
}
}
-// --snip--
+--snip--
struct Published {}
impl State for Published {
- // --snip--
+ --snip--
fn content<'a>(&self, post: &'a Post) -> &'a str {
- [2] &post.content
+ 2 &post.content
}
}
```
@@ -1021,9 +951,9 @@ impl State for Published {
Listing 17-18: Adding the `content` method to the `State` trait
We add a default implementation for the `content` method that returns an empty
-string slice [1]. That means we don’t need to implement `content` on the `Draft`
-and `PendingReview` structs. The `Published` struct will override the `content`
-method and return the value in `post.content` [2].
+string slice [1]. That means we don’t need to implement `content` on the
+`Draft` and `PendingReview` structs. The `Published` struct will override the
+`content` method and return the value in `post.content` [2].
Note that we need lifetime annotations on this method, as we discussed in
Chapter 10. We’re taking a reference to a `post` as an argument and returning a
@@ -1034,14 +964,14 @@ And we’re done—all of Listing 17-11 now works! We’ve implemented the state
pattern with the rules of the blog post workflow. The logic related to the
rules lives in the state objects rather than being scattered throughout `Post`.
-> #### Why Not An Enum?
+> ### Why Not An Enum?
>
> You may have been wondering why we didn’t use an `enum` with the different
-> possible post states as variants. That’s certainly a possible solution, try
-> it and compare the end results to see which you prefer! One disadvantage of
-> using an enum is every place that checks the value of the enum will need a
-> `match` expression or similar to handle every possible variant. This could
-> get more repetitive than this trait object solution.
+possible post states as variants. That’s certainly a possible solution; try it
+and compare the end results to see which you prefer! One disadvantage of using
+an enum is that every place that checks the value of the enum will need a
+`match` expression or similar to handle every possible variant. This could get
+more repetitive than this trait object solution.
### Trade-offs of the State Pattern
@@ -1069,11 +999,11 @@ functionality. To see the simplicity of maintaining code that uses the state
pattern, try a few of these suggestions:
* Add a `reject` method that changes the post’s state from `PendingReview` back
- to `Draft`.
+to `Draft`.
* Require two calls to `approve` before the state can be changed to `Published`.
* Allow users to add text content only when a post is in the `Draft` state.
- Hint: have the state object responsible for what might change about the
- content but not responsible for modifying the `Post`.
+Hint: have the state object responsible for what might change about the content
+but not responsible for modifying the `Post`.
One downside of the state pattern is that, because the states implement the
transitions between states, some of the states are coupled to each other. If we
@@ -1085,22 +1015,22 @@ another design pattern.
Another downside is that we’ve duplicated some logic. To eliminate some of the
duplication, we might try to make default implementations for the
-`request_review` and `approve` methods on the `State` trait that return `self`;
-however, this would violate object safety, because the trait doesn’t know what
-the concrete `self` will be exactly. We want to be able to use `State` as a
-trait object, so we need its methods to be object safe.
+`request_review` and `approve` methods on the `State` trait that return `self`.
+However, this wouldn’t work: when using `State` as a trait object, the trait
+doesn’t know what the concrete `self` will be exactly, so the return type isn’t
+known at compile time.
Other duplication includes the similar implementations of the `request_review`
and `approve` methods on `Post`. Both methods delegate to the implementation of
the same method on the value in the `state` field of `Option` and set the new
value of the `state` field to the result. If we had a lot of methods on `Post`
that followed this pattern, we might consider defining a macro to eliminate the
-repetition (see the “Macros” section in Chapter 19).
+repetition (see “Macros” on page XX).
By implementing the state pattern exactly as it’s defined for object-oriented
languages, we’re not taking as full advantage of Rust’s strengths as we could.
Let’s look at some changes we can make to the `blog` crate that can make
-invalid states and transitions into compile time errors.
+invalid states and transitions into compile-time errors.
#### Encoding States and Behavior as Types
@@ -1129,9 +1059,9 @@ and the ability to add text to the post’s content. But instead of having a
draft posts don’t have the `content` method at all. That way, if we try to get
a draft post’s content, we’ll get a compiler error telling us the method
doesn’t exist. As a result, it will be impossible for us to accidentally
-display draft post content in production, because that code won’t even compile.
+display draft post content in production because that code won’t even compile.
Listing 17-19 shows the definition of a `Post` struct and a `DraftPost` struct,
-as well as methods on each:
+as well as methods on each.
Filename: src/lib.rs
@@ -1145,19 +1075,19 @@ pub struct DraftPost {
}
impl Post {
- [1] pub fn new() -> DraftPost {
+ 1 pub fn new() -> DraftPost {
DraftPost {
content: String::new(),
}
}
- [2] pub fn content(&self) -> &str {
+ 2 pub fn content(&self) -> &str {
&self.content
}
}
impl DraftPost {
- [3] pub fn add_text(&mut self, text: &str) {
+ 3 pub fn add_text(&mut self, text: &str) {
self.content.push_str(text);
}
}
@@ -1189,15 +1119,15 @@ So how do we get a published post? We want to enforce the rule that a draft
post has to be reviewed and approved before it can be published. A post in the
pending review state should still not display any content. Let’s implement
these constraints by adding another struct, `PendingReviewPost`, defining the
-`request_review` method on `DraftPost` to return a `PendingReviewPost`, and
+`request_review` method on `DraftPost` to return a `PendingReviewPost` and
defining an `approve` method on `PendingReviewPost` to return a `Post`, as
-shown in Listing 17-20:
+shown in Listing 17-20.
Filename: src/lib.rs
```
impl DraftPost {
- // --snip--
+ --snip--
pub fn request_review(self) -> PendingReviewPost {
PendingReviewPost {
content: self.content,
@@ -1240,7 +1170,7 @@ called on, so we need to add more `let post =` shadowing assignments to save
the returned instances. We also can’t have the assertions about the draft and
pending review posts’ contents be empty strings, nor do we need them: we can’t
compile code that tries to use the content of posts in those states any longer.
-The updated code in `main` is shown in Listing 17-21:
+The updated code in `main` is shown in Listing 17-21.
Filename: src/main.rs
@@ -1287,16 +1217,17 @@ object-oriented languages don’t have.
## Summary
-No matter whether or not you think Rust is an object-oriented language after
+Regardless of whether you think Rust is an object-oriented language after
reading this chapter, you now know that you can use trait objects to get some
object-oriented features in Rust. Dynamic dispatch can give your code some
flexibility in exchange for a bit of runtime performance. You can use this
flexibility to implement object-oriented patterns that can help your code’s
maintainability. Rust also has other features, like ownership, that
object-oriented languages don’t have. An object-oriented pattern won’t always
-be the best way to take advantage of Rust’s strengths, but is an available
+be the best way to take advantage of Rust’s strengths, but it is an available
option.
Next, we’ll look at patterns, which are another of Rust’s features that enable
lots of flexibility. We’ve looked at them briefly throughout the book but
haven’t seen their full capability yet. Let’s go!
+
diff --git a/src/doc/book/nostarch/chapter18.md b/src/doc/book/nostarch/chapter18.md
index 0b104dcf6..40c7f10a1 100644
--- a/src/doc/book/nostarch/chapter18.md
+++ b/src/doc/book/nostarch/chapter18.md
@@ -23,20 +23,6 @@ Some example patterns include `x`, `(a, 3)`, and `Some(Color::Red)`. In the
contexts in which patterns are valid, these components describe the shape of
data. Our program then matches values against the patterns to determine whether
it has the correct shape of data to continue running a particular piece of code.
-<!-- is there some generic pattern we can show as an example, early on, or
-is it too dependent on where the pattern is used? /LC -->
-<!-- Yeah, if a pattern is out of context, it doesn't look special. Like `3`
-can be a pattern. /Carol -->
-<!-- We could mention something like, "If you've written a little Rust, you've
-already used patterns without knowing it. For example `let x = 3`, the `x` is
-a pattern." Though looks like we use this later.
-
-Or, we could say, "Some example patterns include: `x`, `(a, b)`, and `Color::Red`
-/JT -->
-<!-- Ok, I've tried rewording this paragraph to include some examples, I do
-think it's important to emphasize that these are only patterns in the contexts
-patterns may exist, because without the context, there's no way to distinguish
-patterns from regular values /Carol -->
To use a pattern, we compare it to some value. If the pattern matches the
value, we use the value parts in our code. Recall the `match` expressions in
@@ -56,7 +42,7 @@ Patterns pop up in a number of places in Rust, and you’ve been using them a lo
without realizing it! This section discusses all the places where patterns are
valid.
-### `match` Arms
+### match Arms
As discussed in Chapter 6, we use patterns in the arms of `match` expressions.
Formally, `match` expressions are defined as the keyword `match`, a value to
@@ -71,7 +57,7 @@ match VALUE {
}
```
-For example, here's the `match` expression from Listing 6-5 that matches on an
+For example, here’s the `match` expression from Listing 6-5 that matches on an
`Option<i32>` value in the variable `x`:
```
@@ -81,7 +67,7 @@ match x {
}
```
-The patterns in this `match` expression are the `None` and `Some(i)` on the
+The patterns in this `match` expression are the `None` and `Some(i)` to the
left of each arrow.
One requirement for `match` expressions is that they need to be *exhaustive* in
@@ -93,12 +79,12 @@ value can never fail and thus covers every remaining case.
The particular pattern `_` will match anything, but it never binds to a
variable, so it’s often used in the last match arm. The `_` pattern can be
useful when you want to ignore any value not specified, for example. We’ll
-cover the `_` pattern in more detail in the “Ignoring Values in a Pattern”
-section later in this chapter.
+cover the `_` pattern in more detail in “Ignoring Values in a Pattern” on page
+XX.
-### Conditional `if let` Expressions
+### Conditional if let Expressions
-In Chapter 6 we discussed how to use `if let` expressions mainly as a shorter
+In Chapter 6, we discussed how to use `if let` expressions mainly as a shorter
way to write the equivalent of a `match` that only matches one case.
Optionally, `if let` can have a corresponding `else` containing code to run if
the pattern in the `if let` doesn’t match.
@@ -106,8 +92,8 @@ the pattern in the `if let` doesn’t match.
Listing 18-1 shows that it’s also possible to mix and match `if let`, `else
if`, and `else if let` expressions. Doing so gives us more flexibility than a
`match` expression in which we can express only one value to compare with the
-patterns. Also, Rust doesn't require that the conditions in a series of `if
-let`, `else if`, `else if let` arms relate to each other.
+patterns. Also, Rust doesn’t require that the conditions in a series of `if
+let`, `else if`, and `else if let` arms relate to each other.
The code in Listing 18-1 determines what color to make your background based on
a series of checks for several conditions. For this example, we’ve created
@@ -122,18 +108,20 @@ fn main() {
let is_tuesday = false;
let age: Result<u8, _> = "34".parse();
- [1] if let Some(color) = favorite_color {
- [2] println!("Using your favorite color, {color}, as the background");
- [3] } else if is_tuesday {
- [4] println!("Tuesday is green day!");
- [5]} else if let Ok(age) = age {
- [6] if age > 30 {
- [7] println!("Using purple as the background color");
+ 1 if let Some(color) = favorite_color {
+ 2 println!(
+ "Using your favorite, {color}, as the background"
+ );
+ 3 } else if is_tuesday {
+ 4 println!("Tuesday is green day!");
+ 5 } else if let Ok(age) = age {
+ 6 if age > 30 {
+ 7 println!("Using purple as the background color");
} else {
- [8] println!("Using orange as the background color");
+ 8 println!("Using orange as the background color");
}
- [9] } else {
- [10] println!("Using blue as the background color");
+ 9 } else {
+ 10 println!("Using blue as the background color");
}
}
```
@@ -145,7 +133,7 @@ background [2]. If no favorite color is specified and today is Tuesday [3], the
background color is green [4]. Otherwise, if the user specifies their age as a
string and we can parse it as a number successfully [5], the color is either
purple [7] or orange [8] depending on the value of the number [6]. If none of
-these conditions apply [9], the background color is blue.
+these conditions apply [9], the background color is blue [10].
This conditional structure lets us support complex requirements. With the
hardcoded values we have here, this example will print `Using purple as the
@@ -159,29 +147,20 @@ can’t combine these two conditions into `if let Ok(age) = age && age > 30`. Th
shadowed `age` we want to compare to 30 isn’t valid until the new scope starts
with the curly bracket.
-<!-- Have we given them an intuition yet for why this is? I may be forgetting
-something from the earlier chapters, but I wonder if we should reiterate that
-when a pattern matches, the variable that gets bound is only valid for the
-expression or block that follows the match. /JT -->
-<!-- I don't really see a difference between saying "The shadowed `age` we want
-to compare to 30 isn't valid until the new scope starts with the curly bracket"
-and "when a pattern matches, the variable that gets bound is only valid for the
-expression or block that follows the match"? To me, it sounds like this would
-be saying the same thing twice, so I'm not going to change anything here.
-/Carol -->
-
The downside of using `if let` expressions is that the compiler doesn’t check
for exhaustiveness, whereas with `match` expressions it does. If we omitted the
last `else` block [9] and therefore missed handling some cases, the compiler
would not alert us to the possible logic bug.
-### `while let` Conditional Loops
+### while let Conditional Loops
Similar in construction to `if let`, the `while let` conditional loop allows a
`while` loop to run for as long as a pattern continues to match. In Listing
-18-2 we code a `while let` loop that uses a vector as a stack and prints the
+18-2, we code a `while let` loop that uses a vector as a stack and prints the
values in the vector in the opposite order in which they were pushed.
+Filename: src/main.rs
+
```
let mut stack = Vec::new();
@@ -190,31 +169,33 @@ stack.push(2);
stack.push(3);
while let Some(top) = stack.pop() {
- println!("{}", top);
+ println!("{top}");
}
```
Listing 18-2: Using a `while let` loop to print values for as long as
`stack.pop()` returns `Some`
-This example prints 3, 2, and then 1. The `pop` method takes the last element
-out of the vector and returns `Some(value)`. If the vector is empty, `pop`
-returns `None`. The `while` loop continues running the code in its block as
-long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We can
-use `while let` to pop every element off our stack.
+This example prints `3`, `2`, and then `1`. The `pop` method takes the last
+element out of the vector and returns `Some(value)`. If the vector is empty,
+`pop` returns `None`. The `while` loop continues running the code in its block
+as long as `pop` returns `Some`. When `pop` returns `None`, the loop stops. We
+can use `while let` to pop every element off our stack.
-### `for` Loops
+### for Loops
In a `for` loop, the value that directly follows the keyword `for` is a
-pattern. For example, in `for x in y` the `x` is the pattern. Listing 18-3
-demonstrates how to use a pattern in a `for` loop to destructure, or break
+pattern. For example, in `for x in y`, the `x` is the pattern. Listing 18-3
+demonstrates how to use a pattern in a `for` loop to *destructure*, or break
apart, a tuple as part of the `for` loop.
+Filename: src/main.rs
+
```
let v = vec!['a', 'b', 'c'];
for (index, value) in v.iter().enumerate() {
- println!("{} is at index {}", value, index);
+ println!("{value} is at index {index}");
}
```
@@ -234,7 +215,7 @@ tuple `(0, 'a')`. When this value is matched to the pattern `(index, value)`,
`index` will be `0` and `value` will be `'a'`, printing the first line of the
output.
-### `let` Statements
+### let Statements
Prior to this chapter, we had only explicitly discussed using patterns with
`match` and `if let`, but in fact, we’ve used patterns in other places as well,
@@ -245,7 +226,7 @@ variable assignment with `let`:
let x = 5;
```
-Every time you've used a `let` statement like this you've been using patterns,
+Every time you’ve used a `let` statement like this you’ve been using patterns,
although you might not have realized it! More formally, a `let` statement looks
like this:
@@ -253,14 +234,14 @@ like this:
let PATTERN = EXPRESSION;
```
-In statements like `let x = 5;` with a variable name in the `PATTERN` slot, the
+In statements like `let x = 5;` with a variable name in the PATTERN slot, the
variable name is just a particularly simple form of a pattern. Rust compares
-the expression against the pattern and assigns any names it finds. So in the
+the expression against the pattern and assigns any names it finds. So, in the
`let x = 5;` example, `x` is a pattern that means “bind what matches here to
the variable `x`.” Because the name `x` is the whole pattern, this pattern
effectively means “bind everything to the variable `x`, whatever the value is.”
-To see the pattern matching aspect of `let` more clearly, consider Listing
+To see the pattern-matching aspect of `let` more clearly, consider Listing
18-4, which uses a pattern with `let` to destructure a tuple.
```
@@ -272,9 +253,9 @@ at once
Here, we match a tuple against a pattern. Rust compares the value `(1, 2, 3)`
to the pattern `(x, y, z)` and sees that the value matches the pattern, in that
-it sees that the number of elements is the same in both, so Rust
-binds `1` to `x`, `2` to `y`, and `3` to `z`. You can think of this tuple
-pattern as nesting three individual variable patterns inside it.
+it sees that the number of elements is the same in both, so Rust binds `1` to
+`x`, `2` to `y`, and `3` to `z`. You can think of this tuple pattern as nesting
+three individual variable patterns inside it.
If the number of elements in the pattern doesn’t match the number of elements
in the tuple, the overall type won’t match and we’ll get a compiler error. For
@@ -295,7 +276,8 @@ error[E0308]: mismatched types
--> src/main.rs:2:9
|
2 | let (x, y) = (1, 2, 3);
- | ^^^^^^ --------- this expression has type `({integer}, {integer}, {integer})`
+ | ^^^^^^ --------- this expression has type `({integer}, {integer},
+{integer})`
| |
| expected a tuple with 3 elements, found one with 2 elements
|
@@ -304,9 +286,9 @@ error[E0308]: mismatched types
```
To fix the error, we could ignore one or more of the values in the tuple using
-`_` or `..`, as you’ll see in the “Ignoring Values in a Pattern” section. If
-the problem is that we have too many variables in the pattern, the solution is
-to make the types match by removing variables so the number of variables equals
+`_` or `..`, as you’ll see in “Ignoring Values in a Pattern” on page XX. If the
+problem is that we have too many variables in the pattern, the solution is to
+make the types match by removing variables so the number of variables equals
the number of elements in the tuple.
### Function Parameters
@@ -321,7 +303,7 @@ fn foo(x: i32) {
}
```
-Listing 18-6: A function signature uses patterns in the parameters
+Listing 18-6: A function signature using patterns in the parameters
The `x` part is a pattern! As we did with `let`, we could match a tuple in a
function’s arguments to the pattern. Listing 18-7 splits the values in a tuple
@@ -331,7 +313,7 @@ Filename: src/main.rs
```
fn print_coordinates(&(x, y): &(i32, i32)) {
- println!("Current location: ({}, {})", x, y);
+ println!("Current location: ({x}, {y})");
}
fn main() {
@@ -346,10 +328,10 @@ This code prints `Current location: (3, 5)`. The values `&(3, 5)` match the
pattern `&(x, y)`, so `x` is the value `3` and `y` is the value `5`.
We can also use patterns in closure parameter lists in the same way as in
-function parameter lists, because closures are similar to functions, as
+function parameter lists because closures are similar to functions, as
discussed in Chapter 13.
-At this point, you’ve seen several ways of using patterns, but patterns don’t
+At this point, you’ve seen several ways to use patterns, but patterns don’t
work the same in every place we can use them. In some places, the patterns must
be irrefutable; in other circumstances, they can be refutable. We’ll discuss
these two concepts next.
@@ -365,12 +347,12 @@ a_value` because if the value in the `a_value` variable is `None` rather than
`Some`, the `Some(x)` pattern will not match.
Function parameters, `let` statements, and `for` loops can only accept
-irrefutable patterns, because the program cannot do anything meaningful when
-values don’t match. The `if let` and `while let` expressions accept
-refutable and irrefutable patterns, but the compiler warns against
-irrefutable patterns because by definition they’re intended to handle possible
-failure: the functionality of a conditional is in its ability to perform
-differently depending on success or failure.
+irrefutable patterns because the program cannot do anything meaningful when
+values don’t match. The `if let` and `while let` expressions accept refutable
+and irrefutable patterns, but the compiler warns against irrefutable patterns
+because, by definition, they’re intended to handle possible failure: the
+functionality of a conditional is in its ability to perform differently
+depending on success or failure.
In general, you shouldn’t have to worry about the distinction between refutable
and irrefutable patterns; however, you do need to be familiar with the concept
@@ -380,7 +362,7 @@ using the pattern with, depending on the intended behavior of the code.
Let’s look at an example of what happens when we try to use a refutable pattern
where Rust requires an irrefutable pattern and vice versa. Listing 18-8 shows a
-`let` statement, but for the pattern we’ve specified `Some(x)`, a refutable
+`let` statement, but for the pattern, we’ve specified `Some(x)`, a refutable
pattern. As you might expect, this code will not compile.
```
@@ -389,7 +371,7 @@ let Some(x) = some_option_value;
Listing 18-8: Attempting to use a refutable pattern with `let`
-If `some_option_value` was a `None` value, it would fail to match the pattern
+If `some_option_value` were a `None` value, it would fail to match the pattern
`Some(x)`, meaning the pattern is refutable. However, the `let` statement can
only accept an irrefutable pattern because there is nothing valid the code can
do with a `None` value. At compile time, Rust will complain that we’ve tried to
@@ -402,13 +384,15 @@ error[E0005]: refutable pattern in local binding: `None` not covered
3 | let Some(x) = some_option_value;
| ^^^^^^^ pattern `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: `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: 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 | if let Some(x) = some_option_value { /* */ }
- |
+3 | let x = if let Some(x) = some_option_value { x } else { todo!() };
+ | ++++++++++ ++++++++++++++++++++++
```
Because we didn’t cover (and couldn’t cover!) every valid value with the
@@ -416,13 +400,13 @@ pattern `Some(x)`, Rust rightfully produces a compiler error.
If we have a refutable pattern where an irrefutable pattern is needed, we can
fix it by changing the code that uses the pattern: instead of using `let`, we
-can use `if let`. Then if the pattern doesn’t match, the code will just skip
+can use `if let`. Then, if the pattern doesn’t match, the code will just skip
the code in the curly brackets, giving it a way to continue validly. Listing
18-9 shows how to fix the code in Listing 18-8.
```
if let Some(x) = some_option_value {
- println!("{}", x);
+ println!("{x}");
}
```
@@ -436,7 +420,7 @@ the compiler will give a warning.
```
if let x = 5 {
- println!("{}", x);
+ println!("{x}");
};
```
@@ -453,7 +437,8 @@ warning: irrefutable `if let` pattern
| ^^^^^^^^^
|
= note: `#[warn(irrefutable_let_patterns)]` on by default
- = note: this pattern will always match, so the `if let` is useless
+ = note: this pattern will always match, so the `if let` is
+useless
= help: consider replacing the `if let` with a `let`
```
@@ -469,14 +454,16 @@ patterns.
## Pattern Syntax
-In this section, we gather all the syntax valid in patterns and discuss why and
-when you might want to use each one.
+In this section, we gather all the syntax that is valid in patterns and discuss
+why and when you might want to use each one.
### Matching Literals
As you saw in Chapter 6, you can match patterns against literals directly. The
following code gives some examples:
+Filename: src/main.rs
+
```
let x = 1;
@@ -488,14 +475,14 @@ match x {
}
```
-This code prints `one` because the value in `x` is 1. This syntax is useful
+This code prints `one` because the value in `x` is `1`. This syntax is useful
when you want your code to take an action if it gets a particular concrete
value.
### Matching Named Variables
Named variables are irrefutable patterns that match any value, and we’ve used
-them many times in the book. However, there is a complication when you use
+them many times in this book. However, there is a complication when you use
named variables in `match` expressions. Because `match` starts a new scope,
variables declared as part of a pattern inside the `match` expression will
shadow those with the same name outside the `match` construct, as is the case
@@ -509,16 +496,16 @@ Filename: src/main.rs
```
fn main() {
- [1] let x = Some(5);
- [2] let y = 10;
+ 1 let x = Some(5);
+ 2 let y = 10;
match x {
- [3] Some(50) => println!("Got 50"),
- [4] Some(y) => println!("Matched, y = {y}"),
- [5] _ => println!("Default case, x = {:?}", x),
+ 3 Some(50) => println!("Got 50"),
+ 4 Some(y) => println!("Matched, y = {y}"),
+ 5 _ => println!("Default case, x = {:?}", x),
}
- [6] println!("at the end: x = {:?}, y = {y}", x);
+ 6 println!("at the end: x = {:?}, y = {y}", x);
}
```
@@ -532,7 +519,7 @@ code continues.
The pattern in the second match arm [4] introduces a new variable named `y`
that will match any value inside a `Some` value. Because we’re in a new scope
inside the `match` expression, this is a new `y` variable, not the `y` we
-declared at the beginning with the value 10 [2]. This new `y` binding will
+declared at the beginning with the value `10` [2]. This new `y` binding will
match any value inside a `Some`, which is what we have in `x`. Therefore, this
new `y` binds to the inner value of the `Some` in `x`. That value is `5`, so
the expression for that arm executes and prints `Matched, y = 5`.
@@ -550,8 +537,8 @@ the inner `y`. The last `println!` [6] produces `at the end: x = Some(5), y =
To create a `match` expression that compares the values of the outer `x` and
`y`, rather than introducing a shadowed variable, we would need to use a match
-guard conditional instead. We’ll talk about match guards later in the “Extra
-Conditionals with Match Guards” section.
+guard conditional instead. We’ll talk about match guards in “Extra Conditionals
+with Match Guards” on page XX.
### Multiple Patterns
@@ -561,6 +548,8 @@ the value of `x` against the match arms, the first of which has an *or* option,
meaning if the value of `x` matches either of the values in that arm, that
arm’s code will run:
+Filename: src/main.rs
+
```
let x = 1;
@@ -573,12 +562,14 @@ match x {
This code prints `one or two`.
-### Matching Ranges of Values with `..=`
+### Matching Ranges of Values with ..=
The `..=` syntax allows us to match to an inclusive range of values. In the
following code, when a pattern matches any of the values within the given
range, that arm will execute:
+Filename: src/main.rs
+
```
let x = 5;
@@ -588,11 +579,11 @@ match x {
}
```
-If `x` is 1, 2, 3, 4, or 5, the first arm will match. This syntax is more
-convenient for multiple match values than using the `|` operator to express the
-same idea; if we were to use `|` we would have to specify `1 | 2 | 3 | 4 | 5`.
-Specifying a range is much shorter, especially if we want to match, say, any
-number between 1 and 1,000!
+If `x` is `1`, `2`, `3`, `4`, or `5`, the first arm will match. This syntax is
+more convenient for multiple match values than using the `|` operator to
+express the same idea; if we were to use `|`, we would have to specify `1 | 2 |
+3 | 4 | 5`. Specifying a range is much shorter, especially if we want to match,
+say, any number between 1 and 1,000!
The compiler checks that the range isn’t empty at compile time, and because the
only types for which Rust can tell if a range is empty or not are `char` and
@@ -600,6 +591,8 @@ numeric values, ranges are only allowed with numeric or `char` values.
Here is an example using ranges of `char` values:
+Filename: src/main.rs
+
```
let x = 'c';
@@ -684,7 +677,7 @@ destructure the other fields.
In Listing 18-14, we have a `match` expression that separates `Point` values
into three cases: points that lie directly on the `x` axis (which is true when
-`y = 0`), on the `y` axis (`x = 0`), or neither.
+`y = 0`), on the `y` axis (`x = 0`), or on neither axis.
Filename: src/main.rs
@@ -693,9 +686,11 @@ fn main() {
let p = Point { x: 0, y: 7 };
match p {
- Point { x, y: 0 } => println!("On the x axis at {}", x),
- Point { x: 0, y } => println!("On the y axis at {}", y),
- Point { x, y } => println!("On neither axis: ({}, {})", x, y),
+ Point { x, y: 0 } => println!("On the x axis at {x}"),
+ Point { x: 0, y } => println!("On the y axis at {y}"),
+ Point { x, y } => {
+ println!("On neither axis: ({x}, {y})");
+ }
}
}
```
@@ -712,21 +707,16 @@ value of the `y` field. The third arm doesn’t specify any literals, so it
matches any other `Point` and creates variables for both the `x` and `y` fields.
In this example, the value `p` matches the second arm by virtue of `x`
-containing a 0, so this code will print `On the y axis at 7`.
+containing a `0`, so this code will print `On the y axis at 7`.
Remember that a `match` expression stops checking arms once it has found the
first matching pattern, so even though `Point { x: 0, y: 0}` is on the `x` axis
and the `y` axis, this code would only print `On the x axis at 0`.
-<!-- We should remind them that we stop at the first pattern, so even though
-0,0 is on both x- and y-axis in a sense, you'll only ever see the "on x-axis
-message" /JT -->
-<!-- Done! /Carol -->
-
#### Destructuring Enums
-We've destructured enums in this book (for example, Listing 6-5 in Chapter 6),
-but haven’t yet explicitly discussed that the pattern to destructure an enum
+We’ve destructured enums in this book (for example, Listing 6-5), but we
+haven’t yet explicitly discussed that the pattern to destructure an enum
corresponds to the way the data stored within the enum is defined. As an
example, in Listing 18-15 we use the `Message` enum from Listing 6-2 and write
a `match` with patterns that will destructure each inner value.
@@ -742,22 +732,24 @@ enum Message {
}
fn main() {
- [1] let msg = Message::ChangeColor(0, 160, 255);
+ 1 let msg = Message::ChangeColor(0, 160, 255);
match msg {
- [2] Message::Quit => {
- println!("The Quit variant has no data to destructure.")
+ 2 Message::Quit => {
+ println!(
+ "The Quit variant has no data to destructure."
+ );
}
- [3] Message::Move { x, y } => {
+ 3 Message::Move { x, y } => {
println!(
- "Move in the x direction {} and in the y direction {}",
- x, y
+ "Move in the x dir {x}, in the y dir {y}"
);
}
- [4] Message::Write(text) => println!("Text message: {}", text),
- [5] Message::ChangeColor(r, g, b) => println!(
- "Change the color to red {}, green {}, and blue {}",
- r, g, b
+ 4 Message::Write(text) => {
+ println!("Text message: {text}");
+ }
+ 5 Message::ChangeColor(r, g, b) => println!(
+ "Change color to red {r}, green {g}, and blue {b}"
),
}
}
@@ -765,7 +757,7 @@ fn main() {
Listing 18-15: Destructuring enum variants that hold different kinds of values
-This code will print `Change the color to red 0, green 160, and blue 255`. Try
+This code will print `Change color to red 0, green 160, and blue 255`. Try
changing the value of `msg` [1] to see the code from the other arms run.
For enum variants without any data, like `Message::Quit` [2], we can’t
@@ -791,6 +783,8 @@ but matching can work on nested items too! For example, we can refactor the
code in Listing 18-15 to support RGB and HSV colors in the `ChangeColor`
message, as shown in Listing 18-16.
+Filename: src/main.rs
+
```
enum Color {
Rgb(i32, i32, i32),
@@ -809,12 +803,10 @@ fn main() {
match msg {
Message::ChangeColor(Color::Rgb(r, g, b)) => println!(
- "Change the color to red {}, green {}, and blue {}",
- r, g, b
+ "Change color to red {r}, green {g}, and blue {b}"
),
Message::ChangeColor(Color::Hsv(h, s, v)) => println!(
- "Change the color to hue {}, saturation {}, and value {}",
- h, s, v
+ "Change color to hue {h}, saturation {s}, value {v}"
),
_ => (),
}
@@ -837,7 +829,8 @@ The following example shows a complicated destructure where we nest structs and
tuples inside a tuple and destructure all the primitive values out:
```
-let ((feet, inches), Point { x, y }) = ((3, 10), Point { x: 3, y: -10 });
+let ((feet, inches), Point { x, y }) =
+ ((3, 10), Point { x: 3, y: -10 });
```
This code lets us break complex types into their component parts so we can use
@@ -856,7 +849,7 @@ pattern (which you’ve seen), using the `_` pattern within another pattern,
using a name that starts with an underscore, or using `..` to ignore remaining
parts of a value. Let’s explore how and why to use each of these patterns.
-#### Ignoring an Entire Value with `_`
+#### An Entire Value with _
We’ve used the underscore as a wildcard pattern that will match any value but
not bind to the value. This is especially useful as the last arm in a `match`
@@ -867,7 +860,7 @@ Filename: src/main.rs
```
fn foo(_: i32, y: i32) {
- println!("This code only uses the y parameter: {}", y);
+ println!("This code only uses the y parameter: {y}");
}
fn main() {
@@ -883,12 +876,12 @@ and will print `This code only uses the y parameter: 4`.
In most cases when you no longer need a particular function parameter, you
would change the signature so it doesn’t include the unused parameter. Ignoring
a function parameter can be especially useful in cases when, for example,
-you're implementing a trait when you need a certain type signature but the
+you’re implementing a trait when you need a certain type signature but the
function body in your implementation doesn’t need one of the parameters. You
then avoid getting a compiler warning about unused function parameters, as you
would if you used a name instead.
-#### Ignoring Parts of a Value with a Nested `_`
+#### Parts of a Value with a Nested _
We can also use `_` inside another pattern to ignore just part of a value, for
example, when we want to test for only part of a value but have no use for the
@@ -897,6 +890,8 @@ responsible for managing a setting’s value. The business requirements are that
the user should not be allowed to overwrite an existing customization of a
setting but can unset the setting and give it a value if it is currently unset.
+Filename: src/main.rs
+
```
let mut setting_value = Some(5);
let new_setting_value = Some(10);
@@ -923,30 +918,32 @@ when `setting_value` and `new_setting_value` are the `Some` variant. In that
case, we print the reason for not changing `setting_value`, and it doesn’t get
changed.
-In all other cases (if either `setting_value` or `new_setting_value` are
-`None`) expressed by the `_` pattern in the second arm, we want to allow
+In all other cases (if either `setting_value` or `new_setting_value` is `None`)
+expressed by the `_` pattern in the second arm, we want to allow
`new_setting_value` to become `setting_value`.
We can also use underscores in multiple places within one pattern to ignore
particular values. Listing 18-19 shows an example of ignoring the second and
fourth values in a tuple of five items.
+Filename: src/main.rs
+
```
let numbers = (2, 4, 8, 16, 32);
match numbers {
(first, _, third, _, fifth) => {
- println!("Some numbers: {first}, {third}, {fifth}")
+ println!("Some numbers: {first}, {third}, {fifth}");
}
}
```
Listing 18-19: Ignoring multiple parts of a tuple
-This code will print `Some numbers: 2, 8, 32`, and the values 4 and 16 will be
-ignored.
+This code will print `Some numbers: 2, 8, 32`, and the values `4` and `16` will
+be ignored.
-#### Ignoring an Unused Variable by Starting Its Name with `_`
+#### An Unused Variable by Starting Its Name with _
If you create a variable but don’t use it anywhere, Rust will usually issue a
warning because an unused variable could be a bug. However, sometimes it’s
@@ -965,10 +962,10 @@ fn main() {
}
```
-Listing 18-20: Starting a variable name with an
-underscore to avoid getting unused variable warnings
+Listing 18-20: Starting a variable name with an underscore to avoid getting
+unused variable warnings
-Here we get a warning about not using the variable `y`, but we don’t get a
+Here, we get a warning about not using the variable `y`, but we don’t get a
warning about not using `_x`.
Note that there is a subtle difference between using only `_` and using a name
@@ -976,6 +973,8 @@ that starts with an underscore. The syntax `_x` still binds the value to the
variable, whereas `_` doesn’t bind at all. To show a case where this
distinction matters, Listing 18-21 will provide us with an error.
+Filename: src/main.rs
+
```
let s = Some(String::from("Hello!"));
@@ -987,13 +986,15 @@ println!("{:?}", s);
```
Listing 18-21: An unused variable starting with an underscore still binds the
-value, which might take ownership of the value
+value, which might take ownership of the value.
We’ll receive an error because the `s` value will still be moved into `_s`,
which prevents us from using `s` again. However, using the underscore by itself
doesn’t ever bind to the value. Listing 18-22 will compile without any errors
because `s` doesn’t get moved into `_`.
+Filename: src/main.rs
+
```
let s = Some(String::from("Hello!"));
@@ -1004,11 +1005,11 @@ if let Some(_) = s {
println!("{:?}", s);
```
-Listing 18-22: Using an underscore does not bind the value
+Listing 18-22: Using an underscore does not bind the value.
This code works just fine because we never bind `s` to anything; it isn’t moved.
-#### Ignoring Remaining Parts of a Value with `..`
+#### Remaining Parts of a Value with ..
With values that have many parts, we can use the `..` syntax to use specific
parts and ignore the rest, avoiding the need to list underscores for each
@@ -1018,6 +1019,8 @@ explicitly matched in the rest of the pattern. In Listing 18-23, we have a
`match` expression, we want to operate only on the `x` coordinate and ignore
the values in the `y` and `z` fields.
+Filename: src/main.rs
+
```
struct Point {
x: i32,
@@ -1028,7 +1031,7 @@ struct Point {
let origin = Point { x: 0, y: 0, z: 0 };
match origin {
- Point { x, .. } => println!("x is {}", x),
+ Point { x, .. } => println!("x is {x}"),
}
```
@@ -1059,8 +1062,8 @@ fn main() {
Listing 18-24: Matching only the first and last values in a tuple and ignoring
all other values
-In this code, the first and last value are matched with `first` and `last`. The
-`..` will match and ignore everything in the middle.
+In this code, the first and last values are matched with `first` and `last`.
+The `..` will match and ignore everything in the middle.
However, using `..` must be unambiguous. If it is unclear which values are
intended for matching and which should be ignored, Rust will give us an error.
@@ -1075,7 +1078,7 @@ fn main() {
match numbers {
(.., second, ..) => {
- println!("Some numbers: {}", second)
+ println!("Some numbers: {second}");
},
}
}
@@ -1111,14 +1114,16 @@ useful for expressing more complex ideas than a pattern alone allows.
The condition can use variables created in the pattern. Listing 18-26 shows a
`match` where the first arm has the pattern `Some(x)` and also has a match
-guard of `if x % 2 == 0` (which will be true if the number is even).
+guard of `if x % 2 == 0` (which will be `true` if the number is even).
+
+Filename: src/main.rs
```
let num = Some(4);
match num {
- Some(x) if x % 2 == 0 => println!("The number {} is even", x),
- Some(x) => println!("The number {} is odd", x),
+ Some(x) if x % 2 == 0 => println!("The number {x} is even"),
+ Some(x) => println!("The number {x} is odd"),
None => (),
}
```
@@ -1126,18 +1131,18 @@ match num {
Listing 18-26: Adding a match guard to a pattern
This example will print `The number 4 is even`. When `num` is compared to the
-pattern in the first arm, it matches, because `Some(4)` matches `Some(x)`. Then
+pattern in the first arm, it matches because `Some(4)` matches `Some(x)`. Then
the match guard checks whether the remainder of dividing `x` by 2 is equal to
0, and because it is, the first arm is selected.
If `num` had been `Some(5)` instead, the match guard in the first arm would
-have been false because the remainder of 5 divided by 2 is 1, which is not
+have been `false` because the remainder of 5 divided by 2 is 1, which is not
equal to 0. Rust would then go to the second arm, which would match because the
second arm doesn’t have a match guard and therefore matches any `Some` variant.
There is no way to express the `if x % 2 == 0` condition within a pattern, so
the match guard gives us the ability to express this logic. The downside of
-this additional expressiveness is that the compiler doesn't try to check for
+this additional expressiveness is that the compiler doesn’t try to check for
exhaustiveness when match guard expressions are involved.
In Listing 18-11, we mentioned that we could use match guards to solve our
@@ -1185,6 +1190,8 @@ guard. The important part of this example is that the `if y` match guard
applies to `4`, `5`, *and* `6`, even though it might look like `if y` only
applies to `6`.
+Filename: src/main.rs
+
```
let x = 4;
let y = false;
@@ -1200,11 +1207,11 @@ Listing 18-28: Combining multiple patterns with a match guard
The match condition states that the arm only matches if the value of `x` is
equal to `4`, `5`, or `6` *and* if `y` is `true`. When this code runs, the
pattern of the first arm matches because `x` is `4`, but the match guard `if y`
-is false, so the first arm is not chosen. The code moves on to the second arm,
-which does match, and this program prints `no`. The reason is that the `if`
-condition applies to the whole pattern `4 | 5 | 6`, not only to the last value
-`6`. In other words, the precedence of a match guard in relation to a pattern
-behaves like this:
+is `false`, so the first arm is not chosen. The code moves on to the second
+arm, which does match, and this program prints `no`. The reason is that the
+`if` condition applies to the whole pattern `4 | 5 | 6`, not just to the last
+value `6`. In other words, the precedence of a match guard in relation to a
+pattern behaves like this:
```
(4 | 5 | 6) if y => ...
@@ -1221,15 +1228,17 @@ were applied only to the final value in the list of values specified using the
`|` operator, the arm would have matched and the program would have printed
`yes`.
-### `@` Bindings
+### @ Bindings
The *at* operator `@` lets us create a variable that holds a value at the same
-time as we’re testing that value for a pattern match. In Listing 18-29, we want
-to test that a `Message::Hello` `id` field is within the range `3..=7`. We also
+time we’re testing that value for a pattern match. In Listing 18-29, we want to
+test that a `Message::Hello` `id` field is within the range `3..=7`. We also
want to bind the value to the variable `id_variable` so we can use it in the
code associated with the arm. We could name this variable `id`, the same as the
field, but for this example we’ll use a different name.
+Filename: src/main.rs
+
```
enum Message {
Hello { id: i32 },
@@ -1240,11 +1249,11 @@ let msg = Message::Hello { id: 5 };
match msg {
Message::Hello {
id: id_variable @ 3..=7,
- } => println!("Found an id in range: {}", id_variable),
+ } => println!("Found an id in range: {id_variable}"),
Message::Hello { id: 10..=12 } => {
println!("Found an id in another range")
}
- Message::Hello { id } => println!("Found some other id: {}", id),
+ Message::Hello { id } => println!("Some other id: {id}"),
}
```
@@ -1254,12 +1263,12 @@ This example will print `Found an id in range: 5`. By specifying `id_variable
@` before the range `3..=7`, we’re capturing whatever value matched the range
while also testing that the value matched the range pattern.
-In the second arm, where we only have a range specified in the pattern, the code
-associated with the arm doesn’t have a variable that contains the actual value
-of the `id` field. The `id` field’s value could have been 10, 11, or 12, but
-the code that goes with that pattern doesn’t know which it is. The pattern code
-isn’t able to use the value from the `id` field, because we haven’t saved the
-`id` value in a variable.
+In the second arm, where we only have a range specified in the pattern, the
+code associated with the arm doesn’t have a variable that contains the actual
+value of the `id` field. The `id` field’s value could have been 10, 11, or 12,
+but the code that goes with that pattern doesn’t know which it is. The pattern
+code isn’t able to use the value from the `id` field because we haven’t saved
+the `id` value in a variable.
In the last arm, where we’ve specified a variable without a range, we do have
the value available to use in the arm’s code in a variable named `id`. The
@@ -1280,3 +1289,4 @@ variables. We can create simple or complex patterns to suit our needs.
Next, for the penultimate chapter of the book, we’ll look at some advanced
aspects of a variety of Rust’s features.
+
diff --git a/src/doc/book/nostarch/chapter19.md b/src/doc/book/nostarch/chapter19.md
index 5ef3fd7a2..410e7eb62 100644
--- a/src/doc/book/nostarch/chapter19.md
+++ b/src/doc/book/nostarch/chapter19.md
@@ -9,7 +9,7 @@ directory, so all fixes need to be made in `/src/`.
# Advanced Features
By now, you’ve learned the most commonly used parts of the Rust programming
-language. Before we do one more project in Chapter 20, we’ll look at a few
+language. Before we do one more project, in Chapter 20, we’ll look at a few
aspects of the language you might run into every once in a while, but may not
use every day. You can use this chapter as a reference for when you encounter
any unknowns. The features covered here are useful in very specific situations.
@@ -19,11 +19,11 @@ grasp of all the features Rust has to offer.
In this chapter, we’ll cover:
* Unsafe Rust: how to opt out of some of Rust’s guarantees and take
- responsibility for manually upholding those guarantees
+responsibility for manually upholding those guarantees
* Advanced traits: associated types, default type parameters, fully qualified
- syntax, supertraits, and the newtype pattern in relation to traits
+syntax, supertraits, and the newtype pattern in relation to traits
* Advanced types: more about the newtype pattern, type aliases, the never type,
- and dynamically sized types
+and dynamically sized types
* Advanced functions and closures: function pointers and returning closures
* Macros: ways to define code that defines more code at compile time
@@ -61,30 +61,30 @@ that holds the unsafe code. You can take five actions in unsafe Rust that you
can’t in safe Rust, which we call *unsafe superpowers*. Those superpowers
include the ability to:
-* Dereference a raw pointer
-* Call an unsafe function or method
-* Access or modify a mutable static variable
-* Implement an unsafe trait
-* Access fields of `union`s
+1. Dereference a raw pointer
+1. Call an unsafe function or method
+1. Access or modify a mutable static variable
+1. Implement an unsafe trait
+1. Access fields of `union`s
It’s important to understand that `unsafe` doesn’t turn off the borrow checker
-or disable any other of Rust’s safety checks: if you use a reference in unsafe
+or disable any of Rust’s other safety checks: if you use a reference in unsafe
code, it will still be checked. The `unsafe` keyword only gives you access to
these five features that are then not checked by the compiler for memory
-safety. You’ll still get some degree of safety inside of an unsafe block.
+safety. You’ll still get some degree of safety inside an unsafe block.
In addition, `unsafe` does not mean the code inside the block is necessarily
dangerous or that it will definitely have memory safety problems: the intent is
that as the programmer, you’ll ensure the code inside an `unsafe` block will
access memory in a valid way.
-People are fallible, and mistakes will happen, but by requiring these five
-unsafe operations to be inside blocks annotated with `unsafe` you’ll know that
+People are fallible and mistakes will happen, but by requiring these five
+unsafe operations to be inside blocks annotated with `unsafe`, you’ll know that
any errors related to memory safety must be within an `unsafe` block. Keep
`unsafe` blocks small; you’ll be thankful later when you investigate memory
bugs.
-To isolate unsafe code as much as possible, it’s best to enclose unsafe code
+To isolate unsafe code as much as possible, it’s best to enclose such code
within a safe abstraction and provide a safe API, which we’ll discuss later in
the chapter when we examine unsafe functions and methods. Parts of the standard
library are implemented as safe abstractions over unsafe code that has been
@@ -98,18 +98,18 @@ some abstractions that provide a safe interface to unsafe code.
### Dereferencing a Raw Pointer
-In Chapter 4, in the “Dangling References” section, we mentioned that the
-compiler ensures references are always valid. Unsafe Rust has two new types
-called *raw pointers* that are similar to references. As with references, raw
-pointers can be immutable or mutable and are written as `*const T` and `*mut
-T`, respectively. The asterisk isn’t the dereference operator; it’s part of the
+In “Dangling References” on page XX, we mentioned that the compiler ensures
+references are always valid. Unsafe Rust has two new types called *raw
+pointers* that are similar to references. As with references, raw pointers can
+be immutable or mutable and are written as `*const T` and `*mut T`,
+respectively. The asterisk isn’t the dereference operator; it’s part of the
type name. In the context of raw pointers, *immutable* means that the pointer
can’t be directly assigned to after being dereferenced.
Different from references and smart pointers, raw pointers:
* Are allowed to ignore the borrowing rules by having both immutable and
- mutable pointers or multiple mutable pointers to the same location
+mutable pointers or multiple mutable pointers to the same location
* Aren’t guaranteed to point to valid memory
* Are allowed to be null
* Don’t implement any automatic cleanup
@@ -144,9 +144,9 @@ To demonstrate this, next we’ll create a raw pointer whose validity we can’t
so certain of. Listing 19-2 shows how to create a raw pointer to an arbitrary
location in memory. Trying to use arbitrary memory is undefined: there might be
data at that address or there might not, the compiler might optimize the code
-so there is no memory access, or the program might error with a segmentation
-fault. Usually, there is no good reason to write code like this, but it is
-possible.
+so there is no memory access, or the program might terminate with a
+segmentation fault. Usually, there is no good reason to write code like this,
+but it is possible.
```
let address = 0x012345usize;
@@ -176,8 +176,8 @@ Listing 19-3: Dereferencing raw pointers within an `unsafe` block
Creating a pointer does no harm; it’s only when we try to access the value that
it points at that we might end up dealing with an invalid value.
-Note also that in Listing 19-1 and 19-3, we created `*const i32` and `*mut i32`
-raw pointers that both pointed to the same memory location, where `num` is
+Note also that in Listings 19-1 and 19-3, we created `*const i32` and `*mut
+i32` raw pointers that both pointed to the same memory location, where `num` is
stored. If we instead tried to create an immutable and a mutable reference to
`num`, the code would not have compiled because Rust’s ownership rules don’t
allow a mutable reference at the same time as any immutable references. With
@@ -186,8 +186,8 @@ same location and change data through the mutable pointer, potentially creating
a data race. Be careful!
With all of these dangers, why would you ever use raw pointers? One major use
-case is when interfacing with C code, as you’ll see in the next section,
-“Calling an Unsafe Function or Method.” Another case is when building up safe
+case is when interfacing with C code, as you’ll see in “Calling an Unsafe
+Function or Method” on page XX. Another case is when building up safe
abstractions that the borrow checker doesn’t understand. We’ll introduce unsafe
functions and then look at an example of a safe abstraction that uses unsafe
code.
@@ -201,7 +201,7 @@ definition. The `unsafe` keyword in this context indicates the function has
requirements we need to uphold when we call this function, because Rust can’t
guarantee we’ve met these requirements. By calling an unsafe function within an
`unsafe` block, we’re saying that we’ve read this function’s documentation and
-take responsibility for upholding the function’s contracts.
+we take responsibility for upholding the function’s contracts.
Here is an unsafe function named `dangerous` that doesn’t do anything in its
body:
@@ -218,13 +218,15 @@ We must call the `dangerous` function within a separate `unsafe` block. If we
try to call `dangerous` without the `unsafe` block, we’ll get an error:
```
-error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+error[E0133]: call to unsafe function is unsafe and requires
+unsafe function or block
--> src/main.rs:4:5
|
4 | dangerous();
| ^^^^^^^^^^^ call to unsafe function
|
- = note: consult the function's documentation for information on how to avoid undefined behavior
+ = note: consult the function's documentation for information on
+how to avoid undefined behavior
```
With the `unsafe` block, we’re asserting to Rust that we’ve read the function’s
@@ -264,7 +266,10 @@ implement `split_at_mut` as a function rather than a method and only for slices
of `i32` values rather than for a generic type `T`.
```
-fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
+fn split_at_mut(
+ values: &mut [i32],
+ mid: usize,
+) -> (&mut [i32], &mut [i32]) {
let len = values.len();
assert!(mid <= len);
@@ -289,12 +294,12 @@ When we try to compile the code in Listing 19-5, we’ll get an error:
```
error[E0499]: cannot borrow `*values` as mutable more than once at a time
- --> src/main.rs:6:31
+ --> src/main.rs:9:31
|
-1 | fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
- | - let's call the lifetime of this reference `'1`
+2 | values: &mut [i32],
+ | - let's call the lifetime of this reference `'1`
...
-6 | (&mut values[..mid], &mut values[mid..])
+9 | (&mut values[..mid], &mut values[mid..])
| --------------------------^^^^^^--------
| | | |
| | | second mutable borrow occurs here
@@ -314,16 +319,19 @@ to unsafe functions to make the implementation of `split_at_mut` work.
```
use std::slice;
-fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
- [1] let len = values.len();
- [2] let ptr = values.as_mut_ptr();
+fn split_at_mut(
+ values: &mut [i32],
+ mid: usize,
+) -> (&mut [i32], &mut [i32]) {
+ 1 let len = values.len();
+ 2 let ptr = values.as_mut_ptr();
- [3] assert!(mid <= len);
+ 3 assert!(mid <= len);
- [4] unsafe {
+ 4 unsafe {
(
- [5] slice::from_raw_parts_mut(ptr, mid),
- [6] slice::from_raw_parts_mut(ptr.add(mid), len - mid),
+ 5 slice::from_raw_parts_mut(ptr, mid),
+ 6 slice::from_raw_parts_mut(ptr.add(mid), len - mid),
)
}
}
@@ -332,13 +340,12 @@ fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) {
Listing 19-6: Using unsafe code in the implementation of the `split_at_mut`
function
-
-Recall from “The Slice Type” section in Chapter 4 that a slice is a pointer to
-some data and the length of the slice. We use the `len` method to get the
-length of a slice [1] and the `as_mut_ptr` method to access the raw pointer of
-a slice [2]. In this case, because we have a mutable slice to `i32` values,
-`as_mut_ptr` returns a raw pointer with the type `*mut i32`, which we’ve stored
-in the variable `ptr`.
+Recall from “The Slice Type” on page XX that a slice is a pointer to some data
+and the length of the slice. We use the `len` method to get the length of a
+slice [1] and the `as_mut_ptr` method to access the raw pointer of a slice [2].
+In this case, because we have a mutable slice to `i32` values, `as_mut_ptr`
+returns a raw pointer with the type `*mut i32`, which we’ve stored in the
+variable `ptr`.
We keep the assertion that the `mid` index is within the slice [3]. Then we get
to the unsafe code [4]: the `slice::from_raw_parts_mut` function takes a raw
@@ -350,15 +357,15 @@ we create a slice using that pointer and the remaining number of items after
The function `slice::from_raw_parts_mut` is unsafe because it takes a raw
pointer and must trust that this pointer is valid. The `add` method on raw
-pointers is also unsafe, because it must trust that the offset location is also
+pointers is also unsafe because it must trust that the offset location is also
a valid pointer. Therefore, we had to put an `unsafe` block around our calls to
-`slice::from_raw_parts_mut` and `add` so we could call them. By looking at
-the code and by adding the assertion that `mid` must be less than or equal to
+`slice::from_raw_parts_mut` and `add` so we could call them. By looking at the
+code and by adding the assertion that `mid` must be less than or equal to
`len`, we can tell that all the raw pointers used within the `unsafe` block
will be valid pointers to data within the slice. This is an acceptable and
appropriate use of `unsafe`.
-Note that we don’t need to mark the resulting `split_at_mut` function as
+Note that we don’t need to mark the resultant `split_at_mut` function as
`unsafe`, and we can call this function from safe Rust. We’ve created a safe
abstraction to the unsafe code with an implementation of the function that uses
`unsafe` code in a safe way, because it creates only valid pointers from the
@@ -374,7 +381,9 @@ use std::slice;
let address = 0x01234usize;
let r = address as *mut i32;
-let values: &[i32] = unsafe { slice::from_raw_parts_mut(r, 10000) };
+let values: &[i32] = unsafe {
+ slice::from_raw_parts_mut(r, 10000)
+};
```
Listing 19-7: Creating a slice from an arbitrary memory location
@@ -383,11 +392,11 @@ We don’t own the memory at this arbitrary location, and there is no guarantee
that the slice this code creates contains valid `i32` values. Attempting to use
`values` as though it’s a valid slice results in undefined behavior.
-#### Using `extern` Functions to Call External Code
+#### Using extern Functions to Call External Code
-Sometimes, your Rust code might need to interact with code written in another
+Sometimes your Rust code might need to interact with code written in another
language. For this, Rust has the keyword `extern` that facilitates the creation
-and use of a *Foreign Function Interface (FFI)*. An FFI is a way for a
+and use of a *Foreign Function Interface* *(FFI)*, which is a way for a
programming language to define functions and enable a different (foreign)
programming language to call those functions.
@@ -406,7 +415,10 @@ extern "C" {
fn main() {
unsafe {
- println!("Absolute value of -3 according to C: {}", abs(-3));
+ println!(
+ "Absolute value of -3 according to C: {}",
+ abs(-3)
+ );
}
}
```
@@ -416,33 +428,25 @@ language
Within the `extern "C"` block, we list the names and signatures of external
functions from another language we want to call. The `"C"` part defines which
-*application binary interface (ABI)* the external function uses: the ABI
+*application binary interface* *(ABI)* the external function uses: the ABI
defines how to call the function at the assembly level. The `"C"` ABI is the
most common and follows the C programming language’s ABI.
-<!-- Totally optional - but do we want to mention the other external types
-that Rust supports here? Also, do we want to mention there are helper
-crates for connecting to other languages, include C++?
-/JT -->
-<!-- I don't really want to get into the other external types or other
-languages; there are other resources that cover these topics better than I
-could here. /Carol -->
-
-> #### Calling Rust Functions from Other Languages
+> ### Calling Rust Functions from Other Languages
>
> We can also use `extern` to create an interface that allows other languages
-> to call Rust functions. Instead of an creating a whole `extern` block, we add
-> the `extern` keyword and specify the ABI to use just before the `fn` keyword
-> for the relevant function. We also need to add a `#[no_mangle]` annotation to
-> tell the Rust compiler not to mangle the name of this function. *Mangling* is
-> when a compiler changes the name we’ve given a function to a different name
-> that contains more information for other parts of the compilation process to
-> consume but is less human readable. Every programming language compiler
-> mangles names slightly differently, so for a Rust function to be nameable by
-> other languages, we must disable the Rust compiler’s name mangling.
+to call Rust functions. Instead of creating a whole `extern` block, we add the
+`extern` keyword and specify the ABI to use just before the `fn` keyword for
+the relevant function. We also need to add a `#[no_mangle]` annotation to tell
+the Rust compiler not to mangle the name of this function. *Mangling* is when a
+compiler changes the name we’ve given a function to a different name that
+contains more information for other parts of the compilation process to consume
+but is less human readable. Every programming language compiler mangles names
+slightly differently, so for a Rust function to be nameable by other languages,
+we must disable the Rust compiler’s name mangling.
>
> In the following example, we make the `call_from_c` function accessible from
-> C code, after it’s compiled to a shared library and linked from C:
+C code, after it’s compiled to a shared library and linked from C:
>
> ```
> #[no_mangle]
@@ -455,13 +459,12 @@ could here. /Carol -->
### Accessing or Modifying a Mutable Static Variable
-In this book, we’ve not yet talked about *global variables*, which Rust does
+In this book, we’ve not yet talked about global variables, which Rust does
support but can be problematic with Rust’s ownership rules. If two threads are
accessing the same mutable global variable, it can cause a data race.
In Rust, global variables are called *static* variables. Listing 19-9 shows an
-example declaration and use of a static variable with a string slice as a
-value.
+example declaration and use of a static variable with a string slice as a value.
Filename: src/main.rs
@@ -469,18 +472,18 @@ Filename: src/main.rs
static HELLO_WORLD: &str = "Hello, world!";
fn main() {
- println!("name is: {}", HELLO_WORLD);
+ println!("value is: {HELLO_WORLD}");
}
```
Listing 19-9: Defining and using an immutable static variable
-Static variables are similar to constants, which we discussed in the
-“Differences Between Variables and Constants” section in Chapter 3. The names
-of static variables are in `SCREAMING_SNAKE_CASE` by convention. Static
-variables can only store references with the `'static` lifetime, which means
-the Rust compiler can figure out the lifetime and we aren’t required to
-annotate it explicitly. Accessing an immutable static variable is safe.
+Static variables are similar to constants, which we discussed in “Constants” on
+page XX. The names of static variables are in `SCREAMING_SNAKE_CASE` by
+convention. Static variables can only store references with the `'static`
+lifetime, which means the Rust compiler can figure out the lifetime and we
+aren’t required to annotate it explicitly. Accessing an immutable static
+variable is safe.
A subtle difference between constants and immutable static variables is that
values in a static variable have a fixed address in memory. Using the value
@@ -505,12 +508,12 @@ fn main() {
add_to_count(3);
unsafe {
- println!("COUNTER: {}", COUNTER);
+ println!("COUNTER: {COUNTER}");
}
}
```
-Listing 19-10: Reading from or writing to a mutable static variable is unsafe
+Listing 19-10: Reading from or writing to a mutable static variable is unsafe.
As with regular variables, we specify mutability using the `mut` keyword. Any
code that reads or writes from `COUNTER` must be within an `unsafe` block. This
@@ -522,7 +525,7 @@ With mutable data that is globally accessible, it’s difficult to ensure there
are no data races, which is why Rust considers mutable static variables to be
unsafe. Where possible, it’s preferable to use the concurrency techniques and
thread-safe smart pointers we discussed in Chapter 16 so the compiler checks
-that data accessed from different threads is done safely.
+that data access from different threads is done safely.
### Implementing an Unsafe Trait
@@ -540,8 +543,6 @@ unsafe trait Foo {
unsafe impl Foo for i32 {
// method implementations go here
}
-
-fn main() {}
```
Listing 19-11: Defining and implementing an unsafe trait
@@ -549,25 +550,25 @@ Listing 19-11: Defining and implementing an unsafe trait
By using `unsafe impl`, we’re promising that we’ll uphold the invariants that
the compiler can’t verify.
-As an example, recall the `Sync` and `Send` marker traits we discussed in the
-“Extensible Concurrency with the `Sync` and `Send` Traits” section in Chapter
-16: the compiler implements these traits automatically if our types are
-composed entirely of `Send` and `Sync` types. If we implement a type that
-contains a type that is not `Send` or `Sync`, such as raw pointers, and we want
-to mark that type as `Send` or `Sync`, we must use `unsafe`. Rust can’t verify
-that our type upholds the guarantees that it can be safely sent across threads
-or accessed from multiple threads; therefore, we need to do those checks
-manually and indicate as such with `unsafe`.
+As an example, recall the `Send` and `Sync` marker traits we discussed in
+“Extensible Concurrency with the Send and Sync Traits” on page XX: the compiler
+implements these traits automatically if our types are composed entirely of
+`Send` and `Sync` types. If we implement a type that contains a type that is
+not `Send` or `Sync`, such as raw pointers, and we want to mark that type as
+`Send` or `Sync`, we must use `unsafe`. Rust can’t verify that our type upholds
+the guarantees that it can be safely sent across threads or accessed from
+multiple threads; therefore, we need to do those checks manually and indicate
+as such with `unsafe`.
### Accessing Fields of a Union
-The final action that works only with `unsafe` is accessing fields of a
-*union*. A `union` is similar to a `struct`, but only one declared field is
-used in a particular instance at one time. Unions are primarily used to
-interface with unions in C code. Accessing union fields is unsafe because Rust
-can’t guarantee the type of the data currently being stored in the union
-instance. You can learn more about unions in the Rust Reference at
-*https://doc.rust-lang.org/reference/items/unions.html*.
+The final action that works only with `unsafe` is accessing fields of a union.
+A `union` is similar to a `struct`, but only one declared field is used in a
+particular instance at one time. Unions are primarily used to interface with
+unions in C code. Accessing union fields is unsafe because Rust can’t guarantee
+the type of the data currently being stored in the union instance. You can
+learn more about unions in the Rust Reference at
+*https://doc.rust-lang.org/reference/items/unions.html**.*
### When to Use Unsafe Code
@@ -579,11 +580,11 @@ it easier to track down the source of problems when they occur.
## Advanced Traits
-We first covered traits in the “Traits: Defining Shared Behavior” section of
-Chapter 10, but we didn’t discuss the more advanced details. Now that you know
-more about Rust, we can get into the nitty-gritty.
+We first covered traits in “Traits: Defining Shared Behavior” on page XX, but
+we didn’t discuss the more advanced details. Now that you know more about Rust,
+we can get into the nitty-gritty.
-### Specifying Placeholder Types in Trait Definitions with Associated Types
+### Associated Types
*Associated types* connect a type placeholder with a trait such that the trait
method definitions can use these placeholder types in their signatures. The
@@ -632,7 +633,7 @@ impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
- // --snip--
+ --snip--
```
This syntax seems comparable to that of generics. So why not just define the
@@ -648,7 +649,7 @@ Listing 19-13: A hypothetical definition of the `Iterator` trait using generics
The difference is that when using generics, as in Listing 19-13, we must
annotate the types in each implementation; because we can also implement
-`Iterator<String> for Counter` or any other type, we could have multiple
+`Iterator<``String``> for Counter` or any other type, we could have multiple
implementations of `Iterator` for `Counter`. In other words, when a trait has a
generic parameter, it can be implemented for a type multiple times, changing
the concrete types of the generic type parameters each time. When we use the
@@ -657,29 +658,23 @@ indicate which implementation of `Iterator` we want to use.
With associated types, we don’t need to annotate types because we can’t
implement a trait on a type multiple times. In Listing 19-12 with the
-definition that uses associated types, we can only choose what the type of
-`Item` will be once, because there can only be one `impl Iterator for Counter`.
-We don’t have to specify that we want an iterator of `u32` values everywhere
-that we call `next` on `Counter`.
+definition that uses associated types, we can choose what the type of `Item`
+will be only once because there can be only one `impl Iterator for Counter`. We
+don’t have to specify that we want an iterator of `u32` values everywhere we
+call `next` on `Counter`.
Associated types also become part of the trait’s contract: implementors of the
trait must provide a type to stand in for the associated type placeholder.
Associated types often have a name that describes how the type will be used,
-and documenting the associated type in the API documentation is good practice.
-
-<!-- It also makes the type a part of the trait's contract. Not sure if
-too subtle of a point, but the associated type of a trait is part of the
-require things that the implementor must provide. They often also have a name
-that may clue you in as to how that required type will be used.
-/JT -->
-<!-- Great points, I've added a small paragraph here! /Carol -->
+and documenting the associated type in the API documentation is a good practice.
### Default Generic Type Parameters and Operator Overloading
When we use generic type parameters, we can specify a default concrete type for
the generic type. This eliminates the need for implementors of the trait to
specify a concrete type if the default type works. You specify a default type
-when declaring a generic type with the `<PlaceholderType=ConcreteType>` syntax.
+when declaring a generic type with the `<`PlaceholderType`=`ConcreteType`>`
+syntax.
A great example of a situation where this technique is useful is with *operator
overloading*, in which you customize the behavior of an operator (such as `+`)
@@ -690,7 +685,7 @@ operators. But you can overload the operations and corresponding traits listed
in `std::ops` by implementing the traits associated with the operator. For
example, in Listing 19-14 we overload the `+` operator to add two `Point`
instances together. We do this by implementing the `Add` trait on a `Point`
-struct:
+struct.
Filename: src/main.rs
@@ -743,7 +738,7 @@ trait Add<Rhs=Self> {
This code should look generally familiar: a trait with one method and an
associated type. The new part is `Rhs=Self`: this syntax is called *default
-type parameters*. The `Rhs` generic type parameter (short for “right hand
+type parameters*. The `Rhs` generic type parameter (short for “right-hand
side”) defines the type of the `rhs` parameter in the `add` method. If we don’t
specify a concrete type for `Rhs` when we implement the `Add` trait, the type
of `Rhs` will default to `Self`, which will be the type we’re implementing
@@ -756,11 +751,11 @@ default.
We have two structs, `Millimeters` and `Meters`, holding values in different
units. This thin wrapping of an existing type in another struct is known as the
-*newtype pattern*, which we describe in more detail in the “Using the Newtype
-Pattern to Implement External Traits on External Types” section. We want to add
-values in millimeters to values in meters and have the implementation of `Add`
-do the conversion correctly. We can implement `Add` for `Millimeters` with
-`Meters` as the `Rhs`, as shown in Listing 19-15.
+*newtype pattern*, which we describe in more detail in “Using the Newtype
+Pattern to Implement External Traits on External Types” on page XX. We want to
+add values in millimeters to values in meters and have the implementation of
+`Add` do the conversion correctly. We can implement `Add` for `Millimeters`
+with `Meters` as the `Rhs`, as shown in Listing 19-15.
Filename: src/lib.rs
@@ -780,15 +775,15 @@ impl Add<Meters> for Millimeters {
```
Listing 19-15: Implementing the `Add` trait on `Millimeters` to add
-`Millimeters` to `Meters`
+`Millimeters` and `Meters`
To add `Millimeters` and `Meters`, we specify `impl Add<Meters>` to set the
value of the `Rhs` type parameter instead of using the default of `Self`.
You’ll use default type parameters in two main ways:
-* To extend a type without breaking existing code
-* To allow customization in specific cases most users won’t need
+1. To extend a type without breaking existing code
+1. To allow customization in specific cases most users won’t need
The standard library’s `Add` trait is an example of the second purpose:
usually, you’ll add two like types, but the `Add` trait provides the ability to
@@ -802,7 +797,7 @@ type parameter to an existing trait, you can give it a default to allow
extension of the functionality of the trait without breaking the existing
implementation code.
-### Fully Qualified Syntax for Disambiguation: Calling Methods with the Same Name
+### Disambiguating Between Methods with the Same Name
Nothing in Rust prevents a trait from having a method with the same name as
another trait’s method, nor does Rust prevent you from implementing both traits
@@ -849,7 +844,7 @@ impl Human {
Listing 19-16: Two traits are defined to have a `fly` method and are
implemented on the `Human` type, and a `fly` method is implemented on `Human`
-directly
+directly.
When we call `fly` on an instance of `Human`, the compiler defaults to calling
the method that is directly implemented on the type, as shown in Listing 19-17.
@@ -894,10 +889,6 @@ disambiguate.
Running this code prints the following:
```
-$ cargo run
- Compiling traits-example v0.1.0 (file:///projects/traits-example)
- Finished dev [unoptimized + debuginfo] target(s) in 0.46s
- Running `target/debug/traits-example`
This is your captain speaking.
Up!
*waving arms furiously*
@@ -909,12 +900,12 @@ trait to use based on the type of `self`.
However, associated functions that are not methods don’t have a `self`
parameter. When there are multiple types or traits that define non-method
-functions with the same function name, Rust doesn't always know which type you
-mean unless you use *fully qualified syntax*. For example, in Listing 19-19 we
-create a trait for an animal shelter that wants to name all baby dogs *Spot*.
-We make an `Animal` trait with an associated non-method function `baby_name`.
-The `Animal` trait is implemented for the struct `Dog`, on which we also
-provide an associated non-method function `baby_name` directly.
+functions with the same function name, Rust doesn’t always know which type you
+mean unless you use fully qualified syntax. For example, in Listing 19-19 we
+create a trait for an animal shelter that wants to name all baby dogs Spot. We
+make an `Animal` trait with an associated non-method function `baby_name`. The
+`Animal` trait is implemented for the struct `Dog`, on which we also provide an
+associated non-method function `baby_name` directly.
Filename: src/main.rs
@@ -984,7 +975,8 @@ error[E0283]: type annotations needed
--> src/main.rs:20:43
|
20 | println!("A baby dog is called a {}", Animal::baby_name());
- | ^^^^^^^^^^^^^^^^^ cannot infer type
+ | ^^^^^^^^^^^^^^^^^ cannot infer
+type
|
= note: cannot satisfy `_: Animal`
```
@@ -998,7 +990,10 @@ Filename: src/main.rs
```
fn main() {
- println!("A baby dog is called a {}", <Dog as Animal>::baby_name());
+ println!(
+ "A baby dog is called a {}",
+ <Dog as Animal>::baby_name()
+ );
}
```
@@ -1028,20 +1023,20 @@ in the program. You only need to use this more verbose syntax in cases where
there are multiple implementations that use the same name and Rust needs help
to identify which implementation you want to call.
-### Using Supertraits to Require One Trait’s Functionality Within Another Trait
+### Using Supertraits
-Sometimes, you might write a trait definition that depends on another trait:
-for a type to implement the first trait, you want to require that type to also
+Sometimes you might write a trait definition that depends on another trait: for
+a type to implement the first trait, you want to require that type to also
implement the second trait. You would do this so that your trait definition can
make use of the associated items of the second trait. The trait your trait
definition is relying on is called a *supertrait* of your trait.
For example, let’s say we want to make an `OutlinePrint` trait with an
-`outline_print` method that will print a given value formatted so that it's
+`outline_print` method that will print a given value formatted so that it’s
framed in asterisks. That is, given a `Point` struct that implements the
-standard library trait `Display` to result in `(x, y)`, when we
-call `outline_print` on a `Point` instance that has `1` for `x` and `3` for
-`y`, it should print the following:
+standard library trait `Display` to result in `(x, y)`, when we call
+`outline_print` on a `Point` instance that has `1` for `x` and `3` for `y`, it
+should print the following:
```
**********
@@ -1111,7 +1106,8 @@ error[E0277]: `Point` doesn't implement `std::fmt::Display`
| ^^^^^^^^^^^^ `Point` cannot be formatted with the default formatter
|
= help: the trait `std::fmt::Display` is not implemented for `Point`
- = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for
+pretty-print) instead
note: required by a bound in `OutlinePrint`
--> src/main.rs:3:21
|
@@ -1134,24 +1130,23 @@ impl fmt::Display for Point {
}
```
-Then implementing the `OutlinePrint` trait on `Point` will compile
+Then, implementing the `OutlinePrint` trait on `Point` will compile
successfully, and we can call `outline_print` on a `Point` instance to display
it within an outline of asterisks.
-### Using the Newtype Pattern to Implement External Traits on External Types
-
-In Chapter 10 in the “Implementing a Trait on a Type” section, we mentioned the
-orphan rule that states we’re only allowed to implement a trait on a type if
-either the trait or the type are local to our crate.
-It’s possible to get
-around this restriction using the *newtype pattern*, which involves creating a
-new type in a tuple struct. (We covered tuple structs in the “Using Tuple
-Structs without Named Fields to Create Different Types” section of Chapter 5.)
-The tuple struct will have one field and be a thin wrapper around the type we
-want to implement a trait for. Then the wrapper type is local to our crate, and
-we can implement the trait on the wrapper. *Newtype* is a term that originates
-from the Haskell programming language. There is no runtime performance penalty
-for using this pattern, and the wrapper type is elided at compile time.
+### Using the Newtype Pattern to Implement External Traits
+
+In “Implementing a Trait on a Type” on page XX, we mentioned the orphan rule
+that states we’re only allowed to implement a trait on a type if either the
+trait or the type, or both, are local to our crate. It’s possible to get around
+this restriction using the *newtype pattern*, which involves creating a new
+type in a tuple struct. (We covered tuple structs in “Using Tuple Structs
+Without Named Fields to Create Different Types” on page XX.) The tuple struct
+will have one field and be a thin wrapper around the type for which we want to
+implement a trait. Then the wrapper type is local to our crate, and we can
+implement the trait on the wrapper. *Newtype* is a term that originates from
+the Haskell programming language. There is no runtime performance penalty for
+using this pattern, and the wrapper type is elided at compile time.
As an example, let’s say we want to implement `Display` on `Vec<T>`, which the
orphan rule prevents us from doing directly because the `Display` trait and the
@@ -1173,15 +1168,18 @@ impl fmt::Display for Wrapper {
}
fn main() {
- let w = Wrapper(vec![String::from("hello"), String::from("world")]);
- println!("w = {}", w);
+ let w = Wrapper(vec![
+ String::from("hello"),
+ String::from("world"),
+ ]);
+ println!("w = {w}");
}
```
Listing 19-23: Creating a `Wrapper` type around `Vec<String>` to implement
`Display`
-The implementation of `Display` uses `self.0` to access the inner `Vec<T>`,
+The implementation of `Display` uses `self.0` to access the inner `Vec<T>`
because `Wrapper` is a tuple struct and `Vec<T>` is the item at index 0 in the
tuple. Then we can use the functionality of the `Display` type on `Wrapper`.
@@ -1190,9 +1188,9 @@ doesn’t have the methods of the value it’s holding. We would have to impleme
all the methods of `Vec<T>` directly on `Wrapper` such that the methods
delegate to `self.0`, which would allow us to treat `Wrapper` exactly like a
`Vec<T>`. If we wanted the new type to have every method the inner type has,
-implementing the `Deref` trait (discussed in Chapter 15 in the “Treating Smart
-Pointers Like Regular References with the `Deref` Trait” section) on the
-`Wrapper` to return the inner type would be a solution. If we don’t want the
+implementing the `Deref` trait on the `Wrapper` to return the inner type would
+be a solution (we discussed implementing the `Deref` trait in “Treating Smart
+Pointers Like Regular References with Deref” on page XX). If we didn’t want the
`Wrapper` type to have all the methods of the inner type—for example, to
restrict the `Wrapper` type’s behavior—we would have to implement just the
methods we do want manually.
@@ -1210,16 +1208,15 @@ the `!` type and dynamically sized types.
### Using the Newtype Pattern for Type Safety and Abstraction
-> Note: This section assumes you’ve read the earlier section “Using the
-> Newtype Pattern to Implement External Traits on External
-> Types.”
+> Note: This section assumes you’ve read the earlier section “Using the Newtype
+Pattern to Implement External Traits” on page XX.
The newtype pattern is also useful for tasks beyond those we’ve discussed so
far, including statically enforcing that values are never confused and
indicating the units of a value. You saw an example of using newtypes to
indicate units in Listing 19-15: recall that the `Millimeters` and `Meters`
structs wrapped `u32` values in a newtype. If we wrote a function with a
-parameter of type `Millimeters`, we couldn’t compile a program that
+parameter of type `Millimeters`, we wouldn’t be able to compile a program that
accidentally tried to call that function with a value of type `Meters` or a
plain `u32`.
@@ -1233,8 +1230,8 @@ associated with their name. Code using `People` would only interact with the
public API we provide, such as a method to add a name string to the `People`
collection; that code wouldn’t need to know that we assign an `i32` ID to names
internally. The newtype pattern is a lightweight way to achieve encapsulation
-to hide implementation details, which we discussed in the “Encapsulation that
-Hides Implementation Details” section of Chapter 17.
+to hide implementation details, which we discussed in “Encapsulation That Hides
+Implementation Details” on page XX.
### Creating Type Synonyms with Type Aliases
@@ -1246,7 +1243,7 @@ the alias `Kilometers` to `i32` like so:
type Kilometers = i32;
```
-Now, the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters`
+Now the alias `Kilometers` is a *synonym* for `i32`; unlike the `Millimeters`
and `Meters` types we created in Listing 19-15, `Kilometers` is not a separate,
new type. Values that have the type `Kilometers` will be treated the same as
values of type `i32`:
@@ -1262,20 +1259,11 @@ println!("x + y = {}", x + y);
Because `Kilometers` and `i32` are the same type, we can add values of both
types and we can pass `Kilometers` values to functions that take `i32`
-parameters. However, using this method, we don’t get the type checking benefits
+parameters. However, using this method, we don’t get the type-checking benefits
that we get from the newtype pattern discussed earlier. In other words, if we
mix up `Kilometers` and `i32` values somewhere, the compiler will not give us
an error.
-<!-- Having a few battle wounds trying to debug using this pattern, it's
-definitely good to warn people that if they use type aliases to the same base
-type in their program (like multiple aliases to `usize`), they're asking for
-trouble as the typechecker will not help them if they mix up their types.
-/JT -->
-<!-- I'm not sure if JT was saying this paragraph was good or it could use more
-emphasis? I've added a sentence to the end of the paragraph above in case it
-was the latter /Carol -->
-
The main use case for type synonyms is to reduce repetition. For example, we
might have a lengthy type like this:
@@ -1288,14 +1276,16 @@ over the code can be tiresome and error prone. Imagine having a project full of
code like that in Listing 19-24.
```
-let f: Box<dyn Fn() + Send + 'static> = Box::new(|| println!("hi"));
+let f: Box<dyn Fn() + Send + 'static> = Box::new(|| {
+ println!("hi");
+});
fn takes_long_type(f: Box<dyn Fn() + Send + 'static>) {
- // --snip--
+ --snip--
}
fn returns_long_type() -> Box<dyn Fn() + Send + 'static> {
- // --snip--
+ --snip--
}
```
@@ -1311,11 +1301,11 @@ type Thunk = Box<dyn Fn() + Send + 'static>;
let f: Thunk = Box::new(|| println!("hi"));
fn takes_long_type(f: Thunk) {
- // --snip--
+ --snip--
}
fn returns_long_type() -> Thunk {
- // --snip--
+ --snip--
}
```
@@ -1343,7 +1333,10 @@ pub trait Write {
fn flush(&mut self) -> Result<(), Error>;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
- fn write_fmt(&mut self, fmt: fmt::Arguments) -> Result<(), Error>;
+ fn write_fmt(
+ &mut self,
+ fmt: fmt::Arguments,
+ ) -> Result<(), Error>;
}
```
@@ -1374,7 +1367,7 @@ us a consistent interface across all of `std::io`. Because it’s an alias, it
just another `Result<T, E>`, which means we can use any methods that work on
`Result<T, E>` with it, as well as special syntax like the `?` operator.
-### The Never Type that Never Returns
+### The Never Type That Never Returns
Rust has a special type named `!` that’s known in type theory lingo as the
*empty type* because it has no values. We prefer to call it the *never type*
@@ -1383,16 +1376,16 @@ return. Here is an example:
```
fn bar() -> ! {
- // --snip--
+ --snip--
}
```
This code is read as “the function `bar` returns never.” Functions that return
-never are called *diverging functions*. We can’t create values of the type `!`
+never are called *diverging functions*. We can’t create values of the type `!`,
so `bar` can never possibly return.
But what use is a type you can never create values for? Recall the code from
-Listing 2-5, part of the number guessing game; we’ve reproduced a bit of it
+Listing 2-5, part of the number-guessing game; we’ve reproduced a bit of it
here in Listing 19-26.
```
@@ -1404,9 +1397,9 @@ let guess: u32 = match guess.trim().parse() {
Listing 19-26: A `match` with an arm that ends in `continue`
-At the time, we skipped over some details in this code. In Chapter 6 in “The
-`match` Control Flow Operator” section, we discussed that `match` arms must all
-return the same type. So, for example, the following code doesn’t work:
+At the time, we skipped over some details in this code. In “The match Control
+Flow Construct” on page XX, we discussed that `match` arms must all return the
+same type. So, for example, the following code doesn’t work:
```
let guess = match guess.trim().parse() {
@@ -1440,7 +1433,9 @@ impl<T> Option<T> {
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
- None => panic!("called `Option::unwrap()` on a `None` value"),
+ None => panic!(
+ "called `Option::unwrap()` on a `None` value"
+ ),
}
}
}
@@ -1466,7 +1461,7 @@ Here, the loop never ends, so `!` is the value of the expression. However, this
wouldn’t be true if we included a `break`, because the loop would terminate
when it got to the `break`.
-### Dynamically Sized Types and the `Sized` Trait
+### Dynamically Sized Types and the Sized Trait
Rust needs to know certain details about its types, such as how much space to
allocate for a value of a particular type. This leaves one corner of its type
@@ -1493,25 +1488,25 @@ storage and `s2` needs 15. This is why it’s not possible to create a variable
holding a dynamically sized type.
So what do we do? In this case, you already know the answer: we make the types
-of `s1` and `s2` a `&str` rather than a `str`. Recall from the “String Slices”
-section of Chapter 4 that the slice data structure just stores the starting
-position and the length of the slice. So although a `&T` is a single value that
-stores the memory address of where the `T` is located, a `&str` is *two*
-values: the address of the `str` and its length. As such, we can know the size
-of a `&str` value at compile time: it’s twice the length of a `usize`. That is,
-we always know the size of a `&str`, no matter how long the string it refers to
-is. In general, this is the way in which dynamically sized types are used in
-Rust: they have an extra bit of metadata that stores the size of the dynamic
+of `s1` and `s2` a `&str` rather than a `str`. Recall from “String Slices” on
+page XX that the slice data structure just stores the starting position and the
+length of the slice. So, although a `&T` is a single value that stores the
+memory address of where the `T` is located, a `&str` is *two* values: the
+address of the `str` and its length. As such, we can know the size of a `&str`
+value at compile time: it’s twice the length of a `usize`. That is, we always
+know the size of a `&str`, no matter how long the string it refers to is. In
+general, this is the way in which dynamically sized types are used in Rust:
+they have an extra bit of metadata that stores the size of the dynamic
information. The golden rule of dynamically sized types is that we must always
put values of dynamically sized types behind a pointer of some kind.
We can combine `str` with all kinds of pointers: for example, `Box<str>` or
`Rc<str>`. In fact, you’ve seen this before but with a different dynamically
sized type: traits. Every trait is a dynamically sized type we can refer to by
-using the name of the trait. In Chapter 17 in the “Using Trait Objects That
-Allow for Values of Different Types” section, we mentioned that to use traits
-as trait objects, we must put them behind a pointer, such as `&dyn Trait` or
-`Box<dyn Trait>` (`Rc<dyn Trait>` would work too).
+using the name of the trait. In “Using Trait Objects That Allow for Values of
+Different Types” on page XX, we mentioned that to use traits as trait objects,
+we must put them behind a pointer, such as `&dyn Trait` or `Box<dyn Trait>`
+(`Rc<dyn Trait>` would work too).
To work with DSTs, Rust provides the `Sized` trait to determine whether or not
a type’s size is known at compile time. This trait is automatically implemented
@@ -1521,7 +1516,7 @@ generic function definition like this:
```
fn generic<T>(t: T) {
- // --snip--
+ --snip--
}
```
@@ -1529,7 +1524,7 @@ is actually treated as though we had written this:
```
fn generic<T: Sized>(t: T) {
- // --snip--
+ --snip--
}
```
@@ -1539,7 +1534,7 @@ restriction:
```
fn generic<T: ?Sized>(t: &T) {
- // --snip--
+ --snip--
}
```
@@ -1564,14 +1559,14 @@ including function pointers and returning closures.
We’ve talked about how to pass closures to functions; you can also pass regular
functions to functions! This technique is useful when you want to pass a
function you’ve already defined rather than defining a new closure. Functions
-coerce to the type `fn` (with a lowercase f), not to be confused with the `Fn`
-closure trait. The `fn` type is called a *function pointer*. Passing functions
-with function pointers will allow you to use functions as arguments to other
-functions.
+coerce to the type `fn` (with a lowercase *f*), not to be confused with the
+`Fn` closure trait. The `fn` type is called a *function pointer*. Passing
+functions with function pointers will allow you to use functions as arguments
+to other functions.
The syntax for specifying that a parameter is a function pointer is similar to
that of closures, as shown in Listing 19-27, where we’ve defined a function
-`add_one` that adds one to its parameter. The function `do_twice` takes two
+`add_one` that adds 1 to its parameter. The function `do_twice` takes two
parameters: a function pointer to any function that takes an `i32` parameter
and returns an `i32`, and one `i32 value`. The `do_twice` function calls the
function `f` twice, passing it the `arg` value, then adds the two function call
@@ -1592,7 +1587,7 @@ fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
fn main() {
let answer = do_twice(add_one, 5);
- println!("The answer is: {}", answer);
+ println!("The answer is: {answer}");
}
```
@@ -1619,13 +1614,15 @@ functions can accept functions as arguments, but C doesn’t have closures.
As an example of where you could use either a closure defined inline or a named
function, let’s look at a use of the `map` method provided by the `Iterator`
-trait in the standard library. To use the `map` function to turn a
-vector of numbers into a vector of strings, we could use a closure, like this:
+trait in the standard library. To use the `map` function to turn a vector of
+numbers into a vector of strings, we could use a closure, like this:
```
let list_of_numbers = vec![1, 2, 3];
-let list_of_strings: Vec<String> =
- list_of_numbers.iter().map(|i| i.to_string()).collect();
+let list_of_strings: Vec<String> = list_of_numbers
+ .iter()
+ .map(|i| i.to_string())
+ .collect();
```
Or we could name a function as the argument to `map` instead of the closure,
@@ -1633,23 +1630,25 @@ like this:
```
let list_of_numbers = vec![1, 2, 3];
-let list_of_strings: Vec<String> =
- list_of_numbers.iter().map(ToString::to_string).collect();
+let list_of_strings: Vec<String> = list_of_numbers
+ .iter()
+ .map(ToString::to_string)
+ .collect();
```
-Note that we must use the fully qualified syntax that we talked about earlier
-in the “Advanced Traits” section because there are multiple functions available
+Note that we must use the fully qualified syntax that we talked about in
+“Advanced Traits” on page XX because there are multiple functions available
named `to_string`.
-Here, we’re using the `to_string` function defined in the
-`ToString` trait, which the standard library has implemented for any type that
-implements `Display`.
+Here, we’re using the `to_string` function defined in the `ToString` trait,
+which the standard library has implemented for any type that implements
+`Display`.
-Recall from the “Enum values” section of Chapter 6 that the name of each enum
-variant that we define also becomes an initializer function. We can use these
-initializer functions as function pointers that implement the closure traits,
-which means we can specify the initializer functions as arguments for methods
-that take closures, like so:
+Recall from “Enum Values” on page XX that the name of each enum variant that we
+define also becomes an initializer function. We can use these initializer
+functions as function pointers that implement the closure traits, which means
+we can specify the initializer functions as arguments for methods that take
+closures, like so:
```
enum Status {
@@ -1657,12 +1656,14 @@ enum Status {
Stop,
}
-let list_of_statuses: Vec<Status> = (0u32..20).map(Status::Value).collect();
+let list_of_statuses: Vec<Status> = (0u32..20)
+ .map(Status::Value)
+ .collect();
```
-Here we create `Status::Value` instances using each `u32` value in the range
+Here, we create `Status::Value` instances using each `u32` value in the range
that `map` is called on by using the initializer function of `Status::Value`.
-Some people prefer this style, and some people prefer to use closures. They
+Some people prefer this style and some people prefer to use closures. They
compile to the same code, so use whichever style is clearer to you.
### Returning Closures
@@ -1689,10 +1690,14 @@ error[E0746]: return type cannot have an unboxed trait object
--> src/lib.rs:1:25
|
1 | fn returns_closure() -> dyn Fn(i32) -> i32 {
- | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at
+compile-time
|
- = note: for information on `impl Trait`, see <https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits>
-help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32`
+ = note: for information on `impl Trait`, see
+<https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-
+implement-traits>
+help: use `impl Fn(i32) -> i32` as the return type, as all return paths are of
+type `[closure@src/lib.rs:2:5: 2:14]`, which implements `Fn(i32) -> i32`
|
1 | fn returns_closure() -> impl Fn(i32) -> i32 {
| ~~~~~~~~~~~~~~~~~~~
@@ -1708,9 +1713,8 @@ fn returns_closure() -> Box<dyn Fn(i32) -> i32> {
}
```
-This code will compile just fine. For more about trait objects, refer to the
-section “Using Trait Objects That Allow for Values of Different Types” in
-Chapter 17.
+This code will compile just fine. For more about trait objects, refer to “Using
+Trait Objects That Allow for Values of Different Types” on page XX.
Next, let’s look at macros!
@@ -1722,10 +1726,10 @@ of features in Rust: *declarative* macros with `macro_rules!` and three kinds
of *procedural* macros:
* Custom `#[derive]` macros that specify code added with the `derive` attribute
- used on structs and enums
+used on structs and enums
* Attribute-like macros that define custom attributes usable on any item
* Function-like macros that look like function calls but operate on the tokens
- specified as their argument
+specified as their argument
We’ll talk about each of these in turn, but first, let’s look at why we even
need macros when we already have functions.
@@ -1740,7 +1744,7 @@ macros *expand* to produce more code than the code you’ve written manually.
Metaprogramming is useful for reducing the amount of code you have to write and
maintain, which is also one of the roles of functions. However, macros have
-some additional powers that functions don’t.
+some additional powers that functions don’t have.
A function signature must declare the number and type of parameters the
function has. Macros, on the other hand, can take a variable number of
@@ -1760,14 +1764,14 @@ Another important difference between macros and functions is that you must
define macros or bring them into scope *before* you call them in a file, as
opposed to functions you can define anywhere and call anywhere.
-### Declarative Macros with `macro_rules!` for General Metaprogramming
+### Declarative Macros with macro_rules! for General Metaprogramming
The most widely used form of macros in Rust is the *declarative macro*. These
are also sometimes referred to as “macros by example,” “`macro_rules!` macros,”
or just plain “macros.” At their core, declarative macros allow you to write
something similar to a Rust `match` expression. As discussed in Chapter 6,
`match` expressions are control structures that take an expression, compare the
-resulting value of the expression to patterns, and then run the code associated
+resultant value of the expression to patterns, and then run the code associated
with the matching pattern. Macros also compare a value to patterns that are
associated with particular code: in this situation, the value is the literal
Rust source code passed to the macro; the patterns are compared with the
@@ -1794,15 +1798,15 @@ Listing 19-28 shows a slightly simplified definition of the `vec!` macro.
Filename: src/lib.rs
```
-[1] #[macro_export]
-[2] macro_rules! vec {
- [3] ( $( $x:expr ),* ) => {
+1 #[macro_export]
+2 macro_rules! vec {
+ 3 ( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
- [4] $(
- [5] temp_vec.push($x [6]);
+ 4 $(
+ 5 temp_vec.push(6 $x);
)*
- [7] temp_vec
+ 7 temp_vec
}
};
}
@@ -1811,8 +1815,8 @@ Filename: src/lib.rs
Listing 19-28: A simplified version of the `vec!` macro definition
> Note: The actual definition of the `vec!` macro in the standard library
-> includes code to preallocate the correct amount of memory up front. That code
-> is an optimization that we don’t include here to make the example simpler.
+includes code to pre-allocate the correct amount of memory up front. That code
+is an optimization that we don’t include here, to make the example simpler.
The `#[macro_export]` annotation [1] indicates that this macro should be made
available whenever the crate in which the macro is defined is brought into
@@ -1830,20 +1834,19 @@ is the only pattern in this macro, there is only one valid way to match; any
other pattern will result in an error. More complex macros will have more than
one arm.
-Valid pattern syntax in macro definitions is different than the pattern syntax
+Valid pattern syntax in macro definitions is different from the pattern syntax
covered in Chapter 18 because macro patterns are matched against Rust code
structure rather than values. Let’s walk through what the pattern pieces in
Listing 19-28 mean; for the full macro pattern syntax, see the Rust Reference
at *https://doc.rust-lang.org/reference/macros-by-example.html*.
-First, we use a set of parentheses to encompass the whole pattern. We use a
+First we use a set of parentheses to encompass the whole pattern. We use a
dollar sign (`$`) to declare a variable in the macro system that will contain
the Rust code matching the pattern. The dollar sign makes it clear this is a
-macro variable as opposed to a regular Rust variable.
-Next comes a set of parentheses that captures values that match the
-pattern within the parentheses for use in the replacement code. Within `$()` is
-`$x:expr`, which matches any Rust expression and gives the expression the name
-`$x`.
+macro variable as opposed to a regular Rust variable. Next comes a set of
+parentheses that captures values that match the pattern within the parentheses
+for use in the replacement code. Within `$()` is `$x:expr`, which matches any
+Rust expression and gives the expression the name `$x`.
The comma following `$()` indicates that a literal comma separator character
could optionally appear after the code that matches the code in `$()`. The `*`
@@ -1853,11 +1856,11 @@ When we call this macro with `vec![1, 2, 3];`, the `$x` pattern matches three
times with the three expressions `1`, `2`, and `3`.
Now let’s look at the pattern in the body of the code associated with this arm:
-`temp_vec.push()` [5] within `$()*` [4][7] is generated for each part that
-matches `$()` in the pattern zero or more times depending on how many times the
-pattern matches. The `$x` [6] is replaced with each expression matched. When we
-call this macro with `vec![1, 2, 3];`, the code generated that replaces this
-macro call will be the following:
+`temp_vec.push()` [5] within `$()* at [4] and [7] is generated for each part
+that matches `$()` in the pattern zero or more times depending on how many
+times the pattern matches. The `$x` [6] is replaced with each expression
+matched. When we call this macro with `vec![1, 2, 3];`, the code generated that
+replaces this macro call will be the following:
```
{
@@ -1874,24 +1877,16 @@ generate code to create a vector containing the specified elements.
To learn more about how to write macros, consult the online documentation or
other resources, such as “The Little Book of Rust Macros” at
-*https://veykril.github.io/tlborm/* started by Daniel Keep and continued by
+*https://veykril.github.io/tlborm* started by Daniel Keep and continued by
Lukas Wirth.
-<!-- Not sure what "In the future, Rust will have a second kind of declarative
-macro" means here. I suspect we're "stuck" with the two kinds of macros we
-already have today, at least I don't see much energy in pushing to add a third
-just yet.
-/JT -->
-<!-- Yeah, great catch, I think that part was back when we had more dreams that
-have now been postponed/abandoned. I've removed. /Carol -->
-
### Procedural Macros for Generating Code from Attributes
-The second form of macros is the *procedural macro*, which acts more like a
-function (and is a type of procedure). Procedural macros accept some code as an
-input, operate on that code, and produce some code as an output rather than
+The second form of macros is the procedural macro, which acts more like a
+function (and is a type of procedure). *Procedural macros* accept some code as
+an input, operate on that code, and produce some code as an output rather than
matching against patterns and replacing the code with other code as declarative
-macros do. The three kinds of procedural macros are custom derive,
+macros do. The three kinds of procedural macros are custom `derive`,
attribute-like, and function-like, and all work in a similar fashion.
When creating procedural macros, the definitions must reside in their own crate
@@ -1903,7 +1898,7 @@ macro variety.
Filename: src/lib.rs
```
-use proc_macro;
+use proc_macro::TokenStream;
#[some_attribute]
pub fn some_name(input: TokenStream) -> TokenStream {
@@ -1922,20 +1917,20 @@ that specifies which kind of procedural macro we’re creating. We can have
multiple kinds of procedural macros in the same crate.
Let’s look at the different kinds of procedural macros. We’ll start with a
-custom derive macro and then explain the small dissimilarities that make the
+custom `derive` macro and then explain the small dissimilarities that make the
other forms different.
-### How to Write a Custom `derive` Macro
+### How to Write a Custom derive Macro
Let’s create a crate named `hello_macro` that defines a trait named
`HelloMacro` with one associated function named `hello_macro`. Rather than
making our users implement the `HelloMacro` trait for each of their types,
we’ll provide a procedural macro so users can annotate their type with
`#[derive(HelloMacro)]` to get a default implementation of the `hello_macro`
-function. The default implementation will print `Hello, Macro! My name is
-TypeName!` where `TypeName` is the name of the type on which this trait has
-been defined. In other words, we’ll write a crate that enables another
-programmer to write code like Listing 19-30 using our crate.
+function. The default implementation will print `Hello, Macro! My name is`
+TypeName`!` where TypeName is the name of the type on which this trait has been
+defined. In other words, we’ll write a crate that enables another programmer to
+write code like Listing 19-30 using our crate.
Filename: src/main.rs
@@ -2002,8 +1997,8 @@ name at runtime. We need a macro to generate code at compile time.
The next step is to define the procedural macro. At the time of this writing,
procedural macros need to be in their own crate. Eventually, this restriction
might be lifted. The convention for structuring crates and macro crates is as
-follows: for a crate named `foo`, a custom derive procedural macro crate is
-called `foo_derive`. Let’s start a new crate called `hello_macro_derive` inside
+follows: for a crate named foo, a custom `derive` procedural macro crate is
+called foo`_derive`. Let’s start a new crate called `hello_macro_derive` inside
our `hello_macro` project:
```
@@ -2095,11 +2090,11 @@ The `hello_macro_derive` function first converts the `input` from a
operations on. This is where `syn` comes into play. The `parse` function in
`syn` takes a `TokenStream` and returns a `DeriveInput` struct representing the
parsed Rust code. Listing 19-32 shows the relevant parts of the `DeriveInput`
-struct we get from parsing the `struct Pancakes;` string:
+struct we get from parsing the `struct Pancakes;` string.
```
DeriveInput {
- // --snip--
+ --snip--
ident: Ident {
ident: "Pancakes",
@@ -2121,14 +2116,14 @@ Listing 19-32: The `DeriveInput` instance we get when parsing the code that has
the macro’s attribute in Listing 19-30
The fields of this struct show that the Rust code we’ve parsed is a unit struct
-with the `ident` (identifier, meaning the name) of `Pancakes`. There are more
+with the `ident` (*identifier*, meaning the name) of `Pancakes`. There are more
fields on this struct for describing all sorts of Rust code; check the `syn`
documentation for `DeriveInput` at
*https://docs.rs/syn/1.0/syn/struct.DeriveInput.html* for more information.
Soon we’ll define the `impl_hello_macro` function, which is where we’ll build
the new Rust code we want to include. But before we do, note that the output
-for our derive macro is also a `TokenStream`. The returned `TokenStream` is
+for our `derive` macro is also a `TokenStream`. The returned `TokenStream` is
added to the code that our crate users write, so when they compile their crate,
they’ll get the extra functionality that we provide in the modified
`TokenStream`.
@@ -2153,7 +2148,10 @@ fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
let gen = quote! {
impl HelloMacro for #name {
fn hello_macro() {
- println!("Hello, Macro! My name is {}!", stringify!(#name));
+ println!(
+ "Hello, Macro! My name is {}!",
+ stringify!(#name)
+ );
}
}
};
@@ -2166,7 +2164,7 @@ Listing 19-33: Implementing the `HelloMacro` trait using the parsed Rust code
We get an `Ident` struct instance containing the name (identifier) of the
annotated type using `ast.ident`. The struct in Listing 19-32 shows that when
we run the `impl_hello_macro` function on the code in Listing 19-30, the
-`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus,
+`ident` we get will have the `ident` field with a value of `"Pancakes"`. Thus
the `name` variable in Listing 19-33 will contain an `Ident` struct instance
that, when printed, will be the string `"Pancakes"`, the name of the struct in
Listing 19-30.
@@ -2185,13 +2183,13 @@ introduction.
We want our procedural macro to generate an implementation of our `HelloMacro`
trait for the type the user annotated, which we can get by using `#name`. The
-trait implementation has the one function `hello_macro`, whose body contains the
-functionality we want to provide: printing `Hello, Macro! My name is` and then
-the name of the annotated type.
+trait implementation has the one function `hello_macro`, whose body contains
+the functionality we want to provide: printing `Hello, Macro! My name is` and
+then the name of the annotated type.
The `stringify!` macro used here is built into Rust. It takes a Rust
expression, such as `1 + 2`, and at compile time turns the expression into a
-string literal, such as `"1 + 2"`. This is different than `format!` or
+string literal, such as `"1 + 2"`. This is different from `format!` or
`println!`, macros which evaluate the expression and then turn the result into
a `String`. There is a possibility that the `#name` input might be an
expression to print literally, so we use `stringify!`. Using `stringify!` also
@@ -2203,7 +2201,7 @@ and `hello_macro_derive`. Let’s hook up these crates to the code in Listing
your *projects* directory using `cargo new pancakes`. We need to add
`hello_macro` and `hello_macro_derive` as dependencies in the `pancakes`
crate’s *Cargo.toml*. If you’re publishing your versions of `hello_macro` and
-`hello_macro_derive` to *https://crates.io/*, they would be regular
+`hello_macro_derive` to *https://crates.io*, they would be regular
dependencies; if not, you can specify them as `path` dependencies as follows:
```
@@ -2219,15 +2217,15 @@ should print `Hello, Macro! My name is Pancakes!` The implementation of the
trait implementation.
Next, let’s explore how the other kinds of procedural macros differ from custom
-derive macros.
+`derive` macros.
-### Attribute-like macros
+### Attribute-like Macros
-Attribute-like macros are similar to custom derive macros, but instead of
+Attribute-like macros are similar to custom `derive` macros, but instead of
generating code for the `derive` attribute, they allow you to create new
attributes. They’re also more flexible: `derive` only works for structs and
enums; attributes can be applied to other items as well, such as functions.
-Here’s an example of using an attribute-like macro: say you have an attribute
+Here’s an example of using an attribute-like macro. Say you have an attribute
named `route` that annotates functions when using a web application framework:
```
@@ -2240,7 +2238,10 @@ macro. The signature of the macro definition function would look like this:
```
#[proc_macro_attribute]
-pub fn route(attr: TokenStream, item: TokenStream) -> TokenStream {
+pub fn route(
+ attr: TokenStream,
+ item: TokenStream
+) -> TokenStream {
```
Here, we have two parameters of type `TokenStream`. The first is for the
@@ -2248,21 +2249,21 @@ contents of the attribute: the `GET, "/"` part. The second is the body of the
item the attribute is attached to: in this case, `fn index() {}` and the rest
of the function’s body.
-Other than that, attribute-like macros work the same way as custom derive
+Other than that, attribute-like macros work the same way as custom `derive`
macros: you create a crate with the `proc-macro` crate type and implement a
function that generates the code you want!
-### Function-like macros
+### Function-like Macros
Function-like macros define macros that look like function calls. Similarly to
`macro_rules!` macros, they’re more flexible than functions; for example, they
-can take an unknown number of arguments. However, `macro_rules!` macros can be
-defined only using the match-like syntax we discussed in the section
-“Declarative Macros with `macro_rules!` for General Metaprogramming” earlier.
-Function-like macros take a `TokenStream` parameter and their definition
-manipulates that `TokenStream` using Rust code as the other two types of
-procedural macros do. An example of a function-like macro is an `sql!` macro
-that might be called like so:
+can take an unknown number of arguments. However, `macro_rules!` macros can
+only be defined using the match-like syntax we discussed in “Declarative Macros
+with macro_rules! for General Metaprogramming” on page XX. Function-like macros
+take a `TokenStream` parameter, and their definition manipulates that
+`TokenStream` using Rust code as the other two types of procedural macros do.
+An example of a function-like macro is an `sql!` macro that might be called
+like so:
```
let sql = sql!(SELECT * FROM posts WHERE id=1);
@@ -2277,32 +2278,19 @@ syntactically correct, which is much more complex processing than a
pub fn sql(input: TokenStream) -> TokenStream {
```
-This definition is similar to the custom derive macro’s signature: we receive
+This definition is similar to the custom `derive` macro’s signature: we receive
the tokens that are inside the parentheses and return the code we wanted to
generate.
-<!-- I may get a few looks for this, but I wonder if we should trim the
-procedural macros section above a bit. There's a lot of information in there,
-but it feels like something we could intro and then point people off to other
-materials for. Reason being (and I know I may be in the minority here),
-procedural macros are something we should use only rarely in our Rust projects.
-They are a burden on the compiler, have the potential to hurt readability and
-maintainability, and... you know the saying with great power comes great
-responsibilty and all that. /JT -->
-<!-- I think we felt obligated to have this section when procedural macros were
-introduced because there wasn't any documentation for them. I feel like the
-custom derive is the most common kind people want to make... While I'd love to
-not have to maintain this section, I asked around and people seemed generally
-in favor of keeping it, so I think I will, for now. /Carol -->
-
## Summary
Whew! Now you have some Rust features in your toolbox that you likely won’t use
often, but you’ll know they’re available in very particular circumstances.
We’ve introduced several complex topics so that when you encounter them in
-error message suggestions or in other peoples’ code, you’ll be able to
+error message suggestions or in other people’s code, you’ll be able to
recognize these concepts and syntax. Use this chapter as a reference to guide
you to solutions.
Next, we’ll put everything we’ve discussed throughout the book into practice
and do one more project!
+
diff --git a/src/doc/book/nostarch/chapter20.md b/src/doc/book/nostarch/chapter20.md
index e692e2f1d..9d4e22cd7 100644
--- a/src/doc/book/nostarch/chapter20.md
+++ b/src/doc/book/nostarch/chapter20.md
@@ -16,21 +16,19 @@ lessons.
For our final project, we’ll make a web server that says “hello” and looks like
Figure 20-1 in a web browser.
-!hello from rust at *img/trpl20-01.png*
-
Figure 20-1: Our final shared project
Here is our plan for building the web server:
1. Learn a bit about TCP and HTTP.
-2. Listen for TCP connections on a socket.
-3. Parse a small number of HTTP requests.
-4. Create a proper HTTP response.
-5. Improve the throughput of our server with a thread pool.
+1. Listen for TCP connections on a socket.
+1. Parse a small number of HTTP requests.
+1. Create a proper HTTP response.
+1. Improve the throughput of our server with a thread pool.
Before we get started, we should mention one detail: the method we’ll use won’t
be the best way to build a web server with Rust. Community members have
-published a number of production-ready crates available at *https://crates.io/*
+published a number of production-ready crates available at *https://crates.io*
that provide more complete web server and thread pool implementations than
we’ll build. However, our intention in this chapter is to help you learn, not
to take the easy route. Because Rust is a systems programming language, we can
@@ -81,12 +79,12 @@ Filename: src/main.rs
use std::net::TcpListener;
fn main() {
- [1] let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
+ 1 let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
- [2] for stream in listener.incoming() {
- [3] let stream = stream.unwrap();
+ 2 for stream in listener.incoming() {
+ 3 let stream = stream.unwrap();
- [4] println!("Connection established!");
+ 4 println!("Connection established!");
}
}
```
@@ -99,7 +97,7 @@ Using `TcpListener`, we can listen for TCP connections at the address
address representing your computer (this is the same on every computer and
doesn’t represent the authors’ computer specifically), and `7878` is the port.
We’ve chosen this port for two reasons: HTTP isn’t normally accepted on this
-port so our server is unlikely to conflict with any other web server you might
+port, so our server is unlikely to conflict with any other web server you might
have running on your machine, and 7878 is *rust* typed on a telephone.
The `bind` function in this scenario works like the `new` function in that it
@@ -109,7 +107,7 @@ to a port.”
The `bind` function returns a `Result<T, E>`, which indicates that it’s
possible for binding to fail. For example, connecting to port 80 requires
-administrator privileges (nonadministrators can listen only on ports higher
+administrator privileges (non-administrators can listen only on ports higher
than 1023), so if we tried to connect to port 80 without being an
administrator, binding wouldn’t work. Binding also wouldn’t work, for example,
if we ran two instances of our program and so had two programs listening to the
@@ -141,7 +139,7 @@ open connections are closed.
Let’s try running this code! Invoke `cargo run` in the terminal and then load
*127.0.0.1:7878* in a web browser. The browser should show an error message
-like “Connection reset,” because the server isn’t currently sending back any
+like “Connection reset” because the server isn’t currently sending back any
data. But when you look at your terminal, you should see several messages that
were printed when the browser connected to the server!
@@ -152,7 +150,7 @@ Connection established!
Connection established!
```
-Sometimes, you’ll see multiple messages printed for one browser request; the
+Sometimes you’ll see multiple messages printed for one browser request; the
reason might be that the browser is making a request for the page as well as a
request for other resources, like the *favicon.ico* icon that appears in the
browser tab.
@@ -164,10 +162,10 @@ part of the `drop` implementation. Browsers sometimes deal with closed
connections by retrying, because the problem might be temporary. The important
factor is that we’ve successfully gotten a handle to a TCP connection!
-Remember to stop the program by pressing <span class="keystroke">ctrl-c
-when you’re done running a particular version of the code. Then restart the
-program by invoking the `cargo run` command after you’ve made each set of code
-changes to make sure you’re running the newest code.
+Remember to stop the program by pressing ctrl-C when you’re done running a
+particular version of the code. Then restart the program by invoking the `cargo
+run` command after you’ve made each set of code changes to make sure you’re
+running the newest code.
### Reading the Request
@@ -181,7 +179,7 @@ look like Listing 20-2.
Filename: src/main.rs
```
-[1] use std::{
+1 use std::{
io::{prelude::*, BufReader},
net::{TcpListener, TcpStream},
};
@@ -192,19 +190,19 @@ fn main() {
for stream in listener.incoming() {
let stream = stream.unwrap();
- [2] handle_connection(stream);
+ 2 handle_connection(stream);
}
}
fn handle_connection(mut stream: TcpStream) {
- [3] let buf_reader = BufReader::new(&mut stream);
- [4] let http_request: Vec<_> = buf_reader
- [5] .lines()
- [6] .map(|result| result.unwrap())
- [7] .take_while(|line| !line.is_empty())
+ 3 let buf_reader = BufReader::new(&mut stream);
+ 4 let http_request: Vec<_> = buf_reader
+ 5 .lines()
+ 6 .map(|result| result.unwrap())
+ 7 .take_while(|line| !line.is_empty())
.collect();
- [8] println!("Request: {:#?}", http_request);
+ 8 println!("Request: {:#?}", http_request);
}
```
@@ -251,8 +249,11 @@ $ cargo run
Request: [
"GET / HTTP/1.1",
"Host: 127.0.0.1:7878",
- "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0) Gecko/20100101 Firefox/99.0",
- "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
+ "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:99.0)
+Gecko/20100101 Firefox/99.0",
+ "Accept:
+text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*
+;q=0.8",
"Accept-Language: en-US,en;q=0.5",
"Accept-Encoding: gzip, deflate, br",
"DNT: 1",
@@ -292,17 +293,17 @@ being used, such as `GET` or `POST`, which describes how the client is making
this request. Our client used a `GET` request, which means it is asking for
information.
-The next part of the request line is */*, which indicates the *Uniform Resource
-Identifier* *(URI)* the client is requesting: a URI is almost, but not quite,
-the same as a *Uniform Resource Locator* *(URL)*. The difference between URIs
+The next part of the request line is */*, which indicates the *uniform resource
+identifier* *(URI)* the client is requesting: a URI is almost, but not quite,
+the same as a *uniform resource locator* *(URL)*. The difference between URIs
and URLs isn’t important for our purposes in this chapter, but the HTTP spec
-uses the term URI, so we can just mentally substitute URL for URI here.
+uses the term *URI*, so we can just mentally substitute *URL* for *URI* here.
The last part is the HTTP version the client uses, and then the request line
-ends in a *CRLF sequence*. (CRLF stands for *carriage return* and *line feed*,
+ends in a CRLF sequence. (CRLF stands for *carriage return* and *line feed*,
which are terms from the typewriter days!) The CRLF sequence can also be
written as `\r\n`, where `\r` is a carriage return and `\n` is a line feed. The
-CRLF sequence separates the request line from the rest of the request data.
+*CRLF sequence* separates the request line from the rest of the request data.
Note that when the CRLF is printed, we see a new line start rather than `\r\n`.
Looking at the request line data we received from running our program so far,
@@ -334,8 +335,8 @@ a reason phrase that provides a text description of the status code. After the
CRLF sequence are any headers, another CRLF sequence, and the body of the
response.
-Here is an example response that uses HTTP version 1.1, has a status code of
-200, an OK reason phrase, no headers, and no body:
+Here is an example response that uses HTTP version 1.1, and has a status code
+of 200, an OK reason phrase, no headers, and no body:
```
HTTP/1.1 200 OK\r\n\r\n
@@ -358,9 +359,9 @@ fn handle_connection(mut stream: TcpStream) {
.take_while(|line| !line.is_empty())
.collect();
- [1] let response = "HTTP/1.1 200 OK\r\n\r\n";
+ 1 let response = "HTTP/1.1 200 OK\r\n\r\n";
- [2] stream.write_all(response.as_bytes()[3]).unwrap();
+ 2 stream.write_all(response.3 as_bytes()).unwrap();
}
```
@@ -376,7 +377,7 @@ a real application you would add error handling here.
With these changes, let’s run our code and make a request. We’re no longer
printing any data to the terminal, so we won’t see any output other than the
output from Cargo. When you load *127.0.0.1:7878* in a web browser, you should
-get a blank page instead of an error. You’ve just hand-coded receiving an HTTP
+get a blank page instead of an error. You’ve just handcoded receiving an HTTP
request and sending a response!
### Returning Real HTML
@@ -413,11 +414,11 @@ Filename: src/main.rs
```
use std::{
- [1] fs,
+ 1 fs,
io::{prelude::*, BufReader},
net::{TcpListener, TcpStream},
};
-// --snip--
+--snip--
fn handle_connection(mut stream: TcpStream) {
let buf_reader = BufReader::new(&mut stream);
@@ -431,8 +432,11 @@ fn handle_connection(mut stream: TcpStream) {
let contents = fs::read_to_string("hello.html").unwrap();
let length = contents.len();
- [2] let response =
- format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+ 2 let response = format!(
+ "{status_line}\r\n\
+ Content-Length: {length}\r\n\r\n\
+ {contents}"
+ );
stream.write_all(response.as_bytes()).unwrap();
}
@@ -442,8 +446,8 @@ Listing 20-5: Sending the contents of *hello.html* as the body of the response
We’ve added `fs` to the `use` statement to bring the standard library’s
filesystem module into scope [1]. The code for reading the contents of a file
-to a string should look familiar; we used it in Chapter 12 when we read the
-contents of a file for our I/O project in Listing 12-4.
+to a string should look familiar; we used it when we read the contents of a
+file for our I/O project in Listing 12-4.
Next, we use `format!` to add the file’s contents as the body of the success
response [2]. To ensure a valid HTTP response, we add the `Content-Length`
@@ -465,7 +469,7 @@ request to */*.
Right now, our web server will return the HTML in the file no matter what the
client requested. Let’s add functionality to check that the browser is
-requesting */* before returning the HTML file and return an error if the
+requesting */* before returning the HTML file, and return an error if the
browser requests anything else. For this we need to modify `handle_connection`,
as shown in Listing 20-6. This new code checks the content of the request
received against what we know a request for */* looks like and adds `if` and
@@ -474,23 +478,29 @@ received against what we know a request for */* looks like and adds `if` and
Filename: src/main.rs
```
-// --snip--
+--snip--
fn handle_connection(mut stream: TcpStream) {
let buf_reader = BufReader::new(&mut stream);
- [1] let request_line = buf_reader.lines().next().unwrap().unwrap();
+ 1 let request_line = buf_reader
+ .lines()
+ .next()
+ .unwrap()
+ .unwrap();
- [2] if request_line == "GET / HTTP/1.1" {
+ 2 if request_line == "GET / HTTP/1.1" {
let status_line = "HTTP/1.1 200 OK";
let contents = fs::read_to_string("hello.html").unwrap();
let length = contents.len();
let response = format!(
- "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"
+ "{status_line}\r\n\
+ Content-Length: {length}\r\n\r\n\
+ {contents}"
);
stream.write_all(response.as_bytes()).unwrap();
- [3] } else {
+ 3 } else {
// some other request
}
}
@@ -526,18 +536,20 @@ indicating the response to the end user.
Filename: src/main.rs
```
- // --snip--
- } else {
- [1] let status_line = "HTTP/1.1 404 NOT FOUND";
- [2] let contents = fs::read_to_string("404.html").unwrap();
- let length = contents.len();
+--snip--
+} else {
+ 1 let status_line = "HTTP/1.1 404 NOT FOUND";
+ 2 let contents = fs::read_to_string("404.html").unwrap();
+ let length = contents.len();
- let response = format!(
- "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"
- );
+ let response = format!(
+ "{status_line}\r\n\
+ Content-Length: {length}\r\n\r\n
+ {contents}"
+ );
- stream.write_all(response.as_bytes()).unwrap();
- }
+ stream.write_all(response.as_bytes()).unwrap();
+}
```
Listing 20-7: Responding with status code 404 and an error page if anything
@@ -546,8 +558,8 @@ other than */* was requested
Here, our response has a status line with status code 404 and the reason phrase
`NOT FOUND` [1]. The body of the response will be the HTML in the file
*404.html* [1]. You’ll need to create a *404.html* file next to *hello.html*
-for the error page; again feel free to use any HTML you want or use the example
-HTML in Listing 20-8.
+for the error page; again feel free to use any HTML you want, or use the
+example HTML in Listing 20-8.
Filename: 404.html
@@ -573,34 +585,38 @@ return the contents of *hello.html*, and any other request, like
### A Touch of Refactoring
-At the moment the `if` and `else` blocks have a lot of repetition: they’re both
-reading files and writing the contents of the files to the stream. The only
-differences are the status line and the filename. Let’s make the code more
+At the moment, the `if` and `else` blocks have a lot of repetition: they’re
+both reading files and writing the contents of the files to the stream. The
+only differences are the status line and the filename. Let’s make the code more
concise by pulling out those differences into separate `if` and `else` lines
that will assign the values of the status line and the filename to variables;
we can then use those variables unconditionally in the code to read the file
-and write the response. Listing 20-9 shows the resulting code after replacing
+and write the response. Listing 20-9 shows the resultant code after replacing
the large `if` and `else` blocks.
Filename: src/main.rs
```
-// --snip--
+--snip--
fn handle_connection(mut stream: TcpStream) {
- // --snip--
+ --snip--
- let (status_line, filename) = if request_line == "GET / HTTP/1.1" {
- ("HTTP/1.1 200 OK", "hello.html")
- } else {
- ("HTTP/1.1 404 NOT FOUND", "404.html")
- };
+ let (status_line, filename) =
+ if request_line == "GET / HTTP/1.1" {
+ ("HTTP/1.1 200 OK", "hello.html")
+ } else {
+ ("HTTP/1.1 404 NOT FOUND", "404.html")
+ };
let contents = fs::read_to_string(filename).unwrap();
let length = contents.len();
- let response =
- format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");
+ let response = format!(
+ "{status_line}\r\n\
+ Content-Length: {length}\r\n\r\n\
+ {contents}"
+ );
stream.write_all(response.as_bytes()).unwrap();
}
@@ -638,14 +654,14 @@ server received more and more requests, this serial execution would be less and
less optimal. If the server receives a request that takes a long time to
process, subsequent requests will have to wait until the long request is
finished, even if the new requests can be processed quickly. We’ll need to fix
-this, but first, we’ll look at the problem in action.
+this, but first we’ll look at the problem in action.
-### Simulating a Slow Request in the Current Server Implementation
+### Simulating a Slow Request
We’ll look at how a slow-processing request can affect other requests made to
our current server implementation. Listing 20-10 implements handling a request
to */sleep* with a simulated slow response that will cause the server to sleep
-for 5 seconds before responding.
+for five seconds before responding.
Filename: src/main.rs
@@ -657,44 +673,44 @@ use std::{
thread,
time::Duration,
};
-// --snip--
+--snip--
fn handle_connection(mut stream: TcpStream) {
- // --snip--
+ --snip--
- let (status_line, filename) = [1] match &request_line[..] {
- [2] "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"),
- [3] "GET /sleep HTTP/1.1" => {
+ let (status_line, filename) = 1 match &request_line[..] {
+ 2 "GET / HTTP/1.1" => ("HTTP/1.1 200 OK", "hello.html"),
+ 3 "GET /sleep HTTP/1.1" => {
thread::sleep(Duration::from_secs(5));
("HTTP/1.1 200 OK", "hello.html")
}
- [4] _ => ("HTTP/1.1 404 NOT FOUND", "404.html"),
+ 4 _ => ("HTTP/1.1 404 NOT FOUND", "404.html"),
};
- // --snip--
+ --snip--
}
```
-Listing 20-10: Simulating a slow request by sleeping for 5 seconds
+Listing 20-10: Simulating a slow request by sleeping for five seconds
We switched from `if` to `match` now that we have three cases [1]. We need to
-explicitly match on a slice of `request_line` to pattern match against the
+explicitly match on a slice of `request_line` to pattern-match against the
string literal values; `match` doesn’t do automatic referencing and
-dereferencing like the equality method does.
+dereferencing, like the equality method does.
The first arm [2] is the same as the `if` block from Listing 20-9. The second
arm [3] matches a request to */sleep*. When that request is received, the
-server will sleep for 5 seconds before rendering the successful HTML page. The
-third arm [4] is the same as the `else` block from Listing 20-9.
+server will sleep for five seconds before rendering the successful HTML page.
+The third arm [4] is the same as the `else` block from Listing 20-9.
You can see how primitive our server is: real libraries would handle the
recognition of multiple requests in a much less verbose way!
Start the server using `cargo run`. Then open two browser windows: one for
-*http://127.0.0.1:7878/* and the other for *http://127.0.0.1:7878/sleep*. If
-you enter the */* URI a few times, as before, you’ll see it respond quickly.
-But if you enter */sleep* and then load */*, you’ll see that */* waits until
-`sleep` has slept for its full 5 seconds before loading.
+*http://127.0.0.1:7878* and the other for *http://127.0.0.1:7878/sleep*. If you
+enter the */* URI a few times, as before, you’ll see it respond quickly. But if
+you enter */sleep* and then load */*, you’ll see that */* waits until `sleep`
+has slept for its full five seconds before loading.
There are multiple techniques we could use to avoid requests backing up behind
a slow request; the one we’ll implement is a thread pool.
@@ -711,33 +727,28 @@ a new task. A thread pool allows you to process connections concurrently,
increasing the throughput of your server.
We’ll limit the number of threads in the pool to a small number to protect us
-from Denial of Service (DoS) attacks; if we had our program create a new thread
-for each request as it came in, someone making 10 million requests to our
-server could create havoc by using up all our server’s resources and grinding
-the processing of requests to a halt.
+from DoS attacks; if we had our program create a new thread for each request as
+it came in, someone making 10 million requests to our server could create havoc
+by using up all our server’s resources and grinding the processing of requests
+to a halt.
Rather than spawning unlimited threads, then, we’ll have a fixed number of
threads waiting in the pool. Requests that come in are sent to the pool for
processing. The pool will maintain a queue of incoming requests. Each of the
threads in the pool will pop off a request from this queue, handle the request,
and then ask the queue for another request. With this design, we can process up
-to `N` requests concurrently, where `N` is the number of threads. If each
-thread is responding to a long-running request, subsequent requests can still
-back up in the queue, but we’ve increased the number of long-running requests
-we can handle before reaching that point.
+to N requests concurrently, where N is the number of threads. If each thread is
+responding to a long-running request, subsequent requests can still back up in
+the queue, but we’ve increased the number of long-running requests we can
+handle before reaching that point.
This technique is just one of many ways to improve the throughput of a web
-server. Other options you might explore are the *fork/join model*, the
-*single-threaded async I/O model*, or the *multi-threaded async I/O model*. If
+server. Other options you might explore are the fork/join model, the
+single-threaded async I/O model, and the multithreaded async I/O model. If
you’re interested in this topic, you can read more about other solutions and
try to implement them; with a low-level language like Rust, all of these
options are possible.
-<!-- A more modern approach would probably use tokio, which could be a
-multi-threaded async I/O model. /JT -->
-<!-- I've added "multi-theraded async I/O model", I don't want to get into
-particular async crates though /Carol -->
-
Before we begin implementing a thread pool, let’s talk about what using the
pool should look like. When you’re trying to design code, writing the client
interface first can help guide your design. Write the API of the code so it’s
@@ -757,8 +768,7 @@ First, let’s explore how our code might look if it did create a new thread for
every connection. As mentioned earlier, this isn’t our final plan due to the
problems with potentially spawning an unlimited number of threads, but it is a
starting point to get a working multithreaded server first. Then we’ll add the
-thread pool as an improvement, and contrasting the two solutions will be
-easier.
+thread pool as an improvement, and contrasting the two solutions will be easier.
Listing 20-11 shows the changes to make to `main` to spawn a new thread to
handle each stream within the `for` loop.
@@ -790,9 +800,9 @@ new threads without any limit.
#### Creating a Finite Number of Threads
-We want our thread pool to work in a similar, familiar way so switching from
-threads to a thread pool doesn’t require large changes to the code that uses
-our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool`
+We want our thread pool to work in a similar, familiar way so that switching
+from threads to a thread pool doesn’t require large changes to the code that
+uses our API. Listing 20-12 shows the hypothetical interface for a `ThreadPool`
struct we want to use instead of `thread::spawn`.
Filename: src/main.rs
@@ -800,12 +810,12 @@ Filename: src/main.rs
```
fn main() {
let listener = TcpListener::bind("127.0.0.1:7878").unwrap();
- [1] let pool = ThreadPool::new(4);
+ 1 let pool = ThreadPool::new(4);
for stream in listener.incoming() {
let stream = stream.unwrap();
- [2] pool.execute(|| {
+ 2 pool.execute(|| {
handle_connection(stream);
});
}
@@ -819,9 +829,9 @@ of threads, in this case four [1]. Then, in the `for` loop, `pool.execute` has
a similar interface as `thread::spawn` in that it takes a closure the pool
should run for each stream [2]. We need to implement `pool.execute` so it takes
the closure and gives it to a thread in the pool to run. This code won’t yet
-compile, but we’ll try so the compiler can guide us in how to fix it.
+compile, but we’ll try so that the compiler can guide us in how to fix it.
-#### Building `ThreadPool` Using Compiler Driven Development
+#### Building ThreadPool Using Compiler-Driven Development
Make the changes in Listing 20-12 to *src/main.rs*, and then let’s use the
compiler errors from `cargo check` to drive our development. Here is the first
@@ -831,21 +841,21 @@ error we get:
$ cargo check
Checking hello v0.1.0 (file:///projects/hello)
error[E0433]: failed to resolve: use of undeclared type `ThreadPool`
- --> src/main.rs:10:16
+ --> src/main.rs:11:16
|
-10 | let pool = ThreadPool::new(4);
+11 | let pool = ThreadPool::new(4);
| ^^^^^^^^^^ use of undeclared type `ThreadPool`
```
Great! This error tells us we need a `ThreadPool` type or module, so we’ll
build one now. Our `ThreadPool` implementation will be independent of the kind
-of work our web server is doing. So, let’s switch the `hello` crate from a
+of work our web server is doing. So let’s switch the `hello` crate from a
binary crate to a library crate to hold our `ThreadPool` implementation. After
we change to a library crate, we could also use the separate thread pool
library for any work we want to do using a thread pool, not just for serving
web requests.
-Create a *src/lib.rs* that contains the following, which is the simplest
+Create a *src/lib.rs* file that contains the following, which is the simplest
definition of a `ThreadPool` struct that we can have for now:
Filename: src/lib.rs
@@ -854,7 +864,7 @@ Filename: src/lib.rs
pub struct ThreadPool;
```
-Then edit *main.rs* file to bring `ThreadPool` into scope from the library
+Then edit the *main.rs* file to bring `ThreadPool` into scope from the library
crate by adding the following code to the top of *src/main.rs*:
Filename: src/main.rs
@@ -869,11 +879,13 @@ we need to address:
```
$ cargo check
Checking hello v0.1.0 (file:///projects/hello)
-error[E0599]: no function or associated item named `new` found for struct `ThreadPool` in the current scope
- --> src/bin/main.rs:11:28
+error[E0599]: no function or associated item named `new` found for struct
+`ThreadPool` in the current scope
+ --> src/main.rs:12:28
|
-11 | let pool = ThreadPool::new(4);
- | ^^^ function or associated item not found in `ThreadPool`
+12 | let pool = ThreadPool::new(4);
+ | ^^^ function or associated item not found in
+`ThreadPool`
```
This error indicates that next we need to create an associated function named
@@ -894,37 +906,37 @@ impl ThreadPool {
}
```
-We chose `usize` as the type of the `size` parameter, because we know that a
+We chose `usize` as the type of the `size` parameter because we know that a
negative number of threads doesn’t make any sense. We also know we’ll use this
-4 as the number of elements in a collection of threads, which is what the
-`usize` type is for, as discussed in the “Integer Types” section of Chapter 3.
+`4` as the number of elements in a collection of threads, which is what the
+`usize` type is for, as discussed in “Integer Types” on page XX.
Let’s check the code again:
```
$ cargo check
Checking hello v0.1.0 (file:///projects/hello)
-error[E0599]: no method named `execute` found for struct `ThreadPool` in the current scope
- --> src/bin/main.rs:16:14
+error[E0599]: no method named `execute` found for struct `ThreadPool` in the
+current scope
+ --> src/main.rs:17:14
|
-16 | pool.execute(|| {
+17 | pool.execute(|| {
| ^^^^^^^ method not found in `ThreadPool`
```
Now the error occurs because we don’t have an `execute` method on `ThreadPool`.
-Recall from the “Creating a Finite Number of Threads” section that we decided
+Recall from “Creating a Finite Number of Threads” on page XX that we decided
our thread pool should have an interface similar to `thread::spawn`. In
addition, we’ll implement the `execute` function so it takes the closure it’s
given and gives it to an idle thread in the pool to run.
We’ll define the `execute` method on `ThreadPool` to take a closure as a
-parameter. Recall from the “Moving Captured Values Out of the Closure and the
-`Fn` Traits” section in Chapter 13 that we can take closures as parameters with
-three different traits: `Fn`, `FnMut`, and `FnOnce`. We need to decide which
-kind of closure to use here. We know we’ll end up doing something similar to
-the standard library `thread::spawn` implementation, so we can look at what
-bounds the signature of `thread::spawn` has on its parameter. The documentation
-shows us the following:
+parameter. Recall from “Moving Captured Values Out of Closures and the Fn
+Traits” on page XX that we can take closures as parameters with three different
+traits: `Fn`, `FnMut`, and `FnOnce`. We need to decide which kind of closure to
+use here. We know we’ll end up doing something similar to the standard library
+`thread::spawn` implementation, so we can look at what bounds the signature of
+`thread::spawn` has on its parameter. The documentation shows us the following:
```
pub fn spawn<F, T>(f: F) -> JoinHandle<T>
@@ -952,10 +964,10 @@ Filename: src/lib.rs
```
impl ThreadPool {
- // --snip--
+ --snip--
pub fn execute<F>(&self, f: F)
where
- F: FnOnce() [1] + Send + 'static,
+ F: FnOnce() 1 + Send + 'static,
{
}
}
@@ -967,7 +979,7 @@ function definitions, the return type can be omitted from the signature, but
even if we have no parameters, we still need the parentheses.
Again, this is the simplest implementation of the `execute` method: it does
-nothing, but we’re trying only to make our code compile. Let’s check it again:
+nothing, but we’re only trying to make our code compile. Let’s check it again:
```
$ cargo check
@@ -981,18 +993,18 @@ the chapter. Our library isn’t actually calling the closure passed to `execute
yet!
> Note: A saying you might hear about languages with strict compilers, such as
-> Haskell and Rust, is “if the code compiles, it works.” But this saying is not
-> universally true. Our project compiles, but it does absolutely nothing! If we
-> were building a real, complete project, this would be a good time to start
-> writing unit tests to check that the code compiles *and* has the behavior we
-> want.
+Haskell and Rust, is “if the code compiles, it works.” But this saying is not
+universally true. Our project compiles, but it does absolutely nothing! If we
+were building a real, complete project, this would be a good time to start
+writing unit tests to check that the code compiles *and* has the behavior we
+want.
-#### Validating the Number of Threads in `new`
+#### Validating the Number of Threads in new
We aren’t doing anything with the parameters to `new` and `execute`. Let’s
implement the bodies of these functions with the behavior we want. To start,
let’s think about `new`. Earlier we chose an unsigned type for the `size`
-parameter, because a pool with a negative number of threads makes no sense.
+parameter because a pool with a negative number of threads makes no sense.
However, a pool with zero threads also makes no sense, yet zero is a perfectly
valid `usize`. We’ll add code to check that `size` is greater than zero before
we return a `ThreadPool` instance and have the program panic if it receives a
@@ -1006,16 +1018,16 @@ impl ThreadPool {
///
/// The size is the number of threads in the pool.
///
- [1] /// # Panics
+ 1 /// # Panics
///
/// The `new` function will panic if the size is zero.
pub fn new(size: usize) -> ThreadPool {
- [2] assert!(size > 0);
+ 2 assert!(size > 0);
ThreadPool
}
- // --snip--
+ --snip--
}
```
@@ -1035,14 +1047,10 @@ you’re feeling ambitious, try to write a function named `build` with the
following signature to compare with the `new` function:
```
-pub fn build(size: usize) -> Result<ThreadPool, PoolCreationError> {
+pub fn build(
+ size: usize
+) -> Result<ThreadPool, PoolCreationError> {
```
-<!-- Similar nit here to a comment I made a few chapters ago: fallible
-constructors are awkward to use. We may want to discourage their use. A modern
-approach might use a builder pattern to set the number of threads, and use a
-default number of threads that's non-zero. /JT -->
-<!-- I've changed the function name to be `build` which nicely matches the
-changes JT suggested for chapter 12. /Carol -->
#### Creating Space to Store the Threads
@@ -1073,18 +1081,18 @@ returned a `ThreadPool` instance containing them.
Filename: src/lib.rs
```
-[1] use std::thread;
+1 use std::thread;
pub struct ThreadPool {
- [2] threads: Vec<thread::JoinHandle<()>>,
+ 2 threads: Vec<thread::JoinHandle<()>>,
}
impl ThreadPool {
- // --snip--
+ --snip--
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
- [3] let mut threads = Vec::with_capacity(size);
+ 3 let mut threads = Vec::with_capacity(size);
for _ in 0..size {
// create some threads and store them in the vector
@@ -1092,26 +1100,26 @@ impl ThreadPool {
ThreadPool { threads }
}
- // --snip--
+ --snip--
}
```
Listing 20-14: Creating a vector for `ThreadPool` to hold the threads
-We’ve brought `std::thread` into scope in the library crate [1], because we’re
+We’ve brought `std::thread` into scope in the library crate [1] because we’re
using `thread::JoinHandle` as the type of the items in the vector in
`ThreadPool` [2].
Once a valid size is received, our `ThreadPool` creates a new vector that can
hold `size` items [3]. The `with_capacity` function performs the same task as
-`Vec::new` but with an important difference: it preallocates space in the
+`Vec::new` but with an important difference: it pre-allocates space in the
vector. Because we know we need to store `size` elements in the vector, doing
this allocation up front is slightly more efficient than using `Vec::new`,
which resizes itself as elements are inserted.
When you run `cargo check` again, it should succeed.
-#### A `Worker` Struct Responsible for Sending Code from the `ThreadPool` to a Thread
+#### Sending Code from the ThreadPool to a Thread
We left a comment in the `for` loop in Listing 20-14 regarding the creation of
threads. Here, we’ll look at how we actually create threads. The standard
@@ -1125,31 +1133,31 @@ implement it manually.
We’ll implement this behavior by introducing a new data structure between the
`ThreadPool` and the threads that will manage this new behavior. We’ll call
this data structure *Worker*, which is a common term in pooling
-implementations. The Worker picks up code that needs to be run and runs the
-code in the Worker’s thread.
+implementations. The `Worker` picks up code that needs to be run and runs the
+code in its thread.
-Think of people working in the kitchen at a restaurant: the
-workers wait until orders come in from customers, and then they’re responsible
-for taking those orders and filling them.
+Think of people working in the kitchen at a restaurant: the workers wait until
+orders come in from customers, and then they’re responsible for taking those
+orders and filling them.
Instead of storing a vector of `JoinHandle<()>` instances in the thread pool,
we’ll store instances of the `Worker` struct. Each `Worker` will store a single
`JoinHandle<()>` instance. Then we’ll implement a method on `Worker` that will
take a closure of code to run and send it to the already running thread for
-execution. We’ll also give each worker an `id` so we can distinguish between
-the different workers in the pool when logging or debugging.
+execution. We’ll also give each `Worker` an `id` so we can distinguish between
+the different instances of `Worker` in the pool when logging or debugging.
Here is the new process that will happen when we create a `ThreadPool`. We’ll
implement the code that sends the closure to the thread after we have `Worker`
set up in this way:
1. Define a `Worker` struct that holds an `id` and a `JoinHandle<()>`.
-2. Change `ThreadPool` to hold a vector of `Worker` instances.
-3. Define a `Worker::new` function that takes an `id` number and returns a
- `Worker` instance that holds the `id` and a thread spawned with an empty
- closure.
-4. In `ThreadPool::new`, use the `for` loop counter to generate an `id`, create
- a new `Worker` with that `id`, and store the worker in the vector.
+1. Change `ThreadPool` to hold a vector of `Worker` instances.
+1. Define a `Worker::new` function that takes an `id` number and returns a
+`Worker` instance that holds the `id` and a thread spawned with an empty
+closure.
+1. In `ThreadPool::new`, use the `for` loop counter to generate an `id`, create
+a new `Worker` with that `id`, and store the `Worker` in the vector.
If you’re up for a challenge, try implementing these changes on your own before
looking at the code in Listing 20-15.
@@ -1162,49 +1170,39 @@ Filename: src/lib.rs
use std::thread;
pub struct ThreadPool {
- [1] workers: Vec<Worker>,
+ 1 workers: Vec<Worker>,
}
impl ThreadPool {
- // --snip--
+ --snip--
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let mut workers = Vec::with_capacity(size);
- [2] for id in 0..size {
- [3] workers.push(Worker::new(id));
+ 2 for id in 0..size {
+ 3 workers.push(Worker::new(id));
}
ThreadPool { workers }
}
- // --snip--
+ --snip--
}
-[4] struct Worker {
+4 struct Worker {
id: usize,
thread: thread::JoinHandle<()>,
}
impl Worker {
- [5] fn new(id: usize) -> Worker {
- [6] let thread = thread::spawn(|| {});
+ 5 fn new(id: usize) -> Worker {
+ 6 let thread = thread::spawn(|| {});
- Worker { [7] id, [8] thread }
+ Worker { 7 id, 8 thread }
}
}
```
-<!-- Spawning a thread in the constructor isn't safe to do as the spawn
-of the thread may fail. You can use
-https://doc.rust-lang.org/std/thread/struct.Builder.html#method.spawn
-to be better protected against running out of resources. This should
-probably not live in the constructor, but instead in some helper function
-that can return a Result. /JT -->
-<!-- I've added a note in a few paragraphs. I think this behavior is perfectly
-fine for this example so I'm not going to change the code, but it is something
-readers should know. /Carol -->
-
Listing 20-15: Modifying `ThreadPool` to hold `Worker` instances instead of
holding threads directly
@@ -1221,11 +1219,11 @@ so we make the `Worker` struct [4] and its `new` function [5] private. The
empty closure [6].
> Note: If the operating system can’t create a thread because there aren’t
-> enough system resources, `thread::spawn` will panic. That will cause our
-> whole server to panic, even though the creation of some threads might
-> succeed. For simplicity’s sake, this behavior is fine, but in a production
-> thread pool implementation, you’d likely want to use `std::thread::Builder`
-> and its `spawn` method that returns `Result` instead.
+enough system resources, `thread::spawn` will panic. That will cause our whole
+server to panic, even though the creation of some threads might succeed. For
+simplicity’s sake, this behavior is fine, but in a production thread pool
+implementation, you’d likely want to use `std::thread::Builder` and its `spawn`
+method that returns `Result` instead.
This code will compile and will store the number of `Worker` instances we
specified as an argument to `ThreadPool::new`. But we’re *still* not processing
@@ -1247,13 +1245,13 @@ as the queue of jobs, and `execute` will send a job from the `ThreadPool` to
the `Worker` instances, which will send the job to its thread. Here is the plan:
1. The `ThreadPool` will create a channel and hold on to the sender.
-2. Each `Worker` will hold on to the receiver.
-3. We’ll create a new `Job` struct that will hold the closures we want to send
- down the channel.
-4. The `execute` method will send the job it wants to execute through the
- sender.
-5. In its thread, the `Worker` will loop over its receiver and execute the
- closures of any jobs it receives.
+1. Each `Worker` will hold on to the receiver.
+1. We’ll create a new `Job` struct that will hold the closures we want to send
+down the channel.
+1. The `execute` method will send the job it wants to execute through the
+sender.
+1. In its thread, the `Worker` will loop over its receiver and execute the
+closures of any jobs it receives.
Let’s start by creating a channel in `ThreadPool::new` and holding the sender
in the `ThreadPool` instance, as shown in Listing 20-16. The `Job` struct
@@ -1273,11 +1271,11 @@ pub struct ThreadPool {
struct Job;
impl ThreadPool {
- // --snip--
+ --snip--
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
- [1] let (sender, receiver) = mpsc::channel();
+ 1 let (sender, receiver) = mpsc::channel();
let mut workers = Vec::with_capacity(size);
@@ -1285,9 +1283,9 @@ impl ThreadPool {
workers.push(Worker::new(id));
}
- ThreadPool { workers, [2] sender }
+ ThreadPool { workers, 2 sender }
}
- // --snip--
+ --snip--
}
```
@@ -1297,16 +1295,16 @@ transmits `Job` instances
In `ThreadPool::new`, we create our new channel [1] and have the pool hold the
sender [2]. This will successfully compile.
-Let’s try passing a receiver of the channel into each worker as the thread pool
-creates the channel. We know we want to use the receiver in the thread that the
-workers spawn, so we’ll reference the `receiver` parameter in the closure. The
-code in Listing 20-17 won’t quite compile yet.
+Let’s try passing a receiver of the channel into each `Worker` as the thread
+pool creates the channel. We know we want to use the receiver in the thread
+that the `Worker` instances spawn, so we’ll reference the `receiver` parameter
+in the closure. The code in Listing 20-17 won’t quite compile yet.
Filename: src/lib.rs
```
impl ThreadPool {
- // --snip--
+ --snip--
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
@@ -1315,20 +1313,20 @@ impl ThreadPool {
let mut workers = Vec::with_capacity(size);
for id in 0..size {
- [1] workers.push(Worker::new(id, receiver));
+ 1 workers.push(Worker::new(id, receiver));
}
ThreadPool { workers, sender }
}
- // --snip--
+ --snip--
}
-// --snip--
+--snip--
impl Worker {
fn new(id: usize, receiver: mpsc::Receiver<Job>) -> Worker {
let thread = thread::spawn(|| {
- [2] receiver;
+ 2 receiver;
});
Worker { id, thread }
@@ -1336,7 +1334,7 @@ impl Worker {
}
```
-Listing 20-17: Passing the receiver to the workers
+Listing 20-17: Passing the receiver to each `Worker`
We’ve made some small and straightforward changes: we pass the receiver into
`Worker::new` [1], and then we use it inside the closure [2].
@@ -1347,13 +1345,15 @@ When we try to check this code, we get this error:
$ cargo check
Checking hello v0.1.0 (file:///projects/hello)
error[E0382]: use of moved value: `receiver`
- --> src/lib.rs:27:42
+ --> src/lib.rs:26:42
|
-22 | let (sender, receiver) = mpsc::channel();
- | -------- move occurs because `receiver` has type `std::sync::mpsc::Receiver<Job>`, which does not implement the `Copy` trait
+21 | let (sender, receiver) = mpsc::channel();
+ | -------- move occurs because `receiver` has type
+`std::sync::mpsc::Receiver<Job>`, which does not implement the `Copy` trait
...
-27 | workers.push(Worker::new(id, receiver));
- | ^^^^^^^^ value moved here, in previous iteration of loop
+26 | workers.push(Worker::new(id, receiver));
+ | ^^^^^^^^ value moved here, in
+previous iteration of loop
```
The code is trying to pass `receiver` to multiple `Worker` instances. This
@@ -1361,7 +1361,8 @@ won’t work, as you’ll recall from Chapter 16: the channel implementation tha
Rust provides is multiple *producer*, single *consumer*. This means we can’t
just clone the consuming end of the channel to fix this code. We also don’t
want to send a message multiple times to multiple consumers; we want one list
-of messages with multiple workers such that each message gets processed once.
+of messages with multiple `Worker` instances such that each message gets
+processed once.
Additionally, taking a job off the channel queue involves mutating the
`receiver`, so the threads need a safe way to share and modify `receiver`;
@@ -1369,9 +1370,10 @@ otherwise, we might get race conditions (as covered in Chapter 16).
Recall the thread-safe smart pointers discussed in Chapter 16: to share
ownership across multiple threads and allow the threads to mutate the value, we
-need to use `Arc<Mutex<T>>`. The `Arc` type will let multiple workers own the
-receiver, and `Mutex` will ensure that only one worker gets a job from the
-receiver at a time. Listing 20-18 shows the changes we need to make.
+need to use `Arc<Mutex<T>>`. The `Arc` type will let multiple `Worker`
+instances own the receiver, and `Mutex` will ensure that only one `Worker` gets
+a job from the receiver at a time. Listing 20-18 shows the changes we need to
+make.
Filename: src/lib.rs
@@ -1380,75 +1382,81 @@ use std::{
sync::{mpsc, Arc, Mutex},
thread,
};
-// --snip--
+--snip--
impl ThreadPool {
- // --snip--
+ --snip--
pub fn new(size: usize) -> ThreadPool {
assert!(size > 0);
let (sender, receiver) = mpsc::channel();
- [1] let receiver = Arc::new(Mutex::new(receiver));
+ 1 let receiver = Arc::new(Mutex::new(receiver));
let mut workers = Vec::with_capacity(size);
for id in 0..size {
- workers.push(Worker::new(id, Arc::clone(&receiver)[2]));
+ workers.push(
+ Worker::new(id, Arc::clone(& 2 receiver))
+ );
}
ThreadPool { workers, sender }
}
- // --snip--
+ --snip--
}
-// --snip--
+--snip--
impl Worker {
- fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
- // --snip--
+ fn new(
+ id: usize,
+ receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
+ ) -> Worker {
+ --snip--
}
}
```
-Listing 20-18: Sharing the receiver among the workers using `Arc` and `Mutex`
+Listing 20-18: Sharing the receiver among the `Worker` instances using `Arc`
+and `Mutex`
In `ThreadPool::new`, we put the receiver in an `Arc` and a `Mutex` [1]. For
-each new worker, we clone the `Arc` to bump the reference count so the workers
-can share ownership of the receiver [2].
+each new `Worker`, we clone the `Arc` to bump the reference count so the
+`Worker` instances can share ownership of the receiver [2].
With these changes, the code compiles! We’re getting there!
-#### Implementing the `execute` Method
+#### Implementing the execute Method
Let’s finally implement the `execute` method on `ThreadPool`. We’ll also change
`Job` from a struct to a type alias for a trait object that holds the type of
-closure that `execute` receives. As discussed in the “Creating Type Synonyms
-with Type Aliases” section of Chapter 19, type aliases allow us to make long
-types shorter for ease of use. Look at Listing 20-19.
+closure that `execute` receives. As discussed in “Creating Type Synonyms with
+Type Aliases” on page XX, type aliases allow us to make long types shorter for
+ease of use. Look at Listing 20-19.
Filename: src/lib.rs
```
-// --snip--
+--snip--
type Job = Box<dyn FnOnce() + Send + 'static>;
impl ThreadPool {
- // --snip--
+ --snip--
pub fn execute<F>(&self, f: F)
where
F: FnOnce() + Send + 'static,
{
- [1] let job = Box::new(f);
+ 1 let job = Box::new(f);
- [2] self.sender.send(job).unwrap();
+ 2 self.sender.send(job).unwrap();
}
}
-// --snip--
+--snip--
```
Listing 20-19: Creating a `Job` type alias for a `Box` that holds each closure
@@ -1463,7 +1471,7 @@ executing: our threads continue executing as long as the pool exists. The
reason we use `unwrap` is that we know the failure case won’t happen, but the
compiler doesn’t know that.
-But we’re not quite done yet! In the worker, our closure being passed to
+But we’re not quite done yet! In the `Worker`, our closure being passed to
`thread::spawn` still only *references* the receiving end of the channel.
Instead, we need the closure to loop forever, asking the receiving end of the
channel for a job and running the job when it gets one. Let’s make the change
@@ -1472,12 +1480,19 @@ shown in Listing 20-20 to `Worker::new`.
Filename: src/lib.rs
```
-// --snip--
+--snip--
impl Worker {
- fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ fn new(
+ id: usize,
+ receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
+ ) -> Worker {
let thread = thread::spawn(move || loop {
- let job = receiver.lock()[1].unwrap()[2].recv()[3].unwrap()[4];
+ let job = receiver
+ 1 .lock()
+ 2 .unwrap()
+ 3 .recv()
+ 4 .unwrap();
println!("Worker {id} got a job; executing.");
@@ -1489,7 +1504,8 @@ impl Worker {
}
```
-Listing 20-20: Receiving and executing the jobs in the worker’s thread
+Listing 20-20: Receiving and executing the jobs in the `Worker` instance’s
+thread
Here, we first call `lock` on the `receiver` to acquire the mutex [1], and then
we call `unwrap` to panic on any errors [2]. Acquiring a lock might fail if the
@@ -1555,21 +1571,24 @@ overloaded if the server receives a lot of requests. If we make a request to
*/sleep*, the server will be able to serve other requests by having another
thread run them.
-> Note: if you open */sleep* in multiple browser windows simultaneously, they
-> might load one at a time in 5 second intervals. Some web browsers execute
-> multiple instances of the same request sequentially for caching reasons. This
-> limitation is not caused by our web server.
+> Note: If you open */sleep* in multiple browser windows simultaneously, they
+might load one at a time in five-second intervals. Some web browsers execute
+multiple instances of the same request sequentially for caching reasons. This
+limitation is not caused by our web server.
After learning about the `while let` loop in Chapter 18, you might be wondering
-why we didn’t write the worker thread code as shown in Listing 20-21.
+why we didn’t write the `Worker` thread code as shown in Listing 20-21.
Filename: src/lib.rs
```
-// --snip--
+--snip--
impl Worker {
- fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ fn new(
+ id: usize,
+ receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
+ ) -> Worker {
let thread = thread::spawn(move || {
while let Ok(job) = receiver.lock().unwrap().recv() {
println!("Worker {id} got a job; executing.");
@@ -1598,21 +1617,20 @@ longer than intended if we aren’t mindful of the lifetime of the
The code in Listing 20-20 that uses `let job =
receiver.lock().unwrap().recv().unwrap();` works because with `let`, any
-temporary values used in the expression on the right hand side of the equals
+temporary values used in the expression on the right-hand side of the equal
sign are immediately dropped when the `let` statement ends. However, `while
let` (and `if let` and `match`) does not drop temporary values until the end of
the associated block. In Listing 20-21, the lock remains held for the duration
-of the call to `job()`, meaning other workers cannot receive jobs.
+of the call to `job()`, meaning other `Worker` instances cannot receive jobs.
## Graceful Shutdown and Cleanup
The code in Listing 20-20 is responding to requests asynchronously through the
use of a thread pool, as we intended. We get some warnings about the `workers`,
`id`, and `thread` fields that we’re not using in a direct way that reminds us
-we’re not cleaning up anything. When we use the less elegant <span
-class="keystroke">ctrl-c</span> method to halt the main thread, all other
-threads are stopped immediately as well, even if they’re in the middle of
-serving a request.
+we’re not cleaning up anything. When we use the less elegant ctrl-C method to
+halt the main thread, all other threads are stopped immediately as well, even
+if they’re in the middle of serving a request.
Next, then, we’ll implement the `Drop` trait to call `join` on each of the
threads in the pool so they can finish the requests they’re working on before
@@ -1621,7 +1639,7 @@ accepting new requests and shut down. To see this code in action, we’ll modify
our server to accept only two requests before gracefully shutting down its
thread pool.
-### Implementing the `Drop` Trait on `ThreadPool`
+### Implementing the Drop Trait on ThreadPool
Let’s start with implementing `Drop` on our thread pool. When the pool is
dropped, our threads should all join to make sure they finish their work.
@@ -1633,10 +1651,10 @@ Filename: src/lib.rs
```
impl Drop for ThreadPool {
fn drop(&mut self) {
- [1] for worker in &mut self.workers {
- [2] println!("Shutting down worker {}", worker.id);
+ 1 for worker in &mut self.workers {
+ 2 println!("Shutting down worker {}", worker.id);
- [3] worker.thread.join().unwrap();
+ 3 worker.thread.join().unwrap();
}
}
}
@@ -1644,21 +1662,29 @@ impl Drop for ThreadPool {
Listing 20-22: Joining each thread when the thread pool goes out of scope
-First, we loop through each of the thread pool `workers` [1]. We use `&mut` for
+First we loop through each of the thread pool `workers` [1]. We use `&mut` for
this because `self` is a mutable reference, and we also need to be able to
-mutate `worker`. For each worker, we print a message saying that this
-particular worker is shutting down [2], and then we call `join` on that
-worker’s thread [3]. If the call to `join` fails, we use `unwrap` to make Rust
-panic and go into an ungraceful shutdown.
+mutate `worker`. For each `worker`, we print a message saying that this
+particular `Worker` instance is shutting down [2], and then we call `join` on
+that `Worker` instance’s thread [3]. If the call to `join` fails, we use
+`unwrap` to make Rust panic and go into an ungraceful shutdown.
Here is the error we get when we compile this code:
```
-error[E0507]: cannot move out of `worker.thread` which is behind a mutable reference
- --> src/lib.rs:52:13
- |
-52 | worker.thread.join().unwrap();
- | ^^^^^^^^^^^^^ move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
+error[E0507]: cannot move out of `worker.thread` which is behind a mutable
+reference
+ --> src/lib.rs:52:13
+ |
+52 | worker.thread.join().unwrap();
+ | ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this
+method call
+ | |
+ | 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`
```
The error tells us we can’t call `join` because we only have a mutable borrow
@@ -1687,24 +1713,27 @@ Now let’s lean on the compiler to find the other places that need to change.
Checking this code, we get two errors:
```
-error[E0599]: no method named `join` found for enum `Option` in the current scope
+error[E0599]: no method named `join` found for enum `Option` in the current
+scope
--> src/lib.rs:52:27
|
52 | worker.thread.join().unwrap();
- | ^^^^ method not found in `Option<JoinHandle<()>>`
+ | ^^^^ method not found in
+`Option<JoinHandle<()>>`
error[E0308]: mismatched types
--> src/lib.rs:72:22
|
72 | Worker { id, thread }
- | ^^^^^^ expected enum `Option`, found struct `JoinHandle`
+ | ^^^^^^ expected enum `Option`, found struct
+`JoinHandle`
|
= note: expected enum `Option<JoinHandle<()>>`
found struct `JoinHandle<_>`
help: try wrapping the expression in `Some`
|
-72 | Worker { id, Some(thread) }
- | +++++ +
+72 | Worker { id, thread: Some(thread) }
+ | +++++++++++++ +
```
Let’s address the second error, which points to the code at the end of
@@ -1715,8 +1744,11 @@ Filename: src/lib.rs
```
impl Worker {
- fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
- // --snip--
+ fn new(
+ id: usize,
+ receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
+ ) -> Worker {
+ --snip--
Worker {
id,
@@ -1738,8 +1770,8 @@ impl Drop for ThreadPool {
for worker in &mut self.workers {
println!("Shutting down worker {}", worker.id);
- [1] if let Some(thread) = worker.thread.take() {
- [2] thread.join().unwrap();
+ 1 if let Some(thread) = worker.thread.take() {
+ 2 thread.join().unwrap();
}
}
}
@@ -1749,27 +1781,27 @@ impl Drop for ThreadPool {
As discussed in Chapter 17, the `take` method on `Option` takes the `Some`
variant out and leaves `None` in its place. We’re using `if let` to destructure
the `Some` and get the thread [1]; then we call `join` on the thread [2]. If a
-worker’s thread is already `None`, we know that worker has already had its
-thread cleaned up, so nothing happens in that case.
+`Worker` instance’s thread is already `None`, we know that `Worker` has already
+had its thread cleaned up, so nothing happens in that case.
### Signaling to the Threads to Stop Listening for Jobs
With all the changes we’ve made, our code compiles without any warnings.
-However, the bad news is this code doesn’t function the way we want it to yet.
-The key is the logic in the closures run by the threads of the `Worker`
-instances: at the moment, we call `join`, but that won’t shut down the threads
+However, the bad news is that this code doesn’t function the way we want it to
+yet. The key is the logic in the closures run by the threads of the `Worker`
+instances: at the moment, we call `join`, but that won’t shut down the threads,
because they `loop` forever looking for jobs. If we try to drop our
`ThreadPool` with our current implementation of `drop`, the main thread will
-block forever waiting for the first thread to finish.
+block forever, waiting for the first thread to finish.
-To fix this problem, we’ll need a change in the the `ThreadPool` `drop`
+To fix this problem, we’ll need a change in the `ThreadPool` `drop`
implementation and then a change in the `Worker` loop.
-First, we’ll change the `ThreadPool` `drop` implementation to explicitly drop
+First we’ll change the `ThreadPool` `drop` implementation to explicitly drop
the `sender` before waiting for the threads to finish. Listing 20-23 shows the
changes to `ThreadPool` to explicitly drop `sender`. We use the same `Option`
and `take` technique as we did with the thread to be able to move `sender` out
-of `ThreadPool`:
+of `ThreadPool`.
Filename: src/lib.rs
@@ -1778,10 +1810,10 @@ pub struct ThreadPool {
workers: Vec<Worker>,
sender: Option<mpsc::Sender<Job>>,
}
-// --snip--
+--snip--
impl ThreadPool {
pub fn new(size: usize) -> ThreadPool {
- // --snip--
+ --snip--
ThreadPool {
workers,
@@ -1795,13 +1827,17 @@ impl ThreadPool {
{
let job = Box::new(f);
- self.sender.as_ref().unwrap().send(job).unwrap();
+ self.sender
+ .as_ref()
+ .unwrap()
+ .send(job)
+ .unwrap();
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
- [1] drop(self.sender.take());
+ 1 drop(self.sender.take());
for worker in &mut self.workers {
println!("Shutting down worker {}", worker.id);
@@ -1814,28 +1850,37 @@ impl Drop for ThreadPool {
}
```
-Listing 20-23: Explicitly drop `sender` before joining the worker threads
+Listing 20-23: Explicitly dropping `sender` before joining the `Worker` threads
Dropping `sender` [1] closes the channel, which indicates no more messages will
-be sent. When that happens, all the calls to `recv` that the workers do in the
-infinite loop will return an error. In Listing 20-24, we change the `Worker`
-loop to gracefully exit the loop in that case, which means the threads will
-finish when the `ThreadPool` `drop` implementation calls `join` on them.
+be sent. When that happens, all the calls to `recv` that the `Worker` instances
+do in the infinite loop will return an error. In Listing 20-24, we change the
+`Worker` loop to gracefully exit the loop in that case, which means the threads
+will finish when the `ThreadPool` `drop` implementation calls `join` on them.
Filename: src/lib.rs
```
impl Worker {
- fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
+ fn new(
+ id: usize,
+ receiver: Arc<Mutex<mpsc::Receiver<Job>>>,
+ ) -> Worker {
let thread = thread::spawn(move || loop {
- match receiver.lock().unwrap().recv() {
+ let message = receiver.lock().unwrap().recv();
+
+ match message {
Ok(job) => {
- println!("Worker {id} got a job; executing.");
+ println!(
+ "Worker {id} got a job; executing."
+ );
job();
}
Err(_) => {
- println!("Worker {id} disconnected; shutting down.");
+ println!(
+ "Worker {id} shutting down."
+ );
break;
}
}
@@ -1849,7 +1894,7 @@ impl Worker {
}
```
-Listing 20-24: Explicitly break out of the loop when `recv` returns an error
+Listing 20-24: Explicitly breaking out of the loop when `recv` returns an error
To see this code in action, let’s modify `main` to accept only two requests
before gracefully shutting down the server, as shown in Listing 20-25.
@@ -1873,8 +1918,8 @@ fn main() {
}
```
-Listing 20-25: Shut down the server after serving two requests by exiting the
-loop
+Listing 20-25: Shutting down the server after serving two requests by exiting
+the loop
You wouldn’t want a real-world web server to shut down after serving only two
requests. This code just demonstrates that the graceful shutdown and cleanup is
@@ -1905,26 +1950,27 @@ Shutting down worker 2
Shutting down worker 3
```
-You might see a different ordering of workers and messages printed. We can see
-how this code works from the messages: workers 0 and 3 got the first two
-requests. The server stopped accepting connections after the second connection,
-and the `Drop` implementation on `ThreadPool` starts executing before worker 3
-even starts its job. Dropping the `sender` disconnects all the workers and
-tells them to shut down. The workers each print a message when they disconnect,
-and then the thread pool calls `join` to wait for each worker thread to finish.
+You might see a different ordering of `Worker` IDs and messages printed. We can
+see how this code works from the messages: `Worker` instances 0 and 3 got the
+first two requests. The server stopped accepting connections after the second
+connection, and the `Drop` implementation on `ThreadPool` starts executing
+before `Worker` 3 even starts its job. Dropping the `sender` disconnects all
+the `Worker` instances and tells them to shut down. The `Worker` instances each
+print a message when they disconnect, and then the thread pool calls `join` to
+wait for each `Worker` thread to finish.
Notice one interesting aspect of this particular execution: the `ThreadPool`
-dropped the `sender`, and before any worker received an error, we tried to join
-worker 0. Worker 0 had not yet gotten an error from `recv`, so the main thread
-blocked waiting for worker 0 to finish. In the meantime, worker 3 received a
-job and then all threads received an error. When worker 0 finished, the main
-thread waited for the rest of the workers to finish. At that point, they had
-all exited their loops and stopped.
+dropped the `sender`, and before any `Worker` received an error, we tried to
+join `Worker` 0. `Worker` 0 had not yet gotten an error from `recv`, so the
+main thread blocked, waiting for `Worker` 0 to finish. In the meantime,
+`Worker` 3 received a job and then all threads received an error. When `Worker`
+0 finished, the main thread waited for the rest of the `Worker` instances to
+finish. At that point, they had all exited their loops and stopped.
Congrats! We’ve now completed our project; we have a basic web server that uses
a thread pool to respond asynchronously. We’re able to perform a graceful
shutdown of the server, which cleans up all the threads in the pool. See
-*https://www.nostarch.com/Rust2021/* to download the full code for this chapter
+*https://www.nostarch.com/Rust2021* to download the full code for this chapter
for reference.
We could do more here! If you want to continue enhancing this project, here are
@@ -1934,14 +1980,15 @@ some ideas:
* Add tests of the library’s functionality.
* Change calls to `unwrap` to more robust error handling.
* Use `ThreadPool` to perform some task other than serving web requests.
-* Find a thread pool crate on *https://crates.io/* and implement a similar web
- server using the crate instead. Then compare its API and robustness to the
- thread pool we implemented.
+* Find a thread pool crate on *https://crates.io* and implement a similar web
+server using the crate instead. Then compare its API and robustness to the
+thread pool we implemented.
## Summary
Well done! You’ve made it to the end of the book! We want to thank you for
joining us on this tour of Rust. You’re now ready to implement your own Rust
-projects and help with other peoples’ projects. Keep in mind that there is a
+projects and help with other people’s projects. Keep in mind that there is a
welcoming community of other Rustaceans who would love to help you with any
challenges you encounter on your Rust journey.
+
diff --git a/src/doc/book/nostarch/frontmatter.md b/src/doc/book/nostarch/frontmatter.md
new file mode 100644
index 000000000..001f96483
--- /dev/null
+++ b/src/doc/book/nostarch/frontmatter.md
@@ -0,0 +1,292 @@
+<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->
+## About the Authors
+
+Carol Nichols is a member of the Rust Crates.io Team and a former member of the
+Rust Core Team. She’s a co-founder of Integer 32, LLC, the world’s first
+Rust-focused software consultancy. Nichols has also organized the Rust Belt
+Rust Conference.
+
+Steve Klabnik was the lead for the Rust documentation team and was one of
+Rust’s core developers. A frequent speaker and a prolific open source
+contributor, he previously worked on projects such as Ruby and Ruby on Rails.
+
+## About the Technical Reviewer
+
+JT is a Rust core team member and the co-creator of the Rust error message
+format, Rust Language Server (RLS), and Nushell. They first started using Rust
+in 2011, and in 2016 joined Mozilla to work on Rust full time, helping to shape
+its direction for widespread use. These days, they are a freelance Rust trainer
+and advocate for safe systems programming.
+
+## Brief Contents
+
+## Contents in Detail
+
+## Foreword
+
+It wasn’t always so clear, but the Rust programming language is fundamentally
+about *empowerment*: no matter what kind of code you are writing now, Rust
+empowers you to reach further, to program with confidence in a wider variety of
+domains than you did before.
+
+Take, for example, “systems-level” work that deals with low-level details of
+memory management, data representation, and concurrency. Traditionally, this
+realm of programming is seen as arcane, accessible to only a select few who
+have devoted the necessary years learning it to avoid its infamous pitfalls.
+And even those who practice it do so with caution, lest their code be open to
+exploits, crashes, or corruption.
+
+Rust breaks down these barriers by eliminating the old pitfalls and providing a
+friendly, polished set of tools to help you along the way. Programmers who need
+to “dip down” into lower-level control can do so with Rust, without taking on
+the customary risk of crashes or security holes and without having to learn the
+fine points of a fickle toolchain. Better yet, the language is designed to
+guide you naturally toward reliable code that is efficient in terms of speed
+and memory usage.
+
+Programmers who are already working with low-level code can use Rust to raise
+their ambitions. For example, introducing parallelism in Rust is a relatively
+low-risk operation: the compiler will catch the classical mistakes for you. And
+you can tackle more aggressive optimizations in your code with the confidence
+that you won’t accidentally introduce crashes or vulnerabilities.
+
+But Rust isn’t limited to low-level systems programming. It’s expressive and
+ergonomic enough to make CLI apps, web servers, and many other kinds of code
+quite pleasant to write—you’ll find simple examples later in the book. Working
+with Rust allows you to build skills that transfer from one domain to another;
+you can learn Rust by writing a web app, then apply those same skills to target
+your Raspberry Pi.
+
+This book fully embraces the potential of Rust to empower its users. It’s a
+friendly and approachable text intended to help you level up not just your
+knowledge of Rust, but also your reach and confidence as a programmer in
+general. So dive in, get ready to learn—and welcome to the Rust community!
+
+Nicholas Matsakis and Aaron Turon
+
+## ACKNOWLEDGMENTS
+
+We would like to thank everyone who has worked on the Rust language for
+creating an amazing language worth writing a book about. We’re grateful to
+everyone in the Rust community for being welcoming and creating an environment
+worth welcoming more folks into.
+
+We’re especially thankful for everyone who read early versions of this book
+online and provided feedback, bug reports, and pull requests. Special thanks to
+Eduard-Mihai Burtescu, Alex Crichton, and JT for providing technical review,
+and to Karen Rustad Tölva for the cover art. Thank you to our team at No
+Starch, including Bill Pollock, Liz Chadwick, and Janelle Ludowise, for
+improving this book and bringing it to print.
+
+Carol is grateful for the opportunity to work on this book. She thanks her
+family for their constant love and support, especially her husband, Jake
+Goulding, and her daughter, Vivian.
+
+## Preface
+
+This version of the text assumes you’re using Rust 1.62.0 (released 2022-06-30)
+or later with `edition="2021"` in the *Cargo.toml* file of all projects to
+configure them to use Rust 2021 edition idioms. See “Installation” on page XX
+for instructions on installing or updating Rust, and see Appendix E for
+information on editions.
+
+The 2021 edition of the Rust language includes a number of improvements that
+make Rust more ergonomic and that correct some inconsistencies. On top of a
+general update to reflect these improvements, this rendition of the book has a
+number of improvements to address specific feedback:
+
+* Chapter 7 contains a new quick reference section on organizing your code into
+multiple files with modules.
+* Chapter 13 has new and improved closure examples that more clearly illustrate
+captures, the `move` keyword, and the `Fn` traits.
+* We fixed a number of small errors and imprecise wording throughout the book.
+Thank you to the readers who reported them!
+
+Note that any code from earlier renditions of this book that compiled will
+continue to compile with the relevant edition in the project’s *Cargo.toml*,
+even as you update the Rust compiler version you’re using. That’s Rust’s
+backward-compatibility guarantees at work!
+
+## Introduction
+
+Welcome to *The Rust Programming Language*, an introductory book about Rust.
+The Rust programming language helps you write faster, more reliable software.
+High-level ergonomics and low-level control are often at odds in programming
+language design; Rust challenges that conflict. Through balancing powerful
+technical capacity and a great developer experience, Rust gives you the option
+to control low-level details (such as memory usage) without all the hassle
+traditionally associated with such control.
+
+## Who Rust Is For
+
+Rust is ideal for many people for a variety of reasons. Let’s look at a few of
+the most important groups.
+
+### Teams of Developers
+
+Rust is proving to be a productive tool for collaborating among large teams of
+developers with varying levels of systems programming knowledge. Low-level code
+is prone to various subtle bugs, which in most other languages can only be
+caught through extensive testing and careful code review by experienced
+developers. In Rust, the compiler plays a gatekeeper role by refusing to
+compile code with these elusive bugs, including concurrency bugs. By working
+alongside the compiler, the team can spend their time focusing on the program’s
+logic rather than chasing down bugs.
+
+Rust also brings contemporary developer tools to the systems programming world:
+
+* Cargo, the included dependency manager and build tool, makes adding,
+compiling, and managing dependencies painless and consistent across the Rust
+ecosystem.
+* The `rustfmt` formatting tool ensures a consistent coding style across
+developers.
+* The Rust Language Server powers integrated development environment (IDE)
+integration for code completion and inline error messages.
+
+By using these and other tools in the Rust ecosystem, developers can be
+productive while writing systems-level code.
+
+### Students
+
+Rust is for students and those who are interested in learning about systems
+concepts. Using Rust, many people have learned about topics like operating
+systems development. The community is very welcoming and happy to answer
+students’ questions. Through efforts such as this book, the Rust teams want to
+make systems concepts more accessible to more people, especially those new to
+programming.
+
+### Companies
+
+Hundreds of companies, large and small, use Rust in production for a variety of
+tasks, including command line tools, web services, DevOps tooling, embedded
+devices, audio and video analysis and transcoding, cryptocurrencies,
+bioinformatics, search engines, Internet of Things applications, machine
+learning, and even major parts of the Firefox web browser.
+
+### Open Source Developers
+
+Rust is for people who want to build the Rust programming language, community,
+developer tools, and libraries. We’d love to have you contribute to the Rust
+language.
+
+### People Who Value Speed and Stability
+
+Rust is for people who crave speed and stability in a language. By speed, we
+mean both how quickly Rust code can run and the speed at which Rust lets you
+write programs. The Rust compiler’s checks ensure stability through feature
+additions and refactoring. This is in contrast to the brittle legacy code in
+languages without these checks, which developers are often afraid to modify. By
+striving for zero-cost abstractions, higher-level features that compile to
+lower-level code as fast as code written manually, Rust endeavors to make safe
+code be fast code as well.
+
+The Rust language hopes to support many other users as well; those mentioned
+here are merely some of the biggest stakeholders. Overall, Rust’s greatest
+ambition is to eliminate the trade-offs that programmers have accepted for
+decades by providing safety *and* productivity, speed *and* ergonomics. Give
+Rust a try and see if its choices work for you.
+
+## Who This Book Is For
+
+This book assumes that you’ve written code in another programming language, but
+doesn’t make any assumptions about which one. We’ve tried to make the material
+broadly accessible to those from a wide variety of programming backgrounds. We
+don’t spend a lot of time talking about what programming *is* or how to think
+about it. If you’re entirely new to programming, you would be better served by
+reading a book that specifically provides an introduction to programming.
+
+## How to Use This Book
+
+In general, this book assumes that you’re reading it in sequence from front to
+back. Later chapters build on concepts in earlier chapters, and earlier
+chapters might not delve into details on a particular topic but will revisit
+the topic in a later chapter.
+
+You’ll find two kinds of chapters in this book: concept chapters and project
+chapters. In concept chapters, you’ll learn about an aspect of Rust. In project
+chapters, we’ll build small programs together, applying what you’ve learned so
+far. Chapter 2, Chapter 12, and Chapter 20 are project chapters; the rest are
+concept chapters.
+
+**Chapter 1** explains how to install Rust, how to write a “Hello, world!”
+program, and how to use Cargo, Rust’s package manager and build tool. **Chapter
+2** is a hands-on introduction to writing a program in Rust, having you build
+up a number-guessing game. Here, we cover concepts at a high level, and later
+chapters will provide additional detail. If you want to get your hands dirty
+right away, Chapter 2 is the place for that. **Chapter 3** covers Rust features
+that are similar to those of other programming languages, and in **Chapter 4**
+you’ll learn about Rust’s ownership system. If you’re a particularly meticulous
+learner who prefers to learn every detail before moving on to the next, you
+might want to skip Chapter 2 and go straight to Chapter 3, returning to Chapter
+2 when you’d like to work on a project applying the details you’ve learned.
+
+**Chapter 5** discusses structs and methods, and **Chapter 6** covers enums,
+`match` expressions, and the `if let` control flow construct. You’ll use
+structs and enums to make custom types in Rust.
+
+In **Chapter 7**, you’ll learn about Rust’s module system and about privacy
+rules for organizing your code and its public application programming interface
+(API). **Chapter 8** discusses some common collection data structures that the
+standard library provides, such as vectors, strings, and hash maps. **Chapter
+9** explores Rust’s error-handling philosophy and techniques.
+
+**Chapter 10** digs into generics, traits, and lifetimes, which give you the
+power to define code that applies to multiple types. **Chapter 11** is all
+about testing, which even with Rust’s safety guarantees is necessary to ensure
+your program’s logic is correct. In **Chapter 12**, we’ll build our own
+implementation of a subset of functionality from the `grep` command line tool
+that searches for text within files. For this, we’ll use many of the concepts
+we discussed in the previous chapters.
+
+**Chapter 13** explores closures and iterators: features of Rust that come from
+functional programming languages. In **Chapter 14**, we’ll examine Cargo in
+more depth and talk about best practices for sharing your libraries with
+others. **Chapter 15** discusses smart pointers that the standard library
+provides and the traits that enable their functionality.
+
+In **Chapter 16**, we’ll walk through different models of concurrent
+programming and talk about how Rust helps you program in multiple threads
+fearlessly. **Chapter 17** looks at how Rust idioms compare to object-oriented
+programming principles you might be familiar with.
+
+**Chapter 18** is a reference on patterns and pattern matching, which are
+powerful ways of expressing ideas throughout Rust programs. **Chapter 19**
+contains a smorgasbord of advanced topics of interest, including unsafe Rust,
+macros, and more about lifetimes, traits, types, functions, and closures.
+
+In **Chapter 20**, we’ll complete a project in which we’ll implement a
+low-level multithreaded web server!
+
+Finally, some appendices contain useful information about the language in a
+more reference-like format**. Appendix A** covers Rust’s keywords, **Appendix
+B** covers Rust’s operators and symbols, **Appendix C** covers derivable traits
+provided by the standard library, **Appendix D** covers some useful development
+tools, and **Appendix E** explains Rust editions.
+
+There is no wrong way to read this book: if you want to skip ahead, go for it!
+You might have to jump back to earlier chapters if you experience any
+confusion. But do whatever works for you.
+
+An important part of the process of learning Rust is learning how to read the
+error messages the compiler displays: these will guide you toward working code.
+As such, we’ll provide many examples that don’t compile along with the error
+message the compiler will show you in each situation. Know that if you enter
+and run a random example, it may not compile! Make sure you read the
+surrounding text to see whether the example you’re trying to run is meant to
+error. In most situations, we’ll lead you to the correct version of any code
+that doesn’t compile.
+
+## Resources and How to Contribute to This Book
+
+This book is open source. If you find an error, please don’t hesitate to file
+an issue or send a pull request on GitHub at
+*https://github.com/rust-lang/book*. Please see *CONTRIBUTING.md* at
+*https://github.com/rust-lang/book/blob/main/CONTRIBUTING.md* for more details.
+
+The source code for the examples in this book, errata, and other information
+are available at *https://www.nostarch.com/Rust2021*.
+
diff --git a/src/doc/book/nostarch/introduction.md b/src/doc/book/nostarch/introduction.md
index b3ff9b111..bcaed24c5 100644
--- a/src/doc/book/nostarch/introduction.md
+++ b/src/doc/book/nostarch/introduction.md
@@ -8,7 +8,7 @@ directory, so all fixes need to be made in `/src/`.
# Introduction
-Welcome to *The Rust Programming Language*, an introductory book about Rust.
+Welcome to *The Rust Programming Language,* an introductory book about Rust.
The Rust programming language helps you write faster, more reliable software.
High-level ergonomics and low-level control are often at odds in programming
language design; Rust challenges that conflict. Through balancing powerful
@@ -62,12 +62,6 @@ devices, audio and video analysis and transcoding, cryptocurrencies,
bioinformatics, search engines, Internet of Things applications, machine
learning, and even major parts of the Firefox web browser.
-<!-- with Rust adopted in a lot of really recognizable names, is it worth
-namedropping some companies that use Rust significantly? /LC -->
-<!-- No, I don't want to show favoritism, and there are lots of politics around
-the big companies using Rust that I don't want to get into. I would also worry
-about the list getting dated. /Carol -->
-
### Open Source Developers
Rust is for people who want to build the Rust programming language, community,
@@ -119,7 +113,7 @@ number guessing game. Here we cover concepts at a high level, and later
chapters will provide additional detail. If you want to get your hands dirty
right away, Chapter 2 is the place for that. Chapter 3 covers Rust features
that are similar to those of other programming languages, and in Chapter 4
-you'll learn about Rust’s ownership system. If you’re a particularly meticulous
+you’ll learn about Rust’s ownership system. If you’re a particularly meticulous
learner who prefers to learn every detail before moving on to the next, you
might want to skip Chapter 2 and go straight to Chapter 3, returning to Chapter
2 when you’d like to work on a project applying the details you’ve learned.
@@ -182,10 +176,11 @@ that doesn’t compile.
## Resources and How to Contribute to This Book
-This book is open source. If you find an error, please don't hesitate to file
+This book is open source. If you find an error, please don’t hesitate to file
an issue or send a pull request on GitHub at
*https://github.com/rust-lang/book/*. Please see *CONTRIBUTING.md* at
*https://github.com/rust-lang/book/blob/main/CONTRIBUTING.md* for more details.
The source code for the examples in this book, errata, and other information
are available at *https://www.nostarch.com/Rust2021/*.
+
diff --git a/src/doc/book/nostarch/preface.md b/src/doc/book/nostarch/preface.md
index 5ec239151..33b1a0fd8 100644
--- a/src/doc/book/nostarch/preface.md
+++ b/src/doc/book/nostarch/preface.md
@@ -1,22 +1,22 @@
-# Preface
+## Preface
This version of the text assumes you’re using Rust 1.62.0 (released 2022-06-30)
-or later with edition="2021" in *Cargo.toml* of all projects to use Rust 2021
-Edition idioms. See “Installation” on page 1 to install or update Rust, and see
-Appendix E for information on editions.
+or later with `edition="2021"` in *Cargo.toml* of all projects to use Rust 2021
+Edition idioms. See “Installation” on page 1 for instructions on installing or
+updating Rust, and see Appendix E for information on editions.
-The 2021 Edition of the Rust language includes a small number of improvements
-that make Rust more ergonomic and correct some inconsistencies. This rendition
-of the book has a number of improvements to address feedback:
+The 2021 Edition of the Rust language includes a number of improvements that
+make Rust more ergonomic and correct some inconsistencies. On top of a general
+update to reflect these improvements, this rendition of the book has a number
+of improvements to address specific feedback:
-• Chapter 7 contains a new quick reference section on organizing your code into
+* Chapter 7 contains a new quick reference section on organizing your code into
multiple files with modules.
-• Chapter 13 has new and improved closure examples that more clearly illustrate
+* Chapter 13 has new and improved closure examples that more clearly illustrate
captures, the `move` keyword, and the `Fn` traits.
-• We fixed a number of small errors and imprecise wording throughout the book.
+* We fixed a number of small errors and imprecise wording throughout the book.
Thank you to the readers who reported them!
-
-Note that any code in earlier renditions of this book that compiled will
+Note that any code from earlier renditions of this book that compiled will
continue to compile with the relevant edition in the project’s *Cargo.toml*,
even as you update the Rust compiler version you’re using. That’s Rust’s
backward compatibility guarantees at work!
diff --git a/src/doc/book/src/appendix-04-useful-development-tools.md b/src/doc/book/src/appendix-04-useful-development-tools.md
index b357f64e2..40b076153 100644
--- a/src/doc/book/src/appendix-04-useful-development-tools.md
+++ b/src/doc/book/src/appendix-04-useful-development-tools.md
@@ -130,14 +130,15 @@ fn main() {
Running `cargo clippy` on this project results in this error:
```text
-error: approximate value of `f{32, 64}::consts::PI` found. Consider using it directly
+error: approximate value of `f{32, 64}::consts::PI` found
--> src/main.rs:2:13
|
2 | let x = 3.1415;
| ^^^^^^
|
- = note: #[deny(clippy::approx_constant)] on by default
- = help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/master/index.html#approx_constant
+ = note: `#[deny(clippy::approx_constant)]` on by default
+ = help: consider using the constant directly
+ = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
```
This error lets you know that Rust already has a more precise `PI` constant
@@ -171,9 +172,9 @@ communicate with each other. Different clients can use `rust-analyzer`, such as
[lsp]: http://langserver.org/
[vscode]: https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer
-Visit the `rust-analyzer` project’s [home page][rust-analyzer] for installation
-instructions, then install the language server support in your particular IDE.
-Your IDE will gain abilities such as autocompletion, jump to definition, and
-inline errors.
+Visit the `rust-analyzer` project’s [home page][rust-analyzer]<!-- ignore -->
+for installation instructions, then install the language server support in your
+particular IDE. Your IDE will gain abilities such as autocompletion, jump to
+definition, and inline errors.
[rust-analyzer]: https://rust-analyzer.github.io
diff --git a/src/doc/book/src/appendix-06-translation.md b/src/doc/book/src/appendix-06-translation.md
index 0bc6aabd9..2c5734354 100644
--- a/src/doc/book/src/appendix-06-translation.md
+++ b/src/doc/book/src/appendix-06-translation.md
@@ -24,7 +24,6 @@ For resources in languages other than English. Most are still in progress; see
- [Svenska](https://github.com/sebras/book)
- [Farsi](https://github.com/pomokhtari/rust-book-fa)
- [Deutsch](https://github.com/rust-lang-de/rustbook-de)
-- [Turkish](https://github.com/RustDili/dokuman/tree/master/ceviriler), [online](https://rustdili.github.io/)
- [हिंदी](https://github.com/venkatarun95/rust-book-hindi)
- [ไทย](https://github.com/rust-lang-th/book-th)
- [Danske](https://github.com/DanKHansen/book-dk)
diff --git a/src/doc/book/src/ch00-00-introduction.md b/src/doc/book/src/ch00-00-introduction.md
index ba7b9ea0e..9df8e6c88 100644
--- a/src/doc/book/src/ch00-00-introduction.md
+++ b/src/doc/book/src/ch00-00-introduction.md
@@ -24,8 +24,8 @@ the most important groups.
Rust is proving to be a productive tool for collaborating among large teams of
developers with varying levels of systems programming knowledge. Low-level code
-is prone to a variety of subtle bugs, which in most other languages can be
-caught only through extensive testing and careful code review by experienced
+is prone to various subtle bugs, which in most other languages can be caught
+only through extensive testing and careful code review by experienced
developers. In Rust, the compiler plays a gatekeeper role by refusing to
compile code with these elusive bugs, including concurrency bugs. By working
alongside the compiler, the team can spend their time focusing on the program’s
@@ -36,7 +36,8 @@ Rust also brings contemporary developer tools to the systems programming world:
* Cargo, the included dependency manager and build tool, makes adding,
compiling, and managing dependencies painless and consistent across the Rust
ecosystem.
-* Rustfmt ensures a consistent coding style across developers.
+* The Rustfmt formatting tool ensures a consistent coding style across
+ developers.
* The Rust Language Server powers Integrated Development Environment (IDE)
integration for code completion and inline error messages.
@@ -55,8 +56,8 @@ programming.
### Companies
Hundreds of companies, large and small, use Rust in production for a variety of
-tasks. Those tasks include command line tools, web services, DevOps tooling,
-embedded devices, audio and video analysis and transcoding, cryptocurrencies,
+tasks, including command line tools, web services, DevOps tooling, embedded
+devices, audio and video analysis and transcoding, cryptocurrencies,
bioinformatics, search engines, Internet of Things applications, machine
learning, and even major parts of the Firefox web browser.
@@ -69,13 +70,13 @@ language.
### People Who Value Speed and Stability
Rust is for people who crave speed and stability in a language. By speed, we
-mean the speed of the programs that you can create with Rust and the speed at
-which Rust lets you write them. The Rust compiler’s checks ensure stability
-through feature additions and refactoring. This is in contrast to the brittle
-legacy code in languages without these checks, which developers are often
-afraid to modify. By striving for zero-cost abstractions, higher-level features
-that compile to lower-level code as fast as code written manually, Rust
-endeavors to make safe code be fast code as well.
+mean both how quickly Rust code can run and the speed at which Rust lets you
+write programs. The Rust compiler’s checks ensure stability through feature
+additions and refactoring. This is in contrast to the brittle legacy code in
+languages without these checks, which developers are often afraid to modify. By
+striving for zero-cost abstractions, higher-level features that compile to
+lower-level code as fast as code written manually, Rust endeavors to make safe
+code be fast code as well.
The Rust language hopes to support many other users as well; those mentioned
here are merely some of the biggest stakeholders. Overall, Rust’s greatest
@@ -96,8 +97,8 @@ reading a book that specifically provides an introduction to programming.
In general, this book assumes that you’re reading it in sequence from front to
back. Later chapters build on concepts in earlier chapters, and earlier
-chapters might not delve into details on a topic; we typically revisit the
-topic in a later chapter.
+chapters might not delve into details on a particular topic but will revisit
+the topic in a later chapter.
You’ll find two kinds of chapters in this book: concept chapters and project
chapters. In concept chapters, you’ll learn about an aspect of Rust. In project
@@ -106,15 +107,15 @@ far. Chapters 2, 12, and 20 are project chapters; the rest are concept chapters.
Chapter 1 explains how to install Rust, how to write a “Hello, world!” program,
and how to use Cargo, Rust’s package manager and build tool. Chapter 2 is a
-hands-on introduction to the Rust language. Here we cover concepts at a high
-level, and later chapters will provide additional detail. If you want to get
-your hands dirty right away, Chapter 2 is the place for that. At first, you
-might even want to skip Chapter 3, which covers Rust features similar to those
-of other programming languages, and head straight to Chapter 4 to learn about
-Rust’s ownership system. However, if you’re a particularly meticulous learner
-who prefers to learn every detail before moving on to the next, you might want
-to skip Chapter 2 and go straight to Chapter 3, returning to Chapter 2 when
-you’d like to work on a project applying the details you’ve learned.
+hands-on introduction to writing a program in Rust, having you build up a
+number guessing game. Here we cover concepts at a high level, and later
+chapters will provide additional detail. If you want to get your hands dirty
+right away, Chapter 2 is the place for that. Chapter 3 covers Rust features
+that are similar to those of other programming languages, and in Chapter 4
+you’ll learn about Rust’s ownership system. If you’re a particularly meticulous
+learner who prefers to learn every detail before moving on to the next, you
+might want to skip Chapter 2 and go straight to Chapter 3, returning to Chapter
+2 when you’d like to work on a project applying the details you’ve learned.
Chapter 5 discusses structs and methods, and Chapter 6 covers enums, `match`
expressions, and the `if let` control flow construct. You’ll use structs and
diff --git a/src/doc/book/src/ch01-01-installation.md b/src/doc/book/src/ch01-01-installation.md
index 47664eb4f..fa9617ad9 100644
--- a/src/doc/book/src/ch01-01-installation.md
+++ b/src/doc/book/src/ch01-01-installation.md
@@ -10,18 +10,18 @@ an internet connection for the download.
The following steps install the latest stable version of the Rust compiler.
Rust’s stability guarantees ensure that all the examples in the book that
compile will continue to compile with newer Rust versions. The output might
-differ slightly between versions, because Rust often improves error messages
-and warnings. In other words, any newer, stable version of Rust you install
-using these steps should work as expected with the content of this book.
+differ slightly between versions because Rust often improves error messages and
+warnings. In other words, any newer, stable version of Rust you install using
+these steps should work as expected with the content of this book.
> ### Command Line Notation
>
> In this chapter and throughout the book, we’ll show some commands used in the
> terminal. Lines that you should enter in a terminal all start with `$`. You
-> don’t need to type in the `$` character; it’s the command line prompt shown
-> to indicate the start of each command. Lines that don’t start with `$`
-> typically show the output of the previous command. Additionally,
-> PowerShell-specific examples will use `>` rather than `$`.
+> don’t need to type the `$` character; it’s the command line prompt shown to
+> indicate the start of each command. Lines that don’t start with `$` typically
+> show the output of the previous command. Additionally, PowerShell-specific
+> examples will use `>` rather than `$`.
### Installing `rustup` on Linux or macOS
@@ -60,13 +60,14 @@ the `build-essential` package.
On Windows, go to [https://www.rust-lang.org/tools/install][install] and follow
the instructions for installing Rust. At some point in the installation, you’ll
receive a message explaining that you’ll also need the MSVC build tools for
-Visual Studio 2013 or later. To acquire the build tools, you’ll need to install
-[Visual Studio 2022][visualstudio]. When asked which workloads to install,
-include:
+Visual Studio 2013 or later.
-- “Desktop Development with C++”
-- The Windows 10 or 11 SDK
-- The English language pack component, along with any other language pack of
+To acquire the build tools, you’ll need to install [Visual Studio
+2022][visualstudio]. When asked which workloads to install, include:
+
+* “Desktop Development with C++”
+* The Windows 10 or 11 SDK
+* The English language pack component, along with any other language pack of
your choosing
The rest of this book uses commands that work in both *cmd.exe* and PowerShell.
@@ -82,15 +83,15 @@ $ rustc --version
```
You should see the version number, commit hash, and commit date for the latest
-stable version that has been released in the following format:
+stable version that has been released, in the following format:
```text
rustc x.y.z (abcabcabc yyyy-mm-dd)
```
If you see this information, you have installed Rust successfully! If you don’t
-see this information, check that Rust is in your `%PATH%`
-system variable as follows.
+see this information, check that Rust is in your `%PATH%` system variable as
+follows.
In Windows CMD, use:
@@ -100,27 +101,24 @@ In Windows CMD, use:
In PowerShell, use:
-```console
+```powershell
> echo $env:Path
```
In Linux and macOS, use:
```console
-echo $PATH
+$ echo $PATH
```
If that’s all correct and Rust still isn’t working, there are a number of
-places you can get help. The easiest is the #beginners channel on [the official
-Rust Discord][discord]. There, you can chat with other Rustaceans (a silly
-nickname we call ourselves) who can help you out. Other great resources include
-[the Users forum][users] and [Stack Overflow][stackoverflow].
+places you can get help. Find out how to get in touch with other Rustaceans (a
+silly nickname we call ourselves) on [the community page][community].
### Updating and Uninstalling
-Once Rust is installed via `rustup`, when a new version of Rust is released,
-updating to the latest version is easy. From your shell, run the following
-update script:
+Once Rust is installed via `rustup`, updating to a newly released version is
+easy. From your shell, run the following update script:
```console
$ rustup update
@@ -135,9 +133,9 @@ $ rustup self uninstall
### Local Documentation
-The installation of Rust also includes a local copy of the documentation, so
-you can read it offline. Run `rustup doc` to open the local documentation in
-your browser.
+The installation of Rust also includes a local copy of the documentation so
+that you can read it offline. Run `rustup doc` to open the local documentation
+in your browser.
Any time a type or function is provided by the standard library and you’re not
sure what it does or how to use it, use the application programming interface
@@ -146,6 +144,4 @@ sure what it does or how to use it, use the application programming interface
[otherinstall]: https://forge.rust-lang.org/infra/other-installation-methods.html
[install]: https://www.rust-lang.org/tools/install
[visualstudio]: https://visualstudio.microsoft.com/downloads/
-[discord]: https://discord.gg/rust-lang
-[users]: https://users.rust-lang.org/
-[stackoverflow]: https://stackoverflow.com/questions/tagged/rust
+[community]: https://www.rust-lang.org/community
diff --git a/src/doc/book/src/ch01-02-hello-world.md b/src/doc/book/src/ch01-02-hello-world.md
index ce9b8f55b..8d8d754d7 100644
--- a/src/doc/book/src/ch01-02-hello-world.md
+++ b/src/doc/book/src/ch01-02-hello-world.md
@@ -1,8 +1,8 @@
## Hello, World!
-Now that you’ve installed Rust, let’s write your first Rust program. It’s
-traditional when learning a new language to write a little program that prints
-the text `Hello, world!` to the screen, so we’ll do the same here!
+Now that you’ve installed Rust, it’s time to write your first Rust program.
+It’s traditional when learning a new language to write a little program that
+prints the text `Hello, world!` to the screen, so we’ll do the same here!
> Note: This book assumes basic familiarity with the command line. Rust makes
> no specific demands about your editing or tooling or where your code lives, so
@@ -10,7 +10,7 @@ the text `Hello, world!` to the screen, so we’ll do the same here!
> the command line, feel free to use your favorite IDE. Many IDEs now have some
> degree of Rust support; check the IDE’s documentation for details. The Rust
> team has been focusing on enabling great IDE support via `rust-analyzer`. See
-> [Appendix D][devtools]<!-- ignore --> for more details!
+> [Appendix D][devtools]<!-- ignore --> for more details.
### Creating a Project Directory
@@ -109,7 +109,7 @@ line as the function declaration, adding one space in between.
> use an automatic formatter tool called `rustfmt` to format your code in a
> particular style (more on `rustfmt` in
> [Appendix D][devtools]<!-- ignore -->). The Rust team has included this tool
-> with the standard Rust distribution, like `rustc`, so it should already be
+> with the standard Rust distribution, as `rustc` is, so it should already be
> installed on your computer!
The body of the `main` function holds the following code:
@@ -126,7 +126,7 @@ First, Rust style is to indent with four spaces, not a tab.
Second, `println!` calls a Rust macro. If it had called a function instead, it
would be entered as `println` (without the `!`). We’ll discuss Rust macros in
more detail in Chapter 19. For now, you just need to know that using a `!`
-means that you’re calling a macro instead of a normal function, and that macros
+means that you’re calling a macro instead of a normal function and that macros
don’t always follow the same rules as functions.
Third, you see the `"Hello, world!"` string. We pass this string as an argument
@@ -153,16 +153,16 @@ If you have a C or C++ background, you’ll notice that this is similar to `gcc`
or `clang`. After compiling successfully, Rust outputs a binary executable.
On Linux, macOS, and PowerShell on Windows, you can see the executable by
-entering the `ls` command in your shell. On Linux and macOS, you’ll see two
-files. With PowerShell on Windows, you’ll see the same three files that you
-would see using CMD.
+entering the `ls` command in your shell:
```console
$ ls
main main.rs
```
-With CMD on Windows, you would enter the following:
+On Linux and macOS, you’ll see two files. With PowerShell on Windows, you’ll
+see the same three files that you would see using CMD. With CMD on Windows, you
+would enter the following:
```cmd
> dir /B %= the /B option says to only show the file names =%
diff --git a/src/doc/book/src/ch01-03-hello-cargo.md b/src/doc/book/src/ch01-03-hello-cargo.md
index 9979e76dd..42cd0889c 100644
--- a/src/doc/book/src/ch01-03-hello-cargo.md
+++ b/src/doc/book/src/ch01-03-hello-cargo.md
@@ -17,7 +17,7 @@ assumes that you’re using Cargo too. Cargo comes installed with Rust if you
used the official installers discussed in the
[“Installation”][installation]<!-- ignore --> section. If you installed Rust
through some other means, check whether Cargo is installed by entering the
-following into your terminal:
+following in your terminal:
```console
$ cargo --version
@@ -30,9 +30,9 @@ determine how to install Cargo separately.
### Creating a Project with Cargo
Let’s create a new project using Cargo and look at how it differs from our
-original “Hello, world!” project. Navigate back to your *projects* directory (or
-wherever you decided to store your code). Then, on any operating system, run
-the following:
+original “Hello, world!” project. Navigate back to your *projects* directory
+(or wherever you decided to store your code). Then, on any operating system,
+run the following:
```console
$ cargo new hello_cargo
@@ -74,8 +74,8 @@ edition = "2021"
<span class="caption">Listing 1-2: Contents of *Cargo.toml* generated by `cargo
new`</span>
-This file is in the [*TOML*](https://toml.io)<!-- ignore --> (*Tom’s Obvious,
-Minimal Language*) format, which is Cargo’s configuration format.
+This file is in the [*TOML*][toml]<!-- ignore --> (*Tom’s Obvious, Minimal
+Language*) format, which is Cargo’s configuration format.
The first line, `[package]`, is a section heading that indicates that the
following statements are configuring a package. As we add more information to
@@ -102,7 +102,7 @@ fn main() {
Cargo has generated a “Hello, world!” program for you, just like the one we
wrote in Listing 1-1! So far, the differences between our project and the
-project Cargo generated are that Cargo placed the code in the *src* directory,
+project Cargo generated are that Cargo placed the code in the *src* directory
and we have a *Cargo.toml* configuration file in the top directory.
Cargo expects your source files to live inside the *src* directory. The
@@ -147,7 +147,7 @@ manages its contents for you.
We just built a project with `cargo build` and ran it with
`./target/debug/hello_cargo`, but we can also use `cargo run` to compile the
-code and then run the resulting executable all in one command:
+code and then run the resultant executable all in one command:
```console
$ cargo run
@@ -184,7 +184,7 @@ $ cargo check
```
Why would you not want an executable? Often, `cargo check` is much faster than
-`cargo build`, because it skips the step of producing an executable. If you’re
+`cargo build` because it skips the step of producing an executable. If you’re
continually checking your work while writing the code, using `cargo check` will
speed up the process of letting you know if your project is still compiling! As
such, many Rustaceans run `cargo check` periodically as they write their
@@ -236,9 +236,7 @@ $ cd someproject
$ cargo build
```
-For more information about Cargo, check out [its documentation].
-
-[its documentation]: https://doc.rust-lang.org/cargo/
+For more information about Cargo, check out [its documentation][cargo].
## Summary
@@ -257,4 +255,6 @@ If you would rather start by learning how common programming concepts work in
Rust, see Chapter 3 and then return to Chapter 2.
[installation]: ch01-01-installation.html#installation
+[toml]: https://toml.io
[appendix-e]: appendix-05-editions.html
+[cargo]: https://doc.rust-lang.org/cargo/
diff --git a/src/doc/book/src/ch02-00-guessing-game-tutorial.md b/src/doc/book/src/ch02-00-guessing-game-tutorial.md
index bffbc0501..4dac23764 100644
--- a/src/doc/book/src/ch02-00-guessing-game-tutorial.md
+++ b/src/doc/book/src/ch02-00-guessing-game-tutorial.md
@@ -3,8 +3,8 @@
Let’s jump into Rust by working through a hands-on project together! This
chapter introduces you to a few common Rust concepts by showing you how to use
them in a real program. You’ll learn about `let`, `match`, methods, associated
-functions, using external crates, and more! In the following chapters, we’ll
-explore these ideas in more detail. In this chapter, you’ll practice the
+functions, external crates, and more! In the following chapters, we’ll explore
+these ideas in more detail. In this chapter, you’ll just practice the
fundamentals.
We’ll implement a classic beginner programming problem: a guessing game. Here’s
@@ -34,7 +34,8 @@ cd listings/ch02-guessing-game-tutorial
rm -rf no-listing-01-cargo-new
cargo new no-listing-01-cargo-new --name guessing_game
cd no-listing-01-cargo-new
-cargo run
+cargo run > output.txt 2>&1
+cd ../../..
-->
<span class="filename">Filename: Cargo.toml</span>
@@ -83,16 +84,16 @@ prints it</span>
This code contains a lot of information, so let’s go over it line by line. To
obtain user input and then print the result as output, we need to bring the
-`io` input/output library into scope. The `io` library comes from the
-standard library, known as `std`:
+`io` input/output library into scope. The `io` library comes from the standard
+library, known as `std`:
```rust,ignore
{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}}
```
-By default, Rust has a set of items defined in the standard library that it brings
-into the scope of every program. This set is called the *prelude*, and you can
-see everything in it [in the standard library documentation][prelude].
+By default, Rust has a set of items defined in the standard library that it
+brings into the scope of every program. This set is called the *prelude*, and
+you can see everything in it [in the standard library documentation][prelude].
If a type you want to use isn’t in the prelude, you have to bring that type
into scope explicitly with a `use` statement. Using the `std::io` library
@@ -106,8 +107,8 @@ program:
{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:main}}
```
-The `fn` syntax declares a new function, the parentheses, `()`, indicate there
-are no parameters, and the curly bracket, `{`, starts the body of the function.
+The `fn` syntax declares a new function; the parentheses, `()`, indicate there
+are no parameters; and the curly bracket, `{`, starts the body of the function.
As you also learned in Chapter 1, `println!` is a macro that prints a string to
the screen:
@@ -136,7 +137,7 @@ let apples = 5;
This line creates a new variable named `apples` and binds it to the value 5. In
Rust, variables are immutable by default, meaning once we give the variable a
-value, the value won't change. We’ll be discussing this concept in detail in
+value, the value won’t change. We’ll be discussing this concept in detail in
the [“Variables and Mutability”][variables-and-mutability]<!-- ignore -->
section in Chapter 3. To make a variable mutable, we add `mut` before the
variable name:
@@ -152,7 +153,7 @@ let mut bananas = 5; // mutable
Returning to the guessing game program, you now know that `let mut guess` will
introduce a mutable variable named `guess`. The equal sign (`=`) tells Rust we
-want to bind something to the variable now. On the right of the equals sign is
+want to bind something to the variable now. On the right of the equal sign is
the value that `guess` is bound to, which is the result of calling
`String::new`, a function that returns a new instance of a `String`.
[`String`][string]<!-- ignore --> is a string type provided by the standard
@@ -161,7 +162,7 @@ library that is a growable, UTF-8 encoded bit of text.
The `::` syntax in the `::new` line indicates that `new` is an associated
function of the `String` type. An *associated function* is a function that’s
implemented on a type, in this case `String`. This `new` function creates a
-new, empty string. You’ll find a `new` function on many types, because it’s a
+new, empty string. You’ll find a `new` function on many types because it’s a
common name for a function that makes a new value of some kind.
In full, the `let mut guess = String::new();` line has created a mutable
@@ -178,7 +179,7 @@ input:
{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}}
```
-If we hadn’t imported the `io` library with `use std::io` at the beginning of
+If we hadn’t imported the `io` library with `use std::io;` at the beginning of
the program, we could still use the function by writing this function call as
`std::io::stdin`. The `stdin` function returns an instance of
[`std::io::Stdin`][iostdin]<!-- ignore -->, which is a type that represents a
@@ -198,12 +199,15 @@ let multiple parts of your code access one piece of data without needing to
copy that data into memory multiple times. References are a complex feature,
and one of Rust’s major advantages is how safe and easy it is to use
references. You don’t need to know a lot of those details to finish this
-program. For now, all you need to know is that like variables, references are
+program. For now, all you need to know is that, like variables, references are
immutable by default. Hence, you need to write `&mut guess` rather than
`&guess` to make it mutable. (Chapter 4 will explain references more
thoroughly.)
-### Handling Potential Failure with the `Result` Type
+<!-- Old heading. Do not remove or links may break. -->
+<a id="handling-potential-failure-with-the-result-type"></a>
+
+### Handling Potential Failure with `Result`
We’re still working on this line of code. We’re now discussing a third line of
text, but note that it’s still part of a single logical line of code. The next
@@ -230,10 +234,10 @@ ignore --> is an [*enumeration*][enums]<!-- ignore -->, often called an *enum*,
which is a type that can be in one of multiple possible states. We call each
possible state a *variant*.
-Chapter 6 will cover enums in more detail. The purpose of these `Result` types
-is to encode error-handling information.
+[Chapter 6][enums]<!-- ignore --> will cover enums in more detail. The purpose
+of these `Result` types is to encode error-handling information.
-`Result`'s variants are `Ok` and `Err`. The `Ok` variant indicates the
+`Result`’s variants are `Ok` and `Err`. The `Ok` variant indicates the
operation was successful, and inside `Ok` is the successfully generated value.
The `Err` variant means the operation failed, and `Err` contains information
about how or why the operation failed.
@@ -257,9 +261,9 @@ If you don’t call `expect`, the program will compile, but you’ll get a warni
Rust warns that you haven’t used the `Result` value returned from `read_line`,
indicating that the program hasn’t handled a possible error.
-The right way to suppress the warning is to actually write error handling, but
-in our case we just want to crash this program when a problem occurs, so we can
-use `expect`. You’ll learn about recovering from errors in [Chapter
+The right way to suppress the warning is to actually write error-handling code,
+but in our case we just want to crash this program when a problem occurs, so we
+can use `expect`. You’ll learn about recovering from errors in [Chapter
9][recover]<!-- ignore -->.
### Printing Values with `println!` Placeholders
@@ -273,19 +277,21 @@ the code so far:
This line prints the string that now contains the user’s input. The `{}` set of
curly brackets is a placeholder: think of `{}` as little crab pincers that hold
-a value in place. You can print more than one value using curly brackets: the
-first set of curly brackets holds the first value listed after the format
-string, the second set holds the second value, and so on. Printing multiple
-values in one call to `println!` would look like this:
+a value in place. When printing the value of a variable, the variable name can
+go inside the curly brackets. When printing the result of evaluating an
+expression, place empty curly brackets in the format string, then follow the
+format string with a comma-separated list of expressions to print in each empty
+curly bracket placeholder in the same order. Printing a variable and the result
+of an expression in one call to `println!` would look like this:
```rust
let x = 5;
let y = 10;
-println!("x = {} and y = {}", x, y);
+println!("x = {x} and y + 2 = {}", y + 2);
```
-This code would print `x = 5 and y = 10`.
+This code would print `x = 5 and y = 12`.
### Testing the First Part
@@ -324,15 +330,15 @@ said functionality.
Remember that a crate is a collection of Rust source code files. The project
we’ve been building is a *binary crate*, which is an executable. The `rand`
-crate is a *library crate*, which contains code intended to be used in other
-programs and can't be executed on its own.
+crate is a *library crate*, which contains code that is intended to be used in
+other programs and can’t be executed on its own.
Cargo’s coordination of external crates is where Cargo really shines. Before we
can write code that uses `rand`, we need to modify the *Cargo.toml* file to
include the `rand` crate as a dependency. Open that file now and add the
-following line to the bottom beneath the `[dependencies]` section header that
+following line to the bottom, beneath the `[dependencies]` section header that
Cargo created for you. Be sure to specify `rand` exactly as we have here, with
-this version number, or the code examples in this tutorial may not work.
+this version number, or the code examples in this tutorial may not work:
<!-- When updating the version of `rand` used, also update the version of
`rand` used in these files so they all match:
@@ -343,50 +349,50 @@ this version number, or the code examples in this tutorial may not work.
<span class="filename">Filename: Cargo.toml</span>
```toml
-{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}}
+{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:8:}}
```
In the *Cargo.toml* file, everything that follows a header is part of that
section that continues until another section starts. In `[dependencies]` you
tell Cargo which external crates your project depends on and which versions of
those crates you require. In this case, we specify the `rand` crate with the
-semantic version specifier `0.8.3`. Cargo understands [Semantic
+semantic version specifier `0.8.5`. Cargo understands [Semantic
Versioning][semver]<!-- ignore --> (sometimes called *SemVer*), which is a
-standard for writing version numbers. The number `0.8.3` is actually shorthand
-for `^0.8.3`, which means any version that is at least `0.8.3` but below
-`0.9.0`.
+standard for writing version numbers. The specifier `0.8.5` is actually
+shorthand for `^0.8.5`, which means any version that is at least 0.8.5 but
+below 0.9.0.
Cargo considers these versions to have public APIs compatible with version
-`0.8.3`, and this specification ensures you’ll get the latest patch release
-that will still compile with the code in this chapter. Any version `0.9.0` or
-greater is not guaranteed to have the same API as what the following examples
-use.
+0.8.5, and this specification ensures you’ll get the latest patch release that
+will still compile with the code in this chapter. Any version 0.9.0 or greater
+is not guaranteed to have the same API as what the following examples use.
Now, without changing any of the code, let’s build the project, as shown in
Listing 2-2.
<!-- manual-regeneration
cd listings/ch02-guessing-game-tutorial/listing-02-02/
+rm Cargo.lock
cargo clean
cargo build -->
```console
$ cargo build
Updating crates.io index
- Downloaded rand v0.8.3
- Downloaded libc v0.2.86
- Downloaded getrandom v0.2.2
+ Downloaded rand v0.8.5
+ Downloaded libc v0.2.127
+ Downloaded getrandom v0.2.7
Downloaded cfg-if v1.0.0
- Downloaded ppv-lite86 v0.2.10
- Downloaded rand_chacha v0.3.0
- Downloaded rand_core v0.6.2
- Compiling rand_core v0.6.2
- Compiling libc v0.2.86
- Compiling getrandom v0.2.2
+ Downloaded ppv-lite86 v0.2.16
+ Downloaded rand_chacha v0.3.1
+ Downloaded rand_core v0.6.3
+ Compiling libc v0.2.127
+ Compiling getrandom v0.2.7
Compiling cfg-if v1.0.0
- Compiling ppv-lite86 v0.2.10
- Compiling rand_chacha v0.3.0
- Compiling rand v0.8.3
+ Compiling ppv-lite86 v0.2.16
+ Compiling rand_core v0.6.3
+ Compiling rand_chacha v0.3.1
+ Compiling rand v0.8.5
Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 2.53s
```
@@ -395,8 +401,8 @@ $ cargo build
adding the rand crate as a dependency</span>
You may see different version numbers (but they will all be compatible with the
-code, thanks to SemVer!), different lines (depending on the operating system),
-and the lines may be in a different order.
+code, thanks to SemVer!) and different lines (depending on the operating
+system), and the lines may be in a different order.
When we include an external dependency, Cargo fetches the latest versions of
everything that dependency needs from the *registry*, which is a copy of data
@@ -416,8 +422,8 @@ about them in your *Cargo.toml* file. Cargo also knows that you haven’t change
anything about your code, so it doesn’t recompile that either. With nothing to
do, it simply exits.
-If you open up the *src/main.rs* file, make a trivial change, and then save it
-and build again, you’ll only see two lines of output:
+If you open the *src/main.rs* file, make a trivial change, and then save it and
+build again, you’ll only see two lines of output:
<!-- manual-regeneration
cd listings/ch02-guessing-game-tutorial/listing-02-02/
@@ -430,7 +436,7 @@ $ cargo build
Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
```
-These lines show Cargo only updates the build with your tiny change to the
+These lines show that Cargo only updates the build with your tiny change to the
*src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can
reuse what it has already downloaded and compiled for those.
@@ -439,21 +445,21 @@ reuse what it has already downloaded and compiled for those.
Cargo has a mechanism that ensures you can rebuild the same artifact every time
you or anyone else builds your code: Cargo will use only the versions of the
dependencies you specified until you indicate otherwise. For example, say that
-next week version 0.8.4 of the `rand` crate comes out, and that version
+next week version 0.8.6 of the `rand` crate comes out, and that version
contains an important bug fix, but it also contains a regression that will
break your code. To handle this, Rust creates the *Cargo.lock* file the first
time you run `cargo build`, so we now have this in the *guessing_game*
directory.
-When you build a project for the first time, Cargo figures out all the
-versions of the dependencies that fit the criteria and then writes them to
-the *Cargo.lock* file. When you build your project in the future, Cargo will
-see that the *Cargo.lock* file exists and use the versions specified there
+When you build a project for the first time, Cargo figures out all the versions
+of the dependencies that fit the criteria and then writes them to the
+*Cargo.lock* file. When you build your project in the future, Cargo will see
+that the *Cargo.lock* file exists and will use the versions specified there
rather than doing all the work of figuring out versions again. This lets you
have a reproducible build automatically. In other words, your project will
-remain at `0.8.3` until you explicitly upgrade, thanks to the *Cargo.lock*
-file. Because the *Cargo.lock* file is important for reproducible builds, it's
-often checked into source control with the rest of the code in your project.
+remain at 0.8.5 until you explicitly upgrade, thanks to the *Cargo.lock* file.
+Because the *Cargo.lock* file is important for reproducible builds, it’s often
+checked into source control with the rest of the code in your project.
#### Updating a Crate to Get a New Version
@@ -461,9 +467,9 @@ When you *do* want to update a crate, Cargo provides the command `update`,
which will ignore the *Cargo.lock* file and figure out all the latest versions
that fit your specifications in *Cargo.toml*. Cargo will then write those
versions to the *Cargo.lock* file. Otherwise, by default, Cargo will only look
-for versions greater than `0.8.3` and less than `0.9.0`. If the `rand` crate
-has released the two new versions `0.8.4` and `0.9.0` you would see the
-following if you ran `cargo update`:
+for versions greater than 0.8.5 and less than 0.9.0. If the `rand` crate has
+released the two new versions 0.8.6 and 0.9.0, you would see the following if
+you ran `cargo update`:
<!-- manual-regeneration
cd listings/ch02-guessing-game-tutorial/listing-02-02/
@@ -474,14 +480,13 @@ as a guide to creating the hypothetical output shown here -->
```console
$ cargo update
Updating crates.io index
- Updating rand v0.8.3 -> v0.8.4
+ Updating rand v0.8.5 -> v0.8.6
```
-Cargo ignores the `0.9.0` release. At this point, you would also notice a
-change in your *Cargo.lock* file noting that the version of the `rand` crate
-you are now using is `0.8.4`. To use `rand` version `0.9.0` or any version in
-the `0.9.x` series, you’d have to update the *Cargo.toml* file to look like
-this instead:
+Cargo ignores the 0.9.0 release. At this point, you would also notice a change
+in your *Cargo.lock* file noting that the version of the `rand` crate you are
+now using is 0.8.6. To use `rand` version 0.9.0 or any version in the 0.9.*x*
+series, you’d have to update the *Cargo.toml* file to look like this instead:
```toml
[dependencies]
@@ -493,7 +498,7 @@ available and reevaluate your `rand` requirements according to the new version
you have specified.
There’s a lot more to say about [Cargo][doccargo]<!-- ignore --> and [its
-ecosystem][doccratesio]<!-- ignore --> which we’ll discuss in Chapter 14, but
+ecosystem][doccratesio]<!-- ignore -->, which we’ll discuss in Chapter 14, but
for now, that’s all you need to know. Cargo makes it very easy to reuse
libraries, so Rustaceans are able to write smaller projects that are assembled
from a number of packages.
@@ -512,16 +517,16 @@ update *src/main.rs*, as shown in Listing 2-3.
<span class="caption">Listing 2-3: Adding code to generate a random
number</span>
-First, we add the line `use rand::Rng`. The `Rng` trait defines methods that
+First we add the line `use rand::Rng;`. The `Rng` trait defines methods that
random number generators implement, and this trait must be in scope for us to
use those methods. Chapter 10 will cover traits in detail.
Next, we’re adding two lines in the middle. In the first line, we call the
`rand::thread_rng` function that gives us the particular random number
-generator that we’re going to use: one that is local to the current thread of
-execution and seeded by the operating system. Then we call the `gen_range`
+generator we’re going to use: one that is local to the current thread of
+execution and is seeded by the operating system. Then we call the `gen_range`
method on the random number generator. This method is defined by the `Rng`
-trait that we brought into scope with the `use rand::Rng` statement. The
+trait that we brought into scope with the `use rand::Rng;` statement. The
`gen_range` method takes a range expression as an argument and generates a
random number in the range. The kind of range expression we’re using here takes
the form `start..=end` and is inclusive on the lower and upper bounds, so we
@@ -530,7 +535,7 @@ need to specify `1..=100` to request a number between 1 and 100.
> Note: You won’t just know which traits to use and which methods and functions
> to call from a crate, so each crate has documentation with instructions for
> using it. Another neat feature of Cargo is that running the `cargo doc
-> --open` command will build documentation provided by all of your dependencies
+> --open` command will build documentation provided by all your dependencies
> locally and open it in your browser. If you’re interested in other
> functionality in the `rand` crate, for example, run `cargo doc --open` and
> click `rand` in the sidebar on the left.
@@ -577,8 +582,8 @@ You should get different random numbers, and they should all be numbers between
## Comparing the Guess to the Secret Number
Now that we have user input and a random number, we can compare them. That step
-is shown in Listing 2-4. Note that this code won’t compile quite yet, as we
-will explain.
+is shown in Listing 2-4. Note that this code won’t compile just yet, as we will
+explain.
<span class="filename">Filename: src/main.rs</span>
@@ -597,7 +602,7 @@ the three outcomes that are possible when you compare two values.
Then we add five new lines at the bottom that use the `Ordering` type. The
`cmp` method compares two values and can be called on anything that can be
compared. It takes a reference to whatever you want to compare with: here it’s
-comparing the `guess` to the `secret_number`. Then it returns a variant of the
+comparing `guess` to `secret_number`. Then it returns a variant of the
`Ordering` enum we brought into scope with the `use` statement. We use a
[`match`][match]<!-- ignore --> expression to decide what to do next based on
which variant of `Ordering` was returned from the call to `cmp` with the values
@@ -607,14 +612,16 @@ A `match` expression is made up of *arms*. An arm consists of a *pattern* to
match against, and the code that should be run if the value given to `match`
fits that arm’s pattern. Rust takes the value given to `match` and looks
through each arm’s pattern in turn. Patterns and the `match` construct are
-powerful Rust features that let you express a variety of situations your code
-might encounter and make sure that you handle them all. These features will be
+powerful Rust features: they let you express a variety of situations your code
+might encounter and they make sure you handle them all. These features will be
covered in detail in Chapter 6 and Chapter 18, respectively.
Let’s walk through an example with the `match` expression we use here. Say that
the user has guessed 50 and the randomly generated secret number this time is
-38. When the code compares 50 to 38, the `cmp` method will return
-`Ordering::Greater`, because 50 is greater than 38. The `match` expression gets
+38.
+
+When the code compares 50 to 38, the `cmp` method will return
+`Ordering::Greater` because 50 is greater than 38. The `match` expression gets
the `Ordering::Greater` value and starts checking each arm’s pattern. It looks
at the first arm’s pattern, `Ordering::Less`, and sees that the value
`Ordering::Greater` does not match `Ordering::Less`, so it ignores the code in
@@ -626,6 +633,11 @@ arm in this scenario.
However, the code in Listing 2-4 won’t compile yet. Let’s try it:
+<!--
+The error numbers in this output should be that of the code **WITHOUT** the
+anchor or snip comments
+-->
+
```console
{{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}}
```
@@ -642,8 +654,8 @@ elsewhere that would cause Rust to infer a different numerical type. The reason
for the error is that Rust cannot compare a string and a number type.
Ultimately, we want to convert the `String` the program reads as input into a
-real number type so we can compare it numerically to the secret number. We do so
-by adding this line to the `main` function body:
+real number type so we can compare it numerically to the secret number. We do
+so by adding this line to the `main` function body:
<span class="filename">Filename: src/main.rs</span>
@@ -658,12 +670,12 @@ let guess: u32 = guess.trim().parse().expect("Please type a number!");
```
We create a variable named `guess`. But wait, doesn’t the program already have
-a variable named `guess`? It does, but helpfully Rust allows us to *shadow* the
-previous value of `guess` with a new one. Shadowing lets us reuse the `guess`
+a variable named `guess`? It does, but helpfully Rust allows us to shadow the
+previous value of `guess` with a new one. *Shadowing* lets us reuse the `guess`
variable name rather than forcing us to create two unique variables, such as
-`guess_str` and `guess` for example. We’ll cover this in more detail in Chapter
-3, but for now know that this feature is often used when you want to convert a
-value from one type to another type.
+`guess_str` and `guess`, for example. We’ll cover this in more detail in
+[Chapter 3][shadowing]<!-- ignore -->, but for now, know that this feature is
+often used when you want to convert a value from one type to another type.
We bind this new variable to the expression `guess.trim().parse()`. The `guess`
in the expression refers to the original `guess` variable that contained the
@@ -674,9 +686,9 @@ string to the `u32`, which can only contain numerical data. The user must press
guess, which adds a newline character to the string. For example, if the user
types <span class="keystroke">5</span> and presses <span
class="keystroke">enter</span>, `guess` looks like this: `5\n`. The `\n`
-represents “newline”. (On Windows, pressing <span
+represents “newline.” (On Windows, pressing <span
class="keystroke">enter</span> results in a carriage return and a newline,
-`\r\n`). The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`.
+`\r\n`.) The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`.
The [`parse` method on strings][parse]<!-- ignore --> converts a string to
another type. Here, we use it to convert from a string to a number. We need to
@@ -684,25 +696,27 @@ tell Rust the exact number type we want by using `let guess: u32`. The colon
(`:`) after `guess` tells Rust we’ll annotate the variable’s type. Rust has a
few built-in number types; the `u32` seen here is an unsigned, 32-bit integer.
It’s a good default choice for a small positive number. You’ll learn about
-other number types in Chapter 3. Additionally, the `u32` annotation in this
-example program and the comparison with `secret_number` means that Rust will
-infer that `secret_number` should be a `u32` as well. So now the comparison
-will be between two values of the same type!
+other number types in [Chapter 3][integers]<!-- ignore -->.
+
+Additionally, the `u32` annotation in this example program and the comparison
+with `secret_number` means Rust will infer that `secret_number` should be a
+`u32` as well. So now the comparison will be between two values of the same
+type!
The `parse` method will only work on characters that can logically be converted
into numbers and so can easily cause errors. If, for example, the string
contained `A👍%`, there would be no way to convert that to a number. Because it
might fail, the `parse` method returns a `Result` type, much as the `read_line`
-method does (discussed earlier in [“Handling Potential Failure with the
-`Result` Type”](#handling-potential-failure-with-the-result-type)<!-- ignore
--->). We’ll treat this `Result` the same way by using the `expect` method
-again. If `parse` returns an `Err` `Result` variant because it couldn’t create
-a number from the string, the `expect` call will crash the game and print the
-message we give it. If `parse` can successfully convert the string to a number,
-it will return the `Ok` variant of `Result`, and `expect` will return the
-number that we want from the `Ok` value.
+method does (discussed earlier in [“Handling Potential Failure with
+`Result`”](#handling-potential-failure-with-result)<!-- ignore-->). We’ll treat
+this `Result` the same way by using the `expect` method again. If `parse`
+returns an `Err` `Result` variant because it couldn’t create a number from the
+string, the `expect` call will crash the game and print the message we give it.
+If `parse` can successfully convert the string to a number, it will return the
+`Ok` variant of `Result`, and `expect` will return the number that we want from
+the `Ok` value.
-Let’s run the program now!
+Let’s run the program now:
<!-- manual-regeneration
cd listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/
@@ -788,8 +802,8 @@ thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidD
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
-Typing `quit` will quit the game, but as you’ll notice so will entering any
-other non-number input. This is suboptimal to say the least; we want the game
+Typing `quit` will quit the game, but as you’ll notice, so will entering any
+other non-number input. This is suboptimal, to say the least; we want the game
to also stop when the correct number is guessed.
### Quitting After a Correct Guess
@@ -829,7 +843,7 @@ a `match` expression here, as we did with the `Ordering` result of the `cmp`
method.
If `parse` is able to successfully turn the string into a number, it will
-return an `Ok` value that contains the resulting number. That `Ok` value will
+return an `Ok` value that contains the resultant number. That `Ok` value will
match the first arm’s pattern, and the `match` expression will just return the
`num` value that `parse` produced and put inside the `Ok` value. That number
will end up right where we want it in the new `guess` variable we’re creating.
@@ -891,10 +905,10 @@ secret number. Listing 2-6 shows the final code.
<span class="caption">Listing 2-6: Complete guessing game code</span>
-## Summary
-
At this point, you’ve successfully built the guessing game. Congratulations!
+## Summary
+
This project was a hands-on way to introduce you to many new Rust concepts:
`let`, `match`, functions, the use of external crates, and more. In the next
few chapters, you’ll learn about these concepts in more detail. Chapter 3
@@ -919,4 +933,6 @@ discusses structs and method syntax, and Chapter 6 explains how enums work.
[doccargo]: http://doc.crates.io
[doccratesio]: http://doc.crates.io/crates-io.html
[match]: ch06-02-match.html
+[shadowing]: ch03-01-variables-and-mutability.html#shadowing
[parse]: ../std/primitive.str.html#method.parse
+[integers]: ch03-02-data-types.html#integer-types
diff --git a/src/doc/book/src/ch03-00-common-programming-concepts.md b/src/doc/book/src/ch03-00-common-programming-concepts.md
index 8495543f3..2e37fad02 100644
--- a/src/doc/book/src/ch03-00-common-programming-concepts.md
+++ b/src/doc/book/src/ch03-00-common-programming-concepts.md
@@ -12,9 +12,9 @@ them early will give you a strong core to start from.
> #### Keywords
>
-> The Rust language has a set of *keywords* that are reserved for use by
-> the language only, much as in other languages. Keep in mind that you cannot
-> use these words as names of variables or functions. Most of the keywords have
+> The Rust language has a set of *keywords* that are reserved for use by the
+> language only, much as in other languages. Keep in mind that you cannot use
+> these words as names of variables or functions. Most of the keywords have
> special meanings, and you’ll be using them to do various tasks in your Rust
> programs; a few have no current functionality associated with them but have
> been reserved for functionality that might be added to Rust in the future. You
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 ac583f1b2..883a53050 100644
--- a/src/doc/book/src/ch03-01-variables-and-mutability.md
+++ b/src/doc/book/src/ch03-01-variables-and-mutability.md
@@ -1,7 +1,7 @@
## Variables and Mutability
As mentioned in the [“Storing Values with
-Variables”][storing-values-with-variables]<!-- ignore --> section, by default
+Variables”][storing-values-with-variables]<!-- ignore --> section, by default,
variables are immutable. This is one of many nudges Rust gives you to write
your code in a way that takes advantage of the safety and easy concurrency that
Rust offers. However, you still have the option to make your variables mutable.
@@ -9,12 +9,11 @@ Let’s explore how and why Rust encourages you to favor immutability and why
sometimes you might want to opt out.
When a variable is immutable, once a value is bound to a name, you can’t change
-that value. To illustrate this, let’s generate a new project called *variables*
-in your *projects* directory by using `cargo new variables`.
+that value. To illustrate this, generate a new project called *variables* in
+your *projects* directory by using `cargo new variables`.
Then, in your new *variables* directory, open *src/main.rs* and replace its
-code with the following code. This code won’t compile just yet, we’ll first
-examine the immutability error.
+code with the following code, which won’t compile just yet:
<span class="filename">Filename: src/main.rs</span>
@@ -22,8 +21,8 @@ examine the immutability error.
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/src/main.rs}}
```
-Save and run the program using `cargo run`. You should receive an error
-message, as shown in this output:
+Save and run the program using `cargo run`. You should receive an error message
+regarding an immutability error, as shown in this output:
```console
{{#include ../listings/ch03-common-programming-concepts/no-listing-01-variables-are-immutable/output.txt}}
@@ -34,9 +33,8 @@ Compiler errors can be frustrating, but really they only mean your program
isn’t safely doing what you want it to do yet; they do *not* mean that you’re
not a good programmer! Experienced Rustaceans still get compiler errors.
-The error message indicates that the cause of the error is that you `` cannot
-assign twice to immutable variable `x` ``, because you tried to assign a second
-value to the immutable `x` variable.
+You received the error message `` cannot assign twice to immutable variable `x`
+`` because you tried to assign a second value to the immutable `x` variable.
It’s important that we get compile-time errors when we attempt to change a
value that’s designated as immutable because this very situation can lead to
@@ -45,15 +43,16 @@ never change and another part of our code changes that value, it’s possible
that the first part of the code won’t do what it was designed to do. The cause
of this kind of bug can be difficult to track down after the fact, especially
when the second piece of code changes the value only *sometimes*. The Rust
-compiler guarantees that when you state a value won’t change, it really won’t
-change, so you don’t have to keep track of it yourself. Your code is thus
+compiler guarantees that when you state that a value won’t change, it really
+won’t change, so you don’t have to keep track of it yourself. Your code is thus
easier to reason through.
-But mutability can be very useful, and can make code more convenient to write.
-Although variables are immutable by default, you can make them mutable by adding
-`mut` in front of the variable name as you did in Chapter 2. Adding `mut` also
-conveys intent to future readers of the code by indicating that other parts of
-the code will be changing this variable’s value.
+But mutability can be very useful, and can make code more convenient to write.
+Although variables are immutable by default, you can make them mutable by
+adding `mut` in front of the variable name as you did in [Chapter
+2][storing-values-with-variables]<!-- ignore -->. Adding `mut` also conveys
+intent to future readers of the code by indicating that other parts of the code
+will be changing this variable’s value.
For example, let’s change *src/main.rs* to the following:
@@ -69,8 +68,8 @@ When we run the program now, we get this:
{{#include ../listings/ch03-common-programming-concepts/no-listing-02-adding-mut/output.txt}}
```
-We’re allowed to change the value bound to `x` from `5` to `6` when `mut`
-is used. Ultimately, deciding whether to use mutability or not is up to you and
+We’re allowed to change the value bound to `x` from `5` to `6` when `mut` is
+used. Ultimately, deciding whether to use mutability or not is up to you and
depends on what you think is clearest in that particular situation.
### Constants
@@ -82,9 +81,9 @@ and variables.
First, you aren’t allowed to use `mut` with constants. Constants aren’t just
immutable by default—they’re always immutable. You declare constants using the
`const` keyword instead of the `let` keyword, and the type of the value *must*
-be annotated. We’re about to cover types and type annotations in the next
-section, [“Data Types,”][data-types]<!-- ignore --> so don’t worry about the
-details right now. Just know that you must always annotate the type.
+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
+right now. Just know that you must always annotate the type.
Constants can be declared in any scope, including the global scope, which makes
them useful for values that many parts of code need to know about.
@@ -109,11 +108,11 @@ to the value 10,800. See the [Rust Reference’s section on constant
evaluation][const-eval] for more information on what operations can be used
when declaring constants.
-Constants are valid for the entire time a program runs, within the scope they
-were declared in. This property makes constants useful for values in your
-application domain that multiple parts of the program might need to know about,
-such as the maximum number of points any player of a game is allowed to earn or
-the speed of light.
+Constants are valid for the entire time a program runs, within the scope in
+which they were declared. This property makes constants useful for values in
+your application domain that multiple parts of the program might need to know
+about, such as the maximum number of points any player of a game is allowed to
+earn, or the speed of light.
Naming hardcoded values used throughout your program as constants is useful in
conveying the meaning of that value to future maintainers of the code. It also
@@ -150,7 +149,7 @@ When we run this program, it will output the following:
{{#include ../listings/ch03-common-programming-concepts/no-listing-03-shadowing/output.txt}}
```
-Shadowing is different from marking a variable as `mut`, because we’ll get a
+Shadowing is different from marking a variable as `mut` because we’ll get a
compile-time error if we accidentally try to reassign to this variable without
using the `let` keyword. By using `let`, we can perform a few transformations
on a value but have the variable be immutable after those transformations have
diff --git a/src/doc/book/src/ch03-02-data-types.md b/src/doc/book/src/ch03-02-data-types.md
index 47c00adc8..bedf1450c 100644
--- a/src/doc/book/src/ch03-02-data-types.md
+++ b/src/doc/book/src/ch03-02-data-types.md
@@ -16,9 +16,9 @@ Chapter 2, we must add a type annotation, like this:
let guess: u32 = "42".parse().expect("Not a number!");
```
-If we don’t add the `: u32` type annotation above, Rust will display the
-following error, which means the compiler needs more information from us to
-know which type we want to use:
+If we don’t add the `: u32` type annotation shown in the preceding code, Rust
+will display the following error, which means the compiler needs more
+information from us to know which type we want to use:
```console
{{#include ../listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt}}
@@ -37,7 +37,7 @@ these from other programming languages. Let’s jump into how they work in Rust.
An *integer* is a number without a fractional component. We used one integer
type in Chapter 2, the `u32` type. This type declaration indicates that the
value it’s associated with should be an unsigned integer (signed integer types
-start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows
+start with `i` instead of `u`) that takes up 32 bits of space. Table 3-1 shows
the built-in integer types in Rust. We can use any of these variants to declare
the type of an integer value.
@@ -59,9 +59,8 @@ negative—in other words, whether the number needs to have a sign with it
represented without a sign (unsigned). It’s like writing numbers on paper: when
the sign matters, a number is shown with a plus sign or a minus sign; however,
when it’s safe to assume the number is positive, it’s shown with no sign.
-Signed numbers are stored using [two’s
-complement](https://en.wikipedia.org/wiki/Two%27s_complement)<!-- ignore -->
-representation.
+Signed numbers are stored using [two’s complement][twos-complement]<!-- ignore
+--> representation.
Each signed variant can store numbers from -(2<sup>n - 1</sup>) to 2<sup>n -
1</sup> - 1 inclusive, where *n* is the number of bits that variant uses. So an
@@ -98,12 +97,12 @@ some sort of collection.
> ##### Integer Overflow
>
> Let’s say you have a variable of type `u8` that can hold values between 0 and
-> 255. If you try to change the variable to a value outside of that range, such
-> as 256, *integer overflow* will occur, which can result in one of two
-> behaviors. When you’re compiling in debug mode, Rust includes checks for
-> integer overflow that cause your program to *panic* at runtime if this
-> behavior occurs. Rust uses the term panicking when a program exits with an
-> error; we’ll discuss panics in more depth in the [“Unrecoverable Errors with
+> 255. If you try to change the variable to a value outside that range, such as
+> 256, *integer overflow* will occur, which can result in one of two behaviors.
+> When you’re compiling in debug mode, Rust includes checks for integer overflow
+> that cause your program to *panic* at runtime if this behavior occurs. Rust
+> uses the term *panicking* when a program exits with an error; we’ll discuss
+> panics in more depth in the [“Unrecoverable Errors with
> `panic!`”][unrecoverable-errors-with-panic]<!-- ignore --> section in Chapter
> 9.
>
@@ -119,19 +118,19 @@ some sort of collection.
> To explicitly handle the possibility of overflow, you can use these families
> of methods provided by the standard library for primitive numeric types:
>
-> - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`
-> - Return the `None` value if there is overflow with the `checked_*` methods
-> - Return the value and a boolean indicating whether there was overflow with
-> the `overflowing_*` methods
-> - Saturate at the value’s minimum or maximum values with `saturating_*`
-> methods
+> * Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`.
+> * Return the `None` value if there is overflow with the `checked_*` methods.
+> * Return the value and a boolean indicating whether there was overflow with
+> the `overflowing_*` methods.
+> * Saturate at the value’s minimum or maximum values with the `saturating_*`
+> methods.
#### Floating-Point Types
Rust also has two primitive types for *floating-point numbers*, which are
numbers with decimal points. Rust’s floating-point types are `f32` and `f64`,
which are 32 bits and 64 bits in size, respectively. The default type is `f64`
-because on modern CPUs it’s roughly the same speed as `f32` but is capable of
+because on modern CPUs, it’s roughly the same speed as `f32` but is capable of
more precision. All floating-point types are signed.
Here’s an example that shows floating-point numbers in action:
@@ -147,9 +146,9 @@ Floating-point numbers are represented according to the IEEE-754 standard. The
#### Numeric Operations
-Rust supports the basic mathematical operations you’d expect for all of the
-number types: addition, subtraction, multiplication, division, and remainder.
-Integer division rounds down to the nearest integer. The following code shows
+Rust supports the basic mathematical operations you’d expect for all the number
+types: addition, subtraction, multiplication, division, and remainder. Integer
+division truncates toward zero to the nearest integer. The following code shows
how you’d use each numeric operation in a `let` statement:
<span class="filename">Filename: src/main.rs</span>
@@ -159,8 +158,9 @@ how you’d use each numeric operation in a `let` statement:
```
Each expression in these statements uses a mathematical operator and evaluates
-to a single value, which is then bound to a variable. [Appendix B][appendix_b]<!-- ignore --> contains a
-list of all operators that Rust provides.
+to a single value, which is then bound to a variable. [Appendix
+B][appendix_b]<!-- ignore --> contains a list of all operators that Rust
+provides.
#### The Boolean Type
@@ -180,7 +180,7 @@ Flow”][control-flow]<!-- ignore --> section.
#### The Character Type
-Rust’s `char` type is the language’s most primitive alphabetic type. Here’s
+Rust’s `char` type is the language’s most primitive alphabetic type. Here are
some examples of declaring `char` values:
<span class="filename">Filename: src/main.rs</span>
@@ -207,9 +207,9 @@ primitive compound types: tuples and arrays.
#### The Tuple Type
-A tuple is a general way of grouping together a number of values with a variety
-of types into one compound type. Tuples have a fixed length: once declared,
-they cannot grow or shrink in size.
+A *tuple* is a general way of grouping together a number of values with a
+variety of types into one compound type. Tuples have a fixed length: once
+declared, they cannot grow or shrink in size.
We create a tuple by writing a comma-separated list of values inside
parentheses. Each position in the tuple has a type, and the types of the
@@ -222,7 +222,7 @@ type annotations in this example:
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-10-tuples/src/main.rs}}
```
-The variable `tup` binds to the entire tuple, because a tuple is considered a
+The variable `tup` binds to the entire tuple because a tuple is considered a
single compound element. To get the individual values out of a tuple, we can
use pattern matching to destructure a tuple value, like this:
@@ -234,7 +234,7 @@ use pattern matching to destructure a tuple value, like this:
This program first creates a tuple and binds it to the variable `tup`. It then
uses a pattern with `let` to take `tup` and turn it into three separate
-variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks
+variables, `x`, `y`, and `z`. This is called *destructuring* because it breaks
the single tuple into three parts. Finally, the program prints the value of
`y`, which is `6.4`.
@@ -275,9 +275,9 @@ Arrays are useful when you want your data allocated on the stack rather than
the heap (we will discuss the stack and the heap more in [Chapter
4][stack-and-heap]<!-- ignore -->) or when you want to ensure you always have a
fixed number of elements. An array isn’t as flexible as the vector type,
-though. A vector is a similar collection type provided by the standard library
-that *is* allowed to grow or shrink in size. If you’re unsure whether to use an
-array or a vector, chances are you should use a vector. [Chapter
+though. A *vector* is a similar collection type provided by the standard
+library that *is* allowed to grow or shrink in size. If you’re unsure whether
+to use an array or a vector, chances are you should use a vector. [Chapter
8][vectors]<!-- ignore --> discusses vectors in more detail.
However, arrays are more useful when you know the number of elements will not
@@ -324,9 +324,9 @@ like this:
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-14-array-indexing/src/main.rs}}
```
-In this example, the variable named `first` will get the value `1`, because
-that is the value at index `[0]` in the array. The variable named `second` will
-get the value `2` from index `[1]` in the array.
+In this example, the variable named `first` will get the value `1` because that
+is the value at index `[0]` in the array. The variable named `second` will get
+the value `2` from index `[1]` in the array.
##### Invalid Array Element Access
@@ -341,9 +341,9 @@ Chapter 2, to get an array index from the user:
```
This code compiles successfully. If you run this code using `cargo run` and
-enter 0, 1, 2, 3, or 4, the program will print out the corresponding value at
-that index in the array. If you instead enter a number past the end of the
-array, such as 10, you’ll see output like this:
+enter `0`, `1`, `2`, `3`, or `4`, the program will print out the corresponding
+value at that index in the array. If you instead enter a number past the end of
+the array, such as `10`, you’ll see output like this:
<!-- manual-regeneration
cd listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access
@@ -374,10 +374,10 @@ write readable, safe code that neither panics nor allows invalid memory access.
[comparing-the-guess-to-the-secret-number]:
ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number
+[twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement
[control-flow]: ch03-05-control-flow.html#control-flow
[strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
[stack-and-heap]: ch04-01-what-is-ownership.html#the-stack-and-the-heap
[vectors]: ch08-01-vectors.html
[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html
-[wrapping]: ../std/num/struct.Wrapping.html
[appendix_b]: appendix-02-operators.md
diff --git a/src/doc/book/src/ch03-03-how-functions-work.md b/src/doc/book/src/ch03-03-how-functions-work.md
index c698853ce..2b59f0cd4 100644
--- a/src/doc/book/src/ch03-03-how-functions-work.md
+++ b/src/doc/book/src/ch03-03-how-functions-work.md
@@ -35,8 +35,8 @@ should see the following output:
```
The lines execute in the order in which they appear in the `main` function.
-First, the “Hello, world!” message prints, and then `another_function` is
-called and its message is printed.
+First the “Hello, world!” message prints, and then `another_function` is called
+and its message is printed.
### Parameters
@@ -108,8 +108,9 @@ understand. Other languages don’t have the same distinctions, so let’s look
what statements and expressions are and how their differences affect the bodies
of functions.
-*Statements* are instructions that perform some action and do not return a
-value. *Expressions* evaluate to a resulting value. Let’s look at some examples.
+* **Statements** are instructions that perform some action and do not return
+ a value.
+* **Expressions** evaluate to a resultant value. Let’s look at some examples.
We’ve actually already used statements and expressions. Creating a variable and
assigning a value to it with the `let` keyword is a statement. In Listing 3-1,
@@ -172,10 +173,11 @@ This expression:
is a block that, in this case, evaluates to `4`. That value gets bound to `y`
as part of the `let` statement. Note that the `x + 1` line doesn’t have a
-semicolon at the end, unlike most of the lines you’ve seen so far. Expressions
-do not include ending semicolons. If you add a semicolon to the end of an
-expression, you turn it into a statement, and it will then not return a value.
-Keep this in mind as you explore function return values and expressions next.
+semicolon at the end, which is unlike most of the lines you’ve seen so far.
+Expressions do not include ending semicolons. If you add a semicolon to the end
+of an expression, you turn it into a statement, and it will then not return a
+value. Keep this in mind as you explore function return values and expressions
+next.
### Functions with Return Values
@@ -226,7 +228,7 @@ Let’s look at another example:
Running this code will print `The value of x is: 6`. But if we place a
semicolon at the end of the line containing `x + 1`, changing it from an
-expression to a statement, we’ll get an error.
+expression to a statement, we’ll get an error:
<span class="filename">Filename: src/main.rs</span>
@@ -240,7 +242,7 @@ Compiling this code produces an error, as follows:
{{#include ../listings/ch03-common-programming-concepts/no-listing-23-statements-dont-return-values/output.txt}}
```
-The main error message, “mismatched types,” reveals the core issue with this
+The main error message, `mismatched types`, reveals the core issue with this
code. The definition of the function `plus_one` says that it will return an
`i32`, but statements don’t evaluate to a value, which is expressed by `()`,
the unit type. Therefore, nothing is returned, which contradicts the function
diff --git a/src/doc/book/src/ch03-04-comments.md b/src/doc/book/src/ch03-04-comments.md
index 6af0ce175..bfb0cfe17 100644
--- a/src/doc/book/src/ch03-04-comments.md
+++ b/src/doc/book/src/ch03-04-comments.md
@@ -39,4 +39,7 @@ separate line above the code it’s annotating:
```
Rust also has another kind of comment, documentation comments, which we’ll
-discuss in the “Publishing a Crate to Crates.io” section of Chapter 14.
+discuss in the [“Publishing a Crate to Crates.io”][publishing]<!-- ignore -->
+section of Chapter 14.
+
+[publishing]: ch14-02-publishing-to-crates-io.html
diff --git a/src/doc/book/src/ch03-05-control-flow.md b/src/doc/book/src/ch03-05-control-flow.md
index 100bfb3e3..60d6b95a9 100644
--- a/src/doc/book/src/ch03-05-control-flow.md
+++ b/src/doc/book/src/ch03-05-control-flow.md
@@ -1,9 +1,9 @@
## Control Flow
-The ability to run some code depending on if a condition is true, or run some
-code repeatedly while a condition is true, are basic building blocks in most
-programming languages. The most common constructs that let you control the flow
-of execution of Rust code are `if` expressions and loops.
+The ability to run some code depending on whether a condition is `true` and to
+run some code repeatedly while a condition is `true` are basic building blocks
+in most programming languages. The most common constructs that let you control
+the flow of execution of Rust code are `if` expressions and loops.
### `if` Expressions
@@ -22,17 +22,17 @@ the `if` expression. In the *src/main.rs* file, input the following:
All `if` expressions start with the keyword `if`, followed by a condition. In
this case, the condition checks whether or not the variable `number` has a
-value less than 5. We place the block of code to execute if the condition is true
-immediately after the condition inside curly brackets. Blocks of code
+value less than 5. We place the block of code to execute if the condition is
+`true` immediately after the condition inside curly brackets. Blocks of code
associated with the conditions in `if` expressions are sometimes called *arms*,
just like the arms in `match` expressions that we discussed in the [“Comparing
the Guess to the Secret Number”][comparing-the-guess-to-the-secret-number]<!--
ignore --> section of Chapter 2.
-Optionally, we can also include an `else` expression, which we chose
-to do here, to give the program an alternative block of code to execute should
-the condition evaluate to false. If you don’t provide an `else` expression and
-the condition is false, the program will just skip the `if` block and move on
+Optionally, we can also include an `else` expression, which we chose to do
+here, to give the program an alternative block of code to execute should the
+condition evaluate to `false`. If you don’t provide an `else` expression and
+the condition is `false`, the program will just skip the `if` block and move on
to the next bit of code.
Try running this code; you should see the following output:
@@ -105,11 +105,11 @@ see the following output:
```
When this program executes, it checks each `if` expression in turn and executes
-the first body for which the condition holds true. Note that even though 6 is
-divisible by 2, we don’t see the output `number is divisible by 2`, nor do we
-see the `number is not divisible by 4, 3, or 2` text from the `else` block.
-That’s because Rust only executes the block for the first true condition, and
-once it finds one, it doesn’t even check the rest.
+the first body for which the condition evaluates to `true`. Note that even
+though 6 is divisible by 2, we don’t see the output `number is divisible by 2`,
+nor do we see the `number is not divisible by 4, 3, or 2` text from the `else`
+block. That’s because Rust only executes the block for the first `true`
+condition, and once it finds one, it doesn’t even check the rest.
Using too many `else if` expressions can clutter your code, so if you have more
than one, you might want to refactor your code. Chapter 6 describes a powerful
@@ -171,8 +171,8 @@ if it had to keep track of multiple hypothetical types for any variable.
It’s often useful to execute a block of code more than once. For this task,
Rust provides several *loops*, which will run through the code inside the loop
-body to the end and then start immediately back at the beginning. To
-experiment with loops, let’s make a new project called *loops*.
+body to the end and then start immediately back at the beginning. To experiment
+with loops, let’s make a new project called *loops*.
Rust has three kinds of loops: `loop`, `while`, and `for`. Let’s try each one.
@@ -191,9 +191,9 @@ like this:
```
When we run this program, we’ll see `again!` printed over and over continuously
-until we stop the program manually. Most terminals support the keyboard shortcut
-<span class="keystroke">ctrl-c</span> to interrupt a program that is stuck in
-a continual loop. Give it a try:
+until we stop the program manually. Most terminals support the keyboard
+shortcut <span class="keystroke">ctrl-c</span> to interrupt a program that is
+stuck in a continual loop. Give it a try:
<!-- manual-regeneration
cd listings/ch03-common-programming-concepts/no-listing-32-loop
@@ -213,10 +213,10 @@ again!
^Cagain!
```
-The symbol `^C` represents where you pressed <span class="keystroke">ctrl-c
-</span>. You may or may not see the word `again!` printed after the `^C`,
-depending on where the code was in the loop when it received the interrupt
-signal.
+The symbol `^C` represents where you pressed <span
+class="keystroke">ctrl-c</span>. You may or may not see the word `again!`
+printed after the `^C`, depending on where the code was in the loop when it
+received the interrupt signal.
Fortunately, Rust also provides a way to break out of a loop using code. You
can place the `break` keyword within the loop to tell the program when to stop
@@ -245,18 +245,18 @@ use it, as shown here:
Before the loop, we declare a variable named `counter` and initialize it to
`0`. Then we declare a variable named `result` to hold the value returned from
the loop. On every iteration of the loop, we add `1` to the `counter` variable,
-and then check whether the counter is equal to `10`. When it is, we use the
+and then check whether the `counter` is equal to `10`. When it is, we use the
`break` keyword with the value `counter * 2`. After the loop, we use a
semicolon to end the statement that assigns the value to `result`. Finally, we
-print the value in `result`, which in this case is 20.
+print the value in `result`, which in this case is `20`.
#### Loop Labels to Disambiguate Between Multiple Loops
If you have loops within loops, `break` and `continue` apply to the innermost
-loop at that point. You can optionally specify a *loop label* on a loop that we
-can then use with `break` or `continue` to specify that those keywords apply to
-the labeled loop instead of the innermost loop. Loop labels must begin with a
-single quote. Here’s an example with two nested loops:
+loop at that point. You can optionally specify a *loop label* on a loop that
+you can then use with `break` or `continue` to specify that those keywords
+apply to the labeled loop instead of the innermost loop. Loop labels must begin
+with a single quote. Here’s an example with two nested loops:
```rust
{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-32-5-loop-labels/src/main.rs}}
@@ -274,7 +274,7 @@ doesn’t specify a label will exit the inner loop only. The `break
#### Conditional Loops with `while`
A program will often need to evaluate a condition within a loop. While the
-condition is true, the loop runs. When the condition ceases to be true, the
+condition is `true`, the loop runs. When the condition ceases to be `true`, the
program calls `break`, stopping the loop. It’s possible to implement behavior
like this using a combination of `loop`, `if`, `else`, and `break`; you could
try that now in a program, if you’d like. However, this pattern is so common
@@ -292,8 +292,8 @@ time, and then, after the loop, print a message and exit.
condition holds true</span>
This construct eliminates a lot of nesting that would be necessary if you used
-`loop`, `if`, `else`, and `break`, and it’s clearer. While a condition holds
-true, the code runs; otherwise, it exits the loop.
+`loop`, `if`, `else`, and `break`, and it’s clearer. While a condition
+evaluates to `true`, the code runs; otherwise, it exits the loop.
#### Looping Through a Collection with `for`
@@ -312,8 +312,8 @@ using a `while` loop</span>
Here, the code counts up through the elements in the array. It starts at index
`0`, and then loops until it reaches the final index in the array (that is,
-when `index < 5` is no longer true). Running this code will print every element
-in the array:
+when `index < 5` is no longer `true`). Running this code will print every
+element in the array:
```console
{{#include ../listings/ch03-common-programming-concepts/listing-03-04/output.txt}}
@@ -324,8 +324,8 @@ will reach a value of `5` at some point, the loop stops executing before trying
to fetch a sixth value from the array.
However, this approach is error prone; we could cause the program to panic if
-the index value or test condition are incorrect. For example, if you changed
-the definition of the `a` array to have four elements but forgot to update the
+the index value or test condition is incorrect. For example, if you changed the
+definition of the `a` array to have four elements but forgot to update the
condition to `while index < 4`, the code would panic. It’s also slow, because
the compiler adds runtime code to perform the conditional check of whether the
index is within the bounds of the array on every iteration through the loop.
@@ -372,13 +372,13 @@ This code is a bit nicer, isn’t it?
## Summary
-You made it! That was a sizable chapter: you learned about variables, scalar
-and compound data types, functions, comments, `if` expressions, and loops!
-To practice with the concepts discussed in this chapter, try building
-programs to do the following:
+You made it! This was a sizable chapter: you learned about variables, scalar
+and compound data types, functions, comments, `if` expressions, and loops! To
+practice with the concepts discussed in this chapter, try building programs to
+do the following:
* Convert temperatures between Fahrenheit and Celsius.
-* Generate the nth Fibonacci number.
+* Generate the *n*th Fibonacci number.
* Print the lyrics to the Christmas carol “The Twelve Days of Christmas,”
taking advantage of the repetition in the song.
diff --git a/src/doc/book/src/ch04-01-what-is-ownership.md b/src/doc/book/src/ch04-01-what-is-ownership.md
index 94842e1b0..5249c2dd7 100644
--- a/src/doc/book/src/ch04-01-what-is-ownership.md
+++ b/src/doc/book/src/ch04-01-what-is-ownership.md
@@ -1,8 +1,8 @@
## What Is Ownership?
-*Ownership* is a set of rules that governs how a Rust program manages memory.
+*Ownership* is a set of rules that govern how a Rust program manages memory.
All programs have to manage the way they use a computer’s memory while running.
-Some languages have garbage collection that regularly looks for no-longer used
+Some languages have garbage collection that regularly looks for no-longer-used
memory as the program runs; in other languages, the programmer must explicitly
allocate and free the memory. Rust uses a third approach: memory is managed
through a system of ownership with a set of rules that the compiler checks. If
@@ -49,14 +49,14 @@ strings.
> known, fixed size, you can store the pointer on the stack, but when you want
> the actual data, you must follow the pointer. Think of being seated at a
> restaurant. When you enter, you state the number of people in your group, and
-> the staff finds an empty table that fits everyone and leads you there. If
+> the host finds an empty table that fits everyone and leads you there. If
> someone in your group comes late, they can ask where you’ve been seated to
> find you.
>
> Pushing to the stack is faster than allocating on the heap because the
> allocator never has to search for a place to store new data; that location is
> always at the top of the stack. Comparatively, allocating space on the heap
-> requires more work, because the allocator must first find a big enough space
+> requires more work because the allocator must first find a big enough space
> to hold the data and then perform bookkeeping to prepare for the next
> allocation.
>
@@ -122,8 +122,8 @@ valid</span>
In other words, there are two important points in time here:
-* When `s` comes *into scope*, it is valid.
-* It remains valid until it goes *out of scope*.
+* When `s` comes *into* scope, it is valid.
+* It remains valid until it goes *out of* scope.
At this point, the relationship between scopes and when variables are valid is
similar to that in other programming languages. Now we’ll build on top of this
@@ -133,7 +133,7 @@ understanding by introducing the `String` type.
To illustrate the rules of ownership, we need a data type that is more complex
than those we covered in the [“Data Types”][data-types]<!-- ignore --> section
-of Chapter 3. The types covered previously are all a known size, can be stored
+of Chapter 3. The types covered previously are of a known size, can be stored
on the stack and popped off the stack when their scope is over, and can be
quickly and trivially copied to make a new, independent instance if another
part of code needs to use the same value in a different scope. But we want to
@@ -162,7 +162,7 @@ let s = String::from("hello");
The double colon `::` operator allows us to namespace this particular `from`
function under the `String` type rather than using some sort of name like
`string_from`. We’ll discuss this syntax more in the [“Method
-Syntax”][method-syntax]<!-- ignore --> section of Chapter 5 and when we talk
+Syntax”][method-syntax]<!-- ignore --> section of Chapter 5, and when we talk
about namespacing with modules in [“Paths for Referring to an Item in the
Module Tree”][paths-module-tree]<!-- ignore --> in Chapter 7.
@@ -173,7 +173,7 @@ This kind of string *can* be mutated:
```
So, what’s the difference here? Why can `String` be mutated but literals
-cannot? The difference is how these two types deal with memory.
+cannot? The difference is in how these two types deal with memory.
### Memory and Allocation
@@ -189,8 +189,8 @@ we need to allocate an amount of memory on the heap, unknown at compile time,
to hold the contents. This means:
* The memory must be requested from the memory allocator at runtime.
-* We need a way of returning this memory to the allocator when we’re
- done with our `String`.
+* We need a way of returning this memory to the allocator when we’re done with
+ our `String`.
That first part is done by us: when we call `String::from`, its implementation
requests the memory it needs. This is pretty much universal in programming
@@ -199,7 +199,7 @@ languages.
However, the second part is different. In languages with a *garbage collector
(GC)*, the GC keeps track of and cleans up memory that isn’t being used
anymore, and we don’t need to think about it. In most languages without a GC,
-it’s our responsibility to identify when memory is no longer being used and
+it’s our responsibility to identify when memory is no longer being used and to
call code to explicitly free it, just as we did to request it. Doing this
correctly has historically been a difficult programming problem. If we forget,
we’ll waste memory. If we do it too early, we’ll have an invalid variable. If
@@ -231,7 +231,10 @@ simple right now, but the behavior of code can be unexpected in more
complicated situations when we want to have multiple variables use the data
we’ve allocated on the heap. Let’s explore some of those situations now.
-#### Ways Variables and Data Interact: Move
+<!-- Old heading. Do not remove or links may break. -->
+<a id="ways-variables-and-data-interact-move"></a>
+
+#### Variables and Data Interacting with Move
Multiple variables can interact with the same data in different ways in Rust.
Let’s look at an example using an integer in Listing 4-2.
@@ -265,23 +268,29 @@ the memory that holds the contents of the string, a length, and a capacity.
This group of data is stored on the stack. On the right is the memory on the
heap that holds the contents.
-<img alt="String in memory" src="img/trpl04-01.svg" class="center" style="width: 50%;" />
+<img alt="Two tables: the first table contains the representation of s1 on the
+stack, consisting of its length (5), capacity (5), and a pointer to the first
+value in the second table. The second table contains the representation of the
+string data on the heap, byte by byte." src="img/trpl04-01.svg" class="center"
+style="width: 50%;" />
<span class="caption">Figure 4-1: Representation in memory of a `String`
holding the value `"hello"` bound to `s1`</span>
-The length is how much memory, in bytes, the contents of the `String` is
+The length is how much memory, in bytes, the contents of the `String` are
currently using. The capacity is the total amount of memory, in bytes, that the
-`String` has received from the allocator. The difference between length
-and capacity matters, but not in this context, so for now, it’s fine to ignore
-the capacity.
+`String` has received from the allocator. The difference between length and
+capacity matters, but not in this context, so for now, it’s fine to ignore the
+capacity.
When we assign `s1` to `s2`, the `String` data is copied, meaning we copy the
pointer, the length, and the capacity that are on the stack. We do not copy the
data on the heap that the pointer refers to. In other words, the data
representation in memory looks like Figure 4-2.
-<img alt="s1 and s2 pointing to the same value" src="img/trpl04-02.svg" class="center" style="width: 50%;" />
+<img alt="Three tables: tables s1 and s2 representing those strings on the
+stack, respectively, and both pointing to the same string data on the heap."
+src="img/trpl04-02.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-2: Representation in memory of the variable `s2`
that has a copy of the pointer, length, and capacity of `s1`</span>
@@ -291,7 +300,9 @@ look like if Rust instead copied the heap data as well. If Rust did this, the
operation `s2 = s1` could be very expensive in terms of runtime performance if
the data on the heap were large.
-<img alt="s1 and s2 to two places" src="img/trpl04-03.svg" class="center" style="width: 50%;" />
+<img alt="Four tables: two tables representing the stack data for s1 and s2,
+and each points to its own copy of string data on the heap."
+src="img/trpl04-03.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-3: Another possibility for what `s2 = s1` might
do if Rust copied the heap data as well</span>
@@ -304,7 +315,7 @@ same memory. This is known as a *double free* error and is one of the memory
safety bugs we mentioned previously. Freeing memory twice can lead to memory
corruption, which can potentially lead to security vulnerabilities.
-To ensure memory safety, after the line `let s2 = s1`, Rust considers `s1` as
+To ensure memory safety, after the line `let s2 = s1;`, Rust considers `s1` as
no longer valid. Therefore, Rust doesn’t need to free anything when `s1` goes
out of scope. Check out what happens when you try to use `s1` after `s2` is
created; it won’t work:
@@ -323,23 +334,30 @@ invalidated reference:
If you’ve heard the terms *shallow copy* and *deep copy* while working with
other languages, the concept of copying the pointer, length, and capacity
without copying the data probably sounds like making a shallow copy. But
-because Rust also invalidates the first variable, instead of calling it a
-shallow copy, it’s known as a *move*. In this example, we would say that
-`s1` was *moved* into `s2`. So what actually happens is shown in Figure 4-4.
+because Rust also invalidates the first variable, instead of being called a
+shallow copy, it’s known as a *move*. In this example, we would say that `s1`
+was *moved* into `s2`. So, what actually happens is shown in Figure 4-4.
-<img alt="s1 moved to s2" src="img/trpl04-04.svg" class="center" style="width: 50%;" />
+<img alt="Three tables: tables s1 and s2 representing those strings on the
+stack, respectively, and both pointing to the same string data on the heap.
+Table s1 is grayed out be-cause s1 is no longer valid; only s2 can be used to
+access the heap data." src="img/trpl04-04.svg" class="center" style="width:
+50%;" />
<span class="caption">Figure 4-4: Representation in memory after `s1` has been
invalidated</span>
-That solves our problem! With only `s2` valid, when it goes out of scope, it
+That solves our problem! With only `s2` valid, when it goes out of scope it
alone will free the memory, and we’re done.
In addition, there’s a design choice that’s implied by this: Rust will never
automatically create “deep” copies of your data. Therefore, any *automatic*
copying can be assumed to be inexpensive in terms of runtime performance.
-#### Ways Variables and Data Interact: Clone
+<!-- Old heading. Do not remove or links may break. -->
+<a id="ways-variables-and-data-interact-clone"></a>
+
+#### Variables and Data Interacting with Clone
If we *do* want to deeply copy the heap data of the `String`, not just the
stack data, we can use a common method called `clone`. We’ll discuss method
@@ -361,8 +379,8 @@ different is going on.
#### Stack-Only Data: Copy
-There’s another wrinkle we haven’t talked about yet. This code using integers –
-part of which was shown in Listing 4-2 – works and is valid:
+There’s another wrinkle we haven’t talked about yet. This code using
+integers—part of which was shown in Listing 4-2—works and is valid:
```rust
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-06-copy/src/main.rs:here}}
@@ -376,7 +394,7 @@ time are stored entirely on the stack, so copies of the actual values are quick
to make. That means there’s no reason we would want to prevent `x` from being
valid after we create the variable `y`. In other words, there’s no difference
between deep and shallow copying here, so calling `clone` wouldn’t do anything
-different from the usual shallow copying and we can leave it out.
+different from the usual shallow copying, and we can leave it out.
Rust has a special annotation called the `Copy` trait that we can place on
types that are stored on the stack, as integers are (we’ll talk more about
@@ -391,7 +409,7 @@ we’ll get a compile-time error. To learn about how to add the `Copy` annotatio
to your type to implement the trait, see [“Derivable
Traits”][derivable-traits]<!-- ignore --> in Appendix C.
-So what types implement the `Copy` trait? You can check the documentation for
+So, what types implement the `Copy` trait? You can check the documentation for
the given type to be sure, but as a general rule, any group of simple scalar
values can implement `Copy`, and nothing that requires allocation or is some
form of resource can implement `Copy`. Here are some of the types that
@@ -399,7 +417,7 @@ implement `Copy`:
* All the integer types, such as `u32`.
* The Boolean type, `bool`, with values `true` and `false`.
-* All the floating point types, such as `f64`.
+* All the floating-point types, such as `f64`.
* The character type, `char`.
* Tuples, if they only contain types that also implement `Copy`. For example,
`(i32, i32)` implements `Copy`, but `(i32, String)` does not.
@@ -427,9 +445,9 @@ the ownership rules prevent you from doing so.
### Return Values and Scope
-Returning values can also transfer ownership. Listing 4-4 shows an example
-of a function that returns some value, with similar annotations as those in
-Listing 4-3.
+Returning values can also transfer ownership. Listing 4-4 shows an example of a
+function that returns some value, with similar annotations as those in Listing
+4-3.
<span class="filename">Filename: src/main.rs</span>
diff --git a/src/doc/book/src/ch04-02-references-and-borrowing.md b/src/doc/book/src/ch04-02-references-and-borrowing.md
index 060c344bb..ea2d8d202 100644
--- a/src/doc/book/src/ch04-02-references-and-borrowing.md
+++ b/src/doc/book/src/ch04-02-references-and-borrowing.md
@@ -9,9 +9,8 @@ the data stored at that address; that data is owned by some other variable.
Unlike a pointer, a reference is guaranteed to point to a valid value of a
particular type for the life of that reference.
-Here is how you would define and use a `calculate_length` function that
-has a reference to an object as a parameter instead of taking ownership of the
-value:
+Here is how you would define and use a `calculate_length` function that has a
+reference to an object as a parameter instead of taking ownership of the value:
<span class="filename">Filename: src/main.rs</span>
@@ -25,7 +24,9 @@ function return value is gone. Second, note that we pass `&s1` into
`String`. These ampersands represent *references*, and they allow you to refer
to some value without taking ownership of it. Figure 4-5 depicts this concept.
-<img alt="&amp;String s pointing at String s1" src="img/trpl04-05.svg" class="center" />
+<img alt="Three tables: the table for s contains only a pointer to the table
+for s1. The table for s1 contains the stack data for s1 and points to the
+string data on the heap." src="img/trpl04-05.svg" class="center" />
<span class="caption">Figure 4-5: A diagram of `&String s` pointing at `String
s1`</span>
@@ -54,7 +55,7 @@ the parameter `s` is a reference. Let’s add some explanatory annotations:
The scope in which the variable `s` is valid is the same as any function
parameter’s scope, but the value pointed to by the reference is not dropped
-when `s` stops being used because `s` doesn’t have ownership. When functions
+when `s` stops being used, because `s` doesn’t have ownership. When functions
have references as parameters instead of the actual values, we won’t need to
return the values in order to give back ownership, because we never had
ownership.
@@ -63,7 +64,7 @@ We call the action of creating a reference *borrowing*. As in real life, if a
person owns something, you can borrow it from them. When you’re done, you have
to give it back. You don’t own it.
-So what happens if we try to modify something we’re borrowing? Try the code in
+So, what happens if we try to modify something we’re borrowing? Try the code in
Listing 4-6. Spoiler alert: it doesn’t work!
<span class="filename">Filename: src/main.rs</span>
@@ -94,7 +95,7 @@ with just a few small tweaks that use, instead, a *mutable reference*:
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-09-fixes-listing-04-06/src/main.rs}}
```
-First, we change `s` to be `mut`. Then we create a mutable reference with `&mut
+First we change `s` to be `mut`. Then we create a mutable reference with `&mut
s` where we call the `change` function, and update the function signature to
accept a mutable reference with `some_string: &mut String`. This makes it very
clear that the `change` function will mutate the value it borrows.
@@ -123,7 +124,7 @@ in `r2` that borrows the same data as `r1`.
The restriction preventing multiple mutable references to the same data at the
same time allows for mutation but in a very controlled fashion. It’s something
-that new Rustaceans struggle with, because most languages let you mutate
+that new Rustaceans struggle with because most languages let you mutate
whenever you’d like. The benefit of having this restriction is that Rust can
prevent data races at compile time. A *data race* is similar to a race
condition and happens when these three behaviors occur:
@@ -133,8 +134,8 @@ condition and happens when these three behaviors occur:
* There’s no mechanism being used to synchronize access to the data.
Data races cause undefined behavior and can be difficult to diagnose and fix
-when you’re trying to track them down at runtime; Rust prevents this problem
-by refusing to compile code with data races!
+when you’re trying to track them down at runtime; Rust prevents this problem by
+refusing to compile code with data races!
As always, we can use curly brackets to create a new scope, allowing for
multiple mutable references, just not *simultaneous* ones:
@@ -175,10 +176,9 @@ occurs before the mutable reference is introduced:
The scopes of the immutable references `r1` and `r2` end after the `println!`
where they are last used, which is before the mutable reference `r3` is
-created. These scopes don’t overlap, so this code is allowed. The ability of
-the compiler to tell that a reference is no longer being used at a point before
-the end of the scope is called *Non-Lexical Lifetimes* (NLL for short), and you
-can read more about it in [The Edition Guide][nll].
+created. These scopes don’t overlap, so this code is allowed: the compiler can
+tell that the reference is no longer being used at a point before the end of
+the scope.
Even though borrowing errors may be frustrating at times, remember that it’s
the Rust compiler pointing out a potential bug early (at compile time rather
@@ -188,9 +188,9 @@ have to track down why your data isn’t what you thought it was.
### Dangling References
In languages with pointers, it’s easy to erroneously create a *dangling
-pointer*--a pointer that references a location in memory that may have been
-given to someone else--by freeing some memory while preserving a pointer to
-that memory. In Rust, by contrast, the compiler guarantees that references will
+pointer*—a pointer that references a location in memory that may have been
+given to someone else—by freeing some memory while preserving a pointer to that
+memory. In Rust, by contrast, the compiler guarantees that references will
never be dangling references: if you have a reference to some data, the
compiler will ensure that the data will not go out of scope before the
reference to the data does.
@@ -251,5 +251,3 @@ Let’s recap what we’ve discussed about references:
* References must always be valid.
Next, we’ll look at a different kind of reference: slices.
-
-[nll]: https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/non-lexical-lifetimes.html
diff --git a/src/doc/book/src/ch04-03-slices.md b/src/doc/book/src/ch04-03-slices.md
index afb6f76b1..6ffb1dc11 100644
--- a/src/doc/book/src/ch04-03-slices.md
+++ b/src/doc/book/src/ch04-03-slices.md
@@ -32,7 +32,7 @@ byte index value into the `String` parameter</span>
Because we need to go through the `String` element by element and check whether
a value is a space, we’ll convert our `String` to an array of bytes using the
-`as_bytes` method:
+`as_bytes` method.
```rust,ignore
{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:as_bytes}}
@@ -60,7 +60,7 @@ Because we get a reference to the element from `.iter().enumerate()`, we use
Inside the `for` loop, we search for the byte that represents the space by
using the byte literal syntax. If we find a space, we return the position.
-Otherwise, we return the length of the string by using `s.len()`:
+Otherwise, we return the length of the string by using `s.len()`.
```rust,ignore
{{#rustdoc_include ../listings/ch04-understanding-ownership/listing-04-07/src/main.rs:inside_for}}
@@ -98,8 +98,8 @@ fn second_word(s: &String) -> (usize, usize) {
Now we’re tracking a starting *and* an ending index, and we have even more
values that were calculated from data in a particular state but aren’t tied to
-that state at all. We have three unrelated variables floating around that
-need to be kept in sync.
+that state at all. We have three unrelated variables floating around that need
+to be kept in sync.
Luckily, Rust has a solution to this problem: string slices.
@@ -117,18 +117,22 @@ using a range within brackets by specifying `[starting_index..ending_index]`,
where `starting_index` is the first position in the slice and `ending_index` is
one more than the last position in the slice. Internally, the slice data
structure stores the starting position and the length of the slice, which
-corresponds to `ending_index` minus `starting_index`. So in the case of `let
+corresponds to `ending_index` minus `starting_index`. So, in the case of `let
world = &s[6..11];`, `world` would be a slice that contains a pointer to the
-byte at index 6 of `s` with a length value of 5.
+byte at index 6 of `s` with a length value of `5`.
Figure 4-6 shows this in a diagram.
-<img alt="world containing a pointer to the byte at index 6 of String s and a length 5" src="img/trpl04-06.svg" class="center" style="width: 50%;" />
+<img alt="Three tables: a table representing the stack data of s, which points
+to the byte at index 0 in a table of the string data &quot;hello world&quot; on
+the heap. The third table rep-resents the stack data of the slice world, which
+has a length value of 5 and points to byte 6 of the heap data table."
+src="img/trpl04-06.svg" class="center" style="width: 50%;" />
<span class="caption">Figure 4-6: String slice referring to part of a
`String`</span>
-With Rust’s `..` range syntax, if you want to start at index zero, you can drop
+With Rust’s `..` range syntax, if you want to start at index 0, you can drop
the value before the two periods. In other words, these are equal:
```rust
@@ -178,10 +182,10 @@ slice. The type that signifies “string slice” is written as `&str`:
{{#rustdoc_include ../listings/ch04-understanding-ownership/no-listing-18-first-word-slice/src/main.rs:here}}
```
-We get the index for the end of the word in the same way as we did in Listing
-4-7, by looking for the first occurrence of a space. When we find a space, we
-return a string slice using the start of the string and the index of the space
-as the starting and ending indices.
+We get the index for the end of the word the same way we did in Listing 4-7, by
+looking for the first occurrence of a space. When we find a space, we return a
+string slice using the start of the string and the index of the space as the
+starting and ending indices.
Now when we call `first_word`, we get back a single value that is tied to the
underlying data. The value is made up of a reference to the starting point of
@@ -193,7 +197,7 @@ Returning a slice would also work for a `second_word` function:
fn second_word(s: &String) -> &str {
```
-We now have a straightforward API that’s much harder to mess up, because the
+We now have a straightforward API that’s much harder to mess up because the
compiler will ensure the references into the `String` remain valid. Remember
the bug in the program in Listing 4-8, when we got the index to the end of the
first word but then cleared the string so our index was invalid? That code was
@@ -224,7 +228,10 @@ reference in `clear` and the immutable reference in `word` from existing at the
same time, and compilation fails. Not only has Rust made our API easier to use,
but it has also eliminated an entire class of errors at compile time!
-#### String Literals Are Slices
+<!-- Old heading. Do not remove or links may break. -->
+<a id="string-literals-are-slices"></a>
+
+#### String Literals as Slices
Recall that we talked about string literals being stored inside the binary. Now
that we know about slices, we can properly understand string literals:
@@ -260,10 +267,11 @@ a string slice for the type of the `s` parameter</span>
If we have a string slice, we can pass that directly. If we have a `String`, we
can pass a slice of the `String` or a reference to the `String`. This
flexibility takes advantage of *deref coercions*, a feature we will cover in
-the [“Implicit Deref Coercions with Functions and
-Methods”][deref-coercions]<!--ignore--> section of Chapter 15. Defining a
-function to take a string slice instead of a reference to a `String` makes our
-API more general and useful without losing any functionality:
+[“Implicit Deref Coercions with Functions and
+Methods”][deref-coercions]<!--ignore--> section of Chapter 15.
+
+Defining a function to take a string slice instead of a reference to a `String`
+makes our API more general and useful without losing any functionality:
<span class="filename">Filename: src/main.rs</span>
@@ -274,14 +282,14 @@ API more general and useful without losing any functionality:
### Other Slices
String slices, as you might imagine, are specific to strings. But there’s a
-more general slice type, too. Consider this array:
+more general slice type too. Consider this array:
```rust
let a = [1, 2, 3, 4, 5];
```
-Just as we might want to refer to a part of a string, we might want to refer
-to part of an array. We’d do so like this:
+Just as we might want to refer to part of a string, we might want to refer to
+part of an array. We’d do so like this:
```rust
let a = [1, 2, 3, 4, 5];
diff --git a/src/doc/book/src/ch05-02-example-structs.md b/src/doc/book/src/ch05-02-example-structs.md
index a83fa0564..5d33d9cb1 100644
--- a/src/doc/book/src/ch05-02-example-structs.md
+++ b/src/doc/book/src/ch05-02-example-structs.md
@@ -198,7 +198,7 @@ that expression, and returns ownership of the value.
> Note: Calling the `dbg!` macro prints to the standard error console stream
> (`stderr`), as opposed to `println!` which prints to the standard output
> console stream (`stdout`). We’ll talk more about `stderr` and `stdout` in the
-> “[“Writing Error Messages to Standard Error Instead of Standard
+> [“Writing Error Messages to Standard Error Instead of Standard
> Output” section in Chapter 12][err]<!-- ignore -->.
Here’s an example where we’re interested in the value that gets assigned to the
diff --git a/src/doc/book/src/ch08-02-strings.md b/src/doc/book/src/ch08-02-strings.md
index bf79c3925..9663d36ab 100644
--- a/src/doc/book/src/ch08-02-strings.md
+++ b/src/doc/book/src/ch08-02-strings.md
@@ -355,7 +355,7 @@ of type `char`, and you can iterate over the result to access each element:
```rust
for c in "Зд".chars() {
- println!("{}", c);
+ println!("{c}");
}
```
@@ -371,7 +371,7 @@ appropriate for your domain:
```rust
for b in "Зд".bytes() {
- println!("{}", b);
+ println!("{b}");
}
```
diff --git a/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md b/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md
index f5b9fefb8..5675fe3e7 100644
--- a/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md
+++ b/src/doc/book/src/ch09-01-unrecoverable-errors-with-panic.md
@@ -120,21 +120,21 @@ $ RUST_BACKTRACE=1 cargo run
thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 99', src/main.rs:4:5
stack backtrace:
0: rust_begin_unwind
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:483
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/std/src/panicking.rs:584:5
1: core::panicking::panic_fmt
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:85
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:142:14
2: core::panicking::panic_bounds_check
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:62
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/panicking.rs:84:5
3: <usize as core::slice::index::SliceIndex<[T]>>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:255
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:242:10
4: core::slice::index::<impl core::ops::index::Index<I> for [T]>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/slice/index.rs:15
- 5: <alloc::vec::Vec<T> as core::ops::index::Index<I>>::index
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/alloc/src/vec.rs:1982
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/slice/index.rs:18:9
+ 5: <alloc::vec::Vec<T,A> as core::ops::index::Index<I>>::index
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/alloc/src/vec/mod.rs:2591:9
6: panic::main
- at ./src/main.rs:4
+ at ./src/main.rs:4:5
7: core::ops::function::FnOnce::call_once
- at /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/ops/function.rs:227
+ at /rustc/e092d0b6b43f2de967af0887873151bb1c0b18d3/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
```
diff --git a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md
index 347ef9aa7..2ee006f09 100644
--- a/src/doc/book/src/ch09-02-recoverable-errors-with-result.md
+++ b/src/doc/book/src/ch09-02-recoverable-errors-with-result.md
@@ -6,9 +6,9 @@ interpret and respond to. For example, if you try to open a file and that
operation fails because the file doesn’t exist, you might want to create the
file instead of terminating the process.
-Recall from [“Handling Potential Failure with the `Result`
-Type”][handle_failure]<!-- ignore --> in Chapter 2 that the `Result` enum is
-defined as having two variants, `Ok` and `Err`, as follows:
+Recall from [“Handling Potential Failure with `Result`”][handle_failure]<!--
+ignore --> in Chapter 2 that the `Result` enum is defined as having two
+variants, `Ok` and `Err`, as follows:
```rust
enum Result<T, E> {
@@ -532,6 +532,6 @@ Now that we’ve discussed the details of calling `panic!` or returning `Result`
let’s return to the topic of how to decide which is appropriate to use in which
cases.
-[handle_failure]: ch02-00-guessing-game-tutorial.html#handling-potential-failure-with-the-result-type
+[handle_failure]: ch02-00-guessing-game-tutorial.html#handling-potential-failure-with-result
[trait-objects]: ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
[termination]: ../std/process/trait.Termination.html
diff --git a/src/doc/book/src/ch13-02-iterators.md b/src/doc/book/src/ch13-02-iterators.md
index 2efa552a8..030ebf48e 100644
--- a/src/doc/book/src/ch13-02-iterators.md
+++ b/src/doc/book/src/ch13-02-iterators.md
@@ -133,7 +133,7 @@ ownership of the iterator we call it on.
consume the iterator. Instead, they produce different iterators by changing
some aspect of the original iterator.
-Listing 13-17 shows an example of calling the iterator adaptor method `map`,
+Listing 13-14 shows an example of calling the iterator adaptor method `map`,
which takes a closure to call on each item as the items are iterated through.
The `map` method returns a new iterator that produces the modified items. The
closure here creates a new iterator in which each item from the vector will be
diff --git a/src/doc/book/src/ch14-02-publishing-to-crates-io.md b/src/doc/book/src/ch14-02-publishing-to-crates-io.md
index 64885d052..c5b1ac7fc 100644
--- a/src/doc/book/src/ch14-02-publishing-to-crates-io.md
+++ b/src/doc/book/src/ch14-02-publishing-to-crates-io.md
@@ -442,10 +442,15 @@ yank. For example, if we've published a crate named `guessing_game` version
1.0.1 and we want to yank it, in the project directory for `guessing_game` we'd
run:
+<!-- manual-regeneration:
+cargo yank carol-test --version 2.1.0
+cargo yank carol-test --version 2.1.0 --undo
+-->
+
```console
$ cargo yank --vers 1.0.1
Updating crates.io index
- Yank guessing_game:1.0.1
+ Yank guessing_game@1.0.1
```
By adding `--undo` to the command, you can also undo a yank and allow projects
@@ -454,7 +459,7 @@ to start depending on a version again:
```console
$ cargo yank --vers 1.0.1 --undo
Updating crates.io index
- Unyank guessing_game_:1.0.1
+ Unyank guessing_game@1.0.1
```
A yank *does not* delete any code. It cannot, for example, delete accidentally
diff --git a/src/doc/book/src/ch14-03-cargo-workspaces.md b/src/doc/book/src/ch14-03-cargo-workspaces.md
index 942d61b46..7c67331b7 100644
--- a/src/doc/book/src/ch14-03-cargo-workspaces.md
+++ b/src/doc/book/src/ch14-03-cargo-workspaces.md
@@ -224,9 +224,9 @@ copy output below; the output updating script doesn't handle subdirectories in p
```console
$ cargo build
Updating crates.io index
- Downloaded rand v0.8.3
+ Downloaded rand v0.8.5
--snip--
- Compiling rand v0.8.3
+ Compiling rand v0.8.5
Compiling add_one v0.1.0 (file:///projects/add/add_one)
warning: unused import: `rand`
--> add_one/src/lib.rs:1:5
@@ -236,8 +236,7 @@ warning: unused import: `rand`
|
= note: `#[warn(unused_imports)]` on by default
-warning: 1 warning emitted
-
+warning: `add_one` (lib) generated 1 warning
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished dev [unoptimized + debuginfo] target(s) in 10.18s
```
@@ -300,14 +299,14 @@ $ cargo test
Compiling add_one v0.1.0 (file:///projects/add/add_one)
Compiling adder v0.1.0 (file:///projects/add/adder)
Finished test [unoptimized + debuginfo] target(s) in 0.27s
- Running target/debug/deps/add_one-f0253159197f7841
+ Running unittests src/lib.rs (target/debug/deps/add_one-f0253159197f7841)
running 1 test
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
- Running target/debug/deps/adder-49979ff40686fa8e
+ Running unittests src/main.rs (target/debug/deps/adder-49979ff40686fa8e)
running 0 tests
@@ -338,7 +337,7 @@ copy output below; the output updating script doesn't handle subdirectories in p
```console
$ cargo test -p add_one
Finished test [unoptimized + debuginfo] target(s) in 0.00s
- Running target/debug/deps/add_one-b3235fea9a156f74
+ Running unittests src/lib.rs (target/debug/deps/add_one-b3235fea9a156f74)
running 1 test
test tests::it_works ... ok
diff --git a/src/doc/book/src/ch14-04-installing-binaries.md b/src/doc/book/src/ch14-04-installing-binaries.md
index 425cf9c37..fd821f3a0 100644
--- a/src/doc/book/src/ch14-04-installing-binaries.md
+++ b/src/doc/book/src/ch14-04-installing-binaries.md
@@ -31,14 +31,14 @@ cargo install something you don't have, copy relevant output below
```console
$ cargo install ripgrep
Updating crates.io index
- Downloaded ripgrep v11.0.2
+ Downloaded ripgrep v13.0.0
Downloaded 1 crate (243.3 KB) in 0.88s
- Installing ripgrep v11.0.2
+ Installing ripgrep v13.0.0
--snip--
- Compiling ripgrep v11.0.2
+ Compiling ripgrep v13.0.0
Finished release [optimized + debuginfo] target(s) in 3m 10s
Installing ~/.cargo/bin/rg
- Installed package `ripgrep v11.0.2` (executable `rg`)
+ Installed package `ripgrep v13.0.0` (executable `rg`)
```
The second-to-last line of the output shows the location and the name of the
diff --git a/src/doc/book/src/ch15-00-smart-pointers.md b/src/doc/book/src/ch15-00-smart-pointers.md
index 7552dd5d1..9ecdcc835 100644
--- a/src/doc/book/src/ch15-00-smart-pointers.md
+++ b/src/doc/book/src/ch15-00-smart-pointers.md
@@ -12,7 +12,7 @@ pointer but also have additional metadata and capabilities. The concept of
smart pointers isn’t unique to Rust: smart pointers originated in C++ and exist
in other languages as well. Rust has a variety of smart pointers defined in the
standard library that provide functionality beyond that provided by references.
-To explore the general concept, we'll look at a couple of different examples of
+To explore the general concept, we’ll look at a couple of different examples of
smart pointers, including a *reference counting* smart pointer type. This
pointer enables you to allow data to have multiple owners by keeping track of
the number of owners and, when no owners remain, cleaning up the data.
@@ -21,7 +21,7 @@ Rust, with its concept of ownership and borrowing, has an additional difference
between references and smart pointers: while references only borrow data, in
many cases, smart pointers *own* the data they point to.
-Though we didn't call them as such at the time, we’ve already encountered a few
+Though we didn’t call them as such at the time, we’ve already encountered a few
smart pointers in this book, including `String` and `Vec<T>` in Chapter 8. Both
these types count as smart pointers because they own some memory and allow you
to manipulate it. They also have metadata and extra capabilities or guarantees.
@@ -32,7 +32,7 @@ Smart pointers are usually implemented using structs. Unlike an ordinary
struct, smart pointers implement the `Deref` and `Drop` traits. The `Deref`
trait allows an instance of the smart pointer struct to behave like a reference
so you can write your code to work with either references or smart pointers.
-The `Drop` trait allows you to customize the code that's run when an instance
+The `Drop` trait allows you to customize the code that’s run when an instance
of the smart pointer goes out of scope. In this chapter, we’ll discuss both
traits and demonstrate why they’re important to smart pointers.
diff --git a/src/doc/book/src/ch15-01-box.md b/src/doc/book/src/ch15-01-box.md
index 030a7842d..838062552 100644
--- a/src/doc/book/src/ch15-01-box.md
+++ b/src/doc/book/src/ch15-01-box.md
@@ -82,7 +82,7 @@ function”) in Lisp that constructs a new pair from its two arguments. By
calling `cons` on a pair consisting of a value and another pair, we can
construct cons lists made up of recursive pairs.
-For example, here's a pseudocode representation of a cons list containing the
+For example, here’s a pseudocode representation of a cons list containing the
list 1, 2, 3 with each pair in parentheses:
```text
@@ -150,7 +150,7 @@ a recursive enum</span>
The error shows this type “has infinite size.” The reason is that we’ve defined
`List` with a variant that is recursive: it holds another value of itself
directly. As a result, Rust can’t figure out how much space it needs to store a
-`List` value. Let’s break down why we get this error. First, we'll look at how
+`List` value. Let’s break down why we get this error. First, we’ll look at how
Rust decides how much space it needs to store a value of a non-recursive type.
#### Computing the Size of a Non-Recursive Type
@@ -196,7 +196,7 @@ after doing automatic regeneration, look at listings/ch15-smart-pointers/listing
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
|
2 | Cons(i32, Box<List>),
- | ^^^^ ^
+ | ++++ +
```
In this suggestion, “indirection” means that instead of storing a value
diff --git a/src/doc/book/src/ch15-02-deref.md b/src/doc/book/src/ch15-02-deref.md
index ba0b8990f..23c9fe8bf 100644
--- a/src/doc/book/src/ch15-02-deref.md
+++ b/src/doc/book/src/ch15-02-deref.md
@@ -73,11 +73,12 @@ Listing 15-6:
`Box<i32>`</span>
The main difference between Listing 15-7 and Listing 15-6 is that here we set
-`y` to be an instance of a box pointing to a copied value of `x` rather than a
-reference pointing to the value of `x`. In the last assertion, we can use the
-dereference operator to follow the box’s pointer in the same way that we did
-when `y` was a reference. Next, we’ll explore what is special about `Box<T>`
-that enables us to use the dereference operator by defining our own box type.
+`y` to be an instance of a `Box<T>` pointing to a copied value of `x` rather
+than a reference pointing to the value of `x`. In the last assertion, we can
+use the dereference operator to follow the pointer of the `Box<T>` in the same
+way that we did when `y` was a reference. Next, we’ll explore what is special
+about `Box<T>` that enables us to use the dereference operator by defining our
+own type.
### Defining Our Own Smart Pointer
diff --git a/src/doc/book/src/ch15-03-drop.md b/src/doc/book/src/ch15-03-drop.md
index 1ab2b86f0..05ab86873 100644
--- a/src/doc/book/src/ch15-03-drop.md
+++ b/src/doc/book/src/ch15-03-drop.md
@@ -58,7 +58,7 @@ When we run this program, we’ll see the following output:
Rust automatically called `drop` for us when our instances went out of scope,
calling the code we specified. Variables are dropped in the reverse order of
-their creation, so `d` was dropped before `c`. This example's purpose is to
+their creation, so `d` was dropped before `c`. This example’s purpose is to
give you a visual guide to how the `drop` method works; usually you would
specify the cleanup code that your type needs to run rather than a print
message.
diff --git a/src/doc/book/src/ch15-05-interior-mutability.md b/src/doc/book/src/ch15-05-interior-mutability.md
index 74bb02f05..7b5e825d7 100644
--- a/src/doc/book/src/ch15-05-interior-mutability.md
+++ b/src/doc/book/src/ch15-05-interior-mutability.md
@@ -103,11 +103,11 @@ an immutable value and see why that is useful.
#### A Use Case for Interior Mutability: Mock Objects
Sometimes during testing a programmer will use a type in place of another type,
-in order to observe particular behavior and assert it's implemented correctly.
+in order to observe particular behavior and assert it’s implemented correctly.
This placeholder type is called a *test double*. Think of it in the sense of a
-"stunt double" in filmmaking, where a person steps in and substitutes for an
+“stunt double” in filmmaking, where a person steps in and substitutes for an
actor to do a particular tricky scene. Test doubles stand in for other types
-when we're running tests. *Mock objects* are specific types of test doubles
+when we’re running tests. *Mock objects* are specific types of test doubles
that record what happens during a test so you can assert that the correct
actions took place.
@@ -273,7 +273,7 @@ BorrowMutError`. This is how `RefCell<T>` handles violations of the borrowing
rules at runtime.
Choosing to catch borrowing errors at runtime rather than compile time, as
-we've done here, means you'd potentially be finding mistakes in your code later
+we’ve done here, means you’d potentially be finding mistakes in your code later
in the development process: possibly not until your code was deployed to
production. Also, your code would incur a small runtime performance penalty as
a result of keeping track of the borrows at runtime rather than compile time.
diff --git a/src/doc/book/src/ch15-06-reference-cycles.md b/src/doc/book/src/ch15-06-reference-cycles.md
index 4b55d88a6..bef289202 100644
--- a/src/doc/book/src/ch15-06-reference-cycles.md
+++ b/src/doc/book/src/ch15-06-reference-cycles.md
@@ -117,7 +117,7 @@ up if its `strong_count` is 0. You can also create a *weak reference* to the
value within an `Rc<T>` instance by calling `Rc::downgrade` and passing a
reference to the `Rc<T>`. Strong references are how you can share ownership of
an `Rc<T>` instance. Weak references don’t express an ownership relationship,
-and their count doesn't affect when an `Rc<T>` instance is cleaned up. They
+and their count doesn’t affect when an `Rc<T>` instance is cleaned up. They
won’t cause a reference cycle because any cycle involving some weak references
will be broken once the strong reference count of values involved is 0.
diff --git a/src/doc/book/src/ch16-01-threads.md b/src/doc/book/src/ch16-01-threads.md
index 52947a99b..cfdd0c706 100644
--- a/src/doc/book/src/ch16-01-threads.md
+++ b/src/doc/book/src/ch16-01-threads.md
@@ -173,7 +173,7 @@ threads run at the same time.
We'll often use the `move` keyword with closures passed to `thread::spawn`
because the closure will then take ownership of the values it uses from the
environment, thus transferring ownership of those values from one thread to
-another. In the [“Capturing the Environment with Closures”][capture]<!-- ignore
+another. In the [“Capturing References or Moving Ownership”][capture]<!-- ignore
--> section of Chapter 13, we discussed `move` in the context of closures. Now,
we’ll concentrate more on the interaction between `move` and `thread::spawn`.
@@ -278,4 +278,4 @@ ownership rules.
With a basic understanding of threads and the thread API, let’s look at what we
can *do* with threads.
-[capture]: ch13-01-closures.html#capturing-the-environment-with-closures
+[capture]: ch13-01-closures.html#capturing-references-or-moving-ownership
diff --git a/src/doc/book/src/ch16-03-shared-state.md b/src/doc/book/src/ch16-03-shared-state.md
index 41dccfa13..918d162cf 100644
--- a/src/doc/book/src/ch16-03-shared-state.md
+++ b/src/doc/book/src/ch16-03-shared-state.md
@@ -219,9 +219,9 @@ thread update the final result with its part.
Note that if you are doing simple numerical operations, there are types simpler
than `Mutex<T>` types provided by the [`std::sync::atomic` module of the
-standard library][atomic]. These types provide safe, concurrent, atomic access
-to primitive types. We chose to use `Mutex<T>` with a primitive type for this
-example so we could concentrate on how `Mutex<T>` works.
+standard library][atomic]<!-- ignore -->. These types provide safe, concurrent,
+atomic access to primitive types. We chose to use `Mutex<T>` with a primitive
+type for this example so we could concentrate on how `Mutex<T>` works.
### Similarities Between `RefCell<T>`/`Rc<T>` and `Mutex<T>`/`Arc<T>`
diff --git a/src/doc/book/tools/doc-to-md.sh b/src/doc/book/tools/doc-to-md.sh
index cffe4c04b..8c802a71f 100755
--- a/src/doc/book/tools/doc-to-md.sh
+++ b/src/doc/book/tools/doc-to-md.sh
@@ -7,6 +7,15 @@ find tmp -name '*.docx' -print0 | \
# Extract just the filename so we can reuse it easily.
xargs -0 basename -s .docx | \
while IFS= read -r filename; do
+ # Truncate the `nostarch` dir file and put the "no editing" warning back.
+ # Tell shellcheck to ignore this because I want the `/src/` printed
+ # literally, not expanded.
+ # shellcheck disable=SC2016
+ echo '<!-- DO NOT EDIT THIS FILE.
+
+This file is periodically generated from the content in the `/src/`
+directory, so all fixes need to be made in `/src/`.
+-->' > "nostarch/$filename.md"
# Make a directory to put the XML in.
mkdir -p "tmp/$filename"
# Unzip the docx to get at the XML.
@@ -15,6 +24,6 @@ while IFS= read -r filename; do
xsltproc tools/docx-to-md.xsl "tmp/$filename/word/document.xml" | \
# Hard wrap at 80 chars at word bourdaries.
fold -w 80 -s | \
- # Remove trailing whitespace and save in the `nostarch` dir for comparison.
- sed -e "s/ *$//" > "nostarch/$filename.md"
+ # Remove trailing whitespace and append to the file in the `nostarch` dir for comparison.
+ sed -e "s/ *$//" >> "nostarch/$filename.md"
done
diff --git a/src/doc/book/tools/docx-to-md.xsl b/src/doc/book/tools/docx-to-md.xsl
index 637c7a59c..8deec85c9 100644
--- a/src/doc/book/tools/docx-to-md.xsl
+++ b/src/doc/book/tools/docx-to-md.xsl
@@ -12,14 +12,41 @@
<xsl:template match="w:p[starts-with(w:pPr/w:pStyle/@w:val, 'Contents3')]" />
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ChapterStart']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ChapterNumber']" />
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'Normal']" />
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'Standard']" />
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'AuthorQuery']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BookHalfTitle']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BookTitle0']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BookEdition']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BookAuthor']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'Copyright']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'CopyrightHead']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'CopyrightLOC']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ProductionDirective0']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ProductionDirective']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BoxType']" />
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'GraphicSlug']" />
<xsl:template match="w:p[w:pPr[not(w:pStyle)]]" />
+ <xsl:variable name="chapternumber" select="//w:p[w:pPr/w:pStyle/@w:val = 'ChapterNumber']/w:r/w:t" />
+ <xsl:variable name="appendixnumber" select="//w:p[w:pPr/w:pStyle/@w:val = 'AppendixNumber']/w:r/w:t" />
+
<!-- Paragraph styles -->
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'AppendixNumber']" >
+ <xsl:text>&#10;[TOC]&#10;&#10;</xsl:text>
+ <xsl:text>## Appendix </xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>: </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'AppendixTitle']">
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;&#10;</xsl:text>
+ </xsl:template>
+
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ChapterTitle']">
<xsl:text>&#10;[TOC]&#10;&#10;</xsl:text>
<xsl:text># </xsl:text>
@@ -27,11 +54,13 @@
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'HeadA']">
+
+ <xsl:template match="w:p[(w:pPr/w:pStyle/@w:val = 'HeadA' or w:pPr/w:pStyle/@w:val = 'FrontmatterTitle') and w:r/w:t]">
<xsl:text>## </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
+ <xsl:template match="w:p[(w:pPr/w:pStyle/@w:val = 'HeadA' or w:pPr/w:pStyle/@w:val = 'FrontmatterTitle') and not(w:r/w:t)]" />
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'HeadB']">
<xsl:text>### </xsl:text>
@@ -51,10 +80,13 @@
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'NumListA' or @w:val = 'NumListB']]">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'NumListA' or @w:val = 'NumListB' or @w:val = 'ListNumber' or @w:val = 'ListNumber0']]">
<xsl:text>1. </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;</xsl:text>
+ <xsl:if test="not(following-sibling::*[1][self::w:p]) or following-sibling::w:p[1][w:pPr/w:pStyle[@w:val != 'NumListA' and @w:val != 'NumListB' and @w:val != 'ListNumber' and @w:val != 'ListNumber0']]">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
</xsl:template>
<xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'NumListC']]">
@@ -63,10 +95,27 @@
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BulletA' or @w:val = 'BulletB' or @w:val = 'ListPlainA' or @w:val = 'ListPlainB']]">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BulletA' or @w:val = 'BulletB' or @w:val = 'ListPlainA' or @w:val = 'ListPlainB' or @w:val = 'ListBullet' or @w:val = 'ListPlain' or @w:val = 'ListBullet0']]">
<xsl:text>* </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;</xsl:text>
+ <xsl:if test="not(following-sibling::*[1][self::w:p]) or following-sibling::w:p[1][w:pPr/w:pStyle[@w:val != 'BulletA' and @w:val != 'BulletB' and @w:val != 'ListPlainA' and @w:val != 'ListPlainB' and @w:val != 'ListBullet' and @w:val != 'ListPlain' and @w:val != 'ListBullet0']]">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BoxListBullet']]">
+ <xsl:text>> * </xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="following-sibling::w:p[1][w:pPr/w:pStyle[@w:val = 'BoxBody']]">
+ <xsl:text>>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:when test="not(following-sibling::*[1][self::w:p])">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ </xsl:choose>
</xsl:template>
<xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BulletC' or @w:val = 'ListPlainC']]">
@@ -81,7 +130,13 @@
<xsl:text>&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BodyFirst' or @w:val = 'Body' or @w:val = 'BodyFirstBox' or @w:val = 'BodyBox' or @w:val = '1stPara']]">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'CodeLabel']]">
+ <xsl:text>Filename: </xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BodyFirst' or @w:val = 'Body' or @w:val = 'BodyFirstBox' or @w:val = 'BodyBox' or @w:val = '1stPara' or @w:val = 'ChapterIntro' or @w:val = 'BodyContinued' or @w:val = 'SourceForeword']]">
<xsl:if test=".//w:t">
<xsl:apply-templates select="*" />
<xsl:text>&#10;&#10;</xsl:text>
@@ -113,39 +168,172 @@
<xsl:text>&#10;```&#10;&#10;</xsl:text>
</xsl:template>
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'Code' or @w:val = 'CodeWide' or @w:val = 'CodeAnnotated']]">
+ <xsl:if test="not(preceding-sibling::*[1][self::w:p]) or preceding-sibling::w:p[1][w:pPr[not(w:pStyle) or (w:pStyle/@w:val != 'Code' and w:pStyle/@w:val != 'CodeWide' and w:pStyle/@w:val != 'CodeAnnotated')]]">
+ <xsl:text>```&#10;</xsl:text>
+ </xsl:if>
+
+ <!-- Don't apply Emphasis/etc templates in code blocks -->
+ <xsl:for-each select="w:r">
+ <xsl:value-of select="w:t" />
+ </xsl:for-each>
+
+ <xsl:text>&#10;</xsl:text>
+
+ <xsl:if test="not(following-sibling::*[1][self::w:p]) or following-sibling::w:p[1][w:pPr[not(w:pStyle) or (w:pStyle/@w:val != 'Code' and w:pStyle/@w:val != 'CodeWide' and w:pStyle/@w:val != 'CodeAnnotated')]]">
+ <xsl:text>```&#10;&#10;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BoxCode']]">
+ <xsl:choose>
+ <xsl:when test="not(preceding-sibling::*[1][self::w:p]) or preceding-sibling::w:p[1][w:pPr[not(w:pStyle) or w:pStyle/@w:val != 'BoxCode']]">
+ <xsl:text>> ```&#10;> </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:apply-templates select="*" />
+
+ <xsl:choose>
+ <xsl:when test="following-sibling::w:p[1][w:pPr/w:pStyle/@w:val = 'BoxCode']">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:when test="following-sibling::w:p[1][w:pPr/w:pStyle/@w:val = 'BoxBody']">
+ <xsl:text>&#10;> ```&#10;>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;> ```&#10;&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'CodeSingle']">
<xsl:text>```&#10;</xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;```&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'ProductionDirective']">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'TableTitle']]">
+ <xsl:text>Table </xsl:text>
+ <xsl:value-of select="$chapternumber" />
+ <xsl:value-of select="$appendixnumber" />
+ <xsl:text>-</xsl:text>
+ <xsl:number level="any" count="w:p[w:pPr/w:pStyle[@w:val = 'TableTitle']]" />
+ <xsl:text>: </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'Caption' or @w:val = 'TableTitle' or @w:val = 'Caption1' or @w:val = 'Listing']]">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'Caption' or @w:val = 'Caption1' or @w:val = 'Listing' or @w:val = 'CodeListingCaption']]">
+ <xsl:text>Listing </xsl:text>
+ <xsl:value-of select="$chapternumber" />
+ <xsl:value-of select="$appendixnumber" />
+ <xsl:text>-</xsl:text>
+ <xsl:number level="any" count="w:p[w:pPr/w:pStyle[@w:val = 'Caption' or @w:val = 'Caption1' or @w:val = 'Listing' or @w:val = 'CodeListingCaption']]" />
+ <xsl:text>: </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BlockQuote']]">
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BlockQuote' or @w:val = 'QuotePara']]">
<xsl:text>> </xsl:text>
<xsl:apply-templates select="*" />
</xsl:template>
- <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BlockText']]">
- <xsl:text>&#10;</xsl:text>
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BoxTitle']]">
+ <xsl:text>> ### </xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;>&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle[@w:val = 'BlockText' or @w:val = 'BoxBody']]">
<xsl:text>> </xsl:text>
<xsl:apply-templates select="*" />
- <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:choose>
+ <xsl:when test="following-sibling::w:p[1][w:pPr/w:pStyle/@w:val = 'BlockText' or w:pPr/w:pStyle/@w:val = 'BoxBody' or w:pPr/w:pStyle/@w:val = 'BoxListBullet' or w:pPr/w:pStyle/@w:val = 'BoxCode' or w:pPr/w:pStyle/@w:val = 'BoxRunInHead']">
+ <xsl:text>&#10;>&#10;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>&#10;&#10;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
</xsl:template>
<xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'Note']">
- <xsl:text>> </xsl:text>
+ <xsl:text>> Note: </xsl:text>
<xsl:apply-templates select="*" />
<xsl:text>&#10;&#10;</xsl:text>
</xsl:template>
+ <xsl:template match="w:r[w:rPr/w:rStyle/@w:val = 'NoteHead']" />
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'RunInHead']">
+ <xsl:text>* **</xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>**: </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'RunInPara']">
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="following-sibling::w:p[1][w:pPr/w:pStyle/@w:val != 'RunInHead']">
+ <xsl:text>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BoxRunInHead']">
+ <xsl:text>> * **</xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>**: </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'BoxRunInPara']">
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;</xsl:text>
+ <xsl:if test="following-sibling::w:p[1][w:pPr/w:pStyle/@w:val != 'BoxRunInHead']">
+ <xsl:text>>&#10;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="w:p[w:pPr/w:pStyle/@w:val = 'CaptionLine']">
+ <xsl:text>Figure </xsl:text>
+ <xsl:value-of select="$chapternumber" />
+ <xsl:value-of select="$appendixnumber" />
+ <xsl:text>-</xsl:text>
+ <xsl:number level="any" count="w:p[w:pPr/w:pStyle/@w:val = 'CaptionLine']" />
+ <xsl:text>: </xsl:text>
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:tbl">
+ <xsl:apply-templates select="*" />
+ <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:tr[.//w:pStyle/@w:val = 'TableHeader']">
+ <xsl:apply-templates select="*" />
+ <xsl:text>|&#10;</xsl:text>
+ <xsl:for-each select="w:tc">
+ <xsl:text>|---</xsl:text>
+ </xsl:for-each>
+ <xsl:text>|&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:tr">
+ <xsl:apply-templates select="*" />
+ <xsl:text>|&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:tc">
+ <xsl:text>| </xsl:text>
+ <xsl:apply-templates select=".//w:r" />
+ <xsl:text> </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="w:p[not(w:pPr)]" />
<xsl:template match="w:p">
Unmatched: <xsl:value-of select="w:pPr/w:pStyle/@w:val" />
@@ -163,9 +351,13 @@ Unmatched: <xsl:value-of select="w:pPr/w:pStyle/@w:val" />
<xsl:if test="starts-with(w:t, ' ')">
<xsl:text> </xsl:text>
</xsl:if>
- <xsl:text>`</xsl:text>
+ <xsl:if test="not(preceding-sibling::*[1][self::w:r]) or preceding-sibling::w:r[1][not(w:rPr/w:rStyle/@w:val = 'Literal') and not(w:rPr/w:rStyle/@w:val = 'LiteralBold') and not(w:rPr/w:rStyle/@w:val = 'LiteralCaption') and not(w:rPr/w:rStyle/@w:val = 'LiteralBox')]">
+ <xsl:text>`</xsl:text>
+ </xsl:if>
<xsl:value-of select="normalize-space(w:t)" />
- <xsl:text>`</xsl:text>
+ <xsl:if test="not(following-sibling::*[1][self::w:r]) or following-sibling::w:r[1][not(w:rPr/w:rStyle/@w:val = 'Literal') and not(w:rPr/w:rStyle/@w:val = 'LiteralBold') and not(w:rPr/w:rStyle/@w:val = 'LiteralCaption') and not(w:rPr/w:rStyle/@w:val = 'LiteralBox')] or following-sibling::w:r[1][w:rPr/w:rStyle/@w:val = 'Literal' and not(w:t)]">
+ <xsl:text>`</xsl:text>
+ </xsl:if>
<xsl:if test="substring(w:t, string-length(w:t)) = ' '">
<xsl:text> </xsl:text>
</xsl:if>
@@ -176,7 +368,7 @@ Unmatched: <xsl:value-of select="w:pPr/w:pStyle/@w:val" />
</xsl:choose>
</xsl:template>
- <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'EmphasisBold']]">
+ <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'EmphasisBold' or @w:val = 'Bold']]">
<xsl:choose>
<xsl:when test="normalize-space(w:t) != ''">
<xsl:if test="starts-with(w:t, ' ')">
@@ -195,15 +387,41 @@ Unmatched: <xsl:value-of select="w:pPr/w:pStyle/@w:val" />
</xsl:choose>
</xsl:template>
- <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'EmphasisItalic' or @w:val = 'EmphasisItalicBox' or @w:val = 'EmphasisNote' or @w:val = 'EmphasisRevCaption' or @w:val = 'EmphasisRevItal']]">
+ <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'EmphasisItalic' or @w:val = 'EmphasisItalicBox' or @w:val = 'EmphasisNote' or @w:val = 'EmphasisRevCaption' or @w:val = 'EmphasisRevItal' or @w:val = 'Italic' or @w:val = 'LinkURL']]">
+ <xsl:choose>
+ <xsl:when test="w:t and normalize-space(w:t) != ''">
+ <xsl:if test="starts-with(w:t, ' ')">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ <xsl:if test="not(preceding-sibling::*[1][self::w:r]) or preceding-sibling::w:r[1][not(w:t) or not(w:rPr/w:rStyle/@w:val = 'EmphasisItalic') and not(w:rPr/w:rStyle/@w:val = 'EmphasisItalicBox') and not(w:rPr/w:rStyle/@w:val = 'EmphasisNote') and not(w:rPr/w:rStyle/@w:val = 'EmphasisRevCaption') and not(w:rPr/w:rStyle/@w:val = 'EmphasisRevItal') and not(w:rPr/w:rStyle/@w:val = 'Italic') and not(w:rPr/w:rStyle/@w:val = 'LinkURL')]">
+ <xsl:text>*</xsl:text>
+ </xsl:if>
+
+ <xsl:value-of select="normalize-space(w:t)" />
+
+ <xsl:if test="not(following-sibling::*[1][self::w:r]) or following-sibling::w:r[1][not(w:t) or not(w:rPr/w:rStyle/@w:val = 'EmphasisItalic') and not(w:rPr/w:rStyle/@w:val = 'EmphasisItalicBox') and not(w:rPr/w:rStyle/@w:val = 'EmphasisNote') and not(w:rPr/w:rStyle/@w:val = 'EmphasisRevCaption') and not(w:rPr/w:rStyle/@w:val = 'EmphasisRevItal') and not(w:rPr/w:rStyle/@w:val = 'Italic') and not(w:rPr/w:rStyle/@w:val = 'LinkURL')]">
+ <xsl:text>*</xsl:text>
+ </xsl:if>
+
+ <xsl:if test="substring(w:t, string-length(w:t)) = ' '">
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="w:t">
+ <xsl:text> </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'CodeAnnotation']]">
<xsl:choose>
<xsl:when test="normalize-space(w:t) != ''">
<xsl:if test="starts-with(w:t, ' ')">
<xsl:text> </xsl:text>
</xsl:if>
- <xsl:text>*</xsl:text>
+ <xsl:text>[</xsl:text>
<xsl:value-of select="normalize-space(w:t)" />
- <xsl:text>*</xsl:text>
+ <xsl:text>]</xsl:text>
<xsl:if test="substring(w:t, string-length(w:t)) = ' '">
<xsl:text> </xsl:text>
</xsl:if>
@@ -214,6 +432,16 @@ Unmatched: <xsl:value-of select="w:pPr/w:pStyle/@w:val" />
</xsl:choose>
</xsl:template>
+ <xsl:template match="w:r[w:rPr/w:rStyle[@w:val = 'Superscript']]">
+ <xsl:if test="not(preceding-sibling::*[1][self::w:r]) or preceding-sibling::w:r[1][not(w:t) or not(w:rPr/w:rStyle/@w:val = 'Superscript')]">
+ <xsl:text>&lt;sup></xsl:text>
+ </xsl:if>
+ <xsl:value-of select="w:t" />
+ <xsl:if test="not(following-sibling::*[1][self::w:r]) or following-sibling::w:r[1][not(w:t) or not(w:rPr/w:rStyle/@w:val = 'Superscript')]">
+ <xsl:text>&lt;/sup></xsl:text>
+ </xsl:if>
+ </xsl:template>
+
<xsl:template match="w:r">
<xsl:value-of select="w:t" />
</xsl:template>
diff --git a/src/doc/embedded-book/CITATION.bib b/src/doc/embedded-book/CITATION.bib
new file mode 100644
index 000000000..5bcade5af
--- /dev/null
+++ b/src/doc/embedded-book/CITATION.bib
@@ -0,0 +1,7 @@
+@booklet{embedded-rust-book,
+ title = {The Embedded Rust Book},
+ author = {{Rust on Embedded Devices Working Group} and others},
+ date = {}, % intentionally left empty because the book has no 'publication date'
+ url = {https://docs.rust-embedded.org/book/},
+ urldate = {}, % fill this in manually
+}
diff --git a/src/doc/embedded-book/src/start/registers.md b/src/doc/embedded-book/src/start/registers.md
index 09f695a0a..d5bb3e0cc 100644
--- a/src/doc/embedded-book/src/start/registers.md
+++ b/src/doc/embedded-book/src/start/registers.md
@@ -22,7 +22,7 @@ You may well find that the code you need to access the peripherals in your micro
## Board Crate
-A board crate is the perfect starting point, if you're new to embedded Rust. They nicely abstract the HW details that might be overwelming 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.
+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.
diff --git a/src/doc/index.md b/src/doc/index.md
index 744c7f709..bf08960f3 100644
--- a/src/doc/index.md
+++ b/src/doc/index.md
@@ -113,6 +113,12 @@ resources useful.
[The Reference](reference/index.html) is not a formal spec, but is more detailed and
comprehensive than the book.
+## 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 Rustonomicon
[The Rustonomicon](nomicon/index.html) is your guidebook to the dark arts of unsafe
diff --git a/src/doc/nomicon/src/subtyping.md b/src/doc/nomicon/src/subtyping.md
index 91e870e5e..6f0c12db4 100644
--- a/src/doc/nomicon/src/subtyping.md
+++ b/src/doc/nomicon/src/subtyping.md
@@ -252,7 +252,7 @@ type of the referent is shared knowledge, which is why adjusting that type in on
one place (the reference) can lead to issues. But if you shrink down a reference's
lifetime when you hand it to someone, that lifetime information isn't shared in
any way. There are now two independent references with independent lifetimes.
-There's no way to mess with original reference's lifetime using the other one.
+There's no way to mess with the original reference's lifetime using the other one.
Or rather, the only way to mess with someone's lifetime is to build a meowing dog.
But as soon as you try to build a meowing dog, the lifetime should be wrapped up
diff --git a/src/doc/nomicon/src/transmutes.md b/src/doc/nomicon/src/transmutes.md
index 1f6d7d568..eea866859 100644
--- a/src/doc/nomicon/src/transmutes.md
+++ b/src/doc/nomicon/src/transmutes.md
@@ -2,7 +2,7 @@
Get out of our way type system! We're going to reinterpret these bits or die
trying! Even though this book is all about doing things that are unsafe, I
-really can't emphasize that you should deeply think about finding Another Way
+really can't emphasize enough that you should deeply think about finding Another Way
than the operations covered in this section. This is really, truly, the most
horribly unsafe thing you can do in Rust. The guardrails here are dental floss.
diff --git a/src/doc/reference/book.toml b/src/doc/reference/book.toml
index 19b9afc79..9fb3730c8 100644
--- a/src/doc/reference/book.toml
+++ b/src/doc/reference/book.toml
@@ -10,6 +10,8 @@ edit-url-template = "https://github.com/rust-lang/reference/edit/master/{path}"
[output.html.redirect]
"/expressions/enum-variant-expr.html" = "struct-expr.html"
+"/unsafe-blocks.html" = "unsafe-keyword.html"
+"/unsafe-functions.html" = "unsafe-keyword.html"
[rust]
edition = "2021"
diff --git a/src/doc/reference/src/SUMMARY.md b/src/doc/reference/src/SUMMARY.md
index 82d70d043..4d9cc1d76 100644
--- a/src/doc/reference/src/SUMMARY.md
+++ b/src/doc/reference/src/SUMMARY.md
@@ -118,8 +118,7 @@
- [Inline assembly](inline-assembly.md)
- [Unsafety](unsafety.md)
- - [Unsafe functions](unsafe-functions.md)
- - [Unsafe blocks](unsafe-blocks.md)
+ - [The `unsafe` keyword](unsafe-keyword.md)
- [Behavior considered undefined](behavior-considered-undefined.md)
- [Behavior not considered unsafe](behavior-not-considered-unsafe.md)
diff --git a/src/doc/reference/src/attributes.md b/src/doc/reference/src/attributes.md
index 857cd7d72..b7c1ef609 100644
--- a/src/doc/reference/src/attributes.md
+++ b/src/doc/reference/src/attributes.md
@@ -228,6 +228,8 @@ The following is an index of all built-in attributes.
- [`link`] — Specifies a native library to link with an `extern` block.
- [`link_name`] — Specifies the name of the symbol for functions or statics
in an `extern` block.
+ - [`link_ordinal`] — Specifies the ordinal of the symbol for functions or
+ statics in an `extern` block.
- [`no_link`] — Prevents linking an extern crate.
- [`repr`] — Controls type layout.
- [`crate_type`] — Specifies the type of crate (library, executable, etc.).
@@ -297,6 +299,7 @@ The following is an index of all built-in attributes.
[`ignore`]: attributes/testing.md#the-ignore-attribute
[`inline`]: attributes/codegen.md#the-inline-attribute
[`link_name`]: items/external-blocks.md#the-link_name-attribute
+[`link_ordinal`]: items/external-blocks.md#the-link_ordinal-attribute
[`link_section`]: abi.md#the-link_section-attribute
[`link`]: items/external-blocks.md#the-link-attribute
[`macro_export`]: macros-by-example.md#path-based-scope
diff --git a/src/doc/reference/src/attributes/codegen.md b/src/doc/reference/src/attributes/codegen.md
index 4ebabaccf..3a36a10ca 100644
--- a/src/doc/reference/src/attributes/codegen.md
+++ b/src/doc/reference/src/attributes/codegen.md
@@ -347,7 +347,7 @@ trait object whose methods are attributed.
[target architecture]: ../conditional-compilation.md#target_arch
[trait]: ../items/traits.md
[undefined behavior]: ../behavior-considered-undefined.md
-[unsafe function]: ../unsafe-functions.md
+[unsafe function]: ../unsafe-keyword.md
[rust-abi]: ../items/external-blocks.md#abi
[`core::intrinsics::caller_location`]: ../../core/intrinsics/fn.caller_location.html
[`core::panic::Location::caller`]: ../../core/panic/struct.Location.html#method.caller
diff --git a/src/doc/reference/src/attributes/derive.md b/src/doc/reference/src/attributes/derive.md
index b8909ac71..bb5631f7a 100644
--- a/src/doc/reference/src/attributes/derive.md
+++ b/src/doc/reference/src/attributes/derive.md
@@ -24,10 +24,6 @@ impl<T: PartialEq> PartialEq for Foo<T> {
fn eq(&self, other: &Foo<T>) -> bool {
self.a == other.a && self.b == other.b
}
-
- fn ne(&self, other: &Foo<T>) -> bool {
- self.a != other.a || self.b != other.b
- }
}
```
diff --git a/src/doc/reference/src/attributes/diagnostics.md b/src/doc/reference/src/attributes/diagnostics.md
index 1dd9363d8..45f9cc440 100644
--- a/src/doc/reference/src/attributes/diagnostics.md
+++ b/src/doc/reference/src/attributes/diagnostics.md
@@ -184,7 +184,7 @@ Tuple struct fields are ignored.
Here is an example:
```rust
-#[deprecated(since = "5.2", note = "foo was rarely used. Users should instead use bar")]
+#[deprecated(since = "5.2.0", note = "foo was rarely used. Users should instead use bar")]
pub fn foo() {}
pub fn bar() {}
diff --git a/src/doc/reference/src/conditional-compilation.md b/src/doc/reference/src/conditional-compilation.md
index 6966cec4f..97840e4f6 100644
--- a/src/doc/reference/src/conditional-compilation.md
+++ b/src/doc/reference/src/conditional-compilation.md
@@ -191,6 +191,25 @@ Example values:
* `"pc"`
* `"unknown"`
+### `target_has_atomic`
+
+Key-value option set for each bit width that the target supports
+atomic loads, stores, and compare-and-swap operations.
+
+When this cfg is present, all of the stable [`core::sync::atomic`] APIs are available for
+the relevant atomic width.
+
+[`core::sync::atomic`]: ../core/sync/atomic/index.html
+
+Possible values:
+
+* `"8"`
+* `"16"`
+* `"32"`
+* `"64"`
+* `"128"`
+* `"ptr"`
+
### `test`
Enabled when compiling the test harness. Done with `rustc` by using the
diff --git a/src/doc/reference/src/destructors.md b/src/doc/reference/src/destructors.md
index 6d616b3e7..242d9b2db 100644
--- a/src/doc/reference/src/destructors.md
+++ b/src/doc/reference/src/destructors.md
@@ -158,7 +158,7 @@ smallest scope that contains the expression and is one of the following:
* The entire function body.
* A statement.
-* The body of a [`if`], [`while`] or [`loop`] expression.
+* The body of an [`if`], [`while`] or [`loop`] expression.
* The `else` block of an `if` expression.
* The condition expression of an `if` or `while` expression, or a `match`
guard.
diff --git a/src/doc/reference/src/expressions.md b/src/doc/reference/src/expressions.md
index 32ee658ff..b2411cd8e 100644
--- a/src/doc/reference/src/expressions.md
+++ b/src/doc/reference/src/expressions.md
@@ -22,6 +22,7 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MethodCallExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_FieldExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ClosureExpression_]\
+> &nbsp;&nbsp; &nbsp;&nbsp; | [_AsyncBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_ContinueExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_BreakExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_RangeExpression_]\
@@ -34,7 +35,6 @@
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup>[†](#expression-attributes)\
> &nbsp;&nbsp; (\
> &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; [_BlockExpression_]\
-> &nbsp;&nbsp; &nbsp;&nbsp; | [_AsyncBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_UnsafeBlockExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_LoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IfExpression_]\
@@ -42,28 +42,24 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_MatchExpression_]\
> &nbsp;&nbsp; )
-An expression may have two roles: it always produces a *value*, and it may have
-*effects* (otherwise known as "side effects"). An expression *evaluates to* a
-value, and has effects during *evaluation*. Many expressions contain
-sub-expressions, called the *operands* of the expression. The meaning of each
-kind of expression dictates several things:
+An expression may have two roles: it always produces a *value*, and it may have *effects* (otherwise known as "side effects").
+An expression *evaluates to* a value, and has effects during *evaluation*.
+Many expressions contain sub-expressions, called the *operands* of the expression.
+The meaning of each kind of expression dictates several things:
* Whether or not to evaluate the operands when evaluating the expression
* The order in which to evaluate the operands
* How to combine the operands' values to obtain the value of the expression
In this way, the structure of expressions dictates the structure of execution.
-Blocks are just another kind of expression, so blocks, statements, expressions,
-and blocks again can recursively nest inside each other to an arbitrary depth.
+Blocks are just another kind of expression, so blocks, statements, expressions, and blocks again can recursively nest inside each other to an arbitrary depth.
-> **Note**: We give names to the operands of expressions so that we may discuss
-> them, but these names are not stable and may be changed.
+> **Note**: We give names to the operands of expressions so that we may discuss them, but these names are not stable and may be changed.
## Expression precedence
-The precedence of Rust operators and expressions is ordered as follows, going
-from strong to weak. Binary Operators at the same precedence level are grouped
-in the order given by their associativity.
+The precedence of Rust operators and expressions is ordered as follows, going from strong to weak.
+Binary Operators at the same precedence level are grouped in the order given by their associativity.
| Operator/Expression | Associativity |
|-----------------------------|---------------------|
@@ -89,9 +85,8 @@ in the order given by their associativity.
## Evaluation order of operands
-The following list of expressions all evaluate their operands the same way, as
-described after the list. Other expressions either don't take operands or
-evaluate them conditionally as described on their respective pages.
+The following list of expressions all evaluate their operands the same way, as described after the list.
+Other expressions either don't take operands or evaluate them conditionally as described on their respective pages.
* Dereference expression
* Error propagation expression
@@ -113,15 +108,13 @@ evaluate them conditionally as described on their respective pages.
* Range expression
* Return expression
-The operands of these expressions are evaluated prior to applying the effects of
-the expression. Expressions taking multiple operands are evaluated left to right
-as written in the source code.
+The operands of these expressions are evaluated prior to applying the effects of the expression.
+Expressions taking multiple operands are evaluated left to right as written in the source code.
> **Note**: Which subexpressions are the operands of an expression is
> determined by expression precedence as per the previous section.
-For example, the two `next` method calls will always be called in the same
-order:
+For example, the two `next` method calls will always be called in the same order:
```rust
# // Using vec instead of array to avoid references
@@ -134,23 +127,18 @@ assert_eq!(
);
```
-> **Note**: Since this is applied recursively, these expressions are also
-> evaluated from innermost to outermost, ignoring siblings until there are no
-> inner subexpressions.
+> **Note**: Since this is applied recursively, these expressions are also evaluated from innermost to outermost, ignoring siblings until there are no inner subexpressions.
## Place Expressions and Value Expressions
-Expressions are divided into two main categories: place expressions and value
-expressions; there is also a third, minor category of expressions called
-assignee expressions. Within each expression, operands may likewise occur in
-either place context or value context. The evaluation of an expression depends
-both on its own category and the context it occurs within.
+Expressions are divided into two main categories: place expressions and value expressions;
+there is also a third, minor category of expressions called assignee expressions.
+Within each expression, operands may likewise occur in either place context or value context.
+The evaluation of an expression depends both on its own category and the context it occurs within.
-A *place expression* is an expression that represents a memory location. These
-expressions are [paths] which refer to local variables, [static variables],
-[dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`),
-[field] references (`expr.f`) and parenthesized place expressions. All other
-expressions are value expressions.
+A *place expression* is an expression that represents a memory location.
+These expressions are [paths] which refer to local variables, [static variables], [dereferences][deref] (`*expr`), [array indexing] expressions (`expr[expr]`), [field] references (`expr.f`) and parenthesized place expressions.
+All other expressions are value expressions.
A *value expression* is an expression that represents an actual value.
@@ -166,11 +154,10 @@ The following contexts are *place expression* contexts:
expression.
* The base of a [functional update] struct expression.
-> Note: Historically, place expressions were called *lvalues* and value
-> expressions were called *rvalues*.
+> Note: Historically, place expressions were called *lvalues* and value expressions were called *rvalues*.
-An *assignee expression* is an expression that appears in the left operand of an
-[assignment][assign] expression. Explicitly, the assignee expressions are:
+An *assignee expression* is an expression that appears in the left operand of an [assignment][assign] expression.
+Explicitly, the assignee expressions are:
- Place expressions.
- [Underscores][_UnderscoreExpression_].
@@ -185,59 +172,49 @@ Arbitrary parenthesisation is permitted inside assignee expressions.
### Moved and copied types
-When a place expression is evaluated in a value expression context, or is bound
-by value in a pattern, it denotes the value held _in_ that memory location. If
-the type of that value implements [`Copy`], then the value will be copied. In
-the remaining situations, if that type is [`Sized`], then it may be possible to
-move the value. Only the following place expressions may be moved out of:
+When a place expression is evaluated in a value expression context, or is bound by value in a pattern, it denotes the value held _in_ that memory location.
+If the type of that value implements [`Copy`], then the value will be copied.
+In the remaining situations, if that type is [`Sized`], then it may be possible to move the value.
+Only the following place expressions may be moved out of:
* [Variables] which are not currently borrowed.
* [Temporary values](#temporaries).
-* [Fields][field] of a place expression which can be moved out of and
- don't implement [`Drop`].
-* The result of [dereferencing][deref] an expression with type [`Box<T>`] and
- that can also be moved out of.
+* [Fields][field] of a place expression which can be moved out of and don't implement [`Drop`].
+* The result of [dereferencing][deref] an expression with type [`Box<T>`] and that can also be moved out of.
-After moving out of a place expression that evaluates to a local variable, the
-location is deinitialized and cannot be read from again until it is
-reinitialized. In all other cases, trying to use a place expression in a value
-expression context is an error.
+After moving out of a place expression that evaluates to a local variable, the location is deinitialized and cannot be read from again until it is reinitialized.
+In all other cases, trying to use a place expression in a value expression context is an error.
### Mutability
-For a place expression to be [assigned][assign] to, mutably [borrowed][borrow],
-[implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it
-must be _mutable_. We call these *mutable place expressions*. In contrast,
-other place expressions are called *immutable place expressions*.
+For a place expression to be [assigned][assign] to, mutably [borrowed][borrow], [implicitly mutably borrowed], or bound to a pattern containing `ref mut`, it must be _mutable_.
+We call these *mutable place expressions*.
+In contrast, other place expressions are called *immutable place expressions*.
The following expressions can be mutable place expression contexts:
* Mutable [variables] which are not currently borrowed.
* [Mutable `static` items].
* [Temporary values].
-* [Fields][field]: this evaluates the subexpression in a mutable place
- expression context.
+* [Fields][field]: this evaluates the subexpression in a mutable place expression context.
* [Dereferences][deref] of a `*mut T` pointer.
-* Dereference of a variable, or field of a variable, with type `&mut T`. Note:
- This is an exception to the requirement of the next rule.
-* Dereferences of a type that implements `DerefMut`: this then requires that
- the value being dereferenced is evaluated in a mutable place expression context.
-* [Array indexing] of a type that implements `IndexMut`: this
- then evaluates the value being indexed, but not the index, in mutable place
- expression context.
+* Dereference of a variable, or field of a variable, with type `&mut T`.
+ Note: This is an exception to the requirement of the next rule.
+* Dereferences of a type that implements `DerefMut`:
+ this then requires that the value being dereferenced is evaluated in a mutable place expression context.
+* [Array indexing] of a type that implements `IndexMut`:
+ this then evaluates the value being indexed, but not the index, in mutable place expression context.
### Temporaries
-When using a value expression in most place expression contexts, a temporary
-unnamed memory location is created and initialized to that value. The expression
-evaluates to that location instead, except if [promoted] to a `static`. The
-[drop scope] of the temporary is usually the end of the enclosing statement.
+When using a value expression in most place expression contexts, a temporary unnamed memory location is created and initialized to that value.
+The expression evaluates to that location instead, except if [promoted] to a `static`.
+The [drop scope] of the temporary is usually the end of the enclosing statement.
### Implicit Borrows
-Certain expressions will treat an expression as a place expression by implicitly
-borrowing it. For example, it is possible to compare two unsized [slices][slice] for
-equality directly, because the `==` operator implicitly borrows its operands:
+Certain expressions will treat an expression as a place expression by implicitly borrowing it.
+For example, it is possible to compare two unsized [slices][slice] for equality directly, because the `==` operator implicitly borrows its operands:
```rust
# let c = [1, 2, 3];
@@ -264,31 +241,21 @@ Implicit borrows may be taken in the following expressions:
## Overloading Traits
-Many of the following operators and expressions can also be overloaded for
-other types using traits in `std::ops` or `std::cmp`. These traits also
-exist in `core::ops` and `core::cmp` with the same names.
+Many of the following operators and expressions can also be overloaded for other types using traits in `std::ops` or `std::cmp`.
+These traits also exist in `core::ops` and `core::cmp` with the same names.
## Expression Attributes
-[Outer attributes][_OuterAttribute_] before an expression are allowed only in
-a few specific cases:
+[Outer attributes][_OuterAttribute_] before an expression are allowed only in a few specific cases:
* Before an expression used as a [statement].
-* Elements of [array expressions], [tuple expressions], [call expressions],
- and tuple-style [struct] expressions.
- <!--
- These were likely stabilized inadvertently.
- See https://github.com/rust-lang/rust/issues/32796 and
- https://github.com/rust-lang/rust/issues/15701
- -->
+* Elements of [array expressions], [tuple expressions], [call expressions], and tuple-style [struct] expressions.
* The tail expression of [block expressions].
<!-- Keep list in sync with block-expr.md -->
They are never allowed before:
* [Range][_RangeExpression_] expressions.
-* Binary operator expressions ([_ArithmeticOrLogicalExpression_],
- [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_],
- [_AssignmentExpression_], [_CompoundAssignmentExpression_]).
+* Binary operator expressions ([_ArithmeticOrLogicalExpression_], [_ComparisonExpression_], [_LazyBooleanExpression_], [_TypeCastExpression_], [_AssignmentExpression_], [_CompoundAssignmentExpression_]).
[block expressions]: expressions/block-expr.md
diff --git a/src/doc/reference/src/expressions/block-expr.md b/src/doc/reference/src/expressions/block-expr.md
index a68b27e56..bd9c0a623 100644
--- a/src/doc/reference/src/expressions/block-expr.md
+++ b/src/doc/reference/src/expressions/block-expr.md
@@ -103,7 +103,7 @@ Async contexts are established by async blocks as well as the bodies of async fu
Async blocks act like a function boundary, much like closures.
Therefore, the `?` operator and `return` expressions both affect the output of the future, not the enclosing function or other context.
-That is, `return <expr>` from within a closure will return the result of `<expr>` as the output of the future.
+That is, `return <expr>` from within an async block will return the result of `<expr>` as the output of the future.
Similarly, if `<expr>?` propagates an error, that error is propagated as the result of the future.
Finally, the `break` and `continue` keywords cannot be used to branch out from an async block.
@@ -112,7 +112,7 @@ Therefore the following is illegal:
```rust,compile_fail
loop {
async move {
- break; // This would break out of the loop.
+ break; // error[E0267]: `break` inside of an `async` block
}
}
```
@@ -140,6 +140,10 @@ unsafe {
let a = unsafe { an_unsafe_fn() };
```
+## Labelled block expressions
+
+Labelled block expressions are documented in the [Loops and other breakable expressions] section.
+
## Attributes on block expressions
[Inner attributes] are allowed directly after the opening brace of a block expression in the following situations:
@@ -189,3 +193,4 @@ fn is_unix_platform() -> bool {
[tuple expressions]: tuple-expr.md
[unsafe operations]: ../unsafety.md
[value expressions]: ../expressions.md#place-expressions-and-value-expressions
+[Loops and other breakable expressions]: loop-expr.md#labelled-block-expressions
diff --git a/src/doc/reference/src/expressions/closure-expr.md b/src/doc/reference/src/expressions/closure-expr.md
index bdc177bb5..103f74795 100644
--- a/src/doc/reference/src/expressions/closure-expr.md
+++ b/src/doc/reference/src/expressions/closure-expr.md
@@ -12,7 +12,7 @@
> _ClosureParam_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> [_PatternNoTopAlt_]&nbsp;( `:` [_Type_] )<sup>?</sup>
-A *closure expression*, also know as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
+A *closure expression*, also known as a lambda expression or a lambda, defines a [closure type] and evaluates to a value of that type.
The syntax for a closure expression is an optional `move` keyword, then a pipe-symbol-delimited (`|`) comma-separated list of [patterns], called the *closure parameters* each optionally followed by a `:` and a type, then an optional `->` and type, called the *return type*, and then an expression, called the *closure body operand*.
The optional type after each pattern is a type annotation for the pattern.
If there is a return type, the closure body must be a [block].
diff --git a/src/doc/reference/src/expressions/grouped-expr.md b/src/doc/reference/src/expressions/grouped-expr.md
index 0ff7e2c90..1ae2209c5 100644
--- a/src/doc/reference/src/expressions/grouped-expr.md
+++ b/src/doc/reference/src/expressions/grouped-expr.md
@@ -16,8 +16,8 @@ Parentheses can be used to explicitly modify the precedence order of subexpressi
An example of a parenthesized expression:
```rust
-let x: i32 = 2 + 3 * 4;
-let y: i32 = (2 + 3) * 4;
+let x: i32 = 2 + 3 * 4; // not parenthesized
+let y: i32 = (2 + 3) * 4; // parenthesized
assert_eq!(x, 14);
assert_eq!(y, 20);
```
diff --git a/src/doc/reference/src/expressions/loop-expr.md b/src/doc/reference/src/expressions/loop-expr.md
index 308f3e346..204207ee0 100644
--- a/src/doc/reference/src/expressions/loop-expr.md
+++ b/src/doc/reference/src/expressions/loop-expr.md
@@ -1,4 +1,4 @@
-# Loops
+# Loops and other breakable expressions
> **<sup>Syntax</sup>**\
> _LoopExpression_ :\
@@ -7,6 +7,7 @@
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicateLoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_PredicatePatternLoopExpression_]\
> &nbsp;&nbsp; &nbsp;&nbsp; | [_IteratorLoopExpression_]\
+> &nbsp;&nbsp; &nbsp;&nbsp; | [_LabelBlockExpression_]\
> &nbsp;&nbsp; )
[_LoopLabel_]: #loop-labels
@@ -14,16 +15,19 @@
[_PredicateLoopExpression_]: #predicate-loops
[_PredicatePatternLoopExpression_]: #predicate-pattern-loops
[_IteratorLoopExpression_]: #iterator-loops
+[_LabelBlockExpression_]: #labelled-block-expressions
-Rust supports four loop expressions:
+Rust supports five loop expressions:
* A [`loop` expression](#infinite-loops) denotes an infinite loop.
* A [`while` expression](#predicate-loops) loops until a predicate is false.
* A [`while let` expression](#predicate-pattern-loops) tests a pattern.
* A [`for` expression](#iterator-loops) extracts values from an iterator, looping until the iterator is empty.
+* A [labelled block expression](#labelled-block-expressions) runs a loop exactly once, but allows exiting the loop early with `break`.
-All four types of loop support [`break` expressions](#break-expressions), [`continue` expressions](#continue-expressions), and [labels](#loop-labels).
-Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values).
+All five types of loop support [`break` expressions](#break-expressions), and [labels](#loop-labels).
+All except labelled block expressions support [`continue` expressions](#continue-expressions).
+Only `loop` and labelled block expressions support [evaluation to non-trivial values](#break-and-loop-values).
## Infinite loops
@@ -193,6 +197,18 @@ A loop expression may optionally have a _label_. The label is written as a lifet
If a label is present, then labeled `break` and `continue` expressions nested within this loop may exit out of this loop or return control to its head.
See [break expressions](#break-expressions) and [continue expressions](#continue-expressions).
+Labels follow the hygiene and shadowing rules of local variables. For example, this code will print "outer loop":
+
+```rust
+'a: loop {
+ 'a: loop {
+ break 'a;
+ }
+ print!("outer loop");
+ break 'a;
+}
+```
+
## `break` expressions
> **<sup>Syntax</sup>**\
@@ -226,6 +242,16 @@ Example:
A `break` expression is only permitted in the body of a loop, and has one of the forms `break`, `break 'label` or ([see below](#break-and-loop-values)) `break EXPR` or `break 'label EXPR`.
+## Labelled block expressions
+
+> **<sup>Syntax</sup>**\
+> _LabelBlockExpression_ :\
+> &nbsp;&nbsp; [_BlockExpression_]
+
+Labelled block expressions are exactly like block expressions, except that they allow using `break` expressions within the block.
+Unlike other loops, `break` expressions within a label expression *must* have a label (i.e. the label is not optional).
+Unlike other loops, labelled block expressions *must* begin with a label.
+
## `continue` expressions
> **<sup>Syntax</sup>**\
diff --git a/src/doc/reference/src/identifiers.md b/src/doc/reference/src/identifiers.md
index a4e972cd3..c760f6826 100644
--- a/src/doc/reference/src/identifiers.md
+++ b/src/doc/reference/src/identifiers.md
@@ -13,7 +13,7 @@
> NON_KEYWORD_IDENTIFIER | RAW_IDENTIFIER
<!-- When updating the version, update the UAX links, too. -->
-Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 13.0, with the additions described below. Some examples of identifiers:
+Identifiers follow the specification in [Unicode Standard Annex #31][UAX31] for Unicode version 15.0, with the additions described below. Some examples of identifiers:
* `foo`
* `_identifier`
@@ -68,5 +68,5 @@ keyword except the ones listed above for `RAW_IDENTIFIER`.
[proc-macro]: procedural-macros.md
[reserved]: keywords.md#reserved-keywords
[strict]: keywords.md#strict-keywords
-[UAX15]: https://www.unicode.org/reports/tr15/tr15-50.html
-[UAX31]: https://www.unicode.org/reports/tr31/tr31-33.html
+[UAX15]: https://www.unicode.org/reports/tr15/tr15-53.html
+[UAX31]: https://www.unicode.org/reports/tr31/tr31-37.html
diff --git a/src/doc/reference/src/inline-assembly.md b/src/doc/reference/src/inline-assembly.md
index 6233475a3..996b157da 100644
--- a/src/doc/reference/src/inline-assembly.md
+++ b/src/doc/reference/src/inline-assembly.md
@@ -123,12 +123,17 @@ Several types of operands are supported:
* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`
- Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`).
- You should only write to the register after all inputs are read, otherwise you may clobber an input.
+* `sym <path>`
+ - `<path>` must refer to a `fn` or `static`.
+ - A mangled symbol name referring to the item is substituted into the asm template string.
+ - The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
+ - `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
Operand expressions are evaluated from left to right, just like function call arguments.
After the `asm!` has executed, outputs are written to in left to right order.
This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
-Since `global_asm!` exists outside a function, it cannot use input/output operands.
+Since `global_asm!` exists outside a function, it can only use `sym` operands.
## Register operands
diff --git a/src/doc/reference/src/items/associated-items.md b/src/doc/reference/src/items/associated-items.md
index f5dc31aae..2401127b5 100644
--- a/src/doc/reference/src/items/associated-items.md
+++ b/src/doc/reference/src/items/associated-items.md
@@ -205,22 +205,49 @@ types cannot be defined in [inherent implementations] nor can they be given a
default implementation in traits.
An *associated type declaration* declares a signature for associated type
-definitions. It is written as `type`, then an [identifier], and
-finally an optional list of trait bounds.
+definitions. It is written in one of the following forms, where `Assoc` is the
+name of the associated type, `Params` is a comma-separated list of type,
+lifetime or const parameters, `Bounds` is a plus-separated list of trait bounds
+that the associated type must meet, and `WhereBounds` is a comma-separated list
+of bounds that the parameters must meet:
+
+<!-- ignore: illustrative example forms -->
+```rust,ignore
+type Assoc;
+type Assoc: Bounds;
+type Assoc<Params>;
+type Assoc<Params>: Bounds;
+type Assoc<Params> where WhereBounds;
+type Assoc<Params>: Bounds where WhereBounds;
+```
The identifier is the name of the declared type alias. The optional trait bounds
must be fulfilled by the implementations of the type alias.
There is an implicit [`Sized`] bound on associated types that can be relaxed using the special `?Sized` bound.
-An *associated type definition* defines a type alias on another type. It is
-written as `type`, then an [identifier], then an `=`, and finally a [type].
+An *associated type definition* defines a type alias for the implementation
+of a trait on a type. They are written similarly to an *associated type declaration*,
+but cannot contain `Bounds`, but instead must contain a `Type`:
+
+<!-- ignore: illustrative example forms -->
+```rust,ignore
+type Assoc = Type;
+type Assoc<Params> = Type; // the type `Type` here may reference `Params`
+type Assoc<Params> = Type where WhereBounds;
+type Assoc<Params> where WhereBounds = Type; // deprecated, prefer the form above
+```
If a type `Item` has an associated type `Assoc` from a trait `Trait`, then
`<Item as Trait>::Assoc` is a type that is an alias of the type specified in the
associated type definition. Furthermore, if `Item` is a type parameter, then
`Item::Assoc` can be used in type parameters.
-Associated types must not include [generic parameters] or [where clauses].
+Associated types may include [generic parameters] and [where clauses]; these are
+often referred to as *generic associated types*, or *GATs*. If the type `Thing`
+has an associated type `Item` from a trait `Trait` with the generics `<'a>` , the
+type can be named like `<Thing as Trait>::Item<'x>`, where `'x` is some lifetime
+in scope. In this case, `'x` will be used wherever `'a` appears in the associated
+type definitions on impls.
```rust
trait AssociatedType {
@@ -249,6 +276,37 @@ fn main() {
}
```
+An example of associated types with generics and where clauses:
+
+```rust
+struct ArrayLender<'a, T>(&'a mut [T; 16]);
+
+trait Lend {
+ // Generic associated type declaration
+ type Lender<'a> where Self: 'a;
+ fn lend<'a>(&'a mut self) -> Self::Lender<'a>;
+}
+
+impl<T> Lend for [T; 16] {
+ // Generic associated type definition
+ type Lender<'a> = ArrayLender<'a, T> where Self: 'a;
+
+ fn lend<'a>(&'a mut self) -> Self::Lender<'a> {
+ ArrayLender(self)
+ }
+}
+
+fn borrow<'a, T: Lend>(array: &'a mut T) -> <T as Lend>::Lender<'a> {
+ array.lend()
+}
+
+
+fn main() {
+ let mut array = [0usize; 16];
+ let lender = borrow(&mut array);
+}
+```
+
### Associated Types Container Example
Consider the following example of a `Container` trait. Notice that the type is
@@ -279,6 +337,83 @@ impl<T> Container for Vec<T> {
}
```
+### Relationship between `Bounds` and `WhereBounds`
+
+In this example:
+
+```rust
+# use std::fmt::Debug;
+trait Example {
+ type Output<T>: Ord where T: Debug;
+}
+```
+
+Given a reference to the associated type like `<X as Example>::Output<Y>`, the associated type itself must be `Ord`, and the type `Y` must be `Debug`.
+
+### Required where clauses on generic associated types
+
+Generic associated type declarations on traits currently may require a list of
+where clauses, dependent on functions in the trait and how the GAT is used. These
+rules may be loosened in the future; updates can be found [on the generic
+associated types initiative repository](https://rust-lang.github.io/generic-associated-types-initiative/explainer/required_bounds.html).
+
+In a few words, these where clauses are required in order to maximize the allowed
+definitions of the associated type in impls. To do this, any clauses that *can be
+proven to hold* on functions (using the parameters of the function or trait)
+where a GAT appears as an input or output must also be written on the GAT itself.
+
+```rust
+trait LendingIterator {
+ type Item<'x> where Self: 'x;
+ fn next<'a>(&'a mut self) -> Self::Item<'a>;
+}
+```
+
+In the above, on the `next` function, we can prove that `Self: 'a`, because of
+the implied bounds from `&'a mut self`; therefore, we must write the equivalent
+bound on the GAT itself: `where Self: 'x`.
+
+When there are multiple functions in a trait that use the GAT, then the
+*intersection* of the bounds from the different functions are used, rather than
+the union.
+
+```rust
+trait Check<T> {
+ type Checker<'x>;
+ fn create_checker<'a>(item: &'a T) -> Self::Checker<'a>;
+ fn do_check(checker: Self::Checker<'_>);
+}
+```
+
+In this example, no bounds are required on the `type Checker<'a>;`. While we
+know that `T: 'a` on `create_checker`, we do not know that on `do_check`. However,
+if `do_check` was commented out, then the `where T: 'x` bound would be required
+on `Checker`.
+
+The bounds on associated types also propagate required where clauses.
+
+```rust
+trait Iterable {
+ type Item<'a> where Self: 'a;
+ type Iterator<'a>: Iterator<Item = Self::Item<'a>> where Self: 'a;
+ fn iter<'a>(&'a self) -> Self::Iterator<'a>;
+}
+```
+
+Here, `where Self: 'a` is required on `Item` because of `iter`. However, `Item`
+is used in the bounds of `Iterator`, the `where Self: 'a` clause is also required
+there.
+
+Finally, any explicit uses of `'static` on GATs in the trait do not count towards
+the required bounds.
+
+```rust
+trait StaticReturn {
+ type Y<'a>;
+ fn foo(&self) -> Self::Y<'static>;
+}
+```
+
## Associated Constants
*Associated constants* are [constants] associated with a type.
diff --git a/src/doc/reference/src/items/external-blocks.md b/src/doc/reference/src/items/external-blocks.md
index e768a1502..c91e1d10c 100644
--- a/src/doc/reference/src/items/external-blocks.md
+++ b/src/doc/reference/src/items/external-blocks.md
@@ -122,6 +122,9 @@ specifies the kind of library with the following possible values:
- `static` — Indicates a static library.
- `framework` — Indicates a macOS framework. This is only valid for macOS
targets.
+- `raw-dylib` — Indicates a dynamic library where the compiler will generate
+ an import library to link against (see [`dylib` versus `raw-dylib`] below
+ for details). This is only valid for Windows targets.
The `name` key must be included if `kind` is specified.
@@ -198,9 +201,26 @@ The default for this modifier is `-whole-archive`.
More implementation details about this modifier can be found in
[`whole-archive` documentation for rustc].
+#### `dylib` versus `raw-dylib`
+
+On Windows, linking against a dynamic library requires that an import library
+is provided to the linker: this is a special static library that declares all
+of the symbols exported by the dynamic library in such a way that the linker
+knows that they have to be dynamically loaded at runtime.
+
+Specifying `kind = "dylib"` instructs the Rust compiler to link an import
+library based on the `name` key. The linker will then use its normal library
+resolution logic to find that import library. Alternatively, specifying
+`kind = "raw-dylib"` instructs the compiler to generate an import library
+during compilation and provide that to the linker instead.
+
+`raw-dylib` is only supported on Windows and not supported on 32-bit x86
+(`target_arch="x86"`). Using it when targeting other platforms or
+x86 on Windows will result in a compiler error.
+
### The `link_name` attribute
-The `link_name` attribute may be specified on declarations inside an `extern`
+The *`link_name` attribute* may be specified on declarations inside an `extern`
block to indicate the symbol to import for the given function or static. It
uses the [_MetaNameValueStr_] syntax to specify the name of the symbol.
@@ -211,6 +231,41 @@ extern {
}
```
+Using this attribute with the `link_ordinal` attribute will result in a
+compiler error.
+
+### The `link_ordinal` attribute
+
+The *`link_ordinal` attribute* can be applied on declarations inside an `extern`
+block to indicate the numeric ordinal to use when generating the import library
+to link against. An ordinal is a unique number per symbol exported by a dynamic
+library on Windows and can be used when the library is being loaded to find
+that symbol rather than having to look it up by name.
+
+<div class="warning">
+
+Warning: `link_ordinal` should only be used in cases where the ordinal of the
+symbol is known to be stable: if the ordinal of a symbol is not explicitly set
+when its containing binary is built then one will be automatically assigned to
+it, and that assigned ordinal may change between builds of the binary.
+
+</div>
+
+<!-- ignore: Only works on x86 Windows -->
+```rust,ignore
+#[link(name = "exporter", kind = "raw-dylib")]
+extern "stdcall" {
+ #[link_ordinal(15)]
+ fn imported_function_stdcall(i: i32);
+}
+```
+
+This attribute is only used with the `raw-dylib` linking kind.
+Using any other kind will result in a compiler error.
+
+Using this attribute with the `link_name` attribute will result in a
+compiler error.
+
### Attributes on function parameters
Attributes on extern function parameters follow the same rules and
@@ -233,3 +288,4 @@ restrictions as [regular function parameters].
[regular function parameters]: functions.md#attributes-on-function-parameters
[`bundle` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-bundle
[`whole-archive` documentation for rustc]: ../../rustc/command-line-arguments.html#linking-modifiers-whole-archive
+[`dylib` versus `raw-dylib`]: #dylib-versus-raw-dylib
diff --git a/src/doc/reference/src/items/functions.md b/src/doc/reference/src/items/functions.md
index 325588a53..5b4ac7af6 100644
--- a/src/doc/reference/src/items/functions.md
+++ b/src/doc/reference/src/items/functions.md
@@ -59,8 +59,8 @@ fn answer_to_life_the_universe_and_everything() -> i32 {
## Function parameters
-As with `let` bindings, function parameters are irrefutable [patterns], so any
-pattern that is valid in a let binding is also valid as a parameter:
+Function parameters are irrefutable [patterns], so any pattern that is valid in
+an else-less `let` binding is also valid as a parameter:
```rust
fn first((value, _): (i32, i32)) -> i32 { value }
diff --git a/src/doc/reference/src/items/traits.md b/src/doc/reference/src/items/traits.md
index 26870a0fc..3c5d31d5c 100644
--- a/src/doc/reference/src/items/traits.md
+++ b/src/doc/reference/src/items/traits.md
@@ -70,6 +70,7 @@ Object safe traits can be the base trait of a [trait object]. A trait is
* All [supertraits] must also be object safe.
* `Sized` must not be a [supertrait][supertraits]. In other words, it must not require `Self: Sized`.
* It must not have any associated constants.
+* It must not have any associated types with generics.
* All associated functions must either be dispatchable from a trait object or be explicitly non-dispatchable:
* Dispatchable functions require:
* Not have any type parameters (although lifetime parameters are allowed),
diff --git a/src/doc/reference/src/items/type-aliases.md b/src/doc/reference/src/items/type-aliases.md
index ff0cc75f7..d2e14b903 100644
--- a/src/doc/reference/src/items/type-aliases.md
+++ b/src/doc/reference/src/items/type-aliases.md
@@ -4,7 +4,7 @@
> _TypeAlias_ :\
> &nbsp;&nbsp; `type` [IDENTIFIER]&nbsp;[_GenericParams_]<sup>?</sup>
> ( `:` [_TypeParamBounds_] )<sup>?</sup>
-> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] )<sup>?</sup> `;`
+> [_WhereClause_]<sup>?</sup> ( `=` [_Type_] [_WhereClause_]<sup>?</sup>)<sup>?</sup> `;`
A _type alias_ defines a new name for an existing [type]. Type aliases are
declared with the keyword `type`. Every value has a single, specific type, but
@@ -31,11 +31,18 @@ let _ = UseAlias(5); // OK
let _ = TypeAlias(5); // Doesn't work
```
-A type alias without the [_Type_] specification may only appear as an
-[associated type] in a [trait].
+A type alias, when not used as an associated type, must include a [_Type_] and
+may not include [_TypeParamBounds_].
-A type alias with [_TypeParamBounds_] may only specified when used as
-an [associated type] in a [trait].
+A type alias, when used as an [associated type] in a [trait], must not include a
+[_Type_] specification but may include [_TypeParamBounds_].
+
+A type alias, when used as an [associated type] in a [trait impl], must include
+a [_Type_] specification and may not include [_TypeParamBounds_].
+
+Where clauses before the equals sign on a type alias in a [trait impl] (like
+`type TypeAlias<T> where T: Foo = Bar<T>`) are deprecated. Where clauses after
+the equals sign (like `type TypeAlias<T> = Bar<T> where T: Foo`) are preferred.
[IDENTIFIER]: ../identifiers.md
[_GenericParams_]: generics.md
@@ -45,3 +52,4 @@ an [associated type] in a [trait].
[associated type]: associated-items.md#associated-types
[trait]: traits.md
[type]: ../types.md
+[trait impl]: implementations.md#trait-implementations
diff --git a/src/doc/reference/src/patterns.md b/src/doc/reference/src/patterns.md
index 5c81ecd87..14bbac155 100644
--- a/src/doc/reference/src/patterns.md
+++ b/src/doc/reference/src/patterns.md
@@ -22,18 +22,16 @@
> &nbsp;&nbsp; | [_PathPattern_]\
> &nbsp;&nbsp; | [_MacroInvocation_]
-Patterns are used to match values against structures and to,
-optionally, bind variables to values inside these structures. They are also
-used in variable declarations and parameters for functions and closures.
+Patterns are used to match values against structures and to, optionally, bind variables to values inside these structures.
+They are also used in variable declarations and parameters for functions and closures.
The pattern in the following example does four things:
* Tests if `person` has the `car` field filled with something.
-* Tests if the person's `age` field is between 13 and 19, and binds its value to
- the `person_age` variable.
+* Tests if the person's `age` field is between 13 and 19, and binds its value to the `person_age` variable.
* Binds a reference to the `name` field to the variable `person_name`.
-* Ignores the rest of the fields of `person`. The remaining fields can have any value and
- are not bound to any variables.
+* Ignores the rest of the fields of `person`.
+ The remaining fields can have any value and are not bound to any variables.
```rust
# struct Car;
@@ -65,8 +63,7 @@ if let
Patterns are used in:
* [`let` declarations](statements.md#let-statements)
-* [Function](items/functions.md) and [closure](expressions/closure-expr.md)
- parameters
+* [Function](items/functions.md) and [closure](expressions/closure-expr.md) parameters
* [`match` expressions](expressions/match-expr.md)
* [`if let` expressions](expressions/if-expr.md)
* [`while let` expressions](expressions/loop-expr.md#predicate-pattern-loops)
@@ -75,13 +72,10 @@ Patterns are used in:
## Destructuring
Patterns can be used to *destructure* [structs], [enums], and [tuples].
-Destructuring breaks up a value into its component pieces. The syntax used is
-almost the same as when creating such values. In a pattern whose [scrutinee]
-expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands
-in for a *single* data field, whereas a wildcard `..` stands in for *all* the
-remaining fields of a particular variant. When destructuring a data structure
-with named (but not numbered) fields, it is allowed to write `fieldname` as a
-shorthand for `fieldname: fieldname`.
+Destructuring breaks up a value into its component pieces.
+The syntax used is almost the same as when creating such values.
+In a pattern whose [scrutinee] expression has a `struct`, `enum` or `tuple` type, a placeholder (`_`) stands in for a *single* data field, whereas a wildcard `..` stands in for *all* the remaining fields of a particular variant.
+When destructuring a data structure with named (but not numbered) fields, it is allowed to write `fieldname` as a shorthand for `fieldname: fieldname`.
```rust
# enum Message {
@@ -104,9 +98,9 @@ match message {
## Refutability
-A pattern is said to be *refutable* when it has the possibility of not being matched
-by the value it is being matched against. *Irrefutable* patterns, on the other hand,
-always match the value they are being matched against. Examples:
+A pattern is said to be *refutable* when it has the possibility of not being matched by the value it is being matched against.
+*Irrefutable* patterns, on the other hand, always match the value they are being matched against.
+Examples:
```rust
let (x, y) = (1, 2); // "(x, y)" is an irrefutable pattern
@@ -141,16 +135,12 @@ if let (a, 3) = (1, 2) { // "(a, 3)" is refutable, and will not match
[INTEGER_LITERAL]: tokens.md#integer-literals
[FLOAT_LITERAL]: tokens.md#floating-point-literals
-_Literal patterns_ match exactly the same value as what is created by the
-literal. Since negative numbers are not [literals], literal patterns also
-accept an optional minus sign before the literal, which acts like the negation
-operator.
+_Literal patterns_ match exactly the same value as what is created by the literal.
+Since negative numbers are not [literals], literal patterns also accept an optional minus sign before the literal, which acts like the negation operator.
<div class="warning">
-Floating-point literals are currently accepted, but due to the complexity of comparing
-them, they are going to be forbidden on literal patterns in a future version of Rust (see
-[issue #41620](https://github.com/rust-lang/rust/issues/41620)).
+Floating-point literals are currently accepted, but due to the complexity of comparing them, they are going to be forbidden on literal patterns in a future version of Rust (see [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
</div>
@@ -175,14 +165,13 @@ for i in -2..5 {
> _IdentifierPattern_ :\
> &nbsp;&nbsp; &nbsp;&nbsp; `ref`<sup>?</sup> `mut`<sup>?</sup> [IDENTIFIER] (`@` [_PatternNoTopAlt_] ) <sup>?</sup>
-Identifier patterns bind the value they match to a variable. The identifier
-must be unique within the pattern. The variable will shadow any variables of
-the same name in scope. The scope of the new binding depends on the context of
-where the pattern is used (such as a `let` binding or a `match` arm).
+Identifier patterns bind the value they match to a variable.
+The identifier must be unique within the pattern.
+The variable will shadow any variables of the same name in scope.
+The scope of the new binding depends on the context of where the pattern is used (such as a `let` binding or a `match` arm).
-Patterns that consist of only an identifier, possibly with a `mut`, match any value and
-bind it to that identifier. This is the most commonly used pattern in variable
-declarations and parameters for functions and closures.
+Patterns that consist of only an identifier, possibly with a `mut`, match any value and bind it to that identifier.
+This is the most commonly used pattern in variable declarations and parameters for functions and closures.
```rust
let mut variable = 10;
@@ -191,9 +180,8 @@ fn sum(x: i32, y: i32) -> i32 {
# }
```
-To bind the matched value of a pattern to a variable, use the syntax `variable @
-subpattern`. For example, the following binds the value 2 to `e` (not the
-entire range: the range here is a range subpattern).
+To bind the matched value of a pattern to a variable, use the syntax `variable @ subpattern`.
+For example, the following binds the value 2 to `e` (not the entire range: the range here is a range subpattern).
```rust
let x = 2;
@@ -204,10 +192,8 @@ match x {
}
```
-By default, identifier patterns bind a variable to a copy of or move from the
-matched value depending on whether the matched value implements [`Copy`].
-This can be changed to bind to a reference by using the `ref` keyword,
-or to a mutable reference using `ref mut`. For example:
+By default, identifier patterns bind a variable to a copy of or move from the matched value depending on whether the matched value implements [`Copy`].
+This can be changed to bind to a reference by using the `ref` keyword, or to a mutable reference using `ref mut`. For example:
```rust
# let a = Some(10);
@@ -222,10 +208,10 @@ match a {
}
```
-In the first match expression, the value is copied (or moved). In the second match,
-a reference to the same memory location is bound to the variable value. This syntax is
-needed because in destructuring subpatterns the `&` operator can't be applied to
-the value's fields. For example, the following is not valid:
+In the first match expression, the value is copied (or moved).
+In the second match, a reference to the same memory location is bound to the variable value.
+This syntax is needed because in destructuring subpatterns the `&` operator can't be applied to the value's fields.
+For example, the following is not valid:
```rust,compile_fail
# struct Person {
@@ -247,21 +233,18 @@ To make it valid, write the following:
if let Person {name: ref person_name, age: 18..=150 } = value { }
```
-Thus, `ref` is not something that is being matched against. Its objective is
-exclusively to make the matched binding a reference, instead of potentially
-copying or moving what was matched.
+Thus, `ref` is not something that is being matched against.
+Its objective is exclusively to make the matched binding a reference, instead of potentially copying or moving what was matched.
-[Path patterns](#path-patterns) take precedence over identifier patterns. It is an error
-if `ref` or `ref mut` is specified and the identifier shadows a constant.
+[Path patterns](#path-patterns) take precedence over identifier patterns.
+It is an error if `ref` or `ref mut` is specified and the identifier shadows a constant.
-Identifier patterns are irrefutable if the `@` subpattern is irrefutable or
-the subpattern is not specified.
+Identifier patterns are irrefutable if the `@` subpattern is irrefutable or the subpattern is not specified.
### Binding modes
-To service better ergonomics, patterns operate in different *binding modes* in
-order to make it easier to bind references to values. When a reference value is matched by
-a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding.
+To service better ergonomics, patterns operate in different *binding modes* in order to make it easier to bind references to values.
+When a reference value is matched by a non-reference pattern, it will be automatically treated as a `ref` or `ref mut` binding.
Example:
```rust
@@ -271,26 +254,22 @@ if let Some(y) = x {
}
```
-*Non-reference patterns* include all patterns except bindings, [wildcard
-patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types,
-and [reference patterns](#reference-patterns).
-
-If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the
-*default binding mode* to determine how the variable is bound. The default binding
-mode starts in "move" mode which uses move semantics. When matching a pattern, the
-compiler starts from the outside of the pattern and works inwards. Each time a reference
-is matched using a non-reference pattern, it will automatically dereference the value and
-update the default binding mode. References will set the default binding mode to `ref`.
-Mutable references will set the mode to `ref mut` unless the mode is already `ref` in
-which case it remains `ref`. If the automatically dereferenced value is still a reference,
-it is dereferenced and this process repeats.
-
-Move bindings and reference bindings can be mixed together in the same pattern, doing so will
-result in partial move of the object bound to and the object cannot be used afterwards.
+*Non-reference patterns* include all patterns except bindings, [wildcard patterns](#wildcard-pattern) (`_`), [`const` patterns](#path-patterns) of reference types, and [reference patterns](#reference-patterns).
+
+If a binding pattern does not explicitly have `ref`, `ref mut`, or `mut`, then it uses the *default binding mode* to determine how the variable is bound.
+The default binding mode starts in "move" mode which uses move semantics.
+When matching a pattern, the compiler starts from the outside of the pattern and works inwards.
+Each time a reference is matched using a non-reference pattern, it will automatically dereference the value and update the default binding mode.
+References will set the default binding mode to `ref`.
+Mutable references will set the mode to `ref mut` unless the mode is already `ref` in which case it remains `ref`.
+If the automatically dereferenced value is still a reference, it is dereferenced and this process repeats.
+
+Move bindings and reference bindings can be mixed together in the same pattern.
+Doing so will result in partial move of the object bound to and the object cannot be used afterwards.
This applies only if the type cannot be copied.
-In the example below, `name` is moved out of `person`, trying to use `person` as a whole or
-`person.name` would result in an error because of *partial move*.
+In the example below, `name` is moved out of `person`.
+Trying to use `person` as a whole or `person.name` would result in an error because of *partial move*.
Example:
@@ -310,10 +289,10 @@ let Person { name, ref age } = person;
> _WildcardPattern_ :\
> &nbsp;&nbsp; `_`
-The _wildcard pattern_ (an underscore symbol) matches any value. It is used to ignore values when they don't
-matter. Inside other patterns it matches a single data field (as opposed to the `..`
-which matches the remaining fields). Unlike identifier patterns, it does not copy, move
-or borrow the value it matches.
+The _wildcard pattern_ (an underscore symbol) matches any value.
+It is used to ignore values when they don't matter.
+Inside other patterns it matches a single data field (as opposed to the `..` which matches the remaining fields).
+Unlike identifier patterns, it does not copy, move or borrow the value it matches.
Examples:
@@ -351,13 +330,9 @@ The wildcard pattern is always irrefutable.
> _RestPattern_ :\
> &nbsp;&nbsp; `..`
-The _rest pattern_ (the `..` token) acts as a variable-length pattern which
-matches zero or more elements that haven't been matched already before and
-after. It may only be used in [tuple](#tuple-patterns), [tuple
-struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and
-may only appear once as one of the elements in those patterns. It is also
-allowed in an [identifier pattern](#identifier-patterns) for [slice
-patterns](#slice-patterns) only.
+The _rest pattern_ (the `..` token) acts as a variable-length pattern which matches zero or more elements that haven't been matched already before and after.
+It may only be used in [tuple](#tuple-patterns), [tuple struct](#tuple-struct-patterns), and [slice](#slice-patterns) patterns, and may only appear once as one of the elements in those patterns.
+It is also allowed in an [identifier pattern](#identifier-patterns) for [slice patterns](#slice-patterns) only.
The rest pattern is always irrefutable.
@@ -413,7 +388,8 @@ match tuple {
> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..=` _RangePatternBound_
>
> _HalfOpenRangePattern_ :\
-> &nbsp;&nbsp; | _RangePatternBound_ `..`
+> &nbsp;&nbsp; &nbsp;&nbsp; _RangePatternBound_ `..`
+> &nbsp;&nbsp; | `..=` _RangePatternBound_
>
> _ObsoleteRangePattern_ :\
> &nbsp;&nbsp; _RangePatternBound_ `...` _RangePatternBound_
@@ -425,29 +401,50 @@ match tuple {
> &nbsp;&nbsp; | `-`<sup>?</sup> [FLOAT_LITERAL]\
> &nbsp;&nbsp; | [_PathExpression_]
-Range patterns match values within the range defined by their bounds. A range pattern may be
-closed or half-open. A range pattern is closed if it has both a lower and an upper bound, and
-it matches all the values between and including both of its bounds. A range pattern that is
-half-open is written with a lower bound but not an upper bound, and matches any value equal to
-or greater than the specified lower bound.
+*Range patterns* match scalar values within the range defined by their bounds.
+A bound on the left of its sigils 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.
+
+For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`.
+
+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`.
-For example, a pattern `'m'..='p'` will match only the values `'m'`, `'n'`, `'o'`, and `'p'`. For an integer the
-pattern `1..` will match 9, or 9001, or 9007199254740991 (if it is of an appropriate size), but
-not 0, and not negative numbers for signed integers. The bounds can be literals or paths that point
-to constant values.
+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 pattern in the style `a..` cannot be used to match within the context of a slice.
+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.
+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 pattern `a..=b` must always have a &le; b. It is an error to have a range pattern
-`10..=0`, for example.
+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.
-Range patterns only work on scalar types. The accepted types are:
+Half-open range patterns cannot be used as the top-level pattern for subpatterns in [slice patterns](#slice-patterns).
-* Integer types (u8, i8, u16, i16, usize, isize, etc.).
-* Character types (char).
-* Floating point types (f32 and f64). This is being deprecated and will not be available
- in a future version of Rust (see
- [issue #41620](https://github.com/rust-lang/rust/issues/41620)).
+The bounds is written as one of:
+
+* A character, byte, integer, or float literal.
+* A `-` followed by an integer or float literal.
+* A [path]
+
+If the bounds is written as a path, after macro resolution, the path must resolve to a constant item of the type `char`, an integer type, or a float type.
+
+The type and value of the bounds is dependent upon how it is written out.
+If the bounds is a [path], the pattern has the type and value of the [constant] the path resolves to.
+If it is a literal, it has the type and value of the corresponding [literal expression].
+If is a literal preceded by a `-`, it has the same type as the corresponding [literal expression] and the value of [negating] the value of the corresponding literal expression.
Examples:
@@ -524,23 +521,26 @@ println!("{}", match 0xfacade {
});
```
-Range patterns for (non-`usize` and -`isize`) integer and `char` types are irrefutable
-when they span the entire set of possible values of a type. For example, `0u8..=255u8`
-is irrefutable. The range of values for an integer type is the closed range from its
-minimum to maximum value. The range of values for a `char` type are precisely those
-ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and
-`'\u{E000}'..='\u{10FFFF}'`.
+Range patterns for fix-width integer and `char` types are irrefutable when they span the entire set of possible values of a type.
+For example, `0u8..=255u8` is irrefutable.
+The range of values for an integer type is the closed range from its minimum to maximum value.
+The range of values for a `char` type are precisely those ranges containing all Unicode Scalar Values: `'\u{0000}'..='\u{D7FF}'` and `'\u{E000}'..='\u{10FFFF}'`.
+
+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.
+> **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.
+
## Reference patterns
> **<sup>Syntax</sup>**\
> _ReferencePattern_ :\
> &nbsp;&nbsp; (`&`|`&&`) `mut`<sup>?</sup> [_PatternWithoutRange_]
-Reference patterns dereference the pointers that are being matched
-and, thus, borrow them.
+Reference patterns dereference the pointers that are being matched and, thus, borrow them.
For example, these two matches on `x: &i32` are equivalent:
@@ -553,11 +553,9 @@ let b = match int_reference { &0 => "zero", _ => "some" };
assert_eq!(a, b);
```
-The grammar production for reference patterns has to match the token `&&` to match a
-reference to a reference because it is a token by itself, not two `&` tokens.
+The grammar production for reference patterns has to match the token `&&` to match a reference to a reference because it is a token by itself, not two `&` tokens.
-Adding the `mut` keyword dereferences a mutable reference. The mutability must match the
-mutability of the reference.
+Adding the `mut` keyword dereferences a mutable reference. The mutability must match the mutability of the reference.
Reference patterns are always irrefutable.
@@ -594,8 +592,7 @@ Reference patterns are always irrefutable.
Struct patterns match struct values that match all criteria defined by its subpatterns.
They are also used to [destructure](#destructuring) a struct.
-On a struct pattern, the fields are referenced by name, index (in the case of tuple
-structs) or ignored by use of `..`:
+On a struct pattern, the fields are referenced by name, index (in the case of tuple structs) or ignored by use of `..`:
```rust
# struct Point {
@@ -644,8 +641,7 @@ match struct_value {
}
```
-The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to
-a variable with the same name as the given field.
+The `ref` and/or `mut` _IDENTIFIER_ syntax matches any value and binds it to a variable with the same name as the given field.
```rust
# struct Struct {
@@ -669,9 +665,8 @@ A struct pattern is refutable when one of its subpatterns is refutable.
> _TupleStructItems_ :\
> &nbsp;&nbsp; [_Pattern_]&nbsp;( `,` [_Pattern_] )<sup>\*</sup> `,`<sup>?</sup>
-Tuple struct patterns match tuple struct and enum values that match all criteria defined
-by its subpatterns. They are also used to [destructure](#destructuring) a tuple struct or
-enum value.
+Tuple struct patterns match tuple struct and enum values that match all criteria defined by its subpatterns.
+They are also used to [destructure](#destructuring) a tuple struct or enum value.
A tuple struct pattern is refutable when one of its subpatterns is refutable.
@@ -689,8 +684,7 @@ A tuple struct pattern is refutable when one of its subpatterns is refutable.
Tuple patterns match tuple values that match all criteria defined by its subpatterns.
They are also used to [destructure](#destructuring) a tuple.
-The form `(..)` with a single [_RestPattern_] is a special form that does not
-require a comma, and matches a tuple of any size.
+The form `(..)` with a single [_RestPattern_] is a special form that does not require a comma, and matches a tuple of any size.
The tuple pattern is refutable when one of its subpatterns is refutable.
@@ -710,10 +704,8 @@ assert_eq!(b, "ten");
> _GroupedPattern_ :\
> &nbsp;&nbsp; `(` [_Pattern_] `)`
-Enclosing a pattern in parentheses can be used to explicitly control the
-precedence of compound patterns. For example, a reference pattern next to a
-range pattern such as `&0..=5` is ambiguous and is not allowed, but can be
-expressed with parentheses.
+Enclosing a pattern in parentheses can be used to explicitly control the precedence of compound patterns.
+For example, a reference pattern next to a range pattern such as `&0..=5` is ambiguous and is not allowed, but can be expressed with parentheses.
```rust
let int_reference = &3;
@@ -733,6 +725,7 @@ match int_reference {
> &nbsp;&nbsp; [_Pattern_] \(`,` [_Pattern_])<sup>\*</sup> `,`<sup>?</sup>
Slice patterns can match both arrays of fixed size and slices of dynamic size.
+
```rust
// Fixed size
let arr = [1, 2, 3];
@@ -751,14 +744,10 @@ 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.
+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.
-A future version of Rust may give the non-parenthesized version an alternate meaning.
+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.
## Path patterns
@@ -778,33 +767,27 @@ Unqualified path patterns can refer to:
Qualified path patterns can only refer to associated constants.
-Constants cannot be a union type. Struct and enum constants must have
-`#[derive(PartialEq, Eq)]` (not merely implemented).
+Constants cannot be a union type.
+Struct and enum constants must have `#[derive(PartialEq, Eq)]` (not merely implemented).
-Path patterns are irrefutable when they refer to structs or an enum variant when the enum
-has only one variant or a constant whose type is irrefutable. They are refutable when they
-refer to refutable constants or enum variants for enums with multiple variants.
+Path patterns are irrefutable when they refer to structs or an enum variant when the enum has only one variant or a constant whose type is irrefutable.
+They are refutable when they refer to refutable constants or enum variants for enums with multiple variants.
## Or-patterns
-_Or-patterns_ are patterns that match on one of two or more sub-patterns (e.g.
-`A | B | C`). They can nest arbitrarily. Syntactically, or-patterns are allowed
-in any of the places where other patterns are allowed (represented by the
-_Pattern_ production), with the exceptions of `let`-bindings and function and
-closure arguments (represented by the _PatternNoTopAlt_ production).
+_Or-patterns_ are patterns that match on one of two or more sub-patterns (for example `A | B | C`).
+They can nest arbitrarily.
+Syntactically, or-patterns are allowed in any of the places where other patterns are allowed (represented by the _Pattern_ production), with the exceptions of `let`-bindings and function and closure arguments (represented by the _PatternNoTopAlt_ production).
### Static semantics
-1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`,
- the pattern is considered ill-formed if:
+1. Given a pattern `p | q` at some depth for some arbitrary patterns `p` and `q`, the pattern is considered ill-formed if:
+ the type inferred for `p` does not unify with the type inferred for `q`, or
+ the same set of bindings are not introduced in `p` and `q`, or
- + the type of any two bindings with the same name in `p` and `q` do not unify
- with respect to types or binding modes.
+ + the type of any two bindings with the same name in `p` and `q` do not unify with respect to types or binding modes.
- Unification of types is in all instances aforementioned exact and
- implicit [type coercions] do not apply.
+ Unification of types is in all instances aforementioned exact and implicit [type coercions] do not apply.
2. When type checking an expression `match e_s { a_1 => e_1, ... a_n => e_n }`,
for each match arm `a_i` which contains a pattern of form `p_i | q_i`,
@@ -812,35 +795,27 @@ closure arguments (represented by the _PatternNoTopAlt_ production).
at the depth `d` where it exists the fragment of `e_s` at depth `d`,
the type of the expression fragment does not unify with `p_i | q_i`.
-3. With respect to exhaustiveness checking, a pattern `p | q` is
- considered to cover `p` as well as `q`. For some constructor `c(x, ..)`
- the distributive law applies such that `c(p | q, ..rest)` covers the same
- set of value as `c(p, ..rest) | c(q, ..rest)` does. This can be applied
- recursively until there are no more nested patterns of form `p | q` other
- than those that exist at the top level.
+3. With respect to exhaustiveness checking, a pattern `p | q` is considered to cover `p` as well as `q`.
+ For some constructor `c(x, ..)` the distributive law applies such that `c(p | q, ..rest)` covers the same set of value as `c(p, ..rest) | c(q, ..rest)` does.
+ This can be applied recursively until there are no more nested patterns of form `p | q` other than those that exist at the top level.
- Note that by *"constructor"* we do not refer to tuple struct patterns,
- but rather we refer to a pattern for any product type.
- This includes enum variants, tuple structs, structs with named fields,
- arrays, tuples, and slices.
+ Note that by *"constructor"* we do not refer to tuple struct patterns, but rather we refer to a pattern for any product type.
+ This includes enum variants, tuple structs, structs with named fields, arrays, tuples, and slices.
### Dynamic semantics
-1. The dynamic semantics of pattern matching a scrutinee expression `e_s`
- against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor,
- `p` and `q` are arbitrary patterns, and `rest` is optionally any remaining
- potential factors in `c`, is defined as being the same as that of
- `c(p, ..rest) | c(q, ..rest)`.
+1. The dynamic semantics of pattern matching a scrutinee expression `e_s` against a pattern `c(p | q, ..rest)` at depth `d` where `c` is some constructor,
+ `p` and `q` are arbitrary patterns,
+ and `rest` is optionally any remaining potential factors in `c`,
+ is defined as being the same as that of `c(p, ..rest) | c(q, ..rest)`.
### Precedence with other undelimited patterns
-As shown elsewhere in this chapter, there are several types of patterns that
-are syntactically undelimited, including identifier patterns, reference
-patterns, and or-patterns. Or-patterns always have the lowest-precedence. This
-allows us to reserve syntactic space for a possible future type ascription
-feature and also to reduce ambiguity. For example, `x @ A(..) | B(..)` will
-result in an error that `x` is not bound in all patterns, `&A(x) | B(x)` will
-result in a type mismatch between `x` in the different subpatterns.
+As shown elsewhere in this chapter, there are several types of patterns that are syntactically undelimited, including identifier patterns, reference patterns, and or-patterns.
+Or-patterns always have the lowest-precedence.
+This allows us to reserve syntactic space for a possible future type ascription feature and also to reduce ambiguity.
+For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound in all patterns.
+`&A(x) | B(x)` will result in a type mismatch between `x` in the different subpatterns.
[_GroupedPattern_]: #grouped-patterns
[_IdentifierPattern_]: #identifier-patterns
@@ -865,8 +840,13 @@ result in a type mismatch between `x` in the different subpatterns.
[`Copy`]: special-types-and-traits.md#copy
[IDENTIFIER]: identifiers.md
+[constant]: items/constant-items.md
[enums]: items/enumerations.md
[literals]: expressions/literal-expr.md
+[literal expression]: expressions/literal-expr.md
+[negating]: expressions/operator-expr.md#negation-operators
+[path]: expressions/path-expr.md
+[range expressions]: expressions/range-expr.md
[structs]: items/structs.md
[tuples]: types/tuple.md
[scrutinee]: glossary.md#scrutinee
diff --git a/src/doc/reference/src/statements-and-expressions.md b/src/doc/reference/src/statements-and-expressions.md
index b093972a9..fede41196 100644
--- a/src/doc/reference/src/statements-and-expressions.md
+++ b/src/doc/reference/src/statements-and-expressions.md
@@ -1,11 +1,7 @@
# Statements and expressions
-Rust is _primarily_ an expression language. This means that most forms of
-value-producing or effect-causing evaluation are directed by the uniform syntax
-category of _expressions_. Each kind of expression can typically _nest_ within
-each other kind of expression, and rules for evaluation of expressions involve
-specifying both the value produced by the expression and the order in which its
-sub-expressions are themselves evaluated.
+Rust is _primarily_ an expression language.
+This means that most forms of value-producing or effect-causing evaluation are directed by the uniform syntax category of _expressions_.
+Each kind of expression can typically _nest_ within each other kind of expression, and rules for evaluation of expressions involve specifying both the value produced by the expression and the order in which its sub-expressions are themselves evaluated.
-In contrast, statements serve _mostly_ to contain and explicitly
-sequence expression evaluation.
+In contrast, statements serve _mostly_ to contain and explicitly sequence expression evaluation.
diff --git a/src/doc/reference/src/statements.md b/src/doc/reference/src/statements.md
index 8d9c21d7d..c2ae585a0 100644
--- a/src/doc/reference/src/statements.md
+++ b/src/doc/reference/src/statements.md
@@ -9,35 +9,27 @@
> &nbsp;&nbsp; | [_MacroInvocationSemi_]
-A *statement* is a component of a [block], which is in turn a component of an
-outer [expression] or [function].
+A *statement* is a component of a [block], which is in turn a component of an outer [expression] or [function].
-Rust has two kinds of statement: [declaration
-statements](#declaration-statements) and [expression
-statements](#expression-statements).
+Rust has two kinds of statement: [declaration statements](#declaration-statements) and [expression statements](#expression-statements).
## Declaration statements
-A *declaration statement* is one that introduces one or more *names* into the
-enclosing statement block. The declared names may denote new variables or new
-[items][item].
+A *declaration statement* is one that introduces one or more *names* into the enclosing statement block.
+The declared names may denote new variables or new [items][item].
-The two kinds of declaration statements are item declarations and `let`
-statements.
+The two kinds of declaration statements are item declarations and `let` statements.
### Item declarations
-An *item declaration statement* has a syntactic form identical to an
-[item declaration][item] within a [module]. Declaring an item within a statement
-block restricts its scope to the block containing the statement. The item is not
-given a [canonical path] nor are any sub-items it may declare. The exception to
-this is that associated items defined by [implementations] are still accessible
-in outer scopes as long as the item and, if applicable, trait are accessible.
+An *item declaration statement* has a syntactic form identical to an [item declaration][item] within a [module].
+Declaring an item within a statement block restricts its scope to the block containing the statement.
+The item is not given a [canonical path] nor are any sub-items it may declare.
+The exception to this is that associated items defined by [implementations] are still accessible in outer scopes as long as the item and, if applicable, trait are accessible.
It is otherwise identical in meaning to declaring the item inside a module.
-There is no implicit capture of the containing function's generic parameters,
-parameters, and local variables. For example, `inner` may not access
-`outer_var`.
+There is no implicit capture of the containing function's generic parameters, parameters, and local variables.
+For example, `inner` may not access `outer_var`.
```rust
fn outer() {
@@ -54,16 +46,32 @@ fn outer() {
> **<sup>Syntax</sup>**\
> _LetStatement_ :\
> &nbsp;&nbsp; [_OuterAttribute_]<sup>\*</sup> `let` [_PatternNoTopAlt_]
-> ( `:` [_Type_] )<sup>?</sup> (`=` [_Expression_] )<sup>?</sup> `;`
+> ( `:` [_Type_] )<sup>?</sup> (`=` [_Expression_] [†](#let-else-restriction)
+> ( `else` [_BlockExpression_]) <sup>?</sup> ) <sup>?</sup> `;`
+>
+> <span id="let-else-restriction">† When an `else` block is specified, the
+> _Expression_ must not be a [_LazyBooleanExpression_], or end with a `}`.</span>
+
+A *`let` statement* introduces a new set of [variables], given by a [pattern].
+The pattern is followed optionally by a type annotation and then either ends, or is followed by an initializer expression plus an optional `else` block.
+When no type annotation is given, the compiler will infer the type, or signal an error if insufficient type information is available for definite inference.
+Any variables introduced by a variable declaration are visible from the point of declaration until the end of the enclosing block scope, except when they are shadowed by another variable declaration.
+
+If an `else` block is not present, the pattern must be irrefutable.
+If an `else` block is present, the pattern may be refutable.
+If the pattern does not match (this requires it to be refutable), the `else` block is executed.
+The `else` block must always diverge (evaluate to the [never type]).
-A *`let` statement* introduces a new set of [variables], given by an
-irrefutable [pattern]. The pattern is followed optionally by a type
-annotation and then optionally by an initializer expression. When no
-type annotation is given, the compiler will infer the type, or signal
-an error if insufficient type information is available for definite
-inference. Any variables introduced by a variable declaration are visible
-from the point of declaration until the end of the enclosing block scope,
-except when they are shadowed by another variable declaration.
+```rust
+let (mut v, w) = (vec![1, 2, 3], 42); // The bindings may be mut or const
+let Some(t) = v.pop() else { // Refutable patterns require an else block
+ panic!(); // The else block must diverge
+};
+let [u, v] = [v[0], v[1]] else { // This pattern is irrefutable, so the compiler
+ // will lint as the else block is redundant.
+ panic!();
+};
+```
## Expression statements
@@ -72,16 +80,13 @@ except when they are shadowed by another variable declaration.
> &nbsp;&nbsp; &nbsp;&nbsp; [_ExpressionWithoutBlock_][expression] `;`\
> &nbsp;&nbsp; | [_ExpressionWithBlock_][expression] `;`<sup>?</sup>
-An *expression statement* is one that evaluates an [expression] and ignores its
-result. As a rule, an expression statement's purpose is to trigger the effects
-of evaluating its expression.
+An *expression statement* is one that evaluates an [expression] and ignores its result.
+As a rule, an expression statement's purpose is to trigger the effects of evaluating its expression.
-An expression that consists of only a [block expression][block] or control flow
-expression, if used in a context where a statement is permitted, can omit the
-trailing semicolon. This can cause an ambiguity between it being parsed as a
-standalone statement and as a part of another expression; in this case, it is
-parsed as a statement. The type of [_ExpressionWithBlock_][expression]
-expressions when used as statements must be the unit type.
+An expression that consists of only a [block expression][block] or control flow expression, if used in a context where a statement is permitted, can omit the trailing semicolon.
+This can cause an ambiguity between it being parsed as a standalone statement and as a part of another expression;
+in this case, it is parsed as a statement.
+The type of [_ExpressionWithBlock_][expression] expressions when used as statements must be the unit type.
```rust
# let mut v = vec![1, 2, 3];
@@ -113,14 +118,15 @@ if true {
## Attributes on Statements
-Statements accept [outer attributes]. The attributes that have meaning on a
-statement are [`cfg`], and [the lint check attributes].
+Statements accept [outer attributes].
+The attributes that have meaning on a statement are [`cfg`], and [the lint check attributes].
[block]: expressions/block-expr.md
[expression]: expressions.md
[function]: items/functions.md
[item]: items.md
[module]: items/modules.md
+[never type]: types/never.md
[canonical path]: paths.md#canonical-paths
[implementations]: items/implementations.md
[variables]: variables.md
@@ -128,9 +134,11 @@ statement are [`cfg`], and [the lint check attributes].
[`cfg`]: conditional-compilation.md
[the lint check attributes]: attributes/diagnostics.md#lint-check-attributes
[pattern]: patterns.md
+[_BlockExpression_]: expressions/block-expr.md
[_ExpressionStatement_]: #expression-statements
[_Expression_]: expressions.md
[_Item_]: items.md
+[_LazyBooleanExpression_]: expressions/operator-expr.md#lazy-boolean-operators
[_LetStatement_]: #let-statements
[_MacroInvocationSemi_]: macros.md#macro-invocation
[_OuterAttribute_]: attributes.md
diff --git a/src/doc/reference/src/tokens.md b/src/doc/reference/src/tokens.md
index 197c20147..8f9bcb1f7 100644
--- a/src/doc/reference/src/tokens.md
+++ b/src/doc/reference/src/tokens.md
@@ -667,7 +667,7 @@ Similarly the `r`, `b`, and `br` prefixes used in raw string literals, byte lite
> **Edition Differences**: Starting with the 2021 edition, reserved prefixes are reported as an error by the lexer (in particular, they cannot be passed to macros).
>
-> Before the 2021 edition, a reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token).
+> Before the 2021 edition, reserved prefixes are accepted by the lexer and interpreted as multiple tokens (for example, one token for the identifier or keyword, followed by a `#` token).
>
> Examples accepted in all editions:
> ```rust
diff --git a/src/doc/reference/src/type-layout.md b/src/doc/reference/src/type-layout.md
index ce9296662..80a36abb8 100644
--- a/src/doc/reference/src/type-layout.md
+++ b/src/doc/reference/src/type-layout.md
@@ -20,8 +20,10 @@ The alignment of a value can be checked with the [`align_of_val`] function.
The *size* of a value is the offset in bytes between successive elements in an
array with that item type including alignment padding. The size of a value is
-always a multiple of its alignment. The size of a value can be checked with the
-[`size_of_val`] function.
+always a multiple of its alignment. Note that some types are zero-sized; 0 is
+considered a multiple of any alignment (for example, on some platforms, the type
+`[u16; 0]` has size 0 and alignment 2). The size of a value can be checked with
+the [`size_of_val`] function.
Types where all values have the same size and alignment, and both are known at
compile time, implement the [`Sized`] trait and can be checked with the
@@ -86,9 +88,9 @@ String slices are a UTF-8 representation of characters that have the same layout
## Tuple Layout
-Tuples do not have any guarantees about their layout.
+Tuples are laid out according to the [default representation][Default].
-The exception to this is the unit tuple (`()`) which is guaranteed as a
+The exception to this is the unit tuple (`()`), which is guaranteed as a
zero-sized type to have a size of 0 and an alignment of 1.
## Trait Object Layout
@@ -162,7 +164,25 @@ representation will not change the layout of `Inner`.
Nominal types without a `repr` attribute have the default representation.
Informally, this representation is also called the `rust` representation.
-There are no guarantees of data layout made by this representation.
+The only data layout guarantees made by this representation are those required
+for soundness. They are:
+
+ 1. The fields are properly aligned.
+ 2. The fields do not overlap.
+ 3. The alignment of the type is at least the maximum alignment of its fields.
+
+Formally, the first guarantee means that the offset of any field is divisible by
+that field's alignment. The second guarantee means that the fields can be
+ordered such that the offset plus the size of any field is less than or equal to
+the offset of the next field in the ordering. The ordering does not have to be
+the same as the order in which the fields are specified in the declaration of
+the type.
+
+Be aware that the second guarantee does not imply that the fields have distinct
+addresses: zero-sized types may have the same address as other fields in the
+same struct.
+
+There are no other guarantees of data layout made by this representation.
### The `C` Representation
diff --git a/src/doc/reference/src/types/function-pointer.md b/src/doc/reference/src/types/function-pointer.md
index a51f76135..82103beaa 100644
--- a/src/doc/reference/src/types/function-pointer.md
+++ b/src/doc/reference/src/types/function-pointer.md
@@ -62,5 +62,5 @@ restrictions as [regular function parameters].
[closures]: closure.md
[extern function]: ../items/functions.md#extern-function-qualifier
[function items]: function-item.md
-[unsafe function]: ../unsafe-functions.md
+[unsafe function]: ../unsafe-keyword.md
[regular function parameters]: ../items/functions.md#attributes-on-function-parameters
diff --git a/src/doc/reference/src/types/pointer.md b/src/doc/reference/src/types/pointer.md
index 9c8d80f39..4a74370a5 100644
--- a/src/doc/reference/src/types/pointer.md
+++ b/src/doc/reference/src/types/pointer.md
@@ -11,8 +11,8 @@ They can be moved or copied, stored into data structs, and returned from functio
### Shared references (`&`)
-These point to memory _owned by some other value_.
-When a shared reference to a value is created it prevents direct mutation of the value.
+Shared references point to memory which is owned by some other value.
+When a shared reference to a value is created, it prevents direct mutation of the value.
[Interior mutability] provides an exception for this in certain circumstances.
As the name suggests, any number of shared references to a value may exist.
A shared reference type is written `&type`, or `&'a type` when you need to specify an explicit lifetime.
@@ -22,7 +22,7 @@ Releasing a reference has no effect on the value it points to, but referencing o
### Mutable references (`&mut`)
-These also point to memory owned by some other value.
+Mutable references point to memory which is owned by some other value.
A mutable reference type is written `&mut type` or `&'a mut type`.
A mutable reference (that hasn't been borrowed) is the only way to access the value it points to, so is not `Copy`.
diff --git a/src/doc/reference/src/unsafe-blocks.md b/src/doc/reference/src/unsafe-blocks.md
deleted file mode 100644
index 754278445..000000000
--- a/src/doc/reference/src/unsafe-blocks.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# Unsafe blocks
-
-A block of code can be prefixed with the `unsafe` keyword, to permit calling
-`unsafe` functions or dereferencing raw pointers within a safe function.
-
-When a programmer has sufficient conviction that a sequence of potentially
-unsafe operations is actually safe, they can encapsulate that sequence (taken
-as a whole) within an `unsafe` block. The compiler will consider uses of such
-code safe, in the surrounding context.
-
-Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
-or implement features not directly present in the language. For example, Rust
-provides the language features necessary to implement memory-safe concurrency
-in the language but the implementation of threads and message passing is in the
-standard library.
-
-Rust's type system is a conservative approximation of the dynamic safety
-requirements, so in some cases there is a performance cost to using safe code.
-For example, a doubly-linked list is not a tree structure and can only be
-represented with reference-counted pointers in safe code. By using `unsafe`
-blocks to represent the reverse links as raw pointers, it can be implemented
-with only boxes.
diff --git a/src/doc/reference/src/unsafe-functions.md b/src/doc/reference/src/unsafe-functions.md
deleted file mode 100644
index 7a5064c08..000000000
--- a/src/doc/reference/src/unsafe-functions.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Unsafe functions
-
-Unsafe functions are functions that are not safe in all contexts and/or for all
-possible inputs. Such a function must be prefixed with the keyword `unsafe` and
-can only be called from an `unsafe` block or another `unsafe` function.
diff --git a/src/doc/reference/src/unsafe-keyword.md b/src/doc/reference/src/unsafe-keyword.md
new file mode 100644
index 000000000..5fa5deea6
--- /dev/null
+++ b/src/doc/reference/src/unsafe-keyword.md
@@ -0,0 +1,58 @@
+# The `unsafe` keyword
+
+The `unsafe` keyword can occur in several different contexts:
+unsafe functions (`unsafe fn`), unsafe blocks (`unsafe {}`), unsafe traits (`unsafe trait`), and unsafe trait implementations (`unsafe impl`).
+It plays several different roles, depending on where it is used and whether the `unsafe_op_in_unsafe_fn` lint is enabled:
+- it is used to mark code that *defines* extra safety conditions (`unsafe fn`, `unsafe trait`)
+- it is used to mark code that needs to *satisfy* extra safety conditions (`unsafe {}`, `unsafe impl`, `unsafe fn` without [`unsafe_op_in_unsafe_fn`])
+
+The following discusses each of these cases.
+See the [keyword documentation][keyword] for some illustrative examples.
+
+## Unsafe functions (`unsafe fn`)
+
+Unsafe functions are functions that are not safe in all contexts and/or for all possible inputs.
+We say they have *extra safety conditions*, which are requirements that must be upheld by all callers and that the compiler does not check.
+For example, [`get_unchecked`] has the extra safety condition that the index must be in-bounds.
+The unsafe function should come with documentation explaining what those extra safety conditions are.
+
+Such a function must be prefixed with the keyword `unsafe` and can only be called from inside an `unsafe` block, or inside `unsafe fn` without the [`unsafe_op_in_unsafe_fn`] lint.
+
+## Unsafe blocks (`unsafe {}`)
+
+A block of code can be prefixed with the `unsafe` keyword, to permit calling `unsafe` functions or dereferencing raw pointers.
+By default, the body of an unsafe function is also considered to be an unsafe block;
+this can be changed by enabling the [`unsafe_op_in_unsafe_fn`] lint.
+
+By putting operations into an unsafe block, the programmer states that they have taken care of satisfying the extra safety conditions of all operations inside that block.
+
+Unsafe blocks are the logical dual to unsafe functions:
+where unsafe functions define a proof obligation that callers must uphold, unsafe blocks state that all relevant proof obligations have been discharged.
+There are many ways to discharge proof obligations;
+for example, there could be run-time checks or data structure invariants that guarantee that certain properties are definitely true, or the unsafe block could be inside an `unsafe fn` and use its own proof obligations to discharge the proof obligations of its callees.
+
+Unsafe blocks are used to wrap foreign libraries, make direct use of hardware or implement features not directly present in the language.
+For example, Rust provides the language features necessary to implement memory-safe concurrency in the language but the implementation of threads and message passing in the standard library uses unsafe blocks.
+
+Rust's type system is a conservative approximation of the dynamic safety requirements, so in some cases there is a performance cost to using safe code.
+For example, a doubly-linked list is not a tree structure and can only be represented with reference-counted pointers in safe code.
+By using `unsafe` blocks to represent the reverse links as raw pointers, it can be implemented without reference counting.
+(See ["Learn Rust With Entirely Too Many Linked Lists"](https://rust-unofficial.github.io/too-many-lists/) for a more in-depth exploration of this particular example.)
+
+## Unsafe traits (`unsafe trait`)
+
+An unsafe trait is a trait that comes with extra safety conditions that must be upheld by *implementations* of the trait.
+The unsafe trait should come with documentation explaining what those extra safety conditions are.
+
+Such a trait must be prefixed with the keyword `unsafe` and can only be implemented by `unsafe impl` blocks.
+
+## Unsafe trait implementations (`unsafe impl`)
+
+When implementing an unsafe trait, the implementation needs to be prefixed with the `unsafe` keyword.
+By writing `unsafe impl`, the programmer states that they have taken care of satisfying the extra safety conditions required by the trait.
+
+Unsafe trait implementations are the logical dual to unsafe traits: where unsafe traits define a proof obligation that implementations must uphold, unsafe implementations state that all relevant proof obligations have been discharged.
+
+[keyword]: ../std/keyword.unsafe.html
+[`get_unchecked`]: ../std/primitive.slice.html#method.get_unchecked
+[`unsafe_op_in_unsafe_fn`]: ../rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn
diff --git a/src/doc/rust-by-example/src/cargo/conventions.md b/src/doc/rust-by-example/src/cargo/conventions.md
index 6e8196608..2335104f5 100644
--- a/src/doc/rust-by-example/src/cargo/conventions.md
+++ b/src/doc/rust-by-example/src/cargo/conventions.md
@@ -25,9 +25,9 @@ foo
└── my_other_bin.rs
```
-To tell `cargo` to compile or run this binary as opposed to the default or other
-binaries, we just pass `cargo` the `--bin my_other_bin` flag, where `my_other_bin`
-is the name of the binary we want to work with.
+To tell `cargo` to only compile or run this binary, we just pass `cargo` the
+`--bin my_other_bin` flag, where `my_other_bin` is the name of the binary we
+want to work with.
In addition to extra binaries, `cargo` supports [more features] such as
benchmarks, tests, and examples.
diff --git a/src/doc/rust-by-example/src/cargo/deps.md b/src/doc/rust-by-example/src/cargo/deps.md
index 8913e9e38..85f223f98 100644
--- a/src/doc/rust-by-example/src/cargo/deps.md
+++ b/src/doc/rust-by-example/src/cargo/deps.md
@@ -11,8 +11,8 @@ To create a new Rust project,
# A binary
cargo new foo
-# OR A library
-cargo new --lib foo
+# A library
+cargo new --lib bar
```
For the rest of this chapter, let's assume we are making a binary, rather than
@@ -21,14 +21,19 @@ a library, but all of the concepts are the same.
After the above commands, you should see a file hierarchy like this:
```txt
-foo
-├── Cargo.toml
-└── src
- └── main.rs
+.
+├── bar
+│ ├── Cargo.toml
+│ └── src
+│ └── lib.rs
+└── foo
+ ├── Cargo.toml
+ └── src
+ └── main.rs
```
-The `main.rs` is the root source file for your new project -- nothing new there.
-The `Cargo.toml` is the config file for `cargo` for this project (`foo`). If you
+The `main.rs` is the root source file for your new `foo` project -- nothing new there.
+The `Cargo.toml` is the config file for `cargo` for this project. If you
look inside it, you should see something like this:
```toml
diff --git a/src/doc/rust-by-example/src/conversion/from_into.md b/src/doc/rust-by-example/src/conversion/from_into.md
index 266d10f28..47b327142 100644
--- a/src/doc/rust-by-example/src/conversion/from_into.md
+++ b/src/doc/rust-by-example/src/conversion/from_into.md
@@ -66,7 +66,7 @@ impl From<i32> for Number {
fn main() {
let int = 5;
- // Try removing the type declaration
+ // Try removing the type annotation
let num: Number = int.into();
println!("My number is {:?}", num);
}
diff --git a/src/doc/rust-by-example/src/error/iter_result.md b/src/doc/rust-by-example/src/error/iter_result.md
index e77e21ff6..288f4fc02 100644
--- a/src/doc/rust-by-example/src/error/iter_result.md
+++ b/src/doc/rust-by-example/src/error/iter_result.md
@@ -51,7 +51,7 @@ fn main() {
## Fail the entire operation with `collect()`
-`Result` implements `FromIter` so that a vector of results (`Vec<Result<T, E>>`)
+`Result` implements `FromIterator` so that a vector of results (`Vec<Result<T, E>>`)
can be turned into a result with a vector (`Result<Vec<T>, E>`). Once an
`Result::Err` is found, the iteration will terminate.
diff --git a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
index eb515aee6..117333f12 100644
--- a/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
+++ b/src/doc/rust-by-example/src/error/option_unwrap/defaults.md
@@ -1,6 +1,6 @@
# Unpacking options and defaults
-The is more than one way to unpack an `Option` and fall back on a default if it is `None`. To choose the one that meets our needs, we need to consider the following:
+There is more than one way to unpack an `Option` and fall back on a default if it is `None`. To choose the one that meets our needs, we need to consider the following:
* do we need eager or lazy evaluation?
* do we need to keep the original empty value intact, or modify it in place?
@@ -60,7 +60,7 @@ fn main() {
## `get_or_insert()` evaluates eagerly, modifies empty value in place
-To make sure that an `Option` contains a value, we can use `get_or_insert` to modify it in place with a fallback value, as is shown in the following example. Note that `get_or_insert` eagerly evaluaes its parameter, so variable `apple` is moved:
+To make sure that an `Option` contains a value, we can use `get_or_insert` to modify it in place with a fallback value, as is shown in the following example. Note that `get_or_insert` eagerly evaluates its parameter, so variable `apple` is moved:
```rust,editable
#[derive(Debug)]
@@ -75,7 +75,7 @@ fn main() {
// my_fruit is: Apple
// first_available_fruit is: Apple
//println!("Variable named `apple` is moved: {:?}", apple);
- // TODO: uncomment the line above to see the compliler error
+ // TODO: uncomment the line above to see the compiler error
}
```
diff --git a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md
index 54552972a..93b7e4205 100644
--- a/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md
+++ b/src/doc/rust-by-example/src/flow_control/match/destructuring/destructure_slice.md
@@ -45,4 +45,4 @@ fn main() {
### See also:
-[Arrays and Slices](../../../primitives/array.md)
+[Arrays and Slices](../../../primitives/array.md) and [Binding](../binding.md) for `@` sigil
diff --git a/src/doc/rust-by-example/src/flow_control/match/guard.md b/src/doc/rust-by-example/src/flow_control/match/guard.md
index 6dba58f13..63008a743 100644
--- a/src/doc/rust-by-example/src/flow_control/match/guard.md
+++ b/src/doc/rust-by-example/src/flow_control/match/guard.md
@@ -5,7 +5,7 @@ A `match` *guard* can be added to filter the arm.
```rust,editable
enum Temperature {
Celsius(i32),
- Farenheit(i32),
+ Fahrenheit(i32),
}
fn main() {
@@ -17,8 +17,8 @@ fn main() {
// The `if condition` part ^ is a guard
Temperature::Celsius(t) => println!("{}C is below 30 Celsius", t),
- Temperature::Farenheit(t) if t > 86 => println!("{}F is above 86 Farenheit", t),
- Temperature::Farenheit(t) => println!("{}F is below 86 Farenheit", t),
+ Temperature::Fahrenheit(t) if t > 86 => println!("{}F is above 86 Fahrenheit", t),
+ Temperature::Fahrenheit(t) => println!("{}F is below 86 Fahrenheit", t),
}
}
```
diff --git a/src/doc/rust-by-example/src/macros.md b/src/doc/rust-by-example/src/macros.md
index ffeb923e5..3f12fcc41 100644
--- a/src/doc/rust-by-example/src/macros.md
+++ b/src/doc/rust-by-example/src/macros.md
@@ -37,4 +37,4 @@ So why are macros useful?
3. Variadic interfaces. Sometimes you want to define an interface that takes a
variable number of arguments. An example is `println!` which could take any
- number of arguments, depending on the format string!. (More on this later)
+ number of arguments, depending on the format string. (More on this later)
diff --git a/src/doc/rust-by-example/src/mod/struct_visibility.md b/src/doc/rust-by-example/src/mod/struct_visibility.md
index e7359413c..8641a7264 100644
--- a/src/doc/rust-by-example/src/mod/struct_visibility.md
+++ b/src/doc/rust-by-example/src/mod/struct_visibility.md
@@ -13,7 +13,6 @@ mod my {
}
// A public struct with a private field of generic type `T`
- #[allow(dead_code)]
pub struct ClosedBox<T> {
contents: T,
}
@@ -56,4 +55,4 @@ fn main() {
[generics][generics] and [methods][methods]
[generics]: ../generics.md
-[methods]: ../fn/methods.md \ No newline at end of file
+[methods]: ../fn/methods.md
diff --git a/src/doc/rust-by-example/src/primitives/array.md b/src/doc/rust-by-example/src/primitives/array.md
index 841c71c14..0f56182cd 100644
--- a/src/doc/rust-by-example/src/primitives/array.md
+++ b/src/doc/rust-by-example/src/primitives/array.md
@@ -64,7 +64,7 @@ fn main() {
}
}
- // Out of bound indexing causes compile error
+ // Out of bound indexing causes runtime error
//println!("{}", xs[5]);
}
```
diff --git a/src/doc/rust-by-example/src/std/box.md b/src/doc/rust-by-example/src/std/box.md
index 0740c07d6..ebc8ff430 100644
--- a/src/doc/rust-by-example/src/std/box.md
+++ b/src/doc/rust-by-example/src/std/box.md
@@ -62,11 +62,11 @@ fn main() {
mem::size_of_val(&rectangle));
// box size == pointer size
- println!("Boxed point occupies {} bytes on the heap",
+ println!("Boxed point occupies {} bytes on the stack",
mem::size_of_val(&boxed_point));
- println!("Boxed rectangle occupies {} bytes on the heap",
+ println!("Boxed rectangle occupies {} bytes on the stack",
mem::size_of_val(&boxed_rectangle));
- println!("Boxed box occupies {} bytes on the heap",
+ println!("Boxed box occupies {} bytes on the stack",
mem::size_of_val(&box_in_a_box));
// Copy the data contained in `boxed_point` into `unboxed_point`
diff --git a/src/doc/rust-by-example/src/std/str.md b/src/doc/rust-by-example/src/std/str.md
index 26d8fd109..a15038b90 100644
--- a/src/doc/rust-by-example/src/std/str.md
+++ b/src/doc/rust-by-example/src/std/str.md
@@ -69,7 +69,7 @@ This way you can add any character to your string, even unprintable ones
and ones that you don't know how to type. If you want a literal backslash,
escape it with another one: `\\`
-String or character literal delimiters occuring within a literal must be escaped: `"\""`, `'\''`.
+String or character literal delimiters occurring within a literal must be escaped: `"\""`, `'\''`.
```rust,editable
fn main() {
diff --git a/src/doc/rust-by-example/src/std_misc/path.md b/src/doc/rust-by-example/src/std_misc/path.md
index 48d85c144..af0f3d388 100644
--- a/src/doc/rust-by-example/src/std_misc/path.md
+++ b/src/doc/rust-by-example/src/std_misc/path.md
@@ -13,8 +13,10 @@ between `Path` and `PathBuf` is similar to that of `str` and `String`:
a `PathBuf` can be mutated in-place, and can be dereferenced to a `Path`.
Note that a `Path` is *not* internally represented as an UTF-8 string, but
-instead is stored as a vector of bytes (`Vec<u8>`). Therefore, converting a
-`Path` to a `&str` is *not* free and may fail (an `Option` is returned).
+instead is stored as an `OsString`. Therefore, converting a `Path` to a `&str`
+is *not* free and may fail (an `Option` is returned). However, a `Path` can be
+freely converted to an `OsString` or `&OsStr` using `into_os_string` and
+`as_os_str`, respectively.
```rust,editable
use std::path::Path;
diff --git a/src/doc/rust-by-example/src/testing/doc_testing.md b/src/doc/rust-by-example/src/testing/doc_testing.md
index 2fac440f9..1d6cd46ad 100644
--- a/src/doc/rust-by-example/src/testing/doc_testing.md
+++ b/src/doc/rust-by-example/src/testing/doc_testing.md
@@ -1,9 +1,10 @@
# Documentation testing
The primary way of documenting a Rust project is through annotating the source
-code. Documentation comments are written in [markdown] and support code
-blocks in them. Rust takes care about correctness, so these code blocks are
-compiled and used as documentation tests.
+code. Documentation comments are written in
+[CommonMark Markdown specification][commonmark] and support code blocks in them.
+Rust takes care about correctness, so these code blocks are compiled and used
+as documentation tests.
```rust,ignore
/// First line is a short summary describing function.
@@ -83,7 +84,7 @@ and `unwrap` it in hidden `main`. Sounds complicated? Here's an example:
/// ```
/// # // hidden lines start with `#` symbol, but they're still compilable!
/// # fn try_main() -> Result<(), String> { // line that wraps the body shown in doc
-/// let res = try::try_div(10, 2)?;
+/// let res = doccomments::try_div(10, 2)?;
/// # Ok(()) // returning from try_main
/// # }
/// # fn main() { // starting main that'll unwrap()
@@ -106,6 +107,6 @@ pub fn try_div(a: i32, b: i32) -> Result<i32, String> {
* [API Guidelines][doc-nursery] on documentation guidelines
[doc-nursery]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html
-[markdown]: https://daringfireball.net/projects/markdown/
+[commonmark]: https://commonmark.org/
[RFC505]: https://github.com/rust-lang/rfcs/blob/master/text/0505-api-comment-conventions.md
[question-instead-of-unwrap]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html#examples-use--not-try-not-unwrap-c-question-mark
diff --git a/src/doc/rust-by-example/src/types/cast.md b/src/doc/rust-by-example/src/types/cast.md
index 6182874cd..deed34cf7 100644
--- a/src/doc/rust-by-example/src/types/cast.md
+++ b/src/doc/rust-by-example/src/types/cast.md
@@ -53,13 +53,13 @@ fn main() {
// Unless it already fits, of course.
println!(" 128 as a i16 is: {}", 128 as i16);
- // 128 as i8 -> -128, whose two's complement in eight bits is:
+ // 128 as u8 -> 128, whose value in 8-bit two's complement representation is:
println!(" 128 as a i8 is : {}", 128 as i8);
// repeating the example above
// 1000 as u8 -> 232
println!("1000 as a u8 is : {}", 1000 as u8);
- // and the two's complement of 232 is -24
+ // and the value of 232 in 8-bit two's complement representation is -24
println!(" 232 as a i8 is : {}", 232 as i8);
// Since Rust 1.45, the `as` keyword performs a *saturating cast*
@@ -67,23 +67,23 @@ fn main() {
// the upper bound or is less than the lower bound, the returned value
// will be equal to the bound crossed.
- // 300.0 is 255
- println!("300.0 is {}", 300.0_f32 as u8);
+ // 300.0 as u8 is 255
+ println!(" 300.0 as u8 is : {}", 300.0_f32 as u8);
// -100.0 as u8 is 0
- println!("-100.0 as u8 is {}", -100.0_f32 as u8);
+ println!("-100.0 as u8 is : {}", -100.0_f32 as u8);
// nan as u8 is 0
- println!("nan as u8 is {}", f32::NAN as u8);
+ println!(" nan as u8 is : {}", f32::NAN as u8);
// This behavior incurs a small runtime cost and can be avoided
// with unsafe methods, however the results might overflow and
// return **unsound values**. Use these methods wisely:
unsafe {
- // 300.0 is 44
- println!("300.0 is {}", 300.0_f32.to_int_unchecked::<u8>());
+ // 300.0 as u8 is 44
+ println!(" 300.0 as u8 is : {}", 300.0_f32.to_int_unchecked::<u8>());
// -100.0 as u8 is 156
- println!("-100.0 as u8 is {}", (-100.0_f32).to_int_unchecked::<u8>());
+ println!("-100.0 as u8 is : {}", (-100.0_f32).to_int_unchecked::<u8>());
// nan as u8 is 0
- println!("nan as u8 is {}", f32::NAN.to_int_unchecked::<u8>());
+ println!(" nan as u8 is : {}", f32::NAN.to_int_unchecked::<u8>());
}
}
```
diff --git a/src/doc/rust-by-example/src/unsafe/asm.md b/src/doc/rust-by-example/src/unsafe/asm.md
index ee6b8088a..7ad6e0c5e 100644
--- a/src/doc/rust-by-example/src/unsafe/asm.md
+++ b/src/doc/rust-by-example/src/unsafe/asm.md
@@ -227,7 +227,7 @@ This state is generally referred to as being "clobbered".
We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
```rust
-use core::arch::asm;
+use std::arch::asm;
fn main() {
// three entries of four bytes each
@@ -333,7 +333,7 @@ In some cases, fine control is needed over the way a register name is formatted
By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).
-This default can be overriden by using modifiers on the template string operands, just like you would with format strings:
+This default can be overridden by using modifiers on the template string operands, just like you would with format strings:
```rust
use std::arch::asm;
diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml
index c571d408d..a21e342cb 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml
@@ -14,28 +14,28 @@ jobs:
if: github.repository == 'rust-lang/rustc-dev-guide'
runs-on: ubuntu-latest
env:
- MDBOOK_VERSION: 0.4.12
- MDBOOK_LINKCHECK_VERSION: 0.7.2
- MDBOOK_MERMAID_VERSION: 0.10.0
- MDBOOK_TOC_VERSION: 0.6.1
+ MDBOOK_VERSION: 0.4.21
+ MDBOOK_LINKCHECK_VERSION: 0.7.6
+ MDBOOK_MERMAID_VERSION: 0.11.2
+ MDBOOK_TOC_VERSION: 0.9.0
DEPLOY_DIR: book/html
BASE_SHA: ${{ github.event.pull_request.base.sha }}
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
# linkcheck needs the base commit.
fetch-depth: 0
- name: Cache binaries
id: mdbook-cache
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/.cargo/bin
key: ${{ runner.os }}-${{ env.MDBOOK_VERSION }}--${{ env.MDBOOK_LINKCHECK_VERSION }}--${{ env.MDBOOK_TOC_VERSION }}--${{ env.MDBOOK_MERMAID_VERSION }}
- name: Cache linkcheck
- uses: actions/cache@v2
+ uses: actions/cache@v3
with:
path: |
~/book/linkcheck
@@ -49,10 +49,9 @@ jobs:
- name: Install latest nightly Rust toolchain
if: steps.mdbook-cache.outputs.cache-hit != 'true'
- uses: actions-rs/toolchain@v1
- with:
- toolchain: nightly
- override: true
+ run: |
+ rustup update nightly
+ rustup override set nightly
- name: Install Dependencies
if: steps.mdbook-cache.outputs.cache-hit != 'true'
diff --git a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml
index b808876a4..c34c11c1e 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/date-check.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/date-check.yml
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout repo
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Ensure Rust is up-to-date
run: |
diff --git a/src/doc/rustc-dev-guide/book.toml b/src/doc/rustc-dev-guide/book.toml
index c86ec5638..dc216760e 100644
--- a/src/doc/rustc-dev-guide/book.toml
+++ b/src/doc/rustc-dev-guide/book.toml
@@ -43,3 +43,4 @@ warning-policy = "error"
[output.html.redirect]
"/compiletest.html" = "tests/compiletest.html"
"/diagnostics/sessiondiagnostic.html" = "diagnostics/diagnostic-structs.html"
+"/miri.html" = "const-eval/interpret.html"
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 99b24fe59..360265c0e 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -152,7 +152,7 @@
- [MIR optimizations](./mir/optimizations.md)
- [Debugging](./mir/debugging.md)
- [Constant evaluation](./const-eval.md)
- - [miri const evaluator](./miri.md)
+ - [Interpreter](./const-eval/interpret.md)
- [Monomorphization](./backend/monomorph.md)
- [Lowering MIR](./backend/lowering-mir.md)
- [Code Generation](./backend/codegen.md)
diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md
index b2c71866c..71407854e 100644
--- a/src/doc/rustc-dev-guide/src/about-this-guide.md
+++ b/src/doc/rustc-dev-guide/src/about-this-guide.md
@@ -5,7 +5,7 @@ as well as to help new contributors get involved in rustc development.
There are seven parts to this guide:
-1. [Building and debugging `rustc`][p1]:
+1. [Building `rustc`][p1]:
Contains information that should be useful no matter how you are contributing,
about building, debugging, profiling, etc.
2. [Contributing to `rustc`][p2]:
@@ -23,7 +23,7 @@ There are seven parts to this guide:
7. [Appendices][p7] at the end with useful reference information.
There are a few of these with different information, including a glossary.
-[p1]: ./getting-started.md
+[p1]: ./building/how-to-build-and-run.html
[p2]: ./contributing.md
[p3]: ./part-2-intro.md
[p4]: ./part-3-intro.md
diff --git a/src/doc/rustc-dev-guide/src/appendix/glossary.md b/src/doc/rustc-dev-guide/src/appendix/glossary.md
index 375db493c..42306dc1c 100644
--- a/src/doc/rustc-dev-guide/src/appendix/glossary.md
+++ b/src/doc/rustc-dev-guide/src/appendix/glossary.md
@@ -36,6 +36,7 @@ Term | Meaning
<span id="infcx">infcx</span> &nbsp; | The type inference context (`InferCtxt`). (see `rustc_middle::infer`)
<span id="inf-var">inference variable</span> &nbsp; | When doing type or region inference, an "inference variable" is a kind of special type/region that represents what you are trying to infer. Think of X in algebra. For example, if we are trying to infer the type of a variable in a program, we create an inference variable to represent that unknown type.
<span id="intern">intern</span> &nbsp; | Interning refers to storing certain frequently-used constant data, such as strings, and then referring to the data by an identifier (e.g. a `Symbol`) rather than the data itself, to reduce memory usage and number of allocations. See [this chapter](../memory.md) for more info.
+<span id="interpreter">interpreter</span> &nbsp; | The heart of const evaluation, running MIR code at compile time. ([see more](../const-eval/interpret.md))
<span id="intrinsic">intrinsic</span> &nbsp; | Intrinsics are special functions that are implemented in the compiler itself but exposed (often unstably) to users. They do magical and dangerous things. (See [`std::intrinsics`](https://doc.rust-lang.org/std/intrinsics/index.html))
<span id="ir">IR</span> &nbsp; | Short for Intermediate Representation, a general term in compilers. During compilation, the code is transformed from raw source (ASCII text) to various IRs. In Rust, these are primarily HIR, MIR, and LLVM IR. Each IR is well-suited for some set of computations. For example, MIR is well-suited for the borrow checker, and LLVM IR is well-suited for codegen because LLVM accepts it.
<span id="irlo">IRLO</span> &nbsp; | `IRLO` or `irlo` is sometimes used as an abbreviation for [internals.rust-lang.org](https://internals.rust-lang.org).
@@ -47,7 +48,7 @@ Term | Meaning
<span id="llvm">[LLVM]</span> &nbsp; | (actually not an acronym :P) an open-source compiler backend. It accepts LLVM IR and outputs native binaries. Various languages (e.g. Rust) can then implement a compiler front-end that outputs LLVM IR and use LLVM to compile to all the platforms LLVM supports.
<span id="memoization">memoization</span> &nbsp; | The process of storing the results of (pure) computations (such as pure function calls) to avoid having to repeat them in the future. This is typically a trade-off between execution speed and memory usage.
<span id="mir">MIR</span> &nbsp; | The Mid-level IR that is created after type-checking for use by borrowck and codegen. ([see more](../mir/index.md))
-<span id="miri">miri</span> &nbsp; | An interpreter for MIR used for constant evaluation. ([see more](../miri.md))
+<span id="miri">Miri</span> &nbsp; | A tool to detect Undefined Behavior in (unsafe) Rust code. ([see more](https://github.com/rust-lang/miri))
<span id="mono">monomorphization</span> &nbsp; | The process of taking generic implementations of types and functions and instantiating them with concrete types. For example, in the code we might have `Vec<T>`, but in the final executable, we will have a copy of the `Vec` code for every concrete type used in the program (e.g. a copy for `Vec<usize>`, a copy for `Vec<MyStruct>`, etc).
<span id="normalize">normalize</span> &nbsp; | A general term for converting to a more canonical form, but in the case of rustc typically refers to [associated type normalization](../traits/goals-and-clauses.md#normalizeprojection---type).
<span id="newtype">newtype</span> &nbsp; | A wrapper around some other type (e.g., `struct Foo(T)` is a "newtype" for `T`). This is commonly used in Rust to give a stronger type for indices.
diff --git a/src/doc/rustc-dev-guide/src/backend/codegen.md b/src/doc/rustc-dev-guide/src/backend/codegen.md
index 5feea5202..e2c92430e 100644
--- a/src/doc/rustc-dev-guide/src/backend/codegen.md
+++ b/src/doc/rustc-dev-guide/src/backend/codegen.md
@@ -3,7 +3,7 @@
Code generation (or "codegen") is the part of the compiler
that actually generates an executable binary.
Usually, rustc uses LLVM for code generation,
-bu there is also support for [Cranelift] and [GCC].
+but there is also support for [Cranelift] and [GCC].
The key is that rustc doesn't implement codegen itself.
It's worth noting, though, that in the Rust source code,
many parts of the backend have `codegen` in their names
diff --git a/src/doc/rustc-dev-guide/src/backend/debugging.md b/src/doc/rustc-dev-guide/src/backend/debugging.md
index 791a61fbe..26375204e 100644
--- a/src/doc/rustc-dev-guide/src/backend/debugging.md
+++ b/src/doc/rustc-dev-guide/src/backend/debugging.md
@@ -222,7 +222,7 @@ really helpful for this.
1. Once you have some LLVM IR for the problematic code (see above), you can
create a minimal working example with Godbolt. Go to
-[gcc.godbolt.org](https://gcc.godbolt.org).
+[llvm.godbolt.org](https://llvm.godbolt.org).
2. Choose `LLVM-IR` as programming language.
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping.md b/src/doc/rustc-dev-guide/src/building/bootstrapping.md
index 939c47f1b..3bacc21d3 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping.md
@@ -54,7 +54,7 @@ and its associated dynamic libraries,
which `x.py` will download for you.
(You can also configure `x.py` to use something else.)
-The stage0 compiler is then used only to compile `rustbuild`, `std`, and `rustc`.
+The stage0 compiler is then used only to compile `src/bootstrap`, `std`, and `rustc`.
When compiling `rustc`, the stage0 compiler uses the freshly compiled `std`.
There are two concepts at play here:
a compiler (with its set of dependencies)
@@ -73,9 +73,12 @@ In theory, the stage1 compiler is functionally identical to the stage2 compiler,
but in practice there are subtle differences.
In particular, the stage1 compiler itself was built by stage0
and hence not by the source in your working directory.
-This means that the symbol names used in the compiler source
-may not match the symbol names that would have been made by the stage1 compiler,
-which can cause problems for dynamic libraries and tests.
+This means that the ABI generated by the stage0 compiler may not match the ABI that would have been
+made by the stage1 compiler, which can cause problems for dynamic libraries, tests, and tools using
+`rustc_private`.
+
+Note that the `proc_macro` crate avoids this issue with a C FFI layer called `proc_macro::bridge`,
+allowing it to be used with stage 1.
The `stage2` compiler is the one distributed with `rustup` and all other install methods.
However, it takes a very long time to build
@@ -226,14 +229,6 @@ another program we are building with the stage N compiler:
`build --stage N compiler/rustc` is linking the stage N artifacts to the `std`
built by the stage N compiler.
-Here is a chart of a full build using `x.py`:
-
-<img alt="A diagram of the rustc compilation phases" src="../img/rustc_stages.svg" class="center" />
-
-Keep in mind this diagram is a simplification, i.e. `rustdoc` can be built at
-different stages, the process is a bit different when passing flags such as
-`--keep-stage`, or if there are non-host targets.
-
### Stages and `std`
Note that there are two `std` libraries in play here:
@@ -365,7 +360,7 @@ This flag has the following effects:
Code which does not use `-Z force-unstable-if-unmarked` should include the
`#![feature(rustc_private)]` crate attribute to access these force-unstable
-crates. This is needed for things that link `rustc`, such as `miri`, `rls`, or
+crates. This is needed for things that link `rustc`, such as `miri` or
`clippy`.
You can find more discussion about sysroots in:
@@ -375,9 +370,46 @@ You can find more discussion about sysroots in:
[rustdoc PR]: https://github.com/rust-lang/rust/pull/76728
-### Directories and artifacts generated by `x.py`
+## Passing flags to commands invoked by `bootstrap`
+
+`x.py` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping.
+The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as `RUSTFLAGS` to the bootstrap stage
+(stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages.
+`RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it will be rare to want
+to use it.
+Finally, `MAGIC_EXTRA_RUSTFLAGS` bypasses the `cargo` cache to pass flags to rustc without
+recompiling all dependencies.
+
+`RUSTDOCFLAGS`, `RUSTDOCFLAGS_BOOTSTRAP`, and `RUSTDOCFLAGS_NOT_BOOTSTRAP` are anologous to
+`RUSTFLAGS`, but for rustdoc.
+
+`CARGOFLAGS` will pass arguments to cargo itself (e.g. `--timings`). `CARGOFLAGS_BOOTSTRAP` and
+`CARGOFLAGS_NOT_BOOTSTRAP` work analogously to `RUSTFLAGS_BOOTSTRAP`.
+
+`--test-args` will pass arguments through to the test runner. For `src/test/ui`, this is
+compiletest; for unit tests and doctests this is the `libtest` runner. Most test runner accept
+`--help`, which you can use to find out the options accepted by the runner.
-The following tables indicate the outputs of various stage actions:
+## Environment Variables
+
+During bootstrapping, there are a bunch of compiler-internal environment
+variables that are used. If you are trying to run an intermediate version of
+`rustc`, sometimes you may need to set some of these environment variables
+manually. Otherwise, you get an error like the following:
+
+```text
+thread 'main' panicked at 'RUSTC_STAGE was not set: NotPresent', library/core/src/result.rs:1165:5
+```
+
+If `./stageN/bin/rustc` gives an error about environment variables, that
+usually means something is quite wrong -- or you're trying to compile e.g.
+`rustc` or `std` or something that depends on environment variables. In
+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 |
|-----------------------------------------------------------|----------------------------------------------|
@@ -416,27 +448,3 @@ The following tables indicate the outputs of various stage actions:
| copy `rustdoc` | `build/HOST/stage2/bin` |
`--stage=2` stops here.
-
-## Passing stage-specific flags to `rustc`
-
-`x.py` allows you to pass stage-specific flags to `rustc` when bootstrapping.
-The `RUSTFLAGS_BOOTSTRAP` environment variable is passed as RUSTFLAGS to the bootstrap stage
-(stage0), and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages.
-
-## Environment Variables
-
-During bootstrapping, there are a bunch of compiler-internal environment
-variables that are used. If you are trying to run an intermediate version of
-`rustc`, sometimes you may need to set some of these environment variables
-manually. Otherwise, you get an error like the following:
-
-```text
-thread 'main' panicked at 'RUSTC_STAGE was not set: NotPresent', library/core/src/result.rs:1165:5
-```
-
-If `./stageN/bin/rustc` gives an error about environment variables, that
-usually means something is quite wrong -- or you're trying to compile e.g.
-`rustc` or `std` or something that depends on environment variables. In
-the unlikely case that you actually need to invoke rustc in such a situation,
-you can find the environment variable values by adding the following flag to
-your `x.py` command: `--on-fail=print-env`.
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 cce9d766a..c5cf3166d 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
@@ -150,8 +150,9 @@ This final product (stage1 compiler + libs built using that compiler)
is what you need to build other Rust programs (unless you use `#![no_std]` or
`#![no_core]`).
-You will probably find that building the stage1 `std` is a bottleneck for you** -- but fear not,
-there is a (hacky) workaround. See [the section on "recommended workflows"](./suggested.md) below.
+You will probably find that building the stage1 `std` is a bottleneck for you,
+but fear not, there is a (hacky) workaround...
+see [the section on "recommended workflows"](./suggested.md) below.
Note that this whole command just gives you a subset of the full `rustc`
build. The **full** `rustc` build (what you get with `./x.py build
@@ -220,6 +221,15 @@ fall back to using `cargo` from the installed `nightly`, `beta`, or `stable` too
`rustup install nightly` if you haven't already. See the
[rustup documentation on custom toolchains](https://rust-lang.github.io/rustup/concepts/toolchains.html#custom-toolchains).
+**Note:** rust-analyzer and IntelliJ Rust plugin use a component called
+`rust-analyzer-proc-macro-srv` to work with proc macros. If you intend to use a
+custom toolchain for a project (e.g. via `rustup override set stage1`) you may
+want to build this component:
+
+```bash
+./x.py build proc-macro-srv-cli
+```
+
## Building targets for cross-compilation
To produce a compiler that can cross-compile for other targets,
diff --git a/src/doc/rustc-dev-guide/src/building/new-target.md b/src/doc/rustc-dev-guide/src/building/new-target.md
index 77833fad1..f999a9472 100644
--- a/src/doc/rustc-dev-guide/src/building/new-target.md
+++ b/src/doc/rustc-dev-guide/src/building/new-target.md
@@ -102,15 +102,11 @@ unreleased version of `libc`, you can add it to the top-level
```diff
diff --git a/Cargo.toml b/Cargo.toml
-index be15e50e2bc..4fb1248ba99 100644
+index 1e83f05e0ca..4d0172071c1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
-@@ -66,10 +66,11 @@ cargo = { path = "src/tools/cargo" }
+@@ -113,6 +113,8 @@ cargo-util = { path = "src/tools/cargo/crates/cargo-util" }
[patch.crates-io]
- # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
- # that we're shipping as well (to ensure that the rustfmt in RLS and the
- # `rustfmt` executable are the same exact version).
- rustfmt-nightly = { path = "src/tools/rustfmt" }
+libc = { git = "https://github.com/rust-lang/libc", rev = "0bf7ce340699dcbacabdf5f16a242d2219a49ee0" }
# See comments in `src/tools/rustc-workspace-hack/README.md` for what's going on
diff --git a/src/doc/rustc-dev-guide/src/building/prerequisites.md b/src/doc/rustc-dev-guide/src/building/prerequisites.md
index 0783e82ee..100b14aca 100644
--- a/src/doc/rustc-dev-guide/src/building/prerequisites.md
+++ b/src/doc/rustc-dev-guide/src/building/prerequisites.md
@@ -9,6 +9,7 @@ Before building the compiler, you need the following things installed:
* `git`
* `ssl` which comes in `libssl-dev` or `openssl-devel`
* `pkg-config` if you are compiling on Linux and targeting Linux
+* `libstdc++-static` may be required on some Linux distributions such as Fedora and Ubuntu
If building LLVM from source (the default), you'll need additional tools:
@@ -36,8 +37,10 @@ winget install -e Python.Python.3
winget install -e Kitware.CMake
```
-If any of those is installed already, winget will detect it.
-Then edit your systems `PATH` variable and add: `C:\Program Files\CMake\bin`.
+If any of those is installed already, winget will detect it. Then edit your system's `PATH` variable
+and add: `C:\Program Files\CMake\bin`. See
+[this guide on editing the system `PATH`](https://www.java.com/en/download/help/path.html) from the
+Java documentation.
For more information about building on Windows,
see [the `rust-lang/rust` README](https://github.com/rust-lang/rust#building-on-windows).
diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md
index 3e077977d..5c5e571e4 100644
--- a/src/doc/rustc-dev-guide/src/building/suggested.md
+++ b/src/doc/rustc-dev-guide/src/building/suggested.md
@@ -36,14 +36,18 @@ you can write: <!-- date-check: apr 2022 --><!-- the date comment is for the edi
"./build/$TARGET_TRIPLE/stage0/bin/rustfmt",
"--edition=2021"
],
+ "rust-analyzer.procMacro.server": "./build/$TARGET_TRIPLE/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/$TARGET_TRIPLE/stage0-sysroot",
"rust-analyzer.rustc.source": "./Cargo.toml",
}
```
diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md
index b43be3213..c3906a80b 100644
--- a/src/doc/rustc-dev-guide/src/closure.md
+++ b/src/doc/rustc-dev-guide/src/closure.md
@@ -135,10 +135,10 @@ appropriate trait: `Fn` trait for immutable borrow, `FnMut` for mutable borrow,
and `FnOnce` for move semantics.
Most of the code related to the closure is in the
-[`compiler/rustc_typeck/src/check/upvar.rs`][upvar] file and the data structures are
+[`compiler/rustc_hir_typeck/src/upvar.rs`][upvar] file and the data structures are
declared in the file [`compiler/rustc_middle/src/ty/mod.rs`][ty].
-[upvar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/upvar/index.html
+[upvar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/upvar/index.html
[ty]:https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/index.html
Before we go any further, let's discuss how we can examine the flow of control through the rustc
@@ -146,12 +146,12 @@ codebase. For closures specifically, set the `RUST_LOG` env variable as below an
output in a file:
```console
-> RUST_LOG=rustc_typeck::check::upvar rustc +stage1 -Z dump-mir=all \
+> RUST_LOG=rustc_hir_typeck::upvar rustc +stage1 -Z dump-mir=all \
<.rs file to compile> 2> <file where the output will be dumped>
```
This uses the stage1 compiler and enables `debug!` logging for the
-`rustc_typeck::check::upvar` module.
+`rustc_hir_typeck::upvar` module.
The other option is to step through the code using lldb or gdb.
@@ -164,7 +164,7 @@ Let's start with [`upvar.rs`][upvar]. This file has something called
the [`euv::ExprUseVisitor`] which walks the source of the closure and
invokes a callback for each upvar that is borrowed, mutated, or moved.
-[`euv::ExprUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/expr_use_visitor/struct.ExprUseVisitor.html
+[`euv::ExprUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/expr_use_visitor/struct.ExprUseVisitor.html
```rust
fn main() {
@@ -210,6 +210,6 @@ self.tables
.extend(delegate.adjust_upvar_captures);
```
-[`Delegate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/expr_use_visitor/trait.Delegate.html
-[ibk]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/upvar/struct.InferBorrowKind.html
-[cmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/mem_categorization/index.html
+[`Delegate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/expr_use_visitor/trait.Delegate.html
+[ibk]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/upvar/struct.InferBorrowKind.html
+[cmt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/mem_categorization/index.html
diff --git a/src/doc/rustc-dev-guide/src/const-eval.md b/src/doc/rustc-dev-guide/src/const-eval.md
index 5a11f8cdd..a7b1c8963 100644
--- a/src/doc/rustc-dev-guide/src/const-eval.md
+++ b/src/doc/rustc-dev-guide/src/const-eval.md
@@ -20,26 +20,72 @@ Additionally constant evaluation can be used to reduce the workload or binary
size at runtime by precomputing complex operations at compiletime and only
storing the result.
+All uses of constant evaluation can either be categorized as "influencing the type system"
+(array lengths, enum variant discriminants, const generic parameters), or as solely being
+done to precompute expressions to be used at runtime.
+
Constant evaluation can be done by calling the `const_eval_*` functions of `TyCtxt`.
They're the wrappers of the `const_eval` query.
+* `const_eval_global_id_for_typeck` evaluates a constant to a valtree,
+ so the result value can be further inspected by the compiler.
+* `const_eval_global_id` evaluate a constant to an "opaque blob" containing its final value;
+ this is only useful for codegen backends and the CTFE evaluator engine itself.
+* `eval_static_initializer` specifically computes the initial values of a static.
+ Statics are special; all other functions do not represent statics correctly
+ and have thus assertions preventing their use on statics.
+
The `const_eval_*` functions use a [`ParamEnv`](./param_env.html) of environment
in which the constant is evaluated (e.g. the function within which the constant is used)
and a [`GlobalId`]. The `GlobalId` is made up of an `Instance` referring to a constant
or static or of an `Instance` of a function and an index into the function's `Promoted` table.
-Constant evaluation returns a [`EvalToConstValueResult`] with either the error, or a
-representation of the constant. `static` initializers are always represented as
-[`miri`](./miri.html) virtual memory allocations (via [`ConstValue::ByRef`]).
-Other constants get represented as [`ConstValue::Scalar`]
-or [`ConstValue::Slice`] if possible. This means that the `const_eval_*`
-functions cannot be used to create miri-pointers to the evaluated constant.
-If you need the value of a constant inside Miri, you need to directly work with
-[`const_to_op`].
+Constant evaluation returns an [`EvalToValTreeResult`] for type system constants or
+[`EvalToConstValueResult`] with either the error, or a representation of the constant.
+
+Constants for the type system are encoded in "valtree representation". The `ValTree` datastructure
+allows us to represent
+
+* arrays,
+* many structs,
+* tuples,
+* enums and,
+* most primitives.
+
+The basic rule for
+being permitted in the type system is that every value must be uniquely represented. In other
+words: a specific value must only be representable in one specific way. For example: there is only
+one way to represent an array of two integers as a `ValTree`:
+`ValTree::Branch(&[ValTree::Leaf(first_int), ValTree;:Leaf(second_int)])`.
+Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a
+`ValTree::Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree`
+(and is very complex to do, so it is unlikely anyone is tempted to do so).
+
+These rules also mean that some values are not representable. There can be no `union`s in type
+level constants, as it is not clear how they should be represented, because their active variant
+is unknown. Similarly there is no way to represent raw pointers, as addresses are unknown at
+compile-time and thus we cannot make any assumptions about them. References on the other hand
+*can* be represented, as equality for references is defined as equality on their value, so we
+ignore their address and just look at the backing value. We must make sure that the pointer values
+of the references are not observable at compile time. We thus encode `&42` exactly like `42`.
+Any conversion from
+valtree back to codegen constants must reintroduce an actual indirection. At codegen time the
+addresses may be deduplicated between multiple uses or not, entirely depending on arbitrary
+optimization choices.
+
+As a consequence, all decoding of `ValTree` must happen by matching on the type first and making
+decisions depending on that. The value itself gives no useful information without the type that
+belongs to it.
+
+Other constants get represented as [`ConstValue::Scalar`] or
+[`ConstValue::Slice`] if possible. These values are only useful outside the
+compile-time interpreter. If you need the value of a constant during
+interpretation, you need to directly work with [`const_to_op`].
[`GlobalId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/struct.GlobalId.html
[`ConstValue::Scalar`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Scalar
[`ConstValue::Slice`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.Slice
[`ConstValue::ByRef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/value/enum.ConstValue.html#variant.ByRef
[`EvalToConstValueResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToConstValueResult.html
+[`EvalToValTreeResult`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/interpret/error/type.EvalToValTreeResult.html
[`const_to_op`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/struct.InterpCx.html#method.const_to_op
diff --git a/src/doc/rustc-dev-guide/src/miri.md b/src/doc/rustc-dev-guide/src/const-eval/interpret.md
index c5de358d2..ee044505e 100644
--- a/src/doc/rustc-dev-guide/src/miri.md
+++ b/src/doc/rustc-dev-guide/src/const-eval/interpret.md
@@ -1,14 +1,13 @@
-# Miri
+# Interpreter
<!-- toc -->
-The Miri (**MIR** **I**nterpreter) engine is a virtual machine for executing MIR without
-compiling to machine code. It is usually invoked via `tcx.const_eval_*` functions.
-In the following, we will refer to the Miri engine as just "Miri", but note that
-there also is a stand-alone
-[tool called "Miri"](https://github.com/rust-lang/miri/) that is based on the
-engine (sometimes referred to as Miri-the-tool to disambiguate it from the
-engine).
+The interpreter is a virtual machine for executing MIR without compiling to
+machine code. It is usually invoked via `tcx.const_eval_*` functions. The
+interpreter is shared between the compiler (for compile-time function
+evaluation, CTFE) and the tool [Miri](https://github.com/rust-lang/miri/), which
+uses the same virtual machine to detect Undefined Behavior in (unsafe) Rust
+code.
If you start out with a constant:
@@ -98,7 +97,7 @@ further queries need to be executed in order to get at something as simple as a
`usize`.
Future evaluations of the same constants will not actually invoke
-Miri, but just use the cached result.
+the interpreter, but just use the cached result.
[`Operand`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/enum.Operand.html
[`Immediate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_const_eval/interpret/enum.Immediate.html
@@ -108,7 +107,7 @@ Miri, but just use the cached result.
## Datastructures
-Miri's outside-facing datastructures can be found in
+The interpreter's outside-facing datastructures can be found in
[rustc_middle/src/mir/interpret](https://github.com/rust-lang/rust/blob/master/compiler/rustc_middle/src/mir/interpret).
This is mainly the error enum and the [`ConstValue`] and [`Scalar`] types. A
`ConstValue` can be either `Scalar` (a single `Scalar`, i.e., integer or thin
@@ -124,7 +123,7 @@ in an `Option<u64>` yielding the `Scalar` if possible.
## Memory
-To support any kind of pointers, Miri needs to have a "virtual memory" that the
+To support any kind of pointers, the interpreter needs to have a "virtual memory" that the
pointers can point to. This is implemented in the [`Memory`] type. In the
simplest model, every global variable, stack variable and every dynamic
allocation corresponds to an [`Allocation`] in that memory. (Actually using an
@@ -164,7 +163,7 @@ track of which of its bytes are initialized.
### Global memory and exotic allocations
-`Memory` exists only during the Miri evaluation; it gets destroyed when the
+`Memory` exists only during evaluation; it gets destroyed when the
final value of the constant is computed. In case that constant contains any
pointers, those get "interned" and moved to a global "const eval memory" that is
part of `TyCtxt`. These allocations stay around for the remaining computation
@@ -190,10 +189,10 @@ bytes of its value.
### Pointer values vs Pointer types
-One common cause of confusion in Miri is that being a pointer *value* and having
+One common cause of confusion in the interpreter is that being a pointer *value* and having
a pointer *type* are entirely independent properties. By "pointer value", we
refer to a `Scalar::Ptr` containing a `Pointer` and thus pointing somewhere into
-Miri's virtual memory. This is in contrast to `Scalar::Raw`, which is just some
+the interpreter's virtual memory. This is in contrast to `Scalar::Raw`, which is just some
concrete integer.
However, a variable of pointer or reference *type*, such as `*const T` or `&T`,
@@ -214,7 +213,7 @@ that allow accessing the fields of a `ConstValue` (`ByRef` or otherwise). You sh
never have to access an `Allocation` directly except for translating it to the
compilation target (at the moment just LLVM).
-Miri starts by creating a virtual stack frame for the current constant that is
+The interpreter starts by creating a virtual stack frame for the current constant that is
being evaluated. There's essentially no difference between a constant and a
function with no arguments, except that constants do not allow local (named)
variables at the time of writing this guide.
@@ -231,7 +230,7 @@ The frames are just a `Vec<Frame>`, there's no way to actually refer to a
`Frame`'s memory even if horrible shenanigans are done via unsafe code. The only
memory that can be referred to are `Allocation`s.
-Miri now calls the `step` method (in
+The interpreter now calls the `step` method (in
[rustc_const_eval/src/interpret/step.rs](https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/step.rs)
) until it either returns an error or has no further statements to execute. Each
statement will now initialize or modify the locals or the virtual memory
diff --git a/src/doc/rustc-dev-guide/src/contributing.md b/src/doc/rustc-dev-guide/src/contributing.md
index e59bb0a77..279bc2f28 100644
--- a/src/doc/rustc-dev-guide/src/contributing.md
+++ b/src/doc/rustc-dev-guide/src/contributing.md
@@ -183,6 +183,7 @@ As a developer to this repository, you don't have to treat the following externa
differently from other crates that are directly in this repo:
* [Clippy](https://github.com/rust-lang/rust-clippy)
+* [Miri](https://github.com/rust-lang/miri)
* [rustfmt](https://github.com/rust-lang/rustfmt)
* [rust-analyzer](https://github.com/rust-lang/rust-analyzer)
@@ -249,37 +250,36 @@ subtrees) actually needs to use `git subtree`.
### External Dependencies (submodules)
-Currently building Rust will also build the following external projects:
+Building Rust will also use external git repositories tracked using [git
+submodules]. The complete list may be found in the [`.gitmodules`] file. Some
+of these projects are required (like `stdarch` for the standard library) and
+some of them are optional (like [Miri]).
-* [miri](https://github.com/rust-lang/miri)
-* [rls](https://github.com/rust-lang/rls/)
+Usage of submodules is discussed more in the [Using Git
+chapter](git.md#git-submodules).
-We allow breakage of these tools in the nightly channel. Maintainers of these
-projects will be notified of the breakages and should fix them as soon as
-possible.
-
-After the external is fixed, one could add the changes with
-
-```sh
-git add path/to/submodule
-```
-
-outside the submodule.
-
-In order to prepare your tool-fixing PR, you can run the build locally by doing
-`./x.py build src/tools/TOOL`. If you will be editing the sources
-there, you may wish to set `submodules = false` in the `config.toml`
-to prevent `x.py` from resetting to the original branch.
+Some of the submodules are allowed to be in a "broken" state where they
+either don't build or their tests don't pass, e.g. the documentation books
+like [The Rust Reference]. Maintainers of these projects will be notified
+when the project is in a broken state, and they should fix them as soon
+as possible. The current status is tracked on the [toolstate website].
+More information may be found on the Forge [Toolstate chapter].
Breakage is not allowed in the beta and stable channels, and must be addressed
-before the PR is merged.
+before the PR is merged. They are also not allowed to be broken on master in
+the week leading up to the beta cut.
+
+[git submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
+[`.gitmodules`]: https://github.com/rust-lang/rust/blob/master/.gitmodules
+[The Rust Reference]: https://github.com/rust-lang/reference/
+[toolstate website]: https://rust-lang-nursery.github.io/rust-toolstate/
+[Toolstate chapter]: https://forge.rust-lang.org/infra/toolstate.html
#### Breaking Tools Built With The Compiler
Rust's build system builds a number of tools that make use of the internals of
the compiler and that are hosted in a separate repository, and included in Rust
-via git submodules. This includes [RLS](https://github.com/rust-lang/rls) and
-[Miri](https://github.com/rust-lang/Miri). If these tools break because of your
+via git submodules (such as [Miri]). If these tools break because of your
changes, you may run into a sort of "chicken and egg" problem. These tools rely
on the latest compiler to be built so you can't update them (in their own
repositories) to reflect your changes to the compiler until those changes are
@@ -299,7 +299,7 @@ done and the tools are working again, you go back in the compiler and update the
tools so they can be distributed again.
This should avoid a bunch of synchronization dances and is also much easier on contributors as
-there's no need to block on rls/miri/other tools changes going upstream.
+there's no need to block on tools changes going upstream.
Here are those same steps in detail:
@@ -309,8 +309,8 @@ Here are those same steps in detail:
from resetting to the original branch after you make your changes. If you
need to [update any submodules to their latest versions](#updating-submodules),
see the section of this file about that for more information.
-2. (optional) Run `./x.py test src/tools/rls` (substituting the submodule
- that broke for `rls`). Fix any errors in the submodule (and possibly others).
+2. (optional) Run `./x.py test src/tools/cargo` (substituting the submodule
+ that broke for `cargo`). Fix any errors in the submodule (and possibly others).
3. (optional) Make commits for your changes and send them to upstream repositories as a PR.
4. (optional) Maintainers of these submodules will **not** merge the PR. The PR can't be
merged because CI will be broken. You'll want to write a message on the PR referencing
@@ -320,71 +320,6 @@ Here are those same steps in detail:
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.
-#### Updating submodules
-
-These instructions are specific to updating `rls`, however they may apply
-to the other submodules as well. Please help by improving these instructions
-if you find any discrepancies or special cases that need to be addressed.
-
-To update the `rls` submodule, start by running the appropriate
-[`git submodule` command](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
-For example, to update to the latest commit on the remote master branch,
-you may want to run:
-```
-git submodule update --remote src/tools/rls
-```
-If you run `./x.py build` now, and you are lucky, it may just work. If you see
-an error message about patches that did not resolve to any crates, you will need
-to complete a few more steps which are outlined with their rationale below.
-
-*(This error may change in the future to include more information.)*
-```
-error: failed to resolve patches for `https://github.com/rust-lang/rls`
-
-Caused by:
- patch for `rls` in `https://github.com/rust-lang/rls` did not resolve to any crates
-failed to run: ~/rust/build/x86_64-unknown-linux-gnu/stage0/bin/cargo build --manifest-path ~/rust/src/bootstrap/Cargo.toml
-```
-
-The [`[patch]`][patchsec] section of `Cargo.toml` can be very useful for
-testing. In addition to that, you should read the [Overriding
-dependencies][overriding] section of the documentation.
-
-[patchsec]: http://doc.crates.io/manifest.html#the-patch-section
-[overriding]: http://doc.crates.io/specifying-dependencies.html#overriding-dependencies
-
-Specifically, the following [section in Overriding dependencies][testingbugfix]
-reveals what the problem is:
-
-[testingbugfix]: http://doc.crates.io/specifying-dependencies.html#testing-a-bugfix
-
-> Next up we need to ensure that our lock file is updated to use this new
-> version of uuid so our project uses the locally checked out copy instead of
-> one from crates.io. The way `[patch]` works is that it'll load the dependency
-> at ../path/to/uuid and then whenever crates.io is queried for versions of
-> uuid it'll also return the local version.
->
-> This means that the version number of the local checkout is significant and
-> will affect whether the patch is used. Our manifest declared uuid = "1.0"
-> which means we'll only resolve to >= 1.0.0, < 2.0.0, and Cargo's greedy
-> resolution algorithm also means that we'll resolve to the maximum version
-> within that range. Typically this doesn't matter as the version of the git
-> repository will already be greater or match the maximum version published on
-> crates.io, but it's important to keep this in mind!
-
-This says that when we updated the submodule, the version number in our
-`src/tools/rls/Cargo.toml` changed. The new version is different from
-the version in `Cargo.lock`, so the build can no longer continue.
-
-To resolve this, we need to update `Cargo.lock`. Luckily, cargo provides a
-command to do this easily.
-
-```
-$ cargo update -p rls
-```
-
-This should change the version listed in `Cargo.lock` to the new version you updated
-the submodule to. Running `./x.py build` should work now.
## Writing Documentation
diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md
index 0f0bfd895..e1d5fbe1a 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics.md
@@ -314,10 +314,10 @@ reporting errors.
[errors]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html
-Diagnostics can be implemented as types which implement the `SessionDiagnostic`
+Diagnostics can be implemented as types which implement the `IntoDiagnostic`
trait. This is preferred for new diagnostics as it enforces a separation
between diagnostic emitting logic and the main code paths. For less-complex
-diagnostics, the `SessionDiagnostic` trait can be derived -- see [Diagnostic
+diagnostics, the `IntoDiagnostic` trait can be derived -- see [Diagnostic
structs][diagnostic-structs]. Within the trait implementation, the APIs
described below can be used as normal.
@@ -388,10 +388,8 @@ In addition to telling the user exactly _why_ their code is wrong, it's
oftentimes furthermore possible to tell them how to fix it. To this end,
`DiagnosticBuilder` offers a structured suggestions API, which formats code
suggestions pleasingly in the terminal, or (when the `--error-format json` flag
-is passed) as JSON for consumption by tools, most notably the [Rust Language
-Server][rls] and [`rustfix`][rustfix].
+is passed) as JSON for consumption by tools like [`rustfix`][rustfix].
-[rls]: https://github.com/rust-lang/rls
[rustfix]: https://github.com/rust-lang/rustfix
Not all suggestions should be applied mechanically, they have a degree of
@@ -757,7 +755,7 @@ then dumped into the `Session::buffered_lints` used by the rest of the compiler.
The compiler accepts an `--error-format json` flag to output
diagnostics as JSON objects (for the benefit of tools such as `cargo
-fix` or the RLS). It looks like this:
+fix`). It looks like this:
```console
$ rustc json_error_demo.rs --error-format json
@@ -771,7 +769,7 @@ object, but the series of lines taken together is, unfortunately, not
valid JSON, thwarting tools and tricks (such as [piping to `python3 -m
json.tool`](https://docs.python.org/3/library/json.html#module-json.tool))
that require such. (One speculates that this was intentional for LSP
-performance purposes, so that each line/object can be sent to RLS as
+performance purposes, so that each line/object can be sent as
it is flushed?)
Also note the "rendered" field, which contains the "human" output as a
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 f456474c7..d51e79348 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md
@@ -1,14 +1,14 @@
# Diagnostic and subdiagnostic structs
rustc has two diagnostic derives that can be used to create simple diagnostics,
which are recommended to be used when they are applicable:
-`#[derive(SessionDiagnostic)]` and `#[derive(SessionSubdiagnostic)]`.
+`#[derive(Diagnostic)]` and `#[derive(Subdiagnostic)]`.
Diagnostics created with the derive macros can be translated into different
languages and each has a slug that uniquely identifies the diagnostic.
-## `#[derive(SessionDiagnostic)]`
+## `#[derive(Diagnostic)]`
Instead of using the `DiagnosticBuilder` API to create and emit diagnostics,
-the `SessionDiagnostic` derive can be used. `#[derive(SessionDiagnostic)]` is
+the `Diagnostic` derive can be used. `#[derive(Diagnostic)]` is
only applicable for simple diagnostics that don't require much logic in
deciding whether or not to add additional subdiagnostics.
@@ -16,24 +16,24 @@ Consider the [definition][defn] of the "field already declared" diagnostic
shown below:
```rust,ignore
-#[derive(SessionDiagnostic)]
-#[diag(typeck::field_already_declared, code = "E0124")]
+#[derive(Diagnostic)]
+#[diag(hir_analysis_field_already_declared, code = "E0124")]
pub struct FieldAlreadyDeclared {
pub field_name: Ident,
#[primary_span]
#[label]
pub span: Span,
- #[label(typeck::previous_decl_label)]
+ #[label(hir_analysis_previous_decl_label)]
pub prev_span: Span,
}
```
-`SessionDiagnostic` can only be applied to structs. Every `SessionDiagnostic`
+`Diagnostic` can only be applied to structs. Every `Diagnostic`
has to have one attribute, `#[diag(...)]`, applied to the struct itself.
If an error has an error code (e.g. "E0624"), then that can be specified using
the `code` sub-attribute. Specifying a `code` isn't mandatory, but if you are
-porting a diagnostic that uses `DiagnosticBuilder` to use `SessionDiagnostic`
+porting a diagnostic that uses `DiagnosticBuilder` to use `Diagnostic`
then you should keep the code if there was one.
`#[diag(..)]` must provide a slug as the first positional argument (a path to an
@@ -47,16 +47,16 @@ In our example, the Fluent message for the "field already declared" diagnostic
looks like this:
```fluent
-typeck_field_already_declared =
+hir_analysis_field_already_declared =
field `{$field_name}` is already declared
.label = field already declared
.previous_decl_label = `{$field_name}` first declared here
```
-`typeck_field_already_declared` is the slug from our example and is followed
+`hir_analysis_field_already_declared` is the slug from our example and is followed
by the diagnostic message.
-Every field of the `SessionDiagnostic` which does not have an annotation is
+Every field of the `Diagnostic` which does not have an annotation is
available in Fluent messages as a variable, like `field_name` in the example
above. Fields can be annotated `#[skip_arg]` if this is undesired.
@@ -66,19 +66,19 @@ of the diagnostic.
Diagnostics are more than just their primary message, they often include
labels, notes, help messages and suggestions, all of which can also be
-specified on a `SessionDiagnostic`.
+specified on a `Diagnostic`.
`#[label]`, `#[help]` and `#[note]` can all be applied to fields which have the
type `Span`. Applying any of these attributes will create the corresponding
subdiagnostic with that `Span`. These attributes will look for their
diagnostic message in a Fluent attribute attached to the primary Fluent
message. In our example, `#[label]` will look for
-`typeck_field_already_declared.label` (which has the message "field already
+`hir_analysis_field_already_declared.label` (which has the message "field already
declared"). If there is more than one subdiagnostic of the same type, then
these attributes can also take a value that is the attribute name to look for
(e.g. `previous_decl_label` in our example).
-Other types have special behavior when used in a `SessionDiagnostic` derive:
+Other types have special behavior when used in a `Diagnostic` derive:
- Any attribute applied to an `Option<T>` and will only emit a
subdiagnostic if the option is `Some(..)`.
@@ -107,21 +107,21 @@ the value of the `field_name` field of the struct), not a Fluent identifier.
`applicability` can be used to specify the applicability in the attribute, it
cannot be used when the field's type contains an `Applicability`.
-In the end, the `SessionDiagnostic` derive will generate an implementation of
-`SessionDiagnostic` that looks like the following:
+In the end, the `Diagnostic` derive will generate an implementation of
+`IntoDiagnostic` that looks like the following:
```rust,ignore
-impl SessionDiagnostic<'_> for FieldAlreadyDeclared {
- fn into_diagnostic(self, sess: &'_ rustc_session::Session) -> DiagnosticBuilder<'_> {
- let mut diag = sess.struct_err(rustc_errors::fluent::typeck::field_already_declared);
+impl IntoDiagnostic<'_> for FieldAlreadyDeclared {
+ fn into_diagnostic(self, handler: &'_ rustc_errors::Handler) -> DiagnosticBuilder<'_> {
+ let mut diag = handler.struct_err(rustc_errors::fluent::hir_analysis_field_already_declared);
diag.set_span(self.span);
diag.span_label(
self.span,
- rustc_errors::fluent::typeck::label
+ rustc_errors::fluent::hir_analysis_label
);
diag.span_label(
self.prev_span,
- rustc_errors::fluent::typeck::previous_decl_label
+ rustc_errors::fluent::hir_analysis_previous_decl_label
);
diag
}
@@ -141,22 +141,20 @@ tcx.sess.emit_err(FieldAlreadyDeclared {
```
### Reference
-`#[derive(SessionDiagnostic)]` and `#[derive(LintDiagnostic)]` support the
+`#[derive(Diagnostic)]` and `#[derive(LintDiagnostic)]` support the
following attributes:
- `#[diag(slug, code = "...")]`
- - _Applied to struct._
+ - _Applied to struct or enum variant._
- _Mandatory_
- Defines the text and error code to be associated with the diagnostic.
- Slug (_Mandatory_)
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
mandatory.
- - A path to an item in `rustc_errors::fluent`. Always in a module starting
- with a Fluent resource name (which is typically the name of the crate
- that the diagnostic is from), e.g.
- `rustc_errors::fluent::typeck::field_already_declared`
+ - A path to an item in `rustc_errors::fluent`, e.g.
+ `rustc_errors::fluent::hir_analysis_field_already_declared`
(`rustc_errors::fluent` is implicit in the attribute, so just
- `typeck::field_already_declared`).
+ `hir_analysis_field_already_declared`).
- See [translation documentation](./translation.md).
- `code = "..."` (_Optional_)
- Specifies the error code.
@@ -191,14 +189,12 @@ following attributes:
- _Applied to `(Span, MachineApplicability)` or `Span` fields._
- Adds a suggestion subdiagnostic.
- Slug (_Mandatory_)
- - A path to an item in `rustc_errors::fluent`. Always in a module starting
- with a Fluent resource name (which is typically the name of the crate
- that the diagnostic is from), e.g.
- `rustc_errors::fluent::typeck::field_already_declared`
+ - A path to an item in `rustc_errors::fluent`, e.g.
+ `rustc_errors::fluent::hir_analysis_field_already_declared`
(`rustc_errors::fluent` is implicit in the attribute, so just
- `typeck::field_already_declared`). Fluent attributes for all messages
- exist as top-level items in that module (so `typeck_message.attr` is just
- `typeck::attr`).
+ `hir_analysis_field_already_declared`). Fluent attributes for all messages
+ exist as top-level items in that module (so `hir_analysis_message.attr` is just
+ `attr`).
- See [translation documentation](./translation.md).
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
- `.suggestion` in Fluent).
@@ -210,20 +206,20 @@ following attributes:
`has-placeholders` or `unspecified`.
- `#[subdiagnostic]`
- _Applied to a type that implements `AddToDiagnostic` (from
- `#[derive(SessionSubdiagnostic)]`)._
+ `#[derive(Subdiagnostic)]`)._
- Adds the subdiagnostic represented by the subdiagnostic struct.
- `#[primary_span]` (_Optional_)
- - _Applied to `Span` fields on `SessionSubdiagnostic`s. Not used for `LintDiagnostic`s._
+ - _Applied to `Span` fields on `Subdiagnostic`s. Not used for `LintDiagnostic`s._
- Indicates the primary span of the diagnostic.
- `#[skip_arg]` (_Optional_)
- _Applied to any field._
- Prevents the field from being provided as a diagnostic argument.
-## `#[derive(SessionSubdiagnostic)]`
+## `#[derive(Subdiagnostic)]`
It is common in the compiler to write a function that conditionally adds a
specific subdiagnostic to an error if it is applicable. Oftentimes these
subdiagnostics could be represented using a diagnostic struct even if the
-overall diagnostic could not. In this circumstance, the `SessionSubdiagnostic`
+overall diagnostic could not. In this circumstance, the `Subdiagnostic`
derive can be used to represent a partial diagnostic (e.g a note, label, help or
suggestion) as a struct.
@@ -231,14 +227,14 @@ Consider the [definition][subdiag_defn] of the "expected return type" label
shown below:
```rust
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum ExpectedReturnTypeLabel<'tcx> {
- #[label(typeck::expected_default_return_type)]
+ #[label(hir_analysis_expected_default_return_type)]
Unit {
#[primary_span]
span: Span,
},
- #[label(typeck::expected_return_type)]
+ #[label(hir_analysis_expected_return_type)]
Other {
#[primary_span]
span: Span,
@@ -247,9 +243,9 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
}
```
-Unlike `SessionDiagnostic`, `SessionSubdiagnostic` can be applied to structs or
+Unlike `Diagnostic`, `Subdiagnostic` can be applied to structs or
enums. Attributes that are placed on the type for structs are placed on each
-variants for enums (or vice versa). Each `SessionSubdiagnostic` should have one
+variants for enums (or vice versa). Each `Subdiagnostic` should have one
attribute applied to the struct or each variant, one of:
- `#[label(..)]` for defining a label
@@ -268,9 +264,9 @@ In our example, the Fluent message for the "expected return type" label
looks like this:
```fluent
-typeck_expected_default_return_type = expected `()` because of default return type
+hir_analysis_expected_default_return_type = expected `()` because of default return type
-typeck_expected_return_type = expected `{$expected}` because of return type
+hir_analysis_expected_return_type = expected `{$expected}` because of return type
```
Using the `#[primary_span]` attribute on a field (with type `Span`) will denote
@@ -281,7 +277,7 @@ Every field of the type/variant which does not have an annotation is available
in Fluent messages as a variable. Fields can be annotated `#[skip_arg]` if this
is undesired.
-Like `SessionDiagnostic`, `SessionSubdiagnostic` supports `Option<T>` and
+Like `Diagnostic`, `Subdiagnostic` supports `Option<T>` and
`Vec<T>` fields.
Suggestions can be emitted using one of four attributes on the type/variant:
@@ -306,8 +302,8 @@ following sub-attributes:
Applicabilities can also be specified as a field (of type `Applicability`)
using the `#[applicability]` attribute.
-In the end, the `SessionSubdiagnostic` derive will generate an implementation
-of `SessionSubdiagnostic` that looks like the following:
+In the end, the `Subdiagnostic` derive will generate an implementation
+of `AddToDiagnostic` that looks like the following:
```rust
impl<'tcx> AddToDiagnostic for ExpectedReturnTypeLabel<'tcx> {
@@ -315,11 +311,11 @@ impl<'tcx> AddToDiagnostic for ExpectedReturnTypeLabel<'tcx> {
use rustc_errors::{Applicability, IntoDiagnosticArg};
match self {
ExpectedReturnTypeLabel::Unit { span } => {
- diag.span_label(span, rustc_errors::fluent::typeck::expected_default_return_type)
+ diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_default_return_type)
}
ExpectedReturnTypeLabel::Other { span, expected } => {
diag.set_arg("expected", expected);
- diag.span_label(span, rustc_errors::fluent::typeck::expected_return_type)
+ diag.span_label(span, rustc_errors::fluent::hir_analysis_expected_return_type)
}
}
@@ -333,7 +329,7 @@ diagnostic or by assigning it to a `#[subdiagnostic]`-annotated field of a
diagnostic struct.
### Reference
-`#[derive(SessionSubdiagnostic)]` supports the following attributes:
+`#[derive(Subdiagnostic)]` supports the following attributes:
- `#[label(slug)]`, `#[help(slug)]` or `#[note(slug)]`
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
@@ -342,26 +338,22 @@ diagnostic struct.
- Slug (_Mandatory_)
- Uniquely identifies the diagnostic and corresponds to its Fluent message,
mandatory.
- - A path to an item in `rustc_errors::fluent`. Always in a module starting
- with a Fluent resource name (which is typically the name of the crate
- that the diagnostic is from), e.g.
- `rustc_errors::fluent::typeck::field_already_declared`
+ - A path to an item in `rustc_errors::fluent`, e.g.
+ `rustc_errors::fluent::hir_analysis_field_already_declared`
(`rustc_errors::fluent` is implicit in the attribute, so just
- `typeck::field_already_declared`).
+ `hir_analysis_field_already_declared`).
- See [translation documentation](./translation.md).
- `#[suggestion{,_hidden,_short,_verbose}(slug, code = "...", applicability = "...")]`
- _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
- _Mandatory_
- Defines the type to be representing a suggestion.
- Slug (_Mandatory_)
- - A path to an item in `rustc_errors::fluent`. Always in a module starting
- with a Fluent resource name (which is typically the name of the crate
- that the diagnostic is from), e.g.
- `rustc_errors::fluent::typeck::field_already_declared`
+ - A path to an item in `rustc_errors::fluent`, e.g.
+ `rustc_errors::fluent::hir_analysis_field_already_declared`
(`rustc_errors::fluent` is implicit in the attribute, so just
- `typeck::field_already_declared`). Fluent attributes for all messages
- exist as top-level items in that module (so `typeck_message.attr` is just
- `typeck::attr`).
+ `hir_analysis::field_already_declared`). Fluent attributes for all messages
+ exist as top-level items in that module (so `hir_analysis_message.attr` is just
+ `hir_analysis::attr`).
- See [translation documentation](./translation.md).
- Defaults to `rustc_errors::fluent::_subdiag::suggestion` (or
- `.suggestion` in Fluent).
@@ -376,19 +368,32 @@ diagnostic struct.
- `maybe-incorrect`
- `has-placeholders`
- `unspecified`
-- `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise)
+- `#[multipart_suggestion{,_hidden,_short,_verbose}(slug, applicability = "...")]`
+ - _Applied to struct or enum variant. Mutually exclusive with struct/enum variant attributes._
+ - _Mandatory_
+ - Defines the type to be representing a multipart suggestion.
+ - Slug (_Mandatory_): see `#[suggestion]`
+ - `applicability = "..."` (_Optional_): see `#[suggestion]`
+- `#[primary_span]` (_Mandatory_ for labels and suggestions; _optional_ otherwise; not applicable
+to multipart suggestions)
- _Applied to `Span` fields._
- Indicates the primary span of the subdiagnostic.
-- `#[applicability]` (_Optional_; only applicable to suggestions)
+- `#[suggestion_part(code = "...")]` (_Mandatory_; only applicable to multipart suggestions)
+ - _Applied to `Span` fields._
+ - Indicates the span to be one part of the multipart suggestion.
+ - `code = "..."` (_Mandatory_)
+ - Value is a format string indicating the code to be suggested as a
+ replacement.
+- `#[applicability]` (_Optional_; only applicable to (simple and multipart) suggestions)
- _Applied to `Applicability` fields._
- Indicates the applicability of the suggestion.
- `#[skip_arg]` (_Optional_)
- _Applied to any field._
- Prevents the field from being provided as a diagnostic argument.
-[defn]: https://github.com/rust-lang/rust/blob/bbe9d27b8ff36da56638aa43d6d0cdfdf89a4e57/compiler/rustc_typeck/src/errors.rs#L65-L74
-[use]: https://github.com/rust-lang/rust/blob/eb82facb1626166188d49599a3313fc95201f556/compiler/rustc_typeck/src/collect.rs#L981-L985
+[defn]: https://github.com/rust-lang/rust/blob/6201eabde85db854c1ebb57624be5ec699246b50/compiler/rustc_hir_analysis/src/errors.rs#L68-L77
+[use]: https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/collect.rs#L823-L827
-[subdiag_defn]: https://github.com/rust-lang/rust/blob/e70c60d34b9783a2fd3171d88d248c2e0ec8ecdd/compiler/rustc_typeck/src/errors.rs#L220-L233
-[subdiag_use_1]: https://github.com/rust-lang/rust/blob/e70c60d34b9783a2fd3171d88d248c2e0ec8ecdd/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs#L556-L560
-[subdiag_use_2]: https://github.com/rust-lang/rust/blob/e70c60d34b9783a2fd3171d88d248c2e0ec8ecdd/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs#L575-L579
+[subdiag_defn]: https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/errors.rs#L221-L234
+[subdiag_use_1]: https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs#L670-L674
+[subdiag_use_2]: https://github.com/rust-lang/rust/blob/f1112099eba41abadb6f921df7edba70affe92c5/compiler/rustc_hir_analysis/src/check/fn_ctxt/suggestions.rs#L704-L707
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/translation.md b/src/doc/rustc-dev-guide/src/diagnostics/translation.md
index 5bb37fbc2..e36333039 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/translation.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/translation.md
@@ -11,7 +11,7 @@ There are two ways of writing translatable diagnostics:
diagnostic structs). See [the diagnostic and subdiagnostic structs
documentation](./diagnostic-structs.md).
2. Using typed identifiers with `DiagnosticBuilder` APIs (in
- `SessionDiagnostic` implementations).
+ `Diagnostic` implementations).
When adding or changing a translatable diagnostic, you don't need to worry
about the translations, only updating the original English message. Currently,
@@ -127,14 +127,12 @@ pub static DEFAULT_LOCALE_RESOURCES: &'static [&'static str] = &[
];
mod fluent_generated {
- mod typeck {
- pub const field_multiply_specified_in_initializer: DiagnosticMessage =
- DiagnosticMessage::new("typeck_field_multiply_specified_in_initializer");
- pub const label: SubdiagnosticMessage =
- SubdiagnosticMessage::attr("label");
- pub const label_previous_use: SubdiagnosticMessage =
- SubdiagnosticMessage::attr("previous_use_label");
- }
+ pub const typeck_field_multiply_specified_in_initializer: DiagnosticMessage =
+ DiagnosticMessage::new("typeck_field_multiply_specified_in_initializer");
+ pub const label: SubdiagnosticMessage =
+ SubdiagnosticMessage::attr("label");
+ pub const label_previous_use: SubdiagnosticMessage =
+ SubdiagnosticMessage::attr("previous_use_label");
}
```
@@ -143,9 +141,9 @@ mod fluent_generated {
```rust
use rustc_errors::fluent;
-let mut err = sess.struct_span_err(span, fluent::typeck::field_multiply_specified_in_initializer);
-err.span_label(span, fluent::typeck::label);
-err.span_label(previous_use_span, fluent::typeck::previous_use_label);
+let mut err = sess.struct_span_err(span, fluent::typeck_field_multiply_specified_in_initializer);
+err.span_label(span, fluent::label);
+err.span_label(previous_use_span, fluent::previous_use_label);
err.emit();
```
diff --git a/src/doc/rustc-dev-guide/src/feature-gates.md b/src/doc/rustc-dev-guide/src/feature-gates.md
index 229281f2f..9e9a83ea6 100644
--- a/src/doc/rustc-dev-guide/src/feature-gates.md
+++ b/src/doc/rustc-dev-guide/src/feature-gates.md
@@ -9,7 +9,9 @@ modifying feature gates.
See ["Stability in code"] for help with adding a new feature; this section just
covers how to add the feature gate *declaration*.
-Add a feature gate declaration to `rustc_feature/src/active.rs` in the active
+First, add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block.
+
+Then, add a feature gate declaration to `rustc_feature/src/active.rs` in the active
`declare_features` block:
```rust,ignore
diff --git a/src/doc/rustc-dev-guide/src/generics.md b/src/doc/rustc-dev-guide/src/generics.md
index 13549b2fb..0173bee8f 100644
--- a/src/doc/rustc-dev-guide/src/generics.md
+++ b/src/doc/rustc-dev-guide/src/generics.md
@@ -125,7 +125,7 @@ You may have a couple of followup questions…
`MyStruct`: `Adt(Foo, &[Param(0), Param(1)])`.
**`subst`** How do we actually do the substitutions? There is a function for that too! You use
-[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/trait.Subst.html) to
+[`subst`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/subst/struct.EarlyBinder.html#method.subst) to
replace a `SubstRef` with another list of types.
[Here is an example of actually using `subst` in the compiler][substex]. The exact details are not
@@ -134,7 +134,7 @@ a real `ty::Ty`. You can see that we first get some substitutions (`substs`). T
`type_of` to get a type and call `ty.subst(substs)` to get a new version of `ty` with
the substitutions made.
-[substex]: https://github.com/rust-lang/rust/blob/597f432489f12a3f33419daa039ccef11a12c4fd/src/librustc_typeck/astconv.rs#L942-L953
+[substex]: https://github.com/rust-lang/rust/blob/0940040c0486a536be4f8685c7dd9a078f9e87c2/compiler/rustc_hir_analysis/src/astconv/mod.rs#L1231-L1242
**Note on indices:** It is possible for the indices in `Param` to not match with what we expect. For
example, the index could be out of bounds or it could be the index of a lifetime when we were
diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md
index 5899753ba..65397e349 100644
--- a/src/doc/rustc-dev-guide/src/git.md
+++ b/src/doc/rustc-dev-guide/src/git.md
@@ -148,8 +148,8 @@ Your branch is up to date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
+ modified: src/llvm-project (new commits)
modified: src/tools/cargo (new commits)
- modified: src/tools/rls (new commits)
no changes added to commit (use "git add" and/or "git commit -a")
```
@@ -176,6 +176,8 @@ 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
@@ -391,41 +393,41 @@ you might want to get used to the main concepts of Git before reading this secti
The `rust-lang/rust` repository uses [Git submodules] as a way to use other
Rust projects from within the `rust` repo. Examples include Rust's fork of
-`llvm-project` and many devtools such as `cargo` and `rls`.
+`llvm-project`, `cargo` and libraries like `stdarch` and `backtrace`.
Those projects are developed and maintained in an separate Git (and GitHub)
repository, and they have their own Git history/commits, issue tracker and PRs.
Submodules allow us to create some sort of embedded sub-repository inside the
`rust` repository and use them like they were directories in the `rust` repository.
-Take `miri` for example. `miri` is maintained in the [`rust-lang/miri`] repository,
-but it is used in `rust-lang/rust` by the compiler for const evaluation. We bring it
-in `rust` as a submodule, in the `src/tools/miri` folder.
+Take `llvm-project` for example. `llvm-project` is maintained in the [`rust-lang/llvm-project`]
+repository, but it is used in `rust-lang/rust` by the compiler for code generation and
+optimization. We bring it in `rust` as a submodule, in the `src/llvm-project` folder.
The contents of submodules are ignored by Git: submodules are in some sense isolated
-from the rest of the repository. However, if you try to `cd src/tools/miri` and then
+from the rest of the repository. However, if you try to `cd src/llvm-project` and then
run `git status`:
```
-HEAD detached at 3fafb835
+HEAD detached at 9567f08afc943
nothing to commit, working tree clean
```
-As far as git is concerned, you are no longer in the `rust` repo, but in the `miri` repo.
+As far as git is concerned, you are no longer in the `rust` repo, but in the `llvm-project` repo.
You will notice that we are in "detached HEAD" state, i.e. not on a branch but on a
particular commit.
This is because, like any dependency, we want to be able to control which version to use.
Submodules allow us to do just that: every submodule is "pinned" to a certain
commit, which doesn't change unless modified manually. If you use `git checkout <commit>`
-in the `miri` directory and go back to the `rust` directory, you can stage this
-change like any other, e.g. by running `git add src/tools/miri`. (Note that if
+in the `llvm-project` directory and go back to the `rust` directory, you can stage this
+change like any other, e.g. by running `git add src/llvm-project`. (Note that if
you *don't* stage the change to commit, then you run the risk that running
`x.py` will just undo your change by switching back to the previous commit when
it automatically "updates" the submodules.)
This version selection is usually done by the maintainers of the project, and
-looks like [this][miri-update].
+looks like [this][llvm-update].
Git submodules take some time to get used to, so don't worry if it isn't perfectly
clear yet. You will rarely have to use them directly and, again, you don't need
@@ -434,6 +436,5 @@ exist and that they correspond to some sort of embedded subrepository dependency
that Git can nicely and fairly conveniently handle for us.
[Git submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
-[`rust-toolstate`]: https://rust-lang-nursery.github.io/rust-toolstate/
-[`rust-lang/miri`]: https://github.com/rust-lang/miri
-[miri-update]: https://github.com/rust-lang/rust/pull/77500/files
+[`rust-lang/llvm-project`]: https://github.com/rust-lang/llvm-project
+[llvm-update]: https://github.com/rust-lang/rust/pull/99464/files
diff --git a/src/doc/rustc-dev-guide/src/img/rustc_stages.svg b/src/doc/rustc-dev-guide/src/img/rustc_stages.svg
deleted file mode 100644
index 25f7ab11b..000000000
--- a/src/doc/rustc-dev-guide/src/img/rustc_stages.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" style="background-color: rgb(255, 255, 255);" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="581px" height="816px" viewBox="-0.5 -0.5 581 816"><defs/><g><rect x="0" y="0" width="580" height="315" fill="#ffffff" stroke="#000000" pointer-events="all"/><rect x="0" y="665" width="580" height="150" fill="#ffffff" stroke="#000000" pointer-events="all"/><rect x="0" y="345" width="580" height="287.5" fill="#ffffff" stroke="#000000" pointer-events="all"/><path d="M 120 25 L 193.63 25" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 198.88 25 L 191.88 28.5 L 193.63 25 L 191.88 21.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 25px; margin-left: 160px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Download</div></div></div></foreignObject><text x="160" y="28" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Download</text></switch></g><rect x="40" y="10" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 25px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">beta</div></div></div></foreignObject><text x="80" y="29" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">beta</text></switch></g><rect x="200" y="10" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 25px; margin-left: 201px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0</div></div></div></foreignObject><text x="240" y="29" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0</text></switch></g><path d="M 120 120 L 173.63 120" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 120 L 171.88 123.5 L 173.63 120 L 171.88 116.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="105" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0</div></div></div></foreignObject><text x="80" y="124" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0</text></switch></g><path d="M 260 120 L 313.63 120" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 120 L 311.88 123.5 L 313.63 120 L 311.88 116.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="105" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">libtest/libstd</div></div></div></foreignObject><text x="220" y="124" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">libtest/libstd</text></switch></g><path d="M 400 120 L 453.63 120" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 458.88 120 L 451.88 123.5 L 453.63 120 L 451.88 116.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 120px; margin-left: 430px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="430" y="123" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="320" y="105" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 120px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-std</div></div></div></foreignObject><text x="360" y="124" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-std</text></switch></g><path d="M 515 135 L 515 145 Q 515 155 505 155 L 230 155 Q 220 155 220 161.82 L 220 168.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 173.88 L 216.5 166.88 L 220 168.63 L 223.5 166.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="460" y="105" width="110" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 120px; margin-left: 461px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-sysroot</div></div></div></foreignObject><text x="515" y="124" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-sysroot</text></switch></g><path d="M 120 190 L 173.63 190" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 190 L 171.88 193.5 L 173.63 190 L 171.88 186.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 190px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="193" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="175" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0</div></div></div></foreignObject><text x="80" y="194" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0</text></switch></g><path d="M 260 190 L 313.63 190" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 190 L 311.88 193.5 L 313.63 190 L 311.88 186.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 190px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="193" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="175" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">rustc</div></div></div></foreignObject><text x="220" y="194" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">rustc</text></switch></g><path d="M 400 190 L 453.63 190" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 458.88 190 L 451.88 193.5 L 453.63 190 L 451.88 186.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 190px; margin-left: 430px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="430" y="193" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="320" y="175" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 190px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-rustc</div></div></div></foreignObject><text x="360" y="194" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-rustc</text></switch></g><path d="M 515 205 L 515 227.5 Q 515 237.5 505 237.5 L 230 237.5 Q 220 237.5 220 247.5 L 220 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 268.88 L 216.5 261.88 L 220 263.63 L 223.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="460" y="175" width="110" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 190px; margin-left: 461px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-sysroot</div></div></div></foreignObject><text x="515" y="194" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-sysroot</text></switch></g><path d="M 120 237.5 L 210 237.5 Q 220 237.5 220 247.5 L 220 263.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 268.88 L 216.5 261.88 L 220 263.63 L 223.5 261.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="40" y="222.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 238px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">llvm</div></div></div></foreignObject><text x="80" y="241" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">llvm</text></switch></g><path d="M 120 285 L 173.63 285" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 285 L 171.88 288.5 L 173.63 285 L 171.88 281.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="288" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="270" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 285px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0</div></div></div></foreignObject><text x="80" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0</text></switch></g><path d="M 260 285 L 313.63 285" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 285 L 311.88 288.5 L 313.63 285 L 311.88 281.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 285px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="288" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="270" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 285px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">codegen</div></div></div></foreignObject><text x="220" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">codegen</text></switch></g><rect x="320" y="270" width="100" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 285px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-codegen</div></div></div></foreignObject><text x="370" y="289" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-codegen</text></switch></g><rect x="-30" y="145" width="90" height="20" fill="none" stroke="none" transform="rotate(-90,15,155)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 15 155)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 155px; margin-left: -29px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">Stage 0</div></div></div></foreignObject><text x="15" y="162" fill="#000000" font-family="Helvetica" font-size="24px" text-anchor="middle">Stage 0</text></switch></g><path d="M 150 380 L 203.63 380" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 208.88 380 L 201.88 383.5 L 203.63 380 L 201.88 376.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 380px; margin-left: 174px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="174" y="383" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="40" y="355" width="110" height="50" rx="7.5" ry="7.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 380px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0-rustc<br />stage0-codegen<br />stage0-sysroot</div></div></div></foreignObject><text x="95" y="384" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0-rustc...</text></switch></g><path d="M 250 395 L 250 405 Q 250 415 240 415 L 90 415 Q 80 415 80 421.82 L 80 428.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 80 433.88 L 76.5 426.88 L 80 428.63 L 83.5 426.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="210" y="365" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 380px; margin-left: 211px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1</div></div></div></foreignObject><text x="250" y="384" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1</text></switch></g><path d="M 120 450 L 173.63 450" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 450 L 171.88 453.5 L 173.63 450 L 171.88 446.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 450px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="453" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="435" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 450px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1</div></div></div></foreignObject><text x="80" y="454" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1</text></switch></g><path d="M 260 450 L 313.63 450" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 450 L 311.88 453.5 L 313.63 450 L 311.88 446.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 450px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="453" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="435" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 450px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">libtest/libstd</div></div></div></foreignObject><text x="220" y="454" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">libtest/libstd</text></switch></g><path d="M 400 450 L 453.63 450" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 458.88 450 L 451.88 453.5 L 453.63 450 L 451.88 446.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 450px; margin-left: 430px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="430" y="453" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="320" y="435" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 450px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1-std</div></div></div></foreignObject><text x="360" y="454" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1-std</text></switch></g><path d="M 515 465 L 515 477.5 Q 515 487.5 505 487.5 L 230 487.5 Q 220 487.5 220 495.57 L 220 503.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 508.88 L 216.5 501.88 L 220 503.63 L 223.5 501.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="460" y="435" width="110" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 450px; margin-left: 461px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1/lib/rustlib</div></div></div></foreignObject><text x="515" y="454" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1/lib/rustlib</text></switch></g><path d="M 120 525 L 173.63 525" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 525 L 171.88 528.5 L 173.63 525 L 171.88 521.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 525px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="528" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="510" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 525px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1</div></div></div></foreignObject><text x="80" y="529" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1</text></switch></g><path d="M 260 525 L 313.63 525" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 525 L 311.88 528.5 L 313.63 525 L 311.88 521.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 525px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="528" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="510" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 525px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">rustc</div></div></div></foreignObject><text x="220" y="529" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">rustc</text></switch></g><path d="M 400 525 L 453.63 525" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 458.88 525 L 451.88 528.5 L 453.63 525 L 451.88 521.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 525px; margin-left: 430px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="430" y="528" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="320" y="510" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 525px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1-rustc</div></div></div></foreignObject><text x="360" y="529" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1-rustc</text></switch></g><path d="M 515 540 L 515 550 Q 515 560 505 560 L 230 560 Q 220 560 220 566.82 L 220 573.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 578.88 L 216.5 571.88 L 220 573.63 L 223.5 571.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="460" y="510" width="110" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 525px; margin-left: 461px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1/lib/rustlib</div></div></div></foreignObject><text x="515" y="529" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1/lib/rustlib</text></switch></g><path d="M 120 595 L 173.63 595" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 595 L 171.88 598.5 L 173.63 595 L 171.88 591.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 595px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="598" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="580" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 595px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1</div></div></div></foreignObject><text x="80" y="599" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1</text></switch></g><path d="M 260 595 L 313.63 595" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 595 L 311.88 598.5 L 313.63 595 L 311.88 591.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 595px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="598" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="580" width="80" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 595px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">codegen</div></div></div></foreignObject><text x="220" y="599" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">codegen</text></switch></g><rect x="320" y="580" width="100" height="30" rx="4.5" ry="4.5" fill="#fff2cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 98px; height: 1px; padding-top: 595px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1-codegen</div></div></div></foreignObject><text x="370" y="599" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1-codegen</text></switch></g><rect x="-30" y="510" width="90" height="20" fill="none" stroke="none" transform="rotate(-90,15,520)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 15 520)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 520px; margin-left: -29px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><div>Stage 1</div></div></div></div></foreignObject><text x="15" y="527" fill="#000000" font-family="Helvetica" font-size="24px" text-anchor="middle">Stage 1</text></switch></g><path d="M 150 702.5 L 203.63 702.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 208.88 702.5 L 201.88 706 L 203.63 702.5 L 201.88 699 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 703px; margin-left: 174px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Copy</div></div></div></foreignObject><text x="174" y="706" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="40" y="677.5" width="110" height="50" rx="7.5" ry="7.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 108px; height: 1px; padding-top: 703px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage1-rustc<br />stage1-codegen<br />stage1/lib/rustlib</div></div></div></foreignObject><text x="95" y="706" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage1-rustc...</text></switch></g><path d="M 250 717.5 L 250 730 Q 250 740 240 740 L 90 740 Q 80 740 80 748.07 L 80 756.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 80 761.38 L 76.5 754.38 L 80 756.13 L 83.5 754.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="210" y="687.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 703px; margin-left: 211px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage2</div></div></div></foreignObject><text x="250" y="706" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage2</text></switch></g><path d="M 120 777.5 L 173.63 777.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 777.5 L 171.88 781 L 173.63 777.5 L 171.88 774 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 778px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="781" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="762.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 778px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage2</div></div></div></foreignObject><text x="80" y="781" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage2</text></switch></g><path d="M 260 777.5 L 313.63 777.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 318.88 777.5 L 311.88 781 L 313.63 777.5 L 311.88 774 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 778px; margin-left: 290px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Outputs</div></div></div></foreignObject><text x="290" y="781" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Outputs</text></switch></g><rect x="180" y="762.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 778px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">rustdoc</div></div></div></foreignObject><text x="220" y="781" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">rustdoc</text></switch></g><path d="M 400 777.5 L 443.63 777.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 448.88 777.5 L 441.88 781 L 443.63 777.5 L 441.88 774 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 778px; margin-left: 425px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; "><div style="font-size: 11px">Copy</div></div></div></div></foreignObject><text x="425" y="781" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Copy</text></switch></g><rect x="320" y="762.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 778px; margin-left: 321px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage2-tools</div></div></div></foreignObject><text x="360" y="781" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage2-tools</text></switch></g><path d="M 120 70 L 173.63 70" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 178.88 70 L 171.88 73.5 L 173.63 70 L 171.88 66.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 70px; margin-left: 144px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 11px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; background-color: #ffffff; white-space: nowrap; ">Builds</div></div></div></foreignObject><text x="144" y="73" fill="#000000" font-family="Helvetica" font-size="11px" text-anchor="middle">Builds</text></switch></g><rect x="40" y="55" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 70px; margin-left: 41px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage0</div></div></div></foreignObject><text x="80" y="74" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage0</text></switch></g><rect x="180" y="55" width="80" height="30" rx="4.5" ry="4.5" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 70px; margin-left: 181px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">bootstrap</div></div></div></foreignObject><text x="220" y="74" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">bootstrap</text></switch></g><path d="M 190 560 L 130 560 Q 120 560 120 558.75 L 120 558.13 Q 120 557.5 130 557.5 L 210 557.5 Q 220 557.5 220 564.32 L 220 571.13" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 220 576.38 L 216.5 569.38 L 220 571.13 L 223.5 569.38 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><rect x="110" y="551" width="80" height="18" rx="2.7" ry="2.7" fill="#ffe6cc" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 560px; margin-left: 111px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">llvm</div></div></div></foreignObject><text x="150" y="564" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">llvm</text></switch></g><rect x="450" y="762.5" width="80" height="30" rx="4.5" ry="4.5" fill="#ccff99" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 778px; margin-left: 451px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">stage2</div></div></div></foreignObject><text x="490" y="781" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">stage2</text></switch></g><rect x="-30" y="735" width="90" height="20" fill="none" stroke="none" transform="rotate(-90,15,745)" pointer-events="all"/><g transform="translate(-0.5 -0.5)rotate(-90 15 745)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 745px; margin-left: -29px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 24px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "><div>Stage 2</div></div></div></div></foreignObject><text x="15" y="752" fill="#000000" font-family="Helvetica" font-size="24px" text-anchor="middle">Stage 2</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg> \ No newline at end of file
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 ef6ae6179..9147c1b41 100644
--- a/src/doc/rustc-dev-guide/src/implementing_new_features.md
+++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md
@@ -28,6 +28,12 @@ get by with only an r+. For example, it is OK to add or modify
unstable command-line flags or attributes without an FCP for
compiler development or standard library use, as long as you don't
expect them to be in wide use in the nightly ecosystem.
+Some teams have lighter weight processes that they use in scenarios
+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
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
@@ -123,9 +129,9 @@ a new unstable feature:
2. Pick a name for the feature gate (for RFCs, use the name
in the RFC).
-3. Add a feature gate declaration to `rustc_feature/src/active.rs`
- in the active `declare_features` block. See [here][add-feature-gate] for
- detailed instructions.
+3. Add a feature gate declaration to `rustc_feature/src/active.rs` in the active
+ `declare_features` block, and add the feature gate keyword to
+ `rustc_span/src/symbol.rs`. See [here][add-feature-gate] for detailed instructions.
4. Prevent usage of the new feature unless the feature gate is set.
You can check it in most places in the compiler using the
diff --git a/src/doc/rustc-dev-guide/src/method-lookup.md b/src/doc/rustc-dev-guide/src/method-lookup.md
index 8eb8ec5ce..8b49e8d00 100644
--- a/src/doc/rustc-dev-guide/src/method-lookup.md
+++ b/src/doc/rustc-dev-guide/src/method-lookup.md
@@ -32,8 +32,8 @@ inference variables or other information.
[fully-qualified syntax]: https://doc.rust-lang.org/nightly/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
[UFCS]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md
-[probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/probe/
-[confirm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/check/method/confirm/
+[probe]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/method/probe/
+[confirm]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/method/confirm/
## The Probe phase
diff --git a/src/doc/rustc-dev-guide/src/name-resolution.md b/src/doc/rustc-dev-guide/src/name-resolution.md
index c4f44909b..1dbc95ead 100644
--- a/src/doc/rustc-dev-guide/src/name-resolution.md
+++ b/src/doc/rustc-dev-guide/src/name-resolution.md
@@ -174,7 +174,7 @@ Still, it probably provides useful first guidepost to what happens in there.
following stages of compilation?
* Who calls it and how it is actually used.
* Is it a pass and then the result is only used, or can it be computed
- incrementally (e.g. for RLS)?
+ incrementally?
* The overall strategy description is a bit vague.
* Where does the name `Rib` come from?
* Does this thing have its own tests, or is it tested only as part of some e2e
diff --git a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
index 52d2127bf..f9c2ea74d 100644
--- a/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
+++ b/src/doc/rustc-dev-guide/src/opaque-types-impl-trait-inference.md
@@ -147,7 +147,7 @@ flowchart TD
### Relating an opaque type to another type
-There is one central place where an opaqe type gets its hidden type constrained,
+There is one central place where an opaque type gets its hidden type constrained,
and that is the `handle_opaque_type` function.
Amusingly it takes two types, so you can pass any two types,
but one of them should be an opaque type.
@@ -216,7 +216,7 @@ and then handle it correctly.
The MIR borrow checker relates things via `nll_relate` and only cares about regions.
Any type relation will trigger the binding of hidden types,
so the borrow checker is doing the same thing as the type checker,
-but ignores obivously dead code (e.g. after a panic).
+but ignores obviously dead code (e.g. after a panic).
The borrow checker is also the source of truth when it comes to hidden types,
as it is the only one who can properly figure out what lifetimes on the hidden type correspond
to which lifetimes on the opaque type declaration.
@@ -224,7 +224,7 @@ to which lifetimes on the opaque type declaration.
## Backwards compatibility hacks
`impl Trait` in return position has various quirks that were not part
-of any RFCs and are likely accidental stabilizations.
+of any RFCs and are likely accidental stabilization.
To support these,
the `replace_opaque_types_with_inference_vars` is being used to reintroduce the previous behaviour.
diff --git a/src/doc/rustc-dev-guide/src/overview.md b/src/doc/rustc-dev-guide/src/overview.md
index c7da92542..7fbdfd359 100644
--- a/src/doc/rustc-dev-guide/src/overview.md
+++ b/src/doc/rustc-dev-guide/src/overview.md
@@ -177,7 +177,7 @@ satisfy/optimize for. For example,
of space on the user's system...
- Compiler memory usage: while compiling a program, we don't want to use more
memory than we need.
-- Program speed: how fast is your compiled program. More/better compile-time
+- Program speed: how fast is your compiled program? More/better compile-time
analyses often means the compiler can do better optimizations.
- Program size: how large is the compiled binary? Similar to the previous
point.
@@ -190,7 +190,7 @@ satisfy/optimize for. For example,
the input programs says they do, and should continue to do so despite the
tremendous amount of change constantly going on.
- Integration: a number of other tools need to use the compiler in
- various ways (e.g. cargo, clippy, miri, RLS) that must be supported.
+ various ways (e.g. cargo, clippy, miri) that must be supported.
- Compiler stability: the compiler should not crash or fail ungracefully on the
stable channel.
- Rust stability: the compiler must respect Rust's stability guarantees by not
diff --git a/src/doc/rustc-dev-guide/src/panic-implementation.md b/src/doc/rustc-dev-guide/src/panic-implementation.md
index 66e61548e..d1ca202dc 100644
--- a/src/doc/rustc-dev-guide/src/panic-implementation.md
+++ b/src/doc/rustc-dev-guide/src/panic-implementation.md
@@ -28,7 +28,7 @@ Actually resolving this goes through several layers of indirection:
1. In `compiler/rustc_middle/src/middle/weak_lang_items.rs`, `panic_impl` is
declared as 'weak lang item', with the symbol `rust_begin_unwind`. This is
- used in `rustc_typeck/src/collect.rs` to set the actual symbol name to
+ used in `rustc_hir_analysis/src/collect.rs` to set the actual symbol name to
`rust_begin_unwind`.
Note that `panic_impl` is declared in an `extern "Rust"` block,
diff --git a/src/doc/rustc-dev-guide/src/rustc-driver.md b/src/doc/rustc-dev-guide/src/rustc-driver.md
index 7250c852c..cef50111d 100644
--- a/src/doc/rustc-dev-guide/src/rustc-driver.md
+++ b/src/doc/rustc-dev-guide/src/rustc-driver.md
@@ -7,7 +7,7 @@ using the interface defined in the [`rustc_interface`] crate.
The `rustc_interface` crate provides external users with an (unstable) API
for running code at particular times during the compilation process, allowing
third parties to effectively use `rustc`'s internals as a library for
-analyzing a crate or emulating the compiler in-process (e.g. the RLS or rustdoc).
+analyzing a crate or emulating the compiler in-process (e.g. rustdoc).
For those using `rustc` as a library, the [`rustc_interface::run_compiler()`][i_rc]
function is the main entrypoint to the compiler. It takes a configuration for the compiler
diff --git a/src/doc/rustc-dev-guide/src/rustdoc.md b/src/doc/rustc-dev-guide/src/rustdoc.md
index 4cdda5a3e..23428efd6 100644
--- a/src/doc/rustc-dev-guide/src/rustdoc.md
+++ b/src/doc/rustc-dev-guide/src/rustdoc.md
@@ -148,7 +148,7 @@ authors can request rebuilds, which will be run with the latest rustdoc.
Docs.rs performs some transformations on rustdoc's output in order to save
storage and display a navigation bar at the top. In particular, certain static
-files (like main.js and rustdoc.css may be shared across multiple invocations
+files, like main.js and rustdoc.css, may be shared across multiple invocations
of the same version of rustdoc. Others, like crates.js and sidebar-items.js, are
different for different invocations. Still others, like fonts, will never
change. These categories are distinguished using the `SharedResource` enum in
diff --git a/src/doc/rustc-dev-guide/src/stability.md b/src/doc/rustc-dev-guide/src/stability.md
index 3469ce2ba..b7308ee73 100644
--- a/src/doc/rustc-dev-guide/src/stability.md
+++ b/src/doc/rustc-dev-guide/src/stability.md
@@ -74,13 +74,11 @@ To stabilize a feature, follow these steps:
0. Ask a **@T-libs-api** member to start an FCP on the tracking issue and wait for
the FCP to complete (with `disposition-merge`).
-1. Change `#[unstable(...)]` to `#[stable(since = "version")]`.
- `version` should be the *current nightly*, i.e. stable+2. You can see which version is
- the current nightly [on Forge](https://forge.rust-lang.org/#current-release-versions).
+1. Change `#[unstable(...)]` to `#[stable(since = "CURRENT_RUSTC_VERSION")]`.
2. Remove `#![feature(...)]` from any test or doc-test for this API. If the feature is used in the
compiler or tools, remove it from there as well.
3. If applicable, change `#[rustc_const_unstable(...)]` to
- `#[rustc_const_stable(since = "version")]`.
+ `#[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")]`.
4. Open a PR against `rust-lang/rust`.
- Add the appropriate labels: `@rustbot modify labels: +T-libs-api`.
- Link to the tracking issue and say "Closes #XXXXX".
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 21f834130..cca4973cb 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -2,9 +2,10 @@
## Testing infrastructure
+<!-- date-check: oct 2022 -->
When a Pull Request is opened on GitHub, [GitHub Actions] will automatically
launch a build that will run all tests on some configurations
-(x86_64-gnu-llvm-12 linux. x86_64-gnu-tools linux, mingw-check linux).
+(x86_64-gnu-llvm-13 linux, x86_64-gnu-tools linux, and mingw-check linux).
In essence, each runs `./x.py test` with various different options.
The integration bot [bors] is used for coordinating merges to the master branch.
diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md
index 8b65e4df5..66e0a9eef 100644
--- a/src/doc/rustc-dev-guide/src/tests/intro.md
+++ b/src/doc/rustc-dev-guide/src/tests/intro.md
@@ -115,7 +115,7 @@ will unpack, build, and run all tests.
### Tool tests
Packages that are included with Rust have all of their tests run as well.
-This includes things such as cargo, clippy, rustfmt, rls, miri, bootstrap
+This includes things such as cargo, clippy, rustfmt, miri, bootstrap
(testing the Rust build system itself), etc.
Most of the tools are located in the [`src/tools`] directory.
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index be9d965e4..5d1441936 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -245,14 +245,20 @@ The binary will be created at
`./build/$HOST_ARCH/stage2-tools/$TARGET_ARCH/release/remote-test-server`. Copy
this over to the remote machine.
-On the remote machine, run the `remote-test-server` with the `remote` argument
-(and optionally `-v` for verbose output). Output should look like this:
+On the remote machine, run the `remote-test-server` with the `--bind
+0.0.0.0:12345` flag (and optionally `-v` for verbose output). Output should
+look like this:
```sh
-$ ./remote-test-server -v remote
+$ ./remote-test-server -v --bind 0.0.0.0:12345
starting test server
listening on 0.0.0.0:12345!
```
+Note that binding the server to 0.0.0.0 will allow all hosts able to reach your
+machine to execute arbitrary code on your machine. We strongly recommend either
+setting up a firewall to block external access to port 12345, or to use a more
+restrictive IP address when binding.
+
You can test if the `remote-test-server` is working by connecting to it and
sending `ping\n`. It should reply `pong`:
```sh
diff --git a/src/doc/rustc-dev-guide/src/traits/resolution.md b/src/doc/rustc-dev-guide/src/traits/resolution.md
index 195fe6050..88767ad94 100644
--- a/src/doc/rustc-dev-guide/src/traits/resolution.md
+++ b/src/doc/rustc-dev-guide/src/traits/resolution.md
@@ -72,10 +72,10 @@ Trait resolution consists of three major parts:
are completely fulfilled. Basically it is a worklist of obligations
to be selected: once selection is successful, the obligation is
removed from the worklist and any nested obligations are enqueued.
+ Fulfillment constrains inference variables.
-- **Coherence**: The coherence checks are intended to ensure that there
- are never overlapping impls, where two impls could be used with
- equal precedence.
+- **Evaluation**: Checks whether obligations holds without constraining
+ any inference variables. Used by selection.
## Selection
@@ -111,6 +111,8 @@ may lead to other errors downstream).
### Candidate assembly
+**TODO**: Talk about _why_ we have different candidates, and why it needs to happen in a probe.
+
Searches for impls/where-clauses/etc that might
possibly be used to satisfy the obligation. Each of those is called
a candidate. To avoid ambiguity, we want to find exactly one
@@ -120,68 +122,23 @@ the obligation contains unbound inference variables.
The subroutines that decide whether a particular impl/where-clause/etc applies
to a particular obligation are collectively referred to as the process of
-_matching_. As of <!-- date-check --> May 2022, this amounts to unifying
-the `Self` types, but in the future we may also recursively consider some of the
-nested obligations, in the case of an impl.
-
-**TODO**: what does "unifying the `Self` types" mean? The `Self` of the
-obligation with that of an impl?
-
-The basic idea for candidate assembly is to do a first pass in which
-we identify all possible candidates. During this pass, all that we do
-is try and unify the type parameters. (In particular, we ignore any
-nested where clauses.) Presuming that this unification succeeds, the
-impl is added as a candidate.
+_matching_. For `impl` candidates <!-- date-check: Oct 2022 -->,
+this amounts to unifying the impl header (the `Self` type and the trait arguments)
+while ignoring nested obligations. If matching succeeds then we add it
+to a set of candidates. There are other rules when assembling candidates for
+built-in traits such as `Copy`, `Sized`, and `CoerceUnsized`.
Once this first pass is done, we can examine the set of candidates. If
it is a singleton set, then we are done: this is the only impl in
-scope that could possibly apply. Otherwise, we can winnow down the set
-of candidates by using where clauses and other conditions. If this
-reduced set yields a single, unambiguous entry, we're good to go,
-otherwise the result is considered ambiguous.
-
-#### The basic process: Inferring based on the impls we see
-
-This process is easier if we work through some examples. Consider
-the following trait:
-
-```rust,ignore
-trait Convert<Target> {
- fn convert(&self) -> Target;
-}
-```
+scope that could possibly apply. Otherwise, we can **winnow** down the set
+of candidates by using where clauses and other conditions. Winnowing uses
+`evaluate_candidate` to check whether the nested obligations may apply.
+If this still leaves more than 1 candidate, we use ` fn candidate_should_be_dropped_in_favor_of`
+to prefer some candidates over others.
-This trait just has one method. It's about as simple as it gets. It
-converts from the (implicit) `Self` type to the `Target` type. If we
-wanted to permit conversion between `isize` and `usize`, we might
-implement `Convert` like so:
-```rust,ignore
-impl Convert<usize> for isize { ... } // isize -> usize
-impl Convert<isize> for usize { ... } // usize -> isize
-```
-
-Now imagine there is some code like the following:
-
-```rust,ignore
-let x: isize = ...;
-let y = x.convert();
-```
-
-The call to convert will generate a trait reference `Convert<$Y> for
-isize`, where `$Y` is the type variable representing the type of
-`y`. Of the two impls we can see, the only one that matches is
-`Convert<usize> for isize`. Therefore, we can
-select this impl, which will cause the type of `$Y` to be unified to
-`usize`. (Note that while assembling candidates, we do the initial
-unifications in a transaction, so that they don't affect one another.)
-
-**TODO**: The example says we can "select" the impl, but this section is
-talking specifically about candidate assembly. Does this mean we can sometimes
-skip confirmation? Or is this poor wording?
-**TODO**: Is the unification of `$Y` part of trait resolution or type
-inference? Or is this not the same type of "inference variable" as in type
-inference?
+If this reduced set yields a single, unambiguous entry, we're good to go,
+otherwise the result is considered ambiguous.
#### Winnowing: Resolving ambiguities
@@ -281,38 +238,18 @@ result of selection would be an error.
Note that the candidate impl is chosen based on the `Self` type, but
confirmation is done based on (in this case) the `Target` type parameter.
-### Selection during translation
+### Selection during codegen
As mentioned above, during type checking, we do not store the results of trait
-selection. At trans time, we repeat the trait selection to choose a particular
-impl for each method call. In this second selection, we do not consider any
-where-clauses to be in scope because we know that each resolution will resolve
-to a particular impl.
-
-One interesting twist has to do with nested obligations. In general, in trans,
-we only need to do a "shallow" selection for an obligation. That is, we wish to
-identify which impl applies, but we do not (yet) need to decide how to select
-any nested obligations. Nonetheless, we *do* currently do a complete resolution,
-and that is because it can sometimes inform the results of type inference.
+selection. At codegen time, we repeat the trait selection to choose a particular
+impl for each method call. This is done using `fn codegen_select_candidate`.
+In this second selection, we do not consider any where-clauses to be in scope
+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.
+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
everything out.
-
-**TODO**: is this still talking about trans?
-
-Here is an example:
-
-```rust,ignore
-trait Foo { ... }
-impl<U, T:Bar<U>> Foo for Vec<T> { ... }
-
-impl Bar<usize> for isize { ... }
-```
-
-After one shallow round of selection for an obligation like `Vec<isize>
-: Foo`, we would know which impl we want, and we would know that
-`T=isize`, but we do not know the type of `U`. We must select the
-nested obligation `isize : Bar<U>` to find out that `U=usize`.
-
-It would be good to only do *just as much* nested resolution as
-necessary. Currently, though, we just do a full resolution.
diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md
index 1cc03fce0..9b35f0d4c 100644
--- a/src/doc/rustc-dev-guide/src/ty.md
+++ b/src/doc/rustc-dev-guide/src/ty.md
@@ -78,7 +78,7 @@ expected type. The [`astconv` module][astconv] is where the code responsible for
but also in other parts of the compiler that want to ask questions like "what argument types does
this function expect?"
-[astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_typeck/astconv/index.html
+[astconv]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_analysis/astconv/index.html
**How semantics drive the two instances of `Ty`**
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index d9d430c20..06883ddd5 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -20,9 +20,11 @@
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
- [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
+ - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
- [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md)
- [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md)
- [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md)
+ - [\*-android and \*-androideabi](platform-support/android.md)
- [\*-fuchsia](platform-support/fuchsia.md)
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
@@ -33,6 +35,7 @@
- [*-unknown-openbsd](platform-support/openbsd.md)
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
+ - [x86_64-fortanix-unknown-sgx](platform-support/x86_64-fortanix-unknown-sgx.md)
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md
index f05ff3f1b..2dc182b3d 100644
--- a/src/doc/rustc/src/command-line-arguments.md
+++ b/src/doc/rustc/src/command-line-arguments.md
@@ -270,6 +270,11 @@ This flag will set which lints should be set to the [warn level](lints/levels.md
_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information.
+<a id="option-force-warn"></a>
+## `--force-warn`: force a lint to warn
+
+This flag sets the given lint to the [forced warn level](lints/levels.md#force-warn) and the level cannot be overridden, even ignoring the [lint caps](lints/levels.md#capping-lints).
+
<a id="option-a-allow"></a>
## `-A`: set lint allowed
@@ -295,9 +300,9 @@ _Note:_ The order of these lint level arguments is taken into account, see [lint
## `-Z`: set unstable options
This flag will allow you to set unstable options of rustc. In order to set multiple options,
-the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time`.
+the -Z flag can be used multiple times. For example: `rustc -Z verbose -Z time-passes`.
Specifying options with -Z is only available on nightly. To view all available options
-run: `rustc -Z help`.
+run: `rustc -Z help`, or see [The Unstable Book](../unstable-book/index.html).
<a id="option-cap-lints"></a>
## `--cap-lints`: set the most restrictive lint level
@@ -381,6 +386,12 @@ are:
- `always` — Always use colors.
- `never` — Never colorize output.
+<a id="option-diagnostic-width"></a>
+## `--diagnostic-width`: specify the terminal width for diagnostics
+
+This flag takes a number that specifies the width of the terminal in characters.
+Formatting of diagnostics will take the width into consideration to make them better fit on the screen.
+
<a id="option-remap-path-prefix"></a>
## `--remap-path-prefix`: remap source names in output
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3a6963ebc..a36518cc8 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -125,17 +125,17 @@ target | std | notes
`aarch64-apple-ios` | ✓ | ARM64 iOS
[`aarch64-apple-ios-sim`](platform-support/aarch64-apple-ios-sim.md) | ✓ | Apple iOS Simulator on ARM64
`aarch64-fuchsia` | ✓ | ARM64 Fuchsia
-`aarch64-linux-android` | ✓ | ARM64 Android
+[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
`aarch64-unknown-none` | * | Bare ARM64, hardfloat
-`arm-linux-androideabi` | ✓ | ARMv7 Android
+[`arm-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7 Android
`arm-unknown-linux-musleabi` | ✓ | ARMv6 Linux with MUSL
`arm-unknown-linux-musleabihf` | ✓ | ARMv6 Linux with MUSL, hardfloat
`armebv7r-none-eabi` | * | Bare ARMv7-R, Big Endian
`armebv7r-none-eabihf` | * | Bare ARMv7-R, Big Endian, hardfloat
`armv5te-unknown-linux-gnueabi` | ✓ | ARMv5TE Linux (kernel 4.4, glibc 2.23)
`armv5te-unknown-linux-musleabi` | ✓ | ARMv5TE Linux with MUSL
-`armv7-linux-androideabi` | ✓ | ARMv7a Android
+[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | ARMv7a Android
`armv7-unknown-linux-gnueabi` | ✓ |ARMv7 Linux (kernel 4.15, glibc 2.27)
`armv7-unknown-linux-musleabi` | ✓ |ARMv7 Linux with MUSL
`armv7-unknown-linux-musleabihf` | ✓ | ARMv7 Linux with MUSL, hardfloat
@@ -144,9 +144,9 @@ target | std | notes
`armv7r-none-eabihf` | * | Bare ARMv7-R, hardfloat
`asmjs-unknown-emscripten` | ✓ | asm.js via Emscripten
`i586-pc-windows-msvc` | * | 32-bit Windows w/o SSE
-`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23)
+`i586-unknown-linux-gnu` | ✓ | 32-bit Linux w/o SSE (kernel 3.2, glibc 2.17)
`i586-unknown-linux-musl` | ✓ | 32-bit Linux w/o SSE, MUSL
-`i686-linux-android` | ✓ | 32-bit x86 Android
+[`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android
`i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
`i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
`mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
@@ -165,7 +165,7 @@ target | std | notes
`thumbv7em-none-eabi` | * | Bare Cortex-M4, M7
`thumbv7em-none-eabihf` | * | Bare Cortex-M4F, M7F, FPU, hardfloat
`thumbv7m-none-eabi` | * | Bare Cortex-M3
-`thumbv7neon-linux-androideabi` | ✓ | Thumb2-mode ARMv7a Android with NEON
+[`thumbv7neon-linux-androideabi`](platform-support/android.md) | ✓ | Thumb2-mode ARMv7a Android with NEON
`thumbv7neon-unknown-linux-gnueabihf` | ✓ | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23)
`thumbv8m.base-none-eabi` | * | ARMv8-M Baseline
`thumbv8m.main-none-eabi` | * | ARMv8-M Mainline
@@ -174,9 +174,9 @@ target | std | notes
`wasm32-unknown-unknown` | ✓ | WebAssembly
`wasm32-wasi` | ✓ | WebAssembly with WASI
`x86_64-apple-ios` | ✓ | 64-bit x86 iOS
-`x86_64-fortanix-unknown-sgx` | ✓ | [Fortanix ABI] for 64-bit Intel SGX
+[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
`x86_64-fuchsia` | ✓ | 64-bit Fuchsia
-`x86_64-linux-android` | ✓ | 64-bit x86 Android
+[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
`x86_64-pc-solaris` | ✓ | 64-bit Solaris 10/11, illumos
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
@@ -226,6 +226,7 @@ target | std | host | notes
[`armeb-unknown-linux-gnueabi`](platform-support/armeb-unknown-linux-gnueabi.md) | ✓ | ? | ARM BE8 the default ARM big-endian architecture since [ARMv6](https://developer.arm.com/documentation/101754/0616/armlink-Reference/armlink-Command-line-Options/--be8?lang=en).
`armv4t-none-eabi` | * | | ARMv4T A32
`armv4t-unknown-linux-gnueabi` | ? | |
+[`armv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE A32
`armv5te-unknown-linux-uclibceabi` | ? | | ARMv5TE Linux with uClibc
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
`armv6-unknown-netbsd-eabihf` | ? | |
@@ -292,6 +293,7 @@ target | std | host | notes
`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
[`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
`thumbv4t-none-eabi` | * | | ARMv4T T32
+[`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | ARMv5TE T32
`thumbv7a-pc-windows-msvc` | ? | |
`thumbv7a-uwp-windows-msvc` | ✓ | |
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL
diff --git a/src/doc/rustc/src/platform-support/android.md b/src/doc/rustc/src/platform-support/android.md
new file mode 100644
index 000000000..b2c8e5d4d
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/android.md
@@ -0,0 +1,45 @@
+# *-linux-android and *-linux-androideabi
+
+**Tier: 2**
+
+[Android] is a mobile operating system built on top of the Linux kernel.
+
+[Android]: https://source.android.com/
+
+## Target maintainers
+
+- Chris Wailes ([@chriswailes](https://github.com/chriswailes))
+- Matthew Maurer ([@maurer](https://github.com/maurer))
+- Martin Geisler ([@mgeisler](https://github.com/mgeisler))
+
+## Requirements
+
+This target is cross-compiled from a host environment. Development may be done
+from the [source tree] or using the Android NDK.
+
+[source tree]: https://source.android.com/docs/setup/build/downloading
+
+Android targets support std. Generated binaries use the ELF file format.
+
+## NDK/API Update Policy
+
+Rust will support the most recent Long Term Support (LTS) Android Native
+Development Kit (NDK). By default Rust will support all API levels supported
+by the NDK, but a higher minimum API level may be required if deemed necessary.
+
+## Building the target
+
+To build Rust binaries for Android you'll need a copy of the most recent LTS
+edition of the [Android NDK]. Supported Android targets are:
+
+* aarch64-linux-android
+* arm-linux-androideabi
+* armv7-linux-androideabi
+* i686-linux-android
+* thumbv7neon-linux-androideabi
+* x86_64-linux-android
+
+[Android NDK]: https://developer.android.com/ndk/downloads
+
+A list of all supported targets can be found
+[here](https://doc.rust-lang.org/rustc/platform-support.html)
diff --git a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
index 507631cdc..432e0cfc9 100644
--- a/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
+++ b/src/doc/rustc/src/platform-support/armeb-unknown-linux-gnueabi.md
@@ -1,7 +1,7 @@
# armeb-unknown-linux-gnueabi
**Tier: 3**
-Target for cross-compiling Linux user-mode applications targetting the ARM BE8 architecture.
+Target for cross-compiling Linux user-mode applications targeting the ARM BE8 architecture.
## Overview
BE8 architecture retains the same little-endian ordered code-stream used by conventional little endian ARM systems, however the data accesses are in big-endian. BE8 is used primarily in high-performance networking applications where the ability to read packets in their native "Network Byte Order" is important (many network protocols transmit data in big-endian byte order for their wire formats).
diff --git a/src/doc/rustc/src/platform-support/armv5te-none-eabi.md b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md
new file mode 100644
index 000000000..f469dab1c
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/armv5te-none-eabi.md
@@ -0,0 +1,66 @@
+# `armv5te-none-eabi`
+
+**Tier: 3**
+
+Bare-metal target for any cpu in the ARMv5TE architecture family, supporting
+ARM/Thumb code interworking (aka `a32`/`t32`), with `a32` code as the default code
+generation.
+
+The `thumbv5te-none-eabi` target is the same as this one, but the instruction set defaults to `t32`.
+
+## Target Maintainers
+
+* [@QuinnPainter](https://github.com/QuinnPainter)
+
+## Requirements
+
+The target is cross-compiled, and uses static linking.
+
+By default, the `lld` linker included with Rust will be used.
+
+However, you may want to use the `arm-none-eabi-ld` linker instead. This can be obtained for Windows/Mac/Linux from the [ARM
+Developer Website][arm-dev], or possibly from your OS's package manager. To use it, add the following to your `.cargo/config.toml`:
+
+```toml
+[target.armv5te-none-eabi]
+linker = "arm-none-eabi-ld"
+```
+
+[arm-dev]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain
+
+This target doesn't provide a linker script, you'll need to bring your own
+according to the specific device you want to target. Pass
+`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
+`your_script.ld` during linking.
+
+## Building Rust Programs
+
+Because it is Tier 3, rust does not yet ship pre-compiled artifacts for this target.
+
+Just use the `build-std` nightly cargo feature to build the `core` library. You
+can pass this as a command line argument to cargo, or your `.cargo/config.toml`
+file might include the following lines:
+
+```toml
+[unstable]
+build-std = ["core"]
+```
+
+Most of `core` should work as expected, with the following notes:
+* the target is "soft float", so `f32` and `f64` operations are emulated in
+ software.
+* integer division is also emulated in software.
+* the target is old enough that it doesn't have atomic instructions.
+
+`alloc` is also supported, as long as you provide your own global allocator.
+
+Rust programs are output as ELF files.
+
+## Testing
+
+This is a cross-compiled target that you will need to emulate during testing.
+
+Because this is a device-agnostic target, and the exact emulator that you'll
+need depends on the specific device you want to run your code on.
+
+For example, when programming for the DS, you can use one of the several available DS emulators, such as [melonDS](https://melonds.kuribo64.net/).
diff --git a/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
new file mode 100644
index 000000000..97b5827c1
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/x86_64-fortanix-unknown-sgx.md
@@ -0,0 +1,72 @@
+# `x86_64-fortanix-unknown-sgx`
+
+**Tier: 2**
+
+Secure enclaves using [Intel Software Guard Extensions
+(SGX)](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html)
+based on the ABI defined by Fortanix for the [Enclave Development Platform
+(EDP)](https://edp.fortanix.com/).
+
+## Target maintainers
+
+The [EDP team](mailto:edp.maintainers@fortanix.com) at Fortanix.
+
+- Jethro Beekman [@jethrogb](https://github.com/jethrogb)
+- Raoul Strackx [@raoulstrackx](https://github.com/raoulstrackx)
+- Mohsen Zohrevandi [@mzohreva](https://github.com/mzohreva)
+
+## Requirements
+
+The target supports `std` with a default allocator. Only cross compilation is
+supported.
+
+Binaries support all CPUs that include Intel SGX. Only 64-bit mode is supported.
+
+Not all `std` features are supported, see [Using Rust's
+std](https://edp.fortanix.com/docs/concepts/rust-std/) for details.
+
+The `extern "C"` calling convention is the System V AMD64 ABI.
+
+The supported ABI is the
+[fortanix-sgx-abi](https://edp.fortanix.com/docs/api/fortanix_sgx_abi/index.html).
+
+The compiler output is ELF, but the native format for the platform is the SGX
+stream (SGXS) format. A converter like
+[ftxsgx-elf2sgxs](https://crates.io/crates/fortanix-sgx-tools) is needed.
+
+Programs in SGXS format adhering to the Fortanix SGX ABI can be run with any
+compatible runner, such as
+[ftxsgx-runner](https://crates.io/crates/fortanix-sgx-tools).
+
+See the [EDP installation
+guide](https://edp.fortanix.com/docs/installation/guide/) for recommendations
+on how to setup a development and runtime environment.
+
+## Building the target
+
+As a tier 2 target, the target is built by the Rust project.
+
+You can configure rustbuild like so:
+
+```toml
+[build]
+build-stage = 1
+target = ["x86_64-fortanix-unknown-sgx"]
+```
+
+## Building Rust programs
+
+Standard build flows using `cargo` or `rustc` should work.
+
+## Testing
+
+The Rust test suite as well as custom unit and integration tests will run on
+hardware that has Intel SGX enabled if a cargo runner is configured correctly,
+see the requirements section.
+
+## Cross-compilation toolchains and C code
+
+C code is not generally supported, as there is no libc. C code compiled for
+x86-64 in freestanding mode using the System V AMD64 ABI may work. The
+[rs-libc](https://crates.io/crates/rs-libc) crate contains a subset of libc
+that's known to work with this target.
diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml
index dfa685785..45405a117 100644
--- a/src/doc/rustdoc/book.toml
+++ b/src/doc/rustdoc/book.toml
@@ -6,9 +6,5 @@ title = "The rustdoc book"
git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc"
[output.html.redirect]
-"/what-to-include.html" = "write-documentation/what-to-include.html"
"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html"
-"/linking-to-items-by-name.html" = "write-documentation/linking-to-items-by-name.html"
"/documentation-tests.html" = "write-documentation/documentation-tests.html"
-"/website-features.html" = "advanced-features.html#custom-search-engines"
-"/passes.html" = "deprecated-features.html#passes"
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 32b350074..b8b5014ab 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -197,6 +197,35 @@ To do so, the `#[doc(keyword = "...")]` attribute is used. Example:
mod empty_mod {}
```
+## Effects of other nightly features
+
+These nightly-only features are not primarily related to Rustdoc,
+but have convenient effects on the documentation produced.
+
+### `fundamental` types
+
+Annotating a type with `#[fundamental]` primarily influences coherence rules about generic types,
+i.e., they alter whether other crates can provide implementations for that type.
+The unstable book [links to further information][unstable-fundamental].
+
+[unstable-fundamental]: https://doc.rust-lang.org/unstable-book/language-features/fundamental.html
+
+For documentation, this has an additional side effect:
+If a method is implemented on `F<T>` (or `F<&T>`),
+where `F` is a fundamental type,
+then the method is not only documented at the page about `F`,
+but also on the page about `T`.
+In a sense, it makes the type transparent to Rustdoc.
+This is especially convenient for types that work as annotated pointers,
+such as `Pin<&mut T>`,
+as it ensures that methods only implemented through those annotated pointers
+can still be found with the type they act on.
+
+If the `fundamental` feature's effect on coherence is not intended,
+such a type can be marked as fundamental only for purposes of documentation
+by introducing a custom feature and
+limiting the use of `fundamental` to when documentation is built.
+
## Unstable command-line arguments
These features are enabled by passing a command-line flag to Rustdoc, but the flags in question are
@@ -465,6 +494,16 @@ Note that the third item is the crate root, which in this case is undocumented.
[JSON format](https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc_json_types/). `--output-format html` has no effect,
and is also accepted on stable toolchains.
+JSON Output for toolchain crates (`std`, `alloc`, `core`, `test`, and `proc_macro`)
+is available via the `rust-docs-json` rustup component.
+
+```shell
+rustup component add --toolchain nightly rust-docs-json
+```
+
+Then the json files will be present in the `share/doc/rust/json/` directory
+of the rustup toolchain directory.
+
It can also be used with `--show-coverage`. Take a look at its
[documentation](#--show-coverage-calculate-the-percentage-of-items-with-documentation) for more
information.
diff --git a/src/doc/style-guide/book.toml b/src/doc/style-guide/book.toml
new file mode 100644
index 000000000..056aec8cd
--- /dev/null
+++ b/src/doc/style-guide/book.toml
@@ -0,0 +1,8 @@
+[book]
+title = "The Rust Style Guide"
+author = "The Rust Style Team"
+multilingual = false
+src = "src"
+
+[output.html]
+git-repository-url = "https://github.com/rust-lang/rust/tree/HEAD/src/doc/style-guide/"
diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md
new file mode 100644
index 000000000..adb73a7ee
--- /dev/null
+++ b/src/doc/style-guide/src/README.md
@@ -0,0 +1,190 @@
+# Rust Style Guide
+
+## Motivation - why use a formatting tool?
+
+Formatting code is a mostly mechanical task which takes both time and mental
+effort. By using an automatic formatting tool, a programmer is relieved of
+this task and can concentrate on more important things.
+
+Furthermore, by sticking to an established style guide (such as this one),
+programmers don't need to formulate ad hoc style rules, nor do they need to
+debate with other programmers what style rules should be used, saving time,
+communication overhead, and mental energy.
+
+Humans comprehend information through pattern matching. By ensuring that all
+Rust code has similar formatting, less mental effort is required to comprehend a
+new project, lowering the barrier to entry for new developers.
+
+Thus, there are productivity benefits to using a formatting tool (such as
+rustfmt), and even larger benefits by using a community-consistent formatting,
+typically by using a formatting tool's default settings.
+
+
+## Formatting conventions
+
+### Indentation and line width
+
+* Use spaces, not tabs.
+* Each level of indentation must be four spaces (that is, all indentation
+ outside of string literals and comments must be a multiple of four).
+* The maximum width for a line is 100 characters.
+* A tool should be configurable for all three of these variables.
+
+
+### Blank lines
+
+Separate items and statements by either zero or one blank lines (i.e., one or
+two newlines). E.g,
+
+```rust
+fn foo() {
+ let x = ...;
+
+ let y = ...;
+ let z = ...;
+}
+
+fn bar() {}
+fn baz() {}
+```
+
+Formatting tools should make the bounds on blank lines configurable: there
+should be separate minimum and maximum numbers of newlines between both
+statements and (top-level) items (i.e., four options). As described above, the
+defaults for both statements and items should be minimum: 1, maximum: 2.
+
+
+### [Module-level items](items.md)
+### [Statements](statements.md)
+### [Expressions](expressions.md)
+### [Types](types.md)
+
+
+### Comments
+
+The following guidelines for comments are recommendations only, a mechanical
+formatter might skip formatting of comments.
+
+Prefer line comments (`//`) to block comments (`/* ... */`).
+
+When using line comments there should be a single space after the opening sigil.
+
+When using single-line block comments there should be a single space after the
+opening sigil and before the closing sigil. Multi-line block comments should
+have a newline after the opening sigil and before the closing sigil.
+
+Prefer to put a comment on its own line. Where a comment follows code, there
+should be a single space before it. Where a block comment is inline, there
+should be surrounding whitespace as if it were an identifier or keyword. There
+should be no trailing whitespace after a comment or at the end of any line in a
+multi-line comment. Examples:
+
+```rust
+// A comment on an item.
+struct Foo { ... }
+
+fn foo() {} // A comment after an item.
+
+pub fn foo(/* a comment before an argument */ x: T) {...}
+```
+
+Comments should usually be complete sentences. Start with a capital letter, end
+with a period (`.`). An inline block comment may be treated as a note without
+punctuation.
+
+Source lines which are entirely a comment should be limited to 80 characters
+in length (including comment sigils, but excluding indentation) or the maximum
+width of the line (including comment sigils and indentation), whichever is
+smaller:
+
+```rust
+// This comment goes up to the ................................. 80 char margin.
+
+{
+ // This comment is .............................................. 80 chars wide.
+}
+
+{
+ {
+ {
+ {
+ {
+ {
+ // This comment is limited by the ......................... 100 char margin.
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+#### Doc comments
+
+Prefer line comments (`///`) to block comments (`/** ... */`).
+
+Prefer outer doc comments (`///` or `/** ... */`), only use inner doc comments
+(`//!` and `/*! ... */`) to write module-level or crate-level documentation.
+
+Doc comments should come before attributes.
+
+### Attributes
+
+Put each attribute on its own line, indented to the level of the item.
+In the case of inner attributes (`#!`), indent it to the level of the inside of
+the item. Prefer outer attributes, where possible.
+
+For attributes with argument lists, format like functions.
+
+```rust
+#[repr(C)]
+#[foo(foo, bar)]
+struct CRepr {
+ #![repr(C)]
+ x: f32,
+ y: f32,
+}
+```
+
+For attributes with an equal sign, there should be a single space before and
+after the `=`, e.g., `#[foo = 42]`.
+
+There must only be a single `derive` attribute. Note for tool authors: if
+combining multiple `derive` attributes into a single attribute, the ordering of
+the derived names should be preserved. E.g., `#[derive(bar)] #[derive(foo)]
+struct Baz;` should be formatted to `#[derive(bar, foo)] struct Baz;`.
+
+### *small* items
+
+In many places in this guide we specify that a formatter may format an item
+differently if it is *small*, for example struct literals:
+
+```rust
+// Normal formatting
+Foo {
+ f1: an_expression,
+ f2: another_expression(),
+}
+
+// *small* formatting
+Foo { f1, f2 }
+```
+
+We leave it to individual tools to decide on exactly what *small* means. In
+particular, tools are free to use different definitions in different
+circumstances.
+
+Some suitable heuristics are the size of the item (in characters) or the
+complexity of an item (for example, that all components must be simple names,
+not more complex sub-expressions). For more discussion on suitable heuristics,
+see [this issue](https://github.com/rust-lang-nursery/fmt-rfcs/issues/47).
+
+Tools should give the user an option to ignore such heuristics and always use
+the normal formatting.
+
+
+## [Non-formatting conventions](advice.md)
+
+## [Cargo.toml conventions](cargo.md)
+
+## [Principles used for deciding these guidelines](principles.md)
diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md
new file mode 100644
index 000000000..004692fa6
--- /dev/null
+++ b/src/doc/style-guide/src/SUMMARY.md
@@ -0,0 +1,11 @@
+# Summary
+
+[Introduction](README.md)
+
+- [Module-level items](items.md)
+- [Statements](statements.md)
+- [Expressions](expressions.md)
+- [Types](types.md)
+- [Non-formatting conventions](advice.md)
+- [`Cargo.toml` conventions](cargo.md)
+- [Principles used for deciding these guidelines](principles.md)
diff --git a/src/doc/style-guide/src/advice.md b/src/doc/style-guide/src/advice.md
new file mode 100644
index 000000000..ab4b92b0a
--- /dev/null
+++ b/src/doc/style-guide/src/advice.md
@@ -0,0 +1,34 @@
+# Other style advice
+
+## Expressions
+
+Prefer to use Rust's expression oriented nature where possible;
+
+```rust
+// use
+let x = if y { 1 } else { 0 };
+// not
+let x;
+if y {
+ x = 1;
+} else {
+ x = 0;
+}
+```
+
+## Names
+
+ * Types shall be `UpperCamelCase`,
+ * Enum variants shall be `UpperCamelCase`,
+ * Struct fields shall be `snake_case`,
+ * Function and method names shall be `snake_case`,
+ * Local variables shall be `snake_case`,
+ * Macro names shall be `snake_case`,
+ * Constants (`const`s and immutable `static`s) shall be `SCREAMING_SNAKE_CASE`.
+ * When a name is forbidden because it is a reserved word (e.g., `crate`), use a
+ trailing underscore to make the name legal (e.g., `crate_`), or use raw
+ identifiers if possible.
+
+### Modules
+
+Avoid `#[path]` annotations where possible.
diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md
new file mode 100644
index 000000000..f4993ba06
--- /dev/null
+++ b/src/doc/style-guide/src/cargo.md
@@ -0,0 +1,78 @@
+# Cargo.toml conventions
+
+## Formatting conventions
+
+Use the same line width and indentation as Rust code.
+
+Put a blank line between the last key-value pair in a section and the header of
+the next section. Do not place a blank line between section headers and the
+key-value pairs in that section, or between key-value pairs in a section.
+
+Sort key names alphabetically within each section, with the exception of the
+`[package]` section. Put the `[package]` section at the top of the file; put
+the `name` and `version` keys in that order at the top of that section,
+followed by the remaining keys other than `description` in alphabetical order,
+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.
+
+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.
+
+Use multi-line strings (rather than newline escape sequences) for any string
+values that include multiple lines, such as the crate description.
+
+For array values, such as a list of authors, put the entire list on the same
+line as the key, if it fits. Otherwise, use block indentation: put a newline
+after the opening square bracket, indent each item by one indentation level,
+put a comma after each item (including the last), and put the closing square
+bracket at the start of a line by itself after the last item.
+
+```rust
+authors = [
+ "A Uthor <a.uthor@example.org>",
+ "Another Author <author@example.net>",
+]
+```
+
+For table values, such as a crate dependency with a path, write the entire
+table using curly braces and commas on the same line as the key if it fits. If
+the entire table does not fit on the same line as the key, separate it out into
+a separate section with key-value pairs:
+
+```toml
+[dependencies]
+crate1 = { path = "crate1", version = "1.2.3" }
+
+[dependencies.extremely_long_crate_name_goes_here]
+path = "extremely_long_path_name_goes_right_here"
+version = "4.5.6"
+```
+
+## Metadata conventions
+
+The authors list should consist of strings that each contain an author name
+followed by an email address in angle brackets: `Full Name <email@address>`.
+It should not contain bare email addresses, or names without email addresses.
+(The authors list may also include a mailing list address without an associated
+name.)
+
+The license field must contain a valid [SPDX
+expression](https://spdx.org/spdx-specification-21-web-version#h.jxpfx0ykyb60),
+using valid [SPDX license names](https://spdx.org/licenses/). (As an exception,
+by widespread convention, the license field may use `/` in place of ` OR `; for
+example, `MIT/Apache-2.0`.)
+
+The homepage field, if present, must consist of a single URL, including the
+scheme (e.g. `https://example.org/`, not just `example.org`.)
+
+Within the description field, wrap text at 80 columns. Don't start the
+description field with the name of the crate (e.g. "cratename is a ..."); just
+describe the crate itself. If providing a multi-sentence description, the first
+sentence should go on a line by itself and summarize the crate, like the
+subject of an email or commit message; subsequent sentences can then describe
+the crate in more detail.
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
new file mode 100644
index 000000000..c7d0446dd
--- /dev/null
+++ b/src/doc/style-guide/src/expressions.md
@@ -0,0 +1,850 @@
+## Expressions
+
+### Blocks
+
+A block expression should have a newline after the initial `{` and before the
+terminal `}`. Any qualifier before the block (e.g., `unsafe`) should always be
+on the same line as the opening brace, and separated with a single space. The
+contents of the block should be block indented:
+
+```rust
+fn block_as_stmt() {
+ a_call();
+
+ {
+ a_call_inside_a_block();
+
+ // a comment in a block
+ the_value
+ }
+}
+
+fn block_as_expr() {
+ let foo = {
+ a_call_inside_a_block();
+
+ // a comment in a block
+ the_value
+ };
+}
+
+fn unsafe_block_as_stmt() {
+ a_call();
+
+ unsafe {
+ a_call_inside_a_block();
+
+ // a comment in a block
+ the_value
+ }
+}
+```
+
+If a block has an attribute, it should be on its own line:
+
+```rust
+fn block_as_stmt() {
+ #[an_attribute]
+ {
+ #![an_inner_attribute]
+
+ // a comment in a block
+ the_value
+ }
+}
+```
+
+Avoid writing comments on the same line as the braces.
+
+An empty block should be written as `{}`.
+
+A block may be written on a single line if:
+
+* it is either used in expression position (not statement position) or is an
+ unsafe block in statement position
+* contains a single-line expression and no statements
+* contains no comments
+
+A single line block should have spaces after the opening brace and before the
+closing brace.
+
+Examples:
+
+```rust
+fn main() {
+ // Single line
+ let _ = { a_call() };
+ let _ = unsafe { a_call() };
+
+ // Not allowed on one line
+ // Statement position.
+ {
+ a_call()
+ }
+
+ // Contains a statement
+ let _ = {
+ a_call();
+ };
+ unsafe {
+ a_call();
+ }
+
+ // Contains a comment
+ let _ = {
+ // A comment
+ };
+ let _ = {
+ // A comment
+ a_call()
+ };
+
+ // Multiple lines
+ let _ = {
+ a_call();
+ another_call()
+ };
+ let _ = {
+ a_call(
+ an_argument,
+ another_arg,
+ )
+ };
+}
+```
+
+
+### Closures
+
+Don't put any extra spaces before the first `|` (unless the closure is prefixed
+by `move`); put a space between the second `|` and the expression of the
+closure. Between the `|`s, you should use function definition syntax, however,
+elide types where possible.
+
+Use closures without the enclosing `{}`, if possible. Add the `{}` when you have
+a return type, when there are statements, there are comments in the body, or the
+body expression spans multiple lines and is a control-flow expression. If using
+braces, follow the rules above for blocks. Examples:
+
+```rust
+|arg1, arg2| expr
+
+move |arg1: i32, arg2: i32| -> i32 {
+ expr1;
+ expr2
+}
+
+|| Foo {
+ field1,
+ field2: 0,
+}
+
+|| {
+ if true {
+ blah
+ } else {
+ boo
+ }
+}
+
+|x| unsafe {
+ expr
+}
+```
+
+
+### Struct literals
+
+If a struct literal is *small* it may be formatted on a single line. If not,
+each field should be on it's own, block-indented line. There should be a
+trailing comma in the multi-line form only. There should be a space after the
+colon only.
+
+There should be a space before the opening brace. In the single-line form there
+should be spaces after the opening brace and before the closing brace.
+
+```rust
+Foo { field1, field2: 0 }
+let f = Foo {
+ field1,
+ field2: an_expr,
+};
+```
+
+Functional record update syntax is treated like a field, but it must never have
+a trailing comma. There should be no space after `..`.
+
+let f = Foo {
+ field1,
+ ..an_expr
+};
+
+
+### Tuple literals
+
+Use a single-line form where possible. There should not be spaces around the
+parentheses. Where a single-line form is not possible, each element of the tuple
+should be on its own block-indented line and there should be a trailing comma.
+
+```rust
+(a, b, c)
+
+let x = (
+ a_long_expr,
+ another_very_long_expr,
+);
+```
+
+
+### Tuple struct literals
+
+There should be no space between the identifier and the opening parenthesis.
+Otherwise, follow the rules for tuple literals, e.g., `Foo(a, b)`.
+
+
+### Enum literals
+
+Follow the formatting rules for the various struct literals. Prefer using the
+name of the enum as a qualifying name, unless the enum is in the prelude. E.g.,
+
+```rust
+Foo::Bar(a, b)
+Foo::Baz {
+ field1,
+ field2: 1001,
+}
+Ok(an_expr)
+```
+
+
+### Array literals
+
+For simple array literals, avoid line breaking, no spaces around square
+brackets, contents of the array should be separated by commas and spaces. If
+using the repeating initialiser, there should be a space after the semicolon
+only. Apply the same rules if using the `vec!` or similar macros (always use
+square brackets here). Examples:
+
+```rust
+fn main() {
+ [1, 2, 3];
+ vec![a, b, c, d];
+ let a = [42; 10];
+}
+```
+
+If a line must be broken, prefer breaking only after the `;`, if possible.
+Otherwise, follow the rules below for function calls. In any case, the contents
+of the initialiser should be block indented and there should be line breaks
+after the opening bracket and before the closing bracket:
+
+```rust
+fn main() {
+ [
+ a_long_expression();
+ 1234567890
+ ]
+ let x = [
+ an_expression,
+ another_expression,
+ a_third_expression,
+ ];
+}
+```
+
+
+### Array accesses, indexing, and slicing.
+
+No spaces around the square brackets, avoid breaking lines if possible, never
+break a line between the target expression and the opening bracket. If the
+indexing expression covers multiple lines, then it should be block indented and
+there should be newlines after the opening brackets and before the closing
+bracket. However, this should be avoided where possible.
+
+Examples:
+
+```rust
+fn main() {
+ foo[42];
+ &foo[..10];
+ bar[0..100];
+ foo[4 + 5 / bar];
+ a_long_target[
+ a_long_indexing_expression
+ ];
+}
+```
+
+### Unary operations
+
+Do not include a space between a unary op and its operand (i.e., `!x`, not
+`! x`). However, there must be a space after `&mut`. Avoid line-breaking
+between a unary operator and its operand.
+
+### Binary operations
+
+Do include spaces around binary ops (i.e., `x + 1`, not `x+1`) (including `=`
+and other assignment operators such as `+=` or `*=`).
+
+For comparison operators, because for `T op U`, `&T op &U` is also implemented:
+if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general,
+within expressions, prefer dereferencing to taking references.
+
+Use parentheses liberally, do not necessarily elide them due to precedence.
+Tools should not automatically insert or remove parentheses. Do not use spaces
+to indicate precedence.
+
+If line-breaking, put the operator on a new line and block indent. Put each
+sub-expression on its own line. E.g.,
+
+```rust
+foo_bar
+ + bar
+ + baz
+ + qux
+ + whatever
+```
+
+Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather
+than at other binary operators.
+
+### Control flow
+
+Do not include extraneous parentheses for `if` and `while` expressions.
+
+```rust
+if true {
+}
+```
+
+is better than
+
+```rust
+if (true) {
+}
+```
+
+Do include extraneous parentheses if it makes an arithmetic or logic expression
+easier to understand (`(x * 15) + (y * 20)` is fine)
+
+### Function calls
+
+Do not put a space between the function name, and the opening parenthesis.
+
+Do not put a space between an argument, and the comma which follows.
+
+Do put a space between an argument, and the comma which precedes it.
+
+Prefer not to break a line in the callee expression.
+
+#### Single-line calls
+
+Do not put a space between the function name and open paren, between the open
+paren and the first argument, or between the last argument and the close paren.
+
+Do not put a comma after the last argument.
+
+```rust
+foo(x, y, z)
+```
+
+#### Multi-line calls
+
+If the function call is not *small*, it would otherwise over-run the max width,
+or any argument or the callee is multi-line, then the call should be formatted
+across multiple lines. In this case, each argument should be on it's own block-
+indented line, there should be a newline after the opening parenthesis and
+before the closing parenthesis, and there should be a trailing comma. E.g.,
+
+```rust
+a_function_call(
+ arg1,
+ a_nested_call(a, b),
+)
+```
+
+
+### Method calls
+
+Follow the function rules for calling.
+
+Do not put any spaces around the `.`.
+
+```rust
+x.foo().bar().baz(x, y, z);
+```
+
+
+### Macro uses
+
+Macros which can be parsed like other constructs should be formatted like those
+constructs. For example, a macro use `foo!(a, b, c)` can be parsed like a
+function call (ignoring the `!`), therefore it should be formatted following the
+rules for function calls.
+
+#### Special case macros
+
+Macros which take a format string and where all other arguments are *small* may
+be formatted with arguments before and after the format string on a single line
+and the format string on its own line, rather than putting each argument on its
+own line. For example,
+
+```rust
+println!(
+ "Hello {} and {}",
+ name1, name2,
+);
+
+assert_eq!(
+ x, y,
+ "x and y were not equal, see {}",
+ reason,
+);
+```
+
+
+### Casts (`as`)
+
+Put spaces before and after `as`:
+
+```rust
+let cstr = "Hi\0" as *const str as *const [u8] as *const std::os::raw::c_char;
+```
+
+
+### Chains of fields and method calls
+
+A chain is a sequence of field accesses and/or method calls. A chain may also
+include the try operator ('?'). E.g., `a.b.c().d` or `foo?.bar().baz?`.
+
+Prefer formatting on one line if possible, and the chain is *small*. If
+formatting on multiple lines, each field access or method call in the chain
+should be on its own line with the line-break before the `.` and after any `?`.
+Each line should be block-indented. E.g.,
+
+```rust
+let foo = bar
+ .baz?
+ .qux();
+```
+
+If the length of the last line of the first element plus its indentation is
+less than or equal to the indentation of the second line (and there is space),
+then combine the first and second lines, e.g.,
+
+```rust
+x.baz?
+ .qux()
+
+let foo = x
+ .baz?
+ .qux();
+
+foo(
+ expr1,
+ expr2,
+).baz?
+ .qux();
+```
+
+#### Multi-line elements
+
+If any element in a chain is formatted across multiple lines, then that element
+and any later elements must be on their own line. Earlier elements may be kept
+on a single line. E.g.,
+
+```rust
+a.b.c()?.d
+ .foo(
+ an_expr,
+ another_expr,
+ )
+ .bar
+ .baz
+```
+
+Note there is block indent due to the chain and the function call in the above
+example.
+
+Prefer formatting the whole chain in multi-line style and each element on one
+line, rather than putting some elements on multiple lines and some on a single
+line, e.g.,
+
+```rust
+// Better
+self.pre_comment
+ .as_ref()
+ .map_or(false, |comment| comment.starts_with("//"))
+
+// Worse
+self.pre_comment.as_ref().map_or(
+ false,
+ |comment| comment.starts_with("//"),
+)
+```
+
+### Control flow expressions
+
+This section covers `if`, `if let`, `loop`, `while`, `while let`, and `for`
+expressions.
+
+The keyword, any initial clauses, and the opening brace of the block should be
+on a single line. The usual rules for [block formatting](#blocks) should be
+applied to the block.
+
+If there is an `else` component, then the closing brace, `else`, any following
+clause, and the opening brace should all be on the same line. There should be a
+single space before and after the `else` keyword. For example:
+
+```rust
+if ... {
+ ...
+} else {
+ ...
+}
+
+if let ... {
+ ...
+} else if ... {
+ ...
+} else {
+ ...
+}
+```
+
+If the control line needs to be broken, then prefer to break before the `=` in
+`* let` expressions and before `in` in a `for` expression; the following line
+should be block indented. If the control line is broken for any reason, then the
+opening brace should be on its own line and not indented. Examples:
+
+```rust
+while let Some(foo)
+ = a_long_expression
+{
+ ...
+}
+
+for foo
+ in a_long_expression
+{
+ ...
+}
+
+if a_long_expression
+ && another_long_expression
+ || a_third_long_expression
+{
+ ...
+}
+```
+
+Where the initial clause is multi-lined and ends with one or more closing
+parentheses, square brackets, or braces, and there is nothing else on that line,
+and that line is not indented beyond the indent on the first line of the control
+flow expression, then the opening brace of the block should be put on the same
+line with a preceding space. For example:
+
+```rust
+if !self.config.file_lines().intersects(
+ &self.codemap.lookup_line_range(
+ stmt.span,
+ ),
+) { // Opening brace on same line as initial clause.
+ ...
+}
+```
+
+
+#### Single line `if else`
+
+Formatters may place an `if else` or `if let else` on a single line if it occurs
+in expression context (i.e., is not a standalone statement), it contains a
+single `else` clause, and is *small*. For example:
+
+```rust
+let y = if x { 0 } else { 1 };
+
+// Examples that must be multi-line.
+let y = if something_very_long {
+ not_small
+} else {
+ also_not_small
+};
+
+if x {
+ 0
+} else {
+ 1
+}
+```
+
+
+### Match
+
+Prefer not to line-break inside the discriminant expression. There must always
+be a line break after the opening brace and before the closing brace. The match
+arms must be block indented once:
+
+```rust
+match foo {
+ // arms
+}
+
+let x = match foo.bar.baz() {
+ // arms
+};
+```
+
+Use a trailing comma for a match arm if and only if not using a block.
+
+Never start a match arm pattern with `|`, e.g.,
+
+```rust
+match foo {
+ // Don't do this.
+ | foo => bar,
+ // Or this.
+ | a_very_long_pattern
+ | another_pattern
+ | yet_another_pattern
+ | a_forth_pattern => {
+ ...
+ }
+}
+```
+
+Prefer
+
+
+```rust
+match foo {
+ foo => bar,
+ a_very_long_pattern
+ | another_pattern
+ | yet_another_pattern
+ | a_forth_pattern => {
+ ...
+ }
+}
+```
+
+Avoid splitting the left-hand side (before the `=>`) of a match arm where
+possible. If the right-hand side of the match arm is kept on the same line,
+never use a block (unless the block is empty).
+
+If the right-hand side consists of multiple statements or has line comments or
+the start of the line cannot be fit on the same line as the left-hand side, use
+a block.
+
+The body of a block arm should be block indented once.
+
+Examples:
+
+```rust
+match foo {
+ foo => bar,
+ a_very_long_patten | another_pattern if an_expression() => {
+ no_room_for_this_expression()
+ }
+ foo => {
+ // A comment.
+ an_expression()
+ }
+ foo => {
+ let a = statement();
+ an_expression()
+ }
+ bar => {}
+ // Trailing comma on last item.
+ foo => bar,
+}
+```
+
+If the body is a single expression with no line comments and not a control flow
+expression, then it may be started on the same line as the right-hand side. If
+not, then it must be in a block. Example,
+
+```rust
+match foo {
+ // A combinable expression.
+ foo => a_function_call(another_call(
+ argument1,
+ argument2,
+ )),
+ // A non-combinable expression
+ bar => {
+ a_function_call(
+ another_call(
+ argument1,
+ argument2,
+ ),
+ another_argument,
+ )
+ }
+}
+```
+
+#### Line-breaking
+
+Where it is possible to use a block form on the right-hand side and avoid
+breaking the left-hand side, do that. E.g.
+
+```rust
+ // Assuming the following line does done fit in the max width
+ a_very_long_pattern | another_pattern => ALongStructName {
+ ...
+ },
+ // Prefer this
+ a_very_long_pattern | another_pattern => {
+ ALongStructName {
+ ...
+ }
+ }
+ // To splitting the pattern.
+```
+
+Never break after `=>` without using the block form of the body.
+
+If the left-hand side must be split and there is an `if` clause, break before
+the `if` and block indent. In this case, always use a block body and start the
+body on a new line:
+
+```rust
+ a_very_long_pattern | another_pattern
+ if expr =>
+ {
+ ...
+ }
+```
+
+If required to break the pattern, put each clause of the pattern on its own
+line with no additional indent, breaking before the `|`. If there is an `if`
+clause, then you must use the above form:
+
+```rust
+ a_very_long_pattern
+ | another_pattern
+ | yet_another_pattern
+ | a_forth_pattern => {
+ ...
+ }
+ a_very_long_pattern
+ | another_pattern
+ | yet_another_pattern
+ | a_forth_pattern
+ if expr =>
+ {
+ ...
+ }
+```
+
+If the pattern is multi-line, and the last line is less wide than the indent, do
+not put the `if` clause on a newline. E.g.,
+
+```rust
+ Token::Dimension {
+ value,
+ ref unit,
+ ..
+ } if num_context.is_ok(context.parsing_mode, value) => {
+ ...
+ }
+```
+
+If every clause in a pattern is *small*, but does not fit on one line, then the
+pattern may be formatted across multiple lines with as many clauses per line as
+possible. Again break before a `|`:
+
+```rust
+ foo | bar | baz
+ | qux => {
+ ...
+ }
+```
+
+We define a pattern clause to be *small* if it matches the following grammar:
+
+```
+[small, ntp]:
+ - single token
+ - `&[single-line, ntp]`
+
+[small]:
+ - `[small, ntp]`
+ - unary tuple constructor `([small, ntp])`
+ - `&[small]`
+```
+
+E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.
+
+
+### Combinable expressions
+
+Where a function call has a single argument, and that argument is formatted
+across multiple-lines, the outer call may be formatted as if it were a single-
+line call. The same combining behaviour may be applied to any similar
+expressions which have multi-line, block-indented lists of sub-expressions
+delimited by parentheses (e.g., macros or tuple struct literals). E.g.,
+
+```rust
+foo(bar(
+ an_expr,
+ another_expr,
+))
+
+let x = foo(Bar {
+ field: whatever,
+});
+
+foo(|param| {
+ action();
+ foo(param)
+})
+```
+
+Such behaviour should extend recursively, however, tools may choose to limit the
+depth of nesting.
+
+Only where the multi-line sub-expression is a closure with an explicit block,
+this combining behaviour may be used where there are other arguments, as long as
+all the arguments and the first line of the closure fit on the first line, the
+closure is the last argument, and there is only one closure argument:
+
+```rust
+foo(first_arg, x, |param| {
+ action();
+ foo(param)
+})
+```
+
+
+### Ranges
+
+Do not put spaces in ranges, e.g., `0..10`, `x..=y`, `..x.len()`, `foo..`.
+
+When writing a range with both upper and lower bounds, if the line must be
+broken, break before the range operator and block indent the second line:
+
+```rust
+a_long_expression
+ ..another_long_expression
+```
+
+For the sake of indicating precedence, we recommend that if either bound is a
+compound expression, then use parentheses around it, e.g., `..(x + 1)`,
+`(x.f)..(x.f.len())`, or `0..(x - 10)`.
+
+
+### Hexadecimal literals
+
+Hexadecimal literals may use upper- or lower-case letters, but they must not be
+mixed within the same literal. Projects should use the same case for all
+literals, but we do not make a recommendation for either lower- or upper-case.
+Tools should have an option to convert mixed case literals to upper-case, and
+may have an option to convert all literals to either lower- or upper-case.
+
+
+## Patterns
+
+Patterns should be formatted like their corresponding expressions. See the
+section on `match` for additional formatting for patterns in match arms.
diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md
new file mode 100644
index 000000000..283597535
--- /dev/null
+++ b/src/doc/style-guide/src/items.md
@@ -0,0 +1,565 @@
+## Items
+
+`extern crate` statements must be first in a file. They must be ordered
+alphabetically.
+
+`use` statements, and module *declarations* (`mod foo;`, not `mod { ... }`)
+must come before other items. We recommend that imports come before module
+declarations; if imports and modules are separated, then they should be ordered
+alphabetically. When sorting, `self` and `super` must come before any other
+names. Module declarations should not be moved if they are annotated with
+`#[macro_use]`, since that may be semantics changing.
+
+Tools should make the above ordering optional.
+
+
+### Function definitions
+
+In Rust, one finds functions by searching for `fn [function-name]`; It's
+important that you style your code so that it's very searchable in this way.
+
+The proper ordering and spacing is:
+
+```rust
+[pub] [unsafe] [extern ["ABI"]] fn foo(arg1: i32, arg2: i32) -> i32 {
+ ...
+}
+```
+
+Avoid comments within the signature itself.
+
+If the function signature does not fit on one line, then break after the opening
+parenthesis and before the closing parenthesis and put each argument on its own
+block-indented line. For example,
+
+```rust
+fn foo(
+ arg1: i32,
+ arg2: i32,
+) -> i32 {
+ ...
+}
+```
+
+Note the trailing comma on the last argument.
+
+
+### Tuples and tuple structs
+
+Write the type list as you would a parameter list to a function.
+
+Build a tuple or tuple struct as you would call a function.
+
+#### Single-line
+
+```rust
+struct Bar(Type1, Type2);
+
+let x = Bar(11, 22);
+let y = (11, 22, 33);
+```
+
+### Enums
+
+In the declaration, put each variant on its own line, block indented.
+
+Format each variant accordingly as either a struct, tuple struct, or identifier,
+which doesn't require special formatting (but without the `struct` keyword.
+
+```rust
+enum FooBar {
+ First(u32),
+ Second,
+ Error {
+ err: Box<Error>,
+ line: u32,
+ },
+}
+```
+
+If a struct variant is [*small*](index.html#small-items), it may be formatted on
+one line. In this case, do not use a trailing comma for the field list, but do
+put spaces around each brace:
+
+```rust
+enum FooBar {
+ Error { err: Box<Error>, line: u32 },
+}
+```
+
+In an enum with multiple struct variants, if any struct variant is written on
+multiple lines, then the multi-line formatting should be used for all struct
+variants. However, such a situation might be an indication that you should
+factor out the fields of the variant into their own struct.
+
+
+### Structs and Unions
+
+Struct names follow on the same line as the `struct` keyword, with the opening
+brace on the same line when it fits within the right margin. All struct fields
+are indented once and end with a trailing comma. The closing brace is not
+indented and appears on its own line.
+
+```rust
+struct Foo {
+ a: A,
+ b: B,
+}
+```
+
+If and only if the type of a field does not fit within the right margin, it is
+pulled down to its own line and indented again.
+
+```rust
+struct Foo {
+ a: A,
+ long_name:
+ LongType,
+}
+```
+
+Prefer using a unit struct (e.g., `struct Foo;`) to an empty struct (e.g.,
+`struct Foo();` or `struct Foo {}`, these only exist to simplify code
+generation), but if you must use an empty struct, keep it on one line with no
+space between the braces: `struct Foo;` or `struct Foo {}`.
+
+The same guidelines are used for untagged union declarations.
+
+```rust
+union Foo {
+ a: A,
+ b: B,
+ long_name:
+ LongType,
+}
+```
+
+
+### Tuple structs
+
+Put the whole struct on one line if possible. Types in the parentheses should be
+separated by a comma and space with no trailing comma. No spaces around the
+parentheses or semi-colon:
+
+```rust
+pub struct Foo(String, u8);
+```
+
+Prefer unit structs to empty tuple structs (these only exist to simplify code
+generation), e.g., `struct Foo;` rather than `struct Foo();`.
+
+For more than a few fields, prefer a proper struct with named fields. Given
+this, a tuple struct should always fit on one line. If it does not, block format
+the fields with a field on each line and a trailing comma:
+
+```rust
+pub struct Foo(
+ String,
+ u8,
+);
+```
+
+
+### Traits
+
+Trait items should be block-indented. If there are no items, the trait may be
+formatted on a single line. Otherwise there should be line-breaks after the
+opening brace and before the closing brace:
+
+```rust
+trait Foo {}
+
+pub trait Bar {
+ ...
+}
+```
+
+If the trait has bounds, there should be a space after the colon but not before
+and before and after each `+`, e.g.,
+
+```rust
+trait Foo: Debug + Bar {}
+```
+
+Prefer not to line-break in the bounds if possible (consider using a `where`
+clause). Prefer to break between bounds than to break any individual bound. If
+you must break the bounds, put each bound (including the first) on its own
+block-indented line, break before the `+` and put the opening brace on its own
+line:
+
+```rust
+pub trait IndexRanges:
+ Index<Range<usize>, Output=Self>
+ + Index<RangeTo<usize>, Output=Self>
+ + Index<RangeFrom<usize>, Output=Self>
+ + Index<RangeFull, Output=Self>
+{
+ ...
+}
+```
+
+
+### Impls
+
+Impl items should be block indented. If there are no items, the impl may be
+formatted on a single line. Otherwise there should be line-breaks after the
+opening brace and before the closing brace:
+
+```rust
+impl Foo {}
+
+impl Bar for Foo {
+ ...
+}
+```
+
+Avoid line-breaking in the signature if possible. If a line break is required in
+a non-inherent impl, break immediately before `for`, block indent the concrete type
+and put the opening brace on its own line:
+
+```rust
+impl Bar
+ for Foo
+{
+ ...
+}
+```
+
+
+### Extern crate
+
+`extern crate foo;`
+
+Use spaces around keywords, no spaces around the semi-colon.
+
+
+### Modules
+
+```rust
+mod foo {
+}
+```
+
+```rust
+mod foo;
+```
+
+Use spaces around keywords and before the opening brace, no spaces around the
+semi-colon.
+
+### macro\_rules!
+
+Use `{}` for the full definition of the macro.
+
+```rust
+macro_rules! foo {
+}
+```
+
+
+### Generics
+
+Prefer to put a generics clause on one line. Break other parts of an item
+declaration rather than line-breaking a generics clause. If a generics clause is
+large enough to require line-breaking, you should prefer to use a `where` clause
+instead.
+
+Do not put spaces before or after `<` nor before `>`. Only put a space after `>`
+if it is followed by a word or opening brace, not an opening parenthesis. There
+should be a space after each comma and no trailing comma.
+
+```rust
+fn foo<T: Display, U: Debug>(x: Vec<T>, y: Vec<U>) ...
+
+impl<T: Display, U: Debug> SomeType<T, U> { ...
+```
+
+If the generics clause must be formatted across multiple lines, each parameter
+should have its own block-indented line, there should be newlines after the
+opening bracket and before the closing bracket, and the should be a trailing
+comma.
+
+```rust
+fn foo<
+ T: Display,
+ U: Debug,
+>(x: Vec<T>, y: Vec<U>) ...
+```
+
+If an associated type is bound in a generic type, then there should be spaces on
+either side of the `=`:
+
+```rust
+<T: Example<Item = u32>>
+```
+
+Prefer to use single-letter names for generic parameters.
+
+
+### `where` clauses
+
+These rules apply for `where` clauses on any item.
+
+A `where` clause may immediately follow a closing bracket of any kind.
+Otherwise, it must start a new line, with no indent. Each component of a `where`
+clause must be on its own line and be block indented. There should be a trailing
+comma, unless the clause is terminated with a semicolon. If the `where` clause
+is followed by a block (or assignment), the block should be started on a new
+line. Examples:
+
+```rust
+fn function<T, U>(args)
+where
+ T: Bound,
+ U: AnotherBound,
+{
+ body
+}
+
+fn foo<T>(
+ args
+) -> ReturnType
+where
+ T: Bound,
+{
+ body
+}
+
+fn foo<T, U>(
+ args,
+) where
+ T: Bound,
+ U: AnotherBound,
+{
+ body
+}
+
+fn foo<T, U>(
+ args
+) -> ReturnType
+where
+ T: Bound,
+ U: AnotherBound; // Note, no trailing comma.
+
+// Note that where clauses on `type` aliases are not enforced and should not
+// be used.
+type Foo<T>
+where
+ T: Bound
+= Bar<T>;
+```
+
+If a `where` clause is very short, we recommend using an inline bound on the
+type parameter.
+
+
+If a component of a `where` clause is long, it may be broken before `+` and
+further block indented. Each bound should go on its own line. E.g.,
+
+```rust
+impl<T: ?Sized, Idx> IndexRanges<Idx> for T
+where
+ T: Index<Range<Idx>, Output = Self::Output>
+ + Index<RangeTo<Idx>, Output = Self::Output>
+ + Index<RangeFrom<Idx>, Output = Self::Output>
+ + Index<RangeInclusive<Idx>, Output = Self::Output>
+ + Index<RangeToInclusive<Idx>, Output = Self::Output> + Index<RangeFull>
+```
+
+#### Option - `where_single_line`
+
+`where_single_line` is `false` by default. If `true`, then a where clause with
+exactly one component may be formatted on a single line if the rest of the
+item's signature is also kept on one line. In this case, there is no need for a
+trailing comma and if followed by a block, no need for a newline before the
+block. E.g.,
+
+```rust
+// May be single-lined.
+fn foo<T>(args) -> ReturnType
+where T: Bound {
+ body
+}
+
+// Must be multi-lined.
+fn foo<T>(
+ args
+) -> ReturnType
+where
+ T: Bound,
+{
+ body
+}
+```
+
+
+### Type aliases
+
+Type aliases should generally be kept on one line. If necessary to break the
+line, do so after the `=`; the right-hand-side should be block indented:
+
+```rust
+pub type Foo = Bar<T>;
+
+// If multi-line is required
+type VeryLongType<T, U: SomeBound> =
+ AnEvenLongerType<T, U, Foo<T>>;
+```
+
+Where possible avoid `where` clauses and keep type constraints inline. Where
+that is not possible split the line before and after the `where` clause (and
+split the `where` clause as normal), e.g.,
+
+```rust
+type VeryLongType<T, U>
+where
+ T: U::AnAssociatedType,
+ U: SomeBound,
+= AnEvenLongerType<T, U, Foo<T>>;
+```
+
+
+### Associated types
+
+Associated types should follow the guidelines above for type aliases. Where an
+associated type has a bound, there should be a space after the colon but not
+before:
+
+```rust
+pub type Foo: Bar;
+```
+
+
+### extern items
+
+When writing extern items (such as `extern "C" fn`), always be explicit about
+the ABI. For example, write `extern "C" fn foo ...`, not `extern fn foo ...`, or
+`extern "C" { ... }`.
+
+
+### Imports (`use` statements)
+
+If an import can be formatted on one line, do so. There should be no spaces
+around braces.
+
+```rust
+use a::b::c;
+use a::b::d::*;
+use a::b::{foo, bar, baz};
+```
+
+
+#### Large list imports
+
+Prefer to use multiple imports rather than a multi-line import. However, tools
+should not split imports by default (they may offer this as an option).
+
+If an import does require multiple lines (either because a list of single names
+does not fit within the max width, or because of the rules for nested imports
+below), then break after the opening brace and before the closing brace, use a
+trailing comma, and block indent the names.
+
+
+```rust
+// Prefer
+foo::{long, list, of, imports};
+foo::{more, imports};
+
+// If necessary
+foo::{
+ long, list, of, imports, more,
+ imports, // Note trailing comma
+};
+```
+
+
+#### Ordering of imports
+
+A *group* of imports is a set of imports on the same or sequential lines. One or
+more blank lines or other items (e.g., a function) separate groups of imports.
+
+Within a group of imports, imports must be sorted ascii-betically. Groups of
+imports must not be merged or re-ordered.
+
+
+E.g., input:
+
+```rust
+use d;
+use c;
+
+use b;
+use a;
+```
+
+output:
+
+```rust
+use c;
+use d;
+
+use a;
+use b;
+```
+
+Because of `macro_use`, attributes must also start a new group and prevent
+re-ordering.
+
+Note that tools which only have access to syntax (such as Rustfmt) cannot tell
+which imports are from an external crate or the std lib, etc.
+
+
+#### Ordering list import
+
+Names in a list import must be sorted ascii-betically, but with `self` and
+`super` first, and groups and glob imports last. This applies recursively. For
+example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g.,
+`use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`.
+
+
+#### Normalisation
+
+Tools must make the following normalisations:
+
+* `use a::self;` -> `use a;`
+* `use a::{};` -> (nothing)
+* `use a::{b};` -> `use a::b;`
+
+And must apply these recursively.
+
+Tools must not otherwise merge or un-merge import lists or adjust glob imports
+(without an explicit option).
+
+
+#### Nested imports
+
+If there are any nested imports in a list import, then use the multi-line form,
+even if the import fits on one line. Each nested import must be on its own line,
+but non-nested imports must be grouped on as few lines as possible.
+
+For example,
+
+```rust
+use a::b::{
+ x, y, z,
+ u::{...},
+ w::{...},
+};
+```
+
+
+#### Merging/un-merging imports
+
+An example:
+
+```rust
+// Un-merged
+use a::b;
+use a::c::d;
+
+// Merged
+use a::{b, c::d};
+```
+
+Tools must not merge or un-merge imports by default. They may offer merging or
+un-merging as an option.
diff --git a/src/doc/style-guide/src/principles.md b/src/doc/style-guide/src/principles.md
new file mode 100644
index 000000000..b02b3c047
--- /dev/null
+++ b/src/doc/style-guide/src/principles.md
@@ -0,0 +1,51 @@
+# Guiding principles and rationale
+
+When deciding on style guidelines, the style team tried to be guided by the
+following principles (in rough priority order):
+
+* readability
+ - scan-ability
+ - avoiding misleading formatting
+ - accessibility - readable and editable by users using the the widest
+ variety of hardware, including non-visual accessibility interfaces
+ - readability of code when quoted in rustc error messages
+
+* aesthetics
+ - sense of 'beauty'
+ - consistent with other languages/tools
+
+* specifics
+ - compatibility with version control practices - preserving diffs,
+ merge-friendliness, etc.
+ - preventing right-ward drift
+ - minimising vertical space
+
+* application
+ - ease of manual application
+ - ease of implementation (in Rustfmt, and in other tools/editors/code generators)
+ - internal consistency
+ - simplicity of formatting rules
+
+
+## Overarching guidelines
+
+Prefer block indent over visual indent. E.g.,
+
+```rust
+// Block indent
+a_function_call(
+ foo,
+ bar,
+);
+
+// Visual indent
+a_function_call(foo,
+ bar);
+```
+
+This makes for smaller diffs (e.g., if `a_function_call` is renamed in the above
+example) and less rightward drift.
+
+Lists should have a trailing comma when followed by a newline, see the block
+indent example above. This choice makes moving code (e.g., by copy and paste)
+easier and makes smaller diffs.
diff --git a/src/doc/style-guide/src/statements.md b/src/doc/style-guide/src/statements.md
new file mode 100644
index 000000000..29b48bb1e
--- /dev/null
+++ b/src/doc/style-guide/src/statements.md
@@ -0,0 +1,150 @@
+### Let statements
+
+There should be spaces after the `:` and on both sides of the `=` (if they are
+present). No space before the semi-colon.
+
+```rust
+// A comment.
+let pattern: Type = expr;
+
+let pattern;
+let pattern: Type;
+let pattern = expr;
+```
+
+If possible the declaration should be formatted on a single line. If this is not
+possible, then try splitting after the `=`, if the declaration can fit on two
+lines. The expression should be block indented.
+
+```rust
+let pattern: Type =
+ expr;
+```
+
+If the first line does not fit on a single line, then split after the colon,
+using block indentation. If the type covers multiple lines, even after line-
+breaking after the `:`, then the first line may be placed on the same line as
+the `:`, subject to the [combining rules](https://github.com/rust-lang-nursery/fmt-rfcs/issues/61) (WIP).
+
+
+```rust
+let pattern:
+ Type =
+ expr;
+```
+
+e.g,
+
+```rust
+let Foo {
+ f: abcd,
+ g: qwer,
+}: Foo<Bar> =
+ Foo { f, g };
+
+let (abcd,
+ defg):
+ Baz =
+{ ... }
+```
+
+If the expression covers multiple lines, if the first line of the expression
+fits in the remaining space, it stays on the same line as the `=`, the rest of the
+expression is not indented. If the first line does not fit, then it should start
+on the next lines, and should be block indented. If the expression is a block
+and the type or pattern cover multiple lines, then the opening brace should be
+on a new line and not indented (this provides separation for the interior of the
+block from the type), otherwise the opening brace follows the `=`.
+
+Examples:
+
+```rust
+let foo = Foo {
+ f: abcd,
+ g: qwer,
+};
+
+let foo =
+ ALongName {
+ f: abcd,
+ g: qwer,
+ };
+
+let foo: Type = {
+ an_expression();
+ ...
+};
+
+let foo:
+ ALongType =
+{
+ an_expression();
+ ...
+};
+
+let Foo {
+ f: abcd,
+ g: qwer,
+}: Foo<Bar> = Foo {
+ f: blimblimblim,
+ g: blamblamblam,
+};
+
+let Foo {
+ f: abcd,
+ g: qwer,
+}: Foo<Bar> = foo(
+ blimblimblim,
+ blamblamblam,
+);
+```
+
+
+### Macros in statement position
+
+A macro use in statement position should use parentheses or square brackets as
+delimiters and should be terminated with a semi-colon. There should be no spaces
+between the name, `!`, the delimiters, or the `;`.
+
+```rust
+// A comment.
+a_macro!(...);
+```
+
+
+### Expressions in statement position
+
+There should be no space between the expression and the semi-colon.
+
+```
+<expr>;
+```
+
+All expressions in statement position should be terminated with a semi-colon,
+unless they end with a block or are used as the value for a block.
+
+E.g.,
+
+```rust
+{
+ an_expression();
+ expr_as_value()
+}
+
+return foo();
+
+loop {
+ break;
+}
+```
+
+Use a semi-colon where an expression has void type, even if it could be
+propagated. E.g.,
+
+```rust
+fn foo() { ... }
+
+fn bar() {
+ foo();
+}
+```
diff --git a/src/doc/style-guide/src/types.md b/src/doc/style-guide/src/types.md
new file mode 100644
index 000000000..25861ddab
--- /dev/null
+++ b/src/doc/style-guide/src/types.md
@@ -0,0 +1,58 @@
+## Types and Bounds
+
+### Single line formatting
+
+* `[T]` no spaces
+* `[T; expr]`, e.g., `[u32; 42]`, `[Vec<Foo>; 10 * 2 + foo()]` (space after colon, no spaces around square brackets)
+* `*const T`, `*mut T` (no space after `*`, space before type)
+* `&'a T`, `&T`, `&'a mut T`, `&mut T` (no space after `&`, single spaces separating other words)
+* `unsafe extern "C" fn<'a, 'b, 'c>(T, U, V) -> W` or `fn()` (single spaces around keyowrds and sigils, and after commas, no trailing commas, no spaces around brackets)
+* `!` should be treated like any other type name, `Name`
+* `(A, B, C, D)` (spaces after commas, no spaces around parens, no trailing comma unless it is a one-tuple)
+* `<Baz<T> as SomeTrait>::Foo::Bar` or `Foo::Bar` or `::Foo::Bar` (no spaces around `::` or angle brackets, single spaces around `as`)
+* `Foo::Bar<T, U, V>` (spaces after commas, no trailing comma, no spaces around angle brackets)
+* `T + T + T` (single spaces between types, and `+`).
+* `impl T + T + T` (single spaces between keyword, types, and `+`).
+
+Parentheses used in types should not be surrounded by whitespace, e.g., `(Foo)`
+
+
+### Line breaks
+
+Avoid breaking lines in types where possible. Prefer breaking at outermost scope, e.g., prefer
+
+```rust
+Foo<
+ Bar,
+ Baz<Type1, Type2>,
+>
+```
+
+to
+
+```rust
+Foo<Bar, Baz<
+ Type1,
+ Type2,
+>>
+```
+
+`[T; expr]` may be broken after the `;` if necessary.
+
+Function types may be broken following the rules for function declarations.
+
+Generic types may be broken following the rules for generics.
+
+Types with `+` may be broken after any `+` using block indent and breaking before the `+`. When breaking such a type, all `+`s should be line broken, e.g.,
+
+```rust
+impl Clone
+ + Copy
+ + Debug
+
+Box<
+ Clone
+ + Copy
+ + Debug
+>
+```
diff --git a/src/doc/unstable-book/src/compiler-flags/dylib-lto.md b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md
new file mode 100644
index 000000000..f69ea334f
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md
@@ -0,0 +1,4 @@
+## `dylib-lto`
+
+This option enables using LTO for the `dylib` crate type. This is currently only used for compiling
+`rustc` itself (more specifically, the `librustc_driver` dylib).
diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md
index 3ce18743b..3e644f786 100644
--- a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md
+++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md
@@ -41,7 +41,7 @@ $ rustc -Zself-profile -Zself-profile-events=default,args
- `llvm`
- Adds tracing information about LLVM passes and codegeneration.
- - Disabled by default because this only works when `-Znew-llvm-pass-manager` is enabled.
+ - Disabled by default because this significantly increases the trace file size.
## Event synonyms
diff --git a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md b/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
deleted file mode 100644
index e0bb78227..000000000
--- a/src/doc/unstable-book/src/language-features/arbitrary-enum-discriminant.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# `arbitrary_enum_discriminant`
-
-The tracking issue for this feature is: [#60553]
-
-[#60553]: https://github.com/rust-lang/rust/issues/60553
-
-------------------------
-
-The `arbitrary_enum_discriminant` feature permits tuple-like and
-struct-like enum variants with `#[repr(<int-type>)]` to have explicit discriminants.
-
-## Examples
-
-```rust
-#![feature(arbitrary_enum_discriminant)]
-
-#[allow(dead_code)]
-#[repr(u8)]
-enum Enum {
- Unit = 3,
- Tuple(u16) = 2,
- Struct {
- a: u8,
- b: u16,
- } = 1,
-}
-
-impl Enum {
- fn tag(&self) -> u8 {
- unsafe { *(self as *const Self as *const u8) }
- }
-}
-
-assert_eq!(3, Enum::Unit.tag());
-assert_eq!(2, Enum::Tuple(5).tag());
-assert_eq!(1, Enum::Struct{a: 7, b: 11}.tag());
-```
diff --git a/src/doc/unstable-book/src/language-features/asm-sym.md b/src/doc/unstable-book/src/language-features/asm-sym.md
deleted file mode 100644
index 103d91caf..000000000
--- a/src/doc/unstable-book/src/language-features/asm-sym.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# `asm_sym`
-
-The tracking issue for this feature is: [#93333]
-
-[#93333]: https://github.com/rust-lang/rust/issues/93333
-
-------------------------
-
-This feature adds a `sym <path>` operand type to `asm!` and `global_asm!`.
-- `<path>` must refer to a `fn` or `static`.
-- A mangled symbol name referring to the item is substituted into the asm template string.
-- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
-- `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md
new file mode 100644
index 000000000..56a1a97df
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/half-open-range-patterns-in-slices.md
@@ -0,0 +1,30 @@
+# `half_open_range_patterns_in_slices`
+
+The tracking issue for this feature is: [#67264]
+It is part of the `exclusive_range_pattern` feature,
+tracked at [#37854].
+
+[#67264]: https://github.com/rust-lang/rust/issues/67264
+[#37854]: https://github.com/rust-lang/rust/issues/37854
+-----
+
+This feature allow using top-level half-open range patterns in slices.
+
+```rust
+#![feature(half_open_range_patterns_in_slices)]
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+ let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+ let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs else { return; };
+}
+```
+
+Note that this feature is not required if the patterns are wrapped between parenthesis.
+
+```rust
+fn main() {
+ let xs = [13, 1];
+ let [(a @ 3..), c] = xs else { return; };
+}
+```
diff --git a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md b/src/doc/unstable-book/src/language-features/half-open-range-patterns.md
deleted file mode 100644
index 3b16dd049..000000000
--- a/src/doc/unstable-book/src/language-features/half-open-range-patterns.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# `half_open_range_patterns`
-
-The tracking issue for this feature is: [#67264]
-It is part of the `#![exclusive_range_pattern]` feature,
-tracked at [#37854].
-
-[#67264]: https://github.com/rust-lang/rust/issues/67264
-[#37854]: https://github.com/rust-lang/rust/issues/37854
------
-
-The `half_open_range_patterns` feature allows RangeTo patterns
-(`..10`) to be used in appropriate pattern matching contexts.
-This requires also enabling the `exclusive_range_pattern` feature.
-
-It also enabled RangeFrom patterns but that has since been
-stabilized.
-
-```rust
-#![feature(half_open_range_patterns)]
-#![feature(exclusive_range_pattern)]
- let x = 5;
- match x {
- ..0 => println!("negative!"), // "RangeTo" pattern. Unstable.
- 0 => println!("zero!"),
- 1.. => println!("positive!"), // "RangeFrom" pattern. Stable.
- }
-```
diff --git a/src/doc/unstable-book/src/language-features/unix-sigpipe.md b/src/doc/unstable-book/src/language-features/unix-sigpipe.md
index aa39b6eb2..7ed6a7de8 100644
--- a/src/doc/unstable-book/src/language-features/unix-sigpipe.md
+++ b/src/doc/unstable-book/src/language-features/unix-sigpipe.md
@@ -36,7 +36,7 @@ hello world
Set the `SIGPIPE` handler to `SIG_IGN` before invoking `fn main()`. This will result in `ErrorKind::BrokenPipe` errors if you program tries to write to a closed pipe. This is normally what you want if you for example write socket servers, socket clients, or pipe peers.
-This is what libstd has done by default since 2014. Omitting `#[unix_sigpipe = "..."]` is the same as having `#[unix_sigpipe = "sig_ign"]`.
+This is what libstd has done by default since 2014. (However, see the note on child processes below.)
### Example
@@ -52,3 +52,11 @@ hello world
thread 'main' panicked at 'failed printing to stdout: Broken pipe (os error 32)', library/std/src/io/stdio.rs:1016:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
+
+### Note on child processes
+
+When spawning child processes, the legacy Rust behavior if `#[unix_sigpipe]` is not specified is to
+reset `SIGPIPE` to `SIG_DFL`.
+
+If `#[unix_sigpipe = "..."]` is specified, no matter what its value is, the signal disposition of
+`SIGPIPE` is no longer reset. This means that the child inherits the parent's `SIGPIPE` behavior.
diff --git a/src/etc/cat-and-grep.sh b/src/etc/cat-and-grep.sh
index 77dc52a93..238f7f5b6 100755
--- a/src/etc/cat-and-grep.sh
+++ b/src/etc/cat-and-grep.sh
@@ -26,7 +26,7 @@ Options:
-i Case insensitive search.
'
-GREPPER=fgrep
+GREPPER=grep
INVERT=0
GREPFLAGS='q'
while getopts ':vieh' OPTION; do
@@ -39,7 +39,7 @@ while getopts ':vieh' OPTION; do
GREPFLAGS="i$GREPFLAGS"
;;
e)
- GREPPER=egrep
+ GREPFLAGS="E$GREPFLAGS"
;;
h)
echo "$USAGE"
@@ -51,6 +51,12 @@ while getopts ':vieh' OPTION; do
esac
done
+if ! echo "$GREPFLAGS" | grep -q E
+then
+ # use F flag if there is not an E flag
+ GREPFLAGS="F$GREPFLAGS"
+fi
+
shift $((OPTIND - 1))
# use gnu version of tool if available (for bsd)
diff --git a/src/etc/natvis/libcore.natvis b/src/etc/natvis/libcore.natvis
index a4e8a57e4..624d8cc5c 100644
--- a/src/etc/natvis/libcore.natvis
+++ b/src/etc/natvis/libcore.natvis
@@ -154,10 +154,10 @@
</Type>
<Type Name="core::time::Duration">
- <DisplayString>{secs,d}s {nanos,d}ns</DisplayString>
+ <DisplayString>{secs,d}s {nanos.__0,d}ns</DisplayString>
<Expand>
<Item Name="seconds">secs,d</Item>
- <Item Name="nanoseconds">nanos,d</Item>
+ <Item Name="nanoseconds">nanos.__0,d</Item>
</Expand>
</Type>
</AutoVisualizer>
diff --git a/src/etc/rust-gdbgui b/src/etc/rust-gdbgui
index 9744913b6..590e488e6 100755
--- a/src/etc/rust-gdbgui
+++ b/src/etc/rust-gdbgui
@@ -58,7 +58,6 @@ GDB_ARGS="--directory=\"$GDB_PYTHON_MODULE_DIRECTORY\" -iex \"add-auto-load-safe
# Finally we execute gdbgui.
PYTHONPATH="$PYTHONPATH:$GDB_PYTHON_MODULE_DIRECTORY" \
exec ${RUST_GDBGUI} \
- --gdb ${RUST_GDB} \
- --gdb-args "${GDB_ARGS}" \
+ --gdb-cmd "${RUST_GDB} ${GDB_ARGS}" \
"${@}"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 175472797..764a6d3aa 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -148,7 +148,7 @@ where
})
.collect();
// We are only interested in case the type *doesn't* implement the Sized trait.
- if !ty.is_sized(tcx.at(rustc_span::DUMMY_SP), param_env) {
+ if !ty.is_sized(tcx, param_env) {
// In case `#![no_core]` is used, `sized_trait` returns nothing.
if let Some(item) = tcx.lang_items().sized_trait().and_then(|sized_trait_did| {
self.generate_for_trait(ty, sized_trait_did, param_env, item_def_id, &f, true)
@@ -475,6 +475,12 @@ where
let mut ty_to_fn: FxHashMap<Type, (PolyTrait, Option<Type>)> = Default::default();
+ // FIXME: This code shares much of the logic found in `clean_ty_generics` and
+ // `simplify::where_clause`. Consider deduplicating it to avoid diverging
+ // implementations.
+ // Further, the code below does not merge (partially re-sugared) bounds like
+ // `Tr<A = T>` & `Tr<B = U>` and it does not render higher-ranked parameters
+ // originating from equality predicates.
for p in clean_where_predicates {
let (orig_p, p) = (p, clean_predicate(p, self.cx));
if p.is_none() {
@@ -549,8 +555,8 @@ where
WherePredicate::RegionPredicate { lifetime, bounds } => {
lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
}
- WherePredicate::EqPredicate { lhs, rhs } => {
- match lhs {
+ WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
+ match *lhs {
Type::QPath(box QPathData {
ref assoc, ref self_type, ref trait_, ..
}) => {
@@ -585,13 +591,14 @@ where
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
bindings.push(TypeBinding {
assoc: assoc.clone(),
- kind: TypeBindingKind::Equality { term: rhs },
+ kind: TypeBindingKind::Equality { term: *rhs },
});
}
GenericArgs::Parenthesized { .. } => {
existing_predicates.push(WherePredicate::EqPredicate {
lhs: lhs.clone(),
rhs,
+ bound_params,
});
continue; // If something other than a Fn ends up
// with parentheses, leave it alone
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index cc734389e..8b63c3db3 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -2,7 +2,6 @@ use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtE
use rustc_hir as hir;
use rustc_infer::infer::{InferOk, TyCtxtInferExt};
use rustc_infer::traits;
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::ToPredicate;
use rustc_span::DUMMY_SP;
@@ -14,122 +13,124 @@ pub(crate) struct BlanketImplFinder<'a, 'tcx> {
impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
pub(crate) fn get_blanket_impls(&mut self, item_def_id: DefId) -> Vec<Item> {
- let param_env = self.cx.tcx.param_env(item_def_id);
- let ty = self.cx.tcx.bound_type_of(item_def_id);
+ 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);
trace!("get_blanket_impls({:?})", ty);
let mut impls = Vec::new();
- self.cx.with_all_traits(|cx, all_traits| {
- for &trait_def_id in all_traits {
- if !cx.cache.access_levels.is_public(trait_def_id)
- || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
- {
+ for trait_def_id in cx.tcx.all_traits() {
+ if !cx.cache.effective_visibilities.is_directly_public(trait_def_id)
+ || cx.generated_synthetics.get(&(ty.0, trait_def_id)).is_some()
+ {
+ continue;
+ }
+ // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
+ let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
+ 'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() {
+ trace!(
+ "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
+ trait_def_id,
+ impl_def_id
+ );
+ let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
+ if !matches!(trait_ref.0.self_ty().kind(), ty::Param(_)) {
continue;
}
- // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls
- let trait_impls = cx.tcx.trait_impls_of(trait_def_id);
- for &impl_def_id in trait_impls.blanket_impls() {
- trace!(
- "get_blanket_impls: Considering impl for trait '{:?}' {:?}",
- trait_def_id,
- impl_def_id
- );
- let trait_ref = cx.tcx.bound_impl_trait_ref(impl_def_id).unwrap();
- let is_param = matches!(trait_ref.0.self_ty().kind(), ty::Param(_));
- let may_apply = is_param && cx.tcx.infer_ctxt().enter(|infcx| {
- let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
- let ty = ty.subst(infcx.tcx, substs);
- let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
+ let infcx = cx.tcx.infer_ctxt().build();
+ let substs = infcx.fresh_substs_for_item(DUMMY_SP, item_def_id);
+ let impl_ty = ty.subst(infcx.tcx, substs);
+ let param_env = EarlyBinder(param_env).subst(infcx.tcx, substs);
- let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
- let trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
+ let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+ let impl_trait_ref = trait_ref.subst(infcx.tcx, impl_substs);
- // Require the type the impl is implemented on to match
- // our type, and ignore the impl if there was a mismatch.
- let cause = traits::ObligationCause::dummy();
- let eq_result = infcx.at(&cause, param_env).eq(trait_ref.self_ty(), ty);
- if let Ok(InferOk { value: (), obligations }) = eq_result {
- // FIXME(eddyb) ignoring `obligations` might cause false positives.
- drop(obligations);
+ // Require the type the impl is implemented on to match
+ // our type, and ignore the impl if there was a mismatch.
+ let cause = traits::ObligationCause::dummy();
+ let Ok(eq_result) = infcx.at(&cause, param_env).eq(impl_trait_ref.self_ty(), impl_ty) else {
+ continue
+ };
+ let InferOk { value: (), obligations } = eq_result;
+ // FIXME(eddyb) ignoring `obligations` might cause false positives.
+ drop(obligations);
- trace!(
- "invoking predicate_may_hold: param_env={:?}, trait_ref={:?}, ty={:?}",
- param_env,
- trait_ref,
- ty
- );
- let predicates = cx
- .tcx
- .predicates_of(impl_def_id)
- .instantiate(cx.tcx, impl_substs)
- .predicates
- .into_iter()
- .chain(Some(
- ty::Binder::dummy(trait_ref)
- .to_poly_trait_predicate()
- .map_bound(ty::PredicateKind::Trait)
- .to_predicate(infcx.tcx),
- ));
- for predicate in predicates {
- debug!("testing predicate {:?}", predicate);
- let obligation = traits::Obligation::new(
- traits::ObligationCause::dummy(),
- param_env,
- predicate,
- );
- match infcx.evaluate_obligation(&obligation) {
- Ok(eval_result) if eval_result.may_apply() => {}
- Err(traits::OverflowError::Canonical) => {}
- Err(traits::OverflowError::ErrorReporting) => {}
- _ => {
- return false;
- }
- }
- }
- true
- } else {
- false
- }
- });
- debug!(
- "get_blanket_impls: found applicable impl: {} for trait_ref={:?}, ty={:?}",
- may_apply, trait_ref, ty
+ trace!(
+ "invoking predicate_may_hold: param_env={:?}, impl_trait_ref={:?}, impl_ty={:?}",
+ param_env,
+ impl_trait_ref,
+ impl_ty
+ );
+ let predicates = cx
+ .tcx
+ .predicates_of(impl_def_id)
+ .instantiate(cx.tcx, impl_substs)
+ .predicates
+ .into_iter()
+ .chain(Some(
+ ty::Binder::dummy(impl_trait_ref)
+ .to_poly_trait_predicate()
+ .map_bound(ty::PredicateKind::Trait)
+ .to_predicate(infcx.tcx),
+ ));
+ for predicate in predicates {
+ debug!("testing predicate {:?}", predicate);
+ let obligation = traits::Obligation::new(
+ traits::ObligationCause::dummy(),
+ param_env,
+ predicate,
);
- if !may_apply {
- continue;
+ match infcx.evaluate_obligation(&obligation) {
+ Ok(eval_result) if eval_result.may_apply() => {}
+ Err(traits::OverflowError::Canonical) => {}
+ Err(traits::OverflowError::ErrorReporting) => {}
+ _ => continue 'blanket_impls,
}
+ }
+ debug!(
+ "get_blanket_impls: found applicable impl for trait_ref={:?}, ty={:?}",
+ trait_ref, ty
+ );
- cx.generated_synthetics.insert((ty.0, trait_def_id));
+ cx.generated_synthetics.insert((ty.0, trait_def_id));
- impls.push(Item {
- name: None,
- attrs: Default::default(),
- visibility: Inherited,
- item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
- kind: Box::new(ImplItem(Box::new(Impl {
- unsafety: hir::Unsafety::Normal,
- generics: clean_ty_generics(
- cx,
- cx.tcx.generics_of(impl_def_id),
- cx.tcx.explicit_predicates_of(impl_def_id),
- ),
- // FIXME(eddyb) compute both `trait_` and `for_` from
- // the post-inference `trait_ref`, as it's more accurate.
- trait_: Some(clean_trait_ref_with_bindings(cx, trait_ref.0, ThinVec::new())),
- for_: clean_middle_ty(ty.0, cx, None),
- items: cx.tcx
- .associated_items(impl_def_id)
- .in_definition_order()
- .map(|x| clean_middle_assoc_item(x, cx))
- .collect::<Vec<_>>(),
- polarity: ty::ImplPolarity::Positive,
- kind: ImplKind::Blanket(Box::new(clean_middle_ty(trait_ref.0.self_ty(), cx, None))),
- }))),
- cfg: None,
- });
- }
+ impls.push(Item {
+ name: None,
+ attrs: Default::default(),
+ visibility: Inherited,
+ item_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
+ kind: Box::new(ImplItem(Box::new(Impl {
+ unsafety: hir::Unsafety::Normal,
+ generics: clean_ty_generics(
+ cx,
+ cx.tcx.generics_of(impl_def_id),
+ cx.tcx.explicit_predicates_of(impl_def_id),
+ ),
+ // FIXME(eddyb) compute both `trait_` and `for_` from
+ // the post-inference `trait_ref`, as it's more accurate.
+ trait_: Some(clean_trait_ref_with_bindings(
+ cx,
+ trait_ref.0,
+ ThinVec::new(),
+ )),
+ for_: clean_middle_ty(ty.0, cx, None),
+ items: cx
+ .tcx
+ .associated_items(impl_def_id)
+ .in_definition_order()
+ .map(|x| clean_middle_assoc_item(x, cx))
+ .collect::<Vec<_>>(),
+ polarity: ty::ImplPolarity::Positive,
+ kind: ImplKind::Blanket(Box::new(clean_middle_ty(
+ trait_ref.0.self_ty(),
+ cx,
+ None,
+ ))),
+ }))),
+ cfg: None,
+ });
}
- });
+ }
impls
}
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index df0e9f7cc..4e2031a91 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -55,12 +55,39 @@ pub(crate) fn try_inline(
let mut ret = Vec::new();
debug!("attrs={:?}", attrs);
- let attrs_clone = attrs;
+
+ let attrs_without_docs = attrs.map(|attrs| {
+ attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>()
+ });
+ // We need this ugly code because:
+ //
+ // ```
+ // attrs_without_docs.map(|a| a.as_slice())
+ // ```
+ //
+ // will fail because it returns a temporary slice and:
+ //
+ // ```
+ // attrs_without_docs.map(|s| {
+ // vec = s.as_slice();
+ // vec
+ // })
+ // ```
+ //
+ // will fail because we're moving an uninitialized variable into a closure.
+ let vec;
+ let attrs_without_docs = match attrs_without_docs {
+ Some(s) => {
+ vec = s;
+ Some(vec.as_slice())
+ }
+ None => None,
+ };
let kind = match res {
Res::Def(DefKind::Trait, did) => {
record_extern_fqn(cx, did, ItemType::Trait);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::TraitItem(Box::new(build_external_trait(cx, did)))
}
Res::Def(DefKind::Fn, did) => {
@@ -69,27 +96,27 @@ pub(crate) fn try_inline(
}
Res::Def(DefKind::Struct, did) => {
record_extern_fqn(cx, did, ItemType::Struct);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::StructItem(build_struct(cx, did))
}
Res::Def(DefKind::Union, did) => {
record_extern_fqn(cx, did, ItemType::Union);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::UnionItem(build_union(cx, did))
}
Res::Def(DefKind::TyAlias, did) => {
record_extern_fqn(cx, did, ItemType::Typedef);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::TypedefItem(build_type_alias(cx, did))
}
Res::Def(DefKind::Enum, did) => {
record_extern_fqn(cx, did, ItemType::Enum);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::EnumItem(build_enum(cx, did))
}
Res::Def(DefKind::ForeignTy, did) => {
record_extern_fqn(cx, did, ItemType::ForeignType);
- build_impls(cx, Some(parent_module), did, attrs, &mut ret);
+ build_impls(cx, Some(parent_module), did, attrs_without_docs, &mut ret);
clean::ForeignTypeItem
}
// Never inline enum variants but leave them shown as re-exports.
@@ -123,7 +150,7 @@ pub(crate) fn try_inline(
_ => return None,
};
- let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs_clone);
+ let (attrs, cfg) = merge_attrs(cx, Some(parent_module), load_attrs(cx, did), attrs);
cx.inlined.insert(did.into());
let mut item = clean::Item::from_def_id_and_attrs_and_parts(
did,
@@ -362,7 +389,7 @@ pub(crate) fn build_impl(
if !did.is_local() {
if let Some(traitref) = associated_trait {
let did = traitref.def_id;
- if !cx.cache.access_levels.is_public(did) {
+ if !cx.cache.effective_visibilities.is_directly_public(did) {
return;
}
@@ -391,7 +418,7 @@ pub(crate) fn build_impl(
// reachable in rustdoc generated documentation
if !did.is_local() {
if let Some(did) = for_.def_id(&cx.cache) {
- if !cx.cache.access_levels.is_public(did) {
+ if !cx.cache.effective_visibilities.is_directly_public(did) {
return;
}
@@ -425,7 +452,7 @@ pub(crate) fn build_impl(
let assoc_kind = match item.kind {
hir::ImplItemKind::Const(..) => ty::AssocKind::Const,
hir::ImplItemKind::Fn(..) => ty::AssocKind::Fn,
- hir::ImplItemKind::TyAlias(..) => ty::AssocKind::Type,
+ hir::ImplItemKind::Type(..) => ty::AssocKind::Type,
};
let trait_item = tcx
.associated_items(associated_trait.def_id)
@@ -733,10 +760,6 @@ pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
debug!("record_extern_trait: {:?}", did);
let trait_ = build_external_trait(cx, did);
- let trait_ = clean::TraitWithExtraInfo {
- trait_,
- is_notable: clean::utils::has_doc_flag(cx.tcx, did, sym::notable_trait),
- };
cx.external_traits.borrow_mut().insert(did, trait_);
cx.active_extern_traits.remove(&did);
}
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index c8875c272..64a18757b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -17,16 +17,16 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{DefId, 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::ty::fold::TypeFolder;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
-use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Lift, Ty, TyCtxt};
+use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::{self, AdtKind, DefIdTree, EarlyBinder, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::hygiene::{AstPass, MacroKind};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, ExpnKind};
-use rustc_typeck::hir_ty_to_ty;
use std::assert_matches::assert_matches;
use std::collections::hash_map::Entry;
@@ -176,8 +176,6 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
poly_trait_ref: ty::PolyTraitRef<'tcx>,
bindings: ThinVec<TypeBinding>,
) -> GenericBound {
- let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
-
// collect any late bound regions
let late_bound_regions: Vec<_> = cx
.tcx
@@ -292,8 +290,9 @@ fn clean_where_predicate<'tcx>(
},
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
- lhs: clean_ty(wrp.lhs_ty, cx),
- rhs: clean_ty(wrp.rhs_ty, cx).into(),
+ lhs: Box::new(clean_ty(wrp.lhs_ty, cx)),
+ rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()),
+ bound_params: Vec::new(),
},
})
}
@@ -309,7 +308,9 @@ pub(crate) fn clean_predicate<'tcx>(
}
ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
- ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
+ ty::PredicateKind::Projection(pred) => {
+ Some(clean_projection_predicate(bound_predicate.rebind(pred), cx))
+ }
ty::PredicateKind::ConstEvaluatable(..) => None,
ty::PredicateKind::WellFormed(..) => None,
@@ -387,13 +388,25 @@ fn clean_hir_term<'tcx>(term: &hir::Term<'tcx>, cx: &mut DocContext<'tcx>) -> Te
}
fn clean_projection_predicate<'tcx>(
- pred: ty::ProjectionPredicate<'tcx>,
+ pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
cx: &mut DocContext<'tcx>,
) -> WherePredicate {
- let ty::ProjectionPredicate { projection_ty, term } = pred;
+ let late_bound_regions = cx
+ .tcx
+ .collect_referenced_late_bound_regions(&pred)
+ .into_iter()
+ .filter_map(|br| match br {
+ ty::BrNamed(_, name) if name != kw::UnderscoreLifetime => Some(Lifetime(name)),
+ _ => None,
+ })
+ .collect();
+
+ let ty::ProjectionPredicate { projection_ty, term } = pred.skip_binder();
+
WherePredicate::EqPredicate {
- lhs: clean_projection(projection_ty, cx, None),
- rhs: clean_middle_term(term, cx),
+ lhs: Box::new(clean_projection(projection_ty, cx, None)),
+ rhs: Box::new(clean_middle_term(term, cx)),
+ bound_params: late_bound_regions,
}
}
@@ -402,8 +415,17 @@ fn clean_projection<'tcx>(
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
- let trait_ = clean_trait_ref_with_bindings(cx, lifted.trait_ref(cx.tcx), ThinVec::new());
+ if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
+ let bounds = cx
+ .tcx
+ .explicit_item_bounds(ty.item_def_id)
+ .iter()
+ .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
+ .collect::<Vec<_>>();
+ return clean_middle_opaque_bounds(cx, bounds);
+ }
+
+ let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
let self_type = clean_middle_ty(ty.self_ty(), cx, None);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
@@ -632,7 +654,7 @@ fn clean_ty_generics<'tcx>(
let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
// Bounds in the type_params and lifetimes fields are repeated in the
- // predicates field (see rustc_typeck::collect::ty_generics), so remove
+ // predicates field (see rustc_hir_analysis::collect::ty_generics), so remove
// them.
let stripped_params = gens
.params
@@ -655,8 +677,9 @@ fn clean_ty_generics<'tcx>(
})
.collect::<Vec<GenericParamDef>>();
- // param index -> [(DefId of trait, associated type name and generics, type)]
- let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>)>>::default();
+ // param index -> [(trait DefId, associated type name & generics, type, higher-ranked params)]
+ let mut impl_trait_proj =
+ FxHashMap::<u32, Vec<(DefId, PathSegment, Ty<'_>, Vec<GenericParamDef>)>>::default();
let where_predicates = preds
.predicates
@@ -715,6 +738,14 @@ fn clean_ty_generics<'tcx>(
trait_did,
name,
rhs.ty().unwrap(),
+ p.get_bound_params()
+ .into_iter()
+ .flatten()
+ .map(|param| GenericParamDef {
+ name: param.0,
+ kind: GenericParamDefKind::Lifetime { outlives: Vec::new() },
+ })
+ .collect(),
));
}
@@ -730,15 +761,19 @@ fn clean_ty_generics<'tcx>(
// Move trait bounds to the front.
bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
- if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
- if let Some(proj) = impl_trait_proj.remove(&idx) {
- for (trait_did, name, rhs) in proj {
- let rhs = clean_middle_ty(rhs, cx, None);
- simplify::merge_bounds(cx, &mut bounds, trait_did, name, &Term::Type(rhs));
- }
+ let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
+ if let Some(proj) = impl_trait_proj.remove(&idx) {
+ for (trait_did, name, rhs, bound_params) in proj {
+ let rhs = clean_middle_ty(rhs, cx, None);
+ simplify::merge_bounds(
+ cx,
+ &mut bounds,
+ bound_params,
+ trait_did,
+ name,
+ &Term::Type(rhs),
+ );
}
- } else {
- unreachable!();
}
cx.impl_trait_bounds.insert(param, bounds);
@@ -749,31 +784,36 @@ fn clean_ty_generics<'tcx>(
let mut where_predicates =
where_predicates.into_iter().flat_map(|p| clean_predicate(*p, cx)).collect::<Vec<_>>();
- // Type parameters have a Sized bound by default unless removed with
- // ?Sized. Scan through the predicates and mark any type parameter with
- // a Sized bound, removing the bounds as we find them.
+ // In the surface language, all type parameters except `Self` have an
+ // implicit `Sized` bound unless removed with `?Sized`.
+ // However, in the list of where-predicates below, `Sized` appears like a
+ // normal bound: It's either present (the type is sized) or
+ // absent (the type is unsized) but never *maybe* (i.e. `?Sized`).
+ //
+ // This is unsuitable for rendering.
+ // Thus, as a first step remove all `Sized` bounds that should be implicit.
//
- // Note that associated types also have a sized bound by default, but we
+ // Note that associated types also have an implicit `Sized` bound but we
// don't actually know the set of associated types right here so that's
- // handled in cleaning associated types
+ // handled when cleaning associated types.
let mut sized_params = FxHashSet::default();
- where_predicates.retain(|pred| match *pred {
- WherePredicate::BoundPredicate { ty: Generic(ref g), ref bounds, .. } => {
- if bounds.iter().any(|b| b.is_sized_bound(cx)) {
- sized_params.insert(*g);
- false
- } else {
- true
- }
+ where_predicates.retain(|pred| {
+ if let WherePredicate::BoundPredicate { ty: Generic(g), bounds, .. } = pred
+ && *g != kw::SelfUpper
+ && bounds.iter().any(|b| b.is_sized_bound(cx))
+ {
+ sized_params.insert(*g);
+ false
+ } else {
+ true
}
- _ => true,
});
- // Run through the type parameters again and insert a ?Sized
- // unbound for any we didn't find to be Sized.
+ // As a final step, go through the type parameters again and insert a
+ // `?Sized` bound for each one we didn't find to be `Sized`.
for tp in &stripped_params {
- if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
- && !sized_params.contains(&tp.name)
+ if let types::GenericParamDefKind::Type { .. } = tp.kind
+ && !sized_params.contains(&tp.name)
{
where_predicates.push(WherePredicate::BoundPredicate {
ty: Type::Generic(tp.name),
@@ -1002,7 +1042,7 @@ fn clean_poly_trait_ref<'tcx>(
}
fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
- let local_did = trait_item.def_id.to_def_id();
+ let local_did = trait_item.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match trait_item.kind {
hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
@@ -1054,7 +1094,7 @@ pub(crate) fn clean_impl_item<'tcx>(
impl_: &hir::ImplItem<'tcx>,
cx: &mut DocContext<'tcx>,
) -> Item {
- let local_did = impl_.def_id.to_def_id();
+ let local_did = impl_.owner_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match impl_.kind {
hir::ImplItemKind::Const(ty, expr) => {
@@ -1063,10 +1103,10 @@ pub(crate) fn clean_impl_item<'tcx>(
}
hir::ImplItemKind::Fn(ref sig, body) => {
let m = clean_function(cx, sig, impl_.generics, body);
- let defaultness = cx.tcx.impl_defaultness(impl_.def_id);
+ let defaultness = cx.tcx.impl_defaultness(impl_.owner_id);
MethodItem(m, Some(defaultness))
}
- hir::ImplItemKind::TyAlias(hir_ty) => {
+ hir::ImplItemKind::Type(hir_ty) => {
let type_ = clean_ty(hir_ty, cx);
let generics = clean_generics(impl_.generics, cx);
let item_type = clean_middle_ty(hir_ty_to_ty(cx.tcx, hir_ty), cx, None);
@@ -1080,7 +1120,7 @@ pub(crate) fn clean_impl_item<'tcx>(
let mut what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(impl_.ident.name), inner, cx);
- let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.def_id));
+ let impl_ref = cx.tcx.impl_trait_ref(cx.tcx.local_parent(impl_.owner_id.def_id));
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
@@ -1177,11 +1217,18 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
if let ty::TraitContainer = assoc_item.container {
let bounds = tcx.explicit_item_bounds(assoc_item.def_id);
- let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
- let mut generics =
- clean_ty_generics(cx, tcx.generics_of(assoc_item.def_id), predicates);
- // Filter out the bounds that are (likely?) directly attached to the associated type,
- // as opposed to being located in the where clause.
+ let predicates = tcx.explicit_predicates_of(assoc_item.def_id).predicates;
+ let predicates =
+ tcx.arena.alloc_from_iter(bounds.into_iter().chain(predicates).copied());
+ let mut generics = clean_ty_generics(
+ cx,
+ tcx.generics_of(assoc_item.def_id),
+ ty::GenericPredicates { parent: None, predicates },
+ );
+ // Move bounds that are (likely) directly attached to the associated type
+ // from the where clause to the associated type.
+ // There is no guarantee that this is what the user actually wrote but we have
+ // no way of knowing.
let mut bounds = generics
.where_predicates
.drain_filter(|pred| match *pred {
@@ -1239,6 +1286,24 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
}
None => bounds.push(GenericBound::maybe_sized(cx)),
}
+ // Move bounds that are (likely) directly attached to the parameters of the
+ // (generic) associated type from the where clause to the respective parameter.
+ // There is no guarantee that this is what the user actually wrote but we have
+ // no way of knowing.
+ let mut where_predicates = Vec::new();
+ for mut pred in generics.where_predicates {
+ if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
+ && let Some(GenericParamDef {
+ kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
+ ..
+ }) = generics.params.iter_mut().find(|param| &param.name == arg)
+ {
+ param_bounds.extend(mem::take(bounds));
+ } else {
+ where_predicates.push(pred);
+ }
+ }
+ generics.where_predicates = where_predicates;
if tcx.impl_defaultness(assoc_item.def_id).has_value() {
AssocTypeItem(
@@ -1325,7 +1390,7 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
segments: trait_segments.iter().map(|x| clean_path_segment(x, cx)).collect(),
};
register_res(cx, trait_.res);
- let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
+ let self_def_id = DefId::local(qself.hir_id.owner.def_id.local_def_index);
let self_type = clean_ty(qself, cx);
let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
Type::QPath(Box::new(QPathData {
@@ -1366,7 +1431,7 @@ fn maybe_expand_private_type_alias<'tcx>(
let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None };
// Substitute private type aliases
let def_id = def_id.as_local()?;
- let alias = if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
+ let alias = if !cx.cache.effective_visibilities.is_exported(def_id.to_def_id()) {
&cx.tcx.hir().expect_item(def_id).kind
} else {
return None;
@@ -1480,7 +1545,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
//
- // `const_eval_poly` tries to to first substitute generic parameters which
+ // `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);
@@ -1509,13 +1574,12 @@ 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 => Infer,
- TyKind::Typeof(..) => panic!("unimplemented type {:?}", ty.kind),
+ TyKind::Infer | TyKind::Err | TyKind::Typeof(..) => Infer,
}
}
/// Returns `None` if the type could not be normalized
-fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
+fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
// HACK: low-churn fix for #79459 while we wait for a trait normalization fix
if !cx.tcx.sess.opts.unstable_opts.normalize_docs {
return None;
@@ -1526,13 +1590,11 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
use rustc_middle::traits::ObligationCause;
// Try to normalize `<X as Y>::T` to a type
- let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
- let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
- infcx
- .at(&ObligationCause::dummy(), cx.param_env)
- .normalize(lifted)
- .map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ let normalized = infcx
+ .at(&ObligationCause::dummy(), cx.param_env)
+ .normalize(ty)
+ .map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
match normalized {
Ok(normalized_value) => {
debug!("normalized {:?} to {:?}", ty, normalized_value);
@@ -1546,12 +1608,12 @@ fn normalize<'tcx>(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
}
pub(crate) fn clean_middle_ty<'tcx>(
- this: Ty<'tcx>,
+ ty: Ty<'tcx>,
cx: &mut DocContext<'tcx>,
def_id: Option<DefId>,
) -> Type {
- trace!("cleaning type: {:?}", this);
- let ty = normalize(cx, this).unwrap_or(this);
+ trace!("cleaning type: {:?}", ty);
+ let ty = normalize(cx, ty).unwrap_or(ty);
match *ty.kind() {
ty::Never => Primitive(PrimitiveType::Never),
ty::Bool => Primitive(PrimitiveType::Bool),
@@ -1561,8 +1623,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
ty::Slice(ty) => Slice(Box::new(clean_middle_ty(ty, cx, None))),
- ty::Array(ty, n) => {
- let mut n = cx.tcx.lift(n).expect("array lift failed");
+ ty::Array(ty, mut n) => {
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
let n = print_const(cx, n);
Array(Box::new(clean_middle_ty(ty, cx, None)), n)
@@ -1574,7 +1635,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
type_: Box::new(clean_middle_ty(ty, cx, None)),
},
ty::FnDef(..) | ty::FnPtr(_) => {
- let ty = cx.tcx.lift(this).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
BareFunction(Box::new(BareFunctionDecl {
@@ -1608,7 +1668,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
let did = obj
.principal_def_id()
.or_else(|| dids.next())
- .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", this));
+ .unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", ty));
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
// marker traits have no substs.
@@ -1632,8 +1692,6 @@ pub(crate) fn clean_middle_ty<'tcx>(
.map(|pb| TypeBinding {
assoc: projection_to_path_segment(
pb.skip_binder()
- .lift_to_tcx(cx.tcx)
- .unwrap()
// HACK(compiler-errors): Doesn't actually matter what self
// type we put here, because we're only using the GAT's substs.
.with_self_ty(cx.tcx, cx.tcx.types.self_param)
@@ -1666,66 +1724,13 @@ pub(crate) fn clean_middle_ty<'tcx>(
ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the bounds associated with the def_id.
- let substs = cx.tcx.lift(substs).expect("Opaque lift failed");
let bounds = cx
.tcx
.explicit_item_bounds(def_id)
.iter()
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
.collect::<Vec<_>>();
- let mut regions = vec![];
- let mut has_sized = false;
- let mut bounds = bounds
- .iter()
- .filter_map(|bound| {
- let bound_predicate = bound.kind();
- let trait_ref = match bound_predicate.skip_binder() {
- ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
- ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
- if let Some(r) = clean_middle_region(reg) {
- regions.push(GenericBound::Outlives(r));
- }
- return None;
- }
- _ => return None,
- };
-
- if let Some(sized) = cx.tcx.lang_items().sized_trait() {
- if trait_ref.def_id() == sized {
- has_sized = true;
- return None;
- }
- }
-
- let bindings: ThinVec<_> = bounds
- .iter()
- .filter_map(|bound| {
- if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
- {
- if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
- Some(TypeBinding {
- assoc: projection_to_path_segment(proj.projection_ty, cx),
- kind: TypeBindingKind::Equality {
- term: clean_middle_term(proj.term, cx),
- },
- })
- } else {
- None
- }
- } else {
- None
- }
- })
- .collect();
-
- Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
- })
- .collect::<Vec<_>>();
- bounds.extend(regions);
- if !has_sized && !bounds.is_empty() {
- bounds.insert(0, GenericBound::maybe_sized(cx));
- }
- ImplTrait(bounds)
+ clean_middle_opaque_bounds(cx, bounds)
}
ty::Closure(..) => panic!("Closure"),
@@ -1738,6 +1743,64 @@ pub(crate) fn clean_middle_ty<'tcx>(
}
}
+fn clean_middle_opaque_bounds<'tcx>(
+ cx: &mut DocContext<'tcx>,
+ bounds: Vec<ty::Predicate<'tcx>>,
+) -> Type {
+ let mut regions = vec![];
+ let mut has_sized = false;
+ let mut bounds = bounds
+ .iter()
+ .filter_map(|bound| {
+ let bound_predicate = bound.kind();
+ let trait_ref = match bound_predicate.skip_binder() {
+ ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
+ ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
+ if let Some(r) = clean_middle_region(reg) {
+ regions.push(GenericBound::Outlives(r));
+ }
+ return None;
+ }
+ _ => return None,
+ };
+
+ if let Some(sized) = cx.tcx.lang_items().sized_trait() {
+ if trait_ref.def_id() == sized {
+ has_sized = true;
+ return None;
+ }
+ }
+
+ let bindings: ThinVec<_> = bounds
+ .iter()
+ .filter_map(|bound| {
+ if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder() {
+ if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
+ Some(TypeBinding {
+ assoc: projection_to_path_segment(proj.projection_ty, cx),
+ kind: TypeBindingKind::Equality {
+ term: clean_middle_term(proj.term, cx),
+ },
+ })
+ } else {
+ None
+ }
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
+ })
+ .collect::<Vec<_>>();
+ bounds.extend(regions);
+ if !has_sized && !bounds.is_empty() {
+ bounds.insert(0, GenericBound::maybe_sized(cx));
+ }
+ ImplTrait(bounds)
+}
+
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)
@@ -1895,7 +1958,7 @@ fn clean_maybe_renamed_item<'tcx>(
) -> Vec<Item> {
use hir::ItemKind;
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
@@ -2037,11 +2100,11 @@ fn clean_extern_crate<'tcx>(
cx: &mut DocContext<'tcx>,
) -> Vec<Item> {
// this is the ID of the `extern crate` statement
- let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
+ let cnum = cx.tcx.extern_mod_stmt_cnum(krate.owner_id.def_id).unwrap_or(LOCAL_CRATE);
// this is the ID of the crate itself
let crate_def_id = cnum.as_def_id();
let attrs = cx.tcx.hir().attrs(krate.hir_id());
- let ty_vis = cx.tcx.visibility(krate.def_id);
+ let ty_vis = cx.tcx.visibility(krate.owner_id);
let please_inline = ty_vis.is_public()
&& attrs.iter().any(|a| {
a.has_name(sym::doc)
@@ -2059,7 +2122,7 @@ fn clean_extern_crate<'tcx>(
if let Some(items) = inline::try_inline(
cx,
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
- Some(krate.def_id.to_def_id()),
+ Some(krate.owner_id.to_def_id()),
res,
name,
Some(attrs),
@@ -2095,11 +2158,11 @@ fn clean_use_statement<'tcx>(
return Vec::new();
}
- let visibility = cx.tcx.visibility(import.def_id);
+ let visibility = cx.tcx.visibility(import.owner_id);
let attrs = cx.tcx.hir().attrs(import.hir_id());
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
let pub_underscore = visibility.is_public() && name == kw::Underscore;
- let current_mod = cx.tcx.parent_module_from_def_id(import.def_id);
+ let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id);
// The parent of the module in which this import resides. This
// is the same as `current_mod` if that's already the top
@@ -2170,7 +2233,7 @@ fn clean_use_statement<'tcx>(
}
if !denied {
let mut visited = FxHashSet::default();
- let import_def_id = import.def_id.to_def_id();
+ let import_def_id = import.owner_id.to_def_id();
if let Some(mut items) = inline::try_inline(
cx,
@@ -2193,7 +2256,7 @@ fn clean_use_statement<'tcx>(
Import::new_simple(name, resolve_use_source(cx, path), true)
};
- vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
+ vec![Item::from_def_id_and_parts(import.owner_id.to_def_id(), None, ImportItem(inner), cx)]
}
fn clean_maybe_renamed_foreign_item<'tcx>(
@@ -2201,7 +2264,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>(
item: &hir::ForeignItem<'tcx>,
renamed: Option<Symbol>,
) -> Item {
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
hir::ForeignItemKind::Fn(decl, names, generics) => {
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index af7813a77..1bcb9fcd5 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -14,7 +14,6 @@
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir::def_id::DefId;
use rustc_middle::ty;
-use rustc_span::Symbol;
use crate::clean;
use crate::clean::GenericArgs as PP;
@@ -26,38 +25,37 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
//
// We use `FxIndexMap` so that the insertion order is preserved to prevent messing up to
// the order of the generated bounds.
- let mut params: FxIndexMap<Symbol, (Vec<_>, Vec<_>)> = FxIndexMap::default();
+ let mut tybounds = FxIndexMap::default();
let mut lifetimes = Vec::new();
let mut equalities = Vec::new();
- let mut tybounds = Vec::new();
for clause in clauses {
match clause {
- WP::BoundPredicate { ty, bounds, bound_params } => match ty {
- clean::Generic(s) => {
- let (b, p) = params.entry(s).or_default();
- b.extend(bounds);
- p.extend(bound_params);
- }
- t => tybounds.push((t, (bounds, bound_params))),
- },
+ WP::BoundPredicate { ty, bounds, bound_params } => {
+ let (b, p): &mut (Vec<_>, Vec<_>) = tybounds.entry(ty).or_default();
+ b.extend(bounds);
+ p.extend(bound_params);
+ }
WP::RegionPredicate { lifetime, bounds } => {
lifetimes.push((lifetime, bounds));
}
- WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
+ WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)),
}
}
// Look for equality predicates on associated types that can be merged into
- // general bound predicates
- equalities.retain(|&(ref lhs, ref rhs)| {
- let Some((self_, trait_did, name)) = lhs.projection() else {
- return true;
- };
- let clean::Generic(generic) = self_ else { return true };
- let Some((bounds, _)) = params.get_mut(generic) else { return true };
-
- merge_bounds(cx, bounds, trait_did, name, rhs)
+ // general bound predicates.
+ equalities.retain(|&(ref lhs, ref rhs, ref bound_params)| {
+ let Some((ty, trait_did, name)) = lhs.projection() else { return true; };
+ let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
+ let bound_params = bound_params
+ .into_iter()
+ .map(|param| clean::GenericParamDef {
+ name: param.0,
+ kind: clean::GenericParamDefKind::Lifetime { outlives: Vec::new() },
+ })
+ .collect();
+ merge_bounds(cx, bounds, bound_params, trait_did, name, rhs)
});
// And finally, let's reassemble everything
@@ -65,23 +63,23 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> Vec<WP> {
clauses.extend(
lifetimes.into_iter().map(|(lt, bounds)| WP::RegionPredicate { lifetime: lt, bounds }),
);
- clauses.extend(params.into_iter().map(|(k, (bounds, params))| WP::BoundPredicate {
- ty: clean::Generic(k),
- bounds,
- bound_params: params,
- }));
clauses.extend(tybounds.into_iter().map(|(ty, (bounds, bound_params))| WP::BoundPredicate {
ty,
bounds,
bound_params,
}));
- clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
+ clauses.extend(equalities.into_iter().map(|(lhs, rhs, bound_params)| WP::EqPredicate {
+ lhs,
+ rhs,
+ bound_params,
+ }));
clauses
}
pub(crate) fn merge_bounds(
cx: &clean::DocContext<'_>,
bounds: &mut Vec<clean::GenericBound>,
+ mut bound_params: Vec<clean::GenericParamDef>,
trait_did: DefId,
assoc: clean::PathSegment,
rhs: &clean::Term,
@@ -98,6 +96,14 @@ pub(crate) fn merge_bounds(
return false;
}
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
+
+ trait_ref.generic_params.append(&mut bound_params);
+ // Since the parameters (probably) originate from `tcx.collect_*_late_bound_regions` which
+ // returns a hash set, sort them alphabetically to guarantee a stable and deterministic
+ // output (and to fully deduplicate them).
+ trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
+ trait_ref.generic_params.dedup_by_key(|p| p.name);
+
match last.args {
PP::AngleBracketed { ref mut bindings, .. } => {
bindings.push(clean::TypeBinding {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index f973fd088..cd1f972dc 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -21,6 +21,7 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{BodyId, Mutability};
+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, TyCtxt};
@@ -31,7 +32,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, FileName, Loc};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
-use rustc_typeck::check::intrinsic::intrinsic_operation_unsafety;
use crate::clean::cfg::Cfg;
use crate::clean::clean_visibility;
@@ -119,7 +119,7 @@ pub(crate) struct Crate {
pub(crate) module: Item,
pub(crate) primitives: ThinVec<(DefId, PrimitiveType)>,
/// Only here so that they can be filtered through the rustdoc passes.
- pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, TraitWithExtraInfo>>>,
+ pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, Trait>>>,
}
impl Crate {
@@ -132,13 +132,6 @@ impl Crate {
}
}
-/// This struct is used to wrap additional information added by rustdoc on a `trait` item.
-#[derive(Clone, Debug)]
-pub(crate) struct TraitWithExtraInfo {
- pub(crate) trait_: Trait,
- pub(crate) is_notable: bool,
-}
-
#[derive(Copy, Clone, Debug)]
pub(crate) struct ExternalCrate {
pub(crate) crate_num: CrateNum,
@@ -247,13 +240,13 @@ impl ExternalCrate {
let item = tcx.hir().item(id);
match item.kind {
hir::ItemKind::Mod(_) => {
- as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
+ as_keyword(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
}
hir::ItemKind::Use(path, hir::UseKind::Single)
- if tcx.visibility(id.def_id).is_public() =>
+ if tcx.visibility(id.owner_id).is_public() =>
{
as_keyword(path.res.expect_non_local())
- .map(|(_, prim)| (id.def_id.to_def_id(), prim))
+ .map(|(_, prim)| (id.owner_id.to_def_id(), prim))
}
_ => None,
}
@@ -315,14 +308,14 @@ impl ExternalCrate {
let item = tcx.hir().item(id);
match item.kind {
hir::ItemKind::Mod(_) => {
- as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
+ as_primitive(Res::Def(DefKind::Mod, id.owner_id.to_def_id()))
}
hir::ItemKind::Use(path, hir::UseKind::Single)
- if tcx.visibility(id.def_id).is_public() =>
+ if tcx.visibility(id.owner_id).is_public() =>
{
as_primitive(path.res.expect_non_local()).map(|(_, prim)| {
// Pretend the primitive is local.
- (id.def_id.to_def_id(), prim)
+ (id.owner_id.to_def_id(), prim)
})
}
_ => None,
@@ -689,7 +682,7 @@ impl Item {
let abi = tcx.fn_sig(self.item_id.as_def_id().unwrap()).abi();
hir::FnHeader {
unsafety: if abi == Abi::RustIntrinsic {
- intrinsic_operation_unsafety(self.name.unwrap())
+ intrinsic_operation_unsafety(tcx, self.item_id.as_def_id().unwrap())
} else {
hir::Unsafety::Unsafe
},
@@ -1357,7 +1350,7 @@ impl Lifetime {
pub(crate) enum WherePredicate {
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<Lifetime> },
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
- EqPredicate { lhs: Type, rhs: Term },
+ EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<Lifetime> },
}
impl WherePredicate {
@@ -1368,6 +1361,15 @@ impl WherePredicate {
_ => None,
}
}
+
+ pub(crate) fn get_bound_params(&self) -> Option<&[Lifetime]> {
+ match self {
+ Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
+ Some(bound_params)
+ }
+ _ => None,
+ }
+ }
}
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -1530,6 +1532,9 @@ impl Trait {
pub(crate) fn is_auto(&self, tcx: TyCtxt<'_>) -> bool {
tcx.trait_is_auto(self.def_id)
}
+ pub(crate) fn is_notable_trait(&self, tcx: TyCtxt<'_>) -> bool {
+ tcx.is_doc_notable_trait(self.def_id)
+ }
pub(crate) fn unsafety(&self, tcx: TyCtxt<'_>) -> hir::Unsafety {
tcx.trait_def(self.def_id).unsafety
}
@@ -2201,8 +2206,11 @@ impl Path {
/// Checks if this is a `T::Name` path for an associated type.
pub(crate) fn is_assoc_ty(&self) -> bool {
match self.res {
- Res::SelfTy { .. } if self.segments.len() != 1 => true,
- Res::Def(DefKind::TyParam, _) if self.segments.len() != 1 => true,
+ Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Def(DefKind::TyParam, _)
+ if self.segments.len() != 1 =>
+ {
+ true
+ }
Res::Def(DefKind::AssocTy, _) => true,
_ => false,
}
@@ -2532,15 +2540,15 @@ impl SubstParam {
mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
- // These are in alphabetical order, which is easy to maintain.
+ // tidy-alphabetical-start
static_assert_size!(Crate, 72); // frequently moved by-value
static_assert_size!(DocFragment, 32);
- #[cfg(not(bootstrap))]
- static_assert_size!(GenericArg, 56);
+ static_assert_size!(GenericArg, 48);
static_assert_size!(GenericArgs, 32);
static_assert_size!(GenericParamDef, 56);
static_assert_size!(Item, 56);
- static_assert_size!(ItemKind, 96);
+ static_assert_size!(ItemKind, 88);
static_assert_size!(PathSegment, 40);
- static_assert_size!(Type, 56);
+ static_assert_size!(Type, 48);
+ // tidy-alphabetical-end
}
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 3eaedaf10..58767d3a4 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -7,7 +7,6 @@ use crate::clean::{
PathSegment, Primitive, PrimitiveType, Type, TypeBinding, Visibility,
};
use crate::core::DocContext;
-use crate::formats::item_type::ItemType;
use crate::visit_lib::LibEmbargoVisitor;
use rustc_ast as ast;
@@ -234,8 +233,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
match n.kind() {
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
- assert_eq!(promoted, ());
+ ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs: _ }) => {
let s = if let Some(def) = def.as_local() {
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did))
} else {
@@ -305,9 +303,9 @@ fn format_integer_with_underscore_sep(num: &str) -> String {
.collect()
}
-fn print_const_with_custom_print_scalar(
- tcx: TyCtxt<'_>,
- ct: mir::ConstantKind<'_>,
+fn print_const_with_custom_print_scalar<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ ct: mir::ConstantKind<'tcx>,
underscores_and_type: bool,
) -> String {
// Use a slightly different format for integer types which always shows the actual value.
@@ -321,7 +319,7 @@ fn print_const_with_custom_print_scalar(
}
}
(mir::ConstantKind::Val(ConstValue::Scalar(int), _), ty::Int(i)) => {
- let ty = tcx.lift(ct.ty()).unwrap();
+ let ty = ct.ty();
let size = tcx.layout_of(ty::ParamEnv::empty().and(ty)).unwrap().size;
let data = int.assert_bits(size);
let sign_extended_data = size.sign_extend(data) as i128;
@@ -455,7 +453,9 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
match path.res {
Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
- Res::SelfTy { .. } if path.segments.len() == 1 => Generic(kw::SelfUpper),
+ Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } if path.segments.len() == 1 => {
+ Generic(kw::SelfUpper)
+ }
Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => Generic(path.segments[0].name),
_ => {
let _ = register_res(cx, path.res);
@@ -503,9 +503,6 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
return did;
}
inline::record_extern_fqn(cx, did, kind);
- if let ItemType::Trait = kind {
- inline::record_extern_trait(cx, did);
- }
did
}
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 932533db0..67ea39fb9 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -142,8 +142,6 @@ pub(crate) struct Options {
// Options that alter generated documentation pages
/// Crate version to note on the sidebar of generated docs.
pub(crate) crate_version: Option<String>,
- /// Collected options specific to outputting final pages.
- pub(crate) render_options: RenderOptions,
/// The format that we output when rendering.
///
/// Currently used only for the `--show-coverage` option.
@@ -159,6 +157,10 @@ pub(crate) struct Options {
/// Configuration for scraping examples from the current crate. If this option is Some(..) then
/// the compiler will scrape examples and not generate documentation.
pub(crate) scrape_examples_options: Option<ScrapeExamplesOptions>,
+
+ /// Note: this field is duplicated in `RenderOptions` because it's useful
+ /// to have it in both places.
+ pub(crate) unstable_features: rustc_feature::UnstableFeatures,
}
impl fmt::Debug for Options {
@@ -194,7 +196,6 @@ impl fmt::Debug for Options {
.field("persist_doctests", &self.persist_doctests)
.field("show_coverage", &self.show_coverage)
.field("crate_version", &self.crate_version)
- .field("render_options", &self.render_options)
.field("runtool", &self.runtool)
.field("runtool_args", &self.runtool_args)
.field("enable-per-target-ignores", &self.enable_per_target_ignores)
@@ -202,6 +203,7 @@ impl fmt::Debug for Options {
.field("no_run", &self.no_run)
.field("nocapture", &self.nocapture)
.field("scrape_examples_options", &self.scrape_examples_options)
+ .field("unstable_features", &self.unstable_features)
.finish()
}
}
@@ -267,6 +269,8 @@ pub(crate) struct RenderOptions {
pub(crate) generate_redirect_map: bool,
/// Show the memory layout of types in the docs.
pub(crate) show_type_layout: bool,
+ /// Note: this field is duplicated in `Options` because it's useful to have
+ /// it in both places.
pub(crate) unstable_features: rustc_feature::UnstableFeatures,
pub(crate) emit: Vec<EmitType>,
/// If `true`, HTML source pages will generate links for items to their definition.
@@ -316,7 +320,7 @@ impl Options {
pub(crate) fn from_matches(
matches: &getopts::Matches,
args: Vec<String>,
- ) -> Result<Options, i32> {
+ ) -> Result<(Options, RenderOptions), i32> {
let args = &args[1..];
// Check for unstable options.
nightly_options::check_nightly_options(matches, &opts());
@@ -710,7 +714,9 @@ impl Options {
let with_examples = matches.opt_strs("with-examples");
let call_locations = crate::scrape_examples::load_call_locations(with_examples, &diag)?;
- Ok(Options {
+ let unstable_features =
+ rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
+ let options = Options {
input,
proc_macro_crate,
error_format,
@@ -744,42 +750,42 @@ impl Options {
run_check,
no_run,
nocapture,
- render_options: RenderOptions {
- output,
- external_html,
- id_map,
- playground_url,
- module_sorting,
- themes,
- extension_css,
- extern_html_root_urls,
- extern_html_root_takes_precedence,
- default_settings,
- resource_suffix,
- enable_minification,
- enable_index_page,
- index_page,
- static_root_path,
- markdown_no_toc,
- markdown_css,
- markdown_playground_url,
- document_private,
- document_hidden,
- generate_redirect_map,
- show_type_layout,
- unstable_features: rustc_feature::UnstableFeatures::from_environment(
- crate_name.as_deref(),
- ),
- emit,
- generate_link_to_definition,
- call_locations,
- no_emit_shared: false,
- },
crate_name,
output_format,
json_unused_externs,
scrape_examples_options,
- })
+ unstable_features,
+ };
+ let render_options = RenderOptions {
+ output,
+ external_html,
+ id_map,
+ playground_url,
+ module_sorting,
+ themes,
+ extension_css,
+ extern_html_root_urls,
+ extern_html_root_takes_precedence,
+ default_settings,
+ resource_suffix,
+ enable_minification,
+ enable_index_page,
+ index_page,
+ static_root_path,
+ markdown_no_toc,
+ markdown_css,
+ markdown_playground_url,
+ document_private,
+ document_hidden,
+ generate_redirect_map,
+ show_type_layout,
+ unstable_features,
+ emit,
+ generate_link_to_definition,
+ call_locations,
+ no_emit_shared: false,
+ };
+ Ok((options, render_options))
}
/// Returns `true` if the file given as `self.input` is a Markdown file.
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index c48b25aea..3e5f42b7a 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -1,6 +1,7 @@
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_feature::UnstableFeatures;
@@ -10,12 +11,10 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{HirId, Path, TraitCandidate};
use rustc_interface::interface;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
use rustc_resolve as resolve;
use rustc_session::config::{self, CrateType, ErrorOutputType};
use rustc_session::lint;
-use rustc_session::DiagnosticOutput;
use rustc_session::Session;
use rustc_span::symbol::sym;
use rustc_span::{source_map, Span, Symbol};
@@ -26,7 +25,7 @@ use std::rc::Rc;
use std::sync::LazyLock;
use crate::clean::inline::build_external_trait;
-use crate::clean::{self, ItemId, TraitWithExtraInfo};
+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;
@@ -40,7 +39,6 @@ pub(crate) struct ResolverCaches {
/// 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_traits: Option<Vec<DefId>>,
pub(crate) all_trait_impls: Option<Vec<DefId>>,
pub(crate) all_macro_rules: FxHashMap<Symbol, Res<NodeId>>,
}
@@ -59,7 +57,7 @@ pub(crate) struct DocContext<'tcx> {
/// Most of this logic is copied from rustc_lint::late.
pub(crate) param_env: ParamEnv<'tcx>,
/// Later on moved through `clean::Crate` into `cache`
- pub(crate) external_traits: Rc<RefCell<FxHashMap<DefId, clean::TraitWithExtraInfo>>>,
+ 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>,
@@ -136,12 +134,6 @@ impl<'tcx> DocContext<'tcx> {
}
}
- pub(crate) fn with_all_traits(&mut self, f: impl FnOnce(&mut Self, &[DefId])) {
- let all_traits = self.resolver_caches.all_traits.take();
- f(self, all_traits.as_ref().expect("`all_traits` are already borrowed"));
- self.resolver_caches.all_traits = all_traits;
- }
-
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"));
@@ -287,19 +279,17 @@ pub(crate) fn create_config(
output_file: None,
output_dir: None,
file_loader: None,
- diagnostic_output: DiagnosticOutput::Default,
lint_caps,
parse_sess_created: None,
register_lints: Some(Box::new(crate::lint::register_lints)),
override_queries: Some(|_sess, providers, _external_providers| {
// Most lints will require typechecking, so just don't run them.
providers.lint_mod = |_, _| {};
- // Prevent `rustc_typeck::check_crate` from calling `typeck` on all bodies.
+ // Prevent `rustc_hir_analysis::check_crate` from calling `typeck` on all bodies.
providers.typeck_item_bodies = |_, _| {};
// hack so that `used_trait_imports` won't try to call typeck
providers.used_trait_imports = |_, _| {
- static EMPTY_SET: LazyLock<FxHashSet<LocalDefId>> =
- LazyLock::new(FxHashSet::default);
+ static EMPTY_SET: LazyLock<UnordSet<LocalDefId>> = LazyLock::new(UnordSet::default);
&EMPTY_SET
};
// In case typeck does end up being called, don't ICE in case there were name resolution errors
@@ -356,17 +346,9 @@ pub(crate) fn run_global_ctxt(
});
rustc_passes::stability::check_unused_or_stable_features(tcx);
- let auto_traits = resolver_caches
- .all_traits
- .as_ref()
- .expect("`all_traits` are already borrowed")
- .iter()
- .copied()
- .filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id))
- .collect();
- let access_levels = AccessLevels {
- map: tcx.privacy_access_levels(()).map.iter().map(|(k, v)| (k.to_def_id(), *v)).collect(),
- };
+ let auto_traits =
+ tcx.all_traits().filter(|&trait_def_id| tcx.trait_is_auto(trait_def_id)).collect();
+ let effective_visibilities = tcx.effective_visibilities(()).map_id(Into::into);
let mut ctxt = DocContext {
tcx,
@@ -379,7 +361,7 @@ pub(crate) fn run_global_ctxt(
impl_trait_bounds: Default::default(),
generated_synthetics: Default::default(),
auto_traits,
- cache: Cache::new(access_levels, render_options.document_private),
+ cache: Cache::new(effective_visibilities, render_options.document_private),
inlined: FxHashSet::default(),
output_format,
render_options,
@@ -391,9 +373,7 @@ pub(crate) fn run_global_ctxt(
// Note that in case of `#![no_core]`, the trait is not available.
if let Some(sized_trait_did) = ctxt.tcx.lang_items().sized_trait() {
let sized_trait = build_external_trait(&mut ctxt, sized_trait_did);
- ctxt.external_traits
- .borrow_mut()
- .insert(sized_trait_did, TraitWithExtraInfo { trait_: sized_trait, is_notable: false });
+ ctxt.external_traits.borrow_mut().insert(sized_trait_did, sized_trait);
}
debug!("crate: {:?}", tcx.hir().krate());
@@ -409,12 +389,8 @@ pub(crate) fn run_global_ctxt(
tcx.struct_lint_node(
crate::lint::MISSING_CRATE_LEVEL_DOCS,
DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(),
- |lint| {
- let mut diag =
- lint.build("no documentation found for this crate's top-level module");
- diag.help(&help);
- diag.emit();
- },
+ "no documentation found for this crate's top-level module",
+ |lint| lint.help(help),
);
}
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 20ae102bc..db70029f6 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -14,11 +14,10 @@ use rustc_parse::maybe_new_parser_from_source_str;
use rustc_parse::parser::attr::InnerAttrPolicy;
use rustc_session::config::{self, CrateType, ErrorOutputType};
use rustc_session::parse::ParseSess;
-use rustc_session::{lint, DiagnosticOutput, Session};
+use rustc_session::{lint, Session};
use rustc_span::edition::Edition;
use rustc_span::source_map::SourceMap;
use rustc_span::symbol::sym;
-use rustc_span::Symbol;
use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP};
use rustc_target::spec::TargetTriple;
use tempfile::Builder as TempFileBuilder;
@@ -80,7 +79,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
lint_cap: Some(options.lint_cap.unwrap_or(lint::Forbid)),
cg: options.codegen_options.clone(),
externs: options.externs.clone(),
- unstable_features: options.render_options.unstable_features,
+ unstable_features: options.unstable_features,
actually_rustdoc: true,
edition: options.edition,
target_triple: options.target.clone(),
@@ -100,7 +99,6 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
output_file: None,
output_dir: None,
file_loader: None,
- diagnostic_output: DiagnosticOutput::Default,
lint_caps,
parse_sess_created: None,
register_lints: Some(Box::new(crate::lint::register_lints)),
@@ -125,7 +123,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
let opts = scrape_test_config(crate_attrs);
let enable_per_target_ignores = options.enable_per_target_ignores;
let mut collector = Collector::new(
- tcx.crate_name(LOCAL_CRATE),
+ tcx.crate_name(LOCAL_CRATE).to_string(),
options,
false,
opts,
@@ -210,12 +208,13 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
pub(crate) fn run_tests(
mut test_args: Vec<String>,
nocapture: bool,
- tests: Vec<test::TestDescAndFn>,
+ mut tests: Vec<test::TestDescAndFn>,
) {
test_args.insert(0, "rustdoctest".to_string());
if nocapture {
test_args.push("--nocapture".to_string());
}
+ tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
test::test_main(&test_args, tests, None);
}
@@ -909,7 +908,7 @@ pub(crate) struct Collector {
rustdoc_options: RustdocOptions,
use_headers: bool,
enable_per_target_ignores: bool,
- crate_name: Symbol,
+ crate_name: String,
opts: GlobalTestOptions,
position: Span,
source_map: Option<Lrc<SourceMap>>,
@@ -921,7 +920,7 @@ pub(crate) struct Collector {
impl Collector {
pub(crate) fn new(
- crate_name: Symbol,
+ crate_name: String,
rustdoc_options: RustdocOptions,
use_headers: bool,
opts: GlobalTestOptions,
@@ -984,7 +983,7 @@ impl Tester for Collector {
fn add_test(&mut self, test: String, config: LangString, line: usize) {
let filename = self.get_filename();
let name = self.generate_name(line, &filename);
- let crate_name = self.crate_name.to_string();
+ let crate_name = self.crate_name.clone();
let opts = self.opts.clone();
let edition = config.edition.unwrap_or(self.rustdoc_options.edition);
let rustdoc_options = self.rustdoc_options.clone();
@@ -1134,6 +1133,7 @@ impl Tester for Collector {
panic::resume_unwind(Box::new(()));
}
+ Ok(())
})),
});
}
diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs
index ed702f5c4..c6f1f9de5 100644
--- a/src/librustdoc/fold.rs
+++ b/src/librustdoc/fold.rs
@@ -94,7 +94,7 @@ pub(crate) trait DocFolder: Sized {
let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
for (k, mut v) in external_traits {
- v.trait_.items = v.trait_.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
+ v.items = v.items.into_iter().filter_map(|i| self.fold_item(i)).collect();
c.external_traits.borrow_mut().insert(k, v);
}
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 86392610d..afe2264e8 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -2,9 +2,9 @@ use std::mem;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::{sym, Symbol};
+use rustc_span::Symbol;
use crate::clean::{self, types::ExternalLocation, ExternalCrate, ItemId, PrimitiveType};
use crate::core::DocContext;
@@ -62,7 +62,7 @@ pub(crate) struct Cache {
/// Implementations of a crate should inherit the documentation of the
/// parent trait if no extra documentation is specified, and default methods
/// should show up in documentation about trait implementations.
- pub(crate) traits: FxHashMap<DefId, clean::TraitWithExtraInfo>,
+ pub(crate) traits: FxHashMap<DefId, clean::Trait>,
/// When rendering traits, it's often useful to be able to list all
/// implementors of the trait, and this mapping is exactly, that: a mapping
@@ -77,8 +77,8 @@ pub(crate) struct Cache {
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
- // the access levels from the privacy check pass.
- pub(crate) access_levels: AccessLevels<DefId>,
+ // the effective visibilities from the privacy check pass.
+ pub(crate) effective_visibilities: EffectiveVisibilities<DefId>,
/// The version of the crate being documented, if given from the `--crate-version` flag.
pub(crate) crate_version: Option<String>,
@@ -132,8 +132,11 @@ struct CacheBuilder<'a, 'tcx> {
}
impl Cache {
- pub(crate) fn new(access_levels: AccessLevels<DefId>, document_private: bool) -> Self {
- Cache { access_levels, document_private, ..Cache::default() }
+ pub(crate) fn new(
+ effective_visibilities: EffectiveVisibilities<DefId>,
+ document_private: bool,
+ ) -> Self {
+ Cache { effective_visibilities, document_private, ..Cache::default() }
}
/// Populates the `Cache` with more data. The returned `Crate` will be missing some data that was
@@ -225,12 +228,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// Propagate a trait method's documentation to all implementors of the
// trait.
if let clean::TraitItem(ref t) = *item.kind {
- self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
- clean::TraitWithExtraInfo {
- trait_: *t.clone(),
- is_notable: item.attrs.has_doc_flag(sym::notable_trait),
- }
- });
+ self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| (**t).clone());
}
// Collect all the implementors of traits.
@@ -386,7 +384,10 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// paths map if there was already an entry present and we're
// not a public item.
if !self.cache.paths.contains_key(&item.item_id.expect_def_id())
- || self.cache.access_levels.is_public(item.item_id.expect_def_id())
+ || self
+ .cache
+ .effective_visibilities
+ .is_directly_public(item.item_id.expect_def_id())
{
self.cache.paths.insert(
item.item_id.expect_def_id(),
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 62ba984ac..6f9cc0266 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -58,7 +58,7 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
let emit_crate = options.should_emit_crate();
let (mut format_renderer, krate) = prof
- .extra_verbose_generic_activity("create_renderer", T::descr())
+ .verbose_generic_activity_with_arg("create_renderer", T::descr())
.run(|| T::init(krate, options, cache, tcx))?;
if !emit_crate {
@@ -92,6 +92,6 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
.run(|| cx.item(item))?;
}
}
- prof.extra_verbose_generic_activity("renderer_after_krate", T::descr())
+ prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
.run(|| format_renderer.after_krate())
}
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b499e186c..92e7f2739 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -331,7 +331,8 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
bounds_display.truncate(bounds_display.len() - " + ".len());
write!(f, "{}: {bounds_display}", lifetime.print())
}
- clean::WherePredicate::EqPredicate { lhs, rhs } => {
+ // FIXME(fmease): Render bound params.
+ clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
if f.alternate() {
write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
} else {
@@ -611,7 +612,7 @@ fn generate_macro_def_id_path(
};
if path.len() < 2 {
// The minimum we can have is the crate name followed by the macro name. If shorter, then
- // it means that that `relative` was empty, which is an error.
+ // it means that `relative` was empty, which is an error.
debug!("macro path cannot be empty!");
return Err(HrefError::NotInExternalCache);
}
@@ -658,7 +659,7 @@ pub(crate) fn href_with_root_path(
}
if !did.is_local()
- && !cache.access_levels.is_public(did)
+ && !cache.effective_visibilities.is_directly_public(did)
&& !cache.document_private
&& !cache.primitive_locations.values().any(|&id| id == did)
{
@@ -1010,15 +1011,25 @@ fn fmt_type<'cx>(
write!(f, "]")
}
},
- clean::Array(ref t, ref n) => {
- primitive_link(f, PrimitiveType::Array, "[", cx)?;
- fmt::Display::fmt(&t.print(cx), f)?;
- if f.alternate() {
- primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cx)
- } else {
- primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cx)
+ clean::Array(ref t, ref n) => match **t {
+ clean::Generic(name) if !f.alternate() => primitive_link(
+ f,
+ PrimitiveType::Array,
+ &format!("[{name}; {n}]", n = Escape(n)),
+ cx,
+ ),
+ _ => {
+ write!(f, "[")?;
+ fmt::Display::fmt(&t.print(cx), f)?;
+ if f.alternate() {
+ write!(f, "; {n}")?;
+ } else {
+ write!(f, "; ")?;
+ primitive_link(f, PrimitiveType::Array, &format!("{n}", n = Escape(n)), cx)?;
+ }
+ write!(f, "]")
}
- }
+ },
clean::RawPointer(m, ref t) => {
let m = match m {
hir::Mutability::Mut => "mut",
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 8922bf377..5e28204b2 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -7,19 +7,18 @@
use crate::clean::PrimitiveType;
use crate::html::escape::Escape;
-use crate::html::render::Context;
+use crate::html::render::{Context, LinkFromSrc};
use std::collections::VecDeque;
use std::fmt::{Display, Write};
use rustc_data_structures::fx::FxHashMap;
-use rustc_lexer::{LiteralKind, TokenKind};
+use rustc_lexer::{Cursor, LiteralKind, TokenKind};
use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, Span, DUMMY_SP};
use super::format::{self, Buffer};
-use super::render::LinkFromSrc;
/// This type is needed in case we want to render links on items to allow to go to their definition.
pub(crate) struct HrefContext<'a, 'b, 'c> {
@@ -408,15 +407,16 @@ enum Highlight<'a> {
struct TokenIter<'a> {
src: &'a str,
+ cursor: Cursor<'a>,
}
impl<'a> Iterator for TokenIter<'a> {
type Item = (TokenKind, &'a str);
fn next(&mut self) -> Option<(TokenKind, &'a str)> {
- if self.src.is_empty() {
+ let token = self.cursor.advance_token();
+ if token.kind == TokenKind::Eof {
return None;
}
- let token = rustc_lexer::first_token(self.src);
let (text, rest) = self.src.split_at(token.len as usize);
self.src = rest;
Some((token.kind, text))
@@ -525,7 +525,7 @@ impl<'a> Classifier<'a> {
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
/// file span which will be used later on by the `span_correspondance_map`.
fn new(src: &str, file_span: Span, decoration_info: Option<DecorationInfo>) -> Classifier<'_> {
- let tokens = PeekIter::new(TokenIter { src });
+ let tokens = PeekIter::new(TokenIter { src, cursor: Cursor::new(src) });
let decorations = decoration_info.map(Decorations::new);
Classifier {
tokens,
@@ -850,6 +850,7 @@ impl<'a> Classifier<'a> {
Class::Ident(self.new_span(before, text))
}
TokenKind::Lifetime { .. } => Class::Lifetime,
+ TokenKind::Eof => panic!("Eof in advance"),
};
// Anything that didn't return above is the simple case where we the
// class just spans a single token, so we can use the `string` method.
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 43d07d4a5..1e1c657b0 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -111,14 +111,9 @@ pub(crate) struct MarkdownWithToc<'a>(
pub(crate) Edition,
pub(crate) &'a Option<Playground>,
);
-/// A tuple struct like `Markdown` that renders the markdown escaping HTML tags.
-pub(crate) struct MarkdownHtml<'a>(
- pub(crate) &'a str,
- pub(crate) &'a mut IdMap,
- pub(crate) ErrorCodes,
- pub(crate) Edition,
- pub(crate) &'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);
/// A tuple struct like `Markdown` that renders only the first paragraph.
pub(crate) struct MarkdownSummaryLine<'a>(pub &'a str, pub &'a [RenderedLink]);
@@ -251,8 +246,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
_ => {}
}
}
- let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
- let text = lines.intersperse("\n".into()).collect::<String>();
let parse_result = match kind {
CodeBlockKind::Fenced(ref lang) => {
@@ -265,7 +258,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
<pre class=\"language-{}\"><code>{}</code></pre>\
</div>",
lang,
- Escape(&text),
+ Escape(&origtext),
)
.into(),
));
@@ -275,6 +268,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
CodeBlockKind::Indented => Default::default(),
};
+ let lines = origtext.lines().filter_map(|l| map_line(l).for_html());
+ let text = lines.intersperse("\n".into()).collect::<String>();
+
compile_fail = parse_result.compile_fail;
should_panic = parse_result.should_panic;
ignore = parse_result.ignore;
@@ -818,11 +814,8 @@ impl<'tcx> ExtraInfo<'tcx> {
crate::lint::INVALID_CODEBLOCK_ATTRIBUTES,
hir_id,
self.sp,
- |lint| {
- let mut diag = lint.build(msg);
- diag.help(help);
- diag.emit();
- },
+ msg,
+ |lint| lint.help(help),
);
}
}
@@ -1072,9 +1065,9 @@ impl MarkdownWithToc<'_> {
}
}
-impl MarkdownHtml<'_> {
+impl MarkdownItemInfo<'_> {
pub(crate) fn into_string(self) -> String {
- let MarkdownHtml(md, ids, codes, edition, playground) = self;
+ let MarkdownItemInfo(md, ids) = self;
// This is actually common enough to special-case
if md.is_empty() {
@@ -1093,7 +1086,9 @@ impl MarkdownHtml<'_> {
let p = HeadingLinks::new(p, None, ids, HeadingOffset::H1);
let p = Footnotes::new(p);
let p = TableWrapper::new(p.map(|(ev, _)| ev));
- let p = CodeBlocks::new(p, codes, edition, playground);
+ let p = p.filter(|event| {
+ !matches!(event, Event::Start(Tag::Paragraph) | Event::End(Tag::Paragraph))
+ });
html::push_html(&mut s, p);
s
@@ -1439,6 +1434,7 @@ static DEFAULT_ID_MAP: Lazy<FxHashMap<Cow<'static, str>, usize>> = Lazy::new(||
fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
let mut map = FxHashMap::default();
// This is the list of IDs used in Javascript.
+ map.insert("help".into(), 1);
map.insert("settings".into(), 1);
map.insert("not-displayed".into(), 1);
map.insert("alternative-display".into(), 1);
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 5c0bf0ed9..68b31a6ee 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -1,5 +1,5 @@
use super::{find_testable_code, plain_text_summary, short_markdown_summary};
-use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownHtml};
+use super::{ErrorCodes, HeadingOffset, IdMap, Ignore, LangString, Markdown, MarkdownItemInfo};
use rustc_span::edition::{Edition, DEFAULT_EDITION};
#[test]
@@ -279,14 +279,13 @@ fn test_plain_text_summary() {
fn test_markdown_html_escape() {
fn t(input: &str, expect: &str) {
let mut idmap = IdMap::new();
- let output =
- MarkdownHtml(input, &mut idmap, ErrorCodes::Yes, DEFAULT_EDITION, &None).into_string();
+ let output = MarkdownItemInfo(input, &mut idmap).into_string();
assert_eq!(output, expect, "original: {}", input);
}
- t("`Struct<'a, T>`", "<p><code>Struct&lt;'a, T&gt;</code></p>\n");
- t("Struct<'a, T>", "<p>Struct&lt;’a, T&gt;</p>\n");
- t("Struct<br>", "<p>Struct&lt;br&gt;</p>\n");
+ t("`Struct<'a, T>`", "<code>Struct&lt;'a, T&gt;</code>");
+ t("Struct<'a, T>", "Struct&lt;’a, T&gt;");
+ t("Struct<br>", "Struct&lt;br&gt;");
}
#[test]
@@ -310,3 +309,40 @@ fn test_find_testable_code_line() {
t("```rust\n```\n```rust\n```", &[1, 3]);
t("```rust\n```\n ```rust\n```", &[1, 3]);
}
+
+#[test]
+fn test_ascii_with_prepending_hashtag() {
+ fn t(input: &str, expect: &str) {
+ let mut map = IdMap::new();
+ let output = Markdown {
+ content: input,
+ links: &[],
+ ids: &mut map,
+ error_codes: ErrorCodes::Yes,
+ edition: DEFAULT_EDITION,
+ playground: &None,
+ heading_offset: HeadingOffset::H2,
+ }
+ .into_string();
+ assert_eq!(output, expect, "original: {}", input);
+ }
+
+ t(
+ r#"```ascii
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+```"#,
+ "<div class=\"example-wrap\"><pre class=\"language-ascii\"><code>\
+#..#.####.#....#.....##..
+#..#.#....#....#....#..#.
+####.###..#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.#....#....#....#..#.
+#..#.####.####.####..##..
+</code></pre></div>",
+ );
+}
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 62def4a94..5733d1f9c 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -17,8 +17,8 @@ use super::print_item::{full_path, item_path, print_item};
use super::search_index::build_index;
use super::write_shared::write_shared;
use super::{
- collect_spans_and_sources, print_sidebar, scrape_examples_help, AllTypes, LinkFromSrc, NameDoc,
- StylePath, BASIC_KEYWORDS,
+ collect_spans_and_sources, print_sidebar, scrape_examples_help, sidebar_module_like, AllTypes,
+ LinkFromSrc, NameDoc, StylePath, BASIC_KEYWORDS,
};
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
@@ -430,7 +430,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
extension_css,
resource_suffix,
static_root_path,
- unstable_features,
generate_redirect_map,
show_type_layout,
generate_link_to_definition,
@@ -511,7 +510,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
resource_suffix,
static_root_path,
fs: DocFS::new(sender),
- codes: ErrorCodes::from(unstable_features.is_nightly_build()),
+ codes: ErrorCodes::from(options.unstable_features.is_nightly_build()),
playground,
all: RefCell::new(AllTypes::new()),
errors: receiver,
@@ -581,6 +580,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let crate_name = self.tcx().crate_name(LOCAL_CRATE);
let final_file = self.dst.join(crate_name.as_str()).join("all.html");
let settings_file = self.dst.join("settings.html");
+ let help_file = self.dst.join("help.html");
let scrape_examples_help_file = self.dst.join("scrape-examples-help.html");
let mut root_path = self.dst.to_str().expect("invalid path").to_owned();
@@ -597,16 +597,24 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
keywords: BASIC_KEYWORDS,
resource_suffix: &shared.resource_suffix,
};
- let sidebar = if shared.cache.crate_version.is_some() {
- format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
- } else {
- String::new()
- };
let all = shared.all.replace(AllTypes::new());
+ let mut sidebar = Buffer::html();
+ if shared.cache.crate_version.is_some() {
+ write!(sidebar, "<h2 class=\"location\">Crate {}</h2>", crate_name)
+ };
+
+ let mut items = Buffer::html();
+ sidebar_module_like(&mut items, all.item_sections());
+ if !items.is_empty() {
+ sidebar.push_str("<div class=\"sidebar-elems\">");
+ sidebar.push_buffer(items);
+ sidebar.push_str("</div>");
+ }
+
let v = layout::render(
&shared.layout,
&page,
- sidebar,
+ sidebar.into_inner(),
|buf: &mut Buffer| all.print(buf),
&shared.style_files,
);
@@ -626,9 +634,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
write!(
buf,
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">\
- <span class=\"in-band\">Rustdoc settings</span>\
- </h1>\
+ <h1 class=\"fqn\">Rustdoc settings</h1>\
<span class=\"out-of-band\">\
<a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
Back\
@@ -651,6 +657,39 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
);
shared.fs.write(settings_file, v)?;
+ // Generating help page.
+ page.title = "Rustdoc help";
+ page.description = "Documentation for Rustdoc";
+ page.root_path = "./";
+
+ let sidebar = "<h2 class=\"location\">Help</h2><div class=\"sidebar-elems\"></div>";
+ let v = layout::render(
+ &shared.layout,
+ &page,
+ sidebar,
+ |buf: &mut Buffer| {
+ write!(
+ buf,
+ "<div class=\"main-heading\">\
+ <h1 class=\"fqn\">Rustdoc help</h1>\
+ <span class=\"out-of-band\">\
+ <a id=\"back\" href=\"javascript:void(0)\" onclick=\"history.back();\">\
+ Back\
+ </a>\
+ </span>\
+ </div>\
+ <noscript>\
+ <section>\
+ <p>You need to enable Javascript to use keyboard commands or search.</p>\
+ <p>For more information, browse the <a href=\"https://doc.rust-lang.org/rustdoc/\">rustdoc handbook</a>.</p>\
+ </section>\
+ </noscript>",
+ )
+ },
+ &shared.style_files,
+ );
+ shared.fs.write(help_file, v)?;
+
if shared.layout.scrape_examples_extension {
page.title = "About scraped examples";
page.description = "How the scraped examples feature works in Rustdoc";
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 1e6f20d2b..96c57c8c8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -74,7 +74,9 @@ use crate::html::format::{
PrintWithSpace,
};
use crate::html::highlight;
-use crate::html::markdown::{HeadingOffset, IdMap, Markdown, MarkdownHtml, MarkdownSummaryLine};
+use crate::html::markdown::{
+ HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine,
+};
use crate::html::sources;
use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD;
use crate::scrape_examples::{CallData, CallLocation};
@@ -239,8 +241,8 @@ struct AllTypes {
opaque_tys: FxHashSet<ItemEntry>,
statics: FxHashSet<ItemEntry>,
constants: FxHashSet<ItemEntry>,
- attributes: FxHashSet<ItemEntry>,
- derives: FxHashSet<ItemEntry>,
+ attribute_macros: FxHashSet<ItemEntry>,
+ derive_macros: FxHashSet<ItemEntry>,
trait_aliases: FxHashSet<ItemEntry>,
}
@@ -259,8 +261,8 @@ impl AllTypes {
opaque_tys: new_set(100),
statics: new_set(100),
constants: new_set(100),
- attributes: new_set(100),
- derives: new_set(100),
+ attribute_macros: new_set(100),
+ derive_macros: new_set(100),
trait_aliases: new_set(100),
}
}
@@ -283,27 +285,75 @@ impl AllTypes {
ItemType::OpaqueTy => self.opaque_tys.insert(ItemEntry::new(new_url, name)),
ItemType::Static => self.statics.insert(ItemEntry::new(new_url, name)),
ItemType::Constant => self.constants.insert(ItemEntry::new(new_url, name)),
- ItemType::ProcAttribute => self.attributes.insert(ItemEntry::new(new_url, name)),
- ItemType::ProcDerive => self.derives.insert(ItemEntry::new(new_url, name)),
+ ItemType::ProcAttribute => {
+ self.attribute_macros.insert(ItemEntry::new(new_url, name))
+ }
+ ItemType::ProcDerive => self.derive_macros.insert(ItemEntry::new(new_url, name)),
ItemType::TraitAlias => self.trait_aliases.insert(ItemEntry::new(new_url, name)),
_ => true,
};
}
}
-}
-impl AllTypes {
+ fn item_sections(&self) -> FxHashSet<ItemSection> {
+ let mut sections = FxHashSet::default();
+
+ if !self.structs.is_empty() {
+ sections.insert(ItemSection::Structs);
+ }
+ if !self.enums.is_empty() {
+ sections.insert(ItemSection::Enums);
+ }
+ if !self.unions.is_empty() {
+ sections.insert(ItemSection::Unions);
+ }
+ if !self.primitives.is_empty() {
+ sections.insert(ItemSection::PrimitiveTypes);
+ }
+ if !self.traits.is_empty() {
+ sections.insert(ItemSection::Traits);
+ }
+ if !self.macros.is_empty() {
+ sections.insert(ItemSection::Macros);
+ }
+ if !self.functions.is_empty() {
+ sections.insert(ItemSection::Functions);
+ }
+ if !self.typedefs.is_empty() {
+ sections.insert(ItemSection::TypeDefinitions);
+ }
+ if !self.opaque_tys.is_empty() {
+ sections.insert(ItemSection::OpaqueTypes);
+ }
+ if !self.statics.is_empty() {
+ sections.insert(ItemSection::Statics);
+ }
+ if !self.constants.is_empty() {
+ sections.insert(ItemSection::Constants);
+ }
+ if !self.attribute_macros.is_empty() {
+ sections.insert(ItemSection::AttributeMacros);
+ }
+ if !self.derive_macros.is_empty() {
+ sections.insert(ItemSection::DeriveMacros);
+ }
+ if !self.trait_aliases.is_empty() {
+ sections.insert(ItemSection::TraitAliases);
+ }
+
+ sections
+ }
+
fn print(self, f: &mut Buffer) {
- fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, title: &str, class: &str) {
+ fn print_entries(f: &mut Buffer, e: &FxHashSet<ItemEntry>, kind: ItemSection) {
if !e.is_empty() {
let mut e: Vec<&ItemEntry> = e.iter().collect();
e.sort();
write!(
f,
- "<h3 id=\"{}\">{}</h3><ul class=\"{} docblock\">",
- title.replace(' ', "-"), // IDs cannot contain whitespaces.
- title,
- class
+ "<h3 id=\"{id}\">{title}</h3><ul class=\"all-items\">",
+ id = kind.id(),
+ title = kind.name(),
);
for s in e.iter() {
@@ -314,27 +364,23 @@ impl AllTypes {
}
}
- f.write_str(
- "<h1 class=\"fqn\">\
- <span class=\"in-band\">List of all items</span>\
- </h1>",
- );
+ f.write_str("<h1 class=\"fqn\">List of all items</h1>");
// Note: print_entries does not escape the title, because we know the current set of titles
// doesn't require escaping.
- print_entries(f, &self.structs, "Structs", "structs");
- print_entries(f, &self.enums, "Enums", "enums");
- print_entries(f, &self.unions, "Unions", "unions");
- print_entries(f, &self.primitives, "Primitives", "primitives");
- print_entries(f, &self.traits, "Traits", "traits");
- print_entries(f, &self.macros, "Macros", "macros");
- print_entries(f, &self.attributes, "Attribute Macros", "attributes");
- print_entries(f, &self.derives, "Derive Macros", "derives");
- print_entries(f, &self.functions, "Functions", "functions");
- print_entries(f, &self.typedefs, "Typedefs", "typedefs");
- print_entries(f, &self.trait_aliases, "Trait Aliases", "trait-aliases");
- print_entries(f, &self.opaque_tys, "Opaque Types", "opaque-types");
- print_entries(f, &self.statics, "Statics", "statics");
- print_entries(f, &self.constants, "Constants", "constants")
+ print_entries(f, &self.structs, ItemSection::Structs);
+ print_entries(f, &self.enums, ItemSection::Enums);
+ print_entries(f, &self.unions, ItemSection::Unions);
+ print_entries(f, &self.primitives, ItemSection::PrimitiveTypes);
+ print_entries(f, &self.traits, ItemSection::Traits);
+ print_entries(f, &self.macros, ItemSection::Macros);
+ print_entries(f, &self.attribute_macros, ItemSection::AttributeMacros);
+ print_entries(f, &self.derive_macros, ItemSection::DeriveMacros);
+ print_entries(f, &self.functions, ItemSection::Functions);
+ print_entries(f, &self.typedefs, ItemSection::TypeDefinitions);
+ print_entries(f, &self.trait_aliases, ItemSection::TraitAliases);
+ print_entries(f, &self.opaque_tys, ItemSection::OpaqueTypes);
+ print_entries(f, &self.statics, ItemSection::Statics);
+ print_entries(f, &self.constants, ItemSection::Constants);
}
}
@@ -348,9 +394,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
let mut ids = IdMap::default();
format!(
"<div class=\"main-heading\">\
- <h1 class=\"fqn\">\
- <span class=\"in-band\">About scraped examples</span>\
- </h1>\
+ <h1 class=\"fqn\">About scraped examples</h1>\
</div>\
<div>{}</div>",
Markdown {
@@ -536,7 +580,6 @@ fn short_item_info(
parent: Option<&clean::Item>,
) -> Vec<String> {
let mut extra_info = vec![];
- let error_codes = cx.shared.codes;
if let Some(depr @ Deprecation { note, since, is_since_rustc_version: _, suggestion: _ }) =
item.deprecation(cx.tcx())
@@ -560,13 +603,7 @@ fn short_item_info(
if let Some(note) = note {
let note = note.as_str();
- let html = MarkdownHtml(
- note,
- &mut cx.id_map,
- error_codes,
- cx.shared.edition(),
- &cx.shared.playground,
- );
+ let html = MarkdownItemInfo(note, &mut cx.id_map);
message.push_str(&format!(": {}", html.into_string()));
}
extra_info.push(format!(
@@ -1239,6 +1276,15 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
{
+ // Box has pass-through impls for Read, Write, Iterator, and Future when the
+ // boxed type implements one of those. We don't want to treat every Box return
+ // as being notably an Iterator (etc), though, so we exempt it. Pin has the same
+ // issue, with a pass-through impl for Future.
+ if Some(did) == cx.tcx().lang_items().owned_box()
+ || Some(did) == cx.tcx().lang_items().pin_type()
+ {
+ return "".to_string();
+ }
if let Some(impls) = cx.cache().impls.get(&did) {
for i in impls {
let impl_ = i.inner_impl();
@@ -1251,7 +1297,12 @@ fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
if let Some(trait_) = &impl_.trait_ {
let trait_did = trait_.def_id();
- if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable) {
+ if cx
+ .cache()
+ .traits
+ .get(&trait_did)
+ .map_or(false, |t| t.is_notable_trait(cx.tcx()))
+ {
if out.is_empty() {
write!(
&mut out,
@@ -1555,7 +1606,7 @@ fn render_impl(
link,
render_mode,
false,
- trait_.map(|t| &t.trait_),
+ trait_,
rendering_params,
);
}
@@ -1615,7 +1666,7 @@ fn render_impl(
&mut default_impl_items,
&mut impl_items,
cx,
- &t.trait_,
+ t,
i.inner_impl(),
&i.impl_item,
parent,
@@ -1747,7 +1798,7 @@ pub(crate) fn render_impl_summary(
write!(w, "<section id=\"{}\" class=\"impl has-srclink\"{}>", 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 in-band\">");
+ write!(w, "<h3 class=\"code-header\">");
if let Some(use_absolute) = use_absolute {
write!(w, "{}", inner_impl.print(use_absolute, cx));
@@ -1811,12 +1862,12 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
buffer.write_str("<div class=\"sidebar-elems\">");
if it.is_crate() {
- write!(buffer, "<div class=\"block\"><ul>");
+ write!(buffer, "<ul class=\"block\">");
if let Some(ref version) = cx.cache().crate_version {
write!(buffer, "<li class=\"version\">Version {}</li>", Escape(version));
}
write!(buffer, "<li><a id=\"all-types\" href=\"all.html\">All Items</a></li>");
- buffer.write_str("</ul></div>");
+ buffer.write_str("</ul>");
}
match *it.kind {
@@ -1842,7 +1893,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
if !it.is_mod() {
let path: String = cx.current.iter().map(|s| s.as_str()).intersperse("::").collect();
- write!(buffer, "<h2 class=\"location\"><a href=\"index.html\">In {}</a></h2>", path);
+ write!(buffer, "<h2><a href=\"index.html\">In {}</a></h2>", path);
}
// Closes sidebar-elems div.
@@ -2216,21 +2267,8 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
}
}
-/// Don't call this function directly!!! Use `print_sidebar_title` or `print_sidebar_block` instead!
-fn print_sidebar_title_inner(buf: &mut Buffer, id: &str, title: &str) {
- write!(
- buf,
- "<h3 class=\"sidebar-title\">\
- <a href=\"#{}\">{}</a>\
- </h3>",
- id, title
- );
-}
-
fn print_sidebar_title(buf: &mut Buffer, id: &str, title: &str) {
- buf.push_str("<div class=\"block\">");
- print_sidebar_title_inner(buf, id, title);
- buf.push_str("</div>");
+ write!(buf, "<h3><a href=\"#{}\">{}</a></h3>", id, title);
}
fn print_sidebar_block(
@@ -2239,13 +2277,12 @@ fn print_sidebar_block(
title: &str,
items: impl Iterator<Item = impl fmt::Display>,
) {
- buf.push_str("<div class=\"block\">");
- print_sidebar_title_inner(buf, id, title);
- buf.push_str("<ul>");
+ print_sidebar_title(buf, id, title);
+ buf.push_str("<ul class=\"block\">");
for item in items {
write!(buf, "<li>{}</li>", item);
}
- buf.push_str("</ul></div>");
+ buf.push_str("</ul>");
}
fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
@@ -2469,7 +2506,7 @@ fn sidebar_enum(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, e: &clean:
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-enum ItemSection {
+pub(crate) enum ItemSection {
Reexports,
PrimitiveTypes,
Modules,
@@ -2621,11 +2658,27 @@ fn item_ty_to_section(ty: ItemType) -> ItemSection {
}
}
-fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
+pub(crate) fn sidebar_module_like(buf: &mut Buffer, item_sections_in_use: FxHashSet<ItemSection>) {
use std::fmt::Write as _;
let mut sidebar = String::new();
+ for &sec in ItemSection::ALL.iter().filter(|sec| item_sections_in_use.contains(sec)) {
+ let _ = write!(sidebar, "<li><a href=\"#{}\">{}</a></li>", sec.id(), sec.name());
+ }
+
+ if !sidebar.is_empty() {
+ write!(
+ buf,
+ "<section>\
+ <ul class=\"block\">{}</ul>\
+ </section>",
+ sidebar
+ );
+ }
+}
+
+fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
let item_sections_in_use: FxHashSet<_> = items
.iter()
.filter(|it| {
@@ -2640,21 +2693,8 @@ fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) {
})
.map(|it| item_ty_to_section(it.type_()))
.collect();
- for &sec in ItemSection::ALL.iter().filter(|sec| item_sections_in_use.contains(sec)) {
- let _ = write!(sidebar, "<li><a href=\"#{}\">{}</a></li>", sec.id(), sec.name());
- }
- if !sidebar.is_empty() {
- write!(
- buf,
- "<section>\
- <div class=\"block\">\
- <ul>{}</ul>\
- </div>\
- </section>",
- sidebar
- );
- }
+ sidebar_module_like(buf, item_sections_in_use);
}
fn sidebar_foreign_type(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index cfa450942..632781736 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -400,7 +400,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
if myitem.fn_header(cx.tcx()).unwrap().unsafety
== hir::Unsafety::Unsafe =>
{
- "<a title=\"unsafe function\" href=\"#\"><sup>⚠</sup></a>"
+ "<sup title=\"unsafe function\">⚠</sup>"
}
_ => "",
};
@@ -514,7 +514,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
+ name.as_str().len()
+ generics_len;
- wrap_into_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "fn", |w| {
render_attributes_in_pre(w, it, "");
w.reserve(header_len);
@@ -553,7 +553,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
cx.tcx().trait_def(t.def_id).must_implement_one_of.clone();
// Output the trait definition
- wrap_into_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "trait", |w| {
render_attributes_in_pre(w, it, "");
write!(
@@ -716,9 +716,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
document(&mut content, cx, m, Some(t), HeadingOffset::H5);
let toggled = !content.is_empty();
if toggled {
- write!(w, "<details class=\"rustdoc-toggle\" open><summary>");
+ write!(w, "<details class=\"rustdoc-toggle method-toggle\" open><summary>");
}
- write!(w, "<div id=\"{}\" class=\"method has-srclink\">", id);
+ write!(w, "<section id=\"{}\" class=\"method has-srclink\">", id);
render_rightside(w, cx, m, t, RenderMode::Normal);
write!(w, "<h4 class=\"code-header\">");
render_assoc_item(
@@ -730,7 +730,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
RenderMode::Normal,
);
w.write_str("</h4>");
- w.write_str("</div>");
+ w.write_str("</section>");
if toggled {
write!(w, "</summary>");
w.push_buffer(content);
@@ -890,7 +890,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
w,
"implementors",
"Implementors",
- "<div class=\"item-list\" id=\"implementors-list\">",
+ "<div id=\"implementors-list\">",
);
for implementor in concrete {
render_implementor(cx, implementor, it, w, &implementor_dups, &[]);
@@ -902,7 +902,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
w,
"synthetic-implementors",
"Auto implementors",
- "<div class=\"item-list\" id=\"synthetic-implementors-list\">",
+ "<div id=\"synthetic-implementors-list\">",
);
for implementor in synthetic {
render_implementor(
@@ -923,7 +923,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
w,
"implementors",
"Implementors",
- "<div class=\"item-list\" id=\"implementors-list\"></div>",
+ "<div id=\"implementors-list\"></div>",
);
if t.is_auto(cx.tcx()) {
@@ -931,7 +931,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
w,
"synthetic-implementors",
"Auto implementors",
- "<div class=\"item-list\" id=\"synthetic-implementors-list\"></div>",
+ "<div id=\"synthetic-implementors-list\"></div>",
);
}
}
@@ -1033,7 +1033,7 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "trait-alias", |w| {
render_attributes_in_pre(w, it, "");
write!(
@@ -1057,7 +1057,7 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "opaque", |w| {
render_attributes_in_pre(w, it, "");
write!(
@@ -1096,7 +1096,7 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
});
}
- wrap_into_docblock(w, |w| write_content(w, cx, it, t));
+ wrap_into_item_decl(w, |w| write_content(w, cx, it, t));
document(w, cx, it, None, HeadingOffset::H2);
@@ -1110,7 +1110,7 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "union", |w| {
render_attributes_in_pre(w, it, "");
render_union(w, it, Some(&s.generics), &s.fields, "", cx);
@@ -1174,7 +1174,7 @@ 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 count_variants = e.variants().count();
- wrap_into_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "enum", |w| {
render_attributes_in_pre(w, it, "");
write!(
@@ -1333,14 +1333,14 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
highlight::render_macro_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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
let name = it.name.expect("proc-macros always have names");
match m.kind {
MacroKind::Bang => {
@@ -1387,7 +1387,7 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "const", |w| {
render_attributes_in_code(w, it);
@@ -1436,7 +1436,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
}
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
- wrap_into_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "struct", |w| {
render_attributes_in_code(w, it);
render_struct(w, it, Some(&s.generics), s.struct_type, &s.fields, "", true, cx);
@@ -1489,7 +1489,7 @@ 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_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "static", |w| {
render_attributes_in_code(w, it);
write!(
@@ -1506,7 +1506,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
}
fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
- wrap_into_docblock(w, |w| {
+ wrap_into_item_decl(w, |w| {
wrap_item(w, "foreigntype", |w| {
w.write_str("extern {\n");
render_attributes_in_code(w, it);
@@ -1595,11 +1595,11 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>)
bounds
}
-fn wrap_into_docblock<F>(w: &mut Buffer, f: F)
+fn wrap_into_item_decl<F>(w: &mut Buffer, f: F)
where
F: FnOnce(&mut Buffer),
{
- w.write_str("<div class=\"docblock item-decl\">");
+ w.write_str("<div class=\"item-decl\">");
f(w);
w.write_str("</div>")
}
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index fc4d46fe6..85f63c985 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -517,14 +517,12 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
};
let content = format!(
- "<h1 class=\"fqn\">\
- <span class=\"in-band\">List of all crates</span>\
- </h1><ul class=\"crate mod\">{}</ul>",
+ "<h1 class=\"fqn\">List of all crates</h1><ul class=\"all-items\">{}</ul>",
krates
.iter()
.map(|s| {
format!(
- "<li><a class=\"crate mod\" href=\"{}index.html\">{}</a></li>",
+ "<li><a href=\"{}index.html\">{}</a></li>",
ensure_trailing_slash(s),
s
)
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 2e2bee78b..7ab65bff3 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -274,7 +274,7 @@ pub(crate) fn print_src(
) {
let lines = s.lines().count();
let mut line_numbers = Buffer::empty_from(buf);
- line_numbers.write_str("<pre class=\"line-numbers\">");
+ line_numbers.write_str("<pre class=\"src-line-numbers\">");
match source_context {
SourceContext::Standalone => {
for line in 1..=lines {
diff --git a/src/librustdoc/html/static/css/noscript.css b/src/librustdoc/html/static/css/noscript.css
index 0a19a99ab..301f03a16 100644
--- a/src/librustdoc/html/static/css/noscript.css
+++ b/src/librustdoc/html/static/css/noscript.css
@@ -14,7 +14,11 @@ rules.
display: none;
}
-.sub {
+nav.sub {
/* The search bar and related controls don't work without JS */
display: none;
}
+
+.source .sidebar {
+ display: none;
+}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index bb35970eb..1cc954a98 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -132,19 +132,29 @@ h1, h2, h3, h4, h5, h6 {
font-weight: 500;
}
h1, h2, h3, h4 {
- margin: 20px 0 15px 0;
+ margin: 25px 0 15px 0;
padding-bottom: 6px;
}
.docblock h3, .docblock h4, h5, h6 {
margin: 15px 0 5px 0;
}
+.docblock > h2:first-child,
+.docblock > h3:first-child,
+.docblock > h4:first-child,
+.docblock > h5:first-child,
+.docblock > h6:first-child {
+ margin-top: 0;
+}
h1.fqn {
margin: 0;
padding: 0;
- border-bottom-color: var(--headings-border-bottom-color);
-}
-h2, h3, h4 {
- border-bottom-color: var(--headings-border-bottom-color);
+ flex-grow: 1;
+ /* We use overflow-wrap: break-word for Safari, which doesn't recognize
+ `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */
+ overflow-wrap: break-word;
+ /* Then override it with `anywhere`, which is required to make non-Safari browsers break
+ more aggressively when we want them to. */
+ overflow-wrap: anywhere;
}
.main-heading {
display: flex;
@@ -153,9 +163,6 @@ h2, h3, h4 {
padding-bottom: 6px;
margin-bottom: 15px;
}
-.main-heading a:hover {
- text-decoration: underline;
-}
#toggle-all-docs {
text-decoration: none;
}
@@ -164,7 +171,7 @@ h2, h3, h4 {
Rustdoc-generated h2 section headings (e.g. "Implementations", "Required Methods", etc)
Underlines elsewhere in the documentation break up visual flow and tend to invert
section hierarchies. */
-h2,
+.content h2,
.top-doc .docblock > h3,
.top-doc .docblock > h4 {
border-bottom: 1px solid var(--headings-border-bottom-color);
@@ -177,48 +184,28 @@ h4.code-header {
}
.code-header {
font-weight: 600;
- border-bottom-style: none;
margin: 0;
padding: 0;
- margin-top: 0.6em;
- margin-bottom: 0.4em;
-}
-.impl,
-.impl-items .method,
-.methods .method,
-.impl-items .type,
-.methods .type,
-.impl-items .associatedconstant,
-.methods .associatedconstant,
-.impl-items .associatedtype,
-.methods .associatedtype {
- flex-basis: 100%;
- font-weight: 600;
- position: relative;
}
+#crate-search,
h1, h2, h3, h4, h5, h6,
.sidebar,
.mobile-topbar,
-a.source,
.search-input,
.search-results .result-name,
.item-left > a,
.out-of-band,
span.since,
-details.rustdoc-toggle > summary::before,
-.content ul.crate a.crate,
a.srclink,
-#help-button > button,
+#help-button > a,
details.rustdoc-toggle.top-doc > summary,
-details.rustdoc-toggle.top-doc > summary::before,
details.rustdoc-toggle.non-exhaustive > summary,
-details.rustdoc-toggle.non-exhaustive > summary::before,
.scraped-example-title,
.more-examples-toggle summary, .more-examples-toggle .hide-more,
.example-links a,
/* This selector is for the items listed in the "all items" page. */
-#main-content > ul.docblock > li > a {
+ul.all-items {
font-family: "Fira Sans", Arial, NanumBarunGothic, sans-serif;
}
@@ -230,14 +217,14 @@ pre.rust a,
.sidebar h2 a,
.sidebar h3 a,
.mobile-topbar h2 a,
-.in-band a,
+h1 a,
.search-results a,
.module-item .stab,
.import-item .stab,
.result-name .primitive > i, .result-name .keyword > i,
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
+.method .where,
+.fn .where,
+.where.fmt-newline {
color: var(--main-color);
}
@@ -274,7 +261,7 @@ pre.rust a,
color: var(--macro-link-color);
}
-.content span.mod, .content a.mod, .block a.current.mod {
+.content span.mod, .content a.mod {
color: var(--mod-link-color);
}
@@ -299,32 +286,14 @@ p {
https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html */
margin: 0 0 .75em 0;
}
-
-summary {
- outline: none;
+/* For the last child of a div, the margin will be taken care of
+ by the margin-top of the next item. */
+p:last-child {
+ margin: 0;
}
/* Fix some style changes due to normalize.css 8 */
-td,
-th {
- padding: 0;
-}
-
-table {
- border-collapse: collapse;
-}
-
-button,
-input,
-optgroup,
-select,
-textarea {
- color: inherit;
- font: inherit;
- margin: 0;
-}
-
button {
/* Buttons on Safari have different default padding than other platforms. Make them the same. */
padding: 1px 6px;
@@ -375,9 +344,6 @@ code, pre, a.test-arrow, .code-header {
pre {
padding: 14px;
}
-.docblock.item-decl {
- margin-left: 0;
-}
.item-decl pre {
overflow-x: auto;
}
@@ -394,22 +360,11 @@ img {
overflow: visible;
}
-.sub-container {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
-}
-
.sub-logo-container {
- display: none;
- margin-right: 20px;
+ line-height: 0;
}
-.source .sub-logo-container {
- display: block;
-}
-
-.source .sub-logo-container > img {
+.sub-logo-container > img {
height: 60px;
width: 60px;
object-fit: contain;
@@ -421,7 +376,7 @@ img {
.sidebar {
font-size: 0.875rem;
- width: 250px;
+ width: 200px;
min-width: 200px;
overflow-y: scroll;
position: sticky;
@@ -430,15 +385,6 @@ img {
left: 0;
}
-.sidebar-elems,
-.sidebar > .location {
- padding-left: 24px;
-}
-
-.sidebar .location {
- overflow-wrap: anywhere;
-}
-
.rustdoc.source .sidebar {
width: 50px;
min-width: 0px;
@@ -452,10 +398,6 @@ img {
overflow-y: hidden;
}
-.rustdoc.source .sidebar .sidebar-logo {
- display: none;
-}
-
.source .sidebar, #sidebar-toggle, #source-sidebar {
background-color: var(--sidebar-background-color);
}
@@ -465,16 +407,15 @@ img {
}
.source .sidebar > *:not(#sidebar-toggle) {
- opacity: 0;
visibility: hidden;
}
.source-sidebar-expanded .source .sidebar {
overflow-y: auto;
+ width: 300px;
}
.source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) {
- opacity: 1;
visibility: visible;
}
@@ -532,22 +473,15 @@ img {
width: 100px;
}
-.location:empty {
- border: none;
-}
-
-.location a:first-of-type {
- font-weight: 500;
-}
-
-.block ul, .block li {
+ul.block, .block li {
padding: 0;
margin: 0;
list-style: none;
}
.block a,
-h2.location a {
+.sidebar h2 a,
+.sidebar h3 a {
display: block;
padding: 0.25rem;
margin-left: -0.25rem;
@@ -557,8 +491,7 @@ h2.location a {
}
.sidebar h2 {
- border-bottom: none;
- font-weight: 500;
+ overflow-wrap: anywhere;
padding: 0;
margin: 0;
margin-top: 0.7rem;
@@ -567,11 +500,23 @@ h2.location a {
.sidebar h3 {
font-size: 1.125rem; /* 18px */
- font-weight: 500;
padding: 0;
margin: 0;
}
+.sidebar-elems,
+.sidebar > h2 {
+ padding-left: 24px;
+}
+
+.sidebar a, .sidebar .current {
+ color: var(--sidebar-link-color);
+}
+.sidebar .current,
+.sidebar a:hover {
+ background-color: var(--sidebar-current-link-background-color);
+}
+
.sidebar-elems .block {
margin-bottom: 2em;
}
@@ -585,66 +530,61 @@ h2.location a {
}
.source .content pre.rust {
- white-space: pre;
overflow: auto;
padding-left: 0;
}
.rustdoc .example-wrap {
- display: inline-flex;
+ display: flex;
+ position: relative;
margin-bottom: 10px;
}
+/* For the last child of a div, the margin will be taken care of
+ by the margin-top of the next item. */
+.rustdoc .example-wrap:last-child {
+ margin-bottom: 0px;
+}
-.example-wrap {
- position: relative;
- width: 100%;
+.rustdoc .example-wrap > pre {
+ margin: 0;
+ flex-grow: 1;
+ overflow-x: auto;
}
-.example-wrap > pre.line-number {
+.rustdoc .example-wrap > pre.example-line-numbers,
+.rustdoc .example-wrap > pre.src-line-numbers {
+ flex-grow: 0;
overflow: initial;
+ text-align: right;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.example-line-numbers {
border: 1px solid;
padding: 13px 8px;
- text-align: right;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
+ border-color: var(--example-line-numbers-border-color);
}
-.example-wrap > pre.rust a:hover {
- text-decoration: underline;
-}
-
-.line-numbers {
- text-align: right;
-}
-.rustdoc:not(.source) .example-wrap > pre:not(.line-number) {
- width: 100%;
- overflow-x: auto;
+.src-line-numbers span {
+ cursor: pointer;
+ color: var(--src-line-numbers-span-color);
}
-
-.rustdoc:not(.source) .example-wrap > pre.line-numbers {
- width: auto;
- overflow-x: visible;
+.src-line-numbers .line-highlighted {
+ background-color: var(--src-line-number-highlighted-background-color);
}
-
-.rustdoc .example-wrap > pre {
- margin: 0;
+.src-line-numbers :target {
+ background-color: transparent;
}
.search-loading {
text-align: center;
}
-.content > .example-wrap pre.line-numbers {
- position: relative;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-.line-numbers span {
- cursor: pointer;
-}
-
.docblock-short {
overflow-wrap: break-word;
overflow-wrap: anywhere;
@@ -669,9 +609,6 @@ h2.location a {
.docblock h5 { font-size: 1rem; }
.docblock h6 { font-size: 0.875rem; }
-.docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5, .docblock h6 {
- border-bottom-color: var(--headings-border-bottom-color);
-}
.docblock {
margin-left: 24px;
@@ -683,33 +620,9 @@ h2.location a {
overflow-x: auto;
}
-.content .out-of-band {
+.out-of-band {
flex-grow: 0;
font-size: 1.125rem;
- font-weight: normal;
- float: right;
-}
-
-.method > .code-header, .trait-impl > .code-header {
- max-width: calc(100% - 41px);
- display: block;
-}
-
-.content .in-band {
- flex-grow: 1;
- margin: 0px;
- padding: 0px;
- /* We use overflow-wrap: break-word for Safari, which doesn't recognize
- `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */
- overflow-wrap: break-word;
- /* Then override it with `anywhere`, which is required to make non-Safari browsers break
- more aggressively when we want them to. */
- overflow-wrap: anywhere;
- background-color: var(--main-background-color);
-}
-
-.in-band > code, .in-band > .code-header {
- display: inline-block;
}
.docblock code, .docblock-short code,
@@ -726,6 +639,7 @@ pre, .rustdoc.source .example-wrap {
width: calc(100% - 2px);
overflow-x: auto;
display: block;
+ border-collapse: collapse;
}
.docblock table td {
@@ -740,38 +654,21 @@ pre, .rustdoc.source .example-wrap {
border: 1px solid var(--border-color);
}
-.content .item-list {
- list-style-type: none;
- padding: 0;
-}
-
-.content > .methods > .method {
- font-size: 1rem;
- position: relative;
-}
/* Shift "where ..." part of method or fn definition down a line */
-.content .method .where,
-.content .fn .where,
-.content .where.fmt-newline {
+.method .where,
+.fn .where,
+.where.fmt-newline {
display: block;
font-size: 0.875rem;
}
.item-info {
display: block;
-}
-
-.content .item-info code {
- font-size: 0.875rem;
-}
-
-.content .item-info {
- position: relative;
margin-left: 24px;
}
-.content .impl-items .docblock, .content .impl-items .item-info {
- margin-bottom: .6em;
+.item-info code {
+ font-size: 0.875rem;
}
#main-content > .item-info {
@@ -780,16 +677,24 @@ pre, .rustdoc.source .example-wrap {
}
nav.sub {
+ flex-grow: 1;
+ flex-flow: row nowrap;
+ margin: 4px 0 25px 0;
+ display: flex;
+ align-items: center;
+}
+.search-form {
position: relative;
- font-size: 1rem;
+ display: flex;
+ height: 34px;
flex-grow: 1;
- margin-bottom: 25px;
}
.source nav.sub {
+ margin: 0 0 15px 0;
+}
+.source .search-form {
margin-left: 32px;
}
-nav.sum { text-align: right; }
-nav.sub form { display: inline; }
a {
text-decoration: none;
@@ -805,9 +710,7 @@ a {
display: initial;
}
-.in-band:hover > .anchor, .impl:hover > .anchor, .method.trait-impl:hover > .anchor,
-.type.trait-impl:hover > .anchor, .associatedconstant.trait-impl:hover > .anchor,
-.associatedtype.trait-impl:hover > .anchor {
+.impl:hover > .anchor, .trait-impl:hover > .anchor {
display: inline-block;
position: absolute;
}
@@ -831,12 +734,16 @@ h2.small-section-header > .anchor {
content: '§';
}
-.docblock a:not(.srclink):not(.test-arrow):not(.scrape-help):hover,
-.docblock-short a:not(.srclink):not(.test-arrow):not(.scrape-help):hover, .item-info a {
+.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,
+.item-info a {
text-decoration: underline;
}
-.block a.current.crate { font-weight: 500; }
+.crate.block a.current { font-weight: 500; }
/* In most contexts we use `overflow-wrap: anywhere` to ensure that we can wrap
as much as needed on mobile (see
@@ -876,15 +783,6 @@ table,
padding-right: 1.25rem;
}
-.search-container {
- position: relative;
- display: flex;
- height: 34px;
- margin-top: 4px;
-}
-.search-container > * {
- height: 100%;
-}
.search-results-title {
margin-top: 0;
white-space: nowrap;
@@ -922,6 +820,9 @@ table,
/* Removes default arrow from firefox */
text-indent: 0.01px;
background-color: var(--main-background-color);
+ color: inherit;
+ line-height: 1.5;
+ font-weight: 500;
}
/* cancel stylistic differences in padding in firefox
for "appearance: none"-style (or equivalent) <select>s */
@@ -957,18 +858,14 @@ so that we can apply CSS-filters to change the arrow color in themes */
-webkit-appearance: textfield for search inputs. That
causes rounded corners and no border on iOS Safari. */
-webkit-appearance: none;
- /* Override Normalize.css: we have margins and do
- not want to overflow - the `moz` attribute is necessary
- until Firefox 29, too early to drop at this point */
- -moz-box-sizing: border-box !important;
- box-sizing: border-box !important;
outline: none;
border: 1px solid var(--border-color);
border-radius: 2px;
padding: 8px;
font-size: 1rem;
- width: 100%;
+ flex-grow: 1;
background-color: var(--button-background-color);
+ color: var(--search-color);
}
.search-input:focus {
border-color: var(--search-input-focused-border-color);
@@ -1005,13 +902,18 @@ so that we can apply CSS-filters to change the arrow color in themes */
flex-flow: row wrap;
}
-.search-results .result-name, .search-results div.desc, .search-results .result-description {
+.search-results .result-name, .search-results div.desc {
width: 50%;
}
.search-results .result-name {
padding-right: 1em;
}
+.search-results a:hover,
+.search-results a:focus {
+ background-color: var(--search-result-link-focus-background-color);
+}
+
.popover {
font-size: 1rem;
position: absolute;
@@ -1042,40 +944,36 @@ so that we can apply CSS-filters to change the arrow color in themes */
color: var(--main-color);
}
-#help-button .popover {
+/* use larger max-width for help popover, but not for help.html */
+#help.popover {
max-width: 600px;
}
-#help-button .popover::before {
+#help.popover::before {
right: 48px;
}
-#help-button dt {
+#help dt {
float: left;
clear: left;
display: block;
margin-right: 0.5rem;
}
-#help-button span.top, #help-button span.bottom {
+#help span.top, #help span.bottom {
text-align: center;
display: block;
font-size: 1.125rem;
}
-#help-button span.top {
- text-align: center;
- display: block;
+#help span.top {
margin: 10px 0;
border-bottom: 1px solid var(--border-color);
padding-bottom: 4px;
margin-bottom: 6px;
}
-#help-button span.bottom {
+#help span.bottom {
clear: both;
border-top: 1px solid var(--border-color);
}
-.side-by-side {
- text-align: initial;
-}
.side-by-side > div {
width: 50%;
float: left;
@@ -1097,10 +995,13 @@ so that we can apply CSS-filters to change the arrow color in themes */
margin-bottom: 5px;
font-size: 0.875rem;
font-weight: normal;
+ color: var(--main-color);
+ background-color: var(--stab-background-color);
}
-.stab p {
- display: inline;
- margin: 0;
+
+.stab.portability > code {
+ background: none;
+ color: var(--stab-code-color);
}
.stab .emoji {
@@ -1108,6 +1009,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
margin-right: 0.3rem;
}
+/* This is to prevent the `.stab` elements to overflow the .docblock elements. */
+.docblock .stab {
+ padding: 0 0.125em;
+ margin-bottom: 0;
+}
+
/* Black one-pixel outline around emoji shapes */
.emoji {
text-shadow:
@@ -1142,7 +1049,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
.rightside {
padding-left: 12px;
padding-right: 2px;
- position: initial;
float: right;
}
@@ -1151,23 +1057,55 @@ so that we can apply CSS-filters to change the arrow color in themes */
color: var(--right-side-color);
}
-
-.impl-items .srclink, .impl .srclink, .methods .srclink {
- /* Override header settings otherwise it's too bold */
- font-weight: normal;
- font-size: 1rem;
+pre.rust {
+ tab-size: 4;
+ -moz-tab-size: 4;
}
-td.summary-column {
- width: 100%;
+/* Code highlighting */
+pre.rust .kw {
+ color: var(--code-highlight-kw-color);
}
-
-.summary {
- padding-right: 0px;
+pre.rust .kw-2 {
+ color: var(--code-highlight-kw-2-color);
+}
+pre.rust .lifetime {
+ color: var(--code-highlight-lifetime-color);
+}
+pre.rust .prelude-ty {
+ color: var(--code-highlight-prelude-color);
+}
+pre.rust .prelude-val {
+ color: var(--code-highlight-prelude-val-color);
+}
+pre.rust .string {
+ color: var(--code-highlight-string-color);
+}
+pre.rust .number {
+ color: var(--code-highlight-number-color);
+}
+pre.rust .bool-val {
+ color: var(--code-highlight-literal-color);
+}
+pre.rust .self {
+ color: var(--code-highlight-self-color);
+}
+pre.rust .attribute {
+ color: var(--code-highlight-attribute-color);
+}
+pre.rust .macro,
+pre.rust .macro-nonterminal {
+ color: var(--code-highlight-macro-color);
}
-
pre.rust .question-mark {
font-weight: bold;
+ color: var(--code-highlight-question-mark-color);
+}
+pre.rust .comment {
+ color: var(--code-highlight-comment-color);
+}
+pre.rust .doccomment {
+ color: var(--code-highlight-doc-comment-color);
}
.example-wrap.compile_fail,
@@ -1278,9 +1216,6 @@ a.test-arrow {
.example-wrap:hover .test-arrow {
visibility: visible;
}
-a.test-arrow:hover {
- text-decoration: none;
-}
.code-attribute {
font-weight: 300;
@@ -1300,13 +1235,11 @@ h3.variant {
font-weight: 600;
font-size: 1.125rem;
margin-bottom: 10px;
- border-bottom: none;
}
.sub-variant h4 {
font-size: 1rem;
font-weight: 400;
- border-bottom: none;
margin-top: 0;
margin-bottom: 0;
}
@@ -1357,7 +1290,7 @@ h3.variant {
content: "\00a0\00a0\00a0";
}
-.notable-traits .notable, .notable-traits .docblock {
+.notable-traits .docblock {
margin: 0;
}
@@ -1375,16 +1308,6 @@ h3.variant {
font-size: 1.25rem;
}
-/* Example code has the "Run" button that needs to be positioned relative to the pre */
-pre.rust.rust-example-rendered {
- position: relative;
-}
-
-pre.rust {
- tab-size: 4;
- -moz-tab-size: 4;
-}
-
.search-failed {
text-align: center;
margin-top: 20px;
@@ -1416,6 +1339,8 @@ pre.rust {
border: 0;
border-top: 2px solid;
flex: 1;
+ line-height: 1.5;
+ color: inherit;
}
#titles > button > div.count {
@@ -1433,7 +1358,6 @@ pre.rust {
position: sticky;
top: 0;
left: 0;
- font-weight: bold;
font-size: 1.25rem;
border-bottom: 1px solid;
display: flex;
@@ -1444,7 +1368,6 @@ pre.rust {
}
#source-sidebar {
width: 100%;
- z-index: 1;
overflow: auto;
}
#source-sidebar > .title {
@@ -1454,6 +1377,8 @@ pre.rust {
margin-bottom: 6px;
}
#sidebar-toggle > button {
+ font-size: inherit;
+ font-weight: bold;
background: none;
color: inherit;
cursor: pointer;
@@ -1476,23 +1401,29 @@ pre.rust {
outline: none;
}
-#settings-menu > a, #help-button > button, #copy-path {
- padding: 5px;
+#settings-menu > a, #help-button > a, #copy-path {
width: 33px;
- border: 1px solid var(--border-color);
- border-radius: 2px;
cursor: pointer;
+ line-height: 1.5;
}
-#settings-menu > a, #help-button > button {
+#settings-menu > a, #help-button > a {
padding: 5px;
height: 100%;
display: block;
background-color: var(--button-background-color);
+ border: 1px solid var(--border-color);
+ border-radius: 2px;
}
#copy-path {
color: var(--copy-path-button-color);
+ background: var(--main-background-color);
+ height: 34px;
+ margin-left: 10px;
+ padding: 0;
+ padding-left: 2px;
+ border: 0;
}
#copy-path > img {
filter: var(--copy-path-img-filter);
@@ -1513,26 +1444,7 @@ pre.rust {
animation: rotating 2s linear infinite;
}
-.setting-line .radio-line input:checked {
- box-shadow: inset 0 0 0 3px var(--main-background-color);
- background-color: var(--settings-input-color);
-}
-.setting-line .radio-line 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 {
- 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 {
- border-color: var(--settings-input-color) !important;
-}
-input:checked + .slider {
- background-color: var(--settings-input-color);
-}
-
-#help-button > button {
+#help-button > a {
text-align: center;
/* Rare exception to specifying font sizes in rem. Since this is acting
as an icon, it's okay to specify their sizes in pixels. */
@@ -1540,15 +1452,6 @@ input:checked + .slider {
padding-top: 2px;
}
-#copy-path {
- height: 34px;
- background-color: var(--main-background-color);
- margin-left: 10px;
- padding: 0;
- padding-left: 2px;
- border: 0;
-}
-
kbd {
display: inline-block;
padding: 3px 5px;
@@ -1560,25 +1463,39 @@ kbd {
cursor: default;
}
-#main-content > ul {
- padding-left: 10px;
-}
-#main-content > ul > li {
+ul.all-items > li {
list-style: none;
}
-.non-exhaustive {
- margin-bottom: 1em;
-}
-
details.dir-entry {
padding-left: 4px;
}
+details.dir-entry > summary::after {
+ content: " ►";
+ position: absolute;
+ left: -15px;
+ top: 0px;
+ font-size: 80%;
+ padding: 2px 0px;
+ /* set width to cover gap between arrow and text */
+ width: 25px;
+}
+
+details[open].dir-entry > summary::after {
+ content: " ▼";
+}
+
+details.dir-entry > summary::-webkit-details-marker,
+details.dir-entry > summary::marker {
+ display: none;
+}
+
details.dir-entry > summary {
margin: 0 0 0 13px;
- list-style-position: outside;
+ list-style: none;
cursor: pointer;
+ position: relative;
}
details.dir-entry div.folders, details.dir-entry div.files {
@@ -1589,6 +1506,17 @@ details.dir-entry a {
display: block;
}
+/* We use CSS containment on the details elements because most sizeable elements
+ of the page are contained in one of these. This also makes re-rendering
+ faster on document changes (like closing and opening toggles).
+ Unfortunately we can't yet specify contain: content or contain: strict
+ because the [-]/[+] toggles extend past the boundaries of the <details>
+ https://developer.mozilla.org/en-US/docs/Web/CSS/contain */
+details.rustdoc-toggle {
+ contain: layout;
+ position: relative;
+}
+
/* The hideme class is used on summary tags that contain a span with
placeholder text shown only when the toggle is closed. For instance,
"Expand description" or "Show methods". */
@@ -1598,6 +1526,8 @@ details.rustdoc-toggle > summary.hideme {
details.rustdoc-toggle > summary {
list-style: none;
+ /* focus outline is shown on `::before` instead of this */
+ outline: none;
}
details.rustdoc-toggle > summary::-webkit-details-marker,
details.rustdoc-toggle > summary::marker {
@@ -1621,7 +1551,6 @@ details.rustdoc-toggle > summary::before {
}
details.rustdoc-toggle > summary.hideme > span,
-details.rustdoc-toggle > summary::before,
.more-examples-toggle summary, .more-examples-toggle .hide-more {
color: var(--toggles-color);
}
@@ -1646,6 +1575,15 @@ details.rustdoc-toggle > summary:hover::before {
opacity: 1;
}
+details.rustdoc-toggle > summary:focus-visible::before {
+ /* The SVG is black, and gets turned white using a filter in the dark themes.
+ Do the same with the outline.
+ The dotted 1px style is copied from Firefox's focus ring style.
+ */
+ outline: 1px dotted #000;
+ outline-offset: 1px;
+}
+
details.rustdoc-toggle.top-doc > summary,
details.rustdoc-toggle.top-doc > summary::before,
details.rustdoc-toggle.non-exhaustive > summary,
@@ -1681,10 +1619,6 @@ details.rustdoc-toggle[open] > summary.hideme {
position: absolute;
}
-details.rustdoc-toggle {
- position: relative;
-}
-
details.rustdoc-toggle[open] > summary.hideme > span {
display: none;
}
@@ -1718,37 +1652,20 @@ details.rustdoc-toggle[open] > summary.hideme::after {
display: inline-block;
}
-/* Media Queries */
-
-/*
-WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY;
-If you update this line, then you also need to update the line with the same warning
-in storage.js plus the media query with (max-width: 700px)
-*/
-@media (min-width: 701px) {
- /* In case there is no documentation before a code block, we need to add some margin at the top
- to prevent an overlay between the "collapse toggle" and the information tooltip.
- However, it's not needed with smaller screen width because the doc/code block is always put
- "one line" below. */
- .docblock > .example-wrap:first-child .tooltip {
- margin-top: 16px;
- }
-
- /* When we expand the sidebar on the source code page, we hide the logo on the left of the
- search bar to have more space. */
- .source-sidebar-expanded .source .sidebar + main .width-limiter .sub-logo-container.rust-logo {
- display: none;
- }
-
- .source-sidebar-expanded .source .sidebar {
- width: 300px;
- }
+/* In case there is no documentation before a code block, we need to add some margin at the top
+to prevent an overlay between the "collapse toggle" and the information tooltip.
+However, it's not needed with smaller screen width because the doc/code block is always put
+"one line" below. */
+.docblock > .example-wrap:first-child .tooltip {
+ margin-top: 16px;
}
+/* Media Queries */
+
/*
WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
If you update this line, then you also need to update the line with the same warning
-in storage.js plus the media query with (min-width: 701px)
+in storage.js
*/
@media (max-width: 700px) {
/* When linking to an item with an `id` (for instance, by clicking a link in the sidebar,
@@ -1775,13 +1692,13 @@ in storage.js plus the media query with (min-width: 701px)
flex-direction: column;
}
- .content .out-of-band {
+ .out-of-band {
text-align: left;
margin-left: initial;
padding: initial;
}
- .content .out-of-band .since::before {
+ .out-of-band .since::before {
content: "Since ";
}
@@ -1827,24 +1744,13 @@ in storage.js plus the media query with (min-width: 701px)
}
.rustdoc.source > .sidebar {
- position: fixed;
- margin: 0;
- z-index: 11;
width: 0;
}
- .mobile-topbar .location a {
- padding: 0;
- margin: 0;
- }
-
- .mobile-topbar .location {
- border: none;
- padding: 0;
+ .mobile-topbar h2 {
+ padding-bottom: 0;
margin: auto 0.5em auto auto;
- text-overflow: ellipsis;
overflow: hidden;
- white-space: nowrap;
/* Rare exception to specifying font sizes in rem. Since the topbar
height is specified in pixels, this also has to be specified in
pixels to avoid overflowing the topbar when the user sets a bigger
@@ -1852,6 +1758,13 @@ in storage.js plus the media query with (min-width: 701px)
font-size: 24px;
}
+ .mobile-topbar h2 a {
+ display: block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ }
+
.mobile-topbar .logo-container {
max-height: 45px;
}
@@ -1876,16 +1789,13 @@ in storage.js plus the media query with (min-width: 701px)
top: 0;
}
- .source .mobile-topbar {
- display: none;
- }
-
.sidebar-menu-toggle {
width: 45px;
/* Rare exception to specifying font sizes in rem. Since this is acting
as an icon, it's okay to specify its sizes in pixels. */
font-size: 32px;
border: none;
+ color: var(--main-color);
}
.sidebar-elems {
@@ -1897,10 +1807,6 @@ in storage.js plus the media query with (min-width: 701px)
margin-left: 0px;
}
- .source .content {
- margin-top: 10px;
- }
-
.anchor {
display: none !important;
}
@@ -1941,7 +1847,6 @@ in storage.js plus the media query with (min-width: 701px)
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
cursor: pointer;
- font-weight: bold;
border: 1px solid;
border-left: 0;
}
@@ -1957,14 +1862,6 @@ in storage.js plus the media query with (min-width: 701px)
border-bottom: 1px solid;
}
- #source-sidebar {
- z-index: 11;
- }
-
- #main-content > .line-numbers {
- margin-top: 0;
- }
-
.notable-traits .notable-traits-tooltiptext {
left: 0;
top: 100%;
@@ -1992,10 +1889,10 @@ in storage.js plus the media query with (min-width: 701px)
border-bottom: 1px solid #aaa9;
padding: 5px 0px;
}
- .search-results .result-name, .search-results div.desc, .search-results .result-description {
+ .search-results .result-name, .search-results div.desc {
width: 100%;
}
- .search-results div.desc, .search-results .result-description, .item-right {
+ .search-results div.desc, .item-right {
padding-left: 2em;
}
@@ -2015,13 +1912,18 @@ in storage.js plus the media query with (min-width: 701px)
}
/* Align summary-nested and unnested item-info gizmos. */
- .content .impl-items > .item-info {
+ .impl-items > .item-info {
margin-left: 34px;
}
+
+ .source nav.sub {
+ margin: 0;
+ padding: 8px;
+ }
}
@media print {
- nav.sidebar, nav.sub, .content .out-of-band, a.srclink, #copy-path,
+ nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
details.rustdoc-toggle.top-doc > summary {
display: none;
@@ -2037,10 +1939,6 @@ in storage.js plus the media query with (min-width: 701px)
}
@media (max-width: 464px) {
- #crate-search {
- border-radius: 4px;
- }
-
.docblock {
margin-left: 12px;
}
@@ -2050,15 +1948,15 @@ in storage.js plus the media query with (min-width: 701px)
overflow-wrap: anywhere;
}
- .sub-container {
+ nav.sub {
flex-direction: column;
}
- .sub-logo-container {
- align-self: center;
+ .search-form {
+ align-self: stretch;
}
- .source .sub-logo-container > img {
+ .sub-logo-container > img {
height: 35px;
width: 35px;
}
@@ -2071,23 +1969,24 @@ in storage.js plus the media query with (min-width: 701px)
}
}
-.method-toggle summary,
-.implementors-toggle summary,
-.impl {
+.method-toggle > summary,
+.implementors-toggle > summary,
+.impl,
+#implementors-list > .docblock,
+.impl-items > section,
+.methods > section
+{
margin-bottom: 0.75em;
}
-.method-toggle[open] {
+.method-toggle[open]:not(:last-child),
+.implementors-toggle[open]:not(:last-child) {
margin-bottom: 2em;
}
-.implementors-toggle[open] {
- margin-bottom: 2em;
-}
-
-#trait-implementations-list .method-toggle,
-#synthetic-implementations-list .method-toggle,
-#blanket-implementations-list .method-toggle {
+#trait-implementations-list .method-toggle:not(:last-child),
+#synthetic-implementations-list .method-toggle:not(:last-child),
+#blanket-implementations-list .method-toggle:not(:last-child) {
margin-bottom: 1em;
}
@@ -2124,10 +2023,6 @@ in storage.js plus the media query with (min-width: 701px)
padding-bottom: 0;
}
-.scraped-example:not(.expanded) .code-wrapper pre.line-numbers {
- overflow-x: hidden;
-}
-
.scraped-example .code-wrapper .prev {
position: absolute;
top: 0.25em;
@@ -2170,12 +2065,12 @@ in storage.js plus the media query with (min-width: 701px)
bottom: 0;
}
-.scraped-example .code-wrapper .line-numbers {
+.scraped-example .code-wrapper .src-line-numbers {
margin: 0;
padding: 14px 0;
}
-.scraped-example .code-wrapper .line-numbers span {
+.scraped-example .code-wrapper .src-line-numbers span {
padding: 0 14px;
}
diff --git a/src/librustdoc/html/static/css/settings.css b/src/librustdoc/html/static/css/settings.css
index e82ec0426..83939f63b 100644
--- a/src/librustdoc/html/static/css/settings.css
+++ b/src/librustdoc/html/static/css/settings.css
@@ -12,7 +12,8 @@
margin-right: 0.3em;
height: 1.2rem;
width: 1.2rem;
- border: 1px solid;
+ color: inherit;
+ border: 1px solid currentColor;
outline: none;
-webkit-appearance: none;
cursor: pointer;
@@ -88,3 +89,22 @@ input:checked + .slider:before {
#settings .setting-line {
margin: 1.2em 0.6em;
}
+
+.setting-line .radio-line input:checked {
+ box-shadow: inset 0 0 0 3px var(--main-background-color);
+ background-color: var(--settings-input-color);
+}
+.setting-line .radio-line 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 {
+ 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 {
+ border-color: var(--settings-input-color) !important;
+}
+input:checked + .slider {
+ background-color: var(--settings-input-color);
+}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index e7a898e9f..fdfdb3e19 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -35,6 +35,29 @@ Original by Dempfi (https://github.com/dempfi/ayu)
--keyword-link-color: #39afd7;
--mod-link-color: #39afd7;
--link-color: #39afd7;
+ --sidebar-link-color: #53b1db;
+ --sidebar-current-link-background-color: transparent;
+ --search-result-link-focus-background-color: #3c3c3c;
+ --stab-background-color: #314559;
+ --stab-code-color: #e6e1cf;
+ --search-color: #fff;
+ --code-highlight-kw-color: #ff7733;
+ --code-highlight-kw-2-color: #ff7733;
+ --code-highlight-lifetime-color: #ff7733;
+ --code-highlight-prelude-color: #69f2df;
+ --code-highlight-prelude-val-color: #ff7733;
+ --code-highlight-number-color: #b8cc52;
+ --code-highlight-string-color: #b8cc52;
+ --code-highlight-literal-color: #ff7733;
+ --code-highlight-attribute-color: #e6e1cf;
+ --code-highlight-self-color: #36a3d9;
+ --code-highlight-macro-color: #a37acc;
+ --code-highlight-question-mark-color: #ff9011;
+ --code-highlight-comment-color: #788797;
+ --code-highlight-doc-comment-color: #a1ac88;
+ --example-line-numbers-border-color: none;
+ --src-line-numbers-span-color: #5c6773;
+ --src-line-number-highlighted-background-color: rgba(255, 236, 164, 0.06);
}
.slider {
@@ -50,7 +73,7 @@ input:focus + .slider {
h1, h2, h3, h4 {
color: white;
}
-h1.fqn a {
+h1 a {
color: #fff;
}
h4 {
@@ -85,7 +108,6 @@ pre, .rustdoc.source .example-wrap {
.sidebar .current,
.sidebar a:hover {
- background-color: transparent;
color: #ffb44c;
}
@@ -93,10 +115,8 @@ pre, .rustdoc.source .example-wrap {
color: #ff7733;
}
-.line-numbers span { color: #5c6773; }
-.line-numbers .line-highlighted {
+.src-line-numbers .line-highlighted {
color: #708090;
- background-color: rgba(255, 236, 164, 0.06);
padding-right: 4px;
border-right: 1px solid #ffb44c;
}
@@ -119,12 +139,6 @@ pre, .rustdoc.source .example-wrap {
.content .item-info::before { color: #ccc; }
-.sidebar a { color: #53b1db; }
-.sidebar a.current.type { color: #53b1db; }
-
-pre.rust .comment { color: #788797; }
-pre.rust .doccomment { color: #a1ac88; }
-
.sidebar h2 a,
.sidebar h3 a {
color: white;
@@ -148,53 +162,15 @@ details.rustdoc-toggle > summary::before {
filter: invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);
}
-.search-input {
- color: #fff;
-}
-
.module-item .stab,
.import-item .stab {
color: #000;
}
-.stab {
- color: #c5c5c5;
- background: #314559 !important;
-}
-
-.stab.portability > code {
- color: #e6e1cf;
- background: none;
-}
-
.result-name .primitive > i, .result-name .keyword > i {
color: #788797;
}
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .number, pre.rust .string { color: #b8cc52; }
-pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty,
-pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .lifetime { color: #ff7733; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-pre.rust .self {
- color: #36a3d9;
- font-style: italic;
-}
-pre.rust .attribute {
- color: #e6e1cf;
-}
-
-.example-wrap > pre.line-number {
- color: #5c67736e;
- border: none;
-}
-
a.test-arrow {
font-size: 100%;
color: #788797;
@@ -260,52 +236,13 @@ pre.rust .kw {}
pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, pre.rust .attribute {}
pre.rust .kw-2, pre.rust .prelude-ty {}
-.search-results a:focus span {}
-a.result-trait:focus {}
-a.result-traitalias:focus {}
-a.result-mod:focus,
-a.result-externcrate:focus {}
-a.result-mod:focus {}
-a.result-externcrate:focus {}
-a.result-enum:focus {}
-a.result-struct:focus {}
-a.result-union:focus {}
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus {}
-a.result-type:focus {}
-a.result-associatedtype:focus {}
-a.result-foreigntype:focus {}
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus {}
-a.result-constant:focus,
-a.result-static:focus {}
-a.result-primitive:focus {}
-a.result-keyword:focus {}
-
-.sidebar a.current.enum {}
-.sidebar a.current.struct {}
-.sidebar a.current.foreigntype {}
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro {}
-.sidebar a.current.union {}
-.sidebar a.current.constant
-.sidebar a.current.static {}
-.sidebar a.current.primitive {}
-.sidebar a.current.trait {}
-.sidebar a.current.traitalias {}
-.sidebar a.current.fn {}
-.sidebar a.current.keyword {}
-
kbd {
color: #c5c5c5;
background-color: #314559;
box-shadow: inset 0 -1px 0 #5c6773;
}
-#settings-menu > a, #help-button > button {
+#settings-menu > a, #help-button > a {
color: #fff;
}
@@ -314,7 +251,7 @@ kbd {
}
#settings-menu > a:hover, #settings-menu > a:focus,
-#help-button > button:hover, #help-button > button:focus {
+#help-button > a:hover, #help-button > a:focus {
border-color: #e0e0e0;
}
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 07a1ed8b7..361d3d4a2 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -30,6 +30,29 @@
--keyword-link-color: #d2991d;
--mod-link-color: #d2991d;
--link-color: #d2991d;
+ --sidebar-link-color: #fdbf35;
+ --sidebar-current-link-background-color: #444;
+ --search-result-link-focus-background-color: #616161;
+ --stab-background-color: #314559;
+ --stab-code-color: #e6e1cf;
+ --search-color: #111;
+ --code-highlight-kw-color: #ab8ac1;
+ --code-highlight-kw-2-color: #769acb;
+ --code-highlight-lifetime-color: #d97f26;
+ --code-highlight-prelude-color: #769acb;
+ --code-highlight-prelude-val-color: #ee6868;
+ --code-highlight-number-color: #83a300;
+ --code-highlight-string-color: #83a300;
+ --code-highlight-literal-color: #ee6868;
+ --code-highlight-attribute-color: #ee6868;
+ --code-highlight-self-color: #ee6868;
+ --code-highlight-macro-color: #3e999f;
+ --code-highlight-question-mark-color: #ff9011;
+ --code-highlight-comment-color: #8d8d8b;
+ --code-highlight-doc-comment-color: #8ca375;
+ --example-line-numbers-border-color: #4a4949;
+ --src-line-numbers-span-color: #3b91e2;
+ --src-line-number-highlighted-background-color: #0a042f;
}
.slider {
@@ -49,68 +72,8 @@ input:focus + .slider {
drop-shadow(0 -1px 0 #fff)
}
-.sidebar .current,
-.sidebar a:hover {
- background: #444;
-}
-
-.line-numbers span { color: #3B91E2; }
-.line-numbers .line-highlighted {
- background-color: #0a042f !important;
-}
-
-.search-results a:hover {
- background-color: #777;
-}
-
-.search-results a:focus {
- color: #eee !important;
- background-color: #616161;
-}
-.search-results a:focus span { color: #eee !important; }
-a.result-trait:focus { background-color: #013191; }
-a.result-traitalias:focus { background-color: #013191; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #884719; }
-a.result-enum:focus { background-color: #194e9f; }
-a.result-struct:focus { background-color: #194e9f; }
-a.result-union:focus { background-color: #194e9f; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #4950ed; }
-a.result-type:focus { background-color: #194e9f; }
-a.result-associatedtype:focus { background-color: #884719; }
-a.result-foreigntype:focus { background-color: #194e9f; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #217d1c; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #884719; }
-a.result-primitive:focus { background-color: #194e9f; }
-a.result-keyword:focus { background-color: #884719; }
-
.content .item-info::before { color: #ccc; }
-.sidebar a { color: #fdbf35; }
-.sidebar a.current.enum { color: #12ece2; }
-.sidebar a.current.struct { color: #12ece2; }
-.sidebar a.current.type { color: #12ece2; }
-.sidebar a.current.foreigntype { color: #12ece2; }
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro { color: #0be900; }
-.sidebar a.current.union { color: #12ece2; }
-.sidebar a.current.constant
-.sidebar a.current.static { color: #fdbf35; }
-.sidebar a.current.primitive { color: #12ece2; }
-.sidebar a.current.trait { color: #cca7ff; }
-.sidebar a.current.traitalias { color: #cca7ff; }
-.sidebar a.current.fn { color: #32d479; }
-.sidebar a.current.keyword { color: #fdbf35; }
-
-pre.rust .comment { color: #8d8d8b; }
-pre.rust .doccomment { color: #8ca375; }
-
body.source .example-wrap pre.rust a {
background: #333;
}
@@ -119,10 +82,6 @@ details.rustdoc-toggle > summary::before {
filter: invert(100%);
}
-.search-input {
- color: #111;
-}
-
#crate-search-div::after {
/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);
@@ -134,31 +93,6 @@ details.rustdoc-toggle > summary::before {
filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
}
-.stab { background: #314559; }
-
-.stab.portability > code {
- color: #e6e1cf;
- background: none;
-}
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #ab8ac1; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; }
-pre.rust .number, pre.rust .string { color: #83a300; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute { color: #ee6868; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #d97f26; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
- border-color: #4a4949;
-}
-
a.test-arrow {
color: #dedede;
background-color: rgba(78, 139, 202, 0.2);
@@ -211,12 +145,12 @@ kbd {
box-shadow: inset 0 -1px 0 #c6cbd1;
}
-#settings-menu > a, #help-button > button {
+#settings-menu > a, #help-button > a {
color: #000;
}
#settings-menu > a:hover, #settings-menu > a:focus,
-#help-button > button:hover, #help-button > button:focus {
+#help-button > a:hover, #help-button > a:focus {
border-color: #ffb900;
}
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 64335f629..5eb4bbcf8 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -30,6 +30,29 @@
--keyword-link-color: #3873ad;
--mod-link-color: #3873ad;
--link-color: #3873ad;
+ --sidebar-link-color: #356da4;
+ --sidebar-current-link-background-color: #fff;
+ --search-result-link-focus-background-color: #ccc;
+ --stab-background-color: #fff5d6;
+ --stab-code-color: #000;
+ --search-color: #000;
+ --code-highlight-kw-color: #8959a8;
+ --code-highlight-kw-2-color: #4271ae;
+ --code-highlight-lifetime-color: #b76514;
+ --code-highlight-prelude-color: #4271ae;
+ --code-highlight-prelude-val-color: #c82829;
+ --code-highlight-number-color: #718c00;
+ --code-highlight-string-color: #718c00;
+ --code-highlight-literal-color: #c82829;
+ --code-highlight-attribute-color: #c82829;
+ --code-highlight-self-color: #c82829;
+ --code-highlight-macro-color: #3e999f;
+ --code-highlight-question-mark-color: #ff9011;
+ --code-highlight-comment-color: #8e908c;
+ --code-highlight-doc-comment-color: #4d4d4c;
+ --example-line-numbers-border-color: #c7c7c7;
+ --src-line-numbers-span-color: #c67e2d;
+ --src-line-number-highlighted-background-color: #fdffd3;
}
.slider {
@@ -48,65 +71,8 @@ input:focus + .slider {
*/
}
-.sidebar .current,
-.sidebar a:hover {
- background-color: #fff;
-}
-
-.line-numbers span { color: #c67e2d; }
-.line-numbers .line-highlighted {
- background-color: #FDFFD3 !important;
-}
-
-.search-results a:hover {
- background-color: #ddd;
-}
-
-.search-results a:focus {
- color: #000 !important;
- background-color: #ccc;
-}
-.search-results a:focus span { color: #000 !important; }
-a.result-trait:focus { background-color: #c7b6ff; }
-a.result-traitalias:focus { background-color: #c7b6ff; }
-a.result-mod:focus,
-a.result-externcrate:focus { background-color: #afc6e4; }
-a.result-enum:focus { background-color: #e7b1a0; }
-a.result-struct:focus { background-color: #e7b1a0; }
-a.result-union:focus { background-color: #e7b1a0; }
-a.result-fn:focus,
-a.result-method:focus,
-a.result-tymethod:focus { background-color: #c6afb3; }
-a.result-type:focus { background-color: #e7b1a0; }
-a.result-associatedtype:focus { background-color: #afc6e4; }
-a.result-foreigntype:focus { background-color: #e7b1a0; }
-a.result-attr:focus,
-a.result-derive:focus,
-a.result-macro:focus { background-color: #8ce488; }
-a.result-constant:focus,
-a.result-static:focus { background-color: #afc6e4; }
-a.result-primitive:focus { background-color: #e7b1a0; }
-a.result-keyword:focus { background-color: #afc6e4; }
-
.content .item-info::before { color: #ccc; }
-.sidebar a { color: #356da4; }
-.sidebar a.current.enum { color: #a63283; }
-.sidebar a.current.struct { color: #a63283; }
-.sidebar a.current.type { color: #a63283; }
-.sidebar a.current.foreigntype { color: #356da4; }
-.sidebar a.current.attr,
-.sidebar a.current.derive,
-.sidebar a.current.macro { color: #067901; }
-.sidebar a.current.union { color: #a63283; }
-.sidebar a.current.constant
-.sidebar a.current.static { color: #356da4; }
-.sidebar a.current.primitive { color: #a63283; }
-.sidebar a.current.trait { color: #6849c3; }
-.sidebar a.current.traitalias { color: #4b349e; }
-.sidebar a.current.fn { color: #a67736; }
-.sidebar a.current.keyword { color: #356da4; }
-
body.source .example-wrap pre.rust a {
background: #eee;
}
@@ -122,29 +88,6 @@ body.source .example-wrap pre.rust a {
filter: invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);
}
-.stab { background: #FFF5D6; border-color: #FFC600; }
-.stab.portability > code { background: none; }
-
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #8959A8; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
-pre.rust .number, pre.rust .string { color: #718C00; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute { color: #C82829; }
-pre.rust .comment { color: #8E908C; }
-pre.rust .doccomment { color: #4D4D4C; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #B76514; }
-pre.rust .question-mark {
- color: #ff9011;
-}
-
-.example-wrap > pre.line-number {
- border-color: #c7c7c7;
-}
-
a.test-arrow {
color: #f5f5f5;
background-color: rgba(78, 139, 202, 0.2);
@@ -196,8 +139,12 @@ kbd {
box-shadow: inset 0 -1px 0 #c6cbd1;
}
+#settings-menu > a, #help-button > a {
+ color: #000;
+}
+
#settings-menu > a:hover, #settings-menu > a:focus,
-#help-button > button:hover, #help-button > button:focus {
+#help-button > a:hover, #help-button > a:focus {
border-color: #717171;
}
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 6e9660ddc..33480fa41 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -55,7 +55,7 @@ function blurHandler(event, parentElem, hideCallback) {
function setMobileTopbar() {
// FIXME: It would be nicer to generate this text content directly in HTML,
// but with the current code it's hard to get the right information in the right place.
- const mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
+ const mobileLocationTitle = document.querySelector(".mobile-topbar h2");
const locationTitle = document.querySelector(".sidebar h2.location");
if (mobileLocationTitle && locationTitle) {
mobileLocationTitle.innerHTML = locationTitle.innerHTML;
@@ -192,6 +192,8 @@ function loadCss(cssFileName) {
}
(function() {
+ const isHelpPage = window.location.pathname.endsWith("/help.html");
+
function loadScript(url) {
const script = document.createElement("script");
script.src = url;
@@ -199,6 +201,9 @@ function loadCss(cssFileName) {
}
getSettingsButton().onclick = event => {
+ if (event.ctrlKey || event.altKey || event.metaKey) {
+ return;
+ }
addClass(getSettingsButton(), "rotate");
event.preventDefault();
// Sending request for the CSS and the JS files at the same time so it will
@@ -404,9 +409,12 @@ function loadCss(cssFileName) {
break;
case "+":
+ ev.preventDefault();
+ expandAllDocs();
+ break;
case "-":
ev.preventDefault();
- toggleAllDocs();
+ collapseAllDocs();
break;
case "?":
@@ -442,18 +450,15 @@ function loadCss(cssFileName) {
return;
}
- const div = document.createElement("div");
- div.className = "block " + shortty;
const h3 = document.createElement("h3");
h3.innerHTML = `<a href="index.html#${id}">${longty}</a>`;
- div.appendChild(h3);
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
- let klass = shortty;
let path;
if (shortty === "mod") {
path = name + "/index.html";
@@ -461,20 +466,19 @@ function loadCss(cssFileName) {
path = shortty + "." + name + ".html";
}
const current_page = document.location.href.split("/").pop();
- if (path === current_page) {
- klass += " current";
- }
const link = document.createElement("a");
link.href = path;
link.title = desc;
- link.className = klass;
+ if (path === current_page) {
+ link.className = "current";
+ }
link.textContent = name;
const li = document.createElement("li");
li.appendChild(link);
ul.appendChild(li);
}
- div.appendChild(ul);
- sidebar.appendChild(div);
+ sidebar.appendChild(h3);
+ sidebar.appendChild(ul);
}
if (sidebar) {
@@ -522,7 +526,7 @@ function loadCss(cssFileName) {
}
let currentNbImpls = implementors.getElementsByClassName("impl").length;
- const traitName = document.querySelector("h1.fqn > .in-band > .trait").textContent;
+ const traitName = document.querySelector("h1.fqn > .trait").textContent;
const baseIdName = "impl-" + traitName + "-";
const libs = Object.getOwnPropertyNames(imp);
// We don't want to include impls from this JS file, when the HTML already has them.
@@ -555,7 +559,6 @@ function loadCss(cssFileName) {
const code = document.createElement("h3");
code.innerHTML = struct[TEXT_IDX];
addClass(code, "code-header");
- addClass(code, "in-band");
onEachLazy(code.getElementsByTagName("a"), elem => {
const href = elem.getAttribute("href");
@@ -593,38 +596,52 @@ function loadCss(cssFileName) {
return;
}
// Draw a convenient sidebar of known crates if we have a listing
- const div = document.createElement("div");
- div.className = "block crate";
- div.innerHTML = "<h3>Crates</h3>";
+ const h3 = document.createElement("h3");
+ h3.innerHTML = "Crates";
const ul = document.createElement("ul");
- div.appendChild(ul);
+ ul.className = "block crate";
for (const crate of window.ALL_CRATES) {
- let klass = "crate";
- if (window.rootPath !== "./" && crate === window.currentCrate) {
- klass += " current";
- }
const link = document.createElement("a");
link.href = window.rootPath + crate + "/index.html";
- link.className = klass;
+ if (window.rootPath !== "./" && crate === window.currentCrate) {
+ link.className = "current";
+ }
link.textContent = crate;
const li = document.createElement("li");
li.appendChild(link);
ul.appendChild(li);
}
- sidebarElems.appendChild(div);
+ sidebarElems.appendChild(h3);
+ sidebarElems.appendChild(ul);
}
+ function expandAllDocs() {
+ const innerToggle = document.getElementById(toggleAllDocsId);
+ removeClass(innerToggle, "will-expand");
+ onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ if (!hasClass(e, "type-contents-toggle")) {
+ e.open = true;
+ }
+ });
+ innerToggle.title = "collapse all docs";
+ innerToggle.children[0].innerText = "\u2212"; // "\u2212" is "−" minus sign
+ }
- function labelForToggleButton(sectionIsCollapsed) {
- if (sectionIsCollapsed) {
- // button will expand the section
- return "+";
- }
- // button will collapse the section
- // note that this text is also set in the HTML template in ../render/mod.rs
- return "\u2212"; // "\u2212" is "−" minus sign
+ function collapseAllDocs() {
+ const innerToggle = document.getElementById(toggleAllDocsId);
+ addClass(innerToggle, "will-expand");
+ onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
+ if (e.parentNode.id !== "implementations-list" ||
+ (!hasClass(e, "implementors-toggle") &&
+ !hasClass(e, "type-contents-toggle"))
+ ) {
+ e.open = false;
+ }
+ });
+ innerToggle.title = "expand all docs";
+ innerToggle.children[0].innerText = "+";
}
function toggleAllDocs() {
@@ -632,29 +649,11 @@ function loadCss(cssFileName) {
if (!innerToggle) {
return;
}
- let sectionIsCollapsed = false;
if (hasClass(innerToggle, "will-expand")) {
- removeClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
- if (!hasClass(e, "type-contents-toggle")) {
- e.open = true;
- }
- });
- innerToggle.title = "collapse all docs";
+ expandAllDocs();
} else {
- addClass(innerToggle, "will-expand");
- onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
- if (e.parentNode.id !== "implementations-list" ||
- (!hasClass(e, "implementors-toggle") &&
- !hasClass(e, "type-contents-toggle"))
- ) {
- e.open = false;
- }
- });
- sectionIsCollapsed = true;
- innerToggle.title = "expand all docs";
+ collapseAllDocs();
}
- innerToggle.children[0].innerText = labelForToggleButton(sectionIsCollapsed);
}
(function() {
@@ -697,60 +696,95 @@ function loadCss(cssFileName) {
}
}());
+ window.rustdoc_add_line_numbers_to_examples = () => {
+ onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
+ const parent = x.parentNode;
+ const line_numbers = parent.querySelectorAll(".example-line-numbers");
+ if (line_numbers.length > 0) {
+ return;
+ }
+ const count = x.textContent.split("\n").length;
+ const elems = [];
+ for (let i = 0; i < count; ++i) {
+ elems.push(i + 1);
+ }
+ const node = document.createElement("pre");
+ addClass(node, "example-line-numbers");
+ node.innerHTML = elems.join("\n");
+ parent.insertBefore(node, x);
+ });
+ };
+
+ window.rustdoc_remove_line_numbers_from_examples = () => {
+ onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
+ const parent = x.parentNode;
+ const line_numbers = parent.querySelectorAll(".example-line-numbers");
+ for (const node of line_numbers) {
+ parent.removeChild(node);
+ }
+ });
+ };
+
(function() {
// To avoid checking on "rustdoc-line-numbers" value on every loop...
if (getSettingValue("line-numbers") === "true") {
- onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
- const count = x.textContent.split("\n").length;
- const elems = [];
- for (let i = 0; i < count; ++i) {
- elems.push(i + 1);
- }
- const node = document.createElement("pre");
- addClass(node, "line-number");
- node.innerHTML = elems.join("\n");
- x.parentNode.insertBefore(node, x);
- });
+ window.rustdoc_add_line_numbers_to_examples();
}
}());
let oldSidebarScrollPosition = null;
- function showSidebar() {
- if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
+ // Scroll locking used both here and in source-script.js
+
+ window.rustdocMobileScrollLock = function() {
+ const mobile_topbar = document.querySelector(".mobile-topbar");
+ if (window.innerWidth <= window.RUSTDOC_MOBILE_BREAKPOINT) {
// This is to keep the scroll position on mobile.
oldSidebarScrollPosition = window.scrollY;
document.body.style.width = `${document.body.offsetWidth}px`;
document.body.style.position = "fixed";
document.body.style.top = `-${oldSidebarScrollPosition}px`;
- document.querySelector(".mobile-topbar").style.top = `${oldSidebarScrollPosition}px`;
- document.querySelector(".mobile-topbar").style.position = "relative";
+ if (mobile_topbar) {
+ mobile_topbar.style.top = `${oldSidebarScrollPosition}px`;
+ mobile_topbar.style.position = "relative";
+ }
} else {
oldSidebarScrollPosition = null;
}
- const sidebar = document.getElementsByClassName("sidebar")[0];
- addClass(sidebar, "shown");
- }
+ };
- function hideSidebar() {
+ window.rustdocMobileScrollUnlock = function() {
+ const mobile_topbar = document.querySelector(".mobile-topbar");
if (oldSidebarScrollPosition !== null) {
// This is to keep the scroll position on mobile.
document.body.style.width = "";
document.body.style.position = "";
document.body.style.top = "";
- document.querySelector(".mobile-topbar").style.top = "";
- document.querySelector(".mobile-topbar").style.position = "";
+ if (mobile_topbar) {
+ mobile_topbar.style.top = "";
+ mobile_topbar.style.position = "";
+ }
// The scroll position is lost when resetting the style, hence why we store it in
// `oldSidebarScrollPosition`.
window.scrollTo(0, oldSidebarScrollPosition);
oldSidebarScrollPosition = null;
}
+ };
+
+ function showSidebar() {
+ window.rustdocMobileScrollLock();
+ const sidebar = document.getElementsByClassName("sidebar")[0];
+ addClass(sidebar, "shown");
+ }
+
+ function hideSidebar() {
+ window.rustdocMobileScrollUnlock();
const sidebar = document.getElementsByClassName("sidebar")[0];
removeClass(sidebar, "shown");
}
window.addEventListener("resize", () => {
- if (window.innerWidth >= window.RUSTDOC_MOBILE_BREAKPOINT &&
+ if (window.innerWidth > window.RUSTDOC_MOBILE_BREAKPOINT &&
oldSidebarScrollPosition !== null) {
// If the user opens the sidebar in "mobile" mode, and then grows the browser window,
// we need to switch away from mobile mode and make the main content area scrollable.
@@ -859,7 +893,10 @@ function loadCss(cssFileName) {
rustdoc_version.appendChild(rustdoc_version_code);
const container = document.createElement("div");
- container.className = "popover";
+ if (!isHelpPage) {
+ container.className = "popover";
+ }
+ container.id = "help";
container.style.display = "none";
const side_by_side = document.createElement("div");
@@ -871,15 +908,22 @@ function loadCss(cssFileName) {
container.appendChild(side_by_side);
container.appendChild(rustdoc_version);
- const help_button = getHelpButton();
- help_button.appendChild(container);
-
- container.onblur = helpBlurHandler;
- container.onclick = event => {
- event.preventDefault();
- };
- help_button.onblur = helpBlurHandler;
- help_button.children[0].onblur = helpBlurHandler;
+ if (isHelpPage) {
+ const help_section = document.createElement("section");
+ help_section.appendChild(container);
+ document.getElementById("main-content").appendChild(help_section);
+ container.style.display = "block";
+ } else {
+ const help_button = getHelpButton();
+ help_button.appendChild(container);
+
+ container.onblur = helpBlurHandler;
+ container.onclick = event => {
+ event.preventDefault();
+ };
+ help_button.onblur = helpBlurHandler;
+ help_button.children[0].onblur = helpBlurHandler;
+ }
return container;
}
@@ -888,7 +932,7 @@ function loadCss(cssFileName) {
* Hide all the popover menus.
*/
window.hidePopoverMenus = function() {
- onEachLazy(document.querySelectorAll(".search-container .popover"), elem => {
+ onEachLazy(document.querySelectorAll(".search-form .popover"), elem => {
elem.style.display = "none";
});
};
@@ -920,19 +964,43 @@ function loadCss(cssFileName) {
}
}
- document.querySelector(`#${HELP_BUTTON_ID} > button`).addEventListener("click", event => {
- const target = event.target;
- if (target.tagName !== "BUTTON" || target.parentElement.id !== HELP_BUTTON_ID) {
- return;
- }
- const menu = getHelpMenu(true);
- const shouldShowHelp = menu.style.display === "none";
- if (shouldShowHelp) {
- showHelp();
- } else {
- window.hidePopoverMenus();
- }
- });
+ if (isHelpPage) {
+ showHelp();
+ document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => {
+ // Already on the help page, make help button a no-op.
+ const target = event.target;
+ if (target.tagName !== "A" ||
+ target.parentElement.id !== HELP_BUTTON_ID ||
+ event.ctrlKey ||
+ event.altKey ||
+ event.metaKey) {
+ return;
+ }
+ event.preventDefault();
+ });
+ } else {
+ document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click", event => {
+ // By default, have help button open docs in a popover.
+ // If user clicks with a moderator, though, use default browser behavior,
+ // probably opening in a new window or tab.
+ const target = event.target;
+ if (target.tagName !== "A" ||
+ target.parentElement.id !== HELP_BUTTON_ID ||
+ event.ctrlKey ||
+ event.altKey ||
+ event.metaKey) {
+ return;
+ }
+ event.preventDefault();
+ const menu = getHelpMenu(true);
+ const shouldShowHelp = menu.style.display === "none";
+ if (shouldShowHelp) {
+ showHelp();
+ } else {
+ window.hidePopoverMenus();
+ }
+ });
+ }
setMobileTopbar();
addSidebarItems();
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index fd7a14497..d0fd115fd 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -8,7 +8,7 @@
// Scroll code block to the given code location
function scrollToLoc(elt, loc) {
- const lines = elt.querySelector(".line-numbers");
+ const lines = elt.querySelector(".src-line-numbers");
let scrollOffset;
// If the block is greater than the size of the viewer,
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 797b931af..5e1c7e6f0 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -19,6 +19,13 @@
updateSystemTheme();
updateLightAndDark();
break;
+ case "line-numbers":
+ if (value === true) {
+ window.rustdoc_add_line_numbers_to_examples();
+ } else {
+ window.rustdoc_remove_line_numbers_from_examples();
+ }
+ break;
}
}
@@ -209,7 +216,9 @@
const innerHTML = `<div class="settings">${buildSettingsPageSections(settings)}</div>`;
const el = document.createElement(elementKind);
el.id = "settings";
- el.className = "popover";
+ if (!isSettingsPage) {
+ el.className = "popover";
+ }
el.innerHTML = innerHTML;
if (isSettingsPage) {
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 06d15d9e5..0b9368dd8 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -10,7 +10,6 @@
(function() {
const rootPath = document.getElementById("rustdoc-vars").attributes["data-root-path"].value;
-let oldScrollPosition = null;
const NAME_OFFSET = 0;
const DIRS_OFFSET = 1;
@@ -70,44 +69,18 @@ function createDirEntry(elem, parent, fullPath, hasFoundFile) {
function toggleSidebar() {
const child = this.parentNode.children[0];
if (child.innerText === ">") {
- if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT) {
- // This is to keep the scroll position on mobile.
- oldScrollPosition = window.scrollY;
- document.body.style.position = "fixed";
- document.body.style.top = `-${oldScrollPosition}px`;
- } else {
- oldScrollPosition = null;
- }
+ window.rustdocMobileScrollLock();
addClass(document.documentElement, "source-sidebar-expanded");
child.innerText = "<";
updateLocalStorage("source-sidebar-show", "true");
} else {
- if (window.innerWidth < window.RUSTDOC_MOBILE_BREAKPOINT && oldScrollPosition !== null) {
- // This is to keep the scroll position on mobile.
- document.body.style.position = "";
- document.body.style.top = "";
- // The scroll position is lost when resetting the style, hence why we store it in
- // `oldScrollPosition`.
- window.scrollTo(0, oldScrollPosition);
- oldScrollPosition = null;
- }
+ window.rustdocMobileScrollUnlock();
removeClass(document.documentElement, "source-sidebar-expanded");
child.innerText = ">";
updateLocalStorage("source-sidebar-show", "false");
}
}
-window.addEventListener("resize", () => {
- if (window.innerWidth >= window.RUSTDOC_MOBILE_BREAKPOINT && oldScrollPosition !== null) {
- // If the user opens the sidebar in "mobile" mode, and then grows the browser window,
- // we need to switch away from mobile mode and make the main content area scrollable.
- document.body.style.position = "";
- document.body.style.top = "";
- window.scrollTo(0, oldScrollPosition);
- oldScrollPosition = null;
- }
-});
-
function createSidebarToggle() {
const sidebarToggle = document.createElement("div");
sidebarToggle.id = "sidebar-toggle";
@@ -125,7 +98,7 @@ function createSidebarToggle() {
return sidebarToggle;
}
-// This function is called from "source-files.js", generated in `html/render/mod.rs`.
+// This function is called from "source-files.js", generated in `html/render/write_shared.rs`.
// eslint-disable-next-line no-unused-vars
function createSourceSidebar() {
const container = document.querySelector("nav.sidebar");
@@ -183,7 +156,7 @@ function highlightSourceLines(match) {
if (x) {
x.scrollIntoView();
}
- onEachLazy(document.getElementsByClassName("line-numbers"), e => {
+ onEachLazy(document.getElementsByClassName("src-line-numbers"), e => {
onEachLazy(e.getElementsByTagName("span"), i_e => {
removeClass(i_e, "line-highlighted");
});
@@ -245,7 +218,7 @@ window.addEventListener("hashchange", () => {
}
});
-onEachLazy(document.getElementsByClassName("line-numbers"), el => {
+onEachLazy(document.getElementsByClassName("src-line-numbers"), el => {
el.addEventListener("click", handleSourceHighlight);
});
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 0c5389d45..b462a2c50 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -10,9 +10,9 @@ window.currentTheme = document.getElementById("themeStyle");
window.mainTheme = document.getElementById("mainThemeStyle");
// WARNING: RUSTDOC_MOBILE_BREAKPOINT MEDIA QUERY
-// If you update this line, then you also need to update the two media queries with the same
+// If you update this line, then you also need to update the media query with the same
// warning in rustdoc.css
-window.RUSTDOC_MOBILE_BREAKPOINT = 701;
+window.RUSTDOC_MOBILE_BREAKPOINT = 700;
const settingsDataset = (function() {
const settingsElement = document.getElementById("default-settings");
diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html
index 7caffeae3..c32386916 100644
--- a/src/librustdoc/html/templates/page.html
+++ b/src/librustdoc/html/templates/page.html
@@ -73,6 +73,7 @@
</div> {#- -#}
<![endif]--> {#- -#}
{{- layout.external_html.before_content|safe -}}
+ {%- if page.css_class != "source" -%}
<nav class="mobile-topbar"> {#- -#}
<button class="sidebar-menu-toggle">&#9776;</button> {#- -#}
<a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
@@ -84,9 +85,11 @@
{%- endif -%}
</div> {#- -#}
</a> {#- -#}
- <h2 class="location"></h2> {#- -#}
+ <h2></h2> {#- -#}
</nav> {#- -#}
+ {%- endif -%}
<nav class="sidebar"> {#- -#}
+ {%- if page.css_class != "source" -%}
<a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
<div class="logo-container"> {#- -#}
{%- if !layout.logo.is_empty() %}
@@ -96,11 +99,13 @@
{%- endif -%}
</div> {#- -#}
</a> {#- -#}
+ {%- endif -%}
{{- sidebar|safe -}}
</nav> {#- -#}
<main> {#- -#}
<div class="width-limiter"> {#- -#}
- <div class="sub-container"> {#- -#}
+ <nav class="sub"> {#- -#}
+ {%- if page.css_class == "source" -%}
<a class="sub-logo-container" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
{%- if !layout.logo.is_empty() %}
<img src="{{layout.logo}}" alt="logo"> {#- -#}
@@ -108,30 +113,27 @@
<img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
{%- endif -%}
</a> {#- -#}
- <nav class="sub"> {#- -#}
- <form class="search-form"> {#- -#}
- <div class="search-container"> {#- -#}
- <span></span> {#- This empty span is a hacky fix for Safari - See #93184 -#}
- <input {# -#}
- class="search-input" {# -#}
- name="search" {# -#}
- autocomplete="off" {# -#}
- spellcheck="false" {# -#}
- placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
- type="search"> {#- -#}
- <div id="help-button" title="help" tabindex="-1"> {#- -#}
- <button type="button">?</button> {#- -#}
- </div> {#- -#}
- <div id="settings-menu" tabindex="-1"> {#- -#}
- <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
- <img width="22" height="22" alt="Change settings" {# -#}
- src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
- </a> {#- -#}
- </div> {#- -#}
- </div> {#- -#}
- </form> {#- -#}
- </nav> {#- -#}
- </div> {#- -#}
+ {%- endif -%}
+ <form class="search-form"> {#- -#}
+ <span></span> {#- This empty span is a hacky fix for Safari - See #93184 -#}
+ <input {# -#}
+ class="search-input" {# -#}
+ name="search" {# -#}
+ autocomplete="off" {# -#}
+ spellcheck="false" {# -#}
+ placeholder="Click or press ‘S’ to search, ‘?’ for more options…" {# -#}
+ type="search"> {#- -#}
+ <div id="help-button" title="help" tabindex="-1"> {#- -#}
+ <a href="{{page.root_path|safe}}help.html">?</a> {#- -#}
+ </div> {#- -#}
+ <div id="settings-menu" tabindex="-1"> {#- -#}
+ <a href="{{page.root_path|safe}}settings.html" title="settings"> {#- -#}
+ <img width="22" height="22" alt="Change settings" {# -#}
+ src="{{static_root_path|safe}}wheel{{page.resource_suffix}}.svg"> {#- -#}
+ </a> {#- -#}
+ </div> {#- -#}
+ </form> {#- -#}
+ </nav> {#- -#}
<section id="main-content" class="content">{{- content|safe -}}</section> {#- -#}
</div> {#- -#}
</main> {#- -#}
diff --git a/src/librustdoc/html/templates/print_item.html b/src/librustdoc/html/templates/print_item.html
index c755157d2..b6ce3ea3d 100644
--- a/src/librustdoc/html/templates/print_item.html
+++ b/src/librustdoc/html/templates/print_item.html
@@ -1,18 +1,16 @@
<div class="main-heading"> {#- -#}
<h1 class="fqn"> {#- -#}
- <span class="in-band"> {#- -#}
- {{-typ-}}
- {#- The breadcrumbs of the item path, like std::string -#}
- {%- for component in path_components -%}
- <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"> {#- -#}
- <img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
- width="19" height="18" {# -#}
- alt="Copy item path"> {#- -#}
- </button> {#- -#}
- </span> {#- -#}
+ {{-typ-}}
+ {#- The breadcrumbs of the item path, like std::string -#}
+ {%- for component in path_components -%}
+ <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"> {#- -#}
+ <img src="{{static_root_path|safe}}clipboard{{page.resource_suffix}}.svg" {# -#}
+ width="19" height="18" {# -#}
+ alt="Copy item path"> {#- -#}
+ </button> {#- -#}
</h1> {#- -#}
<span class="out-of-band"> {#- -#}
{% if !stability_since_raw.is_empty() %}
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 49a31f5f1..cdf59cdd3 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -272,7 +272,12 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
MacroItem(m) => ItemEnum::Macro(m.source),
ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
- PrimitiveItem(p) => ItemEnum::PrimitiveType(p.as_sym().to_string()),
+ PrimitiveItem(p) => {
+ ItemEnum::Primitive(Primitive {
+ name: p.as_sym().to_string(),
+ impls: Vec::new(), // Added in JsonRenderer::item
+ })
+ }
TyAssocConstItem(ty) => ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None },
AssocConstItem(ty, default) => {
ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) }
@@ -427,8 +432,9 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
lifetime: convert_lifetime(lifetime),
bounds: bounds.into_tcx(tcx),
},
- EqPredicate { lhs, rhs } => {
- WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
+ // FIXME(fmease): Convert bound parameters as well.
+ EqPredicate { lhs, rhs, bound_params: _ } => {
+ WherePredicate::EqPredicate { lhs: (*lhs).into_tcx(tcx), rhs: (*rhs).into_tcx(tcx) }
}
}
}
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 5e8f5f6fe..d13efe6c1 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -108,7 +108,6 @@ impl<'tcx> JsonRenderer<'tcx> {
.filter_map(|(&id, trait_item)| {
// only need to synthesize items for external traits
if !id.is_local() {
- let trait_item = &trait_item.trait_;
for item in &trait_item.items {
trace!("Adding subitem to {id:?}: {:?}", item.item_id);
self.item(item.clone()).unwrap();
@@ -219,12 +218,15 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
u.impls = self.get_impls(item_id.expect_def_id());
false
}
+ types::ItemEnum::Primitive(ref mut p) => {
+ p.impls = self.get_impls(item_id.expect_def_id());
+ false
+ }
types::ItemEnum::Method(_)
| types::ItemEnum::Module(_)
| types::ItemEnum::AssocConst { .. }
- | types::ItemEnum::AssocType { .. }
- | types::ItemEnum::PrimitiveType(_) => true,
+ | types::ItemEnum::AssocType { .. } => true,
types::ItemEnum::ExternCrate { .. }
| types::ItemEnum::Import(_)
| types::ItemEnum::StructField(_)
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 14d695582..4cf9435d9 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -9,14 +9,12 @@
#![feature(control_flow_enum)]
#![feature(drain_filter)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(test)]
#![feature(never_type)]
#![feature(once_cell)]
#![feature(type_ascription)]
#![feature(iter_intersperse)]
#![feature(type_alias_impl_trait)]
-#![cfg_attr(bootstrap, feature(generic_associated_types))]
#![recursion_limit = "256"]
#![warn(rustc::internal)]
#![allow(clippy::collapsible_if, clippy::collapsible_else_if)]
@@ -43,6 +41,7 @@ extern crate rustc_errors;
extern crate rustc_expand;
extern crate rustc_feature;
extern crate rustc_hir;
+extern crate rustc_hir_analysis;
extern crate rustc_hir_pretty;
extern crate rustc_index;
extern crate rustc_infer;
@@ -61,7 +60,6 @@ extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
extern crate rustc_trait_selection;
-extern crate rustc_typeck;
extern crate test;
// See docs in https://github.com/rust-lang/rust/blob/master/compiler/rustc/src/main.rs
@@ -156,7 +154,6 @@ pub fn main() {
}
}
- rustc_driver::set_sigpipe_handler();
rustc_driver::install_ice_hook();
// When using CI artifacts (with `download_stage1 = true`), tracing is unconditionally built
@@ -461,7 +458,7 @@ fn opts() -> Vec<RustcOptGroup> {
"human|json|short",
)
}),
- unstable("diagnostic-width", |o| {
+ stable("diagnostic-width", |o| {
o.optopt(
"",
"diagnostic-width",
@@ -676,39 +673,6 @@ fn usage(argv0: &str) {
/// A result type used by several functions under `main()`.
type MainResult = Result<(), ErrorGuaranteed>;
-fn main_args(at_args: &[String]) -> MainResult {
- let args = rustc_driver::args::arg_expand_all(at_args);
-
- let mut options = getopts::Options::new();
- for option in opts() {
- (option.apply)(&mut options);
- }
- let matches = match options.parse(&args[1..]) {
- Ok(m) => m,
- Err(err) => {
- early_error(ErrorOutputType::default(), &err.to_string());
- }
- };
-
- // Note that we discard any distinction between different non-zero exit
- // codes from `from_matches` here.
- let options = match config::Options::from_matches(&matches, args) {
- Ok(opts) => opts,
- Err(code) => {
- return if code == 0 {
- Ok(())
- } else {
- Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
- };
- }
- };
- rustc_interface::util::run_in_thread_pool_with_globals(
- options.edition,
- 1, // this runs single-threaded, even in a parallel compiler
- move || main_options(options),
- )
-}
-
fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
match res {
Ok(()) => Ok(()),
@@ -739,7 +703,33 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
}
}
-fn main_options(options: config::Options) -> MainResult {
+fn main_args(at_args: &[String]) -> MainResult {
+ let args = rustc_driver::args::arg_expand_all(at_args);
+
+ let mut options = getopts::Options::new();
+ for option in opts() {
+ (option.apply)(&mut options);
+ }
+ let matches = match options.parse(&args[1..]) {
+ Ok(m) => m,
+ Err(err) => {
+ early_error(ErrorOutputType::default(), &err.to_string());
+ }
+ };
+
+ // Note that we discard any distinction between different non-zero exit
+ // codes from `from_matches` here.
+ let (options, render_options) = match config::Options::from_matches(&matches, args) {
+ Ok(opts) => opts,
+ Err(code) => {
+ return if code == 0 {
+ Ok(())
+ } else {
+ Err(ErrorGuaranteed::unchecked_claim_error_was_emitted())
+ };
+ }
+ };
+
let diag = core::new_handler(
options.error_format,
None,
@@ -751,9 +741,18 @@ fn main_options(options: config::Options) -> MainResult {
(true, true) => return wrap_return(&diag, markdown::test(options)),
(true, false) => return doctest::run(options),
(false, true) => {
+ let input = options.input.clone();
+ let edition = options.edition;
+ let config = core::create_config(options);
+
+ // `markdown::render` can invoke `doctest::make_test`, which
+ // requires session globals and a thread pool, so we use
+ // `run_compiler`.
return wrap_return(
&diag,
- markdown::render(&options.input, options.render_options, options.edition),
+ interface::run_compiler(config, |_compiler| {
+ markdown::render(&input, render_options, edition)
+ }),
);
}
(false, false) => {}
@@ -774,14 +773,12 @@ fn main_options(options: config::Options) -> MainResult {
let crate_version = options.crate_version.clone();
let output_format = options.output_format;
- // FIXME: fix this clone (especially render_options)
let externs = options.externs.clone();
- let render_options = options.render_options.clone();
let scrape_examples_options = options.scrape_examples_options.clone();
- let document_private = options.render_options.document_private;
+
let config = core::create_config(options);
- interface::create_compiler_and_run(config, |compiler| {
+ interface::run_compiler(config, |compiler| {
let sess = compiler.session();
if sess.opts.describe_lints {
@@ -813,7 +810,7 @@ fn main_options(options: config::Options) -> MainResult {
sess,
krate,
externs,
- document_private,
+ render_options.document_private,
)
});
(resolver.clone(), resolver_caches)
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index e76c19a61..3aad97bc2 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -148,7 +148,7 @@ declare_rustdoc_lint! {
///
/// [rustdoc book]: ../../../rustdoc/lints.html#invalid_html_tags
INVALID_HTML_TAGS,
- Allow,
+ Warn,
"detects invalid HTML tags in doc comments"
}
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 0b557ef24..044e05144 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -5,7 +5,6 @@ use std::path::Path;
use rustc_span::edition::Edition;
use rustc_span::source_map::DUMMY_SP;
-use rustc_span::Symbol;
use crate::config::{Options, RenderOptions};
use crate::doctest::{Collector, GlobalTestOptions};
@@ -36,6 +35,8 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) {
/// Render `input` (e.g., "foo.md") into an HTML file in `output`
/// (e.g., output = "bar" => "bar/foo.html").
+///
+/// Requires session globals to be available, for symbol interning.
pub(crate) fn render<P: AsRef<Path>>(
input: P,
options: RenderOptions,
@@ -133,7 +134,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
let mut opts = GlobalTestOptions::default();
opts.no_crate_inject = true;
let mut collector = Collector::new(
- Symbol::intern(&options.input.display().to_string()),
+ options.input.display().to_string(),
options.clone(),
true,
opts,
@@ -142,7 +143,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> {
options.enable_per_target_ignores,
);
collector.set_position(DUMMY_SP);
- let codes = ErrorCodes::from(options.render_options.unstable_features.is_nightly_build());
+ let codes = ErrorCodes::from(options.unstable_features.is_nightly_build());
find_testable_code(&input_str, &mut collector, codes, options.enable_per_target_ignores, None);
diff --git a/src/librustdoc/passes/bare_urls.rs b/src/librustdoc/passes/bare_urls.rs
index 392e26ea6..7ff3ccef9 100644
--- a/src/librustdoc/passes/bare_urls.rs
+++ b/src/librustdoc/passes/bare_urls.rs
@@ -71,16 +71,14 @@ impl<'a, 'tcx> DocVisitor for BareUrlsLinter<'a, 'tcx> {
let report_diag = |cx: &DocContext<'_>, msg: &str, url: &str, range: Range<usize>| {
let sp = super::source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs)
.unwrap_or_else(|| item.attr_span(cx.tcx));
- cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, |lint| {
- lint.build(msg)
- .note("bare URLs are not automatically turned into clickable links")
+ cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| {
+ lint.note("bare URLs are not automatically turned into clickable links")
.span_suggestion(
sp,
"use an automatic link instead",
format!("<{}>", url),
Applicability::MachineApplicable,
)
- .emit();
});
};
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
index 381ac7a5d..2e651b538 100644
--- a/src/librustdoc/passes/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -1,8 +1,9 @@
//! Validates syntax inside Rust code blocks (\`\`\`rust).
use rustc_data_structures::sync::{Lock, Lrc};
use rustc_errors::{
- emitter::Emitter, translation::Translate, Applicability, Diagnostic, Handler,
- LazyFallbackBundle, LintDiagnosticBuilder,
+ emitter::Emitter,
+ translation::{to_fluent_args, Translate},
+ Applicability, Diagnostic, Handler, LazyFallbackBundle,
};
use rustc_parse::parse_stream_from_source_str;
use rustc_session::parse::ParseSess;
@@ -97,48 +98,10 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
None => (item.attr_span(self.cx.tcx), false),
};
- // lambda that will use the lint to start a new diagnostic and add
- // a suggestion to it when needed.
- let diag_builder = |lint: LintDiagnosticBuilder<'_, ()>| {
- let explanation = if is_ignore {
- "`ignore` code blocks require valid Rust code for syntax highlighting; \
- mark blocks that do not contain Rust code as text"
- } else {
- "mark blocks that do not contain Rust code as text"
- };
- let msg = if buffer.has_errors {
- "could not parse code block as Rust code"
- } else {
- "Rust code block is empty"
- };
- let mut diag = lint.build(msg);
-
- if precise_span {
- if is_ignore {
- // giving an accurate suggestion is hard because `ignore` might not have come first in the list.
- // just give a `help` instead.
- diag.span_help(
- sp.from_inner(InnerSpan::new(0, 3)),
- &format!("{}: ```text", explanation),
- );
- } else if empty_block {
- diag.span_suggestion(
- sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
- explanation,
- "text",
- Applicability::MachineApplicable,
- );
- }
- } else if empty_block || is_ignore {
- diag.help(&format!("{}: ```text", explanation));
- }
-
- // FIXME(#67563): Provide more context for these errors by displaying the spans inline.
- for message in buffer.messages.iter() {
- diag.note(message);
- }
-
- diag.emit();
+ let msg = if buffer.has_errors {
+ "could not parse code block as Rust code"
+ } else {
+ "Rust code block is empty"
};
// Finally build and emit the completed diagnostic.
@@ -148,7 +111,42 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
crate::lint::INVALID_RUST_CODEBLOCKS,
hir_id,
sp,
- diag_builder,
+ msg,
+ |lint| {
+ let explanation = if is_ignore {
+ "`ignore` code blocks require valid Rust code for syntax highlighting; \
+ mark blocks that do not contain Rust code as text"
+ } else {
+ "mark blocks that do not contain Rust code as text"
+ };
+
+ if precise_span {
+ if is_ignore {
+ // giving an accurate suggestion is hard because `ignore` might not have come first in the list.
+ // just give a `help` instead.
+ lint.span_help(
+ sp.from_inner(InnerSpan::new(0, 3)),
+ &format!("{}: ```text", explanation),
+ );
+ } else if empty_block {
+ lint.span_suggestion(
+ sp.from_inner(InnerSpan::new(0, 3)).shrink_to_hi(),
+ explanation,
+ "text",
+ Applicability::MachineApplicable,
+ );
+ }
+ } else if empty_block || is_ignore {
+ lint.help(&format!("{}: ```text", explanation));
+ }
+
+ // FIXME(#67563): Provide more context for these errors by displaying the spans inline.
+ for message in buffer.messages.iter() {
+ lint.note(message);
+ }
+
+ lint
+ },
);
}
}
@@ -195,8 +193,11 @@ impl Translate for BufferEmitter {
impl Emitter for BufferEmitter {
fn emit_diagnostic(&mut self, diag: &Diagnostic) {
let mut buffer = self.buffer.borrow_mut();
- // FIXME(davidtwco): need to support translation here eventually
- buffer.messages.push(format!("error from rustc: {}", diag.message[0].0.expect_str()));
+
+ let fluent_args = to_fluent_args(diag.args());
+ let translated_main_message = self.translate_message(&diag.message[0].0, &fluent_args);
+
+ buffer.messages.push(format!("error from rustc: {}", translated_main_message));
if diag.is_error() {
buffer.has_errors = true;
}
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index 55d5f303d..7740c6d5b 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -56,7 +56,7 @@ impl crate::doctest::Tester for Tests {
}
pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
- if !cx.cache.access_levels.is_public(item.item_id.expect_def_id())
+ if !cx.cache.effective_visibilities.is_directly_public(item.item_id.expect_def_id())
|| matches!(
*item.kind,
clean::StructFieldItem(_)
@@ -125,21 +125,19 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
crate::lint::MISSING_DOC_CODE_EXAMPLES,
hir_id,
sp,
- |lint| {
- lint.build("missing code example in this documentation").emit();
- },
+ "missing code example in this documentation",
+ |lint| lint,
);
}
} else if tests.found_tests > 0
- && !cx.cache.access_levels.is_exported(item.item_id.expect_def_id())
+ && !cx.cache.effective_visibilities.is_exported(item.item_id.expect_def_id())
{
cx.tcx.struct_span_lint_hir(
crate::lint::PRIVATE_DOC_TESTS,
hir_id,
item.attr_span(cx.tcx),
- |lint| {
- lint.build("documentation test in private item").emit();
- },
+ "documentation test in private item",
+ |lint| lint,
);
}
}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index b2a41bfa4..8aa0abd36 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -80,10 +80,10 @@ impl Res {
}
}
- fn def_id(self, tcx: TyCtxt<'_>) -> DefId {
+ fn def_id(self, tcx: TyCtxt<'_>) -> Option<DefId> {
match self {
- Res::Def(_, id) => id,
- Res::Primitive(prim) => *PrimitiveType::primitive_locations(tcx).get(&prim).unwrap(),
+ Res::Def(_, id) => Some(id),
+ Res::Primitive(prim) => PrimitiveType::primitive_locations(tcx).get(&prim).copied(),
}
}
@@ -1127,10 +1127,10 @@ impl LinkCollector<'_, '_> {
}
}
- Some(ItemLink {
+ res.def_id(self.cx.tcx).map(|page_id| ItemLink {
link: ori_link.link.clone(),
link_text: link_text.clone(),
- page_id: res.def_id(self.cx.tcx),
+ page_id,
fragment,
})
}
@@ -1202,8 +1202,8 @@ impl LinkCollector<'_, '_> {
item.item_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
})
{
- if self.cx.tcx.privacy_access_levels(()).is_exported(src_id)
- && !self.cx.tcx.privacy_access_levels(()).is_exported(dst_id)
+ if self.cx.tcx.effective_visibilities(()).is_exported(src_id)
+ && !self.cx.tcx.effective_visibilities(()).is_exported(dst_id)
{
privacy_error(self.cx, diag_info, path_str);
}
@@ -1609,9 +1609,7 @@ fn report_diagnostic(
let sp = item.attr_span(tcx);
- tcx.struct_span_lint_hir(lint, hir_id, sp, |lint| {
- let mut diag = lint.build(msg);
-
+ tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| {
let span =
super::source_span_for_markdown_range(tcx, dox, link_range, &item.attrs).map(|sp| {
if dox.as_bytes().get(link_range.start) == Some(&b'`')
@@ -1624,7 +1622,7 @@ fn report_diagnostic(
});
if let Some(sp) = span {
- diag.set_span(sp);
+ lint.set_span(sp);
} else {
// blah blah blah\nblah\nblah [blah] blah blah\nblah blah
// ^ ~~~~
@@ -1634,7 +1632,7 @@ fn report_diagnostic(
let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
// Print the line containing the `link_range` and manually mark it with '^'s.
- diag.note(&format!(
+ lint.note(&format!(
"the link appears in this line:\n\n{line}\n\
{indicator: <before$}{indicator:^<found$}",
line = line,
@@ -1644,9 +1642,9 @@ fn report_diagnostic(
));
}
- decorate(&mut diag, span);
+ decorate(lint, span);
- diag.emit();
+ lint
});
}
@@ -1895,7 +1893,7 @@ fn disambiguator_error(
diag_info.link_range = disambiguator_range;
report_diagnostic(cx.tcx, BROKEN_INTRA_DOC_LINKS, msg, &diag_info, |diag, _sp| {
let msg = format!(
- "see {}/rustdoc/write-documentation/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
+ "see {}/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators",
crate::DOC_RUST_LANG_ORG_CHANNEL
);
diag.note(&msg);
diff --git a/src/librustdoc/passes/collect_intra_doc_links/early.rs b/src/librustdoc/passes/collect_intra_doc_links/early.rs
index 38cfd7a27..1b373cfe5 100644
--- a/src/librustdoc/passes/collect_intra_doc_links/early.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links/early.rs
@@ -37,7 +37,6 @@ pub(crate) fn early_resolve_intra_doc_links(
markdown_links: Default::default(),
doc_link_resolutions: Default::default(),
traits_in_scope: Default::default(),
- all_traits: Default::default(),
all_trait_impls: Default::default(),
all_macro_rules: Default::default(),
document_private_items,
@@ -48,7 +47,6 @@ pub(crate) fn early_resolve_intra_doc_links(
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);
- link_resolver.process_extern_impls();
// 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.
@@ -58,11 +56,12 @@ pub(crate) fn early_resolve_intra_doc_links(
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_traits: Some(link_resolver.all_traits),
all_trait_impls: Some(link_resolver.all_trait_impls),
all_macro_rules: link_resolver.all_macro_rules,
}
@@ -80,7 +79,6 @@ struct EarlyDocLinkResolver<'r, 'ra> {
markdown_links: FxHashMap<String, Vec<PreprocessedMarkdownLink>>,
doc_link_resolutions: FxHashMap<(Symbol, Namespace, DefId), Option<Res<ast::NodeId>>>,
traits_in_scope: DefIdMap<Vec<TraitCandidate>>,
- all_traits: Vec<DefId>,
all_trait_impls: Vec<DefId>,
all_macro_rules: FxHashMap<Symbol, Res<ast::NodeId>>,
document_private_items: bool,
@@ -121,8 +119,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
loop {
let crates = Vec::from_iter(self.resolver.cstore().crates_untracked());
for &cnum in &crates[start_cnum..] {
- let all_traits =
- Vec::from_iter(self.resolver.cstore().traits_in_crate_untracked(cnum));
let all_trait_impls =
Vec::from_iter(self.resolver.cstore().trait_impls_in_crate_untracked(cnum));
let all_inherent_impls =
@@ -131,20 +127,18 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
self.resolver.cstore().incoherent_impls_in_crate_untracked(cnum),
);
- // Querying traits in scope is expensive so we try to prune the impl and traits lists
- // using privacy, private traits and impls from other crates are never documented in
+ // 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 &def_id in &all_traits {
- if self.resolver.cstore().visibility_untracked(def_id).is_public() {
- self.resolve_doc_links_extern_impl(def_id, false);
- }
- }
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);
}
}
@@ -157,7 +151,6 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
self.resolve_doc_links_extern_impl(impl_def_id, true);
}
- self.all_traits.extend(all_traits);
self.all_trait_impls
.extend(all_trait_impls.into_iter().map(|(_, def_id, _)| def_id));
}
@@ -306,15 +299,20 @@ impl<'ra> EarlyDocLinkResolver<'_, 'ra> {
{
if let Some(def_id) = child.res.opt_def_id() && !def_id.is_local() {
let scope_id = match child.res {
- Res::Def(DefKind::Variant, ..) => self.resolver.parent(def_id),
+ 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
}
- // `DefKind::Trait`s are processed in `process_extern_impls`.
- if let Res::Def(DefKind::Mod | DefKind::Enum, ..) = child.res {
+ 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, _) =
@@ -356,10 +354,14 @@ impl Visitor<'_> for EarlyDocLinkResolver<'_, '_> {
self.parent_scope.module = old_module;
} else {
match &item.kind {
- ItemKind::Trait(..) => {
- self.all_traits.push(self.resolver.local_def_id(item.id).to_def_id());
- }
- ItemKind::Impl(box ast::Impl { of_trait: Some(..), .. }) => {
+ 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 => {
diff --git a/src/librustdoc/passes/html_tags.rs b/src/librustdoc/passes/html_tags.rs
index 885dadb32..a89ed7c7e 100644
--- a/src/librustdoc/passes/html_tags.rs
+++ b/src/librustdoc/passes/html_tags.rs
@@ -22,10 +22,8 @@ struct InvalidHtmlTagsLinter<'a, 'tcx> {
}
pub(crate) fn check_invalid_html_tags(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
- if cx.tcx.sess.is_nightly_build() {
- let mut coll = InvalidHtmlTagsLinter { cx };
- coll.visit_crate(&krate);
- }
+ let mut coll = InvalidHtmlTagsLinter { cx };
+ coll.visit_crate(&krate);
krate
}
@@ -186,7 +184,60 @@ fn extract_html_tag(
}
drop_tag(tags, tag_name, r, f);
} else {
- tags.push((tag_name, r));
+ let mut is_self_closing = false;
+ let mut quote_pos = None;
+ if c != '>' {
+ let mut quote = None;
+ let mut after_eq = false;
+ for (i, c) in text[pos..].char_indices() {
+ if !c.is_whitespace() {
+ if let Some(q) = quote {
+ if c == q {
+ quote = None;
+ quote_pos = None;
+ after_eq = false;
+ }
+ } else if c == '>' {
+ break;
+ } else if c == '/' && !after_eq {
+ is_self_closing = true;
+ } else {
+ if is_self_closing {
+ is_self_closing = false;
+ }
+ if (c == '"' || c == '\'') && after_eq {
+ quote = Some(c);
+ quote_pos = Some(pos + i);
+ } else if c == '=' {
+ after_eq = true;
+ }
+ }
+ } else if quote.is_none() {
+ after_eq = false;
+ }
+ }
+ }
+ if let Some(quote_pos) = quote_pos {
+ let qr = Range { start: quote_pos, end: quote_pos };
+ f(
+ &format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
+ &qr,
+ false,
+ );
+ }
+ if is_self_closing {
+ // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
+ let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..])
+ || tags.iter().take(pos + 1).any(|(at, _)| {
+ let at = at.to_lowercase();
+ at == "svg" || at == "math"
+ });
+ if !valid {
+ f(&format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
+ }
+ } else {
+ tags.push((tag_name, r));
+ }
}
}
break;
@@ -240,9 +291,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
Some(sp) => sp,
None => item.attr_span(tcx),
};
- tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, |lint| {
+ tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| {
use rustc_lint_defs::Applicability;
- let mut diag = lint.build(msg);
// If a tag looks like `<this>`, it might actually be a generic.
// We don't try to detect stuff `<like, this>` because that's not valid HTML,
// and we don't try to detect stuff `<like this>` because that's not valid Rust.
@@ -305,11 +355,10 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
if (generics_start > 0 && dox.as_bytes()[generics_start - 1] == b'<')
|| (generics_end < dox.len() && dox.as_bytes()[generics_end] == b'>')
{
- diag.emit();
- return;
+ return lint;
}
// multipart form is chosen here because ``Vec<i32>`` would be confusing.
- diag.multipart_suggestion(
+ lint.multipart_suggestion(
"try marking as source code",
vec![
(generics_sp.shrink_to_lo(), String::from("`")),
@@ -318,7 +367,8 @@ impl<'a, 'tcx> DocVisitor for InvalidHtmlTagsLinter<'a, 'tcx> {
Applicability::MaybeIncorrect,
);
}
- diag.emit()
+
+ lint
});
};
diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs
index 765f7c61b..de3a4b339 100644
--- a/src/librustdoc/passes/propagate_doc_cfg.rs
+++ b/src/librustdoc/passes/propagate_doc_cfg.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> CfgPropagator<'a, 'tcx> {
let expected_parent = hir.get_parent_item(hir_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) {
+ if self.parent == Some(expected_parent.def_id) {
return;
}
}
diff --git a/src/librustdoc/passes/strip_private.rs b/src/librustdoc/passes/strip_private.rs
index f3aa3c7ce..450f69e15 100644
--- a/src/librustdoc/passes/strip_private.rs
+++ b/src/librustdoc/passes/strip_private.rs
@@ -23,7 +23,7 @@ pub(crate) fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) ->
{
let mut stripper = Stripper {
retained: &mut retained,
- access_levels: &cx.cache.access_levels,
+ effective_visibilities: &cx.cache.effective_visibilities,
update_retained: true,
is_json_output,
};
diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs
index a9d768f01..0089ce63d 100644
--- a/src/librustdoc/passes/stripper.rs
+++ b/src/librustdoc/passes/stripper.rs
@@ -1,15 +1,17 @@
//! A collection of utility functions for the `strip_*` passes.
use rustc_hir::def_id::DefId;
-use rustc_middle::middle::privacy::AccessLevels;
+use rustc_middle::middle::privacy::EffectiveVisibilities;
+use rustc_span::symbol::sym;
+
use std::mem;
-use crate::clean::{self, Item, ItemId, ItemIdSet};
+use crate::clean::{self, Item, ItemId, ItemIdSet, NestedAttributesExt};
use crate::fold::{strip_item, DocFolder};
use crate::formats::cache::Cache;
pub(crate) struct Stripper<'a> {
pub(crate) retained: &'a mut ItemIdSet,
- pub(crate) access_levels: &'a AccessLevels<DefId>,
+ pub(crate) effective_visibilities: &'a EffectiveVisibilities<DefId>,
pub(crate) update_retained: bool,
pub(crate) is_json_output: bool,
}
@@ -20,13 +22,13 @@ pub(crate) struct Stripper<'a> {
#[inline]
fn is_item_reachable(
is_json_output: bool,
- access_levels: &AccessLevels<DefId>,
+ effective_visibilities: &EffectiveVisibilities<DefId>,
item_id: ItemId,
) -> bool {
if is_json_output {
- access_levels.is_reachable(item_id.expect_def_id())
+ effective_visibilities.is_reachable(item_id.expect_def_id())
} else {
- access_levels.is_exported(item_id.expect_def_id())
+ effective_visibilities.is_exported(item_id.expect_def_id())
}
}
@@ -64,7 +66,7 @@ impl<'a> DocFolder for Stripper<'a> {
| clean::ForeignTypeItem => {
let item_id = i.item_id;
if item_id.is_local()
- && !is_item_reachable(self.is_json_output, self.access_levels, item_id)
+ && !is_item_reachable(self.is_json_output, self.effective_visibilities, item_id)
{
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
return None;
@@ -151,6 +153,22 @@ pub(crate) struct ImplStripper<'a> {
pub(crate) document_private: bool,
}
+impl<'a> ImplStripper<'a> {
+ #[inline]
+ fn should_keep_impl(&self, item: &Item, for_def_id: DefId) -> bool {
+ if !for_def_id.is_local() || self.retained.contains(&for_def_id.into()) {
+ true
+ } else if self.is_json_output {
+ // If the "for" item is exported and the impl block isn't `#[doc(hidden)]`, then we
+ // need to keep it.
+ self.cache.effective_visibilities.is_exported(for_def_id)
+ && !item.attrs.lists(sym::doc).has_word(sym::hidden)
+ } else {
+ false
+ }
+ }
+}
+
impl<'a> DocFolder for ImplStripper<'a> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
if let clean::ImplItem(ref imp) = *i.kind {
@@ -168,7 +186,7 @@ impl<'a> DocFolder for ImplStripper<'a> {
item_id.is_local()
&& !is_item_reachable(
self.is_json_output,
- &self.cache.access_levels,
+ &self.cache.effective_visibilities,
item_id,
)
})
@@ -178,15 +196,17 @@ impl<'a> DocFolder for ImplStripper<'a> {
return None;
}
}
+ // 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 did.is_local() && !imp.for_.is_assoc_ty() && !self.retained.contains(&did.into())
- {
+ 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.trait_.as_ref().map(|t| t.def_id()) {
- if did.is_local() && !self.retained.contains(&did.into()) {
+ if !self.should_keep_impl(&i, did) {
debug!("ImplStripper: impl item for stripped trait; removing");
return None;
}
@@ -194,7 +214,7 @@ impl<'a> DocFolder for ImplStripper<'a> {
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
for typaram in generics {
if let Some(did) = typaram.def_id(self.cache) {
- if did.is_local() && !self.retained.contains(&did.into()) {
+ if !self.should_keep_impl(&i, did) {
debug!(
"ImplStripper: stripped item in trait's generics; removing impl"
);
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index ca86ac89e..dfa6ba38b 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -143,14 +143,14 @@ where
// then we need to exit before calling typeck (which will panic). See
// test/run-make/rustdoc-scrape-examples-invalid-expr for an example.
let hir = tcx.hir();
- if hir.maybe_body_owned_by(ex.hir_id.owner).is_none() {
+ if hir.maybe_body_owned_by(ex.hir_id.owner.def_id).is_none() {
return;
}
// Get type of function if expression is a function call
let (ty, call_span, ident_span) = match ex.kind {
hir::ExprKind::Call(f, _) => {
- let types = tcx.typeck(ex.hir_id.owner);
+ let types = tcx.typeck(ex.hir_id.owner.def_id);
if let Some(ty) = types.node_type_opt(f.hir_id) {
(ty, ex.span, f.span)
@@ -160,7 +160,7 @@ where
}
}
hir::ExprKind::MethodCall(path, _, _, call_span) => {
- let types = tcx.typeck(ex.hir_id.owner);
+ let types = tcx.typeck(ex.hir_id.owner.def_id);
let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
trace!("type_dependent_def_id({}) = None", ex.hir_id);
return;
@@ -183,9 +183,8 @@ where
// If the enclosing item has a span coming from a proc macro, then we also don't want to include
// the example.
- let enclosing_item_span = tcx
- .hir()
- .span_with_body(tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(ex.hir_id)));
+ let enclosing_item_span =
+ tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id).into());
if enclosing_item_span.from_expansion() {
trace!("Rejecting expr ({call_span:?}) from macro item: {enclosing_item_span:?}");
return;
diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs
index c40274394..d29ceead4 100644
--- a/src/librustdoc/visit.rs
+++ b/src/librustdoc/visit.rs
@@ -65,7 +65,7 @@ pub(crate) trait DocVisitor: Sized {
// FIXME: make this a simple by-ref for loop once external_traits is cleaned up
let external_traits = { std::mem::take(&mut *c.external_traits.borrow_mut()) };
for (k, v) in external_traits {
- v.trait_.items.iter().for_each(|i| self.visit_item(i));
+ v.items.iter().for_each(|i| self.visit_item(i));
c.external_traits.borrow_mut().insert(k, v);
}
}
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index c27ac0ac4..06dffce55 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -7,8 +7,8 @@ use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::Node;
use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::middle::privacy::AccessLevel;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::middle::privacy::Level;
+use rustc_middle::ty::{TyCtxt, Visibility};
use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_span::Span;
@@ -230,7 +230,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
} else {
// All items need to be handled here in case someone wishes to link
// to them with intra-doc links
- self.cx.cache.access_levels.map.insert(did, AccessLevel::Public);
+ self.cx.cache.effective_visibilities.set_public_at_level(
+ did,
+ || Visibility::Restricted(CRATE_DEF_ID),
+ Level::Direct,
+ );
}
}
}
@@ -242,7 +246,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
None => return false,
};
- let is_private = !self.cx.cache.access_levels.is_public(res_did);
+ let is_private = !self.cx.cache.effective_visibilities.is_directly_public(res_did);
let is_hidden = inherits_doc_hidden(self.cx.tcx, res_hir_id);
// Only inline if requested or if the item would otherwise be stripped.
@@ -291,11 +295,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
debug!("visiting item {:?}", item);
let name = renamed.unwrap_or(item.ident.name);
- let def_id = item.def_id.to_def_id();
+ let def_id = item.owner_id.to_def_id();
let is_pub = self.cx.tcx.visibility(def_id).is_public();
if is_pub {
- self.store_path(item.def_id.to_def_id());
+ self.store_path(item.owner_id.to_def_id());
}
match item.kind {
@@ -356,7 +360,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
// 3. We're inlining, since a reexport where inlining has been requested
// should be inlined even if it is also documented at the top level.
- let def_id = item.def_id.to_def_id();
+ 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);
@@ -401,7 +405,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
om: &mut Module<'tcx>,
) {
// If inlining we only want to include public functions.
- if !self.inlining || self.cx.tcx.visibility(item.def_id).is_public() {
+ if !self.inlining || self.cx.tcx.visibility(item.owner_id).is_public() {
om.foreigns.push((item, renamed));
}
}
diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs
index f01ec3866..70214e2ad 100644
--- a/src/librustdoc/visit_lib.rs
+++ b/src/librustdoc/visit_lib.rs
@@ -1,8 +1,8 @@
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId};
-use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
-use rustc_middle::ty::TyCtxt;
+use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_ID};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
+use rustc_middle::ty::{TyCtxt, Visibility};
// FIXME: this may not be exhaustive, but is sufficient for rustdocs current uses
@@ -10,10 +10,10 @@ use rustc_middle::ty::TyCtxt;
/// specific rustdoc annotations into account (i.e., `doc(hidden)`)
pub(crate) struct LibEmbargoVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- // Accessibility levels for reachable nodes
- access_levels: &'a mut AccessLevels<DefId>,
- // Previous accessibility level, None means unreachable
- prev_level: Option<AccessLevel>,
+ // Effective visibilities for reachable nodes
+ effective_visibilities: &'a mut EffectiveVisibilities<DefId>,
+ // Previous level, None means unreachable
+ prev_level: Option<Level>,
// Keeps track of already visited modules, in case a module re-exports its parent
visited_mods: FxHashSet<DefId>,
}
@@ -22,26 +22,30 @@ impl<'a, 'tcx> LibEmbargoVisitor<'a, 'tcx> {
pub(crate) fn new(cx: &'a mut crate::core::DocContext<'tcx>) -> LibEmbargoVisitor<'a, 'tcx> {
LibEmbargoVisitor {
tcx: cx.tcx,
- access_levels: &mut cx.cache.access_levels,
- prev_level: Some(AccessLevel::Public),
+ effective_visibilities: &mut cx.cache.effective_visibilities,
+ prev_level: Some(Level::Direct),
visited_mods: FxHashSet::default(),
}
}
pub(crate) fn visit_lib(&mut self, cnum: CrateNum) {
let did = cnum.as_def_id();
- self.update(did, Some(AccessLevel::Public));
+ self.update(did, Some(Level::Direct));
self.visit_mod(did);
}
// Updates node level and returns the updated level
- fn update(&mut self, did: DefId, level: Option<AccessLevel>) -> Option<AccessLevel> {
+ fn update(&mut self, did: DefId, level: Option<Level>) -> Option<Level> {
let is_hidden = self.tcx.is_doc_hidden(did);
- let old_level = self.access_levels.map.get(&did).cloned();
- // Accessibility levels can only grow
+ let old_level = self.effective_visibilities.public_at_level(did);
+ // Visibility levels can only grow
if level > old_level && !is_hidden {
- self.access_levels.map.insert(did, level.unwrap());
+ self.effective_visibilities.set_public_at_level(
+ did,
+ || Visibility::Restricted(CRATE_DEF_ID),
+ level.unwrap(),
+ );
level
} else {
old_level
diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs
index fb1830426..4bc91fc40 100644
--- a/src/rustdoc-json-types/lib.rs
+++ b/src/rustdoc-json-types/lib.rs
@@ -9,7 +9,7 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize};
/// rustdoc format-version.
-pub const FORMAT_VERSION: u32 = 21;
+pub const FORMAT_VERSION: u32 = 22;
/// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
/// about the language items in the local crate, as well as info about external items to allow
@@ -51,6 +51,11 @@ pub struct ItemSummary {
pub crate_id: u32,
/// The list of path components for the fully qualified path of this item (e.g.
/// `["std", "io", "lazy", "Lazy"]` for `std::io::lazy::Lazy`).
+ ///
+ /// Note that items can appear in multiple paths, and the one chosen is implementation
+ /// defined. Currenty, this is the full path to where the item was defined. Eg
+ /// [`String`] is currently `["alloc", "string", "String"]` and [`HashMap`] is
+ /// `["std", "collections", "hash", "map", "HashMap"]`, but this is subject to change.
pub path: Vec<String>,
/// Whether this item is a struct, trait, macro, etc.
pub kind: ItemKind,
@@ -254,7 +259,7 @@ pub enum ItemEnum {
Macro(String),
ProcMacro(ProcMacro),
- PrimitiveType(String),
+ Primitive(Primitive),
AssocConst {
#[serde(rename = "type")]
@@ -709,5 +714,11 @@ pub struct Static {
pub expr: String,
}
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+pub struct Primitive {
+ pub name: String,
+ pub impls: Vec<Id>,
+}
+
#[cfg(test)]
mod tests;
diff --git a/src/stage0.json b/src/stage0.json
index a54fd5496..db7444839 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -17,292 +17,292 @@
"tool is executed."
],
"compiler": {
- "date": "2022-09-22",
- "version": "1.64.0"
+ "date": "2022-11-03",
+ "version": "1.65.0"
},
"rustfmt": null,
"checksums_sha256": {
- "dist/2022-09-22/cargo-1.64.0-aarch64-apple-darwin.tar.gz": "dbb26b73baefc8351a7024f307445758fe1e9c18d83000358c02b80a5b1003b3",
- "dist/2022-09-22/cargo-1.64.0-aarch64-apple-darwin.tar.xz": "8d987d76039b730086ee303710d93f3ff2abcfe3cb74505d8e68c9f72edaa812",
- "dist/2022-09-22/cargo-1.64.0-aarch64-pc-windows-msvc.tar.gz": "6b86e2b51fa4471358e128369baff21a216815e90eb3ff70af7271e64438da0a",
- "dist/2022-09-22/cargo-1.64.0-aarch64-pc-windows-msvc.tar.xz": "dc174319e5750d6489fd45d982a5dd9d7305845e9aaaa809bef9f445f1c2c219",
- "dist/2022-09-22/cargo-1.64.0-aarch64-unknown-linux-gnu.tar.gz": "a2079bad79c054facecd149bafb645c321047fd9e4d2aa500607b2450654b209",
- "dist/2022-09-22/cargo-1.64.0-aarch64-unknown-linux-gnu.tar.xz": "103d69e4f2f49f5a6309d7d195747b31f94cf707f90fb49cf76039a5ce6295c7",
- "dist/2022-09-22/cargo-1.64.0-aarch64-unknown-linux-musl.tar.gz": "f589c0e8c0472128e88f751429b5e697b5605e2105e3571016400f98f47c1b54",
- "dist/2022-09-22/cargo-1.64.0-aarch64-unknown-linux-musl.tar.xz": "aff8dedcaa02b5059dd59f8c5644ed87b8c9c72be90c578044fe5755ca841418",
- "dist/2022-09-22/cargo-1.64.0-arm-unknown-linux-gnueabi.tar.gz": "f497f70e3154d78399487c75934734a13efdb64d5ba8fe7fcd4d28740cece688",
- "dist/2022-09-22/cargo-1.64.0-arm-unknown-linux-gnueabi.tar.xz": "79e703e1e0355ef3d268d13f778b2c85ada0dee9d5067fb94f5fca20c6d09c53",
- "dist/2022-09-22/cargo-1.64.0-arm-unknown-linux-gnueabihf.tar.gz": "40e6d068d84a110c74c63dbd9bc457c8e9d8c520bb75c64b2b4f1a269378a003",
- "dist/2022-09-22/cargo-1.64.0-arm-unknown-linux-gnueabihf.tar.xz": "d73428a73d9234c9f4f6412025ca827a667b2d6e8dc61e1852725784d8d3136d",
- "dist/2022-09-22/cargo-1.64.0-armv7-unknown-linux-gnueabihf.tar.gz": "a12455495aa39006f2cf83c9f86b7ecc4b188f98e683a99134c97eeb217b66bf",
- "dist/2022-09-22/cargo-1.64.0-armv7-unknown-linux-gnueabihf.tar.xz": "ecd2e5f4c08bbda72ad2936bfdd521d9a641d311e71e8ace44b00570f068b819",
- "dist/2022-09-22/cargo-1.64.0-i686-pc-windows-gnu.tar.gz": "2e73350bbe2e8c5fa27893e57704e37d6c6d8ef5d548a7bbe0d24615468f5158",
- "dist/2022-09-22/cargo-1.64.0-i686-pc-windows-gnu.tar.xz": "3596f78c51024eda28adc8be508ad084e1e6dfb71d8a0bce00a67cfc592ec5ad",
- "dist/2022-09-22/cargo-1.64.0-i686-pc-windows-msvc.tar.gz": "55b9d1a121410a5f3c755012ec4a55ee6f7c270a958c7a506c14542095a793bf",
- "dist/2022-09-22/cargo-1.64.0-i686-pc-windows-msvc.tar.xz": "64711cbcc71906184427f501399ebe304e95a42f2f773d251cdd6bb1a148dc94",
- "dist/2022-09-22/cargo-1.64.0-i686-unknown-linux-gnu.tar.gz": "da713a9521c857d87bfebc1e2b1da01e9882d11fa6cb1c2ebbf38b1b0a15bbcc",
- "dist/2022-09-22/cargo-1.64.0-i686-unknown-linux-gnu.tar.xz": "e2e20a16f5db52cd6b773c94225b03880743544ff2f317dd857cf0dceac6ab57",
- "dist/2022-09-22/cargo-1.64.0-mips-unknown-linux-gnu.tar.gz": "a935deca822265d1b341682324743c95213346a650eecdf7c8493eecd233ba72",
- "dist/2022-09-22/cargo-1.64.0-mips-unknown-linux-gnu.tar.xz": "3227f9957542bc2b8ef6605e24cd27a16ab76ae318d86d18f4e99ffcf17aaae4",
- "dist/2022-09-22/cargo-1.64.0-mips64-unknown-linux-gnuabi64.tar.gz": "4bdf7a09474588dd647e9007ca0fcce13bf8784f20e940442c0649c40b5402d0",
- "dist/2022-09-22/cargo-1.64.0-mips64-unknown-linux-gnuabi64.tar.xz": "4b4c950e95755b39ef64b720913482f3a61daceb4e8a57fe8812f92b4c2bc76f",
- "dist/2022-09-22/cargo-1.64.0-mips64el-unknown-linux-gnuabi64.tar.gz": "e49b9e758768533b47470765eb2b4cc3cdc378460677daeaff62638e711b957b",
- "dist/2022-09-22/cargo-1.64.0-mips64el-unknown-linux-gnuabi64.tar.xz": "252d0edd035601ed2fb633093780a9bbd957ed7abf276cc48e805e6cdedc76cd",
- "dist/2022-09-22/cargo-1.64.0-mipsel-unknown-linux-gnu.tar.gz": "26c870ab447656d4c5610c73af7bbd400dc06dad0fd90c7558206c4ab4783928",
- "dist/2022-09-22/cargo-1.64.0-mipsel-unknown-linux-gnu.tar.xz": "42ffc698db364e1d8a1b1c20e87ba0aadf2a0103f411a76fa277de84fe8139a5",
- "dist/2022-09-22/cargo-1.64.0-powerpc-unknown-linux-gnu.tar.gz": "112820998ab4b1a20a2bac39963ee50e49adf4d3eac22b0f8af4d7b55044ae9a",
- "dist/2022-09-22/cargo-1.64.0-powerpc-unknown-linux-gnu.tar.xz": "d2e075eba43c29fe493d7b9d5b951ead3f0a61fd8c7d7fa795547fd02827cb5b",
- "dist/2022-09-22/cargo-1.64.0-powerpc64-unknown-linux-gnu.tar.gz": "8a5f37a0a50cc516772af9c1b56a4f159c1b90b4ec64470313afa9ad7ffb1552",
- "dist/2022-09-22/cargo-1.64.0-powerpc64-unknown-linux-gnu.tar.xz": "82787ee0f4951227eff08ea0127d4454ea2a56fe1f06ecca6de7823bcb3be647",
- "dist/2022-09-22/cargo-1.64.0-powerpc64le-unknown-linux-gnu.tar.gz": "19df9e098ba8a2a6d6120a1340b40dfcaf4cbb5b0c1294d76665e75555bffdd4",
- "dist/2022-09-22/cargo-1.64.0-powerpc64le-unknown-linux-gnu.tar.xz": "ba7188b2c7890e61bf58d3aa9e94c323fec375f67cf03841bbcc0f6c800fe6ad",
- "dist/2022-09-22/cargo-1.64.0-riscv64gc-unknown-linux-gnu.tar.gz": "f5ebe9cf9237845051bfcb173101eb15c45b651d79b0d7982b11b3c7cd08832d",
- "dist/2022-09-22/cargo-1.64.0-riscv64gc-unknown-linux-gnu.tar.xz": "b94e262dec82b7cacf3baa77f35601c82d389ad338d118b42da4d23e26240760",
- "dist/2022-09-22/cargo-1.64.0-s390x-unknown-linux-gnu.tar.gz": "a5f14599f7ca4c641c27b9fa5bbdfbeb5f92eb8f66101b7474f04ff78df4950d",
- "dist/2022-09-22/cargo-1.64.0-s390x-unknown-linux-gnu.tar.xz": "7c01b6af89c18437778ef410cb98c948493bd6070c4b81e7f38f3c25ae1c6a52",
- "dist/2022-09-22/cargo-1.64.0-x86_64-apple-darwin.tar.gz": "e032116e22f6d3a4cb078f21031794e88f2a87f066625b8eb7623777e42d6eca",
- "dist/2022-09-22/cargo-1.64.0-x86_64-apple-darwin.tar.xz": "9dd507854410d20cd8b75b296e319bb5a62f9b1c2cb6c2b043c32de96eb5cc35",
- "dist/2022-09-22/cargo-1.64.0-x86_64-pc-windows-gnu.tar.gz": "dc029ae8045adc561ccab8a981be89c5eda83162ffcc0c43a1dd7d9c903b2e09",
- "dist/2022-09-22/cargo-1.64.0-x86_64-pc-windows-gnu.tar.xz": "287c49c9a9cfb51f9bb758ee3586cb3542aa1c0651f088cba4e6eb4ba8e87741",
- "dist/2022-09-22/cargo-1.64.0-x86_64-pc-windows-msvc.tar.gz": "b197c91ef9ddd98f1ae129e4f108d9d2b48350dc377300047cbb19c63a6fc641",
- "dist/2022-09-22/cargo-1.64.0-x86_64-pc-windows-msvc.tar.xz": "38d75dbba91dc1dbf35898c5845ee29d6f6ec69b44516220930b4c7e8719bd0a",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-freebsd.tar.gz": "36e86a67fa943d324ce7b977d967ae16ad012ac0aa0b7625db61a16c8f25c2d1",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-freebsd.tar.xz": "6a78d94aed814a9ff3bc650d0ff0ac7ee1eb1595819e672bc7e66d658149d808",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-illumos.tar.gz": "360ebcca8247099bffae548a1c09449c8dc4516918d4f18f7ba09ef650b7775c",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-illumos.tar.xz": "f7ac58bbf283c8c6fcb3648bb18601e0c7c30f6613177b400485f39dc4552044",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-linux-gnu.tar.gz": "12c2e61bf7de8b37c16d0323972a6085f9e01ee6d716549dd1ef4a92481b0610",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-linux-gnu.tar.xz": "21434d83a30ad3fa4e4831487c5574a20b07dd57d213b26e1246290c57d4ec41",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-linux-musl.tar.gz": "fffd3e692f39c28a0392d17ee2f5695f53141e34c0bf8bbb7cdc0ef9fd3ad791",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-linux-musl.tar.xz": "01d06176fd894b9299ed4f5b78e87d78a9a25b9ba803d3f8c50b7a4ea21d8807",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-netbsd.tar.gz": "cb2b26b0081cefdf87e977d7ba3b82687b15f79d875188c6028a3f25f5601a4f",
- "dist/2022-09-22/cargo-1.64.0-x86_64-unknown-netbsd.tar.xz": "302402ff74a8cf51d22808723d3ed3fee2b6cd765677023d2f380c34f2c6f719",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-darwin.tar.gz": "808d3b83211e45cabdf59a19a72565e13d45bba79053ae8210d51eb05500e5fb",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-darwin.tar.xz": "ed79f61b3d8b4ea3ffcb78fb9952cc3b199d646d057827bb3bfa5247489f21cd",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-ios-sim.tar.gz": "24f8b2121f4d342eb9d21b926a34bd7960c34275ce9bee4e77c67969a2780ca9",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-ios-sim.tar.xz": "2e1193d20d85265def6e4e525b32f197b7bec6047f22c43f0df15d8e4aae1ff0",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-ios.tar.gz": "aa6513954fe168aa158fb5f6074037d252e4c8fd9bec5c4894dd68c8be4c8fdd",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-apple-ios.tar.xz": "6c1b63340ba2aa051eea47d09b1c79c817538144140672f6f11be8cefa241501",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-fuchsia.tar.gz": "5ffb190975f5936800e128d1a41ca8a9974acad2ce80d1b45620a259860e6ffe",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-fuchsia.tar.xz": "d69cb543c339c5830b3e65a4bf754b8540a5e57044be44fd34580b1dbe9da0ec",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-linux-android.tar.gz": "b56deb8930974159f1027f884b8a4756e392765189a27f6d80e95519d206b9d1",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-linux-android.tar.xz": "b6395b3bd2be7787672366482e134dbf64a9418aa5011b2090ed906cd3c0a060",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-pc-windows-msvc.tar.gz": "708e7a144c3f7895a80e87cd3f59083ba72d2f5670da550f5dfb843385214c95",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-pc-windows-msvc.tar.xz": "9fd1b3bad839f01c7b8c5075c34dfe8d0c1a9fd7139cd7aedf7144cabfc610e7",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-linux-gnu.tar.gz": "2b425658f84793d5bbf00ce545f410ec6454add202cce27a718d81e0233e7007",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-linux-gnu.tar.xz": "40abc9ec4f86ff0e37ba176e4c68dfa708e9857bb0372169c865367593127566",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-linux-musl.tar.gz": "fc74d1ddc8a12d7a58a40534b10297e249c972e39943a7cb514ac72032c5fcd8",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-linux-musl.tar.xz": "2438f7116711b2c65b60d59662ad333cc5f66868ec34498777ed764103f4d4a3",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-none-softfloat.tar.gz": "6697319c1011268dd73c9140655a04321d52b257dc381da374db68fb990cfc42",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-none-softfloat.tar.xz": "ea09ce9479411883444011727cdc9655748f4fe199d16a547a6464a68c45beb9",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-none.tar.gz": "a32b5b222fc43fd791d62c4c1bebb9a41d2783934e3f27f7bdb692342cca2502",
- "dist/2022-09-22/rust-std-1.64.0-aarch64-unknown-none.tar.xz": "241a7335982e67b510fe48d33acce068c2dda88c20b321d3fe87cb3625239f5f",
- "dist/2022-09-22/rust-std-1.64.0-arm-linux-androideabi.tar.gz": "4fa112179b4df1bbf5922c4e68e7c8fa87770ee1bec951e39761cc5f0e504e29",
- "dist/2022-09-22/rust-std-1.64.0-arm-linux-androideabi.tar.xz": "da0d33bee214073dff52914e2f9cfa4a6ecea6a1035ffae71c4338f5bcaa02e8",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-gnueabi.tar.gz": "f7ca0fc92aab9f1a8c44ec180c7e10018138ca7e9b507bec085d03d9fd3a73e9",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-gnueabi.tar.xz": "9e7dc879ce647d0b5c7423dcfea1438d64ea2e0764895b5cb9b3258ab0ecf8dd",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-gnueabihf.tar.gz": "30ea300372033c2886d61ac59a7532f8d0e4665f548c6e90d8fd25a57f89ee9f",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-gnueabihf.tar.xz": "07fbe4ef51f33e7954e25c433522da224b10c6f7353f612713669a4fc58704e8",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-musleabi.tar.gz": "0f6e4f77289cfa8eb415c037449f59ce359dbef9a161c78ba8474c8405fbd50b",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-musleabi.tar.xz": "f0d24e63e2687af229ea1472650bf5dd5a50d7706062b47a73413e28101fccf1",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-musleabihf.tar.gz": "21990412baeade16a29a7b82e2734460e3fae144abd4eee1bb31848ac94ad30b",
- "dist/2022-09-22/rust-std-1.64.0-arm-unknown-linux-musleabihf.tar.xz": "9955ac8be9828e0400c16a1c0388a769401dc8e732d099ffada156867cab08fb",
- "dist/2022-09-22/rust-std-1.64.0-armebv7r-none-eabi.tar.gz": "a6c849f95edf97d2fceabee5cf21963062ce2d840794acf28a427128430ca01f",
- "dist/2022-09-22/rust-std-1.64.0-armebv7r-none-eabi.tar.xz": "d8bee2d8337bb67ab604961a61e117d09d93b500dc8bea17c85f2f349bf18ad2",
- "dist/2022-09-22/rust-std-1.64.0-armebv7r-none-eabihf.tar.gz": "74296a66735011527c129e5885105398479b2dbdc98b2ff516c655681354ca86",
- "dist/2022-09-22/rust-std-1.64.0-armebv7r-none-eabihf.tar.xz": "39ef3482b47b6218cf811ef53662385b8c52ef91930acc60685a3e334126d02c",
- "dist/2022-09-22/rust-std-1.64.0-armv5te-unknown-linux-gnueabi.tar.gz": "7bcea2b201ebc61748760e5004d4451944191391129d3cd47cdbc909aeb0c3be",
- "dist/2022-09-22/rust-std-1.64.0-armv5te-unknown-linux-gnueabi.tar.xz": "af9b36ce5ad613112f83f085840e1f2c5f58ec7b72d8dbf9e833883105699a37",
- "dist/2022-09-22/rust-std-1.64.0-armv5te-unknown-linux-musleabi.tar.gz": "d38f38f2f31fb099c1360e5ef81fd3159b09ddf0bfd8b555cfb07acc08be5547",
- "dist/2022-09-22/rust-std-1.64.0-armv5te-unknown-linux-musleabi.tar.xz": "5246edd6be26f10d11a3100d3e74f460c2cfbdabb417e4cc8225ce2b82c485ce",
- "dist/2022-09-22/rust-std-1.64.0-armv7-linux-androideabi.tar.gz": "997cb016441d53f45e8bb9c7c7aca1926275c384505f33c1b713e695e3532ae4",
- "dist/2022-09-22/rust-std-1.64.0-armv7-linux-androideabi.tar.xz": "8bcb6ad1ef04154191be993135b604ce344bcc0645f235d87027c05abe9de8fb",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-gnueabi.tar.gz": "89ef5effad1ed58610582b35db06670b01a7a491ac43856c8d6d179b37814e7e",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-gnueabi.tar.xz": "eca7608caa6b8fb31467b4524292e86f854ebd06fcff29f58f5fc860b664c711",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-gnueabihf.tar.gz": "9cda1ef1d14372d7c5288cc69c9b5e9f211f5bebf7da22fae6d6ca8fc06ed687",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-gnueabihf.tar.xz": "ef1820f55b341ed1a78cadbd3564f9f8800f99bbfb7533821ef5f90ba2c21e87",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-musleabi.tar.gz": "bbff558e98be89b530dc5f6aca35e5b9661fb221bd2a199b7de6cf971dc60ab4",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-musleabi.tar.xz": "742fac589f1bc1a0ddd857e32b317e2b673c40adb8ef6dfc3516563ba9bc839f",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-musleabihf.tar.gz": "bb233eb7c5dd2f8ae50c4874aea1a8b2e9965f92d184c4e6574f6db45f3c0562",
- "dist/2022-09-22/rust-std-1.64.0-armv7-unknown-linux-musleabihf.tar.xz": "a31b9284ca3e864343fdad900fc877cc14e00de32dcde7326023372720cd4b09",
- "dist/2022-09-22/rust-std-1.64.0-armv7a-none-eabi.tar.gz": "1074c419524eab1e6b73c54e62a30b50f0557025e30372316965218cba515858",
- "dist/2022-09-22/rust-std-1.64.0-armv7a-none-eabi.tar.xz": "3cc35863989cb5b1e236ae79600649ef5bc460233afb11d806dfb2c028c14e09",
- "dist/2022-09-22/rust-std-1.64.0-armv7r-none-eabi.tar.gz": "df7efe69bfdc3e284550ef75f4617a9d0b5f02157fe19ec3306e81d719959970",
- "dist/2022-09-22/rust-std-1.64.0-armv7r-none-eabi.tar.xz": "c8091d6ad014fc9608a51f942ebd0d67c2fbfa186133e4054cb162c6a03ab3f0",
- "dist/2022-09-22/rust-std-1.64.0-armv7r-none-eabihf.tar.gz": "258d0df03c1ad69a194510c3bfc22dbdeeedbfc881d16e83dd86cbee60d4c952",
- "dist/2022-09-22/rust-std-1.64.0-armv7r-none-eabihf.tar.xz": "52ddc8560c87303b887eb852a7b742c59cee240500bbdbf3069eb7258f9a9e35",
- "dist/2022-09-22/rust-std-1.64.0-asmjs-unknown-emscripten.tar.gz": "71c28ab0421fcc9d045a19eb67778c9c4b9d64a37e076fe94621c1d84bbdb97b",
- "dist/2022-09-22/rust-std-1.64.0-asmjs-unknown-emscripten.tar.xz": "6443813cc696cba8155c1cbfe8eb46ef1846c4609f6887e8d883b0a3a045167d",
- "dist/2022-09-22/rust-std-1.64.0-i586-pc-windows-msvc.tar.gz": "c5ae8faf7a3c8f94a962f460c44b7fb155f0ccc9b98447c21ed63798276cb25c",
- "dist/2022-09-22/rust-std-1.64.0-i586-pc-windows-msvc.tar.xz": "ce02bcf63aad651ddaa05a5034704d2e8c8cf064bca94acff5ce96c0fcda07b9",
- "dist/2022-09-22/rust-std-1.64.0-i586-unknown-linux-gnu.tar.gz": "82779e550c600d664063c935a5fb52fa1c5e3ba840fe1bf01a48ee9757f6b640",
- "dist/2022-09-22/rust-std-1.64.0-i586-unknown-linux-gnu.tar.xz": "791aafcfb41c342783bc3c8cdb57ac61453fc02eee185f15c275716f419556f3",
- "dist/2022-09-22/rust-std-1.64.0-i586-unknown-linux-musl.tar.gz": "a649905b57cff932ae3d8955c410398c225ff2cd9d80da8076eb19d5338cb1e7",
- "dist/2022-09-22/rust-std-1.64.0-i586-unknown-linux-musl.tar.xz": "0cb3b0848cd31bd68ac82cd138c6345e5348f5af3dcc1f13275ee019a0895c59",
- "dist/2022-09-22/rust-std-1.64.0-i686-linux-android.tar.gz": "445755849a1469147316bc496a02ae198f293d537b3a95040d9c3892cf41d37b",
- "dist/2022-09-22/rust-std-1.64.0-i686-linux-android.tar.xz": "b7185e6b963235734acb092d0cef6cc77d5799e659fcd1e1543fea62351ef51e",
- "dist/2022-09-22/rust-std-1.64.0-i686-pc-windows-gnu.tar.gz": "08648a4175ed8f211f9ac7beedb171b9074d041e10b89db45cd45d42af88d854",
- "dist/2022-09-22/rust-std-1.64.0-i686-pc-windows-gnu.tar.xz": "a05610fccaacbcbdc7c872280f73ae0999666058cfba409dffcab3f2cc64d6f6",
- "dist/2022-09-22/rust-std-1.64.0-i686-pc-windows-msvc.tar.gz": "e0871d7e01d404498bb457c2f96143b844f2cf886a546c505a8bff640940e785",
- "dist/2022-09-22/rust-std-1.64.0-i686-pc-windows-msvc.tar.xz": "a18e2b009dac092f6410a4e66d5c22e81e525c7f9cb91296553ed8832fe35d33",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-freebsd.tar.gz": "575ce3a32df08254e0c2ada462c950647a85861c0e1ec18d1b83b17c82d9717b",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-freebsd.tar.xz": "d0ae58443104554e4636ffccde22a09d7ec360749f6638cc06d1cd22eaaa2f4d",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-linux-gnu.tar.gz": "50b32b772e2eb993dea89011fd800c291889c05ce615e45d9a260ee568661069",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-linux-gnu.tar.xz": "c80c57df63517d6171c061e6c095b794593172a3abefa9b4202992706bda12e5",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-linux-musl.tar.gz": "2898a1b2a3c28201d2da4e470bc64c261e6eb61531fbdeeb963b3dbef4d958ec",
- "dist/2022-09-22/rust-std-1.64.0-i686-unknown-linux-musl.tar.xz": "b193faf2e37951bf1ac6c3f2d4bd4fe84971a2f56f22e66323cccd142df54156",
- "dist/2022-09-22/rust-std-1.64.0-mips-unknown-linux-gnu.tar.gz": "1649e72798f14336c25019cf0d5e800016f9087e9e703749c456e1293178f01d",
- "dist/2022-09-22/rust-std-1.64.0-mips-unknown-linux-gnu.tar.xz": "45baef38fbfadf21d4e603554c49d62525d1dff887e4ea7045b1fc88feb81663",
- "dist/2022-09-22/rust-std-1.64.0-mips-unknown-linux-musl.tar.gz": "bc18714aa6ab30d3b53cb166a3126fd3a1876b4c53aeba1741b9227400e49968",
- "dist/2022-09-22/rust-std-1.64.0-mips-unknown-linux-musl.tar.xz": "993b3e003feaa966466509ea9161106978ef7c874877461b4ca1a9936032b25b",
- "dist/2022-09-22/rust-std-1.64.0-mips64-unknown-linux-gnuabi64.tar.gz": "8d876d6b783697d306240414cfea4c1ebca8f97b77a70f32aba5cea41f205756",
- "dist/2022-09-22/rust-std-1.64.0-mips64-unknown-linux-gnuabi64.tar.xz": "a2d2e2d274105054303adfd9ecb75ea2fba36a228ab23a669c609062f4db0035",
- "dist/2022-09-22/rust-std-1.64.0-mips64-unknown-linux-muslabi64.tar.gz": "a51ecd555b7374eba850b47ddc83c0a6a288a547ce14c90629c0077c0297c023",
- "dist/2022-09-22/rust-std-1.64.0-mips64-unknown-linux-muslabi64.tar.xz": "83981de8b57719d714d59b55f3749d8c6ff10588d8d6c7d7ae371bfb668a7b5b",
- "dist/2022-09-22/rust-std-1.64.0-mips64el-unknown-linux-gnuabi64.tar.gz": "2f7632305068706e09c02421856bc8bba5bf28c197dea418a7d076d1d6f35cb9",
- "dist/2022-09-22/rust-std-1.64.0-mips64el-unknown-linux-gnuabi64.tar.xz": "8ec026244400bac48d918230a0c99aa2c31ff33d6cc4d18552228509ca58c074",
- "dist/2022-09-22/rust-std-1.64.0-mips64el-unknown-linux-muslabi64.tar.gz": "d707d6e9e58921ea6c2a57882fc32dc5e2a74003ca0a30c9460e5d88c8b07e5f",
- "dist/2022-09-22/rust-std-1.64.0-mips64el-unknown-linux-muslabi64.tar.xz": "97f40ad383014955448f7917abba7a547d1ddd205746641d3e9c3f730cbd129e",
- "dist/2022-09-22/rust-std-1.64.0-mipsel-unknown-linux-gnu.tar.gz": "6f0e5498ab6505e3f4312249fc369eded48b9d4f33f910eee438936ad5d25758",
- "dist/2022-09-22/rust-std-1.64.0-mipsel-unknown-linux-gnu.tar.xz": "7dbcf969fc6717215796079437cf073a8ef7df95b77ded4654009c8379c91e0a",
- "dist/2022-09-22/rust-std-1.64.0-mipsel-unknown-linux-musl.tar.gz": "eabb79f49167d03e1c5ee4f047316d84db5d50e3224aa6168765a5f5db0afe93",
- "dist/2022-09-22/rust-std-1.64.0-mipsel-unknown-linux-musl.tar.xz": "288dd07746b0ece185753e784c7e97f2f01984e9302ef46a4ff71db665002637",
- "dist/2022-09-22/rust-std-1.64.0-nvptx64-nvidia-cuda.tar.gz": "32d865ba8c5b3a61ae0393fa021ebd15d14a515723879a3c494b7b7320f325ff",
- "dist/2022-09-22/rust-std-1.64.0-nvptx64-nvidia-cuda.tar.xz": "fbf12642d1df994db8e2e25d50f3c1a567b6b9379c53c1151afe2e3c6871022c",
- "dist/2022-09-22/rust-std-1.64.0-powerpc-unknown-linux-gnu.tar.gz": "61d228cb732ddb85802465781b69ed20719314adde5863805cdcac9c3cc1336f",
- "dist/2022-09-22/rust-std-1.64.0-powerpc-unknown-linux-gnu.tar.xz": "6b29ebec4cd705760db634717cf6df68a9a377d52c25def30f5a2e2641a83279",
- "dist/2022-09-22/rust-std-1.64.0-powerpc64-unknown-linux-gnu.tar.gz": "4a96801730f61b8b116553ec7c3572b56b03836b59220b3f2b2736e8428a92e3",
- "dist/2022-09-22/rust-std-1.64.0-powerpc64-unknown-linux-gnu.tar.xz": "dc0352fdcf7f8b4fcb551d63001738ee120ea2a0fcc7d55db11f1f87eba90b3e",
- "dist/2022-09-22/rust-std-1.64.0-powerpc64le-unknown-linux-gnu.tar.gz": "362dc9a7bc63d222598878d8d36dbd9008a1bb05cf389a90eeac28a76f55cdae",
- "dist/2022-09-22/rust-std-1.64.0-powerpc64le-unknown-linux-gnu.tar.xz": "ef697469b2a3ea8897f49b70e3be0c7aaca3f26fd3234812113e2e85cafac738",
- "dist/2022-09-22/rust-std-1.64.0-riscv32i-unknown-none-elf.tar.gz": "a6e4f4e61a84a7dce3554f6daea4854e9897f6affd7d0a4de279912a06f30a99",
- "dist/2022-09-22/rust-std-1.64.0-riscv32i-unknown-none-elf.tar.xz": "6966de249e5b0ac3bf10489baad41a55f29f777dd6d44f76e2ae950ba40cbb41",
- "dist/2022-09-22/rust-std-1.64.0-riscv32imac-unknown-none-elf.tar.gz": "111900d8e3325bb770b18a43cefb101c47ca9c4aece41c494ead994cfc14c007",
- "dist/2022-09-22/rust-std-1.64.0-riscv32imac-unknown-none-elf.tar.xz": "5ba51e00b3352b9e207e0f66c890962b7c2111bda9b9f2d786c3e3f10a9c3011",
- "dist/2022-09-22/rust-std-1.64.0-riscv32imc-unknown-none-elf.tar.gz": "164efc3ec05976883ffba2d52a62243a1c67582d359e301e4a1f6bd83141a747",
- "dist/2022-09-22/rust-std-1.64.0-riscv32imc-unknown-none-elf.tar.xz": "527bd3c4ec7f68c246046463f56c7071862079c5857e465d2b365de92d4bd81b",
- "dist/2022-09-22/rust-std-1.64.0-riscv64gc-unknown-linux-gnu.tar.gz": "5b8e8e67ae67ac74699b976043615f029f487c4148fdca4cb33fe7fe90192860",
- "dist/2022-09-22/rust-std-1.64.0-riscv64gc-unknown-linux-gnu.tar.xz": "284b09a96d4cdbb96827914a318f9c41e2b207c0afeae76b9f0e3830d2ef2d4d",
- "dist/2022-09-22/rust-std-1.64.0-riscv64gc-unknown-none-elf.tar.gz": "bd04973eb7e8061a55fe27c3fd14a29e1cac143714d323ef4c4c480c4df1df76",
- "dist/2022-09-22/rust-std-1.64.0-riscv64gc-unknown-none-elf.tar.xz": "eac6ca401809e0b94ace04ae255525bf972ad5cdc1f8775d401e166c4b688a0d",
- "dist/2022-09-22/rust-std-1.64.0-riscv64imac-unknown-none-elf.tar.gz": "55bfb141b8ae992e3ac1066b264f7a8609d10e2223079ecf503928fd1d138272",
- "dist/2022-09-22/rust-std-1.64.0-riscv64imac-unknown-none-elf.tar.xz": "74af2d8a944a1d57f27c002710ef9ba8e6f434d524ae27ba482f8ce7b5474f0c",
- "dist/2022-09-22/rust-std-1.64.0-s390x-unknown-linux-gnu.tar.gz": "b8c75287bd02dab135199fb760ed8adefa0bea44fd678421dd383582d3af8c28",
- "dist/2022-09-22/rust-std-1.64.0-s390x-unknown-linux-gnu.tar.xz": "939db2384f543325cc8a2423ab53e28623b9e9762dacea1e2010cf894d3e6ab1",
- "dist/2022-09-22/rust-std-1.64.0-sparc64-unknown-linux-gnu.tar.gz": "49d65f9a5bb57325fc3075ed37687e89ace44e2d2d5f1eed97ec3a4a4de1aae5",
- "dist/2022-09-22/rust-std-1.64.0-sparc64-unknown-linux-gnu.tar.xz": "3551f014fe1839e68e7b06eeb1b3f67869bef9c4849da9c9c01a7b8c3e32ebf2",
- "dist/2022-09-22/rust-std-1.64.0-sparcv9-sun-solaris.tar.gz": "4fe9b47445348a7251d0b09708f3c29fd424714e9d50a1a3f6ace492e2149b49",
- "dist/2022-09-22/rust-std-1.64.0-sparcv9-sun-solaris.tar.xz": "d5782d4352ed363011ff896fe89a6ef576e9206e0abb30255fb84cd1707b40aa",
- "dist/2022-09-22/rust-std-1.64.0-thumbv6m-none-eabi.tar.gz": "d73733335ae6554f42471bfc86c27c1e461401f0c3604514bbaa50f59b3e071f",
- "dist/2022-09-22/rust-std-1.64.0-thumbv6m-none-eabi.tar.xz": "419dc37e5fad24e5ff41e21b207bda1ef0c5aa94291fea4620c27f8be6d5f3bc",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7em-none-eabi.tar.gz": "90657346d888b1be2f3d7a6491603daaff804016cd45391945456dc0e3c39448",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7em-none-eabi.tar.xz": "b9e77f24e5f37a0789a1e9d84813cee643f4677ff1272e4c01699d74cd42c8dd",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7em-none-eabihf.tar.gz": "53a0dbe3446ec6d5fd20f595c96519c068939e0acea209f958b457c4c0ce7dbf",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7em-none-eabihf.tar.xz": "e5b653284e38c75b1799a9dc21a174e313d65bd19b88f6022f2009be6e404cc7",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7m-none-eabi.tar.gz": "3e27b5f8cfc2be73edc963529a92a077bc47d6a08518ab279a5de1cd02e6ccb5",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7m-none-eabi.tar.xz": "078100e6d739a786be141f387780f42d0d7a248803c66e51341d3ec8cf8ef269",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7neon-linux-androideabi.tar.gz": "8c677b7e69a9e0c2c67c8fb9d12075c573ef9a7f1f4c00d6f326f4ca9bc33b17",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7neon-linux-androideabi.tar.xz": "49ad860fd9dd866f3b1a698c5b05a1b7a61bc6fcd75cbba1d61aec13c797d0c4",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "320efa58b6066e0b640b9b93330f89f27a14cce490d8a5eafe33f1d3949de5f1",
- "dist/2022-09-22/rust-std-1.64.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "31397ee504b3d30854d70915d445d8d04361480b3297ce19069056d6009055b8",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.base-none-eabi.tar.gz": "d22c9248d92c1b09f7069ee02e85a6441a3751943d928b791e812890fbf9b2f2",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.base-none-eabi.tar.xz": "6a9b3358c082cb2a4fbbe7e784a3e49e80fdd126fd773aa95d510c444bd5cf7f",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.main-none-eabi.tar.gz": "3e94e4e529d5e1df27c23273fda38c6ad8e3d14e67278ece262cb7b74eeeab7d",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.main-none-eabi.tar.xz": "c57e0033ed685123d1a751f6b22569ad004ff2cb4c67c90c87aad7ba4b236851",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.main-none-eabihf.tar.gz": "09330542b62b03c82e56d5404bb79e9e88af9a693faeeb5bcdad1735df6c8ddf",
- "dist/2022-09-22/rust-std-1.64.0-thumbv8m.main-none-eabihf.tar.xz": "3834fc11d573847a74558124768c22e9c3d879be04f196d273bdf678513926b4",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-unknown-emscripten.tar.gz": "547457d0adef92008116afd1635b8abfd10fa7fd8d969223443dc905086a9e4b",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-unknown-emscripten.tar.xz": "d46d12e7b145c292f36eb1cbe87fdcdad03785431d1b1775b804efba6c0dfd2e",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-unknown-unknown.tar.gz": "1ecd99d7c8d568156957fcccb2d064eb8e1be3c309e216ce74c65ea549994d73",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-unknown-unknown.tar.xz": "0be660957c1367d554f9d3649538a26ebffdf2d24d5dc48630c4e4372df6809e",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-wasi.tar.gz": "d9bd33196e84f70dd67f60181aeee94a081406cac401c4ee613c16f82b99d963",
- "dist/2022-09-22/rust-std-1.64.0-wasm32-wasi.tar.xz": "388219deb87b5f6f673cc29fbadac4679c3c8d368147abba3c91e5491b09ca86",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-apple-darwin.tar.gz": "eb2f7c51f63973765f01efe509ccd2f26345d4bf0d77695adb4198a0899ae648",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-apple-darwin.tar.xz": "db5909b4b7544b2e1a5651c2d33be8a378e89ffee6b00d247c7cd2c5d115d83b",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-apple-ios.tar.gz": "7091a4133c652cc118e0b46116cbaf649777e79d1c91ae99151b6d390cfee45b",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-apple-ios.tar.xz": "1093cec3252ce6a9b742b961bf4490b2474dbf1d9614834381631c6bd016ba28",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-fortanix-unknown-sgx.tar.gz": "ae65fbd896e8d6ede58d72c86c6070570a63f6505fa1c6a5aed803419a53d1b0",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-fortanix-unknown-sgx.tar.xz": "ad10d74a47ec79b3300be10da2bb5bd3ba4b83f24be7c52e15f8d914578a1515",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-fuchsia.tar.gz": "4666bcd6009b9f1575ae9fed9bc7b0d9f00822fcd5c2dd9e55b6eed4222481c1",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-fuchsia.tar.xz": "c174539e3fee336168d88349d5fd0b77225bbc00f795a34de83cff7cbfcf40b8",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-linux-android.tar.gz": "9ea4213afa6c9b850116c18f2c461e105a5f907a96a057d3646040bfd22df180",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-linux-android.tar.xz": "80560adee5b2fefcde2a4179764d4e01972c2469da0f8b899bede69dfe649bf6",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-solaris.tar.gz": "711364829736f94401b05f5e2bd85ff48234c01fa17fa92fc593e937436c7934",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-solaris.tar.xz": "a4f68e996b83fb29fea28fcd4b0480c6df482408439f6b134dd87f47f2c03412",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-windows-gnu.tar.gz": "dcf87f97432adf7228e907b551d9b73f1ab16f79dc5da0724a227b7ffdaf57b4",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-windows-gnu.tar.xz": "af605be7aca0d4425863776331b0cf428c2f7fdbce899faea4cf2f09c12750ad",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-windows-msvc.tar.gz": "a374306ef4ac906a777e0631a5749d44360ff7cbe91a0df45c67a74ab2c0b7ba",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-pc-windows-msvc.tar.xz": "a075b165891b8f707da80f7ca316bd328abcba95727ca91ee504e9131a335224",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-sun-solaris.tar.gz": "904860bea5b3d578bbecf71000f7ae8c6034a959a0e6aba92aa29b4555741e6b",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-sun-solaris.tar.xz": "8004c8b1cf3aa1874ff6a163f15a4cdae3dd3eea35ef0182468285af342248d2",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-freebsd.tar.gz": "c91edba781ba56f35f2dba56a268d41866ea9bb5f6ffb9d342635f66b836898b",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-freebsd.tar.xz": "70878bf98440f616b14b325235c8e4434b65524532da335dc44474b19b6ebf80",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-illumos.tar.gz": "7dafef8daa72c7ed37208fa017d6b574e5c453cf6a291184ca94806a71705523",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-illumos.tar.xz": "3e7103ff4ab8263f6890b6726f33f08898541fa4ef7fa9c69d8afa39bde53181",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-gnu.tar.gz": "4d4c2715f816bc8ae82c2a5904106fd4dfd668dbd9a98492c8cd388bff9b0b5c",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-gnu.tar.xz": "6ace34bcbba9557aa2fc3a0515c3da4a83ca24d7d45506c5e1b32f589fa38a8b",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-gnux32.tar.gz": "99a0f82b626aee1ff0c2d0425a78398e2fe1ee448a63e45437bd0d0b6c5f21d8",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-gnux32.tar.xz": "14155beea7c65833fa4bc2a6baac52ae8f83c51dce7edf4797658c617d4865cc",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-musl.tar.gz": "243770414216f5c1891778a7bf0b865d28da1d49bfafdbfb45091aa1dfead9bc",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-linux-musl.tar.xz": "29af13a882abbe797fadd43afcb75bce2e2304438db9e21a3e64a2e9100501fb",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-netbsd.tar.gz": "e5b69cbdf7137e53d332ddbd0f6b6d22dc52163d4f50e81318ea01f82c67e5d8",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-netbsd.tar.xz": "bd4fdf598005d11f20db8fbd773f1c7124ba51ab373b35903e4a6750661dbd0c",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-none.tar.gz": "86e479e7ce264f3099dbf89eaabfef85ea7152f492cf14c23b90c05559014de3",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-none.tar.xz": "f48ab8a410a9142cdb9929c80475df6fde5d0c11b976785307e9a1e8b2044e56",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-redox.tar.gz": "65c5abdcad56554294ad7a4bec4124fc65e633ab76e50323c1079aaf33c62a56",
- "dist/2022-09-22/rust-std-1.64.0-x86_64-unknown-redox.tar.xz": "d8ae246352669df7aec4b43d2bb11fe095da4596533425424827c98a7d93fd4e",
- "dist/2022-09-22/rustc-1.64.0-aarch64-apple-darwin.tar.gz": "cc68733a81b1bac45bfcccb38412bcfb5c8d0abc3aa246fa9bebff7cf2be4826",
- "dist/2022-09-22/rustc-1.64.0-aarch64-apple-darwin.tar.xz": "6a040850c3c11d6a9aa3bf3544929009c9d1cfc3c7bf82799bed58c481b7745b",
- "dist/2022-09-22/rustc-1.64.0-aarch64-pc-windows-msvc.tar.gz": "152871f56d2c3dba43b069bbd0ddc9b1817965375144fea1d16242553f83cc1b",
- "dist/2022-09-22/rustc-1.64.0-aarch64-pc-windows-msvc.tar.xz": "121074f8bc41a58b0ec7e9e25dc8445f8c10f035cc320da9e97b2a521368cb7e",
- "dist/2022-09-22/rustc-1.64.0-aarch64-unknown-linux-gnu.tar.gz": "2347730846c1608619c100d41b8d292da002c050575eb8ab7885d478531baeaa",
- "dist/2022-09-22/rustc-1.64.0-aarch64-unknown-linux-gnu.tar.xz": "8f10b379bcc8caaab983b7d04a3f105dae42f95718f231b46d7e68685d239191",
- "dist/2022-09-22/rustc-1.64.0-aarch64-unknown-linux-musl.tar.gz": "af05a237f766d8d6828533ee169e19ed9886afa966c1a83546be6fa7e820310e",
- "dist/2022-09-22/rustc-1.64.0-aarch64-unknown-linux-musl.tar.xz": "880784ec231629e5244f3a9b80e49c60fdef9e360f519bcb9e2b1bf0ccfd24b5",
- "dist/2022-09-22/rustc-1.64.0-arm-unknown-linux-gnueabi.tar.gz": "9674c7794817e764e1bf55cfcfd5991f0c285a609137b960a24b75cce3fd7a9b",
- "dist/2022-09-22/rustc-1.64.0-arm-unknown-linux-gnueabi.tar.xz": "cf060d16c7aeb4e1c9515488f3a3514821439c044176c2c38987540351ceea36",
- "dist/2022-09-22/rustc-1.64.0-arm-unknown-linux-gnueabihf.tar.gz": "c0184fd0c9657b091809fa9de0ce6eaa923891f9cb7f39af7cb3606d0eb1fb90",
- "dist/2022-09-22/rustc-1.64.0-arm-unknown-linux-gnueabihf.tar.xz": "03475c9ee448e3e14bd3e7e75bcc61d2fed4c4a21f02d80c5574b9c2a859cc0f",
- "dist/2022-09-22/rustc-1.64.0-armv7-unknown-linux-gnueabihf.tar.gz": "81fdf1207dc5abb420d1e6c0f95f68ec717b183ee5c8dc25860f8e4432be7723",
- "dist/2022-09-22/rustc-1.64.0-armv7-unknown-linux-gnueabihf.tar.xz": "455ce33dd2894c451d921b5a1ca259732ab0b2e03a3bbc88a25b4d8d0f0833b0",
- "dist/2022-09-22/rustc-1.64.0-i686-pc-windows-gnu.tar.gz": "c5333399aeb53dfcfd57ec79c245c2f0d4bd1ba3813fcdcfb9d4eb97857927d9",
- "dist/2022-09-22/rustc-1.64.0-i686-pc-windows-gnu.tar.xz": "8c27aca6ebd973e41e0c402ed040be9e1bcd24c2127f6b1968fa6c40796b3ca3",
- "dist/2022-09-22/rustc-1.64.0-i686-pc-windows-msvc.tar.gz": "2b02f2e6bf7650890ddcd88e7cd15a6cc0a494b8653fcd788cda2127139e1224",
- "dist/2022-09-22/rustc-1.64.0-i686-pc-windows-msvc.tar.xz": "9a6257350a25c3d5d18d9f9ae937cb5ed7f46f070e698546ab11f5d9e8d85d96",
- "dist/2022-09-22/rustc-1.64.0-i686-unknown-linux-gnu.tar.gz": "bd805a90ec93aa1fd3f7b1d1f9339ac336c1350a31cb39f0506ba4da793bd3ef",
- "dist/2022-09-22/rustc-1.64.0-i686-unknown-linux-gnu.tar.xz": "3d604e150c469461a64c17b6d26f96a5a3d6975246c92cd13ee9bc6e4df0aaeb",
- "dist/2022-09-22/rustc-1.64.0-mips-unknown-linux-gnu.tar.gz": "ae5608caed9915aaa693b541106eb5e7f730deaad82694f7b699b41cee52f0f1",
- "dist/2022-09-22/rustc-1.64.0-mips-unknown-linux-gnu.tar.xz": "cb857587dfbbee9d2605093835a9dd261e021b37a87c42a6382224175c0493d1",
- "dist/2022-09-22/rustc-1.64.0-mips64-unknown-linux-gnuabi64.tar.gz": "8210e115343aac16e73cb938e8b2b0ed5131937db966b6fb600c0674a9c648f9",
- "dist/2022-09-22/rustc-1.64.0-mips64-unknown-linux-gnuabi64.tar.xz": "6d489dedcc82f201b356ed2ae8db91614eca8344791efe38b5d07b434a32bfc1",
- "dist/2022-09-22/rustc-1.64.0-mips64el-unknown-linux-gnuabi64.tar.gz": "5c108a9bfd8ac42d7cc7eadc76dc0a3c2b07c625c0603a0eb8d82b55d6957915",
- "dist/2022-09-22/rustc-1.64.0-mips64el-unknown-linux-gnuabi64.tar.xz": "9a2249057665460324a8c0dd9c269d783ecee69e2f513412be6cf9fad5d8f14a",
- "dist/2022-09-22/rustc-1.64.0-mipsel-unknown-linux-gnu.tar.gz": "6c338844bbda27edee4284fb7acf4b48b7d5ada3f2f5b0236af8a90a704bf17e",
- "dist/2022-09-22/rustc-1.64.0-mipsel-unknown-linux-gnu.tar.xz": "aeb1e24596ac507f1facf2d91cf8abdbd8a9e27da79820e5258be1024c5d8514",
- "dist/2022-09-22/rustc-1.64.0-powerpc-unknown-linux-gnu.tar.gz": "8c43c6868fe824b35d01357da91c111545f5143810d3ef5cd1e7e9d20ba2214f",
- "dist/2022-09-22/rustc-1.64.0-powerpc-unknown-linux-gnu.tar.xz": "5f4de96bff2937fc0a64a216604c7af765af94460a1f283330eddc610d91271b",
- "dist/2022-09-22/rustc-1.64.0-powerpc64-unknown-linux-gnu.tar.gz": "cb494af7e7cbbd8032f4f59cc0dbba1bb355adb3e5280a45a3b03e72451ed11e",
- "dist/2022-09-22/rustc-1.64.0-powerpc64-unknown-linux-gnu.tar.xz": "f58b7797371087800e4cb89807e7f346cc6eea9ab82a85e6f1088ad8369b01f2",
- "dist/2022-09-22/rustc-1.64.0-powerpc64le-unknown-linux-gnu.tar.gz": "f22636dcac8b16ad357da3a3f36382b277cb3fafbee9b34d7aecd9db3db40d9c",
- "dist/2022-09-22/rustc-1.64.0-powerpc64le-unknown-linux-gnu.tar.xz": "11630fc51fffe722e52f649357b5948c24b5305cfb61a8114527234e054451c4",
- "dist/2022-09-22/rustc-1.64.0-riscv64gc-unknown-linux-gnu.tar.gz": "3a59336edcb5e33a3532168cc672f140ea43277229c84955dd5ba7a856006c3f",
- "dist/2022-09-22/rustc-1.64.0-riscv64gc-unknown-linux-gnu.tar.xz": "5f3e69a185c7246773948ac97c053cf135d81ffdbf926d10a3339de93424f26b",
- "dist/2022-09-22/rustc-1.64.0-s390x-unknown-linux-gnu.tar.gz": "0555443cc4b7a69896171f2d886a8a2ab1ce91cff0763f7aafbc9567b0929815",
- "dist/2022-09-22/rustc-1.64.0-s390x-unknown-linux-gnu.tar.xz": "ac3facab7a17d7e7105178275b3186276e58a5202d91f451aa06cca2d0322bca",
- "dist/2022-09-22/rustc-1.64.0-x86_64-apple-darwin.tar.gz": "1201a655352c1a3ec6cd754e458d12eb0d69afdd1608b2813998d7bda1bb9dff",
- "dist/2022-09-22/rustc-1.64.0-x86_64-apple-darwin.tar.xz": "ea2e44d239492c1426b93c6b071d309a11f100bd0c76f92169883c8f27a567ca",
- "dist/2022-09-22/rustc-1.64.0-x86_64-pc-windows-gnu.tar.gz": "7dd40101913c9fdd707d92dae6ad709d90367aa4bc5e43bfc593fd5447666c01",
- "dist/2022-09-22/rustc-1.64.0-x86_64-pc-windows-gnu.tar.xz": "d38c3404648c1840861da51eb915d42c4c6ab7d12b456e9990dc7dec6521810f",
- "dist/2022-09-22/rustc-1.64.0-x86_64-pc-windows-msvc.tar.gz": "eb69517a2e0e5d93bdd27e24a8cf9a5fd0af8ed7bce0409bb19df8a007509a7d",
- "dist/2022-09-22/rustc-1.64.0-x86_64-pc-windows-msvc.tar.xz": "6a86e668a6111dfa72bff4e06d51b1264b92c9ac20ce7d64dc878f7e03a3fa5b",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-freebsd.tar.gz": "a6293ae73f2cf18f07c550a972135cef89979b9f6972e322596898058df6828a",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-freebsd.tar.xz": "2bfff1f69355252de14f6288bd78922f6d3bf93c4540708d22b6aeb9d7262fe4",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-illumos.tar.gz": "4b714e075756d29f6d1c57ce55a13d2d2788709fb4c55efa66f1a168ca94a1e1",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-illumos.tar.xz": "57f1be16d52a1843aceb8df7a882bdaae96606dc06c3af5e463b5c5c9ea11f84",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-linux-gnu.tar.gz": "5923a063408f2db09a0035da4ec699ee1ee35eb62c09c473c882ad77c42da0d0",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-linux-gnu.tar.xz": "1f5756a03119853b53358018c5b1592940a2354c3c9f84ee7faf684e3478f8f0",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-linux-musl.tar.gz": "e7570860b932a6950631ca5a0c4658787a3c56bbab701ba5a4162a7a23a37fff",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-linux-musl.tar.xz": "5177d749b5dcc74596e314b73c5f3f3eabed8b3e207f812f229fbf0682c162ae",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-netbsd.tar.gz": "29689b4eff49d494ef56850cd22130dbd098928829c72a0b5423a02aada846a4",
- "dist/2022-09-22/rustc-1.64.0-x86_64-unknown-netbsd.tar.xz": "0b6b9e0580078b30a9795b9b116197e7cd2e873c20107dffdb4f775cd4155264"
+ "dist/2022-11-03/cargo-1.65.0-aarch64-apple-darwin.tar.gz": "40858f3078b277165c191b6478c2aba7bf0010162273e28e9964404993eba188",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-apple-darwin.tar.xz": "71013b8d491a355d0b88a97c9c47e50817cf1b506fc8507cd644d2225ec76356",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-pc-windows-msvc.tar.gz": "5b5b684e028b9a024c137974a4121b355f016d644c635a6d0f4d29814cd1c9d9",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-pc-windows-msvc.tar.xz": "b32487855fb9bafc58c423d62b52d283af100ab8e8519ce8a0d406adbfe7ceaf",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-unknown-linux-gnu.tar.gz": "406d244def7ea78ed75ca4852498a1b632360626fb5fec69a8442b14ef04aee8",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-unknown-linux-gnu.tar.xz": "3fd483c0d58673ab69862824408c8a48612827ddcdeaaca0f8fbe5ca02214a4c",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-unknown-linux-musl.tar.gz": "43cb587b766a892d9c474f0a04417533d6c12e085ba07af8e27853d41afb4f91",
+ "dist/2022-11-03/cargo-1.65.0-aarch64-unknown-linux-musl.tar.xz": "5e9880995c5a8f247a2d8ee143183f45feee1ec09bad5e147c837518f01591e4",
+ "dist/2022-11-03/cargo-1.65.0-arm-unknown-linux-gnueabi.tar.gz": "25c783ec2a61c127215609ae5e45ca11de938cf8e1e163ccdd422be2b245414a",
+ "dist/2022-11-03/cargo-1.65.0-arm-unknown-linux-gnueabi.tar.xz": "88b14f59d8dbc64c093100a2748f5392510b480ac4b05a816a85b50030b90db1",
+ "dist/2022-11-03/cargo-1.65.0-arm-unknown-linux-gnueabihf.tar.gz": "1793a5773d24d6e4685870a6e47de3f764e74d35f85bdc0d3e888be0efce6a54",
+ "dist/2022-11-03/cargo-1.65.0-arm-unknown-linux-gnueabihf.tar.xz": "e3b82e61a5bbf6338555716d8e925cd0a96e4fc0ae262dd04bec009a46aa6051",
+ "dist/2022-11-03/cargo-1.65.0-armv7-unknown-linux-gnueabihf.tar.gz": "fcd2a151adebc87fddebb710d7c7606f0aa77245bb45ec05f8b600cd30008687",
+ "dist/2022-11-03/cargo-1.65.0-armv7-unknown-linux-gnueabihf.tar.xz": "a27a726733230bff2807109fdd619ccd04d3e96e22ea53d3e24552524619ec2f",
+ "dist/2022-11-03/cargo-1.65.0-i686-pc-windows-gnu.tar.gz": "894dc627e3d5a597ca8c6aa5d0ef55f2d9130b14dde19df193b41242e605a31f",
+ "dist/2022-11-03/cargo-1.65.0-i686-pc-windows-gnu.tar.xz": "e462df98c630ab06196d27a2a631bbf12da40f8cb0d40028368205e1dcdbe978",
+ "dist/2022-11-03/cargo-1.65.0-i686-pc-windows-msvc.tar.gz": "d8d9ec39ba20f8d0ad37a2c0791008631e6ac6efc419bc9543a65785db097c5a",
+ "dist/2022-11-03/cargo-1.65.0-i686-pc-windows-msvc.tar.xz": "2994d66f1644a7a0d814cec9d619cca204adeb2af81cb03759f168044d9bf4ee",
+ "dist/2022-11-03/cargo-1.65.0-i686-unknown-linux-gnu.tar.gz": "b58b88e7dbfc7b570df1ec0f7be75c318ad8e99ff1e66f4154827b2c81eee3d2",
+ "dist/2022-11-03/cargo-1.65.0-i686-unknown-linux-gnu.tar.xz": "64d456a303d6f1edf0bd9807089aa71ef065705b9dd7d115faff5c2d431e78cd",
+ "dist/2022-11-03/cargo-1.65.0-mips-unknown-linux-gnu.tar.gz": "602458e1f1669d0a0daf5edd0fb0f9aff24891357e2eda12fcef1b2bb56d95c9",
+ "dist/2022-11-03/cargo-1.65.0-mips-unknown-linux-gnu.tar.xz": "f32903493610bb5b2302139bf37120159b848223cdc23da546e6fae7e8e6cbfc",
+ "dist/2022-11-03/cargo-1.65.0-mips64-unknown-linux-gnuabi64.tar.gz": "b9a484868b89cc435dc65bc545ec89126d12a9a76a477a13263bcda2f1572f57",
+ "dist/2022-11-03/cargo-1.65.0-mips64-unknown-linux-gnuabi64.tar.xz": "453e95cc057583057c2239539425a4e57d80e38ba00288f09d04fddcde2548af",
+ "dist/2022-11-03/cargo-1.65.0-mips64el-unknown-linux-gnuabi64.tar.gz": "ca75879b45e7768b6be0d5809e41cc82783f9db4ce7f670966e665ed843a65e2",
+ "dist/2022-11-03/cargo-1.65.0-mips64el-unknown-linux-gnuabi64.tar.xz": "594c03b8e6e6a7f3d38cf655591d63c24ed2ab5ce14ace41f1f2c1181c9c09ca",
+ "dist/2022-11-03/cargo-1.65.0-mipsel-unknown-linux-gnu.tar.gz": "01ffeeaf5cd1837810580ba2fe7c74354cc25cb7a0a6858e815dfad6aa5e3fd8",
+ "dist/2022-11-03/cargo-1.65.0-mipsel-unknown-linux-gnu.tar.xz": "a80ca689ce20508fddb6274e2e5f69a59a5b8e1a1272f840d6b1ca60f83dcccb",
+ "dist/2022-11-03/cargo-1.65.0-powerpc-unknown-linux-gnu.tar.gz": "ac9c7bf7e7c38ef6a14e72ddad5abe9592ebbdd9d80c4c5ce59046fd790260a6",
+ "dist/2022-11-03/cargo-1.65.0-powerpc-unknown-linux-gnu.tar.xz": "cc309119f4157f3cbdafe065d07bee7de5f262da998854e02b2d8f9f425dce73",
+ "dist/2022-11-03/cargo-1.65.0-powerpc64-unknown-linux-gnu.tar.gz": "3aab12cb517b9d27feb0d43fd24834af627a4556bf8760937a77429fe9087592",
+ "dist/2022-11-03/cargo-1.65.0-powerpc64-unknown-linux-gnu.tar.xz": "32fac316c0676e395fa3c87ad4222d3c70489278da4c6986ee30406df6e6eb4f",
+ "dist/2022-11-03/cargo-1.65.0-powerpc64le-unknown-linux-gnu.tar.gz": "aad8a7e6df87d81e2e0c2913670547dc65672434c23d32811da307ec4b767f59",
+ "dist/2022-11-03/cargo-1.65.0-powerpc64le-unknown-linux-gnu.tar.xz": "9393de910df7cd6947e380460a1144ac2373a36c776c7367a81212a51a92d9a7",
+ "dist/2022-11-03/cargo-1.65.0-riscv64gc-unknown-linux-gnu.tar.gz": "913289a36696a53e642bd247d7d78920809c5db6300a3181064b62c82a0444b3",
+ "dist/2022-11-03/cargo-1.65.0-riscv64gc-unknown-linux-gnu.tar.xz": "fdc9be1d0552179318c588e8eebebfa42fcf5eb65d58b93ba2949d9b5718b429",
+ "dist/2022-11-03/cargo-1.65.0-s390x-unknown-linux-gnu.tar.gz": "ca3f9db0bf5bc244bdc225eccb54f9a0b2663ac92e374e33c7c8d6d9339f6b78",
+ "dist/2022-11-03/cargo-1.65.0-s390x-unknown-linux-gnu.tar.xz": "bcddebbf39443e62d67e35b3c669677442a551dbfa1f172e2405368cc571e555",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-apple-darwin.tar.gz": "40cbbd62013130d5208435dc45d6c91703eb6a469b6d8eacf746eedc6974ccc0",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-apple-darwin.tar.xz": "906a656ea12808065da0702082fb08d010f0d51f61148887068ac44613c07ebc",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-pc-windows-gnu.tar.gz": "79819a7e5ade380a36cb7bebf8922034802891333bf85c1d0e194b9b70c7ff4a",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-pc-windows-gnu.tar.xz": "06f51741e03f9ba458fa774c705f078a5bba36f2f5a990e555c710a4b39a9eae",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-pc-windows-msvc.tar.gz": "2932be27a0ebea2d36a30c18b758a7f90582fcb8bc675a225d661e611e57afb9",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-pc-windows-msvc.tar.xz": "a0ef427322ac3f41d64f935655942a7dcf7e40bbc7d4f82600087f96d02de4c0",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-freebsd.tar.gz": "a896973695382f4c622b98544f6126c088b21d6a625c129131b113ac36d777a8",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-freebsd.tar.xz": "b12447bec51998ca618710de0f72fdf728c881de76dd28133ead22758be70de1",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-illumos.tar.gz": "a1f391d8d3a819e4c217ab6a12c864cd0af69255ca653566320dbef5eefe0769",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-illumos.tar.xz": "e357c8cc226a1985649c1bec88c1fe9bb0a860d01c530e5692726739fab3dfad",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-linux-gnu.tar.gz": "f7d67cf3b34a7d82fa2b22d42ad2aed20ee8f4be95ab97f88b8bf03a397217c2",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-linux-gnu.tar.xz": "82547aacaf42fc3c2970ec31b96751dfbeba3dffe1a042a3780bd670c29a89bf",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-linux-musl.tar.gz": "43a7154520914663c0d291284621e40cf116ad3b5fea6274ea7cfdd4b9e7368f",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-linux-musl.tar.xz": "7b2b3632205310b867d8d70403aa7ea3a879972033442628fa59483e4ecf0d8b",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-netbsd.tar.gz": "fc41c57eabf4a601bdfd78b8586f0e639404305ca0b61ad62284be4623394de3",
+ "dist/2022-11-03/cargo-1.65.0-x86_64-unknown-netbsd.tar.xz": "1567ef1c6ca630fc03125cf4560dcb4d4d2cf1cdcd23ef8b1ad7ec7fa4881693",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-darwin.tar.gz": "68316299635d2577af3b64a2de4839a107f6c33f92e9427d6127526d12ecf07f",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-darwin.tar.xz": "c467c69df0821daebc02be91ac012e4e930ac8e9ef8bdeebf3f04cb5517cc7b0",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-ios-sim.tar.gz": "34061a4772a1054803ea26ccddef78f8d4f654b6c00b328232df7fb4f68c0b20",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-ios-sim.tar.xz": "28c94371a7e0f842bd75af8107e3e6c1e057a2500f1fb81fcc2436700559542f",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-ios.tar.gz": "7707c1fd458a72cedbb62cd0060043eabe6d0f6b66f9d73f2453f502231df85e",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-apple-ios.tar.xz": "d47d58f2ab066002fea4f75184ae9ec1eede3a3636e4948d564c6511d2e85fb2",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-fuchsia.tar.gz": "b4798d4b55b8b8423a1cc870118d2972d057439bbfa2b80f28a83fb2ca242f74",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-fuchsia.tar.xz": "12f2213e0451336a6e9f35b13bf51bdbad445c53cad52cb86577b831d6fa5feb",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-linux-android.tar.gz": "a948302c50dc0960a1eeaf564cead55bb9d1228847e4c396a244e1f9cdc9a14d",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-linux-android.tar.xz": "aa7a9537f10b7551711c0a70d8f632ed6416f442749e508a1fc698a47eb34308",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-pc-windows-msvc.tar.gz": "c14710a87c532cd606955a7c3021a75d4f7a3be2cc05211452df6ae00b9205f5",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-pc-windows-msvc.tar.xz": "1aaa57c35d2a3b52123a02daf85e741b525721bbb2eaa5722388a1ddb9f6fe68",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-linux-gnu.tar.gz": "86eea00f31fc4cfe320624b38547d1850efb3c890ed00e73b39f725803c4c755",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-linux-gnu.tar.xz": "735b681c8a6e60925c76d6cc899e78b4cb4562ada24a1f265b2021c1faad78ad",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-linux-musl.tar.gz": "5136887db2170733bb40b18be597e0ac9474fac030d7344c4517b38b0c98c70a",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-linux-musl.tar.xz": "9ea488da40c347826cce7e238847c745ee566254bb1d077412673f8243fb1cd2",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-none-softfloat.tar.gz": "f9c09c55883181e09f5d169e210e8bc15d55c459b4c187e4987969429e076980",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-none-softfloat.tar.xz": "b52417af1f9ea204cc20c66f486c7233a1e1571243dd38630149b79b7ce2c825",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-none.tar.gz": "3be333d58f33e5790586b20b369bb1110e3241d14c42282720f80107d6e0df6b",
+ "dist/2022-11-03/rust-std-1.65.0-aarch64-unknown-none.tar.xz": "8258b2773dc1688826c126e01b138be10c22a43137ebf091f0a1938fee8272f5",
+ "dist/2022-11-03/rust-std-1.65.0-arm-linux-androideabi.tar.gz": "beffe3e8ce63cd9a2f8cf26cdd9dda2c1178d50c8612009e36ef3d40e845ea9c",
+ "dist/2022-11-03/rust-std-1.65.0-arm-linux-androideabi.tar.xz": "5379cc9c176bc708bf3d8d01f101514267cd09cc055e9b68d741b40a0302c396",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-gnueabi.tar.gz": "0802275835c36a936031a1da78e11c8070e3fa7f699951977bc0463748805d07",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-gnueabi.tar.xz": "c8793e77ef43336bc372a7a5b4720d5449e92577c7875471c2bc40ddbfde4811",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-gnueabihf.tar.gz": "cbbd549a619cf13c413e1954ed8dca72939e583a34b59076e1fb034e4e04dc24",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-gnueabihf.tar.xz": "f7d5eb17dbe46ee9d3c4f9fcffc07b8e3311c747545402c8d3b5c43043f27288",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-musleabi.tar.gz": "90ee725d476587abfea627f3e6ebda3073f44fdc1af53d2fc2e71a27f7ad38d1",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-musleabi.tar.xz": "453a1443e4753611dc4e6969e50ad8d7984a31d1a457729a860599ed19b1de7a",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-musleabihf.tar.gz": "1b170a4206d7de4fdfae965c5d41b29f6d44f117c5ed8c691270d54ad82e98a4",
+ "dist/2022-11-03/rust-std-1.65.0-arm-unknown-linux-musleabihf.tar.xz": "32d7f301196d73027fb9a5ae595dbadacdc234307c36b4a175a132e75318e38c",
+ "dist/2022-11-03/rust-std-1.65.0-armebv7r-none-eabi.tar.gz": "e7411233c42774111cbecd5e7f833cc552e4e10047ef368835fc6bb6779bd62a",
+ "dist/2022-11-03/rust-std-1.65.0-armebv7r-none-eabi.tar.xz": "aa0052fc3904d93ba4f107f49e16849118108390cb1152f17323cdc2bd559b1e",
+ "dist/2022-11-03/rust-std-1.65.0-armebv7r-none-eabihf.tar.gz": "c85f7d61c3a9d4930005e5f054b71145aa6da207ad6b3cb10b7f65514adf0f54",
+ "dist/2022-11-03/rust-std-1.65.0-armebv7r-none-eabihf.tar.xz": "2d43f8c1a80a9713955915388cf00756388ca0423930839b22bb0687efa173ed",
+ "dist/2022-11-03/rust-std-1.65.0-armv5te-unknown-linux-gnueabi.tar.gz": "e4410b54c63eab57e234a5c230744b3bb63704e012d503bb27ea27e47b85afb1",
+ "dist/2022-11-03/rust-std-1.65.0-armv5te-unknown-linux-gnueabi.tar.xz": "d079e841be640b4ce26aa821f29bc813243a7c0af7b8aca8ca4acf5c2e5b722f",
+ "dist/2022-11-03/rust-std-1.65.0-armv5te-unknown-linux-musleabi.tar.gz": "8897a7c3df9cad8d5686c7c0aa5475f82aa3e94de2f8ff7184fa017e94da96dd",
+ "dist/2022-11-03/rust-std-1.65.0-armv5te-unknown-linux-musleabi.tar.xz": "1d11ab1d60070ae30ff87b55dca077f4d532d814a9ab7bc77055b5b429a78c6e",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-linux-androideabi.tar.gz": "c7b9649ff1ca1accf8a0f109eccafdb8c5746596b77253bd65c856b616ab02fc",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-linux-androideabi.tar.xz": "da55725498ac8af64359e7c2a46f225dbaf647e1254f648b1f150a3a10a0de94",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-gnueabi.tar.gz": "2b2962822322e6c361bb1213f95fb17ac87aefc0e369ac7de67d7d31035092ef",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-gnueabi.tar.xz": "c14268337c69650a2618909d8e691489385d748374d73ab8d6a2f9d6b030d70d",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-gnueabihf.tar.gz": "616714d28c5c4c0273a22cbc18179ba5354d2e3f4dfc300024266c46b4f68127",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-gnueabihf.tar.xz": "fec73401941bffce3b6913d31955f1291119dea119c0051d94f271ae7c959d4c",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-musleabi.tar.gz": "c920e0c288d08be499efeafeb1d52f6c30c6abeca57f09d57190292af21b9645",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-musleabi.tar.xz": "0b5bc219333e3e983fb1e7e86a0c268c4a52ccbd6326a16785be9d9017d97e9f",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-musleabihf.tar.gz": "da790276100bf066127987bb7964325379ef249f887d17fd3e26bc1628700a8f",
+ "dist/2022-11-03/rust-std-1.65.0-armv7-unknown-linux-musleabihf.tar.xz": "9368527053c4bab0fd320209b45f0278d0a1e54a37006a56a6e565404ab73fef",
+ "dist/2022-11-03/rust-std-1.65.0-armv7a-none-eabi.tar.gz": "f687d4efa0e494feb97ee2103dd2d3149af54d4751c3327d26fea71711ecc464",
+ "dist/2022-11-03/rust-std-1.65.0-armv7a-none-eabi.tar.xz": "4a157c9d23367be9a16cb0ea667f80ee85f2aa4ca549fb0a893f40a846927db7",
+ "dist/2022-11-03/rust-std-1.65.0-armv7r-none-eabi.tar.gz": "cfa95c5ebe1183f5d2fc1d05676915a35fb0234085c7a7ff20da822d8fb3b03c",
+ "dist/2022-11-03/rust-std-1.65.0-armv7r-none-eabi.tar.xz": "b5e9a895d2f59da805453435ed827a957ef131ef465c139456360c5c9ebf86f8",
+ "dist/2022-11-03/rust-std-1.65.0-armv7r-none-eabihf.tar.gz": "e18afa534abd57c7cc8827cabd60e87710299817f4bfdd75699e2f200952d6f3",
+ "dist/2022-11-03/rust-std-1.65.0-armv7r-none-eabihf.tar.xz": "25ced4ebecd8da057b74c14bfd810d645454959f58677c32d5d0b3942303f13b",
+ "dist/2022-11-03/rust-std-1.65.0-asmjs-unknown-emscripten.tar.gz": "10387374e52db6232723a7f71327a130f88980f063b26ffc0a9b450b2fb7d67b",
+ "dist/2022-11-03/rust-std-1.65.0-asmjs-unknown-emscripten.tar.xz": "0b28c4673f2e4006732dfdc1085c754e9c94c82a8c3b2afda17981e87c5cfaf9",
+ "dist/2022-11-03/rust-std-1.65.0-i586-pc-windows-msvc.tar.gz": "3e5c4634045d67fbe710ba77c78b257b58bc74d51d2fde9c25e018676d190da9",
+ "dist/2022-11-03/rust-std-1.65.0-i586-pc-windows-msvc.tar.xz": "d81357c4b1b814f8bde8e3d5fc039fa7e9072c9f15aa75e129e98d37eb9f4675",
+ "dist/2022-11-03/rust-std-1.65.0-i586-unknown-linux-gnu.tar.gz": "2813d22ea020ff3ba737762b19d03e4ede5713d4ffd5222c70f798016019963a",
+ "dist/2022-11-03/rust-std-1.65.0-i586-unknown-linux-gnu.tar.xz": "533eda439eb5ffec258b8219445742d6d60570040b3ff167291e3d0d985b9d70",
+ "dist/2022-11-03/rust-std-1.65.0-i586-unknown-linux-musl.tar.gz": "415c09908b8a38841221e4021d428262e6c394cebc82af32f091bcfbf849e1e2",
+ "dist/2022-11-03/rust-std-1.65.0-i586-unknown-linux-musl.tar.xz": "7f5d9ae65827aef1a51676927a4c9533f942021d2fd45fd93b23dfaa738ee205",
+ "dist/2022-11-03/rust-std-1.65.0-i686-linux-android.tar.gz": "c6cea8b87db4c2b56e02a0a50e5906f4cf73cffe78cb282cc6f5aaa2e5daa78f",
+ "dist/2022-11-03/rust-std-1.65.0-i686-linux-android.tar.xz": "85c9f5f8b165e76876f95f3423adb8260f8c7fe4fc8ca15660ae870cc2d53916",
+ "dist/2022-11-03/rust-std-1.65.0-i686-pc-windows-gnu.tar.gz": "9ea4072ebf97349fc0b34e27cb9c2e03d2b508b07d21edaf74a25e60f7d7853d",
+ "dist/2022-11-03/rust-std-1.65.0-i686-pc-windows-gnu.tar.xz": "c0f6c117faec7b4d8c4cbe0a252604ff45dcadacb3b75fc6b9e67671d0b878fa",
+ "dist/2022-11-03/rust-std-1.65.0-i686-pc-windows-msvc.tar.gz": "139f947a0d85702c61efb294aa0353768dc7b96c014dc5a092979170507f37d9",
+ "dist/2022-11-03/rust-std-1.65.0-i686-pc-windows-msvc.tar.xz": "33f36a6b82ed2dd9a120d503d3701807db12d482144813fb6eaa4f5ca03f425e",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-freebsd.tar.gz": "e0ae8dad99b48ba9525e07351bdc53ea6ef3a88b268b68be5092df9a84b89cbc",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-freebsd.tar.xz": "016666bdc2cb3b3d994385ec7f73e8bf59491d226818757cc8dafc07705ba45a",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-linux-gnu.tar.gz": "8f3c90a21494b90e7f7bb16ee8f0b170b4d63389b05ce6c158eeedf5904d51fb",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-linux-gnu.tar.xz": "99bd62d593a6ab3205cab7f06b5793a075b9d05d868e927a6948e46269d61e82",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-linux-musl.tar.gz": "f29068870b8ce028a13b4593add734c120ca9bd08dfb6826701a9e7fccd5e1ae",
+ "dist/2022-11-03/rust-std-1.65.0-i686-unknown-linux-musl.tar.xz": "644a4c57c1392f776c5ebb13f9832778b69464391b3766e6bbd18c3aa11787a6",
+ "dist/2022-11-03/rust-std-1.65.0-mips-unknown-linux-gnu.tar.gz": "83cd534c97c44b3cda6eb2b5bc1259906cd7b7c4711950d62816736eca82eff3",
+ "dist/2022-11-03/rust-std-1.65.0-mips-unknown-linux-gnu.tar.xz": "50c65a8effc85aa89242ba0a2a2c89bfcc4d0a39dcb42396d10b0036b9a4e90c",
+ "dist/2022-11-03/rust-std-1.65.0-mips-unknown-linux-musl.tar.gz": "ea6c59b68367159e64af476035ef8b94b322f2246a453ac1ed475a990dcead55",
+ "dist/2022-11-03/rust-std-1.65.0-mips-unknown-linux-musl.tar.xz": "3bc5043f4eb7bb6418708792ee8e777197e562d03843a9adf62ce245ba07289a",
+ "dist/2022-11-03/rust-std-1.65.0-mips64-unknown-linux-gnuabi64.tar.gz": "5b163bc93b6fb649668b7dfda6afed48e35d29cb67e05baba59e109b96e77404",
+ "dist/2022-11-03/rust-std-1.65.0-mips64-unknown-linux-gnuabi64.tar.xz": "338c702b79dac33e32dde097084dd38852487d2976c5eb66b44ba8fc8319342b",
+ "dist/2022-11-03/rust-std-1.65.0-mips64-unknown-linux-muslabi64.tar.gz": "7a6ab5c7cd4c6c5c63a118750867f0c4410c862689cdcc7440937d00639aa9d5",
+ "dist/2022-11-03/rust-std-1.65.0-mips64-unknown-linux-muslabi64.tar.xz": "9450745a5e678c9b7e65ecc7d6a016f92d8d22d8091c4a77431b1e58b99a435f",
+ "dist/2022-11-03/rust-std-1.65.0-mips64el-unknown-linux-gnuabi64.tar.gz": "1efc00ec863d21be4b1f097dfbc206fceee31a9b2ffcaff5230ba42e29ffdb04",
+ "dist/2022-11-03/rust-std-1.65.0-mips64el-unknown-linux-gnuabi64.tar.xz": "a0a0e60a0e850140194250fbbfb962c322d4f474f4ec22d03b7f537034257c09",
+ "dist/2022-11-03/rust-std-1.65.0-mips64el-unknown-linux-muslabi64.tar.gz": "91270833ad6cdadf7bb406e175906e8e5c8431caa5fc3cfc10cc40163cb14578",
+ "dist/2022-11-03/rust-std-1.65.0-mips64el-unknown-linux-muslabi64.tar.xz": "0862706d22dcfee39b0d2df874dd6065d8c3020c0b8974f6e7b694edd42413ae",
+ "dist/2022-11-03/rust-std-1.65.0-mipsel-unknown-linux-gnu.tar.gz": "646398fdd4ee9f5b9a96aee16c615a4f32f77f2bcdc7ee2a4f5f2274cf1d6b92",
+ "dist/2022-11-03/rust-std-1.65.0-mipsel-unknown-linux-gnu.tar.xz": "79e078420f7c45fd1cf38b70620ced50d35ddb1621736b65be987c20481fe5bc",
+ "dist/2022-11-03/rust-std-1.65.0-mipsel-unknown-linux-musl.tar.gz": "9db41968e4f025fb9c049a6db88fc1b785503ce161e77f2879f795f422d83f7b",
+ "dist/2022-11-03/rust-std-1.65.0-mipsel-unknown-linux-musl.tar.xz": "482e9245873338a08f47ea2c29683134b8813deb3e3eafb78b786d34bbecce51",
+ "dist/2022-11-03/rust-std-1.65.0-nvptx64-nvidia-cuda.tar.gz": "28e3eecde27c015f854a93f44a4af86efb59f7a0c9800a77b91edeb50d08f571",
+ "dist/2022-11-03/rust-std-1.65.0-nvptx64-nvidia-cuda.tar.xz": "1aeb2f90c2b15d835fadf0c3874bea8a1af740b8ba4b802eb6cbee4496f5357e",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc-unknown-linux-gnu.tar.gz": "7c1f66581e7024e6e3ecd69db878defd5ea4a88b8b049ffaf62965ce9d652b15",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc-unknown-linux-gnu.tar.xz": "672b9ea8018dcdf7d5f79f5298bacc34e7600a082727b4f1a20c14251752aaa2",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc64-unknown-linux-gnu.tar.gz": "f3a25b84be74da0455f6e85c9c1d189ce1cd660e965c6bc7d1018c8fdd31e597",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc64-unknown-linux-gnu.tar.xz": "8a26e08908156ae5a05c64c2732435ef4efb994a2ac6d0b2e9c93c0dae19d089",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc64le-unknown-linux-gnu.tar.gz": "b66b5d04ad9627003b6658399e22ebf758cf6c6ce4b38ae0829cc3817402d776",
+ "dist/2022-11-03/rust-std-1.65.0-powerpc64le-unknown-linux-gnu.tar.xz": "ce18b44300f7d5d94856cef5b270ba010061fafa411beb9782207e26cbab88a6",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32i-unknown-none-elf.tar.gz": "cd0eeecc284385a66f6c217467cde74ce450b02b6ac3418989ed452e1d9fa56e",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32i-unknown-none-elf.tar.xz": "19cdc94ab99fd668cfd0697ddaf38989ab6aa8b6a317291fee87911c4879c09b",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32imac-unknown-none-elf.tar.gz": "a7dd667b06ad75fd6027b2cf34921c57d3419b1e63ee687085af6955a0d79d9a",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32imac-unknown-none-elf.tar.xz": "5d61b0ab7bc4f065279e131aac33d64d2c2f5c5f6ad356f45278340bdb3ad223",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32imc-unknown-none-elf.tar.gz": "9ee81f4c10602eab12d4ab0048e2a3aea8a557bf0cd4e5274a344c2f9ba2ec27",
+ "dist/2022-11-03/rust-std-1.65.0-riscv32imc-unknown-none-elf.tar.xz": "b73be7b808403390cd81c53e46d117be3202c4e97c69dfc7a7e4e34fbe3c0b47",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64gc-unknown-linux-gnu.tar.gz": "ee47cf94cd4fd130a233518236f49b742f7f29bb66e2256be23ba71a292430e2",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64gc-unknown-linux-gnu.tar.xz": "fa99f123ce14f1cda245857b50fd4709adee960e7d36ce663b87c13aee18b64b",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64gc-unknown-none-elf.tar.gz": "55459a12f4f2a3cdc7c050febd26365fb5326db62243b406349eb87783d177b3",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64gc-unknown-none-elf.tar.xz": "8f1bfe6264930035324d4c497bcd1af70bf6c302e470cc96b9103c6c57930264",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64imac-unknown-none-elf.tar.gz": "fdd2b1bbee188a1fd74f700096b486fc659c9d29c5f7f906aa2958d4dc95ec91",
+ "dist/2022-11-03/rust-std-1.65.0-riscv64imac-unknown-none-elf.tar.xz": "04f970b1b643049dba001459075609368203add0b00de797fbca53384c8895d9",
+ "dist/2022-11-03/rust-std-1.65.0-s390x-unknown-linux-gnu.tar.gz": "f3ea601929249df63d207883a3777f0def4e84f4e7c1cfe12e3f7872e3f20996",
+ "dist/2022-11-03/rust-std-1.65.0-s390x-unknown-linux-gnu.tar.xz": "a3f6740be345364f4599ae837d2401e0f31e5d33a4f958852d12a384ee581a83",
+ "dist/2022-11-03/rust-std-1.65.0-sparc64-unknown-linux-gnu.tar.gz": "f58ed6eba451802d5ba37ce1455266317863fdfa04096e0ca8f2cb25488083bd",
+ "dist/2022-11-03/rust-std-1.65.0-sparc64-unknown-linux-gnu.tar.xz": "fc2a8816665f464d3085dcd379c44b9de0ee1f1084fae0a4c32c57754b27992b",
+ "dist/2022-11-03/rust-std-1.65.0-sparcv9-sun-solaris.tar.gz": "021fb2b640e88717b32356d738a1385cf41c860fdec5830045d026cdf11261de",
+ "dist/2022-11-03/rust-std-1.65.0-sparcv9-sun-solaris.tar.xz": "7941668a20b44d293485a0c8369f46a1cb6f29fa976fb1644097897723447960",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv6m-none-eabi.tar.gz": "f8de6b8de74bfdb20921be1f61df7b018e29b4f94829d951004ddb82b9062086",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv6m-none-eabi.tar.xz": "f9b28bdb16e33343e4dbc66921a295f42371273f147c30d76552cf7c97fc15a0",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7em-none-eabi.tar.gz": "b1e9b2f38f8197236efa70ec75de87dd5503c466c8a9bdd14cd54144ab26ec74",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7em-none-eabi.tar.xz": "862f08bbfc281b6f8417630f59670dadd22d49e4fb98f0dd153d2b81e2e39c5c",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7em-none-eabihf.tar.gz": "4afecbf8043a574388c82a28522317dcbc332f585364572fae0dc41bf19f2aee",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7em-none-eabihf.tar.xz": "609f8625e4397903173cd330774c2116d096a1d7a1539afa479a15b9e7961406",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7m-none-eabi.tar.gz": "543a6365bff2f8038c41b144f02cf353c0421241235a9a431b379f53a758c95f",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7m-none-eabi.tar.xz": "878de0ce07f95c8e2837350af17b0d75a1e759d150917a95aa966284f36d104b",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7neon-linux-androideabi.tar.gz": "c1b5a05d36bdbbe3bbbfb1de2566969e3a82c61182fd74691362f8187e3d5622",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7neon-linux-androideabi.tar.xz": "20b23a5b2ec299506b402921841afa5a948a67769749a59646d100f43ca4c206",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "1102d8d4f3cea919ffa97655120f312dc4ec52c86918966f87c0145a055b4a5a",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "0996cdb1f05ae6df6b26f3c2798bd72727952a73a5fa2a8e988ac992e71fa584",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.base-none-eabi.tar.gz": "266ce748b7d7bd241547ce1a9b9c27971580e0706dbee58550d2207fb3d97f91",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.base-none-eabi.tar.xz": "d1fb5e2a653d6d98d6608ceb2ecb16f4379b791c2c81c03f4bcf4c23d70cab3c",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.main-none-eabi.tar.gz": "7222393cc74402a855ba16496620d1ec92a4c3154a44660f3ad0333a4e40b872",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.main-none-eabi.tar.xz": "f6b16ca290d003fd45d2bbea740a5b9803aafc8baa76dedc29074e6eebd07289",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.main-none-eabihf.tar.gz": "17f534931cbc4298a4c2df6677d220989e3dcd3a50edd40f8d1e9113118f198a",
+ "dist/2022-11-03/rust-std-1.65.0-thumbv8m.main-none-eabihf.tar.xz": "1b22f23d4ee80a8c586a84acd988a550dc2b137ce8c624d48c2b44cfd93f1675",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-unknown-emscripten.tar.gz": "d776bc36af79f99582fdd7b559e6f692b7f617b7f83a47f369fa433f0f2b49fa",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-unknown-emscripten.tar.xz": "f9aa938f2c664f885d3eafad45519ba759ebe3631d62d953a2670174bb90517c",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-unknown-unknown.tar.gz": "177a35ce65f969127bbd58ef08e24471afb2c638a811104c493699a23f5e0006",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-unknown-unknown.tar.xz": "e5190436f2a0c7fa6f2b03bfbfd9c2b44a0de499533b6491f0ec05f08e9cbb6b",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-wasi.tar.gz": "5972f8bacfda0ed5e02b0b9a76ca3f6ed8f5f3d4c11d9ff42bafc8833c744b5d",
+ "dist/2022-11-03/rust-std-1.65.0-wasm32-wasi.tar.xz": "cfb55d6d29200a14cd2764a83d513cc85e45a79ed82f2916a7c6f06d10fc1d31",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-apple-darwin.tar.gz": "6b832ef5e94dc9d21c00b5c3cdbf5e4f4223a6215d6fa025ba064b7a24a4963a",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-apple-darwin.tar.xz": "8afef6fee075b7994b5f9b14b13738db27d9841af65f19fb9edccf299b013102",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-apple-ios.tar.gz": "9e5d88ea498ebdf50e1bbded7c3a107a820e668fb6c693c8d0d99244dba125b6",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-apple-ios.tar.xz": "2ba1cb490b834877a6caf77e5db19058492d7e943403b09a4efb1b89a0930cf3",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-fortanix-unknown-sgx.tar.gz": "cdef3244fbbbb2f291c462f53cd4ef6aeeda3d1b7ccb8d77b1d4040947855026",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-fortanix-unknown-sgx.tar.xz": "abdfbe1d32f3935cd5cf5235e88ca0275638977c0586aee2fd5a3a694ca9c0a9",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-fuchsia.tar.gz": "08faecdacef02a81b63d7d2a40fd18a10e7d6954f6461f95c95296936447fc26",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-fuchsia.tar.xz": "4ec2e0c20daf9f474f4cb660dee4707d892f1053c9099cb823b02bb9930d61e1",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-linux-android.tar.gz": "a093924e7fff13cde2c3a46903dc52f4e69e2ad1f79f477dc8e51ff053e87828",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-linux-android.tar.xz": "bd72b31cdab3c65434af6aed84a080cffc388acd4afc0e87d1223e358eff7acf",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-solaris.tar.gz": "611f718e776fc021dcf1c6d7b66de15cb717049dc05d5f040717b4eec54eaa1b",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-solaris.tar.xz": "e89de2a096a90308b78e4e8ee8d51f0b17db0319191bbae8823ee2c805b75ef1",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-windows-gnu.tar.gz": "5ab4b95694511e4cd9af7c5ee3698f0d7c8a2be55e3fc8a7d866bcca1d560625",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-windows-gnu.tar.xz": "05d44a506ec32cfda19a6959f1ad89d994f2705eea3b86f0c00cb9d2ec4423b3",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-windows-msvc.tar.gz": "e07c5bd1b18068bf8e739a7b59875a2911d45315ad8b5e9e6348101f97fdb269",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-pc-windows-msvc.tar.xz": "8b2398872f69d15fcc57777472c31b58f7dc4b55c33f382870fc221995351a0c",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-sun-solaris.tar.gz": "5d7ec4e6f07d78bffad42289b4e8798f48b276c6c436159c4d4117c34c4d4cf0",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-sun-solaris.tar.xz": "4eacb700c3791a8f5d1424a4cdc8e3b35c4fcdee57b97c855cadca6821a7afbd",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-freebsd.tar.gz": "eab943166d86021dad01e65a2f304fcc2914d48e34bcba9f710f362401770e0a",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-freebsd.tar.xz": "bd2242d140bb99bf03d480c56ad85c5ab034d41e29599bee0609191e1181c96f",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-illumos.tar.gz": "153f7d78721ba0e273f9d556ebe4d35ec44522dce0f136e9fa269408345b9e06",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-illumos.tar.xz": "ef652ce8b7183068be581ebb8c91dcefac8ec0f84edbf86f7998261e503edafb",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-gnu.tar.gz": "8c194b0e3814efecb87fc4779767ef17d25399fbd476dbfc92f9a7f88b98f784",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-gnu.tar.xz": "2b588cd2d49688c0c33b7466614123e8fe4c910f4d802fc0ff0662b1772816a9",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-gnux32.tar.gz": "e077e02a56c379950df3c3dda1b18b4fa78d33eb25667f206540dcca3eff0d55",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-gnux32.tar.xz": "7c630f206556916021a7e43dfcfd8392fe1b1e3c7ec94ffc8ef1be87b0ce0631",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-musl.tar.gz": "fbf8b5a2c388710cc7f4cc045d93cf05ebdd2d497936f54f995ccb44d346d85b",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-linux-musl.tar.xz": "55abeb1b55aeebc46a4af2f304271361397df58d12f7eb23fb262bc3132c6056",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-netbsd.tar.gz": "d0405e239dff6b7d840a5a6e45f60c7f661fd428d5a310b25e44de4e7fcb8eec",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-netbsd.tar.xz": "f173d07ccbbe65fc0878c16a7435f17a9db04476f0949e4625a79fa37911e436",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-none.tar.gz": "0942c94117d599cb85e028fc6f9aba057c1d1e8456a6d71c47f64c6d991e6ccd",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-none.tar.xz": "1d3ebe239659688ec787cc87819f8c4a6b77e0361f086111a5c36eb0ad730ca8",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-redox.tar.gz": "b8cc647867823ea52e4f6e647cf5fa7c6370447a324be8a70b56004f179301aa",
+ "dist/2022-11-03/rust-std-1.65.0-x86_64-unknown-redox.tar.xz": "23fd34f7ec55ba1e581e692764314c7c342eb87da00562dcba51808a89cb8a92",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-apple-darwin.tar.gz": "bbcf34977e41b9f966746a559aa2af6fa7efd7f695338851b37f722f7a1104fb",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-apple-darwin.tar.xz": "3368c57e5d2b396486eee5c38d184ddf13f248fbd0291c20764cd26a4e6fb5f1",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-pc-windows-msvc.tar.gz": "1c0be4fe80c052e0df315ca97006d5c9c4fdc4c172f3c3c9e6bad3747731578e",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-pc-windows-msvc.tar.xz": "d5008e3675ba9b57d05e4b9785b64b88d4166dc45b3fada6744e236024bfc18a",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-unknown-linux-gnu.tar.gz": "5ada1a7c9496017e3eed5d8ada62699c8d513f7664d8e02d5d9f02d26974cedc",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-unknown-linux-gnu.tar.xz": "67c3d3545fd898c1383071c0f6296453565e0da10903c50652d7bf679b53e8a2",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-unknown-linux-musl.tar.gz": "f3e2d2890291fedfea3829c7ffe937603cc43464463fde25187a054ab46755df",
+ "dist/2022-11-03/rustc-1.65.0-aarch64-unknown-linux-musl.tar.xz": "51676b3c7023bf57084497b02c6fbfa1604309f52b207d1afe59cf7d20c5fa54",
+ "dist/2022-11-03/rustc-1.65.0-arm-unknown-linux-gnueabi.tar.gz": "05a72c333b1ef236fbbb1dc7245b38af1818f0de4e7148f4f7d03b4019cc9c5e",
+ "dist/2022-11-03/rustc-1.65.0-arm-unknown-linux-gnueabi.tar.xz": "d6157c4f1b33ca22035c4a796449a187cf8ea54ce50baafc0b035cc0728e8d16",
+ "dist/2022-11-03/rustc-1.65.0-arm-unknown-linux-gnueabihf.tar.gz": "2fa0fc7b34eaede3a9a9b85386fc217dc5f455e0a5252bcad10bbc2027b14ef9",
+ "dist/2022-11-03/rustc-1.65.0-arm-unknown-linux-gnueabihf.tar.xz": "a217abf1b6db15feb869702b9e3a6462640ba9e87fef9f3bd7c551d237fa2956",
+ "dist/2022-11-03/rustc-1.65.0-armv7-unknown-linux-gnueabihf.tar.gz": "34698308b23db42d36e2a651d1d122d0078eb0b1b6ad8d0fdf7dde8358f1486c",
+ "dist/2022-11-03/rustc-1.65.0-armv7-unknown-linux-gnueabihf.tar.xz": "883a82b25c5929ba1dbc532394b213a29a914d6dc6bfcf4f28da955c722a760c",
+ "dist/2022-11-03/rustc-1.65.0-i686-pc-windows-gnu.tar.gz": "2c6655ed0b87b123a632c861c7b0748d593f82c886013346884d5372d3c504e7",
+ "dist/2022-11-03/rustc-1.65.0-i686-pc-windows-gnu.tar.xz": "2ee9b0e2880b5e6817816ba891aa481c0e0c6625683126cc296b2b8dc73177cf",
+ "dist/2022-11-03/rustc-1.65.0-i686-pc-windows-msvc.tar.gz": "8ee53ccb1e99945be3c04e36154f467493170c663c47b1c5c8e68e9283875826",
+ "dist/2022-11-03/rustc-1.65.0-i686-pc-windows-msvc.tar.xz": "11c01faea62d1077b6e059958991c6496e27a6db1a0b8fd48fb0d2168981d8a5",
+ "dist/2022-11-03/rustc-1.65.0-i686-unknown-linux-gnu.tar.gz": "88b9ac8670c55077be42cb9168e0f17d922c0b0eba3044ffa3e63729f02b363a",
+ "dist/2022-11-03/rustc-1.65.0-i686-unknown-linux-gnu.tar.xz": "5345c5ffa8aa334419f3c4ca8669c9ea7545abd81097856bbf599271d48b24a8",
+ "dist/2022-11-03/rustc-1.65.0-mips-unknown-linux-gnu.tar.gz": "8f63f3cf93718ea10b7f462f5b31cf16b56178c1a120ea17d8bcf7485a1b2e74",
+ "dist/2022-11-03/rustc-1.65.0-mips-unknown-linux-gnu.tar.xz": "6ac4ffc60c6942be108e881717fe1288cad15db8a735966899ad8155fb39e17e",
+ "dist/2022-11-03/rustc-1.65.0-mips64-unknown-linux-gnuabi64.tar.gz": "8318f09fbe8e07ba5e01b19522fce3c2dea319e4edaeb7616004533510bbc930",
+ "dist/2022-11-03/rustc-1.65.0-mips64-unknown-linux-gnuabi64.tar.xz": "414a54a5dabd280c1d59925b3c2781d7850eb0e958701c7e51765478e69e9f06",
+ "dist/2022-11-03/rustc-1.65.0-mips64el-unknown-linux-gnuabi64.tar.gz": "dbabfcec57e0d8e1699111914affd0ae9618eb069c1c278c65dcc8febfdd6ef4",
+ "dist/2022-11-03/rustc-1.65.0-mips64el-unknown-linux-gnuabi64.tar.xz": "550ca4d5aaeeedcf9e9242060c4ce11eff88fe57860ef11921c7d034fd07a203",
+ "dist/2022-11-03/rustc-1.65.0-mipsel-unknown-linux-gnu.tar.gz": "ef52a7a666f0e76afe8ff61dba430bf64fed424e4b3e32cea11676a0889bad10",
+ "dist/2022-11-03/rustc-1.65.0-mipsel-unknown-linux-gnu.tar.xz": "77ffd6f14aaa13c54a5f470116e3a4866d44ed0fac2546c325bc4e4bfe66083a",
+ "dist/2022-11-03/rustc-1.65.0-powerpc-unknown-linux-gnu.tar.gz": "224e34c6add5e19bd7eb522048c0bedf259612328b21a2c6f01fe8a3fb7a68a5",
+ "dist/2022-11-03/rustc-1.65.0-powerpc-unknown-linux-gnu.tar.xz": "78c5334e77ef84be2ebce14c5adc4d4e20410d975f6349020cdcffd01ff2a590",
+ "dist/2022-11-03/rustc-1.65.0-powerpc64-unknown-linux-gnu.tar.gz": "aaca27aabaeded4e3e4243d372c3bbb213f5781185e8bb2416a5090d434c6ce7",
+ "dist/2022-11-03/rustc-1.65.0-powerpc64-unknown-linux-gnu.tar.xz": "e890651263099a66d85a021d455f1851507b58c5282680d1b1bb2f778d6cad1d",
+ "dist/2022-11-03/rustc-1.65.0-powerpc64le-unknown-linux-gnu.tar.gz": "17222364ca34b31bf2a596b1117114ddd08cd1f0d16309c21c1d712dadd63141",
+ "dist/2022-11-03/rustc-1.65.0-powerpc64le-unknown-linux-gnu.tar.xz": "a6ce7aadd10a3fd84fe4717a59378421a65b101b61f27eed8b09336b8daf62cf",
+ "dist/2022-11-03/rustc-1.65.0-riscv64gc-unknown-linux-gnu.tar.gz": "06f7b5761a290424f08bc66e258b9b4e47e45346873ed0ec0688fb223e232155",
+ "dist/2022-11-03/rustc-1.65.0-riscv64gc-unknown-linux-gnu.tar.xz": "60102ba6b659a1e070626d3f1098fd16427464631923c64a458f4e281901679d",
+ "dist/2022-11-03/rustc-1.65.0-s390x-unknown-linux-gnu.tar.gz": "1a9c7f8e18f3c5136c83d4b941cc567ac7d576b52a82e42c1bafbbf47d493b61",
+ "dist/2022-11-03/rustc-1.65.0-s390x-unknown-linux-gnu.tar.xz": "dc3666eeba9754f67876df7249961c79b21fc576f6e49185ca23d01d82d1356d",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-apple-darwin.tar.gz": "be525d2eb2a55f7f5a9f5b3cffe5c1d7b511b4adf9cf5d5855b861138152f1fa",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-apple-darwin.tar.xz": "4ee585ecd3f195eb2ee380a9a8550d24852a578c38f07138aef354b0a6b10b77",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-pc-windows-gnu.tar.gz": "3abfe8be05104781fb71b6d9f81afd46998733d1f672dd901b27263325f03e5c",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-pc-windows-gnu.tar.xz": "197bb667b78f5bcee3713a28b94f3beed30d8fc8b9ab00d5e70b1a75944a2c70",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-pc-windows-msvc.tar.gz": "894fe660f3508e9dfac49ed27880aff0dc07196bda1bf15c7c7cc530dbe5599b",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-pc-windows-msvc.tar.xz": "0eae7a12177781bedfeb042a21a971e57c1542e5a5a4da751edaf69f95ae7fbf",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-freebsd.tar.gz": "e6104c86d66a19527c48e4e533c28e1b7b74cd2c4e3dfc3eba139c4b152ea121",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-freebsd.tar.xz": "9dcde013879317c17a2e1e0e584f3ac1b6edda2419a51d32fac22201354a25e7",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-illumos.tar.gz": "25154fb657c111809698912f437fe94fabfcf3c367bd10d227755c9a9f6f9109",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-illumos.tar.xz": "922ecf55b2848099369d8b2f6bcfd2979cee307aabd5eab392955b813f7a53ad",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-linux-gnu.tar.gz": "6a30ffca17a244ad6bfb1d257572155f4e2b08d3ca2d852c2fc7420e264c6baa",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-linux-gnu.tar.xz": "62b89786e195fc5a8a262f83118d6689832b24228c9d303cba8ac14dc1e9adc8",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-linux-musl.tar.gz": "afcb7bcec9b128d641224ca476dc5f9e5ab74b6ff82235b95dd305e882e46def",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-linux-musl.tar.xz": "06960685fcf39f24993525cb804649343b8f3c953ad740163edee16d9c9645bd",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-netbsd.tar.gz": "5af04405b78b7a4062e163b7926014fda0a7ef851d75ed50bcaf3f472c277028",
+ "dist/2022-11-03/rustc-1.65.0-x86_64-unknown-netbsd.tar.xz": "d6b913b77954146a2aca87ea15758df6bc9481512692423f0b1c0c39c14d5095"
}
}
diff --git a/src/test/assembly/asm/aarch64-types.rs b/src/test/assembly/asm/aarch64-types.rs
index 04b5f4aed..66c39a48c 100644
--- a/src/test/assembly/asm/aarch64-types.rs
+++ b/src/test/assembly/asm/aarch64-types.rs
@@ -2,7 +2,7 @@
// compile-flags: --target aarch64-unknown-linux-gnu
// needs-llvm-components: aarch64
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/arm-types.rs b/src/test/assembly/asm/arm-types.rs
index 5ac1af6af..b22a26ce3 100644
--- a/src/test/assembly/asm/arm-types.rs
+++ b/src/test/assembly/asm/arm-types.rs
@@ -3,7 +3,7 @@
// compile-flags: -C target-feature=+neon
// needs-llvm-components: arm
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/avr-types.rs b/src/test/assembly/asm/avr-types.rs
index 58bf1ad9e..b2d11a882 100644
--- a/src/test/assembly/asm/avr-types.rs
+++ b/src/test/assembly/asm/avr-types.rs
@@ -2,7 +2,7 @@
// compile-flags: --target avr-unknown-gnu-atmega328
// needs-llvm-components: avr
-#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(non_camel_case_types)]
diff --git a/src/test/assembly/asm/bpf-types.rs b/src/test/assembly/asm/bpf-types.rs
index f894644cc..e177b8d0d 100644
--- a/src/test/assembly/asm/bpf-types.rs
+++ b/src/test/assembly/asm/bpf-types.rs
@@ -2,7 +2,7 @@
// compile-flags: --target bpfel-unknown-none -C target_feature=+alu32
// needs-llvm-components: bpf
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/global_asm.rs b/src/test/assembly/asm/global_asm.rs
index 4cf73b40f..0b361a7ed 100644
--- a/src/test/assembly/asm/global_asm.rs
+++ b/src/test/assembly/asm/global_asm.rs
@@ -4,7 +4,7 @@
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
// compile-flags: -C symbol-mangling-version=v0
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
#![crate_type = "rlib"]
use std::arch::global_asm;
@@ -28,4 +28,6 @@ global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
// CHECK: call _RNvCsiubXh4Yz005_10global_asm6foobar
global_asm!("call {}", sym foobar);
// CHECK: _RNvCsiubXh4Yz005_10global_asm6foobar:
-fn foobar() { loop {} }
+fn foobar() {
+ loop {}
+}
diff --git a/src/test/assembly/asm/hexagon-types.rs b/src/test/assembly/asm/hexagon-types.rs
index eff9a0bb4..af16faedb 100644
--- a/src/test/assembly/asm/hexagon-types.rs
+++ b/src/test/assembly/asm/hexagon-types.rs
@@ -2,7 +2,7 @@
// compile-flags: --target hexagon-unknown-linux-musl
// needs-llvm-components: hexagon
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/mips-types.rs b/src/test/assembly/asm/mips-types.rs
index 04bf49a40..6aa28b062 100644
--- a/src/test/assembly/asm/mips-types.rs
+++ b/src/test/assembly/asm/mips-types.rs
@@ -5,7 +5,7 @@
//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
//[mips64] needs-llvm-components: mips
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/msp430-types.rs b/src/test/assembly/asm/msp430-types.rs
index 4fa2e8081..2c73b3b09 100644
--- a/src/test/assembly/asm/msp430-types.rs
+++ b/src/test/assembly/asm/msp430-types.rs
@@ -2,7 +2,7 @@
// compile-flags: --target msp430-none-elf
// needs-llvm-components: msp430
-#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch, asm_const)]
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch, asm_const)]
#![crate_type = "rlib"]
#![no_core]
#![allow(non_camel_case_types)]
diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs
index 3ebd5b4b8..c319946b5 100644
--- a/src/test/assembly/asm/nvptx-types.rs
+++ b/src/test/assembly/asm/nvptx-types.rs
@@ -3,7 +3,7 @@
// compile-flags: --crate-type cdylib
// needs-llvm-components: nvptx
-#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
#![no_core]
#[rustc_builtin_macro]
diff --git a/src/test/assembly/asm/powerpc-types.rs b/src/test/assembly/asm/powerpc-types.rs
index 0ca890849..e27b00520 100644
--- a/src/test/assembly/asm/powerpc-types.rs
+++ b/src/test/assembly/asm/powerpc-types.rs
@@ -5,7 +5,7 @@
//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
//[powerpc64] needs-llvm-components: powerpc
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/riscv-types.rs b/src/test/assembly/asm/riscv-types.rs
index 68dc186ea..f18ba294d 100644
--- a/src/test/assembly/asm/riscv-types.rs
+++ b/src/test/assembly/asm/riscv-types.rs
@@ -6,7 +6,7 @@
//[riscv32] needs-llvm-components: riscv
// compile-flags: -C target-feature=+d
-#![feature(no_core, lang_items, rustc_attrs, asm_sym)]
+#![feature(no_core, lang_items, rustc_attrs)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register)]
diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs
index 6a12902a0..2fb404dd9 100644
--- a/src/test/assembly/asm/s390x-types.rs
+++ b/src/test/assembly/asm/s390x-types.rs
@@ -3,7 +3,7 @@
//[s390x] compile-flags: --target s390x-unknown-linux-gnu
//[s390x] needs-llvm-components: systemz
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/asm/wasm-types.rs b/src/test/assembly/asm/wasm-types.rs
index 3aa128c46..3b1ac1b45 100644
--- a/src/test/assembly/asm/wasm-types.rs
+++ b/src/test/assembly/asm/wasm-types.rs
@@ -3,7 +3,7 @@
// compile-flags: --crate-type cdylib
// needs-llvm-components: webassembly
-#![feature(no_core, lang_items, rustc_attrs, asm_sym, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)]
#![no_core]
#[rustc_builtin_macro]
diff --git a/src/test/assembly/asm/x86-types.rs b/src/test/assembly/asm/x86-types.rs
index e871535cf..81be79cba 100644
--- a/src/test/assembly/asm/x86-types.rs
+++ b/src/test/assembly/asm/x86-types.rs
@@ -7,7 +7,7 @@
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
// compile-flags: -C target-feature=+avx512bw
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_sym)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd)]
#![crate_type = "rlib"]
#![no_core]
#![allow(asm_sub_register, non_camel_case_types)]
diff --git a/src/test/assembly/x86-stack-probes.rs b/src/test/assembly/x86-stack-probes.rs
new file mode 100644
index 000000000..c7141fb20
--- /dev/null
+++ b/src/test/assembly/x86-stack-probes.rs
@@ -0,0 +1,42 @@
+// min-llvm-version: 16
+// revisions: x86_64 i686
+// assembly-output: emit-asm
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+// compile-flags: -C llvm-args=-x86-asm-syntax=intel
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u8 {}
+
+// Check that inline-asm stack probes are generated correctly.
+// To avoid making this test fragile to slight asm changes,
+// we only check that the stack pointer is decremented by a page at a time,
+// instead of matching the whole probe sequence.
+
+// CHECK-LABEL: small_stack_probe:
+#[no_mangle]
+pub fn small_stack_probe(x: u8, f: fn(&mut [u8; 8192])) {
+ // CHECK-NOT: __rust_probestack
+ // x86_64: sub rsp, 4096
+ // i686: sub esp, 4096
+ f(&mut [x; 8192]);
+}
+
+// CHECK-LABEL: big_stack_probe:
+#[no_mangle]
+pub fn big_stack_probe(x: u8, f: fn(&[u8; 65536])) {
+ // CHECK-NOT: __rust_probestack
+ // x86_64: sub rsp, 4096
+ // i686: sub esp, 4096
+ f(&mut [x; 65536]);
+}
diff --git a/src/test/codegen-units/item-collection/asm-sym.rs b/src/test/codegen-units/item-collection/asm-sym.rs
new file mode 100644
index 000000000..8bafb95bc
--- /dev/null
+++ b/src/test/codegen-units/item-collection/asm-sym.rs
@@ -0,0 +1,20 @@
+// needs-asm-support
+// compile-flags: -Ccodegen-units=1 -Zprint-mono-items=lazy --crate-type=lib
+
+#[inline(always)]
+pub unsafe fn f() {
+ //~ MONO_ITEM static f::S @@ asm_sym-cgu.0[External]
+ static S: usize = 1;
+ //~ MONO_ITEM fn f::fun @@ asm_sym-cgu.0[External]
+ fn fun() {}
+ core::arch::asm!("/* {0} {1} */", sym S, sym fun);
+}
+
+//~ MONO_ITEM fn g @@ asm_sym-cgu.0[External]
+pub unsafe fn g() {
+ //~ MONO_ITEM static g::S @@ asm_sym-cgu.0[Internal]
+ static S: usize = 2;
+ //~ MONO_ITEM fn g::fun @@ asm_sym-cgu.0[Internal]
+ fn fun() {}
+ core::arch::asm!("/* {0} {1} */", sym S, sym fun);
+}
diff --git a/src/test/codegen-units/item-collection/generic-impl.rs b/src/test/codegen-units/item-collection/generic-impl.rs
index dd5367ef0..4260230c2 100644
--- a/src/test/codegen-units/item-collection/generic-impl.rs
+++ b/src/test/codegen-units/item-collection/generic-impl.rs
@@ -30,11 +30,11 @@ pub struct LifeTimeOnly<'a> {
impl<'a> LifeTimeOnly<'a> {
- //~ MONO_ITEM fn LifeTimeOnly::foo
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::foo
pub fn foo(&self) {}
- //~ MONO_ITEM fn LifeTimeOnly::bar
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::bar
pub fn bar(&'a self) {}
- //~ MONO_ITEM fn LifeTimeOnly::baz
+ //~ MONO_ITEM fn LifeTimeOnly::<'_>::baz
pub fn baz<'b>(&'b self) {}
pub fn non_instantiated<T>(&self) {}
diff --git a/src/test/codegen/abi-main-signature-32bit-c-int.rs b/src/test/codegen/abi-main-signature-32bit-c-int.rs
index 31b19a542..7f22ddcfc 100644
--- a/src/test/codegen/abi-main-signature-32bit-c-int.rs
+++ b/src/test/codegen/abi-main-signature-32bit-c-int.rs
@@ -7,4 +7,4 @@
fn main() {
}
-// CHECK: define i32 @main(i32{{( %0)?}}, {{i8\*\*|ptr}}{{( %1)?}})
+// CHECK: define{{( hidden)?}} i32 @main(i32{{( %0)?}}, {{i8\*\*|ptr}}{{( %1)?}})
diff --git a/src/test/codegen/binary-search-index-no-bound-check.rs b/src/test/codegen/binary-search-index-no-bound-check.rs
index 2deabcaa6..c1766a4a4 100644
--- a/src/test/codegen/binary-search-index-no-bound-check.rs
+++ b/src/test/codegen/binary-search-index-no-bound-check.rs
@@ -16,3 +16,23 @@ pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
42
}
}
+
+// Similarly, check that `partition_point` is known to return a valid fencepost.
+
+// CHECK-LABEL: @unknown_split
+#[no_mangle]
+pub fn unknown_split(x: &[i32], i: usize) -> (&[i32], &[i32]) {
+ // This just makes sure that the subsequent function is looking for the
+ // absence of something that might actually be there.
+
+ // CHECK: call core::panicking::panic
+ x.split_at(i)
+}
+
+// CHECK-LABEL: @partition_point_split_no_bounds_check
+#[no_mangle]
+pub fn partition_point_split_no_bounds_check(x: &[i32], needle: i32) -> (&[i32], &[i32]) {
+ // CHECK-NOT: call core::panicking::panic
+ let i = x.partition_point(|p| p < &needle);
+ x.split_at(i)
+}
diff --git a/src/test/codegen/deduced-param-attrs.rs b/src/test/codegen/deduced-param-attrs.rs
new file mode 100644
index 000000000..153046eef
--- /dev/null
+++ b/src/test/codegen/deduced-param-attrs.rs
@@ -0,0 +1,60 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+#![allow(incomplete_features)]
+#![feature(unsized_locals, unsized_fn_params)]
+
+use std::cell::Cell;
+use std::hint;
+
+// Check to make sure that we can deduce the `readonly` attribute from function bodies for
+// parameters passed indirectly.
+
+pub struct BigStruct {
+ blah: [i32; 1024],
+}
+
+pub struct BigCellContainer {
+ blah: [Cell<i32>; 1024],
+}
+
+// The by-value parameter for this big struct can be marked readonly.
+//
+// CHECK: @use_big_struct_immutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_immutably(big_struct: BigStruct) {
+ hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because we mutate it.
+//
+// CHECK-NOT: @use_big_struct_mutably({{.*}} readonly {{.*}} %big_struct)
+#[no_mangle]
+pub fn use_big_struct_mutably(mut big_struct: BigStruct) {
+ big_struct.blah[987] = 654;
+ hint::black_box(&big_struct);
+}
+
+// The by-value parameter for this big struct can't be marked readonly, because it contains
+// UnsafeCell.
+//
+// CHECK-NOT: @use_big_cell_container({{.*}} readonly {{.*}} %big_cell_container)
+#[no_mangle]
+pub fn use_big_cell_container(big_cell_container: BigCellContainer) {
+ hint::black_box(&big_cell_container);
+}
+
+// Make sure that we don't mistakenly mark a big struct as `readonly` when passed through a generic
+// type parameter if it contains UnsafeCell.
+//
+// CHECK-NOT: @use_something({{.*}} readonly {{.*}} %something)
+#[no_mangle]
+#[inline(never)]
+pub fn use_something<T>(something: T) {
+ hint::black_box(&something);
+}
+
+#[no_mangle]
+pub fn forward_big_cell_container(big_cell_container: BigCellContainer) {
+ use_something(big_cell_container)
+}
diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs
index bc650ebf5..44fee9523 100644
--- a/src/test/codegen/function-arguments.rs
+++ b/src/test/codegen/function-arguments.rs
@@ -127,7 +127,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {
pub fn notunpin_borrow(_: &NotUnpin) {
}
-// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef dereferenceable(32) %_1)
+// CHECK: @indirect_struct({{%S\*|ptr}} noalias nocapture noundef readonly dereferenceable(32) %_1)
#[no_mangle]
pub fn indirect_struct(_: S) {
}
diff --git a/src/test/codegen/mem-replace-direct-memcpy.rs b/src/test/codegen/mem-replace-direct-memcpy.rs
index b41ef538d..4318e926e 100644
--- a/src/test/codegen/mem-replace-direct-memcpy.rs
+++ b/src/test/codegen/mem-replace-direct-memcpy.rs
@@ -4,6 +4,7 @@
// known to be `1` after inlining).
// compile-flags: -C no-prepopulate-passes -Zinline-mir=no
+// ignore-debug: the debug assertions get in the way
#![crate_type = "lib"]
diff --git a/src/test/codegen/sanitizer_scs_attr_check.rs b/src/test/codegen/sanitizer_scs_attr_check.rs
index 0b53db3b7..a885d9117 100644
--- a/src/test/codegen/sanitizer_scs_attr_check.rs
+++ b/src/test/codegen/sanitizer_scs_attr_check.rs
@@ -7,11 +7,11 @@
#![crate_type = "lib"]
#![feature(no_sanitize)]
-// CHECK: ; Function Attrs:{{.*}}shadowcallstack
-// CHECK-NEXT: scs
+// CHECK: ; sanitizer_scs_attr_check::scs
+// CHECK-NEXT: ; Function Attrs:{{.*}}shadowcallstack
pub fn scs() {}
+// CHECK: ; sanitizer_scs_attr_check::no_scs
// CHECK-NOT: ; Function Attrs:{{.*}}shadowcallstack
-// CHECK-NEXT: no_scs
#[no_sanitize(shadow_call_stack)]
pub fn no_scs() {}
diff --git a/src/test/codegen/slice-iter-len-eq-zero.rs b/src/test/codegen/slice-iter-len-eq-zero.rs
index fd19e624c..112402825 100644
--- a/src/test/codegen/slice-iter-len-eq-zero.rs
+++ b/src/test/codegen/slice-iter-len-eq-zero.rs
@@ -1,5 +1,6 @@
// no-system-llvm
// compile-flags: -O
+// ignore-debug: the debug assertions add extra comparisons
#![crate_type = "lib"]
type Demo = [u8; 3];
@@ -12,3 +13,16 @@ pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool {
// CHECK: ret i1 %2
y.len() == 0
}
+
+// CHECK-LABEL: @array_into_iter_len_eq_zero
+#[no_mangle]
+pub fn array_into_iter_len_eq_zero(y: std::array::IntoIter<Demo, 123>) -> bool {
+ // This should be able to just check that the indexes are equal, and not
+ // need any subtractions or comparisons to handle `start > end`.
+
+ // CHECK-NOT: icmp
+ // CHECK-NOT: sub
+ // CHECK: %1 = icmp eq {{i16|i32|i64}}
+ // CHECK: ret i1 %1
+ y.len() == 0
+}
diff --git a/src/test/codegen/slice_as_from_ptr_range.rs b/src/test/codegen/slice_as_from_ptr_range.rs
new file mode 100644
index 000000000..0e3fefd97
--- /dev/null
+++ b/src/test/codegen/slice_as_from_ptr_range.rs
@@ -0,0 +1,23 @@
+// compile-flags: -O
+// only-64bit (because we're using [ui]size)
+// ignore-debug (because the assertions get in the way)
+// min-llvm-version: 15.0 (because this is a relatively new instcombine)
+
+#![crate_type = "lib"]
+#![feature(slice_from_ptr_range)]
+
+// This is intentionally using a non-power-of-two array length,
+// as that's where the optimization differences show up
+
+// CHECK-LABEL: @flatten_via_ptr_range
+#[no_mangle]
+pub fn flatten_via_ptr_range(slice_of_arrays: &[[i32; 13]]) -> &[i32] {
+ // CHECK-NOT: lshr
+ // CHECK-NOT: udiv
+ // CHECK: mul nuw nsw i64 %{{.+}}, 13
+ // CHECK-NOT: lshr
+ // CHECK-NOT: udiv
+ let r = slice_of_arrays.as_ptr_range();
+ let r = r.start.cast()..r.end.cast();
+ unsafe { core::slice::from_ptr_range(r) }
+}
diff --git a/src/test/codegen/stack-probes-call.rs b/src/test/codegen/stack-probes-call.rs
new file mode 100644
index 000000000..a18fd41c2
--- /dev/null
+++ b/src/test/codegen/stack-probes-call.rs
@@ -0,0 +1,24 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Call`,
+// or `StackProbeType::InlineOrCall` when running on older LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: i686 x86_64
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+//[i686] ignore-llvm-version: 16 - 99
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+//[x86_64] ignore-llvm-version: 16 - 99
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="__rust_probestack"{{.*}} }
+}
diff --git a/src/test/codegen/stack-probes-inline.rs b/src/test/codegen/stack-probes-inline.rs
new file mode 100644
index 000000000..a6b781de5
--- /dev/null
+++ b/src/test/codegen/stack-probes-inline.rs
@@ -0,0 +1,32 @@
+// Check the "probe-stack" attribute for targets with `StackProbeType::Inline`,
+// or `StackProbeType::InlineOrCall` when running on newer LLVM.
+
+// compile-flags: -C no-prepopulate-passes
+// revisions: powerpc powerpc64 powerpc64le s390x i686 x86_64
+//[powerpc] compile-flags: --target powerpc-unknown-linux-gnu
+//[powerpc] needs-llvm-components: powerpc
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+//[powerpc64le] compile-flags: --target powerpc64le-unknown-linux-gnu
+//[powerpc64le] needs-llvm-components: powerpc
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+//[i686] compile-flags: --target i686-unknown-linux-gnu
+//[i686] needs-llvm-components: x86
+//[i686] min-llvm-version: 16
+//[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//[x86_64] needs-llvm-components: x86
+//[x86_64] min-llvm-version: 16
+
+#![crate_type = "rlib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[no_mangle]
+pub fn foo() {
+// CHECK: @foo() unnamed_addr #0
+// CHECK: attributes #0 = { {{.*}}"probe-stack"="inline-asm"{{.*}} }
+}
diff --git a/src/test/codegen/stack-probes.rs b/src/test/codegen/stack-probes.rs
deleted file mode 100644
index 9bd351df3..000000000
--- a/src/test/codegen/stack-probes.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-// ignore-arm
-// ignore-aarch64
-// ignore-mips
-// ignore-mips64
-// ignore-powerpc
-// ignore-powerpc64
-// ignore-powerpc64le
-// ignore-riscv64
-// ignore-s390x
-// ignore-sparc
-// ignore-sparc64
-// ignore-wasm
-// ignore-emscripten
-// ignore-windows
-// compile-flags: -C no-prepopulate-passes
-
-#![crate_type = "lib"]
-
-#[no_mangle]
-pub fn foo() {
-// CHECK: @foo() unnamed_addr #0
-}
diff --git a/src/test/codegen/vec-calloc.rs b/src/test/codegen/vec-calloc.rs
index 435a4ab51..ae6e448f1 100644
--- a/src/test/codegen/vec-calloc.rs
+++ b/src/test/codegen/vec-calloc.rs
@@ -1,4 +1,4 @@
-// compile-flags: -O
+// compile-flags: -O -Z merge-functions=disabled
// only-x86_64
// ignore-debug
// min-llvm-version: 15.0
@@ -144,6 +144,23 @@ pub fn vec_non_zero_tuple(n: usize) -> Vec<(i16, u8, char)> {
vec![(0, 0, 'A'); n]
}
+// CHECK-LABEL: @vec_option_bool
+#[no_mangle]
+pub fn vec_option_bool(n: usize) -> Vec<Option<bool>> {
+ // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+ // CHECK-NOT: call {{.*}}reserve
+ // CHECK-NOT: call {{.*}}__rust_alloc(
+
+ // CHECK: call {{.*}}__rust_alloc_zeroed(
+
+ // CHECK-NOT: call {{.*}}alloc::vec::from_elem
+ // CHECK-NOT: call {{.*}}reserve
+ // CHECK-NOT: call {{.*}}__rust_alloc(
+
+ // CHECK: ret void
+ vec![Some(false); n]
+}
+
// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away.
// CHECK: declare noalias ptr @__rust_alloc_zeroed(i64, i64 allocalign) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]]
diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs
index 62139aa9b..5df366905 100644
--- a/src/test/codegen/vec-in-place.rs
+++ b/src/test/codegen/vec-in-place.rs
@@ -17,7 +17,7 @@ pub struct Foo {
// Going from an aggregate struct to another type currently requires Copy to
// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
-// reliably recognize the loops as noop for for repr(C) or non-Copy structs.
+// reliably recognize the loops as noop for repr(C) or non-Copy structs.
#[derive(Copy, Clone)]
pub struct Bar {
a: u64,
diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs
index 076eddaab..3ff949fbb 100644
--- a/src/test/incremental/hashes/function_interfaces.rs
+++ b/src/test/incremental/hashes/function_interfaces.rs
@@ -323,7 +323,7 @@ pub fn change_return_impl_trait() -> impl Clone {
#[cfg(not(any(cfail1,cfail4)))]
#[rustc_clean(cfg = "cfail2")]
#[rustc_clean(cfg = "cfail3")]
-#[rustc_clean(cfg = "cfail5")]
+#[rustc_clean(cfg = "cfail5", except = "typeck")]
#[rustc_clean(cfg = "cfail6")]
pub fn change_return_impl_trait() -> impl Copy {
0u32
diff --git a/src/test/incremental/issue-61323.rs b/src/test/incremental/issue-61323.rs
index 97cbfe408..7ce47947c 100644
--- a/src/test/incremental/issue-61323.rs
+++ b/src/test/incremental/issue-61323.rs
@@ -1,7 +1,7 @@
// revisions: rpass cfail
enum A {
- //[cfail]~^ ERROR 3:1: 3:7: recursive type `A` has infinite size [E0072]
+ //[cfail]~^ ERROR 3:1: 3:7: recursive types `A` and `C` have infinite size [E0072]
B(C),
}
@@ -10,6 +10,5 @@ struct C(Box<A>);
#[cfg(cfail)]
struct C(A);
-//[cfail]~^ ERROR 12:1: 12:9: recursive type `C` has infinite size [E0072]
fn main() {}
diff --git a/src/test/incremental/spans_significant_w_panic.rs b/src/test/incremental/spans_significant_w_panic.rs
index e9e35791a..6f51c9729 100644
--- a/src/test/incremental/spans_significant_w_panic.rs
+++ b/src/test/incremental/spans_significant_w_panic.rs
@@ -8,7 +8,6 @@
// compile-flags: -C overflow-checks=on -Z query-dep-graph
#![feature(rustc_attrs)]
-#![feature(bench_black_box)]
#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass2")]
#![rustc_partition_codegened(module = "spans_significant_w_panic", cfg = "rpass4")]
diff --git a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index bde2f04fa..6f01553ee 100644
--- a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
+++ b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
@@ -24,7 +24,7 @@
_2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
// mir::Constant
// + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9
- // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
}
bb1: {
@@ -37,7 +37,7 @@
- _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11
-- // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
+ _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
@@ -53,7 +53,7 @@
- _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16
-- // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
+ _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index 248abb8fd..f8a7c687e 100644
--- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
@@ -33,7 +33,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
- // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 8ce895fe7..e938ca28a 100644
--- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -35,7 +35,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
- // + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
index e040a4b3a..1d4dfc29f 100644
--- a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
@@ -14,10 +14,10 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/cast.rs:+1:9: +1:10
-- _1 = const 42_u8 as u32 (Misc); // scope 0 at $DIR/cast.rs:+1:13: +1:24
+- _1 = const 42_u8 as u32 (IntToInt); // scope 0 at $DIR/cast.rs:+1:13: +1:24
+ _1 = const 42_u32; // scope 0 at $DIR/cast.rs:+1:13: +1:24
StorageLive(_2); // scope 1 at $DIR/cast.rs:+3:9: +3:10
-- _2 = const 42_u32 as u8 (Misc); // scope 1 at $DIR/cast.rs:+3:13: +3:24
+- _2 = const 42_u32 as u8 (IntToInt); // scope 1 at $DIR/cast.rs:+3:13: +3:24
+ _2 = const 42_u8; // scope 1 at $DIR/cast.rs:+3:13: +3:24
_0 = const (); // scope 0 at $DIR/cast.rs:+0:11: +4:2
StorageDead(_2); // scope 1 at $DIR/cast.rs:+4:1: +4:2
diff --git a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
index 948bb7f56..f4c0c5c5e 100644
--- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
@@ -13,7 +13,7 @@
bb0: {
StorageLive(_1); // scope 0 at $DIR/indirect.rs:+1:9: +1:10
StorageLive(_2); // scope 0 at $DIR/indirect.rs:+1:13: +1:25
-- _2 = const 2_u32 as u8 (Misc); // scope 0 at $DIR/indirect.rs:+1:13: +1:25
+- _2 = const 2_u32 as u8 (IntToInt); // scope 0 at $DIR/indirect.rs:+1:13: +1:25
- _3 = CheckedAdd(_2, const 1_u8); // scope 0 at $DIR/indirect.rs:+1:13: +1:29
- assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
+ _2 = const 2_u8; // scope 0 at $DIR/indirect.rs:+1:13: +1:25
diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
index 53f977de5..995611f0e 100644
--- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
+++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
@@ -20,7 +20,7 @@
_2 = core::str::<impl str>::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
// mir::Constant
// + span: $DIR/deduplicate_blocks.rs:5:13: 5:21
- // + literal: Const { ty: for<'r> fn(&'r str) -> &'r [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
index c353c375a..713d56c38 100644
--- a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
+++ b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
@@ -3,15 +3,15 @@
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/derefer_complex_case.rs:+0:11: +0:11
- let mut _1: std::slice::Iter<i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ let mut _1: std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
let mut _2: &[i32; 2]; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
let _3: [i32; 2]; // in scope 0 at $DIR/derefer_complex_case.rs:+1:18: +1:26
- let mut _4: std::slice::Iter<i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ let mut _4: std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
let mut _5: (); // in scope 0 at $DIR/derefer_complex_case.rs:+0:1: +2:2
let _6: (); // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
let mut _7: std::option::Option<&i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
- let mut _8: &mut std::slice::Iter<i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
- let mut _9: &mut std::slice::Iter<i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ let mut _8: &mut std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ let mut _9: &mut std::slice::Iter<'_, i32>; // in scope 0 at $DIR/derefer_complex_case.rs:+1:17: +1:26
let mut _10: isize; // in scope 0 at $DIR/derefer_complex_case.rs:+1:5: +1:40
let mut _11: !; // in scope 0 at $DIR/derefer_complex_case.rs:+1:5: +1:40
let mut _13: i32; // in scope 0 at $DIR/derefer_complex_case.rs:+1:34: +1:37
@@ -53,10 +53,10 @@
StorageLive(_9); // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
_9 = &mut _4; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
_8 = &mut (*_9); // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
- _7 = <std::slice::Iter<i32> as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+ _7 = <std::slice::Iter<'_, i32> as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
// mir::Constant
// + span: $DIR/derefer_complex_case.rs:6:17: 6:26
- // + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter<i32>) -> Option<<std::slice::Iter<i32> as Iterator>::Item> {<std::slice::Iter<i32> as Iterator>::next}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, i32>) -> Option<<std::slice::Iter<'_, i32> as Iterator>::Item> {<std::slice::Iter<'_, i32> as Iterator>::next}, val: Value(<ZST>) }
}
bb3: {
diff --git a/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
index a20a172af..80b09ed5f 100644
--- a/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
@@ -1,12 +1,12 @@
- // MIR for `nrvo` before DestinationPropagation
+ // MIR for `nrvo` after DestinationPropagation
- fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
+ fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] {
debug init => _1; // in scope 0 at $DIR/simple.rs:+0:9: +0:13
let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/simple.rs:+0:39: +0:49
let mut _2: [u8; 1024]; // in scope 0 at $DIR/simple.rs:+1:9: +1:16
let _3: (); // in scope 0 at $DIR/simple.rs:+2:5: +2:19
- let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9
+ let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9
let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18
let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18
scope 1 {
diff --git a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
index 9e089b01b..659aed18f 100644
--- a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
@@ -1,12 +1,12 @@
- // MIR for `no_downcast` before EarlyOtherwiseBranch
+ // MIR for `no_downcast` after EarlyOtherwiseBranch
- fn no_downcast(_1: &E) -> u32 {
+ fn no_downcast(_1: &E<'_>) -> u32 {
debug e => _1; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17
let mut _0: u32; // return place in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:26: +0:29
let mut _2: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:20: +1:30
let mut _3: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
- let mut _4: &E; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17
+ let mut _4: &E<'_>; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:+0:16: +0:17
scope 1 {
}
@@ -16,7 +16,7 @@
}
bb1: {
- _4 = deref_copy (((*_1) as Some).0: &E); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+ _4 = deref_copy (((*_1) as Some).0: &E<'_>); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
_2 = discriminant((*_4)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
}
diff --git a/src/test/mir-opt/enum_cast.bar.mir_map.0.mir b/src/test/mir-opt/enum_cast.bar.mir_map.0.mir
index 59ec80915..e58085f70 100644
--- a/src/test/mir-opt/enum_cast.bar.mir_map.0.mir
+++ b/src/test/mir-opt/enum_cast.bar.mir_map.0.mir
@@ -10,7 +10,7 @@ fn bar(_1: Bar) -> usize {
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
- _0 = move _3 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+ _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
diff --git a/src/test/mir-opt/enum_cast.boo.mir_map.0.mir b/src/test/mir-opt/enum_cast.boo.mir_map.0.mir
index f6903c1ec..525c6234e 100644
--- a/src/test/mir-opt/enum_cast.boo.mir_map.0.mir
+++ b/src/test/mir-opt/enum_cast.boo.mir_map.0.mir
@@ -10,7 +10,7 @@ fn boo(_1: Boo) -> usize {
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
- _0 = move _3 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+ _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
diff --git a/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir b/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir
index 98e1f8e11..bb5faa480 100644
--- a/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir
+++ b/src/test/mir-opt/enum_cast.droppy.mir_map.0.mir
@@ -29,7 +29,7 @@ fn droppy() -> () {
StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
_4 = move _2; // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
_5 = discriminant(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
- _3 = move _5 as usize (Misc); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
+ _3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
}
diff --git a/src/test/mir-opt/enum_cast.foo.mir_map.0.mir b/src/test/mir-opt/enum_cast.foo.mir_map.0.mir
index aaa2d2646..a1d29a0b9 100644
--- a/src/test/mir-opt/enum_cast.foo.mir_map.0.mir
+++ b/src/test/mir-opt/enum_cast.foo.mir_map.0.mir
@@ -10,7 +10,7 @@ fn foo(_1: Foo) -> usize {
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
- _0 = move _3 as usize (Misc); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
+ _0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2
}
diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index dca36b1a7..6ab63e82e 100644
--- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -1,24 +1,24 @@
- // MIR for `float_to_exponential_common` before ConstProp
+ // MIR for `float_to_exponential_common` after ConstProp
- fn float_to_exponential_common(_1: &mut Formatter, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
+ fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
debug fmt => _1; // in scope 0 at $DIR/funky_arms.rs:+0:35: +0:38
debug num => _2; // in scope 0 at $DIR/funky_arms.rs:+0:60: +0:63
debug upper => _3; // in scope 0 at $DIR/funky_arms.rs:+0:69: +0:74
let mut _0: std::result::Result<(), std::fmt::Error>; // return place in scope 0 at $DIR/funky_arms.rs:+0:85: +0:91
let _4: bool; // in scope 0 at $DIR/funky_arms.rs:+4:9: +4:19
- let mut _5: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
+ let mut _5: &std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
let mut _7: std::option::Option<usize>; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45
- let mut _8: &std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45
+ let mut _8: &std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+13:30: +13:45
let mut _9: isize; // in scope 0 at $DIR/funky_arms.rs:+13:12: +13:27
- let mut _11: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+15:43: +15:46
+ let mut _11: &mut std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+15:43: +15:46
let mut _12: &T; // in scope 0 at $DIR/funky_arms.rs:+15:48: +15:51
let mut _13: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:+15:53: +15:57
let mut _14: u32; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:79
let mut _15: u32; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:75
let mut _16: usize; // in scope 0 at $DIR/funky_arms.rs:+15:59: +15:68
let mut _17: bool; // in scope 0 at $DIR/funky_arms.rs:+15:81: +15:86
- let mut _18: &mut std::fmt::Formatter; // in scope 0 at $DIR/funky_arms.rs:+17:46: +17:49
+ let mut _18: &mut std::fmt::Formatter<'_>; // in scope 0 at $DIR/funky_arms.rs:+17:46: +17:49
let mut _19: &T; // in scope 0 at $DIR/funky_arms.rs:+17:51: +17:54
let mut _20: core::num::flt2dec::Sign; // in scope 0 at $DIR/funky_arms.rs:+17:56: +17:60
let mut _21: bool; // in scope 0 at $DIR/funky_arms.rs:+17:62: +17:67
@@ -38,10 +38,10 @@
StorageLive(_4); // scope 0 at $DIR/funky_arms.rs:+4:9: +4:19
StorageLive(_5); // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
_5 = &(*_1); // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
- _4 = Formatter::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
+ _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
// mir::Constant
// + span: $DIR/funky_arms.rs:15:26: 15:35
- // + literal: Const { ty: for<'r> fn(&'r Formatter) -> bool {Formatter::sign_plus}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value(<ZST>) }
}
bb1: {
@@ -66,10 +66,10 @@
StorageLive(_7); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
StorageLive(_8); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
_8 = &(*_1); // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
- _7 = Formatter::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
+ _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
// mir::Constant
// + span: $DIR/funky_arms.rs:24:34: 24:43
- // + literal: Const { ty: for<'r> fn(&'r Formatter) -> Option<usize> {Formatter::precision}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option<usize> {Formatter::<'_>::precision}, val: Value(<ZST>) }
}
bb5: {
@@ -91,7 +91,7 @@
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 (Misc); // scope 3 at $DIR/funky_arms.rs:+15:59: +15:75
+ _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
_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
@@ -100,7 +100,7 @@
_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
// mir::Constant
// + span: $DIR/funky_arms.rs:26:9: 26:42
- // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
+ // + 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: {
@@ -125,7 +125,7 @@
_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
// mir::Constant
// + span: $DIR/funky_arms.rs:28:9: 28:45
- // + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
+ // + 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: {
diff --git a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
index 3f612e03f..ed53c9a95 100644
--- a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
@@ -31,7 +31,7 @@
StorageLive(_6); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:31
StorageLive(_7); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:24
_7 = _2; // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:24
- _6 = move _7 as i32 (Misc); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:31
+ _6 = move _7 as i32 (IntToInt); // scope 1 at $DIR/if-condition-int.rs:+4:23: +4:31
StorageDead(_7); // scope 1 at $DIR/if-condition-int.rs:+4:30: +4:31
_0 = Add(const 100_i32, move _6); // scope 1 at $DIR/if-condition-int.rs:+4:17: +4:31
StorageDead(_6); // scope 1 at $DIR/if-condition-int.rs:+4:30: +4:31
@@ -43,7 +43,7 @@
StorageLive(_4); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:31
StorageLive(_5); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:24
_5 = _2; // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:24
- _4 = move _5 as i32 (Misc); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:31
+ _4 = move _5 as i32 (IntToInt); // scope 1 at $DIR/if-condition-int.rs:+3:23: +3:31
StorageDead(_5); // scope 1 at $DIR/if-condition-int.rs:+3:30: +3:31
_0 = Add(const 10_i32, move _4); // scope 1 at $DIR/if-condition-int.rs:+3:18: +3:31
StorageDead(_4); // scope 1 at $DIR/if-condition-int.rs:+3:30: +3:31
diff --git a/src/test/mir-opt/inline/asm-unwind.rs b/src/test/mir-opt/inline/asm-unwind.rs
new file mode 100644
index 000000000..c03feb433
--- /dev/null
+++ b/src/test/mir-opt/inline/asm-unwind.rs
@@ -0,0 +1,22 @@
+// Tests inlining of `may_unwind` inline assembly.
+//
+// ignore-wasm32-bare compiled with panic=abort by default
+// needs-asm-support
+#![feature(asm_unwind)]
+
+struct D;
+
+impl Drop for D {
+ fn drop(&mut self) {}
+}
+
+#[inline(always)]
+fn foo() {
+ let _d = D;
+ unsafe { std::arch::asm!("", options(may_unwind)) };
+}
+
+// EMIT_MIR asm_unwind.main.Inline.diff
+pub fn main() {
+ foo();
+}
diff --git a/src/test/mir-opt/inline/asm_unwind.main.Inline.diff b/src/test/mir-opt/inline/asm_unwind.main.Inline.diff
new file mode 100644
index 000000000..57072fc0a
--- /dev/null
+++ b/src/test/mir-opt/inline/asm_unwind.main.Inline.diff
@@ -0,0 +1,45 @@
+- // MIR for `main` before Inline
++ // MIR for `main` after Inline
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/asm-unwind.rs:+0:15: +0:15
+ let _1: (); // in scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
++ scope 1 (inlined foo) { // at $DIR/asm-unwind.rs:21:5: 21:10
++ let _2: D; // in scope 1 at $DIR/asm-unwind.rs:15:9: 15:11
++ scope 2 {
++ debug _d => _2; // in scope 2 at $DIR/asm-unwind.rs:15:9: 15:11
++ scope 3 {
++ }
++ }
++ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
+- _1 = foo() -> bb1; // scope 0 at $DIR/asm-unwind.rs:+1:5: +1:10
+- // mir::Constant
+- // + span: $DIR/asm-unwind.rs:21:5: 21:8
+- // + literal: Const { ty: fn() {foo}, val: Value(<ZST>) }
++ StorageLive(_2); // scope 1 at $DIR/asm-unwind.rs:15:9: 15:11
++ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm-unwind.rs:16:14: 16:54
+ }
+
+ bb1: {
++ drop(_2) -> bb2; // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2
++ }
++
++ bb2: {
++ StorageDead(_2); // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2
+ StorageDead(_1); // scope 0 at $DIR/asm-unwind.rs:+1:10: +1:11
+ _0 = const (); // scope 0 at $DIR/asm-unwind.rs:+0:15: +2:2
+ return; // scope 0 at $DIR/asm-unwind.rs:+2:2: +2:2
++ }
++
++ bb3 (cleanup): {
++ drop(_2) -> bb4; // scope 1 at $DIR/asm-unwind.rs:17:1: 17:2
++ }
++
++ bb4 (cleanup): {
++ resume; // scope 1 at $DIR/asm-unwind.rs:14:1: 17:2
+ }
+ }
+
diff --git a/src/test/mir-opt/inline/cycle.f.Inline.diff b/src/test/mir-opt/inline/cycle.f.Inline.diff
index 40fdd1cdb..75ea69a42 100644
--- a/src/test/mir-opt/inline/cycle.f.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.f.Inline.diff
@@ -17,7 +17,7 @@
_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
- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
index 4b50ba950..1e95b5b29 100644
--- a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
+++ b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
@@ -28,7 +28,7 @@
// mir::Constant
// + span: $DIR/dyn-trait.rs:33:13: 33:21
// + user_ty: UserType(0)
- // + literal: Const { ty: for<'r> fn(&'r T) -> &'r <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) }
}
bb1: {
@@ -46,9 +46,9 @@
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> 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<'r> fn(&'r <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
+ // + span: $DIR/dyn-trait.rs:21:7: 21:20
-+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
}
bb2: {
diff --git a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
index 994930ef4..7421db4d0 100644
--- a/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
+++ b/src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
@@ -12,7 +12,7 @@
_0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22
// mir::Constant
// + span: $DIR/dyn-trait.rs:21:7: 21:20
- // + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
index 58c05b9f5..e6e783744 100644
--- a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
+++ b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
@@ -23,9 +23,9 @@
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> 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<'r> fn(&'r (dyn Cache<V = <C as Cache>::V> + 'r)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
+ // + span: $DIR/dyn-trait.rs:21:7: 21:20
-+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
index a25f1454f..a71baad3e 100644
--- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
@@ -25,7 +25,7 @@
bb1: {
StorageLive(_4); // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:10
_4 = _1; // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:10
- _0 = move _4 as u32 (Misc); // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:17
+ _0 = move _4 as u32 (IntToInt); // scope 0 at $DIR/inline-diverging.rs:+2:9: +2:17
StorageDead(_4); // scope 0 at $DIR/inline-diverging.rs:+2:16: +2:17
StorageDead(_2); // scope 0 at $DIR/inline-diverging.rs:+5:5: +5:6
return; // scope 0 at $DIR/inline-diverging.rs:+6:2: +6:2
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
index 0b992e3c3..3fd8aad72 100644
--- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -70,7 +70,7 @@
- _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<'r> fn(Pin<&'r 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>) }
+- // + 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:14: +1:46
+ _7 = const false; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46
+ StorageLive(_10); // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index cabc1a920..169e7f5c5 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -2,8 +2,8 @@
fn bar() -> bool {
let mut _0: bool; // return place in scope 0 at $DIR/inline-retag.rs:+0:13: +0:17
- let _1: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+1:9: +1:10
- let mut _2: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+2:5: +2:6
+ let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+1:9: +1:10
+ let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline-retag.rs:+2:5: +2:6
let mut _3: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9
let _4: &i32; // in scope 0 at $DIR/inline-retag.rs:+2:7: +2:9
let _5: i32; // in scope 0 at $DIR/inline-retag.rs:+2:8: +2:9
@@ -27,7 +27,7 @@ fn bar() -> bool {
_1 = foo; // scope 0 at $DIR/inline-retag.rs:+1:13: +1:16
// mir::Constant
// + span: $DIR/inline-retag.rs:11:13: 11:16
- // + literal: Const { ty: for<'r, 's> fn(&'r i32, &'s i32) -> bool {foo}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}, val: Value(<ZST>) }
StorageLive(_2); // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6
_2 = _1; // scope 1 at $DIR/inline-retag.rs:+2:5: +2:6
StorageLive(_3); // scope 1 at $DIR/inline-retag.rs:+2:7: +2:9
diff --git a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff
index 25ca05893..d691e90b7 100644
--- a/src/test/mir-opt/inline/inline_shims.clone.Inline.diff
+++ b/src/test/mir-opt/inline/inline_shims.clone.Inline.diff
@@ -14,7 +14,7 @@
- _0 = <fn(A, B) as Clone>::clone(move _2) -> bb1; // scope 0 at $DIR/inline-shims.rs:+1:5: +1:14
- // mir::Constant
- // + span: $DIR/inline-shims.rs:6:7: 6:12
-- // + literal: Const { ty: for<'r> fn(&'r fn(A, B)) -> fn(A, B) {<fn(A, B) as Clone>::clone}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a fn(A, B)) -> fn(A, B) {<fn(A, B) as Clone>::clone}, val: Value(<ZST>) }
- }
-
- bb1: {
diff --git a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
index ed95edd16..89eefc292 100644
--- a/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_trait_method.test.Inline.after.mir
@@ -11,7 +11,7 @@ fn test(_1: &dyn X) -> u32 {
_0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline-trait-method.rs:+1:5: +1:10
// mir::Constant
// + span: $DIR/inline-trait-method.rs:9:7: 9:8
- // + literal: Const { ty: for<'r> fn(&'r dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index b8896430d..3d05869fa 100644
--- a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
@@ -21,7 +21,7 @@ fn test2(_1: &dyn X) -> bool {
_0 = <dyn X as X>::y(move _4) -> 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<'r> fn(&'r dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff
index c16dfdf39..4186650df 100644
--- a/src/test/mir-opt/inline/issue_78442.bar.Inline.diff
+++ b/src/test/mir-opt/inline/issue_78442.bar.Inline.diff
@@ -29,7 +29,7 @@
- _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
-- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) }
+ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL
}
diff --git a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
index 0faa522cb..24e9a3df1 100644
--- a/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
+++ b/src/test/mir-opt/inline/issue_78442.bar.RevealAll.diff
@@ -29,8 +29,8 @@
+ _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
-- // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
-+ // + literal: Const { ty: for<'r> extern "rust-call" fn(&'r fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) }
}
bb2: {
diff --git a/src/test/mir-opt/issue-101867.rs b/src/test/mir-opt/issue-101867.rs
index 931396e21..8a357eb79 100644
--- a/src/test/mir-opt/issue-101867.rs
+++ b/src/test/mir-opt/issue-101867.rs
@@ -1,5 +1,3 @@
-#![cfg_attr(bootstrap, feature(let_else))]
-
// EMIT_MIR issue_101867.main.mir_map.0.mir
fn main() {
let x: Option<u8> = Some(1);
diff --git a/src/test/mir-opt/issue_101867.main.mir_map.0.mir b/src/test/mir-opt/issue_101867.main.mir_map.0.mir
index 98501ac8c..42a9e5587 100644
--- a/src/test/mir-opt/issue_101867.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_101867.main.mir_map.0.mir
@@ -1,8 +1,8 @@
// MIR for `main` 0 mir_map
| User Type Annotations
-| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
-| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
+| 0: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { max_universe: U0, variables: [], value: Ty(std::option::Option<u8>) }, span: $DIR/issue-101867.rs:3:12: 3:22, inferred_ty: std::option::Option<u8>
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/issue-101867.rs:+0:11: +0:11
diff --git a/src/test/mir-opt/issue_101973.inner.ConstProp.diff b/src/test/mir-opt/issue_101973.inner.ConstProp.diff
index 89733a9a2..281afe4be 100644
--- a/src/test/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/src/test/mir-opt/issue_101973.inner.ConstProp.diff
@@ -90,9 +90,9 @@
StorageDead(_16); // 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 (Misc); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:65
+ _2 = move _3 as i32 (IntToInt); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:65
StorageDead(_3); // scope 0 at $DIR/issue-101973.rs:+1:64: +1:65
- _0 = move _2 as i64 (Misc); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:72
+ _0 = move _2 as i64 (IntToInt); // scope 0 at $DIR/issue-101973.rs:+1:5: +1:72
StorageDead(_2); // scope 0 at $DIR/issue-101973.rs:+1:71: +1:72
return; // scope 0 at $DIR/issue-101973.rs:+2:2: +2:2
}
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
index 76d8d9396..269e4e326 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
@@ -25,7 +25,7 @@
let _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
let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _27: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _27: std::option::Option<std::fmt::Arguments<'_>>; // 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 _6: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:+6:9: +6:14
@@ -139,7 +139,7 @@
_21 = core::panicking::assert_failed::<i32, i32>(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // 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<'r, 's, 't0> fn(core::panicking::AssertKind, &'r i32, &'s i32, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<i32, i32>}, val: Value(<ZST>) }
+ // + 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)) }
diff --git a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir
index f5092d2ac..625f6c736 100644
--- a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir
+++ b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir
@@ -15,7 +15,7 @@ fn bar(_1: Box<[T]>) -> () {
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
// mir::Constant
// + span: $DIR/issue-91633.rs:15:14: 15:19
- // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir
index 2e8b0feed..9903e203a 100644
--- a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir
+++ b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir
@@ -27,7 +27,7 @@ fn foo(_1: Box<[T]>) -> T {
_2 = <T as Clone>::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
// mir::Constant
// + span: $DIR/issue-91633.rs:28:20: 28:25
- // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
}
bb2: {
diff --git a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir
index 74f4a5a97..37c3b3fca 100644
--- a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir
+++ b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir
@@ -17,7 +17,7 @@ fn hey(_1: &[T]) -> () {
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
// mir::Constant
// + span: $DIR/issue-91633.rs:7:15: 7:20
- // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a [T], usize) -> &'a <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/issue_99325.main.mir_map.0.mir b/src/test/mir-opt/issue_99325.main.mir_map.0.mir
index 8659ddfdb..165efa9df 100644
--- a/src/test/mir-opt/issue_99325.main.mir_map.0.mir
+++ b/src/test/mir-opt/issue_99325.main.mir_map.0.mir
@@ -2,7 +2,7 @@
| User Type Annotations
| 0: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Value(Branch([Leaf(0x41), Leaf(0x41), Leaf(0x41), Leaf(0x41)])) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:10:16: 10:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
-| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [], promoted: () }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
+| 1: user_ty: Canonical { max_universe: U0, variables: [], value: TypeOf(DefId(0:3 ~ issue_99325[8f58]::function_with_bytes), UserSubsts { substs: [Const { ty: &'static [u8; 4], kind: Unevaluated(UnevaluatedConst { def: WithOptConstParam { did: DefId(0:8 ~ issue_99325[8f58]::main::{constant#1}), const_param_did: Some(DefId(0:4 ~ issue_99325[8f58]::function_with_bytes::BYTES)) }, substs: [] }) }], user_self_ty: None }) }, span: $DIR/issue-99325.rs:11:16: 11:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">}
|
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/issue-99325.rs:+0:15: +0:15
@@ -26,7 +26,7 @@ fn main() -> () {
let _19: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _20: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _21: &&[u8; 4]; // 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 _22: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _23: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _24: (&&[u8], &&[u8; 4]); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _25: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -46,7 +46,7 @@ fn main() -> () {
let _40: &&[u8]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _41: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _42: &&[u8; 4]; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _43: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _43: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 {
debug left_val => _8; // in scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
debug right_val => _9; // in scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -101,7 +101,7 @@ fn main() -> () {
_11 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _12, move _13) -> [return: bb2, unwind: bb19]; // scope 1 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<'r, 's> fn(&'r &[u8], &'s &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b> fn(&'a &[u8], &'b &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value(<ZST>) }
}
bb2: {
@@ -128,11 +128,11 @@ fn main() -> () {
_21 = &(*_9); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_20 = &(*_21); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_22); // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _22 = Option::<Arguments>::None; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _22 = Option::<Arguments<'_>>::None; // scope 2 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_16 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _17, move _18, move _20, move _22) -> bb19; // scope 2 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<'r, 's, 't0> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a &[u8], &'b &[u8; 4], Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value(<ZST>) }
}
bb4: {
@@ -210,7 +210,7 @@ fn main() -> () {
_32 = <&[u8] as PartialEq<&[u8; 4]>>::eq(move _33, move _34) -> [return: bb11, unwind: bb19]; // 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: for<'r, 's> fn(&'r &[u8], &'s &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b> fn(&'a &[u8], &'b &[u8; 4]) -> bool {<&[u8] as PartialEq<&[u8; 4]>>::eq}, val: Value(<ZST>) }
}
bb11: {
@@ -237,11 +237,11 @@ fn main() -> () {
_42 = &(*_30); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_41 = &(*_42); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
StorageLive(_43); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- _43 = Option::<Arguments>::None; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ _43 = Option::<Arguments<'_>>::None; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_37 = core::panicking::assert_failed::<&[u8], &[u8; 4]>(move _38, move _39, move _41, move _43) -> bb19; // scope 4 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<'r, 's, 't0> fn(core::panicking::AssertKind, &'r &[u8], &'s &[u8; 4], Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a &[u8], &'b &[u8; 4], Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<&[u8], &[u8; 4]>}, val: Value(<ZST>) }
}
bb13: {
diff --git a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index a648e5d67..d962ef8cb 100644
--- a/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -32,7 +32,7 @@
- _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:49:5: 49:41
-- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
+ _2 = discriminant((*_3)); // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
+ goto -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
}
@@ -53,7 +53,7 @@
- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:50:5: 50:41
-- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
+ _5 = discriminant((*_6)); // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
+ goto -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
}
@@ -74,7 +74,7 @@
- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:51:5: 51:41
-- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
+ _9 = discriminant((*_10)); // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
+ goto -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
}
@@ -95,7 +95,7 @@
- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
- // mir::Constant
- // + span: $DIR/lower_intrinsics.rs:52:5: 52:41
-- // + literal: Const { ty: for<'r> extern "rust-intrinsic" fn(&'r E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
+ _13 = discriminant((*_14)); // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
+ goto -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
}
diff --git a/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
index 4fb6752b6..ec15fd1ef 100644
--- a/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
+++ b/src/test/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
@@ -36,7 +36,7 @@
_7 = &_1; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33
_6 = &raw const (*_7); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:33
_5 = _6; // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:45
- _4 = move _5 as *const i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
+ _4 = move _5 as *const i32 (PtrToPtr); // scope 3 at $DIR/lower_intrinsics.rs:+4:29: +4:59
StorageDead(_5); // scope 3 at $DIR/lower_intrinsics.rs:+4:58: +4:59
StorageLive(_8); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
StorageLive(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
@@ -45,7 +45,7 @@
_11 = &mut _2; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69
_10 = &raw mut (*_11); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:69
_9 = _10; // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
- _8 = move _9 as *mut i32 (Misc); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
+ _8 = move _9 as *mut i32 (PtrToPtr); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
StorageDead(_9); // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
- _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
- // mir::Constant
diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
index 46fccba56..5f5d6e68f 100644
--- a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
+++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
@@ -23,7 +23,7 @@
- _5 = core::slice::<impl [u8]>::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
- // mir::Constant
- // + span: $DIR/lower_slice_len.rs:5:22: 5:25
-- // + literal: Const { ty: for<'r> fn(&'r [u8]) -> usize {core::slice::<impl [u8]>::len}, val: Value(<ZST>) }
+- // + literal: Const { ty: for<'a> fn(&'a [u8]) -> usize {core::slice::<impl [u8]>::len}, val: Value(<ZST>) }
+ _5 = Len((*_6)); // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
+ goto -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
}
diff --git a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
index 25c6e3060..963e7cde6 100644
--- a/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
@@ -20,7 +20,7 @@ fn main() -> () {
_2 = <str as ToString>::to_string(move _3) -> bb1; // scope 0 at $DIR/no-spurious-drop-after-call.rs:+1:20: +1:34
// mir::Constant
// + span: $DIR/no-spurious-drop-after-call.rs:9:23: 9:32
- // + literal: Const { ty: for<'r> fn(&'r str) -> String {<str as ToString>::to_string}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a str) -> String {<str as ToString>::to_string}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
index 9e89bd9fb..ce35f920b 100644
--- a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
+++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
@@ -1,13 +1,13 @@
- // MIR for `nrvo` before RenameReturnPlace
+ // MIR for `nrvo` after RenameReturnPlace
- fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
+ fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] {
debug init => _1; // in scope 0 at $DIR/nrvo-simple.rs:+0:9: +0:13
- let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+0:39: +0:49
+ let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16
let mut _2: [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+1:9: +1:16
let _3: (); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:19
- let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:9
+ let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:+2:5: +2:9
let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18
let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/nrvo-simple.rs:+2:10: +2:18
scope 1 {
diff --git a/src/test/mir-opt/remove-never-const.rs b/src/test/mir-opt/remove-never-const.rs
index 017746647..16095cfdd 100644
--- a/src/test/mir-opt/remove-never-const.rs
+++ b/src/test/mir-opt/remove-never-const.rs
@@ -6,7 +6,6 @@
// compile-flags: --emit mir,link
#![feature(never_type)]
-#![warn(const_err)]
struct PrintName<T>(T);
diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index 99667aabd..188aa5564 100644
--- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -57,7 +57,7 @@
_7 = <std::ops::Range<i32> as Iterator>::next(move _8) -> bb3; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
// mir::Constant
// + span: $DIR/remove_storage_markers.rs:10:14: 10:19
- // + literal: Const { ty: for<'r> fn(&'r mut std::ops::Range<i32>) -> Option<<std::ops::Range<i32> as Iterator>::Item> {<std::ops::Range<i32> as Iterator>::next}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<i32>) -> Option<<std::ops::Range<i32> as Iterator>::Item> {<std::ops::Range<i32> as Iterator>::next}, val: Value(<ZST>) }
}
bb3: {
diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index 899bb67fb..fe57e32a7 100644
--- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -29,7 +29,7 @@ fn array_casts() -> () {
let _31: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let mut _32: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
let _33: &usize; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
- let mut _34: std::option::Option<std::fmt::Arguments>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+ let mut _34: std::option::Option<std::fmt::Arguments<'_>>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
scope 1 {
debug x => _1; // in scope 1 at $DIR/retag.rs:+1:9: +1:14
let _2: *mut usize; // in scope 1 at $DIR/retag.rs:+2:9: +2:10
@@ -180,7 +180,7 @@ fn array_casts() -> () {
_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
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: for<'r, 's, 't0> fn(core::panicking::AssertKind, &'r usize, &'s usize, Option<Arguments<'t0>>) -> ! {core::panicking::assert_failed::<usize, usize>}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a usize, &'b usize, Option<Arguments<'c>>) -> ! {core::panicking::assert_failed::<usize, usize>}, val: Value(<ZST>) }
}
bb4: {
diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index 84f674db2..cdc413c56 100644
--- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
@@ -11,7 +11,7 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
_3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
// mir::Constant
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- // + literal: Const { ty: for<'r> fn(&'r mut Test) {<Test as Drop>::drop}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a mut Test) {<Test as Drop>::drop}, val: Value(<ZST>) }
}
bb1: {
diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 7212de52f..81225b44e 100644
--- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -11,7 +11,7 @@ fn main() -> () {
let mut _9: &mut i32; // in scope 0 at $DIR/retag.rs:+4:19: +4:20
let mut _12: *mut i32; // in scope 0 at $DIR/retag.rs:+7:18: +7:29
let mut _14: [closure@main::{closure#0}]; // in scope 0 at $DIR/retag.rs:+11:31: +14:6
- let mut _16: for<'r> fn(&'r i32) -> &'r i32; // in scope 0 at $DIR/retag.rs:+15:14: +15:15
+ let mut _16: for<'a> fn(&'a i32) -> &'a i32; // in scope 0 at $DIR/retag.rs:+15:14: +15:15
let mut _17: &i32; // in scope 0 at $DIR/retag.rs:+15:16: +15:18
let _18: &i32; // in scope 0 at $DIR/retag.rs:+15:16: +15:18
let _19: &i32; // in scope 0 at $DIR/retag.rs:+18:5: +18:24
@@ -25,7 +25,7 @@ fn main() -> () {
scope 1 {
debug x => _1; // in scope 1 at $DIR/retag.rs:+1:9: +1:14
let _3: &mut i32; // in scope 1 at $DIR/retag.rs:+3:13: +3:14
- let _13: for<'r> fn(&'r i32) -> &'r i32; // in scope 1 at $DIR/retag.rs:+11:9: +11:10
+ let _13: for<'a> fn(&'a i32) -> &'a i32; // in scope 1 at $DIR/retag.rs:+11:9: +11:10
scope 2 {
debug v => _3; // in scope 2 at $DIR/retag.rs:+3:13: +3:14
let _8: &mut i32; // in scope 2 at $DIR/retag.rs:+4:13: +4:14
@@ -75,7 +75,7 @@ fn main() -> () {
_3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
// mir::Constant
// + span: $DIR/retag.rs:33:25: 33:28
- // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x mut i32) -> &'x mut i32 {Test::foo}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'x> fn(&'a Test, &'x mut i32) -> &'x mut i32 {Test::foo}, val: Value(<ZST>) }
}
bb1: {
@@ -114,7 +114,7 @@ fn main() -> () {
StorageLive(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
Deinit(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
Retag(_14); // scope 1 at $DIR/retag.rs:+11:31: +14:6
- _13 = move _14 as for<'r> fn(&'r i32) -> &'r i32 (Pointer(ClosureFnPointer(Normal))); // 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
StorageLive(_15); // scope 6 at $DIR/retag.rs:+15:9: +15:11
StorageLive(_16); // scope 6 at $DIR/retag.rs:+15:14: +15:15
@@ -154,7 +154,7 @@ fn main() -> () {
_19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
// mir::Constant
// + span: $DIR/retag.rs:48:13: 48:20
- // + literal: Const { ty: for<'r, 'x> fn(&'r Test, &'x i32) -> &'x i32 {Test::foo_shr}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a, 'x> fn(&'a Test, &'x i32) -> &'x i32 {Test::foo_shr}, val: Value(<ZST>) }
}
bb4: {
diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index b4b317e84..31ccf1454 100644
--- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -84,7 +84,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
bb13: {
_15 = &raw mut (*_1); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
- _9 = move _15 as *mut std::string::String (Misc); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+ _9 = move _15 as *mut std::string::String (PtrToPtr); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
_10 = Offset(_9, move _3); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
goto -> bb12; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
}
diff --git a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
index 7ffd242e0..ed9f3bdbd 100644
--- a/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
@@ -34,6 +34,6 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
_3 = <Vec<i32> as Drop>::drop(move _2) -> [return: bb5, unwind: bb4]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
// mir::Constant
// + span: $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- // + literal: Const { ty: for<'r> fn(&'r mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a mut Vec<i32>) {<Vec<i32> as Drop>::drop}, val: Value(<ZST>) }
}
}
diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp
index 752c36a0f..18e6d75b1 100644
--- a/src/test/pretty/issue-4264.pp
+++ b/src/test/pretty/issue-4264.pp
@@ -32,12 +32,12 @@ fn bar() ({
({
let res =
((::alloc::fmt::format as
- for<'r> fn(Arguments<'r>) -> String {format})(((::core::fmt::Arguments::new_v1
+ for<'a> fn(Arguments<'a>) -> String {format})(((::core::fmt::Arguments::new_v1
as
- fn(&[&'static str], &[ArgumentV1]) -> Arguments {Arguments::new_v1})((&([("test"
+ fn(&[&'static str], &[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 [ArgumentV1<'_>; 0]) as &[ArgumentV1<'_>; 0])) as
+ Arguments<'_>)) as String);
(res as String)
} as String);
} as ())
diff --git a/src/test/pretty/issue-85089.pp b/src/test/pretty/issue-85089.pp
new file mode 100644
index 000000000..f84e9df04
--- /dev/null
+++ b/src/test/pretty/issue-85089.pp
@@ -0,0 +1,20 @@
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// Test to print lifetimes on HIR pretty-printing.
+
+// pretty-compare-only
+// pretty-mode:hir
+// pp-exact:issue-85089.pp
+
+trait A<'x> { }
+trait B<'x> { }
+
+struct Foo<'b> {
+ bar: &'b dyn for<'a> A<'a>,
+}
+
+impl <'a> B<'a> for dyn for<'b> A<'b> { }
+
+impl <'a> A<'a> for Foo<'a> { }
diff --git a/src/test/pretty/issue-85089.rs b/src/test/pretty/issue-85089.rs
new file mode 100644
index 000000000..eb45d4731
--- /dev/null
+++ b/src/test/pretty/issue-85089.rs
@@ -0,0 +1,16 @@
+// Test to print lifetimes on HIR pretty-printing.
+
+// pretty-compare-only
+// pretty-mode:hir
+// pp-exact:issue-85089.pp
+
+trait A<'x> {}
+trait B<'x> {}
+
+struct Foo<'b> {
+ pub bar: &'b dyn for<'a> A<'a>,
+}
+
+impl<'a> B<'a> for dyn for<'b> A<'b> {}
+
+impl<'a> A<'a> for Foo<'a> {}
diff --git a/src/test/pretty/raw-str-nonexpr.rs b/src/test/pretty/raw-str-nonexpr.rs
index 7af80979b..12440b5ae 100644
--- a/src/test/pretty/raw-str-nonexpr.rs
+++ b/src/test/pretty/raw-str-nonexpr.rs
@@ -1,3 +1,4 @@
+// needs-asm-support
// pp-exact
#[cfg(foo = r#"just parse this"#)]
diff --git a/src/test/pretty/tests-are-sorted.pp b/src/test/pretty/tests-are-sorted.pp
new file mode 100644
index 000000000..15dcd4ed9
--- /dev/null
+++ b/src/test/pretty/tests-are-sorted.pp
@@ -0,0 +1,69 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// compile-flags: --crate-type=lib --test
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:tests-are-sorted.pp
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "m_test"]
+pub const m_test: test::TestDescAndFn =
+ test::TestDescAndFn {
+ desc: test::TestDesc {
+ name: test::StaticTestName("m_test"),
+ ignore: false,
+ ignore_message: ::core::option::Option::None,
+ compile_fail: false,
+ no_run: false,
+ should_panic: test::ShouldPanic::No,
+ test_type: test::TestType::Unknown,
+ },
+ testfn: test::StaticTestFn(|| test::assert_test_result(m_test())),
+ };
+fn m_test() {}
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "z_test"]
+pub const z_test: test::TestDescAndFn =
+ test::TestDescAndFn {
+ desc: test::TestDesc {
+ name: test::StaticTestName("z_test"),
+ ignore: false,
+ ignore_message: ::core::option::Option::None,
+ compile_fail: false,
+ no_run: false,
+ should_panic: test::ShouldPanic::No,
+ test_type: test::TestType::Unknown,
+ },
+ testfn: test::StaticTestFn(|| test::assert_test_result(z_test())),
+ };
+fn z_test() {}
+
+extern crate test;
+#[cfg(test)]
+#[rustc_test_marker = "a_test"]
+pub const a_test: test::TestDescAndFn =
+ test::TestDescAndFn {
+ desc: test::TestDesc {
+ name: test::StaticTestName("a_test"),
+ ignore: false,
+ ignore_message: ::core::option::Option::None,
+ compile_fail: false,
+ no_run: false,
+ should_panic: test::ShouldPanic::No,
+ test_type: test::TestType::Unknown,
+ },
+ testfn: test::StaticTestFn(|| test::assert_test_result(a_test())),
+ };
+fn a_test() {}
+#[rustc_main]
+pub fn main() -> () {
+ extern crate test;
+ test::test_main_static(&[&a_test, &m_test, &z_test])
+}
diff --git a/src/test/pretty/tests-are-sorted.rs b/src/test/pretty/tests-are-sorted.rs
new file mode 100644
index 000000000..1f737d547
--- /dev/null
+++ b/src/test/pretty/tests-are-sorted.rs
@@ -0,0 +1,13 @@
+// compile-flags: --crate-type=lib --test
+// pretty-compare-only
+// pretty-mode:expanded
+// pp-exact:tests-are-sorted.pp
+
+#[test]
+fn m_test() {}
+
+#[test]
+fn z_test() {}
+
+#[test]
+fn a_test() {}
diff --git a/src/test/run-make-fulldeps/alloc-no-rc/Makefile b/src/test/run-make-fulldeps/alloc-no-rc/Makefile
new file mode 100644
index 000000000..5f7ae70fa
--- /dev/null
+++ b/src/test/run-make-fulldeps/alloc-no-rc/Makefile
@@ -0,0 +1,4 @@
+include ../tools.mk
+
+all:
+ $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_rc
diff --git a/src/test/run-make-fulldeps/alloc-no-sync/Makefile b/src/test/run-make-fulldeps/alloc-no-sync/Makefile
new file mode 100644
index 000000000..6a258a2dd
--- /dev/null
+++ b/src/test/run-make-fulldeps/alloc-no-sync/Makefile
@@ -0,0 +1,4 @@
+include ../tools.mk
+
+all:
+ $(RUSTC) --edition=2021 -Dwarnings --crate-type=rlib ../../../../library/alloc/src/lib.rs --cfg no_sync
diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile
new file mode 100644
index 000000000..50fca7f24
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/Makefile
@@ -0,0 +1,11 @@
+# ignore-i686-pc-windows-gnu
+
+# This test doesn't work on 32-bit MinGW as cdylib has its own copy of unwinder
+# so cross-DLL unwinding does not work.
+
+include ../tools.mk
+
+all:
+ $(RUSTC) bar.rs --crate-type=cdylib
+ $(RUSTC) foo.rs
+ $(call RUN,foo) 2>&1 | $(CGREP) "Rust cannot catch foreign exceptions"
diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs
new file mode 100644
index 000000000..5f9efe323
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/bar.rs
@@ -0,0 +1,7 @@
+#![crate_type = "cdylib"]
+#![feature(c_unwind)]
+
+#[no_mangle]
+extern "C-unwind" fn panic() {
+ panic!();
+}
diff --git a/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
new file mode 100644
index 000000000..266987c5b
--- /dev/null
+++ b/src/test/run-make-fulldeps/foreign-rust-exceptions/foo.rs
@@ -0,0 +1,13 @@
+#![feature(c_unwind)]
+
+#[cfg_attr(not(windows), link(name = "bar"))]
+#[cfg_attr(windows, link(name = "bar.dll"))]
+extern "C-unwind" {
+ fn panic();
+}
+
+fn main() {
+ let _ = std::panic::catch_unwind(|| {
+ unsafe { panic() };
+ });
+}
diff --git a/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile
index 3c4dade0f..ff9cc5709 100644
--- a/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile
+++ b/src/test/run-make-fulldeps/intrinsic-unreachable/Makefile
@@ -1,5 +1,6 @@
include ../tools.mk
+# needs-asm-support
# ignore-windows-msvc
#
# Because of Windows exception handling, the code is not necessarily any shorter.
diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs
index fd294b018..7e1b6aeb3 100644
--- a/src/test/run-make-fulldeps/issue-19371/foo.rs
+++ b/src/test/run-make-fulldeps/issue-19371/foo.rs
@@ -5,7 +5,6 @@ extern crate rustc_driver;
extern crate rustc_session;
extern crate rustc_span;
-use rustc_session::DiagnosticOutput;
use rustc_session::config::{Input, Options, OutputType, OutputTypes};
use rustc_interface::interface;
use rustc_span::source_map::FileName;
@@ -55,7 +54,6 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
output_file: Some(output),
output_dir: None,
file_loader: None,
- diagnostic_output: DiagnosticOutput::Default,
lint_caps: Default::default(),
parse_sess_created: None,
register_lints: None,
diff --git a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
index 8f78bda03..a6c60df83 100644
--- a/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
+++ b/src/test/run-make-fulldeps/obtain-borrowck/driver.rs
@@ -69,25 +69,25 @@ impl rustc_driver::Callbacks for CompilerCalls {
let crate_items = tcx.hir_crate_items(());
for id in crate_items.items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Fn) {
- bodies.push(id.def_id);
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Fn) {
+ bodies.push(id.owner_id);
}
}
for id in crate_items.trait_items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::AssocFn) {
let trait_item = hir.trait_item(id);
if let rustc_hir::TraitItemKind::Fn(_, trait_fn) = &trait_item.kind {
if let rustc_hir::TraitFn::Provided(_) = trait_fn {
- bodies.push(trait_item.def_id);
+ bodies.push(trait_item.owner_id);
}
}
}
}
for id in crate_items.impl_items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::AssocFn) {
- bodies.push(id.def_id);
+ if matches!(tcx.def_kind(id.owner_id), DefKind::AssocFn) {
+ bodies.push(id.owner_id);
}
}
diff --git a/src/test/run-make-fulldeps/print-calling-conventions/Makefile b/src/test/run-make-fulldeps/print-calling-conventions/Makefile
new file mode 100644
index 000000000..d3fd06392
--- /dev/null
+++ b/src/test/run-make-fulldeps/print-calling-conventions/Makefile
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+ $(RUSTC) --print calling-conventions
diff --git a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
index bac3970a4..d8658a0f2 100644
--- a/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
+++ b/src/test/run-make-fulldeps/rustdoc-scrape-examples-macros/src/lib.rs
@@ -1,8 +1,8 @@
// Scraped example should only include line numbers for items b and c in ex.rs
-// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '14'
-// @has foobar/fn.f.html '//*[@class="line-numbers"]' '15'
-// @has foobar/fn.f.html '//*[@class="line-numbers"]' '21'
-// @!has foobar/fn.f.html '//*[@class="line-numbers"]' '22'
+// @!has foobar/fn.f.html '//*[@class="src-line-numbers"]' '14'
+// @has foobar/fn.f.html '//*[@class="src-line-numbers"]' '15'
+// @has foobar/fn.f.html '//*[@class="src-line-numbers"]' '21'
+// @!has foobar/fn.f.html '//*[@class="src-line-numbers"]' '22'
pub fn f() {}
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
index 6fc2a6bad..64b2f75ef 100644
--- a/src/test/run-make/coverage-reports/Makefile
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -1,6 +1,11 @@
# needs-profiler-support
# ignore-windows-gnu
+# FIXME(pietroalbini): this test currently does not work on cross-compiled
+# targets because remote-test is not capable of sending back the *.profraw
+# files generated by the LLVM instrumentation.
+# ignore-cross-compile
+
# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6,
# corresponding with LLVM versions 12 and 13, respectively.
# When upgrading LLVM versions, consider whether to enforce a minimum LLVM
@@ -75,19 +80,19 @@ ifdef RUSTC_BLESS_TEST
rm -f expected_*
endif
-include clear_expected_if_blessed
+-include clear_expected_if_blessed
%: $(SOURCEDIR)/lib/%.rs
# Compile the test library with coverage instrumentation
$(RUSTC) $(SOURCEDIR)/lib/$@.rs \
$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \
- --crate-type rlib -Cinstrument-coverage
+ --crate-type rlib -Cinstrument-coverage --target $(TARGET)
%: $(SOURCEDIR)/%.rs
# Compile the test program with coverage instrumentation
$(RUSTC) $(SOURCEDIR)/$@.rs \
$$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \
- -L "$(TMPDIR)" -Cinstrument-coverage
+ -L "$(TMPDIR)" -Cinstrument-coverage --target $(TARGET)
# Run it in order to generate some profiling data,
# with `LLVM_PROFILE_FILE=<profdata_file>` environment variable set to
diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile
index b5270ad2b..986a3f4e6 100644
--- a/src/test/run-make/issue-36710/Makefile
+++ b/src/test/run-make/issue-36710/Makefile
@@ -1,10 +1,6 @@
-# ignore-riscv64 $(call RUN,foo) expects to run the target executable natively
+# ignore-cross-compile $(call RUN,foo) expects to run the target executable natively
# so it won't work with remote-test-server
-# ignore-arm Another build using remote-test-server
# ignore-none no-std is not supported
-# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM
-# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM
-# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std`
# ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain
# (see dist-i586-gnu-i586-i686-musl Dockerfile)
diff --git a/src/test/run-make/macos-fat-archive/Makefile b/src/test/run-make/macos-fat-archive/Makefile
new file mode 100644
index 000000000..cc99375db
--- /dev/null
+++ b/src/test/run-make/macos-fat-archive/Makefile
@@ -0,0 +1,10 @@
+# only-macos
+
+-include ../../run-make-fulldeps/tools.mk
+
+"$(TMPDIR)"/libnative-library.a: native-library.c
+ $(CC) -arch arm64 -arch x86_64 native-library.c -c -o "$(TMPDIR)"/native-library.o
+ $(AR) crs "$(TMPDIR)"/libnative-library.a "$(TMPDIR)"/native-library.o
+
+all: "$(TMPDIR)"/libnative-library.a
+ $(RUSTC) lib.rs --crate-type=lib -L "native=$(TMPDIR)" -l static=native-library
diff --git a/src/test/run-make/macos-fat-archive/lib.rs b/src/test/run-make/macos-fat-archive/lib.rs
new file mode 100644
index 000000000..9943a266c
--- /dev/null
+++ b/src/test/run-make/macos-fat-archive/lib.rs
@@ -0,0 +1,3 @@
+extern "C" {
+ pub fn native_func();
+}
diff --git a/src/test/run-make/macos-fat-archive/native-library.c b/src/test/run-make/macos-fat-archive/native-library.c
new file mode 100644
index 000000000..d300fdf1c
--- /dev/null
+++ b/src/test/run-make/macos-fat-archive/native-library.c
@@ -0,0 +1 @@
+void native_func() {}
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/Makefile b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile
new file mode 100644
index 000000000..e56e1e94e
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/Makefile
@@ -0,0 +1,15 @@
+# ignore-cross-compile
+# ignore-macos
+
+include ../../run-make-fulldeps/tools.mk
+
+all:
+ # Verbatim allows specify precise name.
+ $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_some_strange_name.ext
+ $(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_some_strange_name.ext
+
+ # With verbatim any other name cannot be used (local).
+ $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/liblocal_native_dep.a
+ $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.a
+ $(RUSTC) local_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/local_native_dep.lib
+ $(RUSTC) main.rs -Zunstable-options -l static:+verbatim=local_native_dep 2>&1 | $(CGREP) "local_native_dep"
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs b/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
new file mode 100644
index 000000000..59b6c92d2
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/local_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn local_native_f() -> i32 {
+ return 0;
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-linker/main.rs b/src/test/run-make/native-link-modifier-verbatim-linker/main.rs
new file mode 100644
index 000000000..71b73a489
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-linker/main.rs
@@ -0,0 +1,9 @@
+extern "C" {
+ fn local_native_f() -> i32;
+}
+
+pub fn main() {
+ unsafe {
+ assert!(local_native_f() == 0);
+ };
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile
new file mode 100644
index 000000000..1093b1cd3
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/Makefile
@@ -0,0 +1,12 @@
+include ../../run-make-fulldeps/tools.mk
+
+all:
+ # Verbatim allows specify precise name.
+ $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_some_strange_name.ext
+ $(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_some_strange_name.ext --crate-type rlib
+
+ # With verbatim any other name cannot be used (upstream).
+ $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/libupstream_native_dep.a
+ $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.a
+ $(RUSTC) upstream_native_dep.rs --crate-type=staticlib -o $(TMPDIR)/upstream_native_dep.lib
+ $(RUSTC) rust_dep.rs -Zunstable-options -l static:+verbatim=upstream_native_dep --crate-type rlib 2>&1 | $(CGREP) "upstream_native_dep"
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs b/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
new file mode 100644
index 000000000..e9517218e
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/rust_dep.rs
@@ -0,0 +1,9 @@
+extern "C" {
+ fn upstream_native_f() -> i32;
+}
+
+pub fn rust_dep() {
+ unsafe {
+ assert!(upstream_native_f() == 0);
+ }
+}
diff --git a/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs b/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
new file mode 100644
index 000000000..839686233
--- /dev/null
+++ b/src/test/run-make/native-link-modifier-verbatim-rustc/upstream_native_dep.rs
@@ -0,0 +1,4 @@
+#[no_mangle]
+pub fn upstream_native_f() -> i32 {
+ return 0;
+}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile b/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile
deleted file mode 100644
index 4574cf17f..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs-2/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
--include ../../run-make-fulldeps/tools.mk
-
-# ignore-cross-compile
-
-# Make sure -Zpacked_bundled_libs is compatible with verbatim.
-
-# 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:
- # Build strange-named dep.
- $(RUSTC) native_dep.rs --crate-type=staticlib -o $(TMPDIR)/native_dep.ext
-
- $(RUSTC) rust_dep.rs --crate-type=rlib -Zpacked_bundled_libs
- $(NM) $(TMPDIR)/librust_dep.rlib | $(CGREP) -e "U.*native_f1"
- $(AR) t $(TMPDIR)/librust_dep.rlib | $(CGREP) "native_dep.ext"
-
- # Make sure compiler doesn't use files, that it shouldn't know about.
- rm $(TMPDIR)/native_dep.ext
-
- $(RUSTC) main.rs --extern rust_dep=$(TMPDIR)/librust_dep.rlib -Zpacked_bundled_libs
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs
deleted file mode 100644
index 8d2b8a285..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs-2/main.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-extern crate rust_dep;
-
-pub fn main() {
- rust_dep::rust_dep();
-}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs
deleted file mode 100644
index 321a8237e..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs-2/native_dep.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[no_mangle]
-pub fn native_f1() -> i32 {
- return 1;
-}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs b/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs
deleted file mode 100644
index d99dda05c..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs-2/rust_dep.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(native_link_modifiers_verbatim)]
-#[link(name = "native_dep.ext", kind = "static", modifiers = "+verbatim")]
-extern "C" {
- fn native_f1() -> i32;
-}
-
-pub fn rust_dep() {
- unsafe {
- assert!(native_f1() == 1);
- }
-}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/Makefile b/src/test/run-make/rlib-format-packed-bundled-libs/Makefile
deleted file mode 100644
index 0b991ac42..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
--include ../../run-make-fulldeps/tools.mk
-
-# ignore-cross-compile
-
-# Make sure rlib format with -Zpacked_bundled_libs is correct.
-
-# 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)
- $(RUSTC) rust_dep_up.rs --crate-type=rlib -Zpacked_bundled_libs
- $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f2"
- $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "U.*native_f3"
- $(NM) $(TMPDIR)/librust_dep_up.rlib | $(CGREP) -e "T.*rust_dep_up"
- $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_2"
- $(AR) t $(TMPDIR)/librust_dep_up.rlib | $(CGREP) "native_dep_3"
- $(RUSTC) rust_dep_local.rs --extern rlib=$(TMPDIR)/librust_dep_up.rlib -Zpacked_bundled_libs --crate-type=rlib
- $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "U.*native_f1"
- $(NM) $(TMPDIR)/librust_dep_local.rlib | $(CGREP) -e "T.*rust_dep_local"
- $(AR) t $(TMPDIR)/librust_dep_local.rlib | $(CGREP) "native_dep_1"
-
- # Make sure compiler doesn't use files, that it shouldn't know about.
- rm $(TMPDIR)/*native_dep_*
-
- $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_local.rlib -o $(TMPDIR)/main.exe -Zpacked_bundled_libs --print link-args | $(CGREP) -e "native_dep_1.*native_dep_2.*native_dep_3"
-
-ifndef IS_MSVC
- $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f1"
- $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f2"
- $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*native_f3"
- $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_local"
- $(NM) $(TMPDIR)/main.exe | $(CGREP) -e "T.*rust_dep_up"
-endif
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/main.rs b/src/test/run-make/rlib-format-packed-bundled-libs/main.rs
deleted file mode 100644
index 042a4879f..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/main.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-extern crate rust_dep_local;
-pub fn main() {
- rust_dep_local::rust_dep_local();
-}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c
deleted file mode 100644
index 07be8562c..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_1.c
+++ /dev/null
@@ -1 +0,0 @@
-int native_f1() { return 1; }
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c
deleted file mode 100644
index a1b94e40d..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_2.c
+++ /dev/null
@@ -1 +0,0 @@
-int native_f2() { return 2; }
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c b/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c
deleted file mode 100644
index f81f397a4..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/native_dep_3.c
+++ /dev/null
@@ -1 +0,0 @@
-int native_f3() { return 3; }
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs
deleted file mode 100644
index 8280c7d6c..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_local.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#[link(name = "native_dep_1", kind = "static")]
-extern "C" {
- fn native_f1() -> i32;
-}
-
-extern crate rust_dep_up;
-
-pub fn rust_dep_local() {
- unsafe {
- assert!(native_f1() == 1);
- }
- rust_dep_up::rust_dep_up();
-}
diff --git a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs b/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs
deleted file mode 100644
index edcd7c521..000000000
--- a/src/test/run-make/rlib-format-packed-bundled-libs/rust_dep_up.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#[link(name = "native_dep_2", kind = "static")]
-#[link(name = "native_dep_3", kind = "static")]
-extern "C" {
- fn native_f2() -> i32;
- fn native_f3() -> i32;
-}
-
-pub fn rust_dep_up() {
- unsafe {
- assert!(native_f2() == 2);
- assert!(native_f3() == 3);
- }
-}
diff --git a/src/test/rustdoc-gui/anchor-navigable.goml b/src/test/rustdoc-gui/anchor-navigable.goml
index 424c31223..9d5c55a1e 100644
--- a/src/test/rustdoc-gui/anchor-navigable.goml
+++ b/src/test/rustdoc-gui/anchor-navigable.goml
@@ -4,8 +4,8 @@
// anchor and the `impl Foo`. If there were a gap, this would cause an annoying
// problem: you hover `impl Foo` to see the anchor, then when you move your
// mouse to the left, the anchor disappears before you reach it.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// We check that ".item-info" is bigger than its content.
move-cursor-to: ".impl"
-assert-property: (".impl > a.anchor", {"offsetWidth": "9"})
+assert-property: (".impl > a.anchor", {"offsetWidth": "8"})
assert-css: (".impl > a.anchor", {"left": "-8px"})
diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml
index 3ad62c721..fb8e288fa 100644
--- a/src/test/rustdoc-gui/anchors.goml
+++ b/src/test/rustdoc-gui/anchors.goml
@@ -1,154 +1,107 @@
// This test is to ensure that the anchors (`§`) have the expected color and position.
-goto: file://|DOC_PATH|/staged_api/struct.Foo.html
-// This is needed to ensure that the text color is computed.
-show-text: true
-
-// Set the theme to light.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: ("#toggle-all-docs", {"color": "rgb(0, 0, 0)"})
-assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(0, 0, 0)"})
-assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(173, 55, 138)"})
-assert-css: (
- ".rightside .srclink",
- {"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
- ALL,
-)
-compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
-compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
-
-move-cursor-to: ".main-heading .srclink"
-assert-css: (
- ".main-heading .srclink",
- {"color": "rgb(56, 115, 173)", "text-decoration": "underline solid rgb(56, 115, 173)"},
-)
-move-cursor-to: ".impl-items .rightside .srclink"
-assert-css: (
- ".impl-items .rightside .srclink",
- {"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
-)
-move-cursor-to: ".impl-items .rightside.srclink"
-assert-css: (
- ".impl-items .rightside.srclink",
- {"color": "rgb(56, 115, 173)", "text-decoration": "none solid rgb(56, 115, 173)"},
-)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-
-assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"})
-
-assert-css: (".sidebar a", {"color": "rgb(53, 109, 164)"})
-assert-css: (".in-band a", {"color": "rgb(0, 0, 0)"})
-
-// We move the cursor over the "Implementations" title so the anchor is displayed.
-move-cursor-to: "h2#implementations"
-assert-css: ("h2#implementations a.anchor", {"color": "rgb(0, 0, 0)"})
-
-// Same thing with the impl block title.
-move-cursor-to: "#impl-HeavilyDocumentedStruct"
-assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(0, 0, 0)"})
-
-assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
-
-//
-// We do the same checks with the dark theme now.
-//
-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
-goto: file://|DOC_PATH|/staged_api/struct.Foo.html
-
-assert-css: ("#toggle-all-docs", {"color": "rgb(221, 221, 221)"})
-assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(221, 221, 221)"})
-assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(45, 191, 184)"})
-assert-css: (
- ".rightside .srclink",
- {"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
- ALL,
-)
-compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
-compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
-
-move-cursor-to: ".main-heading .srclink"
-assert-css: (
- ".main-heading .srclink",
- {"color": "rgb(210, 153, 29)", "text-decoration": "underline solid rgb(210, 153, 29)"},
+define-function: (
+ "check-colors",
+ (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color),
+ [
+ ("goto", "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"),
+ // This is needed to ensure that the text color is computed.
+ ("show-text", true),
+
+ // 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"),
+
+ ("assert-css", ("#toggle-all-docs", {"color": |main_color|})),
+ ("assert-css", (".fqn a:nth-of-type(1)", {"color": |fqn_color|})),
+ ("assert-css", (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})),
+ ("assert-css", (
+ ".rightside .srclink",
+ {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
+ ALL,
+ )),
+ (
+ "compare-elements-css",
+ (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"]),
+ ),
+ (
+ "compare-elements-css",
+ (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"]),
+ ),
+
+ ("move-cursor-to", ".main-heading .srclink"),
+ ("assert-css", (
+ ".main-heading .srclink",
+ {"color": |src_link_color|, "text-decoration": "underline solid " + |src_link_color|},
+ )),
+ ("move-cursor-to", ".impl-items .rightside .srclink"),
+ ("assert-css", (
+ ".impl-items .rightside .srclink",
+ {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
+ )),
+ ("move-cursor-to", ".impl-items .rightside.srclink"),
+ ("assert-css", (
+ ".impl-items .rightside.srclink",
+ {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|},
+ )),
+
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"),
+ // Since we changed page, we need to set the theme again.
+ ("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", ("#top-doc-prose-title", {"color": |title_color|})),
+
+ ("assert-css", (".sidebar a", {"color": |sidebar_link_color|})),
+ ("assert-css", ("h1.fqn a", {"color": |title_color|})),
+
+ // We move the cursor over the "Implementations" title so the anchor is displayed.
+ ("move-cursor-to", "h2#implementations"),
+ ("assert-css", ("h2#implementations a.anchor", {"color": |main_color|})),
+
+ // Same thing with the impl block title.
+ ("move-cursor-to", "#impl-HeavilyDocumentedStruct"),
+ ("assert-css", ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|})),
+
+ ("assert-css", ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})),
+ ],
)
-move-cursor-to: ".impl-items .rightside .srclink"
-assert-css: (
- ".impl-items .rightside .srclink",
- {"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
-)
-move-cursor-to: ".impl-items .rightside.srclink"
-assert-css: (
- ".impl-items .rightside.srclink",
- {"color": "rgb(210, 153, 29)", "text-decoration": "none solid rgb(210, 153, 29)"},
-)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-
-assert-css: ("#top-doc-prose-title", {"color": "rgb(221, 221, 221)"})
-
-assert-css: (".sidebar a", {"color": "rgb(253, 191, 53)"})
-assert-css: (".in-band a", {"color": "rgb(221, 221, 221)"})
-
-// We move the cursor over the "Implementations" title so the anchor is displayed.
-move-cursor-to: "h2#implementations"
-assert-css: ("h2#implementations a.anchor", {"color": "rgb(221, 221, 221)"})
-
-// Same thing with the impl block title.
-move-cursor-to: "#impl-HeavilyDocumentedStruct"
-assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(221, 221, 221)"})
-
-assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
-
-//
-// We do the same checks with the ayu theme now.
-//
-local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"}
-goto: file://|DOC_PATH|/staged_api/struct.Foo.html
-assert-css: ("#toggle-all-docs", {"color": "rgb(197, 197, 197)"})
-assert-css: (".fqn .in-band a:nth-of-type(1)", {"color": "rgb(255, 255, 255)"})
-assert-css: (".fqn .in-band a:nth-of-type(2)", {"color": "rgb(255, 160, 165)"})
-assert-css: (
- ".rightside .srclink",
- {"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
- ALL,
+call-function: (
+ "check-colors",
+ {
+ "theme": "ayu",
+ "main_color": "rgb(197, 197, 197)",
+ "title_color": "rgb(255, 255, 255)",
+ "fqn_color": "rgb(255, 255, 255)",
+ "fqn_type_color": "rgb(255, 160, 165)",
+ "src_link_color": "rgb(57, 175, 215)",
+ "sidebar_link_color": "rgb(83, 177, 219)",
+ },
)
-compare-elements-css: (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"])
-compare-elements-css: (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"])
-
-move-cursor-to: ".main-heading .srclink"
-assert-css: (
- ".main-heading .srclink",
- {"color": "rgb(57, 175, 215)", "text-decoration": "underline solid rgb(57, 175, 215)"},
-)
-move-cursor-to: ".impl-items .rightside .srclink"
-assert-css: (
- ".impl-items .rightside .srclink",
- {"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
+call-function: (
+ "check-colors",
+ {
+ "theme": "dark",
+ "main_color": "rgb(221, 221, 221)",
+ "title_color": "rgb(221, 221, 221)",
+ "fqn_color": "rgb(221, 221, 221)",
+ "fqn_type_color": "rgb(45, 191, 184)",
+ "src_link_color": "rgb(210, 153, 29)",
+ "sidebar_link_color": "rgb(253, 191, 53)",
+ },
)
-move-cursor-to: ".impl-items .rightside.srclink"
-assert-css: (
- ".impl-items .rightside.srclink",
- {"color": "rgb(57, 175, 215)", "text-decoration": "none solid rgb(57, 175, 215)"},
+call-function: (
+ "check-colors",
+ {
+ "theme": "light",
+ "main_color": "rgb(0, 0, 0)",
+ "title_color": "rgb(0, 0, 0)",
+ "fqn_color": "rgb(0, 0, 0)",
+ "fqn_type_color": "rgb(173, 55, 138)",
+ "src_link_color": "rgb(56, 115, 173)",
+ "sidebar_link_color": "rgb(53, 109, 164)",
+ },
)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-
-assert-css: ("#top-doc-prose-title", {"color": "rgb(255, 255, 255)"})
-
-assert-css: (".sidebar a", {"color": "rgb(83, 177, 219)"})
-assert-css: (".in-band a", {"color": "rgb(255, 255, 255)"})
-
-// We move the cursor over the "Implementations" title so the anchor is displayed.
-move-cursor-to: "h2#implementations"
-assert-css: ("h2#implementations a.anchor", {"color": "rgb(197, 197, 197)"})
-
-// Same thing with the impl block title.
-move-cursor-to: "#impl-HeavilyDocumentedStruct"
-assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": "rgb(197, 197, 197)"})
-
-assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})
diff --git a/src/test/rustdoc-gui/auto-hide-trait-implementations.goml b/src/test/rustdoc-gui/auto-hide-trait-implementations.goml
index 7b1358fed..0a619c352 100644
--- a/src/test/rustdoc-gui/auto-hide-trait-implementations.goml
+++ b/src/test/rustdoc-gui/auto-hide-trait-implementations.goml
@@ -1,5 +1,5 @@
// Checks that the setting "auto hide trait implementations" is working as expected.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// By default, the trait implementations are not collapsed.
assert-attribute: ("#trait-implementations-list > details", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-gui/basic-code.goml b/src/test/rustdoc-gui/basic-code.goml
index 27deb2c98..f4ba5a128 100644
--- a/src/test/rustdoc-gui/basic-code.goml
+++ b/src/test/rustdoc-gui/basic-code.goml
@@ -1,3 +1,3 @@
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
click: ".srclink"
-assert-count: (".line-numbers", 1)
+assert-count: (".src-line-numbers", 1)
diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml
index 239e51a91..60292835b 100644
--- a/src/test/rustdoc-gui/basic.goml
+++ b/src/test/rustdoc-gui/basic.goml
@@ -1,4 +1,4 @@
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
assert: ("#functions")
-goto: ./struct.Foo.html
+goto: "./struct.Foo.html"
assert: ("div.item-decl")
diff --git a/src/test/rustdoc-gui/check-code-blocks-margin.goml b/src/test/rustdoc-gui/check-code-blocks-margin.goml
index f6266eba7..c2cec0020 100644
--- a/src/test/rustdoc-gui/check-code-blocks-margin.goml
+++ b/src/test/rustdoc-gui/check-code-blocks-margin.goml
@@ -1,6 +1,6 @@
// This test ensures that the docblock elements have the appropriate left margin.
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
// The top docblock elements shouldn't have left margin...
-assert-css: ("#main-content .docblock.item-decl", {"margin-left": "0px"})
+assert-css: ("#main-content .item-decl", {"margin-left": "0px"})
// ... but all the others should!
-assert-css: ("#main-content .docblock:not(.item-decl)", {"margin-left": "24px"})
+assert-css: ("#main-content .docblock", {"margin-left": "24px"})
diff --git a/src/test/rustdoc-gui/check-stab-in-docblock.goml b/src/test/rustdoc-gui/check-stab-in-docblock.goml
new file mode 100644
index 000000000..266fa9997
--- /dev/null
+++ b/src/test/rustdoc-gui/check-stab-in-docblock.goml
@@ -0,0 +1,27 @@
+// This test checks that using `.stab` attributes in `.docblock` elements doesn't
+// create scrollable paragraphs.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// Needs the text to be display to check for scrollable content.
+show-text: true
+size: (786, 600)
+// Confirms that there 3 paragraphs.
+assert-count: (".top-doc .docblock p", 3)
+// Checking that there is no scrollable content.
+store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(1)", "clientHeight")
+store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(1)", "clientWidth")
+assert-property: (
+ ".top-doc .docblock p:nth-of-type(1)",
+ {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|},
+)
+store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(2)", "clientHeight")
+store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(2)", "clientWidth")
+assert-property: (
+ ".top-doc .docblock p:nth-of-type(2)",
+ {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|},
+)
+store-property: (clientHeight, ".top-doc .docblock p:nth-of-type(3)", "clientHeight")
+store-property: (clientWidth, ".top-doc .docblock p:nth-of-type(3)", "clientWidth")
+assert-property: (
+ ".top-doc .docblock p:nth-of-type(3)",
+ {"scrollHeight": |clientHeight|, "scrollWidth": |clientWidth|},
+)
diff --git a/src/test/rustdoc-gui/check_info_sign_position.goml b/src/test/rustdoc-gui/check_info_sign_position.goml
index 47a78f02f..f36e73fc5 100644
--- a/src/test/rustdoc-gui/check_info_sign_position.goml
+++ b/src/test/rustdoc-gui/check_info_sign_position.goml
@@ -1,7 +1,7 @@
// This test checks the position of the information on the code blocks (like
// `compile_fail` or `ignore`).
-goto: file://|DOC_PATH|/test_docs/index.html
-goto: ./fn.check_list_code_block.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+goto: "./fn.check_list_code_block.html"
// If the codeblock is the first element of the docblock, the information tooltip must have
// have some top margin to avoid going over the toggle (the "[+]").
assert-css: (".docblock > .example-wrap.compile_fail .tooltip", { "margin-top": "16px" })
diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml
index f93f3f0ae..fbf0e890b 100644
--- a/src/test/rustdoc-gui/code-blocks-overflow.goml
+++ b/src/test/rustdoc-gui/code-blocks-overflow.goml
@@ -1,8 +1,8 @@
// This test ensures that codeblocks content don't overflow.
-goto: file://|DOC_PATH|/lib2/sub_mod/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html"
size: (1080, 600)
// There should be two codeblocks: a rust one and a non-rust one.
assert-count: (".docblock > .example-wrap", 2)
assert: ".docblock > .example-wrap > .language-txt"
assert: ".docblock > .example-wrap > .rust-example-rendered"
-assert-css: (".docblock > .example-wrap > pre", {"width": "785.25px", "overflow-x": "auto"}, ALL)
+assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL)
diff --git a/src/test/rustdoc-gui/code-color.goml b/src/test/rustdoc-gui/code-color.goml
index 2f95bfb6b..118f04ad6 100644
--- a/src/test/rustdoc-gui/code-color.goml
+++ b/src/test/rustdoc-gui/code-color.goml
@@ -2,29 +2,23 @@
// check that the rule isn't applied on other "<code>" elements.
//
// While we're at it, we also check it for the other themes.
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
// If the text isn't displayed, the browser doesn't compute color style correctly...
show-text: true
-// Set the theme to dark.
-local-storage: {"rustdoc-theme": "dark", "rustdoc-preferred-dark-theme": "dark", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-assert-css: (".docblock pre > code", {"color": "rgb(221, 221, 221)"}, ALL)
-assert-css: (".docblock > p > code", {"color": "rgb(221, 221, 221)"}, ALL)
+define-function: (
+ "check-colors",
+ (theme, doc_code_color, doc_inline_code_color),
+ [
+ // Set 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"),
+ ("assert-css", (".docblock pre > code", {"color": |doc_code_color|}, ALL)),
+ ("assert-css", (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL)),
+ ],
+)
-// Set the theme to ayu.
-local-storage: {"rustdoc-theme": "ayu", "rustdoc-preferred-dark-theme": "ayu", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (".docblock pre > code", {"color": "rgb(230, 225, 207)"}, ALL)
-assert-css: (".docblock > p > code", {"color": "rgb(255, 180, 84)"}, ALL)
-
-// Set the theme to light.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (".docblock pre > code", {"color": "rgb(0, 0, 0)"}, ALL)
-assert-css: (".docblock > p > code", {"color": "rgb(0, 0, 0)"}, ALL)
+call-function: ("check-colors", ("ayu", "rgb(230, 225, 207)", "rgb(255, 180, 84)"))
+call-function: ("check-colors", ("dark", "rgb(221, 221, 221)", "rgb(221, 221, 221)"))
+call-function: ("check-colors", ("light", "rgb(0, 0, 0)", "rgb(0, 0, 0)"))
diff --git a/src/test/rustdoc-gui/code-sidebar-toggle.goml b/src/test/rustdoc-gui/code-sidebar-toggle.goml
index 867db0569..00a0ea1e1 100644
--- a/src/test/rustdoc-gui/code-sidebar-toggle.goml
+++ b/src/test/rustdoc-gui/code-sidebar-toggle.goml
@@ -1,5 +1,5 @@
// This test checks that the source code pages sidebar toggle is working as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
click: ".srclink"
wait-for: "#sidebar-toggle"
click: "#sidebar-toggle"
diff --git a/src/test/rustdoc-gui/code-tags.goml b/src/test/rustdoc-gui/code-tags.goml
index 8d399a9a5..837a2c1d5 100644
--- a/src/test/rustdoc-gui/code-tags.goml
+++ b/src/test/rustdoc-gui/code-tags.goml
@@ -1,5 +1,5 @@
// This test ensures that items and documentation code blocks are wrapped in <pre><code>
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
size: (1080, 600)
// There should be four doc codeblocks.
// Check that their content is inside <pre><code>
@@ -7,14 +7,14 @@ assert-count: (".example-wrap pre > code", 4)
// Check that function signature is inside <pre><code>
assert: "pre.rust.fn > code"
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
assert: "pre.rust.struct > code"
-goto: file://|DOC_PATH|/test_docs/enum.AnEnum.html
+goto: "file://" + |DOC_PATH| + "/test_docs/enum.AnEnum.html"
assert: "pre.rust.enum > code"
-goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
+goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
assert: "pre.rust.trait > code"
-goto: file://|DOC_PATH|/test_docs/type.SomeType.html
+goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
assert: "pre.rust.typedef > code"
diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml
index 21a9e120c..8e681a2a0 100644
--- a/src/test/rustdoc-gui/codeblock-tooltip.goml
+++ b/src/test/rustdoc-gui/codeblock-tooltip.goml
@@ -1,96 +1,80 @@
// Checking the colors of the codeblocks tooltips.
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
show-text: true
-// Dark theme.
-local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
-reload:
-
-// compile_fail block
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.compile_fail"
-
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// should_panic block
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.should_panic"
-
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// ignore block
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgba(255, 142, 0, 0.6)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
-
-move-cursor-to: ".docblock .example-wrap.ignore"
-
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgb(255, 142, 0)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
-
-
-// Light theme.
-local-storage: {"rustdoc-theme": "light"}
-reload:
-
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.compile_fail"
-
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// should_panic block
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.should_panic"
-
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// ignore block
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgba(255, 142, 0, 0.6)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
-
-move-cursor-to: ".docblock .example-wrap.ignore"
-
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgb(255, 142, 0)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
-
-
-// Ayu theme.
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.compile_fail"
-
-assert-css: (".docblock .example-wrap.compile_fail .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// should_panic block
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgba(255, 0, 0, 0.5)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"})
-
-move-cursor-to: ".docblock .example-wrap.should_panic"
-
-assert-css: (".docblock .example-wrap.should_panic .tooltip", {"color": "rgb(255, 0, 0)"})
-assert-css: (".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"})
-
-// ignore block
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgba(255, 142, 0, 0.6)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"})
-
-move-cursor-to: ".docblock .example-wrap.ignore"
-
-assert-css: (".docblock .example-wrap.ignore .tooltip", {"color": "rgb(255, 142, 0)"})
-assert-css: (".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"})
+define-function: (
+ "check-colors",
+ (theme),
+ [
+ // Setting the theme.
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+
+ // compile_fail block
+ ("assert-css", (
+ ".docblock .example-wrap.compile_fail .tooltip",
+ {"color": "rgba(255, 0, 0, 0.5)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.compile_fail",
+ {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
+ )),
+
+ ("move-cursor-to", ".docblock .example-wrap.compile_fail"),
+
+ ("assert-css", (
+ ".docblock .example-wrap.compile_fail .tooltip",
+ {"color": "rgb(255, 0, 0)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.compile_fail",
+ {"border-left": "2px solid rgb(255, 0, 0)"},
+ )),
+
+ // should_panic block
+ ("assert-css", (
+ ".docblock .example-wrap.should_panic .tooltip",
+ {"color": "rgba(255, 0, 0, 0.5)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.should_panic",
+ {"border-left": "2px solid rgba(255, 0, 0, 0.5)"},
+ )),
+
+ ("move-cursor-to", ".docblock .example-wrap.should_panic"),
+
+ ("assert-css", (
+ ".docblock .example-wrap.should_panic .tooltip",
+ {"color": "rgb(255, 0, 0)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.should_panic",
+ {"border-left": "2px solid rgb(255, 0, 0)"},
+ )),
+
+ // ignore block
+ ("assert-css", (
+ ".docblock .example-wrap.ignore .tooltip",
+ {"color": "rgba(255, 142, 0, 0.6)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.ignore",
+ {"border-left": "2px solid rgba(255, 142, 0, 0.6)"},
+ )),
+
+ ("move-cursor-to", ".docblock .example-wrap.ignore"),
+
+ ("assert-css", (
+ ".docblock .example-wrap.ignore .tooltip",
+ {"color": "rgb(255, 142, 0)"},
+ )),
+ ("assert-css", (
+ ".docblock .example-wrap.ignore",
+ {"border-left": "2px solid rgb(255, 142, 0)"},
+ )),
+ ],
+)
+
+call-function: ("check-colors", ("ayu"))
+call-function: ("check-colors", ("dark"))
+call-function: ("check-colors", ("light"))
diff --git a/src/test/rustdoc-gui/default-settings.goml b/src/test/rustdoc-gui/default-settings.goml
index 90f0b087a..ab27b001e 100644
--- a/src/test/rustdoc-gui/default-settings.goml
+++ b/src/test/rustdoc-gui/default-settings.goml
@@ -2,7 +2,7 @@
//
// The "settings" crate uses "ayu" as default setting, which is what we will
// check.
-goto: file://|DOC_PATH|/settings/index.html
+goto: "file://" + |DOC_PATH| + "/settings/index.html"
// Wait a bit to be sure the default theme is applied.
// If the theme isn't applied, the command will time out.
wait-for-css: ("body", {"background-color": "rgb(15, 20, 25)"})
diff --git a/src/test/rustdoc-gui/docblock-big-code-mobile.goml b/src/test/rustdoc-gui/docblock-big-code-mobile.goml
index 02f79f1fc..9f8df44d7 100644
--- a/src/test/rustdoc-gui/docblock-big-code-mobile.goml
+++ b/src/test/rustdoc-gui/docblock-big-code-mobile.goml
@@ -1,7 +1,7 @@
// If we have a long `<code>`, we need to ensure that it'll be fully displayed on mobile, meaning
// that it'll be on two lines.
emulate: "iPhone 8" // it has the following size: (375, 667)
-goto: file://|DOC_PATH|/test_docs/long_code_block/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/long_code_block/index.html"
// We now check that the block is on two lines:
show-text: true // We need to enable text draw to be able to have the "real" size
// Little explanations for this test: if the text wasn't displayed on two lines, it would take
diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
index baf9651c4..911ee34be 100644
--- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml
@@ -1,8 +1,8 @@
// Checks that the setting "line numbers" is working as expected.
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
// We check that without this setting, there is no line number displayed.
-assert-false: "pre.line-number"
+assert-false: "pre.example-line-numbers"
// We now set the setting to show the line numbers on code examples.
local-storage: {"rustdoc-line-numbers": "true" }
@@ -10,13 +10,30 @@ local-storage: {"rustdoc-line-numbers": "true" }
reload:
// We wait for them to be added into the DOM by the JS...
-wait-for: "pre.line-number"
+wait-for: "pre.example-line-numbers"
// If the test didn't fail, it means that it was found!
// Let's now check some CSS properties...
-assert-css: ("pre.line-number", {
+assert-css: ("pre.example-line-numbers", {
"margin": "0px",
"padding": "13px 8px",
"text-align": "right",
})
// The first code block has two lines so let's check its `<pre>` elements lists both of them.
-assert-text: ("pre.line-number", "1\n2")
+assert-text: ("pre.example-line-numbers", "1\n2")
+
+// Now, try changing the setting dynamically. We'll turn it off, using the settings menu,
+// and make sure it goes away.
+
+// First, open the settings menu.
+click: "#settings-menu"
+wait-for: "#settings"
+assert-css: ("#settings", {"display": "block"})
+
+// Then, click the toggle button.
+click: "input#line-numbers + .slider"
+wait-for: 100 // wait-for-false does not exist
+assert-false: "pre.example-line-numbers"
+
+// Finally, turn it on again.
+click: "input#line-numbers + .slider"
+wait-for: "pre.example-line-numbers"
diff --git a/src/test/rustdoc-gui/docblock-details.goml b/src/test/rustdoc-gui/docblock-details.goml
index f6287ade2..9ae571efb 100644
--- a/src/test/rustdoc-gui/docblock-details.goml
+++ b/src/test/rustdoc-gui/docblock-details.goml
@@ -1,5 +1,5 @@
// This ensures that the `<details>`/`<summary>` elements are displayed as expected.
-goto: file://|DOC_PATH|/test_docs/details/struct.Details.html
+goto: "file://" + |DOC_PATH| + "/test_docs/details/struct.Details.html"
show-text: true
local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
reload:
@@ -14,10 +14,21 @@ assert-css: (
// We now check that the `<summary>` doesn't have a bottom border and has the correct display.
assert-css: (
".top-doc .docblock summary h4",
- {"border-bottom": "0px none rgb(210, 210, 210)"},
+ {"border-bottom-width": "0px"},
)
// This allows to ensure that summary is on one line only!
assert-property: (".top-doc .docblock summary h4", {"offsetHeight": "33"})
assert-css: (".top-doc .docblock summary h4", {"margin-top": "15px", "margin-bottom": "5px"})
// So `33 + 15 + 5` == `53`
assert-property: (".top-doc .docblock summary", {"offsetHeight": "53"})
+
+// We now check the `<summary>` on a method.
+assert-css: (
+ ".method-toggle .docblock summary h4",
+ {"border-bottom-width": "0px"},
+)
+// This allows to ensure that summary is on one line only!
+assert-property: (".method-toggle .docblock summary h4", {"offsetHeight": "30"})
+assert-css: (".method-toggle .docblock summary h4", {"margin-top": "15px", "margin-bottom": "5px"})
+// So `30 + 15 + 5` == `50`
+assert-property: (".method-toggle .docblock summary", {"offsetHeight": "50"})
diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml
index 7f97cf220..d8670089a 100644
--- a/src/test/rustdoc-gui/docblock-table-overflow.goml
+++ b/src/test/rustdoc-gui/docblock-table-overflow.goml
@@ -1,10 +1,10 @@
// This test ensures that the type declaration content overflow is handled inside the <pre> directly.
-goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/lib2/long_table/struct.Foo.html"
// We set a fixed size so there is no chance of "random" resize.
size: (1100, 800)
// Logically, the ".docblock" and the "<p>" should have the same scroll width.
compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"])
-assert-property: (".top-doc .docblock", {"scrollWidth": "801"})
+assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
// However, since there is overflow in the <table>, its scroll width is bigger.
assert-property: (".top-doc .docblock table", {"scrollWidth": "1572"})
@@ -16,6 +16,6 @@ compare-elements-property: (
"#implementations-list > details .docblock > p",
["scrollWidth"],
)
-assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "801"})
+assert-property: ("#implementations-list > details .docblock", {"scrollWidth": "816"})
// However, since there is overflow in the <table>, its scroll width is bigger.
assert-property: ("#implementations-list > details .docblock table", {"scrollWidth": "1572"})
diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml
index 7263156ab..4e316ce0b 100644
--- a/src/test/rustdoc-gui/docblock-table.goml
+++ b/src/test/rustdoc-gui/docblock-table.goml
@@ -1,4 +1,4 @@
-goto: file://|DOC_PATH|/test_docs/doc_block_table/struct.DocBlockTable.html#method.func
+goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.html#method.func"
compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"])
compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock table td", ["border"])
diff --git a/src/test/rustdoc-gui/duplicate-macro-reexport.goml b/src/test/rustdoc-gui/duplicate-macro-reexport.goml
index 9ea599062..496203c12 100644
--- a/src/test/rustdoc-gui/duplicate-macro-reexport.goml
+++ b/src/test/rustdoc-gui/duplicate-macro-reexport.goml
@@ -1,5 +1,5 @@
// This test ensures that there is no macro duplicates in the sidebar.
-goto: file://|DOC_PATH|/test_docs/macro.a.html
+goto: "file://" + |DOC_PATH| + "/test_docs/macro.a.html"
// Waiting for the elements in the sidebar to be rendered.
wait-for: ".sidebar-elems .macro"
// Check there is only one macro named "a" listed in the sidebar.
diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml
index a5afb037d..78e9f2309 100644
--- a/src/test/rustdoc-gui/escape-key.goml
+++ b/src/test/rustdoc-gui/escape-key.goml
@@ -1,6 +1,6 @@
// This test ensures that the "Escape" shortcut is handled correctly based on the
// current content displayed.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// First, we check that the search results are hidden when the Escape key is pressed.
write: (".search-input", "test")
// To be SURE that the search will be run.
diff --git a/src/test/rustdoc-gui/font-weight.goml b/src/test/rustdoc-gui/font-weight.goml
index 5f29fde66..8ba005b0c 100644
--- a/src/test/rustdoc-gui/font-weight.goml
+++ b/src/test/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='docblock item-decl']//a[text()='Alias']", {"font-weight": "400"})
+goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
+assert-css: ("//*[@class='item-decl']//a[text()='Alias']", {"font-weight": "400"})
assert-css: (
"//*[@class='structfield small-section-header']//a[text()='Alias']",
{"font-weight": "400"},
@@ -9,17 +9,17 @@ assert-css: ("#method\.a_method > .code-header", {"font-weight": "600"})
assert-css: ("#associatedtype\.X > .code-header", {"font-weight": "600"})
assert-css: ("#associatedconstant\.Y > .code-header", {"font-weight": "600"})
-goto: file://|DOC_PATH|/test_docs/type.SomeType.html
+goto: "file://" + |DOC_PATH| + "/test_docs/type.SomeType.html"
assert-css: (".top-doc .docblock p", {"font-weight": "400"}, ALL)
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-assert-css: (".impl-items .method", {"font-weight": "600"}, ALL)
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+assert-css: (".impl-items .method > .code-header", {"font-weight": "600"}, ALL)
-goto: file://|DOC_PATH|/lib2/trait.Trait.html
+goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
// This is a complex selector, so here's how it works:
//
-// * //*[@class='docblock item-decl'] — selects element of any tag with classes docblock and item-decl
+// * //*[@class='item-decl'] — selects element of any tag with classes docblock and item-decl
// * /pre[@class='rust trait'] — selects immediate child with tag pre and classes rust and trait
// * /code — selects immediate child with tag code
// * /a[@class='constant'] — selects immediate child with tag a and class constant
@@ -29,11 +29,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='docblock item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*",
+ "//*[@class='item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*",
1,
)
assert-css: (
- "//*[@class='docblock item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*",
+ "//*[@class='item-decl']/pre[@class='rust trait']/code/a[@class='constant']//text()/parent::*",
{"font-weight": "400"},
)
@@ -41,4 +41,4 @@ assert-count: (".methods .associatedtype", 1)
assert-css: (".methods .associatedtype", {"font-weight": "600"})
assert-count: (".methods .constant", 1)
assert-css: (".methods .constant", {"font-weight": "600"})
-assert-css: (".methods .method", {"font-weight": "600"})
+assert-css: (".methods .method > .code-header", {"font-weight": "600"})
diff --git a/src/test/rustdoc-gui/hash-item-expansion.goml b/src/test/rustdoc-gui/hash-item-expansion.goml
index 861f69283..3cf94f624 100644
--- a/src/test/rustdoc-gui/hash-item-expansion.goml
+++ b/src/test/rustdoc-gui/hash-item-expansion.goml
@@ -1,5 +1,5 @@
// This test ensures that the element corresponding to the hash is displayed.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.borrow
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.borrow"
// In the blanket implementations list, "Borrow" is the second one, hence the ":nth(2)".
assert-attribute: ("#blanket-implementations-list > details:nth-child(2)", {"open": ""})
// We first check that the impl block is open by default.
diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml
index a47a9c8a1..c80a49c52 100644
--- a/src/test/rustdoc-gui/headers-color.goml
+++ b/src/test/rustdoc-gui/headers-color.goml
@@ -1,117 +1,70 @@
// This test check for headers text and background colors for the different themes.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-// This is needed so that the text color is computed.
-show-text: true
-
-// Ayu theme
-local-storage: {
- "rustdoc-theme": "ayu",
- "rustdoc-preferred-dark-theme": "ayu",
- "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
- ".impl",
- {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"},
- ALL,
-)
-assert-css: (
- ".impl .code-header",
- {"color": "rgb(230, 225, 207)", "background-color": "rgb(15, 20, 25)"},
- ALL,
+define-function: (
+ "check-colors",
+ (theme, color, code_header_color, focus_background_color, headings_color),
+ [
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"),
+ // This is needed so that the text color is computed.
+ ("show-text", true),
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (
+ ".impl",
+ {"color": |color|, "background-color": "rgba(0, 0, 0, 0)"},
+ ALL,
+ )),
+ ("assert-css", (
+ ".impl .code-header",
+ {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"},
+ ALL,
+ )),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"),
+ ("assert-css", (
+ "#impl-Foo",
+ {"color": |color|, "background-color": |focus_background_color|},
+ )),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"),
+ ("assert-css", (
+ "#method\.must_use",
+ {"color": |color|, "background-color": |focus_background_color|},
+ ALL,
+ )),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+ ("assert-css", (".small-section-header a", {"color": |color|}, ALL)),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"),
+ // We select headings (h2, h3, h...).
+ ("assert-css", (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)),
+ ],
)
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
-assert-css: (
- "#impl-Foo",
- {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"},
+call-function: (
+ "check-colors",
+ {
+ "theme": "ayu",
+ "color": "rgb(197, 197, 197)",
+ "code_header_color": "rgb(230, 225, 207)",
+ "focus_background_color": "rgba(255, 236, 164, 0.06)",
+ "headings_color": "rgb(57, 175, 215)",
+ },
)
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
-assert-css: (
- "#method\.must_use",
- {"color": "rgb(197, 197, 197)", "background-color": "rgba(255, 236, 164, 0.06)"},
- ALL,
+call-function: (
+ "check-colors",
+ {
+ "theme": "dark",
+ "color": "rgb(221, 221, 221)",
+ "code_header_color": "rgb(221, 221, 221)",
+ "focus_background_color": "rgb(73, 74, 61)",
+ "headings_color": "rgb(210, 153, 29)",
+ },
)
-
-goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".small-section-header a", {"color": "rgb(197, 197, 197)"}, ALL)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-// We select headings (h2, h3, h...).
-assert-css: (".docblock > :not(p) > a", {"color": "rgb(57, 175, 215)"}, ALL)
-
-// Dark theme
-local-storage: {
- "rustdoc-theme": "dark",
- "rustdoc-preferred-dark-theme": "dark",
- "rustdoc-use-system-theme": "false",
-}
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-
-assert-css: (
- ".impl",
- {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"},
- ALL,
-)
-assert-css: (
- ".impl .code-header",
- {"color": "rgb(221, 221, 221)", "background-color": "rgb(53, 53, 53)"},
- ALL,
-)
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
-assert-css: (
- "#impl-Foo",
- {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"},
-)
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
-assert-css: (
- "#method\.must_use",
- {"color": "rgb(221, 221, 221)", "background-color": "rgb(73, 74, 61)"},
- ALL,
+call-function: (
+ "check-colors",
+ {
+ "theme": "light",
+ "color": "rgb(0, 0, 0)",
+ "code_header_color": "rgb(0, 0, 0)",
+ "focus_background_color": "rgb(253, 255, 211)",
+ "headings_color": "rgb(56, 115, 173)",
+ },
)
-
-goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".small-section-header a", {"color": "rgb(221, 221, 221)"}, ALL)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-// We select headings (h2, h3, h...).
-assert-css: (".docblock > :not(p) > a", {"color": "rgb(210, 153, 29)"}, ALL)
-
-// Light theme
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-reload:
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-
-assert-css: (
- ".impl",
- {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"},
- ALL,
-)
-assert-css: (
- ".impl .code-header",
- {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"},
- ALL,
-)
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#impl-Foo
-assert-css: ("#impl-Foo", {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"})
-
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html#method.must_use
-assert-css: (
- "#method\.must_use",
- {"color": "rgb(0, 0, 0)", "background-color": "rgb(253, 255, 211)"},
- ALL,
-)
-
-goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".small-section-header a", {"color": "rgb(0, 0, 0)"}, ALL)
-
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-// We select headings (h2, h3, h...).
-assert-css: (".docblock > :not(p) > a", {"color": "rgb(56, 115, 173)"}, ALL)
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index ed07e777b..85e17ca95 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -11,7 +11,7 @@
// 18px 1.125em
// 16px 1rem
// 14px 0.875rem
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
assert-css: ("h1.fqn", {"font-size": "24px"})
@@ -50,7 +50,7 @@ assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"font-size": "14px"})
assert-css: ("h6#sub-heading-for-struct-impl-item-doc", {"border-bottom-width": "0px"})
assert-css: ("h6#sub-sub-heading-for-struct-impl-item-doc", {"font-size": "14px"})
-goto: file://|DOC_PATH|/test_docs/enum.HeavilyDocumentedEnum.html
+goto: "file://" + |DOC_PATH| + "/test_docs/enum.HeavilyDocumentedEnum.html"
assert-css: ("h1.fqn", {"font-size": "24px"})
@@ -106,10 +106,10 @@ assert-css: ("h6#sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "14px"})
assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
-assert-text: (".sidebar .mod h3", "Modules")
-assert-css: (".sidebar .mod h3", {"border-bottom-width": "0px"}, ALL)
+assert-text: ("//ul[@class='block mod']/preceding-sibling::h3", "Modules")
+assert-css: ("//ul[@class='block mod']/preceding-sibling::h3", {"border-bottom-width": "0px"}, ALL)
-goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
+goto: "file://" + |DOC_PATH| + "/test_docs/union.HeavilyDocumentedUnion.html"
assert-css: ("h1.fqn", {"font-size": "24px"})
@@ -141,7 +141,7 @@ assert-css: ("h5#title-for-union-impl-item-doc", {"border-bottom-width": "0px"})
assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"font-size": "14px"})
assert-css: ("h6#sub-heading-for-union-impl-item-doc", {"border-bottom-width": "0px"})
-goto: file://|DOC_PATH|/test_docs/macro.heavily_documented_macro.html
+goto: "file://" + |DOC_PATH| + "/test_docs/macro.heavily_documented_macro.html"
assert-css: ("h1.fqn", {"font-size": "24px"})
@@ -150,109 +150,85 @@ assert-css: ("h2#top-doc-prose-title", {"border-bottom-width": "1px"})
assert-css: ("h3#top-doc-prose-sub-heading", {"font-size": "20px"})
assert-css: ("h3#top-doc-prose-sub-heading", {"border-bottom-width": "1px"})
-// Checking colors now.
+// Needed to check colors
show-text: true
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-goto: file://|DOC_PATH|/test_docs/struct.HeavilyDocumentedStruct.html
-assert-css: (
- ".top-doc .docblock h2",
- {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
- ".top-doc .docblock h3",
- {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
- ".top-doc .docblock h4",
- {"color": "rgb(0, 0, 0)", "border-bottom": "1px solid rgb(221, 221, 221)"},
-)
-assert-css: (
- ".top-doc .docblock h5",
- {"color": "rgb(0, 0, 0)", "border-bottom": "0px none rgb(221, 221, 221)"},
-)
-assert-css: (
- "#implementations-list .docblock h4",
- {"color": "rgb(0, 0, 0)", "border-bottom": "0px none rgb(221, 221, 221)"},
-)
-assert-css: (
- "#implementations-list .docblock h5",
- {"color": "rgb(0, 0, 0)", "border-bottom": "0px none rgb(221, 221, 221)"},
-)
-assert-css: (
- "#implementations-list .docblock h6",
- {"color": "rgb(0, 0, 0)", "border-bottom": "0px none rgb(221, 221, 221)"},
-)
-
-local-storage: {"rustdoc-theme": "dark"}
-reload:
-assert-css: (
- ".top-doc .docblock h2",
- {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
- ".top-doc .docblock h3",
- {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
- ".top-doc .docblock h4",
- {"color": "rgb(221, 221, 221)", "border-bottom": "1px solid rgb(210, 210, 210)"},
-)
-assert-css: (
- ".top-doc .docblock h5",
- {"color": "rgb(221, 221, 221)", "border-bottom": "0px none rgb(210, 210, 210)"},
-)
-assert-css: (
- "#implementations-list .docblock h4",
- {"color": "rgb(221, 221, 221)", "border-bottom": "0px none rgb(210, 210, 210)"},
-)
-assert-css: (
- "#implementations-list .docblock h5",
- {"color": "rgb(221, 221, 221)", "border-bottom": "0px none rgb(210, 210, 210)"},
-)
-assert-css: (
- "#implementations-list .docblock h6",
- {"color": "rgb(221, 221, 221)", "border-bottom": "0px none rgb(210, 210, 210)"},
-)
-
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-assert-css: (
- ".top-doc .docblock h2",
- {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
- ".top-doc .docblock h2",
- {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
- ".top-doc .docblock h4",
- {"color": "rgb(255, 255, 255)", "border-bottom": "1px solid rgb(92, 103, 115)"},
-)
-assert-css: (
- ".top-doc .docblock h5",
- {"color": "rgb(197, 197, 197)", "border-bottom": "0px none rgb(92, 103, 115)"},
-)
-assert-css: (
- "#implementations-list .docblock h4",
- {"color": "rgb(255, 255, 255)", "border-bottom": "0px none rgb(92, 103, 115)"},
-)
-assert-css: (
- "#implementations-list .docblock h5",
- {"color": "rgb(197, 197, 197)", "border-bottom": "0px none rgb(92, 103, 115)"},
-)
-assert-css: (
- "#implementations-list .docblock h6",
- {"color": "rgb(197, 197, 197)", "border-bottom": "0px none rgb(92, 103, 115)"},
-)
-
-local-storage: {"rustdoc-theme": "light"}
-goto: file://|DOC_PATH|/staged_api/struct.Foo.html
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
-
-local-storage: {"rustdoc-theme": "dark"}
-reload:
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
-
-local-storage: {"rustdoc-theme": "ayu"}
-reload:
-assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL)
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"
+
+define-function: (
+ "check-colors",
+ (theme, heading_color, small_heading_color, heading_border_color),
+ [
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (
+ ".top-doc .docblock h2",
+ {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+ )),
+ ("assert-css", (
+ ".top-doc .docblock h3",
+ {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+ )),
+ ("assert-css", (
+ ".top-doc .docblock h4",
+ {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|},
+ )),
+ ("assert-css", (
+ ".top-doc .docblock h5",
+ {"color": |small_heading_color|, "border-bottom-width": "0px"},
+ )),
+ ("assert-css", (
+ "#implementations-list .docblock h4",
+ {"color": |heading_color|, "border-bottom-width": "0px"},
+ )),
+ ("assert-css", (
+ "#implementations-list .docblock h5",
+ {"color": |small_heading_color|, "border-bottom-width": "0px"},
+ )),
+ ("assert-css", (
+ "#implementations-list .docblock h6",
+ {"color": |small_heading_color|, "border-bottom-width": "0px"},
+ )),
+ ],
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "ayu",
+ "heading_color": "rgb(255, 255, 255)",
+ "small_heading_color": "rgb(197, 197, 197)",
+ "heading_border_color": "rgb(92, 103, 115)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "dark",
+ "heading_color": "rgb(221, 221, 221)",
+ "small_heading_color": "rgb(221, 221, 221)",
+ "heading_border_color": "rgb(210, 210, 210)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "light",
+ "heading_color": "rgb(0, 0, 0)",
+ "small_heading_color": "rgb(0, 0, 0)",
+ "heading_border_color": "rgb(221, 221, 221)",
+ },
+)
+
+define-function: (
+ "check-since-color",
+ (theme),
+ [
+ ("local-storage", {"rustdoc-theme": |theme|}),
+ ("reload"),
+ ("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)),
+ ],
+)
+
+goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
+call-function: ("check-since-color", ("ayu"))
+call-function: ("check-since-color", ("dark"))
+call-function: ("check-since-color", ("light"))
diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml
new file mode 100644
index 000000000..521e14748
--- /dev/null
+++ b/src/test/rustdoc-gui/help-page.goml
@@ -0,0 +1,24 @@
+// This test ensures that opening the help page in its own tab works.
+goto: "file://" + |DOC_PATH| + "/help.html"
+size: (1000, 1000) // Try desktop size first.
+wait-for: "#help"
+assert-css: ("#help", {"display": "block"})
+click: "#help-button > a"
+assert-css: ("#help", {"display": "block"})
+compare-elements-property: (".sub", "#help", ["offsetWidth"])
+compare-elements-position: (".sub", "#help", ("x"))
+size: (500, 1000) // Try mobile next.
+assert-css: ("#help", {"display": "block"})
+compare-elements-property: (".sub", "#help", ["offsetWidth"])
+compare-elements-position: (".sub", "#help", ("x"))
+
+// This test ensures that opening the help popover without switching pages works.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+size: (1000, 1000) // Only supported on desktop.
+assert-false: "#help"
+click: "#help-button > a"
+assert-css: ("#help", {"display": "block"})
+click: "#help-button > a"
+assert-css: ("#help", {"display": "none"})
+compare-elements-property-false: (".sub", "#help", ["offsetWidth"])
+compare-elements-position-false: (".sub", "#help", ("x"))
diff --git a/src/test/rustdoc-gui/highlight-colors.goml b/src/test/rustdoc-gui/highlight-colors.goml
new file mode 100644
index 000000000..51693314e
--- /dev/null
+++ b/src/test/rustdoc-gui/highlight-colors.goml
@@ -0,0 +1,94 @@
+// This test checks the highlight colors in the source code pages.
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+show-text: true
+
+define-function: (
+ "check-colors",
+ (
+ theme,
+ kw,
+ kw2,
+ prelude_ty,
+ prelude_val,
+ lifetime,
+ number,
+ string,
+ bool_val,
+ self,
+ attribute,
+ macro,
+ question_mark,
+ comment,
+ doc_comment,
+ ),
+ [
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", ("pre.rust .kw", {"color": |kw|}, ALL)),
+ ("assert-css", ("pre.rust .kw-2", {"color": |kw2|}, ALL)),
+ ("assert-css", ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL)),
+ ("assert-css", ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL)),
+ ("assert-css", ("pre.rust .lifetime", {"color": |lifetime|}, ALL)),
+ ("assert-css", ("pre.rust .number", {"color": |number|}, ALL)),
+ ("assert-css", ("pre.rust .string", {"color": |string|}, ALL)),
+ ("assert-css", ("pre.rust .bool-val", {"color": |bool_val|}, ALL)),
+ ("assert-css", ("pre.rust .self", {"color": |self|}, ALL)),
+ ("assert-css", ("pre.rust .attribute", {"color": |attribute|}, ALL)),
+ ("assert-css", ("pre.rust .macro", {"color": |macro|}, ALL)),
+ ("assert-css", ("pre.rust .question-mark", {"color": |question_mark|}, ALL)),
+ ("assert-css", ("pre.rust .comment", {"color": |comment|}, ALL)),
+ ("assert-css", ("pre.rust .doccomment", {"color": |doc_comment|}, ALL)),
+ ],
+)
+
+call-function: ("check-colors", {
+ "theme": "ayu",
+ "kw": "rgb(255, 119, 51)",
+ "kw2": "rgb(255, 119, 51)",
+ "prelude_ty": "rgb(105, 242, 223)",
+ "prelude_val": "rgb(255, 119, 51)",
+ "lifetime": "rgb(255, 119, 51)",
+ "number": "rgb(184, 204, 82)",
+ "string": "rgb(184, 204, 82)",
+ "bool_val": "rgb(255, 119, 51)",
+ "self": "rgb(54, 163, 217)",
+ "attribute": "rgb(230, 225, 207)",
+ "macro": "rgb(163, 122, 204)",
+ "question_mark": "rgb(255, 144, 17)",
+ "comment": "rgb(120, 135, 151)",
+ "doc_comment": "rgb(161, 172, 136)",
+})
+call-function: ("check-colors", {
+ "theme": "dark",
+ "kw": "rgb(171, 138, 193)",
+ "kw2": "rgb(118, 154, 203)",
+ "prelude_ty": "rgb(118, 154, 203)",
+ "prelude_val": "rgb(238, 104, 104)",
+ "lifetime": "rgb(217, 127, 38)",
+ "number": "rgb(131, 163, 0)",
+ "string": "rgb(131, 163, 0)",
+ "bool_val": "rgb(238, 104, 104)",
+ "self": "rgb(238, 104, 104)",
+ "attribute": "rgb(238, 104, 104)",
+ "macro": "rgb(62, 153, 159)",
+ "question_mark": "rgb(255, 144, 17)",
+ "comment": "rgb(141, 141, 139)",
+ "doc_comment": "rgb(140, 163, 117)",
+})
+call-function: ("check-colors", {
+ "theme": "light",
+ "kw": "rgb(137, 89, 168)",
+ "kw2": "rgb(66, 113, 174)",
+ "prelude_ty": "rgb(66, 113, 174)",
+ "prelude_val": "rgb(200, 40, 41)",
+ "lifetime": "rgb(183, 101, 20)",
+ "number": "rgb(113, 140, 0)",
+ "string": "rgb(113, 140, 0)",
+ "bool_val": "rgb(200, 40, 41)",
+ "self": "rgb(200, 40, 41)",
+ "attribute": "rgb(200, 40, 41)",
+ "macro": "rgb(62, 153, 159)",
+ "question_mark": "rgb(255, 144, 17)",
+ "comment": "rgb(142, 144, 140)",
+ "doc_comment": "rgb(77, 77, 76)",
+})
diff --git a/src/test/rustdoc-gui/huge-collection-of-constants.goml b/src/test/rustdoc-gui/huge-collection-of-constants.goml
index 4f75b5841..3ccd33f1c 100644
--- a/src/test/rustdoc-gui/huge-collection-of-constants.goml
+++ b/src/test/rustdoc-gui/huge-collection-of-constants.goml
@@ -1,6 +1,6 @@
// Make sure that the last two entries are more than 12 pixels apart and not stacked on each other.
-goto: file://|DOC_PATH|/test_docs/huge_amount_of_consts/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/huge_amount_of_consts/index.html"
compare-elements-position-near-false: (
"//*[@class='item-table']//div[last()-1]",
diff --git a/src/test/rustdoc-gui/impl-default-expansion.goml b/src/test/rustdoc-gui/impl-default-expansion.goml
index 6df2661e6..c3f9240cc 100644
--- a/src/test/rustdoc-gui/impl-default-expansion.goml
+++ b/src/test/rustdoc-gui/impl-default-expansion.goml
@@ -1,3 +1,3 @@
// This test ensures that the impl blocks are open by default.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
assert-attribute: ("#implementations-list details.implementors-toggle", {"open": ""})
diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml
index 666a6e125..4999283dc 100644
--- a/src/test/rustdoc-gui/implementors.goml
+++ b/src/test/rustdoc-gui/implementors.goml
@@ -1,6 +1,6 @@
// The goal of this test is to check that the external trait implementors, generated with JS,
// have the same display than the "local" ones.
-goto: file://|DOC_PATH|/implementors/trait.Whatever.html
+goto: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
assert: "#implementors-list"
// There are supposed to be two implementors listed.
assert-count: ("#implementors-list .impl", 2)
@@ -8,28 +8,28 @@ assert-count: ("#implementors-list .impl", 2)
assert: ("#implementors-list .impl:nth-child(1) > a.anchor")
assert-attribute: ("#implementors-list .impl:nth-child(1)", {"id": "impl-Whatever-for-Struct"})
assert-attribute: ("#implementors-list .impl:nth-child(1) > a.anchor", {"href": "#impl-Whatever-for-Struct"})
-assert: "#implementors-list .impl:nth-child(1) > .code-header.in-band"
+assert: "#implementors-list .impl:nth-child(1) > .code-header"
assert: ("#implementors-list .impl:nth-child(2) > a.anchor")
assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"})
assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"})
-assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band"
+assert: "#implementors-list .impl:nth-child(2) > .code-header"
-goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.HasEmptyTraits.html"
compare-elements-position-near-false: (
"#impl-EmptyTrait1-for-HasEmptyTraits",
"#impl-EmptyTrait2-for-HasEmptyTraits",
- {"y": 30},
+ {"y": 34},
)
compare-elements-position-near: (
"#impl-EmptyTrait3-for-HasEmptyTraits h3",
"#impl-EmptyTrait3-for-HasEmptyTraits .item-info",
- {"y": 30},
+ {"y": 34},
)
// Now check that re-exports work correctly.
// There should be exactly one impl shown on both of these pages.
-goto: file://|DOC_PATH|/lib2/trait.TraitToReexport.html
+goto: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html"
assert-count: ("#implementors-list .impl", 1)
-goto: file://|DOC_PATH|/implementors/trait.TraitToReexport.html
+goto: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html"
assert-count: ("#implementors-list .impl", 1)
diff --git a/src/test/rustdoc-gui/item-decl-colors.goml b/src/test/rustdoc-gui/item-decl-colors.goml
new file mode 100644
index 000000000..ce688287a
--- /dev/null
+++ b/src/test/rustdoc-gui/item-decl-colors.goml
@@ -0,0 +1,74 @@
+// This test ensures that the color of the items in the type decl are working as expected.
+define-function: (
+ "check-colors",
+ (
+ theme,
+ attr_color,
+ trait_color,
+ struct_color,
+ enum_color,
+ primitive_color,
+ constant_color,
+ fn_color,
+ assoc_type_color,
+ ),
+ [
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"),
+ ("show-text", true),
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (".item-decl .code-attribute", {"color": |attr_color|}, ALL)),
+ ("assert-css", (".item-decl .trait", {"color": |trait_color|}, ALL)),
+ // We need to add `code` here because otherwise it would select the parent too.
+ ("assert-css", (".item-decl code .struct", {"color": |struct_color|}, ALL)),
+ ("assert-css", (".item-decl .enum", {"color": |enum_color|}, ALL)),
+ ("assert-css", (".item-decl .primitive", {"color": |primitive_color|}, ALL)),
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"),
+ ("assert-css", (".item-decl .constant", {"color": |constant_color|}, ALL)),
+ ("assert-css", (".item-decl .fnname", {"color": |fn_color|}, ALL)),
+ ("assert-css", (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)),
+ ],
+)
+
+call-function: (
+ "check-colors",
+ {
+ "theme": "ayu",
+ "attr_color": "rgb(153, 153, 153)",
+ "trait_color": "rgb(57, 175, 215)",
+ "struct_color": "rgb(255, 160, 165)",
+ "enum_color": "rgb(255, 160, 165)",
+ "primitive_color": "rgb(255, 160, 165)",
+ "constant_color": "rgb(57, 175, 215)",
+ "fn_color": "rgb(253, 214, 135)",
+ "assoc_type_color": "rgb(57, 175, 215)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "dark",
+ "attr_color": "rgb(153, 153, 153)",
+ "trait_color": "rgb(183, 140, 242)",
+ "struct_color": "rgb(45, 191, 184)",
+ "enum_color": "rgb(45, 191, 184)",
+ "primitive_color": "rgb(45, 191, 184)",
+ "constant_color": "rgb(210, 153, 29)",
+ "fn_color": "rgb(43, 171, 99)",
+ "assoc_type_color": "rgb(210, 153, 29)",
+ },
+)
+call-function: (
+ "check-colors",
+ {
+ "theme": "light",
+ "attr_color": "rgb(153, 153, 153)",
+ "trait_color": "rgb(110, 79, 201)",
+ "struct_color": "rgb(173, 55, 138)",
+ "enum_color": "rgb(173, 55, 138)",
+ "primitive_color": "rgb(173, 55, 138)",
+ "constant_color": "rgb(56, 115, 173)",
+ "fn_color": "rgb(173, 124, 55)",
+ "assoc_type_color": "rgb(56, 115, 173)",
+ },
+)
diff --git a/src/test/rustdoc-gui/item-info-alignment.goml b/src/test/rustdoc-gui/item-info-alignment.goml
index 4d7b5045f..94b52f005 100644
--- a/src/test/rustdoc-gui/item-info-alignment.goml
+++ b/src/test/rustdoc-gui/item-info-alignment.goml
@@ -1,6 +1,6 @@
// This test ensures that the "item-info" looks about the same
// whether or not it's inside a toggle.
-goto: file://|DOC_PATH|/lib2/struct.ItemInfoAlignmentTest.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.ItemInfoAlignmentTest.html"
// First, we try it in "desktop" mode.
size: (1200, 870)
diff --git a/src/test/rustdoc-gui/item-info-overflow.goml b/src/test/rustdoc-gui/item-info-overflow.goml
index b7095a3c5..8ea14621c 100644
--- a/src/test/rustdoc-gui/item-info-overflow.goml
+++ b/src/test/rustdoc-gui/item-info-overflow.goml
@@ -1,10 +1,10 @@
// This test ensures that the "item-info" elements don't overflow.
-goto: file://|DOC_PATH|/lib2/struct.LongItemInfo.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo.html"
// We set a fixed size so there is no chance of "random" resize.
size: (1200, 870)
// Logically, the "item-decl" and the "item-info" should have the same scroll width.
-compare-elements-property: (".docblock.item-decl", ".item-info", ["scrollWidth"])
-assert-property: (".item-info", {"scrollWidth": "890"})
+compare-elements-property: (".item-decl", ".item-info", ["scrollWidth"])
+assert-property: (".item-info", {"scrollWidth": "940"})
// Just to be sure we're comparing the correct "item-info":
assert-text: (
".item-info",
@@ -13,7 +13,7 @@ assert-text: (
)
// Checking the "item-info" on an impl block as well:
-goto: file://|DOC_PATH|/lib2/struct.LongItemInfo2.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.LongItemInfo2.html"
compare-elements-property: (
"#impl-SimpleTrait-for-LongItemInfo2 .item-info",
"#impl-SimpleTrait-for-LongItemInfo2 + .docblock",
@@ -21,7 +21,7 @@ compare-elements-property: (
)
assert-property: (
"#impl-SimpleTrait-for-LongItemInfo2 .item-info",
- {"scrollWidth": "866"},
+ {"scrollWidth": "916"},
)
// Just to be sure we're comparing the correct "item-info":
assert-text: (
diff --git a/src/test/rustdoc-gui/item-info.goml b/src/test/rustdoc-gui/item-info.goml
index 50c45b76b..6780dfca6 100644
--- a/src/test/rustdoc-gui/item-info.goml
+++ b/src/test/rustdoc-gui/item-info.goml
@@ -1,15 +1,15 @@
// This test ensures a few things for item info elements.
-goto: file://|DOC_PATH|/lib2/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
// Ensuring that the item information don't take 100% of the width if unnecessary.
// We set a fixed size so there is no chance of "random" resize.
size: (1100, 800)
// We check that ".item-info" is bigger than its content.
-assert-css: (".item-info", {"width": "790px"})
+assert-css: (".item-info", {"width": "840px"})
assert-css: (".item-info .stab", {"width": "289px"})
-assert-position: (".item-info .stab", {"x": 295})
+assert-position: (".item-info .stab", {"x": 245})
// Now we ensure that they're not rendered on the same line.
-goto: file://|DOC_PATH|/lib2/trait.Trait.html
+goto: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
// We first ensure that there are two item info on the trait.
assert-count: ("#main-content > .item-info .stab", 2)
// They should not have the same `y` position!
diff --git a/src/test/rustdoc-gui/item-summary-table.goml b/src/test/rustdoc-gui/item-summary-table.goml
index 4bff32b3d..2a92e9da5 100644
--- a/src/test/rustdoc-gui/item-summary-table.goml
+++ b/src/test/rustdoc-gui/item-summary-table.goml
@@ -1,5 +1,5 @@
// This test ensures that <table> elements aren't display in items summary.
-goto: file://|DOC_PATH|/lib2/summary_table/index.html
+goto: "file://" + |DOC_PATH| + "/lib2/summary_table/index.html"
// We check that we picked the right item first.
assert-text: (".item-table .item-left", "Foo")
// Then we check that its summary is empty.
diff --git a/src/test/rustdoc-gui/javascript-disabled.goml b/src/test/rustdoc-gui/javascript-disabled.goml
index 1693f7b64..edf179d0d 100644
--- a/src/test/rustdoc-gui/javascript-disabled.goml
+++ b/src/test/rustdoc-gui/javascript-disabled.goml
@@ -2,5 +2,5 @@
// can't be used without JS.
javascript: false
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
assert-css: (".sub", {"display": "none"})
diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml
index d17400f5b..b65faf13d 100644
--- a/src/test/rustdoc-gui/jump-to-def-background.goml
+++ b/src/test/rustdoc-gui/jump-to-def-background.goml
@@ -1,43 +1,22 @@
// We check the background color on the jump to definition links in the source code page.
-goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
-// Set the theme to dark.
-local-storage: {
- "rustdoc-theme": "dark",
- "rustdoc-preferred-dark-theme": "dark",
- "rustdoc-use-system-theme": "false",
-}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
- "body.source .example-wrap pre.rust a",
- {"background-color": "rgb(51, 51, 51)"},
- ALL,
-)
-
-// Set the theme to ayu.
-local-storage: {
- "rustdoc-theme": "ayu",
- "rustdoc-preferred-dark-theme": "ayu",
- "rustdoc-use-system-theme": "false",
-}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
- "body.source .example-wrap pre.rust a",
- {"background-color": "rgb(51, 51, 51)"},
- ALL,
+define-function: (
+ "check-background-color",
+ (theme, background_color),
+ [
+ // Set 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"),
+ ("assert-css", (
+ "body.source .example-wrap pre.rust a",
+ {"background-color": |background_color|},
+ ALL,
+ )),
+ ],
)
-// Set the theme to light.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-// We reload the page so the local storage settings are being used.
-reload:
-
-assert-css: (
- "body.source .example-wrap pre.rust a",
- {"background-color": "rgb(238, 238, 238)"},
- ALL,
-)
+call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)"))
+call-function: ("check-background-color", ("dark", "rgb(51, 51, 51)"))
+call-function: ("check-background-color", ("light", "rgb(238, 238, 238)"))
diff --git a/src/test/rustdoc-gui/label-next-to-symbol.goml b/src/test/rustdoc-gui/label-next-to-symbol.goml
index 4b4cea262..05f8ddc71 100644
--- a/src/test/rustdoc-gui/label-next-to-symbol.goml
+++ b/src/test/rustdoc-gui/label-next-to-symbol.goml
@@ -1,6 +1,6 @@
// These tests verify that labels like "UNIX" and "Deprecated" stay on the same line as their symbol.
// It also verifies the staggered layout on mobile.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// Desktop view
size: (1080, 600)
diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml
index 69c5b4a67..839629ad9 100644
--- a/src/test/rustdoc-gui/links-color.goml
+++ b/src/test/rustdoc-gui/links-color.goml
@@ -1,5 +1,5 @@
// This test checks links colors.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// This is needed so that the text color is computed.
show-text: true
diff --git a/src/test/rustdoc-gui/list_code_block.goml b/src/test/rustdoc-gui/list_code_block.goml
index eba1a662b..3423a449d 100644
--- a/src/test/rustdoc-gui/list_code_block.goml
+++ b/src/test/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
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+goto: "./fn.check_list_code_block.html"
assert: ("pre.rust.fn")
diff --git a/src/test/rustdoc-gui/mobile.goml b/src/test/rustdoc-gui/mobile.goml
index 13b9b563d..704542a39 100644
--- a/src/test/rustdoc-gui/mobile.goml
+++ b/src/test/rustdoc-gui/mobile.goml
@@ -1,5 +1,5 @@
// Test various properties of the mobile UI
-goto: file://|DOC_PATH|/staged_api/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"
size: (400, 600)
font-size: 18
@@ -12,7 +12,7 @@ assert-css: (".main-heading", {
"flex-direction": "column"
})
-assert-property: (".mobile-topbar h2.location", {"offsetHeight": 36})
+assert-property: (".mobile-topbar h2", {"offsetHeight": 36})
// Note: We can't use assert-text here because the 'Since' is set by CSS and
// is therefore not part of the DOM.
@@ -24,7 +24,7 @@ assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since
// On the settings page, the theme buttons should not line-wrap. Instead, they should
// all be placed as a group on a line below the setting name "Theme."
-goto: file://|DOC_PATH|/settings.html
+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", {"y": 16})
diff --git a/src/test/rustdoc-gui/module-items-font.goml b/src/test/rustdoc-gui/module-items-font.goml
index 758ee391a..cd3676a98 100644
--- a/src/test/rustdoc-gui/module-items-font.goml
+++ b/src/test/rustdoc-gui/module-items-font.goml
@@ -1,5 +1,5 @@
// This test checks that the correct font is used on module items (in index.html pages).
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
assert-css: (
".item-table .module-item a",
{"font-family": '"Fira Sans", Arial, NanumBarunGothic, sans-serif'},
diff --git a/src/test/rustdoc-gui/no-docblock.goml b/src/test/rustdoc-gui/no-docblock.goml
new file mode 100644
index 000000000..2366a60f5
--- /dev/null
+++ b/src/test/rustdoc-gui/no-docblock.goml
@@ -0,0 +1,8 @@
+// This test checks that there are margins applied to methods with no docblocks.
+goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithNoDocblocks.html"
+// Check that the two methods are more than 24px apart.
+compare-elements-position-near-false: ("//*[@id='tymethod.first_fn']", "//*[@id='tymethod.second_fn']", {"y": 24})
+
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithNoDocblocks.html"
+// Check that the two methods are more than 24px apart.
+compare-elements-position-near-false: ("//*[@id='method.first_fn']", "//*[@id='method.second_fn']", {"y": 24})
diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml
new file mode 100644
index 000000000..efe0cb15f
--- /dev/null
+++ b/src/test/rustdoc-gui/notable-trait.goml
@@ -0,0 +1,128 @@
+// This test checks the position of the `i` for the notable traits.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
+show-text: true
+// We start with a wide screen.
+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']",
+ ("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']",
+ ("x"),
+)
+// The `i` should be *after* the type.
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ {"x": 677},
+)
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ {"x": 951},
+)
+// The tooltip should be beside the `i`
+click: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"
+compare-elements-position-near: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+ {"y": 2}
+)
+compare-elements-position-false: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+ ("x")
+)
+// The docblock should be flush with the border.
+assert-css: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']",
+ {"margin-left": "0px"}
+)
+
+// 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']",
+ ("y", "x"),
+)
+
+// Now both the `i` and the struct name should be on the next line.
+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']",
+ ("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']",
+ ("x"),
+)
+// The `i` should be *after* the type.
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ {"x": 245},
+)
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ {"x": 519},
+)
+
+// Checking on mobile now.
+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']",
+ ("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']",
+ ("x"),
+)
+// The `i` should be *after* the type.
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//a[text()='NotableStructWithLongName']",
+ {"x": 15},
+)
+assert-position: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ {"x": 289},
+)
+// The tooltip should be below `i`
+compare-elements-position-near-false: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+ {"y": 2}
+)
+compare-elements-position-false: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+ ("x")
+)
+compare-elements-position-near: (
+ "//*[@id='method.create_an_iterator_from_read']/parent::*",
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']",
+ {"x": 5}
+)
+// The docblock should be flush with the border.
+assert-css: (
+ "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits-tooltiptext force-tooltip']/*[@class='docblock']",
+ {"margin-left": "0px"}
+)
+
+// Checking on very small mobile. The `i` should be on its own line.
+size: (365, 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']",
+ ("y", "x"),
+)
diff --git a/src/test/rustdoc-gui/overflow-tooltip-information.goml b/src/test/rustdoc-gui/overflow-tooltip-information.goml
index f481f82c2..09ad6cdd7 100644
--- a/src/test/rustdoc-gui/overflow-tooltip-information.goml
+++ b/src/test/rustdoc-gui/overflow-tooltip-information.goml
@@ -1,7 +1,7 @@
// The goal of this test is to ensure that the tooltip `.information` class doesn't
// have overflow and max-width CSS rules set because they create a bug in firefox on
// mac. For more information: https://github.com/rust-lang/rust/issues/89185
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
assert-css: (".docblock > .example-wrap .tooltip", {
"overflow-x": "visible",
"max-width": "none"
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
index 71d514648..fb63ea62a 100644
--- a/src/test/rustdoc-gui/pocket-menu.goml
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -1,5 +1,5 @@
// This test ensures that the "pocket menus" are working as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// First we check that the help menu doesn't exist yet.
assert-false: "#help-button .popover"
// Then we display the help menu.
diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml
index b8efa8e30..6c785e1c4 100644
--- a/src/test/rustdoc-gui/run-on-hover.goml
+++ b/src/test/rustdoc-gui/run-on-hover.goml
@@ -1,7 +1,7 @@
// Example code blocks sometimes have a "Run" button to run them on the
// Playground. That button is hidden until the user hovers over the code block.
// This test checks that it is hidden, and that it shows on hover.
-goto: file://|DOC_PATH|/test_docs/fn.foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/fn.foo.html"
assert-css: (".test-arrow", {"visibility": "hidden"})
move-cursor-to: ".example-wrap"
assert-css: (".test-arrow", {"visibility": "visible"})
diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml
index 4a9dcf735..6c8dc8594 100644
--- a/src/test/rustdoc-gui/rust-logo.goml
+++ b/src/test/rustdoc-gui/rust-logo.goml
@@ -1,78 +1,34 @@
// This test ensures that the correct style is applied to the rust logo in the sidebar.
-goto: file://|DOC_PATH|/test_docs/index.html
-
-// First we start with the dark theme.
-local-storage: {
- "rustdoc-theme": "dark",
- "rustdoc-preferred-dark-theme": "dark",
- "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"},
-)
-
-// In the source view page now.
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
-
-local-storage: {
- "rustdoc-theme": "dark",
- "rustdoc-preferred-dark-theme": "dark",
- "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"},
-)
-
-// Then with the ayu theme.
-local-storage: {
- "rustdoc-theme": "ayu",
- "rustdoc-preferred-dark-theme": "ayu",
- "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"},
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+
+define-function: (
+ "check-logo",
+ (theme, filter),
+ [
+ // Going to the doc page.
+ ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+ // Changing theme.
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (".rust-logo", {"filter": |filter|})),
+ // Going to the source code page.
+ ("goto", "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"),
+ // Changing theme (since it's local files, the local storage works by folder).
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (".rust-logo", {"filter": |filter|})),
+ ],
)
-// In the source view page now.
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
-
-local-storage: {
- "rustdoc-theme": "ayu",
- "rustdoc-preferred-dark-theme": "ayu",
- "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"},
+call-function: (
+ "check-logo",
+ ("ayu", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"),
)
-
-// And finally with the light theme.
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "none"},
+call-function: (
+ "check-logo",
+ ("dark", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"),
)
-
-// In the source view page now.
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
-
-local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
-reload:
-
-assert-css: (
- ".rust-logo",
- {"filter": "none"},
+call-function: (
+ "check-logo",
+ ("light", "none"),
)
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index 35d7ca480..27db816e6 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -1,5 +1,5 @@
// Checks that the crate search filtering is handled correctly and changes the results.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
show-text: true
write: (".search-input", "test")
// To be SURE that the search will be run.
@@ -43,7 +43,7 @@ wait-for: "#titles"
assert-property: ("#crate-search", {"value": "all crates"})
// Checking that the URL parameter is taken into account for crate filtering.
-goto: file://|DOC_PATH|/test_docs/index.html?search=test&filter-crate=lib2
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=test&filter-crate=lib2"
wait-for: "#crate-search"
assert-property: ("#crate-search", {"value": "lib2"})
assert-false: "#results .externcrate"
diff --git a/src/test/rustdoc-gui/search-form-elements.goml b/src/test/rustdoc-gui/search-form-elements.goml
index 1c64974e9..542db348c 100644
--- a/src/test/rustdoc-gui/search-form-elements.goml
+++ b/src/test/rustdoc-gui/search-form-elements.goml
@@ -1,5 +1,5 @@
// This test ensures that the elements in ".search-form" have the expected display.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
show-text: true
// Ayu theme
@@ -33,7 +33,7 @@ assert-css: (
{"border-color": "rgb(197, 197, 197)"},
)
assert-css: (
- "#help-button > button",
+ "#help-button > a",
{
"color": "rgb(255, 255, 255)",
"border-color": "rgb(92, 103, 115)",
@@ -47,13 +47,21 @@ assert-css: (
)
// Only "border-color" should change.
assert-css: (
- "#help-button:hover > button",
+ "#help-button:hover > a",
{
"color": "rgb(255, 255, 255)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(20, 25, 32)",
},
)
+// Link color inside
+click: "#help-button"
+assert-css: (
+ "#help a",
+ {
+ "color": "rgb(57, 175, 215)",
+ },
+)
assert-css: (
"#settings-menu",
@@ -62,7 +70,6 @@ assert-css: (
assert-css: (
"#settings-menu > a",
{
- "color": "rgb(255, 255, 255)",
"border-color": "rgb(92, 103, 115)",
"background-color": "rgb(20, 25, 32)",
},
@@ -76,7 +83,6 @@ assert-css: (
assert-css: (
"#settings-menu:hover > a",
{
- "color": "rgb(255, 255, 255)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(20, 25, 32)",
},
@@ -113,7 +119,7 @@ assert-css: (
{"border-color": "rgb(221, 221, 221)"},
)
assert-css: (
- "#help-button > button",
+ "#help-button > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(224, 224, 224)",
@@ -127,13 +133,21 @@ assert-css: (
)
// Only "border-color" should change.
assert-css: (
- "#help-button:hover > button",
+ "#help-button:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(255, 185, 0)",
"background-color": "rgb(240, 240, 240)",
},
)
+// Link color inside
+click: "#help-button"
+assert-css: (
+ "#help a",
+ {
+ "color": "rgb(210, 153, 29)",
+ },
+)
assert-css: (
"#settings-menu",
@@ -142,7 +156,6 @@ assert-css: (
assert-css: (
"#settings-menu > a",
{
- "color": "rgb(0, 0, 0)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(240, 240, 240)",
},
@@ -193,7 +206,7 @@ assert-css: (
{"border-color": "rgb(0, 0, 0)"},
)
assert-css: (
- "#help-button > button",
+ "#help-button > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(224, 224, 224)",
@@ -207,13 +220,21 @@ assert-css: (
)
// Only "border-color" should change.
assert-css: (
- "#help-button:hover > button",
+ "#help-button:hover > a",
{
"color": "rgb(0, 0, 0)",
"border-color": "rgb(113, 113, 113)",
"background-color": "rgb(255, 255, 255)",
},
)
+// Link color inside
+click: "#help-button"
+assert-css: (
+ "#help a",
+ {
+ "color": "rgb(56, 115, 173)",
+ },
+)
assert-css: (
"#settings-menu",
@@ -222,7 +243,6 @@ assert-css: (
assert-css: (
"#settings-menu > a",
{
- "color": "rgb(56, 115, 173)",
"border-color": "rgb(224, 224, 224)",
"background-color": "rgb(255, 255, 255)",
},
@@ -236,7 +256,7 @@ assert-css: (
assert-css: (
"#settings-menu:hover > a",
{
- "color": "rgb(56, 115, 173)",
+ "color": "rgb(0, 0, 0)",
"border-color": "rgb(113, 113, 113)",
"background-color": "rgb(255, 255, 255)",
},
diff --git a/src/test/rustdoc-gui/search-input-mobile.goml b/src/test/rustdoc-gui/search-input-mobile.goml
index 5c95db70a..ce0cef77c 100644
--- a/src/test/rustdoc-gui/search-input-mobile.goml
+++ b/src/test/rustdoc-gui/search-input-mobile.goml
@@ -1,6 +1,6 @@
// Test to ensure that you can click on the search input, whatever the width.
// The PR which fixed it is: https://github.com/rust-lang/rust/pull/81592
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
size: (463, 700)
// We first check that the search input isn't already focused.
assert-false: ("input.search-input:focus")
diff --git a/src/test/rustdoc-gui/search-reexport.goml b/src/test/rustdoc-gui/search-reexport.goml
index 5ef890d47..dd19f03bd 100644
--- a/src/test/rustdoc-gui/search-reexport.goml
+++ b/src/test/rustdoc-gui/search-reexport.goml
@@ -1,6 +1,6 @@
// Checks that the reexports are present in the search index, can have
// doc aliases and are highligted when their ID is the hash of the page.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
reload:
// First we check that the reexport has the correct ID and no background color.
diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml
index c4b5fdf53..69bb30df9 100644
--- a/src/test/rustdoc-gui/search-result-color.goml
+++ b/src/test/rustdoc-gui/search-result-color.goml
@@ -1,5 +1,58 @@
// The goal of this test is to ensure the color of the text is the one expected.
-goto: file://|DOC_PATH|/test_docs/index.html?search=coo
+
+define-function: (
+ "check-result-color",
+ (result_kind, color, hover_color),
+ [
+ (
+ "assert-css",
+ (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL),
+ ),
+ (
+ "assert-css",
+ (
+ ".result-" + |result_kind|,
+ {"color": |entry_color|, "background-color": |background_color|},
+ ),
+ ),
+ (
+ "move-cursor-to",
+ ".result-" + |result_kind|,
+ ),
+ (
+ "assert-css",
+ (
+ ".result-" + |result_kind| + ":hover",
+ {"color": |hover_entry_color|, "background-color": |hover_background_color|},
+ ),
+ ),
+ (
+ "assert-css",
+ (".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}),
+ ),
+ (
+ "move-cursor-to",
+ ".search-input",
+ ),
+ (
+ "focus",
+ ".result-" + |result_kind|,
+ ),
+ (
+ "assert-css",
+ (
+ ".result-" + |result_kind| + ":focus",
+ {"color": |hover_entry_color|, "background-color": |hover_background_color|},
+ ),
+ ),
+ (
+ "assert-css",
+ (".result-" + |result_kind| + ":focus ." + |result_kind|, {"color": |hover_color|}),
+ ),
+ ],
+)
+
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo"
// This is needed so that the text color is computed.
show-text: true
@@ -28,56 +81,71 @@ assert-css: (
{"color": "rgb(120, 135, 151)"},
)
-// Checking the color of "keyword".
-assert-css: (
- ".result-name .keyword",
- {"color": "rgb(57, 175, 215)"},
- ALL,
-)
-// Check the color of "struct".
-assert-css: (
- ".result-name .struct",
- {"color": "rgb(255, 160, 165)"},
- ALL,
-)
-// Check the color of "associated type".
-assert-css: (
- ".result-name .associatedtype",
- {"color": "rgb(57, 175, 215)"},
- ALL,
-)
-// Check the color of "type method".
-assert-css: (
- ".result-name .tymethod",
- {"color": "rgb(253, 214, 135)"},
- ALL,
-)
-// Check the color of "method".
-assert-css: (
- ".result-name .method",
- {"color": "rgb(253, 214, 135)"},
- ALL,
-)
-// Check the color of "struct field".
-assert-css: (
- ".result-name .structfield",
- {"color": "rgb(0, 150, 207)"},
- ALL,
-)
-// Check the color of "macro".
-assert-css: (
- ".result-name .macro",
- {"color": "rgb(163, 122, 204)"},
- ALL,
-)
-// Check the color of "fn".
-assert-css: (
- ".result-name .fn",
- {"color": "rgb(253, 214, 135)"},
- ALL,
+store-value: (entry_color, "rgb(0, 150, 207)") // color of the search entry
+store-value: (hover_entry_color, "rgb(255, 255, 255)") // color of the hovered/focused search entry
+store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
+store-value: (hover_background_color, "rgb(60, 60, 60)") // hover background color
+
+call-function: (
+ "check-result-color", (
+ "keyword", // item kind
+ "rgb(57, 175, 215)", // color of item kind
+ "rgb(57, 175, 215)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "struct", // item kind
+ "rgb(255, 160, 165)", // color of item kind
+ "rgb(255, 160, 165)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "associatedtype", // item kind
+ "rgb(57, 175, 215)", // color of item kind
+ "rgb(57, 175, 215)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "tymethod", // item kind
+ "rgb(253, 214, 135)", // color of item kind
+ "rgb(253, 214, 135)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "method", // item kind
+ "rgb(253, 214, 135)", // color of item kind
+ "rgb(253, 214, 135)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "structfield", // item kind
+ "rgb(0, 150, 207)", // color of item kind
+ "rgb(255, 255, 255)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "macro", // item kind
+ "rgb(163, 122, 204)", // color of item kind
+ "rgb(163, 122, 204)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "fn", // item kind
+ "rgb(253, 214, 135)", // color of item kind
+ "rgb(253, 214, 135)", // color of hovered/focused item kind
+ ),
)
// Checking the `<a>` container.
+move-cursor-to: ".search-input"
+focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
{"color": "rgb(0, 150, 207)", "background-color": "rgba(0, 0, 0, 0)"},
@@ -113,78 +181,82 @@ assert-css: (
{"color": "rgb(221, 221, 221)"},
)
-// Checking the color for "keyword".
+// Checking the color for "keyword" text.
assert-css: (
"//*[@class='result-name']//*[text()='(keyword)']",
{"color": "rgb(221, 221, 221)"},
)
-// Checking the color of "keyword".
-assert-css: (
- ".result-name .keyword",
- {"color": "rgb(210, 153, 29)"},
- ALL,
-)
-// Check the color of "struct".
-assert-css: (
- ".result-name .struct",
- {"color": "rgb(45, 191, 184)"},
- ALL,
-)
-// Check the color of "associated type".
-assert-css: (
- ".result-name .associatedtype",
- {"color": "rgb(210, 153, 29)"},
- ALL,
-)
-// Check the color of "type method".
-assert-css: (
- ".result-name .tymethod",
- {"color": "rgb(43, 171, 99)"},
- ALL,
-)
-// Check the color of "method".
-assert-css: (
- ".result-name .method",
- {"color": "rgb(43, 171, 99)"},
- ALL,
-)
-// Check the color of "struct field".
-assert-css: (
- ".result-name .structfield",
- {"color": "rgb(221, 221, 221)"},
- ALL,
-)
-// Check the color of "macro".
-assert-css: (
- ".result-name .macro",
- {"color": "rgb(9, 189, 0)"},
- ALL,
-)
-// Check the color of "fn".
-assert-css: (
- ".result-name .fn",
- {"color": "rgb(43, 171, 99)"},
- ALL,
+store-value: (entry_color, "rgb(221, 221, 221)") // color of the search entry
+store-value: (hover_entry_color, "rgb(221, 221, 221)") // color of the hovered/focused search entry
+store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
+store-value: (hover_background_color, "rgb(97, 97, 97)") // hover background color
+
+call-function: (
+ "check-result-color", (
+ "keyword", // item kind
+ "rgb(210, 153, 29)", // color of item kind
+ "rgb(210, 153, 29)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "struct", // item kind
+ "rgb(45, 191, 184)", // color of item kind
+ "rgb(45, 191, 184)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "associatedtype", // item kind
+ "rgb(210, 153, 29)", // color of item kind
+ "rgb(210, 153, 29)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "tymethod", // item kind
+ "rgb(43, 171, 99)", // color of item kind
+ "rgb(43, 171, 99)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "method", // item kind
+ "rgb(43, 171, 99)", // color of item kind
+ "rgb(43, 171, 99)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "structfield", // item kind
+ "rgb(221, 221, 221)", // color of item kind
+ "rgb(221, 221, 221)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "macro", // item kind
+ "rgb(9, 189, 0)", // color of item kind
+ "rgb(9, 189, 0)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "fn", // item kind
+ "rgb(43, 171, 99)", // color of item kind
+ "rgb(43, 171, 99)", // color of hovered/focused item kind
+ ),
)
// Checking the `<a>` container.
+move-cursor-to: ".search-input"
+focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
{"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"},
)
-// Checking color and background on hover.
-move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']"
-assert-css: (
- "//*[@class='result-name']/*[text()='test_docs::']",
- {"color": "rgb(221, 221, 221)"},
-)
-assert-css: (
- "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
- {"color": "rgb(221, 221, 221)", "background-color": "rgb(119, 119, 119)"},
-)
-
// Light theme
local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
reload:
@@ -200,80 +272,84 @@ assert-css: (
{"color": "rgb(0, 0, 0)"},
)
-// Checking the color for "keyword".
+// Checking the color for "keyword" text.
assert-css: (
"//*[@class='result-name']//*[text()='(keyword)']",
{"color": "rgb(0, 0, 0)"},
)
-// Checking the color of "keyword".
-assert-css: (
- ".result-name .keyword",
- {"color": "rgb(56, 115, 173)"},
- ALL,
-)
-// Check the color of "struct".
-assert-css: (
- ".result-name .struct",
- {"color": "rgb(173, 55, 138)"},
- ALL,
-)
-// Check the color of "associated type".
-assert-css: (
- ".result-name .associatedtype",
- {"color": "rgb(56, 115, 173)"},
- ALL,
-)
-// Check the color of "type method".
-assert-css: (
- ".result-name .tymethod",
- {"color": "rgb(173, 124, 55)"},
- ALL,
-)
-// Check the color of "method".
-assert-css: (
- ".result-name .method",
- {"color": "rgb(173, 124, 55)"},
- ALL,
-)
-// Check the color of "struct field".
-assert-css: (
- ".result-name .structfield",
- {"color": "rgb(0, 0, 0)"},
- ALL,
-)
-// Check the color of "macro".
-assert-css: (
- ".result-name .macro",
- {"color": "rgb(6, 128, 0)"},
- ALL,
-)
-// Check the color of "fn".
-assert-css: (
- ".result-name .fn",
- {"color": "rgb(173, 124, 55)"},
- ALL,
+store-value: (entry_color, "rgb(0, 0, 0)") // color of the search entry
+store-value: (hover_entry_color, "rgb(0, 0, 0)") // color of the hovered/focused search entry
+store-value: (background_color, "rgba(0, 0, 0, 0)") // background color
+store-value: (hover_background_color, "rgb(204, 204, 204)") // hover background color
+
+call-function: (
+ "check-result-color", (
+ "keyword", // item kind
+ "rgb(56, 115, 173)", // color of item kind
+ "rgb(56, 115, 173)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "struct", // item kind
+ "rgb(173, 55, 138)", // color of item kind
+ "rgb(173, 55, 138)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "associatedtype", // item kind
+ "rgb(56, 115, 173)", // color of item kind
+ "rgb(56, 115, 173)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "tymethod", // item kind
+ "rgb(173, 124, 55)", // color of item kind
+ "rgb(173, 124, 55)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "method", // item kind
+ "rgb(173, 124, 55)", // color of item kind
+ "rgb(173, 124, 55)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "structfield", // item kind
+ "rgb(0, 0, 0)", // color of item kind
+ "rgb(0, 0, 0)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "macro", // item kind
+ "rgb(6, 128, 0)", // color of item kind
+ "rgb(6, 128, 0)", // color of hovered/focused item kind
+ ),
+)
+call-function: (
+ "check-result-color", (
+ "fn", // item kind
+ "rgb(173, 124, 55)", // color of item kind
+ "rgb(173, 124, 55)", // color of hovered/focused item kind
+ ),
)
// Checking the `<a>` container.
+move-cursor-to: ".search-input"
+focus: ".search-input" // To ensure the `<a>` container isnt focus or hover.
assert-css: (
"//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
{"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"},
)
-// Checking color and background on hover.
-move-cursor-to: "//*[@class='desc']//*[text()='Just a normal struct.']"
-assert-css: (
- "//*[@class='result-name']/*[text()='test_docs::']",
- {"color": "rgb(0, 0, 0)"},
-)
-assert-css: (
- "//*[@class='result-name']/*[text()='test_docs::']/ancestor::a",
- {"color": "rgb(0, 0, 0)", "background-color": "rgb(221, 221, 221)"},
-)
-
// Check the alias more specifically in the dark theme.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// We set the theme so we're sure that the correct values will be used, whatever the computer
// this test is running on.
local-storage: {
diff --git a/src/test/rustdoc-gui/search-result-description.goml b/src/test/rustdoc-gui/search-result-description.goml
index d8cb6ee57..53a335b63 100644
--- a/src/test/rustdoc-gui/search-result-description.goml
+++ b/src/test/rustdoc-gui/search-result-description.goml
@@ -1,5 +1,5 @@
// This test is to ensure that the codeblocks are correctly rendered in the search results.
-goto: file://|DOC_PATH|/test_docs/index.html?search=some_more_function
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=some_more_function"
// Waiting for the search results to appear...
wait-for: "#titles"
assert-text: (".search-results .desc code", "format!")
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
index efbbfb925..053bfd8c9 100644
--- a/src/test/rustdoc-gui/search-result-display.goml
+++ b/src/test/rustdoc-gui/search-result-display.goml
@@ -1,5 +1,5 @@
// Checks that the search results have the expected width.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
size: (900, 1000)
write: (".search-input", "test")
// To be SURE that the search will be run.
@@ -7,7 +7,7 @@ press-key: 'Enter'
wait-for: "#crate-search"
// The width is returned by "getComputedStyle" which returns the exact number instead of the
// CSS rule which is "50%"...
-assert-css: (".search-results div.desc", {"width": "293px"})
+assert-css: (".search-results div.desc", {"width": "318px"})
size: (600, 100)
// As counter-intuitive as it may seem, in this width, the width is "100%", which is why
// when computed it's larger.
diff --git a/src/test/rustdoc-gui/search-result-go-to-first.goml b/src/test/rustdoc-gui/search-result-go-to-first.goml
index 255470a3e..eeddf5ef6 100644
--- a/src/test/rustdoc-gui/search-result-go-to-first.goml
+++ b/src/test/rustdoc-gui/search-result-go-to-first.goml
@@ -2,18 +2,18 @@
// First, we check that the first page doesn't have the string we're looking for to ensure
// that the feature is changing page as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
-assert-text-false: (".fqn .in-band", "Struct test_docs::Foo")
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+assert-text-false: (".fqn", "Struct test_docs::Foo")
// We now check that we land on the search result page if "go_to_first" isn't set.
-goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo"
// Waiting for the search results to appear...
wait-for: "#titles"
-assert-text-false: (".fqn .in-band", "Struct test_docs::Foo")
+assert-text-false: (".fqn", "Struct test_docs::Foo")
// Ensure that the search results are displayed, not the "normal" content.
assert-css: ("#main-content", {"display": "none"})
// Now we can check that the feature is working as expected!
-goto: file://|DOC_PATH|/test_docs/index.html?search=struct%3AFoo&go_to_first=true
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=struct%3AFoo&go_to_first=true"
// Waiting for the page to load...
-wait-for-text: (".fqn .in-band", "Struct test_docs::Foo")
+wait-for-text: (".fqn", "Struct test_docs::Foo")
diff --git a/src/test/rustdoc-gui/search-result-keyword.goml b/src/test/rustdoc-gui/search-result-keyword.goml
index 16ae10431..66e63155a 100644
--- a/src/test/rustdoc-gui/search-result-keyword.goml
+++ b/src/test/rustdoc-gui/search-result-keyword.goml
@@ -1,5 +1,5 @@
// Checks that the "keyword" results have the expected text alongside them.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "CookieMonster")
// To be SURE that the search will be run.
press-key: 'Enter'
diff --git a/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
index 9d506c151..a19dc6a8b 100644
--- a/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
+++ b/src/test/rustdoc-gui/search-tab-change-title-fn-sig.goml
@@ -1,6 +1,6 @@
// Checks that the search tab results work correctly with function signature syntax
// First, try a search-by-name
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "Foo")
// To be SURE that the search will be run.
press-key: 'Enter'
@@ -22,7 +22,7 @@ press-key: "ArrowLeft"
wait-for-attribute: ("#titles > button:nth-of-type(3)", {"class": "selected"})
// Now try search-by-return
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "-> String")
// To be SURE that the search will be run.
press-key: 'Enter'
@@ -44,7 +44,7 @@ press-key: "ArrowLeft"
wait-for-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
// Try with a search-by-return with no results
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "-> Something")
// To be SURE that the search will be run.
press-key: 'Enter'
@@ -54,7 +54,7 @@ assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
assert-text: ("#titles > button:nth-of-type(1)", "In Function Return Types", STARTS_WITH)
// Try with a search-by-parameter
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "usize pattern")
// To be SURE that the search will be run.
press-key: 'Enter'
@@ -64,7 +64,7 @@ assert-attribute: ("#titles > button:nth-of-type(1)", {"class": "selected"})
assert-text: ("#titles > button:nth-of-type(1)", "In Function Parameters", STARTS_WITH)
// Try with a search-by-parameter-and-return
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
write: (".search-input", "pattern -> str")
// To be SURE that the search will be run.
press-key: 'Enter'
diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml
index d9cf5ee66..f258f4d2a 100644
--- a/src/test/rustdoc-gui/settings.goml
+++ b/src/test/rustdoc-gui/settings.goml
@@ -1,5 +1,6 @@
-// This test ensures that the settings menu display is working as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
+// This test ensures that the settings menu display is working as expected and that
+// the settings page is also rendered as expected.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
show-text: true // needed when we check for colors below.
// First, we check that the settings page doesn't exist.
assert-false: "#settings"
@@ -138,9 +139,15 @@ wait-for-css: ("#help-button .popover", {"display": "block"})
assert-css: ("#settings-menu .popover", {"display": "none"})
// Now we go to the settings page to check that the CSS is loaded as expected.
-goto: file://|DOC_PATH|/settings.html
+goto: "file://" + |DOC_PATH| + "/settings.html"
wait-for: "#settings"
-assert-css: (".setting-line .toggle .slider", {"width": "45px", "margin-right": "20px"})
+assert-css: (
+ ".setting-line .toggle .slider",
+ {"width": "45px", "margin-right": "20px", "border": "0px none rgb(0, 0, 0)"},
+)
+
+assert-attribute-false: ("#settings", {"class": "popover"}, CONTAINS)
+compare-elements-position: (".sub form", "#settings", ("x"))
// We now check the display with JS disabled.
assert-false: "noscript section"
diff --git a/src/test/rustdoc-gui/shortcuts.goml b/src/test/rustdoc-gui/shortcuts.goml
index 1f20a0eaa..9068680d6 100644
--- a/src/test/rustdoc-gui/shortcuts.goml
+++ b/src/test/rustdoc-gui/shortcuts.goml
@@ -1,5 +1,5 @@
// Check that the various shortcuts are working.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// We first check that the search input isn't already focused.
assert-false: "input.search-input:focus"
press-key: "s"
@@ -11,3 +11,21 @@ press-key: "?"
assert-css: ("#help-button .popover", {"display": "block"})
press-key: "Escape"
assert-css: ("#help-button .popover", {"display": "none"})
+// Checking doc collapse and expand.
+// It should be displaying a "-":
+assert-text: ("#toggle-all-docs", "[\u2212]")
+press-key: "-"
+wait-for-text: ("#toggle-all-docs", "[+]")
+assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
+// Pressing it again shouldn't do anything.
+press-key: "-"
+assert-text: ("#toggle-all-docs", "[+]")
+assert-attribute: ("#toggle-all-docs", {"class": "will-expand"})
+// Expanding now.
+press-key: "+"
+wait-for-text: ("#toggle-all-docs", "[\u2212]")
+assert-attribute: ("#toggle-all-docs", {"class": ""})
+// Pressing it again shouldn't do anything.
+press-key: "+"
+assert-text: ("#toggle-all-docs", "[\u2212]")
+assert-attribute: ("#toggle-all-docs", {"class": ""})
diff --git a/src/test/rustdoc-gui/sidebar-links-color.goml b/src/test/rustdoc-gui/sidebar-links-color.goml
new file mode 100644
index 000000000..18a1a3fad
--- /dev/null
+++ b/src/test/rustdoc-gui/sidebar-links-color.goml
@@ -0,0 +1,233 @@
+// This test checks links colors in sidebar before and after hover.
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+
+// This is needed so that the text color is computed.
+show-text: true
+
+// Ayu theme
+local-storage: {
+ "rustdoc-theme": "ayu",
+ "rustdoc-use-system-theme": "false",
+}
+reload:
+
+// Struct
+assert-css: (
+ ".sidebar .block.struct a:not(.current)",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.struct a:not(.current)"
+assert-css: (
+ ".sidebar .block.struct a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Enum
+assert-css: (
+ ".sidebar .block.enum a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.enum a"
+assert-css: (
+ ".sidebar .block.enum a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Union
+assert-css: (
+ ".sidebar .block.union a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.union a"
+assert-css: (
+ ".sidebar .block.union a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Trait
+assert-css: (
+ ".sidebar .block.trait a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.trait a"
+assert-css: (
+ ".sidebar .block.trait a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Function
+assert-css: (
+ ".sidebar .block.fn a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.fn a"
+assert-css: (
+ ".sidebar .block.fn a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Type definition
+assert-css: (
+ ".sidebar .block.type a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.type a"
+assert-css: (
+ ".sidebar .block.type a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+// Keyword
+assert-css: (
+ ".sidebar .block.keyword a",
+ {"color": "rgb(83, 177, 219)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.keyword a"
+assert-css: (
+ ".sidebar .block.keyword a:hover",
+ {"color": "rgb(255, 180, 76)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+
+// Dark theme
+local-storage: {"rustdoc-theme": "dark"}
+reload:
+
+// Struct
+assert-css: (
+ ".sidebar .block.struct a:not(.current)",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.struct a:not(.current)"
+assert-css: (
+ ".sidebar .block.struct a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Enum
+assert-css: (
+ ".sidebar .block.enum a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.enum a"
+assert-css: (
+ ".sidebar .block.enum a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Union
+assert-css: (
+ ".sidebar .block.union a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.union a"
+assert-css: (
+ ".sidebar .block.union a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Trait
+assert-css: (
+ ".sidebar .block.trait a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.trait a"
+assert-css: (
+ ".sidebar .block.trait a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Function
+assert-css: (
+ ".sidebar .block.fn a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.fn a"
+assert-css: (
+ ".sidebar .block.fn a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Type definition
+assert-css: (
+ ".sidebar .block.type a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.type a"
+assert-css: (
+ ".sidebar .block.type a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+// Keyword
+assert-css: (
+ ".sidebar .block.keyword a",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.keyword a"
+assert-css: (
+ ".sidebar .block.keyword a:hover",
+ {"color": "rgb(253, 191, 53)", "background-color": "rgb(68, 68, 68)"},
+)
+
+// Light theme
+local-storage: {"rustdoc-theme": "light"}
+reload:
+
+// Struct
+assert-css: (
+ ".sidebar .block.struct a:not(.current)",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.struct a:not(.current)"
+assert-css: (
+ ".sidebar .block.struct a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Enum
+assert-css: (
+ ".sidebar .block.enum a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.enum a"
+assert-css: (
+ ".sidebar .block.enum a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Union
+assert-css: (
+ ".sidebar .block.union a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.union a"
+assert-css: (
+ ".sidebar .block.union a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Trait
+assert-css: (
+ ".sidebar .block.trait a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.trait a"
+assert-css: (
+ ".sidebar .block.trait a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Function
+assert-css: (
+ ".sidebar .block.fn a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.fn a"
+assert-css: (
+ ".sidebar .block.fn a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Type definition
+assert-css: (
+ ".sidebar .block.type a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.type a"
+assert-css: (
+ ".sidebar .block.type a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
+// Keyword
+assert-css: (
+ ".sidebar .block.keyword a",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgba(0, 0, 0, 0)"},
+)
+move-cursor-to: ".sidebar .block.keyword a"
+assert-css: (
+ ".sidebar .block.keyword a:hover",
+ {"color": "rgb(53, 109, 164)", "background-color": "rgb(255, 255, 255)"},
+)
diff --git a/src/test/rustdoc-gui/sidebar-macro-reexport.goml b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
index a3a62fe54..b5c1b6a43 100644
--- a/src/test/rustdoc-gui/sidebar-macro-reexport.goml
+++ b/src/test/rustdoc-gui/sidebar-macro-reexport.goml
@@ -1,5 +1,5 @@
// This test ensures that the reexport of a macro doesn't make the original macro
// displayed twice in the sidebar.
-goto: file://|DOC_PATH|/test_docs/macro.repro.html
-wait-for: ".sidebar-elems .macro .macro"
+goto: "file://" + |DOC_PATH| + "/test_docs/macro.repro.html"
+wait-for: ".sidebar-elems .block.macro a"
assert-count: ("//*[@class='sidebar-elems']//*[@class='block macro']//a[text()='repro']", 1)
diff --git a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
index dc50185f0..2449269b1 100644
--- a/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile-scroll.goml
@@ -1,12 +1,12 @@
// This test ensures that the mobile sidebar preserves scroll position.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// Switching to "mobile view" by reducing the width to 600px.
-size: (600, 600)
+size: (700, 600)
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
// Scroll down.
scroll-to: "//h2[@id='blanket-implementations']"
-assert-window-property: {"pageYOffset": "643"}
+assert-window-property: {"pageYOffset": "627"}
// 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": "643"}
+assert-window-property: {"pageYOffset": "627"}
// 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": "643"}
+assert-window-property: {"pageYOffset": "627"}
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index 033c65783..453873f1b 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -1,7 +1,7 @@
// This test ensure that the sidebar isn't "hidden" on mobile but instead moved out of the viewport.
// This is especially important for devices for "text-first" content (like for users with
// sight issues).
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// Switching to "mobile view" by reducing the width to 600px.
size: (600, 600)
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
@@ -13,7 +13,7 @@ click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
// Force the sidebar open by focusing a link inside it.
// This makes it easier for keyboard users to get to it.
-focus: ".sidebar-title a"
+focus: ".sidebar-elems h3 a"
assert-css: (".sidebar", {"display": "block", "left": "0px"})
// When we tab out of the sidebar, close it.
focus: ".search-input"
@@ -23,6 +23,11 @@ assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
click: ".sidebar-menu-toggle"
assert-css: (".sidebar", {"left": "0px"})
+// Make sure the "struct Foo" header is hidden, since the mobile topbar already does it.
+assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='Foo']/parent::h2", {"display": "none"})
+// Make sure the global navigation is still here.
+assert-css: ("//nav[contains(@class, 'sidebar')]//h2/a[text()='In test_docs']/parent::h2", {"display": "block"})
+
// Click elsewhere.
click: "body"
assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
@@ -39,26 +44,27 @@ assert-position: ("#method\.must_use", {"y": 45})
// Check that the bottom-most item on the sidebar menu can be scrolled fully into view.
click: ".sidebar-menu-toggle"
scroll-to: ".block.keyword li:nth-child(1)"
-compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 543})
+compare-elements-position-near: (".block.keyword li:nth-child(1)", ".mobile-topbar", {"y": 543.19})
// Now checking the background color of the sidebar.
+show-text: true
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
reload:
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(80, 80, 80)"})
+assert-css: (".sidebar", {"background-color": "rgb(80, 80, 80)", "color": "rgb(221, 221, 221)"})
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "ayu"}
reload:
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(20, 25, 31)"})
+assert-css: (".sidebar", {"background-color": "rgb(20, 25, 31)", "color": "rgb(197, 197, 197)"})
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "light"}
reload:
// Open the sidebar menu.
click: ".sidebar-menu-toggle"
-assert-css: (".sidebar", {"background-color": "rgb(245, 245, 245)"})
+assert-css: (".sidebar", {"background-color": "rgb(245, 245, 245)", "color": "rgb(0, 0, 0)"})
diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml
index 4321efcdb..4155dab64 100644
--- a/src/test/rustdoc-gui/sidebar-source-code-display.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml
@@ -1,22 +1,19 @@
// This test ensures that the elements in the sidebar are displayed correctly.
javascript: false
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// Since the javascript is disabled, there shouldn't be a toggle.
assert-false: "#sidebar-toggle"
-// For some reason, we need to wait a bit here because it seems like the transition on opacity
-// is being applied whereas it can't be reproduced in a browser...
-wait-for-css: (".sidebar > *", {"visibility": "hidden", "opacity": 0})
+wait-for-css: (".sidebar", {"display": "none"})
// Let's retry with javascript enabled.
javascript: true
reload:
wait-for: "#sidebar-toggle"
-assert-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
-assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden", "opacity": 0})
+assert-css: ("#sidebar-toggle", {"visibility": "visible"})
+assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden"})
// Let's expand the sidebar now.
click: "#sidebar-toggle"
-// Because of the transition CSS, we check by using `wait-for-css` instead of `assert-css`.
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
// We now check that opening the sidebar and clicking a link will leave it open.
// The behavior here on desktop is different than the behavior on mobile,
@@ -25,7 +22,7 @@ wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
wait-for-css: (".sidebar", {"width": "300px"})
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
click: ".sidebar a.selected"
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
wait-for-css: (".sidebar", {"width": "300px"})
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
@@ -36,7 +33,7 @@ show-text: true
local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"}
reload:
// Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
assert-css: (
"#source-sidebar details[open] > .files a.selected",
{"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"},
@@ -91,7 +88,7 @@ assert-css: (
local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"}
reload:
// Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
assert-css: (
"#source-sidebar details[open] > .files > a.selected",
{"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"},
@@ -146,7 +143,7 @@ assert-css: (
local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"}
reload:
// Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
assert-css: (
"#source-sidebar details[open] > .files a.selected",
{"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"},
@@ -201,7 +198,7 @@ assert-css: (
size: (500, 700)
reload:
// Waiting for the sidebar to be displayed...
-wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1})
+wait-for-css: ("#sidebar-toggle", {"visibility": "visible"})
// We now check it takes the full size of the display.
assert-property: ("body", {"clientWidth": "500", "clientHeight": "700"})
@@ -253,7 +250,7 @@ click: "#sidebar-toggle"
wait-for-css: ("#source-sidebar", {"visibility": "visible"})
assert-local-storage: {"rustdoc-source-sidebar-show": "true"}
click: ".sidebar a.selected"
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
wait-for-css: ("#source-sidebar", {"visibility": "hidden"})
assert-local-storage: {"rustdoc-source-sidebar-show": "false"}
// Resize back to desktop size, to check that the sidebar doesn't spontaneously open.
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index e882080c7..9ba663687 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -1,6 +1,6 @@
// The goal of this test is to ensure that the sidebar is working as expected in the source
// code pages.
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// First: desktop mode.
size: (1100, 800)
// We check that the sidebar isn't expanded and has the expected width.
@@ -17,7 +17,7 @@ wait-for: "html:not(.expanded)"
assert: "nav.sidebar"
// Checking that only the path to the current file is "open".
-goto: file://|DOC_PATH|/src/lib2/another_folder/sub_mod/mod.rs.html
+goto: "file://" + |DOC_PATH| + "/src/lib2/another_folder/sub_mod/mod.rs.html"
// First we expand the sidebar again.
click: (10, 10)
// We wait for the sidebar to be expanded.
@@ -42,4 +42,4 @@ assert-false: ".source-sidebar-expanded"
assert: "nav.sidebar"
// Check that the topbar is not visible
-assert-property: (".mobile-topbar", {"offsetParent": "null"})
+assert-false: ".mobile-topbar"
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index 32fe3334f..5058630f4 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -1,5 +1,6 @@
// Checks multiple things on the sidebar display (width of its elements, colors, etc).
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
show-text: true
local-storage: {"rustdoc-theme": "light"}
// We reload the page so the local storage settings are being used.
@@ -8,26 +9,29 @@ reload:
assert-text: (".sidebar > .location", "Crate test_docs")
// In modules, we only have one "location" element.
assert-count: (".sidebar .location", 1)
+assert-count: (".sidebar h2", 1)
assert-text: ("#all-types", "All Items")
assert-css: ("#all-types", {"color": "rgb(53, 109, 164)"})
// We check that we have the crates list and that the "current" on is "test_docs".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
+assert-text: (".sidebar-elems ul.crate > li > a.current", "test_docs")
// And we're also supposed to have the list of items in the current module.
assert-text: (".sidebar-elems section ul > li:nth-child(1)", "Re-exports")
assert-text: (".sidebar-elems section ul > li:nth-child(2)", "Modules")
assert-text: (".sidebar-elems section ul > li:nth-child(3)", "Macros")
assert-text: (".sidebar-elems section ul > li:nth-child(4)", "Structs")
assert-text: (".sidebar-elems section ul > li:nth-child(5)", "Enums")
-assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Traits")
-assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Functions")
-assert-text: (".sidebar-elems section ul > li:nth-child(8)", "Type Definitions")
-assert-text: (".sidebar-elems section ul > li:nth-child(9)", "Unions")
-assert-text: (".sidebar-elems section ul > li:nth-child(10)", "Keywords")
+assert-text: (".sidebar-elems section ul > li:nth-child(6)", "Constants")
+assert-text: (".sidebar-elems section ul > li:nth-child(7)", "Traits")
+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"
// PAGE: struct.Foo.html
-assert-count: (".sidebar .location", 2)
+assert-count: (".sidebar .location", 1)
+assert-count: (".sidebar h2", 2)
// We check that there is no crate listed outside of the top level.
assert-false: ".sidebar-elems > .crate"
@@ -38,38 +42,43 @@ click: ".sidebar h2.location a"
assert-property: ("html", {"scrollTop": "0"})
// We now go back to the crate page to click on the "lib2" crate link.
-goto: file://|DOC_PATH|/test_docs/index.html
-assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(53, 109, 164)"})
-click: ".sidebar-elems .crate > ul > li:first-child > a"
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
+assert-css: (".sidebar-elems ul.crate > li:first-child > a", {"color": "rgb(53, 109, 164)"})
+click: ".sidebar-elems ul.crate > li:first-child > a"
// PAGE: lib2/index.html
-goto: file://|DOC_PATH|/lib2/index.html
+goto: "file://" + |DOC_PATH| + "/lib2/index.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
assert-text: (".sidebar > .location", "Crate lib2")
// We check that we have the crates list and that the "current" on is now "lib2".
-assert-text: (".sidebar-elems .crate > ul > li > a.current", "lib2")
+assert-text: (".sidebar-elems ul.crate > li > a.current", "lib2")
// We now go to the "foobar" function page.
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(1)", "Modules")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(2)", "Structs")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(3)", "Traits")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(4)", "Functions")
-assert-text: (".sidebar-elems > section .block ul > li:nth-child(5)", "Type Definitions")
+assert-text: (".sidebar-elems > section ul.block > li:nth-child(1)", "Modules")
+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"
// PAGE: fn.foobar.html
-// In items containing no items (like functions or constants) and in modules, we have one
-// "location" elements.
-assert-count: (".sidebar .location", 1)
-assert-text: (".sidebar .sidebar-elems .location", "In lib2")
+// In items containing no items (like functions or constants) and in modules, we have no
+// "location" elements. Only the parent module h2.
+assert-count: (".sidebar .location", 0)
+assert-count: (".sidebar h2", 1)
+assert-text: (".sidebar .sidebar-elems h2", "In lib2")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems > .crate"
-goto: ./module/index.html
+goto: "./module/index.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
assert-text: (".sidebar > .location", "Module module")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems > .crate"
-goto: ./sub_module/sub_sub_module/index.html
+goto: "./sub_module/sub_sub_module/index.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
assert-text: (".sidebar > .location", "Module sub_sub_module")
// We check that we don't have the crate list.
assert-false: ".sidebar-elems .crate"
@@ -77,12 +86,22 @@ assert-text: (".sidebar-elems > section ul > li:nth-child(1)", "Functions")
assert-text: ("#functions + .item-table .item-left > 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
+goto: "file://" + |DOC_PATH| + "/lib2/struct.HasALongTraitWithParams.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
assert-property: (".sidebar-elems section .block li > a", {"offsetHeight": 29})
// Test that clicking on of the "In <module>" headings in the sidebar links to the
// appropriate anchor in index.html.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
-click: ".block.mod h3 a"
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+assert-property: (".sidebar", {"clientWidth": "200"})
+click: "//ul[@class='block mod']/preceding-sibling::h3/a"
// PAGE: index.html
assert-css: ("#modules", {"background-color": "rgb(253, 255, 211)"})
+
+// Finally, assert that the `[+]/[−]` toggle doesn't affect sidebar width.
+click: "#toggle-all-docs"
+assert-text: ("#toggle-all-docs", "[+]")
+assert-property: (".sidebar", {"clientWidth": "200"})
+click: "#toggle-all-docs"
+assert-text: ("#toggle-all-docs", "[−]")
+assert-property: (".sidebar", {"clientWidth": "200"}) \ No newline at end of file
diff --git a/src/test/rustdoc-gui/source-anchor-scroll.goml b/src/test/rustdoc-gui/source-anchor-scroll.goml
index 4e51c8dca..ddfe0c3d1 100644
--- a/src/test/rustdoc-gui/source-anchor-scroll.goml
+++ b/src/test/rustdoc-gui/source-anchor-scroll.goml
@@ -1,6 +1,6 @@
// We check that when the anchor changes and is output of the displayed content,
// the page is scrolled to it.
-goto: file://|DOC_PATH|/src/link_to_definition/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html"
// We reduce the window size to make it easier to make an element "out of the page".
size: (600, 800)
@@ -10,7 +10,7 @@ assert-property: ("html", {"scrollTop": "0"})
click: '//a[text() = "barbar"]'
assert-property: ("html", {"scrollTop": "125"})
click: '//a[text() = "bar"]'
-assert-property: ("html", {"scrollTop": "166"})
+assert-property: ("html", {"scrollTop": "156"})
click: '//a[text() = "sub_fn"]'
assert-property: ("html", {"scrollTop": "53"})
diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml
index 581f826a3..a2dac2aa6 100644
--- a/src/test/rustdoc-gui/source-code-page.goml
+++ b/src/test/rustdoc-gui/source-code-page.goml
@@ -1,30 +1,72 @@
// Checks that the interactions with the source code pages are working as expected.
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
+show-text: true
// Check that we can click on the line number.
-click: ".line-numbers > span:nth-child(4)" // This is the span for line 4.
+click: ".src-line-numbers > span:nth-child(4)" // This is the span for line 4.
// Ensure that the page URL was updated.
assert-document-property: ({"URL": "lib.rs.html#4"}, ENDS_WITH)
assert-attribute: ("//*[@id='4']", {"class": "line-highlighted"})
// We now check that the good spans are highlighted
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html#4-6
-assert-attribute-false: (".line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
-assert-attribute: (".line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
-assert-attribute-false: (".line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html#4-6"
+assert-attribute-false: (".src-line-numbers > span:nth-child(3)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(4)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(5)", {"class": "line-highlighted"})
+assert-attribute: (".src-line-numbers > span:nth-child(6)", {"class": "line-highlighted"})
+assert-attribute-false: (".src-line-numbers > span:nth-child(7)", {"class": "line-highlighted"})
+
+define-function: (
+ "check-colors",
+ (theme, color, background_color, highlight_color, highlight_background_color),
+ [
+ ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}),
+ ("reload"),
+ ("assert-css", (
+ ".src-line-numbers > span:not(.line-highlighted)",
+ {"color": |color|, "background-color": |background_color|},
+ ALL,
+ )),
+ ("assert-css", (
+ ".src-line-numbers > span.line-highlighted",
+ {"color": |highlight_color|, "background-color": |highlight_background_color|},
+ ALL,
+ )),
+ ],
+)
+
+call-function: ("check-colors", {
+ "theme": "ayu",
+ "color": "rgb(92, 103, 115)",
+ "background_color": "rgba(0, 0, 0, 0)",
+ "highlight_color": "rgb(112, 128, 144)",
+ "highlight_background_color": "rgba(255, 236, 164, 0.06)",
+})
+call-function: ("check-colors", {
+ "theme": "dark",
+ "color": "rgb(59, 145, 226)",
+ "background_color": "rgba(0, 0, 0, 0)",
+ "highlight_color": "rgb(59, 145, 226)",
+ "highlight_background_color": "rgb(10, 4, 47)",
+})
+call-function: ("check-colors", {
+ "theme": "light",
+ "color": "rgb(198, 126, 45)",
+ "background_color": "rgba(0, 0, 0, 0)",
+ "highlight_color": "rgb(198, 126, 45)",
+ "highlight_background_color": "rgb(253, 255, 211)",
+})
+
// This is to ensure that the content is correctly align with the line numbers.
compare-elements-position: ("//*[@id='1']", ".rust > code > span", ("y"))
// Assert that the line numbers text is aligned to the right.
-assert-css: (".line-numbers", {"text-align": "right"})
+assert-css: (".src-line-numbers", {"text-align": "right"})
// Now let's check that clicking on something else than the line number doesn't
// do anything (and certainly not add a `#NaN` to the URL!).
-show-text: true
-goto: file://|DOC_PATH|/src/test_docs/lib.rs.html
+goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"
// We use this assert-position to know where we will click.
-assert-position: ("//*[@id='1']", {"x": 104, "y": 103})
-// We click on the left of the "1" span but still in the "line-number" `<pre>`.
+assert-position: ("//*[@id='1']", {"x": 104, "y": 112})
+// We click on the left of the "1" span but still in the "src-line-number" `<pre>`.
click: (103, 103)
assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH)
@@ -47,3 +89,25 @@ assert-property: ("#source-sidebar details:first-of-type", {"open": "false"})
// Check the spacing.
assert-css: ("#source-sidebar > details.dir-entry", {"padding-left": "4px"})
+
+// Check the search form
+assert-css: ("nav.sub", {"flex-direction": "row"})
+// The goal of this test is to ensure the search input is perfectly centered
+// between the top of the page and the top of the gray code block.
+// To check this, we maintain the invariant:
+//
+// offsetTop[nav.sub form] = offsetTop[#main-content] - offsetHeight[nav.sub form] - offsetTop[nav.sub form]
+assert-property: ("nav.sub form", {"offsetTop": 28, "offsetHeight": 34})
+assert-property: ("#main-content", {"offsetTop": 90})
+// 28 = 90 - 34 - 28
+
+// Now do the same check on moderately-sized mobile.
+size: (700, 700)
+assert-css: ("nav.sub", {"flex-direction": "row"})
+assert-property: ("nav.sub form", {"offsetTop": 21, "offsetHeight": 34})
+assert-property: ("#main-content", {"offsetTop": 76})
+// 21 = 76 - 34 - 21
+
+// Tiny mobile gets a different display where the logo is stacked on top.
+size: (450, 700)
+assert-css: ("nav.sub", {"flex-direction": "column"})
diff --git a/src/test/rustdoc-gui/src-font-size.goml b/src/test/rustdoc-gui/src-font-size.goml
index 0c01e2545..b17dfd94c 100644
--- a/src/test/rustdoc-gui/src-font-size.goml
+++ b/src/test/rustdoc-gui/src-font-size.goml
@@ -1,11 +1,11 @@
// This test ensures that the "[src]" have the same font size as their headers
// to avoid having some weird height difference in the background when the element
// is selected.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+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"}, ALL)
-assert-css: (".impl.has-srclink .code-header.in-band", {"font-size": "18px"}, ALL)
+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)
// Check the impl items.
-assert-css: (".impl-items .has-srclink .srclink", {"font-size": "16px"}, ALL)
-assert-css: (".impl-items .has-srclink .code-header", {"font-size": "16px"}, ALL)
+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)
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 4eedf7f15..fdf97e492 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -5,6 +5,25 @@
#![crate_name = "test_docs"]
#![feature(rustdoc_internals)]
#![feature(doc_cfg)]
+#![feature(associated_type_defaults)]
+
+/*!
+Enable the feature <span class="stab portability"><code>some-feature</code></span> to enjoy
+this crate even more!
+Enable the feature <span class="stab portability"><code>some-feature</code></span> to enjoy
+this crate even more!
+Enable the feature <span class="stab portability"><code>some-feature</code></span> to enjoy
+this crate even more!
+
+Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
+Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
+Also, stop using `bar` as it's <span class="stab deprecated" title="">deprecated</span>.
+
+Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
+</span>.
+Finally, you can use `quz` only on <span class="stab portability"><code>Unix or x86-64</code>
+</span>.
+*/
use std::convert::AsRef;
use std::fmt;
@@ -298,6 +317,18 @@ pub mod details {
/// <div>I'm the content of the details!</div>
/// </details>
pub struct Details;
+
+ impl Details {
+ /// We check the appearance of the `<details>`/`<summary>` in here.
+ ///
+ /// ## Hello
+ ///
+ /// <details>
+ /// <summary><h4>I'm a summary</h4></summary>
+ /// <div>I'm the content of the details!</div>
+ /// </details>
+ pub fn method() {}
+ }
}
pub mod doc_block_table {
@@ -325,3 +356,63 @@ pub mod doc_block_table {
}
}
+
+pub struct NotableStructWithLongName<R>(R);
+
+impl<R: std::io::Read> NotableStructWithLongName<R> {
+ pub fn create_an_iterator_from_read(r: R) -> NotableStructWithLongName<R> { Self(r) }
+}
+
+impl<R: std::io::Read> std::iter::Iterator for NotableStructWithLongName<R> {
+ type Item = ();
+
+ fn next(&mut self) -> Option<Self::Item> { () }
+}
+
+pub trait TraitWithNoDocblocks {
+ fn first_fn(&self);
+ fn second_fn(&self);
+}
+
+pub struct TypeWithNoDocblocks;
+
+impl TypeWithNoDocblocks {
+ fn x() -> Option<Self> {
+ Some(Self)
+ }
+ fn y() -> Option<u32> {
+ // code comment
+ let t = Self::x()?;
+ Some(0)
+ }
+}
+
+impl TypeWithNoDocblocks {
+ pub fn first_fn(&self) {}
+ pub fn second_fn<'a>(&'a self) {
+ let x = 12;
+ let y = "a";
+ let z = false;
+ }
+}
+
+pub unsafe fn unsafe_fn() {}
+
+pub fn safe_fn() {}
+
+#[repr(C)]
+pub struct WithGenerics<T: TraitWithNoDocblocks, S = String, E = WhoLetTheDogOut, P = i8> {
+ s: S,
+ t: T,
+ e: E,
+ p: P,
+}
+
+pub const CONST: u8 = 0;
+
+pub trait TraitWithoutGenerics {
+ const C: u8 = CONST;
+ type T = SomeType;
+
+ fn foo();
+}
diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml
index fb1c37ae6..b1de3c366 100644
--- a/src/test/rustdoc-gui/theme-change.goml
+++ b/src/test/rustdoc-gui/theme-change.goml
@@ -1,5 +1,5 @@
// Ensures that the theme change is working as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
reload:
click: "#settings-menu"
@@ -17,7 +17,7 @@ click: "#theme-dark"
wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" })
assert-local-storage: { "rustdoc-theme": "dark" }
-goto: file://|DOC_PATH|/settings.html
+goto: "file://" + |DOC_PATH| + "/settings.html"
wait-for: "#settings"
click: "#theme-light"
wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
diff --git a/src/test/rustdoc-gui/theme-in-history.goml b/src/test/rustdoc-gui/theme-in-history.goml
index f576ced1c..c29571728 100644
--- a/src/test/rustdoc-gui/theme-in-history.goml
+++ b/src/test/rustdoc-gui/theme-in-history.goml
@@ -1,5 +1,5 @@
// Ensures that the theme is working when going back in history.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
// Set the theme to dark.
local-storage: {
"rustdoc-theme": "dark",
@@ -12,7 +12,7 @@ assert-css: ("body", { "background-color": "rgb(53, 53, 53)" })
assert-local-storage: { "rustdoc-theme": "dark" }
// Now we go to the settings page.
-goto: file://|DOC_PATH|/settings.html
+goto: "file://" + |DOC_PATH| + "/settings.html"
wait-for: "#settings"
// We change the theme to "light".
click: "#theme-light"
diff --git a/src/test/rustdoc-gui/toggle-click-deadspace.goml b/src/test/rustdoc-gui/toggle-click-deadspace.goml
index 8c3a0bf5b..029403ee1 100644
--- a/src/test/rustdoc-gui/toggle-click-deadspace.goml
+++ b/src/test/rustdoc-gui/toggle-click-deadspace.goml
@@ -1,6 +1,6 @@
// This test ensures that clicking on a method summary, but not on the "[-]",
// doesn't toggle the <details>.
-goto: file://|DOC_PATH|/lib2/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.Foo.html"
assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""})
click: "h4.code-header" // This is the position of "pub" in "pub fn a_method"
assert-attribute: (".impl-items .rustdoc-toggle", {"open": ""})
@@ -12,4 +12,4 @@ assert-attribute-false: (".impl-items .rustdoc-toggle", {"open": ""})
// Click the "Trait" part of "impl Trait" and verify it navigates.
click: "#impl-Trait-for-Foo h3 a:first-of-type"
-assert-text: (".fqn .in-band", "Trait lib2::Trait")
+assert-text: (".fqn", "Trait lib2::Trait")
diff --git a/src/test/rustdoc-gui/toggle-docs-mobile.goml b/src/test/rustdoc-gui/toggle-docs-mobile.goml
index ee6bc3cf7..6ce24a81b 100644
--- a/src/test/rustdoc-gui/toggle-docs-mobile.goml
+++ b/src/test/rustdoc-gui/toggle-docs-mobile.goml
@@ -1,6 +1,6 @@
// Checks that the documentation toggles on mobile have the correct position, style and work
// as expected.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
size: (433, 600)
assert-attribute: (".top-doc", {"open": ""})
click: (4, 270) // This is the position of the top doc comment toggle
diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml
index 63962b576..8c9fd0a88 100644
--- a/src/test/rustdoc-gui/toggle-docs.goml
+++ b/src/test/rustdoc-gui/toggle-docs.goml
@@ -1,5 +1,5 @@
// Checks that the documentation toggles have the correct position, style and work as expected.
-goto: file://|DOC_PATH|/test_docs/index.html
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
assert-attribute: ("#main-content > details.top-doc", {"open": ""})
assert-text: ("#toggle-all-docs", "[−]")
click: "#toggle-all-docs"
@@ -13,7 +13,7 @@ wait-for-attribute: ("#main-content > details.top-doc", {"open": ""})
assert-text: ("#toggle-all-docs", "[−]")
// Check that it works on non-module pages as well.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
// We first check that everything is visible.
assert-text: ("#toggle-all-docs", "[−]")
assert-attribute: ("#implementations-list details.rustdoc-toggle", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-gui/toggle-implementors.goml b/src/test/rustdoc-gui/toggle-implementors.goml
index 15521ff0f..8ff5b91af 100644
--- a/src/test/rustdoc-gui/toggle-implementors.goml
+++ b/src/test/rustdoc-gui/toggle-implementors.goml
@@ -1,4 +1,4 @@
// This test ensures that the implementors toggle are not open by default.
-goto: file://|DOC_PATH|/implementors/trait.Whatever.html
+goto: "file://" + |DOC_PATH| + "/implementors/trait.Whatever.html"
assert-attribute-false: ("#implementors-list > details", {"open": ""}, ALL)
diff --git a/src/test/rustdoc-gui/toggled-open-implementations.goml b/src/test/rustdoc-gui/toggled-open-implementations.goml
index bc97b38c8..e4d59b5d7 100644
--- a/src/test/rustdoc-gui/toggled-open-implementations.goml
+++ b/src/test/rustdoc-gui/toggled-open-implementations.goml
@@ -1,5 +1,5 @@
// This tests that the "implementations" section on struct/enum pages
// has all the implementations toggled open by default, so users can
// find method names in those implementations with Ctrl-F.
-goto: file://|DOC_PATH|/test_docs/struct.Foo.html
+goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
assert-attribute: (".rustdoc-toggle.implementors-toggle", {"open": ""})
diff --git a/src/test/rustdoc-gui/trait-sidebar-item-order.goml b/src/test/rustdoc-gui/trait-sidebar-item-order.goml
index d77d1dca4..a799444a1 100644
--- a/src/test/rustdoc-gui/trait-sidebar-item-order.goml
+++ b/src/test/rustdoc-gui/trait-sidebar-item-order.goml
@@ -1,5 +1,5 @@
// Checks that the elements in the sidebar are alphabetically sorted.
-goto: file://|DOC_PATH|/test_docs/trait.AnotherOne.html
+goto: "file://" + |DOC_PATH| + "/test_docs/trait.AnotherOne.html"
assert-text: (".sidebar-elems section .block li:nth-of-type(1) > a", "another")
assert-text: (".sidebar-elems section .block li:nth-of-type(2) > a", "func1")
assert-text: (".sidebar-elems section .block li:nth-of-type(3) > a", "func2")
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
index 9a46908f9..fce3002e7 100644
--- a/src/test/rustdoc-gui/type-declation-overflow.goml
+++ b/src/test/rustdoc-gui/type-declation-overflow.goml
@@ -1,5 +1,5 @@
// This test ensures that the items declaration content overflow is handled inside the <pre> directly.
-goto: file://|DOC_PATH|/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html
+goto: "file://" + |DOC_PATH| + "/lib2/long_trait/trait.ALongNameBecauseItHelpsTestingTheCurrentProblem.html"
// We set a fixed size so there is no chance of "random" resize.
size: (1100, 800)
// Logically, the <body> scroll width should be the width of the window.
@@ -8,30 +8,30 @@ assert-property: ("body", {"scrollWidth": "1100"})
assert-property: (".item-decl pre", {"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
+goto: "file://" + |DOC_PATH| + "/lib2/too_long/index.html"
assert-property: (".item-table .struct", {"offsetWidth": "684"})
// We now make the same check on type declaration...
-goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html
+goto: "file://" + |DOC_PATH| + "/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html"
assert-property: ("body", {"scrollWidth": "1100"})
// We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "825"})
+assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
assert-property: (".item-decl pre", {"scrollWidth": "1103"})
// ... and constant.
// On a sidenote, it also checks that the (very) long title isn't changing the docblock width.
-goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html
+goto: "file://" + |DOC_PATH| + "/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html"
assert-property: ("body", {"scrollWidth": "1100"})
// We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "825"})
+assert-property: ("#main-content", {"scrollWidth": "840"})
// And now checking that it has scrollable content.
assert-property: (".item-decl pre", {"scrollWidth": "950"})
// On mobile:
size: (600, 600)
-goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html
+goto: "file://" + |DOC_PATH| + "/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html"
// It shouldn't have an overflow in the topbar either.
-assert-property: (".mobile-topbar .location", {"scrollWidth": "500"})
-assert-property: (".mobile-topbar .location", {"clientWidth": "500"})
-assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"})
+store-property: (scrollWidth, ".mobile-topbar h2", "scrollWidth")
+assert-property: (".mobile-topbar h2", {"clientWidth": |scrollWidth|})
+assert-css: (".mobile-topbar h2", {"overflow-x": "hidden"})
diff --git a/src/test/rustdoc-gui/unsafe-fn.goml b/src/test/rustdoc-gui/unsafe-fn.goml
new file mode 100644
index 000000000..5e43b85fc
--- /dev/null
+++ b/src/test/rustdoc-gui/unsafe-fn.goml
@@ -0,0 +1,28 @@
+// Check position and color of the `<sup>` for unsafe elements.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+// If the text isn't displayed, the browser doesn't compute color style correctly...
+show-text: true
+
+compare-elements-property: (
+ "//a[@title='test_docs::safe_fn fn']/..",
+ "//a[@title='test_docs::unsafe_fn fn']/..",
+ ["clientHeight"]
+)
+
+define-function: (
+ "sup-check",
+ // `theme` is the theme being tested.
+ // `color` is the expected color of the `<sup>` element.
+ (theme, color),
+ [
+ // Set 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"),
+ ("assert-css", (".item-left sup", {"color": |color|})),
+ ],
+)
+
+call-function: ("sup-check", ("dark", "rgb(221, 221, 221)"))
+call-function: ("sup-check", ("ayu", "rgb(197, 197, 197)"))
+call-function: ("sup-check", ("light", "rgb(0, 0, 0)"))
diff --git a/src/test/rustdoc-gui/where-whitespace.goml b/src/test/rustdoc-gui/where-whitespace.goml
index 1a3ff1f49..776c8ec72 100644
--- a/src/test/rustdoc-gui/where-whitespace.goml
+++ b/src/test/rustdoc-gui/where-whitespace.goml
@@ -1,5 +1,5 @@
// This test ensures that the where conditions are correctly displayed.
-goto: file://|DOC_PATH|/lib2/trait.Whitespace.html
+goto: "file://" + |DOC_PATH| + "/lib2/trait.Whitespace.html"
show-text: true
// First, we check in the trait definition if the where clause is "on its own" (not on the same
// line than "pub trait Whitespace<Idx>").
@@ -7,7 +7,7 @@ compare-elements-position-false: (".item-decl code", ".where.fmt-newline", ("y")
// And that the code following it isn't on the same line either.
compare-elements-position-false: (".item-decl .fnname", ".where.fmt-newline", ("y"))
-goto: file://|DOC_PATH|/lib2/struct.WhereWhitespace.html
+goto: "file://" + |DOC_PATH| + "/lib2/struct.WhereWhitespace.html"
// We make the screen a bit wider to ensure that the trait impl is on one line.
size: (915, 915)
diff --git a/src/test/rustdoc-js-std/asrawfd.js b/src/test/rustdoc-js-std/asrawfd.js
index fd228a590..369a34f9c 100644
--- a/src/test/rustdoc-js-std/asrawfd.js
+++ b/src/test/rustdoc-js-std/asrawfd.js
@@ -6,9 +6,9 @@ const EXPECTED = {
'others': [
// Reproduction test for https://github.com/rust-lang/rust/issues/78724
// Validate that type alias methods get the correct path.
- { 'path': 'std::os::unix::io::AsRawFd', 'name': 'as_raw_fd' },
- { 'path': 'std::os::wasi::io::AsRawFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' },
{ 'path': 'std::os::linux::process::PidFd', 'name': 'as_raw_fd' },
- { 'path': 'std::os::unix::io::RawFd', 'name': 'as_raw_fd' },
+ { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' },
],
};
diff --git a/src/test/rustdoc-json/primitives/primitive_impls.rs b/src/test/rustdoc-json/primitives/primitive_impls.rs
new file mode 100644
index 000000000..1fc937406
--- /dev/null
+++ b/src/test/rustdoc-json/primitives/primitive_impls.rs
@@ -0,0 +1,34 @@
+#![feature(no_core)]
+#![feature(rustc_attrs)]
+#![feature(rustdoc_internals)]
+#![no_core]
+#![rustc_coherence_is_core]
+
+// @set impl_i32 = "$.index[*][?(@.docs=='Only core can do this')].id"
+
+/// Only core can do this
+impl i32 {
+ // @set identity = "$.index[*][?(@.docs=='Do Nothing')].id"
+
+ /// Do Nothing
+ pub fn identity(self) -> Self {
+ self
+ }
+
+ // @is "$.index[*][?(@.docs=='Only core can do this')].inner.items[*]" $identity
+}
+
+// @set Trait = "$.index[*][?(@.name=='Trait')].id"
+pub trait Trait {}
+// @set impl_trait_for_i32 = "$.index[*][?(@.docs=='impl Trait for i32')].id"
+/// impl Trait for i32
+impl Trait for i32 {}
+
+/// i32
+#[doc(primitive = "i32")]
+mod prim_i32 {}
+
+// @set i32 = "$.index[*][?(@.docs=='i32')].id"
+// @is "$.index[*][?(@.docs=='i32')].name" '"i32"'
+// @is "$.index[*][?(@.docs=='i32')].inner.name" '"i32"'
+// @ismany "$.index[*][?(@.docs=='i32')].inner.impls[*]" $impl_i32 $impl_trait_for_i32
diff --git a/src/test/rustdoc-json/primitive_overloading.rs b/src/test/rustdoc-json/primitives/primitive_overloading.rs
index 56b35cd14..56b35cd14 100644
--- a/src/test/rustdoc-json/primitive_overloading.rs
+++ b/src/test/rustdoc-json/primitives/primitive_overloading.rs
diff --git a/src/test/rustdoc-json/primitives.rs b/src/test/rustdoc-json/primitives/primitive_type.rs
index 8024044bc..8024044bc 100644
--- a/src/test/rustdoc-json/primitives.rs
+++ b/src/test/rustdoc-json/primitives/primitive_type.rs
diff --git a/src/test/rustdoc-json/primitive.rs b/src/test/rustdoc-json/primitives/use_primitive.rs
index 6454dd7f5..e22927374 100644
--- a/src/test/rustdoc-json/primitive.rs
+++ b/src/test/rustdoc-json/primitives/use_primitive.rs
@@ -5,7 +5,7 @@
#[doc(primitive = "usize")]
mod usize {}
-// @set local_crate_id = "$.index[*][?(@.name=='primitive')].crate_id"
+// @set local_crate_id = "$.index[*][?(@.name=='use_primitive')].crate_id"
// @has "$.index[*][?(@.name=='ilog10')]"
// @!is "$.index[*][?(@.name=='ilog10')].crate_id" $local_crate_id
diff --git a/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs b/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs
new file mode 100644
index 000000000..239b1a23b
--- /dev/null
+++ b/src/test/rustdoc-json/reexport/reexport_method_from_private_module.rs
@@ -0,0 +1,28 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/102583>.
+
+// @set impl_S = "$.index[*][?(@.docs=='impl S')].id"
+// @has "$.index[*][?(@.name=='S')].inner.impls[*]" $impl_S
+// @set is_present = "$.index[*][?(@.name=='is_present')].id"
+// @is "$.index[*][?(@.docs=='impl S')].inner.items[*]" $is_present
+// @!has "$.index[*][?(@.name=='hidden_impl')]"
+// @!has "$.index[*][?(@.name=='hidden_fn')]"
+
+#![no_std]
+
+mod private_mod {
+ pub struct S;
+
+ /// impl S
+ impl S {
+ pub fn is_present() {}
+ #[doc(hidden)]
+ pub fn hidden_fn() {}
+ }
+
+ #[doc(hidden)]
+ impl S {
+ pub fn hidden_impl() {}
+ }
+}
+
+pub use private_mod::*;
diff --git a/src/test/rustdoc-ui/bare-urls.stderr b/src/test/rustdoc-ui/bare-urls.stderr
index 7097a8ddf..ccf52cd0b 100644
--- a/src/test/rustdoc-ui/bare-urls.stderr
+++ b/src/test/rustdoc-ui/bare-urls.stderr
@@ -4,12 +4,12 @@ error: this URL is not a hyperlink
LL | /// https://somewhere.com
| ^^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://somewhere.com>`
|
+ = note: bare URLs are not automatically turned into clickable links
note: the lint level is defined here
--> $DIR/bare-urls.rs:3:9
|
LL | #![deny(rustdoc::bare_urls)]
| ^^^^^^^^^^^^^^^^^^
- = note: bare URLs are not automatically turned into clickable links
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:7:5
diff --git a/src/test/rustdoc-ui/check-attr-test.stderr b/src/test/rustdoc-ui/check-attr-test.stderr
index b1fa9edf0..01beba1ff 100644
--- a/src/test/rustdoc-ui/check-attr-test.stderr
+++ b/src/test/rustdoc-ui/check-attr-test.stderr
@@ -8,12 +8,12 @@ error: unknown attribute `compile-fail`. Did you mean `compile_fail`?
9 | | /// ```
| |_______^
|
+ = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
note: the lint level is defined here
--> $DIR/check-attr-test.rs:3:9
|
3 | #![deny(rustdoc::invalid_codeblock_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
--> $DIR/check-attr-test.rs:5:1
diff --git a/src/test/rustdoc-ui/check-attr.stderr b/src/test/rustdoc-ui/check-attr.stderr
index 370b804c5..f66e63ab7 100644
--- a/src/test/rustdoc-ui/check-attr.stderr
+++ b/src/test/rustdoc-ui/check-attr.stderr
@@ -10,12 +10,12 @@ LL | | /// boo
LL | | /// ```
| |_______^
|
+ = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
note: the lint level is defined here
--> $DIR/check-attr.rs:1:9
|
LL | #![deny(rustdoc::invalid_codeblock_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: the code block will either not be tested if not marked as a rust one or won't fail if it compiles successfully
error: unknown attribute `compilefail`. Did you mean `compile_fail`?
--> $DIR/check-attr.rs:3:1
diff --git a/src/test/rustdoc-ui/check-cfg-test.stderr b/src/test/rustdoc-ui/check-cfg-test.stderr
index dc25205da..9770be2f1 100644
--- a/src/test/rustdoc-ui/check-cfg-test.stderr
+++ b/src/test/rustdoc-ui/check-cfg-test.stderr
@@ -4,8 +4,8 @@ warning: unexpected `cfg` condition value
LL | #[cfg(feature = "invalid")]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: expected values for `feature` are: test
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/check-fail.stderr b/src/test/rustdoc-ui/check-fail.stderr
index 217b89d93..d8aeccbfc 100644
--- a/src/test/rustdoc-ui/check-fail.stderr
+++ b/src/test/rustdoc-ui/check-fail.stderr
@@ -32,8 +32,8 @@ LL | | //! let x = 12;
LL | | //! ```
| |_______^
|
- = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(rustdoc::all)]`
= 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: `#[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
diff --git a/src/test/rustdoc-ui/check.stderr b/src/test/rustdoc-ui/check.stderr
index 78ae65d31..d379f33f2 100644
--- a/src/test/rustdoc-ui/check.stderr
+++ b/src/test/rustdoc-ui/check.stderr
@@ -24,14 +24,14 @@ LL | pub fn foo() {}
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
|
LL | #![warn(rustdoc::all)]
| ^^^^^^^^^^^^
= note: `#[warn(rustdoc::missing_crate_level_docs)]` implied by `#[warn(rustdoc::all)]`
- = help: The following guide may be of use:
- https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
warning: missing code example in this documentation
--> $DIR/check.rs:5:1
diff --git a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
index 67d9c3989..3e08354a6 100644
--- a/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
+++ b/src/test/rustdoc-ui/deny-intra-link-resolution-failure.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `v2`
LL | /// [v2]
| ^^ no item named `v2` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/deny-intra-link-resolution-failure.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/diagnostic-width.rs b/src/test/rustdoc-ui/diagnostic-width.rs
index 61961d5ec..290d9db77 100644
--- a/src/test/rustdoc-ui/diagnostic-width.rs
+++ b/src/test/rustdoc-ui/diagnostic-width.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Zunstable-options --diagnostic-width=10
+// compile-flags: --diagnostic-width=10
#![deny(rustdoc::bare_urls)]
/// This is a long line that contains a http://link.com
diff --git a/src/test/rustdoc-ui/diagnostic-width.stderr b/src/test/rustdoc-ui/diagnostic-width.stderr
index fed049d2b..1a00d10d3 100644
--- a/src/test/rustdoc-ui/diagnostic-width.stderr
+++ b/src/test/rustdoc-ui/diagnostic-width.stderr
@@ -4,12 +4,12 @@ error: this URL is not a hyperlink
LL | ... a http://link.com
| ^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://link.com>`
|
+ = note: bare URLs are not automatically turned into clickable links
note: the lint level is defined here
--> $DIR/diagnostic-width.rs:2:9
|
LL | ...ny(rustdoc::bare_url...
| ^^^^^^^^^^^^^^^^^^
- = note: bare URLs are not automatically turned into clickable links
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/doc-attr.stderr b/src/test/rustdoc-ui/doc-attr.stderr
index cc2494c92..68df2771f 100644
--- a/src/test/rustdoc-ui/doc-attr.stderr
+++ b/src/test/rustdoc-ui/doc-attr.stderr
@@ -4,14 +4,14 @@ error: unknown `doc` attribute `as_ptr`
LL | #[doc(as_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 #82730 <https://github.com/rust-lang/rust/issues/82730>
note: the lint level is defined here
--> $DIR/doc-attr.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
error: invalid `doc` attribute
--> $DIR/doc-attr.rs:12:7
diff --git a/src/test/rustdoc-ui/doc-include-suggestion.stderr b/src/test/rustdoc-ui/doc-include-suggestion.stderr
index 870b7efa2..fcc93d053 100644
--- a/src/test/rustdoc-ui/doc-include-suggestion.stderr
+++ b/src/test/rustdoc-ui/doc-include-suggestion.stderr
@@ -4,9 +4,9 @@ warning: unknown `doc` attribute `include`
LL | #[doc(include = "external-cross-doc.md")]
| ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- help: use `doc = include_str!` instead: `#[doc = include_str!("external-cross-doc.md")]`
|
- = note: `#[warn(invalid_doc_attributes)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: `#[warn(invalid_doc_attributes)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/doc-spotlight.stderr b/src/test/rustdoc-ui/doc-spotlight.stderr
index 8e7831139..58612327f 100644
--- a/src/test/rustdoc-ui/doc-spotlight.stderr
+++ b/src/test/rustdoc-ui/doc-spotlight.stderr
@@ -4,16 +4,16 @@ error: unknown `doc` attribute `spotlight`
LL | #[doc(spotlight)]
| ^^^^^^^^^ help: use `notable_trait` instead
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
+ = note: `doc(spotlight)` is now a no-op
note: the lint level is defined here
--> $DIR/doc-spotlight.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
- = note: `doc(spotlight)` was renamed to `doc(notable_trait)`
- = note: `doc(spotlight)` is now a no-op
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/doc-test-attr.stderr b/src/test/rustdoc-ui/doc-test-attr.stderr
index 7f5e2d6bc..5e6014954 100644
--- a/src/test/rustdoc-ui/doc-test-attr.stderr
+++ b/src/test/rustdoc-ui/doc-test-attr.stderr
@@ -4,13 +4,13 @@ error: `#[doc(test(...)]` takes a list of attributes
LL | #![doc(test)]
| ^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
note: the lint level is defined here
--> $DIR/doc-test-attr.rs:2:9
|
LL | #![deny(invalid_doc_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
error: `#[doc(test(...)]` takes a list of attributes
--> $DIR/doc-test-attr.rs:7:8
diff --git a/src/test/rustdoc-ui/doc_cfg_hide.rs b/src/test/rustdoc-ui/doc_cfg_hide.rs
new file mode 100644
index 000000000..5d8791748
--- /dev/null
+++ b/src/test/rustdoc-ui/doc_cfg_hide.rs
@@ -0,0 +1,11 @@
+#![feature(doc_cfg_hide)]
+#![deny(warnings)]
+
+#![doc(cfg_hide = "test")] //~ ERROR
+//~^ WARN
+#![doc(cfg_hide)] //~ ERROR
+//~^ WARN
+
+#[doc(cfg_hide(doc))] //~ ERROR
+//~^ WARN
+pub fn foo() {}
diff --git a/src/test/rustdoc-ui/doc_cfg_hide.stderr b/src/test/rustdoc-ui/doc_cfg_hide.stderr
new file mode 100644
index 000000000..03623368c
--- /dev/null
+++ b/src/test/rustdoc-ui/doc_cfg_hide.stderr
@@ -0,0 +1,40 @@
+error: this attribute can only be applied at the crate level
+ --> $DIR/doc_cfg_hide.rs:9:7
+ |
+LL | #[doc(cfg_hide(doc))]
+ | ^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
+note: the lint level is defined here
+ --> $DIR/doc_cfg_hide.rs:2:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
+help: to apply to the crate, use an inner attribute
+ |
+LL | #![doc(cfg_hide(doc))]
+ | ~~~~~~~~~~~~~~~~~~~~~~
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+ --> $DIR/doc_cfg_hide.rs:4:8
+ |
+LL | #![doc(cfg_hide = "test")]
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: `#[doc(cfg_hide(...)]` takes a list of attributes
+ --> $DIR/doc_cfg_hide.rs:6:8
+ |
+LL | #![doc(cfg_hide)]
+ | ^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/rustdoc-ui/doctest-edition.stderr b/src/test/rustdoc-ui/doctest-edition.stderr
index 1643d6053..8a3329aa3 100644
--- a/src/test/rustdoc-ui/doctest-edition.stderr
+++ b/src/test/rustdoc-ui/doctest-edition.stderr
@@ -7,12 +7,12 @@ LL | | //! foo'b'
LL | | //! ```
| |_______^
|
+ = note: error from rustc: prefix `foo` is unknown
note: the lint level is defined here
--> $DIR/doctest-edition.rs:3:9
|
LL | #![deny(rustdoc::invalid_rust_codeblocks)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: error from rustc: prefix `foo` is unknown
help: mark blocks that do not contain Rust code as text
|
LL | //! ```text
diff --git a/src/test/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr b/src/test/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
index 517e08aa7..cbe9a3d14 100644
--- a/src/test/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
+++ b/src/test/rustdoc-ui/feature-gate-rustdoc_missing_doc_code_examples.stderr
@@ -4,14 +4,14 @@ error: unknown lint: `rustdoc::missing_doc_code_examples`
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
note: the lint level is defined here
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:1:9
|
LL | #![deny(unknown_lints)]
| ^^^^^^^^^^^^^
- = 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: unknown lint: `rustdoc::missing_doc_code_examples`
--> $DIR/feature-gate-rustdoc_missing_doc_code_examples.rs:4:1
diff --git a/src/test/rustdoc-ui/ignore-block-help.stderr b/src/test/rustdoc-ui/ignore-block-help.stderr
index 9c02ff11d..a30ea51dd 100644
--- a/src/test/rustdoc-ui/ignore-block-help.stderr
+++ b/src/test/rustdoc-ui/ignore-block-help.stderr
@@ -7,13 +7,13 @@ LL | | /// let heart = '❤️';
LL | | /// ```
| |_______^
|
- = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
help: `ignore` code blocks require valid Rust code for syntax highlighting; mark blocks that do not contain Rust code as text: ```text
--> $DIR/ignore-block-help.rs:3:5
|
LL | /// ```ignore (to-prevent-tidy-error)
| ^^^
= note: error from rustc: character literal may only contain one codepoint
+ = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
index 2319de556..4b1e04234 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.rs
@@ -1,11 +1,12 @@
+// 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 {
- //~^ ERROR recursive type `f::{closure#0}::E` has infinite size
This(E),
Unit,
}
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
deleted file mode 100644
index aa39d26fe..000000000
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait-return.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0072]: recursive type `DEF_ID` has infinite size
- --> $DIR/infinite-recursive-type-impl-trait-return.rs:7:5
- |
-LL | enum E {
- | ^^^^^^ recursive type has infinite size
-LL |
-LL | This(E),
- | - recursive without indirection
- |
-help: insert some indirection (e.g., a `DEF_ID` representable
- |
-LL | This(Box<E>),
- | ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `DEF_ID`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
index b3a7ee563..ac79582fb 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
+++ b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.rs
@@ -1,6 +1,8 @@
+// check-pass
+
fn f() -> impl Sized {
+ // rustdoc doesn't care that this is infinitely sized
enum E {
- //~^ ERROR recursive type `f::E` has infinite size
V(E),
}
unimplemented!()
diff --git a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr b/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
deleted file mode 100644
index 009bedec5..000000000
--- a/src/test/rustdoc-ui/infinite-recursive-type-impl-trait.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0072]: recursive type `f::E` has infinite size
- --> $DIR/infinite-recursive-type-impl-trait.rs:2:5
- |
-LL | enum E {
- | ^^^^^^ recursive type has infinite size
-LL |
-LL | V(E),
- | - recursive without indirection
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `f::E` representable
- |
-LL | V(Box<E>),
- | ++++ +
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/rustdoc-ui/infinite-recursive-type.stderr b/src/test/rustdoc-ui/infinite-recursive-type.stderr
index b33aba446..9e2c3ff16 100644
--- a/src/test/rustdoc-ui/infinite-recursive-type.stderr
+++ b/src/test/rustdoc-ui/infinite-recursive-type.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `E` has infinite size
--> $DIR/infinite-recursive-type.rs:1:1
|
LL | enum E {
- | ^^^^^^ recursive type has infinite size
+ | ^^^^^^
LL |
LL | V(E),
| - recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | V(Box<E>),
| ++++ +
diff --git a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr
index 00fe229da..7c81044db 100644
--- a/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr
+++ b/src/test/rustdoc-ui/intra-doc/html-as-generics-intra-doc.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `NonExistentStruct`
LL | /// This [test][NonExistentStruct<i32>] thing!
| ^^^^^^^^^^^^^^^^^^^^^^ no item named `NonExistentStruct` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/html-as-generics-intra-doc.rs:2:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: unresolved link to `NonExistentStruct2`
--> $DIR/html-as-generics-intra-doc.rs:17:11
diff --git a/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
index 8e17323fd..6ad8084b0 100644
--- a/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
+++ b/src/test/rustdoc-ui/intra-doc/macro-rules-error.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `before_but_limited_to_module`
LL | /// [before_but_limited_to_module]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no item named `before_but_limited_to_module` in scope
|
+ = note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
note: the lint level is defined here
--> $DIR/macro-rules-error.rs:5:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: `macro_rules` named `before_but_limited_to_module` exists in this crate, but it is not in scope at this link's location
error: unresolved link to `after`
--> $DIR/macro-rules-error.rs:15:6
diff --git a/src/test/rustdoc-ui/intra-doc/malformed-generics.rs b/src/test/rustdoc-ui/intra-doc/malformed-generics.rs
index 15e02925e..161625ed2 100644
--- a/src/test/rustdoc-ui/intra-doc/malformed-generics.rs
+++ b/src/test/rustdoc-ui/intra-doc/malformed-generics.rs
@@ -3,17 +3,26 @@
//! [Vec<] //~ ERROR
//! [Vec<Box<T] //~ ERROR
//! [Vec<Box<T>] //~ ERROR
+//~^ WARN
//! [Vec<Box<T>>>] //~ ERROR
+//~^ WARN
//! [Vec<T>>>] //~ ERROR
+//~^ WARN
//! [<Vec] //~ ERROR
//! [Vec::<] //~ ERROR
//! [<T>] //~ ERROR
+//~^ WARN
//! [<invalid syntax>] //~ ERROR
+//~^ WARN
//! [Vec:<T>:new()] //~ ERROR
+//~^ WARN
//! [Vec<<T>>] //~ ERROR
+//~^ WARN
//! [Vec<>] //~ ERROR
//! [Vec<<>>] //~ ERROR
// FIXME(#74563) support UFCS
//! [<Vec as IntoIterator>::into_iter] //~ ERROR
+//~^ WARN
//! [<Vec<T> as IntoIterator>::iter] //~ ERROR
+//~^ WARN
diff --git a/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr
index 5bc0f84e2..08349fef8 100644
--- a/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr
+++ b/src/test/rustdoc-ui/intra-doc/malformed-generics.stderr
@@ -23,67 +23,67 @@ LL | //! [Vec<Box<T>]
| ^^^^^^^^^^ unbalanced angle brackets
error: unresolved link to `Vec<Box<T>>>`
- --> $DIR/malformed-generics.rs:6:6
+ --> $DIR/malformed-generics.rs:7:6
|
LL | //! [Vec<Box<T>>>]
| ^^^^^^^^^^^^ unbalanced angle brackets
error: unresolved link to `Vec<T>>>`
- --> $DIR/malformed-generics.rs:7:6
+ --> $DIR/malformed-generics.rs:9:6
|
LL | //! [Vec<T>>>]
| ^^^^^^^^ unbalanced angle brackets
error: unresolved link to `<Vec`
- --> $DIR/malformed-generics.rs:8:6
+ --> $DIR/malformed-generics.rs:11:6
|
LL | //! [<Vec]
| ^^^^ unbalanced angle brackets
error: unresolved link to `Vec::<`
- --> $DIR/malformed-generics.rs:9:6
+ --> $DIR/malformed-generics.rs:12:6
|
LL | //! [Vec::<]
| ^^^^^^ unbalanced angle brackets
error: unresolved link to `<T>`
- --> $DIR/malformed-generics.rs:10:6
+ --> $DIR/malformed-generics.rs:13:6
|
LL | //! [<T>]
| ^^^ missing type for generic parameters
error: unresolved link to `<invalid syntax>`
- --> $DIR/malformed-generics.rs:11:6
+ --> $DIR/malformed-generics.rs:15:6
|
LL | //! [<invalid syntax>]
| ^^^^^^^^^^^^^^^^ missing type for generic parameters
error: unresolved link to `Vec:<T>:new`
- --> $DIR/malformed-generics.rs:12:6
+ --> $DIR/malformed-generics.rs:17:6
|
LL | //! [Vec:<T>:new()]
| ^^^^^^^^^^^^^ has invalid path separator
error: unresolved link to `Vec<<T>>`
- --> $DIR/malformed-generics.rs:13:6
+ --> $DIR/malformed-generics.rs:19:6
|
LL | //! [Vec<<T>>]
| ^^^^^^^^ too many angle brackets
error: unresolved link to `Vec<>`
- --> $DIR/malformed-generics.rs:14:6
+ --> $DIR/malformed-generics.rs:21:6
|
LL | //! [Vec<>]
| ^^^^^ empty angle brackets
error: unresolved link to `Vec<<>>`
- --> $DIR/malformed-generics.rs:15:6
+ --> $DIR/malformed-generics.rs:22:6
|
LL | //! [Vec<<>>]
| ^^^^^^^ too many angle brackets
error: unresolved link to `<Vec as IntoIterator>::into_iter`
- --> $DIR/malformed-generics.rs:18:6
+ --> $DIR/malformed-generics.rs:25:6
|
LL | //! [<Vec as IntoIterator>::into_iter]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
@@ -91,12 +91,68 @@ LL | //! [<Vec as IntoIterator>::into_iter]
= note: see https://github.com/rust-lang/rust/issues/74563 for more information
error: unresolved link to `<Vec<T> as IntoIterator>::iter`
- --> $DIR/malformed-generics.rs:19:6
+ --> $DIR/malformed-generics.rs:27:6
|
LL | //! [<Vec<T> as IntoIterator>::iter]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ fully-qualified syntax is unsupported
|
= note: see https://github.com/rust-lang/rust/issues/74563 for more information
-error: aborting due to 15 previous errors
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:5:13
+ |
+LL | //! [Vec<Box<T>]
+ | ^^^
+ |
+ = note: `#[warn(rustdoc::invalid_html_tags)]` on by default
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:7:13
+ |
+LL | //! [Vec<Box<T>>>]
+ | ^^^
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:9:9
+ |
+LL | //! [Vec<T>>>]
+ | ^^^
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:13:6
+ |
+LL | //! [<T>]
+ | ^^^
+
+warning: unclosed HTML tag `invalid`
+ --> $DIR/malformed-generics.rs:15:6
+ |
+LL | //! [<invalid syntax>]
+ | ^^^^^^^^
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:17:10
+ |
+LL | //! [Vec:<T>:new()]
+ | ^^^
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:19:10
+ |
+LL | //! [Vec<<T>>]
+ | ^^^
+
+warning: unclosed HTML tag `Vec`
+ --> $DIR/malformed-generics.rs:25:6
+ |
+LL | //! [<Vec as IntoIterator>::into_iter]
+ | ^^^^
+
+warning: unclosed HTML tag `T`
+ --> $DIR/malformed-generics.rs:27:10
+ |
+LL | //! [<Vec<T> as IntoIterator>::iter]
+ | ^^^
+
+error: aborting due to 15 previous errors; 9 warnings emitted
diff --git a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
index 4828a3044..8ec894d10 100644
--- a/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
+++ b/src/test/rustdoc-ui/intra-doc/non-path-primitives.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `T`
LL | //! [[T]::rotate_left]
| ^ no item named `T` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/non-path-primitives.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: unresolved link to `Z`
--> $DIR/non-path-primitives.rs:14:5
diff --git a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
index 6172cd2e3..4d5bd70bf 100644
--- a/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
+++ b/src/test/rustdoc-ui/intra-doc/private-from-crate-level.stderr
@@ -4,8 +4,8 @@ warning: public documentation for `private_from_crate_level` links to private it
LL | //! [my_module]
| ^^^^^^^^^ this item is private
|
- = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
= note: this link will resolve properly if you pass `--document-private-items`
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/intra-doc/private.private.stderr b/src/test/rustdoc-ui/intra-doc/private.private.stderr
index 392321f9c..6661e9021 100644
--- a/src/test/rustdoc-ui/intra-doc/private.private.stderr
+++ b/src/test/rustdoc-ui/intra-doc/private.private.stderr
@@ -4,8 +4,8 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
| ^^^^^^^^^ this item is private
|
- = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
= note: this link resolves only because you passed `--document-private-items`, but will break without
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
--> $DIR/private.rs:7:23
diff --git a/src/test/rustdoc-ui/intra-doc/private.public.stderr b/src/test/rustdoc-ui/intra-doc/private.public.stderr
index 5d1c34b91..45b51e12e 100644
--- a/src/test/rustdoc-ui/intra-doc/private.public.stderr
+++ b/src/test/rustdoc-ui/intra-doc/private.public.stderr
@@ -4,8 +4,8 @@ warning: public documentation for `DocMe` links to private item `DontDocMe`
LL | /// docs [DontDocMe] [DontDocMe::f] [DontDocMe::x]
| ^^^^^^^^^ this item is private
|
- = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
= note: this link will resolve properly if you pass `--document-private-items`
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
warning: public documentation for `DocMe` links to private item `DontDocMe::f`
--> $DIR/private.rs:7:23
diff --git a/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr
index bf4ab9fdd..e8ee40ad4 100644
--- a/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr
+++ b/src/test/rustdoc-ui/intra-doc/span-ice-55723.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `i`
LL | /// (arr[i])
| ^ no item named `i` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/span-ice-55723.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr b/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
index f0a7ed178..508d0683d 100644
--- a/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
+++ b/src/test/rustdoc-ui/intra-doc/through-proc-macro.stderr
@@ -4,12 +4,12 @@ warning: unresolved link to `Oooops`
LL | /// [Oooops]
| ^^^^^^ no item named `Oooops` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/through-proc-macro.rs:7:9
|
LL | #![warn(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
index bb8572eae..e7b4c43e7 100644
--- a/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unknown-disambiguator.stderr
@@ -4,13 +4,13 @@ error: unknown disambiguator `foo`
LL | //! Linking to [foo@banana] and [`bar@banana!()`].
| ^^^
|
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
note: the lint level is defined here
--> $DIR/unknown-disambiguator.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(warnings)]`
- = 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 `bar`
--> $DIR/unknown-disambiguator.rs:4:35
@@ -18,7 +18,7 @@ error: unknown disambiguator `bar`
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
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
error: unknown disambiguator `foo`
--> $DIR/unknown-disambiguator.rs:10:34
@@ -26,7 +26,7 @@ error: unknown disambiguator `foo`
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
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
error: unknown disambiguator `foo`
--> $DIR/unknown-disambiguator.rs:10:48
@@ -34,7 +34,7 @@ error: unknown disambiguator `foo`
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
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
error: unknown disambiguator ``
--> $DIR/unknown-disambiguator.rs:7:31
@@ -42,7 +42,7 @@ error: unknown disambiguator ``
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
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
error: unknown disambiguator ``
--> $DIR/unknown-disambiguator.rs:7:57
@@ -50,7 +50,7 @@ error: unknown disambiguator ``
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
+ = note: see https://doc.rust-lang.org/$CHANNEL/rustdoc/linking-to-items-by-name.html#namespaces-and-disambiguators for more info about disambiguators
error: aborting due to 6 previous errors
diff --git a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
index 5c0df1d1b..815324563 100644
--- a/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
+++ b/src/test/rustdoc-ui/intra-doc/unused-extern-crate.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `zip`
LL | /// See [zip] crate.
| ^^^ no item named `zip` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/unused-extern-crate.rs:2:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr
index d46df9264..c309a55f4 100644
--- a/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr
+++ b/src/test/rustdoc-ui/intra-doc/warning-crlf.stderr
@@ -4,8 +4,8 @@ warning: unresolved link to `error`
LL | /// [error]
| ^^^^^ no item named `error` in scope
|
- = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
warning: unresolved link to `error1`
--> $DIR/warning-crlf.rs:12:11
diff --git a/src/test/rustdoc-ui/invalid-doc-attr.stderr b/src/test/rustdoc-ui/invalid-doc-attr.stderr
index a4fa38179..3c66e587b 100644
--- a/src/test/rustdoc-ui/invalid-doc-attr.stderr
+++ b/src/test/rustdoc-ui/invalid-doc-attr.stderr
@@ -4,15 +4,15 @@ error: this attribute can only be applied at the crate level
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
note: the lint level is defined here
--> $DIR/invalid-doc-attr.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
- = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
help: to apply to the crate, use an inner attribute
|
LL | #![doc(test(no_crate_inject))]
diff --git a/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs b/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs
new file mode 100644
index 000000000..d973a53cb
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-html-self-closing-tag.rs
@@ -0,0 +1,70 @@
+#![deny(rustdoc::invalid_html_tags)]
+
+/// <p/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct A;
+
+/// <p style/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct B;
+
+/// <p style=""/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct C;
+
+/// <p style="x"/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct D;
+
+/// <p style="x/></p>
+//~^ ERROR unclosed quoted HTML attribute
+pub struct E;
+
+/// <p style='x/></p>
+//~^ ERROR unclosed quoted HTML attribute
+pub struct F;
+
+/// <p style="x/"></p>
+pub struct G;
+
+/// <p style="x/"/>
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct H;
+
+/// <p / >
+//~^ ERROR invalid self-closing HTML tag `p`
+pub struct I;
+
+/// <br/>
+pub struct J;
+
+/// <a href=/></a>
+pub struct K;
+
+/// <a href=//></a>
+pub struct L;
+
+/// <a href="/"/>
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct M;
+
+/// <a href=x />
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct N;
+
+/// <a href= />
+//~^ ERROR invalid self-closing HTML tag `a`
+pub struct O;
+
+/// <a href=x/></a>
+pub struct P;
+
+/// <svg><rect width=1 height=1 /></svg>
+pub struct Q;
+
+/// <svg><rect width=1 height=/></svg>
+//~^ ERROR unclosed HTML tag `rect`
+pub struct R;
+
+/// <svg / q>
+pub struct S;
diff --git a/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr b/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr
new file mode 100644
index 000000000..e45edfb43
--- /dev/null
+++ b/src/test/rustdoc-ui/invalid-html-self-closing-tag.stderr
@@ -0,0 +1,80 @@
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:3:5
+ |
+LL | /// <p/>
+ | ^^
+ |
+note: the lint level is defined here
+ --> $DIR/invalid-html-self-closing-tag.rs:1:9
+ |
+LL | #![deny(rustdoc::invalid_html_tags)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:7:5
+ |
+LL | /// <p style/>
+ | ^^
+
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:11:5
+ |
+LL | /// <p style=""/>
+ | ^^
+
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:15:5
+ |
+LL | /// <p style="x"/>
+ | ^^
+
+error: unclosed quoted HTML attribute on tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:19:14
+ |
+LL | /// <p style="x/></p>
+ | ^
+
+error: unclosed quoted HTML attribute on tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:23:14
+ |
+LL | /// <p style='x/></p>
+ | ^
+
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:30:5
+ |
+LL | /// <p style="x/"/>
+ | ^^
+
+error: invalid self-closing HTML tag `p`
+ --> $DIR/invalid-html-self-closing-tag.rs:34:5
+ |
+LL | /// <p / >
+ | ^^
+
+error: invalid self-closing HTML tag `a`
+ --> $DIR/invalid-html-self-closing-tag.rs:47:5
+ |
+LL | /// <a href="/"/>
+ | ^^
+
+error: invalid self-closing HTML tag `a`
+ --> $DIR/invalid-html-self-closing-tag.rs:51:5
+ |
+LL | /// <a href=x />
+ | ^^
+
+error: invalid self-closing HTML tag `a`
+ --> $DIR/invalid-html-self-closing-tag.rs:55:5
+ |
+LL | /// <a href= />
+ | ^^
+
+error: unclosed HTML tag `rect`
+ --> $DIR/invalid-html-self-closing-tag.rs:65:10
+ |
+LL | /// <svg><rect width=1 height=/></svg>
+ | ^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index b503d1093..acb2a6f08 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -99,3 +99,9 @@ pub fn indent_after_fenced() {}
/// ```
pub fn invalid() {}
//~^^^^ WARNING could not parse code block as Rust code
+
+/// ```
+/// fn wook_at_my_beautifuw_bwaces_plz() {);
+/// ```
+pub fn uwu() {}
+//~^^^^ WARNING could not parse code block as Rust code
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index 4c6249cc6..597d19e74 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -7,10 +7,10 @@ LL | | /// \__________pkt->size___________/ \_result->size_/ \__pkt->si
LL | | /// ```
| |_______^
|
- = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
= note: error from rustc: unknown start of token: \
= note: error from rustc: unknown start of token: \
= note: error from rustc: unknown start of token: \
+ = note: `#[warn(rustdoc::invalid_rust_codeblocks)]` on by default
help: mark blocks that do not contain Rust code as text
|
LL | /// ```text
@@ -150,5 +150,20 @@ help: mark blocks that do not contain Rust code as text
LL | /// ```text
| ++++
-warning: 12 warnings emitted
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:103:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// fn wook_at_my_beautifuw_bwaces_plz() {);
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: mismatched closing delimiter: `)`
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ++++
+
+warning: 13 warnings emitted
diff --git a/src/test/rustdoc-ui/issue-102986.rs b/src/test/rustdoc-ui/issue-102986.rs
new file mode 100644
index 000000000..001784ac2
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-102986.rs
@@ -0,0 +1,4 @@
+struct Struct {
+ y: (typeof("hey"),),
+ //~^ `typeof` is a reserved keyword but unimplemented
+}
diff --git a/src/test/rustdoc-ui/issue-102986.stderr b/src/test/rustdoc-ui/issue-102986.stderr
new file mode 100644
index 000000000..3a573726c
--- /dev/null
+++ b/src/test/rustdoc-ui/issue-102986.stderr
@@ -0,0 +1,14 @@
+error[E0516]: `typeof` is a reserved keyword but unimplemented
+ --> $DIR/issue-102986.rs:2:9
+ |
+LL | y: (typeof("hey"),),
+ | ^^^^^^^^^^^^^ reserved keyword
+ |
+help: consider replacing `typeof(...)` with an actual type
+ |
+LL | y: (&'static str,),
+ | ~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0516`.
diff --git a/src/test/rustdoc-ui/issue-74134.private.stderr b/src/test/rustdoc-ui/issue-74134.private.stderr
index 31d2dbe96..44c88b618 100644
--- a/src/test/rustdoc-ui/issue-74134.private.stderr
+++ b/src/test/rustdoc-ui/issue-74134.private.stderr
@@ -4,8 +4,8 @@ warning: public documentation for `public_item` links to private item `PrivateTy
LL | /// [`PrivateType`]
| ^^^^^^^^^^^ this item is private
|
- = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
= note: this link resolves only because you passed `--document-private-items`, but will break without
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/issue-74134.public.stderr b/src/test/rustdoc-ui/issue-74134.public.stderr
index 6a3173e3e..5b1887b83 100644
--- a/src/test/rustdoc-ui/issue-74134.public.stderr
+++ b/src/test/rustdoc-ui/issue-74134.public.stderr
@@ -4,8 +4,8 @@ warning: public documentation for `public_item` links to private item `PrivateTy
LL | /// [`PrivateType`]
| ^^^^^^^^^^^ this item is private
|
- = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
= note: this link will resolve properly if you pass `--document-private-items`
+ = note: `#[warn(rustdoc::private_intra_doc_links)]` on by default
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/lint-group.stderr b/src/test/rustdoc-ui/lint-group.stderr
index 5336c0445..4f2c96588 100644
--- a/src/test/rustdoc-ui/lint-group.stderr
+++ b/src/test/rustdoc-ui/lint-group.stderr
@@ -35,8 +35,8 @@ error: unresolved link to `error`
LL | /// what up, let's make an [error]
| ^^^^^ no item named `error` in scope
|
- = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+ = note: `#[deny(rustdoc::broken_intra_doc_links)]` implied by `#[deny(rustdoc::all)]`
error: unclosed HTML tag `unknown`
--> $DIR/lint-group.rs:28:5
diff --git a/src/test/rustdoc-ui/macro-docs.stderr b/src/test/rustdoc-ui/macro-docs.stderr
index e3cc17311..2b136f5be 100644
--- a/src/test/rustdoc-ui/macro-docs.stderr
+++ b/src/test/rustdoc-ui/macro-docs.stderr
@@ -7,13 +7,13 @@ LL | /// A
LL | m!();
| ---- in this macro invocation
|
- = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
= note: the link appears in this line:
[`long_cat`] is really long
^^^^^^^^^^
= note: no item named `long_cat` in scope
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
+ = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted
diff --git a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
index 1a1f8085a..fb3a5e415 100644
--- a/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
+++ b/src/test/rustdoc-ui/no-crate-level-doc-lint.stderr
@@ -1,12 +1,12 @@
error: 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/no-crate-level-doc-lint.rs:3:9
|
LL | #![deny(rustdoc::missing_crate_level_docs)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: The following guide may be of use:
- https://doc.rust-lang.org/$CHANNEL/rustdoc/how-to-write-documentation.html
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/normalize-cycle.rs b/src/test/rustdoc-ui/normalize-cycle.rs
index 14ffac1e1..1ed9ac6bc 100644
--- a/src/test/rustdoc-ui/normalize-cycle.rs
+++ b/src/test/rustdoc-ui/normalize-cycle.rs
@@ -1,4 +1,5 @@
// check-pass
+// compile-flags: -Znormalize-docs
// Regression test for <https://github.com/rust-lang/rust/issues/79459>.
pub trait Query {}
diff --git a/src/test/rustdoc-ui/normalize-overflow.rs b/src/test/rustdoc-ui/normalize-overflow.rs
index 0cdcc88e3..3698fe70e 100644
--- a/src/test/rustdoc-ui/normalize-overflow.rs
+++ b/src/test/rustdoc-ui/normalize-overflow.rs
@@ -1,3 +1,5 @@
// aux-crate:overflow=overflow.rs
// check-pass
// Regression test for <https://github.com/rust-lang/rust/issues/79506>.
+
+extern crate overflow;
diff --git a/src/test/rustdoc-ui/pub-export-lint.stderr b/src/test/rustdoc-ui/pub-export-lint.stderr
index c6be9c6a9..81ef79961 100644
--- a/src/test/rustdoc-ui/pub-export-lint.stderr
+++ b/src/test/rustdoc-ui/pub-export-lint.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `aloha`
LL | /// [aloha]
| ^^^^^ no item named `aloha` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/pub-export-lint.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: aborting due to previous error
diff --git a/src/test/rustdoc-ui/reference-link-reports-error-once.stderr b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
index b46a51e93..2ab67090f 100644
--- a/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
+++ b/src/test/rustdoc-ui/reference-link-reports-error-once.stderr
@@ -4,12 +4,12 @@ error: unresolved link to `ref`
LL | /// [a]: ref
| ^^^ no item named `ref` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/reference-link-reports-error-once.rs:1:9
|
LL | #![deny(rustdoc::broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: unresolved link to `ref2`
--> $DIR/reference-link-reports-error-once.rs:15:10
diff --git a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr
index 8e2a2cdd7..ee9b67cb9 100644
--- a/src/test/rustdoc-ui/renamed-lint-still-applies.stderr
+++ b/src/test/rustdoc-ui/renamed-lint-still-applies.stderr
@@ -18,12 +18,12 @@ error: unresolved link to `x`
LL | //! [x]
| ^ no item named `x` in scope
|
+ = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
note: the lint level is defined here
--> $DIR/renamed-lint-still-applies.rs:2:9
|
LL | #![deny(broken_intra_doc_links)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
error: this URL is not a hyperlink
--> $DIR/renamed-lint-still-applies.rs:9:5
@@ -31,12 +31,12 @@ error: this URL is not a hyperlink
LL | //! http://example.com
| ^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<http://example.com>`
|
+ = note: bare URLs are not automatically turned into clickable links
note: the lint level is defined here
--> $DIR/renamed-lint-still-applies.rs:7:9
|
LL | #![deny(rustdoc::non_autolinks)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = note: bare URLs are not automatically turned into clickable links
error: aborting due to 2 previous errors; 2 warnings emitted
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
index 07c8c9ff2..003542d38 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.fixed
@@ -70,3 +70,13 @@ pub struct NestedGenericsWithPunct;
//~^ ERROR unclosed HTML tag `i32`
//~|HELP try marking as source
pub struct NestedGenericsWithPunct2;
+
+/// This [`Vec<i32>`] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLink;
+
+/// This [`Vec::<i32>`] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLinkTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.rs b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
index cdd652f39..4254a660b 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.rs
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.rs
@@ -70,3 +70,13 @@ pub struct NestedGenericsWithPunct;
//~^ ERROR unclosed HTML tag `i32`
//~|HELP try marking as source
pub struct NestedGenericsWithPunct2;
+
+/// This [Vec<i32>] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLink;
+
+/// This [Vec::<i32>] thing!
+//~^ERROR unclosed HTML tag `i32`
+//~|HELP try marking as source
+pub struct IntraDocLinkTurbofish;
diff --git a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
index 211dd4210..481278bda 100644
--- a/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
+++ b/src/test/rustdoc-ui/suggestions/html-as-generics.stderr
@@ -157,5 +157,27 @@ help: try marking as source code
LL | /// Generics with punct `Vec<Vec<i32>>`!
| + +
-error: aborting due to 14 previous errors
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:74:14
+ |
+LL | /// This [Vec<i32>] thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This [`Vec<i32>`] thing!
+ | + +
+
+error: unclosed HTML tag `i32`
+ --> $DIR/html-as-generics.rs:79:16
+ |
+LL | /// This [Vec::<i32>] thing!
+ | ^^^^^
+ |
+help: try marking as source code
+ |
+LL | /// This [`Vec::<i32>`] thing!
+ | + +
+
+error: aborting due to 16 previous errors
diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout
index 749abe364..46f11d2e5 100644
--- a/src/test/rustdoc-ui/z-help.stdout
+++ b/src/test/rustdoc-ui/z-help.stdout
@@ -1,8 +1,8 @@
-Z allow-features=val -- only allow the listed language features to be enabled in code (space separated)
-Z always-encode-mir=val -- encode MIR of all functions into the crate metadata (default: no)
- -Z assume-incomplete-release=val -- make cfg(version) treat the current version as incomplete (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
@@ -17,6 +17,7 @@
-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)
@@ -35,6 +36,7 @@
-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 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
@@ -54,11 +56,11 @@
-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-threshold=val -- a default MIR inlining threshold (default: 50)
-Z inline-mir-hint-threshold=val -- inlining threshold for functions with inline hint (default: 100)
- -Z inline-in-all-cgus=val -- control whether `#[inline]` functions are in all CGUs
+ -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)
@@ -67,6 +69,7 @@
`=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)
@@ -78,11 +81,10 @@
-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-pretty-relative-line-numbers=val -- use line numbers relative to the function in mir pretty printing
-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 new-llvm-pass-manager=val -- use new LLVM pass manager (default: no)
-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
@@ -92,12 +94,11 @@
-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-unique-section-names=val -- do not use unique names for text and data sections when -Z function-sections is used
-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 diagnostic-width=val -- set the current output width for diagnostic truncation
-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
@@ -121,15 +122,13 @@
-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 profiler-runtime=val -- name of the profiler runtime crate to automatically inject (default: `profiler_builtins`)
-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 layout-seed=val -- seed layout randomization
-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 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 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
@@ -137,22 +136,20 @@
-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-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 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;
+ 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 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 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`)
@@ -160,26 +157,28 @@
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 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 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 translate-lang=val -- language identifier for diagnostic output
- -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 tune-cpu=val -- select processor to schedule for (`rustc --print target-cpus` for details)
-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=val -- measure time of rustc processes (default: no)
-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 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)
diff --git a/src/test/rustdoc/anchors.no_const_anchor.html b/src/test/rustdoc/anchors.no_const_anchor.html
index 4da1ffead..75e67330a 100644
--- a/src/test/rustdoc/anchors.no_const_anchor.html
+++ b/src/test/rustdoc/anchors.no_const_anchor.html
@@ -1 +1 @@
-<div 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></div> \ No newline at end of file
+<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
diff --git a/src/test/rustdoc/anchors.no_trait_method_anchor.html b/src/test/rustdoc/anchors.no_trait_method_anchor.html
index 6b78c7c81..d7bd525ff 100644
--- a/src/test/rustdoc/anchors.no_trait_method_anchor.html
+++ b/src/test/rustdoc/anchors.no_trait_method_anchor.html
@@ -1 +1 @@
-<div 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="fnname">bar</a>()</h4></div> \ No newline at end of file
+<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="fnname">bar</a>()</h4></section> \ No newline at end of file
diff --git a/src/test/rustdoc/anchors.no_tymethod_anchor.html b/src/test/rustdoc/anchors.no_tymethod_anchor.html
index c08f4427c..e668e5e4d 100644
--- a/src/test/rustdoc/anchors.no_tymethod_anchor.html
+++ b/src/test/rustdoc/anchors.no_tymethod_anchor.html
@@ -1 +1 @@
-<div 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="fnname">foo</a>()</h4></div> \ No newline at end of file
+<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="fnname">foo</a>()</h4></section> \ No newline at end of file
diff --git a/src/test/rustdoc/anchors.no_type_anchor.html b/src/test/rustdoc/anchors.no_type_anchor.html
index ba8e65443..2c66d5aa3 100644
--- a/src/test/rustdoc/anchors.no_type_anchor.html
+++ b/src/test/rustdoc/anchors.no_type_anchor.html
@@ -1 +1 @@
-<div 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></div> \ No newline at end of file
+<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
diff --git a/src/test/rustdoc/anonymous-lifetime.rs b/src/test/rustdoc/anonymous-lifetime.rs
index f5a7d2258..390ed5a1f 100644
--- a/src/test/rustdoc/anonymous-lifetime.rs
+++ b/src/test/rustdoc/anonymous-lifetime.rs
@@ -12,7 +12,7 @@ pub trait Stream {
}
// @has 'foo/trait.Stream.html'
-// @has - '//*[@class="code-header in-band"]' 'impl<S: ?Sized + Stream + Unpin> Stream for &mut S'
+// @has - '//*[@class="code-header"]' 'impl<S: ?Sized + Stream + Unpin> Stream for &mut S'
impl<S: ?Sized + Stream + Unpin> Stream for &mut S {
type Item = S::Item;
diff --git a/src/test/rustdoc/array-links.link_box_generic.html b/src/test/rustdoc/array-links.link_box_generic.html
new file mode 100644
index 000000000..3481bb6a0
--- /dev/null
+++ b/src/test/rustdoc/array-links.link_box_generic.html
@@ -0,0 +1 @@
+<code>pub fn delta&lt;T&gt;() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;<a class="primitive" href="{{channel}}/core/primitive.array.html">[T; 1]</a>&gt;</code> \ No newline at end of file
diff --git a/src/test/rustdoc/array-links.link_box_u32.html b/src/test/rustdoc/array-links.link_box_u32.html
new file mode 100644
index 000000000..e864ae55c
--- /dev/null
+++ b/src/test/rustdoc/array-links.link_box_u32.html
@@ -0,0 +1 @@
+<code>pub fn gamma() -&gt; <a class="struct" href="struct.MyBox.html" title="struct foo::MyBox">MyBox</a>&lt;[<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]&gt;</code> \ No newline at end of file
diff --git a/src/test/rustdoc/array-links.link_slice_generic.html b/src/test/rustdoc/array-links.link_slice_generic.html
new file mode 100644
index 000000000..f1ca2f59b
--- /dev/null
+++ b/src/test/rustdoc/array-links.link_slice_generic.html
@@ -0,0 +1 @@
+<code>pub fn beta&lt;T&gt;() -&gt; &amp;'static <a class="primitive" href="{{channel}}/core/primitive.array.html">[T; 1]</a></code> \ No newline at end of file
diff --git a/src/test/rustdoc/array-links.link_slice_u32.html b/src/test/rustdoc/array-links.link_slice_u32.html
new file mode 100644
index 000000000..c3943e8d3
--- /dev/null
+++ b/src/test/rustdoc/array-links.link_slice_u32.html
@@ -0,0 +1 @@
+<code>pub fn alpha() -&gt; &amp;'static [<a class="primitive" href="{{channel}}/core/primitive.u32.html">u32</a>; <a class="primitive" href="{{channel}}/core/primitive.array.html">1</a>]</code> \ No newline at end of file
diff --git a/src/test/rustdoc/array-links.rs b/src/test/rustdoc/array-links.rs
new file mode 100644
index 000000000..07f92ac51
--- /dev/null
+++ b/src/test/rustdoc/array-links.rs
@@ -0,0 +1,28 @@
+#![crate_name = "foo"]
+#![no_std]
+
+pub struct MyBox<T: ?Sized>(*const T);
+
+// @has 'foo/fn.alpha.html'
+// @snapshot link_slice_u32 - '//pre[@class="rust fn"]/code'
+pub fn alpha() -> &'static [u32; 1] {
+ loop {}
+}
+
+// @has 'foo/fn.beta.html'
+// @snapshot link_slice_generic - '//pre[@class="rust fn"]/code'
+pub fn beta<T>() -> &'static [T; 1] {
+ loop {}
+}
+
+// @has 'foo/fn.gamma.html'
+// @snapshot link_box_u32 - '//pre[@class="rust fn"]/code'
+pub fn gamma() -> MyBox<[u32; 1]> {
+ loop {}
+}
+
+// @has 'foo/fn.delta.html'
+// @snapshot link_box_generic - '//pre[@class="rust fn"]/code'
+pub fn delta<T>() -> MyBox<[T; 1]> {
+ loop {}
+}
diff --git a/src/test/rustdoc/assoc-consts.rs b/src/test/rustdoc/assoc-consts.rs
index 97b7739b4..a3e10ee55 100644
--- a/src/test/rustdoc/assoc-consts.rs
+++ b/src/test/rustdoc/assoc-consts.rs
@@ -13,7 +13,7 @@ pub trait Foo {
pub struct Bar;
impl Foo for Bar {
- // @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Foo for Bar'
+ // @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Foo for Bar'
// @has - '//*[@id="associatedconstant.FOO"]' 'const FOO: usize'
const FOO: usize = 12;
// @has - '//*[@id="associatedconstant.FOO_NO_DEFAULT"]' 'const FOO_NO_DEFAULT: bool'
@@ -81,7 +81,7 @@ pub trait Qux {
const QUX_DEFAULT2: u32 = 3;
}
-// @has assoc_consts/struct.Bar.html '//h3[@class="code-header in-band"]' 'impl Qux for Bar'
+// @has assoc_consts/struct.Bar.html '//h3[@class="code-header"]' 'impl Qux for Bar'
impl Qux for Bar {
// @has - '//*[@id="associatedconstant.QUX0"]' 'const QUX0: u8'
// @has - '//*[@class="docblock"]' "Docs for QUX0 in trait."
diff --git a/src/test/rustdoc/associated-consts.rs b/src/test/rustdoc/associated-consts.rs
index 9319a073b..adb155bb5 100644
--- a/src/test/rustdoc/associated-consts.rs
+++ b/src/test/rustdoc/associated-consts.rs
@@ -9,7 +9,7 @@ pub trait Trait {
pub struct Bar;
// @has 'foo/struct.Bar.html'
-// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants'
+// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Trait for Bar {
const FOO: u32 = 1;
@@ -22,7 +22,7 @@ pub enum Foo {
}
// @has 'foo/enum.Foo.html'
-// @!has - '//h3[@class="sidebar-title"]' 'Associated Constants'
+// @!has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @!has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Trait for Foo {
const FOO: u32 = 1;
@@ -33,7 +33,7 @@ impl Trait for Foo {
pub struct Baz;
// @has 'foo/struct.Baz.html'
-// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Baz {
pub const FOO: u32 = 42;
@@ -44,7 +44,7 @@ pub enum Quux {
}
// @has 'foo/enum.Quux.html'
-// @has - '//h3[@class="sidebar-title"]' 'Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//h3' 'Associated Constants'
// @has - '//div[@class="sidebar-elems"]//a' 'FOO'
impl Quux {
pub const FOO: u32 = 42;
diff --git a/src/test/rustdoc/async-trait.rs b/src/test/rustdoc/async-trait.rs
new file mode 100644
index 000000000..a473e4674
--- /dev/null
+++ b/src/test/rustdoc/async-trait.rs
@@ -0,0 +1,16 @@
+// aux-build:async-trait-dep.rs
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+extern crate async_trait_dep;
+
+pub struct Oink {}
+
+// @has 'async_trait/struct.Oink.html' '//h4[@class="code-header"]' "async fn woof()"
+impl async_trait_dep::Meow for Oink {
+ async fn woof() {
+ todo!()
+ }
+}
diff --git a/src/test/rustdoc/attribute-rendering.rs b/src/test/rustdoc/attribute-rendering.rs
index 677787184..36e10923c 100644
--- a/src/test/rustdoc/attribute-rendering.rs
+++ b/src/test/rustdoc/attribute-rendering.rs
@@ -1,7 +1,7 @@
#![crate_name = "foo"]
// @has 'foo/fn.f.html'
-// @has - //*[@'class="docblock item-decl"]' '#[export_name = "f"] pub fn f()'
+// @has - //*[@'class="item-decl"]' '#[export_name = "f"] pub fn f()'
#[export_name = "\
f"]
pub fn f() {}
diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs
index 1c7f4b724..a36dadced 100644
--- a/src/test/rustdoc/attributes.rs
+++ b/src/test/rustdoc/attributes.rs
@@ -8,6 +8,6 @@ pub extern "C" fn f() {}
#[export_name = "bar"]
pub extern "C" fn g() {}
-// @has foo/struct.Repr.html '//*[@class="docblock item-decl"]' '#[repr(C, align(8))]'
+// @has foo/struct.Repr.html '//*[@class="item-decl"]' '#[repr(C, align(8))]'
#[repr(C, align(8))]
pub struct Repr;
diff --git a/src/test/rustdoc/auxiliary/async-trait-dep.rs b/src/test/rustdoc/auxiliary/async-trait-dep.rs
new file mode 100644
index 000000000..10a55dd02
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/async-trait-dep.rs
@@ -0,0 +1,9 @@
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Meow {
+ /// Who's a good dog?
+ async fn woof();
+}
diff --git a/src/test/rustdoc/auxiliary/reexport-doc-aux.rs b/src/test/rustdoc/auxiliary/reexport-doc-aux.rs
new file mode 100644
index 000000000..3400717eb
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/reexport-doc-aux.rs
@@ -0,0 +1,5 @@
+pub struct Foo;
+
+impl Foo {
+ pub fn foo() {}
+}
diff --git a/src/test/rustdoc/blanket-reexport-item.rs b/src/test/rustdoc/blanket-reexport-item.rs
index 676d656da..437f0001f 100644
--- a/src/test/rustdoc/blanket-reexport-item.rs
+++ b/src/test/rustdoc/blanket-reexport-item.rs
@@ -1,6 +1,6 @@
#![crate_name = "foo"]
-// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header in-band"]' 'impl<T, U> Into<U> for T'
+// @has foo/struct.S.html '//*[@id="impl-Into%3CU%3E-for-S"]//h3[@class="code-header"]' 'impl<T, U> Into<U> for T'
pub struct S2 {}
mod m {
pub struct S {}
diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs
index 591139523..6cbae9abe 100644
--- a/src/test/rustdoc/const-generics/add-impl.rs
+++ b/src/test/rustdoc/const-generics/add-impl.rs
@@ -7,7 +7,7 @@ pub struct Simd<T, const WIDTH: usize> {
inner: T,
}
-// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
+// @has foo/struct.Simd.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
impl Add for Simd<u8, 16> {
type Output = Self;
diff --git a/src/test/rustdoc/const-generics/const-generics-docs.rs b/src/test/rustdoc/const-generics/const-generics-docs.rs
index 87d2f29e2..5bf76e3c4 100644
--- a/src/test/rustdoc/const-generics/const-generics-docs.rs
+++ b/src/test/rustdoc/const-generics/const-generics-docs.rs
@@ -19,10 +19,10 @@ pub use extern_crate::WTrait;
// @has foo/trait.Trait.html '//pre[@class="rust trait"]' \
// 'pub trait Trait<const N: usize>'
-// @has - '//*[@id="impl-Trait%3C1%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<1> for u8'
-// @has - '//*[@id="impl-Trait%3C2%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<2> for u8'
-// @has - '//*[@id="impl-Trait%3C{1%20+%202}%3E-for-u8"]//h3[@class="code-header in-band"]' 'impl Trait<{1 + 2}> for u8'
-// @has - '//*[@id="impl-Trait%3CN%3E-for-%5Bu8%3B%20N%5D"]//h3[@class="code-header in-band"]' \
+// @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"]' \
// 'impl<const N: usize> Trait<N> for [u8; N]'
pub trait Trait<const N: usize> {}
impl Trait<1> for u8 {}
@@ -36,7 +36,7 @@ pub struct Foo<const N: usize> where u8: Trait<N>;
// @has foo/struct.Bar.html '//pre[@class="rust struct"]' '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 in-band"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
+// @has foo/struct.Foo.html '//*[@id="impl-Foo%3CM%3E"]/h3[@class="code-header"]' 'impl<const M: usize> Foo<M>where u8: Trait<M>'
impl<const M: usize> Foo<M> where u8: Trait<M> {
// @has - '//*[@id="associatedconstant.FOO_ASSOC"]' 'pub const FOO_ASSOC: usize'
pub const FOO_ASSOC: usize = M + 13;
@@ -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 in-band"]' 'impl<const M: usize> Bar<u8, M>'
+// @has foo/struct.Bar.html '//*[@id="impl-Bar%3Cu8%2C%20M%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>'
diff --git a/src/test/rustdoc/const-generics/const-impl.rs b/src/test/rustdoc/const-generics/const-impl.rs
index f1181d54a..75ee84279 100644
--- a/src/test/rustdoc/const-generics/const-impl.rs
+++ b/src/test/rustdoc/const-generics/const-impl.rs
@@ -9,20 +9,20 @@ pub enum Order {
}
// @has foo/struct.VSet.html '//pre[@class="rust struct"]' '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 in-band"]' '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 in-band"]' 'impl<T, const ORDER: Order> Sync for VSet<T, 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>'
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 in-band"]' 'impl<T> VSet<T, { Order::Sorted }>'
+// @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 }>'
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 in-band"]' 'impl<T> VSet<T, { Order::Unsorted }>'
+// @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 }>'
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 in-band"]' 'impl Escape<r#"<script>alert("Escape");</script>"#>'
+// @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>"#>'
impl Escape<r#"<script>alert("Escape");</script>"#> {
pub fn f() {}
}
diff --git a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
index 4eac8e31e..310e89a35 100644
--- a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
+++ b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
@@ -12,7 +12,7 @@ pub struct Hasher<T> {
unsafe impl<T: Default> Send for Hasher<T> {}
// @has foo/struct.Foo.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Send for Foo'
+// @has - '//h3[@class="code-header"]' 'impl Send for Foo'
pub struct Foo {
hasher: Hasher<[u8; 3]>,
}
diff --git a/src/test/rustdoc/const-value-display.rs b/src/test/rustdoc/const-value-display.rs
index 5b2f3c48d..8d95f0de9 100644
--- a/src/test/rustdoc/const-value-display.rs
+++ b/src/test/rustdoc/const-value-display.rs
@@ -1,9 +1,9 @@
#![crate_name = "foo"]
// @has 'foo/constant.HOUR_IN_SECONDS.html'
-// @has - '//*[@class="docblock item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64'
+// @has - '//*[@class="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="docblock item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
+// @has - '//*[@class="item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64'
pub const NEGATIVE: i64 = -60 * 60;
diff --git a/src/test/rustdoc/decl-trailing-whitespace.rs b/src/test/rustdoc/decl-trailing-whitespace.rs
index 46a2307ab..e47edc132 100644
--- a/src/test/rustdoc/decl-trailing-whitespace.rs
+++ b/src/test/rustdoc/decl-trailing-whitespace.rs
@@ -7,7 +7,7 @@ pub struct Error;
// @has 'foo/trait.Write.html'
pub trait Write {
- // @snapshot 'declaration' - '//*[@class="docblock item-decl"]//code'
+ // @snapshot 'declaration' - '//*[@class="item-decl"]//code'
fn poll_write(
self: Option<String>,
cx: &mut Option<String>,
diff --git a/src/test/rustdoc/deref-recursive-pathbuf.rs b/src/test/rustdoc/deref-recursive-pathbuf.rs
index 746df9c80..be2b42b5a 100644
--- a/src/test/rustdoc/deref-recursive-pathbuf.rs
+++ b/src/test/rustdoc/deref-recursive-pathbuf.rs
@@ -7,9 +7,9 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.as_path"]' 'pub fn as_path(&self)'
// @has '-' '//*[@id="deref-methods-Path"]' 'Methods from Deref<Target = Path>'
// @has '-' '//*[@class="impl-items"]//*[@id="method.exists"]' 'pub fn exists(&self)'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-PathBuf"]' 'Methods from Deref<Target=PathBuf>'
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.as_path"]' 'as_path'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Path"]' 'Methods from Deref<Target=Path>'
// @has '-' '//*[@class="sidebar-elems"]//*[@class="block"]//a[@href="#method.exists"]' 'exists'
#![crate_name = "foo"]
diff --git a/src/test/rustdoc/deref-recursive.rs b/src/test/rustdoc/deref-recursive.rs
index d5f8473f2..0436f2f86 100644
--- a/src/test/rustdoc/deref-recursive.rs
+++ b/src/test/rustdoc/deref-recursive.rs
@@ -7,9 +7,9 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.bar"]' 'pub fn bar(&self)'
// @has '-' '//*[@id="deref-methods-Baz"]' 'Methods from Deref<Target = Baz>'
// @has '-' '//*[@class="impl-items"]//*[@id="method.baz"]' 'pub fn baz(&self)'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Bar"]' 'Methods from Deref<Target=Bar>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.bar"]' 'bar'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-Baz"]' 'Methods from Deref<Target=Baz>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.baz"]' 'baz'
#![crate_name = "foo"]
diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs
index 28f977e31..32424d13e 100644
--- a/src/test/rustdoc/deref-typedef.rs
+++ b/src/test/rustdoc/deref-typedef.rs
@@ -6,7 +6,7 @@
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)'
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)'
// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_j"]' 'pub fn foo_j(&self)'
-// @has '-' '//*[@class="sidebar-title"]/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
+// @has '-' '//div[@class="sidebar-elems"]//h3/a[@href="#deref-methods-FooJ"]' 'Methods from Deref<Target=FooJ>'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_a"]' 'foo_a'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_b"]' 'foo_b'
// @has '-' '//*[@class="sidebar-elems"]//section//a[@href="#method.foo_c"]' 'foo_c'
diff --git a/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs b/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs
new file mode 100644
index 000000000..3fb00c7db
--- /dev/null
+++ b/src/test/rustdoc/doc-notable_trait_box_is_not_an_iterator.rs
@@ -0,0 +1,38 @@
+#![feature(doc_notable_trait)]
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+#[lang = "owned_box"]
+pub struct Box<T>;
+
+impl<T> Box<T> {
+ pub fn new(x: T) -> Box<T> {
+ Box
+ }
+}
+
+#[doc(notable_trait)]
+pub trait FakeIterator {}
+
+impl<I: FakeIterator> FakeIterator for Box<I> {}
+
+#[lang = "pin"]
+pub struct Pin<T>;
+
+impl<T> Pin<T> {
+ pub fn new(x: T) -> Pin<T> {
+ Pin
+ }
+}
+
+impl<I: FakeIterator> FakeIterator for Pin<I> {}
+
+// @!has doc_notable_trait_box_is_not_an_iterator/fn.foo.html '//*' 'Notable'
+pub fn foo<T>(x: T) -> Box<T> {
+ Box::new(x)
+}
+
+// @!has doc_notable_trait_box_is_not_an_iterator/fn.bar.html '//*' 'Notable'
+pub fn bar<T>(x: T) -> Pin<T> {
+ Pin::new(x)
+}
diff --git a/src/test/rustdoc/duplicate_impls/issue-33054.rs b/src/test/rustdoc/duplicate_impls/issue-33054.rs
index 84c9e4ac0..c1f95ac91 100644
--- a/src/test/rustdoc/duplicate_impls/issue-33054.rs
+++ b/src/test/rustdoc/duplicate_impls/issue-33054.rs
@@ -1,12 +1,12 @@
// ignore-tidy-linelength
// @has issue_33054/impls/struct.Foo.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Foo'
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
+// @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
// @has issue_33054/impls/bar/trait.Bar.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Foo'
+// @has - '//h3[@class="code-header"]' 'impl Bar for Foo'
// @count - '//*[@class="struct"]' 1
pub mod impls;
diff --git a/src/test/rustdoc/empty-impl-block.rs b/src/test/rustdoc/empty-impl-block.rs
index 6a2a254f6..95d4db06b 100644
--- a/src/test/rustdoc/empty-impl-block.rs
+++ b/src/test/rustdoc/empty-impl-block.rs
@@ -16,5 +16,5 @@ pub struct Another;
pub trait Bar {}
// @has 'foo/struct.Another.html'
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for Another'
+// @has - '//h3[@class="code-header"]' 'impl Bar for Another'
impl Bar for Another {}
diff --git a/src/test/rustdoc/escape-deref-methods.rs b/src/test/rustdoc/escape-deref-methods.rs
index a62ad2c40..66919d73e 100644
--- a/src/test/rustdoc/escape-deref-methods.rs
+++ b/src/test/rustdoc/escape-deref-methods.rs
@@ -27,7 +27,7 @@ impl Deref for TitleList {
}
// @has foo/struct.TitleList.html
-// @has - '//*[@class="sidebar-title"]' 'Methods from Deref<Target=Vec<Title>>'
+// @has - '//div[@class="sidebar-elems"]//h3' 'Methods from Deref<Target=Vec<Title>>'
impl DerefMut for TitleList {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.members
diff --git a/src/test/rustdoc/extern-impl.rs b/src/test/rustdoc/extern-impl.rs
index f357d65df..fd1bc2140 100644
--- a/src/test/rustdoc/extern-impl.rs
+++ b/src/test/rustdoc/extern-impl.rs
@@ -19,9 +19,9 @@ impl Foo {
// @has foo/trait.Bar.html
pub trait Bar {}
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for fn()'
+// @has - '//h3[@class="code-header"]' 'impl Bar for fn()'
impl Bar for fn() {}
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "C" fn()'
+// @has - '//h3[@class="code-header"]' 'impl Bar for extern "C" fn()'
impl Bar for extern fn() {}
-// @has - '//h3[@class="code-header in-band"]' 'impl Bar for extern "system" fn()'
+// @has - '//h3[@class="code-header"]' 'impl Bar for extern "system" fn()'
impl Bar for extern "system" fn() {}
diff --git a/src/test/rustdoc/fn-bound.rs b/src/test/rustdoc/fn-bound.rs
index 4c4ffddc8..9e060ff20 100644
--- a/src/test/rustdoc/fn-bound.rs
+++ b/src/test/rustdoc/fn-bound.rs
@@ -11,7 +11,7 @@ pub struct ConditionalIterator<F> {
}
-// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header in-band"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>'
+// @has 'fn_bound/struct.ConditionalIterator.html' '//h3[@class="code-header"]' 'impl<F: Fn(&i32)> Iterator for ConditionalIterator<F>'
impl<F: Fn(&i32)> Iterator for ConditionalIterator<F> {
type Item = ();
diff --git a/src/test/rustdoc/generic-impl.rs b/src/test/rustdoc/generic-impl.rs
index c6beed70a..6f68b1574 100644
--- a/src/test/rustdoc/generic-impl.rs
+++ b/src/test/rustdoc/generic-impl.rs
@@ -5,7 +5,7 @@ use std::fmt;
// @!has foo/struct.Bar.html '//*[@id="impl-ToString-for-Bar"]' ''
pub struct Bar;
-// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
+// @has foo/struct.Foo.html '//*[@id="impl-ToString-for-Foo"]//h3[@class="code-header"]' 'impl<T> ToString for T'
pub struct Foo;
// @has foo/struct.Foo.html '//*[@class="sidebar-elems"]//section//a[@href="#impl-ToString-for-Foo"]' 'ToString'
diff --git a/src/test/rustdoc/higher-ranked-trait-bounds.rs b/src/test/rustdoc/higher-ranked-trait-bounds.rs
index 59b5b6e57..3493ae6d2 100644
--- a/src/test/rustdoc/higher-ranked-trait-bounds.rs
+++ b/src/test/rustdoc/higher-ranked-trait-bounds.rs
@@ -49,7 +49,7 @@ impl<'a> Foo<'a> {
// @has foo/trait.B.html
pub trait B<'x> {}
-// @has - '//h3[@class="code-header in-band"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
+// @has - '//h3[@class="code-header"]' "impl<'a> B<'a> for dyn for<'b> Trait<'b>"
impl<'a> B<'a> for dyn for<'b> Trait<'b> {}
// @has foo/struct.Bar.html
diff --git a/src/test/rustdoc/impl-disambiguation.rs b/src/test/rustdoc/impl-disambiguation.rs
index d1d39ccff..9e74ede8f 100644
--- a/src/test/rustdoc/impl-disambiguation.rs
+++ b/src/test/rustdoc/impl-disambiguation.rs
@@ -4,13 +4,13 @@ pub trait Foo {}
pub struct Bar<T> { field: T }
-// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl Foo for Bar<u8>"
impl Foo for Bar<u8> {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl Foo for Bar<u16>"
impl Foo for Bar<u16> {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<'a> Foo for &'a Bar<u8>"
impl<'a> Foo for &'a Bar<u8> {}
@@ -22,9 +22,9 @@ pub mod mod2 {
pub enum Baz {}
}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl Foo for foo::mod1::Baz"
impl Foo for mod1::Baz {}
-// @has foo/trait.Foo.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has foo/trait.Foo.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<'a> Foo for &'a foo::mod2::Baz"
impl<'a> Foo for &'a mod2::Baz {}
diff --git a/src/test/rustdoc/impl-parts.rs b/src/test/rustdoc/impl-parts.rs
index b1481e1f2..7b931727e 100644
--- a/src/test/rustdoc/impl-parts.rs
+++ b/src/test/rustdoc/impl-parts.rs
@@ -5,8 +5,8 @@ pub auto trait AnAutoTrait {}
pub struct Foo<T> { field: T }
-// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has impl_parts/struct.Foo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
-// @has impl_parts/trait.AnAutoTrait.html '//*[@class="item-list"]//h3[@class="code-header in-band"]' \
+// @has impl_parts/trait.AnAutoTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<T: Clone> !AnAutoTrait for Foo<T>where T: Sync,"
impl<T: Clone> !AnAutoTrait for Foo<T> where T: Sync {}
diff --git a/src/test/rustdoc/index-page.rs b/src/test/rustdoc/index-page.rs
index be668a127..0c947ea2e 100644
--- a/src/test/rustdoc/index-page.rs
+++ b/src/test/rustdoc/index-page.rs
@@ -5,7 +5,7 @@
#![crate_name = "foo"]
// @has foo/../index.html
-// @has - '//span[@class="in-band"]' 'List of all crates'
-// @has - '//ul[@class="crate mod"]//a[@href="foo/index.html"]' 'foo'
-// @has - '//ul[@class="crate mod"]//a[@href="all_item_types/index.html"]' 'all_item_types'
+// @has - '//h1[@class="fqn"]' 'List of all crates'
+// @has - '//ul[@class="all-items"]//a[@href="foo/index.html"]' 'foo'
+// @has - '//ul[@class="all-items"]//a[@href="all_item_types/index.html"]' 'all_item_types'
pub struct Foo;
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
new file mode 100644
index 000000000..8934bc1ee
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out0.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out0" class="associatedtype">Out0</a>: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = <a class="primitive" href="{{channel}}/std/primitive.unit.html">()</a>&gt;</h4> \ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
new file mode 100644
index 000000000..bf330670e
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out2.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out2" class="associatedtype">Out2</a>&lt;T&gt;: <a class="trait" href="../assoc_item_trait_bounds/trait.Support.html" title="trait assoc_item_trait_bounds::Support">Support</a>&lt;Item = T&gt;</h4> \ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
new file mode 100644
index 000000000..69d84e1b2
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.out9.html
@@ -0,0 +1 @@
+<h4 class="code-header">type <a href="#associatedtype.Out9" class="associatedtype">Out9</a>: <a class="trait" href="{{channel}}/core/ops/function/trait.FnMut.html" title="trait core::ops::function::FnMut">FnMut</a>(<a class="primitive" href="{{channel}}/std/primitive.i32.html">i32</a>) -&gt; <a class="primitive" href="{{channel}}/std/primitive.bool.html">bool</a> + <a class="trait" href="{{channel}}/core/clone/trait.Clone.html" title="trait core::clone::Clone">Clone</a></h4> \ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
new file mode 100644
index 000000000..5f4712aab
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/assoc_item_trait_bounds.rs
@@ -0,0 +1,40 @@
+// Regression test for issues #77763, #84579 and #102142.
+#![crate_name = "main"]
+
+// aux-build:assoc_item_trait_bounds.rs
+// build-aux-docs
+// ignore-cross-compile
+extern crate assoc_item_trait_bounds as aux;
+
+// @has main/trait.Main.html
+// @has - '//*[@id="associatedtype.Out0"]' 'type Out0: Support<Item = ()>'
+// @has - '//*[@id="associatedtype.Out1"]' 'type Out1: Support<Item = Self::Item>'
+// @has - '//*[@id="associatedtype.Out2"]' 'type Out2<T>: Support<Item = T>'
+// @has - '//*[@id="associatedtype.Out3"]' 'type Out3: Support<Produce<()> = bool>'
+// @has - '//*[@id="associatedtype.Out4"]' 'type Out4<T>: Support<Produce<T> = T>'
+// @has - '//*[@id="associatedtype.Out5"]' "type Out5: Support<Output<'static> = &'static ()>"
+// @has - '//*[@id="associatedtype.Out6"]' "type Out6: for<'a> Support<Output<'a> = &'a ()>"
+// @has - '//*[@id="associatedtype.Out7"]' "type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated"
+// @has - '//*[@id="associatedtype.Out8"]' "type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>"
+// @has - '//*[@id="associatedtype.Out9"]' "type Out9: FnMut(i32) -> bool + Clone"
+// @has - '//*[@id="associatedtype.Out10"]' "type Out10<'q>: Support<Output<'q> = ()>"
+// @has - '//*[@id="associatedtype.Out11"]' "type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>"
+// @has - '//*[@id="associatedtype.Out12"]' "type Out12: for<'w> Helper<B<'w> = Cow<'w, str>, A<'w> = bool>"
+// @has - '//*[@id="associatedtype.Out13"]' "type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>"
+// @has - '//*[@id="associatedtype.Out14"]' "type Out14<P: Copy + Eq, Q: ?Sized>"
+//
+// Snapshots:
+// Check that we don't render any where-clauses for the following associated types since
+// all corresponding projection equality predicates should have already been re-sugared
+// to associated type bindings:
+//
+// @snapshot out0 - '//*[@id="associatedtype.Out0"]/*[@class="code-header"]'
+// @snapshot out2 - '//*[@id="associatedtype.Out2"]/*[@class="code-header"]'
+// @snapshot out9 - '//*[@id="associatedtype.Out9"]/*[@class="code-header"]'
+//
+// @has - '//*[@id="tymethod.make"]' \
+// "fn make<F>(F, impl FnMut(&str) -> bool)\
+// where \
+// F: FnOnce(u32) -> String, \
+// Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>"
+pub use aux::Main;
diff --git a/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
new file mode 100644
index 000000000..d326e61da
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/assoc_item_trait_bounds.rs
@@ -0,0 +1,46 @@
+pub trait Main {
+ type Item;
+
+ type Out0: Support<Item = ()>;
+ type Out1: Support<Item = Self::Item>;
+ type Out2<T>: Support<Item = T>;
+ type Out3: Support<Produce<()> = bool>;
+ type Out4<T>: Support<Produce<T> = T>;
+ type Out5: Support<Output<'static> = &'static ()>;
+ type Out6: for<'a> Support<Output<'a> = &'a ()>;
+ type Out7: Support<Item = String, Produce<i32> = u32> + Unrelated;
+ type Out8: Unrelated + Protocol<i16, Q1 = u128, Q0 = ()>;
+ type Out9: FnMut(i32) -> bool + Clone;
+ type Out10<'q>: Support<Output<'q> = ()>;
+ type Out11: for<'r, 's> Helper<A<'s> = &'s (), B<'r> = ()>;
+ type Out12: for<'w> Helper<B<'w> = std::borrow::Cow<'w, str>, A<'w> = bool>;
+ type Out13: for<'fst, 'snd> Aid<'snd, Result<'fst> = &'fst mut str>;
+ type Out14<P: Copy + Eq, Q: ?Sized>;
+
+ fn make<F>(_: F, _: impl FnMut(&str) -> bool)
+ where
+ F: FnOnce(u32) -> String,
+ Self::Out2<()>: Protocol<u8, Q0 = Self::Item, Q1 = ()>;
+}
+
+pub trait Support {
+ type Item;
+ type Output<'a>;
+ type Produce<T>;
+}
+
+pub trait Protocol<K> {
+ type Q0;
+ type Q1;
+}
+
+pub trait Unrelated {}
+
+pub trait Helper {
+ type A<'q>;
+ type B<'q>;
+}
+
+pub trait Aid<'src> {
+ type Result<'inter>;
+}
diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
index 913ba8f2a..19433c968 100644
--- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
+++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs
@@ -13,6 +13,19 @@ pub fn func3(_x: impl Iterator<Item = impl Iterator<Item = u8>> + Clone) {}
pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
+pub fn func5(
+ _f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,
+ _a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
+) {}
+
+pub trait Other {
+ type T<'dependency>;
+}
+
+pub trait Auxiliary<'arena> {
+ type Item<'input>;
+}
+
pub async fn async_fn() {}
pub struct Foo;
diff --git a/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs b/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs
new file mode 100644
index 000000000..e7a13acc6
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/auxiliary/issue-24183.rs
@@ -0,0 +1,14 @@
+#![crate_type = "lib"]
+
+pub trait U/*: ?Sized */ {
+ fn modified(self) -> Self
+ where
+ Self: Sized
+ {
+ self
+ }
+
+ fn touch(&self)/* where Self: ?Sized */{}
+}
+
+pub trait S: Sized {}
diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs
index ef615472b..6c1cf8252 100644
--- a/src/test/rustdoc/inline_cross/impl_trait.rs
+++ b/src/test/rustdoc/inline_cross/impl_trait.rs
@@ -26,6 +26,13 @@ pub use impl_trait_aux::func3;
// @has - '//pre[@class="rust fn"]' "T: Iterator<Item = impl Clone>,"
pub use impl_trait_aux::func4;
+// @has impl_trait/fn.func5.html
+// @has - '//pre[@class="rust fn"]' "func5("
+// @has - '//pre[@class="rust fn"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
+// @has - '//pre[@class="rust fn"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>"
+// @!has - '//pre[@class="rust fn"]' 'where'
+pub use impl_trait_aux::func5;
+
// @has impl_trait/fn.async_fn.html
// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()"
pub use impl_trait_aux::async_fn;
diff --git a/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html b/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
new file mode 100644
index 000000000..6955a9614
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/issue-24183.method_no_where_self_sized.html
@@ -0,0 +1 @@
+<h4 class="code-header">fn <a href="#method.touch" class="fnname">touch</a>(&amp;self)</h4> \ No newline at end of file
diff --git a/src/test/rustdoc/inline_cross/issue-24183.rs b/src/test/rustdoc/inline_cross/issue-24183.rs
new file mode 100644
index 000000000..d11b6955f
--- /dev/null
+++ b/src/test/rustdoc/inline_cross/issue-24183.rs
@@ -0,0 +1,18 @@
+#![crate_type = "lib"]
+#![crate_name = "usr"]
+
+// aux-crate:issue_24183=issue-24183.rs
+// edition: 2021
+
+// @has usr/trait.U.html
+// @has - '//*[@class="item-decl"]' "pub trait U {"
+// @has - '//*[@id="method.modified"]' \
+// "fn modified(self) -> Self\
+// where \
+// Self: Sized"
+// @snapshot method_no_where_self_sized - '//*[@id="method.touch"]/*[@class="code-header"]'
+pub use issue_24183::U;
+
+// @has usr/trait.S.html
+// @has - '//*[@class="item-decl"]' 'pub trait S: Sized {'
+pub use issue_24183::S;
diff --git a/src/test/rustdoc/inline_cross/issue-31948-1.rs b/src/test/rustdoc/inline_cross/issue-31948-1.rs
index be8585dd1..6e89167b3 100644
--- a/src/test/rustdoc/inline_cross/issue-31948-1.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948-1.rs
@@ -5,22 +5,22 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948_1/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
-// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for'
-// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' '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"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::hidden::Wobble;
// @has issue_31948_1/trait.Bark.html
-// @has - '//h3[@class="code-header in-band"]' 'for Foo'
-// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
pub use rustdoc_nonreachable_impls::Bark;
// @has issue_31948_1/trait.Woof.html
-// @has - '//h3[@class="code-header in-band"]' 'for Foo'
-// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
pub use rustdoc_nonreachable_impls::Woof;
// @!has issue_31948_1/trait.Bar.html
diff --git a/src/test/rustdoc/inline_cross/issue-31948-2.rs b/src/test/rustdoc/inline_cross/issue-31948-2.rs
index 7aa994f19..141e07656 100644
--- a/src/test/rustdoc/inline_cross/issue-31948-2.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948-2.rs
@@ -5,15 +5,15 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948_2/struct.Wobble.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Qux for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
-// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' 'Bar for'
+// @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"]' 'Bar for'
pub use rustdoc_nonreachable_impls::hidden::Wobble;
// @has issue_31948_2/trait.Qux.html
-// @has - '//h3[@class="code-header in-band"]' 'for Foo'
-// @has - '//h3[@class="code-header in-band"]' 'for Wobble'
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::hidden::Qux;
// @!has issue_31948_2/trait.Bar.html
diff --git a/src/test/rustdoc/inline_cross/issue-31948.rs b/src/test/rustdoc/inline_cross/issue-31948.rs
index 7bf4110d3..96fc6ca47 100644
--- a/src/test/rustdoc/inline_cross/issue-31948.rs
+++ b/src/test/rustdoc/inline_cross/issue-31948.rs
@@ -5,22 +5,22 @@
extern crate rustdoc_nonreachable_impls;
// @has issue_31948/struct.Foo.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bark for'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Woof for'
-// @!has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'Bar for'
-// @!has - '//*[@class="impl"]//h3[@class="code-header in-band"]' '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 has-srclink"]//h3[@class="code-header"]' 'Bar for'
+// @!has - '//*[@class="impl"]//h3[@class="code-header"]' 'Qux for'
pub use rustdoc_nonreachable_impls::Foo;
// @has issue_31948/trait.Bark.html
-// @has - '//h3[@class="code-header in-band"]' 'for Foo'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wobble'
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+// @!has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::Bark;
// @has issue_31948/trait.Woof.html
-// @has - '//h3[@class="code-header in-band"]' 'for Foo'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wibble'
-// @!has - '//h3[@class="code-header in-band"]' 'for Wobble'
+// @has - '//h3[@class="code-header"]' 'for Foo'
+// @!has - '//h3[@class="code-header"]' 'for Wibble'
+// @!has - '//h3[@class="code-header"]' 'for Wobble'
pub use rustdoc_nonreachable_impls::Woof;
// @!has issue_31948/trait.Bar.html
diff --git a/src/test/rustdoc/inline_cross/issue-32881.rs b/src/test/rustdoc/inline_cross/issue-32881.rs
index 8052339a8..183fd15ab 100644
--- a/src/test/rustdoc/inline_cross/issue-32881.rs
+++ b/src/test/rustdoc/inline_cross/issue-32881.rs
@@ -5,7 +5,7 @@
extern crate rustdoc_trait_object_impl;
// @has issue_32881/trait.Bar.html
-// @has - '//h3[@class="code-header in-band"]' "impl<'a> dyn Bar"
-// @has - '//h3[@class="code-header in-band"]' "impl<'a> Debug for dyn Bar"
+// @has - '//h3[@class="code-header"]' "impl<'a> dyn Bar"
+// @has - '//h3[@class="code-header"]' "impl<'a> Debug for dyn Bar"
pub use rustdoc_trait_object_impl::Bar;
diff --git a/src/test/rustdoc/inline_cross/issue-33113.rs b/src/test/rustdoc/inline_cross/issue-33113.rs
index c60859bbc..d954707fa 100644
--- a/src/test/rustdoc/inline_cross/issue-33113.rs
+++ b/src/test/rustdoc/inline_cross/issue-33113.rs
@@ -5,6 +5,6 @@
extern crate bar;
// @has issue_33113/trait.Bar.html
-// @has - '//h3[@class="code-header in-band"]' "for &'a char"
-// @has - '//h3[@class="code-header in-band"]' "for Foo"
+// @has - '//h3[@class="code-header"]' "for &'a char"
+// @has - '//h3[@class="code-header"]' "for Foo"
pub use bar::Bar;
diff --git a/src/test/rustdoc/inline_cross/trait-vis.rs b/src/test/rustdoc/inline_cross/trait-vis.rs
index 363c52a33..b646babac 100644
--- a/src/test/rustdoc/inline_cross/trait-vis.rs
+++ b/src/test/rustdoc/inline_cross/trait-vis.rs
@@ -3,5 +3,5 @@
extern crate inner;
// @has trait_vis/struct.SomeStruct.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct'
+// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct'
pub use inner::SomeStruct;
diff --git a/src/test/rustdoc/inline_local/trait-vis.rs b/src/test/rustdoc/inline_local/trait-vis.rs
index e7b08088f..19b69da15 100644
--- a/src/test/rustdoc/inline_local/trait-vis.rs
+++ b/src/test/rustdoc/inline_local/trait-vis.rs
@@ -13,6 +13,6 @@ mod asdf {
}
// @has trait_vis/struct.SomeStruct.html
-// @has - '//h3[@class="code-header in-band"]' 'impl ThisTrait for SomeStruct'
-// @!has - '//h3[@class="code-header in-band"]' 'impl PrivateTrait for SomeStruct'
+// @has - '//h3[@class="code-header"]' 'impl ThisTrait for SomeStruct'
+// @!has - '//h3[@class="code-header"]' 'impl PrivateTrait for SomeStruct'
pub use asdf::SomeStruct;
diff --git a/src/test/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs b/src/test/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs
new file mode 100644
index 000000000..2b8fdec1f
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/auxiliary/issue-103463-aux.rs
@@ -0,0 +1,4 @@
+pub trait Trait {
+ /// [`u8::clone`]
+ fn method();
+}
diff --git a/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs b/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
index 5d8dcf8bc..ad50887e9 100644
--- a/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
+++ b/src/test/rustdoc/intra-doc/extern-crate-only-used-in-link.rs
@@ -16,4 +16,4 @@
//! [`empty`]
// @has - '//a[@href="../empty2/index.html"]' 'empty2'
-//! [empty2<x>]
+//! [`empty2<x>`]
diff --git a/src/test/rustdoc/intra-doc/issue-103463.rs b/src/test/rustdoc/intra-doc/issue-103463.rs
new file mode 100644
index 000000000..4adf8a9a8
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/issue-103463.rs
@@ -0,0 +1,8 @@
+// The `Trait` is not pulled into the crate resulting in doc links in its methods being resolved.
+
+// aux-build:issue-103463-aux.rs
+
+extern crate issue_103463_aux;
+use issue_103463_aux::Trait;
+
+fn main() {}
diff --git a/src/test/rustdoc/intra-doc/issue-104145.rs b/src/test/rustdoc/intra-doc/issue-104145.rs
new file mode 100644
index 000000000..9ce36740d
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/issue-104145.rs
@@ -0,0 +1,14 @@
+// Doc links in `Trait`'s methods are resolved because it has a local impl.
+
+// aux-build:issue-103463-aux.rs
+
+extern crate issue_103463_aux;
+use issue_103463_aux::Trait;
+
+pub struct LocalType;
+
+impl Trait for LocalType {
+ fn method() {}
+}
+
+fn main() {}
diff --git a/src/test/rustdoc/intra-doc/no-doc-primitive.rs b/src/test/rustdoc/intra-doc/no-doc-primitive.rs
new file mode 100644
index 000000000..e5eba1d8d
--- /dev/null
+++ b/src/test/rustdoc/intra-doc/no-doc-primitive.rs
@@ -0,0 +1,15 @@
+// Crate tree without a `doc(primitive)` module for primitive type linked to by a doc link.
+
+#![deny(rustdoc::broken_intra_doc_links)]
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+#![rustc_coherence_is_core]
+#![crate_type = "rlib"]
+
+// @has no_doc_primitive/index.html
+//! A [`char`] and its [`char::len_utf8`].
+impl char {
+ pub fn len_utf8(self) -> usize {
+ 42
+ }
+}
diff --git a/src/test/rustdoc/issue-100241.rs b/src/test/rustdoc/issue-100241.rs
new file mode 100644
index 000000000..9e9cba13a
--- /dev/null
+++ b/src/test/rustdoc/issue-100241.rs
@@ -0,0 +1,12 @@
+//! See [`S`].
+
+// Check that this isn't an ICE
+// should-fail
+
+mod foo {
+ pub use inner::S;
+ //~^ ERROR unresolved imports `inner`, `foo::S`
+}
+
+use foo::*;
+use foo::S;
diff --git a/src/test/rustdoc/issue-29503.rs b/src/test/rustdoc/issue-29503.rs
index 134821e1e..01ae44385 100644
--- a/src/test/rustdoc/issue-29503.rs
+++ b/src/test/rustdoc/issue-29503.rs
@@ -5,7 +5,7 @@ pub trait MyTrait {
fn my_string(&self) -> String;
}
-// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header in-band']" "impl<T> MyTrait for Twhere T: Debug"
+// @has - "//div[@id='implementors-list']//*[@id='impl-MyTrait-for-T']//h3[@class='code-header']" "impl<T> MyTrait for Twhere T: Debug"
impl<T> MyTrait for T
where
T: fmt::Debug,
diff --git a/src/test/rustdoc/issue-33592.rs b/src/test/rustdoc/issue-33592.rs
index 815439db9..7a128f0b8 100644
--- a/src/test/rustdoc/issue-33592.rs
+++ b/src/test/rustdoc/issue-33592.rs
@@ -6,8 +6,8 @@ pub struct Bar;
pub struct Baz;
-// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl Foo<i32> for Bar'
+// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl Foo<i32> for Bar'
impl Foo<i32> for Bar {}
-// @has foo/trait.Foo.html '//h3[@class="code-header in-band"]' 'impl<T> Foo<T> for Baz'
+// @has foo/trait.Foo.html '//h3[@class="code-header"]' 'impl<T> Foo<T> for Baz'
impl<T> Foo<T> for Baz {}
diff --git a/src/test/rustdoc/issue-46727.rs b/src/test/rustdoc/issue-46727.rs
index 00e9127a3..8cfc4827a 100644
--- a/src/test/rustdoc/issue-46727.rs
+++ b/src/test/rustdoc/issue-46727.rs
@@ -3,5 +3,5 @@
extern crate issue_46727;
// @has issue_46727/trait.Foo.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Foo for Bar<[T; 3]>'
+// @has - '//h3[@class="code-header"]' 'impl<T> Foo for Bar<[T; 3]>'
pub use issue_46727::{Foo, Bar};
diff --git a/src/test/rustdoc/issue-50159.rs b/src/test/rustdoc/issue-50159.rs
index 43fb705f5..04bc4f304 100644
--- a/src/test/rustdoc/issue-50159.rs
+++ b/src/test/rustdoc/issue-50159.rs
@@ -11,8 +11,8 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
}
// @has issue_50159/struct.Switch.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
-// @has - '//h3[@class="code-header in-band"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
+// @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
pub struct Switch<B: Signal> {
diff --git a/src/test/rustdoc/issue-51236.rs b/src/test/rustdoc/issue-51236.rs
index aa5890a84..1c7aa9c7e 100644
--- a/src/test/rustdoc/issue-51236.rs
+++ b/src/test/rustdoc/issue-51236.rs
@@ -7,7 +7,7 @@ pub mod traits {
}
// @has issue_51236/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/issue-54705.rs b/src/test/rustdoc/issue-54705.rs
index ce0f85d25..7b7290ab4 100644
--- a/src/test/rustdoc/issue-54705.rs
+++ b/src/test/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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs
index ee2420d86..22a18ef90 100644
--- a/src/test/rustdoc/issue-55321.rs
+++ b/src/test/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 in-band"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl !Send for A"
-// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Send for B<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Sync for B<T>"
pub struct B<T: ?Sized>(A, Box<T>);
diff --git a/src/test/rustdoc/issue-56822.rs b/src/test/rustdoc/issue-56822.rs
index aef6ddd8d..b4eef344b 100644
--- a/src/test/rustdoc/issue-56822.rs
+++ b/src/test/rustdoc/issue-56822.rs
@@ -17,7 +17,7 @@ impl<'a, T> MyTrait for Inner<'a, T> {
}
// @has issue_56822/struct.Parser.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/issue-60726.rs b/src/test/rustdoc/issue-60726.rs
index 167f0f039..fbb0f82ae 100644
--- a/src/test/rustdoc/issue-60726.rs
+++ b/src/test/rustdoc/issue-60726.rs
@@ -26,9 +26,9 @@ where
{}
// @has issue_60726/struct.IntoIter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Send for IntoIter<T>"
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Sync for IntoIter<T>"
pub struct IntoIter<T>{
hello:DynTrait<FooInterface<T>>,
diff --git a/src/test/rustdoc/issue-75588.rs b/src/test/rustdoc/issue-75588.rs
index ac97b94fb..3b11059a7 100644
--- a/src/test/rustdoc/issue-75588.rs
+++ b/src/test/rustdoc/issue-75588.rs
@@ -10,8 +10,8 @@ extern crate realcore;
extern crate real_gimli;
// issue #74672
-// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header in-band"]' 'impl Deref for EndianSlice'
+// @!has foo/trait.Deref.html '//*[@id="impl-Deref-for-EndianSlice"]//h3[@class="code-header"]' 'impl Deref for EndianSlice'
pub use realcore::Deref;
-// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header in-band"]' 'impl Join for Foo'
+// @has foo/trait.Join.html '//*[@id="impl-Join-for-Foo"]//h3[@class="code-header"]' 'impl Join for Foo'
pub use realcore::Join;
diff --git a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs
index 515e617b4..62fbc2444 100644
--- a/src/test/rustdoc/issue-80233-normalize-auto-trait.rs
+++ b/src/test/rustdoc/issue-80233-normalize-auto-trait.rs
@@ -31,7 +31,7 @@ impl<T: Trait3> Trait3 for Vec<T> {
pub struct Struct1 {}
// @has issue_80233_normalize_auto_trait/struct.Question.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Question<T>'
+// @has - '//h3[@class="code-header"]' 'impl<T> Send for Question<T>'
pub struct Question<T: Trait1> {
pub ins: <<Vec<T> as Trait3>::Type3 as Trait2>::Type2,
}
diff --git a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs
index 8999e6a88..adf4d111a 100644
--- a/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs
+++ b/src/test/rustdoc/issue-82465-asref-for-and-of-local.rs
@@ -1,14 +1,14 @@
use std::convert::AsRef;
pub struct Local;
-// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header in-band"]' 'impl AsRef<str> for Local'
+// @has issue_82465_asref_for_and_of_local/struct.Local.html '//h3[@class="code-header"]' 'impl AsRef<str> for Local'
impl AsRef<str> for Local {
fn as_ref(&self) -> &str {
todo!()
}
}
-// @has - '//h3[@class="code-header in-band"]' 'impl AsRef<Local> for str'
+// @has - '//h3[@class="code-header"]' 'impl AsRef<Local> for str'
impl AsRef<Local> for str {
fn as_ref(&self) -> &Local {
todo!()
diff --git a/src/test/rustdoc/issue-98697.rs b/src/test/rustdoc/issue-98697.rs
index a8841f137..d50268509 100644
--- a/src/test/rustdoc/issue-98697.rs
+++ b/src/test/rustdoc/issue-98697.rs
@@ -12,6 +12,6 @@ extern crate issue_98697_reexport_with_anonymous_lifetime;
// @!has issue_98697/fn.repro.html '//pre[@class="rust fn"]/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 in-band"]' 'impl MyTrait<&Extra> for Extra'
-// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header in-band"]' 'impl<'
+// @has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl MyTrait<&Extra> for Extra'
+// @!has issue_98697/struct.Extra.html '//div[@id="trait-implementations-list"]//h3[@class="code-header"]' 'impl<'
pub use issue_98697_reexport_with_anonymous_lifetime::Extra;
diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs
index 1cebe4c67..ea1273850 100644
--- a/src/test/rustdoc/keyword.rs
+++ b/src/test/rustdoc/keyword.rs
@@ -7,7 +7,7 @@
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Keywords'
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#keywords'
// @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
-// @has foo/keyword.match.html '//span[@class="in-band"]' 'Keyword match'
+// @has foo/keyword.match.html '//h1[@class="fqn"]' 'Keyword match'
// @has foo/keyword.match.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has foo/index.html '//a/@href' '../foo/index.html'
// @!has foo/foo/index.html
diff --git a/src/test/rustdoc/logo-class-default.rs b/src/test/rustdoc/logo-class-default.rs
index a7016d227..d2d439199 100644
--- a/src/test/rustdoc/logo-class-default.rs
+++ b/src/test/rustdoc/logo-class-default.rs
@@ -1,4 +1,4 @@
// Note: this test is paired with logo-class.rs.
// @has logo_class_default/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
-// @has logo_class_default/struct.SomeStruct.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
+// @has src/logo_class_default/logo-class-default.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
pub struct SomeStruct;
diff --git a/src/test/rustdoc/logo-class.rs b/src/test/rustdoc/logo-class.rs
index f071f356a..d3aa446da 100644
--- a/src/test/rustdoc/logo-class.rs
+++ b/src/test/rustdoc/logo-class.rs
@@ -5,6 +5,6 @@
// @has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
// @!has logo_class/struct.SomeStruct.html '//*[@class="logo-container"]/img[@class="rust-logo"]' ''
//
-// @has logo_class/struct.SomeStruct.html '//*[@class="sub-logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
-// @!has logo_class/struct.SomeStruct.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
+// @has src/logo_class/logo-class.rs.html '//*[@class="sub-logo-container"]/img[@src="https://raw.githubusercontent.com/sagebind/isahc/master/media/isahc.svg.png"]' ''
+// @!has src/logo_class/logo-class.rs.html '//*[@class="sub-logo-container"]/img[@class="rust-logo"]' ''
pub struct SomeStruct;
diff --git a/src/test/rustdoc/macro-higher-kinded-function.rs b/src/test/rustdoc/macro-higher-kinded-function.rs
index 02a430564..b8c52b7b7 100644
--- a/src/test/rustdoc/macro-higher-kinded-function.rs
+++ b/src/test/rustdoc/macro-higher-kinded-function.rs
@@ -11,8 +11,8 @@ macro_rules! gen {
}
// @has 'foo/struct.Providers.html'
-// @has - '//*[@class="docblock item-decl"]//code' "pub a: for<'tcx> fn(_: TyCtxt<'tcx>, _: u8) -> i8,"
-// @has - '//*[@class="docblock item-decl"]//code' "pub b: for<'tcx> fn(_: TyCtxt<'tcx>, _: u16) -> i16,"
+// @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 - '//*[@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/src/test/rustdoc/negative-impl-sidebar.rs b/src/test/rustdoc/negative-impl-sidebar.rs
index b995fff1f..4af6d0084 100644
--- a/src/test/rustdoc/negative-impl-sidebar.rs
+++ b/src/test/rustdoc/negative-impl-sidebar.rs
@@ -4,6 +4,6 @@
pub struct Foo;
// @has foo/struct.Foo.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#trait-implementations"]' 'Trait Implementations'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#trait-implementations"]' 'Trait Implementations'
// @has - '//*[@class="sidebar-elems"]//section//a' '!Sync'
impl !Sync for Foo {}
diff --git a/src/test/rustdoc/negative-impl.rs b/src/test/rustdoc/negative-impl.rs
index 61a239868..af19c784d 100644
--- a/src/test/rustdoc/negative-impl.rs
+++ b/src/test/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 in-band"]' \
+// @matches negative_impl/struct.Alpha.html '//*[@class="impl has-srclink"]//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 in-band"]' "\
+// @matches negative_impl/struct.Bravo.html '//*[@class="impl has-srclink"]//h3[@class="code-header"]' "\
// impl<B> !Send for Bravo<B>"
impl<B> !Send for Bravo<B> {}
diff --git a/src/test/rustdoc/normalize-assoc-item.rs b/src/test/rustdoc/normalize-assoc-item.rs
index ad1a868ee..db56f6852 100644
--- a/src/test/rustdoc/normalize-assoc-item.rs
+++ b/src/test/rustdoc/normalize-assoc-item.rs
@@ -11,11 +11,24 @@ impl Trait for usize {
type X = isize;
}
+impl Trait for () {
+ type X = fn() -> i32;
+}
+
+impl Trait for isize {
+ type X = <() as Trait>::X;
+}
+
// @has 'normalize_assoc_item/fn.f.html' '//pre[@class="rust fn"]' 'pub fn f() -> isize'
pub fn f() -> <usize as Trait>::X {
0
}
+// @has 'normalize_assoc_item/fn.f2.html' '//pre[@class="rust fn"]' 'pub fn f2() -> fn() -> i32'
+pub fn f2() -> <isize as Trait>::X {
+ todo!()
+}
+
pub struct S {
// @has 'normalize_assoc_item/struct.S.html' '//span[@id="structfield.box_me_up"]' 'box_me_up: Box<S, Global>'
pub box_me_up: <S as Trait>::X,
diff --git a/src/test/rustdoc/not-wf-ambiguous-normalization.rs b/src/test/rustdoc/not-wf-ambiguous-normalization.rs
new file mode 100644
index 000000000..1e9f925f8
--- /dev/null
+++ b/src/test/rustdoc/not-wf-ambiguous-normalization.rs
@@ -0,0 +1,24 @@
+// compile-flags: -Znormalize-docs
+
+#![feature(type_alias_impl_trait)]
+
+trait Allocator {
+ type Buffer;
+}
+
+struct DefaultAllocator;
+
+// This unconstrained impl parameter causes the normalization of
+// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
+// which caused an ICE with `-Znormalize-docs`.
+impl<T> Allocator for DefaultAllocator {
+ type Buffer = ();
+}
+
+type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
+
+fn foo() -> A {
+ |_| ()
+}
+
+fn main() {}
diff --git a/src/test/rustdoc/primitive-reference.rs b/src/test/rustdoc/primitive-reference.rs
index 5c1193406..ea8d2d166 100644
--- a/src/test/rustdoc/primitive-reference.rs
+++ b/src/test/rustdoc/primitive-reference.rs
@@ -9,12 +9,12 @@
// @has - '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
// @has foo/primitive.reference.html
// @has - '//a[@class="primitive"]' 'reference'
-// @has - '//span[@class="in-band"]' 'Primitive Type reference'
+// @has - '//h1[@class="fqn"]' 'Primitive Type reference'
// @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
-// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header in-band"]' \
+// @has - '//*[@id="impl-Foo%3C%26A%3E-for-%26B"]/*[@class="code-header"]' \
// 'impl<A, B> Foo<&A> for &B'
#[doc(primitive = "reference")]
/// this is a test!
diff --git a/src/test/rustdoc/primitive-slice-auto-trait.rs b/src/test/rustdoc/primitive-slice-auto-trait.rs
index 7f8f74ff4..cdddd6b65 100644
--- a/src/test/rustdoc/primitive-slice-auto-trait.rs
+++ b/src/test/rustdoc/primitive-slice-auto-trait.rs
@@ -4,7 +4,7 @@
#![feature(rustdoc_internals)]
// @has foo/primitive.slice.html '//a[@class="primitive"]' 'slice'
-// @has - '//span[@class="in-band"]' 'Primitive Type slice'
+// @has - '//h1[@class="fqn"]' 'Primitive Type slice'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl<T> Send for [T]where T: Send'
diff --git a/src/test/rustdoc/primitive-tuple-auto-trait.rs b/src/test/rustdoc/primitive-tuple-auto-trait.rs
index a2fbbf078..df681457f 100644
--- a/src/test/rustdoc/primitive-tuple-auto-trait.rs
+++ b/src/test/rustdoc/primitive-tuple-auto-trait.rs
@@ -4,7 +4,7 @@
#![feature(rustdoc_internals)]
// @has foo/primitive.tuple.html '//a[@class="primitive"]' 'tuple'
-// @has - '//span[@class="in-band"]' 'Primitive Type tuple'
+// @has - '//h1[@class="fqn"]' 'Primitive Type tuple'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'Send'
diff --git a/src/test/rustdoc/primitive-unit-auto-trait.rs b/src/test/rustdoc/primitive-unit-auto-trait.rs
index 76182622e..391e33bea 100644
--- a/src/test/rustdoc/primitive-unit-auto-trait.rs
+++ b/src/test/rustdoc/primitive-unit-auto-trait.rs
@@ -4,7 +4,7 @@
#![feature(rustdoc_internals)]
// @has foo/primitive.unit.html '//a[@class="primitive"]' 'unit'
-// @has - '//span[@class="in-band"]' 'Primitive Type unit'
+// @has - '//h1[@class="fqn"]' 'Primitive Type unit'
// @has - '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has - '//h2[@id="synthetic-implementations"]' 'Auto Trait Implementations'
// @has - '//div[@id="synthetic-implementations-list"]//h3' 'impl Send for ()'
diff --git a/src/test/rustdoc/primitive.rs b/src/test/rustdoc/primitive.rs
index 605ca4d17..6347fdac3 100644
--- a/src/test/rustdoc/primitive.rs
+++ b/src/test/rustdoc/primitive.rs
@@ -7,7 +7,7 @@
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a' 'Primitive Types'
// @has foo/index.html '//div[@class="sidebar-elems"]//li/a/@href' '#primitives'
// @has foo/primitive.i32.html '//a[@class="primitive"]' 'i32'
-// @has foo/primitive.i32.html '//span[@class="in-band"]' 'Primitive Type i32'
+// @has foo/primitive.i32.html '//h1[@class="fqn"]' 'Primitive Type i32'
// @has foo/primitive.i32.html '//section[@id="main-content"]//div[@class="docblock"]//p' 'this is a test!'
// @has foo/index.html '//a/@href' '../foo/index.html'
// @!has foo/index.html '//span' '🔒'
diff --git a/src/test/rustdoc/primitive/primitive-generic-impl.rs b/src/test/rustdoc/primitive/primitive-generic-impl.rs
index eebb2cf5a..7b336b398 100644
--- a/src/test/rustdoc/primitive/primitive-generic-impl.rs
+++ b/src/test/rustdoc/primitive/primitive-generic-impl.rs
@@ -1,7 +1,7 @@
#![feature(rustdoc_internals)]
#![crate_name = "foo"]
-// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header in-band"]' 'impl<T> ToString for T'
+// @has foo/primitive.i32.html '//*[@id="impl-ToString-for-i32"]//h3[@class="code-header"]' 'impl<T> ToString for T'
#[doc(primitive = "i32")]
/// Some useless docs, wouhou!
diff --git a/src/test/rustdoc/recursive-deref.rs b/src/test/rustdoc/recursive-deref.rs
index 2ab9d44be..aa38485c4 100644
--- a/src/test/rustdoc/recursive-deref.rs
+++ b/src/test/rustdoc/recursive-deref.rs
@@ -9,7 +9,7 @@ impl C {
pub fn c(&self) {}
}
-// @has recursive_deref/struct.A.html '//h3[@class="code-header in-band"]' 'impl Deref for A'
+// @has recursive_deref/struct.A.html '//h3[@class="code-header"]' 'impl Deref for A'
// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
impl Deref for A {
type Target = B;
@@ -19,7 +19,7 @@ impl Deref for A {
}
}
-// @has recursive_deref/struct.B.html '//h3[@class="code-header in-band"]' 'impl Deref for B'
+// @has recursive_deref/struct.B.html '//h3[@class="code-header"]' 'impl Deref for B'
// @has '-' '//*[@class="impl-items"]//*[@id="method.c"]' 'pub fn c(&self)'
impl Deref for B {
type Target = C;
@@ -29,7 +29,7 @@ impl Deref for B {
}
}
-// @has recursive_deref/struct.C.html '//h3[@class="code-header in-band"]' 'impl Deref for C'
+// @has recursive_deref/struct.C.html '//h3[@class="code-header"]' 'impl Deref for C'
impl Deref for C {
type Target = B;
@@ -49,7 +49,7 @@ impl G {
pub fn g() {}
}
-// @has recursive_deref/struct.D.html '//h3[@class="code-header in-band"]' 'impl Deref for D'
+// @has recursive_deref/struct.D.html '//h3[@class="code-header"]' 'impl Deref for D'
// We also check that `G::g` method isn't rendered because there is no `self` argument.
// @!has '-' '//*[@id="deref-methods-G"]' ''
impl Deref for D {
@@ -60,7 +60,7 @@ impl Deref for D {
}
}
-// @has recursive_deref/struct.E.html '//h3[@class="code-header in-band"]' 'impl Deref for E'
+// @has recursive_deref/struct.E.html '//h3[@class="code-header"]' 'impl Deref for E'
// We also check that `G::g` method isn't rendered because there is no `self` argument.
// @!has '-' '//*[@id="deref-methods-G"]' ''
impl Deref for E {
@@ -71,7 +71,7 @@ impl Deref for E {
}
}
-// @has recursive_deref/struct.F.html '//h3[@class="code-header in-band"]' 'impl Deref for F'
+// @has recursive_deref/struct.F.html '//h3[@class="code-header"]' 'impl Deref for F'
// We also check that `G::g` method isn't rendered because there is no `self` argument.
// @!has '-' '//*[@id="deref-methods-G"]' ''
impl Deref for F {
@@ -82,7 +82,7 @@ impl Deref for F {
}
}
-// @has recursive_deref/struct.G.html '//h3[@class="code-header in-band"]' 'impl Deref for G'
+// @has recursive_deref/struct.G.html '//h3[@class="code-header"]' 'impl Deref for G'
impl Deref for G {
type Target = E;
@@ -100,7 +100,7 @@ impl I {
pub fn i() {}
}
-// @has recursive_deref/struct.H.html '//h3[@class="code-header in-band"]' 'impl Deref for H'
+// @has recursive_deref/struct.H.html '//h3[@class="code-header"]' 'impl Deref for H'
// @!has '-' '//*[@id="deref-methods-I"]' ''
impl Deref for H {
type Target = I;
@@ -110,7 +110,7 @@ impl Deref for H {
}
}
-// @has recursive_deref/struct.I.html '//h3[@class="code-header in-band"]' 'impl Deref for I'
+// @has recursive_deref/struct.I.html '//h3[@class="code-header"]' 'impl Deref for I'
impl Deref for I {
type Target = H;
diff --git a/src/test/rustdoc/reexport-dep-foreign-fn.rs b/src/test/rustdoc/reexport-dep-foreign-fn.rs
index 6e1dc4539..6694c91d1 100644
--- a/src/test/rustdoc/reexport-dep-foreign-fn.rs
+++ b/src/test/rustdoc/reexport-dep-foreign-fn.rs
@@ -8,5 +8,5 @@
extern crate all_item_types;
// @has 'foo/fn.foo_ffn.html'
-// @has - '//*[@class="docblock item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
+// @has - '//*[@class="item-decl"]//code' 'pub unsafe extern "C" fn foo_ffn()'
pub use all_item_types::foo_ffn;
diff --git a/src/test/rustdoc/reexport-doc.rs b/src/test/rustdoc/reexport-doc.rs
new file mode 100644
index 000000000..df2c889b4
--- /dev/null
+++ b/src/test/rustdoc/reexport-doc.rs
@@ -0,0 +1,8 @@
+// aux-build:reexport-doc-aux.rs
+
+extern crate reexport_doc_aux as dep;
+
+// @has 'reexport_doc/struct.Foo.html'
+// @count - '//p' 'These are the docs for Foo.' 1
+/// These are the docs for Foo.
+pub use dep::Foo;
diff --git a/src/test/rustdoc/reexports-priv.rs b/src/test/rustdoc/reexports-priv.rs
index aea9b9f2b..11364e7f7 100644
--- a/src/test/rustdoc/reexports-priv.rs
+++ b/src/test/rustdoc/reexports-priv.rs
@@ -5,7 +5,7 @@
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="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="docblock item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="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="docblock item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -50,7 +50,7 @@ pub(self) use reexports::TypeSelf;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
@@ -61,33 +61,33 @@ use reexports::UnionLocal;
pub mod outer {
pub mod inner {
- // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="item-decl"]' 'pub macro addr_of($place:expr) {'
pub use reexports::addr_of;
- // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="docblock item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_crate.html' '//*[@class="item-decl"]' 'pub(crate) macro addr_of_crate($place:expr) {'
pub(crate) use reexports::addr_of_crate;
- // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="docblock item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of_super.html' '//*[@class="item-decl"]' 'pub(in outer) macro addr_of_super($place:expr) {'
pub(super) use reexports::addr_of_super;
// @!has 'foo/outer/inner/macro.addr_of_self.html'
pub(self) use reexports::addr_of_self;
// @!has 'foo/outer/inner/macro.addr_of_local.html'
use reexports::addr_of_local;
- // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="docblock item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="item-decl"]' 'pub struct Foo;'
pub use reexports::Foo;
- // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) struct FooCrate;'
+ // @has 'foo/outer/inner/struct.FooCrate.html' '//*[@class="item-decl"]' 'pub(crate) struct FooCrate;'
pub(crate) use reexports::FooCrate;
- // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) struct FooSuper;'
+ // @has 'foo/outer/inner/struct.FooSuper.html' '//*[@class="item-decl"]' 'pub(in outer) struct FooSuper;'
pub(super) use reexports::FooSuper;
// @!has 'foo/outer/inner/struct.FooSelf.html'
pub(self) use reexports::FooSelf;
// @!has 'foo/outer/inner/struct.FooLocal.html'
use reexports::FooLocal;
- // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="docblock item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
- // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) enum BarCrate {'
+ // @has 'foo/outer/inner/enum.BarCrate.html' '//*[@class="item-decl"]' 'pub(crate) enum BarCrate {'
pub(crate) use reexports::BarCrate;
- // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) enum BarSuper {'
+ // @has 'foo/outer/inner/enum.BarSuper.html' '//*[@class="item-decl"]' 'pub(in outer) enum BarSuper {'
pub(super) use reexports::BarSuper;
// @!has 'foo/outer/inner/enum.BarSelf.html'
pub(self) use reexports::BarSelf;
@@ -116,11 +116,11 @@ pub mod outer {
// @!has 'foo/outer/inner/type.TypeLocal.html'
use reexports::TypeLocal;
- // @has 'foo/outer/inner/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
pub use reexports::Union;
- // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="docblock item-decl"]' 'pub(crate) union UnionCrate {'
+ // @has 'foo/outer/inner/union.UnionCrate.html' '//*[@class="item-decl"]' 'pub(crate) union UnionCrate {'
pub(crate) use reexports::UnionCrate;
- // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="docblock item-decl"]' 'pub(in outer) union UnionSuper {'
+ // @has 'foo/outer/inner/union.UnionSuper.html' '//*[@class="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/src/test/rustdoc/reexports.rs b/src/test/rustdoc/reexports.rs
index 7abcbfb61..9aa6d7224 100644
--- a/src/test/rustdoc/reexports.rs
+++ b/src/test/rustdoc/reexports.rs
@@ -4,7 +4,7 @@
extern crate reexports;
-// @has 'foo/macro.addr_of.html' '//*[@class="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
+// @has 'foo/macro.addr_of.html' '//*[@class="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="docblock item-decl"]' 'pub struct Foo;'
+// @has 'foo/struct.Foo.html' '//*[@class="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="docblock item-decl"]' 'pub enum Bar {'
+// @has 'foo/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -49,7 +49,7 @@ pub(self) use reexports::TypeSelf;
// @!has 'foo/type.TypeLocal.html'
use reexports::TypeLocal;
-// @has 'foo/union.Union.html' '//*[@class="docblock item-decl"]' 'pub union Union {'
+// @has 'foo/union.Union.html' '//*[@class="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="docblock item-decl"]' 'pub macro addr_of($place:expr) {'
+ // @has 'foo/outer/inner/macro.addr_of.html' '//*[@class="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="docblock item-decl"]' 'pub struct Foo;'
+ // @has 'foo/outer/inner/struct.Foo.html' '//*[@class="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="docblock item-decl"]' 'pub enum Bar {'
+ // @has 'foo/outer/inner/enum.Bar.html' '//*[@class="item-decl"]' 'pub enum Bar {'
pub use reexports::Bar;
// @!has 'foo/outer/inner/enum.BarCrate.html'
pub(crate) use reexports::BarCrate;
@@ -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="docblock item-decl"]' 'pub union Union {'
+ // @has 'foo/outer/inner/union.Union.html' '//*[@class="item-decl"]' 'pub union Union {'
pub use reexports::Union;
// @!has 'foo/outer/inner/union.UnionCrate.html'
pub(crate) use reexports::UnionCrate;
diff --git a/src/test/rustdoc/rfc-2632-const-trait-impl.rs b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
index f3e211e30..602ee1b1b 100644
--- a/src/test/rustdoc/rfc-2632-const-trait-impl.rs
+++ b/src/test/rustdoc/rfc-2632-const-trait-impl.rs
@@ -18,10 +18,10 @@ pub struct S<T>(T);
// @has - '//pre[@class="rust trait"]/code/span[@class="where"]' ': Clone'
#[const_trait]
pub trait Tr<T> {
- // @!has - '//div[@id="method.a"]/h4[@class="code-header"]' '~const'
- // @has - '//div[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
- // @!has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
- // @has - '//div[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
+ // @!has - '//section[@id="method.a"]/h4[@class="code-header"]' '~const'
+ // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Clone'
+ // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
+ // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
fn a<A: ~const Clone + ~const Destruct>()
where
Option<A>: ~const Clone + ~const Destruct,
@@ -30,10 +30,10 @@ pub trait Tr<T> {
}
// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]' ''
-// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]' '~const'
-// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/a[@class="trait"]' 'Clone'
-// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where"]' '~const'
-// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header in-band"]/span[@class="where fmt-newline"]' ': Clone'
+// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]' '~const'
+// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Clone'
+// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const'
+// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Clone'
impl<T: ~const Clone + ~const Destruct> const Tr<T> for T
where
Option<T>: ~const Clone + ~const Destruct,
diff --git a/src/test/rustdoc/safe-intrinsic.rs b/src/test/rustdoc/safe-intrinsic.rs
index d3bb8514b..d08abdaeb 100644
--- a/src/test/rustdoc/safe-intrinsic.rs
+++ b/src/test/rustdoc/safe-intrinsic.rs
@@ -1,5 +1,6 @@
#![feature(intrinsics)]
#![feature(no_core)]
+#![feature(rustc_attrs)]
#![no_core]
#![crate_name = "foo"]
@@ -7,6 +8,7 @@
extern "rust-intrinsic" {
// @has 'foo/fn.abort.html'
// @has - '//pre[@class="rust fn"]' 'pub extern "rust-intrinsic" fn abort() -> !'
+ #[rustc_safe_intrinsic]
pub fn abort() -> !;
// @has 'foo/fn.unreachable.html'
// @has - '//pre[@class="rust fn"]' 'pub unsafe extern "rust-intrinsic" fn unreachable() -> !'
diff --git a/src/test/rustdoc/sidebar-all-page.rs b/src/test/rustdoc/sidebar-all-page.rs
new file mode 100644
index 000000000..e74b981de
--- /dev/null
+++ b/src/test/rustdoc/sidebar-all-page.rs
@@ -0,0 +1,35 @@
+#![crate_name = "foo"]
+
+#![feature(rustdoc_internals)]
+
+// @has 'foo/all.html'
+// @has - '//*[@class="sidebar-elems"]//li' 'Structs'
+// @has - '//*[@class="sidebar-elems"]//li' 'Enums'
+// @has - '//*[@class="sidebar-elems"]//li' 'Unions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Functions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Traits'
+// @has - '//*[@class="sidebar-elems"]//li' 'Macros'
+// @has - '//*[@class="sidebar-elems"]//li' 'Type Definitions'
+// @has - '//*[@class="sidebar-elems"]//li' 'Constants'
+// @has - '//*[@class="sidebar-elems"]//li' 'Statics'
+// @has - '//*[@class="sidebar-elems"]//li' 'Primitive Types'
+
+pub struct Foo;
+pub enum Enum {
+ A,
+}
+pub union Bar {
+ a: u8,
+ b: u16,
+}
+pub fn foo() {}
+pub trait Trait {}
+#[macro_export]
+macro_rules! foo {
+ () => {}
+}
+pub type Type = u8;
+pub const FOO: u8 = 0;
+pub static BAR: u8 = 0;
+#[doc(primitive = "u8")]
+mod u8 {}
diff --git a/src/test/rustdoc/sidebar-items.rs b/src/test/rustdoc/sidebar-items.rs
index b5b681ab0..6f7afa59b 100644
--- a/src/test/rustdoc/sidebar-items.rs
+++ b/src/test/rustdoc/sidebar-items.rs
@@ -2,17 +2,17 @@
#![crate_name = "foo"]
// @has foo/trait.Foo.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#required-methods"]' 'Required Methods'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-methods"]' 'Required Methods'
// @has - '//*[@class="sidebar-elems"]//section//a' 'bar'
-// @has - '//*[@class="sidebar-title"]/a[@href="#provided-methods"]' 'Provided Methods'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-methods"]' 'Provided Methods'
// @has - '//*[@class="sidebar-elems"]//section//a' 'foo'
-// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-consts"]' 'Required Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-consts"]' 'Required Associated Constants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'FOO'
-// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-consts"]' 'Provided Associated Constants'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-consts"]' 'Provided Associated Constants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'BAR'
-// @has - '//*[@class="sidebar-title"]/a[@href="#required-associated-types"]' 'Required Associated Types'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#required-associated-types"]' 'Required Associated Types'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Output'
-// @has - '//*[@class="sidebar-title"]/a[@href="#provided-associated-types"]' 'Provided Associated Types'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#provided-associated-types"]' 'Provided Associated Types'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Extra'
pub trait Foo {
const FOO: usize;
@@ -25,7 +25,7 @@ pub trait Foo {
}
// @has foo/struct.Bar.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f"]' 'f'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.u"]' 'u'
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
@@ -36,7 +36,7 @@ pub struct Bar {
}
// @has foo/enum.En.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#variants"]' 'Variants'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#variants"]' 'Variants'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Foo'
// @has - '//*[@class="sidebar-elems"]//section//a' 'Bar'
pub enum En {
@@ -45,7 +45,7 @@ pub enum En {
}
// @has foo/union.MyUnion.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#fields"]' 'Fields'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Fields'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f1"]' 'f1'
// @has - '//*[@class="sidebar-elems"]//section//a[@href="#structfield.f2"]' 'f2'
// @!has - '//*[@class="sidebar-elems"]//section//a' 'waza'
diff --git a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
index 155150396..11e946948 100644
--- a/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
+++ b/src/test/rustdoc/sidebar-links-to-foreign-impl.rs
@@ -3,12 +3,12 @@
#![crate_name = "foo"]
// @has foo/trait.Foo.html
-// @has - '//*[@class="sidebar-title"]/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#foreign-impls"]' 'Implementations on Foreign Types'
// @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 in-band"]' 'impl Foo for 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 in-band"]' "impl<'a> Foo for &'a str"
+// @has - '//*[@id="impl-Foo-for-%26%27a%20str"]//h3[@class="code-header"]' "impl<'a> Foo for &'a str"
pub trait Foo {}
impl Foo for u32 {}
diff --git a/src/test/rustdoc/sized_trait.rs b/src/test/rustdoc/sized_trait.rs
index 36718ebe1..feef4de8d 100644
--- a/src/test/rustdoc/sized_trait.rs
+++ b/src/test/rustdoc/sized_trait.rs
@@ -11,7 +11,7 @@ pub struct Bar {
pub struct Foo<T: ?Sized>(T);
// @has foo/struct.Unsized.html
-// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header in-band"]' 'impl !Sized for Unsized'
+// @has - '//*[@id="impl-Sized-for-Unsized"]//h3[@class="code-header"]' 'impl !Sized for Unsized'
pub struct Unsized {
data: [u8],
}
diff --git a/src/test/rustdoc/src-links-auto-impls.rs b/src/test/rustdoc/src-links-auto-impls.rs
index 313a4b118..953563833 100644
--- a/src/test/rustdoc/src-links-auto-impls.rs
+++ b/src/test/rustdoc/src-links-auto-impls.rs
@@ -1,11 +1,11 @@
#![crate_name = "foo"]
// @has foo/struct.Unsized.html
-// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header in-band"]' 'impl !Sized for Unsized'
+// @has - '//*[@id="impl-Sized-for-Unsized"]/h3[@class="code-header"]' 'impl !Sized for Unsized'
// @!has - '//*[@id="impl-Sized-for-Unsized"]//a[@class="srclink"]' 'source'
-// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header in-band"]' 'impl Sync for Unsized'
+// @has - '//*[@id="impl-Sync-for-Unsized"]/h3[@class="code-header"]' 'impl Sync for Unsized'
// @!has - '//*[@id="impl-Sync-for-Unsized"]//a[@class="srclink"]' 'source'
-// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header in-band"]' 'impl<T> Any for T'
+// @has - '//*[@id="impl-Any-for-Unsized"]/h3[@class="code-header"]' 'impl<T> Any for T'
// @has - '//*[@id="impl-Any-for-Unsized"]//a[@class="srclink rightside"]' 'source'
pub struct Unsized {
data: [u8],
diff --git a/src/test/rustdoc/strip-enum-variant.no-not-shown.html b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
index c4ee1a991..782198956 100644
--- a/src/test/rustdoc/strip-enum-variant.no-not-shown.html
+++ b/src/test/rustdoc/strip-enum-variant.no-not-shown.html
@@ -1 +1 @@
-<ul><li><a href="#variant.Shown">Shown</a></li></ul> \ No newline at end of file
+<ul class="block"><li><a href="#variant.Shown">Shown</a></li></ul> \ No newline at end of file
diff --git a/src/test/rustdoc/strip-enum-variant.rs b/src/test/rustdoc/strip-enum-variant.rs
index f82ffdfed..8753a7dc6 100644
--- a/src/test/rustdoc/strip-enum-variant.rs
+++ b/src/test/rustdoc/strip-enum-variant.rs
@@ -3,7 +3,7 @@
// @!has - '//code' 'NotShown'
// @has - '//code' '// some variants omitted'
// Also check that `NotShown` isn't displayed in the sidebar.
-// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]/ul'
+// @snapshot no-not-shown - '//*[@class="sidebar-elems"]/section/*[@class="block"][1]'
pub enum MyThing {
Shown,
#[doc(hidden)]
diff --git a/src/test/rustdoc/synthetic_auto/basic.rs b/src/test/rustdoc/synthetic_auto/basic.rs
index 19138fd1a..7c6a38865 100644
--- a/src/test/rustdoc/synthetic_auto/basic.rs
+++ b/src/test/rustdoc/synthetic_auto/basic.rs
@@ -1,6 +1,6 @@
// @has basic/struct.Foo.html
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Send for Foo<T>where T: Send'
-// @has - '//h3[@class="code-header in-band"]' 'impl<T> Sync for Foo<T>where T: Sync'
+// @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
pub struct Foo<T> {
diff --git a/src/test/rustdoc/synthetic_auto/complex.rs b/src/test/rustdoc/synthetic_auto/complex.rs
index 39f78983d..43393c21f 100644
--- a/src/test/rustdoc/synthetic_auto/complex.rs
+++ b/src/test/rustdoc/synthetic_auto/complex.rs
@@ -20,7 +20,7 @@ mod foo {
}
// @has complex/struct.NotOuter.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/synthetic_auto/crate-local.rs b/src/test/rustdoc/synthetic_auto/crate-local.rs
index 58b787dfa..ed01f63f9 100644
--- a/src/test/rustdoc/synthetic_auto/crate-local.rs
+++ b/src/test/rustdoc/synthetic_auto/crate-local.rs
@@ -3,7 +3,7 @@
pub auto trait Banana {}
// @has crate_local/struct.Peach.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Banana for Peach'
-// @has - '//h3[@class="code-header in-band"]' 'impl Send for Peach'
-// @has - '//h3[@class="code-header in-band"]' 'impl Sync for Peach'
+// @has - '//h3[@class="code-header"]' 'impl Banana for Peach'
+// @has - '//h3[@class="code-header"]' 'impl Send for Peach'
+// @has - '//h3[@class="code-header"]' 'impl Sync for Peach'
pub struct Peach;
diff --git a/src/test/rustdoc/synthetic_auto/lifetimes.rs b/src/test/rustdoc/synthetic_auto/lifetimes.rs
index 0c94850e7..33170a844 100644
--- a/src/test/rustdoc/synthetic_auto/lifetimes.rs
+++ b/src/test/rustdoc/synthetic_auto/lifetimes.rs
@@ -9,10 +9,10 @@ where
{}
// @has lifetimes/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/synthetic_auto/manual.rs b/src/test/rustdoc/synthetic_auto/manual.rs
index 35047e3e8..77c04ad2a 100644
--- a/src/test/rustdoc/synthetic_auto/manual.rs
+++ b/src/test/rustdoc/synthetic_auto/manual.rs
@@ -1,8 +1,8 @@
// @has manual/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// 'impl<T> Send for Foo<T>'
//
// @count - '//*[@id="trait-implementations-list"]//*[@class="impl has-srclink"]' 1
diff --git a/src/test/rustdoc/synthetic_auto/negative.rs b/src/test/rustdoc/synthetic_auto/negative.rs
index 66e749ac3..2c2c848a5 100644
--- a/src/test/rustdoc/synthetic_auto/negative.rs
+++ b/src/test/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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Send for Outer<T>"
//
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// "impl<T> !Sync for Outer<T>"
pub struct Outer<T: Copy> {
inner_field: Inner<T>,
diff --git a/src/test/rustdoc/synthetic_auto/nested.rs b/src/test/rustdoc/synthetic_auto/nested.rs
index 09587bcc3..423bf115a 100644
--- a/src/test/rustdoc/synthetic_auto/nested.rs
+++ b/src/test/rustdoc/synthetic_auto/nested.rs
@@ -9,10 +9,10 @@ where
}
// @has nested/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header"]' \
// 'impl<T> Sync for Foo<T>where T: Sync'
pub struct Foo<T> {
inner_field: Inner<T>,
diff --git a/src/test/rustdoc/synthetic_auto/no-redundancy.rs b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
index 41375decc..59f336233 100644
--- a/src/test/rustdoc/synthetic_auto/no-redundancy.rs
+++ b/src/test/rustdoc/synthetic_auto/no-redundancy.rs
@@ -9,7 +9,7 @@ where
}
// @has no_redundancy/struct.Outer.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/synthetic_auto/overflow.rs b/src/test/rustdoc/synthetic_auto/overflow.rs
index c132ab6fb..35a487c76 100644
--- a/src/test/rustdoc/synthetic_auto/overflow.rs
+++ b/src/test/rustdoc/synthetic_auto/overflow.rs
@@ -21,7 +21,7 @@ enum TyData<I: Interner> {
struct VariableKind<I: Interner>(I::InternedType);
// @has overflow/struct.BoundVarsCollector.html
-// @has - '//h3[@class="code-header in-band"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
+// @has - '//h3[@class="code-header"]' "impl<'tcx> Send for BoundVarsCollector<'tcx>"
pub struct BoundVarsCollector<'tcx> {
val: VariableKind<RustInterner<'tcx>>
}
diff --git a/src/test/rustdoc/synthetic_auto/project.rs b/src/test/rustdoc/synthetic_auto/project.rs
index e80b1b1dc..558ff2add 100644
--- a/src/test/rustdoc/synthetic_auto/project.rs
+++ b/src/test/rustdoc/synthetic_auto/project.rs
@@ -23,10 +23,10 @@ where
}
// @has project/struct.Foo.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/synthetic_auto/self-referential.rs b/src/test/rustdoc/synthetic_auto/self-referential.rs
index d15a8de7d..c6ae96de7 100644
--- a/src/test/rustdoc/synthetic_auto/self-referential.rs
+++ b/src/test/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 in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/synthetic_auto/static-region.rs b/src/test/rustdoc/synthetic_auto/static-region.rs
index 08e956731..1a76cb919 100644
--- a/src/test/rustdoc/synthetic_auto/static-region.rs
+++ b/src/test/rustdoc/synthetic_auto/static-region.rs
@@ -3,7 +3,7 @@ pub trait OwnedTrait<'a> {
}
// @has static_region/struct.Owned.html
-// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has - '//*[@id="synthetic-implementations-list"]//*[@class="impl has-srclink"]//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/src/test/rustdoc/toggle-item-contents.rs b/src/test/rustdoc/toggle-item-contents.rs
index dbaf195e1..47a1d62f5 100644
--- a/src/test/rustdoc/toggle-item-contents.rs
+++ b/src/test/rustdoc/toggle-item-contents.rs
@@ -55,7 +55,7 @@ pub union Union {
// @has 'toggle_item_contents/struct.PrivStruct.html'
// @count - '//details[@class="rustdoc-toggle type-contents-toggle"]' 0
-// @has - '//div[@class="docblock item-decl"]' '/* private fields */'
+// @has - '//div[@class="item-decl"]' '/* private fields */'
pub struct PrivStruct {
a: usize,
b: usize,
diff --git a/src/test/rustdoc/toggle-trait-fn.rs b/src/test/rustdoc/toggle-trait-fn.rs
index 65e8daeb0..e41422ce7 100644
--- a/src/test/rustdoc/toggle-trait-fn.rs
+++ b/src/test/rustdoc/toggle-trait-fn.rs
@@ -4,12 +4,12 @@
// summary. Trait methods with no documentation should not be wrapped.
//
// @has foo/trait.Foo.html
-// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
-// @has - '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented is documented'
-// @has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
-// @!has - '//details[@class="rustdoc-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
-// @has - '//details[@class="rustdoc-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
+// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented()'
+// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented()'
+// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented is documented'
+// @has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'is_documented_optional()'
+// @!has - '//details[@class="rustdoc-toggle method-toggle"]//summary//h4[@class="code-header"]' 'not_documented_optional()'
+// @has - '//details[@class="rustdoc-toggle method-toggle"]//*[@class="docblock"]' 'is_documented_optional is documented'
pub trait Foo {
fn not_documented();
diff --git a/src/test/rustdoc/trait_alias.rs b/src/test/rustdoc/trait_alias.rs
index a0c657d9a..791c099cc 100644
--- a/src/test/rustdoc/trait_alias.rs
+++ b/src/test/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="docblock item-decl"]/pre' 'trait CopyAlias = Copy;'
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait CopyAlias = Copy;'
pub trait CopyAlias = Copy;
// @has foo/traitalias.Alias2.html
-// @has - '//section[@id="main-content"]/div[@class="docblock item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Alias2 = Copy + Debug;'
pub trait Alias2 = Copy + Debug;
// @has foo/traitalias.Foo.html
-// @has - '//section[@id="main-content"]/div[@class="docblock item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
+// @has - '//section[@id="main-content"]/div[@class="item-decl"]/pre' 'trait Foo<T> = Into<T> + Debug;'
pub trait Foo<T> = Into<T> + Debug;
// @has foo/fn.bar.html '//a[@href="traitalias.Alias2.html"]' 'Alias2'
pub fn bar<T>() where T: Alias2 {}
diff --git a/src/test/rustdoc/traits-in-bodies.rs b/src/test/rustdoc/traits-in-bodies.rs
index 6d450a625..a65dd7a54 100644
--- a/src/test/rustdoc/traits-in-bodies.rs
+++ b/src/test/rustdoc/traits-in-bodies.rs
@@ -4,7 +4,7 @@
pub struct Bounded<T: Clone>(T);
// @has traits_in_bodies/struct.SomeStruct.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Clone for SomeStruct'
+// @has - '//h3[@class="code-header"]' 'impl Clone for SomeStruct'
pub struct SomeStruct;
fn asdf() -> Bounded<SomeStruct> {
@@ -18,7 +18,7 @@ fn asdf() -> Bounded<SomeStruct> {
}
// @has traits_in_bodies/struct.Point.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Copy for Point'
+// @has - '//h3[@class="code-header"]' 'impl Copy for Point'
#[derive(Clone)]
pub struct Point {
x: i32,
@@ -31,7 +31,7 @@ const _FOO: () = {
};
// @has traits_in_bodies/struct.Inception.html
-// @has - '//h3[@class="code-header in-band"]' 'impl Clone for Inception'
+// @has - '//h3[@class="code-header"]' 'impl Clone for Inception'
pub struct Inception;
static _BAR: usize = {
diff --git a/src/test/rustdoc/tuple-struct-fields-doc.rs b/src/test/rustdoc/tuple-struct-fields-doc.rs
index 66bb40932..8ab1143d1 100644
--- a/src/test/rustdoc/tuple-struct-fields-doc.rs
+++ b/src/test/rustdoc/tuple-struct-fields-doc.rs
@@ -2,7 +2,7 @@
// @has foo/struct.Foo.html
// @has - '//h2[@id="fields"]' 'Tuple Fields'
-// @has - '//h3[@class="sidebar-title"]/a[@href="#fields"]' 'Tuple Fields'
+// @has - '//div[@class="sidebar-elems"]//h3/a[@href="#fields"]' 'Tuple Fields'
// @has - '//*[@id="structfield.0"]' '0: u32'
// @has - '//*[@id="main-content"]/div[@class="docblock"]' 'hello'
// @!has - '//*[@id="structfield.1"]' ''
diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs
index b68ec4557..d5dfa9484 100644
--- a/src/test/rustdoc/typedef.rs
+++ b/src/test/rustdoc/typedef.rs
@@ -9,8 +9,8 @@ impl MyStruct {
}
// @has typedef/type.MyAlias.html
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias'
-// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias'
+// @has - '//*[@class="impl has-srclink"]//h3[@class="code-header"]' 'impl MyAlias'
+// @has - '//*[@class="impl has-srclink"]//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/src/test/rustdoc/where.SWhere_Simd_item-decl.html b/src/test/rustdoc/where.SWhere_Simd_item-decl.html
index 0133bcaeb..6c1b5d315 100644
--- a/src/test/rustdoc/where.SWhere_Simd_item-decl.html
+++ b/src/test/rustdoc/where.SWhere_Simd_item-decl.html
@@ -1 +1 @@
-<div class="docblock item-decl"><pre class="rust struct"><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
+<div class="item-decl"><pre class="rust struct"><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
diff --git a/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html b/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html
index 542a3337b..24ab77703 100644
--- a/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html
+++ b/src/test/rustdoc/where.SWhere_TraitWhere_item-decl.html
@@ -1,4 +1,4 @@
-<div class="docblock item-decl"><pre class="rust trait"><code>pub trait TraitWhere {
+<div class="item-decl"><pre class="rust trait"><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>;
fn <a href="#method.func" class="fnname">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>,
diff --git a/src/test/rustdoc/where.rs b/src/test/rustdoc/where.rs
index 7a6c0db23..8b5bce28f 100644
--- a/src/test/rustdoc/where.rs
+++ b/src/test/rustdoc/where.rs
@@ -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 in-band"]' \
+// @has foo/struct.Delta.html '//*[@class="impl has-srclink"]//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="docblock item-decl"]'
+// @snapshot SWhere_Simd_item-decl - '//div[@class="item-decl"]'
pub struct Simd<T>([T; 1])
where
T: MyTrait;
// @has 'foo/trait.TraitWhere.html'
-// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="docblock item-decl"]'
+// @snapshot SWhere_TraitWhere_item-decl - '//div[@class="item-decl"]'
pub trait TraitWhere {
type Item<'a> where Self: 'a;
@@ -43,17 +43,17 @@ pub trait TraitWhere {
{ todo!() }
}
-// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' \
+// @has foo/struct.Echo.html '//*[@class="impl has-srclink"]//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 in-band"]' \
+// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//h3[@class="code-header"]' \
// "impl<E> MyTrait for Echo<E>where E: MyTrait"
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 in-band"]' \
+// @has foo/enum.Foxtrot.html '//*[@class="impl has-srclink"]//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 in-band"]' \
+// @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 {}
diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum.html b/src/test/rustdoc/whitespace-after-where-clause.enum.html
index 9e5bf45ae..c74866f4a 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.enum.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.enum.html
@@ -1,4 +1,4 @@
-<div class="docblock item-decl"><pre class="rust enum"><code>pub enum Cow&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,&#160;</span>{
+<div class="item-decl"><pre class="rust enum"><code>pub enum Cow&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,</span>{
Borrowed(<a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.enum2.html b/src/test/rustdoc/whitespace-after-where-clause.enum2.html
index 6bc47beae..ac7d77598 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.enum2.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.enum2.html
@@ -1,4 +1,4 @@
-<div class="docblock item-decl"><pre class="rust enum"><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; {
+<div class="item-decl"><pre class="rust enum"><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),
Whatever(<a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>),
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.rs b/src/test/rustdoc/whitespace-after-where-clause.rs
index c36386a2a..4b740b970 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.rs
+++ b/src/test/rustdoc/whitespace-after-where-clause.rs
@@ -4,7 +4,7 @@
#![crate_name = "foo"]
// @has 'foo/trait.ToOwned.html'
-// @snapshot trait - '//*[@class="docblock item-decl"]'
+// @snapshot trait - '//*[@class="item-decl"]'
pub trait ToOwned<T>
where T: Clone
{
@@ -14,7 +14,7 @@ where T: Clone
}
// @has 'foo/trait.ToOwned2.html'
-// @snapshot trait2 - '//*[@class="docblock item-decl"]'
+// @snapshot trait2 - '//*[@class="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="docblock item-decl"]'
+// @snapshot enum - '//*[@class="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="docblock item-decl"]'
+// @snapshot enum2 - '//*[@class="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="docblock item-decl"]'
+// @snapshot struct - '//*[@class="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="docblock item-decl"]'
+// @snapshot struct2 - '//*[@class="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="docblock item-decl"]'
+// @snapshot union - '//*[@class="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="docblock item-decl"]'
+// @snapshot union2 - '//*[@class="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/src/test/rustdoc/whitespace-after-where-clause.struct.html b/src/test/rustdoc/whitespace-after-where-clause.struct.html
index 236cc3b30..1ba1367d2 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.struct.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.struct.html
@@ -1,4 +1,4 @@
-<div class="docblock item-decl"><pre class="rust struct"><code>pub struct Struct&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,&#160;</span>{
+<div class="item-decl"><pre class="rust struct"><code>pub struct Struct&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,</span>{
pub a: <a class="primitive" href="{{channel}}/std/primitive.reference.html">&amp;'a </a>B,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.struct2.html b/src/test/rustdoc/whitespace-after-where-clause.struct2.html
index 47f5c6ba9..fb06b0f77 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.struct2.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.struct2.html
@@ -1,4 +1,4 @@
-<div class="docblock item-decl"><pre class="rust struct"><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; {
+<div class="item-decl"><pre class="rust struct"><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,
pub b: <a class="primitive" href="{{channel}}/std/primitive.u32.html">u32</a>,
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait.html b/src/test/rustdoc/whitespace-after-where-clause.trait.html
index 98f03b837..16b558237 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.trait.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.trait.html
@@ -1,6 +1,6 @@
-<div class="docblock item-decl"><pre class="rust trait"><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>,&#160;</span>{
+<div class="item-decl"><pre class="rust trait"><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>{
type <a href="#associatedtype.Owned" class="associatedtype">Owned</a>;
fn <a href="#tymethod.to_owned" class="fnname">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="fnname">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.trait2.html b/src/test/rustdoc/whitespace-after-where-clause.trait2.html
index 35052869e..eeca6e1f5 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.trait2.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.trait2.html
@@ -1,6 +1,6 @@
-<div class="docblock item-decl"><pre class="rust trait"><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; {
+<div class="item-decl"><pre class="rust trait"><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>;
fn <a href="#tymethod.to_owned" class="fnname">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="fnname">whatever</a>(&amp;self) -&gt; T;
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.union.html b/src/test/rustdoc/whitespace-after-where-clause.union.html
index 97e1bbcf3..0dfb6407d 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.union.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.union.html
@@ -1,3 +1,3 @@
-<div class="docblock item-decl"><pre class="rust union"><code>pub union Union&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,&#160;</span>{
+<div class="item-decl"><pre class="rust union"><code>pub union Union&lt;'a, B:&#160;?<a class="trait" href="{{channel}}/core/marker/trait.Sized.html" title="trait core::marker::Sized">Sized</a> + 'a&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;,</span>{
/* private fields */
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/rustdoc/whitespace-after-where-clause.union2.html b/src/test/rustdoc/whitespace-after-where-clause.union2.html
index 6c752a8b4..0d237df53 100644
--- a/src/test/rustdoc/whitespace-after-where-clause.union2.html
+++ b/src/test/rustdoc/whitespace-after-where-clause.union2.html
@@ -1,3 +1,3 @@
-<div class="docblock item-decl"><pre class="rust union"><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; {
+<div class="item-decl"><pre class="rust union"><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; {
/* private fields */
-}</code></pre></div>
+}</code></pre></div> \ No newline at end of file
diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
index 03ad3ca82..c05443488 100644
--- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -44,14 +44,16 @@ impl<'tcx> LateLintPass<'tcx> for MissingAllowedAttrPass {
) {
let item = match cx.tcx.hir().get(id) {
Node::Item(item) => item,
- _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id)),
+ _ => cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(id).def_id),
};
let allowed = |attr| pprust::attribute_to_string(attr).contains("allowed_attr");
if !cx.tcx.hir().attrs(item.hir_id()).iter().any(allowed) {
- cx.lint(MISSING_ALLOWED_ATTR, |lint| {
- lint.build("Missing 'allowed_attr' attribute").set_span(span).emit();
- });
+ cx.lint(
+ MISSING_ALLOWED_ATTR,
+ "Missing 'allowed_attr' attribute",
+ |lint| lint.set_span(span)
+ );
}
}
}
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 0b1534939..073da688c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -29,9 +29,11 @@ impl<'tcx> LateLintPass<'tcx> for Pass {
let attrs = cx.tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let span = cx.tcx.def_span(CRATE_DEF_ID);
if !cx.sess().contains_name(attrs, Symbol::intern("crate_okay")) {
- cx.lint(CRATE_NOT_OKAY, |lint| {
- lint.build("crate is not marked with #![crate_okay]").set_span(span).emit();
- });
+ cx.lint(
+ CRATE_NOT_OKAY,
+ "crate is not marked with #![crate_okay]",
+ |lint| lint.set_span(span)
+ );
}
}
}
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 2d41b5f30..4a41e7fbb 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -22,12 +22,10 @@ declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]);
impl<'tcx> LateLintPass<'tcx> for Pass {
fn check_item(&mut self, cx: &LateContext, it: &rustc_hir::Item) {
match it.ident.as_str() {
- "lintme" => cx.lint(TEST_LINT, |lint| {
- lint.build("item is named 'lintme'").set_span(it.span).emit();
- }),
- "pleaselintme" => cx.lint(PLEASE_LINT, |lint| {
- lint.build("item is named 'pleaselintme'").set_span(it.span).emit();
- }),
+ "lintme" => cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span)),
+ "pleaselintme" => {
+ cx.lint(PLEASE_LINT, "item is named 'pleaselintme'", |lint| lint.set_span(it.span))
+ }
_ => {}
}
}
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 285754928..30956deb7 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -21,9 +21,7 @@ declare_lint_pass!(Pass => [TEST_LINT]);
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.name.as_str() == "lintme" {
- cx.lint(TEST_LINT, |lint| {
- lint.build("item is named 'lintme'").set_span(it.span).emit();
- });
+ cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span));
}
}
}
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index 3d5dba42b..c2c024865 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -31,14 +31,10 @@ declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP, TEST_RUSTC_TOOL_LINT]);
impl EarlyLintPass for Pass {
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
if it.ident.name.as_str() == "lintme" {
- cx.lint(TEST_LINT, |lint| {
- lint.build("item is named 'lintme'").set_span(it.span).emit();
- });
+ cx.lint(TEST_LINT, "item is named 'lintme'", |lint| lint.set_span(it.span));
}
if it.ident.name.as_str() == "lintmetoo" {
- cx.lint(TEST_GROUP, |lint| {
- lint.build("item is named 'lintmetoo'").set_span(it.span).emit();
- });
+ cx.lint(TEST_GROUP, "item is named 'lintmetoo'", |lint| lint.set_span(it.span));
}
}
}
diff --git a/src/test/ui-fulldeps/fluent-messages/test.rs b/src/test/ui-fulldeps/fluent-messages/test.rs
index 256857e52..4e8147e2b 100644
--- a/src/test/ui-fulldeps/fluent-messages/test.rs
+++ b/src/test/ui-fulldeps/fluent-messages/test.rs
@@ -49,6 +49,7 @@ 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`
@@ -80,7 +81,7 @@ mod valid {
valid => "./valid.ftl",
}
- use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, valid::key};
+ use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, valid_key};
}
mod missing_crate_name {
@@ -93,5 +94,5 @@ mod missing_crate_name {
//~| ERROR name `with-hyphens` does not start with the crate name
}
- use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate::{foo, with_hyphens}};
+ use self::fluent_generated::{DEFAULT_LOCALE_RESOURCES, test_crate_foo, with_hyphens};
}
diff --git a/src/test/ui-fulldeps/fluent-messages/test.stderr b/src/test/ui-fulldeps/fluent-messages/test.stderr
index 26d87430a..d1cd4fe26 100644
--- a/src/test/ui-fulldeps/fluent-messages/test.stderr
+++ b/src/test/ui-fulldeps/fluent-messages/test.stderr
@@ -30,19 +30,31 @@ error: expected a message field for "missing_message"
|
error: overrides existing message: `a_b_key`
- --> $DIR/test.rs:53:16
+ --> $DIR/test.rs:54:16
|
LL | a_b => "./duplicate-a-b.ftl",
| ^^^^^^^^^^^^^^^^^^^^^
|
help: previously defined in this resource
- --> $DIR/test.rs:52:14
+ --> $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
+
error: name `slug_with_hyphens_this-slug-has-hyphens` contains a '-' character
- --> $DIR/test.rs:62:30
+ --> $DIR/test.rs:63:30
|
LL | slug_with_hyphens => "./slug-with-hyphens.ftl",
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -50,7 +62,7 @@ LL | slug_with_hyphens => "./slug-with-hyphens.ftl",
= help: replace any '-'s with '_'s
error: attribute `label-has-hyphens` contains a '-' character
- --> $DIR/test.rs:71:31
+ --> $DIR/test.rs:72:31
|
LL | label_with_hyphens => "./label-with-hyphens.ftl",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -58,7 +70,7 @@ LL | label_with_hyphens => "./label-with-hyphens.ftl",
= help: replace any '-'s with '_'s
error: name `with-hyphens` contains a '-' character
- --> $DIR/test.rs:90:23
+ --> $DIR/test.rs:91:23
|
LL | test_crate => "./missing-crate-name.ftl",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,7 +78,7 @@ LL | test_crate => "./missing-crate-name.ftl",
= help: replace any '-'s with '_'s
error: name `with-hyphens` does not start with the crate name
- --> $DIR/test.rs:90:23
+ --> $DIR/test.rs:91:23
|
LL | test_crate => "./missing-crate-name.ftl",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -74,12 +86,13 @@ LL | test_crate => "./missing-crate-name.ftl",
= help: prepend `test_crate_` to the slug name: `test_crate_with_hyphens`
error: name `test-crate_foo` contains a '-' character
- --> $DIR/test.rs:90:23
+ --> $DIR/test.rs:91:23
|
LL | test_crate => "./missing-crate-name.ftl",
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: replace any '-'s with '_'s
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors
+For more information about this error, try `rustc --explain E0428`.
diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
index 9d13ee89b..3cb13082f 100644
--- a/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
+++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
@@ -4,12 +4,12 @@ error: prefer `FxHashMap` over `HashMap`, it has better performance
LL | let _map: HashMap<String, String> = HashMap::default();
| ^^^^^^^
|
+ = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
note: the lint level is defined here
--> $DIR/default_hash_types.rs:4:9
|
LL | #![deny(rustc::default_hash_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
error: prefer `FxHashMap` over `HashMap`, it has better performance
--> $DIR/default_hash_types.rs:16:15
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
index e9e809fa4..643e81d99 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -12,66 +12,72 @@ extern crate rustc_session;
extern crate rustc_span;
use rustc_errors::{
- AddSubdiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Handler, fluent
+ AddToDiagnostic, IntoDiagnostic, Diagnostic, DiagnosticBuilder,
+ ErrorGuaranteed, Handler, fluent, SubdiagnosticMessage,
};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
-use rustc_session::SessionDiagnostic;
+use rustc_macros::{Diagnostic, Subdiagnostic};
use rustc_span::Span;
-#[derive(SessionDiagnostic)]
-#[diag(parser::expect_path)]
-struct DeriveSessionDiagnostic {
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct DeriveDiagnostic {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[note(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[note(compiletest_example)]
struct Note {
#[primary_span]
span: Span,
}
-pub struct UntranslatableInSessionDiagnostic;
+pub struct UntranslatableInIntoDiagnostic;
-impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for UntranslatableInSessionDiagnostic {
+impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for UntranslatableInIntoDiagnostic {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
handler.struct_err("untranslatable diagnostic")
//~^ ERROR diagnostics should be created using translatable messages
}
}
-pub struct TranslatableInSessionDiagnostic;
+pub struct TranslatableInIntoDiagnostic;
-impl<'a> SessionDiagnostic<'a, ErrorGuaranteed> for TranslatableInSessionDiagnostic {
+impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic {
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
- handler.struct_err(fluent::parser::expect_path)
+ handler.struct_err(fluent::compiletest_example)
}
}
-pub struct UntranslatableInAddSubdiagnostic;
+pub struct UntranslatableInAddToDiagnostic;
-impl AddSubdiagnostic for UntranslatableInAddSubdiagnostic {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
diag.note("untranslatable diagnostic");
//~^ ERROR diagnostics should be created using translatable messages
}
}
-pub struct TranslatableInAddSubdiagnostic;
+pub struct TranslatableInAddToDiagnostic;
-impl AddSubdiagnostic for TranslatableInAddSubdiagnostic {
- fn add_to_diagnostic(self, diag: &mut Diagnostic) {
- diag.note(fluent::typeck::note);
+impl AddToDiagnostic for TranslatableInAddToDiagnostic {
+ fn add_to_diagnostic_with<F>(self, diag: &mut Diagnostic, _: F)
+ where
+ F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
+ {
+ diag.note(fluent::note);
}
}
pub fn make_diagnostics<'a>(handler: &'a Handler) {
- let _diag = handler.struct_err(fluent::parser::expect_path);
- //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+ let _diag = handler.struct_err(fluent::compiletest_example);
+ //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
let _diag = handler.struct_err("untranslatable diagnostic");
- //~^ ERROR diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
+ //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
//~^^ ERROR diagnostics should be created using translatable messages
}
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
index e5c5bc2e9..510d6a171 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -11,15 +11,15 @@ LL | #![deny(rustc::untranslatable_diagnostic)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:56:14
+ --> $DIR/diagnostics.rs:59:14
|
LL | diag.note("untranslatable diagnostic");
| ^^^^
-error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
- --> $DIR/diagnostics.rs:70:25
+error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+ --> $DIR/diagnostics.rs:76:25
|
-LL | let _diag = handler.struct_err(fluent::parser::expect_path);
+LL | let _diag = handler.struct_err(fluent::compiletest_example);
| ^^^^^^^^^^
|
note: the lint level is defined here
@@ -28,14 +28,14 @@ note: the lint level is defined here
LL | #![deny(rustc::diagnostic_outside_of_impl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: diagnostics should only be created in `SessionDiagnostic`/`AddSubdiagnostic` impls
- --> $DIR/diagnostics.rs:73:25
+error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+ --> $DIR/diagnostics.rs:79:25
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^
error: diagnostics should be created using translatable messages
- --> $DIR/diagnostics.rs:73:25
+ --> $DIR/diagnostics.rs:79:25
|
LL | let _diag = handler.struct_err("untranslatable diagnostic");
| ^^^^^^^^^^
diff --git a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr
index bc9fcdd7b..4e296fff6 100644
--- a/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr
+++ b/src/test/ui-fulldeps/internal-lints/existing_doc_keyword.stderr
@@ -4,12 +4,12 @@ error: found non-existing keyword `tadam` used in `#[doc(keyword = \"...\")]`
LL | #[doc(keyword = "tadam")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = help: only existing keywords are allowed in core/std
note: the lint level is defined here
--> $DIR/existing_doc_keyword.rs:8:9
|
LL | #![deny(rustc::existing_doc_keyword)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: only existing keywords are allowed in core/std
error: aborting due to previous error
diff --git a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index 9df6be65e..ad6e93334 100644
--- a/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/src/test/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -4,12 +4,12 @@ error: implementing `LintPass` by hand
LL | impl LintPass for Foo {
| ^^^^^^^^
|
+ = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
note: the lint level is defined here
--> $DIR/lint_pass_impl_without_macro.rs:4:9
|
LL | #![deny(rustc::lint_pass_impl_without_macro)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead
error: implementing `LintPass` by hand
--> $DIR/lint_pass_impl_without_macro.rs:30:14
diff --git a/src/test/ui-fulldeps/internal-lints/query_stability.stderr b/src/test/ui-fulldeps/internal-lints/query_stability.stderr
index 7e8b448f4..ee4ef9982 100644
--- a/src/test/ui-fulldeps/internal-lints/query_stability.stderr
+++ b/src/test/ui-fulldeps/internal-lints/query_stability.stderr
@@ -4,12 +4,12 @@ error: using `drain` can result in unstable query results
LL | for _ in x.drain() {}
| ^^^^^
|
+ = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
note: the lint level is defined here
--> $DIR/query_stability.rs:4:9
|
LL | #![deny(rustc::potential_query_instability)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
error: using `iter` can result in unstable query results
--> $DIR/query_stability.rs:16:16
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index da6a84bf3..117b79871 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -73,10 +73,10 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
2 => {
let seg = PathSegment::from_ident(Ident::from_str("x"));
iter_exprs(depth - 1, &mut |e| {
- g(ExprKind::MethodCall(seg.clone(), vec![e, make_x()], DUMMY_SP))
+ g(ExprKind::MethodCall(seg.clone(), e, vec![make_x()], DUMMY_SP))
});
iter_exprs(depth - 1, &mut |e| {
- g(ExprKind::MethodCall(seg.clone(), vec![make_x(), e], DUMMY_SP))
+ g(ExprKind::MethodCall(seg.clone(), make_x(), vec![e], DUMMY_SP))
});
}
3..=8 => {
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index c1c109ac1..ca77e483d 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -1,10 +1,10 @@
// check-fail
-// Tests error conditions for specifying diagnostics using #[derive(SessionDiagnostic)]
+// Tests error conditions for specifying diagnostics using #[derive(Diagnostic)]
// normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
// normalize-stderr-test "diagnostic_builder\.rs:[0-9]+:[0-9]+" -> "diagnostic_builder.rs:LL:CC"
// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
-// changing the output of this test. Since SessionDiagnostic is strictly internal to the compiler
+// changing the output of this test. Since Diagnostic is strictly internal to the compiler
// the test is just ignored on stable and beta:
// ignore-beta
// ignore-stable
@@ -17,7 +17,7 @@ use rustc_span::symbol::Ident;
use rustc_span::Span;
extern crate rustc_macros;
-use rustc_macros::{SessionDiagnostic, LintDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
extern crate rustc_middle;
use rustc_middle::ty::Ty;
@@ -27,116 +27,120 @@ use rustc_errors::{Applicability, MultiSpan};
extern crate rustc_session;
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct Hello {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct HelloWarn {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
-//~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
-enum SessionDiagnosticOnEnum {
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+//~^ ERROR unsupported type attribute for diagnostic derive enum
+enum DiagnosticOnEnum {
Foo,
+//~^ ERROR diagnostic slug not specified
Bar,
+//~^ ERROR diagnostic slug not specified
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
#[diag = "E0123"]
//~^ ERROR `#[diag = ...]` is not a valid attribute
struct WrongStructAttrStyle {}
-#[derive(SessionDiagnostic)]
-#[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[nonsense(compiletest_example, code = "E0123")]
//~^ ERROR `#[nonsense(...)]` is not a valid attribute
//~^^ ERROR diagnostic slug not specified
//~^^^ ERROR cannot find attribute `nonsense` in this scope
struct InvalidStructAttr {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag("E0123")]
//~^ ERROR `#[diag("...")]` is not a valid attribute
//~^^ ERROR diagnostic slug not specified
struct InvalidLitNestedAttr {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag(nonsense, code = "E0123")]
//~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent`
struct InvalidNestedStructAttr {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag(nonsense("foo"), code = "E0123", slug = "foo")]
//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute
//~^^ ERROR diagnostic slug not specified
struct InvalidNestedStructAttr1 {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag(nonsense = "...", code = "E0123", slug = "foo")]
//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
struct InvalidNestedStructAttr2 {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag(nonsense = 4, code = "E0123", slug = "foo")]
//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
struct InvalidNestedStructAttr3 {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123", slug = "foo")]
//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
struct InvalidNestedStructAttr4 {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct WrongPlaceField {
#[suggestion = "bar"]
//~^ ERROR `#[suggestion = ...]` is not a valid attribute
sp: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+#[diag(compiletest_example, code = "E0456")]
//~^ ERROR specified multiple times
//~^^ ERROR specified multiple times
struct DiagSpecifiedTwice {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0456", code = "E0457")]
//~^ ERROR specified multiple times
struct CodeSpecifiedTwice {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-//~^ ERROR `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+#[derive(Diagnostic)]
+#[diag(compiletest_example, compiletest_example, code = "E0456")]
+//~^ ERROR `#[diag(compiletest_example)]` is not a valid attribute
struct SlugSpecifiedTwice {}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
struct KindNotProvided {} //~ ERROR diagnostic slug not specified
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[diag(code = "E0456")]
//~^ ERROR diagnostic slug not specified
struct SlugNotProvided {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound)]
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
struct CodeNotProvided {}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct MessageWrongType {
#[primary_span]
//~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
foo: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct InvalidPathFieldAttr {
#[nonsense]
//~^ ERROR `#[nonsense]` is not a valid attribute
@@ -144,201 +148,204 @@ struct InvalidPathFieldAttr {
foo: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithField {
name: String,
- #[label(typeck::label)]
+ #[label(label)]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithMessageAppliedToField {
- #[label(typeck::label)]
+ #[label(label)]
//~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
name: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithNonexistentField {
- #[suggestion(typeck::suggestion, code = "{name}")]
+ #[suggestion(suggestion, code = "{name}")]
//~^ ERROR `name` doesn't refer to a field on this type
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
//~^ ERROR invalid format string: expected `'}'`
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorMissingClosingBrace {
- #[suggestion(typeck::suggestion, code = "{name")]
+ #[suggestion(suggestion, code = "{name")]
suggestion: (Span, Applicability),
name: String,
val: usize,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
//~^ ERROR invalid format string: unmatched `}`
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorMissingOpeningBrace {
- #[suggestion(typeck::suggestion, code = "name}")]
+ #[suggestion(suggestion, code = "name}")]
suggestion: (Span, Applicability),
name: String,
val: usize,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct LabelOnSpan {
- #[label(typeck::label)]
+ #[label(label)]
sp: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct LabelOnNonSpan {
- #[label(typeck::label)]
+ #[label(label)]
//~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
id: u32,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct Suggest {
- #[suggestion(typeck::suggestion, code = "This is the suggested code")]
- #[suggestion_short(typeck::suggestion, code = "This is the suggested code")]
- #[suggestion_hidden(typeck::suggestion, code = "This is the suggested code")]
- #[suggestion_verbose(typeck::suggestion, code = "This is the suggested code")]
+ #[suggestion(suggestion, code = "This is the suggested code")]
+ #[suggestion_short(suggestion, code = "This is the suggested code")]
+ #[suggestion_hidden(suggestion, code = "This is the suggested code")]
+ #[suggestion_verbose(suggestion, code = "This is the suggested code")]
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithoutCode {
- #[suggestion(typeck::suggestion)]
+ #[suggestion(suggestion)]
+ //~^ ERROR suggestion without `code = "..."`
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithBadKey {
#[suggestion(nonsense = "bar")]
//~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
+ //~| ERROR suggestion without `code = "..."`
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithShorthandMsg {
#[suggestion(msg = "bar")]
//~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
+ //~| ERROR suggestion without `code = "..."`
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithoutMsg {
#[suggestion(code = "bar")]
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithTypesSwapped {
- #[suggestion(typeck::suggestion, code = "This is suggested code")]
+ #[suggestion(suggestion, code = "This is suggested code")]
suggestion: (Applicability, Span),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithWrongTypeApplicabilityOnly {
- #[suggestion(typeck::suggestion, code = "This is suggested code")]
+ #[suggestion(suggestion, code = "This is suggested code")]
//~^ ERROR wrong field type for suggestion
suggestion: Applicability,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithSpanOnly {
- #[suggestion(typeck::suggestion, code = "This is suggested code")]
+ #[suggestion(suggestion, code = "This is suggested code")]
suggestion: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithDuplicateSpanAndApplicability {
- #[suggestion(typeck::suggestion, code = "This is suggested code")]
- //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
+ #[suggestion(suggestion, code = "This is suggested code")]
suggestion: (Span, Span, Applicability),
+ //~^ ERROR specified multiple times
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct SuggestWithDuplicateApplicabilityAndSpan {
- #[suggestion(typeck::suggestion, code = "This is suggested code")]
- //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
+ #[suggestion(suggestion, code = "This is suggested code")]
suggestion: (Applicability, Applicability, Span),
+ //~^ ERROR specified multiple times
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct WrongKindOfAnnotation {
#[label = "bar"]
//~^ ERROR `#[label = ...]` is not a valid attribute
z: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct OptionsInErrors {
- #[label(typeck::label)]
+ #[label(label)]
label: Option<Span>,
- #[suggestion(typeck::suggestion)]
+ #[suggestion(suggestion, code = "...")]
opt_sugg: Option<(Span, Applicability)>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0456")]
struct MoveOutOfBorrowError<'tcx> {
name: Ident,
ty: Ty<'tcx>,
#[primary_span]
- #[label(typeck::label)]
+ #[label(label)]
span: Span,
- #[label(typeck::label)]
+ #[label(label)]
other_span: Span,
- #[suggestion(typeck::suggestion, code = "{name}.clone()")]
+ #[suggestion(suggestion, code = "{name}.clone()")]
opt_sugg: Option<(Span, Applicability)>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithLifetime<'a> {
- #[label(typeck::label)]
+ #[label(label)]
span: Span,
name: &'a str,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithDefaultLabelAttr<'a> {
#[label]
span: Span,
name: &'a str,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
//~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
struct ArgFieldWithoutSkip {
#[primary_span]
span: Span,
other: Hello,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ArgFieldWithSkip {
#[primary_span]
span: Span,
@@ -348,236 +355,444 @@ struct ArgFieldWithSkip {
other: Hello,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithSpannedNote {
#[note]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithSpannedNoteCustom {
- #[note(typeck::note)]
+ #[note(note)]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
#[note]
struct ErrorWithNote {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[note(typeck::note)]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+#[note(note)]
struct ErrorWithNoteCustom {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithSpannedHelp {
#[help]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithSpannedHelpCustom {
- #[help(typeck::help)]
+ #[help(help)]
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
#[help]
struct ErrorWithHelp {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[help(typeck::help)]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+#[help(help)]
struct ErrorWithHelpCustom {
val: String,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[help]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithHelpWrongOrder {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[help(typeck::help)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[help(help)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithHelpCustomWrongOrder {
val: String,
}
-#[derive(SessionDiagnostic)]
+#[derive(Diagnostic)]
#[note]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithNoteWrongOrder {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[note(typeck::note)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[note(note)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithNoteCustomWrongOrder {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ApplicabilityInBoth {
- #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
- //~^ ERROR applicability cannot be set in both the field and attribute
+ #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
+ //~^ ERROR specified multiple times
suggestion: (Span, Applicability),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct InvalidApplicability {
- #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
+ #[suggestion(suggestion, code = "...", applicability = "batman")]
//~^ ERROR invalid applicability
suggestion: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ValidApplicability {
- #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
+ #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
suggestion: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct NoApplicability {
- #[suggestion(typeck::suggestion, code = "...")]
+ #[suggestion(suggestion, code = "...")]
suggestion: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[note(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[note(parser_add_paren)]
struct Note;
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound)]
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
struct Subdiagnostic {
#[subdiagnostic]
note: Note,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct VecField {
#[primary_span]
#[label]
spans: Vec<Span>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct UnitField {
#[primary_span]
spans: Span,
#[help]
foo: (),
- #[help(typeck::help)]
+ #[help(help)]
bar: (),
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct OptUnitField {
#[primary_span]
spans: Span,
#[help]
foo: Option<()>,
- #[help(typeck::help)]
+ #[help(help)]
bar: Option<()>,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct LabelWithTrailingPath {
- #[label(typeck::label, foo)]
- //~^ ERROR `#[label(...)]` is not a valid attribute
+ #[label(label, foo)]
+ //~^ ERROR `#[label(foo)]` is not a valid attribute
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct LabelWithTrailingNameValue {
- #[label(typeck::label, foo = "...")]
- //~^ ERROR `#[label(...)]` is not a valid attribute
+ #[label(label, foo = "...")]
+ //~^ ERROR `#[label(foo = ...)]` is not a valid attribute
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct LabelWithTrailingList {
- #[label(typeck::label, foo("..."))]
- //~^ ERROR `#[label(...)]` is not a valid attribute
+ #[label(label, foo("..."))]
+ //~^ ERROR `#[label(foo(...))]` is not a valid attribute
span: Span,
}
#[derive(LintDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound)]
+#[diag(compiletest_example)]
struct LintsGood {
}
#[derive(LintDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound)]
+#[diag(compiletest_example)]
struct PrimarySpanOnLint {
#[primary_span]
//~^ ERROR `#[primary_span]` is not a valid attribute
span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
struct ErrorWithMultiSpan {
#[primary_span]
span: MultiSpan,
}
-#[derive(SessionDiagnostic)]
-#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
#[warning]
struct ErrorWithWarn {
val: String,
}
-#[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[error(compiletest_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(SessionDiagnostic)]
-#[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[warn_(compiletest_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(SessionDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[derive(Diagnostic)]
+#[lint(compiletest_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(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[lint(compiletest_example, code = "E0123")]
//~^ ERROR `#[lint(...)]` is not a valid attribute
+//~| ERROR `#[lint(...)]` is not a valid attribute
//~| ERROR diagnostic slug not specified
//~| ERROR cannot find attribute `lint` in this scope
struct LintAttributeOnLintDiag {}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct DuplicatedSuggestionCode {
+ #[suggestion(suggestion, code = "...", code = ",,,")]
+ //~^ ERROR specified multiple times
+ suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct InvalidTypeInSuggestionTuple {
+ #[suggestion(suggestion, code = "...")]
+ suggestion: (Span, usize),
+ //~^ ERROR wrong types for suggestion
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct MissingApplicabilityInSuggestionTuple {
+ #[suggestion(suggestion, code = "...")]
+ suggestion: (Span,),
+ //~^ ERROR wrong types for suggestion
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct MissingCodeInSuggestion {
+ #[suggestion(suggestion)]
+ //~^ ERROR suggestion without `code = "..."`
+ suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+#[multipart_suggestion(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)]
+ //~^ 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 = "...")]
+//~^ ERROR `#[suggestion(...)]` is not a valid attribute
+struct SuggestionOnStruct {
+ #[primary_span]
+ suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+#[label]
+//~^ ERROR `#[label]` is not a valid attribute
+struct LabelOnStruct {
+ #[primary_span]
+ suggestion: Span,
+}
+
+#[derive(Diagnostic)]
+enum ExampleEnum {
+ #[diag(compiletest_example)]
+ Foo {
+ #[primary_span]
+ sp: Span,
+ #[note]
+ note_sp: Span,
+ },
+ #[diag(compiletest_example)]
+ Bar {
+ #[primary_span]
+ sp: Span,
+ },
+ #[diag(compiletest_example)]
+ Baz,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct RawIdentDiagnosticArg {
+ pub r#type: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticBad {
+ #[subdiagnostic(bad)]
+//~^ ERROR `#[subdiagnostic(bad)]` is not a valid attribute
+ note: Note,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticBadStr {
+ #[subdiagnostic = "bad"]
+//~^ ERROR `#[subdiagnostic = ...]` is not a valid attribute
+ note: Note,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticBadTwice {
+ #[subdiagnostic(bad, bad)]
+//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+ note: Note,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticBadLitStr {
+ #[subdiagnostic("bad")]
+//~^ ERROR `#[subdiagnostic("...")]` is not a valid attribute
+ note: Note,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticEagerLint {
+ #[subdiagnostic(eager)]
+//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+ note: Note,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticEagerCorrect {
+ #[subdiagnostic(eager)]
+ note: Note,
+}
+
+// Check that formatting of `correct` in suggestion doesn't move the binding for that field, making
+// the `set_arg` call a compile error; and that isn't worked around by moving the `set_arg` call
+// after the `span_suggestion` call - which breaks eager translation.
+
+#[derive(Subdiagnostic)]
+#[suggestion_short(
+ use_instead,
+ applicability = "machine-applicable",
+ code = "{correct}"
+)]
+pub(crate) struct SubdiagnosticWithSuggestion {
+ #[primary_span]
+ span: Span,
+ invalid: String,
+ correct: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SubdiagnosticEagerSuggestion {
+ #[subdiagnostic(eager)]
+ sub: SubdiagnosticWithSuggestion,
+}
+
+/// with a doc comment on the type..
+#[derive(Diagnostic)]
+#[diag(compiletest_example, code = "E0123")]
+struct WithDocComment {
+ /// ..and the field
+ #[primary_span]
+ span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionsGood {
+ #[suggestion(code("foo", "bar"))]
+ sub: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionsSingleItem {
+ #[suggestion(code("foo"))]
+ sub: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionsNoItem {
+ #[suggestion(code())]
+ //~^ ERROR expected at least one string literal for `code(...)`
+ sub: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionsInvalidItem {
+ #[suggestion(code(foo))]
+ //~^ ERROR `code(...)` must contain only string literals
+ sub: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(compiletest_example)]
+struct SuggestionsInvalidLiteral {
+ #[suggestion(code = 3)]
+ //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+ sub: Span,
+}
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index ab5c28fe4..859c272b6 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,50 +1,59 @@
-error: `#[derive(SessionDiagnostic)]` can only be used on structs
+error: unsupported type attribute for diagnostic derive enum
--> $DIR/diagnostic-derive.rs:39:1
|
-LL | / #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
-LL | |
-LL | | enum SessionDiagnosticOnEnum {
-LL | | Foo,
-LL | | Bar,
-LL | | }
- | |_^
+LL | #[diag(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: diagnostic slug not specified
+ --> $DIR/diagnostic-derive.rs:42:5
+ |
+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
+ |
+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:48:1
+ --> $DIR/diagnostic-derive.rs:50:1
|
LL | #[diag = "E0123"]
| ^^^^^^^^^^^^^^^^^
error: `#[nonsense(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:53:1
+ --> $DIR/diagnostic-derive.rs:55:1
|
-LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: only `diag`, `help`, `note` and `warning` are valid attributes
+LL | #[nonsense(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:53:1
+ --> $DIR/diagnostic-derive.rs:55:1
|
-LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[nonsense(compiletest_example, code = "E0123")]
LL | |
LL | |
LL | |
LL | | struct InvalidStructAttr {}
| |___________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:60:8
+ --> $DIR/diagnostic-derive.rs:62:8
|
LL | #[diag("E0123")]
| ^^^^^^^
|
- = help: first argument of the attribute should be the diagnostic slug
+ = help: a diagnostic slug is required as the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:60:1
+ --> $DIR/diagnostic-derive.rs:62:1
|
LL | / #[diag("E0123")]
LL | |
@@ -52,18 +61,18 @@ LL | |
LL | | struct InvalidLitNestedAttr {}
| |______________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:71:8
+ --> $DIR/diagnostic-derive.rs:73:8
|
LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^
|
- = help: first argument of the attribute should be the diagnostic slug
+ = help: a diagnostic slug is required as the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:71:1
+ --> $DIR/diagnostic-derive.rs:73:1
|
LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
LL | |
@@ -71,252 +80,300 @@ LL | |
LL | | struct InvalidNestedStructAttr1 {}
| |__________________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:77:8
+ --> $DIR/diagnostic-derive.rs:79:8
|
LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^^^^^
|
- = help: first argument of the attribute should be the diagnostic slug
+ = 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
+ |
+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:77:1
+ --> $DIR/diagnostic-derive.rs:79:1
|
LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
LL | |
LL | |
+LL | |
LL | | struct InvalidNestedStructAttr2 {}
| |__________________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:83:8
+ --> $DIR/diagnostic-derive.rs:86:8
|
LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
| ^^^^^^^^^^^^
+
+error: `#[diag(slug = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:86:38
|
- = help: first argument of the attribute should be the diagnostic slug
+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:83:1
+ --> $DIR/diagnostic-derive.rs:86:1
|
LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
LL | |
LL | |
+LL | |
LL | | struct InvalidNestedStructAttr3 {}
| |__________________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:89:58
+ --> $DIR/diagnostic-derive.rs:93:45
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
- | ^^^^^^^^^^^^
+LL | #[diag(compiletest_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:96:5
+ --> $DIR/diagnostic-derive.rs:100:5
|
LL | #[suggestion = "bar"]
| ^^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:103:1
+ --> $DIR/diagnostic-derive.rs:107:8
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456")]
+ | ^^^^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:102:1
+ --> $DIR/diagnostic-derive.rs:106:8
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:103:49
+ --> $DIR/diagnostic-derive.rs:107:36
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
- | ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456")]
+ | ^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:102:49
+ --> $DIR/diagnostic-derive.rs:106:36
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0123")]
+ | ^^^^^^^
error: specified multiple times
- --> $DIR/diagnostic-derive.rs:109:65
+ --> $DIR/diagnostic-derive.rs:113:52
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
- | ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
+ | ^^^^^^^
|
note: previously specified here
- --> $DIR/diagnostic-derive.rs:109:49
+ --> $DIR/diagnostic-derive.rs:113:36
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
- | ^^^^^^^
+LL | #[diag(compiletest_example, code = "E0456", code = "E0457")]
+ | ^^^^^^^
-error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:114:42
+error: `#[diag(compiletest_example)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:118:29
+ |
+LL | #[diag(compiletest_example, compiletest_example, code = "E0456")]
+ | ^^^^^^^^^^^^^^^^^^^
|
-LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = help: diagnostic slug must be the first argument
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:119:1
+ --> $DIR/diagnostic-derive.rs:123:1
|
LL | struct KindNotProvided {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:122:1
+ --> $DIR/diagnostic-derive.rs:126:1
|
LL | / #[diag(code = "E0456")]
LL | |
LL | | struct SlugNotProvided {}
| |_________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:133:5
+ --> $DIR/diagnostic-derive.rs:137:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: `#[nonsense]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:141:5
+ --> $DIR/diagnostic-derive.rs:145:5
|
LL | #[nonsense]
| ^^^^^^^^^^^
- |
- = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes
error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/diagnostic-derive.rs:158:5
+ --> $DIR/diagnostic-derive.rs:162:5
|
-LL | #[label(typeck::label)]
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(label)]
+ | ^^^^^^^^^^^^^^^
error: `name` doesn't refer to a field on this type
- --> $DIR/diagnostic-derive.rs:166:45
+ --> $DIR/diagnostic-derive.rs:170:37
|
-LL | #[suggestion(typeck::suggestion, code = "{name}")]
- | ^^^^^^^^
+LL | #[suggestion(suggestion, code = "{name}")]
+ | ^^^^^^^^
error: invalid format string: expected `'}'` but string was terminated
- --> $DIR/diagnostic-derive.rs:171:16
+ --> $DIR/diagnostic-derive.rs:175:10
|
-LL | #[derive(SessionDiagnostic)]
- | - ^ expected `'}'` in format string
- | |
- | because of this opening brace
+LL | #[derive(Diagnostic)]
+ | ^^^^^^^^^^ expected `'}'` in format string
|
= note: if you intended to print `{`, you can escape it using `{{`
- = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = 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:181:15
+ --> $DIR/diagnostic-derive.rs:185:10
|
-LL | #[derive(SessionDiagnostic)]
- | ^ unmatched `}` in format string
+LL | #[derive(Diagnostic)]
+ | ^^^^^^^^^^ unmatched `}` in format string
|
= note: if you intended to print `}`, you can escape it using `}}`
- = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = 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:201:5
+ --> $DIR/diagnostic-derive.rs:205:5
|
-LL | #[label(typeck::label)]
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(label)]
+ | ^^^^^^^^^^^^^^^
+
+error: suggestion without `code = "..."`
+ --> $DIR/diagnostic-derive.rs:223:5
+ |
+LL | #[suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion(nonsense = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:226:18
+ --> $DIR/diagnostic-derive.rs:231:18
|
LL | #[suggestion(nonsense = "bar")]
| ^^^^^^^^^^^^^^^^
|
- = help: only `message`, `code` and `applicability` are valid field attributes
+ = help: only `code` and `applicability` are valid nested attributes
+
+error: suggestion without `code = "..."`
+ --> $DIR/diagnostic-derive.rs:231:5
+ |
+LL | #[suggestion(nonsense = "bar")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion(msg = ...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:234:18
+ --> $DIR/diagnostic-derive.rs:240:18
|
LL | #[suggestion(msg = "bar")]
| ^^^^^^^^^^^
|
- = help: only `message`, `code` and `applicability` are valid field attributes
+ = help: only `code` and `applicability` are valid nested attributes
+
+error: suggestion without `code = "..."`
+ --> $DIR/diagnostic-derive.rs:240:5
+ |
+LL | #[suggestion(msg = "bar")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: wrong field type for suggestion
- --> $DIR/diagnostic-derive.rs:256:5
+ --> $DIR/diagnostic-derive.rs:263:5
|
-LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
+LL | / #[suggestion(suggestion, code = "This is suggested code")]
LL | |
LL | | suggestion: Applicability,
| |_____________________________^
|
= help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
-error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
- --> $DIR/diagnostic-derive.rs:271:5
+error: specified multiple times
+ --> $DIR/diagnostic-derive.rs:279:24
|
-LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
-LL | |
-LL | | suggestion: (Span, Span, Applicability),
- | |___________________________________________^
+LL | suggestion: (Span, Span, Applicability),
+ | ^^^^
+ |
+note: previously specified here
+ --> $DIR/diagnostic-derive.rs:279:18
+ |
+LL | suggestion: (Span, Span, Applicability),
+ | ^^^^
-error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
- --> $DIR/diagnostic-derive.rs:279:5
+error: specified multiple times
+ --> $DIR/diagnostic-derive.rs:287:33
|
-LL | / #[suggestion(typeck::suggestion, code = "This is suggested code")]
-LL | |
-LL | | suggestion: (Applicability, Applicability, Span),
- | |____________________________________________________^
+LL | suggestion: (Applicability, Applicability, Span),
+ | ^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/diagnostic-derive.rs:287:18
+ |
+LL | suggestion: (Applicability, Applicability, Span),
+ | ^^^^^^^^^^^^^
error: `#[label = ...]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:287:5
+ --> $DIR/diagnostic-derive.rs:294:5
|
LL | #[label = "bar"]
| ^^^^^^^^^^^^^^^^
-error: applicability cannot be set in both the field and attribute
- --> $DIR/diagnostic-derive.rs:438:52
+error: specified multiple times
+ --> $DIR/diagnostic-derive.rs:445:44
+ |
+LL | #[suggestion(suggestion, code = "...", applicability = "maybe-incorrect")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/diagnostic-derive.rs:447:24
|
-LL | #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | suggestion: (Span, Applicability),
+ | ^^^^^^^^^^^^^
error: invalid applicability
- --> $DIR/diagnostic-derive.rs:446:52
+ --> $DIR/diagnostic-derive.rs:453:44
|
-LL | #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(suggestion, code = "...", applicability = "batman")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
-error: `#[label(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:509:5
+error: `#[label(foo)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:516:20
|
-LL | #[label(typeck::label, foo)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(label, foo)]
+ | ^^^
+ |
+ = help: a diagnostic slug must be the first argument to the attribute
-error: `#[label(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:517:5
+error: `#[label(foo = ...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:524:20
|
-LL | #[label(typeck::label, foo = "...")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(label, foo = "...")]
+ | ^^^^^^^^^^^
-error: `#[label(...)]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:525:5
+error: `#[label(foo(...))]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:532:20
|
-LL | #[label(typeck::label, foo("..."))]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(label, foo("..."))]
+ | ^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
- --> $DIR/diagnostic-derive.rs:538:5
+ --> $DIR/diagnostic-derive.rs:545:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@@ -324,132 +381,281 @@ 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:558:1
- |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $DIR/diagnostic-derive.rs:565:1
|
- = help: `error` and `lint` have been replaced by `diag`
+LL | #[error(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:558:1
+ --> $DIR/diagnostic-derive.rs:565:1
|
-LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[error(compiletest_example, code = "E0123")]
LL | |
LL | |
LL | |
LL | | struct ErrorAttribute {}
| |________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:565:1
- |
-LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $DIR/diagnostic-derive.rs:572:1
|
- = help: `warn_` have been replaced by `warning`
+LL | #[warn_(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:565:1
+ --> $DIR/diagnostic-derive.rs:572:1
|
-LL | / #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[warn_(compiletest_example, code = "E0123")]
LL | |
LL | |
LL | |
LL | | struct WarnAttribute {}
| |_______________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:572:1
- |
-LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ --> $DIR/diagnostic-derive.rs:579:1
|
- = help: `error` and `lint` have been replaced by `diag`
+LL | #[lint(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:572:1
+ --> $DIR/diagnostic-derive.rs:579:1
|
-LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[lint(compiletest_example, code = "E0123")]
LL | |
LL | |
LL | |
LL | | struct LintAttributeOnSessionDiag {}
| |____________________________________^
|
- = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+ = 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:586:1
|
-LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[lint(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[lint(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:586:1
|
- = help: `error` and `lint` have been replaced by `diag`
+LL | #[lint(compiletest_example, code = "E0123")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug not specified
- --> $DIR/diagnostic-derive.rs:579:1
+ --> $DIR/diagnostic-derive.rs:586:1
|
-LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[lint(compiletest_example, code = "E0123")]
+LL | |
LL | |
LL | |
LL | |
LL | | struct LintAttributeOnLintDiag {}
| |_________________________________^
|
- = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]`
+ = 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
+ |
+LL | #[suggestion(suggestion, code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
+ |
+note: previously specified here
+ --> $DIR/diagnostic-derive.rs:596:30
+ |
+LL | #[suggestion(suggestion, code = "...", code = ",,,")]
+ | ^^^^^^^^^^^^
+
+error: wrong types for suggestion
+ --> $DIR/diagnostic-derive.rs:605:24
+ |
+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
+ |
+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
+ |
+LL | #[suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `#[multipart_suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:627:1
+ |
+LL | #[multipart_suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider creating a `Subdiagnostic` instead
+
+error: `#[multipart_suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:630:1
+ |
+LL | #[multipart_suggestion()]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider creating a `Subdiagnostic` instead
+
+error: `#[multipart_suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:634:5
+ |
+LL | #[multipart_suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider creating a `Subdiagnostic` instead
+
+error: `#[suggestion(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:642:1
+ |
+LL | #[suggestion(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
+ |
+LL | #[label]
+ | ^^^^^^^^
+ |
+ = help: `#[label]` and `#[suggestion]` can only be applied to fields
+
+error: `#[subdiagnostic(bad)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:685:21
+ |
+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
+ |
+LL | #[subdiagnostic = "bad"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `eager` is the only supported nested attribute for `subdiagnostic`
+
+error: `#[subdiagnostic(...)]` is not a valid attribute
+ --> $DIR/diagnostic-derive.rs:701:5
+ |
+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:21
+ |
+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
+ |
+LL | #[subdiagnostic(eager)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: eager subdiagnostics are not supported on lints
+
+error: expected at least one string literal for `code(...)`
+ --> $DIR/diagnostic-derive.rs:779:18
+ |
+LL | #[suggestion(code())]
+ | ^^^^^^
+
+error: `code(...)` must contain only string literals
+ --> $DIR/diagnostic-derive.rs:787:23
+ |
+LL | #[suggestion(code(foo))]
+ | ^^^
+
+error: `code = "..."`/`code(...)` must contain only string literals
+ --> $DIR/diagnostic-derive.rs:795:18
+ |
+LL | #[suggestion(code = 3)]
+ | ^^^^^^^^
error: cannot find attribute `nonsense` in this scope
- --> $DIR/diagnostic-derive.rs:53:3
+ --> $DIR/diagnostic-derive.rs:55:3
|
-LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | #[nonsense(compiletest_example, code = "E0123")]
| ^^^^^^^^
error: cannot find attribute `nonsense` in this scope
- --> $DIR/diagnostic-derive.rs:141:7
+ --> $DIR/diagnostic-derive.rs:145:7
|
LL | #[nonsense]
| ^^^^^^^^
error: cannot find attribute `error` in this scope
- --> $DIR/diagnostic-derive.rs:558:3
+ --> $DIR/diagnostic-derive.rs:565:3
|
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | #[error(compiletest_example, code = "E0123")]
| ^^^^^
error: cannot find attribute `warn_` in this scope
- --> $DIR/diagnostic-derive.rs:565:3
+ --> $DIR/diagnostic-derive.rs:572:3
|
-LL | #[warn_(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | #[warn_(compiletest_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:572:3
+ --> $DIR/diagnostic-derive.rs:579:3
|
-LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | #[lint(compiletest_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:579:3
+ --> $DIR/diagnostic-derive.rs:586:3
|
-LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | #[lint(compiletest_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
+ |
+LL | #[multipart_suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `multipart_suggestion` in this scope
+ --> $DIR/diagnostic-derive.rs:630:3
+ |
+LL | #[multipart_suggestion()]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: cannot find attribute `multipart_suggestion` in this scope
+ --> $DIR/diagnostic-derive.rs:634:7
+ |
+LL | #[multipart_suggestion(suggestion)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
- --> $DIR/diagnostic-derive.rs:66:8
+ --> $DIR/diagnostic-derive.rs:68:8
|
LL | #[diag(nonsense, code = "E0123")]
| ^^^^^^^^ not found in `rustc_errors::fluent`
error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
- --> $DIR/diagnostic-derive.rs:331:10
+ --> $DIR/diagnostic-derive.rs:338:10
|
-LL | #[derive(SessionDiagnostic)]
- | ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
+LL | #[derive(Diagnostic)]
+ | ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
|
= help: normalized in stderr
note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
@@ -457,9 +663,9 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
|
LL | arg: impl IntoDiagnosticArg,
| ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
- = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 55 previous errors
+error: aborting due to 83 previous errors
Some errors have detailed explanations: E0277, E0425.
For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 812ca0c72..efec85eb5 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -1,8 +1,8 @@
// check-fail
-// Tests error conditions for specifying subdiagnostics using #[derive(SessionSubdiagnostic)]
+// Tests error conditions for specifying subdiagnostics using #[derive(Subdiagnostic)]
// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
-// changing the output of this test. Since SessionSubdiagnostic is strictly internal to the compiler
+// changing the output of this test. Since Subdiagnostic is strictly internal to the compiler
// the test is just ignored on stable and beta:
// ignore-beta
// ignore-stable
@@ -17,25 +17,25 @@ extern crate rustc_macros;
use rustc_errors::Applicability;
use rustc_span::Span;
-use rustc_macros::SessionSubdiagnostic;
+use rustc_macros::Subdiagnostic;
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct A {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum B {
- #[label(parser::add_paren)]
+ #[label(parser_add_paren)]
A {
#[primary_span]
span: Span,
var: String,
},
- #[label(parser::add_paren)]
+ #[label(parser_add_paren)]
B {
#[primary_span]
span: Span,
@@ -43,23 +43,23 @@ enum B {
}
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
//~^ ERROR label without `#[primary_span]` field
struct C {
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label]
-//~^ ERROR `#[label]` is not a valid attribute
+//~^ ERROR diagnostic slug must be first argument
struct D {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[foo]
//~^ ERROR `#[foo]` is not a valid attribute
//~^^ ERROR cannot find attribute `foo` in this scope
@@ -69,7 +69,7 @@ struct E {
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label = "..."]
//~^ ERROR `#[label = ...]` is not a valid attribute
struct F {
@@ -78,43 +78,47 @@ struct F {
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label(bug = "...")]
//~^ ERROR `#[label(bug = ...)]` is not a valid attribute
+//~| ERROR diagnostic slug must be first argument
struct G {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label("...")]
//~^ ERROR `#[label("...")]` is not a valid attribute
+//~| ERROR diagnostic slug must be first argument
struct H {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label(slug = 4)]
//~^ ERROR `#[label(slug = ...)]` is not a valid attribute
+//~| ERROR diagnostic slug must be first argument
struct J {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label(slug("..."))]
//~^ ERROR `#[label(slug(...))]` is not a valid attribute
+//~| ERROR diagnostic slug must be first argument
struct K {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label(slug)]
//~^ ERROR cannot find value `slug` in module `rustc_errors::fluent`
//~^^ NOTE not found in `rustc_errors::fluent`
@@ -124,7 +128,7 @@ struct L {
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label()]
//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
struct M {
@@ -133,30 +137,30 @@ struct M {
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren, code = "...")]
-//~^ ERROR `code` is not a valid nested attribute of a `label` attribute
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren, code = "...")]
+//~^ ERROR `#[label(code = ...)]` is not a valid attribute
struct N {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren, applicability = "machine-applicable")]
-//~^ ERROR `applicability` is not a valid nested attribute of a `label` attribute
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren, applicability = "machine-applicable")]
+//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
struct O {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[foo]
//~^ ERROR cannot find attribute `foo` in this scope
//~^^ ERROR unsupported type attribute for subdiagnostic enum
enum P {
- #[label(parser::add_paren)]
+ #[label(parser_add_paren)]
A {
#[primary_span]
span: Span,
@@ -164,7 +168,7 @@ enum P {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum Q {
#[bar]
//~^ ERROR `#[bar]` is not a valid attribute
@@ -176,7 +180,7 @@ enum Q {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum R {
#[bar = "..."]
//~^ ERROR `#[bar = ...]` is not a valid attribute
@@ -188,7 +192,7 @@ enum R {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum S {
#[bar = 4]
//~^ ERROR `#[bar = ...]` is not a valid attribute
@@ -200,7 +204,7 @@ enum S {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum T {
#[bar("...")]
//~^ ERROR `#[bar(...)]` is not a valid attribute
@@ -212,10 +216,11 @@ enum T {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum U {
#[label(code = "...")]
//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+ //~| ERROR `#[label(code = ...)]` is not a valid attribute
A {
#[primary_span]
span: Span,
@@ -223,24 +228,23 @@ enum U {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum V {
- #[label(parser::add_paren)]
+ #[label(parser_add_paren)]
A {
#[primary_span]
span: Span,
var: String,
},
B {
- //~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
var: String,
}
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
//~^ ERROR label without `#[primary_span]` field
struct W {
#[primary_span]
@@ -248,8 +252,8 @@ struct W {
span: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct X {
#[primary_span]
span: Span,
@@ -258,8 +262,8 @@ struct X {
applicability: Applicability,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct Y {
#[primary_span]
span: Span,
@@ -269,8 +273,8 @@ struct Y {
bar: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct Z {
#[primary_span]
span: Span,
@@ -280,8 +284,8 @@ struct Z {
bar: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct AA {
#[primary_span]
span: Span,
@@ -291,8 +295,8 @@ struct AA {
bar: String,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct AB {
#[primary_span]
span: Span,
@@ -300,31 +304,31 @@ struct AB {
z: Z
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
union AC {
//~^ ERROR unexpected unsupported untagged union
span: u32,
b: u64
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
+#[label(parser_add_paren)]
struct AD {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren, parser::add_paren)]
-//~^ ERROR `#[label(parser::add_paren)]` is not a valid attribute
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren, parser_add_paren)]
+//~^ ERROR `#[label(parser_add_paren)]` is not a valid attribute
struct AE {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[label(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
struct AF {
#[primary_span]
//~^ NOTE previously specified here
@@ -334,15 +338,15 @@ struct AF {
span_b: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
struct AG {
//~^ ERROR subdiagnostic kind not specified
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
struct AH {
#[primary_span]
span: Span,
@@ -351,9 +355,9 @@ struct AH {
var: String,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum AI {
- #[suggestion(parser::add_paren, code = "...")]
+ #[suggestion(parser_add_paren, code = "...")]
A {
#[primary_span]
span: Span,
@@ -361,7 +365,7 @@ enum AI {
applicability: Applicability,
var: String,
},
- #[suggestion(parser::add_paren, code = "...")]
+ #[suggestion(parser_add_paren, code = "...")]
B {
#[primary_span]
span: Span,
@@ -371,8 +375,8 @@ enum AI {
}
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...", code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...", code = "...")]
//~^ ERROR specified multiple times
//~^^ NOTE previously specified here
struct AJ {
@@ -382,8 +386,8 @@ struct AJ {
applicability: Applicability,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
struct AK {
#[primary_span]
span: Span,
@@ -395,8 +399,8 @@ struct AK {
applicability_b: Applicability,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
struct AL {
#[primary_span]
span: Span,
@@ -405,15 +409,15 @@ struct AL {
applicability: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
struct AM {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren)]
//~^ ERROR suggestion without `code = "..."`
struct AN {
#[primary_span]
@@ -422,43 +426,43 @@ struct AN {
applicability: Applicability,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code ="...", applicability = "foo")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code ="...", applicability = "foo")]
//~^ ERROR invalid applicability
struct AO {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[help(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[help(parser_add_paren)]
struct AP {
var: String
}
-#[derive(SessionSubdiagnostic)]
-#[note(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[note(parser_add_paren)]
struct AQ;
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
//~^ ERROR suggestion without `#[primary_span]` field
struct AR {
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code ="...", applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code ="...", applicability = "machine-applicable")]
struct AS {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
#[label]
//~^ ERROR unsupported type attribute for subdiagnostic enum
enum AT {
- #[label(parser::add_paren)]
+ #[label(parser_add_paren)]
A {
#[primary_span]
span: Span,
@@ -466,25 +470,25 @@ enum AT {
}
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
struct AU {
#[primary_span]
span: Span,
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
//~^ ERROR `var` doesn't refer to a field on this type
struct AV {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum AW {
- #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
A {
#[primary_span]
span: Span,
@@ -492,9 +496,9 @@ enum AW {
}
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
enum AX {
- #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
+ #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
//~^ ERROR `var` doesn't refer to a field on this type
A {
#[primary_span]
@@ -502,19 +506,19 @@ enum AX {
}
}
-#[derive(SessionSubdiagnostic)]
-#[warning(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[warning(parser_add_paren)]
struct AY {}
-#[derive(SessionSubdiagnostic)]
-#[warning(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[warning(parser_add_paren)]
struct AZ {
#[primary_span]
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[suggestion(parser::add_paren, code = "...")]
+#[derive(Subdiagnostic)]
+#[suggestion(parser_add_paren, code = "...")]
//~^ ERROR suggestion without `#[primary_span]` field
struct BA {
#[suggestion_part]
@@ -528,32 +532,32 @@ struct BA {
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
-//~| ERROR `code` is not a valid nested attribute of a `multipart_suggestion` attribute
+//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
struct BBa {
var: String,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BBb {
#[suggestion_part]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
span1: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BBc {
#[suggestion_part()]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
span1: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
//~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
struct BC {
#[primary_span]
@@ -561,8 +565,8 @@ struct BC {
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
struct BD {
#[suggestion_part]
//~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
@@ -581,8 +585,8 @@ struct BD {
s2: String,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BE {
#[suggestion_part(code = "...", code = ",,,")]
//~^ ERROR specified multiple times
@@ -590,8 +594,8 @@ struct BE {
span: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BF {
#[suggestion_part(code = "(")]
first: Span,
@@ -599,8 +603,8 @@ struct BF {
second: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren)]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
struct BG {
#[applicability]
appl: Applicability,
@@ -610,12 +614,11 @@ struct BG {
second: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
-//~^ NOTE previously specified here
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BH {
#[applicability]
- //~^ ERROR specified multiple times
+ //~^ ERROR `#[applicability]` has no effect
appl: Applicability,
#[suggestion_part(code = "(")]
first: Span,
@@ -623,9 +626,83 @@ struct BH {
second: Span,
}
-#[derive(SessionSubdiagnostic)]
-#[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren, applicability = "machine-applicable")]
struct BI {
#[suggestion_part(code = "")]
spans: Vec<Span>,
}
+
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
+struct BJ {
+ #[primary_span]
+ span: Span,
+ r#type: String,
+}
+
+/// with a doc comment on the type..
+#[derive(Subdiagnostic)]
+#[label(parser_add_paren)]
+struct BK {
+ /// ..and the field
+ #[primary_span]
+ span: Span,
+}
+
+/// with a doc comment on the type..
+#[derive(Subdiagnostic)]
+enum BL {
+ /// ..and the variant..
+ #[label(parser_add_paren)]
+ Foo {
+ /// ..and the field
+ #[primary_span]
+ span: Span,
+ }
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
+struct BM {
+ #[suggestion_part(code("foo"))]
+ //~^ ERROR expected exactly one string literal for `code = ...`
+ span: Span,
+ r#type: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
+struct BN {
+ #[suggestion_part(code("foo", "bar"))]
+ //~^ ERROR expected exactly one string literal for `code = ...`
+ span: Span,
+ r#type: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
+struct BO {
+ #[suggestion_part(code(3))]
+ //~^ ERROR expected exactly one string literal for `code = ...`
+ span: Span,
+ r#type: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
+struct BP {
+ #[suggestion_part(code())]
+ //~^ ERROR expected exactly one string literal for `code = ...`
+ span: Span,
+ r#type: String,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(parser_add_paren)]
+struct BQ {
+ #[suggestion_part(code = 3)]
+ //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+ span: Span,
+ r#type: String,
+}
diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 0a0247e89..a85a8711e 100644
--- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -1,14 +1,14 @@
error: label without `#[primary_span]` field
--> $DIR/subdiagnostic-derive.rs:47:1
|
-LL | / #[label(parser::add_paren)]
+LL | / #[label(parser_add_paren)]
LL | |
LL | | struct C {
LL | | var: String,
LL | | }
| |_^
-error: `#[label]` is not a valid attribute
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
--> $DIR/subdiagnostic-derive.rs:54:1
|
LL | #[label]
@@ -31,103 +31,119 @@ error: `#[label(bug = ...)]` is not a valid attribute
|
LL | #[label(bug = "...")]
| ^^^^^^^^^^^
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:82:1
|
- = help: first argument of the attribute should be the diagnostic slug
+LL | #[label(bug = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^
error: `#[label("...")]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:91:9
+ --> $DIR/subdiagnostic-derive.rs:92:9
|
LL | #[label("...")]
| ^^^^^
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:92:1
|
- = help: first argument of the attribute should be the diagnostic slug
+LL | #[label("...")]
+ | ^^^^^^^^^^^^^^^
error: `#[label(slug = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:100:9
+ --> $DIR/subdiagnostic-derive.rs:102:9
|
LL | #[label(slug = 4)]
| ^^^^^^^^
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:102:1
|
- = help: first argument of the attribute should be the diagnostic slug
+LL | #[label(slug = 4)]
+ | ^^^^^^^^^^^^^^^^^^
error: `#[label(slug(...))]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:109:9
+ --> $DIR/subdiagnostic-derive.rs:112:9
|
LL | #[label(slug("..."))]
| ^^^^^^^^^^^
+
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:112:1
|
- = help: first argument of the attribute should be the diagnostic slug
+LL | #[label(slug("..."))]
+ | ^^^^^^^^^^^^^^^^^^^^^
error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:128:1
+ --> $DIR/subdiagnostic-derive.rs:132:1
|
LL | #[label()]
| ^^^^^^^^^^
-error: `code` is not a valid nested attribute of a `label` attribute
- --> $DIR/subdiagnostic-derive.rs:137:28
+error: `#[label(code = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:141:27
|
-LL | #[label(parser::add_paren, code = "...")]
- | ^^^^^^^^^^^^
+LL | #[label(parser_add_paren, code = "...")]
+ | ^^^^^^^^^^^^
-error: `applicability` is not a valid nested attribute of a `label` attribute
- --> $DIR/subdiagnostic-derive.rs:146:28
+error: `#[label(applicability = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:150:27
|
-LL | #[label(parser::add_paren, applicability = "machine-applicable")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[label(parser_add_paren, applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: unsupported type attribute for subdiagnostic enum
- --> $DIR/subdiagnostic-derive.rs:155:1
+ --> $DIR/subdiagnostic-derive.rs:159:1
|
LL | #[foo]
| ^^^^^^
error: `#[bar]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:169:5
+ --> $DIR/subdiagnostic-derive.rs:173:5
|
LL | #[bar]
| ^^^^^^
error: `#[bar = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:181:5
+ --> $DIR/subdiagnostic-derive.rs:185:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar = ...]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:193:5
+ --> $DIR/subdiagnostic-derive.rs:197:5
|
LL | #[bar = 4]
| ^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:205:5
+ --> $DIR/subdiagnostic-derive.rs:209:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
-error: diagnostic slug must be first argument of a `#[label(...)]` attribute
- --> $DIR/subdiagnostic-derive.rs:217:5
+error: `#[label(code = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:221:13
|
LL | #[label(code = "...")]
- | ^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^
-error: subdiagnostic kind not specified
- --> $DIR/subdiagnostic-derive.rs:234:5
+error: diagnostic slug must be first argument of a `#[label(...)]` attribute
+ --> $DIR/subdiagnostic-derive.rs:221:5
|
-LL | B {
- | ^
+LL | #[label(code = "...")]
+ | ^^^^^^^^^^^^^^^^^^^^^^
error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
- --> $DIR/subdiagnostic-derive.rs:246:5
+ --> $DIR/subdiagnostic-derive.rs:250:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: label without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:243:1
+ --> $DIR/subdiagnostic-derive.rs:247:1
|
-LL | / #[label(parser::add_paren)]
+LL | / #[label(parser_add_paren)]
LL | |
LL | | struct W {
LL | | #[primary_span]
@@ -137,13 +153,13 @@ LL | | }
| |_^
error: `#[applicability]` is only valid on suggestions
- --> $DIR/subdiagnostic-derive.rs:256:5
+ --> $DIR/subdiagnostic-derive.rs:260:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: `#[bar]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:266:5
+ --> $DIR/subdiagnostic-derive.rs:270:5
|
LL | #[bar]
| ^^^^^^
@@ -151,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:277:5
+ --> $DIR/subdiagnostic-derive.rs:281:5
|
LL | #[bar = "..."]
| ^^^^^^^^^^^^^^
error: `#[bar(...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:288:5
+ --> $DIR/subdiagnostic-derive.rs:292:5
|
LL | #[bar("...")]
| ^^^^^^^^^^^^^
@@ -165,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:304:1
+ --> $DIR/subdiagnostic-derive.rs:308:1
|
LL | / union AC {
LL | |
@@ -174,78 +190,78 @@ LL | | b: u64
LL | | }
| |_^
-error: `#[label(parser::add_paren)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:319:28
+error: `#[label(parser_add_paren)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:323:27
|
-LL | #[label(parser::add_paren, parser::add_paren)]
- | ^^^^^^^^^^^^^^^^^
+LL | #[label(parser_add_paren, parser_add_paren)]
+ | ^^^^^^^^^^^^^^^^
|
= help: a diagnostic slug must be the first argument to the attribute
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:332:5
+ --> $DIR/subdiagnostic-derive.rs:336:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:329:5
+ --> $DIR/subdiagnostic-derive.rs:333:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
error: subdiagnostic kind not specified
- --> $DIR/subdiagnostic-derive.rs:338:8
+ --> $DIR/subdiagnostic-derive.rs:342:8
|
LL | struct AG {
| ^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:375:47
+ --> $DIR/subdiagnostic-derive.rs:379:46
|
-LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:375:33
+ --> $DIR/subdiagnostic-derive.rs:379:32
|
-LL | #[suggestion(parser::add_paren, code = "...", code = "...")]
- | ^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code = "...", code = "...")]
+ | ^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:393:5
+ --> $DIR/subdiagnostic-derive.rs:397:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:390:5
+ --> $DIR/subdiagnostic-derive.rs:394:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
- --> $DIR/subdiagnostic-derive.rs:403:5
+ --> $DIR/subdiagnostic-derive.rs:407:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
error: suggestion without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:416:1
+ --> $DIR/subdiagnostic-derive.rs:420:1
|
-LL | #[suggestion(parser::add_paren)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: invalid applicability
- --> $DIR/subdiagnostic-derive.rs:426:46
+ --> $DIR/subdiagnostic-derive.rs:430:45
|
-LL | #[suggestion(parser::add_paren, code ="...", applicability = "foo")]
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion(parser_add_paren, code ="...", applicability = "foo")]
+ | ^^^^^^^^^^^^^^^^^^^^^
error: suggestion without `#[primary_span]` field
- --> $DIR/subdiagnostic-derive.rs:444:1
+ --> $DIR/subdiagnostic-derive.rs:448:1
|
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[suggestion(parser_add_paren, code = "...")]
LL | |
LL | | struct AR {
LL | | var: String,
@@ -253,25 +269,25 @@ LL | | }
| |_^
error: unsupported type attribute for subdiagnostic enum
- --> $DIR/subdiagnostic-derive.rs:458:1
+ --> $DIR/subdiagnostic-derive.rs:462:1
|
LL | #[label]
| ^^^^^^^^
error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:478:39
+ --> $DIR/subdiagnostic-derive.rs:482:38
|
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
error: `var` doesn't refer to a field on this type
- --> $DIR/subdiagnostic-derive.rs:497:43
+ --> $DIR/subdiagnostic-derive.rs:501:42
|
-LL | #[suggestion(parser::add_paren, code ="{var}", applicability = "machine-applicable")]
- | ^^^^^^^
+LL | #[suggestion(parser_add_paren, code ="{var}", applicability = "machine-applicable")]
+ | ^^^^^^^
error: `#[suggestion_part]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:520:5
+ --> $DIR/subdiagnostic-derive.rs:524:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
@@ -279,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:523:5
+ --> $DIR/subdiagnostic-derive.rs:527:5
|
LL | #[suggestion_part(code = "...")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -287,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:517:1
+ --> $DIR/subdiagnostic-derive.rs:521:1
|
-LL | / #[suggestion(parser::add_paren, code = "...")]
+LL | / #[suggestion(parser_add_paren, code = "...")]
LL | |
LL | | struct BA {
LL | | #[suggestion_part]
@@ -298,16 +314,18 @@ LL | | var: String,
LL | | }
| |_^
-error: `code` is not a valid nested attribute of a `multipart_suggestion` attribute
- --> $DIR/subdiagnostic-derive.rs:532:43
+error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
+ --> $DIR/subdiagnostic-derive.rs:536:42
+ |
+LL | #[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
+ | ^^^^^^^^^^^^
|
-LL | #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
- | ^^^^^^^^^^^^
+ = help: only `applicability` is a valid nested attributes
error: multipart suggestion without any `#[suggestion_part(...)]` fields
- --> $DIR/subdiagnostic-derive.rs:532:1
+ --> $DIR/subdiagnostic-derive.rs:536:1
|
-LL | / #[multipart_suggestion(parser::add_paren, code = "...", applicability = "machine-applicable")]
+LL | / #[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")]
LL | |
LL | |
LL | | struct BBa {
@@ -316,19 +334,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:542:5
+ --> $DIR/subdiagnostic-derive.rs:546:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:550:5
+ --> $DIR/subdiagnostic-derive.rs:554:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[primary_span]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:559:5
+ --> $DIR/subdiagnostic-derive.rs:563:5
|
LL | #[primary_span]
| ^^^^^^^^^^^^^^^
@@ -336,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:556:1
+ --> $DIR/subdiagnostic-derive.rs:560:1
|
-LL | / #[multipart_suggestion(parser::add_paren)]
+LL | / #[multipart_suggestion(parser_add_paren)]
LL | |
LL | | struct BC {
LL | | #[primary_span]
@@ -348,19 +366,19 @@ LL | | }
| |_^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:567:5
+ --> $DIR/subdiagnostic-derive.rs:571:5
|
LL | #[suggestion_part]
| ^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(...)]` attribute without `code = "..."`
- --> $DIR/subdiagnostic-derive.rs:570:5
+ --> $DIR/subdiagnostic-derive.rs:574:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: `#[suggestion_part(foo = ...)]` is not a valid attribute
- --> $DIR/subdiagnostic-derive.rs:573:23
+ --> $DIR/subdiagnostic-derive.rs:577:23
|
LL | #[suggestion_part(foo = "bar")]
| ^^^^^^^^^^^
@@ -368,40 +386,64 @@ 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:576:5
+ --> $DIR/subdiagnostic-derive.rs:580: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:579:5
+ --> $DIR/subdiagnostic-derive.rs:583:5
|
LL | #[suggestion_part()]
| ^^^^^^^^^^^^^^^^^^^^
error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:587:37
+ --> $DIR/subdiagnostic-derive.rs:591:37
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
|
note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:587:23
+ --> $DIR/subdiagnostic-derive.rs:591:23
|
LL | #[suggestion_part(code = "...", code = ",,,")]
| ^^^^^^^^^^^^
-error: specified multiple times
- --> $DIR/subdiagnostic-derive.rs:617:5
+error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
+ --> $DIR/subdiagnostic-derive.rs:620:5
|
LL | #[applicability]
| ^^^^^^^^^^^^^^^^
+
+error: expected exactly one string literal for `code = ...`
+ --> $DIR/subdiagnostic-derive.rs:668:23
|
-note: previously specified here
- --> $DIR/subdiagnostic-derive.rs:614:43
+LL | #[suggestion_part(code("foo"))]
+ | ^^^^^^^^^^^
+
+error: expected exactly one string literal for `code = ...`
+ --> $DIR/subdiagnostic-derive.rs:677:23
+ |
+LL | #[suggestion_part(code("foo", "bar"))]
+ | ^^^^^^^^^^^^^^^^^^
+
+error: expected exactly one string literal for `code = ...`
+ --> $DIR/subdiagnostic-derive.rs:686:23
+ |
+LL | #[suggestion_part(code(3))]
+ | ^^^^^^^
+
+error: expected exactly one string literal for `code = ...`
+ --> $DIR/subdiagnostic-derive.rs:695:23
+ |
+LL | #[suggestion_part(code())]
+ | ^^^^^^
+
+error: `code = "..."`/`code(...)` must contain only string literals
+ --> $DIR/subdiagnostic-derive.rs:704:23
|
-LL | #[multipart_suggestion(parser::add_paren, applicability = "machine-applicable")]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[suggestion_part(code = 3)]
+ | ^^^^^^^^
error: cannot find attribute `foo` in this scope
--> $DIR/subdiagnostic-derive.rs:63:3
@@ -410,59 +452,59 @@ LL | #[foo]
| ^^^
error: cannot find attribute `foo` in this scope
- --> $DIR/subdiagnostic-derive.rs:155:3
+ --> $DIR/subdiagnostic-derive.rs:159:3
|
LL | #[foo]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:169:7
+ --> $DIR/subdiagnostic-derive.rs:173:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:181:7
+ --> $DIR/subdiagnostic-derive.rs:185:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:193:7
+ --> $DIR/subdiagnostic-derive.rs:197:7
|
LL | #[bar = 4]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:205:7
+ --> $DIR/subdiagnostic-derive.rs:209:7
|
LL | #[bar("...")]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:266:7
+ --> $DIR/subdiagnostic-derive.rs:270:7
|
LL | #[bar]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:277:7
+ --> $DIR/subdiagnostic-derive.rs:281:7
|
LL | #[bar = "..."]
| ^^^
error: cannot find attribute `bar` in this scope
- --> $DIR/subdiagnostic-derive.rs:288:7
+ --> $DIR/subdiagnostic-derive.rs:292:7
|
LL | #[bar("...")]
| ^^^
error[E0425]: cannot find value `slug` in module `rustc_errors::fluent`
- --> $DIR/subdiagnostic-derive.rs:118:9
+ --> $DIR/subdiagnostic-derive.rs:122:9
|
LL | #[label(slug)]
| ^^^^ not found in `rustc_errors::fluent`
-error: aborting due to 63 previous errors
+error: aborting due to 72 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/abi/abi-sysv64-register-usage.rs b/src/test/ui/abi/abi-sysv64-register-usage.rs
index 9404e71d0..393306936 100644
--- a/src/test/ui/abi/abi-sysv64-register-usage.rs
+++ b/src/test/ui/abi/abi-sysv64-register-usage.rs
@@ -6,20 +6,30 @@
// ignore-arm
// ignore-aarch64
// needs-asm-support
-#![feature(asm_sym)]
#[cfg(target_arch = "x86_64")]
-pub extern "sysv64" fn all_the_registers(rdi: i64, rsi: i64, rdx: i64,
- rcx: i64, r8 : i64, r9 : i64,
- xmm0: f32, xmm1: f32, xmm2: f32,
- xmm3: f32, xmm4: f32, xmm5: f32,
- xmm6: f32, xmm7: f32) -> i64 {
+pub extern "sysv64" fn all_the_registers(
+ rdi: i64,
+ rsi: i64,
+ rdx: i64,
+ rcx: i64,
+ r8: i64,
+ r9: i64,
+ xmm0: f32,
+ xmm1: f32,
+ xmm2: f32,
+ xmm3: f32,
+ xmm4: f32,
+ xmm5: f32,
+ xmm6: f32,
+ xmm7: f32,
+) -> i64 {
assert_eq!(rdi, 1);
assert_eq!(rsi, 2);
assert_eq!(rdx, 3);
assert_eq!(rcx, 4);
- assert_eq!(r8, 5);
- assert_eq!(r9, 6);
+ assert_eq!(r8, 5);
+ assert_eq!(r9, 6);
assert_eq!(xmm0, 1.0f32);
assert_eq!(xmm1, 2.0f32);
assert_eq!(xmm2, 4.0f32);
diff --git a/src/test/ui/abi/abi-typo-unstable.rs b/src/test/ui/abi/abi-typo-unstable.rs
new file mode 100644
index 000000000..94991a5eb
--- /dev/null
+++ b/src/test/ui/abi/abi-typo-unstable.rs
@@ -0,0 +1,6 @@
+// rust-intrinsic is unstable and not enabled, so it should not be suggested as a fix
+extern "rust-intrinsec" fn rust_intrinsic() {} //~ ERROR invalid ABI
+
+fn main() {
+ rust_intrinsic();
+}
diff --git a/src/test/ui/abi/abi-typo-unstable.stderr b/src/test/ui/abi/abi-typo-unstable.stderr
new file mode 100644
index 000000000..3b346e002
--- /dev/null
+++ b/src/test/ui/abi/abi-typo-unstable.stderr
@@ -0,0 +1,11 @@
+error[E0703]: invalid ABI: found `rust-intrinsec`
+ --> $DIR/abi-typo-unstable.rs:2:8
+ |
+LL | extern "rust-intrinsec" fn rust_intrinsic() {}
+ | ^^^^^^^^^^^^^^^^ invalid ABI
+ |
+ = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/src/test/ui/abi/segfault-no-out-of-stack.rs b/src/test/ui/abi/segfault-no-out-of-stack.rs
index ad4faf95a..ab2b30894 100644
--- a/src/test/ui/abi/segfault-no-out-of-stack.rs
+++ b/src/test/ui/abi/segfault-no-out-of-stack.rs
@@ -3,6 +3,7 @@
#![allow(unused_imports)]
// ignore-emscripten can't run commands
// ignore-sgx no processes
+// ignore-fuchsia must translate zircon signal to SIGSEGV/SIGBUS, FIXME (#58590)
#![feature(rustc_private)]
extern crate libc;
diff --git a/src/test/ui/abi/stack-probes-lto.rs b/src/test/ui/abi/stack-probes-lto.rs
index 90df1f3f5..6d934538f 100644
--- a/src/test/ui/abi/stack-probes-lto.rs
+++ b/src/test/ui/abi/stack-probes-lto.rs
@@ -3,8 +3,6 @@
// ignore-aarch64
// ignore-mips
// ignore-mips64
-// ignore-powerpc
-// ignore-s390x
// ignore-sparc
// ignore-sparc64
// ignore-wasm
@@ -12,6 +10,7 @@
// ignore-sgx no processes
// ignore-musl FIXME #31506
// ignore-pretty
+// ignore-fuchsia no exception handler registered for segfault
// compile-flags: -C lto
// no-prefer-dynamic
diff --git a/src/test/ui/abi/stack-probes.rs b/src/test/ui/abi/stack-probes.rs
index e998dd0f8..e7b91644b 100644
--- a/src/test/ui/abi/stack-probes.rs
+++ b/src/test/ui/abi/stack-probes.rs
@@ -3,13 +3,12 @@
// ignore-aarch64
// ignore-mips
// ignore-mips64
-// ignore-powerpc
-// ignore-s390x
// ignore-sparc
// ignore-sparc64
// ignore-wasm
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia no exception handler registered for segfault
use std::env;
use std::mem::MaybeUninit;
@@ -26,8 +25,9 @@ fn main() {
let args = env::args().skip(1).collect::<Vec<_>>();
if args.len() > 0 {
match &args[0][..] {
- "main-thread" => recurse(&MaybeUninit::uninit()),
- "child-thread" => thread::spawn(|| recurse(&MaybeUninit::uninit())).join().unwrap(),
+ "main-recurse" => overflow_recurse(),
+ "child-recurse" => thread::spawn(overflow_recurse).join().unwrap(),
+ "child-frame" => overflow_frame(),
_ => panic!(),
}
return;
@@ -40,9 +40,10 @@ fn main() {
// that we report stack overflow on the main thread, see #43052 for some
// details
if cfg!(not(target_os = "linux")) {
- assert_overflow(Command::new(&me).arg("main-thread"));
+ assert_overflow(Command::new(&me).arg("main-recurse"));
}
- assert_overflow(Command::new(&me).arg("child-thread"));
+ assert_overflow(Command::new(&me).arg("child-recurse"));
+ assert_overflow(Command::new(&me).arg("child-frame"));
}
#[allow(unconditional_recursion)]
@@ -54,6 +55,23 @@ fn recurse(array: &MaybeUninit<[u64; 1024]>) {
recurse(&local);
}
+#[inline(never)]
+fn overflow_recurse() {
+ recurse(&MaybeUninit::uninit());
+}
+
+fn overflow_frame() {
+ // By using a 1MiB stack frame with only 512KiB stack, we'll jump over any
+ // guard page, even with 64K pages -- but stack probes should catch it.
+ const STACK_SIZE: usize = 512 * 1024;
+ thread::Builder::new().stack_size(STACK_SIZE).spawn(|| {
+ let local: MaybeUninit<[u8; 2 * STACK_SIZE]> = MaybeUninit::uninit();
+ unsafe {
+ black_box(local.as_ptr() as u64);
+ }
+ }).unwrap().join().unwrap();
+}
+
fn assert_overflow(cmd: &mut Command) {
let output = cmd.output().unwrap();
assert!(!output.status.success());
diff --git a/src/test/ui/abi/unsupported.aarch64.stderr b/src/test/ui/abi/unsupported.aarch64.stderr
index a948947db..e86a73ea6 100644
--- a/src/test/ui/abi/unsupported.aarch64.stderr
+++ b/src/test/ui/abi/unsupported.aarch64.stderr
@@ -52,9 +52,9 @@ warning: use of calling convention not supported on this target
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unsupported_calling_conventions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
error: aborting due to 8 previous errors; 1 warning emitted
diff --git a/src/test/ui/abi/unsupported.arm.stderr b/src/test/ui/abi/unsupported.arm.stderr
index 297354c28..f7569c8cd 100644
--- a/src/test/ui/abi/unsupported.arm.stderr
+++ b/src/test/ui/abi/unsupported.arm.stderr
@@ -46,9 +46,9 @@ warning: use of calling convention not supported on this target
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unsupported_calling_conventions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
error: aborting due to 7 previous errors; 1 warning emitted
diff --git a/src/test/ui/abi/unsupported.x64.stderr b/src/test/ui/abi/unsupported.x64.stderr
index 49b88cd3f..26023a458 100644
--- a/src/test/ui/abi/unsupported.x64.stderr
+++ b/src/test/ui/abi/unsupported.x64.stderr
@@ -46,9 +46,9 @@ warning: use of calling convention not supported on this target
LL | extern "stdcall" fn stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unsupported_calling_conventions)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #87678 <https://github.com/rust-lang/rust/issues/87678>
+ = note: `#[warn(unsupported_calling_conventions)]` on by default
error: aborting due to 7 previous errors; 1 warning emitted
diff --git a/src/test/ui/abi/x86stdcall.rs b/src/test/ui/abi/x86stdcall.rs
index 868923e59..d1cf1319f 100644
--- a/src/test/ui/abi/x86stdcall.rs
+++ b/src/test/ui/abi/x86stdcall.rs
@@ -1,17 +1,15 @@
// run-pass
-// ignore-wasm32-bare no libc to test ffi with
-// ignore-sgx no libc
+// only-windows
// GetLastError doesn't seem to work with stack switching
#[cfg(windows)]
mod kernel32 {
- extern "system" {
- pub fn SetLastError(err: usize);
- pub fn GetLastError() -> usize;
- }
+ extern "system" {
+ pub fn SetLastError(err: usize);
+ pub fn GetLastError() -> usize;
+ }
}
-
#[cfg(windows)]
pub fn main() {
unsafe {
@@ -22,17 +20,3 @@ pub fn main() {
assert_eq!(expected, actual);
}
}
-
-#[cfg(any(target_os = "android",
- target_os = "dragonfly",
- target_os = "emscripten",
- target_os = "freebsd",
- target_os = "fuchsia",
- target_os = "illumos",
- target_os = "linux",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd",
- target_os = "solaris",
- target_os = "vxworks"))]
-pub fn main() { }
diff --git a/src/test/ui/abi/x86stdcall2.rs b/src/test/ui/abi/x86stdcall2.rs
index 563e3aba6..4d508ecb2 100644
--- a/src/test/ui/abi/x86stdcall2.rs
+++ b/src/test/ui/abi/x86stdcall2.rs
@@ -1,4 +1,5 @@
// run-pass
+// only-windows
#![allow(non_camel_case_types)]
pub type HANDLE = usize;
@@ -7,20 +8,16 @@ pub type SIZE_T = u32;
pub type LPVOID = usize;
pub type BOOL = u8;
-#[cfg(windows)]
mod kernel32 {
- use super::{HANDLE, DWORD, SIZE_T, LPVOID, BOOL};
+ use super::{BOOL, DWORD, HANDLE, LPVOID, SIZE_T};
extern "system" {
pub fn GetProcessHeap() -> HANDLE;
- pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T)
- -> LPVOID;
+ pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
}
}
-
-#[cfg(windows)]
pub fn main() {
let heap = unsafe { kernel32::GetProcessHeap() };
let mem = unsafe { kernel32::HeapAlloc(heap, 0, 100) };
@@ -28,6 +25,3 @@ pub fn main() {
let res = unsafe { kernel32::HeapFree(heap, 0, mem) };
assert!(res != 0);
}
-
-#[cfg(not(windows))]
-pub fn main() { }
diff --git a/src/test/ui/alloc-error/default-alloc-error-hook.rs b/src/test/ui/alloc-error/default-alloc-error-hook.rs
index 100e97497..8be09500f 100644
--- a/src/test/ui/alloc-error/default-alloc-error-hook.rs
+++ b/src/test/ui/alloc-error/default-alloc-error-hook.rs
@@ -15,5 +15,14 @@ fn main() {
let me = env::current_exe().unwrap();
let output = Command::new(&me).arg("next").output().unwrap();
assert!(!output.status.success(), "{:?} is a success", output.status);
- assert_eq!(str::from_utf8(&output.stderr).unwrap(), "memory allocation of 42 bytes failed\n");
+
+ let mut stderr = str::from_utf8(&output.stderr).unwrap();
+
+ // When running inside QEMU user-mode emulation, there will be an extra message printed by QEMU
+ // in the stderr whenever a core dump happens. Remove it before the check.
+ stderr = stderr
+ .strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n")
+ .unwrap_or(stderr);
+
+ assert_eq!(stderr, "memory allocation of 42 bytes failed\n");
}
diff --git a/src/test/ui/anon-params/anon-params-deprecated.stderr b/src/test/ui/anon-params/anon-params-deprecated.stderr
index 474b14f59..691e2c795 100644
--- a/src/test/ui/anon-params/anon-params-deprecated.stderr
+++ b/src/test/ui/anon-params/anon-params-deprecated.stderr
@@ -4,13 +4,13 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
LL | fn foo(i32);
| ^^^ help: try naming the parameter or explicitly ignoring it: `_: i32`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
note: the lint level is defined here
--> $DIR/anon-params-deprecated.rs:1:9
|
LL | #![warn(anonymous_parameters)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
warning: anonymous parameters are deprecated and will be removed in the next edition
--> $DIR/anon-params-deprecated.rs:12:30
diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
index 1a0a5fdf4..bf5f642ca 100644
--- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr
+++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr
@@ -6,7 +6,7 @@ LL | f1(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r, 's> fn(&'r (), &'s ()) -> _`
+ = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `f1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:25
@@ -22,7 +22,7 @@ LL | f2(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'a, 'r> fn(&'a (), &'r ()) -> _`
+ = note: expected closure signature `for<'a, 'b> fn(&'a (), &'b ()) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `f2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:17:25
@@ -38,7 +38,7 @@ LL | f3(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r> fn(&(), &'r ()) -> _`
+ = note: expected closure signature `for<'a> fn(&(), &'a ()) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `f3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:29
@@ -54,7 +54,7 @@ LL | f4(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r, 's> fn(&'s (), &'r ()) -> _`
+ = note: expected closure signature `for<'r, 'a> fn(&'a (), &'r ()) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `f4`
--> $DIR/anonymous-higher-ranked-lifetime.rs:19:25
@@ -86,7 +86,7 @@ LL | g1(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>) -> _`
+ = note: expected closure signature `for<'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `g1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:23:25
@@ -102,7 +102,7 @@ LL | g2(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r> fn(&'r (), for<'r> fn(&'r ())) -> _`
+ = note: expected closure signature `for<'a> fn(&'a (), for<'a> fn(&'a ())) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `g2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:24:25
@@ -118,7 +118,7 @@ LL | g3(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>) -> _`
+ = note: expected closure signature `for<'s> fn(&'s (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `g3`
--> $DIR/anonymous-higher-ranked-lifetime.rs:25:25
@@ -134,7 +134,7 @@ LL | g4(|_: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
+ = note: expected closure signature `for<'a> fn(&'a (), for<'r> fn(&'r ())) -> _`
found closure signature `fn((), ()) -> _`
note: required by a bound in `g4`
--> $DIR/anonymous-higher-ranked-lifetime.rs:26:25
@@ -150,7 +150,7 @@ LL | h1(|_: (), _: (), _: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'r, 's> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>, &'s (), for<'r, 's> fn(&'r (), &'s ())) -> _`
+ = note: expected closure signature `for<'a, 'b> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'b (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
found closure signature `fn((), (), (), ()) -> _`
note: required by a bound in `h1`
--> $DIR/anonymous-higher-ranked-lifetime.rs:29:25
@@ -166,7 +166,7 @@ LL | h2(|_: (), _: (), _: (), _: ()| {});
| |
| expected due to this
|
- = note: expected closure signature `for<'t0, 'r> fn(&'r (), Box<(dyn for<'r> Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _`
+ = note: expected closure signature `for<'t0, 'a> fn(&'a (), Box<(dyn for<'a> Fn(&'a ()) + 'static)>, &'t0 (), for<'a, 'b> fn(&'a (), &'b ())) -> _`
found closure signature `fn((), (), (), ()) -> _`
note: required by a bound in `h2`
--> $DIR/anonymous-higher-ranked-lifetime.rs:30:25
diff --git a/src/test/ui/array-slice-vec/array_const_index-0.rs b/src/test/ui/array-slice-vec/array_const_index-0.rs
index 9ff7e2c56..96755802e 100644
--- a/src/test/ui/array-slice-vec/array_const_index-0.rs
+++ b/src/test/ui/array-slice-vec/array_const_index-0.rs
@@ -1,8 +1,7 @@
const A: &'static [i32] = &[];
const B: i32 = (&A)[1];
//~^ index out of bounds: the length is 0 but the index is 1
-//~| ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~| ERROR evaluation of constant value failed
fn main() {
let _ = B;
diff --git a/src/test/ui/array-slice-vec/array_const_index-0.stderr b/src/test/ui/array-slice-vec/array_const_index-0.stderr
index 483239871..3b92cc766 100644
--- a/src/test/ui/array-slice-vec/array_const_index-0.stderr
+++ b/src/test/ui/array-slice-vec/array_const_index-0.stderr
@@ -1,23 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/array_const_index-0.rs:2:16
|
LL | const B: i32 = (&A)[1];
- | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^ index out of bounds: the length is 0 but the index is 1
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/array_const_index-0.rs:2:16
- |
-LL | const B: i32 = (&A)[1];
- | ------------ ^^^^^^^ index out of bounds: the length is 0 but the index is 1
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/array-slice-vec/array_const_index-1.rs b/src/test/ui/array-slice-vec/array_const_index-1.rs
index f4326189c..625bf06a7 100644
--- a/src/test/ui/array-slice-vec/array_const_index-1.rs
+++ b/src/test/ui/array-slice-vec/array_const_index-1.rs
@@ -1,8 +1,7 @@
const A: [i32; 0] = [];
const B: i32 = A[1];
//~^ index out of bounds: the length is 0 but the index is 1
-//~| ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~| ERROR evaluation of constant value failed
fn main() {
let _ = B;
diff --git a/src/test/ui/array-slice-vec/array_const_index-1.stderr b/src/test/ui/array-slice-vec/array_const_index-1.stderr
index 361f518c0..591db268a 100644
--- a/src/test/ui/array-slice-vec/array_const_index-1.stderr
+++ b/src/test/ui/array-slice-vec/array_const_index-1.stderr
@@ -1,23 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/array_const_index-1.rs:2:16
|
LL | const B: i32 = A[1];
- | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^ index out of bounds: the length is 0 but the index is 1
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/array_const_index-1.rs:2:16
- |
-LL | const B: i32 = A[1];
- | ------------ ^^^^ index out of bounds: the length is 0 but the index is 1
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/asm/aarch64/bad-reg.rs b/src/test/ui/asm/aarch64/bad-reg.rs
index 2b6a9b71c..9ccb8ed67 100644
--- a/src/test/ui/asm/aarch64/bad-reg.rs
+++ b/src/test/ui/asm/aarch64/bad-reg.rs
@@ -1,7 +1,7 @@
// only-aarch64
// compile-flags: -C target-feature=+neon
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::asm;
diff --git a/src/test/ui/asm/aarch64/may_unwind.rs b/src/test/ui/asm/aarch64/may_unwind.rs
index dfd891b42..6af8728bb 100644
--- a/src/test/ui/asm/aarch64/may_unwind.rs
+++ b/src/test/ui/asm/aarch64/may_unwind.rs
@@ -2,7 +2,7 @@
// run-pass
// needs-asm-support
-#![feature(asm_sym, asm_unwind)]
+#![feature(asm_unwind)]
use std::arch::asm;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
diff --git a/src/test/ui/asm/aarch64/sym.rs b/src/test/ui/asm/aarch64/sym.rs
index 3f659363c..6a6cdb00d 100644
--- a/src/test/ui/asm/aarch64/sym.rs
+++ b/src/test/ui/asm/aarch64/sym.rs
@@ -3,7 +3,7 @@
// needs-asm-support
// run-pass
-#![feature(thread_local, asm_sym)]
+#![feature(thread_local)]
use std::arch::asm;
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.rs b/src/test/ui/asm/aarch64/type-check-2-2.rs
index aa12d4aa4..0ce1f1d8f 100644
--- a/src/test/ui/asm/aarch64/type-check-2-2.rs
+++ b/src/test/ui/asm/aarch64/type-check-2-2.rs
@@ -1,6 +1,6 @@
// only-aarch64
-#![feature(repr_simd, never_type, asm_sym)]
+#![feature(repr_simd, never_type)]
use std::arch::{asm, global_asm};
diff --git a/src/test/ui/asm/aarch64/type-check-2-2.stderr b/src/test/ui/asm/aarch64/type-check-2-2.stderr
index b2a695529..eef16a165 100644
--- a/src/test/ui/asm/aarch64/type-check-2-2.stderr
+++ b/src/test/ui/asm/aarch64/type-check-2-2.stderr
@@ -5,6 +5,11 @@ LL | let x: u64;
| - binding declared here but left uninitialized
LL | asm!("{}", in(reg) x);
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: u64 = 0;
+ | +++
error[E0381]: used binding `y` isn't initialized
--> $DIR/type-check-2-2.rs:22:9
@@ -13,6 +18,11 @@ LL | let mut y: u64;
| ----- binding declared here but left uninitialized
LL | asm!("{}", inout(reg) y);
| ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut y: u64 = 0;
+ | +++
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-2-2.rs:30:29
diff --git a/src/test/ui/asm/aarch64/type-check-2.rs b/src/test/ui/asm/aarch64/type-check-2.rs
index fdafe63c7..1c71c1185 100644
--- a/src/test/ui/asm/aarch64/type-check-2.rs
+++ b/src/test/ui/asm/aarch64/type-check-2.rs
@@ -1,6 +1,6 @@
// only-aarch64
-#![feature(repr_simd, never_type, asm_sym)]
+#![feature(repr_simd, never_type)]
use std::arch::{asm, global_asm};
diff --git a/src/test/ui/asm/aarch64/type-check-3.stderr b/src/test/ui/asm/aarch64/type-check-3.stderr
index 49292982e..f710df2dc 100644
--- a/src/test/ui/asm/aarch64/type-check-3.stderr
+++ b/src/test/ui/asm/aarch64/type-check-3.stderr
@@ -4,9 +4,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{}", in(reg) 0u8);
| ^^ --- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
+ = note: `#[warn(asm_sub_register)]` on by default
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:50:15
diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
index 5dac693cc..bb6a222b2 100644
--- a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr
@@ -189,9 +189,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
+ = note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted
diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
index 5dac693cc..bb6a222b2 100644
--- a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr
@@ -189,9 +189,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:w}` to have the register formatted as `w0`
= help: or use `{0:x}` to keep the default formatting of `x0`
+ = note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted
diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
index b29b74bac..903b5e959 100644
--- a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr
@@ -189,9 +189,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:e}` to have the register formatted as `eax`
= help: or use `{0:r}` to keep the default formatting of `rax`
+ = note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted
diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
index b29b74bac..903b5e959 100644
--- a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
+++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr
@@ -189,9 +189,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{:foo}", in(reg) foo);
| ^^^^^^ --- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:e}` to have the register formatted as `eax`
= help: or use `{0:r}` to keep the default formatting of `rax`
+ = note: `#[warn(asm_sub_register)]` on by default
error: aborting due to 21 previous errors; 1 warning emitted
diff --git a/src/test/ui/asm/generic-const.rs b/src/test/ui/asm/generic-const.rs
index 55c558780..caa9b7dbc 100644
--- a/src/test/ui/asm/generic-const.rs
+++ b/src/test/ui/asm/generic-const.rs
@@ -1,7 +1,7 @@
// needs-asm-support
// build-pass
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::asm;
diff --git a/src/test/ui/asm/naked-functions-ffi.stderr b/src/test/ui/asm/naked-functions-ffi.stderr
index ac7435513..908881b19 100644
--- a/src/test/ui/asm/naked-functions-ffi.stderr
+++ b/src/test/ui/asm/naked-functions-ffi.stderr
@@ -4,9 +4,9 @@ warning: `extern` fn uses type `char`, which is not FFI-safe
LL | pub extern "C" fn naked(p: char) -> u128 {
| ^^^^ not FFI-safe
|
- = note: `#[warn(improper_ctypes_definitions)]` on by default
= help: consider using `u32` or `libc::wchar_t` instead
= note: the `char` type has no C equivalent
+ = note: `#[warn(improper_ctypes_definitions)]` on by default
warning: `extern` fn uses type `u128`, which is not FFI-safe
--> $DIR/naked-functions-ffi.rs:9:37
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
index 9e626f571..2f3716ca7 100644
--- a/src/test/ui/asm/naked-functions.rs
+++ b/src/test/ui/asm/naked-functions.rs
@@ -4,7 +4,7 @@
// ignore-wasm32
#![feature(naked_functions)]
-#![feature(asm_const, asm_sym, asm_unwind)]
+#![feature(asm_const, asm_unwind)]
#![crate_type = "lib"]
use std::arch::asm;
diff --git a/src/test/ui/asm/named-asm-labels.stderr b/src/test/ui/asm/named-asm-labels.stderr
index 001601497..c8380629e 100644
--- a/src/test/ui/asm/named-asm-labels.stderr
+++ b/src/test/ui/asm/named-asm-labels.stderr
@@ -4,9 +4,9 @@ error: avoid using named labels in inline assembly
LL | asm!("bar: nop");
| ^^^
|
- = note: `#[deny(named_asm_labels)]` on by default
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
+ = note: `#[deny(named_asm_labels)]` on by default
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:27:15
@@ -259,13 +259,13 @@ warning: avoid using named labels in inline assembly
LL | asm!("warned: nop");
| ^^^^^^
|
+ = help: only local labels of the form `<number>:` should be used in inline asm
+ = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
note: the lint level is defined here
--> $DIR/named-asm-labels.rs:132:16
|
LL | #[warn(named_asm_labels)]
| ^^^^^^^^^^^^^^^^
- = help: only local labels of the form `<number>:` should be used in inline asm
- = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:143:20
diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs
index 50b369ae0..59f7b36af 100644
--- a/src/test/ui/asm/type-check-1.rs
+++ b/src/test/ui/asm/type-check-1.rs
@@ -3,7 +3,7 @@
// ignore-spirv
// ignore-wasm32
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::{asm, global_asm};
diff --git a/src/test/ui/asm/unpretty-expanded.rs b/src/test/ui/asm/unpretty-expanded.rs
index 6128f49b8..25cf1c3d7 100644
--- a/src/test/ui/asm/unpretty-expanded.rs
+++ b/src/test/ui/asm/unpretty-expanded.rs
@@ -1,3 +1,4 @@
+// needs-asm-support
// check-pass
// compile-flags: -Zunpretty=expanded
core::arch::global_asm!("x: .byte 42");
diff --git a/src/test/ui/asm/unpretty-expanded.stdout b/src/test/ui/asm/unpretty-expanded.stdout
index 15b60d155..ab1b5f45e 100644
--- a/src/test/ui/asm/unpretty-expanded.stdout
+++ b/src/test/ui/asm/unpretty-expanded.stdout
@@ -4,6 +4,7 @@
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
+// needs-asm-support
// check-pass
// compile-flags: -Zunpretty=expanded
global_asm! ("x: .byte 42");
diff --git a/src/test/ui/asm/x86_64/bad-reg.rs b/src/test/ui/asm/x86_64/bad-reg.rs
index a4f50a534..f5728079a 100644
--- a/src/test/ui/asm/x86_64/bad-reg.rs
+++ b/src/test/ui/asm/x86_64/bad-reg.rs
@@ -1,7 +1,7 @@
// only-x86_64
// compile-flags: -C target-feature=+avx2
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::asm;
diff --git a/src/test/ui/asm/x86_64/issue-96797.rs b/src/test/ui/asm/x86_64/issue-96797.rs
index d3e0906f3..954f8c5cc 100644
--- a/src/test/ui/asm/x86_64/issue-96797.rs
+++ b/src/test/ui/asm/x86_64/issue-96797.rs
@@ -7,8 +7,6 @@
// regression test for #96797
-#![feature(asm_sym)]
-
use std::arch::global_asm;
#[no_mangle]
diff --git a/src/test/ui/asm/x86_64/may_unwind.rs b/src/test/ui/asm/x86_64/may_unwind.rs
index 2f5d1a360..c11f0938d 100644
--- a/src/test/ui/asm/x86_64/may_unwind.rs
+++ b/src/test/ui/asm/x86_64/may_unwind.rs
@@ -3,7 +3,7 @@
// needs-asm-support
// needs-unwind
-#![feature(asm_sym, asm_unwind)]
+#![feature(asm_unwind)]
use std::arch::asm;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
diff --git a/src/test/ui/asm/x86_64/multiple-clobber-abi.rs b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
index 513eb270e..06589431a 100644
--- a/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
+++ b/src/test/ui/asm/x86_64/multiple-clobber-abi.rs
@@ -4,8 +4,6 @@
// Checks that multiple clobber_abi options can be used
-#![feature(asm_sym)]
-
use std::arch::asm;
extern "sysv64" fn foo(x: i32) -> i32 {
diff --git a/src/test/ui/asm/x86_64/sym.rs b/src/test/ui/asm/x86_64/sym.rs
index 447e11e6e..93ef4f090 100644
--- a/src/test/ui/asm/x86_64/sym.rs
+++ b/src/test/ui/asm/x86_64/sym.rs
@@ -3,7 +3,7 @@
// needs-asm-support
// run-pass
-#![feature(thread_local, asm_sym)]
+#![feature(thread_local)]
use std::arch::asm;
diff --git a/src/test/ui/asm/x86_64/type-check-2.rs b/src/test/ui/asm/x86_64/type-check-2.rs
index 59d8cde3f..80b29ec87 100644
--- a/src/test/ui/asm/x86_64/type-check-2.rs
+++ b/src/test/ui/asm/x86_64/type-check-2.rs
@@ -1,6 +1,6 @@
// only-x86_64
-#![feature(repr_simd, never_type, asm_sym)]
+#![feature(repr_simd, never_type)]
use std::arch::{asm, global_asm};
diff --git a/src/test/ui/asm/x86_64/type-check-3.stderr b/src/test/ui/asm/x86_64/type-check-3.stderr
index 366038fea..1baf50ff6 100644
--- a/src/test/ui/asm/x86_64/type-check-3.stderr
+++ b/src/test/ui/asm/x86_64/type-check-3.stderr
@@ -44,9 +44,9 @@ warning: formatting may not be suitable for sub-register argument
LL | asm!("{0} {0}", in(reg) 0i16);
| ^^^ ^^^ ---- for this argument
|
- = note: `#[warn(asm_sub_register)]` on by default
= help: use `{0:x}` to have the register formatted as `ax`
= help: or use `{0:r}` to keep the default formatting of `rax`
+ = note: `#[warn(asm_sub_register)]` on by default
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:36:15
diff --git a/src/test/ui/asm/x86_64/type-check-4.rs b/src/test/ui/asm/x86_64/type-check-4.rs
index da3b76c3d..3d5d3807c 100644
--- a/src/test/ui/asm/x86_64/type-check-4.rs
+++ b/src/test/ui/asm/x86_64/type-check-4.rs
@@ -1,14 +1,13 @@
// only-x86_64
// compile-flags: -C target-feature=+avx512f
-#![feature(asm_const, asm_sym)]
+#![feature(asm_const)]
use std::arch::{asm, global_asm};
use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
-fn main() {
-}
+fn main() {}
// Constants must be... constant
diff --git a/src/test/ui/asm/x86_64/type-check-4.stderr b/src/test/ui/asm/x86_64/type-check-4.stderr
index 33f4638fb..3875bcc21 100644
--- a/src/test/ui/asm/x86_64/type-check-4.stderr
+++ b/src/test/ui/asm/x86_64/type-check-4.stderr
@@ -1,5 +1,5 @@
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-4.rs:22:25
+ --> $DIR/type-check-4.rs:21:25
|
LL | global_asm!("{}", const S);
| ^
@@ -7,7 +7,7 @@ LL | global_asm!("{}", const S);
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-4.rs:25:35
+ --> $DIR/type-check-4.rs:24:35
|
LL | global_asm!("{}", const const_foo(S));
| ^
@@ -15,7 +15,7 @@ LL | global_asm!("{}", const const_foo(S));
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
- --> $DIR/type-check-4.rs:28:35
+ --> $DIR/type-check-4.rs:27:35
|
LL | global_asm!("{}", const const_bar(S));
| ^
diff --git a/src/test/ui/asm/x86_64/type-check-5.rs b/src/test/ui/asm/x86_64/type-check-5.rs
index 6190e0b52..8198df910 100644
--- a/src/test/ui/asm/x86_64/type-check-5.rs
+++ b/src/test/ui/asm/x86_64/type-check-5.rs
@@ -1,6 +1,6 @@
// only-x86_64
-#![feature(repr_simd, never_type, asm_sym)]
+#![feature(repr_simd, never_type)]
use std::arch::asm;
diff --git a/src/test/ui/asm/x86_64/type-check-5.stderr b/src/test/ui/asm/x86_64/type-check-5.stderr
index e9c93fea5..bd90461e5 100644
--- a/src/test/ui/asm/x86_64/type-check-5.stderr
+++ b/src/test/ui/asm/x86_64/type-check-5.stderr
@@ -5,6 +5,11 @@ LL | let x: u64;
| - binding declared here but left uninitialized
LL | asm!("{}", in(reg) x);
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: u64 = 0;
+ | +++
error[E0381]: used binding `y` isn't initialized
--> $DIR/type-check-5.rs:18:9
@@ -13,6 +18,11 @@ LL | let mut y: u64;
| ----- binding declared here but left uninitialized
LL | asm!("{}", inout(reg) y);
| ^^^^^^^^^^^^^^^^^^^^^^^^ `y` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut y: u64 = 0;
+ | +++
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-5.rs:26:29
diff --git a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
index de1d9589e..742b81535 100644
--- a/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
+++ b/src/test/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
@@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait
--> $DIR/associated-const-impl-wrong-lifetime.rs:7:5
|
LL | const NAME: &'a str = "unit";
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected reference `&'static str`
found reference `&'a str`
diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs
index 3936e6a3b..6762d7583 100644
--- a/src/test/ui/associated-consts/defaults-not-assumed-fail.rs
+++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.rs
@@ -6,8 +6,7 @@ trait Tr {
// This should not be a constant evaluation error (overflow). The value of
// `Self::A` must not be assumed to hold inside the trait.
const B: u8 = Self::A + 1;
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of `<() as Tr>::B` failed
}
// An impl that doesn't override any constant will NOT cause a const eval error
@@ -34,7 +33,6 @@ fn main() {
assert_eq!(<() as Tr>::B, 0); // causes the error above
//~^ ERROR evaluation of constant value failed
//~| ERROR erroneous constant used
- //~| WARN this was previously accepted by the compiler but is being phased out
assert_eq!(<u8 as Tr>::A, 254);
assert_eq!(<u8 as Tr>::B, 255);
diff --git a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
index 66ee6031c..aa130f438 100644
--- a/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
+++ b/src/test/ui/associated-consts/defaults-not-assumed-fail.stderr
@@ -1,52 +1,23 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of `<() as Tr>::B` failed
--> $DIR/defaults-not-assumed-fail.rs:8:19
|
LL | const B: u8 = Self::A + 1;
- | ----------- ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
error[E0080]: evaluation of constant value failed
- --> $DIR/defaults-not-assumed-fail.rs:34:16
+ --> $DIR/defaults-not-assumed-fail.rs:33:16
|
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
| ^^^^^^^^^^^^^ referenced constant has errors
-error: erroneous constant used
- --> $DIR/defaults-not-assumed-fail.rs:34:5
+error[E0080]: erroneous constant used
+ --> $DIR/defaults-not-assumed-fail.rs:33:5
|
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/defaults-not-assumed-fail.rs:8:19
- |
-LL | const B: u8 = Self::A + 1;
- | ----------- ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/defaults-not-assumed-fail.rs:34:5
- |
-LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_1.rs b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs
new file mode 100644
index 000000000..4dc6c2e47
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_1.rs
@@ -0,0 +1,18 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ type ArrayType;
+ const SIZE: usize;
+ const ARRAY: Self::ArrayType;
+}
+impl MyTrait for () {
+ type ArrayType = [u8; Self::SIZE];
+ const SIZE: usize = 4;
+ const ARRAY: [u8; Self::SIZE] = [1, 2, 3, 4];
+}
+
+fn main() {
+ let _ = <() as MyTrait>::ARRAY;
+}
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_2.rs b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs
new file mode 100644
index 000000000..539becfdc
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_2.rs
@@ -0,0 +1,11 @@
+// run-pass
+trait Trait {
+ const ASSOC: fn(&'static u32);
+}
+impl Trait for () {
+ const ASSOC: for<'a> fn(&'a u32) = |_| ();
+}
+
+fn main() {
+ let _ = <() as Trait>::ASSOC;
+}
diff --git a/src/test/ui/associated-consts/mismatched_impl_ty_3.rs b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs
new file mode 100644
index 000000000..17bcc8fe5
--- /dev/null
+++ b/src/test/ui/associated-consts/mismatched_impl_ty_3.rs
@@ -0,0 +1,11 @@
+// run-pass
+trait Trait {
+ const ASSOC: for<'a, 'b> fn(&'a u32, &'b u32);
+}
+impl Trait for () {
+ const ASSOC: for<'a> fn(&'a u32, &'a u32) = |_, _| ();
+}
+
+fn main() {
+ let _ = <() as Trait>::ASSOC;
+}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
index f4efd1312..0b96a6bd7 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr
@@ -1,11 +1,11 @@
-error[E0201]: duplicate definitions with name `bar`:
+error[E0592]: duplicate definitions with name `bar`
--> $DIR/associated-item-duplicate-names-2.rs:5:5
|
LL | const bar: bool = true;
- | --------------- previous definition of `bar` here
+ | --------------- other definition for `bar`
LL | fn bar() {}
- | ^^^^^^^^ duplicate definition
+ | ^^^^^^^^ duplicate definitions for `bar`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0201`.
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.rs b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
index 6aa1b483e..3a70a2f94 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.rs
@@ -16,4 +16,5 @@ impl Foo for Baz {
fn main() {
let x: Baz::Bar = 5;
+ //~^ ERROR ambiguous associated type
}
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
index 03782f663..bf4bd634c 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names-3.stderr
@@ -1,11 +1,21 @@
error[E0201]: duplicate definitions with name `Bar`:
--> $DIR/associated-item-duplicate-names-3.rs:14:5
|
+LL | type Bar;
+ | --------- item in trait
+...
LL | type Bar = i16;
- | -------- previous definition of `Bar` here
+ | --------------- previous definition here
LL | type Bar = u16;
- | ^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^ duplicate definition
-error: aborting due to previous error
+error[E0223]: ambiguous associated type
+ --> $DIR/associated-item-duplicate-names-3.rs:18:12
+ |
+LL | let x: Baz::Bar = 5;
+ | ^^^^^^^^ help: use fully-qualified syntax: `<Baz as Trait>::Bar`
+
+error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0201`.
+Some errors have detailed explanations: E0201, E0223.
+For more information about an error, try `rustc --explain E0201`.
diff --git a/src/test/ui/associated-item/associated-item-duplicate-names.stderr b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
index c9119c102..f89ea6e57 100644
--- a/src/test/ui/associated-item/associated-item-duplicate-names.stderr
+++ b/src/test/ui/associated-item/associated-item-duplicate-names.stderr
@@ -1,18 +1,24 @@
error[E0201]: duplicate definitions with name `Ty`:
--> $DIR/associated-item-duplicate-names.rs:11:5
|
+LL | type Ty;
+ | -------- item in trait
+...
LL | type Ty = ();
- | ------- previous definition of `Ty` here
+ | ------------- previous definition here
LL | type Ty = usize;
- | ^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^ duplicate definition
error[E0201]: duplicate definitions with name `BAR`:
--> $DIR/associated-item-duplicate-names.rs:13:5
|
+LL | const BAR: u32;
+ | --------------- item in trait
+...
LL | const BAR: u32 = 7;
- | -------------- previous definition of `BAR` here
+ | ------------------- previous definition here
LL | const BAR: u32 = 8;
- | ^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^^^^ duplicate definition
error: aborting due to 2 previous errors
diff --git a/src/test/ui/impl-duplicate-methods.rs b/src/test/ui/associated-item/impl-duplicate-methods.rs
index adb09d7f5..328d54d5a 100644
--- a/src/test/ui/impl-duplicate-methods.rs
+++ b/src/test/ui/associated-item/impl-duplicate-methods.rs
@@ -3,7 +3,7 @@ struct Foo;
impl Foo {
fn orange(&self) {}
fn orange(&self) {}
- //~^ ERROR duplicate definition
+ //~^ ERROR duplicate definitions with name `orange` [E0592]
}
fn main() {}
diff --git a/src/test/ui/associated-item/impl-duplicate-methods.stderr b/src/test/ui/associated-item/impl-duplicate-methods.stderr
new file mode 100644
index 000000000..6f753845a
--- /dev/null
+++ b/src/test/ui/associated-item/impl-duplicate-methods.stderr
@@ -0,0 +1,11 @@
+error[E0592]: duplicate definitions with name `orange`
+ --> $DIR/impl-duplicate-methods.rs:5:5
+ |
+LL | fn orange(&self) {}
+ | ---------------- other definition for `orange`
+LL | fn orange(&self) {}
+ | ^^^^^^^^^^^^^^^^ duplicate definitions for `orange`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/associated-type-bounds/inside-adt.rs b/src/test/ui/associated-type-bounds/inside-adt.rs
index f26037f07..8eb8c44bb 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.rs
+++ b/src/test/ui/associated-type-bounds/inside-adt.rs
@@ -16,7 +16,7 @@ enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
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)`
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
union U1 { f: ManuallyDrop<dyn Iterator<Item: Copy>> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
@@ -25,6 +25,6 @@ union U2 { f: ManuallyDrop<Box<dyn Iterator<Item: Copy>>> }
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
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)`
+//~| ERROR the size for values of type `(dyn Iterator<Item = impl Sized + 'static> + 'static)`
fn main() {}
diff --git a/src/test/ui/associated-type-bounds/inside-adt.stderr b/src/test/ui/associated-type-bounds/inside-adt.stderr
index 978390fa7..dbfcfa580 100644
--- a/src/test/ui/associated-type-bounds/inside-adt.stderr
+++ b/src/test/ui/associated-type-bounds/inside-adt.stderr
@@ -70,13 +70,13 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | enum E1 { V(Box<dyn Iterator<Item: Copy>>) }
| ++++ +
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+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)`
+ = 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
@@ -107,14 +107,14 @@ help: the `Box` type always has a statically known size and allocates its conten
LL | union U1 { f: Box<ManuallyDrop<dyn Iterator<Item: Copy>>> }
| ++++ +
-error[E0277]: the size for values of type `(dyn Iterator<Item = impl Sized> + 'static)` cannot be known at compilation time
+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)>`, the trait `Sized` is not implemented for `(dyn Iterator<Item = impl Sized> + 'static)`
- = note: required because it appears within the type `ManuallyDrop<(dyn Iterator<Item = impl Sized> + 'static)>`
+ = 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
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
index cc1560162..77841780f 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr
@@ -15,19 +15,19 @@ LL | let a = bar(f, x);
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough
- --> $DIR/project-fn-ret-invariant.rs:40:13
+ --> $DIR/project-fn-ret-invariant.rs:42:13
|
LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
-LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
-LL | let a = bar(f, x);
+...
+LL | let b = bar(f, y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`
- = note: requirement occurs because of a function pointer to `foo`
- = note: the function `foo` is invariant over the parameter `'a`
+ = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
+ = note: the struct `Type<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: `'a` and `'b` must be the same: replace one with the other
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
index 1075fd6e0..e04337913 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.rs
@@ -39,8 +39,8 @@ fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
let f = foo; // <-- No consistent type can be inferred for `f` here.
let a = bar(f, x);
//[oneuse]~^ ERROR lifetime may not live long enough
- //[oneuse]~| ERROR lifetime may not live long enough
let b = bar(f, y);
+ //[oneuse]~^ ERROR lifetime may not live long enough
(a, b)
}
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
index 2d61b2a64..8df326351 100644
--- a/src/test/ui/associated-types/defaults-specialization.stderr
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(associated_type_defaults, specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0053]: method `make` has an incompatible type for trait
--> $DIR/defaults-specialization.rs:19:18
diff --git a/src/test/ui/associated-types/issue-85103.rs b/src/test/ui/associated-types/issue-85103.rs
index c5e138561..9c6a419e9 100644
--- a/src/test/ui/associated-types/issue-85103.rs
+++ b/src/test/ui/associated-types/issue-85103.rs
@@ -4,6 +4,6 @@ use std::borrow::Cow;
#[rustc_layout(debug)]
type Edges<'a, E> = Cow<'a, [E]>;
-//~^ ERROR layout error: NormalizationFailure
+//~^ 6:1: 6:18: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized
fn main() {}
diff --git a/src/test/ui/associated-types/issue-85103.stderr b/src/test/ui/associated-types/issue-85103.stderr
index bddd1dce8..17f714807 100644
--- a/src/test/ui/associated-types/issue-85103.stderr
+++ b/src/test/ui/associated-types/issue-85103.stderr
@@ -1,4 +1,4 @@
-error: layout error: NormalizationFailure(<[E] as std::borrow::ToOwned>::Owned, Type(<[E] as std::borrow::ToOwned>::Owned))
+error: unable to determine layout for `<[E] as ToOwned>::Owned` because `<[E] as ToOwned>::Owned` cannot be normalized
--> $DIR/issue-85103.rs:6:1
|
LL | type Edges<'a, E> = Cow<'a, [E]>;
diff --git a/src/test/ui/associated-types/issue-87261.rs b/src/test/ui/associated-types/issue-87261.rs
index 384561f8c..e8548d402 100644
--- a/src/test/ui/associated-types/issue-87261.rs
+++ b/src/test/ui/associated-types/issue-87261.rs
@@ -77,10 +77,10 @@ where
fn main() {
accepts_trait(returns_opaque());
- //~^ ERROR type mismatch resolving `<impl Trait as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
accepts_trait(returns_opaque_derived());
- //~^ ERROR type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl DerivedTrait + 'static 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<()> as GenericTrait<()>>::Associated == ()`
+ //~^ ERROR type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
accepts_generic_trait(returns_opaque_generic_foo());
//~^ ERROR type mismatch resolving `<impl GenericTrait<()> + Foo as GenericTrait<()>>::Associated == ()`
diff --git a/src/test/ui/associated-types/issue-87261.stderr b/src/test/ui/associated-types/issue-87261.stderr
index f24423dd1..2cce6b947 100644
--- a/src/test/ui/associated-types/issue-87261.stderr
+++ b/src/test/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 as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl Trait + 'static as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:79:19
|
LL | fn returns_opaque() -> impl Trait + 'static {
@@ -144,18 +144,18 @@ LL | accepts_trait(returns_opaque());
| required by a bound introduced by this call
|
= note: expected unit type `()`
- found associated type `<impl Trait as Trait>::Associated`
+ found associated type `<impl Trait + 'static as Trait>::Associated`
note: required by a bound in `accepts_trait`
--> $DIR/issue-87261.rs:43:27
|
LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-help: consider constraining the associated type `<impl Trait as Trait>::Associated` to `()`
+help: consider constraining the associated type `<impl Trait + 'static as Trait>::Associated` to `()`
|
LL | fn returns_opaque() -> impl Trait<Associated = ()> + 'static {
| +++++++++++++++++
-error[E0271]: type mismatch resolving `<impl DerivedTrait as Trait>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl DerivedTrait + 'static as Trait>::Associated == ()`
--> $DIR/issue-87261.rs:82:19
|
LL | fn returns_opaque_derived() -> impl DerivedTrait + 'static {
@@ -167,13 +167,13 @@ LL | accepts_trait(returns_opaque_derived());
| required by a bound introduced by this call
|
= note: expected unit type `()`
- found associated type `<impl DerivedTrait as Trait>::Associated`
+ found associated type `<impl DerivedTrait + 'static as Trait>::Associated`
note: required by a bound in `accepts_trait`
--> $DIR/issue-87261.rs:43:27
|
LL | fn accepts_trait<T: Trait<Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_trait`
-help: consider constraining the associated type `<impl DerivedTrait as Trait>::Associated` to `()`
+help: consider constraining the associated type `<impl DerivedTrait + 'static as Trait>::Associated` to `()`
|
LL | fn returns_opaque_derived() -> impl DerivedTrait<Associated = ()> + '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<()> as GenericTrait<()>>::Associated == ()`
+error[E0271]: type mismatch resolving `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated == ()`
--> $DIR/issue-87261.rs:91:27
|
LL | fn returns_opaque_generic() -> impl GenericTrait<()> + 'static {
@@ -234,13 +234,13 @@ LL | accepts_generic_trait(returns_opaque_generic());
| required by a bound introduced by this call
|
= note: expected unit type `()`
- found associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated`
+ found associated type `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated`
note: required by a bound in `accepts_generic_trait`
--> $DIR/issue-87261.rs:44:46
|
LL | fn accepts_generic_trait<T: GenericTrait<(), Associated = ()>>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `accepts_generic_trait`
-help: consider constraining the associated type `<impl GenericTrait<()> as GenericTrait<()>>::Associated` to `()`
+help: consider constraining the associated type `<impl GenericTrait<()> + 'static as GenericTrait<()>>::Associated` to `()`
|
LL | fn returns_opaque_generic() -> impl GenericTrait<(), Associated = ()> + 'static {
| +++++++++++++++++
diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr
index 40ad46b48..a7b872fe4 100644
--- a/src/test/ui/async-await/async-fn-nonsend.stderr
+++ b/src/test/ui/async-await/async-fn-nonsend.stderr
@@ -27,7 +27,7 @@ error: future cannot be sent between threads safely
LL | assert_send(non_sync_with_method_call());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
- = help: the trait `Send` is not implemented for `dyn std::fmt::Write`
+ = 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
|
diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs
index 155662566..79b7239f3 100644
--- a/src/test/ui/async-await/async-fn-size-moved-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs
@@ -7,7 +7,7 @@
//
// See issue #59123 for a full explanation.
-// ignore-emscripten (sizes don't match)
+// needs-unwind Size of Futures change on panic=abort
// run-pass
// edition:2018
diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
index 31a086ba9..546172693 100644
--- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs
+++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs
@@ -5,6 +5,7 @@
// being reflected in the size.
// ignore-emscripten (sizes don't match)
+// needs-unwind Size of Futures change on panic=abort
// run-pass
// edition:2018
@@ -67,9 +68,7 @@ async fn joined() {
let c = Big::new();
fut().await;
- noop();
joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) };
- noop();
}
async fn joined_with_noop() {
@@ -97,7 +96,7 @@ async fn join_retval() -> Joiner {
fn main() {
assert_eq!(2, std::mem::size_of_val(&single()));
assert_eq!(3, std::mem::size_of_val(&single_with_noop()));
- assert_eq!(3078, std::mem::size_of_val(&joined()));
+ assert_eq!(3074, std::mem::size_of_val(&joined()));
assert_eq!(3078, std::mem::size_of_val(&joined_with_noop()));
assert_eq!(3074, std::mem::size_of_val(&join_retval()));
}
diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs
index 0ea685986..e2062e827 100644
--- a/src/test/ui/async-await/async-trait-fn.rs
+++ b/src/test/ui/async-await/async-trait-fn.rs
@@ -1,11 +1,8 @@
// edition:2018
trait T {
async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
- //~^ ERROR mismatched types
async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async`
- //~^ ERROR mismatched types
async fn baz() { //~ ERROR functions in traits cannot be declared `async`
- //~^ ERROR mismatched types
// Nested item must not ICE.
fn a() {}
}
diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr
index e5c584e31..afbe25cf7 100644
--- a/src/test/ui/async-await/async-trait-fn.stderr
+++ b/src/test/ui/async-await/async-trait-fn.stderr
@@ -9,10 +9,10 @@ LL | async fn foo() {}
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
- --> $DIR/async-trait-fn.rs:5:5
+ --> $DIR/async-trait-fn.rs:4:5
|
LL | async fn bar(&self) {}
| -----^^^^^^^^^^^^^^
@@ -22,10 +22,10 @@ LL | async fn bar(&self) {}
= note: `async` trait functions are not currently supported
= note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
= 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
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
- --> $DIR/async-trait-fn.rs:7:5
+ --> $DIR/async-trait-fn.rs:5:5
|
LL | async fn baz() {
| -----^^^^^^^^^
@@ -35,56 +35,8 @@ LL | async fn baz() {
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
-
-error[E0308]: mismatched types
- --> $DIR/async-trait-fn.rs:3:20
- |
-LL | async fn foo() {}
- | ^^ expected associated type, found opaque type
- |
- ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | ------------------------------- the found opaque type
- |
- = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
-error[E0308]: mismatched types
- --> $DIR/async-trait-fn.rs:5:25
- |
-LL | async fn bar(&self) {}
- | ^^ expected associated type, found opaque type
- |
- ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | ------------------------------- the found opaque type
- |
- = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
-error[E0308]: mismatched types
- --> $DIR/async-trait-fn.rs:7:20
- |
-LL | async fn baz() {
- | ____________________^
-LL | |
-LL | | // Nested item must not ICE.
-LL | | fn a() {}
-LL | | }
- | |_____^ expected associated type, found opaque type
- |
- ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | ------------------------------- the found opaque type
- |
- = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
-Some errors have detailed explanations: E0308, E0706.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0706`.
diff --git a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
index 50a82c08c..d99967eb2 100644
--- a/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
+++ b/src/test/ui/async-await/await-keyword/2015-edition-error-various-positions.stderr
@@ -4,13 +4,13 @@ error: `await` is a keyword in the 2018 edition
LL | pub mod await {
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/2015-edition-error-various-positions.rs:2:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: `await` is a keyword in the 2018 edition
--> $DIR/2015-edition-error-various-positions.rs:7:20
diff --git a/src/test/ui/async-await/await-keyword/2015-edition-warning.stderr b/src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
index 1c4c19ea4..bf5c4d8d6 100644
--- a/src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
+++ b/src/test/ui/async-await/await-keyword/2015-edition-warning.stderr
@@ -4,13 +4,13 @@ error: `await` is a keyword in the 2018 edition
LL | pub mod await {
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/2015-edition-warning.rs:4:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: `await` is a keyword in the 2018 edition
--> $DIR/2015-edition-warning.rs:10:20
diff --git a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
index ccbaa1f2a..6bd8f671d 100644
--- a/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
+++ b/src/test/ui/async-await/await-keyword/2018-edition-error-in-non-macro-position.stderr
@@ -46,7 +46,9 @@ error: expected identifier, found keyword `await`
--> $DIR/2018-edition-error-in-non-macro-position.rs:13:14
|
LL | struct Foo { await: () }
- | ^^^^^ expected identifier, found keyword
+ | --- ^^^^^ expected identifier, found keyword
+ | |
+ | while parsing this struct
|
help: escape `await` to use it as an identifier
|
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
index 22a61dcd2..6bd6d879a 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
@@ -17,7 +17,6 @@ impl Foo {
trait Bar {
async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
//~^ ERROR functions in traits cannot be declared `async`
- //~| ERROR mismatched types
}
fn main() {
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index 8c2902d9b..ba918eb28 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -53,7 +53,7 @@ LL | async fn foo() {}
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0670]: `async fn` is not permitted in Rust 2015
- --> $DIR/edition-deny-async-fns-2015.rs:37:9
+ --> $DIR/edition-deny-async-fns-2015.rs:36:9
|
LL | async fn bar() {}
| ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -62,7 +62,7 @@ LL | async fn bar() {}
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0670]: `async fn` is not permitted in Rust 2015
- --> $DIR/edition-deny-async-fns-2015.rs:27:9
+ --> $DIR/edition-deny-async-fns-2015.rs:26:9
|
LL | async fn foo() {}
| ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -71,7 +71,7 @@ LL | async fn foo() {}
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0670]: `async fn` is not permitted in Rust 2015
- --> $DIR/edition-deny-async-fns-2015.rs:32:13
+ --> $DIR/edition-deny-async-fns-2015.rs:31:13
|
LL | async fn bar() {}
| ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -90,23 +90,9 @@ LL | async fn foo() {}
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
-error[E0308]: mismatched types
- --> $DIR/edition-deny-async-fns-2015.rs:18:20
- |
-LL | async fn foo() {}
- | ^^ expected associated type, found opaque type
- |
- ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | ------------------------------- the found opaque type
- |
- = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
-error: aborting due to 11 previous errors
+error: aborting due to 10 previous errors
-Some errors have detailed explanations: E0308, E0670, E0706.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs b/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs
new file mode 100644
index 000000000..792f378cb
--- /dev/null
+++ b/src/test/ui/async-await/feature-gate-async_fn_in_trait.rs
@@ -0,0 +1,25 @@
+// edition:2021
+
+// RPITIT is not enough to allow use of async functions
+#![allow(incomplete_features)]
+#![feature(return_position_impl_trait_in_trait)]
+
+trait T {
+ async fn foo(); //~ ERROR functions in traits cannot be declared `async`
+}
+
+// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also
+// feature-gate-return_position_impl_trait_in_trait.rs)
+trait T2 {
+ async fn foo() -> impl Sized; //~ ERROR functions in traits cannot be declared `async`
+}
+
+trait T3 {
+ fn foo() -> impl std::future::Future<Output = ()>;
+}
+
+impl T3 for () {
+ async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr b/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr
new file mode 100644
index 000000000..2a5fbd1ec
--- /dev/null
+++ b/src/test/ui/async-await/feature-gate-async_fn_in_trait.stderr
@@ -0,0 +1,42 @@
+error[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:8:5
+ |
+LL | async fn foo();
+ | -----^^^^^^^^^^
+ | |
+ | `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[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:14:5
+ |
+LL | async fn foo() -> impl Sized;
+ | -----^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | `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[E0706]: functions in traits cannot be declared `async`
+ --> $DIR/feature-gate-async_fn_in_trait.rs:22:5
+ |
+LL | async fn foo() {}
+ | -----^^^^^^^^^
+ | |
+ | `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: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0706`.
diff --git a/src/test/ui/async-await/in-trait/async-associated-types.rs b/src/test/ui/async-await/in-trait/async-associated-types.rs
new file mode 100644
index 000000000..a6f928f3b
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-associated-types.rs
@@ -0,0 +1,24 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
+ type MyAssoc;
+
+ async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
+}
+
+impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
+ type MyAssoc = (&'a U, &'b T);
+
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-associated-types.stderr b/src/test/ui/async-await/in-trait/async-associated-types.stderr
new file mode 100644
index 000000000..0985150ee
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-associated-types.stderr
@@ -0,0 +1,57 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
+ --> $DIR/async-associated-types.rs:16:6
+ |
+LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ = note: expected `(&'a U, &'b T)`
+ found `(&U, &T)`
+ = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the types are compatible
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ = note: expected `MyTrait<'static, 'static, T>`
+ found `MyTrait<'_, '_, T>`
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
+ --> $DIR/async-associated-types.rs:16:10
+ |
+LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
+ | ^^
+note: ...so that the types are compatible
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ = note: expected `(&'a U, &'b T)`
+ found `(&U, &T)`
+ = note: but, the lifetime must be valid for the static lifetime...
+note: ...so that the types are compatible
+ --> $DIR/async-associated-types.rs:19:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ | ^^^^^^^^^^^^^^
+ = note: expected `MyTrait<'static, 'static, T>`
+ found `MyTrait<'_, '_, T>`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/async-await/in-trait/async-associated-types2.rs b/src/test/ui/async-await/in-trait/async-associated-types2.rs
new file mode 100644
index 000000000..e546a0579
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-associated-types2.rs
@@ -0,0 +1,30 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(type_alias_impl_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ type Fut<'a>: Future<Output = i32>
+ where
+ Self: 'a;
+
+ fn foo<'a>(&'a self) -> Self::Fut<'a>;
+}
+
+impl MyTrait for i32 {
+ type Fut<'a> = impl Future<Output = i32> + 'a
+ where
+ Self: 'a;
+
+ fn foo<'a>(&'a self) -> Self::Fut<'a> {
+ async {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
new file mode 100644
index 000000000..38ba29718
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+ fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+}
+
+impl MyTrait for i32 {
+ async fn foo(&self) -> i32 {
+ //~^ ERROR method `foo` has an incompatible type for trait
+ *self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
new file mode 100644
index 000000000..22d2928f2
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -0,0 +1,17 @@
+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
+ |
+note: type in trait
+ --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
+ |
+LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: expected fn pointer `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
+ found fn pointer `fn(&i32) -> impl Future<Output = i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
new file mode 100644
index 000000000..61d7e2520
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -0,0 +1,24 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::pin::Pin;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ // This will break once a PR that implements #102745 is merged
+ fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+ Box::pin(async {
+ *self
+ })
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs
new file mode 100644
index 000000000..feeda719e
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared-in-trait.rs
@@ -0,0 +1,21 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ fn foo(&self) -> impl Future<Output = i32> + '_;
+}
+
+impl MyTrait for i32 {
+ // This will break once a PR that implements #102745 is merged
+ async fn foo(&self) -> i32 {
+ *self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example-desugared.rs b/src/test/ui/async-await/in-trait/async-example-desugared.rs
new file mode 100644
index 000000000..1313c9edd
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example-desugared.rs
@@ -0,0 +1,23 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ // This will break once a PR that implements #102745 is merged
+ fn foo(&self) -> impl Future<Output = i32> + '_ {
+ async {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-example.rs b/src/test/ui/async-await/in-trait/async-example.rs
new file mode 100644
index 000000000..abf94ef74
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-example.rs
@@ -0,0 +1,32 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+ async fn bar(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ async fn foo(&self) -> i32 {
+ *self
+ }
+
+ async fn bar(&self) -> i32 {
+ self.foo().await
+ }
+}
+
+fn main() {
+ let x = 5;
+ // Calling from non-async context
+ let _ = x.foo();
+ let _ = x.bar();
+ // Calling from async block in non-async context
+ async {
+ let _: i32 = x.foo().await;
+ let _: i32 = x.bar().await;
+ };
+}
diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs
new file mode 100644
index 000000000..a73d55adf
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -0,0 +1,21 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+use std::hash::Hash;
+
+trait MyTrait<T, U> {
+ async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+ async fn foo(&self) -> &(T, U) {
+ self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr
new file mode 100644
index 000000000..5c8d64fc6
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+ |
+note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
+ --> $DIR/async-generics-and-bounds.rs:12:18
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
+ --> $DIR/async-generics-and-bounds.rs:12:18
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics-and-bounds.rs:12:28
+ |
+LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/src/test/ui/async-await/in-trait/async-generics.rs b/src/test/ui/async-await/in-trait/async-generics.rs
new file mode 100644
index 000000000..67000e577
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-generics.rs
@@ -0,0 +1,18 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T, U> {
+ async fn foo(&self) -> &(T, U);
+}
+
+impl<T, U> MyTrait<T, U> for (T, U) {
+ async fn foo(&self) -> &(T, U) {
+ self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-generics.stderr b/src/test/ui/async-await/in-trait/async-generics.stderr
new file mode 100644
index 000000000..6ae73d9e3
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-generics.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+ |
+note: the parameter type `U` must be valid for the anonymous lifetime as defined here...
+ --> $DIR/async-generics.rs:9:18
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime as defined here...
+ --> $DIR/async-generics.rs:9:18
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+ --> $DIR/async-generics.rs:9:28
+ |
+LL | async fn foo(&self) -> &(T, U);
+ | ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
new file mode 100644
index 000000000..3f7448cec
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -0,0 +1,20 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait MyTrait<'a, 'b, T> {
+ async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr
new file mode 100644
index 000000000..0f0242027
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-lifetimes-and-bounds.stderr
@@ -0,0 +1,23 @@
+error[E0309]: the parameter type `Self` may not live long enough
+ --> $DIR/async-lifetimes-and-bounds.rs:11:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `Self: 'a`...
+ = note: ...so that the reference type `&'a Self` does not outlive the data it points at
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/async-lifetimes-and-bounds.rs:11:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T) where T: Debug + Sized;
+ | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | trait MyTrait<'a, 'b, T: 'b> {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.rs b/src/test/ui/async-await/in-trait/async-lifetimes.rs
new file mode 100644
index 000000000..acbac471c
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-lifetimes.rs
@@ -0,0 +1,18 @@
+// check-fail
+// known-bug: #102682
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<'a, 'b, T> {
+ async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
+}
+
+impl<'a, 'b, T, U> MyTrait<'a, 'b, T> for U {
+ async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
+ (self, key)
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-lifetimes.stderr b/src/test/ui/async-await/in-trait/async-lifetimes.stderr
new file mode 100644
index 000000000..9a7d294bb
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-lifetimes.stderr
@@ -0,0 +1,23 @@
+error[E0309]: the parameter type `Self` may not live long enough
+ --> $DIR/async-lifetimes.rs:9:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = help: consider adding an explicit lifetime bound `Self: 'a`...
+ = note: ...so that the reference type `&'a Self` does not outlive the data it points at
+
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/async-lifetimes.rs:9:43
+ |
+LL | async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T);
+ | ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'b T` does not outlive the data it points at
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | trait MyTrait<'a, 'b, T: 'b> {
+ | ++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/async-await/in-trait/async-recursive-generic.rs b/src/test/ui/async-await/in-trait/async-recursive-generic.rs
new file mode 100644
index 000000000..6839abd38
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-recursive-generic.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait<T> {
+ async fn foo_recursive(&self, n: usize) -> T;
+}
+
+impl<T> MyTrait<T> for T where T: Copy {
+ async fn foo_recursive(&self, n: usize) -> T {
+ //~^ ERROR recursion in an `async fn` requires boxing
+ if n > 0 {
+ self.foo_recursive(n - 1).await
+ } else {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-recursive-generic.stderr b/src/test/ui/async-await/in-trait/async-recursive-generic.stderr
new file mode 100644
index 000000000..cab173bdd
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/async-recursive-generic.rs:11:48
+ |
+LL | async fn foo_recursive(&self, n: usize) -> T {
+ | ^ 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/src/test/ui/async-await/in-trait/async-recursive.rs b/src/test/ui/async-await/in-trait/async-recursive.rs
new file mode 100644
index 000000000..61119f809
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-recursive.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo_recursive(&self, n: usize) -> i32;
+}
+
+impl MyTrait for i32 {
+ async fn foo_recursive(&self, n: usize) -> i32 {
+ //~^ ERROR recursion in an `async fn` requires boxing
+ if n > 0 {
+ self.foo_recursive(n - 1).await
+ } else {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/async-recursive.stderr b/src/test/ui/async-await/in-trait/async-recursive.stderr
new file mode 100644
index 000000000..9feff37b3
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/async-recursive.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+ --> $DIR/async-recursive.rs:11:48
+ |
+LL | async fn foo_recursive(&self, n: usize) -> i32 {
+ | ^^^ 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/src/test/ui/async-await/in-trait/fn-not-async-err.rs b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
new file mode 100644
index 000000000..f94d32145
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.rs
@@ -0,0 +1,17 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+impl MyTrait for i32 {
+ fn foo(&self) -> i32 {
+ //~^ ERROR: `i32` is not a future [E0277]
+ *self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
new file mode 100644
index 000000000..03321dc5b
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `i32` is not a future
+ --> $DIR/fn-not-async-err.rs:11:22
+ |
+LL | fn foo(&self) -> i32 {
+ | ^^^ `i32` is not a future
+ |
+ = help: the trait `Future` is not implemented for `i32`
+ = note: i32 must be a future or must implement `IntoFuture` to be awaited
+note: required by a bound in `MyTrait::foo::{opaque#0}`
+ --> $DIR/fn-not-async-err.rs:7:28
+ |
+LL | async fn foo(&self) -> i32;
+ | ^^^ required by this bound in `MyTrait::foo::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.rs b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
new file mode 100644
index 000000000..594baa91a
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -0,0 +1,21 @@
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+trait MyTrait {
+ async fn foo(&self) -> i32;
+}
+
+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]
+ async {
+ *self
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr b/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr
new file mode 100644
index 000000000..f591f1847
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -0,0 +1,12 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return
+ --> $DIR/fn-not-async-err2.rs:13:22
+ |
+LL | fn foo(&self) -> impl Future<Output = i32> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = 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: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/async-await/in-trait/issue-102138.rs b/src/test/ui/async-await/in-trait/issue-102138.rs
new file mode 100644
index 000000000..f61b34ed9
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/issue-102138.rs
@@ -0,0 +1,46 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+async fn yield_now() {}
+
+trait AsyncIterator {
+ type Item;
+ async fn next(&mut self) -> Option<Self::Item>;
+}
+
+struct YieldingRange {
+ counter: u32,
+ stop: u32,
+}
+
+impl AsyncIterator for YieldingRange {
+ type Item = u32;
+
+ async fn next(&mut self) -> Option<Self::Item> {
+ if self.counter == self.stop {
+ None
+ } else {
+ let c = self.counter;
+ self.counter += 1;
+ yield_now().await;
+ Some(c)
+ }
+ }
+}
+
+async fn async_main() {
+ let mut x = YieldingRange { counter: 0, stop: 10 };
+
+ while let Some(v) = x.next().await {
+ println!("Hi: {v}");
+ }
+}
+
+fn main() {
+ let _ = async_main();
+}
diff --git a/src/test/ui/async-await/in-trait/issue-102219.rs b/src/test/ui/async-await/in-trait/issue-102219.rs
new file mode 100644
index 000000000..9a35f6515
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/issue-102219.rs
@@ -0,0 +1,10 @@
+// compile-flags:--crate-type=lib
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+trait T {
+ async fn foo();
+}
diff --git a/src/test/ui/async-await/in-trait/issue-102310.rs b/src/test/ui/async-await/in-trait/issue-102310.rs
new file mode 100644
index 000000000..49c3e9fee
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/issue-102310.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait SpiDevice {
+ async fn transaction<F, R>(&mut self);
+}
+
+impl SpiDevice for () {
+ async fn transaction<F, R>(&mut self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-64130-1-sync.rs b/src/test/ui/async-await/issue-64130-1-sync.rs
index af83f14bb..1714cec52 100644
--- a/src/test/ui/async-await/issue-64130-1-sync.rs
+++ b/src/test/ui/async-await/issue-64130-1-sync.rs
@@ -1,7 +1,7 @@
#![feature(negative_impls)]
// edition:2018
-// This tests the the specialized async-await-specific error when futures don't implement an
+// This tests the specialized async-await-specific error when futures don't implement an
// auto trait (which is specifically Sync) due to some type that was captured.
struct Foo;
diff --git a/src/test/ui/async-await/issue-64130-2-send.rs b/src/test/ui/async-await/issue-64130-2-send.rs
index 2362831d8..7a6e5952c 100644
--- a/src/test/ui/async-await/issue-64130-2-send.rs
+++ b/src/test/ui/async-await/issue-64130-2-send.rs
@@ -1,7 +1,7 @@
#![feature(negative_impls)]
// edition:2018
-// This tests the the specialized async-await-specific error when futures don't implement an
+// This tests the specialized async-await-specific error when futures don't implement an
// auto trait (which is specifically Send) due to some type that was captured.
struct Foo;
diff --git a/src/test/ui/async-await/issue-64130-3-other.rs b/src/test/ui/async-await/issue-64130-3-other.rs
index 52801c35b..630fb2c41 100644
--- a/src/test/ui/async-await/issue-64130-3-other.rs
+++ b/src/test/ui/async-await/issue-64130-3-other.rs
@@ -2,7 +2,7 @@
#![feature(negative_impls)]
// edition:2018
-// This tests the the unspecialized async-await-specific error when futures don't implement an
+// This tests the unspecialized async-await-specific error when futures don't implement an
// auto trait (which is not Send or Sync) due to some type that was captured.
auto trait Qux {}
diff --git a/src/test/ui/async-await/issue-66387-if-without-else.stderr b/src/test/ui/async-await/issue-66387-if-without-else.stderr
index e8e2a4898..8155fcb56 100644
--- a/src/test/ui/async-await/issue-66387-if-without-else.stderr
+++ b/src/test/ui/async-await/issue-66387-if-without-else.stderr
@@ -4,7 +4,7 @@ error[E0317]: `if` may be missing an `else` clause
LL | / if true {
LL | | return 0;
LL | | }
- | |_____^ expected `()`, found `i32`
+ | |_____^ expected `i32`, found `()`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 198de7bf7..7fb881166 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -18,7 +18,7 @@ LL | async fn baz<T>(_c: impl FnMut() -> T) where T: Future<Output=()> {
| ___________________________________________________________________^
LL | | }
| |_^
- = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future<Output = ()>`, `()`
+ = note: required because it captures the following types: `ResumeTy`, `impl Future<Output = ()>`, `()`
note: required because it's used within this `async` block
--> $DIR/issue-70935-complex-spans.rs:16:16
|
diff --git a/src/test/ui/issues/issue-73541-3.rs b/src/test/ui/async-await/issue-73541-3.rs
index 02ca02da8..02ca02da8 100644
--- a/src/test/ui/issues/issue-73541-3.rs
+++ b/src/test/ui/async-await/issue-73541-3.rs
diff --git a/src/test/ui/issues/issue-73541-3.stderr b/src/test/ui/async-await/issue-73541-3.stderr
index 53487aaca..53487aaca 100644
--- a/src/test/ui/issues/issue-73541-3.stderr
+++ b/src/test/ui/async-await/issue-73541-3.stderr
diff --git a/src/test/ui/issues/issue-73541.rs b/src/test/ui/async-await/issue-73541.rs
index 399a07cd3..399a07cd3 100644
--- a/src/test/ui/issues/issue-73541.rs
+++ b/src/test/ui/async-await/issue-73541.rs
diff --git a/src/test/ui/issues/issue-73541.stderr b/src/test/ui/async-await/issue-73541.stderr
index 4bb466ff1..4bb466ff1 100644
--- a/src/test/ui/issues/issue-73541.stderr
+++ b/src/test/ui/async-await/issue-73541.stderr
diff --git a/src/test/ui/async-await/issue-98634.rs b/src/test/ui/async-await/issue-98634.rs
new file mode 100644
index 000000000..b0d38687f
--- /dev/null
+++ b/src/test/ui/async-await/issue-98634.rs
@@ -0,0 +1,50 @@
+// edition: 2021
+
+use std::{
+ future::Future,
+ pin::Pin,
+ task::{Context, Poll, Waker},
+};
+
+pub struct StructAsync<F: Fn() -> Pin<Box<dyn Future<Output = ()>>>> {
+ pub callback: F,
+}
+
+impl<F> Future for StructAsync<F>
+where
+ F: Fn() -> Pin<Box<dyn Future<Output = ()>>>,
+{
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+ Poll::Pending
+ }
+}
+
+async fn callback() {}
+
+struct Runtime;
+
+fn waker() -> &'static Waker {
+ todo!()
+}
+
+impl Runtime {
+ #[track_caller]
+ pub fn block_on<F: Future>(&self, mut future: F) -> F::Output {
+ loop {
+ unsafe {
+ Pin::new_unchecked(&mut future).poll(&mut Context::from_waker(waker()));
+ }
+ }
+ }
+}
+
+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 = ()>`
+ });
+}
diff --git a/src/test/ui/async-await/issue-98634.stderr b/src/test/ui/async-await/issue-98634.stderr
new file mode 100644
index 000000000..5160e48d8
--- /dev/null
+++ b/src/test/ui/async-await/issue-98634.stderr
@@ -0,0 +1,60 @@
+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 = ()>`
+ --> $DIR/issue-98634.rs:45:23
+ |
+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
+ |
+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 = ()>`
+ --> $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
+ |
+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 = ()>`
+ --> $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
+ |
+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: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
index 5e71229be..b4ea4c9f6 100644
--- a/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
+++ b/src/test/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
@@ -6,7 +6,6 @@
// error-pattern: thread 'main' panicked at '`async fn` resumed after panicking'
// edition:2018
// ignore-wasm no panic or subprocess support
-// ignore-emscripten no panic or subprocess support
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/async-await/issues/issue-95307.stderr b/src/test/ui/async-await/issues/issue-95307.stderr
index 1c12f1e48..a497cebe3 100644
--- a/src/test/ui/async-await/issues/issue-95307.stderr
+++ b/src/test/ui/async-await/issues/issue-95307.stderr
@@ -9,7 +9,7 @@ LL | async fn new() -> [u8; _];
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error: in expressions, `_` can only be used on the left-hand side of an assignment
--> $DIR/issue-95307.rs:7:28
diff --git a/src/test/ui/async-await/large_moves.attribute.stderr b/src/test/ui/async-await/large_moves.attribute.stderr
index 8d3f0b77f..da34f44b2 100644
--- a/src/test/ui/async-await/large_moves.attribute.stderr
+++ b/src/test/ui/async-await/large_moves.attribute.stderr
@@ -10,12 +10,12 @@ LL | | dbg!(y);
LL | | };
| |_____^ value moved from here
|
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
note: the lint level is defined here
--> $DIR/large_moves.rs:1:9
|
LL | #![deny(large_assignments)]
| ^^^^^^^^^^^^^^^^^
- = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
error: moving 10024 bytes
--> $DIR/large_moves.rs:18:14
diff --git a/src/test/ui/async-await/large_moves.option.stderr b/src/test/ui/async-await/large_moves.option.stderr
index 8d3f0b77f..da34f44b2 100644
--- a/src/test/ui/async-await/large_moves.option.stderr
+++ b/src/test/ui/async-await/large_moves.option.stderr
@@ -10,12 +10,12 @@ LL | | dbg!(y);
LL | | };
| |_____^ value moved from here
|
+ = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
note: the lint level is defined here
--> $DIR/large_moves.rs:1:9
|
LL | #![deny(large_assignments)]
| ^^^^^^^^^^^^^^^^^
- = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
error: moving 10024 bytes
--> $DIR/large_moves.rs:18:14
diff --git a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
index 3128b4df4..ae4d0d585 100644
--- a/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
+++ b/src/test/ui/async-await/multiple-lifetimes/ret-impl-trait-one.stderr
@@ -25,7 +25,7 @@ LL | | (a, b)
LL | | }
| |_^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'a>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> + 'b {
| ++++
diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr
index e6f6e9e9f..c5bd520aa 100644
--- a/src/test/ui/async-await/no-const-async.stderr
+++ b/src/test/ui/async-await/no-const-async.stderr
@@ -18,7 +18,7 @@ note: ...which requires borrow-checking `x`...
|
LL | pub const async fn x() {}
| ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `x`...
+note: ...which requires processing MIR for `x`...
--> $DIR/no-const-async.rs:4:1
|
LL | pub const async fn x() {}
diff --git a/src/test/ui/attr-from-macro.rs b/src/test/ui/attr-from-macro.rs
new file mode 100644
index 000000000..bb3a5c94d
--- /dev/null
+++ b/src/test/ui/attr-from-macro.rs
@@ -0,0 +1,20 @@
+// aux-build:attr-from-macro.rs
+// run-pass
+
+extern crate attr_from_macro;
+
+attr_from_macro::creator! {
+ struct Foo;
+ enum Bar;
+ enum FooBar;
+}
+
+fn main() {
+ // Checking the `repr(u32)` on the enum.
+ assert_eq!(4, std::mem::size_of::<Bar>());
+ // Checking the `repr(u16)` on the enum.
+ assert_eq!(2, std::mem::size_of::<FooBar>());
+
+ // Checking the Debug impl on the types.
+ eprintln!("{:?} {:?} {:?}", Foo, Bar::A, FooBar::A);
+}
diff --git a/src/test/ui/attributes/doc-attr.stderr b/src/test/ui/attributes/doc-attr.stderr
index cc2494c92..68df2771f 100644
--- a/src/test/ui/attributes/doc-attr.stderr
+++ b/src/test/ui/attributes/doc-attr.stderr
@@ -4,14 +4,14 @@ error: unknown `doc` attribute `as_ptr`
LL | #[doc(as_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 #82730 <https://github.com/rust-lang/rust/issues/82730>
note: the lint level is defined here
--> $DIR/doc-attr.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
error: invalid `doc` attribute
--> $DIR/doc-attr.rs:12:7
diff --git a/src/test/ui/attributes/invalid-doc-attr.stderr b/src/test/ui/attributes/invalid-doc-attr.stderr
index a4fa38179..3c66e587b 100644
--- a/src/test/ui/attributes/invalid-doc-attr.stderr
+++ b/src/test/ui/attributes/invalid-doc-attr.stderr
@@ -4,15 +4,15 @@ error: this attribute can only be applied at the crate level
LL | #[doc(test(no_crate_inject))]
| ^^^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
note: the lint level is defined here
--> $DIR/invalid-doc-attr.rs:2:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
- = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
help: to apply to the crate, use an inner attribute
|
LL | #![doc(test(no_crate_inject))]
diff --git a/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs b/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs
index e8b4fe7ae..74fbae035 100644
--- a/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs
+++ b/src/test/ui/attributes/unix_sigpipe/auxiliary/sigpipe-utils.rs
@@ -23,9 +23,11 @@ pub fn assert_sigpipe_handler(expected_handler: SignalHandler) {
SignalHandler::Ignore => libc::SIG_IGN,
SignalHandler::Default => libc::SIG_DFL,
};
- assert_eq!(prev, expected);
+ assert_eq!(prev, expected, "expected sigpipe value matches actual value");
// Unlikely to matter, but restore the old value anyway
- unsafe { libc::signal(libc::SIGPIPE, prev); };
+ unsafe {
+ libc::signal(libc::SIGPIPE, prev);
+ };
}
}
diff --git a/src/test/ui/auto-traits/suspicious-impls-lint.stderr b/src/test/ui/auto-traits/suspicious-impls-lint.stderr
index 97b2d7221..9cd4e79f8 100644
--- a/src/test/ui/auto-traits/suspicious-impls-lint.stderr
+++ b/src/test/ui/auto-traits/suspicious-impls-lint.stderr
@@ -4,11 +4,6 @@ error: cross-crate traits with a default impl, like `Send`, should not be specia
LL | unsafe impl<T: Send> Send for MayImplementSendErr<&T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/suspicious-impls-lint.rs:1:9
- |
-LL | #![deny(suspicious_auto_trait_impls)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this will change its meaning in a future release!
= note: for more information, see issue #93367 <https://github.com/rust-lang/rust/issues/93367>
= note: `&T` is not a generic parameter
@@ -17,6 +12,11 @@ note: try using the same sequence of generic parameters as the struct definition
|
LL | struct MayImplementSendErr<T>(T);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/suspicious-impls-lint.rs:1:9
+ |
+LL | #![deny(suspicious_auto_trait_impls)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: cross-crate traits with a default impl, like `Send`, should not be specialized
--> $DIR/suspicious-impls-lint.rs:21:1
diff --git a/src/test/ui/auxiliary/attr-from-macro.rs b/src/test/ui/auxiliary/attr-from-macro.rs
new file mode 100644
index 000000000..9b388675c
--- /dev/null
+++ b/src/test/ui/auxiliary/attr-from-macro.rs
@@ -0,0 +1,15 @@
+#[macro_export]
+macro_rules! creator {
+ (struct $name1:ident; enum $name2:ident; enum $name3:ident;) => {
+ #[derive(Debug)]
+ pub struct $name1;
+
+ #[derive(Debug)]
+ #[repr(u32)]
+ pub enum $name2 { A }
+
+ #[derive(Debug)]
+ #[repr(u16)]
+ pub enum $name3 { A }
+ }
+}
diff --git a/src/test/ui/backtrace.rs b/src/test/ui/backtrace.rs
index e2ac43fff..dd73dd988 100644
--- a/src/test/ui/backtrace.rs
+++ b/src/test/ui/backtrace.rs
@@ -4,6 +4,7 @@
// ignore-openbsd no support for libbacktrace without filename
// ignore-sgx no processes
// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
+// ignore-fuchsia Backtraces not symbolized
// compile-flags:-g
// compile-flags:-Cstrip=none
diff --git a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
index 684172ca6..0450fe8ab 100644
--- a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
+++ b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
@@ -3,7 +3,6 @@
// Check that partially moved from function parameters are dropped after the
// named bindings that move from them.
-// ignore-wasm32-bare compiled with panic=abort by default
use std::{panic, cell::RefCell};
diff --git a/src/test/ui/binding/issue-53114-safety-checks.stderr b/src/test/ui/binding/issue-53114-safety-checks.stderr
index f3840273c..57a065d6d 100644
--- a/src/test/ui/binding/issue-53114-safety-checks.stderr
+++ b/src/test/ui/binding/issue-53114-safety-checks.stderr
@@ -4,11 +4,11 @@ error: reference to packed field is unaligned
LL | let _ = &p.b;
| ^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -109,11 +109,11 @@ error: reference to packed field is unaligned
LL | let _ = &p.b;
| ^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -122,11 +122,11 @@ error: reference to packed field is unaligned
LL | let (_,) = (&p.b,);
| ^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -135,11 +135,11 @@ error: reference to packed field is unaligned
LL | match &p.b { _ => { } }
| ^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -148,9 +148,9 @@ error: reference to packed field is unaligned
LL | match (&p.b,) { (_,) => { } }
| ^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
diff --git a/src/test/ui/binop/issue-77910-1.rs b/src/test/ui/binop/issue-77910-1.rs
index d786e3358..95bbd6a60 100644
--- a/src/test/ui/binop/issue-77910-1.rs
+++ b/src/test/ui/binop/issue-77910-1.rs
@@ -7,5 +7,5 @@ fn main() {
// we shouldn't ice with the bound var here.
assert_eq!(foo, y);
//~^ ERROR binary operation `==` cannot be applied to type
- //~| ERROR `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
+ //~| ERROR `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug`
}
diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr
index 097a14f26..263a35d98 100644
--- a/src/test/ui/binop/issue-77910-1.stderr
+++ b/src/test/ui/binop/issue-77910-1.stderr
@@ -1,25 +1,25 @@
-error[E0369]: binary operation `==` cannot be applied to type `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}`
--> $DIR/issue-77910-1.rs:8:5
|
LL | assert_eq!(foo, y);
| ^^^^^^^^^^^^^^^^^^
| |
- | for<'r> fn(&'r i32) -> &'r i32 {foo}
+ | for<'a> fn(&'a i32) -> &'a i32 {foo}
| _
|
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
+error[E0277]: `for<'a> fn(&'a i32) -> &'a i32 {foo}` doesn't implement `Debug`
--> $DIR/issue-77910-1.rs:8:5
|
LL | fn foo(s: &i32) -> &i32 {
| --- consider calling this function
...
LL | assert_eq!(foo, y);
- | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+ | ^^^^^^^^^^^^^^^^^^ `for<'a> fn(&'a i32) -> &'a i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
- = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}`
- = help: use parentheses to call the function: `foo(s)`
+ = help: the trait `Debug` is not implemented for fn item `for<'a> fn(&'a i32) -> &'a i32 {foo}`
+ = help: use parentheses to call this function: `foo(/* &i32 */)`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 2 previous errors
diff --git a/src/test/ui/binop/issue-77910-2.stderr b/src/test/ui/binop/issue-77910-2.stderr
index a334bd856..b3856b6ae 100644
--- a/src/test/ui/binop/issue-77910-2.stderr
+++ b/src/test/ui/binop/issue-77910-2.stderr
@@ -1,10 +1,10 @@
-error[E0369]: binary operation `==` cannot be applied to type `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}`
--> $DIR/issue-77910-2.rs:7:12
|
LL | if foo == y {}
| --- ^^ - _
| |
- | for<'r> fn(&'r i32) -> &'r i32 {foo}
+ | for<'a> fn(&'a i32) -> &'a i32 {foo}
|
help: use parentheses to call this function
|
diff --git a/src/test/ui/block-result/consider-removing-last-semi.stderr b/src/test/ui/block-result/consider-removing-last-semi.stderr
index 2412dcd32..9be0367ae 100644
--- a/src/test/ui/block-result/consider-removing-last-semi.stderr
+++ b/src/test/ui/block-result/consider-removing-last-semi.stderr
@@ -7,7 +7,7 @@ LL | pub fn f() -> String {
| implicitly returns `()` as its body has no tail or `return` expression
LL | 0u8;
LL | "bla".to_string();
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error[E0308]: mismatched types
--> $DIR/consider-removing-last-semi.rs:8:15
@@ -18,7 +18,7 @@ LL | pub fn g() -> String {
| implicitly returns `()` as its body has no tail or `return` expression
LL | "this won't work".to_string();
LL | "removeme".to_string();
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error[E0308]: mismatched types
--> $DIR/consider-removing-last-semi.rs:13:25
@@ -29,7 +29,7 @@ LL | pub fn macro_tests() -> u32 {
| implicitly returns `()` as its body has no tail or `return` expression
...
LL | mac!();
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error: aborting due to 3 previous errors
diff --git a/src/test/ui/block-result/issue-11714.stderr b/src/test/ui/block-result/issue-11714.stderr
index 5b8d96fd4..42fb3d3d4 100644
--- a/src/test/ui/block-result/issue-11714.stderr
+++ b/src/test/ui/block-result/issue-11714.stderr
@@ -7,7 +7,7 @@ LL | fn blah() -> i32 {
| implicitly returns `()` as its body has no tail or `return` expression
...
LL | ;
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error: aborting due to previous error
diff --git a/src/test/ui/block-result/issue-13428.stderr b/src/test/ui/block-result/issue-13428.stderr
index a33448edf..2b386d10c 100644
--- a/src/test/ui/block-result/issue-13428.stderr
+++ b/src/test/ui/block-result/issue-13428.stderr
@@ -15,7 +15,7 @@ LL | fn bar() -> String {
| implicitly returns `()` as its body has no tail or `return` expression
LL | "foobar".to_string()
LL | ;
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/anonymous-region-in-apit.rs b/src/test/ui/borrowck/anonymous-region-in-apit.rs
new file mode 100644
index 000000000..7799a7cb1
--- /dev/null
+++ b/src/test/ui/borrowck/anonymous-region-in-apit.rs
@@ -0,0 +1,12 @@
+#![feature(anonymous_lifetime_in_impl_trait)]
+
+trait Foo<T> {
+ fn bar(self, baz: T);
+}
+
+fn qux(foo: impl Foo<&str>) {
+ |baz: &str| foo.bar(baz);
+ //~^ ERROR borrowed data escapes outside of closure
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/anonymous-region-in-apit.stderr b/src/test/ui/borrowck/anonymous-region-in-apit.stderr
new file mode 100644
index 000000000..9e100f8ac
--- /dev/null
+++ b/src/test/ui/borrowck/anonymous-region-in-apit.stderr
@@ -0,0 +1,16 @@
+error[E0521]: borrowed data escapes outside of closure
+ --> $DIR/anonymous-region-in-apit.rs:8:17
+ |
+LL | fn qux(foo: impl Foo<&str>) {
+ | --- lifetime `'2` appears in the type of `foo`
+LL | |baz: &str| foo.bar(baz);
+ | --- - ^^^^^^^^^^^^
+ | | | |
+ | | | `baz` escapes the closure body here
+ | | | argument requires that `'1` must outlive `'2`
+ | | let's call the lifetime of this reference `'1`
+ | `baz` is a reference that is only valid in the closure body
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0521`.
diff --git a/src/test/ui/borrowck/borrowck-block-unint.stderr b/src/test/ui/borrowck/borrowck-block-unint.stderr
index e720db1c6..f47921a97 100644
--- a/src/test/ui/borrowck/borrowck-block-unint.stderr
+++ b/src/test/ui/borrowck/borrowck-block-unint.stderr
@@ -7,6 +7,11 @@ LL | force(|| {
| ^^ `x` used here but it isn't initialized
LL | println!("{}", x);
| - borrow occurs due to use in closure
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
index 91038b3ad..ea93a8f40 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit-2.stderr
@@ -8,6 +8,10 @@ LL | println!("{}", x);
| ^ `x` used here but it isn't initialized
|
= 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 assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-break-uninit.stderr b/src/test/ui/borrowck/borrowck-break-uninit.stderr
index 8d0c9582f..a7a8fc2ff 100644
--- a/src/test/ui/borrowck/borrowck-break-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-break-uninit.stderr
@@ -8,6 +8,10 @@ LL | println!("{}", x);
| ^ `x` used here but it isn't initialized
|
= 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 assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
index e8a2fbc91..1a22b5f09 100644
--- a/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-called-fn-expr.stderr
@@ -5,6 +5,11 @@ LL | let i: isize;
| - binding declared here but left uninitialized
LL | i
| ^ `i` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let i: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
index 1e950d6a2..f1b9b9aa7 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fn-expr.stderr
@@ -5,6 +5,11 @@ LL | let i: isize;
| - binding declared here but left uninitialized
LL | i
| ^ `i` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let i: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-init-in-fru.stderr b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
index 83a3e3e0e..39b28811a 100644
--- a/src/test/ui/borrowck/borrowck-init-in-fru.stderr
+++ b/src/test/ui/borrowck/borrowck-init-in-fru.stderr
@@ -5,6 +5,11 @@ LL | let mut origin: Point;
| ---------- binding declared here but left uninitialized
LL | origin = Point { x: 10, ..origin };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `origin.y` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut origin: Point = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-init-op-equal.stderr b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
index 74704b2ab..ef0fa6df4 100644
--- a/src/test/ui/borrowck/borrowck-init-op-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-op-equal.stderr
@@ -5,6 +5,11 @@ LL | let v: isize;
| - binding declared here but left uninitialized
LL | v += 1;
| ^^^^^^ `v` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let v: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
index 7542576d6..cec053318 100644
--- a/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
+++ b/src/test/ui/borrowck/borrowck-init-plus-equal.stderr
@@ -5,6 +5,11 @@ LL | let mut v: isize;
| ----- binding declared here but left uninitialized
LL | v = v + 1;
| ^ `v` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut v: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr
index 15ac73760..d2b845619 100644
--- a/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr
+++ b/src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.stderr
@@ -25,7 +25,10 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
--> $DIR/borrowck-mut-borrow-linear-errors.rs:12:30
|
LL | _ => { addr.push(&mut x); }
- | ^^^^^^ `x` was mutably borrowed here in the previous iteration of the loop
+ | ----------^^^^^^-
+ | | |
+ | | `x` was mutably borrowed here in the previous iteration of the loop
+ | first borrow used here, in later iteration of loop
error: aborting due to 3 previous errors
diff --git a/src/test/ui/borrowck/borrowck-return.stderr b/src/test/ui/borrowck/borrowck-return.stderr
index 1c916e223..9799357c9 100644
--- a/src/test/ui/borrowck/borrowck-return.stderr
+++ b/src/test/ui/borrowck/borrowck-return.stderr
@@ -5,6 +5,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | return x;
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-storage-dead.stderr b/src/test/ui/borrowck/borrowck-storage-dead.stderr
index 2cea4392d..3a413153a 100644
--- a/src/test/ui/borrowck/borrowck-storage-dead.stderr
+++ b/src/test/ui/borrowck/borrowck-storage-dead.stderr
@@ -5,6 +5,11 @@ LL | let x: i32;
| - binding declared here but left uninitialized
LL | let _ = x + 1;
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: i32 = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
index 588b1b0c9..071598b42 100644
--- a/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-after-item.stderr
@@ -6,6 +6,11 @@ LL | let bar;
LL | fn baz(_x: isize) { }
LL | baz(bar);
| ^^^ `bar` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let bar = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
index 6a38a7989..f0f4ad704 100644
--- a/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-field-access.stderr
@@ -5,6 +5,11 @@ LL | let mut a: Point;
| ----- binding declared here but left uninitialized
LL | let _ = a.x + 1;
| ^^^ `a.x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut a: Point = Default::default();
+ | ++++++++++++++++++++
error[E0382]: use of moved value: `line1.origin`
--> $DIR/borrowck-uninit-field-access.rs:25:13
diff --git a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
index 744cb14e6..fdbb451bd 100644
--- a/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-in-assignop.stderr
@@ -5,6 +5,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x += 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:9:5
@@ -13,6 +18,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x -= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:12:5
@@ -21,6 +31,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x *= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:15:5
@@ -29,6 +44,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x /= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:18:5
@@ -37,6 +57,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x %= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:21:5
@@ -45,6 +70,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x ^= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:24:5
@@ -53,6 +83,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x &= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:27:5
@@ -61,6 +96,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x |= 1;
| ^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:30:5
@@ -69,6 +109,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x <<= 1;
| ^^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-in-assignop.rs:33:5
@@ -77,6 +122,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | x >>= 1;
| ^^^^^^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to 10 previous errors
diff --git a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
index c486cb6dd..73fded754 100644
--- a/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit-ref-chain.stderr
@@ -5,6 +5,11 @@ LL | let x: &&Box<i32>;
| - binding declared here but left uninitialized
LL | let _y = &**x;
| ^^^^ `**x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: &&Box<i32> = todo!();
+ | +++++++++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-ref-chain.rs:11:14
@@ -13,6 +18,11 @@ LL | let x: &&S<i32, i32>;
| - binding declared here but left uninitialized
LL | let _y = &**x;
| ^^^^ `**x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: &&S<i32, i32> = todo!();
+ | +++++++++
error[E0381]: used binding `x` isn't initialized
--> $DIR/borrowck-uninit-ref-chain.rs:14:14
@@ -21,6 +31,11 @@ LL | let x: &&i32;
| - binding declared here but left uninitialized
LL | let _y = &**x;
| ^^^^ `**x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: &&i32 = todo!();
+ | +++++++++
error[E0381]: partially assigned binding `a` isn't fully initialized
--> $DIR/borrowck-uninit-ref-chain.rs:18:5
diff --git a/src/test/ui/borrowck/borrowck-uninit.stderr b/src/test/ui/borrowck/borrowck-uninit.stderr
index d5566691a..eeafc4ce1 100644
--- a/src/test/ui/borrowck/borrowck-uninit.stderr
+++ b/src/test/ui/borrowck/borrowck-uninit.stderr
@@ -5,6 +5,11 @@ LL | let x: isize;
| - binding declared here but left uninitialized
LL | foo(x);
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: isize = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
index 459cf1398..18e808f10 100644
--- a/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
+++ b/src/test/ui/borrowck/borrowck-use-in-index-lvalue.stderr
@@ -5,6 +5,11 @@ LL | let w: &mut [isize];
| - binding declared here but left uninitialized
LL | w[5] = 0;
| ^^^^ `*w` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let w: &mut [isize] = todo!();
+ | +++++++++
error[E0381]: used binding `w` isn't initialized
--> $DIR/borrowck-use-in-index-lvalue.rs:6:5
@@ -13,6 +18,11 @@ LL | let mut w: &mut [isize];
| ----- binding declared here but left uninitialized
LL | w[5] = 0;
| ^^^^ `*w` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut w: &mut [isize] = todo!();
+ | +++++++++
error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
index 942ed4fc6..55f3ff553 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast-trait.stderr
@@ -5,6 +5,11 @@ LL | let x: &i32;
| - binding declared here but left uninitialized
LL | let y = x as *const dyn Foo;
| ^ `*x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: &i32 = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
index f3289e239..ea3d0d3ef 100644
--- a/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
+++ b/src/test/ui/borrowck/borrowck-use-uninitialized-in-cast.stderr
@@ -5,6 +5,11 @@ LL | let x: &i32;
| - binding declared here but left uninitialized
LL | let y = x as *const i32;
| ^ `*x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: &i32 = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/borrowck-while-cond.stderr b/src/test/ui/borrowck/borrowck-while-cond.stderr
index e41c1c55e..5d0194989 100644
--- a/src/test/ui/borrowck/borrowck-while-cond.stderr
+++ b/src/test/ui/borrowck/borrowck-while-cond.stderr
@@ -5,6 +5,11 @@ LL | let x: bool;
| - binding declared here but left uninitialized
LL | while x { }
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: bool = false;
+ | +++++++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/issue-102209.rs b/src/test/ui/borrowck/issue-102209.rs
new file mode 100644
index 000000000..37628bff7
--- /dev/null
+++ b/src/test/ui/borrowck/issue-102209.rs
@@ -0,0 +1,28 @@
+use std::marker::PhantomData;
+
+pub struct NfaBuilder<'brand> {
+ brand: PhantomData<&'brand mut &'brand mut ()>,
+}
+
+impl NfaBuilder<'_> {
+ pub fn with<R, F: FnOnce(NfaBuilder<'_>) -> R>(f: F) -> R {
+ Brand::with(|brand| {
+ f(Self { brand: brand.lt })
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR lifetime may not live long enough
+ })
+ }
+}
+
+#[derive(Clone, Copy)]
+pub struct Brand<'brand> {
+ lt: PhantomData<&'brand mut &'brand mut ()>,
+}
+
+impl Brand<'_> {
+ pub fn with<R, F: FnOnce(Brand<'_>) -> R>(f: F) -> R {
+ f(Self { lt: PhantomData })
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-102209.stderr b/src/test/ui/borrowck/issue-102209.stderr
new file mode 100644
index 000000000..351de8217
--- /dev/null
+++ b/src/test/ui/borrowck/issue-102209.stderr
@@ -0,0 +1,22 @@
+error: lifetime may not live long enough
+ --> $DIR/issue-102209.rs:10:29
+ |
+LL | impl NfaBuilder<'_> {
+ | -- lifetime `'2` appears in the `impl`'s self type
+LL | pub fn with<R, F: FnOnce(NfaBuilder<'_>) -> R>(f: F) -> R {
+LL | Brand::with(|brand| {
+ | ----- has type `Brand<'1>`
+LL | f(Self { brand: brand.lt })
+ | ^^^^^^^^ this usage requires that `'1` must outlive `'2`
+
+error: lifetime may not live long enough
+ --> $DIR/issue-102209.rs:10:29
+ |
+LL | impl NfaBuilder<'_> {
+ | -- lifetime `'1` appears in the `impl`'s self type
+...
+LL | f(Self { brand: brand.lt })
+ | ^^^^^^^^ this usage requires that `'1` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/borrowck/issue-103250.rs b/src/test/ui/borrowck/issue-103250.rs
new file mode 100644
index 000000000..46565f61c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-103250.rs
@@ -0,0 +1,37 @@
+// edition:2021
+
+type TranslateFn = Box<dyn Fn(String, String) -> String>;
+
+pub struct DeviceCluster {
+ devices: Vec<Device>,
+}
+
+impl DeviceCluster {
+ pub async fn do_something(&mut self) -> Result<String, Box<dyn std::error::Error>> {
+ let mut last_error: Box<dyn std::error::Error>;
+
+ for device in &mut self.devices {
+ match device.do_something().await {
+ Ok(info) => {
+ return Ok(info);
+ }
+ Err(e) => {}
+ }
+ }
+
+ Err(last_error)
+ //~^ ERROR used binding `last_error` isn't initialized
+ }
+}
+
+pub struct Device {
+ translate_fn: Option<TranslateFn>,
+}
+
+impl Device {
+ pub async fn do_something(&mut self) -> Result<String, Box<dyn std::error::Error>> {
+ Ok(String::from(""))
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-103250.stderr b/src/test/ui/borrowck/issue-103250.stderr
new file mode 100644
index 000000000..4a2378352
--- /dev/null
+++ b/src/test/ui/borrowck/issue-103250.stderr
@@ -0,0 +1,17 @@
+error[E0381]: used binding `last_error` isn't initialized
+ --> $DIR/issue-103250.rs:22:13
+ |
+LL | let mut last_error: Box<dyn std::error::Error>;
+ | -------------- binding declared here but left uninitialized
+...
+LL | Err(last_error)
+ | ^^^^^^^^^^ `last_error` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut last_error: Box<dyn std::error::Error> = todo!();
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/issue-103624.rs b/src/test/ui/borrowck/issue-103624.rs
new file mode 100644
index 000000000..f1fa95f92
--- /dev/null
+++ b/src/test/ui/borrowck/issue-103624.rs
@@ -0,0 +1,31 @@
+// edition:2021
+
+struct StructA {
+ b: StructB,
+}
+
+async fn spawn_blocking<T>(f: impl (Fn() -> T) + Send + Sync + 'static) -> T {
+ todo!()
+}
+
+impl StructA {
+ async fn foo(&self) {
+ let bar = self.b.bar().await;
+ spawn_blocking(move || {
+ //~^ ERROR borrowed data escapes outside of associated function
+ self.b;
+ //~^ ERROR cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
+ })
+ .await;
+ }
+}
+
+struct StructB {}
+
+impl StructB {
+ async fn bar(&self) -> Option<u8> {
+ None
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-103624.stderr b/src/test/ui/borrowck/issue-103624.stderr
new file mode 100644
index 000000000..e6a35dd88
--- /dev/null
+++ b/src/test/ui/borrowck/issue-103624.stderr
@@ -0,0 +1,35 @@
+error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure
+ --> $DIR/issue-103624.rs:16:13
+ |
+LL | async fn foo(&self) {
+ | ----- captured outer variable
+LL | let bar = self.b.bar().await;
+LL | spawn_blocking(move || {
+ | ------- captured by this `Fn` closure
+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
+ --> $DIR/issue-103624.rs:14:9
+ |
+LL | async fn foo(&self) {
+ | -----
+ | |
+ | `self` is a reference that is only valid in the associated function body
+ | let's call the lifetime of this reference `'1`
+LL | let bar = self.b.bar().await;
+LL | / spawn_blocking(move || {
+LL | |
+LL | | self.b;
+LL | |
+LL | | })
+ | | ^
+ | | |
+ | |__________`self` escapes the associated function body here
+ | argument requires that `'1` must outlive `'static`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0507, E0521.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/src/test/ui/issues/issue-17718-static-move.rs b/src/test/ui/borrowck/issue-17718-static-move.rs
index 015487a06..015487a06 100644
--- a/src/test/ui/issues/issue-17718-static-move.rs
+++ b/src/test/ui/borrowck/issue-17718-static-move.rs
diff --git a/src/test/ui/issues/issue-17718-static-move.stderr b/src/test/ui/borrowck/issue-17718-static-move.stderr
index 984534bfb..984534bfb 100644
--- a/src/test/ui/issues/issue-17718-static-move.stderr
+++ b/src/test/ui/borrowck/issue-17718-static-move.stderr
diff --git a/src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs b/src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs
index d45aaa843..d45aaa843 100644
--- a/src/test/ui/issues/issue-23338-params-outlive-temps-of-body.rs
+++ b/src/test/ui/borrowck/issue-23338-params-outlive-temps-of-body.rs
diff --git a/src/test/ui/borrowck/issue-24267-flow-exit.stderr b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
index b85e8f216..58d1c8c0f 100644
--- a/src/test/ui/borrowck/issue-24267-flow-exit.stderr
+++ b/src/test/ui/borrowck/issue-24267-flow-exit.stderr
@@ -8,6 +8,10 @@ LL | println!("{}", x);
| ^ `x` used here but it isn't initialized
|
= 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 assigning a value
+ |
+LL | let x: i32 = 0;
+ | +++
error[E0381]: used binding `x` isn't initialized
--> $DIR/issue-24267-flow-exit.rs:18:20
@@ -19,6 +23,10 @@ LL | println!("{}", x);
| ^ `x` used here but it isn't initialized
|
= 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 assigning a value
+ |
+LL | let x: i32 = 0;
+ | +++
error: aborting due to 2 previous errors
diff --git a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
index f5d2eecfa..9683da919 100644
--- a/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
+++ b/src/test/ui/borrowck/issue-62107-match-arm-scopes.stderr
@@ -5,6 +5,11 @@ LL | let e: i32;
| - binding declared here but left uninitialized
LL | match e {
| ^ `e` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let e: i32 = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/borrowck/issue-81899.rs b/src/test/ui/borrowck/issue-81899.rs
index 9b6061203..24b20b650 100644
--- a/src/test/ui/borrowck/issue-81899.rs
+++ b/src/test/ui/borrowck/issue-81899.rs
@@ -2,8 +2,7 @@
// The `panic!()` below is important to trigger the fixed ICE.
const _CONST: &[u8] = &f(&[], |_| {});
-//~^ ERROR any use of this value
-//~| WARNING this was previously
+//~^ ERROR constant
const fn f<F>(_: &[u8], _: F) -> &[u8]
where
diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr
index fd591c7b5..12e80b9df 100644
--- a/src/test/ui/borrowck/issue-81899.stderr
+++ b/src/test/ui/borrowck/issue-81899.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-81899.rs:12:5
+ --> $DIR/issue-81899.rs:11:5
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
@@ -7,32 +7,17 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
LL | panic!()
| ^^^^^^^^
| |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:12:5
+ | the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
| inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
= 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)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/issue-81899.rs:4:23
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
- | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/issue-81899.rs:4:23
- |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
- | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.rs b/src/test/ui/borrowck/issue-88434-minimal-example.rs
index 7618d001e..983a02310 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.rs
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.rs
@@ -1,8 +1,7 @@
// Regression test related to issue 88434
const _CONST: &() = &f(&|_| {});
-//~^ ERROR any use of this value
-//~| WARNING this was previously
+//~^ ERROR constant
const fn f<F>(_: &F)
where
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
index a3582e780..dc87c4c2b 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-88434-minimal-example.rs:11:5
+ --> $DIR/issue-88434-minimal-example.rs:10:5
|
LL | const _CONST: &() = &f(&|_| {});
| ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
@@ -7,32 +7,17 @@ LL | const _CONST: &() = &f(&|_| {});
LL | panic!()
| ^^^^^^^^
| |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:11:5
+ | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
| inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
= 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)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-minimal-example.rs:3:21
|
LL | const _CONST: &() = &f(&|_| {});
- | ----------------- ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/issue-88434-minimal-example.rs:3:21
- |
-LL | const _CONST: &() = &f(&|_| {});
- | ----------------- ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
index b1fc1615e..a99c5b76a 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.rs
@@ -1,8 +1,7 @@
// Regression test for issue 88434
const _CONST: &[u8] = &f(&[], |_| {});
-//~^ ERROR any use of this value will cause an error
-//~| WARNING this was previously
+//~^ ERROR constant
const fn f<F>(_: &[u8], _: F) -> &[u8]
where
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
index a6c65b302..4b4a25d7b 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-88434-removal-index-should-be-less.rs:11:5
+ --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
@@ -7,32 +7,17 @@ LL | const _CONST: &[u8] = &f(&[], |_| {});
LL | panic!()
| ^^^^^^^^
| |
- | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:11:5
+ | the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
| inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
|
= 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)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
- | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/issue-88434-removal-index-should-be-less.rs:3:23
- |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
- | ------------------- ^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs
new file mode 100644
index 000000000..31eba0740
--- /dev/null
+++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.rs
@@ -0,0 +1,26 @@
+// Tests the suggestion to reborrow the first move site
+// when we move then borrow a `&mut` ref.
+
+struct State;
+
+impl IntoIterator for &mut State {
+ type IntoIter = std::vec::IntoIter<()>;
+ type Item = ();
+
+ fn into_iter(self) -> Self::IntoIter {
+ vec![].into_iter()
+ }
+}
+
+fn once(f: impl FnOnce()) {}
+
+fn fill_memory_blocks_mt(state: &mut State) {
+ for _ in state {}
+ //~^ HELP consider creating a fresh reborrow of `state` here
+ fill_segment(state);
+ //~^ ERROR borrow of moved value: `state`
+}
+
+fn fill_segment(state: &mut State) {}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
new file mode 100644
index 000000000..13a2005e2
--- /dev/null
+++ b/src/test/ui/borrowck/reborrow-sugg-move-then-borrow.stderr
@@ -0,0 +1,24 @@
+error[E0382]: borrow of moved value: `state`
+ --> $DIR/reborrow-sugg-move-then-borrow.rs:20:18
+ |
+LL | fn fill_memory_blocks_mt(state: &mut State) {
+ | ----- move occurs because `state` has type `&mut State`, which does not implement the `Copy` trait
+LL | for _ in state {}
+ | ----- `state` moved due to this implicit call to `.into_iter()`
+LL |
+LL | fill_segment(state);
+ | ^^^^^ value borrowed here after move
+ |
+note: this function takes ownership of the receiver `self`, which moves `state`
+ --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+ |
+LL | fn into_iter(self) -> Self::IntoIter;
+ | ^^^^
+help: consider creating a fresh reborrow of `state` here
+ |
+LL | for _ in &mut *state {}
+ | ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/suggest-assign-rvalue.rs b/src/test/ui/borrowck/suggest-assign-rvalue.rs
new file mode 100644
index 000000000..aaca9d47f
--- /dev/null
+++ b/src/test/ui/borrowck/suggest-assign-rvalue.rs
@@ -0,0 +1,57 @@
+#![allow(dead_code)]
+#![feature(never_type)]
+
+#[derive(Debug, Default)]
+struct Demo {}
+
+#[derive(Debug)]
+struct DemoNoDef {}
+
+fn apple(_: u32) {}
+
+fn banana() {
+ let chaenomeles;
+ apple(chaenomeles);
+ //~^ ERROR used binding `chaenomeles` isn't initialized [E0381]
+}
+
+fn main() {
+ let my_bool: bool = bool::default();
+ println!("my_bool: {}", my_bool);
+
+ let my_float: f32;
+ println!("my_float: {}", my_float);
+ //~^ ERROR used binding `my_float` isn't initialized
+ let demo: Demo;
+ println!("demo: {:?}", demo);
+ //~^ ERROR used binding `demo` isn't initialized
+
+ let demo_no: DemoNoDef;
+ println!("demo_no: {:?}", demo_no);
+ //~^ ERROR used binding `demo_no` isn't initialized
+
+ let arr: [i32; 5];
+ println!("arr: {:?}", arr);
+ //~^ ERROR used binding `arr` isn't initialized
+ let foo: Vec<&str>;
+ println!("foo: {:?}", foo);
+ //~^ ERROR used binding `foo` isn't initialized
+
+ let my_string: String;
+ println!("my_string: {}", my_string);
+ //~^ ERROR used binding `my_string` isn't initialized
+
+ let my_int: &i32;
+ println!("my_int: {}", *my_int);
+ //~^ ERROR used binding `my_int` isn't initialized
+
+ let hello: &str;
+ println!("hello: {}", hello);
+ //~^ ERROR used binding `hello` isn't initialized
+
+ let never: !;
+ println!("never: {}", never);
+ //~^ ERROR used binding `never` isn't initialized [E0381]
+
+ banana();
+}
diff --git a/src/test/ui/borrowck/suggest-assign-rvalue.stderr b/src/test/ui/borrowck/suggest-assign-rvalue.stderr
new file mode 100644
index 000000000..92acba640
--- /dev/null
+++ b/src/test/ui/borrowck/suggest-assign-rvalue.stderr
@@ -0,0 +1,138 @@
+error[E0381]: used binding `chaenomeles` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:14:11
+ |
+LL | let chaenomeles;
+ | ----------- binding declared here but left uninitialized
+LL | apple(chaenomeles);
+ | ^^^^^^^^^^^ `chaenomeles` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let chaenomeles = 0;
+ | +++
+
+error[E0381]: used binding `my_float` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:23:30
+ |
+LL | let my_float: f32;
+ | -------- binding declared here but left uninitialized
+LL | println!("my_float: {}", my_float);
+ | ^^^^^^^^ `my_float` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let my_float: f32 = 0.0;
+ | +++++
+
+error[E0381]: used binding `demo` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:26:28
+ |
+LL | let demo: Demo;
+ | ---- binding declared here but left uninitialized
+LL | println!("demo: {:?}", demo);
+ | ^^^^ `demo` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let demo: Demo = Default::default();
+ | ++++++++++++++++++++
+
+error[E0381]: used binding `demo_no` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:30:31
+ |
+LL | let demo_no: DemoNoDef;
+ | ------- binding declared here but left uninitialized
+LL | println!("demo_no: {:?}", demo_no);
+ | ^^^^^^^ `demo_no` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let demo_no: DemoNoDef = todo!();
+ | +++++++++
+
+error[E0381]: used binding `arr` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:34:27
+ |
+LL | let arr: [i32; 5];
+ | --- binding declared here but left uninitialized
+LL | println!("arr: {:?}", arr);
+ | ^^^ `arr` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let arr: [i32; 5] = todo!();
+ | +++++++++
+
+error[E0381]: used binding `foo` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:37:27
+ |
+LL | let foo: Vec<&str>;
+ | --- binding declared here but left uninitialized
+LL | println!("foo: {:?}", foo);
+ | ^^^ `foo` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let foo: Vec<&str> = vec![];
+ | ++++++++
+
+error[E0381]: used binding `my_string` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:41:31
+ |
+LL | let my_string: String;
+ | --------- binding declared here but left uninitialized
+LL | println!("my_string: {}", my_string);
+ | ^^^^^^^^^ `my_string` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let my_string: String = Default::default();
+ | ++++++++++++++++++++
+
+error[E0381]: used binding `my_int` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:45:28
+ |
+LL | let my_int: &i32;
+ | ------ binding declared here but left uninitialized
+LL | println!("my_int: {}", *my_int);
+ | ^^^^^^^ `*my_int` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let my_int: &i32 = todo!();
+ | +++++++++
+
+error[E0381]: used binding `hello` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:49:27
+ |
+LL | let hello: &str;
+ | ----- binding declared here but left uninitialized
+LL | println!("hello: {}", hello);
+ | ^^^^^ `hello` used here but it isn't initialized
+ |
+ = 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 assigning a value
+ |
+LL | let hello: &str = todo!();
+ | +++++++++
+
+error[E0381]: used binding `never` isn't initialized
+ --> $DIR/suggest-assign-rvalue.rs:53:27
+ |
+LL | let never: !;
+ | ----- binding declared here but left uninitialized
+LL | println!("never: {}", never);
+ | ^^^^^ `never` used here but it isn't initialized
+ |
+ = 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 10 previous errors
+
+For more information about this error, try `rustc --explain E0381`.
diff --git a/src/test/ui/borrowck/two-phase-across-loop.stderr b/src/test/ui/borrowck/two-phase-across-loop.stderr
index 95896c6bb..22f9b39df 100644
--- a/src/test/ui/borrowck/two-phase-across-loop.stderr
+++ b/src/test/ui/borrowck/two-phase-across-loop.stderr
@@ -2,7 +2,10 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> $DIR/two-phase-across-loop.rs:17:22
|
LL | strings.push(foo.get_string());
- | ^^^^^^^^^^^^^^^^ `foo` was mutably borrowed here in the previous iteration of the loop
+ | -------------^^^^^^^^^^^^^^^^-
+ | | |
+ | | `foo` was mutably borrowed here in the previous iteration of the loop
+ | first borrow used here, in later iteration of loop
error: aborting due to previous error
diff --git a/src/test/ui/box/issue-95036.rs b/src/test/ui/box/issue-95036.rs
index c2d4275aa..0611fabc1 100644
--- a/src/test/ui/box/issue-95036.rs
+++ b/src/test/ui/box/issue-95036.rs
@@ -1,7 +1,7 @@
// compile-flags: -O
// build-pass
-#![feature(allocator_api, bench_black_box)]
+#![feature(allocator_api)]
#[inline(never)]
pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) {
diff --git a/src/test/ui/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs
index 3623c4a4d..16add6ff2 100644
--- a/src/test/ui/builtin-clone-unwind.rs
+++ b/src/test/ui/builtin-clone-unwind.rs
@@ -3,7 +3,6 @@
#![allow(unused_variables)]
#![allow(unused_imports)]
-// ignore-wasm32-bare compiled with panic=abort by default
// Test that builtin implementations of `Clone` cleanup everything
// in case of unwinding.
diff --git a/src/test/ui/cast/cast-rfc0401.rs b/src/test/ui/cast/cast-rfc0401.rs
index 996fa013f..9a9875416 100644
--- a/src/test/ui/cast/cast-rfc0401.rs
+++ b/src/test/ui/cast/cast-rfc0401.rs
@@ -159,11 +159,7 @@ fn main()
assert!(foo as usize != bar as usize);
// Taking a few bits of a function's address is totally pointless and we detect that
- // Disabling the lint to ensure that the assertion can still be run
- #[allow(const_err)]
- {
- assert_eq!(foo as i16, foo as usize as i16);
- }
+ assert_eq!(foo as i16, foo as usize as i16);
// fptr-ptr-cast
diff --git a/src/test/ui/cast/issue-88621.rs b/src/test/ui/cast/issue-88621.rs
index 9242b80e2..1679793ee 100644
--- a/src/test/ui/cast/issue-88621.rs
+++ b/src/test/ui/cast/issue-88621.rs
@@ -1,5 +1,3 @@
-#![feature(arbitrary_enum_discriminant)]
-
#[repr(u8)]
enum Kind2 {
Foo() = 1,
diff --git a/src/test/ui/cast/issue-88621.stderr b/src/test/ui/cast/issue-88621.stderr
index e96d86651..886145c1b 100644
--- a/src/test/ui/cast/issue-88621.stderr
+++ b/src/test/ui/cast/issue-88621.stderr
@@ -1,5 +1,5 @@
error[E0605]: non-primitive cast: `Kind2` as `u8`
- --> $DIR/issue-88621.rs:11:13
+ --> $DIR/issue-88621.rs:9:13
|
LL | let _ = Kind2::Foo() as u8;
| ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/src/test/ui/catch-unwind-bang.rs b/src/test/ui/catch-unwind-bang.rs
index b31b5cab5..fb3503937 100644
--- a/src/test/ui/catch-unwind-bang.rs
+++ b/src/test/ui/catch-unwind-bang.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
fn worker() -> ! {
panic!()
diff --git a/src/test/ui/cenum_impl_drop_cast.stderr b/src/test/ui/cenum_impl_drop_cast.stderr
index 98c331057..b3f921c14 100644
--- a/src/test/ui/cenum_impl_drop_cast.stderr
+++ b/src/test/ui/cenum_impl_drop_cast.stderr
@@ -4,13 +4,13 @@ error: cannot cast enum `E` into integer `u32` because it implements `Drop`
LL | let i = e as u32;
| ^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
note: the lint level is defined here
--> $DIR/cenum_impl_drop_cast.rs:1:9
|
LL | #![deny(cenum_impl_drop_cast)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
error: aborting due to previous error
@@ -21,11 +21,11 @@ error: cannot cast enum `E` into integer `u32` because it implements `Drop`
LL | let i = e as u32;
| ^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
note: the lint level is defined here
--> $DIR/cenum_impl_drop_cast.rs:1:9
|
LL | #![deny(cenum_impl_drop_cast)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #73333 <https://github.com/rust-lang/rust/issues/73333>
diff --git a/src/test/ui/cfg/cfg-method-receiver-ok.rs b/src/test/ui/cfg/cfg-method-receiver-ok.rs
new file mode 100644
index 000000000..61ad3b8c1
--- /dev/null
+++ b/src/test/ui/cfg/cfg-method-receiver-ok.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+macro_rules! foo {
+ () => {
+ #[allow(unreachable_patterns)]
+ {
+ 123i32
+ }
+ };
+}
+
+fn main() {
+ let _ = foo!().abs();
+}
diff --git a/src/test/ui/cfg/cfg-method-receiver.rs b/src/test/ui/cfg/cfg-method-receiver.rs
new file mode 100644
index 000000000..71134ff17
--- /dev/null
+++ b/src/test/ui/cfg/cfg-method-receiver.rs
@@ -0,0 +1,11 @@
+macro_rules! cbor_map {
+ ($key:expr) => {
+ $key.signum();
+ //~^ ERROR can't call method `signum` on ambiguous numeric type `{integer}` [E0689]
+ };
+}
+
+fn main() {
+ cbor_map! { #[cfg(test)] 4};
+ //~^ ERROR removing an expression is not supported in this position
+}
diff --git a/src/test/ui/cfg/cfg-method-receiver.stderr b/src/test/ui/cfg/cfg-method-receiver.stderr
new file mode 100644
index 000000000..5767a7c1b
--- /dev/null
+++ b/src/test/ui/cfg/cfg-method-receiver.stderr
@@ -0,0 +1,24 @@
+error: removing an expression is not supported in this position
+ --> $DIR/cfg-method-receiver.rs:9:17
+ |
+LL | cbor_map! { #[cfg(test)] 4};
+ | ^^^^^^^^^^^^
+
+error[E0689]: can't call method `signum` on ambiguous numeric type `{integer}`
+ --> $DIR/cfg-method-receiver.rs:3:14
+ |
+LL | $key.signum();
+ | ^^^^^^
+...
+LL | cbor_map! { #[cfg(test)] 4};
+ | --------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `cbor_map` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you must specify a concrete type for this numeric value, like `i32`
+ |
+LL | cbor_map! { #[cfg(test)] 4_i32};
+ | ~~~~~
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0689`.
diff --git a/src/test/ui/cfg/cfg-panic.rs b/src/test/ui/cfg/cfg-panic.rs
index fb3e5059c..2de72d54a 100644
--- a/src/test/ui/cfg/cfg-panic.rs
+++ b/src/test/ui/cfg/cfg-panic.rs
@@ -1,9 +1,6 @@
// build-pass
// compile-flags: -C panic=unwind
// needs-unwind
-// ignore-emscripten no panic_unwind implementation
-// ignore-wasm32 no panic_unwind implementation
-// ignore-wasm64 no panic_unwind implementation
#[cfg(panic = "abort")]
diff --git a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
index b52535ffd..9ce4710d6 100644
--- a/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
+++ b/src/test/ui/cfg/future-compat-crate-attributes-using-cfg_attr.stderr
@@ -4,9 +4,9 @@ error: `crate_type` within an `#![cfg_attr] attribute is deprecated`
LL | #![cfg_attr(foo, crate_type="bin")]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #91632 <https://github.com/rust-lang/rust/issues/91632>
+ = note: `#[deny(deprecated_cfg_attr_crate_type_name)]` on by default
error: `crate_name` within an `#![cfg_attr] attribute is deprecated`
--> $DIR/future-compat-crate-attributes-using-cfg_attr.rs:9:18
diff --git a/src/test/ui/check-cfg/compact-values.stderr b/src/test/ui/check-cfg/compact-values.stderr
index a196e1537..9864aa385 100644
--- a/src/test/ui/check-cfg/compact-values.stderr
+++ b/src/test/ui/check-cfg/compact-values.stderr
@@ -4,8 +4,8 @@ warning: unexpected `cfg` condition value
LL | #[cfg(target(os = "linux", arch = "X"))]
| ^^^^^^^^^^
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: expected values for `target_arch` are: aarch64, arm, avr, bpf, hexagon, m68k, mips, mips64, msp430, nvptx64, powerpc, powerpc64, riscv32, riscv64, s390x, sparc, sparc64, wasm32, wasm64, x86, x86_64
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/check-cfg/empty-values.stderr b/src/test/ui/check-cfg/empty-values.stderr
index 10dab5034..a0168b2ca 100644
--- a/src/test/ui/check-cfg/empty-values.stderr
+++ b/src/test/ui/check-cfg/empty-values.stderr
@@ -6,8 +6,8 @@ LL | #[cfg(test = "value")]
| |
| help: remove the value
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: no expected value for `test`
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/check-cfg/invalid-cfg-value.stderr b/src/test/ui/check-cfg/invalid-cfg-value.stderr
index 7db2aadec..60abcb188 100644
--- a/src/test/ui/check-cfg/invalid-cfg-value.stderr
+++ b/src/test/ui/check-cfg/invalid-cfg-value.stderr
@@ -4,8 +4,8 @@ warning: unexpected `cfg` condition value
LL | #[cfg(feature = "sedre")]
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: expected values for `feature` are: full, serde
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition value
--> $DIR/invalid-cfg-value.rs:14:7
diff --git a/src/test/ui/check-cfg/no-values.stderr b/src/test/ui/check-cfg/no-values.stderr
index 7025b4cd7..8c926d187 100644
--- a/src/test/ui/check-cfg/no-values.stderr
+++ b/src/test/ui/check-cfg/no-values.stderr
@@ -4,8 +4,8 @@ warning: unexpected `cfg` condition value
LL | #[cfg(feature = "foo")]
| ^^^^^^^^^^^^^^^
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: no expected value for `feature`
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition value
--> $DIR/no-values.rs:10:7
diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr
index 24ce2280c..4ec74494f 100644
--- a/src/test/ui/check-cfg/well-known-values.stderr
+++ b/src/test/ui/check-cfg/well-known-values.stderr
@@ -6,8 +6,8 @@ LL | #[cfg(target_os = "linuz")]
| |
| help: did you mean: `"linux"`
|
- = note: `#[warn(unexpected_cfgs)]` on by default
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
+ = note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition value
--> $DIR/well-known-values.rs:14:7
diff --git a/src/test/ui/check-static-values-constraints.rs b/src/test/ui/check-static-values-constraints.rs
index eb4ecd8ba..f6a577d0d 100644
--- a/src/test/ui/check-static-values-constraints.rs
+++ b/src/test/ui/check-static-values-constraints.rs
@@ -63,7 +63,7 @@ static STATIC8: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
// This example should fail because field1 in the base struct is not safe
static STATIC9: SafeStruct = SafeStruct{field1: SafeEnum::Variant1,
..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
field2: SafeEnum::Variant1}};
struct UnsafeStruct;
diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr
index 3c193ca34..31939f7f6 100644
--- a/src/test/ui/check-static-values-constraints.stderr
+++ b/src/test/ui/check-static-values-constraints.stderr
@@ -1,4 +1,4 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `SafeStruct` cannot be evaluated at compile-time
--> $DIR/check-static-values-constraints.rs:65:43
|
LL | ..SafeStruct{field1: SafeEnum::Variant3(WithDtor),
@@ -7,7 +7,7 @@ LL | |
LL | | field2: SafeEnum::Variant1}};
| | ^- value is dropped here
| |________________________________________________________________________________|
- | statics cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in statics
error[E0010]: allocations are not allowed in statics
--> $DIR/check-static-values-constraints.rs:79:33
diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
index 284fc1c21..e6ddc6068 100644
--- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -26,7 +26,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
| ^ one type is more general than the other
|
= note: expected fn pointer `fn(&u32)`
- found fn pointer `for<'r> fn(&'r u32)`
+ found fn pointer `for<'a> fn(&'a u32)`
error[E0308]: mismatched types
--> $DIR/expect-fn-supply-fn.rs:39:50
@@ -34,7 +34,7 @@ error[E0308]: mismatched types
LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r> fn(&'r u32)`
+ = note: expected fn pointer `for<'a> fn(&'a u32)`
found fn pointer `fn(&u32)`
error[E0308]: mismatched types
@@ -43,7 +43,7 @@ error[E0308]: mismatched types
LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r> fn(&'r u32)`
+ = note: expected fn pointer `for<'a> fn(&'a u32)`
found fn pointer `fn(&u32)`
error: aborting due to 5 previous errors
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
index 7e767cba3..cf414adc0 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness.stderr
@@ -4,13 +4,13 @@ warning: value captured by `a` is never read
LL | a = 1;
| ^
|
+ = help: did you mean to capture by reference instead?
note: the lint level is defined here
--> $DIR/liveness.rs:5:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
- = help: did you mean to capture by reference instead?
warning: unused variable: `a`
--> $DIR/liveness.rs:33:9
@@ -18,8 +18,8 @@ warning: unused variable: `a`
LL | a += 1;
| ^
|
- = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
= help: did you mean to capture by reference instead?
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
warning: value assigned to `a` is never read
--> $DIR/liveness.rs:53:9
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
index 2ac801b49..0410de4c7 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/liveness_unintentional_copy.stderr
@@ -4,13 +4,13 @@ warning: value assigned to `a` is never read
LL | a = s;
| ^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/liveness_unintentional_copy.rs:4:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
- = help: maybe it is overwritten before being read?
warning: unused variable: `a`
--> $DIR/liveness_unintentional_copy.rs:20:9
@@ -18,8 +18,8 @@ warning: unused variable: `a`
LL | a = s;
| ^
|
- = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
= help: did you mean to capture by reference instead?
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
warning: unused variable: `a`
--> $DIR/liveness_unintentional_copy.rs:36:9
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
index 93abbecf4..508c4b911 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/repr_packed.stderr
@@ -4,11 +4,11 @@ error: reference to packed field is unaligned
LL | println!("{}", foo.x);
| ^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -20,10 +20,10 @@ error: reference to packed field is unaligned
LL | println!("{}", foo.x);
| ^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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)
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr
index 15689023d..b3cb558f9 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/issue-88118-2.stderr
@@ -4,9 +4,9 @@ warning: irrefutable `if let` guard pattern
LL | Registry if let _ = registry.try_find_description() => { }
| ^
|
- = note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the guard is useless
= help: consider removing the guard and adding a `let` inside the match arm
+ = note: `#[warn(irrefutable_let_patterns)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
index 3e921dc0f..c1679c6b6 100644
--- a/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/issue-90465.stderr
@@ -10,12 +10,12 @@ LL | let _ = f0;
LL | }
| - in Rust 2018, `f0` is dropped here along with the closure, but in Rust 2021 `f0` is not part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/issue-90465.rs:3:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f0` to be fully captured
|
LL ~ let c0 = move || {
diff --git a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
index 2a49ed4b5..384010859 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr
@@ -18,8 +18,8 @@ LL | | Variant::B => (),
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: closures are lazy and do nothing unless called
+ = note: `#[warn(unused_must_use)]` on by default
warning: unused closure that must be used
--> $DIR/issue-87097.rs:26:5
diff --git a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
index fea5441ec..ad061d93c 100644
--- a/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr
@@ -76,6 +76,11 @@ LL | let x: u8;
| - binding declared here but left uninitialized
LL | let c1 = || match x { };
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: u8 = 0;
+ | +++
error: aborting due to 8 previous errors
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
index d7104bafe..3a42cc8b8 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/auto_traits.stderr
@@ -7,12 +7,12 @@ LL | thread::spawn(move || unsafe {
LL | *fptr.0 = 20;
| ------- in Rust 2018, this closure captures all of `fptr`, but in Rust 2021, it will only capture `fptr.0`
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/auto_traits.rs:2:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `fptr` to be fully captured
|
LL ~ thread::spawn(move || { let _ = &fptr; unsafe {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr
index c611daf13..bb17e3a34 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr
@@ -15,13 +15,13 @@ LL | | println!("{:?}", x);
LL | | });
| |______- in this macro invocation
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/closure-body-macro-fragment.rs:4:9
|
LL | #![warn(rust_2021_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]`
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
help: add a dummy let to cause `a` to be fully captured
|
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr
index 832a81711..a0795c129 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/insignificant_drop_attr_migrations.stderr
@@ -10,12 +10,12 @@ LL | let _t = t.0;
LL | }
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/insignificant_drop_attr_migrations.rs:3:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
index 41b675f79..36a80e694 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/issue-78720.stderr
@@ -4,9 +4,9 @@ warning: irrefutable `if let` pattern
LL | if let a = "" {
| ^^^^^^^^^^
|
- = 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: 1 warning emitted
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr
index 2d0c56aad..c17edce72 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/macro.stderr
@@ -7,12 +7,12 @@ LL | let _ = || dbg!(a.0);
LL | }
| - in Rust 2018, `a` is dropped here, but in Rust 2021, only `a.0` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/macro.rs:5:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `a` to be fully captured
|
LL | let _ = || { let _ = &a; dbg!(a.0) };
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr
index 12760cc72..94526487e 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/migrations_rustfix.stderr
@@ -10,12 +10,12 @@ LL | let _t = t.0;
LL | }
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/migrations_rustfix.rs:2:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
index 89f393141..ff2244a8e 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.fixed
@@ -3,7 +3,6 @@
#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(fn_traits)]
#![feature(never_type)]
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
index 6b0b10521..52e96d013 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.rs
@@ -3,7 +3,6 @@
#![deny(rust_2021_incompatible_closure_captures)]
//~^ NOTE: the lint level is defined here
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(fn_traits)]
#![feature(never_type)]
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
index 2648b0043..e10898f98 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/mir_calls_to_shims.stderr
@@ -1,5 +1,5 @@
error: changes to closure capture in Rust 2021 will affect which traits the closure implements
- --> $DIR/mir_calls_to_shims.rs:21:38
+ --> $DIR/mir_calls_to_shims.rs:20:38
|
LL | let result = panic::catch_unwind(move || {
| ^^^^^^^
@@ -10,12 +10,12 @@ LL | let result = panic::catch_unwind(move || {
LL | f.0()
| --- in Rust 2018, this closure captures all of `f`, but in Rust 2021, it will only capture `f.0`
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/mir_calls_to_shims.rs:4:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f` to be fully captured
|
LL ~ let result = panic::catch_unwind(move || {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
index 96d5c936f..efb264447 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/multi_diagnostics.stderr
@@ -13,12 +13,12 @@ LL | let _f_2 = f2.1;
LL | }
| - in Rust 2018, `f2` is dropped here, but in Rust 2021, only `f2.1` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/multi_diagnostics.rs:2:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `f1`, `f2` to be fully captured
|
LL ~ let c = || {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
index aa9b8672a..eff26a4d6 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/precise.stderr
@@ -10,12 +10,12 @@ LL | let _t = t.0;
LL | }
| - in Rust 2018, `t` is dropped here, but in Rust 2021, only `t.0` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/precise.rs:3:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t` to be fully captured
|
LL ~ let c = || {
diff --git a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr
index 0d9f09ee3..54ad20f89 100644
--- a/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/migrations/significant_drop.stderr
@@ -20,12 +20,12 @@ LL | }
| in Rust 2018, `t1` is dropped here, but in Rust 2021, only `t1.0` will be dropped here as part of the closure
| in Rust 2018, `t2` is dropped here, but in Rust 2021, only `t2.0` will be dropped here as part of the closure
|
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
note: the lint level is defined here
--> $DIR/significant_drop.rs:2:9
|
LL | #![deny(rust_2021_incompatible_closure_captures)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
help: add a dummy let to cause `t`, `t1`, `t2` to be fully captured
|
LL ~ let c = || {
diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr
index 1a40326d9..8ad8273fc 100644
--- a/src/test/ui/closures/closure-bounds-subtype.stderr
+++ b/src/test/ui/closures/closure-bounds-subtype.stderr
@@ -11,6 +11,10 @@ note: required by a bound in `take_const_owned`
|
LL | fn take_const_owned<F>(_: F) where F: FnOnce() + Sync + Send {
| ^^^^ required by this bound in `take_const_owned`
+help: use parentheses to call this type parameter
+ |
+LL | take_const_owned(f());
+ | ++
help: consider further restricting this bound
|
LL | fn give_owned<F>(f: F) where F: FnOnce() + Send + std::marker::Sync {
diff --git a/src/test/ui/closures/closure-reform-bad.stderr b/src/test/ui/closures/closure-reform-bad.stderr
index 9dfff8499..4c40f70b9 100644
--- a/src/test/ui/closures/closure-reform-bad.stderr
+++ b/src/test/ui/closures/closure-reform-bad.stderr
@@ -8,7 +8,7 @@ LL | call_bare(f)
| |
| arguments to this function are incorrect
|
- = note: expected fn pointer `for<'r> fn(&'r str)`
+ = note: expected fn pointer `for<'a> fn(&'a str)`
found closure `[closure@$DIR/closure-reform-bad.rs:10:13: 10:22]`
note: closures can only be coerced to `fn` types if they do not capture any variables
--> $DIR/closure-reform-bad.rs:10:43
diff --git a/src/test/ui/closures/closure-return-type-must-be-sized.rs b/src/test/ui/closures/closure-return-type-must-be-sized.rs
new file mode 100644
index 000000000..8cfa02912
--- /dev/null
+++ b/src/test/ui/closures/closure-return-type-must-be-sized.rs
@@ -0,0 +1,74 @@
+#![feature(unboxed_closures)]
+
+trait A {
+ fn a() where Self: Sized;
+}
+
+mod a {
+ use crate::A;
+
+ pub fn foo<F: FnOnce<()>>() where F::Output: A {
+ F::Output::a()
+ }
+
+ pub fn bar<F: FnOnce() -> R, R: ?Sized>() {}
+
+ pub fn baz<F: FnOnce<()>>() where F::Output: A, F::Output: Sized {
+ F::Output::a()
+ }
+}
+
+mod b {
+ use crate::A;
+
+ pub fn foo<F: Fn<()>>() where F::Output: A {
+ F::Output::a()
+ }
+
+ pub fn bar<F: Fn() -> R, R: ?Sized>() {}
+
+ pub fn baz<F: Fn<()>>() where F::Output: A, F::Output: Sized {
+ F::Output::a()
+ }
+}
+
+mod c {
+ use crate::A;
+
+ pub fn foo<F: FnMut<()>>() where F::Output: A {
+ F::Output::a()
+ }
+
+ pub fn bar<F: FnMut() -> R, R: ?Sized>() {}
+
+ pub fn baz<F: FnMut<()>>() where F::Output: A, F::Output: Sized {
+ F::Output::a()
+ }
+}
+
+impl A for Box<dyn A> {
+ fn a() {}
+}
+
+fn main() {
+ a::foo::<fn() -> dyn A>(); //~ ERROR E0277
+ a::bar::<fn() -> dyn A, _>(); //~ ERROR E0277
+ a::baz::<fn() -> dyn A>(); //~ ERROR E0277
+ a::foo::<fn() -> Box<dyn A>>(); // ok
+ a::bar::<fn() -> Box<dyn A>, _>(); // ok
+ a::baz::<fn() -> Box<dyn A>>(); // ok
+
+ b::foo::<fn() -> dyn A>(); //~ ERROR E0277
+ b::bar::<fn() -> dyn A, _>(); //~ ERROR E0277
+ b::baz::<fn() -> dyn A>(); //~ ERROR E0277
+ b::foo::<fn() -> Box<dyn A>>(); // ok
+ b::bar::<fn() -> Box<dyn A>, _>(); // ok
+ b::baz::<fn() -> Box<dyn A>>(); // ok
+
+ c::foo::<fn() -> dyn A>(); //~ ERROR E0277
+ c::bar::<fn() -> dyn A, _>(); //~ ERROR E0277
+ c::baz::<fn() -> dyn A>(); //~ ERROR E0277
+ c::foo::<fn() -> Box<dyn A>>(); // ok
+ c::bar::<fn() -> Box<dyn A>, _>(); // ok
+ c::baz::<fn() -> Box<dyn A>>(); // ok
+}
diff --git a/src/test/ui/closures/closure-return-type-must-be-sized.stderr b/src/test/ui/closures/closure-return-type-must-be-sized.stderr
new file mode 100644
index 000000000..b07425bd8
--- /dev/null
+++ b/src/test/ui/closures/closure-return-type-must-be-sized.stderr
@@ -0,0 +1,99 @@
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:54:5
+ |
+LL | a::foo::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:55:14
+ |
+LL | a::bar::<fn() -> dyn A, _>();
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+note: required by a bound in `a::bar`
+ --> $DIR/closure-return-type-must-be-sized.rs:14:19
+ |
+LL | pub fn bar<F: FnOnce() -> R, R: ?Sized>() {}
+ | ^^^^^^^^^^^^^ required by this bound in `a::bar`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:56:5
+ |
+LL | a::baz::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:61:5
+ |
+LL | b::foo::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:62:14
+ |
+LL | b::bar::<fn() -> dyn A, _>();
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+note: required by a bound in `b::bar`
+ --> $DIR/closure-return-type-must-be-sized.rs:28:19
+ |
+LL | pub fn bar<F: Fn() -> R, R: ?Sized>() {}
+ | ^^^^^^^^^ required by this bound in `b::bar`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:63:5
+ |
+LL | b::baz::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:68:5
+ |
+LL | c::foo::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:69:14
+ |
+LL | c::bar::<fn() -> dyn A, _>();
+ | ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+note: required by a bound in `c::bar`
+ --> $DIR/closure-return-type-must-be-sized.rs:42:19
+ |
+LL | pub fn bar<F: FnMut() -> R, R: ?Sized>() {}
+ | ^^^^^^^^^^^^ required by this bound in `c::bar`
+
+error[E0277]: the size for values of type `dyn A` cannot be known at compilation time
+ --> $DIR/closure-return-type-must-be-sized.rs:70:5
+ |
+LL | c::baz::<fn() -> dyn A>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+ |
+ = help: within `fn() -> dyn A`, the trait `Sized` is not implemented for `dyn A`
+ = note: required because it appears within the type `fn() -> dyn A`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/closures/closure_promotion.rs b/src/test/ui/closures/closure_promotion.rs
index db36985af..47a8fc090 100644
--- a/src/test/ui/closures/closure_promotion.rs
+++ b/src/test/ui/closures/closure_promotion.rs
@@ -1,7 +1,5 @@
// build-pass (FIXME(62277): could be check-pass?)
-#![allow(const_err)]
-
fn main() {
let x: &'static _ = &|| { let z = 3; z };
}
diff --git a/src/test/ui/closures/issue-101696.rs b/src/test/ui/closures/issue-101696.rs
new file mode 100644
index 000000000..0a358bd16
--- /dev/null
+++ b/src/test/ui/closures/issue-101696.rs
@@ -0,0 +1,36 @@
+// check-pass
+
+use std::marker::PhantomData;
+
+#[derive(Default)]
+struct MyType<'a> {
+ field: usize,
+ _phantom: PhantomData<&'a ()>,
+}
+
+#[derive(Default)]
+struct MyTypeVariant<'a> {
+ field: usize,
+ _phantom: PhantomData<&'a ()>,
+}
+
+trait AsVariantTrait {
+ type Type;
+}
+
+impl<'a> AsVariantTrait for MyType<'a> {
+ type Type = MyTypeVariant<'a>;
+}
+
+type Variant<G> = <G as AsVariantTrait>::Type;
+
+fn foo<T: Default, F: FnOnce(T)>(f: F) {
+ let input = T::default();
+ f(input);
+}
+
+fn main() {
+ foo(|a: <MyType as AsVariantTrait>::Type| {
+ a.field;
+ });
+}
diff --git a/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs b/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs
new file mode 100644
index 000000000..043bf06a1
--- /dev/null
+++ b/src/test/ui/closures/issue-102089-multiple-opaque-cast.rs
@@ -0,0 +1,17 @@
+// edition:2021
+// check-pass
+
+pub struct Example<'a, T> {
+ a: T,
+ b: &'a T,
+}
+
+impl<'a, T> Example<'a, T> {
+ pub fn error_trying_to_destructure_self_in_closure(self) {
+ let closure = || {
+ let Self { a, b } = self;
+ };
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/issue-97607.rs b/src/test/ui/closures/issue-97607.rs
new file mode 100644
index 000000000..74c910ad0
--- /dev/null
+++ b/src/test/ui/closures/issue-97607.rs
@@ -0,0 +1,12 @@
+// check-pass
+#[allow(unused)]
+
+fn test<T, F, U>(f: F) -> Box<dyn Fn(T) -> U + 'static>
+where
+ F: 'static + Fn(T) -> U,
+ for<'a> U: 'a, // < This is the problematic line, see #97607
+{
+ Box::new(move |t| f(t))
+}
+
+fn main() {}
diff --git a/src/test/ui/closures/multiple-fn-bounds.rs b/src/test/ui/closures/multiple-fn-bounds.rs
new file mode 100644
index 000000000..6bb4098e2
--- /dev/null
+++ b/src/test/ui/closures/multiple-fn-bounds.rs
@@ -0,0 +1,15 @@
+fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
+ //~^ NOTE required by a bound in `foo`
+ //~| NOTE required by this bound in `foo`
+ //~| NOTE closure inferred to have a different signature due to this bound
+ todo!();
+}
+
+fn main() {
+ let v = true;
+ foo(move |x| v);
+ //~^ ERROR type mismatch in closure arguments
+ //~| NOTE expected closure signature
+ //~| NOTE expected due to this
+ //~| NOTE found signature defined here
+}
diff --git a/src/test/ui/closures/multiple-fn-bounds.stderr b/src/test/ui/closures/multiple-fn-bounds.stderr
new file mode 100644
index 000000000..eefc123fe
--- /dev/null
+++ b/src/test/ui/closures/multiple-fn-bounds.stderr
@@ -0,0 +1,24 @@
+error[E0631]: type mismatch in closure arguments
+ --> $DIR/multiple-fn-bounds.rs:10:5
+ |
+LL | foo(move |x| v);
+ | ^^^ -------- found signature defined here
+ | |
+ | expected due to this
+ |
+ = note: expected closure signature `fn(char) -> _`
+ found closure signature `for<'a> fn(&'a char) -> _`
+note: closure inferred to have a different signature due to this bound
+ --> $DIR/multiple-fn-bounds.rs:1:11
+ |
+LL | fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
+ | ^^^^^^^^^^^^^^^^^
+note: required by a bound in `foo`
+ --> $DIR/multiple-fn-bounds.rs:1:31
+ |
+LL | fn foo<F: Fn(&char) -> bool + Fn(char) -> bool>(f: F) {
+ | ^^^^^^^^^^^^^^^^ required by this bound in `foo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0631`.
diff --git a/src/test/ui/closures/old-closure-expression-remove-semicolon.fixed b/src/test/ui/closures/old-closure-expression-remove-semicolon.fixed
index 623e917da..8aa9e952b 100644
--- a/src/test/ui/closures/old-closure-expression-remove-semicolon.fixed
+++ b/src/test/ui/closures/old-closure-expression-remove-semicolon.fixed
@@ -7,6 +7,6 @@ fn foo() -> i32 {
fn main() {
let _x: i32 = {
//~^ ERROR mismatched types
- foo() //~ HELP remove this semicolon
+ foo() //~ HELP remove this semicolon to return this value
};
}
diff --git a/src/test/ui/closures/old-closure-expression-remove-semicolon.rs b/src/test/ui/closures/old-closure-expression-remove-semicolon.rs
index 4974b0866..912c7a331 100644
--- a/src/test/ui/closures/old-closure-expression-remove-semicolon.rs
+++ b/src/test/ui/closures/old-closure-expression-remove-semicolon.rs
@@ -7,6 +7,6 @@ fn foo() -> i32 {
fn main() {
let _x: i32 = {
//~^ ERROR mismatched types
- foo(); //~ HELP remove this semicolon
+ foo(); //~ HELP remove this semicolon to return this value
};
}
diff --git a/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr b/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
index 9b73ce4fe..bc54ab4d5 100644
--- a/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
+++ b/src/test/ui/closures/old-closure-expression-remove-semicolon.stderr
@@ -5,7 +5,7 @@ LL | let _x: i32 = {
| ___________________^
LL | |
LL | | foo();
- | | - help: remove this semicolon
+ | | - help: remove this semicolon to return this value
LL | | };
| |_____^ expected `i32`, found `()`
diff --git a/src/test/ui/codemap_tests/unicode.normal.stderr b/src/test/ui/codemap_tests/unicode.normal.stderr
index 60f8cff84..05ceb6910 100644
--- a/src/test/ui/codemap_tests/unicode.normal.stderr
+++ b/src/test/ui/codemap_tests/unicode.normal.stderr
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
LL | extern "路濫狼á́́" fn foo() {}
| ^^^^^^^^^ invalid ABI
|
- = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted, rust-cold
+ = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
error: aborting due to previous error
diff --git a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
index a4843bca5..4c04bb113 100644
--- a/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
+++ b/src/test/ui/coercion/coercion-missing-tail-expected-type.stderr
@@ -6,7 +6,7 @@ LL | fn plus_one(x: i32) -> i32 {
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | x + 1;
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error[E0308]: mismatched types
--> $DIR/coercion-missing-tail-expected-type.rs:8:13
@@ -16,7 +16,7 @@ LL | fn foo() -> Result<u8, u64> {
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Ok(1);
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
|
= note: expected enum `Result<u8, u64>`
found unit type `()`
diff --git a/src/test/ui/coercion/issue-36007.rs b/src/test/ui/coercion/issue-36007.rs
new file mode 100644
index 000000000..78812df87
--- /dev/null
+++ b/src/test/ui/coercion/issue-36007.rs
@@ -0,0 +1,20 @@
+// check-pass
+#![feature(coerce_unsized, unsize)]
+
+use std::marker::Unsize;
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized>(Box<T>);
+
+impl<T> CoerceUnsized<Foo<dyn Baz>> for Foo<T> where T: Unsize<dyn Baz> {}
+
+struct Bar;
+
+trait Baz {}
+
+impl Baz for Bar {}
+
+fn main() {
+ let foo = Foo(Box::new(Bar));
+ let foobar: Foo<Bar> = foo;
+}
diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr
index b08ccb087..632018782 100644
--- a/src/test/ui/coherence/coherence-default-trait-impl.stderr
+++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr
@@ -3,12 +3,24 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe
|
LL | unsafe impl MySafeTrait for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: remove `unsafe` from this trait implementation
+ |
+LL - unsafe impl MySafeTrait for Foo {}
+LL + impl MySafeTrait for Foo {}
+ |
error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
--> $DIR/coherence-default-trait-impl.rs:13:1
|
LL | impl MyUnsafeTrait for Foo {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl MyUnsafeTrait for Foo {}
+ | ++++++
error: aborting due to 2 previous errors
diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
index cfcef9699..7dabd97b9 100644
--- a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
+++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr
@@ -1,10 +1,10 @@
-error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> fn(&'r ()))`
+error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))`
--> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
|
LL | impl Trait for for<'r> fn(fn(&'r ())) {}
| ------------------------------------- first implementation here
LL | impl<'a> Trait for fn(fn(&'a ())) {}
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> fn(&'r ()))`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))`
|
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
diff --git a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr
index 8612ce60d..201871204 100644
--- a/src/test/ui/coherence/coherence-fn-implied-bounds.stderr
+++ b/src/test/ui/coherence/coherence-fn-implied-bounds.stderr
@@ -7,14 +7,14 @@ LL |
LL | impl Trait for for<'c> fn(&'c &'c u32, &'c &'c u32) -> &'c u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a &'b u32, &'b &'a u32) -> &'b u32`
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
+ = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
note: the lint level is defined here
--> $DIR/coherence-fn-implied-bounds.rs:15:9
|
LL | #![deny(coherence_leak_check)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
- = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr
index af18655b0..e2d84b833 100644
--- a/src/test/ui/coherence/coherence-free-vs-bound-region.stderr
+++ b/src/test/ui/coherence/coherence-free-vs-bound-region.stderr
@@ -7,14 +7,14 @@ LL |
LL | impl TheTrait for fn(&u8) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&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 #56105 <https://github.com/rust-lang/rust/issues/56105>
+ = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
note: the lint level is defined here
--> $DIR/coherence-free-vs-bound-region.rs:10:9
|
LL | #![deny(coherence_leak_check)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
- = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
index 97f3c7593..7bd50649d 100644
--- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0391]: cycle detected when building specialization graph of trait `Trait`
--> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
diff --git a/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs b/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs
new file mode 100644
index 000000000..563f28e22
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-copy-bad.rs
@@ -0,0 +1,11 @@
+#![feature(negative_impls)]
+#![crate_type = "lib"]
+
+impl !Copy for str {}
+//~^ ERROR only traits defined in the current crate can be implemented
+
+impl !Copy for fn() {}
+//~^ ERROR only traits defined in the current crate can be implemented
+
+impl !Copy for () {}
+//~^ ERROR only traits defined in the current crate can be implemented
diff --git a/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr b/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr
new file mode 100644
index 000000000..2295d6315
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-copy-bad.stderr
@@ -0,0 +1,36 @@
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+ --> $DIR/coherence-negative-impls-copy-bad.rs:4:1
+ |
+LL | impl !Copy for str {}
+ | ^^^^^^^^^^^^^^^---
+ | | |
+ | | `str` is not defined in the current crate
+ | impl doesn't use only types from inside the current crate
+ |
+ = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+ --> $DIR/coherence-negative-impls-copy-bad.rs:7:1
+ |
+LL | impl !Copy for fn() {}
+ | ^^^^^^^^^^^^^^^----
+ | | |
+ | | `fn()` is not defined in the current crate
+ | impl doesn't use only types from inside the current crate
+ |
+ = note: define and implement a trait or new type instead
+
+error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
+ --> $DIR/coherence-negative-impls-copy-bad.rs:10:1
+ |
+LL | impl !Copy for () {}
+ | ^^^^^^^^^^^^^^^--
+ | | |
+ | | this is not defined in the current crate because tuples are always foreign
+ | impl doesn't use only types from inside the current crate
+ |
+ = note: define and implement a trait or new type instead
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0117`.
diff --git a/src/test/ui/coherence/coherence-negative-impls-copy.rs b/src/test/ui/coherence/coherence-negative-impls-copy.rs
new file mode 100644
index 000000000..7b29aade4
--- /dev/null
+++ b/src/test/ui/coherence/coherence-negative-impls-copy.rs
@@ -0,0 +1,29 @@
+// check-pass
+// regression test for issue #101836
+
+#![feature(negative_impls, extern_types)]
+#![crate_type = "lib"]
+
+struct NonCopy;
+struct NeverCopy(NonCopy);
+
+impl !Copy for NeverCopy {}
+
+
+struct WithDrop;
+impl Drop for WithDrop { fn drop(&mut self) {} }
+
+impl !Copy for WithDrop {}
+
+
+struct Type;
+trait Trait {}
+extern {
+ type ExternType;
+}
+
+impl !Copy for &mut Type {}
+
+impl !Copy for dyn Trait {}
+
+impl !Copy for ExternType {}
diff --git a/src/test/ui/coherence/coherence-subtyping.stderr b/src/test/ui/coherence/coherence-subtyping.stderr
index 25d8c8756..9d90019a5 100644
--- a/src/test/ui/coherence/coherence-subtyping.stderr
+++ b/src/test/ui/coherence/coherence-subtyping.stderr
@@ -7,10 +7,10 @@ LL |
LL | impl TheTrait for for<'a> fn(&'a u8, &'a u8) -> &'a u8 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
|
- = note: `#[warn(coherence_leak_check)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+ = note: `#[warn(coherence_leak_check)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/coherence/coherence-wasm-bindgen.stderr b/src/test/ui/coherence/coherence-wasm-bindgen.stderr
index aa74e2315..cfcc21240 100644
--- a/src/test/ui/coherence/coherence-wasm-bindgen.stderr
+++ b/src/test/ui/coherence/coherence-wasm-bindgen.stderr
@@ -7,15 +7,15 @@ LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(A) -> R + 'b)
LL | impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn for<'x> Fn(&'x A) -> R + 'b)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&dyn std::ops::Fn(&_) -> _`
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
+ = note: downstream crates may implement trait `FromWasmAbi` for type `&_`
+ = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
note: the lint level is defined here
--> $DIR/coherence-wasm-bindgen.rs:10:9
|
LL | #![deny(coherence_leak_check)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
- = note: downstream crates may implement trait `FromWasmAbi` for type `&_`
- = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
error: aborting due to previous error
diff --git a/src/test/ui/coherence/deep-bad-copy-reason.stderr b/src/test/ui/coherence/deep-bad-copy-reason.stderr
index 295538cee..168ee5726 100644
--- a/src/test/ui/coherence/deep-bad-copy-reason.stderr
+++ b/src/test/ui/coherence/deep-bad-copy-reason.stderr
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/deep-bad-copy-reason.rs:33:15
+ --> $DIR/deep-bad-copy-reason.rs:33:24
|
LL | pub struct List<'tcx, T>(Interned<'tcx, ListS<T>>);
| ------------------------ this field does not implement `Copy`
...
LL | impl<'tcx, T> Copy for List<'tcx, T> {}
- | ^^^^
+ | ^^^^^^^^^^^^^
|
note: the `Copy` impl for `Interned<'tcx, ListS<T>>` requires that `OpaqueListContents: Sized`
--> $DIR/deep-bad-copy-reason.rs:23:26
diff --git a/src/test/ui/command/command-current-dir.rs b/src/test/ui/command/command-current-dir.rs
index 69a0b486d..5d06fcdeb 100644
--- a/src/test/ui/command/command-current-dir.rs
+++ b/src/test/ui/command/command-current-dir.rs
@@ -1,6 +1,7 @@
// run-pass
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia Needs directory creation privilege
use std::env;
use std::fs;
diff --git a/src/test/ui/command/command-exec.rs b/src/test/ui/command/command-exec.rs
index 0af87214f..032dad184 100644
--- a/src/test/ui/command/command-exec.rs
+++ b/src/test/ui/command/command-exec.rs
@@ -5,6 +5,7 @@
// ignore-pretty issue #37199
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia no execvp syscall provided
#![feature(process_exec)]
diff --git a/src/test/ui/command/command-pre-exec.rs b/src/test/ui/command/command-pre-exec.rs
index 61914e229..d366c5ffb 100644
--- a/src/test/ui/command/command-pre-exec.rs
+++ b/src/test/ui/command/command-pre-exec.rs
@@ -6,6 +6,7 @@
// ignore-windows - this is a unix-specific test
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia no execvp syscall
#![feature(process_exec, rustc_private)]
extern crate libc;
diff --git a/src/test/ui/command/command-uid-gid.rs b/src/test/ui/command/command-uid-gid.rs
index e1eb4b140..aa4e2f5b8 100644
--- a/src/test/ui/command/command-uid-gid.rs
+++ b/src/test/ui/command/command-uid-gid.rs
@@ -2,6 +2,7 @@
// ignore-android
// ignore-emscripten
// ignore-sgx
+// ignore-fuchsia no '/bin/sh', '/bin/ls'
#![feature(rustc_private)]
diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr
index 84bbec062..ee63f34b7 100644
--- a/src/test/ui/compare-method/issue-90444.stderr
+++ b/src/test/ui/compare-method/issue-90444.stderr
@@ -5,10 +5,10 @@ LL | fn from(_: fn((), (), &mut ())) -> Self {
| ^^^^^^^^^^^^^^^^^^^
| |
| types differ in mutability
- | help: change the parameter type to match the trait: `for<'r> fn((), (), &'r ())`
+ | help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())`
|
- = note: expected fn pointer `fn(for<'r> fn((), (), &'r ())) -> A`
- found fn pointer `fn(for<'r> fn((), (), &'r mut ())) -> A`
+ = note: expected fn pointer `fn(for<'a> fn((), (), &'a ())) -> A`
+ found fn pointer `fn(for<'a> fn((), (), &'a mut ())) -> A`
error[E0053]: method `from` has an incompatible type for trait
--> $DIR/issue-90444.rs:11:16
diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr
index 0c7c50d67..4dcd8f4fc 100644
--- a/src/test/ui/conflicting-repr-hints.stderr
+++ b/src/test/ui/conflicting-repr-hints.stderr
@@ -4,9 +4,9 @@ error[E0566]: conflicting representation hints
LL | #[repr(C, u64)]
| ^ ^^^
|
- = note: `#[deny(conflicting_repr_hints)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+ = note: `#[deny(conflicting_repr_hints)]` on by default
error[E0566]: conflicting representation hints
--> $DIR/conflicting-repr-hints.rs:19:8
diff --git a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
index c62f1d1d2..0ed370b83 100644
--- a/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
+++ b/src/test/ui/const-generics/const-generic-default-wont-borrowck.stderr
@@ -5,6 +5,11 @@ LL | let s: &'static str; s.len()
| - ^^^^^^^ `*s` used here but it isn't initialized
| |
| binding declared here but left uninitialized
+ |
+help: consider assigning a value
+ |
+LL | let s: &'static str = todo!(); s.len()
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs
index 8724fa698..6e04cfaec 100644
--- a/src/test/ui/const-generics/const_trait_fn-issue-88433.rs
+++ b/src/test/ui/const-generics/const_trait_fn-issue-88433.rs
@@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Func<T> {
type Output;
diff --git a/src/test/ui/const-generics/generic_const_exprs/closures.stderr b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
index a15dd2016..a7d891d77 100644
--- a/src/test/ui/const-generics/generic_const_exprs/closures.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/closures.stderr
@@ -1,4 +1,4 @@
-error[E0391]: cycle detected when building an abstract representation for test::{constant#0}
+error[E0391]: cycle detected when building an abstract representation for `test::{constant#0}`
--> $DIR/closures.rs:3:35
|
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
@@ -14,7 +14,7 @@ note: ...which requires type-checking `test::{constant#0}`...
|
LL | fn test<const N: usize>() -> [u8; N + (|| 42)()] {}
| ^^^^^^^^^^^^^
- = note: ...which again requires building an abstract representation for test::{constant#0}, completing the cycle
+ = note: ...which again requires building an abstract representation for `test::{constant#0}`, completing the cycle
note: cycle used when checking that `test` is well-formed
--> $DIR/closures.rs:3:1
|
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
index 4cd86fecd..d674e3acd 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr
@@ -1,5 +1,5 @@
error: generic parameters may not be used in const operations
- --> $DIR/dependence_lint.rs:13:32
+ --> $DIR/dependence_lint.rs:14:32
|
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
| ^ cannot perform const operation using `T`
@@ -8,7 +8,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/dependence_lint.rs:20:37
+ --> $DIR/dependence_lint.rs:21:37
|
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
| ^ cannot perform const operation using `T`
@@ -17,17 +17,17 @@ LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable,
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/dependence_lint.rs:9:9
+ --> $DIR/dependence_lint.rs:10:9
|
LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(const_evaluatable_unchecked)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/dependence_lint.rs:16:9
+ --> $DIR/dependence_lint.rs:17:9
|
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
index b13bcdb2c..74111ef1d 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.gce.stderr
@@ -1,5 +1,5 @@
error: overly complex generic constant
- --> $DIR/dependence_lint.rs:16:9
+ --> $DIR/dependence_lint.rs:17:9
|
LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error with gce
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
@@ -7,7 +7,7 @@ LL | [0; if false { size_of::<T>() } else { 3 }]; // lint on stable, error w
= help: consider moving this anonymous constant into a `const` function
error: overly complex generic constant
- --> $DIR/dependence_lint.rs:20:17
+ --> $DIR/dependence_lint.rs:21:17
|
LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable, error with gce
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ control flow is not supported in generic constants
@@ -15,7 +15,7 @@ LL | let _: [u8; if true { size_of::<T>() } else { 3 }]; // error on stable,
= help: consider moving this anonymous constant into a `const` function
error: unconstrained generic constant
- --> $DIR/dependence_lint.rs:13:12
+ --> $DIR/dependence_lint.rs:14:12
|
LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce
= help: try adding a `where` bound using this expression: `where [(); size_of::<*mut T>()]:`
error: unconstrained generic constant
- --> $DIR/dependence_lint.rs:9:9
+ --> $DIR/dependence_lint.rs:10:9
|
LL | [0; size_of::<*mut T>()]; // lint on stable, error with `generic_const_exprs`
| ^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
index dcdfd75de..b715e07f8 100644
--- a/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/dependence_lint.rs
@@ -1,4 +1,5 @@
// revisions: full gce
+// compile-flags: -Zdeduplicate-diagnostics=yes
#![cfg_attr(gce, feature(generic_const_exprs))]
#![allow(incomplete_features)]
diff --git a/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr b/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr
index b5719b3fe..8eb1fccc5 100644
--- a/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/eval-try-unify.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.rs b/src/test/ui/const-generics/generic_const_exprs/function-call.rs
index b5de66621..3c866333d 100644
--- a/src/test/ui/const-generics/generic_const_exprs/function-call.rs
+++ b/src/test/ui/const-generics/generic_const_exprs/function-call.rs
@@ -1,4 +1,5 @@
// check-pass
+// compile-flags: -Zdeduplicate-diagnostics=yes
const fn foo<T>() -> usize {
// We might instead branch on `std::mem::size_of::<*mut T>() < 8` here,
diff --git a/src/test/ui/const-generics/generic_const_exprs/function-call.stderr b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
index 0d8463714..84abfe578 100644
--- a/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/function-call.stderr
@@ -1,12 +1,12 @@
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/function-call.rs:14:17
+ --> $DIR/function-call.rs:15:17
|
LL | let _ = [0; foo::<T>()];
| ^^^^^^^^^^
|
- = note: `#[warn(const_evaluatable_unchecked)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-102074.rs b/src/test/ui/const-generics/generic_const_exprs/issue-102074.rs
new file mode 100644
index 000000000..66d15cf12
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-102074.rs
@@ -0,0 +1,23 @@
+// check-pass
+// Checks that the NoopMethodCall lint doesn't call Instance::resolve on unresolved consts
+
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+#[derive(Debug, Clone)]
+pub struct Aes128CipherKey([u8; Aes128Cipher::KEY_LEN]);
+
+impl Aes128CipherKey {
+ pub fn new(key: &[u8; Aes128Cipher::KEY_LEN]) -> Self {
+ Self(key.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Aes128Cipher;
+
+impl Aes128Cipher {
+ const KEY_LEN: usize = 16;
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-102768.rs b/src/test/ui/const-generics/generic_const_exprs/issue-102768.rs
new file mode 100644
index 000000000..7aea0d30d
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-102768.rs
@@ -0,0 +1,14 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait X {
+ type Y<'a>;
+}
+
+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
+};
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr
new file mode 100644
index 000000000..9deb9b265
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-102768.stderr
@@ -0,0 +1,33 @@
+error[E0107]: this 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 ()>>) {}
+ | ^ expected 1 lifetime argument
+ |
+note: associated type defined here, with 1 lifetime parameter: `'a`
+ --> $DIR/issue-102768.rs:5:10
+ |
+LL | type Y<'a>;
+ | ^ --
+help: add missing lifetime argument
+ |
+LL | fn f2<'a>(arg: Box<dyn X<Y<'a, 1> = &'a ()>>) {}
+ | +++
+
+error[E0107]: this associated type takes 0 generic arguments but 1 generic argument was supplied
+ --> $DIR/issue-102768.rs:9:30
+ |
+LL | fn f2<'a>(arg: Box<dyn X<Y<1> = &'a ()>>) {}
+ | ^--- help: remove these generics
+ | |
+ | expected 0 generic arguments
+ |
+note: associated type defined here, with 0 generic parameters
+ --> $DIR/issue-102768.rs:5:10
+ |
+LL | type Y<'a>;
+ | ^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
index b5b2b0e40..1cceaece7 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-1.stderr
@@ -4,8 +4,8 @@ warning: the feature `adt_const_params` is incomplete and may not be safe to use
LL | #![feature(adt_const_params, generic_const_exprs)]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> 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/issue-97047-ice-1.rs:3:30
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
index 5dfbd87cc..774e842bc 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-97047-ice-2.stderr
@@ -4,8 +4,8 @@ warning: the feature `adt_const_params` is incomplete and may not be safe to use
LL | #![feature(adt_const_params, generic_const_exprs)]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> 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/issue-97047-ice-2.rs:3:30
diff --git a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
index 45c7d835f..440cf457e 100644
--- a/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/object-safety-err-where-bounds.stderr
@@ -4,11 +4,6 @@ error: the trait `Foo` cannot be made into an object
LL | fn test(&self) where [u8; bar::<Self>()]: Sized;
| ^^^^
|
-note: the lint level is defined here
- --> $DIR/object-safety-err-where-bounds.rs:3:9
- |
-LL | #![deny(where_clauses_object_safety)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
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>
@@ -19,6 +14,11 @@ LL | trait Foo {
LL | fn test(&self) where [u8; bar::<Self>()]: Sized;
| ^^^^ ...because method `test` references the `Self` type in its `where` clause
= help: consider moving `test` to another trait
+note: the lint level is defined here
+ --> $DIR/object-safety-err-where-bounds.rs:3:9
+ |
+LL | #![deny(where_clauses_object_safety)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/const-generics/invariant.stderr b/src/test/ui/const-generics/invariant.stderr
index ce0fad104..aabe4c93b 100644
--- a/src/test/ui/const-generics/invariant.stderr
+++ b/src/test/ui/const-generics/invariant.stderr
@@ -7,10 +7,10 @@ LL | impl SadBee for for<'a> fn(&'a ()) {
LL | impl SadBee for fn(&'static ()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'a> fn(&'a ())`
|
- = note: `#[warn(coherence_leak_check)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56105 <https://github.com/rust-lang/rust/issues/56105>
= note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details
+ = note: `#[warn(coherence_leak_check)]` on by default
error[E0308]: mismatched types
--> $DIR/invariant.rs:27:5
diff --git a/src/test/ui/const-generics/issue-102124.rs b/src/test/ui/const-generics/issue-102124.rs
new file mode 100644
index 000000000..a28f198e9
--- /dev/null
+++ b/src/test/ui/const-generics/issue-102124.rs
@@ -0,0 +1,20 @@
+// run-pass
+// compile-flags: -Zmir-opt-level=3
+
+// regression test for #102124
+
+const L: usize = 4;
+
+pub trait Print<const N: usize> {
+ fn print(&self) -> usize {
+ N
+ }
+}
+
+pub struct Printer;
+impl Print<L> for Printer {}
+
+fn main() {
+ let p = Printer;
+ assert_eq!(p.print(), 4);
+}
diff --git a/src/test/ui/const-generics/issue-103243.rs b/src/test/ui/const-generics/issue-103243.rs
deleted file mode 100644
index 78c73522b..000000000
--- a/src/test/ui/const-generics/issue-103243.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-// build-pass
-
-pub trait CSpace<const N: usize>: Sized {
- type Traj;
-}
-
-pub trait FullTrajectory<T, S1, const N: usize> {}
-
-pub struct Const<const R: usize>;
-
-pub trait Obstacle<CS, const N: usize>
-where
- CS: CSpace<N>,
-{
- fn trajectory_free<FT, S1>(&self, t: &FT)
- where
- FT: FullTrajectory<CS::Traj, S1, N>;
-}
-
-// -----
-
-const N: usize = 4;
-
-struct ObstacleSpace2df32;
-
-impl<CS> Obstacle<CS, N> for ObstacleSpace2df32
-where
- CS: CSpace<N>,
-{
- fn trajectory_free<TF, S1>(&self, t: &TF)
- where
- TF: FullTrajectory<CS::Traj, S1, N>,
- {
- }
-}
-
-fn main() {}
diff --git a/src/test/ui/const-generics/issue-80471.stderr b/src/test/ui/const-generics/issue-80471.stderr
index dbcc0b7b6..b89706710 100644
--- a/src/test/ui/const-generics/issue-80471.stderr
+++ b/src/test/ui/const-generics/issue-80471.stderr
@@ -4,8 +4,8 @@ warning: the feature `adt_const_params` is incomplete and may not be safe to use
LL | #![feature(adt_const_params)]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0741]: `Box<Nat>` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter
--> $DIR/issue-80471.rs:10:17
diff --git a/src/test/ui/const-generics/issue-93647.rs b/src/test/ui/const-generics/issue-93647.rs
index c1a6bf6e3..806540e17 100644
--- a/src/test/ui/const-generics/issue-93647.rs
+++ b/src/test/ui/const-generics/issue-93647.rs
@@ -1,6 +1,6 @@
struct X<const N: usize = {
(||1usize)()
- //~^ ERROR cannot call
+ //~^ ERROR cannot call non-const closure
}>;
fn main() {}
diff --git a/src/test/ui/const-generics/issues/issue-83466.stderr b/src/test/ui/const-generics/issues/issue-83466.stderr
index a60f71ea6..bcfd70639 100644
--- a/src/test/ui/const-generics/issues/issue-83466.stderr
+++ b/src/test/ui/const-generics/issues/issue-83466.stderr
@@ -7,9 +7,9 @@ LL | fn func<'a, U>(self) -> U {
LL | S.func::<'a, 10_u32>()
| ^^
|
- = note: `#[warn(late_bound_lifetime_arguments)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+ = note: `#[warn(late_bound_lifetime_arguments)]` on by default
error[E0747]: constant provided when a type was expected
--> $DIR/issue-83466.rs:11:18
diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr
index d5f914f46..4becf3a36 100644
--- a/src/test/ui/const-generics/issues/issue-83765.stderr
+++ b/src/test/ui/const-generics/issues/issue-83765.stderr
@@ -1,16 +1,16 @@
-error[E0391]: cycle detected when resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`
+error[E0391]: cycle detected when resolving instance `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>::DIM`
--> $DIR/issue-83765.rs:5:5
|
LL | const DIM: usize;
| ^^^^^^^^^^^^^^^^
|
-note: ...which requires computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`...
+note: ...which requires computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>`...
--> $DIR/issue-83765.rs:4:1
|
LL | trait TensorDimension {
| ^^^^^^^^^^^^^^^^^^^^^
- = note: ...which again requires resolving instance `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
-note: cycle used when computing candidate for `<LazyUpdim<T, { T::DIM }, DIM> as TensorDimension>`
+ = note: ...which again requires resolving instance `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>::DIM`, completing the cycle
+note: cycle used when computing candidate for `<LazyUpdim<'_, T, { T::DIM }, DIM> as TensorDimension>`
--> $DIR/issue-83765.rs:4:1
|
LL | trait TensorDimension {
diff --git a/src/test/ui/const-generics/issues/issue-88119.rs b/src/test/ui/const-generics/issues/issue-88119.rs
index 70dfa7f70..647b0eea8 100644
--- a/src/test/ui/const-generics/issues/issue-88119.rs
+++ b/src/test/ui/const-generics/issues/issue-88119.rs
@@ -3,6 +3,7 @@
#![allow(incomplete_features)]
#![feature(const_trait_impl, generic_const_exprs)]
+#[const_trait]
trait ConstName {
const NAME_BYTES: &'static [u8];
}
diff --git a/src/test/ui/const-generics/issues/issue-98629.rs b/src/test/ui/const-generics/issues/issue-98629.rs
index fc8666bbc..1d2d3012a 100644
--- a/src/test/ui/const-generics/issues/issue-98629.rs
+++ b/src/test/ui/const-generics/issues/issue-98629.rs
@@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Trait {
const N: usize;
}
diff --git a/src/test/ui/const-generics/issues/issue-98629.stderr b/src/test/ui/const-generics/issues/issue-98629.stderr
index 535702208..4a248be76 100644
--- a/src/test/ui/const-generics/issues/issue-98629.stderr
+++ b/src/test/ui/const-generics/issues/issue-98629.stderr
@@ -1,5 +1,5 @@
error[E0046]: not all trait items implemented, missing: `N`
- --> $DIR/issue-98629.rs:7:1
+ --> $DIR/issue-98629.rs:8:1
|
LL | const N: usize;
| -------------- `N` from trait
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.rs b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
index 7840989cb..8e667aeba 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-expression.rs
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
@@ -1,3 +1,4 @@
+// compile-flags: -Zdeduplicate-diagnostics=yes
use std::mem::size_of;
fn test<const N: usize>() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
index bf0d0f352..deabd05a6 100644
--- a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
@@ -1,5 +1,5 @@
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:9:38
+ --> $DIR/complex-expression.rs:10:38
|
LL | struct Break0<const N: usize>([u8; { N + 1 }]);
| ^ cannot perform const operation using `N`
@@ -8,7 +8,7 @@ LL | struct Break0<const N: usize>([u8; { N + 1 }]);
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:12:40
+ --> $DIR/complex-expression.rs:13:40
|
LL | struct Break1<const N: usize>([u8; { { N } }]);
| ^ cannot perform const operation using `N`
@@ -17,7 +17,7 @@ LL | struct Break1<const N: usize>([u8; { { N } }]);
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:16:17
+ --> $DIR/complex-expression.rs:17:17
|
LL | let _: [u8; N + 1];
| ^ cannot perform const operation using `N`
@@ -26,7 +26,7 @@ LL | let _: [u8; N + 1];
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:21:17
+ --> $DIR/complex-expression.rs:22:17
|
LL | let _ = [0; N + 1];
| ^ cannot perform const operation using `N`
@@ -35,7 +35,7 @@ LL | let _ = [0; N + 1];
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:25:45
+ --> $DIR/complex-expression.rs:26:45
|
LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
| ^ cannot perform const operation using `T`
@@ -44,7 +44,7 @@ LL | struct BreakTy0<T>(T, [u8; { size_of::<*mut T>() }]);
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:28:47
+ --> $DIR/complex-expression.rs:29:47
|
LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
| ^ cannot perform const operation using `T`
@@ -53,7 +53,7 @@ LL | struct BreakTy1<T>(T, [u8; { { size_of::<*mut T>() } }]);
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
error: generic parameters may not be used in const operations
- --> $DIR/complex-expression.rs:32:32
+ --> $DIR/complex-expression.rs:33:32
|
LL | let _: [u8; size_of::<*mut T>() + 1];
| ^ cannot perform const operation using `T`
@@ -62,14 +62,14 @@ LL | let _: [u8; size_of::<*mut T>() + 1];
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/complex-expression.rs:37:17
+ --> $DIR/complex-expression.rs:38:17
|
LL | let _ = [0; size_of::<*mut T>() + 1];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(const_evaluatable_unchecked)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
error: aborting due to 7 previous errors; 1 warning emitted
diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
index 71d13ca61..e9d868093 100644
--- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
+++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.rs
@@ -1,4 +1,5 @@
// check-pass
+// compile-flags: -Zdeduplicate-diagnostics=yes
#![allow(dead_code)]
fn foo<T>() {
diff --git a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
index f9f6660f6..8003dfa40 100644
--- a/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
+++ b/src/test/ui/const-generics/min_const_generics/const-evaluatable-unchecked.stderr
@@ -1,15 +1,15 @@
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/const-evaluatable-unchecked.rs:5:9
+ --> $DIR/const-evaluatable-unchecked.rs:6:9
|
LL | [0; std::mem::size_of::<*mut T>()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(const_evaluatable_unchecked)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
+ = note: `#[warn(const_evaluatable_unchecked)]` on by default
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/const-evaluatable-unchecked.rs:16:21
+ --> $DIR/const-evaluatable-unchecked.rs:17:21
|
LL | let _ = [0; Self::ASSOC];
| ^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | let _ = [0; Self::ASSOC];
= note: for more information, see issue #76200 <https://github.com/rust-lang/rust/issues/76200>
warning: cannot use constants which depend on generic parameters in types
- --> $DIR/const-evaluatable-unchecked.rs:28:21
+ --> $DIR/const-evaluatable-unchecked.rs:29:21
|
LL | let _ = [0; Self::ASSOC];
| ^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr b/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr
index f9b56bd38..fe3f24a67 100644
--- a/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr
+++ b/src/test/ui/const-generics/occurs-check/unify-fixpoint.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
index 9a73f1a53..9b1212694 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-2.rs
@@ -1,7 +1,7 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
-// The goal is is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
+// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
//
// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty<ct>` we introduced an
// artificial inference cycle.
diff --git a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
index 0d38bd393..d5aeab47e 100644
--- a/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
+++ b/src/test/ui/const-generics/occurs-check/unused-substs-3.rs
@@ -1,7 +1,7 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
-// The goal is is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
+// The goal is to get an unevaluated const `ct` with a `Ty::Infer(TyVar(_#1t)` subst.
//
// If we are then able to infer `ty::Infer(TyVar(_#1t) := Ty<ct>` we introduced an
// artificial inference cycle.
diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
index 82a3c92e6..8978ab436 100644
--- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
@@ -5,7 +5,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:18:34
|
@@ -19,7 +19,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:19:33
|
@@ -33,7 +33,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:22:34
|
@@ -92,7 +92,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `std::slice::from_raw_parts::<u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:43:5
|
@@ -111,7 +111,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:46:34
|
@@ -130,7 +130,7 @@ LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:47:33
|
@@ -230,7 +230,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:79:34
|
@@ -249,7 +249,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:80:35
|
diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
index f88746af9..db42b7c98 100644
--- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
@@ -5,7 +5,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:18:34
|
@@ -19,7 +19,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
- | inside `std::slice::from_raw_parts::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:19:33
|
@@ -33,7 +33,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
- | inside `std::slice::from_raw_parts::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:22:34
|
@@ -92,7 +92,7 @@ LL | &*ptr::slice_from_raw_parts(data, len)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
- | inside `std::slice::from_raw_parts::<u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:43:5
|
@@ -111,7 +111,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:46:34
|
@@ -130,7 +130,7 @@ LL | assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:47:33
|
@@ -230,7 +230,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:79:34
|
@@ -249,7 +249,7 @@ LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
LL | unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
- | ------------------------------ inside `from_ptr_range::<u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+ | ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
|
::: $DIR/forbidden_slices.rs:80:35
|
diff --git a/src/test/ui/const_prop/issue-102553.rs b/src/test/ui/const_prop/issue-102553.rs
new file mode 100644
index 000000000..523a9d7ac
--- /dev/null
+++ b/src/test/ui/const_prop/issue-102553.rs
@@ -0,0 +1,24 @@
+// compile-flags: --crate-type=lib
+// check-pass
+
+pub trait Widget<E> {
+ fn boxed<'w>(self) -> Box<dyn WidgetDyn<E> + 'w>
+ where
+ Self: Sized + 'w;
+}
+
+pub trait WidgetDyn<E> {}
+
+impl<T, E> WidgetDyn<E> for T where T: Widget<E> {}
+
+impl<E> Widget<E> for dyn WidgetDyn<E> + '_ {
+ fn boxed<'w>(self) -> Box<dyn WidgetDyn<E> + 'w>
+ where
+ Self: Sized + 'w,
+ {
+ // Even though this is illegal to const evaluate, this should never
+ // trigger an ICE because it can never be called from actual code
+ // (due to the trivially false where-clause predicate).
+ Box::new(self)
+ }
+}
diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs
index 9b3f735b1..67b49b1ba 100644
--- a/src/test/ui/consts/array-literal-index-oob.rs
+++ b/src/test/ui/consts/array-literal-index-oob.rs
@@ -1,7 +1,7 @@
// build-pass
// ignore-pass (test emits codegen-time warnings and verifies that they are not errors)
-#![warn(const_err, unconditional_panic)]
+#![warn(unconditional_panic)]
fn main() {
&{ [1, 2, 3][4] };
diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr
index f96b8d48b..54bf3af81 100644
--- a/src/test/ui/consts/array-literal-index-oob.stderr
+++ b/src/test/ui/consts/array-literal-index-oob.stderr
@@ -5,10 +5,10 @@ LL | &{ [1, 2, 3][4] };
| ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
|
note: the lint level is defined here
- --> $DIR/array-literal-index-oob.rs:4:20
+ --> $DIR/array-literal-index-oob.rs:4:9
|
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: 1 warning emitted
diff --git a/src/test/ui/consts/assert-type-intrinsics.rs b/src/test/ui/consts/assert-type-intrinsics.rs
index 3ce3e1bdb..263d1ae6a 100644
--- a/src/test/ui/consts/assert-type-intrinsics.rs
+++ b/src/test/ui/consts/assert-type-intrinsics.rs
@@ -1,5 +1,3 @@
-// error-pattern: any use of this value will cause an error
-
#![feature(never_type)]
#![feature(const_assert_type2)]
#![feature(core_intrinsics)]
@@ -12,11 +10,14 @@ fn main() {
const _BAD1: () = unsafe {
MaybeUninit::<!>::uninit().assume_init();
+ //~^ERROR: evaluation of constant value failed
};
const _BAD2: () = {
- intrinsics::assert_uninit_valid::<bool>();
+ intrinsics::assert_uninit_valid::<&'static i32>();
+ //~^ERROR: evaluation of constant value failed
};
const _BAD3: () = {
intrinsics::assert_zero_valid::<&'static i32>();
+ //~^ERROR: evaluation of constant value failed
};
}
diff --git a/src/test/ui/consts/assert-type-intrinsics.stderr b/src/test/ui/consts/assert-type-intrinsics.stderr
index 6eab10197..f92f9fda0 100644
--- a/src/test/ui/consts/assert-type-intrinsics.stderr
+++ b/src/test/ui/consts/assert-type-intrinsics.stderr
@@ -1,75 +1,21 @@
-error: any use of this value will cause an error
- --> $DIR/assert-type-intrinsics.rs:14:9
+error[E0080]: evaluation of constant value failed
+ --> $DIR/assert-type-intrinsics.rs:12:9
|
-LL | const _BAD1: () = unsafe {
- | ---------------
LL | MaybeUninit::<!>::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/assert-type-intrinsics.rs:17:9
- |
-LL | const _BAD2: () = {
- | ---------------
-LL | intrinsics::assert_uninit_valid::<bool>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
+error[E0080]: evaluation of constant value failed
+ --> $DIR/assert-type-intrinsics.rs:16:9
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | intrinsics::assert_uninit_valid::<&'static i32>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:20:9
|
-LL | const _BAD3: () = {
- | ---------------
LL | intrinsics::assert_zero_valid::<&'static i32>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 3 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/assert-type-intrinsics.rs:14:9
- |
-LL | const _BAD1: () = unsafe {
- | ---------------
-LL | MaybeUninit::<!>::uninit().assume_init();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/assert-type-intrinsics.rs:17:9
- |
-LL | const _BAD2: () = {
- | ---------------
-LL | intrinsics::assert_uninit_valid::<bool>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `bool` uninitialized, which is invalid
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/assert-type-intrinsics.rs:20:9
- |
-LL | const _BAD3: () = {
- | ---------------
-LL | intrinsics::assert_zero_valid::<&'static i32>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/assoc_const_generic_impl.rs b/src/test/ui/consts/assoc_const_generic_impl.rs
index 71d947b0c..3475c862b 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.rs
+++ b/src/test/ui/consts/assoc_const_generic_impl.rs
@@ -1,17 +1,14 @@
// build-fail
-#![warn(const_err)]
-
trait ZeroSized: Sized {
const I_AM_ZERO_SIZED: ();
fn requires_zero_size(self);
}
impl<T: Sized> ZeroSized for T {
- const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()]; //~ WARN any use of this value
- //~| WARN this was previously accepted by the compiler but is being phased out
+ const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()]; //~ ERROR evaluation of `<u32 as ZeroSized>::I_AM_ZERO_SIZED` failed
fn requires_zero_size(self) {
- let () = Self::I_AM_ZERO_SIZED; //~ ERROR erroneous constant encountered
+ let () = Self::I_AM_ZERO_SIZED;
println!("requires_zero_size called");
}
}
diff --git a/src/test/ui/consts/assoc_const_generic_impl.stderr b/src/test/ui/consts/assoc_const_generic_impl.stderr
index 17cbaef1f..854b9ce5b 100644
--- a/src/test/ui/consts/assoc_const_generic_impl.stderr
+++ b/src/test/ui/consts/assoc_const_generic_impl.stderr
@@ -1,37 +1,15 @@
-warning: any use of this value will cause an error
- --> $DIR/assoc_const_generic_impl.rs:11:34
+error[E0080]: evaluation of `<u32 as ZeroSized>::I_AM_ZERO_SIZED` failed
+ --> $DIR/assoc_const_generic_impl.rs:9:34
|
LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()];
- | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4
- |
-note: the lint level is defined here
- --> $DIR/assoc_const_generic_impl.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4
-error: erroneous constant encountered
- --> $DIR/assoc_const_generic_impl.rs:14:18
+note: the above error was encountered while instantiating `fn <u32 as ZeroSized>::requires_zero_size`
+ --> $DIR/assoc_const_generic_impl.rs:18:5
|
-LL | let () = Self::I_AM_ZERO_SIZED;
- | ^^^^^^^^^^^^^^^^^^^^^
+LL | 42_u32.requires_zero_size();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error; 1 warning emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/assoc_const_generic_impl.rs:11:34
- |
-LL | const I_AM_ZERO_SIZED: () = [()][std::mem::size_of::<Self>()];
- | ------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 4
- |
-note: the lint level is defined here
- --> $DIR/assoc_const_generic_impl.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+error: aborting due to previous error
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs
index e59ae297d..2767f178f 100644
--- a/src/test/ui/consts/cast-discriminant-zst-enum.rs
+++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs
@@ -1,6 +1,5 @@
// run-pass
// Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to an i32.
-#![feature(bench_black_box)]
use std::hint::black_box;
#[derive(Copy, Clone)]
diff --git a/src/test/ui/consts/const-err-early.rs b/src/test/ui/consts/const-err-early.rs
index d8f7635fe..a3105b4fc 100644
--- a/src/test/ui/consts/const-err-early.rs
+++ b/src/test/ui/consts/const-err-early.rs
@@ -1,15 +1,8 @@
-#![deny(const_err)]
-
-pub const A: i8 = -i8::MIN; //~ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
-pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
-pub const C: u8 = 200u8 * 4; //~ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
-pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
-pub const E: u8 = [5u8][1]; //~ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
+pub const A: i8 = -i8::MIN; //~ ERROR constant
+pub const B: u8 = 200u8 + 200u8; //~ ERROR constant
+pub const C: u8 = 200u8 * 4; //~ ERROR constant
+pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR constant
+pub const E: u8 = [5u8][1]; //~ ERROR constant
fn main() {
let _a = A;
diff --git a/src/test/ui/consts/const-err-early.stderr b/src/test/ui/consts/const-err-early.stderr
index 1b94aa080..59bf637b7 100644
--- a/src/test/ui/consts/const-err-early.stderr
+++ b/src/test/ui/consts/const-err-early.stderr
@@ -1,127 +1,33 @@
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:3:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-early.rs:1:19
|
LL | pub const A: i8 = -i8::MIN;
- | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:5:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-early.rs:2:19
|
LL | pub const B: u8 = 200u8 + 200u8;
- | --------------- ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:7:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-early.rs:3:19
|
LL | pub const C: u8 = 200u8 * 4;
- | --------------- ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:9:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-early.rs:4:19
|
LL | pub const D: u8 = 42u8 - (42u8 + 1);
- | --------------- ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:11:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-early.rs:5:19
|
LL | pub const E: u8 = [5u8][1];
- | --------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
error: aborting due to 5 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:3:19
- |
-LL | pub const A: i8 = -i8::MIN;
- | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:5:19
- |
-LL | pub const B: u8 = 200u8 + 200u8;
- | --------------- ^^^^^^^^^^^^^ attempt to compute `200_u8 + 200_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:7:19
- |
-LL | pub const C: u8 = 200u8 * 4;
- | --------------- ^^^^^^^^^ attempt to compute `200_u8 * 4_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:9:19
- |
-LL | pub const D: u8 = 42u8 - (42u8 + 1);
- | --------------- ^^^^^^^^^^^^^^^^^ attempt to compute `42_u8 - 43_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-early.rs:11:19
- |
-LL | pub const E: u8 = [5u8][1];
- | --------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
-note: the lint level is defined here
- --> $DIR/const-err-early.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-err-late.rs b/src/test/ui/consts/const-err-late.rs
new file mode 100644
index 000000000..a20ae7025
--- /dev/null
+++ b/src/test/ui/consts/const-err-late.rs
@@ -0,0 +1,22 @@
+// build-fail
+// compile-flags: -C overflow-checks=on
+
+#![allow(arithmetic_overflow, unconditional_panic)]
+
+fn black_box<T>(_: T) {
+ unimplemented!()
+}
+
+struct S<T>(T);
+
+impl<T> S<T> {
+ const FOO: u8 = [5u8][1];
+ //~^ ERROR evaluation of `S::<i32>::FOO` failed
+ //~| ERROR evaluation of `S::<u32>::FOO` failed
+}
+
+fn main() {
+ black_box((S::<i32>::FOO, S::<u32>::FOO));
+ //~^ ERROR erroneous constant
+ //~| ERROR erroneous constant
+}
diff --git a/src/test/ui/consts/const-err-late.stderr b/src/test/ui/consts/const-err-late.stderr
new file mode 100644
index 000000000..3a8b10317
--- /dev/null
+++ b/src/test/ui/consts/const-err-late.stderr
@@ -0,0 +1,27 @@
+error[E0080]: evaluation of `S::<i32>::FOO` failed
+ --> $DIR/const-err-late.rs:13:21
+ |
+LL | const FOO: u8 = [5u8][1];
+ | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
+
+error[E0080]: erroneous constant used
+ --> $DIR/const-err-late.rs:19:16
+ |
+LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
+ | ^^^^^^^^^^^^^ referenced constant has errors
+
+error[E0080]: evaluation of `S::<u32>::FOO` failed
+ --> $DIR/const-err-late.rs:13:21
+ |
+LL | const FOO: u8 = [5u8][1];
+ | ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
+
+error[E0080]: erroneous constant used
+ --> $DIR/const-err-late.rs:19:31
+ |
+LL | black_box((S::<i32>::FOO, S::<u32>::FOO));
+ | ^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-err-multi.rs b/src/test/ui/consts/const-err-multi.rs
index 62552e147..fb26e8aac 100644
--- a/src/test/ui/consts/const-err-multi.rs
+++ b/src/test/ui/consts/const-err-multi.rs
@@ -1,17 +1,11 @@
-#![deny(const_err)]
-
pub const A: i8 = -i8::MIN;
-//~^ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
pub const B: i8 = A;
-//~^ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
pub const C: u8 = A as u8;
-//~^ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
pub const D: i8 = 50 - A;
-//~^ ERROR const_err
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
fn main() {
let _ = (A, B, C, D);
diff --git a/src/test/ui/consts/const-err-multi.stderr b/src/test/ui/consts/const-err-multi.stderr
index f17984365..fca9e2270 100644
--- a/src/test/ui/consts/const-err-multi.stderr
+++ b/src/test/ui/consts/const-err-multi.stderr
@@ -1,103 +1,27 @@
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:3:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-multi.rs:1:19
|
LL | pub const A: i8 = -i8::MIN;
- | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-multi.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:6:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-multi.rs:3:19
|
LL | pub const B: i8 = A;
- | --------------- ^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^ referenced constant has errors
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:9:19
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-multi.rs:5:19
|
LL | pub const C: u8 = A as u8;
- | --------------- ^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^ referenced constant has errors
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:12:24
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-err-multi.rs:7:24
|
LL | pub const D: i8 = 50 - A;
- | --------------- ^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^ referenced constant has errors
error: aborting due to 4 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:3:19
- |
-LL | pub const A: i8 = -i8::MIN;
- | --------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-err-multi.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:6:19
- |
-LL | pub const B: i8 = A;
- | --------------- ^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/const-err-multi.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:9:19
- |
-LL | pub const C: u8 = A as u8;
- | --------------- ^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/const-err-multi.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-err-multi.rs:12:24
- |
-LL | pub const D: i8 = 50 - A;
- | --------------- ^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/const-err-multi.rs:1:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-err-rpass.rs b/src/test/ui/consts/const-err-rpass.rs
index 9851f1c58..e7fa10a2a 100644
--- a/src/test/ui/consts/const-err-rpass.rs
+++ b/src/test/ui/consts/const-err-rpass.rs
@@ -2,8 +2,6 @@
#![allow(dead_code)]
// check for const_err regressions
-#![deny(const_err)]
-
const X: *const u8 = b"" as _;
const Y: bool = 'A' == 'B';
const Z: char = 'A';
diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs
deleted file mode 100644
index a8633fd87..000000000
--- a/src/test/ui/consts/const-err.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// build-fail
-// compile-flags: -C overflow-checks=on
-
-#![allow(arithmetic_overflow)]
-#![warn(const_err)]
-
-fn black_box<T>(_: T) {
- unimplemented!()
-}
-
-const FOO: u8 = [5u8][1];
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-fn main() {
- black_box((FOO, FOO));
- //~^ ERROR erroneous constant used
- //~| ERROR erroneous constant
-}
diff --git a/src/test/ui/consts/const-err.stderr b/src/test/ui/consts/const-err.stderr
deleted file mode 100644
index e3b0d29c8..000000000
--- a/src/test/ui/consts/const-err.stderr
+++ /dev/null
@@ -1,44 +0,0 @@
-warning: any use of this value will cause an error
- --> $DIR/const-err.rs:11:17
- |
-LL | const FOO: u8 = [5u8][1];
- | ------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
-note: the lint level is defined here
- --> $DIR/const-err.rs:5:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-error[E0080]: erroneous constant used
- --> $DIR/const-err.rs:16:16
- |
-LL | black_box((FOO, FOO));
- | ^^^ referenced constant has errors
-
-error[E0080]: erroneous constant used
- --> $DIR/const-err.rs:16:21
- |
-LL | black_box((FOO, FOO));
- | ^^^ referenced constant has errors
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const-err.rs:11:17
- |
-LL | const FOO: u8 = [5u8][1];
- | ------------- ^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
-note: the lint level is defined here
- --> $DIR/const-err.rs:5:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.rs b/src/test/ui/consts/const-eval/conditional_array_execution.rs
index bd517e568..27d5383d6 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.rs
@@ -1,16 +1,8 @@
-// build-fail
-
-#![warn(const_err)]
-
const X: u32 = 5;
const Y: u32 = 6;
const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
fn main() {
println!("{}", FOO);
- //~^ ERROR evaluation of constant value failed
- //~| WARN erroneous constant used [const_err]
- //~| WARN this was previously accepted by the compiler but is being phased out
}
diff --git a/src/test/ui/consts/const-eval/conditional_array_execution.stderr b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
index 2953406ee..c3401fbae 100644
--- a/src/test/ui/consts/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/consts/const-eval/conditional_array_execution.stderr
@@ -1,64 +1,9 @@
-warning: any use of this value will cause an error
- --> $DIR/conditional_array_execution.rs:7:19
- |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | -------------- ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/conditional_array_execution.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
error[E0080]: evaluation of constant value failed
- --> $DIR/conditional_array_execution.rs:12:20
- |
-LL | println!("{}", FOO);
- | ^^^ referenced constant has errors
-
-warning: erroneous constant used
- --> $DIR/conditional_array_execution.rs:12:20
- |
-LL | println!("{}", FOO);
- | ^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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; 2 warnings emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/conditional_array_execution.rs:7:19
+ --> $DIR/conditional_array_execution.rs:3:19
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
- | -------------- ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/conditional_array_execution.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^ attempt to compute `5_u32 - 6_u32`, which would overflow
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/conditional_array_execution.rs:12:20
- |
-LL | println!("{}", FOO);
- | ^^^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/conditional_array_execution.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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 E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
index 9300d9576..535d91359 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -1,14 +1,14 @@
// Evaluation of constants in refutable patterns goes through
// different compiler control-flow paths.
-#![allow(unused_imports, warnings, const_err)]
+#![allow(unused_imports, warnings)]
use std::fmt;
use std::{i8, i16, i32, i64, isize};
use std::{u8, u16, u32, u64, usize};
const NEG_128: i8 = -128;
-const NEG_NEG_128: i8 = -NEG_128;
+const NEG_NEG_128: i8 = -NEG_128; //~ ERROR constant
fn main() {
match -128i8 {
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
index cf50c19ca..7b1fe49d4 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -1,3 +1,9 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow-2.rs:11:25
+ |
+LL | const NEG_NEG_128: i8 = -NEG_128;
+ | ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
+
error: could not evaluate constant pattern
--> $DIR/const-eval-overflow-2.rs:15:9
|
@@ -10,20 +16,6 @@ error: could not evaluate constant pattern
LL | NEG_NEG_128 => println!("A"),
| ^^^^^^^^^^^
-error: aborting due to 2 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const-eval-overflow-2.rs:11:25
- |
-LL | const NEG_NEG_128: i8 = -NEG_128;
- | --------------------- ^^^^^^^^ attempt to negate `i8::MIN`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow-2.rs:4:36
- |
-LL | #![allow(unused_imports, warnings, const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+error: aborting due to 3 previous errors
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
index 0e6be6d01..c685922c4 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-3b.stderr
@@ -4,13 +4,13 @@ error[E0308]: mismatched types
LL | = [0; (i8::MAX + 1u8) as usize];
| ^^^ expected `i8`, found `u8`
-error[E0277]: cannot add `u8` to `i8`
+error[E0277]: cannot add `u8` to `i8` in const contexts
--> $DIR/const-eval-overflow-3b.rs:16:20
|
LL | = [0; (i8::MAX + 1u8) as usize];
| ^ no implementation for `i8 + u8`
|
- = help: the trait `Add<u8>` is not implemented for `i8`
+ = help: the trait `~const Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
index 4fa017e04..b39607924 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow-4b.stderr
@@ -4,13 +4,13 @@ error[E0308]: mismatched types
LL | : [u32; (i8::MAX as i8 + 1u8) as usize]
| ^^^ expected `i8`, found `u8`
-error[E0277]: cannot add `u8` to `i8`
+error[E0277]: cannot add `u8` to `i8` in const contexts
--> $DIR/const-eval-overflow-4b.rs:9:28
|
LL | : [u32; (i8::MAX as i8 + 1u8) as usize]
| ^ no implementation for `i8 + u8`
|
- = help: the trait `Add<u8>` is not implemented for `i8`
+ = help: the trait `~const Add<u8>` is not implemented for `i8`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.rs b/src/test/ui/consts/const-eval/const-eval-overflow2.rs
index b11f7d698..1676f7c2a 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.rs
@@ -5,63 +5,53 @@
// change this warn to a deny, then the compiler will exit before
// those errors are detected.
-#![deny(const_err)]
-
use std::fmt;
const VALS_I8: (i8,) =
(
i8::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I16: (i16,) =
(
i16::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I32: (i32,) =
(
i32::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I64: (i64,) =
(
i64::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U8: (u8,) =
(
u8::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U16: (u16,) = (
u16::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U32: (u32,) = (
u32::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U64: (u64,) =
(
u64::MIN - 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
fn main() {
foo(VALS_I8);
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
index dab9a76c7..341c15daf 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2.stderr
@@ -1,243 +1,51 @@
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:14:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:12:6
|
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
LL | i8::MIN - 1,
| ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:21:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:18:6
|
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
LL | i16::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:28:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:24:6
|
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
LL | i32::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:35:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:30:6
|
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
LL | i64::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:42:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:36:6
|
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
LL | u8::MIN - 1,
| ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:48:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:41:6
|
-LL | const VALS_U16: (u16,) = (
- | ----------------------
LL | u16::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:54:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:46:6
|
-LL | const VALS_U32: (u32,) = (
- | ----------------------
LL | u32::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:61:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2.rs:52:6
|
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
LL | u64::MIN - 1,
| ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 8 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:14:6
- |
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
-LL | i8::MIN - 1,
- | ^^^^^^^^^^^ attempt to compute `i8::MIN - 1_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:21:6
- |
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
-LL | i16::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `i16::MIN - 1_i16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:28:6
- |
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
-LL | i32::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `i32::MIN - 1_i32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:35:6
- |
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
-LL | i64::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `i64::MIN - 1_i64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:42:6
- |
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
-LL | u8::MIN - 1,
- | ^^^^^^^^^^^ attempt to compute `0_u8 - 1_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:48:6
- |
-LL | const VALS_U16: (u16,) = (
- | ----------------------
-LL | u16::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `0_u16 - 1_u16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:54:6
- |
-LL | const VALS_U32: (u32,) = (
- | ----------------------
-LL | u32::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2.rs:61:6
- |
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
-LL | u64::MIN - 1,
- | ^^^^^^^^^^^^ attempt to compute `0_u64 - 1_u64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.rs b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs
index 9c3ad8ef9..59d1df568 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2b.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.rs
@@ -5,63 +5,53 @@
// change this warn to a deny, then the compiler will exit before
// those errors are detected.
-#![deny(const_err)]
-
use std::fmt;
const VALS_I8: (i8,) =
(
i8::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I16: (i16,) =
(
i16::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I32: (i32,) =
(
i32::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I64: (i64,) =
(
i64::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U8: (u8,) =
(
u8::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U16: (u16,) = (
u16::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U32: (u32,) = (
u32::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U64: (u64,) =
(
u64::MAX + 1,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
fn main() {
foo(VALS_I8);
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
index 5fe991743..e661836b4 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2b.stderr
@@ -1,243 +1,51 @@
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:14:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:12:6
|
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
LL | i8::MAX + 1,
| ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:21:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:18:6
|
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
LL | i16::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:28:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:24:6
|
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
LL | i32::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:35:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:30:6
|
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
LL | i64::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:42:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:36:6
|
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
LL | u8::MAX + 1,
| ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:48:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:41:6
|
-LL | const VALS_U16: (u16,) = (
- | ----------------------
LL | u16::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:54:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:46:6
|
-LL | const VALS_U32: (u32,) = (
- | ----------------------
LL | u32::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:61:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2b.rs:52:6
|
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
LL | u64::MAX + 1,
| ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 8 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:14:6
- |
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
-LL | i8::MAX + 1,
- | ^^^^^^^^^^^ attempt to compute `i8::MAX + 1_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:21:6
- |
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
-LL | i16::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `i16::MAX + 1_i16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:28:6
- |
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
-LL | i32::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:35:6
- |
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
-LL | i64::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `i64::MAX + 1_i64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:42:6
- |
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
-LL | u8::MAX + 1,
- | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:48:6
- |
-LL | const VALS_U16: (u16,) = (
- | ----------------------
-LL | u16::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `u16::MAX + 1_u16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:54:6
- |
-LL | const VALS_U32: (u32,) = (
- | ----------------------
-LL | u32::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `u32::MAX + 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2b.rs:61:6
- |
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
-LL | u64::MAX + 1,
- | ^^^^^^^^^^^^ attempt to compute `u64::MAX + 1_u64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2b.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.rs b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs
index bac4d042e..33b892601 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2c.rs
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.rs
@@ -5,63 +5,53 @@
// change this warn to a deny, then the compiler will exit before
// those errors are detected.
-#![deny(const_err)]
-
use std::fmt;
const VALS_I8: (i8,) =
(
i8::MIN * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I16: (i16,) =
(
i16::MIN * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I32: (i32,) =
(
i32::MIN * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_I64: (i64,) =
(
i64::MIN * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U8: (u8,) =
(
u8::MAX * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U16: (u16,) = (
u16::MAX * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U32: (u32,) = (
u32::MAX * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
const VALS_U64: (u64,) =
(
u64::MAX * 2,
);
- //~^^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^^ ERROR evaluation of constant value failed
fn main() {
foo(VALS_I8);
diff --git a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
index d5f3a0fb1..1fad15492 100644
--- a/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-overflow2c.stderr
@@ -1,243 +1,51 @@
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:14:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:12:6
|
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
LL | i8::MIN * 2,
| ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:21:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:18:6
|
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
LL | i16::MIN * 2,
| ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:28:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:24:6
|
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
LL | i32::MIN * 2,
| ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:35:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:30:6
|
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
LL | i64::MIN * 2,
| ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:42:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:36:6
|
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
LL | u8::MAX * 2,
| ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:48:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:41:6
|
-LL | const VALS_U16: (u16,) = (
- | ----------------------
LL | u16::MAX * 2,
| ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:54:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:46:6
|
-LL | const VALS_U32: (u32,) = (
- | ----------------------
LL | u32::MAX * 2,
| ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:61:6
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-eval-overflow2c.rs:52:6
|
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
LL | u64::MAX * 2,
| ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 8 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:14:6
- |
-LL | const VALS_I8: (i8,) =
- | --------------------
-LL | (
-LL | i8::MIN * 2,
- | ^^^^^^^^^^^ attempt to compute `i8::MIN * 2_i8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:21:6
- |
-LL | const VALS_I16: (i16,) =
- | ----------------------
-LL | (
-LL | i16::MIN * 2,
- | ^^^^^^^^^^^^ attempt to compute `i16::MIN * 2_i16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:28:6
- |
-LL | const VALS_I32: (i32,) =
- | ----------------------
-LL | (
-LL | i32::MIN * 2,
- | ^^^^^^^^^^^^ attempt to compute `i32::MIN * 2_i32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:35:6
- |
-LL | const VALS_I64: (i64,) =
- | ----------------------
-LL | (
-LL | i64::MIN * 2,
- | ^^^^^^^^^^^^ attempt to compute `i64::MIN * 2_i64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:42:6
- |
-LL | const VALS_U8: (u8,) =
- | --------------------
-LL | (
-LL | u8::MAX * 2,
- | ^^^^^^^^^^^ attempt to compute `u8::MAX * 2_u8`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:48:6
- |
-LL | const VALS_U16: (u16,) = (
- | ----------------------
-LL | u16::MAX * 2,
- | ^^^^^^^^^^^^ attempt to compute `u16::MAX * 2_u16`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:54:6
- |
-LL | const VALS_U32: (u32,) = (
- | ----------------------
-LL | u32::MAX * 2,
- | ^^^^^^^^^^^^ attempt to compute `u32::MAX * 2_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-eval-overflow2c.rs:61:6
- |
-LL | const VALS_U64: (u64,) =
- | ----------------------
-LL | (
-LL | u64::MAX * 2,
- | ^^^^^^^^^^^^ attempt to compute `u64::MAX * 2_u64`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/const-eval-overflow2c.rs:8:9
- |
-LL | #![deny(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.rs b/src/test/ui/consts/const-eval/const-eval-query-stack.rs
index c94604989..8f8a8cee3 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.rs
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.rs
@@ -1,5 +1,4 @@
-// compile-flags: -Ztreat-err-as-bug=2
-// build-fail
+// compile-flags: -Ztreat-err-as-bug=1
// failure-status: 101
// rustc-env:RUST_BACKTRACE=1
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
@@ -15,14 +14,9 @@
#![allow(unconditional_panic)]
-#[warn(const_err)]
-const X: i32 = 1 / 0; //~WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+const X: i32 = 1 / 0; //~ERROR constant
fn main() {
let x: &'static i32 = &X;
- //~^ ERROR evaluation of constant value failed
- //~| ERROR erroneous constant used
- //~| WARNING this was previously accepted by the compiler
println!("x={}", x);
}
diff --git a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
index 0ae7bfa86..b97975c4c 100644
--- a/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
+++ b/src/test/ui/consts/const-eval/const-eval-query-stack.stderr
@@ -1,61 +1,13 @@
-warning: any use of this value will cause an error
- --> $DIR/const-eval-query-stack.rs:19:16
- |
-LL | const X: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
- |
-note: the lint level is defined here
- --> $DIR/const-eval-query-stack.rs:18:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
error[E0080]: evaluation of constant value failed
- --> $DIR/const-eval-query-stack.rs:23:28
+ --> $DIR/const-eval-query-stack.rs:17:16
|
-LL | let x: &'static i32 = &X;
- | ^ referenced constant has errors
-
-error: erroneous constant used
- --> $DIR/const-eval-query-stack.rs:23:27
- |
-LL | let x: &'static i32 = &X;
- | ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+LL | const X: i32 = 1 / 0;
+ | ^^^^^ attempt to divide `1_i32` by zero
query stack during panic:
-#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `main`
-#1 [optimized_mir] optimizing MIR for `main`
-#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
+#0 [eval_to_allocation_raw] const-evaluating + checking `X`
+#1 [eval_to_const_value_raw] simplifying constant for the type system `X`
+#2 [eval_to_const_value_raw] simplifying constant for the type system `X`
+#3 [lint_mod] linting top-level module
+#4 [analysis] running analysis passes on this crate
end of query stack
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const-eval-query-stack.rs:19:16
- |
-LL | const X: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
- |
-note: the lint level is defined here
- --> $DIR/const-eval-query-stack.rs:18:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/const-eval-query-stack.rs:23:27
- |
-LL | let x: &'static i32 = &X;
- | ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
index 12d5b7bd6..bf98d0394 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.64bit.stderr
@@ -1,664 +1,258 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-pointer-values-in-various-types.rs:26:49
|
LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
- | -------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:30:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:29:43
|
LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:34:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:32:45
|
LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:38:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:35:45
|
LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:42:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:38:45
|
LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/const-pointer-values-in-various-types.rs:46:47
+ --> $DIR/const-pointer-values-in-various-types.rs:41:47
|
LL | const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:50:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:45:43
|
LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:54:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:48:45
|
LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:58:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:51:45
|
LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:62:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:54:45
|
LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/const-pointer-values-in-various-types.rs:66:47
+ --> $DIR/const-pointer-values-in-various-types.rs:57:47
|
LL | const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:70:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:61:45
|
LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:74:45
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:64:45
|
LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:78:47
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:67:47
|
LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
- | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:82:47
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:70:47
|
LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
- | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:86:39
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:73:39
|
LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
- | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:90:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:76:41
|
LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:94:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:79:41
|
LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:98:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:82:41
|
LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:102:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:85:43
|
LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:106:39
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:88:39
|
LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
- | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:110:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:91:41
|
LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:114:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:94:41
|
LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:118:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:97:41
|
LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:122:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:100:43
|
LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:126:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:103:41
|
LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:130:41
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:106:41
|
LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:134:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:109:43
|
LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:138:43
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-pointer-values-in-various-types.rs:112:43
|
LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: aborting due to 29 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:26:49
- |
-LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
- | -------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:30:43
- |
-LL | const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:34:45
- |
-LL | const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:38:45
- |
-LL | const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:42:45
- |
-LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:50:43
- |
-LL | const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:54:45
- |
-LL | const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:58:45
- |
-LL | const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:62:45
- |
-LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:70:45
- |
-LL | const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:74:45
- |
-LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
- | ---------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:78:47
- |
-LL | const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
- | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:82:47
- |
-LL | const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
- | ------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:86:39
- |
-LL | const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
- | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:90:41
- |
-LL | const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:94:41
- |
-LL | const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:98:41
- |
-LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:102:43
- |
-LL | const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:106:39
- |
-LL | const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
- | ---------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:110:41
- |
-LL | const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:114:41
- |
-LL | const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:118:41
- |
-LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:122:43
- |
-LL | const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:126:41
- |
-LL | const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:130:41
- |
-LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
- | ------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:134:43
- |
-LL | const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-pointer-values-in-various-types.rs:138:43
- |
-LL | const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
- | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
index f6a5e4d3c..45eed9d84 100644
--- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
+++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.rs
@@ -24,118 +24,91 @@ union Nonsense {
fn main() {
const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_U8_UNION: u8 = unsafe { Nonsense { int_32_ref: &3 }.uint_8 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_U16_UNION: u16 = unsafe { Nonsense { int_32_ref: &3 }.uint_16 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_U32_UNION: u32 = unsafe { Nonsense { int_32_ref: &3 }.uint_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_U128_UNION: u128 = unsafe { Nonsense { int_32_ref: &3 }.uint_128 };
//~^ ERROR evaluation of constant value failed
//~| uninitialized
const I32_REF_I8_UNION: i8 = unsafe { Nonsense { int_32_ref: &3 }.int_8 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_I16_UNION: i16 = unsafe { Nonsense { int_32_ref: &3 }.int_16 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_I32_UNION: i32 = unsafe { Nonsense { int_32_ref: &3 }.int_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_I128_UNION: i128 = unsafe { Nonsense { int_32_ref: &3 }.int_128 };
//~^ ERROR evaluation of constant value failed
//~| uninitialized
const I32_REF_F32_UNION: f32 = unsafe { Nonsense { int_32_ref: &3 }.float_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_BOOL_UNION: bool = unsafe { Nonsense { int_32_ref: &3 }.truthy_falsey };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const I32_REF_CHAR_UNION: char = unsafe { Nonsense { int_32_ref: &3 }.character };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_U8_UNION: u8 = unsafe { Nonsense { stringy: "3" }.uint_8 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_U16_UNION: u16 = unsafe { Nonsense { stringy: "3" }.uint_16 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_U32_UNION: u32 = unsafe { Nonsense { stringy: "3" }.uint_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_U128_UNION: u128 = unsafe { Nonsense { stringy: "3" }.uint_128 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_I8_UNION: i8 = unsafe { Nonsense { stringy: "3" }.int_8 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_I16_UNION: i16 = unsafe { Nonsense { stringy: "3" }.int_16 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_I32_UNION: i32 = unsafe { Nonsense { stringy: "3" }.int_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_I128_UNION: i128 = unsafe { Nonsense { stringy: "3" }.int_128 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_F32_UNION: f32 = unsafe { Nonsense { stringy: "3" }.float_32 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_BOOL_UNION: bool = unsafe { Nonsense { stringy: "3" }.truthy_falsey };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
const STR_CHAR_UNION: char = unsafe { Nonsense { stringy: "3" }.character };
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
}
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
index 804ebf660..b873940c4 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.rs
@@ -1,8 +1,5 @@
-// build-fail
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
-
fn double(x: usize) -> usize {
x * 2
}
@@ -10,6 +7,8 @@ const X: fn(usize) -> usize = double;
const fn bar(x: fn(usize) -> usize, y: usize) -> usize {
x(y)
+ //~^ ERROR evaluation of constant value failed
+ //~| ERROR evaluation of constant value failed
}
const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
@@ -17,7 +16,5 @@ const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
fn main() {
assert_eq!(Y, 4);
- //~^ ERROR evaluation of constant value failed
assert_eq!(Z, 4);
- //~^ ERROR evaluation of constant value failed
}
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index f6ffa1ef2..3784a3861 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -1,99 +1,35 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/const_fn_ptr_fail2.rs:19:16
- |
-LL | assert_eq!(Y, 4);
- | ^ referenced constant has errors
-
-error[E0080]: evaluation of constant value failed
- --> $DIR/const_fn_ptr_fail2.rs:21:16
- |
-LL | assert_eq!(Z, 4);
- | ^ referenced constant has errors
-
-warning: skipping const checks
- |
-help: skipping check that does not even have a feature gate
- --> $DIR/const_fn_ptr_fail2.rs:12:5
- |
-LL | x(y)
- | ^^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_fn_ptr_fail2.rs:12:5
+ --> $DIR/const_fn_ptr_fail2.rs:9:5
|
LL | x(y)
| ^^^^
| |
| calling non-const function `double`
- | inside `bar` at $DIR/const_fn_ptr_fail2.rs:12:5
- | inside `Y` at $DIR/const_fn_ptr_fail2.rs:15:18
+ | inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
...
LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
- | --------------
- |
-note: the lint level is defined here
- --> $DIR/const_fn_ptr_fail2.rs:4:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | --------- inside `Y` at $DIR/const_fn_ptr_fail2.rs:14:18
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_fn_ptr_fail2.rs:12:5
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_fn_ptr_fail2.rs:9:5
|
LL | x(y)
| ^^^^
| |
| calling non-const function `double`
- | inside `bar` at $DIR/const_fn_ptr_fail2.rs:12:5
- | inside `Z` at $DIR/const_fn_ptr_fail2.rs:16:18
+ | inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
...
LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
- | --------------
- |
-note: the lint level is defined here
- --> $DIR/const_fn_ptr_fail2.rs:4:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | -------------- inside `Z` at $DIR/const_fn_ptr_fail2.rs:15:18
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/const_fn_ptr_fail2.rs:19:5
- |
-LL | assert_eq!(Y, 4);
- | ^^^^^^^^^^^^^^^^ referenced constant has errors
+warning: skipping const checks
|
-note: the lint level is defined here
- --> $DIR/const_fn_ptr_fail2.rs:4:10
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_fn_ptr_fail2.rs:9:5
|
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+LL | x(y)
+ | ^^^^
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/const_fn_ptr_fail2.rs:21:5
- |
-LL | assert_eq!(Z, 4);
- | ^^^^^^^^^^^^^^^^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/const_fn_ptr_fail2.rs:4:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+error: aborting due to 2 previous errors; 1 warning emitted
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs
index 18692dbce..1e2bcc55b 100644
--- a/src/test/ui/consts/const-eval/const_let.rs
+++ b/src/test/ui/consts/const-eval/const_let.rs
@@ -14,16 +14,16 @@ const X2: FakeNeedsDrop = { let x; x = FakeNeedsDrop; x };
// error
const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
// error
const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
// error
const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
// error
const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr
index 47f39b703..63442f557 100644
--- a/src/test/ui/consts/const-eval/const_let.stderr
+++ b/src/test/ui/consts/const-eval/const_let.stderr
@@ -1,34 +1,34 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time
--> $DIR/const_let.rs:16:32
|
LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
| ^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `FakeNeedsDrop` cannot be evaluated at compile-time
--> $DIR/const_let.rs:20:33
|
LL | const Y2: FakeNeedsDrop = { let mut x; x = FakeNeedsDrop; x = FakeNeedsDrop; x };
| ^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<FakeNeedsDrop>` cannot be evaluated at compile-time
--> $DIR/const_let.rs:24:21
|
LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
| ^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<FakeNeedsDrop>` cannot be evaluated at compile-time
--> $DIR/const_let.rs:28:22
|
LL | const Z2: () = { let mut x; x = None; x = Some(FakeNeedsDrop); };
| ^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
error: aborting due to 4 previous errors
diff --git a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr
index f06dedc22..3553a18d3 100644
--- a/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr
+++ b/src/test/ui/consts/const-eval/const_panic_stability.e2018.stderr
@@ -4,9 +4,9 @@ warning: panic message is not a string literal
LL | panic!({ "foo" });
| ^^^^^^^^^
|
- = note: `#[warn(non_fmt_panics)]` on by default
= note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/panic-macro-consistency.html>
+ = note: `#[warn(non_fmt_panics)]` on by default
help: add a "{}" format string to `Display` the message
|
LL | panic!("{}", { "foo" });
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index 168fa0ad0..12244450e 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -10,16 +10,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
|
LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
| ^^
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
error[E0277]: can't compare `*const i32` with `_` in const contexts
--> $DIR/const_raw_ptr_ops.rs:6:44
@@ -33,16 +23,6 @@ note: the trait `PartialEq<_>` is implemented for `*const i32`, but that impleme
|
LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
| ^^
- = help: the following other types implement trait `PartialEq<Rhs>`:
- f32
- f64
- i128
- i16
- i32
- i64
- i8
- isize
- and 6 others
error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/const-eval/erroneous-const.rs b/src/test/ui/consts/const-eval/erroneous-const.rs
index bee5a7cb3..cf11531ba 100644
--- a/src/test/ui/consts/const-eval/erroneous-const.rs
+++ b/src/test/ui/consts/const-eval/erroneous-const.rs
@@ -1,11 +1,9 @@
//! Make sure we error on erroneous consts even if they are unused.
-#![warn(const_err, unconditional_panic)]
+#![allow(unconditional_panic)]
struct PrintName<T>(T);
impl<T> PrintName<T> {
- const VOID: () = [()][2]; //~WARN any use of this value will cause an error
- //~^ WARN this operation will panic at runtime
- //~| WARN this was previously accepted by the compiler but is being phased out
+ const VOID: () = [()][2]; //~ERROR evaluation of `PrintName::<i32>::VOID` failed
}
const fn no_codegen<T>() {
diff --git a/src/test/ui/consts/const-eval/erroneous-const.stderr b/src/test/ui/consts/const-eval/erroneous-const.stderr
index adfb4cc61..33579135d 100644
--- a/src/test/ui/consts/const-eval/erroneous-const.stderr
+++ b/src/test/ui/consts/const-eval/erroneous-const.stderr
@@ -1,56 +1,21 @@
-warning: this operation will panic at runtime
+error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
--> $DIR/erroneous-const.rs:6:22
|
LL | const VOID: () = [()][2];
| ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const.rs:2:20
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
-
-warning: any use of this value will cause an error
- --> $DIR/erroneous-const.rs:6:22
- |
-LL | const VOID: () = [()][2];
- | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const.rs:2:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error[E0080]: could not evaluate static initializer
- --> $DIR/erroneous-const.rs:15:17
+ --> $DIR/erroneous-const.rs:13:17
|
LL | let _ = PrintName::<T>::VOID;
| ^^^^^^^^^^^^^^^^^^^^
| |
| referenced constant has errors
- | inside `no_codegen::<i32>` at $DIR/erroneous-const.rs:15:17
+ | inside `no_codegen::<i32>` at $DIR/erroneous-const.rs:13:17
...
LL | pub static FOO: () = no_codegen::<i32>();
- | ------------------- inside `FOO` at $DIR/erroneous-const.rs:19:22
+ | ------------------- inside `FOO` at $DIR/erroneous-const.rs:17:22
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/erroneous-const.rs:6:22
- |
-LL | const VOID: () = [()][2];
- | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const.rs:2:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/erroneous-const2.rs b/src/test/ui/consts/const-eval/erroneous-const2.rs
index aa0f093bf..2fbf7be88 100644
--- a/src/test/ui/consts/const-eval/erroneous-const2.rs
+++ b/src/test/ui/consts/const-eval/erroneous-const2.rs
@@ -1,11 +1,9 @@
//! Make sure we error on erroneous consts even if they are unused.
-#![warn(const_err, unconditional_panic)]
+#![allow(unconditional_panic)]
struct PrintName<T>(T);
impl<T> PrintName<T> {
- const VOID: () = [()][2]; //~WARN any use of this value will cause an error
- //~^ WARN this operation will panic at runtime
- //~| WARN this was previously accepted by the compiler but is being phased out
+ const VOID: () = [()][2]; //~ERROR evaluation of `PrintName::<i32>::VOID` failed
}
pub static FOO: () = {
diff --git a/src/test/ui/consts/const-eval/erroneous-const2.stderr b/src/test/ui/consts/const-eval/erroneous-const2.stderr
index e947d93e4..630b1cf16 100644
--- a/src/test/ui/consts/const-eval/erroneous-const2.stderr
+++ b/src/test/ui/consts/const-eval/erroneous-const2.stderr
@@ -1,50 +1,15 @@
-warning: this operation will panic at runtime
+error[E0080]: evaluation of `PrintName::<i32>::VOID` failed
--> $DIR/erroneous-const2.rs:6:22
|
LL | const VOID: () = [()][2];
| ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const2.rs:2:20
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
-
-warning: any use of this value will cause an error
- --> $DIR/erroneous-const2.rs:6:22
- |
-LL | const VOID: () = [()][2];
- | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const2.rs:2:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error[E0080]: could not evaluate static initializer
- --> $DIR/erroneous-const2.rs:15:17
+ --> $DIR/erroneous-const2.rs:13:17
|
LL | let _ = PrintName::<i32>::VOID;
| ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-error: aborting due to previous error; 2 warnings emitted
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/erroneous-const2.rs:6:22
- |
-LL | const VOID: () = [()][2];
- | -------------- ^^^^^^^ index out of bounds: the length is 1 but the index is 2
- |
-note: the lint level is defined here
- --> $DIR/erroneous-const2.rs:2:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/format.rs b/src/test/ui/consts/const-eval/format.rs
index e43633da3..3eef0d6c3 100644
--- a/src/test/ui/consts/const-eval/format.rs
+++ b/src/test/ui/consts/const-eval/format.rs
@@ -3,8 +3,6 @@ const fn failure() {
//~^ ERROR cannot call non-const formatting macro in constant functions
//~| ERROR erroneous constant used
//~| ERROR erroneous constant used
- //~| WARN this was previously accepted by the compiler
- //~| WARN this was previously accepted by the compiler
}
const fn print() {
@@ -14,8 +12,6 @@ const fn print() {
//~| ERROR cannot call non-const fn `_print` in constant functions
//~| ERROR erroneous constant used
//~| ERROR erroneous constant used
- //~| WARN this was previously accepted by the compiler
- //~| WARN this was previously accepted by the compiler
}
fn main() {}
diff --git a/src/test/ui/consts/const-eval/format.stderr b/src/test/ui/consts/const-eval/format.stderr
index a476b0f58..64c769648 100644
--- a/src/test/ui/consts/const-eval/format.stderr
+++ b/src/test/ui/consts/const-eval/format.stderr
@@ -8,7 +8,7 @@ LL | panic!("{:?}", 0);
= note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0015]: cannot call non-const formatting macro in constant functions
- --> $DIR/format.rs:11:22
+ --> $DIR/format.rs:9:22
|
LL | println!("{:?}", 0);
| ^
@@ -17,7 +17,7 @@ LL | println!("{:?}", 0);
= 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: `Arguments::<'a>::new_v1` is not yet stable as a const fn
- --> $DIR/format.rs:11:5
+ --> $DIR/format.rs:9:5
|
LL | println!("{:?}", 0);
| ^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | println!("{:?}", 0);
= 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[E0015]: cannot call non-const fn `_print` in constant functions
- --> $DIR/format.rs:11:5
+ --> $DIR/format.rs:9:5
|
LL | println!("{:?}", 0);
| ^^^^^^^^^^^^^^^^^^^
@@ -34,91 +34,35 @@ LL | println!("{:?}", 0);
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/format.rs:2:12
|
LL | panic!("{:?}", 0);
| ^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/format.rs:2:20
|
LL | panic!("{:?}", 0);
| ^ referenced constant has errors
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: erroneous constant used
- --> $DIR/format.rs:11:14
+error[E0080]: erroneous constant used
+ --> $DIR/format.rs:9:14
|
LL | println!("{:?}", 0);
| ^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: erroneous constant used
- --> $DIR/format.rs:11:22
+error[E0080]: erroneous constant used
+ --> $DIR/format.rs:9:22
|
LL | println!("{:?}", 0);
| ^ referenced constant has errors
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= 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 8 previous errors
-For more information about this error, try `rustc --explain E0015`.
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/format.rs:2:12
- |
-LL | panic!("{:?}", 0);
- | ^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/format.rs:2:20
- |
-LL | panic!("{:?}", 0);
- | ^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `$crate::const_format_args` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/format.rs:11:14
- |
-LL | println!("{:?}", 0);
- | ^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/format.rs:11:22
- |
-LL | println!("{:?}", 0);
- | ^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+Some errors have detailed explanations: E0015, E0080.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
index 8064cc493..bc2ea3f18 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs
@@ -1,21 +1,19 @@
// build-fail
// Regression test for #66975
-#![warn(const_err, unconditional_panic)]
+#![warn(unconditional_panic)]
#![feature(never_type)]
struct PrintName<T>(T);
impl<T> PrintName<T> {
const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
- //~^ WARN any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of `PrintName::<()>::VOID` failed
}
fn f<T>() {
let _ = PrintName::<T>::VOID;
- //~^ ERROR erroneous constant encountered
}
pub fn main() {
diff --git a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
index da4a21e08..8bcd03005 100644
--- a/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
+++ b/src/test/ui/consts/const-eval/index-out-of-bounds-never-type.stderr
@@ -1,37 +1,15 @@
-warning: any use of this value will cause an error
+error[E0080]: evaluation of `PrintName::<()>::VOID` failed
--> $DIR/index-out-of-bounds-never-type.rs:10:61
|
LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
- | ------------- ^^^^^ index out of bounds: the length is 0 but the index is 0
- |
-note: the lint level is defined here
- --> $DIR/index-out-of-bounds-never-type.rs:4:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^ index out of bounds: the length is 0 but the index is 0
-error: erroneous constant encountered
- --> $DIR/index-out-of-bounds-never-type.rs:17:13
+note: the above error was encountered while instantiating `fn f::<()>`
+ --> $DIR/index-out-of-bounds-never-type.rs:20:5
|
-LL | let _ = PrintName::<T>::VOID;
- | ^^^^^^^^^^^^^^^^^^^^
+LL | f::<()>();
+ | ^^^^^^^^^
-error: aborting due to previous error; 1 warning emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/index-out-of-bounds-never-type.rs:10:61
- |
-LL | const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] };
- | ------------- ^^^^^ index out of bounds: the length is 0 but the index is 0
- |
-note: the lint level is defined here
- --> $DIR/index-out-of-bounds-never-type.rs:4:9
- |
-LL | #![warn(const_err, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+error: aborting due to previous error
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs
index 14a573ccf..4babc9a28 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.rs
+++ b/src/test/ui/consts/const-eval/infinite_loop.rs
@@ -4,8 +4,8 @@ fn main() {
let _ = [(); {
let mut n = 113383; // #20 in https://oeis.org/A006884
while n != 0 {
- n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
//~^ ERROR evaluation of constant value failed
+ n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
}
n
}];
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
index 3b5a0f22f..8b58cb279 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.stderr
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/infinite_loop.rs:7:20
+ --> $DIR/infinite_loop.rs:6:15
|
-LL | n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
- | ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL | while n != 0 {
+ | ^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/issue-100878.rs b/src/test/ui/consts/const-eval/issue-100878.rs
new file mode 100644
index 000000000..353ce5050
--- /dev/null
+++ b/src/test/ui/consts/const-eval/issue-100878.rs
@@ -0,0 +1,8 @@
+// This checks that the const-eval ICE in issue #100878 does not recur.
+//
+// build-pass
+pub fn bitshift_data(data: [u8; 1]) -> u8 {
+ data[0] << 8
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/const-eval/issue-43197.rs b/src/test/ui/consts/const-eval/issue-43197.rs
index e15f8771d..145463f0a 100644
--- a/src/test/ui/consts/const-eval/issue-43197.rs
+++ b/src/test/ui/consts/const-eval/issue-43197.rs
@@ -1,23 +1,11 @@
-// build-fail
-
-#![warn(const_err)]
-
const fn foo(x: u32) -> u32 {
x
}
fn main() {
const X: u32 = 0 - 1;
- //~^ WARN any use of this value will cause
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR constant
const Y: u32 = foo(0 - 1);
- //~^ WARN any use of this value will cause
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR constant
println!("{} {}", X, Y);
- //~^ ERROR evaluation of constant value failed
- //~| ERROR evaluation of constant value failed
- //~| WARN erroneous constant used [const_err]
- //~| WARN erroneous constant used [const_err]
- //~| WARN this was previously accepted by the compiler but is being phased out
- //~| WARN this was previously accepted by the compiler but is being phased out
}
diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr
index 3f67c38f8..c59f13e48 100644
--- a/src/test/ui/consts/const-eval/issue-43197.stderr
+++ b/src/test/ui/consts/const-eval/issue-43197.stderr
@@ -1,120 +1,15 @@
-warning: any use of this value will cause an error
- --> $DIR/issue-43197.rs:10:20
- |
-LL | const X: u32 = 0 - 1;
- | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/issue-43197.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: any use of this value will cause an error
- --> $DIR/issue-43197.rs:13:24
- |
-LL | const Y: u32 = foo(0 - 1);
- | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-43197.rs:16:23
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
-
-warning: erroneous constant used
- --> $DIR/issue-43197.rs:16:23
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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[E0080]: evaluation of constant value failed
- --> $DIR/issue-43197.rs:16:26
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
-
-warning: erroneous constant used
- --> $DIR/issue-43197.rs:16:26
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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 2 previous errors; 4 warnings emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/issue-43197.rs:10:20
+ --> $DIR/issue-43197.rs:6:20
|
LL | const X: u32 = 0 - 1;
- | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/issue-43197.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/issue-43197.rs:13:24
+error[E0080]: evaluation of constant value failed
+ --> $DIR/issue-43197.rs:8:24
|
LL | const Y: u32 = foo(0 - 1);
- | ------------ ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/issue-43197.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/issue-43197.rs:16:23
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/issue-43197.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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)
-
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/issue-43197.rs:16:26
- |
-LL | println!("{} {}", X, Y);
- | ^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/issue-43197.rs:3:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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 2 previous errors
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-44578.rs b/src/test/ui/consts/const-eval/issue-44578.rs
index a88e21970..2dbe1c2bd 100644
--- a/src/test/ui/consts/const-eval/issue-44578.rs
+++ b/src/test/ui/consts/const-eval/issue-44578.rs
@@ -1,7 +1,5 @@
// build-fail
-#![allow(const_err)]
-
trait Foo {
const AMT: usize;
}
@@ -12,7 +10,7 @@ enum Bar<A, B> {
}
impl<A: Foo, B: Foo> Foo for Bar<A, B> {
- const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+ const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; //~ERROR evaluation of `<Bar<u16, u8> as Foo>::AMT` failed
}
impl Foo for u8 {
@@ -26,4 +24,5 @@ impl Foo for u16 {
fn main() {
println!("{}", <Bar<u16, u8> as Foo>::AMT);
//~^ ERROR evaluation of constant value failed
+ //~| ERROR erroneous constant used
}
diff --git a/src/test/ui/consts/const-eval/issue-44578.stderr b/src/test/ui/consts/const-eval/issue-44578.stderr
index 4c27ceea1..963381b58 100644
--- a/src/test/ui/consts/const-eval/issue-44578.stderr
+++ b/src/test/ui/consts/const-eval/issue-44578.stderr
@@ -1,40 +1,23 @@
+error[E0080]: evaluation of `<Bar<u16, u8> as Foo>::AMT` failed
+ --> $DIR/issue-44578.rs:13:24
+ |
+LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
+
error[E0080]: evaluation of constant value failed
- --> $DIR/issue-44578.rs:27:20
+ --> $DIR/issue-44578.rs:25:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/issue-44578.rs:15:24
- |
-LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
- | ---------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
-note: the lint level is defined here
- --> $DIR/issue-44578.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: erroneous constant used
- --> $DIR/issue-44578.rs:27:20
+error[E0080]: erroneous constant used
+ --> $DIR/issue-44578.rs:25:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
-note: the lint level is defined here
- --> $DIR/issue-44578.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this warning 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)
+ = 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 3 previous errors
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.rs b/src/test/ui/consts/const-eval/issue-50814-2.rs
index 15f4de0ae..49d1d8ff0 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.rs
+++ b/src/test/ui/consts/const-eval/issue-50814-2.rs
@@ -11,8 +11,7 @@ trait Foo<T> {
struct A<T>(T);
impl<T: C> Foo<T> for A<T> {
- const BAR: usize = [5, 6, 7][T::BOO]; //~ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ const BAR: usize = [5, 6, 7][T::BOO]; //~ ERROR evaluation of `<A<()> as Foo<()>>::BAR` failed
}
fn foo<T: C>() -> &'static usize {
diff --git a/src/test/ui/consts/const-eval/issue-50814-2.stderr b/src/test/ui/consts/const-eval/issue-50814-2.stderr
index cc19caca7..6604f2b9f 100644
--- a/src/test/ui/consts/const-eval/issue-50814-2.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814-2.stderr
@@ -1,21 +1,17 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of `<A<()> as Foo<()>>::BAR` failed
--> $DIR/issue-50814-2.rs:14:24
|
LL | const BAR: usize = [5, 6, 7][T::BOO];
- | ---------------- ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42
error[E0080]: evaluation of `foo::<()>` failed
- --> $DIR/issue-50814-2.rs:19:6
+ --> $DIR/issue-50814-2.rs:18:6
|
LL | &<A<T> as Foo<T>>::BAR
| ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
note: the above error was encountered while instantiating `fn foo::<()>`
- --> $DIR/issue-50814-2.rs:31:22
+ --> $DIR/issue-50814-2.rs:30:22
|
LL | println!("{:x}", foo::<()>() as *const usize as usize);
| ^^^^^^^^^^^
@@ -23,14 +19,3 @@ LL | println!("{:x}", foo::<()>() as *const usize as usize);
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/issue-50814-2.rs:14:24
- |
-LL | const BAR: usize = [5, 6, 7][T::BOO];
- | ---------------- ^^^^^^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 42
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs
index 98229f919..5a587701f 100644
--- a/src/test/ui/consts/const-eval/issue-50814.rs
+++ b/src/test/ui/consts/const-eval/issue-50814.rs
@@ -13,8 +13,7 @@ struct Sum<A,B>(A,B);
impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
const MAX: u8 = A::MAX + B::MAX;
- //~^ ERROR any use of this value will cause an error [const_err]
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of `<Sum<U8, U8> as Unsigned>::MAX` failed
}
fn foo<T>(_: T) -> &'static u8 {
diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr
index 6ceef91a0..46dd2b89f 100644
--- a/src/test/ui/consts/const-eval/issue-50814.stderr
+++ b/src/test/ui/consts/const-eval/issue-50814.stderr
@@ -1,21 +1,17 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of `<Sum<U8, U8> as Unsigned>::MAX` failed
--> $DIR/issue-50814.rs:15:21
|
LL | const MAX: u8 = A::MAX + B::MAX;
- | ------------- ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow
error[E0080]: evaluation of `foo::<i32>` failed
- --> $DIR/issue-50814.rs:21:6
+ --> $DIR/issue-50814.rs:20:6
|
LL | &Sum::<U8,U8>::MAX
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
note: the above error was encountered while instantiating `fn foo::<i32>`
- --> $DIR/issue-50814.rs:26:5
+ --> $DIR/issue-50814.rs:25:5
|
LL | foo(0);
| ^^^^^^
@@ -23,14 +19,3 @@ LL | foo(0);
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/issue-50814.rs:15:21
- |
-LL | const MAX: u8 = A::MAX + B::MAX;
- | ------------- ^^^^^^^^^^^^^^^ attempt to compute `u8::MAX + u8::MAX`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs
index 2518e4ed4..e6639826c 100644
--- a/src/test/ui/consts/const-eval/issue-65394.rs
+++ b/src/test/ui/consts/const-eval/issue-65394.rs
@@ -4,7 +4,7 @@
// We will likely have to change this behavior before we allow `&mut` in a `const`.
const _: Vec<i32> = {
- let mut x = Vec::<i32>::new(); //~ ERROR destructors cannot be evaluated at compile-time
+ let mut x = Vec::<i32>::new(); //~ ERROR destructor of
let r = &mut x; //~ ERROR mutable references are not allowed in constants
let y = x;
y
diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr
index ec229d7f5..ae6f0e937 100644
--- a/src/test/ui/consts/const-eval/issue-65394.stderr
+++ b/src/test/ui/consts/const-eval/issue-65394.stderr
@@ -7,11 +7,11 @@ LL | let r = &mut x;
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Vec<i32>` cannot be evaluated at compile-time
--> $DIR/issue-65394.rs:7:9
|
LL | let mut x = Vec::<i32>::new();
- | ^^^^^ constants cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constants
...
LL | };
| - value is dropped here
diff --git a/src/test/ui/consts/const-eval/livedrop.rs b/src/test/ui/consts/const-eval/livedrop.rs
index 66b7d0580..543f1f0ec 100644
--- a/src/test/ui/consts/const-eval/livedrop.rs
+++ b/src/test/ui/consts/const-eval/livedrop.rs
@@ -1,6 +1,6 @@
const _: Option<Vec<i32>> = {
let mut never_returned = Some(Vec::new());
- let mut always_returned = None; //~ ERROR destructors cannot be evaluated at compile-time
+ let mut always_returned = None; //~ ERROR destructor of
let mut i = 0;
loop {
diff --git a/src/test/ui/consts/const-eval/livedrop.stderr b/src/test/ui/consts/const-eval/livedrop.stderr
index 1e8b4230c..d04fdb70e 100644
--- a/src/test/ui/consts/const-eval/livedrop.stderr
+++ b/src/test/ui/consts/const-eval/livedrop.stderr
@@ -1,8 +1,8 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/livedrop.rs:3:9
|
LL | let mut always_returned = None;
- | ^^^^^^^^^^^^^^^^^^^ constants cannot evaluate destructors
+ | ^^^^^^^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants
...
LL | always_returned = never_returned;
| --------------- value is dropped here
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
index 80b0a1432..d2a840932 100644
--- a/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.rs
@@ -1,7 +1,6 @@
// build-fail
// Regression test for #66975
-#![warn(const_err)]
#![feature(never_type)]
struct PrintName;
diff --git a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
index b26286411..4204d302b 100644
--- a/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
+++ b/src/test/ui/consts/const-eval/panic-assoc-never-type.stderr
@@ -1,13 +1,13 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/panic-assoc-never-type.rs:10:21
+ --> $DIR/panic-assoc-never-type.rs:9:21
|
LL | const VOID: ! = panic!();
- | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:10:21
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-assoc-never-type.rs:9:21
|
= 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)
error[E0080]: erroneous constant used
- --> $DIR/panic-assoc-never-type.rs:15:13
+ --> $DIR/panic-assoc-never-type.rs:14:13
|
LL | let _ = PrintName::VOID;
| ^^^^^^^^^^^^^^^ referenced constant has errors
diff --git a/src/test/ui/consts/const-eval/panic-never-type.rs b/src/test/ui/consts/const-eval/panic-never-type.rs
index a74d3ba29..a9e9026d9 100644
--- a/src/test/ui/consts/const-eval/panic-never-type.rs
+++ b/src/test/ui/consts/const-eval/panic-never-type.rs
@@ -1,5 +1,4 @@
// Regression test for #66975
-#![warn(const_err)]
#![feature(never_type)]
const VOID: ! = panic!();
diff --git a/src/test/ui/consts/const-eval/panic-never-type.stderr b/src/test/ui/consts/const-eval/panic-never-type.stderr
index 9728aed07..6bff14a45 100644
--- a/src/test/ui/consts/const-eval/panic-never-type.stderr
+++ b/src/test/ui/consts/const-eval/panic-never-type.stderr
@@ -1,8 +1,8 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/panic-never-type.rs:5:17
+ --> $DIR/panic-never-type.rs:4:17
|
LL | const VOID: ! = panic!();
- | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:5:17
+ | ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/panic-never-type.rs:4:17
|
= 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)
diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs b/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs
index 07bca7d64..d6c768868 100644
--- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs
+++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.rs
@@ -5,9 +5,8 @@ const PARTIAL_OVERWRITE: () = {
let mut p = &42;
unsafe {
let ptr: *mut _ = &mut p;
- *(ptr as *mut u8) = 123; //~ ERROR any use of this value
+ *(ptr as *mut u8) = 123; //~ ERROR constant
//~| unable to overwrite parts of a pointer
- //~| WARN previously accepted
}
let x = *p;
};
diff --git a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
index 75e50a27b..13ca4379b 100644
--- a/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
+++ b/src/test/ui/consts/const-eval/partial_ptr_overwrite.stderr
@@ -1,33 +1,12 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/partial_ptr_overwrite.rs:8:9
|
-LL | const PARTIAL_OVERWRITE: () = {
- | ---------------------------
-...
LL | *(ptr as *mut u8) = 123;
| ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/partial_ptr_overwrite.rs:8:9
- |
-LL | const PARTIAL_OVERWRITE: () = {
- | ---------------------------
-...
-LL | *(ptr as *mut u8) = 123;
- | ^^^^^^^^^^^^^^^^^^^^^^^ unable to overwrite parts of a pointer in memory at alloc4
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
index 1fc7af637..656dd33e1 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.rs
@@ -1,5 +1,3 @@
-#![allow(const_err)]
-
#[repr(C)]
union Bar {
a: &'static u8,
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
index c6ca30e09..596fa090d 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail.stderr
@@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promoted_const_fn_fail.rs:19:27
+ --> $DIR/promoted_const_fn_fail.rs:17:27
|
LL | let x: &'static u8 = &(bar() + 1);
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
index c53424664..5009dbcb9 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.rs
@@ -1,5 +1,3 @@
-#![deny(const_err)]
-
#[repr(C)]
union Bar {
a: &'static u8,
diff --git a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
index c6275a835..63dc43a41 100644
--- a/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
+++ b/src/test/ui/consts/const-eval/promoted_const_fn_fail_deny_const_err.stderr
@@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
- --> $DIR/promoted_const_fn_fail_deny_const_err.rs:20:27
+ --> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27
|
LL | let x: &'static u8 = &(bar() + 1);
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
index cfca8ef07..2a254bfde 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr
@@ -5,111 +5,40 @@ LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:20
+ --> $DIR/promoted_errors.rs:11:9
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:21:5
+ --> $DIR/promoted_errors.rs:19:5
|
LL | 1 / 0
| ^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:41
+ --> $DIR/promoted_errors.rs:11:30
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:27:5
+ --> $DIR/promoted_errors.rs:23:5
|
LL | 1 / (1 - 1)
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:31:5
+ --> $DIR/promoted_errors.rs:27:5
|
LL | 1 / (false as i32)
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:35:5
+ --> $DIR/promoted_errors.rs:31:5
|
LL | [1, 2, 3][4]
| ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:15:5
- |
-LL | 0 - 1
- | ^^^^^
- | |
- | attempt to compute `0_u32 - 1_u32`, which would overflow
- | inside `overflow` at $DIR/promoted_errors.rs:15:5
- | inside `X` at $DIR/promoted_errors.rs:43:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:43:28
- |
-LL | const X: () = {
- | -----------
-LL | let _x: &'static u32 = &overflow();
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: 7 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:15:5
- |
-LL | 0 - 1
- | ^^^^^
- | |
- | attempt to compute `0_u32 - 1_u32`, which would overflow
- | inside `overflow` at $DIR/promoted_errors.rs:15:5
- | inside `X` at $DIR/promoted_errors.rs:43:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:43:28
- |
-LL | const X: () = {
- | -----------
-LL | let _x: &'static u32 = &overflow();
- | ^^^^^^^^^^^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+warning: 5 warnings emitted
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
index 984484a85..2a254bfde 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr
@@ -5,113 +5,40 @@ LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:20
+ --> $DIR/promoted_errors.rs:11:9
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:21:5
+ --> $DIR/promoted_errors.rs:19:5
|
LL | 1 / 0
| ^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:41
+ --> $DIR/promoted_errors.rs:11:30
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:27:5
+ --> $DIR/promoted_errors.rs:23:5
|
LL | 1 / (1 - 1)
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:31:5
+ --> $DIR/promoted_errors.rs:27:5
|
LL | 1 / (false as i32)
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:35:5
+ --> $DIR/promoted_errors.rs:31:5
|
LL | [1, 2, 3][4]
| ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:21:5
- |
-LL | 1 / 0
- | ^^^^^
- | |
- | attempt to divide `1_i32` by zero
- | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5
- | inside `X` at $DIR/promoted_errors.rs:46:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:46:28
- |
-LL | const X: () = {
- | -----------
-...
-LL | let _x: &'static i32 = &div_by_zero1();
- | ^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: 7 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:21:5
- |
-LL | 1 / 0
- | ^^^^^
- | |
- | attempt to divide `1_i32` by zero
- | inside `div_by_zero1` at $DIR/promoted_errors.rs:21:5
- | inside `X` at $DIR/promoted_errors.rs:46:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:46:28
- |
-LL | const X: () = {
- | -----------
-...
-LL | let _x: &'static i32 = &div_by_zero1();
- | ^^^^^^^^^^^^^^^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+warning: 5 warnings emitted
diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
index cfca8ef07..2a254bfde 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
+++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr
@@ -5,111 +5,40 @@ LL | 0 - 1
| ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:20
+ --> $DIR/promoted_errors.rs:11:9
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:21:5
+ --> $DIR/promoted_errors.rs:19:5
|
LL | 1 / 0
| ^^^^^ attempt to divide `1_i32` by zero
|
note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:41
+ --> $DIR/promoted_errors.rs:11:30
|
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^^^^^^^^^^^
+LL | #![warn(arithmetic_overflow, unconditional_panic)]
+ | ^^^^^^^^^^^^^^^^^^^
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:27:5
+ --> $DIR/promoted_errors.rs:23:5
|
LL | 1 / (1 - 1)
| ^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:31:5
+ --> $DIR/promoted_errors.rs:27:5
|
LL | 1 / (false as i32)
| ^^^^^^^^^^^^^^^^^^ attempt to divide `1_i32` by zero
warning: this operation will panic at runtime
- --> $DIR/promoted_errors.rs:35:5
+ --> $DIR/promoted_errors.rs:31:5
|
LL | [1, 2, 3][4]
| ^^^^^^^^^^^^ index out of bounds: the length is 3 but the index is 4
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:15:5
- |
-LL | 0 - 1
- | ^^^^^
- | |
- | attempt to compute `0_u32 - 1_u32`, which would overflow
- | inside `overflow` at $DIR/promoted_errors.rs:15:5
- | inside `X` at $DIR/promoted_errors.rs:43:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:43:28
- |
-LL | const X: () = {
- | -----------
-LL | let _x: &'static u32 = &overflow();
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: 7 warnings emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:15:5
- |
-LL | 0 - 1
- | ^^^^^
- | |
- | attempt to compute `0_u32 - 1_u32`, which would overflow
- | inside `overflow` at $DIR/promoted_errors.rs:15:5
- | inside `X` at $DIR/promoted_errors.rs:43:29
-...
-LL | const X: () = {
- | -----------
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/promoted_errors.rs:43:28
- |
-LL | const X: () = {
- | -----------
-LL | let _x: &'static u32 = &overflow();
- | ^^^^^^^^^^^ referenced constant has errors
- |
-note: the lint level is defined here
- --> $DIR/promoted_errors.rs:11:9
- |
-LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+warning: 5 warnings emitted
diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs
index eb891de33..2c42d0356 100644
--- a/src/test/ui/consts/const-eval/promoted_errors.rs
+++ b/src/test/ui/consts/const-eval/promoted_errors.rs
@@ -8,20 +8,16 @@
//! This test ensures that when we promote code that fails to evaluate, the build still succeeds.
-#![warn(const_err, arithmetic_overflow, unconditional_panic)]
+#![warn(arithmetic_overflow, unconditional_panic)]
// The only way to have promoteds that fail is in `const fn` called from `const`/`static`.
const fn overflow() -> u32 {
0 - 1
- //[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
- //[opt_with_overflow_checks,noopt]~| WARN this was previously accepted by the compiler
- //~^^^ WARN this arithmetic operation will overflow
+ //~^ WARN this arithmetic operation will overflow
}
const fn div_by_zero1() -> i32 {
1 / 0
- //[opt]~^ WARN any use of this value will cause an error
- //[opt]~| WARN this was previously accepted by the compiler but is being phased out
- //~^^^ WARN this operation will panic at runtime
+ //~^ WARN this operation will panic at runtime
}
const fn div_by_zero2() -> i32 {
1 / (1 - 1)
@@ -36,21 +32,6 @@ const fn oob() -> i32 {
//~^ WARN this operation will panic at runtime
}
-// An unused constant containing failing promoteds.
-// This should work as long as `const_err` can be turned into just a warning;
-// once it turns into a hard error, just remove `X`.
-const X: () = {
- let _x: &'static u32 = &overflow();
- //[opt_with_overflow_checks,noopt]~^ WARN any use of this value will cause an error
- //[opt_with_overflow_checks,noopt]~| WARN this was previously accepted by the compiler
- let _x: &'static i32 = &div_by_zero1();
- //[opt]~^ WARN any use of this value will cause an error
- //[opt]~| WARN this was previously accepted by the compiler but is being phased out
- let _x: &'static i32 = &div_by_zero2();
- let _x: &'static i32 = &div_by_zero3();
- let _x: &'static i32 = &oob();
-};
-
const fn mk_false() -> bool { false }
// An actually used constant referencing failing promoteds in dead code.
diff --git a/src/test/ui/consts/const-eval/pub_const_err.rs b/src/test/ui/consts/const-eval/pub_const_err.rs
deleted file mode 100644
index 5faacd556..000000000
--- a/src/test/ui/consts/const-eval/pub_const_err.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-#![warn(const_err)]
-
-#![crate_type = "lib"]
-
-pub const Z: u32 = 0 - 1;
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-pub type Foo = [i32; 0 - 1];
diff --git a/src/test/ui/consts/const-eval/pub_const_err.stderr b/src/test/ui/consts/const-eval/pub_const_err.stderr
deleted file mode 100644
index 36197a7ab..000000000
--- a/src/test/ui/consts/const-eval/pub_const_err.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: any use of this value will cause an error
- --> $DIR/pub_const_err.rs:6:20
- |
-LL | pub const Z: u32 = 0 - 1;
- | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/pub_const_err.rs:2:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: 1 warning emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/pub_const_err.rs:6:20
- |
-LL | pub const Z: u32 = 0 - 1;
- | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/pub_const_err.rs:2:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.rs b/src/test/ui/consts/const-eval/pub_const_err_bin.rs
deleted file mode 100644
index 82eae2512..000000000
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-#![warn(const_err)]
-
-pub const Z: u32 = 0 - 1;
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-
-pub type Foo = [i32; 0 - 1];
-
-fn main() {}
diff --git a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr b/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
deleted file mode 100644
index 2eef3b8f5..000000000
--- a/src/test/ui/consts/const-eval/pub_const_err_bin.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: any use of this value will cause an error
- --> $DIR/pub_const_err_bin.rs:4:20
- |
-LL | pub const Z: u32 = 0 - 1;
- | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/pub_const_err_bin.rs:2:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-warning: 1 warning emitted
-
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/pub_const_err_bin.rs:4:20
- |
-LL | pub const Z: u32 = 0 - 1;
- | ---------------- ^^^^^ attempt to compute `0_u32 - 1_u32`, which would overflow
- |
-note: the lint level is defined here
- --> $DIR/pub_const_err_bin.rs:2:9
- |
-LL | #![warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
index 30935e415..032ceb246 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.32bit.stderr
@@ -1,12 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ref_to_int_match.rs:25:27
|
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
- | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
@@ -24,16 +21,4 @@ LL | 10..=BAR => {},
error: aborting due to 3 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ref_to_int_match.rs:25:27
- |
-LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
- | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
index 30935e415..032ceb246 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.64bit.stderr
@@ -1,12 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ref_to_int_match.rs:25:27
|
LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
- | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
@@ -24,16 +21,4 @@ LL | 10..=BAR => {},
error: aborting due to 3 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ref_to_int_match.rs:25:27
- |
-LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
- | -------------- ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.rs b/src/test/ui/consts/const-eval/ref_to_int_match.rs
index 3f342d916..70c6e7d94 100644
--- a/src/test/ui/consts/const-eval/ref_to_int_match.rs
+++ b/src/test/ui/consts/const-eval/ref_to_int_match.rs
@@ -23,5 +23,4 @@ type Int = u64;
type Int = u32;
const BAR: Int = unsafe { Foo { r: &42 }.f };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
diff --git a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
index 752fd01f3..93bc96e67 100644
--- a/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:23:1
+ --> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
@@ -9,31 +9,26 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
01 00 00 00 │ ....
}
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:26:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:30:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:43:1
+ --> $DIR/ub-enum.rs:42:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
@@ -43,47 +38,41 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
00 00 00 00 │ ....
}
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:45:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:49:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:47:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:59:42
+ --> $DIR/ub-enum.rs:56:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:64:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:61:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:82:1
+ --> $DIR/ub-enum.rs:78:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
@@ -94,7 +83,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:84:1
+ --> $DIR/ub-enum.rs:80:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
@@ -105,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:92:1
+ --> $DIR/ub-enum.rs:88:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +105,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:97:77
+ --> $DIR/ub-enum.rs:93:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:99:77
+ --> $DIR/ub-enum.rs:95:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -130,68 +119,3 @@ LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe {
error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:26:1
- |
-LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:30:1
- |
-LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:45:1
- |
-LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:49:1
- |
-LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:64:1
- |
-LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
diff --git a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
index 3f1546a27..280ba25a8 100644
--- a/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:23:1
+ --> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
@@ -9,31 +9,26 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
01 00 00 00 00 00 00 00 │ ........
}
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:26:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:30:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:43:1
+ --> $DIR/ub-enum.rs:42:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
@@ -43,47 +38,41 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
00 00 00 00 00 00 00 00 │ ........
}
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:45:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:49:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:47:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:59:42
+ --> $DIR/ub-enum.rs:56:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:64:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-enum.rs:61:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:82:1
+ --> $DIR/ub-enum.rs:78:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
@@ -94,7 +83,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:84:1
+ --> $DIR/ub-enum.rs:80:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
@@ -105,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-enum.rs:92:1
+ --> $DIR/ub-enum.rs:88:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
@@ -116,13 +105,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:97:77
+ --> $DIR/ub-enum.rs:93:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-enum.rs:99:77
+ --> $DIR/ub-enum.rs:95:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
@@ -130,68 +119,3 @@ LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe {
error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:26:1
- |
-LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:30:1
- |
-LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:45:1
- |
-LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:49:1
- |
-LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-enum.rs:64:1
- |
-LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs
index d8dc6d057..6935be2f9 100644
--- a/src/test/ui/consts/const-eval/ub-enum.rs
+++ b/src/test/ui/consts/const-eval/ub-enum.rs
@@ -1,5 +1,6 @@
// stderr-per-bitwidth
#![feature(never_type)]
+#![allow(invalid_value)]
use std::mem;
@@ -24,12 +25,10 @@ const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
//~^ ERROR is undefined behavior
const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// # simple enum with discriminant 2
@@ -43,12 +42,10 @@ enum Enum2 {
const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
//~^ ERROR is undefined behavior
const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// something wrapping the enum so that we test layout first, not enum
const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// Undef enum discriminant.
#[repr(C)]
@@ -62,8 +59,7 @@ const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
// Pointer value in an enum with a niche that is not just 0.
const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// # valid discriminant for uninhabited variant
diff --git a/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr
index 6100a98d1..edcde13b0 100644
--- a/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-int-array.32bit.stderr
@@ -1,17 +1,17 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:16:9
+ --> $DIR/ub-int-array.rs:15:9
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:31:13
+ --> $DIR/ub-int-array.rs:30:13
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:57:13
+ --> $DIR/ub-int-array.rs:56:13
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
diff --git a/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr
index 6100a98d1..edcde13b0 100644
--- a/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-int-array.64bit.stderr
@@ -1,17 +1,17 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:16:9
+ --> $DIR/ub-int-array.rs:15:9
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:31:13
+ --> $DIR/ub-int-array.rs:30:13
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-int-array.rs:57:13
+ --> $DIR/ub-int-array.rs:56:13
|
LL | MaybeUninit { uninit: () }.init,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
diff --git a/src/test/ui/consts/const-eval/ub-int-array.rs b/src/test/ui/consts/const-eval/ub-int-array.rs
index cb85e3b01..a68d3fb17 100644
--- a/src/test/ui/consts/const-eval/ub-int-array.rs
+++ b/src/test/ui/consts/const-eval/ub-int-array.rs
@@ -1,4 +1,3 @@
-#![allow(const_err)] // make sure we cannot allow away the errors tested here
// stderr-per-bitwidth
//! Test the "array of int" fast path in validity checking, and in particular whether it
//! points at the right array element.
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
index 693c0e99b..dbd05b8f4 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.32bit.stderr
@@ -10,13 +10,13 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-nonnull.rs:19:30
+ --> $DIR/ub-nonnull.rs:18:30
|
LL | let out_of_bounds_ptr = &ptr[255];
| ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:23:1
+ --> $DIR/ub-nonnull.rs:22:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -27,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:25:1
+ --> $DIR/ub-nonnull.rs:24:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -38,13 +38,13 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-nonnull.rs:33:36
+ --> $DIR/ub-nonnull.rs:32:36
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:42:1
+ --> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30
@@ -55,7 +55,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:48:1
+ --> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
index d22191213..5a1ac09bd 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-nonnull.64bit.stderr
@@ -10,13 +10,13 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-nonnull.rs:19:30
+ --> $DIR/ub-nonnull.rs:18:30
|
LL | let out_of_bounds_ptr = &ptr[255];
| ^^^^^^^^ dereferencing pointer failed: alloc11 has size 1, so pointer to 256 bytes starting at offset 0 is out-of-bounds
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:23:1
+ --> $DIR/ub-nonnull.rs:22:1
|
LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -27,7 +27,7 @@ LL | const NULL_U8: NonZeroU8 = unsafe { mem::transmute(0u8) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:25:1
+ --> $DIR/ub-nonnull.rs:24:1
|
LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
@@ -38,13 +38,13 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-nonnull.rs:33:36
+ --> $DIR/ub-nonnull.rs:32:36
|
LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:42:1
+ --> $DIR/ub-nonnull.rs:41:1
|
LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 42, but expected something in the range 10..=30
@@ -55,7 +55,7 @@ LL | const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-nonnull.rs:48:1
+ --> $DIR/ub-nonnull.rs:47:1
|
LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 20, but expected something less or equal to 10, or greater or equal to 30
diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs
index 777c6d988..d22a99cd0 100644
--- a/src/test/ui/consts/const-eval/ub-nonnull.rs
+++ b/src/test/ui/consts/const-eval/ub-nonnull.rs
@@ -1,6 +1,6 @@
// stderr-per-bitwidth
#![feature(rustc_attrs)]
-#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here
+#![allow(invalid_value)] // make sure we cannot allow away the errors tested here
use std::mem;
use std::ptr::NonNull;
@@ -12,7 +12,6 @@ const NON_NULL_PTR: NonNull<u8> = unsafe { mem::transmute(&1) };
const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
//~^ ERROR it is undefined behavior to use this value
-#[deny(const_err)] // this triggers a `const_err` so validation does not even happen
const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe {
let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle
// Use address-of-element for pointer arithmetic. This could wrap around to null!
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
index 3e93219c8..6f5c028cb 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.32bit.stderr
@@ -42,60 +42,47 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
00 00 00 00 │ ....
}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-ref-ptr.rs:31:1
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:39
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:34:39
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:34:38
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:86
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:38:86
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:85
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:38:85
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:47:1
+ --> $DIR/ub-ref-ptr.rs:42:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -106,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:50:1
+ --> $DIR/ub-ref-ptr.rs:45:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -117,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:53:41
+ --> $DIR/ub-ref-ptr.rs:48:41
|
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:57:1
+ --> $DIR/ub-ref-ptr.rs:52:1
|
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -134,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:59:38
+ --> $DIR/ub-ref-ptr.rs:54:38
|
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:62:1
+ --> $DIR/ub-ref-ptr.rs:57:1
|
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -151,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:64:1
+ --> $DIR/ub-ref-ptr.rs:59:1
|
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -164,64 +151,3 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:31:1
- |
-LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:39
- |
-LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:38
- |
-LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:86
- |
-LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:85
- |
-LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
index bc2aa12a2..5ffb710d4 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.64bit.stderr
@@ -42,60 +42,47 @@ LL | const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
00 00 00 00 00 00 00 00 │ ........
}
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ub-ref-ptr.rs:31:1
|
LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:39
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:34:39
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:34:38
|
LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:86
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:38:86
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:85
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-ref-ptr.rs:38:85
|
LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:47:1
+ --> $DIR/ub-ref-ptr.rs:42:1
|
LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x539 is unallocated)
@@ -106,7 +93,7 @@ LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:50:1
+ --> $DIR/ub-ref-ptr.rs:45:1
|
LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (address 0x539 is unallocated)
@@ -117,13 +104,13 @@ LL | const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:53:41
+ --> $DIR/ub-ref-ptr.rs:48:41
|
LL | const UNINIT_PTR: *const i32 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:57:1
+ --> $DIR/ub-ref-ptr.rs:52:1
|
LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a function pointer
@@ -134,13 +121,13 @@ LL | const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-ref-ptr.rs:59:38
+ --> $DIR/ub-ref-ptr.rs:54:38
|
LL | const UNINIT_FN_PTR: fn() = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:62:1
+ --> $DIR/ub-ref-ptr.rs:57:1
|
LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0xd[noalloc], but expected a function pointer
@@ -151,7 +138,7 @@ LL | const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-ref-ptr.rs:64:1
+ --> $DIR/ub-ref-ptr.rs:59:1
|
LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered alloc41, but expected a function pointer
@@ -164,64 +151,3 @@ LL | const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:31:1
- |
-LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:39
- |
-LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:35:38
- |
-LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
- | ---------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:86
- |
-LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-ref-ptr.rs:41:85
- |
-LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
- | ------------------------------------------ ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/ub-ref-ptr.rs b/src/test/ui/consts/const-eval/ub-ref-ptr.rs
index c62848f70..92049d4c1 100644
--- a/src/test/ui/consts/const-eval/ub-ref-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-ref-ptr.rs
@@ -29,20 +29,15 @@ const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
// but that would fail to compile; so we ended up breaking user code that would
// have worked fine had we not promoted.
const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }];
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-//~| ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
+//~| ERROR evaluation of constant value failed
const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
-//~| ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
+//~| ERROR evaluation of constant value failed
const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
//~^ ERROR it is undefined behavior to use this value
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
index 7f0feb130..7d3232257 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:15:1
+ --> $DIR/ub-uninhabit.rs:14:1
|
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar
@@ -8,7 +8,7 @@ LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
= note: the raw bytes of the constant (size: 0, align: 1) {}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:18:1
+ --> $DIR/ub-uninhabit.rs:17:1
|
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar
@@ -19,7 +19,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:21:1
+ --> $DIR/ub-uninhabit.rs:20:1
|
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
index 4dcbbc2f5..2b7659f5d 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:15:1
+ --> $DIR/ub-uninhabit.rs:14:1
|
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar
@@ -8,7 +8,7 @@ LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
= note: the raw bytes of the constant (size: 0, align: 1) {}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:18:1
+ --> $DIR/ub-uninhabit.rs:17:1
|
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to uninhabited type Bar
@@ -19,7 +19,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-uninhabit.rs:21:1
+ --> $DIR/ub-uninhabit.rs:20:1
|
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar
diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs
index 33fbd14c4..213f15b79 100644
--- a/src/test/ui/consts/const-eval/ub-uninhabit.rs
+++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs
@@ -1,5 +1,4 @@
// stderr-per-bitwidth
-#![allow(const_err)] // make sure we cannot allow away the errors tested here
use std::mem;
diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs
index 57dd7b9e5..ceac59870 100644
--- a/src/test/ui/consts/const-eval/ub-upvars.rs
+++ b/src/test/ui/consts/const-eval/ub-upvars.rs
@@ -1,5 +1,5 @@
// stderr-per-bitwidth
-#![allow(const_err, invalid_value)] // make sure we cannot allow away the errors tested here
+#![allow(invalid_value)] // make sure we cannot allow away the errors tested here
use std::mem;
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
index 4cd974e7b..c8b46608d 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:37:1
+ --> $DIR/ub-wide-ptr.rs:36:1
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -10,7 +10,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:39:1
+ --> $DIR/ub-wide-ptr.rs:38:1
|
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -20,31 +20,26 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us
╾─allocN─╼ ff ff ff ff │ ╾──╼....
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:42:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:41:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:46:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:44:1
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:49:1
+ --> $DIR/ub-wide-ptr.rs:46:1
|
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -55,7 +50,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize:
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:53:1
+ --> $DIR/ub-wide-ptr.rs:50:1
|
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
@@ -66,7 +61,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:56:1
+ --> $DIR/ub-wide-ptr.rs:53:1
|
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
@@ -77,13 +72,13 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:63:1
+ --> $DIR/ub-wide-ptr.rs:60:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:70:1
+ --> $DIR/ub-wide-ptr.rs:67:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -94,7 +89,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:73:1
+ --> $DIR/ub-wide-ptr.rs:70:1
|
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -104,19 +99,17 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is
╾─allocN─╼ ff ff ff 7f │ ╾──╼....
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:76:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:73:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:80:1
+ --> $DIR/ub-wide-ptr.rs:76:1
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
@@ -126,19 +119,17 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
╾─allocN─╼ e7 03 00 00 │ ╾──╼....
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:83:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:79:1
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:88:1
+ --> $DIR/ub-wide-ptr.rs:83:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
@@ -148,17 +139,14 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
╾─allocN─╼ │ ╾──╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:88:40
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:83:40
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
- | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:96:1
+ --> $DIR/ub-wide-ptr.rs:90:1
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
@@ -168,17 +156,14 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
╾allocN─╼ │ ╾──╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:96:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:90:42
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:101:1
+ --> $DIR/ub-wide-ptr.rs:94:1
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -188,23 +173,20 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
╾allocN─╼ │ ╾──╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:101:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:94:42
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:110:1
+ --> $DIR/ub-wide-ptr.rs:102:1
|
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:119:1
+ --> $DIR/ub-wide-ptr.rs:111:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -215,7 +197,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:123:1
+ --> $DIR/ub-wide-ptr.rs:115:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -226,7 +208,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:127:1
+ --> $DIR/ub-wide-ptr.rs:119:1
|
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
@@ -237,25 +219,25 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:130:57
+ --> $DIR/ub-wide-ptr.rs:122:57
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:133:57
+ --> $DIR/ub-wide-ptr.rs:125:57
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:136:56
+ --> $DIR/ub-wide-ptr.rs:128:56
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:139:1
+ --> $DIR/ub-wide-ptr.rs:131:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -266,7 +248,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:144:1
+ --> $DIR/ub-wide-ptr.rs:136:1
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -277,7 +259,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:149:1
+ --> $DIR/ub-wide-ptr.rs:141:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
@@ -288,7 +270,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:151:1
+ --> $DIR/ub-wide-ptr.rs:143:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
@@ -299,13 +281,13 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
}
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:157:5
+ --> $DIR/ub-wide-ptr.rs:149:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:161:5
+ --> $DIR/ub-wide-ptr.rs:153:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
@@ -313,88 +295,3 @@ LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
error: aborting due to 32 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:42:1
- |
-LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:46:1
- |
-LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:76:1
- |
-LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:83:1
- |
-LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:88:40
- |
-LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
- | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:96:42
- |
-LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:101:42
- |
-LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
index 1d84b7bce..70574d2dc 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:37:1
+ --> $DIR/ub-wide-ptr.rs:36:1
|
LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -10,7 +10,7 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:39:1
+ --> $DIR/ub-wide-ptr.rs:38:1
|
LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -20,31 +20,26 @@ LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, us
╾───────allocN───────╼ ff ff ff ff ff ff ff ff │ ╾──────╼........
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:42:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:41:1
|
LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:46:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:44:1
|
LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:49:1
+ --> $DIR/ub-wide-ptr.rs:46:1
|
LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -55,7 +50,7 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize:
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:53:1
+ --> $DIR/ub-wide-ptr.rs:50:1
|
LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>: encountered uninitialized data in `str`
@@ -66,7 +61,7 @@ LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:56:1
+ --> $DIR/ub-wide-ptr.rs:53:1
|
LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered uninitialized data in `str`
@@ -77,13 +72,13 @@ LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUni
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:63:1
+ --> $DIR/ub-wide-ptr.rs:60:1
|
LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:70:1
+ --> $DIR/ub-wide-ptr.rs:67:1
|
LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (going beyond the bounds of its allocation)
@@ -94,7 +89,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:73:1
+ --> $DIR/ub-wide-ptr.rs:70:1
|
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered invalid reference metadata: slice is bigger than largest supported object
@@ -104,19 +99,17 @@ LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, is
╾───────allocN───────╼ ff ff ff ff ff ff ff 7f │ ╾──────╼........
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:76:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:73:1
|
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:80:1
+ --> $DIR/ub-wide-ptr.rs:76:1
|
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling box (going beyond the bounds of its allocation)
@@ -126,19 +119,17 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
╾───────allocN───────╼ e7 03 00 00 00 00 00 00 │ ╾──────╼........
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:83:1
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:79:1
|
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:88:1
+ --> $DIR/ub-wide-ptr.rs:83:1
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>[0]: encountered 0x03, but expected a boolean
@@ -148,17 +139,14 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
╾───────allocN───────╼ │ ╾──────╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:88:40
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:83:40
|
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
- | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:96:1
+ --> $DIR/ub-wide-ptr.rs:90:1
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.0: encountered 0x03, but expected a boolean
@@ -168,17 +156,14 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3
╾──────allocN───────╼ │ ╾──────╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:96:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:90:42
|
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:101:1
+ --> $DIR/ub-wide-ptr.rs:94:1
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.1[0]: encountered 0x03, but expected a boolean
@@ -188,23 +173,20 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran
╾──────allocN───────╼ │ ╾──────╼
}
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:101:42
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ub-wide-ptr.rs:94:42
|
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:110:1
+ --> $DIR/ub-wide-ptr.rs:102:1
|
LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:119:1
+ --> $DIR/ub-wide-ptr.rs:111:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -215,7 +197,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:123:1
+ --> $DIR/ub-wide-ptr.rs:115:1
|
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -226,7 +208,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:127:1
+ --> $DIR/ub-wide-ptr.rs:119:1
|
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered 0x4[noalloc], but expected a vtable pointer
@@ -237,25 +219,25 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
}
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:130:57
+ --> $DIR/ub-wide-ptr.rs:122:57
|
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:133:57
+ --> $DIR/ub-wide-ptr.rs:125:57
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: evaluation of constant value failed
- --> $DIR/ub-wide-ptr.rs:136:56
+ --> $DIR/ub-wide-ptr.rs:128:56
|
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:139:1
+ --> $DIR/ub-wide-ptr.rs:131:1
|
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered allocN, but expected a vtable pointer
@@ -266,7 +248,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:144:1
+ --> $DIR/ub-wide-ptr.rs:136:1
|
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -277,7 +259,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:149:1
+ --> $DIR/ub-wide-ptr.rs:141:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
@@ -288,7 +270,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/ub-wide-ptr.rs:151:1
+ --> $DIR/ub-wide-ptr.rs:143:1
|
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
@@ -299,13 +281,13 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
}
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:157:5
+ --> $DIR/ub-wide-ptr.rs:149:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
error[E0080]: could not evaluate static initializer
- --> $DIR/ub-wide-ptr.rs:161:5
+ --> $DIR/ub-wide-ptr.rs:153:5
|
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
@@ -313,88 +295,3 @@ LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
error: aborting due to 32 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:42:1
- |
-LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:46:1
- |
-LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:76:1
- |
-LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:83:1
- |
-LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:88:40
- |
-LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
- | ------------------------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:96:42
- |
-LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ub-wide-ptr.rs:101:42
- |
-LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
- | -------------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index 788403a6d..65f6f0235 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -9,8 +9,7 @@ use std::mem;
// normalize-stderr-test "size \d+" -> "size N"
/// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error
-/// message. Use this whenever the message is "any use of this value will cause an error" instead of
-/// "it is undefined behavior to use this value".
+/// message.
#[repr(transparent)]
struct W<T>(T);
@@ -40,12 +39,10 @@ const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::
//~^ ERROR it is undefined behavior to use this value
// bad str
const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// bad str in user-defined unsized type
const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
//~^ ERROR it is undefined behavior to use this value
@@ -74,34 +71,29 @@ const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::
//~^ ERROR it is undefined behavior to use this value
// bad slice: length not an int
const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// bad slice box: length too big
const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR it is undefined behavior to use this value
// bad slice box: length not an int
const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
// bad data *inside* the slice
const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
//~^ ERROR it is undefined behavior to use this value
-//~| ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted
+//~| ERROR evaluation of constant value failed
// good MySliceBool
const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]);
// bad: sized field is not okay
const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
//~^ ERROR it is undefined behavior to use this value
-//~| ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted
+//~| ERROR evaluation of constant value failed
// bad: unsized part is not okay
const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
//~^ ERROR it is undefined behavior to use this value
-//~| ERROR any use of this value will cause an error
-//~| WARNING this was previously accepted
+//~| ERROR evaluation of constant value failed
// # raw slice
const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok
diff --git a/src/test/ui/consts/const-eval/union-ub.32bit.stderr b/src/test/ui/consts/const-eval/union-ub.32bit.stderr
index 38ded4d65..e5c8f88be 100644
--- a/src/test/ui/consts/const-eval/union-ub.32bit.stderr
+++ b/src/test/ui/consts/const-eval/union-ub.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/union-ub.rs:33:1
+ --> $DIR/union-ub.rs:32:1
|
LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean
@@ -10,7 +10,7 @@ LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
}
error[E0080]: evaluation of constant value failed
- --> $DIR/union-ub.rs:35:36
+ --> $DIR/union-ub.rs:34:36
|
LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
diff --git a/src/test/ui/consts/const-eval/union-ub.64bit.stderr b/src/test/ui/consts/const-eval/union-ub.64bit.stderr
index 38ded4d65..e5c8f88be 100644
--- a/src/test/ui/consts/const-eval/union-ub.64bit.stderr
+++ b/src/test/ui/consts/const-eval/union-ub.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/union-ub.rs:33:1
+ --> $DIR/union-ub.rs:32:1
|
LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x2a, but expected a boolean
@@ -10,7 +10,7 @@ LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool};
}
error[E0080]: evaluation of constant value failed
- --> $DIR/union-ub.rs:35:36
+ --> $DIR/union-ub.rs:34:36
|
LL | const UNINIT_BOOL: bool = unsafe { DummyUnion { unit: () }.bool};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
diff --git a/src/test/ui/consts/const-eval/union-ub.rs b/src/test/ui/consts/const-eval/union-ub.rs
index bb29edcf8..043870c9c 100644
--- a/src/test/ui/consts/const-eval/union-ub.rs
+++ b/src/test/ui/consts/const-eval/union-ub.rs
@@ -1,5 +1,4 @@
// stderr-per-bitwidth
-#![allow(const_err)] // make sure we cannot allow away the errors tested here
#[repr(C)]
union DummyUnion {
diff --git a/src/test/ui/consts/const-eval/union_promotion.rs b/src/test/ui/consts/const-eval/union_promotion.rs
index 7167f88a1..18894c45f 100644
--- a/src/test/ui/consts/const-eval/union_promotion.rs
+++ b/src/test/ui/consts/const-eval/union_promotion.rs
@@ -1,5 +1,3 @@
-#![allow(const_err)]
-
#[repr(C)]
union Foo {
a: &'static u32,
diff --git a/src/test/ui/consts/const-eval/union_promotion.stderr b/src/test/ui/consts/const-eval/union_promotion.stderr
index ed186e3eb..70808c520 100644
--- a/src/test/ui/consts/const-eval/union_promotion.stderr
+++ b/src/test/ui/consts/const-eval/union_promotion.stderr
@@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
- --> $DIR/union_promotion.rs:10:29
+ --> $DIR/union_promotion.rs:8:29
|
LL | let x: &'static bool = &unsafe {
| ____________-------------____^
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.rs b/src/test/ui/consts/const-eval/unused-broken-const.rs
index 3b4523681..0d2776bc2 100644
--- a/src/test/ui/consts/const-eval/unused-broken-const.rs
+++ b/src/test/ui/consts/const-eval/unused-broken-const.rs
@@ -3,7 +3,6 @@
// compile-flags: --emit=dep-info,metadata
const FOO: i32 = [][0];
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR evaluation of constant value failed
fn main() {}
diff --git a/src/test/ui/consts/const-eval/unused-broken-const.stderr b/src/test/ui/consts/const-eval/unused-broken-const.stderr
index df5bd524f..fbb10feb7 100644
--- a/src/test/ui/consts/const-eval/unused-broken-const.stderr
+++ b/src/test/ui/consts/const-eval/unused-broken-const.stderr
@@ -1,23 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/unused-broken-const.rs:5:18
|
LL | const FOO: i32 = [][0];
- | -------------- ^^^^^ index out of bounds: the length is 0 but the index is 0
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^ index out of bounds: the length is 0 but the index is 0
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/unused-broken-const.rs:5:18
- |
-LL | const FOO: i32 = [][0];
- | -------------- ^^^^^ index out of bounds: the length is 0 but the index is 0
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-eval/valid-const.rs b/src/test/ui/consts/const-eval/valid-const.rs
index 9e4707182..5f47d1c4f 100644
--- a/src/test/ui/consts/const-eval/valid-const.rs
+++ b/src/test/ui/consts/const-eval/valid-const.rs
@@ -1,7 +1,6 @@
// check-pass
// Some constants that *are* valid
-#![deny(const_err)]
use std::mem;
use std::ptr::NonNull;
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index bdaeb4a0f..63639729a 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -7,8 +7,8 @@ LL | unsafe { std::mem::transmute(()) }
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
- = note: `#[warn(invalid_value)]` on by default
= note: the `!` type has no valid value
+ = note: `#[warn(invalid_value)]` on by default
error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:4:14
@@ -20,10 +20,10 @@ LL | unsafe { std::mem::transmute(()) }
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
...
LL | const FOO: [empty::Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:23:1
+ --> $DIR/validate_uninhabited_zsts.rs:21:1
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void
@@ -32,7 +32,7 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
= note: the raw bytes of the constant (size: 0, align: 1) {}
warning: the type `empty::Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:23:42
+ --> $DIR/validate_uninhabited_zsts.rs:21:42
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,11 +40,11 @@ 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
|
-note: enums with no variants have no valid value (in this struct field)
- --> $DIR/validate_uninhabited_zsts.rs:16:22
+note: enums with no inhabited variants have no valid value
+ --> $DIR/validate_uninhabited_zsts.rs:13:5
|
-LL | pub struct Empty(Void);
- | ^^^^
+LL | enum Void {}
+ | ^^^^^^^^^
error: aborting due to 2 previous errors; 2 warnings emitted
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index bdaeb4a0f..63639729a 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -7,8 +7,8 @@ LL | unsafe { std::mem::transmute(()) }
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
- = note: `#[warn(invalid_value)]` on by default
= note: the `!` type has no valid value
+ = note: `#[warn(invalid_value)]` on by default
error[E0080]: evaluation of constant value failed
--> $DIR/validate_uninhabited_zsts.rs:4:14
@@ -20,10 +20,10 @@ LL | unsafe { std::mem::transmute(()) }
| inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
...
LL | const FOO: [empty::Empty; 3] = [foo(); 3];
- | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:20:33
+ | ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
error[E0080]: it is undefined behavior to use this value
- --> $DIR/validate_uninhabited_zsts.rs:23:1
+ --> $DIR/validate_uninhabited_zsts.rs:21:1
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0].0: encountered a value of uninhabited type empty::Void
@@ -32,7 +32,7 @@ LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
= note: the raw bytes of the constant (size: 0, align: 1) {}
warning: the type `empty::Empty` does not permit zero-initialization
- --> $DIR/validate_uninhabited_zsts.rs:23:42
+ --> $DIR/validate_uninhabited_zsts.rs:21:42
|
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,11 +40,11 @@ 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
|
-note: enums with no variants have no valid value (in this struct field)
- --> $DIR/validate_uninhabited_zsts.rs:16:22
+note: enums with no inhabited variants have no valid value
+ --> $DIR/validate_uninhabited_zsts.rs:13:5
|
-LL | pub struct Empty(Void);
- | ^^^^
+LL | enum Void {}
+ | ^^^^^^^^^
error: aborting due to 2 previous errors; 2 warnings emitted
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
index 96f331275..c0b326215 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.rs
@@ -16,10 +16,8 @@ pub mod empty {
pub struct Empty(Void);
}
-#[warn(const_err)]
const FOO: [empty::Empty; 3] = [foo(); 3];
-#[warn(const_err)]
const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
//~^ ERROR it is undefined behavior to use this value
//~| WARN the type `empty::Empty` does not permit zero-initialization
diff --git a/src/test/ui/consts/const-external-macro-const-err.rs b/src/test/ui/consts/const-external-macro-const-err.rs
index 440c42e32..5bd84330b 100644
--- a/src/test/ui/consts/const-external-macro-const-err.rs
+++ b/src/test/ui/consts/const-external-macro-const-err.rs
@@ -9,6 +9,5 @@ extern crate external_macro;
use external_macro::static_assert;
fn main() {
- static_assert!(2 + 2 == 5); //~ ERROR
- //~| WARN this was previously accepted by the compiler but is being phased out
+ static_assert!(2 + 2 == 5); //~ ERROR constant
}
diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr
index 205ee92df..81f6c09ff 100644
--- a/src/test/ui/consts/const-external-macro-const-err.stderr
+++ b/src/test/ui/consts/const-external-macro-const-err.stderr
@@ -1,25 +1,11 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-external-macro-const-err.rs:12:5
|
LL | static_assert!(2 + 2 == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in the macro `static_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-external-macro-const-err.rs:12:5
- |
-LL | static_assert!(2 + 2 == 5);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 1 but the index is 1
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `static_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.rs b/src/test/ui/consts/const-float-bits-reject-conv.rs
index b156ded4a..5bf54fdbb 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.rs
+++ b/src/test/ui/consts/const-float-bits-reject-conv.rs
@@ -28,22 +28,18 @@ fn f32() {
const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
// LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern.
// In practice, this seems to only cause a problem on x86, since the most widely used calling
// convention mandates that floating point values are returned on the x87 FPU stack. See #73328.
if !cfg!(target_arch = "x86") {
const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
}
}
@@ -55,20 +51,16 @@ fn f64() {
const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
// See comment above.
if !cfg!(target_arch = "x86") {
const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- //~^ ERROR any use of this value will cause an error
- //~| WARNING this was previously accepted
+ //~^ ERROR evaluation of constant value failed
}
}
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr
index 01f2f4895..b3575f641 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.stderr
+++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr
@@ -36,54 +36,29 @@ LL | const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-float-bits-reject-conv.rs:30:34
|
-LL | const _: () = assert!($a);
- | -----------
-...
LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
| ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:33:34
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:32:34
|
-LL | const _: () = assert!($a);
- | -----------
-...
LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:41:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:39:38
|
-LL | const _: () = assert!($a == $b);
- | -----------
-...
LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:44:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:41:38
|
-LL | const _: () = assert!($a == $b);
- | -----------
-...
LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/num/f64.rs:LL:COL
@@ -97,10 +72,10 @@ LL | panic!("const-eval error: cannot use f64::to_bits on a
LL | unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
| -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:54:30
+ ::: $DIR/const-float-bits-reject-conv.rs:50:30
|
LL | const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
- | ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:54:30
+ | ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:50:30
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -116,173 +91,37 @@ LL | panic!("const-eval error: cannot use f64::to_bits on a
LL | unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
| -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
|
- ::: $DIR/const-float-bits-reject-conv.rs:55:30
+ ::: $DIR/const-float-bits-reject-conv.rs:51:30
|
LL | const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
- | ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:55:30
+ | ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:51:30
|
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:57:34
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:53:34
|
-LL | const _: () = assert!($a);
- | -----------
-...
LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:60:34
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:55:34
|
-LL | const _: () = assert!($a);
- | -----------
-...
LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:66:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:60:38
|
-LL | const _: () = assert!($a == $b);
- | -----------
-...
LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:69:38
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-float-bits-reject-conv.rs:62:38
|
-LL | const _: () = assert!($a == $b);
- | -----------
-...
LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
| ^^^^^^^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:30:34
- |
-LL | const _: () = assert!($a);
- | -----------
-...
-LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:33:34
- |
-LL | const _: () = assert!($a);
- | -----------
-...
-LL | const_assert!(f32::from_bits(MASKED_NAN1).is_nan());
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:41:38
- |
-LL | const _: () = assert!($a == $b);
- | -----------
-...
-LL | const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:44:38
- |
-LL | const _: () = assert!($a == $b);
- | -----------
-...
-LL | const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:57:34
- |
-LL | const _: () = assert!($a);
- | -----------
-...
-LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:60:34
- |
-LL | const _: () = assert!($a);
- | -----------
-...
-LL | const_assert!(f64::from_bits(MASKED_NAN1).is_nan());
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:66:38
- |
-LL | const _: () = assert!($a == $b);
- | -----------
-...
-LL | const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1);
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-float-bits-reject-conv.rs:69:38
- |
-LL | const _: () = assert!($a == $b);
- | -----------
-...
-LL | const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2);
- | ^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-fn-error.rs b/src/test/ui/consts/const-fn-error.rs
index abe68c17a..50b7ce1f8 100644
--- a/src/test/ui/consts/const-fn-error.rs
+++ b/src/test/ui/consts/const-fn-error.rs
@@ -3,10 +3,10 @@ const X : usize = 2;
const fn f(x: usize) -> usize {
let mut sum = 0;
for i in 0..x {
- //~^ ERROR mutable references
- //~| ERROR cannot convert
- //~| ERROR cannot call non-const fn
+ //~^ ERROR cannot convert
//~| ERROR `for` is not allowed in a `const fn`
+ //~| ERROR mutable references are not allowed in constant functions
+ //~| ERROR cannot call non-const fn
sum += i;
}
sum
diff --git a/src/test/ui/consts/const-fn-error.stderr b/src/test/ui/consts/const-fn-error.stderr
index e36324f0b..02960b363 100644
--- a/src/test/ui/consts/const-fn-error.stderr
+++ b/src/test/ui/consts/const-fn-error.stderr
@@ -22,8 +22,8 @@ LL | for i in 0..x {
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
-LL | impl<I: ~const Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constant functions
diff --git a/src/test/ui/consts/const-for.rs b/src/test/ui/consts/const-for.rs
index 58bcb5f74..8db248535 100644
--- a/src/test/ui/consts/const-for.rs
+++ b/src/test/ui/consts/const-for.rs
@@ -3,8 +3,8 @@
const _: () = {
for _ in 0..5 {}
- //~^ error: cannot convert
- //~| error: cannot call non-const fn
+ //~^ error: cannot call
+ //~| error: cannot convert
};
fn main() {}
diff --git a/src/test/ui/consts/const-for.stderr b/src/test/ui/consts/const-for.stderr
index f2e1c8a49..11e4ae309 100644
--- a/src/test/ui/consts/const-for.stderr
+++ b/src/test/ui/consts/const-for.stderr
@@ -7,8 +7,8 @@ LL | for _ in 0..5 {}
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
-LL | impl<I: ~const Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants
diff --git a/src/test/ui/consts/const-int-arithmetic-overflow.rs b/src/test/ui/consts/const-int-arithmetic-overflow.rs
index 99bbeaafd..6446e9451 100644
--- a/src/test/ui/consts/const-int-arithmetic-overflow.rs
+++ b/src/test/ui/consts/const-int-arithmetic-overflow.rs
@@ -1,6 +1,5 @@
// run-pass
// compile-flags: -O
-#![allow(const_err)]
// Make sure arithmetic unary/binary ops actually return the right result, even when overflowing.
// We have to put them in `const fn` and turn on optimizations to avoid overflow checks.
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.rs b/src/test/ui/consts/const-len-underflow-separate-spans.rs
index 7c3d1f320..478761aef 100644
--- a/src/test/ui/consts/const-len-underflow-separate-spans.rs
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.rs
@@ -5,8 +5,7 @@
const ONE: usize = 1;
const TWO: usize = 2;
const LEN: usize = ONE - TWO;
-//~^ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~^ ERROR constant
fn main() {
let a: [i8; LEN] = unimplemented!();
diff --git a/src/test/ui/consts/const-len-underflow-separate-spans.stderr b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
index d1bf4b92e..1416e695e 100644
--- a/src/test/ui/consts/const-len-underflow-separate-spans.stderr
+++ b/src/test/ui/consts/const-len-underflow-separate-spans.stderr
@@ -1,15 +1,11 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-len-underflow-separate-spans.rs:7:20
|
LL | const LEN: usize = ONE - TWO;
- | ---------------- ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
error[E0080]: evaluation of constant value failed
- --> $DIR/const-len-underflow-separate-spans.rs:12:17
+ --> $DIR/const-len-underflow-separate-spans.rs:11:17
|
LL | let a: [i8; LEN] = unimplemented!();
| ^^^ referenced constant has errors
@@ -17,14 +13,3 @@ LL | let a: [i8; LEN] = unimplemented!();
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-len-underflow-separate-spans.rs:7:20
- |
-LL | const LEN: usize = ONE - TWO;
- | ---------------- ^^^^^^^^^ attempt to compute `1_usize - 2_usize`, which would overflow
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/const-negation.rs b/src/test/ui/consts/const-negation.rs
index 26c3c0b83..18bcdfb01 100644
--- a/src/test/ui/consts/const-negation.rs
+++ b/src/test/ui/consts/const-negation.rs
@@ -1,8 +1,6 @@
// run-pass
#![allow(overflowing_literals)]
-#[deny(const_err)]
-
fn main() {
#[cfg(target_pointer_width = "32")]
const I: isize = -2147483648isize;
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.rs b/src/test/ui/consts/const-prop-read-static-in-const.rs
index a65b707f0..214262059 100644
--- a/src/test/ui/consts/const-prop-read-static-in-const.rs
+++ b/src/test/ui/consts/const-prop-read-static-in-const.rs
@@ -2,8 +2,7 @@
#![allow(dead_code)]
-const TEST: u8 = MY_STATIC; //~ ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+const TEST: u8 = MY_STATIC; //~ ERROR constant
static MY_STATIC: u8 = 4;
diff --git a/src/test/ui/consts/const-prop-read-static-in-const.stderr b/src/test/ui/consts/const-prop-read-static-in-const.stderr
index ea5ad24b0..793da6285 100644
--- a/src/test/ui/consts/const-prop-read-static-in-const.stderr
+++ b/src/test/ui/consts/const-prop-read-static-in-const.stderr
@@ -1,12 +1,8 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-prop-read-static-in-const.rs:5:18
|
LL | const TEST: u8 = MY_STATIC;
- | -------------- ^^^^^^^^^ constant accesses static
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^ constant accesses static
warning: skipping const checks
|
@@ -18,14 +14,4 @@ LL | const TEST: u8 = MY_STATIC;
error: aborting due to previous error; 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-prop-read-static-in-const.rs:5:18
- |
-LL | const TEST: u8 = MY_STATIC;
- | -------------- ^^^^^^^^^ constant accesses static
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
index 665371777..4df3a793b 100644
--- a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.rs
@@ -8,9 +8,7 @@ extern "C" {
type Opaque;
}
-const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR
-//~| WARN this was previously accepted by the compiler but is being phased out
-const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR
-//~| WARN this was previously accepted by the compiler but is being phased out
+const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR constant
+const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) }; //~ ERROR constant
fn main() {}
diff --git a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
index d19a89378..ad2de0f4d 100644
--- a/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
+++ b/src/test/ui/consts/const-size_of_val-align_of_val-extern-type.stderr
@@ -1,43 +1,15 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
|
LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
- | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
-error: any use of this value will cause an error
- --> $DIR/const-size_of_val-align_of_val-extern-type.rs:13:32
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-size_of_val-align_of_val-extern-type.rs:12:32
|
LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
error: aborting due to 2 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-size_of_val-align_of_val-extern-type.rs:11:31
- |
-LL | const _SIZE: usize = unsafe { size_of_val(&4 as *const i32 as *const Opaque) };
- | ------------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-size_of_val-align_of_val-extern-type.rs:13:32
- |
-LL | const _ALIGN: usize = unsafe { min_align_of_val(&4 as *const i32 as *const Opaque) };
- | ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `extern type` does not have known layout
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-slice-oob.rs b/src/test/ui/consts/const-slice-oob.rs
index 35e5a4d22..429b97821 100644
--- a/src/test/ui/consts/const-slice-oob.rs
+++ b/src/test/ui/consts/const-slice-oob.rs
@@ -1,10 +1,7 @@
-#[deny(const_err)]
-
const FOO: &'static[u32] = &[1, 2, 3];
const BAR: u32 = FOO[5];
//~^ index out of bounds: the length is 3 but the index is 5
-//~| ERROR any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler but is being phased out
+//~| ERROR evaluation of constant value failed
fn main() {
let _ = BAR;
diff --git a/src/test/ui/consts/const-slice-oob.stderr b/src/test/ui/consts/const-slice-oob.stderr
index 27c21e7af..746883a79 100644
--- a/src/test/ui/consts/const-slice-oob.stderr
+++ b/src/test/ui/consts/const-slice-oob.stderr
@@ -1,23 +1,9 @@
-error: any use of this value will cause an error
- --> $DIR/const-slice-oob.rs:4:18
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const-slice-oob.rs:2:18
|
LL | const BAR: u32 = FOO[5];
- | -------------- ^^^^^^ index out of bounds: the length is 3 but the index is 5
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ^^^^^^ index out of bounds: the length is 3 but the index is 5
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const-slice-oob.rs:4:18
- |
-LL | const BAR: u32 = FOO[5];
- | -------------- ^^^^^^ index out of bounds: the length is 3 but the index is 5
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs
index f623c5101..79e68590e 100644
--- a/src/test/ui/consts/const_discriminant.rs
+++ b/src/test/ui/consts/const_discriminant.rs
@@ -1,6 +1,5 @@
// run-pass
#![feature(const_discriminant)]
-#![feature(bench_black_box)]
#![allow(dead_code)]
use std::mem::{discriminant, Discriminant};
diff --git a/src/test/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/src/test/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr
index e51d6f916..223482722 100644
--- a/src/test/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr
+++ b/src/test/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr
@@ -4,9 +4,9 @@ warning: to use a constant of type `CustomEq` in a pattern, the constant's initi
LL | BAR_BAZ => panic!(),
| ^^^^^^^
|
- = note: `#[warn(nontrivial_structural_match)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
+ = note: `#[warn(nontrivial_structural_match)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/consts/const_in_pattern/incomplete-slice.stderr b/src/test/ui/consts/const_in_pattern/incomplete-slice.stderr
index 0ff708371..ddc576ced 100644
--- a/src/test/ui/consts/const_in_pattern/incomplete-slice.stderr
+++ b/src/test/ui/consts/const_in_pattern/incomplete-slice.stderr
@@ -4,9 +4,9 @@ warning: to use a constant of type `E` in a pattern, `E` must be annotated with
LL | E_SL => {}
| ^^^^
|
- = note: `#[warn(indirect_structural_match)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: `#[warn(indirect_structural_match)]` on by default
error[E0004]: non-exhaustive patterns: `&_` not covered
--> $DIR/incomplete-slice.rs:9:11
diff --git a/src/test/ui/consts/const_in_pattern/issue-44333.stderr b/src/test/ui/consts/const_in_pattern/issue-44333.stderr
index 8302b09e5..731ef509c 100644
--- a/src/test/ui/consts/const_in_pattern/issue-44333.stderr
+++ b/src/test/ui/consts/const_in_pattern/issue-44333.stderr
@@ -4,13 +4,13 @@ warning: function pointers and unsized pointers in patterns behave unpredictably
LL | FOO => println!("foo"),
| ^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
note: the lint level is defined here
--> $DIR/issue-44333.rs:3:9
|
LL | #![warn(pointer_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
warning: function pointers and unsized pointers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
--> $DIR/issue-44333.rs:21:9
diff --git a/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr b/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
index 56405a55d..660198349 100644
--- a/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
+++ b/src/test/ui/consts/const_in_pattern/reject_non_structural.stderr
@@ -64,13 +64,13 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
LL | match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
| ^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/reject_non_structural.rs:12:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
error: aborting due to 10 previous errors; 1 warning emitted
diff --git a/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr b/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
index a24c8d181..e957a43a1 100644
--- a/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
+++ b/src/test/ui/consts/const_in_pattern/warn_corner_cases.stderr
@@ -4,9 +4,9 @@ warning: to use a constant of type `NoDerive` in a pattern, the constant's initi
LL | match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
| ^^^^^
|
- = note: `#[warn(nontrivial_structural_match)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
+ = note: `#[warn(nontrivial_structural_match)]` on by default
warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/warn_corner_cases.rs:32:47
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs
index 773640b72..3ce038c1d 100644
--- a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs
+++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs
@@ -4,8 +4,7 @@
const X: usize = {
let mut x = 0;
while x != 1000 {
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler but is being phased out
+ //~^ ERROR evaluation of constant value failed
x += 1;
}
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
index e450f4aa3..850aebdfb 100644
--- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
@@ -1,29 +1,9 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/const_eval_limit_reached.rs:6:11
|
-LL | const X: usize = {
- | --------------
-LL | let mut x = 0;
LL | while x != 1000 {
| ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to previous error
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/const_eval_limit_reached.rs:6:11
- |
-LL | const X: usize = {
- | --------------
-LL | let mut x = 0;
-LL | while x != 1000 {
- | ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
index ec6ce1f5d..f6de3699f 100644
--- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -1,11 +1,11 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/hint.rs:LL:COL
|
-LL | unsafe { intrinsics::unreachable() }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | entering unreachable code
- | inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
+LL | intrinsics::unreachable()
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | entering unreachable code
+ | inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
|
::: $DIR/const_unsafe_unreachable_ub.rs:6:18
|
diff --git a/src/test/ui/consts/constifconst-call-in-const-position.rs b/src/test/ui/consts/constifconst-call-in-const-position.rs
new file mode 100644
index 000000000..fcf01d5bc
--- /dev/null
+++ b/src/test/ui/consts/constifconst-call-in-const-position.rs
@@ -0,0 +1,22 @@
+// known-bug: #102498
+
+#![feature(const_trait_impl, generic_const_exprs)]
+
+#[const_trait]
+pub trait Tr {
+ fn a() -> usize;
+}
+
+impl Tr for () {
+ fn a() -> usize {
+ 1
+ }
+}
+
+const fn foo<T: ~const Tr>() -> [u8; T::a()] {
+ [0; T::a()]
+}
+
+fn main() {
+ foo::<()>();
+}
diff --git a/src/test/ui/consts/constifconst-call-in-const-position.stderr b/src/test/ui/consts/constifconst-call-in-const-position.stderr
new file mode 100644
index 000000000..d4a445120
--- /dev/null
+++ b/src/test/ui/consts/constifconst-call-in-const-position.stderr
@@ -0,0 +1,18 @@
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+ --> $DIR/constifconst-call-in-const-position.rs:3:30
+ |
+LL | #![feature(const_trait_impl, generic_const_exprs)]
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
+
+error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
+ --> $DIR/constifconst-call-in-const-position.rs:16:38
+ |
+LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
+ | ^^^^^^ calling non-const function `<() as Tr>::a`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/control-flow/drop-fail.precise.stderr b/src/test/ui/consts/control-flow/drop-fail.precise.stderr
index 0b0b2443a..93b5f257e 100644
--- a/src/test/ui/consts/control-flow/drop-fail.precise.stderr
+++ b/src/test/ui/consts/control-flow/drop-fail.precise.stderr
@@ -1,14 +1,14 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:8:9
|
LL | let x = Some(Vec::new());
- | ^ constants cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:39:9
|
LL | let mut tmp = None;
- | ^^^^^^^ constants cannot evaluate destructors
+ | ^^^^^^^ the destructor for this type cannot be evaluated in constants
error: aborting due to 2 previous errors
diff --git a/src/test/ui/consts/control-flow/drop-fail.rs b/src/test/ui/consts/control-flow/drop-fail.rs
index efa5a11c9..41341f312 100644
--- a/src/test/ui/consts/control-flow/drop-fail.rs
+++ b/src/test/ui/consts/control-flow/drop-fail.rs
@@ -6,7 +6,7 @@
const _: Option<Vec<i32>> = {
let y: Option<Vec<i32>> = None;
let x = Some(Vec::new());
- //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
+ //[stock,precise]~^ ERROR destructor of
if true {
x
@@ -19,7 +19,7 @@ const _: Option<Vec<i32>> = {
// existing analysis.
const _: Vec<i32> = {
let vec_tuple = (Vec::new(),);
- //[stock]~^ ERROR destructors cannot be evaluated at compile-time
+ //[stock]~^ ERROR destructor of
vec_tuple.0
};
@@ -27,7 +27,7 @@ const _: Vec<i32> = {
// This applies to single-field enum variants as well.
const _: Vec<i32> = {
let x: Result<_, Vec<i32>> = Ok(Vec::new());
- //[stock]~^ ERROR destructors cannot be evaluated at compile-time
+ //[stock]~^ ERROR destructor of
match x {
Ok(x) | Err(x) => x,
@@ -37,7 +37,7 @@ const _: Vec<i32> = {
const _: Option<Vec<i32>> = {
let mut some = Some(Vec::new());
let mut tmp = None;
- //[stock,precise]~^ ERROR destructors cannot be evaluated at compile-time
+ //[stock,precise]~^ ERROR destructor of
let mut i = 0;
while i < 10 {
diff --git a/src/test/ui/consts/control-flow/drop-fail.stock.stderr b/src/test/ui/consts/control-flow/drop-fail.stock.stderr
index 72ca4fa08..2cc856802 100644
--- a/src/test/ui/consts/control-flow/drop-fail.stock.stderr
+++ b/src/test/ui/consts/control-flow/drop-fail.stock.stderr
@@ -1,35 +1,35 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:8:9
|
LL | let x = Some(Vec::new());
- | ^ constants cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constants
...
LL | };
| - value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(Vec<i32>,)` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:21:9
|
LL | let vec_tuple = (Vec::new(),);
- | ^^^^^^^^^ constants cannot evaluate destructors
+ | ^^^^^^^^^ the destructor for this type cannot be evaluated in constants
...
LL | };
| - value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Result<Vec<i32>, Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:29:9
|
LL | let x: Result<_, Vec<i32>> = Ok(Vec::new());
- | ^ constants cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constants
...
LL | };
| - value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<Vec<i32>>` cannot be evaluated at compile-time
--> $DIR/drop-fail.rs:39:9
|
LL | let mut tmp = None;
- | ^^^^^^^ constants cannot evaluate destructors
+ | ^^^^^^^ the destructor for this type cannot be evaluated in constants
...
LL | };
| - value is dropped here
diff --git a/src/test/ui/consts/control-flow/issue-50577.stderr b/src/test/ui/consts/control-flow/issue-50577.stderr
index b6e73f889..a931c89f4 100644
--- a/src/test/ui/consts/control-flow/issue-50577.stderr
+++ b/src/test/ui/consts/control-flow/issue-50577.stderr
@@ -2,7 +2,7 @@ error[E0317]: `if` may be missing an `else` clause
--> $DIR/issue-50577.rs:3:16
|
LL | Drop = assert_eq!(1, 1),
- | ^^^^^^^^^^^^^^^^ expected `()`, found `isize`
+ | ^^^^^^^^^^^^^^^^ expected `isize`, found `()`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs
index 95acacdb7..d591bfc73 100644
--- a/src/test/ui/consts/dangling-alloc-id-ice.rs
+++ b/src/test/ui/consts/dangling-alloc-id-ice.rs
@@ -1,5 +1,4 @@
// https://github.com/rust-lang/rust/issues/55223
-#![allow(const_err)]
union Foo<'a> {
y: &'a (),
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr
index 8410034c0..0a1cca4ca 100644
--- a/src/test/ui/consts/dangling-alloc-id-ice.stderr
+++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr
@@ -1,5 +1,5 @@
error: encountered dangling pointer in final constant
- --> $DIR/dangling-alloc-id-ice.rs:9:1
+ --> $DIR/dangling-alloc-id-ice.rs:8:1
|
LL | const FOO: &() = {
| ^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/drop_box.rs b/src/test/ui/consts/drop_box.rs
index 58a373a96..679974130 100644
--- a/src/test/ui/consts/drop_box.rs
+++ b/src/test/ui/consts/drop_box.rs
@@ -1,4 +1,4 @@
const fn f<T>(_: Box<T>) {}
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
fn main() {}
diff --git a/src/test/ui/consts/drop_box.stderr b/src/test/ui/consts/drop_box.stderr
index b9d6581e8..62324939b 100644
--- a/src/test/ui/consts/drop_box.stderr
+++ b/src/test/ui/consts/drop_box.stderr
@@ -1,10 +1,10 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Box<T>` cannot be evaluated at compile-time
--> $DIR/drop_box.rs:1:15
|
LL | const fn f<T>(_: Box<T>) {}
| ^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
error: aborting due to previous error
diff --git a/src/test/ui/consts/drop_zst.stderr b/src/test/ui/consts/drop_zst.stderr
index d4be5aa56..37758a4cb 100644
--- a/src/test/ui/consts/drop_zst.stderr
+++ b/src/test/ui/consts/drop_zst.stderr
@@ -1,8 +1,8 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `S` cannot be evaluated at compile-time
--> $DIR/drop_zst.rs:14:9
|
LL | let s = S;
- | ^ constant functions cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constant functions
error: aborting due to previous error
diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
index 86fbadb94..159cdf257 100644
--- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
+++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.rs
@@ -13,15 +13,13 @@ const INVALID_BOOL: () = unsafe {
const INVALID_PTR_IN_INT: () = unsafe {
let _x: usize = transmute(&3u8);
- //[with_flag]~^ ERROR: any use of this value will cause an error
- //[with_flag]~| previously accepted
+ //[with_flag]~^ ERROR: evaluation of constant value failed
};
const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe {
let x: &[u8] = &[0; 32];
let _x: (usize, usize) = transmute(x);
- //[with_flag]~^ ERROR: any use of this value will cause an error
- //[with_flag]~| previously accepted
+ //[with_flag]~^ ERROR: evaluation of constant value failed
};
const UNALIGNED_PTR: () = unsafe {
@@ -31,8 +29,7 @@ const UNALIGNED_PTR: () = unsafe {
};
const UNALIGNED_READ: () = {
- INNER; //[with_flag]~ERROR any use of this value will cause an error
- //[with_flag]~| previously accepted
+ INNER; //[with_flag]~ERROR evaluation of constant value failed
// There is an error here but its span is in the standard library so we cannot match it...
// so we have this in a *nested* const, such that the *outer* const fails to use it.
const INNER: () = unsafe {
diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 793725d3b..3e1195822 100644
--- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -4,36 +4,26 @@ error[E0080]: evaluation of constant value failed
LL | let _x: bool = transmute(3u8);
| ^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/detect-extra-ub.rs:15:21
|
-LL | const INVALID_PTR_IN_INT: () = unsafe {
- | ----------------------------
LL | let _x: usize = transmute(&3u8);
| ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/detect-extra-ub.rs:22:30
+error[E0080]: evaluation of constant value failed
+ --> $DIR/detect-extra-ub.rs:21:30
|
-LL | const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe {
- | ------------------------------------------
-LL | let x: &[u8] = &[0; 32];
LL | let _x: (usize, usize) = transmute(x);
| ^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error[E0080]: evaluation of constant value failed
- --> $DIR/detect-extra-ub.rs:28:20
+ --> $DIR/detect-extra-ub.rs:26:20
|
LL | let _x: &u32 = transmute(&[0u8; 4]);
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered an unaligned reference (required 4 byte alignment but found 1)
@@ -52,66 +42,17 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
LL | unsafe { read(self) }
| ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- ::: $DIR/detect-extra-ub.rs:41:9
+ ::: $DIR/detect-extra-ub.rs:38:9
|
LL | ptr.read();
- | ---------- inside `INNER` at $DIR/detect-extra-ub.rs:41:9
+ | ---------- inside `INNER` at $DIR/detect-extra-ub.rs:38:9
-error: any use of this value will cause an error
- --> $DIR/detect-extra-ub.rs:34:5
+error[E0080]: evaluation of constant value failed
+ --> $DIR/detect-extra-ub.rs:32:5
|
-LL | const UNALIGNED_READ: () = {
- | ------------------------
LL | INNER;
| ^^^^^ referenced constant has errors
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/detect-extra-ub.rs:15:21
- |
-LL | const INVALID_PTR_IN_INT: () = unsafe {
- | ----------------------------
-LL | let _x: usize = transmute(&3u8);
- | ^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/detect-extra-ub.rs:22:30
- |
-LL | const INVALID_SLICE_TO_USIZE_TRANSMUTE: () = unsafe {
- | ------------------------------------------
-LL | let x: &[u8] = &[0; 32];
-LL | let _x: (usize, usize) = transmute(x);
- | ^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/detect-extra-ub.rs:34:5
- |
-LL | const UNALIGNED_READ: () = {
- | ------------------------
-LL | INNER;
- | ^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr
index ae5f6b2ba..bad07989e 100644
--- a/src/test/ui/consts/invalid-union.32bit.stderr
+++ b/src/test/ui/consts/invalid-union.32bit.stderr
@@ -9,27 +9,12 @@ LL | fn main() {
╾─alloc7──╼ │ ╾──╼
}
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/invalid-union.rs:42:25
- |
-LL | let _: &'static _ = &C;
- | ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr
index d50e74a16..a209f0038 100644
--- a/src/test/ui/consts/invalid-union.64bit.stderr
+++ b/src/test/ui/consts/invalid-union.64bit.stderr
@@ -9,27 +9,12 @@ LL | fn main() {
╾───────alloc7────────╼ │ ╾──────╼
}
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/invalid-union.rs:42:25
|
LL | let _: &'static _ = &C;
| ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/invalid-union.rs:42:25
- |
-LL | let _: &'static _ = &C;
- | ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/invalid-union.rs b/src/test/ui/consts/invalid-union.rs
index efeddf75c..435d26d6e 100644
--- a/src/test/ui/consts/invalid-union.rs
+++ b/src/test/ui/consts/invalid-union.rs
@@ -40,5 +40,4 @@ const C: S = {
fn main() { //~ ERROR it is undefined behavior to use this value
let _: &'static _ = &C; //~ ERROR erroneous constant used
- //~^ WARN this was previously accepted
}
diff --git a/src/test/ui/consts/issue-102117.rs b/src/test/ui/consts/issue-102117.rs
new file mode 100644
index 000000000..b77342c41
--- /dev/null
+++ b/src/test/ui/consts/issue-102117.rs
@@ -0,0 +1,30 @@
+#![feature(inline_const, const_type_id)]
+
+use std::alloc::Layout;
+use std::any::TypeId;
+use std::mem::transmute;
+use std::ptr::drop_in_place;
+
+pub struct VTable {
+ layout: Layout,
+ type_id: TypeId,
+ drop_in_place: unsafe fn(*mut ()),
+}
+
+impl VTable {
+ pub fn new<T>() -> &'static Self {
+ const {
+ //~^ ERROR the parameter type `T` may not live long enough
+ //~| ERROR the parameter type `T` may not live long enough
+ &VTable {
+ layout: Layout::new::<T>(),
+ type_id: TypeId::of::<T>(),
+ drop_in_place: unsafe {
+ transmute::<unsafe fn(*mut T), unsafe fn(*mut ())>(drop_in_place::<T>)
+ },
+ }
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/consts/issue-102117.stderr b/src/test/ui/consts/issue-102117.stderr
new file mode 100644
index 000000000..eb4b329bd
--- /dev/null
+++ b/src/test/ui/consts/issue-102117.stderr
@@ -0,0 +1,37 @@
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/issue-102117.rs:16:9
+ |
+LL | / const {
+LL | |
+LL | |
+LL | | &VTable {
+... |
+LL | | }
+LL | | }
+ | |_________^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | pub fn new<T: 'static>() -> &'static Self {
+ | +++++++++
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/issue-102117.rs:16:9
+ |
+LL | / const {
+LL | |
+LL | |
+LL | | &VTable {
+... |
+LL | | }
+LL | | }
+ | |_________^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | pub fn new<T: 'static>() -> &'static Self {
+ | +++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/consts/issue-104155.rs b/src/test/ui/consts/issue-104155.rs
new file mode 100644
index 000000000..1cc8f81b0
--- /dev/null
+++ b/src/test/ui/consts/issue-104155.rs
@@ -0,0 +1,5 @@
+// check-pass
+const _: () = core::mem::forget(Box::<u32>::default);
+const _: () = core::mem::forget(|| Box::<u32>::default());
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-constants-not-static.rs b/src/test/ui/consts/issue-17718-constants-not-static.rs
index 2e6aff161..2e6aff161 100644
--- a/src/test/ui/issues/issue-17718-constants-not-static.rs
+++ b/src/test/ui/consts/issue-17718-constants-not-static.rs
diff --git a/src/test/ui/issues/issue-17718-constants-not-static.stderr b/src/test/ui/consts/issue-17718-constants-not-static.stderr
index 8f3acae71..8f3acae71 100644
--- a/src/test/ui/issues/issue-17718-constants-not-static.stderr
+++ b/src/test/ui/consts/issue-17718-constants-not-static.stderr
diff --git a/src/test/ui/consts/issue-25826.stderr b/src/test/ui/consts/issue-25826.stderr
index b80befa26..905c5ee6e 100644
--- a/src/test/ui/consts/issue-25826.stderr
+++ b/src/test/ui/consts/issue-25826.stderr
@@ -10,10 +10,6 @@ note: the trait `PartialOrd` is implemented for `*const ()`, but that implementa
|
LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
| ^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | fn main() where *const (): ~const PartialOrd {
- | ++++++++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/consts/issue-46553.rs b/src/test/ui/consts/issue-46553.rs
index 9438df193..abeaf10f2 100644
--- a/src/test/ui/consts/issue-46553.rs
+++ b/src/test/ui/consts/issue-46553.rs
@@ -1,5 +1,4 @@
// run-pass
-#![deny(const_err)]
pub struct Data<T> {
function: fn() -> T,
diff --git a/src/test/ui/consts/issue-56164.rs b/src/test/ui/consts/issue-56164.rs
index 094ca377e..df3e3bf90 100644
--- a/src/test/ui/consts/issue-56164.rs
+++ b/src/test/ui/consts/issue-56164.rs
@@ -1,11 +1,10 @@
const fn foo() { (||{})() }
//~^ ERROR cannot call non-const closure
-//~| ERROR erroneous constant used [const_err]
-//~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+//~| ERROR erroneous constant used
const fn bad(input: fn()) {
input()
- //~^ ERROR function pointer
+ //~^ ERROR function pointer calls are not allowed
}
fn main() {
diff --git a/src/test/ui/consts/issue-56164.stderr b/src/test/ui/consts/issue-56164.stderr
index 73a0f8ec0..c5b2c57fb 100644
--- a/src/test/ui/consts/issue-56164.stderr
+++ b/src/test/ui/consts/issue-56164.stderr
@@ -8,32 +8,18 @@ LL | const fn foo() { (||{})() }
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: function pointer calls are not allowed in constant functions
- --> $DIR/issue-56164.rs:7:5
+ --> $DIR/issue-56164.rs:6:5
|
LL | input()
| ^^^^^^^
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/issue-56164.rs:1:18
|
LL | const fn foo() { (||{})() }
| ^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0015`.
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/issue-56164.rs:1:18
- |
-LL | const fn foo() { (||{})() }
- | ^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+Some errors have detailed explanations: E0015, E0080.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/consts/issue-66693.rs b/src/test/ui/consts/issue-66693.rs
index 99d28eb77..1ff250be1 100644
--- a/src/test/ui/consts/issue-66693.rs
+++ b/src/test/ui/consts/issue-66693.rs
@@ -10,8 +10,7 @@ static _FOO: () = panic!(true);
const fn _foo() {
panic!(&1);
//~^ ERROR: argument to `panic!()` in a const context must have type `&str`
- //~| ERROR: erroneous constant used [const_err]
- //~| WARNING: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ //~| ERROR: erroneous constant used
}
// ensure that conforming panics don't cause an error
diff --git a/src/test/ui/consts/issue-66693.stderr b/src/test/ui/consts/issue-66693.stderr
index 5460cc1ee..911374f50 100644
--- a/src/test/ui/consts/issue-66693.stderr
+++ b/src/test/ui/consts/issue-66693.stderr
@@ -22,26 +22,12 @@ LL | panic!(&1);
|
= 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)
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/issue-66693.rs:11:12
|
LL | panic!(&1);
| ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: aborting due to 4 previous errors
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/issue-66693.rs:11:12
- |
-LL | panic!(&1);
- | ^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/issue-78655.stderr b/src/test/ui/consts/issue-78655.stderr
index f5b1123e7..6b83fa0e5 100644
--- a/src/test/ui/consts/issue-78655.stderr
+++ b/src/test/ui/consts/issue-78655.stderr
@@ -5,6 +5,11 @@ LL | let x;
| - binding declared here but left uninitialized
LL | &x
| ^^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x = 0;
+ | +++
error: could not evaluate constant pattern
--> $DIR/issue-78655.rs:7:9
diff --git a/src/test/ui/consts/issue-88071.rs b/src/test/ui/consts/issue-88071.rs
index 1c38c43e6..f58cdb594 100644
--- a/src/test/ui/consts/issue-88071.rs
+++ b/src/test/ui/consts/issue-88071.rs
@@ -2,8 +2,6 @@
//
// regression test for #88071
-#![feature(const_btree_new)]
-
use std::collections::BTreeMap;
pub struct CustomMap<K, V>(BTreeMap<K, V>);
diff --git a/src/test/ui/consts/issue-94675.rs b/src/test/ui/consts/issue-94675.rs
index 0604aab3b..ce21ebdb9 100644
--- a/src/test/ui/consts/issue-94675.rs
+++ b/src/test/ui/consts/issue-94675.rs
@@ -7,9 +7,8 @@ struct Foo<'a> {
impl<'a> Foo<'a> {
const fn spam(&mut self, baz: &mut Vec<u32>) {
self.bar[0] = baz.len();
- //~^ ERROR cannot call non-const fn `Vec::<u32>::len` in constant functions
- //~| ERROR the trait bound `Vec<usize>: ~const IndexMut<usize>` is not satisfied
- //~| ERROR cannot call non-const operator in constant functions
+ //~^ the trait bound `Vec<usize>: ~const Index<_>` is not satisfied
+ //~| the trait bound `Vec<usize>: ~const IndexMut<usize>` is not satisfied
}
}
diff --git a/src/test/ui/consts/issue-94675.stderr b/src/test/ui/consts/issue-94675.stderr
index 6665e4283..f4683f7f5 100644
--- a/src/test/ui/consts/issue-94675.stderr
+++ b/src/test/ui/consts/issue-94675.stderr
@@ -1,10 +1,15 @@
-error[E0015]: cannot call non-const fn `Vec::<u32>::len` in constant functions
- --> $DIR/issue-94675.rs:9:27
+error[E0277]: the trait bound `Vec<usize>: ~const Index<_>` is not satisfied
+ --> $DIR/issue-94675.rs:9:9
|
LL | self.bar[0] = baz.len();
- | ^^^^^
+ | ^^^^^^^^^^^ vector indices are of type `usize` or ranges of `usize`
+ |
+ = help: the trait `~const Index<_>` is not implemented for `Vec<usize>`
+note: the trait `Index<_>` is implemented for `Vec<usize>`, but that implementation is not `const`
+ --> $DIR/issue-94675.rs:9:9
|
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+LL | self.bar[0] = baz.len();
+ | ^^^^^^^^^^^
error[E0277]: the trait bound `Vec<usize>: ~const IndexMut<usize>` is not satisfied
--> $DIR/issue-94675.rs:9:9
@@ -19,20 +24,6 @@ note: the trait `IndexMut<usize>` is implemented for `Vec<usize>`, but that impl
LL | self.bar[0] = baz.len();
| ^^^^^^^^^^^
-error[E0015]: cannot call non-const operator in constant functions
- --> $DIR/issue-94675.rs:9:9
- |
-LL | self.bar[0] = baz.len();
- | ^^^^^^^^^^^
- |
-note: impl defined here, but it is not `const`
- --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
- |
-LL | impl<T, I: SliceIndex<[T]>, A: Allocator> IndexMut<I> for Vec<T, A> {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr
index 0f0539e09..3872e3d4f 100644
--- a/src/test/ui/consts/issue-miri-1910.stderr
+++ b/src/test/ui/consts/issue-miri-1910.stderr
@@ -1,4 +1,4 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
@@ -6,42 +6,20 @@ LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
| |
| unable to copy parts of a pointer from memory at ALLOC
| inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `C` at $DIR/issue-miri-1910.rs:8:5
|
- ::: $DIR/issue-miri-1910.rs:5:1
+ ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
-LL | const C: () = unsafe {
- | -----------
+LL | unsafe { read(self) }
+ | ---------- inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-error: aborting due to previous error
-
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ ::: $DIR/issue-miri-1910.rs:8:5
|
-LL | copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | unable to copy parts of a pointer from memory at ALLOC
- | inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- | inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
- | inside `C` at $DIR/issue-miri-1910.rs:8:5
- |
- ::: $DIR/issue-miri-1910.rs:5:1
+LL | (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
+ | ------------------------------------------------------------------- inside `C` at $DIR/issue-miri-1910.rs:8:5
|
-LL | const C: () = unsafe {
- | -----------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 0bafaf2e8..c2891488c 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -34,7 +34,7 @@ const fn foo35(a: bool, b: bool) -> bool { a ^ b }
struct Foo<T: ?Sized>(T);
impl<T> Foo<T> {
const fn new(t: T) -> Self { Foo(t) }
- const fn into_inner(self) -> T { self.0 } //~ destructors cannot be evaluated
+ const fn into_inner(self) -> T { self.0 } //~ destructor of
const fn get(&self) -> &T { &self.0 }
const fn get_mut(&mut self) -> &mut T { &mut self.0 }
//~^ mutable references
@@ -43,7 +43,7 @@ impl<T> Foo<T> {
}
impl<'a, T> Foo<T> {
const fn new_lt(t: T) -> Self { Foo(t) }
- const fn into_inner_lt(self) -> T { self.0 } //~ destructors cannot be evaluated
+ const fn into_inner_lt(self) -> T { self.0 } //~ destructor of
const fn get_lt(&'a self) -> &T { &self.0 }
const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
//~^ mutable references
@@ -52,7 +52,7 @@ impl<'a, T> Foo<T> {
}
impl<T: Sized> Foo<T> {
const fn new_s(t: T) -> Self { Foo(t) }
- const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructors
+ const fn into_inner_s(self) -> T { self.0 } //~ ERROR destructor
const fn get_s(&self) -> &T { &self.0 }
const fn get_mut_s(&mut self) -> &mut T { &mut self.0 }
//~^ mutable references
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 4ad17602c..11c79e8e2 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -1,10 +1,10 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:37:25
|
LL | const fn into_inner(self) -> T { self.0 }
| ^^^^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/min_const_fn.rs:39:22
@@ -33,13 +33,13 @@ LL | const fn get_mut(&mut self) -> &mut T { &mut self.0 }
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:46:28
|
LL | const fn into_inner_lt(self) -> T { self.0 }
| ^^^^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/min_const_fn.rs:48:25
@@ -68,13 +68,13 @@ LL | const fn get_mut_lt(&'a mut self) -> &mut T { &mut self.0 }
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Foo<T>` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:55:27
|
LL | const fn into_inner_s(self) -> T { self.0 }
| ^^^^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
error[E0658]: mutable references are not allowed in constant functions
--> $DIR/min_const_fn.rs:57:24
@@ -191,21 +191,21 @@ LL | const fn inc(x: &mut i32) { *x += 1 }
= note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
= help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `AlanTuring<impl std::fmt::Debug>` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:122:19
|
LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
| ^^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `impl std::fmt::Debug` cannot be evaluated at compile-time
--> $DIR/min_const_fn.rs:124:18
|
LL | const fn no_apit(_x: impl std::fmt::Debug) {}
| ^^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
error: aborting due to 24 previous errors
diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.rs b/src/test/ui/consts/miri_unleashed/abi-mismatch.rs
index 3360e9cac..205f7183b 100644
--- a/src/test/ui/consts/miri_unleashed/abi-mismatch.rs
+++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.rs
@@ -2,7 +2,6 @@
// compile-flags: -Z unleash-the-miri-inside-of-you
#![feature(const_extern_fn)]
-#![allow(const_err)]
const extern "C" fn c_fn() {}
diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
index aaba19c2c..840d698eb 100644
--- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
+++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
@@ -1,19 +1,19 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/abi-mismatch.rs:10:5
+ --> $DIR/abi-mismatch.rs:9:5
|
LL | my_fn();
| ^^^^^^^
| |
| calling a function with calling convention C using calling convention Rust
- | inside `call_rust_fn` at $DIR/abi-mismatch.rs:10:5
+ | inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
...
LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
- | --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:16:18
+ | --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:15:18
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/abi-mismatch.rs:10:5
+ --> $DIR/abi-mismatch.rs:9:5
|
LL | my_fn();
| ^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.rs b/src/test/ui/consts/miri_unleashed/assoc_const.rs
index 5f520c2cf..76ed667a5 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.rs
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.rs
@@ -1,8 +1,6 @@
// build-fail
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
-
// a test demonstrating why we do need to run static const qualification on associated constants
// instead of just checking the final constant
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
index 1f82ac827..519bd0748 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -1,22 +1,4 @@
-error[E0080]: erroneous constant used
- --> $DIR/assoc_const.rs:31:13
- |
-LL | let y = <String as Bar<Vec<u32>, String>>::F;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-warning: skipping const checks
- |
-help: skipping check that does not even have a feature gate
- --> $DIR/assoc_const.rs:14:20
- |
-LL | const F: u32 = (U::X, 42).1;
- | ^^^^^^^^^^
-
-error: aborting due to previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
+error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
--> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
@@ -25,18 +7,26 @@ LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
| calling non-const function `<Vec<u32> as Drop>::drop`
| inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
| inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
- | inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:14:31
|
- ::: $DIR/assoc_const.rs:14:5
+ ::: $DIR/assoc_const.rs:12:31
|
LL | const F: u32 = (U::X, 42).1;
- | ------------
+ | - inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:12:31
+
+error[E0080]: erroneous constant used
+ --> $DIR/assoc_const.rs:29:13
|
-note: the lint level is defined here
- --> $DIR/assoc_const.rs:4:10
+LL | let y = <String as Bar<Vec<u32>, String>>::F;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+warning: skipping const checks
|
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+help: skipping check that does not even have a feature gate
+ --> $DIR/assoc_const.rs:12:20
+ |
+LL | const F: u32 = (U::X, 42).1;
+ | ^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.rs b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
index 30dd2a515..8377141ea 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.rs
@@ -1,7 +1,5 @@
// build-fail
-#![allow(const_err)]
-
// a test demonstrating that const qualification cannot prevent monomorphization time errors
trait Foo {
@@ -9,7 +7,7 @@ trait Foo {
}
trait Bar<U: Foo> {
- const F: u32 = 100 / U::X;
+ const F: u32 = 100 / U::X; //~ ERROR evaluation of `<std::string::String as Bar<std::string::String>>::F` failed
}
impl Foo for () {
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
index cbf02199f..2bf753c2b 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const_2.stderr
@@ -1,24 +1,15 @@
+error[E0080]: evaluation of `<std::string::String as Bar<std::string::String>>::F` failed
+ --> $DIR/assoc_const_2.rs:10:20
+ |
+LL | const F: u32 = 100 / U::X;
+ | ^^^^^^^^^^ attempt to divide `100_u32` by zero
+
error[E0080]: erroneous constant used
- --> $DIR/assoc_const_2.rs:29:13
+ --> $DIR/assoc_const_2.rs:27:13
|
LL | let y = <String as Bar<String>>::F;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-error: aborting due to previous error
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/assoc_const_2.rs:12:20
- |
-LL | const F: u32 = 100 / U::X;
- | ------------ ^^^^^^^^^^ attempt to divide `100_u32` by zero
- |
-note: the lint level is defined here
- --> $DIR/assoc_const_2.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/miri_unleashed/box.rs b/src/test/ui/consts/miri_unleashed/box.rs
index 32796c672..c2a260aa1 100644
--- a/src/test/ui/consts/miri_unleashed/box.rs
+++ b/src/test/ui/consts/miri_unleashed/box.rs
@@ -1,6 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(box_syntax)]
-#![allow(const_err)]
use std::mem::ManuallyDrop;
diff --git a/src/test/ui/consts/miri_unleashed/box.stderr b/src/test/ui/consts/miri_unleashed/box.stderr
index 05d9858dc..bc5d4a257 100644
--- a/src/test/ui/consts/miri_unleashed/box.stderr
+++ b/src/test/ui/consts/miri_unleashed/box.stderr
@@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/box.rs:10:11
+ --> $DIR/box.rs:9:11
|
LL | &mut *(box 0)
| ^^^^^^^ calling non-const function `alloc::alloc::exchange_malloc`
@@ -7,22 +7,22 @@ LL | &mut *(box 0)
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/box.rs:10:11
+ --> $DIR/box.rs:9:11
|
LL | &mut *(box 0)
| ^^^^^^^
help: skipping check for `const_mut_refs` feature
- --> $DIR/box.rs:10:16
+ --> $DIR/box.rs:9:16
|
LL | &mut *(box 0)
| ^
help: skipping check for `const_mut_refs` feature
- --> $DIR/box.rs:10:5
+ --> $DIR/box.rs:9:5
|
LL | &mut *(box 0)
| ^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/box.rs:10:5
+ --> $DIR/box.rs:9:5
|
LL | &mut *(box 0)
| ^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr
new file mode 100644
index 000000000..a6f467b9e
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.32bit.stderr
@@ -0,0 +1,81 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add`
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:14:14
+ |
+LL | unsafe { *(&FOO as *const _ as *const usize) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^ constant accesses static
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/const_refers_to_static.rs:20:1
+ |
+LL | const REF_INTERIOR_MUT: &usize = {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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) {
+ ╾─alloc4──╼ │ ╾──╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/const_refers_to_static.rs:27:1
+ |
+LL | const READ_IMMUT: &usize = {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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) {
+ ╾─alloc5──╼ │ ╾──╼
+ }
+
+warning: skipping const checks
+ |
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:14:17
+ |
+LL | unsafe { *(&FOO as *const _ as *const usize) }
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:23:18
+ |
+LL | unsafe { &*(&FOO as *const _ as *const usize) }
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:30:6
+ |
+LL | &FOO
+ | ^^^
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr
new file mode 100644
index 000000000..cfaf31a6e
--- /dev/null
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.64bit.stderr
@@ -0,0 +1,81 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add`
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:14:14
+ |
+LL | unsafe { *(&FOO as *const _ as *const usize) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^ constant accesses static
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/const_refers_to_static.rs:20:1
+ |
+LL | const REF_INTERIOR_MUT: &usize = {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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) {
+ ╾───────alloc4────────╼ │ ╾──────╼
+ }
+
+error[E0080]: it is undefined behavior to use this value
+ --> $DIR/const_refers_to_static.rs:27:1
+ |
+LL | const READ_IMMUT: &usize = {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
+ |
+ = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open 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) {
+ ╾───────alloc5────────╼ │ ╾──────╼
+ }
+
+warning: skipping const checks
+ |
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:9:5
+ |
+LL | FOO.fetch_add(1, Ordering::Relaxed)
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:14:17
+ |
+LL | unsafe { *(&FOO as *const _ as *const usize) }
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:18:32
+ |
+LL | const READ_MUT: u32 = unsafe { MUTABLE };
+ | ^^^^^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:23:18
+ |
+LL | unsafe { &*(&FOO as *const _ as *const usize) }
+ | ^^^
+help: skipping check that does not even have a feature gate
+ --> $DIR/const_refers_to_static.rs:30:6
+ |
+LL | &FOO
+ | ^^^
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
index c9dc1de51..7ed5a48d9 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.rs
@@ -1,31 +1,33 @@
-// build-fail
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
+// stderr-per-bitwidth
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
-// These fail during CTFE (as they read a static), so they only cause an error
-// when *using* the const.
-
const MUTATE_INTERIOR_MUT: usize = {
static FOO: AtomicUsize = AtomicUsize::new(0);
- FOO.fetch_add(1, Ordering::Relaxed)
+ FOO.fetch_add(1, Ordering::Relaxed) //~ERROR evaluation of constant value failed
};
const READ_INTERIOR_MUT: usize = {
static FOO: AtomicUsize = AtomicUsize::new(0);
- unsafe { *(&FOO as *const _ as *const usize) }
+ unsafe { *(&FOO as *const _ as *const usize) } //~ERROR evaluation of constant value failed
};
static mut MUTABLE: u32 = 0;
-const READ_MUT: u32 = unsafe { MUTABLE };
+const READ_MUT: u32 = unsafe { MUTABLE }; //~ERROR evaluation of constant value failed
+
+const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value
+//~| encountered a reference pointing to a static variable
+ static FOO: AtomicUsize = AtomicUsize::new(0);
+ unsafe { &*(&FOO as *const _ as *const usize) }
+};
+
+// ok some day perhaps
+const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value
+//~| encountered a reference pointing to a static variable
+ static FOO: usize = 0;
+ &FOO
+};
-fn main() {
- MUTATE_INTERIOR_MUT;
- //~^ ERROR: erroneous constant used
- READ_INTERIOR_MUT;
- //~^ ERROR: erroneous constant used
- READ_MUT;
- //~^ ERROR: erroneous constant used
-}
+fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
deleted file mode 100644
index fa2088124..000000000
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr
+++ /dev/null
@@ -1,100 +0,0 @@
-error[E0080]: erroneous constant used
- --> $DIR/const_refers_to_static.rs:25:5
- |
-LL | MUTATE_INTERIOR_MUT;
- | ^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-error[E0080]: erroneous constant used
- --> $DIR/const_refers_to_static.rs:27:5
- |
-LL | READ_INTERIOR_MUT;
- | ^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-error[E0080]: erroneous constant used
- --> $DIR/const_refers_to_static.rs:29:5
- |
-LL | READ_MUT;
- | ^^^^^^^^ referenced constant has errors
-
-warning: skipping const checks
- |
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static.rs:13:5
- |
-LL | FOO.fetch_add(1, Ordering::Relaxed)
- | ^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static.rs:13:5
- |
-LL | FOO.fetch_add(1, Ordering::Relaxed)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static.rs:18:17
- |
-LL | unsafe { *(&FOO as *const _ as *const usize) }
- | ^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static.rs:22:32
- |
-LL | const READ_MUT: u32 = unsafe { MUTABLE };
- | ^^^^^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static.rs:22:32
- |
-LL | const READ_MUT: u32 = unsafe { MUTABLE };
- | ^^^^^^^
-
-error: aborting due to 3 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static.rs:13:5
- |
-LL | const MUTATE_INTERIOR_MUT: usize = {
- | --------------------------------
-LL | static FOO: AtomicUsize = AtomicUsize::new(0);
-LL | FOO.fetch_add(1, Ordering::Relaxed)
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `AtomicUsize::fetch_add`
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static.rs:18:14
- |
-LL | const READ_INTERIOR_MUT: usize = {
- | ------------------------------
-LL | static FOO: AtomicUsize = AtomicUsize::new(0);
-LL | unsafe { *(&FOO as *const _ as *const usize) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static.rs:22:32
- |
-LL | const READ_MUT: u32 = unsafe { MUTABLE };
- | ------------------- ^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static.rs:3:10
- |
-LL | #![allow(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr
deleted file mode 100644
index 14173ac9f..000000000
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.32bit.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static2.rs:11:1
- |
-LL | const REF_INTERIOR_MUT: &usize = {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
- |
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 4, align: 4) {
- ╾─alloc1──╼ │ ╾──╼
- }
-
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static2.rs:18:1
- |
-LL | const READ_IMMUT: &usize = {
- | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
- |
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 4, align: 4) {
- ╾─alloc2──╼ │ ╾──╼
- }
-
-warning: skipping const checks
- |
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static2.rs:14:18
- |
-LL | unsafe { &*(&FOO as *const _ as *const usize) }
- | ^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static2.rs:21:6
- |
-LL | &FOO
- | ^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr
deleted file mode 100644
index e7e51a418..000000000
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.64bit.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static2.rs:11:1
- |
-LL | const REF_INTERIOR_MUT: &usize = {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
- |
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 8, align: 8) {
- ╾───────alloc1────────╼ │ ╾──────╼
- }
-
-error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static2.rs:18:1
- |
-LL | const READ_IMMUT: &usize = {
- | ^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
- |
- = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
- = note: the raw bytes of the constant (size: 8, align: 8) {
- ╾───────alloc2────────╼ │ ╾──────╼
- }
-
-warning: skipping const checks
- |
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static2.rs:14:18
- |
-LL | unsafe { &*(&FOO as *const _ as *const usize) }
- | ^^^
-help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static2.rs:21:6
- |
-LL | &FOO
- | ^^^
-
-error: aborting due to 2 previous errors; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs
deleted file mode 100644
index 8b8e262fb..000000000
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static2.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// compile-flags: -Zunleash-the-miri-inside-of-you
-// stderr-per-bitwidth
-#![allow(const_err)]
-
-use std::sync::atomic::AtomicUsize;
-use std::sync::atomic::Ordering;
-
-// These only fail during validation (they do not use but just create a reference to a static),
-// so they cause an immediate error when *defining* the const.
-
-const REF_INTERIOR_MUT: &usize = { //~ ERROR undefined behavior to use this value
-//~| encountered a reference pointing to a static variable
- static FOO: AtomicUsize = AtomicUsize::new(0);
- unsafe { &*(&FOO as *const _ as *const usize) }
-};
-
-// ok some day perhaps
-const READ_IMMUT: &usize = { //~ ERROR it is undefined behavior to use this value
-//~| encountered a reference pointing to a static variable
- static FOO: usize = 0;
- &FOO
-};
-
-fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
index 3a22b0689..6df2fe3d0 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static_cross_crate.rs:12:1
+ --> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
LL | const SLICE_MUT: &[u8; 1] = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -10,13 +10,13 @@ LL | const SLICE_MUT: &[u8; 1] = {
}
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:40:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:34:9
|
LL | SLICE_MUT => true,
| ^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static_cross_crate.rs:17:1
+ --> $DIR/const_refers_to_static_cross_crate.rs:15:1
|
LL | const U8_MUT: &u8 = {
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -27,75 +27,55 @@ LL | const U8_MUT: &u8 = {
}
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:49:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:43:9
|
LL | U8_MUT => true,
| ^^^^^^
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:25:15
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static_cross_crate.rs:22:15
|
-LL | const U8_MUT2: &u8 = {
- | ------------------
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:23:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:60:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
LL | U8_MUT2 => true,
| ^^^^^^^
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
-LL | const U8_MUT3: &u8 = {
- | ------------------
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:30:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:68:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:62:9
|
LL | U8_MUT3 => true,
| ^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:40:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:34:9
|
LL | SLICE_MUT => true,
| ^^^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:49:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:43:9
|
LL | U8_MUT => true,
| ^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:60:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
LL | U8_MUT2 => true,
| ^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:68:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:62:9
|
LL | U8_MUT3 => true,
| ^^^^^^^
@@ -103,90 +83,56 @@ LL | U8_MUT3 => true,
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:14:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
LL | unsafe { &static_cross_crate::ZERO }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:14:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
LL | unsafe { &static_cross_crate::ZERO }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:25:17
+ --> $DIR/const_refers_to_static_cross_crate.rs:22:17
|
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 10 previous errors; 3 warnings emitted
+error: aborting due to 12 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:25:15
- |
-LL | const U8_MUT2: &u8 = {
- | ------------------
-LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:23:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
- |
-LL | const U8_MUT3: &u8 = {
- | ------------------
-LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:30:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
index 39c874d64..8802f3ada 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static_cross_crate.rs:12:1
+ --> $DIR/const_refers_to_static_cross_crate.rs:10:1
|
LL | const SLICE_MUT: &[u8; 1] = {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -10,13 +10,13 @@ LL | const SLICE_MUT: &[u8; 1] = {
}
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:40:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:34:9
|
LL | SLICE_MUT => true,
| ^^^^^^^^^
error[E0080]: it is undefined behavior to use this value
- --> $DIR/const_refers_to_static_cross_crate.rs:17:1
+ --> $DIR/const_refers_to_static_cross_crate.rs:15:1
|
LL | const U8_MUT: &u8 = {
| ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -27,75 +27,55 @@ LL | const U8_MUT: &u8 = {
}
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:49:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:43:9
|
LL | U8_MUT => true,
| ^^^^^^
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:25:15
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static_cross_crate.rs:22:15
|
-LL | const U8_MUT2: &u8 = {
- | ------------------
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:23:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:60:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
LL | U8_MUT2 => true,
| ^^^^^^^
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+error[E0080]: evaluation of constant value failed
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
-LL | const U8_MUT3: &u8 = {
- | ------------------
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:30:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:68:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:62:9
|
LL | U8_MUT3 => true,
| ^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:40:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:34:9
|
LL | SLICE_MUT => true,
| ^^^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:49:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:43:9
|
LL | U8_MUT => true,
| ^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:60:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:54:9
|
LL | U8_MUT2 => true,
| ^^^^^^^
error: could not evaluate constant pattern
- --> $DIR/const_refers_to_static_cross_crate.rs:68:9
+ --> $DIR/const_refers_to_static_cross_crate.rs:62:9
|
LL | U8_MUT3 => true,
| ^^^^^^^
@@ -103,90 +83,56 @@ LL | U8_MUT3 => true,
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:14:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
LL | unsafe { &static_cross_crate::ZERO }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:14:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:12:15
|
LL | unsafe { &static_cross_crate::ZERO }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:19:15
+ --> $DIR/const_refers_to_static_cross_crate.rs:17:15
|
LL | unsafe { &static_cross_crate::ZERO[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:25:17
+ --> $DIR/const_refers_to_static_cross_crate.rs:22:17
|
LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
+ --> $DIR/const_refers_to_static_cross_crate.rs:27:20
|
LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 10 previous errors; 3 warnings emitted
+error: aborting due to 12 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:25:15
- |
-LL | const U8_MUT2: &u8 = {
- | ------------------
-LL | unsafe { &(*static_cross_crate::ZERO_REF)[0] }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:23:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
-Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/const_refers_to_static_cross_crate.rs:32:20
- |
-LL | const U8_MUT3: &u8 = {
- | ------------------
-LL | unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
- |
-note: the lint level is defined here
- --> $DIR/const_refers_to_static_cross_crate.rs:30:8
- |
-LL | #[warn(const_err)]
- | ^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
index 4638d73fc..bf4f14f4d 100644
--- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
+++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
@@ -1,9 +1,7 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
// aux-build:static_cross_crate.rs
// stderr-per-bitwidth
-#![allow(const_err)]
-
-#![feature(exclusive_range_pattern, half_open_range_patterns)]
+#![feature(exclusive_range_pattern, half_open_range_patterns_in_slices)]
extern crate static_cross_crate;
@@ -19,20 +17,16 @@ const U8_MUT: &u8 = { //~ ERROR undefined behavior to use this value
unsafe { &static_cross_crate::ZERO[0] }
};
-// Also test indirection that reads from other static. This causes a const_err.
-#[warn(const_err)]
+// Also test indirection that reads from other static.
const U8_MUT2: &u8 = {
unsafe { &(*static_cross_crate::ZERO_REF)[0] }
- //~^ WARN [const_err]
+ //~^ ERROR evaluation of constant value failed
//~| constant accesses static
- //~| WARN this was previously accepted by the compiler but is being phased out
};
-#[warn(const_err)]
const U8_MUT3: &u8 = {
unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
- //~^ WARN [const_err]
+ //~^ ERROR evaluation of constant value failed
//~| constant accesses static
- //~| WARN this was previously accepted by the compiler but is being phased out
};
pub fn test(x: &[u8; 1]) -> bool {
diff --git a/src/test/ui/consts/miri_unleashed/drop.rs b/src/test/ui/consts/miri_unleashed/drop.rs
index 4afa954d9..3942e7ef7 100644
--- a/src/test/ui/consts/miri_unleashed/drop.rs
+++ b/src/test/ui/consts/miri_unleashed/drop.rs
@@ -1,6 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
// error-pattern: calling non-const function `<Vec<i32> as Drop>::drop`
-#![allow(const_err)]
use std::mem::ManuallyDrop;
diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr
index 36db6b786..a3a502723 100644
--- a/src/test/ui/consts/miri_unleashed/drop.stderr
+++ b/src/test/ui/consts/miri_unleashed/drop.stderr
@@ -7,15 +7,15 @@ LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
| calling non-const function `<Vec<i32> as Drop>::drop`
| inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
|
- ::: $DIR/drop.rs:18:1
+ ::: $DIR/drop.rs:17:1
|
LL | };
- | - inside `TEST_BAD` at $DIR/drop.rs:18:1
+ | - inside `TEST_BAD` at $DIR/drop.rs:17:1
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/drop.rs:17:9
+ --> $DIR/drop.rs:16:9
|
LL | let _v: Vec<i32> = Vec::new();
| ^^
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
index 8b17f6885..c24d3338e 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.rs
@@ -1,5 +1,3 @@
-#![allow(const_err)]
-
// a test demonstrating why we do need to run static const qualification on associated constants
// instead of just checking the final constant
@@ -8,7 +6,7 @@ trait Foo<T> {
}
trait Bar<T, U: Foo<T>> {
- const F: u32 = (U::X, 42).1; //~ ERROR destructors cannot be evaluated at compile-time
+ const F: u32 = (U::X, 42).1; //~ ERROR destructor of
}
impl Foo<u32> for () {
diff --git a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
index 0b6cb2fab..45ed88b1b 100644
--- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
+++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr
@@ -1,10 +1,10 @@
-error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:11:20
+error[E0493]: destructor of `(T, u32)` cannot be evaluated at compile-time
+ --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:9:20
|
LL | const F: u32 = (U::X, 42).1;
| ^^^^^^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
error: aborting due to previous error
diff --git a/src/test/ui/consts/miri_unleashed/inline_asm.rs b/src/test/ui/consts/miri_unleashed/inline_asm.rs
index 697117033..6fd52ceb2 100644
--- a/src/test/ui/consts/miri_unleashed/inline_asm.rs
+++ b/src/test/ui/consts/miri_unleashed/inline_asm.rs
@@ -1,6 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
// only-x86_64
-#![allow(const_err)]
use std::arch::asm;
diff --git a/src/test/ui/consts/miri_unleashed/inline_asm.stderr b/src/test/ui/consts/miri_unleashed/inline_asm.stderr
index 595b859cb..6317cd882 100644
--- a/src/test/ui/consts/miri_unleashed/inline_asm.stderr
+++ b/src/test/ui/consts/miri_unleashed/inline_asm.stderr
@@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/inline_asm.rs:11:14
+ --> $DIR/inline_asm.rs:10:14
|
LL | unsafe { asm!("nop"); }
| ^^^^^^^^^^^ inline assembly is not supported
@@ -7,7 +7,7 @@ LL | unsafe { asm!("nop"); }
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/inline_asm.rs:11:14
+ --> $DIR/inline_asm.rs:10:14
|
LL | unsafe { asm!("nop"); }
| ^^^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.rs b/src/test/ui/consts/miri_unleashed/mutable_references.rs
index ca927ef4a..4e9964647 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.rs
@@ -1,5 +1,4 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
use std::cell::UnsafeCell;
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.stderr b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
index c6180c1e0..3ed96701a 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references.stderr
@@ -1,5 +1,5 @@
error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item
- --> $DIR/mutable_references.rs:36:5
+ --> $DIR/mutable_references.rs:35:5
|
LL | *OH_YES = 99;
| ^^^^^^^^^^^^ cannot assign
@@ -7,27 +7,27 @@ LL | *OH_YES = 99;
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references.rs:9:26
+ --> $DIR/mutable_references.rs:8:26
|
LL | static FOO: &&mut u32 = &&mut 42;
| ^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references.rs:13:23
+ --> $DIR/mutable_references.rs:12:23
|
LL | static BAR: &mut () = &mut ();
| ^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references.rs:18:28
+ --> $DIR/mutable_references.rs:17:28
|
LL | static BOO: &mut Foo<()> = &mut Foo(());
| ^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references.rs:26:8
+ --> $DIR/mutable_references.rs:25:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references.rs:30:27
+ --> $DIR/mutable_references.rs:29:27
|
LL | static OH_YES: &mut i32 = &mut 42;
| ^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
index 7ea35f70d..0ea179240 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:17:1
+ --> $DIR/mutable_references_err.rs:15:1
|
LL | const MUH: Meh = Meh {
| ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const`
@@ -10,7 +10,7 @@ LL | const MUH: Meh = Meh {
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:27:1
+ --> $DIR/mutable_references_err.rs:25:1
|
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const`
@@ -21,7 +21,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:31:1
+ --> $DIR/mutable_references_err.rs:29:1
|
LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const`
@@ -34,17 +34,17 @@ LL | const BLUNT: &mut i32 = &mut 42;
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:18:8
+ --> $DIR/mutable_references_err.rs:16:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:27:27
+ --> $DIR/mutable_references_err.rs:25:27
|
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:31:25
+ --> $DIR/mutable_references_err.rs:29:25
|
LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
index 5ad398930..67959d256 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:17:1
+ --> $DIR/mutable_references_err.rs:15:1
|
LL | const MUH: Meh = Meh {
| ^^^^^^^^^^^^^^ constructing invalid value at .x.<deref>: encountered `UnsafeCell` in a `const`
@@ -10,7 +10,7 @@ LL | const MUH: Meh = Meh {
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:27:1
+ --> $DIR/mutable_references_err.rs:25:1
|
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<deref>.<dyn-downcast>.x: encountered `UnsafeCell` in a `const`
@@ -21,7 +21,7 @@ LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
}
error[E0080]: it is undefined behavior to use this value
- --> $DIR/mutable_references_err.rs:31:1
+ --> $DIR/mutable_references_err.rs:29:1
|
LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered mutable reference in a `const`
@@ -34,17 +34,17 @@ LL | const BLUNT: &mut i32 = &mut 42;
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:18:8
+ --> $DIR/mutable_references_err.rs:16:8
|
LL | x: &UnsafeCell::new(42),
| ^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:27:27
+ --> $DIR/mutable_references_err.rs:25:27
|
LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
- --> $DIR/mutable_references_err.rs:31:25
+ --> $DIR/mutable_references_err.rs:29:25
|
LL | const BLUNT: &mut i32 = &mut 42;
| ^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs
index 722b9cf94..6399b122b 100644
--- a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs
+++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs
@@ -1,8 +1,6 @@
// stderr-per-bitwidth
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
-
use std::cell::UnsafeCell;
// this test ensures that our mutability story is sound
diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.rs b/src/test/ui/consts/miri_unleashed/mutating_global.rs
index 902fe0aa1..231f4af0a 100644
--- a/src/test/ui/consts/miri_unleashed/mutating_global.rs
+++ b/src/test/ui/consts/miri_unleashed/mutating_global.rs
@@ -1,5 +1,4 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
// Make sure we cannot mutate globals.
diff --git a/src/test/ui/consts/miri_unleashed/mutating_global.stderr b/src/test/ui/consts/miri_unleashed/mutating_global.stderr
index ba9dd5619..c8770c8d7 100644
--- a/src/test/ui/consts/miri_unleashed/mutating_global.stderr
+++ b/src/test/ui/consts/miri_unleashed/mutating_global.stderr
@@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/mutating_global.rs:10:9
+ --> $DIR/mutating_global.rs:9:9
|
LL | GLOBAL = 99
| ^^^^^^^^^^^ modifying a static's initial value from another static's initializer
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.rs b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
index 70da94df7..44ab60dca 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.rs
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.rs
@@ -1,7 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
-
// A test demonstrating that we prevent calling non-const fn during CTFE.
fn foo() {}
diff --git a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
index 3e9658ad8..57836f796 100644
--- a/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
+++ b/src/test/ui/consts/miri_unleashed/non_const_fn.stderr
@@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/non_const_fn.rs:9:16
+ --> $DIR/non_const_fn.rs:7:16
|
LL | static C: () = foo();
| ^^^^^ calling non-const function `foo`
@@ -7,7 +7,7 @@ LL | static C: () = foo();
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/non_const_fn.rs:9:16
+ --> $DIR/non_const_fn.rs:7:16
|
LL | static C: () = foo();
| ^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
index 6a19b2945..4d12960b8 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
@@ -1,6 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(core_intrinsics)]
-#![allow(const_err)]
// During CTFE, we prevent pointer-to-int casts.
// Pointer comparisons are prevented in the trait system.
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
index e0c4fa175..30fd3a55e 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
@@ -1,11 +1,11 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/ptr_arith.rs:9:13
+ --> $DIR/ptr_arith.rs:8:13
|
LL | let x = &0 as *const _ as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^ exposing pointers is not possible at compile-time
error[E0080]: could not evaluate static initializer
- --> $DIR/ptr_arith.rs:17:14
+ --> $DIR/ptr_arith.rs:16:14
|
LL | let _v = x + 0;
| ^ unable to turn pointer into raw bytes
@@ -16,7 +16,7 @@ LL | let _v = x + 0;
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/ptr_arith.rs:9:13
+ --> $DIR/ptr_arith.rs:8:13
|
LL | let x = &0 as *const _ as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs
index cabd754e0..5f8ec4e6e 100644
--- a/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs
+++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs
@@ -1,7 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
-#![allow(const_err)]
-
use std::cell::UnsafeCell;
const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr
index e145f6dd2..f8dc11d69 100644
--- a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr
@@ -1,5 +1,5 @@
error: untyped pointers are not allowed in constant
- --> $DIR/raw_mutable_const.rs:7:1
+ --> $DIR/raw_mutable_const.rs:5:1
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *m
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/raw_mutable_const.rs:7:38
+ --> $DIR/raw_mutable_const.rs:5:38
|
LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
| ^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/miri_unleashed/tls.rs b/src/test/ui/consts/miri_unleashed/tls.rs
index 7d4f8962a..d06d7cf19 100644
--- a/src/test/ui/consts/miri_unleashed/tls.rs
+++ b/src/test/ui/consts/miri_unleashed/tls.rs
@@ -1,6 +1,5 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
#![feature(thread_local)]
-#![allow(const_err)]
use std::thread;
diff --git a/src/test/ui/consts/miri_unleashed/tls.stderr b/src/test/ui/consts/miri_unleashed/tls.stderr
index a49e50a3e..436c51123 100644
--- a/src/test/ui/consts/miri_unleashed/tls.stderr
+++ b/src/test/ui/consts/miri_unleashed/tls.stderr
@@ -1,11 +1,11 @@
error[E0080]: could not evaluate static initializer
- --> $DIR/tls.rs:12:25
+ --> $DIR/tls.rs:11:25
|
LL | unsafe { let _val = A; }
| ^ cannot access thread local static (DefId(0:6 ~ tls[78b0]::A))
error[E0080]: could not evaluate static initializer
- --> $DIR/tls.rs:19:26
+ --> $DIR/tls.rs:18:26
|
LL | unsafe { let _val = &A; }
| ^ cannot access thread local static (DefId(0:6 ~ tls[78b0]::A))
@@ -13,12 +13,12 @@ LL | unsafe { let _val = &A; }
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
- --> $DIR/tls.rs:12:25
+ --> $DIR/tls.rs:11:25
|
LL | unsafe { let _val = A; }
| ^
help: skipping check that does not even have a feature gate
- --> $DIR/tls.rs:19:26
+ --> $DIR/tls.rs:18:26
|
LL | unsafe { let _val = &A; }
| ^
diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs
index 6830b23cf..907617052 100644
--- a/src/test/ui/consts/promote-not.rs
+++ b/src/test/ui/consts/promote-not.rs
@@ -1,6 +1,6 @@
// ignore-tidy-linelength
// Test various things that we do not want to promote.
-#![allow(unconditional_panic, const_err)]
+#![allow(unconditional_panic)]
use std::cell::Cell;
diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs
index 0a3c2d4be..f442e6138 100644
--- a/src/test/ui/consts/ptr_comparisons.rs
+++ b/src/test/ui/consts/ptr_comparisons.rs
@@ -55,11 +55,9 @@ const _: *const u8 =
//~| out-of-bounds
const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
//~| unable to turn pointer into raw bytes
-//~| WARN this was previously accepted by the compiler but is being phased out
const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
-//~^ ERROR any use of this value will cause an error
+//~^ ERROR evaluation of constant value failed
//~| unable to turn pointer into raw bytes
-//~| WARN this was previously accepted by the compiler but is being phased out
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index 3de2aba5b..b71964b92 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -18,55 +18,24 @@ error[E0080]: evaluation of constant value failed
LL | unsafe { std::ptr::addr_of!((*(FOO as *const usize as *const [u8; 1000]))[999]) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: alloc3 has size $WORD, so pointer to 1000 bytes starting at offset 0 is out-of-bounds
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/ptr_comparisons.rs:57:27
|
LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
- | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-error: any use of this value will cause an error
- --> $DIR/ptr_comparisons.rs:62:27
+error[E0080]: evaluation of constant value failed
+ --> $DIR/ptr_comparisons.rs:61:27
|
LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
- | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
|
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= help: this code performed an operation that depends on the underlying bytes representing a pointer
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ptr_comparisons.rs:57:27
- |
-LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 };
- | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
-Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/ptr_comparisons.rs:62:27
- |
-LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 };
- | -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = help: this code performed an operation that depends on the underlying bytes representing a pointer
- = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
-
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.rs b/src/test/ui/consts/qualif-indirect-mutation-fail.rs
index f74a25a34..a6d293404 100644
--- a/src/test/ui/consts/qualif-indirect-mutation-fail.rs
+++ b/src/test/ui/consts/qualif-indirect-mutation-fail.rs
@@ -6,13 +6,13 @@
// Mutable borrow of a field with drop impl.
pub const fn f() {
- let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructors cannot be evaluated
+ let mut a: (u32, Option<String>) = (0, None); //~ ERROR destructor of
let _ = &mut a.1;
}
// Mutable borrow of a type with drop impl.
pub const A1: () = {
- let mut x = None; //~ ERROR destructors cannot be evaluated
+ let mut x = None; //~ ERROR destructor of
let mut y = Some(String::new());
let a = &mut x;
let b = &mut y;
@@ -28,12 +28,12 @@ pub const A2: () = {
let b = &mut y;
std::mem::swap(a, b);
std::mem::forget(y);
- let _z = x; //~ ERROR destructors cannot be evaluated
+ let _z = x; //~ ERROR destructor of
};
// Shared borrow of a type that might be !Freeze and Drop.
pub const fn g1<T>() {
- let x: Option<T> = None; //~ ERROR destructors cannot be evaluated
+ let x: Option<T> = None; //~ ERROR destructor of
let _ = x.is_some();
}
@@ -41,24 +41,24 @@ pub const fn g1<T>() {
pub const fn g2<T>() {
let x: Option<T> = None;
let _ = x.is_some();
- let _y = x; //~ ERROR destructors cannot be evaluated
+ let _y = x; //~ ERROR destructor of
}
// Mutable raw reference to a Drop type.
pub const fn address_of_mut() {
- let mut x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ let mut x: Option<String> = None; //~ ERROR destructor of
&raw mut x;
- let mut y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ let mut y: Option<String> = None; //~ ERROR destructor of
std::ptr::addr_of_mut!(y);
}
// Const raw reference to a Drop type. Conservatively assumed to allow mutation
// until resolution of https://github.com/rust-lang/rust/issues/56604.
pub const fn address_of_const() {
- let x: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ let x: Option<String> = None; //~ ERROR destructor of
&raw const x;
- let y: Option<String> = None; //~ ERROR destructors cannot be evaluated
+ let y: Option<String> = None; //~ ERROR destructor of
std::ptr::addr_of!(y);
}
diff --git a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
index 713df12b7..6379c00e4 100644
--- a/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
+++ b/src/test/ui/consts/qualif-indirect-mutation-fail.stderr
@@ -1,56 +1,56 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(u32, Option<String>)` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:9:9
|
LL | let mut a: (u32, Option<String>) = (0, None);
- | ^^^^^ constant functions cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:15:9
|
LL | let mut x = None;
- | ^^^^^ constants cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:31:9
|
LL | let _z = x;
- | ^^ constants cannot evaluate destructors
+ | ^^ the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:36:9
|
LL | let x: Option<T> = None;
- | ^ constant functions cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<T>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:44:9
|
LL | let _y = x;
- | ^^ constant functions cannot evaluate destructors
+ | ^^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:52:9
|
LL | let mut y: Option<String> = None;
- | ^^^^^ constant functions cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:49:9
|
LL | let mut x: Option<String> = None;
- | ^^^^^ constant functions cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:62:9
|
LL | let y: Option<String> = None;
- | ^ constant functions cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Option<String>` cannot be evaluated at compile-time
--> $DIR/qualif-indirect-mutation-fail.rs:59:9
|
LL | let x: Option<String> = None;
- | ^ constant functions cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constant functions
error: aborting due to 9 previous errors
diff --git a/src/test/ui/consts/raw-ptr-const.rs b/src/test/ui/consts/raw-ptr-const.rs
index 00fad046b..b9c542d03 100644
--- a/src/test/ui/consts/raw-ptr-const.rs
+++ b/src/test/ui/consts/raw-ptr-const.rs
@@ -1,5 +1,3 @@
-#![allow(const_err)] // make sure we hit the `delay_span_bug`
-
// This is a regression test for a `delay_span_bug` during interning when a constant
// evaluates to a (non-dangling) raw pointer. For now this errors; potentially it
// could also be allowed.
diff --git a/src/test/ui/consts/raw-ptr-const.stderr b/src/test/ui/consts/raw-ptr-const.stderr
index 0ebe1e95c..f7b53433b 100644
--- a/src/test/ui/consts/raw-ptr-const.stderr
+++ b/src/test/ui/consts/raw-ptr-const.stderr
@@ -1,5 +1,5 @@
error: untyped pointers are not allowed in constant
- --> $DIR/raw-ptr-const.rs:7:1
+ --> $DIR/raw-ptr-const.rs:5:1
|
LL | const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/consts/recursive.rs b/src/test/ui/consts/recursive.rs
index 664940c52..5d736e31b 100644
--- a/src/test/ui/consts/recursive.rs
+++ b/src/test/ui/consts/recursive.rs
@@ -2,8 +2,7 @@
const fn f<T>(x: T) { //~ WARN function cannot return without recursing
f(x);
- //~^ ERROR any use of this value will cause an error
- //~| WARN this was previously accepted by the compiler
+ //~^ ERROR evaluation of constant value failed
}
const X: () = f(1);
diff --git a/src/test/ui/consts/recursive.stderr b/src/test/ui/consts/recursive.stderr
index 647ed1db2..14fa3da7a 100644
--- a/src/test/ui/consts/recursive.stderr
+++ b/src/test/ui/consts/recursive.stderr
@@ -6,10 +6,10 @@ LL | const fn f<T>(x: T) {
LL | f(x);
| ---- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
-error: any use of this value will cause an error
+error[E0080]: evaluation of constant value failed
--> $DIR/recursive.rs:4:5
|
LL | f(x);
@@ -18,33 +18,10 @@ LL | f(x);
| reached the configured maximum number of stack frames
| inside `f::<i32>` at $DIR/recursive.rs:4:5
| [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
- | inside `X` at $DIR/recursive.rs:9:15
...
LL | const X: () = f(1);
- | -----------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ---- inside `X` at $DIR/recursive.rs:8:15
error: aborting due to previous error; 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/recursive.rs:4:5
- |
-LL | f(x);
- | ^^^^
- | |
- | reached the configured maximum number of stack frames
- | inside `f::<i32>` at $DIR/recursive.rs:4:5
- | [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
- | inside `X` at $DIR/recursive.rs:9:15
-...
-LL | const X: () = f(1);
- | -----------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
index 4f2f5e244..3855b5f2a 100644
--- a/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
+++ b/src/test/ui/consts/refs_check_const_eq-issue-88384.stderr
@@ -4,8 +4,8 @@ warning: the feature `adt_const_params` is incomplete and may not be safe to use
LL | #![feature(adt_const_params)]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0741]: using function pointers as const generic parameters is forbidden
--> $DIR/refs_check_const_eq-issue-88384.rs:10:21
diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs
index 2b970390f..7cd3dbec9 100644
--- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs
+++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.rs
@@ -11,7 +11,7 @@ impl<T> Either<T, T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "foo", since = "1.0.0")]
pub const fn unwrap(self) -> T {
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
match self {
Self::Left(t) => t,
Self::Right(t) => t,
diff --git a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr
index a3f513541..5f70391ee 100644
--- a/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr
+++ b/src/test/ui/consts/stable-precise-live-drops-in-libcore.stderr
@@ -1,8 +1,8 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `Either<T, T>` cannot be evaluated at compile-time
--> $DIR/stable-precise-live-drops-in-libcore.rs:13:25
|
LL | pub const fn unwrap(self) -> T {
- | ^^^^ constant functions cannot evaluate destructors
+ | ^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
diff --git a/src/test/ui/consts/trait_specialization.stderr b/src/test/ui/consts/trait_specialization.stderr
index e80821cf4..10bebe8eb 100644
--- a/src/test/ui/consts/trait_specialization.stderr
+++ b/src/test/ui/consts/trait_specialization.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.rs b/src/test/ui/consts/uninhabited-const-issue-61744.rs
index 860628c39..a07c39882 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.rs
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.rs
@@ -1,8 +1,7 @@
// build-fail
pub const unsafe fn fake_type<T>() -> T {
- hint_unreachable() //~ ERROR any use of this value will cause an error [const_err]
- //~| WARN this was previously accepted by the compiler but is being phased out
+ hint_unreachable() //~ ERROR evaluation of `<i32 as Const>::CONSTANT` failed
}
pub const unsafe fn hint_unreachable() -> ! {
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
index d31777847..9c7cc8861 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -1,4 +1,4 @@
-error: any use of this value will cause an error
+error[E0080]: evaluation of `<i32 as Const>::CONSTANT` failed
--> $DIR/uninhabited-const-issue-61744.rs:4:5
|
LL | hint_unreachable()
@@ -6,143 +6,142 @@ LL | hint_unreachable()
| |
| reached the configured maximum number of stack frames
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
| inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:13:36
+...
+LL | fake_type()
+ | -----------
+ | |
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
+ | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
...
LL | const CONSTANT: i32 = unsafe { fake_type() };
- | -------------------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ | ----------- inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:12:36
error[E0080]: erroneous constant used
- --> $DIR/uninhabited-const-issue-61744.rs:19:10
+ --> $DIR/uninhabited-const-issue-61744.rs:18:10
|
LL | dbg!(i32::CONSTANT);
| ^^^^^^^^^^^^^ referenced constant has errors
@@ -150,147 +149,3 @@ LL | dbg!(i32::CONSTANT);
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: any use of this value will cause an error
- --> $DIR/uninhabited-const-issue-61744.rs:4:5
- |
-LL | hint_unreachable()
- | ^^^^^^^^^^^^^^^^^^
- | |
- | reached the configured maximum number of stack frames
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:9:5
- | inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
- | inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:13:36
-...
-LL | const CONSTANT: i32 = unsafe { fake_type() };
- | -------------------
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.rs b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
index 16b36c8d5..ca4ed8f0b 100644
--- a/src/test/ui/consts/unstable-const-fn-in-libcore.rs
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.rs
@@ -4,7 +4,7 @@
// gate was not enabled in libcore.
#![stable(feature = "core", since = "1.6.0")]
-#![feature(staged_api)]
+#![feature(staged_api, const_trait_impl)]
enum Opt<T> {
Some(T),
@@ -14,12 +14,12 @@ enum Opt<T> {
impl<T> Opt<T> {
#[rustc_const_unstable(feature = "foo", issue = "none")]
#[stable(feature = "rust1", since = "1.0.0")]
- const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
- //~^ ERROR destructors cannot be evaluated at compile-time
- //~| ERROR destructors cannot be evaluated at compile-time
+ const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
+ //~^ ERROR destructor of
+ //~| ERROR destructor of
match self {
Opt::Some(t) => t,
- Opt::None => f(), //~ ERROR E0015
+ Opt::None => f(),
}
}
}
diff --git a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
index 180f9f10c..e5b00dd07 100644
--- a/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
+++ b/src/test/ui/consts/unstable-const-fn-in-libcore.stderr
@@ -1,34 +1,21 @@
-error[E0015]: cannot call non-const closure in constant functions
- --> $DIR/unstable-const-fn-in-libcore.rs:22:26
+error[E0493]: destructor of `F` cannot be evaluated at compile-time
+ --> $DIR/unstable-const-fn-in-libcore.rs:17:60
|
-LL | Opt::None => f(),
- | ^^^
- |
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
- |
-LL | const fn unwrap_or_else<F: FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
- | +++++++++++++++++++++++++++++
-
-error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/unstable-const-fn-in-libcore.rs:17:53
- |
-LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
- | ^ constant functions cannot evaluate destructors
+LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
+ | ^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
- --> $DIR/unstable-const-fn-in-libcore.rs:17:47
+error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time
+ --> $DIR/unstable-const-fn-in-libcore.rs:17:54
|
-LL | const fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
- | ^^^^ constant functions cannot evaluate destructors
+LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
+ | ^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0015, E0493.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.rs b/src/test/ui/consts/write_to_static_via_mut_ref.rs
index 665c305e9..39b830ae4 100644
--- a/src/test/ui/consts/write_to_static_via_mut_ref.rs
+++ b/src/test/ui/consts/write_to_static_via_mut_ref.rs
@@ -1,5 +1,4 @@
#![feature(const_mut_refs)]
-#![allow(const_err)]
static OH_NO: &mut i32 = &mut 42; //~ ERROR mutable references are not allowed
fn main() {
diff --git a/src/test/ui/consts/write_to_static_via_mut_ref.stderr b/src/test/ui/consts/write_to_static_via_mut_ref.stderr
index d19e998d6..f64f0db6b 100644
--- a/src/test/ui/consts/write_to_static_via_mut_ref.stderr
+++ b/src/test/ui/consts/write_to_static_via_mut_ref.stderr
@@ -1,11 +1,11 @@
error[E0764]: mutable references are not allowed in the final value of statics
- --> $DIR/write_to_static_via_mut_ref.rs:4:26
+ --> $DIR/write_to_static_via_mut_ref.rs:3:26
|
LL | static OH_NO: &mut i32 = &mut 42;
| ^^^^^^^
error[E0594]: cannot assign to `*OH_NO`, as `OH_NO` is an immutable static item
- --> $DIR/write_to_static_via_mut_ref.rs:7:5
+ --> $DIR/write_to_static_via_mut_ref.rs:6:5
|
LL | *OH_NO = 43;
| ^^^^^^^^^^^ cannot assign
diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs
index 65cc4e2ef..0417e952e 100644
--- a/src/test/ui/deprecation/deprecation-lint.rs
+++ b/src/test/ui/deprecation/deprecation-lint.rs
@@ -51,7 +51,7 @@ mod cross_crate {
let _ = nested::DeprecatedTupleStruct (1); //~ ERROR use of deprecated tuple struct `deprecation_lint::nested::DeprecatedTupleStruct`: text
- // At the moment, the lint checker only checks stability in
+ // At the moment, the lint checker only checks stability
// in the arguments of macros.
// Eventually, we will want to lint the contents of the
// macro in the module *defining* it. Also, stability levels
diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr
index bd36a2568..dcdf8f843 100644
--- a/src/test/ui/derive-uninhabited-enum-38885.stderr
+++ b/src/test/ui/derive-uninhabited-enum-38885.stderr
@@ -7,8 +7,8 @@ LL | Bar(u8),
LL | Void(Void),
| ^^^^
|
- = note: `-W dead-code` implied by `-W unused`
= note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
+ = note: `-W dead-code` implied by `-W unused`
warning: 1 warning emitted
diff --git a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
index baf34b46d..512b870fa 100644
--- a/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
+++ b/src/test/ui/derives/clone-debug-dead-code-in-the-same-struct.stderr
@@ -13,12 +13,12 @@ LL | field3: (),
LL | field4: (),
| ^^^^^^
|
+ = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
note: the lint level is defined here
--> $DIR/clone-debug-dead-code-in-the-same-struct.rs:1:11
|
LL | #![forbid(dead_code)]
| ^^^^^^^^^
- = note: `Whatever` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
error: aborting due to previous error
diff --git a/src/test/ui/derives/deriving-with-repr-packed.stderr b/src/test/ui/derives/deriving-with-repr-packed.stderr
index d3fe550c3..0ad800c39 100644
--- a/src/test/ui/derives/deriving-with-repr-packed.stderr
+++ b/src/test/ui/derives/deriving-with-repr-packed.stderr
@@ -4,13 +4,13 @@ error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or co
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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 `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
@@ -52,13 +52,13 @@ error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or co
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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 `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -68,13 +68,13 @@ error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type o
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
@@ -84,13 +84,13 @@ error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not de
LL | #[derive(Default, Hash)]
| ^^^^
|
+ = warning: this was previously accepted 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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
@@ -100,12 +100,12 @@ error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not d
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout
index 56efc2a59..92fce6888 100644
--- a/src/test/ui/deriving/deriving-all-codegen.stdout
+++ b/src/test/ui/deriving/deriving-all-codegen.stdout
@@ -46,13 +46,15 @@ impl ::core::default::Default for Empty {
impl ::core::hash::Hash for Empty {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
}
-impl ::core::marker::StructuralPartialEq for Empty {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Empty { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Empty {
#[inline]
fn eq(&self, other: &Empty) -> bool { true }
}
-impl ::core::marker::StructuralEq for Empty {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Empty { }
#[automatically_derived]
impl ::core::cmp::Eq for Empty {
#[inline]
@@ -115,7 +117,8 @@ impl ::core::hash::Hash for Point {
::core::hash::Hash::hash(&self.y, state)
}
}
-impl ::core::marker::StructuralPartialEq for Point {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Point { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Point {
#[inline]
@@ -123,7 +126,8 @@ impl ::core::cmp::PartialEq for Point {
self.x == other.x && self.y == other.y
}
}
-impl ::core::marker::StructuralEq for Point {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Point { }
#[automatically_derived]
impl ::core::cmp::Eq for Point {
#[inline]
@@ -225,7 +229,8 @@ impl ::core::hash::Hash for Big {
::core::hash::Hash::hash(&self.b8, state)
}
}
-impl ::core::marker::StructuralPartialEq for Big {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Big { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Big {
#[inline]
@@ -236,7 +241,8 @@ impl ::core::cmp::PartialEq for Big {
self.b8 == other.b8
}
}
-impl ::core::marker::StructuralEq for Big {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Big { }
#[automatically_derived]
impl ::core::cmp::Eq for Big {
#[inline]
@@ -345,13 +351,15 @@ impl ::core::hash::Hash for Unsized {
::core::hash::Hash::hash(&self.0, state)
}
}
-impl ::core::marker::StructuralPartialEq for Unsized {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Unsized { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Unsized {
#[inline]
fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 }
}
-impl ::core::marker::StructuralEq for Unsized {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Unsized { }
#[automatically_derived]
impl ::core::cmp::Eq for Unsized {
#[inline]
@@ -410,13 +418,15 @@ impl ::core::hash::Hash for PackedCopy {
::core::hash::Hash::hash(&{ self.0 }, state)
}
}
-impl ::core::marker::StructuralPartialEq for PackedCopy {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for PackedCopy { }
#[automatically_derived]
impl ::core::cmp::PartialEq for PackedCopy {
#[inline]
fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } }
}
-impl ::core::marker::StructuralEq for PackedCopy {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for PackedCopy { }
#[automatically_derived]
impl ::core::cmp::Eq for PackedCopy {
#[inline]
@@ -479,7 +489,8 @@ impl ::core::hash::Hash for PackedNonCopy {
::core::hash::Hash::hash(__self_0_0, state)
}
}
-impl ::core::marker::StructuralPartialEq for PackedNonCopy {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for PackedNonCopy { }
#[automatically_derived]
impl ::core::cmp::PartialEq for PackedNonCopy {
#[inline]
@@ -489,7 +500,8 @@ impl ::core::cmp::PartialEq for PackedNonCopy {
*__self_0_0 == *__self_1_0
}
}
-impl ::core::marker::StructuralEq for PackedNonCopy {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for PackedNonCopy { }
#[automatically_derived]
impl ::core::cmp::Eq for PackedNonCopy {
#[inline]
@@ -540,7 +552,8 @@ impl ::core::hash::Hash for Enum0 {
unsafe { ::core::intrinsics::unreachable() }
}
}
-impl ::core::marker::StructuralPartialEq for Enum0 {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Enum0 { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Enum0 {
#[inline]
@@ -548,7 +561,8 @@ impl ::core::cmp::PartialEq for Enum0 {
unsafe { ::core::intrinsics::unreachable() }
}
}
-impl ::core::marker::StructuralEq for Enum0 {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Enum0 { }
#[automatically_derived]
impl ::core::cmp::Eq for Enum0 {
#[inline]
@@ -607,7 +621,8 @@ impl ::core::hash::Hash for Enum1 {
}
}
}
-impl ::core::marker::StructuralPartialEq for Enum1 {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Enum1 { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Enum1 {
#[inline]
@@ -618,7 +633,8 @@ impl ::core::cmp::PartialEq for Enum1 {
}
}
}
-impl ::core::marker::StructuralEq for Enum1 {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Enum1 { }
#[automatically_derived]
impl ::core::cmp::Eq for Enum1 {
#[inline]
@@ -676,13 +692,15 @@ impl ::core::default::Default for Fieldless1 {
impl ::core::hash::Hash for Fieldless1 {
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {}
}
-impl ::core::marker::StructuralPartialEq for Fieldless1 {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Fieldless1 { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Fieldless1 {
#[inline]
fn eq(&self, other: &Fieldless1) -> bool { true }
}
-impl ::core::marker::StructuralEq for Fieldless1 {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Fieldless1 { }
#[automatically_derived]
impl ::core::cmp::Eq for Fieldless1 {
#[inline]
@@ -743,7 +761,8 @@ impl ::core::hash::Hash for Fieldless {
::core::hash::Hash::hash(&__self_tag, state)
}
}
-impl ::core::marker::StructuralPartialEq for Fieldless {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Fieldless { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Fieldless {
#[inline]
@@ -753,7 +772,8 @@ impl ::core::cmp::PartialEq for Fieldless {
__self_tag == __arg1_tag
}
}
-impl ::core::marker::StructuralEq for Fieldless {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Fieldless { }
#[automatically_derived]
impl ::core::cmp::Eq for Fieldless {
#[inline]
@@ -840,7 +860,8 @@ impl ::core::hash::Hash for Mixed {
}
}
}
-impl ::core::marker::StructuralPartialEq for Mixed {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Mixed { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Mixed {
#[inline]
@@ -858,7 +879,8 @@ impl ::core::cmp::PartialEq for Mixed {
}
}
}
-impl ::core::marker::StructuralEq for Mixed {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Mixed { }
#[automatically_derived]
impl ::core::cmp::Eq for Mixed {
#[inline]
@@ -967,7 +989,8 @@ impl ::core::hash::Hash for Fielded {
}
}
}
-impl ::core::marker::StructuralPartialEq for Fielded {}
+#[automatically_derived]
+impl ::core::marker::StructuralPartialEq for Fielded { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Fielded {
#[inline]
@@ -986,7 +1009,8 @@ impl ::core::cmp::PartialEq for Fielded {
}
}
}
-impl ::core::marker::StructuralEq for Fielded {}
+#[automatically_derived]
+impl ::core::marker::StructuralEq for Fielded { }
#[automatically_derived]
impl ::core::cmp::Eq for Fielded {
#[inline]
diff --git a/src/test/ui/deriving/deriving-default-enum.rs b/src/test/ui/deriving/deriving-default-enum.rs
index d1a81c72c..1c7a501ed 100644
--- a/src/test/ui/deriving/deriving-default-enum.rs
+++ b/src/test/ui/deriving/deriving-default-enum.rs
@@ -12,6 +12,16 @@ enum Foo {
Beta(NotDefault),
}
+// #[default] on a generic enum does not add `Default` bounds to the type params.
+#[derive(Default)]
+enum MyOption<T> {
+ #[default]
+ None,
+ #[allow(dead_code)]
+ Some(T),
+}
+
fn main() {
assert_eq!(Foo::default(), Foo::Alpha);
+ assert!(matches!(MyOption::<NotDefault>::default(), MyOption::None));
}
diff --git a/src/test/ui/deriving/deriving-hash.rs b/src/test/ui/deriving/deriving-hash.rs
index 8b51370bc..16738ec4a 100644
--- a/src/test/ui/deriving/deriving-hash.rs
+++ b/src/test/ui/deriving/deriving-hash.rs
@@ -44,6 +44,17 @@ fn fake_hash<A: Hash>(v: &mut Vec<u8>, a: A) {
a.hash(&mut FakeHasher(v));
}
+struct OnlyOneByteHasher;
+impl Hasher for OnlyOneByteHasher {
+ fn finish(&self) -> u64 {
+ unreachable!()
+ }
+
+ fn write(&mut self, bytes: &[u8]) {
+ assert_eq!(bytes.len(), 1);
+ }
+}
+
fn main() {
let person1 = Person {
id: 5,
@@ -73,4 +84,13 @@ fn main() {
let mut v = vec![];
fake_hash(&mut v, SingleVariantEnum::A(17));
assert_eq!(vec![17], v);
+
+ // issue #39137
+ #[repr(u8)]
+ #[derive(Hash)]
+ enum E {
+ A,
+ B,
+ }
+ E::A.hash(&mut OnlyOneByteHasher);
}
diff --git a/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr b/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr
index 1df7a5f22..e16625136 100644
--- a/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr
+++ b/src/test/ui/destructuring-assignment/warn-unused-duplication.stderr
@@ -4,12 +4,12 @@ warning: value assigned to `a` is never read
LL | (a, a) = (0, 1);
| ^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/warn-unused-duplication.rs:3:9
|
LL | #![warn(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
- = help: maybe it is overwritten before being read?
warning: 1 warning emitted
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
index 2326af934..21f957ab5 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -105,9 +105,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | type H = Fn(u8) -> (u8)::Output;
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | type H = <dyn Fn(u8) -> (u8)>::Output;
diff --git a/src/test/ui/did_you_mean/issue-31424.stderr b/src/test/ui/did_you_mean/issue-31424.stderr
index 886173812..8fe38bf69 100644
--- a/src/test/ui/did_you_mean/issue-31424.stderr
+++ b/src/test/ui/did_you_mean/issue-31424.stderr
@@ -24,8 +24,8 @@ LL | fn bar(self: &mut Self) {
LL | (&mut self).bar();
| ----------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-31424.rs:16:9
diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed
index 87debfece..e566ed488 100644
--- a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed
+++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.fixed
@@ -2,4 +2,9 @@
fn main() {
let _x = !1; //~ ERROR cannot be used as a unary operator
+ let _y = !1; //~ ERROR unexpected `1` after identifier
+ let _z = !false; //~ ERROR unexpected keyword `false` after identifier
+ let _a = !true; //~ ERROR unexpected keyword `true` after identifier
+ let v = 1 + 2;
+ let _v = !v; //~ ERROR unexpected `v` after identifier
}
diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs
index 015a8edce..1708a8050 100644
--- a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs
+++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.rs
@@ -2,4 +2,9 @@
fn main() {
let _x = ~1; //~ ERROR cannot be used as a unary operator
+ let _y = not 1; //~ ERROR unexpected `1` after identifier
+ let _z = not false; //~ ERROR unexpected keyword `false` after identifier
+ let _a = not true; //~ ERROR unexpected keyword `true` after identifier
+ let v = 1 + 2;
+ let _v = not v; //~ ERROR unexpected `v` after identifier
}
diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr
index 84b81d561..2a3242abe 100644
--- a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr
+++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr
@@ -4,5 +4,37 @@ error: `~` cannot be used as a unary operator
LL | let _x = ~1;
| ^ help: use `!` to perform bitwise not
-error: aborting due to previous error
+error: unexpected `1` after identifier
+ --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:5:18
+ |
+LL | let _y = not 1;
+ | ----^
+ | |
+ | help: use `!` to perform bitwise not
+
+error: unexpected keyword `false` after identifier
+ --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:6:18
+ |
+LL | let _z = not false;
+ | ----^^^^^
+ | |
+ | help: use `!` to perform logical negation
+
+error: unexpected keyword `true` after identifier
+ --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:7:18
+ |
+LL | let _a = not true;
+ | ----^^^^
+ | |
+ | help: use `!` to perform logical negation
+
+error: unexpected `v` after identifier
+ --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:9:18
+ |
+LL | let _v = not v;
+ | ----^
+ | |
+ | help: use `!` to perform logical negation or bitwise not
+
+error: aborting due to 5 previous errors
diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
index bca493e67..9dde5b3eb 100644
--- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
+++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr
@@ -1,11 +1,3 @@
-error[E0423]: expected function, tuple struct or tuple variant, found enum `Option`
- --> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
- |
-LL | let x = Option(1);
- | ^^^^^^ help: try to construct one of the enum's variants: `std::option::Option::Some`
- |
- = help: you might have meant to construct the enum's non-tuple variant
-
error[E0532]: expected tuple struct or tuple variant, found enum `Option`
--> $DIR/issue-43871-enum-instead-of-variant.rs:21:12
|
@@ -27,6 +19,14 @@ note: the enum is defined here
LL | enum Example { Ex(String), NotEx }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+error[E0423]: expected function, tuple struct or tuple variant, found enum `Option`
+ --> $DIR/issue-43871-enum-instead-of-variant.rs:19:13
+ |
+LL | let x = Option(1);
+ | ^^^^^^ help: try to construct one of the enum's variants: `std::option::Option::Some`
+ |
+ = help: you might have meant to construct the enum's non-tuple variant
+
error[E0423]: expected function, tuple struct or tuple variant, found enum `Void`
--> $DIR/issue-43871-enum-instead-of-variant.rs:31:13
|
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
index 3ccc14bba..14918ba89 100644
--- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -4,7 +4,7 @@ error: unexpected `for_you` after identifier
LL | if not for_you {
| ----^^^^^^^
| |
- | help: use `!` to perform logical negation
+ | help: use `!` to perform logical negation or bitwise not
error: unexpected `the_worst` after identifier
--> $DIR/issue-46836-identifier-not-instead-of-negation.rs:11:15
@@ -12,13 +12,13 @@ error: unexpected `the_worst` after identifier
LL | while not the_worst {
| ----^^^^^^^^^
| |
- | help: use `!` to perform logical negation
+ | help: use `!` to perform logical negation or bitwise not
error: unexpected `println` after identifier
--> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:9
|
LL | if not // lack of braces is [sic]
- | ----- help: use `!` to perform logical negation
+ | ----- help: use `!` to perform logical negation or bitwise not
LL | println!("Then when?");
| ^^^^^^^
@@ -42,7 +42,7 @@ error: unexpected `2` after identifier
LL | let resource = not 2;
| ----^
| |
- | help: use `!` to perform logical negation
+ | help: use `!` to perform bitwise not
error: unexpected `be_smothered_out_before` after identifier
--> $DIR/issue-46836-identifier-not-instead-of-negation.rs:32:27
@@ -50,7 +50,7 @@ error: unexpected `be_smothered_out_before` after identifier
LL | let young_souls = not be_smothered_out_before;
| ----^^^^^^^^^^^^^^^^^^^^^^^
| |
- | help: use `!` to perform logical negation
+ | help: use `!` to perform logical negation or bitwise not
error: aborting due to 6 previous errors
diff --git a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
index 26986684f..81f3f2694 100644
--- a/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
+++ b/src/test/ui/did_you_mean/issue-49746-unicode-confusable-in-float-literal-expt.stderr
@@ -15,13 +15,13 @@ help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it
LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻²
| ~
-error[E0277]: cannot subtract `{integer}` from `{float}`
+error[E0277]: cannot subtract `{integer}` from `{float}` in const contexts
--> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53
|
LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
| ^ no implementation for `{float} - {integer}`
|
- = help: the trait `Sub<{integer}>` is not implemented for `{float}`
+ = help: the trait `~const Sub<{integer}>` is not implemented for `{float}`
= help: the following other types implement trait `Sub<Rhs>`:
<&'a f32 as Sub<f32>>
<&'a f64 as Sub<f64>>
diff --git a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
index 528c62f50..cbe59e8e0 100644
--- a/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
+++ b/src/test/ui/did_you_mean/issue-54109-and_instead_of_ampersands.stderr
@@ -4,7 +4,7 @@ error: `and` is not a logical operator
LL | let _ = a and b;
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
@@ -12,7 +12,7 @@ error: `and` is not a logical operator
LL | if a and b {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
@@ -20,7 +20,7 @@ error: `or` is not a logical operator
LL | let _ = a or b;
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
@@ -28,7 +28,7 @@ error: `or` is not a logical operator
LL | if a or b {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
@@ -36,7 +36,7 @@ error: `and` is not a logical operator
LL | if (a and b) {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
@@ -44,7 +44,7 @@ error: `or` is not a logical operator
LL | if (a or b) {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
@@ -52,7 +52,7 @@ error: `and` is not a logical operator
LL | while a and b {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
@@ -60,7 +60,7 @@ error: `or` is not a logical operator
LL | while a or b {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error[E0308]: mismatched types
--> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
diff --git a/src/test/ui/did_you_mean/issue-54109-without-witness.stderr b/src/test/ui/did_you_mean/issue-54109-without-witness.stderr
index 0350890c1..6455b0863 100644
--- a/src/test/ui/did_you_mean/issue-54109-without-witness.stderr
+++ b/src/test/ui/did_you_mean/issue-54109-without-witness.stderr
@@ -4,7 +4,7 @@ error: `and` is not a logical operator
LL | let _ = a and b;
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:15:10
@@ -12,7 +12,7 @@ error: `and` is not a logical operator
LL | if a and b {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:24:15
@@ -20,7 +20,7 @@ error: `or` is not a logical operator
LL | let _ = a or b;
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:26:10
@@ -28,7 +28,7 @@ error: `or` is not a logical operator
LL | if a or b {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:34:11
@@ -36,7 +36,7 @@ error: `and` is not a logical operator
LL | if (a and b) {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:42:11
@@ -44,7 +44,7 @@ error: `or` is not a logical operator
LL | if (a or b) {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `and` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:50:13
@@ -52,7 +52,7 @@ error: `and` is not a logical operator
LL | while a and b {
| ^^^ help: use `&&` to perform logical conjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: `or` is not a logical operator
--> $DIR/issue-54109-without-witness.rs:58:13
@@ -60,7 +60,7 @@ error: `or` is not a logical operator
LL | while a or b {
| ^^ help: use `||` to perform logical disjunction
|
- = note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+ = note: unlike in e.g., Python and PHP, `&&` and `||` are used for logical operators
error: aborting due to 8 previous errors
diff --git a/src/test/ui/drop/drop_order.rs b/src/test/ui/drop/drop_order.rs
index e42150dcc..42385216a 100644
--- a/src/test/ui/drop/drop_order.rs
+++ b/src/test/ui/drop/drop_order.rs
@@ -1,4 +1,6 @@
// run-pass
+// compile-flags: -Z validate-mir
+#![feature(let_chains)]
use std::cell::RefCell;
use std::convert::TryInto;
@@ -116,6 +118,58 @@ impl DropOrderCollector {
}
}
+ fn let_chain(&self) {
+ // take the "then" branch
+ if self.option_loud_drop(2).is_some() // 2
+ && self.option_loud_drop(1).is_some() // 1
+ && let Some(_d) = self.option_loud_drop(4) { // 4
+ self.print(3); // 3
+ }
+
+ // take the "else" branch
+ if self.option_loud_drop(6).is_some() // 2
+ && self.option_loud_drop(5).is_some() // 1
+ && let None = self.option_loud_drop(8) { // 4
+ unreachable!();
+ } else {
+ self.print(7); // 3
+ }
+
+ // let exprs interspersed
+ if self.option_loud_drop(9).is_some() // 1
+ && let Some(_d) = self.option_loud_drop(13) // 5
+ && self.option_loud_drop(10).is_some() // 2
+ && let Some(_e) = self.option_loud_drop(12) { // 4
+ self.print(11); // 3
+ }
+
+ // let exprs first
+ if let Some(_d) = self.option_loud_drop(18) // 5
+ && let Some(_e) = self.option_loud_drop(17) // 4
+ && self.option_loud_drop(14).is_some() // 1
+ && self.option_loud_drop(15).is_some() { // 2
+ self.print(16); // 3
+ }
+
+ // let exprs last
+ if self.option_loud_drop(20).is_some() // 2
+ && self.option_loud_drop(19).is_some() // 1
+ && let Some(_d) = self.option_loud_drop(23) // 5
+ && let Some(_e) = self.option_loud_drop(22) { // 4
+ self.print(21); // 3
+ }
+ }
+
+ fn while_(&self) {
+ let mut v = self.option_loud_drop(4);
+ while let Some(_d) = v
+ && self.option_loud_drop(1).is_some()
+ && self.option_loud_drop(2).is_some() {
+ self.print(3);
+ v = None;
+ }
+ }
+
fn assert_sorted(self) {
assert!(
self.0
@@ -142,4 +196,14 @@ fn main() {
let collector = DropOrderCollector::default();
collector.match_();
collector.assert_sorted();
+
+ println!("-- let chain --");
+ let collector = DropOrderCollector::default();
+ collector.let_chain();
+ collector.assert_sorted();
+
+ println!("-- while --");
+ let collector = DropOrderCollector::default();
+ collector.while_();
+ collector.assert_sorted();
}
diff --git a/src/test/ui/drop/dropck_legal_cycles.rs b/src/test/ui/drop/dropck_legal_cycles.rs
index 27a599315..6a0fe7784 100644
--- a/src/test/ui/drop/dropck_legal_cycles.rs
+++ b/src/test/ui/drop/dropck_legal_cycles.rs
@@ -1017,7 +1017,7 @@ impl<'a> Children<'a> for HM<'a> {
where C: Context + PrePost<Self>, Self: Sized
{
if let Some(ref hm) = self.contents.get() {
- for (k, v) in hm.iter().nth(index / 2) {
+ if let Some((k, v)) = hm.iter().nth(index / 2) {
[k, v][index % 2].descend_into_self(context);
}
}
@@ -1032,7 +1032,7 @@ impl<'a> Children<'a> for VD<'a> {
where C: Context + PrePost<Self>, Self: Sized
{
if let Some(ref vd) = self.contents.get() {
- for r in vd.iter().nth(index) {
+ if let Some(r) = vd.iter().nth(index) {
r.descend_into_self(context);
}
}
@@ -1047,7 +1047,7 @@ impl<'a> Children<'a> for VM<'a> {
where C: Context + PrePost<VM<'a>>
{
if let Some(ref vd) = self.contents.get() {
- for (_idx, r) in vd.iter().nth(index) {
+ if let Some((_idx, r)) = vd.iter().nth(index) {
r.descend_into_self(context);
}
}
@@ -1062,7 +1062,7 @@ impl<'a> Children<'a> for LL<'a> {
where C: Context + PrePost<LL<'a>>
{
if let Some(ref ll) = self.contents.get() {
- for r in ll.iter().nth(index) {
+ if let Some(r) = ll.iter().nth(index) {
r.descend_into_self(context);
}
}
@@ -1077,7 +1077,7 @@ impl<'a> Children<'a> for BH<'a> {
where C: Context + PrePost<BH<'a>>
{
if let Some(ref bh) = self.contents.get() {
- for r in bh.iter().nth(index) {
+ if let Some(r) = bh.iter().nth(index) {
r.descend_into_self(context);
}
}
@@ -1092,7 +1092,7 @@ impl<'a> Children<'a> for BTM<'a> {
where C: Context + PrePost<BTM<'a>>
{
if let Some(ref bh) = self.contents.get() {
- for (k, v) in bh.iter().nth(index / 2) {
+ if let Some((k, v)) = bh.iter().nth(index / 2) {
[k, v][index % 2].descend_into_self(context);
}
}
@@ -1107,7 +1107,7 @@ impl<'a> Children<'a> for BTS<'a> {
where C: Context + PrePost<BTS<'a>>
{
if let Some(ref bh) = self.contents.get() {
- for r in bh.iter().nth(index) {
+ if let Some(r) = bh.iter().nth(index) {
r.descend_into_self(context);
}
}
diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs
index 13bd71ecb..8f1cc6691 100644
--- a/src/test/ui/drop/dynamic-drop-async.rs
+++ b/src/test/ui/drop/dynamic-drop-async.rs
@@ -6,7 +6,6 @@
// run-pass
// needs-unwind
// edition:2018
-// ignore-wasm32-bare compiled with panic=abort by default
#![allow(unused)]
diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs
index e70686774..9e51d3ada 100644
--- a/src/test/ui/drop/dynamic-drop.rs
+++ b/src/test/ui/drop/dynamic-drop.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/drop/issue-100276.rs b/src/test/ui/drop/issue-100276.rs
new file mode 100644
index 000000000..6401a8d14
--- /dev/null
+++ b/src/test/ui/drop/issue-100276.rs
@@ -0,0 +1,12 @@
+// check-pass
+// compile-flags: -Z validate-mir
+#![feature(let_chains)]
+
+fn let_chains(entry: std::io::Result<std::fs::DirEntry>) {
+ if let Ok(entry) = entry
+ && let Some(s) = entry.file_name().to_str()
+ && s.contains("")
+ {}
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-17718-const-destructors.rs b/src/test/ui/drop/issue-17718-const-destructors.rs
index c9a729c7b..c9a729c7b 100644
--- a/src/test/ui/issues/issue-17718-const-destructors.rs
+++ b/src/test/ui/drop/issue-17718-const-destructors.rs
diff --git a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs b/src/test/ui/drop/issue-23338-ensure-param-drop-order.rs
index a99f260dd..a99f260dd 100644
--- a/src/test/ui/issues/issue-23338-ensure-param-drop-order.rs
+++ b/src/test/ui/drop/issue-23338-ensure-param-drop-order.rs
diff --git a/src/test/ui/issues/issue-48962.rs b/src/test/ui/drop/issue-48962.rs
index 80d815379..80d815379 100644
--- a/src/test/ui/issues/issue-48962.rs
+++ b/src/test/ui/drop/issue-48962.rs
diff --git a/src/test/ui/drop/repeat-drop-2.rs b/src/test/ui/drop/repeat-drop-2.rs
index 59d5ef202..3cfacea5e 100644
--- a/src/test/ui/drop/repeat-drop-2.rs
+++ b/src/test/ui/drop/repeat-drop-2.rs
@@ -5,7 +5,7 @@ fn borrowck_catch() {
}
const _: [String; 0] = [String::new(); 0];
-//~^ ERROR destructors cannot be evaluated at compile-time [E0493]
+//~^ ERROR destructor of `String` cannot be evaluated at compile-time [E0493]
fn must_be_init() {
let x: u8;
diff --git a/src/test/ui/drop/repeat-drop-2.stderr b/src/test/ui/drop/repeat-drop-2.stderr
index 48fa2bfa9..7357551c4 100644
--- a/src/test/ui/drop/repeat-drop-2.stderr
+++ b/src/test/ui/drop/repeat-drop-2.stderr
@@ -8,13 +8,13 @@ LL | let _bar = foo;
LL | let _baz = [foo; 0];
| ^^^ value used here after move
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
--> $DIR/repeat-drop-2.rs:7:25
|
LL | const _: [String; 0] = [String::new(); 0];
| -^^^^^^^^^^^^^----
| ||
- | |constants cannot evaluate destructors
+ | |the destructor for this type cannot be evaluated in constants
| value is dropped here
error[E0381]: used binding `x` isn't initialized
@@ -24,6 +24,11 @@ LL | let x: u8;
| - binding declared here but left uninitialized
LL | let _ = [x; 0];
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x: u8 = 0;
+ | +++
error: aborting due to 3 previous errors
diff --git a/src/test/ui/drop/repeat-drop.rs b/src/test/ui/drop/repeat-drop.rs
index a43612e5d..8fd46ecaf 100644
--- a/src/test/ui/drop/repeat-drop.rs
+++ b/src/test/ui/drop/repeat-drop.rs
@@ -1,8 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare no unwinding panic
-// ignore-avr no unwinding panic
-// ignore-nvptx64 no unwinding panic
static mut CHECK: usize = 0;
diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
index 49e55be1b..82169ee01 100644
--- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
+++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr
@@ -8,6 +8,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on A)
LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
LL | | }
| |_^
+ |
+ = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt<A, B> {
+ | ++++++
error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute
--> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1
@@ -19,6 +25,12 @@ LL | | // (unsafe to access self.1 due to #[may_dangle] on 'a)
LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); }
LL | | }
| |_^
+ |
+ = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> {
+ | ++++++
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-24805-dropck-itemless.rs b/src/test/ui/dropck/issue-24805-dropck-itemless.rs
index 45761b61c..45761b61c 100644
--- a/src/test/ui/issues/issue-24805-dropck-itemless.rs
+++ b/src/test/ui/dropck/issue-24805-dropck-itemless.rs
diff --git a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
index 3eb5bb7b2..89aded913 100644
--- a/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
+++ b/src/test/ui/dyn-keyword/dyn-2015-edition-keyword-ident-lint.stderr
@@ -4,13 +4,13 @@ error: `dyn` is a keyword in the 2018 edition
LL | pub mod dyn {
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:11:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: `dyn` is a keyword in the 2018 edition
--> $DIR/dyn-2015-edition-keyword-ident-lint.rs:17:20
diff --git a/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr b/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr
index e7db68693..6bafff919 100644
--- a/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr
+++ b/src/test/ui/dyn-keyword/dyn-2018-edition-lint.stderr
@@ -4,13 +4,13 @@ error: trait objects without an explicit `dyn` are deprecated
LL | fn function(x: &SomeTrait, y: Box<SomeTrait>) {
| ^^^^^^^^^
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/dyn-2018-edition-lint.rs:2:8
|
LL | #[deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
help: use `dyn`
|
LL | fn function(x: &dyn SomeTrait, y: Box<SomeTrait>) {
diff --git a/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr b/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr
index 261c2d574..0bb764d71 100644
--- a/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr
+++ b/src/test/ui/dyn-keyword/dyn-angle-brackets.stderr
@@ -4,13 +4,13 @@ error: trait objects without an explicit `dyn` are deprecated
LL | <fmt::Debug>::fmt(self, f)
| ^^^^^^^^^^
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/dyn-angle-brackets.rs:4:9
|
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
help: use `dyn`
|
LL | <dyn fmt::Debug>::fmt(self, f)
diff --git a/src/test/ui/dyn-star/auxiliary/dyn-star-foreign.rs b/src/test/ui/dyn-star/auxiliary/dyn-star-foreign.rs
new file mode 100644
index 000000000..7673c7936
--- /dev/null
+++ b/src/test/ui/dyn-star/auxiliary/dyn-star-foreign.rs
@@ -0,0 +1,10 @@
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+
+pub fn require_dyn_star_display(_: dyn* Display) {}
+
+fn works_locally() {
+ require_dyn_star_display(1usize);
+}
diff --git a/src/test/ui/dyn-star/box.rs b/src/test/ui/dyn-star/box.rs
new file mode 100644
index 000000000..d1f1819d9
--- /dev/null
+++ b/src/test/ui/dyn-star/box.rs
@@ -0,0 +1,17 @@
+// run-pass
+// compile-flags: -C opt-level=0
+
+#![feature(dyn_star)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+
+fn make_dyn_star() -> dyn* Display {
+ Box::new(42) as dyn* Display
+}
+
+fn main() {
+ let x = make_dyn_star();
+
+ println!("{x}");
+}
diff --git a/src/test/ui/dyn-star/const.rs b/src/test/ui/dyn-star/const.rs
index e49caf649..67e3ab7ab 100644
--- a/src/test/ui/dyn-star/const.rs
+++ b/src/test/ui/dyn-star/const.rs
@@ -6,7 +6,7 @@ use std::fmt::Debug;
fn make_dyn_star() {
let i = 42usize;
- let dyn_i: dyn* Debug = i as dyn* Debug;
+ let dyn_i: dyn* Debug = i;
}
fn main() {
diff --git a/src/test/ui/dyn-star/drop.rs b/src/test/ui/dyn-star/drop.rs
index 46b232f3d..1478498c0 100644
--- a/src/test/ui/dyn-star/drop.rs
+++ b/src/test/ui/dyn-star/drop.rs
@@ -15,7 +15,7 @@ impl Drop for Foo {
}
fn make_dyn_star(i: Foo) {
- let _dyn_i: dyn* Debug = i as dyn* Debug;
+ let _dyn_i: dyn* Debug = i;
}
fn main() {
diff --git a/src/test/ui/dyn-star/error.rs b/src/test/ui/dyn-star/error.rs
index 33eff80a5..d8261387e 100644
--- a/src/test/ui/dyn-star/error.rs
+++ b/src/test/ui/dyn-star/error.rs
@@ -7,7 +7,7 @@ trait Foo {}
fn make_dyn_star() {
let i = 42;
- let dyn_i: dyn* Foo = i as dyn* Foo; //~ ERROR trait bound `{integer}: Foo` is not satisfied
+ let dyn_i: dyn* Foo = i; //~ ERROR trait bound `{integer}: Foo` is not satisfied
}
fn main() {}
diff --git a/src/test/ui/dyn-star/error.stderr b/src/test/ui/dyn-star/error.stderr
index d612ccc63..ae54b9ca7 100644
--- a/src/test/ui/dyn-star/error.stderr
+++ b/src/test/ui/dyn-star/error.stderr
@@ -1,7 +1,7 @@
error[E0277]: the trait bound `{integer}: Foo` is not satisfied
--> $DIR/error.rs:10:27
|
-LL | let dyn_i: dyn* Foo = i as dyn* Foo;
+LL | let dyn_i: dyn* Foo = i;
| ^ the trait `Foo` is not implemented for `{integer}`
error: aborting due to previous error
diff --git a/src/test/ui/dyn-star/make-dyn-star.rs b/src/test/ui/dyn-star/make-dyn-star.rs
index 708ffa25d..e5255a64b 100644
--- a/src/test/ui/dyn-star/make-dyn-star.rs
+++ b/src/test/ui/dyn-star/make-dyn-star.rs
@@ -5,9 +5,14 @@
use std::fmt::Debug;
fn make_dyn_star(i: usize) {
+ let _dyn_i: dyn* Debug = i;
+}
+
+fn make_dyn_star_explicit(i: usize) {
let _dyn_i: dyn* Debug = i as dyn* Debug;
}
fn main() {
make_dyn_star(42);
+ make_dyn_star_explicit(42);
}
diff --git a/src/test/ui/dyn-star/method.rs b/src/test/ui/dyn-star/method.rs
index d04958ca2..5a77640f0 100644
--- a/src/test/ui/dyn-star/method.rs
+++ b/src/test/ui/dyn-star/method.rs
@@ -1,4 +1,5 @@
// run-pass
+
#![feature(dyn_star)]
#![allow(incomplete_features)]
@@ -17,7 +18,7 @@ fn invoke_dyn_star(i: dyn* Foo) -> usize {
}
fn make_and_invoke_dyn_star(i: usize) -> usize {
- let dyn_i: dyn* Foo = i as dyn* Foo;
+ let dyn_i: dyn* Foo = i;
invoke_dyn_star(dyn_i)
}
diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs
new file mode 100644
index 000000000..67240c8e8
--- /dev/null
+++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.rs
@@ -0,0 +1,13 @@
+use std::fmt::Debug;
+
+fn make_dyn_star() {
+ let i = 42usize;
+ let dyn_i: dyn* Debug = i as dyn* Debug;
+ //~^ ERROR casting `usize` as `dyn* Debug` is invalid
+ //~| ERROR dyn* trait objects are unstable
+ //~| ERROR dyn* trait objects are unstable
+}
+
+fn main() {
+ make_dyn_star();
+}
diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr
new file mode 100644
index 000000000..687d7db04
--- /dev/null
+++ b/src/test/ui/dyn-star/no-explicit-dyn-star-cast.stderr
@@ -0,0 +1,28 @@
+error[E0658]: dyn* trait objects are unstable
+ --> $DIR/no-explicit-dyn-star-cast.rs:5:16
+ |
+LL | let dyn_i: dyn* Debug = i as dyn* Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(dyn_star)]` to the crate attributes to enable
+
+error[E0658]: dyn* trait objects are unstable
+ --> $DIR/no-explicit-dyn-star-cast.rs:5:34
+ |
+LL | let dyn_i: dyn* Debug = i as dyn* Debug;
+ | ^^^^^^^^^^
+ |
+ = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+ = help: add `#![feature(dyn_star)]` to the crate attributes to enable
+
+error[E0606]: casting `usize` as `dyn* Debug` is invalid
+ --> $DIR/no-explicit-dyn-star-cast.rs:5:29
+ |
+LL | let dyn_i: dyn* Debug = i as dyn* Debug;
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0606, E0658.
+For more information about an error, try `rustc --explain E0606`.
diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star.rs b/src/test/ui/dyn-star/no-explicit-dyn-star.rs
new file mode 100644
index 000000000..4f726b7c6
--- /dev/null
+++ b/src/test/ui/dyn-star/no-explicit-dyn-star.rs
@@ -0,0 +1,8 @@
+// aux-build:dyn-star-foreign.rs
+
+extern crate dyn_star_foreign;
+
+fn main() {
+ dyn_star_foreign::require_dyn_star_display(1usize as _);
+ //~^ ERROR casting `usize` as `dyn* std::fmt::Display` is invalid
+}
diff --git a/src/test/ui/dyn-star/no-explicit-dyn-star.stderr b/src/test/ui/dyn-star/no-explicit-dyn-star.stderr
new file mode 100644
index 000000000..49706fae1
--- /dev/null
+++ b/src/test/ui/dyn-star/no-explicit-dyn-star.stderr
@@ -0,0 +1,9 @@
+error[E0606]: casting `usize` as `dyn* std::fmt::Display` is invalid
+ --> $DIR/no-explicit-dyn-star.rs:6:48
+ |
+LL | dyn_star_foreign::require_dyn_star_display(1usize as _);
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0606`.
diff --git a/src/test/ui/dyn-star/no-implicit-dyn-star.rs b/src/test/ui/dyn-star/no-implicit-dyn-star.rs
new file mode 100644
index 000000000..d9470e284
--- /dev/null
+++ b/src/test/ui/dyn-star/no-implicit-dyn-star.rs
@@ -0,0 +1,8 @@
+// aux-build:dyn-star-foreign.rs
+
+extern crate dyn_star_foreign;
+
+fn main() {
+ dyn_star_foreign::require_dyn_star_display(1usize);
+ //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/dyn-star/no-implicit-dyn-star.stderr b/src/test/ui/dyn-star/no-implicit-dyn-star.stderr
new file mode 100644
index 000000000..e7c591862
--- /dev/null
+++ b/src/test/ui/dyn-star/no-implicit-dyn-star.stderr
@@ -0,0 +1,19 @@
+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 std::fmt::Display`, found `usize`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected trait object `(dyn* std::fmt::Display + 'static)`
+ found type `usize`
+note: function defined here
+ --> $DIR/auxiliary/dyn-star-foreign.rs:6:8
+ |
+LL | pub fn require_dyn_star_display(_: dyn* Display) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/dyn-star/upcast.rs b/src/test/ui/dyn-star/upcast.rs
new file mode 100644
index 000000000..cee76ada7
--- /dev/null
+++ b/src/test/ui/dyn-star/upcast.rs
@@ -0,0 +1,33 @@
+// run-pass
+
+#![feature(dyn_star, trait_upcasting)]
+#![allow(incomplete_features)]
+
+trait Foo: Bar {
+ fn hello(&self);
+}
+
+trait Bar {
+ fn world(&self);
+}
+
+struct W(usize);
+
+impl Foo for W {
+ fn hello(&self) {
+ println!("hello!");
+ }
+}
+
+impl Bar for W {
+ fn world(&self) {
+ println!("world!");
+ }
+}
+
+fn main() {
+ let w: dyn* Foo = W(0);
+ w.hello();
+ let w: dyn* Bar = w;
+ w.world();
+}
diff --git a/src/test/ui/editions/edition-raw-pointer-method-2015.stderr b/src/test/ui/editions/edition-raw-pointer-method-2015.stderr
index 417daf36f..612dd17e7 100644
--- a/src/test/ui/editions/edition-raw-pointer-method-2015.stderr
+++ b/src/test/ui/editions/edition-raw-pointer-method-2015.stderr
@@ -4,14 +4,14 @@ error: type annotations needed
LL | let _ = y.is_null();
| ^^^^^^^
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
note: the lint level is defined here
--> $DIR/edition-raw-pointer-method-2015.rs:5:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
= note: `#[deny(tyvar_behind_raw_pointer)]` implied by `#[deny(warnings)]`
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
error: aborting due to previous error
diff --git a/src/test/ui/empty/empty-attributes.stderr b/src/test/ui/empty/empty-attributes.stderr
index 8653eaf5c..01d0d5a6b 100644
--- a/src/test/ui/empty/empty-attributes.stderr
+++ b/src/test/ui/empty/empty-attributes.stderr
@@ -4,12 +4,12 @@ error: unused attribute
LL | #[repr()]
| ^^^^^^^^^ help: remove this attribute
|
+ = note: attribute `repr` with an empty list has no effect
note: the lint level is defined here
--> $DIR/empty-attributes.rs:3:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = note: attribute `repr` with an empty list has no effect
error: unused attribute
--> $DIR/empty-attributes.rs:14:1
diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr
index 5fc0a916a..5b0ca613f 100644
--- a/src/test/ui/empty/empty-struct-braces-expr.stderr
+++ b/src/test/ui/empty/empty-struct-braces-expr.stderr
@@ -21,29 +21,6 @@ help: a unit struct with a similar name exists
LL | let e1 = XEmpty2;
| ~~~~~~~
-error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
- --> $DIR/empty-struct-braces-expr.rs:16:14
- |
-LL | struct Empty1 {}
- | ---------------- `Empty1` defined here
-...
-LL | let e1 = Empty1();
- | ^^^^^^^^
- |
- ::: $DIR/auxiliary/empty-struct.rs:2:1
- |
-LL | pub struct XEmpty2;
- | ------------------ similarly named unit struct `XEmpty2` defined here
- |
-help: use struct literal syntax instead
- |
-LL | let e1 = Empty1 {};
- | ~~~~~~~~~
-help: a unit struct with a similar name exists
- |
-LL | let e1 = XEmpty2();
- | ~~~~~~~
-
error[E0423]: expected value, found struct variant `E::Empty3`
--> $DIR/empty-struct-braces-expr.rs:18:14
|
@@ -84,6 +61,29 @@ help: a unit struct with a similar name exists
LL | let xe1 = XEmpty2;
| ~~~~~~~
+error[E0423]: expected function, tuple struct or tuple variant, found struct `Empty1`
+ --> $DIR/empty-struct-braces-expr.rs:16:14
+ |
+LL | struct Empty1 {}
+ | ---------------- `Empty1` defined here
+...
+LL | let e1 = Empty1();
+ | ^^^^^^^^
+ |
+ ::: $DIR/auxiliary/empty-struct.rs:2:1
+ |
+LL | pub struct XEmpty2;
+ | ------------------ similarly named unit struct `XEmpty2` defined here
+ |
+help: use struct literal syntax instead
+ |
+LL | let e1 = Empty1 {};
+ | ~~~~~~~~~
+help: a unit struct with a similar name exists
+ |
+LL | let e1 = XEmpty2();
+ | ~~~~~~~
+
error[E0423]: expected function, tuple struct or tuple variant, found struct `XEmpty1`
--> $DIR/empty-struct-braces-expr.rs:23:15
|
diff --git a/src/test/ui/empty_global_asm.rs b/src/test/ui/empty_global_asm.rs
index dbcc7be05..af13762d1 100644
--- a/src/test/ui/empty_global_asm.rs
+++ b/src/test/ui/empty_global_asm.rs
@@ -1,21 +1,8 @@
+// needs-asm-support
// run-pass
-#[allow(unused_imports)]
use std::arch::global_asm;
-#[cfg(target_arch = "x86")]
-global_asm!("");
-
-#[cfg(target_arch = "x86_64")]
-global_asm!("");
-
-#[cfg(target_arch = "arm")]
-global_asm!("");
-
-#[cfg(target_arch = "aarch64")]
-global_asm!("");
-
-#[cfg(target_arch = "mips")]
global_asm!("");
fn main() {}
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
index 4da7b5ab2..a6e5f70fd 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.rs
@@ -1,5 +1,4 @@
#![crate_type="lib"]
-#![feature(arbitrary_enum_discriminant)]
enum Enum {
//~^ ERROR `#[repr(inttype)]` must be specified
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
index 803bb06fc..8cee74696 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant-no-repr.stderr
@@ -1,5 +1,5 @@
error[E0732]: `#[repr(inttype)]` must be specified
- --> $DIR/arbitrary_enum_discriminant-no-repr.rs:4:1
+ --> $DIR/arbitrary_enum_discriminant-no-repr.rs:3:1
|
LL | enum Enum {
| ^^^^^^^^^
diff --git a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
index ccc423e4a..83e74a6e6 100644
--- a/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
+++ b/src/test/ui/enum-discriminant/arbitrary_enum_discriminant.rs
@@ -1,5 +1,5 @@
// run-pass
-#![feature(arbitrary_enum_discriminant, test)]
+#![feature(test)]
extern crate test;
diff --git a/src/test/ui/enum-discriminant/discriminant_size.stderr b/src/test/ui/enum-discriminant/discriminant_size.stderr
index efc7d9984..9b1505b5c 100644
--- a/src/test/ui/enum-discriminant/discriminant_size.stderr
+++ b/src/test/ui/enum-discriminant/discriminant_size.stderr
@@ -4,8 +4,8 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or c
LL | #![feature(core_intrinsics, repr128)]
| ^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/enum-discriminant/discriminant_value.rs b/src/test/ui/enum-discriminant/discriminant_value.rs
index 65ab411db..f3dfac298 100644
--- a/src/test/ui/enum-discriminant/discriminant_value.rs
+++ b/src/test/ui/enum-discriminant/discriminant_value.rs
@@ -1,6 +1,6 @@
// run-pass
#![allow(stable_features)]
-#![feature(arbitrary_enum_discriminant, core, core_intrinsics)]
+#![feature(core, core_intrinsics)]
extern crate core;
use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs
deleted file mode 100644
index 3e90af4d3..000000000
--- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-#![crate_type="lib"]
-
-enum Enum {
- Unit = 1,
- //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
- Tuple() = 2,
- //~^ ERROR discriminants on non-unit variants are experimental
- Struct{} = 3,
- //~^ ERROR discriminants on non-unit variants are experimental
-}
diff --git a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr b/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr
deleted file mode 100644
index b5f61e6e9..000000000
--- a/src/test/ui/enum-discriminant/feature-gate-arbitrary_enum_discriminant.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-error[E0658]: discriminants on non-unit variants are experimental
- --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:6:13
- |
-LL | Tuple() = 2,
- | ^
- |
- = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
- = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
-
-error[E0658]: discriminants on non-unit variants are experimental
- --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:8:14
- |
-LL | Struct{} = 3,
- | ^
- |
- = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
- = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
-
-error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
- --> $DIR/feature-gate-arbitrary_enum_discriminant.rs:4:10
- |
-LL | Unit = 1,
- | ^ disallowed custom discriminant
-LL |
-LL | Tuple() = 2,
- | ----------- tuple variant defined here
-LL |
-LL | Struct{} = 3,
- | ------------ struct variant defined here
- |
- = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
- = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/enum-discriminant/issue-43398.stderr b/src/test/ui/enum-discriminant/issue-43398.stderr
index 9a394153b..fc7bbd062 100644
--- a/src/test/ui/enum-discriminant/issue-43398.stderr
+++ b/src/test/ui/enum-discriminant/issue-43398.stderr
@@ -4,8 +4,8 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or c
LL | #![feature(repr128)]
| ^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
index f927dd189..ad9fcc25b 100644
--- a/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
+++ b/src/test/ui/enum-discriminant/issue-70453-generics-in-discr-ice-2.rs
@@ -1,4 +1,4 @@
-#![feature(arbitrary_enum_discriminant, core_intrinsics)]
+#![feature(core_intrinsics)]
extern crate core;
use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
index e62582fb5..42a062239 100644
--- a/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
+++ b/src/test/ui/enum-discriminant/issue-70453-polymorphic-ctfe.rs
@@ -1,4 +1,4 @@
-#![feature(arbitrary_enum_discriminant, core_intrinsics)]
+#![feature(core_intrinsics)]
extern crate core;
use core::intrinsics::discriminant_value;
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
index ae389e114..3adac7b72 100644
--- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.rs
@@ -1,5 +1,5 @@
// run-pass
-#![feature(repr128, arbitrary_enum_discriminant)]
+#![feature(repr128)]
//~^ WARN the feature `repr128` is incomplete
#[derive(PartialEq, Debug)]
diff --git a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
index 5bf6ea56e..2eef930c3 100644
--- a/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
+++ b/src/test/ui/enum-discriminant/issue-70509-partial_eq.stderr
@@ -1,11 +1,11 @@
warning: the feature `repr128` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/issue-70509-partial_eq.rs:2:12
|
-LL | #![feature(repr128, arbitrary_enum_discriminant)]
+LL | #![feature(repr128)]
| ^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/enum-discriminant/repr128.stderr b/src/test/ui/enum-discriminant/repr128.stderr
index 88adfb174..da8d75c11 100644
--- a/src/test/ui/enum-discriminant/repr128.stderr
+++ b/src/test/ui/enum-discriminant/repr128.stderr
@@ -4,8 +4,8 @@ warning: the feature `repr128` is incomplete and may not be safe to use and/or c
LL | #![feature(repr128, core_intrinsics, discriminant_kind)]
| ^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #56071 <https://github.com/rust-lang/rust/issues/56071> for more information
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr
index 438306795..f79f7a043 100644
--- a/src/test/ui/enum/enum-discrim-too-small2.stderr
+++ b/src/test/ui/enum/enum-discrim-too-small2.stderr
@@ -4,13 +4,13 @@ error: literal out of range for `i8`
LL | Ci8 = 223,
| ^^^
|
+ = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
note: the lint level is defined here
--> $DIR/enum-discrim-too-small2.rs:1:9
|
LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
error: literal out of range for `i16`
--> $DIR/enum-discrim-too-small2.rs:15:12
diff --git a/src/test/ui/error-codes/E0017.stderr b/src/test/ui/error-codes/E0017.stderr
index 830e4db34..6e48f9582 100644
--- a/src/test/ui/error-codes/E0017.stderr
+++ b/src/test/ui/error-codes/E0017.stderr
@@ -4,7 +4,6 @@ warning: taking a mutable reference to a `const` item
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^
|
- = note: `#[warn(const_item_mutation)]` on by default
= note: each usage of a `const` item creates a new temporary
= note: the mutable reference will refer to this temporary, not the original `const` item
note: `const` item defined here
@@ -12,6 +11,7 @@ note: `const` item defined here
|
LL | const C: i32 = 2;
| ^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
error[E0764]: mutable references are not allowed in the final value of constants
--> $DIR/E0017.rs:5:30
diff --git a/src/test/ui/error-codes/E0094.rs b/src/test/ui/error-codes/E0094.rs
index 0d58e5a28..a2ec932c1 100644
--- a/src/test/ui/error-codes/E0094.rs
+++ b/src/test/ui/error-codes/E0094.rs
@@ -1,5 +1,7 @@
#![feature(intrinsics)]
+
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T, U>() -> usize; //~ ERROR E0094
}
diff --git a/src/test/ui/error-codes/E0094.stderr b/src/test/ui/error-codes/E0094.stderr
index da97f3a01..531cd4c78 100644
--- a/src/test/ui/error-codes/E0094.stderr
+++ b/src/test/ui/error-codes/E0094.stderr
@@ -1,5 +1,5 @@
error[E0094]: intrinsic has wrong number of type parameters: found 2, expected 1
- --> $DIR/E0094.rs:3:15
+ --> $DIR/E0094.rs:5:15
|
LL | fn size_of<T, U>() -> usize;
| ^^^^^^ expected 1 type parameter
diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr
index 3632d26cd..99d808c0d 100644
--- a/src/test/ui/error-codes/E0199.stderr
+++ b/src/test/ui/error-codes/E0199.stderr
@@ -3,6 +3,12 @@ error[E0199]: implementing the trait `Bar` is not unsafe
|
LL | unsafe impl Bar for Foo { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: remove `unsafe` from this trait implementation
+ |
+LL - unsafe impl Bar for Foo { }
+LL + impl Bar for Foo { }
+ |
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr
index 677271aad..1fd86aece 100644
--- a/src/test/ui/error-codes/E0200.stderr
+++ b/src/test/ui/error-codes/E0200.stderr
@@ -3,6 +3,12 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration
|
LL | impl Bar for Foo { }
| ^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl Bar for Foo { }
+ | ++++++
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0201.rs b/src/test/ui/error-codes/E0201.rs
index adefd4bcd..04b37091b 100644
--- a/src/test/ui/error-codes/E0201.rs
+++ b/src/test/ui/error-codes/E0201.rs
@@ -2,7 +2,7 @@ struct Foo(u8);
impl Foo {
fn bar(&self) -> bool { self.0 > 5 }
- fn bar() {} //~ ERROR E0201
+ fn bar() {} //~ ERROR E0592
}
trait Baz {
diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr
index 94e068941..608ff6917 100644
--- a/src/test/ui/error-codes/E0201.stderr
+++ b/src/test/ui/error-codes/E0201.stderr
@@ -1,28 +1,35 @@
-error[E0201]: duplicate definitions with name `bar`:
- --> $DIR/E0201.rs:5:5
- |
-LL | fn bar(&self) -> bool { self.0 > 5 }
- | --------------------- previous definition of `bar` here
-LL | fn bar() {}
- | ^^^^^^^^ duplicate definition
-
error[E0201]: duplicate definitions with name `baz`:
--> $DIR/E0201.rs:17:5
|
+LL | fn baz(&self) -> bool;
+ | ---------------------- item in trait
+...
LL | fn baz(&self) -> bool { true }
- | --------------------- previous definition of `baz` here
+ | ------------------------------ previous definition here
LL | fn baz(&self) -> bool { self.0 > 5 }
- | ^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
error[E0201]: duplicate definitions with name `Quux`:
--> $DIR/E0201.rs:18:5
|
+LL | type Quux;
+ | ---------- item in trait
+...
LL | type Quux = u32;
- | --------- previous definition of `Quux` here
+ | ---------------- previous definition here
...
LL | type Quux = u32;
- | ^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^ duplicate definition
+
+error[E0592]: duplicate definitions with name `bar`
+ --> $DIR/E0201.rs:5:5
+ |
+LL | fn bar(&self) -> bool { self.0 > 5 }
+ | --------------------- other definition for `bar`
+LL | fn bar() {}
+ | ^^^^^^^^ duplicate definitions for `bar`
error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0201`.
+Some errors have detailed explanations: E0201, E0592.
+For more information about an error, try `rustc --explain E0201`.
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index 90a28874e..90316c6e9 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -9,8 +9,8 @@ LL | let cont: u32 = Generator::create();
|
help: use a fully-qualified path to a specific available implementation (2 found)
|
-LL | let cont: u32 = <::Impl as Generator>::create();
- | ++++++++++ +
+LL | let cont: u32 = <Impl as Generator>::create();
+ | ++++++++ +
error[E0283]: type annotations needed
--> $DIR/E0283.rs:35:24
diff --git a/src/test/ui/error-codes/E0308.rs b/src/test/ui/error-codes/E0308.rs
index fa79bee57..dd9e0b284 100644
--- a/src/test/ui/error-codes/E0308.rs
+++ b/src/test/ui/error-codes/E0308.rs
@@ -1,6 +1,8 @@
#![feature(intrinsics)]
+#![feature(rustc_attrs)]
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
fn size_of<T>(); //~ ERROR E0308
}
diff --git a/src/test/ui/error-codes/E0308.stderr b/src/test/ui/error-codes/E0308.stderr
index b71fb95e7..187b775f9 100644
--- a/src/test/ui/error-codes/E0308.stderr
+++ b/src/test/ui/error-codes/E0308.stderr
@@ -1,5 +1,5 @@
error[E0308]: intrinsic has wrong type
- --> $DIR/E0308.rs:4:5
+ --> $DIR/E0308.rs:6:5
|
LL | fn size_of<T>();
| ^^^^^^^^^^^^^^^^ expected `()`, found `usize`
diff --git a/src/test/ui/error-codes/E0311.rs b/src/test/ui/error-codes/E0311.rs
new file mode 100644
index 000000000..566b518b4
--- /dev/null
+++ b/src/test/ui/error-codes/E0311.rs
@@ -0,0 +1,9 @@
+fn no_restriction<T>(x: &()) -> &() {
+ with_restriction::<T>(x) //~ ERROR E0311
+}
+
+fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
+ x
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0311.stderr b/src/test/ui/error-codes/E0311.stderr
new file mode 100644
index 000000000..9873b5ae6
--- /dev/null
+++ b/src/test/ui/error-codes/E0311.stderr
@@ -0,0 +1,24 @@
+error[E0311]: the parameter type `T` may not live long enough
+ --> $DIR/E0311.rs:2:5
+ |
+LL | with_restriction::<T>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+ --> $DIR/E0311.rs:1:25
+ |
+LL | fn no_restriction<T>(x: &()) -> &() {
+ | ^^^
+note: ...so that the type `T` will meet its required lifetime bounds
+ --> $DIR/E0311.rs:2:5
+ |
+LL | with_restriction::<T>(x)
+ | ^^^^^^^^^^^^^^^^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
+ | +++ ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/src/test/ui/error-codes/E0388.stderr b/src/test/ui/error-codes/E0388.stderr
index 106efc19a..b51aa263d 100644
--- a/src/test/ui/error-codes/E0388.stderr
+++ b/src/test/ui/error-codes/E0388.stderr
@@ -4,7 +4,6 @@ warning: taking a mutable reference to a `const` item
LL | const CR: &'static mut i32 = &mut C;
| ^^^^^^
|
- = note: `#[warn(const_item_mutation)]` on by default
= note: each usage of a `const` item creates a new temporary
= note: the mutable reference will refer to this temporary, not the original `const` item
note: `const` item defined here
@@ -12,6 +11,7 @@ note: `const` item defined here
|
LL | const C: i32 = 2;
| ^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
error[E0764]: mutable references are not allowed in the final value of constants
--> $DIR/E0388.rs:4:30
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index 8f2ef8c8e..ac70d905d 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -26,6 +26,17 @@ help: surround the struct literal with parentheses
LL | for _ in (std::ops::Range { start: 0, end: 10 }) {}
| + +
+error[E0423]: expected value, found struct `T`
+ --> $DIR/E0423.rs:14:8
+ |
+LL | if T {} == T {} { println!("Ok"); }
+ | ^ not a value
+ |
+help: surround the struct literal with parentheses
+ |
+LL | if (T {}) == T {} { println!("Ok"); }
+ | + +
+
error[E0423]: expected function, tuple struct or tuple variant, found struct `Foo`
--> $DIR/E0423.rs:4:13
|
@@ -47,17 +58,6 @@ help: a function with a similar name exists
LL | let f = foo();
| ~~~
-error[E0423]: expected value, found struct `T`
- --> $DIR/E0423.rs:14:8
- |
-LL | if T {} == T {} { println!("Ok"); }
- | ^ not a value
- |
-help: surround the struct literal with parentheses
- |
-LL | if (T {}) == T {} { println!("Ok"); }
- | + +
-
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr
index 65ebfcdbe..12ecead13 100644
--- a/src/test/ui/error-codes/E0520.stderr
+++ b/src/test/ui/error-codes/E0520.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
--> $DIR/E0520.rs:17:5
diff --git a/src/test/ui/error-codes/E0585.stderr b/src/test/ui/error-codes/E0585.stderr
index 7a31c4896..53c82fb41 100644
--- a/src/test/ui/error-codes/E0585.stderr
+++ b/src/test/ui/error-codes/E0585.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | /// Hello! I'm useless...
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0771.stderr b/src/test/ui/error-codes/E0771.stderr
index 3ab727f5f..b759399a9 100644
--- a/src/test/ui/error-codes/E0771.stderr
+++ b/src/test/ui/error-codes/E0771.stderr
@@ -12,8 +12,8 @@ warning: the feature `adt_const_params` is incomplete and may not be safe to use
LL | #![feature(adt_const_params)]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #95174 <https://github.com/rust-lang/rust/issues/95174> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr
index 6e173a968..f68c0e7d2 100644
--- a/src/test/ui/error-codes/E0790.stderr
+++ b/src/test/ui/error-codes/E0790.stderr
@@ -9,8 +9,8 @@ LL | MyTrait::my_fn();
|
help: use the fully-qualified path to the only available implementation
|
-LL | <::inner::MyStruct as MyTrait>::my_fn();
- | +++++++++++++++++++++ +
+LL | <MyStruct as MyTrait>::my_fn();
+ | ++++++++++++ +
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:21:17
@@ -23,8 +23,8 @@ LL | let _ = MyTrait::MY_ASSOC_CONST;
|
help: use the fully-qualified path to the only available implementation
|
-LL | let _ = <::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
- | +++++++++++++++++++++ +
+LL | let _ = <MyStruct as MyTrait>::MY_ASSOC_CONST;
+ | ++++++++++++ +
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:26:5
@@ -37,8 +37,8 @@ LL | inner::MyTrait::my_fn();
|
help: use the fully-qualified path to the only available implementation
|
-LL | inner::<::inner::MyStruct as MyTrait>::my_fn();
- | +++++++++++++++++++++ +
+LL | inner::<MyStruct as MyTrait>::my_fn();
+ | ++++++++++++ +
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:30:13
@@ -51,8 +51,8 @@ LL | let _ = inner::MyTrait::MY_ASSOC_CONST;
|
help: use the fully-qualified path to the only available implementation
|
-LL | let _ = inner::<::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
- | +++++++++++++++++++++ +
+LL | let _ = inner::<MyStruct as MyTrait>::MY_ASSOC_CONST;
+ | ++++++++++++ +
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
--> $DIR/E0790.rs:50:5
@@ -65,8 +65,8 @@ LL | MyTrait2::my_fn();
|
help: use a fully-qualified path to a specific available implementation (2 found)
|
-LL | <::Impl1 as MyTrait2>::my_fn();
- | +++++++++++ +
+LL | <Impl1 as MyTrait2>::my_fn();
+ | +++++++++ +
error: aborting due to 5 previous errors
diff --git a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
index 4ec78a298..08eb8cfac 100644
--- a/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
+++ b/src/test/ui/errors/issue-89280-emitter-overflow-splice-lines.stderr
@@ -8,9 +8,9 @@ LL | |
LL | | )) {}
| |_____^
|
- = note: `#[warn(anonymous_parameters)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+ = note: `#[warn(anonymous_parameters)]` on by default
help: try naming the parameter or explicitly ignoring it
|
LL ~ fn test(x: u32, _: (
diff --git a/src/test/ui/explain.stdout b/src/test/ui/explain.stdout
index 62f1a7f98..ef1d866c3 100644
--- a/src/test/ui/explain.stdout
+++ b/src/test/ui/explain.stdout
@@ -47,8 +47,8 @@ unsafe {
```
Here, transmute is being used to convert the types of the fn arguments.
-This pattern is incorrect because, because the type of `foo` is a function
-**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
+This pattern is incorrect because the type of `foo` is a function **item**
+(`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
is a function pointer, which is not zero-sized.
This pattern should be rewritten. There are a few possible ways to do this:
diff --git a/src/test/ui/expr/if/bad-if-let-suggestion.stderr b/src/test/ui/expr/if/bad-if-let-suggestion.stderr
index 60d286fed..3a53a20b4 100644
--- a/src/test/ui/expr/if/bad-if-let-suggestion.stderr
+++ b/src/test/ui/expr/if/bad-if-let-suggestion.stderr
@@ -62,6 +62,11 @@ error[E0308]: mismatched types
|
LL | if let x = 1 && i = 2 {}
| ^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | if let x = 1 && i == 2 {}
+ | +
error: aborting due to 8 previous errors
diff --git a/src/test/ui/expr/if/if-let.stderr b/src/test/ui/expr/if/if-let.stderr
index 8238b3f0e..c4bba3cb1 100644
--- a/src/test/ui/expr/if/if-let.stderr
+++ b/src/test/ui/expr/if/if-let.stderr
@@ -9,9 +9,9 @@ LL | | println!("irrefutable pattern");
LL | | });
| |______- in this macro invocation
|
- = 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
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: irrefutable `if let` pattern
diff --git a/src/test/ui/expr/if/if-without-else-result.rs b/src/test/ui/expr/if/if-without-else-result.rs
index cf84a99e5..95604758a 100644
--- a/src/test/ui/expr/if/if-without-else-result.rs
+++ b/src/test/ui/expr/if/if-without-else-result.rs
@@ -1,6 +1,6 @@
fn main() {
let a = if true { true };
//~^ ERROR `if` may be missing an `else` clause [E0317]
- //~| expected `()`, found `bool`
+ //~| expected `bool`, found `()`
println!("{}", a);
}
diff --git a/src/test/ui/expr/if/if-without-else-result.stderr b/src/test/ui/expr/if/if-without-else-result.stderr
index 821635d37..317faf7c6 100644
--- a/src/test/ui/expr/if/if-without-else-result.stderr
+++ b/src/test/ui/expr/if/if-without-else-result.stderr
@@ -5,7 +5,7 @@ LL | let a = if true { true };
| ^^^^^^^^^^----^^
| | |
| | found here
- | expected `()`, found `bool`
+ | expected `bool`, found `()`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
diff --git a/src/test/ui/expr/if/issue-4201.rs b/src/test/ui/expr/if/issue-4201.rs
index 1f292229f..59c465b9e 100644
--- a/src/test/ui/expr/if/issue-4201.rs
+++ b/src/test/ui/expr/if/issue-4201.rs
@@ -3,7 +3,7 @@ fn main() {
0
} else if false {
//~^ ERROR `if` may be missing an `else` clause
-//~| expected `()`, found integer
+//~| expected integer, found `()`
1
};
}
diff --git a/src/test/ui/expr/if/issue-4201.stderr b/src/test/ui/expr/if/issue-4201.stderr
index bc638ddf5..612fe7764 100644
--- a/src/test/ui/expr/if/issue-4201.stderr
+++ b/src/test/ui/expr/if/issue-4201.stderr
@@ -8,7 +8,7 @@ LL | |
LL | | 1
| | - found here
LL | | };
- | |_____^ expected `()`, found integer
+ | |_____^ expected integer, found `()`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
diff --git a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
index 9db9cfc7f..759d79493 100644
--- a/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
+++ b/src/test/ui/expr/malformed_closure/ruby_style_closure.stderr
@@ -14,7 +14,7 @@ LL | let p = Some(45).and_then({
LL | |
LL | | |x| println!("doubling {}", x);
LL | | Some(x * 2)
- | | -----------
+ | | ----------- this tail expression is of type `std::option::Option<_>`
LL | |
LL | | });
| |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<_>`
diff --git a/src/test/ui/extenv/issue-55897.rs b/src/test/ui/extenv/issue-55897.rs
index 64c4107e8..b7533f413 100644
--- a/src/test/ui/extenv/issue-55897.rs
+++ b/src/test/ui/extenv/issue-55897.rs
@@ -14,7 +14,7 @@ mod nonexistent_env {
mod erroneous_literal {
include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
- //~^ ERROR suffixes on a string literal are invalid
+ //~^ ERROR suffixes on string literals are invalid
}
fn main() {}
diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr
index d2ac0b830..63797d4a7 100644
--- a/src/test/ui/extenv/issue-55897.stderr
+++ b/src/test/ui/extenv/issue-55897.stderr
@@ -6,7 +6,7 @@ LL | include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
|
= note: this error originates in the macro `env` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: suffixes on a string literal are invalid
+error: suffixes on string literals are invalid
--> $DIR/issue-55897.rs:16:22
|
LL | include!(concat!("NON_EXISTENT"suffix, "/data.rs"));
@@ -26,6 +26,11 @@ error[E0432]: unresolved import `env`
|
LL | use env;
| ^^^ no `env` in the root
+ |
+help: consider importing this module instead
+ |
+LL | use std::env;
+ | ~~~~~~~~~
error: cannot determine resolution for the macro `env`
--> $DIR/issue-55897.rs:6:22
diff --git a/src/test/ui/extern-flag/empty-extern-arg.rs b/src/test/ui/extern-flag/empty-extern-arg.rs
index 3170537b0..2f4ae7d8e 100644
--- a/src/test/ui/extern-flag/empty-extern-arg.rs
+++ b/src/test/ui/extern-flag/empty-extern-arg.rs
@@ -1,6 +1,6 @@
// compile-flags: --extern std=
// error-pattern: extern location for std does not exist
// needs-unwind since it affects the error output
-// ignore-emscripten compiled with panic=abort, personality not required
+// ignore-emscripten missing eh_catch_typeinfo lang item
fn main() {}
diff --git a/src/test/ui/extern/extern-no-mangle.stderr b/src/test/ui/extern/extern-no-mangle.stderr
index b56428141..f20ee158a 100644
--- a/src/test/ui/extern/extern-no-mangle.stderr
+++ b/src/test/ui/extern/extern-no-mangle.stderr
@@ -7,12 +7,12 @@ LL | #[no_mangle]
LL | let x = 0_u8;
| ------------- not a free function, impl method or static
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/extern-no-mangle.rs:1:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: `#[no_mangle]` has no effect on a foreign static
--> $DIR/extern-no-mangle.rs:11:5
diff --git a/src/test/ui/extern/extern-with-type-bounds.rs b/src/test/ui/extern/extern-with-type-bounds.rs
index 8f9683e4a..a72aa4171 100644
--- a/src/test/ui/extern/extern-with-type-bounds.rs
+++ b/src/test/ui/extern/extern-with-type-bounds.rs
@@ -2,6 +2,7 @@
extern "rust-intrinsic" {
// Real example from libcore
+ #[rustc_safe_intrinsic]
fn type_id<T: ?Sized + 'static>() -> u64;
// Silent bounds made explicit to make sure they are actually
@@ -10,6 +11,7 @@ extern "rust-intrinsic" {
// Bounds aren't checked right now, so this should work
// even though it's incorrect.
+ #[rustc_safe_intrinsic]
fn size_of<T: Clone>() -> usize;
// Unresolved bounds should still error.
diff --git a/src/test/ui/extern/extern-with-type-bounds.stderr b/src/test/ui/extern/extern-with-type-bounds.stderr
index acd059642..88be1e5dd 100644
--- a/src/test/ui/extern/extern-with-type-bounds.stderr
+++ b/src/test/ui/extern/extern-with-type-bounds.stderr
@@ -1,5 +1,5 @@
error[E0405]: cannot find trait `NoSuchTrait` in this scope
- --> $DIR/extern-with-type-bounds.rs:16:20
+ --> $DIR/extern-with-type-bounds.rs:18:20
|
LL | fn align_of<T: NoSuchTrait>() -> usize;
| ^^^^^^^^^^^ not found in this scope
diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
index 7a91cbdc2..233120c92 100644
--- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
+++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// ignore-emscripten no threads support
// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
index e84ff41b3..3b263e58c 100644
--- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
+++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// ignore-emscripten no threads support
// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine
diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr
index 168ac9257..5f0aaf925 100644
--- a/src/test/ui/feature-gates/bench.stderr
+++ b/src/test/ui/feature-gates/bench.stderr
@@ -4,9 +4,9 @@ error: use of unstable library feature 'test': `bench` is a part of custom test
LL | #[bench]
| ^^^^^
|
- = note: `#[deny(soft_unstable)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+ = note: `#[deny(soft_unstable)]` on by default
error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:7:5
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs
deleted file mode 100644
index 0de6b3abb..000000000
--- a/src/test/ui/feature-gates/feature-gate-asm_sym.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-// only-x86_64
-
-use std::arch::asm;
-
-fn bar<const N: usize>() {}
-
-fn foo<const N: usize>() {
- unsafe {
- asm!("mov eax, {}", sym bar::<N>);
- //~^ ERROR sym operands for inline assembly are unstable
- }
-}
-
-fn main() {
- unsafe {
- asm!("mov eax, {}", sym foo::<0>);
- //~^ ERROR sym operands for inline assembly are unstable
- }
-}
diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
deleted file mode 100644
index d4b16f60b..000000000
--- a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0658]: sym operands for inline assembly are unstable
- --> $DIR/feature-gate-asm_sym.rs:9:29
- |
-LL | asm!("mov eax, {}", sym bar::<N>);
- | ^^^^^^^^^^^^
- |
- = note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
- = help: add `#![feature(asm_sym)]` to the crate attributes to enable
-
-error[E0658]: sym operands for inline assembly are unstable
- --> $DIR/feature-gate-asm_sym.rs:16:29
- |
-LL | asm!("mov eax, {}", sym foo::<0>);
- | ^^^^^^^^^^^^
- |
- = note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
- = help: add `#![feature(asm_sym)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
index a7d5c7ac3..308de2692 100644
--- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
+++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr
@@ -4,9 +4,9 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
LL | fn avg<T=i32>(_: T) {}
| ^^^^^
|
- = note: `#[deny(invalid_type_param_default)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6
diff --git a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
index 3de08e215..4d79ce3c6 100644
--- a/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
+++ b/src/test/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
@@ -4,10 +4,10 @@ warning: unknown lint: `non_exhaustive_omitted_patterns`
LL | #![deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unknown_lints)]` on by default
= note: the `non_exhaustive_omitted_patterns` lint is unstable
= note: see issue #89554 <https://github.com/rust-lang/rust/issues/89554> for more information
= help: add `#![feature(non_exhaustive_omitted_patterns_lint)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
warning: unknown lint: `non_exhaustive_omitted_patterns`
--> $DIR/feature-gate-non_exhaustive_omitted_patterns_lint.rs:6:1
diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
index ae44b8020..5b1270a19 100644
--- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
+++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr
@@ -25,9 +25,9 @@ LL |
LL | #[repr(simd)]
| ^^^^
|
- = note: `#[deny(conflicting_repr_hints)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+ = note: `#[deny(conflicting_repr_hints)]` on by default
error: aborting due to 3 previous errors
diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
index de7966c66..637765fff 100644
--- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
+++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.rs
@@ -1,5 +1,18 @@
+// edition:2021
+
+// async_fn_in_trait is not enough to allow use of RPITIT
+#![allow(incomplete_features)]
+#![feature(async_fn_in_trait)]
+
trait Foo {
fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
+ fn baz() -> Box<impl std::fmt::Display>; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
+}
+
+// Both return_position_impl_trait_in_trait and async_fn_in_trait are required for this (see also
+// feature-gate-async_fn_in_trait.rs)
+trait AsyncFoo {
+ async fn bar() -> impl Sized; //~ ERROR `impl Trait` only allowed in function and inherent method return types, not in trait method return
}
fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
index 36177bbe1..aeabed4a6 100644
--- a/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
+++ b/src/test/ui/feature-gates/feature-gate-return_position_impl_trait_in_trait.stderr
@@ -1,5 +1,5 @@
error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
- --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:2:17
+ --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:8:17
|
LL | fn bar() -> impl Sized;
| ^^^^^^^^^^
@@ -7,6 +7,24 @@ 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: aborting due to previous error
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in trait method return
+ --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:9:21
+ |
+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
+ --> $DIR/feature-gate-return_position_impl_trait_in_trait.rs:15:23
+ |
+LL | async 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: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0562`.
diff --git a/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr
index 34bd240c3..751da87cc 100644
--- a/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr
+++ b/src/test/ui/feature-gates/feature-gate-strict_provenance.stderr
@@ -4,10 +4,10 @@ warning: unknown lint: `fuzzy_provenance_casts`
LL | #![deny(fuzzy_provenance_casts)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unknown_lints)]` on by default
= note: the `fuzzy_provenance_casts` lint is unstable
= note: see issue #95228 <https://github.com/rust-lang/rust/issues/95228> for more information
= help: add `#![feature(strict_provenance)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
warning: unknown lint: `lossy_provenance_casts`
--> $DIR/feature-gate-strict_provenance.rs:7:1
diff --git a/src/test/ui/feature-gates/feature-gate-test_unstable_lint.stderr b/src/test/ui/feature-gates/feature-gate-test_unstable_lint.stderr
index a29322443..b4d6aa658 100644
--- a/src/test/ui/feature-gates/feature-gate-test_unstable_lint.stderr
+++ b/src/test/ui/feature-gates/feature-gate-test_unstable_lint.stderr
@@ -4,9 +4,9 @@ warning: unknown lint: `test_unstable_lint`
LL | #![allow(test_unstable_lint)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unknown_lints)]` on by default
= note: the `test_unstable_lint` lint is unstable
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
warning: unknown lint: `test_unstable_lint`
--> $DIR/feature-gate-test_unstable_lint.rs:4:1
diff --git a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index f94ec7d47..5a645cf4e 100644
--- a/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/src/test/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -12,9 +12,9 @@ error: attribute must be of the form `#[inline]` or `#[inline(always|never)]`
LL | #[inline = "2100"] fn f() { }
| ^^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(ill_formed_attribute_input)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+ = note: `#[deny(ill_formed_attribute_input)]` on by default
error: `start` attribute can only be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:1
diff --git a/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs
new file mode 100644
index 000000000..e44a84776
--- /dev/null
+++ b/src/test/ui/fmt/auxiliary/format-string-proc-macro.rs
@@ -0,0 +1,28 @@
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::{Literal, Span, TokenStream, TokenTree};
+
+#[proc_macro]
+pub fn foo_with_input_span(input: TokenStream) -> TokenStream {
+ let span = input.into_iter().next().unwrap().span();
+
+ let mut lit = Literal::string("{foo}");
+ lit.set_span(span);
+
+ TokenStream::from(TokenTree::Literal(lit))
+}
+
+#[proc_macro]
+pub fn err_with_input_span(input: TokenStream) -> TokenStream {
+ let span = input.into_iter().next().unwrap().span();
+
+ let mut lit = Literal::string(" }");
+ lit.set_span(span);
+
+ TokenStream::from(TokenTree::Literal(lit))
+}
diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.rs b/src/test/ui/fmt/format-args-capture-issue-102057.rs
new file mode 100644
index 000000000..b8089d49b
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-issue-102057.rs
@@ -0,0 +1,19 @@
+fn main() {
+ format!("\x7Ba}");
+ //~^ ERROR cannot find value `a` in this scope
+ format!("\x7Ba\x7D");
+ //~^ ERROR cannot find value `a` in this scope
+
+ let a = 0;
+
+ format!("\x7Ba} {b}");
+ //~^ ERROR cannot find value `b` in this scope
+ format!("\x7Ba\x7D {b}");
+ //~^ ERROR cannot find value `b` in this scope
+ format!("\x7Ba} \x7Bb}");
+ //~^ ERROR cannot find value `b` in this scope
+ format!("\x7Ba\x7D \x7Bb}");
+ //~^ ERROR cannot find value `b` in this scope
+ format!("\x7Ba\x7D \x7Bb\x7D");
+ //~^ ERROR cannot find value `b` in this scope
+}
diff --git a/src/test/ui/fmt/format-args-capture-issue-102057.stderr b/src/test/ui/fmt/format-args-capture-issue-102057.stderr
new file mode 100644
index 000000000..f2d625e7f
--- /dev/null
+++ b/src/test/ui/fmt/format-args-capture-issue-102057.stderr
@@ -0,0 +1,45 @@
+error[E0425]: cannot find value `a` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:2:18
+ |
+LL | format!("\x7Ba}");
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `a` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:4:18
+ |
+LL | format!("\x7Ba\x7D");
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `b` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:9:22
+ |
+LL | format!("\x7Ba} {b}");
+ | ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:11:25
+ |
+LL | format!("\x7Ba\x7D {b}");
+ | ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:13:25
+ |
+LL | format!("\x7Ba} \x7Bb}");
+ | ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:15:28
+ |
+LL | format!("\x7Ba\x7D \x7Bb}");
+ | ^ help: a local variable with a similar name exists: `a`
+
+error[E0425]: cannot find value `b` in this scope
+ --> $DIR/format-args-capture-issue-102057.rs:17:28
+ |
+LL | format!("\x7Ba\x7D \x7Bb\x7D");
+ | ^ help: a local variable with a similar name exists: `a`
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.rs b/src/test/ui/fmt/format-args-capture-issue-93378.rs
index 674444442..9d722a028 100644
--- a/src/test/ui/fmt/format-args-capture-issue-93378.rs
+++ b/src/test/ui/fmt/format-args-capture-issue-93378.rs
@@ -3,9 +3,9 @@ fn main() {
let b = "b";
println!("{a} {b} {} {} {c} {}", c = "c");
- //~^ ERROR: invalid reference to positional arguments 1 and 2 (there is 1 argument)
+ //~^ ERROR: 3 positional arguments in format string, but there is 1 argument
let n = 1;
println!("{a:.n$} {b:.*}");
- //~^ ERROR: invalid reference to positional argument 0 (no arguments were given)
+ //~^ ERROR: 1 positional argument in format string, but no arguments were given
}
diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.stderr b/src/test/ui/fmt/format-args-capture-issue-93378.stderr
index b8e2b2afb..6429b0d46 100644
--- a/src/test/ui/fmt/format-args-capture-issue-93378.stderr
+++ b/src/test/ui/fmt/format-args-capture-issue-93378.stderr
@@ -1,19 +1,14 @@
-error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
- --> $DIR/format-args-capture-issue-93378.rs:5:26
+error: 3 positional arguments in format string, but there is 1 argument
+ --> $DIR/format-args-capture-issue-93378.rs:5:23
|
LL | println!("{a} {b} {} {} {c} {}", c = "c");
- | ^^ ^^
- |
- = note: positional arguments are zero-based
+ | ^^ ^^ ^^ ---
-error: invalid reference to positional argument 0 (no arguments were given)
- --> $DIR/format-args-capture-issue-93378.rs:9:23
+error: 1 positional argument in format string, but no arguments were given
+ --> $DIR/format-args-capture-issue-93378.rs:9:26
|
LL | println!("{a:.n$} {b:.*}");
- | - ^^^--^
- | | |
- | | this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected
- | this parameter corresponds to the precision flag
+ | ^^ this precision flag adds an extra required argument at position 0, which is why there is 1 argument expected
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
index fdbd93836..b04f80ba4 100644
--- a/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
+++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.rs
@@ -1,4 +1,22 @@
+// aux-build:format-string-proc-macro.rs
+
+#[macro_use]
+extern crate format_string_proc_macro;
+
+macro_rules! def_site {
+ () => { "{foo}" } //~ ERROR: there is no argument named `foo`
+}
+
+macro_rules! call_site {
+ ($fmt:literal) => { $fmt }
+}
+
fn main() {
format!(concat!("{foo}")); //~ ERROR: there is no argument named `foo`
format!(concat!("{ba", "r} {}"), 1); //~ ERROR: there is no argument named `bar`
+
+ format!(def_site!());
+ format!(call_site!("{foo}")); //~ ERROR: there is no argument named `foo`
+
+ format!(foo_with_input_span!("")); //~ ERROR: there is no argument named `foo`
}
diff --git a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
index 9423e8c81..1b5fbd2af 100644
--- a/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
+++ b/src/test/ui/fmt/format-args-capture-macro-hygiene.stderr
@@ -1,5 +1,5 @@
error: there is no argument named `foo`
- --> $DIR/format-args-capture-macro-hygiene.rs:2:13
+ --> $DIR/format-args-capture-macro-hygiene.rs:15:13
|
LL | format!(concat!("{foo}"));
| ^^^^^^^^^^^^^^^^
@@ -9,7 +9,7 @@ LL | format!(concat!("{foo}"));
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
error: there is no argument named `bar`
- --> $DIR/format-args-capture-macro-hygiene.rs:3:13
+ --> $DIR/format-args-capture-macro-hygiene.rs:16:13
|
LL | format!(concat!("{ba", "r} {}"), 1);
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,5 +18,36 @@ LL | format!(concat!("{ba", "r} {}"), 1);
= note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
= note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 2 previous errors
+error: there is no argument named `foo`
+ --> $DIR/format-args-capture-macro-hygiene.rs:7:13
+ |
+LL | () => { "{foo}" }
+ | ^^^^^^^
+...
+LL | format!(def_site!());
+ | ----------- in this macro invocation
+ |
+ = note: did you intend to capture a variable `foo` from the surrounding scope?
+ = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+ = note: this error originates in the macro `def_site` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: there is no argument named `foo`
+ --> $DIR/format-args-capture-macro-hygiene.rs:19:24
+ |
+LL | format!(call_site!("{foo}"));
+ | ^^^^^^^
+ |
+ = note: did you intend to capture a variable `foo` from the surrounding scope?
+ = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+error: there is no argument named `foo`
+ --> $DIR/format-args-capture-macro-hygiene.rs:21:34
+ |
+LL | format!(foo_with_input_span!(""));
+ | ^^
+ |
+ = note: did you intend to capture a variable `foo` from the surrounding scope?
+ = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro
+
+error: aborting due to 5 previous errors
diff --git a/src/test/ui/fmt/format-concat-span.stderr b/src/test/ui/fmt/format-concat-span.stderr
deleted file mode 100644
index da46f40ab..000000000
--- a/src/test/ui/fmt/format-concat-span.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: invalid format string: unmatched `}` found
- --> $DIR/format-concat-span.rs:13:13
- |
-LL | format!(concat!("abc}"));
- | ^^^^^^^^^^^^^^^ unmatched `}` in format string
- |
- = note: if you intended to print `}`, you can escape it using `}}`
- = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/fmt/format-concat-span.rs b/src/test/ui/fmt/format-expanded-string.rs
index ce92df0ad..4c716f08c 100644
--- a/src/test/ui/fmt/format-concat-span.rs
+++ b/src/test/ui/fmt/format-expanded-string.rs
@@ -1,3 +1,9 @@
+// aux-build:format-string-proc-macro.rs
+
+#[macro_use]
+extern crate format_string_proc_macro;
+
+
// If the format string is another macro invocation, rustc would previously
// compute nonsensical spans, such as:
//
@@ -12,4 +18,7 @@
fn main() {
format!(concat!("abc}"));
//~^ ERROR: invalid format string: unmatched `}` found
+
+ format!(err_with_input_span!(""));
+ //~^ ERROR: invalid format string: unmatched `}` found
}
diff --git a/src/test/ui/fmt/format-expanded-string.stderr b/src/test/ui/fmt/format-expanded-string.stderr
new file mode 100644
index 000000000..26ce7f269
--- /dev/null
+++ b/src/test/ui/fmt/format-expanded-string.stderr
@@ -0,0 +1,19 @@
+error: invalid format string: unmatched `}` found
+ --> $DIR/format-expanded-string.rs:19:13
+ |
+LL | format!(concat!("abc}"));
+ | ^^^^^^^^^^^^^^^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+ = note: this error originates in the macro `concat` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid format string: unmatched `}` found
+ --> $DIR/format-expanded-string.rs:22:34
+ |
+LL | format!(err_with_input_span!(""));
+ | ^^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/fmt/ifmt-bad-arg.rs b/src/test/ui/fmt/ifmt-bad-arg.rs
index f00cb05c9..68861d7bf 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.rs
+++ b/src/test/ui/fmt/ifmt-bad-arg.rs
@@ -20,9 +20,9 @@ fn main() {
//~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
format!("{} {value} {} {}", 1, value=2);
- //~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
+ //~^ ERROR: 3 positional arguments in format string, but there are 2 arguments
format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
- //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+ //~^ ERROR: 6 positional arguments in format string, but there are 3 arguments
format!("{} {foo} {} {bar} {}", 1, 2, 3);
//~^ ERROR: cannot find value `foo` in this scope
@@ -79,7 +79,7 @@ tenth number: {}",
//~^ ERROR 4 positional arguments in format string, but there are 3 arguments
//~| ERROR mismatched types
println!("{} {:07$.*} {}", 1, 3.2, 4);
- //~^ ERROR 4 positional arguments in format string, but there are 3 arguments
+ //~^ ERROR invalid reference to positional arguments 3 and 7 (there are 3 arguments)
//~| ERROR mismatched types
println!("{} {:07$} {}", 1, 3.2, 4);
//~^ ERROR invalid reference to positional argument 7 (there are 3 arguments)
@@ -95,5 +95,5 @@ tenth number: {}",
println!("{:.*}");
//~^ ERROR 2 positional arguments in format string, but no arguments were given
println!("{:.0$}");
- //~^ ERROR 1 positional argument in format string, but no arguments were given
+ //~^ ERROR invalid reference to positional argument 0 (no arguments were given)
}
diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr
index dbb4bc6d9..1b595a50e 100644
--- a/src/test/ui/fmt/ifmt-bad-arg.stderr
+++ b/src/test/ui/fmt/ifmt-bad-arg.stderr
@@ -5,10 +5,10 @@ LL | format!("{}");
| ^^
error: invalid reference to positional argument 1 (there is 1 argument)
- --> $DIR/ifmt-bad-arg.rs:9:14
+ --> $DIR/ifmt-bad-arg.rs:9:15
|
LL | format!("{1}", 1);
- | ^^^
+ | ^
|
= note: positional arguments are zero-based
@@ -27,36 +27,32 @@ LL | format!("{} {}");
| ^^ ^^
error: invalid reference to positional argument 1 (there is 1 argument)
- --> $DIR/ifmt-bad-arg.rs:16:18
+ --> $DIR/ifmt-bad-arg.rs:16:19
|
LL | format!("{0} {1}", 1);
- | ^^^
+ | ^
|
= note: positional arguments are zero-based
error: invalid reference to positional argument 2 (there are 2 arguments)
- --> $DIR/ifmt-bad-arg.rs:19:22
+ --> $DIR/ifmt-bad-arg.rs:19:23
|
LL | format!("{0} {1} {2}", 1, 2);
- | ^^^
+ | ^
|
= note: positional arguments are zero-based
-error: invalid reference to positional argument 2 (there are 2 arguments)
- --> $DIR/ifmt-bad-arg.rs:22:28
+error: 3 positional arguments in format string, but there are 2 arguments
+ --> $DIR/ifmt-bad-arg.rs:22:14
|
LL | format!("{} {value} {} {}", 1, value=2);
- | ^^
- |
- = note: positional arguments are zero-based
+ | ^^ ^^ ^^ - -
-error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
- --> $DIR/ifmt-bad-arg.rs:24:38
+error: 6 positional arguments in format string, but there are 3 arguments
+ --> $DIR/ifmt-bad-arg.rs:24:29
|
LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
- | ^^ ^^ ^^
- |
- = note: positional arguments are zero-based
+ | ^^ ^^ ^^ ^^ ^^ ^^ - - -
error: multiple unused formatting arguments
--> $DIR/ifmt-bad-arg.rs:32:17
@@ -117,20 +113,20 @@ LL | format!("{} {}", 1, 2, foo=1, bar=2);
| multiple missing formatting specifiers
error: duplicate argument named `foo`
- --> $DIR/ifmt-bad-arg.rs:40:33
+ --> $DIR/ifmt-bad-arg.rs:40:29
|
LL | format!("{foo}", foo=1, foo=2);
- | - ^ duplicate argument
- | |
- | previously here
+ | --- ^^^ duplicate argument
+ | |
+ | previously here
error: positional arguments cannot follow named arguments
--> $DIR/ifmt-bad-arg.rs:41:35
|
LL | format!("{foo} {} {}", foo=1, 2);
- | - ^ positional arguments must be before named arguments
- | |
- | named argument
+ | ----- ^ positional arguments must be before named arguments
+ | |
+ | named argument
error: named argument never used
--> $DIR/ifmt-bad-arg.rs:45:51
@@ -191,33 +187,26 @@ error: 4 positional arguments in format string, but there are 3 arguments
|
LL | println!("{} {:.*} {}", 1, 3.2, 4);
| ^^ ^^--^ ^^ - --- -
- | | |
- | | this parameter corresponds to the precision flag
+ | |
| this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
-error: 4 positional arguments in format string, but there are 3 arguments
- --> $DIR/ifmt-bad-arg.rs:81:15
+error: invalid reference to positional arguments 3 and 7 (there are 3 arguments)
+ --> $DIR/ifmt-bad-arg.rs:81:21
|
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
- | ^^ ^^^----^ ^^ - --- -
- | | | |
- | | | this parameter corresponds to the precision flag
- | | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
- | this width flag expects an `usize` argument at position 7, but there are 3 arguments
+ | ^^ ^
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error: invalid reference to positional argument 7 (there are 3 arguments)
- --> $DIR/ifmt-bad-arg.rs:84:18
+ --> $DIR/ifmt-bad-arg.rs:84:21
|
LL | println!("{} {:07$} {}", 1, 3.2, 4);
- | ^^^--^
- | |
- | this width flag expects an `usize` argument at position 7, but there are 3 arguments
+ | ^^
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
@@ -240,24 +229,19 @@ LL | println!("{:foo}", 1);
- `X`, which uses the `UpperHex` trait
error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
- --> $DIR/ifmt-bad-arg.rs:87:15
+ --> $DIR/ifmt-bad-arg.rs:87:16
|
LL | println!("{5} {:4$} {6:7$}", 1);
- | ^^^ ^^--^ ^^^--^
- | | |
- | | this width flag expects an `usize` argument at position 7, but there is 1 argument
- | this width flag expects an `usize` argument at position 4, but there is 1 argument
+ | ^ ^^ ^ ^^
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
error: invalid reference to positional argument 0 (no arguments were given)
- --> $DIR/ifmt-bad-arg.rs:90:15
+ --> $DIR/ifmt-bad-arg.rs:90:20
|
LL | println!("{foo:0$}");
- | ^^^^^--^
- | |
- | this width flag expects an `usize` argument at position 0, but no arguments were given
+ | ^^
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
@@ -273,13 +257,11 @@ LL | println!("{:.*}");
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
-error: 1 positional argument in format string, but no arguments were given
- --> $DIR/ifmt-bad-arg.rs:97:15
+error: invalid reference to positional argument 0 (no arguments were given)
+ --> $DIR/ifmt-bad-arg.rs:97:16
|
LL | println!("{:.0$}");
- | ^^---^
- | |
- | this precision flag expects an `usize` argument at position 0, but no arguments were given
+ | ^^^^
|
= note: positional arguments are zero-based
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
@@ -318,10 +300,10 @@ error[E0308]: mismatched types
--> $DIR/ifmt-bad-arg.rs:78:32
|
LL | println!("{} {:.*} {}", 1, 3.2, 4);
- | ---------------------------^^^----
- | | |
- | | expected `usize`, found floating-point number
- | arguments to this function are incorrect
+ | ^^^
+ | |
+ | expected `usize`, found floating-point number
+ | arguments to this function are incorrect
|
= note: expected reference `&usize`
found reference `&{float}`
@@ -336,10 +318,10 @@ error[E0308]: mismatched types
--> $DIR/ifmt-bad-arg.rs:81:35
|
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
- | ------------------------------^^^----
- | | |
- | | expected `usize`, found floating-point number
- | arguments to this function are incorrect
+ | ^^^
+ | |
+ | expected `usize`, found floating-point number
+ | arguments to this function are incorrect
|
= note: expected reference `&usize`
found reference `&{float}`
diff --git a/src/test/ui/for-loop-while/while-let-2.stderr b/src/test/ui/for-loop-while/while-let-2.stderr
index 2d23a6373..1b1cf6792 100644
--- a/src/test/ui/for-loop-while/while-let-2.stderr
+++ b/src/test/ui/for-loop-while/while-let-2.stderr
@@ -9,9 +9,9 @@ LL | | println!("irrefutable pattern");
LL | | });
| |______- in this macro invocation
|
- = note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the loop will never exit
= help: consider instead using a `loop { ... }` with a `let` inside it
+ = note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: irrefutable `while let` pattern
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
index aed7f72c6..a8f23f81d 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
@@ -5,6 +5,18 @@ 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`
+ |
+ = 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
+ --> $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
+ --> $DIR/fully-qualified-type-name2.rs:8:5
+ |
+LL | pub enum Foo { }
+ | ^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/function-pointer/issue-102289.rs b/src/test/ui/function-pointer/issue-102289.rs
new file mode 100644
index 000000000..de394ca9a
--- /dev/null
+++ b/src/test/ui/function-pointer/issue-102289.rs
@@ -0,0 +1,54 @@
+// check-pass
+
+pub(crate) trait Parser: Sized {
+ type Output;
+ fn parse(&mut self, _input: &str) -> Result<(), ()> {
+ loop {}
+ }
+ fn map<F, B>(self, _f: F) -> Map<Self, F>
+ where
+ F: FnMut(Self::Output) -> B,
+ {
+ todo!()
+ }
+}
+
+pub(crate) struct Chainl1<P, Op>(P, Op);
+impl<P, Op> Parser for Chainl1<P, Op>
+where
+ P: Parser,
+ Op: Parser,
+ Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
+{
+ type Output = P::Output;
+}
+pub(crate) fn chainl1<P, Op>(_parser: P, _op: Op) -> Chainl1<P, Op>
+where
+ P: Parser,
+ Op: Parser,
+ Op::Output: FnOnce(P::Output, P::Output) -> P::Output,
+{
+ loop {}
+}
+
+pub(crate) struct Map<P, F>(P, F);
+impl<A, B, P, F> Parser for Map<P, F>
+where
+ P: Parser<Output = A>,
+ F: FnMut(A) -> B,
+{
+ type Output = B;
+}
+
+impl Parser for u32 {
+ type Output = ();
+}
+
+pub fn chainl1_error_consume() {
+ fn first<T, U>(t: T, _: U) -> T {
+ t
+ }
+ let _ = chainl1(1, 1.map(|_| first)).parse("");
+}
+
+fn main() {}
diff --git a/src/test/ui/function-pointer/sized-ret-with-binder.rs b/src/test/ui/function-pointer/sized-ret-with-binder.rs
new file mode 100644
index 000000000..104ac4d22
--- /dev/null
+++ b/src/test/ui/function-pointer/sized-ret-with-binder.rs
@@ -0,0 +1,15 @@
+// check-pass
+
+#![feature(unboxed_closures)]
+
+fn is_fn<T: for<'a> Fn<(&'a (),)>>() {}
+fn is_fn2<T: for<'a, 'b> Fn<(&'a &'b (),)>>() {}
+
+struct Outlives<'a, 'b>(std::marker::PhantomData<&'a &'b ()>);
+
+fn main() {
+ is_fn::<for<'a> fn(&'a ()) -> &'a ()>();
+ is_fn::<for<'a> fn(&'a ()) -> &'a dyn std::fmt::Debug>();
+ is_fn2::<for<'a, 'b> fn(&'a &'b ()) -> Outlives<'a, 'b>>();
+ is_fn2::<for<'a, 'b> fn(&'a &'b ()) -> (&'a (), &'a ())>();
+}
diff --git a/src/test/ui/function-pointer/unsized-ret.rs b/src/test/ui/function-pointer/unsized-ret.rs
new file mode 100644
index 000000000..60af5769d
--- /dev/null
+++ b/src/test/ui/function-pointer/unsized-ret.rs
@@ -0,0 +1,14 @@
+#![feature(fn_traits)]
+#![feature(unboxed_closures)]
+
+fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+ let y = (f.unwrap()).call(t);
+}
+
+fn main() {
+ foo::<fn() -> str, _>(None, ());
+ //~^ ERROR the size for values of type `str` cannot be known at compilation time
+
+ foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),));
+ //~^ ERROR the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time
+}
diff --git a/src/test/ui/function-pointer/unsized-ret.stderr b/src/test/ui/function-pointer/unsized-ret.stderr
new file mode 100644
index 000000000..bec3e2aa3
--- /dev/null
+++ b/src/test/ui/function-pointer/unsized-ret.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+ --> $DIR/unsized-ret.rs:9:27
+ |
+LL | foo::<fn() -> str, _>(None, ());
+ | --------------------- ^^^^ doesn't have a size known at compile-time
+ | |
+ | required by a bound introduced by this call
+ |
+ = help: within `fn() -> str`, the trait `Sized` is not implemented for `str`
+ = note: required because it appears within the type `fn() -> str`
+note: required by a bound in `foo`
+ --> $DIR/unsized-ret.rs:4:11
+ |
+LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+ | ^^^^^ required by this bound in `foo`
+
+error[E0277]: the size for values of type `(dyn std::fmt::Display + 'a)` cannot be known at compilation time
+ --> $DIR/unsized-ret.rs:12:66
+ |
+LL | foo::<for<'a> fn(&'a ()) -> (dyn std::fmt::Display + 'a), _>(None, (&(),));
+ | ------------------------------------------------------------ ^^^^ doesn't have a size known at compile-time
+ | |
+ | 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 std::fmt::Display + 'a)`
+note: required by a bound in `foo`
+ --> $DIR/unsized-ret.rs:4:11
+ |
+LL | fn foo<F: Fn<T>, T>(f: Option<F>, t: T) {
+ | ^^^^^ required by this bound in `foo`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/future-incompatible-lint-group.stderr b/src/test/ui/future-incompatible-lint-group.stderr
index 8f6dde665..a8fb100a7 100644
--- a/src/test/ui/future-incompatible-lint-group.stderr
+++ b/src/test/ui/future-incompatible-lint-group.stderr
@@ -4,9 +4,9 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
LL | fn f(u8) {}
| ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
|
- = note: `#[warn(anonymous_parameters)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+ = note: `#[warn(anonymous_parameters)]` on by default
error: this attribute can only be applied at the crate level
--> $DIR/future-incompatible-lint-group.rs:13:12
@@ -14,15 +14,15 @@ error: this attribute can only be applied at the crate level
LL | #![doc(test(some_test))]
| ^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
note: the lint level is defined here
--> $DIR/future-incompatible-lint-group.rs:3:9
|
LL | #![deny(future_incompatible)]
| ^^^^^^^^^^^^^^^^^^^
= note: `#[deny(invalid_doc_attributes)]` implied by `#[deny(future_incompatible)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
- = note: read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/generator/issue-102645.rs b/src/test/ui/generator/issue-102645.rs
new file mode 100644
index 000000000..0589c5a00
--- /dev/null
+++ b/src/test/ui/generator/issue-102645.rs
@@ -0,0 +1,23 @@
+// compile-flags: -Zdrop-tracking
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+use std::pin::Pin;
+
+fn main() {
+ let mut a = 5;
+ let mut b = || {
+ let d = 6;
+ yield;
+ _zzz(); // #break
+ a = d;
+ };
+ Pin::new(&mut b).resume();
+ //~^ ERROR this function takes 1 argument but 0 arguments were supplied
+ // This type error is required to reproduce the ICE...
+}
+
+fn _zzz() {
+ ()
+}
diff --git a/src/test/ui/generator/issue-102645.stderr b/src/test/ui/generator/issue-102645.stderr
new file mode 100644
index 000000000..7b4d50213
--- /dev/null
+++ b/src/test/ui/generator/issue-102645.stderr
@@ -0,0 +1,19 @@
+error[E0061]: this function takes 1 argument but 0 arguments were supplied
+ --> $DIR/issue-102645.rs:16:22
+ |
+LL | Pin::new(&mut b).resume();
+ | ^^^^^^-- an argument of type `()` is missing
+ |
+note: associated function defined here
+ --> $SRC_DIR/core/src/ops/generator.rs:LL:COL
+ |
+LL | fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
+ | ^^^^^^
+help: provide the argument
+ |
+LL | Pin::new(&mut b).resume(());
+ | ~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/generator/issue-52398.stderr b/src/test/ui/generator/issue-52398.stderr
index 3f8ebb5a7..30a6732f7 100644
--- a/src/test/ui/generator/issue-52398.stderr
+++ b/src/test/ui/generator/issue-52398.stderr
@@ -6,8 +6,8 @@ LL | | A.test(yield);
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: unused generator that must be used
--> $DIR/issue-52398.rs:24:5
diff --git a/src/test/ui/generator/issue-57084.stderr b/src/test/ui/generator/issue-57084.stderr
index 32a04f94d..29aca9440 100644
--- a/src/test/ui/generator/issue-57084.stderr
+++ b/src/test/ui/generator/issue-57084.stderr
@@ -9,8 +9,8 @@ LL | | }
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/match-bindings.stderr b/src/test/ui/generator/match-bindings.stderr
index 4fd1e26f0..b911b6661 100644
--- a/src/test/ui/generator/match-bindings.stderr
+++ b/src/test/ui/generator/match-bindings.stderr
@@ -10,8 +10,8 @@ LL | | }
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/panic-drops-resume.rs b/src/test/ui/generator/panic-drops-resume.rs
index 8d8eb6a97..4c3caeb14 100644
--- a/src/test/ui/generator/panic-drops-resume.rs
+++ b/src/test/ui/generator/panic-drops-resume.rs
@@ -2,8 +2,6 @@
// run-pass
// needs-unwind
-// ignore-wasm no unwind support
-// ignore-emscripten no unwind support
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/generator/panic-drops.rs b/src/test/ui/generator/panic-drops.rs
index a9de4e7fc..65001fd87 100644
--- a/src/test/ui/generator/panic-drops.rs
+++ b/src/test/ui/generator/panic-drops.rs
@@ -1,7 +1,6 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/generator/panic-safe.rs b/src/test/ui/generator/panic-safe.rs
index 14a0c8dba..3db80bb58 100644
--- a/src/test/ui/generator/panic-safe.rs
+++ b/src/test/ui/generator/panic-safe.rs
@@ -1,7 +1,6 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr
index 3a83021dd..2e0207804 100644
--- a/src/test/ui/generator/print/generator-print-verbose-1.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr
@@ -9,7 +9,7 @@ note: generator is not `Send` as this value is used across a yield
--> $DIR/generator-print-verbose-1.rs:35:9
|
LL | let _non_send_gen = make_non_send_generator();
- | ------------- has type `Opaque(DefId(0:34 ~ generator_print_verbose_1[749a]::make_non_send_generator::{opaque#0}), [])` which is not `Send`
+ | ------------- has type `Opaque(DefId(0:44 ~ 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 | };
@@ -35,17 +35,17 @@ note: required because it's used within this generator
|
LL | || {
| ^^
-note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
+note: required because it appears within the type `Opaque(DefId(0:45 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc<std::cell::RefCell<i32>>])`
--> $DIR/generator-print-verbose-1.rs:41:30
|
LL | pub fn make_gen2<T>(t: T) -> impl Generator<Return = T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
+note: required because it appears within the type `Opaque(DefId(0:46 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`
--> $DIR/generator-print-verbose-1.rs:47:34
|
LL | fn make_non_send_generator2() -> impl Generator<Return = Arc<RefCell<i32>>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: required because it captures the following types: `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()`
+ = note: required because it captures the following types: `Opaque(DefId(0:46 ~ 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
|
diff --git a/src/test/ui/generator/reborrow-mut-upvar.stderr b/src/test/ui/generator/reborrow-mut-upvar.stderr
index ff511b766..e83dbf833 100644
--- a/src/test/ui/generator/reborrow-mut-upvar.stderr
+++ b/src/test/ui/generator/reborrow-mut-upvar.stderr
@@ -10,8 +10,8 @@ LL | | *bar = 2;
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/resume-after-return.rs b/src/test/ui/generator/resume-after-return.rs
index 538609b98..01a059a16 100644
--- a/src/test/ui/generator/resume-after-return.rs
+++ b/src/test/ui/generator/resume-after-return.rs
@@ -1,7 +1,6 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs
index 3c756a86f..601a31418 100644
--- a/src/test/ui/generator/size-moved-locals.rs
+++ b/src/test/ui/generator/size-moved-locals.rs
@@ -12,6 +12,7 @@
// edition:2018
// ignore-wasm32 issue #62807
// ignore-asmjs issue #62807
+// needs-unwind Size of Closures change on panic=abort
#![feature(generators, generator_trait)]
diff --git a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
index 72a2bd4eb..5cb43067f 100644
--- a/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
+++ b/src/test/ui/generator/too-live-local-in-immovable-gen.stderr
@@ -10,8 +10,8 @@ LL | | let _ = &a;
LL | | };
| |__________^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/yield-in-args-rev.stderr b/src/test/ui/generator/yield-in-args-rev.stderr
index a575bf886..c9e1ab722 100644
--- a/src/test/ui/generator/yield-in-args-rev.stderr
+++ b/src/test/ui/generator/yield-in-args-rev.stderr
@@ -7,8 +7,8 @@ LL | | foo(yield, &b);
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/yield-in-box.stderr b/src/test/ui/generator/yield-in-box.stderr
index 7602e8039..8587e1dc6 100644
--- a/src/test/ui/generator/yield-in-box.stderr
+++ b/src/test/ui/generator/yield-in-box.stderr
@@ -10,8 +10,8 @@ LL | | }
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/yield-in-initializer.stderr b/src/test/ui/generator/yield-in-initializer.stderr
index e79047ae7..07de24662 100644
--- a/src/test/ui/generator/yield-in-initializer.stderr
+++ b/src/test/ui/generator/yield-in-initializer.stderr
@@ -10,8 +10,8 @@ LL | | }
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generator/yield-subtype.stderr b/src/test/ui/generator/yield-subtype.stderr
index bded36a4c..fe10477bf 100644
--- a/src/test/ui/generator/yield-subtype.stderr
+++ b/src/test/ui/generator/yield-subtype.stderr
@@ -7,8 +7,8 @@ LL | | yield b;
LL | | };
| |______^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
deleted file mode 100644
index de1b464a4..000000000
--- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error[E0477]: the type `<() as Yay<&'a ()>>::InnerStream<'s>` does not fulfill the required lifetime
- --> $DIR/issue-86218.rs:22:28
- |
-LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: type must outlive the lifetime `'s` as defined here as required by this binding
- --> $DIR/issue-86218.rs:22:22
- |
-LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
- | ^^
-
-error: unconstrained opaque type
- --> $DIR/issue-86218.rs:22:28
- |
-LL | type InnerStream<'s> = impl Stream<Item = i32> + 's;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `InnerStream` must be used in combination with a concrete type within the same module
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0477`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
index c5fd58096..a9a70bb71 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr
@@ -9,8 +9,8 @@ LL | do_something(SomeImplementation(), test);
LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {}
| ------------------------------------------------- found signature defined here
|
- = note: expected function signature `for<'r> fn(&'r mut std::iter::Empty<usize>) -> _`
- found function signature `for<'a, 'r> fn(&'r mut <_ as Iterable>::Iterator<'a>) -> _`
+ = note: expected function signature `for<'a> fn(&'a mut std::iter::Empty<usize>) -> _`
+ found function signature `for<'a, 'b> fn(&'b mut <_ as Iterable>::Iterator<'a>) -> _`
note: required by a bound in `do_something`
--> $DIR/issue-88382.rs:20:48
|
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
deleted file mode 100644
index 3f72734ef..000000000
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0271]: type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
- --> $DIR/issue-89008.rs:38:43
- |
-LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
- | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<Empty<_> as Stream>::Item == Repr`
- | |
- | this type parameter
- |
-note: expected this to be `()`
- --> $DIR/issue-89008.rs:17:17
- |
-LL | type Item = ();
- | ^^
- = note: expected unit type `()`
- found type parameter `Repr`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/generic-associated-types/bugs/issue-91762.rs b/src/test/ui/generic-associated-types/bugs/issue-91762.rs
index 796935cc0..dec668bec 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-91762.rs
+++ b/src/test/ui/generic-associated-types/bugs/issue-91762.rs
@@ -1,7 +1,7 @@
// check-fail
// known-bug
-// We almost certaintly want this to pass, but
+// We almost certainly want this to pass, but
// it's particularly difficult currently, because we need a way of specifying
// that `<Self::Base as Functor>::With<T> = Self` without using that when we have
// a `U`. See `https://github.com/rust-lang/rust/pull/92728` for a (hacky)
diff --git a/src/test/ui/generic-associated-types/issue-102114.rs b/src/test/ui/generic-associated-types/issue-102114.rs
new file mode 100644
index 000000000..de31737ef
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102114.rs
@@ -0,0 +1,16 @@
+trait A {
+ type B<'b>;
+ fn a() -> Self::B<'static>;
+}
+
+struct C;
+
+struct Wrapper<T>(T);
+
+impl A for C {
+ type B<T> = Wrapper<T>;
+ //~^ ERROR type `B` has 1 type parameter but its trait declaration has 0 type parameters
+ fn a() -> Self::B<'static> {}
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-102114.stderr b/src/test/ui/generic-associated-types/issue-102114.stderr
new file mode 100644
index 000000000..8e41dee54
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-102114.stderr
@@ -0,0 +1,12 @@
+error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
+ --> $DIR/issue-102114.rs:11:12
+ |
+LL | type B<'b>;
+ | -- expected 0 type parameters
+...
+LL | type B<T> = Wrapper<T>;
+ | ^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/generic-associated-types/issue-86218-2.rs b/src/test/ui/generic-associated-types/issue-86218-2.rs
new file mode 100644
index 000000000..63c839ea8
--- /dev/null
+++ b/src/test/ui/generic-associated-types/issue-86218-2.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+pub trait Stream {
+ type Item;
+}
+
+impl Stream for () {
+ type Item = i32;
+}
+
+trait Yay<AdditionalValue> {
+ type InnerStream<'s>: Stream<Item = i32> + 's;
+ fn foo<'s>() -> Self::InnerStream<'s>;
+}
+
+impl<T> Yay<T> for () {
+ type InnerStream<'s> = impl Stream<Item = i32> + 's;
+ fn foo<'s>() -> Self::InnerStream<'s> { () }
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/issue-86218.rs
index 3a2d758e7..b2c3071f0 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs
+++ b/src/test/ui/generic-associated-types/issue-86218.rs
@@ -1,7 +1,4 @@
-// check-fail
-// known-bug: #86218
-
-// This should pass, but seems to run into a TAIT issue.
+// check-pass
#![feature(type_alias_impl_trait)]
@@ -20,7 +17,8 @@ trait Yay<AdditionalValue> {
impl<'a> Yay<&'a ()> for () {
type InnerStream<'s> = impl Stream<Item = i32> + 's;
- fn foo<'s>() -> Self::InnerStream<'s> { todo!() }
+ //^ ERROR does not fulfill the required lifetime
+ fn foo<'s>() -> Self::InnerStream<'s> { () }
}
fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-87258_a.stderr b/src/test/ui/generic-associated-types/issue-87258_a.stderr
index fa0748a28..eae9bd9b1 100644
--- a/src/test/ui/generic-associated-types/issue-87258_a.stderr
+++ b/src/test/ui/generic-associated-types/issue-87258_a.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
LL | type FooFuture<'a> = impl Trait1;
| ^^^^^^^^^^^
|
- = note: `FooFuture` must be used in combination with a concrete type within the same module
+ = note: `FooFuture` must be used in combination with a concrete type within the same impl
error: aborting due to previous error
diff --git a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
index d8e889aec..11c4ebf60 100644
--- a/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
+++ b/src/test/ui/generic-associated-types/issue-87429-specialization.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: can't compare `Foo` with `Foo`
--> $DIR/issue-87429-specialization.rs:20:31
diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/issue-89008.rs
index 012aa8df2..669dbafb5 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs
+++ b/src/test/ui/generic-associated-types/issue-89008.rs
@@ -1,42 +1,36 @@
-// check-fail
+// check-pass
// edition:2021
-// known-bug: #88908
-
-// This should pass, but seems to run into a TAIT bug.
#![feature(type_alias_impl_trait)]
use std::future::Future;
+use std::marker::PhantomData;
trait Stream {
type Item;
}
-struct Empty<T>(T);
-impl<T> Stream for Empty<T> {
- type Item = ();
+struct Empty<T> {
+ _phantom: PhantomData<T>,
}
-fn empty<T>() -> Empty<T> {
- todo!()
+
+impl<T> Stream for Empty<T> {
+ type Item = T;
}
trait X {
type LineStream<'a, Repr>: Stream<Item = Repr> where Self: 'a;
-
- type LineStreamFut<'a,Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;
-
- fn line_stream<'a,Repr>(&'a self) -> Self::LineStreamFut<'a,Repr>;
+ type LineStreamFut<'a, Repr>: Future<Output = Self::LineStream<'a, Repr>> where Self: 'a;
+ fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr>;
}
struct Y;
impl X for Y {
type LineStream<'a, Repr> = impl Stream<Item = Repr>;
-
- type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>> ;
-
+ type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {
- async {empty()}
+ async { Empty { _phantom: PhantomData } }
}
}
diff --git a/src/test/ui/generics/issue-94923.rs b/src/test/ui/generics/issue-94923.rs
new file mode 100644
index 000000000..d337a5dff
--- /dev/null
+++ b/src/test/ui/generics/issue-94923.rs
@@ -0,0 +1,49 @@
+// run-pass
+// regression test for issue #94923
+// min-llvm-version: 15.0.0
+// compile-flags: -C opt-level=3
+
+fn f0<T>(mut x: usize) -> usize {
+ for _ in 0..1000 {
+ x *= 123;
+ x %= 99
+ }
+ x + 321 // function composition is not just longer iteration
+}
+
+fn f1<T>(x: usize) -> usize {
+ f0::<(i8, T)>(f0::<(u8, T)>(x))
+}
+
+fn f2<T>(x: usize) -> usize {
+ f1::<(i8, T)>(f1::<(u8, T)>(x))
+}
+
+fn f3<T>(x: usize) -> usize {
+ f2::<(i8, T)>(f2::<(u8, T)>(x))
+}
+
+fn f4<T>(x: usize) -> usize {
+ f3::<(i8, T)>(f3::<(u8, T)>(x))
+}
+
+fn f5<T>(x: usize) -> usize {
+ f4::<(i8, T)>(f4::<(u8, T)>(x))
+}
+
+fn f6<T>(x: usize) -> usize {
+ f5::<(i8, T)>(f5::<(u8, T)>(x))
+}
+
+fn f7<T>(x: usize) -> usize {
+ f6::<(i8, T)>(f6::<(u8, T)>(x))
+}
+
+fn f8<T>(x: usize) -> usize {
+ f7::<(i8, T)>(f7::<(u8, T)>(x))
+}
+
+fn main() {
+ let y = f8::<()>(1);
+ assert_eq!(y, 348);
+}
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
index 3f4c17836..b2e9ffb57 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision.rs
@@ -1,4 +1,4 @@
-#![feature(half_open_range_patterns)]
+#![feature(half_open_range_patterns_in_slices)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
index dedc85491..20f4d8f88 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision2.rs
@@ -1,4 +1,4 @@
-#![feature(half_open_range_patterns)]
+#![feature(half_open_range_patterns_in_slices)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
index 6a9b562cc..14ca07d0a 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.rs
@@ -1,4 +1,3 @@
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
index 665eef2fc..790a13372 100644
--- a/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
+++ b/src/test/ui/half-open-range-patterns/exclusive_range_pattern_syntax_collision3.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:12
+ --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -10,7 +10,7 @@ LL | [..9, 99..100, _] => {},
found type `{integer}`
error[E0308]: mismatched types
- --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:15
+ --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:15
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
@@ -23,7 +23,7 @@ LL | [..9, 99..100, _] => {},
found type `{integer}`
error[E0308]: mismatched types
- --> $DIR/exclusive_range_pattern_syntax_collision3.rs:6:19
+ --> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this expression has type `[std::ops::Range<{integer}>; 3]`
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs
new file mode 100644
index 000000000..dac973473
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.rs
@@ -0,0 +1,7 @@
+#![feature(exclusive_range_pattern)]
+
+fn main() {
+ let xs = [13, 1, 5, 2, 3, 1, 21, 8];
+ let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ //~^ `X..` patterns in slices are experimental
+}
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr
new file mode 100644
index 000000000..ee5b0e11c
--- /dev/null
+++ b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns-in-slices.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `X..` patterns in slices are experimental
+ --> $DIR/feature-gate-half-open-range-patterns-in-slices.rs:5:10
+ |
+LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
+ | ^^^^^^^
+ |
+ = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
+ = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
deleted file mode 100644
index 9281dda67..000000000
--- a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-#![feature(exclusive_range_pattern)]
-
-fn main() {}
-
-#[cfg(FALSE)]
-fn foo() {
- if let ..=5 = 0 {}
- //~^ ERROR half-open range patterns are unstable
- if let ...5 = 0 {}
- //~^ ERROR half-open range patterns are unstable
- //~| ERROR range-to patterns with `...` are not allowed
- if let ..5 = 0 {}
- //~^ ERROR half-open range patterns are unstable
- if let 5..= = 0 {}
- //~^ ERROR inclusive range with no end
- if let 5... = 0 {}
- //~^ ERROR inclusive range with no end
-}
diff --git a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr b/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
deleted file mode 100644
index a04883ae1..000000000
--- a/src/test/ui/half-open-range-patterns/feature-gate-half-open-range-patterns.stderr
+++ /dev/null
@@ -1,53 +0,0 @@
-error: range-to patterns with `...` are not allowed
- --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
- |
-LL | if let ...5 = 0 {}
- | ^^^ help: use `..=` instead
-
-error[E0586]: inclusive range with no end
- --> $DIR/feature-gate-half-open-range-patterns.rs:14:13
- |
-LL | if let 5..= = 0 {}
- | ^^^ help: use `..` instead
- |
- = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
-
-error[E0586]: inclusive range with no end
- --> $DIR/feature-gate-half-open-range-patterns.rs:16:13
- |
-LL | if let 5... = 0 {}
- | ^^^ help: use `..` instead
- |
- = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
-
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:7:12
- |
-LL | if let ..=5 = 0 {}
- | ^^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:9:12
- |
-LL | if let ...5 = 0 {}
- | ^^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error[E0658]: half-open range patterns are unstable
- --> $DIR/feature-gate-half-open-range-patterns.rs:12:12
- |
-LL | if let ..5 = 0 {}
- | ^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
-error: aborting due to 6 previous errors
-
-Some errors have detailed explanations: E0586, E0658.
-For more information about an error, try `rustc --explain E0586`.
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
index b08732219..17ea2b13f 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.rs
@@ -1,4 +1,3 @@
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
index df0dae569..f7c59a196 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-bad-types.stderr
@@ -1,17 +1,17 @@
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/half-open-range-pats-bad-types.rs:5:9
+ --> $DIR/half-open-range-pats-bad-types.rs:4:9
|
LL | let "a".. = "a";
| ^^^ this is of type `&'static str` but it should be `char` or numeric
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/half-open-range-pats-bad-types.rs:6:11
+ --> $DIR/half-open-range-pats-bad-types.rs:5:11
|
LL | let .."a" = "a";
| ^^^ this is of type `&'static str` but it should be `char` or numeric
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/half-open-range-pats-bad-types.rs:7:12
+ --> $DIR/half-open-range-pats-bad-types.rs:6:12
|
LL | let ..="a" = "a";
| ^^^ this is of type `&'static str` but it should be `char` or numeric
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
index be225359b..a2a4c62fa 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.rs
@@ -1,6 +1,5 @@
// Test various non-exhaustive matches for `X..`, `..=X` and `..X` ranges.
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(illegal_floating_point_literal_pattern)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
index d429b4e8e..6b20a820b 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-fail.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:15:8
|
LL | m!(0f32, f32::NEG_INFINITY..);
| ^^^^ pattern `_` not covered
@@ -11,7 +11,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() }
| ++++++++++++++
error[E0004]: non-exhaustive patterns: `_` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:17:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:16:8
|
LL | m!(0f32, ..f32::INFINITY);
| ^^^^ pattern `_` not covered
@@ -23,7 +23,7 @@ LL | match $s { $($t)+ => {}, _ => todo!() }
| ++++++++++++++
error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:25:8
|
LL | m!('a', ..core::char::MAX);
| ^^^ pattern `'\u{10ffff}'` not covered
@@ -35,7 +35,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
| +++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `'\u{10fffe}'..='\u{10ffff}'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:26:8
|
LL | m!('a', ..ALMOST_MAX);
| ^^^ pattern `'\u{10fffe}'..='\u{10ffff}'` not covered
@@ -47,7 +47,7 @@ LL | match $s { $($t)+ => {}, '\u{10fffe}'..='\u{10ffff}' => todo!() }
| ++++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `'\0'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:27:8
|
LL | m!('a', ALMOST_MIN..);
| ^^^ pattern `'\0'` not covered
@@ -59,7 +59,7 @@ LL | match $s { $($t)+ => {}, '\0' => todo!() }
| +++++++++++++++++
error[E0004]: non-exhaustive patterns: `'\u{10ffff}'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:28:8
|
LL | m!('a', ..=ALMOST_MAX);
| ^^^ pattern `'\u{10ffff}'` not covered
@@ -71,7 +71,7 @@ LL | match $s { $($t)+ => {}, '\u{10ffff}' => todo!() }
| +++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `'b'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:29:8
|
LL | m!('a', ..=VAL | VAL_2..);
| ^^^ pattern `'b'` not covered
@@ -83,7 +83,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() }
| ++++++++++++++++
error[E0004]: non-exhaustive patterns: `'b'` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:31:8
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:30:8
|
LL | m!('a', ..VAL_1 | VAL_2..);
| ^^^ pattern `'b'` not covered
@@ -95,7 +95,7 @@ LL | match $s { $($t)+ => {}, 'b' => todo!() }
| ++++++++++++++++
error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:40:12
|
LL | m!(0, ..u8::MAX);
| ^ pattern `u8::MAX` not covered
@@ -107,7 +107,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `254_u8..=u8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:41:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `254_u8..=u8::MAX` not covered
@@ -119,7 +119,7 @@ LL | match $s { $($t)+ => {}, 254_u8..=u8::MAX => todo!() }
| +++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `0_u8` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:42:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `0_u8` not covered
@@ -131,7 +131,7 @@ LL | match $s { $($t)+ => {}, 0_u8 => todo!() }
| +++++++++++++++++
error[E0004]: non-exhaustive patterns: `u8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:43:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `u8::MAX` not covered
@@ -143,7 +143,7 @@ LL | match $s { $($t)+ => {}, u8::MAX => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u8` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:44:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_u8` not covered
@@ -155,7 +155,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u8` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:46:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:45:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_u8` not covered
@@ -167,7 +167,7 @@ LL | match $s { $($t)+ => {}, 43_u8 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:53:12
|
LL | m!(0, ..u16::MAX);
| ^ pattern `u16::MAX` not covered
@@ -179,7 +179,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `65534_u16..=u16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:54:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `65534_u16..=u16::MAX` not covered
@@ -191,7 +191,7 @@ LL | match $s { $($t)+ => {}, 65534_u16..=u16::MAX => todo!() }
| +++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `0_u16` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:55:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `0_u16` not covered
@@ -203,7 +203,7 @@ LL | match $s { $($t)+ => {}, 0_u16 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:56:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `u16::MAX` not covered
@@ -215,7 +215,7 @@ LL | match $s { $($t)+ => {}, u16::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u16` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:57:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_u16` not covered
@@ -227,7 +227,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u16` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:59:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:58:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_u16` not covered
@@ -239,7 +239,7 @@ LL | match $s { $($t)+ => {}, 43_u16 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:66:12
|
LL | m!(0, ..u32::MAX);
| ^ pattern `u32::MAX` not covered
@@ -251,7 +251,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `4294967294_u32..=u32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:67:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `4294967294_u32..=u32::MAX` not covered
@@ -263,7 +263,7 @@ LL | match $s { $($t)+ => {}, 4294967294_u32..=u32::MAX => todo!() }
| ++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `0_u32` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:68:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `0_u32` not covered
@@ -275,7 +275,7 @@ LL | match $s { $($t)+ => {}, 0_u32 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:69:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `u32::MAX` not covered
@@ -287,7 +287,7 @@ LL | match $s { $($t)+ => {}, u32::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u32` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:70:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_u32` not covered
@@ -299,7 +299,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u32` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:72:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:71:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_u32` not covered
@@ -311,7 +311,7 @@ LL | match $s { $($t)+ => {}, 43_u32 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:79:12
|
LL | m!(0, ..u64::MAX);
| ^ pattern `u64::MAX` not covered
@@ -323,7 +323,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `18446744073709551614_u64..=u64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:80:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `18446744073709551614_u64..=u64::MAX` not covered
@@ -335,7 +335,7 @@ LL | match $s { $($t)+ => {}, 18446744073709551614_u64..=u64::MAX => tod
| ++++++++++++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `0_u64` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:81:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `0_u64` not covered
@@ -347,7 +347,7 @@ LL | match $s { $($t)+ => {}, 0_u64 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:82:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `u64::MAX` not covered
@@ -359,7 +359,7 @@ LL | match $s { $($t)+ => {}, u64::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u64` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:83:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_u64` not covered
@@ -371,7 +371,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u64` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:85:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:84:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_u64` not covered
@@ -383,7 +383,7 @@ LL | match $s { $($t)+ => {}, 43_u64 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:92:12
|
LL | m!(0, ..u128::MAX);
| ^ pattern `u128::MAX` not covered
@@ -395,7 +395,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() }
| ++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:93:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `340282366920938463463374607431768211454_u128..=u128::MAX` not covered
@@ -407,7 +407,7 @@ LL | match $s { $($t)+ => {}, 340282366920938463463374607431768211454_u1
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `0_u128` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:94:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `0_u128` not covered
@@ -419,7 +419,7 @@ LL | match $s { $($t)+ => {}, 0_u128 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `u128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:95:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `u128::MAX` not covered
@@ -431,7 +431,7 @@ LL | match $s { $($t)+ => {}, u128::MAX => todo!() }
| ++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u128` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:96:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_u128` not covered
@@ -443,7 +443,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_u128` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:98:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:97:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_u128` not covered
@@ -455,7 +455,7 @@ LL | match $s { $($t)+ => {}, 43_u128 => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:108:12
|
LL | m!(0, ..i8::MAX);
| ^ pattern `i8::MAX` not covered
@@ -467,7 +467,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `126_i8..=i8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:109:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `126_i8..=i8::MAX` not covered
@@ -479,7 +479,7 @@ LL | match $s { $($t)+ => {}, 126_i8..=i8::MAX => todo!() }
| +++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i8::MIN` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:110:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `i8::MIN` not covered
@@ -491,7 +491,7 @@ LL | match $s { $($t)+ => {}, i8::MIN => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i8::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:111:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `i8::MAX` not covered
@@ -503,7 +503,7 @@ LL | match $s { $($t)+ => {}, i8::MAX => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i8` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:112:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_i8` not covered
@@ -515,7 +515,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i8` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:114:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:113:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_i8` not covered
@@ -527,7 +527,7 @@ LL | match $s { $($t)+ => {}, 43_i8 => todo!() }
| ++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:121:12
|
LL | m!(0, ..i16::MAX);
| ^ pattern `i16::MAX` not covered
@@ -539,7 +539,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `32766_i16..=i16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:122:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `32766_i16..=i16::MAX` not covered
@@ -551,7 +551,7 @@ LL | match $s { $($t)+ => {}, 32766_i16..=i16::MAX => todo!() }
| +++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i16::MIN` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:123:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `i16::MIN` not covered
@@ -563,7 +563,7 @@ LL | match $s { $($t)+ => {}, i16::MIN => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i16::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:124:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `i16::MAX` not covered
@@ -575,7 +575,7 @@ LL | match $s { $($t)+ => {}, i16::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i16` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:125:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_i16` not covered
@@ -587,7 +587,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i16` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:127:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:126:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_i16` not covered
@@ -599,7 +599,7 @@ LL | match $s { $($t)+ => {}, 43_i16 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:134:12
|
LL | m!(0, ..i32::MAX);
| ^ pattern `i32::MAX` not covered
@@ -611,7 +611,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `2147483646_i32..=i32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:135:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `2147483646_i32..=i32::MAX` not covered
@@ -623,7 +623,7 @@ LL | match $s { $($t)+ => {}, 2147483646_i32..=i32::MAX => todo!() }
| ++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i32::MIN` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:136:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `i32::MIN` not covered
@@ -635,7 +635,7 @@ LL | match $s { $($t)+ => {}, i32::MIN => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i32::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:137:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `i32::MAX` not covered
@@ -647,7 +647,7 @@ LL | match $s { $($t)+ => {}, i32::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i32` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:138:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_i32` not covered
@@ -659,7 +659,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i32` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:140:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:139:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_i32` not covered
@@ -671,7 +671,7 @@ LL | match $s { $($t)+ => {}, 43_i32 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:147:12
|
LL | m!(0, ..i64::MAX);
| ^ pattern `i64::MAX` not covered
@@ -683,7 +683,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `9223372036854775806_i64..=i64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:148:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `9223372036854775806_i64..=i64::MAX` not covered
@@ -695,7 +695,7 @@ LL | match $s { $($t)+ => {}, 9223372036854775806_i64..=i64::MAX => todo
| +++++++++++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i64::MIN` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:149:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `i64::MIN` not covered
@@ -707,7 +707,7 @@ LL | match $s { $($t)+ => {}, i64::MIN => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i64::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:150:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `i64::MAX` not covered
@@ -719,7 +719,7 @@ LL | match $s { $($t)+ => {}, i64::MAX => todo!() }
| +++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i64` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:151:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_i64` not covered
@@ -731,7 +731,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i64` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:153:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:152:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_i64` not covered
@@ -743,7 +743,7 @@ LL | match $s { $($t)+ => {}, 43_i64 => todo!() }
| +++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:160:12
|
LL | m!(0, ..i128::MAX);
| ^ pattern `i128::MAX` not covered
@@ -755,7 +755,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() }
| ++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:161:12
|
LL | m!(0, ..ALMOST_MAX);
| ^ pattern `170141183460469231731687303715884105726_i128..=i128::MAX` not covered
@@ -767,7 +767,7 @@ LL | match $s { $($t)+ => {}, 170141183460469231731687303715884105726_i1
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i128::MIN` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:162:12
|
LL | m!(0, ALMOST_MIN..);
| ^ pattern `i128::MIN` not covered
@@ -779,7 +779,7 @@ LL | match $s { $($t)+ => {}, i128::MIN => todo!() }
| ++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `i128::MAX` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:163:12
|
LL | m!(0, ..=ALMOST_MAX);
| ^ pattern `i128::MAX` not covered
@@ -791,7 +791,7 @@ LL | match $s { $($t)+ => {}, i128::MAX => todo!() }
| ++++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i128` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:164:12
|
LL | m!(0, ..=VAL | VAL_2..);
| ^ pattern `43_i128` not covered
@@ -803,7 +803,7 @@ LL | match $s { $($t)+ => {}, 43_i128 => todo!() }
| ++++++++++++++++++++
error[E0004]: non-exhaustive patterns: `43_i128` not covered
- --> $DIR/half-open-range-pats-exhaustive-fail.rs:166:12
+ --> $DIR/half-open-range-pats-exhaustive-fail.rs:165:12
|
LL | m!(0, ..VAL_1 | VAL_2..);
| ^ pattern `43_i128` not covered
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
index d3a59e4df..4b7eee134 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-exhaustive-pass.rs
@@ -2,7 +2,6 @@
// Test various exhaustive matches for `X..`, `..=X` and `..X` ranges.
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
fn main() {}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
index daed775cf..526a797e9 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs
@@ -7,8 +7,6 @@
// there's a potential confusion factor here, and we would prefer to keep patterns
// and expressions in-sync. As such, we do not allow `...X` in patterns either.
-#![feature(half_open_range_patterns)]
-
fn main() {}
#[cfg(FALSE)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
index da37ff301..ddffeaf97 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr
@@ -1,29 +1,29 @@
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9
+ --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:15:9
|
LL | ...X => {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9
+ --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:16:9
|
LL | ...0 => {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:19:9
+ --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:17:9
|
LL | ...'a' => {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:20:9
+ --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:18:9
|
LL | ...0.0f32 => {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:27:17
+ --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17
|
LL | let ...$e;
| ^^^ help: use `..=` instead
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
index 9ace0c357..6567c8cc6 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.rs
@@ -1,8 +1,6 @@
// Test `X...` and `X..=` range patterns not being allowed syntactically.
// FIXME(Centril): perhaps these should be semantic restrictions.
-#![feature(half_open_range_patterns)]
-
fn main() {}
#[cfg(FALSE)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
index 5a504a90b..3ad84b0ef 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr
@@ -1,5 +1,5 @@
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:10:13
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:8:13
|
LL | if let 0... = 1 {}
| ^^^ help: use `..` instead
@@ -7,7 +7,7 @@ LL | if let 0... = 1 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:9:13
|
LL | if let 0..= = 1 {}
| ^^^ help: use `..` instead
@@ -15,7 +15,7 @@ LL | if let 0..= = 1 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:13:13
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:11:13
|
LL | if let X... = 1 {}
| ^^^ help: use `..` instead
@@ -23,7 +23,7 @@ LL | if let X... = 1 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:14:13
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:12:13
|
LL | if let X..= = 1 {}
| ^^^ help: use `..` instead
@@ -31,7 +31,7 @@ LL | if let X..= = 1 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:19
|
LL | let $e...;
| ^^^ help: use `..` instead
@@ -43,7 +43,7 @@ LL | mac!(0);
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-inclusive-no-end.rs:21:19
+ --> $DIR/half-open-range-pats-inclusive-no-end.rs:19:19
|
LL | let $e..=;
| ^^^ help: use `..` instead
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
index f054bbea4..2d63fe078 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.rs
@@ -1,5 +1,3 @@
-#![feature(half_open_range_patterns)]
-
fn main() {}
#[cfg(FALSE)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
index 93b73c57e..111e81799 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-ref-ambiguous-interp.stderr
@@ -1,11 +1,11 @@
error: the range pattern here has ambiguous interpretation
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:6:10
|
LL | &0.. | _ => {}
| ^^^ help: add parentheses to clarify the precedence: `(0..)`
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:11
|
LL | &0..= | _ => {}
| ^^^ help: use `..` instead
@@ -13,13 +13,13 @@ LL | &0..= | _ => {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: the range pattern here has ambiguous interpretation
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
|
LL | &0..= | _ => {}
| ^^^^ help: add parentheses to clarify the precedence: `(0..=)`
error[E0586]: inclusive range with no end
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:11:11
|
LL | &0... | _ => {}
| ^^^ help: use `..` instead
@@ -27,25 +27,25 @@ LL | &0... | _ => {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: the range pattern here has ambiguous interpretation
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:16:10
|
LL | &..0 | _ => {}
| ^^^ help: add parentheses to clarify the precedence: `(..0)`
error: the range pattern here has ambiguous interpretation
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:18:10
|
LL | &..=0 | _ => {}
| ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
error: range-to patterns with `...` are not allowed
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
|
LL | &...0 | _ => {}
| ^^^ help: use `..=` instead
error: the range pattern here has ambiguous interpretation
- --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:22:10
+ --> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:20:10
|
LL | &...0 | _ => {}
| ^^^^ help: add parentheses to clarify the precedence: `(..=0)`
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
index ae532d935..6c6ba9319 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-semantics.rs
@@ -3,7 +3,6 @@
// Test half-open range patterns against their expression equivalents
// via `.contains(...)` and make sure the dynamic semantics match.
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(illegal_floating_point_literal_pattern)]
#![allow(unreachable_patterns)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
index 8bb98d3b5..9a73e8906 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-syntactic-pass.rs
@@ -3,7 +3,6 @@
// Test the parsing of half-open ranges.
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
fn main() {}
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
index 2c8e554b2..f55566602 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
@@ -1,4 +1,3 @@
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
#![allow(illegal_floating_point_literal_pattern)]
diff --git a/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
index 4931ddfac..56b224a85 100644
--- a/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
+++ b/src/test/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
@@ -1,155 +1,155 @@
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11
|
LL | m!(0, ..u8::MIN);
| ^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
|
LL | m!(0, ..u16::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11
|
LL | m!(0, ..u32::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11
|
LL | m!(0, ..u64::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
|
LL | m!(0, ..u128::MIN);
| ^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
|
LL | m!(0, ..i8::MIN);
| ^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:31:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
|
LL | m!(0, ..i16::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11
|
LL | m!(0, ..i32::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11
|
LL | m!(0, ..i64::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:40:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11
|
LL | m!(0, ..i128::MIN);
| ^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:44:14
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14
|
LL | m!(0f32, ..f32::NEG_INFINITY);
| ^^^^^^^^^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:47:14
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14
|
LL | m!(0f64, ..f64::NEG_INFINITY);
| ^^^^^^^^^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:51:13
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13
|
LL | m!('a', ..'\u{0}');
| ^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:12:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11
|
LL | m!(0, ..u8::MIN);
| ^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
|
LL | m!(0, ..u16::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:18:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11
|
LL | m!(0, ..u32::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:21:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11
|
LL | m!(0, ..u64::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
|
LL | m!(0, ..u128::MIN);
| ^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
|
LL | m!(0, ..i8::MIN);
| ^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:31:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
|
LL | m!(0, ..i16::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:34:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11
|
LL | m!(0, ..i32::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:37:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11
|
LL | m!(0, ..i64::MIN);
| ^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:40:11
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11
|
LL | m!(0, ..i128::MIN);
| ^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:44:14
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14
|
LL | m!(0f32, ..f32::NEG_INFINITY);
| ^^^^^^^^^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:47:14
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14
|
LL | m!(0f64, ..f64::NEG_INFINITY);
| ^^^^^^^^^^^^^^^^^^^
error[E0579]: lower range bound must be less than upper
- --> $DIR/half-open-range-pats-thir-lower-empty.rs:51:13
+ --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13
|
LL | m!('a', ..'\u{0}');
| ^^^^^^^^^
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
index bd7953682..11c4ab9c5 100644
--- a/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-4.rs
@@ -1,6 +1,5 @@
// check-pass
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
index 613d907cf..995ef03c8 100644
--- a/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.rs
@@ -1,4 +1,3 @@
-#![feature(half_open_range_patterns)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
index 307ad711b..c60842638 100644
--- a/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
+++ b/src/test/ui/half-open-range-patterns/pat-tuple-5.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/pat-tuple-5.rs:8:10
+ --> $DIR/pat-tuple-5.rs:7:10
|
LL | match (0, 1) {
| ------ this expression has type `({integer}, {integer})`
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs
index 8f745e810..acb7feac1 100644
--- a/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs
+++ b/src/test/ui/half-open-range-patterns/range_pat_interactions0.rs
@@ -1,7 +1,6 @@
// run-pass
#![allow(incomplete_features)]
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
#![feature(inline_const_pat)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs
index 41c7e46df..446ed45f9 100644
--- a/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs
+++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.rs
@@ -16,8 +16,7 @@ fn main() {
//~| exclusive range pattern syntax is experimental
y @ -5.. => range_from.push(y),
y @ ..-7 => assert_eq!(y, -8),
- //~^ half-open range patterns are unstable
- //~| exclusive range pattern syntax is experimental
+ //~^ exclusive range pattern syntax is experimental
y => bottom.push(y),
}
}
diff --git a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr
index 5e36996a4..f7fda6775 100644
--- a/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr
+++ b/src/test/ui/half-open-range-patterns/range_pat_interactions3.stderr
@@ -1,12 +1,3 @@
-error[E0658]: half-open range patterns are unstable
- --> $DIR/range_pat_interactions3.rs:18:17
- |
-LL | y @ ..-7 => assert_eq!(y, -8),
- | ^^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
error[E0658]: inline-const in pattern position is experimental
--> $DIR/range_pat_interactions3.rs:14:20
|
@@ -52,6 +43,6 @@ LL | y @ ..-7 => assert_eq!(y, -8),
= note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
index 2884a2734..d54cbfbf4 100644
--- a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
+++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem0.rs
@@ -1,4 +1,4 @@
-#![feature(half_open_range_patterns)]
+#![feature(half_open_range_patterns_in_slices)]
#![feature(exclusive_range_pattern)]
fn main() {
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
index 9e289b591..c37af75b8 100644
--- a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
+++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.rs
@@ -3,7 +3,6 @@ fn main() {
let xs = [13, 1, 5, 2, 3, 1, 21, 8];
let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
//~^ `X..` patterns in slices are experimental
- //~| half-open range patterns are unstable
//~| exclusive range pattern syntax is experimental
//~| exclusive range pattern syntax is experimental
}
diff --git a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
index eadaf8776..3bca554b1 100644
--- a/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
+++ b/src/test/ui/half-open-range-patterns/slice_pattern_syntax_problem1.stderr
@@ -1,12 +1,3 @@
-error[E0658]: half-open range patterns are unstable
- --> $DIR/slice_pattern_syntax_problem1.rs:4:23
- |
-LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
- | ^^^
- |
- = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
-
error[E0658]: `X..` patterns in slices are experimental
--> $DIR/slice_pattern_syntax_problem1.rs:4:10
|
@@ -14,7 +5,7 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
| ^^^^^^^
|
= note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
- = help: add `#![feature(half_open_range_patterns)]` to the crate attributes to enable
+ = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
error[E0658]: exclusive range pattern syntax is experimental
--> $DIR/slice_pattern_syntax_problem1.rs:4:23
@@ -34,6 +25,6 @@ LL | let [a @ 3.., b @ ..3, c @ 4..6, ..] = xs;
= note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
= help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
index 5e75a4cc8..727b9e6be 100644
--- a/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/hrtb-perfect-forwarding.stderr
@@ -9,8 +9,8 @@ LL | | T: Bar<&'b isize>,
LL | no_hrtb(&mut t);
| --------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
warning: function cannot return without recursing
--> $DIR/hrtb-perfect-forwarding.rs:25:1
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-100689.rs b/src/test/ui/higher-rank-trait-bounds/issue-100689.rs
new file mode 100644
index 000000000..2db7f8a35
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-100689.rs
@@ -0,0 +1,29 @@
+// check-pass
+
+struct Foo<'a> {
+ foo: &'a mut usize,
+}
+
+trait Bar<'a> {
+ type FooRef<'b>
+ where
+ 'a: 'b;
+ fn uwu(foo: Foo<'a>, f: impl for<'b> FnMut(Self::FooRef<'b>));
+}
+impl<'a> Bar<'a> for () {
+ type FooRef<'b>
+ =
+ &'b Foo<'a>
+ where
+ 'a : 'b,
+ ;
+
+ fn uwu(
+ foo: Foo<'a>,
+ mut f: impl for<'b> FnMut(&'b Foo<'a>), //relevant part
+ ) {
+ f(&foo);
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-102899.rs b/src/test/ui/higher-rank-trait-bounds/issue-102899.rs
new file mode 100644
index 000000000..952b81584
--- /dev/null
+++ b/src/test/ui/higher-rank-trait-bounds/issue-102899.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+pub trait BufferTrait<'buffer> {
+ type Subset<'channel>
+ where
+ 'buffer: 'channel;
+
+ fn for_each_subset<F>(&self, f: F)
+ where
+ F: for<'channel> Fn(Self::Subset<'channel>);
+}
+
+pub struct SomeBuffer<'buffer> {
+ samples: &'buffer [()],
+}
+
+impl<'buffer> BufferTrait<'buffer> for SomeBuffer<'buffer> {
+ type Subset<'subset> = Subset<'subset> where 'buffer: 'subset;
+
+ fn for_each_subset<F>(&self, _f: F)
+ where
+ F: for<'subset> Fn(Subset<'subset>),
+ {
+ todo!()
+ }
+}
+
+pub struct Subset<'subset> {
+ buffer: &'subset [()],
+}
+
+fn main() {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
index ffe3d7b81..c1e235441 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/issue-30786.stderr
@@ -19,7 +19,7 @@ note: the following trait bounds were not satisfied:
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<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>`, but its trait bounds were not satisfied
--> $DIR/issue-30786.rs:130:24
|
LL | pub struct Filter<S, F> {
@@ -29,12 +29,12 @@ LL | pub struct Filter<S, F> {
| doesn't satisfy `_: StreamExt`
...
LL | let count = filter.countx();
- | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
+ | ^^^^^^ method cannot be called on `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>` due to unsatisfied trait bounds
|
note: the following trait bounds were not satisfied:
- `&'a mut &Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut &mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r u64 {identity::<u64>}>, [closure@$DIR/issue-30786.rs:129:30: 129:37]>: Stream`
- `&'a mut Filter<Map<Repeat, for<'r> fn(&'r u64) -> &'r 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`
+ `&'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
|
LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr b/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr
index 309e1a676..3f874220a 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/issue-46989.stderr
@@ -4,7 +4,7 @@ error: implementation of `Foo` is not general enough
LL | assert_foo::<fn(&i32)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r i32)`
+ = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0`
error: aborting due to previous error
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-95034.rs b/src/test/ui/higher-rank-trait-bounds/issue-95034.rs
index d8edbe7e5..af4946a18 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-95034.rs
+++ b/src/test/ui/higher-rank-trait-bounds/issue-95034.rs
@@ -1,23 +1,5 @@
-// known-bug: #95034
-// failure-status: 101
+// check-pass
// compile-flags: --edition=2021 --crate-type=lib
-// rustc-env:RUST_BACKTRACE=0
-
-// normalize-stderr-test "thread 'rustc' panicked.*" -> "thread 'rustc' panicked"
-// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
-// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
-// normalize-stderr-test "note:.*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" -> ""
-// normalize-stderr-test "query stack during panic:\n" -> ""
-// normalize-stderr-test "we're just showing a limited slice of the query stack\n" -> ""
-// normalize-stderr-test "end of query stack\n" -> ""
-// normalize-stderr-test "#.*\n" -> ""
-
-// This should not ICE.
-
-// Refer to the issue for more minimized versions.
use std::{
future::Future,
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-95034.stderr b/src/test/ui/higher-rank-trait-bounds/issue-95034.stderr
deleted file mode 100644
index 1d8329142..000000000
--- a/src/test/ui/higher-rank-trait-bounds/issue-95034.stderr
+++ /dev/null
@@ -1 +0,0 @@
-thread 'rustc' panicked
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
index eebce827d..4ef96cd95 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-71955.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>`
- found trait `for<'r> FnOnce<(&'r &str,)>`
+ = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>`
+ found trait `for<'a> FnOnce<(&'a &str,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:45:24
|
@@ -23,8 +23,8 @@ error[E0308]: mismatched types
LL | foo(bar, "string", |s| s.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r, 's> FnOnce<(&'r &'s str,)>`
- found trait `for<'r> FnOnce<(&'r &str,)>`
+ = note: expected trait `for<'a, 'b> FnOnce<(&'a &'b str,)>`
+ found trait `for<'a> FnOnce<(&'a &str,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:45:24
|
@@ -42,8 +42,8 @@ error[E0308]: mismatched types
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
- found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+ = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>`
+ found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:48:24
|
@@ -61,8 +61,8 @@ error[E0308]: mismatched types
LL | foo(baz, "string", |s| s.0.len() == 5);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r, 's> FnOnce<(&'r Wrapper<'s>,)>`
- found trait `for<'r> FnOnce<(&'r Wrapper<'_>,)>`
+ = note: expected trait `for<'a, 'b> FnOnce<(&'a Wrapper<'b>,)>`
+ found trait `for<'a> FnOnce<(&'a Wrapper<'_>,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-71955.rs:48:24
|
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
index de9348f53..c10a0888a 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.rs
@@ -6,7 +6,7 @@ trait SomeTrait<'a> {
fn give_me_ice<T>() {
callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
- //~^ ERROR the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied [E0277]
+ //~^ ERROR the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied [E0277]
}
fn callee<T: Fn<(&'static (),)>>() {
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
index 6a948a116..25a4f6088 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-85455.stderr
@@ -1,12 +1,12 @@
-error[E0277]: the trait bound `for<'r> T: SomeTrait<'r>` is not satisfied
+error[E0277]: the trait bound `for<'a> T: SomeTrait<'a>` is not satisfied
--> $DIR/issue-85455.rs:8:5
|
LL | callee::<fn(&()) -> <T as SomeTrait<'_>>::Associated>();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'r> SomeTrait<'r>` is not implemented for `T`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> SomeTrait<'a>` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
-LL | fn give_me_ice<T: for<'r> SomeTrait<'r>>() {
+LL | fn give_me_ice<T: for<'a> SomeTrait<'a>>() {
| +++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr
index bcfcc28ad..1f2a96a4c 100644
--- a/src/test/ui/hygiene/globs.stderr
+++ b/src/test/ui/hygiene/globs.stderr
@@ -1,9 +1,16 @@
error[E0425]: cannot find function `f` in this scope
--> $DIR/globs.rs:22:9
|
+LL | pub fn g() {}
+ | ---------- similarly named function `g` defined here
+...
LL | f();
- | ^ not found in this scope
+ | ^
+ |
+help: a function with a similar name exists
|
+LL | g();
+ | ~
help: consider importing this function
|
LL | use foo::f;
@@ -12,8 +19,11 @@ LL | use foo::f;
error[E0425]: cannot find function `g` in this scope
--> $DIR/globs.rs:15:5
|
+LL | pub fn f() {}
+ | ---------- similarly named function `f` defined here
+...
LL | g();
- | ^ not found in this scope
+ | ^
...
LL | / m! {
LL | | use bar::*;
@@ -23,6 +33,10 @@ LL | | }
| |_____- in this macro invocation
|
= note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: a function with a similar name exists
+ |
+LL | f();
+ | ~
help: consider importing this function
|
LL | use bar::g;
diff --git a/src/test/ui/hygiene/impl_items-2.rs b/src/test/ui/hygiene/impl_items-2.rs
new file mode 100644
index 000000000..465e444ae
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items-2.rs
@@ -0,0 +1,26 @@
+#![feature(decl_macro)]
+
+trait Trait {
+ fn foo() {}
+}
+
+macro trait_impl() {
+ fn foo() {}
+}
+
+// Check that we error on multiple impl items that resolve to the same trait item.
+impl Trait for i32 {
+ trait_impl!();
+ fn foo() {}
+ //~^ ERROR duplicate definitions with name `foo`: [E0201]
+}
+
+struct Type;
+
+// Check that we do not error with inherent impls.
+impl Type {
+ trait_impl!();
+ fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/impl_items-2.stderr b/src/test/ui/hygiene/impl_items-2.stderr
new file mode 100644
index 000000000..3c0ffeb10
--- /dev/null
+++ b/src/test/ui/hygiene/impl_items-2.stderr
@@ -0,0 +1,15 @@
+error[E0201]: duplicate definitions with name `foo`:
+ --> $DIR/impl_items-2.rs:14:5
+ |
+LL | fn foo() {}
+ | ----------- item in trait
+...
+LL | fn foo() {}
+ | ----------- previous definition here
+...
+LL | fn foo() {}
+ | ^^^^^^^^^^^ duplicate definition
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs
index 37794c6e0..ddb25c06b 100644
--- a/src/test/ui/hygiene/impl_items.rs
+++ b/src/test/ui/hygiene/impl_items.rs
@@ -9,7 +9,7 @@ mod foo {
}
pub macro m() {
- let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+ let _: () = S.f(); //~ ERROR type `for<'a> fn(&'a foo::S) {foo::S::f}` is private
}
}
diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr
index 523309f43..46a250038 100644
--- a/src/test/ui/hygiene/impl_items.stderr
+++ b/src/test/ui/hygiene/impl_items.stderr
@@ -1,4 +1,4 @@
-error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private
+error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private
--> $DIR/impl_items.rs:12:23
|
LL | let _: () = S.f();
diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr
index 17d05dd09..1d2a1e124 100644
--- a/src/test/ui/hygiene/rustc-macro-transparency.stderr
+++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr
@@ -19,14 +19,8 @@ LL | semitransparent;
error[E0423]: expected value, found macro `opaque`
--> $DIR/rustc-macro-transparency.rs:30:5
|
-LL | struct Opaque;
- | -------------- similarly named unit struct `Opaque` defined here
-...
LL | opaque;
- | ^^^^^^
- | |
- | not a value
- | help: a unit struct with a similar name exists (notice the capitalization): `Opaque`
+ | ^^^^^^ not a value
error: aborting due to 3 previous errors
diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr
deleted file mode 100644
index c19702a5b..000000000
--- a/src/test/ui/impl-duplicate-methods.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0201]: duplicate definitions with name `orange`:
- --> $DIR/impl-duplicate-methods.rs:5:5
- |
-LL | fn orange(&self) {}
- | ---------------- previous definition of `orange` here
-LL | fn orange(&self) {}
- | ^^^^^^^^^^^^^^^^ duplicate definition
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0201`.
diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr
index b6e283647..feedfc40a 100644
--- a/src/test/ui/impl-trait/auto-trait-leak.stderr
+++ b/src/test/ui/impl-trait/auto-trait-leak.stderr
@@ -9,12 +9,12 @@ note: ...which requires borrow-checking `cycle1`...
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle1`...
+note: ...which requires processing MIR for `cycle1`...
--> $DIR/auto-trait-leak.rs:12:1
|
LL | fn cycle1() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle1`...
+note: ...which requires preparing `cycle1` for borrow checking...
--> $DIR/auto-trait-leak.rs:12:1
|
LL | fn cycle1() -> impl Clone {
@@ -50,12 +50,12 @@ note: ...which requires borrow-checking `cycle2`...
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `cycle2`...
+note: ...which requires processing MIR for `cycle2`...
--> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing MIR for `cycle2`...
+note: ...which requires preparing `cycle2` for borrow checking...
--> $DIR/auto-trait-leak.rs:19:1
|
LL | fn cycle2() -> impl Clone {
diff --git a/src/test/ui/impl-trait/equality-rpass.stderr b/src/test/ui/impl-trait/equality-rpass.stderr
index 11eeceba0..bde8362fd 100644
--- a/src/test/ui/impl-trait/equality-rpass.stderr
+++ b/src/test/ui/impl-trait/equality-rpass.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index d4a349551..1841b8e5d 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/equality.rs:15:5
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 46053c6e7..e399a6102 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/equality2.rs:25:18
diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr
index fd2e454e7..edf3911e2 100644
--- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2015.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied
+error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied
--> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13
|
LL | fn ice() -> impl AsRef<Fn(&())> {
- | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()`
+ | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()`
error: aborting due to previous error
diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr
index 8f4092273..88e2520bf 100644
--- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.edition2021.stderr
@@ -9,11 +9,11 @@ help: add `dyn` keyword before this trait
LL | fn ice() -> impl AsRef<dyn Fn(&())> {
| +++
-error[E0277]: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied
+error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied
--> $DIR/generic-with-implicit-hrtb-without-dyn.rs:6:13
|
LL | fn ice() -> impl AsRef<Fn(&())> {
- | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not implemented for `()`
+ | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs
index 856dc7a3f..5a922697f 100644
--- a/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs
+++ b/src/test/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs
@@ -4,7 +4,7 @@
#![allow(warnings)]
fn ice() -> impl AsRef<Fn(&())> {
- //~^ ERROR: the trait bound `(): AsRef<(dyn for<'r> Fn(&'r ()) + 'static)>` is not satisfied [E0277]
+ //~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277]
//[edition2021]~| ERROR: trait objects must include the `dyn` keyword [E0782]
todo!()
}
diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr
index efc228de5..3cc47e1e8 100644
--- a/src/test/ui/impl-trait/hidden-lifetimes.stderr
+++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr
@@ -1,4 +1,4 @@
-error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
--> $DIR/hidden-lifetimes.rs:29:5
|
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
@@ -6,12 +6,12 @@ LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
LL | x
| ^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
| ++++
-error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap + 'a` captures lifetime that does not appear in bounds
--> $DIR/hidden-lifetimes.rs:46:5
|
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
@@ -19,7 +19,7 @@ LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl S
LL | x
| ^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Swap + 'a` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a + 'b {
| ++++
diff --git a/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs
new file mode 100644
index 000000000..74df300f8
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/auxiliary/rpitit.rs
@@ -0,0 +1,11 @@
+#![feature(return_position_impl_trait_in_trait)]
+
+pub trait Foo {
+ fn bar() -> impl Sized;
+}
+
+pub struct Foreign;
+
+impl Foo for Foreign {
+ fn bar() {}
+}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
new file mode 100644
index 000000000..45ae2b8ad
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![allow(incomplete_features)]
+#![feature(async_fn_in_trait)]
+
+pub trait Foo {
+ async fn woopsie_async(&self) -> String {
+ 42
+ //~^ ERROR mismatched types
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr
new file mode 100644
index 000000000..142b1bff1
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err-2.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/default-body-type-err-2.rs:8:9
+ |
+LL | 42
+ | ^^- help: try using a conversion method: `.to_string()`
+ | |
+ | expected struct `String`, found integer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err.rs b/src/test/ui/impl-trait/in-trait/default-body-type-err.rs
new file mode 100644
index 000000000..ac9baf91c
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err.rs
@@ -0,0 +1,13 @@
+#![allow(incomplete_features)]
+#![feature(return_position_impl_trait_in_trait)]
+
+use std::ops::Deref;
+
+pub trait Foo {
+ fn lol(&self) -> impl Deref<Target = String> {
+ //~^ type mismatch resolving `<&i32 as Deref>::Target == String`
+ &1i32
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr b/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
new file mode 100644
index 000000000..461247a3e
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-type-err.stderr
@@ -0,0 +1,12 @@
+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`
+LL |
+LL | &1i32
+ | ----- return type was inferred to be `&i32` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
new file mode 100644
index 000000000..ad3cc7c25
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -0,0 +1,21 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait Foo {
+ async fn baz(&self) -> impl Debug {
+ ""
+ }
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+
+fn main() {
+ let _ = Bar.baz();
+}
diff --git a/src/test/ui/impl-trait/in-trait/default-body.rs b/src/test/ui/impl-trait/in-trait/default-body.rs
new file mode 100644
index 000000000..b0baf5bb1
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body.rs
@@ -0,0 +1,21 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait Foo {
+ async fn baz(&self) -> &str {
+ ""
+ }
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+
+fn main() {
+ let _ = Bar.baz();
+}
diff --git a/src/test/ui/impl-trait/in-trait/early.rs b/src/test/ui/impl-trait/in-trait/early.rs
new file mode 100644
index 000000000..9c1c2b503
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/early.rs
@@ -0,0 +1,23 @@
+// check-pass
+// edition:2021
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+pub trait Foo {
+ async fn bar<'a: 'a>(&'a mut self);
+}
+
+impl Foo for () {
+ async fn bar<'a: 'a>(&'a mut self) {}
+}
+
+pub trait Foo2 {
+ fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a;
+}
+
+impl Foo2 for () {
+ fn bar<'a: 'a>(&'a mut self) -> impl Sized + 'a {}
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/foreign.rs b/src/test/ui/impl-trait/in-trait/foreign.rs
new file mode 100644
index 000000000..6341f5b42
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/foreign.rs
@@ -0,0 +1,9 @@
+// check-pass
+// aux-build: rpitit.rs
+
+extern crate rpitit;
+
+fn main() {
+ // Witness an RPITIT from another crate
+ let () = <rpitit::Foreign as rpitit::Foo>::bar();
+}
diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.rs b/src/test/ui/impl-trait/in-trait/issue-102140.rs
new file mode 100644
index 000000000..be1e012ac
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/issue-102140.rs
@@ -0,0 +1,30 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Marker {}
+impl Marker for u32 {}
+
+trait MyTrait {
+ fn foo(&self) -> impl Marker
+ where
+ Self: Sized;
+}
+
+struct Outer;
+
+impl MyTrait for Outer {
+ fn foo(&self) -> impl Marker {
+ 42
+ }
+}
+
+impl dyn MyTrait {
+ fn other(&self) -> impl Marker {
+ MyTrait::foo(&self)
+ //~^ ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ //~| ERROR the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/issue-102140.stderr b/src/test/ui/impl-trait/in-trait/issue-102140.stderr
new file mode 100644
index 000000000..08602185f
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/issue-102140.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ --> $DIR/issue-102140.rs:23:22
+ |
+LL | MyTrait::foo(&self)
+ | ------------ -^^^^
+ | | |
+ | | the trait `MyTrait` is not implemented for `&dyn MyTrait`
+ | | help: consider removing the leading `&`-reference
+ | required by a bound introduced by this call
+
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ --> $DIR/issue-102140.rs:23:9
+ |
+LL | MyTrait::foo(&self)
+ | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+ |
+ = help: the trait `MyTrait` is implemented for `Outer`
+
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+ --> $DIR/issue-102140.rs:23:9
+ |
+LL | MyTrait::foo(&self)
+ | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+ |
+ = help: the trait `MyTrait` is implemented for `Outer`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/in-trait/issue-102301.rs b/src/test/ui/impl-trait/in-trait/issue-102301.rs
new file mode 100644
index 000000000..a93714a65
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/issue-102301.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+trait Foo<T> {
+ fn foo<F2: Foo<T>>(self) -> impl Foo<T>;
+}
+
+struct Bar;
+
+impl Foo<u8> for Bar {
+ fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
+ self
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/issue-102571.rs b/src/test/ui/impl-trait/in-trait/issue-102571.rs
new file mode 100644
index 000000000..61c91e644
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/issue-102571.rs
@@ -0,0 +1,24 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Display;
+use std::ops::Deref;
+
+trait Foo {
+ fn bar(self) -> impl Deref<Target = impl Display + ?Sized>;
+}
+
+struct A;
+
+impl Foo for A {
+ fn bar(self) -> &'static str {
+ "Hello, world"
+ }
+}
+
+fn foo<T: Foo>(t: T) {
+ let () = t.bar();
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/issue-102571.stderr b/src/test/ui/impl-trait/in-trait/issue-102571.stderr
new file mode 100644
index 000000000..87219941d
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/issue-102571.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102571.rs:20:9
+ |
+LL | let () = t.bar();
+ | ^^ ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+ | |
+ | expected associated type, found `()`
+ |
+ = note: expected associated type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+ found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/in-trait/signature-mismatch.rs b/src/test/ui/impl-trait/in-trait/signature-mismatch.rs
new file mode 100644
index 000000000..90682631a
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/signature-mismatch.rs
@@ -0,0 +1,21 @@
+// edition:2021
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+
+pub trait AsyncTrait {
+ fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
+}
+
+pub struct Struct;
+
+impl AsyncTrait for Struct {
+ fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+ //~^ ERROR `impl` item signature doesn't match `trait` item signature
+ async move { buff.to_vec() }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr
new file mode 100644
index 000000000..6663d7faa
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr
@@ -0,0 +1,16 @@
+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`
+...
+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 `fn(&'1 Struct, &'2 [u8]) -> impl Future<Output = Vec<u8>> + 'static`
+ found `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
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/issue-100075-2.stderr b/src/test/ui/impl-trait/issue-100075-2.stderr
index 5a1f1a97d..d2dbd8c62 100644
--- a/src/test/ui/impl-trait/issue-100075-2.stderr
+++ b/src/test/ui/impl-trait/issue-100075-2.stderr
@@ -7,8 +7,8 @@ LL | fn opaque<T>(t: T) -> impl Sized {
LL | opaque(Some(t))
| --------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error[E0720]: cannot resolve opaque type
--> $DIR/issue-100075-2.rs:1:23
diff --git a/src/test/ui/impl-trait/issue-102605.rs b/src/test/ui/impl-trait/issue-102605.rs
new file mode 100644
index 000000000..3bbdf35af
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-102605.rs
@@ -0,0 +1,15 @@
+// edition:2021
+
+async fn foo() -> Result<(), String> {
+ Ok(())
+}
+
+fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
+ None
+}
+
+fn main() -> Option<()> {
+ //~^ ERROR `main` has invalid return type `Option<()>`
+ convert_result(foo())
+ //~^ ERROR mismatched types
+}
diff --git a/src/test/ui/impl-trait/issue-102605.stderr b/src/test/ui/impl-trait/issue-102605.stderr
new file mode 100644
index 000000000..d4aba9149
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-102605.stderr
@@ -0,0 +1,41 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102605.rs:13:20
+ |
+LL | convert_result(foo())
+ | -------------- ^^^^^ expected enum `Result`, found opaque type
+ | |
+ | arguments to this function are incorrect
+ |
+note: while checking the return type of the `async fn`
+ --> $DIR/issue-102605.rs:3:19
+ |
+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>>`
+note: function defined here
+ --> $DIR/issue-102605.rs:7:4
+ |
+LL | fn convert_result<T, E>(r: Result<T, E>) -> Option<T> {
+ | ^^^^^^^^^^^^^^ ---------------
+help: consider `await`ing on the `Future`
+ |
+LL | convert_result(foo().await)
+ | ++++++
+help: try wrapping the expression in `Err`
+ |
+LL | convert_result(Err(foo()))
+ | ++++ +
+
+error[E0277]: `main` has invalid return type `Option<()>`
+ --> $DIR/issue-102605.rs:11:14
+ |
+LL | fn main() -> Option<()> {
+ | ^^^^^^^^^^ `main` can only return types that implement `Termination`
+ |
+ = help: consider using `()`, or a `Result`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/issue-103181-1.rs b/src/test/ui/impl-trait/issue-103181-1.rs
new file mode 100644
index 000000000..197aedf9d
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-1.rs
@@ -0,0 +1,85 @@
+// edition:2021
+
+mod hyper {
+ use std::{fmt::Debug, future::Future, marker::PhantomData, pin::Pin, task::Poll};
+
+ pub trait HttpBody {
+ type Error;
+ }
+ impl HttpBody for () {
+ //~^ ERROR not all trait items implemented, missing: `Error`
+ // don't implement `Error` here for the ICE
+ }
+
+ pub struct Server<I, S>(I, S);
+
+ pub fn serve<I, S>(_: S) -> Server<I, S> {
+ todo!()
+ }
+
+ impl<S, B> Future for Server<(), S>
+ where
+ S: MakeServiceRef<(), (), ResBody = B>,
+ B: HttpBody,
+ B::Error: Debug,
+ {
+ type Output = ();
+
+ fn poll(self: Pin<&mut Self>, _: &mut std::task::Context<'_>) -> Poll<Self::Output> {
+ todo!()
+ }
+ }
+
+ pub trait MakeServiceRef<Target, ReqBody> {
+ type ResBody;
+ }
+
+ impl<T, S> MakeServiceRef<(), ()> for T
+ where
+ T: for<'a> Service<&'a (), Response = S>,
+ S: Service<()>,
+ {
+ type ResBody = ();
+ }
+
+ pub struct MakeServiceFn<F>(pub F);
+ pub struct ServiceFn<F, R>(pub PhantomData<(F, R)>);
+
+ pub trait Service<Request> {
+ type Response;
+ }
+
+ impl<'t, F, Ret, Target, Svc> Service<&'t Target> for MakeServiceFn<F>
+ where
+ F: Fn() -> Ret,
+ Ret: Future<Output = Result<Svc, ()>>,
+ {
+ type Response = Svc;
+ }
+
+ impl<F, ReqBody, Ret, ResBody, E> Service<ReqBody> for ServiceFn<F, ReqBody>
+ where
+ F: Fn() -> Ret,
+ Ret: Future<Output = Result<ResBody, E>>,
+ {
+ type Response = ResBody;
+ }
+}
+
+async fn smarvice() -> Result<(), ()> {
+ Ok(())
+}
+
+fn service_fn<F, R, S>(f: F) -> hyper::ServiceFn<F, R>
+where
+ F: Fn() -> S,
+{
+ hyper::ServiceFn(std::marker::PhantomData)
+}
+
+async fn iceice() {
+ let service = hyper::MakeServiceFn(|| async { Ok::<_, ()>(service_fn(|| smarvice())) });
+ hyper::serve::<(), _>(service).await;
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-103181-1.stderr b/src/test/ui/impl-trait/issue-103181-1.stderr
new file mode 100644
index 000000000..cd026607d
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-1.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `Error`
+ --> $DIR/issue-103181-1.rs:9:5
+ |
+LL | type Error;
+ | ---------- `Error` from trait
+LL | }
+LL | impl HttpBody for () {
+ | ^^^^^^^^^^^^^^^^^^^^ missing `Error` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/impl-trait/issue-103181-2.rs b/src/test/ui/impl-trait/issue-103181-2.rs
new file mode 100644
index 000000000..b43ac4507
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-2.rs
@@ -0,0 +1,29 @@
+// edition:2021
+
+trait SendFuture: Send {
+ type Output;
+}
+
+impl<Fut: Send> SendFuture for Fut {
+ type Output = ();
+}
+
+async fn broken_fut() {
+ ident_error;
+ //~^ ERROR cannot find value `ident_error` in this scope
+}
+
+// triggers normalization of `<Fut as SendFuture>::Output`,
+// which requires `Fut: Send`.
+fn normalize<Fut: SendFuture>(_: Fut, _: Fut::Output) {}
+
+async fn iceice<A, B>()
+// <- async fn is necessary
+where
+ A: Send,
+ B: Send, // <- a second bound
+{
+ normalize(broken_fut(), ());
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/issue-103181-2.stderr b/src/test/ui/impl-trait/issue-103181-2.stderr
new file mode 100644
index 000000000..5eb2dd918
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-103181-2.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find value `ident_error` in this scope
+ --> $DIR/issue-103181-2.rs:12:5
+ |
+LL | ident_error;
+ | ^^^^^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/impl-trait/issue-103599.stderr b/src/test/ui/impl-trait/issue-103599.stderr
index 79fb355dd..82038c1dc 100644
--- a/src/test/ui/impl-trait/issue-103599.stderr
+++ b/src/test/ui/impl-trait/issue-103599.stderr
@@ -7,8 +7,8 @@ LL |
LL | wrap(wrap(x))
| ------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/impl-trait/issue-86465.rs b/src/test/ui/impl-trait/issue-86465.rs
index a79bb6474..8c7b41d73 100644
--- a/src/test/ui/impl-trait/issue-86465.rs
+++ b/src/test/ui/impl-trait/issue-86465.rs
@@ -1,6 +1,10 @@
#![feature(type_alias_impl_trait)]
-type X<'a, 'b> = impl std::fmt::Debug;
+pub trait Captures<'a> {}
+
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type X<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
fn f<'t, 'u>(a: &'t u32, b: &'u u32) -> (X<'t, 'u>, X<'u, 't>) {
(a, a)
diff --git a/src/test/ui/impl-trait/issue-86465.stderr b/src/test/ui/impl-trait/issue-86465.stderr
index 90d6904ed..b949b2b42 100644
--- a/src/test/ui/impl-trait/issue-86465.stderr
+++ b/src/test/ui/impl-trait/issue-86465.stderr
@@ -1,5 +1,5 @@
error: concrete type differs from previous defining opaque type use
- --> $DIR/issue-86465.rs:6:5
+ --> $DIR/issue-86465.rs:10:5
|
LL | (a, a)
| ^^^^^^
diff --git a/src/test/ui/impl-trait/issue-87450.stderr b/src/test/ui/impl-trait/issue-87450.stderr
index 5019e544b..173fca63f 100644
--- a/src/test/ui/impl-trait/issue-87450.stderr
+++ b/src/test/ui/impl-trait/issue-87450.stderr
@@ -7,8 +7,8 @@ LL | fn foo() -> impl Fn() {
LL | wrap(wrap(wrap(wrap(wrap(wrap(wrap(foo())))))))
| ----- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error[E0720]: cannot resolve opaque type
--> $DIR/issue-87450.rs:5:13
diff --git a/src/test/ui/impl-trait/issues/issue-78722.rs b/src/test/ui/impl-trait/issues/issue-78722.rs
index 90d1cd379..9ee1ba3d3 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.rs
+++ b/src/test/ui/impl-trait/issues/issue-78722.rs
@@ -12,7 +12,7 @@ struct Bug {
}
let f: F = async { 1 };
//~^ ERROR `async` blocks are not allowed in constants
- //~| ERROR destructors cannot be evaluated at compile-time
+ //~| ERROR destructor of
1
}],
}
diff --git a/src/test/ui/impl-trait/issues/issue-78722.stderr b/src/test/ui/impl-trait/issues/issue-78722.stderr
index 9a0ffbc89..a96994f5a 100644
--- a/src/test/ui/impl-trait/issues/issue-78722.stderr
+++ b/src/test/ui/impl-trait/issues/issue-78722.stderr
@@ -7,11 +7,11 @@ LL | let f: F = async { 1 };
= note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
= help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/issue-78722.rs:13:13
|
LL | let f: F = async { 1 };
- | ^ constants cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in constants
...
LL | }],
| - value is dropped here
diff --git a/src/test/ui/impl-trait/issues/issue-86800.stderr b/src/test/ui/impl-trait/issues/issue-86800.stderr
index 135d06d44..6c4aa3567 100644
--- a/src/test/ui/impl-trait/issues/issue-86800.stderr
+++ b/src/test/ui/impl-trait/issues/issue-86800.stderr
@@ -1,3 +1,11 @@
+error: unconstrained opaque type
+ --> $DIR/issue-86800.rs:33:34
+ |
+LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ =
+
stack backtrace:
@@ -12,8 +20,7 @@ error: internal compiler error: unexpected panic
query stack during panic:
-#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
-#1 [type_of] computing type of `TransactionFuture::{opaque#0}`
-#2 [check_mod_item_types] checking item types in top-level module
-#3 [analysis] running analysis passes on this crate
+#0 [type_of] computing type of `TransactionFuture::{opaque#0}`
+#1 [check_mod_item_types] checking item types in top-level module
+#2 [analysis] running analysis passes on this crate
end of query stack
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
index cb1dc0b7d..ec49a6179 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.stderr
@@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> im
LL | if condition() { a } else { b }
| ^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'d, 'e>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> + 'b
| ++++
diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
index 4388e6601..c36f9bc69 100644
--- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
+++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.stderr
@@ -7,7 +7,7 @@ LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a,
LL | if condition() { a } else { b }
| ^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Trait<'a, 'b>` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> + 'b
| ++++
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index 16767abd7..9c81791fb 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -6,7 +6,7 @@ LL | fn elided(x: &i32) -> impl Copy { x }
| |
| hidden type `&i32` captures the anonymous lifetime defined here
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Copy` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ++++
@@ -19,7 +19,7 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
| |
| hidden type `&'a i32` captures the lifetime `'a` as defined here
|
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Copy` captures `'a`, you can add an explicit `'a` lifetime bound
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ++++
@@ -32,7 +32,7 @@ LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
| |
| let's call the lifetime of this reference `'1`
|
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
| ~~
@@ -47,7 +47,7 @@ error: lifetime may not live long enough
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl Copy + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
| ~~
@@ -76,7 +76,7 @@ help: to declare that the trait object captures data from argument `x`, you can
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug + '_>, impl Debug) { (Box::new(x), x) }
| ++++
-help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Debug` captures data from argument `x`, you can add an explicit `'_` lifetime bound
|
LL | fn elided5(x: &i32) -> (Box<dyn Debug>, impl Debug + '_) { (Box::new(x), x) }
| ++++
@@ -87,7 +87,7 @@ error: lifetime may not live long enough
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
| -- lifetime `'a` defined here ^ returning this value requires that `'a` must outlive `'static`
|
-help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+help: consider changing `impl LifetimeTrait<'a> + 'static`'s explicit `'static` bound to the lifetime of argument `x`
|
LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
| ~~
@@ -104,7 +104,7 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
LL | move |_| println!("{}", y)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: to declare that the `impl Trait` captures `'b`, you can add an explicit `'b` lifetime bound
+help: to declare that `impl Fn(&'a u32)` captures `'b`, you can add an explicit `'b` lifetime bound
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) + 'b {
| ++++
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.rs b/src/test/ui/impl-trait/nested-return-type2-tait.rs
index 42613d5cc..089018a1c 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait.rs
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.rs
@@ -26,6 +26,7 @@ type Sendable = impl Send;
// var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
// type does not implement `Duh`, but if its hidden type does.
fn foo() -> impl Trait<Assoc = Sendable> {
+ //~^ WARN opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
|| 42
}
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
new file mode 100644
index 000000000..a8eb69cfc
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type2-tait.rs:28:24
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `Sendable`
+...
+LL | fn foo() -> impl Trait<Assoc = Sendable> {
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | type Sendable = impl Send + Duh;
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs
index 39928d543..cc1f1f4ec 100644
--- a/src/test/ui/impl-trait/nested-return-type2.rs
+++ b/src/test/ui/impl-trait/nested-return-type2.rs
@@ -23,6 +23,7 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
// Lazy TAIT would error out, but we inserted a hack to make it work again,
// keeping backwards compatibility.
fn foo() -> impl Trait<Assoc = impl Send> {
+ //~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
|| 42
}
diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr
new file mode 100644
index 000000000..3aed05ca1
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type2.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type2.rs:25:24
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `impl Send`
+...
+LL | fn foo() -> impl Trait<Assoc = impl Send> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> {
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait.rs b/src/test/ui/impl-trait/nested-return-type3-tait.rs
index 3936f4dbb..3a97e35b4 100644
--- a/src/test/ui/impl-trait/nested-return-type3-tait.rs
+++ b/src/test/ui/impl-trait/nested-return-type3-tait.rs
@@ -17,6 +17,7 @@ impl<F: Duh> Trait for F {
type Sendable = impl Send;
fn foo() -> impl Trait<Assoc = Sendable> {
+ //~^ WARN opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
42
}
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait.stderr b/src/test/ui/impl-trait/nested-return-type3-tait.stderr
new file mode 100644
index 000000000..5f58c8dca
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type3-tait.rs:19:24
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `Sendable`
+...
+LL | fn foo() -> impl Trait<Assoc = Sendable> {
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | type Sendable = impl Send + Duh;
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait2.rs b/src/test/ui/impl-trait/nested-return-type3-tait2.rs
index 56778ed90..5b6f78a98 100644
--- a/src/test/ui/impl-trait/nested-return-type3-tait2.rs
+++ b/src/test/ui/impl-trait/nested-return-type3-tait2.rs
@@ -16,6 +16,7 @@ impl<F: Duh> Trait for F {
type Sendable = impl Send;
type Traitable = impl Trait<Assoc = Sendable>;
+//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds
fn foo() -> Traitable {
42
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait2.stderr b/src/test/ui/impl-trait/nested-return-type3-tait2.stderr
new file mode 100644
index 000000000..c07f6ead7
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait2.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `Traitable` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type3-tait2.rs:18:29
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `Sendable`
+...
+LL | type Traitable = impl Trait<Assoc = Sendable>;
+ | ^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | type Sendable = impl Send + Duh;
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait3.rs b/src/test/ui/impl-trait/nested-return-type3-tait3.rs
index 04c6c92b1..394d8f581 100644
--- a/src/test/ui/impl-trait/nested-return-type3-tait3.rs
+++ b/src/test/ui/impl-trait/nested-return-type3-tait3.rs
@@ -15,6 +15,7 @@ impl<F: Duh> Trait for F {
}
type Traitable = impl Trait<Assoc = impl Send>;
+//~^ WARN opaque type `Traitable` does not satisfy its associated type bounds
fn foo() -> Traitable {
42
diff --git a/src/test/ui/impl-trait/nested-return-type3-tait3.stderr b/src/test/ui/impl-trait/nested-return-type3-tait3.stderr
new file mode 100644
index 000000000..d98ad8922
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3-tait3.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `Traitable` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type3-tait3.rs:17:29
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `impl Send`
+...
+LL | type Traitable = impl Trait<Assoc = impl Send>;
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | type Traitable = impl Trait<Assoc = impl Send + Duh>;
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/nested-return-type3.rs b/src/test/ui/impl-trait/nested-return-type3.rs
index 74b4dae22..5a764fc4c 100644
--- a/src/test/ui/impl-trait/nested-return-type3.rs
+++ b/src/test/ui/impl-trait/nested-return-type3.rs
@@ -13,6 +13,7 @@ impl<F: Duh> Trait for F {
}
fn foo() -> impl Trait<Assoc = impl Send> {
+ //~^ WARN opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
42
}
diff --git a/src/test/ui/impl-trait/nested-return-type3.stderr b/src/test/ui/impl-trait/nested-return-type3.stderr
new file mode 100644
index 000000000..632de71aa
--- /dev/null
+++ b/src/test/ui/impl-trait/nested-return-type3.stderr
@@ -0,0 +1,17 @@
+warning: opaque type `impl Trait<Assoc = impl Send>` does not satisfy its associated type bounds
+ --> $DIR/nested-return-type3.rs:15:24
+ |
+LL | type Assoc: Duh;
+ | --- this associated type bound is unsatisfied for `impl Send`
+...
+LL | fn foo() -> impl Trait<Assoc = impl Send> {
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: `#[warn(opaque_hidden_inferred_bound)]` on by default
+help: add this bound
+ |
+LL | fn foo() -> impl Trait<Assoc = impl Send + Duh> {
+ | +++++
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/normalize-tait-in-const.rs b/src/test/ui/impl-trait/normalize-tait-in-const.rs
new file mode 100644
index 000000000..020bcbb83
--- /dev/null
+++ b/src/test/ui/impl-trait/normalize-tait-in-const.rs
@@ -0,0 +1,39 @@
+// known-bug: #103507
+// failure-status: 101
+// normalize-stderr-test "note: .*\n\n" -> ""
+// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
+// rustc-env:RUST_BACKTRACE=0
+
+#![feature(type_alias_impl_trait)]
+#![feature(const_trait_impl)]
+#![feature(const_refs_to_cell)]
+#![feature(inline_const)]
+
+use std::marker::Destruct;
+
+trait T {
+ type Item;
+}
+
+type Alias<'a> = impl T<Item = &'a ()>;
+
+struct S;
+impl<'a> T for &'a S {
+ type Item = &'a ();
+}
+
+const fn filter_positive<'a>() -> &'a Alias<'a> {
+ &&S
+}
+
+const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
+ fun(filter_positive());
+}
+
+const fn foo(_: &Alias<'_>) {}
+
+const BAR: () = {
+ with_positive(foo);
+};
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/normalize-tait-in-const.stderr b/src/test/ui/impl-trait/normalize-tait-in-const.stderr
new file mode 100644
index 000000000..b9fc8726f
--- /dev/null
+++ b/src/test/ui/impl-trait/normalize-tait-in-const.stderr
@@ -0,0 +1,8 @@
+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
+
+query stack during panic:
+#0 [eval_to_allocation_raw] const-evaluating + checking `BAR`
+#1 [eval_to_const_value_raw] simplifying constant for the type system `BAR`
+end of query stack
+error: aborting due to previous error
+
diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr
index fdb2fe022..44a790cb1 100644
--- a/src/test/ui/impl-trait/region-escape-via-bound.stderr
+++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr
@@ -7,7 +7,7 @@ LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
LL | x
| ^
|
-help: to declare that the `impl Trait` captures `'x`, you can add an explicit `'x` lifetime bound
+help: to declare that `impl Trait<'y>` captures `'x`, you can add an explicit `'x` lifetime bound
|
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y> + 'x
| ++++
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index b86815231..b365bd884 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -6,7 +6,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
@@ -19,7 +19,7 @@ LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
@@ -32,7 +32,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++
@@ -45,7 +45,7 @@ LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
LL | self.x.iter().map(|a| a.0)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: to declare that the `impl Trait` captures `'a`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = u32>` captures `'a`, you can add an explicit `'a` lifetime bound
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++
diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.fixed b/src/test/ui/impl-trait/unactionable_diagnostic.fixed
new file mode 100644
index 000000000..6c2505177
--- /dev/null
+++ b/src/test/ui/impl-trait/unactionable_diagnostic.fixed
@@ -0,0 +1,25 @@
+// run-rustfix
+
+pub trait Trait {}
+
+pub struct Foo;
+
+impl Trait for Foo {}
+
+fn foo<'x, P>(
+ _post: P,
+ x: &'x Foo,
+) -> &'x impl Trait {
+ x
+}
+
+pub fn bar<'t, T: 't>(
+ //~^ HELP: consider adding an explicit lifetime bound...
+ post: T,
+ x: &'t Foo,
+) -> &'t impl Trait {
+ foo(post, x)
+ //~^ ERROR: the parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.rs b/src/test/ui/impl-trait/unactionable_diagnostic.rs
new file mode 100644
index 000000000..bce35cbdd
--- /dev/null
+++ b/src/test/ui/impl-trait/unactionable_diagnostic.rs
@@ -0,0 +1,25 @@
+// run-rustfix
+
+pub trait Trait {}
+
+pub struct Foo;
+
+impl Trait for Foo {}
+
+fn foo<'x, P>(
+ _post: P,
+ x: &'x Foo,
+) -> &'x impl Trait {
+ x
+}
+
+pub fn bar<'t, T>(
+ //~^ HELP: consider adding an explicit lifetime bound...
+ post: T,
+ x: &'t Foo,
+) -> &'t impl Trait {
+ foo(post, x)
+ //~^ ERROR: the parameter type `T` may not live long enough
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/unactionable_diagnostic.stderr b/src/test/ui/impl-trait/unactionable_diagnostic.stderr
new file mode 100644
index 000000000..a32004cda
--- /dev/null
+++ b/src/test/ui/impl-trait/unactionable_diagnostic.stderr
@@ -0,0 +1,14 @@
+error[E0309]: the parameter type `T` may not live long enough
+ --> $DIR/unactionable_diagnostic.rs:21:5
+ |
+LL | foo(post, x)
+ | ^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | pub fn bar<'t, T: 't>(
+ | ++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr
index 9b346387d..2e7c7ca40 100644
--- a/src/test/ui/impl-trait/where-allowed.stderr
+++ b/src/test/ui/impl-trait/where-allowed.stderr
@@ -301,9 +301,9 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type`
LL | impl <T = impl Debug> T {}
| ^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_type_param_default)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
--> $DIR/where-allowed.rs:241:36
diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr
index 2e4ba8623..059ca9680 100644
--- a/src/test/ui/imports/issue-56125.stderr
+++ b/src/test/ui/imports/issue-56125.stderr
@@ -3,6 +3,18 @@ error[E0432]: unresolved import `empty::issue_56125`
|
LL | use empty::issue_56125;
| ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
+ |
+help: consider importing one of these items instead
+ |
+LL | use crate::m3::last_segment::issue_56125;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | use crate::m3::non_last_segment::non_last_segment::issue_56125;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | use issue_56125::issue_56125;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~
+LL | use issue_56125::last_segment::issue_56125;
+ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ and 1 other candidate
error[E0659]: `issue_56125` is ambiguous
--> $DIR/issue-56125.rs:6:9
diff --git a/src/test/ui/imports/issue-57015.stderr b/src/test/ui/imports/issue-57015.stderr
index d200d23ab..3b72d57fe 100644
--- a/src/test/ui/imports/issue-57015.stderr
+++ b/src/test/ui/imports/issue-57015.stderr
@@ -3,6 +3,11 @@ error[E0432]: unresolved import `single_err::something`
|
LL | use single_err::something;
| ^^^^^^^^^^^^^^^^^^^^^ no `something` in `single_err`
+ |
+help: consider importing this module instead
+ |
+LL | use glob_ok::something;
+ | ~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
diff --git a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
index 3c20f552f..2c1965ac0 100644
--- a/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
+++ b/src/test/ui/imports/local-modularized-tricky-fail-2.stderr
@@ -4,7 +4,6 @@ error: macro-expanded `macro_export` macros from the current crate cannot be ref
LL | use exported;
| ^^^^^^^^
|
- = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #52234 <https://github.com/rust-lang/rust/issues/52234>
note: the macro is defined here
@@ -17,6 +16,7 @@ LL | | }
...
LL | define_exported!();
| ------------------ in this macro invocation
+ = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` on by default
= note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info)
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
diff --git a/src/test/ui/inference/char-as-str-single.fixed b/src/test/ui/inference/char-as-str-single.fixed
index e401492a8..bab1854dc 100644
--- a/src/test/ui/inference/char-as-str-single.fixed
+++ b/src/test/ui/inference/char-as-str-single.fixed
@@ -8,4 +8,5 @@
fn main() {
let _: char = 'a'; //~ ERROR mismatched types
let _: char = '人'; //~ ERROR mismatched types
+ let _: char = '\''; //~ ERROR mismatched types
}
diff --git a/src/test/ui/inference/char-as-str-single.rs b/src/test/ui/inference/char-as-str-single.rs
index 4f23cea53..736920643 100644
--- a/src/test/ui/inference/char-as-str-single.rs
+++ b/src/test/ui/inference/char-as-str-single.rs
@@ -8,4 +8,5 @@
fn main() {
let _: char = "a"; //~ ERROR mismatched types
let _: char = "人"; //~ ERROR mismatched types
+ let _: char = "'"; //~ ERROR mismatched types
}
diff --git a/src/test/ui/inference/char-as-str-single.stderr b/src/test/ui/inference/char-as-str-single.stderr
index 29075c154..3375ec6ac 100644
--- a/src/test/ui/inference/char-as-str-single.stderr
+++ b/src/test/ui/inference/char-as-str-single.stderr
@@ -24,6 +24,19 @@ help: if you meant to write a `char` literal, use single quotes
LL | let _: char = '人';
| ~~~~
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+ --> $DIR/char-as-str-single.rs:11:19
+ |
+LL | let _: char = "'";
+ | ---- ^^^ expected `char`, found `&str`
+ | |
+ | expected due to this
+ |
+help: if you meant to write a `char` literal, use single quotes
+ |
+LL | let _: char = '\'';
+ | ~~~~
+
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr b/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
index c38f57912..3dea09e7f 100644
--- a/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
+++ b/src/test/ui/inference/inference-variable-behind-raw-pointer.stderr
@@ -4,9 +4,9 @@ warning: type annotations needed
LL | if data.is_null() {}
| ^^^^^^^
|
- = note: `#[warn(tyvar_behind_raw_pointer)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
= note: for more information, see issue #46906 <https://github.com/rust-lang/rust/issues/46906>
+ = note: `#[warn(tyvar_behind_raw_pointer)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/inference/inference_unstable.stderr b/src/test/ui/inference/inference_unstable.stderr
index df7a09686..ecbf2641b 100644
--- a/src/test/ui/inference/inference_unstable.stderr
+++ b/src/test/ui/inference/inference_unstable.stderr
@@ -4,11 +4,11 @@ warning: an associated function with this name may be added to the standard libr
LL | assert_eq!('x'.ipu_flatten(), 1);
| ^^^^^^^^^^^
|
- = note: `#[warn(unstable_name_collisions)]` on by default
= warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
= note: for more information, see issue #48919 <https://github.com/rust-lang/rust/issues/48919>
= help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method
= 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
--> $DIR/inference_unstable.rs:19:20
diff --git a/src/test/ui/issues/issue-36053.rs b/src/test/ui/inference/issue-36053.rs
index 5c6d07804..5c6d07804 100644
--- a/src/test/ui/issues/issue-36053.rs
+++ b/src/test/ui/inference/issue-36053.rs
diff --git a/src/test/ui/inference/need_type_info/concrete-impl.stderr b/src/test/ui/inference/need_type_info/concrete-impl.stderr
index b79d34aff..aa3296995 100644
--- a/src/test/ui/inference/need_type_info/concrete-impl.stderr
+++ b/src/test/ui/inference/need_type_info/concrete-impl.stderr
@@ -3,11 +3,6 @@ error[E0282]: type annotations needed
|
LL | <Struct as Ambiguous<_>>::method();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
- |
-help: consider specifying the generic argument
- |
-LL | <Struct as Ambiguous::<_>>::method();
- | ~~~~~
error[E0283]: type annotations needed
--> $DIR/concrete-impl.rs:13:5
@@ -22,10 +17,6 @@ LL | impl Ambiguous<One> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | impl Ambiguous<Two> for Struct {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: consider specifying the generic argument
- |
-LL | <Struct as Ambiguous::<_>>::method();
- | ~~~~~
error: aborting due to 2 previous errors
diff --git a/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs b/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs
new file mode 100644
index 000000000..3084f6eac
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.rs
@@ -0,0 +1,11 @@
+enum OhNo<T, U> {
+ A(T),
+ B(U),
+ C,
+}
+
+fn uwu() {
+ OhNo::C::<u32, _>; //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr b/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr
new file mode 100644
index 000000000..2ad35ab03
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/do-not-suggest-generic-arguments-for-turbofish.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+ --> $DIR/do-not-suggest-generic-arguments-for-turbofish.rs:8:5
+ |
+LL | OhNo::C::<u32, _>;
+ | ^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the enum `OhNo`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/need_type_info/issue-103053.rs b/src/test/ui/inference/need_type_info/issue-103053.rs
new file mode 100644
index 000000000..05169666f
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/issue-103053.rs
@@ -0,0 +1,18 @@
+trait TypeMapper {
+ type MapType;
+}
+
+type Mapped<T> = <T as TypeMapper>::MapType;
+
+struct Test {}
+
+impl TypeMapper for () {
+ type MapType = Test;
+}
+
+fn test() {
+ Mapped::<()> {};
+ None; //~ ERROR type annotations needed
+}
+
+fn main() {}
diff --git a/src/test/ui/inference/need_type_info/issue-103053.stderr b/src/test/ui/inference/need_type_info/issue-103053.stderr
new file mode 100644
index 000000000..84f0475d8
--- /dev/null
+++ b/src/test/ui/inference/need_type_info/issue-103053.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+ --> $DIR/issue-103053.rs:15:5
+ |
+LL | None;
+ | ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+ |
+help: consider specifying the generic argument
+ |
+LL | None::<T>;
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/src/test/ui/inference/str-as-char.fixed b/src/test/ui/inference/str-as-char.fixed
index 09f3dec5a..6aea809cb 100644
--- a/src/test/ui/inference/str-as-char.fixed
+++ b/src/test/ui/inference/str-as-char.fixed
@@ -4,5 +4,7 @@
// run-rustfix
fn main() {
- let _: &str = "a"; //~ ERROR mismatched types
+ let _: &str = "a"; //~ ERROR mismatched types
+ let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+ let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
}
diff --git a/src/test/ui/inference/str-as-char.rs b/src/test/ui/inference/str-as-char.rs
index 7092a6124..eaa8d788c 100644
--- a/src/test/ui/inference/str-as-char.rs
+++ b/src/test/ui/inference/str-as-char.rs
@@ -4,5 +4,7 @@
// run-rustfix
fn main() {
- let _: &str = 'a'; //~ ERROR mismatched types
+ let _: &str = 'a'; //~ ERROR mismatched types
+ let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
+ let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
}
diff --git a/src/test/ui/inference/str-as-char.stderr b/src/test/ui/inference/str-as-char.stderr
index ebbe7c80f..2c84dac8e 100644
--- a/src/test/ui/inference/str-as-char.stderr
+++ b/src/test/ui/inference/str-as-char.stderr
@@ -1,3 +1,25 @@
+error: character literal may only contain one codepoint
+ --> $DIR/str-as-char.rs:8:19
+ |
+LL | let _: &str = '"""';
+ | ^^^^^
+ |
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _: &str = "\"\"\"";
+ | ~~~~~~~~
+
+error: character literal may only contain one codepoint
+ --> $DIR/str-as-char.rs:9:19
+ |
+LL | let _: &str = '\"\"\"';
+ | ^^^^^^^^
+ |
+help: if you meant to write a `str` literal, use double quotes
+ |
+LL | let _: &str = "\"\"\"";
+ | ~~~~~~~~
+
error[E0308]: mismatched types
--> $DIR/str-as-char.rs:7:19
|
@@ -11,6 +33,6 @@ help: if you meant to write a `str` literal, use double quotes
LL | let _: &str = "a";
| ~~~
-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/src/test/ui/infinite/infinite-struct.rs b/src/test/ui/infinite/infinite-struct.rs
index 74185dc59..f08e10f6b 100644
--- a/src/test/ui/infinite/infinite-struct.rs
+++ b/src/test/ui/infinite/infinite-struct.rs
@@ -6,4 +6,11 @@ fn foo() -> Take {
Take(loop {})
}
+// mutually infinite structs
+struct Foo { //~ ERROR has infinite size
+ x: Bar<Foo>,
+}
+
+struct Bar<T>([T; 1]);
+
fn main() {}
diff --git a/src/test/ui/infinite/infinite-struct.stderr b/src/test/ui/infinite/infinite-struct.stderr
index 5a6d13786..b6c72b1de 100644
--- a/src/test/ui/infinite/infinite-struct.stderr
+++ b/src/test/ui/infinite/infinite-struct.stderr
@@ -3,14 +3,25 @@ error[E0072]: recursive type `Take` has infinite size
|
LL | struct Take(Take);
| ^^^^^^^^^^^ ---- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct Take(Box<Take>);
| ++++ +
-error: aborting due to previous error
+error[E0072]: recursive type `Foo` has infinite size
+ --> $DIR/infinite-struct.rs:10:1
+ |
+LL | struct Foo {
+ | ^^^^^^^^^^
+LL | x: Bar<Foo>,
+ | --- recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL | x: Bar<Box<Foo>>,
+ | ++++ +
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
index d2dad4b91..513bbfc1b 100644
--- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr
+++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `MList` has infinite size
|
LL | enum MList { Cons(isize, MList), Nil }
| ^^^^^^^^^^ ----- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | enum MList { Cons(isize, Box<MList>), Nil }
| ++++ +
diff --git a/src/test/ui/inline-const/const-match-pat-range.rs b/src/test/ui/inline-const/const-match-pat-range.rs
index 7dc8c1135..73d6334c3 100644
--- a/src/test/ui/inline-const/const-match-pat-range.rs
+++ b/src/test/ui/inline-const/const-match-pat-range.rs
@@ -1,7 +1,8 @@
// build-pass
#![allow(incomplete_features)]
-#![feature(inline_const_pat, half_open_range_patterns, exclusive_range_pattern)]
+#![feature(inline_const_pat, exclusive_range_pattern)]
+
fn main() {
const N: u32 = 10;
let x: u32 = 3;
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs b/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs
index 29aefe071..1164a3a5b 100644
--- a/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs
+++ b/src/test/ui/intrinsics/const-eval-select-backtrace-std.rs
@@ -1,6 +1,7 @@
// See issue #100696.
// run-fail
// check-run-results
+// exec-env:RUST_BACKTRACE=0
fn main() {
&""[1..];
}
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr b/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr
index e53e60346..463cd52c5 100644
--- a/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr
+++ b/src/test/ui/intrinsics/const-eval-select-backtrace-std.run.stderr
@@ -1,2 +1,2 @@
-thread 'main' panicked at 'byte index 1 is out of bounds of ``', $DIR/const-eval-select-backtrace-std.rs:5:6
+thread 'main' panicked at 'byte index 1 is out of bounds of ``', $DIR/const-eval-select-backtrace-std.rs:6:6
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace.rs b/src/test/ui/intrinsics/const-eval-select-backtrace.rs
index 99f072520..ef1c7c419 100644
--- a/src/test/ui/intrinsics/const-eval-select-backtrace.rs
+++ b/src/test/ui/intrinsics/const-eval-select-backtrace.rs
@@ -2,6 +2,7 @@
// See issue #100696.
// run-fail
// check-run-results
+// exec-env:RUST_BACKTRACE=0
#[track_caller]
fn uhoh() {
diff --git a/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr b/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr
index 2fd730ac7..54e28db5e 100644
--- a/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr
+++ b/src/test/ui/intrinsics/const-eval-select-backtrace.run.stderr
@@ -1,2 +1,2 @@
-thread 'main' panicked at 'Aaah!', $DIR/const-eval-select-backtrace.rs:16:9
+thread 'main' panicked at 'Aaah!', $DIR/const-eval-select-backtrace.rs:17:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/intrinsics/intrinsic-alignment.rs b/src/test/ui/intrinsics/intrinsic-alignment.rs
index 6007eba8c..c8b1ff1db 100644
--- a/src/test/ui/intrinsics/intrinsic-alignment.rs
+++ b/src/test/ui/intrinsics/intrinsic-alignment.rs
@@ -6,6 +6,7 @@
mod rusti {
extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
+ #[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
}
}
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs
index a205a8730..a93d777d2 100644
--- a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs
+++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.rs
@@ -1,6 +1,5 @@
#![feature(core_intrinsics)]
#![feature(const_intrinsic_raw_eq)]
-#![deny(const_err)]
const BAD_RAW_EQ_CALL: bool = unsafe {
std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr
index 9322654b2..56d5a4857 100644
--- a/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr
+++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const-padding.stderr
@@ -1,5 +1,5 @@
error[E0080]: evaluation of constant value failed
- --> $DIR/intrinsic-raw_eq-const-padding.rs:6:5
+ --> $DIR/intrinsic-raw_eq-const-padding.rs:5:5
|
LL | std::intrinsics::raw_eq(&(1_u8, 2_u16), &(1_u8, 2_u16))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reading memory at alloc3[0x0..0x4], but memory is uninitialized at [0x1..0x2], and this operation requires initialized memory
diff --git a/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs b/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs
index 8ea954673..32841f531 100644
--- a/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs
+++ b/src/test/ui/intrinsics/intrinsic-raw_eq-const.rs
@@ -2,7 +2,6 @@
#![feature(core_intrinsics)]
#![feature(const_intrinsic_raw_eq)]
-#![deny(const_err)]
pub fn main() {
use std::intrinsics::raw_eq;
diff --git a/src/test/ui/intrinsics/intrinsics-integer.rs b/src/test/ui/intrinsics/intrinsics-integer.rs
index bac6c8d87..88bf42b68 100644
--- a/src/test/ui/intrinsics/intrinsics-integer.rs
+++ b/src/test/ui/intrinsics/intrinsics-integer.rs
@@ -1,15 +1,21 @@
// run-pass
#![feature(intrinsics)]
+#![feature(rustc_attrs)]
mod rusti {
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
pub fn ctpop<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn ctlz<T>(x: T) -> T;
pub fn ctlz_nonzero<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn cttz<T>(x: T) -> T;
pub fn cttz_nonzero<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn bswap<T>(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn bitreverse<T>(x: T) -> T;
}
}
diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
index 255151a96..ec3860a32 100644
--- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// revisions: mir thir strict
// [thir]compile-flags: -Zthir-unsafeck
// [strict]compile-flags: -Zstrict-init-checks
@@ -8,7 +7,7 @@
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
-#![feature(never_type, arbitrary_enum_discriminant)]
+#![feature(never_type)]
#![allow(deprecated, invalid_value)]
use std::{
@@ -35,6 +34,12 @@ enum OneVariant_NonZero {
DeadVariant(Bar),
}
+#[allow(dead_code, non_camel_case_types)]
+enum OneVariant_Ref {
+ Variant(&'static i32),
+ DeadVariant(Bar),
+}
+
// An `Aggregate` abi enum where 0 is not a valid discriminant.
#[allow(dead_code)]
#[repr(i32)]
@@ -64,6 +69,7 @@ enum ZeroIsValid {
One(NonNull<()>) = 1,
}
+#[track_caller]
fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
let err = panic::catch_unwind(op).err();
assert_eq!(
@@ -72,6 +78,15 @@ fn test_panic_msg<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
);
}
+#[track_caller]
+fn test_panic_msg_only_if_strict<T>(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) {
+ let err = panic::catch_unwind(op).err();
+ assert_eq!(
+ err.as_ref().and_then(|a| a.downcast_ref::<&str>()),
+ if cfg!(strict) { Some(&msg) } else { None },
+ );
+}
+
fn main() {
unsafe {
// Uninhabited types
@@ -140,92 +155,216 @@ fn main() {
"attempted to instantiate uninhabited type `[Bar; 2]`"
);
- // Types that do not like zero-initialziation
+ // Types that don't allow either.
test_panic_msg(
- || mem::uninitialized::<fn()>(),
- "attempted to leave type `fn()` uninitialized, which is invalid"
+ || mem::zeroed::<&i32>(),
+ "attempted to zero-initialize type `&i32`, which is invalid"
);
test_panic_msg(
- || mem::zeroed::<fn()>(),
- "attempted to zero-initialize type `fn()`, which is invalid"
+ || mem::uninitialized::<&i32>(),
+ "attempted to leave type `&i32` uninitialized, which is invalid"
);
test_panic_msg(
- || mem::uninitialized::<*const dyn Send>(),
- "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid"
+ || mem::zeroed::<Box<[i32; 0]>>(),
+ "attempted to zero-initialize type `alloc::boxed::Box<[i32; 0]>`, which is invalid"
+ );
+ test_panic_msg(
+ || mem::uninitialized::<Box<[i32; 0]>>(),
+ "attempted to leave type `alloc::boxed::Box<[i32; 0]>` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<Box<u8>>(),
+ "attempted to zero-initialize type `alloc::boxed::Box<u8>`, which is invalid"
);
test_panic_msg(
+ || mem::uninitialized::<Box<u8>>(),
+ "attempted to leave type `alloc::boxed::Box<u8>` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&[i32]>(),
+ "attempted to zero-initialize type `&[i32]`, which is invalid"
+ );
+ test_panic_msg(
+ || mem::uninitialized::<&[i32]>(),
+ "attempted to leave type `&[i32]` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&(u8, [u8])>(),
+ "attempted to zero-initialize type `&(u8, [u8])`, which is invalid"
+ );
+ test_panic_msg(
+ || mem::uninitialized::<&(u8, [u8])>(),
+ "attempted to leave type `&(u8, [u8])` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&dyn Send>(),
+ "attempted to zero-initialize type `&dyn core::marker::Send`, which is invalid"
+ );
+ test_panic_msg(
+ || mem::uninitialized::<&dyn Send>(),
+ "attempted to leave type `&dyn core::marker::Send` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
|| mem::zeroed::<*const dyn Send>(),
"attempted to zero-initialize type `*const dyn core::marker::Send`, which is invalid"
);
+ test_panic_msg(
+ || mem::uninitialized::<*const dyn Send>(),
+ "attempted to leave type `*const dyn core::marker::Send` uninitialized, which is invalid"
+ );
test_panic_msg(
- || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
- "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, \
+ || mem::uninitialized::<NoNullVariant>(),
+ "attempted to leave type `NoNullVariant` uninitialized, \
+ which is invalid"
+ );
+ test_panic_msg(
+ || mem::zeroed::<NoNullVariant>(),
+ "attempted to zero-initialize type `NoNullVariant`, \
which is invalid"
);
test_panic_msg(
- || mem::zeroed::<(NonNull<u32>, u32, u32)>(),
- "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \
+ || mem::zeroed::<OneVariant_Ref>(),
+ "attempted to zero-initialize type `OneVariant_Ref`, \
which is invalid"
);
+ test_panic_msg(
+ || mem::uninitialized::<OneVariant_Ref>(),
+ "attempted to leave type `OneVariant_Ref` uninitialized, which is invalid"
+ );
+ // Types where both are invalid, but we allow uninit since the 0x01-filling is not LLVM UB.
test_panic_msg(
- || mem::uninitialized::<OneVariant_NonZero>(),
- "attempted to leave type `OneVariant_NonZero` uninitialized, \
+ || mem::zeroed::<fn()>(),
+ "attempted to zero-initialize type `fn()`, which is invalid"
+ );
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<fn()>(),
+ "attempted to leave type `fn()` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&()>(),
+ "attempted to zero-initialize type `&()`, which is invalid"
+ );
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<&()>(),
+ "attempted to leave type `&()` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&[u8]>(),
+ "attempted to zero-initialize type `&[u8]`, which is invalid"
+ );
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<&[u8]>(),
+ "attempted to leave type `&[u8]` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<&str>(),
+ "attempted to zero-initialize type `&str`, which is invalid"
+ );
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<&str>(),
+ "attempted to leave type `&str` uninitialized, which is invalid"
+ );
+
+ test_panic_msg(
+ || mem::zeroed::<(NonNull<u32>, u32, u32)>(),
+ "attempted to zero-initialize type `(core::ptr::non_null::NonNull<u32>, u32, u32)`, \
which is invalid"
);
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<(NonNull<u32>, u32, u32)>(),
+ "attempted to leave type `(core::ptr::non_null::NonNull<u32>, u32, u32)` uninitialized, which is invalid"
+ );
+
test_panic_msg(
|| mem::zeroed::<OneVariant_NonZero>(),
"attempted to zero-initialize type `OneVariant_NonZero`, \
which is invalid"
);
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<OneVariant_NonZero>(),
+ "attempted to leave type `OneVariant_NonZero` uninitialized, which is invalid"
+ );
+ // Types where both are invalid but we allow the zeroed form since it is not LLVM UB.
+ test_panic_msg_only_if_strict(
+ || mem::zeroed::<LR_NonZero>(),
+ "attempted to zero-initialize type `LR_NonZero`, which is invalid"
+ );
test_panic_msg(
|| mem::uninitialized::<LR_NonZero>(),
"attempted to leave type `LR_NonZero` uninitialized, which is invalid"
);
+ test_panic_msg_only_if_strict(
+ || mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
+ "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \
+ which is invalid"
+ );
test_panic_msg(
|| mem::uninitialized::<ManuallyDrop<LR_NonZero>>(),
"attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>` uninitialized, \
which is invalid"
);
- test_panic_msg(
- || mem::uninitialized::<NoNullVariant>(),
- "attempted to leave type `NoNullVariant` uninitialized, \
- which is invalid"
+ // Some strict-only things
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<i32>(),
+ "attempted to leave type `i32` uninitialized, which is invalid"
);
- test_panic_msg(
- || mem::zeroed::<NoNullVariant>(),
- "attempted to zero-initialize type `NoNullVariant`, \
- which is invalid"
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<*const ()>(),
+ "attempted to leave type `*const ()` uninitialized, which is invalid"
);
- // Types that can be zero, but not uninit.
- test_panic_msg(
- || mem::uninitialized::<bool>(),
- "attempted to leave type `bool` uninitialized, which is invalid"
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<[i32; 1]>(),
+ "attempted to leave type `[i32; 1]` uninitialized, which is invalid"
);
+ test_panic_msg_only_if_strict(
+ || mem::zeroed::<[NonNull<()>; 1]>(),
+ "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid"
+ );
+
+ // Types that can be zero, but not uninit (though some are mitigated).
+ let _val = mem::zeroed::<LR>();
test_panic_msg(
|| mem::uninitialized::<LR>(),
"attempted to leave type `LR` uninitialized, which is invalid"
);
+ let _val = mem::zeroed::<ManuallyDrop<LR>>();
test_panic_msg(
|| mem::uninitialized::<ManuallyDrop<LR>>(),
"attempted to leave type `core::mem::manually_drop::ManuallyDrop<LR>` uninitialized, which is invalid"
);
- // Some things that should work.
let _val = mem::zeroed::<bool>();
- let _val = mem::zeroed::<LR>();
- let _val = mem::zeroed::<ManuallyDrop<LR>>();
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<bool>(),
+ "attempted to leave type `bool` uninitialized, which is invalid"
+ );
+
let _val = mem::zeroed::<OneVariant>();
+ test_panic_msg_only_if_strict(
+ || mem::uninitialized::<OneVariant>(),
+ "attempted to leave type `OneVariant` uninitialized, which is invalid"
+ );
+
+ // Some things that are actually allowed.
let _val = mem::zeroed::<Option<&'static i32>>();
let _val = mem::zeroed::<MaybeUninit<NonNull<u32>>>();
let _val = mem::zeroed::<[!; 0]>();
@@ -234,59 +373,5 @@ fn main() {
let _val = mem::uninitialized::<[!; 0]>();
let _val = mem::uninitialized::<()>();
let _val = mem::uninitialized::<ZeroSized>();
-
- if cfg!(strict) {
- test_panic_msg(
- || mem::uninitialized::<i32>(),
- "attempted to leave type `i32` uninitialized, which is invalid"
- );
-
- test_panic_msg(
- || mem::uninitialized::<*const ()>(),
- "attempted to leave type `*const ()` uninitialized, which is invalid"
- );
-
- test_panic_msg(
- || mem::uninitialized::<[i32; 1]>(),
- "attempted to leave type `[i32; 1]` uninitialized, which is invalid"
- );
-
- test_panic_msg(
- || mem::zeroed::<NonNull<()>>(),
- "attempted to zero-initialize type `core::ptr::non_null::NonNull<()>`, which is invalid"
- );
-
- test_panic_msg(
- || mem::zeroed::<[NonNull<()>; 1]>(),
- "attempted to zero-initialize type `[core::ptr::non_null::NonNull<()>; 1]`, which is invalid"
- );
-
- // FIXME(#66151) we conservatively do not error here yet (by default).
- test_panic_msg(
- || mem::zeroed::<LR_NonZero>(),
- "attempted to zero-initialize type `LR_NonZero`, which is invalid"
- );
-
- test_panic_msg(
- || mem::zeroed::<ManuallyDrop<LR_NonZero>>(),
- "attempted to zero-initialize type `core::mem::manually_drop::ManuallyDrop<LR_NonZero>`, \
- which is invalid"
- );
- } else {
- // These are UB because they have not been officially blessed, but we await the resolution
- // of <https://github.com/rust-lang/unsafe-code-guidelines/issues/71> before doing
- // anything about that.
- let _val = mem::uninitialized::<i32>();
- let _val = mem::uninitialized::<*const ()>();
-
- // These are UB, but best to test them to ensure we don't become unintentionally
- // stricter.
-
- // It's currently unchecked to create invalid enums and values inside arrays.
- let _val = mem::zeroed::<LR_NonZero>();
- let _val = mem::zeroed::<[LR_NonZero; 1]>();
- let _val = mem::zeroed::<[NonNull<()>; 1]>();
- let _val = mem::uninitialized::<[NonNull<()>; 1]>();
- }
}
}
diff --git a/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs b/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs
new file mode 100644
index 000000000..50e12eaeb
--- /dev/null
+++ b/src/test/ui/intrinsics/safe-intrinsic-mismatch.rs
@@ -0,0 +1,11 @@
+#![feature(intrinsics)]
+#![feature(rustc_attrs)]
+
+extern "rust-intrinsic" {
+ fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch
+
+ #[rustc_safe_intrinsic]
+ fn assume(b: bool); //~ ERROR intrinsic safety mismatch
+}
+
+fn main() {}
diff --git a/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr b/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr
new file mode 100644
index 000000000..0c2f3be49
--- /dev/null
+++ b/src/test/ui/intrinsics/safe-intrinsic-mismatch.stderr
@@ -0,0 +1,14 @@
+error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of`
+ --> $DIR/safe-intrinsic-mismatch.rs:5:5
+ |
+LL | fn size_of<T>() -> usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume`
+ --> $DIR/safe-intrinsic-mismatch.rs:8:5
+ |
+LL | fn assume(b: bool);
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/invalid/invalid-inline.rs b/src/test/ui/invalid/invalid-inline.rs
index 8aa8f99f5..2501b1e23 100644
--- a/src/test/ui/invalid/invalid-inline.rs
+++ b/src/test/ui/invalid/invalid-inline.rs
@@ -1,19 +1,14 @@
#![allow(dead_code)]
-#[inline(please_no)] //~ ERROR invalid argument
-fn a() {
-}
-
#[inline(please,no)] //~ ERROR expected one argument
-fn b() {
+fn a() {
}
#[inline()] //~ ERROR expected one argument
-fn c() {
+fn b() {
}
fn main() {
a();
b();
- c();
}
diff --git a/src/test/ui/invalid/invalid-inline.stderr b/src/test/ui/invalid/invalid-inline.stderr
index f3d042641..7edbf936b 100644
--- a/src/test/ui/invalid/invalid-inline.stderr
+++ b/src/test/ui/invalid/invalid-inline.stderr
@@ -1,22 +1,15 @@
-error[E0535]: invalid argument
- --> $DIR/invalid-inline.rs:3:10
- |
-LL | #[inline(please_no)]
- | ^^^^^^^^^
-
error[E0534]: expected one argument
- --> $DIR/invalid-inline.rs:7:1
+ --> $DIR/invalid-inline.rs:3:1
|
LL | #[inline(please,no)]
| ^^^^^^^^^^^^^^^^^^^^
error[E0534]: expected one argument
- --> $DIR/invalid-inline.rs:11:1
+ --> $DIR/invalid-inline.rs:7:1
|
LL | #[inline()]
| ^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
-Some errors have detailed explanations: E0534, E0535.
-For more information about an error, try `rustc --explain E0534`.
+For more information about this error, try `rustc --explain E0534`.
diff --git a/src/test/ui/invalid/invalid-llvm-passes.rs b/src/test/ui/invalid/invalid-llvm-passes.rs
index ca3c6230a..ee28f5eb6 100644
--- a/src/test/ui/invalid/invalid-llvm-passes.rs
+++ b/src/test/ui/invalid/invalid-llvm-passes.rs
@@ -1,4 +1,4 @@
// build-fail
-// compile-flags: -Cpasses=unknown-pass -Z new-llvm-pass-manager=yes
+// compile-flags: -Cpasses=unknown-pass
fn main() {}
diff --git a/src/test/ui/issues/issue-102964.rs b/src/test/ui/issues/issue-102964.rs
new file mode 100644
index 000000000..43ff23600
--- /dev/null
+++ b/src/test/ui/issues/issue-102964.rs
@@ -0,0 +1,10 @@
+use std::rc::Rc;
+type Foo<'a, T> = &'a dyn Fn(&T);
+type RcFoo<'a, T> = Rc<Foo<'a, T>>;
+
+fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
+ //~^ ERROR mismatched types
+ let rc = Rc::new(function);
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-102964.stderr b/src/test/ui/issues/issue-102964.stderr
new file mode 100644
index 000000000..450403909
--- /dev/null
+++ b/src/test/ui/issues/issue-102964.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102964.rs:5:41
+ |
+LL | fn bar_function<T>(function: Foo<T>) -> RcFoo<T> {
+ | ------------ ^^^^^^^^ expected struct `Rc`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+ = note: expected struct `Rc<&dyn for<'a> Fn(&'a T)>`
+ found unit type `()`
+help: consider returning the local binding `rc`
+ |
+LL ~ let rc = Rc::new(function);
+LL + rc
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-11958.stderr b/src/test/ui/issues/issue-11958.stderr
index 25de6ff4c..5dca4c2f0 100644
--- a/src/test/ui/issues/issue-11958.stderr
+++ b/src/test/ui/issues/issue-11958.stderr
@@ -4,8 +4,8 @@ warning: value assigned to `x` is never read
LL | let _thunk = Box::new(move|| { x = 2; });
| ^
|
- = note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
+ = note: `#[warn(unused_assignments)]` on by default
warning: unused variable: `x`
--> $DIR/issue-11958.rs:8:36
@@ -13,8 +13,8 @@ warning: unused variable: `x`
LL | let _thunk = Box::new(move|| { x = 2; });
| ^
|
- = note: `#[warn(unused_variables)]` on by default
= help: did you mean to capture by reference instead?
+ = note: `#[warn(unused_variables)]` on by default
warning: 2 warnings emitted
diff --git a/src/test/ui/issues/issue-1460.stderr b/src/test/ui/issues/issue-1460.stderr
index 26f95f5af..f0ff2cafd 100644
--- a/src/test/ui/issues/issue-1460.stderr
+++ b/src/test/ui/issues/issue-1460.stderr
@@ -4,8 +4,8 @@ warning: unused closure that must be used
LL | {|i: u32| if 1 == i { }};
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: closures are lazy and do nothing unless called
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/issues/issue-14875.rs b/src/test/ui/issues/issue-14875.rs
index aaef2aab9..fca330915 100644
--- a/src/test/ui/issues/issue-14875.rs
+++ b/src/test/ui/issues/issue-14875.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// Check that values are not leaked when a dtor panics (#14875)
diff --git a/src/test/ui/issues/issue-16250.stderr b/src/test/ui/issues/issue-16250.stderr
index ae3b7f334..5eb5e0864 100644
--- a/src/test/ui/issues/issue-16250.stderr
+++ b/src/test/ui/issues/issue-16250.stderr
@@ -4,12 +4,6 @@ error: `extern` block uses type `Foo`, which is not FFI-safe
LL | pub fn foo(x: (Foo));
| ^^^ not FFI-safe
|
-note: the lint level is defined here
- --> $DIR/issue-16250.rs:1:9
- |
-LL | #![deny(warnings)]
- | ^^^^^^^^
- = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]`
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
@@ -17,6 +11,12 @@ note: the type is defined here
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/issue-16250.rs:1:9
+ |
+LL | #![deny(warnings)]
+ | ^^^^^^^^
+ = note: `#[deny(improper_ctypes)]` implied by `#[deny(warnings)]`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-16256.stderr b/src/test/ui/issues/issue-16256.stderr
index 9c7312461..ca8e9a1be 100644
--- a/src/test/ui/issues/issue-16256.stderr
+++ b/src/test/ui/issues/issue-16256.stderr
@@ -4,8 +4,8 @@ warning: unused closure that must be used
LL | |c: u8| buf.push(c);
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: closures are lazy and do nothing unless called
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr
index db32eb952..e3af8976c 100644
--- a/src/test/ui/issues/issue-17431-1.stderr
+++ b/src/test/ui/issues/issue-17431-1.stderr
@@ -2,14 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-1.rs:1:1
|
LL | struct Foo { foo: Option<Option<Foo>> }
- | ^^^^^^^^^^ ------------------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^^ --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | struct Foo { foo: Option<Box<Option<Foo>>> }
- | ++++ +
+LL | struct Foo { foo: Option<Option<Box<Foo>>> }
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17431-2.rs b/src/test/ui/issues/issue-17431-2.rs
index 9ed97f631..f7b9c6a55 100644
--- a/src/test/ui/issues/issue-17431-2.rs
+++ b/src/test/ui/issues/issue-17431-2.rs
@@ -1,8 +1,7 @@
struct Baz { q: Option<Foo> }
-//~^ ERROR recursive type `Baz` has infinite size
+//~^ ERROR recursive types `Baz` and `Foo` have infinite size
struct Foo { q: Option<Baz> }
-//~^ ERROR recursive type `Foo` has infinite size
impl Foo { fn bar(&self) {} }
diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr
index d23fd1474..39a99ec1e 100644
--- a/src/test/ui/issues/issue-17431-2.stderr
+++ b/src/test/ui/issues/issue-17431-2.stderr
@@ -1,29 +1,20 @@
-error[E0072]: recursive type `Baz` has infinite size
+error[E0072]: recursive types `Baz` and `Foo` have infinite size
--> $DIR/issue-17431-2.rs:1:1
|
LL | struct Baz { q: Option<Foo> }
- | ^^^^^^^^^^ ----------- recursive without indirection
- | |
- | recursive type has infinite size
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
- |
-LL | struct Baz { q: Option<Box<Foo>> }
- | ++++ +
-
-error[E0072]: recursive type `Foo` has infinite size
- --> $DIR/issue-17431-2.rs:4:1
- |
+ | ^^^^^^^^^^ --- recursive without indirection
+...
LL | struct Foo { q: Option<Baz> }
- | ^^^^^^^^^^ ----------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^^ --- recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+LL ~ struct Baz { q: Option<Box<Foo>> }
+LL |
+LL |
+LL ~ struct Foo { q: Option<Box<Baz>> }
|
-LL | struct Foo { q: Option<Box<Baz>> }
- | ++++ +
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr
index 0dde6f382..394134c78 100644
--- a/src/test/ui/issues/issue-17431-3.stderr
+++ b/src/test/ui/issues/issue-17431-3.stderr
@@ -2,14 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-3.rs:3:1
|
LL | struct Foo { foo: Mutex<Option<Foo>> }
- | ^^^^^^^^^^ ------------------ recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^^ --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
- | ++++ +
+LL | struct Foo { foo: Mutex<Option<Box<Foo>>> }
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr
index ddf669b8f..3d141e44b 100644
--- a/src/test/ui/issues/issue-17431-4.stderr
+++ b/src/test/ui/issues/issue-17431-4.stderr
@@ -2,14 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-4.rs:3:1
|
LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
- | ^^^^^^^^^^^^^ ---------------------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^^^^^ ------ recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | struct Foo<T> { foo: Option<Box<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
- | ++++ +
+LL | struct Foo<T> { foo: Option<Option<Box<Foo<T>>>>, marker: marker::PhantomData<T> }
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr
index a379598c2..44a90a6fe 100644
--- a/src/test/ui/issues/issue-17431-5.stderr
+++ b/src/test/ui/issues/issue-17431-5.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `Bar` has infinite size
|
LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
| ^^^^^^^^^^^^^ -------- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
| ++++ +
diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr
index fcac420b2..e0a822550 100644
--- a/src/test/ui/issues/issue-17431-6.stderr
+++ b/src/test/ui/issues/issue-17431-6.stderr
@@ -2,14 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-6.rs:3:1
|
LL | enum Foo { X(Mutex<Option<Foo>>) }
- | ^^^^^^^^ ------------------ recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^ --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
- | ++++ +
+LL | enum Foo { X(Mutex<Option<Box<Foo>>>) }
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr
index 6f8a7e386..ecf072b8e 100644
--- a/src/test/ui/issues/issue-17431-7.stderr
+++ b/src/test/ui/issues/issue-17431-7.stderr
@@ -2,14 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-7.rs:1:1
|
LL | enum Foo { Voo(Option<Option<Foo>>) }
- | ^^^^^^^^ ------------------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^ --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | enum Foo { Voo(Option<Box<Option<Foo>>>) }
- | ++++ +
+LL | enum Foo { Voo(Option<Option<Box<Foo>>>) }
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-18919.stderr b/src/test/ui/issues/issue-18919.stderr
index d7dbb8299..b0b03a0ee 100644
--- a/src/test/ui/issues/issue-18919.stderr
+++ b/src/test/ui/issues/issue-18919.stderr
@@ -1,10 +1,10 @@
-error[E0277]: the size for values of type `dyn for<'r> Fn(&'r isize) -> isize` cannot be known at compilation time
+error[E0277]: the size for values of type `dyn for<'a> Fn(&'a isize) -> isize` cannot be known at compilation time
--> $DIR/issue-18919.rs:3:15
|
LL | fn ho_func(f: Option<FuncType>) {
| ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
- = help: the trait `Sized` is not implemented for `dyn for<'r> Fn(&'r isize) -> isize`
+ = help: the trait `Sized` is not implemented for `dyn for<'a> Fn(&'a isize) -> isize`
note: required by a bound in `Option`
--> $DIR/issue-18919.rs:7:13
|
diff --git a/src/test/ui/issues/issue-19991.rs b/src/test/ui/issues/issue-19991.rs
index 1f3b73f96..dd0efa972 100644
--- a/src/test/ui/issues/issue-19991.rs
+++ b/src/test/ui/issues/issue-19991.rs
@@ -3,7 +3,7 @@
fn main() {
if let Some(homura) = Some("madoka") { //~ ERROR missing an `else` clause
- //~| expected `()`, found integer
+ //~| expected integer, found `()`
765
};
}
diff --git a/src/test/ui/issues/issue-19991.stderr b/src/test/ui/issues/issue-19991.stderr
index 6e92be87a..57b0882b6 100644
--- a/src/test/ui/issues/issue-19991.stderr
+++ b/src/test/ui/issues/issue-19991.stderr
@@ -6,7 +6,7 @@ LL | |
LL | | 765
| | --- found here
LL | | };
- | |_____^ expected `()`, found integer
+ | |_____^ expected integer, found `()`
|
= note: `if` expressions without `else` evaluate to `()`
= help: consider adding an `else` block that evaluates to the expected type
diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr
index 09402c3d8..5981d9dc7 100644
--- a/src/test/ui/issues/issue-21174.stderr
+++ b/src/test/ui/issues/issue-21174.stderr
@@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently-
LL | let new: T::B = unsafe { std::mem::transmute(value) };
| ^^^^^^^^^^^^^^^^^^^
|
- = note: source type: `<T as Trait>::A` (this type does not have a fixed size)
- = note: target type: `<T as Trait>::B` (this type does not have a fixed size)
+ = note: source type: `<T as Trait<'_>>::A` (this type does not have a fixed size)
+ = note: target type: `<T as Trait<'_>>::B` (this type does not have a fixed size)
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-22644.rs b/src/test/ui/issues/issue-22644.rs
index 9244ff593..b1d69dcd8 100644
--- a/src/test/ui/issues/issue-22644.rs
+++ b/src/test/ui/issues/issue-22644.rs
@@ -29,7 +29,7 @@ fn main() {
< //~ ERROR `<` is interpreted as a start of generic
5);
- println!("{}", a as usize << long_name); //~ ERROR `<` is interpreted as a start of generic
+ println!("{}", a as usize << long_name); //~ ERROR `<<` is interpreted as a start of generic
println!("{}", a: &mut 4); //~ ERROR expected type, found `4`
}
diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr
index 039ffbfd3..45027afa7 100644
--- a/src/test/ui/issues/issue-22644.stderr
+++ b/src/test/ui/issues/issue-22644.stderr
@@ -95,7 +95,7 @@ LL |
LL ~ usize)
|
-error: `<` is interpreted as a start of generic arguments for `usize`, not a shift
+error: `<<` is interpreted as a start of generic arguments for `usize`, not a shift
--> $DIR/issue-22644.rs:32:31
|
LL | println!("{}", a as usize << long_name);
diff --git a/src/test/ui/issues/issue-23122-2.rs b/src/test/ui/issues/issue-23122-2.rs
index 95e1f60d8..338789c2e 100644
--- a/src/test/ui/issues/issue-23122-2.rs
+++ b/src/test/ui/issues/issue-23122-2.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
trait Next {
type Next: Next;
}
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index f6cda3de5..0111cf569 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -1,10 +1,15 @@
-error[E0275]: overflow evaluating the requirement `<T as Next>::Next`
- --> $DIR/issue-23122-2.rs:10:17
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
+ --> $DIR/issue-23122-2.rs:11:17
|
LL | type Next = <GetNext<T::Next> as Next>::Next;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
+note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+ --> $DIR/issue-23122-2.rs:10:15
+ |
+LL | impl<T: Next> Next for GetNext<T> {
+ | ^^^^ ^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-24013.stderr b/src/test/ui/issues/issue-24013.stderr
index 995dce552..72102f460 100644
--- a/src/test/ui/issues/issue-24013.stderr
+++ b/src/test/ui/issues/issue-24013.stderr
@@ -3,11 +3,6 @@ error[E0282]: type annotations needed
|
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap`
- |
-help: consider specifying the generic argument
- |
-LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
- | ~~~~~~~~~~
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr
index 1a4fab165..1e4c8ac7c 100644
--- a/src/test/ui/issues/issue-24322.stderr
+++ b/src/test/ui/issues/issue-24322.stderr
@@ -6,8 +6,8 @@ LL | let x: &fn(&B) -> u32 = &B::func;
| |
| expected due to this
|
- = note: expected reference `&for<'r> fn(&'r B) -> u32`
- found reference `&for<'r> fn(&'r B) -> u32 {B::func}`
+ = note: expected reference `&for<'a> fn(&'a B) -> u32`
+ found reference `&for<'a> fn(&'a B) -> u32 {B::func}`
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-25901.rs b/src/test/ui/issues/issue-25901.rs
index ba12e1ad0..1f7b341a9 100644
--- a/src/test/ui/issues/issue-25901.rs
+++ b/src/test/ui/issues/issue-25901.rs
@@ -2,7 +2,7 @@ struct A;
struct B;
static S: &'static B = &A;
-//~^ ERROR cannot perform deref coercion on `A` in statics
+//~^ ERROR the trait bound
use std::ops::Deref;
diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr
index c6c80e41c..b9cac3222 100644
--- a/src/test/ui/issues/issue-25901.stderr
+++ b/src/test/ui/issues/issue-25901.stderr
@@ -1,23 +1,15 @@
-error[E0015]: cannot perform deref coercion on `A` in statics
+error[E0277]: the trait bound `A: Deref` is not satisfied
--> $DIR/issue-25901.rs:4:24
|
LL | static S: &'static B = &A;
- | ^^
- |
- = note: attempting to deref into `B`
-note: deref defined here
- --> $DIR/issue-25901.rs:10:5
+ | ^^ the trait `~const Deref` is not implemented for `A`
|
-LL | type Target = B;
- | ^^^^^^^^^^^
-note: impl defined here, but it is not `const`
- --> $DIR/issue-25901.rs:9:1
+note: the trait `Deref` is implemented for `A`, but that implementation is not `const`
+ --> $DIR/issue-25901.rs:4:24
|
-LL | impl Deref for A {
- | ^^^^^^^^^^^^^^^^
- = note: calls in statics are limited to constant functions, tuple structs and tuple variants
- = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+LL | static S: &'static B = &A;
+ | ^^
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-28344.stderr b/src/test/ui/issues/issue-28344.stderr
index 85a8698af..f398a5da3 100644
--- a/src/test/ui/issues/issue-28344.stderr
+++ b/src/test/ui/issues/issue-28344.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
| ^^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | let x: u8 = <dyn BitXor>::bitor(0 as u8, 0 as u8);
diff --git a/src/test/ui/issues/issue-29746.rs b/src/test/ui/issues/issue-29746.rs
index 428cc637f..3470a7e09 100644
--- a/src/test/ui/issues/issue-29746.rs
+++ b/src/test/ui/issues/issue-29746.rs
@@ -7,7 +7,7 @@ macro_rules! zip {
zip!([$($rest),*], $a.zip($b), (x,y), [x,y])
};
- // Intermediate steps to build the zipped expression, the match pattern, and
+ // Intermediate steps to build the zipped expression, the match pattern
// and the output tuple of the closure, using macro hygiene to repeatedly
// introduce new variables named 'x'.
([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs
index 01c3ec648..3ed701480 100644
--- a/src/test/ui/issues/issue-29948.rs
+++ b/src/test/ui/issues/issue-29948.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
use std::panic;
diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr
index e49d8e6aa..be25b9091 100644
--- a/src/test/ui/issues/issue-3008-1.stderr
+++ b/src/test/ui/issues/issue-3008-1.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `Bar` has infinite size
--> $DIR/issue-3008-1.rs:5:1
|
LL | enum Bar {
- | ^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^
...
LL | BarSome(Bar)
| --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | BarSome(Box<Bar>)
| ++++ +
diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr
index b3ce6e420..858a8fd6a 100644
--- a/src/test/ui/issues/issue-3008-2.stderr
+++ b/src/test/ui/issues/issue-3008-2.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `Bar` has infinite size
|
LL | struct Bar { x: Bar }
| ^^^^^^^^^^ --- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct Bar { x: Box<Bar> }
| ++++ +
diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr
index c1c043e21..a1a81e293 100644
--- a/src/test/ui/issues/issue-3008-3.stderr
+++ b/src/test/ui/issues/issue-3008-3.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `E2` has infinite size
|
LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
| ^^^^^^^^^^ ------ recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
| ++++ +
diff --git a/src/test/ui/issues/issue-30371.rs b/src/test/ui/issues/issue-30371.rs
index a1ae9a36b..eea548c48 100644
--- a/src/test/ui/issues/issue-30371.rs
+++ b/src/test/ui/issues/issue-30371.rs
@@ -1,5 +1,6 @@
// run-pass
#![allow(unreachable_code)]
+#![allow(for_loops_over_fallibles)]
#![deny(unused_variables)]
fn main() {
diff --git a/src/test/ui/issues/issue-30490.rs b/src/test/ui/issues/issue-30490.rs
index 47c17e362..68d9c4de4 100644
--- a/src/test/ui/issues/issue-30490.rs
+++ b/src/test/ui/issues/issue-30490.rs
@@ -1,6 +1,7 @@
// run-pass
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia Child I/O swaps not privileged
// Previously libstd would set stdio descriptors of a child process
// by `dup`ing the requested descriptors to inherit directly into the
diff --git a/src/test/ui/issues/issue-32326.stderr b/src/test/ui/issues/issue-32326.stderr
index cea765850..dc51198d9 100644
--- a/src/test/ui/issues/issue-32326.stderr
+++ b/src/test/ui/issues/issue-32326.stderr
@@ -2,16 +2,14 @@ error[E0072]: recursive type `Expr` has infinite size
--> $DIR/issue-32326.rs:5:1
|
LL | enum Expr {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
LL | Plus(Expr, Expr),
- | ---- ---- recursive without indirection
- | |
- | recursive without indirection
+ | ---- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | Plus(Box<Expr>, Box<Expr>),
- | ++++ + ++++ +
+LL | Plus(Box<Expr>, Expr),
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-35241.stderr b/src/test/ui/issues/issue-35241.stderr
index 9ee7654a0..42a78ed97 100644
--- a/src/test/ui/issues/issue-35241.stderr
+++ b/src/test/ui/issues/issue-35241.stderr
@@ -11,7 +11,7 @@ LL | fn test() -> Foo { Foo }
|
= note: expected struct `Foo`
found fn item `fn(u32) -> Foo {Foo}`
-help: use parentheses to instantiate this tuple struct
+help: use parentheses to construct this tuple struct
|
LL | fn test() -> Foo { Foo(/* u32 */) }
| +++++++++++
diff --git a/src/test/ui/issues/issue-3563-2.rs b/src/test/ui/issues/issue-3563-2.rs
deleted file mode 100644
index 88a449b85..000000000
--- a/src/test/ui/issues/issue-3563-2.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-// check-pass
-// pretty-expanded FIXME #23616
-
-trait Canvas {
- fn add_point(&self, point: &isize);
- fn add_points(&self, shapes: &[isize]) {
- for pt in shapes {
- self.add_point(pt)
- }
- }
-
-}
-
-pub fn main() {}
diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr
index e853d0f8c..a0dbcc920 100644
--- a/src/test/ui/issues/issue-3779.stderr
+++ b/src/test/ui/issues/issue-3779.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `S` has infinite size
--> $DIR/issue-3779.rs:1:1
|
LL | struct S {
- | ^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^
LL |
LL | element: Option<S>
- | --------- recursive without indirection
+ | - recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | element: Option<Box<S>>
| ++++ +
diff --git a/src/test/ui/issues/issue-40000.stderr b/src/test/ui/issues/issue-40000.stderr
index e6f0b5fbf..c41fbb9d2 100644
--- a/src/test/ui/issues/issue-40000.stderr
+++ b/src/test/ui/issues/issue-40000.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | foo(bar);
| ^^^ one type is more general than the other
|
- = note: expected trait object `dyn for<'r> Fn(&'r i32)`
+ = note: expected trait object `dyn for<'a> Fn(&'a i32)`
found trait object `dyn Fn(&i32)`
error[E0308]: mismatched types
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
LL | foo(bar);
| ^^^ one type is more general than the other
|
- = note: expected trait object `dyn for<'r> Fn(&'r i32)`
+ = note: expected trait object `dyn for<'a> Fn(&'a i32)`
found trait object `dyn Fn(&i32)`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr
index 27e83d495..8c7303f3c 100644
--- a/src/test/ui/issues/issue-4265.stderr
+++ b/src/test/ui/issues/issue-4265.stderr
@@ -1,12 +1,12 @@
-error[E0201]: duplicate definitions with name `bar`:
+error[E0592]: duplicate definitions with name `bar`
--> $DIR/issue-4265.rs:10:5
|
LL | fn bar() {
- | -------- previous definition of `bar` here
+ | -------- other definition for `bar`
...
LL | fn bar() {
- | ^^^^^^^^ duplicate definition
+ | ^^^^^^^^ duplicate definitions for `bar`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0201`.
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/issues/issue-43853.rs b/src/test/ui/issues/issue-43853.rs
index 3162c091c..dd42c1e3c 100644
--- a/src/test/ui/issues/issue-43853.rs
+++ b/src/test/ui/issues/issue-43853.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
use std::panic;
diff --git a/src/test/ui/issues/issue-46519.rs b/src/test/ui/issues/issue-46519.rs
index 9bd3c0948..0567923b7 100644
--- a/src/test/ui/issues/issue-46519.rs
+++ b/src/test/ui/issues/issue-46519.rs
@@ -2,7 +2,6 @@
// compile-flags:--test -O
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#[test]
#[should_panic(expected = "creating inhabited type")]
diff --git a/src/test/ui/issues/issue-47094.stderr b/src/test/ui/issues/issue-47094.stderr
index e323ce660..970e31847 100644
--- a/src/test/ui/issues/issue-47094.stderr
+++ b/src/test/ui/issues/issue-47094.stderr
@@ -4,9 +4,9 @@ error[E0566]: conflicting representation hints
LL | #[repr(C, u8)]
| ^ ^^
|
- = note: `#[deny(conflicting_repr_hints)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #68585 <https://github.com/rust-lang/rust/issues/68585>
+ = note: `#[deny(conflicting_repr_hints)]` on by default
error[E0566]: conflicting representation hints
--> $DIR/issue-47094.rs:8:8
diff --git a/src/test/ui/issues/issue-47486.stderr b/src/test/ui/issues/issue-47486.stderr
index b45f57b7b..2bd24f08c 100644
--- a/src/test/ui/issues/issue-47486.stderr
+++ b/src/test/ui/issues/issue-47486.stderr
@@ -9,11 +9,6 @@ error[E0282]: type annotations needed
|
LL | [0u8; std::mem::size_of::<_>()];
| ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `size_of`
- |
-help: consider specifying the generic argument
- |
-LL | [0u8; std::mem::size_of::<_>()];
- | ~~~~~
error: aborting due to 2 previous errors
diff --git a/src/test/ui/issues/issue-47725.stderr b/src/test/ui/issues/issue-47725.stderr
index c7a9bfe31..7143fb4d6 100644
--- a/src/test/ui/issues/issue-47725.stderr
+++ b/src/test/ui/issues/issue-47725.stderr
@@ -13,12 +13,12 @@ LL | #[link_name = "foo"]
LL | struct Foo;
| ----------- not a foreign function or static
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/issue-47725.rs:1:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
warning: attribute should be applied to a foreign function or static
--> $DIR/issue-47725.rs:8:1
diff --git a/src/test/ui/issues/issue-50582.stderr b/src/test/ui/issues/issue-50582.stderr
index 3d527eb6b..53ecc6112 100644
--- a/src/test/ui/issues/issue-50582.stderr
+++ b/src/test/ui/issues/issue-50582.stderr
@@ -7,13 +7,13 @@ LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
= help: add `#![feature(const_for)]` to the crate attributes to enable
-error[E0277]: cannot add `()` to `{integer}`
+error[E0277]: cannot add `()` to `{integer}` in const contexts
--> $DIR/issue-50582.rs:2:18
|
LL | Vec::<[(); 1 + for x in 0..1 {}]>::new();
| ^ no implementation for `{integer} + ()`
|
- = help: the trait `Add<()>` is not implemented for `{integer}`
+ = help: the trait `~const Add<()>` is not implemented for `{integer}`
= help: the following other types implement trait `Add<Rhs>`:
<&'a f32 as Add<f32>>
<&'a f64 as Add<f64>>
diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr
index 93bd951d3..e185ecdda 100644
--- a/src/test/ui/issues/issue-50781.stderr
+++ b/src/test/ui/issues/issue-50781.stderr
@@ -4,11 +4,6 @@ error: the trait `X` cannot be made into an object
LL | fn foo(&self) where Self: Trait;
| ^^^
|
-note: the lint level is defined here
- --> $DIR/issue-50781.rs:1:9
- |
-LL | #![deny(where_clauses_object_safety)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
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>
@@ -19,6 +14,11 @@ LL | trait X {
LL | fn foo(&self) where Self: Trait;
| ^^^ ...because method `foo` references the `Self` type in its `where` clause
= help: consider moving `foo` to another trait
+note: the lint level is defined here
+ --> $DIR/issue-50781.rs:1:9
+ |
+LL | #![deny(where_clauses_object_safety)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-54044.stderr b/src/test/ui/issues/issue-54044.stderr
index 100965de1..8bd94a041 100644
--- a/src/test/ui/issues/issue-54044.stderr
+++ b/src/test/ui/issues/issue-54044.stderr
@@ -7,12 +7,12 @@ LL | #[cold]
LL | struct Foo;
| ----------- not a function definition
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/issue-54044.rs:1:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error: attribute should be applied to a function definition
--> $DIR/issue-54044.rs:9:5
diff --git a/src/test/ui/issues/issue-55380.stderr b/src/test/ui/issues/issue-55380.stderr
index 65e94d796..403844c72 100644
--- a/src/test/ui/issues/issue-55380.stderr
+++ b/src/test/ui/issues/issue-55380.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/issues/issue-57271.rs b/src/test/ui/issues/issue-57271.rs
index 9940fecbe..f74222e3e 100644
--- a/src/test/ui/issues/issue-57271.rs
+++ b/src/test/ui/issues/issue-57271.rs
@@ -4,7 +4,7 @@ extern crate issue_57271_lib;
use issue_57271_lib::BaseType;
-pub enum ObjectType { //~ ERROR recursive type `ObjectType` has infinite size
+pub enum ObjectType { //~ ERROR recursive types `ObjectType` and `TypeSignature` have infinite size
Class(ClassTypeSignature),
Array(TypeSignature),
TypeVariable(()),
@@ -16,7 +16,7 @@ pub struct ClassTypeSignature {
pub inner: (),
}
-pub enum TypeSignature { //~ ERROR recursive type `TypeSignature` has infinite size
+pub enum TypeSignature {
Base(BaseType),
Object(ObjectType),
}
diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr
index 825009665..391e69c91 100644
--- a/src/test/ui/issues/issue-57271.stderr
+++ b/src/test/ui/issues/issue-57271.stderr
@@ -1,31 +1,27 @@
-error[E0072]: recursive type `ObjectType` has infinite size
+error[E0072]: recursive types `ObjectType` and `TypeSignature` have infinite size
--> $DIR/issue-57271.rs:7:1
|
LL | pub enum ObjectType {
- | ^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^^^^^^^^^
LL | Class(ClassTypeSignature),
LL | Array(TypeSignature),
| ------------- recursive without indirection
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
- |
-LL | Array(Box<TypeSignature>),
- | ++++ +
-
-error[E0072]: recursive type `TypeSignature` has infinite size
- --> $DIR/issue-57271.rs:19:1
- |
+...
LL | pub enum TypeSignature {
- | ^^^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^^^^^^^^^^^^
LL | Base(BaseType),
LL | Object(ObjectType),
| ---------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL ~ Array(Box<TypeSignature>),
+LL | TypeVariable(()),
+ ...
+LL | Base(BaseType),
+LL ~ Object(Box<ObjectType>),
|
-LL | Object(Box<ObjectType>),
- | ++++ +
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr
index 3b6cffeaf..7d08c4643 100644
--- a/src/test/ui/issues/issue-57362-2.stderr
+++ b/src/test/ui/issues/issue-57362-2.stderr
@@ -1,11 +1,11 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, 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<'r> fn(&'r ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
- `for<'r> fn(&'r ()): X`
+ `for<'a> fn(&'a ()): X`
= help: items from traits can only be used if the trait is implemented and in scope
note: `X` defines an item `make_g`, perhaps you need to implement it
--> $DIR/issue-57362-2.rs:8:1
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index 6d24209ad..56d85c066 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -1,9 +1,3 @@
-error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
- --> $DIR/issue-58022.rs:14:9
- |
-LL | Foo(Box::new(*slice))
- | ^^^ not a function, tuple struct or tuple variant
-
error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
--> $DIR/issue-58022.rs:4:25
|
@@ -13,6 +7,12 @@ LL |
LL | fn new(slice: &[u8; Foo::SIZE]) -> Self;
| ^^^^^^^^^ cannot refer to the associated constant of trait
+error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo`
+ --> $DIR/issue-58022.rs:14:9
+ |
+LL | Foo(Box::new(*slice))
+ | ^^^ not a function, tuple struct or tuple variant
+
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0423, E0790.
diff --git a/src/test/ui/issues/issue-58734.stderr b/src/test/ui/issues/issue-58734.stderr
index a91a1b377..d2314626d 100644
--- a/src/test/ui/issues/issue-58734.stderr
+++ b/src/test/ui/issues/issue-58734.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | Trait::nonexistent(());
| ^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | <dyn Trait>::nonexistent(());
diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr
index 08fe0b35e..f9846b62a 100644
--- a/src/test/ui/issues/issue-59488.stderr
+++ b/src/test/ui/issues/issue-59488.stderr
@@ -99,7 +99,7 @@ LL | assert_eq!(Foo::Bar, i);
extern "C" fn(A, B, C, D) -> Ret
extern "C" fn(A, B, C, D, ...) -> Ret
extern "C" fn(A, B, C, D, E) -> Ret
- and 68 others
+ and 118 others
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
@@ -118,7 +118,7 @@ LL | assert_eq!(Foo::Bar, i);
extern "C" fn(A, B, C, D) -> Ret
extern "C" fn(A, B, C, D, ...) -> Ret
extern "C" fn(A, B, C, D, E) -> Ret
- and 68 others
+ and 118 others
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 10 previous errors
diff --git a/src/test/ui/issues/issue-60622.stderr b/src/test/ui/issues/issue-60622.stderr
index b305cc785..ecf1ae758 100644
--- a/src/test/ui/issues/issue-60622.stderr
+++ b/src/test/ui/issues/issue-60622.stderr
@@ -7,14 +7,14 @@ LL | fn a(&self) {}
LL | b.a::<'_, T>();
| ^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
note: the lint level is defined here
--> $DIR/issue-60622.rs:1:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(late_bound_lifetime_arguments)]` implied by `#[deny(warnings)]`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-60622.rs:10:7
diff --git a/src/test/ui/issues/issue-6458-3.stderr b/src/test/ui/issues/issue-6458-3.stderr
index 2c3ec1a33..520efccae 100644
--- a/src/test/ui/issues/issue-6458-3.stderr
+++ b/src/test/ui/issues/issue-6458-3.stderr
@@ -2,12 +2,12 @@ error[E0282]: type annotations needed
--> $DIR/issue-6458-3.rs:4:5
|
LL | mem::transmute(0);
- | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `transmute`
+ | ^^^^^^^^^^^^^^ cannot infer type of the type parameter `Dst` declared on the function `transmute`
|
help: consider specifying the generic arguments
|
-LL | mem::transmute::<i32, U>(0);
- | ++++++++++
+LL | mem::transmute::<i32, Dst>(0);
+ | ++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-6458-4.stderr b/src/test/ui/issues/issue-6458-4.stderr
index d6e74d10e..168ececac 100644
--- a/src/test/ui/issues/issue-6458-4.stderr
+++ b/src/test/ui/issues/issue-6458-4.stderr
@@ -6,7 +6,7 @@ LL | fn foo(b: bool) -> Result<bool,String> {
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | Err("bar".to_string());
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
|
= note: expected enum `Result<bool, String>`
found unit type `()`
diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
index 7f29709ce..b30bcfb77 100644
--- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
+++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
@@ -29,7 +29,7 @@ LL | assert_eq!(a, 0);
| ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
|
= help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
- = help: use parentheses to call the function: `a()`
+ = help: use parentheses to call this function: `a()`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 3 previous errors
diff --git a/src/test/ui/issues/issue-72278.stderr b/src/test/ui/issues/issue-72278.stderr
index 41dff686b..5468837a3 100644
--- a/src/test/ui/issues/issue-72278.stderr
+++ b/src/test/ui/issues/issue-72278.stderr
@@ -7,9 +7,9 @@ LL | fn func<'a, U>(&'a self) -> U {
LL | S.func::<'a, U>()
| ^^
|
- = note: `#[warn(late_bound_lifetime_arguments)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+ = note: `#[warn(late_bound_lifetime_arguments)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/issues/issue-72554.rs b/src/test/ui/issues/issue-72554.rs
index 7287639c6..54f7e9ac5 100644
--- a/src/test/ui/issues/issue-72554.rs
+++ b/src/test/ui/issues/issue-72554.rs
@@ -3,7 +3,6 @@ use std::collections::BTreeSet;
#[derive(Hash)]
pub enum ElemDerived {
//~^ ERROR recursive type `ElemDerived` has infinite size
- //~| ERROR cycle detected when computing drop-check constraints for `ElemDerived`
A(ElemDerived)
}
diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/issues/issue-72554.stderr
index 3e5adcae1..d12be539f 100644
--- a/src/test/ui/issues/issue-72554.stderr
+++ b/src/test/ui/issues/issue-72554.stderr
@@ -2,30 +2,16 @@ error[E0072]: recursive type `ElemDerived` has infinite size
--> $DIR/issue-72554.rs:4:1
|
LL | pub enum ElemDerived {
- | ^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size
-...
+ | ^^^^^^^^^^^^^^^^^^^^
+LL |
LL | A(ElemDerived)
| ----------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | A(Box<ElemDerived>)
| ++++ +
-error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived`
- --> $DIR/issue-72554.rs:4:1
- |
-LL | pub enum ElemDerived {
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: ...which immediately requires computing drop-check constraints for `ElemDerived` again
-note: cycle used when computing drop-check constraints for `Elem`
- --> $DIR/issue-72554.rs:11:1
- |
-LL | pub enum Elem {
- | ^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0072, E0391.
-For more information about an error, try `rustc --explain E0072`.
+For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/issues/issue-75307.rs b/src/test/ui/issues/issue-75307.rs
index 2fe112a3b..cffa6bea8 100644
--- a/src/test/ui/issues/issue-75307.rs
+++ b/src/test/ui/issues/issue-75307.rs
@@ -1,3 +1,3 @@
fn main() {
- format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
+ format!(r"{}{}{}", named_arg=1); //~ ERROR 3 positional arguments in format string, but there is 1 argument
}
diff --git a/src/test/ui/issues/issue-75307.stderr b/src/test/ui/issues/issue-75307.stderr
index 10c952006..c5b0b11e7 100644
--- a/src/test/ui/issues/issue-75307.stderr
+++ b/src/test/ui/issues/issue-75307.stderr
@@ -1,10 +1,8 @@
-error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
- --> $DIR/issue-75307.rs:2:17
+error: 3 positional arguments in format string, but there is 1 argument
+ --> $DIR/issue-75307.rs:2:15
|
LL | format!(r"{}{}{}", named_arg=1);
- | ^^^^
- |
- = note: positional arguments are zero-based
+ | ^^^^^^ -
error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-75907.rs b/src/test/ui/issues/issue-75907.rs
index 1534b6d07..6da99cf64 100644
--- a/src/test/ui/issues/issue-75907.rs
+++ b/src/test/ui/issues/issue-75907.rs
@@ -1,4 +1,4 @@
-// Test for for diagnostic improvement issue #75907
+// Test for diagnostic improvement issue #75907
mod foo {
pub(crate) struct Foo(u8);
diff --git a/src/test/ui/issues/issue-75907_b.rs b/src/test/ui/issues/issue-75907_b.rs
index e30747782..fdfc5907c 100644
--- a/src/test/ui/issues/issue-75907_b.rs
+++ b/src/test/ui/issues/issue-75907_b.rs
@@ -1,4 +1,4 @@
-// Test for for diagnostic improvement issue #75907, extern crate
+// Test for diagnostic improvement issue #75907, extern crate
// aux-build:issue-75907.rs
extern crate issue_75907 as a;
diff --git a/src/test/ui/issues/issue-77993-1.rs b/src/test/ui/issues/issue-77993-1.rs
deleted file mode 100644
index 515b3bc09..000000000
--- a/src/test/ui/issues/issue-77993-1.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-#[derive(Clone)]
-struct InGroup<F> {
- it: It,
- //~^ ERROR cannot find type `It` in this scope
- f: F,
-}
-fn dates_in_year() -> impl Clone {
- InGroup { f: |d| d }
- //~^ ERROR missing field `it` in initializer of `InGroup<_>`
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-77993-1.stderr b/src/test/ui/issues/issue-77993-1.stderr
deleted file mode 100644
index 3dc78ba6f..000000000
--- a/src/test/ui/issues/issue-77993-1.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0412]: cannot find type `It` in this scope
- --> $DIR/issue-77993-1.rs:3:9
- |
-LL | it: It,
- | ^^ not found in this scope
-
-error[E0063]: missing field `it` in initializer of `InGroup<_>`
- --> $DIR/issue-77993-1.rs:8:5
- |
-LL | InGroup { f: |d| d }
- | ^^^^^^^ missing `it`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0063, E0412.
-For more information about an error, try `rustc --explain E0063`.
diff --git a/src/test/ui/issues/issue-78957.stderr b/src/test/ui/issues/issue-78957.stderr
index 45fa69d6f..6de22d6bf 100644
--- a/src/test/ui/issues/issue-78957.stderr
+++ b/src/test/ui/issues/issue-78957.stderr
@@ -10,12 +10,12 @@ error: attribute should be applied to a function definition
LL | pub struct Bar<#[cold] const N: usize>;
| ^^^^^^^ -------------- not a function definition
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
note: the lint level is defined here
--> $DIR/issue-78957.rs:1:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
error[E0517]: attribute should be applied to a struct, enum, or union
--> $DIR/issue-78957.rs:10:23
diff --git a/src/test/ui/issues/issue-86756.stderr b/src/test/ui/issues/issue-86756.stderr
index b26c1834d..693cfeced 100644
--- a/src/test/ui/issues/issue-86756.stderr
+++ b/src/test/ui/issues/issue-86756.stderr
@@ -20,9 +20,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | eq::<dyn, Foo>
| ^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | eq::<dyn, dyn Foo>
diff --git a/src/test/ui/issues/issue-8727.stderr b/src/test/ui/issues/issue-8727.stderr
index 10daba5ef..5e1fdad60 100644
--- a/src/test/ui/issues/issue-8727.stderr
+++ b/src/test/ui/issues/issue-8727.stderr
@@ -6,8 +6,8 @@ LL | fn generic<T>() {
LL | generic::<Option<T>>();
| ---------------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error: reached the recursion limit while instantiating `generic::<Option<Option<Option<O...>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
--> $DIR/issue-8727.rs:8:5
diff --git a/src/test/ui/issues/issue-87707.rs b/src/test/ui/issues/issue-87707.rs
index 26e9e2c8f..c14e52dfe 100644
--- a/src/test/ui/issues/issue-87707.rs
+++ b/src/test/ui/issues/issue-87707.rs
@@ -3,6 +3,7 @@
// run-fail
// exec-env:RUST_BACKTRACE=0
// check-run-results
+// needs-unwind uses catch_unwind
use std::sync::Once;
use std::panic;
diff --git a/src/test/ui/issues/issue-87707.run.stderr b/src/test/ui/issues/issue-87707.run.stderr
index e6c9ea0eb..527c78ba8 100644
--- a/src/test/ui/issues/issue-87707.run.stderr
+++ b/src/test/ui/issues/issue-87707.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:13:24
+thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:14:24
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:15:7
+thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:16:7
diff --git a/src/test/ui/issues/issue-99838.rs b/src/test/ui/issues/issue-99838.rs
index eaeeac72b..2e81d5e82 100644
--- a/src/test/ui/issues/issue-99838.rs
+++ b/src/test/ui/issues/issue-99838.rs
@@ -1,5 +1,5 @@
// run-pass
-#![feature(bench_black_box)]
+
use std::hint;
struct U16(u16);
diff --git a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr
index 9b3125058..2378476e5 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-2018.stderr
+++ b/src/test/ui/iterators/into-iter-on-arrays-2018.stderr
@@ -4,9 +4,9 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
LL | let _: Iter<'_, i32> = array.into_iter();
| ^^^^^^^^^
|
- = note: `#[warn(array_into_iter)]` on by default
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
+ = note: `#[warn(array_into_iter)]` on by default
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | let _: Iter<'_, i32> = array.iter();
diff --git a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
index e32d35d86..2fde276fa 100644
--- a/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
+++ b/src/test/ui/iterators/into-iter-on-arrays-lint.stderr
@@ -4,9 +4,9 @@ warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (du
LL | small.into_iter();
| ^^^^^^^^^
|
- = note: `#[warn(array_into_iter)]` on by default
= warning: this changes meaning in Rust 2021
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
+ = note: `#[warn(array_into_iter)]` on by default
help: use `.iter()` instead of `.into_iter()` to avoid ambiguity
|
LL | small.iter();
diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs
index 15f25f1ca..8e59c11e9 100644
--- a/src/test/ui/iterators/iter-count-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-count-overflow-debug.rs
@@ -1,7 +1,6 @@
// run-pass
// only-32bit too impatient for 2⁶⁴ items
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C debug_assertions=yes -C opt-level=3
use std::panic;
diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs
index 65124c282..7a871e744 100644
--- a/src/test/ui/iterators/iter-position-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-position-overflow-debug.rs
@@ -1,7 +1,6 @@
// run-pass
// only-32bit too impatient for 2⁶⁴ items
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C debug_assertions=yes -C opt-level=3
use std::panic;
diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs
index e16f984de..6aa349ebe 100644
--- a/src/test/ui/iterators/iter-step-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-step-overflow-debug.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C debug_assertions=yes
use std::panic;
diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs
index d8ce43848..24c764ff9 100644
--- a/src/test/ui/iterators/iter-sum-overflow-debug.rs
+++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C debug_assertions=yes
use std::panic;
diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
index bc8dcbdbb..be45c075d 100644
--- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
+++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C overflow-checks
use std::panic;
diff --git a/src/test/ui/keyword/keyword-self-as-type-param.stderr b/src/test/ui/keyword/keyword-self-as-type-param.stderr
index 419652e13..5aef94754 100644
--- a/src/test/ui/keyword/keyword-self-as-type-param.stderr
+++ b/src/test/ui/keyword/keyword-self-as-type-param.stderr
@@ -19,10 +19,8 @@ error[E0072]: recursive type `Foo` has infinite size
|
LL | struct Foo<Self>(Self);
| ^^^^^^^^^^^^^^^^ ---- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct Foo<Self>(Box<Self>);
| ++++ +
diff --git a/src/test/ui/lang-items/issue-83471.stderr b/src/test/ui/lang-items/issue-83471.stderr
index 6d796fe7f..b315df179 100644
--- a/src/test/ui/lang-items/issue-83471.stderr
+++ b/src/test/ui/lang-items/issue-83471.stderr
@@ -4,12 +4,6 @@ error[E0573]: expected type, found built-in attribute `export_name`
LL | fn call(export_name);
| ^^^^^^^^^^^ not a type
-error[E0425]: cannot find function `a` in this scope
- --> $DIR/issue-83471.rs:21:5
- |
-LL | a()
- | ^ not found in this scope
-
error[E0658]: language items are subject to change
--> $DIR/issue-83471.rs:7:1
|
@@ -32,9 +26,9 @@ warning: anonymous parameters are deprecated and will be removed in the next edi
LL | fn call(export_name);
| ^^^^^^^^^^^ help: try naming the parameter or explicitly ignoring it: `_: export_name`
|
- = note: `#[warn(anonymous_parameters)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
+ = note: `#[warn(anonymous_parameters)]` on by default
error[E0718]: `fn` language item must be applied to a trait with 1 generic argument
--> $DIR/issue-83471.rs:11:1
@@ -45,6 +39,12 @@ LL | #[lang = "fn"]
LL | trait Fn {
| - this trait has 0 generic arguments
+error[E0425]: cannot find function `a` in this scope
+ --> $DIR/issue-83471.rs:21:5
+ |
+LL | a()
+ | ^ not found in this scope
+
error: aborting due to 5 previous errors; 1 warning emitted
Some errors have detailed explanations: E0425, E0573, E0658, E0718.
diff --git a/src/test/ui/let-else/const-fn.rs b/src/test/ui/let-else/const-fn.rs
index 336b0b4b7..a3921b803 100644
--- a/src/test/ui/let-else/const-fn.rs
+++ b/src/test/ui/let-else/const-fn.rs
@@ -1,7 +1,6 @@
// run-pass
// issue #101932
-#![cfg_attr(bootstrap, feature(let_else))]
const fn foo(a: Option<i32>) -> i32 {
let Some(a) = a else {
diff --git a/src/test/ui/let-else/let-else-brace-before-else.stderr b/src/test/ui/let-else/let-else-brace-before-else.stderr
index 51051bbd4..cb01e4c18 100644
--- a/src/test/ui/let-else/let-else-brace-before-else.stderr
+++ b/src/test/ui/let-else/let-else-brace-before-else.stderr
@@ -4,7 +4,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow
LL | let Some(1) = { Some(1) } else {
| ^
|
-help: try wrapping the expression in parentheses
+help: wrap the expression in parentheses
|
LL | let Some(1) = ({ Some(1) }) else {
| + +
@@ -15,7 +15,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow
LL | let Some(1) = loop { break Some(1) } else {
| ^
|
-help: try wrapping the expression in parentheses
+help: wrap the expression in parentheses
|
LL | let Some(1) = (loop { break Some(1) }) else {
| + +
@@ -26,7 +26,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow
LL | let 2 = 1 + match 1 { n => n } else {
| ^
|
-help: try wrapping the expression in parentheses
+help: wrap the expression in parentheses
|
LL | let 2 = 1 + (match 1 { n => n }) else {
| + +
@@ -37,7 +37,7 @@ error: right curly brace `}` before `else` in a `let...else` statement not allow
LL | let Some(1) = unsafe { unsafe_fn() } else {
| ^
|
-help: try wrapping the expression in parentheses
+help: wrap the expression in parentheses
|
LL | let Some(1) = (unsafe { unsafe_fn() }) else {
| + +
diff --git a/src/test/ui/let-else/let-else-irrefutable.stderr b/src/test/ui/let-else/let-else-irrefutable.stderr
index e030c50d4..e0581f4d9 100644
--- a/src/test/ui/let-else/let-else-irrefutable.stderr
+++ b/src/test/ui/let-else/let-else-irrefutable.stderr
@@ -4,9 +4,9 @@ warning: irrefutable `let...else` pattern
LL | let x = 1 else { return };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(irrefutable_let_patterns)]` on by default
= note: this pattern will always match, so the `else` clause is useless
= help: consider removing the `else` clause
+ = note: `#[warn(irrefutable_let_patterns)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/let-else/let-else-non-diverging.rs b/src/test/ui/let-else/let-else-non-diverging.rs
index b5bd91ceb..a5442dd82 100644
--- a/src/test/ui/let-else/let-else-non-diverging.rs
+++ b/src/test/ui/let-else/let-else-non-diverging.rs
@@ -8,4 +8,15 @@ fn main() {
}
};
let Some(x) = Some(1) else { Some(2) }; //~ ERROR does not diverge
+
+ // Ensure that uninhabited types do not "diverge".
+ // This might be relaxed in the future, but when it is,
+ // it should be an explicitly wanted decision.
+ let Some(x) = Some(1) else { foo::<Uninhabited>() }; //~ ERROR does not diverge
+}
+
+enum Uninhabited {}
+
+fn foo<T>() -> T {
+ panic!()
}
diff --git a/src/test/ui/let-else/let-else-non-diverging.stderr b/src/test/ui/let-else/let-else-non-diverging.stderr
index c999a5495..78551fcc4 100644
--- a/src/test/ui/let-else/let-else-non-diverging.stderr
+++ b/src/test/ui/let-else/let-else-non-diverging.stderr
@@ -39,6 +39,17 @@ LL | let Some(x) = Some(1) else { Some(2) };
= help: try adding a diverging expression, such as `return` or `panic!(..)`
= help: ...or use `match` instead of `let...else`
-error: aborting due to 3 previous errors
+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`
+ |
+ = note: expected type `!`
+ found enum `Uninhabited`
+ = help: try adding a diverging expression, such as `return` or `panic!(..)`
+ = help: ...or use `match` instead of `let...else`
+
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/let-else/let-else-then-diverge.rs b/src/test/ui/let-else/let-else-then-diverge.rs
index 1c8f7d758..1a75310c9 100644
--- a/src/test/ui/let-else/let-else-then-diverge.rs
+++ b/src/test/ui/let-else/let-else-then-diverge.rs
@@ -1,8 +1,6 @@
-//
-// popped up in in #94012, where an alternative desugaring was
+// popped up in #94012, where an alternative desugaring was
// causing unreachable code errors
-
#![deny(unused_variables)]
#![deny(unreachable_code)]
diff --git a/src/test/ui/let-else/let-else-then-diverge.stderr b/src/test/ui/let-else/let-else-then-diverge.stderr
index ceb61029d..470a11d47 100644
--- a/src/test/ui/let-else/let-else-then-diverge.stderr
+++ b/src/test/ui/let-else/let-else-then-diverge.stderr
@@ -1,11 +1,11 @@
error: unused variable: `x`
- --> $DIR/let-else-then-diverge.rs:11:13
+ --> $DIR/let-else-then-diverge.rs:9:13
|
LL | let x = 5;
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
note: the lint level is defined here
- --> $DIR/let-else-then-diverge.rs:6:9
+ --> $DIR/let-else-then-diverge.rs:4:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lexer/lex-emoji-identifiers.rs b/src/test/ui/lexer/lex-emoji-identifiers.rs
new file mode 100644
index 000000000..91b5929c0
--- /dev/null
+++ b/src/test/ui/lexer/lex-emoji-identifiers.rs
@@ -0,0 +1,17 @@
+fn invalid_emoji_usages() {
+ let arrow↔️ = "basic emoji"; //~ ERROR: identifiers cannot contain emoji
+ // FIXME
+ let planet🪐 = "basic emoji"; //~ ERROR: unknown start of token
+ // FIXME
+ let wireless🛜 = "basic emoji"; //~ ERROR: unknown start of token
+ // FIXME
+ let key1️⃣ = "keycap sequence"; //~ ERROR: unknown start of token
+ //~^ WARN: identifier contains uncommon Unicode codepoints
+ let flag🇺🇳 = "flag sequence"; //~ ERROR: identifiers cannot contain emoji
+ let wales🏴 = "tag sequence"; //~ ERROR: identifiers cannot contain emoji
+ let folded🙏🏿 = "modifier sequence"; //~ ERROR: identifiers cannot contain emoji
+}
+
+fn main() {
+ invalid_emoji_usages();
+}
diff --git a/src/test/ui/lexer/lex-emoji-identifiers.stderr b/src/test/ui/lexer/lex-emoji-identifiers.stderr
new file mode 100644
index 000000000..6237c5d02
--- /dev/null
+++ b/src/test/ui/lexer/lex-emoji-identifiers.stderr
@@ -0,0 +1,52 @@
+error: unknown start of token: \u{1fa90}
+ --> $DIR/lex-emoji-identifiers.rs:4:15
+ |
+LL | let planet🪐 = "basic emoji";
+ | ^^
+
+error: unknown start of token: \u{1f6dc}
+ --> $DIR/lex-emoji-identifiers.rs:6:17
+ |
+LL | let wireless🛜 = "basic emoji";
+ | ^^
+
+error: unknown start of token: \u{20e3}
+ --> $DIR/lex-emoji-identifiers.rs:8:14
+ |
+LL | let key1️⃣ = "keycap sequence";
+ | ^
+
+error: identifiers cannot contain emoji: `arrow↔️`
+ --> $DIR/lex-emoji-identifiers.rs:2:9
+ |
+LL | let arrow↔️ = "basic emoji";
+ | ^^^^^^
+
+error: identifiers cannot contain emoji: `flag🇺🇳`
+ --> $DIR/lex-emoji-identifiers.rs:10:9
+ |
+LL | let flag🇺🇳 = "flag sequence";
+ | ^^^^^^
+
+error: identifiers cannot contain emoji: `wales🏴`
+ --> $DIR/lex-emoji-identifiers.rs:11:9
+ |
+LL | let wales🏴 = "tag sequence";
+ | ^^^^^^^
+
+error: identifiers cannot contain emoji: `folded🙏🏿`
+ --> $DIR/lex-emoji-identifiers.rs:12:9
+ |
+LL | let folded🙏🏿 = "modifier sequence";
+ | ^^^^^^^^^^
+
+warning: identifier contains uncommon Unicode codepoints
+ --> $DIR/lex-emoji-identifiers.rs:8:9
+ |
+LL | let key1️⃣ = "keycap sequence";
+ | ^^^^
+ |
+ = note: `#[warn(uncommon_codepoints)]` on by default
+
+error: aborting due to 7 previous errors; 1 warning emitted
+
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index 08e4be2c0..535985452 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -1,6 +1,8 @@
error[E0574]: expected struct, variant or union type, found type parameter `T`
--> $DIR/lexical-scopes.rs:3:13
|
+LL | struct T { i: i32 }
+ | ------------------- you might have meant to refer to this struct
LL | fn f<T>() {
| - found this type parameter
LL | let t = T { i: 0 };
diff --git a/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs b/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs
new file mode 100644
index 000000000..c1425fa42
--- /dev/null
+++ b/src/test/ui/lifetimes/elided-lifetime-in-param-pat.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+struct S<T> {
+ _t: T,
+}
+
+fn f(S::<&i8> { .. }: S<&i8>) {}
+
+fn main() {
+ f(S { _t: &42_i8 });
+}
diff --git a/src/test/ui/lifetimes/issue-79187-2.stderr b/src/test/ui/lifetimes/issue-79187-2.stderr
index 9322e6171..c5f654b37 100644
--- a/src/test/ui/lifetimes/issue-79187-2.stderr
+++ b/src/test/ui/lifetimes/issue-79187-2.stderr
@@ -31,7 +31,7 @@ error[E0308]: mismatched types
LL | take_foo(|a| a);
| ^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r> Fn<(&'r i32,)>`
+ = note: expected trait `for<'a> Fn<(&'a i32,)>`
found trait `Fn<(&i32,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187-2.rs:8:14
diff --git a/src/test/ui/lifetimes/issue-79187.stderr b/src/test/ui/lifetimes/issue-79187.stderr
index 3e75e7fed..ee6e7b89d 100644
--- a/src/test/ui/lifetimes/issue-79187.stderr
+++ b/src/test/ui/lifetimes/issue-79187.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | thing(f);
| ^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r> FnOnce<(&'r u32,)>`
+ = note: expected trait `for<'a> FnOnce<(&'a u32,)>`
found trait `FnOnce<(&u32,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-79187.rs:4:13
diff --git a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
index d82b2684c..7049f28e2 100644
--- a/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
+++ b/src/test/ui/lifetimes/lifetime-errors/issue_74400.stderr
@@ -15,7 +15,7 @@ error[E0308]: mismatched types
LL | f(data, identity)
| ^^^^^^^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r> Fn<(&'r T,)>`
+ = note: expected trait `for<'a> Fn<(&'a T,)>`
found trait `Fn<(&T,)>`
note: the lifetime requirement is introduced here
--> $DIR/issue_74400.rs:8:34
diff --git a/src/test/ui/lifetimes/nested-binder-print.rs b/src/test/ui/lifetimes/nested-binder-print.rs
new file mode 100644
index 000000000..f97f349fd
--- /dev/null
+++ b/src/test/ui/lifetimes/nested-binder-print.rs
@@ -0,0 +1,10 @@
+struct TwoLt<'a, 'b>(&'a (), &'b ());
+type Foo<'a> = fn(TwoLt<'_, 'a>);
+
+fn foo() {
+ let y: for<'a> fn(Foo<'a>);
+ let x: u32 = y;
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/nested-binder-print.stderr b/src/test/ui/lifetimes/nested-binder-print.stderr
new file mode 100644
index 000000000..32dd89693
--- /dev/null
+++ b/src/test/ui/lifetimes/nested-binder-print.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/nested-binder-print.rs:6:18
+ |
+LL | let x: u32 = y;
+ | --- ^ expected `u32`, found fn pointer
+ | |
+ | expected due to this
+ |
+ = note: expected type `u32`
+ found fn pointer `for<'a> fn(for<'b> fn(TwoLt<'b, 'a>))`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr
index 72bb0782f..c35d8ecec 100644
--- a/src/test/ui/lifetimes/re-empty-in-error.stderr
+++ b/src/test/ui/lifetimes/re-empty-in-error.stderr
@@ -4,7 +4,7 @@ error: higher-ranked lifetime error
LL | foo(&10);
| ^^^^^^^^
|
- = note: could not prove `for<'b, 'r> &'b (): 'r`
+ = note: could not prove `for<'b> &'b (): 'a`
error: aborting due to previous error
diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
index a8b0996d8..31fd8a4d6 100644
--- a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
+++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr
@@ -21,3 +21,4 @@ LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() {
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0311`.
diff --git a/src/test/ui/lifetimes/unusual-rib-combinations.rs b/src/test/ui/lifetimes/unusual-rib-combinations.rs
new file mode 100644
index 000000000..b4c86aab8
--- /dev/null
+++ b/src/test/ui/lifetimes/unusual-rib-combinations.rs
@@ -0,0 +1,28 @@
+#![feature(inline_const)]
+
+struct S<'a>(&'a u8);
+fn foo() {}
+
+// Paren generic args in AnonConst
+fn a() -> [u8; foo::()] {
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+//~| ERROR mismatched types
+ panic!()
+}
+
+// Paren generic args in ConstGeneric
+fn b<const C: u8()>() {}
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+
+// Paren generic args in AnonymousReportError
+fn c<T = u8()>() {}
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+//~| ERROR defaults for type parameters are only allowed in
+//~| WARN this was previously accepted
+
+// 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
+
+fn main() {}
diff --git a/src/test/ui/lifetimes/unusual-rib-combinations.stderr b/src/test/ui/lifetimes/unusual-rib-combinations.stderr
new file mode 100644
index 000000000..6d7b42506
--- /dev/null
+++ b/src/test/ui/lifetimes/unusual-rib-combinations.stderr
@@ -0,0 +1,61 @@
+error[E0106]: missing lifetime specifier
+ --> $DIR/unusual-rib-combinations.rs:24:15
+ |
+LL | fn d<const C: S>() {}
+ | ^ expected named lifetime parameter
+ |
+help: consider introducing a named lifetime parameter
+ |
+LL | fn d<'a, const C: S<'a>>() {}
+ | +++ ++++
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/unusual-rib-combinations.rs:7:16
+ |
+LL | fn a() -> [u8; foo::()] {
+ | ^^^^^^^ only `Fn` traits may use parentheses
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/unusual-rib-combinations.rs:14:15
+ |
+LL | fn b<const C: u8()>() {}
+ | ^^^^ only `Fn` traits may use parentheses
+
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/unusual-rib-combinations.rs:18:10
+ |
+LL | fn c<T = u8()>() {}
+ | ^^^^ only `Fn` traits may use parentheses
+
+error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+ --> $DIR/unusual-rib-combinations.rs:18:6
+ |
+LL | fn c<T = 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 #36887 <https://github.com/rust-lang/rust/issues/36887>
+ = note: `#[deny(invalid_type_param_default)]` on by default
+
+error[E0308]: mismatched types
+ --> $DIR/unusual-rib-combinations.rs:7:16
+ |
+LL | fn a() -> [u8; foo::()] {
+ | ^^^^^^^ expected `usize`, found fn item
+ |
+ = note: expected type `usize`
+ found fn item `fn() {foo}`
+
+error: `S<'static>` is forbidden as the type of a const generic parameter
+ --> $DIR/unusual-rib-combinations.rs:24:15
+ |
+LL | fn d<const C: S>() {}
+ | ^
+ |
+ = 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 7 previous errors
+
+Some errors have detailed explanations: E0106, E0214, E0308.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/src/test/ui/limits/issue-55878.stderr b/src/test/ui/limits/issue-55878.stderr
index 6c3683d78..ee6aab748 100644
--- a/src/test/ui/limits/issue-55878.stderr
+++ b/src/test/ui/limits/issue-55878.stderr
@@ -9,29 +9,14 @@ LL | intrinsics::size_of::<T>()
LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
| ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26
-error: erroneous constant used
+error[E0080]: erroneous constant used
--> $DIR/issue-55878.rs:7:26
|
LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
= note: this error originates in the macro `$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 2 previous errors
For more information about this error, try `rustc --explain E0080`.
-Future incompatibility report: Future breakage diagnostic:
-error: erroneous constant used
- --> $DIR/issue-55878.rs:7:26
- |
-LL | println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
- |
- = note: `#[deny(const_err)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
- = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
-
diff --git a/src/test/ui/linkage-attr/link-attr-validation-early.stderr b/src/test/ui/linkage-attr/link-attr-validation-early.stderr
index 903141e43..24ad9d825 100644
--- a/src/test/ui/linkage-attr/link-attr-validation-early.stderr
+++ b/src/test/ui/linkage-attr/link-attr-validation-early.stderr
@@ -4,9 +4,9 @@ error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib
LL | #[link]
| ^^^^^^^
|
- = note: `#[deny(ill_formed_attribute_input)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+ = note: `#[deny(ill_formed_attribute_input)]` on by default
error: attribute must be of the form `#[link(name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated")]`
--> $DIR/link-attr-validation-early.rs:4:1
diff --git a/src/test/ui/lint/auxiliary/trivial-cast-ice.rs b/src/test/ui/lint/auxiliary/trivial-cast-ice.rs
new file mode 100644
index 000000000..ab2332d06
--- /dev/null
+++ b/src/test/ui/lint/auxiliary/trivial-cast-ice.rs
@@ -0,0 +1,7 @@
+#[macro_export]
+macro_rules! foo {
+ () => {
+ let x: &Option<i32> = &Some(1);
+ let _y = x as *const Option<i32>;
+ }
+}
diff --git a/src/test/ui/lint/bare-trait-objects-path.stderr b/src/test/ui/lint/bare-trait-objects-path.stderr
index 4b8c2b539..8ed303ca6 100644
--- a/src/test/ui/lint/bare-trait-objects-path.stderr
+++ b/src/test/ui/lint/bare-trait-objects-path.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | let _: Dyn::Ty;
| ^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | let _: <dyn Dyn>::Ty;
diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr
index 4607f6849..217eed6c9 100644
--- a/src/test/ui/lint/clashing-extern-fn.stderr
+++ b/src/test/ui/lint/clashing-extern-fn.stderr
@@ -7,13 +7,13 @@ LL | fn clash(x: u8);
LL | fn clash(x: u64);
| ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
+ = note: expected `unsafe extern "C" fn(u8)`
+ found `unsafe extern "C" fn(u64)`
note: the lint level is defined here
--> $DIR/clashing-extern-fn.rs:4:9
|
LL | #![warn(clashing_extern_declarations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn(u8)`
- found `unsafe extern "C" fn(u64)`
warning: `extern_link_name` redeclared with a different signature
--> $DIR/clashing-extern-fn.rs:52:9
@@ -219,9 +219,9 @@ warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI
LL | fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
- = note: `#[warn(improper_ctypes)]` on by default
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
+ = note: `#[warn(improper_ctypes)]` on by default
warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
--> $DIR/clashing-extern-fn.rs:412:46
diff --git a/src/test/ui/lint/cli-lint-override.forbid_warn.stderr b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr
index ff4dc4abc..d1c66a81c 100644
--- a/src/test/ui/lint/cli-lint-override.forbid_warn.stderr
+++ b/src/test/ui/lint/cli-lint-override.forbid_warn.stderr
@@ -4,8 +4,8 @@ error: extern declarations without an explicit ABI are deprecated
LL | extern fn foo() {}
| ^^^^^^^^^^^^^^^ ABI should be specified here
|
- = note: requested on the command line with `-F missing-abi`
= help: the default ABI is C
+ = note: requested on the command line with `-F missing-abi`
error: aborting due to previous error
diff --git a/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr
index 74e7823e1..779c24c93 100644
--- a/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr
+++ b/src/test/ui/lint/cli-lint-override.force_warn_deny.stderr
@@ -4,8 +4,8 @@ warning: extern declarations without an explicit ABI are deprecated
LL | extern fn foo() {}
| ^^^^^^^^^^^^^^^ ABI should be specified here
|
- = note: requested on the command line with `--force-warn missing-abi`
= help: the default ABI is C
+ = note: requested on the command line with `--force-warn missing-abi`
warning: 1 warning emitted
diff --git a/src/test/ui/lint/cli-lint-override.warn_deny.stderr b/src/test/ui/lint/cli-lint-override.warn_deny.stderr
index 2d869adfd..f034cfa93 100644
--- a/src/test/ui/lint/cli-lint-override.warn_deny.stderr
+++ b/src/test/ui/lint/cli-lint-override.warn_deny.stderr
@@ -4,8 +4,8 @@ error: extern declarations without an explicit ABI are deprecated
LL | extern fn foo() {}
| ^^^^^^^^^^^^^^^ ABI should be specified here
|
- = note: requested on the command line with `-D missing-abi`
= help: the default ABI is C
+ = note: requested on the command line with `-D missing-abi`
error: aborting due to previous error
diff --git a/src/test/ui/lint/dead-code/issue-85071-2.stderr b/src/test/ui/lint/dead-code/issue-85071-2.stderr
index 86fbd1d75..5e963183d 100644
--- a/src/test/ui/lint/dead-code/issue-85071-2.stderr
+++ b/src/test/ui/lint/dead-code/issue-85071-2.stderr
@@ -7,16 +7,16 @@ LL |
LL | let _y = x;
| ^^ unreachable definition
|
-note: the lint level is defined here
- --> $DIR/issue-85071-2.rs:7:26
- |
-LL | #![warn(unused_variables,unreachable_code)]
- | ^^^^^^^^^^^^^^^^
note: this expression has type `Foo`, which is uninhabited
--> $DIR/issue-85071-2.rs:18:13
|
LL | let x = s.f();
| ^^^^^
+note: the lint level is defined here
+ --> $DIR/issue-85071-2.rs:7:26
+ |
+LL | #![warn(unused_variables,unreachable_code)]
+ | ^^^^^^^^^^^^^^^^
warning: unused variable: `x`
--> $DIR/issue-85071-2.rs:18:9
diff --git a/src/test/ui/lint/dead-code/issue-85071.stderr b/src/test/ui/lint/dead-code/issue-85071.stderr
index 49555fdaa..721fb8148 100644
--- a/src/test/ui/lint/dead-code/issue-85071.stderr
+++ b/src/test/ui/lint/dead-code/issue-85071.stderr
@@ -7,16 +7,16 @@ LL |
LL | let _ = x;
| ^ unreachable expression
|
-note: the lint level is defined here
- --> $DIR/issue-85071.rs:9:26
- |
-LL | #![warn(unused_variables,unreachable_code)]
- | ^^^^^^^^^^^^^^^^
note: this expression has type `Foo`, which is uninhabited
--> $DIR/issue-85071.rs:15:13
|
LL | let x = f();
| ^^^
+note: the lint level is defined here
+ --> $DIR/issue-85071.rs:9:26
+ |
+LL | #![warn(unused_variables,unreachable_code)]
+ | ^^^^^^^^^^^^^^^^
warning: unused variable: `x`
--> $DIR/issue-85071.rs:15:9
diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr
index a68f64775..6029bf268 100644
--- a/src/test/ui/lint/dead-code/unused-variant.stderr
+++ b/src/test/ui/lint/dead-code/unused-variant.stderr
@@ -6,12 +6,12 @@ LL | enum Enum {
LL | Variant1,
| ^^^^^^^^
|
+ = note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
note: the lint level is defined here
--> $DIR/unused-variant.rs:1:9
|
LL | #![deny(dead_code)]
| ^^^^^^^^^
- = note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis
error: aborting due to previous error
diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr
index 127dd4127..beb0ad795 100644
--- a/src/test/ui/lint/deny-overflowing-literals.stderr
+++ b/src/test/ui/lint/deny-overflowing-literals.stderr
@@ -4,8 +4,8 @@ error: literal out of range for `u8`
LL | let x: u8 = 256;
| ^^^
|
- = note: `#[deny(overflowing_literals)]` on by default
= note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
+ = note: `#[deny(overflowing_literals)]` on by default
error: range endpoint is out of range for `u8`
--> $DIR/deny-overflowing-literals.rs:5:14
diff --git a/src/test/ui/lint/expansion-time.stderr b/src/test/ui/lint/expansion-time.stderr
index b0fc1f8e5..064ee5fad 100644
--- a/src/test/ui/lint/expansion-time.stderr
+++ b/src/test/ui/lint/expansion-time.stderr
@@ -18,13 +18,13 @@ warning: missing fragment specifier
LL | macro_rules! m { ($i) => {} }
| ^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
note: the lint level is defined here
--> $DIR/expansion-time.rs:8:8
|
LL | #[warn(missing_fragment_specifier)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
warning: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable
--> $DIR/expansion-time.rs:14:7
@@ -32,13 +32,13 @@ warning: use of unstable library feature 'test': `bench` is a part of custom tes
LL | #[bench]
| ^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
note: the lint level is defined here
--> $DIR/expansion-time.rs:12:8
|
LL | #[warn(soft_unstable)]
| ^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
warning: include macro expected single expression in source
--> $DIR/expansion-time-include.rs:4:1
diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr
index 61b7993d2..2805720f0 100644
--- a/src/test/ui/lint/fn_must_use.stderr
+++ b/src/test/ui/lint/fn_must_use.stderr
@@ -4,12 +4,12 @@ warning: unused return value of `need_to_use_this_value` that must be used
LL | need_to_use_this_value();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: it's important
note: the lint level is defined here
--> $DIR/fn_must_use.rs:3:9
|
LL | #![warn(unused_must_use)]
| ^^^^^^^^^^^^^^^
- = note: it's important
warning: unused return value of `MyStruct::need_to_use_this_method_value` that must be used
--> $DIR/fn_must_use.rs:60:5
diff --git a/src/test/ui/lint/for_loop_over_fallibles.rs b/src/test/ui/lint/for_loop_over_fallibles.rs
new file mode 100644
index 000000000..43d71c2e8
--- /dev/null
+++ b/src/test/ui/lint/for_loop_over_fallibles.rs
@@ -0,0 +1,43 @@
+// check-pass
+
+fn main() {
+ // Common
+ for _ in Some(1) {}
+ //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement
+ //~| HELP to check pattern in a loop use `while let`
+ //~| HELP consider using `if let` to clear intent
+ for _ in Ok::<_, ()>(1) {}
+ //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement
+ //~| HELP to check pattern in a loop use `while let`
+ //~| HELP consider using `if let` to clear intent
+
+ // `Iterator::next` specific
+ for _ in [0; 0].iter().next() {}
+ //~^ WARN for loop over an `Option`. This is more readably written as an `if let` statement
+ //~| HELP to iterate over `[0; 0].iter()` remove the call to `next`
+ //~| HELP consider using `if let` to clear intent
+
+ // `Result<impl Iterator, _>`, but function doesn't return `Result`
+ for _ in Ok::<_, ()>([0; 0].iter()) {}
+ //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement
+ //~| HELP to check pattern in a loop use `while let`
+ //~| HELP consider using `if let` to clear intent
+}
+
+fn _returns_result() -> Result<(), ()> {
+ // `Result<impl Iterator, _>`
+ for _ in Ok::<_, ()>([0; 0].iter()) {}
+ //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement
+ //~| HELP to check pattern in a loop use `while let`
+ //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents
+ //~| HELP consider using `if let` to clear intent
+
+ // `Result<impl IntoIterator>`
+ for _ in Ok::<_, ()>([0; 0]) {}
+ //~^ WARN for loop over a `Result`. This is more readably written as an `if let` statement
+ //~| HELP to check pattern in a loop use `while let`
+ //~| HELP consider unwrapping the `Result` with `?` to iterate over its contents
+ //~| HELP consider using `if let` to clear intent
+
+ Ok(())
+}
diff --git a/src/test/ui/lint/for_loop_over_fallibles.stderr b/src/test/ui/lint/for_loop_over_fallibles.stderr
new file mode 100644
index 000000000..96efdf85c
--- /dev/null
+++ b/src/test/ui/lint/for_loop_over_fallibles.stderr
@@ -0,0 +1,101 @@
+warning: for loop over an `Option`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:5:14
+ |
+LL | for _ in Some(1) {}
+ | ^^^^^^^
+ |
+ = note: `#[warn(for_loops_over_fallibles)]` on by default
+help: to check pattern in a loop use `while let`
+ |
+LL | while let Some(_) = Some(1) {}
+ | ~~~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+LL | if let Some(_) = Some(1) {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `Result`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:9:14
+ |
+LL | for _ in Ok::<_, ()>(1) {}
+ | ^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+LL | while let Ok(_) = Ok::<_, ()>(1) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+LL | if let Ok(_) = Ok::<_, ()>(1) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: for loop over an `Option`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:15:14
+ |
+LL | for _ in [0; 0].iter().next() {}
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+help: to iterate over `[0; 0].iter()` remove the call to `next`
+ |
+LL | for _ in [0; 0].iter().by_ref() {}
+ | ~~~~~~~~~
+help: consider using `if let` to clear intent
+ |
+LL | if let Some(_) = [0; 0].iter().next() {}
+ | ~~~~~~~~~~~~ ~~~
+
+warning: for loop over a `Result`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:21:14
+ |
+LL | for _ in Ok::<_, ()>([0; 0].iter()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider using `if let` to clear intent
+ |
+LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: for loop over a `Result`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:29:14
+ |
+LL | for _ in Ok::<_, ()>([0; 0].iter()) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+LL | while let Ok(_) = Ok::<_, ()>([0; 0].iter()) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider unwrapping the `Result` with `?` to iterate over its contents
+ |
+LL | for _ in Ok::<_, ()>([0; 0].iter())? {}
+ | +
+help: consider using `if let` to clear intent
+ |
+LL | if let Ok(_) = Ok::<_, ()>([0; 0].iter()) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: for loop over a `Result`. This is more readably written as an `if let` statement
+ --> $DIR/for_loop_over_fallibles.rs:36:14
+ |
+LL | for _ in Ok::<_, ()>([0; 0]) {}
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: to check pattern in a loop use `while let`
+ |
+LL | while let Ok(_) = Ok::<_, ()>([0; 0]) {}
+ | ~~~~~~~~~~~~~ ~~~
+help: consider unwrapping the `Result` with `?` to iterate over its contents
+ |
+LL | for _ in Ok::<_, ()>([0; 0])? {}
+ | +
+help: consider using `if let` to clear intent
+ |
+LL | if let Ok(_) = Ok::<_, ()>([0; 0]) {}
+ | ~~~~~~~~~~ ~~~
+
+warning: 6 warnings emitted
+
diff --git a/src/test/ui/lint/forbid-group-group-2.stderr b/src/test/ui/lint/forbid-group-group-2.stderr
index 214e949c1..b2e2bcea1 100644
--- a/src/test/ui/lint/forbid-group-group-2.stderr
+++ b/src/test/ui/lint/forbid-group-group-2.stderr
@@ -7,13 +7,13 @@ LL | #![forbid(warnings)]
LL | #[allow(nonstandard_style)]
| ^^^^^^^^^^^^^^^^^ overruled by previous forbid
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
note: the lint level is defined here
--> $DIR/forbid-group-group-2.rs:5:9
|
LL | #![deny(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
error: allow(nonstandard_style) incompatible with previous forbid
--> $DIR/forbid-group-group-2.rs:7:9
diff --git a/src/test/ui/lint/forbid-group-member.stderr b/src/test/ui/lint/forbid-group-member.stderr
index 891fa9885..47336d4d8 100644
--- a/src/test/ui/lint/forbid-group-member.stderr
+++ b/src/test/ui/lint/forbid-group-member.stderr
@@ -7,9 +7,9 @@ LL |
LL | #[allow(unused_variables)]
| ^^^^^^^^^^^^^^^^ overruled by previous forbid
|
- = note: `#[warn(forbidden_lint_groups)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+ = note: `#[warn(forbidden_lint_groups)]` on by default
warning: allow(unused_variables) incompatible with previous forbid
--> $DIR/forbid-group-member.rs:8:9
diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
index 3a3d81176..257df13ef 100644
--- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.rs
@@ -1,10 +1,10 @@
// --force-warn $LINT causes $LINT (which is deny-by-default) to warn
// despite $LINT being allowed on command line
-// compile-flags: -A const_err --force-warn const_err
+// compile-flags: -A mutable_transmutes --force-warn mutable_transmutes
// check-pass
-const C: i32 = 1 / 0;
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler
-
-fn main() {}
+fn main() {
+ unsafe {
+ let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior
+ }
+}
diff --git a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
index 915b3b86f..6a1fc76e1 100644
--- a/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/allowed-cli-deny-by-default-lint.stderr
@@ -1,23 +1,10 @@
-warning: any use of this value will cause an error
- --> $DIR/allowed-cli-deny-by-default-lint.rs:6:16
+warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+ --> $DIR/allowed-cli-deny-by-default-lint.rs:8:17
|
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
+LL | let y = std::mem::transmute::<&i32, &mut i32>(&5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: requested on the command line with `--force-warn mutable-transmutes`
warning: 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/allowed-cli-deny-by-default-lint.rs:6:16
- |
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
- |
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
index 08e75a775..0d4b468c2 100644
--- a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.rs
@@ -1,11 +1,11 @@
// --force-warn $LINT causes $LINT (which is deny-by-default) to warn
// despite $LINT being allowed in module
-// compile-flags: --force-warn const_err
+// compile-flags: --force-warn mutable_transmutes
// check-pass
-#![allow(const_err)]
-const C: i32 = 1 / 0;
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler
-
-fn main() {}
+#![allow(mutable_transmutes)]
+fn main() {
+ unsafe {
+ let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior
+ }
+}
diff --git a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
index 3b36d1d02..9ef53d47e 100644
--- a/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/allowed-deny-by-default-lint.stderr
@@ -1,23 +1,10 @@
-warning: any use of this value will cause an error
- --> $DIR/allowed-deny-by-default-lint.rs:7:16
+warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+ --> $DIR/allowed-deny-by-default-lint.rs:9:17
|
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
+LL | let y = std::mem::transmute::<&i32, &mut i32>(&5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: requested on the command line with `--force-warn mutable-transmutes`
warning: 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/allowed-deny-by-default-lint.rs:7:16
- |
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
- |
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr b/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
index 94d81c3aa..0f58953a5 100644
--- a/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/allowed-group-warn-by-default-lint.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | pub fn function(_x: Box<SomeTrait>) {}
| ^^^^^^^^^
|
- = note: requested on the command line with `--force-warn bare-trait-objects`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: requested on the command line with `--force-warn bare-trait-objects`
help: use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/src/test/ui/lint/force-warn/cap-lints-allow.stderr b/src/test/ui/lint/force-warn/cap-lints-allow.stderr
index 7f0fd8530..03a32fa6f 100644
--- a/src/test/ui/lint/force-warn/cap-lints-allow.stderr
+++ b/src/test/ui/lint/force-warn/cap-lints-allow.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | pub fn function(_x: Box<SomeTrait>) {}
| ^^^^^^^^^
|
- = note: requested on the command line with `--force-warn bare-trait-objects`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: requested on the command line with `--force-warn bare-trait-objects`
help: use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr b/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
index 3dafaf705..d1b764b34 100644
--- a/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/cap-lints-warn-allowed-warn-by-default-lint.stderr
@@ -4,9 +4,9 @@ warning: `...` range patterns are deprecated
LL | 0...100 => true,
| ^^^ help: use `..=` for an inclusive range
|
- = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `--force-warn ellipsis-inclusive-range-patterns` implied by `--force-warn rust-2021-compatibility`
warning: 1 warning emitted
diff --git a/src/test/ui/lint/force-warn/deny-by-default-lint.rs b/src/test/ui/lint/force-warn/deny-by-default-lint.rs
index e37102903..c2e9377e9 100644
--- a/src/test/ui/lint/force-warn/deny-by-default-lint.rs
+++ b/src/test/ui/lint/force-warn/deny-by-default-lint.rs
@@ -1,9 +1,9 @@
// --force-warn $LINT causes $LINT (which is deny-by-default) to warn
-// compile-flags: --force-warn const_err
+// compile-flags: --force-warn mutable_transmutes
// check-pass
-const C: i32 = 1 / 0;
-//~^ WARN any use of this value will cause an error
-//~| WARN this was previously accepted by the compiler
-
-fn main() {}
+fn main() {
+ unsafe {
+ let y = std::mem::transmute::<&i32, &mut i32>(&5); //~WARN: undefined behavior
+ }
+}
diff --git a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
index a2e5baa8b..c644d0fe7 100644
--- a/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/deny-by-default-lint.stderr
@@ -1,23 +1,10 @@
-warning: any use of this value will cause an error
- --> $DIR/deny-by-default-lint.rs:5:16
+warning: transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell
+ --> $DIR/deny-by-default-lint.rs:7:17
|
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
+LL | let y = std::mem::transmute::<&i32, &mut i32>(&5);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
+ = note: requested on the command line with `--force-warn mutable-transmutes`
warning: 1 warning emitted
-Future incompatibility report: Future breakage diagnostic:
-warning: any use of this value will cause an error
- --> $DIR/deny-by-default-lint.rs:5:16
- |
-LL | const C: i32 = 1 / 0;
- | ------------ ^^^^^ attempt to divide `1_i32` by zero
- |
- = note: requested on the command line with `--force-warn const-err`
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #71800 <https://github.com/rust-lang/rust/issues/71800>
-
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
index eb2bca7b8..e17630fd3 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-cli-warn-by-default-lint.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | pub fn function(_x: Box<SomeTrait>) {}
| ^^^^^^^^^
|
- = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
help: use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.stderr b/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
index ed01937a5..72198541a 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-lint-group.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | pub fn function(_x: Box<SomeTrait>) {}
| ^^^^^^^^^
|
- = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
help: use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr b/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
index 8db7c1275..52c870ac2 100644
--- a/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
+++ b/src/test/ui/lint/force-warn/lint-group-allowed-warn-by-default-lint.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | pub fn function(_x: Box<SomeTrait>) {}
| ^^^^^^^^^
|
- = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `--force-warn bare-trait-objects` implied by `--force-warn rust-2018-idioms`
help: use `dyn`
|
LL | pub fn function(_x: Box<dyn SomeTrait>) {}
diff --git a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
index 91b8d2b5a..ed9fa0d41 100644
--- a/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
+++ b/src/test/ui/lint/inclusive-range-pattern-syntax.stderr
@@ -4,13 +4,13 @@ warning: `...` range patterns are deprecated
LL | 1...2 => {}
| ^^^ help: use `..=` for an inclusive range
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/inclusive-range-pattern-syntax.rs:4:9
|
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
warning: `...` range patterns are deprecated
--> $DIR/inclusive-range-pattern-syntax.rs:16:9
diff --git a/src/test/ui/lint/inert-attr-macro.stderr b/src/test/ui/lint/inert-attr-macro.stderr
index 3b3aa5d0b..5ccb4ffe7 100644
--- a/src/test/ui/lint/inert-attr-macro.stderr
+++ b/src/test/ui/lint/inert-attr-macro.stderr
@@ -4,17 +4,17 @@ warning: unused attribute `inline`
LL | #[inline] foo!();
| ^^^^^^^^^
|
+note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
+ --> $DIR/inert-attr-macro.rs:10:15
+ |
+LL | #[inline] foo!();
+ | ^^^
note: the lint level is defined here
--> $DIR/inert-attr-macro.rs:3:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
-note: the built-in attribute `inline` will be ignored, since it's applied to the macro invocation `foo`
- --> $DIR/inert-attr-macro.rs:10:15
- |
-LL | #[inline] foo!();
- | ^^^
warning: unused attribute `allow`
--> $DIR/inert-attr-macro.rs:14:5
diff --git a/src/test/ui/lint/inline-trait-and-foreign-items.stderr b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
index fc7e89e4f..2f1fb4c46 100644
--- a/src/test/ui/lint/inline-trait-and-foreign-items.stderr
+++ b/src/test/ui/lint/inline-trait-and-foreign-items.stderr
@@ -4,13 +4,13 @@ warning: `#[inline]` is ignored on constants
LL | #[inline]
| ^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information
note: the lint level is defined here
--> $DIR/inline-trait-and-foreign-items.rs:4:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: see issue #65833 <https://github.com/rust-lang/rust/issues/65833> for more information
error[E0518]: attribute should be applied to function or closure
--> $DIR/inline-trait-and-foreign-items.rs:11:5
@@ -67,7 +67,7 @@ error: unconstrained opaque type
LL | type U = impl Trait;
| ^^^^^^^^^^
|
- = note: `U` must be used in combination with a concrete type within the same module
+ = note: `U` must be used in combination with a concrete type within the same impl
error: aborting due to 6 previous errors; 2 warnings emitted
diff --git a/src/test/ui/lint/uninitialized-zeroed.rs b/src/test/ui/lint/invalid_value.rs
index dae258407..57d8cbe7c 100644
--- a/src/test/ui/lint/uninitialized-zeroed.rs
+++ b/src/test/ui/lint/invalid_value.rs
@@ -34,6 +34,20 @@ enum OneFruit {
Banana,
}
+enum OneFruitNonZero {
+ Apple(!),
+ Banana(NonZeroU32),
+}
+
+enum TwoUninhabited {
+ A(!),
+ B(Void),
+}
+
+#[rustc_layout_scalar_valid_range_start(254)]
+#[rustc_layout_scalar_valid_range_end(1)]
+pub(crate) struct WrapAroundRange(u8);
+
#[allow(unused)]
fn generic<T: 'static>() {
unsafe {
@@ -78,12 +92,21 @@ fn main() {
let _val: NonNull<i32> = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: NonNull<i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+ let _val: (NonZeroU32, i32) = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+ let _val: (NonZeroU32, i32) = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
let _val: *const dyn Send = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: *const dyn Send = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
let _val: [fn(); 2] = mem::zeroed(); //~ ERROR: does not permit zero-initialization
let _val: [fn(); 2] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+ let _val: TwoUninhabited = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+ let _val: TwoUninhabited = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
+ let _val: OneFruitNonZero = mem::zeroed(); //~ ERROR: does not permit zero-initialization
+ let _val: OneFruitNonZero = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
// Things that can be zero, but not uninit.
let _val: bool = mem::zeroed();
let _val: bool = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
@@ -112,6 +135,19 @@ fn main() {
let _val: *const [()] = mem::zeroed();
let _val: *const [()] = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+ let _val: WrapAroundRange = mem::zeroed();
+ let _val: WrapAroundRange = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
+ // Things where 0 is okay due to rustc implementation details,
+ // but that are not guaranteed to keep working.
+ let _val: Result<i32, i32> = mem::zeroed();
+ let _val: Result<i32, i32> = mem::uninitialized(); //~ ERROR: does not permit being left uninitialized
+
+ // Some things that happen to be UB-free due to rustc implementation details,
+ // but are not guaranteed to keep working.
+ let _val: OneFruit = mem::zeroed();
+ let _val: OneFruit = mem::uninitialized();
+
// Transmute-from-0
let _val: &'static i32 = mem::transmute(0usize); //~ ERROR: does not permit zero-initialization
let _val: &'static [i32] = mem::transmute((0usize, 0usize)); //~ ERROR: does not permit zero-initialization
@@ -129,9 +165,5 @@ fn main() {
let _val: bool = MaybeUninit::zeroed().assume_init();
let _val: [bool; 0] = MaybeUninit::uninit().assume_init();
let _val: [!; 0] = MaybeUninit::zeroed().assume_init();
-
- // Some things that happen to work due to rustc implementation details,
- // but are not guaranteed to keep working.
- let _val: OneFruit = mem::uninitialized();
}
}
diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/invalid_value.stderr
index b46042e7b..76afb765f 100644
--- a/src/test/ui/lint/uninitialized-zeroed.stderr
+++ b/src/test/ui/lint/invalid_value.stderr
@@ -1,5 +1,5 @@
error: the type `&T` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:40:32
+ --> $DIR/invalid_value.rs:54:32
|
LL | let _val: &'static T = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -7,15 +7,15 @@ LL | let _val: &'static T = mem::zeroed();
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
+ = note: references must be non-null
note: the lint level is defined here
- --> $DIR/uninitialized-zeroed.rs:6:9
+ --> $DIR/invalid_value.rs:6:9
|
LL | #![deny(invalid_value)]
| ^^^^^^^^^^^^^
- = note: references must be non-null
error: the type `&T` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:41:32
+ --> $DIR/invalid_value.rs:55:32
|
LL | let _val: &'static T = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL | let _val: &'static T = mem::uninitialized();
= note: references must be non-null
error: the type `Wrap<&T>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:43:38
+ --> $DIR/invalid_value.rs:57:38
|
LL | let _val: Wrap<&'static T> = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -35,13 +35,13 @@ LL | let _val: Wrap<&'static T> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:17:18
+ --> $DIR/invalid_value.rs:17:18
|
LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^
error: the type `Wrap<&T>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:44:38
+ --> $DIR/invalid_value.rs:58:38
|
LL | let _val: Wrap<&'static T> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -50,13 +50,13 @@ LL | let _val: Wrap<&'static T> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:17:18
+ --> $DIR/invalid_value.rs:17:18
|
LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^
error: the type `!` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:51:23
+ --> $DIR/invalid_value.rs:65:23
|
LL | let _val: ! = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -67,7 +67,7 @@ LL | let _val: ! = mem::zeroed();
= note: the `!` type has no valid value
error: the type `!` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:52:23
+ --> $DIR/invalid_value.rs:66:23
|
LL | let _val: ! = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -78,7 +78,7 @@ LL | let _val: ! = mem::uninitialized();
= note: the `!` type has no valid value
error: the type `(i32, !)` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:54:30
+ --> $DIR/invalid_value.rs:68:30
|
LL | let _val: (i32, !) = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -89,7 +89,7 @@ LL | let _val: (i32, !) = mem::zeroed();
= note: the `!` type has no valid value
error: the type `(i32, !)` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:55:30
+ --> $DIR/invalid_value.rs:69:30
|
LL | let _val: (i32, !) = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +100,7 @@ LL | let _val: (i32, !) = mem::uninitialized();
= note: integers must not be uninitialized
error: the type `Void` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:57:26
+ --> $DIR/invalid_value.rs:71:26
|
LL | let _val: Void = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -108,10 +108,14 @@ 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
|
- = note: enums with no variants have no valid value
+note: enums with no inhabited variants have no valid value
+ --> $DIR/invalid_value.rs:12:1
+ |
+LL | enum Void {}
+ | ^^^^^^^^^
error: the type `Void` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:58:26
+ --> $DIR/invalid_value.rs:72:26
|
LL | let _val: Void = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -119,10 +123,14 @@ 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
|
- = note: enums with no variants have no valid value
+note: enums with no inhabited variants have no valid value
+ --> $DIR/invalid_value.rs:12:1
+ |
+LL | enum Void {}
+ | ^^^^^^^^^
error: the type `&i32` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:60:34
+ --> $DIR/invalid_value.rs:74:34
|
LL | let _val: &'static i32 = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -133,7 +141,7 @@ LL | let _val: &'static i32 = mem::zeroed();
= note: references must be non-null
error: the type `&i32` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:61:34
+ --> $DIR/invalid_value.rs:75:34
|
LL | let _val: &'static i32 = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -144,7 +152,7 @@ LL | let _val: &'static i32 = mem::uninitialized();
= note: references must be non-null
error: the type `Ref` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:63:25
+ --> $DIR/invalid_value.rs:77:25
|
LL | let _val: Ref = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -153,13 +161,13 @@ LL | let _val: Ref = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:14:12
+ --> $DIR/invalid_value.rs:14:12
|
LL | struct Ref(&'static i32);
| ^^^^^^^^^^^^
error: the type `Ref` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:64:25
+ --> $DIR/invalid_value.rs:78:25
|
LL | let _val: Ref = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -168,13 +176,13 @@ LL | let _val: Ref = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:14:12
+ --> $DIR/invalid_value.rs:14:12
|
LL | struct Ref(&'static i32);
| ^^^^^^^^^^^^
error: the type `fn()` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:66:26
+ --> $DIR/invalid_value.rs:80:26
|
LL | let _val: fn() = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -185,7 +193,7 @@ LL | let _val: fn() = mem::zeroed();
= note: function pointers must be non-null
error: the type `fn()` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:67:26
+ --> $DIR/invalid_value.rs:81:26
|
LL | let _val: fn() = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -196,7 +204,7 @@ LL | let _val: fn() = mem::uninitialized();
= note: function pointers must be non-null
error: the type `Wrap<fn()>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:69:32
+ --> $DIR/invalid_value.rs:83:32
|
LL | let _val: Wrap<fn()> = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -205,13 +213,13 @@ LL | let _val: Wrap<fn()> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: function pointers must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:17:18
+ --> $DIR/invalid_value.rs:17:18
|
LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^
error: the type `Wrap<fn()>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:70:32
+ --> $DIR/invalid_value.rs:84:32
|
LL | let _val: Wrap<fn()> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -220,13 +228,13 @@ LL | let _val: Wrap<fn()> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: function pointers must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:17:18
+ --> $DIR/invalid_value.rs:17:18
|
LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^
error: the type `WrapEnum<fn()>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:72:36
+ --> $DIR/invalid_value.rs:86:36
|
LL | let _val: WrapEnum<fn()> = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -234,14 +242,14 @@ LL | let _val: WrapEnum<fn()> = mem::zeroed();
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
-note: function pointers must be non-null (in this enum field)
- --> $DIR/uninitialized-zeroed.rs:18:28
+note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+ --> $DIR/invalid_value.rs:18:28
|
LL | enum WrapEnum<T> { Wrapped(T) }
| ^
error: the type `WrapEnum<fn()>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:73:36
+ --> $DIR/invalid_value.rs:87:36
|
LL | let _val: WrapEnum<fn()> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -249,14 +257,14 @@ LL | let _val: WrapEnum<fn()> = mem::uninitialized();
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
-note: function pointers must be non-null (in this enum field)
- --> $DIR/uninitialized-zeroed.rs:18:28
+note: function pointers must be non-null (in this field of the only potentially inhabited enum variant)
+ --> $DIR/invalid_value.rs:18:28
|
LL | enum WrapEnum<T> { Wrapped(T) }
| ^
error: the type `Wrap<(RefPair, i32)>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:75:42
+ --> $DIR/invalid_value.rs:89:42
|
LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -265,13 +273,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::zeroed();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:15:16
+ --> $DIR/invalid_value.rs:15:16
|
LL | struct RefPair((&'static i32, i32));
| ^^^^^^^^^^^^^^^^^^^
error: the type `Wrap<(RefPair, i32)>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:76:42
+ --> $DIR/invalid_value.rs:90:42
|
LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -280,13 +288,13 @@ LL | let _val: Wrap<(RefPair, i32)> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: references must be non-null (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:15:16
+ --> $DIR/invalid_value.rs:15:16
|
LL | struct RefPair((&'static i32, i32));
| ^^^^^^^^^^^^^^^^^^^
error: the type `NonNull<i32>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:78:34
+ --> $DIR/invalid_value.rs:92:34
|
LL | let _val: NonNull<i32> = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -297,7 +305,7 @@ LL | let _val: NonNull<i32> = mem::zeroed();
= note: `std::ptr::NonNull<i32>` must be non-null
error: the type `NonNull<i32>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:79:34
+ --> $DIR/invalid_value.rs:93:34
|
LL | let _val: NonNull<i32> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -307,8 +315,30 @@ LL | let _val: NonNull<i32> = mem::uninitialized();
|
= note: `std::ptr::NonNull<i32>` must be non-null
+error: the type `(NonZeroU32, i32)` does not permit zero-initialization
+ --> $DIR/invalid_value.rs:95:39
+ |
+LL | let _val: (NonZeroU32, i32) = mem::zeroed();
+ | ^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+ = note: `std::num::NonZeroU32` must be non-null
+
+error: the type `(NonZeroU32, i32)` does not permit being left uninitialized
+ --> $DIR/invalid_value.rs:96:39
+ |
+LL | let _val: (NonZeroU32, i32) = mem::uninitialized();
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+ = note: `std::num::NonZeroU32` must be non-null
+
error: the type `*const dyn Send` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:81:37
+ --> $DIR/invalid_value.rs:98:37
|
LL | let _val: *const dyn Send = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -319,7 +349,7 @@ LL | let _val: *const dyn Send = mem::zeroed();
= note: the vtable of a wide raw pointer must be non-null
error: the type `*const dyn Send` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:82:37
+ --> $DIR/invalid_value.rs:99:37
|
LL | let _val: *const dyn Send = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -330,7 +360,7 @@ LL | let _val: *const dyn Send = mem::uninitialized();
= note: the vtable of a wide raw pointer must be non-null
error: the type `[fn(); 2]` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:84:31
+ --> $DIR/invalid_value.rs:101:31
|
LL | let _val: [fn(); 2] = mem::zeroed();
| ^^^^^^^^^^^^^
@@ -341,7 +371,7 @@ LL | let _val: [fn(); 2] = mem::zeroed();
= note: function pointers must be non-null
error: the type `[fn(); 2]` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:85:31
+ --> $DIR/invalid_value.rs:102:31
|
LL | let _val: [fn(); 2] = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -351,8 +381,68 @@ LL | let _val: [fn(); 2] = mem::uninitialized();
|
= note: function pointers must be non-null
+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
+ |
+note: enums with no inhabited variants have no valid value
+ --> $DIR/invalid_value.rs:42:1
+ |
+LL | enum TwoUninhabited {
+ | ^^^^^^^^^^^^^^^^^^^
+
+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
+ |
+note: enums with no inhabited variants have no valid value
+ --> $DIR/invalid_value.rs:42:1
+ |
+LL | enum TwoUninhabited {
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: the type `OneFruitNonZero` does not permit zero-initialization
+ --> $DIR/invalid_value.rs:107:37
+ |
+LL | let _val: OneFruitNonZero = mem::zeroed();
+ | ^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+ --> $DIR/invalid_value.rs:39:12
+ |
+LL | Banana(NonZeroU32),
+ | ^^^^^^^^^^
+
+error: the type `OneFruitNonZero` does not permit being left uninitialized
+ --> $DIR/invalid_value.rs:108:37
+ |
+LL | let _val: OneFruitNonZero = mem::uninitialized();
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+note: `std::num::NonZeroU32` must be non-null (in this field of the only potentially inhabited enum variant)
+ --> $DIR/invalid_value.rs:39:12
+ |
+LL | Banana(NonZeroU32),
+ | ^^^^^^^^^^
+
error: the type `bool` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:89:26
+ --> $DIR/invalid_value.rs:112:26
|
LL | let _val: bool = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -363,7 +453,7 @@ LL | let _val: bool = mem::uninitialized();
= note: booleans must be either `true` or `false`
error: the type `Wrap<char>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:92:32
+ --> $DIR/invalid_value.rs:115:32
|
LL | let _val: Wrap<char> = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -372,13 +462,13 @@ LL | let _val: Wrap<char> = mem::uninitialized();
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
note: characters must be a valid Unicode codepoint (in this struct field)
- --> $DIR/uninitialized-zeroed.rs:17:18
+ --> $DIR/invalid_value.rs:17:18
|
LL | struct Wrap<T> { wrapped: T }
| ^^^^^^^^^^
error: the type `NonBig` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:95:28
+ --> $DIR/invalid_value.rs:118:28
|
LL | let _val: NonBig = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -389,7 +479,7 @@ LL | let _val: NonBig = mem::uninitialized();
= note: `NonBig` must be initialized inside its custom valid range
error: the type `Fruit` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:98:27
+ --> $DIR/invalid_value.rs:121:27
|
LL | let _val: Fruit = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -397,14 +487,14 @@ LL | let _val: Fruit = mem::uninitialized();
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
-note: enums have to be initialized to a variant
- --> $DIR/uninitialized-zeroed.rs:26:1
+note: enums with multiple inhabited variants have to be initialized to a variant
+ --> $DIR/invalid_value.rs:26:1
|
LL | enum Fruit {
| ^^^^^^^^^^
error: the type `[bool; 2]` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:101:31
+ --> $DIR/invalid_value.rs:124:31
|
LL | let _val: [bool; 2] = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -415,7 +505,7 @@ LL | let _val: [bool; 2] = mem::uninitialized();
= note: booleans must be either `true` or `false`
error: the type `i32` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:104:25
+ --> $DIR/invalid_value.rs:127:25
|
LL | let _val: i32 = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -426,7 +516,7 @@ LL | let _val: i32 = mem::uninitialized();
= note: integers must not be uninitialized
error: the type `f32` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:107:25
+ --> $DIR/invalid_value.rs:130:25
|
LL | let _val: f32 = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -437,7 +527,7 @@ LL | let _val: f32 = mem::uninitialized();
= note: floats must not be uninitialized
error: the type `*const ()` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:110:31
+ --> $DIR/invalid_value.rs:133:31
|
LL | let _val: *const () = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -448,7 +538,7 @@ LL | let _val: *const () = mem::uninitialized();
= note: raw pointers must not be uninitialized
error: the type `*const [()]` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:113:33
+ --> $DIR/invalid_value.rs:136:33
|
LL | let _val: *const [()] = mem::uninitialized();
| ^^^^^^^^^^^^^^^^^^^^
@@ -458,8 +548,34 @@ LL | let _val: *const [()] = mem::uninitialized();
|
= note: raw pointers must not be uninitialized
+error: the type `WrapAroundRange` does not permit being left uninitialized
+ --> $DIR/invalid_value.rs:139:37
+ |
+LL | let _val: WrapAroundRange = mem::uninitialized();
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+ = note: `WrapAroundRange` must be initialized inside its custom valid range
+
+error: the type `Result<i32, i32>` does not permit being left uninitialized
+ --> $DIR/invalid_value.rs:144:38
+ |
+LL | let _val: Result<i32, i32> = mem::uninitialized();
+ | ^^^^^^^^^^^^^^^^^^^^
+ | |
+ | this code causes undefined behavior when executed
+ | help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
+ |
+note: enums with multiple inhabited variants have to be initialized to a variant
+ --> $SRC_DIR/core/src/result.rs:LL:COL
+ |
+LL | pub enum Result<T, E> {
+ | ^^^^^^^^^^^^^^^^^^^^^
+
error: the type `&i32` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:116:34
+ --> $DIR/invalid_value.rs:152:34
|
LL | let _val: &'static i32 = mem::transmute(0usize);
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -470,7 +586,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize);
= note: references must be non-null
error: the type `&[i32]` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:117:36
+ --> $DIR/invalid_value.rs:153:36
|
LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -481,7 +597,7 @@ LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize));
= note: references must be non-null
error: the type `NonZeroU32` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:118:32
+ --> $DIR/invalid_value.rs:154:32
|
LL | let _val: NonZeroU32 = mem::transmute(0);
| ^^^^^^^^^^^^^^^^^
@@ -492,7 +608,7 @@ LL | let _val: NonZeroU32 = mem::transmute(0);
= note: `std::num::NonZeroU32` must be non-null
error: the type `NonNull<i32>` does not permit zero-initialization
- --> $DIR/uninitialized-zeroed.rs:121:34
+ --> $DIR/invalid_value.rs:157:34
|
LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -503,7 +619,7 @@ LL | let _val: NonNull<i32> = MaybeUninit::zeroed().assume_init();
= note: `std::ptr::NonNull<i32>` must be non-null
error: the type `NonNull<i32>` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:122:34
+ --> $DIR/invalid_value.rs:158:34
|
LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -514,7 +630,7 @@ LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
= note: `std::ptr::NonNull<i32>` must be non-null
error: the type `bool` does not permit being left uninitialized
- --> $DIR/uninitialized-zeroed.rs:123:26
+ --> $DIR/invalid_value.rs:159:26
|
LL | let _val: bool = MaybeUninit::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -524,5 +640,5 @@ LL | let _val: bool = MaybeUninit::uninit().assume_init();
|
= note: booleans must be either `true` or `false`
-error: aborting due to 43 previous errors
+error: aborting due to 51 previous errors
diff --git a/src/test/ui/lint/issue-102705.rs b/src/test/ui/lint/issue-102705.rs
new file mode 100644
index 000000000..5bcc8950a
--- /dev/null
+++ b/src/test/ui/lint/issue-102705.rs
@@ -0,0 +1,22 @@
+// check-pass
+
+#![allow(opaque_hidden_inferred_bound)]
+#![allow(dead_code)]
+
+trait Duh {}
+
+impl Duh for i32 {}
+
+trait Trait {
+ type Assoc: Duh;
+}
+
+impl<R: Duh, F: FnMut() -> R> Trait for F {
+ type Assoc = R;
+}
+
+fn foo() -> impl Trait<Assoc = impl Send> {
+ || 42
+}
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-14309.stderr b/src/test/ui/lint/issue-14309.stderr
index a9538b5e3..9ce62a6b8 100644
--- a/src/test/ui/lint/issue-14309.stderr
+++ b/src/test/ui/lint/issue-14309.stderr
@@ -4,11 +4,6 @@ error: `extern` block uses type `A`, which is not FFI-safe
LL | fn foo(x: A);
| ^ not FFI-safe
|
-note: the lint level is defined here
- --> $DIR/issue-14309.rs:1:9
- |
-LL | #![deny(improper_ctypes)]
- | ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
@@ -16,6 +11,11 @@ note: the type is defined here
|
LL | struct A {
| ^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/issue-14309.rs:1:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
error: `extern` block uses type `A`, which is not FFI-safe
--> $DIR/issue-14309.rs:31:15
diff --git a/src/test/ui/lint/issue-1866.stderr b/src/test/ui/lint/issue-1866.stderr
index 5edae48a1..d19a13496 100644
--- a/src/test/ui/lint/issue-1866.stderr
+++ b/src/test/ui/lint/issue-1866.stderr
@@ -7,13 +7,13 @@ LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
LL | pub fn rust_task_is_unwinding(rt: *const rust_task) -> bool;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
+ = note: expected `unsafe extern "C" fn(*const usize) -> bool`
+ found `unsafe extern "C" fn(*const bool) -> bool`
note: the lint level is defined here
--> $DIR/issue-1866.rs:4:9
|
LL | #![warn(clashing_extern_declarations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn(*const usize) -> bool`
- found `unsafe extern "C" fn(*const bool) -> bool`
warning: 1 warning emitted
diff --git a/src/test/ui/lint/issue-63364.stderr b/src/test/ui/lint/issue-63364.stderr
index 0375359ae..9b5453fa8 100644
--- a/src/test/ui/lint/issue-63364.stderr
+++ b/src/test/ui/lint/issue-63364.stderr
@@ -4,8 +4,8 @@ error: literal out of range for `u16`
LL | for n in 100_000.. {
| ^^^^^^^
|
- = note: `#[deny(overflowing_literals)]` on by default
= note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535`
+ = note: `#[deny(overflowing_literals)]` on by default
error: aborting due to previous error
diff --git a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
index 5093715de..cc44f8aa5 100644
--- a/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
+++ b/src/test/ui/lint/issue-70819-dont-override-forbid-in-same-scope.stderr
@@ -6,13 +6,13 @@ LL | #![forbid(unused)]
LL | #![deny(unused)]
| ^^^^^^ overruled by previous forbid
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
note: the lint level is defined here
--> $DIR/issue-70819-dont-override-forbid-in-same-scope.rs:17:11
|
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
error: aborting due to previous error
diff --git a/src/test/ui/lint/issue-79744.stderr b/src/test/ui/lint/issue-79744.stderr
index 6f6dd44d2..c1b56250d 100644
--- a/src/test/ui/lint/issue-79744.stderr
+++ b/src/test/ui/lint/issue-79744.stderr
@@ -4,9 +4,9 @@ error: literal out of range for `i8`
LL | let e2 = 230;
| ^^^
|
- = note: `#[deny(overflowing_literals)]` on by default
= note: the literal `230` does not fit into the type `i8` whose range is `-128..=127`
= help: consider using the type `u8` instead
+ = note: `#[deny(overflowing_literals)]` on by default
error: aborting due to previous error
diff --git a/src/test/ui/lint/issue-80988.stderr b/src/test/ui/lint/issue-80988.stderr
index 1d397f431..73e27ffda 100644
--- a/src/test/ui/lint/issue-80988.stderr
+++ b/src/test/ui/lint/issue-80988.stderr
@@ -7,9 +7,9 @@ LL |
LL | #[deny(warnings)]
| ^^^^^^^^ overruled by previous forbid
|
- = note: `#[warn(forbidden_lint_groups)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
+ = note: `#[warn(forbidden_lint_groups)]` on by default
warning: deny(warnings) incompatible with previous forbid
--> $DIR/issue-80988.rs:7:8
diff --git a/src/test/ui/lint/issue-83477.stderr b/src/test/ui/lint/issue-83477.stderr
index e619bcfe2..f824fc09e 100644
--- a/src/test/ui/lint/issue-83477.stderr
+++ b/src/test/ui/lint/issue-83477.stderr
@@ -18,13 +18,13 @@ warning: prefer `FxHashMap` over `HashMap`, it has better performance
LL | let _ = std::collections::HashMap::<String, String>::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
note: the lint level is defined here
--> $DIR/issue-83477.rs:3:9
|
LL | #![warn(rustc::internal)]
| ^^^^^^^^^^^^^^^
= note: `#[warn(rustc::default_hash_types)]` implied by `#[warn(rustc::internal)]`
- = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
warning: 3 warnings emitted
diff --git a/src/test/ui/lint/issue-86600-lint-twice.stderr b/src/test/ui/lint/issue-86600-lint-twice.stderr
index 8da3fb5a8..5a65c6121 100644
--- a/src/test/ui/lint/issue-86600-lint-twice.stderr
+++ b/src/test/ui/lint/issue-86600-lint-twice.stderr
@@ -4,9 +4,9 @@ warning: floating-point types cannot be used in patterns
LL | 5.0 => {}
| ^^^
|
- = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+ = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/lint/lint-attr-everywhere-early.stderr b/src/test/ui/lint/lint-attr-everywhere-early.stderr
index 1d6e3cda4..d6c6d5fae 100644
--- a/src/test/ui/lint/lint-attr-everywhere-early.stderr
+++ b/src/test/ui/lint/lint-attr-everywhere-early.stderr
@@ -474,13 +474,13 @@ error: `...` range patterns are deprecated
LL | f1: 0...100,
| ^^^ help: use `..=` for an inclusive range
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-early.rs:166:20
|
LL | #[deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to 36 previous errors
diff --git a/src/test/ui/lint/lint-attr-everywhere-late.stderr b/src/test/ui/lint/lint-attr-everywhere-late.stderr
index 977843997..a69c2e0ef 100644
--- a/src/test/ui/lint/lint-attr-everywhere-late.stderr
+++ b/src/test/ui/lint/lint-attr-everywhere-late.stderr
@@ -163,13 +163,13 @@ LL | fn clashing1();
LL | fn clashing1(_: i32);
| ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
+ = note: expected `unsafe extern "C" fn()`
+ found `unsafe extern "C" fn(i32)`
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:122:13
|
LL | #![deny(clashing_extern_declarations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn()`
- found `unsafe extern "C" fn(i32)`
error: `clashing2` redeclared with a different signature
--> $DIR/lint-attr-everywhere-late.rs:128:5
@@ -180,13 +180,13 @@ LL | fn clashing2();
LL | fn clashing2(_: i32);
| ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
|
+ = note: expected `unsafe extern "C" fn()`
+ found `unsafe extern "C" fn(i32)`
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:127:12
|
LL | #[deny(clashing_extern_declarations)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: expected `unsafe extern "C" fn()`
- found `unsafe extern "C" fn(i32)`
error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped
--> $DIR/lint-attr-everywhere-late.rs:93:38
@@ -206,16 +206,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | fn assoc_fn() { discriminant::<i32>(&123); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:95:12
- |
-LL | #[deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:96:41
|
LL | fn assoc_fn() { discriminant::<i32>(&123); }
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:95:12
+ |
+LL | #[deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: literal out of range for `u8`
--> $DIR/lint-attr-everywhere-late.rs:98:59
@@ -223,12 +223,12 @@ error: literal out of range for `u8`
LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
| ^^^^
|
+ = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255`
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:98:12
|
LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000;
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255`
error: variable `PARAM` should have a snake case name
--> $DIR/lint-attr-everywhere-late.rs:131:37
@@ -248,16 +248,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | let _ = discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:138:12
- |
-LL | #[deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:139:33
|
LL | let _ = discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:138:12
+ |
+LL | #[deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: variable `PARAM` should have a snake case name
--> $DIR/lint-attr-everywhere-late.rs:145:44
@@ -277,16 +277,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:153:17
- |
-LL | #![deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:155:33
|
LL | discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:153:17
+ |
+LL | #![deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:161:13
@@ -294,16 +294,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:159:16
- |
-LL | #[deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:161:33
|
LL | discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:159:16
+ |
+LL | #[deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:168:9
@@ -311,16 +311,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:167:17
- |
-LL | #![deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:168:29
|
LL | discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:167:17
+ |
+LL | #![deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:172:9
@@ -328,16 +328,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:171:16
- |
-LL | #[deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:172:29
|
LL | discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:171:16
+ |
+LL | #[deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:177:5
@@ -345,16 +345,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant::<i32>(&123);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:176:12
- |
-LL | #[deny(enum_intrinsics_non_enums)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:177:25
|
LL | discriminant::<i32>(&123);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:176:12
+ |
+LL | #[deny(enum_intrinsics_non_enums)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:179:41
@@ -362,16 +362,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:179:13
- |
-LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:179:61
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:179:13
+ |
+LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:180:41
@@ -379,16 +379,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:180:13
- |
-LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:180:61
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:180:13
+ |
+LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:182:45
@@ -396,16 +396,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:182:17
- |
-LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:182:65
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:182:17
+ |
+LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-attr-everywhere-late.rs:184:52
@@ -413,16 +413,16 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/lint-attr-everywhere-late.rs:184:24
- |
-LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum.
--> $DIR/lint-attr-everywhere-late.rs:184:72
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
| ^^^^
+note: the lint level is defined here
+ --> $DIR/lint-attr-everywhere-late.rs:184:24
+ |
+LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 31 previous errors
diff --git a/src/test/ui/lint/lint-const-item-mutation.stderr b/src/test/ui/lint/lint-const-item-mutation.stderr
index 94d876423..9f4360e67 100644
--- a/src/test/ui/lint/lint-const-item-mutation.stderr
+++ b/src/test/ui/lint/lint-const-item-mutation.stderr
@@ -4,13 +4,13 @@ warning: attempting to modify a `const` item
LL | ARRAY[0] = 5;
| ^^^^^^^^^^^^
|
- = note: `#[warn(const_item_mutation)]` on by default
= note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified
note: `const` item defined here
--> $DIR/lint-const-item-mutation.rs:26:1
|
LL | const ARRAY: [u8; 1] = [25];
| ^^^^^^^^^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
warning: attempting to modify a `const` item
--> $DIR/lint-const-item-mutation.rs:38:5
diff --git a/src/test/ui/lint/lint-ctypes-73249-2.stderr b/src/test/ui/lint/lint-ctypes-73249-2.stderr
index 7c85e9fa8..8073c33dd 100644
--- a/src/test/ui/lint/lint-ctypes-73249-2.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-2.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
LL | pub fn lint_me() -> A<()>;
| ^^^^^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-2.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-ctypes-73249-3.stderr b/src/test/ui/lint/lint-ctypes-73249-3.stderr
index 83e2a233c..c41ce666d 100644
--- a/src/test/ui/lint/lint-ctypes-73249-3.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-3.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
LL | pub fn lint_me() -> A;
| ^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-3.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-ctypes-73249-5.stderr b/src/test/ui/lint/lint-ctypes-73249-5.stderr
index 37781d78c..98245c4f1 100644
--- a/src/test/ui/lint/lint-ctypes-73249-5.stderr
+++ b/src/test/ui/lint/lint-ctypes-73249-5.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
LL | pub fn lint_me() -> A;
| ^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-73249-5.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-ctypes-73251-1.stderr b/src/test/ui/lint/lint-ctypes-73251-1.stderr
index 76b19d37e..9f43576ad 100644
--- a/src/test/ui/lint/lint-ctypes-73251-1.stderr
+++ b/src/test/ui/lint/lint-ctypes-73251-1.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `Qux`, which is not FFI-safe
LL | pub fn lint_me() -> <u32 as Foo>::Assoc;
| ^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-73251-1.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-ctypes-73251-2.stderr b/src/test/ui/lint/lint-ctypes-73251-2.stderr
index 64f0fb2d8..0b3de379c 100644
--- a/src/test/ui/lint/lint-ctypes-73251-2.stderr
+++ b/src/test/ui/lint/lint-ctypes-73251-2.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `AliasA`, which is not FFI-safe
LL | pub fn lint_me() -> <AliasB as TraitB>::Assoc;
| ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-73251-2.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-ctypes-enum.stderr b/src/test/ui/lint/lint-ctypes-enum.stderr
index de532f69a..8554e2617 100644
--- a/src/test/ui/lint/lint-ctypes-enum.stderr
+++ b/src/test/ui/lint/lint-ctypes-enum.stderr
@@ -4,11 +4,6 @@ error: `extern` block uses type `U`, which is not FFI-safe
LL | fn uf(x: U);
| ^ not FFI-safe
|
-note: the lint level is defined here
- --> $DIR/lint-ctypes-enum.rs:3:9
- |
-LL | #![deny(improper_ctypes)]
- | ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]`, `#[repr(transparent)]`, or integer `#[repr(...)]` attribute to this enum
= note: enum has no representation hint
note: the type is defined here
@@ -16,6 +11,11 @@ note: the type is defined here
|
LL | enum U {
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/lint-ctypes-enum.rs:3:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
error: `extern` block uses type `B`, which is not FFI-safe
--> $DIR/lint-ctypes-enum.rs:61:13
diff --git a/src/test/ui/lint/lint-ctypes-fn.stderr b/src/test/ui/lint/lint-ctypes-fn.stderr
index 6f8d76411..a05206bf1 100644
--- a/src/test/ui/lint/lint-ctypes-fn.stderr
+++ b/src/test/ui/lint/lint-ctypes-fn.stderr
@@ -4,13 +4,13 @@ error: `extern` fn uses type `[u32]`, which is not FFI-safe
LL | pub extern "C" fn slice_type(p: &[u32]) { }
| ^^^^^^ not FFI-safe
|
+ = help: consider using a raw pointer instead
+ = note: slices have no C equivalent
note: the lint level is defined here
--> $DIR/lint-ctypes-fn.rs:4:9
|
LL | #![deny(improper_ctypes_definitions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: consider using a raw pointer instead
- = note: slices have no C equivalent
error: `extern` fn uses type `str`, which is not FFI-safe
--> $DIR/lint-ctypes-fn.rs:76:31
diff --git a/src/test/ui/lint/lint-ctypes.stderr b/src/test/ui/lint/lint-ctypes.stderr
index bfec40e19..121ad0ce8 100644
--- a/src/test/ui/lint/lint-ctypes.stderr
+++ b/src/test/ui/lint/lint-ctypes.stderr
@@ -4,11 +4,6 @@ error: `extern` block uses type `Foo`, which is not FFI-safe
LL | pub fn ptr_type1(size: *const Foo);
| ^^^^^^^^^^ not FFI-safe
|
-note: the lint level is defined here
- --> $DIR/lint-ctypes.rs:4:9
- |
-LL | #![deny(improper_ctypes)]
- | ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
= note: this struct has unspecified layout
note: the type is defined here
@@ -16,6 +11,11 @@ note: the type is defined here
|
LL | pub struct Foo;
| ^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/lint-ctypes.rs:4:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
error: `extern` block uses type `Foo`, which is not FFI-safe
--> $DIR/lint-ctypes.rs:49:28
diff --git a/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr b/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr
index bec9fb62e..63ed2503c 100644
--- a/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr
+++ b/src/test/ui/lint/lint-enum-intrinsics-non-enums.stderr
@@ -4,12 +4,12 @@ error: the return value of `mem::discriminant` is unspecified when called with a
LL | discriminant(&());
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(enum_intrinsics_non_enums)]` on by default
note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `()`, which is not an enum.
--> $DIR/lint-enum-intrinsics-non-enums.rs:26:18
|
LL | discriminant(&());
| ^^^
+ = note: `#[deny(enum_intrinsics_non_enums)]` on by default
error: the return value of `mem::discriminant` is unspecified when called with a non-enum type
--> $DIR/lint-enum-intrinsics-non-enums.rs:29:5
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
index d7fd51461..3a84c6c1f 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr
@@ -7,7 +7,7 @@ LL | const N: i32 = T::N << 42;
note: the lint level is defined here
--> $DIR/lint-exceeding-bitshifts.rs:10:9
|
-LL | #![warn(arithmetic_overflow, const_err)]
+LL | #![warn(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
warning: this arithmetic operation will overflow
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
index d7fd51461..3a84c6c1f 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr
@@ -7,7 +7,7 @@ LL | const N: i32 = T::N << 42;
note: the lint level is defined here
--> $DIR/lint-exceeding-bitshifts.rs:10:9
|
-LL | #![warn(arithmetic_overflow, const_err)]
+LL | #![warn(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
warning: this arithmetic operation will overflow
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
index d7fd51461..3a84c6c1f 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr
@@ -7,7 +7,7 @@ LL | const N: i32 = T::N << 42;
note: the lint level is defined here
--> $DIR/lint-exceeding-bitshifts.rs:10:9
|
-LL | #![warn(arithmetic_overflow, const_err)]
+LL | #![warn(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
warning: this arithmetic operation will overflow
diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs
index d8774cb4d..048c1aff8 100644
--- a/src/test/ui/lint/lint-exceeding-bitshifts.rs
+++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs
@@ -7,7 +7,7 @@
// normalize-stderr-test "shift left by `(64|32)_usize`, which" -> "shift left by `%BITS%`, which"
#![crate_type="lib"]
-#![warn(arithmetic_overflow, const_err)]
+#![warn(arithmetic_overflow)]
pub trait Foo {
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
index afbab9896..2cc4d382d 100644
--- a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -7,9 +7,9 @@ LL |
LL | impl Foo for dyn Send + Send {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
|
- = note: `#[deny(order_dependent_trait_objects)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+ = note: `#[deny(order_dependent_trait_objects)]` on by default
error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
--> $DIR/lint-incoherent-auto-trait-objects.rs:11:1
@@ -37,3 +37,45 @@ LL | impl Foo for dyn Send + Sync + Send {}
error: aborting due to 3 previous errors
+Future incompatibility report: Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:5:1
+ |
+LL | impl Foo for dyn Send {}
+ | --------------------- first implementation here
+LL |
+LL | impl Foo for dyn Send + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+ = note: `#[deny(order_dependent_trait_objects)]` on by default
+
+Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:11:1
+ |
+LL | impl Foo for dyn Send + Sync {}
+ | ---------------------------- first implementation here
+LL |
+LL | impl Foo for dyn Sync + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+ = note: `#[deny(order_dependent_trait_objects)]` on by default
+
+Future breakage diagnostic:
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:15:1
+ |
+LL | impl Foo for dyn Sync + Send {}
+ | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+ = note: `#[deny(order_dependent_trait_objects)]` on by default
+
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-bool.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-bool.stderr
index 2a1847b98..9f38dcb0b 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-bool.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-bool.stderr
@@ -4,8 +4,8 @@ error: atomic loads cannot have `Release` or `AcqRel` ordering
LL | let _ = x.load(Ordering::Release);
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: atomic loads cannot have `Release` or `AcqRel` ordering
--> $DIR/lint-invalid-atomic-ordering-bool.rs:15:20
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
index 021654cf3..cc075ce9e 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange-weak.stderr
@@ -4,8 +4,8 @@ error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRe
LL | let _ = x.compare_exchange_weak(ptr2, ptr, Ordering::Relaxed, Ordering::AcqRel);
| ^^^^^^^^^^^^^^^^ invalid failure ordering
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using `Acquire` or `Relaxed` failure ordering instead
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: `compare_exchange_weak`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange_weak` does not result in a write
--> $DIR/lint-invalid-atomic-ordering-exchange-weak.rs:30:67
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
index f6f8f88e8..fe6c7e55c 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-exchange.stderr
@@ -4,8 +4,8 @@ error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, s
LL | let _ = x.compare_exchange(0, 0, Ordering::Relaxed, Ordering::AcqRel);
| ^^^^^^^^^^^^^^^^ invalid failure ordering
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using `Acquire` or `Relaxed` failure ordering instead
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: `compare_exchange`'s failure ordering may not be `Release` or `AcqRel`, since a failed `compare_exchange` does not result in a write
--> $DIR/lint-invalid-atomic-ordering-exchange.rs:28:57
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fence.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-fence.stderr
index e0741ffed..38327d607 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-fence.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fence.stderr
@@ -4,8 +4,8 @@ error: memory fences cannot have `Relaxed` ordering
LL | fence(Ordering::Relaxed);
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: memory fences cannot have `Relaxed` ordering
--> $DIR/lint-invalid-atomic-ordering-fence.rs:19:20
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
index 267b1c706..33829d68f 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-fetch-update.stderr
@@ -4,8 +4,8 @@ error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since
LL | let _ = x.fetch_update(Ordering::Relaxed, Ordering::AcqRel, |old| Some(old + 1));
| ^^^^^^^^^^^^^^^^ invalid failure ordering
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using `Acquire` or `Relaxed` failure ordering instead
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: `fetch_update`'s failure ordering may not be `Release` or `AcqRel`, since a failed `fetch_update` does not result in a write
--> $DIR/lint-invalid-atomic-ordering-fetch-update.rs:28:47
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-int.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-int.stderr
index dfd999045..36930e2f4 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-int.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-int.stderr
@@ -4,8 +4,8 @@ error: atomic loads cannot have `Release` or `AcqRel` ordering
LL | let _ = x.load(Ordering::Release);
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: atomic loads cannot have `Release` or `AcqRel` ordering
--> $DIR/lint-invalid-atomic-ordering-int.rs:22:20
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-ptr.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-ptr.stderr
index f00cb8e40..12f4cad90 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-ptr.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-ptr.stderr
@@ -4,8 +4,8 @@ error: atomic loads cannot have `Release` or `AcqRel` ordering
LL | let _ = x.load(Ordering::Release);
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: atomic loads cannot have `Release` or `AcqRel` ordering
--> $DIR/lint-invalid-atomic-ordering-ptr.rs:17:20
diff --git a/src/test/ui/lint/lint-invalid-atomic-ordering-uint.stderr b/src/test/ui/lint/lint-invalid-atomic-ordering-uint.stderr
index 36672e434..d26621f2a 100644
--- a/src/test/ui/lint/lint-invalid-atomic-ordering-uint.stderr
+++ b/src/test/ui/lint/lint-invalid-atomic-ordering-uint.stderr
@@ -4,8 +4,8 @@ error: atomic loads cannot have `Release` or `AcqRel` ordering
LL | let _ = x.load(Ordering::Release);
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(invalid_atomic_ordering)]` on by default
= help: consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`
+ = note: `#[deny(invalid_atomic_ordering)]` on by default
error: atomic loads cannot have `Release` or `AcqRel` ordering
--> $DIR/lint-invalid-atomic-ordering-uint.rs:21:20
diff --git a/src/test/ui/lint/lint-non-snake-case-crate-2.stderr b/src/test/ui/lint/lint-non-snake-case-crate-2.stderr
index e29511293..4b42145bb 100644
--- a/src/test/ui/lint/lint-non-snake-case-crate-2.stderr
+++ b/src/test/ui/lint/lint-non-snake-case-crate-2.stderr
@@ -1,11 +1,11 @@
error: crate `NonSnakeCase` should have a snake case name
|
+ = help: convert the identifier to snake case: `non_snake_case`
note: the lint level is defined here
--> $DIR/lint-non-snake-case-crate-2.rs:4:9
|
LL | #![deny(non_snake_case)]
| ^^^^^^^^^^^^^^
- = help: convert the identifier to snake case: `non_snake_case`
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-output-format.rs b/src/test/ui/lint/lint-output-format.rs
index 169a98c94..67e8ec8f1 100644
--- a/src/test/ui/lint/lint-output-format.rs
+++ b/src/test/ui/lint/lint-output-format.rs
@@ -5,6 +5,7 @@
extern crate lint_output_format; //~ ERROR use of unstable library feature
use lint_output_format::{foo, bar}; //~ ERROR use of unstable library feature
+//~| ERROR use of unstable library feature
fn main() {
let _x = foo();
diff --git a/src/test/ui/lint/lint-output-format.stderr b/src/test/ui/lint/lint-output-format.stderr
index 3bc1d6fc1..0db79a156 100644
--- a/src/test/ui/lint/lint-output-format.stderr
+++ b/src/test/ui/lint/lint-output-format.stderr
@@ -7,6 +7,14 @@ LL | extern crate lint_output_format;
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
+ --> $DIR/lint-output-format.rs:7:26
+ |
+LL | use lint_output_format::{foo, bar};
+ | ^^^
+ |
+ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
--> $DIR/lint-output-format.rs:7:31
|
LL | use lint_output_format::{foo, bar};
@@ -15,13 +23,13 @@ LL | use lint_output_format::{foo, bar};
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
error[E0658]: use of unstable library feature 'unstable_test_feature'
- --> $DIR/lint-output-format.rs:11:14
+ --> $DIR/lint-output-format.rs:12:14
|
LL | let _y = bar();
| ^^^
|
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
index 3355bb4e4..ce3e8806a 100644
--- a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
+++ b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr
@@ -4,9 +4,9 @@ warning: `try` is a keyword in the 2018 edition
LL | pub fn try() {}
| ^^^ help: you can use a raw identifier to stay compatible: `r#try`
|
- = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
= note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
+ = note: `-W keyword-idents` implied by `-W rust-2018-compatibility`
warning: 1 warning emitted
diff --git a/src/test/ui/lint/lint-stability-deprecated.rs b/src/test/ui/lint/lint-stability-deprecated.rs
index bdc66e830..74c35083e 100644
--- a/src/test/ui/lint/lint-stability-deprecated.rs
+++ b/src/test/ui/lint/lint-stability-deprecated.rs
@@ -130,7 +130,7 @@ mod cross_crate {
let _ = UnstableTupleStruct (1);
let _ = StableTupleStruct (1);
- // At the moment, the lint checker only checks stability in
+ // At the moment, the lint checker only checks stability
// in the arguments of macros.
// Eventually, we will want to lint the contents of the
// macro in the module *defining* it. Also, stability levels
diff --git a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
index c85934aa3..383623b48 100644
--- a/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
+++ b/src/test/ui/lint/lint-strict-provenance-fuzzy-casts.stderr
@@ -4,12 +4,12 @@ error: strict provenance disallows casting integer `usize` to pointer `*const u8
LL | let dangling = 16_usize as *const u8;
| ^^^^^^^^^^^^^^^^^^^^^
|
+ = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead
note: the lint level is defined here
--> $DIR/lint-strict-provenance-fuzzy-casts.rs:2:9
|
LL | #![deny(fuzzy_provenance_casts)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = help: if you can't comply with strict provenance and don't have a pointer with the correct provenance you can use `std::ptr::from_exposed_addr()` instead
help: use `.with_addr()` to adjust a valid pointer in the same allocation, to this address
|
LL | let dangling = (...).with_addr(16_usize);
diff --git a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
index 05178b34b..aa151fe2d 100644
--- a/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
+++ b/src/test/ui/lint/lint-strict-provenance-lossy-casts.stderr
@@ -4,12 +4,12 @@ error: under strict provenance it is considered bad style to cast pointer `*cons
LL | let addr: usize = &x as *const u8 as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
note: the lint level is defined here
--> $DIR/lint-strict-provenance-lossy-casts.rs:2:9
|
LL | #![deny(lossy_provenance_casts)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = help: if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_addr()` instead
help: use `.addr()` to obtain the address of a pointer
|
LL | let addr: usize = (&x as *const u8).addr();
diff --git a/src/test/ui/lint/lint-temporary-cstring-as-param.stderr b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr
index 0a9e5a4bf..838b3bc13 100644
--- a/src/test/ui/lint/lint-temporary-cstring-as-param.stderr
+++ b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr
@@ -6,13 +6,13 @@ LL | some_function(CString::new("").unwrap().as_ptr());
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
+ = 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
note: the lint level is defined here
--> $DIR/lint-temporary-cstring-as-param.rs:1:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = 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
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr b/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr
index e69d2dd53..79ef57dd1 100644
--- a/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr
+++ b/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr
@@ -6,13 +6,13 @@ LL | let s = CString::new("some text").unwrap().as_ptr();
| |
| this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime
|
+ = 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
note: the lint level is defined here
--> $DIR/lint-temporary-cstring-as-ptr.rs:2:9
|
LL | #![deny(temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = 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
error: aborting due to previous error
diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr
index 3562cb440..b3420ad8a 100644
--- a/src/test/ui/lint/lint-type-limits2.stderr
+++ b/src/test/ui/lint/lint-type-limits2.stderr
@@ -12,13 +12,13 @@ warning: literal out of range for `i8`
LL | 128 > bar()
| ^^^
|
+ = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
note: the lint level is defined here
--> $DIR/lint-type-limits2.rs:2:9
|
LL | #![warn(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr
index 823d1a4c7..db46e7ae7 100644
--- a/src/test/ui/lint/lint-type-limits3.stderr
+++ b/src/test/ui/lint/lint-type-limits3.stderr
@@ -12,13 +12,13 @@ warning: literal out of range for `i8`
LL | while 200 != i {
| ^^^
|
+ = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
note: the lint level is defined here
--> $DIR/lint-type-limits3.rs:2:9
|
LL | #![warn(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr
index 1bb1ec547..48d8228b8 100644
--- a/src/test/ui/lint/lint-type-overflow.stderr
+++ b/src/test/ui/lint/lint-type-overflow.stderr
@@ -4,12 +4,12 @@ error: literal out of range for `u8`
LL | let x1: u8 = 256;
| ^^^
|
+ = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
note: the lint level is defined here
--> $DIR/lint-type-overflow.rs:1:9
|
LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `256` does not fit into the type `u8` whose range is `0..=255`
error: literal out of range for `u8`
--> $DIR/lint-type-overflow.rs:13:14
diff --git a/src/test/ui/lint/lint-type-overflow2.rs b/src/test/ui/lint/lint-type-overflow2.rs
index c1f874c07..9b1eb510b 100644
--- a/src/test/ui/lint/lint-type-overflow2.rs
+++ b/src/test/ui/lint/lint-type-overflow2.rs
@@ -1,7 +1,6 @@
// compile-flags: -O
#![deny(overflowing_literals)]
-#![deny(const_err)]
fn main() {
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr
index 3d40cdf96..eb593d062 100644
--- a/src/test/ui/lint/lint-type-overflow2.stderr
+++ b/src/test/ui/lint/lint-type-overflow2.stderr
@@ -1,19 +1,19 @@
error: literal out of range for `i8`
- --> $DIR/lint-type-overflow2.rs:7:20
+ --> $DIR/lint-type-overflow2.rs:6:20
|
LL | let x2: i8 = --128;
| ^^^
|
+ = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
note: the lint level is defined here
--> $DIR/lint-type-overflow2.rs:3:9
|
LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
error: literal out of range for `f32`
- --> $DIR/lint-type-overflow2.rs:9:14
+ --> $DIR/lint-type-overflow2.rs:8:14
|
LL | let x = -3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL | let x = -3.40282357e+38_f32;
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
error: literal out of range for `f32`
- --> $DIR/lint-type-overflow2.rs:10:14
+ --> $DIR/lint-type-overflow2.rs:9:14
|
LL | let x = 3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL | let x = 3.40282357e+38_f32;
= note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `f32::INFINITY`
error: literal out of range for `f64`
- --> $DIR/lint-type-overflow2.rs:11:14
+ --> $DIR/lint-type-overflow2.rs:10:14
|
LL | let x = -1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -37,7 +37,7 @@ LL | let x = -1.7976931348623159e+308_f64;
= note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `f64::INFINITY`
error: literal out of range for `f64`
- --> $DIR/lint-type-overflow2.rs:12:14
+ --> $DIR/lint-type-overflow2.rs:11:14
|
LL | let x = 1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/lint/lint-unconditional-recursion.stderr b/src/test/ui/lint/lint-unconditional-recursion.stderr
index c11b73f41..9d200a789 100644
--- a/src/test/ui/lint/lint-unconditional-recursion.stderr
+++ b/src/test/ui/lint/lint-unconditional-recursion.stderr
@@ -6,12 +6,12 @@ LL | fn foo() {
LL | foo();
| ----- recursive call site
|
+ = help: a `loop` may express intention better if this is on purpose
note: the lint level is defined here
--> $DIR/lint-unconditional-recursion.rs:1:9
|
LL | #![deny(unconditional_recursion)]
| ^^^^^^^^^^^^^^^^^^^^^^^
- = help: a `loop` may express intention better if this is on purpose
error: function cannot return without recursing
--> $DIR/lint-unconditional-recursion.rs:14:1
diff --git a/src/test/ui/lint/lint-unsafe-code.stderr b/src/test/ui/lint/lint-unsafe-code.stderr
index 8dde05fc4..037f0a832 100644
--- a/src/test/ui/lint/lint-unsafe-code.stderr
+++ b/src/test/ui/lint/lint-unsafe-code.stderr
@@ -4,12 +4,12 @@ error: declaration of a `no_mangle` function
LL | #[no_mangle] fn foo() {}
| ^^^^^^^^^^^^
|
+ = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
note: the lint level is defined here
--> $DIR/lint-unsafe-code.rs:3:9
|
LL | #![deny(unsafe_code)]
| ^^^^^^^^^^^
- = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them
error: declaration of a `no_mangle` static
--> $DIR/lint-unsafe-code.rs:32:1
diff --git a/src/test/ui/lint/must_not_suspend/boxed.stderr b/src/test/ui/lint/must_not_suspend/boxed.stderr
index b3c9b4381..9efc7b069 100644
--- a/src/test/ui/lint/must_not_suspend/boxed.stderr
+++ b/src/test/ui/lint/must_not_suspend/boxed.stderr
@@ -6,11 +6,6 @@ LL | let _guard = bar();
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/boxed.rs:3:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/boxed.rs:20:9
|
@@ -21,6 +16,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let _guard = bar();
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/boxed.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/dedup.stderr b/src/test/ui/lint/must_not_suspend/dedup.stderr
index 13fa3ae30..f8978ba57 100644
--- a/src/test/ui/lint/must_not_suspend/dedup.stderr
+++ b/src/test/ui/lint/must_not_suspend/dedup.stderr
@@ -4,16 +4,16 @@ error: `No` held across a suspend point, but should not be
LL | wheeee(&No {}).await;
| ^^^^^ ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/dedup.rs:3:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
--> $DIR/dedup.rs:16:13
|
LL | wheeee(&No {}).await;
| ^^^^^
+note: the lint level is defined here
+ --> $DIR/dedup.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/gated.stderr b/src/test/ui/lint/must_not_suspend/gated.stderr
index b58ecb555..64de1ebea 100644
--- a/src/test/ui/lint/must_not_suspend/gated.stderr
+++ b/src/test/ui/lint/must_not_suspend/gated.stderr
@@ -4,10 +4,10 @@ warning: unknown lint: `must_not_suspend`
LL | #![deny(must_not_suspend)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unknown_lints)]` on by default
= note: the `must_not_suspend` lint is unstable
= note: see issue #83310 <https://github.com/rust-lang/rust/issues/83310> for more information
= help: add `#![feature(must_not_suspend)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
warning: unknown lint: `must_not_suspend`
--> $DIR/gated.rs:4:1
diff --git a/src/test/ui/lint/must_not_suspend/mutex.stderr b/src/test/ui/lint/must_not_suspend/mutex.stderr
index a968b7ca0..c251cb845 100644
--- a/src/test/ui/lint/must_not_suspend/mutex.stderr
+++ b/src/test/ui/lint/must_not_suspend/mutex.stderr
@@ -6,11 +6,6 @@ LL | let _guard = m.lock().unwrap();
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/mutex.rs:3:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: holding a MutexGuard across suspend points can cause deadlocks, delays, and cause Futures to not implement `Send`
--> $DIR/mutex.rs:8:9
|
@@ -21,6 +16,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let _guard = m.lock().unwrap();
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/mutex.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
index c49d27128..180e187c1 100644
--- a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
+++ b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
@@ -7,11 +7,6 @@ LL |
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/ref-drop-tracking.rs:4:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/ref-drop-tracking.rs:19:13
|
@@ -22,6 +17,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let guard = &mut self.u;
| ^^^^^
+note: the lint level is defined here
+ --> $DIR/ref-drop-tracking.rs:4:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr b/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr
index 0157c8b7f..abf76711b 100644
--- a/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr
+++ b/src/test/ui/lint/must_not_suspend/ref.drop_tracking.stderr
@@ -7,11 +7,6 @@ LL |
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/ref.rs:6:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/ref.rs:21:13
|
@@ -22,6 +17,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let guard = &mut self.u;
| ^^^^^
+note: the lint level is defined here
+ --> $DIR/ref.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr b/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
index 438e6489e..41ac09ea7 100644
--- a/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
+++ b/src/test/ui/lint/must_not_suspend/ref.no_drop_tracking.stderr
@@ -7,11 +7,6 @@ LL |
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/ref.rs:6:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/ref.rs:21:26
|
@@ -22,6 +17,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let guard = &mut self.u;
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/ref.rs:6:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/trait.stderr b/src/test/ui/lint/must_not_suspend/trait.stderr
index 60369430a..d64d25aae 100644
--- a/src/test/ui/lint/must_not_suspend/trait.stderr
+++ b/src/test/ui/lint/must_not_suspend/trait.stderr
@@ -7,16 +7,16 @@ LL | let _guard1 = r#impl();
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/trait.rs:3:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
--> $DIR/trait.rs:21:9
|
LL | let _guard1 = r#impl();
| ^^^^^^^
+note: the lint level is defined here
+ --> $DIR/trait.rs:3: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
diff --git a/src/test/ui/lint/must_not_suspend/unit.stderr b/src/test/ui/lint/must_not_suspend/unit.stderr
index 42d037b35..c967dbac5 100644
--- a/src/test/ui/lint/must_not_suspend/unit.stderr
+++ b/src/test/ui/lint/must_not_suspend/unit.stderr
@@ -6,11 +6,6 @@ LL | let _guard = bar();
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/unit.rs:3:9
- |
-LL | #![deny(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/unit.rs:20:9
|
@@ -21,6 +16,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let _guard = bar();
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/unit.rs:3:9
+ |
+LL | #![deny(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/lint/must_not_suspend/warn.stderr b/src/test/ui/lint/must_not_suspend/warn.stderr
index 417c397da..fe551c652 100644
--- a/src/test/ui/lint/must_not_suspend/warn.stderr
+++ b/src/test/ui/lint/must_not_suspend/warn.stderr
@@ -6,11 +6,6 @@ LL | let _guard = bar();
LL | other().await;
| ------ the value is held across this suspend point
|
-note: the lint level is defined here
- --> $DIR/warn.rs:4:9
- |
-LL | #![warn(must_not_suspend)]
- | ^^^^^^^^^^^^^^^^
note: You gotta use Umm's, ya know?
--> $DIR/warn.rs:21:9
|
@@ -21,6 +16,11 @@ help: consider using a block (`{ ... }`) to shrink the value's scope, ending bef
|
LL | let _guard = bar();
| ^^^^^^
+note: the lint level is defined here
+ --> $DIR/warn.rs:4:9
+ |
+LL | #![warn(must_not_suspend)]
+ | ^^^^^^^^^^^^^^^^
warning: 1 warning emitted
diff --git a/src/test/ui/lint/no-coverage.stderr b/src/test/ui/lint/no-coverage.stderr
index 8452ccc7a..404efbeac 100644
--- a/src/test/ui/lint/no-coverage.stderr
+++ b/src/test/ui/lint/no-coverage.stderr
@@ -94,7 +94,7 @@ error: unconstrained opaque type
LL | type U = impl Trait;
| ^^^^^^^^^^
|
- = note: `U` must be used in combination with a concrete type within the same module
+ = note: `U` must be used in combination with a concrete type within the same impl
error: aborting due to 7 previous errors; 6 warnings emitted
diff --git a/src/test/ui/lint/noop-method-call.rs b/src/test/ui/lint/noop-method-call.rs
index 9870c8135..89b296635 100644
--- a/src/test/ui/lint/noop-method-call.rs
+++ b/src/test/ui/lint/noop-method-call.rs
@@ -46,6 +46,7 @@ fn main() {
fn generic<T>(non_clone_type: &PlainType<T>) {
non_clone_type.clone();
+ //~^ WARNING call to `.clone()` on a reference in this situation does nothing
}
fn non_generic(non_clone_type: &PlainType<u32>) {
diff --git a/src/test/ui/lint/noop-method-call.stderr b/src/test/ui/lint/noop-method-call.stderr
index 7f6f96bf1..6a904d01a 100644
--- a/src/test/ui/lint/noop-method-call.stderr
+++ b/src/test/ui/lint/noop-method-call.stderr
@@ -4,12 +4,12 @@ warning: call to `.clone()` on a reference in this situation does nothing
LL | let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone();
| ^^^^^^^^ unnecessary method call
|
+ = note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
note: the lint level is defined here
--> $DIR/noop-method-call.rs:4:9
|
LL | #![warn(noop_method_call)]
| ^^^^^^^^^^^^^^^^
- = note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
warning: call to `.deref()` on a reference in this situation does nothing
--> $DIR/noop-method-call.rs:28:63
@@ -28,12 +28,20 @@ LL | let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow();
= note: the type `&PlainType<u32>` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed
warning: call to `.clone()` on a reference in this situation does nothing
- --> $DIR/noop-method-call.rs:52:19
+ --> $DIR/noop-method-call.rs:48:19
+ |
+LL | non_clone_type.clone();
+ | ^^^^^^^^ unnecessary method call
+ |
+ = note: the type `&PlainType<T>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
+
+warning: call to `.clone()` on a reference in this situation does nothing
+ --> $DIR/noop-method-call.rs:53:19
|
LL | non_clone_type.clone();
| ^^^^^^^^ unnecessary method call
|
= note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
-warning: 4 warnings emitted
+warning: 5 warnings emitted
diff --git a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
index 62d00fd68..33aa95854 100644
--- a/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/src/test/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `A`, which is not FFI-safe
LL | pub fn a(_: A);
| ^ not FFI-safe
|
+ = note: opaque types have no C equivalent
note: the lint level is defined here
--> $DIR/opaque-ty-ffi-unsafe.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: opaque types have no C equivalent
error: aborting due to previous error
diff --git a/src/test/ui/lint/outer-forbid.stderr b/src/test/ui/lint/outer-forbid.stderr
index 781457321..a47877980 100644
--- a/src/test/ui/lint/outer-forbid.stderr
+++ b/src/test/ui/lint/outer-forbid.stderr
@@ -7,13 +7,13 @@ LL | #![forbid(unused, non_snake_case)]
LL | #[allow(unused_variables)]
| ^^^^^^^^^^^^^^^^ overruled by previous forbid
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
note: the lint level is defined here
--> $DIR/outer-forbid.rs:18:11
|
LL | #![forbid(forbidden_lint_groups)]
| ^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #81670 <https://github.com/rust-lang/rust/issues/81670>
error: allow(unused) incompatible with previous forbid
--> $DIR/outer-forbid.rs:25:9
diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
index bc0c53303..e31d14c55 100644
--- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
+++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr
@@ -1,4 +1,4 @@
-TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }]
+TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(488..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(505..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }]
error: unnecessary trailing semicolon
--> $DIR/redundant-semi-proc-macro.rs:9:19
|
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
index 370e51bf7..2c35647b8 100644
--- a/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
+++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_nested_lint_levels.stderr
@@ -31,8 +31,8 @@ warning: this lint expectation is unfulfilled
LL | unused_mut,
| ^^^^^^^^^^
|
- = note: `#[warn(unfulfilled_lint_expectations)]` on by default
= note: this `expect` is overridden by a `allow` attribute before the `unused_mut` lint is triggered
+ = note: `#[warn(unfulfilled_lint_expectations)]` on by default
warning: this lint expectation is unfulfilled
--> $DIR/expect_nested_lint_levels.rs:24:5
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr
index 9bfee79b0..9a1c3e442 100644
--- a/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr
+++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_unfulfilled_expectation.stderr
@@ -4,9 +4,9 @@ warning: this lint expectation is unfulfilled
LL | #![expect(unfulfilled_lint_expectations, reason = "idk why you would expect this")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unfulfilled_lint_expectations)]` on by default
= note: idk why you would expect this
= note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
+ = note: `#[warn(unfulfilled_lint_expectations)]` on by default
warning: this lint expectation is unfulfilled
--> $DIR/expect_unfulfilled_expectation.rs:13:10
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr
index 82c1a4c08..e349e4081 100644
--- a/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr
+++ b/src/test/ui/lint/rfc-2383-lint-reason/expect_with_reason.stderr
@@ -4,8 +4,8 @@ warning: this lint expectation is unfulfilled
LL | #![expect(unused_variables, reason = "<This should fail and display this reason>")]
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unfulfilled_lint_expectations)]` on by default
= note: <This should fail and display this reason>
+ = note: `#[warn(unfulfilled_lint_expectations)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
index 06befcbb5..5942fa8ae 100644
--- a/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
+++ b/src/test/ui/lint/rfc-2383-lint-reason/force_warn_expected_lints_fulfilled.stderr
@@ -1,11 +1,3 @@
-warning: denote infinite loops with `loop { ... }`
- --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5
- |
-LL | while true {
- | ^^^^^^^^^^ help: use `loop`
- |
- = note: requested on the command line with `--force-warn while-true`
-
warning: unused variable: `x`
--> $DIR/force_warn_expected_lints_fulfilled.rs:20:9
|
@@ -36,5 +28,13 @@ LL | let mut what_does_the_fox_say = "*ding* *deng* *dung*";
|
= note: requested on the command line with `--force-warn unused-mut`
+warning: denote infinite loops with `loop { ... }`
+ --> $DIR/force_warn_expected_lints_fulfilled.rs:10:5
+ |
+LL | while true {
+ | ^^^^^^^^^^ help: use `loop`
+ |
+ = note: requested on the command line with `--force-warn while-true`
+
warning: 5 warnings emitted
diff --git a/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr
index 3bf8137dc..3e9d70821 100644
--- a/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr
+++ b/src/test/ui/lint/rfc-2383-lint-reason/lint-attribute-only-with-reason.stderr
@@ -4,12 +4,12 @@ error: unused attribute
LL | #[allow(reason = "I want to allow something")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
+ = note: attribute `allow` without any lints has no effect
note: the lint level is defined here
--> $DIR/lint-attribute-only-with-reason.rs:3:9
|
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = note: attribute `allow` without any lints has no effect
error: unused attribute
--> $DIR/lint-attribute-only-with-reason.rs:6:1
diff --git a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr
index 9ca034b71..884a4a453 100644
--- a/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr
+++ b/src/test/ui/lint/rfc-2457-non-ascii-idents/lint-mixed-script-confusables.stderr
@@ -4,13 +4,13 @@ error: the usage of Script Group `Greek` in this crate consists solely of mixed
LL | struct ΑctuallyNotLatin;
| ^^^^^^^^^^^^^^^^
|
+ = note: the usage includes 'Α' (U+0391)
+ = note: please recheck to make sure their usages are indeed what you want
note: the lint level is defined here
--> $DIR/lint-mixed-script-confusables.rs:1:9
|
LL | #![deny(mixed_script_confusables)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the usage includes 'Α' (U+0391)
- = note: please recheck to make sure their usages are indeed what you want
error: the usage of Script Group `Cyrillic` in this crate consists solely of mixed script confusables
--> $DIR/lint-mixed-script-confusables.rs:10:5
diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
index 84ad32bdd..49608c205 100644
--- a/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
+++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr
@@ -7,15 +7,15 @@ LL | true;
LL | foo!(warn_in_block)
| ------------------- in this macro invocation
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: macro invocations at the end of a block are treated as expressions
+ = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo`
note: the lint level is defined here
--> $DIR/semicolon-in-expressions-from-macros.rs:4:9
|
LL | #![warn(semicolon_in_expressions_from_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
- = note: macro invocations at the end of a block are treated as expressions
- = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo`
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: trailing semicolon in macro used in expression position
diff --git a/src/test/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr b/src/test/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr
index d770a8c8f..16c152eb2 100644
--- a/src/test/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr
+++ b/src/test/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr
@@ -7,9 +7,9 @@ LL | true;
LL | _ => foo!()
| ------ in this macro invocation
|
- = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted
diff --git a/src/test/ui/lint/trivial-cast-ice.rs b/src/test/ui/lint/trivial-cast-ice.rs
new file mode 100644
index 000000000..f781fab22
--- /dev/null
+++ b/src/test/ui/lint/trivial-cast-ice.rs
@@ -0,0 +1,12 @@
+// aux-build:trivial-cast-ice.rs
+// check-pass
+
+// Demonstrates the ICE in #102561
+
+#![deny(trivial_casts)]
+
+extern crate trivial_cast_ice;
+
+fn main() {
+ trivial_cast_ice::foo!();
+}
diff --git a/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr b/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr
index f7c42acb3..5087807b6 100644
--- a/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr
+++ b/src/test/ui/lint/trivial-casts-featuring-type-ascription.stderr
@@ -4,12 +4,12 @@ error: trivial numeric cast: `i32` as `i32`
LL | let lugubrious = 12i32 as i32;
| ^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
note: the lint level is defined here
--> $DIR/trivial-casts-featuring-type-ascription.rs:1:24
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
error: trivial cast: `&u32` as `*const u32`
--> $DIR/trivial-casts-featuring-type-ascription.rs:8:13
@@ -17,12 +17,12 @@ error: trivial cast: `&u32` as `*const u32`
LL | let _ = haunted as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
note: the lint level is defined here
--> $DIR/trivial-casts-featuring-type-ascription.rs:1:9
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require type ascription or a temporary variable
error: aborting due to 2 previous errors
diff --git a/src/test/ui/lint/trivial-casts.stderr b/src/test/ui/lint/trivial-casts.stderr
index 1544f553c..7ace353de 100644
--- a/src/test/ui/lint/trivial-casts.stderr
+++ b/src/test/ui/lint/trivial-casts.stderr
@@ -4,12 +4,12 @@ error: trivial numeric cast: `i32` as `i32`
LL | let lugubrious = 12i32 as i32;
| ^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
--> $DIR/trivial-casts.rs:1:24
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&u32` as `*const u32`
--> $DIR/trivial-casts.rs:7:13
@@ -17,12 +17,12 @@ error: trivial cast: `&u32` as `*const u32`
LL | let _ = haunted as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
--> $DIR/trivial-casts.rs:1:9
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require a temporary variable
error: aborting due to 2 previous errors
diff --git a/src/test/ui/lint/trivial_casts.stderr b/src/test/ui/lint/trivial_casts.stderr
index 8a216360f..74f962835 100644
--- a/src/test/ui/lint/trivial_casts.stderr
+++ b/src/test/ui/lint/trivial_casts.stderr
@@ -4,12 +4,12 @@ error: trivial numeric cast: `i32` as `i32`
LL | let _ = 42_i32 as i32;
| ^^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
--> $DIR/trivial_casts.rs:4:24
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require a temporary variable
error: trivial numeric cast: `u8` as `u8`
--> $DIR/trivial_casts.rs:19:13
@@ -25,12 +25,12 @@ error: trivial cast: `&u32` as `*const u32`
LL | let _ = x as *const u32;
| ^^^^^^^^^^^^^^^
|
+ = help: cast can be replaced by coercion; this might require a temporary variable
note: the lint level is defined here
--> $DIR/trivial_casts.rs:4:9
|
LL | #![deny(trivial_casts, trivial_numeric_casts)]
| ^^^^^^^^^^^^^
- = help: cast can be replaced by coercion; this might require a temporary variable
error: trivial cast: `&mut u32` as `*mut u32`
--> $DIR/trivial_casts.rs:28:13
diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr
index 8a31fd447..62cb1f7f4 100644
--- a/src/test/ui/lint/type-overflow.stderr
+++ b/src/test/ui/lint/type-overflow.stderr
@@ -4,13 +4,13 @@ warning: literal out of range for `i8`
LL | let error = 255i8;
| ^^^^^
|
+ = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127`
+ = help: consider using the type `u8` instead
note: the lint level is defined here
--> $DIR/type-overflow.rs:2:9
|
LL | #![warn(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
- = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127`
- = help: consider using the type `u8` instead
warning: literal out of range for `i8`
--> $DIR/type-overflow.rs:10:16
diff --git a/src/test/ui/lint/unaligned_references.stderr b/src/test/ui/lint/unaligned_references.stderr
index 97dbec286..346f49b92 100644
--- a/src/test/ui/lint/unaligned_references.stderr
+++ b/src/test/ui/lint/unaligned_references.stderr
@@ -4,15 +4,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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:24:17
@@ -111,15 +111,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -128,15 +128,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -145,15 +145,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -162,15 +162,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -179,15 +179,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -196,15 +196,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -213,15 +213,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -230,15 +230,15 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
error: reference to packed field is unaligned
@@ -247,13 +247,13 @@ error: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
diff --git a/src/test/ui/lint/unaligned_references_external_macro.stderr b/src/test/ui/lint/unaligned_references_external_macro.stderr
index 1262c21ee..c46ca6742 100644
--- a/src/test/ui/lint/unaligned_references_external_macro.stderr
+++ b/src/test/ui/lint/unaligned_references_external_macro.stderr
@@ -10,6 +10,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
|
@@ -21,10 +25,6 @@ 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: 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
@@ -42,6 +42,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
|
@@ -53,9 +57,5 @@ 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: this error originates in the macro `unaligned_references_external_crate::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/lint/unreachable_pub.stderr b/src/test/ui/lint/unreachable_pub.stderr
index e021f500c..762834b97 100644
--- a/src/test/ui/lint/unreachable_pub.stderr
+++ b/src/test/ui/lint/unreachable_pub.stderr
@@ -6,12 +6,12 @@ LL | pub use std::fmt;
| |
| help: consider restricting its visibility: `pub(crate)`
|
+ = help: or consider exporting it for use by other crates
note: the lint level is defined here
--> $DIR/unreachable_pub.rs:4:9
|
LL | #![warn(unreachable_pub)]
| ^^^^^^^^^^^^^^^
- = help: or consider exporting it for use by other crates
warning: unreachable `pub` item
--> $DIR/unreachable_pub.rs:9:24
diff --git a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
index 26fa6eb9b..fe2e3afc8 100644
--- a/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
+++ b/src/test/ui/lint/unused/issue-47390-unused-variable-in-struct-pattern.stderr
@@ -49,8 +49,8 @@ warning: value assigned to `hours_are_suns` is never read
LL | hours_are_suns = false;
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
= help: maybe it is overwritten before being read?
+ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
warning: unused variable: `fire`
--> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:52:32
diff --git a/src/test/ui/lint/unused/must-use-box-from-raw.stderr b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
index 7769f09aa..011acc3bf 100644
--- a/src/test/ui/lint/unused/must-use-box-from-raw.stderr
+++ b/src/test/ui/lint/unused/must-use-box-from-raw.stderr
@@ -4,12 +4,12 @@ warning: unused return value of `Box::<T>::from_raw` that must be used
LL | Box::from_raw(ptr);
| ^^^^^^^^^^^^^^^^^^^
|
+ = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
note: the lint level is defined here
--> $DIR/must-use-box-from-raw.rs:5:9
|
LL | #![warn(unused_must_use)]
| ^^^^^^^^^^^^^^^
- = note: call `drop(from_raw(ptr))` if you intend to drop the `Box`
warning: 1 warning emitted
diff --git a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
index 76978d29d..f5199f43c 100644
--- a/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
+++ b/src/test/ui/lint/unused/must_use-in-stdlib-traits.stderr
@@ -4,12 +4,12 @@ error: unused implementer of `Iterator` that must be used
LL | iterator();
| ^^^^^^^^^^^
|
+ = note: iterators are lazy and do nothing unless consumed
note: the lint level is defined here
--> $DIR/must_use-in-stdlib-traits.rs:1:9
|
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
- = note: iterators are lazy and do nothing unless consumed
error: unused implementer of `Future` that must be used
--> $DIR/must_use-in-stdlib-traits.rs:43:4
diff --git a/src/test/ui/lint/unused/must_use-tuple.stderr b/src/test/ui/lint/unused/must_use-tuple.stderr
index e5709a5f0..63e0318fb 100644
--- a/src/test/ui/lint/unused/must_use-tuple.stderr
+++ b/src/test/ui/lint/unused/must_use-tuple.stderr
@@ -4,12 +4,12 @@ error: unused `Result` in tuple element 0 that must be used
LL | (Ok::<(), ()>(()),);
| ^^^^^^^^^^^^^^^^
|
+ = note: this `Result` may be an `Err` variant, which should be handled
note: the lint level is defined here
--> $DIR/must_use-tuple.rs:1:9
|
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
- = note: this `Result` may be an `Err` variant, which should be handled
error: unused `Result` in tuple element 0 that must be used
--> $DIR/must_use-tuple.rs:10:6
diff --git a/src/test/ui/lint/unused/unused-attr-duplicate.stderr b/src/test/ui/lint/unused/unused-attr-duplicate.stderr
index f592323b5..769b17487 100644
--- a/src/test/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/src/test/ui/lint/unused/unused-attr-duplicate.stderr
@@ -4,16 +4,16 @@ error: unused attribute
LL | #[no_link]
| ^^^^^^^^^^ help: remove this attribute
|
-note: the lint level is defined here
- --> $DIR/unused-attr-duplicate.rs:12:9
- |
-LL | #![deny(unused_attributes)]
- | ^^^^^^^^^^^^^^^^^
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:32:1
|
LL | #[no_link]
| ^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/unused-attr-duplicate.rs:12:9
+ |
+LL | #![deny(unused_attributes)]
+ | ^^^^^^^^^^^^^^^^^
error: unused attribute
--> $DIR/unused-attr-duplicate.rs:37:1
diff --git a/src/test/ui/lint/unused/unused-closure.stderr b/src/test/ui/lint/unused/unused-closure.stderr
index 265d3e8e0..4362abd20 100644
--- a/src/test/ui/lint/unused/unused-closure.stderr
+++ b/src/test/ui/lint/unused/unused-closure.stderr
@@ -6,12 +6,12 @@ LL | | println!("Hello!");
LL | | };
| |______^
|
+ = note: closures are lazy and do nothing unless called
note: the lint level is defined here
--> $DIR/unused-closure.rs:6:9
|
LL | #![deny(unused_must_use)]
| ^^^^^^^^^^^^^^^
- = note: closures are lazy and do nothing unless called
error: unused implementer of `Future` that must be used
--> $DIR/unused-closure.rs:13:5
diff --git a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
index 1a022c309..078b780d8 100644
--- a/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
+++ b/src/test/ui/lint/unused/unused-doc-comments-edge-cases.stderr
@@ -23,12 +23,12 @@ LL |
LL | _ => false,
| ---------- rustdoc does not generate documentation for match arms
|
+ = help: use `//` for a plain comment
note: the lint level is defined here
--> $DIR/unused-doc-comments-edge-cases.rs:1:9
|
LL | #![deny(unused_doc_comments)]
| ^^^^^^^^^^^^^^^^^^^
- = help: use `//` for a plain comment
error: unused doc comment
--> $DIR/unused-doc-comments-edge-cases.rs:23:5
diff --git a/src/test/ui/lint/unused/unused-doc-comments-for-macros.stderr b/src/test/ui/lint/unused/unused-doc-comments-for-macros.stderr
index f4f5bb71e..26b1c2b05 100644
--- a/src/test/ui/lint/unused/unused-doc-comments-for-macros.stderr
+++ b/src/test/ui/lint/unused/unused-doc-comments-for-macros.stderr
@@ -8,12 +8,12 @@ LL | | /// line3
| |
| rustdoc does not generate documentation for macro invocations
|
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
note: the lint level is defined here
--> $DIR/unused-doc-comments-for-macros.rs:1:9
|
LL | #![deny(unused_doc_comments)]
| ^^^^^^^^^^^^^^^^^^^
- = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
error: unused doc comment
--> $DIR/unused-doc-comments-for-macros.rs:13:5
diff --git a/src/test/ui/lint/unused/unused-supertrait.rs b/src/test/ui/lint/unused/unused-supertrait.rs
new file mode 100644
index 000000000..64a8e5204
--- /dev/null
+++ b/src/test/ui/lint/unused/unused-supertrait.rs
@@ -0,0 +1,11 @@
+#![deny(unused_must_use)]
+
+fn it() -> impl ExactSizeIterator<Item = ()> {
+ let x: Box<dyn ExactSizeIterator<Item = ()>> = todo!();
+ x
+}
+
+fn main() {
+ it();
+ //~^ ERROR unused implementer of `Iterator` that must be used
+}
diff --git a/src/test/ui/lint/unused/unused-supertrait.stderr b/src/test/ui/lint/unused/unused-supertrait.stderr
new file mode 100644
index 000000000..d2f8c0078
--- /dev/null
+++ b/src/test/ui/lint/unused/unused-supertrait.stderr
@@ -0,0 +1,15 @@
+error: unused implementer of `Iterator` that must be used
+ --> $DIR/unused-supertrait.rs:9:5
+ |
+LL | it();
+ | ^^^^^
+ |
+ = note: iterators are lazy and do nothing unless consumed
+note: the lint level is defined here
+ --> $DIR/unused-supertrait.rs:1:9
+ |
+LL | #![deny(unused_must_use)]
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lint/unused/unused_attributes-must_use.stderr b/src/test/ui/lint/unused/unused_attributes-must_use.stderr
index dd112c23e..ce959ddbc 100644
--- a/src/test/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/src/test/ui/lint/unused/unused_attributes-must_use.stderr
@@ -4,16 +4,16 @@ error: unused attribute `must_use`
LL | #[must_use]
| ^^^^^^^^^^^
|
-note: the lint level is defined here
- --> $DIR/unused_attributes-must_use.rs:2:9
- |
-LL | #![deny(unused_attributes, unused_must_use)]
- | ^^^^^^^^^^^^^^^^^
note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
--> $DIR/unused_attributes-must_use.rs:59:1
|
LL | global_asm!("");
| ^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/unused_attributes-must_use.rs:2:9
+ |
+LL | #![deny(unused_attributes, unused_must_use)]
+ | ^^^^^^^^^^^^^^^^^
error: `#[must_use]` has no effect when applied to an extern crate
--> $DIR/unused_attributes-must_use.rs:5:1
diff --git a/src/test/ui/lint/unused/useless-comment.stderr b/src/test/ui/lint/unused/useless-comment.stderr
index 0054426fb..8bb5bdaeb 100644
--- a/src/test/ui/lint/unused/useless-comment.stderr
+++ b/src/test/ui/lint/unused/useless-comment.stderr
@@ -4,12 +4,12 @@ error: unused doc comment
LL | /// foo
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macro invocations
|
+ = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
note: the lint level is defined here
--> $DIR/useless-comment.rs:3:9
|
LL | #![deny(unused_doc_comments)]
| ^^^^^^^^^^^^^^^^^^^
- = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion
error: unused doc comment
--> $DIR/useless-comment.rs:32:5
diff --git a/src/test/ui/liveness/liveness-asm.stderr b/src/test/ui/liveness/liveness-asm.stderr
index d052aca33..57d89e44d 100644
--- a/src/test/ui/liveness/liveness-asm.stderr
+++ b/src/test/ui/liveness/liveness-asm.stderr
@@ -4,12 +4,12 @@ warning: value assigned to `src` is never read
LL | asm!("/*{0}*/", inout(reg) src);
| ^^^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/liveness-asm.rs:7:9
|
LL | #![warn(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
- = help: maybe it is overwritten before being read?
warning: value assigned to `src` is never read
--> $DIR/liveness-asm.rs:24:39
diff --git a/src/test/ui/liveness/liveness-consts.stderr b/src/test/ui/liveness/liveness-consts.stderr
index 16209d16c..6199ea96c 100644
--- a/src/test/ui/liveness/liveness-consts.stderr
+++ b/src/test/ui/liveness/liveness-consts.stderr
@@ -4,13 +4,13 @@ warning: variable `a` is assigned to, but never used
LL | let mut a = 0;
| ^
|
+ = note: consider using `_a` instead
note: the lint level is defined here
--> $DIR/liveness-consts.rs:2:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
- = note: consider using `_a` instead
warning: value assigned to `b` is never read
--> $DIR/liveness-consts.rs:17:5
@@ -18,8 +18,8 @@ warning: value assigned to `b` is never read
LL | b += 1;
| ^
|
- = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
= help: maybe it is overwritten before being read?
+ = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
warning: unused variable: `e`
--> $DIR/liveness-consts.rs:24:13
diff --git a/src/test/ui/liveness/liveness-dead.stderr b/src/test/ui/liveness/liveness-dead.stderr
index 12680ab11..de6d5bd99 100644
--- a/src/test/ui/liveness/liveness-dead.stderr
+++ b/src/test/ui/liveness/liveness-dead.stderr
@@ -4,12 +4,12 @@ error: value assigned to `x` is never read
LL | let mut x: isize = 3;
| ^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/liveness-dead.rs:2:9
|
LL | #![deny(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
- = help: maybe it is overwritten before being read?
error: value assigned to `x` is never read
--> $DIR/liveness-dead.rs:17:5
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.rs b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
index e8909c4a5..dff859429 100644
--- a/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.rs
@@ -1,4 +1,3 @@
-//
// regression test for #8005
macro_rules! test { () => { fn foo() -> i32 { 1; } } }
diff --git a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
index 82d136bd3..de0843aa6 100644
--- a/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
+++ b/src/test/ui/liveness/liveness-return-last-stmt-semi.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/liveness-return-last-stmt-semi.rs:7:19
+ --> $DIR/liveness-return-last-stmt-semi.rs:6:19
|
LL | fn no_return() -> i32 {}
| --------- ^^^ expected `i32`, found `()`
@@ -7,17 +7,17 @@ LL | fn no_return() -> i32 {}
| implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types
- --> $DIR/liveness-return-last-stmt-semi.rs:9:19
+ --> $DIR/liveness-return-last-stmt-semi.rs:8:19
|
LL | fn bar(x: u32) -> u32 {
| --- ^^^ expected `u32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
LL | x * 2;
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error[E0308]: mismatched types
- --> $DIR/liveness-return-last-stmt-semi.rs:13:19
+ --> $DIR/liveness-return-last-stmt-semi.rs:12:19
|
LL | fn baz(x: u64) -> u32 {
| --- ^^^ expected `u32`, found `()`
@@ -25,7 +25,7 @@ LL | fn baz(x: u64) -> u32 {
| implicitly returns `()` as its body has no tail or `return` expression
error[E0308]: mismatched types
- --> $DIR/liveness-return-last-stmt-semi.rs:4:41
+ --> $DIR/liveness-return-last-stmt-semi.rs:3:41
|
LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } }
| --- ^^^ expected `i32`, found `()`
diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr
index 4a6122681..f6c478ddb 100644
--- a/src/test/ui/liveness/liveness-unused.stderr
+++ b/src/test/ui/liveness/liveness-unused.stderr
@@ -57,12 +57,12 @@ error: value assigned to `x` is never read
LL | x += 4;
| ^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/liveness-unused.rs:3:9
|
LL | #![deny(unused_assignments)]
| ^^^^^^^^^^^^^^^^^^
- = help: maybe it is overwritten before being read?
error: variable `z` is assigned to, but never used
--> $DIR/liveness-unused.rs:37:13
diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr
index cb104e0a3..82f62371e 100644
--- a/src/test/ui/liveness/liveness-upvars.stderr
+++ b/src/test/ui/liveness/liveness-upvars.stderr
@@ -4,13 +4,13 @@ warning: value assigned to `last` is never read
LL | last = Some(s);
| ^^^^
|
+ = help: maybe it is overwritten before being read?
note: the lint level is defined here
--> $DIR/liveness-upvars.rs:4:9
|
LL | #![warn(unused)]
| ^^^^^^
= note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
- = help: maybe it is overwritten before being read?
warning: unused variable: `last`
--> $DIR/liveness-upvars.rs:10:9
@@ -18,8 +18,8 @@ warning: unused variable: `last`
LL | last = Some(s);
| ^^^^
|
- = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
= help: did you mean to capture by reference instead?
+ = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
warning: unused variable: `sum`
--> $DIR/liveness-upvars.rs:22:9
diff --git a/src/test/ui/loops/loop-proper-liveness.stderr b/src/test/ui/loops/loop-proper-liveness.stderr
index 14e86aee0..f9d94b681 100644
--- a/src/test/ui/loops/loop-proper-liveness.stderr
+++ b/src/test/ui/loops/loop-proper-liveness.stderr
@@ -8,6 +8,10 @@ LL | println!("{:?}", x);
| ^ `x` used here but it isn't initialized
|
= 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 assigning a value
+ |
+LL | let x: i32 = 0;
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/macros/format-parse-errors.stderr b/src/test/ui/macros/format-parse-errors.stderr
index 1a7578e60..f9ea4c633 100644
--- a/src/test/ui/macros/format-parse-errors.stderr
+++ b/src/test/ui/macros/format-parse-errors.stderr
@@ -22,7 +22,7 @@ error: positional arguments cannot follow named arguments
--> $DIR/format-parse-errors.rs:10:9
|
LL | foo = foo,
- | --- named argument
+ | --------- named argument
LL | bar,
| ^^^ positional arguments must be before named arguments
diff --git a/src/test/ui/macros/issue-102878.rs b/src/test/ui/macros/issue-102878.rs
new file mode 100644
index 000000000..aac589193
--- /dev/null
+++ b/src/test/ui/macros/issue-102878.rs
@@ -0,0 +1,10 @@
+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)}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-102878.stderr b/src/test/ui/macros/issue-102878.stderr
new file mode 100644
index 000000000..e0b8855a3
--- /dev/null
+++ b/src/test/ui/macros/issue-102878.stderr
@@ -0,0 +1,60 @@
+error: mismatched closing delimiter: `)`
+ --> $DIR/issue-102878.rs:1:35
+ |
+LL | macro_rules!test{($l:expr,$_:r)=>({const:y y)}
+ | -^ ^ mismatched closing delimiter
+ | ||
+ | |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
+
diff --git a/src/test/ui/macros/issue-39404.stderr b/src/test/ui/macros/issue-39404.stderr
index d2f2a823c..3886a70bb 100644
--- a/src/test/ui/macros/issue-39404.stderr
+++ b/src/test/ui/macros/issue-39404.stderr
@@ -4,9 +4,9 @@ error: missing fragment specifier
LL | macro_rules! m { ($i) => {} }
| ^^
|
- = note: `#[deny(missing_fragment_specifier)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+ = note: `#[deny(missing_fragment_specifier)]` on by default
error: aborting due to previous error
diff --git a/src/test/ui/macros/issue-84195-lint-anon-const.stderr b/src/test/ui/macros/issue-84195-lint-anon-const.stderr
index 39485d74e..306c08b13 100644
--- a/src/test/ui/macros/issue-84195-lint-anon-const.stderr
+++ b/src/test/ui/macros/issue-84195-lint-anon-const.stderr
@@ -7,13 +7,13 @@ LL | () => { 0; };
LL | let val: [u8; len!()] = [];
| ------ in this macro invocation
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
note: the lint level is defined here
--> $DIR/issue-84195-lint-anon-const.rs:5:9
|
LL | #![deny(semicolon_in_expressions_from_macros)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
= note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error
diff --git a/src/test/ui/macros/issue-99265.stderr b/src/test/ui/macros/issue-99265.stderr
index 2bfeedd7d..9185dbff6 100644
--- a/src/test/ui/macros/issue-99265.stderr
+++ b/src/test/ui/macros/issue-99265.stderr
@@ -77,18 +77,18 @@ help: use the named argument by name to avoid ambiguity
LL | println!("Hello {:width$}!", "x", width = 5);
| ~~~~~~
-warning: named argument `width` is not used by name
- --> $DIR/issue-99265.rs:23:46
+warning: named argument `f` is not used by name
+ --> $DIR/issue-99265.rs:23:33
|
LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | -- ^^^^^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `width` by position
+ | -------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `f` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | ~~~~~~
+LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
+ | +
warning: named argument `precision` is not used by name
--> $DIR/issue-99265.rs:23:57
@@ -103,31 +103,31 @@ help: use the named argument by name to avoid ambiguity
LL | println!("Hello {:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
| ~~~~~~~~~~
-warning: named argument `f` is not used by name
- --> $DIR/issue-99265.rs:23:33
+warning: named argument `width` is not used by name
+ --> $DIR/issue-99265.rs:23:46
|
LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | -- ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `f` by position
+ | -- ^^^^^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `width` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | +
+LL | println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
+ | ~~~~~~
-warning: named argument `width` is not used by name
- --> $DIR/issue-99265.rs:31:47
+warning: named argument `f` is not used by name
+ --> $DIR/issue-99265.rs:31:34
|
LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | -- ^^^^^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `width` by position
+ | --------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `f` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | ~~~~~~
+LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
+ | ~
warning: named argument `precision` is not used by name
--> $DIR/issue-99265.rs:31:58
@@ -142,32 +142,32 @@ help: use the named argument by name to avoid ambiguity
LL | println!("Hello {0:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
| ~~~~~~~~~~
-warning: named argument `f` is not used by name
- --> $DIR/issue-99265.rs:31:34
+warning: named argument `width` is not used by name
+ --> $DIR/issue-99265.rs:31:47
|
LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | - ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `f` by position
+ | -- ^^^^^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `width` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
- | ~
+LL | println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
+ | ~~~~~~
-warning: named argument `width` is not used by name
- --> $DIR/issue-99265.rs:52:9
+warning: named argument `f` is not used by name
+ --> $DIR/issue-99265.rs:49:9
|
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
- | -- this formatting argument uses named argument `width` by position
+ | --------- this formatting argument uses named argument `f` by position
...
-LL | width = 5,
- | ^^^^^ this named argument is referred to by position in formatting string
+LL | f = 0.02f32,
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
- | ~~~~~~
+LL | "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
+ | ~
warning: named argument `precision` is not used by name
--> $DIR/issue-99265.rs:54:9
@@ -183,33 +183,33 @@ help: use the named argument by name to avoid ambiguity
LL | "{}, Hello {1:2$.precision$} {4:5$.6$}! {1}",
| ~~~~~~~~~~
-warning: named argument `f` is not used by name
- --> $DIR/issue-99265.rs:49:9
+warning: named argument `width` is not used by name
+ --> $DIR/issue-99265.rs:52:9
|
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
- | - this formatting argument uses named argument `f` by position
+ | -- this formatting argument uses named argument `width` by position
...
-LL | f = 0.02f32,
- | ^ this named argument is referred to by position in formatting string
+LL | width = 5,
+ | ^^^^^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
- | ~
+LL | "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
+ | ~~~~~~
-warning: named argument `width2` is not used by name
- --> $DIR/issue-99265.rs:58:9
+warning: named argument `g` is not used by name
+ --> $DIR/issue-99265.rs:56:9
|
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
- | -- this formatting argument uses named argument `width2` by position
+ | --------- this formatting argument uses named argument `g` by position
...
-LL | width2 = 5,
- | ^^^^^^ this named argument is referred to by position in formatting string
+LL | g = 0.02f32,
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
- | ~~~~~~~
+LL | "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
+ | ~
warning: named argument `precision2` is not used by name
--> $DIR/issue-99265.rs:60:9
@@ -225,25 +225,25 @@ help: use the named argument by name to avoid ambiguity
LL | "{}, Hello {1:2$.3$} {4:5$.precision2$}! {1}",
| ~~~~~~~~~~~
-warning: named argument `g` is not used by name
- --> $DIR/issue-99265.rs:56:9
+warning: named argument `width2` is not used by name
+ --> $DIR/issue-99265.rs:58:9
|
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
- | - this formatting argument uses named argument `g` by position
+ | -- this formatting argument uses named argument `width2` by position
...
-LL | g = 0.02f32,
- | ^ this named argument is referred to by position in formatting string
+LL | width2 = 5,
+ | ^^^^^^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
- | ~
+LL | "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
+ | ~~~~~~~
warning: named argument `f` is not used by name
--> $DIR/issue-99265.rs:49:9
|
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
- | - this formatting argument uses named argument `f` by position
+ | --- this formatting argument uses named argument `f` by position
...
LL | f = 0.02f32,
| ^ this named argument is referred to by position in formatting string
@@ -257,7 +257,7 @@ warning: named argument `f` is not used by name
--> $DIR/issue-99265.rs:64:31
|
LL | println!("Hello {:0.1}!", f = 0.02f32);
- | -- ^ this named argument is referred to by position in formatting string
+ | ------ ^ this named argument is referred to by position in formatting string
| |
| this formatting argument uses named argument `f` by position
|
@@ -270,9 +270,9 @@ warning: named argument `f` is not used by name
--> $DIR/issue-99265.rs:68:32
|
LL | println!("Hello {0:0.1}!", f = 0.02f32);
- | - ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `f` by position
+ | ------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `f` by position
|
help: use the named argument by name to avoid ambiguity
|
@@ -283,6 +283,19 @@ warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:79:23
|
LL | println!("{:0$}", v = val);
+ | ----- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `v` by position
+ |
+help: use the named argument by name to avoid ambiguity
+ |
+LL | println!("{v:0$}", v = val);
+ | +
+
+warning: named argument `v` is not used by name
+ --> $DIR/issue-99265.rs:79:23
+ |
+LL | println!("{:0$}", v = val);
| -- ^ this named argument is referred to by position in formatting string
| |
| this formatting argument uses named argument `v` by position
@@ -293,17 +306,17 @@ LL | println!("{:v$}", v = val);
| ~~
warning: named argument `v` is not used by name
- --> $DIR/issue-99265.rs:79:23
+ --> $DIR/issue-99265.rs:84:24
|
-LL | println!("{:0$}", v = val);
- | -- ^ this named argument is referred to by position in formatting string
+LL | println!("{0:0$}", v = val);
+ | ------ ^ this named argument is referred to by position in formatting string
| |
| this formatting argument uses named argument `v` by position
|
help: use the named argument by name to avoid ambiguity
|
LL | println!("{v:0$}", v = val);
- | +
+ | ~
warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:84:24
@@ -319,30 +332,17 @@ LL | println!("{0:v$}", v = val);
| ~~
warning: named argument `v` is not used by name
- --> $DIR/issue-99265.rs:84:24
- |
-LL | println!("{0:0$}", v = val);
- | - ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `v` by position
- |
-help: use the named argument by name to avoid ambiguity
- |
-LL | println!("{v:0$}", v = val);
- | ~
-
-warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:89:26
|
LL | println!("{:0$.0$}", v = val);
- | -- ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `v` by position
+ | -------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `v` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{:v$.0$}", v = val);
- | ~~
+LL | println!("{v:0$.0$}", v = val);
+ | +
warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:89:26
@@ -361,27 +361,27 @@ warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:89:26
|
LL | println!("{:0$.0$}", v = val);
- | -- ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `v` by position
+ | -- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `v` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{v:0$.0$}", v = val);
- | +
+LL | println!("{:v$.0$}", v = val);
+ | ~~
warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:96:27
|
LL | println!("{0:0$.0$}", v = val);
- | -- ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `v` by position
+ | --------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `v` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{0:v$.0$}", v = val);
- | ~~
+LL | println!("{v:0$.0$}", v = val);
+ | ~
warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:96:27
@@ -400,14 +400,14 @@ warning: named argument `v` is not used by name
--> $DIR/issue-99265.rs:96:27
|
LL | println!("{0:0$.0$}", v = val);
- | - ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `v` by position
+ | -- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `v` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{v:0$.0$}", v = val);
- | ~
+LL | println!("{0:v$.0$}", v = val);
+ | ~~
warning: named argument `a` is not used by name
--> $DIR/issue-99265.rs:104:28
@@ -426,28 +426,28 @@ warning: named argument `a` is not used by name
--> $DIR/issue-99265.rs:104:28
|
LL | println!("{} {a} {0}", a = 1);
- | - ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `a` by position
+ | --- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `a` by position
|
help: use the named argument by name to avoid ambiguity
|
LL | println!("{} {a} {a}", a = 1);
| ~
-warning: named argument `b` is not used by name
- --> $DIR/issue-99265.rs:115:23
+warning: named argument `a` is not used by name
+ --> $DIR/issue-99265.rs:115:14
|
LL | {:1$.2$}",
- | -- this formatting argument uses named argument `b` by position
+ | -------- this formatting argument uses named argument `a` by position
...
LL | a = 1.0, b = 1, c = 2,
- | ^ this named argument is referred to by position in formatting string
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | {:b$.2$}",
- | ~~
+LL | {a:1$.2$}",
+ | +
warning: named argument `c` is not used by name
--> $DIR/issue-99265.rs:115:30
@@ -463,33 +463,33 @@ help: use the named argument by name to avoid ambiguity
LL | {:1$.c$}",
| ~~
-warning: named argument `a` is not used by name
- --> $DIR/issue-99265.rs:115:14
+warning: named argument `b` is not used by name
+ --> $DIR/issue-99265.rs:115:23
|
LL | {:1$.2$}",
- | -- this formatting argument uses named argument `a` by position
+ | -- this formatting argument uses named argument `b` by position
...
LL | a = 1.0, b = 1, c = 2,
- | ^ this named argument is referred to by position in formatting string
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | {a:1$.2$}",
- | +
+LL | {:b$.2$}",
+ | ~~
-warning: named argument `b` is not used by name
- --> $DIR/issue-99265.rs:126:23
+warning: named argument `a` is not used by name
+ --> $DIR/issue-99265.rs:126:14
|
LL | {0:1$.2$}",
- | -- this formatting argument uses named argument `b` by position
+ | --------- this formatting argument uses named argument `a` by position
...
LL | a = 1.0, b = 1, c = 2,
- | ^ this named argument is referred to by position in formatting string
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | {0:b$.2$}",
- | ~~
+LL | {a:1$.2$}",
+ | ~
warning: named argument `c` is not used by name
--> $DIR/issue-99265.rs:126:30
@@ -505,32 +505,32 @@ help: use the named argument by name to avoid ambiguity
LL | {0:1$.c$}",
| ~~
-warning: named argument `a` is not used by name
- --> $DIR/issue-99265.rs:126:14
+warning: named argument `b` is not used by name
+ --> $DIR/issue-99265.rs:126:23
|
LL | {0:1$.2$}",
- | - this formatting argument uses named argument `a` by position
+ | -- this formatting argument uses named argument `b` by position
...
LL | a = 1.0, b = 1, c = 2,
- | ^ this named argument is referred to by position in formatting string
+ | ^ this named argument is referred to by position in formatting string
|
help: use the named argument by name to avoid ambiguity
|
-LL | {a:1$.2$}",
- | ~
+LL | {0:b$.2$}",
+ | ~~
-warning: named argument `width` is not used by name
- --> $DIR/issue-99265.rs:132:39
+warning: named argument `x` is not used by name
+ --> $DIR/issue-99265.rs:132:30
|
LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
- | -- ^^^^^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `width` by position
+ | -------- ^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `x` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
- | ~~~~~~
+LL | println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
+ | +
warning: named argument `precision` is not used by name
--> $DIR/issue-99265.rs:132:50
@@ -545,18 +545,18 @@ help: use the named argument by name to avoid ambiguity
LL | println!("{{{:1$.precision$}}}", x = 1.0, width = 3, precision = 2);
| ~~~~~~~~~~
-warning: named argument `x` is not used by name
- --> $DIR/issue-99265.rs:132:30
+warning: named argument `width` is not used by name
+ --> $DIR/issue-99265.rs:132:39
|
LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
- | -- ^ this named argument is referred to by position in formatting string
- | |
- | this formatting argument uses named argument `x` by position
+ | -- ^^^^^ this named argument is referred to by position in formatting string
+ | |
+ | this formatting argument uses named argument `width` by position
|
help: use the named argument by name to avoid ambiguity
|
-LL | println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
- | +
+LL | println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
+ | ~~~~~~
warning: 42 warnings emitted
diff --git a/src/test/ui/macros/issue-99907.stderr b/src/test/ui/macros/issue-99907.stderr
index 4786ce003..eefb28dee 100644
--- a/src/test/ui/macros/issue-99907.stderr
+++ b/src/test/ui/macros/issue-99907.stderr
@@ -2,7 +2,7 @@ warning: named argument `f` is not used by name
--> $DIR/issue-99907.rs:5:30
|
LL | println!("Hello {:.1}!", f = 0.02f32);
- | -- ^ this named argument is referred to by position in formatting string
+ | ----- ^ this named argument is referred to by position in formatting string
| |
| this formatting argument uses named argument `f` by position
|
@@ -16,7 +16,7 @@ warning: named argument `f` is not used by name
--> $DIR/issue-99907.rs:9:31
|
LL | println!("Hello {:1.1}!", f = 0.02f32);
- | -- ^ this named argument is referred to by position in formatting string
+ | ------ ^ this named argument is referred to by position in formatting string
| |
| this formatting argument uses named argument `f` by position
|
diff --git a/src/test/ui/macros/lint-trailing-macro-call.stderr b/src/test/ui/macros/lint-trailing-macro-call.stderr
index a98a559c8..6ab121f7c 100644
--- a/src/test/ui/macros/lint-trailing-macro-call.stderr
+++ b/src/test/ui/macros/lint-trailing-macro-call.stderr
@@ -7,11 +7,11 @@ LL | #[cfg(FALSE)] 25;
LL | expand_it!()
| ------------ in this macro invocation
|
- = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
= note: macro invocations at the end of a block are treated as expressions
= note: to ignore the value produced by the macro, add a semicolon after the invocation of `expand_it`
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= note: this warning originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted
diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs
index dfd58b25d..8406b4e78 100644
--- a/src/test/ui/macros/macro-comma-behavior-rpass.rs
+++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs
@@ -14,7 +14,6 @@
// compile-flags: --test -C debug_assertions=yes
// revisions: std core
-// ignore-wasm32-bare compiled with panic=abort by default
#![cfg_attr(core, no_std)]
#[cfg(core)]
diff --git a/src/test/ui/macros/macro-context.stderr b/src/test/ui/macros/macro-context.stderr
index 5dc178070..f597c398b 100644
--- a/src/test/ui/macros/macro-context.stderr
+++ b/src/test/ui/macros/macro-context.stderr
@@ -57,7 +57,7 @@ error[E0425]: cannot find value `i` in this scope
--> $DIR/macro-context.rs:3:13
|
LL | () => ( i ; typeof );
- | ^ help: a local variable with a similar name exists: `a`
+ | ^ not found in this scope
...
LL | let i = m!();
| ---- in this macro invocation
@@ -73,9 +73,9 @@ LL | () => ( i ; typeof );
LL | let i = m!();
| ---- in this macro invocation
|
- = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 6 previous errors; 1 warning emitted
diff --git a/src/test/ui/macros/macro-in-expression-context.stderr b/src/test/ui/macros/macro-in-expression-context.stderr
index 1840babd6..1023189ea 100644
--- a/src/test/ui/macros/macro-in-expression-context.stderr
+++ b/src/test/ui/macros/macro-in-expression-context.stderr
@@ -20,11 +20,11 @@ LL | assert_eq!("A", "A");
LL | foo!()
| ------ in this macro invocation
|
- = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
= note: macro invocations at the end of a block are treated as expressions
= note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo`
+ = note: `#[warn(semicolon_in_expressions_from_macros)]` on by default
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/macros/macro-match-nonterminal.stderr b/src/test/ui/macros/macro-match-nonterminal.stderr
index 48b9bc6ff..ef7261c02 100644
--- a/src/test/ui/macros/macro-match-nonterminal.stderr
+++ b/src/test/ui/macros/macro-match-nonterminal.stderr
@@ -10,9 +10,9 @@ error: missing fragment specifier
LL | ($a, $b) => {
| ^
|
- = note: `#[deny(missing_fragment_specifier)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+ = note: `#[deny(missing_fragment_specifier)]` on by default
error: missing fragment specifier
--> $DIR/macro-match-nonterminal.rs:2:10
diff --git a/src/test/ui/macros/macro-missing-fragment-deduplication.stderr b/src/test/ui/macros/macro-missing-fragment-deduplication.stderr
index 7622ca054..3b9e716e1 100644
--- a/src/test/ui/macros/macro-missing-fragment-deduplication.stderr
+++ b/src/test/ui/macros/macro-missing-fragment-deduplication.stderr
@@ -10,9 +10,9 @@ error: missing fragment specifier
LL | ($name) => {}
| ^^^^^
|
- = note: `#[deny(missing_fragment_specifier)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+ = note: `#[deny(missing_fragment_specifier)]` on by default
error: aborting due to 2 previous errors
diff --git a/src/test/ui/macros/macro-missing-fragment.stderr b/src/test/ui/macros/macro-missing-fragment.stderr
index 1bf6f04ec..2aa1e58f6 100644
--- a/src/test/ui/macros/macro-missing-fragment.stderr
+++ b/src/test/ui/macros/macro-missing-fragment.stderr
@@ -10,13 +10,13 @@ warning: missing fragment specifier
LL | ( $( any_token $field_rust_type )* ) => {};
| ^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
note: the lint level is defined here
--> $DIR/macro-missing-fragment.rs:1:9
|
LL | #![warn(missing_fragment_specifier)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
warning: missing fragment specifier
--> $DIR/macro-missing-fragment.rs:12:7
diff --git a/src/test/ui/macros/macro-or-patterns-back-compat.stderr b/src/test/ui/macros/macro-or-patterns-back-compat.stderr
index 9a5b8009f..e04dfefa4 100644
--- a/src/test/ui/macros/macro-or-patterns-back-compat.stderr
+++ b/src/test/ui/macros/macro-or-patterns-back-compat.stderr
@@ -4,13 +4,13 @@ error: the meaning of the `pat` fragment specifier is changing in Rust 2021, whi
LL | macro_rules! foo { ($x:pat | $y:pat) => {} }
| ^^^^^^ help: use pat_param to preserve semantics: `$x:pat_param`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
note: the lint level is defined here
--> $DIR/macro-or-patterns-back-compat.rs:4:9
|
LL | #![deny(rust_2021_incompatible_or_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/or-patterns-macro-rules.html>
error: the meaning of the `pat` fragment specifier is changing in Rust 2021, which may affect this macro
--> $DIR/macro-or-patterns-back-compat.rs:13:23
diff --git a/src/test/ui/macros/macro-use-all-and-none.stderr b/src/test/ui/macros/macro-use-all-and-none.stderr
index 6de7ffb2f..00b10dccd 100644
--- a/src/test/ui/macros/macro-use-all-and-none.stderr
+++ b/src/test/ui/macros/macro-use-all-and-none.stderr
@@ -4,12 +4,12 @@ warning: unused attribute
LL | #[macro_use()]
| ^^^^^^^^^^^^^^ help: remove this attribute
|
+ = note: attribute `macro_use` with an empty list has no effect
note: the lint level is defined here
--> $DIR/macro-use-all-and-none.rs:4:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
- = note: attribute `macro_use` with an empty list has no effect
warning: 1 warning emitted
diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.rs b/src/test/ui/macros/macro_rules-unmatchable-literals.rs
new file mode 100644
index 000000000..bde0fe1a0
--- /dev/null
+++ b/src/test/ui/macros/macro_rules-unmatchable-literals.rs
@@ -0,0 +1,14 @@
+// Pinning tests for things that don't work to make sure we notice if that changes
+
+#![crate_type = "lib"]
+
+macro_rules! octal_with_bad_digit {
+ ( 0o1238 ) => {}; //~ ERROR invalid digit
+}
+
+macro_rules! binary_with_bad_digit {
+ ( 0b012 ) => {}; //~ ERROR invalid digit
+}
+
+// This can't happen for Hex and Decimal as things like `123A` and `0xFFG`
+// get treated as unknown *suffixes*, rather than digits.
diff --git a/src/test/ui/macros/macro_rules-unmatchable-literals.stderr b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr
new file mode 100644
index 000000000..956a66979
--- /dev/null
+++ b/src/test/ui/macros/macro_rules-unmatchable-literals.stderr
@@ -0,0 +1,14 @@
+error: invalid digit for a base 8 literal
+ --> $DIR/macro_rules-unmatchable-literals.rs:6:12
+ |
+LL | ( 0o1238 ) => {};
+ | ^
+
+error: invalid digit for a base 2 literal
+ --> $DIR/macro_rules-unmatchable-literals.rs:10:11
+ |
+LL | ( 0b012 ) => {};
+ | ^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macros/macros-nonfatal-errors.rs b/src/test/ui/macros/macros-nonfatal-errors.rs
index e7a01f105..ab14c3589 100644
--- a/src/test/ui/macros/macros-nonfatal-errors.rs
+++ b/src/test/ui/macros/macros-nonfatal-errors.rs
@@ -4,7 +4,7 @@
// immediately, so that we get more errors listed at a time.
#![feature(trace_macros, concat_idents)]
-#![feature(stmt_expr_attributes, arbitrary_enum_discriminant)]
+#![feature(stmt_expr_attributes)]
use std::arch::asm;
@@ -116,3 +116,24 @@ fn main() {
trace_macros!(invalid); //~ ERROR
}
+
+/// Check that `#[derive(Default)]` does use a `T : Default` bound when the
+/// `#[default]` variant is `#[non_exhaustive]` (should this end up allowed).
+const _: () = {
+ #[derive(Default)]
+ enum NonExhaustiveDefaultGeneric<T> {
+ #[default]
+ #[non_exhaustive]
+ Foo, //~ ERROR default variant must be exhaustive
+ Bar(T),
+ }
+
+ fn assert_impls_default<T: Default>() {}
+
+ enum NotDefault {}
+
+ // Note: the `derive(Default)` currently bails early enough for trait-checking
+ // not to happen. Should it bail late enough, or even pass, make sure to
+ // assert that the following line fails.
+ let _ = assert_impls_default::<NonExhaustiveDefaultGeneric<NotDefault>>;
+};
diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr
index b3c6d07f9..d42f6c179 100644
--- a/src/test/ui/macros/macros-nonfatal-errors.stderr
+++ b/src/test/ui/macros/macros-nonfatal-errors.stderr
@@ -215,11 +215,21 @@ error: trace_macros! accepts only `true` or `false`
LL | trace_macros!(invalid);
| ^^^^^^^^^^^^^^^^^^^^^^
+error: default variant must be exhaustive
+ --> $DIR/macros-nonfatal-errors.rs:127:9
+ |
+LL | #[non_exhaustive]
+ | ----------------- declared `#[non_exhaustive]` here
+LL | Foo,
+ | ^^^
+ |
+ = help: consider a manual implementation of `Default`
+
error: cannot find macro `llvm_asm` in this scope
--> $DIR/macros-nonfatal-errors.rs:99:5
|
LL | llvm_asm!(invalid);
| ^^^^^^^^
-error: aborting due to 27 previous errors
+error: aborting due to 28 previous errors
diff --git a/src/test/ui/macros/must-use-in-macro-55516.stderr b/src/test/ui/macros/must-use-in-macro-55516.stderr
index b56b00cc7..8878b0eea 100644
--- a/src/test/ui/macros/must-use-in-macro-55516.stderr
+++ b/src/test/ui/macros/must-use-in-macro-55516.stderr
@@ -4,8 +4,8 @@ warning: unused `Result` that must be used
LL | write!(&mut example, "{}", 42);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-W unused-must-use` implied by `-W unused`
= note: this `Result` may be an `Err` variant, which should be handled
+ = note: `-W unused-must-use` implied by `-W unused`
= note: this warning originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: 1 warning emitted
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
index f538ec643..b8b6f0846 100644
--- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
@@ -2,6 +2,7 @@
// ignore-tidy-linelength
// only-x86_64
// run-pass
+// needs-unwind Asserting on contents of error message
#![allow(path_statements, unused_allocation)]
#![feature(box_syntax, core_intrinsics, generic_assert, generic_assert_internals)]
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
index 86697c58f..d46f396ee 100644
--- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
@@ -2,6 +2,7 @@
// ignore-tidy-linelength
// only-x86_64
// run-pass
+// needs-unwind Asserting on contents of error message
#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
diff --git a/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
index 06c4993ec..1f5a29ab5 100644
--- a/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
+++ b/src/test/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
@@ -1,6 +1,7 @@
// aux-build:common.rs
// only-x86_64
// run-pass
+// needs-unwind Asserting on contents of error message
#![feature(core_intrinsics, generic_assert, generic_assert_internals)]
diff --git a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
index 0188938a3..a6cff95fd 100644
--- a/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
+++ b/src/test/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr
@@ -319,11 +319,11 @@ LL | unknown_metavar!(a);
|
= note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0425]: cannot find function `count` in this scope
- --> $DIR/syntax-errors.rs:29:30
+error[E0425]: cannot find value `i` in this scope
+ --> $DIR/syntax-errors.rs:29:36
|
LL | ( $( $i:ident ),* ) => { count(i) };
- | ^^^^^ not found in this scope
+ | ^ not found in this scope
...
LL | no_curly__no_rhs_dollar__round!(a, b, c);
| ---------------------------------------- in this macro invocation
@@ -331,10 +331,27 @@ LL | no_curly__no_rhs_dollar__round!(a, b, c);
= note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0425]: cannot find value `i` in this scope
- --> $DIR/syntax-errors.rs:29:36
+ --> $DIR/syntax-errors.rs:35:29
+ |
+LL | ( $i:ident ) => { count(i) };
+ | ^ not found in this scope
+...
+LL | no_curly__no_rhs_dollar__no_round!(a);
+ | ------------------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0425]: cannot find value `a` in this scope
+ --> $DIR/syntax-errors.rs:153:37
+ |
+LL | no_curly__rhs_dollar__no_round!(a);
+ | ^ not found in this scope
+
+error[E0425]: cannot find function `count` in this scope
+ --> $DIR/syntax-errors.rs:29:30
|
LL | ( $( $i:ident ),* ) => { count(i) };
- | ^ not found in this scope
+ | ^^^^^ not found in this scope
...
LL | no_curly__no_rhs_dollar__round!(a, b, c);
| ---------------------------------------- in this macro invocation
@@ -352,17 +369,6 @@ LL | no_curly__no_rhs_dollar__no_round!(a);
|
= note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0425]: cannot find value `i` in this scope
- --> $DIR/syntax-errors.rs:35:29
- |
-LL | ( $i:ident ) => { count(i) };
- | ^ not found in this scope
-...
-LL | no_curly__no_rhs_dollar__no_round!(a);
- | ------------------------------------- in this macro invocation
- |
- = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
-
error[E0425]: cannot find function `count` in this scope
--> $DIR/syntax-errors.rs:46:23
|
@@ -374,12 +380,6 @@ LL | no_curly__rhs_dollar__no_round!(a);
|
= note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info)
-error[E0425]: cannot find value `a` in this scope
- --> $DIR/syntax-errors.rs:153:37
- |
-LL | no_curly__rhs_dollar__no_round!(a);
- | ^ not found in this scope
-
error: aborting due to 40 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs
index dd159cb5b..bc0d44881 100644
--- a/src/test/ui/macros/stringify.rs
+++ b/src/test/ui/macros/stringify.rs
@@ -8,7 +8,6 @@
#![feature(const_trait_impl)]
#![feature(decl_macro)]
#![feature(generators)]
-#![feature(half_open_range_patterns)]
#![feature(more_qualified_paths)]
#![feature(raw_ref_op)]
#![feature(trait_alias)]
diff --git a/src/test/ui/macros/syntax-error-recovery.rs b/src/test/ui/macros/syntax-error-recovery.rs
new file mode 100644
index 000000000..ae6de3c50
--- /dev/null
+++ b/src/test/ui/macros/syntax-error-recovery.rs
@@ -0,0 +1,18 @@
+macro_rules! values {
+ ($($token:ident($value:literal) $(as $inner:ty)? => $attr:meta,)*) => {
+ #[derive(Debug)]
+ pub enum TokenKind {
+ $(
+ #[$attr]
+ $token $($inner)? = $value,
+ )*
+ }
+ };
+}
+//~^^^^^ ERROR expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
+//~| ERROR macro expansion ignores token `(String)` and any following
+
+values!(STRING(1) as (String) => cfg(test),);
+//~^ ERROR expected one of `!` or `::`, found `<eof>`
+
+fn main() {}
diff --git a/src/test/ui/macros/syntax-error-recovery.stderr b/src/test/ui/macros/syntax-error-recovery.stderr
new file mode 100644
index 000000000..c153b3b91
--- /dev/null
+++ b/src/test/ui/macros/syntax-error-recovery.stderr
@@ -0,0 +1,30 @@
+error: expected one of `(`, `,`, `=`, `{`, or `}`, found `(String)`
+ --> $DIR/syntax-error-recovery.rs:7:26
+ |
+LL | $token $($inner)? = $value,
+ | ^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}`
+...
+LL | values!(STRING(1) as (String) => cfg(test),);
+ | -------------------------------------------- in this macro invocation
+ |
+ = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: macro expansion ignores token `(String)` and any following
+ --> $DIR/syntax-error-recovery.rs:7:26
+ |
+LL | $token $($inner)? = $value,
+ | ^^^^^^
+...
+LL | values!(STRING(1) as (String) => cfg(test),);
+ | -------------------------------------------- caused by the macro expansion here
+ |
+ = note: the usage of `values!` is likely invalid in item context
+
+error: expected one of `!` or `::`, found `<eof>`
+ --> $DIR/syntax-error-recovery.rs:15:9
+ |
+LL | values!(STRING(1) as (String) => cfg(test),);
+ | ^^^^^^ expected one of `!` or `::`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/malformed/malformed-regressions.stderr b/src/test/ui/malformed/malformed-regressions.stderr
index 8c2625bdf..9bfbe7eba 100644
--- a/src/test/ui/malformed/malformed-regressions.stderr
+++ b/src/test/ui/malformed/malformed-regressions.stderr
@@ -4,9 +4,9 @@ error: attribute must be of the form `#[doc(hidden|inline|...)]` or `#[doc = "st
LL | #[doc]
| ^^^^^^
|
- = note: `#[deny(ill_formed_attribute_input)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
+ = note: `#[deny(ill_formed_attribute_input)]` on by default
error: attribute must be of the form `#[ignore]` or `#[ignore = "reason"]`
--> $DIR/malformed-regressions.rs:3:1
diff --git a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
index fca986627..649e58915 100644
--- a/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
+++ b/src/test/ui/marker_trait_attr/overlap-doesnt-conflict-with-specialization.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs
new file mode 100644
index 000000000..62aa22d41
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs
@@ -0,0 +1,10 @@
+// check-pass
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait Marker {}
+
+impl Marker for &'static () {}
+impl Marker for &'static () {}
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs
new file mode 100644
index 000000000..eabce1aef
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs
@@ -0,0 +1,9 @@
+#![feature(marker_trait_attr)]
+
+#[marker]
+trait Marker {}
+
+impl Marker for &'_ () {} //~ ERROR type annotations needed
+impl Marker for &'_ () {} //~ ERROR type annotations needed
+
+fn main() {}
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr
new file mode 100644
index 000000000..235c89e20
--- /dev/null
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr
@@ -0,0 +1,31 @@
+error[E0283]: type annotations needed: cannot satisfy `&(): Marker`
+ --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:6
+ |
+LL | impl Marker for &'_ () {}
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `&(): Marker` found
+ --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1
+ |
+LL | impl Marker for &'_ () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Marker for &'_ () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0283]: type annotations needed: cannot satisfy `&(): Marker`
+ --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:6
+ |
+LL | impl Marker for &'_ () {}
+ | ^^^^^^
+ |
+note: multiple `impl`s satisfying `&(): Marker` found
+ --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1
+ |
+LL | impl Marker for &'_ () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+LL | impl Marker for &'_ () {}
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.rs b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs
index 8794d42f4..67e551797 100644
--- a/src/test/ui/marker_trait_attr/overlap-marker-trait.rs
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.rs
@@ -7,7 +7,8 @@
use std::fmt::{Debug, Display};
-#[marker] trait Marker {}
+#[marker]
+trait Marker {}
impl<T: Debug> Marker for T {}
impl<T: Display> Marker for T {}
diff --git a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
index 1f3410597..133bc0484 100644
--- a/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
+++ b/src/test/ui/marker_trait_attr/overlap-marker-trait.stderr
@@ -1,11 +1,11 @@
error[E0277]: the trait bound `NotDebugOrDisplay: Marker` is not satisfied
- --> $DIR/overlap-marker-trait.rs:27:17
+ --> $DIR/overlap-marker-trait.rs:28:17
|
LL | is_marker::<NotDebugOrDisplay>();
| ^^^^^^^^^^^^^^^^^ the trait `Marker` is not implemented for `NotDebugOrDisplay`
|
note: required by a bound in `is_marker`
- --> $DIR/overlap-marker-trait.rs:15:17
+ --> $DIR/overlap-marker-trait.rs:16:17
|
LL | fn is_marker<T: Marker>() { }
| ^^^^^^ required by this bound in `is_marker`
diff --git a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs
index 383313902..f7654458f 100644
--- a/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs
+++ b/src/test/ui/marker_trait_attr/overlap-permitted-for-annotated-marker-traits.rs
@@ -7,7 +7,8 @@
use std::fmt::{Debug, Display};
-#[marker] trait MyMarker {}
+#[marker]
+trait MyMarker {}
impl<T: Debug> MyMarker for T {}
impl<T: Display> MyMarker for T {}
diff --git a/src/test/ui/match/expr_before_ident_pat.rs b/src/test/ui/match/expr_before_ident_pat.rs
index 47db6c3f4..27ef3d05a 100644
--- a/src/test/ui/match/expr_before_ident_pat.rs
+++ b/src/test/ui/match/expr_before_ident_pat.rs
@@ -1,5 +1,3 @@
-#![feature(half_open_range_patterns)]
-
macro_rules! funny {
($a:expr, $b:ident) => {
match [1, 2] {
diff --git a/src/test/ui/match/expr_before_ident_pat.stderr b/src/test/ui/match/expr_before_ident_pat.stderr
index 2bd1b3b94..57a2d2b26 100644
--- a/src/test/ui/match/expr_before_ident_pat.stderr
+++ b/src/test/ui/match/expr_before_ident_pat.stderr
@@ -1,11 +1,11 @@
error[E0425]: cannot find value `a` in this scope
- --> $DIR/expr_before_ident_pat.rs:12:12
+ --> $DIR/expr_before_ident_pat.rs:10:12
|
LL | funny!(a, a);
| ^ not found in this scope
error: arbitrary expressions aren't allowed in patterns
- --> $DIR/expr_before_ident_pat.rs:12:12
+ --> $DIR/expr_before_ident_pat.rs:10:12
|
LL | funny!(a, a);
| ^
diff --git a/src/test/ui/match/issue-41255.rs b/src/test/ui/match/issue-41255.rs
index 9d7072f16..d163801fd 100644
--- a/src/test/ui/match/issue-41255.rs
+++ b/src/test/ui/match/issue-41255.rs
@@ -1,7 +1,6 @@
// Matching against float literals should result in a linter error
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
#![allow(unused)]
#![forbid(illegal_floating_point_literal_pattern)]
diff --git a/src/test/ui/match/issue-41255.stderr b/src/test/ui/match/issue-41255.stderr
index bf81c8d37..9bc49654e 100644
--- a/src/test/ui/match/issue-41255.stderr
+++ b/src/test/ui/match/issue-41255.stderr
@@ -1,19 +1,19 @@
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:11:9
+ --> $DIR/issue-41255.rs:10:9
|
LL | 5.0 => {},
| ^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
note: the lint level is defined here
- --> $DIR/issue-41255.rs:6:11
+ --> $DIR/issue-41255.rs:5:11
|
LL | #![forbid(illegal_floating_point_literal_pattern)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:13:9
+ --> $DIR/issue-41255.rs:12:9
|
LL | 5.0f32 => {},
| ^^^^^^
@@ -22,7 +22,7 @@ LL | 5.0f32 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:15:10
+ --> $DIR/issue-41255.rs:14:10
|
LL | -5.0 => {},
| ^^^
@@ -31,7 +31,7 @@ LL | -5.0 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:17:9
+ --> $DIR/issue-41255.rs:16:9
|
LL | 1.0 .. 33.0 => {},
| ^^^
@@ -40,7 +40,7 @@ LL | 1.0 .. 33.0 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:17:16
+ --> $DIR/issue-41255.rs:16:16
|
LL | 1.0 .. 33.0 => {},
| ^^^^
@@ -49,7 +49,7 @@ LL | 1.0 .. 33.0 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:21:9
+ --> $DIR/issue-41255.rs:20:9
|
LL | 39.0 ..= 70.0 => {},
| ^^^^
@@ -58,7 +58,7 @@ LL | 39.0 ..= 70.0 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:21:18
+ --> $DIR/issue-41255.rs:20:18
|
LL | 39.0 ..= 70.0 => {},
| ^^^^
@@ -67,7 +67,7 @@ LL | 39.0 ..= 70.0 => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:26:11
+ --> $DIR/issue-41255.rs:25:11
|
LL | ..71.0 => {}
| ^^^^
@@ -76,7 +76,7 @@ LL | ..71.0 => {}
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:29:12
+ --> $DIR/issue-41255.rs:28:12
|
LL | ..=72.0 => {}
| ^^^^
@@ -85,7 +85,7 @@ LL | ..=72.0 => {}
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:32:9
+ --> $DIR/issue-41255.rs:31:9
|
LL | 71.0.. => {}
| ^^^^
@@ -94,7 +94,7 @@ LL | 71.0.. => {}
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:40:10
+ --> $DIR/issue-41255.rs:39:10
|
LL | (3.14, 1) => {},
| ^^^^
@@ -103,7 +103,7 @@ LL | (3.14, 1) => {},
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
- --> $DIR/issue-41255.rs:47:18
+ --> $DIR/issue-41255.rs:46:18
|
LL | Foo { x: 2.0 } => {},
| ^^^
diff --git a/src/test/ui/match/issue-92100.rs b/src/test/ui/match/issue-92100.rs
index 021166b2b..baac570dd 100644
--- a/src/test/ui/match/issue-92100.rs
+++ b/src/test/ui/match/issue-92100.rs
@@ -1,4 +1,4 @@
-#![feature(half_open_range_patterns)]
+#![feature(half_open_range_patterns_in_slices)]
fn main() {
match [1, 2] {
diff --git a/src/test/ui/methods/issues/issue-90315.rs b/src/test/ui/methods/issues/issue-90315.rs
index 01bf9f484..79cdc4195 100644
--- a/src/test/ui/methods/issues/issue-90315.rs
+++ b/src/test/ui/methods/issues/issue-90315.rs
@@ -1,7 +1,76 @@
+#![allow(unused)]
fn main() {
- let arr = &[0,1,2,3];
- for _i in 0..arr.len().rev() { //~ERROR not an iterator
- // The above error used to say “the method `rev` exists for type `usize`”.
- // This regression test ensures it doesn't say that any more.
- }
+ let arr = &[0, 1, 2, 3];
+ for _i in 0..arr.len().rev() {
+ //~^ ERROR can't call method
+ //~| surround the range in parentheses
+ // The above error used to say “the method `rev` exists for type `usize`”.
+ // This regression test ensures it doesn't say that any more.
+ }
+
+ // Test for #102396
+ for i in 1..11.rev() {
+ //~^ ERROR can't call method
+ //~| HELP surround the range in parentheses
+ }
+
+ let end: usize = 10;
+ for i in 1..end.rev() {
+ //~^ ERROR can't call method
+ //~| HELP surround the range in parentheses
+ }
+
+ for i in 1..(end + 1).rev() {
+ //~^ ERROR can't call method
+ //~| HELP surround the range in parentheses
+ }
+
+ if 1..(end + 1).is_empty() {
+ //~^ ERROR can't call method
+ //~| ERROR mismatched types [E0308]
+ //~| HELP surround the range in parentheses
+ }
+
+ if 1..(end + 1).is_sorted() {
+ //~^ ERROR mismatched types [E0308]
+ //~| ERROR can't call method
+ //~| HELP surround the range in parentheses
+ }
+
+ let _res: i32 = 3..6.take(2).sum();
+ //~^ ERROR can't call method
+ //~| ERROR mismatched types [E0308]
+ //~| HELP surround the range in parentheses
+
+ let _sum: i32 = 3..6.sum();
+ //~^ ERROR can't call method
+ //~| ERROR mismatched types [E0308]
+ //~| HELP surround the range in parentheses
+
+ let a = 1 as usize;
+ let b = 10 as usize;
+
+ for _a in a..=b.rev() {
+ //~^ ERROR can't call method
+ //~| HELP surround the range in parentheses
+ }
+
+ let _res = ..10.contains(3);
+ //~^ ERROR can't call method
+ //~| HELP surround the range in parentheses
+
+ if 1..end.error_method() {
+ //~^ ERROR no method named `error_method`
+ //~| ERROR mismatched types [E0308]
+ // Won't suggest
+ }
+
+ let _res = b.take(1)..a;
+ //~^ ERROR `usize` is not an iterator
+
+ let _res: i32 = ..6.take(2).sum();
+ //~^ can't call method `take` on ambiguous numeric type
+ //~| ERROR mismatched types [E0308]
+ //~| HELP you must specify a concrete type for this numeric value
+ // Won't suggest because `RangeTo` dest not implemented `take`
}
diff --git a/src/test/ui/methods/issues/issue-90315.stderr b/src/test/ui/methods/issues/issue-90315.stderr
index c6a76c9e7..070cd3054 100644
--- a/src/test/ui/methods/issues/issue-90315.stderr
+++ b/src/test/ui/methods/issues/issue-90315.stderr
@@ -1,13 +1,201 @@
+error[E0689]: can't call method `rev` on type `usize`
+ --> $DIR/issue-90315.rs:4:28
+ |
+LL | for _i in 0..arr.len().rev() {
+ | ^^^ can't call method `rev` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `rev` function
+ |
+LL | for _i in (0..arr.len()).rev() {
+ | + +
+
+error[E0689]: can't call method `rev` on type `{integer}`
+ --> $DIR/issue-90315.rs:12:20
+ |
+LL | for i in 1..11.rev() {
+ | ^^^ can't call method `rev` on type `{integer}`
+ |
+help: you must surround the range in parentheses to call its `rev` function
+ |
+LL | for i in (1..11).rev() {
+ | + +
+
+error[E0689]: can't call method `rev` on type `usize`
+ --> $DIR/issue-90315.rs:18:21
+ |
+LL | for i in 1..end.rev() {
+ | ^^^ can't call method `rev` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `rev` function
+ |
+LL | for i in (1..end).rev() {
+ | + +
+
+error[E0689]: can't call method `rev` on type `usize`
+ --> $DIR/issue-90315.rs:23:27
+ |
+LL | for i in 1..(end + 1).rev() {
+ | ^^^ can't call method `rev` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `rev` function
+ |
+LL | for i in (1..(end + 1)).rev() {
+ | + +
+
+error[E0689]: can't call method `is_empty` on type `usize`
+ --> $DIR/issue-90315.rs:28:21
+ |
+LL | if 1..(end + 1).is_empty() {
+ | ^^^^^^^^ can't call method `is_empty` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `is_empty` function
+ |
+LL | if (1..(end + 1)).is_empty() {
+ | + +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:28:8
+ |
+LL | if 1..(end + 1).is_empty() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `is_sorted` on type `usize`
+ --> $DIR/issue-90315.rs:34:21
+ |
+LL | if 1..(end + 1).is_sorted() {
+ | ^^^^^^^^^ can't call method `is_sorted` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `is_sorted` function
+ |
+LL | if (1..(end + 1)).is_sorted() {
+ | + +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:34:8
+ |
+LL | if 1..(end + 1).is_sorted() {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `take` on type `{integer}`
+ --> $DIR/issue-90315.rs:40:26
+ |
+LL | let _res: i32 = 3..6.take(2).sum();
+ | ^^^^ can't call method `take` on type `{integer}`
+ |
+help: you must surround the range in parentheses to call its `take` function
+ |
+LL | let _res: i32 = (3..6).take(2).sum();
+ | + +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:40:21
+ |
+LL | let _res: i32 = 3..6.take(2).sum();
+ | --- ^^^^^^^^^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `sum` on type `{integer}`
+ --> $DIR/issue-90315.rs:45:26
+ |
+LL | let _sum: i32 = 3..6.sum();
+ | ^^^ can't call method `sum` on type `{integer}`
+ |
+help: you must surround the range in parentheses to call its `sum` function
+ |
+LL | let _sum: i32 = (3..6).sum();
+ | + +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:45:21
+ |
+LL | let _sum: i32 = 3..6.sum();
+ | --- ^^^^^^^^^^ expected `i32`, found struct `std::ops::Range`
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found struct `std::ops::Range<{integer}>`
+
+error[E0689]: can't call method `rev` on type `usize`
+ --> $DIR/issue-90315.rs:53:21
+ |
+LL | for _a in a..=b.rev() {
+ | ^^^ can't call method `rev` on type `usize`
+ |
+help: you must surround the range in parentheses to call its `rev` function
+ |
+LL | for _a in (a..=b).rev() {
+ | + +
+
+error[E0689]: can't call method `contains` on type `{integer}`
+ --> $DIR/issue-90315.rs:58:21
+ |
+LL | let _res = ..10.contains(3);
+ | ^^^^^^^^ can't call method `contains` on type `{integer}`
+ |
+help: you must surround the range in parentheses to call its `contains` function
+ |
+LL | let _res = (..10).contains(3);
+ | + +
+
+error[E0599]: no method named `error_method` found for type `usize` in the current scope
+ --> $DIR/issue-90315.rs:62:15
+ |
+LL | if 1..end.error_method() {
+ | ^^^^^^^^^^^^ method not found in `usize`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:62:8
+ |
+LL | if 1..end.error_method() {
+ | ^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found struct `std::ops::Range`
+ |
+ = note: expected type `bool`
+ found struct `std::ops::Range<{integer}>`
+
error[E0599]: `usize` is not an iterator
- --> $DIR/issue-90315.rs:3:26
+ --> $DIR/issue-90315.rs:68:18
|
-LL | for _i in 0..arr.len().rev() {
- | ^^^ `usize` is not an iterator
+LL | let _res = b.take(1)..a;
+ | ^^^^ `usize` is not an iterator
|
= note: the following trait bounds were not satisfied:
`usize: Iterator`
which is required by `&mut usize: Iterator`
-error: aborting due to previous error
+error[E0689]: can't call method `take` on ambiguous numeric type `{integer}`
+ --> $DIR/issue-90315.rs:71:25
+ |
+LL | let _res: i32 = ..6.take(2).sum();
+ | ^^^^
+ |
+help: you must specify a concrete type for this numeric value, like `i32`
+ |
+LL | let _res: i32 = ..6_i32.take(2).sum();
+ | ~~~~~
+
+error[E0308]: mismatched types
+ --> $DIR/issue-90315.rs:71:21
+ |
+LL | let _res: i32 = ..6.take(2).sum();
+ | --- ^^^^^^^^^^^^^^^^^ expected `i32`, found struct `RangeTo`
+ | |
+ | expected due to this
+ |
+ = note: expected type `i32`
+ found struct `RangeTo<_>`
+
+error: aborting due to 19 previous errors
-For more information about this error, try `rustc --explain E0599`.
+Some errors have detailed explanations: E0308, E0599, E0689.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
index 9e07d5ea3..394c1ac3c 100644
--- a/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-lint-fail.stderr
@@ -7,13 +7,13 @@ LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
LL | S.late::<'static>(&0, &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 #42868 <https://github.com/rust-lang/rust/issues/42868>
note: the lint level is defined here
--> $DIR/method-call-lifetime-args-lint-fail.rs:1:9
|
LL | #![deny(late_bound_lifetime_arguments)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-lint-fail.rs:26:14
diff --git a/src/test/ui/methods/method-call-lifetime-args-lint.stderr b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
index f31f510a3..b4fc2d717 100644
--- a/src/test/ui/methods/method-call-lifetime-args-lint.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-lint.stderr
@@ -7,13 +7,13 @@ LL | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
LL | S.late::<'static>(&0, &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 #42868 <https://github.com/rust-lang/rust/issues/42868>
note: the lint level is defined here
--> $DIR/method-call-lifetime-args-lint.rs:1:9
|
LL | #![deny(late_bound_lifetime_arguments)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/method-call-lifetime-args-lint.rs:16:23
diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
index 78af19586..62f20d6d5 100644
--- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -17,9 +17,9 @@ LL | 0.clone::<'a>();
LL | fn clone(&self) -> Self;
| - the late bound lifetime parameter is introduced here
|
- = note: `#[warn(late_bound_lifetime_arguments)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+ = note: `#[warn(late_bound_lifetime_arguments)]` on by default
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 59075397e..82addab94 100644
--- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals, unsized_fn_params)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24
diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr
index 7ae00835c..dd616c4a5 100644
--- a/src/test/ui/methods/method-macro-backtrace.stderr
+++ b/src/test/ui/methods/method-macro-backtrace.stderr
@@ -1,11 +1,11 @@
-error[E0201]: duplicate definitions with name `bar`:
+error[E0592]: duplicate definitions with name `bar`
--> $DIR/method-macro-backtrace.rs:22:5
|
LL | fn bar(&self) { }
- | ------------- previous definition of `bar` here
+ | ------------- other definition for `bar`
LL | fn bar(&self) { }
- | ^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^ duplicate definitions for `bar`
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0201`.
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
index fc7341a56..624b464ec 100644
--- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
+++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.rs
@@ -3,9 +3,9 @@
static A: () = {
let a: [String; 1];
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
a[0] = String::new();
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
//~| ERROR binding `a` isn't initialized
};
@@ -14,9 +14,9 @@ struct B<T>([T; 1]);
impl<T> B<T> {
pub const fn f(mut self, other: T) -> Self {
let _this = self;
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
self.0[0] = other;
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
//~| ERROR use of moved value
self
}
diff --git a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
index d8154f8d2..d96106172 100644
--- a/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
+++ b/src/test/ui/mir/drop-elaboration-after-borrowck-error.stderr
@@ -1,17 +1,17 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
--> $DIR/drop-elaboration-after-borrowck-error.rs:7:5
|
LL | a[0] = String::new();
| ^^^^
| |
- | statics cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in statics
| value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `[String; 1]` cannot be evaluated at compile-time
--> $DIR/drop-elaboration-after-borrowck-error.rs:5:9
|
LL | let a: [String; 1];
- | ^ statics cannot evaluate destructors
+ | ^ the destructor for this type cannot be evaluated in statics
...
LL | };
| - value is dropped here
@@ -24,21 +24,26 @@ LL | let a: [String; 1];
LL |
LL | a[0] = String::new();
| ^^^^ `a` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let a: [String; 1] = todo!();
+ | +++++++++
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/drop-elaboration-after-borrowck-error.rs:18:9
|
LL | self.0[0] = other;
| ^^^^^^^^^
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
| value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `B<T>` cannot be evaluated at compile-time
--> $DIR/drop-elaboration-after-borrowck-error.rs:16:13
|
LL | let _this = self;
- | ^^^^^ constant functions cannot evaluate destructors
+ | ^^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs
index 42eaab77d..9dc0acfbf 100644
--- a/src/test/ui/mir/mir_calls_to_shims.rs
+++ b/src/test/ui/mir/mir_calls_to_shims.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(fn_traits)]
#![feature(never_type)]
diff --git a/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs
index 3d2156105..19dba4970 100644
--- a/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs
+++ b/src/test/ui/mir/mir_codegen_calls_diverging_drops.rs
@@ -1,7 +1,6 @@
// run-fail
// error-pattern:diverging_fn called
// error-pattern:0 dropped
-// ignore-emscripten no processes
// needs-unwind this test checks that a destructor is called after panicking
struct Droppable(u8);
diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs
index 853efb0fe..75f5b171a 100644
--- a/src/test/ui/mir/mir_drop_order.rs
+++ b/src/test/ui/mir/mir_drop_order.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
use std::cell::RefCell;
use std::panic;
diff --git a/src/test/ui/mir/mir_drop_panics.rs b/src/test/ui/mir/mir_drop_panics.rs
index b4093d704..0d00426d6 100644
--- a/src/test/ui/mir/mir_drop_panics.rs
+++ b/src/test/ui/mir/mir_drop_panics.rs
@@ -2,7 +2,6 @@
// needs-unwind
// error-pattern:panic 1
// error-pattern:drop 2
-// ignore-emscripten no processes
struct Droppable(u32);
impl Drop for Droppable {
diff --git a/src/test/ui/mir/mir_let_chains_drop_order.rs b/src/test/ui/mir/mir_let_chains_drop_order.rs
index 6498a5195..6471553e9 100644
--- a/src/test/ui/mir/mir_let_chains_drop_order.rs
+++ b/src/test/ui/mir/mir_let_chains_drop_order.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// See `mir_drop_order.rs` for more information
@@ -13,7 +12,7 @@ use std::panic;
pub struct DropLogger<'a, T> {
extra: T,
id: usize,
- log: &'a panic::AssertUnwindSafe<RefCell<Vec<usize>>>
+ log: &'a panic::AssertUnwindSafe<RefCell<Vec<usize>>>,
}
impl<'a, T> Drop for DropLogger<'a, T> {
@@ -56,9 +55,9 @@ fn main() {
else {
// 10 is not constructed
d(10, None)
- }
+ },
);
- assert_eq!(get(), vec![3, 8, 7, 1, 2]);
+ assert_eq!(get(), vec![8, 7, 1, 3, 2]);
}
assert_eq!(get(), vec![0, 4, 6, 9, 5]);
@@ -90,5 +89,5 @@ fn main() {
panic::panic_any(InjectedFailure)
);
});
- assert_eq!(get(), vec![14, 19, 20, 17, 15, 11, 18, 16, 12, 13]);
+ assert_eq!(get(), vec![20, 17, 15, 11, 19, 18, 16, 12, 14, 13]);
}
diff --git a/src/test/ui/mir/thir-constparam-temp.stderr b/src/test/ui/mir/thir-constparam-temp.stderr
index ed2766c00..b77d67e08 100644
--- a/src/test/ui/mir/thir-constparam-temp.stderr
+++ b/src/test/ui/mir/thir-constparam-temp.stderr
@@ -4,7 +4,6 @@ warning: taking a mutable reference to a `const` item
LL | YIKES.mut_self()
| ^^^^^^^^^^^^^^^^
|
- = note: `#[warn(const_item_mutation)]` on by default
= note: each usage of a `const` item creates a new temporary
= note: the mutable reference will refer to this temporary, not the original `const` item
note: mutable reference created due to call to this method
@@ -17,6 +16,7 @@ note: `const` item defined here
|
LL | fn foo<const YIKES: Yikes>() {
| ^^^^^^^^^^^^^^^^^^
+ = note: `#[warn(const_item_mutation)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 71469bfec..92d545b73 100644
--- a/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -23,7 +23,7 @@ LL | a.iter().map(|_: &(u16, u16)| 45);
| expected due to this
|
= note: expected closure signature `fn(&(u32, u32)) -> _`
- found closure signature `for<'r> fn(&'r (u16, u16)) -> _`
+ found closure signature `for<'a> fn(&'a (u16, u16)) -> _`
note: required by a bound in `map`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr
index ef76ec63f..a7ef8fa08 100644
--- a/src/test/ui/mismatched_types/closure-mismatch.stderr
+++ b/src/test/ui/mismatched_types/closure-mismatch.stderr
@@ -13,7 +13,7 @@ error[E0308]: mismatched types
LL | baz(|_| ());
| ^^^^^^^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r> Fn<(&'r (),)>`
+ = note: expected trait `for<'a> Fn<(&'a (),)>`
found trait `Fn<(&(),)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/closure-mismatch.rs:8:9
diff --git a/src/test/ui/mismatched_types/fn-variance-1.stderr b/src/test/ui/mismatched_types/fn-variance-1.stderr
index eec6d83fe..5794e606e 100644
--- a/src/test/ui/mismatched_types/fn-variance-1.stderr
+++ b/src/test/ui/mismatched_types/fn-variance-1.stderr
@@ -10,7 +10,7 @@ LL | apply(&3, takes_mut);
| required by a bound introduced by this call
|
= note: expected function signature `fn(&{integer}) -> _`
- found function signature `for<'r> fn(&'r mut isize) -> _`
+ found function signature `for<'a> fn(&'a mut isize) -> _`
note: required by a bound in `apply`
--> $DIR/fn-variance-1.rs:5:37
|
@@ -29,7 +29,7 @@ LL | apply(&mut 3, takes_imm);
| required by a bound introduced by this call
|
= note: expected function signature `fn(&mut {integer}) -> _`
- found function signature `for<'r> fn(&'r isize) -> _`
+ found function signature `for<'a> fn(&'a isize) -> _`
note: required by a bound in `apply`
--> $DIR/fn-variance-1.rs:5:37
|
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index b11ea97d1..906001ca1 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -6,8 +6,8 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
| |
| expected due to this
|
- = note: expected closure signature `for<'r> fn(&'r &str) -> _`
- found closure signature `for<'r> fn(&'r str) -> _`
+ = note: expected closure signature `for<'a> fn(&'a &str) -> _`
+ found closure signature `for<'a> fn(&'a str) -> _`
note: required by a bound in `filter`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
diff --git a/src/test/ui/mismatched_types/show_module.rs b/src/test/ui/mismatched_types/show_module.rs
new file mode 100644
index 000000000..61550b887
--- /dev/null
+++ b/src/test/ui/mismatched_types/show_module.rs
@@ -0,0 +1,18 @@
+pub mod blah {
+ pub mod baz {
+ pub struct Foo;
+ }
+}
+
+pub mod meh {
+ pub struct Foo;
+}
+
+pub type Foo = blah::baz::Foo;
+
+fn foo() -> Foo {
+ meh::Foo
+ //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/show_module.stderr b/src/test/ui/mismatched_types/show_module.stderr
new file mode 100644
index 000000000..5e48e0955
--- /dev/null
+++ b/src/test/ui/mismatched_types/show_module.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/show_module.rs:14:5
+ |
+LL | fn foo() -> Foo {
+ | --- expected `baz::Foo` because of return type
+LL | meh::Foo
+ | ^^^^^^^^ expected struct `baz::Foo`, found struct `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
+ --> $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
+ --> $DIR/show_module.rs:3:9
+ |
+LL | pub struct Foo;
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/similar_paths.rs b/src/test/ui/mismatched_types/similar_paths.rs
new file mode 100644
index 000000000..4b9157f39
--- /dev/null
+++ b/src/test/ui/mismatched_types/similar_paths.rs
@@ -0,0 +1,11 @@
+enum Option<T> {
+ Some(T),
+ None,
+}
+
+pub fn foo() -> Option<u8> {
+ Some(42_u8)
+ //~^ ERROR mismatched types [E0308]
+}
+
+fn main() {}
diff --git a/src/test/ui/mismatched_types/similar_paths.stderr b/src/test/ui/mismatched_types/similar_paths.stderr
new file mode 100644
index 000000000..e65ae58d4
--- /dev/null
+++ b/src/test/ui/mismatched_types/similar_paths.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/similar_paths.rs:7:5
+ |
+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`
+ |
+ = 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`
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ |
+LL | pub enum Option<T> {
+ | ^^^^^^^^^^^^^^^^^^
+note: enum `Option` is defined in the current crate
+ --> $DIR/similar_paths.rs:1:1
+ |
+LL | enum Option<T> {
+ | ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/mismatched_types/similar_paths_primitive.rs b/src/test/ui/mismatched_types/similar_paths_primitive.rs
new file mode 100644
index 000000000..8f5b7cce4
--- /dev/null
+++ b/src/test/ui/mismatched_types/similar_paths_primitive.rs
@@ -0,0 +1,10 @@
+#![allow(non_camel_case_types)]
+
+struct bool;
+
+fn foo(_: bool) {}
+
+fn main() {
+ foo(true);
+ //~^ ERROR mismatched types [E0308]
+}
diff --git a/src/test/ui/mismatched_types/similar_paths_primitive.stderr b/src/test/ui/mismatched_types/similar_paths_primitive.stderr
new file mode 100644
index 000000000..8a2f73945
--- /dev/null
+++ b/src/test/ui/mismatched_types/similar_paths_primitive.stderr
@@ -0,0 +1,24 @@
+error[E0308]: mismatched types
+ --> $DIR/similar_paths_primitive.rs:8:9
+ |
+LL | foo(true);
+ | --- ^^^^ expected struct `bool`, found `bool`
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: bool and struct `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
+ --> $DIR/similar_paths_primitive.rs:3:1
+ |
+LL | struct bool;
+ | ^^^^^^^^^^^
+note: function defined here
+ --> $DIR/similar_paths_primitive.rs:5:4
+ |
+LL | fn foo(_: bool) {}
+ | ^^^ -------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/modules/special_module_name.stderr b/src/test/ui/modules/special_module_name.stderr
index 8b3da2938..bc4b4f1b3 100644
--- a/src/test/ui/modules/special_module_name.stderr
+++ b/src/test/ui/modules/special_module_name.stderr
@@ -20,9 +20,9 @@ warning: found module declaration for lib.rs
LL | mod lib;
| ^^^^^^^^
|
- = note: `#[warn(special_module_name)]` on by default
= note: lib.rs is the root of this crate's library target
= help: to refer to it from other targets, use the library's name as the path
+ = note: `#[warn(special_module_name)]` on by default
warning: found module declaration for main.rs
--> $DIR/special_module_name.rs:4:1
diff --git a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
index c7373b5be..974994223 100644
--- a/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/src/test/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -47,6 +47,11 @@ LL | let value: NonCopy;
| ----- binding declared here but left uninitialized
LL | let _used = value;
| ^^^^^ `value` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let value: NonCopy = todo!();
+ | +++++++++
error[E0381]: used binding `value` isn't initialized
--> $DIR/issue-72649-uninit-in-loop.rs:69:21
@@ -56,6 +61,11 @@ LL | let mut value: NonCopy;
LL | loop {
LL | let _used = value;
| ^^^^^ `value` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut value: NonCopy = todo!();
+ | +++++++++
error: aborting due to 6 previous errors
diff --git a/src/test/ui/moves/move-into-dead-array-1.stderr b/src/test/ui/moves/move-into-dead-array-1.stderr
index 344a6bbf0..6db0f0bcb 100644
--- a/src/test/ui/moves/move-into-dead-array-1.stderr
+++ b/src/test/ui/moves/move-into-dead-array-1.stderr
@@ -5,6 +5,11 @@ LL | let mut a: [D; 4];
| ----- binding declared here but left uninitialized
LL | a[i] = d();
| ^^^^ `a` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let mut a: [D; 4] = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/moves/move-of-addr-of-mut.stderr b/src/test/ui/moves/move-of-addr-of-mut.stderr
index e75f2b1c0..ddebaa012 100644
--- a/src/test/ui/moves/move-of-addr-of-mut.stderr
+++ b/src/test/ui/moves/move-of-addr-of-mut.stderr
@@ -7,6 +7,10 @@ LL | std::ptr::addr_of_mut!(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ `x` used here but it isn't initialized
|
= note: this error originates in the macro `std::ptr::addr_of_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider assigning a value
+ |
+LL | let mut x: S = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr
index 93b0dcfc2..46357ce6f 100644
--- a/src/test/ui/moves/move-out-of-slice-2.stderr
+++ b/src/test/ui/moves/move-out-of-slice-2.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0508]: cannot move out of type `[A]`, a non-copy slice
--> $DIR/move-out-of-slice-2.rs:10:11
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr
index f3dbcc2d7..227d30282 100644
--- a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls-xcrate.stderr
@@ -1,27 +1,27 @@
-error[E0425]: cannot find function `foo` in this scope
- --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:11:5
- |
-LL | foo();
- | ^^^ not found in this scope
-
error[E0425]: cannot find function `foo` in module `m`
--> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:12:8
|
LL | m::foo();
| ^^^ not found in `m`
-error[E0425]: cannot find function `bar` in this scope
- --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:13:5
- |
-LL | bar();
- | ^^^ not found in this scope
-
error[E0425]: cannot find function `bar` in module `m`
--> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:14:8
|
LL | m::bar();
| ^^^ not found in `m`
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:11:5
+ |
+LL | foo();
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find function `bar` in this scope
+ --> $DIR/namespaced-enum-glob-import-no-impls-xcrate.rs:13:5
+ |
+LL | bar();
+ | ^^^ not found in this scope
+
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr
index 98784de8e..111ac7ab0 100644
--- a/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr
+++ b/src/test/ui/namespace/namespaced-enum-glob-import-no-impls.stderr
@@ -1,27 +1,27 @@
-error[E0425]: cannot find function `foo` in this scope
- --> $DIR/namespaced-enum-glob-import-no-impls.rs:21:5
- |
-LL | foo();
- | ^^^ not found in this scope
-
error[E0425]: cannot find function `foo` in module `m`
--> $DIR/namespaced-enum-glob-import-no-impls.rs:22:8
|
LL | m::foo();
| ^^^ not found in `m`
-error[E0425]: cannot find function `bar` in this scope
- --> $DIR/namespaced-enum-glob-import-no-impls.rs:23:5
- |
-LL | bar();
- | ^^^ not found in this scope
-
error[E0425]: cannot find function `bar` in module `m`
--> $DIR/namespaced-enum-glob-import-no-impls.rs:24:8
|
LL | m::bar();
| ^^^ not found in `m`
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/namespaced-enum-glob-import-no-impls.rs:21:5
+ |
+LL | foo();
+ | ^^^ not found in this scope
+
+error[E0425]: cannot find function `bar` in this scope
+ --> $DIR/namespaced-enum-glob-import-no-impls.rs:23:5
+ |
+LL | bar();
+ | ^^^ not found in this scope
+
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/native-library-link-flags/suggest-libname-only-1.rs b/src/test/ui/native-library-link-flags/suggest-libname-only-1.rs
new file mode 100644
index 000000000..abf988a7c
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/suggest-libname-only-1.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: --crate-type rlib
+// error-pattern: could not find native static library `libfoo.a`
+// error-pattern: only provide the library name `foo`, not the full filename
+
+#[link(name = "libfoo.a", kind = "static")]
+extern { }
+
+pub fn main() { }
diff --git a/src/test/ui/native-library-link-flags/suggest-libname-only-1.stderr b/src/test/ui/native-library-link-flags/suggest-libname-only-1.stderr
new file mode 100644
index 000000000..64d0a9077
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/suggest-libname-only-1.stderr
@@ -0,0 +1,6 @@
+error: could not find native static library `libfoo.a`, perhaps an -L flag is missing?
+ |
+ = help: only provide the library name `foo`, not the full filename
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/native-library-link-flags/suggest-libname-only-2.rs b/src/test/ui/native-library-link-flags/suggest-libname-only-2.rs
new file mode 100644
index 000000000..dfa70e56d
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/suggest-libname-only-2.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: --crate-type rlib
+// error-pattern: could not find native static library `bar.lib`
+// error-pattern: only provide the library name `bar`, not the full filename
+
+#[link(name = "bar.lib", kind = "static")]
+extern { }
+
+pub fn main() { }
diff --git a/src/test/ui/native-library-link-flags/suggest-libname-only-2.stderr b/src/test/ui/native-library-link-flags/suggest-libname-only-2.stderr
new file mode 100644
index 000000000..e166af9ed
--- /dev/null
+++ b/src/test/ui/native-library-link-flags/suggest-libname-only-2.stderr
@@ -0,0 +1,6 @@
+error: could not find native static library `bar.lib`, perhaps an -L flag is missing?
+ |
+ = help: only provide the library name `bar`, not the full filename
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/never_type/issue-52443.rs b/src/test/ui/never_type/issue-52443.rs
index cebcca944..0498a8a16 100644
--- a/src/test/ui/never_type/issue-52443.rs
+++ b/src/test/ui/never_type/issue-52443.rs
@@ -9,6 +9,6 @@ fn main() {
[(); { for _ in 0usize.. {}; 0}];
//~^ ERROR `for` is not allowed in a `const`
//~| ERROR cannot convert
- //~| ERROR mutable references are not allowed in constants
- //~| ERROR cannot call non-const fn
+ //~| ERROR mutable references
+ //~| ERROR cannot call
}
diff --git a/src/test/ui/never_type/issue-52443.stderr b/src/test/ui/never_type/issue-52443.stderr
index 3c0daa4c5..0910e9ad7 100644
--- a/src/test/ui/never_type/issue-52443.stderr
+++ b/src/test/ui/never_type/issue-52443.stderr
@@ -47,8 +47,8 @@ LL | [(); { for _ in 0usize.. {}; 0}];
note: impl defined here, but it is not `const`
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
|
-LL | impl<I: ~const Iterator> const IntoIterator for I {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | impl<I: Iterator> const IntoIterator for I {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error[E0658]: mutable references are not allowed in constants
diff --git a/src/test/ui/issues/issue-5500-1.rs b/src/test/ui/never_type/issue-5500-1.rs
index 98d6e1a14..98d6e1a14 100644
--- a/src/test/ui/issues/issue-5500-1.rs
+++ b/src/test/ui/never_type/issue-5500-1.rs
diff --git a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs
new file mode 100644
index 000000000..25f47f5b6
--- /dev/null
+++ b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.rs
@@ -0,0 +1,31 @@
+// Regression test for #102800
+//
+// Here we are generating higher-ranked region constraints when normalizing and relating closure
+// input types. Previously this was an ICE in the error path because we didn't register enough
+// diagnostic information to render the higher-ranked subtyping error.
+
+// check-fail
+
+trait Trait {
+ type Ty;
+}
+
+impl Trait for &'static () {
+ type Ty = ();
+}
+
+fn main() {
+ let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ //~^ ERROR lifetime may not live long enough
+ //~| ERROR higher-ranked subtype error
+ //~| ERROR higher-ranked subtype error
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+ //~| ERROR implementation of `Trait` is not general enough
+}
diff --git a/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr
new file mode 100644
index 000000000..dbd5dabd1
--- /dev/null
+++ b/src/test/ui/nll/closure-malformed-projection-input-issue-102800.stderr
@@ -0,0 +1,104 @@
+error: lifetime may not live long enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^-^
+ | ||
+ | |has type `<&'1 () as Trait>::Ty`
+ | requires that `'1` must outlive `'static`
+
+error: higher-ranked subtype error
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^
+
+error: higher-ranked subtype error
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:12
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: implementation of `Trait` is not general enough
+ --> $DIR/closure-malformed-projection-input-issue-102800.rs:18:48
+ |
+LL | let _: for<'a> fn(<&'a () as Trait>::Ty) = |_| {};
+ | ^^^^^^ implementation of `Trait` is not general enough
+ |
+ = note: `&'0 ()` must implement `Trait`, for any lifetime `'0`...
+ = note: ...but `Trait` is actually implemented for the type `&'static ()`
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 59b848ea8..d2d26b23d 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
|
= note: defining type: test::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) i32)),
+ for<'a, 'b, 'c> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) i32)),
(),
]
diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr
index ff4e8e590..6355d3295 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y);
|
= note: defining type: test::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)),
+ for<'a, 'b> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32)),
(),
]
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 0d94fca28..5f9724ce3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| {
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
+ for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)),
(),
]
= note: late-bound region is '_#4r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 435a53533..ec728ebd5 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
+ for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)),
(),
]
= note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 6aafbe42c..012933797 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -6,7 +6,7 @@ LL | foo(cell, |cell_a, cell_x| {
|
= note: defining type: case1::{closure#0} with closure substs [
i32,
- for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
+ for<'a> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>)),
(),
]
@@ -36,7 +36,7 @@ LL | foo(cell, |cell_a, cell_x| {
|
= note: defining type: case2::{closure#0} with closure substs [
i32,
- for<'r> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>)),
+ for<'a> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>)),
(),
]
= note: number of external vids: 2
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index c95907ea7..ce85b20b3 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) u32>)),
+ for<'a, 'b, 'c, 'd, 'e> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) u32>)),
(),
]
= note: late-bound region is '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index db58d9d6f..20c7967b7 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
+ for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)),
(),
]
= note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index be5f1e5ef..f7db5ab1f 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
|
= note: defining type: test::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
+ for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)),
(),
]
= note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index d18db97be..3488edc75 100644
--- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -6,7 +6,7 @@ LL | |_outlives1, _outlives2, x, y| {
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
+ for<'a, 'b> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)),
(),
]
= note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index e6f88de4e..0dc2d0de9 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>)),
+ for<'a, 'b, 'c, 'd, 'e> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>)),
(),
]
= note: late-bound region is '_#2r
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 5f5fce771..4c9e026ea 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -6,7 +6,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
|
= note: defining type: supply::{closure#0} with closure substs [
i16,
- for<'r, 's, 't0, 't1, 't2, 't3> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('t0) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('t2) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('t3) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('t1) }) u32>)),
+ for<'a, 'b, 'c, 'd, 'e, 'f> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrNamed('c) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrNamed('e) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrNamed('f) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrNamed('d) }) u32>)),
(),
]
= note: late-bound region is '_#3r
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index da89071ea..68429142e 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL | expect_sig(|a, b| b); // ought to return `a`
|
= note: defining type: test::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) i32,
+ for<'a, 'b> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) i32,
(),
]
diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr
index 2be0460df..1c1a31d35 100644
--- a/src/test/ui/nll/closures-in-loops.stderr
+++ b/src/test/ui/nll/closures-in-loops.stderr
@@ -13,17 +13,21 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
--> $DIR/closures-in-loops.rs:13:16
|
LL | v.push(|| x = String::new());
- | ^^ - borrows occur due to use of `x` in closure
- | |
- | `x` was mutably borrowed here in the previous iteration of the loop
+ | -------^^-------------------
+ | | | |
+ | | | borrows occur due to use of `x` in closure
+ | | `x` was mutably borrowed here in the previous iteration of the loop
+ | first borrow used here, in later iteration of loop
error[E0524]: two closures require unique access to `x` at the same time
--> $DIR/closures-in-loops.rs:20:16
|
LL | v.push(|| *x = String::new());
- | ^^ -- borrows occur due to use of `x` in closure
- | |
- | closures are constructed here in different iterations of loop
+ | -------^^--------------------
+ | | | |
+ | | | borrows occur due to use of `x` in closure
+ | | closures are constructed here in different iterations of loop
+ | first borrow used here, in later iteration of loop
error: aborting due to 3 previous errors
diff --git a/src/test/ui/nll/issue-48623-generator.stderr b/src/test/ui/nll/issue-48623-generator.stderr
index 70a83e46f..1b35165db 100644
--- a/src/test/ui/nll/issue-48623-generator.stderr
+++ b/src/test/ui/nll/issue-48623-generator.stderr
@@ -4,8 +4,8 @@ warning: unused generator that must be used
LL | move || { d; yield; &mut *r };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unused_must_use)]` on by default
= note: generators are lazy and do nothing unless resumed
+ = note: `#[warn(unused_must_use)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/nll/issue-51191.stderr b/src/test/ui/nll/issue-51191.stderr
index 9f4e971f9..63ca6ae5c 100644
--- a/src/test/ui/nll/issue-51191.stderr
+++ b/src/test/ui/nll/issue-51191.stderr
@@ -7,8 +7,8 @@ LL | fn bar(self: &mut Self) {
LL | (&mut self).bar();
| ----------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable
--> $DIR/issue-51191.rs:7:9
diff --git a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr
index 0ae6b7c1d..6e96f40c0 100644
--- a/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr
+++ b/src/test/ui/nll/issue-57642-higher-ranked-subtype.stderr
@@ -1,11 +1,11 @@
-error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'r> fn(&'r ())`, but its trait bounds were not satisfied
+error[E0599]: the function or associated item `make_g` exists for fn pointer `for<'a> fn(&'a ())`, 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<'r> fn(&'r ())` due to unsatisfied trait bounds
+ | ^^^^^^ function or associated item cannot be called on `for<'a> fn(&'a ())` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
- `for<'r> fn(&'r ()): X`
+ `for<'a> fn(&'a ()): X`
= help: items from traits can only be used if the trait is implemented and in scope
note: `X` defines an item `make_g`, perhaps you need to implement it
--> $DIR/issue-57642-higher-ranked-subtype.rs:4:1
@@ -13,11 +13,11 @@ note: `X` defines an item `make_g`, perhaps you need to implement it
LL | trait X {
| ^^^^^^^
-error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'r> fn(&'r ())` in the current scope
+error[E0599]: no function or associated item named `make_f` found for fn pointer `for<'a> fn(&'a ())` in the current scope
--> $DIR/issue-57642-higher-ranked-subtype.rs:35:25
|
LL | let x = <fn (&())>::make_f();
- | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())`
+ | ^^^^^^ function or associated item not found in `for<'a> fn(&'a ())`
|
= 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/src/test/ui/nll/issue-97997.stderr b/src/test/ui/nll/issue-97997.stderr
index 78401bbf6..46440c021 100644
--- a/src/test/ui/nll/issue-97997.stderr
+++ b/src/test/ui/nll/issue-97997.stderr
@@ -4,7 +4,7 @@ error: implementation of `Foo` is not general enough
LL | <fn(&u8) as Foo>::ASSOC;
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
+ = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
error: implementation of `Foo` is not general enough
@@ -13,7 +13,7 @@ error: implementation of `Foo` is not general enough
LL | <fn(&u8) as Foo>::ASSOC;
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
- = note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
+ = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a u8)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr
index 250aa482e..2d48a9142 100644
--- a/src/test/ui/nll/match-cfg-fake-edges.stderr
+++ b/src/test/ui/nll/match-cfg-fake-edges.stderr
@@ -9,6 +9,11 @@ LL | _ if { x = 2; true } => 1,
LL | _ if {
LL | x;
| ^ `x` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let x = 0;
+ | +++
error[E0382]: use of moved value: `x`
--> $DIR/match-cfg-fake-edges.rs:35:13
diff --git a/src/test/ui/nll/match-on-borrowed.stderr b/src/test/ui/nll/match-on-borrowed.stderr
index 664f36f69..32666529f 100644
--- a/src/test/ui/nll/match-on-borrowed.stderr
+++ b/src/test/ui/nll/match-on-borrowed.stderr
@@ -40,6 +40,11 @@ LL | let n: Never;
| - binding declared here but left uninitialized
LL | match n {}
| ^ `n` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let n: Never = todo!();
+ | +++++++++
error: aborting due to 4 previous errors
diff --git a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
index 8c4737988..b945ffedd 100644
--- a/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
+++ b/src/test/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr
@@ -4,7 +4,7 @@ error: implementation of `Y` is not general enough
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough
|
- = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())`
+ = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())`
= note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
error: implementation of `Y` is not general enough
@@ -13,7 +13,7 @@ error: implementation of `Y` is not general enough
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough
|
- = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())`
+ = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())`
= note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
error: implementation of `Y` is not general enough
@@ -22,7 +22,7 @@ error: implementation of `Y` is not general enough
LL | let _x = <fn(&())>::make_f();
| ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough
|
- = note: `Y` would have to be implemented for the type `for<'r> fn(&'r ())`
+ = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())`
= note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/nll/relate_tys/universe-violation.stderr b/src/test/ui/nll/relate_tys/universe-violation.stderr
index 6f38154e3..fe801b42c 100644
--- a/src/test/ui/nll/relate_tys/universe-violation.stderr
+++ b/src/test/ui/nll/relate_tys/universe-violation.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | let b: fn(&u32) -> &u32 = a;
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r> fn(&'r u32) -> &'r u32`
+ = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32`
found fn pointer `fn(&u32) -> &u32`
error: aborting due to previous error
diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr
index ae0ffd904..cf1c52ba7 100644
--- a/src/test/ui/nll/trait-associated-constant.stderr
+++ b/src/test/ui/nll/trait-associated-constant.stderr
@@ -2,7 +2,7 @@ error[E0308]: const not compatible with trait
--> $DIR/trait-associated-constant.rs:21:5
|
LL | const AC: Option<&'c str> = None;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
|
= note: expected enum `Option<&'b str>`
found enum `Option<&'c str>`
diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
index 330c6fafa..737cb3584 100644
--- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
+++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr
@@ -1,14 +1,14 @@
-error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
--> $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:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) T` captures the anonymous lifetime 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
| ^
|
-help: to declare that the `impl Trait` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
+help: to declare that `Opaque(DefId(0:13 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReEarlyBound(0, 'a), T, ReEarlyBound(2, 'a)])` captures `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))`, you can add an explicit `ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_))` lifetime bound
|
-LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:13 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
+LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> + ReFree(DefId(0:8 ~ impl_trait_captures[1afc]::foo), BrNamed(DefId(0:12 ~ impl_trait_captures[1afc]::foo::'_), '_)) {
| ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index 5d9a044d1..61c7d2550 100644
--- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -6,7 +6,7 @@ LL | twice(cell, value, |a, b| invoke(a, b));
|
= note: defining type: generic::<T>::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
+ for<'a, 'b> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) T)),
(),
]
= note: number of external vids: 2
@@ -28,7 +28,7 @@ LL | twice(cell, value, |a, b| invoke(a, b));
|
= note: defining type: generic_fail::<T>::{closure#0} with closure substs [
i16,
- for<'r, 's> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('r) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('s) }) T)),
+ for<'a, 'b> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrNamed('a) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrNamed('b) }) T)),
(),
]
= note: late-bound region is '_#2r
diff --git a/src/test/ui/no-patterns-in-args-2.stderr b/src/test/ui/no-patterns-in-args-2.stderr
index 98932349a..6adcbb9dc 100644
--- a/src/test/ui/no-patterns-in-args-2.stderr
+++ b/src/test/ui/no-patterns-in-args-2.stderr
@@ -10,13 +10,13 @@ error: patterns aren't allowed in functions without bodies
LL | fn f1(mut arg: u8);
| ^^^^^^^ help: remove `mut` from the parameter: `arg`
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
note: the lint level is defined here
--> $DIR/no-patterns-in-args-2.rs:1:9
|
LL | #![deny(patterns_in_fns_without_body)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #35203 <https://github.com/rust-lang/rust/issues/35203>
error: aborting due to 2 previous errors
diff --git a/src/test/ui/non-fmt-panic.stderr b/src/test/ui/non-fmt-panic.stderr
index 6e4434e6f..162802b7f 100644
--- a/src/test/ui/non-fmt-panic.stderr
+++ b/src/test/ui/non-fmt-panic.stderr
@@ -4,8 +4,8 @@ warning: panic message contains a brace
LL | panic!("here's a brace: {");
| ^
|
- = note: `#[warn(non_fmt_panics)]` on by default
= note: this message is not used as a format string, but will be in Rust 2021
+ = note: `#[warn(non_fmt_panics)]` on by default
help: add a "{}" format string to use the message literally
|
LL | panic!("{}", "here's a brace: {");
diff --git a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs
index 769114960..260281d75 100644
--- a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs
+++ b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs
@@ -1,7 +1,5 @@
// run-pass
-#![deny(const_err)]
-
// Forces evaluation of constants, triggering hard error
fn force<T>(_: T) {}
diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
index e2eee1ccd..c4abcb784 100644
--- a/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
+++ b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
@@ -1,5 +1,5 @@
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:13:36
+ --> $DIR/issue-8460-const.rs:11:36
|
LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
@@ -7,139 +7,139 @@ LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
= note: `#[deny(unconditional_panic)]` on by default
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:15:36
+ --> $DIR/issue-8460-const.rs:13:36
|
LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:17:36
+ --> $DIR/issue-8460-const.rs:15:36
|
LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:19:36
+ --> $DIR/issue-8460-const.rs:17:36
|
LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:21:36
+ --> $DIR/issue-8460-const.rs:19:36
|
LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:23:36
+ --> $DIR/issue-8460-const.rs:21:36
|
LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:25:36
+ --> $DIR/issue-8460-const.rs:23:36
|
LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
| ^^^^^^^^^^ attempt to divide `1_isize` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:27:36
+ --> $DIR/issue-8460-const.rs:25:36
|
LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
| ^^^^^^^ attempt to divide `1_i8` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:29:36
+ --> $DIR/issue-8460-const.rs:27:36
|
LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i16` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:31:36
+ --> $DIR/issue-8460-const.rs:29:36
|
LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i32` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:33:36
+ --> $DIR/issue-8460-const.rs:31:36
|
LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i64` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:35:36
+ --> $DIR/issue-8460-const.rs:33:36
|
LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
| ^^^^^^^^^ attempt to divide `1_i128` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:37:36
+ --> $DIR/issue-8460-const.rs:35:36
|
LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:39:36
+ --> $DIR/issue-8460-const.rs:37:36
|
LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:41:36
+ --> $DIR/issue-8460-const.rs:39:36
|
LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:43:36
+ --> $DIR/issue-8460-const.rs:41:36
|
LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:45:36
+ --> $DIR/issue-8460-const.rs:43:36
|
LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:47:36
+ --> $DIR/issue-8460-const.rs:45:36
|
LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:49:36
+ --> $DIR/issue-8460-const.rs:47:36
|
LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
| ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:51:36
+ --> $DIR/issue-8460-const.rs:49:36
|
LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
| ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:53:36
+ --> $DIR/issue-8460-const.rs:51:36
|
LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:55:36
+ --> $DIR/issue-8460-const.rs:53:36
|
LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:57:36
+ --> $DIR/issue-8460-const.rs:55:36
|
LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:59:36
+ --> $DIR/issue-8460-const.rs:57:36
|
LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
| ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
index e2eee1ccd..c4abcb784 100644
--- a/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
+++ b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr
@@ -1,5 +1,5 @@
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:13:36
+ --> $DIR/issue-8460-const.rs:11:36
|
LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
@@ -7,139 +7,139 @@ LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
= note: `#[deny(unconditional_panic)]` on by default
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:15:36
+ --> $DIR/issue-8460-const.rs:13:36
|
LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:17:36
+ --> $DIR/issue-8460-const.rs:15:36
|
LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:19:36
+ --> $DIR/issue-8460-const.rs:17:36
|
LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:21:36
+ --> $DIR/issue-8460-const.rs:19:36
|
LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:23:36
+ --> $DIR/issue-8460-const.rs:21:36
|
LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:25:36
+ --> $DIR/issue-8460-const.rs:23:36
|
LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
| ^^^^^^^^^^ attempt to divide `1_isize` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:27:36
+ --> $DIR/issue-8460-const.rs:25:36
|
LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
| ^^^^^^^ attempt to divide `1_i8` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:29:36
+ --> $DIR/issue-8460-const.rs:27:36
|
LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i16` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:31:36
+ --> $DIR/issue-8460-const.rs:29:36
|
LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i32` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:33:36
+ --> $DIR/issue-8460-const.rs:31:36
|
LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i64` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:35:36
+ --> $DIR/issue-8460-const.rs:33:36
|
LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
| ^^^^^^^^^ attempt to divide `1_i128` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:37:36
+ --> $DIR/issue-8460-const.rs:35:36
|
LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:39:36
+ --> $DIR/issue-8460-const.rs:37:36
|
LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:41:36
+ --> $DIR/issue-8460-const.rs:39:36
|
LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:43:36
+ --> $DIR/issue-8460-const.rs:41:36
|
LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:45:36
+ --> $DIR/issue-8460-const.rs:43:36
|
LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:47:36
+ --> $DIR/issue-8460-const.rs:45:36
|
LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:49:36
+ --> $DIR/issue-8460-const.rs:47:36
|
LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
| ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:51:36
+ --> $DIR/issue-8460-const.rs:49:36
|
LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
| ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:53:36
+ --> $DIR/issue-8460-const.rs:51:36
|
LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:55:36
+ --> $DIR/issue-8460-const.rs:53:36
|
LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:57:36
+ --> $DIR/issue-8460-const.rs:55:36
|
LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:59:36
+ --> $DIR/issue-8460-const.rs:57:36
|
LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
| ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
index e2eee1ccd..c4abcb784 100644
--- a/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
+++ b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
@@ -1,5 +1,5 @@
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:13:36
+ --> $DIR/issue-8460-const.rs:11:36
|
LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
@@ -7,139 +7,139 @@ LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
= note: `#[deny(unconditional_panic)]` on by default
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:15:36
+ --> $DIR/issue-8460-const.rs:13:36
|
LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:17:36
+ --> $DIR/issue-8460-const.rs:15:36
|
LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:19:36
+ --> $DIR/issue-8460-const.rs:17:36
|
LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:21:36
+ --> $DIR/issue-8460-const.rs:19:36
|
LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:23:36
+ --> $DIR/issue-8460-const.rs:21:36
|
LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:25:36
+ --> $DIR/issue-8460-const.rs:23:36
|
LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
| ^^^^^^^^^^ attempt to divide `1_isize` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:27:36
+ --> $DIR/issue-8460-const.rs:25:36
|
LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
| ^^^^^^^ attempt to divide `1_i8` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:29:36
+ --> $DIR/issue-8460-const.rs:27:36
|
LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i16` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:31:36
+ --> $DIR/issue-8460-const.rs:29:36
|
LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i32` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:33:36
+ --> $DIR/issue-8460-const.rs:31:36
|
LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
| ^^^^^^^^ attempt to divide `1_i64` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:35:36
+ --> $DIR/issue-8460-const.rs:33:36
|
LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
| ^^^^^^^^^ attempt to divide `1_i128` by zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:37:36
+ --> $DIR/issue-8460-const.rs:35:36
|
LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:39:36
+ --> $DIR/issue-8460-const.rs:37:36
|
LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:41:36
+ --> $DIR/issue-8460-const.rs:39:36
|
LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:43:36
+ --> $DIR/issue-8460-const.rs:41:36
|
LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:45:36
+ --> $DIR/issue-8460-const.rs:43:36
|
LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:47:36
+ --> $DIR/issue-8460-const.rs:45:36
|
LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
| ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:49:36
+ --> $DIR/issue-8460-const.rs:47:36
|
LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
| ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:51:36
+ --> $DIR/issue-8460-const.rs:49:36
|
LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
| ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:53:36
+ --> $DIR/issue-8460-const.rs:51:36
|
LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:55:36
+ --> $DIR/issue-8460-const.rs:53:36
|
LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:57:36
+ --> $DIR/issue-8460-const.rs:55:36
|
LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
| ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
error: this operation will panic at runtime
- --> $DIR/issue-8460-const.rs:59:36
+ --> $DIR/issue-8460-const.rs:57:36
|
LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
| ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
diff --git a/src/test/ui/numbers-arithmetic/issue-8460-const.rs b/src/test/ui/numbers-arithmetic/issue-8460-const.rs
index 8cad6deb3..02e7567da 100644
--- a/src/test/ui/numbers-arithmetic/issue-8460-const.rs
+++ b/src/test/ui/numbers-arithmetic/issue-8460-const.rs
@@ -5,8 +5,6 @@
// build-fail
-#![deny(const_err)]
-
use std::thread;
fn main() {
diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
index f857d4f4c..79d78da33 100644
--- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
+++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
@@ -1,7 +1,6 @@
// run-pass
// compile-flags: -C debug_assertions=yes
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// ignore-emscripten dies with an LLVM error
use std::panic;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs
index e5ce80336..7f8b0c877 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = 1_i32 << 32;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
index 1d029939c..434c9d5b4 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr
@@ -7,7 +7,7 @@ LL | let _x = 1_i32 << 32;
note: the lint level is defined here
--> $DIR/overflowing-lsh-1.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs
index 7fd3407a0..76718ecd1 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = 1 << -1;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
index 8598792e0..c3b44e5a0 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr
@@ -7,7 +7,7 @@ LL | let _x = 1 << -1;
note: the lint level is defined here
--> $DIR/overflowing-lsh-2.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs
index e007eb4a2..b2bdd09bf 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = 1_u64 << 64;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
index 9c6f806f1..9d6479bd7 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr
@@ -7,7 +7,7 @@ LL | let _x = 1_u64 << 64;
note: the lint level is defined here
--> $DIR/overflowing-lsh-3.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs
index 738d01339..1042bfcb3 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs
@@ -4,7 +4,7 @@
// This function is checking that our automatic truncation does not
// sidestep the overflow checking.
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
// this signals overflow when checking is on
diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
index 08081a0b7..2bb5b6a6d 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr
@@ -7,7 +7,7 @@ LL | let x = 1_i8 << 17;
note: the lint level is defined here
--> $DIR/overflowing-lsh-4.rs:7:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs
index f1488cf85..80593c865 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = -1_i32 >> 32;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
index 4d726fa7f..b2b3114d1 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr
@@ -7,7 +7,7 @@ LL | let _x = -1_i32 >> 32;
note: the lint level is defined here
--> $DIR/overflowing-rsh-1.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs
index 39127b970..917352bfc 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = -1_i32 >> -1;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
index 9a8349d5d..ad18c3bb7 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr
@@ -7,7 +7,7 @@ LL | let _x = -1_i32 >> -1;
note: the lint level is defined here
--> $DIR/overflowing-rsh-2.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs
index 8ee6dde93..1e052990a 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _x = -1_i64 >> 64;
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
index f48b7ff6d..37d02e09d 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr
@@ -7,7 +7,7 @@ LL | let _x = -1_i64 >> 64;
note: the lint level is defined here
--> $DIR/overflowing-rsh-3.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs
index ce7f818e3..be918becd 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs
@@ -4,7 +4,7 @@
// This function is checking that our (type-based) automatic
// truncation does not sidestep the overflow checking.
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
// this signals overflow when checking is on
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
index 4816a3899..692602c07 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr
@@ -7,7 +7,7 @@ LL | let x = 2_i8 >> 17;
note: the lint level is defined here
--> $DIR/overflowing-rsh-4.rs:7:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs
index 88928c995..f75e779ed 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _n = 1i64 >> [64][0];
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
index cd36f543d..e3b5859df 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr
@@ -7,7 +7,7 @@ LL | let _n = 1i64 >> [64][0];
note: the lint level is defined here
--> $DIR/overflowing-rsh-5.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs
index 88928c995..f75e779ed 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs
@@ -1,7 +1,7 @@
// build-fail
// compile-flags: -C debug-assertions
-#![deny(arithmetic_overflow, const_err)]
+#![deny(arithmetic_overflow)]
fn main() {
let _n = 1i64 >> [64][0];
diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
index bec8b17df..a3475c04c 100644
--- a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
+++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr
@@ -7,7 +7,7 @@ LL | let _n = 1i64 >> [64][0];
note: the lint level is defined here
--> $DIR/overflowing-rsh-6.rs:4:9
|
-LL | #![deny(arithmetic_overflow, const_err)]
+LL | #![deny(arithmetic_overflow)]
| ^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
index 4785abbc5..76279e913 100644
--- a/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
+++ b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs
@@ -1,5 +1,4 @@
// run-pass
-#![allow(const_err)]
// compile-flags: -O
diff --git a/src/test/ui/object-safety/issue-102762.rs b/src/test/ui/object-safety/issue-102762.rs
new file mode 100644
index 000000000..4f4c36345
--- /dev/null
+++ b/src/test/ui/object-safety/issue-102762.rs
@@ -0,0 +1,26 @@
+// compile-flags: --crate-type=lib
+// This test checks that the `where_clauses_object_safety` lint does not cause
+// other object safety *hard errors* to be suppressed, because we currently
+// only emit one object safety error per trait...
+
+use std::future::Future;
+use std::pin::Pin;
+
+pub trait Fetcher: Send + Sync {
+ fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+ where
+ Self: Sync,
+ {
+ todo!()
+ }
+}
+
+fn fetcher() -> Box<dyn Fetcher> {
+ //~^ ERROR the trait `Fetcher` cannot be made into an object
+ todo!()
+}
+
+pub fn foo() {
+ let fetcher = fetcher();
+ let _ = fetcher.get();
+}
diff --git a/src/test/ui/object-safety/issue-102762.stderr b/src/test/ui/object-safety/issue-102762.stderr
new file mode 100644
index 000000000..5041ebe77
--- /dev/null
+++ b/src/test/ui/object-safety/issue-102762.stderr
@@ -0,0 +1,20 @@
+error[E0038]: the trait `Fetcher` cannot be made into an object
+ --> $DIR/issue-102762.rs:18:21
+ |
+LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+ | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self`
+...
+LL | fn fetcher() -> Box<dyn Fetcher> {
+ | ^^^^^^^^^^^ `Fetcher` 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-102762.rs:10:22
+ |
+LL | pub trait Fetcher: Send + Sync {
+ | ------- this trait cannot be made into an object...
+LL | fn get<'a>(self: &'a Box<Self>) -> Pin<Box<dyn Future<Output = Vec<u8>> + 'a>>
+ | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/object-safety/issue-102933.rs b/src/test/ui/object-safety/issue-102933.rs
new file mode 100644
index 000000000..843391cff
--- /dev/null
+++ b/src/test/ui/object-safety/issue-102933.rs
@@ -0,0 +1,25 @@
+// check-pass
+
+use std::future::Future;
+
+pub trait Service {
+ type Response;
+ type Future: Future<Output = Self::Response>;
+}
+
+pub trait A1: Service<Response = i32> {}
+
+pub trait A2: Service<Future = Box<dyn Future<Output = i32>>> + A1 {
+ fn foo(&self) {}
+}
+
+pub trait B1: Service<Future = Box<dyn Future<Output = i32>>> {}
+
+pub trait B2: Service<Response = i32> + B1 {
+ fn foo(&self) {}
+}
+
+fn main() {
+ let x: &dyn A2 = todo!();
+ let x: &dyn B2 = todo!();
+}
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.rs b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.rs
new file mode 100644
index 000000000..14e00d2ef
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.rs
@@ -0,0 +1,15 @@
+//~ ERROR the parameter type `Self` may not live long enough
+
+trait GatTrait {
+ type Gat<'a>
+ where
+ Self: 'a;
+}
+
+trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+ fn c(&self) -> dyn SuperTrait<T>;
+ //~^ ERROR associated item referring to unboxed trait object for its own trait
+ //~| ERROR the trait `SuperTrait` cannot be made into an object
+}
+
+fn main() {}
diff --git a/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
new file mode 100644
index 000000000..c1aaad31e
--- /dev/null
+++ b/src/test/ui/object-safety/object-safety-supertrait-mentions-GAT.stderr
@@ -0,0 +1,43 @@
+error[E0311]: the parameter type `Self` may not live long enough
+ |
+ = 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
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:9:39
+ |
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+ | ^^^^^^^^^^^
+
+error: associated item referring to unboxed trait object for its own trait
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20
+ |
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+ | ---------- in this trait
+LL | fn c(&self) -> dyn SuperTrait<T>;
+ | ^^^^^^^^^^^^^^^^^
+ |
+help: you might have meant to use `Self` to refer to the implementing type
+ |
+LL | fn c(&self) -> Self;
+ | ~~~~
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:10:20
+ |
+LL | fn c(&self) -> dyn SuperTrait<T>;
+ | ^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+ |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+ --> $DIR/object-safety-supertrait-mentions-GAT.rs:4:10
+ |
+LL | type Gat<'a>
+ | ^^^ ...because it contains the generic associated type `Gat`
+...
+LL | trait SuperTrait<T>: for<'a> GatTrait<Gat<'a> = T> {
+ | ---------- this trait cannot be made into an object...
+ = help: consider moving `Gat` to another trait
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0038, E0311.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/oom_unwind.rs b/src/test/ui/oom_unwind.rs
index d036c817a..21a8fb2b2 100644
--- a/src/test/ui/oom_unwind.rs
+++ b/src/test/ui/oom_unwind.rs
@@ -4,8 +4,6 @@
// needs-unwind
// only-linux
-#![feature(bench_black_box)]
-
use std::hint::black_box;
use std::mem::forget;
use std::panic::catch_unwind;
diff --git a/src/test/ui/opt-in-copy.stderr b/src/test/ui/opt-in-copy.stderr
index 0a275f1aa..4461567df 100644
--- a/src/test/ui/opt-in-copy.stderr
+++ b/src/test/ui/opt-in-copy.stderr
@@ -1,20 +1,20 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/opt-in-copy.rs:7:6
+ --> $DIR/opt-in-copy.rs:7:15
|
LL | but_i_cant: CantCopyThis,
| ------------------------ this field does not implement `Copy`
...
LL | impl Copy for IWantToCopyThis {}
- | ^^^^
+ | ^^^^^^^^^^^^^^^
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/opt-in-copy.rs:19:6
+ --> $DIR/opt-in-copy.rs:19:15
|
LL | ButICant(CantCopyThisEither),
| ------------------ this field does not implement `Copy`
...
LL | impl Copy for IWantToCopyThisToo {}
- | ^^^^
+ | ^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
diff --git a/src/test/ui/packed/issue-27060-rpass.stderr b/src/test/ui/packed/issue-27060-rpass.stderr
index 667b70afb..adf9ae9f5 100644
--- a/src/test/ui/packed/issue-27060-rpass.stderr
+++ b/src/test/ui/packed/issue-27060-rpass.stderr
@@ -5,15 +5,15 @@ warning: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
warning: reference to packed field is unaligned
@@ -22,15 +22,15 @@ warning: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
warning: reference to packed field is unaligned
@@ -39,15 +39,15 @@ warning: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
Future breakage diagnostic:
warning: reference to packed field is unaligned
@@ -56,13 +56,13 @@ warning: reference to packed field is unaligned
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)]
| ^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted 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)
diff --git a/src/test/ui/packed/issue-27060.stderr b/src/test/ui/packed/issue-27060.stderr
index 1bab16e6d..85e08fa02 100644
--- a/src/test/ui/packed/issue-27060.stderr
+++ b/src/test/ui/packed/issue-27060.stderr
@@ -4,11 +4,11 @@ error: reference to packed field is unaligned
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -52,11 +52,11 @@ error: reference to packed field is unaligned
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -65,11 +65,11 @@ error: reference to packed field is unaligned
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -78,11 +78,11 @@ error: reference to packed field is unaligned
LL | let _ = &good.data;
| ^^^^^^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
@@ -91,9 +91,9 @@ error: reference to packed field is unaligned
LL | let _ = &good.data2[0];
| ^^^^^^^^^^^^^^
|
- = note: `#[deny(unaligned_references)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: fields of packed structs are not properly aligned, and creating a misaligned reference is undefined behavior (even if that reference is never dereferenced)
= 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
diff --git a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
index dcd1c19fa..fb2f5615c 100644
--- a/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
+++ b/src/test/ui/packed/packed-struct-borrow-element-64bit.stderr
@@ -4,15 +4,15 @@ warning: reference to packed field is unaligned
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: this was previously accepted 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: 1 warning emitted
@@ -23,13 +23,13 @@ warning: reference to packed field is unaligned
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: this was previously accepted 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)
diff --git a/src/test/ui/packed/packed-struct-borrow-element.stderr b/src/test/ui/packed/packed-struct-borrow-element.stderr
index fb483227e..75d55c4f6 100644
--- a/src/test/ui/packed/packed-struct-borrow-element.stderr
+++ b/src/test/ui/packed/packed-struct-borrow-element.stderr
@@ -4,15 +4,15 @@ warning: reference to packed field is unaligned
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: this was previously accepted 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: reference to packed field is unaligned
--> $DIR/packed-struct-borrow-element.rs:31:15
@@ -34,15 +34,15 @@ warning: reference to packed field is unaligned
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: this was previously accepted 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)
Future breakage diagnostic:
warning: reference to packed field is unaligned
@@ -51,13 +51,13 @@ warning: reference to packed field is unaligned
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: this was previously accepted 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)
diff --git a/src/test/ui/panic-handler/weak-lang-item.rs b/src/test/ui/panic-handler/weak-lang-item.rs
index df31e614c..14a07a9ef 100644
--- a/src/test/ui/panic-handler/weak-lang-item.rs
+++ b/src/test/ui/panic-handler/weak-lang-item.rs
@@ -2,7 +2,7 @@
// error-pattern: `#[panic_handler]` function required, but not found
// error-pattern: language item required, but not found: `eh_personality`
// needs-unwind since it affects the error output
-// ignore-emscripten compiled with panic=abort, personality not required
+// ignore-emscripten missing eh_catch_typeinfo lang item
#![no_std]
diff --git a/src/test/ui/panic-runtime/need-abort-got-unwind.rs b/src/test/ui/panic-runtime/need-abort-got-unwind.rs
index c72fb96e3..e92400931 100644
--- a/src/test/ui/panic-runtime/need-abort-got-unwind.rs
+++ b/src/test/ui/panic-runtime/need-abort-got-unwind.rs
@@ -2,7 +2,6 @@
// needs-unwind
// error-pattern:is incompatible with this crate's strategy of `unwind`
// aux-build:needs-abort.rs
-// ignore-wasm32-bare compiled with panic=abort by default
extern crate needs_abort;
diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
index 622535a75..0e74e300f 100644
--- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
+++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs
@@ -6,7 +6,6 @@
// aux-build:wants-panic-runtime-abort.rs
// aux-build:panic-runtime-lang-items.rs
// error-pattern: is not compiled with this crate's panic strategy `unwind`
-// ignore-wasm32-bare compiled with panic=abort by default
#![no_std]
#![no_main]
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
index 23bfea6af..b6174dc4e 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs
@@ -3,7 +3,6 @@
// error-pattern:is not compiled with this crate's panic strategy `unwind`
// aux-build:panic-runtime-abort.rs
// aux-build:panic-runtime-lang-items.rs
-// ignore-wasm32-bare compiled with panic=abort by default
#![no_std]
#![no_main]
diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
index 7a2e48e2f..b54babbef 100644
--- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
+++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs
@@ -4,7 +4,6 @@
// aux-build:panic-runtime-abort.rs
// aux-build:wants-panic-runtime-abort.rs
// aux-build:panic-runtime-lang-items.rs
-// ignore-wasm32-bare compiled with panic=abort by default
#![no_std]
#![no_main]
diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs
index 098f54ac2..3abedf2a7 100644
--- a/src/test/ui/panic-while-printing.rs
+++ b/src/test/ui/panic-while-printing.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-emscripten no subprocess support
#![feature(internal_output_capture)]
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr
index b6223b937..ac4ed8225 100644
--- a/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr
+++ b/src/test/ui/panics/issue-47429-short-backtraces.legacy.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:22:5
+thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:23:5
stack backtrace:
0: std::panicking::begin_panic
1: issue_47429_short_backtraces::main
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.rs b/src/test/ui/panics/issue-47429-short-backtraces.rs
index f338ace6b..58d0fa62c 100644
--- a/src/test/ui/panics/issue-47429-short-backtraces.rs
+++ b/src/test/ui/panics/issue-47429-short-backtraces.rs
@@ -12,6 +12,7 @@
// ignore-wasm no panic or subprocess support
// ignore-emscripten no panic or subprocess support
// ignore-sgx no subprocess support
+// ignore-fuchsia Backtraces not symbolized
// NOTE(eddyb) output differs between symbol mangling schemes
// revisions: legacy v0
diff --git a/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr b/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr
index c2bea4492..65401fe1c 100644
--- a/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr
+++ b/src/test/ui/panics/issue-47429-short-backtraces.v0.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:22:5
+thread 'main' panicked at 'explicit panic', $DIR/issue-47429-short-backtraces.rs:23:5
stack backtrace:
0: std::panicking::begin_panic::<&str>
1: issue_47429_short_backtraces::main
diff --git a/src/test/ui/panics/runtime-switch.legacy.run.stderr b/src/test/ui/panics/runtime-switch.legacy.run.stderr
index f282f1883..0f7655163 100644
--- a/src/test/ui/panics/runtime-switch.legacy.run.stderr
+++ b/src/test/ui/panics/runtime-switch.legacy.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:25:5
+thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:26:5
stack backtrace:
0: std::panicking::begin_panic
1: runtime_switch::main
diff --git a/src/test/ui/panics/runtime-switch.rs b/src/test/ui/panics/runtime-switch.rs
index 37ef961e2..882340e49 100644
--- a/src/test/ui/panics/runtime-switch.rs
+++ b/src/test/ui/panics/runtime-switch.rs
@@ -12,6 +12,7 @@
// ignore-wasm no panic or subprocess support
// ignore-emscripten no panic or subprocess support
// ignore-sgx no subprocess support
+// ignore-fuchsia Backtrace not symbolized
// NOTE(eddyb) output differs between symbol mangling schemes
// revisions: legacy v0
diff --git a/src/test/ui/panics/runtime-switch.v0.run.stderr b/src/test/ui/panics/runtime-switch.v0.run.stderr
index 7ce9722e5..a4ae44131 100644
--- a/src/test/ui/panics/runtime-switch.v0.run.stderr
+++ b/src/test/ui/panics/runtime-switch.v0.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:25:5
+thread 'main' panicked at 'explicit panic', $DIR/runtime-switch.rs:26:5
stack backtrace:
0: std::panicking::begin_panic::<&str>
1: runtime_switch::main
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index 7ae092cee..8a74f49b9 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -168,9 +168,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error: aborting due to 24 previous errors; 1 warning emitted
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
index 09f494bdc..469c3855c 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs
@@ -1,5 +1,3 @@
-#![feature(half_open_range_patterns)]
-
fn main() {}
#[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 7bb3db030..872c560cb 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -1,5 +1,5 @@
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:5:36
+ --> $DIR/attr-stmt-expr-attr-bad.rs:3:36
|
LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
| ^^^^^^^^
@@ -8,19 +8,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = box #![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected expression, found `]`
- --> $DIR/attr-stmt-expr-attr-bad.rs:7:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:5:40
|
LL | #[cfg(FALSE)] fn e() { let _ = [#[attr]]; }
| ^ expected expression
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:9:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:7:35
|
LL | #[cfg(FALSE)] fn e() { let _ = foo#[attr](); }
| ^ expected one of 8 possible tokens
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:11:36
+ --> $DIR/attr-stmt-expr-attr-bad.rs:9:36
|
LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
| ^^^^^^^^
@@ -29,13 +29,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected expression, found `)`
- --> $DIR/attr-stmt-expr-attr-bad.rs:11:44
+ --> $DIR/attr-stmt-expr-attr-bad.rs:9:44
|
LL | #[cfg(FALSE)] fn e() { let _ = foo(#![attr]); }
| ^ expected expression
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:14:38
+ --> $DIR/attr-stmt-expr-attr-bad.rs:12:38
|
LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
| ^^^^^^^^
@@ -44,13 +44,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected expression, found `)`
- --> $DIR/attr-stmt-expr-attr-bad.rs:14:46
+ --> $DIR/attr-stmt-expr-attr-bad.rs:12:46
|
LL | #[cfg(FALSE)] fn e() { let _ = x.foo(#![attr]); }
| ^ expected expression
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:17:36
+ --> $DIR/attr-stmt-expr-attr-bad.rs:15:36
|
LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
| ^^^^^^^^
@@ -59,7 +59,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = 0 + #![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
+ --> $DIR/attr-stmt-expr-attr-bad.rs:17:33
|
LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
| ^^^^^^^^
@@ -68,7 +68,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = !#![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:21:33
+ --> $DIR/attr-stmt-expr-attr-bad.rs:19:33
|
LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
| ^^^^^^^^
@@ -77,13 +77,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = -#![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected one of `!`, `.`, `::`, `;`, `?`, `else`, `{`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:23:34
+ --> $DIR/attr-stmt-expr-attr-bad.rs:21:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x #![attr] as Y; }
| ^ expected one of 8 possible tokens
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:25:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:23:35
|
LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
| ^^^^^^^^
@@ -92,7 +92,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] foo; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:27:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:25:40
|
LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
| ^^^^^^^^
@@ -101,7 +101,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] foo; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:29:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:27:35
|
LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
| ^^^^^^^^
@@ -110,7 +110,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = || #![attr] {foo}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:29:40
|
LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
| ^^^^^^^^
@@ -119,19 +119,19 @@ LL | #[cfg(FALSE)] fn e() { let _ = move || #![attr] {foo}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected expression, found `..`
- --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:31:40
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..#[attr] 0; }
| ^^ expected expression
error: expected expression, found `..`
- --> $DIR/attr-stmt-expr-attr-bad.rs:35:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:33:40
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] ..; }
| ^^ expected expression
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:37:41
+ --> $DIR/attr-stmt-expr-attr-bad.rs:35:41
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
| ^^^^^^^^
@@ -140,7 +140,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &#![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:39:45
+ --> $DIR/attr-stmt-expr-attr-bad.rs:37:45
|
LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
| ^^^^^^^^
@@ -149,7 +149,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:41:37
+ --> $DIR/attr-stmt-expr-attr-bad.rs:39:37
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
@@ -158,7 +158,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
+ --> $DIR/attr-stmt-expr-attr-bad.rs:41:38
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
| ^^^^^^^^
@@ -167,13 +167,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:45:40
+ --> $DIR/attr-stmt-expr-attr-bad.rs:43:40
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:47:45
+ --> $DIR/attr-stmt-expr-attr-bad.rs:45:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
| ---- ^^^^^^^ -- the attributes are attached to this branch
@@ -182,7 +182,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; }
| the branch belongs to this `else`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:49:46
+ --> $DIR/attr-stmt-expr-attr-bad.rs:47:46
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
| ^^^^^^^^
@@ -191,7 +191,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:51:45
+ --> $DIR/attr-stmt-expr-attr-bad.rs:49:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| ---- ^^^^^^^ ------- the attributes are attached to this branch
@@ -200,7 +200,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; }
| the branch belongs to this `else`
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:53:50
+ --> $DIR/attr-stmt-expr-attr-bad.rs:51:50
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
@@ -209,7 +209,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:55:51
+ --> $DIR/attr-stmt-expr-attr-bad.rs:53:51
|
LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
| ^^^^^^^^
@@ -218,7 +218,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:57:45
+ --> $DIR/attr-stmt-expr-attr-bad.rs:55:45
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
@@ -227,7 +227,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:59:46
+ --> $DIR/attr-stmt-expr-attr-bad.rs:57:46
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
| ^^^^^^^^
@@ -236,13 +236,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:61:48
+ --> $DIR/attr-stmt-expr-attr-bad.rs:59:48
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:63:53
+ --> $DIR/attr-stmt-expr-attr-bad.rs:61:53
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| ---- ^^^^^^^ -- the attributes are attached to this branch
@@ -251,7 +251,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; }
| the branch belongs to this `else`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:65:54
+ --> $DIR/attr-stmt-expr-attr-bad.rs:63:54
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
| ^^^^^^^^
@@ -260,7 +260,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:67:53
+ --> $DIR/attr-stmt-expr-attr-bad.rs:65:53
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; }
| ---- ^^^^^^^ --------------- the attributes are attached to this branch
@@ -269,7 +269,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}
| the branch belongs to this `else`
error: outer attributes are not allowed on `if` and `else` branches
- --> $DIR/attr-stmt-expr-attr-bad.rs:69:66
+ --> $DIR/attr-stmt-expr-attr-bad.rs:67:66
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; }
| -- ^^^^^^^ -- the attributes are attached to this branch
@@ -278,7 +278,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}
| the branch belongs to this `if`
error: an inner attribute is not permitted in this context
- --> $DIR/attr-stmt-expr-attr-bad.rs:71:67
+ --> $DIR/attr-stmt-expr-attr-bad.rs:69:67
|
LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; }
| ^^^^^^^^
@@ -287,7 +287,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted following an outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:74:32
+ --> $DIR/attr-stmt-expr-attr-bad.rs:72:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@@ -298,7 +298,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted following an outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:76:32
+ --> $DIR/attr-stmt-expr-attr-bad.rs:74:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
| ------- ^^^^^^^^ not permitted following an outer attribute
@@ -309,7 +309,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; }
= note: outer attributes, like `#[test]`, annotate the item following them
error: an inner attribute is not permitted following an outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
+ --> $DIR/attr-stmt-expr-attr-bad.rs:76:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); }
| ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
@@ -325,7 +325,7 @@ LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!(); }
|
error: an inner attribute is not permitted following an outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
+ --> $DIR/attr-stmt-expr-attr-bad.rs:78:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; }
| ------- ^^^^^^^^ ------- the inner attribute doesn't annotate this item macro invocation
@@ -341,7 +341,7 @@ LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo![]; }
|
error: an inner attribute is not permitted following an outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:82:32
+ --> $DIR/attr-stmt-expr-attr-bad.rs:80:32
|
LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; }
| ------- ^^^^^^^^ ------ the inner attribute doesn't annotate this item macro invocation
@@ -357,7 +357,7 @@ LL + #[cfg(FALSE)] fn s() { #[attr] #[attr] foo!{}; }
|
error[E0586]: inclusive range with no end
- --> $DIR/attr-stmt-expr-attr-bad.rs:88:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:86:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^^^ help: use `..` instead
@@ -365,13 +365,13 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:88:38
+ --> $DIR/attr-stmt-expr-attr-bad.rs:86:38
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
| ^ expected one of `=>`, `if`, or `|`
error[E0586]: inclusive range with no end
- --> $DIR/attr-stmt-expr-attr-bad.rs:91:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:89:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
| ^^^ help: use `..` instead
@@ -379,19 +379,19 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:91:38
+ --> $DIR/attr-stmt-expr-attr-bad.rs:89:38
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
| ^ expected one of `=>`, `if`, or `|`
error: unexpected token: `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:94:39
+ --> $DIR/attr-stmt-expr-attr-bad.rs:92:39
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
| ^
error[E0586]: inclusive range with no end
- --> $DIR/attr-stmt-expr-attr-bad.rs:96:35
+ --> $DIR/attr-stmt-expr-attr-bad.rs:94:35
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^^^ help: use `..` instead
@@ -399,43 +399,43 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: expected one of `=>`, `if`, or `|`, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:96:38
+ --> $DIR/attr-stmt-expr-attr-bad.rs:94:38
|
LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
| ^ expected one of `=>`, `if`, or `|`
error: unexpected token: `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+ --> $DIR/attr-stmt-expr-attr-bad.rs:98:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:100:34
+ --> $DIR/attr-stmt-expr-attr-bad.rs:98:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: unexpected token: `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
+ --> $DIR/attr-stmt-expr-attr-bad.rs:101:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
| ^
error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#`
- --> $DIR/attr-stmt-expr-attr-bad.rs:103:34
+ --> $DIR/attr-stmt-expr-attr-bad.rs:101:34
|
LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); }
| ^ expected one of `.`, `;`, `?`, `else`, or an operator
error: expected statement after outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:108:37
+ --> $DIR/attr-stmt-expr-attr-bad.rs:106:37
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } }
| ^^^^^^^
error: expected statement after outer attribute
- --> $DIR/attr-stmt-expr-attr-bad.rs:110:37
+ --> $DIR/attr-stmt-expr-attr-bad.rs:108:37
|
LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } }
| ^^^^^^^
diff --git a/src/test/ui/parser/bad-let-as-field.rs b/src/test/ui/parser/bad-let-as-field.rs
new file mode 100644
index 000000000..fec2bc256
--- /dev/null
+++ b/src/test/ui/parser/bad-let-as-field.rs
@@ -0,0 +1,6 @@
+struct Foo {
+ let: i32,
+ //~^ ERROR expected identifier, found keyword
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/bad-let-as-field.stderr b/src/test/ui/parser/bad-let-as-field.stderr
new file mode 100644
index 000000000..57def42b1
--- /dev/null
+++ b/src/test/ui/parser/bad-let-as-field.stderr
@@ -0,0 +1,15 @@
+error: expected identifier, found keyword `let`
+ --> $DIR/bad-let-as-field.rs:2:5
+ |
+LL | struct Foo {
+ | --- while parsing this struct
+LL | let: i32,
+ | ^^^ expected identifier, found keyword
+ |
+help: escape `let` to use it as an identifier
+ |
+LL | r#let: i32,
+ | ++
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/bad-lit-suffixes.rs b/src/test/ui/parser/bad-lit-suffixes.rs
index 446a09405..9724533c4 100644
--- a/src/test/ui/parser/bad-lit-suffixes.rs
+++ b/src/test/ui/parser/bad-lit-suffixes.rs
@@ -1,18 +1,18 @@
extern
- "C"suffix //~ ERROR suffixes on a string literal are invalid
+ "C"suffix //~ ERROR suffixes on string literals are invalid
fn foo() {}
extern
- "C"suffix //~ ERROR suffixes on a string literal are invalid
+ "C"suffix //~ ERROR suffixes on string literals are invalid
{}
fn main() {
- ""suffix; //~ ERROR suffixes on a string literal are invalid
- b""suffix; //~ ERROR suffixes on a byte string literal are invalid
- r#""#suffix; //~ ERROR suffixes on a string literal are invalid
- br#""#suffix; //~ ERROR suffixes on a byte string literal are invalid
- 'a'suffix; //~ ERROR suffixes on a char literal are invalid
- b'a'suffix; //~ ERROR suffixes on a byte literal are invalid
+ ""suffix; //~ ERROR suffixes on string literals are invalid
+ b""suffix; //~ ERROR suffixes on byte string literals are invalid
+ r#""#suffix; //~ ERROR suffixes on string literals are invalid
+ br#""#suffix; //~ ERROR suffixes on byte string literals are invalid
+ 'a'suffix; //~ ERROR suffixes on char literals are invalid
+ b'a'suffix; //~ ERROR suffixes on byte literals are invalid
1234u1024; //~ ERROR invalid width `1024` for integer literal
1234i1024; //~ ERROR invalid width `1024` for integer literal
diff --git a/src/test/ui/parser/bad-lit-suffixes.stderr b/src/test/ui/parser/bad-lit-suffixes.stderr
index 9b5965714..f74eef324 100644
--- a/src/test/ui/parser/bad-lit-suffixes.stderr
+++ b/src/test/ui/parser/bad-lit-suffixes.stderr
@@ -1,46 +1,46 @@
-error: suffixes on a string literal are invalid
+error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:2:5
|
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a string literal are invalid
+error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:6:5
|
LL | "C"suffix
| ^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a string literal are invalid
+error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:10:5
|
LL | ""suffix;
| ^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a byte string literal are invalid
+error: suffixes on byte string literals are invalid
--> $DIR/bad-lit-suffixes.rs:11:5
|
LL | b""suffix;
| ^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a string literal are invalid
+error: suffixes on string literals are invalid
--> $DIR/bad-lit-suffixes.rs:12:5
|
LL | r#""#suffix;
| ^^^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a byte string literal are invalid
+error: suffixes on byte string literals are invalid
--> $DIR/bad-lit-suffixes.rs:13:5
|
LL | br#""#suffix;
| ^^^^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a char literal are invalid
+error: suffixes on char literals are invalid
--> $DIR/bad-lit-suffixes.rs:14:5
|
LL | 'a'suffix;
| ^^^^^^^^^ invalid suffix `suffix`
-error: suffixes on a byte literal are invalid
+error: suffixes on byte literals are invalid
--> $DIR/bad-lit-suffixes.rs:15:5
|
LL | b'a'suffix;
diff --git a/src/test/ui/parser/bad-pointer-type.rs b/src/test/ui/parser/bad-pointer-type.rs
index 59e5e0c5d..6a82acb4c 100644
--- a/src/test/ui/parser/bad-pointer-type.rs
+++ b/src/test/ui/parser/bad-pointer-type.rs
@@ -1,5 +1,5 @@
fn foo(_: *()) {
- //~^ ERROR expected mut or const in raw pointer type
+ //~^ ERROR expected `mut` or `const` keyword in raw pointer type
}
fn main() {}
diff --git a/src/test/ui/parser/bad-pointer-type.stderr b/src/test/ui/parser/bad-pointer-type.stderr
index e18c220af..b7225ca88 100644
--- a/src/test/ui/parser/bad-pointer-type.stderr
+++ b/src/test/ui/parser/bad-pointer-type.stderr
@@ -1,10 +1,15 @@
-error: expected mut or const in raw pointer type
+error: expected `mut` or `const` keyword in raw pointer type
--> $DIR/bad-pointer-type.rs:1:11
|
LL | fn foo(_: *()) {
- | ^ expected mut or const in raw pointer type
+ | ^
|
- = help: use `*mut T` or `*const T` as appropriate
+help: add `mut` or `const` here
+ |
+LL | fn foo(_: *const ()) {
+ | +++++
+LL | fn foo(_: *mut ()) {
+ | +++
error: aborting due to previous error
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 5b763ae72..37aa48ccf 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -29,9 +29,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/default.rs:22:1
diff --git a/src/test/ui/parser/doc-after-struct-field.rs b/src/test/ui/parser/doc-after-struct-field.rs
index 5b6f08036..03faa6733 100644
--- a/src/test/ui/parser/doc-after-struct-field.rs
+++ b/src/test/ui/parser/doc-after-struct-field.rs
@@ -1,13 +1,13 @@
struct X {
a: u8 /** document a */,
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
struct Y {
a: u8 /// document a
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
fn main() {
diff --git a/src/test/ui/parser/doc-after-struct-field.stderr b/src/test/ui/parser/doc-after-struct-field.stderr
index e3b32a7f0..ae177f1a2 100644
--- a/src/test/ui/parser/doc-after-struct-field.stderr
+++ b/src/test/ui/parser/doc-after-struct-field.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | a: u8 /** document a */,
| ^^^^^^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error[E0585]: found a documentation comment that doesn't document anything
--> $DIR/doc-after-struct-field.rs:8:11
@@ -12,7 +12,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | a: u8 /// document a
| ^^^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr
index 0edceb268..8fa12ec26 100644
--- a/src/test/ui/parser/doc-before-extern-rbrace.stderr
+++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr
@@ -4,7 +4,7 @@ error[E0584]: found a documentation comment that doesn't document anything
LL | /// hi
| ^^^^^^ this doc comment doesn't document anything
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-fn-rbrace.rs b/src/test/ui/parser/doc-before-fn-rbrace.rs
index eb355136f..c85021648 100644
--- a/src/test/ui/parser/doc-before-fn-rbrace.rs
+++ b/src/test/ui/parser/doc-before-fn-rbrace.rs
@@ -1,5 +1,5 @@
fn main() {
/// document
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
diff --git a/src/test/ui/parser/doc-before-fn-rbrace.stderr b/src/test/ui/parser/doc-before-fn-rbrace.stderr
index 56241de70..6ea68e42b 100644
--- a/src/test/ui/parser/doc-before-fn-rbrace.stderr
+++ b/src/test/ui/parser/doc-before-fn-rbrace.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | /// document
| ^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-rbrace.rs b/src/test/ui/parser/doc-before-rbrace.rs
index 8ff946344..570306f2c 100644
--- a/src/test/ui/parser/doc-before-rbrace.rs
+++ b/src/test/ui/parser/doc-before-rbrace.rs
@@ -1,5 +1,5 @@
fn main() {
println!("Hi"); /// hi
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
diff --git a/src/test/ui/parser/doc-before-rbrace.stderr b/src/test/ui/parser/doc-before-rbrace.stderr
index 55719cf64..4d4741dfe 100644
--- a/src/test/ui/parser/doc-before-rbrace.stderr
+++ b/src/test/ui/parser/doc-before-rbrace.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | println!("Hi"); /// hi
| ^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs
index 405a7e1e2..444b5874e 100644
--- a/src/test/ui/parser/doc-before-semi.rs
+++ b/src/test/ui/parser/doc-before-semi.rs
@@ -1,6 +1,6 @@
fn main() {
/// hi
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
;
}
diff --git a/src/test/ui/parser/doc-before-semi.stderr b/src/test/ui/parser/doc-before-semi.stderr
index e6bade18d..a879e13ff 100644
--- a/src/test/ui/parser/doc-before-semi.stderr
+++ b/src/test/ui/parser/doc-before-semi.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | /// hi
| ^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.rs b/src/test/ui/parser/doc-before-struct-rbrace-1.rs
index 3866a3105..0c8d90c3b 100644
--- a/src/test/ui/parser/doc-before-struct-rbrace-1.rs
+++ b/src/test/ui/parser/doc-before-struct-rbrace-1.rs
@@ -2,7 +2,7 @@ struct X {
a: u8,
/// document
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
fn main() {
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
index 19f906773..94934f734 100644
--- a/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
+++ b/src/test/ui/parser/doc-before-struct-rbrace-1.stderr
@@ -1,10 +1,13 @@
error[E0585]: found a documentation comment that doesn't document anything
--> $DIR/doc-before-struct-rbrace-1.rs:3:5
|
+LL | struct X {
+ | - while parsing this struct
+LL | a: u8,
LL | /// document
| ^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.rs b/src/test/ui/parser/doc-before-struct-rbrace-2.rs
index dda138f1a..2b2aadf79 100644
--- a/src/test/ui/parser/doc-before-struct-rbrace-2.rs
+++ b/src/test/ui/parser/doc-before-struct-rbrace-2.rs
@@ -1,7 +1,7 @@
struct X {
a: u8 /// document
//~^ ERROR found a documentation comment that doesn't document anything
- //~| HELP maybe a comment was intended
+ //~| HELP if a comment was intended use `//`
}
fn main() {
diff --git a/src/test/ui/parser/doc-before-struct-rbrace-2.stderr b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr
index b25ccab79..6b5c8c1f8 100644
--- a/src/test/ui/parser/doc-before-struct-rbrace-2.stderr
+++ b/src/test/ui/parser/doc-before-struct-rbrace-2.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | a: u8 /// document
| ^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr
index 246255a0a..900124adc 100644
--- a/src/test/ui/parser/doc-inside-trait-item.stderr
+++ b/src/test/ui/parser/doc-inside-trait-item.stderr
@@ -4,7 +4,7 @@ error[E0584]: found a documentation comment that doesn't document anything
LL | /// empty doc
| ^^^^^^^^^^^^^ this doc comment doesn't document anything
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/double-pointer.rs b/src/test/ui/parser/double-pointer.rs
new file mode 100644
index 000000000..54d34db4a
--- /dev/null
+++ b/src/test/ui/parser/double-pointer.rs
@@ -0,0 +1,7 @@
+fn main() {
+ let x: i32 = 5;
+ let ptr: *const i32 = &x;
+ let dptr: **const i32 = &ptr;
+ //~^ ERROR expected `mut` or `const` keyword in raw pointer type
+ //~| HELP add `mut` or `const` here
+}
diff --git a/src/test/ui/parser/double-pointer.stderr b/src/test/ui/parser/double-pointer.stderr
new file mode 100644
index 000000000..28037f932
--- /dev/null
+++ b/src/test/ui/parser/double-pointer.stderr
@@ -0,0 +1,15 @@
+error: expected `mut` or `const` keyword in raw pointer type
+ --> $DIR/double-pointer.rs:4:15
+ |
+LL | let dptr: **const i32 = &ptr;
+ | ^
+ |
+help: add `mut` or `const` here
+ |
+LL | let dptr: *const *const i32 = &ptr;
+ | +++++
+LL | let dptr: *mut *const i32 = &ptr;
+ | +++
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr
index 2550dc3d3..e645b68ba 100644
--- a/src/test/ui/parser/emoji-identifiers.stderr
+++ b/src/test/ui/parser/emoji-identifiers.stderr
@@ -9,15 +9,6 @@ help: Unicode character '➖' (Heavy Minus Sign) looks like '-' (Minus/Hyphen),
LL | let _ = i_like_to_😄_a_lot() - 4;
| ~
-error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope
- --> $DIR/emoji-identifiers.rs:13:13
- |
-LL | fn i_like_to_😅_a_lot() -> 👀 {
- | ----------------------------- similarly named function `i_like_to_😅_a_lot` defined here
-...
-LL | let _ = i_like_to_😄_a_lot() ➖ 4;
- | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot`
-
error: Ferris cannot be used as an identifier
--> $DIR/emoji-identifiers.rs:17:9
|
@@ -85,6 +76,15 @@ LL | 👀::full_of✨()
| function or associated item not found in `👀`
| help: there is an associated function with a similar name: `full_of_✨`
+error[E0425]: cannot find function `i_like_to_😄_a_lot` in this scope
+ --> $DIR/emoji-identifiers.rs:13:13
+ |
+LL | fn i_like_to_😅_a_lot() -> 👀 {
+ | ----------------------------- similarly named function `i_like_to_😅_a_lot` defined here
+...
+LL | let _ = i_like_to_😄_a_lot() ➖ 4;
+ | ^^^^^^^^^^^^^^^^^^ help: a function with a similar name exists: `i_like_to_😅_a_lot`
+
error: aborting due to 10 previous errors
Some errors have detailed explanations: E0425, E0599.
diff --git a/src/test/ui/parser/empty-impl-semicolon.rs b/src/test/ui/parser/empty-impl-semicolon.rs
index 207ebef64..2485f5b85 100644
--- a/src/test/ui/parser/empty-impl-semicolon.rs
+++ b/src/test/ui/parser/empty-impl-semicolon.rs
@@ -1 +1,4 @@
-impl Foo; //~ ERROR expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
+struct Foo;
+impl Foo; //~ ERROR expected `{}`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/empty-impl-semicolon.stderr b/src/test/ui/parser/empty-impl-semicolon.stderr
index 398eb5c89..6ed309eba 100644
--- a/src/test/ui/parser/empty-impl-semicolon.stderr
+++ b/src/test/ui/parser/empty-impl-semicolon.stderr
@@ -1,8 +1,10 @@
-error: expected one of `!`, `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
- --> $DIR/empty-impl-semicolon.rs:1:9
+error: expected `{}`, found `;`
+ --> $DIR/empty-impl-semicolon.rs:2:9
|
LL | impl Foo;
- | ^ expected one of 8 possible tokens
+ | ^
+ |
+ = help: try using `{}` instead
error: aborting due to previous error
diff --git a/src/test/ui/parser/expr-as-stmt-2.stderr b/src/test/ui/parser/expr-as-stmt-2.stderr
index 9b939f05e..2b6314c38 100644
--- a/src/test/ui/parser/expr-as-stmt-2.stderr
+++ b/src/test/ui/parser/expr-as-stmt-2.stderr
@@ -36,11 +36,6 @@ LL | / &&
LL | | if let Some(y) = a { true } else { false }
| |______________________________________________^ expected `bool`, found `&&bool`
|
-help: consider removing the `&&`
- |
-LL - &&
-LL + if let Some(y) = a { true } else { false }
- |
help: parentheses are required to parse this as an expression
|
LL | (if let Some(x) = a { true } else { false })
diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr
index 858b4e8db..6da4ac340 100644
--- a/src/test/ui/parser/expr-as-stmt.stderr
+++ b/src/test/ui/parser/expr-as-stmt.stderr
@@ -170,11 +170,6 @@ LL | fn revenge_from_mars() -> bool {
LL | { true } && { true }
| ^^^^^^^^^^^ expected `bool`, found `&&bool`
|
-help: consider removing the `&&`
- |
-LL - { true } && { true }
-LL + { true } { true }
- |
help: parentheses are required to parse this as an expression
|
LL | ({ true }) && { true }
@@ -201,10 +196,6 @@ LL | { true } || { true }
|
= note: expected type `bool`
found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:16]`
-help: use parentheses to call this closure
- |
-LL | { true } (|| { true })()
- | + +++
help: parentheses are required to parse this as an expression
|
LL | ({ true }) || { true }
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.rs b/src/test/ui/parser/fn-field-parse-error-ice.rs
index 4ea55062f..188257ea5 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.rs
+++ b/src/test/ui/parser/fn-field-parse-error-ice.rs
@@ -3,7 +3,7 @@
struct Baz {
inner : dyn fn ()
//~^ ERROR expected `,`, or `}`, found keyword `fn`
- //~| ERROR functions are not allowed in struct definitions
+ //~| ERROR expected identifier, found keyword `fn`
//~| ERROR cannot find type `dyn` in this scope
}
diff --git a/src/test/ui/parser/fn-field-parse-error-ice.stderr b/src/test/ui/parser/fn-field-parse-error-ice.stderr
index d582f61cc..3bf68e8cc 100644
--- a/src/test/ui/parser/fn-field-parse-error-ice.stderr
+++ b/src/test/ui/parser/fn-field-parse-error-ice.stderr
@@ -4,14 +4,18 @@ error: expected `,`, or `}`, found keyword `fn`
LL | inner : dyn fn ()
| ^ help: try adding a comma: `,`
-error: functions are not allowed in struct definitions
+error: expected identifier, found keyword `fn`
--> $DIR/fn-field-parse-error-ice.rs:4:17
|
+LL | struct Baz {
+ | --- while parsing this struct
LL | inner : dyn fn ()
- | ^^
+ | ^^ expected identifier, found keyword
|
- = help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
- = help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
+help: escape `fn` to use it as an identifier
+ |
+LL | inner : dyn r#fn ()
+ | ++
error[E0412]: cannot find type `dyn` in this scope
--> $DIR/fn-field-parse-error-ice.rs:4:13
diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr
index 36304779d..038fdfb2d 100644
--- a/src/test/ui/parser/fn-header-semantic-fail.stderr
+++ b/src/test/ui/parser/fn-header-semantic-fail.stderr
@@ -147,7 +147,7 @@ LL | async fn ft1();
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:21:9
@@ -160,7 +160,7 @@ LL | const async unsafe extern "C" fn ft5();
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:29:9
@@ -173,7 +173,7 @@ LL | async fn ft1() {}
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/fn-header-semantic-fail.rs:33:9
@@ -186,7 +186,7 @@ LL | const async unsafe extern "C" fn ft5() {}
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0391]: cycle detected when computing type of `main::ff5::{opaque#0}`
--> $DIR/fn-header-semantic-fail.rs:12:44
@@ -199,7 +199,7 @@ note: ...which requires borrow-checking `main::ff5`...
|
LL | const async unsafe extern "C" fn ff5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `main::ff5`...
+note: ...which requires processing MIR for `main::ff5`...
--> $DIR/fn-header-semantic-fail.rs:12:5
|
LL | const async unsafe extern "C" fn ff5() {}
@@ -235,7 +235,7 @@ note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-
|
LL | const async unsafe extern "C" fn ft5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`...
+note: ...which requires processing MIR for `main::<impl at $DIR/fn-header-semantic-fail.rs:28:5: 28:17>::ft5`...
--> $DIR/fn-header-semantic-fail.rs:33:9
|
LL | const async unsafe extern "C" fn ft5() {}
@@ -271,7 +271,7 @@ note: ...which requires borrow-checking `main::<impl at $DIR/fn-header-semantic-
|
LL | const async unsafe extern "C" fn fi5() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires processing `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5`...
+note: ...which requires processing MIR for `main::<impl at $DIR/fn-header-semantic-fail.rs:40:5: 40:11>::fi5`...
--> $DIR/fn-header-semantic-fail.rs:45:9
|
LL | const async unsafe extern "C" fn fi5() {}
diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.stderr b/src/test/ui/parser/inner-attr-after-doc-comment.stderr
index 2cfafac77..3ec3ad8e9 100644
--- a/src/test/ui/parser/inner-attr-after-doc-comment.stderr
+++ b/src/test/ui/parser/inner-attr-after-doc-comment.stderr
@@ -7,7 +7,7 @@ LL | | */
| |___- previous doc comment
LL |
LL | #![recursion_limit="100"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer doc comment
LL |
LL | fn main() {}
| ------------ the inner attribute doesn't annotate this function
diff --git a/src/test/ui/parser/issue-103143.rs b/src/test/ui/parser/issue-103143.rs
new file mode 100644
index 000000000..a584274c4
--- /dev/null
+++ b/src/test/ui/parser/issue-103143.rs
@@ -0,0 +1,5 @@
+fn main() {
+ x::<#[a]y::<z>>
+ //~^ ERROR invalid const generic expression
+ //~| ERROR cannot find value `x` in this scope
+}
diff --git a/src/test/ui/parser/issue-103143.stderr b/src/test/ui/parser/issue-103143.stderr
new file mode 100644
index 000000000..4035c69af
--- /dev/null
+++ b/src/test/ui/parser/issue-103143.stderr
@@ -0,0 +1,20 @@
+error: invalid const generic expression
+ --> $DIR/issue-103143.rs:2:13
+ |
+LL | x::<#[a]y::<z>>
+ | ^^^^^^
+ |
+help: expressions must be enclosed in braces to be used as const generic arguments
+ |
+LL | x::<#[a]{ y::<z> }>
+ | + +
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-103143.rs:2:5
+ |
+LL | x::<#[a]y::<z>>
+ | ^ not found in this scope
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/issue-103425.rs b/src/test/ui/parser/issue-103425.rs
new file mode 100644
index 000000000..c2f8123ca
--- /dev/null
+++ b/src/test/ui/parser/issue-103425.rs
@@ -0,0 +1,15 @@
+fn f() -> f32 {
+ 3
+ //~^ ERROR expected `;`
+ 5.0
+}
+
+fn k() -> f32 {
+ 2_u32
+ //~^ ERROR expected `;`
+ 3_i8
+ //~^ ERROR expected `;`
+ 5.0
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issue-103425.stderr b/src/test/ui/parser/issue-103425.stderr
new file mode 100644
index 000000000..0efe3e3ca
--- /dev/null
+++ b/src/test/ui/parser/issue-103425.stderr
@@ -0,0 +1,29 @@
+error: expected `;`, found `5.0`
+ --> $DIR/issue-103425.rs:2:6
+ |
+LL | 3
+ | ^ help: add `;` here
+LL |
+LL | 5.0
+ | --- unexpected token
+
+error: expected `;`, found `3_i8`
+ --> $DIR/issue-103425.rs:8:10
+ |
+LL | 2_u32
+ | ^ help: add `;` here
+LL |
+LL | 3_i8
+ | ---- unexpected token
+
+error: expected `;`, found `5.0`
+ --> $DIR/issue-103425.rs:10:9
+ |
+LL | 3_i8
+ | ^ help: add `;` here
+LL |
+LL | 5.0
+ | --- unexpected token
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/issues/issue-17718-parse-const.rs b/src/test/ui/parser/issue-17718-parse-const.rs
index d5a5f445d..d5a5f445d 100644
--- a/src/test/ui/issues/issue-17718-parse-const.rs
+++ b/src/test/ui/parser/issue-17718-parse-const.rs
diff --git a/src/test/ui/parser/issues/issue-101540.rs b/src/test/ui/parser/issues/issue-101540.rs
new file mode 100644
index 000000000..328ec6f90
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-101540.rs
@@ -0,0 +1,7 @@
+struct S1 {
+ struct S2 {
+ //~^ ERROR structs are not allowed in struct definitions
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/issues/issue-101540.stderr b/src/test/ui/parser/issues/issue-101540.stderr
new file mode 100644
index 000000000..8af887050
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-101540.stderr
@@ -0,0 +1,12 @@
+error: structs are not allowed in struct definitions
+ --> $DIR/issue-101540.rs:2:5
+ |
+LL | struct S1 {
+ | -- while parsing this struct
+LL | struct S2 {
+ | ^^^^^^^^^
+ |
+ = help: consider creating a new `struct` definition instead of nesting
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issues/issue-102182-impl-trait-recover.rs b/src/test/ui/parser/issues/issue-102182-impl-trait-recover.rs
new file mode 100644
index 000000000..4bfc676d6
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-102182-impl-trait-recover.rs
@@ -0,0 +1,3 @@
+fn foo<T: impl Trait>() {}
+//~^ ERROR expected trait bound, found `impl Trait` type
+fn main() {}
diff --git a/src/test/ui/parser/issues/issue-102182-impl-trait-recover.stderr b/src/test/ui/parser/issues/issue-102182-impl-trait-recover.stderr
new file mode 100644
index 000000000..52b6ae5df
--- /dev/null
+++ b/src/test/ui/parser/issues/issue-102182-impl-trait-recover.stderr
@@ -0,0 +1,14 @@
+error: expected trait bound, found `impl Trait` type
+ --> $DIR/issue-102182-impl-trait-recover.rs:1:11
+ |
+LL | fn foo<T: impl Trait>() {}
+ | ^^^^^^^^^^ not a trait
+ |
+help: use the trait bounds directly
+ |
+LL - fn foo<T: impl Trait>() {}
+LL + fn foo<T: Trait>() {}
+ |
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issues/issue-17383.rs b/src/test/ui/parser/issues/issue-17383.rs
deleted file mode 100644
index 7bf0e64f2..000000000
--- a/src/test/ui/parser/issues/issue-17383.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-enum X {
- A = 3,
- //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
- B(usize)
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/issues/issue-17383.stderr b/src/test/ui/parser/issues/issue-17383.stderr
deleted file mode 100644
index 265d6e148..000000000
--- a/src/test/ui/parser/issues/issue-17383.stderr
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
- --> $DIR/issue-17383.rs:2:9
- |
-LL | A = 3,
- | ^ disallowed custom discriminant
-LL |
-LL | B(usize)
- | -------- tuple variant defined here
- |
- = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
- = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/issues/issue-34222-1.stderr b/src/test/ui/parser/issues/issue-34222-1.stderr
index 0799656b0..b451484ba 100644
--- a/src/test/ui/parser/issues/issue-34222-1.stderr
+++ b/src/test/ui/parser/issues/issue-34222-1.stderr
@@ -4,7 +4,7 @@ error[E0585]: found a documentation comment that doesn't document anything
LL | /// comment
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/issues/issue-48636.stderr b/src/test/ui/parser/issues/issue-48636.stderr
index 462723d1d..6177870d1 100644
--- a/src/test/ui/parser/issues/issue-48636.stderr
+++ b/src/test/ui/parser/issues/issue-48636.stderr
@@ -1,12 +1,14 @@
error[E0585]: found a documentation comment that doesn't document anything
--> $DIR/issue-48636.rs:7:5
|
+LL | struct S {
+ | - while parsing this struct
LL | x: u8
| - help: missing comma here: `,`
LL | /// The ID of the parent core
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = help: doc comments must come before what they document, maybe a comment was intended with `//`?
+ = help: doc comments must come before what they document, if a comment was intended use `//`
error: aborting due to previous error
diff --git a/src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs b/src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs
index 8efb3c73f..b6e5091b6 100644
--- a/src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs
+++ b/src/test/ui/parser/issues/issue-63115-range-pat-interpolated.rs
@@ -1,7 +1,6 @@
// check-pass
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
#![allow(ellipsis_inclusive_range_patterns)]
diff --git a/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
index ef365a616..adabb6859 100644
--- a/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
+++ b/src/test/ui/parser/issues/issue-68000-unicode-ident-after-missing-comma.stderr
@@ -7,6 +7,8 @@ LL | pub bar: Vec<i32>ö
error: expected `:`, found `}`
--> $DIR/issue-68000-unicode-ident-after-missing-comma.rs:4:1
|
+LL | pub struct Foo {
+ | --- while parsing this struct
LL | pub bar: Vec<i32>ö
| - expected `:`
LL |
diff --git a/src/test/ui/parser/issues/issue-8537.stderr b/src/test/ui/parser/issues/issue-8537.stderr
index 505d830ef..523cc9dc5 100644
--- a/src/test/ui/parser/issues/issue-8537.stderr
+++ b/src/test/ui/parser/issues/issue-8537.stderr
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
LL | "invalid-ab_isize"
| ^^^^^^^^^^^^^^^^^^ invalid ABI
|
- = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted, rust-cold
+ = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
error: aborting due to previous error
diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs
index 261fcb5f9..274245f1a 100644
--- a/src/test/ui/parser/issues/issue-93282.rs
+++ b/src/test/ui/parser/issues/issue-93282.rs
@@ -12,4 +12,5 @@ fn foo() {
let x = 1;
bar('y, x);
//~^ ERROR expected
+ //~| ERROR mismatched types
}
diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr
index ee554784b..c6140bb82 100644
--- a/src/test/ui/parser/issues/issue-93282.stderr
+++ b/src/test/ui/parser/issues/issue-93282.stderr
@@ -3,6 +3,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
LL | f<'a,>
| ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | f<'a',>
+ | +
error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `}`, or an operator, found `,`
--> $DIR/issue-93282.rs:2:9
@@ -20,6 +25,26 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
LL | bar('y, x);
| ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | bar('y', x);
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/issue-93282.rs:13:9
+ |
+LL | bar('y, x);
+ | --- ^^ expected `usize`, found `char`
+ | |
+ | arguments to this function are incorrect
+ |
+note: function defined here
+ --> $DIR/issue-93282.rs:7:4
+ |
+LL | fn bar(a: usize, b: usize) -> usize {
+ | ^^^ --------
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/item-needs-block.rs b/src/test/ui/parser/item-needs-block.rs
new file mode 100644
index 000000000..4edac588e
--- /dev/null
+++ b/src/test/ui/parser/item-needs-block.rs
@@ -0,0 +1,10 @@
+trait Trait;
+//~^ ERROR expected `{}`, found `;`
+
+impl Trait for ();
+//~^ ERROR expected `{}`, found `;`
+
+enum Enum;
+//~^ ERROR expected `{}`, found `;`
+
+fn main() {}
diff --git a/src/test/ui/parser/item-needs-block.stderr b/src/test/ui/parser/item-needs-block.stderr
new file mode 100644
index 000000000..3cabd0c73
--- /dev/null
+++ b/src/test/ui/parser/item-needs-block.stderr
@@ -0,0 +1,26 @@
+error: expected `{}`, found `;`
+ --> $DIR/item-needs-block.rs:1:12
+ |
+LL | trait Trait;
+ | ^
+ |
+ = help: try using `{}` instead
+
+error: expected `{}`, found `;`
+ --> $DIR/item-needs-block.rs:4:18
+ |
+LL | impl Trait for ();
+ | ^
+ |
+ = help: try using `{}` instead
+
+error: expected `{}`, found `;`
+ --> $DIR/item-needs-block.rs:7:10
+ |
+LL | enum Enum;
+ | ^
+ |
+ = help: try using `{}` instead
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/parser/label-after-block-like.rs b/src/test/ui/parser/label-after-block-like.rs
new file mode 100644
index 000000000..55f3f8f9f
--- /dev/null
+++ b/src/test/ui/parser/label-after-block-like.rs
@@ -0,0 +1,43 @@
+fn a() {
+ if let () = () 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn b() {
+ if true 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn c() {
+ loop 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn d() {
+ while true 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn e() {
+ while let () = () 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn f() {
+ for _ in 0..0 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn g() {
+ unsafe 'a {}
+ //~^ ERROR labeled expression must be followed by `:`
+ //~| ERROR expected `{`, found `'a`
+}
+
+fn main() {}
diff --git a/src/test/ui/parser/label-after-block-like.stderr b/src/test/ui/parser/label-after-block-like.stderr
new file mode 100644
index 000000000..8ff50b124
--- /dev/null
+++ b/src/test/ui/parser/label-after-block-like.stderr
@@ -0,0 +1,176 @@
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:2:20
+ |
+LL | if let () = () 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:2:20
+ |
+LL | if let () = () 'a {}
+ | ^^ expected `{`
+ |
+note: the `if` expression is missing a block after this condition
+ --> $DIR/label-after-block-like.rs:2:8
+ |
+LL | if let () = () 'a {}
+ | ^^^^^^^^^^^
+help: try placing this code inside a block
+ |
+LL | if let () = () { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:8:13
+ |
+LL | if true 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:8:13
+ |
+LL | if true 'a {}
+ | ^^ expected `{`
+ |
+note: the `if` expression is missing a block after this condition
+ --> $DIR/label-after-block-like.rs:8:8
+ |
+LL | if true 'a {}
+ | ^^^^
+help: try placing this code inside a block
+ |
+LL | if true { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:14:10
+ |
+LL | loop 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:14:10
+ |
+LL | loop 'a {}
+ | ---- ^^ expected `{`
+ | |
+ | while parsing this `loop` expression
+ |
+help: try placing this code inside a block
+ |
+LL | loop { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:20:16
+ |
+LL | while true 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:20:16
+ |
+LL | while true 'a {}
+ | ----- ---- ^^ expected `{`
+ | | |
+ | | this `while` condition successfully parsed
+ | while parsing the body of this `while` expression
+ |
+help: try placing this code inside a block
+ |
+LL | while true { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:26:23
+ |
+LL | while let () = () 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:26:23
+ |
+LL | while let () = () 'a {}
+ | ----- ----------- ^^ expected `{`
+ | | |
+ | | this `while` condition successfully parsed
+ | while parsing the body of this `while` expression
+ |
+help: try placing this code inside a block
+ |
+LL | while let () = () { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:32:19
+ |
+LL | for _ in 0..0 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:32:19
+ |
+LL | for _ in 0..0 'a {}
+ | ^^ expected `{`
+ |
+help: try placing this code inside a block
+ |
+LL | for _ in 0..0 { 'a {} }
+ | + +
+
+error: labeled expression must be followed by `:`
+ --> $DIR/label-after-block-like.rs:38:12
+ |
+LL | unsafe 'a {}
+ | ---^^
+ | | |
+ | | help: add `:` after the label
+ | the label
+ |
+ = note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
+
+error: expected `{`, found `'a`
+ --> $DIR/label-after-block-like.rs:38:12
+ |
+LL | unsafe 'a {}
+ | ------ ^^ expected `{`
+ | |
+ | while parsing this `unsafe` expression
+ |
+help: try placing this code inside a block
+ |
+LL | unsafe { 'a {} }
+ | + +
+
+error: aborting due to 14 previous errors
+
diff --git a/src/test/ui/parser/label-is-actually-char.rs b/src/test/ui/parser/label-is-actually-char.rs
new file mode 100644
index 000000000..183da603d
--- /dev/null
+++ b/src/test/ui/parser/label-is-actually-char.rs
@@ -0,0 +1,16 @@
+fn main() {
+ let c = 'a;
+ //~^ ERROR expected `while`, `for`, `loop` or `{` after a label
+ //~| HELP add `'` to close the char literal
+ match c {
+ 'a'..='b => {}
+ //~^ ERROR unexpected token: `'b`
+ //~| HELP add `'` to close the char literal
+ _ => {}
+ }
+ let x = ['a, 'b];
+ //~^ ERROR expected `while`, `for`, `loop` or `{` after a label
+ //~| ERROR expected `while`, `for`, `loop` or `{` after a label
+ //~| HELP add `'` to close the char literal
+ //~| HELP add `'` to close the char literal
+}
diff --git a/src/test/ui/parser/label-is-actually-char.stderr b/src/test/ui/parser/label-is-actually-char.stderr
new file mode 100644
index 000000000..28c8d2ada
--- /dev/null
+++ b/src/test/ui/parser/label-is-actually-char.stderr
@@ -0,0 +1,46 @@
+error: expected `while`, `for`, `loop` or `{` after a label
+ --> $DIR/label-is-actually-char.rs:2:15
+ |
+LL | let c = 'a;
+ | ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | let c = 'a';
+ | +
+
+error: unexpected token: `'b`
+ --> $DIR/label-is-actually-char.rs:6:15
+ |
+LL | 'a'..='b => {}
+ | ^^
+ |
+help: add `'` to close the char literal
+ |
+LL | 'a'..='b' => {}
+ | +
+
+error: expected `while`, `for`, `loop` or `{` after a label
+ --> $DIR/label-is-actually-char.rs:11:16
+ |
+LL | let x = ['a, 'b];
+ | ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | let x = ['a', 'b];
+ | +
+
+error: expected `while`, `for`, `loop` or `{` after a label
+ --> $DIR/label-is-actually-char.rs:11:20
+ |
+LL | let x = ['a, 'b];
+ | ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | let x = ['a, 'b'];
+ | +
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/parser/macro/issue-33569.stderr b/src/test/ui/parser/macro/issue-33569.stderr
index 39d49fd03..0dca090fb 100644
--- a/src/test/ui/parser/macro/issue-33569.stderr
+++ b/src/test/ui/parser/macro/issue-33569.stderr
@@ -22,9 +22,9 @@ error: missing fragment specifier
LL | { $+ } => {
| ^
|
- = note: `#[deny(missing_fragment_specifier)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
+ = note: `#[deny(missing_fragment_specifier)]` on by default
error: aborting due to 4 previous errors
diff --git a/src/test/ui/parser/macro/issue-37113.stderr b/src/test/ui/parser/macro/issue-37113.stderr
index 0912858dd..b1f8674fb 100644
--- a/src/test/ui/parser/macro/issue-37113.stderr
+++ b/src/test/ui/parser/macro/issue-37113.stderr
@@ -1,6 +1,8 @@
error: expected identifier, found `String`
--> $DIR/issue-37113.rs:4:16
|
+LL | enum SomeEnum {
+ | -------- while parsing this enum
LL | $( $t, )*
| ^^ expected identifier
...
diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
index a47d5506e..ad1e90e43 100644
--- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
+++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-struct.stderr
@@ -10,6 +10,9 @@ 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
diff --git a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
index 46ca1f06b..6d8b0c3fc 100644
--- a/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
+++ b/src/test/ui/parser/missing-closing-angle-bracket-struct-field-ty.stderr
@@ -1,6 +1,9 @@
error: expected one of `>`, a const expression, lifetime, or type, found `}`
--> $DIR/missing-closing-angle-bracket-struct-field-ty.rs:9:1
|
+LL | pub struct Foo {
+ | --- while parsing this struct
+...
LL | c: Arc<Mutex<usize>>,
| - expected one of `>`, a const expression, lifetime, or type
LL | }
diff --git a/src/test/ui/parser/numeric-lifetime.stderr b/src/test/ui/parser/numeric-lifetime.stderr
index 73a828952..7c1bcb726 100644
--- a/src/test/ui/parser/numeric-lifetime.stderr
+++ b/src/test/ui/parser/numeric-lifetime.stderr
@@ -1,3 +1,11 @@
+error[E0308]: mismatched types
+ --> $DIR/numeric-lifetime.rs:6:20
+ |
+LL | let x: usize = "";
+ | ----- ^^ expected `usize`, found `&str`
+ | |
+ | expected due to this
+
error: lifetimes cannot start with a number
--> $DIR/numeric-lifetime.rs:1:10
|
@@ -10,14 +18,6 @@ error: lifetimes cannot start with a number
LL | struct S<'1> { s: &'1 usize }
| ^^
-error[E0308]: mismatched types
- --> $DIR/numeric-lifetime.rs:6:20
- |
-LL | let x: usize = "";
- | ----- ^^ expected `usize`, found `&str`
- | |
- | expected due to this
-
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/parser-recovery-1.stderr b/src/test/ui/parser/parser-recovery-1.stderr
index f56060c3e..0cb771ea3 100644
--- a/src/test/ui/parser/parser-recovery-1.stderr
+++ b/src/test/ui/parser/parser-recovery-1.stderr
@@ -18,18 +18,18 @@ error: unexpected token: `;`
LL | let x = y.;
| ^
-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[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
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/parser-recovery-2.stderr b/src/test/ui/parser/parser-recovery-2.stderr
index 0980d033f..8829cf4c1 100644
--- a/src/test/ui/parser/parser-recovery-2.stderr
+++ b/src/test/ui/parser/parser-recovery-2.stderr
@@ -13,18 +13,18 @@ LL | let x = foo();
LL | )
| ^ mismatched closing delimiter
-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[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
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/parser/recover-enum2.stderr b/src/test/ui/parser/recover-enum2.stderr
index ee29f0663..7634bca92 100644
--- a/src/test/ui/parser/recover-enum2.stderr
+++ b/src/test/ui/parser/recover-enum2.stderr
@@ -1,6 +1,8 @@
error: expected type, found `{`
--> $DIR/recover-enum2.rs:6:18
|
+LL | Var3 {
+ | ---- while parsing this struct
LL | abc: {},
| ^ expected type
diff --git a/src/test/ui/parser/recover-field-semi.stderr b/src/test/ui/parser/recover-field-semi.stderr
index 657366db9..3cf484748 100644
--- a/src/test/ui/parser/recover-field-semi.stderr
+++ b/src/test/ui/parser/recover-field-semi.stderr
@@ -1,12 +1,16 @@
error: struct fields are separated by `,`
--> $DIR/recover-field-semi.rs:2:13
|
+LL | struct Foo {
+ | --- while parsing this struct
LL | foo: i32;
| ^ help: replace `;` with `,`
error: union fields are separated by `,`
--> $DIR/recover-field-semi.rs:7:13
|
+LL | union Bar {
+ | --- while parsing this union
LL | foo: i32;
| ^ help: replace `;` with `,`
@@ -14,7 +18,9 @@ error: struct fields are separated by `,`
--> $DIR/recover-field-semi.rs:12:19
|
LL | Qux { foo: i32; }
- | ^ help: replace `;` with `,`
+ | --- ^ help: replace `;` with `,`
+ | |
+ | while parsing this struct
error: unions cannot have zero fields
--> $DIR/recover-field-semi.rs:6:1
diff --git a/src/test/ui/parser/recover-range-pats.rs b/src/test/ui/parser/recover-range-pats.rs
index 2e5a99154..156c7ad94 100644
--- a/src/test/ui/parser/recover-range-pats.rs
+++ b/src/test/ui/parser/recover-range-pats.rs
@@ -4,7 +4,6 @@
// 2. Or at least we have parser recovery if they don't.
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
#![deny(ellipsis_inclusive_range_patterns)]
fn main() {}
diff --git a/src/test/ui/parser/recover-range-pats.stderr b/src/test/ui/parser/recover-range-pats.stderr
index d0979b23f..c54f13e01 100644
--- a/src/test/ui/parser/recover-range-pats.stderr
+++ b/src/test/ui/parser/recover-range-pats.stderr
@@ -1,47 +1,47 @@
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:22:12
+ --> $DIR/recover-range-pats.rs:21:12
|
LL | if let .0..Y = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:24:16
+ --> $DIR/recover-range-pats.rs:23:16
|
LL | if let X.. .0 = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:35:12
+ --> $DIR/recover-range-pats.rs:34:12
|
LL | if let .0..=Y = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:37:16
+ --> $DIR/recover-range-pats.rs:36:16
|
LL | if let X..=.0 = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:60:12
+ --> $DIR/recover-range-pats.rs:59:12
|
LL | if let .0...Y = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:64:17
+ --> $DIR/recover-range-pats.rs:63:17
|
LL | if let X... .0 = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:75:12
+ --> $DIR/recover-range-pats.rs:74:12
|
LL | if let .0.. = 0 {}
| ^^ help: must have an integer part: `0.0`
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:81:13
+ --> $DIR/recover-range-pats.rs:80:13
|
LL | if let 0..= = 0 {}
| ^^^ help: use `..` instead
@@ -49,7 +49,7 @@ LL | if let 0..= = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:82:13
+ --> $DIR/recover-range-pats.rs:81:13
|
LL | if let X..= = 0 {}
| ^^^ help: use `..` instead
@@ -57,7 +57,7 @@ LL | if let X..= = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:83:16
+ --> $DIR/recover-range-pats.rs:82:16
|
LL | if let true..= = 0 {}
| ^^^ help: use `..` instead
@@ -65,13 +65,13 @@ LL | if let true..= = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:85:12
+ --> $DIR/recover-range-pats.rs:84:12
|
LL | if let .0..= = 0 {}
| ^^ help: must have an integer part: `0.0`
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:85:14
+ --> $DIR/recover-range-pats.rs:84:14
|
LL | if let .0..= = 0 {}
| ^^^ help: use `..` instead
@@ -79,7 +79,7 @@ LL | if let .0..= = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:91:13
+ --> $DIR/recover-range-pats.rs:90:13
|
LL | if let 0... = 0 {}
| ^^^ help: use `..` instead
@@ -87,7 +87,7 @@ LL | if let 0... = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:92:13
+ --> $DIR/recover-range-pats.rs:91:13
|
LL | if let X... = 0 {}
| ^^^ help: use `..` instead
@@ -95,7 +95,7 @@ LL | if let X... = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:93:16
+ --> $DIR/recover-range-pats.rs:92:16
|
LL | if let true... = 0 {}
| ^^^ help: use `..` instead
@@ -103,13 +103,13 @@ LL | if let true... = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:95:12
+ --> $DIR/recover-range-pats.rs:94:12
|
LL | if let .0... = 0 {}
| ^^ help: must have an integer part: `0.0`
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:95:14
+ --> $DIR/recover-range-pats.rs:94:14
|
LL | if let .0... = 0 {}
| ^^^ help: use `..` instead
@@ -117,49 +117,49 @@ LL | if let .0... = 0 {}
= note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:105:15
+ --> $DIR/recover-range-pats.rs:104:15
|
LL | if let .. .0 = 0 {}
| ^^ help: must have an integer part: `0.0`
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:115:15
+ --> $DIR/recover-range-pats.rs:114:15
|
LL | if let ..=.0 = 0 {}
| ^^ help: must have an integer part: `0.0`
error: range-to patterns with `...` are not allowed
- --> $DIR/recover-range-pats.rs:121:12
+ --> $DIR/recover-range-pats.rs:120:12
|
LL | if let ...3 = 0 {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/recover-range-pats.rs:123:12
+ --> $DIR/recover-range-pats.rs:122:12
|
LL | if let ...Y = 0 {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/recover-range-pats.rs:125:12
+ --> $DIR/recover-range-pats.rs:124:12
|
LL | if let ...true = 0 {}
| ^^^ help: use `..=` instead
error: float literals must have an integer part
- --> $DIR/recover-range-pats.rs:128:15
+ --> $DIR/recover-range-pats.rs:127:15
|
LL | if let ....3 = 0 {}
| ^^ help: must have an integer part: `0.3`
error: range-to patterns with `...` are not allowed
- --> $DIR/recover-range-pats.rs:128:12
+ --> $DIR/recover-range-pats.rs:127:12
|
LL | if let ....3 = 0 {}
| ^^^ help: use `..=` instead
error: range-to patterns with `...` are not allowed
- --> $DIR/recover-range-pats.rs:150:17
+ --> $DIR/recover-range-pats.rs:149:17
|
LL | let ...$e;
| ^^^ help: use `..=` instead
@@ -170,7 +170,7 @@ LL | mac!(0);
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:154:19
+ --> $DIR/recover-range-pats.rs:153:19
|
LL | let $e...;
| ^^^ help: use `..` instead
@@ -182,7 +182,7 @@ LL | mac!(0);
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0586]: inclusive range with no end
- --> $DIR/recover-range-pats.rs:155:19
+ --> $DIR/recover-range-pats.rs:154:19
|
LL | let $e..=;
| ^^^ help: use `..` instead
@@ -194,21 +194,21 @@ LL | mac!(0);
= note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info)
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:42:13
+ --> $DIR/recover-range-pats.rs:41:13
|
LL | if let 0...3 = 0 {}
| ^^^ help: use `..=` for an inclusive range
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
- --> $DIR/recover-range-pats.rs:8:9
+ --> $DIR/recover-range-pats.rs:7:9
|
LL | #![deny(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:45:13
+ --> $DIR/recover-range-pats.rs:44:13
|
LL | if let 0...Y = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -217,7 +217,7 @@ LL | if let 0...Y = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:48:13
+ --> $DIR/recover-range-pats.rs:47:13
|
LL | if let X...3 = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -226,7 +226,7 @@ LL | if let X...3 = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:51:13
+ --> $DIR/recover-range-pats.rs:50:13
|
LL | if let X...Y = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -235,7 +235,7 @@ LL | if let X...Y = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:54:16
+ --> $DIR/recover-range-pats.rs:53:16
|
LL | if let true...Y = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -244,7 +244,7 @@ LL | if let true...Y = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:57:13
+ --> $DIR/recover-range-pats.rs:56:13
|
LL | if let X...true = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -253,7 +253,7 @@ LL | if let X...true = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:60:14
+ --> $DIR/recover-range-pats.rs:59:14
|
LL | if let .0...Y = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -262,7 +262,7 @@ LL | if let .0...Y = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:64:13
+ --> $DIR/recover-range-pats.rs:63:13
|
LL | if let X... .0 = 0 {}
| ^^^ help: use `..=` for an inclusive range
@@ -271,7 +271,7 @@ LL | if let X... .0 = 0 {}
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: `...` range patterns are deprecated
- --> $DIR/recover-range-pats.rs:138:20
+ --> $DIR/recover-range-pats.rs:137:20
|
LL | let $e1...$e2;
| ^^^ help: use `..=` for an inclusive range
@@ -284,7 +284,7 @@ LL | mac2!(0, 1);
= note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:20:12
+ --> $DIR/recover-range-pats.rs:19:12
|
LL | if let true..Y = 0 {}
| ^^^^ - this is of type `u8`
@@ -292,7 +292,7 @@ LL | if let true..Y = 0 {}
| this is of type `bool` but it should be `char` or numeric
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:21:15
+ --> $DIR/recover-range-pats.rs:20:15
|
LL | if let X..true = 0 {}
| - ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -300,7 +300,7 @@ LL | if let X..true = 0 {}
| this is of type `u8`
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:22:12
+ --> $DIR/recover-range-pats.rs:21:12
|
LL | if let .0..Y = 0 {}
| ^^ - - this expression has type `{integer}`
@@ -309,7 +309,7 @@ LL | if let .0..Y = 0 {}
| expected integer, found floating-point number
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:24:16
+ --> $DIR/recover-range-pats.rs:23:16
|
LL | if let X.. .0 = 0 {}
| - ^^ - this expression has type `u8`
@@ -321,7 +321,7 @@ LL | if let X.. .0 = 0 {}
found type `{float}`
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:33:12
+ --> $DIR/recover-range-pats.rs:32:12
|
LL | if let true..=Y = 0 {}
| ^^^^ - this is of type `u8`
@@ -329,7 +329,7 @@ LL | if let true..=Y = 0 {}
| this is of type `bool` but it should be `char` or numeric
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:34:16
+ --> $DIR/recover-range-pats.rs:33:16
|
LL | if let X..=true = 0 {}
| - ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -337,7 +337,7 @@ LL | if let X..=true = 0 {}
| this is of type `u8`
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:35:12
+ --> $DIR/recover-range-pats.rs:34:12
|
LL | if let .0..=Y = 0 {}
| ^^ - - this expression has type `{integer}`
@@ -346,7 +346,7 @@ LL | if let .0..=Y = 0 {}
| expected integer, found floating-point number
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:37:16
+ --> $DIR/recover-range-pats.rs:36:16
|
LL | if let X..=.0 = 0 {}
| - ^^ - this expression has type `u8`
@@ -358,7 +358,7 @@ LL | if let X..=.0 = 0 {}
found type `{float}`
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:54:12
+ --> $DIR/recover-range-pats.rs:53:12
|
LL | if let true...Y = 0 {}
| ^^^^ - this is of type `u8`
@@ -366,7 +366,7 @@ LL | if let true...Y = 0 {}
| this is of type `bool` but it should be `char` or numeric
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:57:16
+ --> $DIR/recover-range-pats.rs:56:16
|
LL | if let X...true = 0 {}
| - ^^^^ this is of type `bool` but it should be `char` or numeric
@@ -374,7 +374,7 @@ LL | if let X...true = 0 {}
| this is of type `u8`
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:60:12
+ --> $DIR/recover-range-pats.rs:59:12
|
LL | if let .0...Y = 0 {}
| ^^ - - this expression has type `{integer}`
@@ -383,7 +383,7 @@ LL | if let .0...Y = 0 {}
| expected integer, found floating-point number
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:64:17
+ --> $DIR/recover-range-pats.rs:63:17
|
LL | if let X... .0 = 0 {}
| - ^^ - this expression has type `u8`
@@ -395,13 +395,13 @@ LL | if let X... .0 = 0 {}
found type `{float}`
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:73:12
+ --> $DIR/recover-range-pats.rs:72:12
|
LL | if let true.. = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:75:12
+ --> $DIR/recover-range-pats.rs:74:12
|
LL | if let .0.. = 0 {}
| ^^ - this expression has type `{integer}`
@@ -409,13 +409,13 @@ LL | if let .0.. = 0 {}
| expected integer, found floating-point number
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:83:12
+ --> $DIR/recover-range-pats.rs:82:12
|
LL | if let true..= = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:85:12
+ --> $DIR/recover-range-pats.rs:84:12
|
LL | if let .0..= = 0 {}
| ^^ - this expression has type `{integer}`
@@ -423,13 +423,13 @@ LL | if let .0..= = 0 {}
| expected integer, found floating-point number
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:93:12
+ --> $DIR/recover-range-pats.rs:92:12
|
LL | if let true... = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:95:12
+ --> $DIR/recover-range-pats.rs:94:12
|
LL | if let .0... = 0 {}
| ^^ - this expression has type `{integer}`
@@ -437,13 +437,13 @@ LL | if let .0... = 0 {}
| expected integer, found floating-point number
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:103:14
+ --> $DIR/recover-range-pats.rs:102:14
|
LL | if let ..true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:105:15
+ --> $DIR/recover-range-pats.rs:104:15
|
LL | if let .. .0 = 0 {}
| ^^ - this expression has type `{integer}`
@@ -451,13 +451,13 @@ LL | if let .. .0 = 0 {}
| expected integer, found floating-point number
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:113:15
+ --> $DIR/recover-range-pats.rs:112:15
|
LL | if let ..=true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:115:15
+ --> $DIR/recover-range-pats.rs:114:15
|
LL | if let ..=.0 = 0 {}
| ^^ - this expression has type `{integer}`
@@ -465,13 +465,13 @@ LL | if let ..=.0 = 0 {}
| expected integer, found floating-point number
error[E0029]: only `char` and numeric types are allowed in range patterns
- --> $DIR/recover-range-pats.rs:125:15
+ --> $DIR/recover-range-pats.rs:124:15
|
LL | if let ...true = 0 {}
| ^^^^ this is of type `bool` but it should be `char` or numeric
error[E0308]: mismatched types
- --> $DIR/recover-range-pats.rs:128:15
+ --> $DIR/recover-range-pats.rs:127:15
|
LL | if let ....3 = 0 {}
| ^^ - this expression has type `{integer}`
diff --git a/src/test/ui/parser/recover-struct.stderr b/src/test/ui/parser/recover-struct.stderr
index 1b72184b0..9f6fb06ca 100644
--- a/src/test/ui/parser/recover-struct.stderr
+++ b/src/test/ui/parser/recover-struct.stderr
@@ -1,6 +1,8 @@
error: expected `:`, found `Bad`
--> $DIR/recover-struct.rs:4:9
|
+LL | struct Test {
+ | ---- while parsing this struct
LL | Very
| - expected `:`
LL | Bad
diff --git a/src/test/ui/parser/recovered-struct-variant.stderr b/src/test/ui/parser/recovered-struct-variant.stderr
index 51aaf8bb3..78c67866f 100644
--- a/src/test/ui/parser/recovered-struct-variant.stderr
+++ b/src/test/ui/parser/recovered-struct-variant.stderr
@@ -2,7 +2,9 @@ error: expected `:`, found `,`
--> $DIR/recovered-struct-variant.rs:2:10
|
LL | A { a, b: usize }
- | ^ expected `:`
+ | - ^ expected `:`
+ | |
+ | while parsing this struct
error: aborting due to previous error
diff --git a/src/test/ui/parser/removed-syntax-enum-newtype.stderr b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
index 2daa6249b..8f7ca3567 100644
--- a/src/test/ui/parser/removed-syntax-enum-newtype.stderr
+++ b/src/test/ui/parser/removed-syntax-enum-newtype.stderr
@@ -2,7 +2,9 @@ error: expected one of `<`, `where`, or `{`, found `=`
--> $DIR/removed-syntax-enum-newtype.rs:1:8
|
LL | enum e = isize;
- | ^ expected one of `<`, `where`, or `{`
+ | - ^ expected one of `<`, `where`, or `{`
+ | |
+ | while parsing this enum
error: aborting due to previous error
diff --git a/src/test/ui/parser/removed-syntax-field-let-2.rs b/src/test/ui/parser/removed-syntax-field-let-2.rs
new file mode 100644
index 000000000..7ff91b476
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let-2.rs
@@ -0,0 +1,12 @@
+struct Foo {
+ let x: i32,
+ //~^ ERROR expected identifier, found keyword
+ let y: i32,
+ //~^ ERROR expected identifier, found keyword
+}
+
+fn main() {
+ let _ = Foo {
+ //~^ ERROR missing fields `x` and `y` in initializer of `Foo`
+ };
+}
diff --git a/src/test/ui/parser/removed-syntax-field-let-2.stderr b/src/test/ui/parser/removed-syntax-field-let-2.stderr
new file mode 100644
index 000000000..fda0919b9
--- /dev/null
+++ b/src/test/ui/parser/removed-syntax-field-let-2.stderr
@@ -0,0 +1,33 @@
+error: expected identifier, found keyword `let`
+ --> $DIR/removed-syntax-field-let-2.rs:2:5
+ |
+LL | let x: i32,
+ | ^^^-
+ | |
+ | expected identifier, found keyword
+ | help: remove this `let` keyword
+ |
+ = note: the `let` keyword is not allowed in `struct` fields
+ = note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information
+
+error: expected identifier, found keyword `let`
+ --> $DIR/removed-syntax-field-let-2.rs:4:5
+ |
+LL | let y: i32,
+ | ^^^-
+ | |
+ | expected identifier, found keyword
+ | help: remove this `let` keyword
+ |
+ = note: the `let` keyword is not allowed in `struct` fields
+ = note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information
+
+error[E0063]: missing fields `x` and `y` in initializer of `Foo`
+ --> $DIR/removed-syntax-field-let-2.rs:9:13
+ |
+LL | let _ = Foo {
+ | ^^^ missing `x` and `y`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0063`.
diff --git a/src/test/ui/parser/removed-syntax-field-let.stderr b/src/test/ui/parser/removed-syntax-field-let.stderr
index 10be2e045..9bc18dabd 100644
--- a/src/test/ui/parser/removed-syntax-field-let.stderr
+++ b/src/test/ui/parser/removed-syntax-field-let.stderr
@@ -2,7 +2,13 @@ error: expected identifier, found keyword `let`
--> $DIR/removed-syntax-field-let.rs:2:5
|
LL | let foo: (),
- | ^^^ expected identifier, found keyword
+ | ^^^-
+ | |
+ | expected identifier, found keyword
+ | help: remove this `let` keyword
+ |
+ = note: the `let` keyword is not allowed in `struct` fields
+ = note: see <https://doc.rust-lang.org/book/ch05-01-defining-structs.html> for more information
error: aborting due to previous error
diff --git a/src/test/ui/parser/removed-syntax-field-semicolon.stderr b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
index e4f75f672..532d4fb2b 100644
--- a/src/test/ui/parser/removed-syntax-field-semicolon.stderr
+++ b/src/test/ui/parser/removed-syntax-field-semicolon.stderr
@@ -1,6 +1,8 @@
error: struct fields are separated by `,`
--> $DIR/removed-syntax-field-semicolon.rs:2:12
|
+LL | struct S {
+ | - while parsing this struct
LL | bar: ();
| ^ help: replace `;` with `,`
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs
index f29fd7a54..5b90e905a 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.rs
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs
@@ -23,11 +23,13 @@ fn main() {
//~^ ERROR expected one of
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
//~| ERROR expected
+ //~| HELP add `'` to close the char literal
f<'_>();
//~^ comparison operators cannot be chained
//~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
//~| ERROR expected
+ //~| HELP add `'` to close the char literal
let _ = f<u8>;
//~^ ERROR comparison operators cannot be chained
diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
index 0bf52854e..52e201c43 100644
--- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr
+++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr
@@ -58,6 +58,11 @@ error: expected `while`, `for`, `loop` or `{` after a label
|
LL | let _ = f<'_, i8>();
| ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | let _ = f<'_', i8>();
+ | +
error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, or an operator, found `,`
--> $DIR/require-parens-for-chained-comparison.rs:22:17
@@ -71,13 +76,18 @@ LL | let _ = f::<'_, i8>();
| ++
error: expected `while`, `for`, `loop` or `{` after a label
- --> $DIR/require-parens-for-chained-comparison.rs:27:9
+ --> $DIR/require-parens-for-chained-comparison.rs:28:9
|
LL | f<'_>();
| ^ expected `while`, `for`, `loop` or `{` after a label
+ |
+help: add `'` to close the char literal
+ |
+LL | f<'_'>();
+ | +
error: comparison operators cannot be chained
- --> $DIR/require-parens-for-chained-comparison.rs:27:6
+ --> $DIR/require-parens-for-chained-comparison.rs:28:6
|
LL | f<'_>();
| ^ ^
@@ -88,7 +98,7 @@ LL | f::<'_>();
| ++
error: comparison operators cannot be chained
- --> $DIR/require-parens-for-chained-comparison.rs:32:14
+ --> $DIR/require-parens-for-chained-comparison.rs:34:14
|
LL | let _ = f<u8>;
| ^ ^
diff --git a/src/test/ui/parser/semi-after-closure-in-macro.rs b/src/test/ui/parser/semi-after-closure-in-macro.rs
new file mode 100644
index 000000000..14efb6100
--- /dev/null
+++ b/src/test/ui/parser/semi-after-closure-in-macro.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+// Checks that the fix in #103222 doesn't also disqualify semicolons after
+// closures within parentheses *in macros*, where they're totally allowed.
+
+macro_rules! m {
+ (($expr:expr ; )) => {
+ $expr
+ };
+}
+
+fn main() {
+ let x = m!(( ||() ; ));
+}
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.rs b/src/test/ui/parser/tag-variant-disr-non-nullary.rs
deleted file mode 100644
index a9cfdd549..000000000
--- a/src/test/ui/parser/tag-variant-disr-non-nullary.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-enum Color {
- Red = 0xff0000,
- //~^ ERROR custom discriminant values are not allowed in enums with tuple or struct variants
- Green = 0x00ff00,
- Blue = 0x0000ff,
- Black = 0x000000,
- White = 0xffffff,
- Other(usize),
- Other2(usize, usize),
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr b/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
deleted file mode 100644
index 79f044a06..000000000
--- a/src/test/ui/parser/tag-variant-disr-non-nullary.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0658]: custom discriminant values are not allowed in enums with tuple or struct variants
- --> $DIR/tag-variant-disr-non-nullary.rs:2:11
- |
-LL | Red = 0xff0000,
- | ^^^^^^^^ disallowed custom discriminant
-LL |
-LL | Green = 0x00ff00,
- | ^^^^^^^^ disallowed custom discriminant
-LL | Blue = 0x0000ff,
- | ^^^^^^^^ disallowed custom discriminant
-LL | Black = 0x000000,
- | ^^^^^^^^ disallowed custom discriminant
-LL | White = 0xffffff,
- | ^^^^^^^^ disallowed custom discriminant
-LL | Other(usize),
- | ------------ tuple variant defined here
-LL | Other2(usize, usize),
- | -------------------- tuple variant defined here
- |
- = note: see issue #60553 <https://github.com/rust-lang/rust/issues/60553> for more information
- = help: add `#![feature(arbitrary_enum_discriminant)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
index 76fa86033..be858cd65 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -52,9 +52,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error: aborting due to 6 previous errors; 1 warning emitted
diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr
index 823f75bfa..5e07a3fe6 100644
--- a/src/test/ui/parser/trait-object-trait-parens.stderr
+++ b/src/test/ui/parser/trait-object-trait-parens.stderr
@@ -22,9 +22,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | let _: Box<dyn (Obj) + (?Sized) + (for<'a> Trait<'a>)>;
diff --git a/src/test/ui/parser/type-alias-where-fixable.stderr b/src/test/ui/parser/type-alias-where-fixable.stderr
index 2e516d5c4..f0acb388b 100644
--- a/src/test/ui/parser/type-alias-where-fixable.stderr
+++ b/src/test/ui/parser/type-alias-where-fixable.stderr
@@ -4,8 +4,8 @@ warning: where clause not allowed here
LL | type Assoc where u32: Copy = ();
| ^^^^^^^^^^^^^^^
|
- = note: `#[warn(deprecated_where_clause_location)]` on by default
= note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+ = note: `#[warn(deprecated_where_clause_location)]` on by default
help: move it to the end of the type declaration
|
LL - type Assoc where u32: Copy = ();
diff --git a/src/test/ui/parser/unicode-control-codepoints.stderr b/src/test/ui/parser/unicode-control-codepoints.stderr
index 71509fe41..44548c72f 100644
--- a/src/test/ui/parser/unicode-control-codepoints.stderr
+++ b/src/test/ui/parser/unicode-control-codepoints.stderr
@@ -92,8 +92,8 @@ LL | // if access_level != "user" { // Check if admin
| | '\u{202b}'
| this comment contains invisible unicode text flow control codepoints
|
- = note: `#[deny(text_direction_codepoint_in_comment)]` on by default
= note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = note: `#[deny(text_direction_codepoint_in_comment)]` on by default
= help: if their presence wasn't intentional, you can remove them
error: unicode codepoint changing visible direction of text present in comment
@@ -123,8 +123,8 @@ LL | println!("{:?}", "/* } if isAdmin begin admins only ");
| | '\u{202e}'
| this literal contains invisible unicode text flow control codepoints
|
- = note: `#[deny(text_direction_codepoint_in_literal)]` on by default
= note: these kind of unicode codepoints change the way text flows on applications that support them, but can cause confusion because they change the order of characters on the screen
+ = note: `#[deny(text_direction_codepoint_in_literal)]` on by default
= help: if their presence wasn't intentional, you can remove them
help: if you want to keep them but make them visible in your source code, you can escape them
|
diff --git a/src/test/ui/parser/unmatched-langle-1.stderr b/src/test/ui/parser/unmatched-langle-1.stderr
index c8072b4c5..cdf74bded 100644
--- a/src/test/ui/parser/unmatched-langle-1.stderr
+++ b/src/test/ui/parser/unmatched-langle-1.stderr
@@ -4,18 +4,18 @@ error: unmatched angle brackets
LL | foo::<<<<Ty<i32>>();
| ^^^ help: remove extra angle brackets
-error[E0425]: cannot find function `foo` in this scope
- --> $DIR/unmatched-langle-1.rs:5:5
- |
-LL | foo::<<<<Ty<i32>>();
- | ^^^ not found in this scope
-
error[E0412]: cannot find type `Ty` in this scope
--> $DIR/unmatched-langle-1.rs:5:14
|
LL | foo::<<<<Ty<i32>>();
| ^^ not found in this scope
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/unmatched-langle-1.rs:5:5
+ |
+LL | foo::<<<<Ty<i32>>();
+ | ^^^ not found in this scope
+
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0412, E0425.
diff --git a/src/test/ui/issues/issue-17718-patterns.rs b/src/test/ui/pattern/issue-17718-patterns.rs
index 2ca0f67f8..2ca0f67f8 100644
--- a/src/test/ui/issues/issue-17718-patterns.rs
+++ b/src/test/ui/pattern/issue-17718-patterns.rs
diff --git a/src/test/ui/issues/issue-17718-patterns.stderr b/src/test/ui/pattern/issue-17718-patterns.stderr
index 109091c2a..109091c2a 100644
--- a/src/test/ui/issues/issue-17718-patterns.stderr
+++ b/src/test/ui/pattern/issue-17718-patterns.stderr
diff --git a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
index fef0f3c0e..f40642f30 100644
--- a/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
+++ b/src/test/ui/pattern/issue-66270-pat-struct-parser-recovery.stderr
@@ -1,6 +1,8 @@
error: expected type, found `0`
--> $DIR/issue-66270-pat-struct-parser-recovery.rs:4:22
|
+LL | struct Bug {
+ | --- while parsing this struct
LL | incorrect_field: 0,
| ^ expected type
diff --git a/src/test/ui/pattern/usefulness/consts-opaque.stderr b/src/test/ui/pattern/usefulness/consts-opaque.stderr
index 05c009a6f..35396751a 100644
--- a/src/test/ui/pattern/usefulness/consts-opaque.stderr
+++ b/src/test/ui/pattern/usefulness/consts-opaque.stderr
@@ -40,9 +40,9 @@ warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated w
LL | FOO_REF_REF => {}
| ^^^^^^^^^^^
|
- = note: `#[warn(indirect_structural_match)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: `#[warn(indirect_structural_match)]` on by default
error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/consts-opaque.rs:53:9
diff --git a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
index b97683526..cdb6b5c7a 100644
--- a/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
+++ b/src/test/ui/pattern/usefulness/deny-irrefutable-let-patterns.stderr
@@ -4,13 +4,13 @@ error: irrefutable `if let` pattern
LL | if let _ = 5 {}
| ^^^^^^^^^
|
+ = note: this pattern will always match, so the `if let` is useless
+ = help: consider replacing the `if let` with a `let`
note: the lint level is defined here
--> $DIR/deny-irrefutable-let-patterns.rs:3:9
|
LL | #![deny(irrefutable_let_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this pattern will always match, so the `if let` is useless
- = help: consider replacing the `if let` with a `let`
error: irrefutable `while let` pattern
--> $DIR/deny-irrefutable-let-patterns.rs:8:11
diff --git a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
index 24c0419e1..ea0e8f6e4 100644
--- a/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
+++ b/src/test/ui/pattern/usefulness/integer-ranges/overlapping_range_endpoints.stderr
@@ -6,12 +6,12 @@ LL | m!(0u8, 20..=30, 30..=40);
| |
| this range overlaps on `30_u8`...
|
+ = note: you likely meant to write mutually exclusive ranges
note: the lint level is defined here
--> $DIR/overlapping_range_endpoints.rs:2:9
|
LL | #![deny(overlapping_range_endpoints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: you likely meant to write mutually exclusive ranges
error: multiple patterns overlap on their endpoints
--> $DIR/overlapping_range_endpoints.rs:16:22
diff --git a/src/test/ui/polymorphization/const_parameters/closures.stderr b/src/test/ui/polymorphization/const_parameters/closures.stderr
index fdf817cae..4e927f773 100644
--- a/src/test/ui/polymorphization/const_parameters/closures.stderr
+++ b/src/test/ui/polymorphization/const_parameters/closures.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs, rustc_attrs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: item has unused generic parameters
--> $DIR/closures.rs:19:19
diff --git a/src/test/ui/polymorphization/const_parameters/functions.stderr b/src/test/ui/polymorphization/const_parameters/functions.stderr
index f2b5a7307..9d0922ac7 100644
--- a/src/test/ui/polymorphization/const_parameters/functions.stderr
+++ b/src/test/ui/polymorphization/const_parameters/functions.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs, rustc_attrs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: item has unused generic parameters
--> $DIR/functions.rs:15:8
diff --git a/src/test/ui/polymorphization/generators.stderr b/src/test/ui/polymorphization/generators.stderr
index a24eee5fe..84888f6fb 100644
--- a/src/test/ui/polymorphization/generators.stderr
+++ b/src/test/ui/polymorphization/generators.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs, generators, generator_trait, rustc_attrs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: item has unused generic parameters
--> $DIR/generators.rs:35:5
diff --git a/src/test/ui/polymorphization/predicates.stderr b/src/test/ui/polymorphization/predicates.stderr
index e5af1d751..80bb2af25 100644
--- a/src/test/ui/polymorphization/predicates.stderr
+++ b/src/test/ui/polymorphization/predicates.stderr
@@ -41,7 +41,7 @@ error: item has unused generic parameters
LL | fn bar<I>() {
| ^^^ - generic parameter `I` is unused
-note: the above error was encountered while instantiating `fn foo::<std::slice::Iter<u32>, T>`
+note: the above error was encountered while instantiating `fn foo::<std::slice::Iter<'_, u32>, T>`
--> $DIR/predicates.rs:86:5
|
LL | foo(x.iter());
diff --git a/src/test/ui/polymorphization/promoted-function-2.stderr b/src/test/ui/polymorphization/promoted-function-2.stderr
index 4d7bab6aa..547569df7 100644
--- a/src/test/ui/polymorphization/promoted-function-2.stderr
+++ b/src/test/ui/polymorphization/promoted-function-2.stderr
@@ -4,8 +4,8 @@ warning: the feature `generic_const_exprs` is incomplete and may not be safe to
LL | #![feature(generic_const_exprs, rustc_attrs)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: item has unused generic parameters
--> $DIR/promoted-function-2.rs:8:4
diff --git a/src/test/ui/privacy/access_levels.rs b/src/test/ui/privacy/access_levels.rs
deleted file mode 100644
index d51d2b572..000000000
--- a/src/test/ui/privacy/access_levels.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-#![feature(rustc_attrs)]
-
-#[rustc_access_level] mod outer { //~ ERROR None
- #[rustc_access_level] pub mod inner { //~ ERROR Some(Exported)
- #[rustc_access_level]
- extern "C" { //~ ERROR Some(Exported)
- #[rustc_access_level] static a: u8; //~ ERROR None
- #[rustc_access_level] pub fn b(); //~ ERROR Some(Exported)
- }
- #[rustc_access_level]
- pub trait Trait { //~ ERROR Some(Exported)
- #[rustc_access_level] const A: i32; //~ ERROR Some(Exported)
- #[rustc_access_level] type B; //~ ERROR Some(Exported)
- }
-
- #[rustc_access_level]
- pub struct Struct { //~ ERROR Some(Exported)
- #[rustc_access_level] a: u8, //~ ERROR None
- #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
- }
-
- #[rustc_access_level]
- pub union Union { //~ ERROR Some(Exported)
- #[rustc_access_level] a: u8, //~ ERROR None
- #[rustc_access_level] pub b: u8, //~ ERROR Some(Exported)
- }
-
- #[rustc_access_level]
- pub enum Enum { //~ ERROR Some(Exported)
- #[rustc_access_level] A( //~ ERROR Some(Exported)
- #[rustc_access_level] Struct, //~ ERROR Some(Exported)
- #[rustc_access_level] Union, //~ ERROR Some(Exported)
- ),
- }
- }
-
- #[rustc_access_level] macro_rules! none_macro { //~ ERROR None
- () => {};
- }
-
- #[macro_export]
- #[rustc_access_level] macro_rules! public_macro { //~ ERROR Some(Public)
- () => {};
- }
-}
-
-pub use outer::inner;
-
-fn main() {}
diff --git a/src/test/ui/privacy/access_levels.stderr b/src/test/ui/privacy/access_levels.stderr
deleted file mode 100644
index f326293c3..000000000
--- a/src/test/ui/privacy/access_levels.stderr
+++ /dev/null
@@ -1,125 +0,0 @@
-error: None
- --> $DIR/access_levels.rs:3:23
- |
-LL | #[rustc_access_level] mod outer {
- | ^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:4:27
- |
-LL | #[rustc_access_level] pub mod inner {
- | ^^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:6:9
- |
-LL | / extern "C" {
-LL | | #[rustc_access_level] static a: u8;
-LL | | #[rustc_access_level] pub fn b();
-LL | | }
- | |_________^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:11:9
- |
-LL | pub trait Trait {
- | ^^^^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:17:9
- |
-LL | pub struct Struct {
- | ^^^^^^^^^^^^^^^^^
-
-error: None
- --> $DIR/access_levels.rs:18:35
- |
-LL | #[rustc_access_level] a: u8,
- | ^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:19:35
- |
-LL | #[rustc_access_level] pub b: u8,
- | ^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:23:9
- |
-LL | pub union Union {
- | ^^^^^^^^^^^^^^^
-
-error: None
- --> $DIR/access_levels.rs:24:35
- |
-LL | #[rustc_access_level] a: u8,
- | ^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:25:35
- |
-LL | #[rustc_access_level] pub b: u8,
- | ^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:29:9
- |
-LL | pub enum Enum {
- | ^^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:30:35
- |
-LL | #[rustc_access_level] A(
- | ^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:31:39
- |
-LL | #[rustc_access_level] Struct,
- | ^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:32:39
- |
-LL | #[rustc_access_level] Union,
- | ^^^^^
-
-error: None
- --> $DIR/access_levels.rs:37:27
- |
-LL | #[rustc_access_level] macro_rules! none_macro {
- | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: Some(Public)
- --> $DIR/access_levels.rs:42:27
- |
-LL | #[rustc_access_level] macro_rules! public_macro {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:12:35
- |
-LL | #[rustc_access_level] const A: i32;
- | ^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:13:35
- |
-LL | #[rustc_access_level] type B;
- | ^^^^^^
-
-error: None
- --> $DIR/access_levels.rs:7:35
- |
-LL | #[rustc_access_level] static a: u8;
- | ^^^^^^^^^^^^
-
-error: Some(Exported)
- --> $DIR/access_levels.rs:8:35
- |
-LL | #[rustc_access_level] pub fn b();
- | ^^^^^^^^^^
-
-error: aborting due to 20 previous errors
-
diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.rs b/src/test/ui/privacy/associated-item-privacy-inherent.rs
index c3ae92023..7b7c734a9 100644
--- a/src/test/ui/privacy/associated-item-privacy-inherent.rs
+++ b/src/test/ui/privacy/associated-item-privacy-inherent.rs
@@ -11,11 +11,11 @@ mod priv_nominal {
pub macro mac() {
let value = Pub::method;
- //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
value;
- //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
Pub.method();
- //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
Pub::CONST;
//~^ ERROR associated constant `CONST` is private
// let _: Pub::AssocTy;
diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr
index 4478e5c2a..f4d4ee459 100644
--- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr
+++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr
@@ -1,4 +1,4 @@
-error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
--> $DIR/associated-item-privacy-inherent.rs:13:21
|
LL | let value = Pub::method;
@@ -9,7 +9,7 @@ LL | priv_nominal::mac!();
|
= note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
--> $DIR/associated-item-privacy-inherent.rs:15:9
|
LL | value;
@@ -20,7 +20,7 @@ LL | priv_nominal::mac!();
|
= note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private
+error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private
--> $DIR/associated-item-privacy-inherent.rs:17:13
|
LL | Pub.method();
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs
index c07aeed99..ad9a5e15c 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.rs
+++ b/src/test/ui/privacy/associated-item-privacy-trait.rs
@@ -13,11 +13,11 @@ mod priv_trait {
pub macro mac() {
let value = <Pub as PrivTr>::method;
- //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
value;
- //~^ ERROR type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
Pub.method();
- //~^ ERROR type `for<'r> fn(&'r Self) {<Self as PrivTr>::method}` is private
+ //~^ ERROR type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
<Pub as PrivTr>::CONST;
//~^ ERROR associated constant `<Pub as PrivTr>::CONST` is private
let _: <Pub as PrivTr>::AssocTy;
diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr
index 6095f5f42..c4be1a9d9 100644
--- a/src/test/ui/privacy/associated-item-privacy-trait.stderr
+++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr
@@ -1,4 +1,4 @@
-error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
+error: type `for<'a> fn(&'a priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
--> $DIR/associated-item-privacy-trait.rs:15:21
|
LL | let value = <Pub as PrivTr>::method;
@@ -9,7 +9,7 @@ LL | priv_trait::mac!();
|
= note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
+error: type `for<'a> fn(&'a priv_trait::Pub) {<priv_trait::Pub as PrivTr>::method}` is private
--> $DIR/associated-item-privacy-trait.rs:17:9
|
LL | value;
@@ -20,7 +20,7 @@ LL | priv_trait::mac!();
|
= note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r Self) {<Self as PrivTr>::method}` is private
+error: type `for<'a> fn(&'a Self) {<Self as PrivTr>::method}` is private
--> $DIR/associated-item-privacy-trait.rs:19:13
|
LL | Pub.method();
diff --git a/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs b/src/test/ui/privacy/auxiliary/issue-17718-const-privacy.rs
index 93cf4bf3e..93cf4bf3e 100644
--- a/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs
+++ b/src/test/ui/privacy/auxiliary/issue-17718-const-privacy.rs
diff --git a/src/test/ui/privacy/effective_visibilities.rs b/src/test/ui/privacy/effective_visibilities.rs
new file mode 100644
index 000000000..1d806a1d1
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities.rs
@@ -0,0 +1,75 @@
+#![feature(rustc_attrs)]
+
+#[rustc_effective_visibility]
+mod outer { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+ #[rustc_effective_visibility]
+ pub mod inner1 { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+
+ #[rustc_effective_visibility]
+ extern "C" {} //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+
+ #[rustc_effective_visibility]
+ pub trait PubTrait { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ const A: i32; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ type B; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ }
+
+ #[rustc_effective_visibility]
+ struct PrivStruct; //~ ERROR not in the table
+
+ #[rustc_effective_visibility]
+ pub union PubUnion { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ a: u8, //~ ERROR not in the table
+ #[rustc_effective_visibility]
+ pub b: u8, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ }
+
+ #[rustc_effective_visibility]
+ pub enum Enum { //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ A( //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ PubUnion, //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ ),
+ }
+ }
+
+ #[rustc_effective_visibility]
+ macro_rules! none_macro { //~ Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+ () => {};
+ }
+
+ #[macro_export]
+ #[rustc_effective_visibility]
+ macro_rules! public_macro { //~ Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ () => {};
+ }
+
+ #[rustc_effective_visibility]
+ pub struct ReachableStruct { //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ pub a: u8, //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
+ }
+}
+
+#[rustc_effective_visibility]
+pub use outer::inner1; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+
+pub fn foo() -> outer::ReachableStruct { outer::ReachableStruct {a: 0} }
+
+mod half_public_import {
+ #[rustc_effective_visibility]
+ pub type HalfPublicImport = u8; //~ ERROR Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ #[rustc_effective_visibility]
+ #[allow(non_upper_case_globals)]
+ pub(crate) const HalfPublicImport: u8 = 0; //~ ERROR Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+}
+
+#[rustc_effective_visibility]
+pub use half_public_import::HalfPublicImport; //~ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ //~^ ERROR Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+
+fn main() {}
diff --git a/src/test/ui/privacy/effective_visibilities.stderr b/src/test/ui/privacy/effective_visibilities.stderr
new file mode 100644
index 000000000..1c6201600
--- /dev/null
+++ b/src/test/ui/privacy/effective_visibilities.stderr
@@ -0,0 +1,134 @@
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+ --> $DIR/effective_visibilities.rs:4:1
+ |
+LL | mod outer {
+ | ^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:6:5
+ |
+LL | pub mod inner1 {
+ | ^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:9:9
+ |
+LL | extern "C" {}
+ | ^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:12:9
+ |
+LL | pub trait PubTrait {
+ | ^^^^^^^^^^^^^^^^^^
+
+error: not in the table
+ --> $DIR/effective_visibilities.rs:20:9
+ |
+LL | struct PrivStruct;
+ | ^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:23:9
+ |
+LL | pub union PubUnion {
+ | ^^^^^^^^^^^^^^^^^^
+
+error: not in the table
+ --> $DIR/effective_visibilities.rs:25:13
+ |
+LL | a: u8,
+ | ^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:27:13
+ |
+LL | pub b: u8,
+ | ^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:31:9
+ |
+LL | pub enum Enum {
+ | ^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:33:13
+ |
+LL | A(
+ | ^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:35:17
+ |
+LL | PubUnion,
+ | ^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+ --> $DIR/effective_visibilities.rs:41:5
+ |
+LL | macro_rules! none_macro {
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:47:5
+ |
+LL | macro_rules! public_macro {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:52:5
+ |
+LL | pub struct ReachableStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:54:9
+ |
+LL | pub a: u8,
+ | ^^^^^^^^^
+
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:59:9
+ |
+LL | pub use outer::inner1;
+ | ^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:65:5
+ |
+LL | pub type HalfPublicImport = u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub(crate), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
+ --> $DIR/effective_visibilities.rs:68:5
+ |
+LL | pub(crate) const HalfPublicImport: u8 = 0;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:72:9
+ |
+LL | pub use half_public_import::HalfPublicImport;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub, Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:72:9
+ |
+LL | pub use half_public_import::HalfPublicImport;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:14:13
+ |
+LL | const A: i32;
+ | ^^^^^^^^^^^^
+
+error: Direct: pub(crate), Reexported: pub, Reachable: pub, ReachableThroughImplTrait: pub
+ --> $DIR/effective_visibilities.rs:16:13
+ |
+LL | type B;
+ | ^^^^^^
+
+error: aborting due to 22 previous errors
+
diff --git a/src/test/ui/issues/issue-17718-const-privacy.rs b/src/test/ui/privacy/issue-17718-const-privacy.rs
index 6ab3a60df..6ab3a60df 100644
--- a/src/test/ui/issues/issue-17718-const-privacy.rs
+++ b/src/test/ui/privacy/issue-17718-const-privacy.rs
diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/privacy/issue-17718-const-privacy.stderr
index 133a6360b..133a6360b 100644
--- a/src/test/ui/issues/issue-17718-const-privacy.stderr
+++ b/src/test/ui/privacy/issue-17718-const-privacy.stderr
diff --git a/src/test/ui/privacy/issue-30079.stderr b/src/test/ui/privacy/issue-30079.stderr
index dc98cfe3b..9179ff339 100644
--- a/src/test/ui/privacy/issue-30079.stderr
+++ b/src/test/ui/privacy/issue-30079.stderr
@@ -4,9 +4,9 @@ warning: private type `m1::Priv` in public interface (error E0446)
LL | pub fn f(_: Priv) {}
| ^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(private_in_public)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[warn(private_in_public)]` on by default
error[E0446]: private type `m2::Priv` in public interface
--> $DIR/issue-30079.rs:18:9
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 1abeafe39..a59027d81 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -13,9 +13,9 @@ warning: private trait `PrivTr` in public interface (error E0445)
LL | type Alias1: PrivTr;
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(private_in_public)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[warn(private_in_public)]` on by default
warning: private type `Priv` in public interface (error E0446)
--> $DIR/private-in-public-assoc-ty.rs:27:9
diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr
index 5b4123ea8..de20cada4 100644
--- a/src/test/ui/privacy/private-in-public-non-principal.stderr
+++ b/src/test/ui/privacy/private-in-public-non-principal.stderr
@@ -4,9 +4,9 @@ warning: private trait `PrivNonPrincipal` in public interface (error E0445)
LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(private_in_public)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[warn(private_in_public)]` on by default
error: missing documentation for an associated function
--> $DIR/private-in-public-non-principal.rs:14:9
diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr
index f2ff6cf2f..66f91ce6f 100644
--- a/src/test/ui/privacy/private-in-public-warn.stderr
+++ b/src/test/ui/privacy/private-in-public-warn.stderr
@@ -4,13 +4,13 @@ error: private type `types::Priv` in public interface (error E0446)
LL | pub type Alias = Priv;
| ^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
note: the lint level is defined here
--> $DIR/private-in-public-warn.rs:5:9
|
LL | #![deny(private_in_public)]
| ^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
error: private type `types::Priv` in public interface (error E0446)
--> $DIR/private-in-public-warn.rs:18:12
diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs
index 00f0a715a..0337aedd0 100644
--- a/src/test/ui/privacy/private-inferred-type-3.rs
+++ b/src/test/ui/privacy/private-inferred-type-3.rs
@@ -6,7 +6,7 @@
// error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
// error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private
// error-pattern:type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private
-// error-pattern:type `for<'r> fn(&'r Pub<u8>) {Pub::<u8>::priv_method}` is private
+// error-pattern:type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private
#![feature(decl_macro)]
diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr
index f9dd1c3d0..00b61512d 100644
--- a/src/test/ui/privacy/private-inferred-type-3.stderr
+++ b/src/test/ui/privacy/private-inferred-type-3.stderr
@@ -46,7 +46,7 @@ LL | ext::m!();
|
= note: this error originates in the macro `ext::m` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r Pub<u8>) {Pub::<u8>::priv_method}` is private
+error: type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private
--> $DIR/private-inferred-type-3.rs:16:5
|
LL | ext::m!();
diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs
index b083a3970..e8743dd96 100644
--- a/src/test/ui/privacy/private-inferred-type.rs
+++ b/src/test/ui/privacy/private-inferred-type.rs
@@ -47,7 +47,7 @@ mod m {
PubTupleStruct;
//~^ ERROR type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private
Pub(0u8).priv_method();
- //~^ ERROR type `for<'r> fn(&'r Pub<u8>) {Pub::<u8>::priv_method}` is private
+ //~^ ERROR type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private
}
trait Trait {}
diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr
index aecd8b58c..fc3f9ab62 100644
--- a/src/test/ui/privacy/private-inferred-type.stderr
+++ b/src/test/ui/privacy/private-inferred-type.stderr
@@ -161,7 +161,7 @@ LL | m::m!();
|
= note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: type `for<'r> fn(&'r Pub<u8>) {Pub::<u8>::priv_method}` is private
+error: type `for<'a> fn(&'a Pub<u8>) {Pub::<u8>::priv_method}` is private
--> $DIR/private-inferred-type.rs:49:18
|
LL | Pub(0u8).priv_method();
diff --git a/src/test/ui/privacy/reachable-unnameable-items.rs b/src/test/ui/privacy/reachable-unnameable-items.rs
index 1c91541e6..1babe0119 100644
--- a/src/test/ui/privacy/reachable-unnameable-items.rs
+++ b/src/test/ui/privacy/reachable-unnameable-items.rs
@@ -1,5 +1,4 @@
// run-pass
-// ignore-wasm32-bare compiled with panic=abort by default
// needs-unwind
// aux-build:reachable-unnameable-items.rs
diff --git a/src/test/ui/privacy/where-priv-type.stderr b/src/test/ui/privacy/where-priv-type.stderr
index 7eb71346a..c5fb2cdb0 100644
--- a/src/test/ui/privacy/where-priv-type.stderr
+++ b/src/test/ui/privacy/where-priv-type.stderr
@@ -4,9 +4,9 @@ warning: private type `PrivTy` in public interface (error E0446)
LL | pub struct S
| ^^^^^^^^^^^^
|
- = note: `#[warn(private_in_public)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[warn(private_in_public)]` on by default
warning: private type `PrivTy` in public interface (error E0446)
--> $DIR/where-priv-type.rs:27:1
diff --git a/src/test/ui/proc-macro/attr-complex-fn.stdout b/src/test/ui/proc-macro/attr-complex-fn.stdout
index fc69a13dd..b12eb587f 100644
--- a/src/test/ui/proc-macro/attr-complex-fn.stdout
+++ b/src/test/ui/proc-macro/attr-complex-fn.stdout
@@ -53,12 +53,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '>',
spacing: Joint,
- span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0),
+ span: $DIR/attr-complex-fn.rs:19:36: 19:37 (#0),
},
Punct {
ch: '>',
spacing: Joint,
- span: $DIR/attr-complex-fn.rs:19:36: 19:38 (#0),
+ span: $DIR/attr-complex-fn.rs:19:37: 19:38 (#0),
},
Punct {
ch: '>',
diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs
index b92cc2363..cb634671b 100644
--- a/src/test/ui/proc-macro/call-deprecated.rs
+++ b/src/test/ui/proc-macro/call-deprecated.rs
@@ -5,7 +5,7 @@ extern crate call_deprecated;
// These first two `#[allow(deprecated)]` attributes
// do nothing, since the AST nodes for `First` and `Second`
-// haven't been been assigned a `NodeId`.
+// haven't been assigned a `NodeId`.
// See #63221 for a discussion about how we should
// handle the interaction of 'inert' attributes and
// proc-macro attributes.
diff --git a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
index 4de8746a1..b88fbd3e8 100644
--- a/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
+++ b/src/test/ui/proc-macro/capture-macro-rules-invoke.stdout
@@ -177,12 +177,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:17 (#0),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/capture-macro-rules-invoke.rs:45:16: 45:18 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:45:17: 45:18 (#0),
},
Ident {
ident: "option",
@@ -191,12 +191,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:25 (#0),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/capture-macro-rules-invoke.rs:45:24: 45:26 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:45:25: 45:26 (#0),
},
Ident {
ident: "Option",
@@ -231,12 +231,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:25 (#0),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/capture-macro-rules-invoke.rs:46:24: 46:26 (#0),
+ span: $DIR/capture-macro-rules-invoke.rs:46:25: 46:26 (#0),
},
Ident {
ident: "path",
diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs
index fd34eb974..102bd6b7b 100644
--- a/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs
+++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.rs
@@ -2,6 +2,7 @@
// aux-build:macro-dump-debug.rs
// compile-flags: -Z span-debug
+
extern crate macro_dump_debug;
use macro_dump_debug::dump_debug;
@@ -9,7 +10,11 @@ dump_debug! {
ident // ident
r#ident // raw ident
, // alone punct
- ==> // joint punct
+ && // joint punct, two-char op
+ ||> // joint punct, two-char op + one-char op
+ ||<< // joint punct, two-char op + two-char op
+ ..= // joint punct, three-char op
+ <<=! // joint punct, three-char op + one-char-op
() // empty group
[_] // nonempty group
diff --git a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
index 2c05bdbc4..fa65cbbf1 100644
--- a/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
+++ b/src/test/ui/proc-macro/debug/dump-debug-span-debug.stderr
@@ -1,166 +1,231 @@
-TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }]
+TokenStream [Ident { ident: "ident", span: $DIR/dump-debug-span-debug.rs:10:5: 10:10 (#0) }, Ident { ident: "r#ident", span: $DIR/dump-debug-span-debug.rs:11:5: 11:12 (#0) }, Punct { ch: ',', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:12:5: 12:6 (#0) }, Punct { ch: '&', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:13:5: 13:6 (#0) }, Punct { ch: '&', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:13:6: 13:7 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:14:5: 14:6 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0) }, Punct { ch: '>', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:14:7: 14:8 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:5: 15:6 (#0) }, Punct { ch: '|', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:6: 15:7 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:15:7: 15:8 (#0) }, Punct { ch: '<', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:15:8: 15:9 (#0) }, Punct { ch: '.', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:16:5: 16:6 (#0) }, Punct { ch: '.', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:16:6: 16:7 (#0) }, Punct { ch: '=', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:16:7: 16:8 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0) }, Punct { ch: '<', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:6: 17:7 (#0) }, Punct { ch: '=', spacing: Joint, span: $DIR/dump-debug-span-debug.rs:17:7: 17:8 (#0) }, Punct { ch: '!', spacing: Alone, span: $DIR/dump-debug-span-debug.rs:17:8: 17:9 (#0) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/dump-debug-span-debug.rs:18:5: 18:7 (#0) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: $DIR/dump-debug-span-debug.rs:19:6: 19:7 (#0) }], span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0) }, Literal { kind: Integer, symbol: "0", suffix: None, span: $DIR/dump-debug-span-debug.rs:22:5: 22:6 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: $DIR/dump-debug-span-debug.rs:23:5: 23:8 (#0) }, Literal { kind: Str, symbol: "S", suffix: None, span: $DIR/dump-debug-span-debug.rs:24:5: 24:8 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:25:5: 25:9 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: $DIR/dump-debug-span-debug.rs:27:5: 27:13 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:28:5: 28:11 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: $DIR/dump-debug-span-debug.rs:29:5: 29:15 (#0) }, Literal { kind: Char, symbol: "C", suffix: None, span: $DIR/dump-debug-span-debug.rs:30:5: 30:8 (#0) }, Literal { kind: Byte, symbol: "B", suffix: None, span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:34:5: 34:7 (#0) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:35:5: 35:9 (#0) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:36:5: 36:9 (#0) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:37:5: 37:10 (#0) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:39:5: 39:14 (#0) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:40:5: 40:12 (#0) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:41:5: 41:16 (#0) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:42:5: 42:9 (#0) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: $DIR/dump-debug-span-debug.rs:43:5: 43:10 (#0) }]
TokenStream [
Ident {
ident: "ident",
- span: $DIR/dump-debug-span-debug.rs:9:5: 9:10 (#0),
+ span: $DIR/dump-debug-span-debug.rs:10:5: 10:10 (#0),
},
Ident {
ident: "r#ident",
- span: $DIR/dump-debug-span-debug.rs:10:5: 10:12 (#0),
+ span: $DIR/dump-debug-span-debug.rs:11:5: 11:12 (#0),
},
Punct {
ch: ',',
spacing: Alone,
- span: $DIR/dump-debug-span-debug.rs:11:5: 11:6 (#0),
+ span: $DIR/dump-debug-span-debug.rs:12:5: 12:6 (#0),
+ },
+ Punct {
+ ch: '&',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:13:5: 13:6 (#0),
+ },
+ Punct {
+ ch: '&',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:13:6: 13:7 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:14:5: 14:6 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0),
+ },
+ Punct {
+ ch: '>',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:14:7: 14:8 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:15:5: 15:6 (#0),
+ },
+ Punct {
+ ch: '|',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:15:6: 15:7 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:15:7: 15:8 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:15:8: 15:9 (#0),
+ },
+ Punct {
+ ch: '.',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:16:5: 16:6 (#0),
+ },
+ Punct {
+ ch: '.',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:16:6: 16:7 (#0),
},
Punct {
ch: '=',
+ spacing: Alone,
+ span: $DIR/dump-debug-span-debug.rs:16:7: 16:8 (#0),
+ },
+ Punct {
+ ch: '<',
spacing: Joint,
- span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
+ span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0),
+ },
+ Punct {
+ ch: '<',
+ spacing: Joint,
+ span: $DIR/dump-debug-span-debug.rs:17:6: 17:7 (#0),
},
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/dump-debug-span-debug.rs:12:5: 12:7 (#0),
+ span: $DIR/dump-debug-span-debug.rs:17:7: 17:8 (#0),
},
Punct {
- ch: '>',
+ ch: '!',
spacing: Alone,
- span: $DIR/dump-debug-span-debug.rs:12:7: 12:8 (#0),
+ span: $DIR/dump-debug-span-debug.rs:17:8: 17:9 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
- span: $DIR/dump-debug-span-debug.rs:13:5: 13:7 (#0),
+ span: $DIR/dump-debug-span-debug.rs:18:5: 18:7 (#0),
},
Group {
delimiter: Bracket,
stream: TokenStream [
Ident {
ident: "_",
- span: $DIR/dump-debug-span-debug.rs:14:6: 14:7 (#0),
+ span: $DIR/dump-debug-span-debug.rs:19:6: 19:7 (#0),
},
],
- span: $DIR/dump-debug-span-debug.rs:14:5: 14:8 (#0),
+ span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0),
},
Literal {
kind: Integer,
symbol: "0",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:17:5: 17:6 (#0),
+ span: $DIR/dump-debug-span-debug.rs:22:5: 22:6 (#0),
},
Literal {
kind: Float,
symbol: "1.0",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:18:5: 18:8 (#0),
+ span: $DIR/dump-debug-span-debug.rs:23:5: 23:8 (#0),
},
Literal {
kind: Str,
symbol: "S",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:19:5: 19:8 (#0),
+ span: $DIR/dump-debug-span-debug.rs:24:5: 24:8 (#0),
},
Literal {
kind: ByteStr,
symbol: "B",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:20:5: 20:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:25:5: 25:9 (#0),
},
Literal {
kind: StrRaw(0),
symbol: "R",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:21:5: 21:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0),
},
Literal {
kind: StrRaw(2),
symbol: "R",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:22:5: 22:13 (#0),
+ span: $DIR/dump-debug-span-debug.rs:27:5: 27:13 (#0),
},
Literal {
kind: ByteStrRaw(0),
symbol: "BR",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:23:5: 23:11 (#0),
+ span: $DIR/dump-debug-span-debug.rs:28:5: 28:11 (#0),
},
Literal {
kind: ByteStrRaw(2),
symbol: "BR",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:24:5: 24:15 (#0),
+ span: $DIR/dump-debug-span-debug.rs:29:5: 29:15 (#0),
},
Literal {
kind: Char,
symbol: "C",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:25:5: 25:8 (#0),
+ span: $DIR/dump-debug-span-debug.rs:30:5: 30:8 (#0),
},
Literal {
kind: Byte,
symbol: "B",
suffix: None,
- span: $DIR/dump-debug-span-debug.rs:26:5: 26:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0),
},
Literal {
kind: Integer,
symbol: "0",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:29:5: 29:7 (#0),
+ span: $DIR/dump-debug-span-debug.rs:34:5: 34:7 (#0),
},
Literal {
kind: Float,
symbol: "1.0",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:30:5: 30:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:35:5: 35:9 (#0),
},
Literal {
kind: Str,
symbol: "S",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:31:5: 31:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:36:5: 36:9 (#0),
},
Literal {
kind: ByteStr,
symbol: "B",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:32:5: 32:10 (#0),
+ span: $DIR/dump-debug-span-debug.rs:37:5: 37:10 (#0),
},
Literal {
kind: StrRaw(0),
symbol: "R",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:33:5: 33:10 (#0),
+ span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0),
},
Literal {
kind: StrRaw(2),
symbol: "R",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:34:5: 34:14 (#0),
+ span: $DIR/dump-debug-span-debug.rs:39:5: 39:14 (#0),
},
Literal {
kind: ByteStrRaw(0),
symbol: "BR",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:35:5: 35:12 (#0),
+ span: $DIR/dump-debug-span-debug.rs:40:5: 40:12 (#0),
},
Literal {
kind: ByteStrRaw(2),
symbol: "BR",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:36:5: 36:16 (#0),
+ span: $DIR/dump-debug-span-debug.rs:41:5: 41:16 (#0),
},
Literal {
kind: Char,
symbol: "C",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:37:5: 37:9 (#0),
+ span: $DIR/dump-debug-span-debug.rs:42:5: 42:9 (#0),
},
Literal {
kind: Byte,
symbol: "B",
suffix: Some("q"),
- span: $DIR/dump-debug-span-debug.rs:38:5: 38:10 (#0),
+ span: $DIR/dump-debug-span-debug.rs:43:5: 43:10 (#0),
},
]
diff --git a/src/test/ui/proc-macro/debug/dump-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug.stderr
index 0aedefd4e..db422b601 100644
--- a/src/test/ui/proc-macro/debug/dump-debug.stderr
+++ b/src/test/ui/proc-macro/debug/dump-debug.stderr
@@ -1,4 +1,4 @@
-TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }]
+TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..204) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(204..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }]
TokenStream [
Ident {
ident: "ident",
@@ -16,12 +16,12 @@ TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: #0 bytes(203..205),
+ span: #0 bytes(203..204),
},
Punct {
ch: '=',
spacing: Joint,
- span: #0 bytes(203..205),
+ span: #0 bytes(204..205),
},
Punct {
ch: '>',
diff --git a/src/test/ui/proc-macro/derive-bad.stderr b/src/test/ui/proc-macro/derive-bad.stderr
index ae48141fb..241f99b28 100644
--- a/src/test/ui/proc-macro/derive-bad.stderr
+++ b/src/test/ui/proc-macro/derive-bad.stderr
@@ -2,7 +2,10 @@ error: expected `:`, found `}`
--> $DIR/derive-bad.rs:6:10
|
LL | #[derive(A)]
- | ^ expected `:`
+ | ^
+ | |
+ | expected `:`
+ | while parsing this struct
|
= note: this error originates in the derive macro `A` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/proc-macro/derive-helper-shadowing.stderr b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
index d8287eb73..9c52ca422 100644
--- a/src/test/ui/proc-macro/derive-helper-shadowing.stderr
+++ b/src/test/ui/proc-macro/derive-helper-shadowing.stderr
@@ -80,9 +80,9 @@ LL | #[empty_helper]
LL | #[derive(Empty)]
| ----- the attribute is introduced here
|
- = note: `#[warn(legacy_derive_helpers)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+ = note: `#[warn(legacy_derive_helpers)]` on by default
error: aborting due to 5 previous errors; 1 warning emitted
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
index c0c9ed72c..2622c005d 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -18,12 +18,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4),
+ span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:29 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate-issue-57089.rs:17:28: 17:30 (#4),
+ span: $DIR/dollar-crate-issue-57089.rs:17:29: 17:30 (#4),
},
Ident {
ident: "S",
@@ -58,12 +58,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4),
+ span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:25 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate-issue-57089.rs:21:24: 21:26 (#4),
+ span: $DIR/dollar-crate-issue-57089.rs:21:25: 21:26 (#4),
},
Ident {
ident: "S",
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
index e6148a687..a91908239 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -30,12 +30,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4),
+ span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:31 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate-issue-62325.rs:19:30: 19:32 (#4),
+ span: $DIR/dollar-crate-issue-62325.rs:19:31: 19:32 (#4),
},
Ident {
ident: "S",
@@ -85,12 +85,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12),
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:31 (#12),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/auxiliary/dollar-crate-external.rs:21:30: 21:32 (#12),
+ span: $DIR/auxiliary/dollar-crate-external.rs:21:31: 21:32 (#12),
},
Ident {
ident: "S",
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index d01fcb9d0..4e169d47e 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -18,12 +18,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate.rs:20:32: 20:34 (#4),
+ span: $DIR/dollar-crate.rs:20:32: 20:33 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate.rs:20:32: 20:34 (#4),
+ span: $DIR/dollar-crate.rs:20:33: 20:34 (#4),
},
Ident {
ident: "S",
@@ -58,12 +58,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate.rs:24:28: 24:30 (#4),
+ span: $DIR/dollar-crate.rs:24:28: 24:29 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate.rs:24:28: 24:30 (#4),
+ span: $DIR/dollar-crate.rs:24:29: 24:30 (#4),
},
Ident {
ident: "S",
@@ -98,12 +98,12 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/dollar-crate.rs:27:28: 27:30 (#4),
+ span: $DIR/dollar-crate.rs:27:28: 27:29 (#4),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/dollar-crate.rs:27:28: 27:30 (#4),
+ span: $DIR/dollar-crate.rs:27:29: 27:30 (#4),
},
Ident {
ident: "S",
@@ -138,12 +138,12 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:29 (#15),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/auxiliary/dollar-crate-external.rs:7:28: 7:30 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:7:29: 7:30 (#15),
},
Ident {
ident: "S",
@@ -178,12 +178,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:25 (#15),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/auxiliary/dollar-crate-external.rs:11:24: 11:26 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:11:25: 11:26 (#15),
},
Ident {
ident: "S",
@@ -218,12 +218,12 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Punct {
ch: ':',
spacing: Joint,
- span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:25 (#15),
},
Punct {
ch: ':',
spacing: Alone,
- span: $DIR/auxiliary/dollar-crate-external.rs:14:24: 14:26 (#15),
+ span: $DIR/auxiliary/dollar-crate-external.rs:14:25: 14:26 (#15),
},
Ident {
ident: "S",
diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs
index 21a4547d1..042a28365 100644
--- a/src/test/ui/proc-macro/expand-with-a-macro.rs
+++ b/src/test/ui/proc-macro/expand-with-a-macro.rs
@@ -2,7 +2,6 @@
// needs-unwind
// aux-build:expand-with-a-macro.rs
-// ignore-wasm32-bare compiled with panic=abort by default
#![deny(warnings)]
diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
index 6060f872f..df7c4f72e 100644
--- a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
+++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
@@ -13,7 +13,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:12:1
|
LL | gen_macro_rules!();
- | ^^^^^^^^^^^^^^^^^^ not found in this scope
+ | ^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
...
LL | generated!();
| ------------ in this macro invocation
@@ -24,7 +24,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:21:9
|
LL | local_def;
- | ^^^^^^^^^ not found in this scope
+ | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error: aborting due to 3 previous errors
diff --git a/src/test/ui/proc-macro/generate-mod.stderr b/src/test/ui/proc-macro/generate-mod.stderr
index f1a167e37..39bf28dba 100644
--- a/src/test/ui/proc-macro/generate-mod.stderr
+++ b/src/test/ui/proc-macro/generate-mod.stderr
@@ -44,9 +44,9 @@ error: cannot find type `FromOutside` in this scope
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
- = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot find type `OuterDerive` in this scope
@@ -89,9 +89,9 @@ error: cannot find type `FromOutside` in this scope
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
- = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -101,9 +101,9 @@ error: cannot find type `OuterDerive` in this scope
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
- = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -113,9 +113,9 @@ error: cannot find type `FromOutside` in this scope
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
- = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -125,9 +125,9 @@ error: cannot find type `OuterDerive` in this scope
LL | #[derive(generate_mod::CheckDerive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
- = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
+ = note: `#[deny(proc_macro_derive_resolution_fallback)]` on by default
= note: this error originates in the derive macro `generate_mod::CheckDerive` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -137,13 +137,13 @@ warning: cannot find type `FromOutside` in this scope
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
note: the lint level is defined here
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
@@ -153,12 +153,12 @@ warning: cannot find type `OuterDeriveLint` in this scope
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ names from parent modules are not accessible without an explicit import
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
note: the lint level is defined here
--> $DIR/generate-mod.rs:30:10
|
LL | #[derive(generate_mod::CheckDeriveLint)] // OK, lint is suppressed
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83583 <https://github.com/rust-lang/rust/issues/83583>
= note: this warning originates in the derive macro `generate_mod::CheckDeriveLint` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
index 45b014c4b..9441cdcc8 100644
--- a/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
+++ b/src/test/ui/proc-macro/helper-attr-blocked-by-import-ambig.stderr
@@ -26,9 +26,9 @@ LL | #[empty_helper]
LL | #[derive(Empty)]
| ----- the attribute is introduced here
|
- = note: `#[warn(legacy_derive_helpers)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+ = note: `#[warn(legacy_derive_helpers)]` on by default
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
index 4286896df..2d357d04d 100644
--- a/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
+++ b/src/test/ui/proc-macro/inner-attr-non-inline-mod.stderr
@@ -31,9 +31,9 @@ error: custom inner attributes are unstable
LL | #![rustfmt::skip]
| ^^^^^^^^^^^^^
|
- = note: `#[deny(soft_unstable)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+ = note: `#[deny(soft_unstable)]` on by default
error: aborting due to 4 previous errors
diff --git a/src/test/ui/proc-macro/inner-attrs.stdout b/src/test/ui/proc-macro/inner-attrs.stdout
index 490fc02f5..ee8adf0b4 100644
--- a/src/test/ui/proc-macro/inner-attrs.stdout
+++ b/src/test/ui/proc-macro/inner-attrs.stdout
@@ -627,12 +627,12 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/inner-attrs.rs:39:15: 39:17 (#0),
+ span: $DIR/inner-attrs.rs:39:15: 39:16 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/inner-attrs.rs:39:15: 39:17 (#0),
+ span: $DIR/inner-attrs.rs:39:16: 39:17 (#0),
},
Group {
delimiter: Brace,
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
index 0c1c51c01..a573c6e1c 100644
--- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.rs
@@ -1,18 +1,11 @@
// aux-build:test-macros.rs
+// check-pass
#[macro_use]
extern crate test_macros;
#[derive(Print)]
enum ProceduralMasqueradeDummyType {
-//~^ ERROR using
-//~| WARN this was previously
-//~| ERROR using
-//~| WARN this was previously
-//~| ERROR using
-//~| WARN this was previously
-//~| ERROR using
-//~| WARN this was previously
Input
}
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
deleted file mode 100644
index be4239089..000000000
--- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stderr
+++ /dev/null
@@ -1,91 +0,0 @@
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[deny(proc_macro_back_compat)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-error: aborting due to 4 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[deny(proc_macro_back_compat)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-Future breakage diagnostic:
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[deny(proc_macro_back_compat)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-Future breakage diagnostic:
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[deny(proc_macro_back_compat)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
-Future breakage diagnostic:
-error: using `procedural-masquerade` crate
- --> $DIR/issue-73933-procedural-masquerade.rs:7:6
- |
-LL | enum ProceduralMasqueradeDummyType {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `#[deny(proc_macro_back_compat)]` on by default
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
- = note: The `procedural-masquerade` crate has been unnecessary since Rust 1.30.0. Versions of this crate below 0.1.7 will eventually stop compiling.
-
diff --git a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
index 50334589d..8cd981e03 100644
--- a/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
+++ b/src/test/ui/proc-macro/issue-73933-procedural-masquerade.stdout
@@ -1,22 +1,21 @@
-PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
-PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
PRINT-DERIVE INPUT (DEBUG): TokenStream [
Ident {
ident: "enum",
- span: #0 bytes(86..90),
+ span: #0 bytes(100..104),
},
Ident {
ident: "ProceduralMasqueradeDummyType",
- span: #0 bytes(91..120),
+ span: #0 bytes(105..134),
},
Group {
delimiter: Brace,
stream: TokenStream [
Ident {
ident: "Input",
- span: #0 bytes(315..320),
+ span: #0 bytes(141..146),
},
],
- span: #0 bytes(121..322),
+ span: #0 bytes(135..148),
},
]
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr
index 69d72b55c..6d1efb0dc 100644
--- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stderr
@@ -7,9 +7,9 @@ LL | #[print_helper(a)]
LL | #[derive(Print)]
| ----- the attribute is introduced here
|
- = note: `#[warn(legacy_derive_helpers)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+ = note: `#[warn(legacy_derive_helpers)]` on by default
warning: derive helper attribute is used before it is introduced
--> $DIR/issue-75930-derive-cfg.rs:19:3
diff --git a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
index c81fa201c..83afd0d3e 100644
--- a/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
+++ b/src/test/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -489,12 +489,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:33 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-75930-derive-cfg.rs:33:32: 33:34 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:33:33: 33:34 (#0),
},
Group {
delimiter: Brace,
@@ -567,12 +567,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:61 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:34:61: 34:62 (#0),
},
Group {
delimiter: Brace,
@@ -591,12 +591,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:16 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:35:16: 35:17 (#0),
},
Group {
delimiter: Brace,
@@ -1519,12 +1519,12 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:61 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-75930-derive-cfg.rs:34:60: 34:62 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:34:61: 34:62 (#0),
},
Group {
delimiter: Brace,
@@ -1543,12 +1543,12 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:16 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-75930-derive-cfg.rs:35:15: 35:17 (#0),
+ span: $DIR/issue-75930-derive-cfg.rs:35:16: 35:17 (#0),
},
Group {
delimiter: Brace,
diff --git a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
index 5493f9c7b..09eb33f7e 100644
--- a/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
+++ b/src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
@@ -41,12 +41,12 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
Punct {
ch: '=',
spacing: Joint,
- span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:22 (#0),
},
Punct {
ch: '>',
spacing: Alone,
- span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
+ span: $DIR/issue-76182-leading-vert-pat.rs:15:22: 15:23 (#0),
},
Group {
delimiter: Parenthesis,
diff --git a/src/test/ui/proc-macro/keep-expr-tokens.stderr b/src/test/ui/proc-macro/keep-expr-tokens.stderr
index 11052d11c..1a1f83cc1 100644
--- a/src/test/ui/proc-macro/keep-expr-tokens.stderr
+++ b/src/test/ui/proc-macro/keep-expr-tokens.stderr
@@ -1,15 +1,15 @@
-error[E0425]: cannot find function `missing_fn` in this scope
- --> $DIR/keep-expr-tokens.rs:17:17
- |
-LL | for item in missing_fn() {}
- | ^^^^^^^^^^ not found in this scope
-
error[E0425]: cannot find value `bad` in this scope
--> $DIR/keep-expr-tokens.rs:19:62
|
LL | (#[recollect_attr] #[recollect_attr] ((#[recollect_attr] bad)));
| ^^^ not found in this scope
+error[E0425]: cannot find function `missing_fn` in this scope
+ --> $DIR/keep-expr-tokens.rs:17:17
+ |
+LL | for item in missing_fn() {}
+ | ^^^^^^^^^^ not found in this scope
+
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.rs b/src/test/ui/proc-macro/meta-macro-hygiene.rs
index 62968ea54..70b8d8da1 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.rs
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.rs
@@ -19,8 +19,8 @@ macro_rules! produce_it {
// `print_def_site!` will respan the `$crate` identifier
// with `Span::def_site()`. This should cause it to resolve
// relative to `meta_macro`, *not* `make_macro` (despite
- // the fact that that `print_def_site` is produced by
- // a `macro_rules!` macro in `make_macro`).
+ // the fact that `print_def_site` is produced by a
+ // `macro_rules!` macro in `make_macro`).
meta_macro::print_def_site!($crate::dummy!());
}
}
diff --git a/src/test/ui/proc-macro/meta-macro-hygiene.stdout b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
index 5d04fe1e3..6b7b0c819 100644
--- a/src/test/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/src/test/ui/proc-macro/meta-macro-hygiene.stdout
@@ -1,5 +1,5 @@
Def site: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5)
-Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:43: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }]
+Input: TokenStream [Ident { ident: "$crate", span: $DIR/meta-macro-hygiene.rs:24:37: 24:43 (#4) }, Punct { ch: ':', spacing: Joint, span: $DIR/meta-macro-hygiene.rs:24:43: 24:44 (#4) }, Punct { ch: ':', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:44: 24:45 (#4) }, Ident { ident: "dummy", span: $DIR/meta-macro-hygiene.rs:24:45: 24:50 (#4) }, Punct { ch: '!', spacing: Alone, span: $DIR/meta-macro-hygiene.rs:24:50: 24:51 (#4) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/meta-macro-hygiene.rs:24:51: 24:53 (#4) }]
Respanned: TokenStream [Ident { ident: "$crate", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Joint, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: ':', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Ident { ident: "dummy", span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Punct { ch: '!', spacing: Alone, span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: $DIR/auxiliary/make-macro.rs:7:9: 7:56 (#5) }]
#![feature /* 0#0 */(prelude_import)]
// aux-build:make-macro.rs
@@ -35,8 +35,8 @@ macro_rules! produce_it
// `print_def_site!` will respan the `$crate` identifier
// with `Span::def_site()`. This should cause it to resolve
// relative to `meta_macro`, *not* `make_macro` (despite
- // the fact that that `print_def_site` is produced by
- // a `macro_rules!` macro in `make_macro`).
+ // the fact that `print_def_site` is produced by a
+ // `macro_rules!` macro in `make_macro`).
}
}
diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr
index eab4317de..137860801 100644
--- a/src/test/ui/proc-macro/mixed-site-span.stderr
+++ b/src/test/ui/proc-macro/mixed-site-span.stderr
@@ -10,7 +10,7 @@ error[E0425]: cannot find value `local_use` in this scope
--> $DIR/mixed-site-span.rs:13:9
|
LL | proc_macro_rules!();
- | ^^^^^^^^^^^^^^^^^^^ not found in this scope
+ | ^^^^^^^^^^^^^^^^^^^ help: a local variable with a similar name exists: `local_def`
|
= note: this error originates in the macro `proc_macro_rules` (in Nightly builds, run with -Z macro-backtrace for more info)
@@ -18,7 +18,7 @@ error[E0425]: cannot find value `local_def` in this scope
--> $DIR/mixed-site-span.rs:17:9
|
LL | local_def;
- | ^^^^^^^^^ not found in this scope
+ | ^^^^^^^^^ help: a local variable with a similar name exists: `local_use`
error[E0412]: cannot find type `ItemUse` in crate `$crate`
--> $DIR/mixed-site-span.rs:24:1
diff --git a/src/test/ui/proc-macro/pretty-print-hack-hide.rs b/src/test/ui/proc-macro/pretty-print-hack-hide.rs
new file mode 100644
index 000000000..f53e8fe82
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack-hide.rs
@@ -0,0 +1,12 @@
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+// check-pass
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use] extern crate test_macros;
+
+include!("pretty-print-hack/rental-0.5.6/src/lib.rs");
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/pretty-print-hack-hide.stdout b/src/test/ui/proc-macro/pretty-print-hack-hide.stdout
new file mode 100644
index 000000000..ea796bb26
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack-hide.stdout
@@ -0,0 +1,21 @@
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-hack/rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/pretty-print-hack-show.rs b/src/test/ui/proc-macro/pretty-print-hack-show.rs
new file mode 100644
index 000000000..9b1899e49
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack-show.rs
@@ -0,0 +1,17 @@
+// aux-build:test-macros.rs
+// compile-flags: -Z span-debug
+
+#![no_std] // Don't load unnecessary hygiene information from std
+extern crate std;
+
+#[macro_use] extern crate test_macros;
+
+mod first {
+ include!("pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs");
+}
+
+mod second {
+ include!("pretty-print-hack/rental-0.5.5/src/lib.rs");
+}
+
+fn main() {}
diff --git a/src/test/ui/proc-macro/pretty-print-hack-show.stderr b/src/test/ui/proc-macro/pretty-print-hack-show.stderr
new file mode 100644
index 000000000..873054927
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack-show.stderr
@@ -0,0 +1,179 @@
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+
+error: aborting due to 8 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
+Future breakage diagnostic:
+error: using an old version of `rental`
+ --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6
+ |
+LL | enum ProceduralMasqueradeDummyType {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #83125 <https://github.com/rust-lang/rust/issues/83125>
+ = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives
+ = note: `#[deny(proc_macro_back_compat)]` on by default
+
diff --git a/src/test/ui/proc-macro/pretty-print-hack-show.stdout b/src/test/ui/proc-macro/pretty-print-hack-show.stdout
new file mode 100644
index 000000000..3d793d2a0
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack-show.stdout
@@ -0,0 +1,44 @@
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
+PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, }
+PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input }
+PRINT-DERIVE INPUT (DEBUG): TokenStream [
+ Ident {
+ ident: "enum",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0),
+ },
+ Ident {
+ ident: "ProceduralMasqueradeDummyType",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0),
+ },
+ Group {
+ delimiter: Brace,
+ stream: TokenStream [
+ Ident {
+ ident: "Input",
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0),
+ },
+ ],
+ span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0),
+ },
+]
diff --git a/src/test/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs b/src/test/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs
new file mode 100644
index 000000000..9501980fa
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs
@@ -0,0 +1,14 @@
+// ignore-test
+
+#[derive(Print)]
+enum ProceduralMasqueradeDummyType {
+//~^ ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+ Input
+}
diff --git a/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs b/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs
new file mode 100644
index 000000000..9501980fa
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.5/src/lib.rs
@@ -0,0 +1,14 @@
+// ignore-test
+
+#[derive(Print)]
+enum ProceduralMasqueradeDummyType {
+//~^ ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+ Input
+}
diff --git a/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs b/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs
new file mode 100644
index 000000000..9501980fa
--- /dev/null
+++ b/src/test/ui/proc-macro/pretty-print-hack/rental-0.5.6/src/lib.rs
@@ -0,0 +1,14 @@
+// ignore-test
+
+#[derive(Print)]
+enum ProceduralMasqueradeDummyType {
+//~^ ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+//~| ERROR using
+//~| WARN this was previously
+ Input
+}
diff --git a/src/test/ui/proc-macro/proc-macro-attributes.stderr b/src/test/ui/proc-macro/proc-macro-attributes.stderr
index b66e4575e..140d87906 100644
--- a/src/test/ui/proc-macro/proc-macro-attributes.stderr
+++ b/src/test/ui/proc-macro/proc-macro-attributes.stderr
@@ -85,9 +85,9 @@ LL | #[B]
LL | #[derive(B)]
| - the attribute is introduced here
|
- = note: `#[warn(legacy_derive_helpers)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #79202 <https://github.com/rust-lang/rust/issues/79202>
+ = note: `#[warn(legacy_derive_helpers)]` on by default
warning: derive helper attribute is used before it is introduced
--> $DIR/proc-macro-attributes.rs:10:3
diff --git a/src/test/ui/proc-macro/proc-macro-gates.stderr b/src/test/ui/proc-macro/proc-macro-gates.stderr
index 118213a17..3feb9b829 100644
--- a/src/test/ui/proc-macro/proc-macro-gates.stderr
+++ b/src/test/ui/proc-macro/proc-macro-gates.stderr
@@ -82,9 +82,9 @@ error: inner macro attributes are unstable
LL | #![test]
| ^^^^
|
- = note: `#[deny(soft_unstable)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+ = note: `#[deny(soft_unstable)]` on by default
error: aborting due to 10 previous errors
diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr
index 1ce5e02bd..9cdb2a21b 100644
--- a/src/test/ui/proc-macro/three-equals.stderr
+++ b/src/test/ui/proc-macro/three-equals.stderr
@@ -8,16 +8,16 @@ LL | three_equals!(==);
= note: this error originates in the macro `three_equals` (in Nightly builds, run with -Z macro-backtrace for more info)
error: expected EOF, found `=`.
- --> $DIR/three-equals.rs:15:21
+ --> $DIR/three-equals.rs:15:22
|
LL | three_equals!(=====);
- | ^^
+ | ^
|
note: last good input was here
--> $DIR/three-equals.rs:15:21
|
LL | three_equals!(=====);
- | ^^
+ | ^
= help: input must be: `===`
error: expected `=`, found `abc`.
diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs
index 1ccf6bb05..6d4d24922 100644
--- a/src/test/ui/process/process-panic-after-fork.rs
+++ b/src/test/ui/process/process-panic-after-fork.rs
@@ -5,9 +5,8 @@
// ignore-sgx no libc
// ignore-emscripten no processes
// ignore-sgx no processes
-// ignore-android: FIXME(#85261)
+// ignore-fuchsia no fork
-#![feature(bench_black_box)]
#![feature(rustc_private)]
#![feature(never_type)]
#![feature(panic_always_abort)]
@@ -79,7 +78,49 @@ unsafe impl<A:GlobalAlloc> GlobalAlloc for PidChecking<A> {
fn expect_aborted(status: ExitStatus) {
dbg!(status);
let signal = status.signal().expect("expected child process to die of signal");
+
+ #[cfg(not(target_os = "android"))]
assert!(signal == libc::SIGABRT || signal == libc::SIGILL || signal == libc::SIGTRAP);
+
+ #[cfg(target_os = "android")]
+ {
+ // Android signals an abort() call with SIGSEGV at address 0xdeadbaad
+ // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc
+ assert!(signal == libc::SIGSEGV);
+
+ // Additional checks performed:
+ // 1. Find last tombstone (similar to coredump but in text format) from the
+ // same executable (path) as we are (must be because of usage of fork):
+ // This ensures that we look into the correct tombstone.
+ // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad.
+ // 3. libc::abort call is in one of top two functions on callstack.
+ // The last two steps distinguish between a normal SIGSEGV and one caused
+ // by libc::abort.
+
+ let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap();
+ let exe_string = format!(">>> {this_exe} <<<");
+ let tombstone = (0..100)
+ .map(|n| format!("/data/tombstones/tombstone_{n:02}"))
+ .filter(|f| std::path::Path::new(&f).exists())
+ .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file"))
+ .filter(|f| f.contains(&exe_string))
+ .last()
+ .expect("no tombstone found");
+
+ println!("Content of tombstone:\n{tombstone}");
+
+ assert!(
+ tombstone.contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad")
+ );
+ let abort_on_top = tombstone
+ .lines()
+ .skip_while(|l| !l.contains("backtrace:"))
+ .skip(1)
+ .take_while(|l| l.starts_with(" #"))
+ .take(2)
+ .any(|f| f.contains("/system/lib/libc.so (abort"));
+ assert!(abort_on_top);
+ }
}
fn main() {
diff --git a/src/test/ui/process/process-spawn-nonexistent.rs b/src/test/ui/process/process-spawn-nonexistent.rs
index a51372263..9dd608986 100644
--- a/src/test/ui/process/process-spawn-nonexistent.rs
+++ b/src/test/ui/process/process-spawn-nonexistent.rs
@@ -1,6 +1,7 @@
// run-pass
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia ErrorKind not translated
use std::io::ErrorKind;
use std::process::Command;
diff --git a/src/test/ui/process/process-spawn-with-unicode-params.rs b/src/test/ui/process/process-spawn-with-unicode-params.rs
index 6e9229b62..16dba6292 100644
--- a/src/test/ui/process/process-spawn-with-unicode-params.rs
+++ b/src/test/ui/process/process-spawn-with-unicode-params.rs
@@ -9,6 +9,7 @@
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia Filesystem manipulation privileged
use std::io::prelude::*;
use std::io;
diff --git a/src/test/ui/process/signal-exit-status.rs b/src/test/ui/process/signal-exit-status.rs
index 0963dcc80..9519ed7b4 100644
--- a/src/test/ui/process/signal-exit-status.rs
+++ b/src/test/ui/process/signal-exit-status.rs
@@ -2,6 +2,7 @@
// ignore-emscripten no processes
// ignore-sgx no processes
// ignore-windows
+// ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590)
use std::env;
use std::process::Command;
diff --git a/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr b/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr
index e4d73c647..c7fadc6f9 100644
--- a/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr
+++ b/src/test/ui/pub/pub-reexport-priv-extern-crate.stderr
@@ -28,9 +28,9 @@ error: extern crate `core` is private, and cannot be re-exported (error E0365),
LL | pub use core as reexported_core;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
+ = note: `#[deny(pub_use_of_private_extern_crate)]` on by default
error: aborting due to 3 previous errors
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
index 95bf498c7..b47328f34 100644
--- a/src/test/ui/pub/pub-restricted-error.stderr
+++ b/src/test/ui/pub/pub-restricted-error.stderr
@@ -1,6 +1,8 @@
error: expected identifier, found `(`
--> $DIR/pub-restricted-error.rs:4:16
|
+LL | struct Foo {
+ | --- while parsing this struct
LL | pub(crate) () foo: usize,
| ^ expected identifier
diff --git a/src/test/ui/query-system/query_depth.rs b/src/test/ui/query-system/query_depth.rs
new file mode 100644
index 000000000..e600c1c08
--- /dev/null
+++ b/src/test/ui/query-system/query_depth.rs
@@ -0,0 +1,31 @@
+// build-fail
+
+#![recursion_limit = "64"]
+type Byte = Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Option<Option<Option<Option< Option<Option<Option<Option<
+ Box<String>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+ >>>> >>>>
+>>>> >>>>;
+
+fn main() {
+//~^ ERROR: queries overflow the depth limit!
+ println!("{}", std::mem::size_of::<Byte>());
+}
diff --git a/src/test/ui/query-system/query_depth.stderr b/src/test/ui/query-system/query_depth.stderr
new file mode 100644
index 000000000..43a18b4e0
--- /dev/null
+++ b/src/test/ui/query-system/query_depth.stderr
@@ -0,0 +1,11 @@
+error: queries overflow the depth limit!
+ --> $DIR/query_depth.rs:28:1
+ |
+LL | fn main() {
+ | ^^^^^^^^^
+ |
+ = help: consider increasing the recursion limit by adding a `#![recursion_limit = "128"]` attribute to your crate (`query_depth`)
+ = note: query depth increased by 66 when computing layout of `core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<core::option::Option<alloc::boxed::Box<alloc::string::String>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/query-visibility.rs b/src/test/ui/query-visibility.rs
new file mode 100644
index 000000000..09a289d85
--- /dev/null
+++ b/src/test/ui/query-visibility.rs
@@ -0,0 +1,9 @@
+// check-pass
+// Check that it doesn't panic when `Input` gets its visibility checked.
+
+#![crate_type = "lib"]
+
+pub trait Layer<
+ /// Hello.
+ Input,
+> {}
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence.stderr b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
index 10513374c..f6788d034 100644
--- a/src/test/ui/range/range-inclusive-pattern-precedence.stderr
+++ b/src/test/ui/range/range-inclusive-pattern-precedence.stderr
@@ -10,13 +10,13 @@ warning: `...` range patterns are deprecated
LL | &0...9 => {}
| ^^^^^^ help: use `..=` for an inclusive range: `&(0..=9)`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/range-inclusive-pattern-precedence.rs:7:9
|
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/range/range-inclusive-pattern-precedence2.stderr b/src/test/ui/range/range-inclusive-pattern-precedence2.stderr
index cdec41d7f..bb4e3a13a 100644
--- a/src/test/ui/range/range-inclusive-pattern-precedence2.stderr
+++ b/src/test/ui/range/range-inclusive-pattern-precedence2.stderr
@@ -10,13 +10,13 @@ warning: `...` range patterns are deprecated
LL | box 0...9 => {}
| ^^^ help: use `..=` for an inclusive range
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/range-inclusive-pattern-precedence2.rs:5:9
|
LL | #![warn(ellipsis_inclusive_range_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr
index 32f25faf3..3e0229717 100644
--- a/src/test/ui/recursion/issue-83150.stderr
+++ b/src/test/ui/recursion/issue-83150.stderr
@@ -6,14 +6,12 @@ LL | fn func<T: Iterator<Item = u8>>(iter: &mut T) {
LL | func(&mut iter.map(|x| x + 1))
| ------------------------------ recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= 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 `<std::ops::Range<u8> as Iterator>::Item`
+error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>: Iterator`
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
- = note: required for `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
- = note: 64 redundant requirements hidden
= note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/recursion/issue-95134.rs b/src/test/ui/recursion/issue-95134.rs
index adc9c6ee2..fdc4d5369 100644
--- a/src/test/ui/recursion/issue-95134.rs
+++ b/src/test/ui/recursion/issue-95134.rs
@@ -1,6 +1,8 @@
// build-fail
+// known-bug: #95134
// compile-flags: -Copt-level=0
-//~^^ ERROR overflow evaluating the requirement
+// failure-status: 101
+// dont-check-compiler-stderr
pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> {
if n > 15 {
diff --git a/src/test/ui/recursion/issue-95134.stderr b/src/test/ui/recursion/issue-95134.stderr
deleted file mode 100644
index 57a498694..000000000
--- a/src/test/ui/recursion/issue-95134.stderr
+++ /dev/null
@@ -1,7 +0,0 @@
-error[E0275]: overflow evaluating the requirement `<EmptyWriter as ExampleWriter>::Error`
- |
- = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95134`)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr
index f5d25c564..d662d1022 100644
--- a/src/test/ui/recursion/recursive-enum.stderr
+++ b/src/test/ui/recursion/recursive-enum.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `List` has infinite size
|
LL | enum List<T> { Cons(T, List<T>), Nil }
| ^^^^^^^^^^^^ ------- recursive without indirection
- | |
- | recursive type has infinite size
|
-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
|
LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
| ++++ +
diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
index 321ee0a36..f2307899d 100644
--- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
+++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr
@@ -6,7 +6,7 @@ LL | let Ok(x) = res;
|
= 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: `Result<u32, &R>` defined here
+note: `Result<u32, &R<'_>>` defined here
--> $SRC_DIR/core/src/result.rs:LL:COL
|
LL | pub enum Result<T, E> {
@@ -14,7 +14,7 @@ LL | pub enum Result<T, E> {
...
LL | Err(#[stable(feature = "rust1", since = "1.0.0")] E),
| ^^^ not covered
- = note: the matched value is of type `Result<u32, &R>`
+ = note: the matched value is of type `Result<u32, &R<'_>>`
help: you might want to use `if let` to ignore the variant that isn't matched
|
LL | let x = if let Ok(x) = res { x } else { todo!() };
diff --git a/src/test/ui/regions/issue-101280.rs b/src/test/ui/regions/issue-101280.rs
new file mode 100644
index 000000000..29f158366
--- /dev/null
+++ b/src/test/ui/regions/issue-101280.rs
@@ -0,0 +1,10 @@
+use std::cell::Cell;
+
+type Ty = for<'r> fn(Cell<(&'r i32, &'r i32)>);
+
+fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty {
+ f
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-101280.stderr b/src/test/ui/regions/issue-101280.stderr
new file mode 100644
index 000000000..320d008ae
--- /dev/null
+++ b/src/test/ui/regions/issue-101280.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-101280.rs:6:5
+ |
+LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty {
+ | -- expected `for<'r> fn(Cell<(&'r i32, &'r i32)>)` because of return type
+LL | f
+ | ^ one type is more general than the other
+ |
+ = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)`
+ found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs
new file mode 100644
index 000000000..e0a116421
--- /dev/null
+++ b/src/test/ui/regions/issue-102374.rs
@@ -0,0 +1,20 @@
+use std::cell::Cell;
+
+#[rustfmt::skip]
+fn f(
+ f: for<'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<(& i32, &'a i32, &'b i32, &'c i32, &'d i32,
+ &'e i32, &'f i32, &'g i32, &'h i32, &'i i32,
+ &'j i32, &'k i32, &'l i32, &'m i32, &'n i32,
+ &'o i32, &'p i32, &'q i32, &'r i32, &'s i32,
+ &'t i32, &'u i32, &'v i32, &'w i32, &'x i32,
+ &'y i32, &'z i32, &'z0 i32)>),
+) -> i32 {
+ f
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr
new file mode 100644
index 000000000..31b855c36
--- /dev/null
+++ b/src/test/ui/regions/issue-102374.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102374.rs:16:5
+ |
+LL | ) -> i32 {
+ | --- expected `i32` because of return type
+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<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/issue-102392.rs b/src/test/ui/regions/issue-102392.rs
new file mode 100644
index 000000000..87cc1a8e7
--- /dev/null
+++ b/src/test/ui/regions/issue-102392.rs
@@ -0,0 +1,6 @@
+fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool {
+ f
+ //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/issue-102392.stderr b/src/test/ui/regions/issue-102392.stderr
new file mode 100644
index 000000000..56f4c0c5d
--- /dev/null
+++ b/src/test/ui/regions/issue-102392.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-102392.rs:2:5
+ |
+LL | fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool {
+ | ---- expected `bool` because of return type
+LL | f
+ | ^ expected `bool`, found fn pointer
+ |
+ = note: expected type `bool`
+ found fn pointer `for<'a> fn(for<'b> fn(&'b str, &'a str))`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
index a2396ad42..ea43dde11 100644
--- a/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
+++ b/src/test/ui/regions/region-bound-on-closure-outlives-call.stderr
@@ -7,8 +7,8 @@ LL |
LL | (|x| f(x))(call_rec(f))
| ----------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= help: a `loop` may express intention better if this is on purpose
+ = note: `#[warn(unconditional_recursion)]` on by default
error[E0505]: cannot move out of `f` because it is borrowed
--> $DIR/region-bound-on-closure-outlives-call.rs:3:25
diff --git a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
index 48f2e1a2f..3b62c7b61 100644
--- a/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
+++ b/src/test/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
- found fn item `for<'r, 's> fn(&'r mut &isize, &'s 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::<'_, '_>}`
error: aborting due to previous error
diff --git a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
index 36f40cd9a..8a18a234b 100644
--- a/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
+++ b/src/test/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r, 's, 't0, 't1, 't2, 't3> fn(&'r mut &'s isize, &'t0 mut &'t1 isize, &'t2 mut &'t3 isize)`
- found fn item `for<'r, 's, 't0> fn(&'r mut &isize, &'s mut &isize, &'t0 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::<'_, '_, '_>}`
error: aborting due to previous error
diff --git a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr
index d87d0d2f6..8d82ff958 100644
--- a/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr
+++ b/src/test/ui/regions/regions-fn-subtyping-return-static-fail.stderr
@@ -7,7 +7,7 @@ LL | want_G(baz);
| arguments to this function are incorrect
|
= note: expected fn pointer `for<'cx> fn(&'cx S) -> &'static S`
- found fn item `for<'r> fn(&'r S) -> &'r S {baz}`
+ found fn item `for<'a> fn(&'a S) -> &'a S {baz}`
note: function defined here
--> $DIR/regions-fn-subtyping-return-static-fail.rs:20:4
|
diff --git a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
index a0daf58c6..17a901943 100644
--- a/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
+++ b/src/test/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
LL | let _: fn(&mut &isize, &mut &isize) = a;
| ^ one type is more general than the other
|
- = note: expected fn pointer `for<'r, 's, 't0, 't1> fn(&'r mut &'s isize, &'t0 mut &'t1 isize)`
- found fn item `for<'r, 's> fn(&'r mut &isize, &'s 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::<'_, '_>}`
error: aborting due to previous error
diff --git a/src/test/ui/repr/repr-transparent-issue-87496.stderr b/src/test/ui/repr/repr-transparent-issue-87496.stderr
index 3dc13b1c1..aee31212b 100644
--- a/src/test/ui/repr/repr-transparent-issue-87496.stderr
+++ b/src/test/ui/repr/repr-transparent-issue-87496.stderr
@@ -4,13 +4,13 @@ warning: `extern` block uses type `TransparentCustomZst`, which is not FFI-safe
LL | fn good17(p: TransparentCustomZst);
| ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
- = note: `#[warn(improper_ctypes)]` on by default
= note: this struct contains only zero-sized fields
note: the type is defined here
--> $DIR/repr-transparent-issue-87496.rs:6:1
|
LL | struct TransparentCustomZst(());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[warn(improper_ctypes)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.rs b/src/test/ui/repr/repr-transparent-non-exhaustive.rs
index 9ccd8610d..506f1dcf3 100644
--- a/src/test/ui/repr/repr-transparent-non-exhaustive.rs
+++ b/src/test/ui/repr/repr-transparent-non-exhaustive.rs
@@ -35,62 +35,62 @@ pub struct T4(Sized, ExternalIndirection<(InternalPrivate, InternalNonExhaustive
#[repr(transparent)]
pub struct T5(Sized, Private);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T6(Sized, NonExhaustive);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T7(Sized, NonExhaustiveEnum);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T8(Sized, NonExhaustiveVariant);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T9(Sized, InternalIndirection<Private>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T10(Sized, InternalIndirection<NonExhaustive>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T11(Sized, InternalIndirection<NonExhaustiveEnum>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T12(Sized, InternalIndirection<NonExhaustiveVariant>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T13(Sized, ExternalIndirection<Private>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T14(Sized, ExternalIndirection<NonExhaustive>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T15(Sized, ExternalIndirection<NonExhaustiveEnum>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
#[repr(transparent)]
pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
-//~^ ERROR zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+//~^ ERROR zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
//~| WARN this was previously accepted by the compiler
fn main() {}
diff --git a/src/test/ui/repr/repr-transparent-non-exhaustive.stderr b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr
index 3b1e334a0..16edf59c7 100644
--- a/src/test/ui/repr/repr-transparent-non-exhaustive.stderr
+++ b/src/test/ui/repr/repr-transparent-non-exhaustive.stderr
@@ -1,19 +1,19 @@
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:37:22
|
LL | pub struct T5(Sized, Private);
| ^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
+ = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
note: the lint level is defined here
--> $DIR/repr-transparent-non-exhaustive.rs:1:9
|
LL | #![deny(repr_transparent_external_private_fields)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
- = note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:42:22
|
LL | pub struct T6(Sized, NonExhaustive);
@@ -23,7 +23,7 @@ LL | pub struct T6(Sized, NonExhaustive);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:47:22
|
LL | pub struct T7(Sized, NonExhaustiveEnum);
@@ -33,7 +33,7 @@ LL | pub struct T7(Sized, NonExhaustiveEnum);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:52:22
|
LL | pub struct T8(Sized, NonExhaustiveVariant);
@@ -43,7 +43,7 @@ LL | pub struct T8(Sized, NonExhaustiveVariant);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:57:22
|
LL | pub struct T9(Sized, InternalIndirection<Private>);
@@ -53,7 +53,7 @@ LL | pub struct T9(Sized, InternalIndirection<Private>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:62:23
|
LL | pub struct T10(Sized, InternalIndirection<NonExhaustive>);
@@ -63,7 +63,7 @@ LL | pub struct T10(Sized, InternalIndirection<NonExhaustive>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:67:23
|
LL | pub struct T11(Sized, InternalIndirection<NonExhaustiveEnum>);
@@ -73,7 +73,7 @@ LL | pub struct T11(Sized, InternalIndirection<NonExhaustiveEnum>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:72:23
|
LL | pub struct T12(Sized, InternalIndirection<NonExhaustiveVariant>);
@@ -83,7 +83,7 @@ LL | pub struct T12(Sized, InternalIndirection<NonExhaustiveVariant>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveVariant`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:77:23
|
LL | pub struct T13(Sized, ExternalIndirection<Private>);
@@ -93,7 +93,7 @@ LL | pub struct T13(Sized, ExternalIndirection<Private>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `Private`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:82:23
|
LL | pub struct T14(Sized, ExternalIndirection<NonExhaustive>);
@@ -103,7 +103,7 @@ LL | pub struct T14(Sized, ExternalIndirection<NonExhaustive>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `NonExhaustive`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:87:23
|
LL | pub struct T15(Sized, ExternalIndirection<NonExhaustiveEnum>);
@@ -113,7 +113,7 @@ LL | pub struct T15(Sized, ExternalIndirection<NonExhaustiveEnum>);
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this enum contains `NonExhaustiveEnum`, which is marked with `#[non_exhaustive]`, and makes it not a breaking change to become non-zero-sized in the future.
-error: zero-sized fields in repr(transparent) cannot contain external non-exhaustive types
+error: zero-sized fields in `repr(transparent)` cannot contain external non-exhaustive types
--> $DIR/repr-transparent-non-exhaustive.rs:92:23
|
LL | pub struct T16(Sized, ExternalIndirection<NonExhaustiveVariant>);
diff --git a/src/test/ui/resolve/bad-env-capture.stderr b/src/test/ui/resolve/bad-env-capture.stderr
index f78a38a3d..59b1fabfd 100644
--- a/src/test/ui/resolve/bad-env-capture.stderr
+++ b/src/test/ui/resolve/bad-env-capture.stderr
@@ -6,18 +6,18 @@ LL | fn bar() { log(debug, x); }
|
= help: use the `|| { ... }` closure form instead
-error[E0425]: cannot find function `log` in this scope
- --> $DIR/bad-env-capture.rs:4:16
- |
-LL | fn bar() { log(debug, x); }
- | ^^^ not found in this scope
-
error[E0425]: cannot find value `debug` in this scope
--> $DIR/bad-env-capture.rs:4:20
|
LL | fn bar() { log(debug, x); }
| ^^^^^ not found in this scope
+error[E0425]: cannot find function `log` in this scope
+ --> $DIR/bad-env-capture.rs:4:16
+ |
+LL | fn bar() { log(debug, x); }
+ | ^^^ not found in this scope
+
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0425, E0434.
diff --git a/src/test/ui/resolve/bad-env-capture2.stderr b/src/test/ui/resolve/bad-env-capture2.stderr
index 57c807fd7..811c259de 100644
--- a/src/test/ui/resolve/bad-env-capture2.stderr
+++ b/src/test/ui/resolve/bad-env-capture2.stderr
@@ -6,18 +6,18 @@ LL | fn bar() { log(debug, x); }
|
= help: use the `|| { ... }` closure form instead
-error[E0425]: cannot find function `log` in this scope
- --> $DIR/bad-env-capture2.rs:3:16
- |
-LL | fn bar() { log(debug, x); }
- | ^^^ not found in this scope
-
error[E0425]: cannot find value `debug` in this scope
--> $DIR/bad-env-capture2.rs:3:20
|
LL | fn bar() { log(debug, x); }
| ^^^^^ not found in this scope
+error[E0425]: cannot find function `log` in this scope
+ --> $DIR/bad-env-capture2.rs:3:16
+ |
+LL | fn bar() { log(debug, x); }
+ | ^^^ not found in this scope
+
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0425, E0434.
diff --git a/src/test/ui/resolve/bad-env-capture3.stderr b/src/test/ui/resolve/bad-env-capture3.stderr
index d6eb4f86e..eab37fde9 100644
--- a/src/test/ui/resolve/bad-env-capture3.stderr
+++ b/src/test/ui/resolve/bad-env-capture3.stderr
@@ -6,18 +6,18 @@ LL | fn bar() { log(debug, x); }
|
= help: use the `|| { ... }` closure form instead
-error[E0425]: cannot find function `log` in this scope
- --> $DIR/bad-env-capture3.rs:4:20
- |
-LL | fn bar() { log(debug, x); }
- | ^^^ not found in this scope
-
error[E0425]: cannot find value `debug` in this scope
--> $DIR/bad-env-capture3.rs:4:24
|
LL | fn bar() { log(debug, x); }
| ^^^^^ not found in this scope
+error[E0425]: cannot find function `log` in this scope
+ --> $DIR/bad-env-capture3.rs:4:20
+ |
+LL | fn bar() { log(debug, x); }
+ | ^^^ not found in this scope
+
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0425, E0434.
diff --git a/src/test/ui/resolve/bad-expr-path.stderr b/src/test/ui/resolve/bad-expr-path.stderr
index 77c48c951..8261e8e53 100644
--- a/src/test/ui/resolve/bad-expr-path.stderr
+++ b/src/test/ui/resolve/bad-expr-path.stderr
@@ -1,9 +1,3 @@
-error[E0425]: cannot find function `log` in this scope
- --> $DIR/bad-expr-path.rs:4:5
- |
-LL | log(debug, m1::arguments);
- | ^^^ not found in this scope
-
error[E0425]: cannot find value `debug` in this scope
--> $DIR/bad-expr-path.rs:4:9
|
@@ -16,6 +10,12 @@ error[E0425]: cannot find value `arguments` in module `m1`
LL | log(debug, m1::arguments);
| ^^^^^^^^^ not found in `m1`
+error[E0425]: cannot find function `log` in this scope
+ --> $DIR/bad-expr-path.rs:4:5
+ |
+LL | log(debug, m1::arguments);
+ | ^^^ not found in this scope
+
error[E0580]: `main` function has wrong type
--> $DIR/bad-expr-path.rs:3:1
|
diff --git a/src/test/ui/resolve/bad-expr-path2.stderr b/src/test/ui/resolve/bad-expr-path2.stderr
index d06e10271..6e11296d9 100644
--- a/src/test/ui/resolve/bad-expr-path2.stderr
+++ b/src/test/ui/resolve/bad-expr-path2.stderr
@@ -1,9 +1,3 @@
-error[E0425]: cannot find function `log` in this scope
- --> $DIR/bad-expr-path2.rs:6:5
- |
-LL | log(debug, m1::arguments);
- | ^^^ not found in this scope
-
error[E0425]: cannot find value `debug` in this scope
--> $DIR/bad-expr-path2.rs:6:9
|
@@ -16,6 +10,12 @@ error[E0423]: expected value, found module `m1::arguments`
LL | log(debug, m1::arguments);
| ^^^^^^^^^^^^^ not a value
+error[E0425]: cannot find function `log` in this scope
+ --> $DIR/bad-expr-path2.rs:6:5
+ |
+LL | log(debug, m1::arguments);
+ | ^^^ not found in this scope
+
error[E0580]: `main` function has wrong type
--> $DIR/bad-expr-path2.rs:5:1
|
diff --git a/src/test/ui/resolve/issue-102946.rs b/src/test/ui/resolve/issue-102946.rs
new file mode 100644
index 000000000..c6feca6f3
--- /dev/null
+++ b/src/test/ui/resolve/issue-102946.rs
@@ -0,0 +1,7 @@
+impl Error for str::Utf8Error {
+ //~^ ERROR cannot find trait `Error` in this scope
+ //~| ERROR ambiguous associated type
+ fn description(&self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-102946.stderr b/src/test/ui/resolve/issue-102946.stderr
new file mode 100644
index 000000000..65be0258e
--- /dev/null
+++ b/src/test/ui/resolve/issue-102946.stderr
@@ -0,0 +1,26 @@
+error[E0405]: cannot find trait `Error` in this scope
+ --> $DIR/issue-102946.rs:1:6
+ |
+LL | impl Error for str::Utf8Error {
+ | ^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+LL | use std::error::Error;
+ |
+
+error[E0223]: ambiguous associated type
+ --> $DIR/issue-102946.rs:1:16
+ |
+LL | impl Error for str::Utf8Error {
+ | ^^^^^^^^^^^^^^
+ |
+help: you are looking for the module in `std`, not the primitive type
+ |
+LL | impl Error for std::str::Utf8Error {
+ | +++++
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0223, E0405.
+For more information about an error, try `rustc --explain E0223`.
diff --git a/src/test/ui/resolve/issue-103202.rs b/src/test/ui/resolve/issue-103202.rs
new file mode 100644
index 000000000..469d9d7c8
--- /dev/null
+++ b/src/test/ui/resolve/issue-103202.rs
@@ -0,0 +1,7 @@
+struct S {}
+
+impl S {
+ fn f(self: &S::x) {} //~ ERROR ambiguous associated type
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-103202.stderr b/src/test/ui/resolve/issue-103202.stderr
new file mode 100644
index 000000000..880389371
--- /dev/null
+++ b/src/test/ui/resolve/issue-103202.stderr
@@ -0,0 +1,9 @@
+error[E0223]: ambiguous associated type
+ --> $DIR/issue-103202.rs:4:17
+ |
+LL | fn f(self: &S::x) {}
+ | ^^^^ help: use fully-qualified syntax: `<S as Trait>::x`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/src/test/ui/resolve/issue-14254.stderr b/src/test/ui/resolve/issue-14254.stderr
index b1f45adb8..690a40f7e 100644
--- a/src/test/ui/resolve/issue-14254.stderr
+++ b/src/test/ui/resolve/issue-14254.stderr
@@ -1,21 +1,9 @@
-error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:19:9
- |
-LL | baz();
- | ^^^ help: you might have meant to call the method: `self.baz`
-
error[E0425]: cannot find value `a` in this scope
--> $DIR/issue-14254.rs:21:9
|
LL | a;
| ^ not found in this scope
-error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:28:9
- |
-LL | baz();
- | ^^^ help: you might have meant to call the method: `self.baz`
-
error[E0425]: cannot find value `x` in this scope
--> $DIR/issue-14254.rs:30:9
|
@@ -38,7 +26,12 @@ error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:36:9
|
LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
error[E0425]: cannot find value `b` in this scope
--> $DIR/issue-14254.rs:38:9
@@ -46,12 +39,6 @@ error[E0425]: cannot find value `b` in this scope
LL | b;
| ^ not found in this scope
-error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:45:9
- |
-LL | baz();
- | ^^^ help: you might have meant to call the method: `self.baz`
-
error[E0425]: cannot find value `x` in this scope
--> $DIR/issue-14254.rs:47:9
|
@@ -74,7 +61,12 @@ error[E0425]: cannot find value `bah` in this scope
--> $DIR/issue-14254.rs:53:9
|
LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
error[E0425]: cannot find value `b` in this scope
--> $DIR/issue-14254.rs:55:9
@@ -82,65 +74,108 @@ error[E0425]: cannot find value `b` in this scope
LL | b;
| ^ not found in this scope
-error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:62:9
+error[E0425]: cannot find value `bah` in this scope
+ --> $DIR/issue-14254.rs:64:9
|
-LL | baz();
- | ^^^ help: you might have meant to call the method: `self.baz`
+LL | bah;
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
error[E0425]: cannot find value `bah` in this scope
- --> $DIR/issue-14254.rs:64:9
+ --> $DIR/issue-14254.rs:73:9
+ |
+LL | bah;
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
+
+error[E0425]: cannot find value `bah` in this scope
+ --> $DIR/issue-14254.rs:82:9
+ |
+LL | bah;
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
+
+error[E0425]: cannot find value `bah` in this scope
+ --> $DIR/issue-14254.rs:91:9
+ |
+LL | bah;
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
+
+error[E0425]: cannot find value `bah` in this scope
+ --> $DIR/issue-14254.rs:100:9
|
LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+ | ^^^
+ |
+help: you might have meant to refer to the associated function
+ |
+LL | Self::bah;
+ | ~~~~~~~~~
error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:71:9
+ --> $DIR/issue-14254.rs:19:9
|
LL | baz();
| ^^^ help: you might have meant to call the method: `self.baz`
-error[E0425]: cannot find value `bah` in this scope
- --> $DIR/issue-14254.rs:73:9
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/issue-14254.rs:28:9
|
-LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+LL | baz();
+ | ^^^ help: you might have meant to call the method: `self.baz`
error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:80:9
+ --> $DIR/issue-14254.rs:45:9
|
LL | baz();
| ^^^ help: you might have meant to call the method: `self.baz`
-error[E0425]: cannot find value `bah` in this scope
- --> $DIR/issue-14254.rs:82:9
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/issue-14254.rs:62:9
|
-LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+LL | baz();
+ | ^^^ help: you might have meant to call the method: `self.baz`
error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:89:9
+ --> $DIR/issue-14254.rs:71:9
|
LL | baz();
| ^^^ help: you might have meant to call the method: `self.baz`
-error[E0425]: cannot find value `bah` in this scope
- --> $DIR/issue-14254.rs:91:9
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/issue-14254.rs:80:9
|
-LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+LL | baz();
+ | ^^^ help: you might have meant to call the method: `self.baz`
error[E0425]: cannot find function `baz` in this scope
- --> $DIR/issue-14254.rs:98:9
+ --> $DIR/issue-14254.rs:89:9
|
LL | baz();
| ^^^ help: you might have meant to call the method: `self.baz`
-error[E0425]: cannot find value `bah` in this scope
- --> $DIR/issue-14254.rs:100:9
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/issue-14254.rs:98:9
|
-LL | bah;
- | ^^^ help: you might have meant to call the associated function: `Self::bah`
+LL | baz();
+ | ^^^ help: you might have meant to call the method: `self.baz`
error: aborting due to 24 previous errors
diff --git a/src/test/ui/resolve/issue-23305.rs b/src/test/ui/resolve/issue-23305.rs
index 95635e12a..6d7fe7c50 100644
--- a/src/test/ui/resolve/issue-23305.rs
+++ b/src/test/ui/resolve/issue-23305.rs
@@ -3,6 +3,6 @@ pub trait ToNbt<T> {
}
impl dyn ToNbt<Self> {}
-//~^ ERROR cycle detected
+//~^ ERROR `Self` is not valid in the self type of an impl block
fn main() {}
diff --git a/src/test/ui/resolve/issue-23305.stderr b/src/test/ui/resolve/issue-23305.stderr
index 20aeb7b99..aad1b583a 100644
--- a/src/test/ui/resolve/issue-23305.stderr
+++ b/src/test/ui/resolve/issue-23305.stderr
@@ -1,22 +1,10 @@
-error[E0391]: cycle detected when computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:21>`
+error: `Self` is not valid in the self type of an impl block
--> $DIR/issue-23305.rs:5:16
|
LL | impl dyn ToNbt<Self> {}
| ^^^^
|
- = note: ...which immediately requires computing type of `<impl at $DIR/issue-23305.rs:5:1: 5:21>` again
-note: cycle used when collecting item types in top-level module
- --> $DIR/issue-23305.rs:1:1
- |
-LL | / pub trait ToNbt<T> {
-LL | | fn new(val: T) -> Self;
-LL | | }
-LL | |
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
+ = note: replace `Self` with a different type
error: aborting due to previous error
-For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr
index b8d528efc..e7c53ff44 100644
--- a/src/test/ui/resolve/issue-2356.stderr
+++ b/src/test/ui/resolve/issue-2356.stderr
@@ -1,15 +1,3 @@
-error[E0425]: cannot find function `shave` in this scope
- --> $DIR/issue-2356.rs:17:5
- |
-LL | shave();
- | ^^^^^ not found in this scope
-
-error[E0425]: cannot find function `clone` in this scope
- --> $DIR/issue-2356.rs:24:5
- |
-LL | clone();
- | ^^^^^ help: you might have meant to call the method: `self.clone`
-
error[E0425]: cannot find function `default` in this scope
--> $DIR/issue-2356.rs:31:5
|
@@ -31,6 +19,51 @@ error[E0425]: cannot find value `whiskers` in this scope
LL | whiskers -= other;
| ^^^^^^^^ a field by this name exists in `Self`
+error[E0424]: expected value, found module `self`
+ --> $DIR/issue-2356.rs:65:8
+ |
+LL | fn meow() {
+ | ---- this function doesn't have a `self` parameter
+LL | if self.whiskers > 3 {
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+ |
+help: add a `self` receiver parameter to make the associated `fn` a method
+ |
+LL | fn meow(&self) {
+ | +++++
+
+error[E0425]: cannot find value `whiskers` in this scope
+ --> $DIR/issue-2356.rs:79:5
+ |
+LL | whiskers = 0;
+ | ^^^^^^^^ help: you might have meant to use the available field: `self.whiskers`
+
+error[E0425]: cannot find value `whiskers` in this scope
+ --> $DIR/issue-2356.rs:84:5
+ |
+LL | whiskers = 4;
+ | ^^^^^^^^ a field by this name exists in `Self`
+
+error[E0424]: expected value, found module `self`
+ --> $DIR/issue-2356.rs:92:5
+ |
+LL | fn main() {
+ | ---- this function can't have a `self` parameter
+LL | self += 1;
+ | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
+
+error[E0425]: cannot find function `shave` in this scope
+ --> $DIR/issue-2356.rs:17:5
+ |
+LL | shave();
+ | ^^^^^ not found in this scope
+
+error[E0425]: cannot find function `clone` in this scope
+ --> $DIR/issue-2356.rs:24:5
+ |
+LL | clone();
+ | ^^^^^ help: you might have meant to call the method: `self.clone`
+
error[E0425]: cannot find function `shave` in this scope
--> $DIR/issue-2356.rs:41:5
|
@@ -72,19 +105,6 @@ error[E0425]: cannot find function `purr` in this scope
LL | purr();
| ^^^^ not found in this scope
-error[E0424]: expected value, found module `self`
- --> $DIR/issue-2356.rs:65:8
- |
-LL | fn meow() {
- | ---- this function doesn't have a `self` parameter
-LL | if self.whiskers > 3 {
- | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
- |
-help: add a `self` receiver parameter to make the associated `fn` a method
- |
-LL | fn meow(&self) {
- | +++++
-
error[E0425]: cannot find function `grow_older` in this scope
--> $DIR/issue-2356.rs:72:5
|
@@ -102,32 +122,12 @@ error[E0425]: cannot find function `shave` in this scope
LL | shave();
| ^^^^^ not found in this scope
-error[E0425]: cannot find value `whiskers` in this scope
- --> $DIR/issue-2356.rs:79:5
- |
-LL | whiskers = 0;
- | ^^^^^^^^ help: you might have meant to use the available field: `self.whiskers`
-
-error[E0425]: cannot find value `whiskers` in this scope
- --> $DIR/issue-2356.rs:84:5
- |
-LL | whiskers = 4;
- | ^^^^^^^^ a field by this name exists in `Self`
-
error[E0425]: cannot find function `purr_louder` in this scope
--> $DIR/issue-2356.rs:86:5
|
LL | purr_louder();
| ^^^^^^^^^^^ not found in this scope
-error[E0424]: expected value, found module `self`
- --> $DIR/issue-2356.rs:92:5
- |
-LL | fn main() {
- | ---- this function can't have a `self` parameter
-LL | self += 1;
- | ^^^^ `self` value is a keyword only available in methods with a `self` parameter
-
error: aborting due to 17 previous errors
Some errors have detailed explanations: E0424, E0425.
diff --git a/src/test/ui/resolve/issue-42944.stderr b/src/test/ui/resolve/issue-42944.stderr
index cad3ccc4a..0ee9fd391 100644
--- a/src/test/ui/resolve/issue-42944.stderr
+++ b/src/test/ui/resolve/issue-42944.stderr
@@ -1,15 +1,3 @@
-error[E0423]: cannot initialize a tuple struct which contains private fields
- --> $DIR/issue-42944.rs:9:9
- |
-LL | Bx(());
- | ^^
- |
-note: constructor is not visible here due to private fields
- --> $DIR/issue-42944.rs:2:19
- |
-LL | pub struct Bx(());
- | ^^ private field
-
error[E0425]: cannot find function, tuple struct or tuple variant `Bx` in this scope
--> $DIR/issue-42944.rs:16:9
|
@@ -22,6 +10,18 @@ note: tuple struct `foo::Bx` exists but is inaccessible
LL | pub struct Bx(());
| ^^^^^^^^^^^^^^^^^^ not accessible
+error[E0423]: cannot initialize a tuple struct which contains private fields
+ --> $DIR/issue-42944.rs:9:9
+ |
+LL | Bx(());
+ | ^^
+ |
+note: constructor is not visible here due to private fields
+ --> $DIR/issue-42944.rs:2:19
+ |
+LL | pub struct Bx(());
+ | ^^ private field
+
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0423, E0425.
diff --git a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
index 55c3b66f1..1354abb4f 100644
--- a/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
+++ b/src/test/ui/resolve/issue-70736-async-fn-no-body-def-collector.stderr
@@ -33,7 +33,7 @@ LL | async fn associated();
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error[E0706]: functions in traits cannot be declared `async`
--> $DIR/issue-70736-async-fn-no-body-def-collector.rs:15:5
@@ -46,7 +46,7 @@ LL | async fn associated();
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
error: aborting due to 5 previous errors
diff --git a/src/test/ui/resolve/issue-73427.stderr b/src/test/ui/resolve/issue-73427.stderr
index a2ca46f0c..d31c5e477 100644
--- a/src/test/ui/resolve/issue-73427.stderr
+++ b/src/test/ui/resolve/issue-73427.stderr
@@ -124,13 +124,13 @@ LL | use std::f32::consts::E;
LL | use std::f64::consts::E;
|
-error[E0423]: expected function, tuple struct or tuple variant, found enum `A`
- --> $DIR/issue-73427.rs:46:13
+error[E0532]: expected tuple struct or tuple variant, found enum `A`
+ --> $DIR/issue-73427.rs:48:12
|
-LL | let x = A(3);
- | ^
+LL | if let A(3) = x { }
+ | ^
|
- = help: you might have meant to construct one of the enum's non-tuple variants
+ = help: you might have meant to match against one of the enum's non-tuple variants
note: the enum is defined here
--> $DIR/issue-73427.rs:1:1
|
@@ -142,20 +142,20 @@ LL | | Tuple(),
LL | | Unit,
LL | | }
| |_^
-help: try to construct one of the enum's variants
+help: try to match against one of the enum's variants
|
-LL | let x = A::Tuple(3);
- | ~~~~~~~~
-LL | let x = A::TupleWithFields(3);
- | ~~~~~~~~~~~~~~~~~~
+LL | if let A::Tuple(3) = x { }
+ | ~~~~~~~~
+LL | if let A::TupleWithFields(3) = x { }
+ | ~~~~~~~~~~~~~~~~~~
-error[E0532]: expected tuple struct or tuple variant, found enum `A`
- --> $DIR/issue-73427.rs:48:12
+error[E0423]: expected function, tuple struct or tuple variant, found enum `A`
+ --> $DIR/issue-73427.rs:46:13
|
-LL | if let A(3) = x { }
- | ^
+LL | let x = A(3);
+ | ^
|
- = help: you might have meant to match against one of the enum's non-tuple variants
+ = help: you might have meant to construct one of the enum's non-tuple variants
note: the enum is defined here
--> $DIR/issue-73427.rs:1:1
|
@@ -167,12 +167,12 @@ LL | | Tuple(),
LL | | Unit,
LL | | }
| |_^
-help: try to match against one of the enum's variants
+help: try to construct one of the enum's variants
|
-LL | if let A::Tuple(3) = x { }
- | ~~~~~~~~
-LL | if let A::TupleWithFields(3) = x { }
- | ~~~~~~~~~~~~~~~~~~
+LL | let x = A::Tuple(3);
+ | ~~~~~~~~
+LL | let x = A::TupleWithFields(3);
+ | ~~~~~~~~~~~~~~~~~~
error: aborting due to 7 previous errors
diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr
index 249a7e53d..9a2d61ea4 100644
--- a/src/test/ui/resolve/levenshtein.stderr
+++ b/src/test/ui/resolve/levenshtein.stderr
@@ -39,15 +39,6 @@ LL | const MAX_ITEM: usize = 10;
LL | let v = [0u32; MAXITEM]; // Misspelled constant name.
| ^^^^^^^ help: a constant with a similar name exists: `MAX_ITEM`
-error[E0425]: cannot find function `foobar` in this scope
- --> $DIR/levenshtein.rs:26:5
- |
-LL | fn foo_bar() {}
- | ------------ similarly named function `foo_bar` defined here
-...
-LL | foobar(); // Misspelled function name.
- | ^^^^^^ help: a function with a similar name exists: `foo_bar`
-
error[E0412]: cannot find type `first` in module `m`
--> $DIR/levenshtein.rs:28:15
|
@@ -66,6 +57,15 @@ LL | pub struct Second;
LL | let b: m::first = m::second; // Misspelled item in module.
| ^^^^^^ help: a unit struct with a similar name exists (notice the capitalization): `Second`
+error[E0425]: cannot find function `foobar` in this scope
+ --> $DIR/levenshtein.rs:26:5
+ |
+LL | fn foo_bar() {}
+ | ------------ similarly named function `foo_bar` defined here
+...
+LL | foobar(); // Misspelled function name.
+ | ^^^^^^ help: a function with a similar name exists: `foo_bar`
+
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0412, E0425.
diff --git a/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
new file mode 100644
index 000000000..fba4ffa1c
--- /dev/null
+++ b/src/test/ui/resolve/name-collision-in-trait-fn-sig.rs
@@ -0,0 +1,11 @@
+// check-pass
+// This is currently stable behavior, which was almost accidentally made an
+// error in #102161 since there is no test exercising it. I am not sure if
+// this _should_ be the desired behavior, but at least we should know if it
+// changes.
+
+fn main() {}
+
+trait Foo {
+ fn fn_with_type_named_same_as_local_in_param(b: i32, b: i32);
+}
diff --git a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
index af9f4612a..eb26cd9ca 100644
--- a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
+++ b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
@@ -1,11 +1,16 @@
error[E0574]: expected struct, variant or union type, found type parameter `Baz`
--> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
|
-LL | impl<Baz> Foo<Baz> for Bar {
- | --- found this type parameter
+LL | / struct Baz {
+LL | | num: usize,
+LL | | }
+ | |_- you might have meant to refer to this struct
+LL |
+LL | impl<Baz> Foo<Baz> for Bar {
+ | --- found this type parameter
...
-LL | Baz { num } => num,
- | ^^^ not a struct, variant or union type
+LL | Baz { num } => num,
+ | ^^^ not a struct, variant or union type
error: aborting due to previous error
diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr
index a369dc6db..82a4211f0 100644
--- a/src/test/ui/resolve/privacy-enum-ctor.stderr
+++ b/src/test/ui/resolve/privacy-enum-ctor.stderr
@@ -327,7 +327,7 @@ LL | let _: Z = Z::Fn;
|
= note: expected enum `Z`
found fn item `fn(u8) -> Z {Z::Fn}`
-help: use parentheses to instantiate this tuple variant
+help: use parentheses to construct this tuple variant
|
LL | let _: Z = Z::Fn(/* u8 */);
| ++++++++++
@@ -362,7 +362,7 @@ LL | let _: E = m::E::Fn;
|
= note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}`
-help: use parentheses to instantiate this tuple variant
+help: use parentheses to construct this tuple variant
|
LL | let _: E = m::E::Fn(/* u8 */);
| ++++++++++
@@ -397,7 +397,7 @@ LL | let _: E = E::Fn;
|
= note: expected enum `E`
found fn item `fn(u8) -> E {E::Fn}`
-help: use parentheses to instantiate this tuple variant
+help: use parentheses to construct this tuple variant
|
LL | let _: E = E::Fn(/* u8 */);
| ++++++++++
diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
index b6acaeb8c..8def9aa20 100644
--- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr
+++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr
@@ -50,7 +50,7 @@ error[E0425]: cannot find value `method` in this scope
--> $DIR/resolve-assoc-suggestions.rs:34:9
|
LL | method;
- | ^^^^^^ help: you might have meant to call the method: `self.method`
+ | ^^^^^^ help: you might have meant to refer to the method: `self.method`
error: aborting due to 9 previous errors
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
index bc69ddd8f..1e7ab48ef 100644
--- a/src/test/ui/resolve/resolve-hint-macro.stderr
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -14,17 +14,6 @@ LL | assert_eq { 1, 1 };
| |
| while parsing this struct
-error[E0423]: expected function, found macro `assert_eq`
- --> $DIR/resolve-hint-macro.rs:3:5
- |
-LL | assert_eq(1, 1);
- | ^^^^^^^^^ not a function
- |
-help: use `!` to invoke the macro
- |
-LL | assert_eq!(1, 1);
- | +
-
error[E0574]: expected struct, variant or union type, found macro `assert_eq`
--> $DIR/resolve-hint-macro.rs:5:5
|
@@ -47,6 +36,17 @@ help: use `!` to invoke the macro
LL | assert![true];
| +
+error[E0423]: expected function, found macro `assert_eq`
+ --> $DIR/resolve-hint-macro.rs:3:5
+ |
+LL | assert_eq(1, 1);
+ | ^^^^^^^^^ not a function
+ |
+help: use `!` to invoke the macro
+ |
+LL | assert_eq!(1, 1);
+ | +
+
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0423, E0574.
diff --git a/src/test/ui/resolve/resolve-self-in-impl.rs b/src/test/ui/resolve/resolve-self-in-impl.rs
index 024fdc51e..d0872d1b7 100644
--- a/src/test/ui/resolve/resolve-self-in-impl.rs
+++ b/src/test/ui/resolve/resolve-self-in-impl.rs
@@ -11,10 +11,11 @@ impl Tr for S where Self: Copy {} // OK
impl Tr for S where S<Self>: Copy {} // OK
impl Tr for S where Self::A: Copy {} // OK
-impl Tr for Self {} //~ ERROR cycle detected
-impl Tr for S<Self> {} //~ ERROR cycle detected
-impl Self {} //~ ERROR cycle detected
-impl S<Self> {} //~ ERROR cycle detected
+impl Tr for Self {} //~ ERROR `Self` is not valid in the self type of an impl block
+impl Tr for S<Self> {} //~ ERROR `Self` is not valid in the self type of an impl block
+impl Self {} //~ ERROR `Self` is not valid in the self type of an impl block
+impl S<Self> {} //~ ERROR `Self` is not valid in the self type of an impl block
+impl (Self, Self) {} //~ ERROR `Self` is not valid in the self type of an impl block
impl Tr<Self::A> for S {} //~ ERROR cycle detected
fn main() {}
diff --git a/src/test/ui/resolve/resolve-self-in-impl.stderr b/src/test/ui/resolve/resolve-self-in-impl.stderr
index aa99c1a33..9f9ed6889 100644
--- a/src/test/ui/resolve/resolve-self-in-impl.stderr
+++ b/src/test/ui/resolve/resolve-self-in-impl.stderr
@@ -1,86 +1,50 @@
-error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:17>`
+error: `Self` is not valid in the self type of an impl block
--> $DIR/resolve-self-in-impl.rs:14:13
|
LL | impl Tr for Self {}
| ^^^^
|
- = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:14:1: 14:17>` again
-note: cycle used when collecting item types in top-level module
- --> $DIR/resolve-self-in-impl.rs:1:1
- |
-LL | / #![feature(associated_type_defaults)]
-LL | |
-LL | | struct S<T = u8>(T);
-LL | | trait Tr<T = u8> {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
+ = note: replace `Self` with a different type
-error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:20>`
+error: `Self` is not valid in the self type of an impl block
--> $DIR/resolve-self-in-impl.rs:15:15
|
LL | impl Tr for S<Self> {}
| ^^^^
|
- = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:15:1: 15:20>` again
-note: cycle used when collecting item types in top-level module
- --> $DIR/resolve-self-in-impl.rs:1:1
- |
-LL | / #![feature(associated_type_defaults)]
-LL | |
-LL | | struct S<T = u8>(T);
-LL | | trait Tr<T = u8> {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
+ = note: replace `Self` with a different type
-error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:10>`
+error: `Self` is not valid in the self type of an impl block
--> $DIR/resolve-self-in-impl.rs:16:6
|
LL | impl Self {}
| ^^^^
|
- = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:16:1: 16:10>` again
-note: cycle used when collecting item types in top-level module
- --> $DIR/resolve-self-in-impl.rs:1:1
- |
-LL | / #![feature(associated_type_defaults)]
-LL | |
-LL | | struct S<T = u8>(T);
-LL | | trait Tr<T = u8> {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
+ = note: replace `Self` with a different type
-error[E0391]: cycle detected when computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:13>`
+error: `Self` is not valid in the self type of an impl block
--> $DIR/resolve-self-in-impl.rs:17:8
|
LL | impl S<Self> {}
| ^^^^
|
- = note: ...which immediately requires computing type of `<impl at $DIR/resolve-self-in-impl.rs:17:1: 17:13>` again
-note: cycle used when collecting item types in top-level module
- --> $DIR/resolve-self-in-impl.rs:1:1
+ = note: replace `Self` with a different type
+
+error: `Self` is not valid in the self type of an impl block
+ --> $DIR/resolve-self-in-impl.rs:18:7
|
-LL | / #![feature(associated_type_defaults)]
-LL | |
-LL | | struct S<T = u8>(T);
-LL | | trait Tr<T = u8> {
-... |
-LL | |
-LL | | fn main() {}
- | |____________^
+LL | impl (Self, Self) {}
+ | ^^^^ ^^^^
+ |
+ = note: replace `Self` with a different type
-error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:23>`
- --> $DIR/resolve-self-in-impl.rs:18:1
+error[E0391]: cycle detected when computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>`
+ --> $DIR/resolve-self-in-impl.rs:19:1
|
LL | impl Tr<Self::A> for S {}
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:18:1: 18:23>` again
+ = note: ...which immediately requires computing trait implemented by `<impl at $DIR/resolve-self-in-impl.rs:19:1: 19:23>` again
note: cycle used when collecting item types in top-level module
--> $DIR/resolve-self-in-impl.rs:1:1
|
@@ -93,6 +57,6 @@ LL | |
LL | | fn main() {}
| |____________^
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/resolve/resolve-speculative-adjustment.stderr b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
index 1c34af6d0..be11a7ebe 100644
--- a/src/test/ui/resolve/resolve-speculative-adjustment.stderr
+++ b/src/test/ui/resolve/resolve-speculative-adjustment.stderr
@@ -4,12 +4,6 @@ error[E0425]: cannot find value `field` in this scope
LL | field;
| ^^^^^ not found in this scope
-error[E0425]: cannot find function `method` in this scope
- --> $DIR/resolve-speculative-adjustment.rs:19:13
- |
-LL | method();
- | ^^^^^^ not found in this scope
-
error[E0425]: cannot find value `field` in this scope
--> $DIR/resolve-speculative-adjustment.rs:23:9
|
@@ -22,6 +16,12 @@ error[E0425]: cannot find function `method` in this scope
LL | method();
| ^^^^^^ help: you might have meant to call the method: `self.method`
+error[E0425]: cannot find function `method` in this scope
+ --> $DIR/resolve-speculative-adjustment.rs:19:13
+ |
+LL | method();
+ | ^^^^^^ not found in this scope
+
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/resolve/tuple-struct-alias.stderr b/src/test/ui/resolve/tuple-struct-alias.stderr
index 5a7873301..a739ea43e 100644
--- a/src/test/ui/resolve/tuple-struct-alias.stderr
+++ b/src/test/ui/resolve/tuple-struct-alias.stderr
@@ -1,22 +1,22 @@
-error[E0423]: expected function, tuple struct or tuple variant, found type alias `A`
- --> $DIR/tuple-struct-alias.rs:5:13
+error[E0532]: expected tuple struct or tuple variant, found type alias `A`
+ --> $DIR/tuple-struct-alias.rs:7:9
|
LL | struct S(u8, u16);
| ------------------ similarly named tuple struct `S` defined here
...
-LL | let s = A(0, 1);
- | ^ help: a tuple struct with a similar name exists: `S`
+LL | A(..) => {}
+ | ^ help: a tuple struct with a similar name exists: `S`
|
= note: can't use a type alias as a constructor
-error[E0532]: expected tuple struct or tuple variant, found type alias `A`
- --> $DIR/tuple-struct-alias.rs:7:9
+error[E0423]: expected function, tuple struct or tuple variant, found type alias `A`
+ --> $DIR/tuple-struct-alias.rs:5:13
|
LL | struct S(u8, u16);
| ------------------ similarly named tuple struct `S` defined here
...
-LL | A(..) => {}
- | ^ help: a tuple struct with a similar name exists: `S`
+LL | let s = A(0, 1);
+ | ^ help: a tuple struct with a similar name exists: `S`
|
= note: can't use a type alias as a constructor
diff --git a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr
index 0b0a37f24..f32e0404e 100644
--- a/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr
+++ b/src/test/ui/resolve/typo-suggestion-for-variable-with-name-similar-to-struct-field.stderr
@@ -31,24 +31,6 @@ help: a local variable with a similar name exists
LL | println!("{cofig}");
| ~~~~~
-error[E0425]: cannot find function `baz` in this scope
- --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:31:9
- |
-LL | baz();
- | ^^^
-...
-LL | fn ba() {}
- | ------- similarly named function `ba` defined here
- |
-help: you might have meant to call the method
- |
-LL | self.baz();
- | ~~~~~~~~
-help: a function with a similar name exists
- |
-LL | ba();
- | ~~
-
error[E0425]: cannot find value `bah` in this scope
--> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:33:9
|
@@ -58,7 +40,7 @@ LL | bah;
LL | fn ba() {}
| ------- similarly named function `ba` defined here
|
-help: you might have meant to call the associated function
+help: you might have meant to refer to the associated function
|
LL | Self::bah;
| ~~~~~~~~~
@@ -103,6 +85,24 @@ help: a type alias with a similar name exists
LL | let foo: Bar = "".to_string();
| ~~~
+error[E0425]: cannot find function `baz` in this scope
+ --> $DIR/typo-suggestion-for-variable-with-name-similar-to-struct-field.rs:31:9
+ |
+LL | baz();
+ | ^^^
+...
+LL | fn ba() {}
+ | ------- similarly named function `ba` defined here
+ |
+help: you might have meant to call the method
+ |
+LL | self.baz();
+ | ~~~~~~~~
+help: a function with a similar name exists
+ |
+LL | ba();
+ | ~~
+
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0412, E0425.
diff --git a/src/test/ui/issues/issue-64620.rs b/src/test/ui/return/issue-64620.rs
index a62e5bf8d..a62e5bf8d 100644
--- a/src/test/ui/issues/issue-64620.rs
+++ b/src/test/ui/return/issue-64620.rs
diff --git a/src/test/ui/issues/issue-64620.stderr b/src/test/ui/return/issue-64620.stderr
index f40ac4de3..f40ac4de3 100644
--- a/src/test/ui/issues/issue-64620.stderr
+++ b/src/test/ui/return/issue-64620.stderr
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
index 659a98126..10dd635ff 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
@@ -4,13 +4,13 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
LL | WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
warning: 1 warning emitted
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
index c8c365105..66aecbc4f 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
@@ -4,13 +4,13 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
LL | WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
warning: 1 warning emitted
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
index 8abbd5d34..ee92954a6 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
@@ -4,13 +4,13 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
LL | WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
| ^^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
warning: 1 warning emitted
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
index 3a716d54f..f0c492d6a 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
@@ -4,13 +4,13 @@ warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be a
LL | WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
| ^^^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
|
LL | #![warn(indirect_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
warning: 1 warning emitted
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
index a50093a5b..955ab4b54 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
@@ -4,13 +4,13 @@ warning: to use a constant of type `B` in a pattern, `B` must be annotated with
LL | RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
| ^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
note: the lint level is defined here
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
|
LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq, Eq)]`
--> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
index 8cf87cc85..d6afc0255 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -4,13 +4,13 @@ warning: function pointers and unsized pointers in patterns behave unpredictably
LL | B(TEST) => println!("matched"),
| ^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
note: the lint level is defined here
--> $DIR/issue-63479-match-fnptr.rs:8:9
|
LL | #![warn(pointer_structural_match)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
warning: 1 warning emitted
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
index 4e2961e5e..f37255d08 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/issue-6804.stderr
@@ -4,13 +4,13 @@ error: floating-point types cannot be used in patterns
LL | NAN => {},
| ^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
note: the lint level is defined here
--> $DIR/issue-6804.rs:4:9
|
LL | #![deny(illegal_floating_point_literal_pattern)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
error: floating-point types cannot be used in patterns
--> $DIR/issue-6804.rs:17:10
diff --git a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
index df4809dab..616ed9e48 100644
--- a/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
+++ b/src/test/ui/rfc-1445-restrict-constants-in-patterns/match-forbidden-without-eq.stderr
@@ -10,9 +10,9 @@ warning: floating-point types cannot be used in patterns
LL | f32::INFINITY => { }
| ^^^^^^^^^^^^^
|
- = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #41620 <https://github.com/rust-lang/rust/issues/41620>
+ = note: `#[warn(illegal_floating_point_literal_pattern)]` on by default
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/rfc-1937-termination-trait/issue-103052-1.rs b/src/test/ui/rfc-1937-termination-trait/issue-103052-1.rs
new file mode 100644
index 000000000..a75c91cc9
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/issue-103052-1.rs
@@ -0,0 +1,11 @@
+// Check that we don't blindly emit a diagnostic claiming that "`main` has an invalid return type"
+// if we encounter a type that doesn't implement `std::process::Termination` and is not actually
+// the return type of the program entry `main`.
+
+fn receive(_: impl std::process::Termination) {}
+
+struct Something;
+
+fn main() {
+ receive(Something); //~ ERROR the trait bound `Something: Termination` is not satisfied
+}
diff --git a/src/test/ui/rfc-1937-termination-trait/issue-103052-1.stderr b/src/test/ui/rfc-1937-termination-trait/issue-103052-1.stderr
new file mode 100644
index 000000000..409dede1a
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/issue-103052-1.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-1.rs:10:13
+ |
+LL | receive(Something);
+ | ------- ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `receive`
+ --> $DIR/issue-103052-1.rs:5:20
+ |
+LL | fn receive(_: impl std::process::Termination) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `receive`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/issue-103052-2.rs b/src/test/ui/rfc-1937-termination-trait/issue-103052-2.rs
new file mode 100644
index 000000000..fa9182b6d
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/issue-103052-2.rs
@@ -0,0 +1,18 @@
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+mod child {
+ trait Main {
+ fn main() -> impl std::process::Termination;
+ }
+
+ struct Something;
+
+ impl Main for () {
+ fn main() -> Something { //~ ERROR the trait bound `Something: Termination` is not satisfied
+ Something
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-1937-termination-trait/issue-103052-2.stderr b/src/test/ui/rfc-1937-termination-trait/issue-103052-2.stderr
new file mode 100644
index 000000000..a700c72ea
--- /dev/null
+++ b/src/test/ui/rfc-1937-termination-trait/issue-103052-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+ --> $DIR/issue-103052-2.rs:12:22
+ |
+LL | fn main() -> Something {
+ | ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+ |
+note: required by a bound in `Main::main::{opaque#0}`
+ --> $DIR/issue-103052-2.rs:6:27
+ |
+LL | fn main() -> impl std::process::Termination;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
index cd57d9bca..43888cece 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
@@ -2,7 +2,6 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(test)]
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 7d81de438..6ee323146 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -1,4 +1,4 @@
-error[E0277]: `main` has invalid return type `f32`
+error[E0277]: the trait bound `f32: Termination` is not satisfied
--> $DIR/termination-trait-test-wrong-type.rs:6:1
|
LL | #[test]
@@ -6,14 +6,13 @@ LL | #[test]
LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
LL | | "0".parse()
LL | | }
- | |_^ `main` can only return types that implement `Termination`
+ | |_^ the trait `Termination` is not implemented for `f32`
|
- = help: the trait `Termination` is not implemented for `f32`
= note: required for `Result<f32, ParseFloatError>` to implement `Termination`
note: required by a bound in `assert_test_result`
--> $SRC_DIR/test/src/lib.rs:LL:COL
|
-LL | pub fn assert_test_result<T: Termination>(result: T) {
+LL | pub fn assert_test_result<T: Termination>(result: T) -> Result<(), String> {
| ^^^^^^^^^^^ required by this bound in `assert_test_result`
= note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
index 8a18ebc16..43c8e1015 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr
@@ -4,12 +4,12 @@ error: `extern` block uses type `NonExhaustiveEnum`, which is not FFI-safe
LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum);
| ^^^^^^^^^^^^^^^^^ not FFI-safe
|
+ = note: this enum is non-exhaustive
note: the lint level is defined here
--> $DIR/extern_crate_improper.rs:2:9
|
LL | #![deny(improper_ctypes)]
| ^^^^^^^^^^^^^^^
- = note: this enum is non-exhaustive
error: `extern` block uses type `NormalStruct`, which is not FFI-safe
--> $DIR/extern_crate_improper.rs:14:44
diff --git a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
index 4b9f8564d..996bd4a12 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -4,13 +4,13 @@ warning: some fields are not explicitly listed
LL | VariantNonExhaustive::Bar { x, .. } => {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `y` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:99:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `VariantNonExhaustive` and the `non_exhaustive_omitted_patterns` attribute was found
warning: some fields are not explicitly listed
--> $DIR/omitted-patterns.rs:107:9
@@ -18,13 +18,13 @@ warning: some fields are not explicitly listed
LL | let FunctionalRecord { first_field, second_field, .. } = FunctionalRecord::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `third_field` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:106:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `FunctionalRecord` and the `non_exhaustive_omitted_patterns` attribute was found
warning: some fields are not explicitly listed
--> $DIR/omitted-patterns.rs:115:29
@@ -32,13 +32,13 @@ warning: some fields are not explicitly listed
LL | let NestedStruct { bar: NormalStruct { first_field, .. }, .. } = NestedStruct::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `second_field` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:114:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `NormalStruct` and the `non_exhaustive_omitted_patterns` attribute was found
warning: some fields are not explicitly listed
--> $DIR/omitted-patterns.rs:115:9
@@ -55,13 +55,13 @@ warning: some fields are not explicitly listed
LL | let OnlyUnstableStruct { unstable, .. } = OnlyUnstableStruct::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable2` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:172:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `OnlyUnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
warning: some fields are not explicitly listed
--> $DIR/omitted-patterns.rs:181:9
@@ -69,13 +69,13 @@ warning: some fields are not explicitly listed
LL | let UnstableStruct { stable, stable2, .. } = UnstableStruct::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `unstable` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:180:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:58:9
@@ -83,13 +83,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `NonExhaustiveEnum::Struct { .. }` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:57:16
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:65:9
@@ -97,13 +97,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `NonExhaustiveEnum::Tuple(_)` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:64:16
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:75:9
@@ -111,13 +111,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `NonExhaustiveEnum::Unit` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:74:16
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:92:32
@@ -125,13 +125,13 @@ error: some variants are not matched explicitly
LL | NestedNonExhaustive::A(_) => {}
| ^ patterns `NonExhaustiveEnum::Tuple(_)` and `NonExhaustiveEnum::Struct { .. }` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:89:12
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `NonExhaustiveEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:94:9
@@ -148,13 +148,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `NonExhaustiveSingleVariant::A(_)` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:130:12
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `NonExhaustiveSingleVariant` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:144:9
@@ -162,13 +162,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `UnstableEnum::Unstable` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:143:16
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/omitted-patterns.rs:168:9
@@ -176,13 +176,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `OnlyUnstableEnum::Unstable2` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/omitted-patterns.rs:165:12
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `OnlyUnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: aborting due to 8 previous errors; 6 warnings emitted
diff --git a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
index 533e8abf2..f38368590 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/stable-omitted-patterns.stderr
@@ -4,13 +4,13 @@ warning: some fields are not explicitly listed
LL | let UnstableStruct { stable, .. } = UnstableStruct::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `stable2` not listed
|
+ = help: ensure that all fields are mentioned explicitly by adding the suggested fields
+ = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/stable-omitted-patterns.rs:38:12
|
LL | #[warn(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all fields are mentioned explicitly by adding the suggested fields
- = note: the pattern is of type `UnstableStruct` and the `non_exhaustive_omitted_patterns` attribute was found
error: some variants are not matched explicitly
--> $DIR/stable-omitted-patterns.rs:23:9
@@ -18,13 +18,13 @@ error: some variants are not matched explicitly
LL | _ => {}
| ^ pattern `UnstableEnum::Stable2` not covered
|
+ = help: ensure that all variants are matched explicitly by adding the suggested match arms
+ = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
note: the lint level is defined here
--> $DIR/stable-omitted-patterns.rs:22:16
|
LL | #[deny(non_exhaustive_omitted_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: ensure that all variants are matched explicitly by adding the suggested match arms
- = note: the matched value is of type `UnstableEnum` and the `non_exhaustive_omitted_patterns` attribute was found
error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
index 2b34d0711..2cb9ba0d1 100644
--- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -1,9 +1,3 @@
-error[E0423]: cannot initialize a tuple struct which contains private fields
- --> $DIR/struct.rs:20:14
- |
-LL | let ts = TupleStruct(640, 480);
- | ^^^^^^^^^^^
-
error[E0423]: expected value, found struct `UnitStruct`
--> $DIR/struct.rs:29:14
|
@@ -68,6 +62,12 @@ help: add `..` at the end of the field list to ignore all other fields
LL | let NormalStruct { first_field, second_field , .. } = ns;
| ~~~~~~
+error[E0423]: cannot initialize a tuple struct which contains private fields
+ --> $DIR/struct.rs:20:14
+ |
+LL | let ts = TupleStruct(640, 480);
+ | ^^^^^^^^^^^
+
error[E0638]: `..` required with struct marked as non-exhaustive
--> $DIR/struct.rs:26:9
|
diff --git a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
index b067994a5..f11456250 100644
--- a/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
+++ b/src/test/ui/rfc-2091-track-caller/std-panic-locations.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// revisions: default mir-opt
//[mir-opt] compile-flags: -Zmir-opt-level=4
diff --git a/src/test/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr b/src/test/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr
index a66330ccc..761089cd3 100644
--- a/src/test/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr
+++ b/src/test/ui/rfc-2126-extern-absolute-paths/not-allowed.stderr
@@ -3,6 +3,13 @@ error[E0432]: unresolved import `alloc`
|
LL | use alloc;
| ^^^^^ no external crate `alloc`
+ |
+help: consider importing one of these items instead
+ |
+LL | use core::alloc;
+ | ~~~~~~~~~~~~
+LL | use std::alloc;
+ | ~~~~~~~~~~~
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2294-if-let-guard/warns.stderr b/src/test/ui/rfc-2294-if-let-guard/warns.stderr
index cf64513f9..75f22ac8d 100644
--- a/src/test/ui/rfc-2294-if-let-guard/warns.stderr
+++ b/src/test/ui/rfc-2294-if-let-guard/warns.stderr
@@ -4,13 +4,13 @@ error: irrefutable `if let` guard pattern
LL | Some(x) if let () = x => {}
| ^^
|
+ = note: this pattern will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
note: the lint level is defined here
--> $DIR/warns.rs:3:8
|
LL | #[deny(irrefutable_let_patterns)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this pattern will always match, so the guard is useless
- = help: consider removing the guard and adding a `let` inside the match arm
error: unreachable pattern
--> $DIR/warns.rs:15:25
diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
index bc06fde49..91c001151 100644
--- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr
@@ -1510,7 +1510,7 @@ LL | if x = let 0 = 0 {}
help: you might have meant to compare for equality
|
LL | if x == let 0 = 0 {}
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:157:8
@@ -1704,7 +1704,7 @@ LL | while x = let 0 = 0 {}
help: you might have meant to compare for equality
|
LL | while x == let 0 = 0 {}
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/disallowed-positions.rs:249:11
diff --git a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
index d1d5288ae..be4a52315 100644
--- a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
+++ b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr
@@ -4,13 +4,13 @@ error: leading irrefutable pattern in let chain
LL | if let first = &opt && let Some(ref second) = first && let None = second.start {}
| ^^^^^^^^^^^^^^^^
|
+ = note: this pattern will always match
+ = help: consider moving it outside of the construct
note: the lint level is defined here
--> $DIR/irrefutable-lets.rs:6:30
|
LL | #![cfg_attr(disallowed, deny(irrefutable_let_patterns))]
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: this pattern will always match
- = help: consider moving it outside of the construct
error: irrefutable `if let` patterns
--> $DIR/irrefutable-lets.rs:19:8
@@ -75,26 +75,26 @@ LL | if let first = &opt && let None = Some(1) {}
= note: this pattern will always match
= help: consider moving it outside of the construct
-error: irrefutable `let` patterns
+error: irrefutable `if let` guard patterns
--> $DIR/irrefutable-lets.rs:44:28
|
LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: these patterns will always match, so the `let` is useless
- = help: consider removing `let`
+ = note: these patterns will always match, so the guard is useless
+ = help: consider removing the guard and adding a `let` inside the match arm
-error: leading irrefutable pattern in let chain
- --> $DIR/irrefutable-lets.rs:50:28
+error: trailing irrefutable patterns in let chain
+ --> $DIR/irrefutable-lets.rs:59:16
|
-LL | Some(ref first) if let Range { start: local_start, end: _ } = first
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | && let v = local_end && let w = v => {},
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: this pattern will always match
- = help: consider moving it outside of the construct
+ = note: these patterns will always match
+ = help: consider moving them into the body
error: irrefutable `while let` patterns
- --> $DIR/irrefutable-lets.rs:59:11
+ --> $DIR/irrefutable-lets.rs:68:11
|
LL | while let first = &opt && let (a, b) = (1, 2) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -103,7 +103,7 @@ LL | while let first = &opt && let (a, b) = (1, 2) {}
= help: consider instead using a `loop { ... }` with a `let` inside it
error: trailing irrefutable patterns in let chain
- --> $DIR/irrefutable-lets.rs:62:40
+ --> $DIR/irrefutable-lets.rs:71:40
|
LL | while let Some(ref first) = opt && let second = first && let _third = second {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs
index 3d1626e8f..9afb6853b 100644
--- a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs
+++ b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs
@@ -42,18 +42,27 @@ fn main() {
match opt {
Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {},
- //[disallowed]~^ ERROR irrefutable `let` patterns
+ //[disallowed]~^ ERROR irrefutable `if let` guard patterns
_ => {}
}
+ // No error about leading irrefutable patterns: the expr on the rhs might
+ // use the bindings created by the match.
match opt {
Some(ref first) if let Range { start: local_start, end: _ } = first
- //[disallowed]~^ ERROR leading irrefutable pattern in let chain
&& let None = local_start => {},
_ => {}
}
- // No error, despite the prefix being irrefutable
+ match opt {
+ Some(ref first) if let Range { start: Some(_), end: local_end } = first
+ && let v = local_end && let w = v => {},
+ //[disallowed]~^ ERROR trailing irrefutable patterns in let chain
+ _ => {}
+ }
+
+ // No error, despite the prefix being irrefutable: moving out could change the behaviour,
+ // due to possible side effects of the operation.
while let first = &opt && let Some(ref second) = first && let None = second.start {}
while let first = &opt && let (a, b) = (1, 2) {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
new file mode 100644
index 000000000..780a510c5
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs
@@ -0,0 +1,14 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+ type Assoc: ~const Foo;
+ fn foo() {}
+}
+
+const fn foo<T: ~const Foo>() {
+ <T as Foo>::Assoc::foo();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
index 99eacaa83..7d9dae52c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs
@@ -10,6 +10,7 @@ impl std::ops::Add for NonConstAdd {
}
}
+#[const_trait]
trait Foo {
type Bar: ~const std::ops::Add;
}
@@ -19,6 +20,7 @@ impl const Foo for NonConstAdd {
//~^ ERROR: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
}
+#[const_trait]
trait Baz {
type Qux: std::ops::Add;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
index 64501c523..89177b0f1 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -1,24 +1,20 @@
error[E0277]: cannot add `NonConstAdd` to `NonConstAdd` in const contexts
- --> $DIR/assoc-type.rs:18:16
+ --> $DIR/assoc-type.rs:19:16
|
LL | type Bar = NonConstAdd;
| ^^^^^^^^^^^ no implementation for `NonConstAdd + NonConstAdd`
|
= help: the trait `~const Add` is not implemented for `NonConstAdd`
note: the trait `Add` is implemented for `NonConstAdd`, but that implementation is not `const`
- --> $DIR/assoc-type.rs:18:16
+ --> $DIR/assoc-type.rs:19:16
|
LL | type Bar = NonConstAdd;
| ^^^^^^^^^^^
note: required by a bound in `Foo::Bar`
- --> $DIR/assoc-type.rs:14:15
+ --> $DIR/assoc-type.rs:15:15
|
LL | type Bar: ~const std::ops::Add;
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::Bar`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | impl const Foo for NonConstAdd where NonConstAdd: ~const Add {
- | +++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
index 19e900609..589e3f024 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/auxiliary/staged-api.rs
@@ -3,6 +3,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait MyTrait {
#[stable(feature = "rust1", since = "1.0.0")]
fn func();
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
index 24b9235bb..dd9933974 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs
@@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
+#[const_trait]
pub trait Plus {
fn plus(self, rhs: Self) -> Self;
}
@@ -23,7 +24,6 @@ pub const fn add_i32(a: i32, b: i32) -> i32 {
pub const fn add_u32(a: u32, b: u32) -> u32 {
a.plus(b)
//~^ ERROR the trait bound
- //~| ERROR cannot call non-const fn
}
fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
index 1fc9db277..7350909ba 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -1,24 +1,15 @@
error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
- --> $DIR/call-const-trait-method-fail.rs:24:7
+ --> $DIR/call-const-trait-method-fail.rs:25:7
|
LL | a.plus(b)
- | ^^^^^^^ the trait `~const Plus` is not implemented for `u32`
+ | ^^^^ the trait `~const Plus` is not implemented for `u32`
|
note: the trait `Plus` is implemented for `u32`, but that implementation is not `const`
- --> $DIR/call-const-trait-method-fail.rs:24:7
+ --> $DIR/call-const-trait-method-fail.rs:25:7
|
LL | a.plus(b)
- | ^^^^^^^
+ | ^^^^
-error[E0015]: cannot call non-const fn `<u32 as Plus>::plus` in constant functions
- --> $DIR/call-const-trait-method-fail.rs:24:7
- |
-LL | a.plus(b)
- | ^^^^^^^
- |
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
index cf38bc3c9..b64161b6a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs
@@ -21,6 +21,7 @@ impl const PartialEq for Int {
}
}
+#[const_trait]
pub trait Plus {
fn plus(self, rhs: Self) -> Self;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
index 89dc47aad..50c465790 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -1,6 +1,7 @@
// check-pass
#![feature(const_trait_impl)]
+#[const_trait]
trait MyPartialEq {
fn eq(&self, other: &Self) -> bool;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
index 83d395dda..31e6dbdab 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -9,7 +9,6 @@ note: the trait `PartialEq<_>` is implemented for `T`, but that implementation i
|
LL | *t == *t
| ^^
- = help: the trait `PartialEq<&B>` is implemented for `&A`
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
index d3e14a53a..414a8c87d 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -2,13 +2,18 @@
struct S;
-impl PartialEq for S {
+#[const_trait]
+trait Foo {
+ fn eq(&self, _: &Self) -> bool;
+}
+
+impl Foo for S {
fn eq(&self, _: &S) -> bool {
true
}
}
-const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
+const fn equals_self<T: ~const Foo>(t: &T) -> bool {
true
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
index 0a2a5f0f2..706f52343 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -1,26 +1,21 @@
-error[E0277]: can't compare `S` with `S` in const contexts
- --> $DIR/call-generic-method-nonconst.rs:18:34
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
+ --> $DIR/call-generic-method-nonconst.rs:23:34
|
LL | pub const EQ: bool = equals_self(&S);
- | ----------- ^^ no implementation for `S == S`
+ | ----------- ^^ the trait `~const Foo` is not implemented for `S`
| |
| required by a bound introduced by this call
|
- = help: the trait `~const PartialEq` is not implemented for `S`
-note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
- --> $DIR/call-generic-method-nonconst.rs:18:34
+note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
+ --> $DIR/call-generic-method-nonconst.rs:23:34
|
LL | pub const EQ: bool = equals_self(&S);
| ^^
note: required by a bound in `equals_self`
- --> $DIR/call-generic-method-nonconst.rs:11:25
- |
-LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
- | ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
-help: consider annotating `S` with `#[derive(PartialEq)]`
- |
-LL | #[derive(PartialEq)]
+ --> $DIR/call-generic-method-nonconst.rs:16:25
|
+LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
+ | ^^^^^^^^^^ required by this bound in `equals_self`
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
index b3e3dd62b..52984fb6b 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs
@@ -1,6 +1,7 @@
#![feature(const_trait_impl)]
struct S;
+#[const_trait]
trait T {
fn foo();
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
index 9e49785c5..c8783de4c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr
@@ -1,5 +1,5 @@
error[E0015]: cannot call non-const fn `non_const` in constant functions
- --> $DIR/const-check-fns-in-const-impl.rs:11:16
+ --> $DIR/const-check-fns-in-const-impl.rs:12:16
|
LL | fn foo() { non_const() }
| ^^^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index fddc8d37f..c64930db9 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -11,10 +11,6 @@ note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that imp
|
LL | NonConstImpl.a();
| ^^^^^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
- | +++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
index 2295a822f..796c0d388 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -1,5 +1,5 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
- --> $DIR/const-drop-fail.rs:43:5
+ --> $DIR/const-drop-fail.rs:44:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL | NonTrivialDrop,
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+ --> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
- --> $DIR/const-drop-fail.rs:45:5
+ --> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
- --> $DIR/const-drop-fail.rs:45:5
+ --> $DIR/const-drop-fail.rs:46:5
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,39 +40,60 @@ note: required because it appears within the type `ConstImplWithDropGlue`
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+ --> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:47:5
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail.rs:48:47
|
-LL | const _: () = check($exp);
- | ----- required by a bound introduced by this call
-...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
+ | ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ | |
+ | required by a bound introduced by this call
|
-note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
- --> $DIR/const-drop-fail.rs:28:25
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:48:47
|
-LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
- | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: 1 redundant requirement hidden
- = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
|
-LL | const fn check<T: ~const Destruct>(_: T) {}
- | ^^^^^^^^^^^^^^^ required by this bound in `check`
-help: consider borrowing here
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail.rs:48:5
|
-LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | +
-LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | ++++
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:48:5
+ |
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+ --> $DIR/const-drop-fail.rs:55:9
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ | ^^^^^^^^
+ |
+note: the implementor must specify the same requirement
+ --> $DIR/const-drop-fail.rs:53:1
+ |
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
index 001dd430a..d36c7f81c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs
@@ -19,11 +19,12 @@ impl const Drop for ConstImplWithDropGlue {
fn drop(&mut self) {}
}
-trait A { fn a() { println!("A"); } }
+#[const_trait]
+trait A { fn a() { } }
impl A for NonTrivialDrop {}
-struct ConstDropImplWithBounds<T: A>(PhantomData<T>);
+struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
fn drop(&mut self) {
@@ -46,6 +47,16 @@ check_all! {
//~^ ERROR can't drop
ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
//~^ ERROR the trait bound
+ //~| ERROR the trait bound
+}
+
+struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+
+impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+//~^ ERROR `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+ fn drop(&mut self) {
+ T::a();
+ }
}
fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
index 2295a822f..796c0d388 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -1,5 +1,5 @@
error[E0277]: can't drop `NonTrivialDrop` in const contexts
- --> $DIR/const-drop-fail.rs:43:5
+ --> $DIR/const-drop-fail.rs:44:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL | NonTrivialDrop,
|
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+ --> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
| ++++
error[E0277]: can't drop `NonTrivialDrop` in const contexts
- --> $DIR/const-drop-fail.rs:45:5
+ --> $DIR/const-drop-fail.rs:46:5
|
LL | const _: () = check($exp);
| ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
|
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
- --> $DIR/const-drop-fail.rs:45:5
+ --> $DIR/const-drop-fail.rs:46:5
|
LL | ConstImplWithDropGlue(NonTrivialDrop),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,39 +40,60 @@ note: required because it appears within the type `ConstImplWithDropGlue`
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
| ^^^^^^^^^^^^^^^^^^^^^
note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+ --> $DIR/const-drop-fail.rs:35:19
|
LL | const fn check<T: ~const Destruct>(_: T) {}
| ^^^^^^^^^^^^^^^ required by this bound in `check`
-error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
- --> $DIR/const-drop-fail.rs:47:5
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail.rs:48:47
|
-LL | const _: () = check($exp);
- | ----- required by a bound introduced by this call
-...
LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
+ | ----------------------------------------- ^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ | |
+ | required by a bound introduced by this call
|
-note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
- --> $DIR/const-drop-fail.rs:28:25
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:48:47
|
-LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
- | ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: 1 redundant requirement hidden
- = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
-note: required by a bound in `check`
- --> $DIR/const-drop-fail.rs:34:19
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
|
-LL | const fn check<T: ~const Destruct>(_: T) {}
- | ^^^^^^^^^^^^^^^ required by this bound in `check`
-help: consider borrowing here
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0277]: the trait bound `NonTrivialDrop: ~const A` is not satisfied
+ --> $DIR/const-drop-fail.rs:48:5
|
-LL | &ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | +
-LL | &mut ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
- | ++++
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const A` is not implemented for `NonTrivialDrop`
+ |
+note: the trait `A` is implemented for `NonTrivialDrop`, but that implementation is not `const`
+ --> $DIR/const-drop-fail.rs:48:5
+ |
+LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: required by a bound in `ConstDropImplWithBounds`
+ --> $DIR/const-drop-fail.rs:27:35
+ |
+LL | struct ConstDropImplWithBounds<T: ~const A>(PhantomData<T>);
+ | ^^^^^^^^ required by this bound in `ConstDropImplWithBounds`
+
+error[E0367]: `Drop` impl requires `T: ~const A` but the struct it is implemented for does not
+ --> $DIR/const-drop-fail.rs:55:9
+ |
+LL | impl<T: ~const A> const Drop for ConstDropImplWithNonConstBounds<T> {
+ | ^^^^^^^^
+ |
+note: the implementor must specify the same requirement
+ --> $DIR/const-drop-fail.rs:53:1
+ |
+LL | struct ConstDropImplWithNonConstBounds<T: A>(PhantomData<T>);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0367.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
index 04462c0a1..b0fc3adf9 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop.rs
@@ -48,6 +48,7 @@ mod t {
pub struct HasConstDrop(pub ConstDrop);
pub struct TrivialFields(pub u8, pub i8, pub usize, pub isize);
+ #[const_trait]
pub trait SomeTrait {
fn foo();
}
@@ -59,7 +60,7 @@ mod t {
fn foo() {}
}
- pub struct ConstDropWithBound<T: SomeTrait>(pub core::marker::PhantomData<T>);
+ pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {
fn drop(&mut self) {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
index 470c653dd..837124db0 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.rs
@@ -1,9 +1,11 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Foo {}
const impl Foo for i32 {} //~ ERROR: expected identifier, found keyword
+#[const_trait]
trait Bar {}
const impl<T: Foo> Bar for T {} //~ ERROR: expected identifier, found keyword
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
index 709084c86..7217fc855 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-recovery.stderr
@@ -1,5 +1,5 @@
error: expected identifier, found keyword `impl`
- --> $DIR/const-impl-recovery.rs:5:7
+ --> $DIR/const-impl-recovery.rs:6:7
|
LL | const impl Foo for i32 {}
| ^^^^ expected identifier, found keyword
@@ -11,7 +11,7 @@ LL + impl const Foo for i32 {}
|
error: expected identifier, found keyword `impl`
- --> $DIR/const-impl-recovery.rs:9:7
+ --> $DIR/const-impl-recovery.rs:11:7
|
LL | const impl<T: Foo> Bar for T {}
| ^^^^ expected identifier, found keyword
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
new file mode 100644
index 000000000..2b4963991
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+pub trait A {}
+//~^ HELP: mark `A` as const
+
+impl const A for () {}
+//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
new file mode 100644
index 000000000..478adcf3e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-impl-requires-const-trait.stderr
@@ -0,0 +1,14 @@
+error: const `impl` for trait `A` which is not marked with `#[const_trait]`
+ --> $DIR/const-impl-requires-const-trait.rs:6:12
+ |
+LL | pub trait A {}
+ | - help: mark `A` as const: `#[const_trait]`
+...
+LL | impl const A for () {}
+ | ^
+ |
+ = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+ = note: adding a non-const method body in the future would be a breaking change
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index d4fa44b4b..925ae53e3 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
|
LL | NonConst.func();
| ^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
- | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
index 71ecd9b06..11db0c2b8 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -11,10 +11,6 @@ note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst
|
LL | NonConst.func();
| ^^^^^^^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
- | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
index d27291231..96acdc300 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs
@@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Tr {}
impl Tr for () {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
index 7542b81fe..a244ab10c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr
@@ -1,23 +1,19 @@
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
- --> $DIR/default-method-body-is-const-body-checking.rs:11:15
+ --> $DIR/default-method-body-is-const-body-checking.rs:12:15
|
LL | foo::<()>();
| ^^ the trait `~const Tr` is not implemented for `()`
|
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
- --> $DIR/default-method-body-is-const-body-checking.rs:11:15
+ --> $DIR/default-method-body-is-const-body-checking.rs:12:15
|
LL | foo::<()>();
| ^^
note: required by a bound in `foo`
- --> $DIR/default-method-body-is-const-body-checking.rs:6:28
+ --> $DIR/default-method-body-is-const-body-checking.rs:7:28
|
LL | const fn foo<T>() where T: ~const Tr {}
| ^^^^^^^^^ required by this bound in `foo`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | pub trait Foo where (): ~const Tr {
- | +++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index 85285ba84..c2c16921c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -11,10 +11,6 @@ note: the trait `Tr` is implemented for `()`, but that implementation is not `co
|
LL | ().a()
| ^^
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | pub trait Tr where (): ~const Tr {
- | +++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
index af4d3909e..4c630d33c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr
@@ -1,5 +1,5 @@
error: fatal error triggered by #[rustc_error]
- --> $DIR/feature-gate.rs:13:1
+ --> $DIR/feature-gate.rs:14:1
|
LL | fn main() {}
| ^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
index 7bac72e1b..0b409fbaa 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs
@@ -5,6 +5,7 @@
#![feature(rustc_attrs)]
struct S;
+#[const_trait] //[stock]~ ERROR `const_trait` is a temporary placeholder
trait T {}
impl const T for S {}
//[stock]~^ ERROR const trait impls are experimental
diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
index 91a8bb578..0e938c1c5 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr
@@ -1,5 +1,5 @@
error[E0658]: const trait impls are experimental
- --> $DIR/feature-gate.rs:9:6
+ --> $DIR/feature-gate.rs:10:6
|
LL | impl const T for S {}
| ^^^^^
@@ -7,6 +7,15 @@ LL | impl const T for S {}
= note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
= help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
-error: aborting due to previous error
+error[E0658]: `const_trait` is a temporary placeholder for marking a trait that is suitable for `const` `impls` and all default bodies as `const`, which may be removed or renamed in the future.
+ --> $DIR/feature-gate.rs:8:1
+ |
+LL | #[const_trait]
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #67792 <https://github.com/rust-lang/rust/issues/67792> for more information
+ = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
index 80a4442de..337c73340 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.rs
@@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
+#[const_trait]
pub trait MyTrait {
fn method(&self) -> Option<()>;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
index 32df63e44..6d2be1daa 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/hir-const-check.stderr
@@ -1,5 +1,5 @@
error[E0658]: `?` is not allowed in a `const fn`
- --> $DIR/hir-const-check.rs:11:9
+ --> $DIR/hir-const-check.rs:12:9
|
LL | Some(())?;
| ^^^^^^^^^
diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
index 2cef803a9..f8ac793e4 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl-const-bounds.rs
@@ -3,7 +3,9 @@
struct S;
+#[const_trait]
trait A {}
+#[const_trait]
trait B {}
impl const A for S {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
index 1004bb28c..9f3f38ad4 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
@@ -16,6 +16,7 @@ pub trait IndexMut where Self: Index {
impl Index for () { type Output = (); }
+#[cfg(not(any(nn, yn)))]
impl const IndexMut for <() as Index>::Output {
const C: <Self as Index>::Output = ();
type Assoc = <Self as Index>::Output;
@@ -24,6 +25,15 @@ impl const IndexMut for <() as Index>::Output {
{}
}
+#[cfg(any(nn, yn))]
+impl IndexMut for <() as Index>::Output {
+ const C: <Self as Index>::Output = ();
+ type Assoc = <Self as Index>::Output;
+ fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+ where <Self as Index>::Output:,
+ {}
+}
+
const C: <() as Index>::Output = ();
fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
new file mode 100644
index 000000000..fe4e91081
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.rs
@@ -0,0 +1,15 @@
+#![feature(allocator_api)]
+#![feature(const_trait_impl)]
+
+use core::convert::{From, TryFrom};
+//~^ ERROR
+//~| ERROR
+
+use std::pin::Pin;
+use std::alloc::Allocator;
+impl<T: ?Sized, A: Allocator> const From<Box<T, A>> for Pin<Box<T, A>>
+where
+ A: 'static,
+{}
+
+pub fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
new file mode 100644
index 000000000..8bf00eaff
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102156.stderr
@@ -0,0 +1,19 @@
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+ --> $DIR/issue-102156.rs:4:5
+ |
+LL | use core::convert::{From, TryFrom};
+ | ^^^^ maybe a missing crate `core`?
+ |
+ = help: consider adding `extern crate core` to use the `core` crate
+
+error[E0433]: failed to resolve: maybe a missing crate `core`?
+ --> $DIR/issue-102156.rs:4:5
+ |
+LL | use core::convert::{From, TryFrom};
+ | ^^^^ maybe a missing crate `core`?
+ |
+ = help: consider adding `extern crate core` to use the `core` crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs
new file mode 100644
index 000000000..07d3f51ed
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.rs
@@ -0,0 +1,12 @@
+#![feature(const_trait_impl)]
+
+struct Bug {
+ inner: [(); match || 1 {
+ n => n(),
+ //~^ ERROR the trait bound
+ //~| ERROR the trait bound
+ //~| ERROR cannot call non-const closure in constants
+ }],
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr
new file mode 100644
index 000000000..b98ccbe5d
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-102985.stderr
@@ -0,0 +1,41 @@
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+ |
+ = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-102985.rs:4:23: 4:25]: ~const Fn<()>` is not satisfied
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^ expected an `Fn<()>` closure, found `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+ |
+ = help: the trait `~const Fn<()>` is not implemented for closure `[closure@$DIR/issue-102985.rs:4:23: 4:25]`
+note: the trait `Fn<()>` is implemented for `[closure@$DIR/issue-102985.rs:4:23: 4:25]`, but that implementation is not `const`
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ = note: wrap the `[closure@$DIR/issue-102985.rs:4:23: 4:25]` in a closure with no arguments: `|| { /* code */ }`
+
+error[E0015]: cannot call non-const closure in constants
+ --> $DIR/issue-102985.rs:5:14
+ |
+LL | n => n(),
+ | ^^^
+ |
+ = note: closures need an RFC before allowed to be called in constants
+ = note: calls in constants are limited to constant functions, tuple structs and tuple variants
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0015, E0277.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs
new file mode 100644
index 000000000..d81724a36
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-103677.rs
@@ -0,0 +1,5 @@
+// check-pass
+
+const _: fn(&String) = |s| { &*s as &str; };
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
new file mode 100644
index 000000000..21ddf4ab4
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.rs
@@ -0,0 +1,9 @@
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+fn foo<T>() where T: ~const Bar {}
+//~^ ERROR `~const` is not allowed
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
new file mode 100644
index 000000000..b2a936537
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-90052.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+ --> $DIR/issue-90052.rs:6:22
+ |
+LL | fn foo<T>() where T: ~const Bar {}
+ | ^^^^^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/issue-90052.rs:6:4
+ |
+LL | fn foo<T>() where T: ~const Bar {}
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
index 97c27ce1a..4d3469653 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-92230-wf-super-trait-env.rs
@@ -4,7 +4,9 @@
#![feature(const_trait_impl)]
+#[const_trait]
pub trait Super {}
+#[const_trait]
pub trait Sub: Super {}
impl<A> const Super for &A where A: ~const Super {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs b/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs
new file mode 100644
index 000000000..a85113600
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/nested-closure.rs
@@ -0,0 +1,12 @@
+// check-pass
+
+#![feature(const_trait_impl, once_cell)]
+
+use std::sync::LazyLock;
+
+static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
+ let x = || String::new();
+ x()
+});
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
index defef9e04..1a4509b18 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/non-const-op-in-closure-in-const.rs
@@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Convert<T> {
fn to(self) -> T;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs
new file mode 100644
index 000000000..633543700
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.rs
@@ -0,0 +1,31 @@
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+ fn a() -> u32;
+}
+
+impl<T: Default> A for T {
+ default fn a() -> u32 {
+ 2
+ }
+}
+
+impl<T: Default + ~const Sup> const A for T {
+ fn a() -> u32 {
+ 3
+ }
+}
+
+const fn generic<T: Default>() {
+ <T as A>::a();
+ //~^ ERROR: the trait bound `T: ~const Sup` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr
new file mode 100644
index 000000000..c554671e1
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness-2.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `T: ~const Sup` is not satisfied
+ --> $DIR/specializing-constness-2.rs:27:5
+ |
+LL | <T as A>::a();
+ | ^^^^^^^^^^^^^ the trait `~const Sup` is not implemented for `T`
+ |
+note: required for `T` to implement `~const A`
+ --> $DIR/specializing-constness-2.rs:20:37
+ |
+LL | impl<T: Default + ~const Sup> const A for T {
+ | ^ ^
+help: consider further restricting this bound
+ |
+LL | const fn generic<T: Default + ~const Sup>() {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs
new file mode 100644
index 000000000..ff0cd489d
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.rs
@@ -0,0 +1,26 @@
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub trait Sup {}
+
+impl const Sup for () {}
+
+#[const_trait]
+pub trait A {
+ fn a() -> u32;
+}
+
+impl<T: ~const Default> const A for T {
+ default fn a() -> u32 {
+ 2
+ }
+}
+
+impl<T: Default + Sup> A for T { //~ ERROR: cannot specialize
+ fn a() -> u32 {
+ 3
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr
new file mode 100644
index 000000000..3296c109c
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/specializing-constness.stderr
@@ -0,0 +1,8 @@
+error: cannot specialize on trait `Default`
+ --> $DIR/specializing-constness.rs:20:9
+ |
+LL | impl<T: Default + Sup> A for T {
+ | ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs
new file mode 100644
index 000000000..4520a3696
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/static-const-trait-bound.rs
@@ -0,0 +1,18 @@
+// check-pass
+pub struct S<T, F: FnOnce() -> T = fn() -> T> {
+ f: F,
+ x: Option<T>,
+}
+
+impl<T, F: FnOnce() -> T> S<T, F> {
+ pub const fn new(f: F) -> Self {
+ Self { f, x: None }
+ }
+}
+
+#[derive(Default)]
+pub struct Foo;
+
+static LOCKED_CALLSITES: S<Foo> = S::new(Default::default);
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
new file mode 100644
index 000000000..d4f42b787
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
new file mode 100644
index 000000000..d4f42b787
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-2.rs:11:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
index 7b38c15af..d183efde2 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs
@@ -1,14 +1,19 @@
#![feature(const_trait_impl)]
+// revisions: yy yn ny nn
+
+#[cfg_attr(any(yy, yn), const_trait)]
trait Foo {
fn a(&self);
}
+
+#[cfg_attr(any(yy, ny), const_trait)]
trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
const fn foo<T: Bar>(x: &T) {
x.a();
- //~^ ERROR the trait bound
- //~| ERROR cannot call
+ //[yn,yy]~^ ERROR the trait bound
}
fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
deleted file mode 100644
index 1766cdbee..000000000
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0277]: the trait bound `T: ~const Foo` is not satisfied
- --> $DIR/super-traits-fail-2.rs:9:7
- |
-LL | x.a();
- | ^^^ the trait `~const Foo` is not implemented for `T`
- |
-note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
- --> $DIR/super-traits-fail-2.rs:9:7
- |
-LL | x.a();
- | ^^^
-
-error[E0015]: cannot call non-const fn `<T as Foo>::a` in constant functions
- --> $DIR/super-traits-fail-2.rs:9:7
- |
-LL | x.a();
- | ^^^
- |
- = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
new file mode 100644
index 000000000..b52eb2c03
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail-2.rs:15:5
+ |
+LL | x.a();
+ | ^ - required by a bound introduced by this call
+ | |
+ | the trait `~const Foo` is not implemented for `T`
+ |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/super-traits-fail-2.rs:15:5
+ |
+LL | x.a();
+ | ^
+help: consider further restricting this bound
+ |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
new file mode 100644
index 000000000..b52eb2c03
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `T: ~const Foo` is not satisfied
+ --> $DIR/super-traits-fail-2.rs:15:5
+ |
+LL | x.a();
+ | ^ - required by a bound introduced by this call
+ | |
+ | the trait `~const Foo` is not implemented for `T`
+ |
+note: the trait `Foo` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/super-traits-fail-2.rs:15:5
+ |
+LL | x.a();
+ | ^
+help: consider further restricting this bound
+ |
+LL | const fn foo<T: Bar + ~const Foo>(x: &T) {
+ | ++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
new file mode 100644
index 000000000..d433e1cfa
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr
@@ -0,0 +1,14 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:15:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
new file mode 100644
index 000000000..2a7e8e00b
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:12:19
+ |
+LL | trait Bar: ~const Foo {}
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
new file mode 100644
index 000000000..70d2936d3
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs
@@ -0,0 +1,20 @@
+#![feature(const_trait_impl)]
+
+// revisions: yy yn ny nn
+//[yy] check-pass
+
+#[cfg_attr(any(yy, yn), const_trait)]
+trait Foo {
+ fn a(&self);
+}
+
+#[cfg_attr(any(yy, ny), const_trait)]
+trait Bar: ~const Foo {}
+//[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+
+const fn foo<T: ~const Bar>(x: &T) {
+ //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]`
+ x.a();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
new file mode 100644
index 000000000..e5978c12a
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr
@@ -0,0 +1,8 @@
+error: ~const can only be applied to `#[const_trait]` traits
+ --> $DIR/super-traits-fail-3.rs:15:24
+ |
+LL | const fn foo<T: ~const Bar>(x: &T) {
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
index af465cad3..3e2b81368 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.rs
@@ -1,8 +1,10 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Foo {
fn a(&self);
}
+#[const_trait]
trait Bar: ~const Foo {}
struct S;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
index 9e8b8f8c6..1f8f312df 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits-fail.stderr
@@ -1,23 +1,19 @@
error[E0277]: the trait bound `S: ~const Foo` is not satisfied
- --> $DIR/super-traits-fail.rs:13:12
+ --> $DIR/super-traits-fail.rs:15:12
|
LL | impl const Bar for S {}
| ^^^ the trait `~const Foo` is not implemented for `S`
|
note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
- --> $DIR/super-traits-fail.rs:13:12
+ --> $DIR/super-traits-fail.rs:15:12
|
LL | impl const Bar for S {}
| ^^^
note: required by a bound in `Bar`
- --> $DIR/super-traits-fail.rs:6:12
+ --> $DIR/super-traits-fail.rs:8:12
|
LL | trait Bar: ~const Foo {}
| ^^^^^^^^^^ required by this bound in `Bar`
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
- |
-LL | impl const Bar for S where S: ~const Foo {}
- | +++++++++++++++++++
error: aborting due to previous error
diff --git a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs
index aded4ca9a..df96f6fb4 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/super-traits.rs
@@ -1,9 +1,12 @@
// check-pass
#![feature(const_trait_impl)]
+#[const_trait]
trait Foo {
fn a(&self);
}
+
+#[const_trait]
trait Bar: ~const Foo {}
struct S;
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
new file mode 100644
index 000000000..78a64b901
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs
@@ -0,0 +1,34 @@
+#![feature(const_trait_impl)]
+#![feature(generic_arg_infer)]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+ fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
+ Foo
+ }
+}
+
+#[const_trait]
+trait Add42 {
+ fn add(a: usize) -> usize;
+}
+
+impl const Add42 for () {
+ fn add(a: usize) -> usize {
+ a + 42
+ }
+}
+
+fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ //~^ ERROR `~const` is not allowed here
+ Foo
+}
+
+fn main() {
+ let foo = Foo::<0>;
+ let foo = bar::<(), _>(foo);
+ let _foo = bar::<(), _>(foo);
+}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
new file mode 100644
index 000000000..aae72f36e
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr
@@ -0,0 +1,14 @@
+error: `~const` is not allowed here
+ --> $DIR/tilde-const-and-const-params.rs:25:11
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^^^^^^^^^^
+ |
+note: this function is not `const`, so it cannot have `~const` trait bounds
+ --> $DIR/tilde-const-and-const-params.rs:25:4
+ |
+LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
index b4302f3e7..5bd52151f 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.rs
@@ -1,6 +1,7 @@
#![feature(const_trait_impl)]
#![feature(associated_type_bounds)]
+#[const_trait]
trait T {}
struct S;
impl T for S {}
@@ -17,12 +18,6 @@ fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
//~^ ERROR `~const` is not allowed
-fn generic<P: ~const T>() {}
-//~^ ERROR `~const` is not allowed
-
-fn where_clause<P>() where P: ~const T {}
-//~^ ERROR `~const` is not allowed
-
struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
//~^ ERROR `~const` and `?` are mutually exclusive
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
index 033ec21ba..84867cb4a 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr
@@ -1,56 +1,40 @@
error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:8:19
+ --> $DIR/tilde-const-invalid-places.rs:9:19
|
LL | fn rpit() -> impl ~const T { S }
| ^^^^^^^^
|
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+ = note: `impl Trait`s cannot have `~const` trait bounds
error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:11:17
+ --> $DIR/tilde-const-invalid-places.rs:12:17
|
LL | fn apit(_: impl ~const T) {}
| ^^^^^^^^
|
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+ = note: `impl Trait`s cannot have `~const` trait bounds
error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:14:50
+ --> $DIR/tilde-const-invalid-places.rs:15:50
|
LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ~const T> { Some(S) }
| ^^^^^^^^
|
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+ = note: `impl Trait`s cannot have `~const` trait bounds
error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:17:48
+ --> $DIR/tilde-const-invalid-places.rs:18:48
|
LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ~const T>) {}
| ^^^^^^^^
|
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
-
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:20:15
- |
-LL | fn generic<P: ~const T>() {}
- | ^^^^^^^^
- |
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
-
-error: `~const` is not allowed here
- --> $DIR/tilde-const-invalid-places.rs:23:31
- |
-LL | fn where_clause<P>() where P: ~const T {}
- | ^^^^^^^^
- |
- = note: only allowed on bounds on traits' associated types and functions, const fns, const impls and its associated functions
+ = note: `impl Trait`s cannot have `~const` trait bounds
error: `~const` and `?` are mutually exclusive
- --> $DIR/tilde-const-invalid-places.rs:26:25
+ --> $DIR/tilde-const-invalid-places.rs:21:25
|
LL | struct TildeQuestion<T: ~const ?Sized>(std::marker::PhantomData<T>);
| ^^^^^^^^^^^^^
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
diff --git a/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs b/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
new file mode 100644
index 000000000..285cef571
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/tilde_const_on_impl_bound.rs
@@ -0,0 +1,17 @@
+// check-pass
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Foo {
+ fn foo(&self) {}
+}
+
+struct Bar<T>(T);
+
+impl<T: ~const Foo> Bar<T> {
+ const fn foo(&self) {
+ self.0.foo()
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
new file mode 100644
index 000000000..bfe98b98c
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.rs
@@ -0,0 +1,31 @@
+// Like trait-where-clause.rs, but we are calling from a const context.
+// Checking the validity of traits' where clauses happen at a later stage.
+// (`rustc_const_eval` instead of `rustc_hir_analysis`) Therefore one file as a
+// test is not enough.
+#![feature(const_trait_impl)]
+
+#[const_trait]
+trait Bar {}
+
+#[const_trait]
+trait Foo {
+ fn a();
+ fn b() where Self: ~const Bar;
+ fn c<T: ~const Bar>();
+}
+
+const fn test1<T: ~const Foo + Bar>() {
+ T::a();
+ T::b();
+ //~^ ERROR the trait bound
+ T::c::<T>();
+ //~^ ERROR the trait bound
+}
+
+const fn test2<T: ~const Foo + ~const Bar>() {
+ T::a();
+ T::b();
+ T::c::<T>();
+}
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
new file mode 100644
index 000000000..f2846b6a6
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-const.stderr
@@ -0,0 +1,35 @@
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+ --> $DIR/trait-where-clause-const.rs:19:5
+ |
+LL | T::b();
+ | ^^^^^^ the trait `~const Bar` is not implemented for `T`
+ |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/trait-where-clause-const.rs:19:5
+ |
+LL | T::b();
+ | ^^^^^^
+help: consider further restricting this bound
+ |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+ | ++++++++++++
+
+error[E0277]: the trait bound `T: ~const Bar` is not satisfied
+ --> $DIR/trait-where-clause-const.rs:21:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
+ |
+note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
+ --> $DIR/trait-where-clause-const.rs:21:5
+ |
+LL | T::c::<T>();
+ | ^^^^^^^^^^^
+help: consider further restricting this bound
+ |
+LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
+ | ++++++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
index b7cf9a13b..4b8b00406 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-run.rs
@@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Bar {
fn bar() -> u8;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
index acea58eae..3b028ac48 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause-self-referential.rs
@@ -2,6 +2,7 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Foo {
fn bar() where Self: ~const Foo;
}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
index d37ed3bb8..85ca5fc90 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.rs
@@ -1,5 +1,6 @@
#![feature(const_trait_impl)]
+#[const_trait]
trait Bar {}
trait Foo {
@@ -8,7 +9,7 @@ trait Foo {
fn c<T: ~const Bar>();
}
-const fn test1<T: ~const Foo + Bar>() {
+fn test1<T: Foo>() {
T::a();
T::b();
//~^ ERROR the trait bound
@@ -16,21 +17,7 @@ const fn test1<T: ~const Foo + Bar>() {
//~^ ERROR the trait bound
}
-const fn test2<T: ~const Foo + ~const Bar>() {
- T::a();
- T::b();
- T::c::<T>();
-}
-
-fn test3<T: Foo>() {
- T::a();
- T::b();
- //~^ ERROR the trait bound
- T::c::<T>();
- //~^ ERROR the trait bound
-}
-
-fn test4<T: Foo + Bar>() {
+fn test2<T: Foo + Bar>() {
T::a();
T::b();
T::c::<T>();
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
index fd5fe25dd..11f0c4016 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -1,77 +1,35 @@
-error[E0277]: the trait bound `T: ~const Bar` is not satisfied
- --> $DIR/trait-where-clause.rs:13:5
- |
-LL | T::b();
- | ^^^^ the trait `~const Bar` is not implemented for `T`
- |
-note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
- --> $DIR/trait-where-clause.rs:13:5
- |
-LL | T::b();
- | ^^^^
-note: required by a bound in `Foo::b`
- --> $DIR/trait-where-clause.rs:7:24
- |
-LL | fn b() where Self: ~const Bar;
- | ^^^^^^^^^^ required by this bound in `Foo::b`
-help: consider further restricting this bound
- |
-LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
- | ++++++++++++
-
-error[E0277]: the trait bound `T: ~const Bar` is not satisfied
- --> $DIR/trait-where-clause.rs:15:12
- |
-LL | T::c::<T>();
- | ^ the trait `~const Bar` is not implemented for `T`
- |
-note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
- --> $DIR/trait-where-clause.rs:15:12
- |
-LL | T::c::<T>();
- | ^
-note: required by a bound in `Foo::c`
- --> $DIR/trait-where-clause.rs:8:13
- |
-LL | fn c<T: ~const Bar>();
- | ^^^^^^^^^^ required by this bound in `Foo::c`
-help: consider further restricting this bound
- |
-LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
- | ++++++++++++
-
error[E0277]: the trait bound `T: Bar` is not satisfied
- --> $DIR/trait-where-clause.rs:27:5
+ --> $DIR/trait-where-clause.rs:14:5
|
LL | T::b();
| ^^^^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::b`
- --> $DIR/trait-where-clause.rs:7:24
+ --> $DIR/trait-where-clause.rs:8:24
|
LL | fn b() where Self: ~const Bar;
| ^^^^^^^^^^ required by this bound in `Foo::b`
help: consider further restricting this bound
|
-LL | fn test3<T: Foo + Bar>() {
+LL | fn test1<T: Foo + Bar>() {
| +++++
error[E0277]: the trait bound `T: Bar` is not satisfied
- --> $DIR/trait-where-clause.rs:29:12
+ --> $DIR/trait-where-clause.rs:16:12
|
LL | T::c::<T>();
| ^ the trait `Bar` is not implemented for `T`
|
note: required by a bound in `Foo::c`
- --> $DIR/trait-where-clause.rs:8:13
+ --> $DIR/trait-where-clause.rs:9:13
|
LL | fn c<T: ~const Bar>();
| ^^^^^^^^^^ required by this bound in `Foo::c`
help: consider further restricting this bound
|
-LL | fn test3<T: Foo + Bar>() {
+LL | fn test1<T: Foo + Bar>() {
| +++++
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc1623-2.stderr b/src/test/ui/rfc1623-2.stderr
index 495d45e22..945c6533c 100644
--- a/src/test/ui/rfc1623-2.stderr
+++ b/src/test/ui/rfc1623-2.stderr
@@ -23,7 +23,7 @@ help: consider making the type lifetime-generic with a new `'a` lifetime
LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8);
| +++++++ ++ ++ ++
-error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'r, 's> fn(&'r u8, &'s u8) -> &u8`
+error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8`
--> $DIR/rfc1623-2.rs:10:6
|
LL | &(non_elidable as fn(&u8, &u8) -> &u8);
diff --git a/src/test/ui/rfcs/rfc1857-drop-order.rs b/src/test/ui/rfcs/rfc1857-drop-order.rs
index 243b7fb6f..4c4816c2f 100644
--- a/src/test/ui/rfcs/rfc1857-drop-order.rs
+++ b/src/test/ui/rfcs/rfc1857-drop-order.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![allow(dead_code, unreachable_code)]
diff --git a/src/test/ui/runtime/backtrace-debuginfo.rs b/src/test/ui/runtime/backtrace-debuginfo.rs
index 7c9f1a7f2..8b5466b6c 100644
--- a/src/test/ui/runtime/backtrace-debuginfo.rs
+++ b/src/test/ui/runtime/backtrace-debuginfo.rs
@@ -12,6 +12,7 @@
// ignore-pretty issue #37195
// ignore-emscripten spawning processes is not supported
// ignore-sgx no processes
+// ignore-fuchsia Backtrace not symbolized, trace different line alignment
use std::env;
diff --git a/src/test/ui/runtime/out-of-stack.rs b/src/test/ui/runtime/out-of-stack.rs
index 73c31cd97..6873abc49 100644
--- a/src/test/ui/runtime/out-of-stack.rs
+++ b/src/test/ui/runtime/out-of-stack.rs
@@ -5,6 +5,7 @@
// ignore-android: FIXME (#20004)
// ignore-emscripten no processes
// ignore-sgx no processes
+// ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
#![feature(core_intrinsics)]
#![feature(rustc_private)]
diff --git a/src/test/ui/runtime/rt-explody-panic-payloads.rs b/src/test/ui/runtime/rt-explody-panic-payloads.rs
index eb5bf8f67..755d3df42 100644
--- a/src/test/ui/runtime/rt-explody-panic-payloads.rs
+++ b/src/test/ui/runtime/rt-explody-panic-payloads.rs
@@ -2,9 +2,6 @@
// needs-unwind
// ignore-emscripten no processes
// ignore-sgx no processes
-// ignore-wasm32-bare no unwinding panic
-// ignore-avr no unwinding panic
-// ignore-nvptx64 no unwinding panic
use std::env;
use std::process::Command;
@@ -25,7 +22,12 @@ fn main() {
}.expect("running the command should have succeeded");
println!("{:#?}", output);
let stderr = std::str::from_utf8(&output.stderr);
- assert!(stderr.map(|v| {
- v.ends_with("fatal runtime error: drop of the panic payload panicked\n")
- }).unwrap_or(false));
+ assert!(stderr
+ .map(|v| {
+ // When running inside QEMU user-mode emulation, there will be an extra message printed
+ // by QEMU in the stderr whenever a core dump happens. Remove it before the check.
+ v.strip_suffix("qemu: uncaught target signal 6 (Aborted) - core dumped\n").unwrap_or(v)
+ })
+ .map(|v| { v.ends_with("fatal runtime error: drop of the panic payload panicked\n") })
+ .unwrap_or(false));
}
diff --git a/src/test/ui/rust-2018/async-ident-allowed.stderr b/src/test/ui/rust-2018/async-ident-allowed.stderr
index 5b63eab8e..992b29750 100644
--- a/src/test/ui/rust-2018/async-ident-allowed.stderr
+++ b/src/test/ui/rust-2018/async-ident-allowed.stderr
@@ -4,14 +4,14 @@ error: `async` is a keyword in the 2018 edition
LL | let async = 3;
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/async-ident-allowed.rs:3:9
|
LL | #![deny(rust_2018_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[deny(keyword_idents)]` implied by `#[deny(rust_2018_compatibility)]`
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: aborting due to previous error
diff --git a/src/test/ui/rust-2018/async-ident.stderr b/src/test/ui/rust-2018/async-ident.stderr
index 6396e9dee..d15250c54 100644
--- a/src/test/ui/rust-2018/async-ident.stderr
+++ b/src/test/ui/rust-2018/async-ident.stderr
@@ -4,13 +4,13 @@ error: `async` is a keyword in the 2018 edition
LL | fn async() {}
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/async-ident.rs:2:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: `async` is a keyword in the 2018 edition
--> $DIR/async-ident.rs:12:7
diff --git a/src/test/ui/rust-2018/dyn-keyword.stderr b/src/test/ui/rust-2018/dyn-keyword.stderr
index 699242f2d..b6f5b10cf 100644
--- a/src/test/ui/rust-2018/dyn-keyword.stderr
+++ b/src/test/ui/rust-2018/dyn-keyword.stderr
@@ -4,13 +4,13 @@ error: `dyn` is a keyword in the 2018 edition
LL | let dyn = ();
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/dyn-keyword.rs:5:9
|
LL | #![deny(keyword_idents)]
| ^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
error: aborting due to previous error
diff --git a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
index 6f529fa91..e1709db09 100644
--- a/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
+++ b/src/test/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | let _: <foo::Baz as ::foo::Foo>::Bar = ();
| ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/edition-lint-fully-qualified-paths.rs:4:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
--> $DIR/edition-lint-fully-qualified-paths.rs:23:13
diff --git a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
index e47c320f7..8769cbb35 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
+++ b/src/test/ui/rust-2018/edition-lint-nested-empty-paths.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | use foo::{bar::{baz::{}}};
| ^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}}}`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/edition-lint-nested-empty-paths.rs:4:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
--> $DIR/edition-lint-nested-empty-paths.rs:21:5
diff --git a/src/test/ui/rust-2018/edition-lint-nested-paths.stderr b/src/test/ui/rust-2018/edition-lint-nested-paths.stderr
index 24b17f212..354a6fe32 100644
--- a/src/test/ui/rust-2018/edition-lint-nested-paths.stderr
+++ b/src/test/ui/rust-2018/edition-lint-nested-paths.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | use foo::{a, b};
| ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/edition-lint-nested-paths.rs:4:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
--> $DIR/edition-lint-nested-paths.rs:6:5
diff --git a/src/test/ui/rust-2018/edition-lint-paths.stderr b/src/test/ui/rust-2018/edition-lint-paths.stderr
index 1ded8cd36..42652be94 100644
--- a/src/test/ui/rust-2018/edition-lint-paths.stderr
+++ b/src/test/ui/rust-2018/edition-lint-paths.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | use bar::Bar;
| ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/edition-lint-paths.rs:5:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
--> $DIR/edition-lint-paths.rs:19:9
diff --git a/src/test/ui/rust-2018/extern-crate-rename.stderr b/src/test/ui/rust-2018/extern-crate-rename.stderr
index 4bccbc512..eb040f5de 100644
--- a/src/test/ui/rust-2018/extern-crate-rename.stderr
+++ b/src/test/ui/rust-2018/extern-crate-rename.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | use my_crate::foo;
| ^^^^^^^^^^^^^ help: use `crate`: `crate::my_crate::foo`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/extern-crate-rename.rs:8:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: aborting due to previous error
diff --git a/src/test/ui/rust-2018/extern-crate-submod.stderr b/src/test/ui/rust-2018/extern-crate-submod.stderr
index 3c75319ae..1a9aa7578 100644
--- a/src/test/ui/rust-2018/extern-crate-submod.stderr
+++ b/src/test/ui/rust-2018/extern-crate-submod.stderr
@@ -4,13 +4,13 @@ error: absolute paths must start with `self`, `super`, `crate`, or an external c
LL | use m::edition_lint_paths::foo;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::m::edition_lint_paths::foo`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
note: the lint level is defined here
--> $DIR/extern-crate-submod.rs:9:9
|
LL | #![deny(absolute_paths_not_starting_with_crate)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
error: aborting due to previous error
diff --git a/src/test/ui/rust-2018/try-ident.stderr b/src/test/ui/rust-2018/try-ident.stderr
index 3d93b433c..74015ac9d 100644
--- a/src/test/ui/rust-2018/try-ident.stderr
+++ b/src/test/ui/rust-2018/try-ident.stderr
@@ -4,14 +4,14 @@ warning: `try` is a keyword in the 2018 edition
LL | try();
| ^^^ help: you can use a raw identifier to stay compatible: `r#try`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/try-ident.rs:4:9
|
LL | #![warn(rust_2018_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
warning: `try` is a keyword in the 2018 edition
--> $DIR/try-ident.rs:12:4
diff --git a/src/test/ui/rust-2018/try-macro.stderr b/src/test/ui/rust-2018/try-macro.stderr
index f315b4d4a..760378f09 100644
--- a/src/test/ui/rust-2018/try-macro.stderr
+++ b/src/test/ui/rust-2018/try-macro.stderr
@@ -4,14 +4,14 @@ warning: `try` is a keyword in the 2018 edition
LL | try!(x);
| ^^^ help: you can use a raw identifier to stay compatible: `r#try`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+ = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
note: the lint level is defined here
--> $DIR/try-macro.rs:6:9
|
LL | #![warn(rust_2018_compatibility)]
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(keyword_idents)]` implied by `#[warn(rust_2018_compatibility)]`
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
- = note: for more information, see issue #49716 <https://github.com/rust-lang/rust/issues/49716>
warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr b/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
index fac8d21c7..2a724bd30 100644
--- a/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
+++ b/src/test/ui/rust-2021/array-into-iter-ambiguous.stderr
@@ -4,13 +4,13 @@ warning: trait method `into_iter` will become ambiguous in Rust 2021
LL | let y = points.into_iter();
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyIntoIter::into_iter(points)`
|
+ = warning: this changes meaning in Rust 2021
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
note: the lint level is defined here
--> $DIR/array-into-iter-ambiguous.rs:5:9
|
LL | #![warn(array_into_iter)]
| ^^^^^^^^^^^^^^^
- = warning: this changes meaning in Rust 2021
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>
warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr
index 14ad9b017..f38da132b 100644
--- a/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision-generic-trait.stderr
@@ -4,13 +4,13 @@ warning: trait-associated function `try_from` will become ambiguous in Rust 2021
LL | U::try_from(self)
| ^^^^^^^^^^^ help: disambiguate the associated function: `<U as PyTryFrom<'_, _>>::try_from`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision-generic-trait.rs:5:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/future-prelude-collision-generic.stderr b/src/test/ui/rust-2021/future-prelude-collision-generic.stderr
index e1d3f3c0a..9893b3eba 100644
--- a/src/test/ui/rust-2021/future-prelude-collision-generic.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision-generic.stderr
@@ -4,13 +4,13 @@ warning: trait-associated function `from_iter` will become ambiguous in Rust 202
LL | Generic::from_iter(1);
| ^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Generic<'_, _> as MyFromIter>::from_iter`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision-generic.rs:5:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `from_iter` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-generic.rs:31:5
diff --git a/src/test/ui/rust-2021/future-prelude-collision-imported.stderr b/src/test/ui/rust-2021/future-prelude-collision-imported.stderr
index 56abb8abd..c1d72d0df 100644
--- a/src/test/ui/rust-2021/future-prelude-collision-imported.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision-imported.stderr
@@ -4,13 +4,13 @@ warning: trait method `try_into` will become ambiguous in Rust 2021
LL | let _: u32 = 3u8.try_into().unwrap();
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision-imported.rs:4:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-imported.rs:40:22
diff --git a/src/test/ui/rust-2021/future-prelude-collision-macros.stderr b/src/test/ui/rust-2021/future-prelude-collision-macros.stderr
index 4c3543ca7..4d4a07699 100644
--- a/src/test/ui/rust-2021/future-prelude-collision-macros.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision-macros.stderr
@@ -4,13 +4,13 @@ warning: trait method `try_into` will become ambiguous in Rust 2021
LL | foo!().try_into(todo!());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `MyTry::try_into(foo!(), todo!())`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision-macros.rs:4:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-macros.rs:42:5
diff --git a/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr b/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr
index 2de9020bc..c0ef80fd8 100644
--- a/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision-turbofish.stderr
@@ -4,13 +4,13 @@ warning: trait method `try_into` will become ambiguous in Rust 2021
LL | x.try_into::<usize>().or(Err("foo"))?.checked_sub(1);
| ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `AnnotatableTryInto::try_into::<usize>(x)`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision-turbofish.rs:6:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait method `try_into` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision-turbofish.rs:23:5
diff --git a/src/test/ui/rust-2021/future-prelude-collision.stderr b/src/test/ui/rust-2021/future-prelude-collision.stderr
index 889e66de0..cae113ff7 100644
--- a/src/test/ui/rust-2021/future-prelude-collision.stderr
+++ b/src/test/ui/rust-2021/future-prelude-collision.stderr
@@ -4,13 +4,13 @@ warning: trait method `try_into` will become ambiguous in Rust 2021
LL | let _: u32 = 3u8.try_into().unwrap();
| ^^^^^^^^^^^^^^ help: disambiguate the associated function: `TryIntoU32::try_into(3u8)`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/future-prelude-collision.rs:4:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: trait-associated function `try_from` will become ambiguous in Rust 2021
--> $DIR/future-prelude-collision.rs:61:13
diff --git a/src/test/ui/rust-2021/generic-type-collision.stderr b/src/test/ui/rust-2021/generic-type-collision.stderr
index e6ea28d71..1ec61044f 100644
--- a/src/test/ui/rust-2021/generic-type-collision.stderr
+++ b/src/test/ui/rust-2021/generic-type-collision.stderr
@@ -4,13 +4,13 @@ warning: trait-associated function `from_iter` will become ambiguous in Rust 202
LL | <Vec<i32>>::from_iter(None);
| ^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `<Vec<i32> as MyTrait<_>>::from_iter`
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/generic-type-collision.rs:4:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/inherent-dyn-collision.stderr b/src/test/ui/rust-2021/inherent-dyn-collision.stderr
index 77b4c3851..f5905574a 100644
--- a/src/test/ui/rust-2021/inherent-dyn-collision.stderr
+++ b/src/test/ui/rust-2021/inherent-dyn-collision.stderr
@@ -4,13 +4,13 @@ warning: trait method `try_into` will become ambiguous in Rust 2021
LL | get_dyn_trait().try_into().unwrap()
| ^^^^^^^^^^^^^^^ help: disambiguate the method call: `(&*get_dyn_trait())`
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
note: the lint level is defined here
--> $DIR/inherent-dyn-collision.rs:8:9
|
LL | #![warn(rust_2021_prelude_collisions)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/prelude.html>
warning: 1 warning emitted
diff --git a/src/test/ui/rust-2021/reserved-prefixes-migration.stderr b/src/test/ui/rust-2021/reserved-prefixes-migration.stderr
index c6bc082cf..20914d1b9 100644
--- a/src/test/ui/rust-2021/reserved-prefixes-migration.stderr
+++ b/src/test/ui/rust-2021/reserved-prefixes-migration.stderr
@@ -4,13 +4,13 @@ warning: prefix `z` is unknown
LL | m2!(z"hey");
| ^ unknown prefix
|
+ = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
note: the lint level is defined here
--> $DIR/reserved-prefixes-migration.rs:5:9
|
LL | #![warn(rust_2021_prefixes_incompatible_syntax)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/reserving-syntax.html>
help: insert whitespace here to avoid this being parsed as a prefix in Rust 2021
|
LL | m2!(z "hey");
diff --git a/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr b/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
index a14ab8fe4..e9a4c1dd5 100644
--- a/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
+++ b/src/test/ui/rustdoc/deny-invalid-doc-attrs.stderr
@@ -4,13 +4,13 @@ error: unknown `doc` attribute `x`
LL | #![doc(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 #82730 <https://github.com/rust-lang/rust/issues/82730>
note: the lint level is defined here
--> $DIR/deny-invalid-doc-attrs.rs:1:9
|
LL | #![deny(invalid_doc_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
error: aborting due to previous error
diff --git a/src/test/ui/rustdoc/doc-test-attr.stderr b/src/test/ui/rustdoc/doc-test-attr.stderr
index 7f5e2d6bc..5e6014954 100644
--- a/src/test/ui/rustdoc/doc-test-attr.stderr
+++ b/src/test/ui/rustdoc/doc-test-attr.stderr
@@ -4,13 +4,13 @@ error: `#[doc(test(...)]` takes a list of attributes
LL | #![doc(test)]
| ^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
note: the lint level is defined here
--> $DIR/doc-test-attr.rs:2:9
|
LL | #![deny(invalid_doc_attributes)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
error: `#[doc(test(...)]` takes a list of attributes
--> $DIR/doc-test-attr.rs:7:8
diff --git a/src/test/ui/rustdoc/feature-gate-doc_primitive.stderr b/src/test/ui/rustdoc/feature-gate-doc_primitive.stderr
index 736bf29c5..194b2d87d 100644
--- a/src/test/ui/rustdoc/feature-gate-doc_primitive.stderr
+++ b/src/test/ui/rustdoc/feature-gate-doc_primitive.stderr
@@ -4,9 +4,9 @@ warning: `doc(primitive)` should never have been stable
LL | #[doc(primitive = "usize")]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(invalid_doc_attributes)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #82730 <https://github.com/rust-lang/rust/issues/82730>
+ = note: `#[warn(invalid_doc_attributes)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs
index 9a26a351d..5b2cea875 100644
--- a/src/test/ui/sanitize/address.rs
+++ b/src/test/ui/sanitize/address.rs
@@ -5,9 +5,7 @@
//
// run-fail
// error-pattern: AddressSanitizer: stack-buffer-overflow
-// error-pattern: 'xs' (line 15) <== Memory access at offset
-
-#![feature(bench_black_box)]
+// error-pattern: 'xs' (line 13) <== Memory access at offset
use std::hint::black_box;
diff --git a/src/test/ui/sanitize/hwaddress.rs b/src/test/ui/sanitize/hwaddress.rs
index b988035f7..f9b37a155 100644
--- a/src/test/ui/sanitize/hwaddress.rs
+++ b/src/test/ui/sanitize/hwaddress.rs
@@ -10,8 +10,6 @@
// run-fail
// error-pattern: HWAddressSanitizer: tag-mismatch
-#![feature(bench_black_box)]
-
use std::hint::black_box;
fn main() {
diff --git a/src/test/ui/sanitize/inline-always.stderr b/src/test/ui/sanitize/inline-always.stderr
index 918762d1f..74fba3c0e 100644
--- a/src/test/ui/sanitize/inline-always.stderr
+++ b/src/test/ui/sanitize/inline-always.stderr
@@ -4,12 +4,12 @@ warning: `no_sanitize` will have no effect after inlining
LL | #[no_sanitize(address)]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(inline_no_sanitize)]` on by default
note: inlining requested here
--> $DIR/inline-always.rs:5:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
+ = note: `#[warn(inline_no_sanitize)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/sanitize/leak.rs b/src/test/ui/sanitize/leak.rs
index f63f81352..cbb44ae8a 100644
--- a/src/test/ui/sanitize/leak.rs
+++ b/src/test/ui/sanitize/leak.rs
@@ -6,8 +6,6 @@
// run-fail
// error-pattern: LeakSanitizer: detected memory leaks
-#![feature(bench_black_box)]
-
use std::hint::black_box;
use std::mem;
diff --git a/src/test/ui/sanitize/memory-eager.rs b/src/test/ui/sanitize/memory-eager.rs
index cc0593ec0..0018c2f75 100644
--- a/src/test/ui/sanitize/memory-eager.rs
+++ b/src/test/ui/sanitize/memory-eager.rs
@@ -17,7 +17,6 @@
#![feature(core_intrinsics)]
#![feature(start)]
-#![feature(bench_black_box)]
use std::hint::black_box;
use std::mem::MaybeUninit;
diff --git a/src/test/ui/sanitize/memory.rs b/src/test/ui/sanitize/memory.rs
index 14d4de65d..1a9ac3a4f 100644
--- a/src/test/ui/sanitize/memory.rs
+++ b/src/test/ui/sanitize/memory.rs
@@ -16,7 +16,6 @@
#![feature(core_intrinsics)]
#![feature(start)]
-#![feature(bench_black_box)]
#![allow(invalid_value)]
use std::hint::black_box;
diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
index 1542c7f31..33e18e355 100644
--- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
+++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
@@ -7,7 +7,7 @@
//
// no-prefer-dynamic
// revisions: opt0 opt1
-// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin
+// compile-flags: -Zsanitizer=address -Clto=thin
//[opt0]compile-flags: -Copt-level=0
//[opt1]compile-flags: -Copt-level=1
// run-fail
diff --git a/src/test/ui/save-analysis/issue-68621.stderr b/src/test/ui/save-analysis/issue-68621.stderr
index 4a4bf9a69..4452ee791 100644
--- a/src/test/ui/save-analysis/issue-68621.stderr
+++ b/src/test/ui/save-analysis/issue-68621.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
LL | type Future = impl Trait;
| ^^^^^^^^^^
|
- = note: `Future` must be used in combination with a concrete type within the same module
+ = note: `Future` must be used in combination with a concrete type within the same impl
error: aborting due to previous error
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 7e7d60d0f..eb3d3e4a6 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -6,7 +6,7 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
| |
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 30d2250c0..2c0b2a0d9 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -6,7 +6,7 @@ LL | fn f(self: Pin<&Self>) -> impl Clone { self }
| |
| hidden type `Pin<&Foo>` captures the anonymous lifetime defined here
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Clone` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
| ++++
diff --git a/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr b/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
index 870f4064d..8881ede0d 100644
--- a/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
+++ b/src/test/ui/simd/portable-intrinsics-arent-exposed.stderr
@@ -11,6 +11,11 @@ error[E0432]: unresolved import `std::simd::intrinsics`
|
LL | use std::simd::intrinsics;
| ^^^^^^^^^^^^^^^^^^^^^ no `intrinsics` in `simd`
+ |
+help: consider importing this module instead
+ |
+LL | use std::intrinsics;
+ | ~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
diff --git a/src/test/ui/simd/target-feature-mixup.rs b/src/test/ui/simd/target-feature-mixup.rs
index 6d7688191..5dd163715 100644
--- a/src/test/ui/simd/target-feature-mixup.rs
+++ b/src/test/ui/simd/target-feature-mixup.rs
@@ -5,6 +5,7 @@
// ignore-emscripten
// ignore-sgx no processes
+// ignore-fuchsia must translate zircon signal to SIGILL, FIXME (#58590)
#![feature(repr_simd, target_feature, cfg_target_feature)]
#![feature(avx512_target_feature)]
diff --git a/src/test/ui/single-use-lifetime/derive-eq.rs b/src/test/ui/single-use-lifetime/derive-eq.rs
new file mode 100644
index 000000000..e5bdfc55d
--- /dev/null
+++ b/src/test/ui/single-use-lifetime/derive-eq.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![deny(single_use_lifetimes)]
+
+#[derive(PartialEq, Eq)]
+struct Foo<'a, T> {
+ /// a reference to the underlying secret data that will be derefed
+ pub data: &'a mut T,
+}
+
+fn main() {}
diff --git a/src/test/ui/sized-cycle-note.rs b/src/test/ui/sized-cycle-note.rs
index ca8be5692..766a5fa0d 100644
--- a/src/test/ui/sized-cycle-note.rs
+++ b/src/test/ui/sized-cycle-note.rs
@@ -1,15 +1,6 @@
-// Test the error message resulting from a cycle in solving `Foo:
-// Sized`. The specifics of the message will of course but the main
-// thing we want to preserve is that:
-//
-// 1. the message should appear attached to one of the structs
-// defined in this file;
-// 2. it should elaborate the steps that led to the cycle.
-
struct Baz { q: Option<Foo> }
-//~^ ERROR recursive type `Baz` has infinite size
+//~^ ERROR recursive types `Baz` and `Foo` have infinite size
struct Foo { q: Option<Baz> }
-//~^ ERROR recursive type `Foo` has infinite size
impl Foo { fn bar(&self) {} }
diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr
index 536510814..06c87b61f 100644
--- a/src/test/ui/sized-cycle-note.stderr
+++ b/src/test/ui/sized-cycle-note.stderr
@@ -1,29 +1,19 @@
-error[E0072]: recursive type `Baz` has infinite size
- --> $DIR/sized-cycle-note.rs:9:1
+error[E0072]: recursive types `Baz` and `Foo` have infinite size
+ --> $DIR/sized-cycle-note.rs:1:1
|
LL | struct Baz { q: Option<Foo> }
- | ^^^^^^^^^^ ----------- recursive without indirection
- | |
- | recursive type has infinite size
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
- |
-LL | struct Baz { q: Option<Box<Foo>> }
- | ++++ +
-
-error[E0072]: recursive type `Foo` has infinite size
- --> $DIR/sized-cycle-note.rs:11:1
- |
+ | ^^^^^^^^^^ --- recursive without indirection
+LL |
LL | struct Foo { q: Option<Baz> }
- | ^^^^^^^^^^ ----------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^^ --- recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+LL ~ struct Baz { q: Option<Box<Foo>> }
+LL |
+LL ~ struct Foo { q: Option<Box<Baz>> }
|
-LL | struct Foo { q: Option<Box<Baz>> }
- | ++++ +
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr
index 882ed577c..20f2e0df0 100644
--- a/src/test/ui/span/E0072.stderr
+++ b/src/test/ui/span/E0072.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `ListNode` has infinite size
--> $DIR/E0072.rs:1:1
|
LL | struct ListNode {
- | ^^^^^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^^^^^
LL | head: u8,
LL | tail: Option<ListNode>,
- | ---------------- recursive without indirection
+ | -------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | tail: Option<Box<ListNode>>,
| ++++ +
diff --git a/src/test/ui/span/E0204.stderr b/src/test/ui/span/E0204.stderr
index 257584843..0b2166eed 100644
--- a/src/test/ui/span/E0204.stderr
+++ b/src/test/ui/span/E0204.stderr
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/E0204.rs:5:6
+ --> $DIR/E0204.rs:5:15
|
LL | foo: Vec<u32>,
| ------------- this field does not implement `Copy`
...
LL | impl Copy for Foo { }
- | ^^^^
+ | ^^^
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:7:10
@@ -19,13 +19,13 @@ LL | ty: &'a mut bool,
= note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/E0204.rs:17:6
+ --> $DIR/E0204.rs:17:15
|
LL | Bar { x: Vec<u32> },
| ----------- this field does not implement `Copy`
...
LL | impl Copy for EFoo { }
- | ^^^^
+ | ^^^^
error[E0204]: the trait `Copy` may not be implemented for this type
--> $DIR/E0204.rs:19:10
diff --git a/src/test/ui/span/E0493.rs b/src/test/ui/span/E0493.rs
index ad4100205..625da25a7 100644
--- a/src/test/ui/span/E0493.rs
+++ b/src/test/ui/span/E0493.rs
@@ -15,7 +15,7 @@ impl Drop for Bar {
}
const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
-//~^ destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
fn main() {
}
diff --git a/src/test/ui/span/E0493.stderr b/src/test/ui/span/E0493.stderr
index 29d1b0009..9db627562 100644
--- a/src/test/ui/span/E0493.stderr
+++ b/src/test/ui/span/E0493.stderr
@@ -1,10 +1,10 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(Foo, Foo)` cannot be evaluated at compile-time
--> $DIR/E0493.rs:17:17
|
LL | const F : Foo = (Foo { a : 0 }, Foo { a : 1 }).1;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
error: aborting due to previous error
diff --git a/src/test/ui/span/E0535.stderr b/src/test/ui/span/E0535.stderr
index f52c3f9f2..b1411bc43 100644
--- a/src/test/ui/span/E0535.stderr
+++ b/src/test/ui/span/E0535.stderr
@@ -3,6 +3,8 @@ error[E0535]: invalid argument
|
LL | #[inline(unknown)]
| ^^^^^^^
+ |
+ = help: valid inline arguments are `always` and `never`
error: aborting due to previous error
diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
index 94f578af2..4559da91e 100644
--- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
+++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
@@ -12,7 +12,6 @@ impl A {
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 mismatched types
//~| 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]
diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
index 3814c568e..df1cafdb7 100644
--- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
+++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -1,5 +1,5 @@
error: this file contains an unclosed delimiter
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53
+ --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
|
LL | trait C{async fn new(val: T) {}
| - unclosed delimiter
@@ -25,12 +25,6 @@ LL | trait C{async fn new(val: T) {}
= help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide
-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
-
error[E0412]: cannot find type `T` in this scope
--> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:27
|
@@ -51,7 +45,13 @@ LL | trait C{async fn new(val: T) {}
= 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(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+ = 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
@@ -67,27 +67,13 @@ LL | | crate(move || {} ).await
LL | | }
| |_____^
|
- = note: requested on the command line with `-W rust-2021-incompatible-closure-captures`
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/disjoint-capture-in-closures.html>
+ = 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;
| ++++++++++++++
-error[E0308]: mismatched types
- --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
- |
-LL | trait C{async fn new(val: T) {}
- | ^^ expected associated type, found opaque type
- |
- ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
- |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
- | ------------------------------- the found opaque type
- |
- = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>)
- found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
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
|
@@ -103,7 +89,7 @@ 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 7 previous errors; 2 warnings emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
-Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0412, E0423, E0670, E0706.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/span/issue-7575.rs b/src/test/ui/span/issue-7575.rs
deleted file mode 100644
index eddd158ae..000000000
--- a/src/test/ui/span/issue-7575.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-// Test the mechanism for warning about possible missing `self` declarations.
-trait CtxtFn {
- fn f8(self, _: usize) -> usize;
- fn f9(_: usize) -> usize;
-}
-
-trait OtherTrait {
- fn f9(_: usize) -> usize;
-}
-
-// Note: this trait is not implemented, but we can't really tell
-// whether or not an impl would match anyhow without a self
-// declaration to match against, so we wind up prisizeing it as a
-// candidate. This seems not unreasonable -- perhaps the user meant to
-// implement it, after all.
-trait UnusedTrait {
- fn f9(_: usize) -> usize;
-}
-
-impl CtxtFn for usize {
- fn f8(self, i: usize) -> usize {
- i * 4
- }
-
- fn f9(i: usize) -> usize {
- i * 4
- }
-}
-
-impl OtherTrait for usize {
- fn f9(i: usize) -> usize {
- i * 8
- }
-}
-
-struct Myisize(isize);
-
-impl Myisize {
- fn fff(i: isize) -> isize {
- i
- }
-}
-
-trait ManyImplTrait {
- fn is_str() -> bool {
- false
- }
-}
-
-impl ManyImplTrait for String {
- fn is_str() -> bool {
- true
- }
-}
-
-impl ManyImplTrait for usize {}
-impl ManyImplTrait for isize {}
-impl ManyImplTrait for char {}
-impl ManyImplTrait for Myisize {}
-
-fn no_param_bound(u: usize, m: Myisize) -> usize {
- u.f8(42) + u.f9(342) + m.fff(42)
- //~^ ERROR no method named `f9` found
- //~| ERROR no method named `fff` found
-
-
-}
-
-fn param_bound<T: ManyImplTrait>(t: T) -> bool {
- t.is_str()
- //~^ ERROR no method named `is_str` found
-}
-
-fn main() {
-}
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
deleted file mode 100644
index 4f30edb3f..000000000
--- a/src/test/ui/span/issue-7575.stderr
+++ /dev/null
@@ -1,82 +0,0 @@
-error[E0599]: no method named `f9` found for type `usize` in the current scope
- --> $DIR/issue-7575.rs:62:18
- |
-LL | u.f8(42) + u.f9(342) + m.fff(42)
- | ^^ this is an associated function, not a method
- |
- = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-note: candidate #1 is defined in the trait `CtxtFn`
- --> $DIR/issue-7575.rs:4:5
- |
-LL | fn f9(_: usize) -> usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: candidate #2 is defined in the trait `OtherTrait`
- --> $DIR/issue-7575.rs:8:5
- |
-LL | fn f9(_: usize) -> usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: candidate #3 is defined in the trait `UnusedTrait`
- --> $DIR/issue-7575.rs:17:5
- |
-LL | fn f9(_: usize) -> usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: items from traits can only be used if the trait is implemented and in scope
- = note: the following traits define an item `f9`, perhaps you need to implement one of them:
- candidate #1: `CtxtFn`
- candidate #2: `OtherTrait`
- candidate #3: `UnusedTrait`
-help: disambiguate the associated function for candidate #1
- |
-LL | u.f8(42) + <usize as CtxtFn>::f9(u, 342) + m.fff(42)
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #2
- |
-LL | u.f8(42) + <usize as OtherTrait>::f9(u, 342) + m.fff(42)
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-help: disambiguate the associated function for candidate #3
- |
-LL | u.f8(42) + <usize as UnusedTrait>::f9(u, 342) + m.fff(42)
- | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-error[E0599]: no method named `fff` found for struct `Myisize` in the current scope
- --> $DIR/issue-7575.rs:62:30
- |
-LL | struct Myisize(isize);
- | -------------- method `fff` not found for this struct
-...
-LL | u.f8(42) + u.f9(342) + m.fff(42)
- | --^^^
- | | |
- | | this is an associated function, not a method
- | help: use associated function syntax instead: `Myisize::fff`
- |
- = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-note: the candidate is defined in an impl for the type `Myisize`
- --> $DIR/issue-7575.rs:39:5
- |
-LL | fn fff(i: isize) -> isize {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0599]: no method named `is_str` found for type parameter `T` in the current scope
- --> $DIR/issue-7575.rs:70:7
- |
-LL | fn param_bound<T: ManyImplTrait>(t: T) -> bool {
- | - method `is_str` not found for this type parameter
-LL | t.is_str()
- | ^^^^^^ this is an associated function, not a method
- |
- = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
-note: the candidate is defined in the trait `ManyImplTrait`
- --> $DIR/issue-7575.rs:45:5
- |
-LL | fn is_str() -> bool {
- | ^^^^^^^^^^^^^^^^^^^
- = help: items from traits can only be used if the type parameter is bounded by the trait
-help: disambiguate the associated function for the candidate
- |
-LL | <T as ManyImplTrait>::is_str(t)
- |
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
index 79b13f45f..fc2f6e662 100644
--- a/src/test/ui/span/multiline-span-E0072.stderr
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -3,12 +3,12 @@ error[E0072]: recursive type `ListNode` has infinite size
|
LL | / struct
LL | | ListNode
- | |________^ recursive type has infinite size
+ | |________^
...
LL | tail: Option<ListNode>,
- | ---------------- recursive without indirection
+ | -------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | tail: Option<Box<ListNode>>,
| ++++ +
diff --git a/src/test/ui/span/recursive-type-field.rs b/src/test/ui/span/recursive-type-field.rs
index 58ea81b83..bd4c43534 100644
--- a/src/test/ui/span/recursive-type-field.rs
+++ b/src/test/ui/span/recursive-type-field.rs
@@ -1,11 +1,11 @@
use std::rc::Rc;
-struct Foo<'a> { //~ ERROR recursive type
+struct Foo<'a> { //~ ERROR recursive types `Foo` and `Bar` have infinite size
bar: Bar<'a>,
b: Rc<Bar<'a>>,
}
-struct Bar<'a> { //~ ERROR recursive type
+struct Bar<'a> {
y: (Foo<'a>, Foo<'a>),
z: Option<Bar<'a>>,
a: &'a Foo<'a>,
diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr
index 08e97e750..10af4c36b 100644
--- a/src/test/ui/span/recursive-type-field.stderr
+++ b/src/test/ui/span/recursive-type-field.stderr
@@ -1,35 +1,27 @@
-error[E0072]: recursive type `Foo` has infinite size
+error[E0072]: recursive types `Foo` and `Bar` have infinite size
--> $DIR/recursive-type-field.rs:3:1
|
LL | struct Foo<'a> {
- | ^^^^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^^^^
LL | bar: Bar<'a>,
| ------- recursive without indirection
+...
+LL | struct Bar<'a> {
+ | ^^^^^^^^^^^^^^
+LL | y: (Foo<'a>, Foo<'a>),
+ | ------- ------- recursive without indirection
+ | |
+ | recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
- |
-LL | bar: Box<Bar<'a>>,
- | ++++ +
-
-error[E0072]: recursive type `Bar` has infinite size
- --> $DIR/recursive-type-field.rs:8:1
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
+LL ~ bar: Box<Bar<'a>>,
+LL | b: Rc<Bar<'a>>,
+ ...
LL | struct Bar<'a> {
- | ^^^^^^^^^^^^^^ recursive type has infinite size
-LL | y: (Foo<'a>, Foo<'a>),
- | ------------------ recursive without indirection
-LL | z: Option<Bar<'a>>,
- | --------------- recursive without indirection
-...
-LL | d: [Bar<'a>; 1],
- | ------------ recursive without indirection
-LL | e: Foo<'a>,
- | ------- recursive without indirection
-LL | x: Bar<'a>,
- | ------- recursive without indirection
+LL ~ y: (Box<Foo<'a>>, Box<Foo<'a>>),
|
- = help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
-error: aborting due to 2 previous errors
+error: aborting due to previous error
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.stderr b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
index 17da34caa..f5529c24d 100644
--- a/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
+++ b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/const_trait_impl.rs b/src/test/ui/specialization/const_trait_impl.rs
new file mode 100644
index 000000000..05ba4c8d4
--- /dev/null
+++ b/src/test/ui/specialization/const_trait_impl.rs
@@ -0,0 +1,55 @@
+// check-pass
+#![feature(const_trait_impl, min_specialization, rustc_attrs)]
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub unsafe trait Sup {
+ fn foo() -> u32;
+}
+
+#[rustc_specialization_trait]
+#[const_trait]
+pub unsafe trait Sub: ~const Sup {}
+
+unsafe impl const Sup for u8 {
+ default fn foo() -> u32 {
+ 1
+ }
+}
+
+unsafe impl const Sup for () {
+ fn foo() -> u32 {
+ 42
+ }
+}
+
+unsafe impl const Sub for () {}
+
+#[const_trait]
+pub trait A {
+ fn a() -> u32;
+}
+
+impl<T: ~const Default> const A for T {
+ default fn a() -> u32 {
+ 2
+ }
+}
+
+impl<T: ~const Default + ~const Sup> const A for T {
+ default fn a() -> u32 {
+ 3
+ }
+}
+
+impl<T: ~const Default + ~const Sub> const A for T {
+ fn a() -> u32 {
+ T::foo()
+ }
+}
+
+const _: () = assert!(<()>::a() == 42);
+const _: () = assert!(<u8>::a() == 3);
+const _: () = assert!(<u16>::a() == 2);
+
+fn main() {}
diff --git a/src/test/ui/specialization/cross-crate-defaults.stderr b/src/test/ui/specialization/cross-crate-defaults.stderr
index e368c2e73..ee5c77a76 100644
--- a/src/test/ui/specialization/cross-crate-defaults.stderr
+++ b/src/test/ui/specialization/cross-crate-defaults.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/default-associated-type-bound-1.stderr b/src/test/ui/specialization/default-associated-type-bound-1.stderr
index af9f2f7c2..e498187c0 100644
--- a/src/test/ui/specialization/default-associated-type-bound-1.stderr
+++ b/src/test/ui/specialization/default-associated-type-bound-1.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `str: Clone` is not satisfied
--> $DIR/default-associated-type-bound-1.rs:18:22
diff --git a/src/test/ui/specialization/default-associated-type-bound-2.stderr b/src/test/ui/specialization/default-associated-type-bound-2.stderr
index 91778ed0f..4dbe251ed 100644
--- a/src/test/ui/specialization/default-associated-type-bound-2.stderr
+++ b/src/test/ui/specialization/default-associated-type-bound-2.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: can't compare `&'static B` with `B`
--> $DIR/default-associated-type-bound-2.rs:16:22
diff --git a/src/test/ui/specialization/default-generic-associated-type-bound.stderr b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
index 44c24c1e5..c597eed37 100644
--- a/src/test/ui/specialization/default-generic-associated-type-bound.stderr
+++ b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: can't compare `T` with `T`
--> $DIR/default-generic-associated-type-bound.rs:17:26
diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
index d8b9c48c7..02f13d461 100644
--- a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
+++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.stderr b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
index 9ca915686..2cf1ac909 100644
--- a/src/test/ui/specialization/defaultimpl/out-of-order.stderr
+++ b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.stderr b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
index 31d0e6e38..75fdfafd9 100644
--- a/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
+++ b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/defaultimpl/projection.stderr b/src/test/ui/specialization/defaultimpl/projection.stderr
index 2d5c80d05..cc3fe8237 100644
--- a/src/test/ui/specialization/defaultimpl/projection.stderr
+++ b/src/test/ui/specialization/defaultimpl/projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
index 360b7bc78..770be2af2 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
--> $DIR/specialization-no-default.rs:20:5
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
index 163c93550..407c1ab77 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
index 250f0017b..f19975060 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0046]: not all trait items implemented, missing: `foo_two`
--> $DIR/specialization-trait-item-not-implemented.rs:18:1
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index d1004a690..33ca7a2c2 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait bounds were not satisfied
--> $DIR/specialization-trait-not-implemented.rs:22:29
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
index a8fdbc528..e78016034 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `U: Eq` is not satisfied
--> $DIR/specialization-wfcheck.rs:7:17
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
index cbf0cef5e..eb6dc9355 100644
--- a/src/test/ui/specialization/defaultimpl/validation.stderr
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -14,9 +14,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error: impls of auto traits cannot be default
--> $DIR/validation.rs:9:21
diff --git a/src/test/ui/specialization/issue-35376.stderr b/src/test/ui/specialization/issue-35376.stderr
index 835277d40..6c4167f3f 100644
--- a/src/test/ui/specialization/issue-35376.stderr
+++ b/src/test/ui/specialization/issue-35376.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/issue-36804.stderr b/src/test/ui/specialization/issue-36804.stderr
index 783a38e6b..c2113b25f 100644
--- a/src/test/ui/specialization/issue-36804.stderr
+++ b/src/test/ui/specialization/issue-36804.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr
index 146a56358..117fb10bb 100644
--- a/src/test/ui/specialization/issue-38091-2.stderr
+++ b/src/test/ui/specialization/issue-38091-2.stderr
@@ -4,13 +4,13 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0275]: overflow evaluating the requirement `i32: Check`
|
-note: required for `i32` to implement `Iterate`
+note: required for `i32` to implement `Iterate<'_>`
--> $DIR/issue-38091-2.rs:11:13
|
LL | impl<'a, T> Iterate<'a> for T
diff --git a/src/test/ui/specialization/issue-38091.stderr b/src/test/ui/specialization/issue-38091.stderr
index cc5536c9e..f2210a407 100644
--- a/src/test/ui/specialization/issue-38091.stderr
+++ b/src/test/ui/specialization/issue-38091.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the trait bound `(): Valid` is not satisfied
--> $DIR/issue-38091.rs:12:23
diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr
index 9b74f684b..60157d9a3 100644
--- a/src/test/ui/specialization/issue-39448.stderr
+++ b/src/test/ui/specialization/issue-39448.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0275]: overflow evaluating the requirement `T: FromA<U>`
--> $DIR/issue-39448.rs:45:13
diff --git a/src/test/ui/specialization/issue-39618.stderr b/src/test/ui/specialization/issue-39618.stderr
index 77a45806e..19de60c7c 100644
--- a/src/test/ui/specialization/issue-39618.stderr
+++ b/src/test/ui/specialization/issue-39618.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/issue-50452-fail.stderr b/src/test/ui/specialization/issue-50452-fail.stderr
index 7249ad738..5c136adc4 100644
--- a/src/test/ui/specialization/issue-50452-fail.stderr
+++ b/src/test/ui/specialization/issue-50452-fail.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
--> $DIR/issue-50452-fail.rs:10:5
diff --git a/src/test/ui/specialization/issue-50452.stderr b/src/test/ui/specialization/issue-50452.stderr
index 2f05c4134..48cab9dcd 100644
--- a/src/test/ui/specialization/issue-50452.stderr
+++ b/src/test/ui/specialization/issue-50452.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
index 6d24997a5..c263fe467 100644
--- a/src/test/ui/specialization/issue-52050.stderr
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`
--> $DIR/issue-52050.rs:28:1
diff --git a/src/test/ui/specialization/issue-63716-parse-async.stderr b/src/test/ui/specialization/issue-63716-parse-async.stderr
index cde17872d..a00572da8 100644
--- a/src/test/ui/specialization/issue-63716-parse-async.stderr
+++ b/src/test/ui/specialization/issue-63716-parse-async.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/issue-70442.stderr b/src/test/ui/specialization/issue-70442.stderr
index 5ee82e991..aa72c3286 100644
--- a/src/test/ui/specialization/issue-70442.stderr
+++ b/src/test/ui/specialization/issue-70442.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr
index 8b7d67972..faa14555a 100644
--- a/src/test/ui/specialization/non-defaulted-item-fail.stderr
+++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization, associated_type_defaults)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
--> $DIR/non-defaulted-item-fail.rs:30:5
diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.stderr b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
index 9605bd089..3eea4a53b 100644
--- a/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
+++ b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-assoc-fns.stderr b/src/test/ui/specialization/specialization-assoc-fns.stderr
index a7c0661a8..69f7cece7 100644
--- a/src/test/ui/specialization/specialization-assoc-fns.stderr
+++ b/src/test/ui/specialization/specialization-assoc-fns.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-basics.stderr b/src/test/ui/specialization/specialization-basics.stderr
index afb2af380..7714d4af4 100644
--- a/src/test/ui/specialization/specialization-basics.stderr
+++ b/src/test/ui/specialization/specialization-basics.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-cross-crate.stderr b/src/test/ui/specialization/specialization-cross-crate.stderr
index c69130c0a..06818bb56 100644
--- a/src/test/ui/specialization/specialization-cross-crate.stderr
+++ b/src/test/ui/specialization/specialization-cross-crate.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-default-methods.stderr b/src/test/ui/specialization/specialization-default-methods.stderr
index ef6365ed3..d78d30bd8 100644
--- a/src/test/ui/specialization/specialization-default-methods.stderr
+++ b/src/test/ui/specialization/specialization-default-methods.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr
index 7a2b75a1c..b8b81876d 100644
--- a/src/test/ui/specialization/specialization-default-projection.stderr
+++ b/src/test/ui/specialization/specialization-default-projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/specialization-default-projection.rs:21:5
diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr
index 5ba38face..61a556a93 100644
--- a/src/test/ui/specialization/specialization-default-types.stderr
+++ b/src/test/ui/specialization/specialization-default-types.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0308]: mismatched types
--> $DIR/specialization-default-types.rs:15:9
diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr
index 28c869a70..842cec9c7 100644
--- a/src/test/ui/specialization/specialization-no-default.stderr
+++ b/src/test/ui/specialization/specialization-no-default.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
--> $DIR/specialization-no-default.rs:20:5
diff --git a/src/test/ui/specialization/specialization-on-projection.stderr b/src/test/ui/specialization/specialization-on-projection.stderr
index d051ffe0a..00fc7ffc5 100644
--- a/src/test/ui/specialization/specialization-on-projection.stderr
+++ b/src/test/ui/specialization/specialization-on-projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-out-of-order.stderr b/src/test/ui/specialization/specialization-out-of-order.stderr
index 785ec2923..b524e00f0 100644
--- a/src/test/ui/specialization/specialization-out-of-order.stderr
+++ b/src/test/ui/specialization/specialization-out-of-order.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr
index 552b04a60..fb3d9723a 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.stderr
+++ b/src/test/ui/specialization/specialization-overlap-negative.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`:
--> $DIR/specialization-overlap-negative.rs:9:1
diff --git a/src/test/ui/specialization/specialization-overlap-projection.stderr b/src/test/ui/specialization/specialization-overlap-projection.stderr
index c92db7307..708c0817f 100644
--- a/src/test/ui/specialization/specialization-overlap-projection.stderr
+++ b/src/test/ui/specialization/specialization-overlap-projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr
index 3ccbe1616..989264467 100644
--- a/src/test/ui/specialization/specialization-overlap.stderr
+++ b/src/test/ui/specialization/specialization-overlap.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`
--> $DIR/specialization-overlap.rs:5:1
diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr
index be013552f..f287018ba 100644
--- a/src/test/ui/specialization/specialization-polarity.stderr
+++ b/src/test/ui/specialization/specialization-polarity.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`:
--> $DIR/specialization-polarity.rs:10:1
diff --git a/src/test/ui/specialization/specialization-projection-alias.stderr b/src/test/ui/specialization/specialization-projection-alias.stderr
index 6d2bca5d2..c94d9ed07 100644
--- a/src/test/ui/specialization/specialization-projection-alias.stderr
+++ b/src/test/ui/specialization/specialization-projection-alias.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-projection.stderr b/src/test/ui/specialization/specialization-projection.stderr
index 0f1ecf5e3..bfc4e0a0f 100644
--- a/src/test/ui/specialization/specialization-projection.stderr
+++ b/src/test/ui/specialization/specialization-projection.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-supertraits.stderr b/src/test/ui/specialization/specialization-supertraits.stderr
index d32e47a24..e716bc215 100644
--- a/src/test/ui/specialization/specialization-supertraits.stderr
+++ b/src/test/ui/specialization/specialization-supertraits.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
index d30f7af2c..c7aad3c0f 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.stderr b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
index 1762248f6..1c4fd9325 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
+++ b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/specialization-translate-projections.stderr b/src/test/ui/specialization/specialization-translate-projections.stderr
index 94a0e79dd..22bbb12a0 100644
--- a/src/test/ui/specialization/specialization-translate-projections.stderr
+++ b/src/test/ui/specialization/specialization-translate-projections.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/specialization/transmute-specialization.stderr b/src/test/ui/specialization/transmute-specialization.stderr
index a0ea72415..b1c26d7da 100644
--- a/src/test/ui/specialization/transmute-specialization.stderr
+++ b/src/test/ui/specialization/transmute-specialization.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs
index d89886af3..6eff899bf 100644
--- a/src/test/ui/stability-attribute/missing-const-stability.rs
+++ b/src/test/ui/stability-attribute/missing-const-stability.rs
@@ -19,6 +19,7 @@ impl Foo {
}
#[stable(feature = "stable", since = "1.0.0")]
+#[const_trait]
pub trait Bar {
#[stable(feature = "stable", since = "1.0.0")]
fn fun();
diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr
index 10978728f..4cfbe1528 100644
--- a/src/test/ui/stability-attribute/missing-const-stability.stderr
+++ b/src/test/ui/stability-attribute/missing-const-stability.stderr
@@ -5,7 +5,7 @@ LL | pub const fn foo() {}
| ^^^^^^^^^^^^^^^^^^^^^
error: implementation has missing const stability attribute
- --> $DIR/missing-const-stability.rs:27:1
+ --> $DIR/missing-const-stability.rs:28:1
|
LL | / impl const Bar for Foo {
LL | |
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
index ce2726ffd..0c771ae87 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.rs
@@ -1,4 +1,4 @@
-#![feature(staged_api)]
+#![feature(staged_api, never_type, c_unwind)]
//~^ ERROR module has missing stability attribute
#[stable(feature = "a", since = "1")]
@@ -23,7 +23,21 @@ impl StableTrait for UnstableType {}
impl UnstableTrait for StableType {}
#[unstable(feature = "h", issue = "none")]
+impl StableTrait for ! {}
+
+// Note: If C-unwind is stabilized, switch this to another (unstable) ABI.
+#[unstable(feature = "i", issue = "none")]
+impl StableTrait for extern "C-unwind" fn() {}
+
+#[unstable(feature = "j", issue = "none")]
//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
impl StableTrait for StableType {}
+#[unstable(feature = "k", issue = "none")]
+//~^ ERROR an `#[unstable]` annotation here has no effect [ineffective_unstable_trait_impl]
+impl StableTrait for fn() -> ! {}
+
+#[unstable(feature = "l", issue = "none")]
+impl StableTrait for fn() -> UnstableType {}
+
fn main() {}
diff --git a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
index 310f02024..b91a1d2e1 100644
--- a/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
+++ b/src/test/ui/stability-attribute/stability-attribute-trait-impl.stderr
@@ -1,16 +1,24 @@
error: an `#[unstable]` annotation here has no effect
- --> $DIR/stability-attribute-trait-impl.rs:25:1
+ --> $DIR/stability-attribute-trait-impl.rs:32:1
|
-LL | #[unstable(feature = "h", issue = "none")]
+LL | #[unstable(feature = "j", issue = "none")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
= note: `#[deny(ineffective_unstable_trait_impl)]` on by default
+
+error: an `#[unstable]` annotation here has no effect
+ --> $DIR/stability-attribute-trait-impl.rs:36:1
+ |
+LL | #[unstable(feature = "k", issue = "none")]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
= note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
error: module has missing stability attribute
--> $DIR/stability-attribute-trait-impl.rs:1:1
|
-LL | / #![feature(staged_api)]
+LL | / #![feature(staged_api, never_type, c_unwind)]
LL | |
LL | |
LL | | #[stable(feature = "a", since = "1")]
@@ -19,5 +27,5 @@ LL | |
LL | | fn main() {}
| |____________^
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
diff --git a/src/test/ui/stability-attribute/stable-in-unstable.rs b/src/test/ui/stability-attribute/stable-in-unstable.rs
index 272a1a972..226367c39 100644
--- a/src/test/ui/stability-attribute/stable-in-unstable.rs
+++ b/src/test/ui/stability-attribute/stable-in-unstable.rs
@@ -44,3 +44,11 @@ mod isolated5 {
impl stable_in_unstable_std::old_stable_module::OldTrait for LocalType {}
}
+
+mod isolated6 {
+ use stable_in_unstable_core::new_unstable_module::{OldTrait}; //~ ERROR use of unstable library feature 'unstable_test_feature'
+}
+
+mod isolated7 {
+ use stable_in_unstable_core::new_unstable_module::*; //~ ERROR use of unstable library feature 'unstable_test_feature'
+}
diff --git a/src/test/ui/stability-attribute/stable-in-unstable.stderr b/src/test/ui/stability-attribute/stable-in-unstable.stderr
index e123d8358..b5e3e5f12 100644
--- a/src/test/ui/stability-attribute/stable-in-unstable.stderr
+++ b/src/test/ui/stability-attribute/stable-in-unstable.stderr
@@ -34,6 +34,24 @@ LL | impl stable_in_unstable_core::new_unstable_module::OldTrait for LocalTy
= note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
= help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
-error: aborting due to 4 previous errors
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+ --> $DIR/stable-in-unstable.rs:49:56
+ |
+LL | use stable_in_unstable_core::new_unstable_module::{OldTrait};
+ | ^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+ --> $DIR/stable-in-unstable.rs:53:9
+ |
+LL | use stable_in_unstable_core::new_unstable_module::*;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: see issue #1 <https://github.com/rust-lang/rust/issues/1> for more information
+ = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/static/static-drop-scope.rs b/src/test/ui/static/static-drop-scope.rs
index e7ea8663d..34afa9873 100644
--- a/src/test/ui/static/static-drop-scope.rs
+++ b/src/test/ui/static/static-drop-scope.rs
@@ -5,33 +5,33 @@ impl Drop for WithDtor {
}
static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
//~| ERROR temporary value dropped while borrowed
const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
//~| ERROR temporary value dropped while borrowed
static EARLY_DROP_S: i32 = (WithDtor, 0).1;
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
const EARLY_DROP_C: i32 = (WithDtor, 0).1;
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
const fn const_drop<T>(_: T) {}
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
const fn const_drop2<T>(x: T) {
(x, ()).1
- //~^ ERROR destructors cannot be evaluated at compile-time
+ //~^ ERROR destructor of
}
const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
const HELPER: Option<WithDtor> = Some(WithDtor);
const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
-//~^ ERROR destructors cannot be evaluated at compile-time
+//~^ ERROR destructor of
fn main () {}
diff --git a/src/test/ui/static/static-drop-scope.stderr b/src/test/ui/static/static-drop-scope.stderr
index ac32f217f..112bfc003 100644
--- a/src/test/ui/static/static-drop-scope.stderr
+++ b/src/test/ui/static/static-drop-scope.stderr
@@ -1,10 +1,10 @@
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:7:60
|
LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
| ^^^^^^^^- value is dropped here
| |
- | statics cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in statics
error[E0716]: temporary value dropped while borrowed
--> $DIR/static-drop-scope.rs:7:60
@@ -16,13 +16,13 @@ LL | static PROMOTION_FAIL_S: Option<&'static WithDtor> = Some(&WithDtor);
| | creates a temporary which is freed while still in use
| using this value as a static requires that borrow lasts for `'static`
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `WithDtor` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:11:59
|
LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
| ^^^^^^^^- value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
error[E0716]: temporary value dropped while borrowed
--> $DIR/static-drop-scope.rs:11:59
@@ -34,54 +34,54 @@ LL | const PROMOTION_FAIL_C: Option<&'static WithDtor> = Some(&WithDtor);
| | creates a temporary which is freed while still in use
| using this value as a constant requires that borrow lasts for `'static`
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:15:28
|
LL | static EARLY_DROP_S: i32 = (WithDtor, 0).1;
| ^^^^^^^^^^^^^ - value is dropped here
| |
- | statics cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in statics
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(WithDtor, i32)` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:18:27
|
LL | const EARLY_DROP_C: i32 = (WithDtor, 0).1;
| ^^^^^^^^^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `T` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:21:24
|
LL | const fn const_drop<T>(_: T) {}
| ^ - value is dropped here
| |
- | constant functions cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constant functions
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(T, ())` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:25:5
|
LL | (x, ()).1
- | ^^^^^^^ constant functions cannot evaluate destructors
+ | ^^^^^^^ the destructor for this type cannot be evaluated in constant functions
LL |
LL | }
| - value is dropped here
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:29:34
|
LL | const EARLY_DROP_C_OPTION: i32 = (Some(WithDtor), 0).1;
| ^^^^^^^^^^^^^^^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
-error[E0493]: destructors cannot be evaluated at compile-time
+error[E0493]: destructor of `(Option<WithDtor>, i32)` cannot be evaluated at compile-time
--> $DIR/static-drop-scope.rs:34:43
|
LL | const EARLY_DROP_C_OPTION_CONSTANT: i32 = (HELPER, 0).1;
| ^^^^^^^^^^^ - value is dropped here
| |
- | constants cannot evaluate destructors
+ | the destructor for this type cannot be evaluated in constants
error: aborting due to 10 previous errors
diff --git a/src/test/ui/issues/issue-17718-static-sync.rs b/src/test/ui/statics/issue-17718-static-sync.rs
index 6f278d76b..6f278d76b 100644
--- a/src/test/ui/issues/issue-17718-static-sync.rs
+++ b/src/test/ui/statics/issue-17718-static-sync.rs
diff --git a/src/test/ui/issues/issue-17718-static-sync.stderr b/src/test/ui/statics/issue-17718-static-sync.stderr
index bc6e45e59..bc6e45e59 100644
--- a/src/test/ui/issues/issue-17718-static-sync.stderr
+++ b/src/test/ui/statics/issue-17718-static-sync.stderr
diff --git a/src/test/ui/issues/issue-17718-static-unsafe-interior.rs b/src/test/ui/statics/issue-17718-static-unsafe-interior.rs
index 65a8713ba..65a8713ba 100644
--- a/src/test/ui/issues/issue-17718-static-unsafe-interior.rs
+++ b/src/test/ui/statics/issue-17718-static-unsafe-interior.rs
diff --git a/src/test/ui/statics/uninhabited-static.stderr b/src/test/ui/statics/uninhabited-static.stderr
index 88ee4cbdc..ef794bb36 100644
--- a/src/test/ui/statics/uninhabited-static.stderr
+++ b/src/test/ui/statics/uninhabited-static.stderr
@@ -4,14 +4,14 @@ error: static of uninhabited type
LL | static VOID: Void;
| ^^^^^^^^^^^^^^^^^
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
+ = note: uninhabited statics cannot be initialized, and any access would be an immediate error
note: the lint level is defined here
--> $DIR/uninhabited-static.rs:2:9
|
LL | #![deny(uninhabited_static)]
| ^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
- = note: uninhabited statics cannot be initialized, and any access would be an immediate error
error: static of uninhabited type
--> $DIR/uninhabited-static.rs:8:5
@@ -58,8 +58,12 @@ LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
+note: enums with no inhabited variants have no valid value
+ --> $DIR/uninhabited-static.rs:4:1
+ |
+LL | enum Void {}
+ | ^^^^^^^^^
= note: `#[warn(invalid_value)]` on by default
- = note: enums with no variants have no valid value
error[E0080]: could not evaluate static initializer
--> $DIR/uninhabited-static.rs:16:32
@@ -76,7 +80,11 @@ LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
| this code causes undefined behavior when executed
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
|
- = note: enums with no variants have no valid value
+note: enums with no inhabited variants have no valid value
+ --> $DIR/uninhabited-static.rs:4:1
+ |
+LL | enum Void {}
+ | ^^^^^^^^^
error: aborting due to 6 previous errors; 2 warnings emitted
diff --git a/src/test/ui/stats/hir-stats.rs b/src/test/ui/stats/hir-stats.rs
index 5102574d4..a24b3ada5 100644
--- a/src/test/ui/stats/hir-stats.rs
+++ b/src/test/ui/stats/hir-stats.rs
@@ -1,7 +1,6 @@
// check-pass
// compile-flags: -Zhir-stats
// only-x86_64
-// ignore-stage1
// 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/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 8d9776065..1521b692a 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -26,7 +26,7 @@ ast-stats-1 Block 288 ( 3.4%) 6 48
ast-stats-1 GenericBound 352 ( 4.2%) 4 88
ast-stats-1 - Trait 352 ( 4.2%) 4
ast-stats-1 AssocItem 416 ( 4.9%) 4 104
-ast-stats-1 - TyAlias 208 ( 2.5%) 2
+ast-stats-1 - Type 208 ( 2.5%) 2
ast-stats-1 - Fn 208 ( 2.5%) 2
ast-stats-1 GenericParam 480 ( 5.7%) 5 96
ast-stats-1 PathSegment 720 ( 8.6%) 30 24
@@ -84,7 +84,7 @@ ast-stats-2 Block 288 ( 3.1%) 6 48
ast-stats-2 GenericBound 352 ( 3.8%) 4 88
ast-stats-2 - Trait 352 ( 3.8%) 4
ast-stats-2 AssocItem 416 ( 4.5%) 4 104
-ast-stats-2 - TyAlias 208 ( 2.3%) 2
+ast-stats-2 - Type 208 ( 2.3%) 2
ast-stats-2 - Fn 208 ( 2.3%) 2
ast-stats-2 GenericParam 480 ( 5.2%) 5 96
ast-stats-2 PathSegment 792 ( 8.7%) 33 24
@@ -118,61 +118,61 @@ ast-stats-2
hir-stats HIR STATS
hir-stats Name Accumulated Size Count Item Size
hir-stats ----------------------------------------------------------------
-hir-stats ForeignItemRef 24 ( 0.2%) 1 24
-hir-stats Lifetime 32 ( 0.3%) 1 32
-hir-stats Mod 32 ( 0.3%) 1 32
+hir-stats ForeignItemRef 24 ( 0.3%) 1 24
+hir-stats Lifetime 32 ( 0.4%) 1 32
+hir-stats Mod 32 ( 0.4%) 1 32
hir-stats ExprField 40 ( 0.4%) 1 40
hir-stats TraitItemRef 56 ( 0.6%) 2 28
hir-stats Local 64 ( 0.7%) 1 64
hir-stats Param 64 ( 0.7%) 2 32
-hir-stats InlineAsm 72 ( 0.7%) 1 72
-hir-stats ImplItemRef 72 ( 0.7%) 2 36
-hir-stats Body 96 ( 1.0%) 3 32
-hir-stats GenericArg 96 ( 1.0%) 4 24
-hir-stats - Type 24 ( 0.2%) 1
-hir-stats - Lifetime 72 ( 0.7%) 3
-hir-stats FieldDef 96 ( 1.0%) 2 48
-hir-stats Arm 96 ( 1.0%) 2 48
-hir-stats Stmt 96 ( 1.0%) 3 32
-hir-stats - Local 32 ( 0.3%) 1
-hir-stats - Semi 32 ( 0.3%) 1
-hir-stats - Expr 32 ( 0.3%) 1
-hir-stats FnDecl 120 ( 1.2%) 3 40
-hir-stats Attribute 128 ( 1.3%) 4 32
-hir-stats GenericArgs 144 ( 1.5%) 3 48
-hir-stats Variant 160 ( 1.7%) 2 80
-hir-stats WherePredicate 168 ( 1.7%) 3 56
-hir-stats - BoundPredicate 168 ( 1.7%) 3
-hir-stats GenericBound 192 ( 2.0%) 4 48
-hir-stats - Trait 192 ( 2.0%) 4
-hir-stats Block 288 ( 3.0%) 6 48
-hir-stats Pat 360 ( 3.7%) 5 72
-hir-stats - Wild 72 ( 0.7%) 1
-hir-stats - Struct 72 ( 0.7%) 1
-hir-stats - Binding 216 ( 2.2%) 3
-hir-stats GenericParam 400 ( 4.1%) 5 80
-hir-stats Generics 560 ( 5.8%) 10 56
-hir-stats Ty 720 ( 7.4%) 15 48
+hir-stats InlineAsm 72 ( 0.8%) 1 72
+hir-stats ImplItemRef 72 ( 0.8%) 2 36
+hir-stats Body 96 ( 1.1%) 3 32
+hir-stats GenericArg 96 ( 1.1%) 4 24
+hir-stats - Type 24 ( 0.3%) 1
+hir-stats - Lifetime 72 ( 0.8%) 3
+hir-stats FieldDef 96 ( 1.1%) 2 48
+hir-stats Arm 96 ( 1.1%) 2 48
+hir-stats Stmt 96 ( 1.1%) 3 32
+hir-stats - Local 32 ( 0.4%) 1
+hir-stats - Semi 32 ( 0.4%) 1
+hir-stats - Expr 32 ( 0.4%) 1
+hir-stats FnDecl 120 ( 1.3%) 3 40
+hir-stats Attribute 128 ( 1.4%) 4 32
+hir-stats GenericArgs 144 ( 1.6%) 3 48
+hir-stats Variant 160 ( 1.8%) 2 80
+hir-stats GenericBound 192 ( 2.1%) 4 48
+hir-stats - Trait 192 ( 2.1%) 4
+hir-stats WherePredicate 192 ( 2.1%) 3 64
+hir-stats - BoundPredicate 192 ( 2.1%) 3
+hir-stats Block 288 ( 3.2%) 6 48
+hir-stats Pat 360 ( 3.9%) 5 72
+hir-stats - Wild 72 ( 0.8%) 1
+hir-stats - Struct 72 ( 0.8%) 1
+hir-stats - Binding 216 ( 2.4%) 3
+hir-stats GenericParam 400 ( 4.4%) 5 80
+hir-stats Generics 560 ( 6.1%) 10 56
+hir-stats Ty 720 ( 7.9%) 15 48
hir-stats - Ptr 48 ( 0.5%) 1
hir-stats - Rptr 48 ( 0.5%) 1
-hir-stats - Path 624 ( 6.4%) 13
-hir-stats Expr 768 ( 7.9%) 12 64
+hir-stats - Path 624 ( 6.8%) 13
+hir-stats Expr 768 ( 8.4%) 12 64
hir-stats - Path 64 ( 0.7%) 1
hir-stats - Struct 64 ( 0.7%) 1
hir-stats - Match 64 ( 0.7%) 1
hir-stats - InlineAsm 64 ( 0.7%) 1
-hir-stats - Lit 128 ( 1.3%) 2
-hir-stats - Block 384 ( 4.0%) 6
-hir-stats Item 960 ( 9.9%) 12 80
-hir-stats - Trait 80 ( 0.8%) 1
-hir-stats - Enum 80 ( 0.8%) 1
-hir-stats - ExternCrate 80 ( 0.8%) 1
-hir-stats - ForeignMod 80 ( 0.8%) 1
-hir-stats - Impl 80 ( 0.8%) 1
-hir-stats - Fn 160 ( 1.7%) 2
-hir-stats - Use 400 ( 4.1%) 5
-hir-stats Path 1_536 (15.9%) 32 48
-hir-stats PathSegment 2_240 (23.1%) 40 56
+hir-stats - Lit 128 ( 1.4%) 2
+hir-stats - Block 384 ( 4.2%) 6
+hir-stats Item 960 (10.5%) 12 80
+hir-stats - Trait 80 ( 0.9%) 1
+hir-stats - Enum 80 ( 0.9%) 1
+hir-stats - ExternCrate 80 ( 0.9%) 1
+hir-stats - ForeignMod 80 ( 0.9%) 1
+hir-stats - Impl 80 ( 0.9%) 1
+hir-stats - Fn 160 ( 1.8%) 2
+hir-stats - Use 400 ( 4.4%) 5
+hir-stats Path 1_280 (14.0%) 32 40
+hir-stats PathSegment 1_920 (21.0%) 40 48
hir-stats ----------------------------------------------------------------
-hir-stats Total 9_680
+hir-stats Total 9_128
hir-stats
diff --git a/src/test/ui/std-backtrace.rs b/src/test/ui/std-backtrace.rs
index 3f8306baf..59574b471 100644
--- a/src/test/ui/std-backtrace.rs
+++ b/src/test/ui/std-backtrace.rs
@@ -4,6 +4,7 @@
// ignore-openbsd no support for libbacktrace without filename
// ignore-sgx no processes
// ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
+// ignore-fuchsia Backtraces not symbolized
// compile-flags:-g
// compile-flags:-Cstrip=none
diff --git a/src/test/ui/issues/issue-2718-a.rs b/src/test/ui/structs-enums/issue-2718-a.rs
index 6c4915845..6c4915845 100644
--- a/src/test/ui/issues/issue-2718-a.rs
+++ b/src/test/ui/structs-enums/issue-2718-a.rs
diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/structs-enums/issue-2718-a.stderr
index c6e703f48..7ea620f38 100644
--- a/src/test/ui/issues/issue-2718-a.stderr
+++ b/src/test/ui/structs-enums/issue-2718-a.stderr
@@ -3,10 +3,8 @@ error[E0072]: recursive type `Pong` has infinite size
|
LL | pub struct Pong(SendPacket<Ping>);
| ^^^^^^^^^^^^^^^ ---------------- recursive without indirection
- | |
- | recursive type has infinite size
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Pong` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | pub struct Pong(Box<SendPacket<Ping>>);
| ++++ +
diff --git a/src/test/ui/structs-enums/rec-align-u32.rs b/src/test/ui/structs-enums/rec-align-u32.rs
index 889294daa..ee704198d 100644
--- a/src/test/ui/structs-enums/rec-align-u32.rs
+++ b/src/test/ui/structs-enums/rec-align-u32.rs
@@ -10,6 +10,7 @@ use std::mem;
mod rusti {
extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
+ #[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
}
}
diff --git a/src/test/ui/structs-enums/rec-align-u64.rs b/src/test/ui/structs-enums/rec-align-u64.rs
index 3bc2d16cf..40ede9705 100644
--- a/src/test/ui/structs-enums/rec-align-u64.rs
+++ b/src/test/ui/structs-enums/rec-align-u64.rs
@@ -12,6 +12,7 @@ use std::mem;
mod rusti {
extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
+ #[rustc_safe_intrinsic]
pub fn min_align_of<T>() -> usize;
}
}
diff --git a/src/test/ui/structs-enums/struct-rec/issue-74224.stderr b/src/test/ui/structs-enums/struct-rec/issue-74224.stderr
index 619917846..f1d50bc8a 100644
--- a/src/test/ui/structs-enums/struct-rec/issue-74224.stderr
+++ b/src/test/ui/structs-enums/struct-rec/issue-74224.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `A` has infinite size
--> $DIR/issue-74224.rs:1:1
|
LL | struct A<T> {
- | ^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^
...
LL | y: A<A<T>>,
| ------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `A` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | y: Box<A<A<T>>>,
| ++++ +
diff --git a/src/test/ui/structs-enums/struct-rec/issue-84611.stderr b/src/test/ui/structs-enums/struct-rec/issue-84611.stderr
index 2e99435e0..536f54e3e 100644
--- a/src/test/ui/structs-enums/struct-rec/issue-84611.stderr
+++ b/src/test/ui/structs-enums/struct-rec/issue-84611.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-84611.rs:1:1
|
LL | struct Foo<T> {
- | ^^^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^^^
LL |
LL | x: Foo<[T; 1]>,
| ----------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | x: Box<Foo<[T; 1]>>,
| ++++ +
diff --git a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.rs b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.rs
index cca97f43e..3bfce8b4f 100644
--- a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.rs
+++ b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.rs
@@ -1,22 +1,20 @@
struct A<T> {
-//~^ ERROR recursive type `A` has infinite size
+//~^ ERROR recursive types `A` and `B` have infinite size
x: T,
y: B<T>,
}
struct B<T> {
-//~^ ERROR recursive type `B` has infinite size
z: A<T>
}
struct C<T> {
-//~^ ERROR recursive type `C` has infinite size
+//~^ ERROR recursive types `C` and `D` have infinite size
x: T,
y: Option<Option<D<T>>>,
}
struct D<T> {
-//~^ ERROR recursive type `D` has infinite size
z: Option<Option<C<T>>>,
}
diff --git a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr
index 80a494f3f..881bc2819 100644
--- a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr
+++ b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr
@@ -1,59 +1,49 @@
-error[E0072]: recursive type `A` has infinite size
+error[E0072]: recursive types `A` and `B` have infinite size
--> $DIR/mutual-struct-recursion.rs:1:1
|
LL | struct A<T> {
- | ^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^
...
LL | y: B<T>,
| ---- recursive without indirection
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `A` representable
- |
-LL | y: Box<B<T>>,
- | ++++ +
-
-error[E0072]: recursive type `B` has infinite size
- --> $DIR/mutual-struct-recursion.rs:7:1
- |
+...
LL | struct B<T> {
- | ^^^^^^^^^^^ recursive type has infinite size
-LL |
+ | ^^^^^^^^^^^
LL | z: A<T>
| ---- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `B` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL ~ y: Box<B<T>>,
+LL | }
+LL |
+LL | struct B<T> {
+LL ~ z: Box<A<T>>
|
-LL | z: Box<A<T>>
- | ++++ +
-error[E0072]: recursive type `C` has infinite size
- --> $DIR/mutual-struct-recursion.rs:12:1
+error[E0072]: recursive types `C` and `D` have infinite size
+ --> $DIR/mutual-struct-recursion.rs:11:1
|
LL | struct C<T> {
- | ^^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^^
...
LL | y: Option<Option<D<T>>>,
- | -------------------- recursive without indirection
- |
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `C` representable
- |
-LL | y: Option<Box<Option<D<T>>>>,
- | ++++ +
-
-error[E0072]: recursive type `D` has infinite size
- --> $DIR/mutual-struct-recursion.rs:18:1
- |
+ | ---- recursive without indirection
+...
LL | struct D<T> {
- | ^^^^^^^^^^^ recursive type has infinite size
-LL |
+ | ^^^^^^^^^^^
LL | z: Option<Option<C<T>>>,
- | -------------------- recursive without indirection
+ | ---- recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `D` representable
+LL ~ y: Option<Option<Box<D<T>>>>,
+LL | }
+LL |
+LL | struct D<T> {
+LL ~ z: Option<Option<Box<C<T>>>>,
|
-LL | z: Option<Box<Option<C<T>>>>,
- | ++++ +
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0072`.
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.rs b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
new file mode 100644
index 000000000..cd8a79ba6
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.rs
@@ -0,0 +1,5 @@
+fn main() {}
+
+struct S {
+ fn: u8 //~ ERROR expected identifier, found keyword `fn`
+}
diff --git a/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
new file mode 100644
index 000000000..0d12ba9c9
--- /dev/null
+++ b/src/test/ui/structs/incomplete-fn-in-struct-definition.stderr
@@ -0,0 +1,15 @@
+error: expected identifier, found keyword `fn`
+ --> $DIR/incomplete-fn-in-struct-definition.rs:4:5
+ |
+LL | struct S {
+ | - while parsing this struct
+LL | fn: u8
+ | ^^ expected identifier, found keyword
+ |
+help: escape `fn` to use it as an identifier
+ |
+LL | r#fn: u8
+ | ++
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/structs/struct-fn-in-definition.stderr b/src/test/ui/structs/struct-fn-in-definition.stderr
index 1d7cd5272..472365c6e 100644
--- a/src/test/ui/structs/struct-fn-in-definition.stderr
+++ b/src/test/ui/structs/struct-fn-in-definition.stderr
@@ -1,6 +1,9 @@
error: functions are not allowed in struct definitions
--> $DIR/struct-fn-in-definition.rs:9:5
|
+LL | struct S {
+ | - while parsing this struct
+...
LL | fn foo() {}
| ^^^^^^^^^^^
|
@@ -10,6 +13,9 @@ LL | fn foo() {}
error: functions are not allowed in union definitions
--> $DIR/struct-fn-in-definition.rs:18:5
|
+LL | union U {
+ | - while parsing this union
+...
LL | fn foo() {}
| ^^^^^^^^^^^
|
@@ -19,6 +25,9 @@ LL | fn foo() {}
error: functions are not allowed in enum definitions
--> $DIR/struct-fn-in-definition.rs:27:5
|
+LL | enum E {
+ | - while parsing this enum
+...
LL | fn foo() {}
| ^^^^^^^^^^^
|
diff --git a/src/test/ui/structs/struct-path-associated-type.rs b/src/test/ui/structs/struct-path-associated-type.rs
index f88572f84..2dd7174a9 100644
--- a/src/test/ui/structs/struct-path-associated-type.rs
+++ b/src/test/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 type arguments are not allowed on this type
+ //~| ERROR this 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 type arguments are not allowed on this type
+ let z = T::A::<u8> {}; //~ ERROR this associated type takes 0 generic arguments but 1 generic argument was supplied
match S {
T::A {} => {} // OK
}
diff --git a/src/test/ui/structs/struct-path-associated-type.stderr b/src/test/ui/structs/struct-path-associated-type.stderr
index bdce0e1b3..abb445214 100644
--- a/src/test/ui/structs/struct-path-associated-type.stderr
+++ b/src/test/ui/structs/struct-path-associated-type.stderr
@@ -4,13 +4,19 @@ error[E0071]: expected struct, variant or union type, found associated type
LL | let s = T::A {};
| ^^^^ not a struct
-error[E0109]: type arguments are not allowed on this type
- --> $DIR/struct-path-associated-type.rs:14:20
+error[E0107]: this 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> {};
- | - ^^ type argument not allowed
+ | ^------ help: remove these generics
| |
- | not allowed on this type
+ | expected 0 generic arguments
+ |
+note: associated type defined here, with 0 generic parameters
+ --> $DIR/struct-path-associated-type.rs:4:10
+ |
+LL | type A;
+ | ^
error[E0071]: expected struct, variant or union type, found associated type
--> $DIR/struct-path-associated-type.rs:14:13
@@ -24,13 +30,19 @@ error[E0071]: expected struct, variant or union type, found associated type
LL | T::A {} => {}
| ^^^^ not a struct
-error[E0109]: type arguments are not allowed on this type
- --> $DIR/struct-path-associated-type.rs:25:20
+error[E0107]: this 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> {};
- | - ^^ type argument not allowed
+ | ^------ help: remove these generics
| |
- | not allowed on this type
+ | expected 0 generic arguments
+ |
+note: associated type defined here, with 0 generic parameters
+ --> $DIR/struct-path-associated-type.rs:4:10
+ |
+LL | type A;
+ | ^
error[E0223]: ambiguous associated type
--> $DIR/struct-path-associated-type.rs:32:13
@@ -52,5 +64,5 @@ LL | S::A {} => {}
error: aborting due to 8 previous errors
-Some errors have detailed explanations: E0071, E0109, E0223.
+Some errors have detailed explanations: E0071, E0107, E0223.
For more information about an error, try `rustc --explain E0071`.
diff --git a/src/test/ui/suggestions/abi-typo.fixed b/src/test/ui/suggestions/abi-typo.fixed
new file mode 100644
index 000000000..04d265865
--- /dev/null
+++ b/src/test/ui/suggestions/abi-typo.fixed
@@ -0,0 +1,6 @@
+// run-rustfix
+extern "cdecl" fn cdedl() {} //~ ERROR invalid ABI
+
+fn main() {
+ cdedl();
+}
diff --git a/src/test/ui/suggestions/abi-typo.rs b/src/test/ui/suggestions/abi-typo.rs
new file mode 100644
index 000000000..6d80db522
--- /dev/null
+++ b/src/test/ui/suggestions/abi-typo.rs
@@ -0,0 +1,6 @@
+// run-rustfix
+extern "cdedl" fn cdedl() {} //~ ERROR invalid ABI
+
+fn main() {
+ cdedl();
+}
diff --git a/src/test/ui/suggestions/abi-typo.stderr b/src/test/ui/suggestions/abi-typo.stderr
new file mode 100644
index 000000000..67a84f119
--- /dev/null
+++ b/src/test/ui/suggestions/abi-typo.stderr
@@ -0,0 +1,14 @@
+error[E0703]: invalid ABI: found `cdedl`
+ --> $DIR/abi-typo.rs:2:8
+ |
+LL | extern "cdedl" fn cdedl() {}
+ | ^^^^^^^
+ | |
+ | invalid ABI
+ | help: did you mean: `"cdecl"`
+ |
+ = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0703`.
diff --git a/src/test/ui/suggestions/assoc_fn_without_self.stderr b/src/test/ui/suggestions/assoc_fn_without_self.stderr
index 4a0e62e73..88920b852 100644
--- a/src/test/ui/suggestions/assoc_fn_without_self.stderr
+++ b/src/test/ui/suggestions/assoc_fn_without_self.stderr
@@ -1,10 +1,4 @@
error[E0425]: cannot find function `foo` in this scope
- --> $DIR/assoc_fn_without_self.rs:14:13
- |
-LL | foo();
- | ^^^ not found in this scope
-
-error[E0425]: cannot find function `foo` in this scope
--> $DIR/assoc_fn_without_self.rs:16:9
|
LL | foo();
@@ -32,6 +26,12 @@ help: consider using the associated function
LL | Self::baz(2, 3);
| ~~~~~~~~~
+error[E0425]: cannot find function `foo` in this scope
+ --> $DIR/assoc_fn_without_self.rs:14:13
+ |
+LL | foo();
+ | ^^^ not found in this scope
+
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index bfd506c9f..8ed62f854 100644
--- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -1,9 +1,6 @@
error[E0277]: `fn() -> impl Future<Output = ()> {foo}` is not a future
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:10:9
|
-LL | async fn foo() {}
- | --- consider calling this function
-...
LL | bar(foo);
| --- ^^^ `fn() -> impl Future<Output = ()> {foo}` is not a future
| |
@@ -16,7 +13,7 @@ note: required by a bound in `bar`
|
LL | fn bar(f: impl Future<Output=()>) {}
| ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the function
+help: use parentheses to call this function
|
LL | bar(foo());
| ++
@@ -24,8 +21,6 @@ LL | bar(foo());
error[E0277]: `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
--> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:12:9
|
-LL | let async_closure = async || ();
- | -------- consider calling this closure
LL | bar(async_closure);
| --- ^^^^^^^^^^^^^ `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` is not a future
| |
@@ -38,7 +33,7 @@ note: required by a bound in `bar`
|
LL | fn bar(f: impl Future<Output=()>) {}
| ^^^^^^^^^^^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the closure
+help: use parentheses to call this closure
|
LL | bar(async_closure());
| ++
diff --git a/src/test/ui/suggestions/boxed-variant-field.rs b/src/test/ui/suggestions/boxed-variant-field.rs
index e79be2f61..6050963c4 100644
--- a/src/test/ui/suggestions/boxed-variant-field.rs
+++ b/src/test/ui/suggestions/boxed-variant-field.rs
@@ -9,7 +9,6 @@ fn foo(x: Ty) -> Ty {
Ty::List(elem) => foo(elem),
//~^ ERROR mismatched types
//~| HELP consider unboxing the value
- //~| HELP try wrapping
}
}
diff --git a/src/test/ui/suggestions/boxed-variant-field.stderr b/src/test/ui/suggestions/boxed-variant-field.stderr
index 6dfb73480..9ae36a06a 100644
--- a/src/test/ui/suggestions/boxed-variant-field.stderr
+++ b/src/test/ui/suggestions/boxed-variant-field.stderr
@@ -17,10 +17,6 @@ help: consider unboxing the value
|
LL | Ty::List(elem) => foo(*elem),
| +
-help: try wrapping the expression in `Ty::List`
- |
-LL | Ty::List(elem) => foo(Ty::List(elem)),
- | +++++++++ +
error: aborting due to previous error
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
new file mode 100644
index 000000000..5f811044e
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
@@ -0,0 +1,17 @@
+fn main() {
+ insert_resource(Marker);
+ insert_resource(Time);
+ //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+ //~| HELP use parentheses to construct this tuple struct
+}
+
+trait Resource {}
+
+fn insert_resource<R: Resource>(resource: R) {}
+
+struct Marker;
+impl Resource for Marker {}
+
+struct Time(u32);
+
+impl Resource for Time {}
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
new file mode 100644
index 000000000..58612cbfb
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+ --> $DIR/call-on-unimplemented-ctor.rs:3:21
+ |
+LL | insert_resource(Time);
+ | --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `insert_resource`
+ --> $DIR/call-on-unimplemented-ctor.rs:10:23
+ |
+LL | fn insert_resource<R: Resource>(resource: R) {}
+ | ^^^^^^^^ required by this bound in `insert_resource`
+help: use parentheses to construct this tuple struct
+ |
+LL | insert_resource(Time(/* u32 */));
+ | +++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs
new file mode 100644
index 000000000..86490c724
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.rs
@@ -0,0 +1,15 @@
+struct Foo;
+
+trait Bar {}
+
+impl Bar for Foo {}
+
+fn needs_bar<T: Bar>(_: T) {}
+
+fn blah(f: fn() -> Foo) {
+ needs_bar(f);
+ //~^ ERROR the trait bound `fn() -> Foo: Bar` is not satisfied
+ //~| HELP use parentheses to call this function pointer
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
new file mode 100644
index 000000000..167f7e592
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-fn-ptr.stderr
@@ -0,0 +1,21 @@
+error[E0277]: the trait bound `fn() -> Foo: Bar` is not satisfied
+ --> $DIR/call-on-unimplemented-fn-ptr.rs:10:15
+ |
+LL | needs_bar(f);
+ | --------- ^ the trait `Bar` is not implemented for `fn() -> Foo`
+ | |
+ | required by a bound introduced by this call
+ |
+note: required by a bound in `needs_bar`
+ --> $DIR/call-on-unimplemented-fn-ptr.rs:7:17
+ |
+LL | fn needs_bar<T: Bar>(_: T) {}
+ | ^^^ required by this bound in `needs_bar`
+help: use parentheses to call this function pointer
+ |
+LL | needs_bar(f());
+ | ++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index fe603b675..955148315 100644
--- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -1,9 +1,6 @@
error[E0277]: the trait bound `fn() -> impl T<O = ()> {foo}: T` is not satisfied
--> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:17:9
|
-LL | fn foo() -> impl T<O=()> { S }
- | --- consider calling this function
-...
LL | bar(foo);
| --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
| |
@@ -14,7 +11,7 @@ note: required by a bound in `bar`
|
LL | fn bar(f: impl T<O=()>) {}
| ^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the function
+help: use parentheses to call this function
|
LL | bar(foo());
| ++
@@ -22,8 +19,6 @@ LL | bar(foo());
error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]: T` is not satisfied
--> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9
|
-LL | let closure = || S;
- | -- consider calling this closure
LL | bar(closure);
| --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
| |
@@ -34,7 +29,7 @@ note: required by a bound in `bar`
|
LL | fn bar(f: impl T<O=()>) {}
| ^^^^^^^ required by this bound in `bar`
-help: use parentheses to call the closure
+help: use parentheses to call this closure
|
LL | bar(closure());
| ++
diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
index 3c7b895e3..597dc61c3 100644
--- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
+++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr
@@ -49,7 +49,7 @@ LL | let _: S = S;
|
= note: expected struct `S`
found fn item `fn(usize, usize) -> S {S}`
-help: use parentheses to instantiate this tuple struct
+help: use parentheses to construct this tuple struct
|
LL | let _: S = S(/* usize */, /* usize */);
| ++++++++++++++++++++++++++
@@ -85,7 +85,7 @@ LL | let _: V = V;
|
= note: expected struct `V`
found fn item `fn() -> V {V}`
-help: use parentheses to instantiate this tuple struct
+help: use parentheses to construct this tuple struct
|
LL | let _: V = V();
| ++
@@ -139,7 +139,7 @@ LL | let _: E = E::A;
|
= note: expected enum `E`
found fn item `fn(usize) -> E {E::A}`
-help: use parentheses to instantiate this tuple variant
+help: use parentheses to construct this tuple variant
|
LL | let _: E = E::A(/* usize */);
| +++++++++++++
@@ -220,7 +220,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:41:20
|
LL | fn ban(&self) -> usize { 42 }
- | ---------------------- for<'r> fn(&'r X) -> usize {<X as T>::ban} defined here
+ | ---------------------- for<'a> fn(&'a X) -> usize {<X as T>::ban} defined here
...
LL | let _: usize = X::ban;
| ----- ^^^^^^ expected `usize`, found fn item
@@ -228,7 +228,7 @@ LL | let _: usize = X::ban;
| expected due to this
|
= note: expected type `usize`
- found fn item `for<'r> fn(&'r X) -> usize {<X as T>::ban}`
+ found fn item `for<'a> fn(&'a X) -> usize {<X as T>::ban}`
help: use parentheses to call this associated function
|
LL | let _: usize = X::ban(/* &X */);
@@ -238,7 +238,7 @@ error[E0308]: mismatched types
--> $DIR/fn-or-tuple-struct-without-args.rs:42:20
|
LL | fn bal(&self) -> usize;
- | ----------------------- for<'r> fn(&'r X) -> usize {<X as T>::bal} defined here
+ | ----------------------- for<'a> fn(&'a X) -> usize {<X as T>::bal} defined here
...
LL | let _: usize = X::bal;
| ----- ^^^^^^ expected `usize`, found fn item
@@ -246,7 +246,7 @@ LL | let _: usize = X::bal;
| expected due to this
|
= note: expected type `usize`
- found fn item `for<'r> fn(&'r X) -> usize {<X as T>::bal}`
+ found fn item `for<'a> fn(&'a X) -> usize {<X as T>::bal}`
help: use parentheses to call this associated function
|
LL | let _: usize = X::bal(/* &X */);
diff --git a/src/test/ui/suggestions/fn-to-method.rs b/src/test/ui/suggestions/fn-to-method.rs
new file mode 100644
index 000000000..9a35c3efc
--- /dev/null
+++ b/src/test/ui/suggestions/fn-to-method.rs
@@ -0,0 +1,19 @@
+struct Foo;
+
+impl Foo {
+ fn bar(self) {}
+}
+
+fn main() {
+ let x = cmp(&1, &2);
+ //~^ ERROR cannot find function `cmp` in this scope
+ //~| HELP use the `.` operator to call the method `Ord::cmp` on `&{integer}`
+
+ let y = len([1, 2, 3]);
+ //~^ ERROR cannot find function `len` in this scope
+ //~| HELP use the `.` operator to call the method `len` on `&[{integer}]`
+
+ let z = bar(Foo);
+ //~^ ERROR cannot find function `bar` in this scope
+ //~| HELP use the `.` operator to call the method `bar` on `Foo`
+}
diff --git a/src/test/ui/suggestions/fn-to-method.stderr b/src/test/ui/suggestions/fn-to-method.stderr
new file mode 100644
index 000000000..36c17e60d
--- /dev/null
+++ b/src/test/ui/suggestions/fn-to-method.stderr
@@ -0,0 +1,38 @@
+error[E0425]: cannot find function `cmp` in this scope
+ --> $DIR/fn-to-method.rs:8:13
+ |
+LL | let x = cmp(&1, &2);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `Ord::cmp` on `&{integer}`
+ |
+LL | let x = (&1).cmp(&2);
+ | ~ ~~~~~~~~~
+
+error[E0425]: cannot find function `len` in this scope
+ --> $DIR/fn-to-method.rs:12:13
+ |
+LL | let y = len([1, 2, 3]);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `len` on `&[{integer}]`
+ |
+LL - let y = len([1, 2, 3]);
+LL + let y = [1, 2, 3].len();
+ |
+
+error[E0425]: cannot find function `bar` in this scope
+ --> $DIR/fn-to-method.rs:16:13
+ |
+LL | let z = bar(Foo);
+ | ^^^ not found in this scope
+ |
+help: use the `.` operator to call the method `bar` on `Foo`
+ |
+LL - let z = bar(Foo);
+LL + let z = Foo.bar();
+ |
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/format-borrow.stderr b/src/test/ui/suggestions/format-borrow.stderr
index fac6a5a5f..8ed2b9c9a 100644
--- a/src/test/ui/suggestions/format-borrow.stderr
+++ b/src/test/ui/suggestions/format-borrow.stderr
@@ -11,6 +11,10 @@ help: consider removing the borrow
LL - let a: String = &String::from("a");
LL + let a: String = String::from("a");
|
+help: alternatively, consider changing the type annotation
+ |
+LL | let a: &String = &String::from("a");
+ | +
error[E0308]: mismatched types
--> $DIR/format-borrow.rs:4:21
@@ -25,6 +29,10 @@ help: consider removing the borrow
LL - let b: String = &format!("b");
LL + let b: String = format!("b");
|
+help: alternatively, consider changing the type annotation
+ |
+LL | let b: &String = &format!("b");
+ | +
error[E0308]: mismatched types
--> $DIR/format-borrow.rs:6:21
@@ -39,6 +47,10 @@ help: consider removing the borrow
LL - let c: String = &mut format!("c");
LL + let c: String = format!("c");
|
+help: alternatively, consider changing the type annotation
+ |
+LL | let c: &mut String = &mut format!("c");
+ | ++++
error[E0308]: mismatched types
--> $DIR/format-borrow.rs:8:21
@@ -53,6 +65,10 @@ help: consider removing the borrow
LL - let d: String = &mut (format!("d"));
LL + let d: String = format!("d"));
|
+help: alternatively, consider changing the type annotation
+ |
+LL | let d: &mut String = &mut (format!("d"));
+ | ++++
error: aborting due to 4 previous errors
diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
index e82a6f769..9833da13f 100644
--- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
+++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr
@@ -26,17 +26,25 @@ error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:5:31
|
LL | fn f(_: impl Iterator<Item = &'_ ()>) {}
- | ^^
+ | ^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn f<'a>(_: impl Iterator<Item = &'_'a ()>) {}
+ | ++++ ++
error[E0658]: anonymous lifetimes in `impl Trait` are unstable
--> $DIR/impl-trait-missing-lifetime-gated.rs:8:31
|
LL | fn g(x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()> { x.next() }
- | ^^
+ | ^^ expected named lifetime parameter
|
= help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable
+help: consider introducing a named lifetime parameter
+ |
+LL | fn g<'a>(x: impl Iterator<Item = &'_'a ()>) -> Option<&'_ ()> { x.next() }
+ | ++++ ++
error: aborting due to 4 previous errors
diff --git a/src/test/ui/suggestions/inner_type.fixed b/src/test/ui/suggestions/inner_type.fixed
new file mode 100644
index 000000000..7af7391ca
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.fixed
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+fn main() {
+ let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
+
+ other_item.borrow().method();
+ //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+
+ other_item.borrow_mut().some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+
+ let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
+
+ another_item.lock().unwrap().method();
+ //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
+ //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+ another_item.read().unwrap().method();
+ //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ another_item.write().unwrap().some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/src/test/ui/suggestions/inner_type.rs b/src/test/ui/suggestions/inner_type.rs
new file mode 100644
index 000000000..4aca50716
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.rs
@@ -0,0 +1,40 @@
+// compile-flags: --edition=2021
+// run-rustfix
+
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+fn main() {
+ let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
+
+ other_item.method();
+ //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+
+ other_item.some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+ //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+
+ let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
+
+ another_item.method();
+ //~^ ERROR no method named `method` found for struct `Mutex` in the current scope [E0599]
+ //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
+
+ another_item.method();
+ //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+
+ another_item.some_mutable_method();
+ //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+ //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+}
diff --git a/src/test/ui/suggestions/inner_type.stderr b/src/test/ui/suggestions/inner_type.stderr
new file mode 100644
index 000000000..5ac3d04f1
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type.stderr
@@ -0,0 +1,83 @@
+error[E0599]: no method named `method` found for struct `RefCell` in the current scope
+ --> $DIR/inner_type.rs:17:16
+ |
+LL | other_item.method();
+ | ^^^^^^ method not found in `RefCell<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
+ |
+LL | other_item.borrow().method();
+ | +++++++++
+
+error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope
+ --> $DIR/inner_type.rs:21:16
+ |
+LL | other_item.some_mutable_method();
+ | ^^^^^^^^^^^^^^^^^^^ method not found in `RefCell<Struct<u32>>`
+ |
+note: the method `some_mutable_method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:11:5
+ |
+LL | pub fn some_mutable_method(&mut self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use `.borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
+ |
+LL | other_item.borrow_mut().some_mutable_method();
+ | +++++++++++++
+
+error[E0599]: no method named `method` found for struct `Mutex` in the current scope
+ --> $DIR/inner_type.rs:27:18
+ |
+LL | another_item.method();
+ | ^^^^^^ method not found in `Mutex<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.lock().unwrap().method();
+ | ++++++++++++++++
+
+error[E0599]: no method named `method` found for struct `RwLock` in the current scope
+ --> $DIR/inner_type.rs:33:18
+ |
+LL | another_item.method();
+ | ^^^^^^ method not found in `RwLock<Struct<u32>>`
+ |
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:9:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+help: use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.read().unwrap().method();
+ | ++++++++++++++++
+
+error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope
+ --> $DIR/inner_type.rs:37:18
+ |
+LL | another_item.some_mutable_method();
+ | ^^^^^^^^^^^^^^^^^^^ method not found in `RwLock<Struct<u32>>`
+ |
+note: the method `some_mutable_method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type.rs:11:5
+ |
+LL | pub fn some_mutable_method(&mut self) {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
+ |
+LL | another_item.write().unwrap().some_mutable_method();
+ | +++++++++++++++++
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/inner_type2.rs b/src/test/ui/suggestions/inner_type2.rs
new file mode 100644
index 000000000..c56ea7c03
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type2.rs
@@ -0,0 +1,26 @@
+pub struct Struct<T> {
+ pub p: T,
+}
+
+impl<T> Struct<T> {
+ pub fn method(&self) {}
+
+ pub fn some_mutable_method(&mut self) {}
+}
+
+thread_local! {
+ static STRUCT: Struct<u32> = Struct {
+ p: 42_u32
+ };
+}
+
+fn main() {
+ STRUCT.method();
+ //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599]
+ //~| HELP use `with` or `try_with` to access thread local storage
+
+ let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
+ item.method();
+ //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
+ //~| HELP if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+}
diff --git a/src/test/ui/suggestions/inner_type2.stderr b/src/test/ui/suggestions/inner_type2.stderr
new file mode 100644
index 000000000..eddfd9d63
--- /dev/null
+++ b/src/test/ui/suggestions/inner_type2.stderr
@@ -0,0 +1,29 @@
+error[E0599]: no method named `method` found for struct `LocalKey` in the current scope
+ --> $DIR/inner_type2.rs:18:12
+ |
+LL | STRUCT.method();
+ | ^^^^^^ method not found in `LocalKey<Struct<u32>>`
+ |
+ = help: use `with` or `try_with` to access thread local storage
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type2.rs:6:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope
+ --> $DIR/inner_type2.rs:23:10
+ |
+LL | item.method();
+ | ^^^^^^ method not found in `MaybeUninit<Struct<u32>>`
+ |
+ = help: if this `MaybeUninit::<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
+note: the method `method` exists on the type `Struct<u32>`
+ --> $DIR/inner_type2.rs:6:5
+ |
+LL | pub fn method(&self) {}
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/into-convert.rs b/src/test/ui/suggestions/into-convert.rs
new file mode 100644
index 000000000..1c9a9e0aa
--- /dev/null
+++ b/src/test/ui/suggestions/into-convert.rs
@@ -0,0 +1,26 @@
+use std::path::{Path, PathBuf};
+use std::sync::atomic::AtomicU32;
+use std::sync::Arc;
+
+fn main() {
+ let x: A = B;
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `B` into `A`
+
+ let y: Arc<Path> = PathBuf::new();
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `PathBuf` into `Arc<Path>`
+
+ let z: AtomicU32 = 1;
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression to convert `{integer}` into `AtomicU32`
+}
+
+struct A;
+struct B;
+
+impl From<B> for A {
+ fn from(_: B) -> Self {
+ A
+ }
+}
diff --git a/src/test/ui/suggestions/into-convert.stderr b/src/test/ui/suggestions/into-convert.stderr
new file mode 100644
index 000000000..d43104a21
--- /dev/null
+++ b/src/test/ui/suggestions/into-convert.stderr
@@ -0,0 +1,44 @@
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:6:16
+ |
+LL | let x: A = B;
+ | - ^ expected struct `A`, found struct `B`
+ | |
+ | expected due to this
+ |
+help: call `Into::into` on this expression to convert `B` into `A`
+ |
+LL | let x: A = B.into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:10:24
+ |
+LL | let y: Arc<Path> = PathBuf::new();
+ | --------- ^^^^^^^^^^^^^^ expected struct `Arc`, found struct `PathBuf`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `Arc<Path>`
+ found struct `PathBuf`
+help: call `Into::into` on this expression to convert `PathBuf` into `Arc<Path>`
+ |
+LL | let y: Arc<Path> = PathBuf::new().into();
+ | +++++++
+
+error[E0308]: mismatched types
+ --> $DIR/into-convert.rs:14:24
+ |
+LL | let z: AtomicU32 = 1;
+ | --------- ^ expected struct `AtomicU32`, found integer
+ | |
+ | expected due to this
+ |
+help: call `Into::into` on this expression to convert `{integer}` into `AtomicU32`
+ |
+LL | let z: AtomicU32 = 1.into();
+ | +++++++
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-101065.fixed b/src/test/ui/suggestions/issue-101065.fixed
new file mode 100644
index 000000000..88c716cc8
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101065.fixed
@@ -0,0 +1,14 @@
+// check-fail
+// run-rustfix
+
+enum FakeResult<T> {
+ Ok(T)
+}
+
+fn main() {
+ let _x = if true {
+ FakeResult::Ok(FakeResult::Ok(()))
+ } else {
+ FakeResult::Ok(FakeResult::Ok(())) //~ERROR E0308
+ };
+}
diff --git a/src/test/ui/suggestions/issue-101065.rs b/src/test/ui/suggestions/issue-101065.rs
new file mode 100644
index 000000000..2715f1027
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101065.rs
@@ -0,0 +1,14 @@
+// check-fail
+// run-rustfix
+
+enum FakeResult<T> {
+ Ok(T)
+}
+
+fn main() {
+ let _x = if true {
+ FakeResult::Ok(FakeResult::Ok(()))
+ } else {
+ FakeResult::Ok(()) //~ERROR E0308
+ };
+}
diff --git a/src/test/ui/suggestions/issue-101065.stderr b/src/test/ui/suggestions/issue-101065.stderr
new file mode 100644
index 000000000..6f7ecd24c
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101065.stderr
@@ -0,0 +1,23 @@
+error[E0308]: `if` and `else` have incompatible types
+ --> $DIR/issue-101065.rs:12:9
+ |
+LL | let _x = if true {
+ | ______________-
+LL | | FakeResult::Ok(FakeResult::Ok(()))
+ | | ---------------------------------- expected because of this
+LL | | } else {
+LL | | FakeResult::Ok(())
+ | | ^^^^^^^^^^^^^^^^^^ expected enum `FakeResult`, found `()`
+LL | | };
+ | |_____- `if` and `else` have incompatible types
+ |
+ = note: expected enum `FakeResult<FakeResult<()>>`
+ found enum `FakeResult<()>`
+help: try wrapping the expression in `FakeResult::Ok`
+ |
+LL | FakeResult::Ok(FakeResult::Ok(()))
+ | +++++++++++++++ +
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-101623.rs b/src/test/ui/suggestions/issue-101623.rs
new file mode 100644
index 000000000..d18a4a21f
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101623.rs
@@ -0,0 +1,25 @@
+pub struct Stuff {
+ inner: *mut (),
+}
+
+pub struct Wrap<T>(T);
+
+fn fun<T>(t: T) -> Wrap<T> {
+ todo!()
+}
+
+pub trait Trait<'de> {
+ fn do_stuff(_: Wrap<&'de mut Self>);
+}
+
+impl<'a> Trait<'a> for () {
+ fn do_stuff(_: Wrap<&'a mut Self>) {}
+}
+
+fn fun2(t: &mut Stuff) -> () {
+ let Stuff { inner, .. } = t;
+ Trait::do_stuff({ fun(&mut *inner) });
+ //~^ ERROR the trait bound `*mut (): Trait<'_>` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-101623.stderr b/src/test/ui/suggestions/issue-101623.stderr
new file mode 100644
index 000000000..361483cc0
--- /dev/null
+++ b/src/test/ui/suggestions/issue-101623.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `*mut (): Trait<'_>` is not satisfied
+ --> $DIR/issue-101623.rs:21:21
+ |
+LL | Trait::do_stuff({ fun(&mut *inner) });
+ | --------------- ^^----------------^^
+ | | |
+ | | the trait `Trait<'_>` is not implemented for `*mut ()`
+ | required by a bound introduced by this call
+ |
+ = help: the trait `Trait<'a>` is implemented for `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/issue-101984.stderr b/src/test/ui/suggestions/issue-101984.stderr
index c744c62d1..81758a700 100644
--- a/src/test/ui/suggestions/issue-101984.stderr
+++ b/src/test/ui/suggestions/issue-101984.stderr
@@ -2,11 +2,11 @@ error[E0308]: mismatched types
--> $DIR/issue-101984.rs:21:13
|
LL | let (cmp, router) = self.router.at()?;
- | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'r> fn(&'r ()), Box<Wrapper>)>`
+ | ^^^^^^^^^^^^^ ----------------- this expression has type `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
| |
| expected struct `Match`, found tuple
|
- = note: expected struct `Match<&(for<'r> fn(&'r ()), Box<Wrapper>)>`
+ = note: expected struct `Match<&(for<'a> fn(&'a ()), Box<Wrapper>)>`
found tuple `(_, _)`
error: aborting due to previous error
diff --git a/src/test/ui/suggestions/issue-102354.rs b/src/test/ui/suggestions/issue-102354.rs
new file mode 100644
index 000000000..f881feb00
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102354.rs
@@ -0,0 +1,10 @@
+trait Trait {
+ fn func() {}
+}
+
+impl Trait for i32 {}
+
+fn main() {
+ let x: i32 = 123;
+ x.func(); //~ERROR no method
+}
diff --git a/src/test/ui/suggestions/issue-102354.stderr b/src/test/ui/suggestions/issue-102354.stderr
new file mode 100644
index 000000000..4f76c5f2e
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102354.stderr
@@ -0,0 +1,24 @@
+error[E0599]: no method named `func` found for type `i32` in the current scope
+ --> $DIR/issue-102354.rs:9:7
+ |
+LL | x.func();
+ | ^^^^ this is an associated function, not a method
+ |
+ = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in the trait `Trait`
+ --> $DIR/issue-102354.rs:2:5
+ |
+LL | fn func() {}
+ | ^^^^^^^^^
+help: use associated function syntax instead
+ |
+LL | i32::func();
+ | ~~~~~~~~~
+help: disambiguate the associated function for the candidate
+ |
+LL | <i32 as Trait>::func(x);
+ | ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/issue-102892.rs b/src/test/ui/suggestions/issue-102892.rs
new file mode 100644
index 000000000..c1a791d8d
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102892.rs
@@ -0,0 +1,25 @@
+#![allow(dead_code, unused_variables)]
+
+use std::sync::Arc;
+
+#[derive(Debug)]
+struct A;
+#[derive(Debug)]
+struct B;
+
+fn process_without_annot(arc: &Arc<(A, B)>) {
+ let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
+}
+
+fn process_with_annot(arc: &Arc<(A, B)>) {
+ let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
+ //~^ ERROR mismatched types
+}
+
+fn process_with_tuple_annot(mutation: &mut (A, B), arc: &Arc<(A, B)>) {
+ let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/issue-102892.stderr b/src/test/ui/suggestions/issue-102892.stderr
new file mode 100644
index 000000000..a3dbc7cb8
--- /dev/null
+++ b/src/test/ui/suggestions/issue-102892.stderr
@@ -0,0 +1,57 @@
+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 due to this
+ |
+ = note: expected tuple `(A, B)`
+ found reference `&(A, B)`
+help: consider removing the borrow
+ |
+LL - let (a, b): (A, B) = &**arc; // suggests putting `&**arc` here too
+LL + let (a, b): (A, B) = **arc; // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): &(A, B) = &**arc; // suggests putting `&**arc` here too
+ | +
+
+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)`
+ |
+ = note: expected tuple `(A, B)`
+ found mutable reference `&mut (A, B)`
+help: consider removing the borrow
+ |
+LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+LL + let (a, b): ((A, B), A) = (*mutation, &(**arc).0); // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): (&mut (A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | ++++
+
+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`
+ |
+help: consider removing the borrow
+ |
+LL - let (a, b): ((A, B), A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+LL + let (a, b): ((A, B), A) = (&mut *mutation, (**arc).0); // suggests putting `&**arc` here too
+ |
+help: alternatively, consider changing the type annotation
+ |
+LL | let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
+ | +
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/issue-103112.rs b/src/test/ui/suggestions/issue-103112.rs
new file mode 100644
index 000000000..111ae7c73
--- /dev/null
+++ b/src/test/ui/suggestions/issue-103112.rs
@@ -0,0 +1,4 @@
+fn main() {
+ std::process::abort!();
+ //~^ ERROR: failed to resolve
+}
diff --git a/src/test/ui/suggestions/issue-103112.stderr b/src/test/ui/suggestions/issue-103112.stderr
new file mode 100644
index 000000000..4ca7fdf9b
--- /dev/null
+++ b/src/test/ui/suggestions/issue-103112.stderr
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve: could not find `abort` in `process`
+ --> $DIR/issue-103112.rs:2:19
+ |
+LL | std::process::abort!();
+ | ^^^^^ could not find `abort` in `process`
+ |
+help: std::process::abort is not a macro, but a function, try to remove `!`
+ |
+LL - std::process::abort!();
+LL + std::process::abort();
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/suggestions/issue-61963.stderr b/src/test/ui/suggestions/issue-61963.stderr
index a788cab6e..b99b1b0b9 100644
--- a/src/test/ui/suggestions/issue-61963.stderr
+++ b/src/test/ui/suggestions/issue-61963.stderr
@@ -4,13 +4,13 @@ error: trait objects without an explicit `dyn` are deprecated
LL | bar: Box<Bar>,
| ^^^
|
+ = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+ = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
note: the lint level is defined here
--> $DIR/issue-61963.rs:3:9
|
LL | #![deny(bare_trait_objects)]
| ^^^^^^^^^^^^^^^^^^
- = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
- = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
help: use `dyn`
|
LL | bar: Box<dyn Bar>,
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
index e5d2ead6a..872263fd7 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr
@@ -27,3 +27,4 @@ LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) {
error: aborting due to previous error
+For more information about this error, try `rustc --explain E0311`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index ed1b91676..fa758bf05 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -18,7 +18,7 @@ LL | | *dest = g.get();
LL | | }
| |_____^
|
-help: to declare that the `impl Trait` captures `'_`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl FnOnce()` captures `'_`, you can add an explicit `'_` lifetime bound
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
| ++++
@@ -164,5 +164,5 @@ LL | G: Get<T> + 'a,
error: aborting due to 8 previous errors
-Some errors have detailed explanations: E0261, E0309, E0621, E0700.
+Some errors have detailed explanations: E0261, E0309, E0311, E0621, E0700.
For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
index f49876bcd..c77ef79e7 100644
--- a/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
+++ b/src/test/ui/suggestions/lifetimes/trait-object-nested-in-impl-trait.stderr
@@ -10,7 +10,7 @@ LL | | remaining: self.0.iter(),
LL | | }
| |_________^ returning this value requires that `'1` must outlive `'static`
|
-help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'_` lifetime bound
|
LL | fn iter(&self) -> impl Iterator<Item = Box<dyn Foo>> + '_ {
| ++++
@@ -65,7 +65,7 @@ LL | | remaining: self.0.iter(),
LL | | }
| |_________^ returning this value requires that `'a` must outlive `'static`
|
-help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
+help: to declare that `impl Iterator<Item = Box<(dyn Foo + 'static)>>` captures data from argument `self`, you can add an explicit `'a` lifetime bound
|
LL | fn iter<'a>(&'a self) -> impl Iterator<Item = Box<dyn Foo>> + 'a {
| ++++
diff --git a/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
index be6fc2615..00aa7d18a 100644
--- a/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
+++ b/src/test/ui/suggestions/match-with-different-arm-types-as-stmt-instead-of-expr.stderr
@@ -7,7 +7,7 @@ LL | fn not_all_paths(a: &str) -> u32 {
| implicitly returns `()` as its body has no tail or `return` expression
...
LL | };
- | - help: remove this semicolon
+ | - help: remove this semicolon to return this value
error[E0308]: `match` arms have incompatible types
--> $DIR/match-with-different-arm-types-as-stmt-instead-of-expr.rs:26:14
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
index e0f405eed..9e6f0d9eb 100644
--- a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl-2.stderr
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:9
+ --> $DIR/missing-bound-in-manual-copy-impl-2.rs:16:18
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
...
LL | impl<S> Copy for Wrapper<OnlyCopyIfDisplay<S>> {}
- | ^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the `Copy` impl for `OnlyCopyIfDisplay<S>` requires that `S: std::fmt::Display`
--> $DIR/missing-bound-in-manual-copy-impl-2.rs:4:19
diff --git a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
index 218988511..fe2d133c8 100644
--- a/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
+++ b/src/test/ui/suggestions/missing-bound-in-manual-copy-impl.stderr
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/missing-bound-in-manual-copy-impl.rs:6:9
+ --> $DIR/missing-bound-in-manual-copy-impl.rs:6:18
|
LL | struct Wrapper<T>(T);
| - this field does not implement `Copy`
LL |
LL | impl<S> Copy for Wrapper<S> {}
- | ^^^^
+ | ^^^^^^^^^^
|
help: consider restricting type parameter `S`
|
diff --git a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
index 98b408daa..a7a3f9818 100644
--- a/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
+++ b/src/test/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.rs
@@ -1,4 +1,4 @@
-// In rustc_typeck::check::expr::no_such_field_err we recursively
+// In rustc_hir_analysis::check::expr::no_such_field_err we recursively
// look in subfields for the field. This recursive search is limited
// in depth for compile-time reasons and to avoid infinite recursion
// in case of cycles. This file tests that the limit in the recursion
diff --git a/src/test/ui/suggestions/return-closures.stderr b/src/test/ui/suggestions/return-closures.stderr
index e273793ea..8b856d8de 100644
--- a/src/test/ui/suggestions/return-closures.stderr
+++ b/src/test/ui/suggestions/return-closures.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
--> $DIR/return-closures.rs:3:5
|
LL | fn foo() {
- | - help: try adding a return type: `-> impl for<'r> Fn(&'r i32) -> i32`
+ | - help: try adding a return type: `-> impl for<'a> Fn(&'a i32) -> i32`
LL |
LL | |x: &i32| 1i32
| ^^^^^^^^^^^^^^ expected `()`, found closure
diff --git a/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
index 189759d64..4dd514480 100644
--- a/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
+++ b/src/test/ui/suggestions/struct-field-type-including-single-colon.stderr
@@ -12,6 +12,8 @@ LL | a: foo::A,
error: expected `,`, or `}`, found `:`
--> $DIR/struct-field-type-including-single-colon.rs:9:11
|
+LL | struct Foo {
+ | --- while parsing this struct
LL | a: foo:A,
| ^
@@ -29,6 +31,8 @@ LL | b: foo::bar::B,
error: expected `,`, or `}`, found `:`
--> $DIR/struct-field-type-including-single-colon.rs:15:16
|
+LL | struct Bar {
+ | --- while parsing this struct
LL | b: foo::bar:B,
| ^
diff --git a/src/test/ui/suggestions/sugg-else-for-closure.fixed b/src/test/ui/suggestions/sugg-else-for-closure.fixed
new file mode 100644
index 000000000..cf381d9da
--- /dev/null
+++ b/src/test/ui/suggestions/sugg-else-for-closure.fixed
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let x = "com.example.app";
+ let y: Option<&str> = None;
+ let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/sugg-else-for-closure.rs b/src/test/ui/suggestions/sugg-else-for-closure.rs
new file mode 100644
index 000000000..540ced91f
--- /dev/null
+++ b/src/test/ui/suggestions/sugg-else-for-closure.rs
@@ -0,0 +1,8 @@
+// run-rustfix
+
+fn main() {
+ let x = "com.example.app";
+ let y: Option<&str> = None;
+ let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ //~^ ERROR: mismatched types [E0308]
+}
diff --git a/src/test/ui/suggestions/sugg-else-for-closure.stderr b/src/test/ui/suggestions/sugg-else-for-closure.stderr
new file mode 100644
index 000000000..55a0eee18
--- /dev/null
+++ b/src/test/ui/suggestions/sugg-else-for-closure.stderr
@@ -0,0 +1,23 @@
+error[E0308]: mismatched types
+ --> $DIR/sugg-else-for-closure.rs:6:26
+ |
+LL | let _s = y.unwrap_or(|| x.split('.').nth(1).unwrap());
+ | --------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&str`, found closure
+ | |
+ | arguments to this function are incorrect
+ |
+ = note: expected reference `&str`
+ found closure `[closure@$DIR/sugg-else-for-closure.rs:6:26: 6:28]`
+note: associated function defined here
+ --> $SRC_DIR/core/src/option.rs:LL:COL
+ |
+LL | pub const fn unwrap_or(self, default: T) -> T
+ | ^^^^^^^^^
+help: try calling `unwrap_or_else` instead
+ |
+LL | let _s = y.unwrap_or_else(|| x.split('.').nth(1).unwrap());
+ | +++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.fixed b/src/test/ui/suggestions/suggest-let-for-assignment.fixed
new file mode 100644
index 000000000..3a25e25ee
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.fixed
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+ let demo = 1; //~ ERROR cannot find value `demo` in this scope
+ dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+ let x = "x"; //~ ERROR cannot find value `x` in this scope
+ println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+ if x == "x" {
+ //~^ ERROR cannot find value `x` in this scope
+ println!("x is 1");
+ }
+
+ let y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+ println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.rs b/src/test/ui/suggestions/suggest-let-for-assignment.rs
new file mode 100644
index 000000000..67705fe06
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.rs
@@ -0,0 +1,17 @@
+// run-rustfix
+
+fn main() {
+ demo = 1; //~ ERROR cannot find value `demo` in this scope
+ dbg!(demo); //~ ERROR cannot find value `demo` in this scope
+
+ x = "x"; //~ ERROR cannot find value `x` in this scope
+ println!("x: {}", x); //~ ERROR cannot find value `x` in this scope
+
+ if x == "x" {
+ //~^ ERROR cannot find value `x` in this scope
+ println!("x is 1");
+ }
+
+ y = 1 + 2; //~ ERROR cannot find value `y` in this scope
+ println!("y: {}", y); //~ ERROR cannot find value `y` in this scope
+}
diff --git a/src/test/ui/suggestions/suggest-let-for-assignment.stderr b/src/test/ui/suggestions/suggest-let-for-assignment.stderr
new file mode 100644
index 000000000..3f6a3da4b
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-let-for-assignment.stderr
@@ -0,0 +1,60 @@
+error[E0425]: cannot find value `demo` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:4:5
+ |
+LL | demo = 1;
+ | ^^^^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let demo = 1;
+ | +++
+
+error[E0425]: cannot find value `demo` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:5:10
+ |
+LL | dbg!(demo);
+ | ^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:7:5
+ |
+LL | x = "x";
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let x = "x";
+ | +++
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:8:23
+ |
+LL | println!("x: {}", x);
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:10:8
+ |
+LL | if x == "x" {
+ | ^ not found in this scope
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:15:5
+ |
+LL | y = 1 + 2;
+ | ^
+ |
+help: you might have meant to introduce a new binding
+ |
+LL | let y = 1 + 2;
+ | +++
+
+error[E0425]: cannot find value `y` in this scope
+ --> $DIR/suggest-let-for-assignment.rs:16:23
+ |
+LL | println!("y: {}", y);
+ | ^ not found in this scope
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
index f716e6c17..ffd505fff 100644
--- a/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
+++ b/src/test/ui/suggestions/suggest-swapping-self-ty-and-trait.stderr
@@ -37,9 +37,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | impl<'a, T> Struct<T> for Trait<'a, T> {}
| ^^^^^^^^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | impl<'a, T> Struct<T> for dyn Trait<'a, T> {}
diff --git a/src/test/ui/symbol-names/impl1.legacy.stderr b/src/test/ui/symbol-names/impl1.legacy.stderr
index b6012e415..3d438df92 100644
--- a/src/test/ui/symbol-names/impl1.legacy.stderr
+++ b/src/test/ui/symbol-names/impl1.legacy.stderr
@@ -64,7 +64,7 @@ error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::A
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
+error: def-path(<[&dyn Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
--> $DIR/impl1.rs:69:13
|
LL | #[rustc_def_path]
diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs
index 86f0a8b0b..629c2f33d 100644
--- a/src/test/ui/symbol-names/impl1.rs
+++ b/src/test/ui/symbol-names/impl1.rs
@@ -67,8 +67,8 @@ fn main() {
//[v0]~| ERROR demangling(<[&dyn
//[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method)
#[rustc_def_path]
- //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
- //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
+ //[legacy]~^ ERROR def-path(<[&dyn Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
+ //[v0]~^^ ERROR def-path(<[&dyn Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
fn method(&self) {}
}
};
diff --git a/src/test/ui/symbol-names/impl1.v0.stderr b/src/test/ui/symbol-names/impl1.v0.stderr
index 48f7473b6..33caad71f 100644
--- a/src/test/ui/symbol-names/impl1.v0.stderr
+++ b/src/test/ui/symbol-names/impl1.v0.stderr
@@ -64,7 +64,7 @@ error: demangling-alt(<[&dyn impl1::Foo<Assoc = for<'a> extern "C" fn(&'a u8, ..
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^
-error: def-path(<[&dyn Foo<Assoc = for<'r> extern "C" fn(&'r u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
+error: def-path(<[&dyn Foo<Assoc = for<'a> extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method)
--> $DIR/impl1.rs:69:13
|
LL | #[rustc_def_path]
diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr
index a94ea1e79..0c16ecd4c 100644
--- a/src/test/ui/test-attrs/inaccessible-test-modules.stderr
+++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr
@@ -11,10 +11,16 @@ error[E0432]: unresolved import `test`
--> $DIR/inaccessible-test-modules.rs:6:5
|
LL | use test as y;
- | ----^^^^^
- | |
- | no `test` in the root
- | help: a similar name exists in the module: `test`
+ | ^^^^^^^^^ no `test` in the root
+ |
+help: a similar name exists in the module
+ |
+LL | use test as y;
+ | ~~~~
+help: consider importing this module instead
+ |
+LL | use test::test;
+ | ~~~~~~~~~~~
error: aborting due to 2 previous errors
diff --git a/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs b/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
index ff62d8492..585874e27 100644
--- a/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
+++ b/src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs
@@ -1,4 +1,5 @@
// run-pass
+// needs-unwind (#73509)
#![feature(test)]
diff --git a/src/test/ui/test-attrs/test-on-not-fn.stderr b/src/test/ui/test-attrs/test-on-not-fn.stderr
index 23efd5bc0..fc2c5f62b 100644
--- a/src/test/ui/test-attrs/test-on-not-fn.stderr
+++ b/src/test/ui/test-attrs/test-on-not-fn.stderr
@@ -2,7 +2,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:3:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | mod test {}
| ----------- expected a non-associated function, found a module
|
@@ -15,7 +15,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:6:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | / mod loooooooooooooong_teeeeeeeeeest {
LL | | /*
LL | | this is a comment
@@ -34,7 +34,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:20:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | extern "C" {}
| ------------- expected a non-associated function, found an extern block
|
@@ -47,7 +47,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:23:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | trait Foo {}
| ------------ expected a non-associated function, found a trait
|
@@ -60,7 +60,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:26:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | impl Foo for i32 {}
| ------------------- expected a non-associated function, found an implementation
|
@@ -73,7 +73,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:29:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | const FOO: i32 = -1_i32;
| ------------------------ expected a non-associated function, found a constant item
|
@@ -86,7 +86,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:32:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | static BAR: u64 = 10_000_u64;
| ----------------------------- expected a non-associated function, found a static item
|
@@ -99,7 +99,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:35:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | / enum MyUnit {
LL | | Unit,
LL | | }
@@ -114,7 +114,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:40:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | struct NewI32(i32);
| ------------------- expected a non-associated function, found a struct
|
@@ -127,7 +127,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:43:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | / union Spooky {
LL | | x: i32,
LL | | y: u32,
@@ -143,7 +143,7 @@ error: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:50:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | #[derive(Copy, Clone, Debug)]
LL | / struct MoreAttrs {
LL | | a: i32,
@@ -160,7 +160,7 @@ warning: the `#[test]` attribute may only be used on a non-associated function
--> $DIR/test-on-not-fn.rs:61:1
|
LL | #[test]
- | ^^^^^^^ the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions
+ | ^^^^^^^ the `#[test]` macro causes a function to be run on a test and has no effect on non-functions
LL | foo!();
| ------- expected a non-associated function, found an item macro invocation
|
diff --git a/src/test/ui/test-attrs/test-panic-while-printing.rs b/src/test/ui/test-attrs/test-panic-while-printing.rs
index 01e460da5..033c8beb4 100644
--- a/src/test/ui/test-attrs/test-panic-while-printing.rs
+++ b/src/test/ui/test-attrs/test-panic-while-printing.rs
@@ -1,7 +1,6 @@
// compile-flags:--test
// run-pass
// needs-unwind
-// ignore-emscripten no subprocess support
use std::fmt;
use std::fmt::{Display, Formatter};
diff --git a/src/test/ui/test-attrs/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs
index 3260b6938..83519c452 100644
--- a/src/test/ui/test-attrs/test-should-fail-good-message.rs
+++ b/src/test/ui/test-attrs/test-should-fail-good-message.rs
@@ -1,6 +1,5 @@
// run-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: --test
#[test]
#[should_panic(expected = "foo")]
diff --git a/src/test/ui/test-attrs/test-thread-capture.rs b/src/test/ui/test-attrs/test-thread-capture.rs
index edc972837..53acca341 100644
--- a/src/test/ui/test-attrs/test-thread-capture.rs
+++ b/src/test/ui/test-attrs/test-thread-capture.rs
@@ -5,6 +5,7 @@
// exec-env:RUST_BACKTRACE=0
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// ignore-emscripten no threads support
+// needs-unwind
#[test]
fn thready_pass() {
diff --git a/src/test/ui/test-attrs/test-thread-capture.run.stdout b/src/test/ui/test-attrs/test-thread-capture.run.stdout
index 487cfb55e..c712a78af 100644
--- a/src/test/ui/test-attrs/test-thread-capture.run.stdout
+++ b/src/test/ui/test-attrs/test-thread-capture.run.stdout
@@ -10,7 +10,7 @@ fee
fie
foe
fum
-thread 'main' panicked at 'explicit panic', $DIR/test-thread-capture.rs:31:5
+thread 'main' panicked at 'explicit panic', $DIR/test-thread-capture.rs:32:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/test-attrs/test-thread-nocapture.rs b/src/test/ui/test-attrs/test-thread-nocapture.rs
index 8e8e9bbfd..2b57eb8aa 100644
--- a/src/test/ui/test-attrs/test-thread-nocapture.rs
+++ b/src/test/ui/test-attrs/test-thread-nocapture.rs
@@ -5,6 +5,7 @@
// exec-env:RUST_BACKTRACE=0
// normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
// ignore-emscripten no threads support
+// needs-unwind
#[test]
fn thready_pass() {
diff --git a/src/test/ui/test-attrs/test-thread-nocapture.run.stderr b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr
index 06495681b..0a12a0528 100644
--- a/src/test/ui/test-attrs/test-thread-nocapture.run.stderr
+++ b/src/test/ui/test-attrs/test-thread-nocapture.run.stderr
@@ -1,2 +1,2 @@
-thread 'main' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:31:5
+thread 'main' panicked at 'explicit panic', $DIR/test-thread-nocapture.rs:32:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/src/test/ui/thir-tree.stdout b/src/test/ui/thir-tree.stdout
index 5fcdfca18..7fb90581f 100644
--- a/src/test/ui/thir-tree.stdout
+++ b/src/test/ui/thir-tree.stdout
@@ -33,7 +33,9 @@ Thir {
region_scope: Node(2),
lint_level: Explicit(
HirId {
- owner: DefId(0:3 ~ thir_tree[8f1d]::main),
+ owner: OwnerId {
+ def_id: DefId(0:3 ~ thir_tree[8f1d]::main),
+ },
local_id: 2,
},
),
diff --git a/src/test/ui/threads-sendsync/issue-43733-2.rs b/src/test/ui/threads-sendsync/issue-43733-2.rs
index 21ea8e9a2..32baeec43 100644
--- a/src/test/ui/threads-sendsync/issue-43733-2.rs
+++ b/src/test/ui/threads-sendsync/issue-43733-2.rs
@@ -1,5 +1,5 @@
+// ignore-wasm32
// dont-check-compiler-stderr
-
#![feature(cfg_target_thread_local, thread_local_internals)]
// On platforms *without* `#[thread_local]`, use
diff --git a/src/test/ui/threads-sendsync/issue-43733.rs b/src/test/ui/threads-sendsync/issue-43733.rs
index 0ac6f588f..935e02944 100644
--- a/src/test/ui/threads-sendsync/issue-43733.rs
+++ b/src/test/ui/threads-sendsync/issue-43733.rs
@@ -1,8 +1,8 @@
+// ignore-wasm32
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck
// normalize-stderr-test: "__FastLocalKeyInner::<T>::get" -> "$$LOCALKEYINNER::<T>::get"
// normalize-stderr-test: "__OsLocalKeyInner::<T>::get" -> "$$LOCALKEYINNER::<T>::get"
-
#![feature(thread_local)]
#![feature(cfg_target_thread_local, thread_local_internals)]
diff --git a/src/test/ui/threads-sendsync/sync-send-in-std.rs b/src/test/ui/threads-sendsync/sync-send-in-std.rs
index b8ae214dc..6d1fba64e 100644
--- a/src/test/ui/threads-sendsync/sync-send-in-std.rs
+++ b/src/test/ui/threads-sendsync/sync-send-in-std.rs
@@ -2,6 +2,7 @@
// ignore-wasm32-bare networking not available
// ignore-sgx ToSocketAddrs cannot be used for DNS Resolution
+// ignore-fuchsia Req. test-harness networking privileges
use std::net::ToSocketAddrs;
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
index 4084f69a6..10e82c54e 100644
--- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
+++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
LL | f::<dyn for<'x> X<'x, F = i32>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
|
- = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32`
+ = help: the trait `for<'a> FnOnce<(&'a i32,)>` is not implemented for `i32`
note: required by a bound in `f`
--> $DIR/check-trait-object-bounds-2.rs:8:9
|
diff --git a/src/test/ui/traits/bound/not-on-bare-trait.stderr b/src/test/ui/traits/bound/not-on-bare-trait.stderr
index 1c52629da..8da0b6d6b 100644
--- a/src/test/ui/traits/bound/not-on-bare-trait.stderr
+++ b/src/test/ui/traits/bound/not-on-bare-trait.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | fn foo(_x: Foo + Send) {
| ^^^^^^^^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | fn foo(_x: dyn Foo + Send) {
diff --git a/src/test/ui/traits/copy-impl-cannot-normalize.stderr b/src/test/ui/traits/copy-impl-cannot-normalize.stderr
index afdad1609..68b95b42b 100644
--- a/src/test/ui/traits/copy-impl-cannot-normalize.stderr
+++ b/src/test/ui/traits/copy-impl-cannot-normalize.stderr
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `T: TraitFoo` is not satisfied
- --> $DIR/copy-impl-cannot-normalize.rs:22:1
+ --> $DIR/copy-impl-cannot-normalize.rs:22:18
|
LL | impl<T> Copy for Foo<T> {}
- | ^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitFoo` is not implemented for `T`
+ | ^^^^^^ the trait `TraitFoo` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
diff --git a/src/test/ui/traits/issue-102989.rs b/src/test/ui/traits/issue-102989.rs
new file mode 100644
index 000000000..62f95272f
--- /dev/null
+++ b/src/test/ui/traits/issue-102989.rs
@@ -0,0 +1,16 @@
+// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib"
+
+#![feature(lang_items)]
+#[lang="sized"]
+trait Sized { } //~ ERROR found duplicate lang item `sized`
+
+fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ //~^ ERROR `self` parameter is only allowed in associated functions
+ //~| ERROR cannot find type `Struct` in this scope
+ //~| ERROR mismatched types
+ let x = x << 1;
+ //~^ ERROR the size for values of type `{integer}` cannot be known at compilation time
+ //~| ERROR cannot find value `x` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/issue-102989.stderr b/src/test/ui/traits/issue-102989.stderr
new file mode 100644
index 000000000..efe1a2467
--- /dev/null
+++ b/src/test/ui/traits/issue-102989.stderr
@@ -0,0 +1,59 @@
+error: `self` parameter is only allowed in associated functions
+ --> $DIR/issue-102989.rs:7:15
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ^^^^ not semantically valid as function parameter
+ |
+ = note: associated functions are those in `impl` or `trait` definitions
+
+error[E0412]: cannot find type `Struct` in this scope
+ --> $DIR/issue-102989.rs:7:22
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `x` in this scope
+ --> $DIR/issue-102989.rs:11:13
+ |
+LL | let x = x << 1;
+ | ^ help: a local variable with a similar name exists: `f`
+
+error[E0152]: found duplicate lang item `sized`
+ --> $DIR/issue-102989.rs:5:1
+ |
+LL | trait Sized { }
+ | ^^^^^^^^^^^
+ |
+ = note: the lang item is first defined in crate `core` (which `std` depends on)
+ = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib
+ = note: second definition in the local crate (`issue_102989`)
+
+error[E0277]: the size for values of type `{integer}` cannot be known at compilation time
+ --> $DIR/issue-102989.rs:11:15
+ |
+LL | let x = x << 1;
+ | ^^ doesn't have a size known at compile-time
+ |
+ = help: the trait `std::marker::Sized` is not implemented for `{integer}`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-102989.rs:7:42
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ---------- ^^^^ expected `&u32`, found `()`
+ | |
+ | implicitly returns `()` as its body has no tail or `return` expression
+ |
+note: consider returning one of these bindings
+ --> $DIR/issue-102989.rs:7:30
+ |
+LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 {
+ | ^
+...
+LL | let x = x << 1;
+ | ^
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425.
+For more information about an error, try `rustc --explain E0152`.
diff --git a/src/test/ui/traits/issue-33140-hack-boundaries.stderr b/src/test/ui/traits/issue-33140-hack-boundaries.stderr
index 62cfca545..58286648d 100644
--- a/src/test/ui/traits/issue-33140-hack-boundaries.stderr
+++ b/src/test/ui/traits/issue-33140-hack-boundaries.stderr
@@ -66,3 +66,20 @@ error: aborting due to 8 previous errors
Some errors have detailed explanations: E0119, E0751.
For more information about an error, try `rustc --explain E0119`.
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait0` for type `(dyn std::marker::Send + 'static)`: (E0119)
+ --> $DIR/issue-33140-hack-boundaries.rs:10:1
+ |
+LL | impl Trait0 for dyn Send {}
+ | ------------------------ first implementation here
+LL | impl Trait0 for dyn Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-hack-boundaries.rs:2:10
+ |
+LL | #![allow(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/issues/issue-43784-supertrait.rs b/src/test/ui/traits/issue-43784-supertrait.rs
index 55c26ccd2..55c26ccd2 100644
--- a/src/test/ui/issues/issue-43784-supertrait.rs
+++ b/src/test/ui/traits/issue-43784-supertrait.rs
diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/traits/issue-43784-supertrait.stderr
index bb890cb99..bb890cb99 100644
--- a/src/test/ui/issues/issue-43784-supertrait.stderr
+++ b/src/test/ui/traits/issue-43784-supertrait.stderr
diff --git a/src/test/ui/traits/issue-8153.stderr b/src/test/ui/traits/issue-8153.stderr
index b76bbc023..ae214bb9e 100644
--- a/src/test/ui/traits/issue-8153.stderr
+++ b/src/test/ui/traits/issue-8153.stderr
@@ -1,10 +1,13 @@
error[E0201]: duplicate definitions with name `bar`:
--> $DIR/issue-8153.rs:11:5
|
+LL | fn bar(&self) -> isize;
+ | ----------------------- item in trait
+...
LL | fn bar(&self) -> isize {1}
- | ---------------------- previous definition of `bar` here
+ | -------------------------- previous definition here
LL | fn bar(&self) -> isize {2}
- | ^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition
error: aborting due to previous error
diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
index 6acf2fe65..61b6d4b08 100644
--- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -9,8 +9,8 @@ LL | {
LL | recurse(IteratorOfWrapped(elements).map(|t| t.0))
| ------------------------------------------------- recursive call site
|
- = note: `#[warn(unconditional_recursion)]` on by default
= 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 `(): Sized`
|
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
index ceb86559d..7b54cf542 100644
--- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0750]: negative impls cannot be default impls
--> $DIR/negative-default-impls.rs:9:1
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
index 9a846143d..751e29c3b 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
index 77b4373a2..1cfa49b20 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
--> $DIR/negative-specializes-positive-item.rs:11:1
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
index e5dc81b3e..9f9e28678 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
--> $DIR/negative-specializes-positive.rs:7:1
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
index c091bc81d..545f94143 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -4,9 +4,9 @@ warning: the feature `specialization` is incomplete and may not be safe to use a
LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
= help: consider using `min_specialization` instead, which is more stable and complete
+ = note: `#[warn(incomplete_features)]` on by default
error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
--> $DIR/positive-specializes-negative.rs:7:1
diff --git a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
index 77d71360b..0af4df2ae 100644
--- a/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
+++ b/src/test/ui/traits/object/issue-33140-traitobject-crate.stderr
@@ -6,13 +6,13 @@ LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
|
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
note: the lint level is defined here
--> $DIR/issue-33140-traitobject-crate.rs:3:9
|
LL | #![warn(order_dependent_trait_objects)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
--> $DIR/issue-33140-traitobject-crate.rs:89:1
@@ -40,3 +40,56 @@ LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
warning: 3 warnings emitted
+Future incompatibility report: Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:86:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Sync { }
+ | ------------------------------------------------------ first implementation here
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:89:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Send) + Send + Sync { }
+ | ------------------------------------------------------------- first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/issue-33140-traitobject-crate.rs:93:1
+ |
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send { }
+ | ------------------------------------------------------ first implementation here
+...
+LL | unsafe impl Trait for dyn (::std::marker::Sync) + Send + Sync { }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+ = note: for more information, see issue #56484 <https://github.com/rust-lang/rust/issues/56484>
+note: the lint level is defined here
+ --> $DIR/issue-33140-traitobject-crate.rs:3:9
+ |
+LL | #![warn(order_dependent_trait_objects)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/traits/safety-trait-impl-cc.stderr b/src/test/ui/traits/safety-trait-impl-cc.stderr
index 5a0f8d3b8..0b1fb3047 100644
--- a/src/test/ui/traits/safety-trait-impl-cc.stderr
+++ b/src/test/ui/traits/safety-trait-impl-cc.stderr
@@ -7,6 +7,12 @@ LL | | panic!();
LL | | }
LL | | }
| |_^
+ |
+ = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl lib::Foo for Bar {
+ | ++++++
error: aborting due to previous error
diff --git a/src/test/ui/traits/safety-trait-impl.stderr b/src/test/ui/traits/safety-trait-impl.stderr
index fc0f6c693..721e2b48b 100644
--- a/src/test/ui/traits/safety-trait-impl.stderr
+++ b/src/test/ui/traits/safety-trait-impl.stderr
@@ -3,12 +3,24 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration
|
LL | impl UnsafeTrait for u16 { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword
+help: add `unsafe` to this trait implementation
+ |
+LL | unsafe impl UnsafeTrait for u16 { }
+ | ++++++
error[E0199]: implementing the trait `SafeTrait` is not unsafe
--> $DIR/safety-trait-impl.rs:16:1
|
LL | unsafe impl SafeTrait for u32 { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: remove `unsafe` from this trait implementation
+ |
+LL - unsafe impl SafeTrait for u32 { }
+LL + impl SafeTrait for u32 { }
+ |
error: aborting due to 2 previous errors
diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr
index f1b8f23ec..5f74d0c3b 100644
--- a/src/test/ui/traits/static-method-generic-inference.stderr
+++ b/src/test/ui/traits/static-method-generic-inference.stderr
@@ -9,8 +9,8 @@ LL | let _f: base::Foo = base::HasNew::new();
|
help: use the fully-qualified path to the only available implementation
|
-LL | let _f: base::Foo = base::<::base::Foo as HasNew>::new();
- | +++++++++++++++ +
+LL | let _f: base::Foo = base::<Foo as HasNew>::new();
+ | +++++++ +
error: aborting due to previous error
diff --git a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
index 35af9112a..6c359b698 100644
--- a/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
+++ b/src/test/ui/traits/trait-upcasting/migrate-lint-deny.stderr
@@ -4,13 +4,13 @@ error: `dyn B` implements `Deref` with supertrait `(dyn A + 'static)` as output
LL | take_a(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 #89460 <https://github.com/rust-lang/rust/issues/89460>
note: the lint level is defined here
--> $DIR/migrate-lint-deny.rs:1:9
|
LL | #![deny(deref_into_dyn_supertrait)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
- = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
- = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
error: aborting due to previous error
diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
index 6986ad621..6986ad621 100644
--- a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.rs
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
diff --git a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
index e9670ad7d..956481351 100644
--- a/src/test/ui/traits/trait-upcasting/multiple-occurence-ambiguousity.stderr
+++ b/src/test/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -1,5 +1,5 @@
error[E0308]: mismatched types
- --> $DIR/multiple-occurence-ambiguousity.rs:21:26
+ --> $DIR/multiple-occurrence-ambiguousity.rs:21:26
|
LL | let t: &dyn Bar<_> = s;
| ----------- ^ expected trait `Bar`, found trait `Foo`
diff --git a/src/test/ui/traits/unspecified-self-in-trait-ref.stderr b/src/test/ui/traits/unspecified-self-in-trait-ref.stderr
index 7869176bb..b5e8e8867 100644
--- a/src/test/ui/traits/unspecified-self-in-trait-ref.stderr
+++ b/src/test/ui/traits/unspecified-self-in-trait-ref.stderr
@@ -4,9 +4,9 @@ warning: trait objects without an explicit `dyn` are deprecated
LL | let a = Foo::lol();
| ^^^
|
- = note: `#[warn(bare_trait_objects)]` on by default
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+ = note: `#[warn(bare_trait_objects)]` on by default
help: use `dyn`
|
LL | let a = <dyn Foo>::lol();
diff --git a/src/test/ui/transmutability/enums/should_order_correctly.rs b/src/test/ui/transmutability/enums/should_order_correctly.rs
index b753cf0e6..1335cc9d2 100644
--- a/src/test/ui/transmutability/enums/should_order_correctly.rs
+++ b/src/test/ui/transmutability/enums/should_order_correctly.rs
@@ -2,7 +2,6 @@
//! The payloads of an enum variant should be ordered after its tag.
#![crate_type = "lib"]
-#![feature(arbitrary_enum_discriminant)]
#![feature(transmutability)]
#![allow(dead_code)]
diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.rs b/src/test/ui/transmutability/enums/should_respect_endianness.rs
index 19ff69005..f3567b405 100644
--- a/src/test/ui/transmutability/enums/should_respect_endianness.rs
+++ b/src/test/ui/transmutability/enums/should_respect_endianness.rs
@@ -2,7 +2,6 @@
//! an enum with a multi-byte tag.
#![crate_type = "lib"]
-#![feature(arbitrary_enum_discriminant)]
#![feature(transmutability)]
#![allow(dead_code)]
diff --git a/src/test/ui/transmutability/enums/should_respect_endianness.stderr b/src/test/ui/transmutability/enums/should_respect_endianness.stderr
index fcb70813b..0845a5edf 100644
--- a/src/test/ui/transmutability/enums/should_respect_endianness.stderr
+++ b/src/test/ui/transmutability/enums/should_respect_endianness.stderr
@@ -1,12 +1,12 @@
error[E0277]: `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
- --> $DIR/should_respect_endianness.rs:37:36
+ --> $DIR/should_respect_endianness.rs:36:36
|
LL | assert::is_transmutable::<Src, Unexpected>();
| ^^^^^^^^^^ `Src` cannot be safely transmuted into `Unexpected` in the defining scope of `assert::Context`.
|
= help: the trait `BikeshedIntrinsicFrom<Src, assert::Context, Assume { alignment: true, lifetimes: true, safety: true, validity: true }>` is not implemented for `Unexpected`
note: required by a bound in `is_transmutable`
- --> $DIR/should_respect_endianness.rs:15:14
+ --> $DIR/should_respect_endianness.rs:14:14
|
LL | pub fn is_transmutable<Src, Dst>()
| --------------- required by a bound in this
diff --git a/src/test/ui/transmutability/issue-101739-1.rs b/src/test/ui/transmutability/issue-101739-1.rs
new file mode 100644
index 000000000..bcb8b158e
--- /dev/null
+++ b/src/test/ui/transmutability/issue-101739-1.rs
@@ -0,0 +1,21 @@
+#![feature(transmutability)]
+
+mod assert {
+ use std::mem::BikeshedIntrinsicFrom;
+
+ pub fn is_transmutable<Src, Context, const ASSUME_ALIGNMENT: bool>()
+ where
+ Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>, //~ ERROR cannot find type `Dst` in this scope
+ //~^ ERROR mismatched types
+ {
+ }
+}
+
+fn via_const() {
+ struct Context;
+ struct Src;
+
+ assert::is_transmutable::<Src, Context, false>();
+}
+
+fn main() {}
diff --git a/src/test/ui/transmutability/issue-101739-1.stderr b/src/test/ui/transmutability/issue-101739-1.stderr
new file mode 100644
index 000000000..5fa741f26
--- /dev/null
+++ b/src/test/ui/transmutability/issue-101739-1.stderr
@@ -0,0 +1,16 @@
+error[E0412]: cannot find type `Dst` in this scope
+ --> $DIR/issue-101739-1.rs:8:9
+ |
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
+ | ^^^ not found in this scope
+
+error[E0308]: mismatched types
+ --> $DIR/issue-101739-1.rs:8:50
+ |
+LL | Dst: BikeshedIntrinsicFrom<Src, Context, ASSUME_ALIGNMENT>,
+ | ^^^^^^^^^^^^^^^^ expected struct `Assume`, found `bool`
+
+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/src/test/ui/transmutability/issue-101739-2.rs b/src/test/ui/transmutability/issue-101739-2.rs
new file mode 100644
index 000000000..964a7e49e
--- /dev/null
+++ b/src/test/ui/transmutability/issue-101739-2.rs
@@ -0,0 +1,37 @@
+#![crate_type = "lib"]
+#![feature(transmutability)]
+#![allow(dead_code, incomplete_features, non_camel_case_types)]
+
+mod assert {
+ use std::mem::BikeshedIntrinsicFrom;
+
+ pub fn is_transmutable<
+ Src,
+ Dst,
+ Context,
+ const ASSUME_ALIGNMENT: bool,
+ const ASSUME_LIFETIMES: bool,
+ const ASSUME_VALIDITY: bool,
+ const ASSUME_VISIBILITY: bool,
+ >()
+ where
+ Dst: BikeshedIntrinsicFrom< //~ ERROR this trait takes at most 3 generic arguments but 6 generic arguments were supplied
+ Src,
+ Context,
+ ASSUME_ALIGNMENT,
+ ASSUME_LIFETIMES,
+ ASSUME_VALIDITY,
+ ASSUME_VISIBILITY,
+ >,
+ {}
+}
+
+fn via_const() {
+ struct Context;
+ #[repr(C)] struct Src;
+ #[repr(C)] struct Dst;
+
+ const FALSE: bool = false;
+
+ assert::is_transmutable::<Src, Dst, Context, FALSE, FALSE, FALSE, FALSE>();
+}
diff --git a/src/test/ui/transmutability/issue-101739-2.stderr b/src/test/ui/transmutability/issue-101739-2.stderr
new file mode 100644
index 000000000..3f83d6583
--- /dev/null
+++ b/src/test/ui/transmutability/issue-101739-2.stderr
@@ -0,0 +1,20 @@
+error[E0107]: this trait takes at most 3 generic arguments but 6 generic arguments were supplied
+ --> $DIR/issue-101739-2.rs:18:14
+ |
+LL | Dst: BikeshedIntrinsicFrom<
+ | ^^^^^^^^^^^^^^^^^^^^^ expected at most 3 generic arguments
+...
+LL | / ASSUME_LIFETIMES,
+LL | | ASSUME_VALIDITY,
+LL | | ASSUME_VISIBILITY,
+ | |_____________________________- help: remove these generic arguments
+ |
+note: trait defined here, with at most 3 generic parameters: `Src`, `Context`, `ASSUME`
+ --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
+ |
+LL | pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
+ | ^^^^^^^^^^^^^^^^^^^^^ --- ------- ------------------------------------------
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0107`.
diff --git a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs
index 354abf99d..52aa4bb31 100644
--- a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs
+++ b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.rs
@@ -24,10 +24,6 @@ mod assert {
Src,
Context,
{ from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
- //~^ ERROR E0080
- //~| ERROR E0080
- //~| ERROR E0080
- //~| ERROR E0080
>,
{}
diff --git a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr
index a258f2ece..c6d93876c 100644
--- a/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr
+++ b/src/test/ui/transmutability/malformed-program-gracefulness/wrong-type-assume.stderr
@@ -1,52 +1,27 @@
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:53:51
+ --> $DIR/wrong-type-assume.rs:49:51
|
LL | assert::is_transmutable::<Src, Dst, Context, {0u8}, false, false, false>();
| ^^^ expected `bool`, found `u8`
-error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, {0u8}, false, false, false>::{constant#0}` failed
- --> $DIR/wrong-type-assume.rs:26:15
- |
-LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:54:58
+ --> $DIR/wrong-type-assume.rs:50:58
|
LL | assert::is_transmutable::<Src, Dst, Context, false, {0u8}, false, false>();
| ^^^ expected `bool`, found `u8`
-error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, {0u8}, false, false>::{constant#0}` failed
- --> $DIR/wrong-type-assume.rs:26:15
- |
-LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:55:65
+ --> $DIR/wrong-type-assume.rs:51:65
|
LL | assert::is_transmutable::<Src, Dst, Context, false, false, {0u8}, false>();
| ^^^ expected `bool`, found `u8`
-error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, {0u8}, false>::{constant#0}` failed
- --> $DIR/wrong-type-assume.rs:26:15
- |
-LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
error[E0308]: mismatched types
- --> $DIR/wrong-type-assume.rs:56:72
+ --> $DIR/wrong-type-assume.rs:52:72
|
LL | assert::is_transmutable::<Src, Dst, Context, false, false, false, {0u8}>();
| ^^^ expected `bool`, found `u8`
-error[E0080]: evaluation of `assert::is_transmutable::<test::Src, test::Dst, test::Context, false, false, false, {0u8}>::{constant#0}` failed
- --> $DIR/wrong-type-assume.rs:26:15
- |
-LL | { from_options(ASSUME_ALIGNMENT, ASSUME_LIFETIMES, ASSUME_SAFETY, ASSUME_VALIDITY) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
-Some errors have detailed explanations: E0080, E0308.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/transmute-equal-assoc-types.rs b/src/test/ui/transmute-equal-assoc-types.rs
index 6f357543e..d1b593b7f 100644
--- a/src/test/ui/transmute-equal-assoc-types.rs
+++ b/src/test/ui/transmute-equal-assoc-types.rs
@@ -1,9 +1,11 @@
+// check-pass
+
trait Foo {
type Bar;
}
unsafe fn noop<F: Foo>(foo: F::Bar) -> F::Bar {
- ::std::mem::transmute(foo) //~ ERROR cannot transmute between types of different sizes
+ ::std::mem::transmute(foo)
}
fn main() {}
diff --git a/src/test/ui/transmute-equal-assoc-types.stderr b/src/test/ui/transmute-equal-assoc-types.stderr
deleted file mode 100644
index ce7657f96..000000000
--- a/src/test/ui/transmute-equal-assoc-types.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
- --> $DIR/transmute-equal-assoc-types.rs:6:5
- |
-LL | ::std::mem::transmute(foo)
- | ^^^^^^^^^^^^^^^^^^^^^
- |
- = note: `<F as Foo>::Bar` does not have a fixed size
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/transmute/lifetimes.rs b/src/test/ui/transmute/lifetimes.rs
new file mode 100644
index 000000000..943191551
--- /dev/null
+++ b/src/test/ui/transmute/lifetimes.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+use std::ptr::NonNull;
+
+struct Foo<'a, T: ?Sized>(&'a (), NonNull<T>);
+
+fn foo<'a, 'b, T: ?Sized>(x: Foo<'a, T>) -> Foo<'b, T> {
+ unsafe { std::mem::transmute(x) }
+}
+
+struct Bar<'a, T: ?Sized>(&'a T);
+
+fn bar<'a, 'b, T: ?Sized>(x: Bar<'a, T>) -> Bar<'b, T> {
+ unsafe { std::mem::transmute(x) }
+}
+
+struct Boo<'a, T: ?Sized>(&'a T, u32);
+
+fn boo<'a, 'b, T: ?Sized>(x: Boo<'a, T>) -> Boo<'b, T> {
+ unsafe { std::mem::transmute(x) }
+}
+
+fn main() {}
diff --git a/src/test/ui/transmute/main.rs b/src/test/ui/transmute/main.rs
index cb46fc5ec..da4a0a660 100644
--- a/src/test/ui/transmute/main.rs
+++ b/src/test/ui/transmute/main.rs
@@ -10,7 +10,7 @@ pub trait TypeConstructor<'a> {
unsafe fn transmute_lifetime<'a, 'b, C>(x: <C as TypeConstructor<'a>>::T)
-> <C as TypeConstructor<'b>>::T
where for<'z> C: TypeConstructor<'z> {
- transmute(x) //~ ERROR cannot transmute between types of different sizes
+ transmute(x)
}
unsafe fn sizes() {
diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr
index f48562094..6cb0d7f67 100644
--- a/src/test/ui/transmute/main.stderr
+++ b/src/test/ui/transmute/main.stderr
@@ -1,12 +1,4 @@
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
- --> $DIR/main.rs:13:5
- |
-LL | transmute(x)
- | ^^^^^^^^^
- |
- = note: `<C as TypeConstructor>::T` does not have a fixed size
-
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/main.rs:17:17
|
LL | let x: u8 = transmute(10u16);
@@ -33,6 +25,6 @@ LL | let x: Foo = transmute(10);
= note: source type: `i32` (32 bits)
= note: target type: `Foo` (0 bits)
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0512`.
diff --git a/src/test/ui/treat-err-as-bug/delay_span_bug.rs b/src/test/ui/treat-err-as-bug/delay_span_bug.rs
index d4d44049c..832afddf8 100644
--- a/src/test/ui/treat-err-as-bug/delay_span_bug.rs
+++ b/src/test/ui/treat-err-as-bug/delay_span_bug.rs
@@ -1,7 +1,7 @@
// compile-flags: -Ztreat-err-as-bug
// failure-status: 101
// error-pattern: aborting due to `-Z treat-err-as-bug=1`
-// error-pattern: [trigger_delay_span_bug] trigger a delay span bug
+// error-pattern: [trigger_delay_span_bug] triggering a delay span bug
// normalize-stderr-test "note: .*\n\n" -> ""
// normalize-stderr-test "thread 'rustc' panicked.*\n" -> ""
// rustc-env:RUST_BACKTRACE=0
diff --git a/src/test/ui/treat-err-as-bug/delay_span_bug.stderr b/src/test/ui/treat-err-as-bug/delay_span_bug.stderr
index c23c2b81b..e9457c8fa 100644
--- a/src/test/ui/treat-err-as-bug/delay_span_bug.stderr
+++ b/src/test/ui/treat-err-as-bug/delay_span_bug.stderr
@@ -7,5 +7,5 @@ LL | fn main() {}
error: internal compiler error: unexpected panic
query stack during panic:
-#0 [trigger_delay_span_bug] trigger a delay span bug
+#0 [trigger_delay_span_bug] triggering a delay span bug
end of query stack
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
index 27e6a603a..419a86bf3 100644
--- a/src/test/ui/try-trait/bad-interconversion.stderr
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -16,7 +16,7 @@ LL | Ok(Err(123_i32)?)
<f64 as From<i16>>
<f64 as From<i32>>
<f64 as From<i8>>
- and 67 others
+ and 68 others
= note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
index aaa3159e0..0202a2fea 100644
--- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
+++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr
@@ -4,7 +4,6 @@ error: ambiguous associated item
LL | fn f() -> Self::V { 0 }
| ^^^^^^^ help: use fully-qualified syntax: `<E as Tr>::V`
|
- = note: `#[deny(ambiguous_associated_items)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
note: `V` could refer to the variant defined here
@@ -17,6 +16,7 @@ note: `V` could also refer to the associated type defined here
|
LL | type V;
| ^^^^^^
+ = note: `#[deny(ambiguous_associated_items)]` on by default
error: ambiguous associated item
--> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15
diff --git a/src/test/ui/type-alias-impl-trait/closure_parent_substs.rs b/src/test/ui/type-alias-impl-trait/closure_parent_substs.rs
new file mode 100644
index 000000000..475f4724f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/closure_parent_substs.rs
@@ -0,0 +1,65 @@
+// When WF checking the hidden type in the ParamEnv of the opaque type,
+// one complication arises when the hidden type is a closure/generator:
+// the "parent_substs" of the type may reference lifetime parameters
+// not present in the opaque type.
+// These region parameters are not really useful in this check.
+// So here we ignore them and replace them with fresh region variables.
+
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// Basic test
+mod test1 {
+ // Hidden type = Closure['_#0r]
+ type Opaque = impl Sized;
+
+ fn define<'a: 'a>() -> Opaque {
+ || {}
+ }
+}
+
+// the region vars cannot both be equal to `'static` or `'empty`
+mod test2 {
+ trait Trait {}
+
+ // Hidden type = Closure['a, '_#0r, '_#1r]
+ // Constraints = [('_#0r: 'a), ('a: '_#1r)]
+ type Opaque<'a>
+ where
+ &'a (): Trait,
+ = impl Sized + 'a;
+
+ fn define<'a, 'x, 'y>() -> Opaque<'a>
+ where
+ &'a (): Trait,
+ 'x: 'a,
+ 'a: 'y,
+ {
+ || {}
+ }
+}
+
+// the region var cannot be equal to `'a` or `'b`
+mod test3 {
+ trait Trait {}
+
+ // Hidden type = Closure['a, 'b, '_#0r]
+ // Constraints = [('_#0r: 'a), ('_#0r: 'b)]
+ type Opaque<'a, 'b>
+ where
+ (&'a (), &'b ()): Trait,
+ = impl Sized + 'a + 'b;
+
+ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
+ where
+ (&'a (), &'b ()): Trait,
+ 'x: 'a,
+ 'x: 'b,
+ {
+ || {}
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs
new file mode 100644
index 000000000..53974dbb3
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs
@@ -0,0 +1,65 @@
+// If the hidden type is a closure, we require the "outlives" bounds that appear on the
+// defining site to also appear on the opaque type.
+//
+// It's not clear if this is the desired behavior but at least
+// it's consistent and has no back-compat risk.
+
+// check-fail
+
+#![feature(type_alias_impl_trait)]
+#![allow(dead_code)]
+
+// requires `'a: 'b` bound
+mod test1 {
+ type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ //~^ ERROR lifetime bound not satisfied
+
+ fn define<'a, 'b>() -> Opaque<'a, 'b>
+ where
+ 'a: 'b,
+ {
+ || {}
+ }
+}
+
+// Same as the above but through indirection `'x`
+mod test2 {
+ type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ //~^ ERROR cannot infer an appropriate lifetime
+
+ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
+ where
+ 'a: 'x,
+ 'x: 'b,
+ {
+ || {}
+ }
+}
+
+// fixed version of the above
+mod test2_fixed {
+ type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b;
+
+ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
+ where
+ 'a: 'x,
+ 'x: 'b,
+ {
+ || {}
+ }
+}
+
+// requires `T: 'static`
+mod test3 {
+ type Opaque<T> = impl Sized;
+ //~^ ERROR the parameter type `T` may not live long enough
+
+ fn define<T>() -> Opaque<T>
+ where
+ T: 'static,
+ {
+ || {}
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr
new file mode 100644
index 000000000..ae6462bb6
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr
@@ -0,0 +1,64 @@
+error[E0478]: lifetime bound not satisfied
+ --> $DIR/closure_wf_outlives.rs:14:27
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: lifetime parameter instantiated with the lifetime `'a` as defined here
+ --> $DIR/closure_wf_outlives.rs:14:17
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^
+note: but lifetime parameter must outlive the lifetime `'b` as defined here
+ --> $DIR/closure_wf_outlives.rs:14:21
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+ --> $DIR/closure_wf_outlives.rs:27:27
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
+ --> $DIR/closure_wf_outlives.rs:27:17
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^
+note: ...so that the declared lifetime parameter bounds are satisfied
+ --> $DIR/closure_wf_outlives.rs:27:27
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^^^^^^^^^^^^^^^^^^^
+note: but, the lifetime must be valid for the lifetime `'b` as defined here...
+ --> $DIR/closure_wf_outlives.rs:27:21
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^
+note: ...so that the declared lifetime parameter bounds are satisfied
+ --> $DIR/closure_wf_outlives.rs:27:27
+ |
+LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error[E0310]: the parameter type `T` may not live long enough
+ --> $DIR/closure_wf_outlives.rs:54:22
+ |
+LL | type Opaque<T> = impl Sized;
+ | ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
+ |
+note: ...that is required by this bound
+ --> $DIR/closure_wf_outlives.rs:59:12
+ |
+LL | T: 'static,
+ | ^^^^^^^
+help: consider adding an explicit lifetime bound...
+ |
+LL | type Opaque<T: 'static> = impl Sized;
+ | +++++++++
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0310, E0478, E0495.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
index 811832848..9a50c0f98 100644
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
+++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.rs
@@ -1,8 +1,9 @@
// compile-flags: --edition=2021
+// check-pass
#![feature(type_alias_impl_trait)]
fn main() {
- type T = impl Copy; //~ ERROR unconstrained opaque type
+ type T = impl Copy;
let foo: T = (1u32, 2u32);
let (a, b): (u32, u32) = foo;
}
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr
deleted file mode 100644
index 03b172e6d..000000000
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
- --> $DIR/cross_inference_pattern_bug.rs:5:14
- |
-LL | type T = impl Copy;
- | ^^^^^^^^^
- |
- = note: `T` must be used in combination with a concrete type within the same module
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
index 328096d44..b929122a6 100644
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
+++ b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.rs
@@ -1,13 +1,13 @@
-// known-bug: #96572
// compile-flags: --edition=2021 --crate-type=lib
// rustc-env:RUST_BACKTRACE=0
+// check-pass
// tracked in https://github.com/rust-lang/rust/issues/96572
#![feature(type_alias_impl_trait)]
fn main() {
- type T = impl Copy; // error: unconstrained opaque type
+ type T = impl Copy;
let foo: T = (1u32, 2u32);
- let (a, b) = foo; // removing this line makes the code compile
+ let (a, b) = foo; // this line used to make the code fail
}
diff --git a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr b/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr
deleted file mode 100644
index 8aa1f4956..000000000
--- a/src/test/ui/type-alias-impl-trait/cross_inference_pattern_bug_no_type.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: unconstrained opaque type
- --> $DIR/cross_inference_pattern_bug_no_type.rs:10:14
- |
-LL | type T = impl Copy; // error: unconstrained opaque type
- | ^^^^^^^^^
- |
- = note: `T` must be used in combination with a concrete type within the same module
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
index 7740f774e..0b8157fe3 100644
--- a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
@@ -1,5 +1,5 @@
#![feature(type_alias_impl_trait)]
-// check-pass
+
fn main() {}
// two definitions with different types
@@ -9,7 +9,7 @@ fn foo() -> Foo {
""
}
-fn bar() -> Foo {
+fn bar() -> Foo { //~ ERROR: concrete type differs from previous defining opaque type use
panic!()
}
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
new file mode 100644
index 000000000..09dadb0af
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/different_defining_uses_never_type.rs:12:13
+ |
+LL | fn bar() -> Foo {
+ | ^^^ expected `&'static str`, got `()`
+ |
+note: previous use here
+ --> $DIR/different_defining_uses_never_type.rs:9:5
+ |
+LL | ""
+ | ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs
new file mode 100644
index 000000000..bc827a8f2
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs
@@ -0,0 +1,12 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait = impl Sized;
+
+struct One;
+fn one() -> Tait { One }
+
+struct Two<T>(T);
+fn two() -> Tait { Two::<()>(todo!()) }
+//~^ ERROR concrete type differs from previous defining opaque type use
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
new file mode 100644
index 000000000..146a57cbb
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+ --> $DIR/different_defining_uses_never_type3.rs:9:13
+ |
+LL | fn two() -> Tait { Two::<()>(todo!()) }
+ | ^^^^ expected `One`, got `Two<()>`
+ |
+note: previous use here
+ --> $DIR/different_defining_uses_never_type3.rs:6:20
+ |
+LL | fn one() -> Tait { One }
+ | ^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
index 4f424b8c6..5f75fdc71 100644
--- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
+++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
@@ -1,7 +1,11 @@
#![feature(type_alias_impl_trait)]
#![allow(dead_code)]
-type OneLifetime<'a, 'b> = impl std::fmt::Debug;
+pub trait Captures<'a> {}
+
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type OneLifetime<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
a
diff --git a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
index 0c50a84e8..546598e8a 100644
--- a/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
+++ b/src/test/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
@@ -1,11 +1,11 @@
error: concrete type differs from previous defining opaque type use
- --> $DIR/different_lifetimes_defining_uses.rs:11:5
+ --> $DIR/different_lifetimes_defining_uses.rs:15:5
|
LL | b
| ^ expected `&'a u32`, got `&'b u32`
|
note: previous use here
- --> $DIR/different_lifetimes_defining_uses.rs:7:5
+ --> $DIR/different_lifetimes_defining_uses.rs:11:5
|
LL | a
| ^
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
index c9b9e128f..9d938a616 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
@@ -2,8 +2,11 @@
fn main() {}
-type Two<'a, 'b> = impl std::fmt::Debug;
+pub trait Captures<'a> {}
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
t
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
index 222aaea78..72e1ef4b4 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
@@ -1,13 +1,13 @@
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_lifetime_param.rs:9:5
+ --> $DIR/generic_duplicate_lifetime_param.rs:12:5
|
LL | t
| ^
|
note: lifetime used multiple times
- --> $DIR/generic_duplicate_lifetime_param.rs:5:10
+ --> $DIR/generic_duplicate_lifetime_param.rs:9:10
|
-LL | type Two<'a, 'b> = impl std::fmt::Debug;
+LL | type Two<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
| ^^ ^^
error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index 093c1c231..80462f8ac 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -7,7 +7,12 @@ fn main() {}
// test that unused generic parameters are ok
type TwoTys<T, U> = impl Debug;
-type TwoLifetimes<'a, 'b> = impl Debug;
+
+pub trait Captures<'a> {}
+
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
type TwoConsts<const X: usize, const Y: usize> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index b2edcc552..98e4bfea1 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,5 +1,5 @@
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:16:5
+ --> $DIR/generic_duplicate_param_use.rs:21:5
|
LL | t
| ^
@@ -11,25 +11,25 @@ LL | type TwoTys<T, U> = impl Debug;
| ^ ^
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:21:5
+ --> $DIR/generic_duplicate_param_use.rs:26:5
|
LL | t
| ^
|
note: lifetime used multiple times
- --> $DIR/generic_duplicate_param_use.rs:10:19
+ --> $DIR/generic_duplicate_param_use.rs:15:19
|
-LL | type TwoLifetimes<'a, 'b> = impl Debug;
+LL | type TwoLifetimes<'a, 'b> = impl Debug + Captures<'a> + Captures<'b>;
| ^^ ^^
error: non-defining opaque type use in defining scope
- --> $DIR/generic_duplicate_param_use.rs:26:5
+ --> $DIR/generic_duplicate_param_use.rs:31:5
|
LL | t
| ^
|
note: constant used multiple times
- --> $DIR/generic_duplicate_param_use.rs:12:16
+ --> $DIR/generic_duplicate_param_use.rs:17:16
|
LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
diff --git a/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs b/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs
index e109c38c9..106efefba 100644
--- a/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs
+++ b/src/test/ui/type-alias-impl-trait/generic_lifetime_param.rs
@@ -1,10 +1,11 @@
-// build-pass (FIXME(62277): could be check-pass?)
+// check-pass
#![feature(type_alias_impl_trait)]
fn main() {}
-type Region<'a> = impl std::fmt::Debug;
+type Region<'a> = impl std::fmt::Debug + 'a;
+
fn region<'b>(a: &'b ()) -> Region<'b> {
a
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.rs b/src/test/ui/type-alias-impl-trait/implied_bounds.rs
new file mode 100644
index 000000000..53cbf8d22
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds.rs
@@ -0,0 +1,51 @@
+#![feature(type_alias_impl_trait)]
+
+type WithLifetime<'a> = impl Equals<SelfType = ()>;
+fn _defining_use<'a>() -> WithLifetime<'a> {}
+
+trait Convert<'a> {
+ type Witness;
+ fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T;
+}
+
+impl<'a> Convert<'a> for () {
+ type Witness = WithLifetime<'a>;
+
+ fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T {
+ // compiler used to think it gets to assume 'a: 'b here because
+ // of the `&'b WithLifetime<'a>` argument
+ x
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
+ WithLifetime::<'a>::convert_helper::<(), T>(&(), x)
+}
+
+trait Equals {
+ type SelfType;
+ fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
+ proof: &'b Self::SelfType,
+ x: &'a T,
+ ) -> &'b T;
+}
+
+impl<S> Equals for S {
+ type SelfType = Self;
+ fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
+ proof: &'b Self,
+ x: &'a T,
+ ) -> &'b T {
+ W::convert(proof, x)
+ }
+}
+
+fn main() {
+ let r;
+ {
+ let x = String::from("Hello World?");
+ r = extend_lifetime(&x);
+ }
+ println!("{}", r);
+}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr
new file mode 100644
index 000000000..6f11b6663
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds.stderr
@@ -0,0 +1,16 @@
+error: lifetime may not live long enough
+ --> $DIR/implied_bounds.rs:17:9
+ |
+LL | impl<'a> Convert<'a> for () {
+ | -- lifetime `'a` defined here
+...
+LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<'a>, x: &'a T) -> &'b T {
+ | -- lifetime `'b` defined here
+...
+LL | x
+ | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs
new file mode 100644
index 000000000..b4c4c013c
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs
@@ -0,0 +1,10 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+type Ty<'a, A> = impl Sized + 'a;
+fn defining<'a, A>() -> Ty<'a, A> {}
+fn assert_static<T: 'static>() {}
+fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() }
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds3.rs b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs
new file mode 100644
index 000000000..e39c61328
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds3.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+fn foo<F>(_: F)
+where
+ F: 'static,
+{
+}
+
+fn from<F: Send>(f: F) -> impl Send {
+ f
+}
+
+fn bar<T>() {
+ foo(from(|| ()))
+}
+
+fn main() {
+}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs
new file mode 100644
index 000000000..4cf35f951
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.rs
@@ -0,0 +1,31 @@
+trait StaticDefaultRef: 'static {
+ fn default_ref() -> &'static Self;
+}
+
+impl StaticDefaultRef for str {
+ fn default_ref() -> &'static str {
+ ""
+ }
+}
+
+fn into_impl(x: &str) -> &(impl ?Sized + AsRef<str> + StaticDefaultRef + '_) {
+ x
+}
+
+fn extend_lifetime<'a>(x: &'a str) -> &'static str {
+ let t = into_impl(x);
+ helper(|_| t) //~ ERROR lifetime may not live long enough
+}
+
+fn helper<T: ?Sized + AsRef<str> + StaticDefaultRef>(f: impl FnOnce(&T) -> &T) -> &'static str {
+ f(T::default_ref()).as_ref()
+}
+
+fn main() {
+ let r;
+ {
+ let x = String::from("Hello World?");
+ r = extend_lifetime(&x);
+ }
+ println!("{}", r);
+}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr
new file mode 100644
index 000000000..151564c3b
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds_closure.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+ --> $DIR/implied_bounds_closure.rs:17:16
+ |
+LL | fn extend_lifetime<'a>(x: &'a str) -> &'static str {
+ | -- lifetime `'a` defined here
+LL | let t = into_impl(x);
+LL | helper(|_| t)
+ | ^ returning this value requires that `'a` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs
new file mode 100644
index 000000000..8023cd24f
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.rs
@@ -0,0 +1,51 @@
+#![feature(type_alias_impl_trait)]
+
+type WithLifetime<T> = impl Equals<SelfType = ()>;
+fn _defining_use<T>() -> WithLifetime<T> {}
+
+trait Convert<'a> {
+ type Witness;
+ fn convert<'b, T: ?Sized>(_proof: &'b Self::Witness, x: &'a T) -> &'b T;
+}
+
+impl<'a> Convert<'a> for () {
+ type Witness = WithLifetime<&'a ()>;
+
+ fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
+ // compiler used to think it gets to assume 'a: 'b here because
+ // of the `&'b WithLifetime<&'a ()>` argument
+ x
+ //~^ ERROR lifetime may not live long enough
+ }
+}
+
+fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T {
+ WithLifetime::<&'a ()>::convert_helper::<(), T>(&(), x)
+}
+
+trait Equals {
+ type SelfType;
+ fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
+ proof: &'b Self::SelfType,
+ x: &'a T,
+ ) -> &'b T;
+}
+
+impl<S> Equals for S {
+ type SelfType = Self;
+ fn convert_helper<'a, 'b, W: Convert<'a, Witness = Self>, T: ?Sized>(
+ proof: &'b Self,
+ x: &'a T,
+ ) -> &'b T {
+ W::convert(proof, x)
+ }
+}
+
+fn main() {
+ let r;
+ {
+ let x = String::from("Hello World?");
+ r = extend_lifetime(&x);
+ }
+ println!("{}", r);
+}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
new file mode 100644
index 000000000..cbc5e6073
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
@@ -0,0 +1,16 @@
+error: lifetime may not live long enough
+ --> $DIR/implied_bounds_from_types.rs:17:9
+ |
+LL | impl<'a> Convert<'a> for () {
+ | -- lifetime `'a` defined here
+...
+LL | fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
+ | -- lifetime `'b` defined here
+...
+LL | x
+ | ^ associated function was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a`
+ |
+ = help: consider adding the following bound: `'a: 'b`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs
new file mode 100644
index 000000000..b6a7264a5
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs
@@ -0,0 +1,27 @@
+#![feature(type_alias_impl_trait)]
+
+// known-bug: #99840
+// this should not compile
+// check-pass
+
+type Alias = impl Sized;
+
+fn constrain() -> Alias {
+ 1i32
+}
+
+trait HideIt {
+ type Assoc;
+}
+
+impl HideIt for () {
+ type Assoc = Alias;
+}
+
+pub trait Yay {}
+
+impl Yay for <() as HideIt>::Assoc {}
+// impl Yay for i32 {} // this already errors
+// impl Yay for u32 {} // this also already errors
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
new file mode 100644
index 000000000..07f825aea
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
@@ -0,0 +1,43 @@
+#![feature(type_alias_impl_trait)]
+
+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
+}
+
+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
+}
+
+mod test_type_param {
+ type Ty<A> = impl Sized;
+ fn defining<A>(s: A) -> Ty<A> { s }
+ fn assert_static<A: 'static>() {}
+ fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
+ //~^ ERROR: parameter type `A` may not live long enough
+}
+
+mod test_implied_from_fn_sig {
+ type Opaque<T: 'static> = impl Sized;
+ fn defining<T: 'static>() -> Opaque<T> {}
+ fn assert_static<T: 'static>() {}
+ fn test<T>(_: Opaque<T>) { assert_static::<T>(); }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
new file mode 100644
index 000000000..887620a4d
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
@@ -0,0 +1,58 @@
+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
+ |
+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
+ |
+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
+ |
+LL | fn test<'a>() { assert_static::<'a>() }
+ | -- ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+ | |
+ | lifetime `'a` defined here
+
+error[E0310]: the parameter type `A` may not live long enough
+ --> $DIR/implied_lifetime_wf_check3.rs:32:41
+ |
+LL | fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
+ | ^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+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
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
new file mode 100644
index 000000000..ac32dbde0
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
@@ -0,0 +1,11 @@
+#![feature(type_alias_impl_trait)]
+
+mod test_type_param_static {
+ type Ty<A> = impl Sized + 'static;
+ //~^ ERROR: the parameter type `A` may not live long enough
+ fn defining<A: 'static>(s: A) -> Ty<A> { s }
+ fn assert_static<A: 'static>() {}
+ fn test<A>() where Ty<A>: 'static { assert_static::<A>() }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
new file mode 100644
index 000000000..47bc31e78
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
@@ -0,0 +1,14 @@
+error[E0310]: the parameter type `A` may not live long enough
+ --> $DIR/implied_lifetime_wf_check4_static.rs:4:18
+ |
+LL | type Ty<A> = impl Sized + 'static;
+ | ^^^^^^^^^^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
+ |
+help: consider adding an explicit lifetime bound...
+ |
+LL | type Ty<A: 'static> = impl Sized + 'static;
+ | +++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0310`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-101750.rs b/src/test/ui/type-alias-impl-trait/issue-101750.rs
new file mode 100644
index 000000000..f564f4fa7
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-101750.rs
@@ -0,0 +1,37 @@
+#![feature(type_alias_impl_trait)]
+
+// check-pass
+
+trait Trait {}
+
+type TAIT = impl Trait;
+
+struct Concrete;
+impl Trait for Concrete {}
+
+fn tait() -> TAIT {
+ Concrete
+}
+
+trait OuterTrait {
+ type Item;
+}
+struct Dummy<T> {
+ t: T,
+}
+impl<T> OuterTrait for Dummy<T> {
+ type Item = T;
+}
+
+fn tait_and_impl_trait() -> impl OuterTrait<Item = (TAIT, impl Trait)> {
+ Dummy {
+ t: (tait(), Concrete),
+ }
+}
+
+fn tait_and_dyn_trait() -> impl OuterTrait<Item = (TAIT, Box<dyn Trait>)> {
+ let b: Box<dyn Trait> = Box::new(Concrete);
+ Dummy { t: (tait(), b) }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
index d20b1cc6d..0a34e8486 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr
@@ -1,10 +1,11 @@
-error[E0275]: overflow evaluating the requirement `fn() -> Foo {foo}: Sized`
+error[E0275]: overflow evaluating the requirement `Foo: Sized`
--> $DIR/issue-53398-cyclic-types.rs:5:13
|
LL | fn foo() -> Foo {
| ^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`)
+ = note: required because it appears within the type `fn() -> Foo {foo}`
error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
index f14bf6b0f..6344f114a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-57611-trait-alias.stderr
@@ -4,7 +4,7 @@ error[E0308]: mismatched types
LL | |x| x
| ^^^^^ one type is more general than the other
|
- = note: expected trait `for<'r> Fn<(&'r X,)>`
+ = note: expected trait `for<'a> Fn<(&'a X,)>`
found trait `Fn<(&X,)>`
note: this closure does not fulfill the lifetime requirements
--> $DIR/issue-57611-trait-alias.rs:21:9
diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs
index f20ddf020..477b61390 100644
--- a/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-58662-generator-with-lifetime.rs
@@ -16,7 +16,7 @@ fn rand_generator<'a>(rng: &'a ()) -> RandGenerator<'a> {
}
}
-pub type RandGeneratorWithIndirection<'a> = impl Generator<Return = (), Yield = u64> + 'a;
+pub type RandGeneratorWithIndirection<'c> = impl Generator<Return = (), Yield = u64> + 'c;
pub fn rand_generator_with_indirection<'a>(rng: &'a ()) -> RandGeneratorWithIndirection<'a> {
fn helper<'b>(rng: &'b ()) -> impl 'b + Generator<Return = (), Yield = u64> {
move || {
diff --git a/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs
new file mode 100644
index 000000000..27ca7d0fd
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-58662-simplified.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+#![feature(generators, generator_trait)]
+#![feature(type_alias_impl_trait)]
+
+trait Trait {}
+
+impl<T> Trait for T {}
+
+type Foo<'c> = impl Trait + 'c;
+fn foo<'a>(rng: &'a ()) -> Foo<'a> {
+ fn helper<'b>(rng: &'b ()) -> impl 'b + Trait {
+ rng
+ }
+
+ helper(rng)
+}
+
+fn main() {
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.rs b/src/test/ui/type-alias-impl-trait/issue-89686.rs
index de070fc9d..058417bdb 100644
--- a/src/test/ui/type-alias-impl-trait/issue-89686.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-89686.rs
@@ -4,7 +4,7 @@
use std::future::Future;
-type G<'a, T> = impl Future<Output = ()>;
+type G<'a, T> = impl Future<Output = ()> + 'a;
trait Trait {
type F: Future<Output = ()>;
diff --git a/src/test/ui/type-alias-impl-trait/issue-89686.stderr b/src/test/ui/type-alias-impl-trait/issue-89686.stderr
index b636ada8b..3b95a575a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-89686.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-89686.stderr
@@ -6,7 +6,7 @@ LL | async move { self.f().await }
|
help: consider restricting type parameter `T`
|
-LL | type G<'a, T: Trait> = impl Future<Output = ()>;
+LL | type G<'a, T: Trait> = impl Future<Output = ()> + 'a;
| +++++++
error: aborting due to previous error
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs
new file mode 100644
index 000000000..825710851
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_impl_trait)]
+
+fn main() {
+ type T = impl Copy;
+ let foo: T = Some((1u32, 2u32));
+ match foo {
+ None => (),
+ Some((a, b, c)) => (), //~ ERROR mismatched types
+ }
+}
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr
new file mode 100644
index 000000000..728244a18
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained-mismatch.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-96572-unconstrained-mismatch.rs:8:14
+ |
+LL | match foo {
+ | --- this expression has type `T`
+LL | None => (),
+LL | Some((a, b, c)) => (),
+ | ^^^^^^^^^ expected a tuple with 2 elements, found one with 3 elements
+ |
+ = note: expected tuple `(u32, u32)`
+ found tuple `(_, _, _)`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
new file mode 100644
index 000000000..2c740ccc1
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
@@ -0,0 +1,92 @@
+#![feature(type_alias_impl_trait)]
+// check-pass
+
+fn main() {
+ type T = impl Copy;
+ let foo: T = Some((1u32, 2u32));
+ match foo {
+ None => (),
+ Some((a, b)) => (),
+ }
+}
+
+fn upvar() {
+ #[derive(Copy, Clone)]
+ struct Foo((u32, u32));
+
+ type T = impl Copy;
+ let foo: T = Foo((1u32, 2u32));
+ let x = move || {
+ let Foo((a, b)) = foo;
+ };
+}
+
+fn enum_upvar() {
+ type T = impl Copy;
+ let foo: T = Some((1u32, 2u32));
+ let x = move || {
+ match foo {
+ None => (),
+ Some((a, b)) => (),
+ }
+ };
+}
+
+fn r#struct() {
+ #[derive(Copy, Clone)]
+ struct Foo((u32, u32));
+
+ type U = impl Copy;
+ let foo: U = Foo((1u32, 2u32));
+ let Foo((a, b)) = foo;
+}
+
+mod only_pattern {
+ type T = impl Copy;
+
+ fn foo(foo: T) {
+ let (mut x, mut y) = foo;
+ x = 42;
+ y = "foo";
+ }
+
+ type U = impl Copy;
+
+ fn bar(bar: Option<U>) {
+ match bar {
+ Some((mut x, mut y)) => {
+ x = 42;
+ y = "foo";
+ }
+ None => {}
+ }
+ }
+}
+
+mod only_pattern_rpit {
+ #[allow(unconditional_recursion)]
+ fn foo(b: bool) -> impl Copy {
+ let (mut x, mut y) = foo(false);
+ x = 42;
+ y = "foo";
+ if b {
+ panic!()
+ } else {
+ foo(true)
+ }
+ }
+
+ fn bar(b: bool) -> Option<impl Copy> {
+ if b {
+ return None;
+ }
+ match bar(!b) {
+ Some((mut x, mut y)) => {
+ x = 42;
+ y = "foo";
+ }
+ None => {}
+ }
+ None
+ }
+}
diff --git a/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.rs
new file mode 100644
index 000000000..428194058
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.rs
@@ -0,0 +1,7 @@
+#![feature(type_alias_impl_trait)]
+
+type Opaque<'a, T> = impl Sized;
+fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
+//~^ ERROR: non-defining opaque type use in defining scope
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
new file mode 100644
index 000000000..df2b3ed19
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
@@ -0,0 +1,8 @@
+error: non-defining opaque type use in defining scope
+ --> $DIR/missing_lifetime_bound.rs:4:47
+ |
+LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
+ | ^ lifetime `'a` is part of concrete type but not used in parameter list of the `impl Trait` type alias
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
index 3f122f106..65eb2952e 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -1,6 +1,10 @@
#![feature(type_alias_impl_trait)]
-type Foo<'a, 'b> = impl std::fmt::Debug;
+pub trait Captures<'a> {}
+
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
(i, i) //~ ERROR concrete type differs from previous
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
index 81e603e23..d7676b8e9 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -1,5 +1,5 @@
error: concrete type differs from previous defining opaque type use
- --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
+ --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5
|
LL | (i, i)
| ^^^^^^
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
index 83fd9a1da..21fca047a 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
@@ -7,7 +7,11 @@ fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>)
(a.clone(), a)
}
-type Foo<'a, 'b> = impl std::fmt::Debug;
+pub trait Captures<'a> {}
+
+impl<'a, T: ?Sized> Captures<'a> for T {}
+
+type Foo<'a, 'b> = impl std::fmt::Debug + Captures<'a> + Captures<'b>;
fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
(i, j)
diff --git a/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs
new file mode 100644
index 000000000..f43ad7dce
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/unbounded_opaque_type.rs
@@ -0,0 +1,14 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+type Opaque<T> = impl Sized;
+fn defining<T>() -> Opaque<T> {}
+struct Ss<'a, T>(&'a Opaque<T>);
+
+
+fn test<'a, T>(_: Ss<'a, T>) {
+ // test that we have an implied bound `Opaque<T>: 'a` from fn signature
+ None::<&'a Opaque<T>>;
+}
+
+fn main() {}
diff --git a/src/test/ui/type/issue-101866.rs b/src/test/ui/type/issue-101866.rs
new file mode 100644
index 000000000..d332c4adb
--- /dev/null
+++ b/src/test/ui/type/issue-101866.rs
@@ -0,0 +1,15 @@
+trait TraitA<T> {
+ fn func();
+}
+
+struct StructA {}
+
+impl TraitA<i32> for StructA {
+ fn func() {}
+}
+
+fn main() {
+ TraitA::<i32>::func();
+ //~^ ERROR: cannot call associated function on trait without specifying the corresponding `impl` type [E0790]
+ //~| help: use the fully-qualified path to the only available implementation
+}
diff --git a/src/test/ui/type/issue-101866.stderr b/src/test/ui/type/issue-101866.stderr
new file mode 100644
index 000000000..fe9982119
--- /dev/null
+++ b/src/test/ui/type/issue-101866.stderr
@@ -0,0 +1,18 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+ --> $DIR/issue-101866.rs:12:5
+ |
+LL | fn func();
+ | ---------- `TraitA::func` defined here
+...
+LL | TraitA::<i32>::func();
+ | ^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+ |
+help: use the fully-qualified path to the only available implementation
+ |
+LL - TraitA::<i32>::func();
+LL + <StructA as TraitA<i32>>::func();
+ |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/type/issue-94187-verbose-type-name.rs b/src/test/ui/type/issue-94187-verbose-type-name.rs
new file mode 100644
index 000000000..902ef5ade
--- /dev/null
+++ b/src/test/ui/type/issue-94187-verbose-type-name.rs
@@ -0,0 +1,13 @@
+// Check to insure that the output of `std::any::type_name` does not change based on -Zverbose
+// when printing constants
+// run-pass
+// edition: 2018
+// revisions: normal verbose
+// [verbose]compile-flags:-Zverbose
+
+struct Wrapper<const VALUE: usize>;
+
+fn main() {
+ assert_eq!(std::any::type_name::<[u32; 0]>(), "[u32; 0]");
+ assert_eq!(std::any::type_name::<Wrapper<0>>(), "issue_94187_verbose_type_name::Wrapper<0>");
+}
diff --git a/src/test/ui/type/type-check/assignment-expected-bool.stderr b/src/test/ui/type/type-check/assignment-expected-bool.stderr
index e2b821f7b..56494baff 100644
--- a/src/test/ui/type/type-check/assignment-expected-bool.stderr
+++ b/src/test/ui/type/type-check/assignment-expected-bool.stderr
@@ -7,7 +7,7 @@ LL | let _: bool = 0 = 0;
help: you might have meant to compare for equality
|
LL | let _: bool = 0 == 0;
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:9:14
@@ -18,7 +18,7 @@ LL | 0 => 0 = 0,
help: you might have meant to compare for equality
|
LL | 0 => 0 == 0,
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:10:14
@@ -29,7 +29,7 @@ LL | _ => 0 = 0,
help: you might have meant to compare for equality
|
LL | _ => 0 == 0,
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:14:17
@@ -40,7 +40,7 @@ LL | true => 0 = 0,
help: you might have meant to compare for equality
|
LL | true => 0 == 0,
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:18:8
@@ -51,7 +51,7 @@ LL | if 0 = 0 {}
help: you might have meant to compare for equality
|
LL | if 0 == 0 {}
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:20:24
@@ -62,7 +62,7 @@ LL | let _: bool = if { 0 = 0 } {
help: you might have meant to compare for equality
|
LL | let _: bool = if { 0 == 0 } {
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:21:9
@@ -73,7 +73,7 @@ LL | 0 = 0
help: you might have meant to compare for equality
|
LL | 0 == 0
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:23:9
@@ -84,7 +84,7 @@ LL | 0 = 0
help: you might have meant to compare for equality
|
LL | 0 == 0
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:26:13
@@ -95,7 +95,7 @@ LL | let _ = (0 = 0)
help: you might have meant to compare for equality
|
LL | let _ = (0 == 0)
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:27:14
@@ -106,7 +106,7 @@ LL | && { 0 = 0 }
help: you might have meant to compare for equality
|
LL | && { 0 == 0 }
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-expected-bool.rs:28:12
@@ -117,7 +117,7 @@ LL | || (0 = 0);
help: you might have meant to compare for equality
|
LL | || (0 == 0);
- | ~~
+ | +
error[E0070]: invalid left-hand side of assignment
--> $DIR/assignment-expected-bool.rs:31:22
diff --git a/src/test/ui/type/type-check/assignment-in-if.rs b/src/test/ui/type/type-check/assignment-in-if.rs
index 8da7b32b4..ada250df2 100644
--- a/src/test/ui/type/type-check/assignment-in-if.rs
+++ b/src/test/ui/type/type-check/assignment-in-if.rs
@@ -40,4 +40,23 @@ fn main() {
) {
println!("{}", x);
}
+
+ if x == x && x = x && x == x {
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+ println!("{}", x);
+ }
+
+ if x == x && x == x && x = x {
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ println!("{}", x);
+ }
+
+ if x = 1 && x == 1 {
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ println!("{}", x);
+ }
}
diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr
index f4ef44e24..8ab08e25e 100644
--- a/src/test/ui/type/type-check/assignment-in-if.stderr
+++ b/src/test/ui/type/type-check/assignment-in-if.stderr
@@ -7,7 +7,7 @@ LL | if x = x {
help: you might have meant to compare for equality
|
LL | if x == x {
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:20:8
@@ -18,7 +18,7 @@ LL | if (x = x) {
help: you might have meant to compare for equality
|
LL | if (x == x) {
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:25:8
@@ -29,7 +29,7 @@ LL | if y = (Foo { foo: x }) {
help: you might have meant to compare for equality
|
LL | if y == (Foo { foo: x }) {
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:30:8
@@ -40,7 +40,7 @@ LL | if 3 = x {
help: you might have meant to compare for equality
|
LL | if 3 == x {
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:36:13
@@ -51,7 +51,7 @@ LL | x = 4
help: you might have meant to compare for equality
|
LL | x == 4
- | ~~
+ | +
error[E0308]: mismatched types
--> $DIR/assignment-in-if.rs:38:13
@@ -62,8 +62,65 @@ LL | x = 5
help: you might have meant to compare for equality
|
LL | x == 5
- | ~~
+ | +
-error: aborting due to 6 previous errors
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:44:18
+ |
+LL | if x == x && x = x && x == x {
+ | ^ expected `bool`, found `usize`
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:44:22
+ |
+LL | if x == x && x = x && x == x {
+ | ^ expected `bool`, found `usize`
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:44:8
+ |
+LL | if x == x && x = x && x == x {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | if x == x && x == x && x == x {
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:51:28
+ |
+LL | if x == x && x == x && x = x {
+ | ^ expected `bool`, found `usize`
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:51:8
+ |
+LL | if x == x && x == x && x = x {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | if x == x && x == x && x == x {
+ | +
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:57:12
+ |
+LL | if x = 1 && x == 1 {
+ | ^ expected `bool`, found integer
+
+error[E0308]: mismatched types
+ --> $DIR/assignment-in-if.rs:57:8
+ |
+LL | if x = 1 && x == 1 {
+ | ^^^^^^^^^^^^^^^ expected `bool`, found `()`
+ |
+help: you might have meant to compare for equality
+ |
+LL | if x == 1 && x == 1 {
+ | +
+
+error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/type/type-mismatch-same-crate-name.stderr b/src/test/ui/type/type-mismatch-same-crate-name.stderr
index 783f747fa..fcafd315e 100644
--- a/src/test/ui/type/type-mismatch-same-crate-name.stderr
+++ b/src/test/ui/type/type-mismatch-same-crate-name.stderr
@@ -6,6 +6,17 @@ LL | a::try_foo(foo2);
| |
| 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`
+ --> $DIR/auxiliary/crate_a2.rs:1:1
+ |
+LL | pub struct Foo;
+ | ^^^^^^^^^^^^^^
+note: struct `main::a::Foo` is defined in crate `crate_a1`
+ --> $DIR/auxiliary/crate_a1.rs:1:1
+ |
+LL | pub struct Foo;
+ | ^^^^^^^^^^^^^^
= note: perhaps two different versions of crate `crate_a1` are being used?
note: function defined here
--> $DIR/auxiliary/crate_a1.rs:10:8
diff --git a/src/test/ui/type/type-recursive-box-shadowed.stderr b/src/test/ui/type/type-recursive-box-shadowed.stderr
index c22d848f3..cb0e98287 100644
--- a/src/test/ui/type/type-recursive-box-shadowed.stderr
+++ b/src/test/ui/type/type-recursive-box-shadowed.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `Foo` has infinite size
--> $DIR/type-recursive-box-shadowed.rs:7:1
|
LL | struct Foo {
- | ^^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^^
LL |
LL | inner: Foo,
| --- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | inner: Box<Foo>,
| ++++ +
diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr
index 320271028..9a4d798f6 100644
--- a/src/test/ui/type/type-recursive.stderr
+++ b/src/test/ui/type/type-recursive.stderr
@@ -2,12 +2,12 @@ error[E0072]: recursive type `T1` has infinite size
--> $DIR/type-recursive.rs:1:1
|
LL | struct T1 {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
LL | foo: isize,
LL | foolish: T1,
| -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | foolish: Box<T1>,
| ++++ +
@@ -16,11 +16,11 @@ error[E0072]: recursive type `T2` has infinite size
--> $DIR/type-recursive.rs:6:1
|
LL | struct T2 {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
LL | inner: Option<T2>,
- | ---------- recursive without indirection
+ | -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T2` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | inner: Option<Box<T2>>,
| ++++ +
@@ -29,11 +29,11 @@ error[E0072]: recursive type `T3` has infinite size
--> $DIR/type-recursive.rs:12:1
|
LL | struct T3 {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
LL | inner: OptionT3,
| -------- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T3` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | inner: Box<OptionT3>,
| ++++ +
@@ -42,11 +42,9 @@ error[E0072]: recursive type `T4` has infinite size
--> $DIR/type-recursive.rs:16:1
|
LL | struct T4(Option<T4>);
- | ^^^^^^^^^ ---------- recursive without indirection
- | |
- | recursive type has infinite size
+ | ^^^^^^^^^ -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T4` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | struct T4(Option<Box<T4>>);
| ++++ +
@@ -55,11 +53,11 @@ error[E0072]: recursive type `T5` has infinite size
--> $DIR/type-recursive.rs:18:1
|
LL | enum T5 {
- | ^^^^^^^ recursive type has infinite size
+ | ^^^^^^^
LL | Variant(Option<T5>),
- | ---------- recursive without indirection
+ | -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T5` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | Variant(Option<Box<T5>>),
| ++++ +
@@ -68,11 +66,11 @@ error[E0072]: recursive type `T6` has infinite size
--> $DIR/type-recursive.rs:22:1
|
LL | enum T6 {
- | ^^^^^^^ recursive type has infinite size
+ | ^^^^^^^
LL | Variant{ field: Option<T6> },
- | ---------- recursive without indirection
+ | -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T6` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
LL | Variant{ field: Option<Box<T6>> },
| ++++ +
@@ -81,14 +79,14 @@ error[E0072]: recursive type `T7` has infinite size
--> $DIR/type-recursive.rs:26:1
|
LL | struct T7 {
- | ^^^^^^^^^ recursive type has infinite size
+ | ^^^^^^^^^
LL | foo: std::cell::Cell<Option<T7>>,
- | --------------------------- recursive without indirection
+ | -- recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T7` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | foo: Box<std::cell::Cell<Option<T7>>>,
- | ++++ +
+LL | foo: std::cell::Cell<Option<Box<T7>>>,
+ | ++++ +
error: aborting due to 7 previous errors
diff --git a/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr b/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
index 6bc9c8498..fc7c23a22 100644
--- a/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
+++ b/src/test/ui/typeck/issue-69378-ice-on-invalid-type-node-after-recovery.stderr
@@ -2,7 +2,9 @@ error: expected identifier, found `0`
--> $DIR/issue-69378-ice-on-invalid-type-node-after-recovery.rs:3:14
|
LL | struct Foo { 0: u8 }
- | ^ expected identifier
+ | --- ^ expected identifier
+ | |
+ | while parsing this struct
error: aborting due to previous error
diff --git a/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr b/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr
index a18c54a29..23e7b7cc3 100644
--- a/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr
+++ b/src/test/ui/typeck/issue-87181/empty-tuple-method.stderr
@@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo}` in the
LL | thing.bar.foo();
| ^^^ method not found in `fn() -> Foo {Foo}`
|
-help: use parentheses to instantiate this tuple struct
+help: use parentheses to construct this tuple struct
|
LL | (thing.bar)().foo();
| + +++
diff --git a/src/test/ui/typeck/issue-87181/enum-variant.stderr b/src/test/ui/typeck/issue-87181/enum-variant.stderr
index 90641410d..2247ea270 100644
--- a/src/test/ui/typeck/issue-87181/enum-variant.stderr
+++ b/src/test/ui/typeck/issue-87181/enum-variant.stderr
@@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for fn item `fn() -> Foo {Foo::Tup}` i
LL | thing.bar.foo();
| ^^^ method not found in `fn() -> Foo {Foo::Tup}`
|
-help: use parentheses to instantiate this tuple variant
+help: use parentheses to construct this tuple variant
|
LL | (thing.bar)().foo();
| + +++
diff --git a/src/test/ui/typeck/issue-87181/tuple-field.stderr b/src/test/ui/typeck/issue-87181/tuple-field.stderr
index c1ca26ee9..0a7d30b61 100644
--- a/src/test/ui/typeck/issue-87181/tuple-field.stderr
+++ b/src/test/ui/typeck/issue-87181/tuple-field.stderr
@@ -4,7 +4,7 @@ error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}`
LL | thing.bar.0;
| ^
|
-help: use parentheses to instantiate this tuple struct
+help: use parentheses to construct this tuple struct
|
LL | (thing.bar)(/* char */, /* u16 */).0;
| + ++++++++++++++++++++++++
diff --git a/src/test/ui/typeck/slow-lhs-suggestion.rs b/src/test/ui/typeck/slow-lhs-suggestion.rs
new file mode 100644
index 000000000..80dfd6835
--- /dev/null
+++ b/src/test/ui/typeck/slow-lhs-suggestion.rs
@@ -0,0 +1,26 @@
+fn main() {
+ 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ //~^ ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+ //~| ERROR invalid left-hand side of assignment
+}
diff --git a/src/test/ui/typeck/slow-lhs-suggestion.stderr b/src/test/ui/typeck/slow-lhs-suggestion.stderr
new file mode 100644
index 000000000..c5bf795ee
--- /dev/null
+++ b/src/test/ui/typeck/slow-lhs-suggestion.stderr
@@ -0,0 +1,187 @@
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:95
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:91
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:87
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:83
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:79
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:75
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:71
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:67
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:63
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:59
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:55
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:51
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:47
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:43
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:39
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:35
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:31
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:27
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:23
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:19
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:15
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:11
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error[E0070]: invalid left-hand side of assignment
+ --> $DIR/slow-lhs-suggestion.rs:2:7
+ |
+LL | 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1 = 1;
+ | - ^
+ | |
+ | cannot assign to this expression
+
+error: aborting due to 23 previous errors
+
+For more information about this error, try `rustc --explain E0070`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr
index ba4b3dac6..6450cc30a 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr
@@ -12,8 +12,8 @@ warning: value assigned to `counter` is never read
LL | counter += 1;
| ^^^^^^^
|
- = note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
+ = note: `#[warn(unused_assignments)]` on by default
warning: unused variable: `counter`
--> $DIR/unboxed-closures-counter-not-moved.rs:24:9
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
index 1254f8dbc..5c06f4e62 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
@@ -4,8 +4,8 @@ warning: unused variable: `x`
LL | move || x += 1;
| ^
|
- = note: `#[warn(unused_variables)]` on by default
= help: did you mean to capture by reference instead?
+ = note: `#[warn(unused_variables)]` on by default
warning: unused variable: `x`
--> $DIR/unboxed-closures-move-mutable.rs:21:17
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index 9833304c6..802696e1b 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -1,4 +1,4 @@
-error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21
|
LL | let x = call_it(&square, 22);
@@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
@@ -14,7 +14,7 @@ note: required by a bound in `call_it`
LL | fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it`
-error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25
|
LL | let y = call_it_mut(&mut square, 22);
@@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
@@ -30,7 +30,7 @@ note: required by a bound in `call_it_mut`
LL | fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut`
-error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> unsafe fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26
|
LL | let z = call_it_once(square, 22);
@@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> unsafe fn(&'a isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
index 54c92e0cd..0bbb9836c 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -1,42 +1,42 @@
-error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-wrong-abi.rs:20:21
|
LL | let x = call_it(&square, 22);
- | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ------- ^^^^^^^ expected an `Fn<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-abi.rs:9:15
|
LL | fn call_it<F: Fn(&isize) -> isize>(_: &F, _: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it`
-error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-wrong-abi.rs:25:25
|
LL | let y = call_it_mut(&mut square, 22);
- | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ----------- ^^^^^^^^^^^ expected an `FnMut<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-abi.rs:12:19
|
LL | fn call_it_mut<F: FnMut(&isize) -> isize>(_: &mut F, _: isize) -> isize {
| ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut`
-error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+error[E0277]: expected a `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
--> $DIR/unboxed-closures-wrong-abi.rs:30:26
|
LL | let z = call_it_once(square, 22);
- | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ | ------------ ^^^^^^ expected an `FnOnce<(&isize,)>` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}`
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+ = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `for<'a> extern "C" fn(&'a isize) -> isize {square}`
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-abi.rs:15:20
|
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index 2fedb5b92..31a66790c 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'a> Fn<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
@@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'a> FnMut<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_mut`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
@@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22);
| |
| required by a bound introduced by this call
|
- = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
+ = help: the trait `for<'a> FnOnce<(&'a isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
= note: unsafe function cannot be called generically without an unsafe block
note: required by a bound in `call_it_once`
--> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20
diff --git a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
index 95c209f47..0dfd22a30 100644
--- a/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
+++ b/src/test/ui/uninhabited/privately-uninhabited-mir-call.stderr
@@ -6,6 +6,11 @@ LL | let y: &mut u32;
...
LL | *y = 2;
| ^^^^^^ `y` used here but it isn't initialized
+ |
+help: consider assigning a value
+ |
+LL | let y: &mut u32 = todo!();
+ | +++++++++
error: aborting due to previous error
diff --git a/src/test/ui/union/union-copy.stderr b/src/test/ui/union/union-copy.stderr
index 8ecdafdde..53ee4dd2e 100644
--- a/src/test/ui/union/union-copy.stderr
+++ b/src/test/ui/union/union-copy.stderr
@@ -1,11 +1,11 @@
error[E0204]: the trait `Copy` may not be implemented for this type
- --> $DIR/union-copy.rs:12:6
+ --> $DIR/union-copy.rs:12:15
|
LL | a: std::mem::ManuallyDrop<String>
| --------------------------------- this field does not implement `Copy`
...
LL | impl Copy for W {}
- | ^^^^
+ | ^
|
note: the `Copy` impl for `ManuallyDrop<String>` requires that `String: Copy`
--> $DIR/union-copy.rs:8:8
diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr
index 9804b1418..c266d2e9e 100644
--- a/src/test/ui/union/union-nonrepresentable.stderr
+++ b/src/test/ui/union/union-nonrepresentable.stderr
@@ -2,15 +2,15 @@ error[E0072]: recursive type `U` has infinite size
--> $DIR/union-nonrepresentable.rs:1:1
|
LL | union U {
- | ^^^^^^^ recursive type has infinite size
+ | ^^^^^^^
LL | a: u8,
LL | b: std::mem::ManuallyDrop<U>,
- | ------------------------- recursive without indirection
+ | - recursive without indirection
|
-help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
|
-LL | b: Box<std::mem::ManuallyDrop<U>>,
- | ++++ +
+LL | b: std::mem::ManuallyDrop<Box<U>>,
+ | ++++ +
error: aborting due to previous error
diff --git a/src/test/ui/union/union-repr-c.stderr b/src/test/ui/union/union-repr-c.stderr
index 9abf440f7..49124eee5 100644
--- a/src/test/ui/union/union-repr-c.stderr
+++ b/src/test/ui/union/union-repr-c.stderr
@@ -4,11 +4,6 @@ error: `extern` block uses type `W`, which is not FFI-safe
LL | static FOREIGN2: W;
| ^ not FFI-safe
|
-note: the lint level is defined here
- --> $DIR/union-repr-c.rs:2:9
- |
-LL | #![deny(improper_ctypes)]
- | ^^^^^^^^^^^^^^^
= help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this union
= note: this union has unspecified layout
note: the type is defined here
@@ -16,6 +11,11 @@ note: the type is defined here
|
LL | union W {
| ^^^^^^^
+note: the lint level is defined here
+ --> $DIR/union-repr-c.rs:2:9
+ |
+LL | #![deny(improper_ctypes)]
+ | ^^^^^^^^^^^^^^^
error: aborting due to previous error
diff --git a/src/test/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/src/test/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
index 7e6885bd7..aa73b824a 100644
--- a/src/test/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
+++ b/src/test/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
@@ -1,8 +1,8 @@
error: unknown lint: `test_unstable_lint`
|
- = note: requested on the command line with `-D unknown-lints`
= note: the `test_unstable_lint` lint is unstable
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+ = note: requested on the command line with `-D unknown-lints`
error: unknown lint: `test_unstable_lint`
|
diff --git a/src/test/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/src/test/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
index 2d1027dd0..2a2a9811b 100644
--- a/src/test/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
+++ b/src/test/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr
@@ -4,13 +4,13 @@ error: unknown lint: `test_unstable_lint`
LL | #![allow(test_unstable_lint)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: the `test_unstable_lint` lint is unstable
+ = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
note: the lint level is defined here
--> $DIR/deny-unstable-lint-inline.rs:3:9
|
LL | #![deny(unknown_lints)]
| ^^^^^^^^^^^^^
- = note: the `test_unstable_lint` lint is unstable
- = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
error: unknown lint: `test_unstable_lint`
--> $DIR/deny-unstable-lint-inline.rs:4:1
diff --git a/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
index 799d740b0..82851c800 100644
--- a/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
+++ b/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
@@ -1,8 +1,8 @@
warning: unknown lint: `test_unstable_lint`
|
- = note: requested on the command line with `-W unknown-lints`
= note: the `test_unstable_lint` lint is unstable
= help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+ = note: requested on the command line with `-W unknown-lints`
warning: unknown lint: `test_unstable_lint`
|
diff --git a/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
index 142558b47..0548cd226 100644
--- a/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
+++ b/src/test/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr
@@ -4,13 +4,13 @@ warning: unknown lint: `test_unstable_lint`
LL | #![allow(test_unstable_lint)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
+ = note: the `test_unstable_lint` lint is unstable
+ = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
note: the lint level is defined here
--> $DIR/warn-unknown-unstable-lint-inline.rs:3:9
|
LL | #![warn(unknown_lints)]
| ^^^^^^^^^^^^^
- = note: the `test_unstable_lint` lint is unstable
- = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
warning: unknown lint: `test_unstable_lint`
--> $DIR/warn-unknown-unstable-lint-inline.rs:4:1
diff --git a/src/test/ui/unresolved/unresolved-candidates.rs b/src/test/ui/unresolved/unresolved-candidates.rs
new file mode 100644
index 000000000..38b227f60
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-candidates.rs
@@ -0,0 +1,13 @@
+mod a {
+ pub trait Trait {}
+}
+
+mod b {
+ use Trait; //~ ERROR unresolved import `Trait`
+}
+
+mod c {
+ impl Trait for () {} //~ ERROR cannot find trait `Trait` in this scope
+}
+
+fn main() {}
diff --git a/src/test/ui/unresolved/unresolved-candidates.stderr b/src/test/ui/unresolved/unresolved-candidates.stderr
new file mode 100644
index 000000000..bbd3eec2a
--- /dev/null
+++ b/src/test/ui/unresolved/unresolved-candidates.stderr
@@ -0,0 +1,26 @@
+error[E0432]: unresolved import `Trait`
+ --> $DIR/unresolved-candidates.rs:6:9
+ |
+LL | use Trait;
+ | ^^^^^ no `Trait` in the root
+ |
+help: consider importing this trait instead
+ |
+LL | use a::Trait;
+ | ~~~~~~~~~
+
+error[E0405]: cannot find trait `Trait` in this scope
+ --> $DIR/unresolved-candidates.rs:10:10
+ |
+LL | impl Trait for () {}
+ | ^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+LL | use a::Trait;
+ |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0405, E0432.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
index b968174dd..6f005fe89 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
@@ -4,12 +4,12 @@ error: call to unsafe function is unsafe and requires unsafe block (error E0133)
LL | unsf();
| ^^^^^^ call to unsafe function
|
+ = note: consult the function's documentation for information on how to avoid undefined behavior
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = note: consult the function's documentation for information on how to avoid undefined behavior
error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5
@@ -45,13 +45,13 @@ error: call to unsafe function is unsafe and requires unsafe block (error E0133)
LL | unsf();
| ^^^^^^ call to unsafe function
|
+ = note: consult the function's documentation for information on how to avoid undefined behavior
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
- = note: consult the function's documentation for information on how to avoid undefined behavior
error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
index e36529365..13c080e5b 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
@@ -4,12 +4,12 @@ error: call to unsafe function `unsf` is unsafe and requires unsafe block (error
LL | unsf();
| ^^^^^^ call to unsafe function
|
+ = note: consult the function's documentation for information on how to avoid undefined behavior
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:4:9
|
LL | #![deny(unsafe_op_in_unsafe_fn)]
| ^^^^^^^^^^^^^^^^^^^^^^
- = note: consult the function's documentation for information on how to avoid undefined behavior
error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:15:5
@@ -45,13 +45,13 @@ error: call to unsafe function `unsf` is unsafe and requires unsafe block (error
LL | unsf();
| ^^^^^^ call to unsafe function
|
+ = note: consult the function's documentation for information on how to avoid undefined behavior
note: the lint level is defined here
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:8
|
LL | #[deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
- = note: consult the function's documentation for information on how to avoid undefined behavior
error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
--> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:31:5
diff --git a/src/test/ui/unsized-locals/borrow-after-move.stderr b/src/test/ui/unsized-locals/borrow-after-move.stderr
index 4f2bc06d4..28ae1c068 100644
--- a/src/test/ui/unsized-locals/borrow-after-move.stderr
+++ b/src/test/ui/unsized-locals/borrow-after-move.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals, unsized_fn_params)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0382]: borrow of moved value: `x`
--> $DIR/borrow-after-move.rs:21:24
diff --git a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
index 59d91bc0c..4f13ec7ac 100644
--- a/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
+++ b/src/test/ui/unsized-locals/by-value-trait-object-safety.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error: the `foo` method cannot be invoked on a trait object
--> $DIR/by-value-trait-object-safety.rs:20:7
diff --git a/src/test/ui/unsized-locals/double-move.stderr b/src/test/ui/unsized-locals/double-move.stderr
index 4bb2ad88f..dfae6cc75 100644
--- a/src/test/ui/unsized-locals/double-move.stderr
+++ b/src/test/ui/unsized-locals/double-move.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals, unsized_fn_params)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0382]: use of moved value: `y`
--> $DIR/double-move.rs:21:22
diff --git a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
index 0f0ff5793..b6002cf89 100644
--- a/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
+++ b/src/test/ui/unsized-locals/issue-30276-feature-flagged.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
--> $DIR/issue-30276-feature-flagged.rs:7:29
diff --git a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
index 4523d41b6..8bbe317ec 100644
--- a/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
+++ b/src/test/ui/unsized-locals/issue-50940-with-feature.stderr
@@ -4,8 +4,8 @@ warning: the feature `unsized_locals` is incomplete and may not be safe to use a
LL | #![feature(unsized_locals, unsized_fn_params)]
| ^^^^^^^^^^^^^^
|
- = note: `#[warn(incomplete_features)]` on by default
= note: see issue #48055 <https://github.com/rust-lang/rust/issues/48055> for more information
+ = note: `#[warn(incomplete_features)]` on by default
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/issue-50940-with-feature.rs:6:5
diff --git a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr
index a67f46cd2..214ddc45c 100644
--- a/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr
+++ b/src/test/ui/unwind-abis/feature-gate-c-unwind.stderr
@@ -4,10 +4,10 @@ warning: unknown lint: `ffi_unwind_calls`
LL | #![allow(ffi_unwind_calls)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `#[warn(unknown_lints)]` on by default
= note: the `ffi_unwind_calls` lint is unstable
= note: see issue #74990 <https://github.com/rust-lang/rust/issues/74990> for more information
= help: add `#![feature(c_unwind)]` to the crate attributes to enable
+ = note: `#[warn(unknown_lints)]` on by default
error[E0658]: C-unwind ABI is experimental and subject to change
--> $DIR/feature-gate-c-unwind.rs:8:8
diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs
index dadf4b121..9a324f004 100644
--- a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs
+++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.rs
@@ -1,6 +1,5 @@
// build-pass
// needs-unwind
-// ignore-wasm32-bare compiled with panic=abort by default
#![feature(c_unwind)]
#![warn(ffi_unwind_calls)]
diff --git a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr
index ed41cb746..937a2b3df 100644
--- a/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr
+++ b/src/test/ui/unwind-abis/ffi-unwind-calls-lint.stderr
@@ -1,17 +1,17 @@
warning: call to foreign function with FFI-unwind ABI
- --> $DIR/ffi-unwind-calls-lint.rs:21:14
+ --> $DIR/ffi-unwind-calls-lint.rs:20:14
|
LL | unsafe { foo(); }
| ^^^^^ call to foreign function with FFI-unwind ABI
|
note: the lint level is defined here
- --> $DIR/ffi-unwind-calls-lint.rs:6:9
+ --> $DIR/ffi-unwind-calls-lint.rs:5:9
|
LL | #![warn(ffi_unwind_calls)]
| ^^^^^^^^^^^^^^^^
warning: call to function pointer with FFI-unwind ABI
- --> $DIR/ffi-unwind-calls-lint.rs:25:5
+ --> $DIR/ffi-unwind-calls-lint.rs:24:5
|
LL | ptr();
| ^^^^^ call to function pointer with FFI-unwind ABI
diff --git a/src/test/ui/unwind-no-uwtable.rs b/src/test/ui/unwind-no-uwtable.rs
index 0440cf488..3bc309233 100644
--- a/src/test/ui/unwind-no-uwtable.rs
+++ b/src/test/ui/unwind-no-uwtable.rs
@@ -1,7 +1,6 @@
// run-pass
// needs-unwind
// ignore-windows target requires uwtable
-// ignore-wasm32-bare no proper panic=unwind support
// compile-flags: -C panic=unwind -C force-unwind-tables=n
use std::panic::{self, AssertUnwindSafe};
diff --git a/src/test/ui/variance/variance-regions-unused-indirect.rs b/src/test/ui/variance/variance-regions-unused-indirect.rs
index 1514e3956..6c2c24ddb 100644
--- a/src/test/ui/variance/variance-regions-unused-indirect.rs
+++ b/src/test/ui/variance/variance-regions-unused-indirect.rs
@@ -1,6 +1,7 @@
// Test that disallow lifetime parameters that are unused.
enum Foo<'a> { //~ ERROR parameter `'a` is never used
+ //~^ ERROR recursive types `Foo` and `Bar` have infinite size
Foo1(Bar<'a>)
}
diff --git a/src/test/ui/variance/variance-regions-unused-indirect.stderr b/src/test/ui/variance/variance-regions-unused-indirect.stderr
index 93710cc13..14fdd8492 100644
--- a/src/test/ui/variance/variance-regions-unused-indirect.stderr
+++ b/src/test/ui/variance/variance-regions-unused-indirect.stderr
@@ -1,3 +1,26 @@
+error[E0072]: recursive types `Foo` and `Bar` have infinite size
+ --> $DIR/variance-regions-unused-indirect.rs:3:1
+ |
+LL | enum Foo<'a> {
+ | ^^^^^^^^^^^^
+LL |
+LL | Foo1(Bar<'a>)
+ | ------- recursive without indirection
+...
+LL | enum Bar<'a> {
+ | ^^^^^^^^^^^^
+LL | Bar1(Foo<'a>)
+ | ------- recursive without indirection
+ |
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle
+ |
+LL ~ Foo1(Box<Bar<'a>>)
+LL | }
+LL |
+LL | enum Bar<'a> {
+LL ~ Bar1(Box<Foo<'a>>)
+ |
+
error[E0392]: parameter `'a` is never used
--> $DIR/variance-regions-unused-indirect.rs:3:10
|
@@ -7,13 +30,14 @@ LL | enum Foo<'a> {
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
error[E0392]: parameter `'a` is never used
- --> $DIR/variance-regions-unused-indirect.rs:7:10
+ --> $DIR/variance-regions-unused-indirect.rs:8:10
|
LL | enum Bar<'a> {
| ^^ unused parameter
|
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
-For more information about this error, try `rustc --explain E0392`.
+Some errors have detailed explanations: E0072, E0392.
+For more information about an error, try `rustc --explain E0072`.
diff --git a/src/test/ui/wf/issue-103573.rs b/src/test/ui/wf/issue-103573.rs
new file mode 100644
index 000000000..bcbf4f941
--- /dev/null
+++ b/src/test/ui/wf/issue-103573.rs
@@ -0,0 +1,22 @@
+trait TraitA {
+ type TypeA;
+}
+
+trait TraitD {
+ type TypeD;
+}
+
+pub trait TraitB {
+ type TypeB: TraitD;
+
+ fn f(_: &<Self::TypeB as TraitD>::TypeD);
+}
+
+pub trait TraitC<E> {
+ type TypeC<'a>: TraitB;
+
+ fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA);
+ //~^ ERROR the trait bound `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied
+}
+
+fn main() {}
diff --git a/src/test/ui/wf/issue-103573.stderr b/src/test/ui/wf/issue-103573.stderr
new file mode 100644
index 000000000..fcf3f15e4
--- /dev/null
+++ b/src/test/ui/wf/issue-103573.stderr
@@ -0,0 +1,14 @@
+error[E0277]: the trait bound `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied
+ --> $DIR/issue-103573.rs:18:5
+ |
+LL | fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB`
+ |
+help: consider further restricting the associated type
+ |
+LL | fn g<'a>(_: &<<Self::TypeC<'a> as TraitB>::TypeB as TraitA>::TypeA) where <<Self as TraitC<E>>::TypeC<'a> as TraitB>::TypeB: TraitA;
+ | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
new file mode 100644
index 000000000..30248a7a3
--- /dev/null
+++ b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied
+ --> $DIR/higher-ranked-fn-type.rs:20:5
+ |
+LL | called()
+ | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())`
+ |
+note: required by a bound in `called`
+ --> $DIR/higher-ranked-fn-type.rs:12:25
+ |
+LL | fn called()
+ | ------ required by a bound in this
+LL | where
+LL | for<'b> fn(&'b ()): Foo,
+ | ^^^ required by this bound in `called`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.rs b/src/test/ui/where-clauses/higher-ranked-fn-type.rs
new file mode 100644
index 000000000..ab6edde4e
--- /dev/null
+++ b/src/test/ui/where-clauses/higher-ranked-fn-type.rs
@@ -0,0 +1,25 @@
+// revisions: quiet verbose
+// [verbose]compile-flags: -Zverbose
+
+#![allow(unused_parens)]
+
+trait Foo {
+ type Assoc;
+}
+
+fn called()
+where
+ for<'b> fn(&'b ()): Foo,
+{
+}
+
+fn caller()
+where
+ (for<'a> fn(&'a ())): Foo,
+{
+ called()
+ //[quiet]~^ ERROR the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied
+ //[verbose]~^^ ERROR the trait bound `for<'b> fn(&ReLateBound(
+}
+
+fn main() {}
diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
new file mode 100644
index 000000000..24660ec35
--- /dev/null
+++ b/src/test/ui/where-clauses/higher-ranked-fn-type.verbose.stderr
@@ -0,0 +1,18 @@
+error[E0277]: the trait bound `for<'b> fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ()): Foo` is not satisfied
+ --> $DIR/higher-ranked-fn-type.rs:20:5
+ |
+LL | called()
+ | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&ReLateBound(DebruijnIndex(1), BoundRegion { var: 0, kind: BrNamed(DefId(0:6 ~ higher_ranked_fn_type[1209]::called::'b), 'b) }) ())`
+ |
+note: required by a bound in `called`
+ --> $DIR/higher-ranked-fn-type.rs:12:25
+ |
+LL | fn called()
+ | ------ required by a bound in this
+LL | where
+LL | for<'b> fn(&'b ()): Foo,
+ | ^^^ required by this bound in `called`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 1a6760d8c..b0006cb90 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -11,9 +11,9 @@ mod versions;
use crate::checksum::Checksums;
use crate::manifest::{Component, Manifest, Package, Rename, Target};
use crate::versions::{PkgType, Versions};
-use std::collections::{BTreeMap, HashMap, HashSet};
+use std::collections::{BTreeMap, HashSet};
use std::env;
-use std::fs::{self, File};
+use std::fs;
use std::path::{Path, PathBuf};
static HOSTS: &[&str] = &[
@@ -184,7 +184,7 @@ static PKG_INSTALLERS: &[&str] = &["x86_64-apple-darwin", "aarch64-apple-darwin"
static MINGW: &[&str] = &["i686-pc-windows-gnu", "x86_64-pc-windows-gnu"];
-static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview"];
+static NIGHTLY_ONLY_COMPONENTS: &[&str] = &["miri-preview", "rust-docs-json-preview"];
macro_rules! t {
($e:expr) => {
@@ -193,6 +193,12 @@ macro_rules! t {
Err(e) => panic!("{} failed with {}", stringify!($e), e),
}
};
+ ($e:expr, $extra:expr) => {
+ match $e {
+ Ok(e) => e,
+ Err(e) => panic!("{} failed with {}: {}", stringify!($e), e, $extra),
+ }
+ };
}
struct Builder {
@@ -239,7 +245,6 @@ fn main() {
impl Builder {
fn build(&mut self) {
- self.check_toolstate();
let manifest = self.build_manifest();
let channel = self.versions.channel().to_string();
@@ -261,29 +266,6 @@ impl Builder {
t!(self.checksums.store_cache());
}
- /// If a tool does not pass its tests on *any* of Linux and Windows, don't ship
- /// it on *all* targets, because tools like Miri can "cross-run" programs for
- /// different targets, for example, run a program for `x86_64-pc-windows-msvc`
- /// on `x86_64-unknown-linux-gnu`.
- /// Right now, we do this only for Miri.
- fn check_toolstate(&mut self) {
- for file in &["toolstates-linux.json", "toolstates-windows.json"] {
- let toolstates: Option<HashMap<String, String>> = File::open(self.input.join(file))
- .ok()
- .and_then(|f| serde_json::from_reader(&f).ok());
- let toolstates = toolstates.unwrap_or_else(|| {
- println!("WARNING: `{}` missing/malformed; assuming all tools failed", file);
- HashMap::default() // Use empty map if anything went wrong.
- });
- // Mark some tools as missing based on toolstate.
- if toolstates.get("miri").map(|s| &*s as &str) != Some("test-pass") {
- println!("Miri tests are not passing, removing component");
- self.versions.disable_version(&PkgType::Miri);
- break;
- }
- }
- }
-
fn build_manifest(&mut self) -> Manifest {
let mut manifest = Manifest {
manifest_version: "2".to_string(),
@@ -318,6 +300,7 @@ impl Builder {
package!("rust-mingw", MINGW);
package!("rust-std", TARGETS);
self.package("rust-docs", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
+ self.package("rust-docs-json-preview", &mut manifest.pkg, HOSTS, DOCS_FALLBACK);
package!("rust-src", &["*"]);
package!("rls-preview", HOSTS);
package!("rust-analyzer-preview", HOSTS);
@@ -403,6 +386,7 @@ impl Builder {
rename("rustfmt", "rustfmt-preview");
rename("clippy", "clippy-preview");
rename("miri", "miri-preview");
+ rename("rust-docs-json", "rust-docs-json-preview");
rename("rust-analyzer", "rust-analyzer-preview");
}
@@ -459,6 +443,7 @@ impl Builder {
host_component("rustfmt-preview"),
host_component("llvm-tools-preview"),
host_component("rust-analysis"),
+ host_component("rust-docs-json-preview"),
]);
extensions.extend(
@@ -543,8 +528,18 @@ impl Builder {
for (substr, fallback_target) in fallback {
if target_name.contains(substr) {
let t = Target::from_compressed_tar(self, &tarball_name!(fallback_target));
- // Fallbacks must always be available.
- assert!(t.available);
+ // Fallbacks should typically be available on 'production' builds
+ // but may not be available for try builds, which only build one target by
+ // default. Ideally we'd gate this being a hard error on whether we're in a
+ // production build or not, but it's not information that's readily available
+ // here.
+ if !t.available {
+ eprintln!(
+ "{:?} not available for fallback",
+ tarball_name!(fallback_target)
+ );
+ continue;
+ }
return t;
}
}
@@ -595,7 +590,7 @@ impl Builder {
self.shipped_files.insert(name.clone());
let dst = self.output.join(name);
- t!(fs::write(&dst, contents));
+ t!(fs::write(&dst, contents), format!("failed to create manifest {}", dst.display()));
}
fn write_shipped_files(&self, path: &Path) {
diff --git a/src/tools/build-manifest/src/versions.rs b/src/tools/build-manifest/src/versions.rs
index 95c2297de..0186194a4 100644
--- a/src/tools/build-manifest/src/versions.rs
+++ b/src/tools/build-manifest/src/versions.rs
@@ -20,6 +20,7 @@ pub(crate) enum PkgType {
Rustfmt,
LlvmTools,
Miri,
+ JsonDocs,
Other(String),
}
@@ -36,6 +37,7 @@ impl PkgType {
"rustfmt" | "rustfmt-preview" => PkgType::Rustfmt,
"llvm-tools" | "llvm-tools-preview" => PkgType::LlvmTools,
"miri" | "miri-preview" => PkgType::Miri,
+ "rust-docs-json" | "rust-docs-json-preview" => PkgType::JsonDocs,
other => PkgType::Other(other.into()),
}
}
@@ -53,6 +55,7 @@ impl PkgType {
PkgType::Rustfmt => "rustfmt",
PkgType::LlvmTools => "llvm-tools",
PkgType::Miri => "miri",
+ PkgType::JsonDocs => "rust-docs-json",
PkgType::Other(component) => component,
}
}
@@ -72,6 +75,7 @@ impl PkgType {
PkgType::Rust => true,
PkgType::RustSrc => true,
PkgType::Rustc => true,
+ PkgType::JsonDocs => true,
PkgType::Other(_) => true,
}
}
@@ -113,6 +117,9 @@ impl Versions {
Some(version) => Ok(version.clone()),
None => {
let version_info = self.load_version_from_tarball(package)?;
+ if *package == PkgType::Rust && version_info.version.is_none() {
+ panic!("missing version info for toolchain");
+ }
self.versions.insert(package.clone(), version_info.clone());
Ok(version_info)
}
@@ -127,6 +134,7 @@ impl Versions {
Ok(file) => file,
Err(err) if err.kind() == std::io::ErrorKind::NotFound => {
// Missing tarballs do not return an error, but return empty data.
+ println!("warning: missing tarball {}", tarball.display());
return Ok(VersionInfo::default());
}
Err(err) => return Err(err.into()),
@@ -157,17 +165,6 @@ impl Versions {
Ok(VersionInfo { version, git_commit, present: true })
}
- pub(crate) fn disable_version(&mut self, package: &PkgType) {
- match self.versions.get_mut(package) {
- Some(version) => {
- *version = VersionInfo::default();
- }
- None => {
- self.versions.insert(package.clone(), VersionInfo::default());
- }
- }
- }
-
pub(crate) fn archive_name(
&self,
package: &PkgType,
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 95fe98a68..7044cb892 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -73,7 +73,7 @@ const TEST_REPOS: &[Test] = &[
Test {
name: "servo",
repo: "https://github.com/servo/servo",
- sha: "caac107ae8145ef2fd20365e2b8fadaf09c2eb3b",
+ sha: "785a344e32db58d4e631fd3cae17fd1f29a721ab",
lock: None,
// Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
// This takes much less time to build than all of Servo and supports stable Rust.
@@ -206,6 +206,10 @@ fn run_cargo_test(
.env("CFG_DISABLE_CROSS_TESTS", "1")
// Relax #![deny(warnings)] in some crates
.env("RUSTFLAGS", "--cap-lints warn")
+ // servo tries to use 'lld-link.exe' on windows, but we don't
+ // have lld on our PATH in CI. Override it to use 'link.exe'
+ .env("CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER", "link.exe")
+ .env("CARGO_TARGET_I686_PC_WINDOWS_MSVC_LINKER", "link.exe")
.current_dir(crate_path)
.status()
.unwrap();
diff --git a/src/tools/clippy/.github/workflows/clippy.yml b/src/tools/clippy/.github/workflows/clippy.yml
index fac2c9971..b99213011 100644
--- a/src/tools/clippy/.github/workflows/clippy.yml
+++ b/src/tools/clippy/.github/workflows/clippy.yml
@@ -25,6 +25,7 @@ env:
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
NO_FMT_TEST: 1
CARGO_INCREMENTAL: 0
+ CARGO_UNSTABLE_SPARSE_REGISTRY: true
jobs:
base:
diff --git a/src/tools/clippy/.github/workflows/clippy_bors.yml b/src/tools/clippy/.github/workflows/clippy_bors.yml
index 30607af49..6448b2d40 100644
--- a/src/tools/clippy/.github/workflows/clippy_bors.yml
+++ b/src/tools/clippy/.github/workflows/clippy_bors.yml
@@ -11,6 +11,7 @@ env:
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
NO_FMT_TEST: 1
CARGO_INCREMENTAL: 0
+ CARGO_UNSTABLE_SPARSE_REGISTRY: true
defaults:
run:
diff --git a/src/tools/clippy/.github/workflows/clippy_dev.yml b/src/tools/clippy/.github/workflows/clippy_dev.yml
index 22051093c..14f20212a 100644
--- a/src/tools/clippy/.github/workflows/clippy_dev.yml
+++ b/src/tools/clippy/.github/workflows/clippy_dev.yml
@@ -15,6 +15,8 @@ on:
env:
RUST_BACKTRACE: 1
+ CARGO_INCREMENTAL: 0
+ CARGO_UNSTABLE_SPARSE_REGISTRY: true
jobs:
clippy_dev:
diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md
index d847e4c74..2d7bda27e 100644
--- a/src/tools/clippy/CHANGELOG.md
+++ b/src/tools/clippy/CHANGELOG.md
@@ -6,11 +6,161 @@ document.
## Unreleased / In Rust Nightly
-[d7b5cbf0...master](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...master)
+[3c7e7dbc...master](https://github.com/rust-lang/rust-clippy/compare/3c7e7dbc...master)
+
+## Rust 1.64
+
+Current stable, released 2022-09-22
+
+[d7b5cbf0...3c7e7dbc](https://github.com/rust-lang/rust-clippy/compare/d7b5cbf0...3c7e7dbc)
+
+### New Lints
+
+* [`arithmetic_side_effects`]
+ [#9130](https://github.com/rust-lang/rust-clippy/pull/9130)
+* [`invalid_utf8_in_unchecked`]
+ [#9105](https://github.com/rust-lang/rust-clippy/pull/9105)
+* [`assertions_on_result_states`]
+ [#9225](https://github.com/rust-lang/rust-clippy/pull/9225)
+* [`manual_find`]
+ [#8649](https://github.com/rust-lang/rust-clippy/pull/8649)
+* [`manual_retain`]
+ [#8972](https://github.com/rust-lang/rust-clippy/pull/8972)
+* [`default_instead_of_iter_empty`]
+ [#8989](https://github.com/rust-lang/rust-clippy/pull/8989)
+* [`manual_rem_euclid`]
+ [#9031](https://github.com/rust-lang/rust-clippy/pull/9031)
+* [`obfuscated_if_else`]
+ [#9148](https://github.com/rust-lang/rust-clippy/pull/9148)
+* [`std_instead_of_core`]
+ [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
+* [`std_instead_of_alloc`]
+ [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
+* [`alloc_instead_of_core`]
+ [#9103](https://github.com/rust-lang/rust-clippy/pull/9103)
+* [`explicit_auto_deref`]
+ [#8355](https://github.com/rust-lang/rust-clippy/pull/8355)
+
+
+### Moves and Deprecations
+
+* Moved [`format_push_string`] to `restriction` (now allow-by-default)
+ [#9161](https://github.com/rust-lang/rust-clippy/pull/9161)
+
+### Enhancements
+
+* [`significant_drop_in_scrutinee`]: Now gives more context in the lint message
+ [#8981](https://github.com/rust-lang/rust-clippy/pull/8981)
+* [`single_match`], [`single_match_else`]: Now catches more `Option` cases
+ [#8985](https://github.com/rust-lang/rust-clippy/pull/8985)
+* [`unused_async`]: Now works for async methods
+ [#9025](https://github.com/rust-lang/rust-clippy/pull/9025)
+* [`manual_filter_map`], [`manual_find_map`]: Now lint more expressions
+ [#8958](https://github.com/rust-lang/rust-clippy/pull/8958)
+* [`question_mark`]: Now works for simple `if let` expressions
+ [#8356](https://github.com/rust-lang/rust-clippy/pull/8356)
+* [`undocumented_unsafe_blocks`]: Now finds comments before the start of closures
+ [#9117](https://github.com/rust-lang/rust-clippy/pull/9117)
+* [`trait_duplication_in_bounds`]: Now catches duplicate bounds in where clauses
+ [#8703](https://github.com/rust-lang/rust-clippy/pull/8703)
+* [`shadow_reuse`], [`shadow_same`], [`shadow_unrelated`]: Now lint in const blocks
+ [#9124](https://github.com/rust-lang/rust-clippy/pull/9124)
+* [`slow_vector_initialization`]: Now detects cases with `vec.capacity()`
+ [#8953](https://github.com/rust-lang/rust-clippy/pull/8953)
+* [`unused_self`]: Now respects the `avoid-breaking-exported-api` config option
+ [#9199](https://github.com/rust-lang/rust-clippy/pull/9199)
+* [`box_collection`]: Now supports all std collections
+ [#9170](https://github.com/rust-lang/rust-clippy/pull/9170)
+
+### False Positive Fixes
+
+* [`significant_drop_in_scrutinee`]: Now ignores calls to `IntoIterator::into_iter`
+ [#9140](https://github.com/rust-lang/rust-clippy/pull/9140)
+* [`while_let_loop`]: Now ignores cases when the significant drop order would change
+ [#8981](https://github.com/rust-lang/rust-clippy/pull/8981)
+* [`branches_sharing_code`]: Now ignores cases where moved variables have a significant
+ drop or variable modifications can affect the conditions
+ [#9138](https://github.com/rust-lang/rust-clippy/pull/9138)
+* [`let_underscore_lock`]: Now ignores bindings that aren't locked
+ [#8990](https://github.com/rust-lang/rust-clippy/pull/8990)
+* [`trivially_copy_pass_by_ref`]: Now tracks lifetimes and ignores cases where unsafe
+ pointers are used
+ [#8639](https://github.com/rust-lang/rust-clippy/pull/8639)
+* [`let_unit_value`]: No longer ignores `#[allow]` attributes on the value
+ [#9082](https://github.com/rust-lang/rust-clippy/pull/9082)
+* [`declare_interior_mutable_const`]: Now ignores the `thread_local!` macro
+ [#9015](https://github.com/rust-lang/rust-clippy/pull/9015)
+* [`if_same_then_else`]: Now ignores branches with `todo!` and `unimplemented!`
+ [#9006](https://github.com/rust-lang/rust-clippy/pull/9006)
+* [`enum_variant_names`]: Now ignores names with `_` prefixes
+ [#9032](https://github.com/rust-lang/rust-clippy/pull/9032)
+* [`let_unit_value`]: Now ignores cases, where the unit type is manually specified
+ [#9056](https://github.com/rust-lang/rust-clippy/pull/9056)
+* [`match_same_arms`]: Now ignores branches with `todo!`
+ [#9207](https://github.com/rust-lang/rust-clippy/pull/9207)
+* [`assign_op_pattern`]: Ignores cases that break borrowing rules
+ [#9214](https://github.com/rust-lang/rust-clippy/pull/9214)
+* [`extra_unused_lifetimes`]: No longer triggers in derive macros
+ [#9037](https://github.com/rust-lang/rust-clippy/pull/9037)
+* [`mismatching_type_param_order`]: Now ignores complicated generic parameters
+ [#9146](https://github.com/rust-lang/rust-clippy/pull/9146)
+* [`equatable_if_let`]: No longer lints in macros
+ [#9074](https://github.com/rust-lang/rust-clippy/pull/9074)
+* [`new_without_default`]: Now ignores generics and lifetime parameters on `fn new`
+ [#9115](https://github.com/rust-lang/rust-clippy/pull/9115)
+* [`needless_borrow`]: Now ignores cases that result in the execution of different traits
+ [#9096](https://github.com/rust-lang/rust-clippy/pull/9096)
+* [`declare_interior_mutable_const`]: No longer triggers in thread-local initializers
+ [#9246](https://github.com/rust-lang/rust-clippy/pull/9246)
+
+### Suggestion Fixes/Improvements
+
+* [`type_repetition_in_bounds`]: The suggestion now works with maybe bounds
+ [#9132](https://github.com/rust-lang/rust-clippy/pull/9132)
+* [`transmute_ptr_to_ref`]: Now suggests `pointer::cast` when possible
+ [#8939](https://github.com/rust-lang/rust-clippy/pull/8939)
+* [`useless_format`]: Now suggests the correct variable name
+ [#9237](https://github.com/rust-lang/rust-clippy/pull/9237)
+* [`or_fun_call`]: The lint emission will now only span over the `unwrap_or` call
+ [#9144](https://github.com/rust-lang/rust-clippy/pull/9144)
+* [`neg_multiply`]: Now suggests adding parentheses around suggestion if needed
+ [#9026](https://github.com/rust-lang/rust-clippy/pull/9026)
+* [`unnecessary_lazy_evaluations`]: Now suggest for `bool::then_some` for lazy evaluation
+ [#9099](https://github.com/rust-lang/rust-clippy/pull/9099)
+* [`manual_flatten`]: Improved message for long code snippets
+ [#9156](https://github.com/rust-lang/rust-clippy/pull/9156)
+* [`explicit_counter_loop`]: The suggestion is now machine applicable
+ [#9149](https://github.com/rust-lang/rust-clippy/pull/9149)
+* [`needless_borrow`]: Now keeps parentheses around fields, when needed
+ [#9210](https://github.com/rust-lang/rust-clippy/pull/9210)
+* [`while_let_on_iterator`]: The suggestion now works in `FnOnce` closures
+ [#9134](https://github.com/rust-lang/rust-clippy/pull/9134)
+
+### ICE Fixes
+
+* Fix ICEs related to `#![feature(generic_const_exprs)]` usage
+ [#9241](https://github.com/rust-lang/rust-clippy/pull/9241)
+* Fix ICEs related to reference lints
+ [#9093](https://github.com/rust-lang/rust-clippy/pull/9093)
+* [`question_mark`]: Fix ICE on zero field tuple structs
+ [#9244](https://github.com/rust-lang/rust-clippy/pull/9244)
+
+### Documentation Improvements
+
+* [`needless_option_take`]: Now includes a "What it does" and "Why is this bad?" section.
+ [#9022](https://github.com/rust-lang/rust-clippy/pull/9022)
+
+### Others
+
+* Using `--cap-lints=allow` and only `--force-warn`ing some will now work with Clippy's driver
+ [#9036](https://github.com/rust-lang/rust-clippy/pull/9036)
+* Clippy now tries to read the `rust-version` from `Cargo.toml` to identify the
+ minimum supported rust version
+ [#8774](https://github.com/rust-lang/rust-clippy/pull/8774)
## Rust 1.63
-Current stable, released 2022-08-11
+Released 2022-08-11
[7c21f91b...d7b5cbf0](https://github.com/rust-lang/rust-clippy/compare/7c21f91b...d7b5cbf0)
@@ -3585,6 +3735,7 @@ Released 2018-09-13
[`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
[`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
+[`as_ptr_cast_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_ptr_cast_mut
[`as_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore
[`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants
[`assertions_on_result_states`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_result_states
@@ -3609,6 +3760,7 @@ Released 2018-09-13
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection
+[`box_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_default
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
@@ -3621,6 +3773,7 @@ Released 2018-09-13
[`cast_enum_constructor`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_constructor
[`cast_enum_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_enum_truncation
[`cast_lossless`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_lossless
+[`cast_nan_to_int`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_nan_to_int
[`cast_possible_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_truncation
[`cast_possible_wrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_possible_wrap
[`cast_precision_loss`]: https://rust-lang.github.io/rust-clippy/master/index.html#cast_precision_loss
@@ -3669,6 +3822,7 @@ Released 2018-09-13
[`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
[`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
[`derive_partial_eq_without_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_partial_eq_without_eq
+[`disallowed_macros`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_macros
[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
[`disallowed_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_methods
[`disallowed_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_names
@@ -3766,6 +3920,7 @@ Released 2018-09-13
[`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
+[`implicit_saturating_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_add
[`implicit_saturating_sub`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_saturating_sub
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
@@ -3800,6 +3955,7 @@ Released 2018-09-13
[`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
[`iter_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_count
+[`iter_kv_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_kv_map
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
[`iter_next_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_slice
[`iter_not_returning_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_not_returning_iterator
@@ -3833,6 +3989,8 @@ Released 2018-09-13
[`manual_assert`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert
[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn
[`manual_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_bits
+[`manual_clamp`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_clamp
+[`manual_filter`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter
[`manual_filter_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_filter_map
[`manual_find`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find
[`manual_find_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_find_map
@@ -3891,6 +4049,7 @@ Released 2018-09-13
[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
+[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals
[`mixed_read_write_in_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_read_write_in_expression
@@ -3976,6 +4135,7 @@ Released 2018-09-13
[`panic_in_result_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_in_result_fn
[`panic_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#panic_params
[`panicking_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#panicking_unwrap
+[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#partial_pub_fields
[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl
[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
@@ -4123,6 +4283,7 @@ Released 2018-09-13
[`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented
[`uninit_assumed_init`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_assumed_init
[`uninit_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninit_vec
+[`uninlined_format_args`]: https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
[`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg
[`unit_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_cmp
[`unit_hash`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_hash
@@ -4156,6 +4317,7 @@ Released 2018-09-13
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
+[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs
[`unused_io_amount`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_io_amount
[`unused_label`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_label
[`unused_peekable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_peekable
diff --git a/src/tools/clippy/CONTRIBUTING.md b/src/tools/clippy/CONTRIBUTING.md
index 28b4cfd5f..85f94a74a 100644
--- a/src/tools/clippy/CONTRIBUTING.md
+++ b/src/tools/clippy/CONTRIBUTING.md
@@ -29,7 +29,7 @@ All contributors are expected to follow the [Rust Code of Conduct].
## The Clippy book
-If you're new to Clippy and don't know where to start the [Clippy book] includes
+If you're new to Clippy and don't know where to start, the [Clippy book] includes
a [developer guide] and is a good place to start your journey.
[Clippy book]: https://doc.rust-lang.org/nightly/clippy/index.html
@@ -110,23 +110,28 @@ Just make sure to remove the dependencies again before finally making a pull req
[IntelliJ_rust_homepage]: https://intellij-rust.github.io/
### Rust Analyzer
-As of [#6869][6869], [`rust-analyzer`][ra_homepage] can understand that Clippy uses compiler-internals
-using `extern crate` when `package.metadata.rust-analyzer.rustc_private` is set to `true` in Clippy's `Cargo.toml.`
-You will require a `nightly` toolchain with the `rustc-dev` component installed.
-Make sure that in the `rust-analyzer` configuration, you set
+For [`rust-analyzer`][ra_homepage] to work correctly make sure that in the `rust-analyzer` configuration you set
+
```json
{ "rust-analyzer.rustc.source": "discover" }
```
-and
-```json
-{ "rust-analyzer.updates.channel": "nightly" }
-```
+
You should be able to see information on things like `Expr` or `EarlyContext` now if you hover them, also
a lot more type hints.
-This will work with `rust-analyzer 2021-03-15` shipped in nightly `1.52.0-nightly (107896c32 2021-03-15)` or later.
+
+To have `rust-analyzer` also work in the `clippy_dev` and `lintcheck` crates, add the following configuration
+
+```json
+{
+ "rust-analyzer.linkedProjects": [
+ "./Cargo.toml",
+ "clippy_dev/Cargo.toml",
+ "lintcheck/Cargo.toml",
+ ]
+}
+```
[ra_homepage]: https://rust-analyzer.github.io/
-[6869]: https://github.com/rust-lang/rust-clippy/pull/6869
## How Clippy works
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index b7e136ce9..60200a88b 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "clippy"
-version = "0.1.65"
+version = "0.1.66"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
@@ -23,12 +23,12 @@ path = "src/driver.rs"
[dependencies]
clippy_lints = { path = "clippy_lints" }
semver = "1.0"
-rustc_tools_util = { path = "rustc_tools_util" }
+rustc_tools_util = "0.2.1"
tempfile = { version = "3.2", optional = true }
termize = "0.1"
[dev-dependencies]
-compiletest_rs = { version = "0.8", features = ["tmp"] }
+compiletest_rs = { version = "0.9", features = ["tmp"] }
tester = "0.9"
regex = "1.5"
toml = "0.5"
@@ -55,7 +55,7 @@ tokio = { version = "1", features = ["io-util"] }
rustc-semver = "1.1"
[build-dependencies]
-rustc_tools_util = { version = "0.2", path = "rustc_tools_util" }
+rustc_tools_util = "0.2.1"
[features]
deny-warnings = ["clippy_lints/deny-warnings"]
diff --git a/src/tools/clippy/README.md b/src/tools/clippy/README.md
index 1193771ff..a8a6b86d2 100644
--- a/src/tools/clippy/README.md
+++ b/src/tools/clippy/README.md
@@ -139,25 +139,6 @@ line. (You can swap `clippy::all` with the specific lint category you are target
## Configuration
-Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable =
-value` mapping e.g.
-
-```toml
-avoid-breaking-exported-api = false
-disallowed-names = ["toto", "tata", "titi"]
-cognitive-complexity-threshold = 30
-```
-
-See the [list of lints](https://rust-lang.github.io/rust-clippy/master/index.html) for more information about which
-lints can be configured and the meaning of the variables.
-
-Note that configuration changes will not apply for code that has already been compiled and cached under `./target/`;
-for example, adding a new string to `doc-valid-idents` may still result in Clippy flagging that string. To be sure that
-any configuration changes are applied, you may want to run `cargo clean` and re-compile your crate from scratch.
-
-To deactivate the “for further information visit *lint-link*” message you can
-define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable.
-
### Allowing/denying lints
You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
@@ -205,6 +186,33 @@ the lint(s) you are interested in:
cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
```
+### Configure the behavior of some lints
+
+Some lints can be configured in a TOML file named `clippy.toml` or `.clippy.toml`. It contains a basic `variable =
+value` mapping e.g.
+
+```toml
+avoid-breaking-exported-api = false
+disallowed-names = ["toto", "tata", "titi"]
+cognitive-complexity-threshold = 30
+```
+
+See the [list of lints](https://rust-lang.github.io/rust-clippy/master/index.html) for more information about which
+lints can be configured and the meaning of the variables.
+
+> **Note**
+>
+> `clippy.toml` or `.clippy.toml` cannot be used to allow/deny lints.
+
+> **Note**
+>
+> Configuration changes will not apply for code that has already been compiled and cached under `./target/`;
+> for example, adding a new string to `doc-valid-idents` may still result in Clippy flagging that string. To be sure
+> that any configuration changes are applied, you may want to run `cargo clean` and re-compile your crate from scratch.
+
+To deactivate the “for further information visit *lint-link*” message you can
+define the `CLIPPY_DISABLE_DOCS_LINKS` environment variable.
+
### Specifying the minimum supported Rust version
Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
diff --git a/src/tools/clippy/book/src/development/adding_lints.md b/src/tools/clippy/book/src/development/adding_lints.md
index da781eb97..3c3f368a5 100644
--- a/src/tools/clippy/book/src/development/adding_lints.md
+++ b/src/tools/clippy/book/src/development/adding_lints.md
@@ -90,6 +90,7 @@ We start by opening the test file created at `tests/ui/foo_functions.rs`.
Update the file with some examples to get started:
```rust
+#![allow(unused)]
#![warn(clippy::foo_functions)]
// Impl methods
@@ -477,8 +478,27 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
```
Once the `msrv` is added to the lint, a relevant test case should be added to
-`tests/ui/min_rust_version_attr.rs` which verifies that the lint isn't emitted
-if the project's MSRV is lower.
+the lint's test file, `tests/ui/manual_strip.rs` in this example. It should
+have a case for the version below the MSRV and one with the same contents but
+for the MSRV version itself.
+
+```rust
+#![feature(custom_inner_attributes)]
+
+...
+
+fn msrv_1_44() {
+ #![clippy::msrv = "1.44"]
+
+ /* something that would trigger the lint */
+}
+
+fn msrv_1_45() {
+ #![clippy::msrv = "1.45"]
+
+ /* something that would trigger the lint */
+}
+```
As a last step, the lint should be added to the lint documentation. This is done
in `clippy_lints/src/utils/conf.rs`:
diff --git a/src/tools/clippy/book/src/development/basics.md b/src/tools/clippy/book/src/development/basics.md
index 44ba6e327..6fb53236e 100644
--- a/src/tools/clippy/book/src/development/basics.md
+++ b/src/tools/clippy/book/src/development/basics.md
@@ -69,7 +69,7 @@ the reference file with:
cargo dev bless
```
-For example, this is necessary, if you fix a typo in an error message of a lint
+For example, this is necessary if you fix a typo in an error message of a lint,
or if you modify a test file to add a test case.
> _Note:_ This command may update more files than you intended. In that case
@@ -101,8 +101,9 @@ cargo dev setup intellij
cargo dev dogfood
```
-More about intellij command usage and reasons
-[here](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md#intellij-rust)
+More about [intellij] command usage and reasons.
+
+[intellij]: https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md#intellij-rust
## lintcheck
diff --git a/src/tools/clippy/book/src/development/common_tools_writing_lints.md b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
index 2bc275cef..f5aa06e4b 100644
--- a/src/tools/clippy/book/src/development/common_tools_writing_lints.md
+++ b/src/tools/clippy/book/src/development/common_tools_writing_lints.md
@@ -123,7 +123,8 @@ There are three ways to do this, depending on if the target trait has a
diagnostic item, lang item or neither.
```rust
-use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::is_trait_method;
use rustc_span::symbol::sym;
impl LateLintPass<'_> for MyStructLint {
@@ -143,13 +144,6 @@ impl LateLintPass<'_> for MyStructLint {
.map_or(false, |id| implements_trait(cx, ty, id, &[])) {
// `expr` implements `Drop` trait
}
-
- // 3. Using the type path with the expression
- // we use `match_trait_method` function from Clippy's utils
- // (This method should be avoided if possible)
- if match_trait_method(cx, expr, &paths::INTO) {
- // `expr` implements `Into` trait
- }
}
}
```
@@ -233,8 +227,9 @@ functions to deal with macros:
crates
```rust
- #[macro_use]
- extern crate a_crate_with_macros;
+ use rustc_middle::lint::in_external_macro;
+
+ use a_crate_with_macros::foo;
// `foo` is defined in `a_crate_with_macros`
foo!("bar");
diff --git a/src/tools/clippy/clippy_dev/src/fmt.rs b/src/tools/clippy/clippy_dev/src/fmt.rs
index 357cf6fc4..256231441 100644
--- a/src/tools/clippy/clippy_dev/src/fmt.rs
+++ b/src/tools/clippy/clippy_dev/src/fmt.rs
@@ -82,16 +82,16 @@ pub fn run(check: bool, verbose: bool) {
fn output_err(err: CliError) {
match err {
CliError::CommandFailed(command, stderr) => {
- eprintln!("error: A command failed! `{}`\nstderr: {}", command, stderr);
+ eprintln!("error: A command failed! `{command}`\nstderr: {stderr}");
},
CliError::IoError(err) => {
- eprintln!("error: {}", err);
+ eprintln!("error: {err}");
},
CliError::RustfmtNotInstalled => {
eprintln!("error: rustfmt nightly is not installed.");
},
CliError::WalkDirError(err) => {
- eprintln!("error: {}", err);
+ eprintln!("error: {err}");
},
CliError::IntellijSetupActive => {
eprintln!(
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 54c7456a2..80bb83af4 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,5 +1,4 @@
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(once_cell)]
#![feature(rustc_private)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/clippy_dev/src/main.rs b/src/tools/clippy/clippy_dev/src/main.rs
index a417d3dd8..d3e036692 100644
--- a/src/tools/clippy/clippy_dev/src/main.rs
+++ b/src/tools/clippy/clippy_dev/src/main.rs
@@ -41,7 +41,7 @@ fn main() {
matches.contains_id("msrv"),
) {
Ok(_) => update_lints::update(update_lints::UpdateMode::Change),
- Err(e) => eprintln!("Unable to create lint: {}", e),
+ Err(e) => eprintln!("Unable to create lint: {e}"),
}
},
Some(("setup", sub_command)) => match sub_command.subcommand() {
diff --git a/src/tools/clippy/clippy_dev/src/new_lint.rs b/src/tools/clippy/clippy_dev/src/new_lint.rs
index 331b76484..9e15f1504 100644
--- a/src/tools/clippy/clippy_dev/src/new_lint.rs
+++ b/src/tools/clippy/clippy_dev/src/new_lint.rs
@@ -1,5 +1,5 @@
use crate::clippy_project_root;
-use indoc::{indoc, writedoc};
+use indoc::{formatdoc, writedoc};
use std::fmt::Write as _;
use std::fs::{self, OpenOptions};
use std::io::prelude::*;
@@ -23,7 +23,7 @@ impl<T> Context for io::Result<T> {
match self {
Ok(t) => Ok(t),
Err(e) => {
- let message = format!("{}: {}", text.as_ref(), e);
+ let message = format!("{}: {e}", text.as_ref());
Err(io::Error::new(ErrorKind::Other, message))
},
}
@@ -72,7 +72,7 @@ fn create_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
let lint_contents = get_lint_file_contents(lint, enable_msrv);
let lint_path = format!("clippy_lints/src/{}.rs", lint.name);
write_file(lint.project_root.join(&lint_path), lint_contents.as_bytes())?;
- println!("Generated lint file: `{}`", lint_path);
+ println!("Generated lint file: `{lint_path}`");
Ok(())
}
@@ -86,7 +86,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
path.push("src");
fs::create_dir(&path)?;
- let header = format!("// compile-flags: --crate-name={}", lint_name);
+ let header = format!("// compile-flags: --crate-name={lint_name}");
write_file(path.join("main.rs"), get_test_file_contents(lint_name, Some(&header)))?;
Ok(())
@@ -106,7 +106,7 @@ fn create_test(lint: &LintData<'_>) -> io::Result<()> {
let test_contents = get_test_file_contents(lint.name, None);
write_file(lint.project_root.join(&test_path), test_contents)?;
- println!("Generated test file: `{}`", test_path);
+ println!("Generated test file: `{test_path}`");
}
Ok(())
@@ -186,37 +186,36 @@ pub(crate) fn get_stabilization_version() -> String {
}
fn get_test_file_contents(lint_name: &str, header_commands: Option<&str>) -> String {
- let mut contents = format!(
- indoc! {"
- #![warn(clippy::{})]
-
- fn main() {{
- // test code goes here
- }}
- "},
- lint_name
+ let mut contents = formatdoc!(
+ r#"
+ #![allow(unused)]
+ #![warn(clippy::{lint_name})]
+
+ fn main() {{
+ // test code goes here
+ }}
+ "#
);
if let Some(header) = header_commands {
- contents = format!("{}\n{}", header, contents);
+ contents = format!("{header}\n{contents}");
}
contents
}
fn get_manifest_contents(lint_name: &str, hint: &str) -> String {
- format!(
- indoc! {r#"
- # {}
-
- [package]
- name = "{}"
- version = "0.1.0"
- publish = false
-
- [workspace]
- "#},
- hint, lint_name
+ formatdoc!(
+ r#"
+ # {hint}
+
+ [package]
+ name = "{lint_name}"
+ version = "0.1.0"
+ publish = false
+
+ [workspace]
+ "#
)
}
@@ -237,76 +236,61 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
let name_upper = lint_name.to_uppercase();
result.push_str(&if enable_msrv {
- format!(
- indoc! {"
- use clippy_utils::msrvs;
- {pass_import}
- use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
- use rustc_semver::RustcVersion;
- use rustc_session::{{declare_tool_lint, impl_lint_pass}};
+ formatdoc!(
+ r#"
+ use clippy_utils::msrvs;
+ {pass_import}
+ use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
+ use rustc_semver::RustcVersion;
+ use rustc_session::{{declare_tool_lint, impl_lint_pass}};
- "},
- pass_type = pass_type,
- pass_import = pass_import,
- context_import = context_import,
+ "#
)
} else {
- format!(
- indoc! {"
- {pass_import}
- use rustc_lint::{{{context_import}, {pass_type}}};
- use rustc_session::{{declare_lint_pass, declare_tool_lint}};
-
- "},
- pass_import = pass_import,
- pass_type = pass_type,
- context_import = context_import
+ formatdoc!(
+ r#"
+ {pass_import}
+ use rustc_lint::{{{context_import}, {pass_type}}};
+ use rustc_session::{{declare_lint_pass, declare_tool_lint}};
+
+ "#
)
});
let _ = write!(result, "{}", get_lint_declaration(&name_upper, category));
result.push_str(&if enable_msrv {
- format!(
- indoc! {"
- pub struct {name_camel} {{
- msrv: Option<RustcVersion>,
- }}
+ formatdoc!(
+ r#"
+ pub struct {name_camel} {{
+ msrv: Option<RustcVersion>,
+ }}
- impl {name_camel} {{
- #[must_use]
- pub fn new(msrv: Option<RustcVersion>) -> Self {{
- Self {{ msrv }}
- }}
+ impl {name_camel} {{
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> Self {{
+ Self {{ msrv }}
}}
+ }}
- impl_lint_pass!({name_camel} => [{name_upper}]);
+ impl_lint_pass!({name_camel} => [{name_upper}]);
- impl {pass_type}{pass_lifetimes} for {name_camel} {{
- extract_msrv_attr!({context_import});
- }}
+ impl {pass_type}{pass_lifetimes} for {name_camel} {{
+ extract_msrv_attr!({context_import});
+ }}
- // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
- // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
- // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
- "},
- pass_type = pass_type,
- pass_lifetimes = pass_lifetimes,
- name_upper = name_upper,
- name_camel = name_camel,
- context_import = context_import,
+ // TODO: Add MSRV level to `clippy_utils/src/msrvs.rs` if needed.
+ // TODO: Add MSRV test to `tests/ui/min_rust_version_attr.rs`.
+ // TODO: Update msrv config comment in `clippy_lints/src/utils/conf.rs`
+ "#
)
} else {
- format!(
- indoc! {"
- declare_lint_pass!({name_camel} => [{name_upper}]);
+ formatdoc!(
+ r#"
+ declare_lint_pass!({name_camel} => [{name_upper}]);
- impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
- "},
- pass_type = pass_type,
- pass_lifetimes = pass_lifetimes,
- name_upper = name_upper,
- name_camel = name_camel,
+ impl {pass_type}{pass_lifetimes} for {name_camel} {{}}
+ "#
)
});
@@ -314,8 +298,8 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
}
fn get_lint_declaration(name_upper: &str, category: &str) -> String {
- format!(
- indoc! {r#"
+ formatdoc!(
+ r#"
declare_clippy_lint! {{
/// ### What it does
///
@@ -329,15 +313,13 @@ fn get_lint_declaration(name_upper: &str, category: &str) -> String {
/// ```rust
/// // example code which does not raise clippy warning
/// ```
- #[clippy::version = "{version}"]
+ #[clippy::version = "{}"]
pub {name_upper},
{category},
"default lint description"
}}
- "#},
- version = get_stabilization_version(),
- name_upper = name_upper,
- category = category,
+ "#,
+ get_stabilization_version(),
)
}
@@ -351,7 +333,7 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
_ => {},
}
- let ty_dir = lint.project_root.join(format!("clippy_lints/src/{}", ty));
+ let ty_dir = lint.project_root.join(format!("clippy_lints/src/{ty}"));
assert!(
ty_dir.exists() && ty_dir.is_dir(),
"Directory `{}` does not exist!",
@@ -411,10 +393,10 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
}
write_file(lint_file_path.as_path(), lint_file_contents)?;
- println!("Generated lint file: `clippy_lints/src/{}/{}.rs`", ty, lint.name);
+ println!("Generated lint file: `clippy_lints/src/{ty}/{}.rs`", lint.name);
println!(
- "Be sure to add a call to `{}::check` in `clippy_lints/src/{}/mod.rs`!",
- lint.name, ty
+ "Be sure to add a call to `{}::check` in `clippy_lints/src/{ty}/mod.rs`!",
+ lint.name
);
Ok(())
@@ -541,7 +523,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 _ = write!(new_arr_content, "\n {ident},");
}
new_arr_content.push('\n');
diff --git a/src/tools/clippy/clippy_dev/src/serve.rs b/src/tools/clippy/clippy_dev/src/serve.rs
index f15f24da9..535c25e69 100644
--- a/src/tools/clippy/clippy_dev/src/serve.rs
+++ b/src/tools/clippy/clippy_dev/src/serve.rs
@@ -10,8 +10,8 @@ use std::time::{Duration, SystemTime};
/// Panics if the python commands could not be spawned
pub fn run(port: u16, lint: Option<&String>) -> ! {
let mut url = Some(match lint {
- None => format!("http://localhost:{}", port),
- Some(lint) => format!("http://localhost:{}/#{}", port, lint),
+ None => format!("http://localhost:{port}"),
+ Some(lint) => format!("http://localhost:{port}/#{lint}"),
});
loop {
@@ -49,7 +49,7 @@ fn mtime(path: impl AsRef<Path>) -> SystemTime {
.into_iter()
.flatten()
.flatten()
- .map(|entry| mtime(&entry.path()))
+ .map(|entry| mtime(entry.path()))
.max()
.unwrap_or(SystemTime::UNIX_EPOCH)
} else {
diff --git a/src/tools/clippy/clippy_dev/src/setup/git_hook.rs b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs
index 3fbb77d59..1de5b1940 100644
--- a/src/tools/clippy/clippy_dev/src/setup/git_hook.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/git_hook.rs
@@ -30,10 +30,7 @@ pub fn install_hook(force_override: bool) {
println!("info: the hook can be removed with `cargo dev remove git-hook`");
println!("git hook successfully installed");
},
- Err(err) => eprintln!(
- "error: unable to copy `{}` to `{}` ({})",
- HOOK_SOURCE_FILE, HOOK_TARGET_FILE, err
- ),
+ Err(err) => eprintln!("error: unable to copy `{HOOK_SOURCE_FILE}` to `{HOOK_TARGET_FILE}` ({err})"),
}
}
@@ -77,7 +74,7 @@ pub fn remove_hook() {
fn delete_git_hook_file(path: &Path) -> bool {
if let Err(err) = fs::remove_file(path) {
- eprintln!("error: unable to delete existing pre-commit git hook ({})", err);
+ eprintln!("error: unable to delete existing pre-commit git hook ({err})");
false
} else {
true
diff --git a/src/tools/clippy/clippy_dev/src/setup/intellij.rs b/src/tools/clippy/clippy_dev/src/setup/intellij.rs
index bf741e6d1..efdb158c2 100644
--- a/src/tools/clippy/clippy_dev/src/setup/intellij.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/intellij.rs
@@ -36,9 +36,8 @@ impl ClippyProjectInfo {
}
pub fn setup_rustc_src(rustc_path: &str) {
- let rustc_source_dir = match check_and_get_rustc_dir(rustc_path) {
- Ok(path) => path,
- Err(_) => return,
+ let Ok(rustc_source_dir) = check_and_get_rustc_dir(rustc_path) else {
+ return
};
for project in CLIPPY_PROJECTS {
@@ -60,7 +59,7 @@ fn check_and_get_rustc_dir(rustc_path: &str) -> Result<PathBuf, ()> {
path = absolute_path;
},
Err(err) => {
- eprintln!("error: unable to get the absolute path of rustc ({})", err);
+ eprintln!("error: unable to get the absolute path of rustc ({err})");
return Err(());
},
};
@@ -103,14 +102,14 @@ fn inject_deps_into_project(rustc_source_dir: &Path, project: &ClippyProjectInfo
fn read_project_file(file_path: &str) -> Result<String, ()> {
let path = Path::new(file_path);
if !path.exists() {
- eprintln!("error: unable to find the file `{}`", file_path);
+ eprintln!("error: unable to find the file `{file_path}`");
return Err(());
}
match fs::read_to_string(path) {
Ok(content) => Ok(content),
Err(err) => {
- eprintln!("error: the file `{}` could not be read ({})", file_path, err);
+ eprintln!("error: the file `{file_path}` could not be read ({err})");
Err(())
},
}
@@ -124,10 +123,7 @@ fn inject_deps_into_manifest(
) -> std::io::Result<()> {
// do not inject deps if we have already done so
if cargo_toml.contains(RUSTC_PATH_SECTION) {
- eprintln!(
- "warn: dependencies are already setup inside {}, skipping file",
- manifest_path
- );
+ eprintln!("warn: dependencies are already setup inside {manifest_path}, skipping file");
return Ok(());
}
@@ -142,11 +138,7 @@ fn inject_deps_into_manifest(
let new_deps = extern_crates.map(|dep| {
// format the dependencies that are going to be put inside the Cargo.toml
- format!(
- "{dep} = {{ path = \"{source_path}/{dep}\" }}\n",
- dep = dep,
- source_path = rustc_source_dir.display()
- )
+ format!("{dep} = {{ path = \"{}/{dep}\" }}\n", rustc_source_dir.display())
});
// format a new [dependencies]-block with the new deps we need to inject
@@ -163,11 +155,11 @@ fn inject_deps_into_manifest(
// etc
let new_manifest = cargo_toml.replacen("[dependencies]\n", &all_deps, 1);
- // println!("{}", new_manifest);
+ // println!("{new_manifest}");
let mut file = File::create(manifest_path)?;
file.write_all(new_manifest.as_bytes())?;
- println!("info: successfully setup dependencies inside {}", manifest_path);
+ println!("info: successfully setup dependencies inside {manifest_path}");
Ok(())
}
@@ -179,14 +171,10 @@ pub fn remove_rustc_src() {
}
fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool {
- let mut cargo_content = if let Ok(content) = read_project_file(project.cargo_file) {
- content
- } else {
+ let Ok(mut cargo_content) = read_project_file(project.cargo_file) else {
return false;
};
- let section_start = if let Some(section_start) = cargo_content.find(RUSTC_PATH_SECTION) {
- section_start
- } else {
+ let Some(section_start) = cargo_content.find(RUSTC_PATH_SECTION) else {
println!(
"info: dependencies could not be found in `{}` for {}, skipping file",
project.cargo_file, project.name
@@ -194,9 +182,7 @@ fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool {
return true;
};
- let end_point = if let Some(end_point) = cargo_content.find(DEPENDENCIES_SECTION) {
- end_point
- } else {
+ let Some(end_point) = cargo_content.find(DEPENDENCIES_SECTION) else {
eprintln!(
"error: the end of the rustc dependencies section could not be found in `{}`",
project.cargo_file
@@ -214,8 +200,8 @@ fn remove_rustc_src_from_project(project: &ClippyProjectInfo) -> bool {
},
Err(err) => {
eprintln!(
- "error: unable to open file `{}` to remove rustc dependencies for {} ({})",
- project.cargo_file, project.name, err
+ "error: unable to open file `{}` to remove rustc dependencies for {} ({err})",
+ project.cargo_file, project.name
);
false
},
diff --git a/src/tools/clippy/clippy_dev/src/setup/vscode.rs b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
index d59001b2c..dbcdc9b59 100644
--- a/src/tools/clippy/clippy_dev/src/setup/vscode.rs
+++ b/src/tools/clippy/clippy_dev/src/setup/vscode.rs
@@ -17,10 +17,7 @@ pub fn install_tasks(force_override: bool) {
println!("info: the task file can be removed with `cargo dev remove vscode-tasks`");
println!("vscode tasks successfully installed");
},
- Err(err) => eprintln!(
- "error: unable to copy `{}` to `{}` ({})",
- TASK_SOURCE_FILE, TASK_TARGET_FILE, err
- ),
+ Err(err) => eprintln!("error: unable to copy `{TASK_SOURCE_FILE}` to `{TASK_TARGET_FILE}` ({err})"),
}
}
@@ -44,23 +41,17 @@ fn check_install_precondition(force_override: bool) -> bool {
return delete_vs_task_file(path);
}
- eprintln!(
- "error: there is already a `task.json` file inside the `{}` directory",
- VSCODE_DIR
- );
+ eprintln!("error: there is already a `task.json` file inside the `{VSCODE_DIR}` directory");
println!("info: use the `--force-override` flag to override the existing `task.json` file");
return false;
}
} else {
match fs::create_dir(vs_dir_path) {
Ok(_) => {
- println!("info: created `{}` directory for clippy", VSCODE_DIR);
+ println!("info: created `{VSCODE_DIR}` directory for clippy");
},
Err(err) => {
- eprintln!(
- "error: the task target directory `{}` could not be created ({})",
- VSCODE_DIR, err
- );
+ eprintln!("error: the task target directory `{VSCODE_DIR}` could not be created ({err})");
},
}
}
@@ -82,7 +73,7 @@ pub fn remove_tasks() {
fn delete_vs_task_file(path: &Path) -> bool {
if let Err(err) = fs::remove_file(path) {
- eprintln!("error: unable to delete the existing `tasks.json` file ({})", err);
+ eprintln!("error: unable to delete the existing `tasks.json` file ({err})");
return false;
}
diff --git a/src/tools/clippy/clippy_dev/src/update_lints.rs b/src/tools/clippy/clippy_dev/src/update_lints.rs
index b95061bf8..e690bc369 100644
--- a/src/tools/clippy/clippy_dev/src/update_lints.rs
+++ b/src/tools/clippy/clippy_dev/src/update_lints.rs
@@ -45,9 +45,8 @@ fn generate_lint_files(
renamed_lints: &[RenamedLint],
) {
let internal_lints = Lint::internal_lints(lints);
- let usable_lints = Lint::usable_lints(lints);
- let mut sorted_usable_lints = usable_lints.clone();
- sorted_usable_lints.sort_by_key(|lint| lint.name.clone());
+ let mut usable_lints = Lint::usable_lints(lints);
+ usable_lints.sort_by_key(|lint| lint.name.clone());
replace_region_in_file(
update_mode,
@@ -86,7 +85,7 @@ fn generate_lint_files(
)
.sorted()
{
- writeln!(res, "[`{}`]: {}#{}", lint, DOCS_LINK, lint).unwrap();
+ writeln!(res, "[`{lint}`]: {DOCS_LINK}#{lint}").unwrap();
}
},
);
@@ -99,7 +98,7 @@ fn generate_lint_files(
"// end lints modules, do not remove this comment, it’s used in `update_lints`",
|res| {
for lint_mod in usable_lints.iter().map(|l| &l.module).unique().sorted() {
- writeln!(res, "mod {};", lint_mod).unwrap();
+ writeln!(res, "mod {lint_mod};").unwrap();
}
},
);
@@ -129,7 +128,7 @@ fn generate_lint_files(
for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) {
let content = gen_lint_group_list(&lint_group, lints.iter());
process_file(
- &format!("clippy_lints/src/lib.register_{}.rs", lint_group),
+ format!("clippy_lints/src/lib.register_{lint_group}.rs"),
update_mode,
&content,
);
@@ -190,9 +189,9 @@ fn print_lint_names(header: &str, lints: &BTreeSet<String>) -> bool {
if lints.is_empty() {
return false;
}
- println!("{}", header);
+ println!("{header}");
for lint in lints.iter().sorted() {
- println!(" {}", lint);
+ println!(" {lint}");
}
println!();
true
@@ -205,16 +204,16 @@ pub fn print_lints() {
let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter());
for (lint_group, mut lints) in grouped_by_lint_group {
- println!("\n## {}", lint_group);
+ println!("\n## {lint_group}");
lints.sort_by_key(|l| l.name.clone());
for lint in lints {
- println!("* [{}]({}#{}) ({})", lint.name, DOCS_LINK, lint.name, lint.desc);
+ println!("* [{}]({DOCS_LINK}#{}) ({})", lint.name, lint.name, lint.desc);
}
}
- println!("there are {} lints", usable_lint_count);
+ println!("there are {usable_lint_count} lints");
}
/// Runs the `rename_lint` command.
@@ -235,10 +234,10 @@ pub fn print_lints() {
#[allow(clippy::too_many_lines)]
pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
if let Some((prefix, _)) = old_name.split_once("::") {
- panic!("`{}` should not contain the `{}` prefix", old_name, prefix);
+ panic!("`{old_name}` should not contain the `{prefix}` prefix");
}
if let Some((prefix, _)) = new_name.split_once("::") {
- panic!("`{}` should not contain the `{}` prefix", new_name, prefix);
+ panic!("`{new_name}` should not contain the `{prefix}` prefix");
}
let (mut lints, deprecated_lints, mut renamed_lints) = gather_all();
@@ -251,14 +250,14 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
found_new_name = true;
}
}
- let old_lint_index = old_lint_index.unwrap_or_else(|| panic!("could not find lint `{}`", old_name));
+ let old_lint_index = old_lint_index.unwrap_or_else(|| panic!("could not find lint `{old_name}`"));
let lint = RenamedLint {
- old_name: format!("clippy::{}", old_name),
+ old_name: format!("clippy::{old_name}"),
new_name: if uplift {
new_name.into()
} else {
- format!("clippy::{}", new_name)
+ format!("clippy::{new_name}")
},
};
@@ -266,13 +265,11 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
// case.
assert!(
!renamed_lints.iter().any(|l| lint.old_name == l.old_name),
- "`{}` has already been renamed",
- old_name
+ "`{old_name}` has already been renamed"
);
assert!(
!deprecated_lints.iter().any(|l| lint.old_name == l.name),
- "`{}` has already been deprecated",
- old_name
+ "`{old_name}` has already been deprecated"
);
// Update all lint level attributes. (`clippy::lint_name`)
@@ -309,14 +306,12 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
if uplift {
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
println!(
- "`{}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually.",
- old_name
+ "`{old_name}` has be uplifted. All the code inside `clippy_lints` related to it needs to be removed manually."
);
} else if found_new_name {
write_file(Path::new("tests/ui/rename.rs"), &gen_renamed_lints_test(&renamed_lints));
println!(
- "`{}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually.",
- new_name
+ "`{new_name}` is already defined. The old linting code inside `clippy_lints` needs to be updated/removed manually."
);
} else {
// Rename the lint struct and source files sharing a name with the lint.
@@ -327,16 +322,16 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
// Rename test files. only rename `.stderr` and `.fixed` files if the new test name doesn't exist.
if try_rename_file(
- Path::new(&format!("tests/ui/{}.rs", old_name)),
- Path::new(&format!("tests/ui/{}.rs", new_name)),
+ Path::new(&format!("tests/ui/{old_name}.rs")),
+ Path::new(&format!("tests/ui/{new_name}.rs")),
) {
try_rename_file(
- Path::new(&format!("tests/ui/{}.stderr", old_name)),
- Path::new(&format!("tests/ui/{}.stderr", new_name)),
+ Path::new(&format!("tests/ui/{old_name}.stderr")),
+ Path::new(&format!("tests/ui/{new_name}.stderr")),
);
try_rename_file(
- Path::new(&format!("tests/ui/{}.fixed", old_name)),
- Path::new(&format!("tests/ui/{}.fixed", new_name)),
+ Path::new(&format!("tests/ui/{old_name}.fixed")),
+ Path::new(&format!("tests/ui/{new_name}.fixed")),
);
}
@@ -344,8 +339,8 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
let replacements;
let replacements = if lint.module == old_name
&& try_rename_file(
- Path::new(&format!("clippy_lints/src/{}.rs", old_name)),
- Path::new(&format!("clippy_lints/src/{}.rs", new_name)),
+ Path::new(&format!("clippy_lints/src/{old_name}.rs")),
+ Path::new(&format!("clippy_lints/src/{new_name}.rs")),
) {
// Edit the module name in the lint list. Note there could be multiple lints.
for lint in lints.iter_mut().filter(|l| l.module == old_name) {
@@ -356,14 +351,14 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
} else if !lint.module.contains("::")
// Catch cases like `methods/lint_name.rs` where the lint is stored in `methods/mod.rs`
&& try_rename_file(
- Path::new(&format!("clippy_lints/src/{}/{}.rs", lint.module, old_name)),
- Path::new(&format!("clippy_lints/src/{}/{}.rs", lint.module, new_name)),
+ Path::new(&format!("clippy_lints/src/{}/{old_name}.rs", lint.module)),
+ Path::new(&format!("clippy_lints/src/{}/{new_name}.rs", lint.module)),
)
{
// Edit the module name in the lint list. Note there could be multiple lints, or none.
- let renamed_mod = format!("{}::{}", lint.module, old_name);
+ let renamed_mod = format!("{}::{old_name}", lint.module);
for lint in lints.iter_mut().filter(|l| l.module == renamed_mod) {
- lint.module = format!("{}::{}", lint.module, new_name);
+ lint.module = format!("{}::{new_name}", lint.module);
}
replacements = [(&*old_name_upper, &*new_name_upper), (old_name, new_name)];
replacements.as_slice()
@@ -379,7 +374,7 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) {
}
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
- println!("{} has been successfully renamed", old_name);
+ println!("{old_name} has been successfully renamed");
}
println!("note: `cargo uitest` still needs to be run to update the test results");
@@ -408,7 +403,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) {
});
generate_lint_files(UpdateMode::Change, &lints, &deprecated_lints, &renamed_lints);
- println!("info: `{}` has successfully been deprecated", name);
+ println!("info: `{name}` has successfully been deprecated");
if reason == DEFAULT_DEPRECATION_REASON {
println!("note: the deprecation reason must be updated in `clippy_lints/src/deprecated_lints.rs`");
@@ -421,7 +416,7 @@ pub fn deprecate(name: &str, reason: Option<&String>) {
let name_upper = name.to_uppercase();
let (mut lints, deprecated_lints, renamed_lints) = gather_all();
- let Some(lint) = lints.iter().find(|l| l.name == name_lower) else { eprintln!("error: failed to find lint `{}`", name); return; };
+ let Some(lint) = lints.iter().find(|l| l.name == name_lower) else { eprintln!("error: failed to find lint `{name}`"); return; };
let mod_path = {
let mut mod_path = PathBuf::from(format!("clippy_lints/src/{}", lint.module));
@@ -450,7 +445,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
}
fn remove_test_assets(name: &str) {
- let test_file_stem = format!("tests/ui/{}", name);
+ let test_file_stem = format!("tests/ui/{name}");
let path = Path::new(&test_file_stem);
// Some lints have their own directories, delete them
@@ -512,8 +507,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
fs::read_to_string(path).unwrap_or_else(|_| panic!("failed to read `{}`", path.to_string_lossy()));
eprintln!(
- "warn: you will have to manually remove any code related to `{}` from `{}`",
- name,
+ "warn: you will have to manually remove any code related to `{name}` from `{}`",
path.display()
);
@@ -528,7 +522,7 @@ fn remove_lint_declaration(name: &str, path: &Path, lints: &mut Vec<Lint>) -> io
content.replace_range(lint.declaration_range.clone(), "");
// Remove the module declaration (mod xyz;)
- let mod_decl = format!("\nmod {};", name);
+ let mod_decl = format!("\nmod {name};");
content = content.replacen(&mod_decl, "", 1);
remove_impl_lint_pass(&lint.name.to_uppercase(), &mut content);
@@ -621,13 +615,13 @@ fn round_to_fifty(count: usize) -> usize {
fn process_file(path: impl AsRef<Path>, update_mode: UpdateMode, content: &str) {
if update_mode == UpdateMode::Check {
let old_content =
- fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {}", path.as_ref().display(), e));
+ fs::read_to_string(&path).unwrap_or_else(|e| panic!("Cannot read from {}: {e}", path.as_ref().display()));
if content != old_content {
exit_with_failure();
}
} else {
fs::write(&path, content.as_bytes())
- .unwrap_or_else(|e| panic!("Cannot write to {}: {}", path.as_ref().display(), e));
+ .unwrap_or_else(|e| panic!("Cannot write to {}: {e}", path.as_ref().display()));
}
}
@@ -731,11 +725,10 @@ fn gen_lint_group_list<'a>(group_name: &str, lints: impl Iterator<Item = &'a Lin
let _ = writeln!(
output,
- "store.register_group(true, \"clippy::{0}\", Some(\"clippy_{0}\"), vec![",
- group_name
+ "store.register_group(true, \"clippy::{group_name}\", Some(\"clippy_{group_name}\"), vec![",
);
for (module, name) in details {
- let _ = writeln!(output, " LintId::of({}::{}),", module, name);
+ let _ = writeln!(output, " LintId::of({module}::{name}),");
}
output.push_str("])\n");
@@ -783,7 +776,7 @@ fn gen_register_lint_list<'a>(
if !is_public {
output.push_str(" #[cfg(feature = \"internal\")]\n");
}
- let _ = writeln!(output, " {}::{},", module_name, lint_name);
+ let _ = writeln!(output, " {module_name}::{lint_name},");
}
output.push_str("])\n");
@@ -841,7 +834,7 @@ fn gather_all() -> (Vec<Lint>, Vec<DeprecatedLint>, Vec<RenamedLint>) {
for (rel_path, file) in clippy_lints_src_files() {
let path = file.path();
let contents =
- fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e));
+ fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
let module = rel_path
.components()
.map(|c| c.as_os_str().to_str().unwrap())
@@ -876,13 +869,11 @@ fn clippy_lints_src_files() -> impl Iterator<Item = (PathBuf, DirEntry)> {
macro_rules! match_tokens {
($iter:ident, $($token:ident $({$($fields:tt)*})? $(($capture:ident))?)*) => {
{
- $($(let $capture =)? if let Some(LintDeclSearchResult {
+ $(#[allow(clippy::redundant_pattern)] let Some(LintDeclSearchResult {
token_kind: TokenKind::$token $({$($fields)*})?,
- content: _x,
+ content: $($capture @)? _,
..
- }) = $iter.next() {
- _x
- } else {
+ }) = $iter.next() else {
continue;
};)*
#[allow(clippy::unused_unit)]
@@ -1050,7 +1041,7 @@ fn remove_line_splices(s: &str) -> String {
.trim_matches('#')
.strip_prefix('"')
.and_then(|s| s.strip_suffix('"'))
- .unwrap_or_else(|| panic!("expected quoted string, found `{}`", s));
+ .unwrap_or_else(|| panic!("expected quoted string, found `{s}`"));
let mut res = String::with_capacity(s.len());
unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| {
if ch.is_ok() {
@@ -1076,10 +1067,10 @@ fn replace_region_in_file(
end: &str,
write_replacement: impl FnMut(&mut String),
) {
- let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {}", path.display(), e));
+ let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("Cannot read from `{}`: {e}", path.display()));
let new_contents = match replace_region_in_text(&contents, start, end, write_replacement) {
Ok(x) => x,
- Err(delim) => panic!("Couldn't find `{}` in file `{}`", delim, path.display()),
+ Err(delim) => panic!("Couldn't find `{delim}` in file `{}`", path.display()),
};
match update_mode {
@@ -1087,7 +1078,7 @@ fn replace_region_in_file(
UpdateMode::Check => (),
UpdateMode::Change => {
if let Err(e) = fs::write(path, new_contents.as_bytes()) {
- panic!("Cannot write to `{}`: {}", path.display(), e);
+ panic!("Cannot write to `{}`: {e}", path.display());
}
},
}
@@ -1135,7 +1126,7 @@ fn try_rename_file(old_name: &Path, new_name: &Path) -> bool {
#[allow(clippy::needless_pass_by_value)]
fn panic_file(error: io::Error, name: &Path, action: &str) -> ! {
- panic!("failed to {} file `{}`: {}", action, name.display(), error)
+ panic!("failed to {action} file `{}`: {error}", name.display())
}
fn rewrite_file(path: &Path, f: impl FnOnce(&str) -> Option<String>) {
diff --git a/src/tools/clippy/clippy_lints/Cargo.toml b/src/tools/clippy/clippy_lints/Cargo.toml
index 738562ef8..6fbd6401e 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.65"
+version = "0.1.66"
description = "A bunch of helpful lints to avoid common pitfalls in Rust"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
diff --git a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs b/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
index 59a7c5354..073e4af13 100644
--- a/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
+++ b/src/tools/clippy/clippy_lints/src/almost_complete_letter_range.rs
@@ -4,6 +4,7 @@ use clippy_utils::{meets_msrv, msrvs};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
@@ -79,6 +80,7 @@ fn check_range(cx: &EarlyContext<'_>, span: Span, start: &Expr, end: &Expr, sugg
(LitKind::Byte(b'a') | LitKind::Char('a'), LitKind::Byte(b'z') | LitKind::Char('z'))
| (LitKind::Byte(b'A') | LitKind::Char('A'), LitKind::Byte(b'Z') | LitKind::Char('Z'))
)
+ && !in_external_macro(cx.sess(), span)
{
span_lint_and_then(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/approx_const.rs b/src/tools/clippy/clippy_lints/src/approx_const.rs
index 159f3b0cd..724490fb4 100644
--- a/src/tools/clippy/clippy_lints/src/approx_const.rs
+++ b/src/tools/clippy/clippy_lints/src/approx_const.rs
@@ -92,7 +92,7 @@ impl ApproxConstant {
cx,
APPROX_CONSTANT,
e.span,
- &format!("approximate value of `{}::consts::{}` found", module, &name),
+ &format!("approximate value of `{module}::consts::{}` found", &name),
None,
"consider using the constant directly",
);
@@ -126,7 +126,7 @@ fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool {
// The value is a truncated constant
true
} else {
- let round_const = format!("{:.*}", value.len() - 2, constant);
+ let round_const = format!("{constant:.*}", value.len() - 2);
value == round_const
}
}
diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
index f419781db..9717aa9e9 100644
--- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs
+++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
@@ -44,7 +44,7 @@ fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr
cx,
lint,
expr.span,
- &format!("{} x86 assembly syntax used", style),
+ &format!("{style} x86 assembly syntax used"),
None,
&format!("use {} x86 assembly syntax", !style),
);
@@ -64,6 +64,7 @@ declare_clippy_lint! {
///
/// ```rust,no_run
/// # #![feature(asm)]
+ /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// # unsafe { let ptr = "".as_ptr();
/// # use std::arch::asm;
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
@@ -72,6 +73,7 @@ declare_clippy_lint! {
/// Use instead:
/// ```rust,no_run
/// # #![feature(asm)]
+ /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// # unsafe { let ptr = "".as_ptr();
/// # use std::arch::asm;
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -103,6 +105,7 @@ declare_clippy_lint! {
///
/// ```rust,no_run
/// # #![feature(asm)]
+ /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// # unsafe { let ptr = "".as_ptr();
/// # use std::arch::asm;
/// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
@@ -111,6 +114,7 @@ declare_clippy_lint! {
/// Use instead:
/// ```rust,no_run
/// # #![feature(asm)]
+ /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
/// # unsafe { let ptr = "".as_ptr();
/// # use std::arch::asm;
/// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
index 2705ffffd..a36df55d0 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_constants.rs
@@ -60,9 +60,9 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnConstants {
cx,
ASSERTIONS_ON_CONSTANTS,
macro_call.span,
- &format!("`assert!(false{})` should probably be replaced", assert_arg),
+ &format!("`assert!(false{assert_arg})` should probably be replaced"),
None,
- &format!("use `panic!({})` or `unreachable!({0})`", panic_arg),
+ &format!("use `panic!({panic_arg})` or `unreachable!({panic_arg})`"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
index 7cd198ace..f6d6c23bb 100644
--- a/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
+++ b/src/tools/clippy/clippy_lints/src/assertions_on_result_states.rs
@@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::macros::{find_assert_args, root_macro_call_first_node, PanicExpn};
-use clippy_utils::path_res;
use clippy_utils::source::snippet_with_context;
-use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item};
+use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
use clippy_utils::usage::local_used_after_expr;
+use clippy_utils::{is_expr_final_block_expr, path_res};
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Expr, ExprKind};
@@ -58,6 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
return;
}
}
+ let semicolon = if is_expr_final_block_expr(cx.tcx, e) {";"} else {""};
let mut app = Applicability::MachineApplicable;
match method_segment.ident.as_str() {
"is_ok" if type_suitable_to_unwrap(cx, substs.type_at(1)) => {
@@ -68,7 +69,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
"called `assert!` with `Result::is_ok`",
"replace with",
format!(
- "{}.unwrap()",
+ "{}.unwrap(){semicolon}",
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
),
app,
@@ -82,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
"called `assert!` with `Result::is_err`",
"replace with",
format!(
- "{}.unwrap_err()",
+ "{}.unwrap_err(){semicolon}",
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
),
app,
@@ -94,13 +95,6 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
}
}
-/// This checks whether a given type is known to implement Debug.
-fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
- cx.tcx
- .get_diagnostic_item(sym::Debug)
- .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
-}
-
fn type_suitable_to_unwrap<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
has_debug_impl(cx, ty) && !ty.is_unit() && !ty.is_never()
}
diff --git a/src/tools/clippy/clippy_lints/src/attrs.rs b/src/tools/clippy/clippy_lints/src/attrs.rs
index 732dc2b43..0bd1f8b78 100644
--- a/src/tools/clippy/clippy_lints/src/attrs.rs
+++ b/src/tools/clippy/clippy_lints/src/attrs.rs
@@ -357,7 +357,8 @@ impl<'tcx> LateLintPass<'tcx> for Attributes {
"wildcard_imports"
| "enum_glob_use"
| "redundant_pub_crate"
- | "macro_use_imports",
+ | "macro_use_imports"
+ | "unsafe_removed_from_name",
)
})
{
@@ -541,10 +542,7 @@ fn check_attrs(cx: &LateContext<'_>, span: Span, name: Symbol, attrs: &[Attribut
cx,
INLINE_ALWAYS,
attr.span,
- &format!(
- "you have declared `#[inline(always)]` on `{}`. This is usually a bad idea",
- name
- ),
+ &format!("you have declared `#[inline(always)]` on `{name}`. This is usually a bad idea"),
);
}
}
@@ -720,7 +718,7 @@ fn check_mismatched_target_os(cx: &EarlyContext<'_>, attr: &Attribute) {
let mut unix_suggested = false;
for (os, span) in mismatched {
- let sugg = format!("target_os = \"{}\"", os);
+ let sugg = format!("target_os = \"{os}\"");
diag.span_suggestion(span, "try", sugg, Applicability::MaybeIncorrect);
if !unix_suggested && is_unix(os) {
diff --git a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
index 1761360fb..347178118 100644
--- a/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
+++ b/src/tools/clippy/clippy_lints/src/await_holding_invalid.rs
@@ -1,14 +1,15 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{match_def_path, paths};
use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def::{Namespace, Res};
use rustc_hir::def_id::DefId;
-use rustc_hir::{def::Res, AsyncGeneratorKind, Body, BodyId, GeneratorKind};
+use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::GeneratorInteriorTypeCause;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::Span;
+use rustc_span::{sym, Span};
-use crate::utils::conf::DisallowedType;
+use crate::utils::conf::DisallowedPath;
declare_clippy_lint! {
/// ### What it does
@@ -171,12 +172,12 @@ impl_lint_pass!(AwaitHolding => [AWAIT_HOLDING_LOCK, AWAIT_HOLDING_REFCELL_REF,
#[derive(Debug)]
pub struct AwaitHolding {
- conf_invalid_types: Vec<DisallowedType>,
- def_ids: FxHashMap<DefId, DisallowedType>,
+ conf_invalid_types: Vec<DisallowedPath>,
+ def_ids: FxHashMap<DefId, DisallowedPath>,
}
impl AwaitHolding {
- pub(crate) fn new(conf_invalid_types: Vec<DisallowedType>) -> Self {
+ pub(crate) fn new(conf_invalid_types: Vec<DisallowedPath>) -> Self {
Self {
conf_invalid_types,
def_ids: FxHashMap::default(),
@@ -187,11 +188,8 @@ impl AwaitHolding {
impl LateLintPass<'_> for AwaitHolding {
fn check_crate(&mut self, cx: &LateContext<'_>) {
for conf in &self.conf_invalid_types {
- let path = match conf {
- DisallowedType::Simple(path) | DisallowedType::WithReason { path, .. } => path,
- };
- let segs: Vec<_> = path.split("::").collect();
- if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs) {
+ let segs: Vec<_> = conf.path().split("::").collect();
+ if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
self.def_ids.insert(id, conf.clone());
}
}
@@ -256,29 +254,27 @@ impl AwaitHolding {
}
}
-fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedType) {
- let (type_name, reason) = match disallowed {
- DisallowedType::Simple(path) => (path, &None),
- DisallowedType::WithReason { path, reason } => (path, reason),
- };
-
+fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedPath) {
span_lint_and_then(
cx,
AWAIT_HOLDING_INVALID_TYPE,
span,
- &format!("`{type_name}` may not be held across an `await` point per `clippy.toml`",),
+ &format!(
+ "`{}` may not be held across an `await` point per `clippy.toml`",
+ disallowed.path()
+ ),
|diag| {
- if let Some(reason) = reason {
- diag.note(reason.clone());
+ if let Some(reason) = disallowed.reason() {
+ diag.note(reason);
}
},
);
}
fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
- match_def_path(cx, def_id, &paths::MUTEX_GUARD)
- || match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
- || match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
+ cx.tcx.is_diagnostic_item(sym::MutexGuard, def_id)
+ || cx.tcx.is_diagnostic_item(sym::RwLockReadGuard, def_id)
+ || cx.tcx.is_diagnostic_item(sym::RwLockWriteGuard, def_id)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
diff --git a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
index d9e2c9c85..9c0532474 100644
--- a/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
+++ b/src/tools/clippy/clippy_lints/src/blocks_in_if_conditions.rs
@@ -3,10 +3,11 @@ use clippy_utils::get_parent_expr;
use clippy_utils::higher;
use clippy_utils::source::snippet_block_with_applicability;
use clippy_utils::ty::implements_trait;
+use clippy_utils::visitors::{for_each_expr, Descend};
+use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{BlockCheckMode, Closure, Expr, ExprKind};
+use rustc_hir::{BlockCheckMode, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -44,39 +45,6 @@ declare_clippy_lint! {
declare_lint_pass!(BlocksInIfConditions => [BLOCKS_IN_IF_CONDITIONS]);
-struct ExVisitor<'a, 'tcx> {
- found_block: Option<&'tcx Expr<'tcx>>,
- cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
- if let ExprKind::Closure(&Closure { body, .. }) = expr.kind {
- // do not lint if the closure is called using an iterator (see #1141)
- if_chain! {
- if let Some(parent) = get_parent_expr(self.cx, expr);
- if let ExprKind::MethodCall(_, self_arg, ..) = &parent.kind;
- let caller = self.cx.typeck_results().expr_ty(self_arg);
- if let Some(iter_id) = self.cx.tcx.get_diagnostic_item(sym::Iterator);
- if implements_trait(self.cx, caller, iter_id, &[]);
- then {
- return;
- }
- }
-
- let body = self.cx.tcx.hir().body(body);
- let ex = &body.value;
- if let ExprKind::Block(block, _) = ex.kind {
- if !body.value.span.from_expansion() && !block.stmts.is_empty() {
- self.found_block = Some(ex);
- return;
- }
- }
- }
- walk_expr(self, expr);
- }
-}
-
const BRACED_EXPR_MESSAGE: &str = "omit braces around single expression condition";
const COMPLEX_BLOCK_MESSAGE: &str = "in an `if` condition, avoid complex blocks or closures with blocks; \
instead, move the block or closure higher and bind it with a `let`";
@@ -145,11 +113,31 @@ impl<'tcx> LateLintPass<'tcx> for BlocksInIfConditions {
}
}
} else {
- let mut visitor = ExVisitor { found_block: None, cx };
- walk_expr(&mut visitor, cond);
- if let Some(block) = visitor.found_block {
- span_lint(cx, BLOCKS_IN_IF_CONDITIONS, block.span, COMPLEX_BLOCK_MESSAGE);
- }
+ let _: Option<!> = for_each_expr(cond, |e| {
+ if let ExprKind::Closure(closure) = e.kind {
+ // do not lint if the closure is called using an iterator (see #1141)
+ if_chain! {
+ if let Some(parent) = get_parent_expr(cx, e);
+ if let ExprKind::MethodCall(_, self_arg, _, _) = &parent.kind;
+ let caller = cx.typeck_results().expr_ty(self_arg);
+ if let Some(iter_id) = cx.tcx.get_diagnostic_item(sym::Iterator);
+ if implements_trait(cx, caller, iter_id, &[]);
+ then {
+ return ControlFlow::Continue(Descend::No);
+ }
+ }
+
+ let body = cx.tcx.hir().body(closure.body);
+ let ex = &body.value;
+ if let ExprKind::Block(block, _) = ex.kind {
+ if !body.value.span.from_expansion() && !block.stmts.is_empty() {
+ span_lint(cx, BLOCKS_IN_IF_CONDITIONS, ex.span, COMPLEX_BLOCK_MESSAGE);
+ return ControlFlow::Continue(Descend::No);
+ }
+ }
+ }
+ ControlFlow::Continue(Descend::Yes)
+ });
}
}
}
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 95abe8aa5..4bd55c142 100644
--- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs
@@ -98,9 +98,9 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
cx,
BOOL_ASSERT_COMPARISON,
macro_call.span,
- &format!("used `{}!` with a literal bool", macro_name),
+ &format!("used `{macro_name}!` with a literal bool"),
"replace it with",
- format!("{}!(..)", non_eq_mac),
+ format!("{non_eq_mac}!(..)"),
Applicability::MaybeIncorrect,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
index a4b8cbb0d..001d74c26 100644
--- a/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
+++ b/src/tools/clippy/clippy_lints/src/bool_to_int_with_if.rs
@@ -1,9 +1,9 @@
-use rustc_ast::{ExprPrecedence, LitKind};
+use rustc_ast::LitKind;
use rustc_hir::{Block, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, source::snippet_block_with_applicability};
+use clippy_utils::{diagnostics::span_lint_and_then, is_else_clause, is_integer_literal, sugg::Sugg};
use rustc_errors::Applicability;
declare_clippy_lint! {
@@ -55,27 +55,38 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
if let ExprKind::If(check, then, Some(else_)) = expr.kind
&& let Some(then_lit) = int_literal(then)
&& let Some(else_lit) = int_literal(else_)
- && check_int_literal_equals_val(then_lit, 1)
- && check_int_literal_equals_val(else_lit, 0)
{
+ let inverted = if is_integer_literal(then_lit, 1) && is_integer_literal(else_lit, 0) {
+ false
+ } else if is_integer_literal(then_lit, 0) && is_integer_literal(else_lit, 1) {
+ true
+ } else {
+ // Expression isn't boolean, exit
+ return;
+ };
let mut applicability = Applicability::MachineApplicable;
- let snippet = snippet_block_with_applicability(ctx, check.span, "..", None, &mut applicability);
- let snippet_with_braces = {
- let need_parens = should_have_parentheses(check);
- let (left_paren, right_paren) = if need_parens {("(", ")")} else {("", "")};
- format!("{left_paren}{snippet}{right_paren}")
+ let snippet = {
+ let mut sugg = Sugg::hir_with_applicability(ctx, check, "..", &mut applicability);
+ if inverted {
+ sugg = !sugg;
+ }
+ sugg
};
let ty = ctx.typeck_results().expr_ty(then_lit); // then and else must be of same type
let suggestion = {
let wrap_in_curly = is_else_clause(ctx.tcx, expr);
- let (left_curly, right_curly) = if wrap_in_curly {("{", "}")} else {("", "")};
- format!(
- "{left_curly}{ty}::from({snippet}){right_curly}"
- )
+ let mut s = Sugg::NonParen(format!("{ty}::from({snippet})").into());
+ if wrap_in_curly {
+ s = s.blockify();
+ }
+ s
}; // when used in else clause if statement should be wrapped in curly braces
+ let into_snippet = snippet.clone().maybe_par();
+ let as_snippet = snippet.as_ty(ty);
+
span_lint_and_then(ctx,
BOOL_TO_INT_WITH_IF,
expr.span,
@@ -87,7 +98,7 @@ fn check_if_else<'tcx>(ctx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx
suggestion,
applicability,
);
- diag.note(format!("`{snippet_with_braces} as {ty}` or `{snippet_with_braces}.into()` can also be valid options"));
+ diag.note(format!("`{as_snippet}` or `{into_snippet}.into()` can also be valid options"));
});
};
}
@@ -108,18 +119,3 @@ fn int_literal<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>) -> Option<&'tcx rustc_hi
None
}
}
-
-fn check_int_literal_equals_val<'tcx>(expr: &'tcx rustc_hir::Expr<'tcx>, expected_value: u128) -> bool {
- if let ExprKind::Lit(lit) = &expr.kind
- && let LitKind::Int(val, _) = lit.node
- && val == expected_value
- {
- true
- } else {
- false
- }
-}
-
-fn should_have_parentheses<'tcx>(check: &'tcx rustc_hir::Expr<'tcx>) -> bool {
- check.precedence().order() < ExprPrecedence::Cast.order()
-}
diff --git a/src/tools/clippy/clippy_lints/src/booleans.rs b/src/tools/clippy/clippy_lints/src/booleans.rs
index 656d639f0..08164c0b6 100644
--- a/src/tools/clippy/clippy_lints/src/booleans.rs
+++ b/src/tools/clippy/clippy_lints/src/booleans.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
+use clippy_utils::eq_expr_value;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{eq_expr_value, get_trait_def_id, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@@ -237,7 +237,7 @@ impl<'a, 'tcx, 'v> SuggestContext<'a, 'tcx, 'v> {
}
},
&Term(n) => {
- let snip = snippet_opt(self.cx, self.terminals[n as usize].span)?;
+ let snip = snippet_opt(self.cx, self.terminals[n as usize].span.source_callsite())?;
self.output.push_str(&snip);
},
}
@@ -263,9 +263,8 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
}
.and_then(|op| {
Some(format!(
- "{}{}{}",
+ "{}{op}{}",
snippet_opt(cx, lhs.span)?,
- op,
snippet_opt(cx, rhs.span)?
))
})
@@ -285,7 +284,7 @@ fn simplify_not(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
let path: &str = path.ident.name.as_str();
a == path
})
- .and_then(|(_, neg_method)| Some(format!("{}.{}()", snippet_opt(cx, receiver.span)?, neg_method)))
+ .and_then(|(_, neg_method)| Some(format!("{}.{neg_method}()", snippet_opt(cx, receiver.span)?)))
},
_ => None,
}
@@ -484,7 +483,9 @@ impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
fn implements_ord<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) -> bool {
let ty = cx.typeck_results().expr_ty(expr);
- get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ cx.tcx
+ .get_diagnostic_item(sym::Ord)
+ .map_or(false, |id| implements_trait(cx, ty, id, &[]))
}
struct NotSimplificationVisitor<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/box_default.rs b/src/tools/clippy/clippy_lints/src/box_default.rs
new file mode 100644
index 000000000..36daceabe
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/box_default.rs
@@ -0,0 +1,129 @@
+use clippy_utils::{
+ diagnostics::span_lint_and_sugg, get_parent_node, is_default_equivalent, macros::macro_backtrace, match_path,
+ path_def_id, paths, ty::expr_sig,
+};
+use rustc_errors::Applicability;
+use rustc_hir::{
+ intravisit::{walk_ty, Visitor},
+ Block, Expr, ExprKind, Local, Node, QPath, TyKind,
+};
+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::sym;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// checks for `Box::new(T::default())`, which is better written as
+ /// `Box::<T>::default()`.
+ ///
+ /// ### Why is this bad?
+ /// First, it's more complex, involving two calls instead of one.
+ /// Second, `Box::default()` can be faster
+ /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
+ ///
+ /// ### Example
+ /// ```rust
+ /// let x: Box<String> = Box::new(Default::default());
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let x: Box<String> = Box::default();
+ /// ```
+ #[clippy::version = "1.65.0"]
+ pub BOX_DEFAULT,
+ perf,
+ "Using Box::new(T::default()) instead of Box::default()"
+}
+
+declare_lint_pass!(BoxDefault => [BOX_DEFAULT]);
+
+impl LateLintPass<'_> for BoxDefault {
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+ if let ExprKind::Call(box_new, [arg]) = expr.kind
+ && let ExprKind::Path(QPath::TypeRelative(ty, seg)) = box_new.kind
+ && let ExprKind::Call(arg_path, ..) = arg.kind
+ && !in_external_macro(cx.sess(), expr.span)
+ && (expr.span.eq_ctxt(arg.span) || is_vec_expn(cx, arg))
+ && seg.ident.name == sym::new
+ && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
+ && is_default_equivalent(cx, arg)
+ {
+ let arg_ty = cx.typeck_results().expr_ty(arg);
+ span_lint_and_sugg(
+ cx,
+ BOX_DEFAULT,
+ expr.span,
+ "`Box::new(_)` of default value",
+ "try",
+ if is_plain_default(arg_path) || given_type(cx, expr) {
+ "Box::default()".into()
+ } else {
+ format!("Box::<{arg_ty}>::default()")
+ },
+ Applicability::MachineApplicable
+ );
+ }
+ }
+}
+
+fn is_plain_default(arg_path: &Expr<'_>) -> bool {
+ // we need to match the actual path so we don't match e.g. "u8::default"
+ if let ExprKind::Path(QPath::Resolved(None, path)) = &arg_path.kind {
+ // avoid generic parameters
+ match_path(path, &paths::DEFAULT_TRAIT_METHOD) && path.segments.iter().all(|seg| seg.args.is_none())
+ } else {
+ false
+ }
+}
+
+fn is_vec_expn(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ macro_backtrace(expr.span)
+ .next()
+ .map_or(false, |call| cx.tcx.is_diagnostic_item(sym::vec_macro, call.def_id))
+}
+
+#[derive(Default)]
+struct InferVisitor(bool);
+
+impl<'tcx> Visitor<'tcx> for InferVisitor {
+ fn visit_ty(&mut self, t: &rustc_hir::Ty<'_>) {
+ self.0 |= matches!(t.kind, TyKind::Infer | TyKind::OpaqueDef(..) | TyKind::TraitObject(..));
+ if !self.0 {
+ walk_ty(self, t);
+ }
+ }
+}
+
+fn given_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ match get_parent_node(cx.tcx, expr.hir_id) {
+ Some(Node::Local(Local { ty: Some(ty), .. })) => {
+ let mut v = InferVisitor::default();
+ v.visit_ty(ty);
+ !v.0
+ },
+ Some(
+ Node::Expr(Expr {
+ kind: ExprKind::Call(path, args),
+ ..
+ }) | Node::Block(Block {
+ expr:
+ Some(Expr {
+ kind: ExprKind::Call(path, args),
+ ..
+ }),
+ ..
+ }),
+ ) => {
+ 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)
+ {
+ input.no_bound_vars().is_some()
+ } else {
+ false
+ }
+ },
+ _ => false,
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
index e0442dda4..805121bcc 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/common_metadata.rs
@@ -40,7 +40,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata, ignore_publish: b
}
fn missing_warning(cx: &LateContext<'_>, package: &cargo_metadata::Package, field: &str) {
- let message = format!("package `{}` is missing `{}` metadata", package.name, field);
+ let message = format!("package `{}` is missing `{field}` metadata", package.name);
span_lint(cx, CARGO_COMMON_METADATA, DUMMY_SP, &message);
}
diff --git a/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs b/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
index 79a469a42..37c169dbd 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/feature_name.rs
@@ -57,10 +57,8 @@ fn lint(cx: &LateContext<'_>, feature: &str, substring: &str, is_prefix: bool) {
},
DUMMY_SP,
&format!(
- "the \"{}\" {} in the feature name \"{}\" is {}",
- substring,
+ "the \"{substring}\" {} in the feature name \"{feature}\" is {}",
if is_prefix { "prefix" } else { "suffix" },
- feature,
if is_negative { "negative" } else { "redundant" }
),
None,
diff --git a/src/tools/clippy/clippy_lints/src/cargo/mod.rs b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
index 9f45db86a..3a872e54c 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/mod.rs
@@ -196,7 +196,7 @@ impl LateLintPass<'_> for Cargo {
},
Err(e) => {
for lint in NO_DEPS_LINTS {
- span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));
+ span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
}
},
}
@@ -212,7 +212,7 @@ impl LateLintPass<'_> for Cargo {
},
Err(e) => {
for lint in WITH_DEPS_LINTS {
- span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {}", e));
+ span_lint(cx, lint, DUMMY_SP, &format!("could not read cargo metadata: {e}"));
}
},
}
diff --git a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
index 76fd0819a..f9b17d45e 100644
--- a/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
+++ b/src/tools/clippy/clippy_lints/src/cargo/multiple_crate_versions.rs
@@ -37,7 +37,7 @@ pub(super) fn check(cx: &LateContext<'_>, metadata: &Metadata) {
cx,
MULTIPLE_CRATE_VERSIONS,
DUMMY_SP,
- &format!("multiple versions for dependency `{}`: {}", name, versions),
+ &format!("multiple versions for dependency `{name}`: {versions}"),
);
}
}
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
new file mode 100644
index 000000000..9409f4844
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/casts/as_ptr_cast_mut.rs
@@ -0,0 +1,38 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet_opt;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::{
+ mir::Mutability,
+ ty::{self, Ty, TypeAndMut},
+};
+
+use super::AS_PTR_CAST_MUT;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>) {
+ if let ty::RawPtr(ptrty @ TypeAndMut { mutbl: Mutability::Mut, .. }) = cast_to.kind()
+ && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) =
+ cx.typeck_results().node_type(cast_expr.hir_id).kind()
+ && 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 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)
+ {
+ // `as_mut_ptr` might not exist
+ let applicability = Applicability::MaybeIncorrect;
+
+ span_lint_and_sugg(
+ cx,
+ AS_PTR_CAST_MUT,
+ expr.span,
+ &format!("casting the result of `as_ptr` to *{ptrty}"),
+ "replace with",
+ format!("{recv}.as_mut_ptr()"),
+ applicability
+ );
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
index 6e1f8cd64..294d22d34 100644
--- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs
@@ -30,7 +30,7 @@ pub(super) fn check<'tcx>(
expr.span,
"borrow as raw pointer",
"try",
- format!("{}::ptr::{}!({})", core_or_std, macro_name, snip),
+ format!("{core_or_std}::ptr::{macro_name}!({snip})"),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
index 938458e30..13c403234 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_lossless.rs
@@ -41,15 +41,9 @@ pub(super) fn check(
);
let message = if cast_from.is_bool() {
- format!(
- "casting `{0:}` to `{1:}` is more cleanly stated with `{1:}::from(_)`",
- cast_from, cast_to
- )
+ format!("casting `{cast_from:}` to `{cast_to:}` is more cleanly stated with `{cast_to:}::from(_)`")
} else {
- format!(
- "casting `{}` to `{}` may become silently lossy if you later change the type",
- cast_from, cast_to
- )
+ format!("casting `{cast_from}` to `{cast_to}` may become silently lossy if you later change the type")
};
span_lint_and_sugg(
@@ -58,7 +52,7 @@ pub(super) fn check(
expr.span,
&message,
"try",
- format!("{}::from({})", cast_to, sugg),
+ format!("{cast_to}::from({sugg})"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
new file mode 100644
index 000000000..322dc41b3
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_nan_to_int.rs
@@ -0,0 +1,28 @@
+use super::CAST_NAN_TO_INT;
+
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_note;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, from_ty: Ty<'_>, to_ty: Ty<'_>) {
+ if from_ty.is_floating_point() && to_ty.is_integral() && is_known_nan(cx, cast_expr) {
+ span_lint_and_note(
+ cx,
+ CAST_NAN_TO_INT,
+ expr.span,
+ &format!("casting a known NaN to {to_ty}"),
+ None,
+ "this always evaluates to 0",
+ );
+ }
+}
+
+fn is_known_nan(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
+ match constant(cx, cx.typeck_results(), e) {
+ Some((Constant::F64(n), _)) => n.is_nan(),
+ Some((Constant::F32(n), _)) => n.is_nan(),
+ _ => false,
+ }
+}
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 406547a44..88deb4565 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
@@ -103,10 +103,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
return;
}
- format!(
- "casting `{}` to `{}` may truncate the value{}",
- cast_from, cast_to, suffix,
- )
+ format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
},
(ty::Adt(def, _), true) if def.is_enum() => {
@@ -142,20 +139,17 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
CAST_ENUM_TRUNCATION,
expr.span,
&format!(
- "casting `{}::{}` to `{}` will truncate the value{}",
- cast_from, variant.name, cast_to, suffix,
+ "casting `{cast_from}::{}` to `{cast_to}` will truncate the value{suffix}",
+ variant.name,
),
);
return;
}
- format!(
- "casting `{}` to `{}` may truncate the value{}",
- cast_from, cast_to, suffix,
- )
+ format!("casting `{cast_from}` to `{cast_to}` may truncate the value{suffix}",)
},
(ty::Float(_), true) => {
- format!("casting `{}` to `{}` may truncate the value", cast_from, cast_to)
+ format!("casting `{cast_from}` to `{cast_to}` may truncate the value")
},
(ty::Float(FloatTy::F64), false) if matches!(cast_to.kind(), &ty::Float(FloatTy::F32)) => {
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
index 2c5c1d7cb..28ecdea7e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_wrap.rs
@@ -35,10 +35,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, ca
cx,
CAST_POSSIBLE_WRAP,
expr.span,
- &format!(
- "casting `{}` to `{}` may wrap around the value{}",
- cast_from, cast_to, suffix,
- ),
+ &format!("casting `{cast_from}` to `{cast_to}` may wrap around the value{suffix}",),
);
}
}
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 da7b12f67..97054a0d1 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
@@ -49,9 +49,7 @@ fn lint_cast_ptr_alignment<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, cast_f
CAST_PTR_ALIGNMENT,
expr.span,
&format!(
- "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)",
- cast_from,
- cast_to,
+ "casting from `{cast_from}` to a more-strictly-aligned pointer (`{cast_to}`) ({} < {} bytes)",
from_layout.align.abi.bytes(),
to_layout.align.abi.bytes(),
),
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
index 5b59350be..a20a97d4e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_sign_loss.rs
@@ -14,10 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_op: &Expr<'_>, c
cx,
CAST_SIGN_LOSS,
expr.span,
- &format!(
- "casting `{}` to `{}` may lose the sign of the value",
- cast_from, cast_to
- ),
+ &format!("casting `{cast_from}` to `{cast_to}` may lose the sign of the value"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
index 027c660ce..d31d10d22 100644
--- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs
@@ -35,8 +35,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Optio
CAST_SLICE_DIFFERENT_SIZES,
expr.span,
&format!(
- "casting between raw pointers to `[{}]` (element size {}) and `[{}]` (element size {}) does not adjust the count",
- start_ty.ty, from_size, end_ty.ty, to_size,
+ "casting between raw pointers to `[{}]` (element size {from_size}) and `[{}]` (element size {to_size}) does not adjust the count",
+ start_ty.ty, end_ty.ty,
),
|diag| {
let ptr_snippet = source::snippet(cx, left_cast.span, "..");
diff --git a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
index 7cc406018..82e07c98a 100644
--- a/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/char_lit_as_u8.rs
@@ -31,7 +31,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
diag.span_suggestion(
expr.span,
"use a byte literal instead",
- format!("b{}", snippet),
+ format!("b{snippet}"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
index 35350d8a2..a26bfab4e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast.rs
@@ -25,9 +25,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
cx,
FN_TO_NUMERIC_CAST,
expr.span,
- &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
+ &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
"try",
- format!("{} as usize", from_snippet),
+ format!("{from_snippet} as usize"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
index 03621887a..756541294 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_any.rs
@@ -23,9 +23,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
cx,
FN_TO_NUMERIC_CAST_ANY,
expr.span,
- &format!("casting function pointer `{}` to `{}`", from_snippet, cast_to),
+ &format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
"did you mean to invoke the function?",
- format!("{}() as {}", from_snippet, cast_to),
+ format!("{from_snippet}() as {cast_to}"),
applicability,
);
},
diff --git a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
index 6287f479b..556be1d15 100644
--- a/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/fn_to_numeric_cast_with_truncation.rs
@@ -24,12 +24,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
cx,
FN_TO_NUMERIC_CAST_WITH_TRUNCATION,
expr.span,
- &format!(
- "casting function pointer `{}` to `{}`, which truncates the value",
- from_snippet, cast_to
- ),
+ &format!("casting function pointer `{from_snippet}` to `{cast_to}`, which truncates the value"),
"try",
- format!("{} as usize", from_snippet),
+ format!("{from_snippet} as usize"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index cc5d346b9..b72c4c772 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -1,8 +1,10 @@
+mod as_ptr_cast_mut;
mod as_underscore;
mod borrow_as_ptr;
mod cast_abs_to_unsigned;
mod cast_enum_constructor;
mod cast_lossless;
+mod cast_nan_to_int;
mod cast_possible_truncation;
mod cast_possible_wrap;
mod cast_precision_loss;
@@ -569,6 +571,7 @@ declare_clippy_lint! {
pedantic,
"borrowing just to cast to a raw pointer"
}
+
declare_clippy_lint! {
/// ### What it does
/// Checks for a raw slice being cast to a slice pointer
@@ -596,6 +599,54 @@ declare_clippy_lint! {
"casting a slice created from a pointer and length to a slice pointer"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer
+ ///
+ /// ### Why is this bad?
+ /// Since `as_ptr` takes a `&self`, the pointer won't have write permissions unless interior
+ /// mutability is used, making it unlikely that having it as a mutable pointer is correct.
+ ///
+ /// ### Example
+ /// ```rust
+ /// let string = String::with_capacity(1);
+ /// let ptr = string.as_ptr() as *mut u8;
+ /// unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// let mut string = String::with_capacity(1);
+ /// let ptr = string.as_mut_ptr();
+ /// unsafe { ptr.write(4) };
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub AS_PTR_CAST_MUT,
+ nursery,
+ "casting the result of the `&self`-taking `as_ptr` to a mutabe pointer"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for a known NaN float being cast to an integer
+ ///
+ /// ### Why is this bad?
+ /// NaNs are cast into zero, so one could simply use this and make the
+ /// code more readable. The lint could also hint at a programmer error.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// let _: (0.0_f32 / 0.0) as u64;
+ /// ```
+ /// Use instead:
+ /// ```rust,ignore
+ /// let _: = 0_u64;
+ /// ```
+ #[clippy::version = "1.64.0"]
+ pub CAST_NAN_TO_INT,
+ suspicious,
+ "casting a known floating-point NaN into an integer"
+}
+
pub struct Casts {
msrv: Option<RustcVersion>,
}
@@ -627,7 +678,9 @@ impl_lint_pass!(Casts => [
CAST_ABS_TO_UNSIGNED,
AS_UNDERSCORE,
BORROW_AS_PTR,
- CAST_SLICE_FROM_RAW_PARTS
+ CAST_SLICE_FROM_RAW_PARTS,
+ AS_PTR_CAST_MUT,
+ CAST_NAN_TO_INT,
]);
impl<'tcx> LateLintPass<'tcx> for Casts {
@@ -653,6 +706,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
return;
}
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, self.msrv);
+ as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to);
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
@@ -664,6 +718,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
cast_precision_loss::check(cx, expr, cast_from, cast_to);
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
+ cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
}
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
index 46d45d096..b9509ca65 100644
--- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs
@@ -26,14 +26,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVer
(Mutability::Not, Mutability::Not) | (Mutability::Mut, Mutability::Mut));
// The `U` in `pointer::cast` have to be `Sized`
// as explained here: https://github.com/rust-lang/rust/issues/60602.
- if to_pointee_ty.is_sized(cx.tcx.at(expr.span), cx.param_env);
+ if to_pointee_ty.is_sized(cx.tcx, cx.param_env);
then {
let mut applicability = Applicability::MachineApplicable;
let cast_expr_sugg = Sugg::hir_with_applicability(cx, cast_expr, "_", &mut applicability);
let turbofish = match &cast_to_hir_ty.kind {
TyKind::Infer => Cow::Borrowed(""),
TyKind::Ptr(mut_ty) if matches!(mut_ty.ty.kind, TyKind::Infer) => Cow::Borrowed(""),
- _ => Cow::Owned(format!("::<{}>", to_pointee_ty)),
+ _ => Cow::Owned(format!("::<{to_pointee_ty}>")),
};
span_lint_and_sugg(
cx,
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVer
expr.span,
"`as` casting between raw pointers without changing its mutability",
"try `pointer::cast`, a safer alternative",
- format!("{}.cast{}()", cast_expr_sugg.maybe_par(), turbofish),
+ format!("{}.cast{turbofish}()", cast_expr_sugg.maybe_par()),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
index 19d2e6e1d..c8596987e 100644
--- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::get_parent_expr;
use clippy_utils::numeric_literal::NumericLiteral;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
@@ -30,8 +31,10 @@ pub(super) fn check<'tcx>(
}
}
+ let cast_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
+
if let Some(lit) = get_numeric_literal(cast_expr) {
- let literal_str = snippet_opt(cx, cast_expr.span).unwrap_or_default();
+ let literal_str = &cast_str;
if_chain! {
if let LitKind::Int(n, _) = lit.node;
@@ -49,12 +52,13 @@ pub(super) fn check<'tcx>(
match lit.node {
LitKind::Int(_, LitIntType::Unsuffixed) if cast_to.is_integral() => {
- lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
+ lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
+ return false;
},
LitKind::Float(_, LitFloatType::Unsuffixed) if cast_to.is_floating_point() => {
- lint_unnecessary_cast(cx, expr, &literal_str, cast_from, cast_to);
+ lint_unnecessary_cast(cx, expr, literal_str, cast_from, cast_to);
+ return false;
},
- LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) => {},
LitKind::Int(_, LitIntType::Signed(_) | LitIntType::Unsigned(_))
| LitKind::Float(_, LitFloatType::Suffixed(_))
if cast_from.kind() == cast_to.kind() =>
@@ -62,48 +66,62 @@ pub(super) fn check<'tcx>(
if let Some(src) = snippet_opt(cx, cast_expr.span) {
if let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) {
lint_unnecessary_cast(cx, expr, num_lit.integer, cast_from, cast_to);
+ return true;
}
}
},
- _ => {
- if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
- span_lint_and_sugg(
- cx,
- UNNECESSARY_CAST,
- expr.span,
- &format!(
- "casting to the same type is unnecessary (`{}` -> `{}`)",
- cast_from, cast_to
- ),
- "try",
- literal_str,
- Applicability::MachineApplicable,
- );
- return true;
- }
- },
+ _ => {},
}
}
+ if cast_from.kind() == cast_to.kind() && !in_external_macro(cx.sess(), expr.span) {
+ span_lint_and_sugg(
+ cx,
+ UNNECESSARY_CAST,
+ expr.span,
+ &format!("casting to the same type is unnecessary (`{cast_from}` -> `{cast_to}`)"),
+ "try",
+ cast_str,
+ Applicability::MachineApplicable,
+ );
+ return true;
+ }
+
false
}
-fn lint_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &str, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+fn lint_unnecessary_cast(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ raw_literal_str: &str,
+ cast_from: Ty<'_>,
+ cast_to: Ty<'_>,
+) {
let literal_kind_name = if cast_from.is_integral() { "integer" } else { "float" };
- let replaced_literal;
- let matchless = if literal_str.contains(['(', ')']) {
- replaced_literal = literal_str.replace(['(', ')'], "");
- &replaced_literal
- } else {
- literal_str
+ // first we remove all matches so `-(1)` become `-1`, and remove trailing dots, so `1.` become `1`
+ let literal_str = raw_literal_str
+ .replace(['(', ')'], "")
+ .trim_end_matches('.')
+ .to_string();
+ // we know need to check if the parent is a method call, to add parenthesis accordingly (eg:
+ // (-1).foo() instead of -1.foo())
+ let sugg = if let Some(parent_expr) = get_parent_expr(cx, expr)
+ && let ExprKind::MethodCall(..) = parent_expr.kind
+ && literal_str.starts_with('-')
+ {
+ format!("({literal_str}_{cast_to})")
+
+ } else {
+ format!("{literal_str}_{cast_to}")
};
+
span_lint_and_sugg(
cx,
UNNECESSARY_CAST,
expr.span,
- &format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to),
+ &format!("casting {literal_kind_name} literal to `{cast_to}` is unnecessary"),
"try",
- format!("{}_{}", matchless.trim_end_matches('.'), cast_to),
+ sugg,
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index 37b2fdcff..78e9921f0 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -2,9 +2,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{in_constant, meets_msrv, msrvs, SpanlessEq};
+use clippy_utils::{in_constant, is_integer_literal, meets_msrv, msrvs, SpanlessEq};
use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -82,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
item.span,
"checked cast can be simplified",
"try",
- format!("{}::try_from({}).is_ok()", to_type, snippet),
+ format!("{to_type}::try_from({snippet}).is_ok()"),
applicability,
);
}
@@ -223,16 +222,7 @@ fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> {
/// Check for `expr >= 0`
fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> {
- if_chain! {
- if let ExprKind::Lit(ref lit) = &check.kind;
- if let LitKind::Int(0, _) = &lit.node;
-
- then {
- Some(Conversion::new_any(candidate))
- } else {
- None
- }
- }
+ is_integer_literal(check, 0).then(|| Conversion::new_any(candidate))
}
/// Check for `expr >= (to_type::MIN as from_type)`
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 33c44f8b2..77af3b53d 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -3,10 +3,12 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::for_each_expr;
use clippy_utils::LimitStack;
+use core::ops::ControlFlow;
use rustc_ast::ast::Attribute;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
-use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId};
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, ExprKind, FnDecl, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
@@ -61,11 +63,27 @@ impl CognitiveComplexity {
return;
}
- let expr = &body.value;
+ let expr = body.value;
+
+ let mut cc = 1u64;
+ let mut returns = 0u64;
+ let _: Option<!> = for_each_expr(expr, |e| {
+ match e.kind {
+ ExprKind::If(_, _, _) => {
+ cc += 1;
+ },
+ ExprKind::Match(_, arms, _) => {
+ if arms.len() > 1 {
+ cc += 1;
+ }
+ cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64;
+ },
+ ExprKind::Ret(_) => returns += 1,
+ _ => {},
+ }
+ ControlFlow::Continue(())
+ });
- let mut helper = CcHelper { cc: 1, returns: 0 };
- helper.visit_expr(expr);
- let CcHelper { cc, returns } = helper;
let ret_ty = cx.typeck_results().node_type(expr.hir_id);
let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym::Result) {
returns
@@ -74,13 +92,12 @@ impl CognitiveComplexity {
(returns / 2)
};
- let mut rust_cc = cc;
// prevent degenerate cases where unreachable code contains `return` statements
- if rust_cc >= ret_adjust {
- rust_cc -= ret_adjust;
+ if cc >= ret_adjust {
+ cc -= ret_adjust;
}
- if rust_cc > self.limit.limit() {
+ if cc > self.limit.limit() {
let fn_span = match kind {
FnKind::ItemFn(ident, _, _) | FnKind::Method(ident, _) => ident.span,
FnKind::Closure => {
@@ -107,8 +124,7 @@ impl CognitiveComplexity {
COGNITIVE_COMPLEXITY,
fn_span,
&format!(
- "the function has a cognitive complexity of ({}/{})",
- rust_cc,
+ "the function has a cognitive complexity of ({cc}/{})",
self.limit.limit()
),
None,
@@ -141,27 +157,3 @@ impl<'tcx> LateLintPass<'tcx> for CognitiveComplexity {
self.limit.pop_attrs(cx.sess(), attrs, "cognitive_complexity");
}
}
-
-struct CcHelper {
- cc: u64,
- returns: u64,
-}
-
-impl<'tcx> Visitor<'tcx> for CcHelper {
- fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
- walk_expr(self, e);
- match e.kind {
- ExprKind::If(_, _, _) => {
- self.cc += 1;
- },
- ExprKind::Match(_, arms, _) => {
- if arms.len() > 1 {
- self.cc += 1;
- }
- self.cc += arms.iter().filter(|arm| arm.guard.is_some()).count() as u64;
- },
- ExprKind::Ret(_) => self.returns += 1,
- _ => {},
- }
- }
-}
diff --git a/src/tools/clippy/clippy_lints/src/comparison_chain.rs b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
index a05b41eb3..0fe973b49 100644
--- a/src/tools/clippy/clippy_lints/src/comparison_chain.rs
+++ b/src/tools/clippy/clippy_lints/src/comparison_chain.rs
@@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{get_trait_def_id, if_sequence, in_constant, is_else_clause, paths, SpanlessEq};
+use clippy_utils::{if_sequence, in_constant, is_else_clause, SpanlessEq};
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
@@ -106,7 +107,10 @@ impl<'tcx> LateLintPass<'tcx> for ComparisonChain {
// Check that the type being compared implements `core::cmp::Ord`
let ty = cx.typeck_results().expr_ty(lhs1);
- let is_ord = get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[]));
+ let is_ord = cx
+ .tcx
+ .get_diagnostic_item(sym::Ord)
+ .map_or(false, |id| implements_trait(cx, ty, id, &[]));
if !is_ord {
return;
diff --git a/src/tools/clippy/clippy_lints/src/copy_iterator.rs b/src/tools/clippy/clippy_lints/src/copy_iterator.rs
index 026683f60..e38f77268 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.def_id);
+ let ty = cx.tcx.type_of(item.owner_id);
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/default.rs b/src/tools/clippy/clippy_lints/src/default.rs
index 4e68d6810..7f937de1d 100644
--- a/src/tools/clippy/clippy_lints/src/default.rs
+++ b/src/tools/clippy/clippy_lints/src/default.rs
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
cx,
DEFAULT_TRAIT_ACCESS,
expr.span,
- &format!("calling `{}` is more clear than this expression", replacement),
+ &format!("calling `{replacement}` is more clear than this expression"),
"try",
replacement,
Applicability::Unspecified, // First resolve the TODO above
@@ -210,7 +210,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
.map(|(field, rhs)| {
// extract and store the assigned value for help message
let value_snippet = snippet_with_macro_callsite(cx, rhs.span, "..");
- format!("{}: {}", field, value_snippet)
+ format!("{field}: {value_snippet}")
})
.collect::<Vec<String>>()
.join(", ");
@@ -227,7 +227,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
.map(ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
- format!("{}::<{}>", adt_def_ty_name, &tys_str)
+ format!("{adt_def_ty_name}::<{}>", &tys_str)
} else {
binding_type.to_string()
}
@@ -235,12 +235,12 @@ impl<'tcx> LateLintPass<'tcx> for Default {
let sugg = if ext_with_default {
if field_list.is_empty() {
- format!("{}::default()", binding_type)
+ format!("{binding_type}::default()")
} else {
- format!("{} {{ {}, ..Default::default() }}", binding_type, field_list)
+ format!("{binding_type} {{ {field_list}, ..Default::default() }}")
}
} else {
- format!("{} {{ {} }}", binding_type, field_list)
+ format!("{binding_type} {{ {field_list} }}")
};
// span lint once per statement that binds default
@@ -250,10 +250,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
first_assign.unwrap().span,
"field assignment outside of initializer for an instance created with Default::default()",
Some(local.span),
- &format!(
- "consider initializing the variable with `{}` and removing relevant reassignments",
- sugg
- ),
+ &format!("consider initializing the variable with `{sugg}` and removing relevant reassignments"),
);
self.reassigned_linted.insert(span);
}
diff --git a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
index 3c996d3d2..1ad929864 100644
--- a/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
+++ b/src/tools/clippy/clippy_lints/src/default_instead_of_iter_empty.rs
@@ -23,7 +23,7 @@ declare_clippy_lint! {
/// let _ = std::iter::empty::<usize>();
/// let iter: std::iter::Empty<usize> = std::iter::empty();
/// ```
- #[clippy::version = "1.63.0"]
+ #[clippy::version = "1.64.0"]
pub DEFAULT_INSTEAD_OF_ITER_EMPTY,
style,
"check `std::iter::Empty::default()` and replace with `std::iter::empty()`"
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 be02f328e..03460689e 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
-use clippy_utils::numeric_literal;
use clippy_utils::source::snippet_opt;
+use clippy_utils::{get_parent_node, numeric_literal};
use if_chain::if_chain;
use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::{
intravisit::{walk_expr, walk_stmt, Visitor},
- Body, Expr, ExprKind, HirId, Lit, Stmt, StmtKind,
+ Body, Expr, ExprKind, HirId, ItemKind, Lit, Node, Stmt, StmtKind,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::{
@@ -55,22 +55,31 @@ declare_lint_pass!(DefaultNumericFallback => [DEFAULT_NUMERIC_FALLBACK]);
impl<'tcx> LateLintPass<'tcx> for DefaultNumericFallback {
fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
- let mut visitor = NumericFallbackVisitor::new(cx);
+ let is_parent_const = if let Some(Node::Item(item)) = get_parent_node(cx.tcx, body.id().hir_id) {
+ matches!(item.kind, ItemKind::Const(..))
+ } else {
+ false
+ };
+ let mut visitor = NumericFallbackVisitor::new(cx, is_parent_const);
visitor.visit_body(body);
}
}
struct NumericFallbackVisitor<'a, 'tcx> {
/// Stack manages type bound of exprs. The top element holds current expr type.
- ty_bounds: Vec<TyBound<'tcx>>,
+ ty_bounds: Vec<ExplicitTyBound>,
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
- fn new(cx: &'a LateContext<'tcx>) -> Self {
+ fn new(cx: &'a LateContext<'tcx>, is_parent_const: bool) -> Self {
Self {
- ty_bounds: vec![TyBound::Nothing],
+ ty_bounds: vec![if is_parent_const {
+ ExplicitTyBound(true)
+ } else {
+ ExplicitTyBound(false)
+ }],
cx,
}
}
@@ -79,10 +88,9 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
fn check_lit(&self, lit: &Lit, lit_ty: Ty<'tcx>, emit_hir_id: HirId) {
if_chain! {
if !in_external_macro(self.cx.sess(), lit.span);
- if let Some(ty_bound) = self.ty_bounds.last();
+ if matches!(self.ty_bounds.last(), Some(ExplicitTyBound(false)));
if matches!(lit.node,
LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed));
- if !ty_bound.is_numeric();
then {
let (suffix, is_float) = match lit_ty.kind() {
ty::Int(IntTy::I32) => ("i32", false),
@@ -95,8 +103,8 @@ impl<'a, 'tcx> NumericFallbackVisitor<'a, 'tcx> {
src
} else {
match lit.node {
- LitKind::Int(src, _) => format!("{}", src),
- LitKind::Float(src, _) => format!("{}", src),
+ LitKind::Int(src, _) => format!("{src}"),
+ LitKind::Float(src, _) => format!("{src}"),
_ => return,
}
};
@@ -123,7 +131,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
if let Some(fn_sig) = fn_sig_opt(self.cx, func.hir_id) {
for (expr, bound) in iter::zip(*args, fn_sig.skip_binder().inputs()) {
// Push found arg type, then visit arg.
- self.ty_bounds.push(TyBound::Ty(*bound));
+ self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
self.ty_bounds.pop();
}
@@ -135,7 +143,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
if let Some(def_id) = self.cx.typeck_results().type_dependent_def_id(expr.hir_id) {
let fn_sig = self.cx.tcx.fn_sig(def_id).skip_binder();
for (expr, bound) in iter::zip(std::iter::once(*receiver).chain(args.iter()), fn_sig.inputs()) {
- self.ty_bounds.push(TyBound::Ty(*bound));
+ self.ty_bounds.push((*bound).into());
self.visit_expr(expr);
self.ty_bounds.pop();
}
@@ -169,7 +177,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
// Visit base with no bound.
if let Some(base) = base {
- self.ty_bounds.push(TyBound::Nothing);
+ self.ty_bounds.push(ExplicitTyBound(false));
self.visit_expr(base);
self.ty_bounds.pop();
}
@@ -192,15 +200,10 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> {
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
match stmt.kind {
- StmtKind::Local(local) => {
- if local.ty.is_some() {
- self.ty_bounds.push(TyBound::Any);
- } else {
- self.ty_bounds.push(TyBound::Nothing);
- }
- },
+ // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
+ StmtKind::Local(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())),
- _ => self.ty_bounds.push(TyBound::Nothing),
+ _ => self.ty_bounds.push(ExplicitTyBound(false)),
}
walk_stmt(self, stmt);
@@ -218,28 +221,18 @@ fn fn_sig_opt<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<PolyFnSig<'
}
}
+/// Wrapper around a `bool` to make the meaning of the value clearer
#[derive(Debug, Clone, Copy)]
-enum TyBound<'tcx> {
- Any,
- Ty(Ty<'tcx>),
- Nothing,
-}
+struct ExplicitTyBound(pub bool);
-impl<'tcx> TyBound<'tcx> {
- fn is_numeric(self) -> bool {
- match self {
- TyBound::Any => true,
- TyBound::Ty(t) => t.is_numeric(),
- TyBound::Nothing => false,
- }
+impl<'tcx> From<Ty<'tcx>> for ExplicitTyBound {
+ fn from(v: Ty<'tcx>) -> Self {
+ Self(v.is_numeric())
}
}
-impl<'tcx> From<Option<Ty<'tcx>>> for TyBound<'tcx> {
+impl<'tcx> From<Option<Ty<'tcx>>> for ExplicitTyBound {
fn from(v: Option<Ty<'tcx>>) -> Self {
- match v {
- Some(t) => TyBound::Ty(t),
- None => TyBound::Nothing,
- }
+ Self(v.map_or(false, Ty::is_numeric))
}
}
diff --git a/src/tools/clippy/clippy_lints/src/default_union_representation.rs b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
index d559ad423..dec357ab7 100644
--- a/src/tools/clippy/clippy_lints/src/default_union_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/default_union_representation.rs
@@ -1,10 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_help;
use rustc_hir::{self as hir, HirId, Item, ItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultUnionRepresentation {
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` to explicitly specify memory layout",
- cx.tcx.def_path_str(item.def_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id.to_def_id())
),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs
index 88e28018e..a37ee82d4 100644
--- a/src/tools/clippy/clippy_lints/src/dereference.rs
+++ b/src/tools/clippy/clippy_lints/src/dereference.rs
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
+use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
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};
@@ -11,21 +12,24 @@ use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_ty, Visitor};
use rustc_hir::{
- self as hir, def_id::DefId, BindingAnnotation, Body, BodyId, BorrowKind, Closure, Expr, ExprKind, FnRetTy,
- GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind,
- Path, QPath, TraitItem, TraitItemKind, TyKind, UnOp,
+ self as hir,
+ def_id::{DefId, LocalDefId},
+ BindingAnnotation, Body, BodyId, BorrowKind, Closure, Expr, ExprKind, FnRetTy, GenericArg, HirId, ImplItem,
+ ImplItemKind, Item, ItemKind, Local, MatchSource, Mutability, Node, Pat, PatKind, Path, QPath, TraitItem,
+ TraitItemKind, TyKind, UnOp,
};
use rustc_index::bit_set::BitSet;
use rustc_infer::infer::TyCtxtInferExt;
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, subst::Subst, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
+ self, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{symbol::sym, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
use std::collections::VecDeque;
@@ -135,13 +139,13 @@ declare_clippy_lint! {
/// let x = String::new();
/// let y: &str = &x;
/// ```
- #[clippy::version = "1.60.0"]
+ #[clippy::version = "1.64.0"]
pub EXPLICIT_AUTO_DEREF,
complexity,
"dereferencing when the compiler would automatically dereference"
}
-impl_lint_pass!(Dereferencing => [
+impl_lint_pass!(Dereferencing<'_> => [
EXPLICIT_DEREF_METHODS,
NEEDLESS_BORROW,
REF_BINDING_TO_REFERENCE,
@@ -149,7 +153,7 @@ impl_lint_pass!(Dereferencing => [
]);
#[derive(Default)]
-pub struct Dereferencing {
+pub struct Dereferencing<'tcx> {
state: Option<(State, StateData)>,
// While parsing a `deref` method call in ufcs form, the path to the function is itself an
@@ -170,11 +174,16 @@ pub struct Dereferencing {
/// e.g. `m!(x) | Foo::Bar(ref x)`
ref_locals: FxIndexMap<HirId, Option<RefPat>>,
+ /// Stack of (body owner, `PossibleBorrowerMap`) pairs. Used by
+ /// `needless_borrow_impl_arg_position` to determine when a borrowed expression can instead
+ /// be moved.
+ possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
+
// `IntoIterator` for arrays requires Rust 1.53.
msrv: Option<RustcVersion>,
}
-impl Dereferencing {
+impl<'tcx> Dereferencing<'tcx> {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
Self {
@@ -184,6 +193,7 @@ impl Dereferencing {
}
}
+#[derive(Debug)]
struct StateData {
/// Span of the top level expression
span: Span,
@@ -191,12 +201,14 @@ struct StateData {
position: Position,
}
+#[derive(Debug)]
struct DerefedBorrow {
count: usize,
msg: &'static str,
snip_expr: Option<HirId>,
}
+#[derive(Debug)]
enum State {
// Any number of deref method calls.
DerefMethod {
@@ -241,7 +253,7 @@ struct RefPat {
hir_id: HirId,
}
-impl<'tcx> LateLintPass<'tcx> for Dereferencing {
+impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
#[expect(clippy::too_many_lines)]
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// Skip path expressions from deref calls. e.g. `Deref::deref(e)`
@@ -275,11 +287,13 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
match (self.state.take(), kind) {
(None, kind) => {
let expr_ty = typeck.expr_ty(expr);
- let (position, adjustments) = walk_parents(cx, expr, self.msrv);
-
+ let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, self.msrv);
match kind {
RefOp::Deref => {
- if let Position::FieldAccess(name) = position
+ if let Position::FieldAccess {
+ name,
+ of_union: false,
+ } = position
&& !ty_contains_field(typeck.expr_ty(sub_expr), name)
{
self.state = Some((
@@ -297,13 +311,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
if !is_lint_allowed(cx, EXPLICIT_DEREF_METHODS, expr.hir_id)
&& position.lint_explicit_deref() =>
{
+ let ty_changed_count = usize::from(!deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)));
self.state = Some((
State::DerefMethod {
- ty_changed_count: if deref_method_same_type(expr_ty, typeck.expr_ty(sub_expr)) {
- 0
- } else {
- 1
- },
+ ty_changed_count,
is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)),
target_mut,
},
@@ -454,7 +465,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
(Some((State::DerefedBorrow(state), data)), RefOp::Deref) => {
let position = data.position;
report(cx, expr, State::DerefedBorrow(state), data);
- if let Position::FieldAccess(name) = position
+ if let Position::FieldAccess{name, ..} = position
&& !ty_contains_field(typeck.expr_ty(sub_expr), name)
{
self.state = Some((
@@ -548,6 +559,12 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing {
}
fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
+ if self.possible_borrowers.last().map_or(false, |&(local_def_id, _)| {
+ local_def_id == cx.tcx.hir().body_owner_def_id(body.id())
+ }) {
+ self.possible_borrowers.pop();
+ }
+
if Some(body.id()) == self.current_body {
for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
let replacements = pat.replacements;
@@ -619,14 +636,17 @@ fn deref_method_same_type<'tcx>(result_ty: Ty<'tcx>, arg_ty: Ty<'tcx>) -> bool {
}
/// The position of an expression relative to it's parent.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
enum Position {
MethodReceiver,
/// The method is defined on a reference type. e.g. `impl Foo for &T`
MethodReceiverRefImpl,
Callee,
ImplArg(HirId),
- FieldAccess(Symbol),
+ FieldAccess {
+ name: Symbol,
+ of_union: bool,
+ }, // union fields cannot be auto borrowed
Postfix,
Deref,
/// Any other location which will trigger auto-deref to a specific time.
@@ -648,7 +668,10 @@ impl Position {
}
fn can_auto_borrow(self) -> bool {
- matches!(self, Self::MethodReceiver | Self::FieldAccess(_) | Self::Callee)
+ matches!(
+ self,
+ Self::MethodReceiver | Self::FieldAccess { of_union: false, .. } | Self::Callee
+ )
}
fn lint_explicit_deref(self) -> bool {
@@ -660,7 +683,7 @@ impl Position {
Self::MethodReceiver
| Self::MethodReceiverRefImpl
| Self::Callee
- | Self::FieldAccess(_)
+ | Self::FieldAccess { .. }
| Self::Postfix => PREC_POSTFIX,
Self::ImplArg(_) | Self::Deref => PREC_PREFIX,
Self::DerefStable(p, _) | Self::ReborrowStable(p) | Self::Other(p) => p,
@@ -674,6 +697,7 @@ impl Position {
#[expect(clippy::too_many_lines)]
fn walk_parents<'tcx>(
cx: &LateContext<'tcx>,
+ possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
e: &'tcx Expr<'_>,
msrv: Option<RustcVersion>,
) -> (Position, &'tcx [Adjustment<'tcx>]) {
@@ -691,47 +715,47 @@ fn walk_parents<'tcx>(
},
Node::Item(&Item {
kind: ItemKind::Static(..) | ItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
})
| Node::TraitItem(&TraitItem {
kind: TraitItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
})
| Node::ImplItem(&ImplItem {
kind: ImplItemKind::Const(..),
- def_id,
+ owner_id,
span,
..
}) if span.ctxt() == ctxt => {
- let ty = cx.tcx.type_of(def_id);
+ let ty = cx.tcx.type_of(owner_id.def_id);
Some(ty_auto_deref_stability(cx, ty, precedence).position_for_result(cx))
},
Node::Item(&Item {
kind: ItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
})
| Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
})
| Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(..),
- def_id,
+ owner_id,
span,
..
}) if span.ctxt() == ctxt => {
let output = cx
.tcx
- .erase_late_bound_regions(cx.tcx.fn_sig(def_id.to_def_id()).output());
+ .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))
},
@@ -788,7 +812,16 @@ fn walk_parents<'tcx>(
Some(hir_ty) => binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars()),
None => {
if let ty::Param(param_ty) = ty.skip_binder().kind() {
- needless_borrow_impl_arg_position(cx, parent, i, *param_ty, e, precedence, msrv)
+ needless_borrow_impl_arg_position(
+ cx,
+ possible_borrowers,
+ parent,
+ i,
+ *param_ty,
+ e,
+ precedence,
+ msrv,
+ )
} else {
ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
.position_for_arg()
@@ -823,11 +856,10 @@ fn walk_parents<'tcx>(
// Trait methods taking `self`
arg_ty
} && impl_ty.is_ref()
- && cx.tcx.infer_ctxt().enter(|infcx|
- infcx
- .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
- .must_apply_modulo_regions()
- )
+ && let infcx = cx.tcx.infer_ctxt().build()
+ && infcx
+ .type_implements_trait(trait_id, impl_ty, subs, cx.param_env)
+ .must_apply_modulo_regions()
{
return Some(Position::MethodReceiverRefImpl)
}
@@ -836,7 +868,16 @@ fn walk_parents<'tcx>(
args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
if let ty::Param(param_ty) = ty.kind() {
- needless_borrow_impl_arg_position(cx, parent, i + 1, *param_ty, e, precedence, msrv)
+ needless_borrow_impl_arg_position(
+ cx,
+ possible_borrowers,
+ parent,
+ i + 1,
+ *param_ty,
+ e,
+ precedence,
+ msrv,
+ )
} else {
ty_auto_deref_stability(
cx,
@@ -847,7 +888,10 @@ fn walk_parents<'tcx>(
}
})
},
- ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess(name.name)),
+ ExprKind::Field(child, name) if child.hir_id == e.hir_id => Some(Position::FieldAccess {
+ name: name.name,
+ of_union: is_union(cx.typeck_results(), child),
+ }),
ExprKind::Unary(UnOp::Deref, child) if child.hir_id == e.hir_id => Some(Position::Deref),
ExprKind::Match(child, _, MatchSource::TryDesugar | MatchSource::AwaitDesugar)
| ExprKind::Index(child, _)
@@ -868,6 +912,13 @@ fn walk_parents<'tcx>(
(position, adjustments)
}
+fn is_union<'tcx>(typeck: &'tcx TypeckResults<'_>, path_expr: &'tcx Expr<'_>) -> bool {
+ typeck
+ .expr_ty_adjusted(path_expr)
+ .ty_adt_def()
+ .map_or(false, rustc_middle::ty::AdtDef::is_union)
+}
+
fn closure_result_position<'tcx>(
cx: &LateContext<'tcx>,
closure: &'tcx Closure<'_>,
@@ -939,7 +990,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
cx.typeck_results().node_type(ty.ty.hir_id),
binder_args,
))
- .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
+ .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
)
}
},
@@ -954,7 +1005,7 @@ fn binding_ty_auto_deref_stability<'tcx>(
cx.typeck_results().node_type(ty.ty.hir_id),
binder_args,
))
- .is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
+ .is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
),
TyKind::OpaqueDef(..) | TyKind::Infer | TyKind::Typeof(..) | TyKind::TraitObject(..) | TyKind::Err => {
Position::ReborrowStable(precedence)
@@ -1000,8 +1051,10 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
// If the conditions are met, returns `Some(Position::ImplArg(..))`; otherwise, returns `None`.
// The "is copyable" condition is to avoid the case where removing the `&` means `e` would have to
// be moved, but it cannot be.
+#[expect(clippy::too_many_arguments)]
fn needless_borrow_impl_arg_position<'tcx>(
cx: &LateContext<'tcx>,
+ possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
parent: &Expr<'tcx>,
arg_index: usize,
param_ty: ParamTy,
@@ -1064,10 +1117,13 @@ fn needless_borrow_impl_arg_position<'tcx>(
// elements are modified each time `check_referent` is called.
let mut substs_with_referent_ty = substs_with_expr_ty.to_vec();
- let mut check_referent = |referent| {
+ let mut check_reference_and_referent = |reference, referent| {
let referent_ty = cx.typeck_results().expr_ty(referent);
- if !is_copy(cx, referent_ty) {
+ if !is_copy(cx, referent_ty)
+ && (referent_ty.has_significant_drop(cx.tcx, cx.param_env)
+ || !referent_used_exactly_once(cx, possible_borrowers, reference))
+ {
return false;
}
@@ -1101,15 +1157,14 @@ fn needless_borrow_impl_arg_position<'tcx>(
let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty);
let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
- cx.tcx
- .infer_ctxt()
- .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
+ let infcx = cx.tcx.infer_ctxt().build();
+ infcx.predicate_must_hold_modulo_regions(&obligation)
})
};
let mut needless_borrow = false;
while let ExprKind::AddrOf(_, _, referent) = expr.kind {
- if !check_referent(referent) {
+ if !check_reference_and_referent(expr, referent) {
break;
}
expr = referent;
@@ -1137,6 +1192,36 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
})
}
+fn referent_used_exactly_once<'tcx>(
+ cx: &LateContext<'tcx>,
+ possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
+ reference: &Expr<'tcx>,
+) -> bool {
+ let mir = enclosing_mir(cx.tcx, reference.hir_id);
+ if let Some(local) = expr_local(cx.tcx, reference)
+ && let [location] = *local_assignments(mir, local).as_slice()
+ && let Some(statement) = mir.basic_blocks[location.block].statements.get(location.statement_index)
+ && let StatementKind::Assign(box (_, Rvalue::Ref(_, _, place))) = statement.kind
+ && !place.has_deref()
+ {
+ let body_owner_local_def_id = cx.tcx.hir().enclosing_body_owner(reference.hir_id);
+ if possible_borrowers
+ .last()
+ .map_or(true, |&(local_def_id, _)| local_def_id != body_owner_local_def_id)
+ {
+ possible_borrowers.push((body_owner_local_def_id, PossibleBorrowerMap::new(cx, mir)));
+ }
+ let possible_borrower = &mut possible_borrowers.last_mut().unwrap().1;
+ // If `only_borrowers` were used here, the `copyable_iterator::warn` test would fail. The reason is
+ // that `PossibleBorrowerVisitor::visit_terminator` considers `place.local` a possible borrower of
+ // itself. See the comment in that method for an explanation as to why.
+ possible_borrower.bounded_borrowers(&[local], &[local, place.local], place.local, location)
+ && used_exactly_once(mir, place.local).unwrap_or(false)
+ } else {
+ false
+ }
+}
+
// Iteratively replaces `param_ty` with `new_ty` in `substs`, and similarly for each resulting
// projected type that is a type parameter. Returns `false` if replacing the types would have an
// effect on the function signature beyond substituting `new_ty` for `param_ty`.
@@ -1212,7 +1297,7 @@ impl<'tcx> TyPosition<'tcx> {
fn position_for_result(self, cx: &LateContext<'tcx>) -> Position {
match (self.position, self.ty) {
(Position::ReborrowStable(precedence), Some(ty)) => {
- Position::DerefStable(precedence, ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env))
+ Position::DerefStable(precedence, ty.is_sized(cx.tcx, cx.param_env))
},
(position, _) => position,
}
@@ -1241,7 +1326,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
ty::Adt(..) if ty.has_placeholders() || ty.has_opaque_types() => {
Position::ReborrowStable(precedence).into()
},
- ty::Adt(_, substs) if substs.has_param_types_or_consts() => {
+ ty::Adt(_, substs) if substs.has_non_region_param() => {
TyPosition::new_deref_stable_for_result(precedence, ty)
},
ty::Bool
@@ -1263,7 +1348,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
| ty::Tuple(_)
| ty::Projection(_) => Position::DerefStable(
precedence,
- ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env.without_caller_bounds()),
+ ty.is_sized(cx.tcx, cx.param_env.without_caller_bounds()),
)
.into(),
};
@@ -1311,7 +1396,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
};
let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
- format!("({})", expr_str)
+ format!("({expr_str})")
} else {
expr_str.into_owned()
};
@@ -1325,7 +1410,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
Mutability::Mut => "explicit `deref_mut` method call",
},
"try this",
- format!("{}{}{}", addr_of_str, deref_str, expr_str),
+ format!("{addr_of_str}{deref_str}{expr_str}"),
app,
);
},
@@ -1339,7 +1424,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
&& !has_enclosing_paren(&snip)
&& (expr.precedence().order() < data.position.precedence() || calls_field)
{
- format!("({})", snip)
+ format!("({snip})")
} else {
snip.into()
};
@@ -1382,9 +1467,9 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
let sugg =
if !snip_is_macro && expr.precedence().order() < precedence && !has_enclosing_paren(&snip) {
- format!("{}({})", prefix, snip)
+ format!("{prefix}({snip})")
} else {
- format!("{}{}", prefix, snip)
+ format!("{prefix}{snip}")
};
diag.span_suggestion(data.span, "try this", sugg, app);
},
@@ -1421,8 +1506,8 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
}
}
-impl Dereferencing {
- fn check_local_usage<'tcx>(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) {
+impl<'tcx> Dereferencing<'tcx> {
+ fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &Expr<'tcx>, local: HirId) {
if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
if let Some(pat) = outer_pat {
// Check for auto-deref
@@ -1463,14 +1548,14 @@ impl Dereferencing {
} else {
pat.always_deref = false;
let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
- pat.replacements.push((e.span, format!("&{}", snip)));
+ pat.replacements.push((e.span, format!("&{snip}")));
}
},
_ if !e.span.from_expansion() => {
// Double reference might be needed at this point.
pat.always_deref = false;
let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
- pat.replacements.push((e.span, format!("&{}", snip)));
+ pat.replacements.push((e.span, format!("&{snip}")));
},
// Edge case for macros. The span of the identifier will usually match the context of the
// binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
diff --git a/src/tools/clippy/clippy_lints/src/derivable_impls.rs b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
index ef9eeecc6..ae8f6b794 100644
--- a/src/tools/clippy/clippy_lints/src/derivable_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/derivable_impls.rs
@@ -1,5 +1,6 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{is_default_equivalent, peel_blocks};
+use rustc_errors::Applicability;
use rustc_hir::{
def::{DefKind, Res},
Body, Expr, ExprKind, GenericArg, Impl, ImplItemKind, Item, ItemKind, Node, PathSegment, QPath, TyKind,
@@ -69,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
self_ty,
..
}) = item.kind;
- if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
if !item.span.from_expansion();
if let Some(def_id) = trait_ref.trait_def_id();
if cx.tcx.is_diagnostic_item(sym::Default, def_id);
@@ -77,7 +78,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.def_id).ty_adt_def();
+ if let Some(adt_def) = cx.tcx.type_of(item.owner_id).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);
@@ -100,15 +101,28 @@ impl<'tcx> LateLintPass<'tcx> for DerivableImpls {
ExprKind::Struct(_, fields, _) => fields.iter().all(|ef| is_default_equivalent(cx, ef.expr)),
_ => false,
};
+
if should_emit {
- let path_string = cx.tcx.def_path_str(adt_def.did());
- span_lint_and_help(
+ let struct_span = cx.tcx.def_span(adt_def.did());
+ span_lint_and_then(
cx,
DERIVABLE_IMPLS,
item.span,
"this `impl` can be derived",
- None,
- &format!("try annotating `{}` with `#[derive(Default)]`", path_string),
+ |diag| {
+ diag.span_suggestion_hidden(
+ item.span,
+ "remove the manual implementation...",
+ String::new(),
+ Applicability::MachineApplicable
+ );
+ diag.span_suggestion(
+ struct_span.shrink_to_lo(),
+ "...and instead derive it",
+ "#[derive(Default)]\n".to_string(),
+ Applicability::MachineApplicable
+ );
+ }
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 751ca24d5..102a02138 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -191,7 +191,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.63.0"]
pub DERIVE_PARTIAL_EQ_WITHOUT_EQ,
- style,
+ nursery,
"deriving `PartialEq` on a type that can implement `Eq`, without implementing `Eq`"
}
@@ -210,8 +210,8 @@ impl<'tcx> LateLintPass<'tcx> for Derive {
..
}) = item.kind
{
- let ty = cx.tcx.type_of(item.def_id);
- let is_automatically_derived = cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ let ty = cx.tcx.type_of(item.owner_id);
+ 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);
check_ord_partial_ord(cx, item.span, trait_ref, ty, is_automatically_derived);
@@ -339,10 +339,7 @@ fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &h
Some(id) if trait_ref.trait_def_id() == Some(id) => id,
_ => return,
};
- let copy_id = match cx.tcx.lang_items().copy_trait() {
- Some(id) => id,
- None => return,
- };
+ let Some(copy_id) = cx.tcx.lang_items().copy_trait() else { return };
let (ty_adt, ty_subs) = match *ty.kind() {
// Unions can't derive clone.
ty::Adt(adt, subs) if !adt.is_union() => (adt, subs),
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_macros.rs b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
new file mode 100644
index 000000000..5ab7144e2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/disallowed_macros.rs
@@ -0,0 +1,151 @@
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::macro_backtrace;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefIdMap;
+use rustc_hir::{Expr, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{ExpnId, Span};
+
+use crate::utils::conf;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Denies the configured macros in clippy.toml
+ ///
+ /// Note: Even though this lint is warn-by-default, it will only trigger if
+ /// macros are defined in the clippy.toml file.
+ ///
+ /// ### Why is this bad?
+ /// Some macros are undesirable in certain contexts, and it's beneficial to
+ /// lint for them as needed.
+ ///
+ /// ### Example
+ /// An example clippy.toml configuration:
+ /// ```toml
+ /// # clippy.toml
+ /// disallowed-macros = [
+ /// # Can use a string as the path of the disallowed macro.
+ /// "std::print",
+ /// # Can also use an inline table with a `path` key.
+ /// { path = "std::println" },
+ /// # When using an inline table, can add a `reason` for why the macro
+ /// # is disallowed.
+ /// { path = "serde::Serialize", reason = "no serializing" },
+ /// ]
+ /// ```
+ /// ```
+ /// use serde::Serialize;
+ ///
+ /// // Example code where clippy issues a warning
+ /// println!("warns");
+ ///
+ /// // The diagnostic will contain the message "no serializing"
+ /// #[derive(Serialize)]
+ /// struct Data {
+ /// name: String,
+ /// value: usize,
+ /// }
+ /// ```
+ #[clippy::version = "1.65.0"]
+ pub DISALLOWED_MACROS,
+ style,
+ "use of a disallowed macro"
+}
+
+pub struct DisallowedMacros {
+ conf_disallowed: Vec<conf::DisallowedPath>,
+ disallowed: DefIdMap<usize>,
+ seen: FxHashSet<ExpnId>,
+}
+
+impl DisallowedMacros {
+ pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
+ Self {
+ conf_disallowed,
+ disallowed: DefIdMap::default(),
+ seen: FxHashSet::default(),
+ }
+ }
+
+ fn check(&mut self, cx: &LateContext<'_>, span: Span) {
+ if self.conf_disallowed.is_empty() {
+ return;
+ }
+
+ for mac in macro_backtrace(span) {
+ if !self.seen.insert(mac.expn) {
+ return;
+ }
+
+ if let Some(&index) = self.disallowed.get(&mac.def_id) {
+ let conf = &self.conf_disallowed[index];
+
+ span_lint_and_then(
+ cx,
+ DISALLOWED_MACROS,
+ mac.span,
+ &format!("use of a disallowed macro `{}`", conf.path()),
+ |diag| {
+ if let Some(reason) = conf.reason() {
+ diag.note(&format!("{reason} (from clippy.toml)"));
+ }
+ },
+ );
+ }
+ }
+ }
+}
+
+impl_lint_pass!(DisallowedMacros => [DISALLOWED_MACROS]);
+
+impl LateLintPass<'_> for DisallowedMacros {
+ fn check_crate(&mut self, cx: &LateContext<'_>) {
+ for (index, conf) in self.conf_disallowed.iter().enumerate() {
+ let segs: Vec<_> = conf.path().split("::").collect();
+ if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::MacroNS)) {
+ self.disallowed.insert(id, index);
+ }
+ }
+ }
+
+ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+ self.check(cx, expr.span);
+ }
+
+ fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &Stmt<'_>) {
+ self.check(cx, stmt.span);
+ }
+
+ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) {
+ self.check(cx, ty.span);
+ }
+
+ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
+ self.check(cx, pat.span);
+ }
+
+ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+ self.check(cx, item.span);
+ self.check(cx, item.vis_span);
+ }
+
+ fn check_foreign_item(&mut self, cx: &LateContext<'_>, item: &ForeignItem<'_>) {
+ self.check(cx, item.span);
+ self.check(cx, item.vis_span);
+ }
+
+ fn check_impl_item(&mut self, cx: &LateContext<'_>, item: &ImplItem<'_>) {
+ self.check(cx, item.span);
+ self.check(cx, item.vis_span);
+ }
+
+ fn check_trait_item(&mut self, cx: &LateContext<'_>, item: &TraitItem<'_>) {
+ self.check(cx, item.span);
+ }
+
+ fn check_path(&mut self, cx: &LateContext<'_>, path: &Path<'_>, _: HirId) {
+ self.check(cx, path.span);
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
index 53973ab79..6ac85606d 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_methods.rs
@@ -1,7 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
-use rustc_hir::{def::Res, def_id::DefIdMap, Expr, ExprKind};
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefIdMap;
+use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -58,12 +60,12 @@ declare_clippy_lint! {
#[derive(Clone, Debug)]
pub struct DisallowedMethods {
- conf_disallowed: Vec<conf::DisallowedMethod>,
+ conf_disallowed: Vec<conf::DisallowedPath>,
disallowed: DefIdMap<usize>,
}
impl DisallowedMethods {
- pub fn new(conf_disallowed: Vec<conf::DisallowedMethod>) -> Self {
+ pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
Self {
conf_disallowed,
disallowed: DefIdMap::default(),
@@ -77,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
fn check_crate(&mut self, cx: &LateContext<'_>) {
for (index, conf) in self.conf_disallowed.iter().enumerate() {
let segs: Vec<_> = conf.path().split("::").collect();
- if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs) {
+ if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::ValueNS)) {
self.disallowed.insert(id, index);
}
}
@@ -92,9 +94,8 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
} else {
path_def_id(cx, expr)
};
- let def_id = match uncalled_path.or_else(|| fn_def_id(cx, expr)) {
- Some(def_id) => def_id,
- None => return,
+ let Some(def_id) = uncalled_path.or_else(|| fn_def_id(cx, expr)) else {
+ return
};
let conf = match self.disallowed.get(&def_id) {
Some(&index) => &self.conf_disallowed[index],
@@ -102,11 +103,8 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
};
let msg = format!("use of a disallowed method `{}`", conf.path());
span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
- if let conf::DisallowedMethod::WithReason {
- reason: Some(reason), ..
- } = conf
- {
- diag.note(&format!("{} (from clippy.toml)", reason));
+ if let Some(reason) = conf.reason() {
+ diag.note(&format!("{reason} (from clippy.toml)"));
}
});
}
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
index 0c27c3f92..084190f00 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs
@@ -99,8 +99,7 @@ impl EarlyLintPass for DisallowedScriptIdents {
DISALLOWED_SCRIPT_IDENTS,
span,
&format!(
- "identifier `{}` has a Unicode script that is not allowed by configuration: {}",
- symbol_str,
+ "identifier `{symbol_str}` has a Unicode script that is not allowed by configuration: {}",
script.full_name()
),
);
diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
index 28dbfbab2..c7131fc16 100644
--- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs
+++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs
@@ -1,9 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::{
- def::Res, def_id::DefId, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind,
-};
+use rustc_hir::def::{Namespace, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
@@ -52,13 +52,13 @@ declare_clippy_lint! {
}
#[derive(Clone, Debug)]
pub struct DisallowedTypes {
- conf_disallowed: Vec<conf::DisallowedType>,
+ conf_disallowed: Vec<conf::DisallowedPath>,
def_ids: FxHashMap<DefId, Option<String>>,
prim_tys: FxHashMap<PrimTy, Option<String>>,
}
impl DisallowedTypes {
- pub fn new(conf_disallowed: Vec<conf::DisallowedType>) -> Self {
+ pub fn new(conf_disallowed: Vec<conf::DisallowedPath>) -> Self {
Self {
conf_disallowed,
def_ids: FxHashMap::default(),
@@ -88,15 +88,9 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
fn check_crate(&mut self, cx: &LateContext<'_>) {
for conf in &self.conf_disallowed {
- let (path, reason) = match conf {
- conf::DisallowedType::Simple(path) => (path, None),
- conf::DisallowedType::WithReason { path, reason } => (
- path,
- reason.as_ref().map(|reason| format!("{} (from clippy.toml)", reason)),
- ),
- };
- let segs: Vec<_> = path.split("::").collect();
- match clippy_utils::def_path_res(cx, &segs) {
+ let segs: Vec<_> = conf.path().split("::").collect();
+ let reason = conf.reason().map(|reason| format!("{reason} (from clippy.toml)"));
+ match clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
Res::Def(_, id) => {
self.def_ids.insert(id, reason);
},
@@ -130,7 +124,7 @@ fn emit(cx: &LateContext<'_>, name: &str, span: Span, reason: Option<&str>) {
cx,
DISALLOWED_TYPES,
span,
- &format!("`{}` is not allowed according to config", name),
+ &format!("`{name}` is not allowed according to config"),
|diag| {
if let Some(reason) = reason {
diag.note(reason);
diff --git a/src/tools/clippy/clippy_lints/src/doc.rs b/src/tools/clippy/clippy_lints/src/doc.rs
index eb158d850..24d6a6951 100644
--- a/src/tools/clippy/clippy_lints/src/doc.rs
+++ b/src/tools/clippy/clippy_lints/src/doc.rs
@@ -198,6 +198,29 @@ declare_clippy_lint! {
"presence of `fn main() {` in code examples"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
+ /// outside of code blocks
+ /// ### Why is this bad?
+ /// It is likely a typo when defining an intra-doc link
+ ///
+ /// ### Example
+ /// ```rust
+ /// /// See also: ['foo']
+ /// fn bar() {}
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// /// See also: [`foo`]
+ /// fn bar() {}
+ /// ```
+ #[clippy::version = "1.63.0"]
+ pub DOC_LINK_WITH_QUOTES,
+ pedantic,
+ "possible typo for an intra-doc link"
+}
+
#[expect(clippy::module_name_repetitions)]
#[derive(Clone)]
pub struct DocMarkdown {
@@ -214,9 +237,14 @@ impl DocMarkdown {
}
}
-impl_lint_pass!(DocMarkdown =>
- [DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, NEEDLESS_DOCTEST_MAIN]
-);
+impl_lint_pass!(DocMarkdown => [
+ DOC_LINK_WITH_QUOTES,
+ DOC_MARKDOWN,
+ MISSING_SAFETY_DOC,
+ MISSING_ERRORS_DOC,
+ MISSING_PANICS_DOC,
+ NEEDLESS_DOCTEST_MAIN
+]);
impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
@@ -229,15 +257,23 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let headers = check_attrs(cx, &self.valid_idents, attrs);
match item.kind {
hir::ItemKind::Fn(ref sig, _, body_id) => {
- if !(is_entrypoint_fn(cx, item.def_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
+ if !(is_entrypoint_fn(cx, item.owner_id.to_def_id()) || in_external_macro(cx.tcx.sess, item.span)) {
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
cx,
- typeck_results: cx.tcx.typeck(item.def_id),
+ typeck_results: cx.tcx.typeck(item.owner_id.def_id),
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(
+ cx,
+ item.owner_id.def_id,
+ item.span,
+ sig,
+ headers,
+ Some(body_id),
+ fpu.panic_span,
+ );
}
},
hir::ItemKind::Impl(impl_) => {
@@ -268,7 +304,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let headers = check_attrs(cx, &self.valid_idents, attrs);
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) {
- lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, None, None);
+ lint_for_missing_headers(cx, item.owner_id.def_id, item.span, sig, headers, None, None);
}
}
}
@@ -283,11 +319,19 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
cx,
- typeck_results: cx.tcx.typeck(item.def_id),
+ typeck_results: cx.tcx.typeck(item.owner_id.def_id),
panic_span: None,
};
fpu.visit_expr(body.value);
- lint_for_missing_headers(cx, item.def_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
+ lint_for_missing_headers(
+ cx,
+ item.owner_id.def_id,
+ item.span,
+ sig,
+ headers,
+ Some(body_id),
+ fpu.panic_span,
+ );
}
}
}
@@ -301,7 +345,7 @@ fn lint_for_missing_headers<'tcx>(
body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) {
- if !cx.access_levels.is_exported(def_id) {
+ if !cx.effective_visibilities.is_exported(def_id) {
return; // Private functions do not require doc comments
}
@@ -416,7 +460,7 @@ pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span:
(no_stars, sizes)
}
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default)]
struct DocHeaders {
safety: bool,
errors: bool,
@@ -460,11 +504,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
}
if doc.is_empty() {
- return DocHeaders {
- safety: false,
- errors: false,
- panics: false,
- };
+ return DocHeaders::default();
}
let mut cb = fake_broken_link_callback;
@@ -505,11 +545,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
use pulldown_cmark::Tag::{CodeBlock, Heading, Item, Link, Paragraph};
use pulldown_cmark::{CodeBlockKind, CowStr};
- let mut headers = DocHeaders {
- safety: false,
- errors: false,
- panics: false,
- };
+ let mut headers = DocHeaders::default();
let mut in_code = false;
let mut in_link = None;
let mut in_heading = false;
@@ -596,6 +632,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
check_code(cx, &text, edition, span);
}
} else {
+ 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));
text_to_check.push((text, span));
@@ -606,6 +643,27 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
headers
}
+fn check_link_quotes(
+ cx: &LateContext<'_>,
+ in_link: bool,
+ trimmed_text: &str,
+ span: Span,
+ range: &Range<usize>,
+ begin: usize,
+ text_len: usize,
+) {
+ if in_link && trimmed_text.starts_with('\'') && trimmed_text.ends_with('\'') {
+ // fix the span to only point at the text within the link
+ let lo = span.lo() + BytePos::from_usize(range.start - begin);
+ span_lint(
+ cx,
+ DOC_LINK_WITH_QUOTES,
+ span.with_lo(lo).with_hi(lo + BytePos::from_usize(text_len)),
+ "possible intra-doc link using quotes instead of backticks",
+ );
+ }
+}
+
fn get_current_span(spans: &[(usize, Span)], idx: usize) -> (usize, Span) {
let index = match spans.binary_search_by(|c| c.0.cmp(&idx)) {
Ok(o) => o,
@@ -790,7 +848,7 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
diag.span_suggestion_with_style(
span,
"try",
- format!("`{}`", snippet),
+ format!("`{snippet}`"),
applicability,
// always show the suggestion in a separate line, since the
// inline presentation adds another pair of backticks
diff --git a/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs b/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs
deleted file mode 100644
index 0ff1d2755..000000000
--- a/src/tools/clippy/clippy_lints/src/doc_link_with_quotes.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use itertools::Itertools;
-use rustc_ast::{AttrKind, Attribute};
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-
-declare_clippy_lint! {
- /// ### What it does
- /// Detects the syntax `['foo']` in documentation comments (notice quotes instead of backticks)
- /// outside of code blocks
- /// ### Why is this bad?
- /// It is likely a typo when defining an intra-doc link
- ///
- /// ### Example
- /// ```rust
- /// /// See also: ['foo']
- /// fn bar() {}
- /// ```
- /// Use instead:
- /// ```rust
- /// /// See also: [`foo`]
- /// fn bar() {}
- /// ```
- #[clippy::version = "1.63.0"]
- pub DOC_LINK_WITH_QUOTES,
- pedantic,
- "possible typo for an intra-doc link"
-}
-declare_lint_pass!(DocLinkWithQuotes => [DOC_LINK_WITH_QUOTES]);
-
-impl EarlyLintPass for DocLinkWithQuotes {
- fn check_attribute(&mut self, ctx: &EarlyContext<'_>, attr: &Attribute) {
- if let AttrKind::DocComment(_, symbol) = attr.kind {
- if contains_quote_link(symbol.as_str()) {
- span_lint(
- ctx,
- DOC_LINK_WITH_QUOTES,
- attr.span,
- "possible intra-doc link using quotes instead of backticks",
- );
- }
- }
- }
-}
-
-fn contains_quote_link(s: &str) -> bool {
- let mut in_backticks = false;
- let mut found_opening = false;
-
- for c in s.chars().tuple_windows::<(char, char)>() {
- match c {
- ('`', _) => in_backticks = !in_backticks,
- ('[', '\'') if !in_backticks => found_opening = true,
- ('\'', ']') if !in_backticks && found_opening => return true,
- _ => {},
- }
- }
-
- false
-}
diff --git a/src/tools/clippy/clippy_lints/src/double_parens.rs b/src/tools/clippy/clippy_lints/src/double_parens.rs
index a33ef5ce6..0f1d70186 100644
--- a/src/tools/clippy/clippy_lints/src/double_parens.rs
+++ b/src/tools/clippy/clippy_lints/src/double_parens.rs
@@ -61,9 +61,8 @@ impl EarlyLintPass for DoubleParens {
}
}
},
- ExprKind::MethodCall(_, ref params, _) => {
- if params.len() == 2 {
- let param = &params[1];
+ ExprKind::MethodCall(_, _, ref params, _) => {
+ if let [ref param] = params[..] {
if let ExprKind::Paren(_) = param.kind {
span_lint(cx, DOUBLE_PARENS, param.span, msg);
}
diff --git a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
index b35f0b8ca..4721a7b37 100644
--- a/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/drop_forget_ref.rs
@@ -1,7 +1,8 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_note};
+use clippy_utils::get_parent_node;
use clippy_utils::is_must_use_func_call;
use clippy_utils::ty::{is_copy, is_must_use_ty, is_type_lang_item};
-use rustc_hir::{Expr, ExprKind, LangItem};
+use rustc_hir::{Arm, Expr, ExprKind, LangItem, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
@@ -202,11 +203,13 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
&& let Some(fn_name) = cx.tcx.get_diagnostic_name(def_id)
{
let arg_ty = cx.typeck_results().expr_ty(arg);
+ let is_copy = is_copy(cx, arg_ty);
+ let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
let (lint, msg) = match fn_name {
sym::mem_drop if arg_ty.is_ref() => (DROP_REF, DROP_REF_SUMMARY),
sym::mem_forget if arg_ty.is_ref() => (FORGET_REF, FORGET_REF_SUMMARY),
- sym::mem_drop if is_copy(cx, arg_ty) => (DROP_COPY, DROP_COPY_SUMMARY),
- sym::mem_forget if is_copy(cx, arg_ty) => (FORGET_COPY, FORGET_COPY_SUMMARY),
+ sym::mem_drop if is_copy && !drop_is_single_call_in_arm => (DROP_COPY, DROP_COPY_SUMMARY),
+ sym::mem_forget if is_copy => (FORGET_COPY, FORGET_COPY_SUMMARY),
sym::mem_drop if is_type_lang_item(cx, arg_ty, LangItem::ManuallyDrop) => {
span_lint_and_help(
cx,
@@ -221,7 +224,9 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
sym::mem_drop
if !(arg_ty.needs_drop(cx.tcx, cx.param_env)
|| is_must_use_func_call(cx, arg)
- || is_must_use_ty(cx, arg_ty)) =>
+ || is_must_use_ty(cx, arg_ty)
+ || drop_is_single_call_in_arm
+ ) =>
{
(DROP_NON_DROP, DROP_NON_DROP_SUMMARY)
},
@@ -236,8 +241,23 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetRef {
expr.span,
msg,
Some(arg.span),
- &format!("argument has type `{}`", arg_ty),
+ &format!("argument has type `{arg_ty}`"),
);
}
}
}
+
+// dropping returned value of a function like in the following snippet is considered idiomatic, see
+// #9482 for examples match <var> {
+// <pat> => drop(fn_with_side_effect_and_returning_some_value()),
+// ..
+// }
+fn is_single_call_in_arm<'tcx>(cx: &LateContext<'tcx>, arg: &'tcx Expr<'_>, drop_expr: &'tcx Expr<'_>) -> bool {
+ if matches!(arg.kind, ExprKind::Call(..) | ExprKind::MethodCall(..)) {
+ let parent_node = get_parent_node(cx.tcx, drop_expr.hir_id);
+ if let Some(Node::Arm(Arm { body, .. })) = &parent_node {
+ return body.hir_id == drop_expr.hir_id;
+ }
+ }
+ false
+}
diff --git a/src/tools/clippy/clippy_lints/src/empty_enum.rs b/src/tools/clippy/clippy_lints/src/empty_enum.rs
index bbebc0244..0570c2a10 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.def_id);
+ let ty = cx.tcx.type_of(item.owner_id);
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 e70df3f53..b44e62435 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -65,28 +65,24 @@ 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<'_>) {
- let (cond_expr, then_expr, else_expr) = match higher::If::hir(expr) {
- Some(higher::If { cond, then, r#else }) => (cond, then, r#else),
- _ => return,
+ let Some(higher::If { cond: cond_expr, then: then_expr, r#else: else_expr }) = higher::If::hir(expr) else {
+ return
};
- let (map_ty, contains_expr) = match try_parse_contains(cx, cond_expr) {
- Some(x) => x,
- None => return,
+ let Some((map_ty, contains_expr)) = try_parse_contains(cx, cond_expr) else {
+ return
};
- let then_search = match find_insert_calls(cx, &contains_expr, then_expr) {
- Some(x) => x,
- None => return,
+ let Some(then_search) = find_insert_calls(cx, &contains_expr, then_expr) else {
+ return
};
let mut app = Applicability::MachineApplicable;
let map_str = snippet_with_context(cx, contains_expr.map.span, contains_expr.call_ctxt, "..", &mut app).0;
let key_str = snippet_with_context(cx, contains_expr.key.span, contains_expr.call_ctxt, "..", &mut app).0;
let sugg = if let Some(else_expr) = else_expr {
- let else_search = match find_insert_calls(cx, &contains_expr, else_expr) {
- Some(search) => search,
- None => return,
+ let Some(else_search) = find_insert_calls(cx, &contains_expr, else_expr) else {
+ return;
};
if then_search.edits.is_empty() && else_search.edits.is_empty() {
@@ -113,13 +109,8 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
),
};
format!(
- "if let {}::{} = {}.entry({}) {} else {}",
+ "if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
map_ty.entry_path(),
- entry_kind,
- map_str,
- key_str,
- then_str,
- else_str,
)
} else {
// if .. { insert } else { insert }
@@ -137,16 +128,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
let indent_str = snippet_indent(cx, expr.span);
let indent_str = indent_str.as_deref().unwrap_or("");
format!(
- "match {}.entry({}) {{\n{indent} {entry}::{} => {}\n\
- {indent} {entry}::{} => {}\n{indent}}}",
- map_str,
- key_str,
- then_entry,
+ "match {map_str}.entry({key_str}) {{\n{indent_str} {entry}::{then_entry} => {}\n\
+ {indent_str} {entry}::{else_entry} => {}\n{indent_str}}}",
reindent_multiline(then_str.into(), true, Some(4 + indent_str.len())),
- else_entry,
reindent_multiline(else_str.into(), true, Some(4 + indent_str.len())),
entry = map_ty.entry_path(),
- indent = indent_str,
)
}
} else {
@@ -163,20 +149,16 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
then_search.snippet_occupied(cx, then_expr.span, &mut app)
};
format!(
- "if let {}::{} = {}.entry({}) {}",
+ "if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
map_ty.entry_path(),
- entry_kind,
- map_str,
- key_str,
- body_str,
)
} else if let Some(insertion) = then_search.as_single_insertion() {
let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
if contains_expr.negated {
if insertion.value.can_have_side_effects() {
- format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, value_str)
+ format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
} else {
- format!("{}.entry({}).or_insert({});", map_str, key_str, value_str)
+ format!("{map_str}.entry({key_str}).or_insert({value_str});")
}
} else {
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@@ -186,7 +168,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
} else {
let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
if contains_expr.negated {
- format!("{}.entry({}).or_insert_with(|| {});", map_str, key_str, block_str)
+ format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
} else {
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
// This would need to be a different lint.
diff --git a/src/tools/clippy/clippy_lints/src/enum_variants.rs b/src/tools/clippy/clippy_lints/src/enum_variants.rs
index cd36f9fcd..223545fa7 100644
--- a/src/tools/clippy/clippy_lints/src/enum_variants.rs
+++ b/src/tools/clippy/clippy_lints/src/enum_variants.rs
@@ -202,12 +202,11 @@ fn check_variant(cx: &LateContext<'_>, threshold: u64, def: &EnumDef<'_>, item_n
cx,
ENUM_VARIANT_NAMES,
span,
- &format!("all variants have the same {}fix: `{}`", what, value),
+ &format!("all variants have the same {what}fix: `{value}`"),
None,
&format!(
- "remove the {}fixes and use full paths to \
- the variants instead of glob imports",
- what
+ "remove the {what}fixes and use full paths to \
+ the variants instead of glob imports"
),
);
}
@@ -266,7 +265,7 @@ impl LateLintPass<'_> for EnumVariantNames {
}
// The `module_name_repetitions` lint should only trigger if the item has the module in its
// name. Having the same name is accepted.
- if cx.tcx.visibility(item.def_id).is_public() && item_camel.len() > mod_camel.len() {
+ if cx.tcx.visibility(item.owner_id).is_public() && item_camel.len() > mod_camel.len() {
let matching = count_match_start(mod_camel, &item_camel);
let rmatching = count_match_end(mod_camel, &item_camel);
let nchars = mod_camel.chars().count();
@@ -297,7 +296,7 @@ impl LateLintPass<'_> for EnumVariantNames {
}
}
if let ItemKind::Enum(ref def, _) = item.kind {
- if !(self.avoid_breaking_exported_api && cx.access_levels.is_exported(item.def_id)) {
+ if !(self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(item.owner_id.def_id)) {
check_variant(cx, self.threshold, def, item_name, item.span);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
index bce49165e..b40cb7cdd 100644
--- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
+++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs
@@ -51,9 +51,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
false
},
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
- PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => {
- !etc.as_opt_usize().is_some() && array_rec(a)
- }
+ PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
PatKind::Ref(x, _) | PatKind::Box(x) => unary_pattern(x),
PatKind::Path(_) | PatKind::Lit(_) => true,
}
@@ -93,9 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for PatternEquality {
"this pattern matching can be expressed using equality",
"try",
format!(
- "{} == {}",
+ "{} == {pat_str}",
snippet_with_context(cx, let_expr.init.span, expr.span.ctxt(), "..", &mut applicability).0,
- pat_str,
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index 327865e4c..7f1a4c4be 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_hir;
use rustc_hir::intravisit;
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
@@ -10,7 +11,6 @@ use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::symbol::kw;
use rustc_target::spec::abi::Abi;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
#[derive(Copy, Clone)]
pub struct BoxedLocal {
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
}
}
- let parent_id = cx.tcx.hir().get_parent_item(hir_id);
+ let parent_id = cx.tcx.hir().get_parent_item(hir_id).def_id;
let parent_node = cx.tcx.hir().find_by_def_id(parent_id);
let mut trait_self_ty = None;
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
// be sure we have `self` parameter in this function
if trait_item.kind == (AssocItemKind::Fn { has_self: true }) {
trait_self_ty = Some(
- TraitRef::identity(cx.tcx, trait_item.id.def_id.to_def_id())
+ TraitRef::identity(cx.tcx, trait_item.id.owner_id.to_def_id())
.self_ty()
.skip_binder(),
);
@@ -106,9 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
};
let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
- cx.tcx.infer_ctxt().enter(|infcx| {
- ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
for node in v.set {
span_lint_hir(
@@ -177,7 +176,13 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
}
}
- fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+ fn fake_read(
+ &mut self,
+ _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
+ _: FakeReadCause,
+ _: HirId,
+ ) {
+ }
}
impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> {
diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
index 53bc617a4..7b9786d7e 100644
--- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs
+++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::higher::VecArgs;
use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::usage::local_used_after_expr;
use clippy_utils::{higher, is_adjusted, path_to_local, path_to_local_id};
use if_chain::if_chain;
@@ -11,8 +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::subst::Subst;
-use rustc_middle::ty::{self, ClosureKind, Ty, TypeVisitable};
+use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::sym;
@@ -123,15 +122,12 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
then {
span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| {
if let Some(mut snippet) = snippet_opt(cx, callee.span) {
- if_chain! {
- if let ty::Closure(_, substs) = callee_ty.peel_refs().kind();
- if substs.as_closure().kind() == ClosureKind::FnMut;
- if path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr));
-
- then {
+ if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait()
+ && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &[])
+ && path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr))
+ {
// Mutable closure is used after current expr; we cannot consume it.
- snippet = format!("&mut {}", snippet);
- }
+ snippet = format!("&mut {snippet}");
}
diag.span_suggestion(
expr.span,
@@ -158,7 +154,7 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction {
diag.span_suggestion(
expr.span,
"replace the closure with the method itself",
- format!("{}::{}", name, path.ident.name),
+ format!("{name}::{}", path.ident.name),
Applicability::MachineApplicable,
);
})
@@ -217,9 +213,8 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, closure_ty: Ty<'tcx>, call_ty: Ty<'tc
if !closure_ty.has_late_bound_regions() {
return true;
}
- let substs = match closure_ty.kind() {
- ty::Closure(_, substs) => substs,
- _ => return false,
+ let ty::Closure(_, substs) = closure_ty.kind() else {
+ return false;
};
let closure_sig = cx.tcx.signature_unclosure(substs.as_closure().sig(), Unsafety::Normal);
cx.tcx.erase_late_bound_regions(closure_sig) == cx.tcx.erase_late_bound_regions(call_sig)
diff --git a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
index 173d41b4b..1fece5d1c 100644
--- a/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
+++ b/src/tools/clippy/clippy_lints/src/exhaustive_items.rs
@@ -73,7 +73,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
if_chain! {
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind;
- if cx.access_levels.is_exported(item.def_id);
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id);
let attrs = cx.tcx.hir().attrs(item.hir_id());
if !attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then {
@@ -97,7 +97,7 @@ impl LateLintPass<'_> for ExhaustiveItems {
item.span,
msg,
|diag| {
- let sugg = format!("#[non_exhaustive]\n{}", indent);
+ let sugg = format!("#[non_exhaustive]\n{indent}");
diag.span_suggestion(suggestion_span,
"try adding #[non_exhaustive]",
sugg,
diff --git a/src/tools/clippy/clippy_lints/src/exit.rs b/src/tools/clippy/clippy_lints/src/exit.rs
index cbf52d193..407dd1b39 100644
--- a/src/tools/clippy/clippy_lints/src/exit.rs
+++ b/src/tools/clippy/clippy_lints/src/exit.rs
@@ -33,7 +33,7 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
if let ExprKind::Path(ref path) = path_expr.kind;
if let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::EXIT);
- let parent = cx.tcx.hir().get_parent_item(e.hir_id);
+ let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
if let Some(Node::Item(Item{kind: ItemKind::Fn(..), ..})) = cx.tcx.hir().find_by_def_id(parent);
// If the next item up is a function we check if it is an entry point
// and only then emit a linter warning
diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs
index b9ed4af02..c0ea6f338 100644
--- a/src/tools/clippy/clippy_lints/src/explicit_write.rs
+++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs
@@ -80,12 +80,12 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
// used.
let (used, sugg_mac) = if let Some(macro_name) = calling_macro {
(
- format!("{}!({}(), ...)", macro_name, dest_name),
+ format!("{macro_name}!({dest_name}(), ...)"),
macro_name.replace("write", "print"),
)
} else {
(
- format!("{}().write_fmt(...)", dest_name),
+ format!("{dest_name}().write_fmt(...)"),
"print".into(),
)
};
@@ -100,9 +100,9 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite {
cx,
EXPLICIT_WRITE,
expr.span,
- &format!("use of `{}.unwrap()`", used),
+ &format!("use of `{used}.unwrap()`"),
"try this",
- format!("{}{}!({})", prefix, sugg_mac, inputs_snippet),
+ format!("{prefix}{sugg_mac}!({inputs_snippet})"),
applicability,
)
}
diff --git a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
index 1f69f34a2..0a633f242 100644
--- a/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
+++ b/src/tools/clippy/clippy_lints/src/fallible_impl_from.rs
@@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for FallibleImplFrom {
// check for `impl From<???> for ..`
if_chain! {
if let hir::ItemKind::Impl(impl_) = &item.kind;
- if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
+ if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
if cx.tcx.is_diagnostic_item(sym::From, impl_trait_ref.def_id);
then {
lint_impl_body(cx, item.span, impl_.items);
@@ -107,7 +107,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_items: &[h
let body = cx.tcx.hir().body(body_id);
let mut fpu = FindPanicUnwrap {
lcx: cx,
- typeck_results: cx.tcx.typeck(impl_item.id.def_id),
+ typeck_results: cx.tcx.typeck(impl_item.id.owner_id.def_id),
result: Vec::new(),
};
fpu.visit_expr(body.value);
diff --git a/src/tools/clippy/clippy_lints/src/float_literal.rs b/src/tools/clippy/clippy_lints/src/float_literal.rs
index f2e079809..6fee7fb30 100644
--- a/src/tools/clippy/clippy_lints/src/float_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/float_literal.rs
@@ -173,9 +173,9 @@ impl FloatFormat {
T: fmt::UpperExp + fmt::LowerExp + fmt::Display,
{
match self {
- Self::LowerExp => format!("{:e}", f),
- Self::UpperExp => format!("{:E}", f),
- Self::Normal => format!("{}", f),
+ Self::LowerExp => format!("{f:e}"),
+ Self::UpperExp => format!("{f:E}"),
+ Self::Normal => format!("{f}"),
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
index ba53a9678..0ed301964 100644
--- a/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/floating_point_arithmetic.rs
@@ -142,8 +142,7 @@ fn prepare_receiver_sugg<'a>(cx: &LateContext<'_>, mut expr: &'a Expr<'a>) -> Su
if let ast::LitKind::Float(sym, ast::LitFloatType::Unsuffixed) = lit.node;
then {
let op = format!(
- "{}{}{}",
- suggestion,
+ "{suggestion}{}{}",
// Check for float literals without numbers following the decimal
// separator such as `2.` and adds a trailing zero
if sym.as_str().ends_with('.') {
@@ -172,7 +171,7 @@ fn check_log_base(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, ar
expr.span,
"logarithm for bases 2, 10 and e can be computed more accurately",
"consider using",
- format!("{}.{}()", Sugg::hir(cx, receiver, "..").maybe_par(), method),
+ format!("{}.{method}()", Sugg::hir(cx, receiver, "..").maybe_par()),
Applicability::MachineApplicable,
);
}
@@ -251,7 +250,7 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
expr.span,
"exponent for bases 2 and e can be computed more accurately",
"consider using",
- format!("{}.{}()", prepare_receiver_sugg(cx, &args[0]), method),
+ format!("{}.{method}()", prepare_receiver_sugg(cx, &args[0])),
Applicability::MachineApplicable,
);
}
@@ -312,7 +311,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
if let ExprKind::Binary(
Spanned {
- node: BinOpKind::Add, ..
+ node: op @ (BinOpKind::Add | BinOpKind::Sub),
+ ..
},
lhs,
rhs,
@@ -320,6 +320,16 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
{
let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
+ // Negate expr if original code has subtraction and expr is on the right side
+ let maybe_neg_sugg = |expr, hir_id| {
+ let sugg = Sugg::hir(cx, expr, "..");
+ if matches!(op, BinOpKind::Sub) && hir_id == rhs.hir_id {
+ format!("-{sugg}")
+ } else {
+ sugg.to_string()
+ }
+ };
+
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
@@ -329,8 +339,8 @@ fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args:
format!(
"{}.mul_add({}, {})",
Sugg::hir(cx, receiver, "..").maybe_par(),
- Sugg::hir(cx, receiver, ".."),
- Sugg::hir(cx, other_addend, ".."),
+ maybe_neg_sugg(receiver, expr.hir_id),
+ maybe_neg_sugg(other_addend, other_addend.hir_id),
),
Applicability::MachineApplicable,
);
@@ -444,7 +454,8 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'
fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Binary(
Spanned {
- node: BinOpKind::Add, ..
+ node: op @ (BinOpKind::Add | BinOpKind::Sub),
+ ..
},
lhs,
rhs,
@@ -458,10 +469,27 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
}
}
+ let maybe_neg_sugg = |expr| {
+ let sugg = Sugg::hir(cx, expr, "..");
+ if let BinOpKind::Sub = op {
+ format!("-{sugg}")
+ } else {
+ sugg.to_string()
+ }
+ };
+
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
- (inner_lhs, inner_rhs, rhs)
+ (
+ inner_lhs,
+ Sugg::hir(cx, inner_rhs, "..").to_string(),
+ maybe_neg_sugg(rhs),
+ )
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
- (inner_lhs, inner_rhs, lhs)
+ (
+ inner_lhs,
+ maybe_neg_sugg(inner_rhs),
+ Sugg::hir(cx, lhs, "..").to_string(),
+ )
} else {
return;
};
@@ -472,12 +500,7 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
expr.span,
"multiply and add expressions can be calculated more efficiently and accurately",
"consider using",
- format!(
- "{}.mul_add({}, {})",
- prepare_receiver_sugg(cx, recv),
- Sugg::hir(cx, arg1, ".."),
- Sugg::hir(cx, arg2, ".."),
- ),
+ format!("{}.mul_add({arg1}, {arg2})", prepare_receiver_sugg(cx, recv)),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/format.rs b/src/tools/clippy/clippy_lints/src/format.rs
index 0c5851cdb..bc0c68f53 100644
--- a/src/tools/clippy/clippy_lints/src/format.rs
+++ b/src/tools/clippy/clippy_lints/src/format.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
[_] => {
// Simulate macro expansion, converting {{ and }} to { and }.
let s_expand = format_args.format_string.snippet.replace("{{", "{").replace("}}", "}");
- let sugg = format!("{}.to_string()", s_expand);
+ let sugg = format!("{s_expand}.to_string()");
span_useless_format(cx, call_site, sugg, applicability);
},
[..] => {},
@@ -71,12 +71,12 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat {
let value = arg.param.value;
if_chain! {
if format_args.format_string.parts == [kw::Empty];
+ if arg.format.is_default();
if match cx.typeck_results().expr_ty(value).peel_refs().kind() {
ty::Adt(adt, _) => cx.tcx.is_diagnostic_item(sym::String, adt.did()),
ty::Str => true,
_ => false,
};
- if !arg.format.has_string_formatting();
then {
let is_new_string = match value.kind {
ExprKind::Binary(..) => true,
diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs
index 2a55c48cf..f0fe845d3 100644
--- a/src/tools/clippy/clippy_lints/src/format_args.rs
+++ b/src/tools/clippy/clippy_lints/src/format_args.rs
@@ -1,16 +1,22 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::is_diag_trait_item;
-use clippy_utils::macros::{is_format_macro, FormatArgsExpn};
+use clippy_utils::macros::FormatParamKind::{Implicit, Named, Numbered, Starred};
+use clippy_utils::macros::{
+ is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage,
+};
use clippy_utils::source::snippet_opt;
-use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_hir::{Expr, ExprKind, HirId, QPath};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::Ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::def_id::DefId;
+use rustc_span::edition::Edition::Edition2021;
use rustc_span::{sym, ExpnData, ExpnKind, Span, Symbol};
declare_clippy_lint! {
@@ -64,31 +70,256 @@ declare_clippy_lint! {
"`to_string` applied to a type that implements `Display` in format args"
}
-declare_lint_pass!(FormatArgs => [FORMAT_IN_FORMAT_ARGS, TO_STRING_IN_FORMAT_ARGS]);
+declare_clippy_lint! {
+ /// ### What it does
+ /// Detect when a variable is not inlined in a format string,
+ /// and suggests to inline it.
+ ///
+ /// ### Why is this bad?
+ /// Non-inlined code is slightly more difficult to read and understand,
+ /// as it requires arguments to be matched against the format string.
+ /// The inlined syntax, where allowed, is simpler.
+ ///
+ /// ### Example
+ /// ```rust
+ /// # let var = 42;
+ /// # let width = 1;
+ /// # let prec = 2;
+ /// format!("{}", var);
+ /// format!("{v:?}", v = var);
+ /// format!("{0} {0}", var);
+ /// format!("{0:1$}", var, width);
+ /// format!("{:.*}", prec, var);
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # let var = 42;
+ /// # let width = 1;
+ /// # let prec = 2;
+ /// format!("{var}");
+ /// format!("{var:?}");
+ /// format!("{var} {var}");
+ /// format!("{var:width$}");
+ /// format!("{var:.prec$}");
+ /// ```
+ ///
+ /// ### Known Problems
+ ///
+ /// There may be a false positive if the format string is expanded from certain proc macros:
+ ///
+ /// ```ignore
+ /// println!(indoc!("{}"), var);
+ /// ```
+ ///
+ /// If a format string contains a numbered argument that cannot be inlined
+ /// nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`.
+ #[clippy::version = "1.65.0"]
+ pub UNINLINED_FORMAT_ARGS,
+ pedantic,
+ "using non-inlined variables in `format!` calls"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Detects [formatting parameters] that have no effect on the output of
+ /// `format!()`, `println!()` or similar macros.
+ ///
+ /// ### Why is this bad?
+ /// Shorter format specifiers are easier to read, it may also indicate that
+ /// an expected formatting operation such as adding padding isn't happening.
+ ///
+ /// ### Example
+ /// ```rust
+ /// println!("{:.}", 1.0);
+ ///
+ /// println!("not padded: {:5}", format_args!("..."));
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// println!("{}", 1.0);
+ ///
+ /// println!("not padded: {}", format_args!("..."));
+ /// // OR
+ /// println!("padded: {:5}", format!("..."));
+ /// ```
+ ///
+ /// [formatting parameters]: https://doc.rust-lang.org/std/fmt/index.html#formatting-parameters
+ #[clippy::version = "1.66.0"]
+ pub UNUSED_FORMAT_SPECS,
+ complexity,
+ "use of a format specifier that has no effect"
+}
+
+impl_lint_pass!(FormatArgs => [
+ FORMAT_IN_FORMAT_ARGS,
+ TO_STRING_IN_FORMAT_ARGS,
+ UNINLINED_FORMAT_ARGS,
+ UNUSED_FORMAT_SPECS,
+]);
+
+pub struct FormatArgs {
+ msrv: Option<RustcVersion>,
+}
+
+impl FormatArgs {
+ #[must_use]
+ pub fn new(msrv: Option<RustcVersion>) -> Self {
+ Self { msrv }
+ }
+}
impl<'tcx> LateLintPass<'tcx> for FormatArgs {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
- if_chain! {
- if let Some(format_args) = FormatArgsExpn::parse(cx, expr);
- let expr_expn_data = expr.span.ctxt().outer_expn_data();
- let outermost_expn_data = outermost_expn_data(expr_expn_data);
- if let Some(macro_def_id) = outermost_expn_data.macro_def_id;
- if is_format_macro(cx, macro_def_id);
- if let ExpnKind::Macro(_, name) = outermost_expn_data.kind;
- then {
- for arg in &format_args.args {
- if arg.format.has_string_formatting() {
- continue;
- }
- if is_aliased(&format_args, arg.param.value.hir_id) {
- continue;
- }
- check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value);
- check_to_string_in_format_args(cx, name, arg.param.value);
+ if let Some(format_args) = FormatArgsExpn::parse(cx, expr)
+ && let expr_expn_data = expr.span.ctxt().outer_expn_data()
+ && let outermost_expn_data = outermost_expn_data(expr_expn_data)
+ && let Some(macro_def_id) = outermost_expn_data.macro_def_id
+ && is_format_macro(cx, macro_def_id)
+ && let ExpnKind::Macro(_, name) = outermost_expn_data.kind
+ {
+ for arg in &format_args.args {
+ check_unused_format_specifier(cx, arg);
+ if !arg.format.is_default() {
+ continue;
}
+ if is_aliased(&format_args, arg.param.value.hir_id) {
+ continue;
+ }
+ check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value);
+ check_to_string_in_format_args(cx, name, arg.param.value);
+ }
+ if meets_msrv(self.msrv, msrvs::FORMAT_ARGS_CAPTURE) {
+ check_uninlined_args(cx, &format_args, outermost_expn_data.call_site, macro_def_id);
}
}
}
+
+ extract_msrv_attr!(LateContext);
+}
+
+fn check_unused_format_specifier(cx: &LateContext<'_>, arg: &FormatArg<'_>) {
+ let param_ty = cx.typeck_results().expr_ty(arg.param.value).peel_refs();
+
+ if let Count::Implied(Some(mut span)) = arg.format.precision
+ && !span.is_empty()
+ {
+ span_lint_and_then(
+ cx,
+ UNUSED_FORMAT_SPECS,
+ span,
+ "empty precision specifier has no effect",
+ |diag| {
+ if param_ty.is_floating_point() {
+ diag.note("a precision specifier is not required to format floats");
+ }
+
+ if arg.format.is_default() {
+ // If there's no other specifiers remove the `:` too
+ span = arg.format_span();
+ }
+
+ diag.span_suggestion_verbose(span, "remove the `.`", "", Applicability::MachineApplicable);
+ },
+ );
+ }
+
+ if is_type_diagnostic_item(cx, param_ty, sym::Arguments) && !arg.format.is_default_for_trait() {
+ span_lint_and_then(
+ cx,
+ UNUSED_FORMAT_SPECS,
+ arg.span,
+ "format specifiers have no effect on `format_args!()`",
+ |diag| {
+ let mut suggest_format = |spec, span| {
+ let message = format!("for the {spec} to apply consider using `format!()`");
+
+ if let Some(mac_call) = root_macro_call(arg.param.value.span)
+ && cx.tcx.is_diagnostic_item(sym::format_args_macro, mac_call.def_id)
+ && arg.span.eq_ctxt(mac_call.span)
+ {
+ diag.span_suggestion(
+ cx.sess().source_map().span_until_char(mac_call.span, '!'),
+ message,
+ "format",
+ Applicability::MaybeIncorrect,
+ );
+ } else if let Some(span) = span {
+ diag.span_help(span, message);
+ }
+ };
+
+ if !arg.format.width.is_implied() {
+ suggest_format("width", arg.format.width.span());
+ }
+
+ if !arg.format.precision.is_implied() {
+ suggest_format("precision", arg.format.precision.span());
+ }
+
+ diag.span_suggestion_verbose(
+ arg.format_span(),
+ "if the current behavior is intentional, remove the format specifiers",
+ "",
+ Applicability::MaybeIncorrect,
+ );
+ },
+ );
+ }
+}
+
+fn check_uninlined_args(cx: &LateContext<'_>, args: &FormatArgsExpn<'_>, call_site: Span, def_id: DefId) {
+ if args.format_string.span.from_expansion() {
+ return;
+ }
+ if call_site.edition() < Edition2021 && is_panic(cx, def_id) {
+ // panic! before 2021 edition considers a single string argument as non-format
+ return;
+ }
+
+ let mut fixes = Vec::new();
+ // If any of the arguments are referenced by an index number,
+ // and that argument is not a simple variable and cannot be inlined,
+ // we cannot remove any other arguments in the format string,
+ // because the index numbers might be wrong after inlining.
+ // Example of an un-inlinable format: print!("{}{1}", foo, 2)
+ if !args.params().all(|p| check_one_arg(args, &p, &mut fixes)) || fixes.is_empty() {
+ return;
+ }
+
+ // Temporarily ignore multiline spans: https://github.com/rust-lang/rust/pull/102729#discussion_r988704308
+ if fixes.iter().any(|(span, _)| cx.sess().source_map().is_multiline(*span)) {
+ return;
+ }
+
+ span_lint_and_then(
+ cx,
+ UNINLINED_FORMAT_ARGS,
+ call_site,
+ "variables can be used directly in the `format!` string",
+ |diag| {
+ diag.multipart_suggestion("change this to", fixes, Applicability::MachineApplicable);
+ },
+ );
+}
+
+fn check_one_arg(args: &FormatArgsExpn<'_>, param: &FormatParam<'_>, fixes: &mut Vec<(Span, String)>) -> bool {
+ if matches!(param.kind, Implicit | Starred | Named(_) | Numbered)
+ && let ExprKind::Path(QPath::Resolved(None, path)) = param.value.kind
+ && let [segment] = path.segments
+ && let Some(arg_span) = args.value_with_prev_comma_span(param.value.hir_id)
+ {
+ let replacement = match param.usage {
+ FormatParamUsage::Argument => segment.ident.name.to_string(),
+ FormatParamUsage::Width => format!("{}$", segment.ident.name),
+ FormatParamUsage::Precision => format!(".{}$", segment.ident.name),
+ };
+ fixes.push((param.span, replacement));
+ fixes.push((arg_span, String::new()));
+ true // successful inlining, continue checking
+ } else {
+ // if we can't inline a numbered argument, we can't continue
+ param.kind != Numbered
+ }
}
fn outermost_expn_data(expn_data: ExpnData) -> ExpnData {
@@ -117,11 +348,10 @@ fn check_format_in_format_args(
cx,
FORMAT_IN_FORMAT_ARGS,
call_site,
- &format!("`format!` in `{}!` args", name),
+ &format!("`format!` in `{name}!` args"),
|diag| {
diag.help(&format!(
- "combine the `format!(..)` arguments with the outer `{}!(..)` call",
- name
+ "combine the `format!(..)` arguments with the outer `{name}!(..)` call"
));
diag.help("or consider changing `format!` to `format_args!`");
},
@@ -131,7 +361,7 @@ fn check_format_in_format_args(
fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Expr<'_>) {
if_chain! {
if !value.span.from_expansion();
- if let ExprKind::MethodCall(_, receiver, [], _) = value.kind;
+ if let ExprKind::MethodCall(_, receiver, [], to_string_span) = value.kind;
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id);
if is_diag_trait_item(cx, method_def_id, sym::ToString);
let receiver_ty = cx.typeck_results().expr_ty(receiver);
@@ -147,10 +377,9 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
span_lint_and_sugg(
cx,
TO_STRING_IN_FORMAT_ARGS,
- value.span.with_lo(receiver.span.hi()),
+ to_string_span.with_lo(receiver.span.hi()),
&format!(
- "`to_string` applied to a type that implements `Display` in `{}!` args",
- name
+ "`to_string` applied to a type that implements `Display` in `{name}!` args"
),
"remove this",
String::new(),
@@ -162,16 +391,13 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
TO_STRING_IN_FORMAT_ARGS,
value.span,
&format!(
- "`to_string` applied to a type that implements `Display` in `{}!` args",
- name
+ "`to_string` applied to a type that implements `Display` in `{name}!` args"
),
"use this",
format!(
- "{}{:*>width$}{}",
+ "{}{:*>n_needed_derefs$}{receiver_snippet}",
if needs_ref { "&" } else { "" },
- "",
- receiver_snippet,
- width = n_needed_derefs
+ ""
),
Applicability::MachineApplicable,
);
@@ -180,7 +406,7 @@ fn check_to_string_in_format_args(cx: &LateContext<'_>, name: Symbol, value: &Ex
}
}
-// Returns true if `hir_id` is referred to by multiple format params
+/// Returns true if `hir_id` is referred to by multiple format params
fn is_aliased(args: &FormatArgsExpn<'_>, hir_id: HirId) -> bool {
args.params().filter(|param| param.value.hir_id == hir_id).at_most_one().is_err()
}
diff --git a/src/tools/clippy/clippy_lints/src/format_impl.rs b/src/tools/clippy/clippy_lints/src/format_impl.rs
index b628fd9f7..ed1342a54 100644
--- a/src/tools/clippy/clippy_lints/src/format_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/format_impl.rs
@@ -214,12 +214,12 @@ fn check_print_in_format_impl(cx: &LateContext<'_>, expr: &Expr<'_>, impl_trait:
cx,
PRINT_IN_FORMAT_IMPL,
macro_call.span,
- &format!("use of `{}!` in `{}` impl", name, impl_trait.name),
+ &format!("use of `{name}!` in `{}` impl", impl_trait.name),
"replace with",
if let Some(formatter_name) = impl_trait.formatter_name {
- format!("{}!({}, ..)", replacement, formatter_name)
+ format!("{replacement}!({formatter_name}, ..)")
} else {
- format!("{}!(..)", replacement)
+ format!("{replacement}!(..)")
},
Applicability::HasPlaceholders,
);
diff --git a/src/tools/clippy/clippy_lints/src/formatting.rs b/src/tools/clippy/clippy_lints/src/formatting.rs
index 01cefe4af..a866a6898 100644
--- a/src/tools/clippy/clippy_lints/src/formatting.rs
+++ b/src/tools/clippy/clippy_lints/src/formatting.rs
@@ -154,11 +154,10 @@ fn check_assign(cx: &EarlyContext<'_>, expr: &Expr) {
eqop_span,
&format!(
"this looks like you are trying to use `.. {op}= ..`, but you \
- really are doing `.. = ({op} ..)`",
- op = op
+ really are doing `.. = ({op} ..)`"
),
None,
- &format!("to remove this lint, use either `{op}=` or `= {op}`", op = op),
+ &format!("to remove this lint, use either `{op}=` or `= {op}`"),
);
}
}
@@ -191,16 +190,12 @@ fn check_unop(cx: &EarlyContext<'_>, expr: &Expr) {
SUSPICIOUS_UNARY_OP_FORMATTING,
eqop_span,
&format!(
- "by not having a space between `{binop}` and `{unop}` it looks like \
- `{binop}{unop}` is a single operator",
- binop = binop_str,
- unop = unop_str
+ "by not having a space between `{binop_str}` and `{unop_str}` it looks like \
+ `{binop_str}{unop_str}` is a single operator"
),
None,
&format!(
- "put a space between `{binop}` and `{unop}` and remove the space after `{unop}`",
- binop = binop_str,
- unop = unop_str
+ "put a space between `{binop_str}` and `{unop_str}` and remove the space after `{unop_str}`"
),
);
}
@@ -246,12 +241,11 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) {
cx,
SUSPICIOUS_ELSE_FORMATTING,
else_span,
- &format!("this is an `else {}` but the formatting might hide it", else_desc),
+ &format!("this is an `else {else_desc}` but the formatting might hide it"),
None,
&format!(
"to remove this lint, remove the `else` or remove the new line between \
- `else` and `{}`",
- else_desc,
+ `else` and `{else_desc}`",
),
);
}
@@ -320,11 +314,10 @@ fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
cx,
SUSPICIOUS_ELSE_FORMATTING,
else_span,
- &format!("this looks like {} but the `else` is missing", looks_like),
+ &format!("this looks like {looks_like} but the `else` is missing"),
None,
&format!(
- "to remove this lint, add the missing `else` or add a new line before {}",
- next_thing,
+ "to remove this lint, add the missing `else` or add a new line before {next_thing}",
),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/from_over_into.rs b/src/tools/clippy/clippy_lints/src/from_over_into.rs
index 5d25c1d06..8b24a4962 100644
--- a/src/tools/clippy/clippy_lints/src/from_over_into.rs
+++ b/src/tools/clippy/clippy_lints/src/from_over_into.rs
@@ -1,11 +1,19 @@
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{meets_msrv, msrvs};
-use if_chain::if_chain;
-use rustc_hir as hir;
+use clippy_utils::diagnostics::span_lint_and_then;
+use clippy_utils::macros::span_is_local;
+use clippy_utils::source::snippet_opt;
+use clippy_utils::{meets_msrv, msrvs, path_def_id};
+use rustc_errors::Applicability;
+use rustc_hir::intravisit::{walk_path, Visitor};
+use rustc_hir::{
+ GenericArg, GenericArgs, HirId, Impl, ImplItemKind, ImplItemRef, Item, ItemKind, PatKind, Path, PathSegment, Ty,
+ TyKind,
+};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{kw, sym};
+use rustc_span::{Span, Symbol};
declare_clippy_lint! {
/// ### What it does
@@ -54,28 +62,152 @@ impl FromOverInto {
impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
impl<'tcx> LateLintPass<'tcx> for FromOverInto {
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
- if !meets_msrv(self.msrv, msrvs::RE_REBALANCING_COHERENCE) {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+ if !meets_msrv(self.msrv, msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) {
return;
}
- if_chain! {
- if let hir::ItemKind::Impl{ .. } = &item.kind;
- if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
- if cx.tcx.is_diagnostic_item(sym::Into, impl_trait_ref.def_id);
-
- then {
- span_lint_and_help(
- cx,
- FROM_OVER_INTO,
- cx.tcx.sess.source_map().guess_head_span(item.span),
- "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
- None,
- &format!("consider to implement `From<{}>` instead", impl_trait_ref.self_ty()),
- );
- }
+ if let ItemKind::Impl(Impl {
+ of_trait: Some(hir_trait_ref),
+ self_ty,
+ items: [impl_item_ref],
+ ..
+ }) = item.kind
+ && let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
+ // `impl Into<target_ty> for self_ty`
+ && let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
+ && let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
+ && cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)
+ {
+ span_lint_and_then(
+ cx,
+ FROM_OVER_INTO,
+ cx.tcx.sess.source_map().guess_head_span(item.span),
+ "an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true",
+ |diag| {
+ // If the target type is likely foreign mention the orphan rules as it's a common source of confusion
+ if path_def_id(cx, target_ty.peel_refs()).map_or(true, |id| !id.is_local()) {
+ diag.help(
+ "`impl From<Local> for Foreign` is allowed by the orphan rules, for more information see\n\
+ https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence"
+ );
+ }
+
+ let message = format!("replace the `Into` implentation with `From<{}>`", middle_trait_ref.self_ty());
+ if let Some(suggestions) = convert_to_from(cx, into_trait_seg, target_ty, self_ty, impl_item_ref) {
+ diag.multipart_suggestion(message, suggestions, Applicability::MachineApplicable);
+ } else {
+ diag.help(message);
+ }
+ },
+ );
}
}
extract_msrv_attr!(LateContext);
}
+
+/// Finds the occurences of `Self` and `self`
+struct SelfFinder<'a, 'tcx> {
+ cx: &'a LateContext<'tcx>,
+ /// Occurences of `Self`
+ upper: Vec<Span>,
+ /// Occurences of `self`
+ lower: Vec<Span>,
+ /// If any of the `self`/`Self` usages were from an expansion, or the body contained a binding
+ /// already named `val`
+ invalid: bool,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for SelfFinder<'a, 'tcx> {
+ type NestedFilter = OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+
+ fn visit_path(&mut self, path: &'tcx Path<'tcx>, _id: HirId) {
+ for segment in path.segments {
+ match segment.ident.name {
+ kw::SelfLower => self.lower.push(segment.ident.span),
+ kw::SelfUpper => self.upper.push(segment.ident.span),
+ _ => continue,
+ }
+ }
+
+ self.invalid |= path.span.from_expansion();
+ if !self.invalid {
+ walk_path(self, path);
+ }
+ }
+
+ fn visit_name(&mut self, name: Symbol) {
+ if name == sym::val {
+ self.invalid = true;
+ }
+ }
+}
+
+fn convert_to_from(
+ cx: &LateContext<'_>,
+ into_trait_seg: &PathSegment<'_>,
+ target_ty: &Ty<'_>,
+ self_ty: &Ty<'_>,
+ impl_item_ref: &ImplItemRef,
+) -> Option<Vec<(Span, String)>> {
+ let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id);
+ let ImplItemKind::Fn(ref sig, body_id) = impl_item.kind else { return None };
+ let body = cx.tcx.hir().body(body_id);
+ let [input] = body.params else { return None };
+ let PatKind::Binding(.., self_ident, None) = input.pat.kind else { return None };
+
+ let from = snippet_opt(cx, self_ty.span)?;
+ let into = snippet_opt(cx, target_ty.span)?;
+
+ let mut suggestions = vec![
+ // impl Into<T> for U -> impl From<T> for U
+ // ~~~~ ~~~~
+ (into_trait_seg.ident.span, String::from("From")),
+ // impl Into<T> for U -> impl Into<U> for U
+ // ~ ~
+ (target_ty.span, from.clone()),
+ // impl Into<T> for U -> impl Into<T> for T
+ // ~ ~
+ (self_ty.span, into),
+ // fn into(self) -> T -> fn from(self) -> T
+ // ~~~~ ~~~~
+ (impl_item.ident.span, String::from("from")),
+ // fn into([mut] self) -> T -> fn into([mut] v: T) -> T
+ // ~~~~ ~~~~
+ (self_ident.span, format!("val: {from}")),
+ // fn into(self) -> T -> fn into(self) -> Self
+ // ~ ~~~~
+ (sig.decl.output.span(), String::from("Self")),
+ ];
+
+ let mut finder = SelfFinder {
+ cx,
+ upper: Vec::new(),
+ lower: Vec::new(),
+ invalid: false,
+ };
+ finder.visit_expr(body.value);
+
+ if finder.invalid {
+ return None;
+ }
+
+ // don't try to replace e.g. `Self::default()` with `&[T]::default()`
+ if !finder.upper.is_empty() && !matches!(self_ty.kind, TyKind::Path(_)) {
+ return None;
+ }
+
+ for span in finder.upper {
+ suggestions.push((span, from.clone()));
+ }
+ for span in finder.lower {
+ suggestions.push((span, String::from("val")));
+ }
+
+ Some(suggestions)
+}
diff --git a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
index 74941d817..cf8b7acd6 100644
--- a/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
+++ b/src/tools/clippy/clippy_lints/src/from_str_radix_10.rs
@@ -1,4 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_integer_literal;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
@@ -60,8 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
if pathseg.ident.name.as_str() == "from_str_radix";
// check if the second argument is a primitive `10`
- if let ExprKind::Lit(lit) = &radix.kind;
- if let rustc_ast::ast::LitKind::Int(10, _) = lit.node;
+ if is_integer_literal(radix, 10);
then {
let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
exp.span,
"this call to `from_str_radix` can be replaced with a call to `str::parse`",
"try",
- format!("{}.parse::<{}>()", sugg, prim_ty.name_str()),
+ format!("{sugg}.parse::<{}>()", prim_ty.name_str()),
Applicability::MaybeIncorrect
);
}
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 00a493776..bff69f915 100644
--- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs
@@ -1,27 +1,30 @@
use rustc_ast::ast::Attribute;
use rustc_errors::Applicability;
use rustc_hir::def_id::{DefIdSet, LocalDefId};
-use rustc_hir::{self as hir, def::Res, intravisit, QPath};
+use rustc_hir::{self as hir, def::Res, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::{
lint::in_external_macro,
ty::{self, Ty},
};
-use rustc_span::{sym, Span};
+use rustc_span::{sym, Span, Symbol};
use clippy_utils::attrs::is_proc_macro;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_must_use_ty;
-use clippy_utils::{match_def_path, return_ty, trait_ref_of_method};
+use clippy_utils::visitors::for_each_expr;
+use clippy_utils::{return_ty, trait_ref_of_method};
+
+use core::ops::ControlFlow;
use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT};
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ let attr = cx.tcx.get_attr(item.owner_id.to_def_id(), sym::must_use);
if let hir::ItemKind::Fn(ref sig, _generics, ref body_id) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id);
+ 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);
@@ -31,7 +34,7 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this function could have a `#[must_use]` attribute",
);
@@ -41,19 +44,20 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id);
+ 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());
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ 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);
- } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.def_id).is_none() {
+ } else if is_public && !is_proc_macro(cx.sess(), attrs) && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
+ {
check_must_use_candidate(
cx,
sig.decl,
cx.tcx.hir().body(*body_id),
item.span,
- item.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
@@ -63,11 +67,11 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind {
- let is_public = cx.access_levels.is_exported(item.def_id);
+ 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());
let attrs = cx.tcx.hir().attrs(item.hir_id());
- let attr = cx.tcx.get_attr(item.def_id.to_def_id(), sym::must_use);
+ 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);
} else if let hir::TraitFn::Provided(eid) = *eid {
@@ -78,7 +82,7 @@ pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Tr
sig.decl,
body,
item.span,
- item.def_id,
+ item.owner_id.def_id,
item.span.with_hi(sig.decl.output.span().hi()),
"this method could have a `#[must_use]` attribute",
);
@@ -133,7 +137,7 @@ fn check_must_use_candidate<'tcx>(
|| mutates_static(cx, body)
|| in_external_macro(cx.sess(), item_span)
|| returns_unit(decl)
- || !cx.access_levels.is_exported(item_id)
+ || !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)))
{
return;
@@ -143,7 +147,7 @@ fn check_must_use_candidate<'tcx>(
diag.span_suggestion(
fn_span,
"add the attribute",
- format!("#[must_use] {}", snippet),
+ format!("#[must_use] {snippet}"),
Applicability::MachineApplicable,
);
}
@@ -171,21 +175,23 @@ fn is_mutable_pat(cx: &LateContext<'_>, pat: &hir::Pat<'_>, tys: &mut DefIdSet)
return false; // ignore `_` patterns
}
if cx.tcx.has_typeck_results(pat.hir_id.owner.to_def_id()) {
- is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner).pat_ty(pat), pat.span, tys)
+ is_mutable_ty(cx, cx.tcx.typeck(pat.hir_id.owner.def_id).pat_ty(pat), pat.span, tys)
} else {
false
}
}
-static KNOWN_WRAPPER_TYS: &[&[&str]] = &[&["alloc", "rc", "Rc"], &["std", "sync", "Arc"]];
+static KNOWN_WRAPPER_TYS: &[Symbol] = &[sym::Rc, sym::Arc];
fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &mut DefIdSet) -> bool {
match *ty.kind() {
// primitive types are never mutable
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str => false,
ty::Adt(adt, substs) => {
- tys.insert(adt.did()) && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
- || KNOWN_WRAPPER_TYS.iter().any(|path| match_def_path(cx, adt.did(), path))
+ tys.insert(adt.did()) && !ty.is_freeze(cx.tcx, cx.param_env)
+ || KNOWN_WRAPPER_TYS
+ .iter()
+ .any(|&sym| cx.tcx.is_diagnostic_item(sym, adt.did()))
&& substs.types().any(|ty| is_mutable_ty(cx, ty, span, tys))
},
ty::Tuple(substs) => substs.iter().any(|ty| is_mutable_ty(cx, ty, span, tys)),
@@ -199,79 +205,65 @@ fn is_mutable_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, tys: &m
}
}
-struct StaticMutVisitor<'a, 'tcx> {
- cx: &'a LateContext<'tcx>,
- mutates_static: bool,
+fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
+ use hir::ExprKind::{Field, Index, Path};
+
+ match e.kind {
+ Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
+ Path(_) => true,
+ Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
+ _ => false,
+ }
}
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for StaticMutVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
+ for_each_expr(body.value, |e| {
use hir::ExprKind::{AddrOf, Assign, AssignOp, Call, MethodCall};
- if self.mutates_static {
- return;
- }
- match expr.kind {
+ match e.kind {
Call(_, args) => {
let mut tys = DefIdSet::default();
for arg in args {
- if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+ if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
&& is_mutable_ty(
- self.cx,
- self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+ cx,
+ cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
arg.span,
&mut tys,
)
&& is_mutated_static(arg)
{
- self.mutates_static = true;
- return;
+ return ControlFlow::Break(());
}
tys.clear();
}
+ ControlFlow::Continue(())
},
MethodCall(_, receiver, args, _) => {
let mut tys = DefIdSet::default();
for arg in std::iter::once(receiver).chain(args.iter()) {
- if self.cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
+ if cx.tcx.has_typeck_results(arg.hir_id.owner.to_def_id())
&& is_mutable_ty(
- self.cx,
- self.cx.tcx.typeck(arg.hir_id.owner).expr_ty(arg),
+ cx,
+ cx.tcx.typeck(arg.hir_id.owner.def_id).expr_ty(arg),
arg.span,
&mut tys,
)
&& is_mutated_static(arg)
{
- self.mutates_static = true;
- return;
+ return ControlFlow::Break(());
}
tys.clear();
}
+ ControlFlow::Continue(())
},
- Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target) => {
- self.mutates_static |= is_mutated_static(target);
+ Assign(target, ..) | AssignOp(_, target, _) | AddrOf(_, hir::Mutability::Mut, target)
+ if is_mutated_static(target) =>
+ {
+ ControlFlow::Break(())
},
- _ => {},
+ _ => ControlFlow::Continue(()),
}
- }
-}
-
-fn is_mutated_static(e: &hir::Expr<'_>) -> bool {
- use hir::ExprKind::{Field, Index, Path};
-
- match e.kind {
- Path(QPath::Resolved(_, path)) => !matches!(path.res, Res::Local(_)),
- Path(_) => true,
- Field(inner, _) | Index(inner, _) => is_mutated_static(inner),
- _ => false,
- }
-}
-
-fn mutates_static<'tcx>(cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) -> bool {
- let mut v = StaticMutVisitor {
- cx,
- mutates_static: false,
- };
- intravisit::walk_expr(&mut v, body.value);
- v.mutates_static
+ })
+ .is_some()
}
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 3bbfa52e8..2c0bf551f 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
@@ -5,8 +5,11 @@ use rustc_span::def_id::LocalDefId;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::type_is_unsafe_function;
+use clippy_utils::visitors::for_each_expr_with_closures;
use clippy_utils::{iter_input_pats, path_to_local};
+use core::ops::ControlFlow;
+
use super::NOT_UNSAFE_PTR_ARG_DEREF;
pub(super) fn check_fn<'tcx>(
@@ -28,7 +31,7 @@ pub(super) fn check_fn<'tcx>(
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) {
if let hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(eid)) = item.kind {
let body = cx.tcx.hir().body(eid);
- check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.def_id);
+ check_raw_ptr(cx, sig.header.unsafety, sig.decl, body, item.owner_id.def_id);
}
}
@@ -39,21 +42,34 @@ fn check_raw_ptr<'tcx>(
body: &'tcx hir::Body<'tcx>,
def_id: LocalDefId,
) {
- let expr = &body.value;
- if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(def_id) {
+ if unsafety == hir::Unsafety::Normal && cx.effective_visibilities.is_exported(def_id) {
let raw_ptrs = iter_input_pats(decl, body)
.filter_map(|arg| raw_ptr_arg(cx, arg))
.collect::<HirIdSet>();
if !raw_ptrs.is_empty() {
- let typeck_results = cx.tcx.typeck_body(body.id());
- let mut v = DerefVisitor {
- cx,
- ptrs: raw_ptrs,
- typeck_results,
- };
-
- intravisit::walk_expr(&mut v, expr);
+ let typeck = cx.tcx.typeck_body(body.id());
+ let _: Option<!> = for_each_expr_with_closures(cx, body.value, |e| {
+ match e.kind {
+ hir::ExprKind::Call(f, args) if type_is_unsafe_function(cx, typeck.expr_ty(f)) => {
+ for arg in args {
+ check_arg(cx, &raw_ptrs, arg);
+ }
+ },
+ 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 {
+ check_arg(cx, &raw_ptrs, recv);
+ for arg in args {
+ check_arg(cx, &raw_ptrs, arg);
+ }
+ }
+ },
+ hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => check_arg(cx, &raw_ptrs, ptr),
+ _ => (),
+ }
+ ControlFlow::Continue(())
+ });
}
}
}
@@ -70,54 +86,13 @@ fn raw_ptr_arg(cx: &LateContext<'_>, arg: &hir::Param<'_>) -> Option<hir::HirId>
}
}
-struct DerefVisitor<'a, 'tcx> {
- cx: &'a LateContext<'tcx>,
- ptrs: HirIdSet,
- typeck_results: &'a ty::TypeckResults<'tcx>,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
- match expr.kind {
- hir::ExprKind::Call(f, args) => {
- let ty = self.typeck_results.expr_ty(f);
-
- if type_is_unsafe_function(self.cx, ty) {
- for arg in args {
- self.check_arg(arg);
- }
- }
- },
- hir::ExprKind::MethodCall(_, receiver, args, _) => {
- let def_id = self.typeck_results.type_dependent_def_id(expr.hir_id).unwrap();
- let base_type = self.cx.tcx.type_of(def_id);
-
- if type_is_unsafe_function(self.cx, base_type) {
- self.check_arg(receiver);
- for arg in args {
- self.check_arg(arg);
- }
- }
- },
- hir::ExprKind::Unary(hir::UnOp::Deref, ptr) => self.check_arg(ptr),
- _ => (),
- }
-
- intravisit::walk_expr(self, expr);
- }
-}
-
-impl<'a, 'tcx> DerefVisitor<'a, 'tcx> {
- fn check_arg(&self, ptr: &hir::Expr<'_>) {
- if let Some(id) = path_to_local(ptr) {
- if self.ptrs.contains(&id) {
- span_lint(
- self.cx,
- NOT_UNSAFE_PTR_ARG_DEREF,
- ptr.span,
- "this public function might dereference a raw pointer but is not marked `unsafe`",
- );
- }
- }
+fn check_arg(cx: &LateContext<'_>, raw_ptrs: &HirIdSet, arg: &hir::Expr<'_>) {
+ if path_to_local(arg).map_or(false, |id| raw_ptrs.contains(&id)) {
+ span_lint(
+ cx,
+ NOT_UNSAFE_PTR_ARG_DEREF,
+ arg.span,
+ "this public function might dereference a raw pointer but is not marked `unsafe`",
+ );
}
}
diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs
index 9591405cb..5c63fb2ac 100644
--- a/src/tools/clippy/clippy_lints/src/functions/result.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/result.rs
@@ -34,9 +34,9 @@ fn result_err_ty<'tcx>(
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) {
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind
- && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span)
+ && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
{
- if cx.access_levels.is_exported(item.def_id) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
check_result_unit_err(cx, err_ty, fn_header_span);
}
@@ -47,10 +47,10 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, l
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) {
// Don't lint if method is a trait's implementation, we can't do anything about those
if let hir::ImplItemKind::Fn(ref sig, _) = item.kind
- && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span)
- && trait_ref_of_method(cx, item.def_id).is_none()
+ && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
+ && trait_ref_of_method(cx, item.owner_id.def_id).is_none()
{
- if cx.access_levels.is_exported(item.def_id) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
check_result_unit_err(cx, err_ty, fn_header_span);
}
@@ -61,8 +61,8 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) {
if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
- if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.def_id, item.span) {
- if cx.access_levels.is_exported(item.def_id) {
+ if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) {
+ if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
check_result_unit_err(cx, err_ty, fn_header_span);
}
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
index 5c8d8b8e7..1e08922a6 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_arguments.rs
@@ -59,10 +59,7 @@ fn check_arg_number(cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, fn_span: Span,
cx,
TOO_MANY_ARGUMENTS,
fn_span,
- &format!(
- "this function has too many arguments ({}/{})",
- args, too_many_arguments_threshold
- ),
+ &format!("this function has too many arguments ({args}/{too_many_arguments_threshold})"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
index 54bdea7ea..bd473ac7e 100644
--- a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
@@ -22,9 +22,8 @@ pub(super) fn check_fn(
return;
}
- let code_snippet = match snippet_opt(cx, body.value.span) {
- Some(s) => s,
- _ => return,
+ let Some(code_snippet) = snippet_opt(cx, body.value.span) else {
+ return
};
let mut line_count: u64 = 0;
let mut in_comment = false;
@@ -78,10 +77,7 @@ pub(super) fn check_fn(
cx,
TOO_MANY_LINES,
span,
- &format!(
- "this function has too many lines ({}/{})",
- line_count, too_many_lines_threshold
- ),
+ &format!("this function has too many lines ({line_count}/{too_many_lines_threshold})"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs
index ef7d75aa8..0519f9ac2 100644
--- a/src/tools/clippy/clippy_lints/src/future_not_send.rs
+++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs
@@ -4,11 +4,10 @@ use rustc_hir::intravisit::FnKind;
use rustc_hir::{Body, FnDecl, HirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{EarlyBinder, Opaque, PredicateKind::Trait};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
-use rustc_trait_selection::traits::error_reporting::suggestions::InferCtxtExt;
+use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
use rustc_trait_selection::traits::{self, FulfillmentError};
declare_clippy_lint! {
@@ -78,10 +77,9 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
if is_future {
let send_trait = cx.tcx.get_diagnostic_item(sym::Send).unwrap();
let span = decl.output.span();
- let send_errors = cx.tcx.infer_ctxt().enter(|infcx| {
- let cause = traits::ObligationCause::misc(span, hir_id);
- traits::fully_solve_bound(&infcx, cause, cx.param_env, ret_ty, send_trait)
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ let cause = traits::ObligationCause::misc(span, hir_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(
cx,
@@ -89,18 +87,18 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
span,
"future cannot be sent between threads safely",
|db| {
- cx.tcx.infer_ctxt().enter(|infcx| {
- for FulfillmentError { obligation, .. } in send_errors {
- infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
- if let Trait(trait_pred) = obligation.predicate.kind().skip_binder() {
- db.note(&format!(
- "`{}` doesn't implement `{}`",
- trait_pred.self_ty(),
- trait_pred.trait_ref.print_only_trait_path(),
- ));
- }
+ for FulfillmentError { obligation, .. } in send_errors {
+ infcx
+ .err_ctxt()
+ .maybe_note_obligation_cause_for_async_await(db, &obligation);
+ if let Trait(trait_pred) = obligation.predicate.kind().skip_binder() {
+ db.note(&format!(
+ "`{}` doesn't implement `{}`",
+ trait_pred.self_ty(),
+ trait_pred.trait_ref.print_only_trait_path(),
+ ));
}
- });
+ }
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
index 11c432478..0d6718c16 100644
--- a/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
+++ b/src/tools/clippy/clippy_lints/src/if_then_some_else_none.rs
@@ -1,7 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::source::snippet_with_macro_callsite;
-use clippy_utils::{contains_return, higher, is_else_clause, is_lang_ctor, meets_msrv, msrvs, peel_blocks};
+use clippy_utils::{
+ contains_return, higher, is_else_clause, is_res_lang_ctor, meets_msrv, msrvs, path_res, peel_blocks,
+};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
@@ -76,15 +78,13 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& let ExprKind::Block(then_block, _) = then.kind
&& let Some(then_expr) = then_block.expr
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
- && let ExprKind::Path(ref then_call_qpath) = then_call.kind
- && is_lang_ctor(cx, then_call_qpath, OptionSome)
- && let ExprKind::Path(ref qpath) = peel_blocks(els).kind
- && is_lang_ctor(cx, qpath, OptionNone)
+ && is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
+ && is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
&& !stmts_contains_early_return(then_block.stmts)
{
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
let cond_snip = if matches!(cond.kind, ExprKind::Unary(_, _) | ExprKind::Binary(_, _, _)) {
- format!("({})", cond_snip)
+ format!("({cond_snip})")
} else {
cond_snip.into_owned()
};
@@ -92,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
let mut method_body = if then_block.stmts.is_empty() {
arg_snip.into_owned()
} else {
- format!("{{ /* snippet */ {} }}", arg_snip)
+ format!("{{ /* snippet */ {arg_snip} }}")
};
let method_name = if switch_to_eager_eval(cx, expr) && meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) {
"then_some"
@@ -102,14 +102,13 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
};
let help = format!(
- "consider using `bool::{}` like: `{}.{}({})`",
- method_name, cond_snip, method_name, method_body,
+ "consider using `bool::{method_name}` like: `{cond_snip}.{method_name}({method_body})`",
);
span_lint_and_help(
cx,
IF_THEN_SOME_ELSE_NONE,
expr.span,
- &format!("this could be simplified with `bool::{}`", method_name),
+ &format!("this could be simplified with `bool::{method_name}`"),
None,
&help,
);
diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
index 4f9680f60..94e06cf70 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs
@@ -5,6 +5,7 @@ use rustc_errors::Diagnostic;
use rustc_hir as hir;
use rustc_hir::intravisit::{walk_body, walk_expr, walk_inf, walk_ty, Visitor};
use rustc_hir::{Body, Expr, ExprKind, GenericArg, Item, ItemKind, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::in_external_macro;
@@ -12,7 +13,6 @@ use rustc_middle::ty::{Ty, TypeckResults};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
use if_chain::if_chain;
@@ -89,8 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
(
generics_suggestion_span,
format!(
- "<{}{}S: ::std::hash::BuildHasher{}>",
- generics_snip,
+ "<{generics_snip}{}S: ::std::hash::BuildHasher{}>",
if generics_snip.is_empty() { "" } else { ", " },
if vis.suggestions.is_empty() {
""
@@ -112,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher {
}
}
- if !cx.access_levels.is_exported(item.def_id) {
+ if !cx.effective_visibilities.is_exported(item.owner_id.def_id) {
return;
}
@@ -263,8 +262,8 @@ impl<'tcx> ImplicitHasherType<'tcx> {
fn type_arguments(&self) -> String {
match *self {
- ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{}, {}", k, v),
- ImplicitHasherType::HashSet(.., ref t) => format!("{}", t),
+ ImplicitHasherType::HashMap(.., ref k, ref v) => format!("{k}, {v}"),
+ ImplicitHasherType::HashSet(.., ref t) => format!("{t}"),
}
}
diff --git a/src/tools/clippy/clippy_lints/src/implicit_return.rs b/src/tools/clippy/clippy_lints/src/implicit_return.rs
index feec8ec2e..946d04eff 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_return.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_return.rs
@@ -2,10 +2,11 @@ use clippy_utils::{
diagnostics::span_lint_hir_and_then,
get_async_fn_body, is_async_fn,
source::{snippet_with_applicability, snippet_with_context, walk_span_to_context},
- visitors::expr_visitor_no_bodies,
+ visitors::for_each_expr,
};
+use core::ops::ControlFlow;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, HirId};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -53,7 +54,7 @@ fn lint_return(cx: &LateContext<'_>, emission_place: HirId, span: Span) {
span,
"missing `return` statement",
|diag| {
- diag.span_suggestion(span, "add `return` as shown", format!("return {}", snip), app);
+ diag.span_suggestion(span, "add `return` as shown", format!("return {snip}"), app);
},
);
}
@@ -71,7 +72,7 @@ fn lint_break(cx: &LateContext<'_>, emission_place: HirId, break_span: Span, exp
diag.span_suggestion(
break_span,
"change `break` to `return` as shown",
- format!("return {}", snip),
+ format!("return {snip}"),
app,
);
},
@@ -152,7 +153,7 @@ fn lint_implicit_returns(
ExprKind::Loop(block, ..) => {
let mut add_return = false;
- expr_visitor_no_bodies(|e| {
+ let _: Option<!> = for_each_expr(block, |e| {
if let ExprKind::Break(dest, sub_expr) = e.kind {
if dest.target_id.ok() == Some(expr.hir_id) {
if call_site_span.is_none() && e.span.ctxt() == ctxt {
@@ -167,9 +168,8 @@ fn lint_implicit_returns(
}
}
}
- true
- })
- .visit_block(block);
+ ControlFlow::Continue(())
+ });
if add_return {
#[expect(clippy::option_if_let_else)]
if let Some(span) = call_site_span {
diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
new file mode 100644
index 000000000..bf1351829
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs
@@ -0,0 +1,114 @@
+use clippy_utils::consts::{constant, Constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::get_parent_expr;
+use clippy_utils::source::snippet_with_applicability;
+use if_chain::if_chain;
+use rustc_ast::ast::{LitIntType, LitKind};
+use rustc_errors::Applicability;
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{Int, IntTy, Ty, Uint, UintTy};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for implicit saturating addition.
+ ///
+ /// ### Why is this bad?
+ /// The built-in function is more readable and may be faster.
+ ///
+ /// ### Example
+ /// ```rust
+ ///let mut u:u32 = 7000;
+ ///
+ /// if u != u32::MAX {
+ /// u += 1;
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ ///let mut u:u32 = 7000;
+ ///
+ /// u = u.saturating_add(1);
+ /// ```
+ #[clippy::version = "1.65.0"]
+ pub IMPLICIT_SATURATING_ADD,
+ style,
+ "Perform saturating addition instead of implicitly checking max bound of data type"
+}
+declare_lint_pass!(ImplicitSaturatingAdd => [IMPLICIT_SATURATING_ADD]);
+
+impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if_chain! {
+ if let ExprKind::If(cond, then, None) = expr.kind;
+ if let ExprKind::DropTemps(expr1) = cond.kind;
+ if let Some((c, op_node, l)) = get_const(cx, expr1);
+ if let BinOpKind::Ne | BinOpKind::Lt = op_node;
+ if let ExprKind::Block(block, None) = then.kind;
+ if let Block {
+ stmts:
+ [Stmt
+ { kind: StmtKind::Expr(ex) | StmtKind::Semi(ex), .. }],
+ expr: None, ..} |
+ Block { stmts: [], expr: Some(ex), ..} = block;
+ if let ExprKind::AssignOp(op1, target, value) = ex.kind;
+ let ty = cx.typeck_results().expr_ty(target);
+ if Some(c) == get_int_max(ty);
+ if clippy_utils::SpanlessEq::new(cx).eq_expr(l, target);
+ if BinOpKind::Add == op1.node;
+ if let ExprKind::Lit(ref lit) = value.kind;
+ if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node;
+ if block.expr.is_none();
+ then {
+ let mut app = Applicability::MachineApplicable;
+ let code = snippet_with_applicability(cx, target.span, "_", &mut app);
+ let sugg = if let Some(parent) = get_parent_expr(cx, expr) && let ExprKind::If(_cond, _then, Some(else_)) = parent.kind && else_.hir_id == expr.hir_id {format!("{{{code} = {code}.saturating_add(1); }}")} else {format!("{code} = {code}.saturating_add(1);")};
+ span_lint_and_sugg(cx, IMPLICIT_SATURATING_ADD, expr.span, "manual saturating add detected", "use instead", sugg, app);
+ }
+ }
+ }
+}
+
+fn get_int_max(ty: Ty<'_>) -> Option<u128> {
+ match ty.peel_refs().kind() {
+ Int(IntTy::I8) => i8::max_value().try_into().ok(),
+ Int(IntTy::I16) => i16::max_value().try_into().ok(),
+ Int(IntTy::I32) => i32::max_value().try_into().ok(),
+ Int(IntTy::I64) => i64::max_value().try_into().ok(),
+ Int(IntTy::I128) => i128::max_value().try_into().ok(),
+ Int(IntTy::Isize) => isize::max_value().try_into().ok(),
+ Uint(UintTy::U8) => u8::max_value().try_into().ok(),
+ Uint(UintTy::U16) => u16::max_value().try_into().ok(),
+ Uint(UintTy::U32) => u32::max_value().try_into().ok(),
+ Uint(UintTy::U64) => u64::max_value().try_into().ok(),
+ Uint(UintTy::U128) => Some(u128::max_value()),
+ Uint(UintTy::Usize) => usize::max_value().try_into().ok(),
+ _ => None,
+ }
+}
+
+fn get_const<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<(u128, BinOpKind, &'tcx Expr<'tcx>)> {
+ if let ExprKind::Binary(op, l, r) = expr.kind {
+ let tr = cx.typeck_results();
+ if let Some((Constant::Int(c), _)) = constant(cx, tr, r) {
+ return Some((c, op.node, l));
+ };
+ if let Some((Constant::Int(c), _)) = constant(cx, tr, l) {
+ return Some((c, invert_op(op.node)?, r));
+ }
+ }
+ None
+}
+
+fn invert_op(op: BinOpKind) -> Option<BinOpKind> {
+ use rustc_hir::BinOpKind::{Ge, Gt, Le, Lt, Ne};
+ match op {
+ Lt => Some(Gt),
+ Le => Some(Ge),
+ Ne => Some(Ne),
+ Ge => Some(Le),
+ Gt => Some(Lt),
+ _ => None,
+ }
+}
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 46654bc61..29d59c26d 100644
--- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
+++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{higher, peel_blocks_with_stmt, SpanlessEq};
+use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
@@ -35,7 +35,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.44.0"]
pub IMPLICIT_SATURATING_SUB,
- pedantic,
+ style,
"Perform saturating subtraction instead of implicitly checking lower bound of data type"
}
@@ -131,17 +131,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub {
fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
match peel_blocks_with_stmt(expr).kind {
ExprKind::AssignOp(ref op1, target, value) => {
- if_chain! {
- if BinOpKind::Sub == op1.node;
- // Check if literal being subtracted is one
- if let ExprKind::Lit(ref lit1) = value.kind;
- if let LitKind::Int(1, _) = lit1.node;
- then {
- Some(target)
- } else {
- None
- }
- }
+ // Check if literal being subtracted is one
+ (BinOpKind::Sub == op1.node && is_integer_literal(value, 1)).then_some(target)
},
ExprKind::Assign(target, value, _) => {
if_chain! {
@@ -150,8 +141,7 @@ fn subtracts_one<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<&'a Exp
if SpanlessEq::new(cx).eq_expr(left1, target);
- if let ExprKind::Lit(ref lit1) = right1.kind;
- if let LitKind::Int(1, _) = lit1.node;
+ if is_integer_literal(right1, 1);
then {
Some(target)
} else {
@@ -170,7 +160,7 @@ fn print_lint_and_sugg(cx: &LateContext<'_>, var_name: &str, expr: &Expr<'_>) {
expr.span,
"implicitly performing saturating subtraction",
"try",
- format!("{} = {}.saturating_sub({});", var_name, var_name, '1'),
+ format!("{var_name} = {var_name}.saturating_sub({});", '1'),
Applicability::MachineApplicable,
);
}
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 14b22d2b5..e2f2d3d42 100644
--- a/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
+++ b/src/tools/clippy/clippy_lints/src/inconsistent_struct_constructor.rs
@@ -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 _ = write!(fields_snippet, "{ident}, ");
}
fields_snippet.push_str(&last_ident.to_string());
@@ -100,10 +100,8 @@ impl<'tcx> LateLintPass<'tcx> for InconsistentStructConstructor {
String::new()
};
- let sugg = format!("{} {{ {}{} }}",
+ let sugg = format!("{} {{ {fields_snippet}{base_snippet} }}",
snippet(cx, qpath.span(), ".."),
- fields_snippet,
- base_snippet,
);
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
index 0dd7f5bf0..c7b5badaa 100644
--- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs
@@ -139,14 +139,14 @@ fn lint_slice(cx: &LateContext<'_>, slice: &SliceLintInformation) {
.map(|(index, _)| *index)
.collect::<FxHashSet<_>>();
- let value_name = |index| format!("{}_{}", slice.ident.name, index);
+ let value_name = |index| format!("{}_{index}", slice.ident.name);
if let Some(max_index) = used_indices.iter().max() {
let opt_ref = if slice.needs_ref { "ref " } else { "" };
let pat_sugg_idents = (0..=*max_index)
.map(|index| {
if used_indices.contains(&index) {
- format!("{}{}", opt_ref, value_name(index))
+ format!("{opt_ref}{}", value_name(index))
} else {
"_".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 4a375752e..af40a5a81 100644
--- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs
@@ -19,7 +19,6 @@ declare_clippy_lint! {
///
/// ### Example
/// ```rust,no_run
- /// # #![allow(const_err)]
/// let x = [1, 2, 3, 4];
///
/// x[9];
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 8c2c96fa1..d1d2db27c 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
+use clippy_utils::higher;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{higher, match_def_path, path_def_id, paths};
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -168,9 +168,16 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
},
ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
- ExprKind::Call(path, _) => path_def_id(cx, path)
- .map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
- .into(),
+ ExprKind::Call(path, _) => {
+ if let ExprKind::Path(ref qpath) = path.kind {
+ cx.qpath_res(qpath, path.hir_id)
+ .opt_def_id()
+ .map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
+ .into()
+ } else {
+ Finite
+ }
+ },
ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
_ => Finite,
}
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 17d867aac..14a37f535 100644
--- a/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/inherent_to_string.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
+use clippy_utils::{return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
if is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id()), sym::String);
// Filters instances of to_string which are required by a trait
- if trait_ref_of_method(cx, impl_item.def_id).is_none();
+ if trait_ref_of_method(cx, impl_item.owner_id.def_id).is_none();
then {
show_lint(cx, impl_item);
@@ -118,10 +118,13 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
}
fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
- let display_trait_id = get_trait_def_id(cx, &paths::DISPLAY_TRAIT).expect("Failed to get trait ID of `Display`!");
+ let display_trait_id = cx
+ .tcx
+ .get_diagnostic_item(sym::Display)
+ .expect("Failed to get trait ID of `Display`!");
// Get the real type of 'self'
- let self_type = cx.tcx.fn_sig(item.def_id).input(0);
+ let self_type = cx.tcx.fn_sig(item.owner_id).input(0);
let self_type = self_type.skip_binder().peel_refs();
// Emit either a warning or an error
@@ -131,23 +134,19 @@ fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
INHERENT_TO_STRING_SHADOW_DISPLAY,
item.span,
&format!(
- "type `{}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`",
- self_type
+ "type `{self_type}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`"
),
None,
- &format!("remove the inherent method from type `{}`", self_type),
+ &format!("remove the inherent method from type `{self_type}`"),
);
} else {
span_lint_and_help(
cx,
INHERENT_TO_STRING,
item.span,
- &format!(
- "implementation of inherent method `to_string(&self) -> String` for type `{}`",
- self_type
- ),
+ &format!("implementation of inherent method `to_string(&self) -> String` for type `{self_type}`"),
None,
- &format!("implement trait `Display` for type `{}` instead", self_type),
+ &format!("implement trait `Display` for type `{self_type}` instead"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
index dd7177e01..d609a5ca4 100644
--- a/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
+++ b/src/tools/clippy/clippy_lints/src/inline_fn_without_body.rs
@@ -51,7 +51,7 @@ fn check_attrs(cx: &LateContext<'_>, name: Symbol, attrs: &[Attribute]) {
cx,
INLINE_FN_WITHOUT_BODY,
attr.span,
- &format!("use of `#[inline]` on trait method `{}` which has no body", name),
+ &format!("use of `#[inline]` on trait method `{name}` which has no body"),
|diag| {
diag.suggest_remove_item(cx, attr.span, "remove", Applicability::MachineApplicable);
},
diff --git a/src/tools/clippy/clippy_lints/src/int_plus_one.rs b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
index 9a944def3..33491da3f 100644
--- a/src/tools/clippy/clippy_lints/src/int_plus_one.rs
+++ b/src/tools/clippy/clippy_lints/src/int_plus_one.rs
@@ -138,8 +138,8 @@ impl IntPlusOne {
if let Some(snippet) = snippet_opt(cx, node.span) {
if let Some(other_side_snippet) = snippet_opt(cx, other_side.span) {
let rec = match side {
- Side::Lhs => Some(format!("{} {} {}", snippet, binop_string, other_side_snippet)),
- Side::Rhs => Some(format!("{} {} {}", other_side_snippet, binop_string, snippet)),
+ Side::Lhs => Some(format!("{snippet} {binop_string} {other_side_snippet}")),
+ Side::Rhs => Some(format!("{other_side_snippet} {binop_string} {snippet}")),
};
return rec;
}
diff --git a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
index 36e03e50a..0ef77e03d 100644
--- a/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/invalid_upcast_comparisons.rs
@@ -145,9 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidUpcastComparisons {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Binary(ref cmp, lhs, rhs) = expr.kind {
let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
- let (rel, normalized_lhs, normalized_rhs) = if let Some(val) = normalized {
- val
- } else {
+ let Some((rel, normalized_lhs, normalized_rhs)) = normalized else {
return;
};
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 b56d87c53..e76de77f1 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
@@ -44,7 +44,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator {
let name = item.ident.name.as_str();
if matches!(name, "iter" | "iter_mut") {
if let TraitItemKind::Fn(fn_sig, _) = &item.kind {
- check_sig(cx, name, fn_sig, item.def_id);
+ check_sig(cx, name, fn_sig, item.owner_id.def_id);
}
}
}
@@ -58,7 +58,7 @@ impl<'tcx> LateLintPass<'tcx> for IterNotReturningIterator {
)
{
if let ImplItemKind::Fn(fn_sig, _) = &item.kind {
- check_sig(cx, name, fn_sig, item.def_id);
+ check_sig(cx, name, fn_sig, item.owner_id.def_id);
}
}
}
@@ -80,10 +80,7 @@ fn check_sig(cx: &LateContext<'_>, name: &str, sig: &FnSig<'_>, fn_id: LocalDefI
cx,
ITER_NOT_RETURNING_ITERATOR,
sig.span,
- &format!(
- "this method is named `{}` but its return type does not implement `Iterator`",
- name
- ),
+ &format!("this method is named `{name}` but its return type does not implement `Iterator`"),
);
}
}
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 984c5cd4e..76c83ab47 100644
--- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs
@@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_then;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{BytePos, Pos, Span};
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
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 eb13d0869..06e957285 100644
--- a/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
+++ b/src/tools/clippy/clippy_lints/src/large_enum_variant.rs
@@ -123,10 +123,9 @@ impl<'tcx> LateLintPass<'tcx> for LargeEnumVariant {
return;
}
if let ItemKind::Enum(ref def, _) = item.kind {
- let ty = cx.tcx.type_of(item.def_id);
- let (adt, subst) = match ty.kind() {
- Adt(adt, subst) => (adt, subst),
- _ => panic!("already checked whether this is an enum"),
+ let ty = cx.tcx.type_of(item.owner_id);
+ let Adt(adt, subst) = ty.kind() else {
+ panic!("already checked whether this is an enum")
};
if adt.variants().len() <= 1 {
return;
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 0acbd81ae..5857d81ab 100644
--- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
+++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::source::snippet;
-use if_chain::if_chain;
-use rustc_hir::{Expr, ExprKind};
+use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, ConstKind};
@@ -39,29 +38,28 @@ impl_lint_pass!(LargeStackArrays => [LARGE_STACK_ARRAYS]);
impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
- if_chain! {
- if let ExprKind::Repeat(_, _) = expr.kind;
- if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).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_size) = cx.layout_of(*element_type).map(|l| l.size.bytes());
- if self.maximum_allowed_size < element_count * element_size;
- then {
- span_lint_and_help(
- cx,
- LARGE_STACK_ARRAYS,
- expr.span,
- &format!(
- "allocating a local array larger than {} bytes",
- self.maximum_allowed_size
- ),
- None,
- &format!(
- "consider allocating on the heap with `vec!{}.into_boxed_slice()`",
- snippet(cx, expr.span, "[...]")
- ),
- );
- }
- }
+ 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_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(..), .. })))
+ && self.maximum_allowed_size < element_count * element_size {
+ span_lint_and_help(
+ cx,
+ LARGE_STACK_ARRAYS,
+ expr.span,
+ &format!(
+ "allocating a local array larger than {} bytes",
+ self.maximum_allowed_size
+ ),
+ None,
+ &format!(
+ "consider allocating on the heap with `vec!{}.into_boxed_slice()`",
+ snippet(cx, expr.span, "[...]")
+ ),
+ );
+ }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 7ae8ef830..b0cba40c2 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -134,7 +134,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 cx.access_levels.is_exported(item.def_id);
+ 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());
if imp.of_trait.is_none();
@@ -143,7 +143,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.def_id).skip_binder());
+ if let Some(output) = parse_len_output(cx, cx.tcx.fn_sig(item.owner_id).skip_binder());
then {
let (name, kind) = match cx.tcx.hir().find(ty_hir_id) {
Some(Node::ForeignItem(x)) => (x.ident.name, "extern type"),
@@ -195,7 +195,7 @@ 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.def_id).inputs().skip_binder().len() == 1 }
+ has_self && { cx.tcx.fn_sig(item.id.owner_id).inputs().skip_binder().len() == 1 }
} else {
false
}
@@ -210,10 +210,11 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
}
}
- if cx.access_levels.is_exported(visited_trait.def_id) && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
+ if cx.effective_visibilities.is_exported(visited_trait.owner_id.def_id)
+ && trait_items.iter().any(|i| is_named_self(cx, i, sym::len))
{
let mut current_and_super_traits = DefIdSet::default();
- fill_trait_set(visited_trait.def_id.to_def_id(), &mut current_and_super_traits, cx);
+ fill_trait_set(visited_trait.owner_id.to_def_id(), &mut current_and_super_traits, cx);
let is_empty = sym!(is_empty);
let is_empty_method_found = current_and_super_traits
@@ -278,15 +279,13 @@ impl<'tcx> LenOutput<'tcx> {
_ => "",
};
match self {
- Self::Integral => format!("expected signature: `({}self) -> bool`", self_ref),
- Self::Option(_) => format!(
- "expected signature: `({}self) -> bool` or `({}self) -> Option<bool>",
- self_ref, self_ref
- ),
- Self::Result(..) => format!(
- "expected signature: `({}self) -> bool` or `({}self) -> Result<bool>",
- self_ref, self_ref
- ),
+ Self::Integral => format!("expected signature: `({self_ref}self) -> bool`"),
+ Self::Option(_) => {
+ format!("expected signature: `({self_ref}self) -> bool` or `({self_ref}self) -> Option<bool>")
+ },
+ Self::Result(..) => {
+ format!("expected signature: `({self_ref}self) -> bool` or `({self_ref}self) -> Result<bool>")
+ },
}
}
}
@@ -326,17 +325,15 @@ fn check_for_is_empty<'tcx>(
let (msg, is_empty_span, self_kind) = match is_empty {
None => (
format!(
- "{} `{}` has a public `len` method, but no `is_empty` method",
- item_kind,
+ "{item_kind} `{}` has a public `len` method, but no `is_empty` method",
item_name.as_str(),
),
None,
None,
),
- Some(is_empty) if !cx.access_levels.is_exported(is_empty.def_id.expect_local()) => (
+ Some(is_empty) if !cx.effective_visibilities.is_exported(is_empty.def_id.expect_local()) => (
format!(
- "{} `{}` has a public `len` method, but a private `is_empty` method",
- item_kind,
+ "{item_kind} `{}` has a public `len` method, but a private `is_empty` method",
item_name.as_str(),
),
Some(cx.tcx.def_span(is_empty.def_id)),
@@ -348,8 +345,7 @@ fn check_for_is_empty<'tcx>(
{
(
format!(
- "{} `{}` has a public `len` method, but the `is_empty` method has an unexpected signature",
- item_kind,
+ "{item_kind} `{}` has a public `len` method, but the `is_empty` method has an unexpected signature",
item_name.as_str(),
),
Some(cx.tcx.def_span(is_empty.def_id)),
@@ -419,10 +415,9 @@ fn check_len(
LEN_ZERO,
span,
&format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }),
- &format!("using `{}is_empty` is clearer and more explicit", op),
+ &format!("using `{op}is_empty` is clearer and more explicit"),
format!(
- "{}{}.is_empty()",
- op,
+ "{op}{}.is_empty()",
snippet_with_applicability(cx, receiver.span, "_", &mut applicability)
),
applicability,
@@ -439,10 +434,9 @@ fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Ex
COMPARISON_TO_EMPTY,
span,
"comparison to empty slice",
- &format!("using `{}is_empty` is clearer and more explicit", op),
+ &format!("using `{op}is_empty` is clearer and more explicit"),
format!(
- "{}{}.is_empty()",
- op,
+ "{op}{}.is_empty()",
snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
),
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
index 10fc0f401..db41bc67d 100644
--- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs
+++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
let span = stmt.span.to(if_.span);
let has_interior_mutability = !cx.typeck_results().node_type(canonical_id).is_freeze(
- cx.tcx.at(span),
+ cx.tcx,
cx.param_env,
);
if has_interior_mutability { return; }
@@ -106,8 +106,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq {
// use mutably after the `if`
let sug = format!(
- "let {mut}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
- mut=mutability,
+ "let {mutability}{name} = if {cond} {{{then} {value} }} else {{{else} {default} }};",
name=ident.name,
cond=snippet(cx, cond.span, "_"),
then=if then.stmts.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 176787497..b7798b1c1 100644
--- a/src/tools/clippy/clippy_lints/src/let_underscore.rs
+++ b/src/tools/clippy/clippy_lints/src/let_underscore.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::{is_must_use_ty, match_type};
+use clippy_utils::ty::{is_must_use_ty, is_type_diagnostic_item, match_type};
use clippy_utils::{is_must_use_func_call, paths};
use if_chain::if_chain;
use rustc_hir::{Local, PatKind};
@@ -7,6 +7,7 @@ use rustc_lint::{LateContext, LateLintPass};
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::{sym, Symbol};
declare_clippy_lint! {
/// ### What it does
@@ -99,10 +100,9 @@ declare_clippy_lint! {
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_DROP]);
-const SYNC_GUARD_PATHS: [&[&str]; 6] = [
- &paths::MUTEX_GUARD,
- &paths::RWLOCK_READ_GUARD,
- &paths::RWLOCK_WRITE_GUARD,
+const SYNC_GUARD_SYMS: [Symbol; 3] = [sym::MutexGuard, sym::RwLockReadGuard, sym::RwLockWriteGuard];
+
+const SYNC_GUARD_PATHS: [&[&str]; 3] = [
&paths::PARKING_LOT_MUTEX_GUARD,
&paths::PARKING_LOT_RWLOCK_READ_GUARD,
&paths::PARKING_LOT_RWLOCK_WRITE_GUARD,
@@ -121,7 +121,10 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
let init_ty = cx.typeck_results().expr_ty(init);
let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => {
- SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
+ SYNC_GUARD_SYMS
+ .iter()
+ .any(|&sym| is_type_diagnostic_item(cx, inner_ty, sym))
+ || SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
},
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
@@ -134,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
"non-binding let on a synchronization lock",
None,
"consider using an underscore-prefixed named \
- binding or dropping explicitly with `std::mem::drop`"
+ binding or dropping explicitly with `std::mem::drop`",
);
} else if init_ty.needs_drop(cx.tcx, cx.param_env) {
span_lint_and_help(
@@ -144,7 +147,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
"non-binding `let` on a type that implements `Drop`",
None,
"consider using an underscore-prefixed named \
- binding or dropping explicitly with `std::mem::drop`"
+ binding or dropping explicitly with `std::mem::drop`",
);
} else if is_must_use_ty(cx, cx.typeck_results().expr_ty(init)) {
span_lint_and_help(
@@ -153,7 +156,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
local.span,
"non-binding let on an expression with `#[must_use]` type",
None,
- "consider explicitly using expression value"
+ "consider explicitly using expression value",
);
} else if is_must_use_func_call(cx, init) {
span_lint_and_help(
@@ -162,7 +165,7 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
local.span,
"non-binding let on a result of a `#[must_use]` function",
None,
- "consider explicitly using function result"
+ "consider explicitly using function result",
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_all.rs b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
index 751409602..c455e1561 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_all.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_all.rs
@@ -21,9 +21,11 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(booleans::NONMINIMAL_BOOL),
LintId::of(booleans::OVERLY_COMPLEX_BOOL_EXPR),
LintId::of(borrow_deref_ref::BORROW_DEREF_REF),
+ LintId::of(box_default::BOX_DEFAULT),
LintId::of(casts::CAST_ABS_TO_UNSIGNED),
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
LintId::of(casts::CAST_ENUM_TRUNCATION),
+ LintId::of(casts::CAST_NAN_TO_INT),
LintId::of(casts::CAST_REF_TO_MUT),
LintId::of(casts::CAST_SLICE_DIFFERENT_SIZES),
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
@@ -44,7 +46,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(derivable_impls::DERIVABLE_IMPLS),
LintId::of(derive::DERIVE_HASH_XOR_EQ),
LintId::of(derive::DERIVE_ORD_XOR_PARTIAL_ORD),
- LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
+ LintId::of(disallowed_macros::DISALLOWED_MACROS),
LintId::of(disallowed_methods::DISALLOWED_METHODS),
LintId::of(disallowed_names::DISALLOWED_NAMES),
LintId::of(disallowed_types::DISALLOWED_TYPES),
@@ -70,6 +72,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(format::USELESS_FORMAT),
LintId::of(format_args::FORMAT_IN_FORMAT_ARGS),
LintId::of(format_args::TO_STRING_IN_FORMAT_ARGS),
+ LintId::of(format_args::UNUSED_FORMAT_SPECS),
LintId::of(format_impl::PRINT_IN_FORMAT_IMPL),
LintId::of(format_impl::RECURSIVE_FORMAT_IMPL),
LintId::of(formatting::POSSIBLE_MISSING_COMMA),
@@ -85,6 +88,8 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(functions::RESULT_UNIT_ERR),
LintId::of(functions::TOO_MANY_ARGUMENTS),
LintId::of(if_let_mutex::IF_LET_MUTEX),
+ LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
+ LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
LintId::of(infinite_iter::INFINITE_ITER),
LintId::of(inherent_to_string::INHERENT_TO_STRING),
@@ -107,7 +112,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(loops::EMPTY_LOOP),
LintId::of(loops::EXPLICIT_COUNTER_LOOP),
LintId::of(loops::FOR_KV_MAP),
- LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
LintId::of(loops::ITER_NEXT_LOOP),
LintId::of(loops::MANUAL_FIND),
LintId::of(loops::MANUAL_FLATTEN),
@@ -125,6 +129,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(main_recursion::MAIN_RECURSION),
LintId::of(manual_async_fn::MANUAL_ASYNC_FN),
LintId::of(manual_bits::MANUAL_BITS),
+ LintId::of(manual_clamp::MANUAL_CLAMP),
LintId::of(manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE),
LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
LintId::of(manual_retain::MANUAL_RETAIN),
@@ -134,6 +139,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(match_result_ok::MATCH_RESULT_OK),
LintId::of(matches::COLLAPSIBLE_MATCH),
LintId::of(matches::INFALLIBLE_DESTRUCTURING_MATCH),
+ LintId::of(matches::MANUAL_FILTER),
LintId::of(matches::MANUAL_MAP),
LintId::of(matches::MANUAL_UNWRAP_OR),
LintId::of(matches::MATCH_AS_REF),
@@ -171,6 +177,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(methods::ITERATOR_STEP_BY_ZERO),
LintId::of(methods::ITER_CLONED_COLLECT),
LintId::of(methods::ITER_COUNT),
+ LintId::of(methods::ITER_KV_MAP),
LintId::of(methods::ITER_NEXT_SLICE),
LintId::of(methods::ITER_NTH),
LintId::of(methods::ITER_NTH_ZERO),
@@ -289,6 +296,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(ranges::MANUAL_RANGE_CONTAINS),
LintId::of(ranges::REVERSED_EMPTY_RANGES),
LintId::of(rc_clone_in_vec_init::RC_CLONE_IN_VEC_INIT),
+ LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC),
LintId::of(redundant_clone::REDUNDANT_CLONE),
LintId::of(redundant_closure_call::REDUNDANT_CLOSURE_CALL),
LintId::of(redundant_field_names::REDUNDANT_FIELD_NAMES),
@@ -350,7 +358,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
LintId::of(useless_conversion::USELESS_CONVERSION),
LintId::of(vec::USELESS_VEC),
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
- LintId::of(write::POSITIONAL_NAMED_FORMAT_PARAMETERS),
LintId::of(write::PRINTLN_EMPTY_STRING),
LintId::of(write::PRINT_LITERAL),
LintId::of(write::PRINT_WITH_NEWLINE),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
index aa247352f..8be9dc4ba 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_complexity.rs
@@ -13,6 +13,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
LintId::of(double_parens::DOUBLE_PARENS),
LintId::of(explicit_write::EXPLICIT_WRITE),
LintId::of(format::USELESS_FORMAT),
+ LintId::of(format_args::UNUSED_FORMAT_SPECS),
LintId::of(functions::TOO_MANY_ARGUMENTS),
LintId::of(int_plus_one::INT_PLUS_ONE),
LintId::of(lifetimes::EXTRA_UNUSED_LIFETIMES),
@@ -22,10 +23,12 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
LintId::of(loops::MANUAL_FLATTEN),
LintId::of(loops::SINGLE_ELEMENT_LOOP),
LintId::of(loops::WHILE_LET_LOOP),
+ LintId::of(manual_clamp::MANUAL_CLAMP),
LintId::of(manual_rem_euclid::MANUAL_REM_EUCLID),
LintId::of(manual_strip::MANUAL_STRIP),
LintId::of(map_unit_fn::OPTION_MAP_UNIT_FN),
LintId::of(map_unit_fn::RESULT_MAP_UNIT_FN),
+ LintId::of(matches::MANUAL_FILTER),
LintId::of(matches::MANUAL_UNWRAP_OR),
LintId::of(matches::MATCH_AS_REF),
LintId::of(matches::MATCH_SINGLE_BINDING),
@@ -40,6 +43,7 @@ store.register_group(true, "clippy::complexity", Some("clippy_complexity"), vec!
LintId::of(methods::GET_LAST_WITH_LEN),
LintId::of(methods::INSPECT_FOR_EACH),
LintId::of(methods::ITER_COUNT),
+ LintId::of(methods::ITER_KV_MAP),
LintId::of(methods::MANUAL_FILTER_MAP),
LintId::of(methods::MANUAL_FIND_MAP),
LintId::of(methods::MANUAL_SPLIT_ONCE),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
index ecec5cf57..bb94037ec 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_correctness.rs
@@ -59,6 +59,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
LintId::of(ptr::INVALID_NULL_PTR_USAGE),
LintId::of(ptr::MUT_FROM_REF),
LintId::of(ranges::REVERSED_EMPTY_RANGES),
+ LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC),
LintId::of(regex::INVALID_REGEX),
LintId::of(serde_api::SERDE_API_MISUSE),
LintId::of(size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
index be63646a1..40c94c6e8 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_internal.rs
@@ -3,20 +3,20 @@
// Manual edits will be overwritten.
store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
- LintId::of(utils::internal_lints::CLIPPY_LINTS_INTERNAL),
- LintId::of(utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
- LintId::of(utils::internal_lints::COMPILER_LINT_FUNCTIONS),
- LintId::of(utils::internal_lints::DEFAULT_DEPRECATION_REASON),
- LintId::of(utils::internal_lints::DEFAULT_LINT),
- LintId::of(utils::internal_lints::IF_CHAIN_STYLE),
- LintId::of(utils::internal_lints::INTERNING_DEFINED_SYMBOL),
- LintId::of(utils::internal_lints::INVALID_CLIPPY_VERSION_ATTRIBUTE),
- LintId::of(utils::internal_lints::INVALID_PATHS),
- LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS),
- LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
- LintId::of(utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE),
- LintId::of(utils::internal_lints::MISSING_MSRV_ATTR_IMPL),
- LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA),
- LintId::of(utils::internal_lints::PRODUCE_ICE),
- LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR),
+ LintId::of(utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL),
+ LintId::of(utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS),
+ LintId::of(utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS),
+ LintId::of(utils::internal_lints::if_chain_style::IF_CHAIN_STYLE),
+ LintId::of(utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL),
+ LintId::of(utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR),
+ LintId::of(utils::internal_lints::invalid_paths::INVALID_PATHS),
+ LintId::of(utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON),
+ LintId::of(utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT),
+ LintId::of(utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE),
+ LintId::of(utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS),
+ LintId::of(utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE),
+ LintId::of(utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL),
+ LintId::of(utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA),
+ LintId::of(utils::internal_lints::produce_ice::PRODUCE_ICE),
+ LintId::of(utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH),
])
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
index 962e67220..800e3a876 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_lints.rs
@@ -4,37 +4,37 @@
store.register_lints(&[
#[cfg(feature = "internal")]
- utils::internal_lints::CLIPPY_LINTS_INTERNAL,
+ utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL,
#[cfg(feature = "internal")]
- utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
+ utils::internal_lints::collapsible_calls::COLLAPSIBLE_SPAN_LINT_CALLS,
#[cfg(feature = "internal")]
- utils::internal_lints::COMPILER_LINT_FUNCTIONS,
+ utils::internal_lints::compiler_lint_functions::COMPILER_LINT_FUNCTIONS,
#[cfg(feature = "internal")]
- utils::internal_lints::DEFAULT_DEPRECATION_REASON,
+ utils::internal_lints::if_chain_style::IF_CHAIN_STYLE,
#[cfg(feature = "internal")]
- utils::internal_lints::DEFAULT_LINT,
+ utils::internal_lints::interning_defined_symbol::INTERNING_DEFINED_SYMBOL,
#[cfg(feature = "internal")]
- utils::internal_lints::IF_CHAIN_STYLE,
+ utils::internal_lints::interning_defined_symbol::UNNECESSARY_SYMBOL_STR,
#[cfg(feature = "internal")]
- utils::internal_lints::INTERNING_DEFINED_SYMBOL,
+ utils::internal_lints::invalid_paths::INVALID_PATHS,
#[cfg(feature = "internal")]
- utils::internal_lints::INVALID_CLIPPY_VERSION_ATTRIBUTE,
+ utils::internal_lints::lint_without_lint_pass::DEFAULT_DEPRECATION_REASON,
#[cfg(feature = "internal")]
- utils::internal_lints::INVALID_PATHS,
+ utils::internal_lints::lint_without_lint_pass::DEFAULT_LINT,
#[cfg(feature = "internal")]
- utils::internal_lints::LINT_WITHOUT_LINT_PASS,
+ utils::internal_lints::lint_without_lint_pass::INVALID_CLIPPY_VERSION_ATTRIBUTE,
#[cfg(feature = "internal")]
- utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
+ utils::internal_lints::lint_without_lint_pass::LINT_WITHOUT_LINT_PASS,
#[cfg(feature = "internal")]
- utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE,
+ utils::internal_lints::lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE,
#[cfg(feature = "internal")]
- utils::internal_lints::MISSING_MSRV_ATTR_IMPL,
+ utils::internal_lints::msrv_attr_impl::MISSING_MSRV_ATTR_IMPL,
#[cfg(feature = "internal")]
- utils::internal_lints::OUTER_EXPN_EXPN_DATA,
+ utils::internal_lints::outer_expn_data_pass::OUTER_EXPN_EXPN_DATA,
#[cfg(feature = "internal")]
- utils::internal_lints::PRODUCE_ICE,
+ utils::internal_lints::produce_ice::PRODUCE_ICE,
#[cfg(feature = "internal")]
- utils::internal_lints::UNNECESSARY_SYMBOL_STR,
+ utils::internal_lints::unnecessary_def_path::UNNECESSARY_DEF_PATH,
almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE,
approx_const::APPROX_CONSTANT,
as_conversions::AS_CONVERSIONS,
@@ -60,17 +60,20 @@ store.register_lints(&[
booleans::NONMINIMAL_BOOL,
booleans::OVERLY_COMPLEX_BOOL_EXPR,
borrow_deref_ref::BORROW_DEREF_REF,
+ box_default::BOX_DEFAULT,
cargo::CARGO_COMMON_METADATA,
cargo::MULTIPLE_CRATE_VERSIONS,
cargo::NEGATIVE_FEATURE_NAMES,
cargo::REDUNDANT_FEATURE_NAMES,
cargo::WILDCARD_DEPENDENCIES,
+ casts::AS_PTR_CAST_MUT,
casts::AS_UNDERSCORE,
casts::BORROW_AS_PTR,
casts::CAST_ABS_TO_UNSIGNED,
casts::CAST_ENUM_CONSTRUCTOR,
casts::CAST_ENUM_TRUNCATION,
casts::CAST_LOSSLESS,
+ casts::CAST_NAN_TO_INT,
casts::CAST_POSSIBLE_TRUNCATION,
casts::CAST_POSSIBLE_WRAP,
casts::CAST_PRECISION_LOSS,
@@ -113,16 +116,17 @@ store.register_lints(&[
derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ,
derive::EXPL_IMPL_CLONE_ON_COPY,
derive::UNSAFE_DERIVE_DESERIALIZE,
+ disallowed_macros::DISALLOWED_MACROS,
disallowed_methods::DISALLOWED_METHODS,
disallowed_names::DISALLOWED_NAMES,
disallowed_script_idents::DISALLOWED_SCRIPT_IDENTS,
disallowed_types::DISALLOWED_TYPES,
+ doc::DOC_LINK_WITH_QUOTES,
doc::DOC_MARKDOWN,
doc::MISSING_ERRORS_DOC,
doc::MISSING_PANICS_DOC,
doc::MISSING_SAFETY_DOC,
doc::NEEDLESS_DOCTEST_MAIN,
- doc_link_with_quotes::DOC_LINK_WITH_QUOTES,
double_parens::DOUBLE_PARENS,
drop_forget_ref::DROP_COPY,
drop_forget_ref::DROP_NON_DROP,
@@ -159,6 +163,8 @@ store.register_lints(&[
format::USELESS_FORMAT,
format_args::FORMAT_IN_FORMAT_ARGS,
format_args::TO_STRING_IN_FORMAT_ARGS,
+ format_args::UNINLINED_FORMAT_ARGS,
+ format_args::UNUSED_FORMAT_SPECS,
format_impl::PRINT_IN_FORMAT_IMPL,
format_impl::RECURSIVE_FORMAT_IMPL,
format_push_string::FORMAT_PUSH_STRING,
@@ -182,6 +188,7 @@ store.register_lints(&[
if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
implicit_hasher::IMPLICIT_HASHER,
implicit_return::IMPLICIT_RETURN,
+ implicit_saturating_add::IMPLICIT_SATURATING_ADD,
implicit_saturating_sub::IMPLICIT_SATURATING_SUB,
inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR,
index_refutable_slice::INDEX_REFUTABLE_SLICE,
@@ -223,7 +230,6 @@ store.register_lints(&[
loops::EXPLICIT_INTO_ITER_LOOP,
loops::EXPLICIT_ITER_LOOP,
loops::FOR_KV_MAP,
- loops::FOR_LOOPS_OVER_FALLIBLES,
loops::ITER_NEXT_LOOP,
loops::MANUAL_FIND,
loops::MANUAL_FLATTEN,
@@ -243,6 +249,7 @@ store.register_lints(&[
manual_assert::MANUAL_ASSERT,
manual_async_fn::MANUAL_ASYNC_FN,
manual_bits::MANUAL_BITS,
+ manual_clamp::MANUAL_CLAMP,
manual_instant_elapsed::MANUAL_INSTANT_ELAPSED,
manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE,
manual_rem_euclid::MANUAL_REM_EUCLID,
@@ -254,6 +261,7 @@ store.register_lints(&[
match_result_ok::MATCH_RESULT_OK,
matches::COLLAPSIBLE_MATCH,
matches::INFALLIBLE_DESTRUCTURING_MATCH,
+ matches::MANUAL_FILTER,
matches::MANUAL_MAP,
matches::MANUAL_UNWRAP_OR,
matches::MATCH_AS_REF,
@@ -313,6 +321,7 @@ store.register_lints(&[
methods::ITERATOR_STEP_BY_ZERO,
methods::ITER_CLONED_COLLECT,
methods::ITER_COUNT,
+ methods::ITER_KV_MAP,
methods::ITER_NEXT_SLICE,
methods::ITER_NTH,
methods::ITER_NTH_ZERO,
@@ -398,6 +407,7 @@ store.register_lints(&[
missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES,
missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
+ missing_trait_methods::MISSING_TRAIT_METHODS,
mixed_read_write_in_expression::DIVERGING_SUB_EXPRESSION,
mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION,
module_style::MOD_MODULE_FILES,
@@ -470,6 +480,7 @@ store.register_lints(&[
panic_unimplemented::TODO,
panic_unimplemented::UNIMPLEMENTED,
panic_unimplemented::UNREACHABLE,
+ partial_pub_fields::PARTIAL_PUB_FIELDS,
partialeq_ne_impl::PARTIALEQ_NE_IMPL,
partialeq_to_none::PARTIALEQ_TO_NONE,
pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE,
@@ -595,7 +606,6 @@ store.register_lints(&[
vec_init_then_push::VEC_INIT_THEN_PUSH,
wildcard_imports::ENUM_GLOB_USE,
wildcard_imports::WILDCARD_IMPORTS,
- write::POSITIONAL_NAMED_FORMAT_PARAMETERS,
write::PRINTLN_EMPTY_STRING,
write::PRINT_LITERAL,
write::PRINT_STDERR,
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
index 0876b2c3b..65616d28d 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_nursery.rs
@@ -4,8 +4,10 @@
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
+ LintId::of(casts::AS_PTR_CAST_MUT),
LintId::of(cognitive_complexity::COGNITIVE_COMPLEXITY),
LintId::of(copies::BRANCHES_SHARING_CODE),
+ LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
LintId::of(equatable_if_let::EQUATABLE_IF_LET),
LintId::of(fallible_impl_from::FALLIBLE_IMPL_FROM),
LintId::of(floating_point_arithmetic::IMPRECISE_FLOPS),
@@ -25,14 +27,11 @@ store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
LintId::of(non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY),
LintId::of(nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES),
LintId::of(option_if_let_else::OPTION_IF_LET_ELSE),
- LintId::of(read_zero_byte_vec::READ_ZERO_BYTE_VEC),
LintId::of(redundant_pub_crate::REDUNDANT_PUB_CRATE),
LintId::of(regex::TRIVIAL_REGEX),
LintId::of(strings::STRING_LIT_AS_BYTES),
LintId::of(suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
LintId::of(trailing_empty_array::TRAILING_EMPTY_ARRAY),
- LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
- LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_UNDEFINED_REPR),
LintId::of(unused_peekable::UNUSED_PEEKABLE),
LintId::of(unused_rounding::UNUSED_ROUNDING),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
index 03c3c202e..44e969585 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs
@@ -20,20 +20,20 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
LintId::of(dereference::REF_BINDING_TO_REFERENCE),
LintId::of(derive::EXPL_IMPL_CLONE_ON_COPY),
LintId::of(derive::UNSAFE_DERIVE_DESERIALIZE),
+ LintId::of(doc::DOC_LINK_WITH_QUOTES),
LintId::of(doc::DOC_MARKDOWN),
LintId::of(doc::MISSING_ERRORS_DOC),
LintId::of(doc::MISSING_PANICS_DOC),
- LintId::of(doc_link_with_quotes::DOC_LINK_WITH_QUOTES),
LintId::of(empty_enum::EMPTY_ENUM),
LintId::of(enum_variants::MODULE_NAME_REPETITIONS),
LintId::of(eta_reduction::REDUNDANT_CLOSURE_FOR_METHOD_CALLS),
LintId::of(excessive_bools::FN_PARAMS_EXCESSIVE_BOOLS),
LintId::of(excessive_bools::STRUCT_EXCESSIVE_BOOLS),
+ LintId::of(format_args::UNINLINED_FORMAT_ARGS),
LintId::of(functions::MUST_USE_CANDIDATE),
LintId::of(functions::TOO_MANY_LINES),
LintId::of(if_not_else::IF_NOT_ELSE),
LintId::of(implicit_hasher::IMPLICIT_HASHER),
- LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
LintId::of(inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR),
LintId::of(infinite_iter::MAYBE_INFINITE_ITER),
LintId::of(invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS),
@@ -88,6 +88,8 @@ store.register_group(true, "clippy::pedantic", Some("clippy_pedantic"), vec![
LintId::of(return_self_not_must_use::RETURN_SELF_NOT_MUST_USE),
LintId::of(semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED),
LintId::of(strings::STRING_ADD_ASSIGN),
+ LintId::of(trait_bounds::TRAIT_DUPLICATION_IN_BOUNDS),
+ LintId::of(trait_bounds::TYPE_REPETITION_IN_BOUNDS),
LintId::of(transmute::TRANSMUTE_PTR_TO_PTR),
LintId::of(types::LINKEDLIST),
LintId::of(types::OPTION_OPTION),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
index 195ce41e3..8e927470e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_perf.rs
@@ -3,6 +3,7 @@
// Manual edits will be overwritten.
store.register_group(true, "clippy::perf", Some("clippy_perf"), vec![
+ LintId::of(box_default::BOX_DEFAULT),
LintId::of(entry::MAP_ENTRY),
LintId::of(escape::BOXED_LOCAL),
LintId::of(format_args::FORMAT_IN_FORMAT_ARGS),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
index 6eb9b3d3b..f62d57af5 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_restriction.rs
@@ -47,6 +47,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
LintId::of(missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS),
LintId::of(missing_enforced_import_rename::MISSING_ENFORCED_IMPORT_RENAMES),
LintId::of(missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS),
+ LintId::of(missing_trait_methods::MISSING_TRAIT_METHODS),
LintId::of(mixed_read_write_in_expression::MIXED_READ_WRITE_IN_EXPRESSION),
LintId::of(module_style::MOD_MODULE_FILES),
LintId::of(module_style::SELF_NAMED_MODULE_FILES),
@@ -61,6 +62,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
LintId::of(panic_unimplemented::TODO),
LintId::of(panic_unimplemented::UNIMPLEMENTED),
LintId::of(panic_unimplemented::UNREACHABLE),
+ LintId::of(partial_pub_fields::PARTIAL_PUB_FIELDS),
LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
LintId::of(pub_use::PUB_USE),
LintId::of(redundant_slicing::DEREF_BY_SLICING),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_style.rs b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
index 05d2ec2e9..3312f5648 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_style.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_style.rs
@@ -15,7 +15,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
LintId::of(default::FIELD_REASSIGN_WITH_DEFAULT),
LintId::of(default_instead_of_iter_empty::DEFAULT_INSTEAD_OF_ITER_EMPTY),
LintId::of(dereference::NEEDLESS_BORROW),
- LintId::of(derive::DERIVE_PARTIAL_EQ_WITHOUT_EQ),
+ LintId::of(disallowed_macros::DISALLOWED_MACROS),
LintId::of(disallowed_methods::DISALLOWED_METHODS),
LintId::of(disallowed_names::DISALLOWED_NAMES),
LintId::of(disallowed_types::DISALLOWED_TYPES),
@@ -30,6 +30,8 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
LintId::of(functions::DOUBLE_MUST_USE),
LintId::of(functions::MUST_USE_UNIT),
LintId::of(functions::RESULT_UNIT_ERR),
+ LintId::of(implicit_saturating_add::IMPLICIT_SATURATING_ADD),
+ LintId::of(implicit_saturating_sub::IMPLICIT_SATURATING_SUB),
LintId::of(inherent_to_string::INHERENT_TO_STRING),
LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
LintId::of(len_zero::COMPARISON_TO_EMPTY),
diff --git a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
index bede91f18..b70c4bb73 100644
--- a/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs
@@ -11,6 +11,7 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
LintId::of(casts::CAST_ABS_TO_UNSIGNED),
LintId::of(casts::CAST_ENUM_CONSTRUCTOR),
LintId::of(casts::CAST_ENUM_TRUNCATION),
+ LintId::of(casts::CAST_NAN_TO_INT),
LintId::of(casts::CAST_SLICE_FROM_RAW_PARTS),
LintId::of(crate_in_macro_def::CRATE_IN_MACRO_DEF),
LintId::of(drop_forget_ref::DROP_NON_DROP),
@@ -21,7 +22,6 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
LintId::of(formatting::SUSPICIOUS_ELSE_FORMATTING),
LintId::of(formatting::SUSPICIOUS_UNARY_OP_FORMATTING),
LintId::of(loops::EMPTY_LOOP),
- LintId::of(loops::FOR_LOOPS_OVER_FALLIBLES),
LintId::of(loops::MUT_RANGE_BOUND),
LintId::of(methods::NO_EFFECT_REPLACE),
LintId::of(methods::SUSPICIOUS_MAP),
@@ -35,5 +35,4 @@ store.register_group(true, "clippy::suspicious", Some("clippy_suspicious"), vec!
LintId::of(suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
LintId::of(suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
LintId::of(swap_ptr_to_ref::SWAP_PTR_TO_REF),
- LintId::of(write::POSITIONAL_NAMED_FORMAT_PARAMETERS),
])
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index ceaaf5c6d..1307096b2 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -5,7 +5,6 @@
#![feature(drain_filter)]
#![feature(iter_intersperse)]
#![feature(let_chains)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(lint_reasons)]
#![feature(never_type)]
#![feature(once_cell)]
@@ -32,20 +31,19 @@ extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_hir;
+extern crate rustc_hir_analysis;
+extern crate rustc_hir_typeck;
extern crate rustc_hir_pretty;
extern crate rustc_index;
extern crate rustc_infer;
extern crate rustc_lexer;
extern crate rustc_lint;
extern crate rustc_middle;
-extern crate rustc_mir_dataflow;
extern crate rustc_parse;
-extern crate rustc_parse_format;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
extern crate rustc_trait_selection;
-extern crate rustc_typeck;
#[macro_use]
extern crate clippy_utils;
@@ -182,6 +180,7 @@ mod bool_assert_comparison;
mod bool_to_int_with_if;
mod booleans;
mod borrow_deref_ref;
+mod box_default;
mod cargo;
mod casts;
mod checked_conversions;
@@ -200,12 +199,12 @@ mod default_union_representation;
mod dereference;
mod derivable_impls;
mod derive;
+mod disallowed_macros;
mod disallowed_methods;
mod disallowed_names;
mod disallowed_script_idents;
mod disallowed_types;
mod doc;
-mod doc_link_with_quotes;
mod double_parens;
mod drop_forget_ref;
mod duplicate_mod;
@@ -240,6 +239,7 @@ mod if_not_else;
mod if_then_some_else_none;
mod implicit_hasher;
mod implicit_return;
+mod implicit_saturating_add;
mod implicit_saturating_sub;
mod inconsistent_struct_constructor;
mod index_refutable_slice;
@@ -269,6 +269,7 @@ mod main_recursion;
mod manual_assert;
mod manual_async_fn;
mod manual_bits;
+mod manual_clamp;
mod manual_instant_elapsed;
mod manual_non_exhaustive;
mod manual_rem_euclid;
@@ -289,6 +290,7 @@ mod missing_const_for_fn;
mod missing_doc;
mod missing_enforced_import_rename;
mod missing_inline;
+mod missing_trait_methods;
mod mixed_read_write_in_expression;
mod module_style;
mod multi_assignments;
@@ -324,6 +326,7 @@ mod option_if_let_else;
mod overflow_check_conditional;
mod panic_in_result_fn;
mod panic_unimplemented;
+mod partial_pub_fields;
mod partialeq_ne_impl;
mod partialeq_to_none;
mod pass_by_ref_or_value;
@@ -417,15 +420,13 @@ pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Se
let msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
- sess.err(&format!(
- "error reading Clippy's configuration file. `{}` is not a valid Rust version",
- s
+ sess.err(format!(
+ "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
));
None
})
});
- store.register_pre_expansion_pass(|| Box::new(write::Write::default()));
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv }));
}
@@ -435,9 +436,8 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
.and_then(|v| parse_msrv(&v, None, None));
let clippy_msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
- sess.err(&format!(
- "error reading Clippy's configuration file. `{}` is not a valid Rust version",
- s
+ sess.err(format!(
+ "error reading Clippy's configuration file. `{s}` is not a valid Rust version"
));
None
})
@@ -447,9 +447,8 @@ fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
if let Some(clippy_msrv) = clippy_msrv {
// if both files have an msrv, let's compare them and emit a warning if they differ
if clippy_msrv != cargo_msrv {
- sess.warn(&format!(
- "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{}` from `clippy.toml`",
- clippy_msrv
+ sess.warn(format!(
+ "the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
));
}
@@ -468,7 +467,7 @@ pub fn read_conf(sess: &Session) -> Conf {
Ok(Some(path)) => path,
Ok(None) => return Conf::default(),
Err(error) => {
- sess.struct_err(&format!("error finding Clippy's configuration file: {}", error))
+ sess.struct_err(&format!("error finding Clippy's configuration file: {error}"))
.emit();
return Conf::default();
},
@@ -477,7 +476,7 @@ pub fn read_conf(sess: &Session) -> Conf {
let TryConf { conf, errors, warnings } = utils::conf::read(&file_name);
// all conf errors are non-fatal, we just use the default conf in case of error
for error in errors {
- sess.err(&format!(
+ sess.err(format!(
"error reading Clippy's configuration file `{}`: {}",
file_name.display(),
format_error(error)
@@ -485,7 +484,7 @@ pub fn read_conf(sess: &Session) -> Conf {
}
for warning in warnings {
- sess.struct_warn(&format!(
+ sess.struct_warn(format!(
"error reading Clippy's configuration file `{}`: {}",
file_name.display(),
format_error(warning)
@@ -524,7 +523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
#[cfg(feature = "internal")]
{
if std::env::var("ENABLE_METADATA_COLLECTION").eq(&Ok("1".to_string())) {
- store.register_late_pass(|| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
+ store.register_late_pass(|_| Box::new(utils::internal_lints::metadata_collector::MetadataCollector::new()));
return;
}
}
@@ -532,17 +531,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
// all the internal lints
#[cfg(feature = "internal")]
{
- store.register_early_pass(|| Box::new(utils::internal_lints::ClippyLintsInternal));
- store.register_early_pass(|| Box::new(utils::internal_lints::ProduceIce));
- store.register_late_pass(|_| Box::new(utils::internal_lints::CollapsibleCalls));
- store.register_late_pass(|_| Box::new(utils::internal_lints::CompilerLintFunctions::new()));
- store.register_late_pass(|_| Box::new(utils::internal_lints::IfChainStyle));
- store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths));
- store.register_late_pass(|_| Box::new(utils::internal_lints::InterningDefinedSymbol::default()));
- store.register_late_pass(|_| Box::new(utils::internal_lints::LintWithoutLintPass::default()));
- store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem));
- store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass));
- store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl));
+ store.register_early_pass(|| Box::new(utils::internal_lints::clippy_lints_internal::ClippyLintsInternal));
+ store.register_early_pass(|| Box::new(utils::internal_lints::produce_ice::ProduceIce));
+ store.register_late_pass(|_| Box::new(utils::internal_lints::collapsible_calls::CollapsibleCalls));
+ store.register_late_pass(|_| {
+ Box::new(utils::internal_lints::compiler_lint_functions::CompilerLintFunctions::new())
+ });
+ store.register_late_pass(|_| Box::new(utils::internal_lints::if_chain_style::IfChainStyle));
+ store.register_late_pass(|_| Box::new(utils::internal_lints::invalid_paths::InvalidPaths));
+ store.register_late_pass(|_| {
+ Box::<utils::internal_lints::interning_defined_symbol::InterningDefinedSymbol>::default()
+ });
+ store.register_late_pass(|_| {
+ Box::<utils::internal_lints::lint_without_lint_pass::LintWithoutLintPass>::default()
+ });
+ store.register_late_pass(|_| Box::<utils::internal_lints::unnecessary_def_path::UnnecessaryDefPath>::default());
+ store.register_late_pass(|_| Box::new(utils::internal_lints::outer_expn_data_pass::OuterExpnDataPass));
+ store.register_late_pass(|_| Box::new(utils::internal_lints::msrv_attr_impl::MsrvAttrImpl));
}
let arithmetic_side_effects_allowed = conf.arithmetic_side_effects_allowed.clone();
@@ -632,10 +637,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
msrv,
))
});
- store.register_late_pass(|_| Box::new(shadow::Shadow::default()));
+ store.register_late_pass(|_| Box::<shadow::Shadow>::default());
store.register_late_pass(|_| Box::new(unit_types::UnitTypes));
store.register_late_pass(|_| Box::new(loops::Loops));
- store.register_late_pass(|_| Box::new(main_recursion::MainRecursion::default()));
+ store.register_late_pass(|_| Box::<main_recursion::MainRecursion>::default());
store.register_late_pass(|_| Box::new(lifetimes::Lifetimes));
store.register_late_pass(|_| Box::new(entry::HashMapPass));
store.register_late_pass(|_| Box::new(minmax::MinMaxPass));
@@ -669,7 +674,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(format::UselessFormat));
store.register_late_pass(|_| Box::new(swap::Swap));
store.register_late_pass(|_| Box::new(overflow_check_conditional::OverflowCheckConditional));
- store.register_late_pass(|_| Box::new(new_without_default::NewWithoutDefault::default()));
+ store.register_late_pass(|_| Box::<new_without_default::NewWithoutDefault>::default());
let disallowed_names = conf.disallowed_names.iter().cloned().collect::<FxHashSet<_>>();
store.register_late_pass(move |_| Box::new(disallowed_names::DisallowedNames::new(disallowed_names.clone())));
let too_many_arguments_threshold = conf.too_many_arguments_threshold;
@@ -708,7 +713,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(ref_option_ref::RefOptionRef));
store.register_late_pass(|_| Box::new(infinite_iter::InfiniteIter));
store.register_late_pass(|_| Box::new(inline_fn_without_body::InlineFnWithoutBody));
- store.register_late_pass(|_| Box::new(useless_conversion::UselessConversion::default()));
+ store.register_late_pass(|_| Box::<useless_conversion::UselessConversion>::default());
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));
@@ -778,7 +783,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
upper_case_acronyms_aggressive,
))
});
- store.register_late_pass(|_| Box::new(default::Default::default()));
+ store.register_late_pass(|_| Box::<default::Default>::default());
store.register_late_pass(move |_| Box::new(unused_self::UnusedSelf::new(avoid_breaking_exported_api)));
store.register_late_pass(|_| Box::new(mutable_debug_assertion::DebugAssertWithMutCall));
store.register_late_pass(|_| Box::new(exit::Exit));
@@ -801,7 +806,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_early_pass(|| Box::new(option_env_unwrap::OptionEnvUnwrap));
let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports;
store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
- store.register_late_pass(|_| Box::new(redundant_pub_crate::RedundantPubCrate::default()));
+ store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv)));
store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
@@ -819,11 +824,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
});
let macro_matcher = conf.standard_macro_braces.iter().cloned().collect::<FxHashSet<_>>();
store.register_early_pass(move || Box::new(nonstandard_macro_braces::MacroBraces::new(&macro_matcher)));
- store.register_late_pass(|_| Box::new(macro_use::MacroUseImports::default()));
+ store.register_late_pass(|_| Box::<macro_use::MacroUseImports>::default());
store.register_late_pass(|_| Box::new(pattern_type_mismatch::PatternTypeMismatch));
store.register_late_pass(|_| Box::new(unwrap_in_result::UnwrapInResult));
store.register_late_pass(|_| Box::new(semicolon_if_nothing_returned::SemicolonIfNothingReturned));
store.register_late_pass(|_| Box::new(async_yields_async::AsyncYieldsAsync));
+ let disallowed_macros = conf.disallowed_macros.clone();
+ store.register_late_pass(move |_| Box::new(disallowed_macros::DisallowedMacros::new(disallowed_macros.clone())));
let disallowed_methods = conf.disallowed_methods.clone();
store.register_late_pass(move |_| Box::new(disallowed_methods::DisallowedMethods::new(disallowed_methods.clone())));
store.register_early_pass(|| Box::new(asm_syntax::InlineAsmX86AttSyntax));
@@ -832,7 +839,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(strings::StrToString));
store.register_late_pass(|_| Box::new(strings::StringToString));
store.register_late_pass(|_| Box::new(zero_sized_map_values::ZeroSizedMapValues));
- store.register_late_pass(|_| Box::new(vec_init_then_push::VecInitThenPush::default()));
+ store.register_late_pass(|_| Box::<vec_init_then_push::VecInitThenPush>::default());
store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10));
store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
@@ -860,7 +867,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
))
});
store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
- store.register_late_pass(move |_| Box::new(format_args::FormatArgs));
+ store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv)));
store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
@@ -869,8 +876,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv)));
store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
- store.register_early_pass(|| Box::new(doc_link_with_quotes::DocLinkWithQuotes));
- store.register_late_pass(|_| Box::new(only_used_in_recursion::OnlyUsedInRecursion::default()));
+ store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
let allow_dbg_in_tests = conf.allow_dbg_in_tests;
store.register_late_pass(move |_| Box::new(dbg_macro::DbgMacro::new(allow_dbg_in_tests)));
let cargo_ignore_publish = conf.cargo_ignore_publish;
@@ -879,6 +885,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
ignore_publish: cargo_ignore_publish,
})
});
+ store.register_late_pass(|_| Box::<write::Write>::default());
store.register_early_pass(|| Box::new(crate_in_macro_def::CrateInMacroDef));
store.register_early_pass(|| Box::new(empty_structs_with_brackets::EmptyStructsWithBrackets));
store.register_late_pass(|_| Box::new(unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings));
@@ -888,7 +895,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move |_| Box::new(large_include_file::LargeIncludeFile::new(max_include_file_size)));
store.register_late_pass(|_| Box::new(strings::TrimSplitWhitespace));
store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
- store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
+ store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
@@ -900,13 +907,18 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
- store.register_late_pass(|_| Box::new(std_instead_of_core::StdReexports::default()));
+ store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
store.register_late_pass(|_| Box::new(manual_instant_elapsed::ManualInstantElapsed));
store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
+ store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv)));
store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
store.register_late_pass(|_| Box::new(bool_to_int_with_if::BoolToIntWithIf));
+ store.register_late_pass(|_| Box::new(box_default::BoxDefault));
+ store.register_late_pass(|_| Box::new(implicit_saturating_add::ImplicitSaturatingAdd));
+ store.register_early_pass(|| Box::new(partial_pub_fields::PartialPubFields));
+ store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods));
// 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 643a7cfd5..3bf2d7e4e 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -9,8 +9,8 @@ use rustc_hir::intravisit::{
use rustc_hir::FnRetTy::Return;
use rustc_hir::{
BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
- ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin,
- TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+ ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn,
+ TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter as middle_nested_filter;
@@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for Lifetimes {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
if let ImplItemKind::Fn(ref sig, id) = item.kind {
- let report_extra_lifetimes = trait_ref_of_method(cx, item.def_id).is_none();
+ let report_extra_lifetimes = trait_ref_of_method(cx, item.owner_id.def_id).is_none();
check_fn_inner(
cx,
sig.decl,
diff --git a/src/tools/clippy/clippy_lints/src/literal_representation.rs b/src/tools/clippy/clippy_lints/src/literal_representation.rs
index fb2104861..25f19b9c6 100644
--- a/src/tools/clippy/clippy_lints/src/literal_representation.rs
+++ b/src/tools/clippy/clippy_lints/src/literal_representation.rs
@@ -478,7 +478,7 @@ impl DecimalLiteralRepresentation {
if num_lit.radix == Radix::Decimal;
if val >= u128::from(self.threshold);
then {
- let hex = format!("{:#X}", val);
+ 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| {
warning_type.display(num_lit.format(), cx, lit.span);
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
index 8e3ab26a9..14f223481 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_counter_loop.rs
@@ -44,11 +44,10 @@ pub(super) fn check<'tcx>(
cx,
EXPLICIT_COUNTER_LOOP,
span,
- &format!("the variable `{}` is used as a loop counter", name),
+ &format!("the variable `{name}` is used as a loop counter"),
"consider using",
format!(
- "for ({}, {}) in {}.enumerate()",
- name,
+ "for ({name}, {}) in {}.enumerate()",
snippet_with_applicability(cx, pat.span, "item", &mut applicability),
make_iterator_snippet(cx, arg, &mut applicability),
),
@@ -65,24 +64,21 @@ pub(super) fn check<'tcx>(
cx,
EXPLICIT_COUNTER_LOOP,
span,
- &format!("the variable `{}` is used as a loop counter", name),
+ &format!("the variable `{name}` is used as a loop counter"),
|diag| {
diag.span_suggestion(
span,
"consider using",
format!(
- "for ({}, {}) in (0_{}..).zip({})",
- name,
+ "for ({name}, {}) in (0_{int_name}..).zip({})",
snippet_with_applicability(cx, pat.span, "item", &mut applicability),
- int_name,
make_iterator_snippet(cx, arg, &mut applicability),
),
applicability,
);
diag.note(&format!(
- "`{}` is of type `{}`, making it ineligible for `Iterator::enumerate`",
- name, int_name
+ "`{name}` is of type `{int_name}`, making it ineligible for `Iterator::enumerate`"
));
},
);
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 5f5beccd0..b1f294162 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
@@ -41,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, self_arg: &Expr<'_>, arg: &Expr<'_>, m
"it is more concise to loop over references to containers instead of using explicit \
iteration methods",
"to write this more concisely, try",
- format!("&{}{}", muta, object),
+ format!("&{muta}{object}"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
index bee0e1d76..ed620460d 100644
--- a/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/for_kv_map.rs
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
cx,
FOR_KV_MAP,
arg_span,
- &format!("you seem to want to iterate on a map's {}s", kind),
+ &format!("you seem to want to iterate on a map's {kind}s"),
|diag| {
let map = sugg::Sugg::hir(cx, arg, "map");
multispan_sugg(
@@ -46,7 +46,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx
"use the corresponding method",
vec![
(pat_span, snippet(cx, new_pat_span, kind).into_owned()),
- (arg_span, format!("{}.{}s{}()", map.maybe_par(), kind, mutbl)),
+ (arg_span, format!("{}.{kind}s{mutbl}()", map.maybe_par())),
],
);
},
diff --git a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs b/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs
deleted file mode 100644
index 77de90fd7..000000000
--- a/src/tools/clippy/clippy_lints/src/loops/for_loops_over_fallibles.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-use super::FOR_LOOPS_OVER_FALLIBLES;
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::source::snippet;
-use clippy_utils::ty::is_type_diagnostic_item;
-use rustc_hir::{Expr, Pat};
-use rustc_lint::LateContext;
-use rustc_span::symbol::sym;
-
-/// Checks for `for` loops over `Option`s and `Result`s.
-pub(super) fn check(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>, method_name: Option<&str>) {
- let ty = cx.typeck_results().expr_ty(arg);
- if is_type_diagnostic_item(cx, ty, sym::Option) {
- let help_string = if let Some(method_name) = method_name {
- format!(
- "consider replacing `for {0} in {1}.{method_name}()` with `if let Some({0}) = {1}`",
- snippet(cx, pat.span, "_"),
- snippet(cx, arg.span, "_")
- )
- } else {
- format!(
- "consider replacing `for {0} in {1}` with `if let Some({0}) = {1}`",
- snippet(cx, pat.span, "_"),
- snippet(cx, arg.span, "_")
- )
- };
- span_lint_and_help(
- cx,
- FOR_LOOPS_OVER_FALLIBLES,
- arg.span,
- &format!(
- "for loop over `{0}`, which is an `Option`. This is more readably written as an \
- `if let` statement",
- snippet(cx, arg.span, "_")
- ),
- None,
- &help_string,
- );
- } else if is_type_diagnostic_item(cx, ty, sym::Result) {
- let help_string = if let Some(method_name) = method_name {
- format!(
- "consider replacing `for {0} in {1}.{method_name}()` with `if let Ok({0}) = {1}`",
- snippet(cx, pat.span, "_"),
- snippet(cx, arg.span, "_")
- )
- } else {
- format!(
- "consider replacing `for {0} in {1}` with `if let Ok({0}) = {1}`",
- snippet(cx, pat.span, "_"),
- snippet(cx, arg.span, "_")
- )
- };
- span_lint_and_help(
- cx,
- FOR_LOOPS_OVER_FALLIBLES,
- arg.span,
- &format!(
- "for loop over `{0}`, which is a `Result`. This is more readably written as an \
- `if let` statement",
- snippet(cx, arg.span, "_")
- ),
- None,
- &help_string,
- );
- }
-}
diff --git a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
index e640c62eb..b8a263817 100644
--- a/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/iter_next_loop.rs
@@ -5,7 +5,7 @@ use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_span::sym;
-pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
+pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) {
if is_trait_method(cx, arg, sym::Iterator) {
span_lint(
cx,
@@ -14,8 +14,5 @@ pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>) -> bool {
"you are iterating over `Iterator::next()` which is an Option; this will compile but is \
probably not what you want",
);
- true
- } else {
- false
}
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
index 09b2376d5..4bb9936e9 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_find.rs
@@ -1,7 +1,7 @@
use super::utils::make_iterator_snippet;
use super::MANUAL_FIND;
use clippy_utils::{
- diagnostics::span_lint_and_then, higher, is_lang_ctor, path_res, peel_blocks_with_stmt,
+ diagnostics::span_lint_and_then, higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt,
source::snippet_with_applicability, ty::implements_trait,
};
use if_chain::if_chain;
@@ -30,8 +30,8 @@ pub(super) fn check<'tcx>(
if let [stmt] = block.stmts;
if let StmtKind::Semi(semi) = stmt.kind;
if let ExprKind::Ret(Some(ret_value)) = semi.kind;
- if let ExprKind::Call(Expr { kind: ExprKind::Path(ctor), .. }, [inner_ret]) = ret_value.kind;
- if is_lang_ctor(cx, ctor, LangItem::OptionSome);
+ if let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind;
+ if is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome);
if path_res(cx, inner_ret) == Res::Local(binding_id);
if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr);
then {
@@ -143,8 +143,7 @@ fn last_stmt_and_ret<'tcx>(
if let Some((_, Node::Block(block))) = parent_iter.next();
if let Some((last_stmt, last_ret)) = extract(block);
if last_stmt.hir_id == node_hir;
- if let ExprKind::Path(path) = &last_ret.kind;
- if is_lang_ctor(cx, path, LangItem::OptionNone);
+ if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone);
if let Some((_, Node::Expr(_block))) = parent_iter.next();
// This includes the function header
if let Some((_, func)) = parent_iter.next();
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
index 1d6ddf4b9..8c27c0940 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_flatten.rs
@@ -3,13 +3,13 @@ use super::MANUAL_FLATTEN;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher;
use clippy_utils::visitors::is_local_used;
-use clippy_utils::{is_lang_ctor, path_to_local_id, peel_blocks_with_stmt};
+use clippy_utils::{path_to_local_id, peel_blocks_with_stmt};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, Pat, PatKind};
use rustc_lint::LateContext;
-use rustc_middle::ty;
+use rustc_middle::ty::{self, DefIdTree};
use rustc_span::source_map::Span;
/// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
@@ -30,15 +30,17 @@ pub(super) fn check<'tcx>(
if path_to_local_id(let_expr, pat_hir_id);
// Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind;
- let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
- let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
+ if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id);
+ if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
+ let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id);
+ let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
if some_ctor || ok_ctor;
// Ensure expr in `if let` is not used afterwards
if !is_local_used(cx, if_then, pat_hir_id);
then {
let if_let_type = if some_ctor { "Some" } else { "Ok" };
// Prepare the error message
- let msg = format!("unnecessary `if let` since only the `{}` variant of the iterator element is used", if_let_type);
+ let msg = format!("unnecessary `if let` since only the `{if_let_type}` variant of the iterator element is used");
// Prepare the help message
let mut applicability = Applicability::MaybeIncorrect;
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 3fc569af8..c87fc4f90 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -177,13 +177,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
let dst = if dst_offset == sugg::EMPTY && dst_limit == sugg::EMPTY {
dst_base_str
} else {
- format!(
- "{}[{}..{}]",
- dst_base_str,
- dst_offset.maybe_par(),
- dst_limit.maybe_par()
- )
- .into()
+ format!("{dst_base_str}[{}..{}]", dst_offset.maybe_par(), dst_limit.maybe_par()).into()
};
let method_str = if is_copy(cx, elem_ty) {
@@ -193,10 +187,7 @@ fn build_manual_memcpy_suggestion<'tcx>(
};
format!(
- "{}.{}(&{}[{}..{}]);",
- dst,
- method_str,
- src_base_str,
+ "{dst}.{method_str}(&{src_base_str}[{}..{}]);",
src_offset.maybe_par(),
src_limit.maybe_par()
)
diff --git a/src/tools/clippy/clippy_lints/src/loops/mod.rs b/src/tools/clippy/clippy_lints/src/loops/mod.rs
index 74f3bda9f..bcf278d9c 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mod.rs
@@ -3,7 +3,6 @@ mod explicit_counter_loop;
mod explicit_into_iter_loop;
mod explicit_iter_loop;
mod for_kv_map;
-mod for_loops_over_fallibles;
mod iter_next_loop;
mod manual_find;
mod manual_flatten;
@@ -175,49 +174,6 @@ declare_clippy_lint! {
declare_clippy_lint! {
/// ### What it does
- /// Checks for `for` loops over `Option` or `Result` values.
- ///
- /// ### Why is this bad?
- /// Readability. This is more clearly expressed as an `if
- /// let`.
- ///
- /// ### Example
- /// ```rust
- /// # let opt = Some(1);
- /// # let res: Result<i32, std::io::Error> = Ok(1);
- /// for x in opt {
- /// // ..
- /// }
- ///
- /// for x in &res {
- /// // ..
- /// }
- ///
- /// for x in res.iter() {
- /// // ..
- /// }
- /// ```
- ///
- /// Use instead:
- /// ```rust
- /// # let opt = Some(1);
- /// # let res: Result<i32, std::io::Error> = Ok(1);
- /// if let Some(x) = opt {
- /// // ..
- /// }
- ///
- /// if let Ok(x) = res {
- /// // ..
- /// }
- /// ```
- #[clippy::version = "1.45.0"]
- pub FOR_LOOPS_OVER_FALLIBLES,
- suspicious,
- "for-looping over an `Option` or a `Result`, which is more clearly expressed as an `if let`"
-}
-
-declare_clippy_lint! {
- /// ### What it does
/// Detects `loop + match` combinations that are easier
/// written as a `while let` loop.
///
@@ -635,7 +591,7 @@ declare_clippy_lint! {
/// arr.into_iter().find(|&el| el == 1)
/// }
/// ```
- #[clippy::version = "1.61.0"]
+ #[clippy::version = "1.64.0"]
pub MANUAL_FIND,
complexity,
"manual implementation of `Iterator::find`"
@@ -648,7 +604,6 @@ declare_lint_pass!(Loops => [
EXPLICIT_ITER_LOOP,
EXPLICIT_INTO_ITER_LOOP,
ITER_NEXT_LOOP,
- FOR_LOOPS_OVER_FALLIBLES,
WHILE_LET_LOOP,
NEEDLESS_COLLECT,
EXPLICIT_COUNTER_LOOP,
@@ -739,30 +694,22 @@ fn check_for_loop<'tcx>(
manual_find::check(cx, pat, arg, body, span, expr);
}
-fn check_for_loop_arg(cx: &LateContext<'_>, pat: &Pat<'_>, arg: &Expr<'_>) {
- let mut next_loop_linted = false; // whether or not ITER_NEXT_LOOP lint was used
-
+fn check_for_loop_arg(cx: &LateContext<'_>, _: &Pat<'_>, arg: &Expr<'_>) {
if let ExprKind::MethodCall(method, self_arg, [], _) = arg.kind {
let method_name = method.ident.as_str();
// check for looping over x.iter() or x.iter_mut(), could use &x or &mut x
match method_name {
"iter" | "iter_mut" => {
explicit_iter_loop::check(cx, self_arg, arg, method_name);
- for_loops_over_fallibles::check(cx, pat, self_arg, Some(method_name));
},
"into_iter" => {
explicit_iter_loop::check(cx, self_arg, arg, method_name);
explicit_into_iter_loop::check(cx, self_arg, arg);
- for_loops_over_fallibles::check(cx, pat, self_arg, Some(method_name));
},
"next" => {
- next_loop_linted = iter_next_loop::check(cx, arg);
+ iter_next_loop::check(cx, arg);
},
_ => {},
}
}
-
- if !next_loop_linted {
- for_loops_over_fallibles::check(cx, pat, arg, None);
- }
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
index fce2d5463..91b321c44 100644
--- a/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
@@ -4,11 +4,11 @@ use clippy_utils::{get_enclosing_block, higher, path_to_local};
use if_chain::if_chain;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, Node, PatKind};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::{mir::FakeReadCause, ty};
use rustc_span::source_map::Span;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
pub(super) fn check(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'_>) {
if_chain! {
@@ -65,16 +65,15 @@ fn check_for_mutation<'tcx>(
span_low: None,
span_high: None,
};
- cx.tcx.infer_ctxt().enter(|infcx| {
- ExprUseVisitor::new(
- &mut delegate,
- &infcx,
- body.hir_id.owner,
- cx.param_env,
- cx.typeck_results(),
- )
- .walk_expr(body);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ ExprUseVisitor::new(
+ &mut delegate,
+ &infcx,
+ body.hir_id.owner.def_id,
+ cx.param_env,
+ cx.typeck_results(),
+ )
+ .walk_expr(body);
delegate.mutation_span()
}
@@ -114,7 +113,13 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate<'_, 'tcx> {
}
}
- fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+ fn fake_read(
+ &mut self,
+ _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
+ _: FakeReadCause,
+ _: HirId,
+ ) {
+ }
}
impl MutatePairDelegate<'_, '_> {
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
index 6e6faa79a..66f9e2859 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_collect.rs
@@ -45,7 +45,7 @@ fn check_needless_collect_direct_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCont
let (arg, pred) = contains_arg
.strip_prefix('&')
.map_or(("&x", &*contains_arg), |s| ("x", s));
- format!("any(|{}| x == {})", arg, pred)
+ format!("any(|{arg}| x == {pred})")
}
_ => return,
}
@@ -141,9 +141,9 @@ impl IterFunction {
IterFunctionKind::Contains(span) => {
let s = snippet(cx, *span, "..");
if let Some(stripped) = s.strip_prefix('&') {
- format!(".any(|x| x == {})", stripped)
+ format!(".any(|x| x == {stripped})")
} else {
- format!(".any(|x| x == *{})", s)
+ format!(".any(|x| x == *{s})")
}
},
}
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 8ab640051..27ba27202 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
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::source::snippet;
use clippy_utils::ty::has_iter_method;
use clippy_utils::visitors::is_local_used;
-use clippy_utils::{contains_name, higher, is_integer_const, match_trait_method, paths, sugg, SpanlessEq};
+use clippy_utils::{contains_name, higher, is_integer_const, sugg, SpanlessEq};
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -145,7 +145,7 @@ pub(super) fn check<'tcx>(
cx,
NEEDLESS_RANGE_LOOP,
arg.span,
- &format!("the loop variable `{}` is used to index `{}`", ident.name, indexed),
+ &format!("the loop variable `{}` is used to index `{indexed}`", ident.name),
|diag| {
multispan_sugg(
diag,
@@ -154,7 +154,7 @@ pub(super) fn check<'tcx>(
(pat.span, format!("({}, <item>)", ident.name)),
(
arg.span,
- format!("{}.{}().enumerate(){}{}", indexed, method, method_1, method_2),
+ format!("{indexed}.{method}().enumerate(){method_1}{method_2}"),
),
],
);
@@ -162,16 +162,16 @@ pub(super) fn check<'tcx>(
);
} else {
let repl = if starts_at_zero && take_is_empty {
- format!("&{}{}", ref_mut, indexed)
+ format!("&{ref_mut}{indexed}")
} else {
- format!("{}.{}(){}{}", indexed, method, method_1, method_2)
+ format!("{indexed}.{method}(){method_1}{method_2}")
};
span_lint_and_then(
cx,
NEEDLESS_RANGE_LOOP,
arg.span,
- &format!("the loop variable `{}` is only used to index `{}`", ident.name, indexed),
+ &format!("the loop variable `{}` is only used to index `{indexed}`", ident.name),
|diag| {
multispan_sugg(
diag,
@@ -263,7 +263,8 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
match res {
Res::Local(hir_id) => {
let parent_def_id = self.cx.tcx.hir().get_parent_item(expr.hir_id);
- let extent = self.cx
+ let extent = self
+ .cx
.tcx
.region_scope_tree(parent_def_id)
.var_scope(hir_id.local_id)
@@ -274,11 +275,12 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
(Some(extent), self.cx.typeck_results().node_type(seqexpr.hir_id)),
);
} else {
- self.indexed_indirectly.insert(seqvar.segments[0].ident.name, Some(extent));
+ self.indexed_indirectly
+ .insert(seqvar.segments[0].ident.name, Some(extent));
}
- return false; // no need to walk further *on the variable*
- }
- Res::Def(DefKind::Static (_)| DefKind::Const, ..) => {
+ return false; // no need to walk further *on the variable*
+ },
+ Res::Def(DefKind::Static(_) | DefKind::Const, ..) => {
if index_used_directly {
self.indexed_directly.insert(
seqvar.segments[0].ident.name,
@@ -287,8 +289,8 @@ impl<'a, 'tcx> VarVisitor<'a, 'tcx> {
} else {
self.indexed_indirectly.insert(seqvar.segments[0].ident.name, None);
}
- return false; // no need to walk further *on the variable*
- }
+ return false; // no need to walk further *on the variable*
+ },
_ => (),
}
}
@@ -302,17 +304,26 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
if_chain! {
// a range index op
if let ExprKind::MethodCall(meth, args_0, [args_1, ..], _) = &expr.kind;
- if (meth.ident.name == sym::index && match_trait_method(self.cx, expr, &paths::INDEX))
- || (meth.ident.name == sym::index_mut && match_trait_method(self.cx, expr, &paths::INDEX_MUT));
+ if let Some(trait_id) = self
+ .cx
+ .typeck_results()
+ .type_dependent_def_id(expr.hir_id)
+ .and_then(|def_id| self.cx.tcx.trait_of_item(def_id));
+ if (meth.ident.name == sym::index && self.cx.tcx.lang_items().index_trait() == Some(trait_id))
+ || (meth.ident.name == sym::index_mut && self.cx.tcx.lang_items().index_mut_trait() == Some(trait_id));
if !self.check(args_1, args_0, expr);
- then { return }
+ then {
+ return;
+ }
}
if_chain! {
// an index op
if let ExprKind::Index(seqexpr, idx) = expr.kind;
if !self.check(idx, seqexpr, expr);
- then { return }
+ then {
+ return;
+ }
}
if_chain! {
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 116e589ca..16b00ad66 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -42,6 +42,7 @@ pub(super) fn check(
}
}
+#[derive(Copy, Clone)]
enum NeverLoopResult {
// A break/return always get triggered but not necessarily for the main loop.
AlwaysBreak,
@@ -51,8 +52,8 @@ enum NeverLoopResult {
}
#[must_use]
-fn absorb_break(arg: &NeverLoopResult) -> NeverLoopResult {
- match *arg {
+fn absorb_break(arg: NeverLoopResult) -> NeverLoopResult {
+ match arg {
NeverLoopResult::AlwaysBreak | NeverLoopResult::Otherwise => NeverLoopResult::Otherwise,
NeverLoopResult::MayContinueMainLoop => NeverLoopResult::MayContinueMainLoop,
}
@@ -92,19 +93,29 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult
}
fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult {
- let mut iter = block.stmts.iter().filter_map(stmt_to_expr).chain(block.expr);
+ let mut iter = block
+ .stmts
+ .iter()
+ .filter_map(stmt_to_expr)
+ .chain(block.expr.map(|expr| (expr, None)));
never_loop_expr_seq(&mut iter, main_loop_id)
}
-fn never_loop_expr_seq<'a, T: Iterator<Item = &'a Expr<'a>>>(es: &mut T, main_loop_id: HirId) -> NeverLoopResult {
- es.map(|e| never_loop_expr(e, main_loop_id))
- .fold(NeverLoopResult::Otherwise, combine_seq)
+fn never_loop_expr_seq<'a, T: Iterator<Item = (&'a Expr<'a>, Option<&'a Block<'a>>)>>(
+ es: &mut T,
+ main_loop_id: HirId,
+) -> NeverLoopResult {
+ es.map(|(e, els)| {
+ let e = never_loop_expr(e, main_loop_id);
+ els.map_or(e, |els| combine_branches(e, never_loop_block(els, main_loop_id)))
+ })
+ .fold(NeverLoopResult::Otherwise, combine_seq)
}
-fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> {
+fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'tcx Block<'tcx>>)> {
match stmt.kind {
- StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some(e),
- StmtKind::Local(local) => local.init,
+ StmtKind::Semi(e, ..) | StmtKind::Expr(e, ..) => Some((e, None)),
+ StmtKind::Local(local) => local.init.map(|init| (init, local.els)),
StmtKind::Item(..) => None,
}
}
@@ -139,7 +150,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
| ExprKind::Index(e1, e2) => never_loop_expr_all(&mut [e1, e2].iter().copied(), main_loop_id),
ExprKind::Loop(b, _, _, _) => {
// Break can come from the inner loop so remove them.
- absorb_break(&never_loop_block(b, main_loop_id))
+ absorb_break(never_loop_block(b, main_loop_id))
},
ExprKind::If(e, e2, e3) => {
let e1 = never_loop_expr(e, main_loop_id);
@@ -211,9 +222,5 @@ fn for_to_if_let_sugg(cx: &LateContext<'_>, iterator: &Expr<'_>, pat: &Pat<'_>)
let pat_snippet = snippet(cx, pat.span, "_");
let iter_snippet = make_iterator_snippet(cx, iterator, &mut Applicability::Unspecified);
- format!(
- "if let Some({pat}) = {iter}.next()",
- pat = pat_snippet,
- iter = iter_snippet
- )
+ format!("if let Some({pat_snippet}) = {iter_snippet}.next()")
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index aeefe6e33..07edee46f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -30,10 +30,7 @@ pub(super) fn check<'tcx>(
vec.span,
"it looks like the same item is being pushed into this Vec",
None,
- &format!(
- "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})",
- item_str, vec_str, item_str
- ),
+ &format!("try using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})"),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 4801a84eb..b6f4cf7bb 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -5,12 +5,12 @@ use rustc_ast::ast::{LitIntType, LitKind};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, Pat, PatKind, Stmt};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Symbol};
-use rustc_typeck::hir_ty_to_ty;
use std::iter::Iterator;
#[derive(Debug, PartialEq, Eq)]
@@ -344,9 +344,8 @@ pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic
_ => arg,
};
format!(
- "{}.{}()",
+ "{}.{method_name}()",
sugg::Sugg::hir_with_applicability(cx, caller, "_", applic_ref).maybe_par(),
- method_name,
)
},
_ => format!(
diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
index deb21894f..55989f8a4 100644
--- a/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/while_let_on_iterator.rs
@@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{
- get_enclosing_loop_or_multi_call_closure, is_refutable, is_trait_method, match_def_path, paths,
- visitors::is_res_used,
+ get_enclosing_loop_or_multi_call_closure, is_refutable, is_res_lang_ctor, is_trait_method, visitors::is_res_used,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
+use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp};
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::ty::adjustment::Adjust;
@@ -19,9 +18,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! {
if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
// check for `Some(..)` pattern
- if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind;
- if let Res::Def(_, pat_did) = pat_path.res;
- if match_def_path(cx, pat_did, &paths::OPTION_SOME);
+ if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind;
+ if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome);
// check for call to `Iterator::next`
if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
if method_name.ident.name == sym::next;
@@ -67,7 +65,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
expr.span.with_hi(scrutinee_expr.span.hi()),
"this loop could be written as a `for` loop",
"try",
- format!("for {} in {}{}", loop_var, iterator, by_ref),
+ format!("for {loop_var} in {iterator}{by_ref}"),
applicability,
);
}
@@ -333,9 +331,8 @@ fn needs_mutable_borrow(cx: &LateContext<'_>, iter_expr: &IterExpr, loop_expr: &
}
if let Some(e) = get_enclosing_loop_or_multi_call_closure(cx, loop_expr) {
- let local_id = match iter_expr.path {
- Res::Local(id) => id,
- _ => return true,
+ let Res::Local(local_id) = iter_expr.path else {
+ return true
};
let mut v = NestedLoopVisitor {
cx,
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index d573a1b4f..594f6af76 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -189,9 +189,9 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
let mut suggestions = vec![];
for ((root, span, hir_id), path) in used {
if path.len() == 1 {
- suggestions.push((span, format!("{}::{}", root, path[0]), hir_id));
+ suggestions.push((span, format!("{root}::{}", path[0]), hir_id));
} else {
- suggestions.push((span, format!("{}::{{{}}}", root, path.join(", ")), hir_id));
+ suggestions.push((span, format!("{root}::{{{}}}", path.join(", ")), hir_id));
}
}
@@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for MacroUseImports {
// such as `std::prelude::v1::foo` or some other macro that expands to an import.
if self.mac_refs.is_empty() {
for (span, import, hir_id) in suggestions {
- let help = format!("use {};", import);
+ let help = format!("use {import};");
span_lint_hir_and_then(
cx,
MACRO_USE_IMPORTS,
diff --git a/src/tools/clippy/clippy_lints/src/manual_assert.rs b/src/tools/clippy/clippy_lints/src/manual_assert.rs
index 26b53ab5d..b8ed9b9ec 100644
--- a/src/tools/clippy/clippy_lints/src/manual_assert.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_assert.rs
@@ -1,7 +1,8 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+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::{peel_blocks_with_stmt, sugg};
+use clippy_utils::{peel_blocks_with_stmt, span_extract_comment, sugg};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
@@ -50,20 +51,38 @@ impl<'tcx> LateLintPass<'tcx> for ManualAssert {
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});");
- span_lint_and_sugg(
+ // 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",
- "try",
- sugg,
- Applicability::MachineApplicable,
+ |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 754b0e78a..090f9f8ff 100644
--- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs
@@ -1,6 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::match_function_call;
-use clippy_utils::paths::FUTURE_FROM_GENERATOR;
+use clippy_utils::match_function_call_with_def_id;
use clippy_utils::source::{position_before_rarrow, snippet_block, snippet_opt};
use if_chain::if_chain;
use rustc_errors::Applicability;
@@ -74,11 +73,11 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn {
if let Some(ret_pos) = position_before_rarrow(&header_snip);
if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output);
then {
- let help = format!("make the function `async` and {}", ret_sugg);
+ let help = format!("make the function `async` and {ret_sugg}");
diag.span_suggestion(
header_span,
&help,
- format!("async {}{}", &header_snip[..ret_pos], ret_snip),
+ format!("async {}{ret_snip}", &header_snip[..ret_pos]),
Applicability::MachineApplicable
);
@@ -140,9 +139,9 @@ fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'t
if args.bindings.len() == 1;
let binding = &args.bindings[0];
if binding.ident.name == sym::Output;
- if let TypeBindingKind::Equality{term: Term::Ty(output)} = binding.kind;
+ if let TypeBindingKind::Equality { term: Term::Ty(output) } = binding.kind;
then {
- return Some(output)
+ return Some(output);
}
}
@@ -175,9 +174,16 @@ fn captures_all_lifetimes(inputs: &[Ty<'_>], output_lifetimes: &[LifetimeName])
fn desugared_async_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> {
if_chain! {
if let Some(block_expr) = block.expr;
- if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR);
+ if let Some(args) = cx
+ .tcx
+ .lang_items()
+ .from_generator_fn()
+ .and_then(|def_id| match_function_call_with_def_id(cx, block_expr, def_id));
if args.len() == 1;
- if let Expr{kind: ExprKind::Closure(&Closure { body, .. }), ..} = args[0];
+ if let Expr {
+ kind: ExprKind::Closure(&Closure { body, .. }),
+ ..
+ } = args[0];
let closure_body = cx.tcx.hir().body(body);
if closure_body.generator_kind == Some(GeneratorKind::Async(AsyncGeneratorKind::Block));
then {
@@ -196,7 +202,7 @@ fn suggested_ret(cx: &LateContext<'_>, output: &Ty<'_>) -> Option<(&'static str,
},
_ => {
let sugg = "return the output of the future directly";
- snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {}", snip)))
+ snippet_opt(cx, output.span).map(|snip| (sugg, format!(" -> {snip}")))
},
}
}
diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
new file mode 100644
index 000000000..02dc8755d
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs
@@ -0,0 +1,717 @@
+use itertools::Itertools;
+use rustc_errors::Diagnostic;
+use rustc_hir::{
+ def::Res, Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind,
+};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::{symbol::sym, Span};
+use std::ops::Deref;
+
+use clippy_utils::{
+ diagnostics::{span_lint_and_then, span_lint_hir_and_then},
+ eq_expr_value,
+ higher::If,
+ is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, peel_blocks,
+ peel_blocks_with_stmt,
+ sugg::Sugg,
+ ty::implements_trait,
+ visitors::is_const_evaluatable,
+ MaybePath,
+};
+use rustc_errors::Applicability;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Identifies good opportunities for a clamp function from std or core, and suggests using it.
+ ///
+ /// ### Why is this bad?
+ /// clamp is much shorter, easier to read, and doesn't use any control flow.
+ ///
+ /// ### Known issue(s)
+ /// If the clamped variable is NaN this suggestion will cause the code to propagate NaN
+ /// rather than returning either `max` or `min`.
+ ///
+ /// `clamp` functions will panic if `max < min`, `max.is_nan()`, or `min.is_nan()`.
+ /// Some may consider panicking in these situations to be desirable, but it also may
+ /// introduce panicking where there wasn't any before.
+ ///
+ /// ### Examples
+ /// ```rust
+ /// # let (input, min, max) = (0, -2, 1);
+ /// if input > max {
+ /// max
+ /// } else if input < min {
+ /// min
+ /// } else {
+ /// input
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// ```rust
+ /// # let (input, min, max) = (0, -2, 1);
+ /// input.max(min).min(max)
+ /// # ;
+ /// ```
+ ///
+ /// ```rust
+ /// # let (input, min, max) = (0, -2, 1);
+ /// match input {
+ /// x if x > max => max,
+ /// x if x < min => min,
+ /// x => x,
+ /// }
+ /// # ;
+ /// ```
+ ///
+ /// ```rust
+ /// # let (input, min, max) = (0, -2, 1);
+ /// let mut x = input;
+ /// if x < min { x = min; }
+ /// if x > max { x = max; }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// # let (input, min, max) = (0, -2, 1);
+ /// input.clamp(min, max)
+ /// # ;
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub MANUAL_CLAMP,
+ complexity,
+ "using a clamp pattern instead of the clamp function"
+}
+impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]);
+
+pub struct ManualClamp {
+ msrv: Option<RustcVersion>,
+}
+
+impl ManualClamp {
+ pub fn new(msrv: Option<RustcVersion>) -> Self {
+ Self { msrv }
+ }
+}
+
+#[derive(Debug)]
+struct ClampSuggestion<'tcx> {
+ params: InputMinMax<'tcx>,
+ span: Span,
+ make_assignment: Option<&'tcx Expr<'tcx>>,
+ hir_with_ignore_attr: Option<HirId>,
+}
+
+#[derive(Debug)]
+struct InputMinMax<'tcx> {
+ input: &'tcx Expr<'tcx>,
+ min: &'tcx Expr<'tcx>,
+ max: &'tcx Expr<'tcx>,
+ is_float: bool,
+}
+
+impl<'tcx> LateLintPass<'tcx> for ManualClamp {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+ if !meets_msrv(self.msrv, msrvs::CLAMP) {
+ return;
+ }
+ if !expr.span.from_expansion() {
+ let suggestion = is_if_elseif_else_pattern(cx, expr)
+ .or_else(|| is_max_min_pattern(cx, expr))
+ .or_else(|| is_call_max_min_pattern(cx, expr))
+ .or_else(|| is_match_pattern(cx, expr))
+ .or_else(|| is_if_elseif_pattern(cx, expr));
+ if let Some(suggestion) = suggestion {
+ emit_suggestion(cx, &suggestion);
+ }
+ }
+ }
+
+ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
+ if !meets_msrv(self.msrv, msrvs::CLAMP) {
+ return;
+ }
+ for suggestion in is_two_if_pattern(cx, block) {
+ emit_suggestion(cx, &suggestion);
+ }
+ }
+ extract_msrv_attr!(LateContext);
+}
+
+fn emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggestion<'tcx>) {
+ let ClampSuggestion {
+ params: InputMinMax {
+ input,
+ min,
+ max,
+ is_float,
+ },
+ span,
+ make_assignment,
+ hir_with_ignore_attr,
+ } = suggestion;
+ let input = Sugg::hir(cx, input, "..").maybe_par();
+ let min = Sugg::hir(cx, min, "..");
+ let max = Sugg::hir(cx, max, "..");
+ let semicolon = if make_assignment.is_some() { ";" } else { "" };
+ let assignment = if let Some(assignment) = make_assignment {
+ let assignment = Sugg::hir(cx, assignment, "..");
+ format!("{assignment} = ")
+ } else {
+ String::new()
+ };
+ let suggestion = format!("{assignment}{input}.clamp({min}, {max}){semicolon}");
+ let msg = "clamp-like pattern without using clamp function";
+ let lint_builder = |d: &mut Diagnostic| {
+ d.span_suggestion(*span, "replace with clamp", suggestion, Applicability::MaybeIncorrect);
+ if *is_float {
+ d.note("clamp will panic if max < min, min.is_nan(), or max.is_nan()")
+ .note("clamp returns NaN if the input is NaN");
+ } else {
+ d.note("clamp will panic if max < min");
+ }
+ };
+ if let Some(hir_id) = hir_with_ignore_attr {
+ span_lint_hir_and_then(cx, MANUAL_CLAMP, *hir_id, *span, msg, lint_builder);
+ } else {
+ span_lint_and_then(cx, MANUAL_CLAMP, *span, msg, lint_builder);
+ }
+}
+
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+enum TypeClampability {
+ Float,
+ Ord,
+}
+
+impl TypeClampability {
+ fn is_clampable<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<TypeClampability> {
+ if ty.is_floating_point() {
+ Some(TypeClampability::Float)
+ } else if cx
+ .tcx
+ .get_diagnostic_item(sym::Ord)
+ .map_or(false, |id| implements_trait(cx, ty, id, &[]))
+ {
+ Some(TypeClampability::Ord)
+ } else {
+ None
+ }
+ }
+
+ fn is_float(self) -> bool {
+ matches!(self, TypeClampability::Float)
+ }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// if input < min {
+/// min
+/// } else if input > max {
+/// max
+/// } else {
+/// input
+/// }
+/// # ;
+/// ```
+fn is_if_elseif_else_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+ if let Some(If {
+ cond,
+ then,
+ r#else: Some(else_if),
+ }) = If::hir(expr)
+ && let Some(If {
+ cond: else_if_cond,
+ then: else_if_then,
+ r#else: Some(else_body),
+ }) = If::hir(peel_blocks(else_if))
+ {
+ let params = is_clamp_meta_pattern(
+ cx,
+ &BinaryOp::new(peel_blocks(cond))?,
+ &BinaryOp::new(peel_blocks(else_if_cond))?,
+ peel_blocks(then),
+ peel_blocks(else_if_then),
+ None,
+ )?;
+ // Contents of the else should be the resolved input.
+ if !eq_expr_value(cx, params.input, peel_blocks(else_body)) {
+ return None;
+ }
+ Some(ClampSuggestion {
+ params,
+ span: expr.span,
+ make_assignment: None,
+ hir_with_ignore_attr: None,
+ })
+ } else {
+ None
+ }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min_value, max_value) = (0, -3, 12);
+///
+/// input.max(min_value).min(max_value)
+/// # ;
+/// ```
+fn is_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+ if let ExprKind::MethodCall(seg_second, receiver, [arg_second], _) = &expr.kind
+ && (cx.typeck_results().expr_ty_adjusted(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord))
+ && let ExprKind::MethodCall(seg_first, input, [arg_first], _) = &receiver.kind
+ && (cx.typeck_results().expr_ty_adjusted(input).is_floating_point() || is_trait_method(cx, receiver, sym::Ord))
+ {
+ let is_float = cx.typeck_results().expr_ty_adjusted(input).is_floating_point();
+ let (min, max) = match (seg_first.ident.as_str(), seg_second.ident.as_str()) {
+ ("min", "max") => (arg_second, arg_first),
+ ("max", "min") => (arg_first, arg_second),
+ _ => return None,
+ };
+ Some(ClampSuggestion {
+ params: InputMinMax { input, min, max, is_float },
+ span: expr.span,
+ make_assignment: None,
+ hir_with_ignore_attr: None,
+ })
+ } else {
+ None
+ }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min_value, max_value) = (0, -3, 12);
+/// # use std::cmp::{max, min};
+/// min(max(input, min_value), max_value)
+/// # ;
+/// ```
+fn is_call_max_min_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+ fn segment<'tcx>(cx: &LateContext<'_>, func: &Expr<'tcx>) -> Option<FunctionType<'tcx>> {
+ match func.kind {
+ ExprKind::Path(QPath::Resolved(None, path)) => {
+ let id = path.res.opt_def_id()?;
+ match cx.tcx.get_diagnostic_name(id) {
+ Some(sym::cmp_min) => Some(FunctionType::CmpMin),
+ Some(sym::cmp_max) => Some(FunctionType::CmpMax),
+ _ if is_diag_trait_item(cx, id, sym::Ord) => {
+ Some(FunctionType::OrdOrFloat(path.segments.last().expect("infallible")))
+ },
+ _ => None,
+ }
+ },
+ ExprKind::Path(QPath::TypeRelative(ty, seg)) => {
+ matches!(path_res(cx, ty), Res::PrimTy(PrimTy::Float(_))).then(|| FunctionType::OrdOrFloat(seg))
+ },
+ _ => None,
+ }
+ }
+
+ enum FunctionType<'tcx> {
+ CmpMin,
+ CmpMax,
+ OrdOrFloat(&'tcx PathSegment<'tcx>),
+ }
+
+ fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ outer_fn: &'tcx Expr<'tcx>,
+ inner_call: &'tcx Expr<'tcx>,
+ outer_arg: &'tcx Expr<'tcx>,
+ span: Span,
+ ) -> Option<ClampSuggestion<'tcx>> {
+ if let ExprKind::Call(inner_fn, [first, second]) = &inner_call.kind
+ && let Some(inner_seg) = segment(cx, inner_fn)
+ && let Some(outer_seg) = segment(cx, outer_fn)
+ {
+ let (input, inner_arg) = match (is_const_evaluatable(cx, first), is_const_evaluatable(cx, second)) {
+ (true, false) => (second, first),
+ (false, true) => (first, second),
+ _ => return None,
+ };
+ let is_float = cx.typeck_results().expr_ty_adjusted(input).is_floating_point();
+ let (min, max) = match (inner_seg, outer_seg) {
+ (FunctionType::CmpMin, FunctionType::CmpMax) => (outer_arg, inner_arg),
+ (FunctionType::CmpMax, FunctionType::CmpMin) => (inner_arg, outer_arg),
+ (FunctionType::OrdOrFloat(first_segment), FunctionType::OrdOrFloat(second_segment)) => {
+ match (first_segment.ident.as_str(), second_segment.ident.as_str()) {
+ ("min", "max") => (outer_arg, inner_arg),
+ ("max", "min") => (inner_arg, outer_arg),
+ _ => return None,
+ }
+ }
+ _ => return None,
+ };
+ Some(ClampSuggestion {
+ params: InputMinMax { input, min, max, is_float },
+ span,
+ make_assignment: None,
+ hir_with_ignore_attr: None,
+ })
+ } else {
+ None
+ }
+ }
+
+ if let ExprKind::Call(outer_fn, [first, second]) = &expr.kind {
+ check(cx, outer_fn, first, second, expr.span).or_else(|| check(cx, outer_fn, second, first, expr.span))
+ } else {
+ None
+ }
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// match input {
+/// input if input > max => max,
+/// input if input < min => min,
+/// input => input,
+/// }
+/// # ;
+/// ```
+fn is_match_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+ if let ExprKind::Match(value, [first_arm, second_arm, last_arm], rustc_hir::MatchSource::Normal) = &expr.kind {
+ // Find possible min/max branches
+ let minmax_values = |a: &'tcx Arm<'tcx>| {
+ if let PatKind::Binding(_, var_hir_id, _, None) = &a.pat.kind
+ && let Some(Guard::If(e)) = a.guard {
+ Some((e, var_hir_id, a.body))
+ } else {
+ None
+ }
+ };
+ let (first, first_hir_id, first_expr) = minmax_values(first_arm)?;
+ let (second, second_hir_id, second_expr) = minmax_values(second_arm)?;
+ let first = BinaryOp::new(first)?;
+ let second = BinaryOp::new(second)?;
+ if let PatKind::Binding(_, binding, _, None) = &last_arm.pat.kind
+ && path_to_local_id(peel_blocks_with_stmt(last_arm.body), *binding)
+ && last_arm.guard.is_none()
+ {
+ // Proceed as normal
+ } else {
+ return None;
+ }
+ if let Some(params) = is_clamp_meta_pattern(
+ cx,
+ &first,
+ &second,
+ first_expr,
+ second_expr,
+ Some((*first_hir_id, *second_hir_id)),
+ ) {
+ return Some(ClampSuggestion {
+ params: InputMinMax {
+ input: value,
+ min: params.min,
+ max: params.max,
+ is_float: params.is_float,
+ },
+ span: expr.span,
+ make_assignment: None,
+ hir_with_ignore_attr: None,
+ });
+ }
+ }
+ None
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (input, min, max) = (0, -3, 12);
+///
+/// let mut x = input;
+/// if x < min { x = min; }
+/// if x > max { x = max; }
+/// ```
+fn is_two_if_pattern<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) -> Vec<ClampSuggestion<'tcx>> {
+ block_stmt_with_last(block)
+ .tuple_windows()
+ .filter_map(|(maybe_set_first, maybe_set_second)| {
+ if let StmtKind::Expr(first_expr) = *maybe_set_first
+ && let StmtKind::Expr(second_expr) = *maybe_set_second
+ && let Some(If { cond: first_cond, then: first_then, r#else: None }) = If::hir(first_expr)
+ && let Some(If { cond: second_cond, then: second_then, r#else: None }) = If::hir(second_expr)
+ && let ExprKind::Assign(
+ maybe_input_first_path,
+ maybe_min_max_first,
+ _
+ ) = peel_blocks_with_stmt(first_then).kind
+ && let ExprKind::Assign(
+ maybe_input_second_path,
+ maybe_min_max_second,
+ _
+ ) = peel_blocks_with_stmt(second_then).kind
+ && eq_expr_value(cx, maybe_input_first_path, maybe_input_second_path)
+ && let Some(first_bin) = BinaryOp::new(first_cond)
+ && let Some(second_bin) = BinaryOp::new(second_cond)
+ && let Some(input_min_max) = is_clamp_meta_pattern(
+ cx,
+ &first_bin,
+ &second_bin,
+ maybe_min_max_first,
+ maybe_min_max_second,
+ None
+ )
+ {
+ Some(ClampSuggestion {
+ params: InputMinMax {
+ input: maybe_input_first_path,
+ min: input_min_max.min,
+ max: input_min_max.max,
+ is_float: input_min_max.is_float,
+ },
+ span: first_expr.span.to(second_expr.span),
+ make_assignment: Some(maybe_input_first_path),
+ hir_with_ignore_attr: Some(first_expr.hir_id()),
+ })
+ } else {
+ None
+ }
+ })
+ .collect()
+}
+
+/// Targets patterns like
+///
+/// ```
+/// # let (mut input, min, max) = (0, -3, 12);
+///
+/// if input < min {
+/// input = min;
+/// } else if input > max {
+/// input = max;
+/// }
+/// ```
+fn is_if_elseif_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Option<ClampSuggestion<'tcx>> {
+ if let Some(If {
+ cond,
+ then,
+ r#else: Some(else_if),
+ }) = If::hir(expr)
+ && let Some(If {
+ cond: else_if_cond,
+ then: else_if_then,
+ r#else: None,
+ }) = If::hir(peel_blocks(else_if))
+ && let ExprKind::Assign(
+ maybe_input_first_path,
+ maybe_min_max_first,
+ _
+ ) = peel_blocks_with_stmt(then).kind
+ && let ExprKind::Assign(
+ maybe_input_second_path,
+ maybe_min_max_second,
+ _
+ ) = peel_blocks_with_stmt(else_if_then).kind
+ {
+ let params = is_clamp_meta_pattern(
+ cx,
+ &BinaryOp::new(peel_blocks(cond))?,
+ &BinaryOp::new(peel_blocks(else_if_cond))?,
+ peel_blocks(maybe_min_max_first),
+ peel_blocks(maybe_min_max_second),
+ None,
+ )?;
+ if !eq_expr_value(cx, maybe_input_first_path, maybe_input_second_path) {
+ return None;
+ }
+ Some(ClampSuggestion {
+ params,
+ span: expr.span,
+ make_assignment: Some(maybe_input_first_path),
+ hir_with_ignore_attr: None,
+ })
+ } else {
+ None
+ }
+}
+
+/// `ExprKind::Binary` but more narrowly typed
+#[derive(Debug, Clone, Copy)]
+struct BinaryOp<'tcx> {
+ op: BinOpKind,
+ left: &'tcx Expr<'tcx>,
+ right: &'tcx Expr<'tcx>,
+}
+
+impl<'tcx> BinaryOp<'tcx> {
+ fn new(e: &'tcx Expr<'tcx>) -> Option<BinaryOp<'tcx>> {
+ match &e.kind {
+ ExprKind::Binary(op, left, right) => Some(BinaryOp {
+ op: op.node,
+ left,
+ right,
+ }),
+ _ => None,
+ }
+ }
+
+ fn flip(&self) -> Self {
+ Self {
+ op: match self.op {
+ BinOpKind::Le => BinOpKind::Ge,
+ BinOpKind::Lt => BinOpKind::Gt,
+ BinOpKind::Ge => BinOpKind::Le,
+ BinOpKind::Gt => BinOpKind::Lt,
+ other => other,
+ },
+ left: self.right,
+ right: self.left,
+ }
+ }
+}
+
+/// The clamp meta pattern is a pattern shared between many (but not all) patterns.
+/// In summary, this pattern consists of two if statements that meet many criteria,
+/// - binary operators that are one of [`>`, `<`, `>=`, `<=`].
+/// - Both binary statements must have a shared argument
+/// - Which can appear on the left or right side of either statement
+/// - The binary operators must define a finite range for the shared argument. To put this in
+/// the terms of Rust `std` library, the following ranges are acceptable
+/// - `Range`
+/// - `RangeInclusive`
+/// And all other range types are not accepted. For the purposes of `clamp` it's irrelevant
+/// whether the range is inclusive or not, the output is the same.
+/// - The result of each if statement must be equal to the argument unique to that if statement. The
+/// result can not be the shared argument in either case.
+fn is_clamp_meta_pattern<'tcx>(
+ cx: &LateContext<'tcx>,
+ first_bin: &BinaryOp<'tcx>,
+ second_bin: &BinaryOp<'tcx>,
+ first_expr: &'tcx Expr<'tcx>,
+ second_expr: &'tcx Expr<'tcx>,
+ // This parameters is exclusively for the match pattern.
+ // It exists because the variable bindings used in that pattern
+ // refer to the variable bound in the match arm, not the variable
+ // bound outside of it. Fortunately due to context we know this has to
+ // be the input variable, not the min or max.
+ input_hir_ids: Option<(HirId, HirId)>,
+) -> Option<InputMinMax<'tcx>> {
+ fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ first_bin: &BinaryOp<'tcx>,
+ second_bin: &BinaryOp<'tcx>,
+ first_expr: &'tcx Expr<'tcx>,
+ second_expr: &'tcx Expr<'tcx>,
+ input_hir_ids: Option<(HirId, HirId)>,
+ is_float: bool,
+ ) -> Option<InputMinMax<'tcx>> {
+ match (&first_bin.op, &second_bin.op) {
+ (BinOpKind::Ge | BinOpKind::Gt, BinOpKind::Le | BinOpKind::Lt) => {
+ let (min, max) = (second_expr, first_expr);
+ let refers_to_input = match input_hir_ids {
+ Some((first_hir_id, second_hir_id)) => {
+ path_to_local_id(peel_blocks(first_bin.left), first_hir_id)
+ && path_to_local_id(peel_blocks(second_bin.left), second_hir_id)
+ },
+ None => eq_expr_value(cx, first_bin.left, second_bin.left),
+ };
+ (refers_to_input
+ && eq_expr_value(cx, first_bin.right, first_expr)
+ && eq_expr_value(cx, second_bin.right, second_expr))
+ .then_some(InputMinMax {
+ input: first_bin.left,
+ min,
+ max,
+ is_float,
+ })
+ },
+ _ => None,
+ }
+ }
+ // First filter out any expressions with side effects
+ let exprs = [
+ first_bin.left,
+ first_bin.right,
+ second_bin.left,
+ second_bin.right,
+ first_expr,
+ second_expr,
+ ];
+ let clampability = TypeClampability::is_clampable(cx, cx.typeck_results().expr_ty(first_expr))?;
+ let is_float = clampability.is_float();
+ if exprs.iter().any(|e| peel_blocks(e).can_have_side_effects()) {
+ return None;
+ }
+ if !(is_ord_op(first_bin.op) && is_ord_op(second_bin.op)) {
+ return None;
+ }
+ let cases = [
+ (*first_bin, *second_bin),
+ (first_bin.flip(), second_bin.flip()),
+ (first_bin.flip(), *second_bin),
+ (*first_bin, second_bin.flip()),
+ ];
+
+ cases.into_iter().find_map(|(first, second)| {
+ check(cx, &first, &second, first_expr, second_expr, input_hir_ids, is_float).or_else(|| {
+ check(
+ cx,
+ &second,
+ &first,
+ second_expr,
+ first_expr,
+ input_hir_ids.map(|(l, r)| (r, l)),
+ is_float,
+ )
+ })
+ })
+}
+
+fn block_stmt_with_last<'tcx>(block: &'tcx Block<'tcx>) -> impl Iterator<Item = MaybeBorrowedStmtKind<'tcx>> {
+ block
+ .stmts
+ .iter()
+ .map(|s| MaybeBorrowedStmtKind::Borrowed(&s.kind))
+ .chain(
+ block
+ .expr
+ .as_ref()
+ .map(|e| MaybeBorrowedStmtKind::Owned(StmtKind::Expr(e))),
+ )
+}
+
+fn is_ord_op(op: BinOpKind) -> bool {
+ matches!(op, BinOpKind::Ge | BinOpKind::Gt | BinOpKind::Le | BinOpKind::Lt)
+}
+
+/// Really similar to Cow, but doesn't have a `Clone` requirement.
+#[derive(Debug)]
+enum MaybeBorrowedStmtKind<'a> {
+ Borrowed(&'a StmtKind<'a>),
+ Owned(StmtKind<'a>),
+}
+
+impl<'a> Clone for MaybeBorrowedStmtKind<'a> {
+ fn clone(&self) -> Self {
+ match self {
+ Self::Borrowed(t) => Self::Borrowed(t),
+ Self::Owned(StmtKind::Expr(e)) => Self::Owned(StmtKind::Expr(e)),
+ Self::Owned(_) => unreachable!("Owned should only ever contain a StmtKind::Expr."),
+ }
+ }
+}
+
+impl<'a> Deref for MaybeBorrowedStmtKind<'a> {
+ type Target = StmtKind<'a>;
+
+ fn deref(&self) -> &Self::Target {
+ match self {
+ Self::Borrowed(t) => t,
+ Self::Owned(t) => t,
+ }
+ }
+}
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 2b04475c7..6806c1466 100644
--- a/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
@@ -133,7 +133,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct {
diag.span_suggestion(
header_span,
"add the attribute",
- format!("#[non_exhaustive] {}", snippet),
+ format!("#[non_exhaustive] {snippet}"),
Applicability::Unspecified,
);
}
@@ -166,7 +166,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
if let Some((id, span)) = iter.next()
&& iter.next().is_none()
{
- self.potential_enums.push((item.def_id, id, item.span, span));
+ self.potential_enums.push((item.owner_id.def_id, id, item.span, span));
}
}
}
@@ -207,7 +207,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
diag.span_suggestion(
header_span,
"add the attribute",
- format!("#[non_exhaustive] {}", snippet),
+ format!("#[non_exhaustive] {snippet}"),
Applicability::Unspecified,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
index 95cc6bdbd..6f25a2ed8 100644
--- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs
@@ -27,7 +27,7 @@ declare_clippy_lint! {
/// let x: i32 = 24;
/// let rem = x.rem_euclid(4);
/// ```
- #[clippy::version = "1.63.0"]
+ #[clippy::version = "1.64.0"]
pub MANUAL_REM_EUCLID,
complexity,
"manually reimplementing `rem_euclid`"
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index f28c37d3d..3181bc86d 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -43,7 +43,7 @@ declare_clippy_lint! {
/// let mut vec = vec![0, 1, 2];
/// vec.retain(|x| x % 2 == 0);
/// ```
- #[clippy::version = "1.63.0"]
+ #[clippy::version = "1.64.0"]
pub MANUAL_RETAIN,
perf,
"`retain()` is simpler and the same functionalitys"
@@ -92,7 +92,7 @@ fn check_into_iter(
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
&& let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
- && match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
+ && cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
&& match_acceptable_type(cx, left_expr, msrv)
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
suggest(cx, parent_expr, left_expr, target_expr);
@@ -153,7 +153,7 @@ fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::E
&& let [filter_params] = filter_body.params
&& let Some(sugg) = match filter_params.pat.kind {
hir::PatKind::Binding(_, _, filter_param_ident, None) => {
- Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, "..")))
+ Some(format!("{}.retain(|{filter_param_ident}| {})", snippet(cx, left_expr.span, ".."), snippet(cx, filter_body.value.span, "..")))
},
hir::PatKind::Tuple([key_pat, value_pat], _) => {
make_sugg(cx, key_pat, value_pat, left_expr, filter_body)
@@ -161,7 +161,7 @@ fn suggest(cx: &LateContext<'_>, parent_expr: &hir::Expr<'_>, left_expr: &hir::E
hir::PatKind::Ref(pat, _) => {
match pat.kind {
hir::PatKind::Binding(_, _, filter_param_ident, None) => {
- Some(format!("{}.retain(|{}| {})", snippet(cx, left_expr.span, ".."), filter_param_ident, snippet(cx, filter_body.value.span, "..")))
+ Some(format!("{}.retain(|{filter_param_ident}| {})", snippet(cx, left_expr.span, ".."), snippet(cx, filter_body.value.span, "..")))
},
_ => None
}
@@ -190,23 +190,19 @@ fn make_sugg(
match (&key_pat.kind, &value_pat.kind) {
(hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Binding(_, _, value_param_ident, None)) => {
Some(format!(
- "{}.retain(|{}, &mut {}| {})",
+ "{}.retain(|{key_param_ident}, &mut {value_param_ident}| {})",
snippet(cx, left_expr.span, ".."),
- key_param_ident,
- value_param_ident,
snippet(cx, filter_body.value.span, "..")
))
},
(hir::PatKind::Binding(_, _, key_param_ident, None), hir::PatKind::Wild) => Some(format!(
- "{}.retain(|{}, _| {})",
+ "{}.retain(|{key_param_ident}, _| {})",
snippet(cx, left_expr.span, ".."),
- key_param_ident,
snippet(cx, filter_body.value.span, "..")
)),
(hir::PatKind::Wild, hir::PatKind::Binding(_, _, value_param_ident, None)) => Some(format!(
- "{}.retain(|_, &mut {}| {})",
+ "{}.retain(|_, &mut {value_param_ident}| {})",
snippet(cx, left_expr.span, ".."),
- value_param_ident,
snippet(cx, filter_body.value.span, "..")
)),
_ => None,
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 7941c8c9c..0976940af 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -108,15 +108,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
};
let test_span = expr.span.until(then.span);
- span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {} manually", kind_word), |diag| {
- diag.span_note(test_span, &format!("the {} was tested here", kind_word));
+ span_lint_and_then(cx, MANUAL_STRIP, strippings[0], &format!("stripping a {kind_word} manually"), |diag| {
+ diag.span_note(test_span, &format!("the {kind_word} was tested here"));
multispan_sugg(
diag,
- &format!("try using the `strip_{}` method", kind_word),
+ &format!("try using the `strip_{kind_word}` method"),
vec![(test_span,
- format!("if let Some(<stripped>) = {}.strip_{}({}) ",
+ format!("if let Some(<stripped>) = {}.strip_{kind_word}({}) ",
snippet(cx, target_arg.span, ".."),
- kind_word,
snippet(cx, pattern.span, "..")))]
.into_iter().chain(strippings.into_iter().map(|span| (span, "<stripped>".into()))),
);
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 33d744815..32da37a86 100644
--- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs
@@ -131,12 +131,12 @@ fn reduce_unit_expression<'a>(cx: &LateContext<'_>, expr: &'a hir::Expr<'_>) ->
},
hir::ExprKind::Block(block, _) => {
match (block.stmts, block.expr.as_ref()) {
- (&[], Some(inner_expr)) => {
+ ([], Some(inner_expr)) => {
// If block only contains an expression,
// reduce `{ X }` to `X`
reduce_unit_expression(cx, inner_expr)
},
- (&[ref inner_stmt], None) => {
+ ([inner_stmt], None) => {
// If block only contains statements,
// reduce `{ X; }` to `X` or `X;`
match inner_stmt.kind {
@@ -194,10 +194,7 @@ fn let_binding_name(cx: &LateContext<'_>, var_arg: &hir::Expr<'_>) -> String {
#[must_use]
fn suggestion_msg(function_type: &str, map_type: &str) -> String {
- format!(
- "called `map(f)` on an `{0}` value where `f` is a {1} that returns the unit type `()`",
- map_type, function_type
- )
+ format!("called `map(f)` on an `{map_type}` value where `f` is a {function_type} that returns the unit type `()`")
}
fn lint_map_unit_fn(
diff --git a/src/tools/clippy/clippy_lints/src/match_result_ok.rs b/src/tools/clippy/clippy_lints/src/match_result_ok.rs
index 8588ab1ed..a020282d2 100644
--- a/src/tools/clippy/clippy_lints/src/match_result_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/match_result_ok.rs
@@ -70,9 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
let some_expr_string = snippet_with_applicability(cx, y[0].span, "", &mut applicability);
let trimmed_ok = snippet_with_applicability(cx, let_expr.span.until(ok_path.ident.span), "", &mut applicability);
let sugg = format!(
- "{} let Ok({}) = {}",
- ifwhile,
- some_expr_string,
+ "{ifwhile} let Ok({some_expr_string}) = {}",
trimmed_ok.trim().trim_end_matches('.'),
);
span_lint_and_sugg(
@@ -80,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchResultOk {
MATCH_RESULT_OK,
expr.span.with_hi(let_expr.span.hi()),
"matching on `Some` with `ok()` is redundant",
- &format!("consider matching on `Ok({})` and removing the call to `ok` instead", some_expr_string),
+ &format!("consider matching on `Ok({some_expr_string})` and removing the call to `ok` instead"),
sugg,
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
index 07021f1bc..33a052c41 100644
--- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs
@@ -1,7 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLetOrMatch;
+use clippy_utils::source::snippet;
use clippy_utils::visitors::is_local_used;
-use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq};
+use clippy_utils::{
+ is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
+};
use if_chain::if_chain;
use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
@@ -61,7 +64,8 @@ fn check_arm<'tcx>(
if !pat_contains_or(inner_then_pat);
// the binding must come from the pattern of the containing match arm
// ..<local>.. => match <local> { .. }
- if let Some(binding_span) = find_pat_binding(outer_pat, binding_id);
+ if let (Some(binding_span), is_innermost_parent_pat_struct)
+ = find_pat_binding_and_is_innermost_parent_pat_struct(outer_pat, binding_id);
// the "else" branches must be equal
if match (outer_else_body, inner_else_body) {
(None, None) => true,
@@ -86,6 +90,13 @@ fn check_arm<'tcx>(
if matches!(inner, IfLetOrMatch::Match(..)) { "match" } else { "if let" },
if outer_is_match { "match" } else { "if let" },
);
+ // collapsing patterns need an explicit field name in struct pattern matching
+ // ex: Struct {x: Some(1)}
+ let replace_msg = if is_innermost_parent_pat_struct {
+ format!(", prefixed by {}:", snippet(cx, binding_span, "their field name"))
+ } else {
+ String::new()
+ };
span_lint_and_then(
cx,
COLLAPSIBLE_MATCH,
@@ -94,7 +105,7 @@ fn check_arm<'tcx>(
|diag| {
let mut help_span = MultiSpan::from_spans(vec![binding_span, inner_then_pat.span]);
help_span.push_span_label(binding_span, "replace this binding");
- help_span.push_span_label(inner_then_pat.span, "with this pattern");
+ help_span.push_span_label(inner_then_pat.span, format!("with this pattern{replace_msg}"));
diag.span_help(help_span, "the outer pattern can be modified to include the inner pattern");
},
);
@@ -110,13 +121,14 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
}
match arm.pat.kind {
PatKind::Binding(..) | PatKind::Wild => true,
- PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
+ PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
_ => false,
}
}
-fn find_pat_binding(pat: &Pat<'_>, hir_id: HirId) -> Option<Span> {
+fn find_pat_binding_and_is_innermost_parent_pat_struct(pat: &Pat<'_>, hir_id: HirId) -> (Option<Span>, bool) {
let mut span = None;
+ let mut is_innermost_parent_pat_struct = false;
pat.walk_short(|p| match &p.kind {
// ignore OR patterns
PatKind::Or(_) => false,
@@ -127,9 +139,12 @@ fn find_pat_binding(pat: &Pat<'_>, hir_id: HirId) -> Option<Span> {
}
!found
},
- _ => true,
+ _ => {
+ is_innermost_parent_pat_struct = matches!(p.kind, PatKind::Struct(..));
+ true
+ },
});
- span
+ (span, is_innermost_parent_pat_struct)
}
fn pat_contains_or(pat: &Pat<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
new file mode 100644
index 000000000..66ba1f6f9
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_filter.rs
@@ -0,0 +1,153 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::contains_unsafe_block;
+use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
+
+use rustc_hir::LangItem::OptionSome;
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind};
+use rustc_lint::LateContext;
+use rustc_span::{sym, SyntaxContext};
+
+use super::manual_utils::{check_with, SomeExpr};
+use super::MANUAL_FILTER;
+
+// Function called on the <expr> of `[&+]Some((ref | ref mut) x) => <expr>`
+// Need to check if it's of the form `<expr>=if <cond> {<then_expr>} else {<else_expr>}`
+// AND that only one `then/else_expr` resolves to `Some(x)` while the other resolves to `None`
+// return the `cond` expression if so.
+fn get_cond_expr<'tcx>(
+ cx: &LateContext<'tcx>,
+ pat: &Pat<'_>,
+ expr: &'tcx Expr<'_>,
+ ctxt: SyntaxContext,
+) -> Option<SomeExpr<'tcx>> {
+ if_chain! {
+ if let Some(block_expr) = peels_blocks_incl_unsafe_opt(expr);
+ if let ExprKind::If(cond, then_expr, Some(else_expr)) = block_expr.kind;
+ if let PatKind::Binding(_,target, ..) = pat.kind;
+ if let (then_visitor, else_visitor)
+ = (is_some_expr(cx, target, ctxt, then_expr),
+ is_some_expr(cx, target, ctxt, else_expr));
+ if then_visitor != else_visitor; // check that one expr resolves to `Some(x)`, the other to `None`
+ then {
+ return Some(SomeExpr {
+ expr: peels_blocks_incl_unsafe(cond.peel_drop_temps()),
+ needs_unsafe_block: contains_unsafe_block(cx, expr),
+ needs_negated: !then_visitor // if the `then_expr` resolves to `None`, need to negate the cond
+ })
+ }
+ };
+ None
+}
+
+fn peels_blocks_incl_unsafe_opt<'a>(expr: &'a Expr<'a>) -> Option<&'a Expr<'a>> {
+ // we don't want to use `peel_blocks` here because we don't care if the block is unsafe, it's
+ // checked by `contains_unsafe_block`
+ if let ExprKind::Block(block, None) = expr.kind {
+ if block.stmts.is_empty() {
+ return block.expr;
+ }
+ };
+ None
+}
+
+fn peels_blocks_incl_unsafe<'a>(expr: &'a Expr<'a>) -> &'a Expr<'a> {
+ peels_blocks_incl_unsafe_opt(expr).unwrap_or(expr)
+}
+
+// function called for each <expr> expression:
+// Some(x) => if <cond> {
+// <expr>
+// } else {
+// <expr>
+// }
+// Returns true if <expr> resolves to `Some(x)`, `false` otherwise
+fn is_some_expr<'tcx>(cx: &LateContext<'_>, target: HirId, ctxt: SyntaxContext, expr: &'tcx Expr<'_>) -> bool {
+ if let Some(inner_expr) = peels_blocks_incl_unsafe_opt(expr) {
+ // there can be not statements in the block as they would be removed when switching to `.filter`
+ if let ExprKind::Call(callee, [arg]) = inner_expr.kind {
+ return ctxt == expr.span.ctxt()
+ && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome)
+ && path_to_local_id(arg, target);
+ }
+ };
+ false
+}
+
+// given the closure: `|<pattern>| <expr>`
+// returns `|&<pattern>| <expr>`
+fn add_ampersand_if_copy(body_str: String, has_copy_trait: bool) -> String {
+ if has_copy_trait {
+ let mut with_ampersand = body_str;
+ with_ampersand.insert(1, '&');
+ with_ampersand
+ } else {
+ body_str
+ }
+}
+
+pub(super) fn check_match<'tcx>(
+ cx: &LateContext<'tcx>,
+ scrutinee: &'tcx Expr<'_>,
+ arms: &'tcx [Arm<'_>],
+ expr: &'tcx Expr<'_>,
+) {
+ let ty = cx.typeck_results().expr_ty(expr);
+ if is_type_diagnostic_item(cx, ty, sym::Option)
+ && let [first_arm, second_arm] = arms
+ && first_arm.guard.is_none()
+ && second_arm.guard.is_none()
+ {
+ check(cx, expr, scrutinee, first_arm.pat, first_arm.body, Some(second_arm.pat), second_arm.body);
+ }
+}
+
+pub(super) fn check_if_let<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ let_pat: &'tcx Pat<'_>,
+ let_expr: &'tcx Expr<'_>,
+ then_expr: &'tcx Expr<'_>,
+ else_expr: &'tcx Expr<'_>,
+) {
+ check(cx, expr, let_expr, let_pat, then_expr, None, else_expr);
+}
+
+fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ scrutinee: &'tcx Expr<'_>,
+ then_pat: &'tcx Pat<'_>,
+ then_body: &'tcx Expr<'_>,
+ else_pat: Option<&'tcx Pat<'_>>,
+ else_body: &'tcx Expr<'_>,
+) {
+ if let Some(sugg_info) = check_with(
+ cx,
+ expr,
+ scrutinee,
+ then_pat,
+ then_body,
+ else_pat,
+ else_body,
+ get_cond_expr,
+ ) {
+ let body_str = add_ampersand_if_copy(sugg_info.body_str, sugg_info.scrutinee_impl_copy);
+ span_lint_and_sugg(
+ cx,
+ MANUAL_FILTER,
+ expr.span,
+ "manual implementation of `Option::filter`",
+ "try this",
+ if sugg_info.needs_brackets {
+ format!(
+ "{{ {}{}.filter({body_str}) }}",
+ sugg_info.scrutinee_str, sugg_info.as_ref_str
+ )
+ } else {
+ format!("{}{}.filter({body_str})", sugg_info.scrutinee_str, sugg_info.as_ref_str)
+ },
+ sugg_info.app,
+ );
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
index b0198e856..aaba23967 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_map.rs
@@ -1,22 +1,13 @@
-use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
+use super::manual_utils::{check_with, SomeExpr};
+use super::MANUAL_MAP;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
-use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
-use clippy_utils::{
- can_move_expr_to_closure, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id, peel_blocks,
- peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
-};
-use rustc_ast::util::parser::PREC_POSTFIX;
-use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionNone, OptionSome};
-use rustc_hir::{
- def::Res, Arm, BindingAnnotation, Block, BlockCheckMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path,
- QPath, UnsafeSource,
-};
-use rustc_lint::LateContext;
-use rustc_span::{sym, SyntaxContext};
-use super::MANUAL_MAP;
+use clippy_utils::{is_res_lang_ctor, path_res};
+
+use rustc_hir::LangItem::OptionSome;
+use rustc_hir::{Arm, Block, BlockCheckMode, Expr, ExprKind, Pat, UnsafeSource};
+use rustc_lint::LateContext;
+use rustc_span::SyntaxContext;
pub(super) fn check_match<'tcx>(
cx: &LateContext<'tcx>,
@@ -43,7 +34,6 @@ pub(super) fn check_if_let<'tcx>(
check(cx, expr, let_expr, let_pat, then_expr, None, else_expr);
}
-#[expect(clippy::too_many_lines)]
fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
@@ -53,254 +43,74 @@ fn check<'tcx>(
else_pat: Option<&'tcx Pat<'_>>,
else_body: &'tcx Expr<'_>,
) {
- let (scrutinee_ty, ty_ref_count, ty_mutability) =
- peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee));
- if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::Option)
- && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Option))
- {
- return;
- }
-
- let expr_ctxt = expr.span.ctxt();
- let (some_expr, some_pat, pat_ref_count, is_wild_none) = match (
- try_parse_pattern(cx, then_pat, expr_ctxt),
- else_pat.map_or(Some(OptionPat::Wild), |p| try_parse_pattern(cx, p, expr_ctxt)),
+ if let Some(sugg_info) = check_with(
+ cx,
+ expr,
+ scrutinee,
+ then_pat,
+ then_body,
+ else_pat,
+ else_body,
+ get_some_expr,
) {
- (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
- (else_body, pattern, ref_count, true)
- },
- (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
- (else_body, pattern, ref_count, false)
- },
- (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_body) => {
- (then_body, pattern, ref_count, true)
- },
- (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_body) => {
- (then_body, pattern, ref_count, false)
- },
- _ => return,
- };
-
- // Top level or patterns aren't allowed in closures.
- if matches!(some_pat.kind, PatKind::Or(_)) {
- return;
- }
-
- let some_expr = match get_some_expr(cx, some_expr, false, expr_ctxt) {
- Some(expr) => expr,
- None => return,
- };
-
- // These two lints will go back and forth with each other.
- if cx.typeck_results().expr_ty(some_expr.expr) == cx.tcx.types.unit
- && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id)
- {
- return;
- }
-
- // `map` won't perform any adjustments.
- if !cx.typeck_results().expr_adjustments(some_expr.expr).is_empty() {
- return;
- }
-
- // Determine which binding mode to use.
- let explicit_ref = some_pat.contains_explicit_ref_binding();
- let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then_some(ty_mutability));
-
- let as_ref_str = match binding_ref {
- Some(Mutability::Mut) => ".as_mut()",
- Some(Mutability::Not) => ".as_ref()",
- None => "",
- };
-
- match can_move_expr_to_closure(cx, some_expr.expr) {
- Some(captures) => {
- // Check if captures the closure will need conflict with borrows made in the scrutinee.
- // TODO: check all the references made in the scrutinee expression. This will require interacting
- // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
- if let Some(binding_ref_mutability) = binding_ref {
- let e = peel_hir_expr_while(scrutinee, |e| match e.kind {
- ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
- _ => None,
- });
- if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
- match captures.get(l) {
- Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return,
- Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
- return;
- },
- Some(CaptureKind::Ref(Mutability::Not)) | None => (),
- }
- }
- }
- },
- None => return,
- };
-
- let mut app = Applicability::MachineApplicable;
-
- // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or
- // it's being passed by value.
- let scrutinee = peel_hir_expr_refs(scrutinee).0;
- let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
- let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
- format!("({})", scrutinee_str)
- } else {
- scrutinee_str.into()
- };
-
- let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
- if_chain! {
- if !some_expr.needs_unsafe_block;
- if let Some(func) = can_pass_as_func(cx, id, some_expr.expr);
- if func.span.ctxt() == some_expr.expr.span.ctxt();
- then {
- snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
+ span_lint_and_sugg(
+ cx,
+ MANUAL_MAP,
+ expr.span,
+ "manual implementation of `Option::map`",
+ "try this",
+ if sugg_info.needs_brackets {
+ format!(
+ "{{ {}{}.map({}) }}",
+ sugg_info.scrutinee_str, sugg_info.as_ref_str, sugg_info.body_str
+ )
} else {
- if path_to_local_id(some_expr.expr, id)
- && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
- && binding_ref.is_some()
- {
- return;
- }
-
- // `ref` and `ref mut` annotations were handled earlier.
- let annotation = if matches!(annotation, BindingAnnotation::MUT) {
- "mut "
- } else {
- ""
- };
- let expr_snip = snippet_with_context(cx, some_expr.expr.span, expr_ctxt, "..", &mut app).0;
- if some_expr.needs_unsafe_block {
- format!("|{}{}| unsafe {{ {} }}", annotation, some_binding, expr_snip)
- } else {
- format!("|{}{}| {}", annotation, some_binding, expr_snip)
- }
- }
- }
- } else if !is_wild_none && explicit_ref.is_none() {
- // TODO: handle explicit reference annotations.
- let pat_snip = snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0;
- let expr_snip = snippet_with_context(cx, some_expr.expr.span, expr_ctxt, "..", &mut app).0;
- if some_expr.needs_unsafe_block {
- format!("|{}| unsafe {{ {} }}", pat_snip, expr_snip)
- } else {
- format!("|{}| {}", pat_snip, expr_snip)
- }
- } else {
- // Refutable bindings and mixed reference annotations can't be handled by `map`.
- return;
- };
-
- span_lint_and_sugg(
- cx,
- MANUAL_MAP,
- expr.span,
- "manual implementation of `Option::map`",
- "try this",
- if else_pat.is_none() && is_else_clause(cx.tcx, expr) {
- format!("{{ {}{}.map({}) }}", scrutinee_str, as_ref_str, body_str)
- } else {
- format!("{}{}.map({})", scrutinee_str, as_ref_str, body_str)
- },
- app,
- );
-}
-
-// Checks whether the expression could be passed as a function, or whether a closure is needed.
-// Returns the function to be passed to `map` if it exists.
-fn can_pass_as_func<'tcx>(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
- match expr.kind {
- ExprKind::Call(func, [arg])
- if path_to_local_id(arg, binding)
- && cx.typeck_results().expr_adjustments(arg).is_empty()
- && !type_is_unsafe_function(cx, cx.typeck_results().expr_ty(func).peel_refs()) =>
- {
- Some(func)
- },
- _ => None,
- }
-}
-
-enum OptionPat<'a> {
- Wild,
- None,
- Some {
- // The pattern contained in the `Some` tuple.
- pattern: &'a Pat<'a>,
- // The number of references before the `Some` tuple.
- // e.g. `&&Some(_)` has a ref count of 2.
- ref_count: usize,
- },
-}
-
-struct SomeExpr<'tcx> {
- expr: &'tcx Expr<'tcx>,
- needs_unsafe_block: bool,
-}
-
-// Try to parse into a recognized `Option` pattern.
-// i.e. `_`, `None`, `Some(..)`, or a reference to any of those.
-fn try_parse_pattern<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: SyntaxContext) -> Option<OptionPat<'tcx>> {
- fn f<'tcx>(
- cx: &LateContext<'tcx>,
- pat: &'tcx Pat<'_>,
- ref_count: usize,
- ctxt: SyntaxContext,
- ) -> Option<OptionPat<'tcx>> {
- match pat.kind {
- PatKind::Wild => Some(OptionPat::Wild),
- PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
- PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None),
- PatKind::TupleStruct(ref qpath, [pattern], _)
- if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt =>
- {
- Some(OptionPat::Some { pattern, ref_count })
+ format!(
+ "{}{}.map({})",
+ sugg_info.scrutinee_str, sugg_info.as_ref_str, sugg_info.body_str
+ )
},
- _ => None,
- }
+ sugg_info.app,
+ );
}
- f(cx, pat, 0, ctxt)
}
// Checks for an expression wrapped by the `Some` constructor. Returns the contained expression.
fn get_some_expr<'tcx>(
cx: &LateContext<'tcx>,
+ _: &'tcx Pat<'_>,
expr: &'tcx Expr<'_>,
- needs_unsafe_block: bool,
ctxt: SyntaxContext,
) -> Option<SomeExpr<'tcx>> {
- // TODO: Allow more complex expressions.
- match expr.kind {
- ExprKind::Call(
- Expr {
- kind: ExprKind::Path(ref qpath),
- ..
- },
- [arg],
- ) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(SomeExpr {
- expr: arg,
- needs_unsafe_block,
- }),
- ExprKind::Block(
- Block {
- stmts: [],
- expr: Some(expr),
- rules,
- ..
+ fn get_some_expr_internal<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ needs_unsafe_block: bool,
+ ctxt: SyntaxContext,
+ ) -> Option<SomeExpr<'tcx>> {
+ // TODO: Allow more complex expressions.
+ match expr.kind {
+ ExprKind::Call(callee, [arg])
+ if ctxt == expr.span.ctxt() && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) =>
+ {
+ Some(SomeExpr::new_no_negated(arg, needs_unsafe_block))
},
- _,
- ) => get_some_expr(
- cx,
- expr,
- needs_unsafe_block || *rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
- ctxt,
- ),
- _ => None,
+ ExprKind::Block(
+ Block {
+ stmts: [],
+ expr: Some(expr),
+ rules,
+ ..
+ },
+ _,
+ ) => get_some_expr_internal(
+ cx,
+ expr,
+ needs_unsafe_block || *rules == BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided),
+ ctxt,
+ ),
+ _ => None,
+ }
}
-}
-
-// Checks for the `None` value.
-fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
- matches!(peel_blocks(expr).kind, ExprKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
+ get_some_expr_internal(cx, expr, false, ctxt)
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index e1111c80f..587c926dc 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
@@ -3,12 +3,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
-use clippy_utils::{is_lang_ctor, path_to_local_id, sugg};
+use clippy_utils::{is_res_lang_ctor, path_to_local_id, sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::LangItem::{OptionNone, ResultErr};
use rustc_hir::{Arm, Expr, PatKind};
use rustc_lint::LateContext;
+use rustc_middle::ty::DefIdTree;
use rustc_span::sym;
use super::MANUAL_UNWRAP_OR;
@@ -42,12 +44,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, scrutinee:
span_lint_and_sugg(
cx,
MANUAL_UNWRAP_OR, expr.span,
- &format!("this pattern reimplements `{}::unwrap_or`", ty_name),
+ &format!("this pattern reimplements `{ty_name}::unwrap_or`"),
"replace with",
format!(
- "{}.unwrap_or({})",
- suggestion,
- reindented_or_body,
+ "{suggestion}.unwrap_or({reindented_or_body})",
),
Applicability::MachineApplicable,
);
@@ -61,15 +61,19 @@ fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'
if arms.iter().all(|arm| arm.guard.is_none());
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
match arm.pat.kind {
- PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
+ PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [pat], _) =>
- matches!(pat.kind, PatKind::Wild) && is_lang_ctor(cx, qpath, ResultErr),
+ matches!(pat.kind, PatKind::Wild)
+ && is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr),
_ => false,
}
});
let unwrap_arm = &arms[1 - idx];
if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
- if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
+ if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.pat.hir_id);
+ if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
+ if cx.tcx.lang_items().option_some_variant() == Some(variant_id)
+ || cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
if path_to_local_id(unwrap_arm.body, binding_hir_id);
if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty();
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
new file mode 100644
index 000000000..5b7644a53
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs
@@ -0,0 +1,277 @@
+use crate::{map_unit_fn::OPTION_MAP_UNIT_FN, matches::MATCH_AS_REF};
+use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
+use clippy_utils::ty::{is_copy, is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
+use clippy_utils::{
+ can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
+ peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, sugg::Sugg, CaptureKind,
+};
+use rustc_ast::util::parser::PREC_POSTFIX;
+use rustc_errors::Applicability;
+use rustc_hir::LangItem::{OptionNone, OptionSome};
+use rustc_hir::{def::Res, BindingAnnotation, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
+use rustc_lint::LateContext;
+use rustc_span::{sym, SyntaxContext};
+
+#[expect(clippy::too_many_arguments)]
+#[expect(clippy::too_many_lines)]
+pub(super) fn check_with<'tcx, F>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ scrutinee: &'tcx Expr<'_>,
+ then_pat: &'tcx Pat<'_>,
+ then_body: &'tcx Expr<'_>,
+ else_pat: Option<&'tcx Pat<'_>>,
+ else_body: &'tcx Expr<'_>,
+ get_some_expr_fn: F,
+) -> Option<SuggInfo<'tcx>>
+where
+ F: Fn(&LateContext<'tcx>, &'tcx Pat<'_>, &'tcx Expr<'_>, SyntaxContext) -> Option<SomeExpr<'tcx>>,
+{
+ let (scrutinee_ty, ty_ref_count, ty_mutability) =
+ peel_mid_ty_refs_is_mutable(cx.typeck_results().expr_ty(scrutinee));
+ if !(is_type_diagnostic_item(cx, scrutinee_ty, sym::Option)
+ && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(expr), sym::Option))
+ {
+ return None;
+ }
+
+ let expr_ctxt = expr.span.ctxt();
+ let (some_expr, some_pat, pat_ref_count, is_wild_none) = match (
+ try_parse_pattern(cx, then_pat, expr_ctxt),
+ else_pat.map_or(Some(OptionPat::Wild), |p| try_parse_pattern(cx, p, expr_ctxt)),
+ ) {
+ (Some(OptionPat::Wild), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
+ (else_body, pattern, ref_count, true)
+ },
+ (Some(OptionPat::None), Some(OptionPat::Some { pattern, ref_count })) if is_none_expr(cx, then_body) => {
+ (else_body, pattern, ref_count, false)
+ },
+ (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::Wild)) if is_none_expr(cx, else_body) => {
+ (then_body, pattern, ref_count, true)
+ },
+ (Some(OptionPat::Some { pattern, ref_count }), Some(OptionPat::None)) if is_none_expr(cx, else_body) => {
+ (then_body, pattern, ref_count, false)
+ },
+ _ => return None,
+ };
+
+ // Top level or patterns aren't allowed in closures.
+ if matches!(some_pat.kind, PatKind::Or(_)) {
+ return None;
+ }
+
+ let Some(some_expr) = get_some_expr_fn(cx, some_pat, some_expr, expr_ctxt) else {
+ return None;
+ };
+
+ // These two lints will go back and forth with each other.
+ if cx.typeck_results().expr_ty(some_expr.expr) == cx.tcx.types.unit
+ && !is_lint_allowed(cx, OPTION_MAP_UNIT_FN, expr.hir_id)
+ {
+ return None;
+ }
+
+ // `map` won't perform any adjustments.
+ if !cx.typeck_results().expr_adjustments(some_expr.expr).is_empty() {
+ return None;
+ }
+
+ // Determine which binding mode to use.
+ let explicit_ref = some_pat.contains_explicit_ref_binding();
+ let binding_ref = explicit_ref.or_else(|| (ty_ref_count != pat_ref_count).then_some(ty_mutability));
+
+ let as_ref_str = match binding_ref {
+ Some(Mutability::Mut) => ".as_mut()",
+ Some(Mutability::Not) => ".as_ref()",
+ None => "",
+ };
+
+ match can_move_expr_to_closure(cx, some_expr.expr) {
+ Some(captures) => {
+ // Check if captures the closure will need conflict with borrows made in the scrutinee.
+ // TODO: check all the references made in the scrutinee expression. This will require interacting
+ // with the borrow checker. Currently only `<local>[.<field>]*` is checked for.
+ if let Some(binding_ref_mutability) = binding_ref {
+ let e = peel_hir_expr_while(scrutinee, |e| match e.kind {
+ ExprKind::Field(e, _) | ExprKind::AddrOf(_, _, e) => Some(e),
+ _ => None,
+ });
+ if let ExprKind::Path(QPath::Resolved(None, Path { res: Res::Local(l), .. })) = e.kind {
+ match captures.get(l) {
+ Some(CaptureKind::Value | CaptureKind::Ref(Mutability::Mut)) => return None,
+ Some(CaptureKind::Ref(Mutability::Not)) if binding_ref_mutability == Mutability::Mut => {
+ return None;
+ },
+ Some(CaptureKind::Ref(Mutability::Not)) | None => (),
+ }
+ }
+ }
+ },
+ None => return None,
+ };
+
+ let mut app = Applicability::MachineApplicable;
+
+ // Remove address-of expressions from the scrutinee. Either `as_ref` will be called, or
+ // it's being passed by value.
+ let scrutinee = peel_hir_expr_refs(scrutinee).0;
+ let (scrutinee_str, _) = snippet_with_context(cx, scrutinee.span, expr_ctxt, "..", &mut app);
+ let scrutinee_str = if scrutinee.span.ctxt() == expr.span.ctxt() && scrutinee.precedence().order() < PREC_POSTFIX {
+ format!("({scrutinee_str})")
+ } else {
+ scrutinee_str.into()
+ };
+
+ let closure_expr_snip = some_expr.to_snippet_with_context(cx, expr_ctxt, &mut app);
+ let body_str = if let PatKind::Binding(annotation, id, some_binding, None) = some_pat.kind {
+ if_chain! {
+ if !some_expr.needs_unsafe_block;
+ if let Some(func) = can_pass_as_func(cx, id, some_expr.expr);
+ if func.span.ctxt() == some_expr.expr.span.ctxt();
+ then {
+ snippet_with_applicability(cx, func.span, "..", &mut app).into_owned()
+ } else {
+ if path_to_local_id(some_expr.expr, id)
+ && !is_lint_allowed(cx, MATCH_AS_REF, expr.hir_id)
+ && binding_ref.is_some()
+ {
+ return None;
+ }
+
+ // `ref` and `ref mut` annotations were handled earlier.
+ let annotation = if matches!(annotation, BindingAnnotation::MUT) {
+ "mut "
+ } else {
+ ""
+ };
+
+ if some_expr.needs_unsafe_block {
+ format!("|{annotation}{some_binding}| unsafe {{ {closure_expr_snip} }}")
+ } else {
+ format!("|{annotation}{some_binding}| {closure_expr_snip}")
+ }
+ }
+ }
+ } else if !is_wild_none && explicit_ref.is_none() {
+ // TODO: handle explicit reference annotations.
+ let pat_snip = snippet_with_context(cx, some_pat.span, expr_ctxt, "..", &mut app).0;
+ if some_expr.needs_unsafe_block {
+ format!("|{pat_snip}| unsafe {{ {closure_expr_snip} }}")
+ } else {
+ format!("|{pat_snip}| {closure_expr_snip}")
+ }
+ } else {
+ // Refutable bindings and mixed reference annotations can't be handled by `map`.
+ return None;
+ };
+
+ // relies on the fact that Option<T>: Copy where T: copy
+ let scrutinee_impl_copy = is_copy(cx, scrutinee_ty);
+
+ Some(SuggInfo {
+ needs_brackets: else_pat.is_none() && is_else_clause(cx.tcx, expr),
+ scrutinee_impl_copy,
+ scrutinee_str,
+ as_ref_str,
+ body_str,
+ app,
+ })
+}
+
+pub struct SuggInfo<'a> {
+ pub needs_brackets: bool,
+ pub scrutinee_impl_copy: bool,
+ pub scrutinee_str: String,
+ pub as_ref_str: &'a str,
+ pub body_str: String,
+ pub app: Applicability,
+}
+
+// Checks whether the expression could be passed as a function, or whether a closure is needed.
+// Returns the function to be passed to `map` if it exists.
+fn can_pass_as_func<'tcx>(cx: &LateContext<'tcx>, binding: HirId, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
+ match expr.kind {
+ ExprKind::Call(func, [arg])
+ if path_to_local_id(arg, binding)
+ && cx.typeck_results().expr_adjustments(arg).is_empty()
+ && !type_is_unsafe_function(cx, cx.typeck_results().expr_ty(func).peel_refs()) =>
+ {
+ Some(func)
+ },
+ _ => None,
+ }
+}
+
+#[derive(Debug)]
+pub(super) enum OptionPat<'a> {
+ Wild,
+ None,
+ Some {
+ // The pattern contained in the `Some` tuple.
+ pattern: &'a Pat<'a>,
+ // The number of references before the `Some` tuple.
+ // e.g. `&&Some(_)` has a ref count of 2.
+ ref_count: usize,
+ },
+}
+
+pub(super) struct SomeExpr<'tcx> {
+ pub expr: &'tcx Expr<'tcx>,
+ pub needs_unsafe_block: bool,
+ pub needs_negated: bool, // for `manual_filter` lint
+}
+
+impl<'tcx> SomeExpr<'tcx> {
+ pub fn new_no_negated(expr: &'tcx Expr<'tcx>, needs_unsafe_block: bool) -> Self {
+ Self {
+ expr,
+ needs_unsafe_block,
+ needs_negated: false,
+ }
+ }
+
+ pub fn to_snippet_with_context(
+ &self,
+ cx: &LateContext<'tcx>,
+ ctxt: SyntaxContext,
+ app: &mut Applicability,
+ ) -> Sugg<'tcx> {
+ let sugg = Sugg::hir_with_context(cx, self.expr, ctxt, "..", app);
+ if self.needs_negated { !sugg } else { sugg }
+ }
+}
+
+// Try to parse into a recognized `Option` pattern.
+// i.e. `_`, `None`, `Some(..)`, or a reference to any of those.
+pub(super) fn try_parse_pattern<'tcx>(
+ cx: &LateContext<'tcx>,
+ pat: &'tcx Pat<'_>,
+ ctxt: SyntaxContext,
+) -> Option<OptionPat<'tcx>> {
+ fn f<'tcx>(
+ cx: &LateContext<'tcx>,
+ pat: &'tcx Pat<'_>,
+ ref_count: usize,
+ ctxt: SyntaxContext,
+ ) -> Option<OptionPat<'tcx>> {
+ match pat.kind {
+ PatKind::Wild => Some(OptionPat::Wild),
+ PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
+ PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => {
+ Some(OptionPat::None)
+ },
+ PatKind::TupleStruct(ref qpath, [pattern], _)
+ if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt =>
+ {
+ Some(OptionPat::Some { pattern, ref_count })
+ },
+ _ => None,
+ }
+ }
+ f(cx, pat, 0, ctxt)
+}
+
+// Checks for the `None` value.
+fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+ is_res_lang_ctor(cx, path_res(cx, peel_blocks(expr)), OptionNone)
+}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
index 91d17f481..2818f030b 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_lang_ctor, peel_blocks};
+use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
use rustc_lint::LateContext;
@@ -45,13 +45,11 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
cx,
MATCH_AS_REF,
expr.span,
- &format!("use `{}()` instead", suggestion),
+ &format!("use `{suggestion}()` instead"),
"try this",
format!(
- "{}.{}(){}",
+ "{}.{suggestion}(){cast}",
snippet_with_applicability(cx, ex.span, "_", &mut applicability),
- suggestion,
- cast,
),
applicability,
);
@@ -61,18 +59,20 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
// Checks if arm has the form `None => None`
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
- matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, LangItem::OptionNone))
+ matches!(
+ arm.pat.kind,
+ PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
+ )
}
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
if_chain! {
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
- if is_lang_ctor(cx, qpath, LangItem::OptionSome);
+ if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome);
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
- if let ExprKind::Path(ref some_path) = e.kind;
- if is_lang_ctor(cx, some_path, LangItem::OptionSome);
+ if is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome);
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
then {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
index 34cc08268..107fad323 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_like_matches.rs
@@ -112,7 +112,7 @@ where
.join(" | ")
};
let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
- format!("{} if {}", pat, snippet_with_applicability(cx, g.span, "..", &mut applicability))
+ format!("{pat} if {}", snippet_with_applicability(cx, g.span, "..", &mut applicability))
} else {
pat
};
@@ -131,10 +131,9 @@ where
&format!("{} expression looks like `matches!` macro", if is_if_let { "if let .. else" } else { "match" }),
"try this",
format!(
- "{}matches!({}, {})",
+ "{}matches!({}, {pat_and_guard})",
if b0 { "" } else { "!" },
snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
- pat_and_guard,
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
index d37f44d4a..168c1e4d2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
@@ -134,7 +134,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
diag.span_suggestion(
keep_arm.pat.span,
"try merging the arm patterns",
- format!("{} | {}", keep_pat_snip, move_pat_snip),
+ format!("{keep_pat_snip} | {move_pat_snip}"),
Applicability::MaybeIncorrect,
)
.help("or try changing either arm body")
@@ -221,7 +221,6 @@ fn iter_matching_struct_fields<'a>(
#[expect(clippy::similar_names)]
impl<'a> NormalizedPat<'a> {
- #[expect(clippy::too_many_lines)]
fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self {
match pat.kind {
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
@@ -235,9 +234,8 @@ impl<'a> NormalizedPat<'a> {
Self::Struct(cx.qpath_res(path, pat.hir_id).opt_def_id(), fields)
},
PatKind::TupleStruct(ref path, pats, wild_idx) => {
- let adt = match cx.typeck_results().pat_ty(pat).ty_adt_def() {
- Some(x) => x,
- None => return Self::Wild,
+ let Some(adt) = cx.typeck_results().pat_ty(pat).ty_adt_def() else {
+ return Self::Wild
};
let (var_id, variant) = if adt.is_enum() {
match cx.qpath_res(path, pat.hir_id).opt_def_id() {
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
index 5ae4a65ac..1bf8d4e96 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs
@@ -58,6 +58,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
&snippet_body,
&mut applicability,
Some(span),
+ true,
);
span_lint_and_sugg(
@@ -75,12 +76,11 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
Some(AssignmentExpr::Local { span, pat_span }) => (
span,
format!(
- "let {} = {};\n{}let {} = {};",
+ "let {} = {};\n{}let {} = {snippet_body};",
snippet_with_applicability(cx, bind_names, "..", &mut applicability),
snippet_with_applicability(cx, matched_vars, "..", &mut applicability),
" ".repeat(indent_of(cx, expr.span).unwrap_or(0)),
- snippet_with_applicability(cx, pat_span, "..", &mut applicability),
- snippet_body
+ snippet_with_applicability(cx, pat_span, "..", &mut applicability)
),
),
None => {
@@ -91,6 +91,7 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
&snippet_body,
&mut applicability,
None,
+ true,
);
(expr.span, sugg)
},
@@ -108,12 +109,14 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e
},
PatKind::Wild => {
if ex.can_have_side_effects() {
- let indent = " ".repeat(indent_of(cx, expr.span).unwrap_or(0));
- let sugg = format!(
- "{};\n{}{}",
- snippet_with_applicability(cx, ex.span, "..", &mut applicability),
- indent,
- snippet_body
+ let sugg = sugg_with_curlies(
+ cx,
+ (ex, expr),
+ (bind_names, matched_vars),
+ &snippet_body,
+ &mut applicability,
+ None,
+ false,
);
span_lint_and_sugg(
@@ -172,16 +175,17 @@ fn sugg_with_curlies<'a>(
snippet_body: &str,
applicability: &mut Applicability,
assignment: Option<Span>,
+ needs_var_binding: bool,
) -> String {
let mut indent = " ".repeat(indent_of(cx, ex.span).unwrap_or(0));
let (mut cbrace_start, mut cbrace_end) = (String::new(), String::new());
if let Some(parent_expr) = get_parent_expr(cx, match_expr) {
if let ExprKind::Closure { .. } = parent_expr.kind {
- cbrace_end = format!("\n{}}}", indent);
+ cbrace_end = format!("\n{indent}}}");
// Fix body indent due to the closure
indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
- cbrace_start = format!("{{\n{}", indent);
+ cbrace_start = format!("{{\n{indent}");
}
}
@@ -190,10 +194,10 @@ fn sugg_with_curlies<'a>(
let parent_node_id = cx.tcx.hir().get_parent_node(match_expr.hir_id);
if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) {
if let ExprKind::Match(..) = arm.body.kind {
- cbrace_end = format!("\n{}}}", indent);
+ cbrace_end = format!("\n{indent}}}");
// Fix body indent due to the match
indent = " ".repeat(indent_of(cx, bind_names).unwrap_or(0));
- cbrace_start = format!("{{\n{}", indent);
+ cbrace_start = format!("{{\n{indent}");
}
}
@@ -203,14 +207,15 @@ fn sugg_with_curlies<'a>(
s
});
- format!(
- "{}let {} = {};\n{}{}{}{}",
- cbrace_start,
- snippet_with_applicability(cx, bind_names, "..", applicability),
- snippet_with_applicability(cx, matched_vars, "..", applicability),
- indent,
- assignment_str,
- snippet_body,
- cbrace_end
- )
+ let scrutinee = if needs_var_binding {
+ format!(
+ "let {} = {}",
+ snippet_with_applicability(cx, bind_names, "..", applicability),
+ snippet_with_applicability(cx, matched_vars, "..", applicability)
+ )
+ } else {
+ snippet_with_applicability(cx, matched_vars, "..", applicability).to_string()
+ };
+
+ format!("{cbrace_start}{scrutinee};\n{indent}{assignment_str}{snippet_body}{cbrace_end}")
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index 1e80b6cf2..6647322ca 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -118,8 +118,8 @@ fn lint(cx: &LateContext<'_>, case_method: &CaseMethod, bad_case_span: Span, bad
MATCH_STR_CASE_MISMATCH,
bad_case_span,
"this `match` arm has a differing case than its expression",
- &format!("consider changing the case of this arm to respect `{}`", method_str),
- format!("\"{}\"", suggestion),
+ &format!("consider changing the case of this arm to respect `{method_str}`"),
+ format!("\"{suggestion}\""),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
index a3aa2e4b3..42f1e2629 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_err_arm.rs
@@ -38,7 +38,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &Expr<'tcx>, arms: &[Arm<'
span_lint_and_note(cx,
MATCH_WILD_ERR_ARM,
arm.pat.span,
- &format!("`Err({})` matches all errors", ident_bind_name),
+ &format!("`Err({ident_bind_name})` matches all errors"),
None,
"match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable",
);
diff --git a/src/tools/clippy/clippy_lints/src/matches/mod.rs b/src/tools/clippy/clippy_lints/src/matches/mod.rs
index e6b183fc0..7d8171ead 100644
--- a/src/tools/clippy/clippy_lints/src/matches/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/mod.rs
@@ -1,7 +1,9 @@
mod collapsible_match;
mod infallible_destructuring_match;
+mod manual_filter;
mod manual_map;
mod manual_unwrap_or;
+mod manual_utils;
mod match_as_ref;
mod match_bool;
mod match_like_matches;
@@ -898,6 +900,34 @@ declare_clippy_lint! {
"reimplementation of `map`"
}
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for usages of `match` which could be implemented using `filter`
+ ///
+ /// ### Why is this bad?
+ /// Using the `filter` method is clearer and more concise.
+ ///
+ /// ### Example
+ /// ```rust
+ /// match Some(0) {
+ /// Some(x) => if x % 2 == 0 {
+ /// Some(x)
+ /// } else {
+ /// None
+ /// },
+ /// None => None,
+ /// };
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// Some(0).filter(|&x| x % 2 == 0);
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub MANUAL_FILTER,
+ complexity,
+ "reimplentation of `filter`"
+}
+
#[derive(Default)]
pub struct Matches {
msrv: Option<RustcVersion>,
@@ -939,6 +969,7 @@ impl_lint_pass!(Matches => [
SIGNIFICANT_DROP_IN_SCRUTINEE,
TRY_ERR,
MANUAL_MAP,
+ MANUAL_FILTER,
]);
impl<'tcx> LateLintPass<'tcx> for Matches {
@@ -988,6 +1019,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
if !in_constant(cx, expr.hir_id) {
manual_unwrap_or::check(cx, expr, ex, arms);
manual_map::check_match(cx, expr, ex, arms);
+ manual_filter::check_match(cx, ex, arms, expr);
}
if self.infallible_destructuring_match_linted {
@@ -1014,6 +1046,14 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
}
if !in_constant(cx, expr.hir_id) {
manual_map::check_if_let(cx, expr, if_let.let_pat, if_let.let_expr, if_let.if_then, else_expr);
+ manual_filter::check_if_let(
+ cx,
+ expr,
+ if_let.let_pat,
+ if_let.let_expr,
+ if_let.if_then,
+ else_expr,
+ );
}
}
redundant_pattern_match::check_if_let(
diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
index 634eef82e..c4f6852ae 100644
--- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs
@@ -3,15 +3,15 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
use clippy_utils::{
- eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_lang_ctor, over,
+ eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_res_lang_ctor, over, path_res,
peel_blocks_with_stmt,
};
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, FnRetTy, Guard, Node, Pat, PatKind, Path, QPath};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::LateContext;
use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
pub(crate) fn check_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) {
if arms.len() > 1 && expr_ty_matches_p_ty(cx, ex, expr) && check_all_arms(cx, ex, arms) {
@@ -112,10 +112,7 @@ fn check_if_let_inner(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool
let ret = strip_return(else_expr);
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
- if let ExprKind::Path(ref qpath) = ret.kind {
- return is_lang_ctor(cx, qpath, OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
- }
- return false;
+ return is_res_lang_ctor(cx, path_res(cx, ret), OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
}
return eq_expr_value(cx, if_let.let_expr, ret);
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
index c89784065..81bebff34 100644
--- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs
@@ -4,11 +4,12 @@ use clippy_utils::source::snippet;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
-use clippy_utils::{higher, is_lang_ctor, is_trait_method};
+use clippy_utils::{higher, is_trait_method};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::LangItem::{self, OptionSome, OptionNone, PollPending, PollReady, ResultOk, ResultErr};
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty};
@@ -87,15 +88,21 @@ fn find_sugg_for_if_let<'tcx>(
}
},
PatKind::Path(ref path) => {
- let method = if is_lang_ctor(cx, path, OptionNone) {
- "is_none()"
- } else if is_lang_ctor(cx, path, PollPending) {
- "is_pending()"
+ if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id)
+ && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
+ {
+ let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) {
+ "is_none()"
+ } else if cx.tcx.lang_items().poll_pending_variant() == Some(variant_id) {
+ "is_pending()"
+ } else {
+ return;
+ };
+ // `None` and `Pending` don't have an inner type.
+ (method, cx.tcx.types.unit)
} else {
return;
- };
- // `None` and `Pending` don't have an inner type.
- (method, cx.tcx.types.unit)
+ }
},
_ => return,
};
@@ -138,7 +145,7 @@ fn find_sugg_for_if_let<'tcx>(
cx,
REDUNDANT_PATTERN_MATCHING,
let_pat.span,
- &format!("redundant pattern matching, consider using `{}`", good_method),
+ &format!("redundant pattern matching, consider using `{good_method}`"),
|diag| {
// if/while let ... = ... { ... }
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -162,7 +169,7 @@ fn find_sugg_for_if_let<'tcx>(
.maybe_par()
.to_string();
- diag.span_suggestion(span, "try this", format!("{} {}.{}", keyword, sugg, good_method), app);
+ diag.span_suggestion(span, "try this", format!("{keyword} {sugg}.{good_method}"), app);
if needs_drop {
diag.note("this will change drop order of the result, as well as all temporaries");
@@ -213,7 +220,6 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
if patterns.len() == 1 =>
{
if let PatKind::Wild = patterns[0].kind {
-
find_good_method_for_match(
cx,
arms,
@@ -253,12 +259,12 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
cx,
REDUNDANT_PATTERN_MATCHING,
expr.span,
- &format!("redundant pattern matching, consider using `{}`", good_method),
+ &format!("redundant pattern matching, consider using `{good_method}`"),
|diag| {
diag.span_suggestion(
span,
"try this",
- format!("{}.{}", snippet(cx, result_expr.span, "_"), good_method),
+ format!("{}.{good_method}", snippet(cx, result_expr.span, "_")),
Applicability::MaybeIncorrect, // snippet
);
},
@@ -269,8 +275,8 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
#[derive(Clone, Copy)]
enum Item {
- Lang(LangItem),
- Diag(Symbol, Symbol),
+ Lang(LangItem),
+ Diag(Symbol, Symbol),
}
fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expected_item: Item) -> bool {
@@ -285,15 +291,16 @@ fn is_pat_variant(cx: &LateContext<'_>, pat: &Pat<'_>, path: &QPath<'_>, expecte
let ty = cx.typeck_results().pat_ty(pat);
if is_type_diagnostic_item(cx, ty, expected_ty) {
- let variant = ty.ty_adt_def()
+ let variant = ty
+ .ty_adt_def()
.expect("struct pattern type is not an ADT")
.variant_of_res(cx.qpath_res(path, pat.hir_id));
- return variant.name == expected_variant
+ return variant.name == expected_variant;
}
false
- }
+ },
}
}
@@ -308,20 +315,16 @@ fn find_good_method_for_match<'a>(
should_be_left: &'a str,
should_be_right: &'a str,
) -> Option<&'a str> {
- let pat_left = arms[0].pat;
- let pat_right = arms[1].pat;
+ let first_pat = arms[0].pat;
+ let second_pat = arms[1].pat;
- let body_node_pair = if (
- is_pat_variant(cx, pat_left, path_left, expected_item_left)
- ) && (
- is_pat_variant(cx, pat_right, path_right, expected_item_right)
- ) {
+ let body_node_pair = if (is_pat_variant(cx, first_pat, path_left, expected_item_left))
+ && (is_pat_variant(cx, second_pat, path_right, expected_item_right))
+ {
(&arms[0].body.kind, &arms[1].body.kind)
- } else if (
- is_pat_variant(cx, pat_left, path_left, expected_item_right)
- ) && (
- is_pat_variant(cx, pat_right, path_right, expected_item_left)
- ) {
+ } else if (is_pat_variant(cx, first_pat, path_left, expected_item_right))
+ && (is_pat_variant(cx, second_pat, path_right, expected_item_left))
+ {
(&arms[1].body.kind, &arms[0].body.kind)
} else {
return None;
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 86a9df034..85269e533 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
@@ -50,13 +50,13 @@ fn set_diagnostic<'tcx>(diag: &mut Diagnostic, cx: &LateContext<'tcx>, expr: &'t
let trailing_indent = " ".repeat(indent_of(cx, found.found_span).unwrap_or(0));
let replacement = if found.lint_suggestion == LintSuggestion::MoveAndDerefToCopy {
- format!("let value = *{};\n{}", original, trailing_indent)
+ format!("let value = *{original};\n{trailing_indent}")
} else if found.is_unit_return_val {
// If the return value of the expression to be moved is unit, then we don't need to
// capture the result in a temporary -- we can just replace it completely with `()`.
- format!("{};\n{}", original, trailing_indent)
+ format!("{original};\n{trailing_indent}")
} else {
- format!("let value = {};\n{}", original, trailing_indent)
+ format!("let value = {original};\n{trailing_indent}")
};
let suggestion_message = if found.lint_suggestion == LintSuggestion::MoveOnly {
diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
index 56bcdc01f..e5a15b2e1 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -1,14 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{expr_block, snippet};
-use clippy_utils::ty::{implements_trait, match_type, peel_mid_ty_refs};
-use clippy_utils::{
- is_lint_allowed, is_unit_expr, is_wild, paths, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs,
-};
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, peel_mid_ty_refs};
+use clippy_utils::{is_lint_allowed, is_unit_expr, is_wild, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs};
use core::cmp::max;
use rustc_errors::Applicability;
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
+use rustc_span::sym;
use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE};
@@ -99,23 +98,21 @@ fn report_single_pattern(
let msg = "you seem to be trying to use `match` for an equality check. Consider using `if`";
let sugg = format!(
- "if {} == {}{} {}{}",
+ "if {} == {}{} {}{els_str}",
snippet(cx, ex.span, ".."),
// PartialEq for different reference counts may not exist.
"&".repeat(ref_count_diff),
snippet(cx, arms[0].pat.span, ".."),
expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
- els_str,
);
(msg, sugg)
} else {
let msg = "you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`";
let sugg = format!(
- "if let {} = {} {}{}",
+ "if let {} = {} {}{els_str}",
snippet(cx, arms[0].pat.span, ".."),
snippet(cx, ex.span, ".."),
expr_block(cx, arms[0].body, None, "..", Some(expr.span)),
- els_str,
);
(msg, sugg)
}
@@ -158,10 +155,10 @@ fn pat_in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'a>, pat: &Pat<'_>) ->
/// Returns `true` if the given type is an enum we know won't be expanded in the future
fn in_candidate_enum<'a>(cx: &LateContext<'a>, ty: Ty<'_>) -> bool {
// list of candidate `Enum`s we know will never get any more members
- let candidates = [&paths::COW, &paths::OPTION, &paths::RESULT];
+ let candidates = [sym::Cow, sym::Option, sym::Result];
for candidate_ty in candidates {
- if match_type(cx, ty, candidate_ty) {
+ if is_type_diagnostic_item(cx, ty, candidate_ty) {
return true;
}
}
diff --git a/src/tools/clippy/clippy_lints/src/matches/try_err.rs b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
index 663277d11..c6cba81d8 100644
--- a/src/tools/clippy/clippy_lints/src/matches/try_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/try_err.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{get_parent_expr, is_lang_ctor, match_def_path, paths};
+use clippy_utils::{get_parent_expr, is_res_lang_ctor, match_def_path, path_res, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::ResultErr;
@@ -27,8 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..));
if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind;
- if let ExprKind::Path(ref err_fun_path) = err_fun.kind;
- if is_lang_ctor(cx, err_fun_path, ResultErr);
+ if is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr);
if let Some(return_ty) = find_return_type(cx, &expr.kind);
then {
let prefix;
@@ -61,9 +60,9 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
"return "
};
let suggestion = if err_ty == expr_err_ty {
- format!("{}{}{}{}", ret_prefix, prefix, origin_snippet, suffix)
+ format!("{ret_prefix}{prefix}{origin_snippet}{suffix}")
} else {
- format!("{}{}{}.into(){}", ret_prefix, prefix, origin_snippet, suffix)
+ format!("{ret_prefix}{prefix}{origin_snippet}.into(){suffix}")
};
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/mem_replace.rs b/src/tools/clippy/clippy_lints/src/mem_replace.rs
index cad3ea2a1..0c4d9f100 100644
--- a/src/tools/clippy/clippy_lints/src/mem_replace.rs
+++ b/src/tools/clippy/clippy_lints/src/mem_replace.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_non_aggregate_primitive_type;
-use clippy_utils::{is_default_equivalent, is_lang_ctor, meets_msrv, msrvs};
+use clippy_utils::{is_default_equivalent, is_res_lang_ctor, meets_msrv, msrvs, path_res};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
@@ -102,40 +102,38 @@ impl_lint_pass!(MemReplace =>
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
- if let ExprKind::Path(ref replacement_qpath) = src.kind {
- // Check that second argument is `Option::None`
- if is_lang_ctor(cx, replacement_qpath, OptionNone) {
- // Since this is a late pass (already type-checked),
- // and we already know that the second argument is an
- // `Option`, we do not need to check the first
- // argument's type. All that's left is to get
- // replacee's path.
- let replaced_path = match dest.kind {
- ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
- if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
- replaced_path
- } else {
- return;
- }
- },
- ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
- _ => return,
- };
+ // Check that second argument is `Option::None`
+ if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+ // Since this is a late pass (already type-checked),
+ // and we already know that the second argument is an
+ // `Option`, we do not need to check the first
+ // argument's type. All that's left is to get
+ // replacee's path.
+ let replaced_path = match dest.kind {
+ ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
+ if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
+ replaced_path
+ } else {
+ return;
+ }
+ },
+ ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
+ _ => return,
+ };
- let mut applicability = Applicability::MachineApplicable;
- span_lint_and_sugg(
- cx,
- MEM_REPLACE_OPTION_WITH_NONE,
- expr_span,
- "replacing an `Option` with `None`",
- "consider `Option::take()` instead",
- format!(
- "{}.take()",
- snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
- ),
- applicability,
- );
- }
+ let mut applicability = Applicability::MachineApplicable;
+ span_lint_and_sugg(
+ cx,
+ MEM_REPLACE_OPTION_WITH_NONE,
+ expr_span,
+ "replacing an `Option` with `None`",
+ "consider `Option::take()` instead",
+ format!(
+ "{}.take()",
+ snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
+ ),
+ applicability,
+ );
}
}
@@ -203,10 +201,8 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
return;
}
// disable lint for Option since it is covered in another lint
- if let ExprKind::Path(q) = &src.kind {
- if is_lang_ctor(cx, q, OptionNone) {
- return;
- }
+ if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
+ return;
}
if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
span_lint_and_then(
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index 22f5635a5..cc26b0f7f 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -85,7 +85,7 @@ pub(crate) trait BindInsteadOfMap {
let closure_args_snip = snippet(cx, closure_args_span, "..");
let option_snip = snippet(cx, recv.span, "..");
- let note = format!("{}.{}({} {})", option_snip, Self::GOOD_METHOD_NAME, closure_args_snip, some_inner_snip);
+ let note = format!("{option_snip}.{}({closure_args_snip} {some_inner_snip})", Self::GOOD_METHOD_NAME);
span_lint_and_sugg(
cx,
BIND_INSTEAD_OF_MAP,
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 44857d61f..2e96346be 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bytes_nth.rs
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
cx,
BYTES_NTH,
expr.span,
- &format!("called `.bytes().nth()` on a `{}`", caller_type),
+ &format!("called `.bytes().nth()` on a `{caller_type}`"),
"try",
format!(
"{}.as_bytes().get({})",
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
index b2bc1ad5c..56b7fbb9d 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp.rs
@@ -33,12 +33,11 @@ pub(super) fn check(
cx,
lint,
info.expr.span,
- &format!("you should use the `{}` method", suggest),
+ &format!("you should use the `{suggest}` method"),
"like this",
- format!("{}{}.{}({})",
+ format!("{}{}.{suggest}({})",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
- suggest,
snippet_with_applicability(cx, arg_char.span, "..", &mut applicability)),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
index b85bfec2b..7e8087606 100644
--- a/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/chars_cmp_with_unwrap.rs
@@ -26,12 +26,11 @@ pub(super) fn check<'tcx>(
cx,
lint,
info.expr.span,
- &format!("you should use the `{}` method", suggest),
+ &format!("you should use the `{suggest}` method"),
"like this",
- format!("{}{}.{}('{}')",
+ format!("{}{}.{suggest}('{}')",
if info.eq { "" } else { "!" },
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
- suggest,
c.escape_default()),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
index 7ab6b84c2..7c7938dd2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs
@@ -49,8 +49,7 @@ pub(super) fn check(
expr.span,
&format!(
"using `clone` on a double-reference; \
- this will copy the reference of type `{}` instead of cloning the inner type",
- ty
+ this will copy the reference of type `{ty}` instead of cloning the inner type"
),
|diag| {
if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) {
@@ -62,11 +61,11 @@ pub(super) fn check(
}
let refs = "&".repeat(n + 1);
let derefs = "*".repeat(n);
- let explicit = format!("<{}{}>::clone({})", refs, ty, snip);
+ let explicit = format!("<{refs}{ty}>::clone({snip})");
diag.span_suggestion(
expr.span,
"try dereferencing it",
- format!("{}({}{}).clone()", refs, derefs, snip.deref()),
+ format!("{refs}({derefs}{}).clone()", snip.deref()),
Applicability::MaybeIncorrect,
);
diag.span_suggestion(
@@ -121,16 +120,16 @@ pub(super) fn check(
let (help, sugg) = if deref_count == 0 {
("try removing the `clone` call", snip.into())
} else if parent_is_suffix_expr {
- ("try dereferencing it", format!("({}{})", "*".repeat(deref_count), snip))
+ ("try dereferencing it", format!("({}{snip})", "*".repeat(deref_count)))
} else {
- ("try dereferencing it", format!("{}{}", "*".repeat(deref_count), snip))
+ ("try dereferencing it", format!("{}{snip}", "*".repeat(deref_count)))
};
span_lint_and_sugg(
cx,
CLONE_ON_COPY,
expr.span,
- &format!("using `clone` on type `{}` which implements the `Copy` trait", ty),
+ &format!("using `clone` on type `{ty}` which implements the `Copy` trait"),
help,
sugg,
app,
diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
index f82ca8912..355f53532 100644
--- a/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_ref_ptr.rs
@@ -41,7 +41,7 @@ pub(super) fn check(
expr.span,
"using `.clone()` on a ref-counted pointer",
"try this",
- format!("{}::<{}>::clone(&{})", caller_type, subst.type_at(0), snippet),
+ format!("{caller_type}::<{}>::clone(&{snippet})", subst.type_at(0)),
Applicability::Unspecified, // Sometimes unnecessary ::<_> after Rc/Arc/Weak
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
index 570a1b873..720d9a68c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/err_expect.rs
@@ -1,6 +1,6 @@
use super::ERR_EXPECT;
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::has_debug_impl;
use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item};
use rustc_errors::Applicability;
use rustc_lint::LateContext;
@@ -28,7 +28,7 @@ pub(super) fn check(
// Tests if the T type in a `Result<T, E>` is not None
if let Some(data_type) = get_data_type(cx, result_type);
// Tests if the T type in a `Result<T, E>` implements debug
- if has_debug_impl(data_type, cx);
+ if has_debug_impl(cx, data_type);
then {
span_lint_and_sugg(
@@ -51,10 +51,3 @@ fn get_data_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
_ => None,
}
}
-
-/// Given a type, very if the Debug trait has been impl'd
-fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
- cx.tcx
- .get_diagnostic_item(sym::Debug)
- .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
-}
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 bd846d71d..d0cf411df 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
@@ -143,9 +143,9 @@ pub(super) fn check<'tcx>(
cx,
EXPECT_FUN_CALL,
span_replace_word,
- &format!("use of `{}` followed by a function call", name),
+ &format!("use of `{name}` followed by a function call"),
"try this",
- format!("unwrap_or_else({} panic!({}))", closure_args, sugg),
+ format!("unwrap_or_else({closure_args} panic!({sugg}))"),
applicability,
);
return;
@@ -160,12 +160,9 @@ pub(super) fn check<'tcx>(
cx,
EXPECT_FUN_CALL,
span_replace_word,
- &format!("use of `{}` followed by a function call", name),
+ &format!("use of `{name}` followed by a function call"),
"try this",
- format!(
- "unwrap_or_else({} {{ panic!(\"{{}}\", {}) }})",
- closure_args, arg_root_snippet
- ),
+ format!("unwrap_or_else({closure_args} {{ panic!(\"{{}}\", {arg_root_snippet}) }})"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
index 7b2967feb..3fef53739 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filetype_is_file.rs
@@ -1,17 +1,18 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::match_type;
-use clippy_utils::{get_parent_expr, paths};
+use clippy_utils::get_parent_expr;
+use clippy_utils::ty::is_type_diagnostic_item;
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;
+use rustc_span::sym;
use super::FILETYPE_IS_FILE;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) {
let ty = cx.typeck_results().expr_ty(recv);
- if !match_type(cx, ty, &paths::FILE_TYPE) {
+ if !is_type_diagnostic_item(cx, ty, sym::FileType) {
return;
}
@@ -35,7 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
span = expr.span;
}
}
- let lint_msg = format!("`{}FileType::is_file()` only {} regular files", lint_unary, verb);
- let help_msg = format!("use `{}FileType::is_dir()` instead", help_unary);
+ let lint_msg = format!("`{lint_unary}FileType::is_file()` only {verb} regular files");
+ let help_msg = format!("use `{help_unary}FileType::is_dir()` instead");
span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, None, &help_msg);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
index 38ec4d8e3..ddf8a1f09 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_next.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try this",
- format!("{}.find_map({})", iter_snippet, filter_snippet),
+ format!("{iter_snippet}.find_map({filter_snippet})"),
Applicability::MachineApplicable,
);
} else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
index bcf8d93b6..edcec0fc1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_next.rs
@@ -32,7 +32,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try this",
- format!("{}.find({})", iter_snippet, filter_snippet),
+ format!("{iter_snippet}.find({filter_snippet})"),
Applicability::MachineApplicable,
);
} else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
index 6436e28a6..66dfce368 100644
--- a/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/from_iter_instead_of_collect.rs
@@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Exp
// `expr` implements `FromIterator` trait
let iter_expr = sugg::Sugg::hir(cx, &args[0], "..").maybe_par();
let turbofish = extract_turbofish(cx, expr, ty);
- let sugg = format!("{}.collect::<{}>()", iter_expr, turbofish);
+ let sugg = format!("{iter_expr}.collect::<{turbofish}>()");
span_lint_and_sugg(
cx,
FROM_ITER_INSTEAD_OF_COLLECT,
@@ -63,7 +63,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
if e == type_specifier { None } else { Some((*e).to_string()) }
}).collect::<Vec<_>>();
// join and add the type specifier at the end (i.e.: `collections::BTreeSet<u32>`)
- format!("{}{}", without_ts.join("::"), type_specifier)
+ format!("{}{type_specifier}", without_ts.join("::"))
} else {
// type is not explicitly specified so wildcards are needed
// i.e.: 2 wildcards in `std::collections::BTreeMap<&i32, &char>`
@@ -72,7 +72,7 @@ fn extract_turbofish(cx: &LateContext<'_>, expr: &hir::Expr<'_>, ty: Ty<'_>) ->
let end = ty_str.find('>').unwrap_or(ty_str.len());
let nb_wildcard = ty_str[start..end].split(',').count();
let wildcards = format!("_{}", ", _".repeat(nb_wildcard - 1));
- format!("{}<{}>", elements.join("::"), wildcards)
+ format!("{}<{wildcards}>", elements.join("::"))
}
}
}
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 4de77de74..cb17af608 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs
@@ -29,9 +29,9 @@ pub(super) fn check<'tcx>(
cx,
GET_FIRST,
expr.span,
- &format!("accessing first element with `{0}.get(0)`", slice_name),
+ &format!("accessing first element with `{slice_name}.get(0)`"),
"try",
- format!("{}.first()", slice_name),
+ format!("{slice_name}.first()"),
app,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
index 02aada872..3bdc154df 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_last_with_len.rs
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::SpanlessEq;
-use rustc_ast::LitKind;
+use clippy_utils::{is_integer_literal, SpanlessEq};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
@@ -26,8 +25,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg:
&& lhs_path.ident.name == sym::len
// RHS of subtraction is 1
- && let ExprKind::Lit(rhs_lit) = &rhs.kind
- && let LitKind::Int(1, ..) = rhs_lit.node
+ && is_integer_literal(rhs, 1)
// check that recv == lhs_recv `recv.get(lhs_recv.len() - 1)`
&& SpanlessEq::new(cx).eq_expr(recv, lhs_recv)
diff --git a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
index 18e08d6ee..ffc3a4d78 100644
--- a/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/get_unwrap.rs
@@ -71,16 +71,11 @@ pub(super) fn check<'tcx>(
cx,
GET_UNWRAP,
span,
- &format!(
- "called `.get{0}().unwrap()` on a {1}. Using `[]` is more clear and more concise",
- mut_str, caller_type
- ),
+ &format!("called `.get{mut_str}().unwrap()` on a {caller_type}. Using `[]` is more clear and more concise"),
"try this",
format!(
- "{}{}[{}]",
- borrow_str,
- snippet_with_applicability(cx, recv.span, "..", &mut applicability),
- get_args_str
+ "{borrow_str}{}[{get_args_str}]",
+ snippet_with_applicability(cx, recv.span, "..", &mut applicability)
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
index 9651a52be..429cdc191 100644
--- a/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/implicit_clone.rs
@@ -26,12 +26,12 @@ pub fn check(cx: &LateContext<'_>, method_name: &str, expr: &hir::Expr<'_>, recv
cx,
IMPLICIT_CLONE,
expr.span,
- &format!("implicitly cloning a `{}` by calling `{}` on its dereferenced type", ty_name, method_name),
+ &format!("implicitly cloning a `{ty_name}` by calling `{method_name}` on its dereferenced type"),
"consider using",
if ref_count > 1 {
- format!("({}{}).clone()", "*".repeat(ref_count - 1), recv_snip)
+ format!("({}{recv_snip}).clone()", "*".repeat(ref_count - 1))
} else {
- format!("{}.clone()", recv_snip)
+ format!("{recv_snip}.clone()")
},
app,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
index e1c9b5248..ede3b8bb7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/inefficient_to_string.rs
@@ -34,18 +34,17 @@ pub fn check<'tcx>(
cx,
INEFFICIENT_TO_STRING,
expr.span,
- &format!("calling `to_string` on `{}`", arg_ty),
+ &format!("calling `to_string` on `{arg_ty}`"),
|diag| {
diag.help(&format!(
- "`{}` implements `ToString` through a slower blanket impl, but `{}` has a fast specialization of `ToString`",
- self_ty, deref_self_ty
+ "`{self_ty}` implements `ToString` through a slower blanket impl, but `{deref_self_ty}` has a fast specialization of `ToString`"
));
let mut applicability = Applicability::MachineApplicable;
let arg_snippet = snippet_with_applicability(cx, receiver.span, "..", &mut applicability);
diag.span_suggestion(
expr.span,
"try dereferencing the receiver",
- format!("({}{}).to_string()", "*".repeat(deref_count), arg_snippet),
+ format!("({}{arg_snippet}).to_string()", "*".repeat(deref_count)),
applicability,
);
},
@@ -66,7 +65,7 @@ fn specializes_tostring(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
}
if let ty::Adt(adt, substs) = ty.kind() {
- match_def_path(cx, adt.did(), &paths::COW) && substs.type_at(1).is_str()
+ cx.tcx.is_diagnostic_item(sym::Cow, adt.did()) && substs.type_at(1).is_str()
} else {
false
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
index 11e76841e..8adf9e370 100644
--- a/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/into_iter_on_ref.rs
@@ -30,8 +30,7 @@ pub(super) fn check(
INTO_ITER_ON_REF,
method_span,
&format!(
- "this `.into_iter()` call is equivalent to `.{}()` and will not consume the `{}`",
- method_name, kind,
+ "this `.into_iter()` call is equivalent to `.{method_name}()` and will not consume the `{kind}`",
),
"call directly",
method_name.to_string(),
@@ -43,9 +42,8 @@ pub(super) fn check(
fn ty_has_iter_method(cx: &LateContext<'_>, self_ref_ty: Ty<'_>) -> Option<(Symbol, &'static str)> {
has_iter_method(cx, self_ref_ty).map(|ty_name| {
- let mutbl = match self_ref_ty.kind() {
- ty::Ref(_, _, mutbl) => mutbl,
- _ => unreachable!(),
+ let ty::Ref(_, _, mutbl) = self_ref_ty.kind() else {
+ unreachable!()
};
let method_name = match mutbl {
hir::Mutability::Not => "iter",
diff --git a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
index aa176dcc8..304024e80 100644
--- a/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/is_digit_ascii_radix.rs
@@ -37,12 +37,11 @@ pub(super) fn check<'tcx>(
cx,
IS_DIGIT_ASCII_RADIX,
expr.span,
- &format!("use of `char::is_digit` with literal radix of {}", num),
+ &format!("use of `char::is_digit` with literal radix of {num}"),
"try",
format!(
- "{}.{}()",
- snippet_with_applicability(cx, self_arg.span, "..", &mut applicability),
- replacement
+ "{}.{replacement}()",
+ snippet_with_applicability(cx, self_arg.span, "..", &mut applicability)
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
index 30d56113c..bde6f92b0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_cloned_collect.rs
@@ -20,8 +20,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, method_name: &str, expr: &hir:
cx,
ITER_CLONED_COLLECT,
to_replace,
- &format!("called `iter().{}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
- more readable", method_name),
+ &format!("called `iter().{method_name}().collect()` on a slice to create a `Vec`. Calling `to_vec()` is both faster and \
+ more readable"),
"try",
".to_vec()".to_string(),
Applicability::MachineApplicable,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
index 052be3d8e..bcddc7c78 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_count.rs
@@ -37,7 +37,7 @@ pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx E
cx,
ITER_COUNT,
expr.span,
- &format!("called `.{}().count()` on a `{}`", iter_method, caller_type),
+ &format!("called `.{iter_method}().count()` on a `{caller_type}`"),
"try",
format!(
"{}.len()",
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
new file mode 100644
index 000000000..2244ebfb1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_kv_map.rs
@@ -0,0 +1,87 @@
+#![allow(unused_imports)]
+
+use super::ITER_KV_MAP;
+use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_sugg, span_lint_and_then};
+use clippy_utils::source::{snippet, snippet_with_applicability};
+use clippy_utils::sugg;
+use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::is_local_used;
+use rustc_hir::{BindingAnnotation, Body, BorrowKind, Expr, ExprKind, Mutability, Pat, PatKind};
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::ty;
+use rustc_span::sym;
+use rustc_span::Span;
+
+/// lint use of:
+/// - `hashmap.iter().map(|(_, v)| v)`
+/// - `hashmap.into_iter().map(|(_, v)| v)`
+/// on `HashMaps` and `BTreeMaps` in std
+
+pub(super) fn check<'tcx>(
+ cx: &LateContext<'tcx>,
+ map_type: &'tcx str, // iter / into_iter
+ expr: &'tcx Expr<'tcx>, // .iter().map(|(_, v_| v))
+ recv: &'tcx Expr<'tcx>, // hashmap
+ m_arg: &'tcx Expr<'tcx>, // |(_, v)| v
+) {
+ if_chain! {
+ if !expr.span.from_expansion();
+ if let ExprKind::Closure(c) = m_arg.kind;
+ if let Body {params: [p], value: body_expr, generator_kind: _ } = cx.tcx.hir().body(c.body);
+ if let PatKind::Tuple([key_pat, val_pat], _) = p.pat.kind;
+
+ let (replacement_kind, binded_ident) = match (&key_pat.kind, &val_pat.kind) {
+ (key, PatKind::Binding(_, _, value, _)) if pat_is_wild(cx, key, m_arg) => ("value", value),
+ (PatKind::Binding(_, _, key, _), value) if pat_is_wild(cx, value, m_arg) => ("key", key),
+ _ => return,
+ };
+
+ let ty = cx.typeck_results().expr_ty(recv);
+ if is_type_diagnostic_item(cx, ty, sym::HashMap) || is_type_diagnostic_item(cx, ty, sym::BTreeMap);
+
+ then {
+ let mut applicability = rustc_errors::Applicability::MachineApplicable;
+ let recv_snippet = snippet_with_applicability(cx, recv.span, "map", &mut applicability);
+ let into_prefix = if map_type == "into_iter" {"into_"} else {""};
+
+ if_chain! {
+ if let ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) = body_expr.kind;
+ if let [local_ident] = path.segments;
+ if local_ident.ident.as_str() == binded_ident.as_str();
+
+ then {
+ span_lint_and_sugg(
+ cx,
+ ITER_KV_MAP,
+ expr.span,
+ &format!("iterating on a map's {replacement_kind}s"),
+ "try",
+ format!("{recv_snippet}.{into_prefix}{replacement_kind}s()"),
+ applicability,
+ );
+ } else {
+ span_lint_and_sugg(
+ cx,
+ ITER_KV_MAP,
+ expr.span,
+ &format!("iterating on a map's {replacement_kind}s"),
+ "try",
+ format!("{recv_snippet}.{into_prefix}{replacement_kind}s().map(|{binded_ident}| {})",
+ snippet_with_applicability(cx, body_expr.span, "/* body */", &mut applicability)),
+ applicability,
+ );
+ }
+ }
+ }
+ }
+}
+
+/// Returns `true` if the pattern is a `PatWild`, or is an ident prefixed with `_`
+/// that is not locally used.
+fn pat_is_wild<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
+ match *pat {
+ PatKind::Wild => true,
+ PatKind::Binding(_, id, ident, None) if ident.as_str().starts_with('_') => !is_local_used(cx, body, id),
+ _ => false,
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
index b8d1dabe0..83c1bf203 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_next_slice.rs
@@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, cal
let suggest = if start_idx == 0 {
format!("{}.first()", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
} else {
- format!("{}.get({})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability), start_idx)
+ format!("{}.get({start_idx})", snippet_with_applicability(cx, caller_var.span, "..", &mut applicability))
};
span_lint_and_sugg(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
index 80ca4c942..ceee12784 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_nth.rs
@@ -32,8 +32,8 @@ pub(super) fn check<'tcx>(
cx,
ITER_NTH,
expr.span,
- &format!("called `.iter{0}().nth()` on a {1}", mut_str, caller_type),
+ &format!("called `.iter{mut_str}().nth()` on a {caller_type}"),
None,
- &format!("calling `.get{}()` is both faster and more readable", mut_str),
+ &format!("calling `.get{mut_str}()` is both faster and more readable"),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
index cea7b0d82..4f73b3ec4 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_on_single_or_empty_collections.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
-use clippy_utils::{get_expr_use_or_unification_node, is_lang_ctor, is_no_std_crate};
+use clippy_utils::{get_expr_use_or_unification_node, is_no_std_crate, is_res_lang_ctor, path_res};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -26,26 +26,11 @@ impl IterType {
}
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
- let item = match &recv.kind {
- ExprKind::Array(v) if v.len() <= 1 => v.first(),
- ExprKind::Path(p) => {
- if is_lang_ctor(cx, p, OptionNone) {
- None
- } else {
- return;
- }
- },
- ExprKind::Call(f, some_args) if some_args.len() == 1 => {
- if let ExprKind::Path(p) = &f.kind {
- if is_lang_ctor(cx, p, OptionSome) {
- Some(&some_args[0])
- } else {
- return;
- }
- } else {
- return;
- }
- },
+ let item = match recv.kind {
+ ExprKind::Array([]) => None,
+ ExprKind::Array([e]) => Some(e),
+ ExprKind::Path(ref p) if is_res_lang_ctor(cx, cx.qpath_res(p, recv.hir_id), OptionNone) => None,
+ ExprKind::Call(f, [arg]) if is_res_lang_ctor(cx, path_res(cx, f), OptionSome) => Some(arg),
_ => return,
};
let iter_type = match method_name {
diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
index a669cbbbc..3da230e12 100644
--- a/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/iter_with_drain.rs
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
cx,
ITER_WITH_DRAIN,
span.with_hi(expr.span.hi()),
- &format!("`drain(..)` used on a `{}`", ty_name),
+ &format!("`drain(..)` used on a `{ty_name}`"),
"try this",
"into_iter()".to_string(),
Applicability::MaybeIncorrect,
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 ffd2f4a38..5b758f1e6 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
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_lang_ctor, path_to_local_id};
+use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{ResultErr, ResultOk};
-use rustc_hir::{Closure, Expr, ExprKind, PatKind};
+use rustc_hir::{Expr, ExprKind, PatKind};
use rustc_lint::LateContext;
use rustc_span::symbol::sym;
@@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
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 let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, [err_arg]) = or_expr.kind;
- if is_lang_ctor(cx, err_path, ResultErr);
+ 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);
if let Some(recv_snippet) = snippet_opt(cx, recv.span);
if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span);
@@ -37,9 +37,7 @@ pub(super) fn check<'tcx>(
"this pattern reimplements `Option::ok_or`",
"replace with",
format!(
- "{}.ok_or({})",
- recv_snippet,
- reindented_err_arg_snippet
+ "{recv_snippet}.ok_or({reindented_err_arg_snippet})"
),
Applicability::MachineApplicable,
);
@@ -48,17 +46,19 @@ pub(super) fn check<'tcx>(
}
fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
- if let ExprKind::Path(ref qpath) = map_expr.kind {
- if is_lang_ctor(cx, qpath, ResultOk) {
- return true;
- }
- }
- if_chain! {
- if let ExprKind::Closure(&Closure { body, .. }) = map_expr.kind;
- let body = cx.tcx.hir().body(body);
- if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
- if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, &[ref ok_arg]) = body.value.kind;
- if is_lang_ctor(cx, ok_path, ResultOk);
- then { path_to_local_id(ok_arg, param_id) } else { false }
+ match map_expr.kind {
+ ExprKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, map_expr.hir_id), ResultOk) => true,
+ ExprKind::Closure(closure) => {
+ let body = cx.tcx.hir().body(closure.body);
+ if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind
+ && let ExprKind::Call(callee, [ok_arg]) = body.value.kind
+ && is_res_lang_ctor(cx, path_res(cx, callee), ResultOk)
+ {
+ path_to_local_id(ok_arg, param_id)
+ } else {
+ false
+ }
+ },
+ _ => false,
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 0fe510bea..b80541b86 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -21,11 +21,7 @@ pub fn check(
return;
}
- let mm = if let Some(mm) = is_min_or_max(cx, unwrap_arg) {
- mm
- } else {
- return;
- };
+ let Some(mm) = is_min_or_max(cx, unwrap_arg) else { return };
if ty.is_signed() {
use self::{
@@ -33,9 +29,7 @@ pub fn check(
Sign::{Neg, Pos},
};
- let sign = if let Some(sign) = lit_sign(arith_rhs) {
- sign
- } else {
+ let Some(sign) = lit_sign(arith_rhs) else {
return;
};
@@ -57,11 +51,10 @@ pub fn check(
super::MANUAL_SATURATING_ARITHMETIC,
expr.span,
"manual saturating arithmetic",
- &format!("try using `saturating_{}`", arith),
+ &format!("try using `saturating_{arith}`"),
format!(
- "{}.saturating_{}({})",
+ "{}.saturating_{arith}({})",
snippet_with_applicability(cx, arith_lhs.span, "..", &mut applicability),
- arith,
snippet_with_applicability(cx, arith_rhs.span, "..", &mut applicability),
),
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
index 46d2fc493..8b6b8f1bf 100644
--- a/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/manual_str_repeat.rs
@@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::is_path_diagnostic_item;
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::Sugg;
-use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
-use clippy_utils::{is_expr_path_def_path, paths};
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
use if_chain::if_chain;
use rustc_ast::LitKind;
use rustc_errors::Applicability;
@@ -38,7 +38,7 @@ fn parse_repeat_arg(cx: &LateContext<'_>, e: &Expr<'_>) -> Option<RepeatKind> {
let ty = cx.typeck_results().expr_ty(e);
if is_type_diagnostic_item(cx, ty, sym::String)
|| (is_type_lang_item(cx, ty, LangItem::OwnedBox) && get_ty_param(ty).map_or(false, Ty::is_str))
- || (match_type(cx, ty, &paths::COW) && get_ty_param(ty).map_or(false, Ty::is_str))
+ || (is_type_diagnostic_item(cx, ty, sym::Cow) && get_ty_param(ty).map_or(false, Ty::is_str))
{
Some(RepeatKind::String)
} else {
@@ -57,7 +57,7 @@ pub(super) fn check(
) {
if_chain! {
if let ExprKind::Call(repeat_fn, [repeat_arg]) = take_self_arg.kind;
- if is_expr_path_def_path(cx, repeat_fn, &paths::ITER_REPEAT);
+ if is_path_diagnostic_item(cx, repeat_fn, sym::iter_repeat);
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(collect_expr), sym::String);
if let Some(collect_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id);
if let Some(take_id) = cx.typeck_results().type_dependent_def_id(take_expr.hir_id);
@@ -91,7 +91,7 @@ pub(super) fn check(
collect_expr.span,
"manual implementation of `str::repeat` using iterators",
"try this",
- format!("{}.repeat({})", val_str, count_snip),
+ format!("{val_str}.repeat({count_snip})"),
app
)
}
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 8261ef5e1..7ce14ec08 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_clone.rs
@@ -111,11 +111,10 @@ fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_cop
MAP_CLONE,
replace,
message,
- &format!("consider calling the dedicated `{}` method", sugg_method),
+ &format!("consider calling the dedicated `{sugg_method}` method"),
format!(
- "{}.{}()",
+ "{}.{sugg_method}()",
snippet_with_applicability(cx, root, "..", &mut applicability),
- sugg_method,
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
index 13853dec9..361ffcb5e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_flatten.rs
@@ -20,12 +20,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, map_
cx,
MAP_FLATTEN,
expr.span.with_lo(map_span.lo()),
- &format!("called `map(..).flatten()` on `{}`", caller_ty_name),
- &format!(
- "try replacing `map` with `{}` and remove the `.flatten()`",
- method_to_use
- ),
- format!("{}({})", method_to_use, closure_snippet),
+ &format!("called `map(..).flatten()` on `{caller_ty_name}`"),
+ &format!("try replacing `map` with `{method_to_use}` and remove the `.flatten()`"),
+ format!("{method_to_use}({closure_snippet})"),
applicability,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
index 862a9578e..0f25ef82e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_identity.rs
@@ -30,7 +30,7 @@ pub(super) fn check(
MAP_IDENTITY,
sugg_span,
"unnecessary map of the identity function",
- &format!("remove the call to `{}`", name),
+ &format!("remove the call to `{name}`"),
String::new(),
Applicability::MachineApplicable,
)
diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
index 4a8e7ce4d..74fdead21 100644
--- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs
@@ -65,7 +65,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try this",
- format!("{}.map_or_else({}, {})", var_snippet, unwrap_snippet, map_snippet),
+ format!("{var_snippet}.map_or_else({unwrap_snippet}, {map_snippet})"),
Applicability::MachineApplicable,
);
return true;
diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs
index 41942b20e..8a76ba0b0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs
@@ -35,6 +35,7 @@ mod into_iter_on_ref;
mod is_digit_ascii_radix;
mod iter_cloned_collect;
mod iter_count;
+mod iter_kv_map;
mod iter_next_slice;
mod iter_nth;
mod iter_nth_zero;
@@ -101,20 +102,18 @@ use bind_instead_of_map::BindInsteadOfMap;
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::ty::{contains_adt_constructor, implements_trait, is_copy, is_type_diagnostic_item};
-use clippy_utils::{
- contains_return, get_trait_def_id, is_trait_method, iter_input_pats, meets_msrv, msrvs, paths, return_ty,
-};
+use clippy_utils::{contains_return, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TraitItem, TraitItemKind};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, TraitRef, Ty};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
@@ -3036,6 +3035,37 @@ declare_clippy_lint! {
"use of `File::read_to_end` or `File::read_to_string`"
}
+declare_clippy_lint! {
+ /// ### What it does
+ ///
+ /// Checks for iterating a map (`HashMap` or `BTreeMap`) and
+ /// ignoring either the keys or values.
+ ///
+ /// ### Why is this bad?
+ ///
+ /// Readability. There are `keys` and `values` methods that
+ /// can be used to express that we only need the keys or the values.
+ ///
+ /// ### Example
+ ///
+ /// ```
+ /// # use std::collections::HashMap;
+ /// let map: HashMap<u32, u32> = HashMap::new();
+ /// let values = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+ /// ```
+ ///
+ /// Use instead:
+ /// ```
+ /// # use std::collections::HashMap;
+ /// let map: HashMap<u32, u32> = HashMap::new();
+ /// let values = map.values().collect::<Vec<_>>();
+ /// ```
+ #[clippy::version = "1.65.0"]
+ pub ITER_KV_MAP,
+ complexity,
+ "iterating on map using `iter` when `keys` or `values` would do"
+}
+
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Option<RustcVersion>,
@@ -3159,6 +3189,7 @@ impl_lint_pass!(Methods => [
UNNECESSARY_SORT_BY,
VEC_RESIZE_TO_ZERO,
VERBOSE_FILE_READS,
+ ITER_KV_MAP,
]);
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3217,70 +3248,64 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
return;
}
let name = impl_item.ident.name.as_str();
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ 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.def_id);
+ let self_ty = cx.tcx.type_of(item.owner_id);
let implements_trait = matches!(item.kind, hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }));
- if_chain! {
- if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
- if let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next();
-
- let method_sig = cx.tcx.fn_sig(impl_item.def_id);
+ 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.erase_late_bound_regions(method_sig);
-
- let first_arg_ty = method_sig.inputs().iter().next();
-
- // check conventions w.r.t. conversion method names and predicates
- if let Some(first_arg_ty) = first_arg_ty;
-
- then {
- // if this impl block implements a trait, lint in trait definition instead
- if !implements_trait && cx.access_levels.is_exported(impl_item.def_id) {
- // check missing trait implementations
- for method_config in &TRAIT_METHODS {
- if name == method_config.method_name &&
- sig.decl.inputs.len() == method_config.param_count &&
- method_config.output_type.matches(&sig.decl.output) &&
- method_config.self_kind.matches(cx, self_ty, *first_arg_ty) &&
- fn_header_equals(method_config.fn_header, sig.header) &&
- method_config.lifetime_param_cond(impl_item)
- {
- span_lint_and_help(
- cx,
- SHOULD_IMPLEMENT_TRAIT,
- impl_item.span,
- &format!(
- "method `{}` can be confused for the standard trait method `{}::{}`",
- method_config.method_name,
- method_config.trait_name,
- method_config.method_name
- ),
- None,
- &format!(
- "consider implementing the trait `{}` or choosing a less ambiguous method name",
- method_config.trait_name
- )
- );
- }
+ let first_arg_ty_opt = method_sig.inputs().iter().next().copied();
+ // if this impl block implements a trait, lint in trait definition instead
+ if !implements_trait && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
+ // check missing trait implementations
+ for method_config in &TRAIT_METHODS {
+ if name == method_config.method_name
+ && sig.decl.inputs.len() == method_config.param_count
+ && method_config.output_type.matches(&sig.decl.output)
+ // in case there is no first arg, since we already have checked the number of arguments
+ // it's should be always true
+ && first_arg_ty_opt.map_or(true, |first_arg_ty| method_config
+ .self_kind.matches(cx, self_ty, first_arg_ty)
+ )
+ && fn_header_equals(method_config.fn_header, sig.header)
+ && method_config.lifetime_param_cond(impl_item)
+ {
+ span_lint_and_help(
+ cx,
+ SHOULD_IMPLEMENT_TRAIT,
+ impl_item.span,
+ &format!(
+ "method `{}` can be confused for the standard trait method `{}::{}`",
+ method_config.method_name, method_config.trait_name, method_config.method_name
+ ),
+ None,
+ &format!(
+ "consider implementing the trait `{}` or choosing a less ambiguous method name",
+ method_config.trait_name
+ ),
+ );
}
}
+ }
- if sig.decl.implicit_self.has_implicit_self()
+ if sig.decl.implicit_self.has_implicit_self()
&& !(self.avoid_breaking_exported_api
- && cx.access_levels.is_exported(impl_item.def_id))
+ && cx.effective_visibilities.is_exported(impl_item.owner_id.def_id))
+ && let Some(first_arg) = iter_input_pats(sig.decl, cx.tcx.hir().body(id)).next()
+ && let Some(first_arg_ty) = first_arg_ty_opt
{
wrong_self_convention::check(
cx,
name,
self_ty,
- *first_arg_ty,
+ first_arg_ty,
first_arg.pat.span,
implements_trait,
false
);
}
- }
}
// if this impl block implements a trait, lint in trait definition instead
@@ -3345,7 +3370,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
then {
let first_arg_span = first_arg_ty.span;
let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
+ let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
+ .self_ty()
+ .skip_binder();
wrong_self_convention::check(
cx,
item.ident.name.as_str(),
@@ -3353,7 +3380,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
first_arg_ty,
first_arg_span,
false,
- true
+ true,
);
}
}
@@ -3362,7 +3389,9 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
if item.ident.name == sym::new;
if let TraitItemKind::Fn(_, _) = item.kind;
let ret_ty = return_ty(cx, item.hir_id());
- let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
+ let self_ty = TraitRef::identity(cx.tcx, item.owner_id.to_def_id())
+ .self_ty()
+ .skip_binder();
if !ret_ty.contains(self_ty);
then {
@@ -3498,6 +3527,9 @@ impl Methods {
(name @ ("map" | "map_err"), [m_arg]) => {
if name == "map" {
map_clone::check(cx, expr, recv, m_arg, self.msrv);
+ if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _)) = method_call(recv) {
+ iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
+ }
} else {
map_err_ignore::check(cx, expr, m_arg);
}
@@ -3763,7 +3795,6 @@ const TRAIT_METHODS: [ShouldImplTraitCase; 30] = [
ShouldImplTraitCase::new("std::borrow::BorrowMut", "borrow_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
ShouldImplTraitCase::new("std::clone::Clone", "clone", 1, FN_HEADER, SelfKind::Ref, OutType::Any, true),
ShouldImplTraitCase::new("std::cmp::Ord", "cmp", 2, FN_HEADER, SelfKind::Ref, OutType::Any, true),
- // FIXME: default doesn't work
ShouldImplTraitCase::new("std::default::Default", "default", 0, FN_HEADER, SelfKind::No, OutType::Any, true),
ShouldImplTraitCase::new("std::ops::Deref", "deref", 1, FN_HEADER, SelfKind::Ref, OutType::Ref, true),
ShouldImplTraitCase::new("std::ops::DerefMut", "deref_mut", 1, FN_HEADER, SelfKind::RefMut, OutType::Ref, true),
@@ -3791,7 +3822,7 @@ enum SelfKind {
Value,
Ref,
RefMut,
- No,
+ No, // When we want the first argument type to be different than `Self`
}
impl SelfKind {
@@ -3817,14 +3848,13 @@ impl SelfKind {
return m == mutability && t == parent_ty;
}
- let trait_path = match mutability {
- hir::Mutability::Not => &paths::ASREF_TRAIT,
- hir::Mutability::Mut => &paths::ASMUT_TRAIT,
+ let trait_sym = match mutability {
+ hir::Mutability::Not => sym::AsRef,
+ hir::Mutability::Mut => sym::AsMut,
};
- let trait_def_id = match get_trait_def_id(cx, trait_path) {
- Some(did) => did,
- None => return false,
+ let Some(trait_def_id) = cx.tcx.get_diagnostic_item(trait_sym) else {
+ return false
};
implements_trait(cx, ty, trait_def_id, &[parent_ty.into()])
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
index d64a9f320..646fc4a7b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/ok_expect.rs
@@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::ty::{has_debug_impl, is_type_diagnostic_item};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_lint::LateContext;
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
let result_type = cx.typeck_results().expr_ty(recv);
if let Some(error_type) = get_error_type(cx, result_type);
- if has_debug_impl(error_type, cx);
+ if has_debug_impl(cx, error_type);
then {
span_lint_and_help(
@@ -37,10 +37,3 @@ fn get_error_type<'a>(cx: &LateContext<'_>, ty: Ty<'a>) -> Option<Ty<'a>> {
_ => None,
}
}
-
-/// This checks whether a given type is known to implement Debug.
-fn has_debug_impl<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool {
- cx.tcx
- .get_diagnostic_item(sym::Debug)
- .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index c409268de..742483e6b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -32,8 +32,7 @@ pub(super) fn check<'tcx>(
return;
}
- let deref_aliases: [&[&str]; 9] = [
- &paths::DEREF_TRAIT_METHOD,
+ let deref_aliases: [&[&str]; 8] = [
&paths::DEREF_MUT_TRAIT_METHOD,
&paths::CSTRING_AS_C_STR,
&paths::OS_STRING_AS_OS_STR,
@@ -45,12 +44,14 @@ pub(super) fn check<'tcx>(
];
let is_deref = match map_arg.kind {
- hir::ExprKind::Path(ref expr_qpath) => cx
- .qpath_res(expr_qpath, map_arg.hir_id)
- .opt_def_id()
- .map_or(false, |fun_def_id| {
- deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
- }),
+ hir::ExprKind::Path(ref expr_qpath) => {
+ cx.qpath_res(expr_qpath, map_arg.hir_id)
+ .opt_def_id()
+ .map_or(false, |fun_def_id| {
+ cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
+ || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
+ })
+ },
hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
let closure_body = cx.tcx.hir().body(body);
let closure_expr = peel_blocks(closure_body.value);
@@ -68,7 +69,8 @@ pub(super) fn check<'tcx>(
if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj;
then {
let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
- deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
+ cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
+ || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
} else {
false
}
@@ -98,13 +100,12 @@ pub(super) fn check<'tcx>(
format!(".as_ref().map({})", snippet(cx, map_arg.span, ".."))
};
let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" };
- let hint = format!("{}.{}()", snippet(cx, as_ref_recv.span, ".."), method_hint);
- let suggestion = format!("try using {} instead", method_hint);
+ let hint = format!("{}.{method_hint}()", snippet(cx, as_ref_recv.span, ".."));
+ let suggestion = format!("try using {method_hint} instead");
let msg = format!(
- "called `{0}` on an Option value. This can be done more directly \
- by calling `{1}` instead",
- current_method, hint
+ "called `{current_method}` on an Option value. This can be done more directly \
+ by calling `{hint}` instead"
);
span_lint_and_sugg(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
index 6657cdccd..3a23ecc50 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_or_none.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_lang_ctor, path_def_id};
+use clippy_utils::{is_res_lang_ctor, path_def_id, path_res};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::LangItem::{OptionNone, OptionSome};
@@ -51,22 +51,12 @@ pub(super) fn check<'tcx>(
return;
}
- let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
- is_lang_ctor(cx, qpath, OptionNone)
- } else {
- return;
- };
-
- if !default_arg_is_none {
+ if !is_res_lang_ctor(cx, path_res(cx, def_arg), OptionNone) {
// nothing to lint!
return;
}
- let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
- is_lang_ctor(cx, qpath, OptionSome)
- } else {
- false
- };
+ let f_arg_is_some = is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome);
if is_option {
let self_snippet = snippet(cx, recv.span, "..");
@@ -87,7 +77,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try using `map` instead",
- format!("{0}.map({1} {2})", self_snippet, arg_snippet,func_snippet),
+ format!("{self_snippet}.map({arg_snippet} {func_snippet})"),
Applicability::MachineApplicable,
);
}
@@ -102,7 +92,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try using `and_then` instead",
- format!("{0}.and_then({1})", self_snippet, func_snippet),
+ format!("{self_snippet}.and_then({func_snippet})"),
Applicability::MachineApplicable,
);
} else if f_arg_is_some {
@@ -115,7 +105,7 @@ pub(super) fn check<'tcx>(
expr.span,
msg,
"try using `ok` instead",
- format!("{0}.ok()", self_snippet),
+ format!("{self_snippet}.ok()"),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 3c4002a3a..30421a6dd 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -65,9 +65,8 @@ pub(super) fn check<'tcx>(
"map_or(<a>, <f>)"
};
let msg = &format!(
- "called `map(<f>).unwrap_or({})` on an `Option` value. \
- This can be done more directly by calling `{}` instead",
- arg, suggest
+ "called `map(<f>).unwrap_or({arg})` on an `Option` value. \
+ This can be done more directly by calling `{suggest}` instead"
);
span_lint_and_then(cx, MAP_UNWRAP_OR, expr.span, msg, |diag| {
@@ -82,10 +81,10 @@ pub(super) fn check<'tcx>(
];
if !unwrap_snippet_none {
- suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{}, ", unwrap_snippet)));
+ suggestion.push((map_arg_span.with_hi(map_arg_span.lo()), format!("{unwrap_snippet}, ")));
}
- diag.multipart_suggestion(&format!("use `{}` instead", suggest), suggestion, applicability);
+ diag.multipart_suggestion(&format!("use `{suggest}` instead"), suggestion, applicability);
});
}
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
index b43b9258c..991d3dd53 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_fun_call.rs
@@ -1,14 +1,14 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::eager_or_lazy::switch_to_lazy_eval;
use clippy_utils::source::{snippet, snippet_with_macro_callsite};
-use clippy_utils::ty::{implements_trait, match_type};
-use clippy_utils::{contains_return, is_trait_item, last_path_segment, paths};
+use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
+use clippy_utils::{contains_return, is_trait_item, last_path_segment};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Symbol};
use std::borrow::Cow;
use super::OR_FUN_CALL;
@@ -62,9 +62,9 @@ pub(super) fn check<'tcx>(
cx,
OR_FUN_CALL,
method_span.with_hi(span.hi()),
- &format!("use of `{}` followed by a call to `{}`", name, path),
+ &format!("use of `{name}` followed by a call to `{path}`"),
"try this",
- format!("{}()", sugg),
+ format!("{sugg}()"),
Applicability::MachineApplicable,
);
@@ -88,11 +88,11 @@ pub(super) fn check<'tcx>(
fun_span: Option<Span>,
) {
// (path, fn_has_argument, methods, suffix)
- const KNOW_TYPES: [(&[&str], bool, &[&str], &str); 4] = [
- (&paths::BTREEMAP_ENTRY, false, &["or_insert"], "with"),
- (&paths::HASHMAP_ENTRY, false, &["or_insert"], "with"),
- (&paths::OPTION, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
- (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
+ const KNOW_TYPES: [(Symbol, bool, &[&str], &str); 4] = [
+ (sym::BTreeEntry, false, &["or_insert"], "with"),
+ (sym::HashMapEntry, false, &["or_insert"], "with"),
+ (sym::Option, false, &["map_or", "ok_or", "or", "unwrap_or"], "else"),
+ (sym::Result, true, &["or", "unwrap_or"], "else"),
];
if_chain! {
@@ -104,7 +104,7 @@ pub(super) fn check<'tcx>(
let self_ty = cx.typeck_results().expr_ty(self_expr);
if let Some(&(_, fn_has_arguments, poss, suffix)) =
- KNOW_TYPES.iter().find(|&&i| match_type(cx, self_ty, i.0));
+ KNOW_TYPES.iter().find(|&&i| is_type_diagnostic_item(cx, self_ty, i.0));
if poss.contains(&name);
@@ -121,17 +121,16 @@ pub(super) fn check<'tcx>(
macro_expanded_snipped = snippet(cx, snippet_span, "..");
match macro_expanded_snipped.strip_prefix("$crate::vec::") {
Some(stripped) => Cow::from(stripped),
- None => macro_expanded_snipped
+ None => macro_expanded_snipped,
}
- }
- else {
+ } else {
not_macro_argument_snippet
}
};
if use_lambda {
let l_arg = if fn_has_arguments { "_" } else { "" };
- format!("|{}| {}", l_arg, snippet).into()
+ format!("|{l_arg}| {snippet}").into()
} else {
snippet
}
@@ -141,9 +140,9 @@ pub(super) fn check<'tcx>(
cx,
OR_FUN_CALL,
span_replace_word,
- &format!("use of `{}` followed by a function call", name),
+ &format!("use of `{name}` followed by a function call"),
"try this",
- format!("{}_{}({})", name, suffix, sugg),
+ format!("{name}_{suffix}({sugg})"),
Applicability::HasPlaceholders,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
index be5768c35..55ba6e262 100644
--- a/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/or_then_unwrap.rs
@@ -1,6 +1,6 @@
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{diagnostics::span_lint_and_sugg, is_lang_ctor};
+use clippy_utils::{diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res};
use rustc_errors::Applicability;
use rustc_hir::{lang_items::LangItem, Expr, ExprKind};
use rustc_lint::LateContext;
@@ -58,8 +58,7 @@ pub(super) fn check<'tcx>(
fn get_content_if_ctor_matches(cx: &LateContext<'_>, expr: &Expr<'_>, item: LangItem) -> Option<Span> {
if let ExprKind::Call(some_expr, [arg]) = expr.kind
- && let ExprKind::Path(qpath) = &some_expr.kind
- && is_lang_ctor(cx, qpath, item)
+ && is_res_lang_ctor(cx, path_res(cx, some_expr), item)
{
Some(arg.span)
} else {
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 7572ba3fe..324c9c17b 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
@@ -30,10 +30,7 @@ pub(super) fn check<'tcx>(
let option_check_method = if is_some { "is_some" } else { "is_none" };
// lint if caller of search is an Iterator
if is_trait_method(cx, is_some_recv, sym::Iterator) {
- let msg = format!(
- "called `{}()` after searching an `Iterator` with `{}`",
- option_check_method, search_method
- );
+ let msg = format!("called `{option_check_method}()` after searching an `Iterator` with `{search_method}`");
let search_snippet = snippet(cx, search_arg.span, "..");
if search_snippet.lines().count() <= 1 {
// suggest `any(|x| ..)` instead of `any(|&x| ..)` for `find(|&x| ..).is_some()`
@@ -86,8 +83,7 @@ pub(super) fn check<'tcx>(
&msg,
"use `!_.any()` instead",
format!(
- "!{}.any({})",
- iter,
+ "!{iter}.any({})",
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
),
applicability,
@@ -119,7 +115,7 @@ pub(super) fn check<'tcx>(
if is_string_or_str_slice(search_recv);
if is_string_or_str_slice(search_arg);
then {
- let msg = format!("called `{}()` after calling `find()` on a string", option_check_method);
+ let msg = format!("called `{option_check_method}()` after calling `find()` on a string");
match option_check_method {
"is_some" => {
let mut applicability = Applicability::MachineApplicable;
@@ -130,7 +126,7 @@ pub(super) fn check<'tcx>(
method_span.with_hi(expr.span.hi()),
&msg,
"use `contains()` instead",
- format!("contains({})", find_arg),
+ format!("contains({find_arg})"),
applicability,
);
},
@@ -144,7 +140,7 @@ pub(super) fn check<'tcx>(
expr.span,
&msg,
"use `!_.contains()` instead",
- format!("!{}.contains({})", string, find_arg),
+ format!("!{string}.contains({find_arg})"),
applicability,
);
},
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
index 18b6b5be1..44a7ad394 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_insert_string.rs
@@ -14,7 +14,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
let base_string_snippet =
snippet_with_applicability(cx, receiver.span.source_callsite(), "_", &mut applicability);
let pos_arg = snippet_with_applicability(cx, args[0].span, "..", &mut applicability);
- let sugg = format!("{}.insert({}, {})", base_string_snippet, pos_arg, extension_string);
+ let sugg = format!("{base_string_snippet}.insert({pos_arg}, {extension_string})");
span_lint_and_sugg(
cx,
SINGLE_CHAR_ADD_STR,
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
index 9ea675195..0698bd6a0 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_push_string.rs
@@ -13,7 +13,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::
if let Some(extension_string) = get_hint_if_single_char_arg(cx, &args[0], &mut applicability) {
let base_string_snippet =
snippet_with_applicability(cx, receiver.span.source_callsite(), "..", &mut applicability);
- let sugg = format!("{}.push({})", base_string_snippet, extension_string);
+ let sugg = format!("{base_string_snippet}.push({extension_string})");
span_lint_and_sugg(
cx,
SINGLE_CHAR_ADD_STR,
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 91951c65b..09c8ca4cb 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
@@ -17,11 +17,11 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, recv: &'tcx
cx,
STABLE_SORT_PRIMITIVE,
e.span,
- &format!("used `sort` on primitive type `{}`", slice_type),
+ &format!("used `sort` on primitive type `{slice_type}`"),
|diag| {
let mut app = Applicability::MachineApplicable;
let recv_snip = snippet_with_context(cx, recv.span, e.span.ctxt(), "..", &mut app).0;
- diag.span_suggestion(e.span, "try", format!("{}.sort_unstable()", recv_snip), app);
+ diag.span_suggestion(e.span, "try", format!("{recv_snip}.sort_unstable()"), app);
diag.note(
"an unstable sort typically performs faster without any observable difference for this data type",
);
diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
index 9ca4d6555..1acac5914 100644
--- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs
@@ -2,11 +2,11 @@ use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_context;
use clippy_utils::usage::local_used_after_expr;
-use clippy_utils::visitors::expr_visitor;
+use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
use clippy_utils::{is_diag_item_method, match_def_path, meets_msrv, msrvs, path_to_local_id, paths};
+use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::Visitor;
use rustc_hir::{
BindingAnnotation, Expr, ExprKind, HirId, LangItem, Local, MatchSource, Node, Pat, PatKind, QPath, Stmt, StmtKind,
};
@@ -211,7 +211,7 @@ fn indirect_usage<'tcx>(
binding: HirId,
ctxt: SyntaxContext,
) -> Option<IndirectUsage<'tcx>> {
- if let StmtKind::Local(Local {
+ if let StmtKind::Local(&Local {
pat: Pat {
kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None),
..
@@ -222,14 +222,12 @@ fn indirect_usage<'tcx>(
}) = stmt.kind
{
let mut path_to_binding = None;
- expr_visitor(cx, |expr| {
- if path_to_local_id(expr, binding) {
- path_to_binding = Some(expr);
+ let _: Option<!> = for_each_expr_with_closures(cx, init_expr, |e| {
+ if path_to_local_id(e, binding) {
+ path_to_binding = Some(e);
}
-
- path_to_binding.is_none()
- })
- .visit_expr(init_expr);
+ ControlFlow::Continue(Descend::from(path_to_binding.is_none()))
+ });
let mut parents = cx.tcx.hir().parent_iter(path_to_binding?.hir_id);
let iter_usage = parse_iter_usage(cx, ctxt, &mut parents)?;
@@ -250,7 +248,7 @@ fn indirect_usage<'tcx>(
..
} = iter_usage
{
- if parent_id == *local_hir_id {
+ if parent_id == local_hir_id {
return Some(IndirectUsage {
name: ident.name,
span: stmt.span,
@@ -291,9 +289,7 @@ fn parse_iter_usage<'tcx>(
) -> Option<IterUsage> {
let (kind, span) = match iter.next() {
Some((_, Node::Expr(e))) if e.span.ctxt() == ctxt => {
- let (name, args) = if let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind {
- (name, args)
- } else {
+ let ExprKind::MethodCall(name, _, [args @ ..], _) = e.kind else {
return None;
};
let did = cx.typeck_results().type_dependent_def_id(e.hir_id)?;
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 143dcee35..6974260f7 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
@@ -34,9 +34,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
"calling `.extend(_.chars())`",
"try this",
format!(
- "{}.push_str({}{})",
+ "{}.push_str({ref_str}{})",
snippet_with_applicability(cx, recv.span, "..", &mut applicability),
- ref_str,
snippet_with_applicability(cx, target.span, "..", &mut applicability)
),
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
index 55567d862..219a9edd6 100644
--- a/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_splitn.rs
@@ -24,10 +24,10 @@ pub(super) fn check(cx: &LateContext<'_>, method_name: &str, expr: &Expr<'_>, se
}
let (msg, note_msg) = if count == 0 {
- (format!("`{}` called with `0` splits", method_name),
+ (format!("`{method_name}` called with `0` splits"),
"the resulting iterator will always return `None`")
} else {
- (format!("`{}` called with `1` split", method_name),
+ (format!("`{method_name}` called with `1` split"),
if self_ty.is_slice() {
"the resulting iterator will always return the entire slice followed by `None`"
} else {
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 6b306fbf0..15c1c618c 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
@@ -24,9 +24,9 @@ pub fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>) -
cx,
SUSPICIOUS_TO_OWNED,
expr.span,
- &format!("this `to_owned` call clones the {0} itself and does not cause the {0} contents to become owned", input_type),
+ &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!("{0}.clone()` or `{0}.into_owned()", recv_snip),
+ format!("{recv_snip}.clone()` or `{recv_snip}.into_owned()"),
app,
);
return true;
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
index 4e8c201f4..1cef6226a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_filter_map.rs
@@ -2,9 +2,10 @@ use super::utils::clone_or_copy_needed;
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::is_copy;
use clippy_utils::usage::mutated_variables;
-use clippy_utils::{is_lang_ctor, is_trait_method, path_to_local_id};
+use clippy_utils::visitors::{for_each_expr, Descend};
+use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
+use core::ops::ControlFlow;
use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_lint::LateContext;
use rustc_middle::ty;
@@ -13,7 +14,7 @@ use rustc_span::sym;
use super::UNNECESSARY_FILTER_MAP;
use super::UNNECESSARY_FIND_MAP;
-pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, name: &str) {
+pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, arg: &'tcx hir::Expr<'tcx>, name: &str) {
if !is_trait_method(cx, expr, sym::Iterator) {
return;
}
@@ -26,10 +27,16 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
let (mut found_mapping, mut found_filtering) = check_expression(cx, arg_id, body.value);
- let mut return_visitor = ReturnVisitor::new(cx, arg_id);
- return_visitor.visit_expr(body.value);
- found_mapping |= return_visitor.found_mapping;
- found_filtering |= return_visitor.found_filtering;
+ let _: Option<!> = for_each_expr(body.value, |e| {
+ if let hir::ExprKind::Ret(Some(e)) = &e.kind {
+ let (found_mapping_res, found_filtering_res) = check_expression(cx, arg_id, e);
+ found_mapping |= found_mapping_res;
+ found_filtering |= found_filtering_res;
+ ControlFlow::Continue(Descend::No)
+ } else {
+ ControlFlow::Continue(Descend::Yes)
+ }
+ });
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id);
let sugg = if !found_filtering {
@@ -54,22 +61,20 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
UNNECESSARY_FIND_MAP
},
expr.span,
- &format!("this `.{}` can be written more simply using `.{}`", name, sugg),
+ &format!("this `.{name}` can be written more simply using `.{sugg}`"),
);
}
}
// returns (found_mapping, found_filtering)
fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) {
- match &expr.kind {
+ match expr.kind {
hir::ExprKind::Call(func, args) => {
- if let hir::ExprKind::Path(ref path) = func.kind {
- if is_lang_ctor(cx, path, OptionSome) {
- if path_to_local_id(&args[0], arg_id) {
- return (false, false);
- }
- return (true, false);
+ if is_res_lang_ctor(cx, path_res(cx, func), OptionSome) {
+ if path_to_local_id(&args[0], arg_id) {
+ return (false, false);
}
+ return (true, false);
}
(true, true)
},
@@ -80,7 +85,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
hir::ExprKind::Match(_, arms, _) => {
let mut found_mapping = false;
let mut found_filtering = false;
- for arm in *arms {
+ for arm in arms {
let (m, f) = check_expression(cx, arg_id, arm.body);
found_mapping |= m;
found_filtering |= f;
@@ -93,39 +98,9 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
let else_check = check_expression(cx, arg_id, else_arm);
(if_check.0 | else_check.0, if_check.1 | else_check.1)
},
- hir::ExprKind::Path(path) if is_lang_ctor(cx, path, OptionNone) => (false, true),
+ hir::ExprKind::Path(ref path) if is_res_lang_ctor(cx, cx.qpath_res(path, expr.hir_id), OptionNone) => {
+ (false, true)
+ },
_ => (true, true),
}
}
-
-struct ReturnVisitor<'a, 'tcx> {
- cx: &'a LateContext<'tcx>,
- arg_id: hir::HirId,
- // Found a non-None return that isn't Some(input)
- found_mapping: bool,
- // Found a return that isn't Some
- found_filtering: bool,
-}
-
-impl<'a, 'tcx> ReturnVisitor<'a, 'tcx> {
- fn new(cx: &'a LateContext<'tcx>, arg_id: hir::HirId) -> ReturnVisitor<'a, 'tcx> {
- ReturnVisitor {
- cx,
- arg_id,
- found_mapping: false,
- found_filtering: false,
- }
- }
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ReturnVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
- if let hir::ExprKind::Ret(Some(expr)) = &expr.kind {
- let (found_mapping, found_filtering) = check_expression(self.cx, self.arg_id, expr);
- self.found_mapping |= found_mapping;
- self.found_filtering |= found_filtering;
- } else {
- walk_expr(self, expr);
- }
- }
-}
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
index c17ef6809..aa87dead3 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs
@@ -49,15 +49,12 @@ pub(super) fn check(
let mut applicability = Applicability::MachineApplicable;
let sugg = if replacement_has_args {
format!(
- "{replacement}(|{s}| {r})",
- replacement = replacement_method_name,
- s = second_arg_ident,
+ "{replacement_method_name}(|{second_arg_ident}| {r})",
r = snippet_with_applicability(cx, right_expr.span, "EXPR", &mut applicability),
)
} else {
format!(
- "{replacement}()",
- replacement = replacement_method_name,
+ "{replacement_method_name}()",
)
};
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 95138c0e2..1966a85f7 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -68,7 +68,7 @@ pub fn check_for_loop_iter(
cx,
UNNECESSARY_TO_OWNED,
expr.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
|diag| {
// If `check_into_iter_call_arg` called `check_for_loop_iter` because a call to
// a `to_owned`-like function was removed, then the next suggestion may be
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
index a187a8d60..0e73459ad 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_lazy_eval.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{eager_or_lazy, usage};
+use clippy_utils::{eager_or_lazy, is_from_proc_macro, usage};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
@@ -18,6 +18,10 @@ pub(super) fn check<'tcx>(
arg: &'tcx hir::Expr<'_>,
simplify_using: &str,
) {
+ if is_from_proc_macro(cx, expr) {
+ return;
+ }
+
let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
let is_bool = cx.typeck_results().expr_ty(recv).is_bool();
@@ -58,8 +62,8 @@ pub(super) fn check<'tcx>(
span_lint_and_then(cx, UNNECESSARY_LAZY_EVALUATIONS, expr.span, msg, |diag| {
diag.span_suggestion(
span,
- &format!("use `{}(..)` instead", simplify_using),
- format!("{}({})", simplify_using, snippet(cx, body_expr.span, "..")),
+ &format!("use `{simplify_using}(..)` instead"),
+ format!("{simplify_using}({})", snippet(cx, body_expr.span, "..")),
applicability,
);
});
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 763bfafec..3566fe9a0 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
@@ -1,6 +1,5 @@
use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
-use crate::rustc_middle::ty::Subst;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
@@ -8,7 +7,8 @@ use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
-use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
+use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
+use rustc_hir_typeck::{FnCtxt, Inherited};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::Mutability;
@@ -19,7 +19,6 @@ use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitP
use rustc_semver::RustcVersion;
use rustc_span::{sym, Symbol};
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
-use rustc_typeck::check::{FnCtxt, Inherited};
use std::cmp::max;
use super::UNNECESSARY_TO_OWNED;
@@ -133,12 +132,11 @@ fn check_addr_of_expr(
cx,
UNNECESSARY_TO_OWNED,
parent.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"use",
format!(
- "{:&>width$}{}",
+ "{:&>width$}{receiver_snippet}",
"",
- receiver_snippet,
width = n_target_refs - n_receiver_refs
),
Applicability::MachineApplicable,
@@ -155,7 +153,7 @@ fn check_addr_of_expr(
cx,
UNNECESSARY_TO_OWNED,
parent.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"use",
receiver_snippet,
Applicability::MachineApplicable,
@@ -165,7 +163,7 @@ fn check_addr_of_expr(
cx,
UNNECESSARY_TO_OWNED,
expr.span.with_lo(receiver.span.hi()),
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"remove this",
String::new(),
Applicability::MachineApplicable,
@@ -182,9 +180,9 @@ fn check_addr_of_expr(
cx,
UNNECESSARY_TO_OWNED,
parent.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"use",
- format!("{}.as_ref()", receiver_snippet),
+ format!("{receiver_snippet}.as_ref()"),
Applicability::MachineApplicable,
);
return true;
@@ -229,9 +227,9 @@ fn check_into_iter_call_arg(
cx,
UNNECESSARY_TO_OWNED,
parent.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"use",
- format!("{}.iter().{}()", receiver_snippet, cloned_or_copied),
+ format!("{receiver_snippet}.iter().{cloned_or_copied}()"),
Applicability::MaybeIncorrect,
);
return true;
@@ -269,16 +267,16 @@ fn check_other_call_arg<'tcx>(
// We can't add an `&` when the trait is `Deref` because `Target = &T` won't match
// `Target = T`.
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
- let n_refs = max(n_refs, if is_copy(cx, receiver_ty) { 0 } else { 1 });
+ let n_refs = max(n_refs, usize::from(!is_copy(cx, receiver_ty)));
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
then {
span_lint_and_sugg(
cx,
UNNECESSARY_TO_OWNED,
maybe_arg.span,
- &format!("unnecessary use of `{}`", method_name),
+ &format!("unnecessary use of `{method_name}`"),
"use",
- format!("{:&>width$}{}", "", receiver_snippet, width = n_refs),
+ format!("{:&>n_refs$}{receiver_snippet}", ""),
Applicability::MachineApplicable,
);
return true;
@@ -365,7 +363,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
&& 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 fn_ctxt = FnCtxt::new(inherited, cx.param_env, item.hir_id());
fn_ctxt.can_coerce(ty, output_ty)
}) {
if has_lifetime(output_ty) && has_lifetime(ty) {
@@ -380,6 +378,10 @@ 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)
{
+ if cx.tcx.lang_items().require(LangItem::IntoFutureIntoFuture) == Ok(callee_def_id) {
+ return false;
+ }
+
let fn_sig = cx.tcx.fn_sig(callee_def_id).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)
@@ -418,9 +420,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
if trait_predicates.any(|predicate| {
let predicate = EarlyBinder(predicate).subst(cx.tcx, new_subst);
let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate);
- !cx.tcx
- .infer_ctxt()
- .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation))
+ !cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation)
}) {
return false;
}
diff --git a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
index ca5d33ee8..c1139d84e 100644
--- a/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/useless_asref.rs
@@ -1,11 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::walk_ptrs_ty_depth;
-use clippy_utils::{get_parent_expr, match_trait_method, paths};
+use clippy_utils::{get_parent_expr, is_trait_method};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
+use rustc_span::sym;
use super::USELESS_ASREF;
@@ -13,7 +14,7 @@ use super::USELESS_ASREF;
pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str, recvr: &hir::Expr<'_>) {
// when we get here, we've already checked that the call name is "as_ref" or "as_mut"
// check if the call is to the actual `AsRef` or `AsMut` trait
- if match_trait_method(cx, expr, &paths::ASREF_TRAIT) || match_trait_method(cx, expr, &paths::ASMUT_TRAIT) {
+ if is_trait_method(cx, expr, sym::AsRef) || is_trait_method(cx, expr, sym::AsMut) {
// check if the type after `as_ref` or `as_mut` is the same as before
let rcv_ty = cx.typeck_results().expr_ty(recvr);
let res_ty = cx.typeck_results().expr_ty(expr);
@@ -35,7 +36,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: &str,
cx,
USELESS_ASREF,
expr.span,
- &format!("this call to `{}` does nothing", call_name),
+ &format!("this call to `{call_name}` does nothing"),
"try this",
snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
index 4b368d3ff..1fbf783b8 100644
--- a/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/wrong_self_convention.rs
@@ -61,20 +61,20 @@ impl Convention {
impl fmt::Display for Convention {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
match *self {
- Self::Eq(this) => format!("`{}`", this).fmt(f),
- Self::StartsWith(this) => format!("`{}*`", this).fmt(f),
- Self::EndsWith(this) => format!("`*{}`", this).fmt(f),
- Self::NotEndsWith(this) => format!("`~{}`", this).fmt(f),
+ Self::Eq(this) => format!("`{this}`").fmt(f),
+ Self::StartsWith(this) => format!("`{this}*`").fmt(f),
+ Self::EndsWith(this) => format!("`*{this}`").fmt(f),
+ Self::NotEndsWith(this) => format!("`~{this}`").fmt(f),
Self::IsSelfTypeCopy(is_true) => {
format!("`self` type is{} `Copy`", if is_true { "" } else { " not" }).fmt(f)
},
Self::ImplementsTrait(is_true) => {
let (negation, s_suffix) = if is_true { ("", "s") } else { (" does not", "") };
- format!("method{} implement{} a trait", negation, s_suffix).fmt(f)
+ format!("method{negation} implement{s_suffix} a trait").fmt(f)
},
Self::IsTraitItem(is_true) => {
let suffix = if is_true { " is" } else { " is not" };
- format!("method{} a trait item", suffix).fmt(f)
+ format!("method{suffix} a trait item").fmt(f)
},
}
}
@@ -138,8 +138,7 @@ pub(super) fn check<'tcx>(
WRONG_SELF_CONVENTION,
first_arg_span,
&format!(
- "{} usually take {}",
- suggestion,
+ "{suggestion} usually take {}",
&self_kinds
.iter()
.map(|k| k.description())
diff --git a/src/tools/clippy/clippy_lints/src/minmax.rs b/src/tools/clippy/clippy_lints/src/minmax.rs
index 4d8579135..4f967755b 100644
--- a/src/tools/clippy/clippy_lints/src/minmax.rs
+++ b/src/tools/clippy/clippy_lints/src/minmax.rs
@@ -1,6 +1,6 @@
use clippy_utils::consts::{constant_simple, Constant};
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::{match_trait_method, paths};
+use clippy_utils::is_trait_method;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -83,7 +83,7 @@ fn min_max<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(MinMax, Cons
}
},
ExprKind::MethodCall(path, receiver, args @ [_], _) => {
- if cx.typeck_results().expr_ty(receiver).is_floating_point() || match_trait_method(cx, expr, &paths::ORD) {
+ if cx.typeck_results().expr_ty(receiver).is_floating_point() || is_trait_method(cx, expr, sym::Ord) {
if path.ident.name == sym!(max) {
fetch_const(cx, Some(receiver), args, MinMax::Max)
} else if path.ident.name == sym!(min) {
diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs
index ea245edd7..516dee20f 100644
--- a/src/tools/clippy/clippy_lints/src/misc.rs
+++ b/src/tools/clippy/clippy_lints/src/misc.rs
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::source::{snippet, snippet_opt};
use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
@@ -15,7 +14,7 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::source_map::{ExpnKind, Span};
use clippy_utils::sugg::Sugg;
-use clippy_utils::{get_parent_expr, in_constant, iter_input_pats, last_path_segment, SpanlessEq};
+use clippy_utils::{get_parent_expr, in_constant, is_integer_literal, iter_input_pats, last_path_segment, SpanlessEq};
declare_clippy_lint! {
/// ### What it does
@@ -178,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
("", sugg_init.addr())
};
let tyopt = if let Some(ty) = local.ty {
- format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, ".."))
+ format!(": &{mutopt}{ty}", ty=snippet(cx, ty.span, ".."))
} else {
String::new()
};
@@ -195,8 +194,6 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
format!(
"let {name}{tyopt} = {initref};",
name=snippet(cx, name.span, ".."),
- tyopt=tyopt,
- initref=initref,
),
Applicability::MachineApplicable,
);
@@ -222,8 +219,7 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
stmt.span,
"replace it with",
format!(
- "if {} {{ {}; }}",
- sugg,
+ "if {sugg} {{ {}; }}",
&snippet(cx, b.span, ".."),
),
Applicability::MachineApplicable, // snippet
@@ -275,9 +271,8 @@ impl<'tcx> LateLintPass<'tcx> for MiscLints {
USED_UNDERSCORE_BINDING,
expr.span,
&format!(
- "used binding `{}` which is prefixed with an underscore. A leading \
- underscore signals that a binding will not be used",
- binding
+ "used binding `{binding}` which is prefixed with an underscore. A leading \
+ underscore signals that a binding will not be used"
),
);
}
@@ -318,8 +313,7 @@ fn non_macro_local(cx: &LateContext<'_>, res: def::Res) -> bool {
fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>) {
if_chain! {
if let TyKind::Ptr(ref mut_ty) = ty.kind;
- if let ExprKind::Lit(ref lit) = e.kind;
- if let LitKind::Int(0, _) = lit.node;
+ if is_integer_literal(e, 0);
if !in_constant(cx, e.hir_id);
then {
let (msg, sugg_fn) = match mut_ty.mutbl {
@@ -328,12 +322,12 @@ fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>)
};
let (sugg, appl) = if let TyKind::Infer = mut_ty.ty.kind {
- (format!("{}()", sugg_fn), Applicability::MachineApplicable)
+ (format!("{sugg_fn}()"), Applicability::MachineApplicable)
} else if let Some(mut_ty_snip) = snippet_opt(cx, mut_ty.ty.span) {
- (format!("{}::<{}>()", sugg_fn, mut_ty_snip), Applicability::MachineApplicable)
+ (format!("{sugg_fn}::<{mut_ty_snip}>()"), Applicability::MachineApplicable)
} else {
// `MaybeIncorrect` as type inference may not work with the suggested code
- (format!("{}()", sugg_fn), Applicability::MaybeIncorrect)
+ (format!("{sugg_fn}()"), Applicability::MaybeIncorrect)
};
span_lint_and_sugg(cx, ZERO_PTR, span, msg, "try", sugg, appl);
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
index 1165c19a0..27e7f8505 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/literal_suffix.rs
@@ -6,9 +6,7 @@ use rustc_lint::EarlyContext;
use super::{SEPARATED_LITERAL_SUFFIX, UNSEPARATED_LITERAL_SUFFIX};
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &str, sugg_type: &str) {
- let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
- val
- } else {
+ let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
return; // It's useless so shouldn't lint.
};
// Do not lint when literal is unsuffixed.
@@ -18,9 +16,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
cx,
SEPARATED_LITERAL_SUFFIX,
lit.span,
- &format!("{} type suffix should not be separated by an underscore", sugg_type),
+ &format!("{sugg_type} type suffix should not be separated by an underscore"),
"remove the underscore",
- format!("{}{}", &lit_snip[..maybe_last_sep_idx], suffix),
+ format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
} else {
@@ -28,9 +26,9 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str, suffix: &s
cx,
UNSEPARATED_LITERAL_SUFFIX,
lit.span,
- &format!("{} type suffix should be separated by an underscore", sugg_type),
+ &format!("{sugg_type} type suffix should be separated by an underscore"),
"add an underscore",
- format!("{}_{}", &lit_snip[..=maybe_last_sep_idx], suffix),
+ format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
index 80e242131..263ee1e94 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mixed_case_hex_literals.rs
@@ -5,9 +5,7 @@ use rustc_lint::EarlyContext;
use super::MIXED_CASE_HEX_LITERALS;
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, suffix: &str, lit_snip: &str) {
- let maybe_last_sep_idx = if let Some(val) = lit_snip.len().checked_sub(suffix.len() + 1) {
- val
- } else {
+ let Some(maybe_last_sep_idx) = lit_snip.len().checked_sub(suffix.len() + 1) else {
return; // It's useless so shouldn't lint.
};
if maybe_last_sep_idx <= 2 {
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
index 704918c0b..c8227ca44 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/mod.rs
@@ -357,9 +357,8 @@ impl EarlyLintPass for MiscEarlyLints {
DUPLICATE_UNDERSCORE_ARGUMENT,
*correspondence,
&format!(
- "`{}` already exists, having another argument having almost the same \
- name makes code comprehension and documentation more difficult",
- arg_name
+ "`{arg_name}` already exists, having another argument having almost the same \
+ name makes code comprehension and documentation more difficult"
),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
index fff533167..676e5d40b 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/unneeded_field_pattern.rs
@@ -27,7 +27,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
pat.span,
"all the struct fields are matched to a wildcard pattern, consider using `..`",
None,
- &format!("try with `{} {{ .. }}` instead", type_name),
+ &format!("try with `{type_name} {{ .. }}` instead"),
);
return;
}
@@ -63,7 +63,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, pat: &Pat) {
"you matched a field with a wildcard pattern, consider using `..` \
instead",
None,
- &format!("try with `{} {{ {}, .. }}`", type_name, normal[..].join(", ")),
+ &format!("try with `{type_name} {{ {}, .. }}`", normal[..].join(", ")),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs b/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
index 4963bba82..9ead43ea4 100644
--- a/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
+++ b/src/tools/clippy/clippy_lints/src/misc_early/zero_prefixed_literal.rs
@@ -6,6 +6,7 @@ use rustc_lint::EarlyContext;
use super::ZERO_PREFIXED_LITERAL;
pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) {
+ let trimmed_lit_snip = lit_snip.trim_start_matches(|c| c == '_' || c == '0');
span_lint_and_then(
cx,
ZERO_PREFIXED_LITERAL,
@@ -15,15 +16,18 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit: &Lit, lit_snip: &str) {
diag.span_suggestion(
lit.span,
"if you mean to use a decimal constant, remove the `0` to avoid confusion",
- lit_snip.trim_start_matches(|c| c == '_' || c == '0').to_string(),
- Applicability::MaybeIncorrect,
- );
- diag.span_suggestion(
- lit.span,
- "if you mean to use an octal constant, use `0o`",
- format!("0o{}", lit_snip.trim_start_matches(|c| c == '_' || c == '0')),
+ trimmed_lit_snip.to_string(),
Applicability::MaybeIncorrect,
);
+ // do not advise to use octal form if the literal cannot be expressed in base 8.
+ if !lit_snip.contains(|c| c == '8' || c == '9') {
+ diag.span_suggestion(
+ lit.span,
+ "if you mean to use an octal constant, use `0o`",
+ format!("0o{trimmed_lit_snip}"),
+ Applicability::MaybeIncorrect,
+ );
+ }
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
index 020efeaeb..9de4b56b7 100644
--- a/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
+++ b/src/tools/clippy/clippy_lints/src/mismatching_type_param_order.rs
@@ -70,9 +70,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
// find the type that the Impl is for
// only lint on struct/enum/union for now
- let defid = match path.res {
- Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) => defid,
- _ => return,
+ let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, defid) = path.res else {
+ return
};
// get the names of the generic parameters in the type
@@ -91,10 +90,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeParamMismatch {
let type_name = segment.ident;
for (i, (impl_param_name, impl_param_span)) in impl_params.iter().enumerate() {
if mismatch_param_name(i, impl_param_name, &type_param_names_hashmap) {
- let msg = format!("`{}` has a similarly named generic type parameter `{}` in its declaration, but in a different order",
- type_name, impl_param_name);
- let help = format!("try `{}`, or a name that does not conflict with `{}`'s generic params",
- type_param_names[i], type_name);
+ let msg = format!("`{type_name}` has a similarly named generic type parameter `{impl_param_name}` in its declaration, but in a different order");
+ let help = format!("try `{}`, or a name that does not conflict with `{type_name}`'s generic params",
+ type_param_names[i]);
span_lint_and_help(
cx,
MISMATCHING_TYPE_PARAM_ORDER,
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 bc304c081..71cc0d0a8 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
@@ -8,12 +8,12 @@ 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_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
// Const fns are not allowed as methods in a trait.
{
- let parent = cx.tcx.hir().get_parent_item(hir_id);
+ let parent = cx.tcx.hir().get_parent_item(hir_id).def_id;
if parent != CRATE_DEF_ID {
if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent) {
if let hir::ItemKind::Trait(..) = &item.kind {
diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs
index 3701fdb4a..2a63681db 100644
--- a/src/tools/clippy/clippy_lints/src/missing_doc.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs
@@ -103,7 +103,7 @@ impl MissingDoc {
cx,
MISSING_DOCS_IN_PRIVATE_ITEMS,
sp,
- &format!("missing documentation for {} {}", article, desc),
+ &format!("missing documentation for {article} {desc}"),
);
}
}
@@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
hir::ItemKind::Fn(..) => {
// ignore main()
if it.ident.name == sym::main {
- let at_root = cx.tcx.local_parent(it.def_id) == CRATE_DEF_ID;
+ let at_root = cx.tcx.local_parent(it.owner_id.def_id) == CRATE_DEF_ID;
if at_root {
return;
}
@@ -155,7 +155,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
| hir::ItemKind::Use(..) => return,
};
- let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(it.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(it.hir_id());
if !is_from_proc_macro(cx, it) {
@@ -164,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
- let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());
+ let (article, desc) = cx.tcx.article_and_description(trait_item.owner_id.to_def_id());
let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
if !is_from_proc_macro(cx, trait_item) {
@@ -174,7 +174,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
// If the method is an impl for a trait, don't doc.
- if let Some(cid) = cx.tcx.associated_item(impl_item.def_id).impl_container(cx.tcx) {
+ if let Some(cid) = cx.tcx.associated_item(impl_item.owner_id).impl_container(cx.tcx) {
if cx.tcx.impl_trait_ref(cid).is_some() {
return;
}
@@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDoc {
return;
}
- let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
+ 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);
diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
index 3d0a23822..872679f25 100644
--- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs
@@ -58,7 +58,8 @@ impl_lint_pass!(ImportRename => [MISSING_ENFORCED_IMPORT_RENAMES]);
impl LateLintPass<'_> for ImportRename {
fn check_crate(&mut self, cx: &LateContext<'_>) {
for Rename { path, rename } in &self.conf_renames {
- if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &path.split("::").collect::<Vec<_>>()) {
+ let segs = path.split("::").collect::<Vec<_>>();
+ if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, None) {
self.renames.insert(id, Symbol::intern(rename));
}
}
@@ -90,9 +91,7 @@ impl LateLintPass<'_> for ImportRename {
"this import should be renamed",
"try",
format!(
- "{} as {}",
- import,
- name,
+ "{import} as {name}",
),
Applicability::MachineApplicable,
);
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 07bc2ca5d..758ce47cf 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -65,7 +65,7 @@ fn check_missing_inline_attrs(cx: &LateContext<'_>, attrs: &[ast::Attribute], sp
cx,
MISSING_INLINE_IN_PUBLIC_ITEMS,
sp,
- &format!("missing `#[inline]` for {}", desc),
+ &format!("missing `#[inline]` for {desc}"),
);
}
}
@@ -88,7 +88,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
return;
}
- if !cx.access_levels.is_exported(it.def_id) {
+ if !cx.effective_visibilities.is_exported(it.owner_id.def_id) {
return;
}
match it.kind {
@@ -105,7 +105,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
match tit_.kind {
hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => {},
hir::TraitItemKind::Fn(..) => {
- if cx.tcx.impl_defaultness(tit.id.def_id).has_value() {
+ if cx.tcx.impl_defaultness(tit.id.owner_id).has_value() {
// trait method with default body needs inline in case
// an impl is not provided
let desc = "a default trait method";
@@ -142,16 +142,16 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
}
// If the item being implemented is not exported, then we don't need #[inline]
- if !cx.access_levels.is_exported(impl_item.def_id) {
+ if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
return;
}
let desc = match impl_item.kind {
hir::ImplItemKind::Fn(..) => "a method",
- hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) => return,
+ hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => return,
};
- let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+ let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
let container_id = assoc_item.container_id(cx.tcx);
let trait_def_id = match assoc_item.container {
TraitContainer => Some(container_id),
@@ -159,7 +159,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
};
if let Some(trait_def_id) = trait_def_id {
- if trait_def_id.is_local() && !cx.access_levels.is_exported(impl_item.def_id) {
+ if trait_def_id.is_local() && !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) {
// If a trait is being implemented for an item, and the
// trait is not exported, we don't need #[inline]
return;
diff --git a/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
new file mode 100644
index 000000000..68af8a672
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
@@ -0,0 +1,98 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::is_lint_allowed;
+use clippy_utils::macros::span_is_local;
+use rustc_hir::def_id::DefIdMap;
+use rustc_hir::{Impl, Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::AssocItem;
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks if a provided method is used implicitly by a trait
+ /// implementation. A usage example would be a wrapper where every method
+ /// should perform some operation before delegating to the inner type's
+ /// implemenation.
+ ///
+ /// This lint should typically be enabled on a specific trait `impl` item
+ /// rather than globally.
+ ///
+ /// ### Why is this bad?
+ /// Indicates that a method is missing.
+ ///
+ /// ### Example
+ /// ```rust
+ /// trait Trait {
+ /// fn required();
+ ///
+ /// fn provided() {}
+ /// }
+ ///
+ /// # struct Type;
+ /// #[warn(clippy::missing_trait_methods)]
+ /// impl Trait for Type {
+ /// fn required() { /* ... */ }
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// trait Trait {
+ /// fn required();
+ ///
+ /// fn provided() {}
+ /// }
+ ///
+ /// # struct Type;
+ /// #[warn(clippy::missing_trait_methods)]
+ /// impl Trait for Type {
+ /// fn required() { /* ... */ }
+ ///
+ /// fn provided() { /* ... */ }
+ /// }
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub MISSING_TRAIT_METHODS,
+ restriction,
+ "trait implementation uses default provided method"
+}
+declare_lint_pass!(MissingTraitMethods => [MISSING_TRAIT_METHODS]);
+
+impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+ if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id())
+ && span_is_local(item.span)
+ && let ItemKind::Impl(Impl {
+ items,
+ of_trait: Some(trait_ref),
+ ..
+ }) = item.kind
+ && let Some(trait_id) = trait_ref.trait_def_id()
+ {
+ let mut provided: DefIdMap<&AssocItem> = cx
+ .tcx
+ .provided_trait_methods(trait_id)
+ .map(|assoc| (assoc.def_id, assoc))
+ .collect();
+
+ for impl_item in *items {
+ if let Some(def_id) = impl_item.trait_item_def_id {
+ provided.remove(&def_id);
+ }
+ }
+
+ for assoc in provided.values() {
+ let source_map = cx.tcx.sess.source_map();
+ let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
+
+ span_lint_and_help(
+ cx,
+ MISSING_TRAIT_METHODS,
+ source_map.guess_head_span(item.span),
+ &format!("missing trait method provided by default: `{}`", assoc.name),
+ Some(definition_span),
+ "implement the method",
+ );
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index a2419c277..675297634 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -190,10 +190,7 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) {
if parent_id == cur_id {
break;
}
- let parent_node = match map.find(parent_id) {
- Some(parent) => parent,
- None => break,
- };
+ let Some(parent_node) = map.find(parent_id) else { break };
let stop_early = match parent_node {
Node::Expr(expr) => check_expr(vis, expr),
diff --git a/src/tools/clippy/clippy_lints/src/module_style.rs b/src/tools/clippy/clippy_lints/src/module_style.rs
index 0a3936572..0742943df 100644
--- a/src/tools/clippy/clippy_lints/src/module_style.rs
+++ b/src/tools/clippy/clippy_lints/src/module_style.rs
@@ -2,7 +2,7 @@ use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_lint::{EarlyContext, EarlyLintPass, Level, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::{FileName, RealFileName, SourceFile, Span, SyntaxContext};
+use rustc_span::{FileName, SourceFile, Span, SyntaxContext};
use std::ffi::OsStr;
use std::path::{Component, Path};
@@ -79,7 +79,7 @@ impl EarlyLintPass for ModStyle {
let files = cx.sess().source_map().files();
- let RealFileName::LocalPath(trim_to_src) = &cx.sess().opts.working_dir else { return };
+ let Some(trim_to_src) = cx.sess().opts.working_dir.local_path() else { return };
// `folder_segments` is all unique folder path segments `path/to/foo.rs` gives
// `[path, to]` but not foo
@@ -90,7 +90,7 @@ impl EarlyLintPass for ModStyle {
// `{ foo => path/to/foo.rs, .. }
let mut file_map = FxHashMap::default();
for file in files.iter() {
- if let FileName::Real(RealFileName::LocalPath(lp)) = &file.name {
+ if let FileName::Real(name) = &file.name && let Some(lp) = name.local_path() {
let path = if lp.is_relative() {
lp
} else if let Ok(relative) = lp.strip_prefix(trim_to_src) {
@@ -117,12 +117,8 @@ impl EarlyLintPass for ModStyle {
cx.struct_span_lint(
SELF_NAMED_MODULE_FILES,
Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
- |build| {
- let mut lint =
- build.build(&format!("`mod.rs` files are required, found `{}`", path.display()));
- lint.help(&format!("move `{}` to `{}`", path.display(), correct.display(),));
- lint.emit();
- },
+ format!("`mod.rs` files are required, found `{}`", path.display()),
+ |lint| lint.help(format!("move `{}` to `{}`", path.display(), correct.display(),)),
);
}
}
@@ -156,11 +152,8 @@ fn check_self_named_mod_exists(cx: &EarlyContext<'_>, path: &Path, file: &Source
cx.struct_span_lint(
MOD_MODULE_FILES,
Span::new(file.start_pos, file.start_pos, SyntaxContext::root(), None),
- |build| {
- let mut lint = build.build(&format!("`mod.rs` files are not allowed, found `{}`", path.display()));
- lint.help(&format!("move `{}` to `{}`", path.display(), mod_file.display(),));
- lint.emit();
- },
+ format!("`mod.rs` files are not allowed, found `{}`", path.display()),
+ |lint| lint.help(format!("move `{}` to `{}`", path.display(), mod_file.display())),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/mut_key.rs b/src/tools/clippy/clippy_lints/src/mut_key.rs
index 4db103bbc..4b62dcdff 100644
--- a/src/tools/clippy/clippy_lints/src/mut_key.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_key.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
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.def_id).is_none() {
+ if trait_ref_of_method(cx, item.owner_id.def_id).is_none() {
check_sig(cx, item.hir_id(), sig.decl);
}
}
@@ -136,12 +136,14 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
/// [`Hash`] or [`Ord`].
fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
match *ty.kind() {
- Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span),
+ Ref(_, inner_ty, mutbl) => {
+ mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span)
+ }
Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span),
Array(inner_ty, size) => {
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
&& is_interior_mutable_type(cx, inner_ty, span)
- },
+ }
Tuple(fields) => fields.iter().any(|ty| is_interior_mutable_type(cx, ty, span)),
Adt(def, substs) => {
// Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
@@ -167,9 +169,9 @@ fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Sp
} else {
!ty.has_escaping_bound_vars()
&& cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
- && !ty.is_freeze(cx.tcx.at(span), cx.param_env)
+ && !ty.is_freeze(cx.tcx, cx.param_env)
}
- },
+ }
_ => false,
}
}
diff --git a/src/tools/clippy/clippy_lints/src/mut_reference.rs b/src/tools/clippy/clippy_lints/src/mut_reference.rs
index 82dc03ef5..4547ed7ea 100644
--- a/src/tools/clippy/clippy_lints/src/mut_reference.rs
+++ b/src/tools/clippy/clippy_lints/src/mut_reference.rs
@@ -1,7 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::iter;
@@ -88,7 +87,7 @@ fn check_arguments<'tcx>(
cx,
UNNECESSARY_MUT_PASSED,
argument.span,
- &format!("the {} `{}` doesn't need a mutable reference", fn_kind, name),
+ &format!("the {fn_kind} `{name}` doesn't need a mutable reference"),
);
}
},
diff --git a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
index 44fdf84c6..d8647a991 100644
--- a/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
+++ b/src/tools/clippy/clippy_lints/src/mutable_debug_assertion.rs
@@ -56,10 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for DebugAssertWithMutCall {
cx,
DEBUG_ASSERT_WITH_MUT_CALL,
span,
- &format!(
- "do not call a function with mutable arguments inside of `{}!`",
- macro_name
- ),
+ &format!("do not call a function with mutable arguments inside of `{macro_name}!`"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
index a98577093..09cb53331 100644
--- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
+++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs
@@ -84,9 +84,8 @@ impl<'tcx> LateLintPass<'tcx> for Mutex {
let mutex_param = subst.type_at(0);
if let Some(atomic_name) = get_atomic_name(mutex_param) {
let msg = format!(
- "consider using an `{}` instead of a `Mutex` here; if you just want the locking \
- behavior and not the internal type, consider using `Mutex<()>`",
- atomic_name
+ "consider using an `{atomic_name}` instead of a `Mutex` here; if you just want the locking \
+ behavior and not the internal type, consider using `Mutex<()>`"
);
match *mutex_param.kind() {
ty::Uint(t) if t != ty::UintTy::Usize => span_lint(cx, MUTEX_INTEGER, expr.span, &msg),
diff --git a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
index b8855e5ad..10c3ff026 100644
--- a/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_borrowed_ref.rs
@@ -1,6 +1,4 @@
use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::source::snippet_with_applicability;
-use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, Mutability, Node, Pat, PatKind};
use rustc_lint::{LateContext, LateLintPass};
@@ -8,36 +6,26 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
/// ### What it does
- /// Checks for bindings that destructure a reference and borrow the inner
+ /// Checks for bindings that needlessly destructure a reference and borrow the inner
/// value with `&ref`.
///
/// ### Why is this bad?
/// This pattern has no effect in almost all cases.
///
- /// ### Known problems
- /// In some cases, `&ref` is needed to avoid a lifetime mismatch error.
- /// Example:
- /// ```rust
- /// fn foo(a: &Option<String>, b: &Option<String>) {
- /// match (a, b) {
- /// (None, &ref c) | (&ref c, None) => (),
- /// (&Some(ref c), _) => (),
- /// };
- /// }
- /// ```
- ///
/// ### Example
/// ```rust
/// let mut v = Vec::<String>::new();
- /// # #[allow(unused)]
/// v.iter_mut().filter(|&ref a| a.is_empty());
+ ///
+ /// if let &[ref first, ref second] = v.as_slice() {}
/// ```
///
/// Use instead:
/// ```rust
/// let mut v = Vec::<String>::new();
- /// # #[allow(unused)]
/// v.iter_mut().filter(|a| a.is_empty());
+ ///
+ /// if let [first, second] = v.as_slice() {}
/// ```
#[clippy::version = "pre 1.29.0"]
pub NEEDLESS_BORROWED_REFERENCE,
@@ -54,34 +42,83 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef {
return;
}
- if_chain! {
- // Only lint immutable refs, because `&mut ref T` may be useful.
- if let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind;
+ // Do not lint patterns that are part of an OR `|` pattern, the binding mode must match in all arms
+ for (_, node) in cx.tcx.hir().parent_iter(pat.hir_id) {
+ let Node::Pat(pat) = node else { break };
+
+ if matches!(pat.kind, PatKind::Or(_)) {
+ return;
+ }
+ }
+
+ // Only lint immutable refs, because `&mut ref T` may be useful.
+ let PatKind::Ref(sub_pat, Mutability::Not) = pat.kind else { return };
+ match sub_pat.kind {
// Check sub_pat got a `ref` keyword (excluding `ref mut`).
- if let PatKind::Binding(BindingAnnotation::REF, .., spanned_name, _) = sub_pat.kind;
- let parent_id = cx.tcx.hir().get_parent_node(pat.hir_id);
- if let Some(parent_node) = cx.tcx.hir().find(parent_id);
- then {
- // do not recurse within patterns, as they may have other references
- // XXXManishearth we can relax this constraint if we only check patterns
- // with a single ref pattern inside them
- if let Node::Pat(_) = parent_node {
- return;
+ PatKind::Binding(BindingAnnotation::REF, _, ident, None) => {
+ span_lint_and_then(
+ cx,
+ NEEDLESS_BORROWED_REFERENCE,
+ pat.span,
+ "this pattern takes a reference on something that is being dereferenced",
+ |diag| {
+ // `&ref ident`
+ // ^^^^^
+ let span = pat.span.until(ident.span);
+ diag.span_suggestion_verbose(
+ span,
+ "try removing the `&ref` part",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ },
+ );
+ },
+ // Slices where each element is `ref`: `&[ref a, ref b, ..., ref z]`
+ PatKind::Slice(
+ before,
+ None
+ | Some(Pat {
+ kind: PatKind::Wild, ..
+ }),
+ after,
+ ) => {
+ let mut suggestions = Vec::new();
+
+ for element_pat in itertools::chain(before, after) {
+ if let PatKind::Binding(BindingAnnotation::REF, _, ident, None) = element_pat.kind {
+ // `&[..., ref ident, ...]`
+ // ^^^^
+ let span = element_pat.span.until(ident.span);
+ suggestions.push((span, String::new()));
+ } else {
+ return;
+ }
}
- let mut applicability = Applicability::MachineApplicable;
- span_lint_and_then(cx, NEEDLESS_BORROWED_REFERENCE, pat.span,
- "this pattern takes a reference on something that is being de-referenced",
- |diag| {
- let hint = snippet_with_applicability(cx, spanned_name.span, "..", &mut applicability).into_owned();
- diag.span_suggestion(
- pat.span,
- "try removing the `&ref` part and just keep",
- hint,
- applicability,
- );
- });
- }
+
+ if !suggestions.is_empty() {
+ span_lint_and_then(
+ cx,
+ NEEDLESS_BORROWED_REFERENCE,
+ pat.span,
+ "dereferencing a slice pattern where every element takes a reference",
+ |diag| {
+ // `&[...]`
+ // ^
+ let span = pat.span.until(sub_pat.span);
+ suggestions.push((span, String::new()));
+
+ diag.multipart_suggestion(
+ "try removing the `&` and `ref` parts",
+ suggestions,
+ Applicability::MachineApplicable,
+ );
+ },
+ );
+ }
+ },
+ _ => {},
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/needless_continue.rs b/src/tools/clippy/clippy_lints/src/needless_continue.rs
index 98a3bce1f..6f0e75546 100644
--- a/src/tools/clippy/clippy_lints/src/needless_continue.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_continue.rs
@@ -309,7 +309,7 @@ fn emit_warning<'a>(cx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str,
expr.span,
message,
None,
- &format!("{}\n{}", header, snip),
+ &format!("{header}\n{snip}"),
);
}
@@ -322,10 +322,7 @@ fn suggestion_snippet_for_continue_inside_if<'a>(cx: &EarlyContext<'_>, data: &'
let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
format!(
- "{indent}if {} {}\n{indent}{}",
- cond_code,
- continue_code,
- else_code,
+ "{indent}if {cond_code} {continue_code}\n{indent}{else_code}",
indent = " ".repeat(indent_if),
)
}
@@ -349,7 +346,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data:
let span = cx.sess().source_map().stmt_span(stmt.span, data.loop_block.span);
let snip = snippet_block(cx, span, "..", None).into_owned();
snip.lines()
- .map(|line| format!("{}{}", " ".repeat(indent), line))
+ .map(|line| format!("{}{line}", " ".repeat(indent)))
.collect::<Vec<_>>()
.join("\n")
})
@@ -358,10 +355,7 @@ fn suggestion_snippet_for_continue_inside_else<'a>(cx: &EarlyContext<'_>, data:
let indent_if = indent_of(cx, data.if_expr.span).unwrap_or(0);
format!(
- "{indent_if}if {} {}\n{indent}// merged code follows:\n{}\n{indent_if}}}",
- cond_code,
- block_code,
- to_annex,
+ "{indent_if}if {cond_code} {block_code}\n{indent}// merged code follows:\n{to_annex}\n{indent_if}}}",
indent = " ".repeat(indent),
indent_if = " ".repeat(indent_if),
)
diff --git a/src/tools/clippy/clippy_lints/src/needless_for_each.rs b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
index 3233d87c0..c3b633fd6 100644
--- a/src/tools/clippy/clippy_lints/src/needless_for_each.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_for_each.rs
@@ -49,9 +49,8 @@ declare_lint_pass!(NeedlessForEach => [NEEDLESS_FOR_EACH]);
impl<'tcx> LateLintPass<'tcx> for NeedlessForEach {
fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) {
- let expr = match stmt.kind {
- StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr,
- _ => return,
+ let (StmtKind::Expr(expr) | StmtKind::Semi(expr)) = stmt.kind else {
+ return
};
if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
index de99f1d70..67debe7e0 100644
--- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs
@@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::path_to_local;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::needs_ordered_drop;
-use clippy_utils::visitors::{expr_visitor, expr_visitor_no_bodies, is_local_used};
+use clippy_utils::visitors::{for_each_expr, for_each_expr_with_closures, is_local_used};
+use core::ops::ControlFlow;
use rustc_errors::{Applicability, MultiSpan};
-use rustc_hir::intravisit::Visitor;
use rustc_hir::{
BindingAnnotation, Block, Expr, ExprKind, HirId, Local, LocalSource, MatchSource, Node, Pat, PatKind, Stmt,
StmtKind,
@@ -64,31 +64,25 @@ declare_clippy_lint! {
declare_lint_pass!(NeedlessLateInit => [NEEDLESS_LATE_INIT]);
fn contains_assign_expr<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> bool {
- let mut seen = false;
- expr_visitor(cx, |expr| {
- if let ExprKind::Assign(..) = expr.kind {
- seen = true;
+ for_each_expr_with_closures(cx, stmt, |e| {
+ if matches!(e.kind, ExprKind::Assign(..)) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
-
- !seen
})
- .visit_stmt(stmt);
-
- seen
+ .is_some()
}
fn contains_let(cond: &Expr<'_>) -> bool {
- let mut seen = false;
- expr_visitor_no_bodies(|expr| {
- if let ExprKind::Let(_) = expr.kind {
- seen = true;
+ for_each_expr(cond, |e| {
+ if matches!(e.kind, ExprKind::Let(_)) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
-
- !seen
})
- .visit_expr(cond);
-
- seen
+ .is_some()
}
fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool {
@@ -186,10 +180,13 @@ fn assignment_suggestions<'tcx>(
let suggestions = assignments
.iter()
.flat_map(|assignment| {
- [
- assignment.span.until(assignment.rhs_span),
- assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()),
- ]
+ let mut spans = vec![assignment.span.until(assignment.rhs_span)];
+
+ if assignment.rhs_span.hi() != assignment.span.hi() {
+ spans.push(assignment.rhs_span.shrink_to_hi().with_hi(assignment.span.hi()));
+ }
+
+ spans
})
.map(|span| (span, String::new()))
.collect::<Vec<(Span, String)>>();
@@ -287,7 +284,7 @@ fn check<'tcx>(
diag.span_suggestion(
assign.lhs_span,
- &format!("declare `{}` here", binding_name),
+ &format!("declare `{binding_name}` here"),
let_snippet,
Applicability::MachineApplicable,
);
@@ -307,8 +304,8 @@ fn check<'tcx>(
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
- &format!("declare `{}` here", binding_name),
- format!("{} = ", let_snippet),
+ &format!("declare `{binding_name}` here"),
+ format!("{let_snippet} = "),
applicability,
);
@@ -338,8 +335,8 @@ fn check<'tcx>(
diag.span_suggestion_verbose(
usage.stmt.span.shrink_to_lo(),
- &format!("declare `{}` here", binding_name),
- format!("{} = ", let_snippet),
+ &format!("declare `{binding_name}` here"),
+ format!("{let_snippet} = "),
applicability,
);
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 060037ed4..b2e9ce5c9 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
@@ -12,6 +12,7 @@ use rustc_hir::{
BindingAnnotation, Body, FnDecl, GenericArg, HirId, Impl, ItemKind, Mutability, Node, PatKind, QPath, TyKind,
};
use rustc_hir::{HirIdMap, HirIdSet};
+use rustc_hir_typeck::expr_use_visitor as euv;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
@@ -22,7 +23,6 @@ use rustc_span::{sym, Span};
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
use rustc_trait_selection::traits::misc::can_type_implement_copy;
-use rustc_typeck::expr_use_visitor as euv;
use std::borrow::Cow;
declare_clippy_lint! {
@@ -138,10 +138,8 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
..
} = {
let mut ctx = MovedVariablesCtxt::default();
- cx.tcx.infer_ctxt().enter(|infcx| {
- euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
- .consume_body(body);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
ctx
};
@@ -186,6 +184,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
if !is_self(arg);
if !ty.is_mutable_ptr();
if !is_copy(cx, ty);
+ if ty.is_sized(cx.tcx, cx.param_env);
if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[]));
if !implements_borrow_trait;
if !all_borrowable_trait;
@@ -236,7 +235,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
snippet_opt(cx, span)
.map_or(
"change the call to".into(),
- |x| Cow::from(format!("change `{}` to", x)),
+ |x| Cow::from(format!("change `{x}` to")),
)
.as_ref(),
suggestion,
@@ -266,7 +265,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
snippet_opt(cx, span)
.map_or(
"change the call to".into(),
- |x| Cow::from(format!("change `{}` to", x))
+ |x| Cow::from(format!("change `{x}` to"))
)
.as_ref(),
suggestion,
@@ -341,5 +340,11 @@ impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt {
fn mutate(&mut self, _: &euv::PlaceWithHirId<'tcx>, _: HirId) {}
- fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+ fn fake_read(
+ &mut self,
+ _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
+ _: FakeReadCause,
+ _: HirId,
+ ) {
+ }
}
diff --git a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
index 8f85b0059..97c8cfbd3 100644
--- a/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_question_mark.rs
@@ -1,11 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_lang_ctor;
+use clippy_utils::path_res;
use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::LangItem::{OptionSome, ResultOk};
+use rustc_hir::def::{DefKind, Res};
use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::DefIdTree;
use rustc_session::{declare_lint_pass, declare_tool_lint};
declare_clippy_lint! {
@@ -112,11 +113,12 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! {
- if let ExprKind::Call(path, [arg]) = &expr.kind;
- if let ExprKind::Path(ref qpath) = &path.kind;
- let sugg_remove = if is_lang_ctor(cx, qpath, OptionSome) {
+ if let ExprKind::Call(path, [arg]) = expr.kind;
+ if let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path);
+ if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
+ let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
"Some()"
- } else if is_lang_ctor(cx, qpath, ResultOk) {
+ } else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) {
"Ok()"
} else {
return;
@@ -134,7 +136,7 @@ fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
NEEDLESS_QUESTION_MARK,
expr.span,
"question mark operator is useless here",
- &format!("try removing question mark and `{}`", sugg_remove),
+ &format!("try removing question mark and `{sugg_remove}`"),
format!("{}", snippet(cx, inner_expr.span, r#""...""#)),
Applicability::MachineApplicable,
);
diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
index a7e0e3578..5c2b96f5b 100644
--- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs
@@ -1,11 +1,11 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::implements_trait;
-use clippy_utils::{self, get_trait_def_id, paths};
use if_chain::if_chain;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
@@ -47,18 +47,16 @@ declare_lint_pass!(NoNegCompOpForPartialOrd => [NEG_CMP_OP_ON_PARTIAL_ORD]);
impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
-
if !in_external_macro(cx.sess(), expr.span);
if let ExprKind::Unary(UnOp::Not, inner) = expr.kind;
if let ExprKind::Binary(ref op, left, _) = inner.kind;
if let BinOpKind::Le | BinOpKind::Ge | BinOpKind::Lt | BinOpKind::Gt = op.node;
then {
-
let ty = cx.typeck_results().expr_ty(left);
let implements_ord = {
- if let Some(id) = get_trait_def_id(cx, &paths::ORD) {
+ if let Some(id) = cx.tcx.get_diagnostic_item(sym::Ord) {
implements_trait(cx, ty, id, &[])
} else {
return;
@@ -81,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd {
"the use of negated comparison operators on partially ordered \
types produces code that is hard to read and refactor, please \
consider using the `partial_cmp` method instead, to make it \
- clear that the two values could be incomparable"
+ clear that the two values could be incomparable",
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/neg_multiply.rs b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
index b087cfb36..fb9a4abd0 100644
--- a/src/tools/clippy/clippy_lints/src/neg_multiply.rs
+++ b/src/tools/clippy/clippy_lints/src/neg_multiply.rs
@@ -62,9 +62,9 @@ fn check_mul(cx: &LateContext<'_>, span: Span, lit: &Expr<'_>, exp: &Expr<'_>) {
let mut applicability = Applicability::MachineApplicable;
let snip = snippet_with_applicability(cx, exp.span, "..", &mut applicability);
let suggestion = if exp.precedence().order() < PREC_PREFIX && !has_enclosing_paren(&snip) {
- format!("-({})", snip)
+ format!("-({snip})")
} else {
- format!("-{}", snip)
+ format!("-{snip}")
};
span_lint_and_sugg(
cx,
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 5c45ee6d9..54a3c82b7 100644
--- a/src/tools/clippy/clippy_lints/src/new_without_default.rs
+++ b/src/tools/clippy/clippy_lints/src/new_without_default.rs
@@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
// can't be implemented for unsafe new
return;
}
- if cx.tcx.is_doc_hidden(impl_item.def_id) {
+ if cx.tcx.is_doc_hidden(impl_item.owner_id.def_id) {
// shouldn't be implemented when it is hidden in docs
return;
}
@@ -96,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
if_chain! {
if sig.decl.inputs.is_empty();
if name == sym::new;
- if cx.access_levels.is_reachable(impl_item.def_id);
+ 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);
if self_ty == return_ty(cx, id);
@@ -136,8 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
id,
impl_item.span,
&format!(
- "you should consider adding a `Default` implementation for `{}`",
- self_type_snip
+ "you should consider adding a `Default` implementation for `{self_type_snip}`"
),
|diag| {
diag.suggest_prepend_item(
@@ -161,9 +160,9 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
fn create_new_without_default_suggest_msg(self_type_snip: &str, generics_sugg: &str) -> String {
#[rustfmt::skip]
format!(
-"impl{} Default for {} {{
+"impl{generics_sugg} Default for {self_type_snip} {{
fn default() -> Self {{
Self::new()
}}
-}}", generics_sugg, self_type_snip)
+}}")
}
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 72c86f28b..2a3bd4ee6 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -13,14 +13,14 @@ use rustc_hir::def_id::DefId;
use rustc_hir::{
BodyId, Expr, ExprKind, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp,
};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass, Lint};
use rustc_middle::mir;
use rustc_middle::mir::interpret::{ConstValue, ErrorHandled};
use rustc_middle::ty::adjustment::Adjust;
use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{sym, InnerSpan, Span, DUMMY_SP};
-use rustc_typeck::hir_ty_to_ty;
+use rustc_span::{sym, InnerSpan, Span};
// FIXME: this is a correctness problem but there's no suitable
// warn-by-default category.
@@ -136,7 +136,7 @@ fn is_unfrozen<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
// since it works when a pointer indirection involves (`Cell<*const T>`).
// Making up a `ParamEnv` where every generic params and assoc types are `Freeze`is another option;
// but I'm not sure whether it's a decent way, if possible.
- cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx.at(DUMMY_SP), cx.param_env)
+ cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env)
}
fn is_value_unfrozen_raw<'tcx>(
@@ -149,6 +149,9 @@ fn is_value_unfrozen_raw<'tcx>(
// the fact that we have to dig into every structs to search enums
// leads us to the point checking `UnsafeCell` directly is the only option.
ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
+ // As of 2022-09-08 miri doesn't track which union field is active so there's no safe way to check the
+ // contained value.
+ ty::Adt(def, ..) if def.is_union() => false,
ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
val.fields.iter().any(|field| inner(cx, *field))
@@ -195,7 +198,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D
let result = cx.tcx.const_eval_resolve(
cx.param_env,
- ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
);
is_value_unfrozen_raw(cx, result, ty)
@@ -286,7 +289,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
if let ImplItemKind::Const(hir_ty, body_id) = &impl_item.kind {
- let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let item_def_id = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let item = cx.tcx.hir().expect_item(item_def_id);
match &item.kind {
@@ -300,7 +303,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
if let Some(of_trait_def_id) = of_trait_ref.trait_def_id();
if let Some(of_assoc_item) = cx
.tcx
- .associated_item(impl_item.def_id)
+ .associated_item(impl_item.owner_id)
.trait_item_def_id;
if cx
.tcx
@@ -354,9 +357,8 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst {
}
// Make sure it is a const item.
- let item_def_id = match cx.qpath_res(qpath, expr.hir_id) {
- Res::Def(DefKind::Const | DefKind::AssocConst, did) => did,
- _ => return,
+ let Res::Def(DefKind::Const | DefKind::AssocConst, item_def_id) = cx.qpath_res(qpath, expr.hir_id) else {
+ return
};
// Climb up to resolve any field access and explicit referencing.
diff --git a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
index b96af06b8..9f6917c14 100644
--- a/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
+++ b/src/tools/clippy/clippy_lints/src/non_expressive_names.rs
@@ -15,6 +15,10 @@ declare_clippy_lint! {
/// ### What it does
/// Checks for names that are very similar and thus confusing.
///
+ /// Note: this lint looks for similar names throughout each
+ /// scope. To allow it, you need to allow it on the scope
+ /// level, not on the name that is reported.
+ ///
/// ### Why is this bad?
/// It's hard to distinguish between names that differ only
/// by a single character.
@@ -108,10 +112,7 @@ impl<'a, 'tcx> SimilarNamesLocalVisitor<'a, 'tcx> {
self.cx,
MANY_SINGLE_CHAR_NAMES,
span,
- &format!(
- "{} bindings with single-character names in scope",
- num_single_char_names
- ),
+ &format!("{num_single_char_names} bindings with single-character names in scope"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index 25fb4f0f4..2ecb04874 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,12 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
-use clippy_utils::ty::match_type;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
@@ -49,14 +50,13 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
if_chain! {
if (path.ident.name == sym!(mode)
&& (match_type(cx, obj_ty, &paths::OPEN_OPTIONS)
- || match_type(cx, obj_ty, &paths::DIR_BUILDER)))
+ || is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder)))
|| (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS));
if let ExprKind::Lit(_) = param.kind;
then {
- let snip = match snippet_opt(cx, param.span) {
- Some(s) => s,
- _ => return,
+ let Some(snip) = snippet_opt(cx, param.span) else {
+ return
};
if !snip.starts_with("0o") {
@@ -71,16 +71,10 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
if let ExprKind::Lit(_) = param.kind;
-
+ if let Some(snip) = snippet_opt(cx, param.span);
+ if !snip.starts_with("0o");
then {
- let snip = match snippet_opt(cx, param.span) {
- Some(s) => s,
- _ => return,
- };
-
- if !snip.starts_with("0o") {
- show_error(cx, param);
- }
+ show_error(cx, param);
}
}
},
diff --git a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
index ddef7352d..714c0ff22 100644
--- a/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
+++ b/src/tools/clippy/clippy_lints/src/non_send_fields_in_send_ty.rs
@@ -89,7 +89,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSendFieldInSendTy {
if let Some(trait_id) = trait_ref.trait_def_id();
if send_trait == trait_id;
if hir_impl.polarity == ImplPolarity::Positive;
- if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.def_id);
+ if let Some(ty_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id);
if let self_ty = ty_trait_ref.self_ty();
if let ty::Adt(adt_def, impl_trait_substs) = self_ty.kind();
then {
diff --git a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
index 4722c0310..6c909e5ed 100644
--- a/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
+++ b/src/tools/clippy/clippy_lints/src/nonstandard_macro_braces.rs
@@ -3,16 +3,17 @@ use std::{
hash::{Hash, Hasher},
};
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use if_chain::if_chain;
use rustc_ast::ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::hygiene::{ExpnKind, MacroKind};
-use rustc_span::{Span, Symbol};
+use rustc_span::Span;
use serde::{de, Deserialize};
declare_clippy_lint! {
@@ -39,8 +40,8 @@ declare_clippy_lint! {
const BRACES: &[(&str, &str)] = &[("(", ")"), ("{", "}"), ("[", "]")];
-/// The (name, (open brace, close brace), source snippet)
-type MacroInfo<'a> = (Symbol, &'a (String, String), String);
+/// The (callsite span, (open brace, close brace), source snippet)
+type MacroInfo<'a> = (Span, &'a (String, String), String);
#[derive(Clone, Debug, Default)]
pub struct MacroBraces {
@@ -62,33 +63,29 @@ impl_lint_pass!(MacroBraces => [NONSTANDARD_MACRO_BRACES]);
impl EarlyLintPass for MacroBraces {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
- if let Some((name, braces, snip)) = is_offending_macro(cx, item.span, self) {
- let span = item.span.ctxt().outer_expn_data().call_site;
- emit_help(cx, snip, braces, name, span);
+ if let Some((span, braces, snip)) = is_offending_macro(cx, item.span, self) {
+ emit_help(cx, &snip, braces, span);
self.done.insert(span);
}
}
fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) {
- if let Some((name, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
- let span = stmt.span.ctxt().outer_expn_data().call_site;
- emit_help(cx, snip, braces, name, span);
+ if let Some((span, braces, snip)) = is_offending_macro(cx, stmt.span, self) {
+ emit_help(cx, &snip, braces, span);
self.done.insert(span);
}
}
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
- if let Some((name, braces, snip)) = is_offending_macro(cx, expr.span, self) {
- let span = expr.span.ctxt().outer_expn_data().call_site;
- emit_help(cx, snip, braces, name, span);
+ if let Some((span, braces, snip)) = is_offending_macro(cx, expr.span, self) {
+ emit_help(cx, &snip, braces, span);
self.done.insert(span);
}
}
fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) {
- if let Some((name, braces, snip)) = is_offending_macro(cx, ty.span, self) {
- let span = ty.span.ctxt().outer_expn_data().call_site;
- emit_help(cx, snip, braces, name, span);
+ if let Some((span, braces, snip)) = is_offending_macro(cx, ty.span, self) {
+ emit_help(cx, &snip, braces, span);
self.done.insert(span);
}
}
@@ -102,48 +99,44 @@ fn is_offending_macro<'a>(cx: &EarlyContext<'_>, span: Span, mac_braces: &'a Mac
.last()
.map_or(false, |e| e.macro_def_id.map_or(false, DefId::is_local))
};
+ let span_call_site = span.ctxt().outer_expn_data().call_site;
if_chain! {
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = span.ctxt().outer_expn_data().kind;
let name = mac_name.as_str();
if let Some(braces) = mac_braces.macro_braces.get(name);
- if let Some(snip) = snippet_opt(cx, span.ctxt().outer_expn_data().call_site);
+ if let Some(snip) = snippet_opt(cx, span_call_site);
// we must check only invocation sites
// https://github.com/rust-lang/rust-clippy/issues/7422
- if snip.starts_with(&format!("{}!", name));
+ if snip.starts_with(&format!("{name}!"));
if unnested_or_local();
// make formatting consistent
let c = snip.replace(' ', "");
- if !c.starts_with(&format!("{}!{}", name, braces.0));
- if !mac_braces.done.contains(&span.ctxt().outer_expn_data().call_site);
+ if !c.starts_with(&format!("{name}!{}", braces.0));
+ if !mac_braces.done.contains(&span_call_site);
then {
- Some((mac_name, braces, snip))
+ Some((span_call_site, braces, snip))
} else {
None
}
}
}
-fn emit_help(cx: &EarlyContext<'_>, snip: String, braces: &(String, String), name: Symbol, span: Span) {
- let with_space = &format!("! {}", braces.0);
- let without_space = &format!("!{}", braces.0);
- let mut help = snip;
- for b in BRACES.iter().filter(|b| b.0 != braces.0) {
- help = help.replace(b.0, &braces.0).replace(b.1, &braces.1);
- // Only `{` traditionally has space before the brace
- if braces.0 != "{" && help.contains(with_space) {
- help = help.replace(with_space, without_space);
- } else if braces.0 == "{" && help.contains(without_space) {
- help = help.replace(without_space, with_space);
- }
+fn emit_help(cx: &EarlyContext<'_>, snip: &str, braces: &(String, String), span: Span) {
+ if let Some((macro_name, macro_args_str)) = snip.split_once('!') {
+ let mut macro_args = macro_args_str.trim().to_string();
+ // now remove the wrong braces
+ macro_args.remove(0);
+ macro_args.pop();
+ span_lint_and_sugg(
+ cx,
+ NONSTANDARD_MACRO_BRACES,
+ span,
+ &format!("use of irregular braces for `{macro_name}!` macro"),
+ "consider writing",
+ format!("{macro_name}!{}{macro_args}{}", braces.0, braces.1),
+ Applicability::MachineApplicable,
+ );
}
- span_lint_and_help(
- cx,
- NONSTANDARD_MACRO_BRACES,
- span,
- &format!("use of irregular braces for `{}!` macro", name),
- Some(span),
- &format!("consider writing `{}`", help),
- );
}
fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, String)> {
@@ -184,6 +177,10 @@ fn macro_braces(conf: FxHashSet<MacroMatcher>) -> FxHashMap<String, (String, Str
name: "vec",
braces: ("[", "]"),
),
+ macro_matcher!(
+ name: "matches",
+ braces: ("(", ")"),
+ ),
]
.into_iter()
.collect::<FxHashMap<_, _>>();
@@ -269,9 +266,7 @@ impl<'de> Deserialize<'de> for MacroMatcher {
.iter()
.find(|b| b.0 == brace)
.map(|(o, c)| ((*o).to_owned(), (*c).to_owned()))
- .ok_or_else(|| {
- de::Error::custom(&format!("expected one of `(`, `{{`, `[` found `{}`", brace))
- })?,
+ .ok_or_else(|| de::Error::custom(format!("expected one of `(`, `{{`, `[` found `{brace}`")))?,
})
}
}
diff --git a/src/tools/clippy/clippy_lints/src/octal_escapes.rs b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
index bffbf20b4..f380a5065 100644
--- a/src/tools/clippy/clippy_lints/src/octal_escapes.rs
+++ b/src/tools/clippy/clippy_lints/src/octal_escapes.rs
@@ -102,7 +102,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) {
// construct a replacement escape
// the maximum value is \077, or \x3f, so u8 is sufficient here
if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) {
- write!(suggest_1, "\\x{:02x}", n).unwrap();
+ write!(suggest_1, "\\x{n:02x}").unwrap();
}
// append the null byte as \x00 and the following digits literally
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 6217110a1..7722a476d 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
@@ -227,25 +227,25 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
// `skip_params` is either `0` or `1` to skip the `self` parameter in trait functions.
// It can't be renamed, and it can't be removed without removing it from multiple functions.
let (fn_id, fn_kind, skip_params) = match get_parent_node(cx.tcx, body.value.hir_id) {
- Some(Node::Item(i)) => (i.def_id.to_def_id(), FnKind::Fn, 0),
+ Some(Node::Item(i)) => (i.owner_id.to_def_id(), FnKind::Fn, 0),
Some(Node::TraitItem(&TraitItem {
kind: TraitItemKind::Fn(ref sig, _),
- def_id,
+ owner_id,
..
})) => (
- def_id.to_def_id(),
+ owner_id.to_def_id(),
FnKind::TraitFn,
usize::from(sig.decl.implicit_self.has_implicit_self()),
),
Some(Node::ImplItem(&ImplItem {
kind: ImplItemKind::Fn(ref sig, _),
- def_id,
+ owner_id,
..
})) => {
#[allow(trivial_casts)]
- if let Some(Node::Item(item)) = get_parent_node(cx.tcx, cx.tcx.hir().local_def_id_to_hir_id(def_id))
- && let Some(trait_ref) = cx.tcx.impl_trait_ref(item.def_id)
- && let Some(trait_item_id) = cx.tcx.associated_item(def_id).trait_item_def_id
+ 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)
+ && let Some(trait_item_id) = cx.tcx.associated_item(owner_id).trait_item_def_id
{
(
trait_item_id,
@@ -253,7 +253,7 @@ impl<'tcx> LateLintPass<'tcx> for OnlyUsedInRecursion {
usize::from(sig.decl.implicit_self.has_implicit_self()),
)
} else {
- (def_id.to_def_id(), FnKind::Fn, 0)
+ (owner_id.to_def_id(), FnKind::Fn, 0)
}
},
_ => return,
diff --git a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
index 1ec4240af..d29ca37ea 100644
--- a/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/absurd_extreme_comparisons.rs
@@ -34,13 +34,12 @@ pub(super) fn check<'tcx>(
};
let help = format!(
- "because `{}` is the {} value for this type, {}",
+ "because `{}` is the {} value for this type, {conclusion}",
snippet(cx, culprit.expr.span, "x"),
match culprit.which {
ExtremeType::Minimum => "minimum",
ExtremeType::Maximum => "maximum",
- },
- conclusion
+ }
);
span_lint_and_help(cx, ABSURD_EXTREME_COMPARISONS, expr.span, msg, None, &help);
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 83b69fbb3..8827daaa3 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,3 @@
-#![allow(
- // False positive
- clippy::match_same_arms
-)]
-
use super::ARITHMETIC_SIDE_EFFECTS;
use clippy_utils::{consts::constant_simple, diagnostics::span_lint};
use rustc_ast as ast;
@@ -14,11 +9,12 @@ use rustc_session::impl_lint_pass;
use rustc_span::source_map::{Span, Spanned};
const HARD_CODED_ALLOWED: &[&str] = &[
+ "&str",
"f32",
"f64",
"std::num::Saturating",
- "std::string::String",
"std::num::Wrapping",
+ "std::string::String",
];
#[derive(Debug)]
@@ -42,60 +38,62 @@ impl ArithmeticSideEffects {
}
}
- /// Checks assign operators (+=, -=, *=, /=) of integers in a non-constant environment that
- /// won't overflow.
- fn has_valid_assign_op(op: &Spanned<hir::BinOpKind>, rhs: &hir::Expr<'_>, rhs_refs: Ty<'_>) -> bool {
- if !Self::is_literal_integer(rhs, rhs_refs) {
- return false;
- }
- if let hir::BinOpKind::Div | hir::BinOpKind::Mul = op.node
- && let hir::ExprKind::Lit(ref lit) = rhs.kind
- && let ast::LitKind::Int(1, _) = lit.node
+ /// Assuming that `expr` is a literal integer, checks operators (+=, -=, *, /) in a
+ /// non-constant environment that won't overflow.
+ fn has_valid_op(op: &Spanned<hir::BinOpKind>, expr: &hir::Expr<'_>) -> bool {
+ if let hir::ExprKind::Lit(ref lit) = expr.kind &&
+ let ast::LitKind::Int(value, _) = lit.node
{
- return true;
+ match (&op.node, value) {
+ (hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
+ (hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
+ | (hir::BinOpKind::Div | hir::BinOpKind::Rem, _)
+ | (hir::BinOpKind::Mul, 0 | 1) => true,
+ _ => false,
+ }
+ } else {
+ false
}
- false
- }
-
- /// Checks "raw" binary operators (+, -, *, /) of integers in a non-constant environment
- /// already handled by the CTFE.
- fn has_valid_bin_op(lhs: &hir::Expr<'_>, lhs_refs: Ty<'_>, rhs: &hir::Expr<'_>, rhs_refs: Ty<'_>) -> bool {
- Self::is_literal_integer(lhs, lhs_refs) && Self::is_literal_integer(rhs, rhs_refs)
}
/// Checks if the given `expr` has any of the inner `allowed` elements.
- fn is_allowed_ty(&self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
- self.allowed.contains(
- cx.typeck_results()
- .expr_ty(expr)
- .to_string()
- .split('<')
- .next()
- .unwrap_or_default(),
- )
+ fn is_allowed_ty(&self, ty: Ty<'_>) -> bool {
+ self.allowed
+ .contains(ty.to_string().split('<').next().unwrap_or_default())
}
- /// Explicit integers like `1` or `i32::MAX`. Does not take into consideration references.
- fn is_literal_integer(expr: &hir::Expr<'_>, expr_refs: Ty<'_>) -> bool {
- let is_integral = expr_refs.is_integral();
- let is_literal = matches!(expr.kind, hir::ExprKind::Lit(_));
- is_integral && is_literal
+ // For example, 8i32 or &i64::MAX.
+ fn is_integral(ty: Ty<'_>) -> bool {
+ ty.peel_refs().is_integral()
}
+ // Common entry-point to avoid code duplication.
fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
- span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, "arithmetic detected");
+ let msg = "arithmetic operation that can potentially result in unexpected side-effects";
+ span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
self.expr_span = Some(expr.span);
}
+ /// If `expr` does not match any variant of `LiteralIntegerTy`, returns `None`.
+ fn literal_integer<'expr, 'tcx>(expr: &'expr hir::Expr<'tcx>) -> Option<LiteralIntegerTy<'expr, 'tcx>> {
+ if matches!(expr.kind, hir::ExprKind::Lit(_)) {
+ return Some(LiteralIntegerTy::Value(expr));
+ }
+ if let hir::ExprKind::AddrOf(.., inn) = expr.kind && let hir::ExprKind::Lit(_) = inn.kind {
+ return Some(LiteralIntegerTy::Ref(inn));
+ }
+ None
+ }
+
/// Manages when the lint should be triggered. Operations in constant environments, hard coded
/// types, custom allowed types and non-constant operations that won't overflow are ignored.
- fn manage_bin_ops(
+ fn manage_bin_ops<'tcx>(
&mut self,
- cx: &LateContext<'_>,
- expr: &hir::Expr<'_>,
+ cx: &LateContext<'tcx>,
+ expr: &hir::Expr<'tcx>,
op: &Spanned<hir::BinOpKind>,
- lhs: &hir::Expr<'_>,
- rhs: &hir::Expr<'_>,
+ lhs: &hir::Expr<'tcx>,
+ rhs: &hir::Expr<'tcx>,
) {
if constant_simple(cx, cx.typeck_results(), expr).is_some() {
return;
@@ -112,21 +110,29 @@ impl ArithmeticSideEffects {
) {
return;
};
- if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
+ let lhs_ty = cx.typeck_results().expr_ty(lhs);
+ let rhs_ty = cx.typeck_results().expr_ty(rhs);
+ let lhs_and_rhs_have_the_same_ty = lhs_ty == rhs_ty;
+ if lhs_and_rhs_have_the_same_ty && self.is_allowed_ty(lhs_ty) && self.is_allowed_ty(rhs_ty) {
return;
}
- let lhs_refs = cx.typeck_results().expr_ty(lhs).peel_refs();
- let rhs_refs = cx.typeck_results().expr_ty(rhs).peel_refs();
- let has_valid_assign_op = Self::has_valid_assign_op(op, rhs, rhs_refs);
- if has_valid_assign_op || Self::has_valid_bin_op(lhs, lhs_refs, rhs, rhs_refs) {
- return;
+ let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
+ match (Self::literal_integer(lhs), Self::literal_integer(rhs)) {
+ (None, Some(lit_int_ty)) | (Some(lit_int_ty), None) => Self::has_valid_op(op, lit_int_ty.into()),
+ (Some(LiteralIntegerTy::Value(_)), Some(LiteralIntegerTy::Value(_))) => true,
+ (None, None) | (Some(_), Some(_)) => false,
+ }
+ } else {
+ false
+ };
+ if !has_valid_op {
+ self.issue_lint(cx, expr);
}
- self.issue_lint(cx, expr);
}
}
impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
if self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) {
return;
}
@@ -171,3 +177,22 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
}
}
}
+
+/// Tells if an expression is a integer declared by value or by reference.
+///
+/// If `LiteralIntegerTy::Ref`, then the contained value will be `hir::ExprKind::Lit` rather
+/// than `hirExprKind::Addr`.
+enum LiteralIntegerTy<'expr, 'tcx> {
+ /// For example, `&199`
+ Ref(&'expr hir::Expr<'tcx>),
+ /// For example, `1` or `i32::MAX`
+ Value(&'expr hir::Expr<'tcx>),
+}
+
+impl<'expr, 'tcx> From<LiteralIntegerTy<'expr, 'tcx>> for &'expr hir::Expr<'tcx> {
+ fn from(from: LiteralIntegerTy<'expr, 'tcx>) -> Self {
+ match from {
+ LiteralIntegerTy::Ref(elem) | LiteralIntegerTy::Value(elem) => elem,
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index 945a09a64..ee9fd9406 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -2,16 +2,17 @@ use clippy_utils::binop_traits;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::implements_trait;
+use clippy_utils::visitors::for_each_expr;
use clippy_utils::{eq_expr_value, trait_ref_of_method};
+use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_lint::LateContext;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty::BorrowKind;
use rustc_trait_selection::infer::TyCtxtInferExt;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use super::ASSIGN_OP_PATTERN;
@@ -28,7 +29,7 @@ pub(super) fn check<'tcx>(
if_chain! {
if let Some((_, lang_item)) = binop_traits(op.node);
if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
- let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id);
+ let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
if trait_ref_of_method(cx, parent_fn)
.map_or(true, |t| t.path.res.def_id() != trait_id);
if implements_trait(cx, ty, trait_id, &[rty.into()]);
@@ -55,7 +56,7 @@ pub(super) fn check<'tcx>(
diag.span_suggestion(
expr.span,
"replace it with",
- format!("{} {}= {}", snip_a, op.node.as_str(), snip_r),
+ format!("{snip_a} {}= {snip_r}", op.node.as_str()),
Applicability::MachineApplicable,
);
}
@@ -65,15 +66,19 @@ pub(super) fn check<'tcx>(
}
};
- let mut visitor = ExprVisitor {
- assignee,
- counter: 0,
- cx,
- };
-
- walk_expr(&mut visitor, e);
+ let mut found = false;
+ let found_multiple = for_each_expr(e, |e| {
+ if eq_expr_value(cx, assignee, e) {
+ if found {
+ return ControlFlow::Break(());
+ }
+ found = true;
+ }
+ ControlFlow::Continue(())
+ })
+ .is_some();
- if visitor.counter == 1 {
+ if found && !found_multiple {
// a = a op b
if eq_expr_value(cx, assignee, l) {
lint(assignee, r);
@@ -98,22 +103,6 @@ pub(super) fn check<'tcx>(
}
}
-struct ExprVisitor<'a, 'tcx> {
- assignee: &'a hir::Expr<'a>,
- counter: u8,
- cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for ExprVisitor<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
- if eq_expr_value(self.cx, self.assignee, expr) {
- self.counter += 1;
- }
-
- walk_expr(self, expr);
- }
-}
-
fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet {
struct S(hir::HirIdSet);
impl Delegate<'_> for S {
@@ -134,16 +123,15 @@ fn imm_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
}
let mut s = S(hir::HirIdSet::default());
- cx.tcx.infer_ctxt().enter(|infcx| {
- let mut v = ExprUseVisitor::new(
- &mut s,
- &infcx,
- cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
- cx.param_env,
- cx.typeck_results(),
- );
- v.consume_expr(e);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ let mut v = ExprUseVisitor::new(
+ &mut s,
+ &infcx,
+ cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+ cx.param_env,
+ cx.typeck_results(),
+ );
+ v.consume_expr(e);
s.0
}
@@ -167,15 +155,14 @@ fn mut_borrows_in_expr(cx: &LateContext<'_>, e: &hir::Expr<'_>) -> hir::HirIdSet
}
let mut s = S(hir::HirIdSet::default());
- cx.tcx.infer_ctxt().enter(|infcx| {
- let mut v = ExprUseVisitor::new(
- &mut s,
- &infcx,
- cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
- cx.param_env,
- cx.typeck_results(),
- );
- v.consume_expr(e);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ let mut v = ExprUseVisitor::new(
+ &mut s,
+ &infcx,
+ cx.tcx.hir().body_owner_def_id(cx.enclosing_body.unwrap()),
+ cx.param_env,
+ cx.typeck_results(),
+ );
+ v.consume_expr(e);
s.0
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
index 74387fbc8..1369b3e74 100644
--- a/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/bit_mask.rs
@@ -64,10 +64,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ & {}` can never be equal to `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ & {mask_value}` can never be equal to `{cmp_value}`"),
);
}
} else if mask_value == 0 {
@@ -80,10 +77,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ | {}` can never be equal to `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ | {mask_value}` can never be equal to `{cmp_value}`"),
);
}
},
@@ -96,10 +90,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ & {}` will always be lower than `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ & {mask_value}` will always be lower than `{cmp_value}`"),
);
} else if mask_value == 0 {
span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -111,10 +102,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ | {}` will never be lower than `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ | {mask_value}` will never be lower than `{cmp_value}`"),
);
} else {
check_ineffective_lt(cx, span, mask_value, cmp_value, "|");
@@ -130,10 +118,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ & {}` will never be higher than `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ & {mask_value}` will never be higher than `{cmp_value}`"),
);
} else if mask_value == 0 {
span_lint(cx, BAD_BIT_MASK, span, "&-masking with zero");
@@ -145,10 +130,7 @@ fn check_bit_mask(
cx,
BAD_BIT_MASK,
span,
- &format!(
- "incompatible bit mask: `_ | {}` will always be higher than `{}`",
- mask_value, cmp_value
- ),
+ &format!("incompatible bit mask: `_ | {mask_value}` will always be higher than `{cmp_value}`"),
);
} else {
check_ineffective_gt(cx, span, mask_value, cmp_value, "|");
@@ -167,10 +149,7 @@ fn check_ineffective_lt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
cx,
INEFFECTIVE_BIT_MASK,
span,
- &format!(
- "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
- op, m, c
- ),
+ &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
);
}
}
@@ -181,10 +160,7 @@ fn check_ineffective_gt(cx: &LateContext<'_>, span: Span, m: u128, c: u128, op:
cx,
INEFFECTIVE_BIT_MASK,
span,
- &format!(
- "ineffective bit mask: `x {} {}` compared to `{}`, is the same as x compared directly",
- op, m, c
- ),
+ &format!("ineffective bit mask: `x {op} {m}` compared to `{c}`, is the same as x compared directly"),
);
}
}
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 638a514ff..24aeb82a3 100644
--- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
use clippy_utils::ty::{implements_trait, is_copy};
-use clippy_utils::{match_any_def_paths, path_def_id, paths};
+use clippy_utils::{match_def_path, path_def_id, paths};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_lint::LateContext;
@@ -49,13 +49,15 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
(arg, arg.span)
},
ExprKind::Call(path, [arg])
- if path_def_id(cx, path)
- .and_then(|id| match_any_def_paths(cx, id, &[&paths::FROM_STR_METHOD, &paths::FROM_FROM]))
- .map_or(false, |idx| match idx {
- 0 => true,
- 1 => !is_copy(cx, typeck.expr_ty(expr)),
- _ => false,
- }) =>
+ if path_def_id(cx, path).map_or(false, |id| {
+ if match_def_path(cx, id, &paths::FROM_STR_METHOD) {
+ true
+ } else if cx.tcx.lang_items().from_fn() == Some(id) {
+ !is_copy(cx, typeck.expr_ty(expr))
+ } else {
+ false
+ }
+ }) =>
{
(arg, arg.span)
},
@@ -99,7 +101,7 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
let expr_snip;
let eq_impl;
if with_deref.is_implemented() {
- expr_snip = format!("*{}", arg_snip);
+ expr_snip = format!("*{arg_snip}");
eq_impl = with_deref;
} else {
expr_snip = arg_snip.to_string();
@@ -121,17 +123,15 @@ fn check_op(cx: &LateContext<'_>, expr: &Expr<'_>, other: &Expr<'_>, left: bool)
};
if eq_impl.ty_eq_other {
hint = format!(
- "{}{}{}",
- expr_snip,
+ "{expr_snip}{}{}",
snippet(cx, cmp_span, ".."),
snippet(cx, other.span, "..")
);
} else {
hint = format!(
- "{}{}{}",
+ "{}{}{expr_snip}",
snippet(cx, other.span, ".."),
- snippet(cx, cmp_span, ".."),
- expr_snip
+ snippet(cx, cmp_span, "..")
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
index 827a2b267..49e662cac 100644
--- a/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/duration_subsec.rs
@@ -31,12 +31,11 @@ pub(crate) fn check<'tcx>(
cx,
DURATION_SUBSEC,
expr.span,
- &format!("calling `{}()` is more concise than this calculation", suggested_fn),
+ &format!("calling `{suggested_fn}()` is more concise than this calculation"),
"try",
format!(
- "{}.{}()",
- snippet_with_applicability(cx, self_arg.span, "_", &mut applicability),
- suggested_fn
+ "{}.{suggested_fn}()",
+ snippet_with_applicability(cx, self_arg.span, "_", &mut applicability)
),
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
index 44cf0bb06..67913f739 100644
--- a/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/eq_op.rs
@@ -22,7 +22,7 @@ pub(crate) fn check_assert<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
cx,
EQ_OP,
lhs.span.to(rhs.span),
- &format!("identical args used in this `{}!` macro call", macro_name),
+ &format!("identical args used in this `{macro_name}!` macro call"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
index 0024384d9..ae805147f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/misrefactored_assign_op.rs
@@ -47,18 +47,14 @@ fn lint_misrefactored_assign_op(
if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs_other.span)) {
let a = &sugg::Sugg::hir(cx, assignee, "..");
let r = &sugg::Sugg::hir(cx, rhs, "..");
- let long = format!("{} = {}", snip_a, sugg::make_binop(op.into(), a, r));
+ let long = format!("{snip_a} = {}", sugg::make_binop(op.into(), a, r));
diag.span_suggestion(
expr.span,
&format!(
- "did you mean `{} = {} {} {}` or `{}`? Consider replacing it with",
- snip_a,
- snip_a,
- op.as_str(),
- snip_r,
- long
+ "did you mean `{snip_a} = {snip_a} {} {snip_r}` or `{long}`? Consider replacing it with",
+ op.as_str()
),
- format!("{} {}= {}", snip_a, op.as_str(), snip_r),
+ format!("{snip_a} {}= {snip_r}", op.as_str()),
Applicability::MaybeIncorrect,
);
diag.span_suggestion(
diff --git a/src/tools/clippy/clippy_lints/src/operators/mod.rs b/src/tools/clippy/clippy_lints/src/operators/mod.rs
index c32b4df4f..b8a20d5eb 100644
--- a/src/tools/clippy/clippy_lints/src/operators/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/mod.rs
@@ -67,7 +67,7 @@ declare_clippy_lint! {
/// Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
/// or can panic (`/`, `%`).
///
- /// Known safe built-in types like `Wrapping` or `Saturing`, floats, operations in constant
+ /// Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant
/// environments, allowed types and non-constant operations that won't overflow are ignored.
///
/// ### Why is this bad?
diff --git a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
index e902235a0..ab5fb1787 100644
--- a/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/needless_bitwise_bool.rs
@@ -27,7 +27,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &Expr<'_>, op: BinOpKind, lhs: &Exp
if let Some(lhs_snip) = snippet_opt(cx, lhs.span)
&& let Some(rhs_snip) = snippet_opt(cx, rhs.span)
{
- let sugg = format!("{} {} {}", lhs_snip, op_str, rhs_snip);
+ let sugg = format!("{lhs_snip} {op_str} {rhs_snip}");
diag.span_suggestion(e.span, "try", sugg, Applicability::MachineApplicable);
}
},
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 b6097710d..0830a106f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/numeric_arithmetic.rs
@@ -1,5 +1,6 @@
use clippy_utils::consts::constant_simple;
use clippy_utils::diagnostics::span_lint;
+use clippy_utils::is_integer_literal;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_span::source_map::Span;
@@ -50,11 +51,9 @@ impl Context {
hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
hir::ExprKind::Lit(_lit) => (),
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
- if let hir::ExprKind::Lit(lit) = &expr.kind {
- if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
- span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
- self.expr_id = Some(expr.hir_id);
- }
+ if is_integer_literal(expr, 1) {
+ span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
+ self.expr_id = Some(expr.hir_id);
}
},
_ => {
diff --git a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
index 1085e6089..71b31b5e4 100644
--- a/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/op_ref.rs
@@ -204,7 +204,7 @@ fn are_equal<'tcx>(cx: &LateContext<'tcx>, middle_ty: Ty<'_>, hir_ty: &rustc_hir
if let ty::Adt(adt_def, _) = middle_ty.kind();
if let Some(local_did) = adt_def.did().as_local();
let item = cx.tcx.hir().expect_item(local_did);
- let middle_ty_id = item.def_id.to_def_id();
+ let middle_ty_id = item.owner_id.to_def_id();
if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
if let Res::Def(_, hir_ty_id) = path.res;
diff --git a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
index 1aefc2741..1229c202f 100644
--- a/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/ptr_eq.rs
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
expr.span,
LINT_MSG,
"try",
- format!("std::ptr::eq({}, {})", left_snip, right_snip),
+ format!("std::ptr::eq({left_snip}, {right_snip})"),
Applicability::MachineApplicable,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
index 9d6bec05b..7c9d5320a 100644
--- a/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/self_assignment.rs
@@ -14,7 +14,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, lhs: &'tcx
cx,
SELF_ASSIGNMENT,
e.span,
- &format!("self-assignment of `{}` to `{}`", rhs, lhs),
+ &format!("self-assignment of `{rhs}` to `{lhs}`"),
);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
index ff85fd554..fbf65e92b 100644
--- a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs
@@ -35,7 +35,7 @@ pub(super) fn check<'tcx>(
diag.span_suggestion(
e.span,
"try",
- format!("{}.trailing_zeros() >= {}", sugg, n.count_ones()),
+ format!("{sugg}.trailing_zeros() >= {}", n.count_ones()),
Applicability::MaybeIncorrect,
);
},
diff --git a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
index 3f5286ba0..d9ee031c9 100644
--- a/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/option_env_unwrap.rs
@@ -37,9 +37,9 @@ declare_lint_pass!(OptionEnvUnwrap => [OPTION_ENV_UNWRAP]);
impl EarlyLintPass for OptionEnvUnwrap {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if_chain! {
- if let ExprKind::MethodCall(path_segment, args, _) = &expr.kind;
+ if let ExprKind::MethodCall(path_segment, receiver, _, _) = &expr.kind;
if matches!(path_segment.ident.name, sym::expect | sym::unwrap);
- if let ExprKind::Call(caller, _) = &args[0].kind;
+ if let ExprKind::Call(caller, _) = &receiver.kind;
if is_direct_expn_of(caller.span, "option_env").is_some();
then {
span_lint_and_help(
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 0315678bf..4eb42da1f 100644
--- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
+++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::{
- can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_lang_ctor, peel_blocks,
+ can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_res_lang_ctor, peel_blocks,
peel_hir_expr_while, CaptureKind,
};
use if_chain::if_chain;
@@ -88,7 +88,7 @@ declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);
/// None/_ => {..}
/// }
/// ```
-struct OptionOccurence {
+struct OptionOccurrence {
option: String,
method_sugg: String,
some_expr: String,
@@ -109,13 +109,13 @@ fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: boo
)
}
-fn try_get_option_occurence<'tcx>(
+fn try_get_option_occurrence<'tcx>(
cx: &LateContext<'tcx>,
pat: &Pat<'tcx>,
expr: &Expr<'_>,
if_then: &'tcx Expr<'_>,
if_else: &'tcx Expr<'_>,
-) -> Option<OptionOccurence> {
+) -> Option<OptionOccurrence> {
let cond_expr = match expr.kind {
ExprKind::Unary(UnOp::Deref, inner_expr) | ExprKind::AddrOf(_, _, inner_expr) => inner_expr,
_ => expr,
@@ -160,10 +160,10 @@ fn try_get_option_occurence<'tcx>(
}
}
- return Some(OptionOccurence {
+ return Some(OptionOccurrence {
option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
method_sugg: method_sugg.to_string(),
- some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir_with_macro_callsite(cx, some_body, "..")),
+ some_expr: format!("|{capture_mut}{capture_name}| {}", Sugg::hir_with_macro_callsite(cx, some_body, "..")),
none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir_with_macro_callsite(cx, none_body, "..")),
});
}
@@ -174,7 +174,8 @@ fn try_get_option_occurence<'tcx>(
fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
- if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk) {
+ let res = cx.qpath_res(qpath, pat.hir_id);
+ if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
return Some(inner_pat);
}
}
@@ -182,9 +183,9 @@ fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'
}
/// If this expression is the option if let/else construct we're detecting, then
-/// this function returns an `OptionOccurence` struct with details if
+/// this function returns an `OptionOccurrence` struct with details if
/// this construct is found, or None if this construct is not found.
-fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurence> {
+fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurrence> {
if let Some(higher::IfLet {
let_pat,
let_expr,
@@ -193,16 +194,16 @@ fn detect_option_if_let_else<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) ->
}) = higher::IfLet::hir(cx, expr)
{
if !is_else_clause(cx.tcx, expr) {
- return try_get_option_occurence(cx, let_pat, let_expr, if_then, if_else);
+ return try_get_option_occurrence(cx, let_pat, let_expr, if_then, if_else);
}
}
None
}
-fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurence> {
+fn detect_option_match<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Option<OptionOccurrence> {
if let ExprKind::Match(ex, arms, MatchSource::Normal) = expr.kind {
if let Some((let_pat, if_then, if_else)) = try_convert_match(cx, arms) {
- return try_get_option_occurence(cx, let_pat, ex, if_then, if_else);
+ return try_get_option_occurrence(cx, let_pat, ex, if_then, if_else);
}
}
None
@@ -226,9 +227,10 @@ fn try_convert_match<'tcx>(
fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
match arm.pat.kind {
- PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
+ PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [first_pat], _) => {
- is_lang_ctor(cx, qpath, ResultErr) && matches!(first_pat.kind, PatKind::Wild)
+ is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
+ && matches!(first_pat.kind, PatKind::Wild)
},
PatKind::Wild => true,
_ => false,
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 4aa0d9227..efec12489 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
@@ -2,9 +2,10 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::root_macro_call_first_node;
use clippy_utils::return_ty;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::visitors::expr_visitor_no_bodies;
+use clippy_utils::visitors::{for_each_expr, Descend};
+use core::ops::ControlFlow;
use rustc_hir as hir;
-use rustc_hir::intravisit::{FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
@@ -58,18 +59,20 @@ impl<'tcx> LateLintPass<'tcx> for PanicInResultFn {
fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, body: &'tcx hir::Body<'tcx>) {
let mut panics = Vec::new();
- expr_visitor_no_bodies(|expr| {
- let Some(macro_call) = root_macro_call_first_node(cx, expr) else { return true };
+ let _: Option<!> = for_each_expr(body.value, |e| {
+ let Some(macro_call) = root_macro_call_first_node(cx, e) else {
+ return ControlFlow::Continue(Descend::Yes);
+ };
if matches!(
cx.tcx.item_name(macro_call.def_id).as_str(),
"unimplemented" | "unreachable" | "panic" | "todo" | "assert" | "assert_eq" | "assert_ne"
) {
panics.push(macro_call.span);
- return false;
+ ControlFlow::Continue(Descend::No)
+ } else {
+ ControlFlow::Continue(Descend::Yes)
}
- true
- })
- .visit_expr(body.value);
+ });
if !panics.is_empty() {
span_lint_and_then(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
new file mode 100644
index 000000000..f60d9d65b
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/partial_pub_fields.rs
@@ -0,0 +1,81 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_ast::ast::{Item, ItemKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks whether partial fields of a struct are public.
+ ///
+ /// Either make all fields of a type public, or make none of them public
+ ///
+ /// ### Why is this bad?
+ /// Most types should either be:
+ /// * Abstract data types: complex objects with opaque implementation which guard
+ /// interior invariants and expose intentionally limited API to the outside world.
+ /// * Data: relatively simple objects which group a bunch of related attributes together.
+ ///
+ /// ### Example
+ /// ```rust
+ /// pub struct Color {
+ /// pub r: u8,
+ /// pub g: u8,
+ /// b: u8,
+ /// }
+ /// ```
+ /// Use instead:
+ /// ```rust
+ /// pub struct Color {
+ /// pub r: u8,
+ /// pub g: u8,
+ /// pub b: u8,
+ /// }
+ /// ```
+ #[clippy::version = "1.66.0"]
+ pub PARTIAL_PUB_FIELDS,
+ restriction,
+ "partial fields of a struct are public"
+}
+declare_lint_pass!(PartialPubFields => [PARTIAL_PUB_FIELDS]);
+
+impl EarlyLintPass for PartialPubFields {
+ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+ let ItemKind::Struct(ref st, _) = item.kind else {
+ return;
+ };
+
+ let mut fields = st.fields().iter();
+ let Some(first_field) = fields.next() else {
+ // Empty struct.
+ return;
+ };
+ let all_pub = first_field.vis.kind.is_pub();
+ let all_priv = !all_pub;
+
+ let msg = "mixed usage of pub and non-pub fields";
+
+ for field in fields {
+ if all_priv && field.vis.kind.is_pub() {
+ span_lint_and_help(
+ cx,
+ PARTIAL_PUB_FIELDS,
+ field.vis.span,
+ msg,
+ None,
+ "consider using private field here",
+ );
+ return;
+ } else if all_pub && !field.vis.kind.is_pub() {
+ span_lint_and_help(
+ cx,
+ PARTIAL_PUB_FIELDS,
+ field.vis.span,
+ msg,
+ None,
+ "consider using public field here",
+ );
+ return;
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
index 09ac514d0..5aa3c6f2f 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_ne_impl.rs
@@ -36,7 +36,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialEqNeImpl {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if_chain! {
if let ItemKind::Impl(Impl { of_trait: Some(ref trait_ref), items: impl_items, .. }) = item.kind;
- if !cx.tcx.has_attr(item.def_id.to_def_id(), sym::automatically_derived);
+ if !cx.tcx.has_attr(item.owner_id.to_def_id(), sym::automatically_derived);
if let Some(eq_trait) = cx.tcx.lang_items().eq_trait();
if trait_ref.path.res.def_id() == eq_trait;
then {
diff --git a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
index 000b0ba7a..6810a2431 100644
--- a/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
+++ b/src/tools/clippy/clippy_lints/src/partialeq_to_none.rs
@@ -1,5 +1,5 @@
use clippy_utils::{
- diagnostics::span_lint_and_sugg, is_lang_ctor, peel_hir_expr_refs, peel_ref_operators, sugg,
+ diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_operators, sugg,
ty::is_type_diagnostic_item,
};
use rustc_errors::Applicability;
@@ -54,8 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialeqToNone {
// If the expression is a literal `Option::None`
let is_none_ctor = |expr: &Expr<'_>| {
!expr.span.from_expansion()
- && matches!(&peel_hir_expr_refs(expr).0.kind,
- ExprKind::Path(p) if is_lang_ctor(cx, p, LangItem::OptionNone))
+ && is_res_lang_ctor(cx, path_res(cx, peel_hir_expr_refs(expr).0), LangItem::OptionNone)
};
let mut applicability = Applicability::MachineApplicable;
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 0960b050c..f9fd36456 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
@@ -139,7 +139,7 @@ impl<'tcx> PassByRefOrValue {
}
fn check_poly_fn(&mut self, cx: &LateContext<'tcx>, def_id: LocalDefId, decl: &FnDecl<'_>, span: Option<Span>) {
- if self.avoid_breaking_exported_api && cx.access_levels.is_exported(def_id) {
+ if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
@@ -209,7 +209,7 @@ impl<'tcx> PassByRefOrValue {
cx,
TRIVIALLY_COPY_PASS_BY_REF,
input.span,
- &format!("this argument ({} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", size, self.ref_min_size),
+ &format!("this argument ({size} byte) is passed by reference, but would be more efficient if passed by value (limit: {} byte)", self.ref_min_size),
"consider passing by value instead",
value_type,
Applicability::Unspecified,
@@ -237,7 +237,7 @@ impl<'tcx> PassByRefOrValue {
cx,
LARGE_TYPES_PASSED_BY_VALUE,
input.span,
- &format!("this argument ({} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", size, self.value_max_size),
+ &format!("this argument ({size} byte) is passed by value, but might be more efficient if passed by reference (limit: {} byte)", self.value_max_size),
"consider passing by reference instead",
format!("&{}", snippet(cx, input.span, "_")),
Applicability::MaybeIncorrect,
@@ -261,7 +261,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue {
}
if let hir::TraitItemKind::Fn(method_sig, _) = &item.kind {
- self.check_poly_fn(cx, item.def_id, method_sig.decl, None);
+ self.check_poly_fn(cx, item.owner_id.def_id, method_sig.decl, None);
}
}
diff --git a/src/tools/clippy/clippy_lints/src/precedence.rs b/src/tools/clippy/clippy_lints/src/precedence.rs
index cc0533c9f..e6e3ad05a 100644
--- a/src/tools/clippy/clippy_lints/src/precedence.rs
+++ b/src/tools/clippy/clippy_lints/src/precedence.rs
@@ -109,12 +109,12 @@ impl EarlyLintPass for Precedence {
let mut arg = operand;
let mut all_odd = true;
- while let ExprKind::MethodCall(path_segment, args, _) = &arg.kind {
+ while let ExprKind::MethodCall(path_segment, receiver, _, _) = &arg.kind {
let path_segment_str = path_segment.ident.name.as_str();
all_odd &= ALLOWED_ODD_FUNCTIONS
.iter()
.any(|odd_function| **odd_function == *path_segment_str);
- arg = args.first().expect("A method always has a receiver.");
+ arg = receiver;
}
if_chain! {
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 41d1baba6..0d74c90a8 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -15,13 +15,17 @@ use rustc_hir::{
ImplItemKind, ItemKind, Lifetime, LifetimeName, Mutability, Node, Param, ParamName, PatKind, QPath, TraitFn,
TraitItem, TraitItemKind, TyKind, Unsafety,
};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, Binder, ExistentialPredicate, List, PredicateKind, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::sym;
use rustc_span::symbol::Symbol;
+use rustc_trait_selection::infer::InferCtxtExt as _;
+use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use std::fmt;
use std::iter;
@@ -160,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.def_id).skip_binder().inputs(),
+ cx.tcx.fn_sig(item.owner_id).skip_binder().inputs(),
sig.decl.inputs,
&[],
)
@@ -184,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
let (item_id, sig, is_trait_item) = match parents.next() {
Some((_, Node::Item(i))) => {
if let ItemKind::Fn(sig, ..) = &i.kind {
- (i.def_id, sig, false)
+ (i.owner_id, sig, false)
} else {
return;
}
@@ -196,14 +200,14 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
return;
}
if let ImplItemKind::Fn(sig, _) = &i.kind {
- (i.def_id, sig, false)
+ (i.owner_id, sig, false)
} else {
return;
}
},
Some((_, Node::TraitItem(i))) => {
if let TraitItemKind::Fn(sig, _) = &i.kind {
- (i.def_id, sig, true)
+ (i.owner_id, sig, true)
} else {
return;
}
@@ -384,6 +388,17 @@ enum DerefTy<'tcx> {
Slice(Option<Span>, Ty<'tcx>),
}
impl<'tcx> DerefTy<'tcx> {
+ fn ty(&self, cx: &LateContext<'tcx>) -> Ty<'tcx> {
+ match *self {
+ Self::Str => cx.tcx.types.str_,
+ Self::Path => cx.tcx.mk_adt(
+ cx.tcx.adt_def(cx.tcx.get_diagnostic_item(sym::Path).unwrap()),
+ List::empty(),
+ ),
+ Self::Slice(_, ty) => cx.tcx.mk_slice(ty),
+ }
+ }
+
fn argless_str(&self) -> &'static str {
match *self {
Self::Str => "str",
@@ -463,7 +478,7 @@ fn check_fn_args<'cx, 'tcx: 'cx>(
diag.span_suggestion(
hir_ty.span,
"change this to",
- format!("&{}{}", mutability.prefix_str(), ty_name),
+ format!("&{}{ty_name}", mutability.prefix_str()),
Applicability::Unspecified,
);
}
@@ -552,9 +567,8 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
}
// Check if this is local we care about
- let args_idx = match path_to_local(e).and_then(|id| self.bindings.get(&id)) {
- Some(&i) => i,
- None => return walk_expr(self, e),
+ let Some(&args_idx) = path_to_local(e).and_then(|id| self.bindings.get(&id)) else {
+ return walk_expr(self, e);
};
let args = &self.args[args_idx];
let result = &mut self.results[args_idx];
@@ -582,6 +596,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
let i = expr_args.iter().position(|arg| arg.hir_id == child_id).unwrap_or(0);
if expr_sig(self.cx, f).and_then(|sig| sig.input(i)).map_or(true, |ty| {
match *ty.skip_binder().peel_refs().kind() {
+ ty::Dynamic(preds, _, _) => !matches_preds(self.cx, args.deref_ty.ty(self.cx), preds),
ty::Param(_) => true,
ty::Adt(def, _) => def.did() == args.ty_did,
_ => false,
@@ -609,14 +624,15 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
}
}
- let id = if let Some(x) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) {
- x
- } else {
+ let Some(id) = self.cx.typeck_results().type_dependent_def_id(e.hir_id) else {
set_skip_flag();
return;
};
match *self.cx.tcx.fn_sig(id).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();
+ },
ty::Param(_) => {
set_skip_flag();
},
@@ -668,8 +684,32 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
v.results
}
+fn matches_preds<'tcx>(
+ cx: &LateContext<'tcx>,
+ ty: Ty<'tcx>,
+ preds: &'tcx [Binder<'tcx, ExistentialPredicate<'tcx>>],
+) -> bool {
+ let infcx = cx.tcx.infer_ctxt().build();
+ preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) {
+ ExistentialPredicate::Trait(p) => infcx
+ .type_implements_trait(p.def_id, ty, p.substs, cx.param_env)
+ .must_apply_modulo_regions(),
+ ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new(
+ ObligationCause::dummy(),
+ cx.param_env,
+ cx.tcx.mk_predicate(Binder::bind_with_vars(
+ PredicateKind::Projection(p.with_self_ty(cx.tcx, ty)),
+ List::empty(),
+ )),
+ )),
+ ExistentialPredicate::AutoTrait(p) => infcx
+ .type_implements_trait(p, ty, List::empty(), cx.param_env)
+ .must_apply_modulo_regions(),
+ })
+}
+
fn get_rptr_lm<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability, Span)> {
- if let TyKind::Rptr(ref lt, ref m) = ty.kind {
+ if let TyKind::Rptr(lt, ref m) = ty.kind {
Some((lt, m.mutbl, ty.span))
} else {
None
diff --git a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
index 4dc65da3e..72dda67c7 100644
--- a/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr_offset_with_cast.rs
@@ -49,18 +49,16 @@ declare_lint_pass!(PtrOffsetWithCast => [PTR_OFFSET_WITH_CAST]);
impl<'tcx> LateLintPass<'tcx> for PtrOffsetWithCast {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
// Check if the expressions is a ptr.offset or ptr.wrapping_offset method call
- let (receiver_expr, arg_expr, method) = match expr_as_ptr_offset_call(cx, expr) {
- Some(call_arg) => call_arg,
- None => return,
+ let Some((receiver_expr, arg_expr, method)) = expr_as_ptr_offset_call(cx, expr) else {
+ return
};
// Check if the argument to the method call is a cast from usize
- let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) {
- Some(cast_lhs_expr) => cast_lhs_expr,
- None => return,
+ let Some(cast_lhs_expr) = expr_as_cast_from_usize(cx, arg_expr) else {
+ return
};
- let msg = format!("use of `{}` with a `usize` casted to an `isize`", method);
+ let msg = format!("use of `{method}` with a `usize` casted to an `isize`");
if let Some(sugg) = build_suggestion(cx, method, receiver_expr, cast_lhs_expr) {
span_lint_and_sugg(
cx,
@@ -124,7 +122,7 @@ fn build_suggestion<'tcx>(
) -> Option<String> {
let receiver = snippet_opt(cx, receiver_expr.span)?;
let cast_lhs = snippet_opt(cx, cast_lhs_expr.span)?;
- Some(format!("{}.{}({})", receiver, method.suggestion(), cast_lhs))
+ Some(format!("{receiver}.{}({cast_lhs})", method.suggestion()))
}
#[derive(Copy, Clone)]
diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs
index 569870ab2..bb86fb3b7 100644
--- a/src/tools/clippy/clippy_lints/src/question_mark.rs
+++ b/src/tools/clippy/clippy_lints/src/question_mark.rs
@@ -3,11 +3,12 @@ use clippy_utils::higher;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{
- eq_expr_value, get_parent_node, is_else_clause, is_lang_ctor, path_to_local, path_to_local_id, peel_blocks,
- peel_blocks_with_stmt,
+ eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id,
+ peel_blocks, peel_blocks_with_stmt,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
+use rustc_hir::def::Res;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
use rustc_lint::{LateContext, LateLintPass};
@@ -58,7 +59,7 @@ enum IfBlockType<'hir> {
/// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
/// if_else (d)
IfLet(
- &'hir QPath<'hir>,
+ Res,
Ty<'hir>,
Symbol,
&'hir Expr<'hir>,
@@ -93,16 +94,16 @@ fn check_is_none_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr: &Ex
then {
let mut applicability = Applicability::MachineApplicable;
let receiver_str = snippet_with_applicability(cx, caller.span, "..", &mut applicability);
- let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx.at(caller.span), cx.param_env) &&
+ let by_ref = !caller_ty.is_copy_modulo_regions(cx.tcx, cx.param_env) &&
!matches!(caller.kind, ExprKind::Call(..) | ExprKind::MethodCall(..));
let sugg = if let Some(else_inner) = r#else {
if eq_expr_value(cx, caller, peel_blocks(else_inner)) {
- format!("Some({}?)", receiver_str)
+ format!("Some({receiver_str}?)")
} else {
return;
}
} else {
- format!("{}{}?;", receiver_str, if by_ref { ".as_ref()" } else { "" })
+ format!("{receiver_str}{}?;", if by_ref { ".as_ref()" } else { "" })
};
span_lint_and_sugg(
@@ -126,7 +127,14 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
if ddpos.as_opt_usize().is_none();
if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
let caller_ty = cx.typeck_results().expr_ty(let_expr);
- let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
+ let if_block = IfBlockType::IfLet(
+ cx.qpath_res(path1, let_pat.hir_id),
+ caller_ty,
+ ident.name,
+ let_expr,
+ if_then,
+ if_else
+ );
if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|| is_early_return(sym::Result, cx, &if_block);
if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
@@ -135,8 +143,7 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
let receiver_str = snippet_with_applicability(cx, let_expr.span, "..", &mut applicability);
let requires_semi = matches!(get_parent_node(cx.tcx, expr.hir_id), Some(Node::Stmt(_)));
let sugg = format!(
- "{}{}?{}",
- receiver_str,
+ "{receiver_str}{}?{}",
if by_ref == ByRef::Yes { ".as_ref()" } else { "" },
if requires_semi { ";" } else { "" }
);
@@ -166,21 +173,21 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_
_ => false,
}
},
- IfBlockType::IfLet(qpath, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
+ IfBlockType::IfLet(res, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
is_type_diagnostic_item(cx, let_expr_ty, smbl)
&& match smbl {
sym::Option => {
// We only need to check `if let Some(x) = option` not `if let None = option`,
// because the later one will be suggested as `if option.is_none()` thus causing conflict.
- is_lang_ctor(cx, qpath, OptionSome)
+ is_res_lang_ctor(cx, res, OptionSome)
&& if_else.is_some()
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, None)
},
sym::Result => {
- (is_lang_ctor(cx, qpath, ResultOk)
+ (is_res_lang_ctor(cx, res, ResultOk)
&& if_else.is_some()
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
- || is_lang_ctor(cx, qpath, ResultErr)
+ || is_res_lang_ctor(cx, res, ResultErr)
&& expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
},
_ => false,
@@ -199,7 +206,7 @@ fn expr_return_none_or_err(
match peel_blocks_with_stmt(expr).kind {
ExprKind::Ret(Some(ret_expr)) => expr_return_none_or_err(smbl, cx, ret_expr, cond_expr, err_sym),
ExprKind::Path(ref qpath) => match smbl {
- sym::Option => is_lang_ctor(cx, qpath, OptionNone),
+ sym::Option => is_res_lang_ctor(cx, cx.qpath_res(qpath, expr.hir_id), OptionNone),
sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
_ => false,
},
@@ -224,7 +231,9 @@ fn expr_return_none_or_err(
impl<'tcx> LateLintPass<'tcx> for QuestionMark {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- check_is_none_or_err_and_early_return(cx, expr);
- check_if_let_some_or_err_and_early_return(cx, expr);
+ if !in_constant(cx, expr.hir_id) {
+ check_is_none_or_err_and_early_return(cx, expr);
+ check_if_let_some_or_err_and_early_return(cx, expr);
+ }
}
}
diff --git a/src/tools/clippy/clippy_lints/src/ranges.rs b/src/tools/clippy/clippy_lints/src/ranges.rs
index 918d624ee..c6fbb5e80 100644
--- a/src/tools/clippy/clippy_lints/src/ranges.rs
+++ b/src/tools/clippy/clippy_lints/src/ranges.rs
@@ -243,9 +243,9 @@ fn check_possible_range_contains(
cx,
MANUAL_RANGE_CONTAINS,
span,
- &format!("manual `{}::contains` implementation", range_type),
+ &format!("manual `{range_type}::contains` implementation"),
"use",
- format!("({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
+ format!("({lo}{space}{range_op}{hi}).contains(&{name})"),
applicability,
);
} else if !combine_and && ord == Some(l.ord) {
@@ -273,9 +273,9 @@ fn check_possible_range_contains(
cx,
MANUAL_RANGE_CONTAINS,
span,
- &format!("manual `!{}::contains` implementation", range_type),
+ &format!("manual `!{range_type}::contains` implementation"),
"use",
- format!("!({}{}{}{}).contains(&{})", lo, space, range_op, hi, name),
+ format!("!({lo}{space}{range_op}{hi}).contains(&{name})"),
applicability,
);
}
@@ -372,14 +372,14 @@ fn check_exclusive_range_plus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
diag.span_suggestion(
span,
"use",
- format!("({}..={})", start, end),
+ format!("({start}..={end})"),
Applicability::MaybeIncorrect,
);
} else {
diag.span_suggestion(
span,
"use",
- format!("{}..={}", start, end),
+ format!("{start}..={end}"),
Applicability::MachineApplicable, // snippet
);
}
@@ -408,7 +408,7 @@ fn check_inclusive_range_minus_one(cx: &LateContext<'_>, expr: &Expr<'_>) {
diag.span_suggestion(
expr.span,
"use",
- format!("{}..{}", start, end),
+ format!("{start}..{end}"),
Applicability::MachineApplicable, // snippet
);
},
@@ -486,7 +486,7 @@ fn check_reversed_empty_range(cx: &LateContext<'_>, expr: &Expr<'_>) {
expr.span,
"consider using the following if you are attempting to iterate over this \
range in reverse",
- format!("({}{}{}).rev()", end_snippet, dots, start_snippet),
+ format!("({end_snippet}{dots}{start_snippet}).rev()"),
Applicability::MaybeIncorrect,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
index 2882ba033..fa1078588 100644
--- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs
@@ -2,9 +2,10 @@ use clippy_utils::{
diagnostics::{span_lint, span_lint_and_sugg},
higher::{get_vec_init_kind, VecInitKind},
source::snippet,
- visitors::expr_visitor_no_bodies,
+ visitors::for_each_expr,
};
-use hir::{intravisit::Visitor, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind};
+use core::ops::ControlFlow;
+use hir::{Expr, ExprKind, Local, PatKind, PathSegment, QPath, StmtKind};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
@@ -43,7 +44,7 @@ declare_clippy_lint! {
/// ```
#[clippy::version = "1.63.0"]
pub READ_ZERO_BYTE_VEC,
- nursery,
+ correctness,
"checks for reads into a zero-length `Vec`"
}
declare_lint_pass!(ReadZeroByteVec => [READ_ZERO_BYTE_VEC]);
@@ -58,10 +59,8 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
&& let PatKind::Binding(_, _, ident, _) = pat.kind
&& let Some(vec_init_kind) = get_vec_init_kind(cx, init)
{
- // finds use of `_.read(&mut v)`
- let mut read_found = false;
- let mut visitor = expr_visitor_no_bodies(|expr| {
- if let ExprKind::MethodCall(path, _self, [arg], _) = expr.kind
+ let visitor = |expr: &Expr<'_>| {
+ if let ExprKind::MethodCall(path, _, [arg], _) = expr.kind
&& let PathSegment { ident: read_or_read_exact, .. } = *path
&& matches!(read_or_read_exact.as_str(), "read" | "read_exact")
&& let ExprKind::AddrOf(_, hir::Mutability::Mut, inner) = arg.kind
@@ -69,27 +68,22 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
&& let [inner_seg] = inner_path.segments
&& ident.name == inner_seg.ident.name
{
- read_found = true;
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
- !read_found
- });
+ };
- let next_stmt_span;
- if idx == block.stmts.len() - 1 {
+ let (read_found, next_stmt_span) =
+ if let Some(next_stmt) = block.stmts.get(idx + 1) {
+ // case { .. stmt; stmt; .. }
+ (for_each_expr(next_stmt, visitor).is_some(), next_stmt.span)
+ } else if let Some(e) = block.expr {
// case { .. stmt; expr }
- if let Some(e) = block.expr {
- visitor.visit_expr(e);
- next_stmt_span = e.span;
- } else {
- return;
- }
+ (for_each_expr(e, visitor).is_some(), e.span)
} else {
- // case { .. stmt; stmt; .. }
- let next_stmt = &block.stmts[idx + 1];
- visitor.visit_stmt(next_stmt);
- next_stmt_span = next_stmt.span;
- }
- drop(visitor);
+ return
+ };
if read_found && !next_stmt_span.from_expansion() {
let applicability = Applicability::MaybeIncorrect;
@@ -101,9 +95,8 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec {
next_stmt_span,
"reading zero byte data to `Vec`",
"try",
- format!("{}.resize({}, 0); {}",
+ format!("{}.resize({len}, 0); {}",
ident.as_str(),
- len,
snippet(cx, next_stmt_span, "..")
),
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index 9fd86331e..aedbe08e3 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -1,25 +1,18 @@
use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
+use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, walk_ptrs_ty_depth};
use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
use if_chain::if_chain;
-use rustc_data_structures::fx::FxHashMap;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
use rustc_hir::{def_id, Body, FnDecl, HirId};
-use rustc_index::bit_set::{BitSet, HybridBitSet};
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::mir::{
- self, traversal,
- visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
- Mutability,
-};
-use rustc_middle::ty::{self, visit::TypeVisitor, Ty};
-use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor};
+use rustc_middle::mir;
+use rustc_middle::ty::{self, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{BytePos, Span};
use rustc_span::sym;
-use std::ops::ControlFlow;
macro_rules! unwrap_or_continue {
($x:expr) => {
@@ -89,21 +82,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
let mir = cx.tcx.optimized_mir(def_id.to_def_id());
- let possible_origin = {
- let mut vis = PossibleOriginVisitor::new(mir);
- vis.visit_body(mir);
- vis.into_map(cx)
- };
- let maybe_storage_live_result = MaybeStorageLive
- .into_engine(cx.tcx, mir)
- .pass_name("redundant_clone")
- .iterate_to_fixpoint()
- .into_results_cursor(mir);
- let mut possible_borrower = {
- let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
- vis.visit_body(mir);
- vis.into_map(cx, maybe_storage_live_result)
- };
+ let mut possible_borrower = PossibleBorrowerMap::new(cx, mir);
for (bb, bbdata) in mir.basic_blocks.iter_enumerated() {
let terminator = bbdata.terminator();
@@ -374,403 +353,40 @@ struct CloneUsage {
/// Whether the clone value is mutated.
clone_consumed_or_mutated: bool,
}
-fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage {
- struct V {
- cloned: mir::Local,
- clone: mir::Local,
- result: CloneUsage,
- }
- impl<'tcx> mir::visit::Visitor<'tcx> for V {
- fn visit_basic_block_data(&mut self, block: mir::BasicBlock, data: &mir::BasicBlockData<'tcx>) {
- let statements = &data.statements;
- for (statement_index, statement) in statements.iter().enumerate() {
- self.visit_statement(statement, mir::Location { block, statement_index });
- }
-
- self.visit_terminator(
- data.terminator(),
- mir::Location {
- block,
- statement_index: statements.len(),
- },
- );
- }
-
- fn visit_place(&mut self, place: &mir::Place<'tcx>, ctx: PlaceContext, loc: mir::Location) {
- let local = place.local;
-
- if local == self.cloned
- && !matches!(
- ctx,
- PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)
- )
- {
- self.result.cloned_used = true;
- self.result.cloned_consume_or_mutate_loc = self.result.cloned_consume_or_mutate_loc.or_else(|| {
- matches!(
- ctx,
- PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
- | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
- )
- .then(|| loc)
- });
- } else if local == self.clone {
- match ctx {
- PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
- | PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
- self.result.clone_consumed_or_mutated = true;
- },
- _ => {},
- }
- }
- }
- }
-
- let init = CloneUsage {
- cloned_used: false,
- cloned_consume_or_mutate_loc: None,
- // Consider non-temporary clones consumed.
- // TODO: Actually check for mutation of non-temporaries.
- clone_consumed_or_mutated: mir.local_kind(clone) != mir::LocalKind::Temp,
- };
- traversal::ReversePostorder::new(mir, bb)
- .skip(1)
- .fold(init, |usage, (tbb, tdata)| {
- // Short-circuit
- if (usage.cloned_used && usage.clone_consumed_or_mutated) ||
- // Give up on loops
- tdata.terminator().successors().any(|s| s == bb)
- {
- return CloneUsage {
- cloned_used: true,
- clone_consumed_or_mutated: true,
- ..usage
- };
- }
-
- let mut v = V {
- cloned,
- clone,
- result: usage,
- };
- v.visit_basic_block_data(tbb, tdata);
- v.result
- })
-}
-
-/// Determines liveness of each local purely based on `StorageLive`/`Dead`.
-#[derive(Copy, Clone)]
-struct MaybeStorageLive;
-
-impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive {
- type Domain = BitSet<mir::Local>;
- const NAME: &'static str = "maybe_storage_live";
-
- fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
- // bottom = dead
- BitSet::new_empty(body.local_decls.len())
- }
-
- fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {
- for arg in body.args_iter() {
- state.insert(arg);
- }
- }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
- type Idx = mir::Local;
-
- fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) {
- match stmt.kind {
- mir::StatementKind::StorageLive(l) => trans.gen(l),
- mir::StatementKind::StorageDead(l) => trans.kill(l),
- _ => (),
- }
- }
-
- fn terminator_effect(
- &self,
- _trans: &mut impl GenKill<Self::Idx>,
- _terminator: &mir::Terminator<'tcx>,
- _loc: mir::Location,
- ) {
- }
-
- fn call_return_effect(
- &self,
- _trans: &mut impl GenKill<Self::Idx>,
- _block: mir::BasicBlock,
- _return_places: CallReturnPlaces<'_, 'tcx>,
- ) {
- // Nothing to do when a call returns successfully
- }
-}
-
-/// Collects the possible borrowers of each local.
-/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
-/// possible borrowers of `a`.
-struct PossibleBorrowerVisitor<'a, 'tcx> {
- possible_borrower: TransitiveRelation,
- body: &'a mir::Body<'tcx>,
- cx: &'a LateContext<'tcx>,
- possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
-}
-
-impl<'a, 'tcx> PossibleBorrowerVisitor<'a, 'tcx> {
- fn new(
- cx: &'a LateContext<'tcx>,
- body: &'a mir::Body<'tcx>,
- possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
- ) -> Self {
- Self {
- possible_borrower: TransitiveRelation::default(),
- cx,
- body,
- possible_origin,
- }
- }
-
- fn into_map(
- self,
- cx: &LateContext<'tcx>,
- maybe_live: ResultsCursor<'tcx, 'tcx, MaybeStorageLive>,
- ) -> PossibleBorrowerMap<'a, 'tcx> {
- let mut map = FxHashMap::default();
- for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
- if is_copy(cx, self.body.local_decls[row].ty) {
- continue;
- }
-
- let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
- borrowers.remove(mir::Local::from_usize(0));
- if !borrowers.is_empty() {
- map.insert(row, borrowers);
- }
- }
-
- let bs = BitSet::new_empty(self.body.local_decls.len());
- PossibleBorrowerMap {
- map,
- maybe_live,
- bitset: (bs.clone(), bs),
- }
- }
-}
-
-impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'tcx> {
- fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
- let lhs = place.local;
- match rvalue {
- mir::Rvalue::Ref(_, _, borrowed) => {
- self.possible_borrower.add(borrowed.local, lhs);
- },
- other => {
- if ContainsRegion
- .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
- .is_continue()
- {
- return;
- }
- rvalue_locals(other, |rhs| {
- if lhs != rhs {
- self.possible_borrower.add(rhs, lhs);
- }
- });
- },
- }
- }
-
- fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
- if let mir::TerminatorKind::Call {
- args,
- destination: mir::Place { local: dest, .. },
- ..
- } = &terminator.kind
- {
- // TODO add doc
- // If the call returns something with lifetimes,
- // let's conservatively assume the returned value contains lifetime of all the arguments.
- // For example, given `let y: Foo<'a> = foo(x)`, `y` is considered to be a possible borrower of `x`.
-
- let mut immutable_borrowers = vec![];
- let mut mutable_borrowers = vec![];
-
- for op in args {
- match op {
- mir::Operand::Copy(p) | mir::Operand::Move(p) => {
- if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
- mutable_borrowers.push(p.local);
- } else {
- immutable_borrowers.push(p.local);
- }
- },
- mir::Operand::Constant(..) => (),
- }
- }
-
- let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
- .iter()
- .filter_map(|r| self.possible_origin.get(r))
- .flat_map(HybridBitSet::iter)
- .collect();
-
- if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
- mutable_variables.push(*dest);
- }
-
- for y in mutable_variables {
- for x in &immutable_borrowers {
- self.possible_borrower.add(*x, y);
- }
- for x in &mutable_borrowers {
- self.possible_borrower.add(*x, y);
- }
- }
- }
- }
-}
-
-/// Collect possible borrowed for every `&mut` local.
-/// For example, `_1 = &mut _2` generate _1: {_2,...}
-/// Known Problems: not sure all borrowed are tracked
-struct PossibleOriginVisitor<'a, 'tcx> {
- possible_origin: TransitiveRelation,
- body: &'a mir::Body<'tcx>,
-}
-
-impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
- fn new(body: &'a mir::Body<'tcx>) -> Self {
- Self {
- possible_origin: TransitiveRelation::default(),
- body,
- }
- }
-
- fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> {
- let mut map = FxHashMap::default();
- for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
- if is_copy(cx, self.body.local_decls[row].ty) {
- continue;
- }
-
- let mut borrowers = self.possible_origin.reachable_from(row, self.body.local_decls.len());
- borrowers.remove(mir::Local::from_usize(0));
- if !borrowers.is_empty() {
- map.insert(row, borrowers);
- }
- }
- map
- }
-}
-
-impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
- fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
- let lhs = place.local;
- match rvalue {
- // Only consider `&mut`, which can modify origin place
- mir::Rvalue::Ref(_, rustc_middle::mir::BorrowKind::Mut { .. }, borrowed) |
- // _2: &mut _;
- // _3 = move _2
- mir::Rvalue::Use(mir::Operand::Move(borrowed)) |
- // _3 = move _2 as &mut _;
- mir::Rvalue::Cast(_, mir::Operand::Move(borrowed), _)
- => {
- self.possible_origin.add(lhs, borrowed.local);
- },
- _ => {},
- }
- }
-}
-
-struct ContainsRegion;
-
-impl TypeVisitor<'_> for ContainsRegion {
- type BreakTy = ();
-
- fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
- ControlFlow::BREAK
- }
-}
-
-fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
- use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use};
-
- let mut visit_op = |op: &mir::Operand<'_>| match op {
- mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),
- mir::Operand::Constant(..) => (),
- };
- match rvalue {
- Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op),
- Aggregate(_, ops) => ops.iter().for_each(visit_op),
- BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
- visit_op(lhs);
- visit_op(rhs);
+fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>, bb: mir::BasicBlock) -> CloneUsage {
+ if let Some((
+ LocalUsage {
+ local_use_locs: cloned_use_locs,
+ local_consume_or_mutate_locs: cloned_consume_or_mutate_locs,
},
- _ => (),
- }
-}
-
-/// Result of `PossibleBorrowerVisitor`.
-struct PossibleBorrowerMap<'a, 'tcx> {
- /// Mapping `Local -> its possible borrowers`
- map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
- maybe_live: ResultsCursor<'a, 'tcx, MaybeStorageLive>,
- // Caches to avoid allocation of `BitSet` on every query
- bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
-}
-
-impl PossibleBorrowerMap<'_, '_> {
- /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
- fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
- self.maybe_live.seek_after_primary_effect(at);
-
- self.bitset.0.clear();
- let maybe_live = &mut self.maybe_live;
- if let Some(bitset) = self.map.get(&borrowed) {
- for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) {
- self.bitset.0.insert(b);
- }
- } else {
- return false;
- }
-
- self.bitset.1.clear();
- for b in borrowers {
- self.bitset.1.insert(*b);
+ LocalUsage {
+ local_use_locs: _,
+ local_consume_or_mutate_locs: clone_consume_or_mutate_locs,
+ },
+ )) = visit_local_usage(
+ &[cloned, clone],
+ mir,
+ mir::Location {
+ block: bb,
+ statement_index: mir.basic_blocks[bb].statements.len(),
+ },
+ )
+ .map(|mut vec| (vec.remove(0), vec.remove(0)))
+ {
+ CloneUsage {
+ cloned_used: !cloned_use_locs.is_empty(),
+ cloned_consume_or_mutate_loc: cloned_consume_or_mutate_locs.first().copied(),
+ // Consider non-temporary clones consumed.
+ // TODO: Actually check for mutation of non-temporaries.
+ clone_consumed_or_mutated: mir.local_kind(clone) != mir::LocalKind::Temp
+ || !clone_consume_or_mutate_locs.is_empty(),
}
-
- self.bitset.0 == self.bitset.1
- }
-
- fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
- self.maybe_live.seek_after_primary_effect(at);
- self.maybe_live.contains(local)
- }
-}
-
-#[derive(Default)]
-struct TransitiveRelation {
- relations: FxHashMap<mir::Local, Vec<mir::Local>>,
-}
-impl TransitiveRelation {
- fn add(&mut self, a: mir::Local, b: mir::Local) {
- self.relations.entry(a).or_default().push(b);
- }
-
- fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> {
- let mut seen = HybridBitSet::new_empty(domain_size);
- let mut stack = vec![a];
- while let Some(u) = stack.pop() {
- if let Some(edges) = self.relations.get(&u) {
- for &v in edges {
- if seen.insert(v) {
- stack.push(v);
- }
- }
- }
+ } else {
+ CloneUsage {
+ cloned_used: true,
+ cloned_consume_or_mutate_loc: None,
+ clone_consumed_or_mutated: true,
}
- seen
}
}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
index 323326381..26075e9f7 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs
@@ -46,17 +46,17 @@ impl_lint_pass!(RedundantPubCrate => [REDUNDANT_PUB_CRATE]);
impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if_chain! {
- if cx.tcx.visibility(item.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
- if !cx.access_levels.is_exported(item.def_id) && self.is_exported.last() == Some(&false);
+ if cx.tcx.visibility(item.owner_id.def_id) == ty::Visibility::Restricted(CRATE_DEF_ID.to_def_id());
+ if !cx.effective_visibilities.is_exported(item.owner_id.def_id) && self.is_exported.last() == Some(&false);
if is_not_macro_export(item);
then {
let span = item.span.with_hi(item.ident.span.hi());
- let descr = cx.tcx.def_kind(item.def_id).descr(item.def_id.to_def_id());
+ let descr = cx.tcx.def_kind(item.owner_id).descr(item.owner_id.to_def_id());
span_lint_and_then(
cx,
REDUNDANT_PUB_CRATE,
span,
- &format!("pub(crate) {} inside private module", descr),
+ &format!("pub(crate) {descr} inside private module"),
|diag| {
diag.span_suggestion(
item.vis_span,
@@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate {
}
if let ItemKind::Mod { .. } = item.kind {
- self.is_exported.push(cx.access_levels.is_exported(item.def_id));
+ self.is_exported.push(cx.effective_visibilities.is_exported(item.owner_id.def_id));
}
}
diff --git a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
index 8693ca9af..245a02ea2 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_slicing.rs
@@ -127,9 +127,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if (deref_count != 0 || !reborrow_str.is_empty()) && needs_parens_for_prefix {
- format!("({}{}{})", reborrow_str, "*".repeat(deref_count), snip)
+ format!("({reborrow_str}{}{snip})", "*".repeat(deref_count))
} else {
- format!("{}{}{}", reborrow_str, "*".repeat(deref_count), snip)
+ format!("{reborrow_str}{}{snip}", "*".repeat(deref_count))
};
(lint, help_str, sugg)
@@ -141,9 +141,9 @@ impl<'tcx> LateLintPass<'tcx> for RedundantSlicing {
if deref_ty == expr_ty {
let snip = snippet_with_context(cx, indexed.span, ctxt, "..", &mut app).0;
let sugg = if needs_parens_for_prefix {
- format!("(&{}{}*{})", mutability.prefix_str(), "*".repeat(indexed_ref_count), snip)
+ format!("(&{}{}*{snip})", mutability.prefix_str(), "*".repeat(indexed_ref_count))
} else {
- format!("&{}{}*{}", mutability.prefix_str(), "*".repeat(indexed_ref_count), snip)
+ format!("&{}{}*{snip}", mutability.prefix_str(), "*".repeat(indexed_ref_count))
};
(DEREF_BY_SLICING_LINT, "dereference the original value instead", sugg)
} else {
diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
index 2d751c274..60ba62c4a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs
@@ -67,7 +67,7 @@ impl RedundantStaticLifetimes {
TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) => {
if lifetime.ident.name == rustc_span::symbol::kw::StaticLifetime {
let snip = snippet(cx, borrow_type.ty.span, "<type>");
- let sugg = format!("&{}", snip);
+ let sugg = format!("&{snip}");
span_lint_and_then(
cx,
REDUNDANT_STATIC_LIFETIMES,
diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
index 42514f861..f21b3ea6c 100644
--- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs
@@ -52,7 +52,8 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef {
GenericArg::Type(inner_ty) => Some(inner_ty),
_ => None,
});
- if let TyKind::Rptr(_, _) = inner_ty.kind;
+ if let TyKind::Rptr(_, ref inner_mut_ty) = inner_ty.kind;
+ if inner_mut_ty.mutbl == Mutability::Not;
then {
span_lint_and_sugg(
diff --git a/src/tools/clippy/clippy_lints/src/regex.rs b/src/tools/clippy/clippy_lints/src/regex.rs
index 6bcae0da8..1fda58fa5 100644
--- a/src/tools/clippy/clippy_lints/src/regex.rs
+++ b/src/tools/clippy/clippy_lints/src/regex.rs
@@ -172,7 +172,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
);
},
Err(e) => {
- span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
+ span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
},
}
}
@@ -200,7 +200,7 @@ fn check_regex<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, utf8: bool) {
);
},
Err(e) => {
- span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {}", e));
+ span_lint(cx, INVALID_REGEX, expr.span, &format!("regex syntax error: {e}"));
},
}
}
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 6bea6dc07..76d6ad0b2 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -11,8 +11,8 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::disallowed_method", "clippy::disallowed_methods"),
("clippy::disallowed_type", "clippy::disallowed_types"),
("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"),
- ("clippy::for_loop_over_option", "clippy::for_loops_over_fallibles"),
- ("clippy::for_loop_over_result", "clippy::for_loops_over_fallibles"),
+ ("clippy::for_loop_over_option", "for_loops_over_fallibles"),
+ ("clippy::for_loop_over_result", "for_loops_over_fallibles"),
("clippy::identity_conversion", "clippy::useless_conversion"),
("clippy::if_let_some_result", "clippy::match_result_ok"),
("clippy::logic_bug", "clippy::overly_complex_bool_expr"),
@@ -31,11 +31,13 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
("clippy::to_string_in_display", "clippy::recursive_format_impl"),
("clippy::zero_width_space", "clippy::invisible_characters"),
("clippy::drop_bounds", "drop_bounds"),
+ ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
("clippy::into_iter_on_array", "array_into_iter"),
("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
("clippy::invalid_ref", "invalid_value"),
("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"),
("clippy::panic_params", "non_fmt_panics"),
+ ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"),
("clippy::temporary_cstring_as_ptr", "temporary_cstring_as_ptr"),
("clippy::unknown_clippy_lints", "unknown_lints"),
("clippy::unused_label", "unused_labels"),
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 60be6bd33..b77faf732 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
@@ -74,7 +74,7 @@ fn check_method(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_def: LocalDefId, spa
if !in_external_macro(cx.sess(), span);
if decl.implicit_self.has_implicit_self();
// We only show this warning for public exported methods.
- if cx.access_levels.is_exported(fn_def);
+ 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.visibility(fn_def.to_def_id()).is_public();
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for ReturnSelfNotMustUse {
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.def_id, item.span, item.hir_id());
+ check_method(cx, sig.decl, item.owner_id.def_id, item.span, item.hir_id());
}
}
}
diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs
index 91553240e..2b2a41d16 100644
--- a/src/tools/clippy/clippy_lints/src/returns.rs
+++ b/src/tools/clippy/clippy_lints/src/returns.rs
@@ -1,9 +1,11 @@
-use clippy_utils::diagnostics::span_lint_hir_and_then;
+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 core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
+use rustc_hir::intravisit::FnKind;
use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -72,6 +74,27 @@ enum RetReplacement {
Unit,
}
+impl RetReplacement {
+ fn sugg_help(self) -> &'static str {
+ match self {
+ Self::Empty => "remove `return`",
+ Self::Block => "replace `return` with an empty block",
+ Self::Unit => "replace `return` with a unit value",
+ }
+ }
+}
+
+impl ToString for RetReplacement {
+ fn to_string(&self) -> String {
+ match *self {
+ Self::Empty => "",
+ Self::Block => "{}",
+ Self::Unit => "()",
+ }
+ .to_string()
+ }
+}
+
declare_lint_pass!(Return => [LET_AND_RETURN, NEEDLESS_RETURN]);
impl<'tcx> LateLintPass<'tcx> for Return {
@@ -139,26 +162,35 @@ impl<'tcx> LateLintPass<'tcx> for Return {
} else {
RetReplacement::Empty
};
- check_final_expr(cx, body.value, Some(body.value.span), replacement);
+ check_final_expr(cx, body.value, vec![], replacement);
},
FnKind::ItemFn(..) | FnKind::Method(..) => {
- if let ExprKind::Block(block, _) = body.value.kind {
- check_block_return(cx, block);
- }
+ check_block_return(cx, &body.value.kind, vec![]);
},
}
}
}
-fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) {
- if let Some(expr) = block.expr {
- check_final_expr(cx, expr, Some(expr.span), RetReplacement::Empty);
- } else if let Some(stmt) = block.stmts.iter().last() {
- match stmt.kind {
- StmtKind::Expr(expr) | StmtKind::Semi(expr) => {
- check_final_expr(cx, expr, Some(stmt.span), RetReplacement::Empty);
- },
- _ => (),
+// 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>) {
+ if let ExprKind::Block(block, _) = expr_kind {
+ if let Some(block_expr) = block.expr {
+ check_final_expr(cx, block_expr, semi_spans, RetReplacement::Empty);
+ } else if let Some(stmt) = block.stmts.iter().last() {
+ match stmt.kind {
+ StmtKind::Expr(expr) => {
+ 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);
+ }
+ },
+ _ => (),
+ }
}
}
}
@@ -166,10 +198,12 @@ fn check_block_return<'tcx>(cx: &LateContext<'tcx>, block: &Block<'tcx>) {
fn check_final_expr<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'tcx>,
- span: Option<Span>,
+ semi_spans: Vec<Span>, /* containing all the places where we would need to remove semicolons if finding an
+ * needless return */
replacement: RetReplacement,
) {
- match expr.kind {
+ let peeled_drop_expr = expr.peel_drop_temps();
+ match &peeled_drop_expr.kind {
// simple return is always "bad"
ExprKind::Ret(ref inner) => {
if cx.tcx.hir().attrs(expr.hir_id).is_empty() {
@@ -177,24 +211,18 @@ fn check_final_expr<'tcx>(
if !borrows {
emit_return_lint(
cx,
- inner.map_or(expr.hir_id, |inner| inner.hir_id),
- span.expect("`else return` is not possible"),
+ peeled_drop_expr.span,
+ semi_spans,
inner.as_ref().map(|i| i.span),
replacement,
);
}
}
},
- // a whole block? check it!
- ExprKind::Block(block, _) => {
- check_block_return(cx, block);
- },
ExprKind::If(_, then, else_clause_opt) => {
- if let ExprKind::Block(ifblock, _) = then.kind {
- check_block_return(cx, ifblock);
- }
+ check_block_return(cx, &then.kind, semi_spans.clone());
if let Some(else_clause) = else_clause_opt {
- check_final_expr(cx, else_clause, None, RetReplacement::Empty);
+ check_block_return(cx, &else_clause.kind, semi_spans);
}
},
// a match expr, check all arms
@@ -203,123 +231,61 @@ fn check_final_expr<'tcx>(
// (except for unit type functions) so we don't match it
ExprKind::Match(_, arms, MatchSource::Normal) => {
for arm in arms.iter() {
- check_final_expr(cx, arm.body, Some(arm.body.span), RetReplacement::Unit);
+ check_final_expr(cx, arm.body, semi_spans.clone(), RetReplacement::Unit);
}
},
- ExprKind::DropTemps(expr) => check_final_expr(cx, expr, None, RetReplacement::Empty),
- _ => (),
+ // if it's a whole block, check it
+ other_expr_kind => check_block_return(cx, other_expr_kind, semi_spans),
}
}
fn emit_return_lint(
cx: &LateContext<'_>,
- emission_place: HirId,
ret_span: Span,
+ semi_spans: Vec<Span>,
inner_span: Option<Span>,
replacement: RetReplacement,
) {
if ret_span.from_expansion() {
return;
}
- match inner_span {
- Some(inner_span) => {
- let mut applicability = Applicability::MachineApplicable;
- span_lint_hir_and_then(
- cx,
- NEEDLESS_RETURN,
- emission_place,
- ret_span,
- "unneeded `return` statement",
- |diag| {
- let (snippet, _) = snippet_with_context(cx, inner_span, ret_span.ctxt(), "..", &mut applicability);
- diag.span_suggestion(ret_span, "remove `return`", snippet, applicability);
- },
- );
- },
- None => match replacement {
- RetReplacement::Empty => {
- span_lint_hir_and_then(
- cx,
- NEEDLESS_RETURN,
- emission_place,
- ret_span,
- "unneeded `return` statement",
- |diag| {
- diag.span_suggestion(
- ret_span,
- "remove `return`",
- String::new(),
- Applicability::MachineApplicable,
- );
- },
- );
- },
- RetReplacement::Block => {
- span_lint_hir_and_then(
- cx,
- NEEDLESS_RETURN,
- emission_place,
- ret_span,
- "unneeded `return` statement",
- |diag| {
- diag.span_suggestion(
- ret_span,
- "replace `return` with an empty block",
- "{}".to_string(),
- Applicability::MachineApplicable,
- );
- },
- );
- },
- RetReplacement::Unit => {
- span_lint_hir_and_then(
- cx,
- NEEDLESS_RETURN,
- emission_place,
- ret_span,
- "unneeded `return` statement",
- |diag| {
- diag.span_suggestion(
- ret_span,
- "replace `return` with a unit value",
- "()".to_string(),
- Applicability::MachineApplicable,
- );
- },
- );
- },
+ 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()
+ };
+ 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
+ for semi_stmt_span in semi_spans {
+ diag.tool_only_span_suggestion(semi_stmt_span, "remove this semicolon", "", applicability);
+ }
+ });
}
fn last_statement_borrows<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
- let mut visitor = BorrowVisitor { cx, borrows: false };
- walk_expr(&mut visitor, expr);
- visitor.borrows
-}
-
-struct BorrowVisitor<'a, 'tcx> {
- cx: &'a LateContext<'tcx>,
- borrows: bool,
-}
-
-impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
- if self.borrows || expr.span.from_expansion() {
- return;
- }
-
- if let Some(def_id) = fn_def_id(self.cx, expr) {
- self.borrows = self
- .cx
+ for_each_expr(expr, |e| {
+ if let Some(def_id) = fn_def_id(cx, e)
+ && cx
.tcx
.fn_sig(def_id)
- .output()
.skip_binder()
+ .output()
.walk()
- .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
+ .any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
+ {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::from(!expr.span.from_expansion()))
}
-
- walk_expr(self, expr);
- }
+ })
+ .is_some()
}
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 20184d54b..caab5851b 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.def_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,
@@ -108,7 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
|diag| {
diag.span_note(
trait_method_span,
- &format!("existing `{}` defined here", method_name),
+ &format!("existing `{method_name}` defined here"),
);
},
);
@@ -151,7 +151,7 @@ impl<'tcx> LateLintPass<'tcx> for SameNameMethod {
// iterate on trait_spans?
diag.span_note(
trait_spans[0],
- &format!("existing `{}` defined here", method_name),
+ &format!("existing `{method_name}` defined here"),
);
},
);
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 9cea4d880..71b387c66 100644
--- a/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
+++ b/src/tools/clippy/clippy_lints/src/self_named_constructors.rs
@@ -51,9 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for SelfNamedConstructors {
_ => return,
}
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ 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.def_id);
+ let self_ty = cx.tcx.type_of(item.owner_id);
let ret_ty = return_ty(cx, impl_item.hir_id());
// Do not check trait impls
diff --git a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
index 729694da4..66638eed9 100644
--- a/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/clippy_lints/src/semicolon_if_nothing_returned.rs
@@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for SemicolonIfNothingReturned {
}
let sugg = sugg::Sugg::hir_with_macro_callsite(cx, expr, "..");
- let suggestion = format!("{0};", sugg);
+ let suggestion = format!("{sugg};");
span_lint_and_sugg(
cx,
SEMICOLON_IF_NOTHING_RETURNED,
diff --git a/src/tools/clippy/clippy_lints/src/shadow.rs b/src/tools/clippy/clippy_lints/src/shadow.rs
index 5dcdab5b8..87f966ced 100644
--- a/src/tools/clippy/clippy_lints/src/shadow.rs
+++ b/src/tools/clippy/clippy_lints/src/shadow.rs
@@ -106,10 +106,7 @@ impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);
impl<'tcx> LateLintPass<'tcx> for Shadow {
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
- let (id, ident) = match pat.kind {
- PatKind::Binding(_, hir_id, ident, _) => (hir_id, ident),
- _ => return,
- };
+ let PatKind::Binding(_, id, ident, _) = pat.kind else { return };
if pat.span.desugaring_kind().is_some() {
return;
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index c07aa00a1..760399231 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -1,9 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{get_enclosing_block, is_expr_path_def_path, path_to_local, path_to_local_id, paths, SpanlessEq};
+use clippy_utils::{
+ get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local, path_to_local_id, SpanlessEq,
+};
use if_chain::if_chain;
-use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind};
@@ -174,7 +175,7 @@ impl SlowVectorInit {
diag.span_suggestion(
vec_alloc.allocation_expr.span,
"consider replace allocation with",
- format!("vec![0; {}]", len_expr),
+ format!("vec![0; {len_expr}]"),
Applicability::Unspecified,
);
});
@@ -219,8 +220,7 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
&& path_to_local_id(self_arg, self.vec_alloc.local_id)
&& path.ident.name == sym!(resize)
// Check that is filled with 0
- && let ExprKind::Lit(ref lit) = fill_arg.kind
- && let LitKind::Int(0, _) = lit.node {
+ && is_integer_literal(fill_arg, 0) {
// Check that len expression is equals to `with_capacity` expression
if SpanlessEq::new(self.cx).eq_expr(len_arg, self.vec_alloc.len_expr) {
self.slow_expression = Some(InitializationType::Resize(expr));
@@ -254,10 +254,8 @@ impl<'a, 'tcx> VectorInitializationVisitor<'a, 'tcx> {
fn is_repeat_zero(&self, expr: &Expr<'_>) -> bool {
if_chain! {
if let ExprKind::Call(fn_expr, [repeat_arg]) = expr.kind;
- if is_expr_path_def_path(self.cx, fn_expr, &paths::ITER_REPEAT);
- if let ExprKind::Lit(ref lit) = repeat_arg.kind;
- if let LitKind::Int(0, _) = lit.node;
-
+ if is_path_diagnostic_item(self.cx, fn_expr, sym::iter_repeat);
+ if is_integer_literal(repeat_arg, 0);
then {
true
} else {
diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
index ffd63cc68..d6b336bef 100644
--- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
+++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs
@@ -1,6 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_help;
+use rustc_hir::def_id::DefId;
use rustc_hir::{def::Res, HirId, Path, PathSegment};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::DefIdTree;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, symbol::kw, Span};
@@ -94,6 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) {
if let Res::Def(_, def_id) = path.res
&& let Some(first_segment) = get_first_segment(path)
+ && is_stable(cx, def_id)
{
let (lint, msg, help) = match first_segment.ident.name {
sym::std => match cx.tcx.crate_name(def_id.krate) {
@@ -146,3 +149,22 @@ fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>>
_ => None,
}
}
+
+/// Checks if all ancestors of `def_id` are stable, to avoid linting
+/// [unstable moves](https://github.com/rust-lang/rust/pull/95956)
+fn is_stable(cx: &LateContext<'_>, mut def_id: DefId) -> bool {
+ loop {
+ if cx
+ .tcx
+ .lookup_stability(def_id)
+ .map_or(false, |stability| stability.is_unstable())
+ {
+ return false;
+ }
+
+ match cx.tcx.opt_parent(def_id) {
+ Some(parent) => def_id = parent,
+ None => return true,
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/strings.rs b/src/tools/clippy/clippy_lints/src/strings.rs
index 662d399ca..d356c99c8 100644
--- a/src/tools/clippy/clippy_lints/src/strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strings.rs
@@ -284,7 +284,7 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes {
e.span,
"calling a slice of `as_bytes()` with `from_utf8` should be not necessary",
"try",
- format!("Some(&{}[{}])", snippet_app, snippet(cx, right.span, "..")),
+ format!("Some(&{snippet_app}[{}])", snippet(cx, right.span, "..")),
applicability
)
}
@@ -500,8 +500,8 @@ impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace {
cx,
TRIM_SPLIT_WHITESPACE,
trim_span.with_hi(split_ws_span.lo()),
- &format!("found call to `str::{}` before `str::split_whitespace`", trim_fn_name),
- &format!("remove `{}()`", trim_fn_name),
+ &format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"),
+ &format!("remove `{trim_fn_name}()`"),
String::new(),
Applicability::MachineApplicable,
);
diff --git a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
index 78403d9fd..03324c66e 100644
--- a/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/strlen_on_c_strings.rs
@@ -79,7 +79,7 @@ impl<'tcx> LateLintPass<'tcx> for StrlenOnCStrings {
span,
"using `libc::strlen` on a `CString` or `CStr` value",
"try this",
- format!("{}.{}().len()", val_name, method_name),
+ format!("{val_name}.{method_name}().len()"),
app,
);
}
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
index fe8859905..eef9bdc78 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
@@ -326,8 +326,7 @@ fn replace_left_sugg(
applicability: &mut Applicability,
) -> String {
format!(
- "{} {} {}",
- left_suggestion,
+ "{left_suggestion} {} {}",
binop.op.to_string(),
snippet_with_applicability(cx, binop.right.span, "..", applicability),
)
@@ -340,10 +339,9 @@ fn replace_right_sugg(
applicability: &mut Applicability,
) -> String {
format!(
- "{} {} {}",
+ "{} {} {right_suggestion}",
snippet_with_applicability(cx, binop.left.span, "..", applicability),
binop.op.to_string(),
- right_suggestion,
)
}
@@ -595,7 +593,7 @@ fn ident_difference_expr_with_base_location(
| (Unary(_, _), Unary(_, _))
| (Binary(_, _, _), Binary(_, _, _))
| (Tup(_), Tup(_))
- | (MethodCall(_, _, _), MethodCall(_, _, _))
+ | (MethodCall(_, _, _, _), MethodCall(_, _, _, _))
| (Call(_, _), Call(_, _))
| (ConstBlock(_), ConstBlock(_))
| (Array(_), Array(_))
@@ -676,9 +674,8 @@ fn suggestion_with_swapped_ident(
}
Some(format!(
- "{}{}{}",
+ "{}{new_ident}{}",
snippet_with_applicability(cx, expr.span.with_hi(current_ident.span.lo()), "..", applicability),
- new_ident,
snippet_with_applicability(cx, expr.span.with_lo(current_ident.span.hi()), "..", applicability),
))
})
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index 6add20c1f..b57b484bd 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -1,8 +1,9 @@
use clippy_utils::diagnostics::span_lint;
+use clippy_utils::visitors::for_each_expr;
use clippy_utils::{binop_traits, trait_ref_of_method, BINOP_TRAITS, OP_ASSIGN_TRAITS};
+use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_hir as hir;
-use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -64,11 +65,11 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
// Check for more than one binary operation in the implemented function
// Linting when multiple operations are involved can result in false positives
- let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
+ let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
if let hir::Node::ImplItem(impl_item) = cx.tcx.hir().get_by_def_id(parent_fn);
if let hir::ImplItemKind::Fn(_, body_id) = impl_item.kind;
let body = cx.tcx.hir().body(body_id);
- let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id);
+ let parent_fn = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
if let Some(trait_ref) = trait_ref_of_method(cx, parent_fn);
let trait_id = trait_ref.path.res.def_id();
if ![binop_trait_id, op_assign_trait_id].contains(&trait_id);
@@ -92,25 +93,17 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
}
fn count_binops(expr: &hir::Expr<'_>) -> u32 {
- let mut visitor = BinaryExprVisitor::default();
- visitor.visit_expr(expr);
- visitor.nb_binops
-}
-
-#[derive(Default)]
-struct BinaryExprVisitor {
- nb_binops: u32,
-}
-
-impl<'tcx> Visitor<'tcx> for BinaryExprVisitor {
- fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
- match expr.kind {
+ let mut count = 0u32;
+ let _: Option<!> = for_each_expr(expr, |e| {
+ if matches!(
+ e.kind,
hir::ExprKind::Binary(..)
- | hir::ExprKind::Unary(hir::UnOp::Not | hir::UnOp::Neg, _)
- | hir::ExprKind::AssignOp(..) => self.nb_binops += 1,
- _ => {},
+ | hir::ExprKind::Unary(hir::UnOp::Not | hir::UnOp::Neg, _)
+ | hir::ExprKind::AssignOp(..)
+ ) {
+ count += 1;
}
-
- walk_expr(self, expr);
- }
+ ControlFlow::Continue(())
+ });
+ count
}
diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs
index 1885f3ca4..f46c21e12 100644
--- a/src/tools/clippy/clippy_lints/src/swap.rs
+++ b/src/tools/clippy/clippy_lints/src/swap.rs
@@ -96,7 +96,7 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
cx,
MANUAL_SWAP,
span,
- &format!("this looks like you are swapping elements of `{}` manually", slice),
+ &format!("this looks like you are swapping elements of `{slice}` manually"),
"try",
format!(
"{}.swap({}, {})",
@@ -121,16 +121,16 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
cx,
MANUAL_SWAP,
span,
- &format!("this looks like you are swapping `{}` and `{}` manually", first, second),
+ &format!("this looks like you are swapping `{first}` and `{second}` manually"),
|diag| {
diag.span_suggestion(
span,
"try",
- format!("{}::mem::swap({}, {})", sugg, first.mut_addr(), second.mut_addr()),
+ format!("{sugg}::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
applicability,
);
if !is_xor_based {
- diag.note(&format!("or maybe you should use `{}::mem::replace`?", sugg));
+ diag.note(&format!("or maybe you should use `{sugg}::mem::replace`?"));
}
},
);
@@ -182,7 +182,7 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
let rhs0 = Sugg::hir_opt(cx, rhs0);
let (what, lhs, rhs) = if let (Some(first), Some(second)) = (lhs0, rhs0) {
(
- format!(" `{}` and `{}`", first, second),
+ format!(" `{first}` and `{second}`"),
first.mut_addr().to_string(),
second.mut_addr().to_string(),
)
@@ -196,22 +196,19 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
span_lint_and_then(cx,
ALMOST_SWAPPED,
span,
- &format!("this looks like you are trying to swap{}", what),
+ &format!("this looks like you are trying to swap{what}"),
|diag| {
if !what.is_empty() {
diag.span_suggestion(
span,
"try",
format!(
- "{}::mem::swap({}, {})",
- sugg,
- lhs,
- rhs,
+ "{sugg}::mem::swap({lhs}, {rhs})",
),
Applicability::MaybeIncorrect,
);
diag.note(
- &format!("or maybe you should use `{}::mem::replace`?", sugg)
+ &format!("or maybe you should use `{sugg}::mem::replace`?")
);
}
});
diff --git a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
index 3cbbda80f..d085dda35 100644
--- a/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
+++ b/src/tools/clippy/clippy_lints/src/swap_ptr_to_ref.rs
@@ -58,7 +58,7 @@ impl LateLintPass<'_> for SwapPtrToRef {
let mut app = Applicability::MachineApplicable;
let snip1 = snippet_with_context(cx, arg1_span.unwrap_or(arg1.span), ctxt, "..", &mut app).0;
let snip2 = snippet_with_context(cx, arg2_span.unwrap_or(arg2.span), ctxt, "..", &mut app).0;
- diag.span_suggestion(e.span, "use ptr::swap", format!("core::ptr::swap({}, {})", snip1, snip2), app);
+ diag.span_suggestion(e.span, "use ptr::swap", format!("core::ptr::swap({snip1}, {snip2})"), app);
}
}
);
diff --git a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
index 651201f34..2512500a6 100644
--- a/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
+++ b/src/tools/clippy/clippy_lints/src/to_digit_is_some.rs
@@ -84,9 +84,9 @@ impl<'tcx> LateLintPass<'tcx> for ToDigitIsSome {
"use of `.to_digit(..).is_some()`",
"try this",
if is_method_call {
- format!("{}.is_digit({})", char_arg_snip, radix_snip)
+ format!("{char_arg_snip}.is_digit({radix_snip})")
} else {
- format!("char::is_digit({}, {})", char_arg_snip, radix_snip)
+ format!("char::is_digit({char_arg_snip}, {radix_snip})")
},
applicability,
);
diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
index 58cc057a3..8cf3efc8d 100644
--- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
+++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs
@@ -46,7 +46,7 @@ impl<'tcx> LateLintPass<'tcx> for TrailingEmptyArray {
None,
&format!(
"consider annotating `{}` with `#[repr(C)]` or another `repr` attribute",
- cx.tcx.def_path_str(item.def_id.to_def_id())
+ cx.tcx.def_path_str(item.owner_id.to_def_id())
),
);
}
diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
index a25be93b8..b5f11b4ac 100644
--- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs
+++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs
@@ -128,7 +128,7 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds {
if !bound_predicate.span.from_expansion();
if let TyKind::Path(QPath::Resolved(_, Path { segments, .. })) = bound_predicate.bounded_ty.kind;
if let Some(PathSegment {
- res: Res::SelfTy{ trait_: Some(def_id), alias_to: _ }, ..
+ res: Res::SelfTyParam { trait_: def_id }, ..
}) = segments.first();
if let Some(
Node::Item(
@@ -215,9 +215,8 @@ impl TraitBounds {
.map(|(_, _, span)| snippet_with_applicability(cx, span, "..", &mut applicability))
.join(" + ");
let hint_string = format!(
- "consider combining the bounds: `{}: {}`",
+ "consider combining the bounds: `{}: {trait_bounds}`",
snippet(cx, p.bounded_ty.span, "_"),
- trait_bounds,
);
span_lint_and_help(
cx,
diff --git a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
index 25d0543c8..c4b9d82fc 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/crosspointer_transmute.rs
@@ -13,10 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
- &format!(
- "transmute from a type (`{}`) to the type that it points to (`{}`)",
- from_ty, to_ty
- ),
+ &format!("transmute from a type (`{from_ty}`) to the type that it points to (`{to_ty}`)"),
);
true
},
@@ -25,10 +22,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
cx,
CROSSPOINTER_TRANSMUTE,
e.span,
- &format!(
- "transmute from a type (`{}`) to a pointer to that type (`{}`)",
- from_ty, to_ty
- ),
+ &format!("transmute from a type (`{from_ty}`) to a pointer to that type (`{to_ty}`)"),
);
true
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
index 1bde977cf..5ecba512b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_float_to_int.rs
@@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_FLOAT_TO_INT,
e.span,
- &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+ &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
|diag| {
let mut sugg = sugg::Sugg::hir(cx, arg, "..");
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(
if let ExprKind::Lit(lit) = &arg.kind;
if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node;
then {
- let op = format!("{}{}", sugg, float_ty.name_str()).into();
+ let op = format!("{sugg}{}", float_ty.name_str()).into();
match sugg {
sugg::Sugg::MaybeParen(_) => sugg = sugg::Sugg::MaybeParen(op),
_ => sugg = sugg::Sugg::NonParen(op)
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
index 8c50b58ca..58227c53d 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_bool.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_INT_TO_BOOL,
e.span,
- &format!("transmute from a `{}` to a `bool`", from_ty),
+ &format!("transmute from a `{from_ty}` to a `bool`"),
|diag| {
let arg = sugg::Sugg::hir(cx, arg, "..");
let zero = sugg::Sugg::NonParen(Cow::from("0"));
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
index 9e1823c37..7d31c375f 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_char.rs
@@ -23,7 +23,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_INT_TO_CHAR,
e.span,
- &format!("transmute from a `{}` to a `char`", from_ty),
+ &format!("transmute from a `{from_ty}` to a `char`"),
|diag| {
let arg = sugg::Sugg::hir(cx, arg, "..");
let arg = if let ty::Int(_) = from_ty.kind() {
@@ -34,7 +34,7 @@ pub(super) fn check<'tcx>(
diag.span_suggestion(
e.span,
"consider using",
- format!("std::char::from_u32({}).unwrap()", arg),
+ format!("std::char::from_u32({arg}).unwrap()"),
Applicability::Unspecified,
);
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
index b8703052e..cc3422edb 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_int_to_float.rs
@@ -22,7 +22,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_INT_TO_FLOAT,
e.span,
- &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+ &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
|diag| {
let arg = sugg::Sugg::hir(cx, arg, "..");
let arg = if let ty::Int(int_ty) = from_ty.kind() {
@@ -36,7 +36,7 @@ pub(super) fn check<'tcx>(
diag.span_suggestion(
e.span,
"consider using",
- format!("{}::from_bits({})", to_ty, arg),
+ format!("{to_ty}::from_bits({arg})"),
Applicability::Unspecified,
);
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
index 52d193d11..009d5a7c8 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_num_to_bytes.rs
@@ -31,13 +31,13 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_NUM_TO_BYTES,
e.span,
- &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+ &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
|diag| {
let arg = sugg::Sugg::hir(cx, arg, "..");
diag.span_suggestion(
e.span,
"consider using `to_ne_bytes()`",
- format!("{}.to_ne_bytes()", arg),
+ format!("{arg}.to_ne_bytes()"),
Applicability::Unspecified,
);
},
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 5eb03275b..12d0b866e 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
@@ -25,10 +25,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_PTR_TO_REF,
e.span,
- &format!(
- "transmute from a pointer type (`{}`) to a reference type (`{}`)",
- from_ty, to_ty
- ),
+ &format!("transmute from a pointer type (`{from_ty}`) to a reference type (`{to_ty}`)"),
|diag| {
let arg = sugg::Sugg::hir(cx, arg, "..");
let (deref, cast) = if *mutbl == Mutability::Mut {
@@ -41,26 +38,25 @@ pub(super) fn check<'tcx>(
let sugg = if let Some(ty) = get_explicit_type(path) {
let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app);
if meets_msrv(msrv, msrvs::POINTER_CAST) {
- format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), ty_snip)
+ format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par())
} else if from_ptr_ty.has_erased_regions() {
- sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, ty_snip)))
- .to_string()
+ sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string()
} else {
- sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, ty_snip))).to_string()
+ sugg::make_unop(deref, arg.as_ty(format!("{cast} {ty_snip}"))).to_string()
}
} else if from_ptr_ty.ty == *to_ref_ty {
if from_ptr_ty.has_erased_regions() {
if meets_msrv(msrv, msrvs::POINTER_CAST) {
- format!("{}{}.cast::<{}>()", deref, arg.maybe_par(), to_ref_ty)
+ format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par())
} else {
- sugg::make_unop(deref, arg.as_ty(format!("{} () as {} {}", cast, cast, to_ref_ty)))
+ sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}")))
.to_string()
}
} else {
sugg::make_unop(deref, arg).to_string()
}
} else {
- sugg::make_unop(deref, arg.as_ty(format!("{} {}", cast, to_ref_ty))).to_string()
+ sugg::make_unop(deref, arg.as_ty(format!("{cast} {to_ref_ty}"))).to_string()
};
diag.span_suggestion(e.span, "try", sugg, app);
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 707a11d36..afb7f2e13 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
@@ -38,7 +38,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_BYTES_TO_STR,
e.span,
- &format!("transmute from a `{}` to a `{}`", from_ty, to_ty),
+ &format!("transmute from a `{from_ty}` to a `{to_ty}`"),
"consider using",
if const_context {
format!("std::str::from_utf8_unchecked{postfix}({snippet})")
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 b6d7d9f5b..3d4bbbf64 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
@@ -3,9 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_c_void;
use rustc_hir::Expr;
use rustc_lint::LateContext;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, IntTy, Ty, TypeAndMut, UintTy};
-use rustc_span::DUMMY_SP;
#[expect(clippy::too_many_lines)]
pub(super) fn check<'tcx>(
@@ -28,24 +27,32 @@ pub(super) fn check<'tcx>(
// `Repr(C)` <-> unordered type.
// If the first field of the `Repr(C)` type matches then the transmute is ok
- (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::UnorderedFields(to_sub_ty))
- | (ReducedTy::UnorderedFields(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty))) => {
+ (
+ ReducedTy::OrderedFields(_, Some(from_sub_ty)),
+ ReducedTy::UnorderedFields(to_sub_ty),
+ )
+ | (
+ ReducedTy::UnorderedFields(from_sub_ty),
+ ReducedTy::OrderedFields(_, Some(to_sub_ty)),
+ ) => {
from_ty = from_sub_ty;
to_ty = to_sub_ty;
continue;
- },
- (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty)) if reduced_tys.to_fat_ptr => {
+ }
+ (ReducedTy::OrderedFields(_, Some(from_sub_ty)), ReducedTy::Other(to_sub_ty))
+ if reduced_tys.to_fat_ptr =>
+ {
from_ty = from_sub_ty;
to_ty = to_sub_ty;
continue;
- },
+ }
(ReducedTy::Other(from_sub_ty), ReducedTy::OrderedFields(_, Some(to_sub_ty)))
if reduced_tys.from_fat_ptr =>
{
from_ty = from_sub_ty;
to_ty = to_sub_ty;
continue;
- },
+ }
// ptr <-> ptr
(ReducedTy::Other(from_sub_ty), ReducedTy::Other(to_sub_ty))
@@ -55,19 +62,19 @@ pub(super) fn check<'tcx>(
from_ty = from_sub_ty;
to_ty = to_sub_ty;
continue;
- },
+ }
// fat ptr <-> (*size, *size)
(ReducedTy::Other(_), ReducedTy::UnorderedFields(to_ty))
if reduced_tys.from_fat_ptr && is_size_pair(to_ty) =>
{
return false;
- },
+ }
(ReducedTy::UnorderedFields(from_ty), ReducedTy::Other(_))
if reduced_tys.to_fat_ptr && is_size_pair(from_ty) =>
{
return false;
- },
+ }
// fat ptr -> some struct | some struct -> fat ptr
(ReducedTy::Other(_), _) if reduced_tys.from_fat_ptr => {
@@ -75,31 +82,37 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+ &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| {
if from_ty_orig.peel_refs() != from_ty.peel_refs() {
- diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+ diag.note(&format!(
+ "the contained type `{from_ty}` has an undefined layout"
+ ));
}
},
);
return true;
- },
+ }
(_, ReducedTy::Other(_)) if reduced_tys.to_fat_ptr => {
span_lint_and_then(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute to `{}` which has an undefined layout", to_ty_orig),
+ &format!("transmute to `{to_ty_orig}` which has an undefined layout"),
|diag| {
if to_ty_orig.peel_refs() != to_ty.peel_refs() {
- diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+ diag.note(&format!(
+ "the contained type `{to_ty}` has an undefined layout"
+ ));
}
},
);
return true;
- },
+ }
- (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty)) if from_ty != to_ty => {
+ (ReducedTy::UnorderedFields(from_ty), ReducedTy::UnorderedFields(to_ty))
+ if from_ty != to_ty =>
+ {
let same_adt_did = if let (ty::Adt(from_def, from_subs), ty::Adt(to_def, to_subs))
= (from_ty.kind(), to_ty.kind())
&& from_def == to_def
@@ -116,8 +129,7 @@ pub(super) fn check<'tcx>(
TRANSMUTE_UNDEFINED_REPR,
e.span,
&format!(
- "transmute from `{}` to `{}`, both of which have an undefined layout",
- from_ty_orig, to_ty_orig
+ "transmute from `{from_ty_orig}` to `{to_ty_orig}`, both of which have an undefined layout"
),
|diag| {
if let Some(same_adt_did) = same_adt_did {
@@ -127,57 +139,73 @@ pub(super) fn check<'tcx>(
));
} else {
if from_ty_orig.peel_refs() != from_ty {
- diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+ diag.note(&format!(
+ "the contained type `{from_ty}` has an undefined layout"
+ ));
}
if to_ty_orig.peel_refs() != to_ty {
- diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+ diag.note(&format!(
+ "the contained type `{to_ty}` has an undefined layout"
+ ));
}
}
},
);
return true;
- },
+ }
(
ReducedTy::UnorderedFields(from_ty),
- ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
+ ReducedTy::Other(_)
+ | ReducedTy::OrderedFields(..)
+ | ReducedTy::TypeErasure { raw_ptr_only: true },
) => {
span_lint_and_then(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute from `{}` which has an undefined layout", from_ty_orig),
+ &format!("transmute from `{from_ty_orig}` which has an undefined layout"),
|diag| {
if from_ty_orig.peel_refs() != from_ty {
- diag.note(&format!("the contained type `{}` has an undefined layout", from_ty));
+ diag.note(&format!(
+ "the contained type `{from_ty}` has an undefined layout"
+ ));
}
},
);
return true;
- },
+ }
(
- ReducedTy::Other(_) | ReducedTy::OrderedFields(..) | ReducedTy::TypeErasure { raw_ptr_only: true },
+ ReducedTy::Other(_)
+ | ReducedTy::OrderedFields(..)
+ | ReducedTy::TypeErasure { raw_ptr_only: true },
ReducedTy::UnorderedFields(to_ty),
) => {
span_lint_and_then(
cx,
TRANSMUTE_UNDEFINED_REPR,
e.span,
- &format!("transmute into `{}` which has an undefined layout", to_ty_orig),
+ &format!("transmute into `{to_ty_orig}` which has an undefined layout"),
|diag| {
if to_ty_orig.peel_refs() != to_ty {
- diag.note(&format!("the contained type `{}` has an undefined layout", to_ty));
+ diag.note(&format!(
+ "the contained type `{to_ty}` has an undefined layout"
+ ));
}
},
);
return true;
- },
+ }
(
- ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
- ReducedTy::OrderedFields(..) | ReducedTy::Other(_) | ReducedTy::TypeErasure { raw_ptr_only: true },
+ ReducedTy::OrderedFields(..)
+ | ReducedTy::Other(_)
+ | ReducedTy::TypeErasure { raw_ptr_only: true },
+ ReducedTy::OrderedFields(..)
+ | ReducedTy::Other(_)
+ | ReducedTy::TypeErasure { raw_ptr_only: true },
)
| (ReducedTy::UnorderedFields(_), ReducedTy::UnorderedFields(_)) => {
break;
- },
+ }
}
}
@@ -195,42 +223,38 @@ struct ReducedTys<'tcx> {
}
/// Remove references so long as both types are references.
-fn reduce_refs<'tcx>(cx: &LateContext<'tcx>, mut from_ty: Ty<'tcx>, mut to_ty: Ty<'tcx>) -> ReducedTys<'tcx> {
+fn reduce_refs<'tcx>(
+ cx: &LateContext<'tcx>,
+ mut from_ty: Ty<'tcx>,
+ mut to_ty: Ty<'tcx>,
+) -> ReducedTys<'tcx> {
let mut from_raw_ptr = false;
let mut to_raw_ptr = false;
- let (from_fat_ptr, to_fat_ptr) = loop {
- break match (from_ty.kind(), to_ty.kind()) {
- (
- &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
- &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
- ) => {
- from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
- from_ty = from_sub_ty;
- to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
- to_ty = to_sub_ty;
- continue;
- },
- (&(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })), _)
- if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
- {
- (true, false)
- },
- (_, &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })))
- if !unsized_ty.is_sized(cx.tcx.at(DUMMY_SP), cx.param_env) =>
- {
- (false, true)
- },
- _ => (false, false),
+ let (from_fat_ptr, to_fat_ptr) =
+ loop {
+ break match (from_ty.kind(), to_ty.kind()) {
+ (
+ &(ty::Ref(_, from_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: from_sub_ty, .. })),
+ &(ty::Ref(_, to_sub_ty, _) | ty::RawPtr(TypeAndMut { ty: to_sub_ty, .. })),
+ ) => {
+ from_raw_ptr = matches!(*from_ty.kind(), ty::RawPtr(_));
+ from_ty = from_sub_ty;
+ to_raw_ptr = matches!(*to_ty.kind(), ty::RawPtr(_));
+ to_ty = to_sub_ty;
+ continue;
+ }
+ (
+ &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
+ _,
+ ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (true, false),
+ (
+ _,
+ &(ty::Ref(_, unsized_ty, _) | ty::RawPtr(TypeAndMut { ty: unsized_ty, .. })),
+ ) if !unsized_ty.is_sized(cx.tcx, cx.param_env) => (false, true),
+ _ => (false, false),
+ };
};
- };
- ReducedTys {
- from_ty,
- to_ty,
- from_raw_ptr,
- to_raw_ptr,
- from_fat_ptr,
- to_fat_ptr,
- }
+ ReducedTys { from_ty, to_ty, from_raw_ptr, to_raw_ptr, from_fat_ptr, to_fat_ptr }
}
enum ReducedTy<'tcx> {
@@ -253,11 +277,11 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
return match *ty.kind() {
ty::Array(sub_ty, _) if matches!(sub_ty.kind(), ty::Int(_) | ty::Uint(_)) => {
ReducedTy::TypeErasure { raw_ptr_only: false }
- },
+ }
ty::Array(sub_ty, _) | ty::Slice(sub_ty) => {
ty = sub_ty;
continue;
- },
+ }
ty::Tuple(args) if args.is_empty() => ReducedTy::TypeErasure { raw_ptr_only: false },
ty::Tuple(args) => {
let mut iter = args.iter();
@@ -269,7 +293,7 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
continue;
}
ReducedTy::UnorderedFields(ty)
- },
+ }
ty::Adt(def, substs) if def.is_struct() => {
let mut iter = def
.non_enum_variant()
@@ -288,10 +312,12 @@ fn reduce_ty<'tcx>(cx: &LateContext<'tcx>, mut ty: Ty<'tcx>) -> ReducedTy<'tcx>
} else {
ReducedTy::UnorderedFields(ty)
}
- },
- ty::Adt(def, _) if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) => {
+ }
+ ty::Adt(def, _)
+ if def.is_enum() && (def.variants().is_empty() || is_c_void(cx, ty)) =>
+ {
ReducedTy::TypeErasure { raw_ptr_only: false }
- },
+ }
// TODO: Check if the conversion to or from at least one of a union's fields is valid.
ty::Adt(def, _) if def.is_union() => ReducedTy::TypeErasure { raw_ptr_only: false },
ty::Foreign(_) | ty::Param(_) => ReducedTy::TypeErasure { raw_ptr_only: false },
@@ -330,7 +356,11 @@ fn same_except_params<'tcx>(subs1: SubstsRef<'tcx>, subs2: SubstsRef<'tcx>) -> b
for (ty1, ty2) in subs1.types().zip(subs2.types()).filter(|(ty1, ty2)| ty1 != ty2) {
match (ty1.kind(), ty2.kind()) {
(ty::Param(_), _) | (_, ty::Param(_)) => (),
- (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2)) if adt1 == adt2 && same_except_params(subs1, subs2) => (),
+ (ty::Adt(adt1, subs1), ty::Adt(adt2, subs2))
+ if adt1 == adt2 && same_except_params(subs1, subs2) =>
+ {
+ ()
+ }
_ => return 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 626d7cd46..6b444922a 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
@@ -21,10 +21,7 @@ pub(super) fn check<'tcx>(
cx,
TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS,
e.span,
- &format!(
- "transmute from `{}` to `{}` which could be expressed as a pointer cast instead",
- from_ty, to_ty
- ),
+ &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();
diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
index d8e349af7..19ce5ae72 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/transmuting_null.rs
@@ -1,8 +1,6 @@
use clippy_utils::consts::{constant_context, Constant};
use clippy_utils::diagnostics::span_lint;
-use clippy_utils::is_path_diagnostic_item;
-use if_chain::if_chain;
-use rustc_ast::LitKind;
+use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
@@ -19,37 +17,28 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
// Catching transmute over constants that resolve to `null`.
let mut const_eval_context = constant_context(cx, cx.typeck_results());
- if_chain! {
- if let ExprKind::Path(ref _qpath) = arg.kind;
- if let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg);
- if x == 0;
- then {
- span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
- return true;
- }
+ if let ExprKind::Path(ref _qpath) = arg.kind &&
+ let Some(Constant::RawPtr(x)) = const_eval_context.expr(arg) &&
+ x == 0
+ {
+ span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+ return true;
}
// Catching:
// `std::mem::transmute(0 as *const i32)`
- if_chain! {
- if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind;
- if let ExprKind::Lit(ref lit) = inner_expr.kind;
- if let LitKind::Int(0, _) = lit.node;
- then {
- span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
- return true;
- }
+ if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind && is_integer_literal(inner_expr, 0) {
+ span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+ return true;
}
// Catching:
// `std::mem::transmute(std::ptr::null::<i32>())`
- if_chain! {
- if let ExprKind::Call(func1, []) = arg.kind;
- if is_path_diagnostic_item(cx, func1, sym::ptr_null);
- then {
- span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
- return true;
- }
+ if let ExprKind::Call(func1, []) = arg.kind &&
+ is_path_diagnostic_item(cx, func1, sym::ptr_null)
+ {
+ span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG);
+ return true;
}
// FIXME:
diff --git a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
index 831b0d450..b1445311b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/unsound_collection_transmute.rs
@@ -37,10 +37,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
cx,
UNSOUND_COLLECTION_TRANSMUTE,
e.span,
- &format!(
- "transmute from `{}` to `{}` with mismatched layout is unsound",
- from_ty, to_ty
- ),
+ &format!("transmute from `{from_ty}` to `{to_ty}` with mismatched layout is unsound"),
);
true
} else {
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 8122cd716..f919bbd5a 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(
cx,
USELESS_TRANSMUTE,
e.span,
- &format!("transmute from a type (`{}`) to itself", from_ty),
+ &format!("transmute from a type (`{from_ty}`) to itself"),
);
true
},
diff --git a/src/tools/clippy/clippy_lints/src/transmute/utils.rs b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
index 8bdadf244..641cdf5d3 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/utils.rs
@@ -1,8 +1,9 @@
use rustc_hir::Expr;
+use rustc_hir_typeck::{cast, FnCtxt, Inherited};
use rustc_lint::LateContext;
use rustc_middle::ty::{cast::CastKind, Ty};
use rustc_span::DUMMY_SP;
-use rustc_typeck::check::{cast::{self, CastCheckResult}, FnCtxt, Inherited};
+use rustc_hir as hir;
// check if the component types of the transmuted collection and the result have different ABI,
// size or alignment
@@ -42,10 +43,10 @@ pub(super) fn can_be_expressed_as_pointer_cast<'tcx>(
/// 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> {
let hir_id = e.hir_id;
- let local_def_id = hir_id.owner;
+ 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, hir_id);
// If we already have errors, we can't be sure we can pointer cast.
assert!(
@@ -53,10 +54,10 @@ fn check_cast<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty<'tcx>
"Newly created FnCtxt contained errors"
);
- if let CastCheckResult::Deferred(check) = cast::check_cast(
+ if let Ok(check) = cast::CastCheck::new(
&fn_ctxt, e, from_ty, to_ty,
// We won't show any error to the user, so we don't care what the span is here.
- DUMMY_SP, DUMMY_SP,
+ DUMMY_SP, DUMMY_SP, hir::Constness::NotConst,
) {
let res = check.do_check(&fn_ctxt);
diff --git a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
index 2118f3d69..d1965565b 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/wrong_transmute.rs
@@ -13,7 +13,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, from_ty: Ty
cx,
WRONG_TRANSMUTE,
e.span,
- &format!("transmute from a `{}` to a pointer", from_ty),
+ &format!("transmute from a `{from_ty}` to a pointer"),
);
true
},
diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
index 94945b2e1..9c6629958 100644
--- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs
@@ -49,15 +49,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, m
let inner_snippet = snippet(cx, inner.span, "..");
let suggestion = match &inner.kind {
TyKind::TraitObject(bounds, lt_bound, _) if bounds.len() > 1 || !lt_bound.is_elided() => {
- format!("&{}({})", ltopt, &inner_snippet)
+ format!("&{ltopt}({})", &inner_snippet)
},
TyKind::Path(qpath)
if get_bounds_if_impl_trait(cx, qpath, inner.hir_id)
.map_or(false, |bounds| bounds.len() > 1) =>
{
- format!("&{}({})", ltopt, &inner_snippet)
+ format!("&{ltopt}({})", &inner_snippet)
},
- _ => format!("&{}{}", ltopt, &inner_snippet),
+ _ => format!("&{ltopt}{}", &inner_snippet),
};
span_lint_and_sugg(
cx,
@@ -104,7 +104,7 @@ fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id:
if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
if synthetic;
- if let Some(generics) = cx.tcx.hir().get_generics(id.owner);
+ if let Some(generics) = cx.tcx.hir().get_generics(id.owner.def_id);
if let Some(pred) = generics.bounds_for_param(did.expect_local()).next();
then {
Some(pred.bounds)
diff --git a/src/tools/clippy/clippy_lints/src/types/box_collection.rs b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
index ba51404d2..08020ce66 100644
--- a/src/tools/clippy/clippy_lints/src/types/box_collection.rs
+++ b/src/tools/clippy/clippy_lints/src/types/box_collection.rs
@@ -16,7 +16,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
_ => "<..>",
};
- let box_content = format!("{outer}{generic}", outer = item_type);
+ let box_content = format!("{item_type}{generic}");
span_lint_and_help(
cx,
BOX_COLLECTION,
diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs
index 353a6f6b8..f6de87b05 100644
--- a/src/tools/clippy/clippy_lints/src/types/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/types/mod.rs
@@ -313,13 +313,13 @@ impl_lint_pass!(Types => [BOX_COLLECTION, VEC_BOX, OPTION_OPTION, LINKEDLIST, BO
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)) {
+ 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
};
- let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(id));
+ let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(id));
self.check_fn_decl(
cx,
@@ -333,7 +333,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
- let is_exported = cx.access_levels.is_exported(item.def_id);
+ let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
match item.kind {
ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => self.check_ty(
@@ -352,8 +352,10 @@ impl<'tcx> LateLintPass<'tcx> for Types {
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
match item.kind {
ImplItemKind::Const(ty, _) => {
- 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(item.hir_id()))
+ 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(item.hir_id()).def_id)
{
matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }))
} else {
@@ -372,12 +374,12 @@ impl<'tcx> LateLintPass<'tcx> for Types {
// Methods are covered by check_fn.
// Type aliases are ignored because oftentimes it's impossible to
// make type alias declaration in trait simpler, see #1013
- ImplItemKind::Fn(..) | ImplItemKind::TyAlias(..) => (),
+ ImplItemKind::Fn(..) | ImplItemKind::Type(..) => (),
}
}
fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) {
- let is_exported = cx.access_levels.is_exported(cx.tcx.hir().local_def_id(field.hir_id));
+ let is_exported = cx.effective_visibilities.is_exported(cx.tcx.hir().local_def_id(field.hir_id));
self.check_ty(
cx,
@@ -390,7 +392,7 @@ impl<'tcx> LateLintPass<'tcx> for Types {
}
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &TraitItem<'_>) {
- let is_exported = cx.access_levels.is_exported(item.def_id);
+ let is_exported = cx.effective_visibilities.is_exported(item.owner_id.def_id);
let context = CheckTyContext {
is_exported,
@@ -535,7 +537,7 @@ impl Types {
QPath::LangItem(..) => {},
}
},
- TyKind::Rptr(ref lt, ref mut_ty) => {
+ TyKind::Rptr(lt, ref mut_ty) => {
context.is_nested_call = true;
if !borrowed_box::check(cx, hir_ty, lt, mut_ty) {
self.check_ty(cx, mut_ty.ty, context);
diff --git a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
index 4d72a29e8..fa567b9b2 100644
--- a/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
+++ b/src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
@@ -9,6 +9,7 @@ use rustc_span::symbol::sym;
use super::RC_BUFFER;
pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
+ let app = Applicability::Unspecified;
if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
if let Some(alternate) = match_buffer_type(cx, qpath) {
span_lint_and_sugg(
@@ -17,8 +18,8 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
hir_ty.span,
"usage of `Rc<T>` when T is a buffer type",
"try",
- format!("Rc<{}>", alternate),
- Applicability::MachineApplicable,
+ format!("Rc<{alternate}>"),
+ app,
);
} else {
let Some(ty) = qpath_generic_tys(qpath).next() else { return false };
@@ -26,15 +27,12 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
return false;
}
- let qpath = match &ty.kind {
- TyKind::Path(qpath) => qpath,
- _ => return false,
- };
+ let TyKind::Path(qpath) = &ty.kind else { return false };
let inner_span = match qpath_generic_tys(qpath).next() {
Some(ty) => ty.span,
None => return false,
};
- let mut applicability = Applicability::MachineApplicable;
+ let mut applicability = app;
span_lint_and_sugg(
cx,
RC_BUFFER,
@@ -45,7 +43,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
"Rc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
- Applicability::MachineApplicable,
+ app,
);
return true;
}
@@ -57,23 +55,20 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
hir_ty.span,
"usage of `Arc<T>` when T is a buffer type",
"try",
- format!("Arc<{}>", alternate),
- Applicability::MachineApplicable,
+ format!("Arc<{alternate}>"),
+ app,
);
} else if let Some(ty) = qpath_generic_tys(qpath).next() {
let Some(id) = path_def_id(cx, ty) else { return false };
if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
return false;
}
- let qpath = match &ty.kind {
- TyKind::Path(qpath) => qpath,
- _ => return false,
- };
+ let TyKind::Path(qpath) = &ty.kind else { return false };
let inner_span = match qpath_generic_tys(qpath).next() {
Some(ty) => ty.span,
None => return false,
};
- let mut applicability = Applicability::MachineApplicable;
+ let mut applicability = app;
span_lint_and_sugg(
cx,
RC_BUFFER,
@@ -84,7 +79,7 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
"Arc<[{}]>",
snippet_with_applicability(cx, inner_span, "..", &mut applicability)
),
- Applicability::MachineApplicable,
+ app,
);
return true;
}
diff --git a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
index a1312fcda..2b964b64a 100644
--- a/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
+++ b/src/tools/clippy/clippy_lints/src/types/redundant_allocation.rs
@@ -3,13 +3,19 @@ use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::{path_def_id, qpath_generic_tys};
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_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
use super::{utils, REDUNDANT_ALLOCATION};
-pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ hir_ty: &hir::Ty<'_>,
+ qpath: &QPath<'_>,
+ def_id: DefId,
+) -> bool {
+ let mut applicability = Applicability::MaybeIncorrect;
let outer_sym = if Some(def_id) == cx.tcx.lang_items().owned_box() {
"Box"
} else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
@@ -21,19 +27,21 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
};
if let Some(span) = utils::match_borrows_parameter(cx, qpath) {
- let mut applicability = Applicability::MaybeIncorrect;
let generic_snippet = snippet_with_applicability(cx, span, "..", &mut applicability);
span_lint_and_then(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
- &format!("usage of `{}<{}>`", outer_sym, generic_snippet),
+ &format!("usage of `{outer_sym}<{generic_snippet}>`"),
|diag| {
- diag.span_suggestion(hir_ty.span, "try", format!("{}", generic_snippet), applicability);
+ diag.span_suggestion(
+ hir_ty.span,
+ "try",
+ format!("{generic_snippet}"),
+ applicability,
+ );
diag.note(&format!(
- "`{generic}` is already a pointer, `{outer}<{generic}>` allocates a pointer on the heap",
- outer = outer_sym,
- generic = generic_snippet
+ "`{generic_snippet}` is already a pointer, `{outer_sym}<{generic_snippet}>` allocates a pointer on the heap"
));
},
);
@@ -49,42 +57,37 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
_ => return false,
};
- let inner_qpath = match &ty.kind {
- TyKind::Path(inner_qpath) => inner_qpath,
- _ => return false,
+ let TyKind::Path(inner_qpath) = &ty.kind else {
+ return false
};
let inner_span = match qpath_generic_tys(inner_qpath).next() {
Some(ty) => {
// Reallocation of a fat pointer causes it to become thin. `hir_ty_to_ty` is safe to use
// here because `mod.rs` guarantees this lint is only run on types outside of bodies and
// is not run on locals.
- if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx.at(ty.span), cx.param_env) {
+ if !hir_ty_to_ty(cx.tcx, ty).is_sized(cx.tcx, cx.param_env) {
return false;
}
ty.span
- },
+ }
None => return false,
};
if inner_sym == outer_sym {
- let mut applicability = Applicability::MaybeIncorrect;
let generic_snippet = snippet_with_applicability(cx, inner_span, "..", &mut applicability);
span_lint_and_then(
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
- &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+ &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
|diag| {
diag.span_suggestion(
hir_ty.span,
"try",
- format!("{}<{}>", outer_sym, generic_snippet),
+ format!("{outer_sym}<{generic_snippet}>"),
applicability,
);
diag.note(&format!(
- "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
- outer = outer_sym,
- inner = inner_sym,
- generic = generic_snippet
+ "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
));
},
);
@@ -94,19 +97,13 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
cx,
REDUNDANT_ALLOCATION,
hir_ty.span,
- &format!("usage of `{}<{}<{}>>`", outer_sym, inner_sym, generic_snippet),
+ &format!("usage of `{outer_sym}<{inner_sym}<{generic_snippet}>>`"),
|diag| {
diag.note(&format!(
- "`{inner}<{generic}>` is already on the heap, `{outer}<{inner}<{generic}>>` makes an extra allocation",
- outer = outer_sym,
- inner = inner_sym,
- generic = generic_snippet
+ "`{inner_sym}<{generic_snippet}>` is already on the heap, `{outer_sym}<{inner_sym}<{generic_snippet}>>` makes an extra allocation"
));
diag.help(&format!(
- "consider using just `{outer}<{generic}>` or `{inner}<{generic}>`",
- outer = outer_sym,
- inner = inner_sym,
- generic = generic_snippet
+ "consider using just `{outer_sym}<{generic_snippet}>` or `{inner_sym}<{generic_snippet}>`"
));
},
);
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 b2f536ca7..9ad2cb853 100644
--- a/src/tools/clippy/clippy_lints/src/types/vec_box.rs
+++ b/src/tools/clippy/clippy_lints/src/types/vec_box.rs
@@ -4,11 +4,11 @@ use clippy_utils::source::snippet;
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, def_id::DefId, GenericArg, QPath, TyKind};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::LateContext;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::TypeVisitable;
use rustc_span::symbol::sym;
-use rustc_typeck::hir_ty_to_ty;
use super::VEC_BOX;
@@ -40,7 +40,7 @@ pub(super) fn check(
});
let ty_ty = hir_ty_to_ty(cx.tcx, boxed_ty);
if !ty_ty.has_escaping_bound_vars();
- if ty_ty.is_sized(cx.tcx.at(ty.span), cx.param_env);
+ if ty_ty.is_sized(cx.tcx, cx.param_env);
if let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes());
if ty_ty_size <= box_size_threshold;
then {
diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
index 3f99bd3f3..1ab0162a8 100644
--- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs
+++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
use clippy_utils::higher::{get_vec_init_kind, VecInitKind};
use clippy_utils::ty::{is_type_diagnostic_item, is_uninit_value_valid_for_ty};
-use clippy_utils::{is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
+use clippy_utils::{is_integer_literal, is_lint_allowed, path_to_local_id, peel_hir_expr_while, SpanlessEq};
use rustc_hir::{Block, Expr, ExprKind, HirId, PatKind, PathSegment, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
@@ -211,9 +211,12 @@ fn extract_set_len_self<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Opt
}
});
match expr.kind {
- ExprKind::MethodCall(path, self_expr, [_], _) => {
+ ExprKind::MethodCall(path, self_expr, [arg], _) => {
let self_type = cx.typeck_results().expr_ty(self_expr).peel_refs();
- if is_type_diagnostic_item(cx, self_type, sym::Vec) && path.ident.name.as_str() == "set_len" {
+ if is_type_diagnostic_item(cx, self_type, sym::Vec)
+ && path.ident.name.as_str() == "set_len"
+ && !is_integer_literal(arg, 0)
+ {
Some((self_expr, expr.span))
} else {
None
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 c0a4f3fba..130728862 100644
--- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs
@@ -1,5 +1,4 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::{get_trait_def_id, paths};
use if_chain::if_chain;
use rustc_hir::def_id::DefId;
use rustc_hir::{Closure, Expr, ExprKind, StmtKind};
@@ -7,7 +6,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::{GenericPredicates, PredicateKind, ProjectionPredicate, TraitPredicate};
use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::{BytePos, Span};
+use rustc_span::{sym, BytePos, Span};
declare_clippy_lint! {
/// ### What it does
@@ -80,7 +79,7 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
let fn_sig = cx.tcx.fn_sig(def_id);
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, get_trait_def_id(cx, &paths::ORD));
+ let ord_preds = get_trait_predicates_for_trait_id(cx, generics, cx.tcx.get_diagnostic_item(sym::Ord));
let partial_ord_preds =
get_trait_predicates_for_trait_id(cx, generics, cx.tcx.lang_items().partial_ord_trait());
// Trying to call erase_late_bound_regions on fn_sig.inputs() gives the following error
@@ -99,11 +98,15 @@ fn get_args_to_check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Ve
if trait_pred.self_ty() == inp;
if let Some(return_ty_pred) = get_projection_pred(cx, generics, *trait_pred);
then {
- if ord_preds.iter().any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty()) {
+ if ord_preds
+ .iter()
+ .any(|ord| Some(ord.self_ty()) == return_ty_pred.term.ty())
+ {
args_to_check.push((i, "Ord".to_string()));
- } else if partial_ord_preds.iter().any(|pord| {
- pord.self_ty() == return_ty_pred.term.ty().unwrap()
- }) {
+ } else if partial_ord_preds
+ .iter()
+ .any(|pord| pord.self_ty() == return_ty_pred.term.ty().unwrap())
+ {
args_to_check.push((i, "PartialOrd".to_string()));
}
}
@@ -157,8 +160,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
span,
&format!(
"this closure returns \
- the unit type which also implements {}",
- trait_name
+ the unit type which also implements {trait_name}"
),
);
},
@@ -169,8 +171,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitReturnExpectingOrd {
span,
&format!(
"this closure returns \
- the unit type which also implements {}",
- trait_name
+ the unit type which also implements {trait_name}"
),
Some(last_semi),
"probably caused by this trailing semicolon",
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
index a6f777abc..f6d3fb00f 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs
@@ -74,7 +74,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
cx,
UNIT_ARG,
expr.span,
- &format!("passing {}unit value{} to a function", singular, plural),
+ &format!("passing {singular}unit value{plural} to a function"),
|db| {
let mut or = "";
args_to_recover
@@ -129,7 +129,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
if arg_snippets_without_empty_blocks.is_empty() {
db.multipart_suggestion(
- &format!("use {}unit literal{} instead", singular, plural),
+ &format!("use {singular}unit literal{plural} instead"),
args_to_recover
.iter()
.map(|arg| (arg.span, "()".to_string()))
@@ -143,8 +143,7 @@ fn lint_unit_args(cx: &LateContext<'_>, expr: &Expr<'_>, args_to_recover: &[&Exp
db.span_suggestion(
expr.span,
&format!(
- "{}move the expression{} in front of the call and replace {} with the unit literal `()`",
- or, empty_or_s, it_or_them
+ "{or}move the expression{empty_or_s} in front of the call and replace {it_or_them} with the unit literal `()`"
),
sugg,
applicability,
diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
index 1dd8895eb..226495dcb 100644
--- a/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
+++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_cmp.rs
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
cx,
UNIT_CMP,
macro_call.span,
- &format!("`{}` of unit values detected. This will always {}", macro_name, result),
+ &format!("`{macro_name}` of unit values detected. This will always {result}"),
);
}
return;
@@ -40,9 +40,8 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
UNIT_CMP,
expr.span,
&format!(
- "{}-comparison of unit values detected. This will always be {}",
- op.as_str(),
- result
+ "{}-comparison of unit values detected. This will always be {result}",
+ op.as_str()
),
);
}
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 8a4f4c0ad..016aacbf9 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
@@ -3,7 +3,7 @@ use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
+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};
@@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
);
} else {
if_chain! {
- if match_def_path(cx, fun_def_id, &paths::FROM_FROM);
+ if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(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_self_imports.rs b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
index 839a4bdab..bc0dd263d 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_self_imports.rs
@@ -57,7 +57,7 @@ impl EarlyLintPass for UnnecessarySelfImports {
format!(
"{}{};",
last_segment.ident,
- if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {}", alias) } else { String::new() },
+ if let UseTreeKind::Simple(Some(alias), ..) = self_tree.kind { format!(" as {alias}") } else { String::new() },
),
Applicability::MaybeIncorrect,
);
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
index 2c40827db..60b46854b 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::snippet;
-use clippy_utils::{contains_return, is_lang_ctor, return_ty, visitors::find_all_ret_expressions};
+use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty, visitors::find_all_ret_expressions};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::intravisit::FnKind;
@@ -83,7 +83,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
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.access_levels.is_exported(def_id) {
+ if self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(def_id) {
return;
}
},
@@ -120,9 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
if !ret_expr.span.from_expansion();
// Check if a function call.
if let ExprKind::Call(func, [arg]) = ret_expr.kind;
- // Check if OPTION_SOME or RESULT_OK, depending on return type.
- if let ExprKind::Path(qpath) = &func.kind;
- if is_lang_ctor(cx, qpath, lang_item);
+ if is_res_lang_ctor(cx, path_res(cx, func), lang_item);
// Make sure the function argument does not contain a return expression.
if !contains_return(arg);
then {
@@ -153,11 +151,8 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
)
} else {
(
- format!(
- "this function's return value is unnecessarily wrapped by `{}`",
- return_type_label
- ),
- format!("remove `{}` from the return type...", return_type_label),
+ format!("this function's return value is unnecessarily wrapped by `{return_type_label}`"),
+ format!("remove `{return_type_label}` from the return type..."),
inner_type.to_string(),
"...and then change returning expressions",
)
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 fb73c3866..b305dae76 100644
--- a/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
@@ -163,9 +163,8 @@ fn unnest_or_patterns(pat: &mut P<Pat>) -> bool {
noop_visit_pat(p, self);
// Don't have an or-pattern? Just quit early on.
- let alternatives = match &mut p.kind {
- Or(ps) => ps,
- _ => return,
+ let Or(alternatives) = &mut p.kind else {
+ return
};
// Collapse or-patterns directly nested in or-patterns.
diff --git a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
index 64f7a055c..32cd46812 100644
--- a/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/clippy_lints/src/unsafe_removed_from_name.rs
@@ -65,10 +65,7 @@ fn unsafe_to_safe_check(old_name: Ident, new_name: Ident, cx: &EarlyContext<'_>,
cx,
UNSAFE_REMOVED_FROM_NAME,
span,
- &format!(
- "removed `unsafe` from the name of `{}` in use as `{}`",
- old_str, new_str
- ),
+ &format!("removed `unsafe` from the name of `{old_str}` in use as `{new_str}`"),
);
}
}
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 b38d71784..92053cec5 100644
--- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs
@@ -1,8 +1,9 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
-use clippy_utils::{is_try, match_trait_method, paths};
+use clippy_utils::{is_trait_method, is_try, match_trait_method, paths};
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::sym;
declare_clippy_lint! {
/// ### What it does
@@ -46,9 +47,8 @@ declare_lint_pass!(UnusedIoAmount => [UNUSED_IO_AMOUNT]);
impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount {
fn check_stmt(&mut self, cx: &LateContext<'_>, s: &hir::Stmt<'_>) {
- let expr = match s.kind {
- hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr,
- _ => return,
+ let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = s.kind else {
+ return
};
match expr.kind {
@@ -116,13 +116,13 @@ fn check_method_call(cx: &LateContext<'_>, call: &hir::Expr<'_>, expr: &hir::Exp
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCREADEXT)
|| match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCREADEXT)
} else {
- match_trait_method(cx, call, &paths::IO_READ)
+ is_trait_method(cx, call, sym::IoRead)
};
let write_trait = if is_await {
match_trait_method(cx, call, &paths::FUTURES_IO_ASYNCWRITEEXT)
|| match_trait_method(cx, call, &paths::TOKIO_IO_ASYNCWRITEEXT)
} else {
- match_trait_method(cx, call, &paths::IO_WRITE)
+ is_trait_method(cx, call, sym::IoWrite)
};
match (read_trait, write_trait, symbol, is_await) {
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index cc8656435..f1cebf0f9 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -6,6 +6,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
@@ -109,8 +110,14 @@ impl<'a, 'tcx> PeekableVisitor<'a, 'tcx> {
}
}
-impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
- fn visit_expr(&mut self, ex: &'_ Expr<'_>) {
+impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
+ type NestedFilter = OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+
+ fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
if self.found_peek_call {
return;
}
@@ -136,12 +143,11 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
return;
}
- if args.iter().any(|arg| {
- matches!(arg.kind, ExprKind::Path(_)) && arg_is_mut_peekable(self.cx, arg)
- }) {
+ if args.iter().any(|arg| arg_is_mut_peekable(self.cx, arg)) {
self.found_peek_call = true;
- return;
}
+
+ return;
},
// Catch anything taking a Peekable mutably
ExprKind::MethodCall(
@@ -190,21 +196,21 @@ impl<'tcx> Visitor<'_> for PeekableVisitor<'_, 'tcx> {
Node::Local(Local { init: Some(init), .. }) => {
if arg_is_mut_peekable(self.cx, init) {
self.found_peek_call = true;
- return;
}
- break;
+ return;
},
- Node::Stmt(stmt) => match stmt.kind {
- StmtKind::Expr(_) | StmtKind::Semi(_) => {},
- _ => {
- self.found_peek_call = true;
- return;
- },
+ Node::Stmt(stmt) => {
+ match stmt.kind {
+ StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true,
+ StmtKind::Expr(_) | StmtKind::Semi(_) => {},
+ }
+
+ return;
},
Node::Block(_) | Node::ExprField(_) => {},
_ => {
- break;
+ return;
},
}
}
diff --git a/src/tools/clippy/clippy_lints/src/unused_rounding.rs b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
index 72d8a4431..316493729 100644
--- a/src/tools/clippy/clippy_lints/src/unused_rounding.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_rounding.rs
@@ -30,11 +30,10 @@ declare_clippy_lint! {
declare_lint_pass!(UnusedRounding => [UNUSED_ROUNDING]);
fn is_useless_rounding(expr: &Expr) -> Option<(&str, String)> {
- if let ExprKind::MethodCall(name_ident, args, _) = &expr.kind
+ if let ExprKind::MethodCall(name_ident, receiver, _, _) = &expr.kind
&& let method_name = name_ident.ident.name.as_str()
&& (method_name == "ceil" || method_name == "round" || method_name == "floor")
- && !args.is_empty()
- && let ExprKind::Lit(spanned) = &args[0].kind
+ && let ExprKind::Lit(spanned) = &receiver.kind
&& let LitKind::Float(symbol, ty) = spanned.kind {
let f = symbol.as_str().parse::<f64>().unwrap();
let f_str = symbol.to_string() + if let LitFloatType::Suffixed(ty) = ty {
@@ -59,8 +58,8 @@ impl EarlyLintPass for UnusedRounding {
cx,
UNUSED_ROUNDING,
expr.span,
- &format!("used the `{}` method with a whole number float", method_name),
- &format!("remove the `{}` method call", method_name),
+ &format!("used the `{method_name}` method with a whole number float"),
+ &format!("remove the `{method_name}` method call"),
float,
Applicability::MachineApplicable,
);
diff --git a/src/tools/clippy/clippy_lints/src/unused_self.rs b/src/tools/clippy/clippy_lints/src/unused_self.rs
index 51c65d898..42bccc721 100644
--- a/src/tools/clippy/clippy_lints/src/unused_self.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_self.rs
@@ -54,14 +54,14 @@ impl<'tcx> LateLintPass<'tcx> for UnusedSelf {
if impl_item.span.from_expansion() {
return;
}
- let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id());
+ let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id()).def_id;
let parent_item = cx.tcx.hir().expect_item(parent);
- let assoc_item = cx.tcx.associated_item(impl_item.def_id);
+ let assoc_item = cx.tcx.associated_item(impl_item.owner_id);
if_chain! {
if let ItemKind::Impl(Impl { of_trait: None, .. }) = parent_item.kind;
if assoc_item.fn_has_self_parameter;
if let ImplItemKind::Fn(.., body_id) = &impl_item.kind;
- if !cx.access_levels.is_exported(impl_item.def_id) || !self.avoid_breaking_exported_api;
+ if !cx.effective_visibilities.is_exported(impl_item.owner_id.def_id) || !self.avoid_breaking_exported_api;
let body = cx.tcx.hir().body(*body_id);
if let [self_param, ..] = body.params;
if !is_local_used(cx, body, self_param.pat.hir_id);
diff --git a/src/tools/clippy/clippy_lints/src/unwrap.rs b/src/tools/clippy/clippy_lints/src/unwrap.rs
index 3ef265580..ea878043c 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap.rs
@@ -257,9 +257,8 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
expr.hir_id,
expr.span,
&format!(
- "called `{}` on `{}` after checking its variant with `{}`",
+ "called `{}` on `{unwrappable_variable_name}` after checking its variant with `{}`",
method_name.ident.name,
- unwrappable_variable_name,
unwrappable.check_name.ident.as_str(),
),
|diag| {
@@ -268,9 +267,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
unwrappable.check.span.with_lo(unwrappable.if_expr.span.lo()),
"try",
format!(
- "if let {} = {}",
- suggested_pattern,
- unwrappable_variable_name,
+ "if let {suggested_pattern} = {unwrappable_variable_name}",
),
// We don't track how the unwrapped value is used inside the
// block or suggest deleting the unwrap, so we can't offer a
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 46020adca..f3611d174 100644
--- a/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
+++ b/src/tools/clippy/clippy_lints/src/unwrap_in_result.rs
@@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::ty::is_type_diagnostic_item;
+use clippy_utils::visitors::for_each_expr;
use clippy_utils::{method_chain_args, return_ty};
+use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{Expr, ImplItemKind};
+use rustc_hir::ImplItemKind;
use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{sym, Span};
@@ -73,51 +73,37 @@ impl<'tcx> LateLintPass<'tcx> for UnwrapInResult {
}
}
-struct FindExpectUnwrap<'a, 'tcx> {
- lcx: &'a LateContext<'tcx>,
- typeck_results: &'tcx ty::TypeckResults<'tcx>,
- result: Vec<Span>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for FindExpectUnwrap<'a, 'tcx> {
- fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
- // check for `expect`
- if let Some(arglists) = method_chain_args(expr, &["expect"]) {
- let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
- if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
- || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
- {
- self.result.push(expr.span);
+fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
+ if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
+ let body = cx.tcx.hir().body(body_id);
+ let typeck = cx.tcx.typeck(impl_item.owner_id.def_id);
+ let mut result = Vec::new();
+ let _: Option<!> = for_each_expr(body.value, |e| {
+ // check for `expect`
+ if let Some(arglists) = method_chain_args(e, &["expect"]) {
+ let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs();
+ if is_type_diagnostic_item(cx, receiver_ty, sym::Option)
+ || is_type_diagnostic_item(cx, receiver_ty, sym::Result)
+ {
+ result.push(e.span);
+ }
}
- }
- // check for `unwrap`
- if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
- let receiver_ty = self.typeck_results.expr_ty(arglists[0].0).peel_refs();
- if is_type_diagnostic_item(self.lcx, receiver_ty, sym::Option)
- || is_type_diagnostic_item(self.lcx, receiver_ty, sym::Result)
- {
- self.result.push(expr.span);
+ // check for `unwrap`
+ if let Some(arglists) = method_chain_args(e, &["unwrap"]) {
+ let receiver_ty = typeck.expr_ty(arglists[0].0).peel_refs();
+ if is_type_diagnostic_item(cx, receiver_ty, sym::Option)
+ || is_type_diagnostic_item(cx, receiver_ty, sym::Result)
+ {
+ result.push(e.span);
+ }
}
- }
- // and check sub-expressions
- intravisit::walk_expr(self, expr);
- }
-}
-
-fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tcx hir::ImplItem<'_>) {
- if let ImplItemKind::Fn(_, body_id) = impl_item.kind {
- let body = cx.tcx.hir().body(body_id);
- let mut fpu = FindExpectUnwrap {
- lcx: cx,
- typeck_results: cx.tcx.typeck(impl_item.def_id),
- result: Vec::new(),
- };
- fpu.visit_expr(body.value);
+ ControlFlow::Continue(())
+ });
// if we've found one, lint
- if !fpu.result.is_empty() {
+ if !result.is_empty() {
span_lint_and_then(
cx,
UNWRAP_IN_RESULT,
@@ -125,7 +111,7 @@ fn lint_impl_body<'tcx>(cx: &LateContext<'tcx>, impl_span: Span, impl_item: &'tc
"used unwrap or expect in a function that returns result or option",
move |diag| {
diag.help("unwrap and expect should not be used in a function that returns result or option");
- diag.span_note(fpu.result, "potential non-recoverable error(s)");
+ diag.span_note(result, "potential non-recoverable error(s)");
},
);
}
diff --git a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
index 02bf09ed5..1d2d3eb12 100644
--- a/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
+++ b/src/tools/clippy/clippy_lints/src/upper_case_acronyms.rs
@@ -93,7 +93,7 @@ fn check_ident(cx: &LateContext<'_>, ident: &Ident, be_aggressive: bool) {
cx,
UPPER_CASE_ACRONYMS,
span,
- &format!("name `{}` contains a capitalized acronym", ident),
+ &format!("name `{ident}` contains a capitalized acronym"),
"consider making the acronym lowercase, except the initial letter",
corrected,
Applicability::MaybeIncorrect,
@@ -105,7 +105,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
fn check_item(&mut self, cx: &LateContext<'_>, it: &Item<'_>) {
// do not lint public items or in macros
if in_external_macro(cx.sess(), it.span)
- || (self.avoid_breaking_exported_api && cx.access_levels.is_exported(it.def_id))
+ || (self.avoid_breaking_exported_api && cx.effective_visibilities.is_exported(it.owner_id.def_id))
{
return;
}
@@ -114,6 +114,7 @@ impl LateLintPass<'_> for UpperCaseAcronyms {
check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
},
ItemKind::Enum(ref enumdef, _) => {
+ check_ident(cx, &it.ident, self.upper_case_acronyms_aggressive);
// check enum variants separately because again we only want to lint on private enums and
// the fn check_variant does not know about the vis of the enum of its variants
enumdef
diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs
index 486ea5e5c..c6cdf3f85 100644
--- a/src/tools/clippy/clippy_lints/src/use_self.rs
+++ b/src/tools/clippy/clippy_lints/src/use_self.rs
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::ty::same_type_and_consts;
-use clippy_utils::{meets_msrv, msrvs};
+use clippy_utils::{is_from_proc_macro, meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@@ -12,11 +12,11 @@ use rustc_hir::{
Expr, ExprKind, FnRetTy, FnSig, GenericArg, HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath,
TyKind,
};
+use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
@@ -87,7 +87,7 @@ impl_lint_pass!(UseSelf => [USE_SELF]);
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
impl<'tcx> LateLintPass<'tcx> for UseSelf {
- fn check_item(&mut self, _cx: &LateContext<'_>, item: &Item<'_>) {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) {
if matches!(item.kind, ItemKind::OpaqueTy(_)) {
// skip over `ItemKind::OpaqueTy` in order to lint `foo() -> impl <..>`
return;
@@ -103,9 +103,10 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
if parameters.as_ref().map_or(true, |params| {
!params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))
});
+ if !is_from_proc_macro(cx, item); // expensive, should be last check
then {
StackItem::Check {
- impl_id: item.def_id,
+ impl_id: item.owner_id.def_id,
in_body: 0,
types_to_skip: std::iter::once(self_ty.hir_id).collect(),
}
@@ -142,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
// trait, not in the impl of the trait.
let trait_method = cx
.tcx
- .associated_item(impl_item.def_id)
+ .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);
@@ -205,7 +206,12 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
ref types_to_skip,
}) = self.stack.last();
if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind;
- if !matches!(path.res, Res::SelfTy { .. } | Res::Def(DefKind::TyParam, _));
+ if !matches!(
+ path.res,
+ Res::SelfTyParam { .. }
+ | Res::SelfTyAlias { .. }
+ | Res::Def(DefKind::TyParam, _)
+ );
if !types_to_skip.contains(&hir_ty.hir_id);
let ty = if in_body > 0 {
cx.typeck_results().node_type(hir_ty.hir_id)
@@ -213,9 +219,6 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
hir_ty_to_ty(cx.tcx, hir_ty)
};
if same_type_and_consts(ty, cx.tcx.type_of(impl_id));
- let hir = cx.tcx.hir();
- // prevents false positive on `#[derive(serde::Deserialize)]`
- if !hir.span(hir.get_parent_node(hir_ty.hir_id)).in_derive_expansion();
then {
span_lint(cx, hir_ty.span);
}
@@ -232,7 +235,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
}
match expr.kind {
ExprKind::Struct(QPath::Resolved(_, path), ..) => match path.res {
- Res::SelfTy { .. } => (),
+ Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => (),
Res::Def(DefKind::Variant, _) => lint_path_to_variant(cx, path),
_ => span_lint(cx, path.span),
},
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index f1b6463ad..1f69db1cb 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
+use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -55,9 +55,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
match e.kind {
ExprKind::Match(_, arms, MatchSource::TryDesugar) => {
- let e = match arms[0].body.kind {
- ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e)) => e,
- _ => return,
+ let (ExprKind::Ret(Some(e)) | ExprKind::Break(_, Some(e))) = arms[0].body.kind else {
+ return
};
if let ExprKind::Call(_, [arg, ..]) = e.kind {
self.try_desugar_arm.push(arg.hir_id);
@@ -74,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
cx,
USELESS_CONVERSION,
e.span,
- &format!("useless conversion to the same type: `{}`", b),
+ &format!("useless conversion to the same type: `{b}`"),
"consider removing `.into()`",
sugg,
Applicability::MachineApplicable, // snippet
@@ -97,7 +96,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
cx,
USELESS_CONVERSION,
e.span,
- &format!("useless conversion to the same type: `{}`", b),
+ &format!("useless conversion to the same type: `{b}`"),
"consider removing `.into_iter()`",
sugg,
Applicability::MachineApplicable, // snippet
@@ -118,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
cx,
USELESS_CONVERSION,
e.span,
- &format!("useless conversion to the same type: `{}`", b),
+ &format!("useless conversion to the same type: `{b}`"),
None,
"consider removing `.try_into()`",
);
@@ -146,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
cx,
USELESS_CONVERSION,
e.span,
- &format!("useless conversion to the same type: `{}`", b),
+ &format!("useless conversion to the same type: `{b}`"),
None,
&hint,
);
@@ -154,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
}
if_chain! {
- if match_def_path(cx, def_id, &paths::FROM_FROM);
+ if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(def_id);
if same_type_and_consts(a, b);
then {
@@ -165,7 +164,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
cx,
USELESS_CONVERSION,
e.span,
- &format!("useless conversion to the same type: `{}`", b),
+ &format!("useless conversion to the same type: `{b}`"),
&sugg_msg,
sugg.to_string(),
Applicability::MachineApplicable, // snippet
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 4003fff27..0c052d86e 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -12,6 +12,7 @@ use rustc_hir::{
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::symbol::{Ident, Symbol};
+use std::cell::Cell;
use std::fmt::{Display, Formatter, Write as _};
declare_clippy_lint! {
@@ -37,15 +38,13 @@ declare_clippy_lint! {
///
/// ```rust,ignore
/// // ./tests/ui/new_lint.stdout
- /// if_chain! {
- /// if let ExprKind::If(ref cond, ref then, None) = item.kind,
- /// if let ExprKind::Binary(BinOp::Eq, ref left, ref right) = cond.kind,
- /// if let ExprKind::Path(ref path) = left.kind,
- /// if let ExprKind::Lit(ref lit) = right.kind,
- /// if let LitKind::Int(42, _) = lit.node,
- /// then {
- /// // report your lint here
- /// }
+ /// if ExprKind::If(ref cond, ref then, None) = item.kind
+ /// && let ExprKind::Binary(BinOp::Eq, ref left, ref right) = cond.kind
+ /// && let ExprKind::Path(ref path) = left.kind
+ /// && let ExprKind::Lit(ref lit) = right.kind
+ /// && let LitKind::Int(42, _) = lit.node
+ /// {
+ /// // report your lint here
/// }
/// ```
pub LINT_AUTHOR,
@@ -91,15 +90,16 @@ macro_rules! field {
};
}
-fn prelude() {
- println!("if_chain! {{");
-}
-
-fn done() {
- println!(" then {{");
- println!(" // report your lint here");
- println!(" }}");
- println!("}}");
+/// Print a condition of a let chain, `chain!(self, "let Some(x) = y")` will print
+/// `if let Some(x) = y` on the first call and ` && let Some(x) = y` thereafter
+macro_rules! chain {
+ ($self:ident, $($t:tt)*) => {
+ if $self.first.take() {
+ println!("if {}", format_args!($($t)*));
+ } else {
+ println!(" && {}", format_args!($($t)*));
+ }
+ }
}
impl<'tcx> LateLintPass<'tcx> for Author {
@@ -140,7 +140,7 @@ impl<'tcx> LateLintPass<'tcx> for Author {
fn check_item(cx: &LateContext<'_>, hir_id: HirId) {
let hir = cx.tcx.hir();
- if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner()) {
+ if let Some(body_id) = hir.maybe_body_owned_by(hir_id.expect_owner().def_id) {
check_node(cx, hir_id, |v| {
v.expr(&v.bind("expr", hir.body(body_id).value));
});
@@ -149,9 +149,10 @@ fn check_item(cx: &LateContext<'_>, hir_id: HirId) {
fn check_node(cx: &LateContext<'_>, hir_id: HirId, f: impl Fn(&PrintVisitor<'_, '_>)) {
if has_attr(cx, hir_id) {
- prelude();
f(&PrintVisitor::new(cx));
- done();
+ println!("{{");
+ println!(" // report your lint here");
+ println!("}}");
}
}
@@ -195,7 +196,9 @@ struct PrintVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
/// Fields are the current index that needs to be appended to pattern
/// binding names
- ids: std::cell::Cell<FxHashMap<&'static str, u32>>,
+ ids: Cell<FxHashMap<&'static str, u32>>,
+ /// Currently at the first condition in the if chain
+ first: Cell<bool>,
}
#[allow(clippy::unused_self)]
@@ -203,7 +206,8 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn new(cx: &'a LateContext<'tcx>) -> Self {
Self {
cx,
- ids: std::cell::Cell::default(),
+ ids: Cell::default(),
+ first: Cell::new(true),
}
}
@@ -226,10 +230,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn option<T: Copy>(&self, option: &Binding<Option<T>>, name: &'static str, f: impl Fn(&Binding<T>)) {
match option.value {
- None => out!("if {option}.is_none();"),
+ None => chain!(self, "{option}.is_none()"),
Some(value) => {
let value = &self.bind(name, value);
- out!("if let Some({value}) = {option};");
+ chain!(self, "let Some({value}) = {option}");
f(value);
},
}
@@ -237,9 +241,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn slice<T>(&self, slice: &Binding<&[T]>, f: impl Fn(&Binding<&T>)) {
if slice.value.is_empty() {
- out!("if {slice}.is_empty();");
+ chain!(self, "{slice}.is_empty()");
} else {
- out!("if {slice}.len() == {};", slice.value.len());
+ chain!(self, "{slice}.len() == {}", slice.value.len());
for (i, value) in slice.value.iter().enumerate() {
let name = format!("{slice}[{i}]");
f(&Binding { name, value });
@@ -254,23 +258,23 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}
fn ident(&self, ident: &Binding<Ident>) {
- out!("if {ident}.as_str() == {:?};", ident.value.as_str());
+ chain!(self, "{ident}.as_str() == {:?}", ident.value.as_str());
}
fn symbol(&self, symbol: &Binding<Symbol>) {
- out!("if {symbol}.as_str() == {:?};", symbol.value.as_str());
+ chain!(self, "{symbol}.as_str() == {:?}", symbol.value.as_str());
}
fn qpath(&self, qpath: &Binding<&QPath<'_>>) {
if let QPath::LangItem(lang_item, ..) = *qpath.value {
- out!("if matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _));");
+ chain!(self, "matches!({qpath}, QPath::LangItem(LangItem::{lang_item:?}, _))");
} else {
- out!("if match_qpath({qpath}, &[{}]);", path_to_string(qpath.value));
+ chain!(self, "match_qpath({qpath}, &[{}])", path_to_string(qpath.value));
}
}
fn lit(&self, lit: &Binding<&Lit>) {
- let kind = |kind| out!("if let LitKind::{kind} = {lit}.node;");
+ let kind = |kind| chain!(self, "let LitKind::{kind} = {lit}.node");
macro_rules! kind {
($($t:tt)*) => (kind(format_args!($($t)*)));
}
@@ -298,7 +302,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
LitKind::ByteStr(ref vec) => {
bind!(self, vec);
kind!("ByteStr(ref {vec})");
- out!("if let [{:?}] = **{vec};", vec.value);
+ chain!(self, "let [{:?}] = **{vec}", vec.value);
},
LitKind::Str(s, _) => {
bind!(self, s);
@@ -311,15 +315,15 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn arm(&self, arm: &Binding<&hir::Arm<'_>>) {
self.pat(field!(arm.pat));
match arm.value.guard {
- None => out!("if {arm}.guard.is_none();"),
+ None => chain!(self, "{arm}.guard.is_none()"),
Some(hir::Guard::If(expr)) => {
bind!(self, expr);
- out!("if let Some(Guard::If({expr})) = {arm}.guard;");
+ chain!(self, "let Some(Guard::If({expr})) = {arm}.guard");
self.expr(expr);
},
Some(hir::Guard::IfLet(let_expr)) => {
bind!(self, let_expr);
- out!("if let Some(Guard::IfLet({let_expr}) = {arm}.guard;");
+ chain!(self, "let Some(Guard::IfLet({let_expr}) = {arm}.guard");
self.pat(field!(let_expr.pat));
self.expr(field!(let_expr.init));
},
@@ -331,9 +335,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn expr(&self, expr: &Binding<&hir::Expr<'_>>) {
if let Some(higher::While { condition, body }) = higher::While::hir(expr.value) {
bind!(self, condition, body);
- out!(
- "if let Some(higher::While {{ condition: {condition}, body: {body} }}) \
- = higher::While::hir({expr});"
+ chain!(
+ self,
+ "let Some(higher::While {{ condition: {condition}, body: {body} }}) \
+ = higher::While::hir({expr})"
);
self.expr(condition);
self.expr(body);
@@ -347,9 +352,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}) = higher::WhileLet::hir(expr.value)
{
bind!(self, let_pat, let_expr, if_then);
- out!(
- "if let Some(higher::WhileLet {{ let_pat: {let_pat}, let_expr: {let_expr}, if_then: {if_then} }}) \
- = higher::WhileLet::hir({expr});"
+ chain!(
+ self,
+ "let Some(higher::WhileLet {{ let_pat: {let_pat}, let_expr: {let_expr}, if_then: {if_then} }}) \
+ = higher::WhileLet::hir({expr})"
);
self.pat(let_pat);
self.expr(let_expr);
@@ -359,9 +365,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
if let Some(higher::ForLoop { pat, arg, body, .. }) = higher::ForLoop::hir(expr.value) {
bind!(self, pat, arg, body);
- out!(
- "if let Some(higher::ForLoop {{ pat: {pat}, arg: {arg}, body: {body}, .. }}) \
- = higher::ForLoop::hir({expr});"
+ chain!(
+ self,
+ "let Some(higher::ForLoop {{ pat: {pat}, arg: {arg}, body: {body}, .. }}) \
+ = higher::ForLoop::hir({expr})"
);
self.pat(pat);
self.expr(arg);
@@ -369,7 +376,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
return;
}
- let kind = |kind| out!("if let ExprKind::{kind} = {expr}.kind;");
+ let kind = |kind| chain!(self, "let ExprKind::{kind} = {expr}.kind");
macro_rules! kind {
($($t:tt)*) => (kind(format_args!($($t)*)));
}
@@ -383,7 +390,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
// if it's a path
if let Some(TyKind::Path(ref qpath)) = let_expr.value.ty.as_ref().map(|ty| &ty.kind) {
bind!(self, qpath);
- out!("if let TyKind::Path(ref {qpath}) = {let_expr}.ty.kind;");
+ chain!(self, "let TyKind::Path(ref {qpath}) = {let_expr}.ty.kind");
self.qpath(qpath);
}
self.expr(field!(let_expr.init));
@@ -419,7 +426,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
ExprKind::Binary(op, left, right) => {
bind!(self, op, left, right);
kind!("Binary({op}, {left}, {right})");
- out!("if BinOpKind::{:?} == {op}.node;", op.value.node);
+ chain!(self, "BinOpKind::{:?} == {op}.node", op.value.node);
self.expr(left);
self.expr(right);
},
@@ -438,7 +445,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("Cast({expr}, {cast_ty})");
if let TyKind::Path(ref qpath) = cast_ty.value.kind {
bind!(self, qpath);
- out!("if let TyKind::Path(ref {qpath}) = {cast_ty}.kind;");
+ chain!(self, "let TyKind::Path(ref {qpath}) = {cast_ty}.kind");
self.qpath(qpath);
}
self.expr(expr);
@@ -485,7 +492,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
bind!(self, fn_decl, body_id);
kind!("Closure(CaptureBy::{capture_clause:?}, {fn_decl}, {body_id}, _, {movability})");
- out!("if let {ret_ty} = {fn_decl}.output;");
+ chain!(self, "let {ret_ty} = {fn_decl}.output");
self.body(body_id);
},
ExprKind::Yield(sub, source) => {
@@ -509,7 +516,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
ExprKind::AssignOp(op, target, value) => {
bind!(self, op, target, value);
kind!("AssignOp({op}, {target}, {value})");
- out!("if BinOpKind::{:?} == {op}.node;", op.value.node);
+ chain!(self, "BinOpKind::{:?} == {op}.node", op.value.node);
self.expr(target);
self.expr(value);
},
@@ -573,10 +580,10 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
kind!("Repeat({value}, {length})");
self.expr(value);
match length.value {
- ArrayLen::Infer(..) => out!("if let ArrayLen::Infer(..) = length;"),
+ ArrayLen::Infer(..) => chain!(self, "let ArrayLen::Infer(..) = length"),
ArrayLen::Body(anon_const) => {
bind!(self, anon_const);
- out!("if let ArrayLen::Body({anon_const}) = {length};");
+ chain!(self, "let ArrayLen::Body({anon_const}) = {length}");
self.body(field!(anon_const.body));
},
}
@@ -600,12 +607,12 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
fn body(&self, body_id: &Binding<hir::BodyId>) {
let expr = self.cx.tcx.hir().body(body_id.value).value;
bind!(self, expr);
- out!("let {expr} = &cx.tcx.hir().body({body_id}).value;");
+ chain!(self, "{expr} = &cx.tcx.hir().body({body_id}).value");
self.expr(expr);
}
fn pat(&self, pat: &Binding<&hir::Pat<'_>>) {
- let kind = |kind| out!("if let PatKind::{kind} = {pat}.kind;");
+ let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind");
macro_rules! kind {
($($t:tt)*) => (kind(format_args!($($t)*)));
}
@@ -688,7 +695,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
}
fn stmt(&self, stmt: &Binding<&hir::Stmt<'_>>) {
- let kind = |kind| out!("if let StmtKind::{kind} = {stmt}.kind;");
+ let kind = |kind| chain!(self, "let StmtKind::{kind} = {stmt}.kind");
macro_rules! kind {
($($t:tt)*) => (kind(format_args!($($t)*)));
}
@@ -739,7 +746,7 @@ fn path_to_string(path: &QPath<'_>) -> String {
*s += ", ";
write!(s, "{:?}", segment.ident.as_str()).unwrap();
},
- other => write!(s, "/* unimplemented: {:?}*/", other).unwrap(),
+ other => write!(s, "/* unimplemented: {other:?}*/").unwrap(),
},
QPath::LangItem(..) => panic!("path_to_string: called for lang item qpath"),
}
diff --git a/src/tools/clippy/clippy_lints/src/utils/conf.rs b/src/tools/clippy/clippy_lints/src/utils/conf.rs
index a8500beb2..668123e4d 100644
--- a/src/tools/clippy/clippy_lints/src/utils/conf.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/conf.rs
@@ -39,28 +39,28 @@ pub struct Rename {
pub rename: String,
}
-/// A single disallowed method, used by the `DISALLOWED_METHODS` lint.
#[derive(Clone, Debug, Deserialize)]
#[serde(untagged)]
-pub enum DisallowedMethod {
+pub enum DisallowedPath {
Simple(String),
WithReason { path: String, reason: Option<String> },
}
-impl DisallowedMethod {
+impl DisallowedPath {
pub fn path(&self) -> &str {
let (Self::Simple(path) | Self::WithReason { path, .. }) = self;
path
}
-}
-/// A single disallowed type, used by the `DISALLOWED_TYPES` lint.
-#[derive(Clone, Debug, Deserialize)]
-#[serde(untagged)]
-pub enum DisallowedType {
- Simple(String),
- WithReason { path: String, reason: Option<String> },
+ pub fn reason(&self) -> Option<&str> {
+ match self {
+ Self::WithReason {
+ reason: Some(reason), ..
+ } => Some(reason),
+ _ => None,
+ }
+ }
}
/// Conf with parse errors
@@ -213,7 +213,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.
+ /// 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.
///
/// The minimum rust version that the project supports
(msrv: Option<String> = None),
@@ -315,14 +315,18 @@ define_Conf! {
///
/// Whether to allow certain wildcard imports (prelude, super in tests).
(warn_on_all_wildcard_imports: bool = false),
+ /// Lint: DISALLOWED_MACROS.
+ ///
+ /// The list of disallowed macros, written as fully qualified paths.
+ (disallowed_macros: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_METHODS.
///
/// The list of disallowed methods, written as fully qualified paths.
- (disallowed_methods: Vec<crate::utils::conf::DisallowedMethod> = Vec::new()),
+ (disallowed_methods: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
/// Lint: DISALLOWED_TYPES.
///
/// The list of disallowed types, written as fully qualified paths.
- (disallowed_types: Vec<crate::utils::conf::DisallowedType> = Vec::new()),
+ (disallowed_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
/// Lint: UNREADABLE_LITERAL.
///
/// Should the fraction of a decimal be linted to include separators.
@@ -362,7 +366,7 @@ define_Conf! {
/// For example, `[_, _, _, e, ..]` is a slice pattern with 4 elements.
(max_suggested_slice_pattern_length: u64 = 3),
/// Lint: AWAIT_HOLDING_INVALID_TYPE
- (await_holding_invalid_types: Vec<crate::utils::conf::DisallowedType> = Vec::new()),
+ (await_holding_invalid_types: Vec<crate::utils::conf::DisallowedPath> = Vec::new()),
/// Lint: LARGE_INCLUDE_FILE.
///
/// The maximum size of a file included via `include_bytes!()` or `include_str!()`, in bytes
@@ -476,22 +480,19 @@ pub fn format_error(error: Box<dyn Error>) -> String {
let mut msg = String::from(prefix);
for row in 0..rows {
- write!(msg, "\n").unwrap();
+ writeln!(msg).unwrap();
for (column, column_width) in column_widths.iter().copied().enumerate() {
let index = column * rows + row;
let field = fields.get(index).copied().unwrap_or_default();
write!(
msg,
- "{:separator_width$}{:field_width$}",
- " ",
- field,
- separator_width = SEPARATOR_WIDTH,
- field_width = column_width
+ "{:SEPARATOR_WIDTH$}{field:column_width$}",
+ " "
)
.unwrap();
}
}
- write!(msg, "\n{}", suffix).unwrap();
+ write!(msg, "\n{suffix}").unwrap();
msg
} else {
s
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
index 17d9a0418..71f6c9909 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints.rs
@@ -1,1437 +1,12 @@
-use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
-use clippy_utils::consts::{constant_simple, Constant};
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::macros::root_macro_call_first_node;
-use clippy_utils::source::snippet;
-use clippy_utils::ty::match_type;
-use clippy_utils::{
- def_path_res, higher, is_else_clause, is_expn_of, is_expr_path_def_path, is_lint_allowed, match_def_path,
- method_calls, paths, peel_blocks_with_stmt, SpanlessEq,
-};
-use if_chain::if_chain;
-use rustc_ast as ast;
-use rustc_ast::ast::{Crate, ItemKind, LitKind, ModKind, NodeId};
-use rustc_ast::visit::FnKind;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::Applicability;
-use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::DefId;
-use rustc_hir::hir_id::CRATE_HIR_ID;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{
- BinOpKind, Block, Closure, Expr, ExprKind, HirId, Item, Local, MutTy, Mutability, Node, Path, Stmt, StmtKind, Ty,
- TyKind, UnOp,
-};
-use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
-use rustc_middle::hir::nested_filter;
-use rustc_middle::mir::interpret::ConstValue;
-use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, subst::GenericArgKind, FloatTy};
-use rustc_semver::RustcVersion;
-use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
-use rustc_span::source_map::Spanned;
-use rustc_span::symbol::Symbol;
-use rustc_span::{sym, BytePos, Span};
-use rustc_typeck::hir_ty_to_ty;
-
-use std::borrow::{Borrow, Cow};
-
-#[cfg(feature = "internal")]
+pub mod clippy_lints_internal;
+pub mod collapsible_calls;
+pub mod compiler_lint_functions;
+pub mod if_chain_style;
+pub mod interning_defined_symbol;
+pub mod invalid_paths;
+pub mod lint_without_lint_pass;
pub mod metadata_collector;
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for various things we like to keep tidy in clippy.
- ///
- /// ### Why is this bad?
- /// We like to pretend we're an example of tidy code.
- ///
- /// ### Example
- /// Wrong ordering of the util::paths constants.
- pub CLIPPY_LINTS_INTERNAL,
- internal,
- "various things that will negatively affect your clippy experience"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Ensures every lint is associated to a `LintPass`.
- ///
- /// ### Why is this bad?
- /// The compiler only knows lints via a `LintPass`. Without
- /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
- /// know the name of the lint.
- ///
- /// ### Known problems
- /// Only checks for lints associated using the
- /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
- ///
- /// ### Example
- /// ```rust,ignore
- /// declare_lint! { pub LINT_1, ... }
- /// declare_lint! { pub LINT_2, ... }
- /// declare_lint! { pub FORGOTTEN_LINT, ... }
- /// // ...
- /// declare_lint_pass!(Pass => [LINT_1, LINT_2]);
- /// // missing FORGOTTEN_LINT
- /// ```
- pub LINT_WITHOUT_LINT_PASS,
- internal,
- "declaring a lint without associating it in a LintPass"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `cx.span_lint*` and suggests to use the `utils::*`
- /// variant of the function.
- ///
- /// ### Why is this bad?
- /// The `utils::*` variants also add a link to the Clippy documentation to the
- /// warning/error messages.
- ///
- /// ### Example
- /// ```rust,ignore
- /// cx.span_lint(LINT_NAME, "message");
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// utils::span_lint(cx, LINT_NAME, "message");
- /// ```
- pub COMPILER_LINT_FUNCTIONS,
- internal,
- "usage of the lint functions of the compiler instead of the utils::* variant"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `cx.outer().expn_data()` and suggests to use
- /// the `cx.outer_expn_data()`
- ///
- /// ### Why is this bad?
- /// `cx.outer_expn_data()` is faster and more concise.
- ///
- /// ### Example
- /// ```rust,ignore
- /// expr.span.ctxt().outer().expn_data()
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// expr.span.ctxt().outer_expn_data()
- /// ```
- pub OUTER_EXPN_EXPN_DATA,
- internal,
- "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Not an actual lint. This lint is only meant for testing our customized internal compiler
- /// error message by calling `panic`.
- ///
- /// ### Why is this bad?
- /// ICE in large quantities can damage your teeth
- ///
- /// ### Example
- /// ```rust,ignore
- /// 🍦🍦🍦🍦🍦
- /// ```
- pub PRODUCE_ICE,
- internal,
- "this message should not appear anywhere as we ICE before and don't emit the lint"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for cases of an auto-generated lint without an updated description,
- /// i.e. `default lint description`.
- ///
- /// ### Why is this bad?
- /// Indicates that the lint is not finished.
- ///
- /// ### Example
- /// ```rust,ignore
- /// declare_lint! { pub COOL_LINT, nursery, "default lint description" }
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// declare_lint! { pub COOL_LINT, nursery, "a great new lint" }
- /// ```
- pub DEFAULT_LINT,
- internal,
- "found 'default lint description' in a lint declaration"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Lints `span_lint_and_then` function calls, where the
- /// closure argument has only one statement and that statement is a method
- /// call to `span_suggestion`, `span_help`, `span_note` (using the same
- /// span), `help` or `note`.
- ///
- /// These usages of `span_lint_and_then` should be replaced with one of the
- /// wrapper functions `span_lint_and_sugg`, span_lint_and_help`, or
- /// `span_lint_and_note`.
- ///
- /// ### Why is this bad?
- /// Using the wrapper `span_lint_and_*` functions, is more
- /// convenient, readable and less error prone.
- ///
- /// ### Example
- /// ```rust,ignore
- /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
- /// diag.span_suggestion(
- /// expr.span,
- /// help_msg,
- /// sugg.to_string(),
- /// Applicability::MachineApplicable,
- /// );
- /// });
- /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
- /// diag.span_help(expr.span, help_msg);
- /// });
- /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
- /// diag.help(help_msg);
- /// });
- /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
- /// diag.span_note(expr.span, note_msg);
- /// });
- /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
- /// diag.note(note_msg);
- /// });
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// span_lint_and_sugg(
- /// cx,
- /// TEST_LINT,
- /// expr.span,
- /// lint_msg,
- /// help_msg,
- /// sugg.to_string(),
- /// Applicability::MachineApplicable,
- /// );
- /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg);
- /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg);
- /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg);
- /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg);
- /// ```
- pub COLLAPSIBLE_SPAN_LINT_CALLS,
- internal,
- "found collapsible `span_lint_and_then` calls"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for calls to `utils::match_type()` on a type diagnostic item
- /// and suggests to use `utils::is_type_diagnostic_item()` instead.
- ///
- /// ### Why is this bad?
- /// `utils::is_type_diagnostic_item()` does not require hardcoded paths.
- ///
- /// ### Example
- /// ```rust,ignore
- /// utils::match_type(cx, ty, &paths::VEC)
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// utils::is_type_diagnostic_item(cx, ty, sym::Vec)
- /// ```
- pub MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
- internal,
- "using `utils::match_type()` instead of `utils::is_type_diagnostic_item()`"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks the paths module for invalid paths.
- ///
- /// ### Why is this bad?
- /// It indicates a bug in the code.
- ///
- /// ### Example
- /// None.
- pub INVALID_PATHS,
- internal,
- "invalid path"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for interning symbols that have already been pre-interned and defined as constants.
- ///
- /// ### Why is this bad?
- /// It's faster and easier to use the symbol constant.
- ///
- /// ### Example
- /// ```rust,ignore
- /// let _ = sym!(f32);
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// let _ = sym::f32;
- /// ```
- pub INTERNING_DEFINED_SYMBOL,
- internal,
- "interning a symbol that is pre-interned and defined as a constant"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for unnecessary conversion from Symbol to a string.
- ///
- /// ### Why is this bad?
- /// It's faster use symbols directly instead of strings.
- ///
- /// ### Example
- /// ```rust,ignore
- /// symbol.as_str() == "clippy";
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// symbol == sym::clippy;
- /// ```
- pub UNNECESSARY_SYMBOL_STR,
- internal,
- "unnecessary conversion between Symbol and string"
-}
-
-declare_clippy_lint! {
- /// Finds unidiomatic usage of `if_chain!`
- pub IF_CHAIN_STYLE,
- internal,
- "non-idiomatic `if_chain!` usage"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for invalid `clippy::version` attributes.
- ///
- /// Valid values are:
- /// * "pre 1.29.0"
- /// * any valid semantic version
- pub INVALID_CLIPPY_VERSION_ATTRIBUTE,
- internal,
- "found an invalid `clippy::version` attribute"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for declared clippy lints without the `clippy::version` attribute.
- ///
- pub MISSING_CLIPPY_VERSION_ATTRIBUTE,
- internal,
- "found clippy lint without `clippy::version` attribute"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Check that the `extract_msrv_attr!` macro is used, when a lint has a MSRV.
- ///
- pub MISSING_MSRV_ATTR_IMPL,
- internal,
- "checking if all necessary steps were taken when adding a MSRV to a lint"
-}
-
-declare_clippy_lint! {
- /// ### What it does
- /// Checks for cases of an auto-generated deprecated lint without an updated reason,
- /// i.e. `"default deprecation note"`.
- ///
- /// ### Why is this bad?
- /// Indicates that the documentation is incomplete.
- ///
- /// ### Example
- /// ```rust,ignore
- /// declare_deprecated_lint! {
- /// /// ### What it does
- /// /// Nothing. This lint has been deprecated.
- /// ///
- /// /// ### Deprecation reason
- /// /// TODO
- /// #[clippy::version = "1.63.0"]
- /// pub COOL_LINT,
- /// "default deprecation note"
- /// }
- /// ```
- ///
- /// Use instead:
- /// ```rust,ignore
- /// declare_deprecated_lint! {
- /// /// ### What it does
- /// /// Nothing. This lint has been deprecated.
- /// ///
- /// /// ### Deprecation reason
- /// /// This lint has been replaced by `cooler_lint`
- /// #[clippy::version = "1.63.0"]
- /// pub COOL_LINT,
- /// "this lint has been replaced by `cooler_lint`"
- /// }
- /// ```
- pub DEFAULT_DEPRECATION_REASON,
- internal,
- "found 'default deprecation note' in a deprecated lint declaration"
-}
-
-declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
-
-impl EarlyLintPass for ClippyLintsInternal {
- fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
- if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
- if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
- if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
- if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind {
- let mut last_name: Option<&str> = None;
- for item in items {
- let name = item.ident.as_str();
- if let Some(last_name) = last_name {
- if *last_name > *name {
- span_lint(
- cx,
- CLIPPY_LINTS_INTERNAL,
- item.span,
- "this constant should be before the previous constant due to lexical \
- ordering",
- );
- }
- }
- last_name = Some(name);
- }
- }
- }
- }
- }
- }
-}
-
-#[derive(Clone, Debug, Default)]
-pub struct LintWithoutLintPass {
- declared_lints: FxHashMap<Symbol, Span>,
- registered_lints: FxHashSet<Symbol>,
-}
-
-impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE, DEFAULT_DEPRECATION_REASON]);
-
-impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
- if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id())
- || is_lint_allowed(cx, DEFAULT_DEPRECATION_REASON, item.hir_id())
- {
- return;
- }
-
- if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
- let is_lint_ref_ty = is_lint_ref_type(cx, ty);
- if is_deprecated_lint(cx, ty) || is_lint_ref_ty {
- check_invalid_clippy_version_attribute(cx, item);
-
- let expr = &cx.tcx.hir().body(body_id).value;
- let fields;
- if is_lint_ref_ty {
- if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
- && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind {
- fields = struct_fields;
- } else {
- return;
- }
- } else if let ExprKind::Struct(_, struct_fields, _) = expr.kind {
- fields = struct_fields;
- } else {
- return;
- }
-
- let field = fields
- .iter()
- .find(|f| f.ident.as_str() == "desc")
- .expect("lints must have a description field");
-
- if let ExprKind::Lit(Spanned {
- node: LitKind::Str(ref sym, _),
- ..
- }) = field.expr.kind
- {
- let sym_str = sym.as_str();
- if is_lint_ref_ty {
- if sym_str == "default lint description" {
- span_lint(
- cx,
- DEFAULT_LINT,
- item.span,
- &format!("the lint `{}` has the default lint description", item.ident.name),
- );
- }
-
- self.declared_lints.insert(item.ident.name, item.span);
- } else if sym_str == "default deprecation note" {
- span_lint(
- cx,
- DEFAULT_DEPRECATION_REASON,
- item.span,
- &format!("the lint `{}` has the default deprecation reason", item.ident.name),
- );
- }
- }
- }
- } else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
- if !matches!(
- cx.tcx.item_name(macro_call.def_id).as_str(),
- "impl_lint_pass" | "declare_lint_pass"
- ) {
- return;
- }
- if let hir::ItemKind::Impl(hir::Impl {
- of_trait: None,
- items: impl_item_refs,
- ..
- }) = item.kind
- {
- let mut collector = LintCollector {
- output: &mut self.registered_lints,
- 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(),
- ),
- );
- collector.visit_expr(cx.tcx.hir().body(body_id).value);
- }
- }
- }
-
- fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
- if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
- return;
- }
-
- for (lint_name, &lint_span) in &self.declared_lints {
- // When using the `declare_tool_lint!` macro, the original `lint_span`'s
- // file points to "<rustc macros>".
- // `compiletest-rs` thinks that's an error in a different file and
- // just ignores it. This causes the test in compile-fail/lint_pass
- // not able to capture the error.
- // Therefore, we need to climb the macro expansion tree and find the
- // actual span that invoked `declare_tool_lint!`:
- let lint_span = lint_span.ctxt().outer_expn_data().call_site;
-
- if !self.registered_lints.contains(lint_name) {
- span_lint(
- cx,
- LINT_WITHOUT_LINT_PASS,
- lint_span,
- &format!("the lint `{}` is not added to any `LintPass`", lint_name),
- );
- }
- }
- }
-}
-
-fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &Ty<'_>) -> bool {
- if let TyKind::Rptr(
- _,
- MutTy {
- ty: inner,
- mutbl: Mutability::Not,
- },
- ) = ty.kind
- {
- if let TyKind::Path(ref path) = inner.kind {
- if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) {
- return match_def_path(cx, def_id, &paths::LINT);
- }
- }
- }
-
- false
-}
-
-fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) {
- if let Some(value) = extract_clippy_version_value(cx, item) {
- // The `sym!` macro doesn't work as it only expects a single token.
- // It's better to keep it this way and have a direct `Symbol::intern` call here.
- if value == Symbol::intern("pre 1.29.0") {
- return;
- }
-
- if RustcVersion::parse(value.as_str()).is_err() {
- span_lint_and_help(
- cx,
- INVALID_CLIPPY_VERSION_ATTRIBUTE,
- item.span,
- "this item has an invalid `clippy::version` attribute",
- None,
- "please use a valid semantic version, see `doc/adding_lints.md`",
- );
- }
- } else {
- span_lint_and_help(
- cx,
- MISSING_CLIPPY_VERSION_ATTRIBUTE,
- item.span,
- "this lint is missing the `clippy::version` attribute or version value",
- None,
- "please use a `clippy::version` attribute, see `doc/adding_lints.md`",
- );
- }
-}
-
-/// This function extracts the version value of a `clippy::version` attribute if the given value has
-/// one
-fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
- let attrs = cx.tcx.hir().attrs(item.hir_id());
- attrs.iter().find_map(|attr| {
- if_chain! {
- // Identify attribute
- if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind;
- if let [tool_name, attr_name] = &attr_kind.item.path.segments[..];
- if tool_name.ident.name == sym::clippy;
- if attr_name.ident.name == sym::version;
- if let Some(version) = attr.value_str();
- then {
- Some(version)
- } else {
- None
- }
- }
- })
-}
-
-struct LintCollector<'a, 'tcx> {
- output: &'a mut FxHashSet<Symbol>,
- cx: &'a LateContext<'tcx>,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
- type NestedFilter = nested_filter::All;
-
- fn visit_path(&mut self, path: &'tcx Path<'_>, _: HirId) {
- if path.segments.len() == 1 {
- self.output.insert(path.segments[0].ident.name);
- }
- }
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.cx.tcx.hir()
- }
-}
-
-#[derive(Clone, Default)]
-pub struct CompilerLintFunctions {
- map: FxHashMap<&'static str, &'static str>,
-}
-
-impl CompilerLintFunctions {
- #[must_use]
- pub fn new() -> Self {
- let mut map = FxHashMap::default();
- map.insert("span_lint", "utils::span_lint");
- map.insert("struct_span_lint", "utils::span_lint");
- map.insert("lint", "utils::span_lint");
- map.insert("span_lint_note", "utils::span_lint_and_note");
- map.insert("span_lint_help", "utils::span_lint_and_help");
- Self { map }
- }
-}
-
-impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]);
-
-impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if is_lint_allowed(cx, COMPILER_LINT_FUNCTIONS, expr.hir_id) {
- return;
- }
-
- if_chain! {
- if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind;
- let fn_name = path.ident;
- if let Some(sugg) = self.map.get(fn_name.as_str());
- let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
- if match_type(cx, ty, &paths::EARLY_CONTEXT)
- || match_type(cx, ty, &paths::LATE_CONTEXT);
- then {
- span_lint_and_help(
- cx,
- COMPILER_LINT_FUNCTIONS,
- path.ident.span,
- "usage of a compiler lint function",
- None,
- &format!("please use the Clippy variant of this function: `{}`", sugg),
- );
- }
- }
- }
-}
-
-declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);
-
-impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
- if is_lint_allowed(cx, OUTER_EXPN_EXPN_DATA, expr.hir_id) {
- return;
- }
-
- let (method_names, arg_lists, spans) = method_calls(expr, 2);
- let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect();
- if_chain! {
- if let ["expn_data", "outer_expn"] = method_names.as_slice();
- let (self_arg, args)= arg_lists[1];
- if args.is_empty();
- let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
- if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
- then {
- span_lint_and_sugg(
- cx,
- OUTER_EXPN_EXPN_DATA,
- spans[1].with_hi(expr.span.hi()),
- "usage of `outer_expn().expn_data()`",
- "try",
- "outer_expn_data()".to_string(),
- Applicability::MachineApplicable,
- );
- }
- }
- }
-}
-
-declare_lint_pass!(ProduceIce => [PRODUCE_ICE]);
-
-impl EarlyLintPass for ProduceIce {
- fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) {
- assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?");
- }
-}
-
-fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
- match fn_kind {
- FnKind::Fn(_, ident, ..) => ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy",
- FnKind::Closure(..) => false,
- }
-}
-
-declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
-
-impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
- if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) {
- return;
- }
-
- if_chain! {
- if let ExprKind::Call(func, and_then_args) = expr.kind;
- if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]);
- if and_then_args.len() == 5;
- if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind;
- let body = cx.tcx.hir().body(body);
- let only_expr = peel_blocks_with_stmt(body.value);
- if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind;
- if let ExprKind::Path(..) = recv.kind;
- then {
- let and_then_snippets = get_and_then_snippets(cx, and_then_args);
- let mut sle = SpanlessEq::new(cx).deny_side_effects();
- match ps.ident.as_str() {
- "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
- suggest_suggestion(cx, expr, &and_then_snippets, &span_suggestion_snippets(cx, span_call_args));
- },
- "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
- let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
- suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
- },
- "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
- let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
- suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
- },
- "help" => {
- let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
- suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false);
- }
- "note" => {
- let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
- suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false);
- }
- _ => (),
- }
- }
- }
- }
-}
-
-struct AndThenSnippets<'a> {
- cx: Cow<'a, str>,
- lint: Cow<'a, str>,
- span: Cow<'a, str>,
- msg: Cow<'a, str>,
-}
-
-fn get_and_then_snippets<'a, 'hir>(cx: &LateContext<'_>, and_then_snippets: &'hir [Expr<'hir>]) -> AndThenSnippets<'a> {
- let cx_snippet = snippet(cx, and_then_snippets[0].span, "cx");
- let lint_snippet = snippet(cx, and_then_snippets[1].span, "..");
- let span_snippet = snippet(cx, and_then_snippets[2].span, "span");
- let msg_snippet = snippet(cx, and_then_snippets[3].span, r#""...""#);
-
- AndThenSnippets {
- cx: cx_snippet,
- lint: lint_snippet,
- span: span_snippet,
- msg: msg_snippet,
- }
-}
-
-struct SpanSuggestionSnippets<'a> {
- help: Cow<'a, str>,
- sugg: Cow<'a, str>,
- applicability: Cow<'a, str>,
-}
-
-fn span_suggestion_snippets<'a, 'hir>(
- cx: &LateContext<'_>,
- span_call_args: &'hir [Expr<'hir>],
-) -> SpanSuggestionSnippets<'a> {
- let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
- let sugg_snippet = snippet(cx, span_call_args[2].span, "..");
- let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable");
-
- SpanSuggestionSnippets {
- help: help_snippet,
- sugg: sugg_snippet,
- applicability: applicability_snippet,
- }
-}
-
-fn suggest_suggestion(
- cx: &LateContext<'_>,
- expr: &Expr<'_>,
- and_then_snippets: &AndThenSnippets<'_>,
- span_suggestion_snippets: &SpanSuggestionSnippets<'_>,
-) {
- span_lint_and_sugg(
- cx,
- COLLAPSIBLE_SPAN_LINT_CALLS,
- expr.span,
- "this call is collapsible",
- "collapse into",
- format!(
- "span_lint_and_sugg({}, {}, {}, {}, {}, {}, {})",
- and_then_snippets.cx,
- and_then_snippets.lint,
- and_then_snippets.span,
- and_then_snippets.msg,
- span_suggestion_snippets.help,
- span_suggestion_snippets.sugg,
- span_suggestion_snippets.applicability
- ),
- Applicability::MachineApplicable,
- );
-}
-
-fn suggest_help(
- cx: &LateContext<'_>,
- expr: &Expr<'_>,
- and_then_snippets: &AndThenSnippets<'_>,
- help: &str,
- with_span: bool,
-) {
- let option_span = if with_span {
- format!("Some({})", and_then_snippets.span)
- } else {
- "None".to_string()
- };
-
- span_lint_and_sugg(
- cx,
- COLLAPSIBLE_SPAN_LINT_CALLS,
- expr.span,
- "this call is collapsible",
- "collapse into",
- format!(
- "span_lint_and_help({}, {}, {}, {}, {}, {})",
- and_then_snippets.cx,
- and_then_snippets.lint,
- and_then_snippets.span,
- and_then_snippets.msg,
- &option_span,
- help
- ),
- Applicability::MachineApplicable,
- );
-}
-
-fn suggest_note(
- cx: &LateContext<'_>,
- expr: &Expr<'_>,
- and_then_snippets: &AndThenSnippets<'_>,
- note: &str,
- with_span: bool,
-) {
- let note_span = if with_span {
- format!("Some({})", and_then_snippets.span)
- } else {
- "None".to_string()
- };
-
- span_lint_and_sugg(
- cx,
- COLLAPSIBLE_SPAN_LINT_CALLS,
- expr.span,
- "this call is collapsible",
- "collapse into",
- format!(
- "span_lint_and_note({}, {}, {}, {}, {}, {})",
- and_then_snippets.cx,
- and_then_snippets.lint,
- and_then_snippets.span,
- and_then_snippets.msg,
- note_span,
- note
- ),
- Applicability::MachineApplicable,
- );
-}
-
-declare_lint_pass!(MatchTypeOnDiagItem => [MATCH_TYPE_ON_DIAGNOSTIC_ITEM]);
-
-impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
- if is_lint_allowed(cx, MATCH_TYPE_ON_DIAGNOSTIC_ITEM, expr.hir_id) {
- return;
- }
-
- if_chain! {
- // Check if this is a call to utils::match_type()
- if let ExprKind::Call(fn_path, [context, ty, ty_path]) = expr.kind;
- if is_expr_path_def_path(cx, fn_path, &["clippy_utils", "ty", "match_type"]);
- // Extract the path to the matched type
- if let Some(segments) = path_to_matched_type(cx, ty_path);
- let segments: Vec<&str> = segments.iter().map(Symbol::as_str).collect();
- if let Some(ty_did) = def_path_res(cx, &segments[..]).opt_def_id();
- // Check if the matched type is a diagnostic item
- if let Some(item_name) = cx.tcx.get_diagnostic_name(ty_did);
- then {
- // TODO: check paths constants from external crates.
- let cx_snippet = snippet(cx, context.span, "_");
- let ty_snippet = snippet(cx, ty.span, "_");
-
- span_lint_and_sugg(
- cx,
- MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
- expr.span,
- "usage of `clippy_utils::ty::match_type()` on a type diagnostic item",
- "try",
- format!("clippy_utils::ty::is_type_diagnostic_item({}, {}, sym::{})", cx_snippet, ty_snippet, item_name),
- Applicability::MaybeIncorrect,
- );
- }
- }
- }
-}
-
-fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Vec<Symbol>> {
- use rustc_hir::ItemKind;
-
- match &expr.kind {
- ExprKind::AddrOf(.., expr) => return path_to_matched_type(cx, expr),
- ExprKind::Path(qpath) => match cx.qpath_res(qpath, expr.hir_id) {
- Res::Local(hir_id) => {
- let parent_id = cx.tcx.hir().get_parent_node(hir_id);
- if let Some(Node::Local(local)) = cx.tcx.hir().find(parent_id) {
- if let Some(init) = local.init {
- return path_to_matched_type(cx, init);
- }
- }
- },
- Res::Def(DefKind::Const | DefKind::Static(..), def_id) => {
- if let Some(Node::Item(item)) = cx.tcx.hir().get_if_local(def_id) {
- if let ItemKind::Const(.., body_id) | ItemKind::Static(.., body_id) = item.kind {
- let body = cx.tcx.hir().body(body_id);
- return path_to_matched_type(cx, body.value);
- }
- }
- },
- _ => {},
- },
- ExprKind::Array(exprs) => {
- let segments: Vec<Symbol> = exprs
- .iter()
- .filter_map(|expr| {
- if let ExprKind::Lit(lit) = &expr.kind {
- if let LitKind::Str(sym, _) = lit.node {
- return Some(sym);
- }
- }
-
- None
- })
- .collect();
-
- if segments.len() == exprs.len() {
- return Some(segments);
- }
- },
- _ => {},
- }
-
- None
-}
-
-// This is not a complete resolver for paths. It works on all the paths currently used in the paths
-// module. That's all it does and all it needs to do.
-pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
- if def_path_res(cx, path) != Res::Err {
- return true;
- }
-
- // Some implementations can't be found by `path_to_res`, particularly inherent
- // implementations of native types. Check lang items.
- let path_syms: Vec<_> = path.iter().map(|p| Symbol::intern(p)).collect();
- let lang_items = cx.tcx.lang_items();
- // This list isn't complete, but good enough for our current list of paths.
- let incoherent_impls = [
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
- SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
- SimplifiedTypeGen::SliceSimplifiedType,
- SimplifiedTypeGen::StrSimplifiedType,
- ]
- .iter()
- .flat_map(|&ty| cx.tcx.incoherent_impls(ty));
- for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) {
- let lang_item_path = cx.get_def_path(*item_def_id);
- if path_syms.starts_with(&lang_item_path) {
- if let [item] = &path_syms[lang_item_path.len()..] {
- if matches!(
- cx.tcx.def_kind(*item_def_id),
- DefKind::Mod | DefKind::Enum | DefKind::Trait
- ) {
- for child in cx.tcx.module_children(*item_def_id) {
- if child.ident.name == *item {
- return true;
- }
- }
- } else {
- for child in cx.tcx.associated_item_def_ids(*item_def_id) {
- if cx.tcx.item_name(*child) == *item {
- return true;
- }
- }
- }
- }
- }
- }
-
- false
-}
-
-declare_lint_pass!(InvalidPaths => [INVALID_PATHS]);
-
-impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
- let local_def_id = &cx.tcx.parent_module(item.hir_id());
- let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
- if_chain! {
- if mod_name.as_str() == "paths";
- if let hir::ItemKind::Const(ty, body_id) = item.kind;
- let ty = hir_ty_to_ty(cx.tcx, ty);
- if let ty::Array(el_ty, _) = &ty.kind();
- if let ty::Ref(_, el_ty, _) = &el_ty.kind();
- if el_ty.is_str();
- let body = cx.tcx.hir().body(body_id);
- let typeck_results = cx.tcx.typeck_body(body_id);
- if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value);
- let path: Vec<&str> = path.iter().map(|x| {
- if let Constant::Str(s) = x {
- s.as_str()
- } else {
- // We checked the type of the constant above
- unreachable!()
- }
- }).collect();
- if !check_path(cx, &path[..]);
- then {
- span_lint(cx, INVALID_PATHS, item.span, "invalid path");
- }
- }
- }
-}
-
-#[derive(Default)]
-pub struct InterningDefinedSymbol {
- // Maps the symbol value to the constant DefId.
- symbol_map: FxHashMap<u32, DefId>,
-}
-
-impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]);
-
-impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
- fn check_crate(&mut self, cx: &LateContext<'_>) {
- if !self.symbol_map.is_empty() {
- return;
- }
-
- for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
- if let Some(def_id) = def_path_res(cx, module).opt_def_id() {
- 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);
- 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();
- then {
- self.symbol_map.insert(value, item_def_id);
- }
- }
- }
- }
- }
- }
-
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
- if_chain! {
- if let ExprKind::Call(func, [arg]) = &expr.kind;
- if let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind();
- if match_def_path(cx, *def_id, &paths::SYMBOL_INTERN);
- if let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg);
- let value = Symbol::intern(&arg).as_u32();
- if let Some(&def_id) = self.symbol_map.get(&value);
- then {
- span_lint_and_sugg(
- cx,
- INTERNING_DEFINED_SYMBOL,
- is_expn_of(expr.span, "sym").unwrap_or(expr.span),
- "interning a defined symbol",
- "try",
- cx.tcx.def_path_str(def_id),
- Applicability::MachineApplicable,
- );
- }
- }
- if let ExprKind::Binary(op, left, right) = expr.kind {
- if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) {
- let data = [
- (left, self.symbol_str_expr(left, cx)),
- (right, self.symbol_str_expr(right, cx)),
- ];
- match data {
- // both operands are a symbol string
- [(_, Some(left)), (_, Some(right))] => {
- span_lint_and_sugg(
- cx,
- UNNECESSARY_SYMBOL_STR,
- expr.span,
- "unnecessary `Symbol` to string conversion",
- "try",
- format!(
- "{} {} {}",
- left.as_symbol_snippet(cx),
- op.node.as_str(),
- right.as_symbol_snippet(cx),
- ),
- Applicability::MachineApplicable,
- );
- },
- // one of the operands is a symbol string
- [(expr, Some(symbol)), _] | [_, (expr, Some(symbol))] => {
- // creating an owned string for comparison
- if matches!(symbol, SymbolStrExpr::Expr { is_to_owned: true, .. }) {
- span_lint_and_sugg(
- cx,
- UNNECESSARY_SYMBOL_STR,
- expr.span,
- "unnecessary string allocation",
- "try",
- format!("{}.as_str()", symbol.as_symbol_snippet(cx)),
- Applicability::MachineApplicable,
- );
- }
- },
- // nothing found
- [(_, None), (_, None)] => {},
- }
- }
- }
- }
-}
-
-impl InterningDefinedSymbol {
- fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> {
- static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR, &paths::TO_STRING_METHOD];
- static SYMBOL_STR_PATHS: &[&[&str]] = &[
- &paths::SYMBOL_AS_STR,
- &paths::SYMBOL_TO_IDENT_STRING,
- &paths::TO_STRING_METHOD,
- ];
- let call = if_chain! {
- if let ExprKind::AddrOf(_, _, e) = expr.kind;
- if let ExprKind::Unary(UnOp::Deref, e) = e.kind;
- then { e } else { expr }
- };
- if_chain! {
- // is a method call
- if let ExprKind::MethodCall(_, item, [], _) = call.kind;
- if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id);
- let ty = cx.typeck_results().expr_ty(item);
- // ...on either an Ident or a Symbol
- if let Some(is_ident) = if match_type(cx, ty, &paths::SYMBOL) {
- Some(false)
- } else if match_type(cx, ty, &paths::IDENT) {
- Some(true)
- } else {
- None
- };
- // ...which converts it to a string
- let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS };
- if let Some(path) = paths.iter().find(|path| match_def_path(cx, did, path));
- then {
- let is_to_owned = path.last().unwrap().ends_with("string");
- return Some(SymbolStrExpr::Expr {
- item,
- is_ident,
- is_to_owned,
- });
- }
- }
- // is a string constant
- if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) {
- let value = Symbol::intern(&s).as_u32();
- // ...which matches a symbol constant
- if let Some(&def_id) = self.symbol_map.get(&value) {
- return Some(SymbolStrExpr::Const(def_id));
- }
- }
- None
- }
-}
-
-enum SymbolStrExpr<'tcx> {
- /// a string constant with a corresponding symbol constant
- Const(DefId),
- /// a "symbol to string" expression like `symbol.as_str()`
- Expr {
- /// part that evaluates to `Symbol` or `Ident`
- item: &'tcx Expr<'tcx>,
- is_ident: bool,
- /// whether an owned `String` is created like `to_ident_string()`
- is_to_owned: bool,
- },
-}
-
-impl<'tcx> SymbolStrExpr<'tcx> {
- /// Returns a snippet that evaluates to a `Symbol` and is const if possible
- fn as_symbol_snippet(&self, cx: &LateContext<'_>) -> Cow<'tcx, str> {
- match *self {
- Self::Const(def_id) => cx.tcx.def_path_str(def_id).into(),
- Self::Expr { item, is_ident, .. } => {
- let mut snip = snippet(cx, item.span.source_callsite(), "..");
- if is_ident {
- // get `Ident.name`
- snip.to_mut().push_str(".name");
- }
- snip
- },
- }
- }
-}
-
-declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]);
-
-impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
- fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
- let (local, after, if_chain_span) = if_chain! {
- if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts;
- if let Some(if_chain_span) = is_expn_of(block.span, "if_chain");
- then { (local, after, if_chain_span) } else { return }
- };
- if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) {
- span_lint(
- cx,
- IF_CHAIN_STYLE,
- if_chain_local_span(cx, local, if_chain_span),
- "`let` expression should be above the `if_chain!`",
- );
- } else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) {
- span_lint(
- cx,
- IF_CHAIN_STYLE,
- if_chain_local_span(cx, local, if_chain_span),
- "`let` expression should be inside `then { .. }`",
- );
- }
- }
-
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
- let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) {
- (cond, then, r#else.is_some())
- } else {
- return;
- };
- let then_block = match then.kind {
- ExprKind::Block(block, _) => block,
- _ => return,
- };
- let if_chain_span = is_expn_of(expr.span, "if_chain");
- if !els {
- check_nested_if_chains(cx, expr, then_block, if_chain_span);
- }
- let if_chain_span = match if_chain_span {
- None => return,
- Some(span) => span,
- };
- // check for `if a && b;`
- if_chain! {
- if let ExprKind::Binary(op, _, _) = cond.kind;
- if op.node == BinOpKind::And;
- if cx.sess().source_map().is_multiline(cond.span);
- then {
- span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`");
- }
- }
- if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span)
- && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span)
- {
- span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`");
- }
- }
-}
-
-fn check_nested_if_chains(
- cx: &LateContext<'_>,
- if_expr: &Expr<'_>,
- then_block: &Block<'_>,
- if_chain_span: Option<Span>,
-) {
- #[rustfmt::skip]
- let (head, tail) = match *then_block {
- Block { stmts, expr: Some(tail), .. } => (stmts, tail),
- Block {
- stmts: &[
- ref head @ ..,
- Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. }
- ],
- ..
- } => (head, tail),
- _ => return,
- };
- if_chain! {
- if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail);
- let sm = cx.sess().source_map();
- if head
- .iter()
- .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span));
- if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr);
- then {} else { return }
- }
- let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) {
- (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"),
- (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"),
- (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"),
- _ => return,
- };
- span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| {
- let (span, msg) = match head {
- [] => return,
- [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"),
- [a, .., b] => (
- a.span.to(b.span),
- "these `let` statements can also be in the `if_chain!`",
- ),
- };
- diag.span_help(span, msg);
- });
-}
-
-fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool {
- cx.tcx
- .hir()
- .parent_iter(hir_id)
- .find(|(_, node)| {
- #[rustfmt::skip]
- !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_))
- })
- .map_or(false, |(id, _)| {
- is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span)
- })
-}
-
-/// Checks a trailing slice of statements and expression of a `Block` to see if they are part
-/// of the `then {..}` portion of an `if_chain!`
-fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool {
- let span = if let [stmt, ..] = stmts {
- stmt.span
- } else if let Some(expr) = expr {
- expr.span
- } else {
- // empty `then {}`
- return true;
- };
- is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span)
-}
-
-/// Creates a `Span` for `let x = ..;` in an `if_chain!` call.
-fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span {
- let mut span = local.pat.span;
- if let Some(init) = local.init {
- span = span.to(init.span);
- }
- span.adjust(if_chain_span.ctxt().outer_expn());
- let sm = cx.sess().source_map();
- let span = sm.span_extend_to_prev_str(span, "let", false, true).unwrap_or(span);
- let span = sm.span_extend_to_next_char(span, ';', false);
- Span::new(
- span.lo() - BytePos(3),
- span.hi() + BytePos(1),
- span.ctxt(),
- span.parent(),
- )
-}
-
-declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]);
-
-impl LateLintPass<'_> for MsrvAttrImpl {
- fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
- if_chain! {
- if let hir::ItemKind::Impl(hir::Impl {
- of_trait: Some(lint_pass_trait_ref),
- self_ty,
- items,
- ..
- }) = &item.kind;
- if let Some(lint_pass_trait_def_id) = lint_pass_trait_ref.trait_def_id();
- let is_late_pass = match_def_path(cx, lint_pass_trait_def_id, &paths::LATE_LINT_PASS);
- if is_late_pass || match_def_path(cx, lint_pass_trait_def_id, &paths::EARLY_LINT_PASS);
- let self_ty = hir_ty_to_ty(cx.tcx, self_ty);
- if let ty::Adt(self_ty_def, _) = self_ty.kind();
- if self_ty_def.is_struct();
- if self_ty_def.all_fields().any(|f| {
- cx.tcx
- .type_of(f.did)
- .walk()
- .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
- .any(|t| match_type(cx, t.expect_ty(), &paths::RUSTC_VERSION))
- });
- if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs));
- then {
- let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
- let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
- let span = cx.sess().source_map().span_through_char(item.span, '{');
- span_lint_and_sugg(
- cx,
- MISSING_MSRV_ATTR_IMPL,
- span,
- &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
- &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
- format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")),
- Applicability::MachineApplicable,
- );
- }
- }
- }
-}
+pub mod msrv_attr_impl;
+pub mod outer_expn_data_pass;
+pub mod produce_ice;
+pub mod unnecessary_def_path;
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/clippy_lints_internal.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/clippy_lints_internal.rs
new file mode 100644
index 000000000..da9514dd1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/clippy_lints_internal.rs
@@ -0,0 +1,49 @@
+use clippy_utils::diagnostics::span_lint;
+use rustc_ast::ast::{Crate, ItemKind, ModKind};
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for various things we like to keep tidy in clippy.
+ ///
+ /// ### Why is this bad?
+ /// We like to pretend we're an example of tidy code.
+ ///
+ /// ### Example
+ /// Wrong ordering of the util::paths constants.
+ pub CLIPPY_LINTS_INTERNAL,
+ internal,
+ "various things that will negatively affect your clippy experience"
+}
+
+declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);
+
+impl EarlyLintPass for ClippyLintsInternal {
+ fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &Crate) {
+ if let Some(utils) = krate.items.iter().find(|item| item.ident.name.as_str() == "utils") {
+ if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = utils.kind {
+ if let Some(paths) = items.iter().find(|item| item.ident.name.as_str() == "paths") {
+ if let ItemKind::Mod(_, ModKind::Loaded(ref items, ..)) = paths.kind {
+ let mut last_name: Option<&str> = None;
+ for item in items {
+ let name = item.ident.as_str();
+ if let Some(last_name) = last_name {
+ if *last_name > *name {
+ span_lint(
+ cx,
+ CLIPPY_LINTS_INTERNAL,
+ item.span,
+ "this constant should be before the previous constant due to lexical \
+ ordering",
+ );
+ }
+ }
+ last_name = Some(name);
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
new file mode 100644
index 000000000..d7666b77f
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/collapsible_calls.rs
@@ -0,0 +1,245 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::{is_expr_path_def_path, is_lint_allowed, peel_blocks_with_stmt, SpanlessEq};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::{Closure, Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+use std::borrow::{Borrow, Cow};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Lints `span_lint_and_then` function calls, where the
+ /// closure argument has only one statement and that statement is a method
+ /// call to `span_suggestion`, `span_help`, `span_note` (using the same
+ /// span), `help` or `note`.
+ ///
+ /// These usages of `span_lint_and_then` should be replaced with one of the
+ /// wrapper functions `span_lint_and_sugg`, span_lint_and_help`, or
+ /// `span_lint_and_note`.
+ ///
+ /// ### Why is this bad?
+ /// Using the wrapper `span_lint_and_*` functions, is more
+ /// convenient, readable and less error prone.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
+ /// diag.span_suggestion(
+ /// expr.span,
+ /// help_msg,
+ /// sugg.to_string(),
+ /// Applicability::MachineApplicable,
+ /// );
+ /// });
+ /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
+ /// diag.span_help(expr.span, help_msg);
+ /// });
+ /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
+ /// diag.help(help_msg);
+ /// });
+ /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
+ /// diag.span_note(expr.span, note_msg);
+ /// });
+ /// span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |diag| {
+ /// diag.note(note_msg);
+ /// });
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// span_lint_and_sugg(
+ /// cx,
+ /// TEST_LINT,
+ /// expr.span,
+ /// lint_msg,
+ /// help_msg,
+ /// sugg.to_string(),
+ /// Applicability::MachineApplicable,
+ /// );
+ /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg);
+ /// span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg);
+ /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg);
+ /// span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg);
+ /// ```
+ pub COLLAPSIBLE_SPAN_LINT_CALLS,
+ internal,
+ "found collapsible `span_lint_and_then` calls"
+}
+
+declare_lint_pass!(CollapsibleCalls => [COLLAPSIBLE_SPAN_LINT_CALLS]);
+
+impl<'tcx> LateLintPass<'tcx> for CollapsibleCalls {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+ if is_lint_allowed(cx, COLLAPSIBLE_SPAN_LINT_CALLS, expr.hir_id) {
+ return;
+ }
+
+ if_chain! {
+ if let ExprKind::Call(func, and_then_args) = expr.kind;
+ if is_expr_path_def_path(cx, func, &["clippy_utils", "diagnostics", "span_lint_and_then"]);
+ if and_then_args.len() == 5;
+ if let ExprKind::Closure(&Closure { body, .. }) = &and_then_args[4].kind;
+ let body = cx.tcx.hir().body(body);
+ let only_expr = peel_blocks_with_stmt(body.value);
+ if let ExprKind::MethodCall(ps, recv, span_call_args, _) = &only_expr.kind;
+ if let ExprKind::Path(..) = recv.kind;
+ then {
+ let and_then_snippets = get_and_then_snippets(cx, and_then_args);
+ let mut sle = SpanlessEq::new(cx).deny_side_effects();
+ match ps.ident.as_str() {
+ "span_suggestion" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+ suggest_suggestion(
+ cx,
+ expr,
+ &and_then_snippets,
+ &span_suggestion_snippets(cx, span_call_args),
+ );
+ },
+ "span_help" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+ let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), true);
+ },
+ "span_note" if sle.eq_expr(&and_then_args[2], &span_call_args[0]) => {
+ let note_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), true);
+ },
+ "help" => {
+ let help_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
+ suggest_help(cx, expr, &and_then_snippets, help_snippet.borrow(), false);
+ },
+ "note" => {
+ let note_snippet = snippet(cx, span_call_args[0].span, r#""...""#);
+ suggest_note(cx, expr, &and_then_snippets, note_snippet.borrow(), false);
+ },
+ _ => (),
+ }
+ }
+ }
+ }
+}
+
+struct AndThenSnippets<'a> {
+ cx: Cow<'a, str>,
+ lint: Cow<'a, str>,
+ span: Cow<'a, str>,
+ msg: Cow<'a, str>,
+}
+
+fn get_and_then_snippets<'a, 'hir>(cx: &LateContext<'_>, and_then_snippets: &'hir [Expr<'hir>]) -> AndThenSnippets<'a> {
+ let cx_snippet = snippet(cx, and_then_snippets[0].span, "cx");
+ let lint_snippet = snippet(cx, and_then_snippets[1].span, "..");
+ let span_snippet = snippet(cx, and_then_snippets[2].span, "span");
+ let msg_snippet = snippet(cx, and_then_snippets[3].span, r#""...""#);
+
+ AndThenSnippets {
+ cx: cx_snippet,
+ lint: lint_snippet,
+ span: span_snippet,
+ msg: msg_snippet,
+ }
+}
+
+struct SpanSuggestionSnippets<'a> {
+ help: Cow<'a, str>,
+ sugg: Cow<'a, str>,
+ applicability: Cow<'a, str>,
+}
+
+fn span_suggestion_snippets<'a, 'hir>(
+ cx: &LateContext<'_>,
+ span_call_args: &'hir [Expr<'hir>],
+) -> SpanSuggestionSnippets<'a> {
+ let help_snippet = snippet(cx, span_call_args[1].span, r#""...""#);
+ let sugg_snippet = snippet(cx, span_call_args[2].span, "..");
+ let applicability_snippet = snippet(cx, span_call_args[3].span, "Applicability::MachineApplicable");
+
+ SpanSuggestionSnippets {
+ help: help_snippet,
+ sugg: sugg_snippet,
+ applicability: applicability_snippet,
+ }
+}
+
+fn suggest_suggestion(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ and_then_snippets: &AndThenSnippets<'_>,
+ span_suggestion_snippets: &SpanSuggestionSnippets<'_>,
+) {
+ span_lint_and_sugg(
+ cx,
+ COLLAPSIBLE_SPAN_LINT_CALLS,
+ expr.span,
+ "this call is collapsible",
+ "collapse into",
+ format!(
+ "span_lint_and_sugg({}, {}, {}, {}, {}, {}, {})",
+ and_then_snippets.cx,
+ and_then_snippets.lint,
+ and_then_snippets.span,
+ and_then_snippets.msg,
+ span_suggestion_snippets.help,
+ span_suggestion_snippets.sugg,
+ span_suggestion_snippets.applicability
+ ),
+ Applicability::MachineApplicable,
+ );
+}
+
+fn suggest_help(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ and_then_snippets: &AndThenSnippets<'_>,
+ help: &str,
+ with_span: bool,
+) {
+ let option_span = if with_span {
+ format!("Some({})", and_then_snippets.span)
+ } else {
+ "None".to_string()
+ };
+
+ span_lint_and_sugg(
+ cx,
+ COLLAPSIBLE_SPAN_LINT_CALLS,
+ expr.span,
+ "this call is collapsible",
+ "collapse into",
+ format!(
+ "span_lint_and_help({}, {}, {}, {}, {}, {help})",
+ and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg, &option_span,
+ ),
+ Applicability::MachineApplicable,
+ );
+}
+
+fn suggest_note(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ and_then_snippets: &AndThenSnippets<'_>,
+ note: &str,
+ with_span: bool,
+) {
+ let note_span = if with_span {
+ format!("Some({})", and_then_snippets.span)
+ } else {
+ "None".to_string()
+ };
+
+ span_lint_and_sugg(
+ cx,
+ COLLAPSIBLE_SPAN_LINT_CALLS,
+ expr.span,
+ "this call is collapsible",
+ "collapse into",
+ format!(
+ "span_lint_and_note({}, {}, {}, {}, {note_span}, {note})",
+ and_then_snippets.cx, and_then_snippets.lint, and_then_snippets.span, and_then_snippets.msg,
+ ),
+ Applicability::MachineApplicable,
+ );
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
new file mode 100644
index 000000000..cacd05262
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs
@@ -0,0 +1,77 @@
+use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::ty::match_type;
+use clippy_utils::{is_lint_allowed, paths};
+use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for calls to `cx.span_lint*` and suggests to use the `utils::*`
+ /// variant of the function.
+ ///
+ /// ### Why is this bad?
+ /// The `utils::*` variants also add a link to the Clippy documentation to the
+ /// warning/error messages.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// cx.span_lint(LINT_NAME, "message");
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// utils::span_lint(cx, LINT_NAME, "message");
+ /// ```
+ pub COMPILER_LINT_FUNCTIONS,
+ internal,
+ "usage of the lint functions of the compiler instead of the utils::* variant"
+}
+
+impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]);
+
+#[derive(Clone, Default)]
+pub struct CompilerLintFunctions {
+ map: FxHashMap<&'static str, &'static str>,
+}
+
+impl CompilerLintFunctions {
+ #[must_use]
+ pub fn new() -> Self {
+ let mut map = FxHashMap::default();
+ map.insert("span_lint", "utils::span_lint");
+ map.insert("struct_span_lint", "utils::span_lint");
+ map.insert("lint", "utils::span_lint");
+ map.insert("span_lint_note", "utils::span_lint_and_note");
+ map.insert("span_lint_help", "utils::span_lint_and_help");
+ Self { map }
+ }
+}
+
+impl<'tcx> LateLintPass<'tcx> for CompilerLintFunctions {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ if is_lint_allowed(cx, COMPILER_LINT_FUNCTIONS, expr.hir_id) {
+ return;
+ }
+
+ if_chain! {
+ if let ExprKind::MethodCall(path, self_arg, _, _) = &expr.kind;
+ let fn_name = path.ident;
+ if let Some(sugg) = self.map.get(fn_name.as_str());
+ let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
+ if match_type(cx, ty, &paths::EARLY_CONTEXT) || match_type(cx, ty, &paths::LATE_CONTEXT);
+ then {
+ span_lint_and_help(
+ cx,
+ COMPILER_LINT_FUNCTIONS,
+ path.ident.span,
+ "usage of a compiler lint function",
+ None,
+ &format!("please use the Clippy variant of this function: `{sugg}`"),
+ );
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs
new file mode 100644
index 000000000..883a5c08e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/if_chain_style.rs
@@ -0,0 +1,164 @@
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::{higher, is_else_clause, is_expn_of};
+use if_chain::if_chain;
+use rustc_hir as hir;
+use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Local, Node, Stmt, StmtKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{BytePos, Span};
+
+declare_clippy_lint! {
+ /// Finds unidiomatic usage of `if_chain!`
+ pub IF_CHAIN_STYLE,
+ internal,
+ "non-idiomatic `if_chain!` usage"
+}
+
+declare_lint_pass!(IfChainStyle => [IF_CHAIN_STYLE]);
+
+impl<'tcx> LateLintPass<'tcx> for IfChainStyle {
+ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
+ let (local, after, if_chain_span) = if_chain! {
+ if let [Stmt { kind: StmtKind::Local(local), .. }, after @ ..] = block.stmts;
+ if let Some(if_chain_span) = is_expn_of(block.span, "if_chain");
+ then { (local, after, if_chain_span) } else { return }
+ };
+ if is_first_if_chain_expr(cx, block.hir_id, if_chain_span) {
+ span_lint(
+ cx,
+ IF_CHAIN_STYLE,
+ if_chain_local_span(cx, local, if_chain_span),
+ "`let` expression should be above the `if_chain!`",
+ );
+ } else if local.span.ctxt() == block.span.ctxt() && is_if_chain_then(after, block.expr, if_chain_span) {
+ span_lint(
+ cx,
+ IF_CHAIN_STYLE,
+ if_chain_local_span(cx, local, if_chain_span),
+ "`let` expression should be inside `then { .. }`",
+ );
+ }
+ }
+
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+ let (cond, then, els) = if let Some(higher::IfOrIfLet { cond, r#else, then }) = higher::IfOrIfLet::hir(expr) {
+ (cond, then, r#else.is_some())
+ } else {
+ return;
+ };
+ let ExprKind::Block(then_block, _) = then.kind else { return };
+ let if_chain_span = is_expn_of(expr.span, "if_chain");
+ if !els {
+ check_nested_if_chains(cx, expr, then_block, if_chain_span);
+ }
+ let Some(if_chain_span) = if_chain_span else { return };
+ // check for `if a && b;`
+ if_chain! {
+ if let ExprKind::Binary(op, _, _) = cond.kind;
+ if op.node == BinOpKind::And;
+ if cx.sess().source_map().is_multiline(cond.span);
+ then {
+ span_lint(cx, IF_CHAIN_STYLE, cond.span, "`if a && b;` should be `if a; if b;`");
+ }
+ }
+ if is_first_if_chain_expr(cx, expr.hir_id, if_chain_span)
+ && is_if_chain_then(then_block.stmts, then_block.expr, if_chain_span)
+ {
+ span_lint(cx, IF_CHAIN_STYLE, expr.span, "`if_chain!` only has one `if`");
+ }
+ }
+}
+
+fn check_nested_if_chains(
+ cx: &LateContext<'_>,
+ if_expr: &Expr<'_>,
+ then_block: &Block<'_>,
+ if_chain_span: Option<Span>,
+) {
+ #[rustfmt::skip]
+ let (head, tail) = match *then_block {
+ Block { stmts, expr: Some(tail), .. } => (stmts, tail),
+ Block {
+ stmts: &[
+ ref head @ ..,
+ Stmt { kind: StmtKind::Expr(tail) | StmtKind::Semi(tail), .. }
+ ],
+ ..
+ } => (head, tail),
+ _ => return,
+ };
+ if_chain! {
+ if let Some(higher::IfOrIfLet { r#else: None, .. }) = higher::IfOrIfLet::hir(tail);
+ let sm = cx.sess().source_map();
+ if head
+ .iter()
+ .all(|stmt| matches!(stmt.kind, StmtKind::Local(..)) && !sm.is_multiline(stmt.span));
+ if if_chain_span.is_some() || !is_else_clause(cx.tcx, if_expr);
+ then {
+ } else {
+ return;
+ }
+ }
+ let (span, msg) = match (if_chain_span, is_expn_of(tail.span, "if_chain")) {
+ (None, Some(_)) => (if_expr.span, "this `if` can be part of the inner `if_chain!`"),
+ (Some(_), None) => (tail.span, "this `if` can be part of the outer `if_chain!`"),
+ (Some(a), Some(b)) if a != b => (b, "this `if_chain!` can be merged with the outer `if_chain!`"),
+ _ => return,
+ };
+ span_lint_and_then(cx, IF_CHAIN_STYLE, span, msg, |diag| {
+ let (span, msg) = match head {
+ [] => return,
+ [stmt] => (stmt.span, "this `let` statement can also be in the `if_chain!`"),
+ [a, .., b] => (
+ a.span.to(b.span),
+ "these `let` statements can also be in the `if_chain!`",
+ ),
+ };
+ diag.span_help(span, msg);
+ });
+}
+
+fn is_first_if_chain_expr(cx: &LateContext<'_>, hir_id: HirId, if_chain_span: Span) -> bool {
+ cx.tcx
+ .hir()
+ .parent_iter(hir_id)
+ .find(|(_, node)| {
+ #[rustfmt::skip]
+ !matches!(node, Node::Expr(Expr { kind: ExprKind::Block(..), .. }) | Node::Stmt(_))
+ })
+ .map_or(false, |(id, _)| {
+ is_expn_of(cx.tcx.hir().span(id), "if_chain") != Some(if_chain_span)
+ })
+}
+
+/// Checks a trailing slice of statements and expression of a `Block` to see if they are part
+/// of the `then {..}` portion of an `if_chain!`
+fn is_if_chain_then(stmts: &[Stmt<'_>], expr: Option<&Expr<'_>>, if_chain_span: Span) -> bool {
+ let span = if let [stmt, ..] = stmts {
+ stmt.span
+ } else if let Some(expr) = expr {
+ expr.span
+ } else {
+ // empty `then {}`
+ return true;
+ };
+ is_expn_of(span, "if_chain").map_or(true, |span| span != if_chain_span)
+}
+
+/// Creates a `Span` for `let x = ..;` in an `if_chain!` call.
+fn if_chain_local_span(cx: &LateContext<'_>, local: &Local<'_>, if_chain_span: Span) -> Span {
+ let mut span = local.pat.span;
+ if let Some(init) = local.init {
+ span = span.to(init.span);
+ }
+ span.adjust(if_chain_span.ctxt().outer_expn());
+ let sm = cx.sess().source_map();
+ let span = sm.span_extend_to_prev_str(span, "let", false, true).unwrap_or(span);
+ let span = sm.span_extend_to_next_char(span, ';', false);
+ Span::new(
+ span.lo() - BytePos(3),
+ span.hi() + BytePos(1),
+ span.ctxt(),
+ span.parent(),
+ )
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
new file mode 100644
index 000000000..096b60157
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs
@@ -0,0 +1,239 @@
+use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::match_type;
+use clippy_utils::{def_path_res, is_expn_of, match_def_path, paths};
+use if_chain::if_chain;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::mir::interpret::ConstValue;
+use rustc_middle::ty::{self};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::symbol::Symbol;
+
+use std::borrow::Cow;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for interning symbols that have already been pre-interned and defined as constants.
+ ///
+ /// ### Why is this bad?
+ /// It's faster and easier to use the symbol constant.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// let _ = sym!(f32);
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// let _ = sym::f32;
+ /// ```
+ pub INTERNING_DEFINED_SYMBOL,
+ internal,
+ "interning a symbol that is pre-interned and defined as a constant"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for unnecessary conversion from Symbol to a string.
+ ///
+ /// ### Why is this bad?
+ /// It's faster use symbols directly instead of strings.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// symbol.as_str() == "clippy";
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// symbol == sym::clippy;
+ /// ```
+ pub UNNECESSARY_SYMBOL_STR,
+ internal,
+ "unnecessary conversion between Symbol and string"
+}
+
+#[derive(Default)]
+pub struct InterningDefinedSymbol {
+ // Maps the symbol value to the constant DefId.
+ symbol_map: FxHashMap<u32, DefId>,
+}
+
+impl_lint_pass!(InterningDefinedSymbol => [INTERNING_DEFINED_SYMBOL, UNNECESSARY_SYMBOL_STR]);
+
+impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
+ fn check_crate(&mut self, cx: &LateContext<'_>) {
+ if !self.symbol_map.is_empty() {
+ return;
+ }
+
+ for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
+ if let Some(def_id) = def_path_res(cx, module, None).opt_def_id() {
+ 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);
+ 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();
+ then {
+ self.symbol_map.insert(value, item_def_id);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+ if_chain! {
+ if let ExprKind::Call(func, [arg]) = &expr.kind;
+ if let ty::FnDef(def_id, _) = cx.typeck_results().expr_ty(func).kind();
+ if match_def_path(cx, *def_id, &paths::SYMBOL_INTERN);
+ if let Some(Constant::Str(arg)) = constant_simple(cx, cx.typeck_results(), arg);
+ let value = Symbol::intern(&arg).as_u32();
+ if let Some(&def_id) = self.symbol_map.get(&value);
+ then {
+ span_lint_and_sugg(
+ cx,
+ INTERNING_DEFINED_SYMBOL,
+ is_expn_of(expr.span, "sym").unwrap_or(expr.span),
+ "interning a defined symbol",
+ "try",
+ cx.tcx.def_path_str(def_id),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ if let ExprKind::Binary(op, left, right) = expr.kind {
+ if matches!(op.node, BinOpKind::Eq | BinOpKind::Ne) {
+ let data = [
+ (left, self.symbol_str_expr(left, cx)),
+ (right, self.symbol_str_expr(right, cx)),
+ ];
+ match data {
+ // both operands are a symbol string
+ [(_, Some(left)), (_, Some(right))] => {
+ span_lint_and_sugg(
+ cx,
+ UNNECESSARY_SYMBOL_STR,
+ expr.span,
+ "unnecessary `Symbol` to string conversion",
+ "try",
+ format!(
+ "{} {} {}",
+ left.as_symbol_snippet(cx),
+ op.node.as_str(),
+ right.as_symbol_snippet(cx),
+ ),
+ Applicability::MachineApplicable,
+ );
+ },
+ // one of the operands is a symbol string
+ [(expr, Some(symbol)), _] | [_, (expr, Some(symbol))] => {
+ // creating an owned string for comparison
+ if matches!(symbol, SymbolStrExpr::Expr { is_to_owned: true, .. }) {
+ span_lint_and_sugg(
+ cx,
+ UNNECESSARY_SYMBOL_STR,
+ expr.span,
+ "unnecessary string allocation",
+ "try",
+ format!("{}.as_str()", symbol.as_symbol_snippet(cx)),
+ Applicability::MachineApplicable,
+ );
+ }
+ },
+ // nothing found
+ [(_, None), (_, None)] => {},
+ }
+ }
+ }
+ }
+}
+
+impl InterningDefinedSymbol {
+ fn symbol_str_expr<'tcx>(&self, expr: &'tcx Expr<'tcx>, cx: &LateContext<'tcx>) -> Option<SymbolStrExpr<'tcx>> {
+ static IDENT_STR_PATHS: &[&[&str]] = &[&paths::IDENT_AS_STR, &paths::TO_STRING_METHOD];
+ static SYMBOL_STR_PATHS: &[&[&str]] = &[
+ &paths::SYMBOL_AS_STR,
+ &paths::SYMBOL_TO_IDENT_STRING,
+ &paths::TO_STRING_METHOD,
+ ];
+ let call = if_chain! {
+ if let ExprKind::AddrOf(_, _, e) = expr.kind;
+ if let ExprKind::Unary(UnOp::Deref, e) = e.kind;
+ then { e } else { expr }
+ };
+ if_chain! {
+ // is a method call
+ if let ExprKind::MethodCall(_, item, [], _) = call.kind;
+ if let Some(did) = cx.typeck_results().type_dependent_def_id(call.hir_id);
+ let ty = cx.typeck_results().expr_ty(item);
+ // ...on either an Ident or a Symbol
+ if let Some(is_ident) = if match_type(cx, ty, &paths::SYMBOL) {
+ Some(false)
+ } else if match_type(cx, ty, &paths::IDENT) {
+ Some(true)
+ } else {
+ None
+ };
+ // ...which converts it to a string
+ let paths = if is_ident { IDENT_STR_PATHS } else { SYMBOL_STR_PATHS };
+ if let Some(path) = paths.iter().find(|path| match_def_path(cx, did, path));
+ then {
+ let is_to_owned = path.last().unwrap().ends_with("string");
+ return Some(SymbolStrExpr::Expr {
+ item,
+ is_ident,
+ is_to_owned,
+ });
+ }
+ }
+ // is a string constant
+ if let Some(Constant::Str(s)) = constant_simple(cx, cx.typeck_results(), expr) {
+ let value = Symbol::intern(&s).as_u32();
+ // ...which matches a symbol constant
+ if let Some(&def_id) = self.symbol_map.get(&value) {
+ return Some(SymbolStrExpr::Const(def_id));
+ }
+ }
+ None
+ }
+}
+
+enum SymbolStrExpr<'tcx> {
+ /// a string constant with a corresponding symbol constant
+ Const(DefId),
+ /// a "symbol to string" expression like `symbol.as_str()`
+ Expr {
+ /// part that evaluates to `Symbol` or `Ident`
+ item: &'tcx Expr<'tcx>,
+ is_ident: bool,
+ /// whether an owned `String` is created like `to_ident_string()`
+ is_to_owned: bool,
+ },
+}
+
+impl<'tcx> SymbolStrExpr<'tcx> {
+ /// Returns a snippet that evaluates to a `Symbol` and is const if possible
+ fn as_symbol_snippet(&self, cx: &LateContext<'_>) -> Cow<'tcx, str> {
+ match *self {
+ Self::Const(def_id) => cx.tcx.def_path_str(def_id).into(),
+ Self::Expr { item, is_ident, .. } => {
+ let mut snip = snippet(cx, item.span.source_callsite(), "..");
+ if is_ident {
+ // get `Ident.name`
+ snip.to_mut().push_str(".name");
+ }
+ snip
+ },
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
new file mode 100644
index 000000000..25532dd4e
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/invalid_paths.rs
@@ -0,0 +1,108 @@
+use clippy_utils::consts::{constant_simple, Constant};
+use clippy_utils::def_path_res;
+use clippy_utils::diagnostics::span_lint;
+use if_chain::if_chain;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::Item;
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, fast_reject::SimplifiedTypeGen, FloatTy};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::Symbol;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks the paths module for invalid paths.
+ ///
+ /// ### Why is this bad?
+ /// It indicates a bug in the code.
+ ///
+ /// ### Example
+ /// None.
+ pub INVALID_PATHS,
+ internal,
+ "invalid path"
+}
+
+declare_lint_pass!(InvalidPaths => [INVALID_PATHS]);
+
+impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+ let local_def_id = &cx.tcx.parent_module(item.hir_id());
+ let mod_name = &cx.tcx.item_name(local_def_id.to_def_id());
+ if_chain! {
+ if mod_name.as_str() == "paths";
+ if let hir::ItemKind::Const(ty, body_id) = item.kind;
+ let ty = hir_ty_to_ty(cx.tcx, ty);
+ if let ty::Array(el_ty, _) = &ty.kind();
+ if let ty::Ref(_, el_ty, _) = &el_ty.kind();
+ if el_ty.is_str();
+ let body = cx.tcx.hir().body(body_id);
+ let typeck_results = cx.tcx.typeck_body(body_id);
+ if let Some(Constant::Vec(path)) = constant_simple(cx, typeck_results, body.value);
+ let path: Vec<&str> = path
+ .iter()
+ .map(|x| {
+ if let Constant::Str(s) = x {
+ s.as_str()
+ } else {
+ // We checked the type of the constant above
+ unreachable!()
+ }
+ })
+ .collect();
+ if !check_path(cx, &path[..]);
+ then {
+ span_lint(cx, INVALID_PATHS, item.span, "invalid path");
+ }
+ }
+ }
+}
+
+// This is not a complete resolver for paths. It works on all the paths currently used in the paths
+// module. That's all it does and all it needs to do.
+pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
+ if def_path_res(cx, path, None) != Res::Err {
+ return true;
+ }
+
+ // Some implementations can't be found by `path_to_res`, particularly inherent
+ // implementations of native types. Check lang items.
+ let path_syms: Vec<_> = path.iter().map(|p| Symbol::intern(p)).collect();
+ let lang_items = cx.tcx.lang_items();
+ // This list isn't complete, but good enough for our current list of paths.
+ let incoherent_impls = [
+ SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F32),
+ SimplifiedTypeGen::FloatSimplifiedType(FloatTy::F64),
+ SimplifiedTypeGen::SliceSimplifiedType,
+ SimplifiedTypeGen::StrSimplifiedType,
+ ]
+ .iter()
+ .flat_map(|&ty| cx.tcx.incoherent_impls(ty));
+ for item_def_id in lang_items.items().iter().flatten().chain(incoherent_impls) {
+ let lang_item_path = cx.get_def_path(*item_def_id);
+ if path_syms.starts_with(&lang_item_path) {
+ if let [item] = &path_syms[lang_item_path.len()..] {
+ if matches!(
+ cx.tcx.def_kind(*item_def_id),
+ DefKind::Mod | DefKind::Enum | DefKind::Trait
+ ) {
+ for child in cx.tcx.module_children(*item_def_id) {
+ if child.ident.name == *item {
+ return true;
+ }
+ }
+ } else {
+ for child in cx.tcx.associated_item_def_ids(*item_def_id) {
+ if cx.tcx.item_name(*child) == *item {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ false
+}
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
new file mode 100644
index 000000000..0dac64376
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/lint_without_lint_pass.rs
@@ -0,0 +1,342 @@
+use crate::utils::internal_lints::metadata_collector::is_deprecated_lint;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::macros::root_macro_call_first_node;
+use clippy_utils::{is_lint_allowed, match_def_path, paths};
+use if_chain::if_chain;
+use rustc_ast as ast;
+use rustc_ast::ast::LitKind;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::hir_id::CRATE_HIR_ID;
+use rustc_hir::intravisit::Visitor;
+use rustc_hir::{ExprKind, HirId, Item, MutTy, Mutability, Path, TyKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::hir::nested_filter;
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::Symbol;
+use rustc_span::{sym, Span};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Ensures every lint is associated to a `LintPass`.
+ ///
+ /// ### Why is this bad?
+ /// The compiler only knows lints via a `LintPass`. Without
+ /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
+ /// know the name of the lint.
+ ///
+ /// ### Known problems
+ /// Only checks for lints associated using the
+ /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// declare_lint! { pub LINT_1, ... }
+ /// declare_lint! { pub LINT_2, ... }
+ /// declare_lint! { pub FORGOTTEN_LINT, ... }
+ /// // ...
+ /// declare_lint_pass!(Pass => [LINT_1, LINT_2]);
+ /// // missing FORGOTTEN_LINT
+ /// ```
+ pub LINT_WITHOUT_LINT_PASS,
+ internal,
+ "declaring a lint without associating it in a LintPass"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for cases of an auto-generated lint without an updated description,
+ /// i.e. `default lint description`.
+ ///
+ /// ### Why is this bad?
+ /// Indicates that the lint is not finished.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// declare_lint! { pub COOL_LINT, nursery, "default lint description" }
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// declare_lint! { pub COOL_LINT, nursery, "a great new lint" }
+ /// ```
+ pub DEFAULT_LINT,
+ internal,
+ "found 'default lint description' in a lint declaration"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for invalid `clippy::version` attributes.
+ ///
+ /// Valid values are:
+ /// * "pre 1.29.0"
+ /// * any valid semantic version
+ pub INVALID_CLIPPY_VERSION_ATTRIBUTE,
+ internal,
+ "found an invalid `clippy::version` attribute"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for declared clippy lints without the `clippy::version` attribute.
+ ///
+ pub MISSING_CLIPPY_VERSION_ATTRIBUTE,
+ internal,
+ "found clippy lint without `clippy::version` attribute"
+}
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for cases of an auto-generated deprecated lint without an updated reason,
+ /// i.e. `"default deprecation note"`.
+ ///
+ /// ### Why is this bad?
+ /// Indicates that the documentation is incomplete.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// declare_deprecated_lint! {
+ /// /// ### What it does
+ /// /// Nothing. This lint has been deprecated.
+ /// ///
+ /// /// ### Deprecation reason
+ /// /// TODO
+ /// #[clippy::version = "1.63.0"]
+ /// pub COOL_LINT,
+ /// "default deprecation note"
+ /// }
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// declare_deprecated_lint! {
+ /// /// ### What it does
+ /// /// Nothing. This lint has been deprecated.
+ /// ///
+ /// /// ### Deprecation reason
+ /// /// This lint has been replaced by `cooler_lint`
+ /// #[clippy::version = "1.63.0"]
+ /// pub COOL_LINT,
+ /// "this lint has been replaced by `cooler_lint`"
+ /// }
+ /// ```
+ pub DEFAULT_DEPRECATION_REASON,
+ internal,
+ "found 'default deprecation note' in a deprecated lint declaration"
+}
+
+#[derive(Clone, Debug, Default)]
+pub struct LintWithoutLintPass {
+ declared_lints: FxHashMap<Symbol, Span>,
+ registered_lints: FxHashSet<Symbol>,
+}
+
+impl_lint_pass!(LintWithoutLintPass => [DEFAULT_LINT, LINT_WITHOUT_LINT_PASS, INVALID_CLIPPY_VERSION_ATTRIBUTE, MISSING_CLIPPY_VERSION_ATTRIBUTE, DEFAULT_DEPRECATION_REASON]);
+
+impl<'tcx> LateLintPass<'tcx> for LintWithoutLintPass {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
+ if is_lint_allowed(cx, DEFAULT_LINT, item.hir_id())
+ || is_lint_allowed(cx, DEFAULT_DEPRECATION_REASON, item.hir_id())
+ {
+ return;
+ }
+
+ if let hir::ItemKind::Static(ty, Mutability::Not, body_id) = item.kind {
+ let is_lint_ref_ty = is_lint_ref_type(cx, ty);
+ if is_deprecated_lint(cx, ty) || is_lint_ref_ty {
+ check_invalid_clippy_version_attribute(cx, item);
+
+ let expr = &cx.tcx.hir().body(body_id).value;
+ let fields;
+ if is_lint_ref_ty {
+ if let ExprKind::AddrOf(_, _, inner_exp) = expr.kind
+ && let ExprKind::Struct(_, struct_fields, _) = inner_exp.kind {
+ fields = struct_fields;
+ } else {
+ return;
+ }
+ } else if let ExprKind::Struct(_, struct_fields, _) = expr.kind {
+ fields = struct_fields;
+ } else {
+ return;
+ }
+
+ let field = fields
+ .iter()
+ .find(|f| f.ident.as_str() == "desc")
+ .expect("lints must have a description field");
+
+ if let ExprKind::Lit(Spanned {
+ node: LitKind::Str(ref sym, _),
+ ..
+ }) = field.expr.kind
+ {
+ let sym_str = sym.as_str();
+ if is_lint_ref_ty {
+ if sym_str == "default lint description" {
+ span_lint(
+ cx,
+ DEFAULT_LINT,
+ item.span,
+ &format!("the lint `{}` has the default lint description", item.ident.name),
+ );
+ }
+
+ self.declared_lints.insert(item.ident.name, item.span);
+ } else if sym_str == "default deprecation note" {
+ span_lint(
+ cx,
+ DEFAULT_DEPRECATION_REASON,
+ item.span,
+ &format!("the lint `{}` has the default deprecation reason", item.ident.name),
+ );
+ }
+ }
+ }
+ } else if let Some(macro_call) = root_macro_call_first_node(cx, item) {
+ if !matches!(
+ cx.tcx.item_name(macro_call.def_id).as_str(),
+ "impl_lint_pass" | "declare_lint_pass"
+ ) {
+ return;
+ }
+ if let hir::ItemKind::Impl(hir::Impl {
+ of_trait: None,
+ items: impl_item_refs,
+ ..
+ }) = item.kind
+ {
+ let mut collector = LintCollector {
+ output: &mut self.registered_lints,
+ 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(),
+ ),
+ );
+ collector.visit_expr(cx.tcx.hir().body(body_id).value);
+ }
+ }
+ }
+
+ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
+ if is_lint_allowed(cx, LINT_WITHOUT_LINT_PASS, CRATE_HIR_ID) {
+ return;
+ }
+
+ for (lint_name, &lint_span) in &self.declared_lints {
+ // When using the `declare_tool_lint!` macro, the original `lint_span`'s
+ // file points to "<rustc macros>".
+ // `compiletest-rs` thinks that's an error in a different file and
+ // just ignores it. This causes the test in compile-fail/lint_pass
+ // not able to capture the error.
+ // Therefore, we need to climb the macro expansion tree and find the
+ // actual span that invoked `declare_tool_lint!`:
+ let lint_span = lint_span.ctxt().outer_expn_data().call_site;
+
+ if !self.registered_lints.contains(lint_name) {
+ span_lint(
+ cx,
+ LINT_WITHOUT_LINT_PASS,
+ lint_span,
+ &format!("the lint `{lint_name}` is not added to any `LintPass`"),
+ );
+ }
+ }
+ }
+}
+
+pub(super) fn is_lint_ref_type<'tcx>(cx: &LateContext<'tcx>, ty: &hir::Ty<'_>) -> bool {
+ if let TyKind::Rptr(
+ _,
+ MutTy {
+ ty: inner,
+ mutbl: Mutability::Not,
+ },
+ ) = ty.kind
+ {
+ if let TyKind::Path(ref path) = inner.kind {
+ if let Res::Def(DefKind::Struct, def_id) = cx.qpath_res(path, inner.hir_id) {
+ return match_def_path(cx, def_id, &paths::LINT);
+ }
+ }
+ }
+
+ false
+}
+
+fn check_invalid_clippy_version_attribute(cx: &LateContext<'_>, item: &'_ Item<'_>) {
+ if let Some(value) = extract_clippy_version_value(cx, item) {
+ // The `sym!` macro doesn't work as it only expects a single token.
+ // It's better to keep it this way and have a direct `Symbol::intern` call here.
+ if value == Symbol::intern("pre 1.29.0") {
+ return;
+ }
+
+ if RustcVersion::parse(value.as_str()).is_err() {
+ span_lint_and_help(
+ cx,
+ INVALID_CLIPPY_VERSION_ATTRIBUTE,
+ item.span,
+ "this item has an invalid `clippy::version` attribute",
+ None,
+ "please use a valid semantic version, see `doc/adding_lints.md`",
+ );
+ }
+ } else {
+ span_lint_and_help(
+ cx,
+ MISSING_CLIPPY_VERSION_ATTRIBUTE,
+ item.span,
+ "this lint is missing the `clippy::version` attribute or version value",
+ None,
+ "please use a `clippy::version` attribute, see `doc/adding_lints.md`",
+ );
+ }
+}
+
+/// This function extracts the version value of a `clippy::version` attribute if the given value has
+/// one
+pub(super) fn extract_clippy_version_value(cx: &LateContext<'_>, item: &'_ Item<'_>) -> Option<Symbol> {
+ let attrs = cx.tcx.hir().attrs(item.hir_id());
+ attrs.iter().find_map(|attr| {
+ if_chain! {
+ // Identify attribute
+ if let ast::AttrKind::Normal(ref attr_kind) = &attr.kind;
+ if let [tool_name, attr_name] = &attr_kind.item.path.segments[..];
+ if tool_name.ident.name == sym::clippy;
+ if attr_name.ident.name == sym::version;
+ if let Some(version) = attr.value_str();
+ then { Some(version) } else { None }
+ }
+ })
+}
+
+struct LintCollector<'a, 'tcx> {
+ output: &'a mut FxHashSet<Symbol>,
+ cx: &'a LateContext<'tcx>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
+ type NestedFilter = nested_filter::All;
+
+ fn visit_path(&mut self, path: &'tcx Path<'_>, _: HirId) {
+ if path.segments.len() == 1 {
+ self.output.insert(path.segments[0].ident.name);
+ }
+ }
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+}
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 342f627e3..d06a616e4 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
@@ -8,7 +8,7 @@
//! a simple mistake)
use crate::renamed_lints::RENAMED_LINTS;
-use crate::utils::internal_lints::{extract_clippy_version_value, is_lint_ref_type};
+use crate::utils::internal_lints::lint_without_lint_pass::{extract_clippy_version_value, is_lint_ref_type};
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::{match_type, walk_ptrs_ty_depth};
@@ -64,46 +64,6 @@ const DEFAULT_LINT_LEVELS: &[(&str, &str)] = &[
/// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
/// to only keep the actual lint group in the output.
const CLIPPY_LINT_GROUP_PREFIX: &str = "clippy::";
-
-/// This template will be used to format the configuration section in the lint documentation.
-/// The `configurations` parameter will be replaced with one or multiple formatted
-/// `ClippyConfiguration` instances. See `CONFIGURATION_VALUE_TEMPLATE` for further customizations
-macro_rules! CONFIGURATION_SECTION_TEMPLATE {
- () => {
- r#"
-### Configuration
-This lint has the following configuration variables:
-
-{configurations}
-"#
- };
-}
-/// This template will be used to format an individual `ClippyConfiguration` instance in the
-/// lint documentation.
-///
-/// The format function will provide strings for the following parameters: `name`, `ty`, `doc` and
-/// `default`
-macro_rules! CONFIGURATION_VALUE_TEMPLATE {
- () => {
- "* `{name}`: `{ty}`: {doc} (defaults to `{default}`)\n"
- };
-}
-
-macro_rules! RENAMES_SECTION_TEMPLATE {
- () => {
- r#"
-### Past names
-
-{names}
-"#
- };
-}
-macro_rules! RENAME_VALUE_TEMPLATE {
- () => {
- "* `{name}`\n"
- };
-}
-
const LINT_EMISSION_FUNCTIONS: [&[&str]; 7] = [
&["clippy_utils", "diagnostics", "span_lint"],
&["clippy_utils", "diagnostics", "span_lint_and_help"],
@@ -205,7 +165,16 @@ impl MetadataCollector {
.filter(|config| config.lints.iter().any(|lint| lint == lint_name))
.map(ToString::to_string)
.reduce(|acc, x| acc + &x)
- .map(|configurations| format!(CONFIGURATION_SECTION_TEMPLATE!(), configurations = configurations))
+ .map(|configurations| {
+ format!(
+ r#"
+### Configuration
+This lint has the following configuration variables:
+
+{configurations}
+"#
+ )
+ })
}
}
@@ -291,16 +260,13 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
continue;
}
- panic!("lint `{}` has an unterminated code block", lint_name)
+ panic!("lint `{lint_name}` has an unterminated code block")
}
break;
},
Some(line) if line.trim_start() == "{{produces}}" => {
- panic!(
- "lint `{}` has marker {{{{produces}}}} with an ignored or missing code block",
- lint_name
- )
+ panic!("lint `{lint_name}` has marker {{{{produces}}}} with an ignored or missing code block")
},
Some(line) => {
let line = line.trim();
@@ -319,7 +285,7 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
match lines.next() {
Some(line) if line.trim_start() == "```" => break,
Some(line) => example.push(line),
- None => panic!("lint `{}` has an unterminated code block", lint_name),
+ None => panic!("lint `{lint_name}` has an unterminated code block"),
}
}
@@ -336,10 +302,9 @@ fn replace_produces(lint_name: &str, docs: &mut String, clippy_project_root: &Pa
<summary>Produces</summary>\n\
\n\
```text\n\
- {}\n\
+ {output}\n\
```\n\
- </details>",
- output
+ </details>"
),
);
@@ -394,7 +359,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
panic!("failed to write to `{}`: {e}", file.as_path().to_string_lossy());
}
- let prefixed_name = format!("{}{lint_name}", CLIPPY_LINT_GROUP_PREFIX);
+ let prefixed_name = format!("{CLIPPY_LINT_GROUP_PREFIX}{lint_name}");
let mut cmd = Command::new("cargo");
@@ -417,7 +382,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
let output = cmd
.arg(file.as_path())
.output()
- .unwrap_or_else(|e| panic!("failed to run `{:?}`: {e}", cmd));
+ .unwrap_or_else(|e| panic!("failed to run `{cmd:?}`: {e}"));
let tmp_file_path = file.to_string_lossy();
let stderr = std::str::from_utf8(&output.stderr).unwrap();
@@ -441,8 +406,7 @@ fn get_lint_output(lint_name: &str, example: &[&mut String], clippy_project_root
let rendered: Vec<&str> = msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> = stderr.lines().filter(|line| !line.starts_with('{')).collect();
panic!(
- "did not find lint `{}` in output of example, got:\n{}\n{}",
- lint_name,
+ "did not find lint `{lint_name}` in output of example, got:\n{}\n{}",
non_json.join("\n"),
rendered.join("\n")
);
@@ -568,7 +532,11 @@ fn parse_config_field_doc(doc_comment: &str) -> Option<(Vec<String>, String)> {
// Extract lints
doc_comment.make_ascii_lowercase();
- let lints: Vec<String> = doc_comment.split_off(DOC_START.len()).split(", ").map(str::to_string).collect();
+ let lints: Vec<String> = doc_comment
+ .split_off(DOC_START.len())
+ .split(", ")
+ .map(str::to_string)
+ .collect();
// Format documentation correctly
// split off leading `.` from lint name list and indent for correct formatting
@@ -588,13 +556,10 @@ fn to_kebab(config_name: &str) -> String {
impl fmt::Display for ClippyConfiguration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
- write!(
+ writeln!(
f,
- CONFIGURATION_VALUE_TEMPLATE!(),
- name = self.name,
- ty = self.config_type,
- doc = self.doc,
- default = self.default
+ "* `{}`: `{}`: {} (defaults to `{}`)",
+ self.name, self.config_type, self.doc, self.default
)
}
}
@@ -811,7 +776,7 @@ fn get_lint_group_and_level_or_lint(
lint_collection_error_item(
cx,
item,
- &format!("Unable to determine lint level for found group `{}`", group),
+ &format!("Unable to determine lint level for found group `{group}`"),
);
None
}
@@ -869,7 +834,7 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
if name == lint_name;
if let Some(past_name) = k.strip_prefix(CLIPPY_LINT_GROUP_PREFIX);
then {
- write!(collected, RENAME_VALUE_TEMPLATE!(), name = past_name).unwrap();
+ writeln!(collected, "* `{past_name}`").unwrap();
names.push(past_name.to_string());
}
}
@@ -882,7 +847,15 @@ fn collect_renames(lints: &mut Vec<LintMetadata>) {
}
if !collected.is_empty() {
- write!(&mut lint.docs, RENAMES_SECTION_TEMPLATE!(), names = collected).unwrap();
+ write!(
+ &mut lint.docs,
+ r#"
+### Past names
+
+{collected}
+"#
+ )
+ .unwrap();
}
}
}
@@ -895,7 +868,7 @@ fn lint_collection_error_item(cx: &LateContext<'_>, item: &Item<'_>, message: &s
cx,
INTERNAL_METADATA_COLLECTOR,
item.ident.span,
- &format!("metadata collection error for `{}`: {}", item.ident.name, message),
+ &format!("metadata collection error for `{}`: {message}", item.ident.name),
);
}
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
new file mode 100644
index 000000000..1e994e3f2
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/msrv_attr_impl.rs
@@ -0,0 +1,63 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::match_type;
+use clippy_utils::{match_def_path, paths};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir_analysis::hir_ty_to_ty;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::ty::{self, subst::GenericArgKind};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Check that the `extract_msrv_attr!` macro is used, when a lint has a MSRV.
+ ///
+ pub MISSING_MSRV_ATTR_IMPL,
+ internal,
+ "checking if all necessary steps were taken when adding a MSRV to a lint"
+}
+
+declare_lint_pass!(MsrvAttrImpl => [MISSING_MSRV_ATTR_IMPL]);
+
+impl LateLintPass<'_> for MsrvAttrImpl {
+ fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
+ if_chain! {
+ if let hir::ItemKind::Impl(hir::Impl {
+ of_trait: Some(lint_pass_trait_ref),
+ self_ty,
+ items,
+ ..
+ }) = &item.kind;
+ if let Some(lint_pass_trait_def_id) = lint_pass_trait_ref.trait_def_id();
+ let is_late_pass = match_def_path(cx, lint_pass_trait_def_id, &paths::LATE_LINT_PASS);
+ if is_late_pass || match_def_path(cx, lint_pass_trait_def_id, &paths::EARLY_LINT_PASS);
+ let self_ty = hir_ty_to_ty(cx.tcx, self_ty);
+ if let ty::Adt(self_ty_def, _) = self_ty.kind();
+ if self_ty_def.is_struct();
+ if self_ty_def.all_fields().any(|f| {
+ cx.tcx
+ .type_of(f.did)
+ .walk()
+ .filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
+ .any(|t| match_type(cx, t.expect_ty(), &paths::RUSTC_VERSION))
+ });
+ if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs));
+ then {
+ let context = if is_late_pass { "LateContext" } else { "EarlyContext" };
+ let lint_pass = if is_late_pass { "LateLintPass" } else { "EarlyLintPass" };
+ let span = cx.sess().source_map().span_through_char(item.span, '{');
+ span_lint_and_sugg(
+ cx,
+ MISSING_MSRV_ATTR_IMPL,
+ span,
+ &format!("`extract_msrv_attr!` macro missing from `{lint_pass}` implementation"),
+ &format!("add `extract_msrv_attr!({context})` to the `{lint_pass}` implementation"),
+ format!("{}\n extract_msrv_attr!({context});", snippet(cx, span, "..")),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
new file mode 100644
index 000000000..2b13fad80
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/outer_expn_data_pass.rs
@@ -0,0 +1,62 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::ty::match_type;
+use clippy_utils::{is_lint_allowed, method_calls, paths};
+use if_chain::if_chain;
+use rustc_errors::Applicability;
+use rustc_hir as hir;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::symbol::Symbol;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for calls to `cx.outer().expn_data()` and suggests to use
+ /// the `cx.outer_expn_data()`
+ ///
+ /// ### Why is this bad?
+ /// `cx.outer_expn_data()` is faster and more concise.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// expr.span.ctxt().outer().expn_data()
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// expr.span.ctxt().outer_expn_data()
+ /// ```
+ pub OUTER_EXPN_EXPN_DATA,
+ internal,
+ "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`"
+}
+
+declare_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);
+
+impl<'tcx> LateLintPass<'tcx> for OuterExpnDataPass {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+ if is_lint_allowed(cx, OUTER_EXPN_EXPN_DATA, expr.hir_id) {
+ return;
+ }
+
+ let (method_names, arg_lists, spans) = method_calls(expr, 2);
+ let method_names: Vec<&str> = method_names.iter().map(Symbol::as_str).collect();
+ if_chain! {
+ if let ["expn_data", "outer_expn"] = method_names.as_slice();
+ let (self_arg, args) = arg_lists[1];
+ if args.is_empty();
+ let self_ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
+ if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
+ then {
+ span_lint_and_sugg(
+ cx,
+ OUTER_EXPN_EXPN_DATA,
+ spans[1].with_hi(expr.span.hi()),
+ "usage of `outer_expn().expn_data()`",
+ "try",
+ "outer_expn_data()".to_string(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs
new file mode 100644
index 000000000..5899b94e1
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/produce_ice.rs
@@ -0,0 +1,37 @@
+use rustc_ast::ast::NodeId;
+use rustc_ast::visit::FnKind;
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::Span;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Not an actual lint. This lint is only meant for testing our customized internal compiler
+ /// error message by calling `panic`.
+ ///
+ /// ### Why is this bad?
+ /// ICE in large quantities can damage your teeth
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// 🍦🍦🍦🍦🍦
+ /// ```
+ pub PRODUCE_ICE,
+ internal,
+ "this message should not appear anywhere as we ICE before and don't emit the lint"
+}
+
+declare_lint_pass!(ProduceIce => [PRODUCE_ICE]);
+
+impl EarlyLintPass for ProduceIce {
+ fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: Span, _: NodeId) {
+ assert!(!is_trigger_fn(fn_kind), "Would you like some help with that?");
+ }
+}
+
+fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool {
+ match fn_kind {
+ FnKind::Fn(_, ident, ..) => ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy",
+ FnKind::Closure(..) => false,
+ }
+}
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
new file mode 100644
index 000000000..4cf76f536
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -0,0 +1,343 @@
+use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
+use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{def_path_res, 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_errors::Applicability;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Namespace, Res};
+use rustc_hir::def_id::DefId;
+use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
+use rustc_middle::ty::{self, AssocKind, DefIdTree, Ty};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::Span;
+
+use std::str;
+
+declare_clippy_lint! {
+ /// ### What it does
+ /// Checks for usages of def paths when a diagnostic item or a `LangItem` could be used.
+ ///
+ /// ### Why is this bad?
+ /// The path for an item is subject to change and is less efficient to look up than a
+ /// diagnostic item or a `LangItem`.
+ ///
+ /// ### Example
+ /// ```rust,ignore
+ /// utils::match_type(cx, ty, &paths::VEC)
+ /// ```
+ ///
+ /// Use instead:
+ /// ```rust,ignore
+ /// utils::is_type_diagnostic_item(cx, ty, sym::Vec)
+ /// ```
+ pub UNNECESSARY_DEF_PATH,
+ internal,
+ "using a def path when a diagnostic item or a `LangItem` is available"
+}
+
+impl_lint_pass!(UnnecessaryDefPath => [UNNECESSARY_DEF_PATH]);
+
+#[derive(Default)]
+pub struct UnnecessaryDefPath {
+ array_def_ids: FxHashSet<(DefId, Span)>,
+ linted_def_ids: FxHashSet<DefId>,
+}
+
+impl<'tcx> LateLintPass<'tcx> for UnnecessaryDefPath {
+ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+ if is_lint_allowed(cx, UNNECESSARY_DEF_PATH, expr.hir_id) {
+ return;
+ }
+
+ match expr.kind {
+ ExprKind::Call(func, args) => self.check_call(cx, func, args, expr.span),
+ ExprKind::Array(elements) => self.check_array(cx, elements, expr.span),
+ _ => {},
+ }
+ }
+
+ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
+ for &(def_id, span) in &self.array_def_ids {
+ if self.linted_def_ids.contains(&def_id) {
+ continue;
+ }
+
+ let (msg, sugg) = if let Some(sym) = cx.tcx.get_diagnostic_name(def_id) {
+ ("diagnostic item", format!("sym::{sym}"))
+ } else if let Some(sym) = get_lang_item_name(cx, def_id) {
+ ("language item", format!("LangItem::{sym}"))
+ } else {
+ continue;
+ };
+
+ span_lint_and_help(
+ cx,
+ UNNECESSARY_DEF_PATH,
+ span,
+ &format!("hardcoded path to a {msg}"),
+ None,
+ &format!("convert all references to use `{sugg}`"),
+ );
+ }
+ }
+}
+
+impl UnnecessaryDefPath {
+ #[allow(clippy::too_many_lines)]
+ fn check_call(&mut self, cx: &LateContext<'_>, func: &Expr<'_>, args: &[Expr<'_>], span: Span) {
+ enum Item {
+ LangItem(Symbol),
+ DiagnosticItem(Symbol),
+ }
+ static PATHS: &[&[&str]] = &[
+ &["clippy_utils", "match_def_path"],
+ &["clippy_utils", "match_trait_method"],
+ &["clippy_utils", "ty", "match_type"],
+ &["clippy_utils", "is_expr_path_def_path"],
+ ];
+
+ if_chain! {
+ if let [cx_arg, def_arg, args @ ..] = args;
+ if let ExprKind::Path(path) = &func.kind;
+ if let Some(id) = cx.qpath_res(path, func.hir_id).opt_def_id();
+ if let Some(which_path) = match_any_def_paths(cx, id, PATHS);
+ let item_arg = if which_path == 4 { &args[1] } else { &args[0] };
+ // Extract the path to the matched type
+ if let Some(segments) = path_to_matched_type(cx, item_arg);
+ let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
+ if let Some(def_id) = inherent_def_path_res(cx, &segments[..]);
+ then {
+ // Check if the target item is a diagnostic item or LangItem.
+ #[rustfmt::skip]
+ let (msg, item) = if let Some(item_name)
+ = cx.tcx.diagnostic_items(def_id.krate).id_to_name.get(&def_id)
+ {
+ (
+ "use of a def path to a diagnostic item",
+ Item::DiagnosticItem(*item_name),
+ )
+ } else if let Some(item_name) = get_lang_item_name(cx, def_id) {
+ (
+ "use of a def path to a `LangItem`",
+ Item::LangItem(item_name),
+ )
+ } else {
+ return;
+ };
+
+ let has_ctor = match cx.tcx.def_kind(def_id) {
+ DefKind::Struct => {
+ let variant = cx.tcx.adt_def(def_id).non_enum_variant();
+ variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
+ },
+ DefKind::Variant => {
+ let variant = cx.tcx.adt_def(cx.tcx.parent(def_id)).variant_with_id(def_id);
+ variant.ctor_def_id.is_some() && variant.fields.iter().all(|f| f.vis.is_public())
+ },
+ _ => false,
+ };
+
+ let mut app = Applicability::MachineApplicable;
+ let cx_snip = snippet_with_applicability(cx, cx_arg.span, "..", &mut app);
+ let def_snip = snippet_with_applicability(cx, def_arg.span, "..", &mut app);
+ let (sugg, with_note) = match (which_path, item) {
+ // match_def_path
+ (0, Item::DiagnosticItem(item)) => (
+ format!("{cx_snip}.tcx.is_diagnostic_item(sym::{item}, {def_snip})"),
+ has_ctor,
+ ),
+ (0, Item::LangItem(item)) => (
+ format!("{cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some({def_snip})"),
+ has_ctor,
+ ),
+ // match_trait_method
+ (1, Item::DiagnosticItem(item)) => {
+ (format!("is_trait_method({cx_snip}, {def_snip}, sym::{item})"), false)
+ },
+ // match_type
+ (2, Item::DiagnosticItem(item)) => (
+ format!("is_type_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"),
+ false,
+ ),
+ (2, Item::LangItem(item)) => (
+ format!("is_type_lang_item({cx_snip}, {def_snip}, LangItem::{item})"),
+ false,
+ ),
+ // is_expr_path_def_path
+ (3, Item::DiagnosticItem(item)) if has_ctor => (
+ format!("is_res_diag_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), sym::{item})",),
+ false,
+ ),
+ (3, Item::LangItem(item)) if has_ctor => (
+ format!("is_res_lang_ctor({cx_snip}, path_res({cx_snip}, {def_snip}), LangItem::{item})",),
+ false,
+ ),
+ (3, Item::DiagnosticItem(item)) => (
+ format!("is_path_diagnostic_item({cx_snip}, {def_snip}, sym::{item})"),
+ false,
+ ),
+ (3, Item::LangItem(item)) => (
+ format!(
+ "path_res({cx_snip}, {def_snip}).opt_def_id()\
+ .map_or(false, |id| {cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some(id))",
+ ),
+ false,
+ ),
+ _ => return,
+ };
+
+ span_lint_and_then(cx, UNNECESSARY_DEF_PATH, span, msg, |diag| {
+ diag.span_suggestion(span, "try", sugg, app);
+ if with_note {
+ diag.help(
+ "if this `DefId` came from a constructor expression or pattern then the \
+ parent `DefId` should be used instead",
+ );
+ }
+ });
+
+ self.linted_def_ids.insert(def_id);
+ }
+ }
+ }
+
+ fn check_array(&mut self, cx: &LateContext<'_>, elements: &[Expr<'_>], span: Span) {
+ let Some(path) = path_from_array(elements) else { return };
+
+ if let Some(def_id) = inherent_def_path_res(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
+ self.array_def_ids.insert((def_id, span));
+ }
+ }
+}
+
+fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Vec<String>> {
+ match peel_hir_expr_refs(expr).0.kind {
+ ExprKind::Path(ref qpath) => match cx.qpath_res(qpath, expr.hir_id) {
+ Res::Local(hir_id) => {
+ let parent_id = cx.tcx.hir().get_parent_node(hir_id);
+ if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) {
+ path_to_matched_type(cx, init)
+ } else {
+ None
+ }
+ },
+ 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),
+ ),
+ 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))
+ },
+ _ => None,
+ },
+ _ => None,
+ },
+ ExprKind::Array(exprs) => path_from_array(exprs),
+ _ => None,
+ }
+}
+
+fn read_mir_alloc_def_path<'tcx>(cx: &LateContext<'tcx>, alloc: &'tcx Allocation, ty: Ty<'_>) -> Option<Vec<String>> {
+ let (alloc, ty) = if let ty::Ref(_, ty, Mutability::Not) = *ty.kind() {
+ let &alloc = alloc.provenance().values().next()?;
+ if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
+ (alloc.inner(), ty)
+ } else {
+ return None;
+ }
+ } else {
+ (alloc, ty)
+ };
+
+ if let ty::Array(ty, _) | ty::Slice(ty) = *ty.kind()
+ && let ty::Ref(_, ty, Mutability::Not) = *ty.kind()
+ && ty.is_str()
+ {
+ alloc
+ .provenance()
+ .values()
+ .map(|&alloc| {
+ if let GlobalAlloc::Memory(alloc) = cx.tcx.global_alloc(alloc) {
+ let alloc = alloc.inner();
+ str::from_utf8(alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()))
+ .ok().map(ToOwned::to_owned)
+ } else {
+ None
+ }
+ })
+ .collect()
+ } else {
+ None
+ }
+}
+
+fn path_from_array(exprs: &[Expr<'_>]) -> Option<Vec<String>> {
+ exprs
+ .iter()
+ .map(|expr| {
+ if let ExprKind::Lit(lit) = &expr.kind {
+ if let LitKind::Str(sym, _) = lit.node {
+ return Some((*sym.as_str()).to_owned());
+ }
+ }
+
+ None
+ })
+ .collect()
+}
+
+// def_path_res will match field names before anything else, but for this we want to match
+// inherent functions first.
+fn inherent_def_path_res(cx: &LateContext<'_>, segments: &[&str]) -> Option<DefId> {
+ def_path_res(cx, segments, None).opt_def_id().map(|def_id| {
+ if cx.tcx.def_kind(def_id) == DefKind::Field {
+ let method_name = *segments.last().unwrap();
+ cx.tcx
+ .def_key(def_id)
+ .parent
+ .and_then(|parent_idx| {
+ cx.tcx
+ .inherent_impls(DefId {
+ index: parent_idx,
+ krate: def_id.krate,
+ })
+ .iter()
+ .find_map(|impl_id| {
+ cx.tcx.associated_items(*impl_id).find_by_name_and_kind(
+ cx.tcx,
+ Ident::from_str(method_name),
+ AssocKind::Fn,
+ *impl_id,
+ )
+ })
+ })
+ .map_or(def_id, |item| item.def_id)
+ } else {
+ def_id
+ }
+ })
+}
+
+fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<Symbol> {
+ if let Some(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) {
+ let lang_items = def_path_res(cx, &["rustc_hir", "lang_items", "LangItem"], Some(Namespace::TypeNS)).def_id();
+ let item_name = cx
+ .tcx
+ .adt_def(lang_items)
+ .variants()
+ .iter()
+ .nth(lang_item)
+ .unwrap()
+ .name;
+ Some(item_name)
+ } else {
+ None
+ }
+}
diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
index 5418eca38..be9834447 100644
--- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
+++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs
@@ -120,14 +120,14 @@ impl LateLintPass<'_> for WildcardImports {
if is_test_module_or_function(cx.tcx, item) {
self.test_modules_deep = self.test_modules_deep.saturating_add(1);
}
- let module = cx.tcx.parent_module_from_def_id(item.def_id);
- if cx.tcx.visibility(item.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
+ let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id);
+ if cx.tcx.visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module.to_def_id()) {
return;
}
if_chain! {
if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind;
if self.warn_on_all || !self.check_exceptions(item, use_path.segments);
- let used_imports = cx.tcx.names_imported_by_glob_use(item.def_id);
+ let used_imports = cx.tcx.names_imported_by_glob_use(item.owner_id.def_id);
if !used_imports.is_empty(); // Already handled by `unused_imports`
then {
let mut applicability = Applicability::MachineApplicable;
@@ -173,7 +173,7 @@ impl LateLintPass<'_> for WildcardImports {
let sugg = if braced_glob {
imports_string
} else {
- format!("{}::{}", import_source_snippet, imports_string)
+ format!("{import_source_snippet}::{imports_string}")
};
let (lint, message) = if let Res::Def(DefKind::Enum, _) = use_path.res {
diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs
index 640a09a7a..36574198f 100644
--- a/src/tools/clippy/clippy_lints/src/write.rs
+++ b/src/tools/clippy/clippy_lints/src/write.rs
@@ -1,20 +1,12 @@
-use std::borrow::Cow;
-use std::iter;
-use std::ops::{Deref, Range};
-
-use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
-use rustc_ast::ast::{Expr, ExprKind, Impl, Item, ItemKind, MacCall, Path, StrLit, StrStyle};
-use rustc_ast::ptr::P;
-use rustc_ast::token::{self, LitKind};
-use rustc_ast::tokenstream::TokenStream;
-use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_lexer::unescape::{self, EscapeError};
-use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
-use rustc_parse::parser;
+use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
+use clippy_utils::macros::{root_macro_call_first_node, FormatArgsExpn, MacroCall};
+use clippy_utils::source::{expand_past_previous_comma, snippet_opt};
+use rustc_ast::LitKind;
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind, HirIdMap, Impl, Item, ItemKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_tool_lint, impl_lint_pass};
-use rustc_span::symbol::{kw, Symbol};
-use rustc_span::{sym, BytePos, InnerSpan, Span, DUMMY_SP};
+use rustc_span::{sym, BytePos};
declare_clippy_lint! {
/// ### What it does
@@ -74,13 +66,7 @@ declare_clippy_lint! {
/// application and might forget to remove those prints afterward.
///
/// ### Known problems
- /// * Only catches `print!` and `println!` calls.
- /// * The lint level is unaffected by crate attributes. The level can still
- /// be set for functions, modules and other items. To change the level for
- /// the entire crate, please use command line flags. More information and a
- /// configuration example can be found in [clippy#6610].
- ///
- /// [clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
+ /// Only catches `print!` and `println!` calls.
///
/// ### Example
/// ```rust
@@ -102,13 +88,7 @@ declare_clippy_lint! {
/// application and might forget to remove those prints afterward.
///
/// ### Known problems
- /// * Only catches `eprint!` and `eprintln!` calls.
- /// * The lint level is unaffected by crate attributes. The level can still
- /// be set for functions, modules and other items. To change the level for
- /// the entire crate, please use command line flags. More information and a
- /// configuration example can be found in [clippy#6610].
- ///
- /// [clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
+ /// Only catches `eprint!` and `eprintln!` calls.
///
/// ### Example
/// ```rust
@@ -149,10 +129,6 @@ declare_clippy_lint! {
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
- /// ### Known problems
- /// Will also warn with macro calls as arguments that expand to literals
- /// -- e.g., `println!("{}", env!("FOO"))`.
- ///
/// ### Example
/// ```rust
/// println!("{}", "foo");
@@ -234,10 +210,6 @@ declare_clippy_lint! {
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
- /// ### Known problems
- /// Will also warn with macro calls as arguments that expand to literals
- /// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
- ///
/// ### Example
/// ```rust
/// # use std::fmt::Write;
@@ -257,28 +229,6 @@ declare_clippy_lint! {
"writing a literal with a format string"
}
-declare_clippy_lint! {
- /// ### What it does
- /// This lint warns when a named parameter in a format string is used as a positional one.
- ///
- /// ### Why is this bad?
- /// It may be confused for an assignment and obfuscates which parameter is being used.
- ///
- /// ### Example
- /// ```rust
- /// println!("{}", x = 10);
- /// ```
- ///
- /// Use instead:
- /// ```rust
- /// println!("{x}", x = 10);
- /// ```
- #[clippy::version = "1.63.0"]
- pub POSITIONAL_NAMED_FORMAT_PARAMETERS,
- suspicious,
- "named parameter in a format string is used positionally"
-}
-
#[derive(Default)]
pub struct Write {
in_debug_impl: bool,
@@ -294,537 +244,301 @@ impl_lint_pass!(Write => [
WRITE_WITH_NEWLINE,
WRITELN_EMPTY_STRING,
WRITE_LITERAL,
- POSITIONAL_NAMED_FORMAT_PARAMETERS,
]);
-impl EarlyLintPass for Write {
- fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
- if let ItemKind::Impl(box Impl {
- of_trait: Some(trait_ref),
- ..
- }) = &item.kind
- {
- let trait_name = trait_ref
- .path
- .segments
- .iter()
- .last()
- .expect("path has at least one segment")
- .ident
- .name;
- if trait_name == sym::Debug {
- self.in_debug_impl = true;
- }
+impl<'tcx> LateLintPass<'tcx> for Write {
+ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+ if is_debug_impl(cx, item) {
+ self.in_debug_impl = true;
}
}
- fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) {
- self.in_debug_impl = false;
+ fn check_item_post(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
+ if is_debug_impl(cx, item) {
+ self.in_debug_impl = false;
+ }
}
- fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) {
- fn is_build_script(cx: &EarlyContext<'_>) -> bool {
- // Cargo sets the crate name for build scripts to `build_script_build`
- cx.sess()
- .opts
- .crate_name
- .as_ref()
- .map_or(false, |crate_name| crate_name == "build_script_build")
- }
+ 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 Some(diag_name) = cx.tcx.get_diagnostic_name(macro_call.def_id) else { return };
+ let Some(name) = diag_name.as_str().strip_suffix("_macro") else { return };
- if mac.path == sym!(print) {
- if !is_build_script(cx) {
- span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`");
- }
- self.lint_print_with_newline(cx, mac);
- } else if mac.path == sym!(println) {
- if !is_build_script(cx) {
- span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`");
- }
- self.lint_println_empty_string(cx, mac);
- } else if mac.path == sym!(eprint) {
- span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprint!`");
- self.lint_print_with_newline(cx, mac);
- } else if mac.path == sym!(eprintln) {
- span_lint(cx, PRINT_STDERR, mac.span(), "use of `eprintln!`");
- self.lint_println_empty_string(cx, mac);
- } else if mac.path == sym!(write) {
- if let (Some(fmt_str), dest) = self.check_tts(cx, mac.args.inner_tokens(), true) {
- if check_newlines(&fmt_str) {
- let (nl_span, only_nl) = newline_span(&fmt_str);
- let nl_span = match (dest, only_nl) {
- // Special case of `write!(buf, "\n")`: Mark everything from the end of
- // `buf` for removal so no trailing comma [`writeln!(buf, )`] remains.
- (Some(dest_expr), true) => nl_span.with_lo(dest_expr.span.hi()),
- _ => nl_span,
- };
- span_lint_and_then(
- cx,
- WRITE_WITH_NEWLINE,
- mac.span(),
- "using `write!()` with a format string that ends in a single newline",
- |err| {
- err.multipart_suggestion(
- "use `writeln!()` instead",
- vec![(mac.path.span, String::from("writeln")), (nl_span, String::new())],
- Applicability::MachineApplicable,
- );
- },
- );
- }
- }
- } else if mac.path == sym!(writeln) {
- if let (Some(fmt_str), expr) = self.check_tts(cx, mac.args.inner_tokens(), true) {
- if fmt_str.symbol == kw::Empty {
- let mut applicability = Applicability::MachineApplicable;
- let suggestion = if let Some(e) = expr {
- snippet_with_applicability(cx, e.span, "v", &mut applicability)
- } else {
- applicability = Applicability::HasPlaceholders;
- Cow::Borrowed("v")
- };
-
- span_lint_and_sugg(
- cx,
- WRITELN_EMPTY_STRING,
- mac.span(),
- format!("using `writeln!({}, \"\")`", suggestion).as_str(),
- "replace it with",
- format!("writeln!({})", suggestion),
- applicability,
- );
+ let is_build_script = cx
+ .sess()
+ .opts
+ .crate_name
+ .as_ref()
+ .map_or(false, |crate_name| crate_name == "build_script_build");
+
+ match diag_name {
+ sym::print_macro | sym::println_macro => {
+ if !is_build_script {
+ span_lint(cx, PRINT_STDOUT, macro_call.span, &format!("use of `{name}!`"));
}
- }
+ },
+ sym::eprint_macro | sym::eprintln_macro => {
+ span_lint(cx, PRINT_STDERR, macro_call.span, &format!("use of `{name}!`"));
+ },
+ sym::write_macro | sym::writeln_macro => {},
+ _ => return,
}
- }
-}
-/// Given a format string that ends in a newline and its span, calculates the span of the
-/// newline, or the format string itself if the format string consists solely of a newline.
-/// Return this and a boolean indicating whether it only consisted of a newline.
-fn newline_span(fmtstr: &StrLit) -> (Span, bool) {
- let sp = fmtstr.span;
- let contents = fmtstr.symbol.as_str();
-
- if contents == r"\n" {
- return (sp, true);
- }
+ let Some(format_args) = FormatArgsExpn::find_nested(cx, expr, macro_call.expn) else { return };
- let newline_sp_hi = sp.hi()
- - match fmtstr.style {
- StrStyle::Cooked => BytePos(1),
- StrStyle::Raw(hashes) => BytePos((1 + hashes).into()),
- };
+ // ignore `writeln!(w)` and `write!(v, some_macro!())`
+ if format_args.format_string.span.from_expansion() {
+ return;
+ }
- let newline_sp_len = if contents.ends_with('\n') {
- BytePos(1)
- } else if contents.ends_with(r"\n") {
- BytePos(2)
- } else {
- panic!("expected format string to contain a newline");
- };
+ match diag_name {
+ sym::print_macro | sym::eprint_macro | sym::write_macro => {
+ check_newline(cx, &format_args, &macro_call, name);
+ },
+ sym::println_macro | sym::eprintln_macro | sym::writeln_macro => {
+ check_empty_string(cx, &format_args, &macro_call, name);
+ },
+ _ => {},
+ }
- (sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi), false)
-}
+ check_literal(cx, &format_args, name);
-/// Stores a list of replacement spans for each argument, but only if all the replacements used an
-/// empty format string.
-#[derive(Default)]
-struct SimpleFormatArgs {
- unnamed: Vec<Vec<Span>>,
- complex_unnamed: Vec<Vec<Span>>,
- named: Vec<(Symbol, Vec<Span>)>,
+ if !self.in_debug_impl {
+ for arg in &format_args.args {
+ if arg.format.r#trait == sym::Debug {
+ span_lint(cx, USE_DEBUG, arg.span, "use of `Debug`-based formatting");
+ }
+ }
+ }
+ }
}
-impl SimpleFormatArgs {
- fn get_unnamed(&self) -> impl Iterator<Item = &[Span]> {
- self.unnamed.iter().map(|x| match x.as_slice() {
- // Ignore the dummy span added from out of order format arguments.
- [DUMMY_SP] => &[],
- x => x,
- })
+fn is_debug_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
+ if let ItemKind::Impl(Impl { of_trait: Some(trait_ref), .. }) = &item.kind
+ && let Some(trait_id) = trait_ref.trait_def_id()
+ {
+ cx.tcx.is_diagnostic_item(sym::Debug, trait_id)
+ } else {
+ false
}
+}
- fn get_complex_unnamed(&self) -> impl Iterator<Item = &[Span]> {
- self.complex_unnamed.iter().map(Vec::as_slice)
- }
+fn check_newline(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_call: &MacroCall, name: &str) {
+ let format_string_parts = &format_args.format_string.parts;
+ let mut format_string_span = format_args.format_string.span;
- fn get_named(&self, n: &Path) -> &[Span] {
- self.named.iter().find(|x| *n == x.0).map_or(&[], |x| x.1.as_slice())
- }
+ let Some(last) = format_string_parts.last() else { return };
- fn push(&mut self, arg: rustc_parse_format::Argument<'_>, span: Span) {
- use rustc_parse_format::{
- AlignUnknown, ArgumentImplicitlyIs, ArgumentIs, ArgumentNamed, CountImplied, FormatSpec,
- };
+ let count_vertical_whitespace = || {
+ format_string_parts
+ .iter()
+ .flat_map(|part| part.as_str().chars())
+ .filter(|ch| matches!(ch, '\r' | '\n'))
+ .count()
+ };
- const SIMPLE: FormatSpec<'_> = FormatSpec {
- fill: None,
- align: AlignUnknown,
- flags: 0,
- precision: CountImplied,
- precision_span: None,
- width: CountImplied,
- width_span: None,
- ty: "",
- ty_span: None,
- };
+ if last.as_str().ends_with('\n')
+ // ignore format strings with other internal vertical whitespace
+ && count_vertical_whitespace() == 1
- match arg.position {
- ArgumentIs(n) | ArgumentImplicitlyIs(n) => {
- if self.unnamed.len() <= n {
- // Use a dummy span to mark all unseen arguments.
- self.unnamed.resize_with(n, || vec![DUMMY_SP]);
- if arg.format == SIMPLE {
- self.unnamed.push(vec![span]);
- } else {
- self.unnamed.push(Vec::new());
- }
- } else {
- let args = &mut self.unnamed[n];
- match (args.as_mut_slice(), arg.format == SIMPLE) {
- // A non-empty format string has been seen already.
- ([], _) => (),
- // Replace the dummy span, if it exists.
- ([dummy @ DUMMY_SP], true) => *dummy = span,
- ([_, ..], true) => args.push(span),
- ([_, ..], false) => *args = Vec::new(),
- }
- }
- },
- ArgumentNamed(n) => {
- let n = Symbol::intern(n);
- if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) {
- match x.1.as_slice() {
- // A non-empty format string has been seen already.
- [] => (),
- [_, ..] if arg.format == SIMPLE => x.1.push(span),
- [_, ..] => x.1 = Vec::new(),
- }
- } else if arg.format == SIMPLE {
- self.named.push((n, vec![span]));
- } else {
- self.named.push((n, Vec::new()));
- }
- },
- };
- }
+ // ignore trailing arguments: `print!("Issue\n{}", 1265);`
+ && format_string_parts.len() > format_args.args.len()
+ {
+ let lint = if name == "write" {
+ format_string_span = expand_past_previous_comma(cx, format_string_span);
- fn push_to_complex(&mut self, span: Span, position: usize) {
- if self.complex_unnamed.len() <= position {
- self.complex_unnamed.resize_with(position, Vec::new);
- self.complex_unnamed.push(vec![span]);
+ WRITE_WITH_NEWLINE
} else {
- let args: &mut Vec<Span> = &mut self.complex_unnamed[position];
- args.push(span);
- }
- }
-
- fn push_complex(
- &mut self,
- cx: &EarlyContext<'_>,
- arg: rustc_parse_format::Argument<'_>,
- str_lit_span: Span,
- fmt_span: Span,
- ) {
- use rustc_parse_format::{ArgumentImplicitlyIs, ArgumentIs, CountIsParam, CountIsStar};
-
- let snippet = snippet_opt(cx, fmt_span);
-
- let end = snippet
- .as_ref()
- .and_then(|s| s.find(':'))
- .or_else(|| fmt_span.hi().0.checked_sub(fmt_span.lo().0 + 1).map(|u| u as usize));
-
- if let (ArgumentIs(n) | ArgumentImplicitlyIs(n), Some(end)) = (arg.position, end) {
- let span = fmt_span.from_inner(InnerSpan::new(1, end));
- self.push_to_complex(span, n);
+ PRINT_WITH_NEWLINE
};
- if let (CountIsParam(n) | CountIsStar(n), Some(span)) = (arg.format.precision, arg.format.precision_span) {
- // We need to do this hack as precision spans should be converted from .* to .foo$
- let hack = if snippet.as_ref().and_then(|s| s.find('*')).is_some() {
- 0
- } else {
- 1
- };
+ span_lint_and_then(
+ cx,
+ lint,
+ macro_call.span,
+ &format!("using `{name}!()` with a format string that ends in a single newline"),
+ |diag| {
+ let name_span = cx.sess().source_map().span_until_char(macro_call.span, '!');
+ let Some(format_snippet) = snippet_opt(cx, format_string_span) else { return };
+
+ if format_string_parts.len() == 1 && last.as_str() == "\n" {
+ // print!("\n"), write!(f, "\n")
+
+ diag.multipart_suggestion(
+ &format!("use `{name}ln!` instead"),
+ vec![(name_span, format!("{name}ln")), (format_string_span, String::new())],
+ Applicability::MachineApplicable,
+ );
+ } else if format_snippet.ends_with("\\n\"") {
+ // print!("...\n"), write!(f, "...\n")
- let span = str_lit_span.from_inner(InnerSpan {
- start: span.start + 1,
- end: span.end - hack,
- });
- self.push_to_complex(span, n);
- };
+ let hi = format_string_span.hi();
+ let newline_span = format_string_span.with_lo(hi - BytePos(3)).with_hi(hi - BytePos(1));
- if let (CountIsParam(n), Some(span)) = (arg.format.width, arg.format.width_span) {
- let span = str_lit_span.from_inner(InnerSpan {
- start: span.start,
- end: span.end - 1,
- });
- self.push_to_complex(span, n);
- };
+ diag.multipart_suggestion(
+ &format!("use `{name}ln!` instead"),
+ vec![(name_span, format!("{name}ln")), (newline_span, String::new())],
+ Applicability::MachineApplicable,
+ );
+ }
+ },
+ );
}
}
-impl Write {
- /// Parses a format string into a collection of spans for each argument. This only keeps track
- /// of empty format arguments. Will also lint usages of debug format strings outside of debug
- /// impls.
- fn parse_fmt_string(&self, cx: &EarlyContext<'_>, str_lit: &StrLit) -> Option<SimpleFormatArgs> {
- use rustc_parse_format::{ParseMode, Parser, Piece};
-
- let str_sym = str_lit.symbol_unescaped.as_str();
- let style = match str_lit.style {
- StrStyle::Cooked => None,
- StrStyle::Raw(n) => Some(n as usize),
- };
-
- let mut parser = Parser::new(str_sym, style, snippet_opt(cx, str_lit.span), false, ParseMode::Format);
- let mut args = SimpleFormatArgs::default();
-
- while let Some(arg) = parser.next() {
- let arg = match arg {
- Piece::String(_) => continue,
- Piece::NextArgument(arg) => arg,
- };
- let span = parser
- .arg_places
- .last()
- .map_or(DUMMY_SP, |&x| str_lit.span.from_inner(InnerSpan::new(x.start, x.end)));
-
- if !self.in_debug_impl && arg.format.ty == "?" {
- // FIXME: modify rustc's fmt string parser to give us the current span
- span_lint(cx, USE_DEBUG, span, "use of `Debug`-based formatting");
- }
- args.push(arg, span);
- args.push_complex(cx, arg, str_lit.span, span);
- }
-
- parser.errors.is_empty().then_some(args)
- }
+fn check_empty_string(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, macro_call: &MacroCall, name: &str) {
+ if let [part] = &format_args.format_string.parts[..]
+ && let mut span = format_args.format_string.span
+ && part.as_str() == "\n"
+ {
+ let lint = if name == "writeln" {
+ span = expand_past_previous_comma(cx, span);
- /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
- /// `Option`s. The first `Option` of the tuple is the macro's format string. It includes
- /// the contents of the string, whether it's a raw string, and the span of the literal in the
- /// source. The second `Option` in the tuple is, in the `write[ln]!` case, the expression the
- /// `format_str` should be written to.
- ///
- /// Example:
- ///
- /// Calling this function on
- /// ```rust
- /// # use std::fmt::Write;
- /// # let mut buf = String::new();
- /// # let something = "something";
- /// writeln!(buf, "string to write: {}", something);
- /// ```
- /// will return
- /// ```rust,ignore
- /// (Some("string to write: {}"), Some(buf))
- /// ```
- fn check_tts<'a>(&self, cx: &EarlyContext<'a>, tts: TokenStream, is_write: bool) -> (Option<StrLit>, Option<Expr>) {
- let mut parser = parser::Parser::new(&cx.sess().parse_sess, tts, false, None);
- let expr = if is_write {
- match parser
- .parse_expr()
- .map(rustc_ast::ptr::P::into_inner)
- .map_err(DiagnosticBuilder::cancel)
- {
- // write!(e, ...)
- Ok(p) if parser.eat(&token::Comma) => Some(p),
- // write!(e) or error
- e => return (None, e.ok()),
- }
+ WRITELN_EMPTY_STRING
} else {
- None
+ PRINTLN_EMPTY_STRING
};
- let fmtstr = match parser.parse_str_lit() {
- Ok(fmtstr) => fmtstr,
- Err(_) => return (None, expr),
- };
+ span_lint_and_then(
+ cx,
+ lint,
+ macro_call.span,
+ &format!("empty string literal in `{name}!`"),
+ |diag| {
+ diag.span_suggestion(
+ span,
+ "remove the empty string",
+ String::new(),
+ Applicability::MachineApplicable,
+ );
+ },
+ );
+ }
+}
- let args = match self.parse_fmt_string(cx, &fmtstr) {
- Some(args) => args,
- None => return (Some(fmtstr), expr),
- };
+fn check_literal(cx: &LateContext<'_>, format_args: &FormatArgsExpn<'_>, name: &str) {
+ let mut counts = HirIdMap::<usize>::default();
+ for param in format_args.params() {
+ *counts.entry(param.value.hir_id).or_default() += 1;
+ }
- let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
- let mut unnamed_args = args.get_unnamed();
- let mut complex_unnamed_args = args.get_complex_unnamed();
- loop {
- if !parser.eat(&token::Comma) {
- return (Some(fmtstr), expr);
- }
+ for arg in &format_args.args {
+ let value = arg.param.value;
- let comma_span = parser.prev_token.span;
- let token_expr = if let Ok(expr) = parser.parse_expr().map_err(DiagnosticBuilder::cancel) {
- expr
- } else {
- return (Some(fmtstr), None);
- };
- let complex_unnamed_arg = complex_unnamed_args.next();
-
- let (fmt_spans, lit) = match &token_expr.kind {
- ExprKind::Lit(lit) => (unnamed_args.next().unwrap_or(&[]), lit),
- ExprKind::Assign(lhs, rhs, _) => {
- if let Some(span) = complex_unnamed_arg {
- for x in span {
- Self::report_positional_named_param(cx, *x, lhs, rhs);
- }
- }
- match (&lhs.kind, &rhs.kind) {
- (ExprKind::Path(_, p), ExprKind::Lit(lit)) => (args.get_named(p), lit),
- _ => continue,
+ if counts[&value.hir_id] == 1
+ && arg.format.is_default()
+ && let ExprKind::Lit(lit) = &value.kind
+ && !value.span.from_expansion()
+ && let Some(value_string) = snippet_opt(cx, value.span)
+ {
+ let (replacement, replace_raw) = match lit.node {
+ LitKind::Str(..) => extract_str_literal(&value_string),
+ LitKind::Char(ch) => (
+ match ch {
+ '"' => "\\\"",
+ '\'' => "'",
+ _ => &value_string[1..value_string.len() - 1],
}
- },
- _ => {
- unnamed_args.next();
- continue;
- },
+ .to_string(),
+ false,
+ ),
+ LitKind::Bool(b) => (b.to_string(), false),
+ _ => continue,
};
- let replacement: String = match lit.token_lit.kind {
- LitKind::StrRaw(_) | LitKind::ByteStrRaw(_) if matches!(fmtstr.style, StrStyle::Raw(_)) => {
- lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
+ let lint = if name.starts_with("write") {
+ WRITE_LITERAL
+ } else {
+ PRINT_LITERAL
+ };
+
+ let format_string_is_raw = format_args.format_string.style.is_some();
+ let replacement = match (format_string_is_raw, replace_raw) {
+ (false, false) => Some(replacement),
+ (false, true) => Some(replacement.replace('"', "\\\"").replace('\\', "\\\\")),
+ (true, false) => match conservative_unescape(&replacement) {
+ Ok(unescaped) => Some(unescaped),
+ Err(UnescapeErr::Lint) => None,
+ Err(UnescapeErr::Ignore) => continue,
},
- LitKind::Str | LitKind::ByteStr if matches!(fmtstr.style, StrStyle::Cooked) => {
- lit.token_lit.symbol.as_str().replace('{', "{{").replace('}', "}}")
+ (true, true) => {
+ if replacement.contains(['#', '"']) {
+ None
+ } else {
+ Some(replacement)
+ }
},
- LitKind::StrRaw(_)
- | LitKind::Str
- | LitKind::ByteStrRaw(_)
- | LitKind::ByteStr
- | LitKind::Integer
- | LitKind::Float
- | LitKind::Err => continue,
- LitKind::Byte | LitKind::Char => match lit.token_lit.symbol.as_str() {
- "\"" if matches!(fmtstr.style, StrStyle::Cooked) => "\\\"",
- "\"" if matches!(fmtstr.style, StrStyle::Raw(0)) => continue,
- "\\\\" if matches!(fmtstr.style, StrStyle::Raw(_)) => "\\",
- "\\'" => "'",
- "{" => "{{",
- "}" => "}}",
- x if matches!(fmtstr.style, StrStyle::Raw(_)) && x.starts_with('\\') => continue,
- x => x,
- }
- .into(),
- LitKind::Bool => lit.token_lit.symbol.as_str().deref().into(),
};
- if !fmt_spans.is_empty() {
- span_lint_and_then(
- cx,
- lint,
- token_expr.span,
- "literal with an empty format string",
- |diag| {
+ span_lint_and_then(
+ cx,
+ lint,
+ value.span,
+ "literal with an empty format string",
+ |diag| {
+ if let Some(replacement) = replacement
+ // `format!("{}", "a")`, `format!("{named}", named = "b")
+ // ~~~~~ ~~~~~~~~~~~~~
+ && let Some(value_span) = format_args.value_with_prev_comma_span(value.hir_id)
+ {
+ let replacement = replacement.replace('{', "{{").replace('}', "}}");
diag.multipart_suggestion(
"try this",
- iter::once((comma_span.to(token_expr.span), String::new()))
- .chain(fmt_spans.iter().copied().zip(iter::repeat(replacement)))
- .collect(),
+ vec![(arg.span, replacement), (value_span, String::new())],
Applicability::MachineApplicable,
);
- },
- );
- }
- }
- }
-
- fn report_positional_named_param(cx: &EarlyContext<'_>, span: Span, lhs: &P<Expr>, _rhs: &P<Expr>) {
- if let ExprKind::Path(_, _p) = &lhs.kind {
- let mut applicability = Applicability::MachineApplicable;
- let name = snippet_with_applicability(cx, lhs.span, "name", &mut applicability);
- // We need to do this hack as precision spans should be converted from .* to .foo$
- let hack = snippet(cx, span, "").contains('*');
-
- span_lint_and_sugg(
- cx,
- POSITIONAL_NAMED_FORMAT_PARAMETERS,
- span,
- &format!("named parameter {} is used as a positional parameter", name),
- "replace it with",
- if hack {
- format!("{}$", name)
- } else {
- format!("{}", name)
+ }
},
- applicability,
);
- };
- }
-
- fn lint_println_empty_string(&self, cx: &EarlyContext<'_>, mac: &MacCall) {
- if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
- if fmt_str.symbol == kw::Empty {
- let name = mac.path.segments[0].ident.name;
- span_lint_and_sugg(
- cx,
- PRINTLN_EMPTY_STRING,
- mac.span(),
- &format!("using `{}!(\"\")`", name),
- "replace it with",
- format!("{}!()", name),
- Applicability::MachineApplicable,
- );
- }
- }
- }
-
- fn lint_print_with_newline(&self, cx: &EarlyContext<'_>, mac: &MacCall) {
- if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
- if check_newlines(&fmt_str) {
- let name = mac.path.segments[0].ident.name;
- let suggested = format!("{}ln", name);
- span_lint_and_then(
- cx,
- PRINT_WITH_NEWLINE,
- mac.span(),
- &format!("using `{}!()` with a format string that ends in a single newline", name),
- |err| {
- err.multipart_suggestion(
- &format!("use `{}!` instead", suggested),
- vec![(mac.path.span, suggested), (newline_span(&fmt_str).0, String::new())],
- Applicability::MachineApplicable,
- );
- },
- );
- }
}
}
}
-/// Checks if the format string contains a single newline that terminates it.
+/// Removes the raw marker, `#`s and quotes from a str, and returns if the literal is raw
///
-/// Literal and escaped newlines are both checked (only literal for raw strings).
-fn check_newlines(fmtstr: &StrLit) -> bool {
- let mut has_internal_newline = false;
- let mut last_was_cr = false;
- let mut should_lint = false;
-
- let contents = fmtstr.symbol.as_str();
-
- let mut cb = |r: Range<usize>, c: Result<char, EscapeError>| {
- let c = match c {
- Ok(c) => c,
- Err(e) if !e.is_fatal() => return,
- Err(e) => panic!("{:?}", e),
- };
-
- if r.end == contents.len() && c == '\n' && !last_was_cr && !has_internal_newline {
- should_lint = true;
- } else {
- last_was_cr = c == '\r';
- if c == '\n' {
- has_internal_newline = true;
- }
- }
+/// `r#"a"#` -> (`a`, true)
+///
+/// `"b"` -> (`b`, false)
+fn extract_str_literal(literal: &str) -> (String, bool) {
+ let (literal, raw) = match literal.strip_prefix('r') {
+ Some(stripped) => (stripped.trim_matches('#'), true),
+ None => (literal, false),
};
- match fmtstr.style {
- StrStyle::Cooked => unescape::unescape_literal(contents, unescape::Mode::Str, &mut cb),
- StrStyle::Raw(_) => unescape::unescape_literal(contents, unescape::Mode::RawStr, &mut cb),
+ (literal[1..literal.len() - 1].to_string(), raw)
+}
+
+enum UnescapeErr {
+ /// Should still be linted, can be manually resolved by author, e.g.
+ ///
+ /// ```ignore
+ /// print!(r"{}", '"');
+ /// ```
+ Lint,
+ /// Should not be linted, e.g.
+ ///
+ /// ```ignore
+ /// print!(r"{}", '\r');
+ /// ```
+ Ignore,
+}
+
+/// Unescape a normal string into a raw string
+fn conservative_unescape(literal: &str) -> Result<String, UnescapeErr> {
+ let mut unescaped = String::with_capacity(literal.len());
+ let mut chars = literal.chars();
+ let mut err = false;
+
+ while let Some(ch) = chars.next() {
+ match ch {
+ '#' => err = true,
+ '\\' => match chars.next() {
+ Some('\\') => unescaped.push('\\'),
+ Some('"') => err = true,
+ _ => return Err(UnescapeErr::Ignore),
+ },
+ _ => unescaped.push(ch),
+ }
}
- should_lint
+ if err { Err(UnescapeErr::Lint) } else { Ok(unescaped) }
}
diff --git a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
index 50d3c079f..9b3de35db 100644
--- a/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/zero_div_zero.rs
@@ -57,8 +57,7 @@ impl<'tcx> LateLintPass<'tcx> for ZeroDiv {
"constant division of `0.0` with `0.0` will always result in NaN",
None,
&format!(
- "consider using `{}::NAN` if you would like a constant representing NaN",
- float_type,
+ "consider using `{float_type}::NAN` if you would like a constant representing NaN",
),
);
}
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 8dc43c0e2..6cf2a955f 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
@@ -2,12 +2,12 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{is_normalizable, is_type_diagnostic_item};
use if_chain::if_chain;
use rustc_hir::{self as hir, HirId, ItemKind, Node};
+use rustc_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_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;
-use rustc_typeck::hir_ty_to_ty;
declare_clippy_lint! {
/// ### What it does
@@ -69,10 +69,7 @@ impl LateLintPass<'_> for ZeroSizedMapValues {
fn in_trait_impl(cx: &LateContext<'_>, hir_id: HirId) -> bool {
let parent_id = cx.tcx.hir().get_parent_item(hir_id);
- let second_parent_id = cx
- .tcx
- .hir()
- .get_parent_item(cx.tcx.hir().local_def_id_to_hir_id(parent_id));
+ let second_parent_id = cx.tcx.hir().get_parent_item(parent_id.into()).def_id;
if let Some(Node::Item(item)) = cx.tcx.hir().find_by_def_id(second_parent_id) {
if let ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = item.kind {
return true;
diff --git a/src/tools/clippy/clippy_utils/Cargo.toml b/src/tools/clippy/clippy_utils/Cargo.toml
index c36bca065..83fee7bb3 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.65"
+version = "0.1.66"
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 e84adee9d..013399756 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs
@@ -147,7 +147,9 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
(Array(l), Array(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)),
- (MethodCall(lc, la, _), MethodCall(rc, ra, _)) => eq_path_seg(lc, rc) && over(la, ra, |l, r| eq_expr(l, r)),
+ (MethodCall(lc, ls, la, _), MethodCall(rc, rs, ra, _)) => {
+ eq_path_seg(lc, rc) && eq_expr(ls, rs) && over(la, ra, |l, r| eq_expr(l, r))
+ },
(Binary(lo, ll, lr), Binary(ro, rl, rr)) => lo.node == ro.node && eq_expr(ll, rl) && eq_expr(lr, rr),
(Unary(lo, l), Unary(ro, r)) => mem::discriminant(lo) == mem::discriminant(ro) && eq_expr(l, r),
(Lit(l), Lit(r)) => l.kind == r.kind,
@@ -436,14 +438,14 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
},
(
- TyAlias(box ast::TyAlias {
+ Type(box ast::TyAlias {
defaultness: ld,
generics: lg,
bounds: lb,
ty: lt,
..
}),
- TyAlias(box ast::TyAlias {
+ Type(box ast::TyAlias {
defaultness: rd,
generics: rg,
bounds: rb,
diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs
index 8ab77c881..cd8575c90 100644
--- a/src/tools/clippy/clippy_utils/src/attrs.rs
+++ b/src/tools/clippy/clippy_utils/src/attrs.rs
@@ -131,12 +131,12 @@ pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'s
match attr.style {
ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()),
ast::AttrStyle::Inner => {
- sess.struct_span_err(attr.span, &format!("`{}` is defined multiple times", name))
+ sess.struct_span_err(attr.span, &format!("`{name}` is defined multiple times"))
.span_note(unique_attr.as_ref().unwrap().span, "first definition found here")
.emit();
},
ast::AttrStyle::Outer => {
- sess.span_err(attr.span, &format!("`{}` cannot be an outer attribute", name));
+ sess.span_err(attr.span, format!("`{name}` cannot be an outer attribute"));
},
}
}
diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
index 7a8d4e806..c6bf98b7b 100644
--- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
+++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs
@@ -220,7 +220,7 @@ fn trait_item_search_pat(item: &TraitItem<'_>) -> (Pat, Pat) {
fn impl_item_search_pat(item: &ImplItem<'_>) -> (Pat, Pat) {
let (start_pat, end_pat) = match &item.kind {
ImplItemKind::Const(..) => (Pat::Str("const"), Pat::Str(";")),
- ImplItemKind::TyAlias(..) => (Pat::Str("type"), Pat::Str(";")),
+ ImplItemKind::Type(..) => (Pat::Str("type"), Pat::Str(";")),
ImplItemKind::Fn(sig, ..) => (fn_header_search_pat(sig.header), Pat::Str("")),
};
if item.vis_span.is_empty() {
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index e053708ed..07e4ef6a2 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -9,7 +9,7 @@ use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, Item, ItemKind,
use rustc_lint::LateContext;
use rustc_middle::mir;
use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::ty::subst::{Subst, SubstsRef};
+use rustc_middle::ty::SubstsRef;
use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::symbol::Symbol;
@@ -136,17 +136,49 @@ impl Constant {
(&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r),
(&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r),
(&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)),
- (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => iter::zip(l, r)
- .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
- .find(|r| r.map_or(true, |o| o != Ordering::Equal))
- .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
+ (&Self::Tuple(ref l), &Self::Tuple(ref r)) if l.len() == r.len() => match *cmp_type.kind() {
+ ty::Tuple(tys) if tys.len() == l.len() => l
+ .iter()
+ .zip(r)
+ .zip(tys)
+ .map(|((li, ri), cmp_type)| Self::partial_cmp(tcx, cmp_type, li, ri))
+ .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+ .unwrap_or_else(|| Some(l.len().cmp(&r.len()))),
+ _ => None,
+ },
+ (&Self::Vec(ref l), &Self::Vec(ref r)) => {
+ let cmp_type = match *cmp_type.kind() {
+ ty::Array(ty, _) | ty::Slice(ty) => ty,
+ _ => return None,
+ };
+ iter::zip(l, r)
+ .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri))
+ .find(|r| r.map_or(true, |o| o != Ordering::Equal))
+ .unwrap_or_else(|| Some(l.len().cmp(&r.len())))
+ },
(&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => {
- match Self::partial_cmp(tcx, cmp_type, lv, rv) {
+ match Self::partial_cmp(
+ tcx,
+ match *cmp_type.kind() {
+ ty::Array(ty, _) => ty,
+ _ => return None,
+ },
+ lv,
+ rv,
+ ) {
Some(Equal) => Some(ls.cmp(rs)),
x => x,
}
},
- (&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(tcx, cmp_type, lb, rb),
+ (&Self::Ref(ref lb), &Self::Ref(ref rb)) => Self::partial_cmp(
+ tcx,
+ match *cmp_type.kind() {
+ ty::Ref(_, ty, _) => ty,
+ _ => return None,
+ },
+ lb,
+ rb,
+ ),
// TODO: are there any useful inter-type orderings?
_ => None,
}
@@ -424,7 +456,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
.tcx
.const_eval_resolve(
self.param_env,
- ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
+ mir::UnevaluatedConst::new(ty::WithOptConstParam::unknown(def_id), substs),
None,
)
.ok()
@@ -501,8 +533,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
BinOpKind::Mul => l.checked_mul(r).map(zext),
BinOpKind::Div if r != 0 => l.checked_div(r).map(zext),
BinOpKind::Rem if r != 0 => l.checked_rem(r).map(zext),
- BinOpKind::Shr => l.checked_shr(r.try_into().expect("invalid shift")).map(zext),
- BinOpKind::Shl => l.checked_shl(r.try_into().expect("invalid shift")).map(zext),
+ BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(zext),
+ BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(zext),
BinOpKind::BitXor => Some(zext(l ^ r)),
BinOpKind::BitOr => Some(zext(l | r)),
BinOpKind::BitAnd => Some(zext(l & r)),
@@ -521,8 +553,8 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
BinOpKind::Mul => l.checked_mul(r).map(Constant::Int),
BinOpKind::Div => l.checked_div(r).map(Constant::Int),
BinOpKind::Rem => l.checked_rem(r).map(Constant::Int),
- BinOpKind::Shr => l.checked_shr(r.try_into().expect("shift too large")).map(Constant::Int),
- BinOpKind::Shl => l.checked_shl(r.try_into().expect("shift too large")).map(Constant::Int),
+ BinOpKind::Shr => l.checked_shr(r.try_into().ok()?).map(Constant::Int),
+ BinOpKind::Shl => l.checked_shl(r.try_into().ok()?).map(Constant::Int),
BinOpKind::BitXor => Some(Constant::Int(l ^ r)),
BinOpKind::BitOr => Some(Constant::Int(l | r)),
BinOpKind::BitAnd => Some(Constant::Int(l & r)),
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index ad95369b9..78f93755b 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -18,12 +18,11 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
diag.help(&format!(
- "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{}",
+ "for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
&option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
// extract just major + minor version and ignore patch versions
format!("rust-{}", n.rsplit_once('.').unwrap().1)
- }),
- lint
+ })
));
}
}
@@ -47,10 +46,9 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) {
/// | ^^^^^^^^^^^^^^^^^^^^^^^
/// ```
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: &str) {
- cx.struct_span_lint(lint, sp, |diag| {
- let mut diag = diag.build(msg);
- docs_link(&mut diag, lint);
- diag.emit();
+ cx.struct_span_lint(lint, sp, msg, |diag| {
+ docs_link(diag, lint);
+ diag
});
}
@@ -82,15 +80,14 @@ pub fn span_lint_and_help<'a, T: LintContext>(
help_span: Option<Span>,
help: &str,
) {
- cx.struct_span_lint(lint, span, |diag| {
- let mut diag = diag.build(msg);
+ cx.struct_span_lint(lint, span, msg, |diag| {
if let Some(help_span) = help_span {
diag.span_help(help_span, help);
} else {
diag.help(help);
}
- docs_link(&mut diag, lint);
- diag.emit();
+ docs_link(diag, lint);
+ diag
});
}
@@ -125,15 +122,14 @@ pub fn span_lint_and_note<'a, T: LintContext>(
note_span: Option<Span>,
note: &str,
) {
- cx.struct_span_lint(lint, span, |diag| {
- let mut diag = diag.build(msg);
+ cx.struct_span_lint(lint, span, msg, |diag| {
if let Some(note_span) = note_span {
diag.span_note(note_span, note);
} else {
diag.note(note);
}
- docs_link(&mut diag, lint);
- diag.emit();
+ docs_link(diag, lint);
+ diag
});
}
@@ -147,19 +143,17 @@ where
S: Into<MultiSpan>,
F: FnOnce(&mut Diagnostic),
{
- cx.struct_span_lint(lint, sp, |diag| {
- let mut diag = diag.build(msg);
- f(&mut diag);
- docs_link(&mut diag, lint);
- diag.emit();
+ cx.struct_span_lint(lint, sp, msg, |diag| {
+ f(diag);
+ docs_link(diag, lint);
+ diag
});
}
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) {
- cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| {
- let mut diag = diag.build(msg);
- docs_link(&mut diag, lint);
- diag.emit();
+ cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
+ docs_link(diag, lint);
+ diag
});
}
@@ -171,11 +165,10 @@ pub fn span_lint_hir_and_then(
msg: &str,
f: impl FnOnce(&mut Diagnostic),
) {
- cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| {
- let mut diag = diag.build(msg);
- f(&mut diag);
- docs_link(&mut diag, lint);
- diag.emit();
+ cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |diag| {
+ f(diag);
+ docs_link(diag, lint);
+ diag
});
}
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 91c9c382c..95b3e651e 100644
--- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
+++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs
@@ -113,7 +113,17 @@ fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessS
},
args,
) => match self.cx.qpath_res(path, hir_id) {
- Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => (),
+ Res::Def(DefKind::Ctor(..) | DefKind::Variant, _) | Res::SelfCtor(_) => {
+ if self
+ .cx
+ .typeck_results()
+ .expr_ty(e)
+ .has_significant_drop(self.cx.tcx, self.cx.param_env)
+ {
+ self.eagerness = ForceNoChange;
+ return;
+ }
+ },
Res::Def(_, id) if self.cx.tcx.is_promotable_const_fn(id) => (),
// No need to walk the arguments here, `is_const_evaluatable` already did
Res::Def(..) if is_const_evaluatable(self.cx, e) => {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 7212d9cd7..cf24ec8b6 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -962,7 +962,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
mut_ty.mutbl.hash(&mut self.s);
},
TyKind::Rptr(lifetime, ref mut_ty) => {
- self.hash_lifetime(*lifetime);
+ self.hash_lifetime(lifetime);
self.hash_ty(mut_ty.ty);
mut_ty.mutbl.hash(&mut self.s);
},
@@ -992,7 +992,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
in_trait.hash(&mut self.s);
},
TyKind::TraitObject(_, lifetime, _) => {
- self.hash_lifetime(*lifetime);
+ self.hash_lifetime(lifetime);
},
TyKind::Typeof(anon_const) => {
self.hash_body(anon_const.body);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 62da850a1..3ebfc5e00 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -3,7 +3,7 @@
#![feature(control_flow_enum)]
#![feature(let_chains)]
#![feature(lint_reasons)]
-#![cfg_attr(bootstrap, feature(let_else))]
+#![feature(never_type)]
#![feature(once_cell)]
#![feature(rustc_private)]
#![recursion_limit = "512"]
@@ -24,16 +24,18 @@ extern crate rustc_attr;
extern crate rustc_data_structures;
extern crate rustc_errors;
extern crate rustc_hir;
+extern crate rustc_hir_typeck;
+extern crate rustc_index;
extern crate rustc_infer;
extern crate rustc_lexer;
extern crate rustc_lint;
extern crate rustc_middle;
+extern crate rustc_mir_dataflow;
extern crate rustc_parse_format;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
extern crate rustc_trait_selection;
-extern crate rustc_typeck;
#[macro_use]
pub mod sym_helper;
@@ -48,6 +50,7 @@ pub mod eager_or_lazy;
pub mod higher;
mod hir_utils;
pub mod macros;
+pub mod mir;
pub mod msrvs;
pub mod numeric_literal;
pub mod paths;
@@ -66,6 +69,7 @@ pub use self::hir_utils::{
both, count_eq, eq_expr_value, hash_expr, hash_stmt, over, HirEqInterExpr, SpanlessEq, SpanlessHash,
};
+use core::ops::ControlFlow;
use std::collections::hash_map::Entry;
use std::hash::BuildHasherDefault;
use std::sync::OnceLock;
@@ -77,8 +81,8 @@ use rustc_ast::Attribute;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::unhash::UnhashMap;
use rustc_hir as hir;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_ID};
+use rustc_hir::def::{DefKind, Namespace, Res};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
use rustc_hir::hir_id::{HirIdMap, HirIdSet};
use rustc_hir::intravisit::{walk_expr, FnKind, Visitor};
use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk};
@@ -114,14 +118,14 @@ use rustc_target::abi::Integer;
use crate::consts::{constant, Constant};
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
-use crate::visitors::expr_visitor_no_bodies;
+use crate::visitors::for_each_expr;
pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
if let Ok(version) = RustcVersion::parse(msrv) {
return Some(version);
} else if let Some(sess) = sess {
if let Some(span) = span {
- sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
+ sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
}
}
None
@@ -212,7 +216,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<
/// }
/// ```
pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
- let parent_id = cx.tcx.hir().get_parent_item(id);
+ let parent_id = cx.tcx.hir().get_parent_item(id).def_id;
match cx.tcx.hir().get_by_def_id(parent_id) {
Node::Item(&Item {
kind: ItemKind::Const(..) | ItemKind::Static(..),
@@ -239,19 +243,69 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
}
}
-/// Checks if a `QPath` resolves to a constructor of a `LangItem`.
+/// Checks if a `Res` refers to a constructor of a `LangItem`
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
-pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem) -> bool {
+pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
+ if let Res::Def(DefKind::Ctor(..), id) = res
+ && let Ok(lang_id) = cx.tcx.lang_items().require(lang_item)
+ && let Some(id) = cx.tcx.opt_parent(id)
+ {
+ id == lang_id
+ } else {
+ false
+ }
+}
+
+pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool {
+ if let Res::Def(DefKind::Ctor(..), id) = res
+ && let Some(id) = cx.tcx.opt_parent(id)
+ {
+ cx.tcx.is_diagnostic_item(diag_item, id)
+ } else {
+ false
+ }
+}
+
+/// Checks if a `QPath` resolves to a constructor of a diagnostic item.
+pub fn is_diagnostic_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, diagnostic_item: Symbol) -> bool {
if let QPath::Resolved(_, path) = qpath {
if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
- if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
- return cx.tcx.parent(ctor_id) == item_id;
- }
+ return cx.tcx.is_diagnostic_item(diagnostic_item, cx.tcx.parent(ctor_id));
}
}
false
}
+/// Checks if the `DefId` matches the given diagnostic item or it's constructor.
+pub fn is_diagnostic_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: Symbol) -> bool {
+ let did = match cx.tcx.def_kind(did) {
+ DefKind::Ctor(..) => cx.tcx.parent(did),
+ // Constructors for types in external crates seem to have `DefKind::Variant`
+ DefKind::Variant => match cx.tcx.opt_parent(did) {
+ Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
+ _ => did,
+ },
+ _ => did,
+ };
+
+ cx.tcx.is_diagnostic_item(item, did)
+}
+
+/// Checks if the `DefId` matches the given `LangItem` or it's constructor.
+pub fn is_lang_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: LangItem) -> bool {
+ let did = match cx.tcx.def_kind(did) {
+ DefKind::Ctor(..) => cx.tcx.parent(did),
+ // Constructors for types in external crates seem to have `DefKind::Variant`
+ DefKind::Variant => match cx.tcx.opt_parent(did) {
+ Some(did) if matches!(cx.tcx.def_kind(did), DefKind::Variant) => did,
+ _ => did,
+ },
+ _ => did,
+ };
+
+ cx.tcx.lang_items().require(item).map_or(false, |id| id == did)
+}
+
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
matches!(
expr.kind,
@@ -471,15 +525,49 @@ pub fn path_def_id<'tcx>(cx: &LateContext<'_>, maybe_path: &impl MaybePath<'tcx>
path_res(cx, maybe_path).opt_def_id()
}
-/// Resolves a def path like `std::vec::Vec`.
+fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
+ let single = |ty| tcx.incoherent_impls(ty).iter().copied();
+ let empty = || [].iter().copied();
+ match name {
+ "bool" => single(BoolSimplifiedType),
+ "char" => single(CharSimplifiedType),
+ "str" => single(StrSimplifiedType),
+ "array" => single(ArraySimplifiedType),
+ "slice" => single(SliceSimplifiedType),
+ // FIXME: rustdoc documents these two using just `pointer`.
+ //
+ // Maybe this is something we should do here too.
+ "const_ptr" => single(PtrSimplifiedType(Mutability::Not)),
+ "mut_ptr" => single(PtrSimplifiedType(Mutability::Mut)),
+ "isize" => single(IntSimplifiedType(IntTy::Isize)),
+ "i8" => single(IntSimplifiedType(IntTy::I8)),
+ "i16" => single(IntSimplifiedType(IntTy::I16)),
+ "i32" => single(IntSimplifiedType(IntTy::I32)),
+ "i64" => single(IntSimplifiedType(IntTy::I64)),
+ "i128" => single(IntSimplifiedType(IntTy::I128)),
+ "usize" => single(UintSimplifiedType(UintTy::Usize)),
+ "u8" => single(UintSimplifiedType(UintTy::U8)),
+ "u16" => single(UintSimplifiedType(UintTy::U16)),
+ "u32" => single(UintSimplifiedType(UintTy::U32)),
+ "u64" => single(UintSimplifiedType(UintTy::U64)),
+ "u128" => single(UintSimplifiedType(UintTy::U128)),
+ "f32" => single(FloatSimplifiedType(FloatTy::F32)),
+ "f64" => single(FloatSimplifiedType(FloatTy::F64)),
+ _ => empty(),
+ }
+}
+
+/// Resolves a def path like `std::vec::Vec`. `namespace_hint` can be supplied to disambiguate
+/// between `std::vec` the module and `std::vec` the macro
+///
/// This function is expensive and should be used sparingly.
-pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
- fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str) -> Option<Res> {
+pub fn def_path_res(cx: &LateContext<'_>, path: &[&str], namespace_hint: Option<Namespace>) -> Res {
+ fn item_child_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: &str, matches_ns: impl Fn(Res) -> bool) -> Option<Res> {
match tcx.def_kind(def_id) {
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
.module_children(def_id)
.iter()
- .find(|item| item.ident.name.as_str() == name)
+ .find(|item| item.ident.name.as_str() == name && matches_ns(item.res.expect_non_local()))
.map(|child| child.res.expect_non_local()),
DefKind::Impl => tcx
.associated_item_def_ids(def_id)
@@ -487,40 +575,17 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
.copied()
.find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
.map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
+ DefKind::Struct | DefKind::Union => tcx
+ .adt_def(def_id)
+ .non_enum_variant()
+ .fields
+ .iter()
+ .find(|f| f.name.as_str() == name)
+ .map(|f| Res::Def(DefKind::Field, f.did)),
_ => None,
}
}
- fn find_primitive<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
- let single = |ty| tcx.incoherent_impls(ty).iter().copied();
- let empty = || [].iter().copied();
- match name {
- "bool" => single(BoolSimplifiedType),
- "char" => single(CharSimplifiedType),
- "str" => single(StrSimplifiedType),
- "array" => single(ArraySimplifiedType),
- "slice" => single(SliceSimplifiedType),
- // FIXME: rustdoc documents these two using just `pointer`.
- //
- // Maybe this is something we should do here too.
- "const_ptr" => single(PtrSimplifiedType(Mutability::Not)),
- "mut_ptr" => single(PtrSimplifiedType(Mutability::Mut)),
- "isize" => single(IntSimplifiedType(IntTy::Isize)),
- "i8" => single(IntSimplifiedType(IntTy::I8)),
- "i16" => single(IntSimplifiedType(IntTy::I16)),
- "i32" => single(IntSimplifiedType(IntTy::I32)),
- "i64" => single(IntSimplifiedType(IntTy::I64)),
- "i128" => single(IntSimplifiedType(IntTy::I128)),
- "usize" => single(UintSimplifiedType(UintTy::Usize)),
- "u8" => single(UintSimplifiedType(UintTy::U8)),
- "u16" => single(UintSimplifiedType(UintTy::U16)),
- "u32" => single(UintSimplifiedType(UintTy::U32)),
- "u64" => single(UintSimplifiedType(UintTy::U64)),
- "u128" => single(UintSimplifiedType(UintTy::U128)),
- "f32" => single(FloatSimplifiedType(FloatTy::F32)),
- "f64" => single(FloatSimplifiedType(FloatTy::F64)),
- _ => empty(),
- }
- }
+
fn find_crate(tcx: TyCtxt<'_>, name: &str) -> Option<DefId> {
tcx.crates(())
.iter()
@@ -529,32 +594,45 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
.map(CrateNum::as_def_id)
}
- let (base, first, path) = match *path {
- [base, first, ref path @ ..] => (base, first, path),
+ let (base, path) = match *path {
[primitive] => {
return PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy);
},
+ [base, ref path @ ..] => (base, path),
_ => return Res::Err,
};
let tcx = cx.tcx;
let starts = find_primitive(tcx, base)
.chain(find_crate(tcx, base))
- .filter_map(|id| item_child_by_name(tcx, id, first));
+ .map(|id| Res::Def(tcx.def_kind(id), id));
for first in starts {
let last = path
.iter()
.copied()
+ .enumerate()
// for each segment, find the child item
- .try_fold(first, |res, segment| {
+ .try_fold(first, |res, (idx, segment)| {
+ let matches_ns = |res: Res| {
+ // If at the last segment in the path, respect the namespace hint
+ if idx == path.len() - 1 {
+ match namespace_hint {
+ Some(ns) => res.matches_ns(ns),
+ None => true,
+ }
+ } else {
+ res.matches_ns(Namespace::TypeNS)
+ }
+ };
+
let def_id = res.def_id();
- if let Some(item) = item_child_by_name(tcx, def_id, segment) {
+ if let Some(item) = item_child_by_name(tcx, def_id, segment, matches_ns) {
Some(item)
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
// it is not a child item so check inherent impl items
tcx.inherent_impls(def_id)
.iter()
- .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment))
+ .find_map(|&impl_def_id| item_child_by_name(tcx, impl_def_id, segment, matches_ns))
} else {
None
}
@@ -570,8 +648,10 @@ pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
/// Convenience function to get the `DefId` of a trait by path.
/// It could be a trait or trait alias.
+///
+/// This function is expensive and should be used sparingly.
pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
- match def_path_res(cx, path) {
+ match def_path_res(cx, path, Some(Namespace::TypeNS)) {
Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
_ => None,
}
@@ -597,8 +677,8 @@ pub fn trait_ref_of_method<'tcx>(cx: &LateContext<'tcx>, def_id: LocalDefId) ->
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
let parent_impl = cx.tcx.hir().get_parent_item(hir_id);
if_chain! {
- if parent_impl != CRATE_DEF_ID;
- if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl);
+ if parent_impl != hir::CRATE_OWNER_ID;
+ if let hir::Node::Item(item) = cx.tcx.hir().get_by_def_id(parent_impl.def_id);
if let hir::ItemKind::Impl(impl_) = &item.kind;
then {
return impl_.of_trait.as_ref();
@@ -738,13 +818,37 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
false
}
},
- ExprKind::Call(repl_func, _) => is_default_equivalent_call(cx, repl_func),
- ExprKind::Path(qpath) => is_lang_ctor(cx, qpath, OptionNone),
+ ExprKind::Call(repl_func, []) => is_default_equivalent_call(cx, repl_func),
+ ExprKind::Call(from_func, [ref arg]) => is_default_equivalent_from(cx, from_func, arg),
+ ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
_ => false,
}
}
+fn is_default_equivalent_from(cx: &LateContext<'_>, from_func: &Expr<'_>, arg: &Expr<'_>) -> bool {
+ if let ExprKind::Path(QPath::TypeRelative(ty, seg)) = from_func.kind &&
+ seg.ident.name == sym::from
+ {
+ match arg.kind {
+ ExprKind::Lit(hir::Lit {
+ node: LitKind::Str(ref sym, _),
+ ..
+ }) => return sym.is_empty() && is_path_diagnostic_item(cx, ty, sym::String),
+ ExprKind::Array([]) => return is_path_diagnostic_item(cx, ty, sym::Vec),
+ ExprKind::Repeat(_, ArrayLen::Body(len)) => {
+ if let ExprKind::Lit(ref const_lit) = cx.tcx.hir().body(len.body).value.kind &&
+ let LitKind::Int(v, _) = const_lit.node
+ {
+ return v == 0 && is_path_diagnostic_item(cx, ty, sym::Vec);
+ }
+ }
+ _ => (),
+ }
+ }
+ false
+}
+
/// Checks if the top level expression can be moved into a closure as is.
/// Currently checks for:
/// * Break/Continue outside the given loop HIR ids.
@@ -1104,7 +1208,7 @@ pub fn is_in_panic_handler(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
/// Gets the name of the item the expression is in, if available.
pub fn get_item_name(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<Symbol> {
- let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id);
+ let parent_id = cx.tcx.hir().get_parent_item(expr.hir_id).def_id;
match cx.tcx.hir().find_by_def_id(parent_id) {
Some(
Node::Item(Item { ident, .. })
@@ -1137,17 +1241,14 @@ pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
/// Returns `true` if `expr` contains a return expression
pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
- let mut found = false;
- expr_visitor_no_bodies(|expr| {
- if !found {
- if let hir::ExprKind::Ret(..) = &expr.kind {
- found = true;
- }
+ for_each_expr(expr, |e| {
+ if matches!(e.kind, hir::ExprKind::Ret(..)) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
- !found
})
- .visit_expr(expr);
- found
+ .is_some()
}
/// Extends the span to the beginning of the spans line, incl. whitespaces.
@@ -1387,8 +1488,8 @@ pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
/// Examples of coercions can be found in the Nomicon at
/// <https://doc.rust-lang.org/nomicon/coercions.html>.
///
-/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more
-/// information on adjustments and coercions.
+/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_hir_analysis::check::coercion` for
+/// more information on adjustments and coercions.
pub fn is_adjusted(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
cx.typeck_results().adjustments().get(e.hir_id).is_some()
}
@@ -1536,7 +1637,7 @@ pub fn is_self(slf: &Param<'_>) -> bool {
pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
- if let Res::SelfTy { .. } = path.res {
+ if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
return true;
}
}
@@ -1554,7 +1655,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
if_chain! {
if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
if ddpos.as_opt_usize().is_none();
- if is_lang_ctor(cx, path, ResultOk);
+ if is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk);
if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
if path_to_local_id(arm.body, hir_id);
then {
@@ -1566,7 +1667,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
- is_lang_ctor(cx, path, ResultErr)
+ is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultErr)
} else {
false
}
@@ -1648,7 +1749,7 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool
return true;
}
prev_enclosing_node = Some(enclosing_node);
- enclosing_node = map.local_def_id_to_hir_id(map.get_parent_item(enclosing_node));
+ enclosing_node = map.get_parent_item(enclosing_node).into();
}
false
@@ -1665,6 +1766,7 @@ pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool
/// ```rust,ignore
/// if let Some(args) = match_function_call(cx, cmp_max_call, &paths::CMP_MAX);
/// ```
+/// This function is deprecated. Use [`match_function_call_with_def_id`].
pub fn match_function_call<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
@@ -1682,6 +1784,22 @@ pub fn match_function_call<'tcx>(
None
}
+pub fn match_function_call_with_def_id<'tcx>(
+ cx: &LateContext<'tcx>,
+ expr: &'tcx Expr<'_>,
+ fun_def_id: DefId,
+) -> Option<&'tcx [Expr<'tcx>]> {
+ if_chain! {
+ if let ExprKind::Call(fun, args) = expr.kind;
+ if let ExprKind::Path(ref qpath) = fun.kind;
+ if cx.qpath_res(qpath, fun.hir_id).opt_def_id() == Some(fun_def_id);
+ then {
+ return Some(args);
+ }
+ };
+ None
+}
+
/// Checks if the given `DefId` matches any of the paths. Returns the index of matching path, if
/// any.
///
@@ -1990,9 +2108,9 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
}
}
-/// Returns Option<String> where String is a textual representation of the type encapsulated in the
-/// slice iff the given expression is a slice of primitives (as defined in the
-/// `is_recursively_primitive_type` function) and None otherwise.
+/// Returns `Option<String>` where String is a textual representation of the type encapsulated in
+/// the slice iff the given expression is a slice of primitives (as defined in the
+/// `is_recursively_primitive_type` function) and `None` otherwise.
pub fn is_slice_of_primitives(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<String> {
let expr_type = cx.typeck_results().expr_ty_adjusted(expr);
let expr_kind = expr_type.kind();
@@ -2163,7 +2281,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalDefId, f: impl Fn(&[Symbol
Entry::Vacant(entry) => {
let mut names = Vec::new();
for id in tcx.hir().module_items(module) {
- if matches!(tcx.def_kind(id.def_id), DefKind::Const)
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
&& let item = tcx.hir().item(id)
&& let ItemKind::Const(ty, _body) = item.kind {
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
@@ -2296,6 +2414,29 @@ pub fn span_contains_comment(sm: &SourceMap, span: Span) -> bool {
});
}
+/// Return all the comments a given span contains
+/// Comments are returned wrapped with their relevant delimiters
+pub fn span_extract_comment(sm: &SourceMap, span: Span) -> String {
+ let snippet = sm.span_to_snippet(span).unwrap_or_default();
+ let mut comments_buf: Vec<String> = Vec::new();
+ let mut index: usize = 0;
+
+ for token in tokenize(&snippet) {
+ let token_range = index..(index + token.len as usize);
+ index += token.len as usize;
+ match token.kind {
+ TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => {
+ if let Some(comment) = snippet.get(token_range) {
+ comments_buf.push(comment.to_string());
+ }
+ },
+ _ => (),
+ }
+ }
+
+ comments_buf.join("\n")
+}
+
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 bd89ff977..9a682fbe6 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -2,13 +2,13 @@
use crate::is_path_diagnostic_item;
use crate::source::snippet_opt;
-use crate::visitors::expr_visitor_no_bodies;
+use crate::visitors::{for_each_expr, Descend};
use arrayvec::ArrayVec;
use itertools::{izip, Either, Itertools};
use rustc_ast::ast::LitKind;
-use rustc_hir::intravisit::Visitor;
-use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
+use rustc_hir::intravisit::{walk_expr, Visitor};
+use rustc_hir::{self as hir, Expr, ExprField, ExprKind, HirId, Node, QPath};
use rustc_lexer::unescape::unescape_literal;
use rustc_lexer::{tokenize, unescape, LiteralKind, TokenKind};
use rustc_lint::LateContext;
@@ -16,6 +16,7 @@ use rustc_parse_format::{self as rpf, Alignment};
use rustc_span::def_id::DefId;
use rustc_span::hygiene::{self, MacroKind, SyntaxContext};
use rustc_span::{sym, BytePos, ExpnData, ExpnId, ExpnKind, Pos, Span, SpanData, Symbol};
+use std::iter::{once, zip};
use std::ops::ControlFlow;
const FORMAT_MACRO_DIAG_ITEMS: &[Symbol] = &[
@@ -270,20 +271,19 @@ fn find_assert_args_inner<'a, const N: usize>(
};
let mut args = ArrayVec::new();
let mut panic_expn = None;
- expr_visitor_no_bodies(|e| {
+ let _: Option<!> = for_each_expr(expr, |e| {
if args.is_full() {
if panic_expn.is_none() && e.span.ctxt() != expr.span.ctxt() {
panic_expn = PanicExpn::parse(cx, e);
}
- panic_expn.is_none()
+ ControlFlow::Continue(Descend::from(panic_expn.is_none()))
} else if is_assert_arg(cx, e, expn) {
args.push(e);
- false
+ ControlFlow::Continue(Descend::No)
} else {
- true
+ ControlFlow::Continue(Descend::Yes)
}
- })
- .visit_expr(expr);
+ });
let args = args.into_inner().ok()?;
// if no `panic!(..)` is found, use `PanicExpn::Empty`
// to indicate that the default assertion message is used
@@ -297,22 +297,19 @@ fn find_assert_within_debug_assert<'a>(
expn: ExpnId,
assert_name: Symbol,
) -> Option<(&'a Expr<'a>, ExpnId)> {
- let mut found = None;
- expr_visitor_no_bodies(|e| {
- if found.is_some() || !e.span.from_expansion() {
- return false;
+ for_each_expr(expr, |e| {
+ if !e.span.from_expansion() {
+ return ControlFlow::Continue(Descend::No);
}
let e_expn = e.span.ctxt().outer_expn();
if e_expn == expn {
- return true;
- }
- if e_expn.expn_data().macro_def_id.map(|id| cx.tcx.item_name(id)) == Some(assert_name) {
- found = Some((e, e_expn));
+ ControlFlow::Continue(Descend::Yes)
+ } else if e_expn.expn_data().macro_def_id.map(|id| cx.tcx.item_name(id)) == Some(assert_name) {
+ ControlFlow::Break((e, e_expn))
+ } else {
+ ControlFlow::Continue(Descend::No)
}
- false
})
- .visit_expr(expr);
- found
}
fn is_assert_arg(cx: &LateContext<'_>, expr: &Expr<'_>, assert_expn: ExpnId) -> bool {
@@ -392,20 +389,18 @@ impl FormatString {
unescape_literal(inner, mode, &mut |_, ch| match ch {
Ok(ch) => unescaped.push(ch),
Err(e) if !e.is_fatal() => (),
- Err(e) => panic!("{:?}", e),
+ Err(e) => panic!("{e:?}"),
});
let mut parts = Vec::new();
- expr_visitor_no_bodies(|expr| {
- if let ExprKind::Lit(lit) = &expr.kind {
- if let LitKind::Str(symbol, _) = lit.node {
- parts.push(symbol);
- }
+ let _: Option<!> = for_each_expr(pieces, |expr| {
+ if let ExprKind::Lit(lit) = &expr.kind
+ && let LitKind::Str(symbol, _) = lit.node
+ {
+ parts.push(symbol);
}
-
- true
- })
- .visit_expr(pieces);
+ ControlFlow::Continue(())
+ });
Some(Self {
span,
@@ -418,7 +413,8 @@ impl FormatString {
}
struct FormatArgsValues<'tcx> {
- /// See `FormatArgsExpn::value_args`
+ /// Values passed after the format string and implicit captures. `[1, z + 2, x]` for
+ /// `format!("{x} {} {}", 1, z + 2)`.
value_args: Vec<&'tcx Expr<'tcx>>,
/// Maps an `rt::v1::Argument::position` or an `rt::v1::Count::Param` to its index in
/// `value_args`
@@ -431,7 +427,7 @@ impl<'tcx> FormatArgsValues<'tcx> {
fn new(args: &'tcx Expr<'tcx>, format_string_span: SpanData) -> Self {
let mut pos_to_value_index = Vec::new();
let mut value_args = Vec::new();
- expr_visitor_no_bodies(|expr| {
+ let _: Option<!> = for_each_expr(args, |expr| {
if expr.span.ctxt() == args.span.ctxt() {
// ArgumentV1::new_<format_trait>(<val>)
// ArgumentV1::from_usize(<val>)
@@ -453,16 +449,13 @@ impl<'tcx> FormatArgsValues<'tcx> {
pos_to_value_index.push(val_idx);
}
-
- true
+ ControlFlow::Continue(Descend::Yes)
} else {
// assume that any expr with a differing span is a value
value_args.push(expr);
-
- false
+ ControlFlow::Continue(Descend::No)
}
- })
- .visit_expr(args);
+ });
Self {
value_args,
@@ -485,64 +478,49 @@ struct ParamPosition {
precision: Option<usize>,
}
-/// 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> {
- 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
+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
+ && let LitKind::Int(pos, _) = lit.node
+ {
+ self.value = pos as usize;
+ }
+ },
+ sym::precision => {
+ self.precision = parse_count(field.expr);
+ },
+ sym::width => {
+ self.width = parse_count(field.expr);
+ },
+ _ => walk_expr(self, field.expr),
}
}
+}
+/// 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();
-
- // ::core::fmt::rt::v1::Argument {
- // position: 0usize,
- // format: ::core::fmt::rt::v1::FormatSpec {
- // ..
- // precision: ::core::fmt::rt::v1::Count::Implied,
- // width: ::core::fmt::rt::v1::Count::Implied,
- // },
- // }
-
- // TODO: this can be made much nicer next sync with `Visitor::visit_expr_field`
- if let ExprKind::Struct(_, fields, _) = spec.kind {
- for field in fields {
- match (field.ident.name, &field.expr.kind) {
- (sym::position, ExprKind::Lit(lit)) => {
- if let LitKind::Int(pos, _) = lit.node {
- position.value = pos as usize;
- }
- },
- (sym::format, &ExprKind::Struct(_, spec_fields, _)) => {
- for spec_field in spec_fields {
- match spec_field.ident.name {
- sym::precision => {
- position.precision = parse_count(spec_field.expr);
- },
- sym::width => {
- position.width = parse_count(spec_field.expr);
- },
- _ => {},
- }
- }
- },
- _ => {},
- }
- }
- }
-
+ position.visit_expr(spec);
position
}))
} else {
@@ -560,19 +538,32 @@ fn span_from_inner(base: SpanData, inner: rpf::InnerSpan) -> Span {
)
}
+/// How a format parameter is used in the format string
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FormatParamKind {
/// An implicit parameter , such as `{}` or `{:?}`.
Implicit,
- /// A parameter with an explicit number, or an asterisk precision. e.g. `{1}`, `{0:?}`,
- /// `{:.0$}` or `{:.*}`.
+ /// A parameter with an explicit number, e.g. `{1}`, `{0:?}`, or `{:.0$}`
Numbered,
+ /// A parameter with an asterisk precision. e.g. `{:.*}`.
+ Starred,
/// A named parameter with a named `value_arg`, such as the `x` in `format!("{x}", x = 1)`.
Named(Symbol),
/// An implicit named parameter, such as the `y` in `format!("{y}")`.
NamedInline(Symbol),
}
+/// Where a format parameter is being used in the format string
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum FormatParamUsage {
+ /// Appears as an argument, e.g. `format!("{}", foo)`
+ Argument,
+ /// Appears as a width, e.g. `format!("{:width$}", foo, width = 1)`
+ Width,
+ /// Appears as a precision, e.g. `format!("{:.precision$}", foo, precision = 1)`
+ Precision,
+}
+
/// A `FormatParam` is any place in a `FormatArgument` that refers to a supplied value, e.g.
///
/// ```
@@ -588,6 +579,8 @@ pub struct FormatParam<'tcx> {
pub value: &'tcx Expr<'tcx>,
/// How this parameter refers to its `value`.
pub kind: FormatParamKind,
+ /// Where this format param is being used - argument/width/precision
+ pub usage: FormatParamUsage,
/// Span of the parameter, may be zero width. Includes the whitespace of implicit parameters.
///
/// ```text
@@ -600,6 +593,7 @@ pub struct FormatParam<'tcx> {
impl<'tcx> FormatParam<'tcx> {
fn new(
mut kind: FormatParamKind,
+ usage: FormatParamUsage,
position: usize,
inner: rpf::InnerSpan,
values: &FormatArgsValues<'tcx>,
@@ -614,7 +608,12 @@ impl<'tcx> FormatParam<'tcx> {
kind = FormatParamKind::NamedInline(name);
}
- Some(Self { value, kind, span })
+ Some(Self {
+ value,
+ kind,
+ usage,
+ span,
+ })
}
}
@@ -628,33 +627,48 @@ pub enum Count<'tcx> {
/// `FormatParamKind::Numbered`.
Param(FormatParam<'tcx>),
/// Not specified.
- Implied,
+ Implied(Option<Span>),
}
impl<'tcx> Count<'tcx> {
fn new(
+ usage: FormatParamUsage,
count: rpf::Count<'_>,
position: Option<usize>,
inner: Option<rpf::InnerSpan>,
values: &FormatArgsValues<'tcx>,
) -> Option<Self> {
+ let span = inner.map(|inner| span_from_inner(values.format_string_span, inner));
+
Some(match count {
- rpf::Count::CountIs(val) => Self::Is(val, span_from_inner(values.format_string_span, inner?)),
- rpf::Count::CountIsName(name, span) => Self::Param(FormatParam::new(
+ rpf::Count::CountIs(val) => Self::Is(val, span?),
+ rpf::Count::CountIsName(name, _) => Self::Param(FormatParam::new(
FormatParamKind::Named(Symbol::intern(name)),
+ usage,
position?,
- span,
+ inner?,
values,
)?),
- rpf::Count::CountIsParam(_) | rpf::Count::CountIsStar(_) => {
- Self::Param(FormatParam::new(FormatParamKind::Numbered, position?, inner?, values)?)
- },
- rpf::Count::CountImplied => Self::Implied,
+ rpf::Count::CountIsParam(_) => Self::Param(FormatParam::new(
+ FormatParamKind::Numbered,
+ usage,
+ position?,
+ inner?,
+ values,
+ )?),
+ rpf::Count::CountIsStar(_) => Self::Param(FormatParam::new(
+ FormatParamKind::Starred,
+ usage,
+ position?,
+ inner?,
+ values,
+ )?),
+ rpf::Count::CountImplied => Self::Implied(span),
})
}
pub fn is_implied(self) -> bool {
- matches!(self, Count::Implied)
+ matches!(self, Count::Implied(_))
}
pub fn param(self) -> Option<FormatParam<'tcx>> {
@@ -663,6 +677,14 @@ impl<'tcx> Count<'tcx> {
_ => None,
}
}
+
+ pub fn span(self) -> Option<Span> {
+ match self {
+ Count::Is(_, span) => Some(span),
+ Count::Param(param) => Some(param.span),
+ Count::Implied(span) => span,
+ }
+ }
}
/// Specification for the formatting of an argument in the format string. See
@@ -691,8 +713,20 @@ impl<'tcx> FormatSpec<'tcx> {
fill: spec.fill,
align: spec.align,
flags: spec.flags,
- precision: Count::new(spec.precision, positions.precision, spec.precision_span, values)?,
- width: Count::new(spec.width, positions.width, spec.width_span, values)?,
+ precision: Count::new(
+ FormatParamUsage::Precision,
+ spec.precision,
+ positions.precision,
+ spec.precision_span,
+ values,
+ )?,
+ width: Count::new(
+ FormatParamUsage::Width,
+ spec.width,
+ positions.width,
+ spec.width_span,
+ values,
+ )?,
r#trait: match spec.ty {
"" => sym::Display,
"?" => sym::Debug,
@@ -711,9 +745,19 @@ impl<'tcx> FormatSpec<'tcx> {
})
}
- /// Returns true if this format spec would change the contents of a string when formatted
- pub fn has_string_formatting(&self) -> bool {
- self.r#trait != sym::Display || !self.width.is_implied() || !self.precision.is_implied()
+ /// Returns true if this format spec is unchanged from the default. e.g. returns true for `{}`,
+ /// `{foo}` and `{2}`, but false for `{:?}`, `{foo:5}` and `{3:.5}`
+ pub fn is_default(&self) -> bool {
+ self.r#trait == sym::Display && self.is_default_for_trait()
+ }
+
+ /// 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
}
}
@@ -728,22 +772,108 @@ pub struct FormatArg<'tcx> {
pub span: Span,
}
+impl<'tcx> FormatArg<'tcx> {
+ /// Span of the `:` and format specifiers
+ ///
+ /// ```ignore
+ /// format!("{:.}"), format!("{foo:.}")
+ /// ^^ ^^
+ /// ```
+ pub fn format_span(&self) -> Span {
+ let base = self.span.data();
+
+ // `base.hi` is `{...}|`, subtract 1 byte (the length of '}') so that it points before the closing
+ // brace `{...|}`
+ Span::new(self.param.span.hi(), base.hi - BytePos(1), base.ctxt, base.parent)
+ }
+}
+
/// A parsed `format_args!` expansion.
#[derive(Debug)]
pub struct FormatArgsExpn<'tcx> {
/// The format string literal.
pub format_string: FormatString,
- // The format arguments, such as `{:?}`.
+ /// The format arguments, such as `{:?}`.
pub args: Vec<FormatArg<'tcx>>,
/// Has an added newline due to `println!()`/`writeln!()`/etc. The last format string part will
/// include this added newline.
pub newline: bool,
- /// Values passed after the format string and implicit captures. `[1, z + 2, x]` for
+ /// Spans of the commas between the format string and explicit values, excluding any trailing
+ /// comma
+ ///
+ /// ```ignore
+ /// format!("..", 1, 2, 3,)
+ /// // ^ ^ ^
+ /// ```
+ comma_spans: Vec<Span>,
+ /// Explicit values passed after the format string, ignoring implicit captures. `[1, z + 2]` for
/// `format!("{x} {} {y}", 1, z + 2)`.
- value_args: Vec<&'tcx Expr<'tcx>>,
+ explicit_values: Vec<&'tcx Expr<'tcx>>,
}
impl<'tcx> FormatArgsExpn<'tcx> {
+ /// Gets the spans of the commas inbetween the format string and explicit args, not including
+ /// any trailing comma
+ ///
+ /// ```ignore
+ /// format!("{} {}", a, b)
+ /// // ^ ^
+ /// ```
+ ///
+ /// Ensures that the format string and values aren't coming from a proc macro that sets the
+ /// output span to that of its input
+ fn comma_spans(cx: &LateContext<'_>, explicit_values: &[&Expr<'_>], fmt_span: Span) -> Option<Vec<Span>> {
+ // `format!("{} {} {c}", "one", "two", c = "three")`
+ // ^^^^^ ^^^^^ ^^^^^^^
+ let value_spans = explicit_values
+ .iter()
+ .map(|val| hygiene::walk_chain(val.span, fmt_span.ctxt()));
+
+ // `format!("{} {} {c}", "one", "two", c = "three")`
+ // ^^ ^^ ^^^^^^
+ let between_spans = once(fmt_span)
+ .chain(value_spans)
+ .tuple_windows()
+ .map(|(start, end)| start.between(end));
+
+ let mut comma_spans = Vec::new();
+ for between_span in between_spans {
+ let mut offset = 0;
+ let mut seen_comma = false;
+
+ for token in tokenize(&snippet_opt(cx, between_span)?) {
+ match token.kind {
+ TokenKind::LineComment { .. } | TokenKind::BlockComment { .. } | TokenKind::Whitespace => {},
+ TokenKind::Comma if !seen_comma => {
+ seen_comma = true;
+
+ let base = between_span.data();
+ comma_spans.push(Span::new(
+ base.lo + BytePos(offset),
+ base.lo + BytePos(offset + 1),
+ base.ctxt,
+ base.parent,
+ ));
+ },
+ // named arguments, `start_val, name = end_val`
+ // ^^^^^^^^^ between_span
+ TokenKind::Ident | TokenKind::Eq if seen_comma => {},
+ // An unexpected token usually indicates the format string or a value came from a proc macro output
+ // that sets the span of its output to an input, e.g. `println!(some_proc_macro!("input"), ..)` that
+ // emits a string literal with the span set to that of `"input"`
+ _ => return None,
+ }
+ offset += token.len;
+ }
+
+ if !seen_comma {
+ return None;
+ }
+ }
+
+ Some(comma_spans)
+ }
+
pub fn parse(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<Self> {
let macro_name = macro_backtrace(expr.span)
.map(|macro_call| cx.tcx.item_name(macro_call.def_id))
@@ -807,6 +937,7 @@ impl<'tcx> FormatArgsExpn<'tcx> {
// NamedInline is handled by `FormatParam::new()`
rpf::Position::ArgumentNamed(name) => FormatParamKind::Named(Symbol::intern(name)),
},
+ FormatParamUsage::Argument,
position.value,
parsed_arg.position_span,
&values,
@@ -817,11 +948,22 @@ impl<'tcx> FormatArgsExpn<'tcx> {
})
.collect::<Option<Vec<_>>>()?;
+ let mut explicit_values = values.value_args;
+ // remove values generated for implicitly captured vars
+ let len = explicit_values
+ .iter()
+ .take_while(|val| !format_string.span.contains(val.span))
+ .count();
+ explicit_values.truncate(len);
+
+ let comma_spans = Self::comma_spans(cx, &explicit_values, format_string.span)?;
+
Some(Self {
format_string,
args,
- value_args: values.value_args,
newline,
+ comma_spans,
+ explicit_values,
})
} else {
None
@@ -829,27 +971,25 @@ impl<'tcx> FormatArgsExpn<'tcx> {
}
pub fn find_nested(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expn_id: ExpnId) -> Option<Self> {
- let mut format_args = None;
- expr_visitor_no_bodies(|e| {
- if format_args.is_some() {
- return false;
- }
+ for_each_expr(expr, |e| {
let e_ctxt = e.span.ctxt();
if e_ctxt == expr.span.ctxt() {
- return true;
- }
- if e_ctxt.outer_expn().is_descendant_of(expn_id) {
- format_args = FormatArgsExpn::parse(cx, e);
+ ControlFlow::Continue(Descend::Yes)
+ } else if e_ctxt.outer_expn().is_descendant_of(expn_id) {
+ if let Some(args) = FormatArgsExpn::parse(cx, e) {
+ ControlFlow::Break(args)
+ } else {
+ ControlFlow::Continue(Descend::No)
+ }
+ } else {
+ ControlFlow::Continue(Descend::No)
}
- false
})
- .visit_expr(expr);
- format_args
}
/// Source callsite span of all inputs
pub fn inputs_span(&self) -> Span {
- match *self.value_args {
+ match *self.explicit_values {
[] => self.format_string.span,
[.., last] => self
.format_string
@@ -858,6 +998,22 @@ impl<'tcx> FormatArgsExpn<'tcx> {
}
}
+ /// Get the span of a value expanded to the previous comma, e.g. for the value `10`
+ ///
+ /// ```ignore
+ /// format("{}.{}", 10, 11)
+ /// // ^^^^
+ /// ```
+ pub fn value_with_prev_comma_span(&self, value_id: HirId) -> Option<Span> {
+ for (comma_span, value) in zip(&self.comma_spans, &self.explicit_values) {
+ if value.hir_id == value_id {
+ return Some(comma_span.to(hygiene::walk_chain(value.span, comma_span.ctxt())));
+ }
+ }
+
+ None
+ }
+
/// Iterator of all format params, both values and those referenced by `width`/`precision`s.
pub fn params(&'tcx self) -> impl Iterator<Item = FormatParam<'tcx>> {
self.args
diff --git a/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs b/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs
new file mode 100644
index 000000000..d262b335d
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/mir/maybe_storage_live.rs
@@ -0,0 +1,52 @@
+use rustc_index::bit_set::BitSet;
+use rustc_middle::mir;
+use rustc_mir_dataflow::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis};
+
+/// Determines liveness of each local purely based on `StorageLive`/`Dead`.
+#[derive(Copy, Clone)]
+pub(super) struct MaybeStorageLive;
+
+impl<'tcx> AnalysisDomain<'tcx> for MaybeStorageLive {
+ type Domain = BitSet<mir::Local>;
+ const NAME: &'static str = "maybe_storage_live";
+
+ fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+ // bottom = dead
+ BitSet::new_empty(body.local_decls.len())
+ }
+
+ fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {
+ for arg in body.args_iter() {
+ state.insert(arg);
+ }
+ }
+}
+
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive {
+ type Idx = mir::Local;
+
+ fn statement_effect(&self, trans: &mut impl GenKill<Self::Idx>, stmt: &mir::Statement<'tcx>, _: mir::Location) {
+ match stmt.kind {
+ mir::StatementKind::StorageLive(l) => trans.gen(l),
+ mir::StatementKind::StorageDead(l) => trans.kill(l),
+ _ => (),
+ }
+ }
+
+ fn terminator_effect(
+ &self,
+ _trans: &mut impl GenKill<Self::Idx>,
+ _terminator: &mir::Terminator<'tcx>,
+ _loc: mir::Location,
+ ) {
+ }
+
+ fn call_return_effect(
+ &self,
+ _trans: &mut impl GenKill<Self::Idx>,
+ _block: mir::BasicBlock,
+ _return_places: CallReturnPlaces<'_, 'tcx>,
+ ) {
+ // Nothing to do when a call returns successfully
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
new file mode 100644
index 000000000..818e603f6
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -0,0 +1,164 @@
+use rustc_hir::{Expr, HirId};
+use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::{
+ traversal, Body, InlineAsmOperand, Local, Location, Place, StatementKind, TerminatorKind, START_BLOCK,
+};
+use rustc_middle::ty::TyCtxt;
+
+mod maybe_storage_live;
+
+mod possible_borrower;
+pub use possible_borrower::PossibleBorrowerMap;
+
+mod possible_origin;
+
+mod transitive_relation;
+
+#[derive(Clone, Debug, Default)]
+pub struct LocalUsage {
+ /// The locations where the local is used, if any.
+ pub local_use_locs: Vec<Location>,
+ /// The locations where the local is consumed or mutated, if any.
+ pub local_consume_or_mutate_locs: Vec<Location>,
+}
+
+pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -> Option<Vec<LocalUsage>> {
+ let init = vec![
+ LocalUsage {
+ local_use_locs: Vec::new(),
+ local_consume_or_mutate_locs: Vec::new(),
+ };
+ locals.len()
+ ];
+
+ traversal::ReversePostorder::new(mir, location.block).try_fold(init, |usage, (tbb, tdata)| {
+ // Give up on loops
+ if tdata.terminator().successors().any(|s| s == location.block) {
+ return None;
+ }
+
+ let mut v = V {
+ locals,
+ location,
+ results: usage,
+ };
+ v.visit_basic_block_data(tbb, tdata);
+ Some(v.results)
+ })
+}
+
+struct V<'a> {
+ locals: &'a [Local],
+ location: Location,
+ results: Vec<LocalUsage>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for V<'a> {
+ fn visit_place(&mut self, place: &Place<'tcx>, ctx: PlaceContext, loc: Location) {
+ if loc.block == self.location.block && loc.statement_index <= self.location.statement_index {
+ return;
+ }
+
+ let local = place.local;
+
+ for (i, self_local) in self.locals.iter().enumerate() {
+ if local == *self_local {
+ if !matches!(
+ ctx,
+ PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_)
+ ) {
+ self.results[i].local_use_locs.push(loc);
+ }
+ if matches!(
+ ctx,
+ PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
+ | PlaceContext::MutatingUse(MutatingUseContext::Borrow)
+ ) {
+ self.results[i].local_consume_or_mutate_locs.push(loc);
+ }
+ }
+ }
+ }
+}
+
+/// Convenience wrapper around `visit_local_usage`.
+pub fn used_exactly_once(mir: &rustc_middle::mir::Body<'_>, local: rustc_middle::mir::Local) -> Option<bool> {
+ visit_local_usage(
+ &[local],
+ mir,
+ Location {
+ block: START_BLOCK,
+ statement_index: 0,
+ },
+ )
+ .map(|mut vec| {
+ let LocalUsage { local_use_locs, .. } = vec.remove(0);
+ local_use_locs
+ .into_iter()
+ .filter(|location| !is_local_assignment(mir, local, *location))
+ .count()
+ == 1
+ })
+}
+
+/// Returns the `mir::Body` containing the node associated with `hir_id`.
+#[allow(clippy::module_name_repetitions)]
+pub fn enclosing_mir(tcx: TyCtxt<'_>, hir_id: HirId) -> &Body<'_> {
+ let body_owner_local_def_id = tcx.hir().enclosing_body_owner(hir_id);
+ tcx.optimized_mir(body_owner_local_def_id.to_def_id())
+}
+
+/// Tries to determine the `Local` corresponding to `expr`, if any.
+/// This function is expensive and should be used sparingly.
+pub fn expr_local(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> Option<Local> {
+ let mir = enclosing_mir(tcx, expr.hir_id);
+ mir.local_decls.iter_enumerated().find_map(|(local, local_decl)| {
+ if local_decl.source_info.span == expr.span {
+ Some(local)
+ } else {
+ None
+ }
+ })
+}
+
+/// Returns a vector of `mir::Location` where `local` is assigned.
+pub fn local_assignments(mir: &Body<'_>, local: Local) -> Vec<Location> {
+ let mut locations = Vec::new();
+ for (block, data) in mir.basic_blocks.iter_enumerated() {
+ for statement_index in 0..=data.statements.len() {
+ let location = Location { block, statement_index };
+ if is_local_assignment(mir, local, location) {
+ locations.push(location);
+ }
+ }
+ }
+ locations
+}
+
+// `is_local_assignment` is based on `is_place_assignment`:
+// https://github.com/rust-lang/rust/blob/b7413511dc85ec01ef4b91785f86614589ac6103/compiler/rustc_middle/src/mir/visit.rs#L1350
+fn is_local_assignment(mir: &Body<'_>, local: Local, location: Location) -> bool {
+ let Location { block, statement_index } = location;
+ let basic_block = &mir.basic_blocks[block];
+ if statement_index < basic_block.statements.len() {
+ let statement = &basic_block.statements[statement_index];
+ if let StatementKind::Assign(box (place, _)) = statement.kind {
+ place.as_local() == Some(local)
+ } else {
+ false
+ }
+ } else {
+ let terminator = basic_block.terminator();
+ match &terminator.kind {
+ TerminatorKind::Call { destination, .. } => destination.as_local() == Some(local),
+ TerminatorKind::InlineAsm { operands, .. } => operands.iter().any(|operand| {
+ if let InlineAsmOperand::Out { place: Some(place), .. } = operand {
+ place.as_local() == Some(local)
+ } else {
+ false
+ }
+ }),
+ _ => false,
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
new file mode 100644
index 000000000..25717bf3d
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_borrower.rs
@@ -0,0 +1,241 @@
+use super::{
+ maybe_storage_live::MaybeStorageLive, possible_origin::PossibleOriginVisitor,
+ transitive_relation::TransitiveRelation,
+};
+use crate::ty::is_copy;
+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_mir_dataflow::{Analysis, ResultsCursor};
+use std::ops::ControlFlow;
+
+/// Collects the possible borrowers of each local.
+/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c`
+/// possible borrowers of `a`.
+#[allow(clippy::module_name_repetitions)]
+struct PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+ possible_borrower: TransitiveRelation,
+ body: &'b mir::Body<'tcx>,
+ cx: &'a LateContext<'tcx>,
+ possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+}
+
+impl<'a, 'b, 'tcx> PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+ fn new(
+ cx: &'a LateContext<'tcx>,
+ body: &'b mir::Body<'tcx>,
+ possible_origin: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+ ) -> Self {
+ Self {
+ possible_borrower: TransitiveRelation::default(),
+ cx,
+ body,
+ possible_origin,
+ }
+ }
+
+ fn into_map(
+ self,
+ cx: &'a LateContext<'tcx>,
+ maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>,
+ ) -> PossibleBorrowerMap<'b, 'tcx> {
+ let mut map = FxHashMap::default();
+ for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
+ if is_copy(cx, self.body.local_decls[row].ty) {
+ continue;
+ }
+
+ let mut borrowers = self.possible_borrower.reachable_from(row, self.body.local_decls.len());
+ borrowers.remove(mir::Local::from_usize(0));
+ if !borrowers.is_empty() {
+ map.insert(row, borrowers);
+ }
+ }
+
+ let bs = BitSet::new_empty(self.body.local_decls.len());
+ PossibleBorrowerMap {
+ map,
+ maybe_live,
+ bitset: (bs.clone(), bs),
+ }
+ }
+}
+
+impl<'a, 'b, 'tcx> mir::visit::Visitor<'tcx> for PossibleBorrowerVisitor<'a, 'b, 'tcx> {
+ fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
+ let lhs = place.local;
+ match rvalue {
+ mir::Rvalue::Ref(_, _, borrowed) => {
+ self.possible_borrower.add(borrowed.local, lhs);
+ },
+ other => {
+ if ContainsRegion
+ .visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
+ .is_continue()
+ {
+ return;
+ }
+ rvalue_locals(other, |rhs| {
+ if lhs != rhs {
+ self.possible_borrower.add(rhs, lhs);
+ }
+ });
+ },
+ }
+ }
+
+ fn visit_terminator(&mut self, terminator: &mir::Terminator<'_>, _loc: mir::Location) {
+ if let mir::TerminatorKind::Call {
+ args,
+ destination: mir::Place { local: dest, .. },
+ ..
+ } = &terminator.kind
+ {
+ // TODO add doc
+ // If the call returns something with lifetimes,
+ // let's conservatively assume the returned value contains lifetime of all the arguments.
+ // For example, given `let y: Foo<'a> = foo(x)`, `y` is considered to be a possible borrower of `x`.
+
+ let mut immutable_borrowers = vec![];
+ let mut mutable_borrowers = vec![];
+
+ for op in args {
+ match op {
+ mir::Operand::Copy(p) | mir::Operand::Move(p) => {
+ if let ty::Ref(_, _, Mutability::Mut) = self.body.local_decls[p.local].ty.kind() {
+ mutable_borrowers.push(p.local);
+ } else {
+ immutable_borrowers.push(p.local);
+ }
+ },
+ mir::Operand::Constant(..) => (),
+ }
+ }
+
+ let mut mutable_variables: Vec<mir::Local> = mutable_borrowers
+ .iter()
+ .filter_map(|r| self.possible_origin.get(r))
+ .flat_map(HybridBitSet::iter)
+ .collect();
+
+ if ContainsRegion.visit_ty(self.body.local_decls[*dest].ty).is_break() {
+ mutable_variables.push(*dest);
+ }
+
+ for y in mutable_variables {
+ for x in &immutable_borrowers {
+ self.possible_borrower.add(*x, y);
+ }
+ for x in &mutable_borrowers {
+ self.possible_borrower.add(*x, y);
+ }
+ }
+ }
+ }
+}
+
+struct ContainsRegion;
+
+impl TypeVisitor<'_> for ContainsRegion {
+ type BreakTy = ();
+
+ fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
+ ControlFlow::BREAK
+ }
+}
+
+fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) {
+ use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use};
+
+ let mut visit_op = |op: &mir::Operand<'_>| match op {
+ mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local),
+ mir::Operand::Constant(..) => (),
+ };
+
+ match rvalue {
+ Use(op) | Repeat(op, _) | Cast(_, op, _) | UnaryOp(_, op) => visit_op(op),
+ Aggregate(_, ops) => ops.iter().for_each(visit_op),
+ BinaryOp(_, box (lhs, rhs)) | CheckedBinaryOp(_, box (lhs, rhs)) => {
+ visit_op(lhs);
+ visit_op(rhs);
+ },
+ _ => (),
+ }
+}
+
+/// Result of `PossibleBorrowerVisitor`.
+#[allow(clippy::module_name_repetitions)]
+pub struct PossibleBorrowerMap<'b, 'tcx> {
+ /// Mapping `Local -> its possible borrowers`
+ pub map: FxHashMap<mir::Local, HybridBitSet<mir::Local>>,
+ maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive>,
+ // Caches to avoid allocation of `BitSet` on every query
+ pub bitset: (BitSet<mir::Local>, BitSet<mir::Local>),
+}
+
+impl<'a, 'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> {
+ pub fn new(cx: &'a LateContext<'tcx>, mir: &'b mir::Body<'tcx>) -> Self {
+ let possible_origin = {
+ let mut vis = PossibleOriginVisitor::new(mir);
+ vis.visit_body(mir);
+ vis.into_map(cx)
+ };
+ let maybe_storage_live_result = MaybeStorageLive
+ .into_engine(cx.tcx, mir)
+ .pass_name("redundant_clone")
+ .iterate_to_fixpoint()
+ .into_results_cursor(mir);
+ let mut vis = PossibleBorrowerVisitor::new(cx, mir, possible_origin);
+ vis.visit_body(mir);
+ vis.into_map(cx, maybe_storage_live_result)
+ }
+
+ /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`.
+ pub fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool {
+ self.bounded_borrowers(borrowers, borrowers, borrowed, at)
+ }
+
+ /// Returns true if the set of borrowers of `borrowed` living at `at` includes at least `below`
+ /// but no more than `above`.
+ pub fn bounded_borrowers(
+ &mut self,
+ below: &[mir::Local],
+ above: &[mir::Local],
+ borrowed: mir::Local,
+ at: mir::Location,
+ ) -> bool {
+ self.maybe_live.seek_after_primary_effect(at);
+
+ self.bitset.0.clear();
+ let maybe_live = &mut self.maybe_live;
+ if let Some(bitset) = self.map.get(&borrowed) {
+ for b in bitset.iter().filter(move |b| maybe_live.contains(*b)) {
+ self.bitset.0.insert(b);
+ }
+ } else {
+ return false;
+ }
+
+ self.bitset.1.clear();
+ for b in below {
+ self.bitset.1.insert(*b);
+ }
+
+ if !self.bitset.0.superset(&self.bitset.1) {
+ return false;
+ }
+
+ for b in above {
+ self.bitset.0.remove(*b);
+ }
+
+ self.bitset.0.is_empty()
+ }
+
+ pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool {
+ self.maybe_live.seek_after_primary_effect(at);
+ self.maybe_live.contains(local)
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs
new file mode 100644
index 000000000..8e7513d74
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/mir/possible_origin.rs
@@ -0,0 +1,59 @@
+use super::transitive_relation::TransitiveRelation;
+use crate::ty::is_copy;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_index::bit_set::HybridBitSet;
+use rustc_lint::LateContext;
+use rustc_middle::mir;
+
+/// Collect possible borrowed for every `&mut` local.
+/// For example, `_1 = &mut _2` generate _1: {_2,...}
+/// Known Problems: not sure all borrowed are tracked
+#[allow(clippy::module_name_repetitions)]
+pub(super) struct PossibleOriginVisitor<'a, 'tcx> {
+ possible_origin: TransitiveRelation,
+ body: &'a mir::Body<'tcx>,
+}
+
+impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> {
+ pub fn new(body: &'a mir::Body<'tcx>) -> Self {
+ Self {
+ possible_origin: TransitiveRelation::default(),
+ body,
+ }
+ }
+
+ pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap<mir::Local, HybridBitSet<mir::Local>> {
+ let mut map = FxHashMap::default();
+ for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) {
+ if is_copy(cx, self.body.local_decls[row].ty) {
+ continue;
+ }
+
+ let mut borrowers = self.possible_origin.reachable_from(row, self.body.local_decls.len());
+ borrowers.remove(mir::Local::from_usize(0));
+ if !borrowers.is_empty() {
+ map.insert(row, borrowers);
+ }
+ }
+ map
+ }
+}
+
+impl<'a, 'tcx> mir::visit::Visitor<'tcx> for PossibleOriginVisitor<'a, 'tcx> {
+ fn visit_assign(&mut self, place: &mir::Place<'tcx>, rvalue: &mir::Rvalue<'_>, _location: mir::Location) {
+ let lhs = place.local;
+ match rvalue {
+ // Only consider `&mut`, which can modify origin place
+ mir::Rvalue::Ref(_, rustc_middle::mir::BorrowKind::Mut { .. }, borrowed) |
+ // _2: &mut _;
+ // _3 = move _2
+ mir::Rvalue::Use(mir::Operand::Move(borrowed)) |
+ // _3 = move _2 as &mut _;
+ mir::Rvalue::Cast(_, mir::Operand::Move(borrowed), _)
+ => {
+ self.possible_origin.add(lhs, borrowed.local);
+ },
+ _ => {},
+ }
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs
new file mode 100644
index 000000000..7fe296073
--- /dev/null
+++ b/src/tools/clippy/clippy_utils/src/mir/transitive_relation.rs
@@ -0,0 +1,29 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_index::bit_set::HybridBitSet;
+use rustc_middle::mir;
+
+#[derive(Default)]
+pub(super) struct TransitiveRelation {
+ relations: FxHashMap<mir::Local, Vec<mir::Local>>,
+}
+
+impl TransitiveRelation {
+ pub fn add(&mut self, a: mir::Local, b: mir::Local) {
+ self.relations.entry(a).or_default().push(b);
+ }
+
+ pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> HybridBitSet<mir::Local> {
+ let mut seen = HybridBitSet::new_empty(domain_size);
+ let mut stack = vec![a];
+ while let Some(u) = stack.pop() {
+ if let Some(edges) = self.relations.get(&u) {
+ for &v in edges {
+ if seen.insert(v) {
+ stack.push(v);
+ }
+ }
+ }
+ }
+ seen
+ }
+}
diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs
index 62020e21c..8b843732a 100644
--- a/src/tools/clippy/clippy_utils/src/msrvs.rs
+++ b/src/tools/clippy/clippy_utils/src/msrvs.rs
@@ -13,10 +13,11 @@ macro_rules! msrv_aliases {
// names may refer to stabilized feature flags or library items
msrv_aliases! {
1,62,0 { BOOL_THEN_SOME }
+ 1,58,0 { FORMAT_ARGS_CAPTURE }
1,53,0 { OR_PATTERNS, MANUAL_BITS, BTREE_MAP_RETAIN, BTREE_SET_RETAIN, ARRAY_INTO_ITERATOR }
1,52,0 { STR_SPLIT_ONCE, REM_EUCLID_CONST }
1,51,0 { BORROW_AS_PTR, UNSIGNED_ABS }
- 1,50,0 { BOOL_THEN }
+ 1,50,0 { BOOL_THEN, CLAMP }
1,47,0 { TAU }
1,46,0 { CONST_IF_MATCH }
1,45,0 { STR_STRIP_PREFIX }
diff --git a/src/tools/clippy/clippy_utils/src/numeric_literal.rs b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
index 80098d976..c5dcd7b31 100644
--- a/src/tools/clippy/clippy_utils/src/numeric_literal.rs
+++ b/src/tools/clippy/clippy_utils/src/numeric_literal.rs
@@ -69,12 +69,13 @@ impl<'a> NumericLiteral<'a> {
#[must_use]
pub fn new(lit: &'a str, suffix: Option<&'a str>, float: bool) -> Self {
+ let unsigned_lit = lit.trim_start_matches('-');
// Determine delimiter for radix prefix, if present, and radix.
- let radix = if lit.starts_with("0x") {
+ let radix = if unsigned_lit.starts_with("0x") {
Radix::Hexadecimal
- } else if lit.starts_with("0b") {
+ } else if unsigned_lit.starts_with("0b") {
Radix::Binary
- } else if lit.starts_with("0o") {
+ } else if unsigned_lit.starts_with("0o") {
Radix::Octal
} else {
Radix::Decimal
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 07170e2df..bc8514734 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -16,26 +16,17 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
#[cfg(feature = "internal")]
pub const DIAGNOSTIC_BUILDER: [&str; 3] = ["rustc_errors", "diagnostic_builder", "DiagnosticBuilder"];
pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
-pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"];
-pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"];
pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
-pub const BTREEMAP_ENTRY: [&str; 6] = ["alloc", "collections", "btree", "map", "entry", "Entry"];
pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
-pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
pub const CORE_ITER_COLLECT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "collect"];
pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
-pub const CORE_ITER_INTO_ITER: [&str; 6] = ["core", "iter", "traits", "collect", "IntoIterator", "into_iter"];
pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
-/// Preferably use the diagnostic item `sym::deref_method` where possible
-pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
-pub const DIR_BUILDER: [&str; 3] = ["std", "fs", "DirBuilder"];
-pub const DISPLAY_TRAIT: [&str; 3] = ["core", "fmt", "Display"];
#[cfg(feature = "internal")]
pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
#[cfg(feature = "internal")]
@@ -43,32 +34,22 @@ pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"]
pub const EXIT: [&str; 3] = ["std", "process", "exit"];
pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
-pub const FILE: [&str; 3] = ["std", "fs", "File"];
-pub const FILE_TYPE: [&str; 3] = ["std", "fs", "FileType"];
-pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"];
pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"];
-pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
-pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"];
pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"];
#[cfg(feature = "internal")]
pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
#[cfg(feature = "internal")]
pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
-pub const INDEX: [&str; 3] = ["core", "ops", "Index"];
-pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"];
pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
-pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
-pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"];
pub const ITER_EMPTY: [&str; 5] = ["core", "iter", "sources", "empty", "Empty"];
-pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"];
pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
#[cfg(feature = "internal")]
pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
@@ -79,13 +60,7 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
#[cfg(feature = "internal")]
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
-pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
-/// Preferably use the diagnostic item `sym::Option` where possible
-pub const OPTION: [&str; 3] = ["core", "option", "Option"];
-pub const OPTION_NONE: [&str; 4] = ["core", "option", "Option", "None"];
-pub const OPTION_SOME: [&str; 4] = ["core", "option", "Option", "Some"];
-pub const ORD: [&str; 3] = ["core", "cmp", "Ord"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
@@ -98,8 +73,6 @@ pub const PERMISSIONS: [&str; 3] = ["std", "fs", "Permissions"];
#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
-pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
-pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
pub const PTR_COPY: [&str; 3] = ["core", "intrinsics", "copy"];
pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
@@ -122,26 +95,14 @@ pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"];
pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"];
pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
-/// Preferably use the diagnostic item `sym::Result` where possible
-pub const RESULT: [&str; 3] = ["core", "result", "Result"];
-pub const RESULT_ERR: [&str; 4] = ["core", "result", "Result", "Err"];
-pub const RESULT_OK: [&str; 4] = ["core", "result", "Result", "Ok"];
#[cfg(feature = "internal")]
pub const RUSTC_VERSION: [&str; 2] = ["rustc_semver", "RustcVersion"];
-pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGuard"];
-pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
diff --git a/src/tools/clippy/clippy_utils/src/ptr.rs b/src/tools/clippy/clippy_utils/src/ptr.rs
index 0226f7490..88837d8a1 100644
--- a/src/tools/clippy/clippy_utils/src/ptr.rs
+++ b/src/tools/clippy/clippy_utils/src/ptr.rs
@@ -1,7 +1,7 @@
use crate::source::snippet;
-use crate::visitors::expr_visitor_no_bodies;
+use crate::visitors::{for_each_expr, Descend};
use crate::{path_to_local_id, strip_pat_refs};
-use rustc_hir::intravisit::Visitor;
+use core::ops::ControlFlow;
use rustc_hir::{Body, BodyId, ExprKind, HirId, PatKind};
use rustc_lint::LateContext;
use rustc_span::Span;
@@ -30,28 +30,23 @@ fn extract_clone_suggestions<'tcx>(
replace: &[(&'static str, &'static str)],
body: &'tcx Body<'_>,
) -> Option<Vec<(Span, Cow<'static, str>)>> {
- let mut abort = false;
let mut spans = Vec::new();
- expr_visitor_no_bodies(|expr| {
- if abort {
- return false;
- }
- if let ExprKind::MethodCall(seg, recv, [], _) = expr.kind {
- if path_to_local_id(recv, id) {
- if seg.ident.name.as_str() == "capacity" {
- abort = true;
- return false;
- }
- for &(fn_name, suffix) in replace {
- if seg.ident.name.as_str() == fn_name {
- spans.push((expr.span, snippet(cx, recv.span, "_") + suffix));
- return false;
- }
+ for_each_expr(body, |e| {
+ if let ExprKind::MethodCall(seg, recv, [], _) = e.kind
+ && path_to_local_id(recv, id)
+ {
+ if seg.ident.as_str() == "capacity" {
+ return ControlFlow::Break(());
+ }
+ for &(fn_name, suffix) in replace {
+ if seg.ident.as_str() == fn_name {
+ spans.push((e.span, snippet(cx, recv.span, "_") + suffix));
+ return ControlFlow::Continue(Descend::No);
}
}
}
- !abort
+ ControlFlow::Continue(Descend::Yes)
})
- .visit_body(body);
- if abort { None } else { Some(spans) }
+ .is_none()
+ .then_some(spans)
}
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 8835b9329..45b63a4aa 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
@@ -33,10 +33,10 @@ pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv:
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Trait(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => continue,
- 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),
- ty::PredicateKind::Coerce(_) => panic!("coerce 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:#?}"),
+ ty::PredicateKind::Coerce(_) => panic!("coerce predicate on function: {predicate:#?}"),
}
}
match predicates.parent {
@@ -129,7 +129,12 @@ fn check_rvalue<'tcx>(
| Rvalue::Use(operand)
| Rvalue::Cast(
CastKind::PointerFromExposedAddress
- | CastKind::Misc
+ | CastKind::IntToInt
+ | CastKind::FloatToInt
+ | CastKind::IntToFloat
+ | CastKind::FloatToFloat
+ | CastKind::FnPtrToPtr
+ | CastKind::PtrToPtr
| CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
operand,
_,
@@ -260,6 +265,7 @@ fn check_place<'tcx>(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &B
}
},
ProjectionElem::ConstantIndex { .. }
+ | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Downcast(..)
| ProjectionElem::Subslice { .. }
| ProjectionElem::Deref
@@ -318,8 +324,7 @@ fn check_terminator<'a, 'tcx>(
span,
format!(
"can only call other `const fn` within a `const fn`, \
- but `{:?}` is not stable as `const fn`",
- func,
+ but `{func:?}` is not stable as `const fn`",
)
.into(),
));
@@ -366,10 +371,23 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<RustcVersion>) -> bo
// Checking MSRV is manually necessary because `rustc` has no such concept. This entire
// function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
// as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
+
+ // HACK(nilstrieb): CURRENT_RUSTC_VERSION can return versions like 1.66.0-dev. `rustc-semver`
+ // doesn't accept the `-dev` version number so we have to strip it
+ // off.
+ let short_version = since
+ .as_str()
+ .split('-')
+ .next()
+ .expect("rustc_attr::StabilityLevel::Stable::since` is empty");
+
+ let since = rustc_span::Symbol::intern(short_version);
+
crate::meets_msrv(
msrv,
- RustcVersion::parse(since.as_str())
- .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"),
+ RustcVersion::parse(since.as_str()).unwrap_or_else(|err| {
+ panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")
+ }),
)
} else {
// Unstable const fn with the feature enabled.
diff --git a/src/tools/clippy/clippy_utils/src/source.rs b/src/tools/clippy/clippy_utils/src/source.rs
index d85f591fb..d28bd92d7 100644
--- a/src/tools/clippy/clippy_utils/src/source.rs
+++ b/src/tools/clippy/clippy_utils/src/source.rs
@@ -25,11 +25,11 @@ pub fn expr_block<'a, T: LintContext>(
if expr.span.from_expansion() {
Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
} else if let ExprKind::Block(_, _) = expr.kind {
- Cow::Owned(format!("{}{}", code, string))
+ Cow::Owned(format!("{code}{string}"))
} else if string.is_empty() {
- Cow::Owned(format!("{{ {} }}", code))
+ Cow::Owned(format!("{{ {code} }}"))
} else {
- Cow::Owned(format!("{{\n{};\n{}\n}}", code, string))
+ Cow::Owned(format!("{{\n{code};\n{string}\n}}"))
}
}
@@ -392,6 +392,16 @@ pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
.span()
}
+/// Expand a span to include a preceding comma
+/// ```rust,ignore
+/// writeln!(o, "") -> writeln!(o, "")
+/// ^^ ^^^^
+/// ```
+pub fn expand_past_previous_comma(cx: &LateContext<'_>, span: Span) -> Span {
+ let extended = cx.sess().source_map().span_extend_to_prev_char(span, ',', true);
+ extended.with_lo(extended.lo() - BytePos(1))
+}
+
#[cfg(test)]
mod test {
use super::{reindent_multiline, without_block_comments};
@@ -466,7 +476,7 @@ mod test {
#[test]
fn test_without_block_comments_lines_without_block_comments() {
let result = without_block_comments(vec!["/*", "", "*/"]);
- println!("result: {:?}", result);
+ println!("result: {result:?}");
assert!(result.is_empty());
let result = without_block_comments(vec!["", "/*", "", "*/", "#[crate_type = \"lib\"]", "/*", "", "*/", ""]);
diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs
index cca71bbf7..aad7da61a 100644
--- a/src/tools/clippy/clippy_utils/src/sugg.rs
+++ b/src/tools/clippy/clippy_utils/src/sugg.rs
@@ -1,7 +1,9 @@
//! Contains utility functions to generate suggestions.
#![deny(clippy::missing_docs_in_private_items)]
-use crate::source::{snippet, snippet_opt, snippet_with_applicability, snippet_with_macro_callsite};
+use crate::source::{
+ snippet, snippet_opt, snippet_with_applicability, snippet_with_context, snippet_with_macro_callsite,
+};
use crate::ty::expr_sig;
use crate::{get_parent_expr_for_hir, higher};
use rustc_ast::util::parser::AssocOp;
@@ -10,19 +12,19 @@ use rustc_ast_pretty::pprust::token_kind_to_string;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::{Closure, ExprKind, HirId, MutTy, TyKind};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{EarlyContext, LateContext, LintContext};
use rustc_middle::hir::place::ProjectionKind;
use rustc_middle::mir::{FakeReadCause, Mutability};
use rustc_middle::ty;
use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext};
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use std::borrow::Cow;
use std::fmt::{Display, Write as _};
use std::ops::{Add, Neg, Not, Sub};
/// A helper type to build suggestion correctly handling parentheses.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub enum Sugg<'a> {
/// An expression that never needs parentheses such as `1337` or `[0; 42]`.
NonParen(Cow<'a, str>),
@@ -110,7 +112,7 @@ impl<'a> Sugg<'a> {
if expr.span.ctxt() == ctxt {
Self::hir_from_snippet(expr, |span| snippet(cx, span, default))
} else {
- let snip = snippet_with_applicability(cx, expr.span, default, applicability);
+ let (snip, _) = snippet_with_context(cx, expr.span, ctxt, default, applicability);
Sugg::NonParen(snip)
}
}
@@ -155,8 +157,8 @@ impl<'a> Sugg<'a> {
| hir::ExprKind::Ret(..)
| hir::ExprKind::Struct(..)
| hir::ExprKind::Tup(..)
- | hir::ExprKind::DropTemps(_)
| 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))
},
@@ -177,11 +179,11 @@ impl<'a> Sugg<'a> {
pub fn ast(cx: &EarlyContext<'_>, expr: &ast::Expr, default: &'a str) -> Self {
use rustc_ast::ast::RangeLimits;
- let get_whole_snippet = || {
- if expr.span.from_expansion() {
- snippet_with_macro_callsite(cx, expr.span, default)
+ let snippet_without_expansion = |cx, span: Span, default| {
+ if span.from_expansion() {
+ snippet_with_macro_callsite(cx, span, default)
} else {
- snippet(cx, expr.span, default)
+ snippet(cx, span, default)
}
};
@@ -192,7 +194,7 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::If(..)
| ast::ExprKind::Let(..)
| ast::ExprKind::Unary(..)
- | ast::ExprKind::Match(..) => Sugg::MaybeParen(get_whole_snippet()),
+ | ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet_without_expansion(cx, expr.span, default)),
ast::ExprKind::Async(..)
| ast::ExprKind::Block(..)
| ast::ExprKind::Break(..)
@@ -221,41 +223,45 @@ impl<'a> Sugg<'a> {
| ast::ExprKind::Array(..)
| ast::ExprKind::While(..)
| ast::ExprKind::Await(..)
- | ast::ExprKind::Err => Sugg::NonParen(get_whole_snippet()),
+ | ast::ExprKind::Err => Sugg::NonParen(snippet_without_expansion(cx, expr.span, default)),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::HalfOpen) => Sugg::BinOp(
AssocOp::DotDot,
- lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
- rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
+ lhs.as_ref()
+ .map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
+ rhs.as_ref()
+ .map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
),
ast::ExprKind::Range(ref lhs, ref rhs, RangeLimits::Closed) => Sugg::BinOp(
AssocOp::DotDotEq,
- lhs.as_ref().map_or("".into(), |lhs| snippet(cx, lhs.span, default)),
- rhs.as_ref().map_or("".into(), |rhs| snippet(cx, rhs.span, default)),
+ lhs.as_ref()
+ .map_or("".into(), |lhs| snippet_without_expansion(cx, lhs.span, default)),
+ rhs.as_ref()
+ .map_or("".into(), |rhs| snippet_without_expansion(cx, rhs.span, default)),
),
ast::ExprKind::Assign(ref lhs, ref rhs, _) => Sugg::BinOp(
AssocOp::Assign,
- snippet(cx, lhs.span, default),
- snippet(cx, rhs.span, default),
+ snippet_without_expansion(cx, lhs.span, default),
+ snippet_without_expansion(cx, rhs.span, default),
),
ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => Sugg::BinOp(
astbinop2assignop(op),
- snippet(cx, lhs.span, default),
- snippet(cx, rhs.span, default),
+ snippet_without_expansion(cx, lhs.span, default),
+ snippet_without_expansion(cx, rhs.span, default),
),
ast::ExprKind::Binary(op, ref lhs, ref rhs) => Sugg::BinOp(
AssocOp::from_ast_binop(op.node),
- snippet(cx, lhs.span, default),
- snippet(cx, rhs.span, default),
+ snippet_without_expansion(cx, lhs.span, default),
+ snippet_without_expansion(cx, rhs.span, default),
),
ast::ExprKind::Cast(ref lhs, ref ty) => Sugg::BinOp(
AssocOp::As,
- snippet(cx, lhs.span, default),
- snippet(cx, ty.span, default),
+ snippet_without_expansion(cx, lhs.span, default),
+ snippet_without_expansion(cx, ty.span, default),
),
ast::ExprKind::Type(ref lhs, ref ty) => Sugg::BinOp(
AssocOp::Colon,
- snippet(cx, lhs.span, default),
- snippet(cx, ty.span, default),
+ snippet_without_expansion(cx, lhs.span, default),
+ snippet_without_expansion(cx, ty.span, default),
),
}
}
@@ -306,19 +312,19 @@ impl<'a> Sugg<'a> {
/// Convenience method to transform suggestion into a return call
pub fn make_return(self) -> Sugg<'static> {
- Sugg::NonParen(Cow::Owned(format!("return {}", self)))
+ Sugg::NonParen(Cow::Owned(format!("return {self}")))
}
/// Convenience method to transform suggestion into a block
/// where the suggestion is a trailing expression
pub fn blockify(self) -> Sugg<'static> {
- Sugg::NonParen(Cow::Owned(format!("{{ {} }}", self)))
+ Sugg::NonParen(Cow::Owned(format!("{{ {self} }}")))
}
/// Convenience method to prefix the expression with the `async` keyword.
/// Can be used after `blockify` to create an async block.
pub fn asyncify(self) -> Sugg<'static> {
- Sugg::NonParen(Cow::Owned(format!("async {}", self)))
+ Sugg::NonParen(Cow::Owned(format!("async {self}")))
}
/// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>`
@@ -342,12 +348,12 @@ impl<'a> Sugg<'a> {
if has_enclosing_paren(&sugg) {
Sugg::MaybeParen(sugg)
} else {
- Sugg::NonParen(format!("({})", sugg).into())
+ Sugg::NonParen(format!("({sugg})").into())
}
},
Sugg::BinOp(op, lhs, rhs) => {
let sugg = binop_to_string(op, &lhs, &rhs);
- Sugg::NonParen(format!("({})", sugg).into())
+ Sugg::NonParen(format!("({sugg})").into())
},
}
}
@@ -375,20 +381,18 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String {
| AssocOp::Greater
| AssocOp::GreaterEqual => {
format!(
- "{} {} {}",
- lhs,
- op.to_ast_binop().expect("Those are AST ops").to_string(),
- rhs
+ "{lhs} {} {rhs}",
+ op.to_ast_binop().expect("Those are AST ops").to_string()
)
},
- AssocOp::Assign => format!("{} = {}", lhs, rhs),
+ AssocOp::Assign => format!("{lhs} = {rhs}"),
AssocOp::AssignOp(op) => {
- format!("{} {}= {}", lhs, token_kind_to_string(&token::BinOp(op)), rhs)
+ format!("{lhs} {}= {rhs}", token_kind_to_string(&token::BinOp(op)))
},
- AssocOp::As => format!("{} as {}", lhs, rhs),
- AssocOp::DotDot => format!("{}..{}", lhs, rhs),
- AssocOp::DotDotEq => format!("{}..={}", lhs, rhs),
- AssocOp::Colon => format!("{}: {}", lhs, rhs),
+ AssocOp::As => format!("{lhs} as {rhs}"),
+ AssocOp::DotDot => format!("{lhs}..{rhs}"),
+ AssocOp::DotDotEq => format!("{lhs}..={rhs}"),
+ AssocOp::Colon => format!("{lhs}: {rhs}"),
}
}
@@ -519,7 +523,7 @@ impl<T: Display> Display for ParenHelper<T> {
/// operators have the same
/// precedence.
pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
- Sugg::MaybeParen(format!("{}{}", op, expr.maybe_par()).into())
+ Sugg::MaybeParen(format!("{op}{}", expr.maybe_par()).into())
}
/// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@@ -740,7 +744,7 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
if let Some(indent) = indentation(cx, item) {
let span = item.with_hi(item.lo());
- self.span_suggestion(span, msg, format!("{}\n{}", attr, indent), applicability);
+ self.span_suggestion(span, msg, format!("{attr}\n{indent}"), applicability);
}
}
@@ -754,21 +758,20 @@ impl<T: LintContext> DiagnosticExt<T> for rustc_errors::Diagnostic {
.map(|l| {
if first {
first = false;
- format!("{}\n", l)
+ format!("{l}\n")
} else {
- format!("{}{}\n", indent, l)
+ format!("{indent}{l}\n")
}
})
.collect::<String>();
- self.span_suggestion(span, msg, format!("{}\n{}", new_item, indent), applicability);
+ self.span_suggestion(span, msg, format!("{new_item}\n{indent}"), applicability);
}
}
fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability) {
let mut remove_span = item;
- let hi = cx.sess().source_map().next_point(remove_span).hi();
- let fmpos = cx.sess().source_map().lookup_byte_offset(hi);
+ let fmpos = cx.sess().source_map().lookup_byte_offset(remove_span.hi());
if let Some(ref src) = fmpos.sf.src {
let non_whitespace_offset = src[fmpos.pos.to_usize()..].find(|c| c != ' ' && c != '\t' && c != '\n');
@@ -819,10 +822,9 @@ pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, closure: &'tcx hir::Expr<'
};
let fn_def_id = cx.tcx.hir().local_def_id(closure.hir_id);
- cx.tcx.infer_ctxt().enter(|infcx| {
- ExprUseVisitor::new(&mut visitor, &infcx, fn_def_id, cx.param_env, cx.typeck_results())
- .consume_body(closure_body);
- });
+ 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);
if !visitor.suggestion_start.is_empty() {
return Some(DerefClosure {
@@ -859,7 +861,7 @@ impl<'tcx> DerefDelegate<'_, 'tcx> {
pub fn finish(&mut self) -> String {
let end_span = Span::new(self.next_pos, self.closure_span.hi(), self.closure_span.ctxt(), None);
let end_snip = snippet_with_applicability(self.cx, end_span, "..", &mut self.applicability);
- let sugg = format!("{}{}", self.suggestion_start, end_snip);
+ let sugg = format!("{}{end_snip}", self.suggestion_start);
if self.closure_arg_is_type_annotated_double_ref {
sugg.replacen('&', "", 1)
} else {
@@ -921,7 +923,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 _ = 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()`
@@ -936,7 +938,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 _ = write!(self.suggestion_start, "{start_snip}{ident_str_with_proj}");
self.next_pos = span.hi();
return;
},
@@ -969,9 +971,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
} else {
ident_str
};
- format!("{}{}", start_snip, ident)
+ format!("{start_snip}{ident}")
} else {
- format!("{}&{}", start_snip, ident_str)
+ format!("{start_snip}&{ident_str}")
};
self.suggestion_start.push_str(&ident_sugg);
self.next_pos = span.hi();
@@ -1038,13 +1040,13 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
for item in projections {
if item.kind == ProjectionKind::Deref {
- replacement_str = format!("*{}", replacement_str);
+ replacement_str = format!("*{replacement_str}");
}
}
}
}
- let _ = write!(self.suggestion_start, "{}{}", start_snip, replacement_str);
+ let _ = write!(self.suggestion_start, "{start_snip}{replacement_str}");
}
self.next_pos = span.hi();
}
@@ -1052,7 +1054,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
fn mutate(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {}
- fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+ fn fake_read(&mut self, _: &PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
}
#[cfg(test)]
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index a8ad6cf4f..4e024ce40 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -12,13 +12,13 @@ use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::mir::interpret::{ConstValue, Scalar};
-use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{
self, AdtDef, Binder, BoundRegion, DefIdTree, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, ProjectionTy,
Region, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, VariantDef, VariantDiscr,
};
+use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_span::symbol::Ident;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{sym, Span, Symbol};
use rustc_target::abi::{Size, VariantIdx};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::query::normalize::AtExt;
@@ -28,7 +28,14 @@ use crate::{match_def_path, path_res, paths};
// Checks if the given type implements copy.
pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
- ty.is_copy_modulo_regions(cx.tcx.at(DUMMY_SP), cx.param_env)
+ ty.is_copy_modulo_regions(cx.tcx, cx.param_env)
+}
+
+/// This checks whether a given type is known to implement Debug.
+pub fn has_debug_impl<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+ cx.tcx
+ .get_diagnostic_item(sym::Debug)
+ .map_or(false, |debug| implements_trait(cx, ty, debug, &[]))
}
/// Checks whether a type can be partially moved.
@@ -165,11 +172,10 @@ pub fn implements_trait_with_env<'tcx>(
return false;
}
let ty_params = tcx.mk_substs(ty_params.iter());
- tcx.infer_ctxt().enter(|infcx| {
- infcx
- .type_implements_trait(trait_id, ty, ty_params, param_env)
- .must_apply_modulo_regions()
- })
+ let infcx = tcx.infer_ctxt().build();
+ infcx
+ .type_implements_trait(trait_id, ty, ty_params, param_env)
+ .must_apply_modulo_regions()
}
/// Checks whether this type implements `Drop`.
@@ -235,27 +241,26 @@ fn is_normalizable_helper<'tcx>(
}
// prevent recursive loops, false-negative is better than endless loop leading to stack overflow
cache.insert(ty, false);
- let result = cx.tcx.infer_ctxt().enter(|infcx| {
- let cause = rustc_middle::traits::ObligationCause::dummy();
- if infcx.at(&cause, param_env).normalize(ty).is_ok() {
- match ty.kind() {
- ty::Adt(def, substs) => def.variants().iter().all(|variant| {
- variant
- .fields
- .iter()
- .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
- }),
- _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
- GenericArgKind::Type(inner_ty) if inner_ty != ty => {
- is_normalizable_helper(cx, param_env, inner_ty, cache)
- },
- _ => true, // if inner_ty == ty, we've already checked it
- }),
- }
- } else {
- false
+ let infcx = cx.tcx.infer_ctxt().build();
+ let cause = rustc_middle::traits::ObligationCause::dummy();
+ let result = if infcx.at(&cause, param_env).normalize(ty).is_ok() {
+ match ty.kind() {
+ ty::Adt(def, substs) => def.variants().iter().all(|variant| {
+ variant
+ .fields
+ .iter()
+ .all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
+ }),
+ _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
+ GenericArgKind::Type(inner_ty) if inner_ty != ty => {
+ is_normalizable_helper(cx, param_env, inner_ty, cache)
+ },
+ _ => true, // if inner_ty == ty, we've already checked it
+ }),
}
- });
+ } else {
+ false
+ };
cache.insert(ty, result);
result
}
@@ -652,21 +657,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
let mut output = None;
let lang_items = cx.tcx.lang_items();
- for pred in cx
+ for (pred, _) in cx
.tcx
.bound_explicit_item_bounds(ty.item_def_id)
- .transpose_iter()
- .map(|x| x.map_bound(|(p, _)| p))
+ .subst_iter_copied(cx.tcx, ty.substs)
{
- match pred.0.kind().skip_binder() {
+ match pred.kind().skip_binder() {
PredicateKind::Trait(p)
if (lang_items.fn_trait() == Some(p.def_id())
|| lang_items.fn_mut_trait() == Some(p.def_id())
|| lang_items.fn_once_trait() == Some(p.def_id())) =>
{
- let i = pred
- .map_bound(|pred| pred.kind().rebind(p.trait_ref.substs.type_at(1)))
- .subst(cx.tcx, ty.substs);
+ let i = pred.kind().rebind(p.trait_ref.substs.type_at(1));
if inputs.map_or(false, |inputs| inputs != i) {
// Multiple different fn trait impls. Is this even allowed?
@@ -679,10 +681,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: ProjectionTy<'tcx>) -> O
// Multiple different fn trait impls. Is this even allowed?
return None;
}
- output = Some(
- pred.map_bound(|pred| pred.kind().rebind(p.term.ty().unwrap()))
- .subst(cx.tcx, ty.substs),
- );
+ output = pred.kind().rebind(p.term.ty()).transpose();
},
_ => (),
}
diff --git a/src/tools/clippy/clippy_utils/src/usage.rs b/src/tools/clippy/clippy_utils/src/usage.rs
index 3af5dfb62..000fb51c0 100644
--- a/src/tools/clippy/clippy_utils/src/usage.rs
+++ b/src/tools/clippy/clippy_utils/src/usage.rs
@@ -1,15 +1,16 @@
use crate as utils;
-use crate::visitors::{expr_visitor, expr_visitor_no_bodies};
+use crate::visitors::{for_each_expr, for_each_expr_with_closures, Descend};
+use core::ops::ControlFlow;
use rustc_hir as hir;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::HirIdSet;
use rustc_hir::{Expr, ExprKind, HirId, Node};
+use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::LateContext;
use rustc_middle::hir::nested_filter;
use rustc_middle::mir::FakeReadCause;
use rustc_middle::ty;
-use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
/// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined.
pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) -> Option<HirIdSet> {
@@ -17,16 +18,15 @@ pub fn mutated_variables<'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'tcx>) ->
used_mutably: HirIdSet::default(),
skip: false,
};
- cx.tcx.infer_ctxt().enter(|infcx| {
- ExprUseVisitor::new(
- &mut delegate,
- &infcx,
- expr.hir_id.owner,
- cx.param_env,
- cx.typeck_results(),
- )
- .walk_expr(expr);
- });
+ let infcx = cx.tcx.infer_ctxt().build();
+ ExprUseVisitor::new(
+ &mut delegate,
+ &infcx,
+ expr.hir_id.owner.def_id,
+ cx.param_env,
+ cx.typeck_results(),
+ )
+ .walk_expr(expr);
if delegate.skip {
return None;
@@ -73,7 +73,12 @@ impl<'tcx> Delegate<'tcx> for MutVarsDelegate {
self.update(cmt);
}
- fn fake_read(&mut self, _: &rustc_typeck::expr_use_visitor::PlaceWithHirId<'tcx>, _: FakeReadCause, _: HirId) {}
+ fn fake_read(
+ &mut self,
+ _: &rustc_hir_typeck::expr_use_visitor::PlaceWithHirId<'tcx>,
+ _: FakeReadCause,
+ _: HirId,
+ ) {}
}
pub struct ParamBindingIdCollector {
@@ -142,28 +147,17 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for BindingUsageFinder<'a, 'tcx> {
}
pub fn contains_return_break_continue_macro(expression: &Expr<'_>) -> bool {
- let mut seen_return_break_continue = false;
- expr_visitor_no_bodies(|ex| {
- if seen_return_break_continue {
- return false;
- }
- match &ex.kind {
- ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => {
- seen_return_break_continue = true;
- },
+ for_each_expr(expression, |e| {
+ match e.kind {
+ ExprKind::Ret(..) | ExprKind::Break(..) | ExprKind::Continue(..) => ControlFlow::Break(()),
// Something special could be done here to handle while or for loop
// desugaring, as this will detect a break if there's a while loop
// or a for loop inside the expression.
- _ => {
- if ex.span.from_expansion() {
- seen_return_break_continue = true;
- }
- },
+ _ if e.span.from_expansion() => ControlFlow::Break(()),
+ _ => ControlFlow::Continue(()),
}
- !seen_return_break_continue
})
- .visit_expr(expression);
- seen_return_break_continue
+ .is_some()
}
pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr<'_>) -> bool {
@@ -194,23 +188,16 @@ pub fn local_used_after_expr(cx: &LateContext<'_>, local_id: HirId, after: &Expr
return true;
}
- let mut used_after_expr = false;
let mut past_expr = false;
- expr_visitor(cx, |expr| {
- if used_after_expr {
- return false;
- }
-
- if expr.hir_id == after.hir_id {
+ for_each_expr_with_closures(cx, block, |e| {
+ if e.hir_id == after.hir_id {
past_expr = true;
- return false;
- }
-
- if past_expr && utils::path_to_local_id(expr, local_id) {
- used_after_expr = true;
+ ControlFlow::Continue(Descend::No)
+ } else if past_expr && utils::path_to_local_id(e, local_id) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(Descend::Yes)
}
- !used_after_expr
})
- .visit_block(block);
- used_after_expr
+ .is_some()
}
diff --git a/src/tools/clippy/clippy_utils/src/visitors.rs b/src/tools/clippy/clippy_utils/src/visitors.rs
index 232d57190..d4294f18f 100644
--- a/src/tools/clippy/clippy_utils/src/visitors.rs
+++ b/src/tools/clippy/clippy_utils/src/visitors.rs
@@ -5,14 +5,13 @@ use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::intravisit::{self, walk_block, walk_expr, Visitor};
use rustc_hir::{
- Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Let, Pat, QPath, Stmt, UnOp,
- UnsafeSource, Unsafety,
+ AnonConst, Arm, Block, BlockCheckMode, Body, BodyId, Expr, ExprKind, HirId, ItemId, ItemKind, Let, Pat, QPath,
+ Stmt, UnOp, UnsafeSource, Unsafety,
};
use rustc_lint::LateContext;
-use rustc_middle::hir::map::Map;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::adjustment::Adjust;
-use rustc_middle::ty::{self, Ty, TypeckResults};
+use rustc_middle::ty::{self, Ty, TyCtxt, TypeckResults};
use rustc_span::Span;
mod internal {
@@ -48,6 +47,26 @@ impl Continue for Descend {
}
}
+/// A type which can be visited.
+pub trait Visitable<'tcx> {
+ /// Calls the corresponding `visit_*` function on the visitor.
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
+}
+macro_rules! visitable_ref {
+ ($t:ident, $f:ident) => {
+ impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
+ fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
+ visitor.$f(self);
+ }
+ }
+ };
+}
+visitable_ref!(Arm, visit_arm);
+visitable_ref!(Block, visit_block);
+visitable_ref!(Body, visit_body);
+visitable_ref!(Expr, visit_expr);
+visitable_ref!(Stmt, visit_stmt);
+
/// Calls the given function once for each expression contained. This does not enter any bodies or
/// nested items.
pub fn for_each_expr<'tcx, B, C: Continue>(
@@ -82,57 +101,63 @@ pub fn for_each_expr<'tcx, B, C: Continue>(
v.res
}
-/// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested
-/// bodies (i.e. closures) are visited.
-/// If the callback returns `true`, the expr just provided to the callback is walked.
-#[must_use]
-pub fn expr_visitor<'tcx>(cx: &LateContext<'tcx>, f: impl FnMut(&'tcx Expr<'tcx>) -> bool) -> impl Visitor<'tcx> {
- struct V<'tcx, F> {
- hir: Map<'tcx>,
+/// Calls the given function once for each expression contained. This will enter bodies, but not
+/// nested items.
+pub fn for_each_expr_with_closures<'tcx, B, C: Continue>(
+ cx: &LateContext<'tcx>,
+ node: impl Visitable<'tcx>,
+ f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>,
+) -> Option<B> {
+ struct V<'tcx, B, F> {
+ tcx: TyCtxt<'tcx>,
f: F,
+ res: Option<B>,
}
- impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<'tcx, F> {
+ impl<'tcx, B, C: Continue, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B, C>> Visitor<'tcx> for V<'tcx, B, F> {
type NestedFilter = nested_filter::OnlyBodies;
fn nested_visit_map(&mut self) -> Self::Map {
- self.hir
+ self.tcx.hir()
}
- fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
- if (self.f)(expr) {
- walk_expr(self, expr);
+ fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) {
+ if self.res.is_some() {
+ return;
}
- }
- }
- V { hir: cx.tcx.hir(), f }
-}
-
-/// Convenience method for creating a `Visitor` with just `visit_expr` overridden and nested
-/// bodies (i.e. closures) are not visited.
-/// If the callback returns `true`, the expr just provided to the callback is walked.
-#[must_use]
-pub fn expr_visitor_no_bodies<'tcx>(f: impl FnMut(&'tcx Expr<'tcx>) -> bool) -> impl Visitor<'tcx> {
- struct V<F>(F);
- impl<'tcx, F: FnMut(&'tcx Expr<'tcx>) -> bool> Visitor<'tcx> for V<F> {
- fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
- if (self.0)(e) {
- walk_expr(self, e);
+ match (self.f)(e) {
+ ControlFlow::Continue(c) if c.descend() => walk_expr(self, e),
+ ControlFlow::Break(b) => self.res = Some(b),
+ ControlFlow::Continue(_) => (),
}
}
+
+ // Only walk closures
+ fn visit_anon_const(&mut self, _: &'tcx AnonConst) {}
+ // Avoid unnecessary `walk_*` calls.
+ fn visit_ty(&mut self, _: &'tcx hir::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) {}
}
- V(f)
+ let mut v = V {
+ tcx: cx.tcx,
+ f,
+ res: None,
+ };
+ node.visit(&mut v);
+ v.res
}
/// returns `true` if expr contains match expr desugared from try
fn contains_try(expr: &hir::Expr<'_>) -> bool {
- let mut found = false;
- expr_visitor_no_bodies(|e| {
- if !found {
- found = matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar));
+ for_each_expr(expr, |e| {
+ if matches!(e.kind, hir::ExprKind::Match(_, _, hir::MatchSource::TryDesugar)) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
- !found
})
- .visit_expr(expr);
- found
+ .is_some()
}
pub fn find_all_ret_expressions<'hir, F>(_cx: &LateContext<'_>, expr: &'hir hir::Expr<'hir>, callback: F) -> bool
@@ -228,68 +253,29 @@ where
}
}
-/// A type which can be visited.
-pub trait Visitable<'tcx> {
- /// Calls the corresponding `visit_*` function on the visitor.
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V);
-}
-macro_rules! visitable_ref {
- ($t:ident, $f:ident) => {
- impl<'tcx> Visitable<'tcx> for &'tcx $t<'tcx> {
- fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
- visitor.$f(self);
- }
- }
- };
-}
-visitable_ref!(Arm, visit_arm);
-visitable_ref!(Block, visit_block);
-visitable_ref!(Body, visit_body);
-visitable_ref!(Expr, visit_expr);
-visitable_ref!(Stmt, visit_stmt);
-
-// impl<'tcx, I: IntoIterator> Visitable<'tcx> for I
-// where
-// I::Item: Visitable<'tcx>,
-// {
-// fn visit<V: Visitor<'tcx>>(self, visitor: &mut V) {
-// for x in self {
-// x.visit(visitor);
-// }
-// }
-// }
-
/// Checks if the given resolved path is used in the given body.
pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
- let mut found = false;
- expr_visitor(cx, |e| {
- if found {
- return false;
- }
-
+ for_each_expr_with_closures(cx, cx.tcx.hir().body(body).value, |e| {
if let ExprKind::Path(p) = &e.kind {
if cx.qpath_res(p, e.hir_id) == res {
- found = true;
+ return ControlFlow::Break(());
}
}
- !found
+ ControlFlow::Continue(())
})
- .visit_expr(cx.tcx.hir().body(body).value);
- found
+ .is_some()
}
/// Checks if the given local is used.
pub fn is_local_used<'tcx>(cx: &LateContext<'tcx>, visitable: impl Visitable<'tcx>, id: HirId) -> bool {
- let mut is_used = false;
- let mut visitor = expr_visitor(cx, |expr| {
- if !is_used {
- is_used = path_to_local_id(expr, id);
+ for_each_expr_with_closures(cx, visitable, |e| {
+ if path_to_local_id(e, id) {
+ ControlFlow::Break(())
+ } else {
+ ControlFlow::Continue(())
}
- !is_used
- });
- visitable.visit(&mut visitor);
- drop(visitor);
- is_used
+ })
+ .is_some()
}
/// Checks if the given expression is a constant.
diff --git a/src/tools/clippy/lintcheck/Cargo.toml b/src/tools/clippy/lintcheck/Cargo.toml
index 737c845c0..de31c16b8 100644
--- a/src/tools/clippy/lintcheck/Cargo.toml
+++ b/src/tools/clippy/lintcheck/Cargo.toml
@@ -12,9 +12,11 @@ publish = false
[dependencies]
cargo_metadata = "0.14"
clap = "3.2"
+crossbeam-channel = "0.5.6"
flate2 = "1.0"
rayon = "1.5.1"
serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0.85"
tar = "0.4"
toml = "0.5"
ureq = "2.2"
diff --git a/src/tools/clippy/lintcheck/README.md b/src/tools/clippy/lintcheck/README.md
index 6f3d23382..6142de5e3 100644
--- a/src/tools/clippy/lintcheck/README.md
+++ b/src/tools/clippy/lintcheck/README.md
@@ -69,9 +69,27 @@ is checked.
is explicitly specified in the options.
### Fix mode
-You can run `./lintcheck/target/debug/lintcheck --fix` which will run Clippy with `--fix` and
+You can run `cargo lintcheck --fix` which will run Clippy with `--fix` and
print a warning if Clippy's suggestions fail to apply (if the resulting code does not build).
This lets us spot bad suggestions or false positives automatically in some cases.
Please note that the target dir should be cleaned afterwards since clippy will modify
the downloaded sources which can lead to unexpected results when running lintcheck again afterwards.
+
+### Recursive mode
+You can run `cargo lintcheck --recursive` to also run Clippy on the dependencies
+of the crates listed in the crates source `.toml`. e.g. adding `rand 0.8.5`
+would also lint `rand_core`, `rand_chacha`, etc.
+
+Particularly slow crates in the dependency graph can be ignored using
+`recursive.ignore`:
+
+```toml
+[crates]
+cargo = {name = "cargo", versions = ['0.64.0']}
+
+[recursive]
+ignore = [
+ "unicode-normalization",
+]
+```
diff --git a/src/tools/clippy/lintcheck/lintcheck_crates.toml b/src/tools/clippy/lintcheck/lintcheck_crates.toml
index ebbe9c9ae..52f7fee47 100644
--- a/src/tools/clippy/lintcheck/lintcheck_crates.toml
+++ b/src/tools/clippy/lintcheck/lintcheck_crates.toml
@@ -33,3 +33,11 @@ cfg-expr = {name = "cfg-expr", versions = ['0.7.1']}
puffin = {name = "puffin", git_url = "https://github.com/EmbarkStudios/puffin", git_hash = "02dd4a3"}
rpmalloc = {name = "rpmalloc", versions = ['0.2.0']}
tame-oidc = {name = "tame-oidc", versions = ['0.1.0']}
+
+[recursive]
+ignore = [
+ # Takes ~30s to lint
+ "combine",
+ # Has 1.2 million `clippy::match_same_arms`s
+ "unicode-normalization",
+]
diff --git a/src/tools/clippy/lintcheck/src/config.rs b/src/tools/clippy/lintcheck/src/config.rs
index 1742cf677..b8824024e 100644
--- a/src/tools/clippy/lintcheck/src/config.rs
+++ b/src/tools/clippy/lintcheck/src/config.rs
@@ -34,11 +34,16 @@ fn get_clap_config() -> ArgMatches {
Arg::new("markdown")
.long("markdown")
.help("Change the reports table to use markdown links"),
+ Arg::new("recursive")
+ .long("--recursive")
+ .help("Run clippy on the dependencies of crates specified in crates-toml")
+ .conflicts_with("threads")
+ .conflicts_with("fix"),
])
.get_matches()
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub(crate) struct LintcheckConfig {
/// max number of jobs to spawn (default 1)
pub max_jobs: usize,
@@ -54,6 +59,8 @@ pub(crate) struct LintcheckConfig {
pub lint_filter: Vec<String>,
/// Indicate if the output should support markdown syntax
pub markdown: bool,
+ /// Run clippy on the dependencies of crates
+ pub recursive: bool,
}
impl LintcheckConfig {
@@ -66,8 +73,7 @@ impl LintcheckConfig {
let sources_toml = env::var("LINTCHECK_TOML").unwrap_or_else(|_| {
clap_config
.get_one::<String>("crates-toml")
- .map(|s| &**s)
- .unwrap_or("lintcheck/lintcheck_crates.toml")
+ .map_or("lintcheck/lintcheck_crates.toml", |s| &**s)
.into()
});
@@ -90,7 +96,7 @@ impl LintcheckConfig {
Some(&0) => {
// automatic choice
// Rayon seems to return thread count so half that for core count
- (rayon::current_num_threads() / 2) as usize
+ rayon::current_num_threads() / 2
},
Some(&threads) => threads,
// no -j passed, use a single thread
@@ -119,6 +125,7 @@ impl LintcheckConfig {
fix: clap_config.contains_id("fix"),
lint_filter,
markdown,
+ recursive: clap_config.contains_id("recursive"),
}
}
}
diff --git a/src/tools/clippy/lintcheck/src/driver.rs b/src/tools/clippy/lintcheck/src/driver.rs
new file mode 100644
index 000000000..47724a2fe
--- /dev/null
+++ b/src/tools/clippy/lintcheck/src/driver.rs
@@ -0,0 +1,67 @@
+use crate::recursive::{deserialize_line, serialize_line, DriverInfo};
+
+use std::io::{self, BufReader, Write};
+use std::net::TcpStream;
+use std::process::{self, Command, Stdio};
+use std::{env, mem};
+
+/// 1. Sends [`DriverInfo`] to the [`crate::recursive::LintcheckServer`] running on `addr`
+/// 2. Receives [bool] from the server, if `false` returns `None`
+/// 3. Otherwise sends the stderr of running `clippy-driver` to the server
+fn run_clippy(addr: &str) -> Option<i32> {
+ let driver_info = DriverInfo {
+ package_name: env::var("CARGO_PKG_NAME").ok()?,
+ crate_name: env::var("CARGO_CRATE_NAME").ok()?,
+ version: env::var("CARGO_PKG_VERSION").ok()?,
+ };
+
+ let mut stream = BufReader::new(TcpStream::connect(addr).unwrap());
+
+ serialize_line(&driver_info, stream.get_mut());
+
+ let should_run = deserialize_line::<bool, _>(&mut stream);
+ if !should_run {
+ return None;
+ }
+
+ // Remove --cap-lints allow so that clippy runs and lints are emitted
+ let mut include_next = true;
+ let args = env::args().skip(1).filter(|arg| match arg.as_str() {
+ "--cap-lints=allow" => false,
+ "--cap-lints" => {
+ include_next = false;
+ false
+ },
+ _ => mem::replace(&mut include_next, true),
+ });
+
+ let output = Command::new(env::var("CLIPPY_DRIVER").expect("missing env CLIPPY_DRIVER"))
+ .args(args)
+ .stdout(Stdio::inherit())
+ .output()
+ .expect("failed to run clippy-driver");
+
+ stream
+ .get_mut()
+ .write_all(&output.stderr)
+ .unwrap_or_else(|e| panic!("{e:?} in {driver_info:?}"));
+
+ match output.status.code() {
+ Some(0) => Some(0),
+ code => {
+ io::stderr().write_all(&output.stderr).unwrap();
+ Some(code.expect("killed by signal"))
+ },
+ }
+}
+
+pub fn drive(addr: &str) {
+ process::exit(run_clippy(addr).unwrap_or_else(|| {
+ Command::new("rustc")
+ .args(env::args_os().skip(2))
+ .status()
+ .unwrap()
+ .code()
+ .unwrap()
+ }))
+}
diff --git a/src/tools/clippy/lintcheck/src/main.rs b/src/tools/clippy/lintcheck/src/main.rs
index 9ee25280f..54c1b80c4 100644
--- a/src/tools/clippy/lintcheck/src/main.rs
+++ b/src/tools/clippy/lintcheck/src/main.rs
@@ -8,13 +8,17 @@
#![allow(clippy::collapsible_else_if)]
mod config;
+mod driver;
+mod recursive;
-use config::LintcheckConfig;
+use crate::config::LintcheckConfig;
+use crate::recursive::LintcheckServer;
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
use std::env;
+use std::env::consts::EXE_SUFFIX;
use std::fmt::Write as _;
-use std::fs::write;
+use std::fs;
use std::io::ErrorKind;
use std::path::{Path, PathBuf};
use std::process::Command;
@@ -22,22 +26,12 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
use std::time::Duration;
-use cargo_metadata::diagnostic::DiagnosticLevel;
+use cargo_metadata::diagnostic::{Diagnostic, DiagnosticLevel};
use cargo_metadata::Message;
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use walkdir::{DirEntry, WalkDir};
-#[cfg(not(windows))]
-const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver";
-#[cfg(not(windows))]
-const CARGO_CLIPPY_PATH: &str = "target/debug/cargo-clippy";
-
-#[cfg(windows)]
-const CLIPPY_DRIVER_PATH: &str = "target/debug/clippy-driver.exe";
-#[cfg(windows)]
-const CARGO_CLIPPY_PATH: &str = "target/debug/cargo-clippy.exe";
-
const LINTCHECK_DOWNLOADS: &str = "target/lintcheck/downloads";
const LINTCHECK_SOURCES: &str = "target/lintcheck/sources";
@@ -45,6 +39,13 @@ const LINTCHECK_SOURCES: &str = "target/lintcheck/sources";
#[derive(Debug, Serialize, Deserialize)]
struct SourceList {
crates: HashMap<String, TomlCrate>,
+ #[serde(default)]
+ recursive: RecursiveOptions,
+}
+
+#[derive(Debug, Serialize, Deserialize, Default)]
+struct RecursiveOptions {
+ ignore: HashSet<String>,
}
/// A crate source stored inside the .toml
@@ -105,12 +106,7 @@ struct ClippyWarning {
#[allow(unused)]
impl ClippyWarning {
- fn new(cargo_message: Message, krate: &Crate) -> Option<Self> {
- let diag = match cargo_message {
- Message::CompilerMessage(message) => message.message,
- _ => return None,
- };
-
+ fn new(diag: Diagnostic, crate_name: &str, crate_version: &str) -> Option<Self> {
let lint_type = diag.code?.code;
if !(lint_type.contains("clippy") || diag.message.contains("clippy"))
|| diag.message.contains("could not read cargo metadata")
@@ -120,16 +116,17 @@ impl ClippyWarning {
let span = diag.spans.into_iter().find(|span| span.is_primary)?;
- let file = match Path::new(&span.file_name).strip_prefix(env!("CARGO_HOME")) {
- Ok(stripped) => format!("$CARGO_HOME/{}", stripped.display()),
- Err(_) => format!(
+ let file = if let Ok(stripped) = Path::new(&span.file_name).strip_prefix(env!("CARGO_HOME")) {
+ format!("$CARGO_HOME/{}", stripped.display())
+ } else {
+ format!(
"target/lintcheck/sources/{}-{}/{}",
- krate.name, krate.version, span.file_name
- ),
+ crate_name, crate_version, span.file_name
+ )
};
Some(Self {
- crate_name: krate.name.clone(),
+ crate_name: crate_name.to_owned(),
file,
line: span.line_start,
column: span.column_start,
@@ -142,24 +139,23 @@ impl ClippyWarning {
fn to_output(&self, markdown: bool) -> String {
let file_with_pos = format!("{}:{}:{}", &self.file, &self.line, &self.column);
if markdown {
- let lint = format!("`{}`", self.lint_type);
-
let mut file = self.file.clone();
if !file.starts_with('$') {
file.insert_str(0, "../");
}
let mut output = String::from("| ");
- let _ = write!(output, "[`{}`]({}#L{})", file_with_pos, file, self.line);
- let _ = write!(output, r#" | {:<50} | "{}" |"#, lint, self.message);
+ let _ = write!(output, "[`{file_with_pos}`]({file}#L{})", self.line);
+ let _ = write!(output, r#" | `{:<50}` | "{}" |"#, self.lint_type, self.message);
output.push('\n');
output
} else {
- format!("{} {} \"{}\"\n", file_with_pos, self.lint_type, self.message)
+ format!("{file_with_pos} {} \"{}\"\n", self.lint_type, self.message)
}
}
}
+#[allow(clippy::result_large_err)]
fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
const MAX_RETRIES: u8 = 4;
let mut retries = 0;
@@ -167,11 +163,11 @@ fn get(path: &str) -> Result<ureq::Response, ureq::Error> {
match ureq::get(path).call() {
Ok(res) => return Ok(res),
Err(e) if retries >= MAX_RETRIES => return Err(e),
- Err(ureq::Error::Transport(e)) => eprintln!("Error: {}", e),
+ Err(ureq::Error::Transport(e)) => eprintln!("Error: {e}"),
Err(e) => return Err(e),
}
- eprintln!("retrying in {} seconds...", retries);
- thread::sleep(Duration::from_secs(retries as u64));
+ eprintln!("retrying in {retries} seconds...");
+ thread::sleep(Duration::from_secs(u64::from(retries)));
retries += 1;
}
}
@@ -187,11 +183,11 @@ impl CrateSource {
let krate_download_dir = PathBuf::from(LINTCHECK_DOWNLOADS);
// url to download the crate from crates.io
- let url = format!("https://crates.io/api/v1/crates/{}/{}/download", name, version);
- println!("Downloading and extracting {} {} from {}", name, version, url);
+ let url = format!("https://crates.io/api/v1/crates/{name}/{version}/download");
+ println!("Downloading and extracting {name} {version} from {url}");
create_dirs(&krate_download_dir, &extract_dir);
- let krate_file_path = krate_download_dir.join(format!("{}-{}.crate.tar.gz", name, version));
+ let krate_file_path = krate_download_dir.join(format!("{name}-{version}.crate.tar.gz"));
// don't download/extract if we already have done so
if !krate_file_path.is_file() {
// create a file path to download and write the crate data into
@@ -211,7 +207,7 @@ impl CrateSource {
Crate {
version: version.clone(),
name: name.clone(),
- path: extract_dir.join(format!("{}-{}/", name, version)),
+ path: extract_dir.join(format!("{name}-{version}/")),
options: options.clone(),
}
},
@@ -224,12 +220,12 @@ impl CrateSource {
let repo_path = {
let mut repo_path = PathBuf::from(LINTCHECK_SOURCES);
// add a -git suffix in case we have the same crate from crates.io and a git repo
- repo_path.push(format!("{}-git", name));
+ repo_path.push(format!("{name}-git"));
repo_path
};
// clone the repo if we have not done so
if !repo_path.is_dir() {
- println!("Cloning {} and checking out {}", url, commit);
+ println!("Cloning {url} and checking out {commit}");
if !Command::new("git")
.arg("clone")
.arg(url)
@@ -238,11 +234,12 @@ impl CrateSource {
.expect("Failed to clone git repo!")
.success()
{
- eprintln!("Failed to clone {} into {}", url, repo_path.display())
+ eprintln!("Failed to clone {url} into {}", repo_path.display());
}
}
// check out the commit/branch/whatever
if !Command::new("git")
+ .args(["-c", "advice.detachedHead=false"])
.arg("checkout")
.arg(commit)
.current_dir(&repo_path)
@@ -250,7 +247,7 @@ impl CrateSource {
.expect("Failed to check out commit")
.success()
{
- eprintln!("Failed to checkout {} of repo at {}", commit, repo_path.display())
+ eprintln!("Failed to checkout {commit} of repo at {}", repo_path.display());
}
Crate {
@@ -261,22 +258,22 @@ impl CrateSource {
}
},
CrateSource::Path { name, path, options } => {
+ fn is_cache_dir(entry: &DirEntry) -> bool {
+ std::fs::read(entry.path().join("CACHEDIR.TAG"))
+ .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
+ .unwrap_or(false)
+ }
+
// copy path into the dest_crate_root but skip directories that contain a CACHEDIR.TAG file.
// The target/ directory contains a CACHEDIR.TAG file so it is the most commonly skipped directory
// as a result of this filter.
let dest_crate_root = PathBuf::from(LINTCHECK_SOURCES).join(name);
if dest_crate_root.exists() {
- println!("Deleting existing directory at {:?}", dest_crate_root);
+ println!("Deleting existing directory at {dest_crate_root:?}");
std::fs::remove_dir_all(&dest_crate_root).unwrap();
}
- println!("Copying {:?} to {:?}", path, dest_crate_root);
-
- fn is_cache_dir(entry: &DirEntry) -> bool {
- std::fs::read(entry.path().join("CACHEDIR.TAG"))
- .map(|x| x.starts_with(b"Signature: 8a477f597d28d172789f06886806bc55"))
- .unwrap_or(false)
- }
+ println!("Copying {path:?} to {dest_crate_root:?}");
for entry in WalkDir::new(path).into_iter().filter_entry(|e| !is_cache_dir(e)) {
let entry = entry.unwrap();
@@ -306,13 +303,16 @@ impl CrateSource {
impl Crate {
/// Run `cargo clippy` on the `Crate` and collect and return all the lint warnings that clippy
/// issued
+ #[allow(clippy::too_many_arguments)]
fn run_clippy_lints(
&self,
cargo_clippy_path: &Path,
+ clippy_driver_path: &Path,
target_dir_index: &AtomicUsize,
total_crates_to_lint: usize,
config: &LintcheckConfig,
lint_filter: &Vec<String>,
+ server: &Option<LintcheckServer>,
) -> Vec<ClippyWarning> {
// advance the atomic index by one
let index = target_dir_index.fetch_add(1, Ordering::SeqCst);
@@ -336,36 +336,64 @@ impl Crate {
let shared_target_dir = clippy_project_root().join("target/lintcheck/shared_target_dir");
- let mut args = if config.fix {
+ let mut cargo_clippy_args = if config.fix {
vec!["--fix", "--"]
} else {
vec!["--", "--message-format=json", "--"]
};
+ let mut clippy_args = Vec::<&str>::new();
if let Some(options) = &self.options {
for opt in options {
- args.push(opt);
+ clippy_args.push(opt);
}
} else {
- args.extend(&["-Wclippy::pedantic", "-Wclippy::cargo"])
+ clippy_args.extend(["-Wclippy::pedantic", "-Wclippy::cargo"]);
}
if lint_filter.is_empty() {
- args.push("--cap-lints=warn");
+ clippy_args.push("--cap-lints=warn");
} else {
- args.push("--cap-lints=allow");
- args.extend(lint_filter.iter().map(|filter| filter.as_str()))
+ clippy_args.push("--cap-lints=allow");
+ clippy_args.extend(lint_filter.iter().map(std::string::String::as_str));
}
- let all_output = std::process::Command::new(&cargo_clippy_path)
+ if let Some(server) = server {
+ let target = shared_target_dir.join("recursive");
+
+ // `cargo clippy` is a wrapper around `cargo check` that mainly sets `RUSTC_WORKSPACE_WRAPPER` to
+ // `clippy-driver`. We do the same thing here with a couple changes:
+ //
+ // `RUSTC_WRAPPER` is used instead of `RUSTC_WORKSPACE_WRAPPER` so that we can lint all crate
+ // dependencies rather than only workspace members
+ //
+ // The wrapper is set to the `lintcheck` so we can force enable linting and ignore certain crates
+ // (see `crate::driver`)
+ let status = Command::new("cargo")
+ .arg("check")
+ .arg("--quiet")
+ .current_dir(&self.path)
+ .env("CLIPPY_ARGS", clippy_args.join("__CLIPPY_HACKERY__"))
+ .env("CARGO_TARGET_DIR", target)
+ .env("RUSTC_WRAPPER", env::current_exe().unwrap())
+ // Pass the absolute path so `crate::driver` can find `clippy-driver`, as it's executed in various
+ // different working directories
+ .env("CLIPPY_DRIVER", clippy_driver_path)
+ .env("LINTCHECK_SERVER", server.local_addr.to_string())
+ .status()
+ .expect("failed to run cargo");
+
+ assert_eq!(status.code(), Some(0));
+
+ return Vec::new();
+ }
+
+ cargo_clippy_args.extend(clippy_args);
+
+ let all_output = Command::new(&cargo_clippy_path)
// use the looping index to create individual target dirs
- .env(
- "CARGO_TARGET_DIR",
- shared_target_dir.join(format!("_{:?}", thread_index)),
- )
- // lint warnings will look like this:
- // src/cargo/ops/cargo_compile.rs:127:35: warning: usage of `FromIterator::from_iter`
- .args(&args)
+ .env("CARGO_TARGET_DIR", shared_target_dir.join(format!("_{thread_index:?}")))
+ .args(&cargo_clippy_args)
.current_dir(&self.path)
.output()
.unwrap_or_else(|error| {
@@ -394,8 +422,8 @@ impl Crate {
{
let subcrate = &stderr[63..];
println!(
- "ERROR: failed to apply some suggetion to {} / to (sub)crate {}",
- self.name, subcrate
+ "ERROR: failed to apply some suggetion to {} / to (sub)crate {subcrate}",
+ self.name
);
}
// fast path, we don't need the warnings anyway
@@ -404,7 +432,10 @@ impl Crate {
// get all clippy warnings and ICEs
let warnings: Vec<ClippyWarning> = Message::parse_stream(stdout.as_bytes())
- .filter_map(|msg| ClippyWarning::new(msg.unwrap(), &self))
+ .filter_map(|msg| match msg {
+ Ok(Message::CompilerMessage(message)) => ClippyWarning::new(message.message, &self.name, &self.version),
+ _ => None,
+ })
.collect();
warnings
@@ -423,23 +454,19 @@ fn build_clippy() {
}
}
-/// Read a `toml` file and return a list of `CrateSources` that we want to check with clippy
-fn read_crates(toml_path: &Path) -> Vec<CrateSource> {
+/// Read a `lintcheck_crates.toml` file
+fn read_crates(toml_path: &Path) -> (Vec<CrateSource>, RecursiveOptions) {
let toml_content: String =
- std::fs::read_to_string(&toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display()));
+ std::fs::read_to_string(toml_path).unwrap_or_else(|_| panic!("Failed to read {}", toml_path.display()));
let crate_list: SourceList =
- toml::from_str(&toml_content).unwrap_or_else(|e| panic!("Failed to parse {}: \n{}", toml_path.display(), e));
+ toml::from_str(&toml_content).unwrap_or_else(|e| panic!("Failed to parse {}: \n{e}", toml_path.display()));
// parse the hashmap of the toml file into a list of crates
- let tomlcrates: Vec<TomlCrate> = crate_list
- .crates
- .into_iter()
- .map(|(_cratename, tomlcrate)| tomlcrate)
- .collect();
+ let tomlcrates: Vec<TomlCrate> = crate_list.crates.into_values().collect();
// flatten TomlCrates into CrateSources (one TomlCrates may represent several versions of a crate =>
// multiple Cratesources)
let mut crate_sources = Vec::new();
- tomlcrates.into_iter().for_each(|tk| {
+ for tk in tomlcrates {
if let Some(ref path) = tk.path {
crate_sources.push(CrateSource::Path {
name: tk.name.clone(),
@@ -448,13 +475,13 @@ fn read_crates(toml_path: &Path) -> Vec<CrateSource> {
});
} else if let Some(ref versions) = tk.versions {
// if we have multiple versions, save each one
- versions.iter().for_each(|ver| {
+ for ver in versions.iter() {
crate_sources.push(CrateSource::CratesIo {
name: tk.name.clone(),
version: ver.to_string(),
options: tk.options.clone(),
});
- })
+ }
} else if tk.git_url.is_some() && tk.git_hash.is_some() {
// otherwise, we should have a git source
crate_sources.push(CrateSource::Git {
@@ -471,20 +498,23 @@ fn read_crates(toml_path: &Path) -> Vec<CrateSource> {
if tk.versions.is_some() && (tk.git_url.is_some() || tk.git_hash.is_some())
|| tk.git_hash.is_some() != tk.git_url.is_some()
{
- eprintln!("tomlkrate: {:?}", tk);
- if tk.git_hash.is_some() != tk.git_url.is_some() {
- panic!("Error: Encountered TomlCrate with only one of git_hash and git_url!");
- }
- if tk.path.is_some() && (tk.git_hash.is_some() || tk.versions.is_some()) {
- panic!("Error: TomlCrate can only have one of 'git_.*', 'version' or 'path' fields");
- }
+ eprintln!("tomlkrate: {tk:?}");
+ assert_eq!(
+ tk.git_hash.is_some(),
+ tk.git_url.is_some(),
+ "Error: Encountered TomlCrate with only one of git_hash and git_url!"
+ );
+ assert!(
+ tk.path.is_none() || (tk.git_hash.is_none() && tk.versions.is_none()),
+ "Error: TomlCrate can only have one of 'git_.*', 'version' or 'path' fields"
+ );
unreachable!("Failed to translate TomlCrate into CrateSource!");
}
- });
+ }
// sort the crates
crate_sources.sort();
- crate_sources
+ (crate_sources, crate_list.recursive)
}
/// Generate a short list of occurring lints-types and their count
@@ -499,13 +529,13 @@ fn gather_stats(clippy_warnings: &[ClippyWarning]) -> (String, HashMap<&String,
let mut stats: Vec<(&&String, &usize)> = counter.iter().map(|(lint, count)| (lint, count)).collect();
// sort by "000{count} {clippy::lintname}"
// to not have a lint with 200 and 2 warnings take the same spot
- stats.sort_by_key(|(lint, count)| format!("{:0>4}, {}", count, lint));
+ stats.sort_by_key(|(lint, count)| format!("{count:0>4}, {lint}"));
let mut header = String::from("| lint | count |\n");
header.push_str("| -------------------------------------------------- | ----- |\n");
let stats_string = stats
.iter()
- .map(|(lint, count)| format!("| {:<50} | {:>4} |\n", lint, count))
+ .map(|(lint, count)| format!("| {lint:<50} | {count:>4} |\n"))
.fold(header, |mut table, line| {
table.push_str(&line);
table
@@ -516,20 +546,20 @@ fn gather_stats(clippy_warnings: &[ClippyWarning]) -> (String, HashMap<&String,
/// check if the latest modification of the logfile is older than the modification date of the
/// clippy binary, if this is true, we should clean the lintchec shared target directory and recheck
-fn lintcheck_needs_rerun(lintcheck_logs_path: &Path) -> bool {
+fn lintcheck_needs_rerun(lintcheck_logs_path: &Path, paths: [&Path; 2]) -> bool {
if !lintcheck_logs_path.exists() {
return true;
}
let clippy_modified: std::time::SystemTime = {
- let mut times = [CLIPPY_DRIVER_PATH, CARGO_CLIPPY_PATH].iter().map(|p| {
+ let [cargo, driver] = paths.map(|p| {
std::fs::metadata(p)
.expect("failed to get metadata of file")
.modified()
.expect("failed to get modification date")
});
// the oldest modification of either of the binaries
- std::cmp::max(times.next().unwrap(), times.next().unwrap())
+ std::cmp::max(cargo, driver)
};
let logs_modified: std::time::SystemTime = std::fs::metadata(lintcheck_logs_path)
@@ -542,7 +572,13 @@ fn lintcheck_needs_rerun(lintcheck_logs_path: &Path) -> bool {
logs_modified < clippy_modified
}
+#[allow(clippy::too_many_lines)]
fn main() {
+ // We're being executed as a `RUSTC_WRAPPER` as part of `--recursive`
+ if let Ok(addr) = env::var("LINTCHECK_SERVER") {
+ driver::drive(&addr);
+ }
+
// assert that we launch lintcheck from the repo root (via cargo lintcheck)
if std::fs::metadata("lintcheck/Cargo.toml").is_err() {
eprintln!("lintcheck needs to be run from clippy's repo root!\nUse `cargo lintcheck` alternatively.");
@@ -555,24 +591,26 @@ fn main() {
build_clippy();
println!("Done compiling");
+ let cargo_clippy_path = fs::canonicalize(format!("target/debug/cargo-clippy{EXE_SUFFIX}")).unwrap();
+ let clippy_driver_path = fs::canonicalize(format!("target/debug/clippy-driver{EXE_SUFFIX}")).unwrap();
+
// if the clippy bin is newer than our logs, throw away target dirs to force clippy to
// refresh the logs
- if lintcheck_needs_rerun(&config.lintcheck_results_path) {
+ if lintcheck_needs_rerun(
+ &config.lintcheck_results_path,
+ [&cargo_clippy_path, &clippy_driver_path],
+ ) {
let shared_target_dir = "target/lintcheck/shared_target_dir";
// if we get an Err here, the shared target dir probably does simply not exist
- if let Ok(metadata) = std::fs::metadata(&shared_target_dir) {
+ if let Ok(metadata) = std::fs::metadata(shared_target_dir) {
if metadata.is_dir() {
println!("Clippy is newer than lint check logs, clearing lintcheck shared target dir...");
- std::fs::remove_dir_all(&shared_target_dir)
+ std::fs::remove_dir_all(shared_target_dir)
.expect("failed to remove target/lintcheck/shared_target_dir");
}
}
}
- let cargo_clippy_path: PathBuf = PathBuf::from(CARGO_CLIPPY_PATH)
- .canonicalize()
- .expect("failed to canonicalize path to clippy binary");
-
// assert that clippy is found
assert!(
cargo_clippy_path.is_file(),
@@ -580,7 +618,7 @@ fn main() {
cargo_clippy_path.display()
);
- let clippy_ver = std::process::Command::new(CARGO_CLIPPY_PATH)
+ let clippy_ver = std::process::Command::new(&cargo_clippy_path)
.arg("--version")
.output()
.map(|o| String::from_utf8_lossy(&o.stdout).into_owned())
@@ -589,7 +627,7 @@ fn main() {
// download and extract the crates, then run clippy on them and collect clippy's warnings
// flatten into one big list of warnings
- let crates = read_crates(&config.sources_toml_path);
+ let (crates, recursive_options) = read_crates(&config.sources_toml_path);
let old_stats = read_stats_from_file(&config.lintcheck_results_path);
let counter = AtomicUsize::new(1);
@@ -639,11 +677,31 @@ fn main() {
.build_global()
.unwrap();
- let clippy_warnings: Vec<ClippyWarning> = crates
+ let server = config.recursive.then(|| {
+ fs::remove_dir_all("target/lintcheck/shared_target_dir/recursive").unwrap_or_default();
+
+ LintcheckServer::spawn(recursive_options)
+ });
+
+ let mut clippy_warnings: Vec<ClippyWarning> = crates
.par_iter()
- .flat_map(|krate| krate.run_clippy_lints(&cargo_clippy_path, &counter, crates.len(), &config, &lint_filter))
+ .flat_map(|krate| {
+ krate.run_clippy_lints(
+ &cargo_clippy_path,
+ &clippy_driver_path,
+ &counter,
+ crates.len(),
+ &config,
+ &lint_filter,
+ &server,
+ )
+ })
.collect();
+ if let Some(server) = server {
+ clippy_warnings.extend(server.warnings());
+ }
+
// if we are in --fix mode, don't change the log files, terminate here
if config.fix {
return;
@@ -676,13 +734,13 @@ fn main() {
}
write!(text, "{}", all_msgs.join("")).unwrap();
text.push_str("\n\n### ICEs:\n");
- for (cratename, msg) in ices.iter() {
- let _ = write!(text, "{}: '{}'", cratename, msg);
+ for (cratename, msg) in &ices {
+ let _ = write!(text, "{cratename}: '{msg}'");
}
println!("Writing logs to {}", config.lintcheck_results_path.display());
- std::fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
- write(&config.lintcheck_results_path, text).unwrap();
+ fs::create_dir_all(config.lintcheck_results_path.parent().unwrap()).unwrap();
+ fs::write(&config.lintcheck_results_path, text).unwrap();
print_stats(old_stats, new_stats, &config.lint_filter);
}
@@ -721,7 +779,7 @@ fn read_stats_from_file(file_path: &Path) -> HashMap<String, usize> {
fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, usize>, lint_filter: &Vec<String>) {
let same_in_both_hashmaps = old_stats
.iter()
- .filter(|(old_key, old_val)| new_stats.get::<&String>(&old_key) == Some(old_val))
+ .filter(|(old_key, old_val)| new_stats.get::<&String>(old_key) == Some(old_val))
.map(|(k, v)| (k.to_string(), *v))
.collect::<Vec<(String, usize)>>();
@@ -729,37 +787,37 @@ fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, us
let mut new_stats_deduped = new_stats;
// remove duplicates from both hashmaps
- same_in_both_hashmaps.iter().for_each(|(k, v)| {
+ for (k, v) in &same_in_both_hashmaps {
assert!(old_stats_deduped.remove(k) == Some(*v));
assert!(new_stats_deduped.remove(k) == Some(*v));
- });
+ }
println!("\nStats:");
// list all new counts (key is in new stats but not in old stats)
new_stats_deduped
.iter()
- .filter(|(new_key, _)| old_stats_deduped.get::<str>(&new_key).is_none())
+ .filter(|(new_key, _)| old_stats_deduped.get::<str>(new_key).is_none())
.for_each(|(new_key, new_value)| {
- println!("{} 0 => {}", new_key, new_value);
+ println!("{new_key} 0 => {new_value}");
});
// list all changed counts (key is in both maps but value differs)
new_stats_deduped
.iter()
- .filter(|(new_key, _new_val)| old_stats_deduped.get::<str>(&new_key).is_some())
+ .filter(|(new_key, _new_val)| old_stats_deduped.get::<str>(new_key).is_some())
.for_each(|(new_key, new_val)| {
- let old_val = old_stats_deduped.get::<str>(&new_key).unwrap();
- println!("{} {} => {}", new_key, old_val, new_val);
+ let old_val = old_stats_deduped.get::<str>(new_key).unwrap();
+ println!("{new_key} {old_val} => {new_val}");
});
// list all gone counts (key is in old status but not in new stats)
old_stats_deduped
.iter()
- .filter(|(old_key, _)| new_stats_deduped.get::<&String>(&old_key).is_none())
+ .filter(|(old_key, _)| new_stats_deduped.get::<&String>(old_key).is_none())
.filter(|(old_key, _)| lint_filter.is_empty() || lint_filter.contains(old_key))
.for_each(|(old_key, old_value)| {
- println!("{} {} => 0", old_key, old_value);
+ println!("{old_key} {old_value} => 0");
});
}
@@ -770,19 +828,21 @@ fn print_stats(old_stats: HashMap<String, usize>, new_stats: HashMap<&String, us
/// This function panics if creating one of the dirs fails.
fn create_dirs(krate_download_dir: &Path, extract_dir: &Path) {
std::fs::create_dir("target/lintcheck/").unwrap_or_else(|err| {
- if err.kind() != ErrorKind::AlreadyExists {
- panic!("cannot create lintcheck target dir");
- }
+ assert_eq!(
+ err.kind(),
+ ErrorKind::AlreadyExists,
+ "cannot create lintcheck target dir"
+ );
});
- std::fs::create_dir(&krate_download_dir).unwrap_or_else(|err| {
- if err.kind() != ErrorKind::AlreadyExists {
- panic!("cannot create crate download dir");
- }
+ std::fs::create_dir(krate_download_dir).unwrap_or_else(|err| {
+ assert_eq!(err.kind(), ErrorKind::AlreadyExists, "cannot create crate download dir");
});
- std::fs::create_dir(&extract_dir).unwrap_or_else(|err| {
- if err.kind() != ErrorKind::AlreadyExists {
- panic!("cannot create crate extraction dir");
- }
+ std::fs::create_dir(extract_dir).unwrap_or_else(|err| {
+ assert_eq!(
+ err.kind(),
+ ErrorKind::AlreadyExists,
+ "cannot create crate extraction dir"
+ );
});
}
@@ -805,7 +865,7 @@ fn lintcheck_test() {
"lintcheck/test_sources.toml",
];
let status = std::process::Command::new("cargo")
- .args(&args)
+ .args(args)
.current_dir("..") // repo root
.status();
//.output();
diff --git a/src/tools/clippy/lintcheck/src/recursive.rs b/src/tools/clippy/lintcheck/src/recursive.rs
new file mode 100644
index 000000000..49072e651
--- /dev/null
+++ b/src/tools/clippy/lintcheck/src/recursive.rs
@@ -0,0 +1,123 @@
+//! In `--recursive` mode we set the `lintcheck` binary as the `RUSTC_WRAPPER` of `cargo check`,
+//! this allows [`crate::driver`] to be run for every dependency. The driver connects to
+//! [`LintcheckServer`] to ask if it should be skipped, and if not sends the stderr of running
+//! clippy on the crate to the server
+
+use crate::ClippyWarning;
+use crate::RecursiveOptions;
+
+use std::collections::HashSet;
+use std::io::{BufRead, BufReader, Read, Write};
+use std::net::{SocketAddr, TcpListener, TcpStream};
+use std::sync::{Arc, Mutex};
+use std::thread;
+
+use cargo_metadata::diagnostic::Diagnostic;
+use crossbeam_channel::{Receiver, Sender};
+use serde::de::DeserializeOwned;
+use serde::{Deserialize, Serialize};
+
+#[derive(Debug, Eq, Hash, PartialEq, Clone, Serialize, Deserialize)]
+pub(crate) struct DriverInfo {
+ pub package_name: String,
+ pub crate_name: String,
+ pub version: String,
+}
+
+pub(crate) fn serialize_line<T, W>(value: &T, writer: &mut W)
+where
+ T: Serialize,
+ W: Write,
+{
+ let mut buf = serde_json::to_vec(&value).expect("failed to serialize");
+ buf.push(b'\n');
+ writer.write_all(&buf).expect("write_all failed");
+}
+
+pub(crate) fn deserialize_line<T, R>(reader: &mut R) -> T
+where
+ T: DeserializeOwned,
+ R: BufRead,
+{
+ let mut string = String::new();
+ reader.read_line(&mut string).expect("read_line failed");
+ serde_json::from_str(&string).expect("failed to deserialize")
+}
+
+fn process_stream(
+ stream: TcpStream,
+ sender: &Sender<ClippyWarning>,
+ options: &RecursiveOptions,
+ seen: &Mutex<HashSet<DriverInfo>>,
+) {
+ let mut stream = BufReader::new(stream);
+
+ let driver_info: DriverInfo = deserialize_line(&mut stream);
+
+ let unseen = seen.lock().unwrap().insert(driver_info.clone());
+ let ignored = options.ignore.contains(&driver_info.package_name);
+ let should_run = unseen && !ignored;
+
+ serialize_line(&should_run, stream.get_mut());
+
+ let mut stderr = String::new();
+ stream.read_to_string(&mut stderr).unwrap();
+
+ let messages = stderr
+ .lines()
+ .filter_map(|json_msg| serde_json::from_str::<Diagnostic>(json_msg).ok())
+ .filter_map(|diag| ClippyWarning::new(diag, &driver_info.package_name, &driver_info.version));
+
+ for message in messages {
+ sender.send(message).unwrap();
+ }
+}
+
+pub(crate) struct LintcheckServer {
+ pub local_addr: SocketAddr,
+ receiver: Receiver<ClippyWarning>,
+ sender: Arc<Sender<ClippyWarning>>,
+}
+
+impl LintcheckServer {
+ pub fn spawn(options: RecursiveOptions) -> Self {
+ let listener = TcpListener::bind("localhost:0").unwrap();
+ let local_addr = listener.local_addr().unwrap();
+
+ let (sender, receiver) = crossbeam_channel::unbounded::<ClippyWarning>();
+ let sender = Arc::new(sender);
+ // The spawned threads hold a `Weak<Sender>` so that they don't keep the channel connected
+ // indefinitely
+ let sender_weak = Arc::downgrade(&sender);
+
+ // Ignore dependencies multiple times, e.g. for when it's both checked and compiled for a
+ // build dependency
+ let seen = Mutex::default();
+
+ thread::spawn(move || {
+ thread::scope(|s| {
+ s.spawn(|| {
+ while let Ok((stream, _)) = listener.accept() {
+ let sender = sender_weak.upgrade().expect("received connection after server closed");
+ let options = &options;
+ let seen = &seen;
+ s.spawn(move || process_stream(stream, &sender, options, seen));
+ }
+ });
+ });
+ });
+
+ Self {
+ local_addr,
+ receiver,
+ sender,
+ }
+ }
+
+ pub fn warnings(self) -> impl Iterator<Item = ClippyWarning> {
+ // causes the channel to become disconnected so that the receiver iterator ends
+ drop(self.sender);
+
+ self.receiver.into_iter()
+ }
+}
diff --git a/src/tools/clippy/rust-toolchain b/src/tools/clippy/rust-toolchain
index b6976366d..748d8a317 100644
--- a/src/tools/clippy/rust-toolchain
+++ b/src/tools/clippy/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-09-08"
+channel = "nightly-2022-10-20"
components = ["cargo", "llvm-tools-preview", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"]
diff --git a/src/tools/clippy/rustc_tools_util/Cargo.toml b/src/tools/clippy/rustc_tools_util/Cargo.toml
index 9554d4d6c..89c3d6aaa 100644
--- a/src/tools/clippy/rustc_tools_util/Cargo.toml
+++ b/src/tools/clippy/rustc_tools_util/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "rustc_tools_util"
-version = "0.2.0"
+version = "0.2.1"
description = "small helper to generate version information for git packages"
repository = "https://github.com/rust-lang/rust-clippy"
readme = "README.md"
diff --git a/src/tools/clippy/rustc_tools_util/README.md b/src/tools/clippy/rustc_tools_util/README.md
index 01891b51d..e947f9c7e 100644
--- a/src/tools/clippy/rustc_tools_util/README.md
+++ b/src/tools/clippy/rustc_tools_util/README.md
@@ -6,17 +6,17 @@ for packages installed from a git repo
## Usage
Add a `build.rs` file to your repo and list it in `Cargo.toml`
-````
+````toml
build = "build.rs"
````
List rustc_tools_util as regular AND build dependency.
-````
+````toml
[dependencies]
-rustc_tools_util = "0.1"
+rustc_tools_util = "0.2.1"
[build-dependencies]
-rustc_tools_util = "0.1"
+rustc_tools_util = "0.2.1"
````
In `build.rs`, generate the data in your `main()`
diff --git a/src/tools/clippy/rustc_tools_util/src/lib.rs b/src/tools/clippy/rustc_tools_util/src/lib.rs
index 429dddc42..01d25c531 100644
--- a/src/tools/clippy/rustc_tools_util/src/lib.rs
+++ b/src/tools/clippy/rustc_tools_util/src/lib.rs
@@ -48,8 +48,8 @@ impl std::fmt::Display for VersionInfo {
if (hash_trimmed.len() + date_trimmed.len()) > 0 {
write!(
f,
- "{} {}.{}.{} ({} {})",
- self.crate_name, self.major, self.minor, self.patch, hash_trimmed, date_trimmed,
+ "{} {}.{}.{} ({hash_trimmed} {date_trimmed})",
+ self.crate_name, self.major, self.minor, self.patch,
)?;
} else {
write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
@@ -137,7 +137,7 @@ mod test {
let vi = get_version_info!();
assert_eq!(vi.major, 0);
assert_eq!(vi.minor, 2);
- assert_eq!(vi.patch, 0);
+ assert_eq!(vi.patch, 1);
assert_eq!(vi.crate_name, "rustc_tools_util");
// hard to make positive tests for these since they will always change
assert!(vi.commit_hash.is_none());
@@ -147,16 +147,16 @@ mod test {
#[test]
fn test_display_local() {
let vi = get_version_info!();
- assert_eq!(vi.to_string(), "rustc_tools_util 0.2.0");
+ assert_eq!(vi.to_string(), "rustc_tools_util 0.2.1");
}
#[test]
fn test_debug_local() {
let vi = get_version_info!();
- let s = format!("{:?}", vi);
+ let s = format!("{vi:?}");
assert_eq!(
s,
- "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 0 }"
+ "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 1 }"
);
}
}
diff --git a/src/tools/clippy/src/docs.rs b/src/tools/clippy/src/docs.rs
index f3a5048e7..c033ad294 100644
--- a/src/tools/clippy/src/docs.rs
+++ b/src/tools/clippy/src/docs.rs
@@ -28,6 +28,7 @@ docs! {
"approx_constant",
"arithmetic_side_effects",
"as_conversions",
+ "as_ptr_cast_mut",
"as_underscore",
"assertions_on_constants",
"assertions_on_result_states",
@@ -48,6 +49,7 @@ docs! {
"borrow_interior_mutable_const",
"borrowed_box",
"box_collection",
+ "box_default",
"boxed_local",
"branches_sharing_code",
"builtin_type_shadow",
@@ -59,6 +61,7 @@ docs! {
"cast_enum_constructor",
"cast_enum_truncation",
"cast_lossless",
+ "cast_nan_to_int",
"cast_possible_truncation",
"cast_possible_wrap",
"cast_precision_loss",
@@ -105,6 +108,7 @@ docs! {
"derive_hash_xor_eq",
"derive_ord_xor_partial_ord",
"derive_partial_eq_without_eq",
+ "disallowed_macros",
"disallowed_methods",
"disallowed_names",
"disallowed_script_idents",
@@ -168,7 +172,6 @@ docs! {
"fn_to_numeric_cast_any",
"fn_to_numeric_cast_with_truncation",
"for_kv_map",
- "for_loops_over_fallibles",
"forget_copy",
"forget_non_drop",
"forget_ref",
@@ -190,6 +193,7 @@ docs! {
"implicit_clone",
"implicit_hasher",
"implicit_return",
+ "implicit_saturating_add",
"implicit_saturating_sub",
"imprecise_flops",
"inconsistent_digit_grouping",
@@ -221,6 +225,7 @@ docs! {
"items_after_statements",
"iter_cloned_collect",
"iter_count",
+ "iter_kv_map",
"iter_next_loop",
"iter_next_slice",
"iter_not_returning_iterator",
@@ -253,6 +258,8 @@ docs! {
"manual_assert",
"manual_async_fn",
"manual_bits",
+ "manual_clamp",
+ "manual_filter",
"manual_filter_map",
"manual_find",
"manual_find_map",
@@ -309,6 +316,7 @@ docs! {
"missing_panics_doc",
"missing_safety_doc",
"missing_spin_loop",
+ "missing_trait_methods",
"mistyped_literal_suffixes",
"mixed_case_hex_literals",
"mixed_read_write_in_expression",
@@ -387,11 +395,11 @@ docs! {
"panic",
"panic_in_result_fn",
"panicking_unwrap",
+ "partial_pub_fields",
"partialeq_ne_impl",
"partialeq_to_none",
"path_buf_push_overwrite",
"pattern_type_mismatch",
- "positional_named_format_parameters",
"possible_missing_comma",
"precedence",
"print_in_format_impl",
@@ -521,6 +529,7 @@ docs! {
"unimplemented",
"uninit_assumed_init",
"uninit_vec",
+ "uninlined_format_args",
"unit_arg",
"unit_cmp",
"unit_hash",
@@ -549,6 +558,7 @@ docs! {
"unseparated_literal_suffix",
"unsound_collection_transmute",
"unused_async",
+ "unused_format_specs",
"unused_io_amount",
"unused_peekable",
"unused_rounding",
diff --git a/src/tools/clippy/src/docs/arithmetic_side_effects.txt b/src/tools/clippy/src/docs/arithmetic_side_effects.txt
index 6c7d51a49..4ae8bce88 100644
--- a/src/tools/clippy/src/docs/arithmetic_side_effects.txt
+++ b/src/tools/clippy/src/docs/arithmetic_side_effects.txt
@@ -5,7 +5,7 @@ Operators like `+`, `-`, `*` or `<<` are usually capable of overflowing accordin
Reference](https://doc.rust-lang.org/reference/expressions/operator-expr.html#overflow),
or can panic (`/`, `%`).
-Known safe built-in types like `Wrapping` or `Saturing`, floats, operations in constant
+Known safe built-in types like `Wrapping` or `Saturating`, floats, operations in constant
environments, allowed types and non-constant operations that won't overflow are ignored.
### Why is this bad?
diff --git a/src/tools/clippy/src/docs/as_ptr_cast_mut.txt b/src/tools/clippy/src/docs/as_ptr_cast_mut.txt
new file mode 100644
index 000000000..228dde996
--- /dev/null
+++ b/src/tools/clippy/src/docs/as_ptr_cast_mut.txt
@@ -0,0 +1,19 @@
+### What it does
+Checks for the result of a `&self`-taking `as_ptr` being cast to a mutable pointer
+
+### Why is this bad?
+Since `as_ptr` takes a `&self`, the pointer won't have write permissions unless interior
+mutability is used, making it unlikely that having it as a mutable pointer is correct.
+
+### Example
+```
+let string = String::with_capacity(1);
+let ptr = string.as_ptr() as *mut u8;
+unsafe { ptr.write(4) }; // UNDEFINED BEHAVIOUR
+```
+Use instead:
+```
+let mut string = String::with_capacity(1);
+let ptr = string.as_mut_ptr();
+unsafe { ptr.write(4) };
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/box_default.txt b/src/tools/clippy/src/docs/box_default.txt
new file mode 100644
index 000000000..1c670c773
--- /dev/null
+++ b/src/tools/clippy/src/docs/box_default.txt
@@ -0,0 +1,17 @@
+### What it does
+checks for `Box::new(T::default())`, which is better written as
+`Box::<T>::default()`.
+
+### Why is this bad?
+First, it's more complex, involving two calls instead of one.
+Second, `Box::default()` can be faster
+[in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box).
+
+### Example
+```
+let x: Box<String> = Box::new(Default::default());
+```
+Use instead:
+```
+let x: Box<String> = Box::default();
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/cast_nan_to_int.txt b/src/tools/clippy/src/docs/cast_nan_to_int.txt
new file mode 100644
index 000000000..122f5da0c
--- /dev/null
+++ b/src/tools/clippy/src/docs/cast_nan_to_int.txt
@@ -0,0 +1,15 @@
+### What it does
+Checks for a known NaN float being cast to an integer
+
+### Why is this bad?
+NaNs are cast into zero, so one could simply use this and make the
+code more readable. The lint could also hint at a programmer error.
+
+### Example
+```
+let _: (0.0_f32 / 0.0) as u64;
+```
+Use instead:
+```
+let _: = 0_u64;
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/disallowed_macros.txt b/src/tools/clippy/src/docs/disallowed_macros.txt
new file mode 100644
index 000000000..96fa15afa
--- /dev/null
+++ b/src/tools/clippy/src/docs/disallowed_macros.txt
@@ -0,0 +1,36 @@
+### What it does
+Denies the configured macros in clippy.toml
+
+Note: Even though this lint is warn-by-default, it will only trigger if
+macros are defined in the clippy.toml file.
+
+### Why is this bad?
+Some macros are undesirable in certain contexts, and it's beneficial to
+lint for them as needed.
+
+### Example
+An example clippy.toml configuration:
+```
+disallowed-macros = [
+ # Can use a string as the path of the disallowed macro.
+ "std::print",
+ # Can also use an inline table with a `path` key.
+ { path = "std::println" },
+ # When using an inline table, can add a `reason` for why the macro
+ # is disallowed.
+ { path = "serde::Serialize", reason = "no serializing" },
+]
+```
+```
+use serde::Serialize;
+
+// Example code where clippy issues a warning
+println!("warns");
+
+// The diagnostic will contain the message "no serializing"
+#[derive(Serialize)]
+struct Data {
+ name: String,
+ value: usize,
+}
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/for_loops_over_fallibles.txt b/src/tools/clippy/src/docs/for_loops_over_fallibles.txt
deleted file mode 100644
index c5a7508e4..000000000
--- a/src/tools/clippy/src/docs/for_loops_over_fallibles.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-### What it does
-Checks for `for` loops over `Option` or `Result` values.
-
-### Why is this bad?
-Readability. This is more clearly expressed as an `if
-let`.
-
-### Example
-```
-for x in opt {
- // ..
-}
-
-for x in &res {
- // ..
-}
-
-for x in res.iter() {
- // ..
-}
-```
-
-Use instead:
-```
-if let Some(x) = opt {
- // ..
-}
-
-if let Ok(x) = res {
- // ..
-}
-``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/implicit_saturating_add.txt b/src/tools/clippy/src/docs/implicit_saturating_add.txt
new file mode 100644
index 000000000..5883a5363
--- /dev/null
+++ b/src/tools/clippy/src/docs/implicit_saturating_add.txt
@@ -0,0 +1,20 @@
+### What it does
+Checks for implicit saturating addition.
+
+### Why is this bad?
+The built-in function is more readable and may be faster.
+
+### Example
+```
+let mut u:u32 = 7000;
+
+if u != u32::MAX {
+ u += 1;
+}
+```
+Use instead:
+```
+let mut u:u32 = 7000;
+
+u = u.saturating_add(1);
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/iter_kv_map.txt b/src/tools/clippy/src/docs/iter_kv_map.txt
new file mode 100644
index 000000000..a063c8195
--- /dev/null
+++ b/src/tools/clippy/src/docs/iter_kv_map.txt
@@ -0,0 +1,22 @@
+### What it does
+
+Checks for iterating a map (`HashMap` or `BTreeMap`) and
+ignoring either the keys or values.
+
+### Why is this bad?
+
+Readability. There are `keys` and `values` methods that
+can be used to express that we only need the keys or the values.
+
+### Example
+
+```
+let map: HashMap<u32, u32> = HashMap::new();
+let values = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+```
+
+Use instead:
+```
+let map: HashMap<u32, u32> = HashMap::new();
+let values = map.values().collect::<Vec<_>>();
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_clamp.txt b/src/tools/clippy/src/docs/manual_clamp.txt
new file mode 100644
index 000000000..8993f6683
--- /dev/null
+++ b/src/tools/clippy/src/docs/manual_clamp.txt
@@ -0,0 +1,46 @@
+### What it does
+Identifies good opportunities for a clamp function from std or core, and suggests using it.
+
+### Why is this bad?
+clamp is much shorter, easier to read, and doesn't use any control flow.
+
+### Known issue(s)
+If the clamped variable is NaN this suggestion will cause the code to propagate NaN
+rather than returning either `max` or `min`.
+
+`clamp` functions will panic if `max < min`, `max.is_nan()`, or `min.is_nan()`.
+Some may consider panicking in these situations to be desirable, but it also may
+introduce panicking where there wasn't any before.
+
+### Examples
+```
+if input > max {
+ max
+} else if input < min {
+ min
+} else {
+ input
+}
+```
+
+```
+input.max(min).min(max)
+```
+
+```
+match input {
+ x if x > max => max,
+ x if x < min => min,
+ x => x,
+}
+```
+
+```
+let mut x = input;
+if x < min { x = min; }
+if x > max { x = max; }
+```
+Use instead:
+```
+input.clamp(min, max)
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/manual_filter.txt b/src/tools/clippy/src/docs/manual_filter.txt
new file mode 100644
index 000000000..19a4d9319
--- /dev/null
+++ b/src/tools/clippy/src/docs/manual_filter.txt
@@ -0,0 +1,21 @@
+### What it does
+Checks for usages of `match` which could be implemented using `filter`
+
+### Why is this bad?
+Using the `filter` method is clearer and more concise.
+
+### Example
+```
+match Some(0) {
+ Some(x) => if x % 2 == 0 {
+ Some(x)
+ } else {
+ None
+ },
+ None => None,
+};
+```
+Use instead:
+```
+Some(0).filter(|&x| x % 2 == 0);
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/missing_trait_methods.txt b/src/tools/clippy/src/docs/missing_trait_methods.txt
new file mode 100644
index 000000000..788ad764f
--- /dev/null
+++ b/src/tools/clippy/src/docs/missing_trait_methods.txt
@@ -0,0 +1,40 @@
+### What it does
+Checks if a provided method is used implicitly by a trait
+implementation. A usage example would be a wrapper where every method
+should perform some operation before delegating to the inner type's
+implemenation.
+
+This lint should typically be enabled on a specific trait `impl` item
+rather than globally.
+
+### Why is this bad?
+Indicates that a method is missing.
+
+### Example
+```
+trait Trait {
+ fn required();
+
+ fn provided() {}
+}
+
+#[warn(clippy::missing_trait_methods)]
+impl Trait for Type {
+ fn required() { /* ... */ }
+}
+```
+Use instead:
+```
+trait Trait {
+ fn required();
+
+ fn provided() {}
+}
+
+#[warn(clippy::missing_trait_methods)]
+impl Trait for Type {
+ fn required() { /* ... */ }
+
+ fn provided() { /* ... */ }
+}
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/needless_borrowed_reference.txt b/src/tools/clippy/src/docs/needless_borrowed_reference.txt
index 55faa0cf5..152459ba1 100644
--- a/src/tools/clippy/src/docs/needless_borrowed_reference.txt
+++ b/src/tools/clippy/src/docs/needless_borrowed_reference.txt
@@ -1,30 +1,22 @@
### What it does
-Checks for bindings that destructure a reference and borrow the inner
+Checks for bindings that needlessly destructure a reference and borrow the inner
value with `&ref`.
### Why is this bad?
This pattern has no effect in almost all cases.
-### Known problems
-In some cases, `&ref` is needed to avoid a lifetime mismatch error.
-Example:
-```
-fn foo(a: &Option<String>, b: &Option<String>) {
- match (a, b) {
- (None, &ref c) | (&ref c, None) => (),
- (&Some(ref c), _) => (),
- };
-}
-```
-
### Example
```
let mut v = Vec::<String>::new();
v.iter_mut().filter(|&ref a| a.is_empty());
+
+if let &[ref first, ref second] = v.as_slice() {}
```
Use instead:
```
let mut v = Vec::<String>::new();
v.iter_mut().filter(|a| a.is_empty());
+
+if let [first, second] = v.as_slice() {}
``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/partial_pub_fields.txt b/src/tools/clippy/src/docs/partial_pub_fields.txt
new file mode 100644
index 000000000..b529adf15
--- /dev/null
+++ b/src/tools/clippy/src/docs/partial_pub_fields.txt
@@ -0,0 +1,27 @@
+### What it does
+Checks whether partial fields of a struct are public.
+
+Either make all fields of a type public, or make none of them public
+
+### Why is this bad?
+Most types should either be:
+* Abstract data types: complex objects with opaque implementation which guard
+interior invariants and expose intentionally limited API to the outside world.
+* Data: relatively simple objects which group a bunch of related attributes together.
+
+### Example
+```
+pub struct Color {
+ pub r: u8,
+ pub g: u8,
+ b: u8,
+}
+```
+Use instead:
+```
+pub struct Color {
+ pub r: u8,
+ pub g: u8,
+ pub b: u8,
+}
+``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/positional_named_format_parameters.txt b/src/tools/clippy/src/docs/positional_named_format_parameters.txt
deleted file mode 100644
index e391d2406..000000000
--- a/src/tools/clippy/src/docs/positional_named_format_parameters.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-### What it does
-This lint warns when a named parameter in a format string is used as a positional one.
-
-### Why is this bad?
-It may be confused for an assignment and obfuscates which parameter is being used.
-
-### Example
-```
-println!("{}", x = 10);
-```
-
-Use instead:
-```
-println!("{x}", x = 10);
-``` \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/print_literal.txt b/src/tools/clippy/src/docs/print_literal.txt
index 160073414..a6252a687 100644
--- a/src/tools/clippy/src/docs/print_literal.txt
+++ b/src/tools/clippy/src/docs/print_literal.txt
@@ -6,10 +6,6 @@ Using literals as `println!` args is inefficient
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
(i.e., just put the literal in the format string)
-### Known problems
-Will also warn with macro calls as arguments that expand to literals
--- e.g., `println!("{}", env!("FOO"))`.
-
### Example
```
println!("{}", "foo");
diff --git a/src/tools/clippy/src/docs/print_stderr.txt b/src/tools/clippy/src/docs/print_stderr.txt
index fc14511cd..9c6edeeef 100644
--- a/src/tools/clippy/src/docs/print_stderr.txt
+++ b/src/tools/clippy/src/docs/print_stderr.txt
@@ -7,13 +7,7 @@ People often print on *stderr* while debugging an
application and might forget to remove those prints afterward.
### Known problems
-* Only catches `eprint!` and `eprintln!` calls.
-* The lint level is unaffected by crate attributes. The level can still
- be set for functions, modules and other items. To change the level for
- the entire crate, please use command line flags. More information and a
- configuration example can be found in [clippy#6610].
-
-[clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
+Only catches `eprint!` and `eprintln!` calls.
### Example
```
diff --git a/src/tools/clippy/src/docs/print_stdout.txt b/src/tools/clippy/src/docs/print_stdout.txt
index 6c9a4b98e..d2cbd811d 100644
--- a/src/tools/clippy/src/docs/print_stdout.txt
+++ b/src/tools/clippy/src/docs/print_stdout.txt
@@ -7,13 +7,7 @@ People often print on *stdout* while debugging an
application and might forget to remove those prints afterward.
### Known problems
-* Only catches `print!` and `println!` calls.
-* The lint level is unaffected by crate attributes. The level can still
- be set for functions, modules and other items. To change the level for
- the entire crate, please use command line flags. More information and a
- configuration example can be found in [clippy#6610].
-
-[clippy#6610]: https://github.com/rust-lang/rust-clippy/issues/6610#issuecomment-977120558
+Only catches `print!` and `println!` calls.
### Example
```
diff --git a/src/tools/clippy/src/docs/similar_names.txt b/src/tools/clippy/src/docs/similar_names.txt
index 13aca9c0b..f9eff21b6 100644
--- a/src/tools/clippy/src/docs/similar_names.txt
+++ b/src/tools/clippy/src/docs/similar_names.txt
@@ -1,6 +1,10 @@
### What it does
Checks for names that are very similar and thus confusing.
+Note: this lint looks for similar names throughout each
+scope. To allow it, you need to allow it on the scope
+level, not on the name that is reported.
+
### Why is this bad?
It's hard to distinguish between names that differ only
by a single character.
diff --git a/src/tools/clippy/src/docs/uninlined_format_args.txt b/src/tools/clippy/src/docs/uninlined_format_args.txt
new file mode 100644
index 000000000..3d2966c84
--- /dev/null
+++ b/src/tools/clippy/src/docs/uninlined_format_args.txt
@@ -0,0 +1,36 @@
+### What it does
+Detect when a variable is not inlined in a format string,
+and suggests to inline it.
+
+### Why is this bad?
+Non-inlined code is slightly more difficult to read and understand,
+as it requires arguments to be matched against the format string.
+The inlined syntax, where allowed, is simpler.
+
+### Example
+```
+format!("{}", var);
+format!("{v:?}", v = var);
+format!("{0} {0}", var);
+format!("{0:1$}", var, width);
+format!("{:.*}", prec, var);
+```
+Use instead:
+```
+format!("{var}");
+format!("{var:?}");
+format!("{var} {var}");
+format!("{var:width$}");
+format!("{var:.prec$}");
+```
+
+### Known Problems
+
+There may be a false positive if the format string is expanded from certain proc macros:
+
+```
+println!(indoc!("{}"), var);
+```
+
+If a format string contains a numbered argument that cannot be inlined
+nothing will be suggested, e.g. `println!("{0}={1}", var, 1+2)`. \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/unused_format_specs.txt b/src/tools/clippy/src/docs/unused_format_specs.txt
new file mode 100644
index 000000000..77be3a2fb
--- /dev/null
+++ b/src/tools/clippy/src/docs/unused_format_specs.txt
@@ -0,0 +1,24 @@
+### What it does
+Detects [formatting parameters] that have no effect on the output of
+`format!()`, `println!()` or similar macros.
+
+### Why is this bad?
+Shorter format specifiers are easier to read, it may also indicate that
+an expected formatting operation such as adding padding isn't happening.
+
+### Example
+```
+println!("{:.}", 1.0);
+
+println!("not padded: {:5}", format_args!("..."));
+```
+Use instead:
+```
+println!("{}", 1.0);
+
+println!("not padded: {}", format_args!("..."));
+// OR
+println!("padded: {:5}", format!("..."));
+```
+
+[formatting parameters]: https://doc.rust-lang.org/std/fmt/index.html#formatting-parameters \ No newline at end of file
diff --git a/src/tools/clippy/src/docs/write_literal.txt b/src/tools/clippy/src/docs/write_literal.txt
index 9c41a48f9..a7a884d08 100644
--- a/src/tools/clippy/src/docs/write_literal.txt
+++ b/src/tools/clippy/src/docs/write_literal.txt
@@ -6,10 +6,6 @@ Using literals as `writeln!` args is inefficient
(c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
(i.e., just put the literal in the format string)
-### Known problems
-Will also warn with macro calls as arguments that expand to literals
--- e.g., `writeln!(buf, "{}", env!("FOO"))`.
-
### Example
```
writeln!(buf, "{}", "foo");
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 235eae5af..b12208ac6 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -193,8 +193,8 @@ fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
let 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!("Clippy version: {}", version_info).into(),
+ format!("we would appreciate a bug report: {bug_report_url}").into(),
+ format!("Clippy version: {version_info}").into(),
];
for note in &xs {
@@ -290,7 +290,7 @@ pub fn main() {
if orig_args.iter().any(|a| a == "--version" || a == "-V") {
let version_info = rustc_tools_util::get_version_info!();
- println!("{}", version_info);
+ println!("{version_info}");
exit(0);
}
diff --git a/src/tools/clippy/src/main.rs b/src/tools/clippy/src/main.rs
index 4a32e0e54..fce3cdfc4 100644
--- a/src/tools/clippy/src/main.rs
+++ b/src/tools/clippy/src/main.rs
@@ -37,12 +37,12 @@ You can use tool lints to allow or deny lints from your code, eg.:
"#;
fn show_help() {
- println!("{}", CARGO_CLIPPY_HELP);
+ println!("{CARGO_CLIPPY_HELP}");
}
fn show_version() {
let version_info = rustc_tools_util::get_version_info!();
- println!("{}", version_info);
+ println!("{version_info}");
}
pub fn main() {
@@ -133,7 +133,7 @@ impl ClippyCmd {
let clippy_args: String = self
.clippy_args
.iter()
- .map(|arg| format!("{}__CLIPPY_HACKERY__", arg))
+ .map(|arg| format!("{arg}__CLIPPY_HACKERY__"))
.collect();
// Currently, `CLIPPY_TERMINAL_WIDTH` is used only to format "unknown field" error messages.
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index ba6186e59..c10ee969c 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -111,15 +111,14 @@ static EXTERN_FLAGS: LazyLock<String> = LazyLock::new(|| {
.collect();
assert!(
not_found.is_empty(),
- "dependencies not found in depinfo: {:?}\n\
+ "dependencies not found in depinfo: {not_found:?}\n\
help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
help: Try adding to dev-dependencies in Cargo.toml\n\
help: Be sure to also add `extern crate ...;` to tests/compile-test.rs",
- not_found,
);
crates
.into_iter()
- .map(|(name, path)| format!(" --extern {}={}", name, path))
+ .map(|(name, path)| format!(" --extern {name}={path}"))
.collect()
});
@@ -150,9 +149,8 @@ fn base_config(test_dir: &str) -> compiletest::Config {
.map(|p| format!(" -L dependency={}", Path::new(p).join("deps").display()))
.unwrap_or_default();
config.target_rustcflags = Some(format!(
- "--emit=metadata -Dwarnings -Zui-testing -L dependency={}{}{}",
+ "--emit=metadata -Dwarnings -Zui-testing -L dependency={}{host_libs}{}",
deps_path.display(),
- host_libs,
&*EXTERN_FLAGS,
));
@@ -239,7 +237,7 @@ fn run_ui_toml() {
Ok(true) => {},
Ok(false) => panic!("Some tests failed"),
Err(e) => {
- panic!("I/O failure during tests: {:?}", e);
+ panic!("I/O failure during tests: {e:?}");
},
}
}
@@ -285,7 +283,7 @@ fn run_ui_cargo() {
env::set_current_dir(&src_path)?;
let cargo_toml_path = case.path().join("Cargo.toml");
- let cargo_content = fs::read(&cargo_toml_path)?;
+ let cargo_content = fs::read(cargo_toml_path)?;
let cargo_parsed: toml::Value = toml::from_str(
std::str::from_utf8(&cargo_content).expect("`Cargo.toml` is not a valid utf-8 file!"),
)
@@ -348,7 +346,7 @@ fn run_ui_cargo() {
Ok(true) => {},
Ok(false) => panic!("Some tests failed"),
Err(e) => {
- panic!("I/O failure during tests: {:?}", e);
+ panic!("I/O failure during tests: {e:?}");
},
}
}
@@ -419,16 +417,15 @@ fn check_rustfix_coverage() {
if rs_path.starts_with("tests/ui/crashes") {
continue;
}
- assert!(rs_path.starts_with("tests/ui/"), "{:?}", rs_file);
+ assert!(rs_path.starts_with("tests/ui/"), "{rs_file:?}");
let filename = rs_path.strip_prefix("tests/ui/").unwrap();
assert!(
RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS
.binary_search_by_key(&filename, Path::new)
.is_ok(),
- "`{}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \
+ "`{rs_file}` runs `MachineApplicable` diagnostics but is missing a `run-rustfix` annotation. \
Please either add `// run-rustfix` at the top of the file or add the file to \
`RUSTFIX_COVERAGE_KNOWN_EXCEPTIONS` in `tests/compile-test.rs`.",
- rs_file,
);
}
}
@@ -478,15 +475,13 @@ fn ui_cargo_toml_metadata() {
.map(|component| component.as_os_str().to_string_lossy().replace('-', "_"))
.any(|s| *s == name)
|| path.starts_with(&cargo_common_metadata_path),
- "{:?} has incorrect package name",
- path
+ "{path:?} has incorrect package name"
);
let publish = package.get("publish").and_then(toml::Value::as_bool).unwrap_or(true);
assert!(
!publish || publish_exceptions.contains(&path.parent().unwrap().to_path_buf()),
- "{:?} lacks `publish = false`",
- path
+ "{path:?} lacks `publish = false`"
);
}
}
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 961525bbd..6d0022f7a 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -20,7 +20,14 @@ fn dogfood_clippy() {
}
// "" is the root package
- for package in &["", "clippy_dev", "clippy_lints", "clippy_utils", "rustc_tools_util"] {
+ for package in &[
+ "",
+ "clippy_dev",
+ "clippy_lints",
+ "clippy_utils",
+ "lintcheck",
+ "rustc_tools_util",
+ ] {
run_clippy_for_package(package, &["-D", "clippy::all", "-D", "clippy::pedantic"]);
}
}
diff --git a/src/tools/clippy/tests/integration.rs b/src/tools/clippy/tests/integration.rs
index 23a9bef3c..818ff70b3 100644
--- a/src/tools/clippy/tests/integration.rs
+++ b/src/tools/clippy/tests/integration.rs
@@ -6,10 +6,15 @@ use std::env;
use std::ffi::OsStr;
use std::process::Command;
+#[cfg(not(windows))]
+const CARGO_CLIPPY: &str = "cargo-clippy";
+#[cfg(windows)]
+const CARGO_CLIPPY: &str = "cargo-clippy.exe";
+
#[cfg_attr(feature = "integration", test)]
fn integration_test() {
let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
- let repo_url = format!("https://github.com/{}", repo_name);
+ let repo_url = format!("https://github.com/{repo_name}");
let crate_name = repo_name
.split('/')
.nth(1)
@@ -31,7 +36,7 @@ fn integration_test() {
let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let target_dir = std::path::Path::new(&root_dir).join("target");
- let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");
+ let clippy_binary = target_dir.join(env!("PROFILE")).join(CARGO_CLIPPY);
let output = Command::new(clippy_binary)
.current_dir(repo_dir)
@@ -51,17 +56,15 @@ fn integration_test() {
.expect("unable to run clippy");
let stderr = String::from_utf8_lossy(&output.stderr);
- if stderr.contains("internal compiler error") {
- let backtrace_start = stderr
- .find("thread 'rustc' panicked at")
- .expect("start of backtrace not found");
- let backtrace_end = stderr
- .rfind("error: internal compiler error")
+ if let Some(backtrace_start) = stderr.find("error: internal compiler error") {
+ static BACKTRACE_END_MSG: &str = "end of query stack";
+ let backtrace_end = stderr[backtrace_start..]
+ .find(BACKTRACE_END_MSG)
.expect("end of backtrace not found");
panic!(
"internal compiler error\nBacktrace:\n\n{}",
- &stderr[backtrace_start..backtrace_end]
+ &stderr[backtrace_start..backtrace_start + backtrace_end + BACKTRACE_END_MSG.len()]
);
} else if stderr.contains("query stack during panic") {
panic!("query stack during panic in the output");
@@ -83,7 +86,7 @@ fn integration_test() {
match output.status.code() {
Some(0) => println!("Compilation successful"),
- Some(code) => eprintln!("Compilation failed. Exit code: {}", code),
+ Some(code) => eprintln!("Compilation failed. Exit code: {code}"),
None => panic!("Process terminated by signal"),
}
}
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 2e0f4e760..abd0d1bc5 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -102,7 +102,7 @@ fn lint_message_convention() {
"error: the test '{}' contained the following nonconforming lines :",
message.path.display()
);
- message.bad_lines.iter().for_each(|line| eprintln!("{}", line));
+ message.bad_lines.iter().for_each(|line| eprintln!("{line}"));
eprintln!("\n\n");
}
diff --git a/src/tools/clippy/tests/missing-test-files.rs b/src/tools/clippy/tests/missing-test-files.rs
index 7d6edc2b1..caedd5d76 100644
--- a/src/tools/clippy/tests/missing-test-files.rs
+++ b/src/tools/clippy/tests/missing-test-files.rs
@@ -17,7 +17,7 @@ fn test_missing_tests() {
"Didn't see a test file for the following files:\n\n{}\n",
missing_files
.iter()
- .map(|s| format!("\t{}", s))
+ .map(|s| format!("\t{s}"))
.collect::<Vec<_>>()
.join("\n")
);
diff --git a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr
index b450a2b18..3b80d89a6 100644
--- a/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/duplicate_mod/fail/src/main.stderr
@@ -7,8 +7,8 @@ LL | / #[path = "b.rs"]
LL | | mod b2;
| |_______^ loaded again here
|
- = note: `-D clippy::duplicate-mod` implied by `-D warnings`
= help: replace all but one `mod` item with `use` items
+ = note: `-D clippy::duplicate-mod` implied by `-D warnings`
error: file is loaded as a module multiple times: `$DIR/c.rs`
--> $DIR/main.rs:9:1
diff --git a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
index b9e6cb49b..c6a11fa93 100644
--- a/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/feature_name/fail/src/main.stderr
@@ -1,7 +1,7 @@
error: the "no-" prefix in the feature name "no-qaq" is negative
|
- = note: `-D clippy::negative-feature-names` implied by `-D warnings`
= help: consider renaming the feature to "qaq", but make sure the feature adds functionality
+ = note: `-D clippy::negative-feature-names` implied by `-D warnings`
error: the "no_" prefix in the feature name "no_qaq" is negative
|
@@ -17,8 +17,8 @@ error: the "not_" prefix in the feature name "not_orz" is negative
error: the "-support" suffix in the feature name "qvq-support" is redundant
|
- = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
= help: consider renaming the feature to "qvq"
+ = note: `-D clippy::redundant-feature-names` implied by `-D warnings`
error: the "_support" suffix in the feature name "qvq_support" is redundant
|
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
index e2010e998..697c8b57c 100644
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod/src/main.stderr
@@ -4,8 +4,8 @@ error: `mod.rs` files are required, found `bad/inner.rs`
LL | pub mod stuff;
| ^
|
- = note: `-D clippy::self-named-module-files` implied by `-D warnings`
= help: move `bad/inner.rs` to `bad/inner/mod.rs`
+ = note: `-D clippy::self-named-module-files` implied by `-D warnings`
error: `mod.rs` files are required, found `bad/inner/stuff.rs`
--> $DIR/bad/inner/stuff.rs:1:1
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml
new file mode 100644
index 000000000..a822fad38
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+name = "fail-mod-remap"
+version = "0.1.0"
+edition = "2018"
+publish = false
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs
new file mode 100644
index 000000000..509aad186
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad.rs
@@ -0,0 +1 @@
+pub mod inner;
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad/inner.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad/inner.rs
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/bad/inner.rs
@@ -0,0 +1 @@
+
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
new file mode 100644
index 000000000..ba4c8c873
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.rs
@@ -0,0 +1,7 @@
+// compile-flags: --remap-path-prefix {{src-base}}=/remapped
+
+#![warn(clippy::self_named_module_files)]
+
+mod bad;
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
new file mode 100644
index 000000000..ea6ea9806
--- /dev/null
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_mod_remap/src/main.stderr
@@ -0,0 +1,11 @@
+error: `mod.rs` files are required, found `bad.rs`
+ --> /remapped/module_style/fail_mod_remap/src/bad.rs:1:1
+ |
+LL | pub mod inner;
+ | ^
+ |
+ = help: move `bad.rs` to `bad/mod.rs`
+ = note: `-D clippy::self-named-module-files` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
index f91940209..f40ceea23 100644
--- a/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
+++ b/src/tools/clippy/tests/ui-cargo/module_style/fail_no_mod/src/main.stderr
@@ -4,8 +4,8 @@ error: `mod.rs` files are not allowed, found `bad/mod.rs`
LL | pub struct Thing;
| ^
|
- = note: `-D clippy::mod-module-files` implied by `-D warnings`
= help: move `bad/mod.rs` to `bad.rs`
+ = note: `-D clippy::mod-module-files` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs b/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs
new file mode 100644
index 000000000..52fcaec4d
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/auxiliary/paths.rs
@@ -0,0 +1,2 @@
+pub static OPTION: [&str; 3] = ["core", "option", "Option"];
+pub const RESULT: &[&str] = &["core", "result", "Result"];
diff --git a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
index 2aa4de490..fd8c8379f 100644
--- a/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
+++ b/src/tools/clippy/tests/ui-internal/check_clippy_version_attribute.stderr
@@ -10,13 +10,13 @@ LL | | report_in_external_macro: true
LL | | }
| |_^
|
+ = help: please use a valid semantic version, see `doc/adding_lints.md`
note: the lint level is defined here
--> $DIR/check_clippy_version_attribute.rs:1:9
|
LL | #![deny(clippy::internal)]
| ^^^^^^^^^^^^^^^^
= note: `#[deny(clippy::invalid_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
- = help: please use a valid semantic version, see `doc/adding_lints.md`
= note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this item has an invalid `clippy::version` attribute
@@ -46,8 +46,8 @@ LL | | report_in_external_macro: true
LL | | }
| |_^
|
- = note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
= help: please use a `clippy::version` attribute, see `doc/adding_lints.md`
+ = note: `#[deny(clippy::missing_clippy_version_attribute)]` implied by `#[deny(clippy::internal)]`
= note: this error originates in the macro `$crate::declare_tool_lint` which comes from the expansion of the macro `declare_tool_lint` (in Nightly builds, run with -Z macro-backtrace for more info)
error: this lint is missing the `clippy::version` attribute or version value
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 a1b8e2ee1..07c594101 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 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs
+thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints/produce_ice.rs:28:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: internal compiler error: unexpected panic
diff --git a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
index 24106510e..d8f1ffb21 100644
--- a/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
+++ b/src/tools/clippy/tests/ui-internal/if_chain_style.stderr
@@ -10,12 +10,12 @@ LL | | }
LL | | }
| |_____^
|
- = note: `-D clippy::if-chain-style` implied by `-D warnings`
help: this `let` statement can also be in the `if_chain!`
--> $DIR/if_chain_style.rs:10:9
|
LL | let x = "";
| ^^^^^^^^^^^
+ = note: `-D clippy::if-chain-style` implied by `-D warnings`
error: `if a && b;` should be `if a; if b;`
--> $DIR/if_chain_style.rs:19:12
diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.rs b/src/tools/clippy/tests/ui-internal/invalid_paths.rs
index b823ff7fe..9a9790a4b 100644
--- a/src/tools/clippy/tests/ui-internal/invalid_paths.rs
+++ b/src/tools/clippy/tests/ui-internal/invalid_paths.rs
@@ -1,5 +1,5 @@
#![warn(clippy::internal)]
-#![allow(clippy::missing_clippy_version_attribute)]
+#![allow(clippy::missing_clippy_version_attribute, clippy::unnecessary_def_path)]
mod paths {
// Good path
diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs
deleted file mode 100644
index 4b41ff15e..000000000
--- a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs
+++ /dev/null
@@ -1,39 +0,0 @@
-#![deny(clippy::internal)]
-#![allow(clippy::missing_clippy_version_attribute)]
-#![feature(rustc_private)]
-
-extern crate clippy_utils;
-extern crate rustc_hir;
-extern crate rustc_lint;
-extern crate rustc_middle;
-
-#[macro_use]
-extern crate rustc_session;
-use clippy_utils::{paths, ty::match_type};
-use rustc_hir::Expr;
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
-
-declare_lint! {
- pub TEST_LINT,
- Warn,
- ""
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-static OPTION: [&str; 3] = ["core", "option", "Option"];
-
-impl<'tcx> LateLintPass<'tcx> for Pass {
- fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) {
- let ty = cx.typeck_results().expr_ty(expr);
-
- let _ = match_type(cx, ty, &OPTION);
- let _ = match_type(cx, ty, &["core", "result", "Result"]);
-
- let rc_path = &["alloc", "rc", "Rc"];
- let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
- }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr
deleted file mode 100644
index e3cb6b6c2..000000000
--- a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr
+++ /dev/null
@@ -1,27 +0,0 @@
-error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item
- --> $DIR/match_type_on_diag_item.rs:31:17
- |
-LL | let _ = match_type(cx, ty, &OPTION);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::Option)`
- |
-note: the lint level is defined here
- --> $DIR/match_type_on_diag_item.rs:1:9
- |
-LL | #![deny(clippy::internal)]
- | ^^^^^^^^^^^^^^^^
- = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]`
-
-error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item
- --> $DIR/match_type_on_diag_item.rs:32:17
- |
-LL | let _ = match_type(cx, ty, &["core", "result", "Result"]);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::Result)`
-
-error: usage of `clippy_utils::ty::match_type()` on a type diagnostic item
- --> $DIR/match_type_on_diag_item.rs:35:17
- |
-LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `clippy_utils::ty::is_type_diagnostic_item(cx, ty, sym::Rc)`
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
new file mode 100644
index 000000000..cbbb46523
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.fixed
@@ -0,0 +1,62 @@
+// run-rustfix
+// aux-build:paths.rs
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate clippy_utils;
+extern crate paths;
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_middle;
+extern crate rustc_span;
+
+#[allow(unused)]
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
+#[allow(unused)]
+use clippy_utils::{
+ is_expr_path_def_path, is_path_diagnostic_item, is_res_diagnostic_ctor, is_res_lang_ctor, is_trait_method,
+ match_def_path, match_trait_method, path_res,
+};
+
+#[allow(unused)]
+use rustc_hir::LangItem;
+#[allow(unused)]
+use rustc_span::sym;
+
+use rustc_hir::def_id::DefId;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+
+#[allow(unused, clippy::unnecessary_def_path)]
+static OPTION: [&str; 3] = ["core", "option", "Option"];
+#[allow(unused, clippy::unnecessary_def_path)]
+const RESULT: &[&str] = &["core", "result", "Result"];
+
+fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) {
+ let _ = is_type_diagnostic_item(cx, ty, sym::Option);
+ let _ = is_type_diagnostic_item(cx, ty, sym::Result);
+ let _ = is_type_diagnostic_item(cx, ty, sym::Result);
+
+ #[allow(unused, clippy::unnecessary_def_path)]
+ let rc_path = &["alloc", "rc", "Rc"];
+ let _ = is_type_diagnostic_item(cx, ty, sym::Rc);
+
+ let _ = is_type_diagnostic_item(cx, ty, sym::Option);
+ let _ = is_type_diagnostic_item(cx, ty, sym::Result);
+
+ let _ = is_type_lang_item(cx, ty, LangItem::OwnedBox);
+ let _ = is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit);
+
+ let _ = cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did);
+ let _ = cx.tcx.is_diagnostic_item(sym::Option, did);
+ let _ = cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did);
+
+ let _ = is_trait_method(cx, expr, sym::AsRef);
+
+ let _ = is_path_diagnostic_item(cx, expr, sym::Option);
+ let _ = path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id));
+ let _ = is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome);
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
new file mode 100644
index 000000000..f17fed6c6
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.rs
@@ -0,0 +1,62 @@
+// run-rustfix
+// aux-build:paths.rs
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate clippy_utils;
+extern crate paths;
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_middle;
+extern crate rustc_span;
+
+#[allow(unused)]
+use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item, match_type};
+#[allow(unused)]
+use clippy_utils::{
+ is_expr_path_def_path, is_path_diagnostic_item, is_res_diagnostic_ctor, is_res_lang_ctor, is_trait_method,
+ match_def_path, match_trait_method, path_res,
+};
+
+#[allow(unused)]
+use rustc_hir::LangItem;
+#[allow(unused)]
+use rustc_span::sym;
+
+use rustc_hir::def_id::DefId;
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::ty::Ty;
+
+#[allow(unused, clippy::unnecessary_def_path)]
+static OPTION: [&str; 3] = ["core", "option", "Option"];
+#[allow(unused, clippy::unnecessary_def_path)]
+const RESULT: &[&str] = &["core", "result", "Result"];
+
+fn _f<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, did: DefId, expr: &Expr<'_>) {
+ let _ = match_type(cx, ty, &OPTION);
+ let _ = match_type(cx, ty, RESULT);
+ let _ = match_type(cx, ty, &["core", "result", "Result"]);
+
+ #[allow(unused, clippy::unnecessary_def_path)]
+ let rc_path = &["alloc", "rc", "Rc"];
+ let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
+
+ let _ = match_type(cx, ty, &paths::OPTION);
+ let _ = match_type(cx, ty, paths::RESULT);
+
+ let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]);
+ let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]);
+
+ let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
+ let _ = match_def_path(cx, did, &["core", "option", "Option"]);
+ let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
+
+ let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]);
+
+ let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]);
+ let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
+ let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]);
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
new file mode 100644
index 000000000..a99a8f71f
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path.stderr
@@ -0,0 +1,101 @@
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:37:13
+ |
+LL | let _ = match_type(cx, ty, &OPTION);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
+ |
+note: the lint level is defined here
+ --> $DIR/unnecessary_def_path.rs:3:9
+ |
+LL | #![deny(clippy::internal)]
+ | ^^^^^^^^^^^^^^^^
+ = note: `#[deny(clippy::unnecessary_def_path)]` implied by `#[deny(clippy::internal)]`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:38:13
+ |
+LL | let _ = match_type(cx, ty, RESULT);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:39:13
+ |
+LL | let _ = match_type(cx, ty, &["core", "result", "Result"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:43:13
+ |
+LL | let _ = clippy_utils::ty::match_type(cx, ty, rc_path);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Rc)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:45:13
+ |
+LL | let _ = match_type(cx, ty, &paths::OPTION);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Option)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:46:13
+ |
+LL | let _ = match_type(cx, ty, paths::RESULT);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::Result)`
+
+error: use of a def path to a `LangItem`
+ --> $DIR/unnecessary_def_path.rs:48:13
+ |
+LL | let _ = match_type(cx, ty, &["alloc", "boxed", "Box"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_lang_item(cx, ty, LangItem::OwnedBox)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:49:13
+ |
+LL | let _ = match_type(cx, ty, &["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_type_diagnostic_item(cx, ty, sym::maybe_uninit_uninit)`
+
+error: use of a def path to a `LangItem`
+ --> $DIR/unnecessary_def_path.rs:51:13
+ |
+LL | let _ = match_def_path(cx, did, &["alloc", "boxed", "Box"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OwnedBox).ok() == Some(did)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:52:13
+ |
+LL | let _ = match_def_path(cx, did, &["core", "option", "Option"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.is_diagnostic_item(sym::Option, did)`
+
+error: use of a def path to a `LangItem`
+ --> $DIR/unnecessary_def_path.rs:53:13
+ |
+LL | let _ = match_def_path(cx, did, &["core", "option", "Option", "Some"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cx.tcx.lang_items().require(LangItem::OptionSome).ok() == Some(did)`
+ |
+ = help: if this `DefId` came from a constructor expression or pattern then the parent `DefId` should be used instead
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:55:13
+ |
+LL | let _ = match_trait_method(cx, expr, &["core", "convert", "AsRef"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_trait_method(cx, expr, sym::AsRef)`
+
+error: use of a def path to a diagnostic item
+ --> $DIR/unnecessary_def_path.rs:57:13
+ |
+LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_path_diagnostic_item(cx, expr, sym::Option)`
+
+error: use of a def path to a `LangItem`
+ --> $DIR/unnecessary_def_path.rs:58:13
+ |
+LL | let _ = is_expr_path_def_path(cx, expr, &["core", "iter", "traits", "Iterator", "next"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `path_res(cx, expr).opt_def_id().map_or(false, |id| cx.tcx.lang_items().require(LangItem::IteratorNext).ok() == Some(id))`
+
+error: use of a def path to a `LangItem`
+ --> $DIR/unnecessary_def_path.rs:59:13
+ |
+LL | let _ = is_expr_path_def_path(cx, expr, &["core", "option", "Option", "Some"]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `is_res_lang_ctor(cx, path_res(cx, expr), LangItem::OptionSome)`
+
+error: aborting due to 15 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
new file mode 100644
index 000000000..b5ff3a542
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.rs
@@ -0,0 +1,16 @@
+#![feature(rustc_private)]
+#![allow(unused)]
+#![warn(clippy::unnecessary_def_path)]
+
+extern crate rustc_hir;
+
+use rustc_hir::LangItem;
+
+fn main() {
+ const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
+ const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
+ const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+
+ // Don't lint, not yet a diagnostic or language item
+ const DEREF_MUT_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "DerefMut", "deref_mut"];
+}
diff --git a/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
new file mode 100644
index 000000000..af46d87bf
--- /dev/null
+++ b/src/tools/clippy/tests/ui-internal/unnecessary_def_path_hardcoded_path.stderr
@@ -0,0 +1,27 @@
+error: hardcoded path to a language item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:11:40
+ |
+LL | const DEREF_MUT_TRAIT: [&str; 4] = ["core", "ops", "deref", "DerefMut"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `LangItem::DerefMut`
+ = note: `-D clippy::unnecessary-def-path` implied by `-D warnings`
+
+error: hardcoded path to a diagnostic item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:12:43
+ |
+LL | const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `sym::deref_method`
+
+error: hardcoded path to a diagnostic item
+ --> $DIR/unnecessary_def_path_hardcoded_path.rs:10:36
+ |
+LL | const DEREF_TRAIT: [&str; 4] = ["core", "ops", "deref", "Deref"];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: convert all references to use `sym::Deref`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
index 62c45b546..4c7599843 100644
--- a/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
+++ b/src/tools/clippy/tests/ui-toml/await_holding_invalid_type/await_holding_invalid_type.stderr
@@ -4,8 +4,8 @@ error: `std::string::String` may not be held across an `await` point per `clippy
LL | let _x = String::from("hello");
| ^^
|
- = note: `-D clippy::await-holding-invalid-type` implied by `-D warnings`
= note: strings are bad
+ = note: `-D clippy::await-holding-invalid-type` implied by `-D warnings`
error: `std::net::Ipv4Addr` may not be held across an `await` point per `clippy.toml`
--> $DIR/await_holding_invalid_type.rs:10:9
diff --git a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
index b4e677ea1..7f1c512d7 100644
--- a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
+++ b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
fn main() {}
#[warn(clippy::cognitive_complexity)]
diff --git a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
index 4c560299e..630bad07c 100644
--- a/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
+++ b/src/tools/clippy/tests/ui-toml/conf_deprecated_key/conf_deprecated_key.stderr
@@ -3,13 +3,13 @@ warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecate
warning: error reading Clippy's configuration file `$DIR/clippy.toml`: deprecated field `blacklisted-names`. Please use `disallowed-names` instead
error: the function has a cognitive complexity of (3/2)
- --> $DIR/conf_deprecated_key.rs:4:4
+ --> $DIR/conf_deprecated_key.rs:6:4
|
LL | fn cognitive_complexity() {
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
= help: you could split it up into multiple smaller functions
+ = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
error: aborting due to previous error; 2 warnings emitted
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/auxiliary/macros.rs b/src/tools/clippy/tests/ui-toml/disallowed_macros/auxiliary/macros.rs
new file mode 100644
index 000000000..fcaeace0e
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/auxiliary/macros.rs
@@ -0,0 +1,32 @@
+#[macro_export]
+macro_rules! expr {
+ () => {
+ 1
+ };
+}
+
+#[macro_export]
+macro_rules! stmt {
+ () => {
+ let _x = ();
+ };
+}
+
+#[macro_export]
+macro_rules! ty {
+ () => { &'static str };
+}
+
+#[macro_export]
+macro_rules! pat {
+ () => {
+ _
+ };
+}
+
+#[macro_export]
+macro_rules! item {
+ () => {
+ const ITEM: usize = 1;
+ };
+}
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/clippy.toml b/src/tools/clippy/tests/ui-toml/disallowed_macros/clippy.toml
new file mode 100644
index 000000000..c8fe8be9a
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/clippy.toml
@@ -0,0 +1,11 @@
+disallowed-macros = [
+ "std::println",
+ "std::vec",
+ { path = "std::cfg" },
+ { path = "serde::Serialize", reason = "no serializing" },
+ "macros::expr",
+ "macros::stmt",
+ "macros::ty",
+ "macros::pat",
+ "macros::item",
+]
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs
new file mode 100644
index 000000000..2bb537607
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.rs
@@ -0,0 +1,39 @@
+// aux-build:macros.rs
+
+#![allow(unused)]
+
+extern crate macros;
+
+use serde::Serialize;
+
+fn main() {
+ println!("one");
+ println!("two");
+ cfg!(unix);
+ vec![1, 2, 3];
+
+ #[derive(Serialize)]
+ struct Derive;
+
+ let _ = macros::expr!();
+ macros::stmt!();
+ let macros::pat!() = 1;
+ let _: macros::ty!() = "";
+ macros::item!();
+
+ eprintln!("allowed");
+}
+
+struct S;
+
+impl S {
+ macros::item!();
+}
+
+trait Y {
+ macros::item!();
+}
+
+impl Y for S {
+ macros::item!();
+}
diff --git a/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
new file mode 100644
index 000000000..aed9feb6f
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/disallowed_macros/disallowed_macros.stderr
@@ -0,0 +1,84 @@
+error: use of a disallowed macro `std::println`
+ --> $DIR/disallowed_macros.rs:10:5
+ |
+LL | println!("one");
+ | ^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::disallowed-macros` implied by `-D warnings`
+
+error: use of a disallowed macro `std::println`
+ --> $DIR/disallowed_macros.rs:11:5
+ |
+LL | println!("two");
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `std::cfg`
+ --> $DIR/disallowed_macros.rs:12:5
+ |
+LL | cfg!(unix);
+ | ^^^^^^^^^^
+
+error: use of a disallowed macro `std::vec`
+ --> $DIR/disallowed_macros.rs:13:5
+ |
+LL | vec![1, 2, 3];
+ | ^^^^^^^^^^^^^
+
+error: use of a disallowed macro `serde::Serialize`
+ --> $DIR/disallowed_macros.rs:15:14
+ |
+LL | #[derive(Serialize)]
+ | ^^^^^^^^^
+ |
+ = note: no serializing (from clippy.toml)
+
+error: use of a disallowed macro `macros::expr`
+ --> $DIR/disallowed_macros.rs:18:13
+ |
+LL | let _ = macros::expr!();
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::stmt`
+ --> $DIR/disallowed_macros.rs:19:5
+ |
+LL | macros::stmt!();
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::pat`
+ --> $DIR/disallowed_macros.rs:20:9
+ |
+LL | let macros::pat!() = 1;
+ | ^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::ty`
+ --> $DIR/disallowed_macros.rs:21:12
+ |
+LL | let _: macros::ty!() = "";
+ | ^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::item`
+ --> $DIR/disallowed_macros.rs:22:5
+ |
+LL | macros::item!();
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::item`
+ --> $DIR/disallowed_macros.rs:30:5
+ |
+LL | macros::item!();
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::item`
+ --> $DIR/disallowed_macros.rs:34:5
+ |
+LL | macros::item!();
+ | ^^^^^^^^^^^^^^^
+
+error: use of a disallowed macro `macros::item`
+ --> $DIR/disallowed_macros.rs:38:5
+ |
+LL | macros::item!();
+ | ^^^^^^^^^^^^^^^
+
+error: aborting due to 13 previous errors
+
diff --git a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
index c5d95cb8a..28a08599c 100644
--- a/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
+++ b/src/tools/clippy/tests/ui-toml/expect_used/expect_used.stderr
@@ -4,8 +4,8 @@ error: used `expect()` on `an Option` value
LL | let _ = opt.expect("");
| ^^^^^^^^^^^^^^
|
- = note: `-D clippy::expect-used` implied by `-D warnings`
= help: if this value is `None`, it will panic
+ = note: `-D clippy::expect-used` implied by `-D warnings`
error: used `expect()` on `a Result` value
--> $DIR/expect_used.rs:11:13
diff --git a/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr b/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr
index d05adc3d3..87bdb61c6 100644
--- a/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/fn_params_excessive_bools/test.stderr
@@ -4,8 +4,8 @@ error: more than 1 bools in function parameters
LL | fn g(_: bool, _: bool) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
= help: consider refactoring bools into two-variant enums
+ = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr
index 6a685a583..7b5fb9e87 100644
--- a/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr
+++ b/src/tools/clippy/tests/ui-toml/large_include_file/large_include_file.stderr
@@ -4,8 +4,8 @@ error: attempted to include a large file
LL | const TOO_BIG_INCLUDE_BYTES: &[u8; 654] = include_bytes!("too_big.txt");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::large-include-file` implied by `-D warnings`
= note: the configuration allows a maximum size of 600 bytes
+ = note: `-D clippy::large-include-file` implied by `-D warnings`
= note: this error originates in the macro `include_bytes` (in Nightly builds, run with -Z macro-backtrace for more info)
error: attempted to include a large file
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
new file mode 100644
index 000000000..01d135764
--- /dev/null
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.fixed
@@ -0,0 +1,62 @@
+// aux-build:proc_macro_derive.rs
+// run-rustfix
+
+#![warn(clippy::nonstandard_macro_braces)]
+
+extern crate proc_macro_derive;
+extern crate quote;
+
+use quote::quote;
+
+#[derive(proc_macro_derive::DeriveSomething)]
+pub struct S;
+
+proc_macro_derive::foo_bar!();
+
+#[rustfmt::skip]
+macro_rules! test {
+ () => {
+ vec![0, 0, 0]
+ };
+}
+
+#[rustfmt::skip]
+macro_rules! test2 {
+ ($($arg:tt)*) => {
+ format_args!($($arg)*)
+ };
+}
+
+macro_rules! type_pos {
+ ($what:ty) => {
+ Vec<$what>
+ };
+}
+
+macro_rules! printlnfoo {
+ ($thing:expr) => {
+ println!("{}", $thing)
+ };
+}
+
+#[rustfmt::skip]
+fn main() {
+ let _ = vec![1, 2, 3];
+ let _ = format!("ugh {} stop being such a good compiler", "hello");
+ let _ = matches!({}, ());
+ let _ = quote!{let x = 1;};
+ let _ = quote::quote!{match match match};
+ let _ = test!(); // trigger when macro def is inside our own crate
+ let _ = vec![1,2,3];
+
+ let _ = quote::quote! {true || false};
+ let _ = vec! [0 ,0 ,0];
+ let _ = format!("fds{}fds", 10);
+ let _ = test2!["{}{}{}", 1, 2, 3];
+
+ let _: type_pos![usize] = vec![];
+
+ eprint!["test if user config overrides defaults"];
+
+ printlnfoo!["test if printlnfoo is triggered by println"];
+}
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
index 5b4adc868..72883e827 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.rs
@@ -1,4 +1,5 @@
// aux-build:proc_macro_derive.rs
+// run-rustfix
#![warn(clippy::nonstandard_macro_braces)]
@@ -42,6 +43,7 @@ macro_rules! printlnfoo {
fn main() {
let _ = vec! {1, 2, 3};
let _ = format!["ugh {} stop being such a good compiler", "hello"];
+ let _ = matches!{{}, ()};
let _ = quote!(let x = 1;);
let _ = quote::quote!(match match match);
let _ = test!(); // trigger when macro def is inside our own crate
diff --git a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr
index 039b23b1b..7ae381597 100644
--- a/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr
+++ b/src/tools/clippy/tests/ui-toml/nonstandard_macro_braces/conf_nonstandard_macro_braces.stderr
@@ -1,94 +1,57 @@
error: use of irregular braces for `vec!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:43:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:44:13
|
LL | let _ = vec! {1, 2, 3};
- | ^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^ help: consider writing: `vec![1, 2, 3]`
|
= note: `-D clippy::nonstandard-macro-braces` implied by `-D warnings`
-help: consider writing `vec![1, 2, 3]`
- --> $DIR/conf_nonstandard_macro_braces.rs:43:13
- |
-LL | let _ = vec! {1, 2, 3};
- | ^^^^^^^^^^^^^^
error: use of irregular braces for `format!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:44:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:45:13
|
LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: consider writing `format!("ugh () stop being such a good compiler", "hello")`
- --> $DIR/conf_nonstandard_macro_braces.rs:44:13
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `format!("ugh {} stop being such a good compiler", "hello")`
+
+error: use of irregular braces for `matches!` macro
+ --> $DIR/conf_nonstandard_macro_braces.rs:46:13
|
-LL | let _ = format!["ugh {} stop being such a good compiler", "hello"];
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | let _ = matches!{{}, ()};
+ | ^^^^^^^^^^^^^^^^ help: consider writing: `matches!({}, ())`
error: use of irregular braces for `quote!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:45:13
- |
-LL | let _ = quote!(let x = 1;);
- | ^^^^^^^^^^^^^^^^^^
- |
-help: consider writing `quote! {let x = 1;}`
- --> $DIR/conf_nonstandard_macro_braces.rs:45:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:47:13
|
LL | let _ = quote!(let x = 1;);
- | ^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^ help: consider writing: `quote!{let x = 1;}`
error: use of irregular braces for `quote::quote!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:46:13
+ --> $DIR/conf_nonstandard_macro_braces.rs:48:13
|
LL | let _ = quote::quote!(match match match);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: consider writing `quote::quote! {match match match}`
- --> $DIR/conf_nonstandard_macro_braces.rs:46:13
- |
-LL | let _ = quote::quote!(match match match);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `quote::quote!{match match match}`
error: use of irregular braces for `vec!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:18:9
+ --> $DIR/conf_nonstandard_macro_braces.rs:19:9
|
LL | vec!{0, 0, 0}
- | ^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^ help: consider writing: `vec![0, 0, 0]`
...
LL | let _ = test!(); // trigger when macro def is inside our own crate
| ------- in this macro invocation
|
-help: consider writing `vec![0, 0, 0]`
- --> $DIR/conf_nonstandard_macro_braces.rs:18:9
- |
-LL | vec!{0, 0, 0}
- | ^^^^^^^^^^^^^
-...
-LL | let _ = test!(); // trigger when macro def is inside our own crate
- | ------- in this macro invocation
= note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
error: use of irregular braces for `type_pos!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:55:12
- |
-LL | let _: type_pos!(usize) = vec![];
- | ^^^^^^^^^^^^^^^^
- |
-help: consider writing `type_pos![usize]`
- --> $DIR/conf_nonstandard_macro_braces.rs:55:12
+ --> $DIR/conf_nonstandard_macro_braces.rs:57:12
|
LL | let _: type_pos!(usize) = vec![];
- | ^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^ help: consider writing: `type_pos![usize]`
error: use of irregular braces for `eprint!` macro
- --> $DIR/conf_nonstandard_macro_braces.rs:57:5
- |
-LL | eprint!("test if user config overrides defaults");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: consider writing `eprint!["test if user config overrides defaults"]`
- --> $DIR/conf_nonstandard_macro_braces.rs:57:5
+ --> $DIR/conf_nonstandard_macro_braces.rs:59:5
|
LL | eprint!("test if user config overrides defaults");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `eprint!["test if user config overrides defaults"]`
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr b/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr
index 49eecf18b..c72f8c648 100644
--- a/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/strict_non_send_fields_in_send_ty/test.stderr
@@ -4,13 +4,13 @@ error: some fields in `NoGeneric` are not safe to be sent to another thread
LL | unsafe impl Send for NoGeneric {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings`
note: it is not safe to send field `rc_is_not_send` to another thread
--> $DIR/test.rs:8:5
|
LL | rc_is_not_send: Rc<String>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: use a thread-safe type that implements `Send`
+ = note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings`
error: some fields in `MultiField<T>` are not safe to be sent to another thread
--> $DIR/test.rs:19:1
diff --git a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr
index 65861d10d..4e7c70d18 100644
--- a/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr
+++ b/src/tools/clippy/tests/ui-toml/struct_excessive_bools/test.stderr
@@ -6,8 +6,8 @@ LL | | a: bool,
LL | | }
| |_^
|
- = note: `-D clippy::struct-excessive-bools` implied by `-D warnings`
= help: consider using a state machine or refactoring bools into two-variant enums
+ = note: `-D clippy::struct-excessive-bools` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
index c902d2112..28774db62 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/clippy.toml
@@ -3,6 +3,7 @@ disallowed-methods = [
"std::iter::Iterator::sum",
"f32::clamp",
"slice::sort_unstable",
+ "futures::stream::select_all",
# can give path and reason with an inline table
{ path = "regex::Regex::is_match", reason = "no matching allowed" },
# can use an inline table but omit reason
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
index 3397fa1ec..b483f1600 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.rs
@@ -1,6 +1,9 @@
#![warn(clippy::disallowed_methods)]
+extern crate futures;
extern crate regex;
+
+use futures::stream::{empty, select_all};
use regex::Regex;
fn main() {
@@ -20,4 +23,7 @@ fn main() {
let in_call = Box::new(f32::clamp);
let in_method_call = ["^", "$"].into_iter().map(Regex::new);
+
+ // resolve ambiguity between `futures::stream::select_all` the module and the function
+ let same_name_as_module = select_all(vec![empty::<()>()]);
}
diff --git a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
index 5cbb56754..6d78c32e1 100644
--- a/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
+++ b/src/tools/clippy/tests/ui-toml/toml_disallowed_methods/conf_disallowed_methods.stderr
@@ -1,5 +1,5 @@
error: use of a disallowed method `regex::Regex::new`
- --> $DIR/conf_disallowed_methods.rs:7:14
+ --> $DIR/conf_disallowed_methods.rs:10:14
|
LL | let re = Regex::new(r"ab.*c").unwrap();
| ^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | let re = Regex::new(r"ab.*c").unwrap();
= note: `-D clippy::disallowed-methods` implied by `-D warnings`
error: use of a disallowed method `regex::Regex::is_match`
- --> $DIR/conf_disallowed_methods.rs:8:5
+ --> $DIR/conf_disallowed_methods.rs:11:5
|
LL | re.is_match("abc");
| ^^^^^^^^^^^^^^^^^^
@@ -15,40 +15,46 @@ LL | re.is_match("abc");
= note: no matching allowed (from clippy.toml)
error: use of a disallowed method `std::iter::Iterator::sum`
- --> $DIR/conf_disallowed_methods.rs:11:5
+ --> $DIR/conf_disallowed_methods.rs:14:5
|
LL | a.iter().sum::<i32>();
| ^^^^^^^^^^^^^^^^^^^^^
error: use of a disallowed method `slice::sort_unstable`
- --> $DIR/conf_disallowed_methods.rs:13:5
+ --> $DIR/conf_disallowed_methods.rs:16:5
|
LL | a.sort_unstable();
| ^^^^^^^^^^^^^^^^^
error: use of a disallowed method `f32::clamp`
- --> $DIR/conf_disallowed_methods.rs:15:13
+ --> $DIR/conf_disallowed_methods.rs:18:13
|
LL | let _ = 2.0f32.clamp(3.0f32, 4.0f32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: use of a disallowed method `regex::Regex::new`
- --> $DIR/conf_disallowed_methods.rs:18:61
+ --> $DIR/conf_disallowed_methods.rs:21:61
|
LL | let indirect: fn(&str) -> Result<Regex, regex::Error> = Regex::new;
| ^^^^^^^^^^
error: use of a disallowed method `f32::clamp`
- --> $DIR/conf_disallowed_methods.rs:21:28
+ --> $DIR/conf_disallowed_methods.rs:24:28
|
LL | let in_call = Box::new(f32::clamp);
| ^^^^^^^^^^
error: use of a disallowed method `regex::Regex::new`
- --> $DIR/conf_disallowed_methods.rs:22:53
+ --> $DIR/conf_disallowed_methods.rs:25:53
|
LL | let in_method_call = ["^", "$"].into_iter().map(Regex::new);
| ^^^^^^^^^^
-error: aborting due to 8 previous errors
+error: use of a disallowed method `futures::stream::select_all`
+ --> $DIR/conf_disallowed_methods.rs:28:31
+ |
+LL | let same_name_as_module = select_all(vec![empty::<()>()]);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 9 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 f27f78d15..82ee80541 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
@@ -11,6 +11,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
cargo-ignore-publish
cognitive-complexity-threshold
cyclomatic-complexity-threshold
+ disallowed-macros
disallowed-methods
disallowed-names
disallowed-types
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 6bcfa0a8b..681b5eaf5 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
@@ -16,8 +16,8 @@ error: used `unwrap()` on `an Option` value
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+ = note: `-D clippy::unwrap-used` implied by `-D warnings`
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/unwrap_used.rs:36:17
diff --git a/src/tools/clippy/tests/ui/absurd-extreme-comparisons.stderr b/src/tools/clippy/tests/ui/absurd-extreme-comparisons.stderr
index 6de554378..21cb11fa1 100644
--- a/src/tools/clippy/tests/ui/absurd-extreme-comparisons.stderr
+++ b/src/tools/clippy/tests/ui/absurd-extreme-comparisons.stderr
@@ -4,8 +4,8 @@ error: this comparison involving the minimum or maximum element for this type co
LL | u <= 0;
| ^^^^^^
|
- = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings`
= help: because `0` is the minimum value for this type, the case where the two sides are not equal never occurs, consider using `u == 0` instead
+ = note: `-D clippy::absurd-extreme-comparisons` implied by `-D warnings`
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
--> $DIR/absurd-extreme-comparisons.rs:15:5
diff --git a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
index cd040a144..23f17e9a7 100644
--- a/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
+++ b/src/tools/clippy/tests/ui/allow_attributes_without_reason.stderr
@@ -4,12 +4,12 @@ error: `allow` attribute without specifying a reason
LL | #[allow(dead_code)]
| ^^^^^^^^^^^^^^^^^^^
|
+ = help: try adding a reason at the end with `, reason = ".."`
note: the lint level is defined here
--> $DIR/allow_attributes_without_reason.rs:2:9
|
LL | #![deny(clippy::allow_attributes_without_reason)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: try adding a reason at the end with `, reason = ".."`
error: `allow` attribute without specifying a reason
--> $DIR/allow_attributes_without_reason.rs:6:1
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed b/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed
index e69b40f35..079b7c000 100644
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed
+++ b/src/tools/clippy/tests/ui/almost_complete_letter_range.fixed
@@ -1,5 +1,6 @@
// run-rustfix
// edition:2018
+// aux-build:macro_rules.rs
#![feature(custom_inner_attributes)]
#![feature(exclusive_range_pattern)]
@@ -8,12 +9,21 @@
#![allow(ellipsis_inclusive_range_patterns)]
#![allow(clippy::needless_parens_on_range_literals)]
+#[macro_use]
+extern crate macro_rules;
+
macro_rules! a {
() => {
'a'
};
}
+macro_rules! b {
+ () => {
+ let _ = 'a'..='z';
+ };
+}
+
fn main() {
#[rustfmt::skip]
{
@@ -47,6 +57,9 @@ fn main() {
'B'..'Z' => 4,
_ => 5,
};
+
+ almost_complete_letter_range!();
+ b!();
}
fn _under_msrv() {
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.rs b/src/tools/clippy/tests/ui/almost_complete_letter_range.rs
index f2240981d..a66900a97 100644
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.rs
+++ b/src/tools/clippy/tests/ui/almost_complete_letter_range.rs
@@ -1,5 +1,6 @@
// run-rustfix
// edition:2018
+// aux-build:macro_rules.rs
#![feature(custom_inner_attributes)]
#![feature(exclusive_range_pattern)]
@@ -8,12 +9,21 @@
#![allow(ellipsis_inclusive_range_patterns)]
#![allow(clippy::needless_parens_on_range_literals)]
+#[macro_use]
+extern crate macro_rules;
+
macro_rules! a {
() => {
'a'
};
}
+macro_rules! b {
+ () => {
+ let _ = 'a'..'z';
+ };
+}
+
fn main() {
#[rustfmt::skip]
{
@@ -47,6 +57,9 @@ fn main() {
'B'..'Z' => 4,
_ => 5,
};
+
+ almost_complete_letter_range!();
+ b!();
}
fn _under_msrv() {
diff --git a/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr b/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
index 5b5dc40ee..3de44c72c 100644
--- a/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
+++ b/src/tools/clippy/tests/ui/almost_complete_letter_range.stderr
@@ -1,5 +1,5 @@
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:20:17
+ --> $DIR/almost_complete_letter_range.rs:30:17
|
LL | let _ = ('a') ..'z';
| ^^^^^^--^^^
@@ -9,7 +9,7 @@ LL | let _ = ('a') ..'z';
= note: `-D clippy::almost-complete-letter-range` implied by `-D warnings`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:21:17
+ --> $DIR/almost_complete_letter_range.rs:31:17
|
LL | let _ = 'A' .. ('Z');
| ^^^^--^^^^^^
@@ -17,7 +17,7 @@ LL | let _ = 'A' .. ('Z');
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:27:13
+ --> $DIR/almost_complete_letter_range.rs:37:13
|
LL | let _ = (b'a')..(b'z');
| ^^^^^^--^^^^^^
@@ -25,7 +25,7 @@ LL | let _ = (b'a')..(b'z');
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:28:13
+ --> $DIR/almost_complete_letter_range.rs:38:13
|
LL | let _ = b'A'..b'Z';
| ^^^^--^^^^
@@ -33,7 +33,7 @@ LL | let _ = b'A'..b'Z';
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:33:13
+ --> $DIR/almost_complete_letter_range.rs:43:13
|
LL | let _ = a!()..'z';
| ^^^^--^^^
@@ -41,7 +41,7 @@ LL | let _ = a!()..'z';
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:36:9
+ --> $DIR/almost_complete_letter_range.rs:46:9
|
LL | b'a'..b'z' if true => 1,
| ^^^^--^^^^
@@ -49,7 +49,7 @@ LL | b'a'..b'z' if true => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:37:9
+ --> $DIR/almost_complete_letter_range.rs:47:9
|
LL | b'A'..b'Z' if true => 2,
| ^^^^--^^^^
@@ -57,7 +57,7 @@ LL | b'A'..b'Z' if true => 2,
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:44:9
+ --> $DIR/almost_complete_letter_range.rs:54:9
|
LL | 'a'..'z' if true => 1,
| ^^^--^^^
@@ -65,7 +65,7 @@ LL | 'a'..'z' if true => 1,
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:45:9
+ --> $DIR/almost_complete_letter_range.rs:55:9
|
LL | 'A'..'Z' if true => 2,
| ^^^--^^^
@@ -73,7 +73,20 @@ LL | 'A'..'Z' if true => 2,
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:55:9
+ --> $DIR/almost_complete_letter_range.rs:23:17
+ |
+LL | let _ = 'a'..'z';
+ | ^^^--^^^
+ | |
+ | help: use an inclusive range: `..=`
+...
+LL | b!();
+ | ---- in this macro invocation
+ |
+ = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: almost complete ascii letter range
+ --> $DIR/almost_complete_letter_range.rs:68:9
|
LL | 'a'..'z' => 1,
| ^^^--^^^
@@ -81,7 +94,7 @@ LL | 'a'..'z' => 1,
| help: use an inclusive range: `...`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:62:13
+ --> $DIR/almost_complete_letter_range.rs:75:13
|
LL | let _ = 'a'..'z';
| ^^^--^^^
@@ -89,12 +102,12 @@ LL | let _ = 'a'..'z';
| help: use an inclusive range: `..=`
error: almost complete ascii letter range
- --> $DIR/almost_complete_letter_range.rs:64:9
+ --> $DIR/almost_complete_letter_range.rs:77:9
|
LL | 'a'..'z' => 1,
| ^^^--^^^
| |
| help: use an inclusive range: `..=`
-error: aborting due to 12 previous errors
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/approx_const.stderr b/src/tools/clippy/tests/ui/approx_const.stderr
index 4da1b8215..0932a2eec 100644
--- a/src/tools/clippy/tests/ui/approx_const.stderr
+++ b/src/tools/clippy/tests/ui/approx_const.stderr
@@ -4,8 +4,8 @@ error: approximate value of `f{32, 64}::consts::E` found
LL | let my_e = 2.7182;
| ^^^^^^
|
- = note: `-D clippy::approx-constant` implied by `-D warnings`
= help: consider using the constant directly
+ = note: `-D clippy::approx-constant` implied by `-D warnings`
error: approximate value of `f{32, 64}::consts::E` found
--> $DIR/approx_const.rs:5:20
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
index f5390c746..b25e68f13 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.rs
@@ -1,9 +1,75 @@
-#![allow(clippy::assign_op_pattern, clippy::unnecessary_owned_empty_strings)]
-#![feature(inline_const, saturating_int_impl)]
+#![allow(
+ clippy::assign_op_pattern,
+ clippy::erasing_op,
+ clippy::identity_op,
+ clippy::op_ref,
+ clippy::unnecessary_owned_empty_strings,
+ arithmetic_overflow,
+ unconditional_panic
+)]
+#![feature(const_mut_refs, inline_const, saturating_int_impl)]
#![warn(clippy::arithmetic_side_effects)]
use core::num::{Saturating, Wrapping};
+pub struct Custom;
+
+macro_rules! impl_arith {
+ ( $( $_trait:ident, $ty:ty, $method:ident; )* ) => {
+ $(
+ impl core::ops::$_trait<$ty> for Custom {
+ type Output = Self;
+ fn $method(self, _: $ty) -> Self::Output { Self }
+ }
+ )*
+ }
+}
+
+impl_arith!(
+ Add, i32, add;
+ Div, i32, div;
+ Mul, i32, mul;
+ Sub, i32, sub;
+
+ Add, f64, add;
+ Div, f64, div;
+ Mul, f64, mul;
+ Sub, f64, sub;
+);
+
+pub fn association_with_structures_should_not_trigger_the_lint() {
+ enum Foo {
+ Bar = -2,
+ }
+
+ impl Trait for Foo {
+ const ASSOC: i32 = {
+ let _: [i32; 1 + 1];
+ fn foo() {}
+ 1 + 1
+ };
+ }
+
+ struct Baz([i32; 1 + 1]);
+
+ trait Trait {
+ const ASSOC: i32 = 1 + 1;
+ }
+
+ type Alias = [i32; 1 + 1];
+
+ union Qux {
+ field: [i32; 1 + 1],
+ }
+
+ let _: [i32; 1 + 1] = [0, 0];
+
+ let _: [i32; 1 + 1] = {
+ let a: [i32; 1 + 1] = [0, 0];
+ a
+ };
+}
+
pub fn hard_coded_allowed() {
let _ = 1f32 + 1f32;
let _ = 1f64 + 1f64;
@@ -26,7 +92,7 @@ pub fn hard_coded_allowed() {
}
#[rustfmt::skip]
-pub fn non_overflowing_ops() {
+pub fn const_ops_should_not_trigger_the_lint() {
const _: i32 = { let mut n = 1; n += 1; n };
let _ = const { let mut n = 1; n += 1; n };
@@ -37,21 +103,122 @@ pub fn non_overflowing_ops() {
let _ = const { let mut n = 1; n = 1 + n; n };
const _: i32 = 1 + 1;
- let _ = 1 + 1;
let _ = const { 1 + 1 };
- let mut _a = 1;
- _a *= 1;
- _a /= 1;
+ const _: i32 = { let mut n = 1; n = -1; n = -(-1); n = -n; n };
+ let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
}
-#[rustfmt::skip]
-pub fn overflowing_ops() {
- let mut _a = 1; _a += 1;
+pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_trigger_the_lint() {
+ let mut _n = i32::MAX;
+
+ // Assign
+ _n += 0;
+ _n += &0;
+ _n -= 0;
+ _n -= &0;
+ _n /= 99;
+ _n /= &99;
+ _n %= 99;
+ _n %= &99;
+ _n *= 0;
+ _n *= &0;
+ _n *= 1;
+ _n *= &1;
+
+ // Binary
+ _n = _n + 0;
+ _n = _n + &0;
+ _n = 0 + _n;
+ _n = &0 + _n;
+ _n = _n - 0;
+ _n = _n - &0;
+ _n = 0 - _n;
+ _n = &0 - _n;
+ _n = _n / 99;
+ _n = _n / &99;
+ _n = _n % 99;
+ _n = _n % &99;
+ _n = _n * 0;
+ _n = _n * &0;
+ _n = 0 * _n;
+ _n = &0 * _n;
+ _n = _n * 1;
+ _n = _n * &1;
+ _n = 1 * _n;
+ _n = &1 * _n;
+ _n = 23 + 85;
+
+ // Unary
+ _n = -1;
+ _n = -(-1);
+}
+
+pub fn runtime_ops() {
+ let mut _n = i32::MAX;
+
+ // Assign
+ _n += 1;
+ _n += &1;
+ _n -= 1;
+ _n -= &1;
+ _n /= 0;
+ _n /= &0;
+ _n %= 0;
+ _n %= &0;
+ _n *= 2;
+ _n *= &2;
+
+ // Binary
+ _n = _n + 1;
+ _n = _n + &1;
+ _n = 1 + _n;
+ _n = &1 + _n;
+ _n = _n - 1;
+ _n = _n - &1;
+ _n = 1 - _n;
+ _n = &1 - _n;
+ _n = _n / 0;
+ _n = _n / &0;
+ _n = _n % 0;
+ _n = _n % &0;
+ _n = _n * 2;
+ _n = _n * &2;
+ _n = 2 * _n;
+ _n = &2 * _n;
+ _n = 23 + &85;
+ _n = &23 + 85;
+ _n = &23 + &85;
- let mut _b = 1; _b = _b + 1;
+ // Custom
+ let _ = Custom + 0;
+ let _ = Custom + 1;
+ let _ = Custom + 2;
+ let _ = Custom + 0.0;
+ let _ = Custom + 1.0;
+ let _ = Custom + 2.0;
+ let _ = Custom - 0;
+ let _ = Custom - 1;
+ let _ = Custom - 2;
+ let _ = Custom - 0.0;
+ let _ = Custom - 1.0;
+ let _ = Custom - 2.0;
+ let _ = Custom / 0;
+ let _ = Custom / 1;
+ let _ = Custom / 2;
+ let _ = Custom / 0.0;
+ let _ = Custom / 1.0;
+ let _ = Custom / 2.0;
+ let _ = Custom * 0;
+ let _ = Custom * 1;
+ let _ = Custom * 2;
+ let _ = Custom * 0.0;
+ let _ = Custom * 1.0;
+ let _ = Custom * 2.0;
- let mut _c = 1; _c = 1 + _c;
+ // Unary
+ _n = -_n;
+ _n = -&_n;
}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
index 6c4c8bdec..0f06e22ba 100644
--- a/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
+++ b/src/tools/clippy/tests/ui/arithmetic_side_effects.stderr
@@ -1,22 +1,352 @@
-error: arithmetic detected
- --> $DIR/arithmetic_side_effects.rs:50:21
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:78:13
|
-LL | let mut _a = 1; _a += 1;
- | ^^^^^^^
+LL | let _ = String::new() + "";
+ | ^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
-error: arithmetic detected
- --> $DIR/arithmetic_side_effects.rs:52:26
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:86:27
|
-LL | let mut _b = 1; _b = _b + 1;
- | ^^^^^^
+LL | let inferred_string = string + "";
+ | ^^^^^^^^^^^
-error: arithmetic detected
- --> $DIR/arithmetic_side_effects.rs:54:26
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:90:13
|
-LL | let mut _c = 1; _c = 1 + _c;
- | ^^^^^^
+LL | let _ = inferred_string + "";
+ | ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 3 previous errors
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:161:5
+ |
+LL | _n += 1;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:162:5
+ |
+LL | _n += &1;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:163:5
+ |
+LL | _n -= 1;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:164:5
+ |
+LL | _n -= &1;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:165:5
+ |
+LL | _n /= 0;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:166:5
+ |
+LL | _n /= &0;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:167:5
+ |
+LL | _n %= 0;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:168:5
+ |
+LL | _n %= &0;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:169:5
+ |
+LL | _n *= 2;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:170:5
+ |
+LL | _n *= &2;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:173:10
+ |
+LL | _n = _n + 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:174:10
+ |
+LL | _n = _n + &1;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:175:10
+ |
+LL | _n = 1 + _n;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:176:10
+ |
+LL | _n = &1 + _n;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:177:10
+ |
+LL | _n = _n - 1;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:178:10
+ |
+LL | _n = _n - &1;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:179:10
+ |
+LL | _n = 1 - _n;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:180:10
+ |
+LL | _n = &1 - _n;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:181:10
+ |
+LL | _n = _n / 0;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:182:10
+ |
+LL | _n = _n / &0;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:183:10
+ |
+LL | _n = _n % 0;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:184:10
+ |
+LL | _n = _n % &0;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:185:10
+ |
+LL | _n = _n * 2;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:186:10
+ |
+LL | _n = _n * &2;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:187:10
+ |
+LL | _n = 2 * _n;
+ | ^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:188:10
+ |
+LL | _n = &2 * _n;
+ | ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:189:10
+ |
+LL | _n = 23 + &85;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:190:10
+ |
+LL | _n = &23 + 85;
+ | ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:191:10
+ |
+LL | _n = &23 + &85;
+ | ^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:194:13
+ |
+LL | let _ = Custom + 0;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:195:13
+ |
+LL | let _ = Custom + 1;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:196:13
+ |
+LL | let _ = Custom + 2;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:197:13
+ |
+LL | let _ = Custom + 0.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:198:13
+ |
+LL | let _ = Custom + 1.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:199:13
+ |
+LL | let _ = Custom + 2.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:200:13
+ |
+LL | let _ = Custom - 0;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:201:13
+ |
+LL | let _ = Custom - 1;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:202:13
+ |
+LL | let _ = Custom - 2;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:203:13
+ |
+LL | let _ = Custom - 0.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:204:13
+ |
+LL | let _ = Custom - 1.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:205:13
+ |
+LL | let _ = Custom - 2.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:206:13
+ |
+LL | let _ = Custom / 0;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:207:13
+ |
+LL | let _ = Custom / 1;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:208:13
+ |
+LL | let _ = Custom / 2;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:209:13
+ |
+LL | let _ = Custom / 0.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:210:13
+ |
+LL | let _ = Custom / 1.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:211:13
+ |
+LL | let _ = Custom / 2.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:212:13
+ |
+LL | let _ = Custom * 0;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:213:13
+ |
+LL | let _ = Custom * 1;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:214:13
+ |
+LL | let _ = Custom * 2;
+ | ^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:215:13
+ |
+LL | let _ = Custom * 0.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:216:13
+ |
+LL | let _ = Custom * 1.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:217:13
+ |
+LL | let _ = Custom * 2.0;
+ | ^^^^^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:220:10
+ |
+LL | _n = -_n;
+ | ^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+ --> $DIR/arithmetic_side_effects.rs:221:10
+ |
+LL | _n = -&_n;
+ | ^^^^
+
+error: aborting due to 58 previous errors
diff --git a/src/tools/clippy/tests/ui/as_conversions.stderr b/src/tools/clippy/tests/ui/as_conversions.stderr
index d11b56171..f5d59e1e5 100644
--- a/src/tools/clippy/tests/ui/as_conversions.stderr
+++ b/src/tools/clippy/tests/ui/as_conversions.stderr
@@ -4,8 +4,8 @@ error: using a potentially dangerous silent `as` conversion
LL | let i = 0u32 as u64;
| ^^^^^^^^^^^
|
- = note: `-D clippy::as-conversions` implied by `-D warnings`
= help: consider using a safe wrapper for this conversion
+ = note: `-D clippy::as-conversions` implied by `-D warnings`
error: using a potentially dangerous silent `as` conversion
--> $DIR/as_conversions.rs:17:13
diff --git a/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs b/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs
new file mode 100644
index 000000000..0d1d92584
--- /dev/null
+++ b/src/tools/clippy/tests/ui/as_ptr_cast_mut.rs
@@ -0,0 +1,37 @@
+#![allow(unused)]
+#![warn(clippy::as_ptr_cast_mut)]
+#![allow(clippy::wrong_self_convention)]
+
+struct MutPtrWrapper(Vec<u8>);
+impl MutPtrWrapper {
+ fn as_ptr(&mut self) -> *const u8 {
+ self.0.as_mut_ptr() as *const u8
+ }
+}
+
+struct Covariant<T>(*const T);
+impl<T> Covariant<T> {
+ fn as_ptr(self) -> *const T {
+ self.0
+ }
+}
+
+fn main() {
+ let mut string = String::new();
+ let _ = string.as_ptr() as *mut u8;
+ let _: *mut i8 = string.as_ptr() as *mut _;
+ let _ = string.as_ptr() as *const i8;
+ let _ = string.as_mut_ptr();
+ let _ = string.as_mut_ptr() as *mut u8;
+ let _ = string.as_mut_ptr() as *const u8;
+
+ let nn = std::ptr::NonNull::new(4 as *mut u8).unwrap();
+ let _ = nn.as_ptr() as *mut u8;
+
+ let mut wrap = MutPtrWrapper(Vec::new());
+ let _ = wrap.as_ptr() as *mut u8;
+
+ let mut local = 4;
+ let ref_with_write_perm = Covariant(std::ptr::addr_of_mut!(local) as *const _);
+ let _ = ref_with_write_perm.as_ptr() as *mut u8;
+}
diff --git a/src/tools/clippy/tests/ui/as_ptr_cast_mut.stderr b/src/tools/clippy/tests/ui/as_ptr_cast_mut.stderr
new file mode 100644
index 000000000..2189c3d2f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/as_ptr_cast_mut.stderr
@@ -0,0 +1,16 @@
+error: casting the result of `as_ptr` to *mut u8
+ --> $DIR/as_ptr_cast_mut.rs:21:13
+ |
+LL | let _ = string.as_ptr() as *mut u8;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()`
+ |
+ = note: `-D clippy::as-ptr-cast-mut` implied by `-D warnings`
+
+error: casting the result of `as_ptr` to *mut i8
+ --> $DIR/as_ptr_cast_mut.rs:22:22
+ |
+LL | let _: *mut i8 = string.as_ptr() as *mut _;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/asm_syntax.stderr b/src/tools/clippy/tests/ui/asm_syntax.stderr
index e9b150121..9c7c3ba7d 100644
--- a/src/tools/clippy/tests/ui/asm_syntax.stderr
+++ b/src/tools/clippy/tests/ui/asm_syntax.stderr
@@ -4,8 +4,8 @@ error: Intel x86 assembly syntax used
LL | asm!("");
| ^^^^^^^^
|
- = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
= help: use AT&T x86 assembly syntax
+ = note: `-D clippy::inline-asm-x86-intel-syntax` implied by `-D warnings`
error: Intel x86 assembly syntax used
--> $DIR/asm_syntax.rs:9:9
@@ -29,8 +29,8 @@ error: AT&T x86 assembly syntax used
LL | asm!("", options(att_syntax));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
= help: use Intel x86 assembly syntax
+ = note: `-D clippy::inline-asm-x86-att-syntax` implied by `-D warnings`
error: AT&T x86 assembly syntax used
--> $DIR/asm_syntax.rs:24:9
diff --git a/src/tools/clippy/tests/ui/assertions_on_constants.stderr b/src/tools/clippy/tests/ui/assertions_on_constants.stderr
index e1f818814..29fe00903 100644
--- a/src/tools/clippy/tests/ui/assertions_on_constants.stderr
+++ b/src/tools/clippy/tests/ui/assertions_on_constants.stderr
@@ -4,8 +4,8 @@ error: `assert!(true)` will be optimized out by the compiler
LL | assert!(true);
| ^^^^^^^^^^^^^
|
- = note: `-D clippy::assertions-on-constants` implied by `-D warnings`
= help: remove it
+ = note: `-D clippy::assertions-on-constants` implied by `-D warnings`
error: `assert!(false)` should probably be replaced
--> $DIR/assertions_on_constants.rs:11:5
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
index 795f435f2..2bb755290 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.fixed
@@ -75,3 +75,9 @@ fn main() {
let r: Result<Foo, Foo> = Err(Foo);
assert!(r.is_err());
}
+
+#[allow(dead_code)]
+fn issue9450() {
+ let res: Result<i32, i32> = Ok(1);
+ res.unwrap_err();
+}
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.rs b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
index 1101aec1e..d8a9bd2f1 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.rs
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.rs
@@ -75,3 +75,9 @@ fn main() {
let r: Result<Foo, Foo> = Err(Foo);
assert!(r.is_err());
}
+
+#[allow(dead_code)]
+fn issue9450() {
+ let res: Result<i32, i32> = Ok(1);
+ assert!(res.is_err())
+}
diff --git a/src/tools/clippy/tests/ui/assertions_on_result_states.stderr b/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
index 97a5f3dfc..298d63c9c 100644
--- a/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
+++ b/src/tools/clippy/tests/ui/assertions_on_result_states.stderr
@@ -36,5 +36,11 @@ error: called `assert!` with `Result::is_err`
LL | assert!(r.is_err());
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
-error: aborting due to 6 previous errors
+error: called `assert!` with `Result::is_err`
+ --> $DIR/assertions_on_result_states.rs:82:5
+ |
+LL | assert!(res.is_err())
+ | ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();`
+
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/assign_ops2.rs b/src/tools/clippy/tests/ui/assign_ops2.rs
index f6d3a8fa3..2c876a96c 100644
--- a/src/tools/clippy/tests/ui/assign_ops2.rs
+++ b/src/tools/clippy/tests/ui/assign_ops2.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
#[allow(unused_assignments)]
#[warn(clippy::misrefactored_assign_op, clippy::assign_op_pattern)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/assign_ops2.stderr b/src/tools/clippy/tests/ui/assign_ops2.stderr
index 04b1dc93d..25e746022 100644
--- a/src/tools/clippy/tests/ui/assign_ops2.stderr
+++ b/src/tools/clippy/tests/ui/assign_ops2.stderr
@@ -1,5 +1,5 @@
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:5:5
+ --> $DIR/assign_ops2.rs:7:5
|
LL | a += a + 1;
| ^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | a = a + a + 1;
| ~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:6:5
+ --> $DIR/assign_ops2.rs:8:5
|
LL | a += 1 + a;
| ^^^^^^^^^^
@@ -30,7 +30,7 @@ LL | a = a + 1 + a;
| ~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:7:5
+ --> $DIR/assign_ops2.rs:9:5
|
LL | a -= a - 1;
| ^^^^^^^^^^
@@ -45,7 +45,7 @@ LL | a = a - (a - 1);
| ~~~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:8:5
+ --> $DIR/assign_ops2.rs:10:5
|
LL | a *= a * 99;
| ^^^^^^^^^^^
@@ -60,7 +60,7 @@ LL | a = a * a * 99;
| ~~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:9:5
+ --> $DIR/assign_ops2.rs:11:5
|
LL | a *= 42 * a;
| ^^^^^^^^^^^
@@ -75,7 +75,7 @@ LL | a = a * 42 * a;
| ~~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:10:5
+ --> $DIR/assign_ops2.rs:12:5
|
LL | a /= a / 2;
| ^^^^^^^^^^
@@ -90,7 +90,7 @@ LL | a = a / (a / 2);
| ~~~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:11:5
+ --> $DIR/assign_ops2.rs:13:5
|
LL | a %= a % 5;
| ^^^^^^^^^^
@@ -105,7 +105,7 @@ LL | a = a % (a % 5);
| ~~~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:12:5
+ --> $DIR/assign_ops2.rs:14:5
|
LL | a &= a & 1;
| ^^^^^^^^^^
@@ -120,7 +120,7 @@ LL | a = a & a & 1;
| ~~~~~~~~~~~~~
error: variable appears on both sides of an assignment operation
- --> $DIR/assign_ops2.rs:13:5
+ --> $DIR/assign_ops2.rs:15:5
|
LL | a *= a * a;
| ^^^^^^^^^^
@@ -135,7 +135,7 @@ LL | a = a * a * a;
| ~~~~~~~~~~~~~
error: manual implementation of an assign operation
- --> $DIR/assign_ops2.rs:50:5
+ --> $DIR/assign_ops2.rs:52:5
|
LL | buf = buf + cows.clone();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()`
diff --git a/src/tools/clippy/tests/ui/author.stdout b/src/tools/clippy/tests/ui/author.stdout
index 597318a55..27ad538f2 100644
--- a/src/tools/clippy/tests/ui/author.stdout
+++ b/src/tools/clippy/tests/ui/author.stdout
@@ -1,14 +1,12 @@
-if_chain! {
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if let ExprKind::Cast(expr, cast_ty) = init.kind;
- if let TyKind::Path(ref qpath) = cast_ty.kind;
- if match_qpath(qpath, &["char"]);
- if let ExprKind::Lit(ref lit) = expr.kind;
- if let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node;
- if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
- if name.as_str() == "x";
- then {
- // report your lint here
- }
+if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && let ExprKind::Cast(expr, cast_ty) = init.kind
+ && let TyKind::Path(ref qpath) = cast_ty.kind
+ && match_qpath(qpath, &["char"])
+ && let ExprKind::Lit(ref lit) = expr.kind
+ && let LitKind::Int(69, LitIntType::Unsuffixed) = lit.node
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind
+ && name.as_str() == "x"
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui/author/blocks.stdout
index a529981e2..9de0550d8 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui/author/blocks.stdout
@@ -1,64 +1,58 @@
-if_chain! {
- if let ExprKind::Block(block, None) = expr.kind;
- if block.stmts.len() == 3;
- if let StmtKind::Local(local) = block.stmts[0].kind;
- if let Some(init) = local.init;
- if let ExprKind::Lit(ref lit) = init.kind;
- if let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node;
- if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
- if name.as_str() == "x";
- if let StmtKind::Local(local1) = block.stmts[1].kind;
- if let Some(init1) = local1.init;
- if let ExprKind::Lit(ref lit1) = init1.kind;
- if let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node;
- if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local1.pat.kind;
- if name1.as_str() == "_t";
- if let StmtKind::Semi(e) = block.stmts[2].kind;
- if let ExprKind::Unary(UnOp::Neg, inner) = e.kind;
- if let ExprKind::Path(ref qpath) = inner.kind;
- if match_qpath(qpath, &["x"]);
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let ExprKind::Block(block, None) = expr.kind
+ && block.stmts.len() == 3
+ && let StmtKind::Local(local) = block.stmts[0].kind
+ && let Some(init) = local.init
+ && let ExprKind::Lit(ref lit) = init.kind
+ && let LitKind::Int(42, LitIntType::Signed(IntTy::I32)) = lit.node
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind
+ && name.as_str() == "x"
+ && let StmtKind::Local(local1) = block.stmts[1].kind
+ && let Some(init1) = local1.init
+ && let ExprKind::Lit(ref lit1) = init1.kind
+ && let LitKind::Float(_, LitFloatType::Suffixed(FloatTy::F32)) = lit1.node
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local1.pat.kind
+ && name1.as_str() == "_t"
+ && let StmtKind::Semi(e) = block.stmts[2].kind
+ && let ExprKind::Unary(UnOp::Neg, inner) = e.kind
+ && let ExprKind::Path(ref qpath) = inner.kind
+ && match_qpath(qpath, &["x"])
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let ExprKind::Block(block, None) = expr.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Local(local) = block.stmts[0].kind;
- if let Some(init) = local.init;
- if let ExprKind::Call(func, args) = init.kind;
- if let ExprKind::Path(ref qpath) = func.kind;
- if match_qpath(qpath, &["String", "new"]);
- if args.is_empty();
- if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind;
- if name.as_str() == "expr";
- if let Some(trailing_expr) = block.expr;
- if let ExprKind::Call(func1, args1) = trailing_expr.kind;
- if let ExprKind::Path(ref qpath1) = func1.kind;
- if match_qpath(qpath1, &["drop"]);
- if args1.len() == 1;
- if let ExprKind::Path(ref qpath2) = args1[0].kind;
- if match_qpath(qpath2, &["expr"]);
- then {
- // report your lint here
- }
+if let ExprKind::Block(block, None) = expr.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Local(local) = block.stmts[0].kind
+ && let Some(init) = local.init
+ && let ExprKind::Call(func, args) = init.kind
+ && let ExprKind::Path(ref qpath) = func.kind
+ && match_qpath(qpath, &["String", "new"])
+ && args.is_empty()
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local.pat.kind
+ && name.as_str() == "expr"
+ && let Some(trailing_expr) = block.expr
+ && let ExprKind::Call(func1, args1) = trailing_expr.kind
+ && let ExprKind::Path(ref qpath1) = func1.kind
+ && match_qpath(qpath1, &["drop"])
+ && args1.len() == 1
+ && let ExprKind::Path(ref qpath2) = args1[0].kind
+ && match_qpath(qpath2, &["expr"])
+{
+ // report your lint here
}
-if_chain! {
- if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind;
- if let FnRetTy::DefaultReturn(_) = fn_decl.output;
- let expr1 = &cx.tcx.hir().body(body_id).value;
- if let ExprKind::Call(func, args) = expr1.kind;
- if let ExprKind::Path(ref qpath) = func.kind;
- if matches!(qpath, QPath::LangItem(LangItem::FromGenerator, _));
- if args.len() == 1;
- if let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind;
- if let FnRetTy::DefaultReturn(_) = fn_decl1.output;
- let expr2 = &cx.tcx.hir().body(body_id1).value;
- if let ExprKind::Block(block, None) = expr2.kind;
- if block.stmts.is_empty();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let ExprKind::Closure(CaptureBy::Value, fn_decl, body_id, _, None) = expr.kind
+ && let FnRetTy::DefaultReturn(_) = fn_decl.output
+ && expr1 = &cx.tcx.hir().body(body_id).value
+ && let ExprKind::Call(func, args) = expr1.kind
+ && let ExprKind::Path(ref qpath) = func.kind
+ && matches!(qpath, QPath::LangItem(LangItem::FromGenerator, _))
+ && args.len() == 1
+ && let ExprKind::Closure(CaptureBy::Value, fn_decl1, body_id1, _, Some(Movability::Static)) = args[0].kind
+ && let FnRetTy::DefaultReturn(_) = fn_decl1.output
+ && expr2 = &cx.tcx.hir().body(body_id1).value
+ && let ExprKind::Block(block, None) = expr2.kind
+ && block.stmts.is_empty()
+ && block.expr.is_none()
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/call.stdout b/src/tools/clippy/tests/ui/author/call.stdout
index 266312d63..f040f6330 100644
--- a/src/tools/clippy/tests/ui/author/call.stdout
+++ b/src/tools/clippy/tests/ui/author/call.stdout
@@ -1,16 +1,14 @@
-if_chain! {
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if let ExprKind::Call(func, args) = init.kind;
- if let ExprKind::Path(ref qpath) = func.kind;
- if match_qpath(qpath, &["{{root}}", "std", "cmp", "min"]);
- if args.len() == 2;
- if let ExprKind::Lit(ref lit) = args[0].kind;
- if let LitKind::Int(3, LitIntType::Unsuffixed) = lit.node;
- if let ExprKind::Lit(ref lit1) = args[1].kind;
- if let LitKind::Int(4, LitIntType::Unsuffixed) = lit1.node;
- if let PatKind::Wild = local.pat.kind;
- then {
- // report your lint here
- }
+if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && let ExprKind::Call(func, args) = init.kind
+ && let ExprKind::Path(ref qpath) = func.kind
+ && match_qpath(qpath, &["{{root}}", "std", "cmp", "min"])
+ && args.len() == 2
+ && let ExprKind::Lit(ref lit) = args[0].kind
+ && let LitKind::Int(3, LitIntType::Unsuffixed) = lit.node
+ && let ExprKind::Lit(ref lit1) = args[1].kind
+ && let LitKind::Int(4, LitIntType::Unsuffixed) = lit1.node
+ && let PatKind::Wild = local.pat.kind
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index 8d92849b3..5d7961882 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui/author/if.stdout
@@ -1,50 +1,46 @@
-if_chain! {
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if let ExprKind::If(cond, then, Some(else_expr)) = init.kind;
- if let ExprKind::DropTemps(expr) = cond.kind;
- if let ExprKind::Lit(ref lit) = expr.kind;
- if let LitKind::Bool(true) = lit.node;
- if let ExprKind::Block(block, None) = then.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Semi(e) = block.stmts[0].kind;
- if let ExprKind::Binary(op, left, right) = e.kind;
- if BinOpKind::Eq == op.node;
- if let ExprKind::Lit(ref lit1) = left.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node;
- if let ExprKind::Lit(ref lit2) = right.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit2.node;
- if block.expr.is_none();
- if let ExprKind::Block(block1, None) = else_expr.kind;
- if block1.stmts.len() == 1;
- if let StmtKind::Semi(e1) = block1.stmts[0].kind;
- if let ExprKind::Binary(op1, left1, right1) = e1.kind;
- if BinOpKind::Eq == op1.node;
- if let ExprKind::Lit(ref lit3) = left1.kind;
- if let LitKind::Int(2, LitIntType::Unsuffixed) = lit3.node;
- if let ExprKind::Lit(ref lit4) = right1.kind;
- if let LitKind::Int(2, LitIntType::Unsuffixed) = lit4.node;
- if block1.expr.is_none();
- if let PatKind::Wild = local.pat.kind;
- then {
- // report your lint here
- }
+if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && let ExprKind::If(cond, then, Some(else_expr)) = init.kind
+ && let ExprKind::DropTemps(expr) = cond.kind
+ && let ExprKind::Lit(ref lit) = expr.kind
+ && let LitKind::Bool(true) = lit.node
+ && let ExprKind::Block(block, None) = then.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Semi(e) = block.stmts[0].kind
+ && let ExprKind::Binary(op, left, right) = e.kind
+ && BinOpKind::Eq == op.node
+ && let ExprKind::Lit(ref lit1) = left.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node
+ && let ExprKind::Lit(ref lit2) = right.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit2.node
+ && block.expr.is_none()
+ && let ExprKind::Block(block1, None) = else_expr.kind
+ && block1.stmts.len() == 1
+ && let StmtKind::Semi(e1) = block1.stmts[0].kind
+ && let ExprKind::Binary(op1, left1, right1) = e1.kind
+ && BinOpKind::Eq == op1.node
+ && let ExprKind::Lit(ref lit3) = left1.kind
+ && let LitKind::Int(2, LitIntType::Unsuffixed) = lit3.node
+ && let ExprKind::Lit(ref lit4) = right1.kind
+ && let LitKind::Int(2, LitIntType::Unsuffixed) = lit4.node
+ && block1.expr.is_none()
+ && let PatKind::Wild = local.pat.kind
+{
+ // report your lint here
}
-if_chain! {
- if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind;
- if let ExprKind::Let(let_expr) = cond.kind;
- if let PatKind::Lit(lit_expr) = let_expr.pat.kind;
- if let ExprKind::Lit(ref lit) = lit_expr.kind;
- if let LitKind::Bool(true) = lit.node;
- if let ExprKind::Path(ref qpath) = let_expr.init.kind;
- if match_qpath(qpath, &["a"]);
- if let ExprKind::Block(block, None) = then.kind;
- if block.stmts.is_empty();
- if block.expr.is_none();
- if let ExprKind::Block(block1, None) = else_expr.kind;
- if block1.stmts.is_empty();
- if block1.expr.is_none();
- then {
- // report your lint here
- }
+if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind
+ && let ExprKind::Let(let_expr) = cond.kind
+ && let PatKind::Lit(lit_expr) = let_expr.pat.kind
+ && let ExprKind::Lit(ref lit) = lit_expr.kind
+ && let LitKind::Bool(true) = lit.node
+ && let ExprKind::Path(ref qpath) = let_expr.init.kind
+ && match_qpath(qpath, &["a"])
+ && let ExprKind::Block(block, None) = then.kind
+ && block.stmts.is_empty()
+ && block.expr.is_none()
+ && let ExprKind::Block(block1, None) = else_expr.kind
+ && block1.stmts.is_empty()
+ && block1.expr.is_none()
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/issue_3849.stdout b/src/tools/clippy/tests/ui/author/issue_3849.stdout
index bce4bc702..32a3127b8 100644
--- a/src/tools/clippy/tests/ui/author/issue_3849.stdout
+++ b/src/tools/clippy/tests/ui/author/issue_3849.stdout
@@ -1,14 +1,12 @@
-if_chain! {
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if let ExprKind::Call(func, args) = init.kind;
- if let ExprKind::Path(ref qpath) = func.kind;
- if match_qpath(qpath, &["std", "mem", "transmute"]);
- if args.len() == 1;
- if let ExprKind::Path(ref qpath1) = args[0].kind;
- if match_qpath(qpath1, &["ZPTR"]);
- if let PatKind::Wild = local.pat.kind;
- then {
- // report your lint here
- }
+if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && let ExprKind::Call(func, args) = init.kind
+ && let ExprKind::Path(ref qpath) = func.kind
+ && match_qpath(qpath, &["std", "mem", "transmute"])
+ && args.len() == 1
+ && let ExprKind::Path(ref qpath1) = args[0].kind
+ && match_qpath(qpath1, &["ZPTR"])
+ && let PatKind::Wild = local.pat.kind
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout
index ceb53fcd4..94a6436ed 100644
--- a/src/tools/clippy/tests/ui/author/loop.stdout
+++ b/src/tools/clippy/tests/ui/author/loop.stdout
@@ -1,113 +1,101 @@
-if_chain! {
- if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
- if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind;
- if name.as_str() == "y";
- if let ExprKind::Struct(qpath, fields, None) = arg.kind;
- if matches!(qpath, QPath::LangItem(LangItem::Range, _));
- if fields.len() == 2;
- if fields[0].ident.as_str() == "start";
- if let ExprKind::Lit(ref lit) = fields[0].expr.kind;
- if let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node;
- if fields[1].ident.as_str() == "end";
- if let ExprKind::Lit(ref lit1) = fields[1].expr.kind;
- if let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node;
- if let ExprKind::Block(block, None) = body.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Local(local) = block.stmts[0].kind;
- if let Some(init) = local.init;
- if let ExprKind::Path(ref qpath1) = init.kind;
- if match_qpath(qpath1, &["y"]);
- if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
- if name1.as_str() == "z";
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = pat.kind
+ && name.as_str() == "y"
+ && let ExprKind::Struct(qpath, fields, None) = arg.kind
+ && matches!(qpath, QPath::LangItem(LangItem::Range, _))
+ && fields.len() == 2
+ && fields[0].ident.as_str() == "start"
+ && let ExprKind::Lit(ref lit) = fields[0].expr.kind
+ && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+ && fields[1].ident.as_str() == "end"
+ && let ExprKind::Lit(ref lit1) = fields[1].expr.kind
+ && let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node
+ && let ExprKind::Block(block, None) = body.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Local(local) = block.stmts[0].kind
+ && let Some(init) = local.init
+ && let ExprKind::Path(ref qpath1) = init.kind
+ && match_qpath(qpath1, &["y"])
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind
+ && name1.as_str() == "z"
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
- if let PatKind::Wild = pat.kind;
- if let ExprKind::Struct(qpath, fields, None) = arg.kind;
- if matches!(qpath, QPath::LangItem(LangItem::Range, _));
- if fields.len() == 2;
- if fields[0].ident.as_str() == "start";
- if let ExprKind::Lit(ref lit) = fields[0].expr.kind;
- if let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node;
- if fields[1].ident.as_str() == "end";
- if let ExprKind::Lit(ref lit1) = fields[1].expr.kind;
- if let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node;
- if let ExprKind::Block(block, None) = body.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Semi(e) = block.stmts[0].kind;
- if let ExprKind::Break(destination, None) = e.kind;
- if destination.label.is_none();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
+ && let PatKind::Wild = pat.kind
+ && let ExprKind::Struct(qpath, fields, None) = arg.kind
+ && matches!(qpath, QPath::LangItem(LangItem::Range, _))
+ && fields.len() == 2
+ && fields[0].ident.as_str() == "start"
+ && let ExprKind::Lit(ref lit) = fields[0].expr.kind
+ && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+ && fields[1].ident.as_str() == "end"
+ && let ExprKind::Lit(ref lit1) = fields[1].expr.kind
+ && let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node
+ && let ExprKind::Block(block, None) = body.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Semi(e) = block.stmts[0].kind
+ && let ExprKind::Break(destination, None) = e.kind
+ && destination.label.is_none()
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr);
- if let PatKind::Wild = pat.kind;
- if let ExprKind::Struct(qpath, fields, None) = arg.kind;
- if matches!(qpath, QPath::LangItem(LangItem::Range, _));
- if fields.len() == 2;
- if fields[0].ident.as_str() == "start";
- if let ExprKind::Lit(ref lit) = fields[0].expr.kind;
- if let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node;
- if fields[1].ident.as_str() == "end";
- if let ExprKind::Lit(ref lit1) = fields[1].expr.kind;
- if let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node;
- if let ExprKind::Block(block, None) = body.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Semi(e) = block.stmts[0].kind;
- if let ExprKind::Break(destination, None) = e.kind;
- if let Some(label) = destination.label;
- if label.ident.as_str() == "'label";
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::ForLoop::hir(expr)
+ && let PatKind::Wild = pat.kind
+ && let ExprKind::Struct(qpath, fields, None) = arg.kind
+ && matches!(qpath, QPath::LangItem(LangItem::Range, _))
+ && fields.len() == 2
+ && fields[0].ident.as_str() == "start"
+ && let ExprKind::Lit(ref lit) = fields[0].expr.kind
+ && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node
+ && fields[1].ident.as_str() == "end"
+ && let ExprKind::Lit(ref lit1) = fields[1].expr.kind
+ && let LitKind::Int(10, LitIntType::Unsuffixed) = lit1.node
+ && let ExprKind::Block(block, None) = body.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Semi(e) = block.stmts[0].kind
+ && let ExprKind::Break(destination, None) = e.kind
+ && let Some(label) = destination.label
+ && label.ident.as_str() == "'label"
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let Some(higher::While { condition: condition, body: body }) = higher::While::hir(expr);
- if let ExprKind::Path(ref qpath) = condition.kind;
- if match_qpath(qpath, &["a"]);
- if let ExprKind::Block(block, None) = body.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Semi(e) = block.stmts[0].kind;
- if let ExprKind::Break(destination, None) = e.kind;
- if destination.label.is_none();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let Some(higher::While { condition: condition, body: body }) = higher::While::hir(expr)
+ && let ExprKind::Path(ref qpath) = condition.kind
+ && match_qpath(qpath, &["a"])
+ && let ExprKind::Block(block, None) = body.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Semi(e) = block.stmts[0].kind
+ && let ExprKind::Break(destination, None) = e.kind
+ && destination.label.is_none()
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr);
- if let PatKind::Lit(lit_expr) = let_pat.kind;
- if let ExprKind::Lit(ref lit) = lit_expr.kind;
- if let LitKind::Bool(true) = lit.node;
- if let ExprKind::Path(ref qpath) = let_expr.kind;
- if match_qpath(qpath, &["a"]);
- if let ExprKind::Block(block, None) = if_then.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Semi(e) = block.stmts[0].kind;
- if let ExprKind::Break(destination, None) = e.kind;
- if destination.label.is_none();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr)
+ && let PatKind::Lit(lit_expr) = let_pat.kind
+ && let ExprKind::Lit(ref lit) = lit_expr.kind
+ && let LitKind::Bool(true) = lit.node
+ && let ExprKind::Path(ref qpath) = let_expr.kind
+ && match_qpath(qpath, &["a"])
+ && let ExprKind::Block(block, None) = if_then.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Semi(e) = block.stmts[0].kind
+ && let ExprKind::Break(destination, None) = e.kind
+ && destination.label.is_none()
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let ExprKind::Loop(body, None, LoopSource::Loop, _) = expr.kind;
- if body.stmts.len() == 1;
- if let StmtKind::Semi(e) = body.stmts[0].kind;
- if let ExprKind::Break(destination, None) = e.kind;
- if destination.label.is_none();
- if body.expr.is_none();
- then {
- // report your lint here
- }
+if let ExprKind::Loop(body, None, LoopSource::Loop, _) = expr.kind
+ && body.stmts.len() == 1
+ && let StmtKind::Semi(e) = body.stmts[0].kind
+ && let ExprKind::Break(destination, None) = e.kind
+ && destination.label.is_none()
+ && body.expr.is_none()
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout
index 2cf69a035..88e2ca656 100644
--- a/src/tools/clippy/tests/ui/author/matches.stdout
+++ b/src/tools/clippy/tests/ui/author/matches.stdout
@@ -1,38 +1,36 @@
-if_chain! {
- if let StmtKind::Local(local) = stmt.kind;
- if let Some(init) = local.init;
- if let ExprKind::Match(scrutinee, arms, MatchSource::Normal) = init.kind;
- if let ExprKind::Lit(ref lit) = scrutinee.kind;
- if let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node;
- if arms.len() == 3;
- if let PatKind::Lit(lit_expr) = arms[0].pat.kind;
- if let ExprKind::Lit(ref lit1) = lit_expr.kind;
- if let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node;
- if arms[0].guard.is_none();
- if let ExprKind::Lit(ref lit2) = arms[0].body.kind;
- if let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node;
- if let PatKind::Lit(lit_expr1) = arms[1].pat.kind;
- if let ExprKind::Lit(ref lit3) = lit_expr1.kind;
- if let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node;
- if arms[1].guard.is_none();
- if let ExprKind::Block(block, None) = arms[1].body.kind;
- if block.stmts.len() == 1;
- if let StmtKind::Local(local1) = block.stmts[0].kind;
- if let Some(init1) = local1.init;
- if let ExprKind::Lit(ref lit4) = init1.kind;
- if let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node;
- if let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local1.pat.kind;
- if name.as_str() == "x";
- if let Some(trailing_expr) = block.expr;
- if let ExprKind::Path(ref qpath) = trailing_expr.kind;
- if match_qpath(qpath, &["x"]);
- if let PatKind::Wild = arms[2].pat.kind;
- if arms[2].guard.is_none();
- if let ExprKind::Lit(ref lit5) = arms[2].body.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node;
- if let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind;
- if name1.as_str() == "a";
- then {
- // report your lint here
- }
+if let StmtKind::Local(local) = stmt.kind
+ && let Some(init) = local.init
+ && let ExprKind::Match(scrutinee, arms, MatchSource::Normal) = init.kind
+ && let ExprKind::Lit(ref lit) = scrutinee.kind
+ && let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node
+ && arms.len() == 3
+ && let PatKind::Lit(lit_expr) = arms[0].pat.kind
+ && let ExprKind::Lit(ref lit1) = lit_expr.kind
+ && let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node
+ && arms[0].guard.is_none()
+ && let ExprKind::Lit(ref lit2) = arms[0].body.kind
+ && let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node
+ && let PatKind::Lit(lit_expr1) = arms[1].pat.kind
+ && let ExprKind::Lit(ref lit3) = lit_expr1.kind
+ && let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node
+ && arms[1].guard.is_none()
+ && let ExprKind::Block(block, None) = arms[1].body.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Local(local1) = block.stmts[0].kind
+ && let Some(init1) = local1.init
+ && let ExprKind::Lit(ref lit4) = init1.kind
+ && let LitKind::Int(3, LitIntType::Unsuffixed) = lit4.node
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name, None) = local1.pat.kind
+ && name.as_str() == "x"
+ && let Some(trailing_expr) = block.expr
+ && let ExprKind::Path(ref qpath) = trailing_expr.kind
+ && match_qpath(qpath, &["x"])
+ && let PatKind::Wild = arms[2].pat.kind
+ && arms[2].guard.is_none()
+ && let ExprKind::Lit(ref lit5) = arms[2].body.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit5.node
+ && let PatKind::Binding(BindingAnnotation::NONE, _, name1, None) = local.pat.kind
+ && name1.as_str() == "a"
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui/author/repeat.stdout
index 471bbce4f..c2a369610 100644
--- a/src/tools/clippy/tests/ui/author/repeat.stdout
+++ b/src/tools/clippy/tests/ui/author/repeat.stdout
@@ -1,12 +1,10 @@
-if_chain! {
- if let ExprKind::Repeat(value, length) = expr.kind;
- if let ExprKind::Lit(ref lit) = value.kind;
- if let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node;
- if let ArrayLen::Body(anon_const) = length;
- let expr1 = &cx.tcx.hir().body(anon_const.body).value;
- if let ExprKind::Lit(ref lit1) = expr1.kind;
- if let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node;
- then {
- // report your lint here
- }
+if let ExprKind::Repeat(value, length) = expr.kind
+ && let ExprKind::Lit(ref lit) = value.kind
+ && let LitKind::Int(1, LitIntType::Unsigned(UintTy::U8)) = lit.node
+ && let ArrayLen::Body(anon_const) = length
+ && expr1 = &cx.tcx.hir().body(anon_const.body).value
+ && let ExprKind::Lit(ref lit1) = expr1.kind
+ && let LitKind::Int(5, LitIntType::Unsuffixed) = lit1.node
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout
index b5bbc9e21..0b332d5e7 100644
--- a/src/tools/clippy/tests/ui/author/struct.stdout
+++ b/src/tools/clippy/tests/ui/author/struct.stdout
@@ -1,64 +1,56 @@
-if_chain! {
- if let ExprKind::Struct(qpath, fields, None) = expr.kind;
- if match_qpath(qpath, &["Test"]);
- if fields.len() == 1;
- if fields[0].ident.as_str() == "field";
- if let ExprKind::If(cond, then, Some(else_expr)) = fields[0].expr.kind;
- if let ExprKind::DropTemps(expr1) = cond.kind;
- if let ExprKind::Lit(ref lit) = expr1.kind;
- if let LitKind::Bool(true) = lit.node;
- if let ExprKind::Block(block, None) = then.kind;
- if block.stmts.is_empty();
- if let Some(trailing_expr) = block.expr;
- if let ExprKind::Lit(ref lit1) = trailing_expr.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node;
- if let ExprKind::Block(block1, None) = else_expr.kind;
- if block1.stmts.is_empty();
- if let Some(trailing_expr1) = block1.expr;
- if let ExprKind::Lit(ref lit2) = trailing_expr1.kind;
- if let LitKind::Int(0, LitIntType::Unsuffixed) = lit2.node;
- then {
- // report your lint here
- }
+if let ExprKind::Struct(qpath, fields, None) = expr.kind
+ && match_qpath(qpath, &["Test"])
+ && fields.len() == 1
+ && fields[0].ident.as_str() == "field"
+ && let ExprKind::If(cond, then, Some(else_expr)) = fields[0].expr.kind
+ && let ExprKind::DropTemps(expr1) = cond.kind
+ && let ExprKind::Lit(ref lit) = expr1.kind
+ && let LitKind::Bool(true) = lit.node
+ && let ExprKind::Block(block, None) = then.kind
+ && block.stmts.is_empty()
+ && let Some(trailing_expr) = block.expr
+ && let ExprKind::Lit(ref lit1) = trailing_expr.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit1.node
+ && let ExprKind::Block(block1, None) = else_expr.kind
+ && block1.stmts.is_empty()
+ && let Some(trailing_expr1) = block1.expr
+ && let ExprKind::Lit(ref lit2) = trailing_expr1.kind
+ && let LitKind::Int(0, LitIntType::Unsuffixed) = lit2.node
+{
+ // report your lint here
}
-if_chain! {
- if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind;
- if match_qpath(qpath, &["Test"]);
- if fields.len() == 1;
- if fields[0].ident.as_str() == "field";
- if let PatKind::Lit(lit_expr) = fields[0].pat.kind;
- if let ExprKind::Lit(ref lit) = lit_expr.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node;
- if arm.guard.is_none();
- if let ExprKind::Block(block, None) = arm.body.kind;
- if block.stmts.is_empty();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind
+ && match_qpath(qpath, &["Test"])
+ && fields.len() == 1
+ && fields[0].ident.as_str() == "field"
+ && let PatKind::Lit(lit_expr) = fields[0].pat.kind
+ && let ExprKind::Lit(ref lit) = lit_expr.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
+ && arm.guard.is_none()
+ && let ExprKind::Block(block, None) = arm.body.kind
+ && block.stmts.is_empty()
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind;
- if match_qpath(qpath, &["TestTuple"]);
- if fields.len() == 1;
- if let PatKind::Lit(lit_expr) = fields[0].kind;
- if let ExprKind::Lit(ref lit) = lit_expr.kind;
- if let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node;
- if arm.guard.is_none();
- if let ExprKind::Block(block, None) = arm.body.kind;
- if block.stmts.is_empty();
- if block.expr.is_none();
- then {
- // report your lint here
- }
+if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind
+ && match_qpath(qpath, &["TestTuple"])
+ && fields.len() == 1
+ && let PatKind::Lit(lit_expr) = fields[0].kind
+ && let ExprKind::Lit(ref lit) = lit_expr.kind
+ && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
+ && arm.guard.is_none()
+ && let ExprKind::Block(block, None) = arm.body.kind
+ && block.stmts.is_empty()
+ && block.expr.is_none()
+{
+ // report your lint here
}
-if_chain! {
- if let ExprKind::MethodCall(method_name, receiver, args, _) = expr.kind;
- if method_name.ident.as_str() == "test";
- if let ExprKind::Path(ref qpath) = receiver.kind;
- if match_qpath(qpath, &["test_method_call"]);
- if args.is_empty();
- then {
- // report your lint here
- }
+if let ExprKind::MethodCall(method_name, receiver, args, _) = expr.kind
+ && method_name.ident.as_str() == "test"
+ && let ExprKind::Path(ref qpath) = receiver.kind
+ && match_qpath(qpath, &["test_method_call"])
+ && args.is_empty()
+{
+ // report your lint here
}
diff --git a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
index 83a0af6b8..ef3ca9aea 100644
--- a/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
@@ -140,3 +140,10 @@ macro_rules! manual_rem_euclid {
macro_rules! equatable_if_let {
($a:ident) => {{ if let 2 = $a {} }};
}
+
+#[macro_export]
+macro_rules! almost_complete_letter_range {
+ () => {
+ let _ = 'a'..'z';
+ };
+}
diff --git a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
index ae2cc2492..4914f14b5 100644
--- a/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/src/tools/clippy/tests/ui/auxiliary/proc_macro_attr.rs
@@ -4,7 +4,7 @@
#![crate_type = "proc-macro"]
#![feature(repr128, proc_macro_hygiene, proc_macro_quote, box_patterns)]
#![allow(incomplete_features)]
-#![allow(clippy::useless_conversion)]
+#![allow(clippy::useless_conversion, clippy::uninlined_format_args)]
extern crate proc_macro;
extern crate quote;
diff --git a/src/tools/clippy/tests/ui/await_holding_lock.stderr b/src/tools/clippy/tests/ui/await_holding_lock.stderr
index 976da8d92..81a2d0524 100644
--- a/src/tools/clippy/tests/ui/await_holding_lock.stderr
+++ b/src/tools/clippy/tests/ui/await_holding_lock.stderr
@@ -4,7 +4,6 @@ error: this `MutexGuard` is held across an `await` point
LL | let guard = x.lock().unwrap();
| ^^^^^
|
- = note: `-D clippy::await-holding-lock` implied by `-D warnings`
= help: consider using an async-aware `Mutex` type or ensuring the `MutexGuard` is dropped before calling await
note: these are all the `await` points this lock is held through
--> $DIR/await_holding_lock.rs:9:9
@@ -13,6 +12,7 @@ LL | / let guard = x.lock().unwrap();
LL | | baz().await
LL | | }
| |_____^
+ = note: `-D clippy::await-holding-lock` implied by `-D warnings`
error: this `MutexGuard` is held across an `await` point
--> $DIR/await_holding_lock.rs:24:13
diff --git a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
index 4339fca73..25c15ab80 100644
--- a/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
+++ b/src/tools/clippy/tests/ui/await_holding_refcell_ref.stderr
@@ -4,7 +4,6 @@ error: this `RefCell` reference is held across an `await` point
LL | let b = x.borrow();
| ^
|
- = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
= help: ensure the reference is dropped before calling `await`
note: these are all the `await` points this reference is held through
--> $DIR/await_holding_refcell_ref.rs:6:5
@@ -13,6 +12,7 @@ LL | / let b = x.borrow();
LL | | baz().await
LL | | }
| |_^
+ = note: `-D clippy::await-holding-refcell-ref` implied by `-D warnings`
error: this `RefCell` reference is held across an `await` point
--> $DIR/await_holding_refcell_ref.rs:11:9
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map.fixed b/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
index 5815550d7..d94e2ac60 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![deny(clippy::bind_instead_of_map)]
+#![allow(clippy::uninlined_format_args)]
// need a main anyway, use it get rid of unused warnings too
pub fn main() {
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map.rs b/src/tools/clippy/tests/ui/bind_instead_of_map.rs
index 623b100a4..86f31f582 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map.rs
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![deny(clippy::bind_instead_of_map)]
+#![allow(clippy::uninlined_format_args)]
// need a main anyway, use it get rid of unused warnings too
pub fn main() {
diff --git a/src/tools/clippy/tests/ui/bind_instead_of_map.stderr b/src/tools/clippy/tests/ui/bind_instead_of_map.stderr
index 24c6b7f9e..b6a81d21b 100644
--- a/src/tools/clippy/tests/ui/bind_instead_of_map.stderr
+++ b/src/tools/clippy/tests/ui/bind_instead_of_map.stderr
@@ -1,5 +1,5 @@
error: using `Option.and_then(Some)`, which is a no-op
- --> $DIR/bind_instead_of_map.rs:8:13
+ --> $DIR/bind_instead_of_map.rs:9:13
|
LL | let _ = x.and_then(Some);
| ^^^^^^^^^^^^^^^^ help: use the expression directly: `x`
@@ -11,13 +11,13 @@ LL | #![deny(clippy::bind_instead_of_map)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`
- --> $DIR/bind_instead_of_map.rs:9:13
+ --> $DIR/bind_instead_of_map.rs:10:13
|
LL | let _ = x.and_then(|o| Some(o + 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `x.map(|o| o + 1)`
error: using `Result.and_then(Ok)`, which is a no-op
- --> $DIR/bind_instead_of_map.rs:15:13
+ --> $DIR/bind_instead_of_map.rs:16:13
|
LL | let _ = x.and_then(Ok);
| ^^^^^^^^^^^^^^ help: use the expression directly: `x`
diff --git a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
index 537557f8b..e83eb4d60 100644
--- a/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
+++ b/src/tools/clippy/tests/ui/blanket_clippy_restriction_lints.stderr
@@ -4,8 +4,8 @@ error: restriction lints are not meant to be all enabled
LL | #![warn(clippy::restriction)]
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
= help: try enabling only the lints you really need
+ = note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
error: restriction lints are not meant to be all enabled
--> $DIR/blanket_clippy_restriction_lints.rs:5:9
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
index 9c1098dc4..2c8339cdd 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.fixed
@@ -14,6 +14,7 @@ fn main() {
// precedence
i32::from(a);
i32::from(!a);
+ i32::from(!a);
i32::from(a || b);
i32::from(cond(a, b));
i32::from(x + y < 4);
@@ -21,7 +22,12 @@ fn main() {
// if else if
if a {
123
- } else {i32::from(b)};
+ } else { i32::from(b) };
+
+ // if else if inverted
+ if a {
+ 123
+ } else { i32::from(!b) };
// Shouldn't lint
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
index 0c967dac6..5d9496f01 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.rs
@@ -17,6 +17,11 @@ fn main() {
} else {
0
};
+ if a {
+ 0
+ } else {
+ 1
+ };
if !a {
1
} else {
@@ -47,6 +52,15 @@ fn main() {
0
};
+ // if else if inverted
+ if a {
+ 123
+ } else if b {
+ 0
+ } else {
+ 1
+ };
+
// Shouldn't lint
if a {
diff --git a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
index 8647a9cff..4cb5531be 100644
--- a/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
+++ b/src/tools/clippy/tests/ui/bool_to_int_with_if.stderr
@@ -8,12 +8,24 @@ LL | | 0
LL | | };
| |_____^ help: replace with from: `i32::from(a)`
|
- = note: `-D clippy::bool-to-int-with-if` implied by `-D warnings`
= note: `a as i32` or `a.into()` can also be valid options
+ = note: `-D clippy::bool-to-int-with-if` implied by `-D warnings`
error: boolean to int conversion using if
--> $DIR/bool_to_int_with_if.rs:20:5
|
+LL | / if a {
+LL | | 0
+LL | | } else {
+LL | | 1
+LL | | };
+ | |_____^ help: replace with from: `i32::from(!a)`
+ |
+ = note: `!a as i32` or `(!a).into()` can also be valid options
+
+error: boolean to int conversion using if
+ --> $DIR/bool_to_int_with_if.rs:25:5
+ |
LL | / if !a {
LL | | 1
LL | | } else {
@@ -21,10 +33,10 @@ LL | | 0
LL | | };
| |_____^ help: replace with from: `i32::from(!a)`
|
- = note: `!a as i32` or `!a.into()` can also be valid options
+ = note: `!a as i32` or `(!a).into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:25:5
+ --> $DIR/bool_to_int_with_if.rs:30:5
|
LL | / if a || b {
LL | | 1
@@ -36,7 +48,7 @@ LL | | };
= note: `(a || b) as i32` or `(a || b).into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:30:5
+ --> $DIR/bool_to_int_with_if.rs:35:5
|
LL | / if cond(a, b) {
LL | | 1
@@ -48,7 +60,7 @@ LL | | };
= note: `cond(a, b) as i32` or `cond(a, b).into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:35:5
+ --> $DIR/bool_to_int_with_if.rs:40:5
|
LL | / if x + y < 4 {
LL | | 1
@@ -60,7 +72,7 @@ LL | | };
= note: `(x + y < 4) as i32` or `(x + y < 4).into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:44:12
+ --> $DIR/bool_to_int_with_if.rs:49:12
|
LL | } else if b {
| ____________^
@@ -68,17 +80,30 @@ LL | | 1
LL | | } else {
LL | | 0
LL | | };
- | |_____^ help: replace with from: `{i32::from(b)}`
+ | |_____^ help: replace with from: `{ i32::from(b) }`
|
= note: `b as i32` or `b.into()` can also be valid options
error: boolean to int conversion using if
- --> $DIR/bool_to_int_with_if.rs:102:5
+ --> $DIR/bool_to_int_with_if.rs:58:12
+ |
+LL | } else if b {
+ | ____________^
+LL | | 0
+LL | | } else {
+LL | | 1
+LL | | };
+ | |_____^ help: replace with from: `{ i32::from(!b) }`
+ |
+ = note: `!b as i32` or `(!b).into()` can also be valid options
+
+error: boolean to int conversion using if
+ --> $DIR/bool_to_int_with_if.rs:116:5
|
LL | if a { 1 } else { 0 }
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with from: `u8::from(a)`
|
= note: `a as u8` or `a.into()` can also be valid options
-error: aborting due to 7 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/borrow_box.rs b/src/tools/clippy/tests/ui/borrow_box.rs
index 35ed87b0f..3b5b6bf4c 100644
--- a/src/tools/clippy/tests/ui/borrow_box.rs
+++ b/src/tools/clippy/tests/ui/borrow_box.rs
@@ -1,7 +1,6 @@
#![deny(clippy::borrowed_box)]
-#![allow(clippy::disallowed_names)]
-#![allow(unused_variables)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_variables)]
+#![allow(clippy::uninlined_format_args, clippy::disallowed_names)]
use std::fmt::Display;
diff --git a/src/tools/clippy/tests/ui/borrow_box.stderr b/src/tools/clippy/tests/ui/borrow_box.stderr
index 3eac32815..99cb60a1e 100644
--- a/src/tools/clippy/tests/ui/borrow_box.stderr
+++ b/src/tools/clippy/tests/ui/borrow_box.stderr
@@ -1,5 +1,5 @@
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:21:14
+ --> $DIR/borrow_box.rs:20:14
|
LL | let foo: &Box<bool>;
| ^^^^^^^^^^ help: try: `&bool`
@@ -11,55 +11,55 @@ LL | #![deny(clippy::borrowed_box)]
| ^^^^^^^^^^^^^^^^^^^^
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:25:10
+ --> $DIR/borrow_box.rs:24:10
|
LL | foo: &'a Box<bool>,
| ^^^^^^^^^^^^^ help: try: `&'a bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:29:17
+ --> $DIR/borrow_box.rs:28:17
|
LL | fn test4(a: &Box<bool>);
| ^^^^^^^^^^ help: try: `&bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:95:25
+ --> $DIR/borrow_box.rs:94:25
|
LL | pub fn test14(_display: &Box<dyn Display>) {}
| ^^^^^^^^^^^^^^^^^ help: try: `&dyn Display`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:96:25
+ --> $DIR/borrow_box.rs:95:25
|
LL | pub fn test15(_display: &Box<dyn Display + Send>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:97:29
+ --> $DIR/borrow_box.rs:96:29
|
LL | pub fn test16<'a>(_display: &'a Box<dyn Display + 'a>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (dyn Display + 'a)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:99:25
+ --> $DIR/borrow_box.rs:98:25
|
LL | pub fn test17(_display: &Box<impl Display>) {}
| ^^^^^^^^^^^^^^^^^^ help: try: `&impl Display`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:100:25
+ --> $DIR/borrow_box.rs:99:25
|
LL | pub fn test18(_display: &Box<impl Display + Send>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(impl Display + Send)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:101:29
+ --> $DIR/borrow_box.rs:100:29
|
LL | pub fn test19<'a>(_display: &'a Box<impl Display + 'a>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&'a (impl Display + 'a)`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
- --> $DIR/borrow_box.rs:106:25
+ --> $DIR/borrow_box.rs:105:25
|
LL | pub fn test20(_display: &Box<(dyn Display + Send)>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&(dyn Display + Send)`
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
index 654a1ee7d..b0cab977a 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/enums.stderr
@@ -4,8 +4,8 @@ error: a `const` item with interior mutability should not be borrowed
LL | let _ = &UNFROZEN_VARIANT; //~ ERROR interior mutability
| ^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
= help: assign this const to a local or static variable, and use the variable here
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
error: a `const` item with interior mutability should not be borrowed
--> $DIR/enums.rs:37:18
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
index 9a908cf30..c87ad206c 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/others.stderr
@@ -4,8 +4,8 @@ error: a `const` item with interior mutability should not be borrowed
LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability
| ^^^^^^
|
- = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
= help: assign this const to a local or static variable, and use the variable here
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
error: a `const` item with interior mutability should not be borrowed
--> $DIR/others.rs:55:16
diff --git a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
index 8f26403ab..f34ae8814 100644
--- a/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
+++ b/src/tools/clippy/tests/ui/borrow_interior_mutable_const/traits.stderr
@@ -4,8 +4,8 @@ error: a `const` item with interior mutability should not be borrowed
LL | let _ = &Self::ATOMIC; //~ ERROR interior mutable
| ^^^^^^^^^^^^
|
- = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
= help: assign this const to a local or static variable, and use the variable here
+ = note: `-D clippy::borrow-interior-mutable-const` implied by `-D warnings`
error: a `const` item with interior mutability should not be borrowed
--> $DIR/traits.rs:26:18
diff --git a/src/tools/clippy/tests/ui/box_collection.rs b/src/tools/clippy/tests/ui/box_collection.rs
index 0780c8f05..4c9947b9a 100644
--- a/src/tools/clippy/tests/ui/box_collection.rs
+++ b/src/tools/clippy/tests/ui/box_collection.rs
@@ -15,7 +15,7 @@ macro_rules! boxit {
}
fn test_macro() {
- boxit!(Vec::new(), Vec<u8>);
+ boxit!(vec![1], Vec<u8>);
}
fn test1(foo: Box<Vec<bool>>) {}
@@ -50,7 +50,7 @@ fn test_local_not_linted() {
pub fn pub_test(foo: Box<Vec<bool>>) {}
pub fn pub_test_ret() -> Box<Vec<bool>> {
- Box::new(Vec::new())
+ Box::default()
}
fn main() {}
diff --git a/src/tools/clippy/tests/ui/box_collection.stderr b/src/tools/clippy/tests/ui/box_collection.stderr
index 2b28598de..40b6f9be6 100644
--- a/src/tools/clippy/tests/ui/box_collection.stderr
+++ b/src/tools/clippy/tests/ui/box_collection.stderr
@@ -4,8 +4,8 @@ error: you seem to be trying to use `Box<Vec<..>>`. Consider using just `Vec<..>
LL | fn test1(foo: Box<Vec<bool>>) {}
| ^^^^^^^^^^^^^^
|
- = note: `-D clippy::box-collection` implied by `-D warnings`
= help: `Vec<..>` is already on the heap, `Box<Vec<..>>` makes an extra allocation
+ = note: `-D clippy::box-collection` implied by `-D warnings`
error: you seem to be trying to use `Box<String>`. Consider using just `String`
--> $DIR/box_collection.rs:28:15
diff --git a/src/tools/clippy/tests/ui/box_default.fixed b/src/tools/clippy/tests/ui/box_default.fixed
new file mode 100644
index 000000000..911fa856a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/box_default.fixed
@@ -0,0 +1,57 @@
+// run-rustfix
+#![warn(clippy::box_default)]
+
+#[derive(Default)]
+struct ImplementsDefault;
+
+struct OwnDefault;
+
+impl OwnDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+macro_rules! outer {
+ ($e: expr) => {
+ $e
+ };
+}
+
+fn main() {
+ let _string: Box<String> = Box::default();
+ let _byte = Box::<u8>::default();
+ let _vec = Box::<std::vec::Vec<u8>>::default();
+ let _impl = Box::<ImplementsDefault>::default();
+ let _impl2 = Box::<ImplementsDefault>::default();
+ let _impl3: Box<ImplementsDefault> = Box::default();
+ let _own = Box::new(OwnDefault::default()); // should not lint
+ let _in_macro = outer!(Box::<std::string::String>::default());
+ let _string_default = outer!(Box::<std::string::String>::default());
+ let _vec2: Box<Vec<ImplementsDefault>> = Box::default();
+ let _vec3: Box<Vec<bool>> = Box::default();
+ let _vec4: Box<_> = Box::<std::vec::Vec<bool>>::default();
+ let _more = ret_ty_fn();
+ call_ty_fn(Box::default());
+}
+
+fn ret_ty_fn() -> Box<bool> {
+ Box::<bool>::default()
+}
+
+#[allow(clippy::boxed_local)]
+fn call_ty_fn(_b: Box<u8>) {
+ issue_9621_dyn_trait();
+}
+
+use std::io::{Read, Result};
+
+impl Read for ImplementsDefault {
+ fn read(&mut self, _: &mut [u8]) -> Result<usize> {
+ Ok(0)
+ }
+}
+
+fn issue_9621_dyn_trait() {
+ let _: Box<dyn Read> = Box::<ImplementsDefault>::default();
+}
diff --git a/src/tools/clippy/tests/ui/box_default.rs b/src/tools/clippy/tests/ui/box_default.rs
new file mode 100644
index 000000000..20019c2ee
--- /dev/null
+++ b/src/tools/clippy/tests/ui/box_default.rs
@@ -0,0 +1,57 @@
+// run-rustfix
+#![warn(clippy::box_default)]
+
+#[derive(Default)]
+struct ImplementsDefault;
+
+struct OwnDefault;
+
+impl OwnDefault {
+ fn default() -> Self {
+ Self
+ }
+}
+
+macro_rules! outer {
+ ($e: expr) => {
+ $e
+ };
+}
+
+fn main() {
+ let _string: Box<String> = Box::new(Default::default());
+ let _byte = Box::new(u8::default());
+ let _vec = Box::new(Vec::<u8>::new());
+ let _impl = Box::new(ImplementsDefault::default());
+ let _impl2 = Box::new(<ImplementsDefault as Default>::default());
+ let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
+ let _own = Box::new(OwnDefault::default()); // should not lint
+ let _in_macro = outer!(Box::new(String::new()));
+ let _string_default = outer!(Box::new(String::from("")));
+ let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
+ let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
+ let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
+ let _more = ret_ty_fn();
+ call_ty_fn(Box::new(u8::default()));
+}
+
+fn ret_ty_fn() -> Box<bool> {
+ Box::new(bool::default())
+}
+
+#[allow(clippy::boxed_local)]
+fn call_ty_fn(_b: Box<u8>) {
+ issue_9621_dyn_trait();
+}
+
+use std::io::{Read, Result};
+
+impl Read for ImplementsDefault {
+ fn read(&mut self, _: &mut [u8]) -> Result<usize> {
+ Ok(0)
+ }
+}
+
+fn issue_9621_dyn_trait() {
+ let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
+}
diff --git a/src/tools/clippy/tests/ui/box_default.stderr b/src/tools/clippy/tests/ui/box_default.stderr
new file mode 100644
index 000000000..5ea410331
--- /dev/null
+++ b/src/tools/clippy/tests/ui/box_default.stderr
@@ -0,0 +1,88 @@
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:22:32
+ |
+LL | let _string: Box<String> = Box::new(Default::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+ |
+ = note: `-D clippy::box-default` implied by `-D warnings`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:23:17
+ |
+LL | let _byte = Box::new(u8::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<u8>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:24:16
+ |
+LL | let _vec = Box::new(Vec::<u8>::new());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<u8>>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:25:17
+ |
+LL | let _impl = Box::new(ImplementsDefault::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:26:18
+ |
+LL | let _impl2 = Box::new(<ImplementsDefault as Default>::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:27:42
+ |
+LL | let _impl3: Box<ImplementsDefault> = Box::new(Default::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:29:28
+ |
+LL | let _in_macro = outer!(Box::new(String::new()));
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:30:34
+ |
+LL | let _string_default = outer!(Box::new(String::from("")));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::string::String>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:31:46
+ |
+LL | let _vec2: Box<Vec<ImplementsDefault>> = Box::new(vec![]);
+ | ^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:32:33
+ |
+LL | let _vec3: Box<Vec<bool>> = Box::new(Vec::from([]));
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:33:25
+ |
+LL | let _vec4: Box<_> = Box::new(Vec::from([false; 0]));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<std::vec::Vec<bool>>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:35:16
+ |
+LL | call_ty_fn(Box::new(u8::default()));
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:39:5
+ |
+LL | Box::new(bool::default())
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
+
+error: `Box::new(_)` of default value
+ --> $DIR/box_default.rs:56:28
+ |
+LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
+
+error: aborting due to 14 previous errors
+
diff --git a/src/tools/clippy/tests/ui/box_default_no_std.rs b/src/tools/clippy/tests/ui/box_default_no_std.rs
new file mode 100644
index 000000000..4326abc9a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/box_default_no_std.rs
@@ -0,0 +1,33 @@
+#![feature(lang_items, start, libc)]
+#![warn(clippy::box_default)]
+#![no_std]
+
+pub struct NotBox<T> {
+ _value: T,
+}
+
+impl<T> NotBox<T> {
+ pub fn new(value: T) -> Self {
+ Self { _value: value }
+ }
+}
+
+impl<T: Default> Default for NotBox<T> {
+ fn default() -> Self {
+ Self::new(T::default())
+ }
+}
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ let _p = NotBox::new(isize::default());
+ 0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+ loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs
index 12f550d9c..6a63008b5 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.rs
@@ -1,5 +1,6 @@
-#![allow(dead_code, clippy::equatable_if_let)]
#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![allow(dead_code)]
+#![allow(clippy::equatable_if_let, clippy::uninlined_format_args)]
// This tests the branches_sharing_code lint at the end of blocks
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
index 5e1a68d21..b9b113dc0 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_bottom.stderr
@@ -1,5 +1,5 @@
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:30:5
+ --> $DIR/shared_at_bottom.rs:31:5
|
LL | / let result = false;
LL | | println!("Block end!");
@@ -7,12 +7,12 @@ LL | | result
LL | | };
| |_____^
|
+ = note: the end suggestion probably needs some adjustments to use the expression result correctly
note: the lint level is defined here
- --> $DIR/shared_at_bottom.rs:2:36
+ --> $DIR/shared_at_bottom.rs:1:36
|
LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the end suggestion probably needs some adjustments to use the expression result correctly
help: consider moving these statements after the if
|
LL ~ }
@@ -22,7 +22,7 @@ LL ~ result;
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:48:5
+ --> $DIR/shared_at_bottom.rs:49:5
|
LL | / println!("Same end of block");
LL | | }
@@ -35,7 +35,7 @@ LL + println!("Same end of block");
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:65:5
+ --> $DIR/shared_at_bottom.rs:66:5
|
LL | / println!(
LL | | "I'm moveable because I know: `outer_scope_value`: '{}'",
@@ -54,7 +54,7 @@ LL + );
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:77:9
+ --> $DIR/shared_at_bottom.rs:78:9
|
LL | / println!("Hello World");
LL | | }
@@ -67,7 +67,7 @@ LL + println!("Hello World");
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:93:5
+ --> $DIR/shared_at_bottom.rs:94:5
|
LL | / let later_used_value = "A string value";
LL | | println!("{}", later_used_value);
@@ -84,7 +84,7 @@ LL + println!("{}", later_used_value);
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:106:5
+ --> $DIR/shared_at_bottom.rs:107:5
|
LL | / let simple_examples = "I now identify as a &str :)";
LL | | println!("This is the new simple_example: {}", simple_examples);
@@ -100,7 +100,7 @@ LL + println!("This is the new simple_example: {}", simple_examples);
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:171:5
+ --> $DIR/shared_at_bottom.rs:172:5
|
LL | / x << 2
LL | | };
@@ -114,7 +114,7 @@ LL ~ x << 2;
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:178:5
+ --> $DIR/shared_at_bottom.rs:179:5
|
LL | / x * 4
LL | | }
@@ -128,7 +128,7 @@ LL + x * 4
|
error: all if blocks contain the same code at the end
- --> $DIR/shared_at_bottom.rs:190:44
+ --> $DIR/shared_at_bottom.rs:191:44
|
LL | if x == 17 { b = 1; a = 0x99; } else { a = 0x99; }
| ^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
index bdeb0a395..9e0b99f16 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.rs
@@ -1,5 +1,6 @@
-#![allow(dead_code, clippy::mixed_read_write_in_expression)]
-#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+#![allow(dead_code)]
+#![allow(clippy::mixed_read_write_in_expression, clippy::uninlined_format_args)]
// This tests the branches_sharing_code lint at the start of blocks
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
index d890b12ec..3e3242a75 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top.stderr
@@ -1,15 +1,15 @@
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:10:5
+ --> $DIR/shared_at_top.rs:11:5
|
LL | / if true {
LL | | println!("Hello World!");
| |_________________________________^
|
note: the lint level is defined here
- --> $DIR/shared_at_top.rs:2:36
+ --> $DIR/shared_at_top.rs:1:9
|
-LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider moving these statements before the if
|
LL ~ println!("Hello World!");
@@ -17,7 +17,7 @@ LL + if true {
|
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:19:5
+ --> $DIR/shared_at_top.rs:20:5
|
LL | / if x == 0 {
LL | | let y = 9;
@@ -35,7 +35,7 @@ LL + if x == 0 {
|
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:40:5
+ --> $DIR/shared_at_top.rs:41:5
|
LL | / let _ = if x == 7 {
LL | | let y = 16;
@@ -48,7 +48,7 @@ LL + let _ = if x == 7 {
|
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:58:5
+ --> $DIR/shared_at_top.rs:59:5
|
LL | / if x == 10 {
LL | | let used_value_name = "Different type";
@@ -64,7 +64,7 @@ LL + if x == 10 {
|
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:72:5
+ --> $DIR/shared_at_top.rs:73:5
|
LL | / if x == 11 {
LL | | let can_be_overridden = "Move me";
@@ -80,7 +80,7 @@ LL + if x == 11 {
|
error: all if blocks contain the same code at the start
- --> $DIR/shared_at_top.rs:88:5
+ --> $DIR/shared_at_top.rs:89:5
|
LL | / if x == 2020 {
LL | | println!("This should trigger the `SHARED_CODE_IN_IF_BLOCKS` lint.");
@@ -95,7 +95,7 @@ LL + if x == 2020 {
|
error: this `if` has identical blocks
- --> $DIR/shared_at_top.rs:96:18
+ --> $DIR/shared_at_top.rs:97:18
|
LL | if x == 2019 {
| __________________^
@@ -103,19 +103,19 @@ LL | | println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
LL | | } else {
| |_____^
|
-note: the lint level is defined here
- --> $DIR/shared_at_top.rs:2:9
- |
-LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: same as this
- --> $DIR/shared_at_top.rs:98:12
+ --> $DIR/shared_at_top.rs:99:12
|
LL | } else {
| ____________^
LL | | println!("This should trigger `IS_SAME_THAN_ELSE` as usual");
LL | | }
| |_____^
+note: the lint level is defined here
+ --> $DIR/shared_at_top.rs:1:40
+ |
+LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
index deefdad32..93b8c6e10 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs
@@ -1,5 +1,6 @@
+#![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
#![allow(dead_code)]
-#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![allow(clippy::uninlined_format_args)]
// branches_sharing_code at the top and bottom of the if blocks
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
index a270f637f..ccd697a42 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr
@@ -1,5 +1,5 @@
error: all if blocks contain the same code at both the start and the end
- --> $DIR/shared_at_top_and_bottom.rs:16:5
+ --> $DIR/shared_at_top_and_bottom.rs:17:5
|
LL | / if x == 7 {
LL | | let t = 7;
@@ -7,17 +7,17 @@ LL | | let _overlap_start = t * 2;
LL | | let _overlap_end = 2 * t;
| |_________________________________^
|
-note: the lint level is defined here
- --> $DIR/shared_at_top_and_bottom.rs:2:36
- |
-LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: this code is shared at the end
- --> $DIR/shared_at_top_and_bottom.rs:28:5
+ --> $DIR/shared_at_top_and_bottom.rs:29:5
|
LL | / let _u = 9;
LL | | }
| |_____^
+note: the lint level is defined here
+ --> $DIR/shared_at_top_and_bottom.rs:1:9
+ |
+LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: consider moving these statements before the if
|
LL ~ let t = 7;
@@ -32,7 +32,7 @@ LL + let _u = 9;
|
error: all if blocks contain the same code at both the start and the end
- --> $DIR/shared_at_top_and_bottom.rs:32:5
+ --> $DIR/shared_at_top_and_bottom.rs:33:5
|
LL | / if x == 99 {
LL | | let r = 7;
@@ -41,7 +41,7 @@ LL | | let _overlap_middle = r * r;
| |____________________________________^
|
note: this code is shared at the end
- --> $DIR/shared_at_top_and_bottom.rs:43:5
+ --> $DIR/shared_at_top_and_bottom.rs:44:5
|
LL | / let _overlap_end = r * r * r;
LL | | let z = "end";
@@ -63,7 +63,7 @@ LL + let z = "end";
|
error: all if blocks contain the same code at both the start and the end
- --> $DIR/shared_at_top_and_bottom.rs:61:5
+ --> $DIR/shared_at_top_and_bottom.rs:62:5
|
LL | / if (x > 7 && y < 13) || (x + y) % 2 == 1 {
LL | | let a = 0xcafe;
@@ -72,7 +72,7 @@ LL | | let e_id = gen_id(a, b);
| |________________________________^
|
note: this code is shared at the end
- --> $DIR/shared_at_top_and_bottom.rs:81:5
+ --> $DIR/shared_at_top_and_bottom.rs:82:5
|
LL | / let pack = DataPack {
LL | | id: e_id,
@@ -102,14 +102,14 @@ LL + process_data(pack);
|
error: all if blocks contain the same code at both the start and the end
- --> $DIR/shared_at_top_and_bottom.rs:94:5
+ --> $DIR/shared_at_top_and_bottom.rs:95:5
|
LL | / let _ = if x == 7 {
LL | | let _ = 19;
| |___________________^
|
note: this code is shared at the end
- --> $DIR/shared_at_top_and_bottom.rs:103:5
+ --> $DIR/shared_at_top_and_bottom.rs:104:5
|
LL | / x << 2
LL | | };
@@ -127,14 +127,14 @@ LL ~ x << 2;
|
error: all if blocks contain the same code at both the start and the end
- --> $DIR/shared_at_top_and_bottom.rs:106:5
+ --> $DIR/shared_at_top_and_bottom.rs:107:5
|
LL | / if x == 9 {
LL | | let _ = 17;
| |___________________^
|
note: this code is shared at the end
- --> $DIR/shared_at_top_and_bottom.rs:115:5
+ --> $DIR/shared_at_top_and_bottom.rs:116:5
|
LL | / x * 4
LL | | }
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
index a26141be2..2d6055eb6 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.rs
@@ -1,5 +1,6 @@
-#![allow(dead_code, clippy::mixed_read_write_in_expression)]
-#![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
+#![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+#![allow(dead_code)]
+#![allow(clippy::mixed_read_write_in_expression, clippy::uninlined_format_args)]
// This tests valid if blocks that shouldn't trigger the lint
diff --git a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
index a815995e7..ce7fff012 100644
--- a/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
+++ b/src/tools/clippy/tests/ui/branches_sharing_code/valid_if_blocks.stderr
@@ -1,26 +1,26 @@
error: this `if` has identical blocks
- --> $DIR/valid_if_blocks.rs:104:14
+ --> $DIR/valid_if_blocks.rs:105:14
|
LL | if false {
| ______________^
LL | | } else {
| |_____^
|
-note: the lint level is defined here
- --> $DIR/valid_if_blocks.rs:2:9
- |
-LL | #![deny(clippy::if_same_then_else, clippy::branches_sharing_code)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
note: same as this
- --> $DIR/valid_if_blocks.rs:105:12
+ --> $DIR/valid_if_blocks.rs:106:12
|
LL | } else {
| ____________^
LL | | }
| |_____^
+note: the lint level is defined here
+ --> $DIR/valid_if_blocks.rs:1:40
+ |
+LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `if` has identical blocks
- --> $DIR/valid_if_blocks.rs:115:15
+ --> $DIR/valid_if_blocks.rs:116:15
|
LL | if x == 0 {
| _______________^
@@ -31,7 +31,7 @@ LL | | } else {
| |_____^
|
note: same as this
- --> $DIR/valid_if_blocks.rs:119:12
+ --> $DIR/valid_if_blocks.rs:120:12
|
LL | } else {
| ____________^
@@ -42,19 +42,19 @@ LL | | }
| |_____^
error: this `if` has identical blocks
- --> $DIR/valid_if_blocks.rs:126:23
+ --> $DIR/valid_if_blocks.rs:127:23
|
LL | let _ = if x == 6 { 7 } else { 7 };
| ^^^^^
|
note: same as this
- --> $DIR/valid_if_blocks.rs:126:34
+ --> $DIR/valid_if_blocks.rs:127:34
|
LL | let _ = if x == 6 { 7 } else { 7 };
| ^^^^^
error: this `if` has identical blocks
- --> $DIR/valid_if_blocks.rs:132:23
+ --> $DIR/valid_if_blocks.rs:133:23
|
LL | } else if x == 68 {
| _______________________^
@@ -66,7 +66,7 @@ LL | | } else {
| |_____^
|
note: same as this
- --> $DIR/valid_if_blocks.rs:137:12
+ --> $DIR/valid_if_blocks.rs:138:12
|
LL | } else {
| ____________^
@@ -78,7 +78,7 @@ LL | | };
| |_____^
error: this `if` has identical blocks
- --> $DIR/valid_if_blocks.rs:146:23
+ --> $DIR/valid_if_blocks.rs:147:23
|
LL | } else if x == 68 {
| _______________________^
@@ -88,7 +88,7 @@ LL | | } else {
| |_____^
|
note: same as this
- --> $DIR/valid_if_blocks.rs:149:12
+ --> $DIR/valid_if_blocks.rs:150:12
|
LL | } else {
| ____________^
diff --git a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
index 5d9a043ed..a28dd8bd5 100644
--- a/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/case_sensitive_file_extension_comparisons.stderr
@@ -4,8 +4,8 @@ error: case-sensitive file extension comparison
LL | filename.ends_with(".rs")
| ^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
= help: consider using a case-insensitive comparison instead
+ = note: `-D clippy::case-sensitive-file-extension-comparisons` implied by `-D warnings`
error: case-sensitive file extension comparison
--> $DIR/case_sensitive_file_extension_comparisons.rs:17:27
diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
index 7ecefd7b1..e6bf944c7 100644
--- a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
+++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.fixed
@@ -1,5 +1,8 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::cast_abs_to_unsigned)]
+#![allow(clippy::uninlined_format_args, unused)]
fn main() {
let x: i32 = -42;
@@ -29,3 +32,17 @@ fn main() {
let _ = (x as i64 - y as i64).unsigned_abs() as u32;
}
+
+fn msrv_1_50() {
+ #![clippy::msrv = "1.50"]
+
+ let x: i32 = 10;
+ assert_eq!(10u32, x.abs() as u32);
+}
+
+fn msrv_1_51() {
+ #![clippy::msrv = "1.51"]
+
+ let x: i32 = 10;
+ assert_eq!(10u32, x.unsigned_abs());
+}
diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
index 30c603fca..c87320b52 100644
--- a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
+++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.rs
@@ -1,5 +1,8 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::cast_abs_to_unsigned)]
+#![allow(clippy::uninlined_format_args, unused)]
fn main() {
let x: i32 = -42;
@@ -29,3 +32,17 @@ fn main() {
let _ = (x as i64 - y as i64).abs() as u32;
}
+
+fn msrv_1_50() {
+ #![clippy::msrv = "1.50"]
+
+ let x: i32 = 10;
+ assert_eq!(10u32, x.abs() as u32);
+}
+
+fn msrv_1_51() {
+ #![clippy::msrv = "1.51"]
+
+ let x: i32 = 10;
+ assert_eq!(10u32, x.abs() as u32);
+}
diff --git a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr
index 045537745..1b39c554b 100644
--- a/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr
+++ b/src/tools/clippy/tests/ui/cast_abs_to_unsigned.stderr
@@ -1,5 +1,5 @@
error: casting the result of `i32::abs()` to u32
- --> $DIR/cast_abs_to_unsigned.rs:6:18
+ --> $DIR/cast_abs_to_unsigned.rs:9:18
|
LL | let y: u32 = x.abs() as u32;
| ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()`
@@ -7,100 +7,106 @@ LL | let y: u32 = x.abs() as u32;
= note: `-D clippy::cast-abs-to-unsigned` implied by `-D warnings`
error: casting the result of `i32::abs()` to usize
- --> $DIR/cast_abs_to_unsigned.rs:10:20
+ --> $DIR/cast_abs_to_unsigned.rs:13:20
|
LL | let _: usize = a.abs() as usize;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i32::abs()` to usize
- --> $DIR/cast_abs_to_unsigned.rs:11:20
+ --> $DIR/cast_abs_to_unsigned.rs:14:20
|
LL | let _: usize = a.abs() as _;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i32::abs()` to usize
- --> $DIR/cast_abs_to_unsigned.rs:12:13
+ --> $DIR/cast_abs_to_unsigned.rs:15:13
|
LL | let _ = a.abs() as usize;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to usize
- --> $DIR/cast_abs_to_unsigned.rs:15:13
+ --> $DIR/cast_abs_to_unsigned.rs:18:13
|
LL | let _ = a.abs() as usize;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u8
- --> $DIR/cast_abs_to_unsigned.rs:16:13
+ --> $DIR/cast_abs_to_unsigned.rs:19:13
|
LL | let _ = a.abs() as u8;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u16
- --> $DIR/cast_abs_to_unsigned.rs:17:13
+ --> $DIR/cast_abs_to_unsigned.rs:20:13
|
LL | let _ = a.abs() as u16;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u32
- --> $DIR/cast_abs_to_unsigned.rs:18:13
+ --> $DIR/cast_abs_to_unsigned.rs:21:13
|
LL | let _ = a.abs() as u32;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u64
- --> $DIR/cast_abs_to_unsigned.rs:19:13
+ --> $DIR/cast_abs_to_unsigned.rs:22:13
|
LL | let _ = a.abs() as u64;
| ^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u128
- --> $DIR/cast_abs_to_unsigned.rs:20:13
+ --> $DIR/cast_abs_to_unsigned.rs:23:13
|
LL | let _ = a.abs() as u128;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to usize
- --> $DIR/cast_abs_to_unsigned.rs:23:13
+ --> $DIR/cast_abs_to_unsigned.rs:26:13
|
LL | let _ = a.abs() as usize;
| ^^^^^^^^^^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to u8
- --> $DIR/cast_abs_to_unsigned.rs:24:13
+ --> $DIR/cast_abs_to_unsigned.rs:27:13
|
LL | let _ = a.abs() as u8;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to u16
- --> $DIR/cast_abs_to_unsigned.rs:25:13
+ --> $DIR/cast_abs_to_unsigned.rs:28:13
|
LL | let _ = a.abs() as u16;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to u32
- --> $DIR/cast_abs_to_unsigned.rs:26:13
+ --> $DIR/cast_abs_to_unsigned.rs:29:13
|
LL | let _ = a.abs() as u32;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to u64
- --> $DIR/cast_abs_to_unsigned.rs:27:13
+ --> $DIR/cast_abs_to_unsigned.rs:30:13
|
LL | let _ = a.abs() as u64;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `isize::abs()` to u128
- --> $DIR/cast_abs_to_unsigned.rs:28:13
+ --> $DIR/cast_abs_to_unsigned.rs:31:13
|
LL | let _ = a.abs() as u128;
| ^^^^^^^ help: replace with: `a.unsigned_abs()`
error: casting the result of `i64::abs()` to u32
- --> $DIR/cast_abs_to_unsigned.rs:30:13
+ --> $DIR/cast_abs_to_unsigned.rs:33:13
|
LL | let _ = (x as i64 - y as i64).abs() as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(x as i64 - y as i64).unsigned_abs()`
-error: aborting due to 17 previous errors
+error: casting the result of `i32::abs()` to u32
+ --> $DIR/cast_abs_to_unsigned.rs:47:23
+ |
+LL | assert_eq!(10u32, x.abs() as u32);
+ | ^^^^^^^^^^^^^^ help: replace with: `x.unsigned_abs()`
+
+error: aborting due to 18 previous errors
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
index 9e2da45c3..af13b755e 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.fixed
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
@@ -40,3 +41,15 @@ mod cast_lossless_in_impl {
}
}
}
+
+fn msrv_1_27() {
+ #![clippy::msrv = "1.27"]
+
+ let _ = true as u8;
+}
+
+fn msrv_1_28() {
+ #![clippy::msrv = "1.28"]
+
+ let _ = u8::from(true);
+}
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.rs b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
index b6f6c59a0..3b06af899 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.rs
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.rs
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
@@ -40,3 +41,15 @@ mod cast_lossless_in_impl {
}
}
}
+
+fn msrv_1_27() {
+ #![clippy::msrv = "1.27"]
+
+ let _ = true as u8;
+}
+
+fn msrv_1_28() {
+ #![clippy::msrv = "1.28"]
+
+ let _ = true as u8;
+}
diff --git a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
index 6b1483360..768b033d1 100644
--- a/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
+++ b/src/tools/clippy/tests/ui/cast_lossless_bool.stderr
@@ -1,5 +1,5 @@
error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
- --> $DIR/cast_lossless_bool.rs:8:13
+ --> $DIR/cast_lossless_bool.rs:9:13
|
LL | let _ = true as u8;
| ^^^^^^^^^^ help: try: `u8::from(true)`
@@ -7,76 +7,82 @@ LL | let _ = true as u8;
= note: `-D clippy::cast-lossless` implied by `-D warnings`
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
- --> $DIR/cast_lossless_bool.rs:9:13
+ --> $DIR/cast_lossless_bool.rs:10:13
|
LL | let _ = true as u16;
| ^^^^^^^^^^^ help: try: `u16::from(true)`
error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)`
- --> $DIR/cast_lossless_bool.rs:10:13
+ --> $DIR/cast_lossless_bool.rs:11:13
|
LL | let _ = true as u32;
| ^^^^^^^^^^^ help: try: `u32::from(true)`
error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)`
- --> $DIR/cast_lossless_bool.rs:11:13
+ --> $DIR/cast_lossless_bool.rs:12:13
|
LL | let _ = true as u64;
| ^^^^^^^^^^^ help: try: `u64::from(true)`
error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)`
- --> $DIR/cast_lossless_bool.rs:12:13
+ --> $DIR/cast_lossless_bool.rs:13:13
|
LL | let _ = true as u128;
| ^^^^^^^^^^^^ help: try: `u128::from(true)`
error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)`
- --> $DIR/cast_lossless_bool.rs:13:13
+ --> $DIR/cast_lossless_bool.rs:14:13
|
LL | let _ = true as usize;
| ^^^^^^^^^^^^^ help: try: `usize::from(true)`
error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)`
- --> $DIR/cast_lossless_bool.rs:15:13
+ --> $DIR/cast_lossless_bool.rs:16:13
|
LL | let _ = true as i8;
| ^^^^^^^^^^ help: try: `i8::from(true)`
error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)`
- --> $DIR/cast_lossless_bool.rs:16:13
+ --> $DIR/cast_lossless_bool.rs:17:13
|
LL | let _ = true as i16;
| ^^^^^^^^^^^ help: try: `i16::from(true)`
error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)`
- --> $DIR/cast_lossless_bool.rs:17:13
+ --> $DIR/cast_lossless_bool.rs:18:13
|
LL | let _ = true as i32;
| ^^^^^^^^^^^ help: try: `i32::from(true)`
error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)`
- --> $DIR/cast_lossless_bool.rs:18:13
+ --> $DIR/cast_lossless_bool.rs:19:13
|
LL | let _ = true as i64;
| ^^^^^^^^^^^ help: try: `i64::from(true)`
error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)`
- --> $DIR/cast_lossless_bool.rs:19:13
+ --> $DIR/cast_lossless_bool.rs:20:13
|
LL | let _ = true as i128;
| ^^^^^^^^^^^^ help: try: `i128::from(true)`
error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)`
- --> $DIR/cast_lossless_bool.rs:20:13
+ --> $DIR/cast_lossless_bool.rs:21:13
|
LL | let _ = true as isize;
| ^^^^^^^^^^^^^ help: try: `isize::from(true)`
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
- --> $DIR/cast_lossless_bool.rs:23:13
+ --> $DIR/cast_lossless_bool.rs:24:13
|
LL | let _ = (true | false) as u16;
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
-error: aborting due to 13 previous errors
+error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
+ --> $DIR/cast_lossless_bool.rs:54:13
+ |
+LL | let _ = true as u8;
+ | ^^^^^^^^^^ help: try: `u8::from(true)`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/cast_nan_to_int.rs b/src/tools/clippy/tests/ui/cast_nan_to_int.rs
new file mode 100644
index 000000000..287c5aa21
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cast_nan_to_int.rs
@@ -0,0 +1,18 @@
+#![warn(clippy::cast_nan_to_int)]
+#![allow(clippy::eq_op)]
+
+fn main() {
+ let _ = (0.0_f32 / -0.0) as usize;
+ let _ = (f64::INFINITY * -0.0) as usize;
+ let _ = (0.0 * f32::INFINITY) as usize;
+
+ let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize;
+ let _ = (f32::INFINITY - f32::INFINITY) as usize;
+ let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize;
+
+ // those won't be linted:
+ let _ = (1.0_f32 / 0.0) as usize;
+ let _ = (f32::INFINITY * f32::NEG_INFINITY) as usize;
+ let _ = (f32::INFINITY - f32::NEG_INFINITY) as usize;
+ let _ = (f64::INFINITY - 0.0) as usize;
+}
diff --git a/src/tools/clippy/tests/ui/cast_nan_to_int.stderr b/src/tools/clippy/tests/ui/cast_nan_to_int.stderr
new file mode 100644
index 000000000..3539be75a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/cast_nan_to_int.stderr
@@ -0,0 +1,51 @@
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:5:13
+ |
+LL | let _ = (0.0_f32 / -0.0) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+ = note: `-D clippy::cast-nan-to-int` implied by `-D warnings`
+
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:6:13
+ |
+LL | let _ = (f64::INFINITY * -0.0) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:7:13
+ |
+LL | let _ = (0.0 * f32::INFINITY) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:9:13
+ |
+LL | let _ = (f64::INFINITY + f64::NEG_INFINITY) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:10:13
+ |
+LL | let _ = (f32::INFINITY - f32::INFINITY) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+
+error: casting a known NaN to usize
+ --> $DIR/cast_nan_to_int.rs:11:13
+ |
+LL | let _ = (f32::INFINITY / f32::NEG_INFINITY) as usize;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: this always evaluates to 0
+
+error: aborting due to 6 previous errors
+
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
index 061a4ab9b..8a5645b22 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.fixed
@@ -1,5 +1,5 @@
// run-rustfix
-#![feature(stmt_expr_attributes)]
+#![feature(stmt_expr_attributes, custom_inner_attributes)]
#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)]
#![warn(clippy::deprecated_cfg_attr)]
@@ -29,3 +29,17 @@ mod foo {
pub fn f() {}
}
+
+fn msrv_1_29() {
+ #![clippy::msrv = "1.29"]
+
+ #[cfg_attr(rustfmt, rustfmt::skip)]
+ 1+29;
+}
+
+fn msrv_1_30() {
+ #![clippy::msrv = "1.30"]
+
+ #[rustfmt::skip]
+ 1+30;
+}
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
index 035169fab..2fb140efa 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.rs
@@ -1,5 +1,5 @@
// run-rustfix
-#![feature(stmt_expr_attributes)]
+#![feature(stmt_expr_attributes, custom_inner_attributes)]
#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)]
#![warn(clippy::deprecated_cfg_attr)]
@@ -29,3 +29,17 @@ mod foo {
pub fn f() {}
}
+
+fn msrv_1_29() {
+ #![clippy::msrv = "1.29"]
+
+ #[cfg_attr(rustfmt, rustfmt::skip)]
+ 1+29;
+}
+
+fn msrv_1_30() {
+ #![clippy::msrv = "1.30"]
+
+ #[cfg_attr(rustfmt, rustfmt::skip)]
+ 1+30;
+}
diff --git a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.stderr b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.stderr
index c1efd47db..08df7b2b3 100644
--- a/src/tools/clippy/tests/ui/cfg_attr_rustfmt.stderr
+++ b/src/tools/clippy/tests/ui/cfg_attr_rustfmt.stderr
@@ -12,5 +12,11 @@ error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes
LL | #[cfg_attr(rustfmt, rustfmt_skip)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]`
-error: aborting due to 2 previous errors
+error: `cfg_attr` is deprecated for rustfmt and got replaced by tool attributes
+ --> $DIR/cfg_attr_rustfmt.rs:43:5
+ |
+LL | #[cfg_attr(rustfmt, rustfmt::skip)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `#[rustfmt::skip]`
+
+error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/char_lit_as_u8.stderr b/src/tools/clippy/tests/ui/char_lit_as_u8.stderr
index b9836d2f2..39fc9d6dd 100644
--- a/src/tools/clippy/tests/ui/char_lit_as_u8.stderr
+++ b/src/tools/clippy/tests/ui/char_lit_as_u8.stderr
@@ -4,8 +4,8 @@ error: casting a character literal to `u8` truncates
LL | let _ = '❤' as u8; // no suggestion, since a byte literal won't work.
| ^^^^^^^^^
|
- = note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
= note: `char` is four bytes wide, but `u8` is a single byte
+ = note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.stderr b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.stderr
index bf7cb1607..586174c50 100644
--- a/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.stderr
+++ b/src/tools/clippy/tests/ui/char_lit_as_u8_suggestions.stderr
@@ -4,8 +4,8 @@ error: casting a character literal to `u8` truncates
LL | let _ = 'a' as u8;
| ^^^^^^^^^ help: use a byte literal instead: `b'a'`
|
- = note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
= note: `char` is four bytes wide, but `u8` is a single byte
+ = note: `-D clippy::char-lit-as-u8` implied by `-D warnings`
error: casting a character literal to `u8` truncates
--> $DIR/char_lit_as_u8_suggestions.rs:7:13
diff --git a/src/tools/clippy/tests/ui/checked_conversions.fixed b/src/tools/clippy/tests/ui/checked_conversions.fixed
index cb7100bc9..f936957cb 100644
--- a/src/tools/clippy/tests/ui/checked_conversions.fixed
+++ b/src/tools/clippy/tests/ui/checked_conversions.fixed
@@ -1,7 +1,9 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(
clippy::cast_lossless,
+ unused,
// Int::max_value will be deprecated in the future
deprecated,
)]
@@ -76,4 +78,18 @@ pub const fn issue_8898(i: u32) -> bool {
i <= i32::MAX as u32
}
+fn msrv_1_33() {
+ #![clippy::msrv = "1.33"]
+
+ let value: i64 = 33;
+ let _ = value <= (u32::MAX as i64) && value >= 0;
+}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let value: i64 = 34;
+ let _ = u32::try_from(value).is_ok();
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/checked_conversions.rs b/src/tools/clippy/tests/ui/checked_conversions.rs
index ed4e06923..77aec713f 100644
--- a/src/tools/clippy/tests/ui/checked_conversions.rs
+++ b/src/tools/clippy/tests/ui/checked_conversions.rs
@@ -1,7 +1,9 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(
clippy::cast_lossless,
+ unused,
// Int::max_value will be deprecated in the future
deprecated,
)]
@@ -76,4 +78,18 @@ pub const fn issue_8898(i: u32) -> bool {
i <= i32::MAX as u32
}
+fn msrv_1_33() {
+ #![clippy::msrv = "1.33"]
+
+ let value: i64 = 33;
+ let _ = value <= (u32::MAX as i64) && value >= 0;
+}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let value: i64 = 34;
+ let _ = value <= (u32::MAX as i64) && value >= 0;
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/checked_conversions.stderr b/src/tools/clippy/tests/ui/checked_conversions.stderr
index 2e5180405..b2bf7af8d 100644
--- a/src/tools/clippy/tests/ui/checked_conversions.stderr
+++ b/src/tools/clippy/tests/ui/checked_conversions.stderr
@@ -1,5 +1,5 @@
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:15:13
+ --> $DIR/checked_conversions.rs:17:13
|
LL | let _ = value <= (u32::max_value() as i64) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
@@ -7,94 +7,100 @@ LL | let _ = value <= (u32::max_value() as i64) && value >= 0;
= note: `-D clippy::checked-conversions` implied by `-D warnings`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:16:13
+ --> $DIR/checked_conversions.rs:18:13
|
LL | let _ = value <= (u32::MAX as i64) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:20:13
+ --> $DIR/checked_conversions.rs:22:13
|
LL | let _ = value <= i64::from(u16::max_value()) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:21:13
+ --> $DIR/checked_conversions.rs:23:13
|
LL | let _ = value <= i64::from(u16::MAX) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:25:13
+ --> $DIR/checked_conversions.rs:27:13
|
LL | let _ = value <= (u8::max_value() as isize) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:26:13
+ --> $DIR/checked_conversions.rs:28:13
|
LL | let _ = value <= (u8::MAX as isize) && value >= 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:32:13
+ --> $DIR/checked_conversions.rs:34:13
|
LL | let _ = value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:33:13
+ --> $DIR/checked_conversions.rs:35:13
|
LL | let _ = value <= (i32::MAX as i64) && value >= (i32::MIN as i64);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:37:13
+ --> $DIR/checked_conversions.rs:39:13
|
LL | let _ = value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:38:13
+ --> $DIR/checked_conversions.rs:40:13
|
LL | let _ = value <= i64::from(i16::MAX) && value >= i64::from(i16::MIN);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:44:13
+ --> $DIR/checked_conversions.rs:46:13
|
LL | let _ = value <= i32::max_value() as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:45:13
+ --> $DIR/checked_conversions.rs:47:13
|
LL | let _ = value <= i32::MAX as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:49:13
+ --> $DIR/checked_conversions.rs:51:13
|
LL | let _ = value <= isize::max_value() as usize && value as i32 == 5;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:50:13
+ --> $DIR/checked_conversions.rs:52:13
|
LL | let _ = value <= isize::MAX as usize && value as i32 == 5;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:54:13
+ --> $DIR/checked_conversions.rs:56:13
|
LL | let _ = value <= u16::max_value() as u32 && value as i32 == 5;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
error: checked cast can be simplified
- --> $DIR/checked_conversions.rs:55:13
+ --> $DIR/checked_conversions.rs:57:13
|
LL | let _ = value <= u16::MAX as u32 && value as i32 == 5;
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
-error: aborting due to 16 previous errors
+error: checked cast can be simplified
+ --> $DIR/checked_conversions.rs:92:13
+ |
+LL | let _ = value <= (u32::MAX as i64) && value >= 0;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
+
+error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
index 46c6f6970..d44d5072e 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/complex_conditionals.stderr
@@ -6,12 +6,12 @@ LL | if x.is_ok() && y.is_err() {
LL | x.unwrap(); // unnecessary
| ^^^^^^^^^^
|
+ = help: try using `if let` or `match`
note: the lint level is defined here
--> $DIR/complex_conditionals.rs:1:35
|
LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: try using `if let` or `match`
error: this call to `unwrap_err()` will always panic
--> $DIR/complex_conditionals.rs:9:9
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
index 4eb999e18..42ed232d1 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.fixed
@@ -1,5 +1,8 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::cloned_instead_of_copied)]
+#![allow(unused)]
fn main() {
// yay
@@ -13,3 +16,24 @@ fn main() {
let _ = [String::new()].iter().cloned();
let _ = Some(&String::new()).cloned();
}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let _ = [1].iter().cloned();
+ let _ = Some(&1).cloned();
+}
+
+fn msrv_1_35() {
+ #![clippy::msrv = "1.35"]
+
+ let _ = [1].iter().cloned();
+ let _ = Some(&1).copied(); // Option::copied needs 1.35
+}
+
+fn msrv_1_36() {
+ #![clippy::msrv = "1.36"]
+
+ let _ = [1].iter().copied(); // Iterator::copied needs 1.36
+ let _ = Some(&1).copied();
+}
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
index 894496c0e..471bd9654 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.rs
@@ -1,5 +1,8 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::cloned_instead_of_copied)]
+#![allow(unused)]
fn main() {
// yay
@@ -13,3 +16,24 @@ fn main() {
let _ = [String::new()].iter().cloned();
let _ = Some(&String::new()).cloned();
}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let _ = [1].iter().cloned();
+ let _ = Some(&1).cloned();
+}
+
+fn msrv_1_35() {
+ #![clippy::msrv = "1.35"]
+
+ let _ = [1].iter().cloned();
+ let _ = Some(&1).cloned(); // Option::copied needs 1.35
+}
+
+fn msrv_1_36() {
+ #![clippy::msrv = "1.36"]
+
+ let _ = [1].iter().cloned(); // Iterator::copied needs 1.36
+ let _ = Some(&1).cloned();
+}
diff --git a/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
index e0707d321..914c9a91e 100644
--- a/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
+++ b/src/tools/clippy/tests/ui/cloned_instead_of_copied.stderr
@@ -1,5 +1,5 @@
error: used `cloned` where `copied` could be used instead
- --> $DIR/cloned_instead_of_copied.rs:6:24
+ --> $DIR/cloned_instead_of_copied.rs:9:24
|
LL | let _ = [1].iter().cloned();
| ^^^^^^ help: try: `copied`
@@ -7,28 +7,46 @@ LL | let _ = [1].iter().cloned();
= note: `-D clippy::cloned-instead-of-copied` implied by `-D warnings`
error: used `cloned` where `copied` could be used instead
- --> $DIR/cloned_instead_of_copied.rs:7:31
+ --> $DIR/cloned_instead_of_copied.rs:10:31
|
LL | let _ = vec!["hi"].iter().cloned();
| ^^^^^^ help: try: `copied`
error: used `cloned` where `copied` could be used instead
- --> $DIR/cloned_instead_of_copied.rs:8:22
+ --> $DIR/cloned_instead_of_copied.rs:11:22
|
LL | let _ = Some(&1).cloned();
| ^^^^^^ help: try: `copied`
error: used `cloned` where `copied` could be used instead
- --> $DIR/cloned_instead_of_copied.rs:9:34
+ --> $DIR/cloned_instead_of_copied.rs:12:34
|
LL | let _ = Box::new([1].iter()).cloned();
| ^^^^^^ help: try: `copied`
error: used `cloned` where `copied` could be used instead
- --> $DIR/cloned_instead_of_copied.rs:10:32
+ --> $DIR/cloned_instead_of_copied.rs:13:32
|
LL | let _ = Box::new(Some(&1)).cloned();
| ^^^^^^ help: try: `copied`
-error: aborting due to 5 previous errors
+error: used `cloned` where `copied` could be used instead
+ --> $DIR/cloned_instead_of_copied.rs:31:22
+ |
+LL | let _ = Some(&1).cloned(); // Option::copied needs 1.35
+ | ^^^^^^ help: try: `copied`
+
+error: used `cloned` where `copied` could be used instead
+ --> $DIR/cloned_instead_of_copied.rs:37:24
+ |
+LL | let _ = [1].iter().cloned(); // Iterator::copied needs 1.36
+ | ^^^^^^ help: try: `copied`
+
+error: used `cloned` where `copied` could be used instead
+ --> $DIR/cloned_instead_of_copied.rs:38:22
+ |
+LL | let _ = Some(&1).cloned();
+ | ^^^^^^ help: try: `copied`
+
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity.stderr b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
index a0ddc673a..d7f2f24e5 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity.stderr
+++ b/src/tools/clippy/tests/ui/cognitive_complexity.stderr
@@ -4,8 +4,8 @@ error: the function has a cognitive complexity of (28/25)
LL | fn main() {
| ^^^^
|
- = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
= help: you could split it up into multiple smaller functions
+ = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
error: the function has a cognitive complexity of (7/1)
--> $DIR/cognitive_complexity.rs:91:4
diff --git a/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr b/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr
index f5ff53dda..bb48f3297 100644
--- a/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr
+++ b/src/tools/clippy/tests/ui/cognitive_complexity_attr_used.stderr
@@ -4,8 +4,8 @@ error: the function has a cognitive complexity of (3/0)
LL | fn kaboom() {
| ^^^^^^
|
- = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
= help: you could split it up into multiple smaller functions
+ = note: `-D clippy::cognitive-complexity` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/collapsible_if.fixed b/src/tools/clippy/tests/ui/collapsible_if.fixed
index 5b0e4a473..6bb7682ba 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.fixed
+++ b/src/tools/clippy/tests/ui/collapsible_if.fixed
@@ -139,6 +139,9 @@ fn main() {
// Fix #5962
if matches!(true, true) && matches!(true, true) {}
+ // Issue #9375
+ if matches!(true, true) && truth() && matches!(true, true) {}
+
if true {
#[cfg(not(teehee))]
if true {
diff --git a/src/tools/clippy/tests/ui/collapsible_if.rs b/src/tools/clippy/tests/ui/collapsible_if.rs
index cd231a5d7..e216a9ee5 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.rs
+++ b/src/tools/clippy/tests/ui/collapsible_if.rs
@@ -155,6 +155,11 @@ fn main() {
if matches!(true, true) {}
}
+ // Issue #9375
+ if matches!(true, true) && truth() {
+ if matches!(true, true) {}
+ }
+
if true {
#[cfg(not(teehee))]
if true {
diff --git a/src/tools/clippy/tests/ui/collapsible_if.stderr b/src/tools/clippy/tests/ui/collapsible_if.stderr
index 674961238..6327444df 100644
--- a/src/tools/clippy/tests/ui/collapsible_if.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_if.stderr
@@ -126,5 +126,13 @@ LL | | if matches!(true, true) {}
LL | | }
| |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
-error: aborting due to 8 previous errors
+error: this `if` statement can be collapsed
+ --> $DIR/collapsible_if.rs:159:5
+ |
+LL | / if matches!(true, true) && truth() {
+LL | | if matches!(true, true) {}
+LL | | }
+ | |_____^ help: collapse nested if block: `if matches!(true, true) && truth() && matches!(true, true) {}`
+
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/collapsible_match.rs b/src/tools/clippy/tests/ui/collapsible_match.rs
index 603ae7dc9..1d7a72846 100644
--- a/src/tools/clippy/tests/ui/collapsible_match.rs
+++ b/src/tools/clippy/tests/ui/collapsible_match.rs
@@ -1,9 +1,10 @@
#![warn(clippy::collapsible_match)]
#![allow(
+ clippy::equatable_if_let,
clippy::needless_return,
clippy::no_effect,
clippy::single_match,
- clippy::equatable_if_let
+ clippy::uninlined_format_args
)]
fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
@@ -252,6 +253,27 @@ fn negative_cases(res_opt: Result<Option<u32>, String>, res_res: Result<Result<u
};
}
+pub enum Issue9647 {
+ A { a: Option<Option<u8>>, b: () },
+ B,
+}
+
+pub fn test_1(x: Issue9647) {
+ if let Issue9647::A { a, .. } = x {
+ if let Some(u) = a {
+ println!("{u:?}")
+ }
+ }
+}
+
+pub fn test_2(x: Issue9647) {
+ if let Issue9647::A { a: Some(a), .. } = x {
+ if let Some(u) = a {
+ println!("{u}")
+ }
+ }
+}
+
fn make<T>() -> T {
unimplemented!()
}
diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr
index 5f18b6935..0294be60b 100644
--- a/src/tools/clippy/tests/ui/collapsible_match.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_match.stderr
@@ -1,5 +1,5 @@
error: this `match` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:12:20
+ --> $DIR/collapsible_match.rs:13:20
|
LL | Ok(val) => match val {
| ____________________^
@@ -8,17 +8,17 @@ LL | | _ => return,
LL | | },
| |_________^
|
- = note: `-D clippy::collapsible-match` implied by `-D warnings`
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:12:12
+ --> $DIR/collapsible_match.rs:13:12
|
LL | Ok(val) => match val {
| ^^^ replace this binding
LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
+ = note: `-D clippy::collapsible-match` implied by `-D warnings`
error: this `match` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:21:20
+ --> $DIR/collapsible_match.rs:22:20
|
LL | Ok(val) => match val {
| ____________________^
@@ -28,7 +28,7 @@ LL | | },
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:21:12
+ --> $DIR/collapsible_match.rs:22:12
|
LL | Ok(val) => match val {
| ^^^ replace this binding
@@ -36,7 +36,7 @@ LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
error: this `if let` can be collapsed into the outer `if let`
- --> $DIR/collapsible_match.rs:30:9
+ --> $DIR/collapsible_match.rs:31:9
|
LL | / if let Some(n) = val {
LL | | take(n);
@@ -44,7 +44,7 @@ LL | | }
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:29:15
+ --> $DIR/collapsible_match.rs:30:15
|
LL | if let Ok(val) = res_opt {
| ^^^ replace this binding
@@ -52,7 +52,7 @@ LL | if let Some(n) = val {
| ^^^^^^^ with this pattern
error: this `if let` can be collapsed into the outer `if let`
- --> $DIR/collapsible_match.rs:37:9
+ --> $DIR/collapsible_match.rs:38:9
|
LL | / if let Some(n) = val {
LL | | take(n);
@@ -62,7 +62,7 @@ LL | | }
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:36:15
+ --> $DIR/collapsible_match.rs:37:15
|
LL | if let Ok(val) = res_opt {
| ^^^ replace this binding
@@ -70,7 +70,7 @@ LL | if let Some(n) = val {
| ^^^^^^^ with this pattern
error: this `match` can be collapsed into the outer `if let`
- --> $DIR/collapsible_match.rs:48:9
+ --> $DIR/collapsible_match.rs:49:9
|
LL | / match val {
LL | | Some(n) => foo(n),
@@ -79,7 +79,7 @@ LL | | }
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:47:15
+ --> $DIR/collapsible_match.rs:48:15
|
LL | if let Ok(val) = res_opt {
| ^^^ replace this binding
@@ -88,7 +88,7 @@ LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
error: this `if let` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:57:13
+ --> $DIR/collapsible_match.rs:58:13
|
LL | / if let Some(n) = val {
LL | | take(n);
@@ -96,7 +96,7 @@ LL | | }
| |_____________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:56:12
+ --> $DIR/collapsible_match.rs:57:12
|
LL | Ok(val) => {
| ^^^ replace this binding
@@ -104,7 +104,7 @@ LL | if let Some(n) = val {
| ^^^^^^^ with this pattern
error: this `match` can be collapsed into the outer `if let`
- --> $DIR/collapsible_match.rs:66:9
+ --> $DIR/collapsible_match.rs:67:9
|
LL | / match val {
LL | | Some(n) => foo(n),
@@ -113,7 +113,7 @@ LL | | }
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:65:15
+ --> $DIR/collapsible_match.rs:66:15
|
LL | if let Ok(val) = res_opt {
| ^^^ replace this binding
@@ -122,7 +122,7 @@ LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
error: this `if let` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:77:13
+ --> $DIR/collapsible_match.rs:78:13
|
LL | / if let Some(n) = val {
LL | | take(n);
@@ -132,7 +132,7 @@ LL | | }
| |_____________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:76:12
+ --> $DIR/collapsible_match.rs:77:12
|
LL | Ok(val) => {
| ^^^ replace this binding
@@ -140,7 +140,7 @@ LL | if let Some(n) = val {
| ^^^^^^^ with this pattern
error: this `match` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:88:20
+ --> $DIR/collapsible_match.rs:89:20
|
LL | Ok(val) => match val {
| ____________________^
@@ -150,7 +150,7 @@ LL | | },
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:88:12
+ --> $DIR/collapsible_match.rs:89:12
|
LL | Ok(val) => match val {
| ^^^ replace this binding
@@ -158,7 +158,7 @@ LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
error: this `match` can be collapsed into the outer `match`
- --> $DIR/collapsible_match.rs:97:22
+ --> $DIR/collapsible_match.rs:98:22
|
LL | Some(val) => match val {
| ______________________^
@@ -168,12 +168,44 @@ LL | | },
| |_________^
|
help: the outer pattern can be modified to include the inner pattern
- --> $DIR/collapsible_match.rs:97:14
+ --> $DIR/collapsible_match.rs:98:14
|
LL | Some(val) => match val {
| ^^^ replace this binding
LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
-error: aborting due to 10 previous errors
+error: this `if let` can be collapsed into the outer `if let`
+ --> $DIR/collapsible_match.rs:263:9
+ |
+LL | / if let Some(u) = a {
+LL | | println!("{u:?}")
+LL | | }
+ | |_________^
+ |
+help: the outer pattern can be modified to include the inner pattern
+ --> $DIR/collapsible_match.rs:262:27
+ |
+LL | if let Issue9647::A { a, .. } = x {
+ | ^ replace this binding
+LL | if let Some(u) = a {
+ | ^^^^^^^ with this pattern, prefixed by a:
+
+error: this `if let` can be collapsed into the outer `if let`
+ --> $DIR/collapsible_match.rs:271:9
+ |
+LL | / if let Some(u) = a {
+LL | | println!("{u}")
+LL | | }
+ | |_________^
+ |
+help: the outer pattern can be modified to include the inner pattern
+ --> $DIR/collapsible_match.rs:270:35
+ |
+LL | if let Issue9647::A { a: Some(a), .. } = x {
+ | ^ replace this binding
+LL | if let Some(u) = a {
+ | ^^^^^^^ with this pattern
+
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/collapsible_match2.stderr b/src/tools/clippy/tests/ui/collapsible_match2.stderr
index fe64e4693..144dbe40a 100644
--- a/src/tools/clippy/tests/ui/collapsible_match2.stderr
+++ b/src/tools/clippy/tests/ui/collapsible_match2.stderr
@@ -8,7 +8,6 @@ LL | | _ => return,
LL | | },
| |_____________^
|
- = note: `-D clippy::collapsible-match` implied by `-D warnings`
help: the outer pattern can be modified to include the inner pattern
--> $DIR/collapsible_match2.rs:13:16
|
@@ -16,6 +15,7 @@ LL | Ok(val) if make() => match val {
| ^^^ replace this binding
LL | Some(n) => foo(n),
| ^^^^^^^ with this pattern
+ = note: `-D clippy::collapsible-match` implied by `-D warnings`
error: this `match` can be collapsed into the outer `match`
--> $DIR/collapsible_match2.rs:20:24
diff --git a/src/tools/clippy/tests/ui/comparison_chain.stderr b/src/tools/clippy/tests/ui/comparison_chain.stderr
index be25a80dd..2eeb50202 100644
--- a/src/tools/clippy/tests/ui/comparison_chain.stderr
+++ b/src/tools/clippy/tests/ui/comparison_chain.stderr
@@ -8,8 +8,8 @@ LL | | b()
LL | | }
| |_____^
|
- = note: `-D clippy::comparison-chain` implied by `-D warnings`
= help: consider rewriting the `if` chain to use `cmp` and `match`
+ = note: `-D clippy::comparison-chain` implied by `-D warnings`
error: `if` chain can be rewritten with `match`
--> $DIR/comparison_chain.rs:27:5
diff --git a/src/tools/clippy/tests/ui/copy_iterator.stderr b/src/tools/clippy/tests/ui/copy_iterator.stderr
index f8ce6af79..6bc6fd6b6 100644
--- a/src/tools/clippy/tests/ui/copy_iterator.stderr
+++ b/src/tools/clippy/tests/ui/copy_iterator.stderr
@@ -10,8 +10,8 @@ LL | | }
LL | | }
| |_^
|
- = note: `-D clippy::copy-iterator` implied by `-D warnings`
= note: consider implementing `IntoIterator` instead
+ = note: `-D clippy::copy-iterator` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-360.stderr b/src/tools/clippy/tests/ui/crashes/ice-360.stderr
index 0eb7bb12b..a2e2ab8fd 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-360.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-360.stderr
@@ -18,8 +18,8 @@ error: empty `loop {}` wastes CPU cycles
LL | loop {}
| ^^^^^^^
|
- = note: `-D clippy::empty-loop` implied by `-D warnings`
= help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
+ = note: `-D clippy::empty-loop` implied by `-D warnings`
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/crashes/ice-4775.rs b/src/tools/clippy/tests/ui/crashes/ice-4775.rs
index 405e3039e..f693aafd1 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-4775.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-4775.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
pub struct ArrayWrapper<const N: usize>([usize; N]);
impl<const N: usize> ArrayWrapper<{ N }> {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr b/src/tools/clippy/tests/ui/crashes/ice-6254.stderr
index f37ab2e9b..22d82a30c 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-6254.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-6254.stderr
@@ -4,9 +4,9 @@ error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated wit
LL | FOO_REF_REF => {},
| ^^^^^^^^^^^
|
- = note: `-D indirect-structural-match` implied by `-D warnings`
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+ = note: `-D indirect-structural-match` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7126.rs b/src/tools/clippy/tests/ui/crashes/ice-7126.rs
index ca563ba09..b2dc2248b 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7126.rs
+++ b/src/tools/clippy/tests/ui/crashes/ice-7126.rs
@@ -1,13 +1,13 @@
// This test requires a feature gated const fn and will stop working in the future.
-#![feature(const_btree_new)]
+#![feature(const_btree_len)]
use std::collections::BTreeMap;
-struct Foo(BTreeMap<i32, i32>);
+struct Foo(usize);
impl Foo {
fn new() -> Self {
- Self(BTreeMap::new())
+ Self(BTreeMap::len(&BTreeMap::<u8, u8>::new()))
}
}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
index 1a33e6475..1d8314e88 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-7868.stderr
@@ -4,8 +4,8 @@ error: unsafe block missing a safety comment
LL | unsafe { 0 };
| ^^^^^^^^^^^^
|
- = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
= help: consider adding a safety comment on the preceding line
+ = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
index 4fa9fb27e..35d1e8fd2 100644
--- a/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
+++ b/src/tools/clippy/tests/ui/crashes/ice-7869.stderr
@@ -8,8 +8,8 @@ LL | | TyöValmis,
LL | | }
| |_^
|
- = note: `-D clippy::enum-variant-names` implied by `-D warnings`
= help: remove the prefixes and use full paths to the variants instead of glob imports
+ = note: `-D clippy::enum-variant-names` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9445.rs b/src/tools/clippy/tests/ui/crashes/ice-9445.rs
new file mode 100644
index 000000000..c67b22f6f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9445.rs
@@ -0,0 +1,3 @@
+const UNINIT: core::mem::MaybeUninit<core::cell::Cell<&'static ()>> = core::mem::MaybeUninit::uninit();
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9459.rs b/src/tools/clippy/tests/ui/crashes/ice-9459.rs
new file mode 100644
index 000000000..55615124f
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9459.rs
@@ -0,0 +1,5 @@
+#![feature(unsized_fn_params)]
+
+pub fn f0(_f: dyn FnOnce()) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9463.rs b/src/tools/clippy/tests/ui/crashes/ice-9463.rs
new file mode 100644
index 000000000..9564e77c2
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9463.rs
@@ -0,0 +1,5 @@
+#![deny(arithmetic_overflow)]
+fn main() {
+ let _x = -1_i32 >> -1;
+ let _y = 1u32 >> 10000000000000u32;
+}
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9463.stderr b/src/tools/clippy/tests/ui/crashes/ice-9463.stderr
new file mode 100644
index 000000000..2b425e85a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9463.stderr
@@ -0,0 +1,29 @@
+error: this arithmetic operation will overflow
+ --> $DIR/ice-9463.rs:3:14
+ |
+LL | let _x = -1_i32 >> -1;
+ | ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/ice-9463.rs:1:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: this arithmetic operation will overflow
+ --> $DIR/ice-9463.rs:4:14
+ |
+LL | let _y = 1u32 >> 10000000000000u32;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift right by `1316134912_u32`, which would overflow
+
+error: literal out of range for `u32`
+ --> $DIR/ice-9463.rs:4:22
+ |
+LL | let _y = 1u32 >> 10000000000000u32;
+ | ^^^^^^^^^^^^^^^^^
+ |
+ = note: the literal `10000000000000u32` does not fit into the type `u32` whose range is `0..=4294967295`
+ = note: `#[deny(overflowing_literals)]` on by default
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/crashes/ice-9625.rs b/src/tools/clippy/tests/ui/crashes/ice-9625.rs
new file mode 100644
index 000000000..a765882b5
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-9625.rs
@@ -0,0 +1,4 @@
+fn main() {
+ let x = &1;
+ let _ = &1 < x && x < &10;
+}
diff --git a/src/tools/clippy/tests/ui/crashes/regressions.rs b/src/tools/clippy/tests/ui/crashes/regressions.rs
index 55a8b4034..b34997d4e 100644
--- a/src/tools/clippy/tests/ui/crashes/regressions.rs
+++ b/src/tools/clippy/tests/ui/crashes/regressions.rs
@@ -1,4 +1,4 @@
-#![allow(clippy::disallowed_names)]
+#![allow(clippy::disallowed_names, clippy::uninlined_format_args)]
pub fn foo(bar: *const u8) {
println!("{:#p}", bar);
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr
index 459cf12a1..3d79a115c 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr
+++ b/src/tools/clippy/tests/ui/crate_level_checks/entrypoint_recursion.stderr
@@ -4,8 +4,8 @@ error: recursing into entrypoint `a`
LL | a();
| ^
|
- = note: `-D clippy::main-recursion` implied by `-D warnings`
= help: consider using another function for this recursion
+ = note: `-D clippy::main-recursion` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
index 48152d8ad..7d8ea3f76 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
+++ b/src/tools/clippy/tests/ui/crate_level_checks/no_std_swap.stderr
@@ -5,8 +5,8 @@ LL | / a = b;
LL | | b = a;
| |_________^ help: try: `core::mem::swap(&mut a, &mut b)`
|
- = note: `-D clippy::almost-swapped` implied by `-D warnings`
= note: or maybe you should use `core::mem::replace`?
+ = note: `-D clippy::almost-swapped` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr b/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr
index 0a260f9d2..82c68bd1c 100644
--- a/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr
+++ b/src/tools/clippy/tests/ui/crate_level_checks/std_main_recursion.stderr
@@ -4,8 +4,8 @@ error: recursing into entrypoint `main`
LL | main();
| ^^^^
|
- = note: `-D clippy::main-recursion` implied by `-D warnings`
= help: consider using another function for this recursion
+ = note: `-D clippy::main-recursion` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/def_id_nocore.stderr b/src/tools/clippy/tests/ui/def_id_nocore.stderr
index 6210d7c6c..f8fc17e87 100644
--- a/src/tools/clippy/tests/ui/def_id_nocore.stderr
+++ b/src/tools/clippy/tests/ui/def_id_nocore.stderr
@@ -4,8 +4,8 @@ error: methods called `as_*` usually take `self` by reference or `self` by mutab
LL | pub fn as_ref(self) -> &'static str {
| ^^^^
|
- = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
= help: consider choosing a less ambiguous name
+ = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
index a28bff767..a370ccc76 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.fixed
@@ -33,6 +33,7 @@ mod basic_expr {
let x: [f64; 3] = [1., 2., 3.];
let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
let x: _ = 1.;
+ const X: f32 = 1.;
}
}
@@ -59,6 +60,14 @@ mod nested_local {
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
2.
};
+
+ const X: f32 = {
+ // Should lint this because this literal is not bound to any types.
+ let y = 1.0_f64;
+
+ // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+ 1.
+ };
}
}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
index b48435cc7..2476fe951 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.rs
@@ -33,6 +33,7 @@ mod basic_expr {
let x: [f64; 3] = [1., 2., 3.];
let x: (f64, f64) = if true { (1., 2.) } else { (3., 4.) };
let x: _ = 1.;
+ const X: f32 = 1.;
}
}
@@ -59,6 +60,14 @@ mod nested_local {
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
2.
};
+
+ const X: f32 = {
+ // Should lint this because this literal is not bound to any types.
+ let y = 1.;
+
+ // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+ 1.
+ };
}
}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
index f8b6c7746..5df2f6423 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_f64.stderr
@@ -61,79 +61,85 @@ LL | _ => 1.,
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:43:21
+ --> $DIR/default_numeric_fallback_f64.rs:44:21
|
LL | let y = 1.;
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:51:21
+ --> $DIR/default_numeric_fallback_f64.rs:52:21
|
LL | let y = 1.;
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:57:21
+ --> $DIR/default_numeric_fallback_f64.rs:58:21
|
LL | let y = 1.;
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:69:9
+ --> $DIR/default_numeric_fallback_f64.rs:66:21
+ |
+LL | let y = 1.;
+ | ^^ help: consider adding suffix: `1.0_f64`
+
+error: default numeric fallback might occur
+ --> $DIR/default_numeric_fallback_f64.rs:78:9
|
LL | 1.
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:75:27
+ --> $DIR/default_numeric_fallback_f64.rs:84:27
|
LL | let f = || -> _ { 1. };
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:79:29
+ --> $DIR/default_numeric_fallback_f64.rs:88:29
|
LL | let f = || -> f64 { 1. };
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:93:21
+ --> $DIR/default_numeric_fallback_f64.rs:102:21
|
LL | generic_arg(1.);
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:96:32
+ --> $DIR/default_numeric_fallback_f64.rs:105:32
|
LL | let x: _ = generic_arg(1.);
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:114:28
+ --> $DIR/default_numeric_fallback_f64.rs:123:28
|
LL | GenericStruct { x: 1. };
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:117:36
+ --> $DIR/default_numeric_fallback_f64.rs:126:36
|
LL | let _ = GenericStruct { x: 1. };
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:135:24
+ --> $DIR/default_numeric_fallback_f64.rs:144:24
|
LL | GenericEnum::X(1.);
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:155:23
+ --> $DIR/default_numeric_fallback_f64.rs:164:23
|
LL | s.generic_arg(1.);
| ^^ help: consider adding suffix: `1.0_f64`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_f64.rs:162:21
+ --> $DIR/default_numeric_fallback_f64.rs:171:21
|
LL | let x = 22.;
| ^^^ help: consider adding suffix: `22.0_f64`
@@ -143,5 +149,5 @@ LL | internal_macro!();
|
= note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 23 previous errors
+error: aborting due to 24 previous errors
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
index 55451cf2f..3f4994f04 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.fixed
@@ -33,6 +33,8 @@ mod basic_expr {
let x: [i32; 3] = [1, 2, 3];
let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
let x: _ = 1;
+ let x: u64 = 1;
+ const CONST_X: i8 = 1;
}
}
@@ -59,6 +61,14 @@ mod nested_local {
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
2
};
+
+ const CONST_X: i32 = {
+ // Should lint this because this literal is not bound to any types.
+ let y = 1_i32;
+
+ // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+ 1
+ };
}
}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
index 62d72f2fe..2df0e0978 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.rs
@@ -33,6 +33,8 @@ mod basic_expr {
let x: [i32; 3] = [1, 2, 3];
let x: (i32, i32) = if true { (1, 2) } else { (3, 4) };
let x: _ = 1;
+ let x: u64 = 1;
+ const CONST_X: i8 = 1;
}
}
@@ -59,6 +61,14 @@ mod nested_local {
// Should NOT lint this because this literal is bound to `_` of outer `Local`.
2
};
+
+ const CONST_X: i32 = {
+ // Should lint this because this literal is not bound to any types.
+ let y = 1;
+
+ // Should NOT lint this because this literal is bound to `_` of outer `Local`.
+ 1
+ };
}
}
diff --git a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
index f7c5e724c..6f219c3fc 100644
--- a/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
+++ b/src/tools/clippy/tests/ui/default_numeric_fallback_i32.stderr
@@ -73,79 +73,85 @@ LL | _ => 2,
| ^ help: consider adding suffix: `2_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:43:21
+ --> $DIR/default_numeric_fallback_i32.rs:45:21
|
LL | let y = 1;
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:51:21
+ --> $DIR/default_numeric_fallback_i32.rs:53:21
|
LL | let y = 1;
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:57:21
+ --> $DIR/default_numeric_fallback_i32.rs:59:21
|
LL | let y = 1;
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:69:9
+ --> $DIR/default_numeric_fallback_i32.rs:67:21
+ |
+LL | let y = 1;
+ | ^ help: consider adding suffix: `1_i32`
+
+error: default numeric fallback might occur
+ --> $DIR/default_numeric_fallback_i32.rs:79:9
|
LL | 1
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:75:27
+ --> $DIR/default_numeric_fallback_i32.rs:85:27
|
LL | let f = || -> _ { 1 };
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:79:29
+ --> $DIR/default_numeric_fallback_i32.rs:89:29
|
LL | let f = || -> i32 { 1 };
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:93:21
+ --> $DIR/default_numeric_fallback_i32.rs:103:21
|
LL | generic_arg(1);
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:96:32
+ --> $DIR/default_numeric_fallback_i32.rs:106:32
|
LL | let x: _ = generic_arg(1);
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:114:28
+ --> $DIR/default_numeric_fallback_i32.rs:124:28
|
LL | GenericStruct { x: 1 };
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:117:36
+ --> $DIR/default_numeric_fallback_i32.rs:127:36
|
LL | let _ = GenericStruct { x: 1 };
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:135:24
+ --> $DIR/default_numeric_fallback_i32.rs:145:24
|
LL | GenericEnum::X(1);
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:155:23
+ --> $DIR/default_numeric_fallback_i32.rs:165:23
|
LL | s.generic_arg(1);
| ^ help: consider adding suffix: `1_i32`
error: default numeric fallback might occur
- --> $DIR/default_numeric_fallback_i32.rs:162:21
+ --> $DIR/default_numeric_fallback_i32.rs:172:21
|
LL | let x = 22;
| ^^ help: consider adding suffix: `22_i32`
@@ -155,5 +161,5 @@ LL | internal_macro!();
|
= note: this error originates in the macro `internal_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 25 previous errors
+error: aborting due to 26 previous errors
diff --git a/src/tools/clippy/tests/ui/default_trait_access.fixed b/src/tools/clippy/tests/ui/default_trait_access.fixed
index fce66eb17..eedd43619 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.fixed
+++ b/src/tools/clippy/tests/ui/default_trait_access.fixed
@@ -1,8 +1,8 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
-
-#![allow(unused_imports, dead_code)]
#![deny(clippy::default_trait_access)]
+#![allow(dead_code, unused_imports)]
+#![allow(clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
diff --git a/src/tools/clippy/tests/ui/default_trait_access.rs b/src/tools/clippy/tests/ui/default_trait_access.rs
index 3e8e898b7..11d4bc5c5 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.rs
+++ b/src/tools/clippy/tests/ui/default_trait_access.rs
@@ -1,8 +1,8 @@
// run-rustfix
// aux-build: proc_macro_with_span.rs
-
-#![allow(unused_imports, dead_code)]
#![deny(clippy::default_trait_access)]
+#![allow(dead_code, unused_imports)]
+#![allow(clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
diff --git a/src/tools/clippy/tests/ui/default_trait_access.stderr b/src/tools/clippy/tests/ui/default_trait_access.stderr
index 3493de37a..49b2dde3f 100644
--- a/src/tools/clippy/tests/ui/default_trait_access.stderr
+++ b/src/tools/clippy/tests/ui/default_trait_access.stderr
@@ -5,7 +5,7 @@ LL | let s1: String = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
note: the lint level is defined here
- --> $DIR/default_trait_access.rs:5:9
+ --> $DIR/default_trait_access.rs:3:9
|
LL | #![deny(clippy::default_trait_access)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/default_union_representation.stderr b/src/tools/clippy/tests/ui/default_union_representation.stderr
index 138884af8..8b7ed94cb 100644
--- a/src/tools/clippy/tests/ui/default_union_representation.stderr
+++ b/src/tools/clippy/tests/ui/default_union_representation.stderr
@@ -7,8 +7,8 @@ LL | | b: u32,
LL | | }
| |_^
|
- = note: `-D clippy::default-union-representation` implied by `-D warnings`
= help: consider annotating `NoAttribute` with `#[repr(C)]` to explicitly specify memory layout
+ = note: `-D clippy::default-union-representation` implied by `-D warnings`
error: this union has the default representation
--> $DIR/default_union_representation.rs:16:1
diff --git a/src/tools/clippy/tests/ui/derivable_impls.fixed b/src/tools/clippy/tests/ui/derivable_impls.fixed
new file mode 100644
index 000000000..7dcdfb093
--- /dev/null
+++ b/src/tools/clippy/tests/ui/derivable_impls.fixed
@@ -0,0 +1,213 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+use std::collections::HashMap;
+
+#[derive(Default)]
+struct FooDefault<'a> {
+ a: bool,
+ b: i32,
+ c: u64,
+ d: Vec<i32>,
+ e: FooND1,
+ f: FooND2,
+ g: HashMap<i32, i32>,
+ h: (i32, Vec<i32>),
+ i: [Vec<i32>; 3],
+ j: [i32; 5],
+ k: Option<i32>,
+ l: &'a [i32],
+}
+
+
+
+#[derive(Default)]
+struct TupleDefault(bool, i32, u64);
+
+
+
+struct FooND1 {
+ a: bool,
+}
+
+impl std::default::Default for FooND1 {
+ fn default() -> Self {
+ Self { a: true }
+ }
+}
+
+struct FooND2 {
+ a: i32,
+}
+
+impl std::default::Default for FooND2 {
+ fn default() -> Self {
+ Self { a: 5 }
+ }
+}
+
+struct FooNDNew {
+ a: bool,
+}
+
+impl FooNDNew {
+ fn new() -> Self {
+ Self { a: true }
+ }
+}
+
+impl Default for FooNDNew {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+struct FooNDVec(Vec<i32>);
+
+impl Default for FooNDVec {
+ fn default() -> Self {
+ Self(vec![5, 12])
+ }
+}
+
+#[derive(Default)]
+struct StrDefault<'a>(&'a str);
+
+
+
+#[derive(Default)]
+struct AlreadyDerived(i32, bool);
+
+macro_rules! mac {
+ () => {
+ 0
+ };
+ ($e:expr) => {
+ struct X(u32);
+ impl Default for X {
+ fn default() -> Self {
+ Self($e)
+ }
+ }
+ };
+}
+
+mac!(0);
+
+#[derive(Default)]
+struct Y(u32);
+
+
+struct RustIssue26925<T> {
+ a: Option<T>,
+}
+
+// We should watch out for cases where a manual impl is needed because a
+// derive adds different type bounds (https://github.com/rust-lang/rust/issues/26925).
+// For example, a struct with Option<T> does not require T: Default, but a derive adds
+// that type bound anyways. So until #26925 get fixed we should disable lint
+// for the following case
+impl<T> Default for RustIssue26925<T> {
+ fn default() -> Self {
+ Self { a: None }
+ }
+}
+
+struct SpecializedImpl<A, B> {
+ a: A,
+ b: B,
+}
+
+impl<T: Default> Default for SpecializedImpl<T, T> {
+ fn default() -> Self {
+ Self {
+ a: T::default(),
+ b: T::default(),
+ }
+ }
+}
+
+#[derive(Default)]
+struct WithoutSelfCurly {
+ a: bool,
+}
+
+
+
+#[derive(Default)]
+struct WithoutSelfParan(bool);
+
+
+
+// https://github.com/rust-lang/rust-clippy/issues/7655
+
+pub struct SpecializedImpl2<T> {
+ v: Vec<T>,
+}
+
+impl Default for SpecializedImpl2<String> {
+ fn default() -> Self {
+ Self { v: Vec::new() }
+ }
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/7654
+
+pub struct Color {
+ pub r: u8,
+ pub g: u8,
+ pub b: u8,
+}
+
+/// `#000000`
+impl Default for Color {
+ fn default() -> Self {
+ Color { r: 0, g: 0, b: 0 }
+ }
+}
+
+pub struct Color2 {
+ pub r: u8,
+ pub g: u8,
+ pub b: u8,
+}
+
+impl Default for Color2 {
+ /// `#000000`
+ fn default() -> Self {
+ Self { r: 0, g: 0, b: 0 }
+ }
+}
+
+#[derive(Default)]
+pub struct RepeatDefault1 {
+ a: [i8; 32],
+}
+
+
+
+pub struct RepeatDefault2 {
+ a: [i8; 33],
+}
+
+impl Default for RepeatDefault2 {
+ fn default() -> Self {
+ RepeatDefault2 { a: [0; 33] }
+ }
+}
+
+// https://github.com/rust-lang/rust-clippy/issues/7753
+
+pub enum IntOrString {
+ Int(i32),
+ String(String),
+}
+
+impl Default for IntOrString {
+ fn default() -> Self {
+ IntOrString::Int(0)
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/derivable_impls.rs b/src/tools/clippy/tests/ui/derivable_impls.rs
index a64120047..625cbcdde 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.rs
+++ b/src/tools/clippy/tests/ui/derivable_impls.rs
@@ -1,3 +1,7 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
use std::collections::HashMap;
struct FooDefault<'a> {
diff --git a/src/tools/clippy/tests/ui/derivable_impls.stderr b/src/tools/clippy/tests/ui/derivable_impls.stderr
index 49fb471a2..c1db5a58b 100644
--- a/src/tools/clippy/tests/ui/derivable_impls.stderr
+++ b/src/tools/clippy/tests/ui/derivable_impls.stderr
@@ -1,5 +1,5 @@
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:18:1
+ --> $DIR/derivable_impls.rs:22:1
|
LL | / impl std::default::Default for FooDefault<'_> {
LL | | fn default() -> Self {
@@ -11,10 +11,14 @@ LL | | }
| |_^
|
= note: `-D clippy::derivable-impls` implied by `-D warnings`
- = help: try annotating `FooDefault` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:39:1
+ --> $DIR/derivable_impls.rs:43:1
|
LL | / impl std::default::Default for TupleDefault {
LL | | fn default() -> Self {
@@ -23,10 +27,14 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `TupleDefault` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:91:1
+ --> $DIR/derivable_impls.rs:95:1
|
LL | / impl Default for StrDefault<'_> {
LL | | fn default() -> Self {
@@ -35,10 +43,14 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `StrDefault` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:117:1
+ --> $DIR/derivable_impls.rs:121:1
|
LL | / impl Default for Y {
LL | | fn default() -> Self {
@@ -47,10 +59,14 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `Y` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:156:1
+ --> $DIR/derivable_impls.rs:160:1
|
LL | / impl Default for WithoutSelfCurly {
LL | | fn default() -> Self {
@@ -59,10 +75,14 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `WithoutSelfCurly` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:164:1
+ --> $DIR/derivable_impls.rs:168:1
|
LL | / impl Default for WithoutSelfParan {
LL | | fn default() -> Self {
@@ -71,10 +91,14 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `WithoutSelfParan` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: this `impl` can be derived
- --> $DIR/derivable_impls.rs:214:1
+ --> $DIR/derivable_impls.rs:218:1
|
LL | / impl Default for RepeatDefault1 {
LL | | fn default() -> Self {
@@ -83,7 +107,11 @@ LL | | }
LL | | }
| |_^
|
- = help: try annotating `RepeatDefault1` with `#[derive(Default)]`
+ = help: remove the manual implementation...
+help: ...and instead derive it
+ |
+LL | #[derive(Default)]
+ |
error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/derive.stderr b/src/tools/clippy/tests/ui/derive.stderr
index 82a70ceec..e1fbb8dcd 100644
--- a/src/tools/clippy/tests/ui/derive.stderr
+++ b/src/tools/clippy/tests/ui/derive.stderr
@@ -8,7 +8,6 @@ LL | | }
LL | | }
| |_^
|
- = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings`
note: consider deriving `Clone` or removing `Copy`
--> $DIR/derive.rs:8:1
|
@@ -18,6 +17,7 @@ LL | | Qux
LL | | }
LL | | }
| |_^
+ = note: `-D clippy::expl-impl-clone-on-copy` implied by `-D warnings`
error: you are implementing `Clone` explicitly on a `Copy` type
--> $DIR/derive.rs:32:1
diff --git a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
index 2a4abb0c5..16c923978 100644
--- a/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
+++ b/src/tools/clippy/tests/ui/derive_hash_xor_eq.stderr
@@ -4,12 +4,12 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly
LL | #[derive(Hash)]
| ^^^^
|
- = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
note: `PartialEq` implemented here
--> $DIR/derive_hash_xor_eq.rs:15:1
|
LL | impl PartialEq for Bar {
| ^^^^^^^^^^^^^^^^^^^^^^
+ = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are deriving `Hash` but have implemented `PartialEq` explicitly
diff --git a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr
index baf8341ab..58efbb854 100644
--- a/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr
+++ b/src/tools/clippy/tests/ui/derive_ord_xor_partial_ord.stderr
@@ -4,12 +4,12 @@ error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
LL | #[derive(Ord, PartialEq, Eq)]
| ^^^
|
- = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings`
note: `PartialOrd` implemented here
--> $DIR/derive_ord_xor_partial_ord.rs:24:1
|
LL | impl PartialOrd for DeriveOrd {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::derive-ord-xor-partial-ord` implied by `-D warnings`
= note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are deriving `Ord` but have implemented `PartialOrd` explicitly
diff --git a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
index a462b9887..f2ac6bc32 100644
--- a/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
+++ b/src/tools/clippy/tests/ui/doc/unbalanced_ticks.stderr
@@ -7,8 +7,8 @@ LL | | /// Because of the initial `unbalanced_tick` pair, the error message is
LL | | /// very `confusing_and_misleading`.
| |____________________________________^
|
- = note: `-D clippy::doc-markdown` implied by `-D warnings`
= help: a backtick may be missing a pair
+ = note: `-D clippy::doc-markdown` implied by `-D warnings`
error: backticks are unbalanced
--> $DIR/unbalanced_ticks.rs:13:1
diff --git a/src/tools/clippy/tests/ui/doc_link_with_quotes.rs b/src/tools/clippy/tests/ui/doc_link_with_quotes.rs
index ab52fb1a4..17c04c34e 100644
--- a/src/tools/clippy/tests/ui/doc_link_with_quotes.rs
+++ b/src/tools/clippy/tests/ui/doc_link_with_quotes.rs
@@ -4,9 +4,14 @@ fn main() {
foo()
}
-/// Calls ['bar']
+/// Calls ['bar'] uselessly
pub fn foo() {
bar()
}
+/// # Examples
+/// This demonstrates issue \#8961
+/// ```
+/// let _ = vec!['w', 'a', 't'];
+/// ```
pub fn bar() {}
diff --git a/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr b/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr
index bf6d57d8a..ea730e667 100644
--- a/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr
+++ b/src/tools/clippy/tests/ui/doc_link_with_quotes.stderr
@@ -1,8 +1,8 @@
error: possible intra-doc link using quotes instead of backticks
- --> $DIR/doc_link_with_quotes.rs:7:1
+ --> $DIR/doc_link_with_quotes.rs:7:12
|
-LL | /// Calls ['bar']
- | ^^^^^^^^^^^^^^^^^
+LL | /// Calls ['bar'] uselessly
+ | ^^^^^
|
= note: `-D clippy::doc-link-with-quotes` implied by `-D warnings`
diff --git a/src/tools/clippy/tests/ui/double_must_use.stderr b/src/tools/clippy/tests/ui/double_must_use.stderr
index 8290ece1c..3d34557a8 100644
--- a/src/tools/clippy/tests/ui/double_must_use.stderr
+++ b/src/tools/clippy/tests/ui/double_must_use.stderr
@@ -4,8 +4,8 @@ error: this function has an empty `#[must_use]` attribute, but returns a type al
LL | pub fn must_use_result() -> Result<(), ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::double-must-use` implied by `-D warnings`
= help: either add some descriptive text or remove the attribute
+ = note: `-D clippy::double-must-use` implied by `-D warnings`
error: this function has an empty `#[must_use]` attribute, but returns a type already marked as `#[must_use]`
--> $DIR/double_must_use.rs:10:1
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.rs b/src/tools/clippy/tests/ui/drop_forget_copy.rs
index 7c7a9ecff..a7276dd59 100644
--- a/src/tools/clippy/tests/ui/drop_forget_copy.rs
+++ b/src/tools/clippy/tests/ui/drop_forget_copy.rs
@@ -64,3 +64,23 @@ fn main() {
let a5 = a1.clone();
forget(a5);
}
+
+#[allow(unused)]
+#[allow(clippy::unit_cmp)]
+fn issue9482(x: u8) {
+ fn println_and<T>(t: T) -> T {
+ println!("foo");
+ t
+ }
+
+ match x {
+ 0 => drop(println_and(12)), // Don't lint (copy type), we only care about side-effects
+ 1 => drop(println_and(String::new())), // Don't lint (no copy type), we only care about side-effects
+ 2 => {
+ drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
+ },
+ 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ 4 => drop(2), // Lint, not a fn/method call
+ _ => (),
+ }
+}
diff --git a/src/tools/clippy/tests/ui/drop_forget_copy.stderr b/src/tools/clippy/tests/ui/drop_forget_copy.stderr
index 88228afae..90bef1c3c 100644
--- a/src/tools/clippy/tests/ui/drop_forget_copy.stderr
+++ b/src/tools/clippy/tests/ui/drop_forget_copy.stderr
@@ -4,12 +4,12 @@ error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a
LL | drop(s1);
| ^^^^^^^^
|
- = note: `-D clippy::drop-copy` implied by `-D warnings`
note: argument has type `SomeStruct`
--> $DIR/drop_forget_copy.rs:33:10
|
LL | drop(s1);
| ^^
+ = note: `-D clippy::drop-copy` implied by `-D warnings`
error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
--> $DIR/drop_forget_copy.rs:34:5
@@ -41,12 +41,12 @@ error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetti
LL | forget(s1);
| ^^^^^^^^^^
|
- = note: `-D clippy::forget-copy` implied by `-D warnings`
note: argument has type `SomeStruct`
--> $DIR/drop_forget_copy.rs:39:12
|
LL | forget(s1);
| ^^
+ = note: `-D clippy::forget-copy` implied by `-D warnings`
error: calls to `std::mem::forget` with a value that implements `Copy`. Forgetting a copy leaves the original intact
--> $DIR/drop_forget_copy.rs:40:5
@@ -72,5 +72,41 @@ note: argument has type `SomeStruct`
LL | forget(s4);
| ^^
-error: aborting due to 6 previous errors
+error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
+ --> $DIR/drop_forget_copy.rs:80:13
+ |
+LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: argument has type `i32`
+ --> $DIR/drop_forget_copy.rs:80:18
+ |
+LL | drop(println_and(13)); // Lint, even if we only care about the side-effect, it's already in a block
+ | ^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
+ --> $DIR/drop_forget_copy.rs:82:14
+ |
+LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+note: argument has type `i32`
+ --> $DIR/drop_forget_copy.rs:82:19
+ |
+LL | 3 if drop(println_and(14)) == () => (), // Lint, idiomatic use is only in body of `Arm`
+ | ^^^^^^^^^^^^^^^
+
+error: calls to `std::mem::drop` with a value that implements `Copy`. Dropping a copy leaves the original intact
+ --> $DIR/drop_forget_copy.rs:83:14
+ |
+LL | 4 => drop(2), // Lint, not a fn/method call
+ | ^^^^^^^
+ |
+note: argument has type `i32`
+ --> $DIR/drop_forget_copy.rs:83:19
+ |
+LL | 4 => drop(2), // Lint, not a fn/method call
+ | ^
+
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/drop_non_drop.stderr b/src/tools/clippy/tests/ui/drop_non_drop.stderr
index 30121033d..b86057c0c 100644
--- a/src/tools/clippy/tests/ui/drop_non_drop.stderr
+++ b/src/tools/clippy/tests/ui/drop_non_drop.stderr
@@ -4,12 +4,12 @@ error: call to `std::mem::drop` with a value that does not implement `Drop`. Dro
LL | drop(Foo);
| ^^^^^^^^^
|
- = note: `-D clippy::drop-non-drop` implied by `-D warnings`
note: argument has type `main::Foo`
--> $DIR/drop_non_drop.rs:22:10
|
LL | drop(Foo);
| ^^^
+ = note: `-D clippy::drop-non-drop` implied by `-D warnings`
error: call to `std::mem::drop` with a value that does not implement `Drop`. Dropping such a type only extends its contained lifetimes
--> $DIR/drop_non_drop.rs:37:5
diff --git a/src/tools/clippy/tests/ui/drop_ref.stderr b/src/tools/clippy/tests/ui/drop_ref.stderr
index 531849f06..4743cf79b 100644
--- a/src/tools/clippy/tests/ui/drop_ref.stderr
+++ b/src/tools/clippy/tests/ui/drop_ref.stderr
@@ -4,12 +4,12 @@ error: calls to `std::mem::drop` with a reference instead of an owned value. Dro
LL | drop(&SomeStruct);
| ^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::drop-ref` implied by `-D warnings`
note: argument has type `&SomeStruct`
--> $DIR/drop_ref.rs:11:10
|
LL | drop(&SomeStruct);
| ^^^^^^^^^^^
+ = note: `-D clippy::drop-ref` implied by `-D warnings`
error: calls to `std::mem::drop` with a reference instead of an owned value. Dropping a reference does nothing
--> $DIR/drop_ref.rs:14:5
diff --git a/src/tools/clippy/tests/ui/else_if_without_else.stderr b/src/tools/clippy/tests/ui/else_if_without_else.stderr
index 6f47658cf..90ccfb4fa 100644
--- a/src/tools/clippy/tests/ui/else_if_without_else.stderr
+++ b/src/tools/clippy/tests/ui/else_if_without_else.stderr
@@ -8,8 +8,8 @@ LL | | println!("else if");
LL | | }
| |_____^
|
- = note: `-D clippy::else-if-without-else` implied by `-D warnings`
= help: add an `else` block here
+ = note: `-D clippy::else-if-without-else` implied by `-D warnings`
error: `if` expression with an `else if`, but without a final `else`
--> $DIR/else_if_without_else.rs:54:12
diff --git a/src/tools/clippy/tests/ui/empty_enum.stderr b/src/tools/clippy/tests/ui/empty_enum.stderr
index 7125e5f60..0d9aa5818 100644
--- a/src/tools/clippy/tests/ui/empty_enum.stderr
+++ b/src/tools/clippy/tests/ui/empty_enum.stderr
@@ -4,8 +4,8 @@ error: enum with no variants
LL | enum Empty {}
| ^^^^^^^^^^^^^
|
- = note: `-D clippy::empty-enum` implied by `-D warnings`
= help: consider using the uninhabited type `!` (never type) or a wrapper around it to introduce a type which can't be instantiated
+ = note: `-D clippy::empty-enum` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/empty_loop.stderr b/src/tools/clippy/tests/ui/empty_loop.stderr
index 555f3d3d8..760241233 100644
--- a/src/tools/clippy/tests/ui/empty_loop.stderr
+++ b/src/tools/clippy/tests/ui/empty_loop.stderr
@@ -4,8 +4,8 @@ error: empty `loop {}` wastes CPU cycles
LL | loop {}
| ^^^^^^^
|
- = note: `-D clippy::empty-loop` implied by `-D warnings`
= help: you should either use `panic!()` or add `std::thread::sleep(..);` to the loop body
+ = note: `-D clippy::empty-loop` implied by `-D warnings`
error: empty `loop {}` wastes CPU cycles
--> $DIR/empty_loop.rs:11:9
diff --git a/src/tools/clippy/tests/ui/empty_loop_no_std.stderr b/src/tools/clippy/tests/ui/empty_loop_no_std.stderr
index 5ded35a6f..71af64f49 100644
--- a/src/tools/clippy/tests/ui/empty_loop_no_std.stderr
+++ b/src/tools/clippy/tests/ui/empty_loop_no_std.stderr
@@ -4,8 +4,8 @@ error: empty `loop {}` wastes CPU cycles
LL | loop {}
| ^^^^^^^
|
- = note: `-D clippy::empty-loop` implied by `-D warnings`
= help: you should either use `panic!()` or add a call pausing or sleeping the thread to the loop body
+ = note: `-D clippy::empty-loop` implied by `-D warnings`
error: empty `loop {}` wastes CPU cycles
--> $DIR/empty_loop_no_std.rs:25:5
diff --git a/src/tools/clippy/tests/ui/entry.fixed b/src/tools/clippy/tests/ui/entry.fixed
index e43635abc..79c29c04e 100644
--- a/src/tools/clippy/tests/ui/entry.fixed
+++ b/src/tools/clippy/tests/ui/entry.fixed
@@ -1,3 +1,4 @@
+// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/entry.rs b/src/tools/clippy/tests/ui/entry.rs
index d999b3b7d..2d7985457 100644
--- a/src/tools/clippy/tests/ui/entry.rs
+++ b/src/tools/clippy/tests/ui/entry.rs
@@ -1,3 +1,4 @@
+// needs-asm-support
// run-rustfix
#![allow(unused, clippy::needless_pass_by_value, clippy::collapsible_if)]
diff --git a/src/tools/clippy/tests/ui/entry.stderr b/src/tools/clippy/tests/ui/entry.stderr
index 2ef996652..2c4c49d25 100644
--- a/src/tools/clippy/tests/ui/entry.stderr
+++ b/src/tools/clippy/tests/ui/entry.stderr
@@ -1,5 +1,5 @@
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:24:5
+ --> $DIR/entry.rs:25:5
|
LL | / if !m.contains_key(&k) {
LL | | m.insert(k, v);
@@ -9,7 +9,7 @@ LL | | }
= note: `-D clippy::map-entry` implied by `-D warnings`
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:29:5
+ --> $DIR/entry.rs:30:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@@ -32,7 +32,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:38:5
+ --> $DIR/entry.rs:39:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@@ -55,7 +55,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:47:5
+ --> $DIR/entry.rs:48:5
|
LL | / if !m.contains_key(&k) {
LL | | if true {
@@ -79,7 +79,7 @@ LL + }
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:57:5
+ --> $DIR/entry.rs:58:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
@@ -96,7 +96,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:63:5
+ --> $DIR/entry.rs:64:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
@@ -122,7 +122,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:75:5
+ --> $DIR/entry.rs:76:5
|
LL | / if !m.contains_key(&k) {
LL | | match 0 {
@@ -146,7 +146,7 @@ LL + }
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:85:5
+ --> $DIR/entry.rs:86:5
|
LL | / if !m.contains_key(&k) {
LL | | foo();
@@ -187,7 +187,7 @@ LL + });
|
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:119:5
+ --> $DIR/entry.rs:120:5
|
LL | / if !m.contains_key(&m!(k)) {
LL | | m.insert(m!(k), m!(v));
@@ -195,7 +195,7 @@ LL | | }
| |_____^ help: try this: `m.entry(m!(k)).or_insert_with(|| m!(v));`
error: usage of `contains_key` followed by `insert` on a `HashMap`
- --> $DIR/entry.rs:151:5
+ --> $DIR/entry.rs:152:5
|
LL | / if !m.contains_key(&k) {
LL | | let x = (String::new(), String::new());
diff --git a/src/tools/clippy/tests/ui/eprint_with_newline.rs b/src/tools/clippy/tests/ui/eprint_with_newline.rs
index 8df32649a..de5e121be 100644
--- a/src/tools/clippy/tests/ui/eprint_with_newline.rs
+++ b/src/tools/clippy/tests/ui/eprint_with_newline.rs
@@ -45,5 +45,13 @@ fn main() {
eprint!("\r\n");
eprint!("foo\r\n");
eprint!("\\r\n"); //~ ERROR
- eprint!("foo\rbar\n") // ~ ERROR
+ eprint!("foo\rbar\n");
+
+ // Ignore expanded format strings
+ macro_rules! newline {
+ () => {
+ "\n"
+ };
+ }
+ eprint!(newline!());
}
diff --git a/src/tools/clippy/tests/ui/eprint_with_newline.stderr b/src/tools/clippy/tests/ui/eprint_with_newline.stderr
index f137787bf..0eefb9f0c 100644
--- a/src/tools/clippy/tests/ui/eprint_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/eprint_with_newline.stderr
@@ -83,7 +83,7 @@ LL | | );
help: use `eprintln!` instead
|
LL ~ eprintln!(
-LL ~ ""
+LL ~
|
error: using `eprint!()` with a format string that ends in a single newline
@@ -98,7 +98,7 @@ LL | | );
help: use `eprintln!` instead
|
LL ~ eprintln!(
-LL ~ r""
+LL ~
|
error: using `eprint!()` with a format string that ends in a single newline
@@ -113,17 +113,5 @@ LL - eprint!("/r/n"); //~ ERROR
LL + eprintln!("/r"); //~ ERROR
|
-error: using `eprint!()` with a format string that ends in a single newline
- --> $DIR/eprint_with_newline.rs:48:5
- |
-LL | eprint!("foo/rbar/n") // ~ ERROR
- | ^^^^^^^^^^^^^^^^^^^^^
- |
-help: use `eprintln!` instead
- |
-LL - eprint!("foo/rbar/n") // ~ ERROR
-LL + eprintln!("foo/rbar") // ~ ERROR
- |
-
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/err_expect.fixed b/src/tools/clippy/tests/ui/err_expect.fixed
index 7e18d70ba..3bac738ac 100644
--- a/src/tools/clippy/tests/ui/err_expect.fixed
+++ b/src/tools/clippy/tests/ui/err_expect.fixed
@@ -1,5 +1,8 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
+
struct MyTypeNonDebug;
#[derive(Debug)]
@@ -12,3 +15,17 @@ fn main() {
let test_non_debug: Result<MyTypeNonDebug, u32> = Ok(MyTypeNonDebug);
test_non_debug.err().expect("Testing non debug type");
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ let x: Result<u32, &str> = Ok(16);
+ x.err().expect("16");
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ let x: Result<u32, &str> = Ok(17);
+ x.expect_err("17");
+}
diff --git a/src/tools/clippy/tests/ui/err_expect.rs b/src/tools/clippy/tests/ui/err_expect.rs
index bf8c3c9fb..6e7c47d9a 100644
--- a/src/tools/clippy/tests/ui/err_expect.rs
+++ b/src/tools/clippy/tests/ui/err_expect.rs
@@ -1,5 +1,8 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
+
struct MyTypeNonDebug;
#[derive(Debug)]
@@ -12,3 +15,17 @@ fn main() {
let test_non_debug: Result<MyTypeNonDebug, u32> = Ok(MyTypeNonDebug);
test_non_debug.err().expect("Testing non debug type");
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ let x: Result<u32, &str> = Ok(16);
+ x.err().expect("16");
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ let x: Result<u32, &str> = Ok(17);
+ x.err().expect("17");
+}
diff --git a/src/tools/clippy/tests/ui/err_expect.stderr b/src/tools/clippy/tests/ui/err_expect.stderr
index ffd97e00a..91a6cf8de 100644
--- a/src/tools/clippy/tests/ui/err_expect.stderr
+++ b/src/tools/clippy/tests/ui/err_expect.stderr
@@ -1,10 +1,16 @@
error: called `.err().expect()` on a `Result` value
- --> $DIR/err_expect.rs:10:16
+ --> $DIR/err_expect.rs:13:16
|
LL | test_debug.err().expect("Testing debug type");
| ^^^^^^^^^^^^ help: try: `expect_err`
|
= note: `-D clippy::err-expect` implied by `-D warnings`
-error: aborting due to previous error
+error: called `.err().expect()` on a `Result` value
+ --> $DIR/err_expect.rs:30:7
+ |
+LL | x.err().expect("17");
+ | ^^^^^^^^^^^^ help: try: `expect_err`
+
+error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/eta.fixed b/src/tools/clippy/tests/ui/eta.fixed
index f8d559bf2..a9cc80aaa 100644
--- a/src/tools/clippy/tests/ui/eta.fixed
+++ b/src/tools/clippy/tests/ui/eta.fixed
@@ -1,14 +1,14 @@
// run-rustfix
-
+#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
+#![allow(unused)]
#![allow(
- unused,
- clippy::no_effect,
- clippy::redundant_closure_call,
+ clippy::needless_borrow,
clippy::needless_pass_by_value,
+ clippy::no_effect,
clippy::option_map_unit_fn,
- clippy::needless_borrow
+ clippy::redundant_closure_call,
+ clippy::uninlined_format_args
)]
-#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
use std::path::{Path, PathBuf};
@@ -303,3 +303,16 @@ fn not_general_enough() {
fn f(_: impl FnMut(&Path) -> std::io::Result<()>) {}
f(|path| std::fs::remove_file(path));
}
+
+// https://github.com/rust-lang/rust-clippy/issues/9369
+pub fn mutable_impl_fn_mut(mut f: impl FnMut(), mut f_used_once: impl FnMut()) -> impl FnMut() {
+ fn takes_fn_mut(_: impl FnMut()) {}
+ takes_fn_mut(&mut f);
+
+ fn takes_fn_once(_: impl FnOnce()) {}
+ takes_fn_once(&mut f);
+
+ f();
+
+ move || takes_fn_mut(&mut f_used_once)
+}
diff --git a/src/tools/clippy/tests/ui/eta.rs b/src/tools/clippy/tests/ui/eta.rs
index f0fb55a1e..cc99906cc 100644
--- a/src/tools/clippy/tests/ui/eta.rs
+++ b/src/tools/clippy/tests/ui/eta.rs
@@ -1,14 +1,14 @@
// run-rustfix
-
+#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
+#![allow(unused)]
#![allow(
- unused,
- clippy::no_effect,
- clippy::redundant_closure_call,
+ clippy::needless_borrow,
clippy::needless_pass_by_value,
+ clippy::no_effect,
clippy::option_map_unit_fn,
- clippy::needless_borrow
+ clippy::redundant_closure_call,
+ clippy::uninlined_format_args
)]
-#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)]
use std::path::{Path, PathBuf};
@@ -303,3 +303,16 @@ fn not_general_enough() {
fn f(_: impl FnMut(&Path) -> std::io::Result<()>) {}
f(|path| std::fs::remove_file(path));
}
+
+// https://github.com/rust-lang/rust-clippy/issues/9369
+pub fn mutable_impl_fn_mut(mut f: impl FnMut(), mut f_used_once: impl FnMut()) -> impl FnMut() {
+ fn takes_fn_mut(_: impl FnMut()) {}
+ takes_fn_mut(|| f());
+
+ fn takes_fn_once(_: impl FnOnce()) {}
+ takes_fn_once(|| f());
+
+ f();
+
+ move || takes_fn_mut(|| f_used_once())
+}
diff --git a/src/tools/clippy/tests/ui/eta.stderr b/src/tools/clippy/tests/ui/eta.stderr
index bf2e97e74..434706b7e 100644
--- a/src/tools/clippy/tests/ui/eta.stderr
+++ b/src/tools/clippy/tests/ui/eta.stderr
@@ -116,5 +116,23 @@ error: redundant closure
LL | Some(1).map(|n| in_loop(n));
| ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop`
-error: aborting due to 19 previous errors
+error: redundant closure
+ --> $DIR/eta.rs:310:18
+ |
+LL | takes_fn_mut(|| f());
+ | ^^^^^^ help: replace the closure with the function itself: `&mut f`
+
+error: redundant closure
+ --> $DIR/eta.rs:313:19
+ |
+LL | takes_fn_once(|| f());
+ | ^^^^^^ help: replace the closure with the function itself: `&mut f`
+
+error: redundant closure
+ --> $DIR/eta.rs:317:26
+ |
+LL | move || takes_fn_mut(|| f_used_once())
+ | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once`
+
+error: aborting due to 22 previous errors
diff --git a/src/tools/clippy/tests/ui/expect.stderr b/src/tools/clippy/tests/ui/expect.stderr
index 904c09046..f6738865c 100644
--- a/src/tools/clippy/tests/ui/expect.stderr
+++ b/src/tools/clippy/tests/ui/expect.stderr
@@ -4,8 +4,8 @@ error: used `expect()` on `an Option` value
LL | let _ = opt.expect("");
| ^^^^^^^^^^^^^^
|
- = note: `-D clippy::expect-used` implied by `-D warnings`
= help: if this value is `None`, it will panic
+ = note: `-D clippy::expect-used` implied by `-D warnings`
error: used `expect()` on `a Result` value
--> $DIR/expect.rs:10:13
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.fixed b/src/tools/clippy/tests/ui/expect_fun_call.fixed
index 53e45d28b..15172ae34 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/expect_fun_call.fixed
@@ -1,7 +1,6 @@
// run-rustfix
-
#![warn(clippy::expect_fun_call)]
-#![allow(clippy::to_string_in_format_args)]
+#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
/// Checks implementation of the `EXPECT_FUN_CALL` lint
@@ -101,4 +100,10 @@ fn main() {
let opt_ref = &opt;
opt_ref.unwrap_or_else(|| panic!("{:?}", opt_ref));
}
+
+ let format_capture: Option<i32> = None;
+ format_capture.unwrap_or_else(|| panic!("{error_code}"));
+
+ let format_capture_and_value: Option<i32> = None;
+ format_capture_and_value.unwrap_or_else(|| panic!("{error_code}, {}", 1));
}
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.rs b/src/tools/clippy/tests/ui/expect_fun_call.rs
index 22e530b80..0f448d004 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.rs
+++ b/src/tools/clippy/tests/ui/expect_fun_call.rs
@@ -1,7 +1,6 @@
// run-rustfix
-
#![warn(clippy::expect_fun_call)]
-#![allow(clippy::to_string_in_format_args)]
+#![allow(clippy::to_string_in_format_args, clippy::uninlined_format_args)]
/// Checks implementation of the `EXPECT_FUN_CALL` lint
@@ -101,4 +100,10 @@ fn main() {
let opt_ref = &opt;
opt_ref.expect(&format!("{:?}", opt_ref));
}
+
+ let format_capture: Option<i32> = None;
+ format_capture.expect(&format!("{error_code}"));
+
+ let format_capture_and_value: Option<i32> = None;
+ format_capture_and_value.expect(&format!("{error_code}, {}", 1));
}
diff --git a/src/tools/clippy/tests/ui/expect_fun_call.stderr b/src/tools/clippy/tests/ui/expect_fun_call.stderr
index aca15935f..cb55e32ae 100644
--- a/src/tools/clippy/tests/ui/expect_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/expect_fun_call.stderr
@@ -1,5 +1,5 @@
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:35:26
+ --> $DIR/expect_fun_call.rs:34:26
|
LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
@@ -7,76 +7,88 @@ LL | with_none_and_format.expect(&format!("Error {}: fake error", error_code
= note: `-D clippy::expect-fun-call` implied by `-D warnings`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:38:26
+ --> $DIR/expect_fun_call.rs:37:26
|
LL | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:41:37
+ --> $DIR/expect_fun_call.rs:40:37
|
LL | with_none_and_format_with_macro.expect(format!("Error {}: fake error", one!()).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", one!()))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:51:25
+ --> $DIR/expect_fun_call.rs:50:25
|
LL | with_err_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:54:25
+ --> $DIR/expect_fun_call.rs:53:25
|
LL | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:66:17
+ --> $DIR/expect_fun_call.rs:65:17
|
LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:87:21
+ --> $DIR/expect_fun_call.rs:86:21
|
LL | Some("foo").expect(&get_string());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:88:21
+ --> $DIR/expect_fun_call.rs:87:21
|
LL | Some("foo").expect(get_string().as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:89:21
+ --> $DIR/expect_fun_call.rs:88:21
|
LL | Some("foo").expect(get_string().as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_string()) })`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:91:21
+ --> $DIR/expect_fun_call.rs:90:21
|
LL | Some("foo").expect(get_static_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_static_str()) })`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:92:21
+ --> $DIR/expect_fun_call.rs:91:21
|
LL | Some("foo").expect(get_non_static_str(&0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:96:16
+ --> $DIR/expect_fun_call.rs:95:16
|
LL | Some(true).expect(&format!("key {}, {}", 1, 2));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))`
error: use of `expect` followed by a function call
- --> $DIR/expect_fun_call.rs:102:17
+ --> $DIR/expect_fun_call.rs:101:17
|
LL | opt_ref.expect(&format!("{:?}", opt_ref));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{:?}", opt_ref))`
-error: aborting due to 13 previous errors
+error: use of `expect` followed by a function call
+ --> $DIR/expect_fun_call.rs:105:20
+ |
+LL | format_capture.expect(&format!("{error_code}"));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}"))`
+
+error: use of `expect` followed by a function call
+ --> $DIR/expect_fun_call.rs:108:30
+ |
+LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{error_code}, {}", 1))`
+
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.rs b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
index aa966761f..6eddc01e2 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.rs
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.rs
@@ -1,4 +1,5 @@
#![warn(clippy::explicit_counter_loop)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
let mut vec = vec![1, 2, 3, 4];
diff --git a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
index f9f8407d5..d3f3c626b 100644
--- a/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
+++ b/src/tools/clippy/tests/ui/explicit_counter_loop.stderr
@@ -1,5 +1,5 @@
error: the variable `_index` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:6:5
+ --> $DIR/explicit_counter_loop.rs:7:5
|
LL | for _v in &vec {
| ^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.iter().enumerate()`
@@ -7,49 +7,49 @@ LL | for _v in &vec {
= note: `-D clippy::explicit-counter-loop` implied by `-D warnings`
error: the variable `_index` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:12:5
+ --> $DIR/explicit_counter_loop.rs:13:5
|
LL | for _v in &vec {
| ^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.iter().enumerate()`
error: the variable `_index` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:17:5
+ --> $DIR/explicit_counter_loop.rs:18:5
|
LL | for _v in &mut vec {
| ^^^^^^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.iter_mut().enumerate()`
error: the variable `_index` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:22:5
+ --> $DIR/explicit_counter_loop.rs:23:5
|
LL | for _v in vec {
| ^^^^^^^^^^^^^ help: consider using: `for (_index, _v) in vec.into_iter().enumerate()`
error: the variable `count` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:61:9
+ --> $DIR/explicit_counter_loop.rs:62:9
|
LL | for ch in text.chars() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()`
error: the variable `count` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:72:9
+ --> $DIR/explicit_counter_loop.rs:73:9
|
LL | for ch in text.chars() {
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()`
error: the variable `count` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:130:9
+ --> $DIR/explicit_counter_loop.rs:131:9
|
LL | for _i in 3..10 {
| ^^^^^^^^^^^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()`
error: the variable `idx_usize` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:170:9
+ --> $DIR/explicit_counter_loop.rs:171:9
|
LL | for _item in slice {
| ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_usize, _item) in slice.iter().enumerate()`
error: the variable `idx_u32` is used as a loop counter
- --> $DIR/explicit_counter_loop.rs:182:9
+ --> $DIR/explicit_counter_loop.rs:183:9
|
LL | for _item in slice {
| ^^^^^^^^^^^^^^^^^^ help: consider using: `for (idx_u32, _item) in (0_u32..).zip(slice.iter())`
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
index 523cae183..6d32bbece 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed
@@ -1,13 +1,13 @@
// run-rustfix
-
+#![warn(clippy::explicit_deref_methods)]
+#![allow(unused_variables)]
#![allow(
- unused_variables,
+ clippy::borrow_deref_ref,
clippy::clone_double_ref,
+ clippy::explicit_auto_deref,
clippy::needless_borrow,
- clippy::borrow_deref_ref,
- clippy::explicit_auto_deref
+ clippy::uninlined_format_args
)]
-#![warn(clippy::explicit_deref_methods)]
use std::ops::{Deref, DerefMut};
diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
index 0bbc1ae57..779909e42 100644
--- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs
+++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs
@@ -1,13 +1,13 @@
// run-rustfix
-
+#![warn(clippy::explicit_deref_methods)]
+#![allow(unused_variables)]
#![allow(
- unused_variables,
+ clippy::borrow_deref_ref,
clippy::clone_double_ref,
+ clippy::explicit_auto_deref,
clippy::needless_borrow,
- clippy::borrow_deref_ref,
- clippy::explicit_auto_deref
+ clippy::uninlined_format_args
)]
-#![warn(clippy::explicit_deref_methods)]
use std::ops::{Deref, DerefMut};
diff --git a/src/tools/clippy/tests/ui/explicit_write.fixed b/src/tools/clippy/tests/ui/explicit_write.fixed
index 74d0e5290..862c3fea9 100644
--- a/src/tools/clippy/tests/ui/explicit_write.fixed
+++ b/src/tools/clippy/tests/ui/explicit_write.fixed
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused_imports)]
#![warn(clippy::explicit_write)]
+#![allow(unused_imports)]
+#![allow(clippy::uninlined_format_args)]
fn stdout() -> String {
String::new()
@@ -36,6 +37,8 @@ fn main() {
eprintln!("with {} {}", 2, value);
eprintln!("with {value}");
eprintln!("macro arg {}", one!());
+ let width = 2;
+ eprintln!("{:w$}", value, w = width);
}
// these should not warn, different destination
{
diff --git a/src/tools/clippy/tests/ui/explicit_write.rs b/src/tools/clippy/tests/ui/explicit_write.rs
index e7a698d3e..41d7c2255 100644
--- a/src/tools/clippy/tests/ui/explicit_write.rs
+++ b/src/tools/clippy/tests/ui/explicit_write.rs
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused_imports)]
#![warn(clippy::explicit_write)]
+#![allow(unused_imports)]
+#![allow(clippy::uninlined_format_args)]
fn stdout() -> String {
String::new()
@@ -36,6 +37,8 @@ fn main() {
writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
writeln!(std::io::stderr(), "with {value}").unwrap();
writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
+ let width = 2;
+ writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
}
// these should not warn, different destination
{
diff --git a/src/tools/clippy/tests/ui/explicit_write.stderr b/src/tools/clippy/tests/ui/explicit_write.stderr
index 29ae0cdec..457e9c627 100644
--- a/src/tools/clippy/tests/ui/explicit_write.stderr
+++ b/src/tools/clippy/tests/ui/explicit_write.stderr
@@ -1,5 +1,5 @@
error: use of `write!(stdout(), ...).unwrap()`
- --> $DIR/explicit_write.rs:23:9
+ --> $DIR/explicit_write.rs:24:9
|
LL | write!(std::io::stdout(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
@@ -7,70 +7,76 @@ LL | write!(std::io::stdout(), "test").unwrap();
= note: `-D clippy::explicit-write` implied by `-D warnings`
error: use of `write!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:24:9
+ --> $DIR/explicit_write.rs:25:9
|
LL | write!(std::io::stderr(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
error: use of `writeln!(stdout(), ...).unwrap()`
- --> $DIR/explicit_write.rs:25:9
+ --> $DIR/explicit_write.rs:26:9
|
LL | writeln!(std::io::stdout(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:26:9
+ --> $DIR/explicit_write.rs:27:9
|
LL | writeln!(std::io::stderr(), "test").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test")`
error: use of `stdout().write_fmt(...).unwrap()`
- --> $DIR/explicit_write.rs:27:9
+ --> $DIR/explicit_write.rs:28:9
|
LL | std::io::stdout().write_fmt(format_args!("test")).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `print!("test")`
error: use of `stderr().write_fmt(...).unwrap()`
- --> $DIR/explicit_write.rs:28:9
+ --> $DIR/explicit_write.rs:29:9
|
LL | std::io::stderr().write_fmt(format_args!("test")).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprint!("test")`
error: use of `writeln!(stdout(), ...).unwrap()`
- --> $DIR/explicit_write.rs:31:9
+ --> $DIR/explicit_write.rs:32:9
|
LL | writeln!(std::io::stdout(), "test/ntest").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `println!("test/ntest")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:32:9
+ --> $DIR/explicit_write.rs:33:9
|
LL | writeln!(std::io::stderr(), "test/ntest").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("test/ntest")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:35:9
+ --> $DIR/explicit_write.rs:36:9
|
LL | writeln!(std::io::stderr(), "with {}", value).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {}", value)`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:36:9
+ --> $DIR/explicit_write.rs:37:9
|
LL | writeln!(std::io::stderr(), "with {} {}", 2, value).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {} {}", 2, value)`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:37:9
+ --> $DIR/explicit_write.rs:38:9
|
LL | writeln!(std::io::stderr(), "with {value}").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("with {value}")`
error: use of `writeln!(stderr(), ...).unwrap()`
- --> $DIR/explicit_write.rs:38:9
+ --> $DIR/explicit_write.rs:39:9
|
LL | writeln!(std::io::stderr(), "macro arg {}", one!()).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("macro arg {}", one!())`
-error: aborting due to 12 previous errors
+error: use of `writeln!(stderr(), ...).unwrap()`
+ --> $DIR/explicit_write.rs:41:9
+ |
+LL | writeln!(std::io::stderr(), "{:w$}", value, w = width).unwrap();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `eprintln!("{:w$}", value, w = width)`
+
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.rs b/src/tools/clippy/tests/ui/fallible_impl_from.rs
index 5d5af4e46..fb6e8ec70 100644
--- a/src/tools/clippy/tests/ui/fallible_impl_from.rs
+++ b/src/tools/clippy/tests/ui/fallible_impl_from.rs
@@ -1,4 +1,5 @@
#![deny(clippy::fallible_impl_from)]
+#![allow(clippy::uninlined_format_args)]
// docs example
struct Foo(i32);
diff --git a/src/tools/clippy/tests/ui/fallible_impl_from.stderr b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
index d637dbce5..21761484f 100644
--- a/src/tools/clippy/tests/ui/fallible_impl_from.stderr
+++ b/src/tools/clippy/tests/ui/fallible_impl_from.stderr
@@ -1,5 +1,5 @@
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:5:1
+ --> $DIR/fallible_impl_from.rs:6:1
|
LL | / impl From<String> for Foo {
LL | | fn from(s: String) -> Self {
@@ -8,20 +8,20 @@ LL | | }
LL | | }
| |_^
|
-note: the lint level is defined here
- --> $DIR/fallible_impl_from.rs:1:9
- |
-LL | #![deny(clippy::fallible_impl_from)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:7:13
+ --> $DIR/fallible_impl_from.rs:8:13
|
LL | Foo(s.parse().unwrap())
| ^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+ --> $DIR/fallible_impl_from.rs:1:9
+ |
+LL | #![deny(clippy::fallible_impl_from)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:26:1
+ --> $DIR/fallible_impl_from.rs:27:1
|
LL | / impl From<usize> for Invalid {
LL | | fn from(i: usize) -> Invalid {
@@ -34,14 +34,14 @@ LL | | }
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:29:13
+ --> $DIR/fallible_impl_from.rs:30:13
|
LL | panic!();
| ^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:35:1
+ --> $DIR/fallible_impl_from.rs:36:1
|
LL | / impl From<Option<String>> for Invalid {
LL | | fn from(s: Option<String>) -> Invalid {
@@ -54,7 +54,7 @@ LL | | }
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:37:17
+ --> $DIR/fallible_impl_from.rs:38:17
|
LL | let s = s.unwrap();
| ^^^^^^^^^^
@@ -68,7 +68,7 @@ LL | panic!("{:?}", s);
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
error: consider implementing `TryFrom` instead
- --> $DIR/fallible_impl_from.rs:53:1
+ --> $DIR/fallible_impl_from.rs:54:1
|
LL | / impl<'a> From<&'a mut <Box<u32> as ProjStrTrait>::ProjString> for Invalid {
LL | | fn from(s: &'a mut <Box<u32> as ProjStrTrait>::ProjString) -> Invalid {
@@ -81,7 +81,7 @@ LL | | }
|
= help: `From` is intended for infallible conversions only. Use `TryFrom` if there's a possibility for the conversion to fail
note: potential failure(s)
- --> $DIR/fallible_impl_from.rs:55:12
+ --> $DIR/fallible_impl_from.rs:56:12
|
LL | if s.parse::<u32>().ok().unwrap() != 42 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
index 3ce4b91a5..710bb66a4 100644
--- a/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
+++ b/src/tools/clippy/tests/ui/field_reassign_with_default.stderr
@@ -4,12 +4,12 @@ error: field assignment outside of initializer for an instance created with Defa
LL | a.i = 42;
| ^^^^^^^^^
|
- = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
note: consider initializing the variable with `main::A { i: 42, ..Default::default() }` and removing relevant reassignments
--> $DIR/field_reassign_with_default.rs:62:5
|
LL | let mut a: A = Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::field-reassign-with-default` implied by `-D warnings`
error: field assignment outside of initializer for an instance created with Default::default()
--> $DIR/field_reassign_with_default.rs:103:5
diff --git a/src/tools/clippy/tests/ui/filetype_is_file.stderr b/src/tools/clippy/tests/ui/filetype_is_file.stderr
index cd1e3ac37..e51a90d6c 100644
--- a/src/tools/clippy/tests/ui/filetype_is_file.stderr
+++ b/src/tools/clippy/tests/ui/filetype_is_file.stderr
@@ -4,8 +4,8 @@ error: `FileType::is_file()` only covers regular files
LL | if fs::metadata("foo.txt")?.file_type().is_file() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::filetype-is-file` implied by `-D warnings`
= help: use `!FileType::is_dir()` instead
+ = note: `-D clippy::filetype-is-file` implied by `-D warnings`
error: `!FileType::is_file()` only denies regular files
--> $DIR/filetype_is_file.rs:13:8
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
index c3992d7e9..41828ddd7 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.fixed
@@ -1,6 +1,8 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![warn(clippy::all, clippy::pedantic)]
+#![allow(unused)]
fn main() {
let a = ["1", "lol", "3", "NaN", "5"];
@@ -8,3 +10,17 @@ fn main() {
let element: Option<i32> = a.iter().find_map(|s| s.parse().ok());
assert_eq!(element, Some(1));
}
+
+fn msrv_1_29() {
+ #![clippy::msrv = "1.29"]
+
+ let a = ["1", "lol", "3", "NaN", "5"];
+ let _: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+}
+
+fn msrv_1_30() {
+ #![clippy::msrv = "1.30"]
+
+ let a = ["1", "lol", "3", "NaN", "5"];
+ let _: Option<i32> = a.iter().find_map(|s| s.parse().ok());
+}
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
index 447219a96..be492a81b 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.rs
@@ -1,6 +1,8 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![warn(clippy::all, clippy::pedantic)]
+#![allow(unused)]
fn main() {
let a = ["1", "lol", "3", "NaN", "5"];
@@ -8,3 +10,17 @@ fn main() {
let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
assert_eq!(element, Some(1));
}
+
+fn msrv_1_29() {
+ #![clippy::msrv = "1.29"]
+
+ let a = ["1", "lol", "3", "NaN", "5"];
+ let _: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+}
+
+fn msrv_1_30() {
+ #![clippy::msrv = "1.30"]
+
+ let a = ["1", "lol", "3", "NaN", "5"];
+ let _: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+}
diff --git a/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr b/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
index 3bb062ffd..e789efeab 100644
--- a/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
+++ b/src/tools/clippy/tests/ui/filter_map_next_fixable.stderr
@@ -1,10 +1,16 @@
error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead
- --> $DIR/filter_map_next_fixable.rs:8:32
+ --> $DIR/filter_map_next_fixable.rs:10:32
|
LL | let element: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())`
|
= note: `-D clippy::filter-map-next` implied by `-D warnings`
-error: aborting due to previous error
+error: called `filter_map(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find_map(..)` instead
+ --> $DIR/filter_map_next_fixable.rs:25:26
+ |
+LL | let _: Option<i32> = a.iter().filter_map(|s| s.parse().ok()).next();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `a.iter().find_map(|s| s.parse().ok())`
+
+error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/float_cmp.stderr b/src/tools/clippy/tests/ui/float_cmp.stderr
index 9cc1f1b75..e3e9f3949 100644
--- a/src/tools/clippy/tests/ui/float_cmp.stderr
+++ b/src/tools/clippy/tests/ui/float_cmp.stderr
@@ -4,8 +4,8 @@ error: strict comparison of `f32` or `f64`
LL | ONE as f64 != 2.0;
| ^^^^^^^^^^^^^^^^^ help: consider comparing them within some margin of error: `(ONE as f64 - 2.0).abs() > error_margin`
|
- = note: `-D clippy::float-cmp` implied by `-D warnings`
= note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
+ = note: `-D clippy::float-cmp` implied by `-D warnings`
error: strict comparison of `f32` or `f64`
--> $DIR/float_cmp.rs:62:5
diff --git a/src/tools/clippy/tests/ui/float_cmp_const.stderr b/src/tools/clippy/tests/ui/float_cmp_const.stderr
index d8182cf85..65c45648a 100644
--- a/src/tools/clippy/tests/ui/float_cmp_const.stderr
+++ b/src/tools/clippy/tests/ui/float_cmp_const.stderr
@@ -4,8 +4,8 @@ error: strict comparison of `f32` or `f64` constant
LL | 1f32 == ONE;
| ^^^^^^^^^^^ help: consider comparing them within some margin of error: `(1f32 - ONE).abs() < error_margin`
|
- = note: `-D clippy::float-cmp-const` implied by `-D warnings`
= note: `f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`
+ = note: `-D clippy::float-cmp-const` implied by `-D warnings`
error: strict comparison of `f32` or `f64` constant
--> $DIR/float_cmp_const.rs:17:5
diff --git a/src/tools/clippy/tests/ui/floating_point_exp.fixed b/src/tools/clippy/tests/ui/floating_point_exp.fixed
index c86a502d1..b9e3d89c2 100644
--- a/src/tools/clippy/tests/ui/floating_point_exp.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_exp.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 2f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_exp.rs b/src/tools/clippy/tests/ui/floating_point_exp.rs
index e59589f91..ef008dd9b 100644
--- a/src/tools/clippy/tests/ui/floating_point_exp.rs
+++ b/src/tools/clippy/tests/ui/floating_point_exp.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 2f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_exp.stderr b/src/tools/clippy/tests/ui/floating_point_exp.stderr
index f84eede19..b92fae56e 100644
--- a/src/tools/clippy/tests/ui/floating_point_exp.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_exp.stderr
@@ -1,5 +1,5 @@
error: (e.pow(x) - 1) can be computed more accurately
- --> $DIR/floating_point_exp.rs:6:13
+ --> $DIR/floating_point_exp.rs:7:13
|
LL | let _ = x.exp() - 1.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
@@ -7,25 +7,25 @@ LL | let _ = x.exp() - 1.0;
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: (e.pow(x) - 1) can be computed more accurately
- --> $DIR/floating_point_exp.rs:7:13
+ --> $DIR/floating_point_exp.rs:8:13
|
LL | let _ = x.exp() - 1.0 + 2.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
error: (e.pow(x) - 1) can be computed more accurately
- --> $DIR/floating_point_exp.rs:8:13
+ --> $DIR/floating_point_exp.rs:9:13
|
LL | let _ = (x as f32).exp() - 1.0 + 2.0;
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).exp_m1()`
error: (e.pow(x) - 1) can be computed more accurately
- --> $DIR/floating_point_exp.rs:14:13
+ --> $DIR/floating_point_exp.rs:15:13
|
LL | let _ = x.exp() - 1.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
error: (e.pow(x) - 1) can be computed more accurately
- --> $DIR/floating_point_exp.rs:15:13
+ --> $DIR/floating_point_exp.rs:16:13
|
LL | let _ = x.exp() - 1.0 + 2.0;
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
diff --git a/src/tools/clippy/tests/ui/floating_point_log.fixed b/src/tools/clippy/tests/ui/floating_point_log.fixed
index 4def9300b..ee5406461 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_log.fixed
@@ -1,5 +1,5 @@
// run-rustfix
-#![allow(dead_code, clippy::double_parens)]
+#![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
const TWO: f32 = 2.0;
diff --git a/src/tools/clippy/tests/ui/floating_point_log.rs b/src/tools/clippy/tests/ui/floating_point_log.rs
index 1e04caa7d..0590670a5 100644
--- a/src/tools/clippy/tests/ui/floating_point_log.rs
+++ b/src/tools/clippy/tests/ui/floating_point_log.rs
@@ -1,5 +1,5 @@
// run-rustfix
-#![allow(dead_code, clippy::double_parens)]
+#![allow(dead_code, clippy::double_parens, clippy::unnecessary_cast)]
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
const TWO: f32 = 2.0;
diff --git a/src/tools/clippy/tests/ui/floating_point_logbase.fixed b/src/tools/clippy/tests/ui/floating_point_logbase.fixed
index 936462f94..7347bf72c 100644
--- a/src/tools/clippy/tests/ui/floating_point_logbase.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_logbase.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 3f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_logbase.rs b/src/tools/clippy/tests/ui/floating_point_logbase.rs
index 0b56fa8fa..ba5b8d406 100644
--- a/src/tools/clippy/tests/ui/floating_point_logbase.rs
+++ b/src/tools/clippy/tests/ui/floating_point_logbase.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 3f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_logbase.stderr b/src/tools/clippy/tests/ui/floating_point_logbase.stderr
index 384e3554c..9d736b5e1 100644
--- a/src/tools/clippy/tests/ui/floating_point_logbase.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_logbase.stderr
@@ -1,5 +1,5 @@
error: log base can be expressed more clearly
- --> $DIR/floating_point_logbase.rs:7:13
+ --> $DIR/floating_point_logbase.rs:8:13
|
LL | let _ = x.ln() / y.ln();
| ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
@@ -7,25 +7,25 @@ LL | let _ = x.ln() / y.ln();
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: log base can be expressed more clearly
- --> $DIR/floating_point_logbase.rs:8:13
+ --> $DIR/floating_point_logbase.rs:9:13
|
LL | let _ = (x as f32).ln() / y.ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).log(y)`
error: log base can be expressed more clearly
- --> $DIR/floating_point_logbase.rs:9:13
+ --> $DIR/floating_point_logbase.rs:10:13
|
LL | let _ = x.log2() / y.log2();
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
error: log base can be expressed more clearly
- --> $DIR/floating_point_logbase.rs:10:13
+ --> $DIR/floating_point_logbase.rs:11:13
|
LL | let _ = x.log10() / y.log10();
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
error: log base can be expressed more clearly
- --> $DIR/floating_point_logbase.rs:11:13
+ --> $DIR/floating_point_logbase.rs:12:13
|
LL | let _ = x.log(5f32) / y.log(5f32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
index 169ec02f8..d3e536ba3 100644
--- a/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_mul_add.fixed
@@ -19,7 +19,9 @@ fn main() {
let d: f64 = 0.0001;
let _ = a.mul_add(b, c);
+ let _ = a.mul_add(b, -c);
let _ = a.mul_add(b, c);
+ let _ = a.mul_add(-b, c);
let _ = 2.0f64.mul_add(4.0, a);
let _ = 2.0f64.mul_add(4., a);
diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.rs b/src/tools/clippy/tests/ui/floating_point_mul_add.rs
index 5338d4fc2..5d4a9e35c 100644
--- a/src/tools/clippy/tests/ui/floating_point_mul_add.rs
+++ b/src/tools/clippy/tests/ui/floating_point_mul_add.rs
@@ -19,7 +19,9 @@ fn main() {
let d: f64 = 0.0001;
let _ = a * b + c;
+ let _ = a * b - c;
let _ = c + a * b;
+ let _ = c - a * b;
let _ = a + 2.0 * 4.0;
let _ = a + 2. * 4.;
diff --git a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr
index e637bbf90..a79ae94e8 100644
--- a/src/tools/clippy/tests/ui/floating_point_mul_add.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_mul_add.stderr
@@ -9,56 +9,68 @@ LL | let _ = a * b + c;
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:22:13
|
+LL | let _ = a * b - c;
+ | ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_mul_add.rs:23:13
+ |
LL | let _ = c + a * b;
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:23:13
+ --> $DIR/floating_point_mul_add.rs:24:13
+ |
+LL | let _ = c - a * b;
+ | ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_mul_add.rs:25:13
|
LL | let _ = a + 2.0 * 4.0;
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:24:13
+ --> $DIR/floating_point_mul_add.rs:26:13
|
LL | let _ = a + 2. * 4.;
| ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:26:13
+ --> $DIR/floating_point_mul_add.rs:28:13
|
LL | let _ = (a * b) + c;
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:27:13
+ --> $DIR/floating_point_mul_add.rs:29:13
|
LL | let _ = c + (a * b);
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:28:13
+ --> $DIR/floating_point_mul_add.rs:30:13
|
LL | let _ = a * b * c + d;
| ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:30:13
+ --> $DIR/floating_point_mul_add.rs:32:13
|
LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:31:13
+ --> $DIR/floating_point_mul_add.rs:33:13
|
LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_mul_add.rs:33:13
+ --> $DIR/floating_point_mul_add.rs:35:13
|
LL | let _ = (a * a + b).sqrt();
| ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)`
-error: aborting due to 10 previous errors
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.fixed b/src/tools/clippy/tests/ui/floating_point_powf.fixed
index e7ef45634..f7f93de29 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powf.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 3f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.rs b/src/tools/clippy/tests/ui/floating_point_powf.rs
index d749aa2d4..499fc0e15 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powf.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let x = 3f32;
diff --git a/src/tools/clippy/tests/ui/floating_point_powf.stderr b/src/tools/clippy/tests/ui/floating_point_powf.stderr
index e9693de8f..7c9d50db2 100644
--- a/src/tools/clippy/tests/ui/floating_point_powf.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_powf.stderr
@@ -1,5 +1,5 @@
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:6:13
+ --> $DIR/floating_point_powf.rs:7:13
|
LL | let _ = 2f32.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
@@ -7,43 +7,43 @@ LL | let _ = 2f32.powf(x);
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:7:13
+ --> $DIR/floating_point_powf.rs:8:13
|
LL | let _ = 2f32.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp2()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:8:13
+ --> $DIR/floating_point_powf.rs:9:13
|
LL | let _ = 2f32.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp2()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:9:13
+ --> $DIR/floating_point_powf.rs:10:13
|
LL | let _ = std::f32::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:10:13
+ --> $DIR/floating_point_powf.rs:11:13
|
LL | let _ = std::f32::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f32.exp()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:11:13
+ --> $DIR/floating_point_powf.rs:12:13
|
LL | let _ = std::f32::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f32).exp()`
error: square-root of a number can be computed more efficiently and accurately
- --> $DIR/floating_point_powf.rs:12:13
+ --> $DIR/floating_point_powf.rs:13:13
|
LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately
- --> $DIR/floating_point_powf.rs:13:13
+ --> $DIR/floating_point_powf.rs:14:13
|
LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
@@ -51,139 +51,139 @@ LL | let _ = x.powf(1.0 / 3.0);
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: cube-root of a number can be computed more accurately
- --> $DIR/floating_point_powf.rs:14:13
+ --> $DIR/floating_point_powf.rs:15:13
|
LL | let _ = (x as f32).powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).cbrt()`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:15:13
+ --> $DIR/floating_point_powf.rs:16:13
|
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:16:13
+ --> $DIR/floating_point_powf.rs:17:13
|
LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:17:13
+ --> $DIR/floating_point_powf.rs:18:13
|
LL | let _ = x.powf(16_777_215.0);
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(16_777_215)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:18:13
+ --> $DIR/floating_point_powf.rs:19:13
|
LL | let _ = x.powf(-16_777_215.0);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-16_777_215)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:19:13
+ --> $DIR/floating_point_powf.rs:20:13
|
LL | let _ = (x as f32).powf(-16_777_215.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).powi(-16_777_215)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:20:13
+ --> $DIR/floating_point_powf.rs:21:13
|
LL | let _ = (x as f32).powf(3.0);
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x as f32).powi(3)`
error: cube-root of a number can be computed more accurately
- --> $DIR/floating_point_powf.rs:21:13
+ --> $DIR/floating_point_powf.rs:22:13
|
LL | let _ = (1.5_f32 + 1.0).powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(1.5_f32 + 1.0).cbrt()`
error: cube-root of a number can be computed more accurately
- --> $DIR/floating_point_powf.rs:22:13
+ --> $DIR/floating_point_powf.rs:23:13
|
LL | let _ = 1.5_f64.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.cbrt()`
error: square-root of a number can be computed more efficiently and accurately
- --> $DIR/floating_point_powf.rs:23:13
+ --> $DIR/floating_point_powf.rs:24:13
|
LL | let _ = 1.5_f64.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.sqrt()`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:24:13
+ --> $DIR/floating_point_powf.rs:25:13
|
LL | let _ = 1.5_f64.powf(3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `1.5_f64.powi(3)`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:33:13
+ --> $DIR/floating_point_powf.rs:34:13
|
LL | let _ = 2f64.powf(x);
| ^^^^^^^^^^^^ help: consider using: `x.exp2()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:34:13
+ --> $DIR/floating_point_powf.rs:35:13
|
LL | let _ = 2f64.powf(3.1);
| ^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp2()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:35:13
+ --> $DIR/floating_point_powf.rs:36:13
|
LL | let _ = 2f64.powf(-3.1);
| ^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp2()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:36:13
+ --> $DIR/floating_point_powf.rs:37:13
|
LL | let _ = std::f64::consts::E.powf(x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.exp()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:37:13
+ --> $DIR/floating_point_powf.rs:38:13
|
LL | let _ = std::f64::consts::E.powf(3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `3.1f64.exp()`
error: exponent for bases 2 and e can be computed more accurately
- --> $DIR/floating_point_powf.rs:38:13
+ --> $DIR/floating_point_powf.rs:39:13
|
LL | let _ = std::f64::consts::E.powf(-3.1);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-3.1f64).exp()`
error: square-root of a number can be computed more efficiently and accurately
- --> $DIR/floating_point_powf.rs:39:13
+ --> $DIR/floating_point_powf.rs:40:13
|
LL | let _ = x.powf(1.0 / 2.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.sqrt()`
error: cube-root of a number can be computed more accurately
- --> $DIR/floating_point_powf.rs:40:13
+ --> $DIR/floating_point_powf.rs:41:13
|
LL | let _ = x.powf(1.0 / 3.0);
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:41:13
+ --> $DIR/floating_point_powf.rs:42:13
|
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:42:13
+ --> $DIR/floating_point_powf.rs:43:13
|
LL | let _ = x.powf(-2.0);
| ^^^^^^^^^^^^ help: consider using: `x.powi(-2)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:43:13
+ --> $DIR/floating_point_powf.rs:44:13
|
LL | let _ = x.powf(-2_147_483_648.0);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(-2_147_483_648)`
error: exponentiation with integer powers can be computed more efficiently
- --> $DIR/floating_point_powf.rs:44:13
+ --> $DIR/floating_point_powf.rs:45:13
|
LL | let _ = x.powf(2_147_483_647.0);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2_147_483_647)`
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.fixed b/src/tools/clippy/tests/ui/floating_point_powi.fixed
index 5758db7c6..884d05fed 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.fixed
+++ b/src/tools/clippy/tests/ui/floating_point_powi.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let one = 1;
@@ -7,7 +8,9 @@ fn main() {
let y = 4f32;
let _ = x.mul_add(x, y);
+ let _ = x.mul_add(x, -y);
let _ = y.mul_add(y, x);
+ let _ = y.mul_add(-y, x);
let _ = (y as f32).mul_add(y as f32, x);
let _ = x.mul_add(x, y).sqrt();
let _ = y.mul_add(y, x).sqrt();
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.rs b/src/tools/clippy/tests/ui/floating_point_powi.rs
index 5926bf1b0..e6a1c8953 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.rs
+++ b/src/tools/clippy/tests/ui/floating_point_powi.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
+#![allow(clippy::unnecessary_cast)]
fn main() {
let one = 1;
@@ -7,7 +8,9 @@ fn main() {
let y = 4f32;
let _ = x.powi(2) + y;
+ let _ = x.powi(2) - y;
let _ = x + y.powi(2);
+ let _ = x - y.powi(2);
let _ = x + (y as f32).powi(2);
let _ = (x.powi(2) + y).sqrt();
let _ = (x + y.powi(2)).sqrt();
diff --git a/src/tools/clippy/tests/ui/floating_point_powi.stderr b/src/tools/clippy/tests/ui/floating_point_powi.stderr
index a3c745442..5df0de1fe 100644
--- a/src/tools/clippy/tests/ui/floating_point_powi.stderr
+++ b/src/tools/clippy/tests/ui/floating_point_powi.stderr
@@ -1,5 +1,5 @@
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_powi.rs:9:13
+ --> $DIR/floating_point_powi.rs:10:13
|
LL | let _ = x.powi(2) + y;
| ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
@@ -7,28 +7,40 @@ LL | let _ = x.powi(2) + y;
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_powi.rs:10:13
+ --> $DIR/floating_point_powi.rs:11:13
+ |
+LL | let _ = x.powi(2) - y;
+ | ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, -y)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:12:13
|
LL | let _ = x + y.powi(2);
| ^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_powi.rs:11:13
+ --> $DIR/floating_point_powi.rs:13:13
+ |
+LL | let _ = x - y.powi(2);
+ | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-y, x)`
+
+error: multiply and add expressions can be calculated more efficiently and accurately
+ --> $DIR/floating_point_powi.rs:14:13
|
LL | let _ = x + (y as f32).powi(2);
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(y as f32).mul_add(y as f32, x)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_powi.rs:12:13
+ --> $DIR/floating_point_powi.rs:15:13
|
LL | let _ = (x.powi(2) + y).sqrt();
| ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
error: multiply and add expressions can be calculated more efficiently and accurately
- --> $DIR/floating_point_powi.rs:13:13
+ --> $DIR/floating_point_powi.rs:16:13
|
LL | let _ = (x + y.powi(2)).sqrt();
| ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
-error: aborting due to 5 previous errors
+error: aborting due to 7 previous errors
diff --git a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
index cd9d07fa1..116271056 100644
--- a/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
+++ b/src/tools/clippy/tests/ui/fn_params_excessive_bools.stderr
@@ -4,8 +4,8 @@ error: more than 3 bools in function parameters
LL | fn g(_: bool, _: bool, _: bool, _: bool) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
= help: consider refactoring bools into two-variant enums
+ = note: `-D clippy::fn-params-excessive-bools` implied by `-D warnings`
error: more than 3 bools in function parameters
--> $DIR/fn_params_excessive_bools.rs:21:1
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.fixed b/src/tools/clippy/tests/ui/for_loop_fixable.fixed
index aa69781d1..e9dd38fe4 100644
--- a/src/tools/clippy/tests/ui/for_loop_fixable.fixed
+++ b/src/tools/clippy/tests/ui/for_loop_fixable.fixed
@@ -1,6 +1,6 @@
// run-rustfix
-
#![allow(dead_code, unused)]
+#![allow(clippy::uninlined_format_args)]
use std::collections::*;
diff --git a/src/tools/clippy/tests/ui/for_loop_fixable.rs b/src/tools/clippy/tests/ui/for_loop_fixable.rs
index 7c063d995..534fb4dd4 100644
--- a/src/tools/clippy/tests/ui/for_loop_fixable.rs
+++ b/src/tools/clippy/tests/ui/for_loop_fixable.rs
@@ -1,6 +1,6 @@
// run-rustfix
-
#![allow(dead_code, unused)]
+#![allow(clippy::uninlined_format_args)]
use std::collections::*;
diff --git a/src/tools/clippy/tests/ui/for_loop_unfixable.rs b/src/tools/clippy/tests/ui/for_loop_unfixable.rs
index efcaffce2..55fb3788a 100644
--- a/src/tools/clippy/tests/ui/for_loop_unfixable.rs
+++ b/src/tools/clippy/tests/ui/for_loop_unfixable.rs
@@ -8,6 +8,7 @@
clippy::for_kv_map
)]
#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)]
+#[allow(for_loops_over_fallibles)]
fn main() {
let vec = vec![1, 2, 3, 4];
diff --git a/src/tools/clippy/tests/ui/for_loop_unfixable.stderr b/src/tools/clippy/tests/ui/for_loop_unfixable.stderr
index f769b4bdc..50a86eaa6 100644
--- a/src/tools/clippy/tests/ui/for_loop_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/for_loop_unfixable.stderr
@@ -1,5 +1,5 @@
error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
- --> $DIR/for_loop_unfixable.rs:14:15
+ --> $DIR/for_loop_unfixable.rs:15:15
|
LL | for _v in vec.iter().next() {}
| ^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/for_loops_over_fallibles.rs b/src/tools/clippy/tests/ui/for_loops_over_fallibles.rs
deleted file mode 100644
index 3390111d0..000000000
--- a/src/tools/clippy/tests/ui/for_loops_over_fallibles.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-#![warn(clippy::for_loops_over_fallibles)]
-
-fn for_loops_over_fallibles() {
- let option = Some(1);
- let mut result = option.ok_or("x not found");
- let v = vec![0, 1, 2];
-
- // check over an `Option`
- for x in option {
- println!("{}", x);
- }
-
- // check over an `Option`
- for x in option.iter() {
- println!("{}", x);
- }
-
- // check over a `Result`
- for x in result {
- println!("{}", x);
- }
-
- // check over a `Result`
- for x in result.iter_mut() {
- println!("{}", x);
- }
-
- // check over a `Result`
- for x in result.into_iter() {
- println!("{}", x);
- }
-
- for x in option.ok_or("x not found") {
- println!("{}", x);
- }
-
- // make sure LOOP_OVER_NEXT lint takes clippy::precedence when next() is the last call
- // in the chain
- for x in v.iter().next() {
- println!("{}", x);
- }
-
- // make sure we lint when next() is not the last call in the chain
- for x in v.iter().next().and(Some(0)) {
- println!("{}", x);
- }
-
- for x in v.iter().next().ok_or("x not found") {
- println!("{}", x);
- }
-
- // check for false positives
-
- // for loop false positive
- for x in v {
- println!("{}", x);
- }
-
- // while let false positive for Option
- while let Some(x) = option {
- println!("{}", x);
- break;
- }
-
- // while let false positive for Result
- while let Ok(x) = result {
- println!("{}", x);
- break;
- }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/for_loops_over_fallibles.stderr b/src/tools/clippy/tests/ui/for_loops_over_fallibles.stderr
deleted file mode 100644
index 8c8c02224..000000000
--- a/src/tools/clippy/tests/ui/for_loops_over_fallibles.stderr
+++ /dev/null
@@ -1,95 +0,0 @@
-error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:9:14
- |
-LL | for x in option {
- | ^^^^^^
- |
- = note: `-D clippy::for-loops-over-fallibles` implied by `-D warnings`
- = help: consider replacing `for x in option` with `if let Some(x) = option`
-
-error: for loop over `option`, which is an `Option`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:14:14
- |
-LL | for x in option.iter() {
- | ^^^^^^
- |
- = help: consider replacing `for x in option.iter()` with `if let Some(x) = option`
-
-error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:19:14
- |
-LL | for x in result {
- | ^^^^^^
- |
- = help: consider replacing `for x in result` with `if let Ok(x) = result`
-
-error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:24:14
- |
-LL | for x in result.iter_mut() {
- | ^^^^^^
- |
- = help: consider replacing `for x in result.iter_mut()` with `if let Ok(x) = result`
-
-error: for loop over `result`, which is a `Result`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:29:14
- |
-LL | for x in result.into_iter() {
- | ^^^^^^
- |
- = help: consider replacing `for x in result.into_iter()` with `if let Ok(x) = result`
-
-error: for loop over `option.ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:33:14
- |
-LL | for x in option.ok_or("x not found") {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider replacing `for x in option.ok_or("x not found")` with `if let Ok(x) = option.ok_or("x not found")`
-
-error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want
- --> $DIR/for_loops_over_fallibles.rs:39:14
- |
-LL | for x in v.iter().next() {
- | ^^^^^^^^^^^^^^^
- |
- = note: `#[deny(clippy::iter_next_loop)]` on by default
-
-error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:44:14
- |
-LL | for x in v.iter().next().and(Some(0)) {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider replacing `for x in v.iter().next().and(Some(0))` with `if let Some(x) = v.iter().next().and(Some(0))`
-
-error: for loop over `v.iter().next().ok_or("x not found")`, which is a `Result`. This is more readably written as an `if let` statement
- --> $DIR/for_loops_over_fallibles.rs:48:14
- |
-LL | for x in v.iter().next().ok_or("x not found") {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
- = help: consider replacing `for x in v.iter().next().ok_or("x not found")` with `if let Ok(x) = v.iter().next().ok_or("x not found")`
-
-error: this loop never actually loops
- --> $DIR/for_loops_over_fallibles.rs:60:5
- |
-LL | / while let Some(x) = option {
-LL | | println!("{}", x);
-LL | | break;
-LL | | }
- | |_____^
- |
- = note: `#[deny(clippy::never_loop)]` on by default
-
-error: this loop never actually loops
- --> $DIR/for_loops_over_fallibles.rs:66:5
- |
-LL | / while let Ok(x) = result {
-LL | | println!("{}", x);
-LL | | break;
-LL | | }
- | |_____^
-
-error: aborting due to 11 previous errors
-
diff --git a/src/tools/clippy/tests/ui/forget_non_drop.stderr b/src/tools/clippy/tests/ui/forget_non_drop.stderr
index 03fb00960..194e37c8b 100644
--- a/src/tools/clippy/tests/ui/forget_non_drop.stderr
+++ b/src/tools/clippy/tests/ui/forget_non_drop.stderr
@@ -4,12 +4,12 @@ error: call to `std::mem::forget` with a value that does not implement `Drop`. F
LL | forget(Foo);
| ^^^^^^^^^^^
|
- = note: `-D clippy::forget-non-drop` implied by `-D warnings`
note: argument has type `main::Foo`
--> $DIR/forget_non_drop.rs:13:12
|
LL | forget(Foo);
| ^^^
+ = note: `-D clippy::forget-non-drop` implied by `-D warnings`
error: call to `std::mem::forget` with a value that does not implement `Drop`. Forgetting such a type is the same as dropping it
--> $DIR/forget_non_drop.rs:24:5
diff --git a/src/tools/clippy/tests/ui/forget_ref.stderr b/src/tools/clippy/tests/ui/forget_ref.stderr
index df5cd8cac..011cdefc6 100644
--- a/src/tools/clippy/tests/ui/forget_ref.stderr
+++ b/src/tools/clippy/tests/ui/forget_ref.stderr
@@ -4,12 +4,12 @@ error: calls to `std::mem::forget` with a reference instead of an owned value. F
LL | forget(&SomeStruct);
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::forget-ref` implied by `-D warnings`
note: argument has type `&SomeStruct`
--> $DIR/forget_ref.rs:11:12
|
LL | forget(&SomeStruct);
| ^^^^^^^^^^^
+ = note: `-D clippy::forget-ref` implied by `-D warnings`
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing
--> $DIR/forget_ref.rs:14:5
diff --git a/src/tools/clippy/tests/ui/format.fixed b/src/tools/clippy/tests/ui/format.fixed
index b56d6aec5..beedf2c1d 100644
--- a/src/tools/clippy/tests/ui/format.fixed
+++ b/src/tools/clippy/tests/ui/format.fixed
@@ -1,13 +1,13 @@
// run-rustfix
-
+#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
clippy::print_literal,
clippy::redundant_clone,
clippy::to_string_in_format_args,
- clippy::needless_borrow
+ clippy::needless_borrow,
+ clippy::uninlined_format_args
)]
-#![warn(clippy::useless_format)]
struct Foo(pub String);
@@ -28,8 +28,6 @@ fn main() {
format!("{:?}", "foo"); // Don't warn about `Debug`.
format!("{:8}", "foo");
format!("{:width$}", "foo", width = 8);
- "foo".to_string(); // Warn when the format makes no difference.
- "foo".to_string(); // Warn when the format makes no difference.
format!("foo {}", "bar");
format!("{} bar", "foo");
@@ -38,8 +36,6 @@ fn main() {
format!("{:?}", arg); // Don't warn about debug.
format!("{:8}", arg);
format!("{:width$}", arg, width = 8);
- arg.to_string(); // Warn when the format makes no difference.
- arg.to_string(); // Warn when the format makes no difference.
format!("foo {}", arg);
format!("{} bar", arg);
diff --git a/src/tools/clippy/tests/ui/format.rs b/src/tools/clippy/tests/ui/format.rs
index 4c1a3a840..e805f1818 100644
--- a/src/tools/clippy/tests/ui/format.rs
+++ b/src/tools/clippy/tests/ui/format.rs
@@ -1,13 +1,13 @@
// run-rustfix
-
+#![warn(clippy::useless_format)]
#![allow(
unused_tuple_struct_fields,
clippy::print_literal,
clippy::redundant_clone,
clippy::to_string_in_format_args,
- clippy::needless_borrow
+ clippy::needless_borrow,
+ clippy::uninlined_format_args
)]
-#![warn(clippy::useless_format)]
struct Foo(pub String);
@@ -30,8 +30,6 @@ fn main() {
format!("{:?}", "foo"); // Don't warn about `Debug`.
format!("{:8}", "foo");
format!("{:width$}", "foo", width = 8);
- format!("{:+}", "foo"); // Warn when the format makes no difference.
- format!("{:<}", "foo"); // Warn when the format makes no difference.
format!("foo {}", "bar");
format!("{} bar", "foo");
@@ -40,8 +38,6 @@ fn main() {
format!("{:?}", arg); // Don't warn about debug.
format!("{:8}", arg);
format!("{:width$}", arg, width = 8);
- format!("{:+}", arg); // Warn when the format makes no difference.
- format!("{:<}", arg); // Warn when the format makes no difference.
format!("foo {}", arg);
format!("{} bar", arg);
diff --git a/src/tools/clippy/tests/ui/format.stderr b/src/tools/clippy/tests/ui/format.stderr
index 6c35caeb0..0ef0ac655 100644
--- a/src/tools/clippy/tests/ui/format.stderr
+++ b/src/tools/clippy/tests/ui/format.stderr
@@ -46,82 +46,58 @@ LL | format!("{}", "foo");
| ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:33:5
- |
-LL | format!("{:+}", "foo"); // Warn when the format makes no difference.
- | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
-
-error: useless use of `format!`
- --> $DIR/format.rs:34:5
- |
-LL | format!("{:<}", "foo"); // Warn when the format makes no difference.
- | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"foo".to_string()`
-
-error: useless use of `format!`
- --> $DIR/format.rs:39:5
+ --> $DIR/format.rs:37:5
|
LL | format!("{}", arg);
| ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:43:5
- |
-LL | format!("{:+}", arg); // Warn when the format makes no difference.
- | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
-
-error: useless use of `format!`
- --> $DIR/format.rs:44:5
- |
-LL | format!("{:<}", arg); // Warn when the format makes no difference.
- | ^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `arg.to_string()`
-
-error: useless use of `format!`
- --> $DIR/format.rs:71:5
+ --> $DIR/format.rs:67:5
|
LL | format!("{}", 42.to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `42.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:73:5
+ --> $DIR/format.rs:69:5
|
LL | format!("{}", x.display().to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.display().to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:77:18
+ --> $DIR/format.rs:73:18
|
LL | let _ = Some(format!("{}", a + "bar"));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `a + "bar"`
error: useless use of `format!`
- --> $DIR/format.rs:81:22
+ --> $DIR/format.rs:77: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:87:13
+ --> $DIR/format.rs:83:13
|
LL | let _ = format!("{x}");
| ^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:89:13
+ --> $DIR/format.rs:85:13
|
LL | let _ = format!("{y}", y = x);
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `x.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:93:13
+ --> $DIR/format.rs:89:13
|
LL | let _ = format!("{abc}");
| ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `abc.to_string()`
error: useless use of `format!`
- --> $DIR/format.rs:95:13
+ --> $DIR/format.rs:91:13
|
LL | let _ = format!("{xx}");
| ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()`
-error: aborting due to 19 previous errors
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/format_args.fixed b/src/tools/clippy/tests/ui/format_args.fixed
index e1c2d4d70..825e122be 100644
--- a/src/tools/clippy/tests/ui/format_args.fixed
+++ b/src/tools/clippy/tests/ui/format_args.fixed
@@ -1,10 +1,13 @@
// run-rustfix
-
-#![allow(unused)]
-#![allow(clippy::assertions_on_constants)]
-#![allow(clippy::eq_op)]
-#![allow(clippy::print_literal)]
#![warn(clippy::to_string_in_format_args)]
+#![allow(unused)]
+#![allow(
+ clippy::assertions_on_constants,
+ clippy::double_parens,
+ clippy::eq_op,
+ clippy::print_literal,
+ clippy::uninlined_format_args
+)]
use std::io::{stdout, Write};
use std::ops::Deref;
@@ -112,6 +115,8 @@ fn main() {
println!("error: something failed at {}", my_other_macro!());
// https://github.com/rust-lang/rust-clippy/issues/7903
println!("{foo}{foo:?}", foo = "foo".to_string());
+ print!("{}", (Location::caller()));
+ print!("{}", ((Location::caller())));
}
fn issue8643(vendor_id: usize, product_id: usize, name: &str) {
diff --git a/src/tools/clippy/tests/ui/format_args.rs b/src/tools/clippy/tests/ui/format_args.rs
index b9a4d66c2..a41e53389 100644
--- a/src/tools/clippy/tests/ui/format_args.rs
+++ b/src/tools/clippy/tests/ui/format_args.rs
@@ -1,10 +1,13 @@
// run-rustfix
-
-#![allow(unused)]
-#![allow(clippy::assertions_on_constants)]
-#![allow(clippy::eq_op)]
-#![allow(clippy::print_literal)]
#![warn(clippy::to_string_in_format_args)]
+#![allow(unused)]
+#![allow(
+ clippy::assertions_on_constants,
+ clippy::double_parens,
+ clippy::eq_op,
+ clippy::print_literal,
+ clippy::uninlined_format_args
+)]
use std::io::{stdout, Write};
use std::ops::Deref;
@@ -112,6 +115,8 @@ fn main() {
println!("error: something failed at {}", my_other_macro!());
// https://github.com/rust-lang/rust-clippy/issues/7903
println!("{foo}{foo:?}", foo = "foo".to_string());
+ print!("{}", (Location::caller().to_string()));
+ print!("{}", ((Location::caller()).to_string()));
}
fn issue8643(vendor_id: usize, product_id: usize, name: &str) {
diff --git a/src/tools/clippy/tests/ui/format_args.stderr b/src/tools/clippy/tests/ui/format_args.stderr
index aa6e3659b..f1832b970 100644
--- a/src/tools/clippy/tests/ui/format_args.stderr
+++ b/src/tools/clippy/tests/ui/format_args.stderr
@@ -1,5 +1,5 @@
error: `to_string` applied to a type that implements `Display` in `format!` args
- --> $DIR/format_args.rs:74:72
+ --> $DIR/format_args.rs:77:72
|
LL | let _ = format!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
@@ -7,136 +7,148 @@ LL | let _ = format!("error: something failed at {}", Location::caller().to_
= note: `-D clippy::to-string-in-format-args` implied by `-D warnings`
error: `to_string` applied to a type that implements `Display` in `write!` args
- --> $DIR/format_args.rs:78:27
+ --> $DIR/format_args.rs:81:27
|
LL | Location::caller().to_string()
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `writeln!` args
- --> $DIR/format_args.rs:83:27
+ --> $DIR/format_args.rs:86:27
|
LL | Location::caller().to_string()
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `print!` args
- --> $DIR/format_args.rs:85:63
+ --> $DIR/format_args.rs:88:63
|
LL | print!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:86:65
+ --> $DIR/format_args.rs:89:65
|
LL | println!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `eprint!` args
- --> $DIR/format_args.rs:87:64
+ --> $DIR/format_args.rs:90:64
|
LL | eprint!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `eprintln!` args
- --> $DIR/format_args.rs:88:66
+ --> $DIR/format_args.rs:91:66
|
LL | eprintln!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `format_args!` args
- --> $DIR/format_args.rs:89:77
+ --> $DIR/format_args.rs:92:77
|
LL | let _ = format_args!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert!` args
- --> $DIR/format_args.rs:90:70
+ --> $DIR/format_args.rs:93:70
|
LL | assert!(true, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert_eq!` args
- --> $DIR/format_args.rs:91:73
+ --> $DIR/format_args.rs:94:73
|
LL | assert_eq!(0, 0, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `assert_ne!` args
- --> $DIR/format_args.rs:92:73
+ --> $DIR/format_args.rs:95:73
|
LL | assert_ne!(0, 0, "error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `panic!` args
- --> $DIR/format_args.rs:93:63
+ --> $DIR/format_args.rs:96:63
|
LL | panic!("error: something failed at {}", Location::caller().to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:94:20
+ --> $DIR/format_args.rs:97:20
|
LL | println!("{}", X(1).to_string());
| ^^^^^^^^^^^^^^^^ help: use this: `*X(1)`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:95:20
+ --> $DIR/format_args.rs:98:20
|
LL | println!("{}", Y(&X(1)).to_string());
| ^^^^^^^^^^^^^^^^^^^^ help: use this: `***Y(&X(1))`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:96:24
+ --> $DIR/format_args.rs:99:24
|
LL | println!("{}", Z(1).to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:97:20
+ --> $DIR/format_args.rs:100:20
|
LL | println!("{}", x.to_string());
| ^^^^^^^^^^^^^ help: use this: `**x`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:98:20
+ --> $DIR/format_args.rs:101:20
|
LL | println!("{}", x_ref.to_string());
| ^^^^^^^^^^^^^^^^^ help: use this: `***x_ref`
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:100:39
+ --> $DIR/format_args.rs:103:39
|
LL | println!("{foo}{bar}", foo = "foo".to_string(), bar = "bar");
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:101:52
+ --> $DIR/format_args.rs:104:52
|
LL | println!("{foo}{bar}", foo = "foo", bar = "bar".to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:102:39
+ --> $DIR/format_args.rs:105:39
|
LL | println!("{foo}{bar}", bar = "bar".to_string(), foo = "foo");
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:103:52
+ --> $DIR/format_args.rs:106:52
|
LL | println!("{foo}{bar}", bar = "bar", foo = "foo".to_string());
| ^^^^^^^^^^^^ help: remove this
+error: `to_string` applied to a type that implements `Display` in `print!` args
+ --> $DIR/format_args.rs:118:37
+ |
+LL | print!("{}", (Location::caller().to_string()));
+ | ^^^^^^^^^^^^ help: remove this
+
+error: `to_string` applied to a type that implements `Display` in `print!` args
+ --> $DIR/format_args.rs:119:39
+ |
+LL | print!("{}", ((Location::caller()).to_string()));
+ | ^^^^^^^^^^^^ help: remove this
+
error: `to_string` applied to a type that implements `Display` in `format!` args
- --> $DIR/format_args.rs:142:38
+ --> $DIR/format_args.rs:147:38
|
LL | let x = format!("{} {}", a, b.to_string());
| ^^^^^^^^^^^^ help: remove this
error: `to_string` applied to a type that implements `Display` in `println!` args
- --> $DIR/format_args.rs:156:24
+ --> $DIR/format_args.rs:161:24
|
LL | println!("{}", original[..10].to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use this: `&original[..10]`
-error: aborting due to 23 previous errors
+error: aborting due to 25 previous errors
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.rs b/src/tools/clippy/tests/ui/format_args_unfixable.rs
index b24ddf732..eb0ac15bf 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.rs
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.rs
@@ -1,7 +1,5 @@
-#![allow(clippy::assertions_on_constants)]
-#![allow(clippy::eq_op)]
-#![warn(clippy::format_in_format_args)]
-#![warn(clippy::to_string_in_format_args)]
+#![warn(clippy::format_in_format_args, clippy::to_string_in_format_args)]
+#![allow(clippy::assertions_on_constants, clippy::eq_op, clippy::uninlined_format_args)]
use std::io::{stdout, Error, ErrorKind, Write};
use std::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/format_args_unfixable.stderr b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
index 4476218ad..b291d475a 100644
--- a/src/tools/clippy/tests/ui/format_args_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/format_args_unfixable.stderr
@@ -1,15 +1,15 @@
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:27:5
+ --> $DIR/format_args_unfixable.rs:25:5
|
LL | println!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::format-in-format-args` implied by `-D warnings`
= help: combine the `format!(..)` arguments with the outer `println!(..)` call
= help: or consider changing `format!` to `format_args!`
+ = note: `-D clippy::format-in-format-args` implied by `-D warnings`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:28:5
+ --> $DIR/format_args_unfixable.rs:26:5
|
LL | println!("{}: {}", error, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -18,7 +18,7 @@ LL | println!("{}: {}", error, format!("something failed at {}", Location::c
= help: or consider changing `format!` to `format_args!`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:29:5
+ --> $DIR/format_args_unfixable.rs:27:5
|
LL | println!("{:?}: {}", error, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -27,7 +27,7 @@ LL | println!("{:?}: {}", error, format!("something failed at {}", Location:
= help: or consider changing `format!` to `format_args!`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:30:5
+ --> $DIR/format_args_unfixable.rs:28:5
|
LL | println!("{{}}: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -36,7 +36,7 @@ LL | println!("{{}}: {}", format!("something failed at {}", Location::caller
= help: or consider changing `format!` to `format_args!`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:31:5
+ --> $DIR/format_args_unfixable.rs:29:5
|
LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL | println!(r#"error: "{}""#, format!("something failed at {}", Location::
= help: or consider changing `format!` to `format_args!`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:32:5
+ --> $DIR/format_args_unfixable.rs:30:5
|
LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -54,7 +54,7 @@ LL | println!("error: {}", format!(r#"something failed at "{}""#, Location::
= help: or consider changing `format!` to `format_args!`
error: `format!` in `println!` args
- --> $DIR/format_args_unfixable.rs:33:5
+ --> $DIR/format_args_unfixable.rs:31:5
|
LL | println!("error: {}", format!("something failed at {} {0}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL | println!("error: {}", format!("something failed at {} {0}", Location::c
= help: or consider changing `format!` to `format_args!`
error: `format!` in `format!` args
- --> $DIR/format_args_unfixable.rs:34:13
+ --> $DIR/format_args_unfixable.rs:32:13
|
LL | let _ = format!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -72,7 +72,7 @@ LL | let _ = format!("error: {}", format!("something failed at {}", Location
= help: or consider changing `format!` to `format_args!`
error: `format!` in `write!` args
- --> $DIR/format_args_unfixable.rs:35:13
+ --> $DIR/format_args_unfixable.rs:33:13
|
LL | let _ = write!(
| _____________^
@@ -86,7 +86,7 @@ LL | | );
= help: or consider changing `format!` to `format_args!`
error: `format!` in `writeln!` args
- --> $DIR/format_args_unfixable.rs:40:13
+ --> $DIR/format_args_unfixable.rs:38:13
|
LL | let _ = writeln!(
| _____________^
@@ -100,7 +100,7 @@ LL | | );
= help: or consider changing `format!` to `format_args!`
error: `format!` in `print!` args
- --> $DIR/format_args_unfixable.rs:45:5
+ --> $DIR/format_args_unfixable.rs:43:5
|
LL | print!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -109,7 +109,7 @@ LL | print!("error: {}", format!("something failed at {}", Location::caller(
= help: or consider changing `format!` to `format_args!`
error: `format!` in `eprint!` args
- --> $DIR/format_args_unfixable.rs:46:5
+ --> $DIR/format_args_unfixable.rs:44:5
|
LL | eprint!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -118,7 +118,7 @@ LL | eprint!("error: {}", format!("something failed at {}", Location::caller
= help: or consider changing `format!` to `format_args!`
error: `format!` in `eprintln!` args
- --> $DIR/format_args_unfixable.rs:47:5
+ --> $DIR/format_args_unfixable.rs:45:5
|
LL | eprintln!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -127,7 +127,7 @@ LL | eprintln!("error: {}", format!("something failed at {}", Location::call
= help: or consider changing `format!` to `format_args!`
error: `format!` in `format_args!` args
- --> $DIR/format_args_unfixable.rs:48:13
+ --> $DIR/format_args_unfixable.rs:46:13
|
LL | let _ = format_args!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,7 +136,7 @@ LL | let _ = format_args!("error: {}", format!("something failed at {}", Loc
= help: or consider changing `format!` to `format_args!`
error: `format!` in `assert!` args
- --> $DIR/format_args_unfixable.rs:49:5
+ --> $DIR/format_args_unfixable.rs:47:5
|
LL | assert!(true, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -145,7 +145,7 @@ LL | assert!(true, "error: {}", format!("something failed at {}", Location::
= help: or consider changing `format!` to `format_args!`
error: `format!` in `assert_eq!` args
- --> $DIR/format_args_unfixable.rs:50:5
+ --> $DIR/format_args_unfixable.rs:48:5
|
LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -154,7 +154,7 @@ LL | assert_eq!(0, 0, "error: {}", format!("something failed at {}", Locatio
= help: or consider changing `format!` to `format_args!`
error: `format!` in `assert_ne!` args
- --> $DIR/format_args_unfixable.rs:51:5
+ --> $DIR/format_args_unfixable.rs:49:5
|
LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -163,7 +163,7 @@ LL | assert_ne!(0, 0, "error: {}", format!("something failed at {}", Locatio
= help: or consider changing `format!` to `format_args!`
error: `format!` in `panic!` args
- --> $DIR/format_args_unfixable.rs:52:5
+ --> $DIR/format_args_unfixable.rs:50:5
|
LL | panic!("error: {}", format!("something failed at {}", Location::caller()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/format_push_string.stderr b/src/tools/clippy/tests/ui/format_push_string.stderr
index 953784bcc..d7be9a5f2 100644
--- a/src/tools/clippy/tests/ui/format_push_string.stderr
+++ b/src/tools/clippy/tests/ui/format_push_string.stderr
@@ -4,8 +4,8 @@ error: `format!(..)` appended to existing `String`
LL | string += &format!("{:?}", 1234);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::format-push-string` implied by `-D warnings`
= help: consider using `write!` to avoid the extra allocation
+ = note: `-D clippy::format-push-string` implied by `-D warnings`
error: `format!(..)` appended to existing `String`
--> $DIR/format_push_string.rs:6:5
diff --git a/src/tools/clippy/tests/ui/formatting.stderr b/src/tools/clippy/tests/ui/formatting.stderr
index 9272cd604..caccd5cba 100644
--- a/src/tools/clippy/tests/ui/formatting.stderr
+++ b/src/tools/clippy/tests/ui/formatting.stderr
@@ -4,8 +4,8 @@ error: this looks like you are trying to use `.. -= ..`, but you really are doin
LL | a =- 35;
| ^^^^
|
- = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings`
= note: to remove this lint, use either `-=` or `= -`
+ = note: `-D clippy::suspicious-assignment-formatting` implied by `-D warnings`
error: this looks like you are trying to use `.. *= ..`, but you really are doing `.. = (* ..)`
--> $DIR/formatting.rs:17:6
@@ -29,8 +29,8 @@ error: possibly missing a comma here
LL | -1, -2, -3 // <= no comma here
| ^
|
- = note: `-D clippy::possible-missing-comma` implied by `-D warnings`
= note: to remove this lint, add a comma or write the expr in a single line
+ = note: `-D clippy::possible-missing-comma` implied by `-D warnings`
error: possibly missing a comma here
--> $DIR/formatting.rs:33:19
diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed
new file mode 100644
index 000000000..1cf49ca45
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into.fixed
@@ -0,0 +1,87 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
+#![warn(clippy::from_over_into)]
+#![allow(unused)]
+
+// this should throw an error
+struct StringWrapper(String);
+
+impl From<String> for StringWrapper {
+ fn from(val: String) -> Self {
+ StringWrapper(val)
+ }
+}
+
+struct SelfType(String);
+
+impl From<String> for SelfType {
+ fn from(val: String) -> Self {
+ SelfType(String::new())
+ }
+}
+
+#[derive(Default)]
+struct X;
+
+impl X {
+ const FOO: &'static str = "a";
+}
+
+struct SelfKeywords;
+
+impl From<X> for SelfKeywords {
+ fn from(val: X) -> Self {
+ let _ = X::default();
+ let _ = X::FOO;
+ let _: X = val;
+
+ SelfKeywords
+ }
+}
+
+struct ExplicitPaths(bool);
+
+impl core::convert::From<crate::ExplicitPaths> for bool {
+ fn from(mut val: crate::ExplicitPaths) -> Self {
+ let in_closure = || val.0;
+
+ val.0 = false;
+ val.0
+ }
+}
+
+// this is fine
+struct A(String);
+
+impl From<String> for A {
+ fn from(s: String) -> A {
+ A(s)
+ }
+}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ struct FromOverInto<T>(Vec<T>);
+
+ impl<T> Into<FromOverInto<T>> for Vec<T> {
+ fn into(self) -> FromOverInto<T> {
+ FromOverInto(self)
+ }
+ }
+}
+
+fn msrv_1_41() {
+ #![clippy::msrv = "1.41"]
+
+ struct FromOverInto<T>(Vec<T>);
+
+ impl<T> From<Vec<T>> for FromOverInto<T> {
+ fn from(val: Vec<T>) -> Self {
+ FromOverInto(val)
+ }
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs
index 292d0924f..d30f3c3fc 100644
--- a/src/tools/clippy/tests/ui/from_over_into.rs
+++ b/src/tools/clippy/tests/ui/from_over_into.rs
@@ -1,4 +1,8 @@
+// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::from_over_into)]
+#![allow(unused)]
// this should throw an error
struct StringWrapper(String);
@@ -9,6 +13,44 @@ impl Into<StringWrapper> for String {
}
}
+struct SelfType(String);
+
+impl Into<SelfType> for String {
+ fn into(self) -> SelfType {
+ SelfType(Self::new())
+ }
+}
+
+#[derive(Default)]
+struct X;
+
+impl X {
+ const FOO: &'static str = "a";
+}
+
+struct SelfKeywords;
+
+impl Into<SelfKeywords> for X {
+ fn into(self) -> SelfKeywords {
+ let _ = Self::default();
+ let _ = Self::FOO;
+ let _: Self = self;
+
+ SelfKeywords
+ }
+}
+
+struct ExplicitPaths(bool);
+
+impl core::convert::Into<bool> for crate::ExplicitPaths {
+ fn into(mut self) -> bool {
+ let in_closure = || self.0;
+
+ self.0 = false;
+ self.0
+ }
+}
+
// this is fine
struct A(String);
@@ -18,4 +60,28 @@ impl From<String> for A {
}
}
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ struct FromOverInto<T>(Vec<T>);
+
+ impl<T> Into<FromOverInto<T>> for Vec<T> {
+ fn into(self) -> FromOverInto<T> {
+ FromOverInto(self)
+ }
+ }
+}
+
+fn msrv_1_41() {
+ #![clippy::msrv = "1.41"]
+
+ struct FromOverInto<T>(Vec<T>);
+
+ impl<T> Into<FromOverInto<T>> for Vec<T> {
+ fn into(self) -> FromOverInto<T> {
+ FromOverInto(self)
+ }
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into.stderr b/src/tools/clippy/tests/ui/from_over_into.stderr
index 2951e6bda..9c2a7c04c 100644
--- a/src/tools/clippy/tests/ui/from_over_into.stderr
+++ b/src/tools/clippy/tests/ui/from_over_into.stderr
@@ -1,11 +1,75 @@
error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
- --> $DIR/from_over_into.rs:6:1
+ --> $DIR/from_over_into.rs:10:1
|
LL | impl Into<StringWrapper> for String {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::from-over-into` implied by `-D warnings`
- = help: consider to implement `From<std::string::String>` instead
+help: replace the `Into` implentation with `From<std::string::String>`
+ |
+LL ~ impl From<String> for StringWrapper {
+LL ~ fn from(val: String) -> Self {
+LL ~ StringWrapper(val)
+ |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into.rs:18:1
+ |
+LL | impl Into<SelfType> for String {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace the `Into` implentation with `From<std::string::String>`
+ |
+LL ~ impl From<String> for SelfType {
+LL ~ fn from(val: String) -> Self {
+LL ~ SelfType(String::new())
+ |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into.rs:33:1
+ |
+LL | impl Into<SelfKeywords> for X {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace the `Into` implentation with `From<X>`
+ |
+LL ~ impl From<X> for SelfKeywords {
+LL ~ fn from(val: X) -> Self {
+LL ~ let _ = X::default();
+LL ~ let _ = X::FOO;
+LL ~ let _: X = val;
+ |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into.rs:45:1
+ |
+LL | impl core::convert::Into<bool> for crate::ExplicitPaths {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+ https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+help: replace the `Into` implentation with `From<ExplicitPaths>`
+ |
+LL ~ impl core::convert::From<crate::ExplicitPaths> for bool {
+LL ~ fn from(mut val: crate::ExplicitPaths) -> Self {
+LL ~ let in_closure = || val.0;
+LL |
+LL ~ val.0 = false;
+LL ~ val.0
+ |
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into.rs:80:5
+ |
+LL | impl<T> Into<FromOverInto<T>> for Vec<T> {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: replace the `Into` implentation with `From<std::vec::Vec<T>>`
+ |
+LL ~ impl<T> From<Vec<T>> for FromOverInto<T> {
+LL ~ fn from(val: Vec<T>) -> Self {
+LL ~ FromOverInto(val)
+ |
-error: aborting due to previous error
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
new file mode 100644
index 000000000..3b280b748
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs
@@ -0,0 +1,35 @@
+#![warn(clippy::from_over_into)]
+
+struct InMacro(String);
+
+macro_rules! in_macro {
+ ($e:ident) => {
+ $e
+ };
+}
+
+impl Into<InMacro> for String {
+ fn into(self) -> InMacro {
+ InMacro(in_macro!(self))
+ }
+}
+
+struct WeirdUpperSelf;
+
+impl Into<WeirdUpperSelf> for &'static [u8] {
+ fn into(self) -> WeirdUpperSelf {
+ let _ = Self::default();
+ WeirdUpperSelf
+ }
+}
+
+struct ContainsVal;
+
+impl Into<u8> for ContainsVal {
+ fn into(self) -> u8 {
+ let val = 1;
+ val + 1
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
new file mode 100644
index 000000000..6f6ce3519
--- /dev/null
+++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr
@@ -0,0 +1,29 @@
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into_unfixable.rs:11:1
+ |
+LL | impl Into<InMacro> for String {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: replace the `Into` implentation with `From<std::string::String>`
+ = note: `-D clippy::from-over-into` implied by `-D warnings`
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into_unfixable.rs:19:1
+ |
+LL | impl Into<WeirdUpperSelf> for &'static [u8] {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: replace the `Into` implentation with `From<&'static [u8]>`
+
+error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true
+ --> $DIR/from_over_into_unfixable.rs:28:1
+ |
+LL | impl Into<u8> for ContainsVal {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: `impl From<Local> for Foreign` is allowed by the orphan rules, for more information see
+ https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence
+ = help: replace the `Into` implentation with `From<ContainsVal>`
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/functions.rs b/src/tools/clippy/tests/ui/functions.rs
index 5521870ea..18149bfbc 100644
--- a/src/tools/clippy/tests/ui/functions.rs
+++ b/src/tools/clippy/tests/ui/functions.rs
@@ -1,6 +1,6 @@
#![warn(clippy::all)]
-#![allow(dead_code)]
-#![allow(unused_unsafe, clippy::missing_safety_doc)]
+#![allow(dead_code, unused_unsafe)]
+#![allow(clippy::missing_safety_doc, clippy::uninlined_format_args)]
// TOO_MANY_ARGUMENTS
fn good(_one: u32, _two: u32, _three: &str, _four: bool, _five: f32, _six: f32, _seven: bool) {}
diff --git a/src/tools/clippy/tests/ui/future_not_send.stderr b/src/tools/clippy/tests/ui/future_not_send.stderr
index a9f2ad36d..5b6858e45 100644
--- a/src/tools/clippy/tests/ui/future_not_send.stderr
+++ b/src/tools/clippy/tests/ui/future_not_send.stderr
@@ -4,7 +4,6 @@ error: future cannot be sent between threads safely
LL | async fn private_future(rc: Rc<[u8]>, cell: &Cell<usize>) -> bool {
| ^^^^ future returned by `private_future` is not `Send`
|
- = note: `-D clippy::future-not-send` implied by `-D warnings`
note: future is not `Send` as this value is used across an await
--> $DIR/future_not_send.rs:8:19
|
@@ -25,6 +24,7 @@ LL | async { true }.await
LL | }
| - `cell` is later dropped here
= note: `std::cell::Cell<usize>` doesn't implement `std::marker::Sync`
+ = note: `-D clippy::future-not-send` implied by `-D warnings`
error: future cannot be sent between threads safely
--> $DIR/future_not_send.rs:11:42
diff --git a/src/tools/clippy/tests/ui/get_unwrap.stderr b/src/tools/clippy/tests/ui/get_unwrap.stderr
index ea8fec527..937f85904 100644
--- a/src/tools/clippy/tests/ui/get_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/get_unwrap.stderr
@@ -16,8 +16,8 @@ error: used `unwrap()` on `an Option` value
LL | let _ = boxed_slice.get(1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+ = note: `-D clippy::unwrap-used` implied by `-D warnings`
error: called `.get().unwrap()` on a slice. Using `[]` is more clear and more concise
--> $DIR/get_unwrap.rs:36:17
diff --git a/src/tools/clippy/tests/ui/identity_op.fixed b/src/tools/clippy/tests/ui/identity_op.fixed
index fa564e23c..e7b9a78c5 100644
--- a/src/tools/clippy/tests/ui/identity_op.fixed
+++ b/src/tools/clippy/tests/ui/identity_op.fixed
@@ -1,13 +1,13 @@
// run-rustfix
-
#![warn(clippy::identity_op)]
+#![allow(unused)]
#![allow(
clippy::eq_op,
clippy::no_effect,
clippy::unnecessary_operation,
clippy::op_ref,
clippy::double_parens,
- unused
+ clippy::uninlined_format_args
)]
use std::fmt::Write as _;
diff --git a/src/tools/clippy/tests/ui/identity_op.rs b/src/tools/clippy/tests/ui/identity_op.rs
index 3d06d2a73..9a435cdbb 100644
--- a/src/tools/clippy/tests/ui/identity_op.rs
+++ b/src/tools/clippy/tests/ui/identity_op.rs
@@ -1,13 +1,13 @@
// run-rustfix
-
#![warn(clippy::identity_op)]
+#![allow(unused)]
#![allow(
clippy::eq_op,
clippy::no_effect,
clippy::unnecessary_operation,
clippy::op_ref,
clippy::double_parens,
- unused
+ clippy::uninlined_format_args
)]
use std::fmt::Write as _;
diff --git a/src/tools/clippy/tests/ui/if_let_mutex.stderr b/src/tools/clippy/tests/ui/if_let_mutex.stderr
index 8a4d5dbac..da0cc25f0 100644
--- a/src/tools/clippy/tests/ui/if_let_mutex.stderr
+++ b/src/tools/clippy/tests/ui/if_let_mutex.stderr
@@ -13,8 +13,8 @@ LL | | do_stuff(lock);
LL | | };
| |_____^
|
- = note: `-D clippy::if-let-mutex` implied by `-D warnings`
= help: move the lock call outside of the `if let ...` expression
+ = note: `-D clippy::if-let-mutex` implied by `-D warnings`
error: calling `Mutex::lock` inside the scope of another `Mutex::lock` causes a deadlock
--> $DIR/if_let_mutex.rs:22:5
diff --git a/src/tools/clippy/tests/ui/if_not_else.stderr b/src/tools/clippy/tests/ui/if_not_else.stderr
index 8c8cc44bb..46671c152 100644
--- a/src/tools/clippy/tests/ui/if_not_else.stderr
+++ b/src/tools/clippy/tests/ui/if_not_else.stderr
@@ -8,8 +8,8 @@ LL | | println!("Bunny");
LL | | }
| |_____^
|
- = note: `-D clippy::if-not-else` implied by `-D warnings`
= help: remove the `!` and swap the blocks of the `if`/`else`
+ = note: `-D clippy::if-not-else` implied by `-D warnings`
error: unnecessary `!=` operation
--> $DIR/if_not_else.rs:17:5
diff --git a/src/tools/clippy/tests/ui/if_same_then_else.stderr b/src/tools/clippy/tests/ui/if_same_then_else.stderr
index 2cdf44248..fb23b81d3 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else.stderr
@@ -11,7 +11,6 @@ LL | | foo();
LL | | } else {
| |_____^
|
- = note: `-D clippy::if-same-then-else` implied by `-D warnings`
note: same as this
--> $DIR/if_same_then_else.rs:31:12
|
@@ -24,6 +23,7 @@ LL | | 0..10;
LL | | foo();
LL | | }
| |_____^
+ = note: `-D clippy::if-same-then-else` implied by `-D warnings`
error: this `if` has identical blocks
--> $DIR/if_same_then_else.rs:67:21
diff --git a/src/tools/clippy/tests/ui/if_same_then_else2.stderr b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
index cac788f85..704cfd966 100644
--- a/src/tools/clippy/tests/ui/if_same_then_else2.stderr
+++ b/src/tools/clippy/tests/ui/if_same_then_else2.stderr
@@ -11,7 +11,6 @@ LL | | }
LL | | } else {
| |_____^
|
- = note: `-D clippy::if-same-then-else` implied by `-D warnings`
note: same as this
--> $DIR/if_same_then_else2.rs:23:12
|
@@ -24,6 +23,7 @@ LL | | let bar: &Option<_> = &Some::<u8>(42);
LL | | }
LL | | }
| |_____^
+ = note: `-D clippy::if-same-then-else` implied by `-D warnings`
error: this `if` has identical blocks
--> $DIR/if_same_then_else2.rs:35:13
diff --git a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
index c22ace30d..24e0b5947 100644
--- a/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
+++ b/src/tools/clippy/tests/ui/if_then_some_else_none.stderr
@@ -10,8 +10,8 @@ LL | | None
LL | | };
| |_____^
|
- = note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
= help: consider using `bool::then` like: `foo().then(|| { /* snippet */ "foo" })`
+ = note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
error: this could be simplified with `bool::then`
--> $DIR/if_then_some_else_none.rs:14:13
diff --git a/src/tools/clippy/tests/ui/ifs_same_cond.stderr b/src/tools/clippy/tests/ui/ifs_same_cond.stderr
index 0c8f49b86..411308732 100644
--- a/src/tools/clippy/tests/ui/ifs_same_cond.stderr
+++ b/src/tools/clippy/tests/ui/ifs_same_cond.stderr
@@ -4,12 +4,12 @@ error: this `if` has the same condition as a previous `if`
LL | } else if b {
| ^
|
- = note: `-D clippy::ifs-same-cond` implied by `-D warnings`
note: same as this
--> $DIR/ifs_same_cond.rs:8:8
|
LL | if b {
| ^
+ = note: `-D clippy::ifs-same-cond` implied by `-D warnings`
error: this `if` has the same condition as a previous `if`
--> $DIR/ifs_same_cond.rs:14:15
diff --git a/src/tools/clippy/tests/ui/impl.stderr b/src/tools/clippy/tests/ui/impl.stderr
index 8703ecac9..e28b1bf0c 100644
--- a/src/tools/clippy/tests/ui/impl.stderr
+++ b/src/tools/clippy/tests/ui/impl.stderr
@@ -6,7 +6,6 @@ LL | | fn second() {}
LL | | }
| |_^
|
- = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings`
note: first implementation here
--> $DIR/impl.rs:6:1
|
@@ -14,6 +13,7 @@ LL | / impl MyStruct {
LL | | fn first() {}
LL | | }
| |_^
+ = note: `-D clippy::multiple-inherent-impl` implied by `-D warnings`
error: multiple implementations of this structure
--> $DIR/impl.rs:24:5
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_add.fixed b/src/tools/clippy/tests/ui/implicit_saturating_add.fixed
new file mode 100644
index 000000000..7d363d59a
--- /dev/null
+++ b/src/tools/clippy/tests/ui/implicit_saturating_add.fixed
@@ -0,0 +1,106 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::implicit_saturating_add)]
+
+fn main() {
+ let mut u_8: u8 = 255;
+ let mut u_16: u16 = 500;
+ let mut u_32: u32 = 7000;
+ let mut u_64: u64 = 7000;
+ let mut i_8: i8 = 30;
+ let mut i_16: i16 = 500;
+ let mut i_32: i32 = 7000;
+ let mut i_64: i64 = 7000;
+
+ if i_8 < 42 {
+ i_8 += 1;
+ }
+ if i_8 != 42 {
+ i_8 += 1;
+ }
+
+ u_8 = u_8.saturating_add(1);
+
+ u_8 = u_8.saturating_add(1);
+
+ if u_8 < 15 {
+ u_8 += 1;
+ }
+
+ u_16 = u_16.saturating_add(1);
+
+ u_16 = u_16.saturating_add(1);
+
+ u_16 = u_16.saturating_add(1);
+
+ u_32 = u_32.saturating_add(1);
+
+ u_32 = u_32.saturating_add(1);
+
+ u_32 = u_32.saturating_add(1);
+
+ u_64 = u_64.saturating_add(1);
+
+ u_64 = u_64.saturating_add(1);
+
+ u_64 = u_64.saturating_add(1);
+
+ i_8 = i_8.saturating_add(1);
+
+ i_8 = i_8.saturating_add(1);
+
+ i_8 = i_8.saturating_add(1);
+
+ i_16 = i_16.saturating_add(1);
+
+ i_16 = i_16.saturating_add(1);
+
+ i_16 = i_16.saturating_add(1);
+
+ i_32 = i_32.saturating_add(1);
+
+ i_32 = i_32.saturating_add(1);
+
+ i_32 = i_32.saturating_add(1);
+
+ i_64 = i_64.saturating_add(1);
+
+ i_64 = i_64.saturating_add(1);
+
+ i_64 = i_64.saturating_add(1);
+
+ if i_64 < 42 {
+ i_64 += 1;
+ }
+
+ if 42 > i_64 {
+ i_64 += 1;
+ }
+
+ let a = 12;
+ let mut b = 8;
+
+ if a < u8::MAX {
+ b += 1;
+ }
+
+ if u8::MAX > a {
+ b += 1;
+ }
+
+ if u_32 < u32::MAX {
+ u_32 += 1;
+ } else {
+ println!("don't lint this");
+ }
+
+ if u_32 < u32::MAX {
+ println!("don't lint this");
+ u_32 += 1;
+ }
+
+ if u_32 < 42 {
+ println!("brace yourself!");
+ } else {u_32 = u_32.saturating_add(1); }
+}
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_add.rs b/src/tools/clippy/tests/ui/implicit_saturating_add.rs
new file mode 100644
index 000000000..31a591627
--- /dev/null
+++ b/src/tools/clippy/tests/ui/implicit_saturating_add.rs
@@ -0,0 +1,154 @@
+// run-rustfix
+
+#![allow(unused)]
+#![warn(clippy::implicit_saturating_add)]
+
+fn main() {
+ let mut u_8: u8 = 255;
+ let mut u_16: u16 = 500;
+ let mut u_32: u32 = 7000;
+ let mut u_64: u64 = 7000;
+ let mut i_8: i8 = 30;
+ let mut i_16: i16 = 500;
+ let mut i_32: i32 = 7000;
+ let mut i_64: i64 = 7000;
+
+ if i_8 < 42 {
+ i_8 += 1;
+ }
+ if i_8 != 42 {
+ i_8 += 1;
+ }
+
+ if u_8 != u8::MAX {
+ u_8 += 1;
+ }
+
+ if u_8 < u8::MAX {
+ u_8 += 1;
+ }
+
+ if u_8 < 15 {
+ u_8 += 1;
+ }
+
+ if u_16 != u16::MAX {
+ u_16 += 1;
+ }
+
+ if u_16 < u16::MAX {
+ u_16 += 1;
+ }
+
+ if u16::MAX > u_16 {
+ u_16 += 1;
+ }
+
+ if u_32 != u32::MAX {
+ u_32 += 1;
+ }
+
+ if u_32 < u32::MAX {
+ u_32 += 1;
+ }
+
+ if u32::MAX > u_32 {
+ u_32 += 1;
+ }
+
+ if u_64 != u64::MAX {
+ u_64 += 1;
+ }
+
+ if u_64 < u64::MAX {
+ u_64 += 1;
+ }
+
+ if u64::MAX > u_64 {
+ u_64 += 1;
+ }
+
+ if i_8 != i8::MAX {
+ i_8 += 1;
+ }
+
+ if i_8 < i8::MAX {
+ i_8 += 1;
+ }
+
+ if i8::MAX > i_8 {
+ i_8 += 1;
+ }
+
+ if i_16 != i16::MAX {
+ i_16 += 1;
+ }
+
+ if i_16 < i16::MAX {
+ i_16 += 1;
+ }
+
+ if i16::MAX > i_16 {
+ i_16 += 1;
+ }
+
+ if i_32 != i32::MAX {
+ i_32 += 1;
+ }
+
+ if i_32 < i32::MAX {
+ i_32 += 1;
+ }
+
+ if i32::MAX > i_32 {
+ i_32 += 1;
+ }
+
+ if i_64 != i64::MAX {
+ i_64 += 1;
+ }
+
+ if i_64 < i64::MAX {
+ i_64 += 1;
+ }
+
+ if i64::MAX > i_64 {
+ i_64 += 1;
+ }
+
+ if i_64 < 42 {
+ i_64 += 1;
+ }
+
+ if 42 > i_64 {
+ i_64 += 1;
+ }
+
+ let a = 12;
+ let mut b = 8;
+
+ if a < u8::MAX {
+ b += 1;
+ }
+
+ if u8::MAX > a {
+ b += 1;
+ }
+
+ if u_32 < u32::MAX {
+ u_32 += 1;
+ } else {
+ println!("don't lint this");
+ }
+
+ if u_32 < u32::MAX {
+ println!("don't lint this");
+ u_32 += 1;
+ }
+
+ if u_32 < 42 {
+ println!("brace yourself!");
+ } else if u_32 < u32::MAX {
+ u_32 += 1;
+ }
+}
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_add.stderr b/src/tools/clippy/tests/ui/implicit_saturating_add.stderr
new file mode 100644
index 000000000..42ae1b488
--- /dev/null
+++ b/src/tools/clippy/tests/ui/implicit_saturating_add.stderr
@@ -0,0 +1,197 @@
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:23:5
+ |
+LL | / if u_8 != u8::MAX {
+LL | | u_8 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_8 = u_8.saturating_add(1);`
+ |
+ = note: `-D clippy::implicit-saturating-add` implied by `-D warnings`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:27:5
+ |
+LL | / if u_8 < u8::MAX {
+LL | | u_8 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_8 = u_8.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:35:5
+ |
+LL | / if u_16 != u16::MAX {
+LL | | u_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:39:5
+ |
+LL | / if u_16 < u16::MAX {
+LL | | u_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:43:5
+ |
+LL | / if u16::MAX > u_16 {
+LL | | u_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_16 = u_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:47:5
+ |
+LL | / if u_32 != u32::MAX {
+LL | | u_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:51:5
+ |
+LL | / if u_32 < u32::MAX {
+LL | | u_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:55:5
+ |
+LL | / if u32::MAX > u_32 {
+LL | | u_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_32 = u_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:59:5
+ |
+LL | / if u_64 != u64::MAX {
+LL | | u_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:63:5
+ |
+LL | / if u_64 < u64::MAX {
+LL | | u_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:67:5
+ |
+LL | / if u64::MAX > u_64 {
+LL | | u_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `u_64 = u_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:71:5
+ |
+LL | / if i_8 != i8::MAX {
+LL | | i_8 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:75:5
+ |
+LL | / if i_8 < i8::MAX {
+LL | | i_8 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:79:5
+ |
+LL | / if i8::MAX > i_8 {
+LL | | i_8 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_8 = i_8.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:83:5
+ |
+LL | / if i_16 != i16::MAX {
+LL | | i_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:87:5
+ |
+LL | / if i_16 < i16::MAX {
+LL | | i_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:91:5
+ |
+LL | / if i16::MAX > i_16 {
+LL | | i_16 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_16 = i_16.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:95:5
+ |
+LL | / if i_32 != i32::MAX {
+LL | | i_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:99:5
+ |
+LL | / if i_32 < i32::MAX {
+LL | | i_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:103:5
+ |
+LL | / if i32::MAX > i_32 {
+LL | | i_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_32 = i_32.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:107:5
+ |
+LL | / if i_64 != i64::MAX {
+LL | | i_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:111:5
+ |
+LL | / if i_64 < i64::MAX {
+LL | | i_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:115:5
+ |
+LL | / if i64::MAX > i_64 {
+LL | | i_64 += 1;
+LL | | }
+ | |_____^ help: use instead: `i_64 = i_64.saturating_add(1);`
+
+error: manual saturating add detected
+ --> $DIR/implicit_saturating_add.rs:151:12
+ |
+LL | } else if u_32 < u32::MAX {
+ | ____________^
+LL | | u_32 += 1;
+LL | | }
+ | |_____^ help: use instead: `{u_32 = u_32.saturating_add(1); }`
+
+error: aborting due to 24 previous errors
+
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
index e6f57e926..93df81b1a 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.fixed
@@ -2,6 +2,21 @@
#![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)]
#![warn(clippy::implicit_saturating_sub)]
+use std::cmp::PartialEq;
+use std::ops::SubAssign;
+// Mock type
+struct Mock;
+
+impl PartialEq<u32> for Mock {
+ fn eq(&self, _: &u32) -> bool {
+ true
+ }
+}
+
+impl SubAssign<u32> for Mock {
+ fn sub_assign(&mut self, _: u32) {}
+}
+
fn main() {
// Tests for unsigned integers
@@ -165,4 +180,39 @@ fn main() {
} else {
println!("side effect");
}
+
+ // Extended tests
+ let mut m = Mock;
+ let mut u_32 = 3000;
+ let a = 200;
+ let mut _b = 8;
+
+ if m != 0 {
+ m -= 1;
+ }
+
+ if a > 0 {
+ _b -= 1;
+ }
+
+ if 0 > a {
+ _b -= 1;
+ }
+
+ if u_32 > 0 {
+ u_32 -= 1;
+ } else {
+ println!("don't lint this");
+ }
+
+ if u_32 > 0 {
+ println!("don't lint this");
+ u_32 -= 1;
+ }
+
+ if u_32 > 42 {
+ println!("brace yourself!");
+ } else if u_32 > 0 {
+ u_32 -= 1;
+ }
}
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
index 8bb28d149..8340bc826 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.rs
@@ -2,6 +2,21 @@
#![allow(unused_assignments, unused_mut, clippy::assign_op_pattern)]
#![warn(clippy::implicit_saturating_sub)]
+use std::cmp::PartialEq;
+use std::ops::SubAssign;
+// Mock type
+struct Mock;
+
+impl PartialEq<u32> for Mock {
+ fn eq(&self, _: &u32) -> bool {
+ true
+ }
+}
+
+impl SubAssign<u32> for Mock {
+ fn sub_assign(&mut self, _: u32) {}
+}
+
fn main() {
// Tests for unsigned integers
@@ -211,4 +226,39 @@ fn main() {
} else {
println!("side effect");
}
+
+ // Extended tests
+ let mut m = Mock;
+ let mut u_32 = 3000;
+ let a = 200;
+ let mut _b = 8;
+
+ if m != 0 {
+ m -= 1;
+ }
+
+ if a > 0 {
+ _b -= 1;
+ }
+
+ if 0 > a {
+ _b -= 1;
+ }
+
+ if u_32 > 0 {
+ u_32 -= 1;
+ } else {
+ println!("don't lint this");
+ }
+
+ if u_32 > 0 {
+ println!("don't lint this");
+ u_32 -= 1;
+ }
+
+ if u_32 > 42 {
+ println!("brace yourself!");
+ } else if u_32 > 0 {
+ u_32 -= 1;
+ }
}
diff --git a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
index 5bb9a6064..5e589d931 100644
--- a/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
+++ b/src/tools/clippy/tests/ui/implicit_saturating_sub.stderr
@@ -1,5 +1,5 @@
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:13:5
+ --> $DIR/implicit_saturating_sub.rs:28:5
|
LL | / if u_8 > 0 {
LL | | u_8 = u_8 - 1;
@@ -9,7 +9,7 @@ LL | | }
= note: `-D clippy::implicit-saturating-sub` implied by `-D warnings`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:20:13
+ --> $DIR/implicit_saturating_sub.rs:35:13
|
LL | / if u_8 > 0 {
LL | | u_8 -= 1;
@@ -17,7 +17,7 @@ LL | | }
| |_____________^ help: try: `u_8 = u_8.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:34:5
+ --> $DIR/implicit_saturating_sub.rs:49:5
|
LL | / if u_16 > 0 {
LL | | u_16 -= 1;
@@ -25,7 +25,7 @@ LL | | }
| |_____^ help: try: `u_16 = u_16.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:44:5
+ --> $DIR/implicit_saturating_sub.rs:59:5
|
LL | / if u_32 != 0 {
LL | | u_32 -= 1;
@@ -33,7 +33,7 @@ LL | | }
| |_____^ help: try: `u_32 = u_32.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:65:5
+ --> $DIR/implicit_saturating_sub.rs:80:5
|
LL | / if u_64 > 0 {
LL | | u_64 -= 1;
@@ -41,7 +41,7 @@ LL | | }
| |_____^ help: try: `u_64 = u_64.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:70:5
+ --> $DIR/implicit_saturating_sub.rs:85:5
|
LL | / if 0 < u_64 {
LL | | u_64 -= 1;
@@ -49,7 +49,7 @@ LL | | }
| |_____^ help: try: `u_64 = u_64.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:75:5
+ --> $DIR/implicit_saturating_sub.rs:90:5
|
LL | / if 0 != u_64 {
LL | | u_64 -= 1;
@@ -57,7 +57,7 @@ LL | | }
| |_____^ help: try: `u_64 = u_64.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:96:5
+ --> $DIR/implicit_saturating_sub.rs:111:5
|
LL | / if u_usize > 0 {
LL | | u_usize -= 1;
@@ -65,7 +65,7 @@ LL | | }
| |_____^ help: try: `u_usize = u_usize.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:108:5
+ --> $DIR/implicit_saturating_sub.rs:123:5
|
LL | / if i_8 > i8::MIN {
LL | | i_8 -= 1;
@@ -73,7 +73,7 @@ LL | | }
| |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:113:5
+ --> $DIR/implicit_saturating_sub.rs:128:5
|
LL | / if i_8 > i8::MIN {
LL | | i_8 -= 1;
@@ -81,7 +81,7 @@ LL | | }
| |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:118:5
+ --> $DIR/implicit_saturating_sub.rs:133:5
|
LL | / if i_8 != i8::MIN {
LL | | i_8 -= 1;
@@ -89,7 +89,7 @@ LL | | }
| |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:123:5
+ --> $DIR/implicit_saturating_sub.rs:138:5
|
LL | / if i_8 != i8::MIN {
LL | | i_8 -= 1;
@@ -97,7 +97,7 @@ LL | | }
| |_____^ help: try: `i_8 = i_8.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:133:5
+ --> $DIR/implicit_saturating_sub.rs:148:5
|
LL | / if i_16 > i16::MIN {
LL | | i_16 -= 1;
@@ -105,7 +105,7 @@ LL | | }
| |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:138:5
+ --> $DIR/implicit_saturating_sub.rs:153:5
|
LL | / if i_16 > i16::MIN {
LL | | i_16 -= 1;
@@ -113,7 +113,7 @@ LL | | }
| |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:143:5
+ --> $DIR/implicit_saturating_sub.rs:158:5
|
LL | / if i_16 != i16::MIN {
LL | | i_16 -= 1;
@@ -121,7 +121,7 @@ LL | | }
| |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:148:5
+ --> $DIR/implicit_saturating_sub.rs:163:5
|
LL | / if i_16 != i16::MIN {
LL | | i_16 -= 1;
@@ -129,7 +129,7 @@ LL | | }
| |_____^ help: try: `i_16 = i_16.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:158:5
+ --> $DIR/implicit_saturating_sub.rs:173:5
|
LL | / if i_32 > i32::MIN {
LL | | i_32 -= 1;
@@ -137,7 +137,7 @@ LL | | }
| |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:163:5
+ --> $DIR/implicit_saturating_sub.rs:178:5
|
LL | / if i_32 > i32::MIN {
LL | | i_32 -= 1;
@@ -145,7 +145,7 @@ LL | | }
| |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:168:5
+ --> $DIR/implicit_saturating_sub.rs:183:5
|
LL | / if i_32 != i32::MIN {
LL | | i_32 -= 1;
@@ -153,7 +153,7 @@ LL | | }
| |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:173:5
+ --> $DIR/implicit_saturating_sub.rs:188:5
|
LL | / if i_32 != i32::MIN {
LL | | i_32 -= 1;
@@ -161,7 +161,7 @@ LL | | }
| |_____^ help: try: `i_32 = i_32.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:183:5
+ --> $DIR/implicit_saturating_sub.rs:198:5
|
LL | / if i64::MIN < i_64 {
LL | | i_64 -= 1;
@@ -169,7 +169,7 @@ LL | | }
| |_____^ help: try: `i_64 = i_64.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:188:5
+ --> $DIR/implicit_saturating_sub.rs:203:5
|
LL | / if i64::MIN != i_64 {
LL | | i_64 -= 1;
@@ -177,7 +177,7 @@ LL | | }
| |_____^ help: try: `i_64 = i_64.saturating_sub(1);`
error: implicitly performing saturating subtraction
- --> $DIR/implicit_saturating_sub.rs:193:5
+ --> $DIR/implicit_saturating_sub.rs:208:5
|
LL | / if i64::MIN < i_64 {
LL | | i_64 -= 1;
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
index c2c0c520d..0a3374d11 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.rs
@@ -1,4 +1,5 @@
#![deny(clippy::index_refutable_slice)]
+#![allow(clippy::uninlined_format_args)]
enum SomeEnum<T> {
One(T),
diff --git a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
index a607df9b8..0a13ac135 100644
--- a/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
+++ b/src/tools/clippy/tests/ui/index_refutable_slice/if_let_slice_binding.stderr
@@ -1,5 +1,5 @@
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:13:17
+ --> $DIR/if_let_slice_binding.rs:14:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@@ -19,7 +19,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:19:17
+ --> $DIR/if_let_slice_binding.rs:20:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@@ -34,7 +34,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:25:17
+ --> $DIR/if_let_slice_binding.rs:26:17
|
LL | if let Some(slice) = slice {
| ^^^^^
@@ -50,7 +50,7 @@ LL ~ println!("{}", slice_0);
|
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:32:26
+ --> $DIR/if_let_slice_binding.rs:33:26
|
LL | if let SomeEnum::One(slice) | SomeEnum::Three(slice) = slice_wrapped {
| ^^^^^
@@ -65,7 +65,7 @@ LL | println!("{}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:39:29
+ --> $DIR/if_let_slice_binding.rs:40:29
|
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
| ^
@@ -80,7 +80,7 @@ LL | println!("{} -> {}", a_2, b[1]);
| ~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:39:38
+ --> $DIR/if_let_slice_binding.rs:40:38
|
LL | if let (SomeEnum::Three(a), Some(b)) = (a_wrapped, b_wrapped) {
| ^
@@ -95,7 +95,7 @@ LL | println!("{} -> {}", a[2], b_1);
| ~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:46:21
+ --> $DIR/if_let_slice_binding.rs:47:21
|
LL | if let Some(ref slice) = slice {
| ^^^^^
@@ -110,7 +110,7 @@ LL | println!("{:?}", slice_1);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:54:17
+ --> $DIR/if_let_slice_binding.rs:55:17
|
LL | if let Some(slice) = &slice {
| ^^^^^
@@ -125,7 +125,7 @@ LL | println!("{:?}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:123:17
+ --> $DIR/if_let_slice_binding.rs:124:17
|
LL | if let Some(slice) = wrap.inner {
| ^^^^^
@@ -140,7 +140,7 @@ LL | println!("This is awesome! {}", slice_0);
| ~~~~~~~
error: this binding can be a slice pattern to avoid indexing
- --> $DIR/if_let_slice_binding.rs:130:17
+ --> $DIR/if_let_slice_binding.rs:131:17
|
LL | if let Some(slice) = wrap.inner {
| ^^^^^
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.rs b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
index 7ebf6ee99..4476e0eb9 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.rs
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.rs
@@ -3,7 +3,7 @@
// We also check the out_of_bounds_indexing lint here, because it lints similar things and
// we want to avoid false positives.
#![warn(clippy::out_of_bounds_indexing)]
-#![allow(const_err, unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
+#![allow(unconditional_panic, clippy::no_effect, clippy::unnecessary_operation)]
const ARR: [i32; 2] = [1, 2];
const REF: &i32 = &ARR[idx()]; // Ok, should not produce stderr.
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
index 6ae700753..da5bc38b3 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_index.stderr
@@ -16,8 +16,8 @@ error: indexing may panic
LL | x[index];
| ^^^^^^^^
|
- = note: `-D clippy::indexing-slicing` implied by `-D warnings`
= help: consider using `.get(n)` or `.get_mut(n)` instead
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
error: indexing may panic
--> $DIR/indexing_slicing_index.rs:38:5
@@ -59,6 +59,12 @@ LL | v[M];
|
= help: consider using `.get(n)` or `.get_mut(n)` instead
-error: aborting due to 8 previous errors
+error[E0080]: evaluation of constant value failed
+ --> $DIR/indexing_slicing_index.rs:10:24
+ |
+LL | const REF_ERR: &i32 = &ARR[idx4()]; // Ok, let rustc handle const contexts.
+ | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4
+
+error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0080`.
diff --git a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
index f70722b92..dc54bd413 100644
--- a/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
+++ b/src/tools/clippy/tests/ui/indexing_slicing_slice.stderr
@@ -4,8 +4,8 @@ error: slicing may panic
LL | &x[index..];
| ^^^^^^^^^^
|
- = note: `-D clippy::indexing-slicing` implied by `-D warnings`
= help: consider using `.get(n..)` or .get_mut(n..)` instead
+ = note: `-D clippy::indexing-slicing` implied by `-D warnings`
error: slicing may panic
--> $DIR/indexing_slicing_slice.rs:13:6
diff --git a/src/tools/clippy/tests/ui/inefficient_to_string.stderr b/src/tools/clippy/tests/ui/inefficient_to_string.stderr
index 4be46161e..914dc92bf 100644
--- a/src/tools/clippy/tests/ui/inefficient_to_string.stderr
+++ b/src/tools/clippy/tests/ui/inefficient_to_string.stderr
@@ -4,12 +4,12 @@ error: calling `to_string` on `&&str`
LL | let _: String = rrstr.to_string();
| ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrstr).to_string()`
|
+ = help: `&str` implements `ToString` through a slower blanket impl, but `str` has a fast specialization of `ToString`
note: the lint level is defined here
--> $DIR/inefficient_to_string.rs:2:9
|
LL | #![deny(clippy::inefficient_to_string)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: `&str` implements `ToString` through a slower blanket impl, but `str` has a fast specialization of `ToString`
error: calling `to_string` on `&&&str`
--> $DIR/inefficient_to_string.rs:12:21
@@ -35,21 +35,21 @@ LL | let _: String = rrrstring.to_string();
|
= help: `&&std::string::String` implements `ToString` through a slower blanket impl, but `std::string::String` has a fast specialization of `ToString`
-error: calling `to_string` on `&&std::borrow::Cow<str>`
+error: calling `to_string` on `&&std::borrow::Cow<'_, str>`
--> $DIR/inefficient_to_string.rs:29:21
|
LL | let _: String = rrcow.to_string();
| ^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(*rrcow).to_string()`
|
- = help: `&std::borrow::Cow<str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<str>` has a fast specialization of `ToString`
+ = help: `&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString`
-error: calling `to_string` on `&&&std::borrow::Cow<str>`
+error: calling `to_string` on `&&&std::borrow::Cow<'_, str>`
--> $DIR/inefficient_to_string.rs:30:21
|
LL | let _: String = rrrcow.to_string();
| ^^^^^^^^^^^^^^^^^^ help: try dereferencing the receiver: `(**rrrcow).to_string()`
|
- = help: `&&std::borrow::Cow<str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<str>` has a fast specialization of `ToString`
+ = help: `&&std::borrow::Cow<'_, str>` implements `ToString` through a slower blanket impl, but `std::borrow::Cow<'_, str>` has a fast specialization of `ToString`
error: aborting due to 6 previous errors
diff --git a/src/tools/clippy/tests/ui/infinite_iter.rs b/src/tools/clippy/tests/ui/infinite_iter.rs
index a1e5fad0c..622644f67 100644
--- a/src/tools/clippy/tests/ui/infinite_iter.rs
+++ b/src/tools/clippy/tests/ui/infinite_iter.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
use std::iter::repeat;
fn square_is_lower_64(x: &u32) -> bool {
x * x < 64
diff --git a/src/tools/clippy/tests/ui/infinite_iter.stderr b/src/tools/clippy/tests/ui/infinite_iter.stderr
index ba277e363..b911163f7 100644
--- a/src/tools/clippy/tests/ui/infinite_iter.stderr
+++ b/src/tools/clippy/tests/ui/infinite_iter.stderr
@@ -1,29 +1,29 @@
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:9:5
+ --> $DIR/infinite_iter.rs:11:5
|
LL | repeat(0_u8).collect::<Vec<_>>(); // infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/infinite_iter.rs:7:8
+ --> $DIR/infinite_iter.rs:9:8
|
LL | #[deny(clippy::infinite_iter)]
| ^^^^^^^^^^^^^^^^^^^^^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:10:5
+ --> $DIR/infinite_iter.rs:12:5
|
LL | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:11:5
+ --> $DIR/infinite_iter.rs:13:5
|
LL | (0..8_u64).chain(0..).max(); // infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:16:5
+ --> $DIR/infinite_iter.rs:18:5
|
LL | / (0..8_u32)
LL | | .rev()
@@ -33,37 +33,37 @@ LL | | .for_each(|x| println!("{}", x)); // infinite iter
| |________________________________________^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:22:5
+ --> $DIR/infinite_iter.rs:24:5
|
LL | (0_usize..).flat_map(|x| 0..x).product::<usize>(); // infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:23:5
+ --> $DIR/infinite_iter.rs:25:5
|
LL | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:30:5
+ --> $DIR/infinite_iter.rs:32:5
|
LL | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
- --> $DIR/infinite_iter.rs:28:8
+ --> $DIR/infinite_iter.rs:30:8
|
LL | #[deny(clippy::maybe_infinite_iter)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:31:5
+ --> $DIR/infinite_iter.rs:33:5
|
LL | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:32:5
+ --> $DIR/infinite_iter.rs:34:5
|
LL | / (1..)
LL | | .scan(0, |state, x| {
@@ -74,31 +74,31 @@ LL | | .min(); // maybe infinite iter
| |______________^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:38:5
+ --> $DIR/infinite_iter.rs:40:5
|
LL | (0..).find(|x| *x == 24); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:39:5
+ --> $DIR/infinite_iter.rs:41:5
|
LL | (0..).position(|x| x == 24); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:40:5
+ --> $DIR/infinite_iter.rs:42:5
|
LL | (0..).any(|x| x == 24); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^
error: possible infinite iteration detected
- --> $DIR/infinite_iter.rs:41:5
+ --> $DIR/infinite_iter.rs:43:5
|
LL | (0..).all(|x| x == 24); // maybe infinite iter
| ^^^^^^^^^^^^^^^^^^^^^^
error: infinite iteration detected
- --> $DIR/infinite_iter.rs:63:31
+ --> $DIR/infinite_iter.rs:65:31
|
LL | let _: HashSet<i32> = (0..).collect(); // Infinite iter
| ^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/infinite_loop.stderr b/src/tools/clippy/tests/ui/infinite_loop.stderr
index 4ec7d900a..85258b9d6 100644
--- a/src/tools/clippy/tests/ui/infinite_loop.stderr
+++ b/src/tools/clippy/tests/ui/infinite_loop.stderr
@@ -4,8 +4,8 @@ error: variables in the condition are not mutated in the loop body
LL | while y < 10 {
| ^^^^^^
|
- = note: `#[deny(clippy::while_immutable_condition)]` on by default
= note: this may lead to an infinite or to a never running loop
+ = note: `#[deny(clippy::while_immutable_condition)]` on by default
error: variables in the condition are not mutated in the loop body
--> $DIR/infinite_loop.rs:25:11
diff --git a/src/tools/clippy/tests/ui/inherent_to_string.stderr b/src/tools/clippy/tests/ui/inherent_to_string.stderr
index 4f331f5be..443fecae1 100644
--- a/src/tools/clippy/tests/ui/inherent_to_string.stderr
+++ b/src/tools/clippy/tests/ui/inherent_to_string.stderr
@@ -6,8 +6,8 @@ LL | | "A.to_string()".to_string()
LL | | }
| |_____^
|
- = note: `-D clippy::inherent-to-string` implied by `-D warnings`
= help: implement trait `Display` for type `A` instead
+ = note: `-D clippy::inherent-to-string` implied by `-D warnings`
error: type `C` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`
--> $DIR/inherent_to_string.rs:44:5
@@ -17,12 +17,12 @@ LL | | "C.to_string()".to_string()
LL | | }
| |_____^
|
+ = help: remove the inherent method from type `C`
note: the lint level is defined here
--> $DIR/inherent_to_string.rs:2:9
|
LL | #![deny(clippy::inherent_to_string_shadow_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: remove the inherent method from type `C`
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/inspect_for_each.stderr b/src/tools/clippy/tests/ui/inspect_for_each.stderr
index 9f976bb74..67c2d5e53 100644
--- a/src/tools/clippy/tests/ui/inspect_for_each.stderr
+++ b/src/tools/clippy/tests/ui/inspect_for_each.stderr
@@ -9,8 +9,8 @@ LL | | b.push(z);
LL | | });
| |______^
|
- = note: `-D clippy::inspect-for-each` implied by `-D warnings`
= help: move the code from `inspect(..)` to `for_each(..)` and remove the `inspect(..)`
+ = note: `-D clippy::inspect-for-each` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/integer_division.stderr b/src/tools/clippy/tests/ui/integer_division.stderr
index cbb7f8814..ca8001279 100644
--- a/src/tools/clippy/tests/ui/integer_division.stderr
+++ b/src/tools/clippy/tests/ui/integer_division.stderr
@@ -4,8 +4,8 @@ error: integer division
LL | let n = 1 / 2;
| ^^^^^
|
- = note: `-D clippy::integer-division` implied by `-D warnings`
= help: division of integers may cause loss of precision. consider using floats
+ = note: `-D clippy::integer-division` implied by `-D warnings`
error: integer division
--> $DIR/integer_division.rs:6:13
diff --git a/src/tools/clippy/tests/ui/issue_2356.fixed b/src/tools/clippy/tests/ui/issue_2356.fixed
index 942e99fa8..a73ee0fb2 100644
--- a/src/tools/clippy/tests/ui/issue_2356.fixed
+++ b/src/tools/clippy/tests/ui/issue_2356.fixed
@@ -1,6 +1,7 @@
// run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
+#![allow(clippy::uninlined_format_args)]
use std::iter::Iterator;
diff --git a/src/tools/clippy/tests/ui/issue_2356.rs b/src/tools/clippy/tests/ui/issue_2356.rs
index b000234ea..9dd906960 100644
--- a/src/tools/clippy/tests/ui/issue_2356.rs
+++ b/src/tools/clippy/tests/ui/issue_2356.rs
@@ -1,6 +1,7 @@
// run-rustfix
#![deny(clippy::while_let_on_iterator)]
#![allow(unused_mut)]
+#![allow(clippy::uninlined_format_args)]
use std::iter::Iterator;
diff --git a/src/tools/clippy/tests/ui/issue_2356.stderr b/src/tools/clippy/tests/ui/issue_2356.stderr
index 4e3ff7522..a24b0b32e 100644
--- a/src/tools/clippy/tests/ui/issue_2356.stderr
+++ b/src/tools/clippy/tests/ui/issue_2356.stderr
@@ -1,5 +1,5 @@
error: this loop could be written as a `for` loop
- --> $DIR/issue_2356.rs:17:9
+ --> $DIR/issue_2356.rs:18:9
|
LL | while let Some(e) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for e in it`
diff --git a/src/tools/clippy/tests/ui/issue_4266.rs b/src/tools/clippy/tests/ui/issue_4266.rs
index d9d48189b..8e0620e52 100644
--- a/src/tools/clippy/tests/ui/issue_4266.rs
+++ b/src/tools/clippy/tests/ui/issue_4266.rs
@@ -1,4 +1,5 @@
#![allow(dead_code)]
+#![allow(clippy::uninlined_format_args)]
async fn sink1<'a>(_: &'a str) {} // lint
async fn sink1_elided(_: &str) {} // ok
diff --git a/src/tools/clippy/tests/ui/issue_4266.stderr b/src/tools/clippy/tests/ui/issue_4266.stderr
index e5042aaa7..fb2a93c95 100644
--- a/src/tools/clippy/tests/ui/issue_4266.stderr
+++ b/src/tools/clippy/tests/ui/issue_4266.stderr
@@ -1,5 +1,5 @@
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/issue_4266.rs:3:1
+ --> $DIR/issue_4266.rs:4:1
|
LL | async fn sink1<'a>(_: &'a str) {} // lint
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,19 +7,19 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint
= note: `-D clippy::needless-lifetimes` implied by `-D warnings`
error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
- --> $DIR/issue_4266.rs:7:1
+ --> $DIR/issue_4266.rs:8:1
|
LL | async fn one_to_one<'a>(s: &'a str) -> &'a str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: methods called `new` usually take no `self`
- --> $DIR/issue_4266.rs:27:22
+ --> $DIR/issue_4266.rs:28:22
|
LL | pub async fn new(&mut self) -> Self {
| ^^^^^^^^^
|
- = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
= help: consider choosing a less ambiguous name
+ = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/item_after_statement.rs b/src/tools/clippy/tests/ui/item_after_statement.rs
index d439ca1e4..5e92dcab1 100644
--- a/src/tools/clippy/tests/ui/item_after_statement.rs
+++ b/src/tools/clippy/tests/ui/item_after_statement.rs
@@ -1,4 +1,5 @@
#![warn(clippy::items_after_statements)]
+#![allow(clippy::uninlined_format_args)]
fn ok() {
fn foo() {
diff --git a/src/tools/clippy/tests/ui/item_after_statement.stderr b/src/tools/clippy/tests/ui/item_after_statement.stderr
index ab4a6374c..2523c53ac 100644
--- a/src/tools/clippy/tests/ui/item_after_statement.stderr
+++ b/src/tools/clippy/tests/ui/item_after_statement.stderr
@@ -1,5 +1,5 @@
error: adding items after statements is confusing, since items exist from the start of the scope
- --> $DIR/item_after_statement.rs:12:5
+ --> $DIR/item_after_statement.rs:13:5
|
LL | / fn foo() {
LL | | println!("foo");
@@ -9,7 +9,7 @@ LL | | }
= note: `-D clippy::items-after-statements` implied by `-D warnings`
error: adding items after statements is confusing, since items exist from the start of the scope
- --> $DIR/item_after_statement.rs:19:5
+ --> $DIR/item_after_statement.rs:20:5
|
LL | / fn foo() {
LL | | println!("foo");
@@ -17,7 +17,7 @@ LL | | }
| |_____^
error: adding items after statements is confusing, since items exist from the start of the scope
- --> $DIR/item_after_statement.rs:32:13
+ --> $DIR/item_after_statement.rs:33:13
|
LL | / fn say_something() {
LL | | println!("something");
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.fixed b/src/tools/clippy/tests/ui/iter_kv_map.fixed
new file mode 100644
index 000000000..83fee0408
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_kv_map.fixed
@@ -0,0 +1,64 @@
+// run-rustfix
+
+#![warn(clippy::iter_kv_map)]
+#![allow(clippy::redundant_clone)]
+#![allow(clippy::suspicious_map)]
+#![allow(clippy::map_identity)]
+
+use std::collections::{BTreeMap, HashMap};
+
+fn main() {
+ let get_key = |(key, _val)| key;
+
+ let map: HashMap<u32, u32> = HashMap::new();
+
+ let _ = map.keys().collect::<Vec<_>>();
+ let _ = map.values().collect::<Vec<_>>();
+ let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_keys().collect::<Vec<_>>();
+ let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_values().collect::<Vec<_>>();
+ let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().values().collect::<Vec<_>>();
+ let _ = map.keys().filter(|x| *x % 2 == 0).count();
+
+ // Don't lint
+ let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+ let _ = map.iter().map(get_key).collect::<Vec<_>>();
+
+ // Linting the following could be an improvement to the lint
+ // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+
+ // Lint
+ let _ = map.keys().map(|key| key * 9).count();
+ let _ = map.values().map(|value| value * 17).count();
+
+ let map: BTreeMap<u32, u32> = BTreeMap::new();
+
+ let _ = map.keys().collect::<Vec<_>>();
+ let _ = map.values().collect::<Vec<_>>();
+ let _ = map.values().map(|v| v + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_keys().collect::<Vec<_>>();
+ let _ = map.clone().into_keys().map(|key| key + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_values().collect::<Vec<_>>();
+ let _ = map.clone().into_values().map(|val| val + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().values().collect::<Vec<_>>();
+ let _ = map.keys().filter(|x| *x % 2 == 0).count();
+
+ // Don't lint
+ let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+ let _ = map.iter().map(get_key).collect::<Vec<_>>();
+
+ // Linting the following could be an improvement to the lint
+ // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+
+ // Lint
+ let _ = map.keys().map(|key| key * 9).count();
+ let _ = map.values().map(|value| value * 17).count();
+}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.rs b/src/tools/clippy/tests/ui/iter_kv_map.rs
new file mode 100644
index 000000000..7a1f1fb01
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_kv_map.rs
@@ -0,0 +1,64 @@
+// run-rustfix
+
+#![warn(clippy::iter_kv_map)]
+#![allow(clippy::redundant_clone)]
+#![allow(clippy::suspicious_map)]
+#![allow(clippy::map_identity)]
+
+use std::collections::{BTreeMap, HashMap};
+
+fn main() {
+ let get_key = |(key, _val)| key;
+
+ let map: HashMap<u32, u32> = HashMap::new();
+
+ let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
+ let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+ let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
+ let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
+ let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
+ let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+
+ // Don't lint
+ let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+ let _ = map.iter().map(get_key).collect::<Vec<_>>();
+
+ // Linting the following could be an improvement to the lint
+ // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+
+ // Lint
+ let _ = map.iter().map(|(key, _value)| key * 9).count();
+ let _ = map.iter().map(|(_key, value)| value * 17).count();
+
+ let map: BTreeMap<u32, u32> = BTreeMap::new();
+
+ let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
+ let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+ let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
+ let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
+ let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
+
+ let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
+ let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+
+ // Don't lint
+ let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count();
+ let _ = map.iter().map(get_key).collect::<Vec<_>>();
+
+ // Linting the following could be an improvement to the lint
+ // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count();
+
+ // Lint
+ let _ = map.iter().map(|(key, _value)| key * 9).count();
+ let _ = map.iter().map(|(_key, value)| value * 17).count();
+}
diff --git a/src/tools/clippy/tests/ui/iter_kv_map.stderr b/src/tools/clippy/tests/ui/iter_kv_map.stderr
new file mode 100644
index 000000000..9b9b04c97
--- /dev/null
+++ b/src/tools/clippy/tests/ui/iter_kv_map.stderr
@@ -0,0 +1,136 @@
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:15:13
+ |
+LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
+ |
+ = note: `-D clippy::iter-kv-map` implied by `-D warnings`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:16:13
+ |
+LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:17:13
+ |
+LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:19:13
+ |
+LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:20:13
+ |
+LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:22:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:23:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:25:13
+ |
+LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:26:13
+ |
+LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:36:13
+ |
+LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:37:13
+ |
+LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:41:13
+ |
+LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:42:13
+ |
+LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:43:13
+ |
+LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:45:13
+ |
+LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:46:13
+ |
+LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:48:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:49:13
+ |
+LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:51:13
+ |
+LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:52:13
+ |
+LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()`
+
+error: iterating on a map's keys
+ --> $DIR/iter_kv_map.rs:62:13
+ |
+LL | let _ = map.iter().map(|(key, _value)| key * 9).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)`
+
+error: iterating on a map's values
+ --> $DIR/iter_kv_map.rs:63:13
+ |
+LL | let _ = map.iter().map(|(_key, value)| value * 17).count();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)`
+
+error: aborting due to 22 previous errors
+
diff --git a/src/tools/clippy/tests/ui/iter_nth.stderr b/src/tools/clippy/tests/ui/iter_nth.stderr
index d00b2fb67..a0fe353bc 100644
--- a/src/tools/clippy/tests/ui/iter_nth.stderr
+++ b/src/tools/clippy/tests/ui/iter_nth.stderr
@@ -4,8 +4,8 @@ error: called `.iter().nth()` on a Vec
LL | let bad_vec = some_vec.iter().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::iter-nth` implied by `-D warnings`
= help: calling `.get()` is both faster and more readable
+ = note: `-D clippy::iter-nth` implied by `-D warnings`
error: called `.iter().nth()` on a slice
--> $DIR/iter_nth.rs:34:26
diff --git a/src/tools/clippy/tests/ui/iter_skip_next_unfixable.stderr b/src/tools/clippy/tests/ui/iter_skip_next_unfixable.stderr
index 74c327c74..4062706f9 100644
--- a/src/tools/clippy/tests/ui/iter_skip_next_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/iter_skip_next_unfixable.stderr
@@ -4,12 +4,12 @@ error: called `skip(..).next()` on an iterator
LL | let _: Vec<&str> = sp.skip(1).next().unwrap().split(' ').collect();
| ^^^^^^^^^^^^^^^ help: use `nth` instead: `.nth(1)`
|
- = note: `-D clippy::iter-skip-next` implied by `-D warnings`
help: for this change `sp` has to be mutable
--> $DIR/iter_skip_next_unfixable.rs:8:9
|
LL | let sp = test_string.split('|').map(|s| s.trim());
| ^^
+ = note: `-D clippy::iter-skip-next` implied by `-D warnings`
error: called `skip(..).next()` on an iterator
--> $DIR/iter_skip_next_unfixable.rs:11:29
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.rs b/src/tools/clippy/tests/ui/large_enum_variant.rs
index 717009e4c..3b96f09d7 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.rs
+++ b/src/tools/clippy/tests/ui/large_enum_variant.rs
@@ -101,12 +101,12 @@ struct Struct2 {
#[derive(Copy, Clone)]
enum CopyableLargeEnum {
A(bool),
- B([u128; 4000]),
+ B([u64; 8000]),
}
enum ManuallyCopyLargeEnum {
A(bool),
- B([u128; 4000]),
+ B([u64; 8000]),
}
impl Clone for ManuallyCopyLargeEnum {
diff --git a/src/tools/clippy/tests/ui/large_enum_variant.stderr b/src/tools/clippy/tests/ui/large_enum_variant.stderr
index c6ed97487..709972b4a 100644
--- a/src/tools/clippy/tests/ui/large_enum_variant.stderr
+++ b/src/tools/clippy/tests/ui/large_enum_variant.stderr
@@ -167,8 +167,8 @@ error: large size difference between variants
LL | / enum CopyableLargeEnum {
LL | | A(bool),
| | ------- the second-largest variant contains at least 1 bytes
-LL | | B([u128; 4000]),
- | | --------------- the largest variant contains at least 64000 bytes
+LL | | B([u64; 8000]),
+ | | -------------- the largest variant contains at least 64000 bytes
LL | | }
| |_^ the entire enum is at least 64008 bytes
|
@@ -180,8 +180,8 @@ LL | enum CopyableLargeEnum {
help: consider boxing the large fields to reduce the total size of the enum
--> $DIR/large_enum_variant.rs:104:5
|
-LL | B([u128; 4000]),
- | ^^^^^^^^^^^^^^^
+LL | B([u64; 8000]),
+ | ^^^^^^^^^^^^^^
error: large size difference between variants
--> $DIR/large_enum_variant.rs:107:1
@@ -189,8 +189,8 @@ error: large size difference between variants
LL | / enum ManuallyCopyLargeEnum {
LL | | A(bool),
| | ------- the second-largest variant contains at least 1 bytes
-LL | | B([u128; 4000]),
- | | --------------- the largest variant contains at least 64000 bytes
+LL | | B([u64; 8000]),
+ | | -------------- the largest variant contains at least 64000 bytes
LL | | }
| |_^ the entire enum is at least 64008 bytes
|
@@ -202,8 +202,8 @@ LL | enum ManuallyCopyLargeEnum {
help: consider boxing the large fields to reduce the total size of the enum
--> $DIR/large_enum_variant.rs:109:5
|
-LL | B([u128; 4000]),
- | ^^^^^^^^^^^^^^^
+LL | B([u64; 8000]),
+ | ^^^^^^^^^^^^^^
error: large size difference between variants
--> $DIR/large_enum_variant.rs:120:1
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.rs b/src/tools/clippy/tests/ui/large_stack_arrays.rs
index d9161bfcf..6790765f8 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.rs
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.rs
@@ -12,6 +12,12 @@ enum E {
T(u32),
}
+pub static DOESNOTLINT: [u8; 512_001] = [0; 512_001];
+pub static DOESNOTLINT2: [u8; 512_001] = {
+ let x = 0;
+ [x; 512_001]
+};
+
fn main() {
let bad = (
[0u32; 20_000_000],
diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.stderr b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
index 58c0a77c1..c7bf941ad 100644
--- a/src/tools/clippy/tests/ui/large_stack_arrays.stderr
+++ b/src/tools/clippy/tests/ui/large_stack_arrays.stderr
@@ -1,14 +1,14 @@
error: allocating a local array larger than 512000 bytes
- --> $DIR/large_stack_arrays.rs:17:9
+ --> $DIR/large_stack_arrays.rs:23:9
|
LL | [0u32; 20_000_000],
| ^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::large-stack-arrays` implied by `-D warnings`
= help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()`
+ = note: `-D clippy::large-stack-arrays` implied by `-D warnings`
error: allocating a local array larger than 512000 bytes
- --> $DIR/large_stack_arrays.rs:18:9
+ --> $DIR/large_stack_arrays.rs:24:9
|
LL | [S { data: [0; 32] }; 5000],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | [S { data: [0; 32] }; 5000],
= help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
- --> $DIR/large_stack_arrays.rs:19:9
+ --> $DIR/large_stack_arrays.rs:25:9
|
LL | [Some(""); 20_000_000],
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL | [Some(""); 20_000_000],
= help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
- --> $DIR/large_stack_arrays.rs:20:9
+ --> $DIR/large_stack_arrays.rs:26:9
|
LL | [E::T(0); 5000],
| ^^^^^^^^^^^^^^^
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 1e938e72b..78397c2af 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.rs
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.rs
@@ -274,7 +274,7 @@ impl AsyncLen {
}
pub async fn len(&self) -> usize {
- if self.async_task().await { 0 } else { 1 }
+ usize::from(!self.async_task().await)
}
pub async fn is_empty(&self) -> bool {
diff --git a/src/tools/clippy/tests/ui/len_without_is_empty.stderr b/src/tools/clippy/tests/ui/len_without_is_empty.stderr
index a1f48f761..8e890e2e2 100644
--- a/src/tools/clippy/tests/ui/len_without_is_empty.stderr
+++ b/src/tools/clippy/tests/ui/len_without_is_empty.stderr
@@ -92,8 +92,8 @@ error: this returns a `Result<_, ()>`
LL | pub fn len(&self) -> Result<usize, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::result-unit-err` implied by `-D warnings`
= help: use a custom `Error` type instead
+ = note: `-D clippy::result-unit-err` implied by `-D warnings`
error: this returns a `Result<_, ()>`
--> $DIR/len_without_is_empty.rs:240:5
diff --git a/src/tools/clippy/tests/ui/let_if_seq.stderr b/src/tools/clippy/tests/ui/let_if_seq.stderr
index 271ccce68..f2e0edb6f 100644
--- a/src/tools/clippy/tests/ui/let_if_seq.stderr
+++ b/src/tools/clippy/tests/ui/let_if_seq.stderr
@@ -7,8 +7,8 @@ LL | | foo = 42;
LL | | }
| |_____^ help: it is more idiomatic to write: `let <mut> foo = if f() { 42 } else { 0 };`
|
- = note: `-D clippy::useless-let-if-seq` implied by `-D warnings`
= note: you might not need `mut` at all
+ = note: `-D clippy::useless-let-if-seq` implied by `-D warnings`
error: `if _ { .. } else { .. }` is an expression
--> $DIR/let_if_seq.rs:71:5
diff --git a/src/tools/clippy/tests/ui/let_underscore_drop.stderr b/src/tools/clippy/tests/ui/let_underscore_drop.stderr
index ee7bbe995..324b7cd43 100644
--- a/src/tools/clippy/tests/ui/let_underscore_drop.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_drop.stderr
@@ -4,8 +4,8 @@ error: non-binding `let` on a type that implements `Drop`
LL | let _ = Box::new(());
| ^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::let-underscore-drop` implied by `-D warnings`
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+ = note: `-D clippy::let-underscore-drop` implied by `-D warnings`
error: non-binding `let` on a type that implements `Drop`
--> $DIR/let_underscore_drop.rs:18:5
diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.stderr b/src/tools/clippy/tests/ui/let_underscore_lock.stderr
index 4365b48fa..d7779e7b6 100644
--- a/src/tools/clippy/tests/ui/let_underscore_lock.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_lock.stderr
@@ -4,8 +4,8 @@ error: non-binding let on a synchronization lock
LL | let _ = m.lock();
| ^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
= help: consider using an underscore-prefixed named binding or dropping explicitly with `std::mem::drop`
+ = note: `-D clippy::let-underscore-lock` implied by `-D warnings`
error: non-binding let on a synchronization lock
--> $DIR/let_underscore_lock.rs:10:5
diff --git a/src/tools/clippy/tests/ui/let_underscore_must_use.stderr b/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
index 5b751ea56..bae60f2ff 100644
--- a/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
+++ b/src/tools/clippy/tests/ui/let_underscore_must_use.stderr
@@ -4,8 +4,8 @@ error: non-binding let on a result of a `#[must_use]` function
LL | let _ = f();
| ^^^^^^^^^^^^
|
- = note: `-D clippy::let-underscore-must-use` implied by `-D warnings`
= help: consider explicitly using function result
+ = note: `-D clippy::let-underscore-must-use` implied by `-D warnings`
error: non-binding let on an expression with `#[must_use]` type
--> $DIR/let_underscore_must_use.rs:68:5
diff --git a/src/tools/clippy/tests/ui/linkedlist.stderr b/src/tools/clippy/tests/ui/linkedlist.stderr
index 51327df13..c76c94961 100644
--- a/src/tools/clippy/tests/ui/linkedlist.stderr
+++ b/src/tools/clippy/tests/ui/linkedlist.stderr
@@ -4,8 +4,8 @@ error: you seem to be using a `LinkedList`! Perhaps you meant some other data st
LL | const C: LinkedList<i32> = LinkedList::new();
| ^^^^^^^^^^^^^^^
|
- = note: `-D clippy::linkedlist` implied by `-D warnings`
= help: a `VecDeque` might work
+ = note: `-D clippy::linkedlist` implied by `-D warnings`
error: you seem to be using a `LinkedList`! Perhaps you meant some other data structure?
--> $DIR/linkedlist.rs:9:11
diff --git a/src/tools/clippy/tests/ui/literals.rs b/src/tools/clippy/tests/ui/literals.rs
index 0cadd5a3d..1a646e49c 100644
--- a/src/tools/clippy/tests/ui/literals.rs
+++ b/src/tools/clippy/tests/ui/literals.rs
@@ -40,3 +40,10 @@ fn main() {
let ok26 = 0x6_A0_BF;
let ok27 = 0b1_0010_0101;
}
+
+fn issue9651() {
+ // lint but octal form is not possible here
+ let _ = 08;
+ let _ = 09;
+ let _ = 089;
+}
diff --git a/src/tools/clippy/tests/ui/literals.stderr b/src/tools/clippy/tests/ui/literals.stderr
index 365b24074..603d47bac 100644
--- a/src/tools/clippy/tests/ui/literals.stderr
+++ b/src/tools/clippy/tests/ui/literals.stderr
@@ -135,5 +135,38 @@ error: digits of hex or binary literal not grouped by four
LL | let fail25 = 0b01_100_101;
| ^^^^^^^^^^^^ help: consider: `0b0110_0101`
-error: aborting due to 18 previous errors
+error: this is a decimal constant
+ --> $DIR/literals.rs:46:13
+ |
+LL | let _ = 08;
+ | ^^
+ |
+help: if you mean to use a decimal constant, remove the `0` to avoid confusion
+ |
+LL | let _ = 8;
+ | ~
+
+error: this is a decimal constant
+ --> $DIR/literals.rs:47:13
+ |
+LL | let _ = 09;
+ | ^^
+ |
+help: if you mean to use a decimal constant, remove the `0` to avoid confusion
+ |
+LL | let _ = 9;
+ | ~
+
+error: this is a decimal constant
+ --> $DIR/literals.rs:48:13
+ |
+LL | let _ = 089;
+ | ^^^
+ |
+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
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
index 65598f1ea..c9a819ba5 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.fixed
@@ -1,10 +1,11 @@
// revisions: edition2018 edition2021
-// [edition2018] edition:2018
-// [edition2021] edition:2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
// run-rustfix
#![warn(clippy::manual_assert)]
-#![allow(clippy::nonminimal_bool)]
+#![allow(dead_code, unused_doc_comments)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
macro_rules! one {
() => {
@@ -28,7 +29,9 @@ fn main() {
panic!("qaqaq{:?}", a);
}
assert!(a.is_empty(), "qaqaq{:?}", a);
- assert!(a.is_empty(), "qwqwq");
+ if !a.is_empty() {
+ panic!("qwqwq");
+ }
if a.len() == 3 {
println!("qwq");
println!("qwq");
@@ -43,10 +46,32 @@ fn main() {
println!("qwq");
}
let b = vec![1, 2, 3];
- assert!(!b.is_empty(), "panic1");
- assert!(!(b.is_empty() && a.is_empty()), "panic2");
- assert!(!(a.is_empty() && !b.is_empty()), "panic3");
- assert!(!(b.is_empty() || a.is_empty()), "panic4");
- assert!(!(a.is_empty() || !b.is_empty()), "panic5");
+ 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!(!a.is_empty(), "with expansion {}", one!());
}
+
+fn issue7730(a: u8) {
+ // Suggestion should preserve comment
+ if a > 2 {
+ // comment
+ /* this is a
+ multiline
+ comment */
+ /// Doc comment
+ panic!("panic with comment") // comment after `panic!`
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
index a0f31afd6..1f2e1e308 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2018.stderr
@@ -1,68 +1,20 @@
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:30:5
+ --> $DIR/manual_assert.rs:31:5
|
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:33:5
- |
-LL | / if !a.is_empty() {
-LL | | panic!("qwqwq");
-LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:50:5
- |
-LL | / if b.is_empty() {
-LL | | panic!("panic1");
-LL | | }
- | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:53:5
- |
-LL | / if b.is_empty() && a.is_empty() {
-LL | | panic!("panic2");
-LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:56:5
- |
-LL | / if a.is_empty() && !b.is_empty() {
-LL | | panic!("panic3");
-LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:59:5
- |
-LL | / if b.is_empty() || a.is_empty() {
-LL | | panic!("panic4");
-LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:62:5
- |
-LL | / if a.is_empty() || !b.is_empty() {
-LL | | panic!("panic5");
-LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
-
-error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:65:5
+ --> $DIR/manual_assert.rs:66:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
- | |_____^ help: try: `assert!(!a.is_empty(), "with expansion {}", one!());`
+ | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
-error: aborting due to 8 previous errors
+error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
index 65598f1ea..2f62de51c 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.fixed
@@ -1,10 +1,11 @@
// revisions: edition2018 edition2021
-// [edition2018] edition:2018
-// [edition2021] edition:2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
// run-rustfix
#![warn(clippy::manual_assert)]
-#![allow(clippy::nonminimal_bool)]
+#![allow(dead_code, unused_doc_comments)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
macro_rules! one {
() => {
@@ -50,3 +51,14 @@ fn main() {
assert!(!(a.is_empty() || !b.is_empty()), "panic5");
assert!(!a.is_empty(), "with expansion {}", one!());
}
+
+fn issue7730(a: u8) {
+ // Suggestion should preserve comment
+ // comment
+/* this is a
+ multiline
+ comment */
+/// Doc comment
+// comment after `panic!`
+assert!(!(a > 2), "panic with comment");
+}
diff --git a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
index a0f31afd6..237638ee1 100644
--- a/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/manual_assert.edition2021.stderr
@@ -1,68 +1,85 @@
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:30:5
+ --> $DIR/manual_assert.rs:31:5
|
LL | / if !a.is_empty() {
LL | | panic!("qaqaq{:?}", a);
LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qaqaq{:?}", a);`
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qaqaq{:?}", a);`
|
= note: `-D clippy::manual-assert` implied by `-D warnings`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:33:5
+ --> $DIR/manual_assert.rs:34:5
|
LL | / if !a.is_empty() {
LL | | panic!("qwqwq");
LL | | }
- | |_____^ help: try: `assert!(a.is_empty(), "qwqwq");`
+ | |_____^ help: try instead: `assert!(a.is_empty(), "qwqwq");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:50:5
+ --> $DIR/manual_assert.rs:51:5
|
LL | / if b.is_empty() {
LL | | panic!("panic1");
LL | | }
- | |_____^ help: try: `assert!(!b.is_empty(), "panic1");`
+ | |_____^ help: try instead: `assert!(!b.is_empty(), "panic1");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:53:5
+ --> $DIR/manual_assert.rs:54:5
|
LL | / if b.is_empty() && a.is_empty() {
LL | | panic!("panic2");
LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
+ | |_____^ help: try instead: `assert!(!(b.is_empty() && a.is_empty()), "panic2");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:56:5
+ --> $DIR/manual_assert.rs:57:5
|
LL | / if a.is_empty() && !b.is_empty() {
LL | | panic!("panic3");
LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
+ | |_____^ help: try instead: `assert!(!(a.is_empty() && !b.is_empty()), "panic3");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:59:5
+ --> $DIR/manual_assert.rs:60:5
|
LL | / if b.is_empty() || a.is_empty() {
LL | | panic!("panic4");
LL | | }
- | |_____^ help: try: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
+ | |_____^ help: try instead: `assert!(!(b.is_empty() || a.is_empty()), "panic4");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:62:5
+ --> $DIR/manual_assert.rs:63:5
|
LL | / if a.is_empty() || !b.is_empty() {
LL | | panic!("panic5");
LL | | }
- | |_____^ help: try: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
+ | |_____^ help: try instead: `assert!(!(a.is_empty() || !b.is_empty()), "panic5");`
error: only a `panic!` in `if`-then statement
- --> $DIR/manual_assert.rs:65:5
+ --> $DIR/manual_assert.rs:66:5
|
LL | / if a.is_empty() {
LL | | panic!("with expansion {}", one!())
LL | | }
- | |_____^ help: try: `assert!(!a.is_empty(), "with expansion {}", one!());`
+ | |_____^ help: try instead: `assert!(!a.is_empty(), "with expansion {}", one!());`
-error: aborting due to 8 previous errors
+error: only a `panic!` in `if`-then statement
+ --> $DIR/manual_assert.rs:73: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_assert.fixed b/src/tools/clippy/tests/ui/manual_assert.fixed
deleted file mode 100644
index a2393674f..000000000
--- a/src/tools/clippy/tests/ui/manual_assert.fixed
+++ /dev/null
@@ -1,45 +0,0 @@
-// revisions: edition2018 edition2021
-// [edition2018] edition:2018
-// [edition2021] edition:2021
-// run-rustfix
-
-#![warn(clippy::manual_assert)]
-#![allow(clippy::nonminimal_bool)]
-
-fn main() {
- let a = vec![1, 2, 3];
- let c = Some(2);
- if !a.is_empty()
- && a.len() == 3
- && c.is_some()
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- && !a.is_empty()
- && a.len() == 3
- {
- panic!("qaqaq{:?}", a);
- }
- assert!(a.is_empty(), "qaqaq{:?}", a);
- assert!(a.is_empty(), "qwqwq");
- if a.len() == 3 {
- println!("qwq");
- println!("qwq");
- println!("qwq");
- }
- if let Some(b) = c {
- panic!("orz {}", b);
- }
- if a.len() == 3 {
- panic!("qaqaq");
- } else {
- println!("qwq");
- }
- let b = vec![1, 2, 3];
- assert!(!b.is_empty(), "panic1");
- assert!(!(b.is_empty() && a.is_empty()), "panic2");
- assert!(!(a.is_empty() && !b.is_empty()), "panic3");
- assert!(!(b.is_empty() || a.is_empty()), "panic4");
- assert!(!(a.is_empty() || !b.is_empty()), "panic5");
-}
diff --git a/src/tools/clippy/tests/ui/manual_assert.rs b/src/tools/clippy/tests/ui/manual_assert.rs
index 4d2706dd6..6a4cc2468 100644
--- a/src/tools/clippy/tests/ui/manual_assert.rs
+++ b/src/tools/clippy/tests/ui/manual_assert.rs
@@ -1,10 +1,11 @@
// revisions: edition2018 edition2021
-// [edition2018] edition:2018
-// [edition2021] edition:2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
// run-rustfix
#![warn(clippy::manual_assert)]
-#![allow(clippy::nonminimal_bool)]
+#![allow(dead_code, unused_doc_comments)]
+#![allow(clippy::nonminimal_bool, clippy::uninlined_format_args)]
macro_rules! one {
() => {
@@ -66,3 +67,15 @@ fn main() {
panic!("with expansion {}", one!())
}
}
+
+fn issue7730(a: u8) {
+ // Suggestion should preserve comment
+ if a > 2 {
+ // comment
+ /* this is a
+ multiline
+ comment */
+ /// Doc comment
+ panic!("panic with comment") // comment after `panic!`
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_bits.fixed b/src/tools/clippy/tests/ui/manual_bits.fixed
index 386360dbd..e7f8cd878 100644
--- a/src/tools/clippy/tests/ui/manual_bits.fixed
+++ b/src/tools/clippy/tests/ui/manual_bits.fixed
@@ -6,7 +6,8 @@
clippy::useless_conversion,
path_statements,
unused_must_use,
- clippy::unnecessary_operation
+ clippy::unnecessary_operation,
+ clippy::unnecessary_cast
)]
use std::mem::{size_of, size_of_val};
diff --git a/src/tools/clippy/tests/ui/manual_bits.rs b/src/tools/clippy/tests/ui/manual_bits.rs
index 62638f047..7b1d15495 100644
--- a/src/tools/clippy/tests/ui/manual_bits.rs
+++ b/src/tools/clippy/tests/ui/manual_bits.rs
@@ -6,7 +6,8 @@
clippy::useless_conversion,
path_statements,
unused_must_use,
- clippy::unnecessary_operation
+ clippy::unnecessary_operation,
+ clippy::unnecessary_cast
)]
use std::mem::{size_of, size_of_val};
diff --git a/src/tools/clippy/tests/ui/manual_bits.stderr b/src/tools/clippy/tests/ui/manual_bits.stderr
index 69c591a20..652fafbc4 100644
--- a/src/tools/clippy/tests/ui/manual_bits.stderr
+++ b/src/tools/clippy/tests/ui/manual_bits.stderr
@@ -1,5 +1,5 @@
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:15:5
+ --> $DIR/manual_bits.rs:16:5
|
LL | size_of::<i8>() * 8;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize`
@@ -7,169 +7,169 @@ LL | size_of::<i8>() * 8;
= note: `-D clippy::manual-bits` implied by `-D warnings`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:16:5
+ --> $DIR/manual_bits.rs:17:5
|
LL | size_of::<i16>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:17:5
+ --> $DIR/manual_bits.rs:18:5
|
LL | size_of::<i32>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:18:5
+ --> $DIR/manual_bits.rs:19:5
|
LL | size_of::<i64>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:19:5
+ --> $DIR/manual_bits.rs:20:5
|
LL | size_of::<i128>() * 8;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:20:5
+ --> $DIR/manual_bits.rs:21:5
|
LL | size_of::<isize>() * 8;
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:22:5
+ --> $DIR/manual_bits.rs:23:5
|
LL | size_of::<u8>() * 8;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:23:5
+ --> $DIR/manual_bits.rs:24:5
|
LL | size_of::<u16>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:24:5
+ --> $DIR/manual_bits.rs:25:5
|
LL | size_of::<u32>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:25:5
+ --> $DIR/manual_bits.rs:26:5
|
LL | size_of::<u64>() * 8;
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:26:5
+ --> $DIR/manual_bits.rs:27:5
|
LL | size_of::<u128>() * 8;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:27:5
+ --> $DIR/manual_bits.rs:28:5
|
LL | size_of::<usize>() * 8;
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:29:5
+ --> $DIR/manual_bits.rs:30:5
|
LL | 8 * size_of::<i8>();
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:30:5
+ --> $DIR/manual_bits.rs:31:5
|
LL | 8 * size_of::<i16>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:31:5
+ --> $DIR/manual_bits.rs:32:5
|
LL | 8 * size_of::<i32>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:32:5
+ --> $DIR/manual_bits.rs:33:5
|
LL | 8 * size_of::<i64>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:33:5
+ --> $DIR/manual_bits.rs:34:5
|
LL | 8 * size_of::<i128>();
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:34:5
+ --> $DIR/manual_bits.rs:35:5
|
LL | 8 * size_of::<isize>();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:36:5
+ --> $DIR/manual_bits.rs:37:5
|
LL | 8 * size_of::<u8>();
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:37:5
+ --> $DIR/manual_bits.rs:38:5
|
LL | 8 * size_of::<u16>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:38:5
+ --> $DIR/manual_bits.rs:39:5
|
LL | 8 * size_of::<u32>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:39:5
+ --> $DIR/manual_bits.rs:40:5
|
LL | 8 * size_of::<u64>();
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:40:5
+ --> $DIR/manual_bits.rs:41:5
|
LL | 8 * size_of::<u128>();
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:41:5
+ --> $DIR/manual_bits.rs:42:5
|
LL | 8 * size_of::<usize>();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:51:5
+ --> $DIR/manual_bits.rs:52:5
|
LL | size_of::<Word>() * 8;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS as usize`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:55:18
+ --> $DIR/manual_bits.rs:56:18
|
LL | let _: u32 = (size_of::<u128>() * 8) as u32;
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:56:18
+ --> $DIR/manual_bits.rs:57:18
|
LL | let _: u32 = (size_of::<u128>() * 8).try_into().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:57:13
+ --> $DIR/manual_bits.rs:58:13
|
LL | let _ = (size_of::<u128>() * 8).pow(5);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)`
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
- --> $DIR/manual_bits.rs:58:14
+ --> $DIR/manual_bits.rs:59:14
|
LL | let _ = &(size_of::<u128>() * 8);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)`
diff --git a/src/tools/clippy/tests/ui/manual_clamp.rs b/src/tools/clippy/tests/ui/manual_clamp.rs
new file mode 100644
index 000000000..331fd29b7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_clamp.rs
@@ -0,0 +1,331 @@
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_clamp)]
+#![allow(
+ unused,
+ dead_code,
+ clippy::unnecessary_operation,
+ clippy::no_effect,
+ clippy::if_same_then_else
+)]
+
+use std::cmp::{max as cmp_max, min as cmp_min};
+
+const CONST_MAX: i32 = 10;
+const CONST_MIN: i32 = 4;
+
+const CONST_F64_MAX: f64 = 10.0;
+const CONST_F64_MIN: f64 = 4.0;
+
+fn main() {
+ let (input, min, max) = (0, -2, 3);
+ // Lint
+ let x0 = if max < input {
+ max
+ } else if min > input {
+ min
+ } else {
+ input
+ };
+
+ let x1 = if input > max {
+ max
+ } else if input < min {
+ min
+ } else {
+ input
+ };
+
+ let x2 = if input < min {
+ min
+ } else if input > max {
+ max
+ } else {
+ input
+ };
+
+ let x3 = if min > input {
+ min
+ } else if max < input {
+ max
+ } else {
+ input
+ };
+
+ let x4 = input.max(min).min(max);
+
+ let x5 = input.min(max).max(min);
+
+ let x6 = match input {
+ x if x > max => max,
+ x if x < min => min,
+ x => x,
+ };
+
+ let x7 = match input {
+ x if x < min => min,
+ x if x > max => max,
+ x => x,
+ };
+
+ let x8 = match input {
+ x if max < x => max,
+ x if min > x => min,
+ x => x,
+ };
+
+ let mut x9 = input;
+ if x9 < min {
+ x9 = min;
+ }
+ if x9 > max {
+ x9 = max;
+ }
+
+ let x10 = match input {
+ x if min > x => min,
+ x if max < x => max,
+ x => x,
+ };
+
+ let mut x11 = input;
+ let _ = 1;
+ if x11 > max {
+ x11 = max;
+ }
+ if x11 < min {
+ x11 = min;
+ }
+
+ let mut x12 = input;
+ if min > x12 {
+ x12 = min;
+ }
+ if max < x12 {
+ x12 = max;
+ }
+
+ let mut x13 = input;
+ if max < x13 {
+ x13 = max;
+ }
+ if min > x13 {
+ x13 = min;
+ }
+
+ let x14 = if input > CONST_MAX {
+ CONST_MAX
+ } else if input < CONST_MIN {
+ CONST_MIN
+ } else {
+ input
+ };
+ {
+ let (input, min, max) = (0.0f64, -2.0, 3.0);
+ let x15 = if input > max {
+ max
+ } else if input < min {
+ min
+ } else {
+ input
+ };
+ }
+ {
+ let input: i32 = cmp_min_max(1);
+ // These can only be detected if exactly one of the arguments to the inner function is const.
+ let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN);
+ let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX);
+ let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX));
+ let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN));
+ let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN);
+ let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX);
+ let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input));
+ let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input));
+ let input: f64 = cmp_min_max(1) as f64;
+ let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN);
+ let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX);
+ let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX));
+ let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN));
+ let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN);
+ let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX);
+ let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input));
+ let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input));
+ }
+ let mut x32 = input;
+ if x32 < min {
+ x32 = min;
+ } else if x32 > max {
+ x32 = max;
+ }
+
+ // It's important this be the last set of statements
+ let mut x33 = input;
+ if max < x33 {
+ x33 = max;
+ }
+ if min > x33 {
+ x33 = min;
+ }
+}
+
+// This code intentionally nonsense.
+fn no_lint() {
+ let (input, min, max) = (0, -2, 3);
+ let x0 = if max < input {
+ max
+ } else if min > input {
+ max
+ } else {
+ min
+ };
+
+ let x1 = if input > max {
+ max
+ } else if input > min {
+ min
+ } else {
+ max
+ };
+
+ let x2 = if max < min {
+ min
+ } else if input > max {
+ input
+ } else {
+ input
+ };
+
+ let x3 = if min > input {
+ input
+ } else if max < input {
+ max
+ } else {
+ max
+ };
+
+ let x6 = match input {
+ x if x < max => x,
+ x if x < min => x,
+ x => x,
+ };
+
+ let x7 = match input {
+ x if x < min => max,
+ x if x > max => min,
+ x => x,
+ };
+
+ let x8 = match input {
+ x if max > x => max,
+ x if min > x => min,
+ x => x,
+ };
+
+ let mut x9 = input;
+ if x9 > min {
+ x9 = min;
+ }
+ if x9 > max {
+ x9 = max;
+ }
+
+ let x10 = match input {
+ x if min > x => min,
+ x if max < x => max,
+ x => min,
+ };
+
+ let mut x11 = input;
+ if x11 > max {
+ x11 = min;
+ }
+ if x11 < min {
+ x11 = max;
+ }
+
+ let mut x12 = input;
+ if min > x12 {
+ x12 = max * 3;
+ }
+ if max < x12 {
+ x12 = min;
+ }
+
+ let mut x13 = input;
+ if max < x13 {
+ let x13 = max;
+ }
+ if min > x13 {
+ x13 = min;
+ }
+ let mut x14 = input;
+ if x14 < min {
+ x14 = 3;
+ } else if x14 > max {
+ x14 = max;
+ }
+ {
+ let input: i32 = cmp_min_max(1);
+ // These can only be detected if exactly one of the arguments to the inner function is const.
+ let x16 = cmp_max(cmp_max(input, CONST_MAX), CONST_MIN);
+ let x17 = cmp_min(cmp_min(input, CONST_MIN), CONST_MAX);
+ let x18 = cmp_max(CONST_MIN, cmp_max(input, CONST_MAX));
+ let x19 = cmp_min(CONST_MAX, cmp_min(input, CONST_MIN));
+ let x20 = cmp_max(cmp_max(CONST_MAX, input), CONST_MIN);
+ let x21 = cmp_min(cmp_min(CONST_MIN, input), CONST_MAX);
+ let x22 = cmp_max(CONST_MIN, cmp_max(CONST_MAX, input));
+ let x23 = cmp_min(CONST_MAX, cmp_min(CONST_MIN, input));
+ let input: f64 = cmp_min_max(1) as f64;
+ let x24 = f64::max(f64::max(input, CONST_F64_MAX), CONST_F64_MIN);
+ let x25 = f64::min(f64::min(input, CONST_F64_MIN), CONST_F64_MAX);
+ let x26 = f64::max(CONST_F64_MIN, f64::max(input, CONST_F64_MAX));
+ let x27 = f64::min(CONST_F64_MAX, f64::min(input, CONST_F64_MIN));
+ let x28 = f64::max(f64::max(CONST_F64_MAX, input), CONST_F64_MIN);
+ let x29 = f64::min(f64::min(CONST_F64_MIN, input), CONST_F64_MAX);
+ let x30 = f64::max(CONST_F64_MIN, f64::max(CONST_F64_MAX, input));
+ let x31 = f64::min(CONST_F64_MAX, f64::min(CONST_F64_MIN, input));
+ let x32 = f64::min(CONST_F64_MAX, f64::min(CONST_F64_MIN, CONST_F64_MAX));
+ }
+}
+
+fn dont_tell_me_what_to_do() {
+ let (input, min, max) = (0, -2, 3);
+ let mut x_never = input;
+ #[allow(clippy::manual_clamp)]
+ if x_never < min {
+ x_never = min;
+ }
+ if x_never > max {
+ x_never = max;
+ }
+}
+
+/// Just to ensure this isn't const evaled
+fn cmp_min_max(input: i32) -> i32 {
+ input * 3
+}
+
+fn msrv_1_49() {
+ #![clippy::msrv = "1.49"]
+
+ let (input, min, max) = (0, -1, 2);
+ let _ = if input < min {
+ min
+ } else if input > max {
+ max
+ } else {
+ input
+ };
+}
+
+fn msrv_1_50() {
+ #![clippy::msrv = "1.50"]
+
+ let (input, min, max) = (0, -1, 2);
+ let _ = if input < min {
+ min
+ } else if input > max {
+ max
+ } else {
+ input
+ };
+}
diff --git a/src/tools/clippy/tests/ui/manual_clamp.stderr b/src/tools/clippy/tests/ui/manual_clamp.stderr
new file mode 100644
index 000000000..70abe2809
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_clamp.stderr
@@ -0,0 +1,390 @@
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:77:5
+ |
+LL | / if x9 < min {
+LL | | x9 = min;
+LL | | }
+LL | | if x9 > max {
+LL | | x9 = max;
+LL | | }
+ | |_____^ help: replace with clamp: `x9 = x9.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+ = note: `-D clippy::manual-clamp` implied by `-D warnings`
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:92:5
+ |
+LL | / if x11 > max {
+LL | | x11 = max;
+LL | | }
+LL | | if x11 < min {
+LL | | x11 = min;
+LL | | }
+ | |_____^ help: replace with clamp: `x11 = x11.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:100:5
+ |
+LL | / if min > x12 {
+LL | | x12 = min;
+LL | | }
+LL | | if max < x12 {
+LL | | x12 = max;
+LL | | }
+ | |_____^ help: replace with clamp: `x12 = x12.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:108:5
+ |
+LL | / if max < x13 {
+LL | | x13 = max;
+LL | | }
+LL | | if min > x13 {
+LL | | x13 = min;
+LL | | }
+ | |_____^ help: replace with clamp: `x13 = x13.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:162:5
+ |
+LL | / if max < x33 {
+LL | | x33 = max;
+LL | | }
+LL | | if min > x33 {
+LL | | x33 = min;
+LL | | }
+ | |_____^ help: replace with clamp: `x33 = x33.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:22:14
+ |
+LL | let x0 = if max < input {
+ | ______________^
+LL | | max
+LL | | } else if min > input {
+LL | | min
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:30:14
+ |
+LL | let x1 = if input > max {
+ | ______________^
+LL | | max
+LL | | } else if input < min {
+LL | | min
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:38:14
+ |
+LL | let x2 = if input < min {
+ | ______________^
+LL | | min
+LL | | } else if input > max {
+LL | | max
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:46:14
+ |
+LL | let x3 = if min > input {
+ | ______________^
+LL | | min
+LL | | } else if max < input {
+LL | | max
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:54:14
+ |
+LL | let x4 = input.max(min).min(max);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:56:14
+ |
+LL | let x5 = input.min(max).max(min);
+ | ^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:58:14
+ |
+LL | let x6 = match input {
+ | ______________^
+LL | | x if x > max => max,
+LL | | x if x < min => min,
+LL | | x => x,
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:64:14
+ |
+LL | let x7 = match input {
+ | ______________^
+LL | | x if x < min => min,
+LL | | x if x > max => max,
+LL | | x => x,
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:70:14
+ |
+LL | let x8 = match input {
+ | ______________^
+LL | | x if max < x => max,
+LL | | x if min > x => min,
+LL | | x => x,
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:84:15
+ |
+LL | let x10 = match input {
+ | _______________^
+LL | | x if min > x => min,
+LL | | x if max < x => max,
+LL | | x => x,
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:115:15
+ |
+LL | let x14 = if input > CONST_MAX {
+ | _______________^
+LL | | CONST_MAX
+LL | | } else if input < CONST_MIN {
+LL | | CONST_MIN
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:124:19
+ |
+LL | let x15 = if input > max {
+ | ___________________^
+LL | | max
+LL | | } else if input < min {
+LL | | min
+LL | | } else {
+LL | | input
+LL | | };
+ | |_________^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:135:19
+ |
+LL | let x16 = cmp_max(cmp_min(input, CONST_MAX), CONST_MIN);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:136:19
+ |
+LL | let x17 = cmp_min(cmp_max(input, CONST_MIN), CONST_MAX);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:137:19
+ |
+LL | let x18 = cmp_max(CONST_MIN, cmp_min(input, CONST_MAX));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:138:19
+ |
+LL | let x19 = cmp_min(CONST_MAX, cmp_max(input, CONST_MIN));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:139:19
+ |
+LL | let x20 = cmp_max(cmp_min(CONST_MAX, input), CONST_MIN);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:140:19
+ |
+LL | let x21 = cmp_min(cmp_max(CONST_MIN, input), CONST_MAX);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:141:19
+ |
+LL | let x22 = cmp_max(CONST_MIN, cmp_min(CONST_MAX, input));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:142:19
+ |
+LL | let x23 = cmp_min(CONST_MAX, cmp_max(CONST_MIN, input));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_MIN, CONST_MAX)`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:144:19
+ |
+LL | let x24 = f64::max(f64::min(input, CONST_F64_MAX), CONST_F64_MIN);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:145:19
+ |
+LL | let x25 = f64::min(f64::max(input, CONST_F64_MIN), CONST_F64_MAX);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:146:19
+ |
+LL | let x26 = f64::max(CONST_F64_MIN, f64::min(input, CONST_F64_MAX));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:147:19
+ |
+LL | let x27 = f64::min(CONST_F64_MAX, f64::max(input, CONST_F64_MIN));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:148:19
+ |
+LL | let x28 = f64::max(f64::min(CONST_F64_MAX, input), CONST_F64_MIN);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:149:19
+ |
+LL | let x29 = f64::min(f64::max(CONST_F64_MIN, input), CONST_F64_MAX);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:150:19
+ |
+LL | let x30 = f64::max(CONST_F64_MIN, f64::min(CONST_F64_MAX, input));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:151:19
+ |
+LL | let x31 = f64::min(CONST_F64_MAX, f64::max(CONST_F64_MIN, input));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `input.clamp(CONST_F64_MIN, CONST_F64_MAX)`
+ |
+ = note: clamp will panic if max < min, min.is_nan(), or max.is_nan()
+ = note: clamp returns NaN if the input is NaN
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:154:5
+ |
+LL | / if x32 < min {
+LL | | x32 = min;
+LL | | } else if x32 > max {
+LL | | x32 = max;
+LL | | }
+ | |_____^ help: replace with clamp: `x32 = x32.clamp(min, max);`
+ |
+ = note: clamp will panic if max < min
+
+error: clamp-like pattern without using clamp function
+ --> $DIR/manual_clamp.rs:324:13
+ |
+LL | let _ = if input < min {
+ | _____________^
+LL | | min
+LL | | } else if input > max {
+LL | | max
+LL | | } else {
+LL | | input
+LL | | };
+ | |_____^ help: replace with clamp: `input.clamp(min, max)`
+ |
+ = note: clamp will panic if max < min
+
+error: aborting due to 35 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_filter.fixed b/src/tools/clippy/tests/ui/manual_filter.fixed
new file mode 100644
index 000000000..3553291b8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_filter.fixed
@@ -0,0 +1,119 @@
+// run-rustfix
+
+#![warn(clippy::manual_filter)]
+#![allow(unused_variables, dead_code)]
+
+fn main() {
+ Some(0).filter(|&x| x <= 0);
+
+ Some(1).filter(|&x| x <= 0);
+
+ Some(2).filter(|&x| x <= 0);
+
+ Some(3).filter(|&x| x > 0);
+
+ let y = Some(4);
+ y.filter(|&x| x <= 0);
+
+ Some(5).filter(|&x| x > 0);
+
+ Some(6).as_ref().filter(|&x| x > &0);
+
+ let external_cond = true;
+ Some(String::new()).filter(|x| external_cond);
+
+ Some(7).filter(|&x| external_cond);
+
+ Some(8).filter(|&x| x != 0);
+
+ Some(9).filter(|&x| x > 10 && x < 100);
+
+ const fn f1() {
+ // Don't lint, `.filter` is not const
+ match Some(10) {
+ Some(x) => {
+ if x > 10 && x < 100 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+ }
+
+ #[allow(clippy::blocks_in_if_conditions)]
+ Some(11).filter(|&x| {
+ println!("foo");
+ x > 10 && x < 100
+ });
+
+ match Some(12) {
+ // Don't Lint, statement is lost by `.filter`
+ Some(x) => {
+ if x > 10 && x < 100 {
+ println!("foo");
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ match Some(13) {
+ // Don't Lint, because of `None => Some(1)`
+ Some(x) => {
+ if x > 10 && x < 100 {
+ println!("foo");
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => Some(1),
+ };
+
+ unsafe fn f(x: u32) -> bool {
+ true
+ }
+ let _ = Some(14).filter(|&x| unsafe { f(x) });
+ let _ = Some(15).filter(|&x| unsafe { f(x) });
+
+ #[allow(clippy::redundant_pattern_matching)]
+ if let Some(_) = Some(16) {
+ Some(16)
+ } else { Some(16).filter(|&x| x % 2 == 0) };
+
+ match Some((17, 17)) {
+ // Not linted for now could be
+ Some((x, y)) => {
+ if y != x {
+ Some((x, y))
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ struct NamedTuple {
+ pub x: u8,
+ pub y: (i32, u32),
+ }
+
+ match Some(NamedTuple {
+ // Not linted for now could be
+ x: 17,
+ y: (18, 19),
+ }) {
+ Some(NamedTuple { x, y }) => {
+ if y.1 != x as u32 {
+ Some(NamedTuple { x, y })
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/manual_filter.rs b/src/tools/clippy/tests/ui/manual_filter.rs
new file mode 100644
index 000000000..aa9f90f75
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_filter.rs
@@ -0,0 +1,243 @@
+// run-rustfix
+
+#![warn(clippy::manual_filter)]
+#![allow(unused_variables, dead_code)]
+
+fn main() {
+ match Some(0) {
+ None => None,
+ Some(x) => {
+ if x > 0 {
+ None
+ } else {
+ Some(x)
+ }
+ },
+ };
+
+ match Some(1) {
+ Some(x) => {
+ if x > 0 {
+ None
+ } else {
+ Some(x)
+ }
+ },
+ None => None,
+ };
+
+ match Some(2) {
+ Some(x) => {
+ if x > 0 {
+ None
+ } else {
+ Some(x)
+ }
+ },
+ _ => None,
+ };
+
+ match Some(3) {
+ Some(x) => {
+ if x > 0 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ let y = Some(4);
+ match y {
+ // Some(4)
+ None => None,
+ Some(x) => {
+ if x > 0 {
+ None
+ } else {
+ Some(x)
+ }
+ },
+ };
+
+ match Some(5) {
+ Some(x) => {
+ if x > 0 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ _ => None,
+ };
+
+ match Some(6) {
+ Some(ref x) => {
+ if x > &0 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ _ => None,
+ };
+
+ let external_cond = true;
+ match Some(String::new()) {
+ Some(x) => {
+ if external_cond {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ _ => None,
+ };
+
+ if let Some(x) = Some(7) {
+ if external_cond { Some(x) } else { None }
+ } else {
+ None
+ };
+
+ match &Some(8) {
+ &Some(x) => {
+ if x != 0 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ _ => None,
+ };
+
+ match Some(9) {
+ Some(x) => {
+ if x > 10 && x < 100 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ const fn f1() {
+ // Don't lint, `.filter` is not const
+ match Some(10) {
+ Some(x) => {
+ if x > 10 && x < 100 {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+ }
+
+ #[allow(clippy::blocks_in_if_conditions)]
+ match Some(11) {
+ // Lint, statement is preserved by `.filter`
+ Some(x) => {
+ if {
+ println!("foo");
+ x > 10 && x < 100
+ } {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ match Some(12) {
+ // Don't Lint, statement is lost by `.filter`
+ Some(x) => {
+ if x > 10 && x < 100 {
+ println!("foo");
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ match Some(13) {
+ // Don't Lint, because of `None => Some(1)`
+ Some(x) => {
+ if x > 10 && x < 100 {
+ println!("foo");
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => Some(1),
+ };
+
+ unsafe fn f(x: u32) -> bool {
+ true
+ }
+ let _ = match Some(14) {
+ Some(x) => {
+ if unsafe { f(x) } {
+ Some(x)
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+ let _ = match Some(15) {
+ Some(x) => unsafe {
+ if f(x) { Some(x) } else { None }
+ },
+ None => None,
+ };
+
+ #[allow(clippy::redundant_pattern_matching)]
+ if let Some(_) = Some(16) {
+ Some(16)
+ } else if let Some(x) = Some(16) {
+ // Lint starting from here
+ if x % 2 == 0 { Some(x) } else { None }
+ } else {
+ None
+ };
+
+ match Some((17, 17)) {
+ // Not linted for now could be
+ Some((x, y)) => {
+ if y != x {
+ Some((x, y))
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+
+ struct NamedTuple {
+ pub x: u8,
+ pub y: (i32, u32),
+ }
+
+ match Some(NamedTuple {
+ // Not linted for now could be
+ x: 17,
+ y: (18, 19),
+ }) {
+ Some(NamedTuple { x, y }) => {
+ if y.1 != x as u32 {
+ Some(NamedTuple { x, y })
+ } else {
+ None
+ }
+ },
+ None => None,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/manual_filter.stderr b/src/tools/clippy/tests/ui/manual_filter.stderr
new file mode 100644
index 000000000..53dea9229
--- /dev/null
+++ b/src/tools/clippy/tests/ui/manual_filter.stderr
@@ -0,0 +1,191 @@
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:7:5
+ |
+LL | / match Some(0) {
+LL | | None => None,
+LL | | Some(x) => {
+LL | | if x > 0 {
+... |
+LL | | },
+LL | | };
+ | |_____^ help: try this: `Some(0).filter(|&x| x <= 0)`
+ |
+ = note: `-D clippy::manual-filter` implied by `-D warnings`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:18:5
+ |
+LL | / match Some(1) {
+LL | | Some(x) => {
+LL | | if x > 0 {
+LL | | None
+... |
+LL | | None => None,
+LL | | };
+ | |_____^ help: try this: `Some(1).filter(|&x| x <= 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:29:5
+ |
+LL | / match Some(2) {
+LL | | Some(x) => {
+LL | | if x > 0 {
+LL | | None
+... |
+LL | | _ => None,
+LL | | };
+ | |_____^ help: try this: `Some(2).filter(|&x| x <= 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:40:5
+ |
+LL | / match Some(3) {
+LL | | Some(x) => {
+LL | | if x > 0 {
+LL | | Some(x)
+... |
+LL | | None => None,
+LL | | };
+ | |_____^ help: try this: `Some(3).filter(|&x| x > 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:52:5
+ |
+LL | / match y {
+LL | | // Some(4)
+LL | | None => None,
+LL | | Some(x) => {
+... |
+LL | | },
+LL | | };
+ | |_____^ help: try this: `y.filter(|&x| x <= 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:64:5
+ |
+LL | / match Some(5) {
+LL | | Some(x) => {
+LL | | if x > 0 {
+LL | | Some(x)
+... |
+LL | | _ => None,
+LL | | };
+ | |_____^ help: try this: `Some(5).filter(|&x| x > 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:75:5
+ |
+LL | / match Some(6) {
+LL | | Some(ref x) => {
+LL | | if x > &0 {
+LL | | Some(x)
+... |
+LL | | _ => None,
+LL | | };
+ | |_____^ help: try this: `Some(6).as_ref().filter(|&x| x > &0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:87:5
+ |
+LL | / match Some(String::new()) {
+LL | | Some(x) => {
+LL | | if external_cond {
+LL | | Some(x)
+... |
+LL | | _ => None,
+LL | | };
+ | |_____^ help: try this: `Some(String::new()).filter(|x| external_cond)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:98:5
+ |
+LL | / if let Some(x) = Some(7) {
+LL | | if external_cond { Some(x) } else { None }
+LL | | } else {
+LL | | None
+LL | | };
+ | |_____^ help: try this: `Some(7).filter(|&x| external_cond)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:104:5
+ |
+LL | / match &Some(8) {
+LL | | &Some(x) => {
+LL | | if x != 0 {
+LL | | Some(x)
+... |
+LL | | _ => None,
+LL | | };
+ | |_____^ help: try this: `Some(8).filter(|&x| x != 0)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:115:5
+ |
+LL | / match Some(9) {
+LL | | Some(x) => {
+LL | | if x > 10 && x < 100 {
+LL | | Some(x)
+... |
+LL | | None => None,
+LL | | };
+ | |_____^ help: try this: `Some(9).filter(|&x| x > 10 && x < 100)`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:141:5
+ |
+LL | / match Some(11) {
+LL | | // Lint, statement is preserved by `.filter`
+LL | | Some(x) => {
+LL | | if {
+... |
+LL | | None => None,
+LL | | };
+ | |_____^
+ |
+help: try this
+ |
+LL ~ Some(11).filter(|&x| {
+LL + println!("foo");
+LL + x > 10 && x < 100
+LL ~ });
+ |
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:185:13
+ |
+LL | let _ = match Some(14) {
+ | _____________^
+LL | | Some(x) => {
+LL | | if unsafe { f(x) } {
+LL | | Some(x)
+... |
+LL | | None => None,
+LL | | };
+ | |_____^ help: try this: `Some(14).filter(|&x| unsafe { f(x) })`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:195:13
+ |
+LL | let _ = match Some(15) {
+ | _____________^
+LL | | Some(x) => unsafe {
+LL | | if f(x) { Some(x) } else { None }
+LL | | },
+LL | | None => None,
+LL | | };
+ | |_____^ help: try this: `Some(15).filter(|&x| unsafe { f(x) })`
+
+error: manual implementation of `Option::filter`
+ --> $DIR/manual_filter.rs:205:12
+ |
+LL | } else if let Some(x) = Some(16) {
+ | ____________^
+LL | | // Lint starting from here
+LL | | if x % 2 == 0 { Some(x) } else { None }
+LL | | } else {
+LL | | None
+LL | | };
+ | |_____^ help: try this: `{ Some(16).filter(|&x| x % 2 == 0) }`
+
+error: aborting due to 15 previous errors
+
diff --git a/src/tools/clippy/tests/ui/manual_find.stderr b/src/tools/clippy/tests/ui/manual_find.stderr
index da0fd4aae..ea04bb066 100644
--- a/src/tools/clippy/tests/ui/manual_find.stderr
+++ b/src/tools/clippy/tests/ui/manual_find.stderr
@@ -9,8 +9,8 @@ LL | | }
LL | | None
| |________^ help: replace with an iterator: `strings.into_iter().find(|s| s == String::new())`
|
- = note: `-D clippy::manual-find` implied by `-D warnings`
= note: you may need to dereference some variables
+ = note: `-D clippy::manual-find` implied by `-D warnings`
error: manual implementation of `Iterator::find`
--> $DIR/manual_find.rs:14:5
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.fixed b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
index 36d1644c2..2bce6e624 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.fixed
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.fixed
@@ -1,7 +1,7 @@
// run-rustfix
-
-#![allow(unused, clippy::needless_return)]
#![warn(clippy::manual_find)]
+#![allow(unused)]
+#![allow(clippy::needless_return, clippy::uninlined_format_args)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/manual_find_fixable.rs b/src/tools/clippy/tests/ui/manual_find_fixable.rs
index ed277ddaa..f5c6de37a 100644
--- a/src/tools/clippy/tests/ui/manual_find_fixable.rs
+++ b/src/tools/clippy/tests/ui/manual_find_fixable.rs
@@ -1,7 +1,7 @@
// run-rustfix
-
-#![allow(unused, clippy::needless_return)]
#![warn(clippy::manual_find)]
+#![allow(unused)]
+#![allow(clippy::needless_return, clippy::uninlined_format_args)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/manual_flatten.rs b/src/tools/clippy/tests/ui/manual_flatten.rs
index d922593bc..96cd87c0e 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.rs
+++ b/src/tools/clippy/tests/ui/manual_flatten.rs
@@ -1,5 +1,5 @@
#![warn(clippy::manual_flatten)]
-#![allow(clippy::useless_vec)]
+#![allow(clippy::useless_vec, clippy::uninlined_format_args)]
fn main() {
// Test for loop over implicitly adjusted `Iterator` with `if let` expression
diff --git a/src/tools/clippy/tests/ui/manual_flatten.stderr b/src/tools/clippy/tests/ui/manual_flatten.stderr
index da053c056..180a6ff4e 100644
--- a/src/tools/clippy/tests/ui/manual_flatten.stderr
+++ b/src/tools/clippy/tests/ui/manual_flatten.stderr
@@ -11,7 +11,6 @@ LL | | }
LL | | }
| |_____^
|
- = note: `-D clippy::manual-flatten` implied by `-D warnings`
help: ...and remove the `if let` statement in the for loop
--> $DIR/manual_flatten.rs:8:9
|
@@ -19,6 +18,7 @@ LL | / if let Some(y) = n {
LL | | println!("{}", y);
LL | | }
| |_________^
+ = note: `-D clippy::manual-flatten` implied by `-D warnings`
error: unnecessary `if let` since only the `Ok` variant of the iterator element is used
--> $DIR/manual_flatten.rs:15:5
diff --git a/src/tools/clippy/tests/ui/manual_map_option.fixed b/src/tools/clippy/tests/ui/manual_map_option.fixed
index a59da4ae1..e12ea7ec1 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.fixed
+++ b/src/tools/clippy/tests/ui/manual_map_option.fixed
@@ -7,7 +7,7 @@
clippy::unit_arg,
clippy::match_ref_pats,
clippy::redundant_pattern_matching,
- clippy::for_loops_over_fallibles,
+ for_loops_over_fallibles,
dead_code
)]
diff --git a/src/tools/clippy/tests/ui/manual_map_option.rs b/src/tools/clippy/tests/ui/manual_map_option.rs
index 0bdbefa51..325a6db06 100644
--- a/src/tools/clippy/tests/ui/manual_map_option.rs
+++ b/src/tools/clippy/tests/ui/manual_map_option.rs
@@ -7,7 +7,7 @@
clippy::unit_arg,
clippy::match_ref_pats,
clippy::redundant_pattern_matching,
- clippy::for_loops_over_fallibles,
+ for_loops_over_fallibles,
dead_code
)]
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
index 144fe86df..087f766be 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_enum.stderr
@@ -13,12 +13,12 @@ LL | | _C,
LL | | }
| |_^
|
- = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
help: remove this variant
--> $DIR/manual_non_exhaustive_enum.rs:9:5
|
LL | _C,
| ^^
+ = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
error: this seems like a manual implementation of the non-exhaustive pattern
--> $DIR/manual_non_exhaustive_enum.rs:14:1
diff --git a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
index e0766c17b..d0bed8e11 100644
--- a/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
+++ b/src/tools/clippy/tests/ui/manual_non_exhaustive_struct.stderr
@@ -12,12 +12,12 @@ LL | | _c: (),
LL | | }
| |_____^
|
- = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
help: remove this field
--> $DIR/manual_non_exhaustive_struct.rs:8:9
|
LL | _c: (),
| ^^^^^^
+ = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings`
error: this seems like a manual implementation of the non-exhaustive pattern
--> $DIR/manual_non_exhaustive_struct.rs:13:5
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
index 5601c96c1..b942fbfe9 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.fixed
@@ -1,6 +1,7 @@
// run-rustfix
// aux-build:macro_rules.rs
+#![feature(custom_inner_attributes)]
#![warn(clippy::manual_rem_euclid)]
#[macro_use]
@@ -53,3 +54,32 @@ pub fn rem_euclid_4(num: i32) -> i32 {
pub const fn const_rem_euclid_4(num: i32) -> i32 {
num.rem_euclid(4)
}
+
+pub fn msrv_1_37() {
+ #![clippy::msrv = "1.37"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
+
+pub fn msrv_1_38() {
+ #![clippy::msrv = "1.38"]
+
+ let x: i32 = 10;
+ let _: i32 = x.rem_euclid(4);
+}
+
+// For const fns:
+pub const fn msrv_1_51() {
+ #![clippy::msrv = "1.51"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
+
+pub const fn msrv_1_52() {
+ #![clippy::msrv = "1.52"]
+
+ let x: i32 = 10;
+ let _: i32 = x.rem_euclid(4);
+}
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.rs b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
index 52135be26..7462d5321 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.rs
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.rs
@@ -1,6 +1,7 @@
// run-rustfix
// aux-build:macro_rules.rs
+#![feature(custom_inner_attributes)]
#![warn(clippy::manual_rem_euclid)]
#[macro_use]
@@ -53,3 +54,32 @@ pub fn rem_euclid_4(num: i32) -> i32 {
pub const fn const_rem_euclid_4(num: i32) -> i32 {
((num % 4) + 4) % 4
}
+
+pub fn msrv_1_37() {
+ #![clippy::msrv = "1.37"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
+
+pub fn msrv_1_38() {
+ #![clippy::msrv = "1.38"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
+
+// For const fns:
+pub const fn msrv_1_51() {
+ #![clippy::msrv = "1.51"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
+
+pub const fn msrv_1_52() {
+ #![clippy::msrv = "1.52"]
+
+ let x: i32 = 10;
+ let _: i32 = ((x % 4) + 4) % 4;
+}
diff --git a/src/tools/clippy/tests/ui/manual_rem_euclid.stderr b/src/tools/clippy/tests/ui/manual_rem_euclid.stderr
index a237fd021..d51bac03b 100644
--- a/src/tools/clippy/tests/ui/manual_rem_euclid.stderr
+++ b/src/tools/clippy/tests/ui/manual_rem_euclid.stderr
@@ -1,5 +1,5 @@
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:19:18
+ --> $DIR/manual_rem_euclid.rs:20:18
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@@ -7,31 +7,31 @@ LL | let _: i32 = ((value % 4) + 4) % 4;
= note: `-D clippy::manual-rem-euclid` implied by `-D warnings`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:20:18
+ --> $DIR/manual_rem_euclid.rs:21:18
|
LL | let _: i32 = (4 + (value % 4)) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:21:18
+ --> $DIR/manual_rem_euclid.rs:22:18
|
LL | let _: i32 = (value % 4 + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:22:18
+ --> $DIR/manual_rem_euclid.rs:23:18
|
LL | let _: i32 = (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:23:22
+ --> $DIR/manual_rem_euclid.rs:24:22
|
LL | let _: i32 = 1 + (4 + value % 4) % 4;
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:12:22
+ --> $DIR/manual_rem_euclid.rs:13:22
|
LL | let _: i32 = ((value % 4) + 4) % 4;
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `value.rem_euclid(4)`
@@ -42,16 +42,28 @@ LL | internal_rem_euclid!();
= note: this error originates in the macro `internal_rem_euclid` (in Nightly builds, run with -Z macro-backtrace for more info)
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:49:5
+ --> $DIR/manual_rem_euclid.rs:50:5
|
LL | ((num % 4) + 4) % 4
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
error: manual `rem_euclid` implementation
- --> $DIR/manual_rem_euclid.rs:54:5
+ --> $DIR/manual_rem_euclid.rs:55:5
|
LL | ((num % 4) + 4) % 4
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `num.rem_euclid(4)`
-error: aborting due to 8 previous errors
+error: manual `rem_euclid` implementation
+ --> $DIR/manual_rem_euclid.rs:69:18
+ |
+LL | let _: i32 = ((x % 4) + 4) % 4;
+ | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)`
+
+error: manual `rem_euclid` implementation
+ --> $DIR/manual_rem_euclid.rs:84:18
+ |
+LL | let _: i32 = ((x % 4) + 4) % 4;
+ | ^^^^^^^^^^^^^^^^^ help: consider using: `x.rem_euclid(4)`
+
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/manual_strip.rs b/src/tools/clippy/tests/ui/manual_strip.rs
index cbb84eb5c..85009d785 100644
--- a/src/tools/clippy/tests/ui/manual_strip.rs
+++ b/src/tools/clippy/tests/ui/manual_strip.rs
@@ -1,3 +1,4 @@
+#![feature(custom_inner_attributes)]
#![warn(clippy::manual_strip)]
fn main() {
@@ -64,3 +65,21 @@ fn main() {
s4[2..].to_string();
}
}
+
+fn msrv_1_44() {
+ #![clippy::msrv = "1.44"]
+
+ let s = "abc";
+ if s.starts_with('a') {
+ s[1..].to_string();
+ }
+}
+
+fn msrv_1_45() {
+ #![clippy::msrv = "1.45"]
+
+ let s = "abc";
+ if s.starts_with('a') {
+ s[1..].to_string();
+ }
+}
diff --git a/src/tools/clippy/tests/ui/manual_strip.stderr b/src/tools/clippy/tests/ui/manual_strip.stderr
index 896edf2ae..ad2a362f3 100644
--- a/src/tools/clippy/tests/ui/manual_strip.stderr
+++ b/src/tools/clippy/tests/ui/manual_strip.stderr
@@ -1,15 +1,15 @@
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:7:24
+ --> $DIR/manual_strip.rs:8:24
|
LL | str::to_string(&s["ab".len()..]);
| ^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::manual-strip` implied by `-D warnings`
note: the prefix was tested here
- --> $DIR/manual_strip.rs:6:5
+ --> $DIR/manual_strip.rs:7:5
|
LL | if s.starts_with("ab") {
| ^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::manual-strip` implied by `-D warnings`
help: try using the `strip_prefix` method
|
LL ~ if let Some(<stripped>) = s.strip_prefix("ab") {
@@ -21,13 +21,13 @@ LL ~ <stripped>.to_string();
|
error: stripping a suffix manually
- --> $DIR/manual_strip.rs:15:24
+ --> $DIR/manual_strip.rs:16:24
|
LL | str::to_string(&s[..s.len() - "bc".len()]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the suffix was tested here
- --> $DIR/manual_strip.rs:14:5
+ --> $DIR/manual_strip.rs:15:5
|
LL | if s.ends_with("bc") {
| ^^^^^^^^^^^^^^^^^^^^^
@@ -42,13 +42,13 @@ LL ~ <stripped>.to_string();
|
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:24:24
+ --> $DIR/manual_strip.rs:25:24
|
LL | str::to_string(&s[1..]);
| ^^^^^^^
|
note: the prefix was tested here
- --> $DIR/manual_strip.rs:23:5
+ --> $DIR/manual_strip.rs:24:5
|
LL | if s.starts_with('a') {
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -60,13 +60,13 @@ LL ~ <stripped>.to_string();
|
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:31:24
+ --> $DIR/manual_strip.rs:32:24
|
LL | str::to_string(&s[prefix.len()..]);
| ^^^^^^^^^^^^^^^^^^
|
note: the prefix was tested here
- --> $DIR/manual_strip.rs:30:5
+ --> $DIR/manual_strip.rs:31:5
|
LL | if s.starts_with(prefix) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -77,13 +77,13 @@ LL ~ str::to_string(<stripped>);
|
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:37:24
+ --> $DIR/manual_strip.rs:38:24
|
LL | str::to_string(&s[PREFIX.len()..]);
| ^^^^^^^^^^^^^^^^^^
|
note: the prefix was tested here
- --> $DIR/manual_strip.rs:36:5
+ --> $DIR/manual_strip.rs:37:5
|
LL | if s.starts_with(PREFIX) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -95,13 +95,13 @@ LL ~ str::to_string(<stripped>);
|
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:44:24
+ --> $DIR/manual_strip.rs:45:24
|
LL | str::to_string(&TARGET[prefix.len()..]);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
note: the prefix was tested here
- --> $DIR/manual_strip.rs:43:5
+ --> $DIR/manual_strip.rs:44:5
|
LL | if TARGET.starts_with(prefix) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -112,13 +112,13 @@ LL ~ str::to_string(<stripped>);
|
error: stripping a prefix manually
- --> $DIR/manual_strip.rs:50:9
+ --> $DIR/manual_strip.rs:51:9
|
LL | s1[2..].to_uppercase();
| ^^^^^^^
|
note: the prefix was tested here
- --> $DIR/manual_strip.rs:49:5
+ --> $DIR/manual_strip.rs:50:5
|
LL | if s1.starts_with("ab") {
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -128,5 +128,22 @@ LL ~ if let Some(<stripped>) = s1.strip_prefix("ab") {
LL ~ <stripped>.to_uppercase();
|
-error: aborting due to 7 previous errors
+error: stripping a prefix manually
+ --> $DIR/manual_strip.rs:83:9
+ |
+LL | s[1..].to_string();
+ | ^^^^^^
+ |
+note: the prefix was tested here
+ --> $DIR/manual_strip.rs:82:5
+ |
+LL | if s.starts_with('a') {
+ | ^^^^^^^^^^^^^^^^^^^^^^
+help: try using the `strip_prefix` method
+ |
+LL ~ if let Some(<stripped>) = s.strip_prefix('a') {
+LL ~ <stripped>.to_string();
+ |
+
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui/map_err.stderr b/src/tools/clippy/tests/ui/map_err.stderr
index c03584052..d44403a84 100644
--- a/src/tools/clippy/tests/ui/map_err.stderr
+++ b/src/tools/clippy/tests/ui/map_err.stderr
@@ -4,8 +4,8 @@ error: `map_err(|_|...` wildcard pattern discards the original error
LL | println!("{:?}", x.map_err(|_| Errors::Ignored));
| ^^^
|
- = note: `-D clippy::map-err-ignore` implied by `-D warnings`
= help: consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
+ = note: `-D clippy::map-err-ignore` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.rs b/src/tools/clippy/tests/ui/map_unwrap_or.rs
index 87e16f5d0..396b22a9a 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or.rs
+++ b/src/tools/clippy/tests/ui/map_unwrap_or.rs
@@ -1,6 +1,8 @@
// aux-build:option_helpers.rs
+#![feature(custom_inner_attributes)]
#![warn(clippy::map_unwrap_or)]
+#![allow(clippy::uninlined_format_args, clippy::unnecessary_lazy_evaluations)]
#[macro_use]
extern crate option_helpers;
@@ -79,3 +81,19 @@ fn main() {
option_methods();
result_methods();
}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ let res: Result<i32, ()> = Ok(1);
+
+ let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
+}
+
+fn msrv_1_41() {
+ #![clippy::msrv = "1.41"]
+
+ let res: Result<i32, ()> = Ok(1);
+
+ let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
+}
diff --git a/src/tools/clippy/tests/ui/map_unwrap_or.stderr b/src/tools/clippy/tests/ui/map_unwrap_or.stderr
index abc9c1ece..d17d24a40 100644
--- a/src/tools/clippy/tests/ui/map_unwrap_or.stderr
+++ b/src/tools/clippy/tests/ui/map_unwrap_or.stderr
@@ -1,5 +1,5 @@
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:16:13
+ --> $DIR/map_unwrap_or.rs:18:13
|
LL | let _ = opt.map(|x| x + 1)
| _____________^
@@ -15,7 +15,7 @@ LL + let _ = opt.map_or(0, |x| x + 1);
|
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:20:13
+ --> $DIR/map_unwrap_or.rs:22:13
|
LL | let _ = opt.map(|x| {
| _____________^
@@ -33,7 +33,7 @@ LL ~ );
|
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:24:13
+ --> $DIR/map_unwrap_or.rs:26:13
|
LL | let _ = opt.map(|x| x + 1)
| _____________^
@@ -50,7 +50,7 @@ LL ~ }, |x| x + 1);
|
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
- --> $DIR/map_unwrap_or.rs:29:13
+ --> $DIR/map_unwrap_or.rs:31:13
|
LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL + let _ = opt.and_then(|x| Some(x + 1));
|
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
- --> $DIR/map_unwrap_or.rs:31:13
+ --> $DIR/map_unwrap_or.rs:33:13
|
LL | let _ = opt.map(|x| {
| _____________^
@@ -80,7 +80,7 @@ LL ~ );
|
error: called `map(<f>).unwrap_or(None)` on an `Option` value. This can be done more directly by calling `and_then(<f>)` instead
- --> $DIR/map_unwrap_or.rs:35:13
+ --> $DIR/map_unwrap_or.rs:37:13
|
LL | let _ = opt
| _____________^
@@ -95,7 +95,7 @@ LL + .and_then(|x| Some(x + 1));
|
error: called `map(<f>).unwrap_or(<a>)` on an `Option` value. This can be done more directly by calling `map_or(<a>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:46:13
+ --> $DIR/map_unwrap_or.rs:48:13
|
LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -107,7 +107,7 @@ LL + let _ = Some("prefix").map_or(id, |p| format!("{}.", p));
|
error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:50:13
+ --> $DIR/map_unwrap_or.rs:52:13
|
LL | let _ = opt.map(|x| {
| _____________^
@@ -117,7 +117,7 @@ LL | | ).unwrap_or_else(|| 0);
| |__________________________^
error: called `map(<f>).unwrap_or_else(<g>)` on an `Option` value. This can be done more directly by calling `map_or_else(<g>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:54:13
+ --> $DIR/map_unwrap_or.rs:56:13
|
LL | let _ = opt.map(|x| x + 1)
| _____________^
@@ -127,7 +127,7 @@ LL | | );
| |_________^
error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:66:13
+ --> $DIR/map_unwrap_or.rs:68:13
|
LL | let _ = res.map(|x| {
| _____________^
@@ -137,7 +137,7 @@ LL | | ).unwrap_or_else(|_e| 0);
| |____________________________^
error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
- --> $DIR/map_unwrap_or.rs:70:13
+ --> $DIR/map_unwrap_or.rs:72:13
|
LL | let _ = res.map(|x| x + 1)
| _____________^
@@ -146,5 +146,11 @@ LL | | 0
LL | | });
| |__________^
-error: aborting due to 11 previous errors
+error: called `map(<f>).unwrap_or_else(<g>)` on a `Result` value. This can be done more directly by calling `.map_or_else(<g>, <f>)` instead
+ --> $DIR/map_unwrap_or.rs:98:13
+ |
+LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)`
+
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
index 95ca571d0..249800769 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.fixed
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![warn(clippy::match_like_matches_macro)]
#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
@@ -193,3 +194,18 @@ fn main() {
_ => false,
};
}
+
+fn msrv_1_41() {
+ #![clippy::msrv = "1.41"]
+
+ let _y = match Some(5) {
+ Some(0) => true,
+ _ => false,
+ };
+}
+
+fn msrv_1_42() {
+ #![clippy::msrv = "1.42"]
+
+ let _y = matches!(Some(5), Some(0));
+}
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
index 3b9c8cada..b4e48499b 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.rs
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![warn(clippy::match_like_matches_macro)]
#![allow(unreachable_patterns, dead_code, clippy::equatable_if_let)]
@@ -234,3 +235,21 @@ fn main() {
_ => false,
};
}
+
+fn msrv_1_41() {
+ #![clippy::msrv = "1.41"]
+
+ let _y = match Some(5) {
+ Some(0) => true,
+ _ => false,
+ };
+}
+
+fn msrv_1_42() {
+ #![clippy::msrv = "1.42"]
+
+ let _y = match Some(5) {
+ Some(0) => true,
+ _ => false,
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
index e94555e27..f1d1c23ae 100644
--- a/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
+++ b/src/tools/clippy/tests/ui/match_expr_like_matches_macro.stderr
@@ -1,5 +1,5 @@
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:10:14
+ --> $DIR/match_expr_like_matches_macro.rs:11:14
|
LL | let _y = match x {
| ______________^
@@ -11,7 +11,7 @@ LL | | };
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:16:14
+ --> $DIR/match_expr_like_matches_macro.rs:17:14
|
LL | let _w = match x {
| ______________^
@@ -21,7 +21,7 @@ LL | | };
| |_____^ help: try this: `matches!(x, Some(_))`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/match_expr_like_matches_macro.rs:22:14
+ --> $DIR/match_expr_like_matches_macro.rs:23:14
|
LL | let _z = match x {
| ______________^
@@ -33,7 +33,7 @@ LL | | };
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:28:15
+ --> $DIR/match_expr_like_matches_macro.rs:29:15
|
LL | let _zz = match x {
| _______________^
@@ -43,13 +43,13 @@ LL | | };
| |_____^ help: try this: `!matches!(x, Some(r) if r == 0)`
error: if let .. else expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:34:16
+ --> $DIR/match_expr_like_matches_macro.rs:35:16
|
LL | let _zzz = if let Some(5) = x { true } else { false };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `matches!(x, Some(5))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:58:20
+ --> $DIR/match_expr_like_matches_macro.rs:59:20
|
LL | let _ans = match x {
| ____________________^
@@ -60,7 +60,7 @@ LL | | };
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:68:20
+ --> $DIR/match_expr_like_matches_macro.rs:69:20
|
LL | let _ans = match x {
| ____________________^
@@ -73,7 +73,7 @@ LL | | };
| |_________^ help: try this: `matches!(x, E::A(_) | E::B(_))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:78:20
+ --> $DIR/match_expr_like_matches_macro.rs:79:20
|
LL | let _ans = match x {
| ____________________^
@@ -84,7 +84,7 @@ LL | | };
| |_________^ help: try this: `!matches!(x, E::B(_) | E::C)`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:138:18
+ --> $DIR/match_expr_like_matches_macro.rs:139:18
|
LL | let _z = match &z {
| __________________^
@@ -94,7 +94,7 @@ LL | | };
| |_________^ help: try this: `matches!(z, Some(3))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:147:18
+ --> $DIR/match_expr_like_matches_macro.rs:148:18
|
LL | let _z = match &z {
| __________________^
@@ -104,7 +104,7 @@ LL | | };
| |_________^ help: try this: `matches!(&z, Some(3))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:164:21
+ --> $DIR/match_expr_like_matches_macro.rs:165:21
|
LL | let _ = match &z {
| _____________________^
@@ -114,7 +114,7 @@ LL | | };
| |_____________^ help: try this: `matches!(&z, AnEnum::X)`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:178:20
+ --> $DIR/match_expr_like_matches_macro.rs:179:20
|
LL | let _res = match &val {
| ____________________^
@@ -124,7 +124,7 @@ LL | | };
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
error: match expression looks like `matches!` macro
- --> $DIR/match_expr_like_matches_macro.rs:190:20
+ --> $DIR/match_expr_like_matches_macro.rs:191:20
|
LL | let _res = match &val {
| ____________________^
@@ -133,5 +133,15 @@ LL | | _ => false,
LL | | };
| |_________^ help: try this: `matches!(&val, &Some(ref _a))`
-error: aborting due to 13 previous errors
+error: match expression looks like `matches!` macro
+ --> $DIR/match_expr_like_matches_macro.rs:251:14
+ |
+LL | let _y = match Some(5) {
+ | ______________^
+LL | | Some(0) => true,
+LL | | _ => false,
+LL | | };
+ | |_____^ help: try this: `matches!(Some(5), Some(0))`
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.rs b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
index 2f85e6357..b4097fa96 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.rs
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.rs
@@ -1,5 +1,4 @@
#![feature(exclusive_range_pattern)]
-#![feature(half_open_range_patterns)]
#![warn(clippy::match_overlapping_arm)]
#![allow(clippy::redundant_pattern_matching)]
#![allow(clippy::if_same_then_else, clippy::equatable_if_let)]
diff --git a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
index b81bb1ecf..b98d4799e 100644
--- a/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
+++ b/src/tools/clippy/tests/ui/match_overlapping_arm.stderr
@@ -1,96 +1,96 @@
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:13:9
+ --> $DIR/match_overlapping_arm.rs:12:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
|
- = note: `-D clippy::match-overlapping-arm` implied by `-D warnings`
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:14:9
+ --> $DIR/match_overlapping_arm.rs:13:9
|
LL | 0..=11 => println!("0..=11"),
| ^^^^^^
+ = note: `-D clippy::match-overlapping-arm` implied by `-D warnings`
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:19:9
+ --> $DIR/match_overlapping_arm.rs:18:9
|
LL | 0..=5 => println!("0..=5"),
| ^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:21:9
+ --> $DIR/match_overlapping_arm.rs:20:9
|
LL | FOO..=11 => println!("FOO..=11"),
| ^^^^^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:56:9
+ --> $DIR/match_overlapping_arm.rs:55:9
|
LL | 0..11 => println!("0..11"),
| ^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:57:9
+ --> $DIR/match_overlapping_arm.rs:56:9
|
LL | 0..=11 => println!("0..=11"),
| ^^^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:81:9
+ --> $DIR/match_overlapping_arm.rs:80:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:80:9
+ --> $DIR/match_overlapping_arm.rs:79:9
|
LL | 5..14 => println!("5..14"),
| ^^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:86:9
+ --> $DIR/match_overlapping_arm.rs:85:9
|
LL | 0..7 => println!("0..7"),
| ^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:87:9
+ --> $DIR/match_overlapping_arm.rs:86:9
|
LL | 0..=10 => println!("0..=10"),
| ^^^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:98:9
+ --> $DIR/match_overlapping_arm.rs:97:9
|
LL | ..=23 => println!("..=23"),
| ^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:99:9
+ --> $DIR/match_overlapping_arm.rs:98:9
|
LL | ..26 => println!("..26"),
| ^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:107:9
+ --> $DIR/match_overlapping_arm.rs:106:9
|
LL | 21..=30 => (),
| ^^^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:108:9
+ --> $DIR/match_overlapping_arm.rs:107:9
|
LL | 21..=40 => (),
| ^^^^^^^
error: some ranges overlap
- --> $DIR/match_overlapping_arm.rs:121:9
+ --> $DIR/match_overlapping_arm.rs:120:9
|
LL | 0..=0x0000_0000_0000_00ff => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: overlaps with this
- --> $DIR/match_overlapping_arm.rs:122:9
+ --> $DIR/match_overlapping_arm.rs:121:9
|
LL | 0..=0x0000_0000_0000_ffff => (),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.fixed b/src/tools/clippy/tests/ui/match_ref_pats.fixed
index 1b6c2d924..cf37fc6dc 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.fixed
+++ b/src/tools/clippy/tests/ui/match_ref_pats.fixed
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::match_ref_pats)]
-#![allow(dead_code, unused_variables, clippy::equatable_if_let, clippy::enum_variant_names)]
+#![allow(dead_code, unused_variables)]
+#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)]
fn ref_pats() {
{
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.rs b/src/tools/clippy/tests/ui/match_ref_pats.rs
index 68dfac4e2..3220b97d1 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.rs
+++ b/src/tools/clippy/tests/ui/match_ref_pats.rs
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::match_ref_pats)]
-#![allow(dead_code, unused_variables, clippy::equatable_if_let, clippy::enum_variant_names)]
+#![allow(dead_code, unused_variables)]
+#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)]
fn ref_pats() {
{
diff --git a/src/tools/clippy/tests/ui/match_ref_pats.stderr b/src/tools/clippy/tests/ui/match_ref_pats.stderr
index 353f7399d..7d9646c84 100644
--- a/src/tools/clippy/tests/ui/match_ref_pats.stderr
+++ b/src/tools/clippy/tests/ui/match_ref_pats.stderr
@@ -1,5 +1,5 @@
error: you don't need to add `&` to all patterns
- --> $DIR/match_ref_pats.rs:8:9
+ --> $DIR/match_ref_pats.rs:9:9
|
LL | / match v {
LL | | &Some(v) => println!("{:?}", v),
@@ -16,7 +16,7 @@ LL ~ None => println!("none"),
|
error: you don't need to add `&` to both the expression and the patterns
- --> $DIR/match_ref_pats.rs:25:5
+ --> $DIR/match_ref_pats.rs:26:5
|
LL | / match &w {
LL | | &Some(v) => println!("{:?}", v),
@@ -32,7 +32,7 @@ LL ~ None => println!("none"),
|
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/match_ref_pats.rs:37:12
+ --> $DIR/match_ref_pats.rs:38:12
|
LL | if let &None = a {
| -------^^^^^---- help: try this: `if a.is_none()`
@@ -40,13 +40,13 @@ LL | if let &None = a {
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_none()`
- --> $DIR/match_ref_pats.rs:42:12
+ --> $DIR/match_ref_pats.rs:43:12
|
LL | if let &None = &b {
| -------^^^^^----- help: try this: `if b.is_none()`
error: you don't need to add `&` to all patterns
- --> $DIR/match_ref_pats.rs:102:9
+ --> $DIR/match_ref_pats.rs:103:9
|
LL | / match foobar_variant!(0) {
LL | | &FooBar::Foo => println!("Foo"),
diff --git a/src/tools/clippy/tests/ui/match_result_ok.fixed b/src/tools/clippy/tests/ui/match_result_ok.fixed
index d4760a975..8b91b9854 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.fixed
+++ b/src/tools/clippy/tests/ui/match_result_ok.fixed
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_result_ok)]
-#![allow(clippy::boxed_local)]
#![allow(dead_code)]
+#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
// Checking `if` cases
diff --git a/src/tools/clippy/tests/ui/match_result_ok.rs b/src/tools/clippy/tests/ui/match_result_ok.rs
index 0b818723d..bc2c4b50e 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.rs
+++ b/src/tools/clippy/tests/ui/match_result_ok.rs
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_result_ok)]
-#![allow(clippy::boxed_local)]
#![allow(dead_code)]
+#![allow(clippy::boxed_local, clippy::uninlined_format_args)]
// Checking `if` cases
diff --git a/src/tools/clippy/tests/ui/match_result_ok.stderr b/src/tools/clippy/tests/ui/match_result_ok.stderr
index cc3bc8c76..98a95705c 100644
--- a/src/tools/clippy/tests/ui/match_result_ok.stderr
+++ b/src/tools/clippy/tests/ui/match_result_ok.stderr
@@ -1,5 +1,5 @@
error: matching on `Some` with `ok()` is redundant
- --> $DIR/match_result_ok.rs:10:5
+ --> $DIR/match_result_ok.rs:9:5
|
LL | if let Some(y) = x.parse().ok() { y } else { 0 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL | if let Ok(y) = x.parse() { y } else { 0 }
| ~~~~~~~~~~~~~~~~~~~~~~~~
error: matching on `Some` with `ok()` is redundant
- --> $DIR/match_result_ok.rs:20:9
+ --> $DIR/match_result_ok.rs:19:9
|
LL | if let Some(y) = x . parse() . ok () {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | if let Ok(y) = x . parse() {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: matching on `Some` with `ok()` is redundant
- --> $DIR/match_result_ok.rs:46:5
+ --> $DIR/match_result_ok.rs:45:5
|
LL | while let Some(a) = wat.next().ok() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_same_arms.stderr b/src/tools/clippy/tests/ui/match_same_arms.stderr
index b6d04263b..db85b5964 100644
--- a/src/tools/clippy/tests/ui/match_same_arms.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms.stderr
@@ -4,13 +4,13 @@ error: this match arm has an identical body to the `_` wildcard arm
LL | Abc::A => 0,
| ^^^^^^^^^^^ help: try removing the arm
|
- = note: `-D clippy::match-same-arms` implied by `-D warnings`
= help: or try changing either arm body
note: `_` wildcard arm here
--> $DIR/match_same_arms.rs:13:9
|
LL | _ => 0, //~ ERROR match arms have same body
| ^^^^^^
+ = note: `-D clippy::match-same-arms` implied by `-D warnings`
error: this match arm has an identical body to another arm
--> $DIR/match_same_arms.rs:17:9
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.rs b/src/tools/clippy/tests/ui/match_same_arms2.rs
index 61793e80c..82b2c433d 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms2.rs
@@ -1,5 +1,9 @@
#![warn(clippy::match_same_arms)]
-#![allow(clippy::disallowed_names, clippy::diverging_sub_expression)]
+#![allow(
+ clippy::disallowed_names,
+ clippy::diverging_sub_expression,
+ clippy::uninlined_format_args
+)]
fn bar<T>(_: T) {}
fn foo() -> bool {
diff --git a/src/tools/clippy/tests/ui/match_same_arms2.stderr b/src/tools/clippy/tests/ui/match_same_arms2.stderr
index 14a672ba2..06cd43000 100644
--- a/src/tools/clippy/tests/ui/match_same_arms2.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms2.stderr
@@ -1,5 +1,5 @@
error: this match arm has an identical body to the `_` wildcard arm
- --> $DIR/match_same_arms2.rs:11:9
+ --> $DIR/match_same_arms2.rs:15:9
|
LL | / 42 => {
LL | | foo();
@@ -10,10 +10,9 @@ LL | | a
LL | | },
| |_________^ help: try removing the arm
|
- = note: `-D clippy::match-same-arms` implied by `-D warnings`
= help: or try changing either arm body
note: `_` wildcard arm here
- --> $DIR/match_same_arms2.rs:20:9
+ --> $DIR/match_same_arms2.rs:24:9
|
LL | / _ => {
LL | | //~ ERROR match arms have same body
@@ -23,9 +22,10 @@ LL | | let mut a = 42 + [23].len() as i32;
LL | | a
LL | | },
| |_________^
+ = note: `-D clippy::match-same-arms` implied by `-D warnings`
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:34:9
+ --> $DIR/match_same_arms2.rs:38:9
|
LL | 51 => foo(), //~ ERROR match arms have same body
| --^^^^^^^^^
@@ -34,13 +34,13 @@ LL | 51 => foo(), //~ ERROR match arms have same body
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:33:9
+ --> $DIR/match_same_arms2.rs:37:9
|
LL | 42 => foo(),
| ^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:40:9
+ --> $DIR/match_same_arms2.rs:44:9
|
LL | None => 24, //~ ERROR match arms have same body
| ----^^^^^^
@@ -49,13 +49,13 @@ LL | None => 24, //~ ERROR match arms have same body
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:39:9
+ --> $DIR/match_same_arms2.rs:43:9
|
LL | Some(_) => 24,
| ^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:62:9
+ --> $DIR/match_same_arms2.rs:66:9
|
LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body
| ---------------^^^^^^^^^^
@@ -64,13 +64,13 @@ LL | (None, Some(a)) => bar(a), //~ ERROR match arms have same body
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:61:9
+ --> $DIR/match_same_arms2.rs:65:9
|
LL | (Some(a), None) => bar(a),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:67:9
+ --> $DIR/match_same_arms2.rs:71:9
|
LL | (Some(a), ..) => bar(a),
| -------------^^^^^^^^^^
@@ -79,13 +79,13 @@ LL | (Some(a), ..) => bar(a),
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:68:9
+ --> $DIR/match_same_arms2.rs:72:9
|
LL | (.., Some(a)) => bar(a), //~ ERROR match arms have same body
| ^^^^^^^^^^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:101:9
+ --> $DIR/match_same_arms2.rs:105:9
|
LL | (Ok(x), Some(_)) => println!("ok {}", x),
| ----------------^^^^^^^^^^^^^^^^^^^^^^^^
@@ -94,13 +94,13 @@ LL | (Ok(x), Some(_)) => println!("ok {}", x),
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:102:9
+ --> $DIR/match_same_arms2.rs:106:9
|
LL | (Ok(_), Some(x)) => println!("ok {}", x),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:117:9
+ --> $DIR/match_same_arms2.rs:121:9
|
LL | Ok(_) => println!("ok"),
| -----^^^^^^^^^^^^^^^^^^
@@ -109,13 +109,13 @@ LL | Ok(_) => println!("ok"),
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:116:9
+ --> $DIR/match_same_arms2.rs:120:9
|
LL | Ok(3) => println!("ok"),
| ^^^^^^^^^^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:144:9
+ --> $DIR/match_same_arms2.rs:148:9
|
LL | 1 => {
| ^ help: try merging the arm patterns: `1 | 0`
@@ -127,7 +127,7 @@ LL | | },
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:141:9
+ --> $DIR/match_same_arms2.rs:145:9
|
LL | / 0 => {
LL | | empty!(0);
@@ -135,7 +135,7 @@ LL | | },
| |_________^
error: match expression looks like `matches!` macro
- --> $DIR/match_same_arms2.rs:162:16
+ --> $DIR/match_same_arms2.rs:166:16
|
LL | let _ans = match x {
| ________________^
@@ -148,7 +148,7 @@ LL | | };
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:194:9
+ --> $DIR/match_same_arms2.rs:198:9
|
LL | Foo::X(0) => 1,
| ---------^^^^^
@@ -157,13 +157,13 @@ LL | Foo::X(0) => 1,
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:196:9
+ --> $DIR/match_same_arms2.rs:200:9
|
LL | Foo::Z(_) => 1,
| ^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:204:9
+ --> $DIR/match_same_arms2.rs:208:9
|
LL | Foo::Z(_) => 1,
| ---------^^^^^
@@ -172,13 +172,13 @@ LL | Foo::Z(_) => 1,
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:202:9
+ --> $DIR/match_same_arms2.rs:206:9
|
LL | Foo::X(0) => 1,
| ^^^^^^^^^^^^^^
error: this match arm has an identical body to another arm
- --> $DIR/match_same_arms2.rs:227:9
+ --> $DIR/match_same_arms2.rs:231:9
|
LL | Some(Bar { y: 0, x: 5, .. }) => 1,
| ----------------------------^^^^^
@@ -187,7 +187,7 @@ LL | Some(Bar { y: 0, x: 5, .. }) => 1,
|
= help: or try changing either arm body
note: other arm here
- --> $DIR/match_same_arms2.rs:224:9
+ --> $DIR/match_same_arms2.rs:228:9
|
LL | Some(Bar { x: 0, y: 5, .. }) => 1,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/match_single_binding.fixed b/src/tools/clippy/tests/ui/match_single_binding.fixed
index de46e6cff..a6e315e47 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding.fixed
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_single_binding)]
-#![allow(unused_variables, clippy::toplevel_ref_arg)]
+#![allow(unused_variables)]
+#![allow(clippy::toplevel_ref_arg, clippy::uninlined_format_args)]
struct Point {
x: i32,
@@ -124,3 +124,12 @@ fn issue_8723() {
let _ = val;
}
+
+#[allow(dead_code)]
+fn issue_9575() {
+ fn side_effects() {}
+ let _ = || {
+ side_effects();
+ println!("Needs curlies");
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.rs b/src/tools/clippy/tests/ui/match_single_binding.rs
index eea64fcb2..cecbd703e 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding.rs
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_single_binding)]
-#![allow(unused_variables, clippy::toplevel_ref_arg)]
+#![allow(unused_variables)]
+#![allow(clippy::toplevel_ref_arg, clippy::uninlined_format_args)]
struct Point {
x: i32,
@@ -140,3 +140,11 @@ fn issue_8723() {
let _ = val;
}
+
+#[allow(dead_code)]
+fn issue_9575() {
+ fn side_effects() {}
+ let _ = || match side_effects() {
+ _ => println!("Needs curlies"),
+ };
+}
diff --git a/src/tools/clippy/tests/ui/match_single_binding.stderr b/src/tools/clippy/tests/ui/match_single_binding.stderr
index 5d4e7314b..2b9ec7ee7 100644
--- a/src/tools/clippy/tests/ui/match_single_binding.stderr
+++ b/src/tools/clippy/tests/ui/match_single_binding.stderr
@@ -196,5 +196,22 @@ LL + suf
LL ~ };
|
-error: aborting due to 13 previous errors
+error: this match could be replaced by its scrutinee and body
+ --> $DIR/match_single_binding.rs:147:16
+ |
+LL | let _ = || match side_effects() {
+ | ________________^
+LL | | _ => println!("Needs curlies"),
+LL | | };
+ | |_____^
+ |
+help: consider using the scrutinee and body instead
+ |
+LL ~ let _ = || {
+LL + side_effects();
+LL + println!("Needs curlies");
+LL ~ };
+ |
+
+error: aborting due to 14 previous errors
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.fixed b/src/tools/clippy/tests/ui/match_single_binding2.fixed
index a91fcc212..6a7db67e3 100644
--- a/src/tools/clippy/tests/ui/match_single_binding2.fixed
+++ b/src/tools/clippy/tests/ui/match_single_binding2.fixed
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
// Lint (additional curly braces needed, see #6572)
diff --git a/src/tools/clippy/tests/ui/match_single_binding2.rs b/src/tools/clippy/tests/ui/match_single_binding2.rs
index 476386eba..5a4bb8441 100644
--- a/src/tools/clippy/tests/ui/match_single_binding2.rs
+++ b/src/tools/clippy/tests/ui/match_single_binding2.rs
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::match_single_binding)]
#![allow(unused_variables)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
// Lint (additional curly braces needed, see #6572)
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr
deleted file mode 100644
index 2d66daea8..000000000
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2018.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:14:9
- |
-LL | Err(_) => panic!("err"),
- | ^^^^^^
- |
- = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
- = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:20:9
- |
-LL | Err(_) => panic!(),
- | ^^^^^^
- |
- = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
-
-error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:26:9
- |
-LL | Err(_) => {
- | ^^^^^^
- |
- = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
-
-error: `Err(_e)` matches all errors
- --> $DIR/match_wild_err_arm.rs:34:9
- |
-LL | Err(_e) => panic!(),
- | ^^^^^^^
- |
- = note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.rs b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
index 0a86144b9..823be65ef 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.rs
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.rs
@@ -1,6 +1,3 @@
-// revisions: edition2018 edition2021
-// [edition2018] edition:2018
-// [edition2021] edition:2021
#![feature(exclusive_range_pattern)]
#![allow(clippy::match_same_arms)]
#![warn(clippy::match_wild_err_arm)]
diff --git a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr b/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
index 2d66daea8..b016d6826 100644
--- a/src/tools/clippy/tests/ui/match_wild_err_arm.edition2021.stderr
+++ b/src/tools/clippy/tests/ui/match_wild_err_arm.stderr
@@ -1,14 +1,14 @@
error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:14:9
+ --> $DIR/match_wild_err_arm.rs:11:9
|
LL | Err(_) => panic!("err"),
| ^^^^^^
|
- = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
= note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
+ = note: `-D clippy::match-wild-err-arm` implied by `-D warnings`
error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:20:9
+ --> $DIR/match_wild_err_arm.rs:17:9
|
LL | Err(_) => panic!(),
| ^^^^^^
@@ -16,7 +16,7 @@ LL | Err(_) => panic!(),
= note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
error: `Err(_)` matches all errors
- --> $DIR/match_wild_err_arm.rs:26:9
+ --> $DIR/match_wild_err_arm.rs:23:9
|
LL | Err(_) => {
| ^^^^^^
@@ -24,7 +24,7 @@ LL | Err(_) => {
= note: match each error separately or use the error output, or use `.expect(msg)` if the error case is unreachable
error: `Err(_e)` matches all errors
- --> $DIR/match_wild_err_arm.rs:34:9
+ --> $DIR/match_wild_err_arm.rs:31:9
|
LL | Err(_e) => panic!(),
| ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/mem_replace.fixed b/src/tools/clippy/tests/ui/mem_replace.fixed
index b609ba659..ae237395b 100644
--- a/src/tools/clippy/tests/ui/mem_replace.fixed
+++ b/src/tools/clippy/tests/ui/mem_replace.fixed
@@ -1,5 +1,7 @@
// run-rustfix
-#![allow(unused_imports)]
+
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
#![warn(
clippy::all,
clippy::style,
@@ -77,3 +79,17 @@ fn main() {
replace_with_default();
dont_lint_primitive();
}
+
+fn msrv_1_39() {
+ #![clippy::msrv = "1.39"]
+
+ let mut s = String::from("foo");
+ let _ = std::mem::replace(&mut s, String::default());
+}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ let mut s = String::from("foo");
+ let _ = std::mem::take(&mut s);
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace.rs b/src/tools/clippy/tests/ui/mem_replace.rs
index 93f6dcdec..3202e99e0 100644
--- a/src/tools/clippy/tests/ui/mem_replace.rs
+++ b/src/tools/clippy/tests/ui/mem_replace.rs
@@ -1,5 +1,7 @@
// run-rustfix
-#![allow(unused_imports)]
+
+#![feature(custom_inner_attributes)]
+#![allow(unused)]
#![warn(
clippy::all,
clippy::style,
@@ -77,3 +79,17 @@ fn main() {
replace_with_default();
dont_lint_primitive();
}
+
+fn msrv_1_39() {
+ #![clippy::msrv = "1.39"]
+
+ let mut s = String::from("foo");
+ let _ = std::mem::replace(&mut s, String::default());
+}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ let mut s = String::from("foo");
+ let _ = std::mem::replace(&mut s, String::default());
+}
diff --git a/src/tools/clippy/tests/ui/mem_replace.stderr b/src/tools/clippy/tests/ui/mem_replace.stderr
index 90dc6c95f..dd8a50dab 100644
--- a/src/tools/clippy/tests/ui/mem_replace.stderr
+++ b/src/tools/clippy/tests/ui/mem_replace.stderr
@@ -1,5 +1,5 @@
error: replacing an `Option` with `None`
- --> $DIR/mem_replace.rs:15:13
+ --> $DIR/mem_replace.rs:17:13
|
LL | let _ = mem::replace(&mut an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
@@ -7,13 +7,13 @@ LL | let _ = mem::replace(&mut an_option, None);
= note: `-D clippy::mem-replace-option-with-none` implied by `-D warnings`
error: replacing an `Option` with `None`
- --> $DIR/mem_replace.rs:17:13
+ --> $DIR/mem_replace.rs:19:13
|
LL | let _ = mem::replace(an_option, None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider `Option::take()` instead: `an_option.take()`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:22:13
+ --> $DIR/mem_replace.rs:24:13
|
LL | let _ = std::mem::replace(&mut s, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
@@ -21,100 +21,106 @@ LL | let _ = std::mem::replace(&mut s, String::default());
= note: `-D clippy::mem-replace-with-default` implied by `-D warnings`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:25:13
+ --> $DIR/mem_replace.rs:27:13
|
LL | let _ = std::mem::replace(s, String::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:26:13
+ --> $DIR/mem_replace.rs:28:13
|
LL | let _ = std::mem::replace(s, Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(s)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:29:13
+ --> $DIR/mem_replace.rs:31:13
|
LL | let _ = std::mem::replace(&mut v, Vec::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:30:13
+ --> $DIR/mem_replace.rs:32:13
|
LL | let _ = std::mem::replace(&mut v, Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:31:13
+ --> $DIR/mem_replace.rs:33:13
|
LL | let _ = std::mem::replace(&mut v, Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:32:13
+ --> $DIR/mem_replace.rs:34:13
|
LL | let _ = std::mem::replace(&mut v, vec![]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut v)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:35:13
+ --> $DIR/mem_replace.rs:37:13
|
LL | let _ = std::mem::replace(&mut hash_map, HashMap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_map)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:38:13
+ --> $DIR/mem_replace.rs:40:13
|
LL | let _ = std::mem::replace(&mut btree_map, BTreeMap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_map)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:41:13
+ --> $DIR/mem_replace.rs:43:13
|
LL | let _ = std::mem::replace(&mut vd, VecDeque::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut vd)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:44:13
+ --> $DIR/mem_replace.rs:46:13
|
LL | let _ = std::mem::replace(&mut hash_set, HashSet::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut hash_set)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:47:13
+ --> $DIR/mem_replace.rs:49:13
|
LL | let _ = std::mem::replace(&mut btree_set, BTreeSet::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut btree_set)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:50:13
+ --> $DIR/mem_replace.rs:52:13
|
LL | let _ = std::mem::replace(&mut list, LinkedList::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut list)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:53:13
+ --> $DIR/mem_replace.rs:55:13
|
LL | let _ = std::mem::replace(&mut binary_heap, BinaryHeap::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut binary_heap)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:56:13
+ --> $DIR/mem_replace.rs:58:13
|
LL | let _ = std::mem::replace(&mut tuple, (vec![], BinaryHeap::new()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut tuple)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:59:13
+ --> $DIR/mem_replace.rs:61:13
|
LL | let _ = std::mem::replace(&mut refstr, "");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut refstr)`
error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
- --> $DIR/mem_replace.rs:62:13
+ --> $DIR/mem_replace.rs:64:13
|
LL | let _ = std::mem::replace(&mut slice, &[]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut slice)`
-error: aborting due to 19 previous errors
+error: replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`
+ --> $DIR/mem_replace.rs:94:13
+ |
+LL | let _ = std::mem::replace(&mut s, String::default());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::mem::take(&mut s)`
+
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/min_max.rs b/src/tools/clippy/tests/ui/min_max.rs
index b2bc97f47..24e52afd6 100644
--- a/src/tools/clippy/tests/ui/min_max.rs
+++ b/src/tools/clippy/tests/ui/min_max.rs
@@ -1,4 +1,5 @@
#![warn(clippy::all)]
+#![allow(clippy::manual_clamp)]
use std::cmp::max as my_max;
use std::cmp::min as my_min;
diff --git a/src/tools/clippy/tests/ui/min_max.stderr b/src/tools/clippy/tests/ui/min_max.stderr
index c70b77eab..069d90686 100644
--- a/src/tools/clippy/tests/ui/min_max.stderr
+++ b/src/tools/clippy/tests/ui/min_max.stderr
@@ -1,5 +1,5 @@
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:23:5
+ --> $DIR/min_max.rs:24:5
|
LL | min(1, max(3, x));
| ^^^^^^^^^^^^^^^^^
@@ -7,73 +7,73 @@ LL | min(1, max(3, x));
= note: `-D clippy::min-max` implied by `-D warnings`
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:24:5
+ --> $DIR/min_max.rs:25:5
|
LL | min(max(3, x), 1);
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:25:5
+ --> $DIR/min_max.rs:26:5
|
LL | max(min(x, 1), 3);
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:26:5
+ --> $DIR/min_max.rs:27:5
|
LL | max(3, min(x, 1));
| ^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:28:5
+ --> $DIR/min_max.rs:29:5
|
LL | my_max(3, my_min(x, 1));
| ^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:38:5
+ --> $DIR/min_max.rs:39:5
|
LL | min("Apple", max("Zoo", s));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:39:5
+ --> $DIR/min_max.rs:40:5
|
LL | max(min(s, "Apple"), "Zoo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:44:5
+ --> $DIR/min_max.rs:45:5
|
LL | x.min(1).max(3);
| ^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:45:5
+ --> $DIR/min_max.rs:46:5
|
LL | x.max(3).min(1);
| ^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:46:5
+ --> $DIR/min_max.rs:47:5
|
LL | f.max(3f32).min(1f32);
| ^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:52:5
+ --> $DIR/min_max.rs:53:5
|
LL | max(x.min(1), 3);
| ^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:55:5
+ --> $DIR/min_max.rs:56:5
|
LL | s.max("Zoo").min("Apple");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: this `min`/`max` combination leads to constant result
- --> $DIR/min_max.rs:56:5
+ --> $DIR/min_max.rs:57:5
|
LL | s.min("Apple").max("Zoo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
index 44e407bd1..cd148063b 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
@@ -1,228 +1,29 @@
#![allow(clippy::redundant_clone)]
#![feature(custom_inner_attributes)]
-#![clippy::msrv = "1.0.0"]
-use std::ops::{Deref, RangeFrom};
+fn main() {}
-fn approx_const() {
+fn just_under_msrv() {
+ #![clippy::msrv = "1.42.0"]
let log2_10 = 3.321928094887362;
- let log10_2 = 0.301029995663981;
}
-fn cloned_instead_of_copied() {
- let _ = [1].iter().cloned();
-}
-
-fn option_as_ref_deref() {
- let mut opt = Some(String::from("123"));
-
- let _ = opt.as_ref().map(String::as_str);
- let _ = opt.as_ref().map(|x| x.as_str());
- let _ = opt.as_mut().map(String::as_mut_str);
- let _ = opt.as_mut().map(|x| x.as_mut_str());
-}
-
-fn match_like_matches() {
- let _y = match Some(5) {
- Some(0) => true,
- _ => false,
- };
-}
-
-fn match_same_arms() {
- match (1, 2, 3) {
- (1, .., 3) => 42,
- (.., 3) => 42, //~ ERROR match arms have same body
- _ => 0,
- };
-}
-
-fn match_same_arms2() {
- let _ = match Some(42) {
- Some(_) => 24,
- None => 24, //~ ERROR match arms have same body
- };
-}
-
-pub fn manual_strip_msrv() {
- let s = "hello, world!";
- if s.starts_with("hello, ") {
- assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- }
-}
-
-pub fn redundant_fieldnames() {
- let start = 0;
- let _ = RangeFrom { start: start };
-}
-
-pub fn redundant_static_lifetime() {
- const VAR_ONE: &'static str = "Test constant #1";
-}
-
-pub fn checked_conversion() {
- let value: i64 = 42;
- let _ = value <= (u32::max_value() as i64) && value >= 0;
- let _ = value <= (u32::MAX as i64) && value >= 0;
-}
-
-pub struct FromOverInto(String);
-
-impl Into<FromOverInto> for String {
- fn into(self) -> FromOverInto {
- FromOverInto(self)
- }
-}
-
-pub fn filter_map_next() {
- let a = ["1", "lol", "3", "NaN", "5"];
-
- #[rustfmt::skip]
- let _: Option<u32> = vec![1, 2, 3, 4, 5, 6]
- .into_iter()
- .filter_map(|x| {
- if x == 2 {
- Some(x * 2)
- } else {
- None
- }
- })
- .next();
-}
-
-#[allow(clippy::no_effect)]
-#[allow(clippy::short_circuit_statement)]
-#[allow(clippy::unnecessary_operation)]
-pub fn manual_range_contains() {
- let x = 5;
- x >= 8 && x < 12;
-}
-
-pub fn use_self() {
- struct Foo;
-
- impl Foo {
- fn new() -> Foo {
- Foo {}
- }
- fn test() -> Foo {
- Foo::new()
- }
- }
-}
-
-fn replace_with_default() {
- let mut s = String::from("foo");
- let _ = std::mem::replace(&mut s, String::default());
-}
-
-fn map_unwrap_or() {
- let opt = Some(1);
-
- // Check for `option.map(_).unwrap_or(_)` use.
- // Single line case.
- let _ = opt
- .map(|x| x + 1)
- // Should lint even though this call is on a separate line.
- .unwrap_or(0);
-}
-
-// Could be const
-fn missing_const_for_fn() -> i32 {
- 1
-}
-
-fn unnest_or_patterns() {
- struct TS(u8, u8);
- if let TS(0, x) | TS(1, x) = TS(0, 0) {}
-}
-
-#[cfg_attr(rustfmt, rustfmt_skip)]
-fn deprecated_cfg_attr() {}
-
-#[warn(clippy::cast_lossless)]
-fn int_from_bool() -> u8 {
- true as u8
-}
-
-fn err_expect() {
- let x: Result<u32, &str> = Ok(10);
- x.err().expect("Testing expect_err");
-}
-
-fn cast_abs_to_unsigned() {
- let x: i32 = 10;
- assert_eq!(10u32, x.abs() as u32);
-}
-
-fn manual_rem_euclid() {
- let x: i32 = 10;
- let _: i32 = ((x % 4) + 4) % 4;
-}
-
-fn main() {
- filter_map_next();
- checked_conversion();
- redundant_fieldnames();
- redundant_static_lifetime();
- option_as_ref_deref();
- match_like_matches();
- match_same_arms();
- match_same_arms2();
- manual_strip_msrv();
- manual_range_contains();
- use_self();
- replace_with_default();
- map_unwrap_or();
- missing_const_for_fn();
- unnest_or_patterns();
- int_from_bool();
- err_expect();
- cast_abs_to_unsigned();
- manual_rem_euclid();
+fn meets_msrv() {
+ #![clippy::msrv = "1.43.0"]
+ let log2_10 = 3.321928094887362;
}
-mod just_under_msrv {
- #![feature(custom_inner_attributes)]
+fn just_above_msrv() {
#![clippy::msrv = "1.44.0"]
-
- fn main() {
- let s = "hello, world!";
- if s.starts_with("hello, ") {
- assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- }
- }
-}
-
-mod meets_msrv {
- #![feature(custom_inner_attributes)]
- #![clippy::msrv = "1.45.0"]
-
- fn main() {
- let s = "hello, world!";
- if s.starts_with("hello, ") {
- assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- }
- }
+ let log2_10 = 3.321928094887362;
}
-mod just_above_msrv {
- #![feature(custom_inner_attributes)]
- #![clippy::msrv = "1.46.0"]
-
- fn main() {
- let s = "hello, world!";
- if s.starts_with("hello, ") {
- assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- }
- }
+fn no_patch_under() {
+ #![clippy::msrv = "1.42"]
+ let log2_10 = 3.321928094887362;
}
-mod const_rem_euclid {
- #![feature(custom_inner_attributes)]
- #![clippy::msrv = "1.50.0"]
-
- pub const fn const_rem_euclid_4(num: i32) -> i32 {
- ((num % 4) + 4) % 4
- }
+fn no_patch_meets() {
+ #![clippy::msrv = "1.43"]
+ let log2_10 = 3.321928094887362;
}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
index b1c23b539..68aa58748 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
@@ -1,37 +1,27 @@
-error: stripping a prefix manually
- --> $DIR/min_rust_version_attr.rs:204:24
+error: approximate value of `f{32, 64}::consts::LOG2_10` found
+ --> $DIR/min_rust_version_attr.rs:13:19
|
-LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- | ^^^^^^^^^^^^^^^^^^^^
- |
- = note: `-D clippy::manual-strip` implied by `-D warnings`
-note: the prefix was tested here
- --> $DIR/min_rust_version_attr.rs:203:9
- |
-LL | if s.starts_with("hello, ") {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: try using the `strip_prefix` method
- |
-LL ~ if let Some(<stripped>) = s.strip_prefix("hello, ") {
-LL ~ assert_eq!(<stripped>.to_uppercase(), "WORLD!");
+LL | let log2_10 = 3.321928094887362;
+ | ^^^^^^^^^^^^^^^^^
|
+ = help: consider using the constant directly
+ = note: `#[deny(clippy::approx_constant)]` on by default
-error: stripping a prefix manually
- --> $DIR/min_rust_version_attr.rs:216:24
+error: approximate value of `f{32, 64}::consts::LOG2_10` found
+ --> $DIR/min_rust_version_attr.rs:18:19
|
-LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- | ^^^^^^^^^^^^^^^^^^^^
+LL | let log2_10 = 3.321928094887362;
+ | ^^^^^^^^^^^^^^^^^
|
-note: the prefix was tested here
- --> $DIR/min_rust_version_attr.rs:215:9
- |
-LL | if s.starts_with("hello, ") {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: try using the `strip_prefix` method
+ = help: consider using the constant directly
+
+error: approximate value of `f{32, 64}::consts::LOG2_10` found
+ --> $DIR/min_rust_version_attr.rs:28:19
|
-LL ~ if let Some(<stripped>) = s.strip_prefix("hello, ") {
-LL ~ assert_eq!(<stripped>.to_uppercase(), "WORLD!");
+LL | let log2_10 = 3.321928094887362;
+ | ^^^^^^^^^^^^^^^^^
|
+ = help: consider using the constant directly
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
index f20841891..02892f329 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
+++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
@@ -2,3 +2,17 @@
#![clippy::msrv = "invalid.version"]
fn main() {}
+
+#[clippy::msrv = "invalid.version"]
+fn outer_attr() {}
+
+mod multiple {
+ #![clippy::msrv = "1.40"]
+ #![clippy::msrv = "=1.35.0"]
+ #![clippy::msrv = "1.10.1"]
+
+ mod foo {
+ #![clippy::msrv = "1"]
+ #![clippy::msrv = "1.0.0"]
+ }
+}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
index 6ff88ca56..93370a0fa 100644
--- a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
+++ b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
@@ -4,5 +4,47 @@ error: `invalid.version` is not a valid Rust version
LL | #![clippy::msrv = "invalid.version"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-error: aborting due to previous error
+error: `msrv` cannot be an outer attribute
+ --> $DIR/min_rust_version_invalid_attr.rs:6:1
+ |
+LL | #[clippy::msrv = "invalid.version"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `msrv` is defined multiple times
+ --> $DIR/min_rust_version_invalid_attr.rs:11:5
+ |
+LL | #![clippy::msrv = "=1.35.0"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: first definition found here
+ --> $DIR/min_rust_version_invalid_attr.rs:10:5
+ |
+LL | #![clippy::msrv = "1.40"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `msrv` is defined multiple times
+ --> $DIR/min_rust_version_invalid_attr.rs:12:5
+ |
+LL | #![clippy::msrv = "1.10.1"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: first definition found here
+ --> $DIR/min_rust_version_invalid_attr.rs:10:5
+ |
+LL | #![clippy::msrv = "1.40"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `msrv` is defined multiple times
+ --> $DIR/min_rust_version_invalid_attr.rs:16:9
+ |
+LL | #![clippy::msrv = "1.0.0"]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+note: first definition found here
+ --> $DIR/min_rust_version_invalid_attr.rs:15:9
+ |
+LL | #![clippy::msrv = "1"]
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs
deleted file mode 100644
index e882d5ccf..000000000
--- a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-#![feature(custom_inner_attributes)]
-#![clippy::msrv = "1.40"]
-#![clippy::msrv = "=1.35.0"]
-#![clippy::msrv = "1.10.1"]
-
-mod foo {
- #![clippy::msrv = "1"]
- #![clippy::msrv = "1.0.0"]
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr
deleted file mode 100644
index e3ff6605c..000000000
--- a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr
+++ /dev/null
@@ -1,38 +0,0 @@
-error: `msrv` is defined multiple times
- --> $DIR/min_rust_version_multiple_inner_attr.rs:3:1
- |
-LL | #![clippy::msrv = "=1.35.0"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: first definition found here
- --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
- |
-LL | #![clippy::msrv = "1.40"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: `msrv` is defined multiple times
- --> $DIR/min_rust_version_multiple_inner_attr.rs:4:1
- |
-LL | #![clippy::msrv = "1.10.1"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: first definition found here
- --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
- |
-LL | #![clippy::msrv = "1.40"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: `msrv` is defined multiple times
- --> $DIR/min_rust_version_multiple_inner_attr.rs:8:5
- |
-LL | #![clippy::msrv = "1.0.0"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
- |
-note: first definition found here
- --> $DIR/min_rust_version_multiple_inner_attr.rs:7:5
- |
-LL | #![clippy::msrv = "1"]
- | ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs b/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs
deleted file mode 100644
index 98fffe1e3..000000000
--- a/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![allow(clippy::redundant_clone)]
-#![feature(custom_inner_attributes)]
-#![clippy::msrv = "1.0"]
-
-fn manual_strip_msrv() {
- let s = "hello, world!";
- if s.starts_with("hello, ") {
- assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
- }
-}
-
-fn main() {
- manual_strip_msrv()
-}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs
deleted file mode 100644
index 551948bd7..000000000
--- a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#![feature(custom_inner_attributes)]
-
-#[clippy::msrv = "invalid.version"]
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr
deleted file mode 100644
index 579ee7a87..000000000
--- a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `msrv` cannot be an outer attribute
- --> $DIR/min_rust_version_outer_attr.rs:3:1
- |
-LL | #[clippy::msrv = "invalid.version"]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr b/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr
index 3534b5328..9822c77c9 100644
--- a/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr
+++ b/src/tools/clippy/tests/ui/mismatched_target_os_unix.stderr
@@ -6,8 +6,8 @@ LL | #[cfg(linux)]
| |
| help: try: `target_os = "linux"`
|
- = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
= help: did you mean `unix`?
+ = note: `-D clippy::mismatched-target-os` implied by `-D warnings`
error: operating system used in target family position
--> $DIR/mismatched_target_os_unix.rs:9:1
diff --git a/src/tools/clippy/tests/ui/mismatching_type_param_order.stderr b/src/tools/clippy/tests/ui/mismatching_type_param_order.stderr
index cb720256c..204d49905 100644
--- a/src/tools/clippy/tests/ui/mismatching_type_param_order.stderr
+++ b/src/tools/clippy/tests/ui/mismatching_type_param_order.stderr
@@ -4,8 +4,8 @@ error: `Foo` has a similarly named generic type parameter `B` in its declaration
LL | impl<B, A> Foo<B, A> {}
| ^
|
- = note: `-D clippy::mismatching-type-param-order` implied by `-D warnings`
= help: try `A`, or a name that does not conflict with `Foo`'s generic params
+ = note: `-D clippy::mismatching-type-param-order` implied by `-D warnings`
error: `Foo` has a similarly named generic type parameter `A` in its declaration, but in a different order
--> $DIR/mismatching_type_param_order.rs:11:23
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
index 88f6935d2..b85e88784 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.rs
@@ -77,5 +77,17 @@ mod const_fn_stabilized_before_msrv {
}
}
+fn msrv_1_45() -> i32 {
+ #![clippy::msrv = "1.45"]
+
+ 45
+}
+
+fn msrv_1_46() -> i32 {
+ #![clippy::msrv = "1.46"]
+
+ 46
+}
+
// Should not be const
fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
index 3eb52b682..f8e221c82 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/could_be_const.stderr
@@ -81,5 +81,15 @@ LL | | byte.is_ascii_digit();
LL | | }
| |_____^
-error: aborting due to 10 previous errors
+error: this could be a `const fn`
+ --> $DIR/could_be_const.rs:86:1
+ |
+LL | / fn msrv_1_46() -> i32 {
+LL | | #![clippy::msrv = "1.46"]
+LL | |
+LL | | 46
+LL | | }
+ | |_^
+
+error: aborting due to 11 previous errors
diff --git a/src/tools/clippy/tests/ui/missing_doc.rs b/src/tools/clippy/tests/ui/missing_doc.rs
index 29cc026a8..590ad63c9 100644
--- a/src/tools/clippy/tests/ui/missing_doc.rs
+++ b/src/tools/clippy/tests/ui/missing_doc.rs
@@ -1,3 +1,4 @@
+// needs-asm-support
// aux-build: proc_macro_with_span.rs
#![warn(clippy::missing_docs_in_private_items)]
diff --git a/src/tools/clippy/tests/ui/missing_doc.stderr b/src/tools/clippy/tests/ui/missing_doc.stderr
index 6c8e66f46..d3bef28bf 100644
--- a/src/tools/clippy/tests/ui/missing_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_doc.stderr
@@ -1,5 +1,5 @@
error: missing documentation for a type alias
- --> $DIR/missing_doc.rs:15:1
+ --> $DIR/missing_doc.rs:16:1
|
LL | type Typedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | type Typedef = String;
= note: `-D clippy::missing-docs-in-private-items` implied by `-D warnings`
error: missing documentation for a type alias
- --> $DIR/missing_doc.rs:16:1
+ --> $DIR/missing_doc.rs:17:1
|
LL | pub type PubTypedef = String;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:18:1
+ --> $DIR/missing_doc.rs:19:1
|
LL | mod module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:19:1
+ --> $DIR/missing_doc.rs:20:1
|
LL | pub mod pub_module_no_dox {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:23:1
+ --> $DIR/missing_doc.rs:24:1
|
LL | pub fn foo2() {}
| ^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:24:1
+ --> $DIR/missing_doc.rs:25:1
|
LL | fn foo3() {}
| ^^^^^^^^^^^^
error: missing documentation for an enum
- --> $DIR/missing_doc.rs:38:1
+ --> $DIR/missing_doc.rs:39:1
|
LL | / enum Baz {
LL | | BazA { a: isize, b: isize },
@@ -46,31 +46,31 @@ LL | | }
| |_^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:39:5
+ --> $DIR/missing_doc.rs:40:5
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:39:12
+ --> $DIR/missing_doc.rs:40:12
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:39:22
+ --> $DIR/missing_doc.rs:40:22
|
LL | BazA { a: isize, b: isize },
| ^^^^^^^^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:40:5
+ --> $DIR/missing_doc.rs:41:5
|
LL | BarB,
| ^^^^
error: missing documentation for an enum
- --> $DIR/missing_doc.rs:43:1
+ --> $DIR/missing_doc.rs:44:1
|
LL | / pub enum PubBaz {
LL | | PubBazA { a: isize },
@@ -78,43 +78,43 @@ LL | | }
| |_^
error: missing documentation for a variant
- --> $DIR/missing_doc.rs:44:5
+ --> $DIR/missing_doc.rs:45:5
|
LL | PubBazA { a: isize },
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a struct field
- --> $DIR/missing_doc.rs:44:15
+ --> $DIR/missing_doc.rs:45:15
|
LL | PubBazA { a: isize },
| ^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing_doc.rs:64:1
+ --> $DIR/missing_doc.rs:65:1
|
LL | const FOO: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^
error: missing documentation for a constant
- --> $DIR/missing_doc.rs:71:1
+ --> $DIR/missing_doc.rs:72:1
|
LL | pub const FOO4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing_doc.rs:73:1
+ --> $DIR/missing_doc.rs:74:1
|
LL | static BAR: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a static
- --> $DIR/missing_doc.rs:80:1
+ --> $DIR/missing_doc.rs:81:1
|
LL | pub static BAR4: u32 = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a module
- --> $DIR/missing_doc.rs:82:1
+ --> $DIR/missing_doc.rs:83:1
|
LL | / mod internal_impl {
LL | | /// dox
@@ -126,31 +126,31 @@ LL | | }
| |_^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:85:5
+ --> $DIR/missing_doc.rs:86:5
|
LL | pub fn undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:86:5
+ --> $DIR/missing_doc.rs:87:5
|
LL | pub fn undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:87:5
+ --> $DIR/missing_doc.rs:88:5
|
LL | fn undocumented3() {}
| ^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:92:9
+ --> $DIR/missing_doc.rs:93:9
|
LL | pub fn also_undocumented1() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: missing documentation for a function
- --> $DIR/missing_doc.rs:93:9
+ --> $DIR/missing_doc.rs:94:9
|
LL | fn also_undocumented2() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/missing_panics_doc.stderr b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
index 91ebd6952..c9ded7f1a 100644
--- a/src/tools/clippy/tests/ui/missing_panics_doc.stderr
+++ b/src/tools/clippy/tests/ui/missing_panics_doc.stderr
@@ -7,12 +7,12 @@ LL | | result.unwrap()
LL | | }
| |_^
|
- = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
note: first possible panic found here
--> $DIR/missing_panics_doc.rs:8:5
|
LL | result.unwrap()
| ^^^^^^^^^^^^^^^
+ = note: `-D clippy::missing-panics-doc` implied by `-D warnings`
error: docs for function which may panic missing `# Panics` section
--> $DIR/missing_panics_doc.rs:12:1
diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.rs b/src/tools/clippy/tests/ui/missing_trait_methods.rs
new file mode 100644
index 000000000..8df885919
--- /dev/null
+++ b/src/tools/clippy/tests/ui/missing_trait_methods.rs
@@ -0,0 +1,50 @@
+#![allow(unused, clippy::needless_lifetimes)]
+#![warn(clippy::missing_trait_methods)]
+
+trait A {
+ fn provided() {}
+}
+
+trait B {
+ fn required();
+
+ fn a(_: usize) -> usize {
+ 1
+ }
+
+ fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] {
+ a.as_ref()
+ }
+}
+
+struct Partial;
+
+impl A for Partial {}
+
+impl B for Partial {
+ fn required() {}
+
+ fn a(_: usize) -> usize {
+ 2
+ }
+}
+
+struct Complete;
+
+impl A for Complete {
+ fn provided() {}
+}
+
+impl B for Complete {
+ fn required() {}
+
+ fn a(_: usize) -> usize {
+ 2
+ }
+
+ fn b<T: AsRef<[u8]>>(a: &T) -> &[u8] {
+ a.as_ref()
+ }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/missing_trait_methods.stderr b/src/tools/clippy/tests/ui/missing_trait_methods.stderr
new file mode 100644
index 000000000..0c5205e19
--- /dev/null
+++ b/src/tools/clippy/tests/ui/missing_trait_methods.stderr
@@ -0,0 +1,27 @@
+error: missing trait method provided by default: `provided`
+ --> $DIR/missing_trait_methods.rs:22:1
+ |
+LL | impl A for Partial {}
+ | ^^^^^^^^^^^^^^^^^^
+ |
+help: implement the method
+ --> $DIR/missing_trait_methods.rs:5:5
+ |
+LL | fn provided() {}
+ | ^^^^^^^^^^^^^
+ = note: `-D clippy::missing-trait-methods` implied by `-D warnings`
+
+error: missing trait method provided by default: `b`
+ --> $DIR/missing_trait_methods.rs:24:1
+ |
+LL | impl B for Partial {
+ | ^^^^^^^^^^^^^^^^^^
+ |
+help: implement the method
+ --> $DIR/missing_trait_methods.rs:15:5
+ |
+LL | fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/mixed_read_write_in_expression.stderr b/src/tools/clippy/tests/ui/mixed_read_write_in_expression.stderr
index 2e951cdbc..8cc68b0ac 100644
--- a/src/tools/clippy/tests/ui/mixed_read_write_in_expression.stderr
+++ b/src/tools/clippy/tests/ui/mixed_read_write_in_expression.stderr
@@ -4,12 +4,12 @@ error: unsequenced read of `x`
LL | } + x;
| ^
|
- = note: `-D clippy::mixed-read-write-in-expression` implied by `-D warnings`
note: whether read occurs before this write depends on evaluation order
--> $DIR/mixed_read_write_in_expression.rs:12:9
|
LL | x = 1;
| ^^^^^
+ = note: `-D clippy::mixed-read-write-in-expression` implied by `-D warnings`
error: unsequenced read of `x`
--> $DIR/mixed_read_write_in_expression.rs:17:5
diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_float.stderr b/src/tools/clippy/tests/ui/modulo_arithmetic_float.stderr
index 97844aaaa..36106de31 100644
--- a/src/tools/clippy/tests/ui/modulo_arithmetic_float.stderr
+++ b/src/tools/clippy/tests/ui/modulo_arithmetic_float.stderr
@@ -4,8 +4,8 @@ error: you are using modulo operator on constants with different signs: `-1.600
LL | -1.6 % 2.1;
| ^^^^^^^^^^
|
- = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
= note: double check for expected result especially when interoperating with different languages
+ = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
error: you are using modulo operator on constants with different signs: `1.600 % -2.100`
--> $DIR/modulo_arithmetic_float.rs:7:5
diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_integral.stderr b/src/tools/clippy/tests/ui/modulo_arithmetic_integral.stderr
index f71adf5b0..9ff676ff6 100644
--- a/src/tools/clippy/tests/ui/modulo_arithmetic_integral.stderr
+++ b/src/tools/clippy/tests/ui/modulo_arithmetic_integral.stderr
@@ -4,9 +4,9 @@ error: you are using modulo operator on types that might have different signs
LL | a % b;
| ^^^^^
|
- = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
= note: double check for expected result especially when interoperating with different languages
= note: or consider using `rem_euclid` or similar function
+ = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
error: you are using modulo operator on types that might have different signs
--> $DIR/modulo_arithmetic_integral.rs:9:5
diff --git a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr
index 11b5f7746..1453d44f4 100644
--- a/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr
+++ b/src/tools/clippy/tests/ui/modulo_arithmetic_integral_const.stderr
@@ -4,9 +4,9 @@ error: you are using modulo operator on constants with different signs: `-1 % 2`
LL | -1 % 2;
| ^^^^^^
|
- = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
= note: double check for expected result especially when interoperating with different languages
= note: or consider using `rem_euclid` or similar function
+ = note: `-D clippy::modulo-arithmetic` implied by `-D warnings`
error: you are using modulo operator on constants with different signs: `1 % -2`
--> $DIR/modulo_arithmetic_integral_const.rs:12:5
diff --git a/src/tools/clippy/tests/ui/mut_from_ref.stderr b/src/tools/clippy/tests/ui/mut_from_ref.stderr
index b76d6a13f..c20ff54bf 100644
--- a/src/tools/clippy/tests/ui/mut_from_ref.stderr
+++ b/src/tools/clippy/tests/ui/mut_from_ref.stderr
@@ -4,12 +4,12 @@ error: mutable borrow from immutable input(s)
LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo {
| ^^^^^^^^
|
- = note: `-D clippy::mut-from-ref` implied by `-D warnings`
note: immutable borrow here
--> $DIR/mut_from_ref.rs:7:29
|
LL | fn this_wont_hurt_a_bit(&self) -> &mut Foo {
| ^^^^^
+ = note: `-D clippy::mut-from-ref` implied by `-D warnings`
error: mutable borrow from immutable input(s)
--> $DIR/mut_from_ref.rs:13:25
diff --git a/src/tools/clippy/tests/ui/mut_mut.rs b/src/tools/clippy/tests/ui/mut_mut.rs
index be854d941..ac8fd9d8f 100644
--- a/src/tools/clippy/tests/ui/mut_mut.rs
+++ b/src/tools/clippy/tests/ui/mut_mut.rs
@@ -1,7 +1,7 @@
// aux-build:macro_rules.rs
-
-#![allow(unused, clippy::no_effect, clippy::unnecessary_operation)]
#![warn(clippy::mut_mut)]
+#![allow(unused)]
+#![allow(clippy::no_effect, clippy::uninlined_format_args, clippy::unnecessary_operation)]
#[macro_use]
extern crate macro_rules;
diff --git a/src/tools/clippy/tests/ui/mut_range_bound.stderr b/src/tools/clippy/tests/ui/mut_range_bound.stderr
index 4b5a3fc1e..e0c8dced3 100644
--- a/src/tools/clippy/tests/ui/mut_range_bound.stderr
+++ b/src/tools/clippy/tests/ui/mut_range_bound.stderr
@@ -4,8 +4,8 @@ error: attempt to mutate range bound within loop
LL | m = 5;
| ^
|
- = note: `-D clippy::mut-range-bound` implied by `-D warnings`
= note: the range of the loop is unchanged
+ = note: `-D clippy::mut-range-bound` implied by `-D warnings`
error: attempt to mutate range bound within loop
--> $DIR/mut_range_bound.rs:15:9
diff --git a/src/tools/clippy/tests/ui/needless_borrow.fixed b/src/tools/clippy/tests/ui/needless_borrow.fixed
index 8cf93bd24..340e89d2d 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrow.fixed
@@ -1,9 +1,13 @@
// run-rustfix
-
#![feature(custom_inner_attributes, lint_reasons)]
#[warn(clippy::all, clippy::needless_borrow)]
-#[allow(unused_variables, clippy::unnecessary_mut_passed)]
+#[allow(unused_variables)]
+#[allow(
+ clippy::uninlined_format_args,
+ clippy::unnecessary_mut_passed,
+ clippy::unnecessary_to_owned
+)]
fn main() {
let a = 5;
let ref_a = &a;
@@ -134,6 +138,7 @@ fn main() {
multiple_constraints([[""]]);
multiple_constraints_normalizes_to_same(X, X);
let _ = Some("").unwrap_or("");
+ let _ = std::fs::write("x", "".to_string());
only_sized(&""); // Don't lint. `Sized` is only bound
let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound
@@ -276,8 +281,9 @@ mod copyable_iterator {
fn dont_warn(mut x: Iter) {
takes_iter(&mut x);
}
+ #[allow(unused_mut)]
fn warn(mut x: &mut Iter) {
- takes_iter(&mut x)
+ takes_iter(x)
}
}
@@ -298,3 +304,84 @@ mod meets_msrv {
let _ = std::process::Command::new("ls").args(["-a", "-l"]).status().unwrap();
}
}
+
+#[allow(unused)]
+fn issue9383() {
+ // Should not lint because unions need explicit deref when accessing field
+ use std::mem::ManuallyDrop;
+
+ union Coral {
+ crab: ManuallyDrop<Vec<i32>>,
+ }
+
+ union Ocean {
+ coral: ManuallyDrop<Coral>,
+ }
+
+ let mut ocean = Ocean {
+ coral: ManuallyDrop::new(Coral {
+ crab: ManuallyDrop::new(vec![1, 2, 3]),
+ }),
+ };
+
+ unsafe {
+ ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
+
+ (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
+ ManuallyDrop::drop(&mut (*ocean.coral).crab);
+
+ ManuallyDrop::drop(&mut ocean.coral);
+ }
+}
+
+#[allow(dead_code)]
+fn closure_test() {
+ let env = "env".to_owned();
+ let arg = "arg".to_owned();
+ let f = |arg| {
+ let loc = "loc".to_owned();
+ let _ = std::fs::write("x", &env); // Don't lint. In environment
+ let _ = std::fs::write("x", arg);
+ let _ = std::fs::write("x", loc);
+ };
+ let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
+ f(arg);
+}
+
+#[allow(dead_code)]
+mod significant_drop {
+ #[derive(Debug)]
+ struct X;
+
+ #[derive(Debug)]
+ struct Y;
+
+ impl Drop for Y {
+ fn drop(&mut self) {}
+ }
+
+ fn foo(x: X, y: Y) {
+ debug(x);
+ debug(&y); // Don't lint. Has significant drop
+ }
+
+ fn debug(_: impl std::fmt::Debug) {}
+}
+
+#[allow(dead_code)]
+mod used_exactly_once {
+ fn foo(x: String) {
+ use_x(x);
+ }
+ fn use_x(_: impl AsRef<str>) {}
+}
+
+#[allow(dead_code)]
+mod used_more_than_once {
+ fn foo(x: String) {
+ use_x(&x);
+ use_x_again(&x);
+ }
+ fn use_x(_: impl AsRef<str>) {}
+ fn use_x_again(_: impl AsRef<str>) {}
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.rs b/src/tools/clippy/tests/ui/needless_borrow.rs
index fd9b2a11d..c93711ac8 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.rs
+++ b/src/tools/clippy/tests/ui/needless_borrow.rs
@@ -1,9 +1,13 @@
// run-rustfix
-
#![feature(custom_inner_attributes, lint_reasons)]
#[warn(clippy::all, clippy::needless_borrow)]
-#[allow(unused_variables, clippy::unnecessary_mut_passed)]
+#[allow(unused_variables)]
+#[allow(
+ clippy::uninlined_format_args,
+ clippy::unnecessary_mut_passed,
+ clippy::unnecessary_to_owned
+)]
fn main() {
let a = 5;
let ref_a = &a;
@@ -134,6 +138,7 @@ fn main() {
multiple_constraints(&[[""]]);
multiple_constraints_normalizes_to_same(&X, X);
let _ = Some("").unwrap_or(&"");
+ let _ = std::fs::write("x", &"".to_string());
only_sized(&""); // Don't lint. `Sized` is only bound
let _ = std::any::Any::type_id(&""); // Don't lint. `Any` is only bound
@@ -276,6 +281,7 @@ mod copyable_iterator {
fn dont_warn(mut x: Iter) {
takes_iter(&mut x);
}
+ #[allow(unused_mut)]
fn warn(mut x: &mut Iter) {
takes_iter(&mut x)
}
@@ -298,3 +304,84 @@ mod meets_msrv {
let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
}
}
+
+#[allow(unused)]
+fn issue9383() {
+ // Should not lint because unions need explicit deref when accessing field
+ use std::mem::ManuallyDrop;
+
+ union Coral {
+ crab: ManuallyDrop<Vec<i32>>,
+ }
+
+ union Ocean {
+ coral: ManuallyDrop<Coral>,
+ }
+
+ let mut ocean = Ocean {
+ coral: ManuallyDrop::new(Coral {
+ crab: ManuallyDrop::new(vec![1, 2, 3]),
+ }),
+ };
+
+ unsafe {
+ ManuallyDrop::drop(&mut (&mut ocean.coral).crab);
+
+ (*ocean.coral).crab = ManuallyDrop::new(vec![4, 5, 6]);
+ ManuallyDrop::drop(&mut (*ocean.coral).crab);
+
+ ManuallyDrop::drop(&mut ocean.coral);
+ }
+}
+
+#[allow(dead_code)]
+fn closure_test() {
+ let env = "env".to_owned();
+ let arg = "arg".to_owned();
+ let f = |arg| {
+ let loc = "loc".to_owned();
+ let _ = std::fs::write("x", &env); // Don't lint. In environment
+ let _ = std::fs::write("x", &arg);
+ let _ = std::fs::write("x", &loc);
+ };
+ let _ = std::fs::write("x", &env); // Don't lint. Borrowed by `f`
+ f(arg);
+}
+
+#[allow(dead_code)]
+mod significant_drop {
+ #[derive(Debug)]
+ struct X;
+
+ #[derive(Debug)]
+ struct Y;
+
+ impl Drop for Y {
+ fn drop(&mut self) {}
+ }
+
+ fn foo(x: X, y: Y) {
+ debug(&x);
+ debug(&y); // Don't lint. Has significant drop
+ }
+
+ fn debug(_: impl std::fmt::Debug) {}
+}
+
+#[allow(dead_code)]
+mod used_exactly_once {
+ fn foo(x: String) {
+ use_x(&x);
+ }
+ fn use_x(_: impl AsRef<str>) {}
+}
+
+#[allow(dead_code)]
+mod used_more_than_once {
+ fn foo(x: String) {
+ use_x(&x);
+ use_x_again(&x);
+ }
+ fn use_x(_: impl AsRef<str>) {}
+ fn use_x_again(_: impl AsRef<str>) {}
+}
diff --git a/src/tools/clippy/tests/ui/needless_borrow.stderr b/src/tools/clippy/tests/ui/needless_borrow.stderr
index 5af68706d..8b593268b 100644
--- a/src/tools/clippy/tests/ui/needless_borrow.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrow.stderr
@@ -1,5 +1,5 @@
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:11:15
+ --> $DIR/needless_borrow.rs:15:15
|
LL | let _ = x(&&a); // warn
| ^^^ help: change this to: `&a`
@@ -7,172 +7,208 @@ LL | let _ = x(&&a); // warn
= note: `-D clippy::needless-borrow` implied by `-D warnings`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:15:13
+ --> $DIR/needless_borrow.rs:19:13
|
LL | mut_ref(&mut &mut b); // warn
| ^^^^^^^^^^^ help: change this to: `&mut b`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:27:13
+ --> $DIR/needless_borrow.rs:31:13
|
LL | &&a
| ^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:29:15
+ --> $DIR/needless_borrow.rs:33:15
|
LL | 46 => &&a,
| ^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:35:27
+ --> $DIR/needless_borrow.rs:39:27
|
LL | break &ref_a;
| ^^^^^^ help: change this to: `ref_a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:42:15
+ --> $DIR/needless_borrow.rs:46:15
|
LL | let _ = x(&&&a);
| ^^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:43:15
+ --> $DIR/needless_borrow.rs:47:15
|
LL | let _ = x(&mut &&a);
| ^^^^^^^^ help: change this to: `&a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:44:15
+ --> $DIR/needless_borrow.rs:48:15
|
LL | let _ = x(&&&mut b);
| ^^^^^^^^ help: change this to: `&mut b`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:45:15
+ --> $DIR/needless_borrow.rs:49:15
|
LL | let _ = x(&&ref_a);
| ^^^^^^^ help: change this to: `ref_a`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:48:11
+ --> $DIR/needless_borrow.rs:52:11
|
LL | x(&b);
| ^^ help: change this to: `b`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:55:13
+ --> $DIR/needless_borrow.rs:59:13
|
LL | mut_ref(&mut x);
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:56:13
+ --> $DIR/needless_borrow.rs:60:13
|
LL | mut_ref(&mut &mut x);
| ^^^^^^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:57:23
+ --> $DIR/needless_borrow.rs:61:23
|
LL | let y: &mut i32 = &mut x;
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:58:23
+ --> $DIR/needless_borrow.rs:62:23
|
LL | let y: &mut i32 = &mut &mut x;
| ^^^^^^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:67:14
+ --> $DIR/needless_borrow.rs:71:14
|
LL | 0 => &mut x,
| ^^^^^^ help: change this to: `x`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:73:14
+ --> $DIR/needless_borrow.rs:77:14
|
LL | 0 => &mut x,
| ^^^^^^ help: change this to: `x`
error: this expression borrows a value the compiler would automatically borrow
- --> $DIR/needless_borrow.rs:85:13
+ --> $DIR/needless_borrow.rs:89:13
|
LL | let _ = (&x).0;
| ^^^^ help: change this to: `x`
error: this expression borrows a value the compiler would automatically borrow
- --> $DIR/needless_borrow.rs:87:22
+ --> $DIR/needless_borrow.rs:91:22
|
LL | let _ = unsafe { (&*x).0 };
| ^^^^^ help: change this to: `(*x)`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:97:5
+ --> $DIR/needless_borrow.rs:101:5
|
LL | (&&()).foo();
| ^^^^^^ help: change this to: `(&())`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:106:5
+ --> $DIR/needless_borrow.rs:110:5
|
LL | (&&5).foo();
| ^^^^^ help: change this to: `(&5)`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:131:51
+ --> $DIR/needless_borrow.rs:135:51
|
LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
| ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:132:44
+ --> $DIR/needless_borrow.rs:136:44
|
LL | let _ = std::path::Path::new(".").join(&&".");
| ^^^^^ help: change this to: `"."`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:133:23
+ --> $DIR/needless_borrow.rs:137:23
|
LL | deref_target_is_x(&X);
| ^^ help: change this to: `X`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:134:26
+ --> $DIR/needless_borrow.rs:138:26
|
LL | multiple_constraints(&[[""]]);
| ^^^^^^^ help: change this to: `[[""]]`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:135:45
+ --> $DIR/needless_borrow.rs:139:45
|
LL | multiple_constraints_normalizes_to_same(&X, X);
| ^^ help: change this to: `X`
error: this expression creates a reference which is immediately dereferenced by the compiler
- --> $DIR/needless_borrow.rs:136:32
+ --> $DIR/needless_borrow.rs:140:32
|
LL | let _ = Some("").unwrap_or(&"");
| ^^^ help: change this to: `""`
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:141:33
+ |
+LL | let _ = std::fs::write("x", &"".to_string());
+ | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()`
+
error: this expression borrows a value the compiler would automatically borrow
- --> $DIR/needless_borrow.rs:187:13
+ --> $DIR/needless_borrow.rs:192:13
|
LL | (&self.f)()
| ^^^^^^^^^ help: change this to: `(self.f)`
error: this expression borrows a value the compiler would automatically borrow
- --> $DIR/needless_borrow.rs:196:13
+ --> $DIR/needless_borrow.rs:201:13
|
LL | (&mut self.f)()
| ^^^^^^^^^^^^^ help: change this to: `(self.f)`
error: the borrowed expression implements the required traits
- --> $DIR/needless_borrow.rs:298:55
+ --> $DIR/needless_borrow.rs:286:20
+ |
+LL | takes_iter(&mut x)
+ | ^^^^^^ help: change this to: `x`
+
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:304:55
|
LL | let _ = std::process::Command::new("ls").args(&["-a", "-l"]).status().unwrap();
| ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]`
-error: aborting due to 29 previous errors
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:344:37
+ |
+LL | let _ = std::fs::write("x", &arg);
+ | ^^^^ help: change this to: `arg`
+
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:345:37
+ |
+LL | let _ = std::fs::write("x", &loc);
+ | ^^^^ help: change this to: `loc`
+
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:364:15
+ |
+LL | debug(&x);
+ | ^^ help: change this to: `x`
+
+error: the borrowed expression implements the required traits
+ --> $DIR/needless_borrow.rs:374:15
+ |
+LL | use_x(&x);
+ | ^^ help: change this to: `x`
+
+error: aborting due to 35 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
index a0937a2c5..bcb4eb2dd 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.fixed
@@ -1,17 +1,38 @@
// run-rustfix
-#[warn(clippy::needless_borrowed_reference)]
-#[allow(unused_variables)]
-fn main() {
+#![warn(clippy::needless_borrowed_reference)]
+#![allow(unused, clippy::needless_borrow)]
+
+fn main() {}
+
+fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
let mut v = Vec::<String>::new();
let _ = v.iter_mut().filter(|a| a.is_empty());
- // ^ should be linted
let var = 3;
let thingy = Some(&var);
- if let Some(&ref v) = thingy {
- // ^ should be linted
- }
+ if let Some(v) = thingy {}
+
+ if let &[a, ref b] = slice_of_refs {}
+
+ let [a, ..] = &array;
+ let [a, b, ..] = &array;
+
+ if let [a, b] = slice {}
+ if let [a, b] = &vec[..] {}
+
+ if let [a, b, ..] = slice {}
+ if let [a, .., b] = slice {}
+ if let [.., a, b] = slice {}
+}
+
+fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+ if let [ref a] = slice {}
+ if let &[ref a, b] = slice {}
+ if let &[ref a, .., b] = slice {}
+
+ // must not be removed as variables must be bound consistently across | patterns
+ if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
let mut var2 = 5;
let thingy2 = Some(&mut var2);
@@ -28,17 +49,15 @@ fn main() {
}
}
-#[allow(dead_code)]
enum Animal {
Cat(u64),
Dog(u64),
}
-#[allow(unused_variables)]
-#[allow(dead_code)]
fn foo(a: &Animal, b: &Animal) {
match (a, b) {
- (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref'
+ // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
+ (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
// ^ and ^ should **not** be linted
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
}
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
index 500ac448f..f6de1a6d8 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.rs
@@ -1,17 +1,38 @@
// run-rustfix
-#[warn(clippy::needless_borrowed_reference)]
-#[allow(unused_variables)]
-fn main() {
+#![warn(clippy::needless_borrowed_reference)]
+#![allow(unused, clippy::needless_borrow)]
+
+fn main() {}
+
+fn should_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
let mut v = Vec::<String>::new();
let _ = v.iter_mut().filter(|&ref a| a.is_empty());
- // ^ should be linted
let var = 3;
let thingy = Some(&var);
- if let Some(&ref v) = thingy {
- // ^ should be linted
- }
+ if let Some(&ref v) = thingy {}
+
+ if let &[&ref a, ref b] = slice_of_refs {}
+
+ let &[ref a, ..] = &array;
+ let &[ref a, ref b, ..] = &array;
+
+ if let &[ref a, ref b] = slice {}
+ if let &[ref a, ref b] = &vec[..] {}
+
+ if let &[ref a, ref b, ..] = slice {}
+ if let &[ref a, .., ref b] = slice {}
+ if let &[.., ref a, ref b] = slice {}
+}
+
+fn should_not_lint(array: [u8; 4], slice: &[u8], slice_of_refs: &[&u8], vec: Vec<u8>) {
+ if let [ref a] = slice {}
+ if let &[ref a, b] = slice {}
+ if let &[ref a, .., b] = slice {}
+
+ // must not be removed as variables must be bound consistently across | patterns
+ if let (&[ref a], _) | ([], ref a) = (slice_of_refs, &1u8) {}
let mut var2 = 5;
let thingy2 = Some(&mut var2);
@@ -28,17 +49,15 @@ fn main() {
}
}
-#[allow(dead_code)]
enum Animal {
Cat(u64),
Dog(u64),
}
-#[allow(unused_variables)]
-#[allow(dead_code)]
fn foo(a: &Animal, b: &Animal) {
match (a, b) {
- (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (), // lifetime mismatch error if there is no '&ref'
+ // lifetime mismatch error if there is no '&ref' before `feature(nll)` stabilization in 1.63
+ (&Animal::Cat(v), &ref k) | (&ref k, &Animal::Cat(v)) => (),
// ^ and ^ should **not** be linted
(&Animal::Dog(ref a), &Animal::Dog(_)) => (), // ^ should **not** be linted
}
diff --git a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
index 0a5cfb3db..7453542e6 100644
--- a/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
+++ b/src/tools/clippy/tests/ui/needless_borrowed_ref.stderr
@@ -1,10 +1,123 @@
-error: this pattern takes a reference on something that is being de-referenced
- --> $DIR/needless_borrowed_ref.rs:7:34
+error: this pattern takes a reference on something that is being dereferenced
+ --> $DIR/needless_borrowed_ref.rs:10:34
|
LL | let _ = v.iter_mut().filter(|&ref a| a.is_empty());
- | ^^^^^^ help: try removing the `&ref` part and just keep: `a`
+ | ^^^^^^
|
= note: `-D clippy::needless-borrowed-reference` implied by `-D warnings`
+help: try removing the `&ref` part
+ |
+LL - let _ = v.iter_mut().filter(|&ref a| a.is_empty());
+LL + let _ = v.iter_mut().filter(|a| a.is_empty());
+ |
+
+error: this pattern takes a reference on something that is being dereferenced
+ --> $DIR/needless_borrowed_ref.rs:14:17
+ |
+LL | if let Some(&ref v) = thingy {}
+ | ^^^^^^
+ |
+help: try removing the `&ref` part
+ |
+LL - if let Some(&ref v) = thingy {}
+LL + if let Some(v) = thingy {}
+ |
+
+error: this pattern takes a reference on something that is being dereferenced
+ --> $DIR/needless_borrowed_ref.rs:16:14
+ |
+LL | if let &[&ref a, ref b] = slice_of_refs {}
+ | ^^^^^^
+ |
+help: try removing the `&ref` part
+ |
+LL - if let &[&ref a, ref b] = slice_of_refs {}
+LL + if let &[a, ref b] = slice_of_refs {}
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:18:9
+ |
+LL | let &[ref a, ..] = &array;
+ | ^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - let &[ref a, ..] = &array;
+LL + let [a, ..] = &array;
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:19:9
+ |
+LL | let &[ref a, ref b, ..] = &array;
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - let &[ref a, ref b, ..] = &array;
+LL + let [a, b, ..] = &array;
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:21:12
+ |
+LL | if let &[ref a, ref b] = slice {}
+ | ^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - if let &[ref a, ref b] = slice {}
+LL + if let [a, b] = slice {}
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:22:12
+ |
+LL | if let &[ref a, ref b] = &vec[..] {}
+ | ^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - if let &[ref a, ref b] = &vec[..] {}
+LL + if let [a, b] = &vec[..] {}
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:24:12
+ |
+LL | if let &[ref a, ref b, ..] = slice {}
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - if let &[ref a, ref b, ..] = slice {}
+LL + if let [a, b, ..] = slice {}
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:25:12
+ |
+LL | if let &[ref a, .., ref b] = slice {}
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - if let &[ref a, .., ref b] = slice {}
+LL + if let [a, .., b] = slice {}
+ |
+
+error: dereferencing a slice pattern where every element takes a reference
+ --> $DIR/needless_borrowed_ref.rs:26:12
+ |
+LL | if let &[.., ref a, ref b] = slice {}
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: try removing the `&` and `ref` parts
+ |
+LL - if let &[.., ref a, ref b] = slice {}
+LL + if let [.., a, b] = slice {}
+ |
-error: aborting due to previous error
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.rs b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
index 12a9ace1e..6d213b46c 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.rs
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::uninlined_format_args)]
+
use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque};
fn main() {
diff --git a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
index 9f0880cc6..99e1b91d8 100644
--- a/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
+++ b/src/tools/clippy/tests/ui/needless_collect_indirect.stderr
@@ -1,5 +1,5 @@
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:5:39
+ --> $DIR/needless_collect_indirect.rs:7:39
|
LL | let indirect_iter = sample.iter().collect::<Vec<_>>();
| ^^^^^^^
@@ -14,7 +14,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>();
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:7:38
+ --> $DIR/needless_collect_indirect.rs:9:38
|
LL | let indirect_len = sample.iter().collect::<VecDeque<_>>();
| ^^^^^^^
@@ -28,7 +28,7 @@ LL ~ sample.iter().count();
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:9:40
+ --> $DIR/needless_collect_indirect.rs:11:40
|
LL | let indirect_empty = sample.iter().collect::<VecDeque<_>>();
| ^^^^^^^
@@ -42,7 +42,7 @@ LL ~ sample.iter().next().is_none();
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:11:43
+ --> $DIR/needless_collect_indirect.rs:13:43
|
LL | let indirect_contains = sample.iter().collect::<VecDeque<_>>();
| ^^^^^^^
@@ -56,7 +56,7 @@ LL ~ sample.iter().any(|x| x == &5);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:23:48
+ --> $DIR/needless_collect_indirect.rs:25:48
|
LL | let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
| ^^^^^^^
@@ -70,7 +70,7 @@ LL ~ sample.into_iter().any(|x| x == a);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:52:51
+ --> $DIR/needless_collect_indirect.rs:54:51
|
LL | let buffer: Vec<&str> = string.split('/').collect();
| ^^^^^^^
@@ -84,7 +84,7 @@ LL ~ string.split('/').count()
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:57:55
+ --> $DIR/needless_collect_indirect.rs:59:55
|
LL | let indirect_len: VecDeque<_> = sample.iter().collect();
| ^^^^^^^
@@ -98,7 +98,7 @@ LL ~ sample.iter().count()
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:62:57
+ --> $DIR/needless_collect_indirect.rs:64:57
|
LL | let indirect_len: LinkedList<_> = sample.iter().collect();
| ^^^^^^^
@@ -112,7 +112,7 @@ LL ~ sample.iter().count()
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:67:57
+ --> $DIR/needless_collect_indirect.rs:69:57
|
LL | let indirect_len: BinaryHeap<_> = sample.iter().collect();
| ^^^^^^^
@@ -126,7 +126,7 @@ LL ~ sample.iter().count()
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:127:59
+ --> $DIR/needless_collect_indirect.rs:129:59
|
LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
| ^^^^^^^
@@ -143,7 +143,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:152:59
+ --> $DIR/needless_collect_indirect.rs:154:59
|
LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
| ^^^^^^^
@@ -160,7 +160,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:181:63
+ --> $DIR/needless_collect_indirect.rs:183:63
|
LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
| ^^^^^^^
@@ -177,7 +177,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:217:59
+ --> $DIR/needless_collect_indirect.rs:219:59
|
LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect();
| ^^^^^^^
@@ -195,7 +195,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n);
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:242:26
+ --> $DIR/needless_collect_indirect.rs:244:26
|
LL | let w = v.iter().collect::<Vec<_>>();
| ^^^^^^^
@@ -211,7 +211,7 @@ LL ~ for _ in 0..v.iter().count() {
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:264:30
+ --> $DIR/needless_collect_indirect.rs:266:30
|
LL | let mut w = v.iter().collect::<Vec<_>>();
| ^^^^^^^
@@ -227,7 +227,7 @@ LL ~ while 1 == v.iter().count() {
|
error: avoid using `collect()` when not needed
- --> $DIR/needless_collect_indirect.rs:286:30
+ --> $DIR/needless_collect_indirect.rs:288:30
|
LL | let mut w = v.iter().collect::<Vec<_>>();
| ^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_continue.rs b/src/tools/clippy/tests/ui/needless_continue.rs
index f105d3d65..c891c9de3 100644
--- a/src/tools/clippy/tests/ui/needless_continue.rs
+++ b/src/tools/clippy/tests/ui/needless_continue.rs
@@ -1,4 +1,5 @@
#![warn(clippy::needless_continue)]
+#![allow(clippy::uninlined_format_args)]
macro_rules! zero {
($x:expr) => {
diff --git a/src/tools/clippy/tests/ui/needless_continue.stderr b/src/tools/clippy/tests/ui/needless_continue.stderr
index b8657c74c..d99989b54 100644
--- a/src/tools/clippy/tests/ui/needless_continue.stderr
+++ b/src/tools/clippy/tests/ui/needless_continue.stderr
@@ -1,5 +1,5 @@
error: this `else` block is redundant
- --> $DIR/needless_continue.rs:29:16
+ --> $DIR/needless_continue.rs:30:16
|
LL | } else {
| ________________^
@@ -7,7 +7,6 @@ LL | | continue;
LL | | }
| |_________^
|
- = note: `-D clippy::needless-continue` implied by `-D warnings`
= help: consider dropping the `else` clause and merging the code that follows (in the loop) with the `if` block
if i % 2 == 0 && i % 3 == 0 {
println!("{}", i);
@@ -33,9 +32,10 @@ LL | | }
}
println!("bleh");
}
+ = note: `-D clippy::needless-continue` implied by `-D warnings`
error: there is no need for an explicit `else` block for this `if` expression
- --> $DIR/needless_continue.rs:44:9
+ --> $DIR/needless_continue.rs:45:9
|
LL | / if (zero!(i % 2) || nonzero!(i % 5)) && i % 3 != 0 {
LL | | continue;
@@ -55,7 +55,7 @@ LL | | }
}
error: this `continue` expression is redundant
- --> $DIR/needless_continue.rs:57:9
+ --> $DIR/needless_continue.rs:58:9
|
LL | continue; // should lint here
| ^^^^^^^^^
@@ -63,7 +63,7 @@ LL | continue; // should lint here
= help: consider dropping the `continue` expression
error: this `continue` expression is redundant
- --> $DIR/needless_continue.rs:64:9
+ --> $DIR/needless_continue.rs:65:9
|
LL | continue; // should lint here
| ^^^^^^^^^
@@ -71,7 +71,7 @@ LL | continue; // should lint here
= help: consider dropping the `continue` expression
error: this `continue` expression is redundant
- --> $DIR/needless_continue.rs:71:9
+ --> $DIR/needless_continue.rs:72:9
|
LL | continue // should lint here
| ^^^^^^^^
@@ -79,7 +79,7 @@ LL | continue // should lint here
= help: consider dropping the `continue` expression
error: this `continue` expression is redundant
- --> $DIR/needless_continue.rs:79:9
+ --> $DIR/needless_continue.rs:80:9
|
LL | continue // should lint here
| ^^^^^^^^
@@ -87,7 +87,7 @@ LL | continue // should lint here
= help: consider dropping the `continue` expression
error: this `else` block is redundant
- --> $DIR/needless_continue.rs:129:24
+ --> $DIR/needless_continue.rs:130:24
|
LL | } else {
| ________________________^
@@ -110,7 +110,7 @@ LL | | }
}
error: there is no need for an explicit `else` block for this `if` expression
- --> $DIR/needless_continue.rs:135:17
+ --> $DIR/needless_continue.rs:136:17
|
LL | / if condition() {
LL | | continue; // should lint here
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
index c1685f7b6..09e671b88 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.fixed
@@ -1,10 +1,11 @@
// run-rustfix
#![warn(clippy::needless_for_each)]
+#![allow(unused)]
#![allow(
- unused,
- clippy::needless_return,
+ clippy::let_unit_value,
clippy::match_single_binding,
- clippy::let_unit_value
+ clippy::needless_return,
+ clippy::uninlined_format_args
)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
index ad17b0956..abb4045b9 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.rs
@@ -1,10 +1,11 @@
// run-rustfix
#![warn(clippy::needless_for_each)]
+#![allow(unused)]
#![allow(
- unused,
- clippy::needless_return,
+ clippy::let_unit_value,
clippy::match_single_binding,
- clippy::let_unit_value
+ clippy::needless_return,
+ clippy::uninlined_format_args
)]
use std::collections::HashMap;
diff --git a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
index 08e995851..aebb762cc 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
+++ b/src/tools/clippy/tests/ui/needless_for_each_fixable.stderr
@@ -1,5 +1,5 @@
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:15:5
+ --> $DIR/needless_for_each_fixable.rs:16:5
|
LL | / v.iter().for_each(|elem| {
LL | | acc += elem;
@@ -15,7 +15,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:18:5
+ --> $DIR/needless_for_each_fixable.rs:19:5
|
LL | / v.into_iter().for_each(|elem| {
LL | | acc += elem;
@@ -30,7 +30,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:22:5
+ --> $DIR/needless_for_each_fixable.rs:23:5
|
LL | / [1, 2, 3].iter().for_each(|elem| {
LL | | acc += elem;
@@ -45,7 +45,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:27:5
+ --> $DIR/needless_for_each_fixable.rs:28:5
|
LL | / hash_map.iter().for_each(|(k, v)| {
LL | | acc += k + v;
@@ -60,7 +60,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:30:5
+ --> $DIR/needless_for_each_fixable.rs:31:5
|
LL | / hash_map.iter_mut().for_each(|(k, v)| {
LL | | acc += *k + *v;
@@ -75,7 +75,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:33:5
+ --> $DIR/needless_for_each_fixable.rs:34:5
|
LL | / hash_map.keys().for_each(|k| {
LL | | acc += k;
@@ -90,7 +90,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:36:5
+ --> $DIR/needless_for_each_fixable.rs:37:5
|
LL | / hash_map.values().for_each(|v| {
LL | | acc += v;
@@ -105,7 +105,7 @@ LL + }
|
error: needless use of `for_each`
- --> $DIR/needless_for_each_fixable.rs:43:5
+ --> $DIR/needless_for_each_fixable.rs:44:5
|
LL | / my_vec().iter().for_each(|elem| {
LL | | acc += elem;
diff --git a/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs b/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs
index d765d7dab..282c72881 100644
--- a/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs
+++ b/src/tools/clippy/tests/ui/needless_for_each_unfixable.rs
@@ -1,5 +1,5 @@
#![warn(clippy::needless_for_each)]
-#![allow(clippy::needless_return)]
+#![allow(clippy::needless_return, clippy::uninlined_format_args)]
fn main() {
let v: Vec<i32> = Vec::new();
diff --git a/src/tools/clippy/tests/ui/needless_late_init.fixed b/src/tools/clippy/tests/ui/needless_late_init.fixed
index fee8e3030..17f2227ba 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.fixed
+++ b/src/tools/clippy/tests/ui/needless_late_init.fixed
@@ -1,12 +1,13 @@
// run-rustfix
#![feature(let_chains)]
+#![allow(unused)]
#![allow(
- unused,
clippy::assign_op_pattern,
clippy::blocks_in_if_conditions,
clippy::let_and_return,
clippy::let_unit_value,
- clippy::nonminimal_bool
+ clippy::nonminimal_bool,
+ clippy::uninlined_format_args
)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
diff --git a/src/tools/clippy/tests/ui/needless_late_init.rs b/src/tools/clippy/tests/ui/needless_late_init.rs
index 402d9f9ef..d84457a29 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.rs
+++ b/src/tools/clippy/tests/ui/needless_late_init.rs
@@ -1,12 +1,13 @@
// run-rustfix
#![feature(let_chains)]
+#![allow(unused)]
#![allow(
- unused,
clippy::assign_op_pattern,
clippy::blocks_in_if_conditions,
clippy::let_and_return,
clippy::let_unit_value,
- clippy::nonminimal_bool
+ clippy::nonminimal_bool,
+ clippy::uninlined_format_args
)]
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
diff --git a/src/tools/clippy/tests/ui/needless_late_init.stderr b/src/tools/clippy/tests/ui/needless_late_init.stderr
index 313cdbbeb..0a256fb4a 100644
--- a/src/tools/clippy/tests/ui/needless_late_init.stderr
+++ b/src/tools/clippy/tests/ui/needless_late_init.stderr
@@ -1,5 +1,5 @@
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:23:5
+ --> $DIR/needless_late_init.rs:24:5
|
LL | let a;
| ^^^^^^ created here
@@ -13,7 +13,7 @@ LL | let a = "zero";
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:26:5
+ --> $DIR/needless_late_init.rs:27:5
|
LL | let b;
| ^^^^^^ created here
@@ -27,7 +27,7 @@ LL | let b = 1;
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:27:5
+ --> $DIR/needless_late_init.rs:28:5
|
LL | let c;
| ^^^^^^ created here
@@ -41,7 +41,7 @@ LL | let c = 2;
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:31:5
+ --> $DIR/needless_late_init.rs:32:5
|
LL | let d: usize;
| ^^^^^^^^^^^^^ created here
@@ -54,7 +54,7 @@ LL | let d: usize = 1;
| ~~~~~~~~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:34:5
+ --> $DIR/needless_late_init.rs:35:5
|
LL | let e;
| ^^^^^^ created here
@@ -67,7 +67,7 @@ LL | let e = format!("{}", d);
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:39:5
+ --> $DIR/needless_late_init.rs:40:5
|
LL | let a;
| ^^^^^^
@@ -88,7 +88,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:48:5
+ --> $DIR/needless_late_init.rs:49:5
|
LL | let b;
| ^^^^^^
@@ -109,7 +109,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:55:5
+ --> $DIR/needless_late_init.rs:56:5
|
LL | let d;
| ^^^^^^
@@ -130,7 +130,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:63:5
+ --> $DIR/needless_late_init.rs:64:5
|
LL | let e;
| ^^^^^^
@@ -151,7 +151,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:70:5
+ --> $DIR/needless_late_init.rs:71:5
|
LL | let f;
| ^^^^^^
@@ -167,7 +167,7 @@ LL + 1 => "three",
|
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:76:5
+ --> $DIR/needless_late_init.rs:77:5
|
LL | let g: usize;
| ^^^^^^^^^^^^^
@@ -187,7 +187,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:84:5
+ --> $DIR/needless_late_init.rs:85:5
|
LL | let x;
| ^^^^^^ created here
@@ -201,7 +201,7 @@ LL | let x = 1;
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:88:5
+ --> $DIR/needless_late_init.rs:89:5
|
LL | let x;
| ^^^^^^ created here
@@ -215,7 +215,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:92:5
+ --> $DIR/needless_late_init.rs:93:5
|
LL | let x;
| ^^^^^^ created here
@@ -229,7 +229,7 @@ LL | let x = SignificantDrop;
| ~~~~~
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:111:5
+ --> $DIR/needless_late_init.rs:112:5
|
LL | let a;
| ^^^^^^
@@ -250,7 +250,7 @@ LL | };
| +
error: unneeded late initialization
- --> $DIR/needless_late_init.rs:128:5
+ --> $DIR/needless_late_init.rs:129:5
|
LL | let a;
| ^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.rs b/src/tools/clippy/tests/ui/needless_pass_by_value.rs
index 5a35b100a..d79ad86b1 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_value.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_value.rs
@@ -1,10 +1,11 @@
#![warn(clippy::needless_pass_by_value)]
+#![allow(dead_code)]
#![allow(
- dead_code,
- clippy::single_match,
- clippy::redundant_pattern_matching,
clippy::option_option,
- clippy::redundant_clone
+ clippy::redundant_clone,
+ clippy::redundant_pattern_matching,
+ clippy::single_match,
+ clippy::uninlined_format_args
)]
use std::borrow::Borrow;
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
index 38f33c53f..0e660a77d 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_value.stderr
@@ -1,5 +1,5 @@
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:17:23
+ --> $DIR/needless_pass_by_value.rs:18:23
|
LL | fn foo<T: Default>(v: Vec<T>, w: Vec<T>, mut x: Vec<T>, y: Vec<T>) -> Vec<T> {
| ^^^^^^ help: consider changing the type to: `&[T]`
@@ -7,55 +7,55 @@ LL | fn foo<T: Default>(v: Vec<T>, w: Vec<T>, mut x: Vec<T>, y: Vec<T>) -> Vec<T
= note: `-D clippy::needless-pass-by-value` implied by `-D warnings`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:31:11
+ --> $DIR/needless_pass_by_value.rs:32:11
|
LL | fn bar(x: String, y: Wrapper) {
| ^^^^^^ help: consider changing the type to: `&str`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:31:22
+ --> $DIR/needless_pass_by_value.rs:32:22
|
LL | fn bar(x: String, y: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:37:71
+ --> $DIR/needless_pass_by_value.rs:38:71
|
LL | fn test_borrow_trait<T: Borrow<str>, U: AsRef<str>, V>(t: T, u: U, v: V) {
| ^ help: consider taking a reference instead: `&V`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:49:18
+ --> $DIR/needless_pass_by_value.rs:50:18
|
LL | fn test_match(x: Option<Option<String>>, y: Option<Option<String>>) {
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&Option<Option<String>>`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:62:24
+ --> $DIR/needless_pass_by_value.rs:63:24
|
LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:62:36
+ --> $DIR/needless_pass_by_value.rs:63:36
|
LL | fn test_destructure(x: Wrapper, y: Wrapper, z: Wrapper) {
| ^^^^^^^ help: consider taking a reference instead: `&Wrapper`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:78:49
+ --> $DIR/needless_pass_by_value.rs:79:49
|
LL | fn test_blanket_ref<T: Foo, S: Serialize>(_foo: T, _serializable: S) {}
| ^ help: consider taking a reference instead: `&T`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:80:18
+ --> $DIR/needless_pass_by_value.rs:81:18
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^ help: consider taking a reference instead: `&String`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:80:29
+ --> $DIR/needless_pass_by_value.rs:81:29
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^
@@ -70,13 +70,13 @@ LL | let _ = t.to_string();
| ~~~~~~~~~~~~~
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:80:40
+ --> $DIR/needless_pass_by_value.rs:81:40
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^^^ help: consider taking a reference instead: `&Vec<i32>`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:80:53
+ --> $DIR/needless_pass_by_value.rs:81:53
|
LL | fn issue_2114(s: String, t: String, u: Vec<i32>, v: Vec<i32>) {
| ^^^^^^^^
@@ -91,85 +91,85 @@ LL | let _ = v.to_owned();
| ~~~~~~~~~~~~
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:93:12
+ --> $DIR/needless_pass_by_value.rs:94:12
|
LL | s: String,
| ^^^^^^ help: consider changing the type to: `&str`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:94:12
+ --> $DIR/needless_pass_by_value.rs:95:12
|
LL | t: String,
| ^^^^^^ help: consider taking a reference instead: `&String`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:103:23
+ --> $DIR/needless_pass_by_value.rs:104:23
|
LL | fn baz(&self, _u: U, _s: Self) {}
| ^ help: consider taking a reference instead: `&U`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:103:30
+ --> $DIR/needless_pass_by_value.rs:104:30
|
LL | fn baz(&self, _u: U, _s: Self) {}
| ^^^^ help: consider taking a reference instead: `&Self`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:125:24
+ --> $DIR/needless_pass_by_value.rs:126:24
|
LL | fn bar_copy(x: u32, y: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: consider marking this type as `Copy`
- --> $DIR/needless_pass_by_value.rs:123:1
+ --> $DIR/needless_pass_by_value.rs:124:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:131:29
+ --> $DIR/needless_pass_by_value.rs:132:29
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: consider marking this type as `Copy`
- --> $DIR/needless_pass_by_value.rs:123:1
+ --> $DIR/needless_pass_by_value.rs:124:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:131:45
+ --> $DIR/needless_pass_by_value.rs:132:45
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: consider marking this type as `Copy`
- --> $DIR/needless_pass_by_value.rs:123:1
+ --> $DIR/needless_pass_by_value.rs:124:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:131:61
+ --> $DIR/needless_pass_by_value.rs:132:61
|
LL | fn test_destructure_copy(x: CopyWrapper, y: CopyWrapper, z: CopyWrapper) {
| ^^^^^^^^^^^ help: consider taking a reference instead: `&CopyWrapper`
|
help: consider marking this type as `Copy`
- --> $DIR/needless_pass_by_value.rs:123:1
+ --> $DIR/needless_pass_by_value.rs:124:1
|
LL | struct CopyWrapper(u32);
| ^^^^^^^^^^^^^^^^^^
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:143:40
+ --> $DIR/needless_pass_by_value.rs:144:40
|
LL | fn some_fun<'b, S: Bar<'b, ()>>(_item: S) {}
| ^ help: consider taking a reference instead: `&S`
error: this argument is passed by value, but not consumed in the function body
- --> $DIR/needless_pass_by_value.rs:148:20
+ --> $DIR/needless_pass_by_value.rs:149:20
|
LL | fn more_fun(_item: impl Club<'static, i32>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider taking a reference instead: `&impl Club<'static, i32>`
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.rs b/src/tools/clippy/tests/ui/needless_range_loop.rs
index 3fce34367..921801138 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.rs
+++ b/src/tools/clippy/tests/ui/needless_range_loop.rs
@@ -1,4 +1,5 @@
#![warn(clippy::needless_range_loop)]
+#![allow(clippy::uninlined_format_args)]
static STATIC: [usize; 4] = [0, 1, 8, 16];
const CONST: [usize; 4] = [0, 1, 8, 16];
diff --git a/src/tools/clippy/tests/ui/needless_range_loop.stderr b/src/tools/clippy/tests/ui/needless_range_loop.stderr
index a86cc69df..b31544ec3 100644
--- a/src/tools/clippy/tests/ui/needless_range_loop.stderr
+++ b/src/tools/clippy/tests/ui/needless_range_loop.stderr
@@ -1,5 +1,5 @@
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:10:14
+ --> $DIR/needless_range_loop.rs:11:14
|
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
@@ -11,7 +11,7 @@ LL | for <item> in &vec {
| ~~~~~~ ~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:19:14
+ --> $DIR/needless_range_loop.rs:20:14
|
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | for <item> in &vec {
| ~~~~~~ ~~~~
error: the loop variable `j` is only used to index `STATIC`
- --> $DIR/needless_range_loop.rs:24:14
+ --> $DIR/needless_range_loop.rs:25:14
|
LL | for j in 0..4 {
| ^^^^
@@ -33,7 +33,7 @@ LL | for <item> in &STATIC {
| ~~~~~~ ~~~~~~~
error: the loop variable `j` is only used to index `CONST`
- --> $DIR/needless_range_loop.rs:28:14
+ --> $DIR/needless_range_loop.rs:29:14
|
LL | for j in 0..4 {
| ^^^^
@@ -44,7 +44,7 @@ LL | for <item> in &CONST {
| ~~~~~~ ~~~~~~
error: the loop variable `i` is used to index `vec`
- --> $DIR/needless_range_loop.rs:32:14
+ --> $DIR/needless_range_loop.rs:33:14
|
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL | for (i, <item>) in vec.iter().enumerate() {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec2`
- --> $DIR/needless_range_loop.rs:40:14
+ --> $DIR/needless_range_loop.rs:41:14
|
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
@@ -66,7 +66,7 @@ LL | for <item> in vec2.iter().take(vec.len()) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:44:14
+ --> $DIR/needless_range_loop.rs:45:14
|
LL | for i in 5..vec.len() {
| ^^^^^^^^^^^^
@@ -77,7 +77,7 @@ LL | for <item> in vec.iter().skip(5) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:48:14
+ --> $DIR/needless_range_loop.rs:49:14
|
LL | for i in 0..MAX_LEN {
| ^^^^^^^^^^
@@ -88,7 +88,7 @@ LL | for <item> in vec.iter().take(MAX_LEN) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:52:14
+ --> $DIR/needless_range_loop.rs:53:14
|
LL | for i in 0..=MAX_LEN {
| ^^^^^^^^^^^
@@ -99,7 +99,7 @@ LL | for <item> in vec.iter().take(MAX_LEN + 1) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:56:14
+ --> $DIR/needless_range_loop.rs:57:14
|
LL | for i in 5..10 {
| ^^^^^
@@ -110,7 +110,7 @@ LL | for <item> in vec.iter().take(10).skip(5) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is only used to index `vec`
- --> $DIR/needless_range_loop.rs:60:14
+ --> $DIR/needless_range_loop.rs:61:14
|
LL | for i in 5..=10 {
| ^^^^^^
@@ -121,7 +121,7 @@ LL | for <item> in vec.iter().take(10 + 1).skip(5) {
| ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is used to index `vec`
- --> $DIR/needless_range_loop.rs:64:14
+ --> $DIR/needless_range_loop.rs:65:14
|
LL | for i in 5..vec.len() {
| ^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL | for (i, <item>) in vec.iter().enumerate().skip(5) {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is used to index `vec`
- --> $DIR/needless_range_loop.rs:68:14
+ --> $DIR/needless_range_loop.rs:69:14
|
LL | for i in 5..10 {
| ^^^^^
@@ -143,7 +143,7 @@ LL | for (i, <item>) in vec.iter().enumerate().take(10).skip(5) {
| ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: the loop variable `i` is used to index `vec`
- --> $DIR/needless_range_loop.rs:73:14
+ --> $DIR/needless_range_loop.rs:74:14
|
LL | for i in 0..vec.len() {
| ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/needless_return.fixed b/src/tools/clippy/tests/ui/needless_return.fixed
index 695883e8d..d2163b14f 100644
--- a/src/tools/clippy/tests/ui/needless_return.fixed
+++ b/src/tools/clippy/tests/ui/needless_return.fixed
@@ -232,4 +232,41 @@ fn issue_9361() -> i32 {
return 1 + 2;
}
+fn issue8336(x: i32) -> bool {
+ if x > 0 {
+ println!("something");
+ true
+ } else {
+ false
+ }
+}
+
+fn issue8156(x: u8) -> u64 {
+ match x {
+ 80 => {
+ 10
+ },
+ _ => {
+ 100
+ },
+ }
+}
+
+// Ideally the compiler should throw `unused_braces` in this case
+fn issue9192() -> i32 {
+ {
+ 0
+ }
+}
+
+fn issue9503(x: usize) -> isize {
+ unsafe {
+ if x > 12 {
+ *(x as *const isize)
+ } else {
+ !*(x as *const isize)
+ }
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.rs b/src/tools/clippy/tests/ui/needless_return.rs
index 63d9fe9ec..114414b5f 100644
--- a/src/tools/clippy/tests/ui/needless_return.rs
+++ b/src/tools/clippy/tests/ui/needless_return.rs
@@ -232,4 +232,41 @@ fn issue_9361() -> i32 {
return 1 + 2;
}
+fn issue8336(x: i32) -> bool {
+ if x > 0 {
+ println!("something");
+ return true;
+ } else {
+ return false;
+ };
+}
+
+fn issue8156(x: u8) -> u64 {
+ match x {
+ 80 => {
+ return 10;
+ },
+ _ => {
+ return 100;
+ },
+ };
+}
+
+// Ideally the compiler should throw `unused_braces` in this case
+fn issue9192() -> i32 {
+ {
+ return 0;
+ };
+}
+
+fn issue9503(x: usize) -> isize {
+ unsafe {
+ if x > 12 {
+ return *(x as *const isize);
+ } else {
+ return !*(x as *const isize);
+ };
+ };
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/needless_return.stderr b/src/tools/clippy/tests/ui/needless_return.stderr
index cadee6e00..047fb6c23 100644
--- a/src/tools/clippy/tests/ui/needless_return.stderr
+++ b/src/tools/clippy/tests/ui/needless_return.stderr
@@ -2,225 +2,354 @@ error: unneeded `return` statement
--> $DIR/needless_return.rs:26:5
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
|
= note: `-D clippy::needless-return` implied by `-D warnings`
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:30:5
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:35:9
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:37:9
|
LL | return false;
- | ^^^^^^^^^^^^^ help: remove `return`: `false`
+ | ^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:43:17
|
LL | true => return false,
- | ^^^^^^^^^^^^ help: remove `return`: `false`
+ | ^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:45:13
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:52:9
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:54:16
|
LL | let _ = || return true;
- | ^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:58:5
|
LL | return the_answer!();
- | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:62:5
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:67:9
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:69:9
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:76:14
|
LL | _ => return,
- | ^^^^^^ help: replace `return` with a unit value: `()`
+ | ^^^^^^
+ |
+ = help: replace `return` with a unit value
error: unneeded `return` statement
--> $DIR/needless_return.rs:85:13
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:87:14
|
LL | _ => return,
- | ^^^^^^ help: replace `return` with a unit value: `()`
+ | ^^^^^^
+ |
+ = help: replace `return` with a unit value
error: unneeded `return` statement
--> $DIR/needless_return.rs:100:9
|
LL | return String::from("test");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:102:9
|
LL | return String::new();
- | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:124:32
|
LL | bar.unwrap_or_else(|_| return)
- | ^^^^^^ help: replace `return` with an empty block: `{}`
+ | ^^^^^^
+ |
+ = help: replace `return` with an empty block
error: unneeded `return` statement
--> $DIR/needless_return.rs:129:13
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:131:20
|
LL | let _ = || return;
- | ^^^^^^ help: replace `return` with an empty block: `{}`
+ | ^^^^^^
+ |
+ = help: replace `return` with an empty block
error: unneeded `return` statement
--> $DIR/needless_return.rs:137:32
|
LL | res.unwrap_or_else(|_| return Foo)
- | ^^^^^^^^^^ help: remove `return`: `Foo`
+ | ^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:146:5
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:150:5
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:155:9
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:157:9
|
LL | return false;
- | ^^^^^^^^^^^^^ help: remove `return`: `false`
+ | ^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:163:17
|
LL | true => return false,
- | ^^^^^^^^^^^^ help: remove `return`: `false`
+ | ^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:165:13
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:172:9
|
LL | return true;
- | ^^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:174:16
|
LL | let _ = || return true;
- | ^^^^^^^^^^^ help: remove `return`: `true`
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:178:5
|
LL | return the_answer!();
- | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `the_answer!()`
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:182:5
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:187:9
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:189:9
|
LL | return;
- | ^^^^^^^ help: remove `return`
+ | ^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:196:14
|
LL | _ => return,
- | ^^^^^^ help: replace `return` with a unit value: `()`
+ | ^^^^^^
+ |
+ = help: replace `return` with a unit value
error: unneeded `return` statement
--> $DIR/needless_return.rs:209:9
|
LL | return String::from("test");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::from("test")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:211:9
|
LL | return String::new();
- | ^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `String::new()`
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
error: unneeded `return` statement
--> $DIR/needless_return.rs:227:5
|
LL | return format!("Hello {}", "world!");
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove `return`: `format!("Hello {}", "world!")`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:238:9
+ |
+LL | return true;
+ | ^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:240:9
+ |
+LL | return false;
+ | ^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:247:13
+ |
+LL | return 10;
+ | ^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:250:13
+ |
+LL | return 100;
+ | ^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:258:9
+ |
+LL | return 0;
+ | ^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:265:13
+ |
+LL | return *(x as *const isize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
+
+error: unneeded `return` statement
+ --> $DIR/needless_return.rs:267:13
+ |
+LL | return !*(x as *const isize);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: remove `return`
-error: aborting due to 37 previous errors
+error: aborting due to 44 previous errors
diff --git a/src/tools/clippy/tests/ui/never_loop.rs b/src/tools/clippy/tests/ui/never_loop.rs
index 0a21589dd..3dbef1989 100644
--- a/src/tools/clippy/tests/ui/never_loop.rs
+++ b/src/tools/clippy/tests/ui/never_loop.rs
@@ -203,6 +203,32 @@ pub fn test17() {
};
}
+// Issue #9356: `continue` in else branch of let..else
+pub fn test18() {
+ let x = Some(0);
+ let y = 0;
+ // might loop
+ let _ = loop {
+ let Some(x) = x else {
+ if y > 0 {
+ continue;
+ } else {
+ return;
+ }
+ };
+
+ break x;
+ };
+ // never loops
+ let _ = loop {
+ let Some(x) = x else {
+ return;
+ };
+
+ break x;
+ };
+}
+
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 f49b23924..3033f0192 100644
--- a/src/tools/clippy/tests/ui/never_loop.stderr
+++ b/src/tools/clippy/tests/ui/never_loop.stderr
@@ -101,5 +101,18 @@ LL | | break 'label;
LL | | }
| |_________^
-error: aborting due to 9 previous errors
+error: this loop never actually loops
+ --> $DIR/never_loop.rs:223:13
+ |
+LL | let _ = loop {
+ | _____________^
+LL | | let Some(x) = x else {
+LL | | return;
+LL | | };
+LL | |
+LL | | break x;
+LL | | };
+ | |_____^
+
+error: aborting due to 10 previous errors
diff --git a/src/tools/clippy/tests/ui/no_effect.rs b/src/tools/clippy/tests/ui/no_effect.rs
index fdefb11ae..f08eb092e 100644
--- a/src/tools/clippy/tests/ui/no_effect.rs
+++ b/src/tools/clippy/tests/ui/no_effect.rs
@@ -1,9 +1,7 @@
#![feature(box_syntax, fn_traits, unboxed_closures)]
#![warn(clippy::no_effect_underscore_binding)]
-#![allow(dead_code)]
-#![allow(path_statements)]
-#![allow(clippy::deref_addrof)]
-#![allow(clippy::redundant_field_names)]
+#![allow(dead_code, path_statements)]
+#![allow(clippy::deref_addrof, clippy::redundant_field_names, clippy::uninlined_format_args)]
struct Unit;
struct Tuple(i32);
diff --git a/src/tools/clippy/tests/ui/no_effect.stderr b/src/tools/clippy/tests/ui/no_effect.stderr
index 328d2555c..6a1e636f9 100644
--- a/src/tools/clippy/tests/ui/no_effect.stderr
+++ b/src/tools/clippy/tests/ui/no_effect.stderr
@@ -1,5 +1,5 @@
error: statement with no effect
- --> $DIR/no_effect.rs:94:5
+ --> $DIR/no_effect.rs:92:5
|
LL | 0;
| ^^
@@ -7,157 +7,157 @@ LL | 0;
= note: `-D clippy::no-effect` implied by `-D warnings`
error: statement with no effect
- --> $DIR/no_effect.rs:95:5
+ --> $DIR/no_effect.rs:93:5
|
LL | s2;
| ^^^
error: statement with no effect
- --> $DIR/no_effect.rs:96:5
+ --> $DIR/no_effect.rs:94:5
|
LL | Unit;
| ^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:97:5
+ --> $DIR/no_effect.rs:95:5
|
LL | Tuple(0);
| ^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:98:5
+ --> $DIR/no_effect.rs:96:5
|
LL | Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:99:5
+ --> $DIR/no_effect.rs:97:5
|
LL | Struct { ..s };
| ^^^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:100:5
+ --> $DIR/no_effect.rs:98:5
|
LL | Union { a: 0 };
| ^^^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:101:5
+ --> $DIR/no_effect.rs:99:5
|
LL | Enum::Tuple(0);
| ^^^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:102:5
+ --> $DIR/no_effect.rs:100:5
|
LL | Enum::Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:103:5
+ --> $DIR/no_effect.rs:101:5
|
LL | 5 + 6;
| ^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:104:5
+ --> $DIR/no_effect.rs:102:5
|
LL | *&42;
| ^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:105:5
+ --> $DIR/no_effect.rs:103:5
|
LL | &6;
| ^^^
error: statement with no effect
- --> $DIR/no_effect.rs:106:5
+ --> $DIR/no_effect.rs:104:5
|
LL | (5, 6, 7);
| ^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:107:5
+ --> $DIR/no_effect.rs:105:5
|
LL | box 42;
| ^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:108:5
+ --> $DIR/no_effect.rs:106:5
|
LL | ..;
| ^^^
error: statement with no effect
- --> $DIR/no_effect.rs:109:5
+ --> $DIR/no_effect.rs:107:5
|
LL | 5..;
| ^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:110:5
+ --> $DIR/no_effect.rs:108:5
|
LL | ..5;
| ^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:111:5
+ --> $DIR/no_effect.rs:109:5
|
LL | 5..6;
| ^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:112:5
+ --> $DIR/no_effect.rs:110:5
|
LL | 5..=6;
| ^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:113:5
+ --> $DIR/no_effect.rs:111:5
|
LL | [42, 55];
| ^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:114:5
+ --> $DIR/no_effect.rs:112:5
|
LL | [42, 55][1];
| ^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:115:5
+ --> $DIR/no_effect.rs:113:5
|
LL | (42, 55).1;
| ^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:116:5
+ --> $DIR/no_effect.rs:114:5
|
LL | [42; 55];
| ^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:117:5
+ --> $DIR/no_effect.rs:115:5
|
LL | [42; 55][13];
| ^^^^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:119:5
+ --> $DIR/no_effect.rs:117:5
|
LL | || x += 5;
| ^^^^^^^^^^
error: statement with no effect
- --> $DIR/no_effect.rs:121:5
+ --> $DIR/no_effect.rs:119:5
|
LL | FooString { s: s };
| ^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect
- --> $DIR/no_effect.rs:122:5
+ --> $DIR/no_effect.rs:120:5
|
LL | let _unused = 1;
| ^^^^^^^^^^^^^^^^
@@ -165,19 +165,19 @@ LL | let _unused = 1;
= note: `-D clippy::no-effect-underscore-binding` implied by `-D warnings`
error: binding to `_` prefixed variable with no side-effect
- --> $DIR/no_effect.rs:123:5
+ --> $DIR/no_effect.rs:121:5
|
LL | let _penguin = || println!("Some helpful closure");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect
- --> $DIR/no_effect.rs:124:5
+ --> $DIR/no_effect.rs:122:5
|
LL | let _duck = Struct { field: 0 };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: binding to `_` prefixed variable with no side-effect
- --> $DIR/no_effect.rs:125:5
+ --> $DIR/no_effect.rs:123:5
|
LL | let _cat = [2, 4, 6, 8][2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr
index b6c904a14..e912b59a6 100644
--- a/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr
+++ b/src/tools/clippy/tests/ui/non_send_fields_in_send_ty.stderr
@@ -4,13 +4,13 @@ error: some fields in `RingBuffer<T>` are not safe to be sent to another thread
LL | unsafe impl<T> Send for RingBuffer<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings`
note: it is not safe to send field `data` to another thread
--> $DIR/non_send_fields_in_send_ty.rs:12:5
|
LL | data: Vec<UnsafeCell<T>>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
= help: add bounds on type parameter `T` that satisfy `Vec<UnsafeCell<T>>: Send`
+ = note: `-D clippy::non-send-fields-in-send-ty` implied by `-D warnings`
error: some fields in `MvccRwLock<T>` are not safe to be sent to another thread
--> $DIR/non_send_fields_in_send_ty.rs:25:1
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.rs b/src/tools/clippy/tests/ui/nonminimal_bool.rs
index 24ae62bb0..e9b4367ca 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.rs
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.rs
@@ -57,3 +57,9 @@ fn check_expect() {
#[expect(clippy::nonminimal_bool)]
let _ = !!a;
}
+
+fn issue9428() {
+ if matches!(true, true) && true {
+ println!("foo");
+ }
+}
diff --git a/src/tools/clippy/tests/ui/nonminimal_bool.stderr b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
index fc6a5ce1d..91b5805aa 100644
--- a/src/tools/clippy/tests/ui/nonminimal_bool.stderr
+++ b/src/tools/clippy/tests/ui/nonminimal_bool.stderr
@@ -107,5 +107,11 @@ LL | let _ = !(a == b || c == d);
LL | let _ = a != b && c != d;
| ~~~~~~~~~~~~~~~~
-error: aborting due to 12 previous errors
+error: this boolean expression can be simplified
+ --> $DIR/nonminimal_bool.rs:62:8
+ |
+LL | if matches!(true, true) && true {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(true, true)`
+
+error: aborting due to 13 previous errors
diff --git a/src/tools/clippy/tests/ui/octal_escapes.stderr b/src/tools/clippy/tests/ui/octal_escapes.stderr
index 54f5bbb0f..295dc1798 100644
--- a/src/tools/clippy/tests/ui/octal_escapes.stderr
+++ b/src/tools/clippy/tests/ui/octal_escapes.stderr
@@ -4,8 +4,8 @@ error: octal-looking escape in string literal
LL | let _bad1 = "/033[0m";
| ^^^^^^^^^
|
- = note: `-D clippy::octal-escapes` implied by `-D warnings`
= help: octal escapes are not supported, `/0` is always a null character
+ = note: `-D clippy::octal-escapes` implied by `-D warnings`
help: if an octal escape was intended, use the hexadecimal representation instead
|
LL | let _bad1 = "/x1b[0m";
diff --git a/src/tools/clippy/tests/ui/ok_expect.stderr b/src/tools/clippy/tests/ui/ok_expect.stderr
index b02b28e7f..6c40adbb5 100644
--- a/src/tools/clippy/tests/ui/ok_expect.stderr
+++ b/src/tools/clippy/tests/ui/ok_expect.stderr
@@ -4,8 +4,8 @@ error: called `ok().expect()` on a `Result` value
LL | res.ok().expect("disaster!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::ok-expect` implied by `-D warnings`
= help: you can call `expect()` directly on the `Result`
+ = note: `-D clippy::ok-expect` implied by `-D warnings`
error: called `ok().expect()` on a `Result` value
--> $DIR/ok_expect.rs:20:5
diff --git a/src/tools/clippy/tests/ui/only_used_in_recursion.stderr b/src/tools/clippy/tests/ui/only_used_in_recursion.stderr
index 74057ddcf..571e5c4b5 100644
--- a/src/tools/clippy/tests/ui/only_used_in_recursion.stderr
+++ b/src/tools/clippy/tests/ui/only_used_in_recursion.stderr
@@ -4,12 +4,12 @@ error: parameter is only used in recursion
LL | fn _one_unused(flag: u32, a: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
|
- = note: `-D clippy::only-used-in-recursion` implied by `-D warnings`
note: parameter used here
--> $DIR/only_used_in_recursion.rs:12:53
|
LL | if flag == 0 { 0 } else { _one_unused(flag - 1, a) }
| ^
+ = note: `-D clippy::only-used-in-recursion` implied by `-D warnings`
error: parameter is only used in recursion
--> $DIR/only_used_in_recursion.rs:15:27
diff --git a/src/tools/clippy/tests/ui/only_used_in_recursion2.stderr b/src/tools/clippy/tests/ui/only_used_in_recursion2.stderr
index 23f6ffd30..8dcbfdd61 100644
--- a/src/tools/clippy/tests/ui/only_used_in_recursion2.stderr
+++ b/src/tools/clippy/tests/ui/only_used_in_recursion2.stderr
@@ -4,12 +4,12 @@ error: parameter is only used in recursion
LL | fn _with_inner(flag: u32, a: u32, b: u32) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`
|
- = note: `-D clippy::only-used-in-recursion` implied by `-D warnings`
note: parameter used here
--> $DIR/only_used_in_recursion2.rs:9:52
|
LL | if flag == 0 { 0 } else { _with_inner(flag, a, b + x) }
| ^
+ = note: `-D clippy::only-used-in-recursion` implied by `-D warnings`
error: parameter is only used in recursion
--> $DIR/only_used_in_recursion2.rs:4:25
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
index 07d7f0b45..bc376d0d7 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.fixed
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused_imports, clippy::redundant_clone)]
+#![feature(custom_inner_attributes)]
+#![allow(unused, clippy::redundant_clone)]
#![warn(clippy::option_as_ref_deref)]
use std::ffi::{CString, OsString};
@@ -42,3 +43,17 @@ fn main() {
// Issue #5927
let _ = opt.as_deref();
}
+
+fn msrv_1_39() {
+ #![clippy::msrv = "1.39"]
+
+ let opt = Some(String::from("123"));
+ let _ = opt.as_ref().map(String::as_str);
+}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ let opt = Some(String::from("123"));
+ let _ = opt.as_deref();
+}
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.rs b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
index 6ae059c94..ba3a2eedc 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.rs
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.rs
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused_imports, clippy::redundant_clone)]
+#![feature(custom_inner_attributes)]
+#![allow(unused, clippy::redundant_clone)]
#![warn(clippy::option_as_ref_deref)]
use std::ffi::{CString, OsString};
@@ -45,3 +46,17 @@ fn main() {
// Issue #5927
let _ = opt.as_ref().map(std::ops::Deref::deref);
}
+
+fn msrv_1_39() {
+ #![clippy::msrv = "1.39"]
+
+ let opt = Some(String::from("123"));
+ let _ = opt.as_ref().map(String::as_str);
+}
+
+fn msrv_1_40() {
+ #![clippy::msrv = "1.40"]
+
+ let opt = Some(String::from("123"));
+ let _ = opt.as_ref().map(String::as_str);
+}
diff --git a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
index 62f282324..7de8b3b6b 100644
--- a/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
+++ b/src/tools/clippy/tests/ui/option_as_ref_deref.stderr
@@ -1,5 +1,5 @@
error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:13:13
+ --> $DIR/option_as_ref_deref.rs:14:13
|
LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.clone().as_deref()`
@@ -7,7 +7,7 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len);
= note: `-D clippy::option-as-ref-deref` implied by `-D warnings`
error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:16:13
+ --> $DIR/option_as_ref_deref.rs:17:13
|
LL | let _ = opt.clone()
| _____________^
@@ -17,94 +17,100 @@ LL | | )
| |_________^ help: try using as_deref instead: `opt.clone().as_deref()`
error: called `.as_mut().map(DerefMut::deref_mut)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:22:13
+ --> $DIR/option_as_ref_deref.rs:23:13
|
LL | let _ = opt.as_mut().map(DerefMut::deref_mut);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:24:13
+ --> $DIR/option_as_ref_deref.rs:25:13
|
LL | let _ = opt.as_ref().map(String::as_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
error: called `.as_ref().map(|x| x.as_str())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:25:13
+ --> $DIR/option_as_ref_deref.rs:26:13
|
LL | let _ = opt.as_ref().map(|x| x.as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
error: called `.as_mut().map(String::as_mut_str)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:26:13
+ --> $DIR/option_as_ref_deref.rs:27:13
|
LL | let _ = opt.as_mut().map(String::as_mut_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
error: called `.as_mut().map(|x| x.as_mut_str())` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:27:13
+ --> $DIR/option_as_ref_deref.rs:28:13
|
LL | let _ = opt.as_mut().map(|x| x.as_mut_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
error: called `.as_ref().map(CString::as_c_str)` on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:28:13
+ --> $DIR/option_as_ref_deref.rs:29:13
|
LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()`
error: called `.as_ref().map(OsString::as_os_str)` on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:29:13
+ --> $DIR/option_as_ref_deref.rs:30:13
|
LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()`
error: called `.as_ref().map(PathBuf::as_path)` on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:30:13
+ --> $DIR/option_as_ref_deref.rs:31:13
|
LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()`
error: called `.as_ref().map(Vec::as_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:31:13
+ --> $DIR/option_as_ref_deref.rs:32:13
|
LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()`
error: called `.as_mut().map(Vec::as_mut_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:32:13
+ --> $DIR/option_as_ref_deref.rs:33:13
|
LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()`
error: called `.as_ref().map(|x| x.deref())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:34:13
+ --> $DIR/option_as_ref_deref.rs:35:13
|
LL | let _ = opt.as_ref().map(|x| x.deref());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
error: called `.as_mut().map(|x| x.deref_mut())` on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:35:13
+ --> $DIR/option_as_ref_deref.rs:36:13
|
LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()`
error: called `.as_ref().map(|x| &**x)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:42:13
+ --> $DIR/option_as_ref_deref.rs:43:13
|
LL | let _ = opt.as_ref().map(|x| &**x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead
- --> $DIR/option_as_ref_deref.rs:43:13
+ --> $DIR/option_as_ref_deref.rs:44:13
|
LL | let _ = opt.as_mut().map(|x| &mut **x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()`
error: called `.as_ref().map(std::ops::Deref::deref)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
- --> $DIR/option_as_ref_deref.rs:46:13
+ --> $DIR/option_as_ref_deref.rs:47:13
|
LL | let _ = opt.as_ref().map(std::ops::Deref::deref);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
-error: aborting due to 17 previous errors
+error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead
+ --> $DIR/option_as_ref_deref.rs:61:13
+ |
+LL | let _ = opt.as_ref().map(String::as_str);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()`
+
+error: aborting due to 18 previous errors
diff --git a/src/tools/clippy/tests/ui/option_env_unwrap.stderr b/src/tools/clippy/tests/ui/option_env_unwrap.stderr
index 885ac096c..bc188a07e 100644
--- a/src/tools/clippy/tests/ui/option_env_unwrap.stderr
+++ b/src/tools/clippy/tests/ui/option_env_unwrap.stderr
@@ -4,8 +4,8 @@ error: this will panic at run-time if the environment variable doesn't exist at
LL | let _ = option_env!("PATH").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::option-env-unwrap` implied by `-D warnings`
= help: consider using the `env!` macro instead
+ = note: `-D clippy::option-env-unwrap` implied by `-D warnings`
error: this will panic at run-time if the environment variable doesn't exist at compile-time
--> $DIR/option_env_unwrap.rs:19:13
diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
index 1290bd8ef..00264dcce 100644
--- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
+++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.fixed
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::option_map_unit_fn)]
#![allow(unused)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
fn do_nothing<T>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
index f3e5b62c6..f3363ebce 100644
--- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
+++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.rs
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::option_map_unit_fn)]
#![allow(unused)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
fn do_nothing<T>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr
index ab2a294a0..0305387b9 100644
--- a/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr
+++ b/src/tools/clippy/tests/ui/option_map_unit_fn_fixable.stderr
@@ -1,5 +1,5 @@
error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:39:5
+ --> $DIR/option_map_unit_fn_fixable.rs:38:5
|
LL | x.field.map(do_nothing);
| ^^^^^^^^^^^^^^^^^^^^^^^-
@@ -9,7 +9,7 @@ LL | x.field.map(do_nothing);
= note: `-D clippy::option-map-unit-fn` implied by `-D warnings`
error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:41:5
+ --> $DIR/option_map_unit_fn_fixable.rs:40:5
|
LL | x.field.map(do_nothing);
| ^^^^^^^^^^^^^^^^^^^^^^^-
@@ -17,7 +17,7 @@ LL | x.field.map(do_nothing);
| help: try this: `if let Some(x_field) = x.field { do_nothing(x_field) }`
error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:43:5
+ --> $DIR/option_map_unit_fn_fixable.rs:42:5
|
LL | x.field.map(diverge);
| ^^^^^^^^^^^^^^^^^^^^-
@@ -25,7 +25,7 @@ LL | x.field.map(diverge);
| help: try this: `if let Some(x_field) = x.field { diverge(x_field) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:49:5
+ --> $DIR/option_map_unit_fn_fixable.rs:48:5
|
LL | x.field.map(|value| x.do_option_nothing(value + captured));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -33,7 +33,7 @@ LL | x.field.map(|value| x.do_option_nothing(value + captured));
| help: try this: `if let Some(value) = x.field { x.do_option_nothing(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:51:5
+ --> $DIR/option_map_unit_fn_fixable.rs:50:5
|
LL | x.field.map(|value| { x.do_option_plus_one(value + captured); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -41,7 +41,7 @@ LL | x.field.map(|value| { x.do_option_plus_one(value + captured); });
| help: try this: `if let Some(value) = x.field { x.do_option_plus_one(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:54:5
+ --> $DIR/option_map_unit_fn_fixable.rs:53:5
|
LL | x.field.map(|value| do_nothing(value + captured));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -49,7 +49,7 @@ LL | x.field.map(|value| do_nothing(value + captured));
| help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:56:5
+ --> $DIR/option_map_unit_fn_fixable.rs:55:5
|
LL | x.field.map(|value| { do_nothing(value + captured) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -57,7 +57,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) });
| help: try this: `if let Some(value) = x.field { do_nothing(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:58:5
+ --> $DIR/option_map_unit_fn_fixable.rs:57:5
|
LL | x.field.map(|value| { do_nothing(value + captured); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -65,7 +65,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); });
| help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:60:5
+ --> $DIR/option_map_unit_fn_fixable.rs:59:5
|
LL | x.field.map(|value| { { do_nothing(value + captured); } });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -73,7 +73,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } });
| help: try this: `if let Some(value) = x.field { do_nothing(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:63:5
+ --> $DIR/option_map_unit_fn_fixable.rs:62:5
|
LL | x.field.map(|value| diverge(value + captured));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -81,7 +81,7 @@ LL | x.field.map(|value| diverge(value + captured));
| help: try this: `if let Some(value) = x.field { diverge(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:65:5
+ --> $DIR/option_map_unit_fn_fixable.rs:64:5
|
LL | x.field.map(|value| { diverge(value + captured) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -89,7 +89,7 @@ LL | x.field.map(|value| { diverge(value + captured) });
| help: try this: `if let Some(value) = x.field { diverge(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:67:5
+ --> $DIR/option_map_unit_fn_fixable.rs:66:5
|
LL | x.field.map(|value| { diverge(value + captured); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -97,7 +97,7 @@ LL | x.field.map(|value| { diverge(value + captured); });
| help: try this: `if let Some(value) = x.field { diverge(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:69:5
+ --> $DIR/option_map_unit_fn_fixable.rs:68:5
|
LL | x.field.map(|value| { { diverge(value + captured); } });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -105,7 +105,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } });
| help: try this: `if let Some(value) = x.field { diverge(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:74:5
+ --> $DIR/option_map_unit_fn_fixable.rs:73:5
|
LL | x.field.map(|value| { let y = plus_one(value + captured); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -113,7 +113,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); });
| help: try this: `if let Some(value) = x.field { let y = plus_one(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:76:5
+ --> $DIR/option_map_unit_fn_fixable.rs:75:5
|
LL | x.field.map(|value| { plus_one(value + captured); });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -121,7 +121,7 @@ LL | x.field.map(|value| { plus_one(value + captured); });
| help: try this: `if let Some(value) = x.field { plus_one(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:78:5
+ --> $DIR/option_map_unit_fn_fixable.rs:77:5
|
LL | x.field.map(|value| { { plus_one(value + captured); } });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -129,7 +129,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } });
| help: try this: `if let Some(value) = x.field { plus_one(value + captured); }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:81:5
+ --> $DIR/option_map_unit_fn_fixable.rs:80:5
|
LL | x.field.map(|ref value| { do_nothing(value + captured) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -137,7 +137,7 @@ LL | x.field.map(|ref value| { do_nothing(value + captured) });
| help: try this: `if let Some(ref value) = x.field { do_nothing(value + captured) }`
error: called `map(f)` on an `Option` value where `f` is a function that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:83:5
+ --> $DIR/option_map_unit_fn_fixable.rs:82:5
|
LL | option().map(do_nothing);
| ^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -145,7 +145,7 @@ LL | option().map(do_nothing);
| help: try this: `if let Some(a) = option() { do_nothing(a) }`
error: called `map(f)` on an `Option` value where `f` is a closure that returns the unit type `()`
- --> $DIR/option_map_unit_fn_fixable.rs:85:5
+ --> $DIR/option_map_unit_fn_fixable.rs:84:5
|
LL | option().map(|value| println!("{:?}", value));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
diff --git a/src/tools/clippy/tests/ui/option_take_on_temporary.fixed b/src/tools/clippy/tests/ui/option_take_on_temporary.fixed
deleted file mode 100644
index 29691e816..000000000
--- a/src/tools/clippy/tests/ui/option_take_on_temporary.fixed
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-rustfix
-
-fn main() {
- println!("Testing non erroneous option_take_on_temporary");
- let mut option = Some(1);
- let _ = Box::new(move || option.take().unwrap());
-
- println!("Testing non erroneous option_take_on_temporary");
- let x = Some(3);
- x.as_ref();
-
- println!("Testing erroneous option_take_on_temporary");
- let x = Some(3);
- x.as_ref();
-}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.fixed b/src/tools/clippy/tests/ui/or_fun_call.fixed
index 5991188ab..23b1aa8be 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.fixed
+++ b/src/tools/clippy/tests/ui/or_fun_call.fixed
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::or_fun_call)]
#![allow(dead_code)]
-#![allow(clippy::unnecessary_wraps, clippy::borrow_as_ptr)]
+#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
use std::collections::BTreeMap;
use std::collections::HashMap;
@@ -226,4 +225,15 @@ mod issue8239 {
}
}
+mod issue9608 {
+ fn sig_drop() {
+ enum X {
+ X(std::fs::File),
+ Y(u32),
+ }
+
+ let _ = None.unwrap_or(X::Y(0));
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.rs b/src/tools/clippy/tests/ui/or_fun_call.rs
index c353b41e4..039998f22 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.rs
+++ b/src/tools/clippy/tests/ui/or_fun_call.rs
@@ -1,8 +1,7 @@
// run-rustfix
-
#![warn(clippy::or_fun_call)]
#![allow(dead_code)]
-#![allow(clippy::unnecessary_wraps, clippy::borrow_as_ptr)]
+#![allow(clippy::borrow_as_ptr, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
use std::collections::BTreeMap;
use std::collections::HashMap;
@@ -226,4 +225,15 @@ mod issue8239 {
}
}
+mod issue9608 {
+ fn sig_drop() {
+ enum X {
+ X(std::fs::File),
+ Y(u32),
+ }
+
+ let _ = None.unwrap_or(X::Y(0));
+ }
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/or_fun_call.stderr b/src/tools/clippy/tests/ui/or_fun_call.stderr
index e3dab4cb1..113ba150c 100644
--- a/src/tools/clippy/tests/ui/or_fun_call.stderr
+++ b/src/tools/clippy/tests/ui/or_fun_call.stderr
@@ -1,5 +1,5 @@
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:49:22
+ --> $DIR/or_fun_call.rs:48:22
|
LL | with_constructor.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
@@ -7,151 +7,151 @@ LL | with_constructor.unwrap_or(make());
= note: `-D clippy::or-fun-call` implied by `-D warnings`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:52:14
+ --> $DIR/or_fun_call.rs:51:14
|
LL | with_new.unwrap_or(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:55:21
+ --> $DIR/or_fun_call.rs:54:21
|
LL | with_const_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:58:14
+ --> $DIR/or_fun_call.rs:57:14
|
LL | with_err.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:61:19
+ --> $DIR/or_fun_call.rs:60:19
|
LL | with_err_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a call to `default`
- --> $DIR/or_fun_call.rs:64:24
+ --> $DIR/or_fun_call.rs:63:24
|
LL | with_default_trait.unwrap_or(Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `default`
- --> $DIR/or_fun_call.rs:67:23
+ --> $DIR/or_fun_call.rs:66:23
|
LL | with_default_type.unwrap_or(u64::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:70:18
+ --> $DIR/or_fun_call.rs:69:18
|
LL | self_default.unwrap_or(<FakeDefault>::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(<FakeDefault>::default)`
error: use of `unwrap_or` followed by a call to `default`
- --> $DIR/or_fun_call.rs:73:18
+ --> $DIR/or_fun_call.rs:72:18
|
LL | real_default.unwrap_or(<FakeDefault as Default>::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:76:14
+ --> $DIR/or_fun_call.rs:75:14
|
LL | with_vec.unwrap_or(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:79:21
+ --> $DIR/or_fun_call.rs:78:21
|
LL | without_default.unwrap_or(Foo::new());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
error: use of `or_insert` followed by a call to `new`
- --> $DIR/or_fun_call.rs:82:19
+ --> $DIR/or_fun_call.rs:81:19
|
LL | map.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
error: use of `or_insert` followed by a call to `new`
- --> $DIR/or_fun_call.rs:85:23
+ --> $DIR/or_fun_call.rs:84:23
|
LL | map_vec.entry(42).or_insert(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
error: use of `or_insert` followed by a call to `new`
- --> $DIR/or_fun_call.rs:88:21
+ --> $DIR/or_fun_call.rs:87:21
|
LL | btree.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
error: use of `or_insert` followed by a call to `new`
- --> $DIR/or_fun_call.rs:91:25
+ --> $DIR/or_fun_call.rs:90:25
|
LL | btree_vec.entry(42).or_insert(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:94:21
+ --> $DIR/or_fun_call.rs:93:21
|
LL | let _ = stringy.unwrap_or(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:102:21
+ --> $DIR/or_fun_call.rs:101:21
|
LL | let _ = Some(1).unwrap_or(map[&1]);
| ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:104:21
+ --> $DIR/or_fun_call.rs:103:21
|
LL | let _ = Some(1).unwrap_or(map[&1]);
| ^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| map[&1])`
error: use of `or` followed by a function call
- --> $DIR/or_fun_call.rs:128:35
+ --> $DIR/or_fun_call.rs:127:35
|
LL | let _ = Some("a".to_string()).or(Some("b".to_string()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:167:14
+ --> $DIR/or_fun_call.rs:166:14
|
LL | None.unwrap_or(ptr_to_ref(s));
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| ptr_to_ref(s))`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:173:14
+ --> $DIR/or_fun_call.rs:172:14
|
LL | None.unwrap_or(unsafe { ptr_to_ref(s) });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
error: use of `unwrap_or` followed by a function call
- --> $DIR/or_fun_call.rs:175:14
+ --> $DIR/or_fun_call.rs:174:14
|
LL | None.unwrap_or( unsafe { ptr_to_ref(s) } );
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:189:14
+ --> $DIR/or_fun_call.rs:188:14
|
LL | .unwrap_or(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:202:14
+ --> $DIR/or_fun_call.rs:201:14
|
LL | .unwrap_or(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:214:14
+ --> $DIR/or_fun_call.rs:213:14
|
LL | .unwrap_or(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `new`
- --> $DIR/or_fun_call.rs:225:10
+ --> $DIR/or_fun_call.rs:224:10
|
LL | .unwrap_or(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_default()`
diff --git a/src/tools/clippy/tests/ui/out_of_bounds_indexing/issue-3102.rs b/src/tools/clippy/tests/ui/out_of_bounds_indexing/issue-3102.rs
index f20a0ede1..edd2123d4 100644
--- a/src/tools/clippy/tests/ui/out_of_bounds_indexing/issue-3102.rs
+++ b/src/tools/clippy/tests/ui/out_of_bounds_indexing/issue-3102.rs
@@ -1,5 +1,5 @@
#![warn(clippy::out_of_bounds_indexing)]
-#![allow(clippy::no_effect, const_err)]
+#![allow(clippy::no_effect)]
fn main() {
let x = [1, 2, 3, 4];
diff --git a/src/tools/clippy/tests/ui/out_of_bounds_indexing/simple.rs b/src/tools/clippy/tests/ui/out_of_bounds_indexing/simple.rs
index 590e578d7..4c541c23f 100644
--- a/src/tools/clippy/tests/ui/out_of_bounds_indexing/simple.rs
+++ b/src/tools/clippy/tests/ui/out_of_bounds_indexing/simple.rs
@@ -1,5 +1,5 @@
#![warn(clippy::out_of_bounds_indexing)]
-#![allow(clippy::no_effect, clippy::unnecessary_operation, const_err)]
+#![allow(clippy::no_effect, clippy::unnecessary_operation)]
fn main() {
let x = [1, 2, 3, 4];
diff --git a/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr b/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr
index 158cae8b8..e989f2ece 100644
--- a/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr
+++ b/src/tools/clippy/tests/ui/overly_complex_bool_expr.stderr
@@ -4,12 +4,12 @@ error: this boolean expression contains a logic bug
LL | let _ = a && b || a;
| ^^^^^^^^^^^ help: it would look like the following: `a`
|
- = note: `-D clippy::overly-complex-bool-expr` implied by `-D warnings`
help: this expression can be optimized out by applying boolean operations to the outer expression
--> $DIR/overly_complex_bool_expr.rs:11:18
|
LL | let _ = a && b || a;
| ^
+ = note: `-D clippy::overly-complex-bool-expr` implied by `-D warnings`
error: this boolean expression contains a logic bug
--> $DIR/overly_complex_bool_expr.rs:13:13
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
index 561503ae5..97787bc84 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn.stderr
@@ -7,13 +7,13 @@ LL | | panic!("error");
LL | | }
| |_____^
|
- = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
--> $DIR/panic_in_result_fn.rs:8:9
|
LL | panic!("error");
| ^^^^^^^^^^^^^^^
+ = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
--> $DIR/panic_in_result_fn.rs:11:5
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.rs b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.rs
index ffdf8288a..08ab4d868 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.rs
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.rs
@@ -1,5 +1,5 @@
#![warn(clippy::panic_in_result_fn)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
struct A;
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
index b6aa005e7..eb0aacbb6 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn_assertions.stderr
@@ -8,13 +8,13 @@ LL | | Ok(true)
LL | | }
| |_____^
|
- = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
= help: `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertions should not be used in a function that returns `Result` as `Result` is expected to return an error instead of crashing
note: return Err() instead of panicking
--> $DIR/panic_in_result_fn_assertions.rs:9:9
|
LL | assert!(x == 5, "wrong argument");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::panic-in-result-fn` implied by `-D warnings`
error: used `unimplemented!()`, `unreachable!()`, `todo!()`, `panic!()` or assertion in a function that returns `Result`
--> $DIR/panic_in_result_fn_assertions.rs:13:5
diff --git a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs b/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs
index c4fcd7e70..df89d8c50 100644
--- a/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs
+++ b/src/tools/clippy/tests/ui/panic_in_result_fn_debug_assertions.rs
@@ -1,5 +1,5 @@
#![warn(clippy::panic_in_result_fn)]
-#![allow(clippy::unnecessary_wraps)]
+#![allow(clippy::uninlined_format_args, clippy::unnecessary_wraps)]
// debug_assert should never trigger the `panic_in_result_fn` lint
diff --git a/src/tools/clippy/tests/ui/partial_pub_fields.rs b/src/tools/clippy/tests/ui/partial_pub_fields.rs
new file mode 100644
index 000000000..668545da8
--- /dev/null
+++ b/src/tools/clippy/tests/ui/partial_pub_fields.rs
@@ -0,0 +1,40 @@
+#![allow(unused)]
+#![warn(clippy::partial_pub_fields)]
+
+fn main() {
+ use std::collections::HashMap;
+
+ #[derive(Default)]
+ pub struct FileSet {
+ files: HashMap<String, u32>,
+ pub paths: HashMap<u32, String>,
+ }
+
+ pub struct Color {
+ pub r: u8,
+ pub g: u8,
+ b: u8,
+ }
+
+ pub struct Point(i32, pub i32);
+
+ pub struct Visibility {
+ r#pub: bool,
+ pub pos: u32,
+ }
+
+ // Don't lint on empty structs;
+ pub struct Empty1;
+ pub struct Empty2();
+ pub struct Empty3 {};
+
+ // Don't lint on structs with one field.
+ pub struct Single1(i32);
+ pub struct Single2(pub i32);
+ pub struct Single3 {
+ v1: i32,
+ }
+ pub struct Single4 {
+ pub v1: i32,
+ }
+}
diff --git a/src/tools/clippy/tests/ui/partial_pub_fields.stderr b/src/tools/clippy/tests/ui/partial_pub_fields.stderr
new file mode 100644
index 000000000..84cfc1a91
--- /dev/null
+++ b/src/tools/clippy/tests/ui/partial_pub_fields.stderr
@@ -0,0 +1,35 @@
+error: mixed usage of pub and non-pub fields
+ --> $DIR/partial_pub_fields.rs:10:9
+ |
+LL | pub paths: HashMap<u32, String>,
+ | ^^^
+ |
+ = help: consider using private field here
+ = note: `-D clippy::partial-pub-fields` implied by `-D warnings`
+
+error: mixed usage of pub and non-pub fields
+ --> $DIR/partial_pub_fields.rs:16:9
+ |
+LL | b: u8,
+ | ^
+ |
+ = help: consider using public field here
+
+error: mixed usage of pub and non-pub fields
+ --> $DIR/partial_pub_fields.rs:19:27
+ |
+LL | pub struct Point(i32, pub i32);
+ | ^^^
+ |
+ = help: consider using private field here
+
+error: mixed usage of pub and non-pub fields
+ --> $DIR/partial_pub_fields.rs:23:9
+ |
+LL | pub pos: u32,
+ | ^^^
+ |
+ = help: consider using private field here
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.stderr
index 3421d5683..87fb243b6 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/mutability.stderr
@@ -4,8 +4,8 @@ error: type of pattern does not match the expression type
LL | Some(_) => (),
| ^^^^^^^
|
- = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
= help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
+ = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
error: type of pattern does not match the expression type
--> $DIR/mutability.rs:15:9
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
index d285c9378..a91b5ac6c 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_alternatives.stderr
@@ -4,8 +4,8 @@ error: type of pattern does not match the expression type
LL | if let Value::B | Value::A(_) = ref_value {}
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
= help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
+ = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
error: type of pattern does not match the expression type
--> $DIR/pattern_alternatives.rs:16:34
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
index d428e85b0..8bc5c63ba 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_structs.stderr
@@ -4,8 +4,8 @@ error: type of pattern does not match the expression type
LL | let Struct { .. } = ref_value;
| ^^^^^^^^^^^^^
|
- = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
= help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
+ = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
error: type of pattern does not match the expression type
--> $DIR/pattern_structs.rs:14:33
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
index edd0074d0..a1ef540d2 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/pattern_tuples.stderr
@@ -4,8 +4,8 @@ error: type of pattern does not match the expression type
LL | let TupleStruct(_) = ref_value;
| ^^^^^^^^^^^^^^
|
- = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
= help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
+ = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
error: type of pattern does not match the expression type
--> $DIR/pattern_tuples.rs:12:25
diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
index 12b3d3a8b..f56a3a893 100644
--- a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
+++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr
@@ -4,8 +4,8 @@ error: type of pattern does not match the expression type
LL | Some(_) => (),
| ^^^^^^^
|
- = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
= help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings
+ = note: `-D clippy::pattern-type-mismatch` implied by `-D warnings`
error: type of pattern does not match the expression type
--> $DIR/syntax.rs:30:12
diff --git a/src/tools/clippy/tests/ui/patterns.fixed b/src/tools/clippy/tests/ui/patterns.fixed
index f22388154..cd6901432 100644
--- a/src/tools/clippy/tests/ui/patterns.fixed
+++ b/src/tools/clippy/tests/ui/patterns.fixed
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused)]
#![warn(clippy::all)]
+#![allow(unused)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
let v = Some(true);
diff --git a/src/tools/clippy/tests/ui/patterns.rs b/src/tools/clippy/tests/ui/patterns.rs
index 5848ecd38..9128da420 100644
--- a/src/tools/clippy/tests/ui/patterns.rs
+++ b/src/tools/clippy/tests/ui/patterns.rs
@@ -1,6 +1,7 @@
// run-rustfix
-#![allow(unused)]
#![warn(clippy::all)]
+#![allow(unused)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
let v = Some(true);
diff --git a/src/tools/clippy/tests/ui/patterns.stderr b/src/tools/clippy/tests/ui/patterns.stderr
index af0675806..2c46b4eb5 100644
--- a/src/tools/clippy/tests/ui/patterns.stderr
+++ b/src/tools/clippy/tests/ui/patterns.stderr
@@ -1,5 +1,5 @@
error: the `y @ _` pattern can be written as just `y`
- --> $DIR/patterns.rs:10:9
+ --> $DIR/patterns.rs:11:9
|
LL | y @ _ => (),
| ^^^^^ help: try: `y`
@@ -7,13 +7,13 @@ LL | y @ _ => (),
= note: `-D clippy::redundant-pattern` implied by `-D warnings`
error: the `x @ _` pattern can be written as just `x`
- --> $DIR/patterns.rs:25:9
+ --> $DIR/patterns.rs:26:9
|
LL | ref mut x @ _ => {
| ^^^^^^^^^^^^^ help: try: `ref mut x`
error: the `x @ _` pattern can be written as just `x`
- --> $DIR/patterns.rs:33:9
+ --> $DIR/patterns.rs:34:9
|
LL | ref x @ _ => println!("vec: {:?}", x),
| ^^^^^^^^^ help: try: `ref x`
diff --git a/src/tools/clippy/tests/ui/positional_named_format_parameters.fixed b/src/tools/clippy/tests/ui/positional_named_format_parameters.fixed
deleted file mode 100644
index 4170e1098..000000000
--- a/src/tools/clippy/tests/ui/positional_named_format_parameters.fixed
+++ /dev/null
@@ -1,56 +0,0 @@
-// run-rustfix
-#![allow(unused_must_use)]
-#![allow(named_arguments_used_positionally)] // Unstable at time of writing.
-#![warn(clippy::positional_named_format_parameters)]
-
-use std::io::Write;
-
-fn main() {
- let mut v = Vec::new();
- let hello = "Hello";
-
- println!("{hello:.foo$}", foo = 2);
- writeln!(v, "{hello:.foo$}", foo = 2);
-
- // Warnings
- println!("{zero} {one:?}", zero = 0, one = 1);
- println!("This is a test {zero} {one:?}", zero = 0, one = 1);
- println!("Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
- println!("Hello {one:zero$}!", zero = 5, one = 1);
- println!("Hello {zero:one$}!", zero = 4, one = 1);
- println!("Hello {zero:0one$}!", zero = 4, one = 1);
- println!("Hello is {one:.zero$}", zero = 5, one = 0.01);
- println!("Hello is {one:<6.zero$}", zero = 5, one = 0.01);
- println!("{zero}, `{two:>8.one$}` has 3", zero = hello, one = 3, two = hello);
- println!("Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
- println!("Hello {world} {world}!", world = 5);
-
- writeln!(v, "{zero} {one:?}", zero = 0, one = 1);
- writeln!(v, "This is a test {zero} {one:?}", zero = 0, one = 1);
- writeln!(v, "Hello {one} is {two:.zero$}", zero = 5, one = hello, two = 0.01);
- writeln!(v, "Hello {one:zero$}!", zero = 4, one = 1);
- writeln!(v, "Hello {zero:one$}!", zero = 4, one = 1);
- writeln!(v, "Hello {zero:0one$}!", zero = 4, one = 1);
- writeln!(v, "Hello is {one:.zero$}", zero = 3, one = 0.01);
- writeln!(v, "Hello is {one:<6.zero$}", zero = 2, one = 0.01);
- writeln!(v, "{zero}, `{two:>8.one$}` has 3", zero = hello, one = 3, two = hello);
- writeln!(v, "Hello {one} is {two:.zero$}", zero = 1, one = hello, two = 0.01);
- writeln!(v, "Hello {world} {world}!", world = 0);
-
- // Tests from other files
- println!("{w:w$}", w = 1);
- println!("{p:.p$}", p = 1);
- println!("{v}", v = 1);
- println!("{v:v$}", v = 1);
- println!("{v:v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{v:v$.v$}", v = 1);
- println!("{w:w$}", w = 1);
- println!("{p:.p$}", p = 1);
- println!("{:p$.w$}", 1, w = 1, p = 1);
-}
diff --git a/src/tools/clippy/tests/ui/positional_named_format_parameters.rs b/src/tools/clippy/tests/ui/positional_named_format_parameters.rs
deleted file mode 100644
index 553d8494e..000000000
--- a/src/tools/clippy/tests/ui/positional_named_format_parameters.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// run-rustfix
-#![allow(unused_must_use)]
-#![allow(named_arguments_used_positionally)] // Unstable at time of writing.
-#![warn(clippy::positional_named_format_parameters)]
-
-use std::io::Write;
-
-fn main() {
- let mut v = Vec::new();
- let hello = "Hello";
-
- println!("{hello:.foo$}", foo = 2);
- writeln!(v, "{hello:.foo$}", foo = 2);
-
- // Warnings
- println!("{} {1:?}", zero = 0, one = 1);
- println!("This is a test { } {000001:?}", zero = 0, one = 1);
- println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- println!("Hello {1:0$}!", zero = 5, one = 1);
- println!("Hello {0:1$}!", zero = 4, one = 1);
- println!("Hello {0:01$}!", zero = 4, one = 1);
- println!("Hello is {1:.*}", zero = 5, one = 0.01);
- println!("Hello is {:<6.*}", zero = 5, one = 0.01);
- println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- println!("Hello {world} {}!", world = 5);
-
- writeln!(v, "{} {1:?}", zero = 0, one = 1);
- writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
- writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
- writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
- writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
- writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
- writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
- writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
- writeln!(v, "Hello {world} {}!", world = 0);
-
- // Tests from other files
- println!("{:w$}", w = 1);
- println!("{:.p$}", p = 1);
- println!("{}", v = 1);
- println!("{:0$}", v = 1);
- println!("{0:0$}", v = 1);
- println!("{:0$.0$}", v = 1);
- println!("{0:0$.0$}", v = 1);
- println!("{0:0$.v$}", v = 1);
- println!("{0:v$.0$}", v = 1);
- println!("{v:0$.0$}", v = 1);
- println!("{v:v$.0$}", v = 1);
- println!("{v:0$.v$}", v = 1);
- println!("{:w$}", w = 1);
- println!("{:.p$}", p = 1);
- println!("{:p$.w$}", 1, w = 1, p = 1);
-}
diff --git a/src/tools/clippy/tests/ui/positional_named_format_parameters.stderr b/src/tools/clippy/tests/ui/positional_named_format_parameters.stderr
deleted file mode 100644
index 48ddb6d67..000000000
--- a/src/tools/clippy/tests/ui/positional_named_format_parameters.stderr
+++ /dev/null
@@ -1,418 +0,0 @@
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:16:16
- |
-LL | println!("{} {1:?}", zero = 0, one = 1);
- | ^ help: replace it with: `zero`
- |
- = note: `-D clippy::positional-named-format-parameters` implied by `-D warnings`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:16:19
- |
-LL | println!("{} {1:?}", zero = 0, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:17:31
- |
-LL | println!("This is a test { } {000001:?}", zero = 0, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:17:35
- |
-LL | println!("This is a test { } {000001:?}", zero = 0, one = 1);
- | ^^^^^^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:18:32
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:18:22
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter two is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:18:29
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `two`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:19:24
- |
-LL | println!("Hello {1:0$}!", zero = 5, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:19:22
- |
-LL | println!("Hello {1:0$}!", zero = 5, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:20:22
- |
-LL | println!("Hello {0:1$}!", zero = 4, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:20:24
- |
-LL | println!("Hello {0:1$}!", zero = 4, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:21:22
- |
-LL | println!("Hello {0:01$}!", zero = 4, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:21:25
- |
-LL | println!("Hello {0:01$}!", zero = 4, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:22:28
- |
-LL | println!("Hello is {1:.*}", zero = 5, one = 0.01);
- | ^ help: replace it with: `zero$`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:22:25
- |
-LL | println!("Hello is {1:.*}", zero = 5, one = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:23:29
- |
-LL | println!("Hello is {:<6.*}", zero = 5, one = 0.01);
- | ^ help: replace it with: `zero$`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:23:25
- |
-LL | println!("Hello is {:<6.*}", zero = 5, one = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:24:16
- |
-LL | println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:24:28
- |
-LL | println!("{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- | ^ help: replace it with: `one$`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:25:32
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:25:22
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter two is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:25:29
- |
-LL | println!("Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `two`
-
-error: named parameter world is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:26:30
- |
-LL | println!("Hello {world} {}!", world = 5);
- | ^ help: replace it with: `world`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:28:19
- |
-LL | writeln!(v, "{} {1:?}", zero = 0, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:28:22
- |
-LL | writeln!(v, "{} {1:?}", zero = 0, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:29:34
- |
-LL | writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:29:38
- |
-LL | writeln!(v, "This is a test { } {000001:?}", zero = 0, one = 1);
- | ^^^^^^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:30:35
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:30:25
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter two is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:30:32
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 5, one = hello, two = 0.01);
- | ^ help: replace it with: `two`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:31:27
- |
-LL | writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:31:25
- |
-LL | writeln!(v, "Hello {1:0$}!", zero = 4, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:32:25
- |
-LL | writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:32:27
- |
-LL | writeln!(v, "Hello {0:1$}!", zero = 4, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:33:25
- |
-LL | writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:33:28
- |
-LL | writeln!(v, "Hello {0:01$}!", zero = 4, one = 1);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:34:31
- |
-LL | writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
- | ^ help: replace it with: `zero$`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:34:28
- |
-LL | writeln!(v, "Hello is {1:.*}", zero = 3, one = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:35:32
- |
-LL | writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
- | ^ help: replace it with: `zero$`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:35:28
- |
-LL | writeln!(v, "Hello is {:<6.*}", zero = 2, one = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:36:19
- |
-LL | writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:36:31
- |
-LL | writeln!(v, "{}, `{two:>8.*}` has 3", zero = hello, one = 3, two = hello);
- | ^ help: replace it with: `one$`
-
-error: named parameter zero is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:37:35
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
- | ^ help: replace it with: `zero`
-
-error: named parameter one is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:37:25
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
- | ^ help: replace it with: `one`
-
-error: named parameter two is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:37:32
- |
-LL | writeln!(v, "Hello {1} is {2:.0$}", zero = 1, one = hello, two = 0.01);
- | ^ help: replace it with: `two`
-
-error: named parameter world is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:38:33
- |
-LL | writeln!(v, "Hello {world} {}!", world = 0);
- | ^ help: replace it with: `world`
-
-error: named parameter w is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:41:16
- |
-LL | println!("{:w$}", w = 1);
- | ^ help: replace it with: `w`
-
-error: named parameter p is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:42:16
- |
-LL | println!("{:.p$}", p = 1);
- | ^ help: replace it with: `p`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:43:16
- |
-LL | println!("{}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:44:16
- |
-LL | println!("{:0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:44:17
- |
-LL | println!("{:0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:45:16
- |
-LL | println!("{0:0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:45:18
- |
-LL | println!("{0:0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:46:16
- |
-LL | println!("{:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:46:20
- |
-LL | println!("{:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:46:17
- |
-LL | println!("{:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:47:16
- |
-LL | println!("{0:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:47:21
- |
-LL | println!("{0:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:47:18
- |
-LL | println!("{0:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:48:16
- |
-LL | println!("{0:0$.v$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:48:18
- |
-LL | println!("{0:0$.v$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:49:16
- |
-LL | println!("{0:v$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:49:21
- |
-LL | println!("{0:v$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:50:21
- |
-LL | println!("{v:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:50:18
- |
-LL | println!("{v:0$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:51:21
- |
-LL | println!("{v:v$.0$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter v is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:52:18
- |
-LL | println!("{v:0$.v$}", v = 1);
- | ^ help: replace it with: `v`
-
-error: named parameter w is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:53:16
- |
-LL | println!("{:w$}", w = 1);
- | ^ help: replace it with: `w`
-
-error: named parameter p is used as a positional parameter
- --> $DIR/positional_named_format_parameters.rs:54:16
- |
-LL | println!("{:.p$}", p = 1);
- | ^ help: replace it with: `p`
-
-error: aborting due to 69 previous errors
-
diff --git a/src/tools/clippy/tests/ui/print_literal.rs b/src/tools/clippy/tests/ui/print_literal.rs
index 8665a3bb2..86f908f66 100644
--- a/src/tools/clippy/tests/ui/print_literal.rs
+++ b/src/tools/clippy/tests/ui/print_literal.rs
@@ -1,4 +1,5 @@
#![warn(clippy::print_literal)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
// these should be fine
@@ -20,11 +21,13 @@ fn main() {
println!("{} of {:b} people know binary, the other half doesn't", 1, 2);
println!("10 / 4 is {}", 2.5);
println!("2 + 1 = {}", 3);
+ println!("From expansion {}", stringify!(not a string literal));
// these should throw warnings
print!("Hello {}", "world");
println!("Hello {} {}", world, "world");
println!("Hello {}", "world");
+ println!("{} {:.4}", "a literal", 5);
// positional args don't change the fact
// that we're using a literal -- this should
diff --git a/src/tools/clippy/tests/ui/print_literal.stderr b/src/tools/clippy/tests/ui/print_literal.stderr
index 72aae0756..6404dacda 100644
--- a/src/tools/clippy/tests/ui/print_literal.stderr
+++ b/src/tools/clippy/tests/ui/print_literal.stderr
@@ -1,5 +1,5 @@
error: literal with an empty format string
- --> $DIR/print_literal.rs:25:24
+ --> $DIR/print_literal.rs:27:24
|
LL | print!("Hello {}", "world");
| ^^^^^^^
@@ -12,7 +12,7 @@ LL + print!("Hello world");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:26:36
+ --> $DIR/print_literal.rs:28:36
|
LL | println!("Hello {} {}", world, "world");
| ^^^^^^^
@@ -24,7 +24,7 @@ LL + println!("Hello {} world", world);
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:27:26
+ --> $DIR/print_literal.rs:29:26
|
LL | println!("Hello {}", "world");
| ^^^^^^^
@@ -36,7 +36,19 @@ LL + println!("Hello world");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:32:25
+ --> $DIR/print_literal.rs:30:26
+ |
+LL | println!("{} {:.4}", "a literal", 5);
+ | ^^^^^^^^^^^
+ |
+help: try this
+ |
+LL - println!("{} {:.4}", "a literal", 5);
+LL + println!("a literal {:.4}", 5);
+ |
+
+error: literal with an empty format string
+ --> $DIR/print_literal.rs:35:25
|
LL | println!("{0} {1}", "hello", "world");
| ^^^^^^^
@@ -48,7 +60,7 @@ LL + println!("hello {1}", "world");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:32:34
+ --> $DIR/print_literal.rs:35:34
|
LL | println!("{0} {1}", "hello", "world");
| ^^^^^^^
@@ -60,34 +72,34 @@ LL + println!("{0} world", "hello");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:33:25
+ --> $DIR/print_literal.rs:36:34
|
LL | println!("{1} {0}", "hello", "world");
- | ^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - println!("{1} {0}", "hello", "world");
-LL + println!("{1} hello", "world");
+LL + println!("world {0}", "hello");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:33:34
+ --> $DIR/print_literal.rs:36:25
|
LL | println!("{1} {0}", "hello", "world");
- | ^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - println!("{1} {0}", "hello", "world");
-LL + println!("world {0}", "hello");
+LL + println!("{1} hello", "world");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:36:29
+ --> $DIR/print_literal.rs:39:35
|
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
@@ -96,10 +108,10 @@ LL + println!("hello {bar}", bar = "world");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:36:44
+ --> $DIR/print_literal.rs:39:50
|
LL | println!("{foo} {bar}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
@@ -108,28 +120,28 @@ LL + println!("{foo} world", foo = "hello");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:37:29
+ --> $DIR/print_literal.rs:40:50
|
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - println!("{bar} {foo}", foo = "hello", bar = "world");
-LL + println!("{bar} hello", bar = "world");
+LL + println!("world {foo}", foo = "hello");
|
error: literal with an empty format string
- --> $DIR/print_literal.rs:37:44
+ --> $DIR/print_literal.rs:40:35
|
LL | println!("{bar} {foo}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - println!("{bar} {foo}", foo = "hello", bar = "world");
-LL + println!("world {foo}", foo = "hello");
+LL + println!("{bar} hello", bar = "world");
|
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/print_with_newline.rs b/src/tools/clippy/tests/ui/print_with_newline.rs
index a43a1fc4f..b8c29d207 100644
--- a/src/tools/clippy/tests/ui/print_with_newline.rs
+++ b/src/tools/clippy/tests/ui/print_with_newline.rs
@@ -48,5 +48,13 @@ fn main() {
print!("\r\n");
print!("foo\r\n");
print!("\\r\n"); //~ ERROR
- print!("foo\rbar\n") // ~ ERROR
+ print!("foo\rbar\n");
+
+ // Ignore expanded format strings
+ macro_rules! newline {
+ () => {
+ "\n"
+ };
+ }
+ print!(newline!());
}
diff --git a/src/tools/clippy/tests/ui/print_with_newline.stderr b/src/tools/clippy/tests/ui/print_with_newline.stderr
index edbaa1cdf..b9f5675fa 100644
--- a/src/tools/clippy/tests/ui/print_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/print_with_newline.stderr
@@ -83,7 +83,7 @@ LL | | );
help: use `println!` instead
|
LL ~ println!(
-LL ~ ""
+LL ~
|
error: using `print!()` with a format string that ends in a single newline
@@ -98,7 +98,7 @@ LL | | );
help: use `println!` instead
|
LL ~ println!(
-LL ~ r""
+LL ~
|
error: using `print!()` with a format string that ends in a single newline
@@ -113,17 +113,5 @@ LL - print!("/r/n"); //~ ERROR
LL + println!("/r"); //~ ERROR
|
-error: using `print!()` with a format string that ends in a single newline
- --> $DIR/print_with_newline.rs:51:5
- |
-LL | print!("foo/rbar/n") // ~ ERROR
- | ^^^^^^^^^^^^^^^^^^^^
- |
-help: use `println!` instead
- |
-LL - print!("foo/rbar/n") // ~ ERROR
-LL + println!("foo/rbar") // ~ ERROR
- |
-
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/println_empty_string.stderr b/src/tools/clippy/tests/ui/println_empty_string.stderr
index 17fe4ea74..3cc8bb947 100644
--- a/src/tools/clippy/tests/ui/println_empty_string.stderr
+++ b/src/tools/clippy/tests/ui/println_empty_string.stderr
@@ -1,28 +1,36 @@
-error: using `println!("")`
+error: empty string literal in `println!`
--> $DIR/println_empty_string.rs:6:5
|
LL | println!("");
- | ^^^^^^^^^^^^ help: replace it with: `println!()`
+ | ^^^^^^^^^--^
+ | |
+ | help: remove the empty string
|
= note: `-D clippy::println-empty-string` implied by `-D warnings`
-error: using `println!("")`
+error: empty string literal in `println!`
--> $DIR/println_empty_string.rs:9:14
|
LL | _ => println!(""),
- | ^^^^^^^^^^^^ help: replace it with: `println!()`
+ | ^^^^^^^^^--^
+ | |
+ | help: remove the empty string
-error: using `eprintln!("")`
+error: empty string literal in `eprintln!`
--> $DIR/println_empty_string.rs:13:5
|
LL | eprintln!("");
- | ^^^^^^^^^^^^^ help: replace it with: `eprintln!()`
+ | ^^^^^^^^^^--^
+ | |
+ | help: remove the empty string
-error: using `eprintln!("")`
+error: empty string literal in `eprintln!`
--> $DIR/println_empty_string.rs:16:14
|
LL | _ => eprintln!(""),
- | ^^^^^^^^^^^^^ help: replace it with: `eprintln!()`
+ | ^^^^^^^^^^--^
+ | |
+ | help: remove the empty string
error: aborting due to 4 previous errors
diff --git a/src/tools/clippy/tests/ui/proc_macro.stderr b/src/tools/clippy/tests/ui/proc_macro.stderr
index 48fd58c9a..c795f6ad0 100644
--- a/src/tools/clippy/tests/ui/proc_macro.stderr
+++ b/src/tools/clippy/tests/ui/proc_macro.stderr
@@ -4,8 +4,8 @@ error: approximate value of `f{32, 64}::consts::PI` found
LL | let _x = 3.14;
| ^^^^
|
- = note: `#[deny(clippy::approx_constant)]` on by default
= help: consider using the constant directly
+ = note: `#[deny(clippy::approx_constant)]` on by default
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/ptr_arg.rs b/src/tools/clippy/tests/ui/ptr_arg.rs
index fd15001e5..5f54101ca 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.rs
+++ b/src/tools/clippy/tests/ui/ptr_arg.rs
@@ -3,7 +3,7 @@
#![warn(clippy::ptr_arg)]
use std::borrow::Cow;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
fn do_vec(x: &Vec<i64>) {
//Nothing here
@@ -207,3 +207,31 @@ fn cow_conditional_to_mut(a: &mut Cow<str>) {
a.to_mut().push_str("foo");
}
}
+
+// Issue #9542
+fn dyn_trait_ok(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
+ trait T {}
+ impl<U> T for Vec<U> {}
+ impl T for String {}
+ impl T for PathBuf {}
+ fn takes_dyn(_: &mut dyn T) {}
+
+ takes_dyn(a);
+ takes_dyn(b);
+ takes_dyn(c);
+}
+
+fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
+ trait T {}
+ impl<U> T for Vec<U> {}
+ impl<U> T for [U] {}
+ impl T for String {}
+ impl T for str {}
+ impl T for PathBuf {}
+ impl T for Path {}
+ fn takes_dyn(_: &mut dyn T) {}
+
+ takes_dyn(a);
+ takes_dyn(b);
+ takes_dyn(c);
+}
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index d64b5f454..6b4de98ce 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -162,5 +162,23 @@ error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a sl
LL | fn mut_vec_slice_methods(v: &mut Vec<u32>) {
| ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
-error: aborting due to 17 previous errors
+error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do
+ --> $DIR/ptr_arg.rs:224:17
+ |
+LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
+ | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]`
+
+error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do
+ --> $DIR/ptr_arg.rs:224:35
+ |
+LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
+ | ^^^^^^^^^^^ help: change this to: `&mut str`
+
+error: writing `&mut PathBuf` instead of `&mut Path` involves a new object where a slice will do
+ --> $DIR/ptr_arg.rs:224:51
+ |
+LL | fn dyn_trait(a: &mut Vec<u32>, b: &mut String, c: &mut PathBuf) {
+ | ^^^^^^^^^^^^ help: change this to: `&mut Path`
+
+error: aborting due to 20 previous errors
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
index 718e391e8..c57e2990f 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.fixed
@@ -1,4 +1,5 @@
// run-rustfix
+#![allow(clippy::unnecessary_cast)]
fn main() {
let vec = vec![b'a', b'b', b'c'];
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
index f613742c7..3de7997ac 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.rs
@@ -1,4 +1,5 @@
// run-rustfix
+#![allow(clippy::unnecessary_cast)]
fn main() {
let vec = vec![b'a', b'b', b'c'];
diff --git a/src/tools/clippy/tests/ui/ptr_offset_with_cast.stderr b/src/tools/clippy/tests/ui/ptr_offset_with_cast.stderr
index fd45224ca..3ba40593d 100644
--- a/src/tools/clippy/tests/ui/ptr_offset_with_cast.stderr
+++ b/src/tools/clippy/tests/ui/ptr_offset_with_cast.stderr
@@ -1,5 +1,5 @@
error: use of `offset` with a `usize` casted to an `isize`
- --> $DIR/ptr_offset_with_cast.rs:12:17
+ --> $DIR/ptr_offset_with_cast.rs:13:17
|
LL | let _ = ptr.offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)`
@@ -7,7 +7,7 @@ LL | let _ = ptr.offset(offset_usize as isize);
= note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings`
error: use of `wrapping_offset` with a `usize` casted to an `isize`
- --> $DIR/ptr_offset_with_cast.rs:16:17
+ --> $DIR/ptr_offset_with_cast.rs:17:17
|
LL | let _ = ptr.wrapping_offset(offset_usize as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)`
diff --git a/src/tools/clippy/tests/ui/pub_use.stderr b/src/tools/clippy/tests/ui/pub_use.stderr
index 9ab710df8..ba4ee732c 100644
--- a/src/tools/clippy/tests/ui/pub_use.stderr
+++ b/src/tools/clippy/tests/ui/pub_use.stderr
@@ -4,8 +4,8 @@ error: using `pub use`
LL | pub use inner::Test;
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::pub-use` implied by `-D warnings`
= help: move the exported item to a public module instead
+ = note: `-D clippy::pub-use` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/question_mark.fixed b/src/tools/clippy/tests/ui/question_mark.fixed
index 57f23bd19..993389232 100644
--- a/src/tools/clippy/tests/ui/question_mark.fixed
+++ b/src/tools/clippy/tests/ui/question_mark.fixed
@@ -223,3 +223,12 @@ fn pattern() -> Result<(), PatternedError> {
}
fn main() {}
+
+// should not lint, `?` operator not available in const context
+const fn issue9175(option: Option<()>) -> Option<()> {
+ if option.is_none() {
+ return None;
+ }
+ //stuff
+ Some(())
+}
diff --git a/src/tools/clippy/tests/ui/question_mark.rs b/src/tools/clippy/tests/ui/question_mark.rs
index 436f027c2..9ae0d8882 100644
--- a/src/tools/clippy/tests/ui/question_mark.rs
+++ b/src/tools/clippy/tests/ui/question_mark.rs
@@ -259,3 +259,12 @@ fn pattern() -> Result<(), PatternedError> {
}
fn main() {}
+
+// should not lint, `?` operator not available in const context
+const fn issue9175(option: Option<()>) -> Option<()> {
+ if option.is_none() {
+ return None;
+ }
+ //stuff
+ Some(())
+}
diff --git a/src/tools/clippy/tests/ui/range_contains.fixed b/src/tools/clippy/tests/ui/range_contains.fixed
index 85d021b2f..824f00cb9 100644
--- a/src/tools/clippy/tests/ui/range_contains.fixed
+++ b/src/tools/clippy/tests/ui/range_contains.fixed
@@ -1,10 +1,12 @@
// run-rustfix
-#[warn(clippy::manual_range_contains)]
-#[allow(unused)]
-#[allow(clippy::no_effect)]
-#[allow(clippy::short_circuit_statement)]
-#[allow(clippy::unnecessary_operation)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_range_contains)]
+#![allow(unused)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::short_circuit_statement)]
+#![allow(clippy::unnecessary_operation)]
+
fn main() {
let x = 9_i32;
@@ -62,3 +64,17 @@ fn main() {
pub const fn in_range(a: i32) -> bool {
3 <= a && a <= 20
}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let x = 5;
+ x >= 8 && x < 34;
+}
+
+fn msrv_1_35() {
+ #![clippy::msrv = "1.35"]
+
+ let x = 5;
+ (8..35).contains(&x);
+}
diff --git a/src/tools/clippy/tests/ui/range_contains.rs b/src/tools/clippy/tests/ui/range_contains.rs
index 9a7a75dc1..df925eead 100644
--- a/src/tools/clippy/tests/ui/range_contains.rs
+++ b/src/tools/clippy/tests/ui/range_contains.rs
@@ -1,10 +1,12 @@
// run-rustfix
-#[warn(clippy::manual_range_contains)]
-#[allow(unused)]
-#[allow(clippy::no_effect)]
-#[allow(clippy::short_circuit_statement)]
-#[allow(clippy::unnecessary_operation)]
+#![feature(custom_inner_attributes)]
+#![warn(clippy::manual_range_contains)]
+#![allow(unused)]
+#![allow(clippy::no_effect)]
+#![allow(clippy::short_circuit_statement)]
+#![allow(clippy::unnecessary_operation)]
+
fn main() {
let x = 9_i32;
@@ -62,3 +64,17 @@ fn main() {
pub const fn in_range(a: i32) -> bool {
3 <= a && a <= 20
}
+
+fn msrv_1_34() {
+ #![clippy::msrv = "1.34"]
+
+ let x = 5;
+ x >= 8 && x < 34;
+}
+
+fn msrv_1_35() {
+ #![clippy::msrv = "1.35"]
+
+ let x = 5;
+ x >= 8 && x < 35;
+}
diff --git a/src/tools/clippy/tests/ui/range_contains.stderr b/src/tools/clippy/tests/ui/range_contains.stderr
index 936859db5..9689e665b 100644
--- a/src/tools/clippy/tests/ui/range_contains.stderr
+++ b/src/tools/clippy/tests/ui/range_contains.stderr
@@ -1,5 +1,5 @@
error: manual `Range::contains` implementation
- --> $DIR/range_contains.rs:12:5
+ --> $DIR/range_contains.rs:14:5
|
LL | x >= 8 && x < 12;
| ^^^^^^^^^^^^^^^^ help: use: `(8..12).contains(&x)`
@@ -7,118 +7,124 @@ LL | x >= 8 && x < 12;
= note: `-D clippy::manual-range-contains` implied by `-D warnings`
error: manual `Range::contains` implementation
- --> $DIR/range_contains.rs:13:5
+ --> $DIR/range_contains.rs:15:5
|
LL | x < 42 && x >= 21;
| ^^^^^^^^^^^^^^^^^ help: use: `(21..42).contains(&x)`
error: manual `Range::contains` implementation
- --> $DIR/range_contains.rs:14:5
+ --> $DIR/range_contains.rs:16:5
|
LL | 100 > x && 1 <= x;
| ^^^^^^^^^^^^^^^^^ help: use: `(1..100).contains(&x)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:17:5
+ --> $DIR/range_contains.rs:19:5
|
LL | x >= 9 && x <= 99;
| ^^^^^^^^^^^^^^^^^ help: use: `(9..=99).contains(&x)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:18:5
+ --> $DIR/range_contains.rs:20:5
|
LL | x <= 33 && x >= 1;
| ^^^^^^^^^^^^^^^^^ help: use: `(1..=33).contains(&x)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:19:5
+ --> $DIR/range_contains.rs:21:5
|
LL | 999 >= x && 1 <= x;
| ^^^^^^^^^^^^^^^^^^ help: use: `(1..=999).contains(&x)`
error: manual `!Range::contains` implementation
- --> $DIR/range_contains.rs:22:5
+ --> $DIR/range_contains.rs:24:5
|
LL | x < 8 || x >= 12;
| ^^^^^^^^^^^^^^^^ help: use: `!(8..12).contains(&x)`
error: manual `!Range::contains` implementation
- --> $DIR/range_contains.rs:23:5
+ --> $DIR/range_contains.rs:25:5
|
LL | x >= 42 || x < 21;
| ^^^^^^^^^^^^^^^^^ help: use: `!(21..42).contains(&x)`
error: manual `!Range::contains` implementation
- --> $DIR/range_contains.rs:24:5
+ --> $DIR/range_contains.rs:26:5
|
LL | 100 <= x || 1 > x;
| ^^^^^^^^^^^^^^^^^ help: use: `!(1..100).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:27:5
+ --> $DIR/range_contains.rs:29:5
|
LL | x < 9 || x > 99;
| ^^^^^^^^^^^^^^^ help: use: `!(9..=99).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:28:5
+ --> $DIR/range_contains.rs:30:5
|
LL | x > 33 || x < 1;
| ^^^^^^^^^^^^^^^ help: use: `!(1..=33).contains(&x)`
error: manual `!RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:29:5
+ --> $DIR/range_contains.rs:31:5
|
LL | 999 < x || 1 > x;
| ^^^^^^^^^^^^^^^^ help: use: `!(1..=999).contains(&x)`
error: manual `Range::contains` implementation
- --> $DIR/range_contains.rs:44:5
+ --> $DIR/range_contains.rs:46:5
|
LL | y >= 0. && y < 1.;
| ^^^^^^^^^^^^^^^^^ help: use: `(0. ..1.).contains(&y)`
error: manual `!RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:45:5
+ --> $DIR/range_contains.rs:47:5
|
LL | y < 0. || y > 1.;
| ^^^^^^^^^^^^^^^^ help: use: `!(0. ..=1.).contains(&y)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:48:5
+ --> $DIR/range_contains.rs:50:5
|
LL | x >= -10 && x <= 10;
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-10..=10).contains(&x)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:50:5
+ --> $DIR/range_contains.rs:52:5
|
LL | y >= -3. && y <= 3.;
| ^^^^^^^^^^^^^^^^^^^ help: use: `(-3. ..=3.).contains(&y)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:55:30
+ --> $DIR/range_contains.rs:57:30
|
LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
| ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&z)`
error: manual `RangeInclusive::contains` implementation
- --> $DIR/range_contains.rs:55:5
+ --> $DIR/range_contains.rs:57:5
|
LL | (x >= 0) && (x <= 10) && (z >= 0) && (z <= 10);
| ^^^^^^^^^^^^^^^^^^^^^ help: use: `(0..=10).contains(&x)`
error: manual `!Range::contains` implementation
- --> $DIR/range_contains.rs:56:29
+ --> $DIR/range_contains.rs:58:29
|
LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
| ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&z)`
error: manual `!Range::contains` implementation
- --> $DIR/range_contains.rs:56:5
+ --> $DIR/range_contains.rs:58:5
|
LL | (x < 0) || (x >= 10) || (z < 0) || (z >= 10);
| ^^^^^^^^^^^^^^^^^^^^ help: use: `!(0..10).contains(&x)`
-error: aborting due to 20 previous errors
+error: manual `Range::contains` implementation
+ --> $DIR/range_contains.rs:79:5
+ |
+LL | x >= 8 && x < 35;
+ | ^^^^^^^^^^^^^^^^ help: use: `(8..35).contains(&x)`
+
+error: aborting due to 21 previous errors
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
index cd7d91e12..7814f5b54 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/arc.stderr
@@ -4,8 +4,8 @@ error: initializing a reference-counted pointer in `vec![elem; len]`
LL | let v = vec![Arc::new("x".to_string()); 2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
= note: each element will point to the same `Arc` instance
+ = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
help: consider initializing each `Arc` element individually
|
LL ~ let v = {
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
index fe861afe0..80deb7cb9 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/rc.stderr
@@ -4,8 +4,8 @@ error: initializing a reference-counted pointer in `vec![elem; len]`
LL | let v = vec![Rc::new("x".to_string()); 2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
= note: each element will point to the same `Rc` instance
+ = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
help: consider initializing each `Rc` element individually
|
LL ~ let v = {
diff --git a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
index 4a21946cc..789e14a30 100644
--- a/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
+++ b/src/tools/clippy/tests/ui/rc_clone_in_vec_init/weak.stderr
@@ -4,8 +4,8 @@ error: initializing a reference-counted pointer in `vec![elem; len]`
LL | let v = vec![SyncWeak::<u32>::new(); 2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
= note: each element will point to the same `Weak` instance
+ = note: `-D clippy::rc-clone-in-vec-init` implied by `-D warnings`
help: consider initializing each `Weak` element individually
|
LL ~ let v = {
diff --git a/src/tools/clippy/tests/ui/rc_mutex.stderr b/src/tools/clippy/tests/ui/rc_mutex.stderr
index fe84361d7..cee3bd8b2 100644
--- a/src/tools/clippy/tests/ui/rc_mutex.stderr
+++ b/src/tools/clippy/tests/ui/rc_mutex.stderr
@@ -4,8 +4,8 @@ error: usage of `Rc<Mutex<_>>`
LL | foo: Rc<Mutex<i32>>,
| ^^^^^^^^^^^^^^
|
- = note: `-D clippy::rc-mutex` implied by `-D warnings`
= help: consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead
+ = note: `-D clippy::rc-mutex` implied by `-D warnings`
error: usage of `Rc<Mutex<_>>`
--> $DIR/rc_mutex.rs:26:18
diff --git a/src/tools/clippy/tests/ui/recursive_format_impl.rs b/src/tools/clippy/tests/ui/recursive_format_impl.rs
index cb6ba36b1..b92490b4c 100644
--- a/src/tools/clippy/tests/ui/recursive_format_impl.rs
+++ b/src/tools/clippy/tests/ui/recursive_format_impl.rs
@@ -1,9 +1,10 @@
#![warn(clippy::recursive_format_impl)]
#![allow(
+ clippy::borrow_deref_ref,
+ clippy::deref_addrof,
clippy::inherent_to_string_shadow_display,
clippy::to_string_in_format_args,
- clippy::deref_addrof,
- clippy::borrow_deref_ref
+ clippy::uninlined_format_args
)]
use std::fmt;
diff --git a/src/tools/clippy/tests/ui/recursive_format_impl.stderr b/src/tools/clippy/tests/ui/recursive_format_impl.stderr
index 84ce69df5..8a58b9a3b 100644
--- a/src/tools/clippy/tests/ui/recursive_format_impl.stderr
+++ b/src/tools/clippy/tests/ui/recursive_format_impl.stderr
@@ -1,5 +1,5 @@
error: using `self.to_string` in `fmt::Display` implementation will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:30:25
+ --> $DIR/recursive_format_impl.rs:31:25
|
LL | write!(f, "{}", self.to_string())
| ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | write!(f, "{}", self.to_string())
= note: `-D clippy::recursive-format-impl` implied by `-D warnings`
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:74:9
+ --> $DIR/recursive_format_impl.rs:75:9
|
LL | write!(f, "{}", self)
| ^^^^^^^^^^^^^^^^^^^^^
@@ -15,7 +15,7 @@ LL | write!(f, "{}", self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:83:9
+ --> $DIR/recursive_format_impl.rs:84:9
|
LL | write!(f, "{}", &self)
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -23,7 +23,7 @@ LL | write!(f, "{}", &self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Debug` in `impl Debug` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:89:9
+ --> $DIR/recursive_format_impl.rs:90:9
|
LL | write!(f, "{:?}", &self)
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -31,7 +31,7 @@ LL | write!(f, "{:?}", &self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:98:9
+ --> $DIR/recursive_format_impl.rs:99:9
|
LL | write!(f, "{}", &&&self)
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -39,7 +39,7 @@ LL | write!(f, "{}", &&&self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:172:9
+ --> $DIR/recursive_format_impl.rs:173:9
|
LL | write!(f, "{}", &*self)
| ^^^^^^^^^^^^^^^^^^^^^^^
@@ -47,7 +47,7 @@ LL | write!(f, "{}", &*self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Debug` in `impl Debug` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:178:9
+ --> $DIR/recursive_format_impl.rs:179:9
|
LL | write!(f, "{:?}", &*self)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -55,7 +55,7 @@ LL | write!(f, "{:?}", &*self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:194:9
+ --> $DIR/recursive_format_impl.rs:195:9
|
LL | write!(f, "{}", *self)
| ^^^^^^^^^^^^^^^^^^^^^^
@@ -63,7 +63,7 @@ LL | write!(f, "{}", *self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:210:9
+ --> $DIR/recursive_format_impl.rs:211:9
|
LL | write!(f, "{}", **&&*self)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,7 +71,7 @@ LL | write!(f, "{}", **&&*self)
= note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info)
error: using `self` as `Display` in `impl Display` will cause infinite recursion
- --> $DIR/recursive_format_impl.rs:226:9
+ --> $DIR/recursive_format_impl.rs:227:9
|
LL | write!(f, "{}", &&**&&*self)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/redundant_allocation.stderr b/src/tools/clippy/tests/ui/redundant_allocation.stderr
index 54d4d88db..e0826fefa 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation.stderr
+++ b/src/tools/clippy/tests/ui/redundant_allocation.stderr
@@ -4,9 +4,9 @@ error: usage of `Box<Rc<T>>`
LL | pub fn box_test6<T>(foo: Box<Rc<T>>) {}
| ^^^^^^^^^^
|
- = note: `-D clippy::redundant-allocation` implied by `-D warnings`
= note: `Rc<T>` is already on the heap, `Box<Rc<T>>` makes an extra allocation
= help: consider using just `Box<T>` or `Rc<T>`
+ = note: `-D clippy::redundant-allocation` implied by `-D warnings`
error: usage of `Box<Arc<T>>`
--> $DIR/redundant_allocation.rs:19:30
diff --git a/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr b/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
index fdd76ef17..8dd4a6a26 100644
--- a/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
+++ b/src/tools/clippy/tests/ui/redundant_allocation_fixable.stderr
@@ -4,8 +4,8 @@ error: usage of `Box<&T>`
LL | pub fn box_test1<T>(foo: Box<&T>) {}
| ^^^^^^^ help: try: `&T`
|
- = note: `-D clippy::redundant-allocation` implied by `-D warnings`
= note: `&T` is already a pointer, `Box<&T>` allocates a pointer on the heap
+ = note: `-D clippy::redundant-allocation` implied by `-D warnings`
error: usage of `Box<&MyStruct>`
--> $DIR/redundant_allocation_fixable.rs:28:27
diff --git a/src/tools/clippy/tests/ui/redundant_clone.fixed b/src/tools/clippy/tests/ui/redundant_clone.fixed
index da52c0acf..00b427450 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.fixed
+++ b/src/tools/clippy/tests/ui/redundant_clone.fixed
@@ -1,8 +1,8 @@
// run-rustfix
// rustfix-only-machine-applicable
-
#![feature(lint_reasons)]
-#![allow(clippy::implicit_clone, clippy::drop_non_drop)]
+#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
+
use std::ffi::OsString;
use std::path::Path;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.rs b/src/tools/clippy/tests/ui/redundant_clone.rs
index 5867d019d..f899127db 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.rs
+++ b/src/tools/clippy/tests/ui/redundant_clone.rs
@@ -1,8 +1,8 @@
// run-rustfix
// rustfix-only-machine-applicable
-
#![feature(lint_reasons)]
-#![allow(clippy::implicit_clone, clippy::drop_non_drop)]
+#![allow(clippy::drop_non_drop, clippy::implicit_clone, clippy::uninlined_format_args)]
+
use std::ffi::OsString;
use std::path::Path;
diff --git a/src/tools/clippy/tests/ui/redundant_clone.stderr b/src/tools/clippy/tests/ui/redundant_clone.stderr
index aa1dd7cbb..782590034 100644
--- a/src/tools/clippy/tests/ui/redundant_clone.stderr
+++ b/src/tools/clippy/tests/ui/redundant_clone.stderr
@@ -4,12 +4,12 @@ error: redundant clone
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^ help: remove this
|
- = note: `-D clippy::redundant-clone` implied by `-D warnings`
note: this value is dropped without further use
--> $DIR/redundant_clone.rs:10:14
|
LL | let _s = ["lorem", "ipsum"].join(" ").to_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::redundant-clone` implied by `-D warnings`
error: redundant clone
--> $DIR/redundant_clone.rs:13:15
diff --git a/src/tools/clippy/tests/ui/redundant_else.stderr b/src/tools/clippy/tests/ui/redundant_else.stderr
index 9000cdc81..de9d00a60 100644
--- a/src/tools/clippy/tests/ui/redundant_else.stderr
+++ b/src/tools/clippy/tests/ui/redundant_else.stderr
@@ -7,8 +7,8 @@ LL | | println!("yet don't pull down your hedge.");
LL | | }
| |_________^
|
- = note: `-D clippy::redundant-else` implied by `-D warnings`
= help: remove the `else` block and move the contents out
+ = note: `-D clippy::redundant-else` implied by `-D warnings`
error: redundant else block
--> $DIR/redundant_else.rs:17:16
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.fixed b/src/tools/clippy/tests/ui/redundant_field_names.fixed
index 5b4b8eeed..34ab552cb 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.fixed
+++ b/src/tools/clippy/tests/ui/redundant_field_names.fixed
@@ -1,4 +1,6 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::redundant_field_names)]
#![allow(clippy::no_effect, dead_code, unused_variables)]
@@ -69,3 +71,17 @@ fn issue_3476() {
S { foo: foo::<i32> };
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ let start = 0;
+ let _ = RangeFrom { start: start };
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ let start = 0;
+ let _ = RangeFrom { start };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.rs b/src/tools/clippy/tests/ui/redundant_field_names.rs
index 3f97b80c5..a051b1f96 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.rs
+++ b/src/tools/clippy/tests/ui/redundant_field_names.rs
@@ -1,4 +1,6 @@
// run-rustfix
+
+#![feature(custom_inner_attributes)]
#![warn(clippy::redundant_field_names)]
#![allow(clippy::no_effect, dead_code, unused_variables)]
@@ -69,3 +71,17 @@ fn issue_3476() {
S { foo: foo::<i32> };
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ let start = 0;
+ let _ = RangeFrom { start: start };
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ let start = 0;
+ let _ = RangeFrom { start: start };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_field_names.stderr b/src/tools/clippy/tests/ui/redundant_field_names.stderr
index 7976292df..8b82e062b 100644
--- a/src/tools/clippy/tests/ui/redundant_field_names.stderr
+++ b/src/tools/clippy/tests/ui/redundant_field_names.stderr
@@ -1,5 +1,5 @@
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:34:9
+ --> $DIR/redundant_field_names.rs:36:9
|
LL | gender: gender,
| ^^^^^^^^^^^^^^ help: replace it with: `gender`
@@ -7,40 +7,46 @@ LL | gender: gender,
= note: `-D clippy::redundant-field-names` implied by `-D warnings`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:35:9
+ --> $DIR/redundant_field_names.rs:37:9
|
LL | age: age,
| ^^^^^^^^ help: replace it with: `age`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:56:25
+ --> $DIR/redundant_field_names.rs:58:25
|
LL | let _ = RangeFrom { start: start };
| ^^^^^^^^^^^^ help: replace it with: `start`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:57:23
+ --> $DIR/redundant_field_names.rs:59:23
|
LL | let _ = RangeTo { end: end };
| ^^^^^^^^ help: replace it with: `end`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:58:21
+ --> $DIR/redundant_field_names.rs:60:21
|
LL | let _ = Range { start: start, end: end };
| ^^^^^^^^^^^^ help: replace it with: `start`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:58:35
+ --> $DIR/redundant_field_names.rs:60:35
|
LL | let _ = Range { start: start, end: end };
| ^^^^^^^^ help: replace it with: `end`
error: redundant field names in struct initialization
- --> $DIR/redundant_field_names.rs:60:32
+ --> $DIR/redundant_field_names.rs:62:32
|
LL | let _ = RangeToInclusive { end: end };
| ^^^^^^^^ help: replace it with: `end`
-error: aborting due to 7 previous errors
+error: redundant field names in struct initialization
+ --> $DIR/redundant_field_names.rs:86:25
+ |
+LL | let _ = RangeFrom { start: start };
+ | ^^^^^^^^^^^^ help: replace it with: `start`
+
+error: aborting due to 8 previous errors
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
index eb7aa70ee..23f08103f 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_drop_order.stderr
@@ -4,9 +4,9 @@ error: redundant pattern matching, consider using `is_ok()`
LL | if let Ok(_) = m.lock() {}
| -------^^^^^----------- help: try this: `if m.lock().is_ok()`
|
- = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
= note: this will change drop order of the result, as well as all temporaries
= note: add `#[allow(clippy::redundant_pattern_matching)]` if this is important
+ = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_err()`
--> $DIR/redundant_pattern_matching_drop_order.rs:13:12
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
index acc8de5f4..21bae9095 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
@@ -1,8 +1,11 @@
// run-rustfix
-
-#![warn(clippy::all)]
-#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![warn(clippy::all, clippy::redundant_pattern_matching)]
+#![allow(unused_must_use)]
+#![allow(
+ clippy::match_like_matches_macro,
+ clippy::needless_bool,
+ clippy::uninlined_format_args
+)]
use std::net::{
IpAddr::{self, V4, V6},
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
index 678d91ce9..4dd917167 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
@@ -1,8 +1,11 @@
// run-rustfix
-
-#![warn(clippy::all)]
-#![warn(clippy::redundant_pattern_matching)]
-#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+#![warn(clippy::all, clippy::redundant_pattern_matching)]
+#![allow(unused_must_use)]
+#![allow(
+ clippy::match_like_matches_macro,
+ clippy::needless_bool,
+ clippy::uninlined_format_args
+)]
use std::net::{
IpAddr::{self, V4, V6},
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
index caf458cd8..536b589de 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
@@ -1,5 +1,5 @@
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:14:12
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:17:12
|
LL | if let V4(_) = &ipaddr {}
| -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()`
@@ -7,31 +7,31 @@ LL | if let V4(_) = &ipaddr {}
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:16:12
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:19:12
|
LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
| -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:21:12
|
LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
| -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:20:15
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:23:15
|
LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
| ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:22:15
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:25:15
|
LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
| ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:32:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:35:5
|
LL | / match V4(Ipv4Addr::LOCALHOST) {
LL | | V4(_) => true,
@@ -40,7 +40,7 @@ LL | | };
| |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:37:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:40:5
|
LL | / match V4(Ipv4Addr::LOCALHOST) {
LL | | V4(_) => false,
@@ -49,7 +49,7 @@ LL | | };
| |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:42:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:45:5
|
LL | / match V6(Ipv6Addr::LOCALHOST) {
LL | | V4(_) => false,
@@ -58,7 +58,7 @@ LL | | };
| |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:47:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:50:5
|
LL | / match V6(Ipv6Addr::LOCALHOST) {
LL | | V4(_) => true,
@@ -67,49 +67,49 @@ LL | | };
| |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:52:20
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:55:20
|
LL | let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) {
| -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:60:20
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:63:20
|
LL | let _ = if let V4(_) = gen_ipaddr() {
| -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:62:19
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:65:19
|
LL | } else if let V6(_) = gen_ipaddr() {
| -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:74:12
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:77:12
|
LL | if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
| -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:76:12
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:79:12
|
LL | if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
| -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:78:15
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:81:15
|
LL | while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
| ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:80:15
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:83:15
|
LL | while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
| ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
error: redundant pattern matching, consider using `is_ipv4()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:82:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:85:5
|
LL | / match V4(Ipv4Addr::LOCALHOST) {
LL | | V4(_) => true,
@@ -118,7 +118,7 @@ LL | | };
| |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
error: redundant pattern matching, consider using `is_ipv6()`
- --> $DIR/redundant_pattern_matching_ipaddr.rs:87:5
+ --> $DIR/redundant_pattern_matching_ipaddr.rs:90:5
|
LL | / match V6(Ipv6Addr::LOCALHOST) {
LL | | V4(_) => false,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
index 83c783385..b88c5d0be 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
@@ -1,14 +1,13 @@
// run-rustfix
-
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
+#![allow(deprecated, unused_must_use)]
#![allow(
- unused_must_use,
- clippy::needless_bool,
+ clippy::if_same_then_else,
clippy::match_like_matches_macro,
- clippy::unnecessary_wraps,
- deprecated,
- clippy::if_same_then_else
+ clippy::needless_bool,
+ clippy::uninlined_format_args,
+ clippy::unnecessary_wraps
)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
index e06d4485a..5949cb227 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
@@ -1,14 +1,13 @@
// run-rustfix
-
#![warn(clippy::all)]
#![warn(clippy::redundant_pattern_matching)]
+#![allow(deprecated, unused_must_use)]
#![allow(
- unused_must_use,
- clippy::needless_bool,
+ clippy::if_same_then_else,
clippy::match_like_matches_macro,
- clippy::unnecessary_wraps,
- deprecated,
- clippy::if_same_then_else
+ clippy::needless_bool,
+ clippy::uninlined_format_args,
+ clippy::unnecessary_wraps
)]
fn main() {
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
index d674d061e..e6afe9eb7 100644
--- a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
+++ b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
@@ -1,5 +1,5 @@
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:16:12
+ --> $DIR/redundant_pattern_matching_result.rs:15:12
|
LL | if let Ok(_) = &result {}
| -------^^^^^---------- help: try this: `if result.is_ok()`
@@ -7,31 +7,31 @@ LL | if let Ok(_) = &result {}
= note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:18:12
+ --> $DIR/redundant_pattern_matching_result.rs:17:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:20:12
+ --> $DIR/redundant_pattern_matching_result.rs:19:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:22:15
+ --> $DIR/redundant_pattern_matching_result.rs:21:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:24:15
+ --> $DIR/redundant_pattern_matching_result.rs:23:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:34:5
+ --> $DIR/redundant_pattern_matching_result.rs:33:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
@@ -40,7 +40,7 @@ LL | | };
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:39:5
+ --> $DIR/redundant_pattern_matching_result.rs:38:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => false,
@@ -49,7 +49,7 @@ LL | | };
| |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:44:5
+ --> $DIR/redundant_pattern_matching_result.rs:43:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,
@@ -58,7 +58,7 @@ LL | | };
| |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:49:5
+ --> $DIR/redundant_pattern_matching_result.rs:48:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => true,
@@ -67,73 +67,73 @@ LL | | };
| |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:54:20
+ --> $DIR/redundant_pattern_matching_result.rs:53:20
|
LL | let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
| -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:60:20
+ --> $DIR/redundant_pattern_matching_result.rs:59:20
|
LL | let _ = if let Ok(_) = gen_res() {
| -------^^^^^------------ help: try this: `if gen_res().is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:62:19
+ --> $DIR/redundant_pattern_matching_result.rs:61:19
|
LL | } else if let Err(_) = gen_res() {
| -------^^^^^^------------ help: try this: `if gen_res().is_err()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:85:19
+ --> $DIR/redundant_pattern_matching_result.rs:84:19
|
LL | while let Some(_) = r#try!(result_opt()) {}
| ----------^^^^^^^----------------------- help: try this: `while (r#try!(result_opt())).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:86:16
+ --> $DIR/redundant_pattern_matching_result.rs:85:16
|
LL | if let Some(_) = r#try!(result_opt()) {}
| -------^^^^^^^----------------------- help: try this: `if (r#try!(result_opt())).is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:92:12
+ --> $DIR/redundant_pattern_matching_result.rs:91:12
|
LL | if let Some(_) = m!() {}
| -------^^^^^^^------- help: try this: `if m!().is_some()`
error: redundant pattern matching, consider using `is_some()`
- --> $DIR/redundant_pattern_matching_result.rs:93:15
+ --> $DIR/redundant_pattern_matching_result.rs:92:15
|
LL | while let Some(_) = m!() {}
| ----------^^^^^^^------- help: try this: `while m!().is_some()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:111:12
+ --> $DIR/redundant_pattern_matching_result.rs:110:12
|
LL | if let Ok(_) = Ok::<i32, i32>(42) {}
| -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:113:12
+ --> $DIR/redundant_pattern_matching_result.rs:112:12
|
LL | if let Err(_) = Err::<i32, i32>(42) {}
| -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:115:15
+ --> $DIR/redundant_pattern_matching_result.rs:114:15
|
LL | while let Ok(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:117:15
+ --> $DIR/redundant_pattern_matching_result.rs:116:15
|
LL | while let Err(_) = Ok::<i32, i32>(10) {}
| ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
error: redundant pattern matching, consider using `is_ok()`
- --> $DIR/redundant_pattern_matching_result.rs:119:5
+ --> $DIR/redundant_pattern_matching_result.rs:118:5
|
LL | / match Ok::<i32, i32>(42) {
LL | | Ok(_) => true,
@@ -142,7 +142,7 @@ LL | | };
| |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
error: redundant pattern matching, consider using `is_err()`
- --> $DIR/redundant_pattern_matching_result.rs:124:5
+ --> $DIR/redundant_pattern_matching_result.rs:123:5
|
LL | / match Err::<i32, i32>(42) {
LL | | Ok(_) => false,
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
index acc8f1e25..42110dbe8 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(unused)]
#[derive(Debug)]
@@ -54,3 +55,15 @@ impl Foo {
impl Bar for Foo {
const TRAIT_VAR: &'static str = "foo";
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ static V: &'static u8 = &16;
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ static V: &u8 = &17;
+}
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
index f2f0f7865..bc5200bc8 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
@@ -1,5 +1,6 @@
// run-rustfix
+#![feature(custom_inner_attributes)]
#![allow(unused)]
#[derive(Debug)]
@@ -54,3 +55,15 @@ impl Foo {
impl Bar for Foo {
const TRAIT_VAR: &'static str = "foo";
}
+
+fn msrv_1_16() {
+ #![clippy::msrv = "1.16"]
+
+ static V: &'static u8 = &16;
+}
+
+fn msrv_1_17() {
+ #![clippy::msrv = "1.17"]
+
+ static V: &'static u8 = &17;
+}
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
index 649831f9c..735113460 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
@@ -1,5 +1,5 @@
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:8:17
+ --> $DIR/redundant_static_lifetimes.rs:9:17
|
LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removing 'static.
| -^^^^^^^---- help: consider removing `'static`: `&str`
@@ -7,94 +7,100 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR Consider removin
= note: `-D clippy::redundant-static-lifetimes` implied by `-D warnings`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:12:21
+ --> $DIR/redundant_static_lifetimes.rs:13:21
|
LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
| -^^^^^^^---- help: consider removing `'static`: `&str`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:14:32
+ --> $DIR/redundant_static_lifetimes.rs:15:32
|
LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
| -^^^^^^^---- help: consider removing `'static`: `&str`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:14:47
+ --> $DIR/redundant_static_lifetimes.rs:15:47
|
LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR Consider removing 'static
| -^^^^^^^---- help: consider removing `'static`: `&str`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:16:17
+ --> $DIR/redundant_static_lifetimes.rs:17:17
|
LL | const VAR_SIX: &'static u8 = &5;
| -^^^^^^^--- help: consider removing `'static`: `&u8`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:18:20
+ --> $DIR/redundant_static_lifetimes.rs:19:20
|
LL | const VAR_HEIGHT: &'static Foo = &Foo {};
| -^^^^^^^---- help: consider removing `'static`: `&Foo`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:20:19
+ --> $DIR/redundant_static_lifetimes.rs:21:19
|
LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR Consider removing 'static.
| -^^^^^^^----- help: consider removing `'static`: `&[u8]`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:22:19
+ --> $DIR/redundant_static_lifetimes.rs:23:19
|
LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
| -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
error: constants have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:24:19
+ --> $DIR/redundant_static_lifetimes.rs:25:19
|
LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
| -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:26:25
+ --> $DIR/redundant_static_lifetimes.rs:27:25
|
LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR Consider removing 'static.
| -^^^^^^^---- help: consider removing `'static`: `&str`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:30:29
+ --> $DIR/redundant_static_lifetimes.rs:31:29
|
LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR Consider removing 'static
| -^^^^^^^---- help: consider removing `'static`: `&str`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:32:25
+ --> $DIR/redundant_static_lifetimes.rs:33:25
|
LL | static STATIC_VAR_SIX: &'static u8 = &5;
| -^^^^^^^--- help: consider removing `'static`: `&u8`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:34:28
+ --> $DIR/redundant_static_lifetimes.rs:35:28
|
LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {};
| -^^^^^^^---- help: consider removing `'static`: `&Foo`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:36:27
+ --> $DIR/redundant_static_lifetimes.rs:37:27
|
LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR Consider removing 'static.
| -^^^^^^^----- help: consider removing `'static`: `&[u8]`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:38:27
+ --> $DIR/redundant_static_lifetimes.rs:39:27
|
LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR Consider removing 'static.
| -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
error: statics have by default a `'static` lifetime
- --> $DIR/redundant_static_lifetimes.rs:40:27
+ --> $DIR/redundant_static_lifetimes.rs:41:27
|
LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR Consider removing 'static.
| -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
-error: aborting due to 16 previous errors
+error: statics have by default a `'static` lifetime
+ --> $DIR/redundant_static_lifetimes.rs:68:16
+ |
+LL | static V: &'static u8 = &17;
+ | -^^^^^^^--- help: consider removing `'static`: `&u8`
+
+error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/ref_option_ref.rs b/src/tools/clippy/tests/ui/ref_option_ref.rs
index 2df45c927..e487799e1 100644
--- a/src/tools/clippy/tests/ui/ref_option_ref.rs
+++ b/src/tools/clippy/tests/ui/ref_option_ref.rs
@@ -45,3 +45,8 @@ impl RefOptTrait for u32 {
fn main() {
let x: &Option<&u32> = &None;
}
+
+fn issue9682(arg: &Option<&mut String>) {
+ // Should not lint, as the inner ref is mutable making it non `Copy`
+ println!("{arg:?}");
+}
diff --git a/src/tools/clippy/tests/ui/regex.stderr b/src/tools/clippy/tests/ui/regex.stderr
index 1394a9b63..2424644c6 100644
--- a/src/tools/clippy/tests/ui/regex.stderr
+++ b/src/tools/clippy/tests/ui/regex.stderr
@@ -4,8 +4,8 @@ error: trivial regex
LL | let pipe_in_wrong_position = Regex::new("|");
| ^^^
|
- = note: `-D clippy::trivial-regex` implied by `-D warnings`
= help: the regex is unlikely to be useful as it is
+ = note: `-D clippy::trivial-regex` implied by `-D warnings`
error: trivial regex
--> $DIR/regex.rs:14:60
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 9cbad2269..8beae8dee 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -12,7 +12,7 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::for_loops_over_fallibles)]
+#![allow(for_loops_over_fallibles)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::match_result_ok)]
#![allow(clippy::overly_complex_bool_expr)]
@@ -32,6 +32,7 @@
#![allow(invalid_value)]
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
+#![allow(named_arguments_used_positionally)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
@@ -44,8 +45,8 @@
#![warn(clippy::disallowed_methods)]
#![warn(clippy::disallowed_types)]
#![warn(clippy::mixed_read_write_in_expression)]
-#![warn(clippy::for_loops_over_fallibles)]
-#![warn(clippy::for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
+#![warn(for_loops_over_fallibles)]
#![warn(clippy::useless_conversion)]
#![warn(clippy::match_result_ok)]
#![warn(clippy::overly_complex_bool_expr)]
@@ -64,11 +65,13 @@
#![warn(clippy::recursive_format_impl)]
#![warn(clippy::invisible_characters)]
#![warn(drop_bounds)]
+#![warn(for_loops_over_fallibles)]
#![warn(array_into_iter)]
#![warn(invalid_atomic_ordering)]
#![warn(invalid_value)]
#![warn(enum_intrinsics_non_enums)]
#![warn(non_fmt_panics)]
+#![warn(named_arguments_used_positionally)]
#![warn(temporary_cstring_as_ptr)]
#![warn(unknown_lints)]
#![warn(unused_labels)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 9153c0dab..9e665047b 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -12,7 +12,7 @@
#![allow(clippy::disallowed_methods)]
#![allow(clippy::disallowed_types)]
#![allow(clippy::mixed_read_write_in_expression)]
-#![allow(clippy::for_loops_over_fallibles)]
+#![allow(for_loops_over_fallibles)]
#![allow(clippy::useless_conversion)]
#![allow(clippy::match_result_ok)]
#![allow(clippy::overly_complex_bool_expr)]
@@ -32,6 +32,7 @@
#![allow(invalid_value)]
#![allow(enum_intrinsics_non_enums)]
#![allow(non_fmt_panics)]
+#![allow(named_arguments_used_positionally)]
#![allow(temporary_cstring_as_ptr)]
#![allow(unknown_lints)]
#![allow(unused_labels)]
@@ -64,11 +65,13 @@
#![warn(clippy::to_string_in_display)]
#![warn(clippy::zero_width_space)]
#![warn(clippy::drop_bounds)]
+#![warn(clippy::for_loops_over_fallibles)]
#![warn(clippy::into_iter_on_array)]
#![warn(clippy::invalid_atomic_ordering)]
#![warn(clippy::invalid_ref)]
#![warn(clippy::mem_discriminant_non_enum)]
#![warn(clippy::panic_params)]
+#![warn(clippy::positional_named_format_parameters)]
#![warn(clippy::temporary_cstring_as_ptr)]
#![warn(clippy::unknown_clippy_lints)]
#![warn(clippy::unused_label)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 9c03ea914..63eb56518 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
- --> $DIR/rename.rs:38:9
+ --> $DIR/rename.rs:39:9
|
LL | #![warn(clippy::blacklisted_name)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
@@ -7,220 +7,232 @@ LL | #![warn(clippy::blacklisted_name)]
= note: `-D renamed-and-removed-lints` implied by `-D warnings`
error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:39:9
+ --> $DIR/rename.rs:40:9
|
LL | #![warn(clippy::block_in_if_condition_expr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
- --> $DIR/rename.rs:40:9
+ --> $DIR/rename.rs:41:9
|
LL | #![warn(clippy::block_in_if_condition_stmt)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
- --> $DIR/rename.rs:41:9
+ --> $DIR/rename.rs:42:9
|
LL | #![warn(clippy::box_vec)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
- --> $DIR/rename.rs:42:9
+ --> $DIR/rename.rs:43:9
|
LL | #![warn(clippy::const_static_lifetime)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
- --> $DIR/rename.rs:43:9
+ --> $DIR/rename.rs:44:9
|
LL | #![warn(clippy::cyclomatic_complexity)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
- --> $DIR/rename.rs:44:9
+ --> $DIR/rename.rs:45:9
|
LL | #![warn(clippy::disallowed_method)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
- --> $DIR/rename.rs:45:9
+ --> $DIR/rename.rs:46:9
|
LL | #![warn(clippy::disallowed_type)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
- --> $DIR/rename.rs:46:9
+ --> $DIR/rename.rs:47:9
|
LL | #![warn(clippy::eval_order_dependence)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
-error: lint `clippy::for_loop_over_option` has been renamed to `clippy::for_loops_over_fallibles`
- --> $DIR/rename.rs:47:9
+error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
+ --> $DIR/rename.rs:48:9
|
LL | #![warn(clippy::for_loop_over_option)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
-error: lint `clippy::for_loop_over_result` has been renamed to `clippy::for_loops_over_fallibles`
- --> $DIR/rename.rs:48:9
+error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
+ --> $DIR/rename.rs:49:9
|
LL | #![warn(clippy::for_loop_over_result)]
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::for_loops_over_fallibles`
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
- --> $DIR/rename.rs:49:9
+ --> $DIR/rename.rs:50:9
|
LL | #![warn(clippy::identity_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
- --> $DIR/rename.rs:50:9
+ --> $DIR/rename.rs:51:9
|
LL | #![warn(clippy::if_let_some_result)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
- --> $DIR/rename.rs:51:9
+ --> $DIR/rename.rs:52:9
|
LL | #![warn(clippy::logic_bug)]
| ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
- --> $DIR/rename.rs:52:9
+ --> $DIR/rename.rs:53:9
|
LL | #![warn(clippy::new_without_default_derive)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
- --> $DIR/rename.rs:53:9
+ --> $DIR/rename.rs:54:9
|
LL | #![warn(clippy::option_and_then_some)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:54:9
+ --> $DIR/rename.rs:55:9
|
LL | #![warn(clippy::option_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:55:9
+ --> $DIR/rename.rs:56:9
|
LL | #![warn(clippy::option_map_unwrap_or)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:56:9
+ --> $DIR/rename.rs:57:9
|
LL | #![warn(clippy::option_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:57:9
+ --> $DIR/rename.rs:58:9
|
LL | #![warn(clippy::option_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
- --> $DIR/rename.rs:58:9
+ --> $DIR/rename.rs:59:9
|
LL | #![warn(clippy::ref_in_deref)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
- --> $DIR/rename.rs:59:9
+ --> $DIR/rename.rs:60:9
|
LL | #![warn(clippy::result_expect_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
- --> $DIR/rename.rs:60:9
+ --> $DIR/rename.rs:61:9
|
LL | #![warn(clippy::result_map_unwrap_or_else)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
- --> $DIR/rename.rs:61:9
+ --> $DIR/rename.rs:62:9
|
LL | #![warn(clippy::result_unwrap_used)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
- --> $DIR/rename.rs:62:9
+ --> $DIR/rename.rs:63:9
|
LL | #![warn(clippy::single_char_push_str)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
- --> $DIR/rename.rs:63:9
+ --> $DIR/rename.rs:64:9
|
LL | #![warn(clippy::stutter)]
| ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
- --> $DIR/rename.rs:64:9
+ --> $DIR/rename.rs:65:9
|
LL | #![warn(clippy::to_string_in_display)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
- --> $DIR/rename.rs:65:9
+ --> $DIR/rename.rs:66:9
|
LL | #![warn(clippy::zero_width_space)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
- --> $DIR/rename.rs:66:9
+ --> $DIR/rename.rs:67:9
|
LL | #![warn(clippy::drop_bounds)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
+error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
+ --> $DIR/rename.rs:68:9
+ |
+LL | #![warn(clippy::for_loops_over_fallibles)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
+
error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
- --> $DIR/rename.rs:67:9
+ --> $DIR/rename.rs:69:9
|
LL | #![warn(clippy::into_iter_on_array)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
- --> $DIR/rename.rs:68:9
+ --> $DIR/rename.rs:70:9
|
LL | #![warn(clippy::invalid_atomic_ordering)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
- --> $DIR/rename.rs:69:9
+ --> $DIR/rename.rs:71:9
|
LL | #![warn(clippy::invalid_ref)]
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
- --> $DIR/rename.rs:70:9
+ --> $DIR/rename.rs:72:9
|
LL | #![warn(clippy::mem_discriminant_non_enum)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
- --> $DIR/rename.rs:71:9
+ --> $DIR/rename.rs:73:9
|
LL | #![warn(clippy::panic_params)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
+error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
+ --> $DIR/rename.rs:74:9
+ |
+LL | #![warn(clippy::positional_named_format_parameters)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
+
error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
- --> $DIR/rename.rs:72:9
+ --> $DIR/rename.rs:75:9
|
LL | #![warn(clippy::temporary_cstring_as_ptr)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
- --> $DIR/rename.rs:73:9
+ --> $DIR/rename.rs:76:9
|
LL | #![warn(clippy::unknown_clippy_lints)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
error: lint `clippy::unused_label` has been renamed to `unused_labels`
- --> $DIR/rename.rs:74:9
+ --> $DIR/rename.rs:77:9
|
LL | #![warn(clippy::unused_label)]
| ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
-error: aborting due to 37 previous errors
+error: aborting due to 39 previous errors
diff --git a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
index 57ebd47f8..e15633fb1 100644
--- a/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
+++ b/src/tools/clippy/tests/ui/rest_pat_in_fully_bound_structs.stderr
@@ -4,8 +4,8 @@ error: unnecessary use of `..` pattern in struct binding. All fields were alread
LL | A { a: 5, b: 42, c: "", .. } => {}, // Lint
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::rest-pat-in-fully-bound-structs` implied by `-D warnings`
= help: consider removing `..` from this binding
+ = note: `-D clippy::rest-pat-in-fully-bound-structs` implied by `-D warnings`
error: unnecessary use of `..` pattern in struct binding. All fields were already bound
--> $DIR/rest_pat_in_fully_bound_structs.rs:23:9
diff --git a/src/tools/clippy/tests/ui/result_large_err.stderr b/src/tools/clippy/tests/ui/result_large_err.stderr
index ef19f2854..bea101fe2 100644
--- a/src/tools/clippy/tests/ui/result_large_err.stderr
+++ b/src/tools/clippy/tests/ui/result_large_err.stderr
@@ -4,8 +4,8 @@ error: the `Err`-variant returned from this function is very large
LL | pub fn large_err() -> Result<(), [u8; 512]> {
| ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
|
- = note: `-D clippy::result-large-err` implied by `-D warnings`
= help: try reducing the size of `[u8; 512]`, for example by boxing large elements or replacing it with `Box<[u8; 512]>`
+ = note: `-D clippy::result-large-err` implied by `-D warnings`
error: the `Err`-variant returned from this function is very large
--> $DIR/result_large_err.rs:19:21
diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
index 14c331f67..d8b56237e 100644
--- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
+++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.fixed
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::result_map_unit_fn)]
#![allow(unused)]
+#![allow(clippy::uninlined_format_args)]
fn do_nothing<T>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
index 8b0fca9ec..44f50d211 100644
--- a/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
+++ b/src/tools/clippy/tests/ui/result_map_unit_fn_fixable.rs
@@ -1,7 +1,7 @@
// run-rustfix
-
#![warn(clippy::result_map_unit_fn)]
#![allow(unused)]
+#![allow(clippy::uninlined_format_args)]
fn do_nothing<T>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/result_unit_error.stderr b/src/tools/clippy/tests/ui/result_unit_error.stderr
index 8c7573eab..8393a4bf0 100644
--- a/src/tools/clippy/tests/ui/result_unit_error.stderr
+++ b/src/tools/clippy/tests/ui/result_unit_error.stderr
@@ -4,8 +4,8 @@ error: this returns a `Result<_, ()>`
LL | pub fn returns_unit_error() -> Result<u32, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::result-unit-err` implied by `-D warnings`
= help: use a custom `Error` type instead
+ = note: `-D clippy::result-unit-err` implied by `-D warnings`
error: this returns a `Result<_, ()>`
--> $DIR/result_unit_error.rs:12:5
diff --git a/src/tools/clippy/tests/ui/return_self_not_must_use.stderr b/src/tools/clippy/tests/ui/return_self_not_must_use.stderr
index 94be87dfa..34932fe1c 100644
--- a/src/tools/clippy/tests/ui/return_self_not_must_use.stderr
+++ b/src/tools/clippy/tests/ui/return_self_not_must_use.stderr
@@ -4,8 +4,8 @@ error: missing `#[must_use]` attribute on a method returning `Self`
LL | fn what(&self) -> Self;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::return-self-not-must-use` implied by `-D warnings`
= help: consider adding the `#[must_use]` attribute to the method or directly to the `Self` type
+ = note: `-D clippy::return-self-not-must-use` implied by `-D warnings`
error: missing `#[must_use]` attribute on a method returning `Self`
--> $DIR/return_self_not_must_use.rs:18:5
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
index 79e482eec..c67edb36c 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::reversed_empty_ranges)]
+#![allow(clippy::uninlined_format_args)]
const ANSWER: i32 = 42;
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
index b2e8bf337..0a4fef5bf 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::reversed_empty_ranges)]
+#![allow(clippy::uninlined_format_args)]
const ANSWER: i32 = 42;
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.stderr b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.stderr
index 2d1bfe62c..c2495ea95 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.stderr
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_fixable.stderr
@@ -1,5 +1,5 @@
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_fixable.rs:9:5
+ --> $DIR/reversed_empty_ranges_fixable.rs:10:5
|
LL | (42..=21).for_each(|x| println!("{}", x));
| ^^^^^^^^^
@@ -11,7 +11,7 @@ LL | (21..=42).rev().for_each(|x| println!("{}", x));
| ~~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_fixable.rs:10:13
+ --> $DIR/reversed_empty_ranges_fixable.rs:11:13
|
LL | let _ = (ANSWER..21).filter(|x| x % 2 == 0).take(10).collect::<Vec<_>>();
| ^^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | let _ = (21..ANSWER).rev().filter(|x| x % 2 == 0).take(10).collect::<Ve
| ~~~~~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_fixable.rs:12:14
+ --> $DIR/reversed_empty_ranges_fixable.rs:13:14
|
LL | for _ in -21..=-42 {}
| ^^^^^^^^^
@@ -33,7 +33,7 @@ LL | for _ in (-42..=-21).rev() {}
| ~~~~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_fixable.rs:13:14
+ --> $DIR/reversed_empty_ranges_fixable.rs:14:14
|
LL | for _ in 42u32..21u32 {}
| ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
index f1503ed6d..78401e463 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.fixed
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::reversed_empty_ranges)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
const MAX_LEN: usize = 42;
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
index a733788dc..f9e0f7fcd 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.rs
@@ -1,5 +1,6 @@
// run-rustfix
#![warn(clippy::reversed_empty_ranges)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
const MAX_LEN: usize = 42;
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.stderr b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.stderr
index a135da488..dfc52e64c 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.stderr
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_fixable.stderr
@@ -1,5 +1,5 @@
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:7:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:8:14
|
LL | for i in 10..0 {
| ^^^^^
@@ -11,7 +11,7 @@ LL | for i in (0..10).rev() {
| ~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:11:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:12:14
|
LL | for i in 10..=0 {
| ^^^^^^
@@ -22,7 +22,7 @@ LL | for i in (0..=10).rev() {
| ~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:15:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:16:14
|
LL | for i in MAX_LEN..0 {
| ^^^^^^^^^^
@@ -33,7 +33,7 @@ LL | for i in (0..MAX_LEN).rev() {
| ~~~~~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:34:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:35:14
|
LL | for i in (10..0).map(|x| x * 2) {
| ^^^^^^^
@@ -44,7 +44,7 @@ LL | for i in (0..10).rev().map(|x| x * 2) {
| ~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:39:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:40:14
|
LL | for i in 10..5 + 4 {
| ^^^^^^^^^
@@ -55,7 +55,7 @@ LL | for i in (5 + 4..10).rev() {
| ~~~~~~~~~~~~~~~~~
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_fixable.rs:43:14
+ --> $DIR/reversed_empty_ranges_loops_fixable.rs:44:14
|
LL | for i in (5 + 2)..(3 - 1) {
| ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.rs b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.rs
index c4c572244..50264ef68 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.rs
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.rs
@@ -1,4 +1,5 @@
#![warn(clippy::reversed_empty_ranges)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
for i in 5..5 {
diff --git a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.stderr b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.stderr
index 30095d20c..4490ff35f 100644
--- a/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/reversed_empty_ranges_loops_unfixable.stderr
@@ -1,5 +1,5 @@
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_unfixable.rs:4:14
+ --> $DIR/reversed_empty_ranges_loops_unfixable.rs:5:14
|
LL | for i in 5..5 {
| ^^^^
@@ -7,7 +7,7 @@ LL | for i in 5..5 {
= note: `-D clippy::reversed-empty-ranges` implied by `-D warnings`
error: this range is empty so it will yield no values
- --> $DIR/reversed_empty_ranges_loops_unfixable.rs:8:14
+ --> $DIR/reversed_empty_ranges_loops_unfixable.rs:9:14
|
LL | for i in (5 + 2)..(8 - 1) {
| ^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
index a48829caa..e6198a1bc 100644
--- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
+++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.rs
@@ -1,8 +1,14 @@
#![feature(adt_const_params)]
-#![allow(incomplete_features)]
#![warn(clippy::same_functions_in_if_condition)]
-#![allow(clippy::ifs_same_cond)] // This warning is different from `ifs_same_cond`.
-#![allow(clippy::if_same_then_else, clippy::comparison_chain)] // all empty blocks
+// ifs_same_cond warning is different from `ifs_same_cond`.
+// clippy::if_same_then_else, clippy::comparison_chain -- all empty blocks
+#![allow(incomplete_features)]
+#![allow(
+ clippy::comparison_chain,
+ clippy::if_same_then_else,
+ clippy::ifs_same_cond,
+ clippy::uninlined_format_args
+)]
fn function() -> bool {
true
diff --git a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
index cd438b830..f352ade15 100644
--- a/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
+++ b/src/tools/clippy/tests/ui/same_functions_in_if_condition.stderr
@@ -1,72 +1,72 @@
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:31:15
+ --> $DIR/same_functions_in_if_condition.rs:37:15
|
LL | } else if function() {
| ^^^^^^^^^^
|
- = note: `-D clippy::same-functions-in-if-condition` implied by `-D warnings`
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:30:8
+ --> $DIR/same_functions_in_if_condition.rs:36:8
|
LL | if function() {
| ^^^^^^^^^^
+ = note: `-D clippy::same-functions-in-if-condition` implied by `-D warnings`
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:36:15
+ --> $DIR/same_functions_in_if_condition.rs:42:15
|
LL | } else if fn_arg(a) {
| ^^^^^^^^^
|
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:35:8
+ --> $DIR/same_functions_in_if_condition.rs:41:8
|
LL | if fn_arg(a) {
| ^^^^^^^^^
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:41:15
+ --> $DIR/same_functions_in_if_condition.rs:47:15
|
LL | } else if obj.method() {
| ^^^^^^^^^^^^
|
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:40:8
+ --> $DIR/same_functions_in_if_condition.rs:46:8
|
LL | if obj.method() {
| ^^^^^^^^^^^^
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:46:15
+ --> $DIR/same_functions_in_if_condition.rs:52:15
|
LL | } else if obj.method_arg(a) {
| ^^^^^^^^^^^^^^^^^
|
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:45:8
+ --> $DIR/same_functions_in_if_condition.rs:51:8
|
LL | if obj.method_arg(a) {
| ^^^^^^^^^^^^^^^^^
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:53:15
+ --> $DIR/same_functions_in_if_condition.rs:59:15
|
LL | } else if v.pop().is_none() {
| ^^^^^^^^^^^^^^^^^
|
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:51:8
+ --> $DIR/same_functions_in_if_condition.rs:57:8
|
LL | if v.pop().is_none() {
| ^^^^^^^^^^^^^^^^^
error: this `if` has the same function call as a previous `if`
- --> $DIR/same_functions_in_if_condition.rs:58:15
+ --> $DIR/same_functions_in_if_condition.rs:64:15
|
LL | } else if v.len() == 42 {
| ^^^^^^^^^^^^^
|
note: same as this
- --> $DIR/same_functions_in_if_condition.rs:56:8
+ --> $DIR/same_functions_in_if_condition.rs:62:8
|
LL | if v.len() == 42 {
| ^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/same_item_push.stderr b/src/tools/clippy/tests/ui/same_item_push.stderr
index d9ffa1578..1d1254d9f 100644
--- a/src/tools/clippy/tests/ui/same_item_push.stderr
+++ b/src/tools/clippy/tests/ui/same_item_push.stderr
@@ -4,8 +4,8 @@ error: it looks like the same item is being pushed into this Vec
LL | vec.push(item);
| ^^^
|
- = note: `-D clippy::same-item-push` implied by `-D warnings`
= help: try using vec![item;SIZE] or vec.resize(NEW_SIZE, item)
+ = note: `-D clippy::same-item-push` implied by `-D warnings`
error: it looks like the same item is being pushed into this Vec
--> $DIR/same_item_push.rs:29:9
diff --git a/src/tools/clippy/tests/ui/same_name_method.stderr b/src/tools/clippy/tests/ui/same_name_method.stderr
index f55ec9f3c..0c6908c09 100644
--- a/src/tools/clippy/tests/ui/same_name_method.stderr
+++ b/src/tools/clippy/tests/ui/same_name_method.stderr
@@ -4,12 +4,12 @@ error: method's name is the same as an existing method in a trait
LL | fn foo() {}
| ^^^^^^^^^^^
|
- = note: `-D clippy::same-name-method` implied by `-D warnings`
note: existing `foo` defined here
--> $DIR/same_name_method.rs:25:13
|
LL | fn foo() {}
| ^^^^^^^^^^^
+ = note: `-D clippy::same-name-method` implied by `-D warnings`
error: method's name is the same as an existing method in a trait
--> $DIR/same_name_method.rs:35:13
diff --git a/src/tools/clippy/tests/ui/search_is_some.stderr b/src/tools/clippy/tests/ui/search_is_some.stderr
index 54760545b..6bea8c674 100644
--- a/src/tools/clippy/tests/ui/search_is_some.stderr
+++ b/src/tools/clippy/tests/ui/search_is_some.stderr
@@ -8,8 +8,8 @@ LL | | }
LL | | ).is_some();
| |______________________________^
|
- = note: `-D clippy::search-is-some` implied by `-D warnings`
= help: this is more succinctly expressed by calling `any()`
+ = note: `-D clippy::search-is-some` implied by `-D warnings`
error: called `is_some()` after searching an `Iterator` with `position`
--> $DIR/search_is_some.rs:20:13
diff --git a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
index c4dfbd921..4ab7dbab5 100644
--- a/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
+++ b/src/tools/clippy/tests/ui/semicolon_if_nothing_returned.rs
@@ -1,5 +1,5 @@
#![warn(clippy::semicolon_if_nothing_returned)]
-#![allow(clippy::redundant_closure)]
+#![allow(clippy::redundant_closure, clippy::uninlined_format_args)]
fn get_unit() {}
diff --git a/src/tools/clippy/tests/ui/shadow.stderr b/src/tools/clippy/tests/ui/shadow.stderr
index 43d76094d..c3d7bc2a5 100644
--- a/src/tools/clippy/tests/ui/shadow.stderr
+++ b/src/tools/clippy/tests/ui/shadow.stderr
@@ -4,12 +4,12 @@ error: `x` is shadowed by itself in `x`
LL | let x = x;
| ^
|
- = note: `-D clippy::shadow-same` implied by `-D warnings`
note: previous binding is here
--> $DIR/shadow.rs:5:9
|
LL | let x = 1;
| ^
+ = note: `-D clippy::shadow-same` implied by `-D warnings`
error: `mut x` is shadowed by itself in `&x`
--> $DIR/shadow.rs:7:13
@@ -53,12 +53,12 @@ error: `x` is shadowed
LL | let x = x.0;
| ^
|
- = note: `-D clippy::shadow-reuse` implied by `-D warnings`
note: previous binding is here
--> $DIR/shadow.rs:13:9
|
LL | let x = ([[0]], ());
| ^
+ = note: `-D clippy::shadow-reuse` implied by `-D warnings`
error: `x` is shadowed
--> $DIR/shadow.rs:15:9
@@ -150,12 +150,12 @@ error: `x` shadows a previous, unrelated binding
LL | let x = 2;
| ^
|
- = note: `-D clippy::shadow-unrelated` implied by `-D warnings`
note: previous binding is here
--> $DIR/shadow.rs:30:9
|
LL | let x = 1;
| ^
+ = note: `-D clippy::shadow-unrelated` implied by `-D warnings`
error: `x` shadows a previous, unrelated binding
--> $DIR/shadow.rs:36:13
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
index 2b7d4628c..161dd66b0 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_1.stderr
@@ -6,8 +6,8 @@ LL | | unimplemented!()
LL | | }
| |_____^
|
- = note: `-D clippy::should-implement-trait` implied by `-D warnings`
= help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
+ = note: `-D clippy::should-implement-trait` implied by `-D warnings`
error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
--> $DIR/method_list_1.rs:29:5
@@ -99,6 +99,16 @@ LL | | }
|
= help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
+error: method `default` can be confused for the standard trait method `std::default::Default::default`
+ --> $DIR/method_list_1.rs:65:5
+ |
+LL | / pub fn default() -> Self {
+LL | | unimplemented!()
+LL | | }
+ | |_____^
+ |
+ = help: consider implementing the trait `std::default::Default` or choosing a less ambiguous method name
+
error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
--> $DIR/method_list_1.rs:69:5
|
@@ -139,5 +149,5 @@ LL | | }
|
= help: consider implementing the trait `std::ops::Drop` or choosing a less ambiguous method name
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
diff --git a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
index b6fd43569..10bfea68f 100644
--- a/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
+++ b/src/tools/clippy/tests/ui/should_impl_trait/method_list_2.stderr
@@ -6,8 +6,8 @@ LL | | unimplemented!()
LL | | }
| |_____^
|
- = note: `-D clippy::should-implement-trait` implied by `-D warnings`
= help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
+ = note: `-D clippy::should-implement-trait` implied by `-D warnings`
error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
--> $DIR/method_list_2.rs:30:5
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
index 84ecf1ea5..c65df9ece 100644
--- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.rs
@@ -1,11 +1,8 @@
// FIXME: Ideally these suggestions would be fixed via rustfix. Blocked by rust-lang/rust#53934
// // run-rustfix
-
#![warn(clippy::significant_drop_in_scrutinee)]
-#![allow(clippy::single_match)]
-#![allow(clippy::match_single_binding)]
-#![allow(unused_assignments)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_assignments)]
+#![allow(clippy::match_single_binding, clippy::single_match, clippy::uninlined_format_args)]
use std::num::ParseIntError;
use std::ops::Deref;
diff --git a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
index 88ea6bce2..75063a8c9 100644
--- a/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
+++ b/src/tools/clippy/tests/ui/significant_drop_in_scrutinee.stderr
@@ -1,5 +1,5 @@
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:59:11
+ --> $DIR/significant_drop_in_scrutinee.rs:56:11
|
LL | match mutex.lock().unwrap().foo() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -10,8 +10,8 @@ LL | mutex.lock().unwrap().bar();
LL | };
| - temporary lives until here
|
- = note: `-D clippy::significant-drop-in-scrutinee` implied by `-D warnings`
= note: this might lead to deadlocks or other unexpected behavior
+ = note: `-D clippy::significant-drop-in-scrutinee` implied by `-D warnings`
help: try moving the temporary above the match
|
LL ~ let value = mutex.lock().unwrap().foo();
@@ -19,7 +19,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:145:11
+ --> $DIR/significant_drop_in_scrutinee.rs:142:11
|
LL | match s.lock_m().get_the_value() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:166:11
+ --> $DIR/significant_drop_in_scrutinee.rs:163:11
|
LL | match s.lock_m_m().get_the_value() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -57,7 +57,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:214:11
+ --> $DIR/significant_drop_in_scrutinee.rs:211:11
|
LL | match counter.temp_increment().len() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -73,7 +73,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:237:16
+ --> $DIR/significant_drop_in_scrutinee.rs:234:16
|
LL | match (mutex1.lock().unwrap().s.len(), true) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -92,7 +92,7 @@ LL ~ match (value, true) {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:246:22
+ --> $DIR/significant_drop_in_scrutinee.rs:243:22
|
LL | match (true, mutex1.lock().unwrap().s.len(), true) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -111,7 +111,7 @@ LL ~ match (true, value, true) {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:256:16
+ --> $DIR/significant_drop_in_scrutinee.rs:253:16
|
LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -132,7 +132,7 @@ LL ~ match (value, true, mutex2.lock().unwrap().s.len()) {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:256:54
+ --> $DIR/significant_drop_in_scrutinee.rs:253:54
|
LL | match (mutex1.lock().unwrap().s.len(), true, mutex2.lock().unwrap().s.len()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -153,7 +153,7 @@ LL ~ match (mutex1.lock().unwrap().s.len(), true, value) {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:267:15
+ --> $DIR/significant_drop_in_scrutinee.rs:264:15
|
LL | match mutex3.lock().unwrap().s.as_str() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -169,7 +169,7 @@ LL | };
= note: this might lead to deadlocks or other unexpected behavior
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:277:22
+ --> $DIR/significant_drop_in_scrutinee.rs:274:22
|
LL | match (true, mutex3.lock().unwrap().s.as_str()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -185,7 +185,7 @@ LL | };
= note: this might lead to deadlocks or other unexpected behavior
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:296:11
+ --> $DIR/significant_drop_in_scrutinee.rs:293:11
|
LL | match mutex.lock().unwrap().s.len() > 1 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -204,7 +204,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:303:11
+ --> $DIR/significant_drop_in_scrutinee.rs:300:11
|
LL | match 1 < mutex.lock().unwrap().s.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -223,7 +223,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:321:11
+ --> $DIR/significant_drop_in_scrutinee.rs:318:11
|
LL | match mutex1.lock().unwrap().s.len() < mutex2.lock().unwrap().s.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -244,7 +244,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:332:11
+ --> $DIR/significant_drop_in_scrutinee.rs:329:11
|
LL | match mutex1.lock().unwrap().s.len() >= mutex2.lock().unwrap().s.len() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -265,7 +265,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:367:11
+ --> $DIR/significant_drop_in_scrutinee.rs:364:11
|
LL | match get_mutex_guard().s.len() > 1 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -284,7 +284,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:384:11
+ --> $DIR/significant_drop_in_scrutinee.rs:381:11
|
LL | match match i {
| ___________^
@@ -316,7 +316,7 @@ LL ~ match value
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:410:11
+ --> $DIR/significant_drop_in_scrutinee.rs:407:11
|
LL | match if i > 1 {
| ___________^
@@ -349,7 +349,7 @@ LL ~ match value
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:464:11
+ --> $DIR/significant_drop_in_scrutinee.rs:461:11
|
LL | match s.lock().deref().deref() {
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -367,7 +367,7 @@ LL ~ match value {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:492:11
+ --> $DIR/significant_drop_in_scrutinee.rs:489:11
|
LL | match s.lock().deref().deref() {
| ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -380,7 +380,7 @@ LL | };
= note: this might lead to deadlocks or other unexpected behavior
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:511:11
+ --> $DIR/significant_drop_in_scrutinee.rs:508:11
|
LL | match mutex.lock().unwrap().i = i {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -399,7 +399,7 @@ LL ~ match () {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:517:11
+ --> $DIR/significant_drop_in_scrutinee.rs:514:11
|
LL | match i = mutex.lock().unwrap().i {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -418,7 +418,7 @@ LL ~ match () {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:523:11
+ --> $DIR/significant_drop_in_scrutinee.rs:520:11
|
LL | match mutex.lock().unwrap().i += 1 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -437,7 +437,7 @@ LL ~ match () {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:529:11
+ --> $DIR/significant_drop_in_scrutinee.rs:526:11
|
LL | match i += mutex.lock().unwrap().i {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -456,7 +456,7 @@ LL ~ match () {
|
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:592:11
+ --> $DIR/significant_drop_in_scrutinee.rs:589:11
|
LL | match rwlock.read().unwrap().to_number() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -467,7 +467,7 @@ LL | };
= note: this might lead to deadlocks or other unexpected behavior
error: temporary with significant `Drop` in `for` loop condition will live until the end of the `for` expression
- --> $DIR/significant_drop_in_scrutinee.rs:602:14
+ --> $DIR/significant_drop_in_scrutinee.rs:599:14
|
LL | for s in rwlock.read().unwrap().iter() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -478,7 +478,7 @@ LL | }
= note: this might lead to deadlocks or other unexpected behavior
error: temporary with significant `Drop` in `match` scrutinee will live until the end of the `match` expression
- --> $DIR/significant_drop_in_scrutinee.rs:617:11
+ --> $DIR/significant_drop_in_scrutinee.rs:614:11
|
LL | match mutex.lock().unwrap().foo() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/similar_names.stderr b/src/tools/clippy/tests/ui/similar_names.stderr
index 6e7726938..43c5cee4b 100644
--- a/src/tools/clippy/tests/ui/similar_names.stderr
+++ b/src/tools/clippy/tests/ui/similar_names.stderr
@@ -4,12 +4,12 @@ error: binding's name is too similar to existing binding
LL | let bpple: i32;
| ^^^^^
|
- = note: `-D clippy::similar-names` implied by `-D warnings`
note: existing binding defined here
--> $DIR/similar_names.rs:19:9
|
LL | let apple: i32;
| ^^^^^
+ = note: `-D clippy::similar-names` implied by `-D warnings`
error: binding's name is too similar to existing binding
--> $DIR/similar_names.rs:23:9
diff --git a/src/tools/clippy/tests/ui/single_char_lifetime_names.stderr b/src/tools/clippy/tests/ui/single_char_lifetime_names.stderr
index 1438b3999..bfe6d44b5 100644
--- a/src/tools/clippy/tests/ui/single_char_lifetime_names.stderr
+++ b/src/tools/clippy/tests/ui/single_char_lifetime_names.stderr
@@ -4,8 +4,8 @@ error: single-character lifetime names are likely uninformative
LL | struct DiagnosticCtx<'a, 'b>
| ^^
|
- = note: `-D clippy::single-char-lifetime-names` implied by `-D warnings`
= help: use a more informative name
+ = note: `-D clippy::single-char-lifetime-names` implied by `-D warnings`
error: single-character lifetime names are likely uninformative
--> $DIR/single_char_lifetime_names.rs:5:26
diff --git a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
index cf990be1b..633546f64 100644
--- a/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
+++ b/src/tools/clippy/tests/ui/single_component_path_imports_nested_first.stderr
@@ -4,8 +4,8 @@ error: this import is redundant
LL | use {regex, serde};
| ^^^^^
|
- = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
= help: remove this import
+ = note: `-D clippy::single-component-path-imports` implied by `-D warnings`
error: this import is redundant
--> $DIR/single_component_path_imports_nested_first.rs:13:17
diff --git a/src/tools/clippy/tests/ui/single_match.rs b/src/tools/clippy/tests/ui/single_match.rs
index dd148edf5..d0c9b7b56 100644
--- a/src/tools/clippy/tests/ui/single_match.rs
+++ b/src/tools/clippy/tests/ui/single_match.rs
@@ -1,4 +1,5 @@
#![warn(clippy::single_match)]
+#![allow(clippy::uninlined_format_args)]
fn dummy() {}
diff --git a/src/tools/clippy/tests/ui/single_match.stderr b/src/tools/clippy/tests/ui/single_match.stderr
index 4d2b9ec5f..7cecc1b73 100644
--- a/src/tools/clippy/tests/ui/single_match.stderr
+++ b/src/tools/clippy/tests/ui/single_match.stderr
@@ -1,5 +1,5 @@
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:8:5
+ --> $DIR/single_match.rs:9:5
|
LL | / match x {
LL | | Some(y) => {
@@ -18,7 +18,7 @@ LL ~ };
|
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:16:5
+ --> $DIR/single_match.rs:17:5
|
LL | / match x {
LL | | // Note the missing block braces.
@@ -30,7 +30,7 @@ LL | | }
| |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:25:5
+ --> $DIR/single_match.rs:26:5
|
LL | / match z {
LL | | (2..=3, 7..=9) => dummy(),
@@ -39,7 +39,7 @@ LL | | };
| |_____^ help: try this: `if let (2..=3, 7..=9) = z { dummy() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:54:5
+ --> $DIR/single_match.rs:55:5
|
LL | / match x {
LL | | Some(y) => dummy(),
@@ -48,7 +48,7 @@ LL | | };
| |_____^ help: try this: `if let Some(y) = x { dummy() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:59:5
+ --> $DIR/single_match.rs:60:5
|
LL | / match y {
LL | | Ok(y) => dummy(),
@@ -57,7 +57,7 @@ LL | | };
| |_____^ help: try this: `if let Ok(y) = y { dummy() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:66:5
+ --> $DIR/single_match.rs:67:5
|
LL | / match c {
LL | | Cow::Borrowed(..) => dummy(),
@@ -66,7 +66,7 @@ LL | | };
| |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }`
error: you seem to be trying to use `match` for an equality check. Consider using `if`
- --> $DIR/single_match.rs:87:5
+ --> $DIR/single_match.rs:88:5
|
LL | / match x {
LL | | "test" => println!(),
@@ -75,7 +75,7 @@ LL | | }
| |_____^ help: try this: `if x == "test" { println!() }`
error: you seem to be trying to use `match` for an equality check. Consider using `if`
- --> $DIR/single_match.rs:100:5
+ --> $DIR/single_match.rs:101:5
|
LL | / match x {
LL | | Foo::A => println!(),
@@ -84,7 +84,7 @@ LL | | }
| |_____^ help: try this: `if x == Foo::A { println!() }`
error: you seem to be trying to use `match` for an equality check. Consider using `if`
- --> $DIR/single_match.rs:106:5
+ --> $DIR/single_match.rs:107:5
|
LL | / match x {
LL | | FOO_C => println!(),
@@ -93,7 +93,7 @@ LL | | }
| |_____^ help: try this: `if x == FOO_C { println!() }`
error: you seem to be trying to use `match` for an equality check. Consider using `if`
- --> $DIR/single_match.rs:111:5
+ --> $DIR/single_match.rs:112:5
|
LL | / match &&x {
LL | | Foo::A => println!(),
@@ -102,7 +102,7 @@ LL | | }
| |_____^ help: try this: `if x == Foo::A { println!() }`
error: you seem to be trying to use `match` for an equality check. Consider using `if`
- --> $DIR/single_match.rs:117:5
+ --> $DIR/single_match.rs:118:5
|
LL | / match &x {
LL | | Foo::A => println!(),
@@ -111,7 +111,7 @@ LL | | }
| |_____^ help: try this: `if x == &Foo::A { println!() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:134:5
+ --> $DIR/single_match.rs:135:5
|
LL | / match x {
LL | | Bar::A => println!(),
@@ -120,7 +120,7 @@ LL | | }
| |_____^ help: try this: `if let Bar::A = x { println!() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:142:5
+ --> $DIR/single_match.rs:143:5
|
LL | / match x {
LL | | None => println!(),
@@ -129,7 +129,7 @@ LL | | };
| |_____^ help: try this: `if let None = x { println!() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:164:5
+ --> $DIR/single_match.rs:165:5
|
LL | / match x {
LL | | (Some(_), _) => {},
@@ -138,7 +138,7 @@ LL | | }
| |_____^ help: try this: `if let (Some(_), _) = x {}`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:170:5
+ --> $DIR/single_match.rs:171:5
|
LL | / match x {
LL | | (Some(E::V), _) => todo!(),
@@ -147,7 +147,7 @@ LL | | }
| |_____^ help: try this: `if let (Some(E::V), _) = x { todo!() }`
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match.rs:176:5
+ --> $DIR/single_match.rs:177:5
|
LL | / match (Some(42), Some(E::V), Some(42)) {
LL | | (.., Some(E::V), _) => {},
diff --git a/src/tools/clippy/tests/ui/single_match_else.rs b/src/tools/clippy/tests/ui/single_match_else.rs
index 70d6febb7..5d03f77e9 100644
--- a/src/tools/clippy/tests/ui/single_match_else.rs
+++ b/src/tools/clippy/tests/ui/single_match_else.rs
@@ -1,8 +1,6 @@
// aux-build: proc_macro_with_span.rs
-
#![warn(clippy::single_match_else)]
-#![allow(clippy::needless_return)]
-#![allow(clippy::no_effect)]
+#![allow(clippy::needless_return, clippy::no_effect, clippy::uninlined_format_args)]
extern crate proc_macro_with_span;
use proc_macro_with_span::with_span;
diff --git a/src/tools/clippy/tests/ui/single_match_else.stderr b/src/tools/clippy/tests/ui/single_match_else.stderr
index 38fd9c6a6..62876a55d 100644
--- a/src/tools/clippy/tests/ui/single_match_else.stderr
+++ b/src/tools/clippy/tests/ui/single_match_else.stderr
@@ -1,5 +1,5 @@
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match_else.rs:19:13
+ --> $DIR/single_match_else.rs:17:13
|
LL | let _ = match ExprNode::Butterflies {
| _____________^
@@ -21,7 +21,7 @@ LL ~ };
|
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match_else.rs:84:5
+ --> $DIR/single_match_else.rs:82:5
|
LL | / match Some(1) {
LL | | Some(a) => println!("${:?}", a),
@@ -41,7 +41,7 @@ LL + }
|
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match_else.rs:93:5
+ --> $DIR/single_match_else.rs:91:5
|
LL | / match Some(1) {
LL | | Some(a) => println!("${:?}", a),
@@ -61,7 +61,7 @@ LL + }
|
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match_else.rs:103:5
+ --> $DIR/single_match_else.rs:101:5
|
LL | / match Result::<i32, Infallible>::Ok(1) {
LL | | Ok(a) => println!("${:?}", a),
@@ -81,7 +81,7 @@ LL + }
|
error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
- --> $DIR/single_match_else.rs:112:5
+ --> $DIR/single_match_else.rs:110:5
|
LL | / match Cow::from("moo") {
LL | | Cow::Owned(a) => println!("${:?}", a),
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
index 0f0dff57f..037f695f3 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/expressions.stderr
@@ -4,8 +4,8 @@ error: found a count of bytes instead of a count of elements of `T`
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+ = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
error: found a count of bytes instead of a count of elements of `T`
--> $DIR/expressions.rs:18:62
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
index c1e824167..4351e6a14 100644
--- a/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
+++ b/src/tools/clippy/tests/ui/size_of_in_element_count/functions.stderr
@@ -4,8 +4,8 @@ error: found a count of bytes instead of a count of elements of `T`
LL | unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
|
- = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+ = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
error: found a count of bytes instead of a count of elements of `T`
--> $DIR/functions.rs:19:62
diff --git a/src/tools/clippy/tests/ui/skip_while_next.stderr b/src/tools/clippy/tests/ui/skip_while_next.stderr
index 269cc1346..7308ab4e5 100644
--- a/src/tools/clippy/tests/ui/skip_while_next.stderr
+++ b/src/tools/clippy/tests/ui/skip_while_next.stderr
@@ -4,8 +4,8 @@ error: called `skip_while(<p>).next()` on an `Iterator`
LL | let _ = v.iter().skip_while(|&x| *x < 0).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::skip-while-next` implied by `-D warnings`
= help: this is more succinctly expressed by calling `.find(!<p>)` instead
+ = note: `-D clippy::skip-while-next` implied by `-D warnings`
error: called `skip_while(<p>).next()` on an `Iterator`
--> $DIR/skip_while_next.rs:17:13
diff --git a/src/tools/clippy/tests/ui/stable_sort_primitive.stderr b/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
index c35e0c22a..1432fdcff 100644
--- a/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
+++ b/src/tools/clippy/tests/ui/stable_sort_primitive.stderr
@@ -4,8 +4,8 @@ error: used `sort` on primitive type `i32`
LL | vec.sort();
| ^^^^^^^^^^ help: try: `vec.sort_unstable()`
|
- = note: `-D clippy::stable-sort-primitive` implied by `-D warnings`
= note: an unstable sort typically performs faster without any observable difference for this data type
+ = note: `-D clippy::stable-sort-primitive` implied by `-D warnings`
error: used `sort` on primitive type `bool`
--> $DIR/stable_sort_primitive.rs:9:5
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs
index 6b27475de..75b114ba0 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.rs
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs
@@ -24,6 +24,12 @@ fn std_instead_of_core() {
let cell_absolute = ::std::cell::Cell::new(8u32);
let _ = std::env!("PATH");
+
+ // do not lint until `error_in_core` is stable
+ use std::error::Error;
+
+ // lint items re-exported from private modules, `core::iter::traits::iterator::Iterator`
+ use std::iter::Iterator;
}
#[warn(clippy::std_instead_of_alloc)]
diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
index bc49dabf5..d21024973 100644
--- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr
+++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr
@@ -4,8 +4,8 @@ error: used import from `std` instead of `core`
LL | use std::hash::Hasher;
| ^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::std-instead-of-core` implied by `-D warnings`
= help: consider importing the item from `core`
+ = note: `-D clippy::std-instead-of-core` implied by `-D warnings`
error: used import from `std` instead of `core`
--> $DIR/std_instead_of_core.rs:11:9
@@ -63,17 +63,25 @@ LL | let cell_absolute = ::std::cell::Cell::new(8u32);
|
= help: consider importing the item from `core`
-error: used import from `std` instead of `alloc`
+error: used import from `std` instead of `core`
--> $DIR/std_instead_of_core.rs:32:9
|
+LL | use std::iter::Iterator;
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+ = help: consider importing the item from `core`
+
+error: used import from `std` instead of `alloc`
+ --> $DIR/std_instead_of_core.rs:38:9
+ |
LL | use std::vec;
| ^^^^^^^^
|
- = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
= help: consider importing the item from `alloc`
+ = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings`
error: used import from `std` instead of `alloc`
- --> $DIR/std_instead_of_core.rs:33:9
+ --> $DIR/std_instead_of_core.rs:39:9
|
LL | use std::vec::Vec;
| ^^^^^^^^^^^^^
@@ -81,13 +89,13 @@ LL | use std::vec::Vec;
= help: consider importing the item from `alloc`
error: used import from `alloc` instead of `core`
- --> $DIR/std_instead_of_core.rs:38:9
+ --> $DIR/std_instead_of_core.rs:44:9
|
LL | use alloc::slice::from_ref;
| ^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
= help: consider importing the item from `core`
+ = note: `-D clippy::alloc-instead-of-core` implied by `-D warnings`
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/str_to_string.stderr b/src/tools/clippy/tests/ui/str_to_string.stderr
index b1f73eda5..1d47da571 100644
--- a/src/tools/clippy/tests/ui/str_to_string.stderr
+++ b/src/tools/clippy/tests/ui/str_to_string.stderr
@@ -4,8 +4,8 @@ error: `to_string()` called on a `&str`
LL | let hello = "hello world".to_string();
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::str-to-string` implied by `-D warnings`
= help: consider using `.to_owned()`
+ = note: `-D clippy::str-to-string` implied by `-D warnings`
error: `to_string()` called on a `&str`
--> $DIR/str_to_string.rs:6:5
diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr
index 1ebd17999..e304c3e34 100644
--- a/src/tools/clippy/tests/ui/string_to_string.stderr
+++ b/src/tools/clippy/tests/ui/string_to_string.stderr
@@ -4,8 +4,8 @@ error: `to_string()` called on a `String`
LL | let mut v = message.to_string();
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::string-to-string` implied by `-D warnings`
= help: consider using `.clone()`
+ = note: `-D clippy::string-to-string` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/struct_excessive_bools.stderr b/src/tools/clippy/tests/ui/struct_excessive_bools.stderr
index 2941bf298..e4d50043a 100644
--- a/src/tools/clippy/tests/ui/struct_excessive_bools.stderr
+++ b/src/tools/clippy/tests/ui/struct_excessive_bools.stderr
@@ -9,8 +9,8 @@ LL | | d: bool,
LL | | }
| |_^
|
- = note: `-D clippy::struct-excessive-bools` implied by `-D warnings`
= help: consider using a state machine or refactoring bools into two-variant enums
+ = note: `-D clippy::struct-excessive-bools` implied by `-D warnings`
error: more than 3 bools in a struct
--> $DIR/struct_excessive_bools.rs:38:5
diff --git a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
index ee68eb5a7..2e512b47f 100644
--- a/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_else_formatting.stderr
@@ -4,8 +4,8 @@ error: this looks like an `else {..}` but the `else` is missing
LL | } {
| ^
|
- = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings`
= note: to remove this lint, add the missing `else` or add a new line before the next block
+ = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings`
error: this looks like an `else if` but the `else` is missing
--> $DIR/suspicious_else_formatting.rs:21:6
diff --git a/src/tools/clippy/tests/ui/suspicious_map.stderr b/src/tools/clippy/tests/ui/suspicious_map.stderr
index 3ffcd1a90..e25167481 100644
--- a/src/tools/clippy/tests/ui/suspicious_map.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_map.stderr
@@ -4,8 +4,8 @@ error: this call to `map()` won't have an effect on the call to `count()`
LL | let _ = (0..3).map(|x| x + 2).count();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::suspicious-map` implied by `-D warnings`
= help: make sure you did not confuse `map` with `filter`, `for_each` or `inspect`
+ = note: `-D clippy::suspicious-map` implied by `-D warnings`
error: this call to `map()` won't have an effect on the call to `count()`
--> $DIR/suspicious_map.rs:7:13
diff --git a/src/tools/clippy/tests/ui/suspicious_splitn.stderr b/src/tools/clippy/tests/ui/suspicious_splitn.stderr
index 3bcd681fa..55ce63d4f 100644
--- a/src/tools/clippy/tests/ui/suspicious_splitn.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_splitn.stderr
@@ -4,8 +4,8 @@ error: `splitn` called with `0` splits
LL | let _ = "a,b".splitn(0, ',');
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::suspicious-splitn` implied by `-D warnings`
= note: the resulting iterator will always return `None`
+ = note: `-D clippy::suspicious-splitn` implied by `-D warnings`
error: `rsplitn` called with `0` splits
--> $DIR/suspicious_splitn.rs:11:13
diff --git a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
index 92e1024bf..ae1aec34d 100644
--- a/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_to_owned.stderr
@@ -1,4 +1,4 @@
-error: this `to_owned` call clones the std::borrow::Cow<str> itself and does not cause the std::borrow::Cow<str> contents to become owned
+error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
--> $DIR/suspicious_to_owned.rs:16:13
|
LL | let _ = cow.to_owned();
@@ -6,19 +6,19 @@ LL | let _ = cow.to_owned();
|
= note: `-D clippy::suspicious-to-owned` implied by `-D warnings`
-error: this `to_owned` call clones the std::borrow::Cow<[char; 3]> itself and does not cause the std::borrow::Cow<[char; 3]> contents to become owned
+error: this `to_owned` call clones the std::borrow::Cow<'_, [char; 3]> itself and does not cause the std::borrow::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()`
-error: this `to_owned` call clones the std::borrow::Cow<std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<std::vec::Vec<char>> contents to become owned
+error: this `to_owned` call clones the std::borrow::Cow<'_, std::vec::Vec<char>> itself and does not cause the std::borrow::Cow<'_, std::vec::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()`
-error: this `to_owned` call clones the std::borrow::Cow<str> itself and does not cause the std::borrow::Cow<str> contents to become owned
+error: this `to_owned` call clones the std::borrow::Cow<'_, str> itself and does not cause the std::borrow::Cow<'_, str> contents to become owned
--> $DIR/suspicious_to_owned.rs:46:13
|
LL | let _ = cow.to_owned();
diff --git a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
index 581527dcf..9f1289ccb 100644
--- a/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
+++ b/src/tools/clippy/tests/ui/suspicious_unary_op_formatting.stderr
@@ -4,8 +4,8 @@ error: by not having a space between `>` and `-` it looks like `>-` is a single
LL | if a >- 30 {}
| ^^^^
|
- = note: `-D clippy::suspicious-unary-op-formatting` implied by `-D warnings`
= help: put a space between `>` and `-` and remove the space after `-`
+ = note: `-D clippy::suspicious-unary-op-formatting` implied by `-D warnings`
error: by not having a space between `>=` and `-` it looks like `>=-` is a single operator
--> $DIR/suspicious_unary_op_formatting.rs:9:9
diff --git a/src/tools/clippy/tests/ui/swap.stderr b/src/tools/clippy/tests/ui/swap.stderr
index 2b556b475..ee4b7a508 100644
--- a/src/tools/clippy/tests/ui/swap.stderr
+++ b/src/tools/clippy/tests/ui/swap.stderr
@@ -6,8 +6,8 @@ LL | | bar.a = bar.b;
LL | | bar.b = temp;
| |________________^ help: try: `std::mem::swap(&mut bar.a, &mut bar.b)`
|
- = note: `-D clippy::manual-swap` implied by `-D warnings`
= note: or maybe you should use `std::mem::replace`?
+ = 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
@@ -96,8 +96,8 @@ LL | / a = b;
LL | | b = a;
| |_________^ help: try: `std::mem::swap(&mut a, &mut b)`
|
- = note: `-D clippy::almost-swapped` implied by `-D warnings`
= note: or maybe you should use `std::mem::replace`?
+ = 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
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
index b129d95c5..09fb66ca3 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.fixed
@@ -1,7 +1,7 @@
// run-rustfix
// aux-build:macro_rules.rs
-
#![warn(clippy::toplevel_ref_arg)]
+#![allow(clippy::uninlined_format_args)]
#[macro_use]
extern crate macro_rules;
diff --git a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
index 73eb4ff73..9d1f2f810 100644
--- a/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
+++ b/src/tools/clippy/tests/ui/toplevel_ref_arg.rs
@@ -1,7 +1,7 @@
// run-rustfix
// aux-build:macro_rules.rs
-
#![warn(clippy::toplevel_ref_arg)]
+#![allow(clippy::uninlined_format_args)]
#[macro_use]
extern crate macro_rules;
diff --git a/src/tools/clippy/tests/ui/trailing_empty_array.stderr b/src/tools/clippy/tests/ui/trailing_empty_array.stderr
index 9e2bd31d9..2e1484400 100644
--- a/src/tools/clippy/tests/ui/trailing_empty_array.stderr
+++ b/src/tools/clippy/tests/ui/trailing_empty_array.stderr
@@ -7,8 +7,8 @@ LL | | last: [usize; 0],
LL | | }
| |_^
|
- = note: `-D clippy::trailing-empty-array` implied by `-D warnings`
= help: consider annotating `RarelyUseful` with `#[repr(C)]` or another `repr` attribute
+ = note: `-D clippy::trailing-empty-array` implied by `-D warnings`
error: trailing zero-sized array in a struct which is not marked with a `repr` attribute
--> $DIR/trailing_empty_array.rs:10:1
diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_unfixable.stderr b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_unfixable.stderr
index fbd9abb00..4d56a9464 100644
--- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_unfixable.stderr
+++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_unfixable.stderr
@@ -4,12 +4,12 @@ error: this trait bound is already specified in the where clause
LL | fn bad_foo<T: Clone + Default, Z: Copy>(arg0: T, arg1: Z)
| ^^^^^
|
+ = help: consider removing this trait bound
note: the lint level is defined here
--> $DIR/trait_duplication_in_bounds_unfixable.rs:1:9
|
LL | #![deny(clippy::trait_duplication_in_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: consider removing this trait bound
error: this trait bound is already specified in the where clause
--> $DIR/trait_duplication_in_bounds_unfixable.rs:6:23
diff --git a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
index 2993e5e7b..10117ee91 100644
--- a/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
+++ b/src/tools/clippy/tests/ui/transmute_ptr_to_ref.stderr
@@ -42,13 +42,13 @@ error: transmute from a pointer type (`*mut U`) to a reference type (`&T`)
LL | let _: &T = std::mem::transmute(om);
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(om as *const T)`
-error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<u8>`)
+error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, u8>`)
--> $DIR/transmute_ptr_to_ref.rs:36:32
|
LL | let _: &Foo<u8> = unsafe { std::mem::transmute::<_, &Foo<_>>(raw) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*raw.cast::<Foo<_>>()`
-error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<&u8>`)
+error: transmute from a pointer type (`*const i32`) to a reference type (`&_issue1231::Foo<'_, &u8>`)
--> $DIR/transmute_ptr_to_ref.rs:38:33
|
LL | let _: &Foo<&u8> = unsafe { std::mem::transmute::<_, &Foo<&_>>(raw) };
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 539239fc1..7263abac1 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
@@ -8,7 +8,7 @@
use std::mem::{size_of, transmute};
-// rustc_typeck::check::cast contains documentation about when a cast `e as U` is
+// rustc_hir_analysis::check::cast contains documentation about when a cast `e as U` is
// valid, which we quote from below.
fn main() {
// We should see an error message for each transmute, and no error messages for
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 b9e446dc8..d8e4421d4 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
@@ -8,7 +8,7 @@
use std::mem::{size_of, transmute};
-// rustc_typeck::check::cast contains documentation about when a cast `e as U` is
+// rustc_hir_analysis::check::cast contains documentation about when a cast `e as U` is
// valid, which we quote from below.
fn main() {
// We should see an error message for each transmute, and no error messages for
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
index c0c64ebca..af4f3b184 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.rs
@@ -1,8 +1,11 @@
// normalize-stderr-test "\(\d+ byte\)" -> "(N byte)"
// normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)"
-
#![deny(clippy::trivially_copy_pass_by_ref)]
-#![allow(clippy::disallowed_names, clippy::redundant_field_names)]
+#![allow(
+ clippy::disallowed_names,
+ clippy::redundant_field_names,
+ clippy::uninlined_format_args
+)]
#[derive(Copy, Clone)]
struct Foo(u32);
diff --git a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
index 66ecb3d8e..6a8eca965 100644
--- a/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
+++ b/src/tools/clippy/tests/ui/trivially_copy_pass_by_ref.stderr
@@ -1,113 +1,113 @@
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:47:11
+ --> $DIR/trivially_copy_pass_by_ref.rs:50:11
|
LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `u32`
|
note: the lint level is defined here
- --> $DIR/trivially_copy_pass_by_ref.rs:4:9
+ --> $DIR/trivially_copy_pass_by_ref.rs:3:9
|
LL | #![deny(clippy::trivially_copy_pass_by_ref)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:47:20
+ --> $DIR/trivially_copy_pass_by_ref.rs:50:20
|
LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:47:29
+ --> $DIR/trivially_copy_pass_by_ref.rs:50:29
|
LL | fn bad(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:54:12
+ --> $DIR/trivially_copy_pass_by_ref.rs:57:12
|
LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
| ^^^^^ help: consider passing by value instead: `self`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:54:22
+ --> $DIR/trivially_copy_pass_by_ref.rs:57:22
|
LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `u32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:54:31
+ --> $DIR/trivially_copy_pass_by_ref.rs:57:31
|
LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:54:40
+ --> $DIR/trivially_copy_pass_by_ref.rs:57:40
|
LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:56:16
+ --> $DIR/trivially_copy_pass_by_ref.rs:59:16
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `u32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:56:25
+ --> $DIR/trivially_copy_pass_by_ref.rs:59:25
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:56:34
+ --> $DIR/trivially_copy_pass_by_ref.rs:59:34
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:58:35
+ --> $DIR/trivially_copy_pass_by_ref.rs:61:35
|
LL | fn bad_issue7518(self, other: &Self) {}
| ^^^^^ help: consider passing by value instead: `Self`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:70:16
+ --> $DIR/trivially_copy_pass_by_ref.rs:73:16
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `u32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:70:25
+ --> $DIR/trivially_copy_pass_by_ref.rs:73:25
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:70:34
+ --> $DIR/trivially_copy_pass_by_ref.rs:73:34
|
LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {}
| ^^^^ help: consider passing by value instead: `Baz`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:74:34
+ --> $DIR/trivially_copy_pass_by_ref.rs:77:34
|
LL | fn trait_method(&self, _foo: &Foo);
| ^^^^ help: consider passing by value instead: `Foo`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:106:21
+ --> $DIR/trivially_copy_pass_by_ref.rs:109:21
|
LL | fn foo_never(x: &i32) {
| ^^^^ help: consider passing by value instead: `i32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:111:15
+ --> $DIR/trivially_copy_pass_by_ref.rs:114:15
|
LL | fn foo(x: &i32) {
| ^^^^ help: consider passing by value instead: `i32`
error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte)
- --> $DIR/trivially_copy_pass_by_ref.rs:138:37
+ --> $DIR/trivially_copy_pass_by_ref.rs:141:37
|
LL | fn _unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 {
| ^^^^^^^ help: consider passing by value instead: `u32`
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 1d8871481..70d700c1c 100644
--- a/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
+++ b/src/tools/clippy/tests/ui/type_repetition_in_bounds.stderr
@@ -4,12 +4,12 @@ error: this type has already been used as a bound predicate
LL | T: Clone,
| ^^^^^^^^
|
+ = help: consider combining the bounds: `T: Copy + Clone`
note: the lint level is defined here
--> $DIR/type_repetition_in_bounds.rs:1:9
|
LL | #![deny(clippy::type_repetition_in_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: consider combining the bounds: `T: Copy + Clone`
error: this type has already been used as a bound predicate
--> $DIR/type_repetition_in_bounds.rs:25:5
diff --git a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
index c6a212744..2c466ff5c 100644
--- a/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
+++ b/src/tools/clippy/tests/ui/undocumented_unsafe_blocks.stderr
@@ -4,8 +4,8 @@ error: unsafe block missing a safety comment
LL | /* Safety: */ unsafe {}
| ^^^^^^^^^
|
- = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
= help: consider adding a safety comment on the preceding line
+ = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings`
error: unsafe block missing a safety comment
--> $DIR/undocumented_unsafe_blocks.rs:266:5
diff --git a/src/tools/clippy/tests/ui/undropped_manually_drops.stderr b/src/tools/clippy/tests/ui/undropped_manually_drops.stderr
index 2ac0fe986..92611a9b7 100644
--- a/src/tools/clippy/tests/ui/undropped_manually_drops.stderr
+++ b/src/tools/clippy/tests/ui/undropped_manually_drops.stderr
@@ -4,8 +4,8 @@ error: the inner value of this ManuallyDrop will not be dropped
LL | drop(std::mem::ManuallyDrop::new(S));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::undropped-manually-drops` implied by `-D warnings`
= help: to drop a `ManuallyDrop<T>`, use std::mem::ManuallyDrop::drop
+ = note: `-D clippy::undropped-manually-drops` implied by `-D warnings`
error: the inner value of this ManuallyDrop will not be dropped
--> $DIR/undropped_manually_drops.rs:15:5
diff --git a/src/tools/clippy/tests/ui/uninit_vec.rs b/src/tools/clippy/tests/ui/uninit_vec.rs
index dc150cf28..194e4fc15 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.rs
+++ b/src/tools/clippy/tests/ui/uninit_vec.rs
@@ -91,4 +91,10 @@ fn main() {
vec1.set_len(200);
vec2.set_len(200);
}
+
+ // set_len(0) should not be detected
+ let mut vec: Vec<u8> = Vec::with_capacity(1000);
+ unsafe {
+ vec.set_len(0);
+ }
}
diff --git a/src/tools/clippy/tests/ui/uninit_vec.stderr b/src/tools/clippy/tests/ui/uninit_vec.stderr
index 520bfb26b..77fc689f0 100644
--- a/src/tools/clippy/tests/ui/uninit_vec.stderr
+++ b/src/tools/clippy/tests/ui/uninit_vec.stderr
@@ -7,8 +7,8 @@ LL | unsafe {
LL | vec.set_len(200);
| ^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::uninit-vec` implied by `-D warnings`
= help: initialize the buffer or wrap the content in `MaybeUninit`
+ = note: `-D clippy::uninit-vec` implied by `-D warnings`
error: calling `set_len()` immediately after reserving a buffer creates uninitialized values
--> $DIR/uninit_vec.rs:18:5
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.fixed b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
new file mode 100644
index 000000000..106274479
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.fixed
@@ -0,0 +1,182 @@
+// aux-build:proc_macro_with_span.rs
+// run-rustfix
+#![feature(custom_inner_attributes)]
+#![warn(clippy::uninlined_format_args)]
+#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
+#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
+
+extern crate proc_macro_with_span;
+use proc_macro_with_span::with_span;
+
+macro_rules! no_param_str {
+ () => {
+ "{}"
+ };
+}
+
+macro_rules! my_println {
+ ($($args:tt),*) => {{
+ println!($($args),*)
+ }};
+}
+
+macro_rules! my_println_args {
+ ($($args:tt),*) => {{
+ println!("foo: {}", format_args!($($args),*))
+ }};
+}
+
+fn tester(fn_arg: i32) {
+ let local_i32 = 1;
+ let local_f64 = 2.0;
+ let local_opt: Option<i32> = Some(3);
+ let width = 4;
+ let prec = 5;
+ let val = 6;
+
+ // make sure this file hasn't been corrupted with tabs converted to spaces
+ // let _ = ' '; // <- this is a single tab character
+ let _: &[u8; 3] = b" "; // <- <tab><space><tab>
+
+ println!("val='{local_i32}'");
+ println!("val='{local_i32}'"); // 3 spaces
+ println!("val='{local_i32}'"); // tab
+ println!("val='{local_i32}'"); // space+tab
+ println!("val='{local_i32}'"); // tab+space
+ println!(
+ "val='{
+ }'",
+ local_i32
+ );
+ println!("{local_i32}");
+ println!("{fn_arg}");
+ println!("{local_i32:?}");
+ println!("{local_i32:#?}");
+ println!("{local_i32:4}");
+ println!("{local_i32:04}");
+ println!("{local_i32:<3}");
+ println!("{local_i32:#010x}");
+ println!("{local_f64:.1}");
+ println!("Hello {} is {local_f64:.local_i32$}", "x");
+ println!("Hello {local_i32} is {local_f64:.*}", 5);
+ println!("Hello {local_i32} is {local_f64:.*}", 5);
+ println!("{local_i32} {local_f64}");
+ println!("{local_i32}, {}", local_opt.unwrap());
+ println!("{val}");
+ println!("{val}");
+ println!("{} {1}", local_i32, 42);
+ println!("val='{local_i32}'");
+ println!("val='{local_i32}'");
+ println!("val='{local_i32}'");
+ println!("val='{fn_arg}'");
+ println!("{local_i32}");
+ println!("{local_i32:?}");
+ println!("{local_i32:#?}");
+ println!("{local_i32:04}");
+ println!("{local_i32:<3}");
+ println!("{local_i32:#010x}");
+ println!("{local_f64:.1}");
+ println!("{local_i32} {local_i32}");
+ println!("{local_f64} {local_i32} {local_i32} {local_f64}");
+ println!("{local_i32} {local_f64}");
+ println!("{local_f64} {local_i32}");
+ println!("{local_f64} {local_i32} {local_f64} {local_i32}");
+ println!("{1} {0}", "str", local_i32);
+ println!("{local_i32}");
+ println!("{local_i32:width$}");
+ println!("{local_i32:width$}");
+ println!("{local_i32:.prec$}");
+ println!("{local_i32:.prec$}");
+ println!("{val:val$}");
+ println!("{val:val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{val:val$.val$}");
+ println!("{width:width$}");
+ println!("{local_i32:width$}");
+ println!("{width:width$}");
+ println!("{local_i32:width$}");
+ println!("{prec:.prec$}");
+ println!("{local_i32:.prec$}");
+ println!("{prec:.prec$}");
+ println!("{local_i32:.prec$}");
+ println!("{width:width$.prec$}");
+ println!("{width:width$.prec$}");
+ println!("{local_f64:width$.prec$}");
+ println!("{local_f64:width$.prec$} {local_f64} {width} {prec}");
+ println!(
+ "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}",
+ local_i32, width, prec,
+ );
+ println!(
+ "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$} {3}",
+ local_i32,
+ width,
+ prec,
+ 1 + 2
+ );
+ println!("Width = {local_i32}, value with width = {local_f64:local_i32$}");
+ println!("{local_i32:width$.prec$}");
+ println!("{width:width$.prec$}");
+ println!("{}", format!("{local_i32}"));
+ my_println!("{}", local_i32);
+ my_println_args!("{}", local_i32);
+
+ // these should NOT be modified by the lint
+ println!(concat!("nope ", "{}"), local_i32);
+ println!("val='{local_i32}'");
+ println!("val='{local_i32 }'");
+ println!("val='{local_i32 }'"); // with tab
+ println!("val='{local_i32\n}'");
+ println!("{}", usize::MAX);
+ println!("{}", local_opt.unwrap());
+ println!(
+ "val='{local_i32
+ }'"
+ );
+ println!(no_param_str!(), local_i32);
+
+ println!(
+ "{}",
+ // comment with a comma , in it
+ val,
+ );
+ println!("{val}");
+
+ println!(with_span!("{0} {1}" "{1} {0}"), local_i32, local_f64);
+ println!("{}", with_span!(span val));
+
+ if local_i32 > 0 {
+ panic!("p1 {local_i32}");
+ }
+ if local_i32 > 0 {
+ panic!("p2 {local_i32}");
+ }
+ if local_i32 > 0 {
+ panic!("p3 {local_i32}");
+ }
+ if local_i32 > 0 {
+ panic!("p4 {local_i32}");
+ }
+}
+
+fn main() {
+ tester(42);
+}
+
+fn _under_msrv() {
+ #![clippy::msrv = "1.57"]
+ let local_i32 = 1;
+ println!("don't expand='{}'", local_i32);
+}
+
+fn _meets_msrv() {
+ #![clippy::msrv = "1.58"]
+ let local_i32 = 1;
+ println!("expand='{local_i32}'");
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.rs b/src/tools/clippy/tests/ui/uninlined_format_args.rs
new file mode 100644
index 000000000..8e495ebd0
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.rs
@@ -0,0 +1,182 @@
+// aux-build:proc_macro_with_span.rs
+// run-rustfix
+#![feature(custom_inner_attributes)]
+#![warn(clippy::uninlined_format_args)]
+#![allow(named_arguments_used_positionally, unused_imports, unused_macros, unused_variables)]
+#![allow(clippy::eq_op, clippy::format_in_format_args, clippy::print_literal)]
+
+extern crate proc_macro_with_span;
+use proc_macro_with_span::with_span;
+
+macro_rules! no_param_str {
+ () => {
+ "{}"
+ };
+}
+
+macro_rules! my_println {
+ ($($args:tt),*) => {{
+ println!($($args),*)
+ }};
+}
+
+macro_rules! my_println_args {
+ ($($args:tt),*) => {{
+ println!("foo: {}", format_args!($($args),*))
+ }};
+}
+
+fn tester(fn_arg: i32) {
+ let local_i32 = 1;
+ let local_f64 = 2.0;
+ let local_opt: Option<i32> = Some(3);
+ let width = 4;
+ let prec = 5;
+ let val = 6;
+
+ // make sure this file hasn't been corrupted with tabs converted to spaces
+ // let _ = ' '; // <- this is a single tab character
+ let _: &[u8; 3] = b" "; // <- <tab><space><tab>
+
+ println!("val='{}'", local_i32);
+ println!("val='{ }'", local_i32); // 3 spaces
+ println!("val='{ }'", local_i32); // tab
+ println!("val='{ }'", local_i32); // space+tab
+ println!("val='{ }'", local_i32); // tab+space
+ println!(
+ "val='{
+ }'",
+ local_i32
+ );
+ println!("{}", local_i32);
+ println!("{}", fn_arg);
+ println!("{:?}", local_i32);
+ println!("{:#?}", local_i32);
+ println!("{:4}", local_i32);
+ println!("{:04}", local_i32);
+ println!("{:<3}", local_i32);
+ println!("{:#010x}", local_i32);
+ println!("{:.1}", local_f64);
+ println!("Hello {} is {:.*}", "x", local_i32, local_f64);
+ println!("Hello {} is {:.*}", local_i32, 5, local_f64);
+ println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
+ println!("{} {}", local_i32, local_f64);
+ println!("{}, {}", local_i32, local_opt.unwrap());
+ println!("{}", val);
+ println!("{}", v = val);
+ println!("{} {1}", local_i32, 42);
+ println!("val='{\t }'", local_i32);
+ println!("val='{\n }'", local_i32);
+ println!("val='{local_i32}'", local_i32 = local_i32);
+ println!("val='{local_i32}'", local_i32 = fn_arg);
+ println!("{0}", local_i32);
+ println!("{0:?}", local_i32);
+ println!("{0:#?}", local_i32);
+ println!("{0:04}", local_i32);
+ println!("{0:<3}", local_i32);
+ println!("{0:#010x}", local_i32);
+ println!("{0:.1}", local_f64);
+ println!("{0} {0}", local_i32);
+ println!("{1} {} {0} {}", local_i32, local_f64);
+ println!("{0} {1}", local_i32, local_f64);
+ println!("{1} {0}", local_i32, local_f64);
+ println!("{1} {0} {1} {0}", local_i32, local_f64);
+ println!("{1} {0}", "str", local_i32);
+ println!("{v}", v = local_i32);
+ println!("{local_i32:0$}", width);
+ println!("{local_i32:w$}", w = width);
+ println!("{local_i32:.0$}", prec);
+ println!("{local_i32:.p$}", p = prec);
+ println!("{:0$}", v = val);
+ println!("{0:0$}", v = val);
+ println!("{:0$.0$}", v = val);
+ println!("{0:0$.0$}", v = val);
+ println!("{0:0$.v$}", v = val);
+ println!("{0:v$.0$}", v = val);
+ println!("{v:0$.0$}", v = val);
+ println!("{v:v$.0$}", v = val);
+ println!("{v:0$.v$}", v = val);
+ println!("{v:v$.v$}", v = val);
+ println!("{:0$}", width);
+ println!("{:1$}", local_i32, width);
+ println!("{:w$}", w = width);
+ println!("{:w$}", local_i32, w = width);
+ println!("{:.0$}", prec);
+ println!("{:.1$}", local_i32, prec);
+ println!("{:.p$}", p = prec);
+ println!("{:.p$}", local_i32, p = prec);
+ println!("{:0$.1$}", width, prec);
+ println!("{:0$.w$}", width, w = prec);
+ println!("{:1$.2$}", local_f64, width, prec);
+ println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec);
+ println!(
+ "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$}",
+ local_i32, width, prec,
+ );
+ println!(
+ "{0:1$.2$} {0:2$.1$} {1:0$.2$} {1:2$.0$} {2:0$.1$} {2:1$.0$} {3}",
+ local_i32,
+ width,
+ prec,
+ 1 + 2
+ );
+ println!("Width = {}, value with width = {:0$}", local_i32, local_f64);
+ println!("{:w$.p$}", local_i32, w = width, p = prec);
+ println!("{:w$.p$}", w = width, p = prec);
+ println!("{}", format!("{}", local_i32));
+ my_println!("{}", local_i32);
+ my_println_args!("{}", local_i32);
+
+ // these should NOT be modified by the lint
+ println!(concat!("nope ", "{}"), local_i32);
+ println!("val='{local_i32}'");
+ println!("val='{local_i32 }'");
+ println!("val='{local_i32 }'"); // with tab
+ println!("val='{local_i32\n}'");
+ println!("{}", usize::MAX);
+ println!("{}", local_opt.unwrap());
+ println!(
+ "val='{local_i32
+ }'"
+ );
+ println!(no_param_str!(), local_i32);
+
+ println!(
+ "{}",
+ // comment with a comma , in it
+ val,
+ );
+ println!("{}", /* comment with a comma , in it */ val);
+
+ println!(with_span!("{0} {1}" "{1} {0}"), local_i32, local_f64);
+ println!("{}", with_span!(span val));
+
+ if local_i32 > 0 {
+ panic!("p1 {}", local_i32);
+ }
+ if local_i32 > 0 {
+ panic!("p2 {0}", local_i32);
+ }
+ if local_i32 > 0 {
+ panic!("p3 {local_i32}", local_i32 = local_i32);
+ }
+ if local_i32 > 0 {
+ panic!("p4 {local_i32}");
+ }
+}
+
+fn main() {
+ tester(42);
+}
+
+fn _under_msrv() {
+ #![clippy::msrv = "1.57"]
+ let local_i32 = 1;
+ println!("don't expand='{}'", local_i32);
+}
+
+fn _meets_msrv() {
+ #![clippy::msrv = "1.58"]
+ let local_i32 = 1;
+ println!("expand='{}'", local_i32);
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args.stderr b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
new file mode 100644
index 000000000..2ce3b7fa9
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args.stderr
@@ -0,0 +1,879 @@
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:41:5
+ |
+LL | println!("val='{}'", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::uninlined-format-args` implied by `-D warnings`
+help: change this to
+ |
+LL - println!("val='{}'", local_i32);
+LL + println!("val='{local_i32}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:42:5
+ |
+LL | println!("val='{ }'", local_i32); // 3 spaces
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{ }'", local_i32); // 3 spaces
+LL + println!("val='{local_i32}'"); // 3 spaces
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:43:5
+ |
+LL | println!("val='{ }'", local_i32); // tab
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{ }'", local_i32); // tab
+LL + println!("val='{local_i32}'"); // tab
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:44:5
+ |
+LL | println!("val='{ }'", local_i32); // space+tab
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{ }'", local_i32); // space+tab
+LL + println!("val='{local_i32}'"); // space+tab
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:45:5
+ |
+LL | println!("val='{ }'", local_i32); // tab+space
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{ }'", local_i32); // tab+space
+LL + println!("val='{local_i32}'"); // tab+space
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:51:5
+ |
+LL | println!("{}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", local_i32);
+LL + println!("{local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:52:5
+ |
+LL | println!("{}", fn_arg);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", fn_arg);
+LL + println!("{fn_arg}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:53:5
+ |
+LL | println!("{:?}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:?}", local_i32);
+LL + println!("{local_i32:?}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:54:5
+ |
+LL | println!("{:#?}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:#?}", local_i32);
+LL + println!("{local_i32:#?}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:55:5
+ |
+LL | println!("{:4}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:4}", local_i32);
+LL + println!("{local_i32:4}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:56:5
+ |
+LL | println!("{:04}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:04}", local_i32);
+LL + println!("{local_i32:04}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:57:5
+ |
+LL | println!("{:<3}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:<3}", local_i32);
+LL + println!("{local_i32:<3}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:58:5
+ |
+LL | println!("{:#010x}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:#010x}", local_i32);
+LL + println!("{local_i32:#010x}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:59:5
+ |
+LL | println!("{:.1}", local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:.1}", local_f64);
+LL + println!("{local_f64:.1}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:60:5
+ |
+LL | println!("Hello {} is {:.*}", "x", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("Hello {} is {:.*}", "x", local_i32, local_f64);
+LL + println!("Hello {} is {local_f64:.local_i32$}", "x");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:61:5
+ |
+LL | println!("Hello {} is {:.*}", local_i32, 5, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("Hello {} is {:.*}", local_i32, 5, local_f64);
+LL + println!("Hello {local_i32} is {local_f64:.*}", 5);
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:62:5
+ |
+LL | println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("Hello {} is {2:.*}", local_i32, 5, local_f64);
+LL + println!("Hello {local_i32} is {local_f64:.*}", 5);
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:63:5
+ |
+LL | println!("{} {}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{} {}", local_i32, local_f64);
+LL + println!("{local_i32} {local_f64}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:64:5
+ |
+LL | println!("{}, {}", local_i32, local_opt.unwrap());
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}, {}", local_i32, local_opt.unwrap());
+LL + println!("{local_i32}, {}", local_opt.unwrap());
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:65:5
+ |
+LL | println!("{}", val);
+ | ^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", val);
+LL + println!("{val}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:66:5
+ |
+LL | println!("{}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", v = val);
+LL + println!("{val}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:68:5
+ |
+LL | println!("val='{/t }'", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{/t }'", local_i32);
+LL + println!("val='{local_i32}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:69:5
+ |
+LL | println!("val='{/n }'", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{/n }'", local_i32);
+LL + println!("val='{local_i32}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:70:5
+ |
+LL | println!("val='{local_i32}'", local_i32 = local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{local_i32}'", local_i32 = local_i32);
+LL + println!("val='{local_i32}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:71:5
+ |
+LL | println!("val='{local_i32}'", local_i32 = fn_arg);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("val='{local_i32}'", local_i32 = fn_arg);
+LL + println!("val='{fn_arg}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:72:5
+ |
+LL | println!("{0}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0}", local_i32);
+LL + println!("{local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:73:5
+ |
+LL | println!("{0:?}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:?}", local_i32);
+LL + println!("{local_i32:?}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:74:5
+ |
+LL | println!("{0:#?}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:#?}", local_i32);
+LL + println!("{local_i32:#?}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:75:5
+ |
+LL | println!("{0:04}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:04}", local_i32);
+LL + println!("{local_i32:04}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:76:5
+ |
+LL | println!("{0:<3}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:<3}", local_i32);
+LL + println!("{local_i32:<3}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:77:5
+ |
+LL | println!("{0:#010x}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:#010x}", local_i32);
+LL + println!("{local_i32:#010x}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:78:5
+ |
+LL | println!("{0:.1}", local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:.1}", local_f64);
+LL + println!("{local_f64:.1}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:79:5
+ |
+LL | println!("{0} {0}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0} {0}", local_i32);
+LL + println!("{local_i32} {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:80:5
+ |
+LL | println!("{1} {} {0} {}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{1} {} {0} {}", local_i32, local_f64);
+LL + println!("{local_f64} {local_i32} {local_i32} {local_f64}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:81:5
+ |
+LL | println!("{0} {1}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0} {1}", local_i32, local_f64);
+LL + println!("{local_i32} {local_f64}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:82:5
+ |
+LL | println!("{1} {0}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{1} {0}", local_i32, local_f64);
+LL + println!("{local_f64} {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:83:5
+ |
+LL | println!("{1} {0} {1} {0}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{1} {0} {1} {0}", local_i32, local_f64);
+LL + println!("{local_f64} {local_i32} {local_f64} {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:85:5
+ |
+LL | println!("{v}", v = local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{v}", v = local_i32);
+LL + println!("{local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:86:5
+ |
+LL | println!("{local_i32:0$}", width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{local_i32:0$}", width);
+LL + println!("{local_i32:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:87:5
+ |
+LL | println!("{local_i32:w$}", w = width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{local_i32:w$}", w = width);
+LL + println!("{local_i32:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:88:5
+ |
+LL | println!("{local_i32:.0$}", prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{local_i32:.0$}", prec);
+LL + println!("{local_i32:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:89:5
+ |
+LL | println!("{local_i32:.p$}", p = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{local_i32:.p$}", p = prec);
+LL + println!("{local_i32:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:90:5
+ |
+LL | println!("{:0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:0$}", v = val);
+LL + println!("{val:val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:91:5
+ |
+LL | println!("{0:0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:0$}", v = val);
+LL + println!("{val:val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:92:5
+ |
+LL | println!("{:0$.0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:0$.0$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:93:5
+ |
+LL | println!("{0:0$.0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:0$.0$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:94:5
+ |
+LL | println!("{0:0$.v$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:0$.v$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:95:5
+ |
+LL | println!("{0:v$.0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{0:v$.0$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:96:5
+ |
+LL | println!("{v:0$.0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{v:0$.0$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:97:5
+ |
+LL | println!("{v:v$.0$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{v:v$.0$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:98:5
+ |
+LL | println!("{v:0$.v$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{v:0$.v$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:99:5
+ |
+LL | println!("{v:v$.v$}", v = val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{v:v$.v$}", v = val);
+LL + println!("{val:val$.val$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:100:5
+ |
+LL | println!("{:0$}", width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:0$}", width);
+LL + println!("{width:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:101:5
+ |
+LL | println!("{:1$}", local_i32, width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:1$}", local_i32, width);
+LL + println!("{local_i32:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:102:5
+ |
+LL | println!("{:w$}", w = width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:w$}", w = width);
+LL + println!("{width:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:103:5
+ |
+LL | println!("{:w$}", local_i32, w = width);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:w$}", local_i32, w = width);
+LL + println!("{local_i32:width$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:104:5
+ |
+LL | println!("{:.0$}", prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:.0$}", prec);
+LL + println!("{prec:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:105:5
+ |
+LL | println!("{:.1$}", local_i32, prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:.1$}", local_i32, prec);
+LL + println!("{local_i32:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:106:5
+ |
+LL | println!("{:.p$}", p = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:.p$}", p = prec);
+LL + println!("{prec:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:107:5
+ |
+LL | println!("{:.p$}", local_i32, p = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:.p$}", local_i32, p = prec);
+LL + println!("{local_i32:.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:108:5
+ |
+LL | println!("{:0$.1$}", width, prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:0$.1$}", width, prec);
+LL + println!("{width:width$.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:109:5
+ |
+LL | println!("{:0$.w$}", width, w = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:0$.w$}", width, w = prec);
+LL + println!("{width:width$.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:110:5
+ |
+LL | println!("{:1$.2$}", local_f64, width, prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:1$.2$}", local_f64, width, prec);
+LL + println!("{local_f64:width$.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:111:5
+ |
+LL | println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:1$.2$} {0} {1} {2}", local_f64, width, prec);
+LL + println!("{local_f64:width$.prec$} {local_f64} {width} {prec}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:123:5
+ |
+LL | println!("Width = {}, value with width = {:0$}", local_i32, local_f64);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("Width = {}, value with width = {:0$}", local_i32, local_f64);
+LL + println!("Width = {local_i32}, value with width = {local_f64:local_i32$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:124:5
+ |
+LL | println!("{:w$.p$}", local_i32, w = width, p = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:w$.p$}", local_i32, w = width, p = prec);
+LL + println!("{local_i32:width$.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:125:5
+ |
+LL | println!("{:w$.p$}", w = width, p = prec);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{:w$.p$}", w = width, p = prec);
+LL + println!("{width:width$.prec$}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:126:20
+ |
+LL | println!("{}", format!("{}", local_i32));
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", format!("{}", local_i32));
+LL + println!("{}", format!("{local_i32}"));
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:149:5
+ |
+LL | println!("{}", /* comment with a comma , in it */ val);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("{}", /* comment with a comma , in it */ val);
+LL + println!("{val}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:155:9
+ |
+LL | panic!("p1 {}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p1 {}", local_i32);
+LL + panic!("p1 {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:158:9
+ |
+LL | panic!("p2 {0}", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p2 {0}", local_i32);
+LL + panic!("p2 {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:161:9
+ |
+LL | panic!("p3 {local_i32}", local_i32 = local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p3 {local_i32}", local_i32 = local_i32);
+LL + panic!("p3 {local_i32}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args.rs:181:5
+ |
+LL | println!("expand='{}'", local_i32);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - println!("expand='{}'", local_i32);
+LL + println!("expand='{local_i32}'");
+ |
+
+error: aborting due to 73 previous errors
+
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
new file mode 100644
index 000000000..96cc08779
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.fixed
@@ -0,0 +1,29 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+
+#![warn(clippy::uninlined_format_args)]
+
+fn main() {
+ let var = 1;
+
+ println!("val='{var}'");
+
+ if var > 0 {
+ panic!("p1 {}", var);
+ }
+ if var > 0 {
+ panic!("p2 {0}", var);
+ }
+ if var > 0 {
+ panic!("p3 {var}", var = var);
+ }
+
+ #[allow(non_fmt_panics)]
+ {
+ if var > 0 {
+ panic!("p4 {var}");
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr
new file mode 100644
index 000000000..2c8061259
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2018.stderr
@@ -0,0 +1,15 @@
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:11:5
+ |
+LL | println!("val='{}'", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::uninlined-format-args` implied by `-D warnings`
+help: change this to
+ |
+LL - println!("val='{}'", var);
+LL + println!("val='{var}'");
+ |
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
new file mode 100644
index 000000000..faf8ca4d3
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.fixed
@@ -0,0 +1,29 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+
+#![warn(clippy::uninlined_format_args)]
+
+fn main() {
+ let var = 1;
+
+ println!("val='{var}'");
+
+ if var > 0 {
+ panic!("p1 {var}");
+ }
+ if var > 0 {
+ panic!("p2 {var}");
+ }
+ if var > 0 {
+ panic!("p3 {var}");
+ }
+
+ #[allow(non_fmt_panics)]
+ {
+ if var > 0 {
+ panic!("p4 {var}");
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
new file mode 100644
index 000000000..0f09c45f4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.edition2021.stderr
@@ -0,0 +1,51 @@
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:11:5
+ |
+LL | println!("val='{}'", var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: `-D clippy::uninlined-format-args` implied by `-D warnings`
+help: change this to
+ |
+LL - println!("val='{}'", var);
+LL + println!("val='{var}'");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:14:9
+ |
+LL | panic!("p1 {}", var);
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p1 {}", var);
+LL + panic!("p1 {var}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:17:9
+ |
+LL | panic!("p2 {0}", var);
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p2 {0}", var);
+LL + panic!("p2 {var}");
+ |
+
+error: variables can be used directly in the `format!` string
+ --> $DIR/uninlined_format_args_panic.rs:20:9
+ |
+LL | panic!("p3 {var}", var = var);
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+help: change this to
+ |
+LL - panic!("p3 {var}", var = var);
+LL + panic!("p3 {var}");
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
new file mode 100644
index 000000000..6421c5bbe
--- /dev/null
+++ b/src/tools/clippy/tests/ui/uninlined_format_args_panic.rs
@@ -0,0 +1,29 @@
+// revisions: edition2018 edition2021
+//[edition2018] edition:2018
+//[edition2021] edition:2021
+// run-rustfix
+
+#![warn(clippy::uninlined_format_args)]
+
+fn main() {
+ let var = 1;
+
+ println!("val='{}'", var);
+
+ if var > 0 {
+ panic!("p1 {}", var);
+ }
+ if var > 0 {
+ panic!("p2 {0}", var);
+ }
+ if var > 0 {
+ panic!("p3 {var}", var = var);
+ }
+
+ #[allow(non_fmt_panics)]
+ {
+ if var > 0 {
+ panic!("p4 {var}");
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/unit_arg.rs b/src/tools/clippy/tests/ui/unit_arg.rs
index 7bf3adc07..07e70873a 100644
--- a/src/tools/clippy/tests/ui/unit_arg.rs
+++ b/src/tools/clippy/tests/ui/unit_arg.rs
@@ -1,17 +1,16 @@
// aux-build: proc_macro_with_span.rs
-
#![warn(clippy::unit_arg)]
+#![allow(unused_must_use, unused_variables)]
#![allow(
+ clippy::let_unit_value,
+ clippy::needless_question_mark,
+ clippy::never_loop,
clippy::no_effect,
- unused_must_use,
- unused_variables,
- clippy::unused_unit,
- clippy::unnecessary_wraps,
clippy::or_fun_call,
- clippy::needless_question_mark,
clippy::self_named_constructors,
- clippy::let_unit_value,
- clippy::never_loop
+ clippy::uninlined_format_args,
+ clippy::unnecessary_wraps,
+ clippy::unused_unit
)]
extern crate proc_macro_with_span;
diff --git a/src/tools/clippy/tests/ui/unit_arg.stderr b/src/tools/clippy/tests/ui/unit_arg.stderr
index 1de9d44bb..74d4d2f40 100644
--- a/src/tools/clippy/tests/ui/unit_arg.stderr
+++ b/src/tools/clippy/tests/ui/unit_arg.stderr
@@ -1,5 +1,5 @@
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:63:5
+ --> $DIR/unit_arg.rs:62:5
|
LL | / foo({
LL | | 1;
@@ -20,7 +20,7 @@ LL ~ foo(());
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:66:5
+ --> $DIR/unit_arg.rs:65:5
|
LL | foo(foo(1));
| ^^^^^^^^^^^
@@ -32,7 +32,7 @@ LL ~ foo(());
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:67:5
+ --> $DIR/unit_arg.rs:66:5
|
LL | / foo({
LL | | foo(1);
@@ -54,7 +54,7 @@ LL ~ foo(());
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:72:5
+ --> $DIR/unit_arg.rs:71:5
|
LL | / b.bar({
LL | | 1;
@@ -74,7 +74,7 @@ LL ~ b.bar(());
|
error: passing unit values to a function
- --> $DIR/unit_arg.rs:75:5
+ --> $DIR/unit_arg.rs:74:5
|
LL | taking_multiple_units(foo(0), foo(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL ~ taking_multiple_units((), ());
|
error: passing unit values to a function
- --> $DIR/unit_arg.rs:76:5
+ --> $DIR/unit_arg.rs:75:5
|
LL | / taking_multiple_units(foo(0), {
LL | | foo(1);
@@ -110,7 +110,7 @@ LL ~ taking_multiple_units((), ());
|
error: passing unit values to a function
- --> $DIR/unit_arg.rs:80:5
+ --> $DIR/unit_arg.rs:79:5
|
LL | / taking_multiple_units(
LL | | {
@@ -146,7 +146,7 @@ LL ~ );
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:91:13
+ --> $DIR/unit_arg.rs:90:13
|
LL | None.or(Some(foo(2)));
| ^^^^^^^^^^^^
@@ -160,7 +160,7 @@ LL ~ });
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:94:5
+ --> $DIR/unit_arg.rs:93:5
|
LL | foo(foo(()));
| ^^^^^^^^^^^^
@@ -172,7 +172,7 @@ LL ~ foo(());
|
error: passing a unit value to a function
- --> $DIR/unit_arg.rs:131:5
+ --> $DIR/unit_arg.rs:130:5
|
LL | Some(foo(1))
| ^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
index 9400e93ca..5787471a3 100644
--- a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
+++ b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.fixed
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::unit_arg)]
-#![allow(clippy::no_effect, unused_must_use, unused_variables)]
+#![allow(unused_must_use, unused_variables)]
+#![allow(clippy::no_effect, clippy::uninlined_format_args)]
use std::fmt::Debug;
diff --git a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
index 5f52b6c53..6a42c2ccf 100644
--- a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
+++ b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.rs
@@ -1,6 +1,7 @@
// run-rustfix
#![warn(clippy::unit_arg)]
-#![allow(clippy::no_effect, unused_must_use, unused_variables)]
+#![allow(unused_must_use, unused_variables)]
+#![allow(clippy::no_effect, clippy::uninlined_format_args)]
use std::fmt::Debug;
diff --git a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.stderr b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.stderr
index d35e93169..c697dfb1e 100644
--- a/src/tools/clippy/tests/ui/unit_arg_empty_blocks.stderr
+++ b/src/tools/clippy/tests/ui/unit_arg_empty_blocks.stderr
@@ -1,5 +1,5 @@
error: passing a unit value to a function
- --> $DIR/unit_arg_empty_blocks.rs:16:5
+ --> $DIR/unit_arg_empty_blocks.rs:17:5
|
LL | foo({});
| ^^^^--^
@@ -9,7 +9,7 @@ LL | foo({});
= note: `-D clippy::unit-arg` implied by `-D warnings`
error: passing a unit value to a function
- --> $DIR/unit_arg_empty_blocks.rs:17:5
+ --> $DIR/unit_arg_empty_blocks.rs:18:5
|
LL | foo3({}, 2, 2);
| ^^^^^--^^^^^^^
@@ -17,7 +17,7 @@ LL | foo3({}, 2, 2);
| help: use a unit literal instead: `()`
error: passing unit values to a function
- --> $DIR/unit_arg_empty_blocks.rs:18:5
+ --> $DIR/unit_arg_empty_blocks.rs:19:5
|
LL | taking_two_units({}, foo(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL ~ taking_two_units((), ());
|
error: passing unit values to a function
- --> $DIR/unit_arg_empty_blocks.rs:19:5
+ --> $DIR/unit_arg_empty_blocks.rs:20:5
|
LL | taking_three_units({}, foo(0), foo(1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/clippy/tests/ui/unit_hash.stderr b/src/tools/clippy/tests/ui/unit_hash.stderr
index 050fa55a1..089d1212d 100644
--- a/src/tools/clippy/tests/ui/unit_hash.stderr
+++ b/src/tools/clippy/tests/ui/unit_hash.stderr
@@ -4,8 +4,8 @@ error: this call to `hash` on the unit type will do nothing
LL | Foo::Empty => ().hash(&mut state),
| ^^^^^^^^^^^^^^^^^^^ help: remove the call to `hash` or consider using: `0_u8.hash(&mut state)`
|
- = note: `-D clippy::unit-hash` implied by `-D warnings`
= note: the implementation of `Hash` for `()` is a no-op
+ = note: `-D clippy::unit-hash` implied by `-D warnings`
error: this call to `hash` on the unit type will do nothing
--> $DIR/unit_hash.rs:24:5
diff --git a/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr b/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
index e63d58746..1d9564ce2 100644
--- a/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
+++ b/src/tools/clippy/tests/ui/unit_return_expecting_ord.stderr
@@ -4,12 +4,12 @@ error: this closure returns the unit type which also implements Ord
LL | structs.sort_by_key(|s| {
| ^^^
|
- = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings`
help: probably caused by this trailing semicolon
--> $DIR/unit_return_expecting_ord.rs:19:24
|
LL | double(s.field);
| ^
+ = note: `-D clippy::unit-return-expecting-ord` implied by `-D warnings`
error: this closure returns the unit type which also implements PartialOrd
--> $DIR/unit_return_expecting_ord.rs:22:30
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.fixed b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
index ee9f15734..ec8c6abfa 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.fixed
@@ -97,4 +97,22 @@ mod fixable {
let _ = -(1 + 1) as i64;
}
+
+ fn issue_9563() {
+ let _: f64 = (-8.0_f64).exp();
+ #[allow(clippy::precedence)]
+ let _: f64 = -8.0_f64.exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
+ }
+
+ fn issue_9562_non_literal() {
+ fn foo() -> f32 {
+ 0.
+ }
+
+ let _num = foo();
+ }
+
+ fn issue_9603() {
+ let _: f32 = -0x400 as f32;
+ }
}
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.rs b/src/tools/clippy/tests/ui/unnecessary_cast.rs
index 5b7041242..5213cdc26 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.rs
@@ -97,4 +97,22 @@ mod fixable {
let _ = -(1 + 1) as i64;
}
+
+ fn issue_9563() {
+ let _: f64 = (-8.0 as f64).exp();
+ #[allow(clippy::precedence)]
+ let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
+ }
+
+ fn issue_9562_non_literal() {
+ fn foo() -> f32 {
+ 0.
+ }
+
+ let _num = foo() as f32;
+ }
+
+ fn issue_9603() {
+ let _: f32 = -0x400 as f32;
+ }
}
diff --git a/src/tools/clippy/tests/ui/unnecessary_cast.stderr b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
index f7829ff3b..e5c3dd5e5 100644
--- a/src/tools/clippy/tests/ui/unnecessary_cast.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_cast.stderr
@@ -162,5 +162,23 @@ error: casting integer literal to `i64` is unnecessary
LL | let _: i64 = -(1) as i64;
| ^^^^^^^^^^^ help: try: `-1_i64`
-error: aborting due to 27 previous errors
+error: casting float literal to `f64` is unnecessary
+ --> $DIR/unnecessary_cast.rs:102:22
+ |
+LL | let _: f64 = (-8.0 as f64).exp();
+ | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)`
+
+error: casting float literal to `f64` is unnecessary
+ --> $DIR/unnecessary_cast.rs:104:23
+ |
+LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
+ | ^^^^^^^^^^^^ help: try: `8.0_f64`
+
+error: casting to the same type is unnecessary (`f32` -> `f32`)
+ --> $DIR/unnecessary_cast.rs:112:20
+ |
+LL | let _num = foo() as f32;
+ | ^^^^^^^^^^^^ help: try: `foo()`
+
+error: aborting due to 30 previous errors
diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.rs b/src/tools/clippy/tests/ui/unnecessary_clone.rs
index 6770a7fac..8b1629b19 100644
--- a/src/tools/clippy/tests/ui/unnecessary_clone.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_clone.rs
@@ -1,7 +1,7 @@
// does not test any rustfixable lints
-
#![warn(clippy::clone_on_ref_ptr)]
-#![allow(unused, clippy::redundant_clone, clippy::unnecessary_wraps)]
+#![allow(unused)]
+#![allow(clippy::redundant_clone, clippy::uninlined_format_args, clippy::unnecessary_wraps)]
use std::cell::RefCell;
use std::rc::{self, Rc};
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.fixed b/src/tools/clippy/tests/ui/unnecessary_join.fixed
index 7e12c6ae4..347953960 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_join.fixed
@@ -1,6 +1,6 @@
// run-rustfix
-
#![warn(clippy::unnecessary_join)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
// should be linted
diff --git a/src/tools/clippy/tests/ui/unnecessary_join.rs b/src/tools/clippy/tests/ui/unnecessary_join.rs
index 0a21656a7..344918cd2 100644
--- a/src/tools/clippy/tests/ui/unnecessary_join.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_join.rs
@@ -1,6 +1,6 @@
// run-rustfix
-
#![warn(clippy::unnecessary_join)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
// should be linted
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
index eed817968..ce4a82e02 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.fixed
@@ -1,9 +1,13 @@
// run-rustfix
+// aux-build: proc_macro_with_span.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
+extern crate proc_macro_with_span;
+use proc_macro_with_span::with_span;
+
struct Deep(Option<usize>);
#[derive(Copy, Clone)]
@@ -21,6 +25,14 @@ fn some_call<T: Default>() -> T {
T::default()
}
+struct Issue9427(i32);
+
+impl Drop for Issue9427 {
+ fn drop(&mut self) {
+ println!("{}", self.0);
+ }
+}
+
fn main() {
let astronomers_pi = 10;
let ext_arr: [usize; 1] = [2];
@@ -73,6 +85,9 @@ fn main() {
let _ = deep.0.or_else(|| some_call());
let _ = opt.ok_or_else(|| ext_arr[0]);
+ // Should not lint - bool
+ let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
+
// should not lint, bind_instead_of_map takes priority
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
let _ = Some(10).and_then(|idx| Some(idx));
@@ -130,3 +145,9 @@ fn main() {
let _: Result<usize, usize> = res.and_then(|x| Err(x));
let _: Result<usize, usize> = res.or_else(|err| Ok(err));
}
+
+#[allow(unused)]
+fn issue9485() {
+ // should not lint, is in proc macro
+ with_span!(span Some(42).unwrap_or_else(|| 2););
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
index 1588db79b..59cdf6628 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.rs
@@ -1,9 +1,13 @@
// run-rustfix
+// aux-build: proc_macro_with_span.rs
#![warn(clippy::unnecessary_lazy_evaluations)]
#![allow(clippy::redundant_closure)]
#![allow(clippy::bind_instead_of_map)]
#![allow(clippy::map_identity)]
+extern crate proc_macro_with_span;
+use proc_macro_with_span::with_span;
+
struct Deep(Option<usize>);
#[derive(Copy, Clone)]
@@ -21,6 +25,14 @@ fn some_call<T: Default>() -> T {
T::default()
}
+struct Issue9427(i32);
+
+impl Drop for Issue9427 {
+ fn drop(&mut self) {
+ println!("{}", self.0);
+ }
+}
+
fn main() {
let astronomers_pi = 10;
let ext_arr: [usize; 1] = [2];
@@ -73,6 +85,9 @@ fn main() {
let _ = deep.0.or_else(|| some_call());
let _ = opt.ok_or_else(|| ext_arr[0]);
+ // Should not lint - bool
+ let _ = (0 == 1).then(|| Issue9427(0)); // Issue9427 has a significant drop
+
// should not lint, bind_instead_of_map takes priority
let _ = Some(10).and_then(|idx| Some(ext_arr[idx]));
let _ = Some(10).and_then(|idx| Some(idx));
@@ -130,3 +145,9 @@ fn main() {
let _: Result<usize, usize> = res.and_then(|x| Err(x));
let _: Result<usize, usize> = res.or_else(|err| Ok(err));
}
+
+#[allow(unused)]
+fn issue9485() {
+ // should not lint, is in proc macro
+ with_span!(span Some(42).unwrap_or_else(|| 2););
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
index 83dc7fd83..8a9ece4aa 100644
--- a/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_lazy_eval.stderr
@@ -1,5 +1,5 @@
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:36:13
+ --> $DIR/unnecessary_lazy_eval.rs:48:13
|
LL | let _ = opt.unwrap_or_else(|| 2);
| ^^^^--------------------
@@ -9,7 +9,7 @@ LL | let _ = opt.unwrap_or_else(|| 2);
= note: `-D clippy::unnecessary-lazy-evaluations` implied by `-D warnings`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:37:13
+ --> $DIR/unnecessary_lazy_eval.rs:49:13
|
LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
| ^^^^---------------------------------
@@ -17,7 +17,7 @@ LL | let _ = opt.unwrap_or_else(|| astronomers_pi);
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:38:13
+ --> $DIR/unnecessary_lazy_eval.rs:50:13
|
LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
| ^^^^-------------------------------------
@@ -25,7 +25,7 @@ LL | let _ = opt.unwrap_or_else(|| ext_str.some_field);
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:40:13
+ --> $DIR/unnecessary_lazy_eval.rs:52:13
|
LL | let _ = opt.and_then(|_| ext_opt);
| ^^^^---------------------
@@ -33,7 +33,7 @@ LL | let _ = opt.and_then(|_| ext_opt);
| help: use `and(..)` instead: `and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:41:13
+ --> $DIR/unnecessary_lazy_eval.rs:53:13
|
LL | let _ = opt.or_else(|| ext_opt);
| ^^^^-------------------
@@ -41,7 +41,7 @@ LL | let _ = opt.or_else(|| ext_opt);
| help: use `or(..)` instead: `or(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:42:13
+ --> $DIR/unnecessary_lazy_eval.rs:54:13
|
LL | let _ = opt.or_else(|| None);
| ^^^^----------------
@@ -49,7 +49,7 @@ LL | let _ = opt.or_else(|| None);
| help: use `or(..)` instead: `or(None)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:43:13
+ --> $DIR/unnecessary_lazy_eval.rs:55:13
|
LL | let _ = opt.get_or_insert_with(|| 2);
| ^^^^------------------------
@@ -57,7 +57,7 @@ LL | let _ = opt.get_or_insert_with(|| 2);
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:44:13
+ --> $DIR/unnecessary_lazy_eval.rs:56:13
|
LL | let _ = opt.ok_or_else(|| 2);
| ^^^^----------------
@@ -65,7 +65,7 @@ LL | let _ = opt.ok_or_else(|| 2);
| help: use `ok_or(..)` instead: `ok_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:45:13
+ --> $DIR/unnecessary_lazy_eval.rs:57:13
|
LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
| ^^^^^^^^^^^^^^^^^-------------------------------
@@ -73,7 +73,7 @@ LL | let _ = nested_tuple_opt.unwrap_or_else(|| Some((1, 2)));
| help: use `unwrap_or(..)` instead: `unwrap_or(Some((1, 2)))`
error: unnecessary closure used with `bool::then`
- --> $DIR/unnecessary_lazy_eval.rs:46:13
+ --> $DIR/unnecessary_lazy_eval.rs:58:13
|
LL | let _ = cond.then(|| astronomers_pi);
| ^^^^^-----------------------
@@ -81,7 +81,7 @@ LL | let _ = cond.then(|| astronomers_pi);
| help: use `then_some(..)` instead: `then_some(astronomers_pi)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:49:13
+ --> $DIR/unnecessary_lazy_eval.rs:61:13
|
LL | let _ = Some(10).unwrap_or_else(|| 2);
| ^^^^^^^^^--------------------
@@ -89,7 +89,7 @@ LL | let _ = Some(10).unwrap_or_else(|| 2);
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:50:13
+ --> $DIR/unnecessary_lazy_eval.rs:62:13
|
LL | let _ = Some(10).and_then(|_| ext_opt);
| ^^^^^^^^^---------------------
@@ -97,7 +97,7 @@ LL | let _ = Some(10).and_then(|_| ext_opt);
| help: use `and(..)` instead: `and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:51:28
+ --> $DIR/unnecessary_lazy_eval.rs:63:28
|
LL | let _: Option<usize> = None.or_else(|| ext_opt);
| ^^^^^-------------------
@@ -105,7 +105,7 @@ LL | let _: Option<usize> = None.or_else(|| ext_opt);
| help: use `or(..)` instead: `or(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:52:13
+ --> $DIR/unnecessary_lazy_eval.rs:64:13
|
LL | let _ = None.get_or_insert_with(|| 2);
| ^^^^^------------------------
@@ -113,7 +113,7 @@ LL | let _ = None.get_or_insert_with(|| 2);
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:53:35
+ --> $DIR/unnecessary_lazy_eval.rs:65:35
|
LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
| ^^^^^----------------
@@ -121,7 +121,7 @@ LL | let _: Result<usize, usize> = None.ok_or_else(|| 2);
| help: use `ok_or(..)` instead: `ok_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:54:28
+ --> $DIR/unnecessary_lazy_eval.rs:66:28
|
LL | let _: Option<usize> = None.or_else(|| None);
| ^^^^^----------------
@@ -129,7 +129,7 @@ LL | let _: Option<usize> = None.or_else(|| None);
| help: use `or(..)` instead: `or(None)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:57:13
+ --> $DIR/unnecessary_lazy_eval.rs:69:13
|
LL | let _ = deep.0.unwrap_or_else(|| 2);
| ^^^^^^^--------------------
@@ -137,7 +137,7 @@ LL | let _ = deep.0.unwrap_or_else(|| 2);
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:58:13
+ --> $DIR/unnecessary_lazy_eval.rs:70:13
|
LL | let _ = deep.0.and_then(|_| ext_opt);
| ^^^^^^^---------------------
@@ -145,7 +145,7 @@ LL | let _ = deep.0.and_then(|_| ext_opt);
| help: use `and(..)` instead: `and(ext_opt)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:59:13
+ --> $DIR/unnecessary_lazy_eval.rs:71:13
|
LL | let _ = deep.0.or_else(|| None);
| ^^^^^^^----------------
@@ -153,7 +153,7 @@ LL | let _ = deep.0.or_else(|| None);
| help: use `or(..)` instead: `or(None)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:60:13
+ --> $DIR/unnecessary_lazy_eval.rs:72:13
|
LL | let _ = deep.0.get_or_insert_with(|| 2);
| ^^^^^^^------------------------
@@ -161,7 +161,7 @@ LL | let _ = deep.0.get_or_insert_with(|| 2);
| help: use `get_or_insert(..)` instead: `get_or_insert(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:61:13
+ --> $DIR/unnecessary_lazy_eval.rs:73:13
|
LL | let _ = deep.0.ok_or_else(|| 2);
| ^^^^^^^----------------
@@ -169,7 +169,7 @@ LL | let _ = deep.0.ok_or_else(|| 2);
| help: use `ok_or(..)` instead: `ok_or(2)`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:81:28
+ --> $DIR/unnecessary_lazy_eval.rs:96:28
|
LL | let _: Option<usize> = None.or_else(|| Some(3));
| ^^^^^-------------------
@@ -177,7 +177,7 @@ LL | let _: Option<usize> = None.or_else(|| Some(3));
| help: use `or(..)` instead: `or(Some(3))`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:82:13
+ --> $DIR/unnecessary_lazy_eval.rs:97:13
|
LL | let _ = deep.0.or_else(|| Some(3));
| ^^^^^^^-------------------
@@ -185,7 +185,7 @@ LL | let _ = deep.0.or_else(|| Some(3));
| help: use `or(..)` instead: `or(Some(3))`
error: unnecessary closure used to substitute value for `Option::None`
- --> $DIR/unnecessary_lazy_eval.rs:83:13
+ --> $DIR/unnecessary_lazy_eval.rs:98:13
|
LL | let _ = opt.or_else(|| Some(3));
| ^^^^-------------------
@@ -193,7 +193,7 @@ LL | let _ = opt.or_else(|| Some(3));
| help: use `or(..)` instead: `or(Some(3))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:89:13
+ --> $DIR/unnecessary_lazy_eval.rs:104:13
|
LL | let _ = res2.unwrap_or_else(|_| 2);
| ^^^^^---------------------
@@ -201,7 +201,7 @@ LL | let _ = res2.unwrap_or_else(|_| 2);
| help: use `unwrap_or(..)` instead: `unwrap_or(2)`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:90:13
+ --> $DIR/unnecessary_lazy_eval.rs:105:13
|
LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
| ^^^^^----------------------------------
@@ -209,7 +209,7 @@ LL | let _ = res2.unwrap_or_else(|_| astronomers_pi);
| help: use `unwrap_or(..)` instead: `unwrap_or(astronomers_pi)`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:91:13
+ --> $DIR/unnecessary_lazy_eval.rs:106:13
|
LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
| ^^^^^--------------------------------------
@@ -217,7 +217,7 @@ LL | let _ = res2.unwrap_or_else(|_| ext_str.some_field);
| help: use `unwrap_or(..)` instead: `unwrap_or(ext_str.some_field)`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:113:35
+ --> $DIR/unnecessary_lazy_eval.rs:128:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
| ^^^^--------------------
@@ -225,7 +225,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(2));
| help: use `and(..)` instead: `and(Err(2))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:114:35
+ --> $DIR/unnecessary_lazy_eval.rs:129:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
| ^^^^---------------------------------
@@ -233,7 +233,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(astronomers_pi));
| help: use `and(..)` instead: `and(Err(astronomers_pi))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:115:35
+ --> $DIR/unnecessary_lazy_eval.rs:130:35
|
LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field));
| ^^^^-------------------------------------
@@ -241,7 +241,7 @@ LL | let _: Result<usize, usize> = res.and_then(|_| Err(ext_str.some_field))
| help: use `and(..)` instead: `and(Err(ext_str.some_field))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:117:35
+ --> $DIR/unnecessary_lazy_eval.rs:132:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
| ^^^^------------------
@@ -249,7 +249,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(2));
| help: use `or(..)` instead: `or(Ok(2))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:118:35
+ --> $DIR/unnecessary_lazy_eval.rs:133:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
| ^^^^-------------------------------
@@ -257,7 +257,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(astronomers_pi));
| help: use `or(..)` instead: `or(Ok(astronomers_pi))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:119:35
+ --> $DIR/unnecessary_lazy_eval.rs:134:35
|
LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
| ^^^^-----------------------------------
@@ -265,7 +265,7 @@ LL | let _: Result<usize, usize> = res.or_else(|_| Ok(ext_str.some_field));
| help: use `or(..)` instead: `or(Ok(ext_str.some_field))`
error: unnecessary closure used to substitute value for `Result::Err`
- --> $DIR/unnecessary_lazy_eval.rs:120:35
+ --> $DIR/unnecessary_lazy_eval.rs:135:35
|
LL | let _: Result<usize, usize> = res.
| ___________________________________^
diff --git a/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr b/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr
index 83a5618c9..db805eb36 100644
--- a/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_self_imports.stderr
@@ -6,8 +6,8 @@ LL | use std::fs::{self as alias};
| |
| help: consider omitting `::{self}`: `fs as alias;`
|
- = note: `-D clippy::unnecessary-self-imports` implied by `-D warnings`
= note: this will slightly change semantics; any non-module items at the same path will also be imported
+ = note: `-D clippy::unnecessary-self-imports` implied by `-D warnings`
error: import ending with `::{self}`
--> $DIR/unnecessary_self_imports.rs:8:1
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
index a920c63b1..fe09aad06 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.fixed
@@ -1,6 +1,6 @@
// run-rustfix
-#![allow(clippy::ptr_arg)]
+#![allow(clippy::needless_borrow, clippy::ptr_arg)]
#![warn(clippy::unnecessary_to_owned)]
#![feature(custom_inner_attributes)]
@@ -417,3 +417,12 @@ mod issue_9351 {
predicates_are_satisfied(id("abc".to_string()));
}
}
+
+mod issue_9504 {
+ #![allow(dead_code)]
+
+ async fn foo<S: AsRef<str>>(_: S) {}
+ async fn bar() {
+ foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
+ }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
index 2128bdacd..3de6d0903 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.rs
@@ -1,6 +1,6 @@
// run-rustfix
-#![allow(clippy::ptr_arg)]
+#![allow(clippy::needless_borrow, clippy::ptr_arg)]
#![warn(clippy::unnecessary_to_owned)]
#![feature(custom_inner_attributes)]
@@ -417,3 +417,12 @@ mod issue_9351 {
predicates_are_satisfied(id("abc".to_string()));
}
}
+
+mod issue_9504 {
+ #![allow(dead_code)]
+
+ async fn foo<S: AsRef<str>>(_: S) {}
+ async fn bar() {
+ foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
+ }
+}
diff --git a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
index 7deb90b06..02bf45a33 100644
--- a/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
+++ b/src/tools/clippy/tests/ui/unnecessary_to_owned.stderr
@@ -4,12 +4,12 @@ error: redundant clone
LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
| ^^^^^^^^^^^ help: remove this
|
- = note: `-D clippy::redundant-clone` implied by `-D warnings`
note: this value is dropped without further use
--> $DIR/unnecessary_to_owned.rs:151:20
|
LL | require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap().to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::redundant-clone` implied by `-D warnings`
error: redundant clone
--> $DIR/unnecessary_to_owned.rs:152:40
diff --git a/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr b/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
index b8d3c2945..6f7c31545 100644
--- a/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
+++ b/src/tools/clippy/tests/ui/unneeded_field_pattern.stderr
@@ -4,8 +4,8 @@ error: you matched a field with a wildcard pattern, consider using `..` instead
LL | Foo { a: _, b: 0, .. } => {},
| ^^^^
|
- = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings`
= help: try with `Foo { b: 0, .. }`
+ = note: `-D clippy::unneeded-field-pattern` implied by `-D warnings`
error: all the struct fields are matched to a wildcard pattern, consider using `..`
--> $DIR/unneeded_field_pattern.rs:16:9
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
index c223b5bc7..9786c7b12 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.fixed
@@ -1,9 +1,9 @@
// run-rustfix
-#![feature(box_patterns)]
+#![feature(box_patterns, custom_inner_attributes)]
#![warn(clippy::unnested_or_patterns)]
#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)]
-#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)]
+#![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
fn main() {
// Should be ignored by this lint, as nesting requires more characters.
@@ -33,3 +33,15 @@ fn main() {
if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {}
if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
}
+
+fn msrv_1_52() {
+ #![clippy::msrv = "1.52"]
+
+ if let [1] | [52] = [0] {}
+}
+
+fn msrv_1_53() {
+ #![clippy::msrv = "1.53"]
+
+ if let [1 | 53] = [0] {}
+}
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.rs b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
index 04cd11036..f57322396 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.rs
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.rs
@@ -1,9 +1,9 @@
// run-rustfix
-#![feature(box_patterns)]
+#![feature(box_patterns, custom_inner_attributes)]
#![warn(clippy::unnested_or_patterns)]
#![allow(clippy::cognitive_complexity, clippy::match_ref_pats, clippy::upper_case_acronyms)]
-#![allow(unreachable_patterns, irrefutable_let_patterns, unused_variables)]
+#![allow(unreachable_patterns, irrefutable_let_patterns, unused)]
fn main() {
// Should be ignored by this lint, as nesting requires more characters.
@@ -33,3 +33,15 @@ fn main() {
if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {}
}
+
+fn msrv_1_52() {
+ #![clippy::msrv = "1.52"]
+
+ if let [1] | [52] = [0] {}
+}
+
+fn msrv_1_53() {
+ #![clippy::msrv = "1.53"]
+
+ if let [1] | [53] = [0] {}
+}
diff --git a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
index 453c66cbb..fbc12fff0 100644
--- a/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
+++ b/src/tools/clippy/tests/ui/unnested_or_patterns.stderr
@@ -175,5 +175,16 @@ help: nest the patterns
LL | if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {}
| ~~~~~~~~~~~~~~~~~
-error: aborting due to 16 previous errors
+error: unnested or-patterns
+ --> $DIR/unnested_or_patterns.rs:46:12
+ |
+LL | if let [1] | [53] = [0] {}
+ | ^^^^^^^^^^
+ |
+help: nest the patterns
+ |
+LL | if let [1 | 53] = [0] {}
+ | ~~~~~~~~
+
+error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr
index 18c4276c6..8aaae2d7f 100644
--- a/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr
+++ b/src/tools/clippy/tests/ui/unsafe_derive_deserialize.stderr
@@ -4,8 +4,8 @@ error: you are deriving `serde::Deserialize` on a type that has methods using `u
LL | #[derive(Deserialize)]
| ^^^^^^^^^^^
|
- = note: `-D clippy::unsafe-derive-deserialize` implied by `-D warnings`
= help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html
+ = note: `-D clippy::unsafe-derive-deserialize` implied by `-D warnings`
= note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)
error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe`
diff --git a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
index cde4e96d6..d29888ac6 100644
--- a/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
+++ b/src/tools/clippy/tests/ui/unsafe_removed_from_name.rs
@@ -24,4 +24,7 @@ use mod_with_some_unsafe_things::Unsafe as LieAboutModSafety;
use mod_with_some_unsafe_things::Safe as IPromiseItsSafeThisTime;
use mod_with_some_unsafe_things::Unsafe as SuperUnsafeModThing;
+#[allow(clippy::unsafe_removed_from_name)]
+use mod_with_some_unsafe_things::Unsafe as SuperSafeThing;
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/unused_async.stderr b/src/tools/clippy/tests/ui/unused_async.stderr
index 8b8ad065a..cff3eccbd 100644
--- a/src/tools/clippy/tests/ui/unused_async.stderr
+++ b/src/tools/clippy/tests/ui/unused_async.stderr
@@ -6,8 +6,8 @@ LL | | 4
LL | | }
| |_^
|
- = note: `-D clippy::unused-async` implied by `-D warnings`
= help: consider removing the `async` from this function
+ = note: `-D clippy::unused-async` implied by `-D warnings`
error: unused `async` for function with no await statements
--> $DIR/unused_async.rs:17:5
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.fixed b/src/tools/clippy/tests/ui/unused_format_specs.fixed
new file mode 100644
index 000000000..2930722b4
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_format_specs.fixed
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::unused_format_specs)]
+#![allow(unused)]
+
+fn main() {
+ let f = 1.0f64;
+ println!("{}", 1.0);
+ println!("{f} {f:?}");
+
+ println!("{}", 1);
+}
+
+fn should_not_lint() {
+ let f = 1.0f64;
+ println!("{:.1}", 1.0);
+ println!("{f:.w$} {f:.*?}", 3, w = 2);
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.rs b/src/tools/clippy/tests/ui/unused_format_specs.rs
new file mode 100644
index 000000000..ee192a000
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_format_specs.rs
@@ -0,0 +1,18 @@
+// run-rustfix
+
+#![warn(clippy::unused_format_specs)]
+#![allow(unused)]
+
+fn main() {
+ let f = 1.0f64;
+ println!("{:.}", 1.0);
+ println!("{f:.} {f:.?}");
+
+ println!("{:.}", 1);
+}
+
+fn should_not_lint() {
+ let f = 1.0f64;
+ println!("{:.1}", 1.0);
+ println!("{f:.w$} {f:.*?}", 3, w = 2);
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs.stderr b/src/tools/clippy/tests/ui/unused_format_specs.stderr
new file mode 100644
index 000000000..7231c17e7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_format_specs.stderr
@@ -0,0 +1,54 @@
+error: empty precision specifier has no effect
+ --> $DIR/unused_format_specs.rs:8:17
+ |
+LL | println!("{:.}", 1.0);
+ | ^
+ |
+ = note: a precision specifier is not required to format floats
+ = note: `-D clippy::unused-format-specs` implied by `-D warnings`
+help: remove the `.`
+ |
+LL - println!("{:.}", 1.0);
+LL + println!("{}", 1.0);
+ |
+
+error: empty precision specifier has no effect
+ --> $DIR/unused_format_specs.rs:9:18
+ |
+LL | println!("{f:.} {f:.?}");
+ | ^
+ |
+ = note: a precision specifier is not required to format floats
+help: remove the `.`
+ |
+LL - println!("{f:.} {f:.?}");
+LL + println!("{f} {f:.?}");
+ |
+
+error: empty precision specifier has no effect
+ --> $DIR/unused_format_specs.rs:9:24
+ |
+LL | println!("{f:.} {f:.?}");
+ | ^
+ |
+ = note: a precision specifier is not required to format floats
+help: remove the `.`
+ |
+LL - println!("{f:.} {f:.?}");
+LL + println!("{f:.} {f:?}");
+ |
+
+error: empty precision specifier has no effect
+ --> $DIR/unused_format_specs.rs:11:17
+ |
+LL | println!("{:.}", 1);
+ | ^
+ |
+help: remove the `.`
+ |
+LL - println!("{:.}", 1);
+LL + println!("{}", 1);
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_format_specs_unfixable.rs b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.rs
new file mode 100644
index 000000000..78601a348
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.rs
@@ -0,0 +1,30 @@
+#![warn(clippy::unused_format_specs)]
+#![allow(unused)]
+
+macro_rules! format_args_from_macro {
+ () => {
+ format_args!("from macro")
+ };
+}
+
+fn main() {
+ // prints `.`, not ` .`
+ println!("{:5}.", format_args!(""));
+ //prints `abcde`, not `abc`
+ println!("{:.3}", format_args!("abcde"));
+
+ println!("{:5}.", format_args_from_macro!());
+
+ let args = format_args!("");
+ println!("{args:5}");
+}
+
+fn should_not_lint() {
+ println!("{}", format_args!(""));
+ // Technically the same as `{}`, but the `format_args` docs specifically mention that you can use
+ // debug formatting so allow it
+ println!("{:?}", format_args!(""));
+
+ let args = format_args!("");
+ println!("{args}");
+}
diff --git a/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr
new file mode 100644
index 000000000..9f1890282
--- /dev/null
+++ b/src/tools/clippy/tests/ui/unused_format_specs_unfixable.stderr
@@ -0,0 +1,69 @@
+error: format specifiers have no effect on `format_args!()`
+ --> $DIR/unused_format_specs_unfixable.rs:12:15
+ |
+LL | println!("{:5}.", format_args!(""));
+ | ^^^^
+ |
+ = note: `-D clippy::unused-format-specs` implied by `-D warnings`
+help: for the width to apply consider using `format!()`
+ |
+LL | println!("{:5}.", format!(""));
+ | ~~~~~~
+help: if the current behavior is intentional, remove the format specifiers
+ |
+LL - println!("{:5}.", format_args!(""));
+LL + println!("{}.", format_args!(""));
+ |
+
+error: format specifiers have no effect on `format_args!()`
+ --> $DIR/unused_format_specs_unfixable.rs:14:15
+ |
+LL | println!("{:.3}", format_args!("abcde"));
+ | ^^^^^
+ |
+help: for the precision to apply consider using `format!()`
+ |
+LL | println!("{:.3}", format!("abcde"));
+ | ~~~~~~
+help: if the current behavior is intentional, remove the format specifiers
+ |
+LL - println!("{:.3}", format_args!("abcde"));
+LL + println!("{}", format_args!("abcde"));
+ |
+
+error: format specifiers have no effect on `format_args!()`
+ --> $DIR/unused_format_specs_unfixable.rs:16:15
+ |
+LL | println!("{:5}.", format_args_from_macro!());
+ | ^^^^
+ |
+help: for the width to apply consider using `format!()`
+ --> $DIR/unused_format_specs_unfixable.rs:16:17
+ |
+LL | println!("{:5}.", format_args_from_macro!());
+ | ^
+help: if the current behavior is intentional, remove the format specifiers
+ |
+LL - println!("{:5}.", format_args_from_macro!());
+LL + println!("{}.", format_args_from_macro!());
+ |
+
+error: format specifiers have no effect on `format_args!()`
+ --> $DIR/unused_format_specs_unfixable.rs:19:15
+ |
+LL | println!("{args:5}");
+ | ^^^^^^^^
+ |
+help: for the width to apply consider using `format!()`
+ --> $DIR/unused_format_specs_unfixable.rs:19:21
+ |
+LL | println!("{args:5}");
+ | ^
+help: if the current behavior is intentional, remove the format specifiers
+ |
+LL - println!("{args:5}");
+LL + println!("{args}");
+ |
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui/unused_io_amount.stderr b/src/tools/clippy/tests/ui/unused_io_amount.stderr
index e5bdd993a..7ba7e09c0 100644
--- a/src/tools/clippy/tests/ui/unused_io_amount.stderr
+++ b/src/tools/clippy/tests/ui/unused_io_amount.stderr
@@ -4,8 +4,8 @@ error: written amount is not handled
LL | s.write(b"test")?;
| ^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::unused-io-amount` implied by `-D warnings`
= help: use `Write::write_all` instead, or handle partial writes
+ = note: `-D clippy::unused-io-amount` implied by `-D warnings`
error: read amount is not handled
--> $DIR/unused_io_amount.rs:11:5
diff --git a/src/tools/clippy/tests/ui/unused_peekable.rs b/src/tools/clippy/tests/ui/unused_peekable.rs
index 153457e36..7374dfdf9 100644
--- a/src/tools/clippy/tests/ui/unused_peekable.rs
+++ b/src/tools/clippy/tests/ui/unused_peekable.rs
@@ -57,12 +57,22 @@ fn valid() {
impl PeekableConsumer {
fn consume(&self, _: Peekable<Empty<u32>>) {}
fn consume_mut_ref(&self, _: &mut Peekable<Empty<u32>>) {}
+ fn consume_assoc(_: Peekable<Empty<u32>>) {}
+ fn consume_assoc_mut_ref(_: &mut Peekable<Empty<u32>>) {}
}
-
let peekable_consumer = PeekableConsumer;
- let mut passed_along_to_method = std::iter::empty::<u32>().peekable();
- peekable_consumer.consume_mut_ref(&mut passed_along_to_method);
- peekable_consumer.consume(passed_along_to_method);
+
+ let peekable = std::iter::empty::<u32>().peekable();
+ peekable_consumer.consume(peekable);
+
+ let mut peekable = std::iter::empty::<u32>().peekable();
+ peekable_consumer.consume_mut_ref(&mut peekable);
+
+ let peekable = std::iter::empty::<u32>().peekable();
+ PeekableConsumer::consume_assoc(peekable);
+
+ let mut peekable = std::iter::empty::<u32>().peekable();
+ PeekableConsumer::consume_assoc_mut_ref(&mut peekable);
// `peek` called in another block
let mut peekable_in_block = std::iter::empty::<u32>().peekable();
@@ -141,4 +151,19 @@ fn valid() {
{
peekable_last_expr.peek();
}
+
+ let mut peek_in_closure = std::iter::empty::<u32>().peekable();
+ let _ = || {
+ let _ = peek_in_closure.peek();
+ };
+
+ trait PeekTrait {}
+ impl<I> PeekTrait for Peekable<I> where I: Iterator {}
+
+ let mut peekable = std::iter::empty::<u32>().peekable();
+ let _dyn = &mut peekable as &mut dyn PeekTrait;
+
+ fn takes_dyn(_: &mut dyn PeekTrait) {}
+ let mut peekable = std::iter::empty::<u32>().peekable();
+ takes_dyn(&mut peekable);
}
diff --git a/src/tools/clippy/tests/ui/unused_peekable.stderr b/src/tools/clippy/tests/ui/unused_peekable.stderr
index d557f5417..54788f2fa 100644
--- a/src/tools/clippy/tests/ui/unused_peekable.stderr
+++ b/src/tools/clippy/tests/ui/unused_peekable.stderr
@@ -4,8 +4,8 @@ error: `peek` never called on `Peekable` iterator
LL | let peekable = std::iter::empty::<u32>().peekable();
| ^^^^^^^^
|
- = note: `-D clippy::unused-peekable` implied by `-D warnings`
= help: consider removing the call to `peekable`
+ = note: `-D clippy::unused-peekable` implied by `-D warnings`
error: `peek` never called on `Peekable` iterator
--> $DIR/unused_peekable.rs:18:9
diff --git a/src/tools/clippy/tests/ui/unused_self.stderr b/src/tools/clippy/tests/ui/unused_self.stderr
index 0534b40ea..23186122a 100644
--- a/src/tools/clippy/tests/ui/unused_self.stderr
+++ b/src/tools/clippy/tests/ui/unused_self.stderr
@@ -4,8 +4,8 @@ error: unused `self` argument
LL | fn unused_self_move(self) {}
| ^^^^
|
- = note: `-D clippy::unused-self` implied by `-D warnings`
= help: consider refactoring to a associated function
+ = note: `-D clippy::unused-self` implied by `-D warnings`
error: unused `self` argument
--> $DIR/unused_self.rs:12:28
diff --git a/src/tools/clippy/tests/ui/unwrap.stderr b/src/tools/clippy/tests/ui/unwrap.stderr
index 784227578..e88d580f7 100644
--- a/src/tools/clippy/tests/ui/unwrap.stderr
+++ b/src/tools/clippy/tests/ui/unwrap.stderr
@@ -4,8 +4,8 @@ error: used `unwrap()` on `an Option` value
LL | let _ = opt.unwrap();
| ^^^^^^^^^^^^
|
- = note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: if you don't want to handle the `None` case gracefully, consider using `expect()` to provide a better panic message
+ = note: `-D clippy::unwrap-used` implied by `-D warnings`
error: used `unwrap()` on `a Result` value
--> $DIR/unwrap.rs:10:13
diff --git a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
index 1a19459b2..211d2be18 100644
--- a/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_expect_used.stderr
@@ -4,8 +4,8 @@ error: used `unwrap()` on `an Option` value
LL | Some(3).unwrap();
| ^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::unwrap-used` implied by `-D warnings`
= help: if this value is `None`, it will panic
+ = note: `-D clippy::unwrap-used` implied by `-D warnings`
error: used `expect()` on `an Option` value
--> $DIR/unwrap_expect_used.rs:24:5
@@ -13,8 +13,8 @@ error: used `expect()` on `an Option` value
LL | Some(3).expect("Hello world!");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::expect-used` implied by `-D warnings`
= help: if this value is `None`, it will panic
+ = note: `-D clippy::expect-used` implied by `-D warnings`
error: used `unwrap()` on `a Result` value
--> $DIR/unwrap_expect_used.rs:31:5
diff --git a/src/tools/clippy/tests/ui/unwrap_in_result.stderr b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
index 56bc2f2d1..40e6bfe08 100644
--- a/src/tools/clippy/tests/ui/unwrap_in_result.stderr
+++ b/src/tools/clippy/tests/ui/unwrap_in_result.stderr
@@ -10,13 +10,13 @@ LL | | }
LL | | }
| |_____^
|
- = note: `-D clippy::unwrap-in-result` implied by `-D warnings`
= help: unwrap and expect should not be used in a function that returns result or option
note: potential non-recoverable error(s)
--> $DIR/unwrap_in_result.rs:24:17
|
LL | let i = i_str.parse::<i32>().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: `-D clippy::unwrap-in-result` implied by `-D warnings`
error: used unwrap or expect in a function that returns result or option
--> $DIR/unwrap_in_result.rs:32:5
diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.rs b/src/tools/clippy/tests/ui/upper_case_acronyms.rs
index 48bb9e54b..9b7c2f28e 100644
--- a/src/tools/clippy/tests/ui/upper_case_acronyms.rs
+++ b/src/tools/clippy/tests/ui/upper_case_acronyms.rs
@@ -38,4 +38,13 @@ enum ParseErrorPrivate<T> {
Parse(T, String),
}
+// do lint here
+struct JSON;
+
+// do lint here
+enum YAML {
+ Num(u32),
+ Str(String),
+}
+
fn main() {}
diff --git a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr
index 250b196a9..74082ec16 100644
--- a/src/tools/clippy/tests/ui/upper_case_acronyms.stderr
+++ b/src/tools/clippy/tests/ui/upper_case_acronyms.stderr
@@ -54,5 +54,17 @@ error: name `WASD` contains a capitalized acronym
LL | WASD(u8),
| ^^^^ help: consider making the acronym lowercase, except the initial letter: `Wasd`
-error: aborting due to 9 previous errors
+error: name `JSON` contains a capitalized acronym
+ --> $DIR/upper_case_acronyms.rs:42:8
+ |
+LL | struct JSON;
+ | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Json`
+
+error: name `YAML` contains a capitalized acronym
+ --> $DIR/upper_case_acronyms.rs:45:6
+ |
+LL | enum YAML {
+ | ^^^^ help: consider making the acronym lowercase, except the initial letter: `Yaml`
+
+error: aborting due to 11 previous errors
diff --git a/src/tools/clippy/tests/ui/use_self.fixed b/src/tools/clippy/tests/ui/use_self.fixed
index 4f80aaecc..3b54fe9d5 100644
--- a/src/tools/clippy/tests/ui/use_self.fixed
+++ b/src/tools/clippy/tests/ui/use_self.fixed
@@ -1,6 +1,7 @@
// run-rustfix
// aux-build:proc_macro_derive.rs
+#![feature(custom_inner_attributes)]
#![warn(clippy::use_self)]
#![allow(dead_code, unreachable_code)]
#![allow(
@@ -608,3 +609,44 @@ mod issue8845 {
}
}
}
+
+mod issue6902 {
+ use serde::Serialize;
+
+ #[derive(Serialize)]
+ pub enum Foo {
+ Bar = 1,
+ }
+}
+
+fn msrv_1_36() {
+ #![clippy::msrv = "1.36"]
+
+ enum E {
+ A,
+ }
+
+ impl E {
+ fn foo(self) {
+ match self {
+ E::A => {},
+ }
+ }
+ }
+}
+
+fn msrv_1_37() {
+ #![clippy::msrv = "1.37"]
+
+ enum E {
+ A,
+ }
+
+ impl E {
+ fn foo(self) {
+ match self {
+ Self::A => {},
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/use_self.rs b/src/tools/clippy/tests/ui/use_self.rs
index 52da72db5..bf87633cd 100644
--- a/src/tools/clippy/tests/ui/use_self.rs
+++ b/src/tools/clippy/tests/ui/use_self.rs
@@ -1,6 +1,7 @@
// run-rustfix
// aux-build:proc_macro_derive.rs
+#![feature(custom_inner_attributes)]
#![warn(clippy::use_self)]
#![allow(dead_code, unreachable_code)]
#![allow(
@@ -608,3 +609,44 @@ mod issue8845 {
}
}
}
+
+mod issue6902 {
+ use serde::Serialize;
+
+ #[derive(Serialize)]
+ pub enum Foo {
+ Bar = 1,
+ }
+}
+
+fn msrv_1_36() {
+ #![clippy::msrv = "1.36"]
+
+ enum E {
+ A,
+ }
+
+ impl E {
+ fn foo(self) {
+ match self {
+ E::A => {},
+ }
+ }
+ }
+}
+
+fn msrv_1_37() {
+ #![clippy::msrv = "1.37"]
+
+ enum E {
+ A,
+ }
+
+ impl E {
+ fn foo(self) {
+ match self {
+ E::A => {},
+ }
+ }
+ }
+}
diff --git a/src/tools/clippy/tests/ui/use_self.stderr b/src/tools/clippy/tests/ui/use_self.stderr
index f06bb959b..16fb06092 100644
--- a/src/tools/clippy/tests/ui/use_self.stderr
+++ b/src/tools/clippy/tests/ui/use_self.stderr
@@ -1,5 +1,5 @@
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:22:21
+ --> $DIR/use_self.rs:23:21
|
LL | fn new() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
@@ -7,244 +7,250 @@ LL | fn new() -> Foo {
= note: `-D clippy::use-self` implied by `-D warnings`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:23:13
+ --> $DIR/use_self.rs:24:13
|
LL | Foo {}
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:25:22
+ --> $DIR/use_self.rs:26:22
|
LL | fn test() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:26:13
+ --> $DIR/use_self.rs:27:13
|
LL | Foo::new()
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:31:25
+ --> $DIR/use_self.rs:32:25
|
LL | fn default() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:32:13
+ --> $DIR/use_self.rs:33:13
|
LL | Foo::new()
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:97:24
+ --> $DIR/use_self.rs:98:24
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:97:55
+ --> $DIR/use_self.rs:98:55
|
LL | fn bad(foos: &[Foo]) -> impl Iterator<Item = &Foo> {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:112:13
+ --> $DIR/use_self.rs:113:13
|
LL | TS(0)
| ^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:147:29
+ --> $DIR/use_self.rs:148:29
|
LL | fn bar() -> Bar {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:148:21
+ --> $DIR/use_self.rs:149:21
|
LL | Bar { foo: Foo {} }
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:159:21
+ --> $DIR/use_self.rs:160:21
|
LL | fn baz() -> Foo {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:160:13
+ --> $DIR/use_self.rs:161:13
|
LL | Foo {}
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:177:21
+ --> $DIR/use_self.rs:178:21
|
LL | let _ = Enum::B(42);
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:178:21
+ --> $DIR/use_self.rs:179:21
|
LL | let _ = Enum::C { field: true };
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:179:21
+ --> $DIR/use_self.rs:180:21
|
LL | let _ = Enum::A;
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:221:13
+ --> $DIR/use_self.rs:222:13
|
LL | nested::A::fun_1();
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:222:13
+ --> $DIR/use_self.rs:223:13
|
LL | nested::A::A;
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:224:13
+ --> $DIR/use_self.rs:225:13
|
LL | nested::A {};
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:243:13
+ --> $DIR/use_self.rs:244:13
|
LL | TestStruct::from_something()
| ^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:257:25
+ --> $DIR/use_self.rs:258:25
|
LL | async fn g() -> S {
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:258:13
+ --> $DIR/use_self.rs:259:13
|
LL | S {}
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:262:16
+ --> $DIR/use_self.rs:263:16
|
LL | &p[S::A..S::B]
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:262:22
+ --> $DIR/use_self.rs:263:22
|
LL | &p[S::A..S::B]
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:285:29
+ --> $DIR/use_self.rs:286:29
|
LL | fn foo(value: T) -> Foo<T> {
| ^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:286:13
+ --> $DIR/use_self.rs:287:13
|
LL | Foo::<T> { value }
| ^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:458:13
+ --> $DIR/use_self.rs:459:13
|
LL | A::new::<submod::B>(submod::B {})
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:495:13
+ --> $DIR/use_self.rs:496:13
|
LL | S2::new()
| ^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:532:17
+ --> $DIR/use_self.rs:533:17
|
LL | Foo::Bar => unimplemented!(),
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:533:17
+ --> $DIR/use_self.rs:534:17
|
LL | Foo::Baz => unimplemented!(),
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:539:20
+ --> $DIR/use_self.rs:540:20
|
LL | if let Foo::Bar = self {
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:563:17
+ --> $DIR/use_self.rs:564:17
|
LL | Something::Num(n) => *n,
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:564:17
+ --> $DIR/use_self.rs:565:17
|
LL | Something::TupleNums(n, _m) => *n,
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:565:17
+ --> $DIR/use_self.rs:566:17
|
LL | Something::StructNums { one, two: _ } => *one,
| ^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:571:17
+ --> $DIR/use_self.rs:572:17
|
LL | crate::issue8845::Something::Num(n) => *n,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:572:17
+ --> $DIR/use_self.rs:573:17
|
LL | crate::issue8845::Something::TupleNums(n, _m) => *n,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:573:17
+ --> $DIR/use_self.rs:574:17
|
LL | crate::issue8845::Something::StructNums { one, two: _ } => *one,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:589:17
+ --> $DIR/use_self.rs:590:17
|
LL | let Foo(x) = self;
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:594:17
+ --> $DIR/use_self.rs:595:17
|
LL | let crate::issue8845::Foo(x) = self;
| ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:601:17
+ --> $DIR/use_self.rs:602:17
|
LL | let Bar { x, .. } = self;
| ^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
- --> $DIR/use_self.rs:606:17
+ --> $DIR/use_self.rs:607:17
|
LL | let crate::issue8845::Bar { x, .. } = self;
| ^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
-error: aborting due to 41 previous errors
+error: unnecessary structure name repetition
+ --> $DIR/use_self.rs:648:17
+ |
+LL | E::A => {},
+ | ^ help: use the applicable keyword: `Self`
+
+error: aborting due to 42 previous errors
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.rs b/src/tools/clippy/tests/ui/used_underscore_binding.rs
index 322083511..8c29e15b1 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.rs
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.rs
@@ -1,9 +1,8 @@
// aux-build:proc_macro_derive.rs
-
#![feature(rustc_private)]
#![warn(clippy::all)]
-#![allow(clippy::disallowed_names, clippy::eq_op)]
#![warn(clippy::used_underscore_binding)]
+#![allow(clippy::disallowed_names, clippy::eq_op, clippy::uninlined_format_args)]
#[macro_use]
extern crate proc_macro_derive;
diff --git a/src/tools/clippy/tests/ui/used_underscore_binding.stderr b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
index 61a9161d2..875fafe43 100644
--- a/src/tools/clippy/tests/ui/used_underscore_binding.stderr
+++ b/src/tools/clippy/tests/ui/used_underscore_binding.stderr
@@ -1,5 +1,5 @@
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:25:5
+ --> $DIR/used_underscore_binding.rs:24:5
|
LL | _foo + 1
| ^^^^
@@ -7,31 +7,31 @@ LL | _foo + 1
= note: `-D clippy::used-underscore-binding` implied by `-D warnings`
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:30:20
+ --> $DIR/used_underscore_binding.rs:29:20
|
LL | println!("{}", _foo);
| ^^^^
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:31:16
+ --> $DIR/used_underscore_binding.rs:30:16
|
LL | assert_eq!(_foo, _foo);
| ^^^^
error: used binding `_foo` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:31:22
+ --> $DIR/used_underscore_binding.rs:30:22
|
LL | assert_eq!(_foo, _foo);
| ^^^^
error: used binding `_underscore_field` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:44:5
+ --> $DIR/used_underscore_binding.rs:43:5
|
LL | s._underscore_field += 1;
| ^^^^^^^^^^^^^^^^^^^
error: used binding `_i` which is prefixed with an underscore. A leading underscore signals that a binding will not be used
- --> $DIR/used_underscore_binding.rs:105:16
+ --> $DIR/used_underscore_binding.rs:104:16
|
LL | uses_i(_i);
| ^^
diff --git a/src/tools/clippy/tests/ui/useless_asref.fixed b/src/tools/clippy/tests/ui/useless_asref.fixed
index 90cb8945e..38e4b9201 100644
--- a/src/tools/clippy/tests/ui/useless_asref.fixed
+++ b/src/tools/clippy/tests/ui/useless_asref.fixed
@@ -1,7 +1,6 @@
// run-rustfix
-
#![deny(clippy::useless_asref)]
-#![allow(clippy::explicit_auto_deref)]
+#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)]
use std::fmt::Debug;
diff --git a/src/tools/clippy/tests/ui/useless_asref.rs b/src/tools/clippy/tests/ui/useless_asref.rs
index cb9f8ae59..f1e83f9d3 100644
--- a/src/tools/clippy/tests/ui/useless_asref.rs
+++ b/src/tools/clippy/tests/ui/useless_asref.rs
@@ -1,7 +1,6 @@
// run-rustfix
-
#![deny(clippy::useless_asref)]
-#![allow(clippy::explicit_auto_deref)]
+#![allow(clippy::explicit_auto_deref, clippy::uninlined_format_args)]
use std::fmt::Debug;
diff --git a/src/tools/clippy/tests/ui/useless_asref.stderr b/src/tools/clippy/tests/ui/useless_asref.stderr
index b21c67bb3..67ce8b64e 100644
--- a/src/tools/clippy/tests/ui/useless_asref.stderr
+++ b/src/tools/clippy/tests/ui/useless_asref.stderr
@@ -1,71 +1,71 @@
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:44:18
+ --> $DIR/useless_asref.rs:43:18
|
LL | foo_rstr(rstr.as_ref());
| ^^^^^^^^^^^^^ help: try this: `rstr`
|
note: the lint level is defined here
- --> $DIR/useless_asref.rs:3:9
+ --> $DIR/useless_asref.rs:2:9
|
LL | #![deny(clippy::useless_asref)]
| ^^^^^^^^^^^^^^^^^^^^^
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:46:20
+ --> $DIR/useless_asref.rs:45:20
|
LL | foo_rslice(rslice.as_ref());
| ^^^^^^^^^^^^^^^ help: try this: `rslice`
error: this call to `as_mut` does nothing
- --> $DIR/useless_asref.rs:50:21
+ --> $DIR/useless_asref.rs:49:21
|
LL | foo_mrslice(mrslice.as_mut());
| ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:52:20
+ --> $DIR/useless_asref.rs:51:20
|
LL | foo_rslice(mrslice.as_ref());
| ^^^^^^^^^^^^^^^^ help: try this: `mrslice`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:59:20
+ --> $DIR/useless_asref.rs:58:20
|
LL | foo_rslice(rrrrrslice.as_ref());
| ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:61:18
+ --> $DIR/useless_asref.rs:60:18
|
LL | foo_rstr(rrrrrstr.as_ref());
| ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr`
error: this call to `as_mut` does nothing
- --> $DIR/useless_asref.rs:66:21
+ --> $DIR/useless_asref.rs:65:21
|
LL | foo_mrslice(mrrrrrslice.as_mut());
| ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:68:20
+ --> $DIR/useless_asref.rs:67:20
|
LL | foo_rslice(mrrrrrslice.as_ref());
| ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:72:16
+ --> $DIR/useless_asref.rs:71:16
|
LL | foo_rrrrmr((&&&&MoreRef).as_ref());
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)`
error: this call to `as_mut` does nothing
- --> $DIR/useless_asref.rs:122:13
+ --> $DIR/useless_asref.rs:121:13
|
LL | foo_mrt(mrt.as_mut());
| ^^^^^^^^^^^^ help: try this: `mrt`
error: this call to `as_ref` does nothing
- --> $DIR/useless_asref.rs:124:12
+ --> $DIR/useless_asref.rs:123:12
|
LL | foo_rt(mrt.as_ref());
| ^^^^^^^^^^^^ help: try this: `mrt`
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index e6760f700..65ee3807f 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -46,7 +46,7 @@ error: useless conversion to the same type: `std::string::String`
LL | let _ = String::from(format!("A: {:04}", 123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
-error: useless conversion to the same type: `std::str::Lines`
+error: useless conversion to the same type: `std::str::Lines<'_>`
--> $DIR/useless_conversion.rs:65:13
|
LL | let _ = "".lines().into_iter();
diff --git a/src/tools/clippy/tests/ui/useless_conversion_try.stderr b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
index 12e74d614..9aef9dda6 100644
--- a/src/tools/clippy/tests/ui/useless_conversion_try.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion_try.stderr
@@ -4,12 +4,12 @@ error: useless conversion to the same type: `T`
LL | let _ = T::try_from(val).unwrap();
| ^^^^^^^^^^^^^^^^
|
+ = help: consider removing `T::try_from()`
note: the lint level is defined here
--> $DIR/useless_conversion_try.rs:1:9
|
LL | #![deny(clippy::useless_conversion)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
- = help: consider removing `T::try_from()`
error: useless conversion to the same type: `T`
--> $DIR/useless_conversion_try.rs:5:5
diff --git a/src/tools/clippy/tests/ui/vec.fixed b/src/tools/clippy/tests/ui/vec.fixed
index 318f9c2dc..2518d8049 100644
--- a/src/tools/clippy/tests/ui/vec.fixed
+++ b/src/tools/clippy/tests/ui/vec.fixed
@@ -1,6 +1,6 @@
// run-rustfix
-#![allow(clippy::nonstandard_macro_braces)]
#![warn(clippy::useless_vec)]
+#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
#[derive(Debug)]
struct NonCopy;
diff --git a/src/tools/clippy/tests/ui/vec.rs b/src/tools/clippy/tests/ui/vec.rs
index d7673ce3e..e1492e2f3 100644
--- a/src/tools/clippy/tests/ui/vec.rs
+++ b/src/tools/clippy/tests/ui/vec.rs
@@ -1,6 +1,6 @@
// run-rustfix
-#![allow(clippy::nonstandard_macro_braces)]
#![warn(clippy::useless_vec)]
+#![allow(clippy::nonstandard_macro_braces, clippy::uninlined_format_args)]
#[derive(Debug)]
struct NonCopy;
diff --git a/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr b/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr
index 7428cf62d..8851e9f38 100644
--- a/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr
+++ b/src/tools/clippy/tests/ui/vec_resize_to_zero.stderr
@@ -6,8 +6,8 @@ LL | v.resize(0, 5);
| |
| help: ...or you can empty the vector with: `clear()`
|
- = note: `-D clippy::vec-resize-to-zero` implied by `-D warnings`
= help: the arguments may be inverted...
+ = note: `-D clippy::vec-resize-to-zero` implied by `-D warnings`
error: aborting due to previous error
diff --git a/src/tools/clippy/tests/ui/verbose_file_reads.stderr b/src/tools/clippy/tests/ui/verbose_file_reads.stderr
index 550b6ab67..44266c7c0 100644
--- a/src/tools/clippy/tests/ui/verbose_file_reads.stderr
+++ b/src/tools/clippy/tests/ui/verbose_file_reads.stderr
@@ -4,8 +4,8 @@ error: use of `File::read_to_end`
LL | f.read_to_end(&mut buffer)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::verbose-file-reads` implied by `-D warnings`
= help: consider using `fs::read` instead
+ = note: `-D clippy::verbose-file-reads` implied by `-D warnings`
error: use of `File::read_to_string`
--> $DIR/verbose_file_reads.rs:26:5
diff --git a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr b/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
index 2f1be61e5..14748f583 100644
--- a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
+++ b/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
@@ -4,8 +4,8 @@ error: comparing trait object pointers compares a non-unique vtable address
LL | let _ = a == b;
| ^^^^^^
|
- = note: `-D clippy::vtable-address-comparisons` implied by `-D warnings`
= help: consider extracting and comparing data pointers only
+ = note: `-D clippy::vtable-address-comparisons` implied by `-D warnings`
error: comparing trait object pointers compares a non-unique vtable address
--> $DIR/vtable_address_comparisons.rs:15:13
diff --git a/src/tools/clippy/tests/ui/while_let_loop.rs b/src/tools/clippy/tests/ui/while_let_loop.rs
index c42e2a79a..5b8075731 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.rs
+++ b/src/tools/clippy/tests/ui/while_let_loop.rs
@@ -1,4 +1,5 @@
#![warn(clippy::while_let_loop)]
+#![allow(clippy::uninlined_format_args)]
fn main() {
let y = Some(true);
diff --git a/src/tools/clippy/tests/ui/while_let_loop.stderr b/src/tools/clippy/tests/ui/while_let_loop.stderr
index 13dd0ee22..04808c0b3 100644
--- a/src/tools/clippy/tests/ui/while_let_loop.stderr
+++ b/src/tools/clippy/tests/ui/while_let_loop.stderr
@@ -1,5 +1,5 @@
error: this loop could be written as a `while let` loop
- --> $DIR/while_let_loop.rs:5:5
+ --> $DIR/while_let_loop.rs:6:5
|
LL | / loop {
LL | | if let Some(_x) = y {
@@ -13,7 +13,7 @@ LL | | }
= note: `-D clippy::while-let-loop` implied by `-D warnings`
error: this loop could be written as a `while let` loop
- --> $DIR/while_let_loop.rs:22:5
+ --> $DIR/while_let_loop.rs:23:5
|
LL | / loop {
LL | | match y {
@@ -24,7 +24,7 @@ LL | | }
| |_____^ help: try: `while let Some(_x) = y { .. }`
error: this loop could be written as a `while let` loop
- --> $DIR/while_let_loop.rs:29:5
+ --> $DIR/while_let_loop.rs:30:5
|
LL | / loop {
LL | | let x = match y {
@@ -36,7 +36,7 @@ LL | | }
| |_____^ help: try: `while let Some(x) = y { .. }`
error: this loop could be written as a `while let` loop
- --> $DIR/while_let_loop.rs:38:5
+ --> $DIR/while_let_loop.rs:39:5
|
LL | / loop {
LL | | let x = match y {
@@ -48,7 +48,7 @@ LL | | }
| |_____^ help: try: `while let Some(x) = y { .. }`
error: this loop could be written as a `while let` loop
- --> $DIR/while_let_loop.rs:68:5
+ --> $DIR/while_let_loop.rs:69:5
|
LL | / loop {
LL | | let (e, l) = match "".split_whitespace().next() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
index c57c46736..5afa0a89f 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.fixed
@@ -1,14 +1,12 @@
// run-rustfix
-
#![warn(clippy::while_let_on_iterator)]
+#![allow(dead_code, unreachable_code, unused_mut)]
#![allow(
- clippy::never_loop,
- unreachable_code,
- unused_mut,
- dead_code,
clippy::equatable_if_let,
clippy::manual_find,
- clippy::redundant_closure_call
+ clippy::never_loop,
+ clippy::redundant_closure_call,
+ clippy::uninlined_format_args
)]
fn base() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.rs b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
index 8b9a2dbcc..3de586c9d 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.rs
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.rs
@@ -1,14 +1,12 @@
// run-rustfix
-
#![warn(clippy::while_let_on_iterator)]
+#![allow(dead_code, unreachable_code, unused_mut)]
#![allow(
- clippy::never_loop,
- unreachable_code,
- unused_mut,
- dead_code,
clippy::equatable_if_let,
clippy::manual_find,
- clippy::redundant_closure_call
+ clippy::never_loop,
+ clippy::redundant_closure_call,
+ clippy::uninlined_format_args
)]
fn base() {
diff --git a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
index 3236765e1..4d9866619 100644
--- a/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
+++ b/src/tools/clippy/tests/ui/while_let_on_iterator.stderr
@@ -1,5 +1,5 @@
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:16:5
+ --> $DIR/while_let_on_iterator.rs:14:5
|
LL | while let Option::Some(x) = iter.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
@@ -7,151 +7,151 @@ LL | while let Option::Some(x) = iter.next() {
= note: `-D clippy::while-let-on-iterator` implied by `-D warnings`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:21:5
+ --> $DIR/while_let_on_iterator.rs:19:5
|
LL | while let Some(x) = iter.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:26:5
+ --> $DIR/while_let_on_iterator.rs:24:5
|
LL | while let Some(_) = iter.next() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:102:9
+ --> $DIR/while_let_on_iterator.rs:100:9
|
LL | while let Some([..]) = it.next() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:109:9
+ --> $DIR/while_let_on_iterator.rs:107:9
|
LL | while let Some([_x]) = it.next() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:122:9
+ --> $DIR/while_let_on_iterator.rs:120:9
|
LL | while let Some(x @ [_]) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:142:9
+ --> $DIR/while_let_on_iterator.rs:140:9
|
LL | while let Some(_) = y.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:199:9
+ --> $DIR/while_let_on_iterator.rs:197:9
|
LL | while let Some(m) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:210:5
+ --> $DIR/while_let_on_iterator.rs:208:5
|
LL | while let Some(n) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:212:9
+ --> $DIR/while_let_on_iterator.rs:210:9
|
LL | while let Some(m) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:221:9
+ --> $DIR/while_let_on_iterator.rs:219:9
|
LL | while let Some(m) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:230:9
+ --> $DIR/while_let_on_iterator.rs:228:9
|
LL | while let Some(m) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:247:9
+ --> $DIR/while_let_on_iterator.rs:245:9
|
LL | while let Some(m) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for m in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:262:13
+ --> $DIR/while_let_on_iterator.rs:260:13
|
LL | while let Some(i) = self.0.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:294:13
+ --> $DIR/while_let_on_iterator.rs:292:13
|
LL | while let Some(i) = self.0.0.0.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for i in self.0.0.0.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:323:5
+ --> $DIR/while_let_on_iterator.rs:321:5
|
LL | while let Some(n) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for n in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:335:9
+ --> $DIR/while_let_on_iterator.rs:333:9
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:349:5
+ --> $DIR/while_let_on_iterator.rs:347:5
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:360:5
+ --> $DIR/while_let_on_iterator.rs:358:5
|
LL | while let Some(x) = it.0.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.0.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:395:5
+ --> $DIR/while_let_on_iterator.rs:393:5
|
LL | while let Some(x) = s.x.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in s.x.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:402:5
+ --> $DIR/while_let_on_iterator.rs:400:5
|
LL | while let Some(x) = x[0].next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in x[0].by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:410:9
+ --> $DIR/while_let_on_iterator.rs:408:9
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:420:9
+ --> $DIR/while_let_on_iterator.rs:418:9
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:430:9
+ --> $DIR/while_let_on_iterator.rs:428:9
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it.by_ref()`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:440:9
+ --> $DIR/while_let_on_iterator.rs:438:9
|
LL | while let Some(x) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in it`
error: this loop could be written as a `for` loop
- --> $DIR/while_let_on_iterator.rs:450:5
+ --> $DIR/while_let_on_iterator.rs:448:5
|
LL | while let Some(..) = it.next() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in it`
diff --git a/src/tools/clippy/tests/ui/wild_in_or_pats.stderr b/src/tools/clippy/tests/ui/wild_in_or_pats.stderr
index 45b87aa0f..bd5860f45 100644
--- a/src/tools/clippy/tests/ui/wild_in_or_pats.stderr
+++ b/src/tools/clippy/tests/ui/wild_in_or_pats.stderr
@@ -4,8 +4,8 @@ error: wildcard pattern covers any other pattern as it will match anyway
LL | "bar" | _ => {
| ^^^^^^^^^
|
- = note: `-D clippy::wildcard-in-or-patterns` implied by `-D warnings`
= help: consider handling `_` separately
+ = note: `-D clippy::wildcard-in-or-patterns` implied by `-D warnings`
error: wildcard pattern covers any other pattern as it will match anyway
--> $DIR/wild_in_or_pats.rs:16:9
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 3ee4ab48a..236074978 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
@@ -1,15 +1,13 @@
// run-rustfix
// aux-build:non-exhaustive-enum.rs
-
#![deny(clippy::wildcard_enum_match_arm)]
+#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(
- unreachable_code,
- unused_variables,
- dead_code,
+ clippy::diverging_sub_expression,
clippy::single_match,
- clippy::wildcard_in_or_patterns,
+ clippy::uninlined_format_args,
clippy::unnested_or_patterns,
- clippy::diverging_sub_expression
+ clippy::wildcard_in_or_patterns
)]
extern crate non_exhaustive_enum;
diff --git a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
index 468865504..decd86165 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
@@ -1,15 +1,13 @@
// run-rustfix
// aux-build:non-exhaustive-enum.rs
-
#![deny(clippy::wildcard_enum_match_arm)]
+#![allow(dead_code, unreachable_code, unused_variables)]
#![allow(
- unreachable_code,
- unused_variables,
- dead_code,
+ clippy::diverging_sub_expression,
clippy::single_match,
- clippy::wildcard_in_or_patterns,
+ clippy::uninlined_format_args,
clippy::unnested_or_patterns,
- clippy::diverging_sub_expression
+ clippy::wildcard_in_or_patterns
)]
extern crate non_exhaustive_enum;
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 d63f20903..efecc9576 100644
--- a/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
+++ b/src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
@@ -1,41 +1,41 @@
error: wildcard match will also match any future added variants
- --> $DIR/wildcard_enum_match_arm.rs:42:9
+ --> $DIR/wildcard_enum_match_arm.rs:40:9
|
LL | _ => eprintln!("Not red"),
| ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
|
note: the lint level is defined here
- --> $DIR/wildcard_enum_match_arm.rs:4:9
+ --> $DIR/wildcard_enum_match_arm.rs:3:9
|
LL | #![deny(clippy::wildcard_enum_match_arm)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: wildcard match will also match any future added variants
- --> $DIR/wildcard_enum_match_arm.rs:46:9
+ --> $DIR/wildcard_enum_match_arm.rs:44:9
|
LL | _not_red => eprintln!("Not red"),
| ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
error: wildcard match will also match any future added variants
- --> $DIR/wildcard_enum_match_arm.rs:50:9
+ --> $DIR/wildcard_enum_match_arm.rs:48:9
|
LL | not_red => format!("{:?}", not_red),
| ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
error: wildcard match will also match any future added variants
- --> $DIR/wildcard_enum_match_arm.rs:66:9
+ --> $DIR/wildcard_enum_match_arm.rs:64:9
|
LL | _ => "No red",
| ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
error: wildcard matches known variants and will also match future added variants
- --> $DIR/wildcard_enum_match_arm.rs:83:9
+ --> $DIR/wildcard_enum_match_arm.rs:81:9
|
LL | _ => {},
| ^ help: try this: `ErrorKind::PermissionDenied | _`
error: wildcard matches known variants and will also match future added variants
- --> $DIR/wildcard_enum_match_arm.rs:101:13
+ --> $DIR/wildcard_enum_match_arm.rs:99:13
|
LL | _ => (),
| ^ help: try this: `Enum::B | _`
diff --git a/src/tools/clippy/tests/ui/write_literal.rs b/src/tools/clippy/tests/ui/write_literal.rs
index 446691744..218385ea1 100644
--- a/src/tools/clippy/tests/ui/write_literal.rs
+++ b/src/tools/clippy/tests/ui/write_literal.rs
@@ -1,5 +1,5 @@
-#![allow(unused_must_use)]
#![warn(clippy::write_literal)]
+#![allow(clippy::uninlined_format_args, unused_must_use)]
use std::io::Write;
@@ -25,11 +25,13 @@ fn main() {
writeln!(v, "{} of {:b} people know binary, the other half doesn't", 1, 2);
writeln!(v, "10 / 4 is {}", 2.5);
writeln!(v, "2 + 1 = {}", 3);
+ writeln!(v, "From expansion {}", stringify!(not a string literal));
// these should throw warnings
write!(v, "Hello {}", "world");
writeln!(v, "Hello {} {}", world, "world");
writeln!(v, "Hello {}", "world");
+ writeln!(v, "{} {:.4}", "a literal", 5);
// positional args don't change the fact
// that we're using a literal -- this should
diff --git a/src/tools/clippy/tests/ui/write_literal.stderr b/src/tools/clippy/tests/ui/write_literal.stderr
index 3c5ec91d3..1e306ae28 100644
--- a/src/tools/clippy/tests/ui/write_literal.stderr
+++ b/src/tools/clippy/tests/ui/write_literal.stderr
@@ -1,5 +1,5 @@
error: literal with an empty format string
- --> $DIR/write_literal.rs:30:27
+ --> $DIR/write_literal.rs:31:27
|
LL | write!(v, "Hello {}", "world");
| ^^^^^^^
@@ -12,7 +12,7 @@ LL + write!(v, "Hello world");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:31:39
+ --> $DIR/write_literal.rs:32:39
|
LL | writeln!(v, "Hello {} {}", world, "world");
| ^^^^^^^
@@ -24,7 +24,7 @@ LL + writeln!(v, "Hello {} world", world);
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:32:29
+ --> $DIR/write_literal.rs:33:29
|
LL | writeln!(v, "Hello {}", "world");
| ^^^^^^^
@@ -36,7 +36,19 @@ LL + writeln!(v, "Hello world");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:37:28
+ --> $DIR/write_literal.rs:34:29
+ |
+LL | writeln!(v, "{} {:.4}", "a literal", 5);
+ | ^^^^^^^^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, "{} {:.4}", "a literal", 5);
+LL + writeln!(v, "a literal {:.4}", 5);
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal.rs:39:28
|
LL | writeln!(v, "{0} {1}", "hello", "world");
| ^^^^^^^
@@ -48,7 +60,7 @@ LL + writeln!(v, "hello {1}", "world");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:37:37
+ --> $DIR/write_literal.rs:39:37
|
LL | writeln!(v, "{0} {1}", "hello", "world");
| ^^^^^^^
@@ -60,34 +72,34 @@ LL + writeln!(v, "{0} world", "hello");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:38:28
+ --> $DIR/write_literal.rs:40:37
|
LL | writeln!(v, "{1} {0}", "hello", "world");
- | ^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - writeln!(v, "{1} {0}", "hello", "world");
-LL + writeln!(v, "{1} hello", "world");
+LL + writeln!(v, "world {0}", "hello");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:38:37
+ --> $DIR/write_literal.rs:40:28
|
LL | writeln!(v, "{1} {0}", "hello", "world");
- | ^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - writeln!(v, "{1} {0}", "hello", "world");
-LL + writeln!(v, "world {0}", "hello");
+LL + writeln!(v, "{1} hello", "world");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:41:32
+ --> $DIR/write_literal.rs:43:38
|
LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
@@ -96,10 +108,10 @@ LL + writeln!(v, "hello {bar}", bar = "world");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:41:47
+ --> $DIR/write_literal.rs:43:53
|
LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
@@ -108,28 +120,28 @@ LL + writeln!(v, "{foo} world", foo = "hello");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:42:32
+ --> $DIR/write_literal.rs:44:53
|
LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-LL + writeln!(v, "{bar} hello", bar = "world");
+LL + writeln!(v, "world {foo}", foo = "hello");
|
error: literal with an empty format string
- --> $DIR/write_literal.rs:42:47
+ --> $DIR/write_literal.rs:44:38
|
LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
- | ^^^^^^^^^^^^^
+ | ^^^^^^^
|
help: try this
|
LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world");
-LL + writeln!(v, "world {foo}", foo = "hello");
+LL + writeln!(v, "{bar} hello", bar = "world");
|
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
diff --git a/src/tools/clippy/tests/ui/write_literal_2.rs b/src/tools/clippy/tests/ui/write_literal_2.rs
index ba0d7be5e..55a11daa1 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.rs
+++ b/src/tools/clippy/tests/ui/write_literal_2.rs
@@ -10,7 +10,7 @@ fn main() {
writeln!(v, r"{}", r"{hello}");
writeln!(v, "{}", '\'');
writeln!(v, "{}", '"');
- writeln!(v, r"{}", '"'); // don't lint
+ writeln!(v, r"{}", '"');
writeln!(v, r"{}", '\'');
writeln!(
v,
@@ -24,4 +24,11 @@ fn main() {
{} \\ {}",
"1", "2", "3",
);
+ writeln!(v, "{}", "\\");
+ writeln!(v, r"{}", "\\");
+ writeln!(v, r#"{}"#, "\\");
+ writeln!(v, "{}", r"\");
+ writeln!(v, "{}", "\r");
+ writeln!(v, r#"{}{}"#, '#', '"'); // hard mode
+ writeln!(v, r"{}", "\r"); // should not lint
}
diff --git a/src/tools/clippy/tests/ui/write_literal_2.stderr b/src/tools/clippy/tests/ui/write_literal_2.stderr
index 9ff297069..d5956db9f 100644
--- a/src/tools/clippy/tests/ui/write_literal_2.stderr
+++ b/src/tools/clippy/tests/ui/write_literal_2.stderr
@@ -48,6 +48,12 @@ LL + writeln!(v, "/"");
|
error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:13:24
+ |
+LL | writeln!(v, r"{}", '"');
+ | ^^^
+
+error: literal with an empty format string
--> $DIR/write_literal_2.rs:14:24
|
LL | writeln!(v, r"{}", '/'');
@@ -108,5 +114,77 @@ LL ~ {} / 3",
LL ~ "1", "2",
|
-error: aborting due to 9 previous errors
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:27:23
+ |
+LL | writeln!(v, "{}", "/");
+ | ^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, "{}", "/");
+LL + writeln!(v, "/");
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:28:24
+ |
+LL | writeln!(v, r"{}", "/");
+ | ^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, r"{}", "/");
+LL + writeln!(v, r"/");
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:29:26
+ |
+LL | writeln!(v, r#"{}"#, "/");
+ | ^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, r#"{}"#, "/");
+LL + writeln!(v, r#"/"#);
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:30:23
+ |
+LL | writeln!(v, "{}", r"/");
+ | ^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, "{}", r"/");
+LL + writeln!(v, "/");
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:31:23
+ |
+LL | writeln!(v, "{}", "/r");
+ | ^^^^
+ |
+help: try this
+ |
+LL - writeln!(v, "{}", "/r");
+LL + writeln!(v, "/r");
+ |
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:32:28
+ |
+LL | writeln!(v, r#"{}{}"#, '#', '"'); // hard mode
+ | ^^^
+
+error: literal with an empty format string
+ --> $DIR/write_literal_2.rs:32:33
+ |
+LL | writeln!(v, r#"{}{}"#, '#', '"'); // hard mode
+ | ^^^
+
+error: aborting due to 17 previous errors
diff --git a/src/tools/clippy/tests/ui/write_with_newline.rs b/src/tools/clippy/tests/ui/write_with_newline.rs
index 446d6914d..b79364c87 100644
--- a/src/tools/clippy/tests/ui/write_with_newline.rs
+++ b/src/tools/clippy/tests/ui/write_with_newline.rs
@@ -56,4 +56,12 @@ fn main() {
write!(v, "foo\r\n");
write!(v, "\\r\n"); //~ ERROR
write!(v, "foo\rbar\n");
+
+ // Ignore expanded format strings
+ macro_rules! newline {
+ () => {
+ "\n"
+ };
+ }
+ write!(v, newline!());
}
diff --git a/src/tools/clippy/tests/ui/write_with_newline.stderr b/src/tools/clippy/tests/ui/write_with_newline.stderr
index 5f55431be..2baaea166 100644
--- a/src/tools/clippy/tests/ui/write_with_newline.stderr
+++ b/src/tools/clippy/tests/ui/write_with_newline.stderr
@@ -5,7 +5,7 @@ LL | write!(v, "Hello/n");
| ^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::write-with-newline` implied by `-D warnings`
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "Hello/n");
LL + writeln!(v, "Hello");
@@ -17,7 +17,7 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "Hello {}/n", "world");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "Hello {}/n", "world");
LL + writeln!(v, "Hello {}", "world");
@@ -29,7 +29,7 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "Hello {} {}/n", "world", "#2");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "Hello {} {}/n", "world", "#2");
LL + writeln!(v, "Hello {} {}", "world", "#2");
@@ -41,7 +41,7 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "{}/n", 1265);
| ^^^^^^^^^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "{}/n", 1265);
LL + writeln!(v, "{}", 1265);
@@ -53,7 +53,7 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "/n");
| ^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "/n");
LL + writeln!(v);
@@ -65,7 +65,7 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "//n"); // should fail
| ^^^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "//n"); // should fail
LL + writeln!(v, "/"); // should fail
@@ -81,11 +81,10 @@ LL | | "
LL | | );
| |_____^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL ~ writeln!(
-LL | v,
-LL ~ ""
+LL ~ v
|
error: using `write!()` with a format string that ends in a single newline
@@ -98,11 +97,10 @@ LL | | "
LL | | );
| |_____^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL ~ writeln!(
-LL | v,
-LL ~ r""
+LL ~ v
|
error: using `write!()` with a format string that ends in a single newline
@@ -111,23 +109,11 @@ error: using `write!()` with a format string that ends in a single newline
LL | write!(v, "/r/n"); //~ ERROR
| ^^^^^^^^^^^^^^^^^^
|
-help: use `writeln!()` instead
+help: use `writeln!` instead
|
LL - write!(v, "/r/n"); //~ ERROR
LL + writeln!(v, "/r"); //~ ERROR
|
-error: using `write!()` with a format string that ends in a single newline
- --> $DIR/write_with_newline.rs:58:5
- |
-LL | write!(v, "foo/rbar/n");
- | ^^^^^^^^^^^^^^^^^^^^^^^
- |
-help: use `writeln!()` instead
- |
-LL - write!(v, "foo/rbar/n");
-LL + writeln!(v, "foo/rbar");
- |
-
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
diff --git a/src/tools/clippy/tests/ui/writeln_empty_string.stderr b/src/tools/clippy/tests/ui/writeln_empty_string.stderr
index ac65aadfc..25e69ec48 100644
--- a/src/tools/clippy/tests/ui/writeln_empty_string.stderr
+++ b/src/tools/clippy/tests/ui/writeln_empty_string.stderr
@@ -1,16 +1,20 @@
-error: using `writeln!(v, "")`
+error: empty string literal in `writeln!`
--> $DIR/writeln_empty_string.rs:11:5
|
LL | writeln!(v, "");
- | ^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)`
+ | ^^^^^^^^^^----^
+ | |
+ | help: remove the empty string
|
= note: `-D clippy::writeln-empty-string` implied by `-D warnings`
-error: using `writeln!(suggestion, "")`
+error: empty string literal in `writeln!`
--> $DIR/writeln_empty_string.rs:14:5
|
LL | writeln!(suggestion, "");
- | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(suggestion)`
+ | ^^^^^^^^^^^^^^^^^^^----^
+ | |
+ | help: remove the empty string
error: aborting due to 2 previous errors
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention.stderr b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
index 2e7ee51d7..d002e55c5 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention.stderr
@@ -4,8 +4,8 @@ error: methods called `from_*` usually take no `self`
LL | fn from_i32(self) {}
| ^^^^
|
- = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
= help: consider choosing a less ambiguous name
+ = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention.rs:22:21
diff --git a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
index 5bdc47f91..8de10e7be 100644
--- a/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_convention2.stderr
@@ -4,8 +4,8 @@ error: methods called `from_*` usually take no `self`
LL | pub fn from_be_self(self) -> Self {
| ^^^^
|
- = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
= help: consider choosing a less ambiguous name
+ = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
error: methods called `from_*` usually take no `self`
--> $DIR/wrong_self_convention2.rs:63:25
diff --git a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
index 8665d8dc9..3d009083c 100644
--- a/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
+++ b/src/tools/clippy/tests/ui/wrong_self_conventions_mut.stderr
@@ -4,8 +4,8 @@ error: methods with the following characteristics: (`to_*` and `self` type is no
LL | pub fn to_many(&mut self) -> Option<&mut [T]> {
| ^^^^^^^^^
|
- = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
= help: consider choosing a less ambiguous name
+ = note: `-D clippy::wrong-self-convention` implied by `-D warnings`
error: methods with the following characteristics: (`to_*` and `*_mut`) usually take `self` by mutable reference
--> $DIR/wrong_self_conventions_mut.rs:22:28
diff --git a/src/tools/clippy/tests/ui/zero_div_zero.stderr b/src/tools/clippy/tests/ui/zero_div_zero.stderr
index 86563542e..2793d1606 100644
--- a/src/tools/clippy/tests/ui/zero_div_zero.stderr
+++ b/src/tools/clippy/tests/ui/zero_div_zero.stderr
@@ -4,8 +4,8 @@ error: constant division of `0.0` with `0.0` will always result in NaN
LL | let nan = 0.0 / 0.0;
| ^^^^^^^^^
|
- = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings`
= help: consider using `f64::NAN` if you would like a constant representing NaN
+ = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings`
error: constant division of `0.0` with `0.0` will always result in NaN
--> $DIR/zero_div_zero.rs:5:19
diff --git a/src/tools/clippy/tests/ui/zero_sized_btreemap_values.stderr b/src/tools/clippy/tests/ui/zero_sized_btreemap_values.stderr
index d924f3379..c6ba6fa76 100644
--- a/src/tools/clippy/tests/ui/zero_sized_btreemap_values.stderr
+++ b/src/tools/clippy/tests/ui/zero_sized_btreemap_values.stderr
@@ -4,8 +4,8 @@ error: map with zero-sized value type
LL | const CONST_NOT_OK: Option<BTreeMap<String, ()>> = None;
| ^^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::zero-sized-map-values` implied by `-D warnings`
= help: consider using a set instead
+ = note: `-D clippy::zero-sized-map-values` implied by `-D warnings`
error: map with zero-sized value type
--> $DIR/zero_sized_btreemap_values.rs:8:30
diff --git a/src/tools/clippy/tests/ui/zero_sized_hashmap_values.stderr b/src/tools/clippy/tests/ui/zero_sized_hashmap_values.stderr
index 79770bf90..75bdeb42e 100644
--- a/src/tools/clippy/tests/ui/zero_sized_hashmap_values.stderr
+++ b/src/tools/clippy/tests/ui/zero_sized_hashmap_values.stderr
@@ -4,8 +4,8 @@ error: map with zero-sized value type
LL | const CONST_NOT_OK: Option<HashMap<String, ()>> = None;
| ^^^^^^^^^^^^^^^^^^^
|
- = note: `-D clippy::zero-sized-map-values` implied by `-D warnings`
= help: consider using a set instead
+ = note: `-D clippy::zero-sized-map-values` implied by `-D warnings`
error: map with zero-sized value type
--> $DIR/zero_sized_hashmap_values.rs:8:30
diff --git a/src/tools/clippy/tests/versioncheck.rs b/src/tools/clippy/tests/versioncheck.rs
index 38498ebdc..a6d8d0307 100644
--- a/src/tools/clippy/tests/versioncheck.rs
+++ b/src/tools/clippy/tests/versioncheck.rs
@@ -8,12 +8,12 @@ use std::fs;
#[test]
fn check_that_clippy_lints_and_clippy_utils_have_the_same_version_as_clippy() {
fn read_version(path: &str) -> String {
- let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("error reading `{}`: {:?}", path, e));
+ let contents = fs::read_to_string(path).unwrap_or_else(|e| panic!("error reading `{path}`: {e:?}"));
contents
.lines()
.filter_map(|l| l.split_once('='))
.find_map(|(k, v)| (k.trim() == "version").then(|| v.trim()))
- .unwrap_or_else(|| panic!("error finding version in `{}`", path))
+ .unwrap_or_else(|| panic!("error finding version in `{path}`"))
.to_string()
}
@@ -48,7 +48,7 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() {
// `RUSTC_REAL` if Clippy is build in the Rust repo with `./x.py`.
let rustc = std::env::var("RUSTC_REAL").unwrap_or_else(|_| "rustc".to_string());
let rustc_version = String::from_utf8(
- std::process::Command::new(&rustc)
+ std::process::Command::new(rustc)
.arg("--version")
.output()
.expect("failed to run `rustc --version`")
@@ -83,7 +83,7 @@ fn check_that_clippy_has_the_same_major_version_as_rustc() {
// we don't want our tests failing suddenly
},
_ => {
- panic!("Failed to parse rustc version: {:?}", vsplit);
+ panic!("Failed to parse rustc version: {vsplit:?}");
},
};
}
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 64df76e27..0260f6848 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -269,19 +269,15 @@ pub struct Config {
pub runtool: Option<String>,
/// Flags to pass to the compiler when building for the host
- pub host_rustcflags: Option<String>,
+ pub host_rustcflags: Vec<String>,
/// Flags to pass to the compiler when building for the target
- pub target_rustcflags: Option<String>,
+ pub target_rustcflags: Vec<String>,
/// Whether tests should be optimized by default. Individual test-suites and test files may
/// override this setting.
pub optimize_tests: bool,
- /// What panic strategy the target is built with. Unwind supports Abort, but
- /// not vice versa.
- pub target_panic: PanicStrategy,
-
/// Target system to be tested
pub target: String,
@@ -389,7 +385,8 @@ impl Config {
}
fn target_cfg(&self) -> &TargetCfg {
- self.target_cfg.borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target))
+ self.target_cfg
+ .borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target, &self.target_rustcflags))
}
pub fn matches_arch(&self, arch: &str) -> bool {
@@ -426,6 +423,10 @@ impl Config {
*&self.target_cfg().pointer_width
}
+ pub fn can_unwind(&self) -> bool {
+ self.target_cfg().panic == PanicStrategy::Unwind
+ }
+
pub fn has_asm_support(&self) -> bool {
static ASM_SUPPORTED_ARCHS: &[&str] = &[
"x86", "x86_64", "arm", "aarch64", "riscv32",
@@ -446,6 +447,7 @@ pub struct TargetCfg {
families: Vec<String>,
pointer_width: u32,
endian: Endian,
+ panic: PanicStrategy,
}
#[derive(Eq, PartialEq, Clone, Debug)]
@@ -455,11 +457,12 @@ pub enum Endian {
}
impl TargetCfg {
- fn new(rustc_path: &Path, target: &str) -> TargetCfg {
+ fn new(rustc_path: &Path, target: &str, target_rustcflags: &Vec<String>) -> TargetCfg {
let output = match Command::new(rustc_path)
.arg("--print=cfg")
.arg("--target")
.arg(target)
+ .args(target_rustcflags)
.output()
{
Ok(output) => output,
@@ -481,6 +484,7 @@ impl TargetCfg {
let mut families = Vec::new();
let mut pointer_width = None;
let mut endian = None;
+ let mut panic = None;
for line in print_cfg.lines() {
if let Some((name, value)) = line.split_once('=') {
let value = value.trim_matches('"');
@@ -498,6 +502,13 @@ impl TargetCfg {
s => panic!("unexpected {s}"),
})
}
+ "panic" => {
+ panic = match value {
+ "abort" => Some(PanicStrategy::Abort),
+ "unwind" => Some(PanicStrategy::Unwind),
+ s => panic!("unexpected {s}"),
+ }
+ }
_ => {}
}
}
@@ -510,6 +521,7 @@ impl TargetCfg {
families,
pointer_width: pointer_width.unwrap(),
endian: endian.unwrap(),
+ panic: panic.unwrap(),
}
}
}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 3ff1cbf20..0d9a629e1 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -4,10 +4,11 @@ use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::{Path, PathBuf};
+use std::process::Command;
use tracing::*;
-use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PanicStrategy, PassMode};
+use crate::common::{CompareMode, Config, Debugger, FailMode, Mode, PassMode};
use crate::util;
use crate::{extract_cdb_version, extract_gdb_version};
@@ -843,6 +844,20 @@ pub fn extract_llvm_version(version: &str) -> Option<u32> {
Some(version)
}
+pub fn extract_llvm_version_from_binary(binary_path: &str) -> Option<u32> {
+ let output = Command::new(binary_path).arg("--version").output().ok()?;
+ if !output.status.success() {
+ return None;
+ }
+ let version = String::from_utf8(output.stdout).ok()?;
+ for line in version.lines() {
+ if let Some(version) = line.split("LLVM version ").skip(1).next() {
+ return extract_llvm_version(version);
+ }
+ }
+ None
+}
+
/// Takes a directive of the form "<version1> [- <version2>]",
/// returns the numeric representation of <version1> and <version2> as
/// tuple: (<version1> as u32, <version2> as u32)
@@ -949,8 +964,7 @@ pub fn make_test_description<R: Read>(
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.target_panic == PanicStrategy::Abort
- && config.parse_name_directive(ln, "needs-unwind");
+ 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);
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index 38c7b87fc..19cf54780 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -5,9 +5,7 @@
extern crate test;
-use crate::common::{
- expected_output_path, output_base_dir, output_relative_path, PanicStrategy, UI_EXTENSIONS,
-};
+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 getopts::Options;
@@ -105,7 +103,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
.optmulti("", "host-rustcflags", "flags to pass to rustc for host", "FLAGS")
.optmulti("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS")
.optflag("", "optimize-tests", "run tests with optimizations enabled")
- .optopt("", "target-panic", "what panic strategy the target supports", "unwind | abort")
.optflag("", "verbose", "run tests verbosely, showing all output")
.optflag(
"",
@@ -203,7 +200,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
};
let llvm_version =
- matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version);
+ matches.opt_str("llvm-version").as_deref().and_then(header::extract_llvm_version).or_else(
+ || header::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
+ );
let src_base = opt_path(matches, "src-base");
let run_ignored = matches.opt_present("ignored");
@@ -255,14 +254,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
}),
logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
runtool: matches.opt_str("runtool"),
- host_rustcflags: Some(matches.opt_strs("host-rustcflags").join(" ")),
- target_rustcflags: Some(matches.opt_strs("target-rustcflags").join(" ")),
+ host_rustcflags: matches.opt_strs("host-rustcflags"),
+ target_rustcflags: matches.opt_strs("target-rustcflags"),
optimize_tests: matches.opt_present("optimize-tests"),
- target_panic: match matches.opt_str("target-panic").as_deref() {
- Some("unwind") | None => PanicStrategy::Unwind,
- Some("abort") => PanicStrategy::Abort,
- _ => panic!("unknown `--target-panic` option `{}` given", mode),
- },
target,
host: opt_str2(matches.opt_str("host")),
cdb,
@@ -328,8 +322,8 @@ pub fn log_config(config: &Config) {
format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
);
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
- logv(c, format!("host-rustcflags: {}", opt_str(&config.host_rustcflags)));
- logv(c, format!("target-rustcflags: {}", opt_str(&config.target_rustcflags)));
+ logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
+ logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
logv(c, format!("target: {}", config.target));
logv(c, format!("host: {}", config.host));
logv(c, format!("android-cross-path: {:?}", config.android_cross_path.display()));
@@ -403,6 +397,8 @@ pub fn run_tests(config: Config) {
make_tests(c, &mut tests);
}
+ tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
+
let res = test::run_tests_console(&opts, tests);
match res {
Ok(true) => {}
@@ -805,7 +801,10 @@ fn make_test_closure(
let config = config.clone();
let testpaths = testpaths.clone();
let revision = revision.cloned();
- test::DynTestFn(Box::new(move || runtest::run(config, &testpaths, revision.as_deref())))
+ test::DynTestFn(Box::new(move || {
+ runtest::run(config, &testpaths, revision.as_deref());
+ Ok(())
+ }))
}
/// Returns `true` if the given target is an Android target for the
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 8f289876f..8af5f1da6 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -558,10 +558,7 @@ impl<'test> TestCx<'test> {
.arg(&aux_dir)
.args(&self.props.compile_flags)
.envs(self.props.rustc_env.clone());
- self.maybe_add_external_args(
- &mut rustc,
- self.split_maybe_args(&self.config.target_rustcflags),
- );
+ self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
let src = match read_from {
ReadFrom::Stdin(src) => Some(src),
@@ -629,10 +626,7 @@ impl<'test> TestCx<'test> {
.arg("-L")
.arg(aux_dir);
self.set_revision_flags(&mut rustc);
- self.maybe_add_external_args(
- &mut rustc,
- self.split_maybe_args(&self.config.target_rustcflags),
- );
+ self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
rustc.args(&self.props.compile_flags);
self.compose_and_run_compiler(rustc, Some(src))
@@ -1186,23 +1180,14 @@ impl<'test> TestCx<'test> {
ProcRes { status, stdout: out, stderr: err, cmdline: format!("{:?}", cmd) }
}
- fn cleanup_debug_info_options(&self, options: &Option<String>) -> Option<String> {
- if options.is_none() {
- return None;
- }
-
+ fn cleanup_debug_info_options(&self, options: &Vec<String>) -> Vec<String> {
// Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
- let new_options = self
- .split_maybe_args(options)
- .into_iter()
- .filter(|x| !options_to_remove.contains(x))
- .collect::<Vec<String>>();
- Some(new_options.join(" "))
+ options.iter().filter(|x| !options_to_remove.contains(x)).map(|x| x.clone()).collect()
}
- fn maybe_add_external_args(&self, cmd: &mut Command, args: Vec<String>) {
+ fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec<String>) {
// Filter out the arguments that should not be added by runtest here.
//
// Notable use-cases are: do not add our optimisation flag if
@@ -2035,15 +2020,9 @@ impl<'test> TestCx<'test> {
}
if self.props.force_host {
- self.maybe_add_external_args(
- &mut rustc,
- self.split_maybe_args(&self.config.host_rustcflags),
- );
+ self.maybe_add_external_args(&mut rustc, &self.config.host_rustcflags);
} else {
- self.maybe_add_external_args(
- &mut rustc,
- self.split_maybe_args(&self.config.target_rustcflags),
- );
+ self.maybe_add_external_args(&mut rustc, &self.config.target_rustcflags);
if !is_rustdoc {
if let Some(ref linker) = self.config.linker {
rustc.arg(format!("-Clinker={}", linker));
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index 9d047b63c..e5ff0906b 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -11,9 +11,15 @@ mod tests;
pub const ASAN_SUPPORTED_TARGETS: &[&str] = &[
"aarch64-apple-darwin",
"aarch64-fuchsia",
+ "aarch64-linux-android",
"aarch64-unknown-linux-gnu",
+ "arm-linux-androideabi",
+ "armv7-linux-androideabi",
+ "i686-linux-android",
+ "i686-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-fuchsia",
+ "x86_64-linux-android",
"x86_64-unknown-freebsd",
"x86_64-unknown-linux-gnu",
];
diff --git a/src/tools/error_index_generator/error-index.css b/src/tools/error_index_generator/error-index.css
index 8975af82d..dcac2e18e 100644
--- a/src/tools/error_index_generator/error-index.css
+++ b/src/tools/error_index_generator/error-index.css
@@ -27,10 +27,11 @@ pre .tooltip::before {
content: " ";
position: absolute;
top: 50%;
- left: 16px;
+ left: 2px;
margin-top: -5px;
border-width: 5px;
border-style: solid;
+ height: 0px;
}
pre .tooltip:hover::before, pre .tooltip:hover::after {
diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs
index ad8e96a0b..6d986e575 100644
--- a/src/tools/jsondoclint/src/item_kind.rs
+++ b/src/tools/jsondoclint/src/item_kind.rs
@@ -142,8 +142,7 @@ impl Kind {
ItemEnum::Static(_) => Static,
ItemEnum::Macro(_) => Macro,
ItemEnum::ProcMacro(_) => ProcMacro,
- // https://github.com/rust-lang/rust/issues/100961
- ItemEnum::PrimitiveType(_) => Primitive,
+ ItemEnum::Primitive(_) => Primitive,
ItemEnum::ForeignType => ForeignType,
ItemEnum::ExternCrate { .. } => ExternCrate,
ItemEnum::AssocConst { .. } => AssocConst,
diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs
index a0e77127d..94af4c5e9 100644
--- a/src/tools/jsondoclint/src/validator.rs
+++ b/src/tools/jsondoclint/src/validator.rs
@@ -4,8 +4,8 @@ use std::hash::Hash;
use rustdoc_json_types::{
Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs,
GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Method, Module, OpaqueTy,
- Path, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding,
- TypeBindingKind, Typedef, Union, Variant, WherePredicate,
+ Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type,
+ TypeBinding, TypeBindingKind, Typedef, Union, Variant, WherePredicate,
};
use crate::{item_kind::Kind, Error, ErrorKind};
@@ -76,7 +76,7 @@ impl<'a> Validator<'a> {
ItemEnum::ForeignType => {} // nop
ItemEnum::Macro(x) => self.check_macro(x),
ItemEnum::ProcMacro(x) => self.check_proc_macro(x),
- ItemEnum::PrimitiveType(x) => self.check_primitive_type(x),
+ ItemEnum::Primitive(x) => self.check_primitive_type(x),
ItemEnum::Module(x) => self.check_module(x),
// FIXME: Why don't these have their own structs?
ItemEnum::ExternCrate { .. } => {}
@@ -219,8 +219,8 @@ impl<'a> Validator<'a> {
// nop
}
- fn check_primitive_type(&mut self, _: &'a str) {
- // nop
+ fn check_primitive_type(&mut self, x: &'a Primitive) {
+ x.impls.iter().for_each(|i| self.add_impl_id(i));
}
fn check_generics(&mut self, x: &'a Generics) {
diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs
index a7c78d80c..7842611bd 100644
--- a/src/tools/linkchecker/main.rs
+++ b/src/tools/linkchecker/main.rs
@@ -215,6 +215,7 @@ impl Checker {
|| url.starts_with("ftp:")
|| url.starts_with("irc:")
|| url.starts_with("data:")
+ || url.starts_with("mailto:")
{
report.links_ignored_external += 1;
return;
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index c0cef8f7b..9c16ef2cb 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -30,7 +30,6 @@ except ImportError:
# These should be collaborators of the rust-lang/rust repository (with at least
# read privileges on it). CI will fail otherwise.
MAINTAINERS = {
- 'miri': {'oli-obk', 'RalfJung'},
'book': {'carols10cents'},
'nomicon': {'frewsxcv', 'Gankra', 'JohnTitor'},
'reference': {'Havvy', 'matthewjasper', 'ehuss'},
@@ -41,7 +40,6 @@ MAINTAINERS = {
}
LABELS = {
- 'miri': ['A-miri', 'C-bug'],
'book': ['C-bug'],
'nomicon': ['C-bug'],
'reference': ['C-bug'],
@@ -52,7 +50,6 @@ LABELS = {
}
REPOS = {
- 'miri': 'https://github.com/rust-lang/miri',
'book': 'https://github.com/rust-lang/book',
'nomicon': 'https://github.com/rust-lang/nomicon',
'reference': 'https://github.com/rust-lang/reference',
@@ -239,16 +236,10 @@ def update_latest(
message += '{} (cc {}).\n' \
.format(title, maintainers)
# See if we need to create an issue.
- if tool == 'miri':
- # Create issue if tests used to pass before. Don't open a *second*
- # issue when we regress from "test-fail" to "build-fail".
- if old == 'test-pass':
- create_issue_for_status = new
- else:
- # Create issue if things no longer build.
- # (No issue for mere test failures to avoid spurious issues.)
- if new == 'build-fail':
- create_issue_for_status = new
+ # Create issue if things no longer build.
+ # (No issue for mere test failures to avoid spurious issues.)
+ if new == 'build-fail':
+ create_issue_for_status = new
if create_issue_for_status is not None:
try:
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 9f10d92c4..0ddea2f72 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -37,9 +37,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.62"
+version = "1.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305"
+checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
[[package]]
name = "anymap"
@@ -49,9 +49,9 @@ checksum = "8f1f8f5a6f3d50d89e3797d7593a50f96bb2aaa20ca0cc7be1fb673232c91d72"
[[package]]
name = "arbitrary"
-version = "1.1.3"
+version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a7924531f38b1970ff630f03eb20a2fde69db5c590c93b0f3482e95dcc5fd60"
+checksum = "d86fd10d912cab78764cc44307d9cd5f164e09abbeb87fb19fb6d95937e8da5f"
[[package]]
name = "arrayvec"
@@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chalk-derive"
-version = "0.84.0"
+version = "0.86.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf29c109d57f8d57b0e7675391be37a9285d86dd93278bd5f14a0ad3c447a6c2"
+checksum = "5499d415d855b5094366a824815341893ad3de0ecb6048c430118bdae6d27402"
dependencies = [
"proc-macro2",
"quote",
@@ -183,9 +183,9 @@ dependencies = [
[[package]]
name = "chalk-ir"
-version = "0.84.0"
+version = "0.86.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d391763027b5e50a5e15caf6d2857ec585fd68160367bbeac9e1804209620918"
+checksum = "3800118c76a48507b0eece3a01f3a429b5c478d203c493096e6040c67ab960e1"
dependencies = [
"bitflags",
"chalk-derive",
@@ -194,9 +194,9 @@ dependencies = [
[[package]]
name = "chalk-recursive"
-version = "0.84.0"
+version = "0.86.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "afafd92dcdc7fe0ea940ee94bdd8cc5bd18f4a4a84c593d6d7025fe16c150478"
+checksum = "1baf60628fd73104d1f8562586a52d48f37f1e84435aab2e62674b1fd935b8c8"
dependencies = [
"chalk-derive",
"chalk-ir",
@@ -207,9 +207,9 @@ dependencies = [
[[package]]
name = "chalk-solve"
-version = "0.84.0"
+version = "0.86.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3af1d111f11c91c48ace02e93e470c5bae6d2631bd112e4545317da53660d7fc"
+checksum = "0e9c3c068f9358786348e58a1b94ef0a5cf90a9810fc1f10fda896f0b5d80185"
dependencies = [
"chalk-derive",
"chalk-ir",
@@ -270,45 +270,44 @@ dependencies = [
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
- "once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
name = "dashmap"
-version = "5.3.4"
+version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f"
+checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
dependencies = [
"cfg-if",
"hashbrown",
"lock_api",
+ "once_cell",
"parking_lot_core 0.9.3",
]
[[package]]
name = "derive_arbitrary"
-version = "1.1.3"
+version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9a577516173adb681466d517d39bd468293bc2c2a16439375ef0f35bba45f3d"
+checksum = "226ad66541d865d7a7173ad6a9e691c33fdb910ac723f4bc734b3e5294a1f931"
dependencies = [
"proc-macro2",
"quote",
@@ -394,6 +393,7 @@ dependencies = [
"crossbeam-channel",
"jod-thread",
"paths",
+ "rustc-hash",
"serde",
"serde_json",
"stdx",
@@ -403,11 +403,10 @@ dependencies = [
[[package]]
name = "form_urlencoded"
-version = "1.0.1"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [
- "matches",
"percent-encoding",
]
@@ -545,6 +544,7 @@ version = "0.0.0"
dependencies = [
"arrayvec",
"base-db",
+ "chalk-derive",
"chalk-ir",
"chalk-recursive",
"chalk-solve",
@@ -572,9 +572,9 @@ dependencies = [
[[package]]
name = "home"
-version = "0.5.3"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"
+checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
dependencies = [
"winapi",
]
@@ -660,6 +660,7 @@ dependencies = [
"indexmap",
"itertools",
"limit",
+ "memchr",
"once_cell",
"parser",
"profile",
@@ -712,11 +713,10 @@ dependencies = [
[[package]]
name = "idna"
-version = "0.2.3"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
- "matches",
"unicode-bidi",
"unicode-normalization",
]
@@ -762,18 +762,18 @@ dependencies = [
[[package]]
name = "itertools"
-version = "0.10.3"
+version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
-version = "1.0.3"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "jod-thread"
@@ -813,9 +813,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.132"
+version = "0.2.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
[[package]]
name = "libloading"
@@ -829,9 +829,9 @@ dependencies = [
[[package]]
name = "libmimalloc-sys"
-version = "0.1.25"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11ca136052550448f55df7898c6dbe651c6b574fe38a0d9ea687a9f8088a2e2c"
+checksum = "8fc093ab289b0bfda3aa1bdfab9c9542be29c7ef385cfcbe77f8c9813588eb48"
dependencies = [
"cc",
]
@@ -842,9 +842,9 @@ version = "0.0.0"
[[package]]
name = "lock_api"
-version = "0.4.7"
+version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
dependencies = [
"autocfg",
"scopeguard",
@@ -861,7 +861,7 @@ dependencies = [
[[package]]
name = "lsp-server"
-version = "0.6.0"
+version = "0.7.0"
dependencies = [
"crossbeam-channel",
"log",
@@ -893,12 +893,6 @@ dependencies = [
]
[[package]]
-name = "matches"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
-
-[[package]]
name = "mbe"
version = "0.0.0"
dependencies = [
@@ -939,18 +933,18 @@ dependencies = [
[[package]]
name = "mimalloc"
-version = "0.1.29"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f64ad83c969af2e732e907564deb0d0ed393cec4af80776f77dd77a1a427698"
+checksum = "76ce6a4b40d3bff9eb3ce9881ca0737a85072f9f975886082640cd46a75cdb35"
dependencies = [
"libmimalloc-sys",
]
[[package]]
name = "miniz_oxide"
-version = "0.5.3"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
@@ -978,9 +972,9 @@ dependencies = [
[[package]]
name = "notify"
-version = "5.0.0-pre.16"
+version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "530f6314d6904508082f4ea424a0275cf62d341e118b313663f266429cb19693"
+checksum = "ed2c66da08abae1c024c01d635253e402341b4060a12e99b31c7594063bf490a"
dependencies = [
"bitflags",
"crossbeam-channel",
@@ -1015,9 +1009,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.13.1"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
+checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "oorandom"
@@ -1086,9 +1080,9 @@ dependencies = [
[[package]]
name = "paste"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22"
+checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
[[package]]
name = "paths"
@@ -1096,9 +1090,9 @@ version = "0.0.0"
[[package]]
name = "percent-encoding"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "perf-event"
@@ -1188,9 +1182,9 @@ version = "0.0.0"
[[package]]
name = "proc-macro2"
-version = "1.0.43"
+version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
@@ -1263,9 +1257,9 @@ dependencies = [
[[package]]
name = "pulldown-cmark-to-cmark"
-version = "10.0.2"
+version = "10.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1353ac408192fa925228d3e60ff746167d03f4f7e54835d78ef79e08225d913"
+checksum = "0194e6e1966c23cc5fd988714f85b18d548d773e81965413555d96569931833d"
dependencies = [
"pulldown-cmark",
]
@@ -1338,9 +1332,9 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rowan"
-version = "0.15.8"
+version = "0.15.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e88acf7b001007e9e8c989fe7449f6601d909e5dd2c56399fc158977ad6c56e8"
+checksum = "5811547e7ba31e903fe48c8ceab10d40d70a101f3d15523c847cce91aa71f332"
dependencies = [
"countme",
"hashbrown",
@@ -1491,27 +1485,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
-version = "1.0.13"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
dependencies = [
"serde",
]
[[package]]
name = "serde"
-version = "1.0.143"
+version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
+checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.143"
+version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
+checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
@@ -1520,9 +1514,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.83"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
+checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
dependencies = [
"indexmap",
"itoa",
@@ -1552,9 +1546,9 @@ dependencies = [
[[package]]
name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smol_str"
@@ -1591,9 +1585,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.99"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
+checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
@@ -1664,18 +1658,18 @@ checksum = "288cb548dbe72b652243ea797201f3d481a0609a967980fcc5b2315ea811560a"
[[package]]
name = "thiserror"
-version = "1.0.31"
+version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.31"
+version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
@@ -1713,9 +1707,9 @@ dependencies = [
[[package]]
name = "tikv-jemalloc-sys"
-version = "0.5.1+5.3.0-patched"
+version = "0.5.2+5.3.0-patched"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "931e876f91fed0827f863a2d153897790da0b24d882c721a79cb3beb0b903261"
+checksum = "ec45c14da997d0925c7835883e4d5c181f196fa142f8c19d7643d1e9af2592c3"
dependencies = [
"cc",
"fs_extra",
@@ -1756,9 +1750,9 @@ dependencies = [
[[package]]
name = "tracing"
-version = "0.1.36"
+version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
"pin-project-lite",
@@ -1768,9 +1762,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2",
"quote",
@@ -1779,9 +1773,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.29"
+version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [
"once_cell",
"valuable",
@@ -1800,9 +1794,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
-version = "0.3.15"
+version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
+checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
dependencies = [
"matchers",
"once_cell",
@@ -1864,40 +1858,39 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[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 = "unicode-normalization"
-version = "0.1.21"
+version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
[[package]]
name = "unicode-xid"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
-version = "2.2.2"
+version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
- "matches",
"percent-encoding",
"serde",
]
@@ -2080,18 +2073,18 @@ checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
[[package]]
name = "xflags"
-version = "0.2.4"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f14fe1ed41a5a2b5ef3f565586c4a8a559ee55d3953faab360a771135bdee00"
+checksum = "cbf19f5031a1a812e96fede16f8161218883079946cea87619d3613db1efd268"
dependencies = [
"xflags-macros",
]
[[package]]
name = "xflags-macros"
-version = "0.2.4"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45d11d5fc2a97287eded8b170ca80533b3c42646dd7fa386a5eb045817921022"
+checksum = "2afbd7f2039bb6cad2dd45f0c5dff49c0d4e26118398768b7a605524d4251809"
[[package]]
name = "xshell"
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 6b68ca823..286ef1e7d 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -27,6 +27,7 @@ debug = 0
# chalk-solve = { path = "../chalk/chalk-solve" }
# chalk-ir = { path = "../chalk/chalk-ir" }
# chalk-recursive = { path = "../chalk/chalk-recursive" }
+# chalk-derive = { path = "../chalk/chalk-derive" }
# ungrammar = { path = "../ungrammar" }
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 8e6e6a11a..5b7828a26 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
@@ -196,7 +196,7 @@ impl ChangeFixture {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
} else {
for (from, to, prelude) in crate_deps {
@@ -270,7 +270,7 @@ impl ChangeFixture {
Env::default(),
Ok(proc_macro),
true,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
for krate in all_crates {
@@ -398,7 +398,7 @@ fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
let (version, origin) = match b.split_once(':') {
Some(("CratesIo", data)) => match data.split_once(',') {
Some((version, url)) => {
- (version, CrateOrigin::CratesIo { repo: Some(url.to_owned()) })
+ (version, CrateOrigin::CratesIo { repo: Some(url.to_owned()), name: None })
}
_ => panic!("Bad crates.io parameter: {}", data),
},
@@ -409,7 +409,7 @@ fn parse_crate(crate_str: String) -> (String, CrateOrigin, Option<String>) {
let crate_origin = match &*crate_str {
"std" => CrateOrigin::Lang(LangCrateOrigin::Std),
"core" => CrateOrigin::Lang(LangCrateOrigin::Core),
- _ => CrateOrigin::CratesIo { repo: None },
+ _ => CrateOrigin::CratesIo { repo: None, name: None },
};
(crate_str, crate_origin, None)
}
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 b388e47de..e7f0c4ec2 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -136,7 +136,7 @@ impl ops::Deref for CrateName {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CrateOrigin {
/// Crates that are from crates.io official registry,
- CratesIo { repo: Option<String> },
+ CratesIo { repo: Option<String>, name: Option<String> },
/// Crates that are provided by the language, like std, core, proc-macro, ...
Lang(LangCrateOrigin),
}
@@ -648,7 +648,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -660,7 +660,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@@ -672,7 +672,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -698,7 +698,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -710,7 +710,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -733,7 +733,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -745,7 +745,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate3 = graph.add_crate_root(
FileId(3u32),
@@ -757,7 +757,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
assert!(graph
.add_dep(crate1, Dependency::new(CrateName::new("crate2").unwrap(), crate2))
@@ -780,7 +780,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
let crate2 = graph.add_crate_root(
FileId(2u32),
@@ -792,7 +792,7 @@ mod tests {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
assert!(graph
.add_dep(
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index c9664a83a..ee1ad677a 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -22,5 +22,5 @@ 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.0"
-derive_arbitrary = "1.1.0"
+arbitrary = "1.1.7"
+derive_arbitrary = "1.1.6"
diff --git a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
index d3d180ece..2ad32d248 100644
--- a/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/flycheck/Cargo.toml
@@ -11,10 +11,11 @@ doctest = false
[dependencies]
crossbeam-channel = "0.5.5"
-tracing = "0.1.35"
+tracing = "0.1.37"
cargo_metadata = "0.15.0"
+rustc-hash = "1.1.0"
serde = { version = "1.0.137", features = ["derive"] }
-serde_json = "1.0.81"
+serde_json = "1.0.86"
jod-thread = "0.1.2"
toolchain = { path = "../toolchain", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index d9f4ef5b7..73c3a48b4 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -12,6 +12,7 @@ use std::{
use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
use paths::AbsPathBuf;
+use rustc_hash::FxHashMap;
use serde::Deserialize;
use stdx::{process::streaming_output, JodChild};
@@ -20,6 +21,20 @@ pub use cargo_metadata::diagnostic::{
DiagnosticSpanMacroExpansion,
};
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub enum InvocationStrategy {
+ Once,
+ #[default]
+ PerWorkspace,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum InvocationLocation {
+ Root(AbsPathBuf),
+ #[default]
+ Workspace,
+}
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlycheckConfig {
CargoCommand {
@@ -30,10 +45,14 @@ pub enum FlycheckConfig {
all_features: bool,
features: Vec<String>,
extra_args: Vec<String>,
+ extra_env: FxHashMap<String, String>,
},
CustomCommand {
command: String,
args: Vec<String>,
+ extra_env: FxHashMap<String, String>,
+ invocation_strategy: InvocationStrategy,
+ invocation_location: InvocationLocation,
},
}
@@ -41,7 +60,7 @@ impl fmt::Display for FlycheckConfig {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command),
- FlycheckConfig::CustomCommand { command, args } => {
+ FlycheckConfig::CustomCommand { command, args, .. } => {
write!(f, "{} {}", command, args.join(" "))
}
}
@@ -133,11 +152,15 @@ enum Restart {
No,
}
+/// A [`FlycheckActor`] is a single check instance of a workspace.
struct FlycheckActor {
+ /// The workspace id of this flycheck instance.
id: usize,
sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig,
- workspace_root: AbsPathBuf,
+ /// Either the workspace root of the workspace we are flychecking,
+ /// or the project root of the project.
+ root: AbsPathBuf,
/// CargoHandle exists to wrap around the communication needed to be able to
/// run `cargo check` without blocking. Currently the Rust standard library
/// doesn't provide a way to read sub-process output without blocking, so we
@@ -159,20 +182,27 @@ impl FlycheckActor {
workspace_root: AbsPathBuf,
) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck");
- FlycheckActor { id, sender, config, workspace_root, cargo_handle: None }
+ FlycheckActor { id, sender, config, root: workspace_root, cargo_handle: None }
}
- fn progress(&self, progress: Progress) {
+
+ fn report_progress(&self, progress: Progress) {
self.send(Message::Progress { id: self.id, progress });
}
+
fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> {
let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver);
+ if let Ok(msg) = inbox.try_recv() {
+ // give restarts a preference so check outputs don't block a restart or stop
+ return Some(Event::Restart(msg));
+ }
select! {
recv(inbox) -> msg => msg.ok().map(Event::Restart),
recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())),
}
}
+
fn run(mut self, inbox: Receiver<Restart>) {
- while let Some(event) = self.next_event(&inbox) {
+ 'event: while let Some(event) = self.next_event(&inbox) {
match event {
Event::Restart(Restart::No) => {
self.cancel_check_process();
@@ -180,7 +210,12 @@ impl FlycheckActor {
Event::Restart(Restart::Yes) => {
// Cancel the previously spawned process
self.cancel_check_process();
- while let Ok(_) = inbox.recv_timeout(Duration::from_millis(50)) {}
+ while let Ok(restart) = inbox.recv_timeout(Duration::from_millis(50)) {
+ // restart chained with a stop, so just cancel
+ if let Restart::No = restart {
+ continue 'event;
+ }
+ }
let command = self.check_command();
tracing::debug!(?command, "will restart flycheck");
@@ -191,10 +226,10 @@ impl FlycheckActor {
"did restart flycheck"
);
self.cargo_handle = Some(cargo_handle);
- self.progress(Progress::DidStart);
+ self.report_progress(Progress::DidStart);
}
Err(error) => {
- self.progress(Progress::DidFailToRestart(format!(
+ self.report_progress(Progress::DidFailToRestart(format!(
"Failed to run the following command: {:?} error={}",
self.check_command(),
error
@@ -214,17 +249,17 @@ impl FlycheckActor {
self.check_command()
);
}
- self.progress(Progress::DidFinish(res));
+ self.report_progress(Progress::DidFinish(res));
}
Event::CheckEvent(Some(message)) => match message {
CargoMessage::CompilerArtifact(msg) => {
- self.progress(Progress::DidCheckCrate(msg.target.name));
+ self.report_progress(Progress::DidCheckCrate(msg.target.name));
}
CargoMessage::Diagnostic(msg) => {
self.send(Message::AddDiagnostic {
id: self.id,
- workspace_root: self.workspace_root.clone(),
+ workspace_root: self.root.clone(),
diagnostic: msg,
});
}
@@ -242,12 +277,12 @@ impl FlycheckActor {
"did cancel flycheck"
);
cargo_handle.cancel();
- self.progress(Progress::DidCancel);
+ self.report_progress(Progress::DidCancel);
}
}
fn check_command(&self) -> Command {
- let mut cmd = match &self.config {
+ let (mut cmd, args) = match &self.config {
FlycheckConfig::CargoCommand {
command,
target_triple,
@@ -256,12 +291,11 @@ impl FlycheckActor {
all_features,
extra_args,
features,
+ extra_env,
} => {
let mut cmd = Command::new(toolchain::cargo());
cmd.arg(command);
- cmd.current_dir(&self.workspace_root);
- cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
- .arg(self.workspace_root.join("Cargo.toml").as_os_str());
+ cmd.args(&["--workspace", "--message-format=json"]);
if let Some(target) = target_triple {
cmd.args(&["--target", target.as_str()]);
@@ -280,16 +314,41 @@ impl FlycheckActor {
cmd.arg(features.join(" "));
}
}
- cmd.args(extra_args);
- cmd
+ cmd.envs(extra_env);
+ (cmd, extra_args)
}
- FlycheckConfig::CustomCommand { command, args } => {
+ FlycheckConfig::CustomCommand {
+ command,
+ args,
+ extra_env,
+ invocation_strategy,
+ invocation_location,
+ } => {
let mut cmd = Command::new(command);
- cmd.args(args);
- cmd
+ cmd.envs(extra_env);
+
+ match invocation_location {
+ InvocationLocation::Workspace => {
+ match invocation_strategy {
+ InvocationStrategy::Once => {
+ cmd.current_dir(&self.root);
+ }
+ InvocationStrategy::PerWorkspace => {
+ // FIXME: cmd.current_dir(&affected_workspace);
+ cmd.current_dir(&self.root);
+ }
+ }
+ }
+ InvocationLocation::Root(root) => {
+ cmd.current_dir(root);
+ }
+ }
+
+ (cmd, args)
}
};
- cmd.current_dir(&self.workspace_root);
+
+ cmd.args(args);
cmd
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index e8cff2f3e..4ad8e7597 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -15,17 +15,17 @@ arrayvec = "0.7.2"
bitflags = "1.3.2"
cov-mark = "2.0.0-pre.1"
# We need to freeze the version of the crate, as the raw-api feature is considered unstable
-dashmap = { version = "=5.3.4", features = ["raw-api"] }
+dashmap = { version = "=5.4.0", features = ["raw-api"] }
drop_bomb = "0.1.5"
either = "1.7.0"
fst = { version = "0.4.7", default-features = false }
hashbrown = { version = "0.12.1", default-features = false }
indexmap = "1.9.1"
-itertools = "0.10.3"
+itertools = "0.10.5"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-once_cell = "1.12.0"
+once_cell = "1.15.0"
rustc-hash = "1.1.0"
-smallvec = "1.9.0"
+smallvec = "1.10.0"
tracing = "0.1.35"
stdx = { path = "../stdx", version = "0.0.0" }
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 277135d6d..938db032f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/adt.rs
@@ -1,12 +1,12 @@
//! Defines hir-level representation of structs, enums and unions
-use std::sync::Arc;
+use std::{num::NonZeroU32, sync::Arc};
use base_db::CrateId;
use either::Either;
use hir_expand::{
name::{AsName, Name},
- InFile,
+ HirFileId, InFile,
};
use la_arena::{Arena, ArenaMap};
use syntax::ast::{self, HasName, HasVisibility};
@@ -14,15 +14,18 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
use crate::{
body::{CfgExpander, LowerCtx},
+ builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
intern::Interned,
- item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
+ item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
+ nameres::diagnostics::DefDiagnostic,
src::HasChildSource,
src::HasSource,
trace::Trace,
type_ref::TypeRef,
visibility::RawVisibility,
- EnumId, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
+ EnumId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StructId, UnionId,
+ VariantId,
};
use cfg::CfgOptions;
@@ -31,7 +34,7 @@ use cfg::CfgOptions;
pub struct StructData {
pub name: Name,
pub variant_data: Arc<VariantData>,
- pub repr: Option<ReprKind>,
+ pub repr: Option<ReprData>,
pub visibility: RawVisibility,
}
@@ -39,6 +42,7 @@ pub struct StructData {
pub struct EnumData {
pub name: Name,
pub variants: Arena<EnumVariantData>,
+ pub repr: Option<ReprData>,
pub visibility: RawVisibility,
}
@@ -63,10 +67,19 @@ pub struct FieldData {
pub visibility: RawVisibility,
}
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub enum ReprKind {
- Packed,
- Other,
+ C,
+ BuiltinInt { builtin: Either<BuiltinInt, BuiltinUint>, is_c: bool },
+ Transparent,
+ Default,
+}
+
+#[derive(Copy, Debug, Clone, PartialEq, Eq)]
+pub struct ReprData {
+ pub kind: ReprKind,
+ pub packed: bool,
+ pub align: Option<NonZeroU32>,
}
fn repr_from_value(
@@ -74,25 +87,71 @@ fn repr_from_value(
krate: CrateId,
item_tree: &ItemTree,
of: AttrOwner,
-) -> Option<ReprKind> {
+) -> Option<ReprData> {
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
}
-fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
+fn parse_repr_tt(tt: &Subtree) -> Option<ReprData> {
match tt.delimiter {
Some(Delimiter { kind: DelimiterKind::Parenthesis, .. }) => {}
_ => return None,
}
- let mut it = tt.token_trees.iter();
- match it.next()? {
- TokenTree::Leaf(Leaf::Ident(ident)) if ident.text == "packed" => Some(ReprKind::Packed),
- _ => Some(ReprKind::Other),
+ let mut data = ReprData { kind: ReprKind::Default, packed: false, align: None };
+
+ let mut tts = tt.token_trees.iter().peekable();
+ while let Some(tt) = tts.next() {
+ if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
+ match &*ident.text {
+ "packed" => {
+ data.packed = true;
+ if let Some(TokenTree::Subtree(_)) = tts.peek() {
+ tts.next();
+ }
+ }
+ "align" => {
+ if let Some(TokenTree::Subtree(tt)) = tts.peek() {
+ tts.next();
+ if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
+ if let Ok(align) = lit.text.parse() {
+ data.align = Some(align);
+ }
+ }
+ }
+ }
+ "C" => {
+ if let ReprKind::BuiltinInt { is_c, .. } = &mut data.kind {
+ *is_c = true;
+ } else {
+ data.kind = ReprKind::C;
+ }
+ }
+ "transparent" => data.kind = ReprKind::Transparent,
+ repr => {
+ let is_c = matches!(data.kind, ReprKind::C);
+ if let Some(builtin) = BuiltinInt::from_suffix(repr)
+ .map(Either::Left)
+ .or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
+ {
+ data.kind = ReprKind::BuiltinInt { builtin, is_c };
+ }
+ }
+ }
+ }
}
+
+ Some(data)
}
impl StructData {
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
+ db.struct_data_with_diagnostics(id).0
+ }
+
+ pub(crate) fn struct_data_with_diagnostics_query(
+ db: &dyn DefDatabase,
+ id: StructId,
+ ) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -100,15 +159,35 @@ impl StructData {
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
let strukt = &item_tree[loc.id.value];
- let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
- Arc::new(StructData {
- name: strukt.name.clone(),
- variant_data: Arc::new(variant_data),
- repr,
- visibility: item_tree[strukt.visibility].clone(),
- })
+ let (variant_data, diagnostics) = lower_fields(
+ db,
+ krate,
+ loc.id.file_id(),
+ loc.container.local_id,
+ &item_tree,
+ &cfg_options,
+ &strukt.fields,
+ None,
+ );
+ (
+ Arc::new(StructData {
+ name: strukt.name.clone(),
+ variant_data: Arc::new(variant_data),
+ repr,
+ visibility: item_tree[strukt.visibility].clone(),
+ }),
+ diagnostics.into(),
+ )
}
+
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
+ db.union_data_with_diagnostics(id).0
+ }
+
+ pub(crate) fn union_data_with_diagnostics_query(
+ db: &dyn DefDatabase,
+ id: UnionId,
+ ) -> (Arc<StructData>, Arc<[DefDiagnostic]>) {
let loc = id.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
@@ -116,56 +195,98 @@ impl StructData {
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
let union = &item_tree[loc.id.value];
- let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
-
- Arc::new(StructData {
- name: union.name.clone(),
- variant_data: Arc::new(variant_data),
- repr,
- visibility: item_tree[union.visibility].clone(),
- })
+ let (variant_data, diagnostics) = lower_fields(
+ db,
+ krate,
+ loc.id.file_id(),
+ loc.container.local_id,
+ &item_tree,
+ &cfg_options,
+ &union.fields,
+ None,
+ );
+ (
+ Arc::new(StructData {
+ name: union.name.clone(),
+ variant_data: Arc::new(variant_data),
+ repr,
+ visibility: item_tree[union.visibility].clone(),
+ }),
+ diagnostics.into(),
+ )
}
}
impl EnumData {
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
+ db.enum_data_with_diagnostics(e).0
+ }
+
+ pub(crate) fn enum_data_with_diagnostics_query(
+ db: &dyn DefDatabase,
+ e: EnumId,
+ ) -> (Arc<EnumData>, Arc<[DefDiagnostic]>) {
let loc = e.lookup(db);
let krate = loc.container.krate;
let item_tree = loc.id.item_tree(db);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
+ let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
+ let mut diagnostics = Vec::new();
for tree_id in enum_.variants.clone() {
- if item_tree.attrs(db, krate, tree_id.into()).is_cfg_enabled(&cfg_options) {
- let var = &item_tree[tree_id];
- let var_data = lower_fields(
+ let attrs = item_tree.attrs(db, krate, tree_id.into());
+ let var = &item_tree[tree_id];
+ if attrs.is_cfg_enabled(&cfg_options) {
+ let (var_data, field_diagnostics) = lower_fields(
db,
krate,
+ loc.id.file_id(),
+ loc.container.local_id,
&item_tree,
&cfg_options,
&var.fields,
Some(enum_.visibility),
);
+ diagnostics.extend(field_diagnostics);
variants.alloc(EnumVariantData {
name: var.name.clone(),
variant_data: Arc::new(var_data),
});
+ } else {
+ diagnostics.push(DefDiagnostic::unconfigured_code(
+ loc.container.local_id,
+ InFile::new(loc.id.file_id(), var.ast_id.upcast()),
+ attrs.cfg().unwrap(),
+ cfg_options.clone(),
+ ))
}
}
- Arc::new(EnumData {
- name: enum_.name.clone(),
- variants,
- visibility: item_tree[enum_.visibility].clone(),
- })
+ (
+ Arc::new(EnumData {
+ name: enum_.name.clone(),
+ variants,
+ repr,
+ visibility: item_tree[enum_.visibility].clone(),
+ }),
+ diagnostics.into(),
+ )
}
pub fn variant(&self, name: &Name) -> Option<LocalEnumVariantId> {
let (id, _) = self.variants.iter().find(|(_id, data)| &data.name == name)?;
Some(id)
}
+
+ pub fn variant_body_type(&self) -> Either<BuiltinInt, BuiltinUint> {
+ match self.repr {
+ Some(ReprData { kind: ReprKind::BuiltinInt { builtin, .. }, .. }) => builtin,
+ _ => Either::Left(BuiltinInt::Isize),
+ }
+ }
}
impl HasChildSource<LocalEnumVariantId> for EnumId {
@@ -324,31 +445,64 @@ fn lower_struct(
fn lower_fields(
db: &dyn DefDatabase,
krate: CrateId,
+ current_file_id: HirFileId,
+ container: LocalModuleId,
item_tree: &ItemTree,
cfg_options: &CfgOptions,
fields: &Fields,
override_visibility: Option<RawVisibilityId>,
-) -> VariantData {
+) -> (VariantData, Vec<DefDiagnostic>) {
+ let mut diagnostics = Vec::new();
match fields {
Fields::Record(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
- if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
- arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
+ let attrs = item_tree.attrs(db, krate, field_id.into());
+ let field = &item_tree[field_id];
+ if attrs.is_cfg_enabled(cfg_options) {
+ arena.alloc(lower_field(item_tree, field, override_visibility));
+ } else {
+ diagnostics.push(DefDiagnostic::unconfigured_code(
+ container,
+ InFile::new(
+ current_file_id,
+ match field.ast_id {
+ FieldAstId::Record(it) => it.upcast(),
+ FieldAstId::Tuple(it) => it.upcast(),
+ },
+ ),
+ attrs.cfg().unwrap(),
+ cfg_options.clone(),
+ ))
}
}
- VariantData::Record(arena)
+ (VariantData::Record(arena), diagnostics)
}
Fields::Tuple(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
- if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
- arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
+ let attrs = item_tree.attrs(db, krate, field_id.into());
+ let field = &item_tree[field_id];
+ if attrs.is_cfg_enabled(cfg_options) {
+ arena.alloc(lower_field(item_tree, field, override_visibility));
+ } else {
+ diagnostics.push(DefDiagnostic::unconfigured_code(
+ container,
+ InFile::new(
+ current_file_id,
+ match field.ast_id {
+ FieldAstId::Record(it) => it.upcast(),
+ FieldAstId::Tuple(it) => it.upcast(),
+ },
+ ),
+ attrs.cfg().unwrap(),
+ cfg_options.clone(),
+ ))
}
}
- VariantData::Tuple(arena)
+ (VariantData::Tuple(arena), diagnostics)
}
- Fields::Unit => VariantData::Unit,
+ Fields::Unit => (VariantData::Unit, diagnostics),
}
}
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 22f5fb992..759f3b8c0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -27,7 +27,7 @@ use crate::{
macro_id_to_def_id,
nameres::DefMap,
path::{ModPath, Path},
- src::HasSource,
+ src::{HasChildSource, HasSource},
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, MacroId, ModuleId,
UnresolvedMacro,
};
@@ -311,7 +311,20 @@ impl Body {
DefWithBodyId::FunctionId(f) => {
let f = f.lookup(db);
let src = f.source(db);
- params = src.value.param_list();
+ params = src.value.param_list().map(|param_list| {
+ let item_tree = f.id.item_tree(db);
+ let func = &item_tree[f.id.value];
+ let krate = f.container.module(db).krate;
+ let crate_graph = db.crate_graph();
+ (
+ param_list,
+ func.params.clone().map(move |param| {
+ item_tree
+ .attrs(db, krate, param.into())
+ .is_cfg_enabled(&crate_graph[krate].cfg_options)
+ }),
+ )
+ });
(src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
}
DefWithBodyId::ConstId(c) => {
@@ -324,10 +337,17 @@ impl Body {
let src = s.source(db);
(src.file_id, s.module(db), src.value.body())
}
+ DefWithBodyId::VariantId(v) => {
+ let e = v.parent.lookup(db);
+ let src = v.parent.child_source(db);
+ let variant = &src.value[v.local_id];
+ (src.file_id, e.container, variant.expr())
+ }
};
let expander = Expander::new(db, file_id, module);
let (mut body, source_map) = Body::new(db, expander, params, body);
body.shrink_to_fit();
+
(Arc::new(body), Arc::new(source_map))
}
@@ -364,7 +384,7 @@ impl Body {
fn new(
db: &dyn DefDatabase,
expander: Expander,
- params: Option<ast::ParamList>,
+ params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
) -> (Body, BodySourceMap) {
lower::lower(db, expander, params, body)
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 3b3297f78..ccc01c3ef 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
@@ -29,8 +29,9 @@ use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
db::DefDatabase,
expr::{
- dummy_expr_id, Array, BindingAnnotation, Expr, ExprId, FloatTypeWrapper, Label, LabelId,
- Literal, MatchArm, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
+ dummy_expr_id, Array, BindingAnnotation, ClosureKind, Expr, ExprId, FloatTypeWrapper,
+ Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
+ Statement,
},
intern::Interned,
item_scope::BuiltinShadowMode,
@@ -76,7 +77,7 @@ impl<'a> LowerCtx<'a> {
pub(super) fn lower(
db: &dyn DefDatabase,
expander: Expander,
- params: Option<ast::ParamList>,
+ params: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
) -> (Body, BodySourceMap) {
ExprCollector {
@@ -97,6 +98,7 @@ pub(super) fn lower(
name_to_pat_grouping: Default::default(),
is_lowering_inside_or_pat: false,
is_lowering_assignee_expr: false,
+ is_lowering_generator: false,
}
.collect(params, body)
}
@@ -111,16 +113,19 @@ struct ExprCollector<'a> {
name_to_pat_grouping: FxHashMap<Name, Vec<PatId>>,
is_lowering_inside_or_pat: bool,
is_lowering_assignee_expr: bool,
+ is_lowering_generator: bool,
}
impl ExprCollector<'_> {
fn collect(
mut self,
- param_list: Option<ast::ParamList>,
+ param_list: Option<(ast::ParamList, impl Iterator<Item = bool>)>,
body: Option<ast::Expr>,
) -> (Body, BodySourceMap) {
- if let Some(param_list) = param_list {
- if let Some(self_param) = param_list.self_param() {
+ if let Some((param_list, mut attr_enabled)) = param_list {
+ if let Some(self_param) =
+ param_list.self_param().filter(|_| attr_enabled.next().unwrap_or(false))
+ {
let ptr = AstPtr::new(&self_param);
let param_pat = self.alloc_pat(
Pat::Bind {
@@ -136,7 +141,11 @@ impl ExprCollector<'_> {
self.body.params.push(param_pat);
}
- for pat in param_list.params().filter_map(|param| param.pat()) {
+ for pat in param_list
+ .params()
+ .zip(attr_enabled)
+ .filter_map(|(param, enabled)| param.pat().filter(|_| enabled))
+ {
let param_pat = self.collect_pat(pat);
self.body.params.push(param_pat);
}
@@ -358,6 +367,7 @@ impl ExprCollector<'_> {
self.alloc_expr(Expr::Return { expr }, syntax_ptr)
}
ast::Expr::YieldExpr(e) => {
+ self.is_lowering_generator = true;
let expr = e.expr().map(|e| self.collect_expr(e));
self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
}
@@ -459,13 +469,31 @@ impl ExprCollector<'_> {
.ret_type()
.and_then(|r| r.ty())
.map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
+
+ let prev_is_lowering_generator = self.is_lowering_generator;
+ self.is_lowering_generator = false;
+
let body = self.collect_expr_opt(e.body());
+
+ let closure_kind = if self.is_lowering_generator {
+ let movability = if e.static_token().is_some() {
+ Movability::Static
+ } else {
+ Movability::Movable
+ };
+ ClosureKind::Generator(movability)
+ } else {
+ ClosureKind::Closure
+ };
+ self.is_lowering_generator = prev_is_lowering_generator;
+
self.alloc_expr(
Expr::Closure {
args: args.into(),
arg_types: arg_types.into(),
ret_type,
body,
+ closure_kind,
},
syntax_ptr,
)
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 f2fed9544..162d173d5 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
@@ -2,8 +2,10 @@
use std::fmt::{self, Write};
+use syntax::ast::HasName;
+
use crate::{
- expr::{Array, BindingAnnotation, Literal, Statement},
+ expr::{Array, BindingAnnotation, ClosureKind, Literal, Movability, Statement},
pretty::{print_generic_args, print_path, print_type_ref},
type_ref::TypeRef,
};
@@ -32,6 +34,16 @@ pub(super) fn print_body_hir(db: &dyn DefDatabase, body: &Body, owner: DefWithBo
};
format!("const {} = ", name)
}
+ DefWithBodyId::VariantId(it) => {
+ needs_semi = false;
+ let src = it.parent.child_source(db);
+ let variant = &src.value[it.local_id];
+ let name = match &variant.name() {
+ Some(name) => name.to_string(),
+ None => "_".to_string(),
+ };
+ format!("{}", name)
+ }
};
let mut p = Printer { body, buf: header, indent_level: 0, needs_indent: false };
@@ -350,7 +362,10 @@ impl<'a> Printer<'a> {
self.print_expr(*index);
w!(self, "]");
}
- Expr::Closure { args, arg_types, ret_type, body } => {
+ Expr::Closure { args, arg_types, ret_type, body, closure_kind } => {
+ if let ClosureKind::Generator(Movability::Static) = closure_kind {
+ w!(self, "static ");
+ }
w!(self, "|");
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
if i != 0 {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
index 0e7ce5f85..39581b33a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
@@ -379,7 +379,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
// ==========================================================================
rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
- rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
gated!(
alloc_error_handler, Normal, template!(Word), WarnFollowing,
experimental!(alloc_error_handler)
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 5b1435e8f..bb1316525 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
@@ -198,6 +198,10 @@ impl ChildBySource for EnumId {
impl ChildBySource for DefWithBodyId {
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap, file_id: HirFileId) {
let body = db.body(*self);
+ if let &DefWithBodyId::VariantId(v) = self {
+ VariantId::EnumVariantId(v).child_by_source_to(db, res, file_id)
+ }
+
for (_, def_map) in body.blocks(db) {
// All block expressions are merged into the same map, because they logically all add
// inner items to the containing `DefWithBodyId`.
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 631ae3cf1..2dc69b00a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -219,7 +219,7 @@ impl TraitData {
pub(crate) fn trait_data_with_diagnostics_query(
db: &dyn DefDatabase,
tr: TraitId,
- ) -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>) {
+ ) -> (Arc<TraitData>, Arc<[DefDiagnostic]>) {
let tr_loc @ ItemLoc { container: module_id, id: tree_id } = tr.lookup(db);
let item_tree = tree_id.item_tree(db);
let tr_def = &item_tree[tree_id.value];
@@ -251,7 +251,7 @@ impl TraitData {
visibility,
skip_array_during_method_dispatch,
}),
- Arc::new(diagnostics),
+ diagnostics.into(),
)
}
@@ -299,7 +299,7 @@ impl ImplData {
pub(crate) fn impl_data_with_diagnostics_query(
db: &dyn DefDatabase,
id: ImplId,
- ) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>) {
+ ) -> (Arc<ImplData>, Arc<[DefDiagnostic]>) {
let _p = profile::span("impl_data_with_diagnostics_query");
let ItemLoc { container: module_id, id: tree_id } = id.lookup(db);
@@ -318,7 +318,7 @@ impl ImplData {
(
Arc::new(ImplData { target_trait, self_ty, items, is_negative, attribute_calls }),
- Arc::new(diagnostics),
+ diagnostics.into(),
)
}
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 40b2f734b..431c82554 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -97,24 +97,33 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
#[salsa::invoke(StructData::struct_data_query)]
fn struct_data(&self, id: StructId) -> Arc<StructData>;
+ #[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
+ fn struct_data_with_diagnostics(&self, id: StructId)
+ -> (Arc<StructData>, Arc<[DefDiagnostic]>);
+
#[salsa::invoke(StructData::union_data_query)]
fn union_data(&self, id: UnionId) -> Arc<StructData>;
+ #[salsa::invoke(StructData::union_data_with_diagnostics_query)]
+ fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, Arc<[DefDiagnostic]>);
+
#[salsa::invoke(EnumData::enum_data_query)]
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
+ #[salsa::invoke(EnumData::enum_data_with_diagnostics_query)]
+ fn enum_data_with_diagnostics(&self, e: EnumId) -> (Arc<EnumData>, Arc<[DefDiagnostic]>);
+
#[salsa::invoke(ImplData::impl_data_query)]
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
- fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<Vec<DefDiagnostic>>);
+ fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, Arc<[DefDiagnostic]>);
#[salsa::invoke(TraitData::trait_data_query)]
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
- fn trait_data_with_diagnostics(&self, tr: TraitId)
- -> (Arc<TraitData>, Arc<Vec<DefDiagnostic>>);
+ fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, Arc<[DefDiagnostic]>);
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
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 419d3feec..162646550 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expr.rs
@@ -198,6 +198,7 @@ pub enum Expr {
arg_types: Box<[Option<Interned<TypeRef>>]>,
ret_type: Option<Interned<TypeRef>>,
body: ExprId,
+ closure_kind: ClosureKind,
},
Tuple {
exprs: Box<[ExprId]>,
@@ -211,6 +212,18 @@ pub enum Expr {
Underscore,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum ClosureKind {
+ Closure,
+ Generator(Movability),
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Movability {
+ Static,
+ Movable,
+}
+
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Array {
ElementList { elements: Box<[ExprId]>, is_assignee_expr: bool },
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 89e961f84..c70e6fdcc 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
@@ -1,6 +1,6 @@
//! An algorithm to find a path to refer to a certain item.
-use std::iter;
+use std::{cmp::Ordering, iter};
use hir_expand::name::{known, AsName, Name};
use rustc_hash::FxHashSet;
@@ -16,9 +16,14 @@ use crate::{
/// Find a path that can be used to refer to a certain item. This can depend on
/// *from where* you're referring to the item, hence the `from` parameter.
-pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
+pub fn find_path(
+ db: &dyn DefDatabase,
+ item: ItemInNs,
+ from: ModuleId,
+ prefer_no_std: bool,
+) -> Option<ModPath> {
let _p = profile::span("find_path");
- find_path_inner(db, item, from, None)
+ find_path_inner(db, item, from, None, prefer_no_std)
}
pub fn find_path_prefixed(
@@ -26,47 +31,14 @@ pub fn find_path_prefixed(
item: ItemInNs,
from: ModuleId,
prefix_kind: PrefixKind,
+ prefer_no_std: bool,
) -> Option<ModPath> {
let _p = profile::span("find_path_prefixed");
- find_path_inner(db, item, from, Some(prefix_kind))
+ find_path_inner(db, item, from, Some(prefix_kind), prefer_no_std)
}
const MAX_PATH_LEN: usize = 15;
-trait ModPathExt {
- fn starts_with_std(&self) -> bool;
- fn can_start_with_std(&self) -> bool;
-}
-
-impl ModPathExt for ModPath {
- fn starts_with_std(&self) -> bool {
- self.segments().first() == Some(&known::std)
- }
-
- // Can we replace the first segment with `std::` and still get a valid, identical path?
- fn can_start_with_std(&self) -> bool {
- let first_segment = self.segments().first();
- first_segment == Some(&known::alloc) || first_segment == Some(&known::core)
- }
-}
-
-fn check_self_super(def_map: &DefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
- if item == ItemInNs::Types(from.into()) {
- // - if the item is the module we're in, use `self`
- Some(ModPath::from_segments(PathKind::Super(0), None))
- } else if let Some(parent_id) = def_map[from.local_id].parent {
- // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
- let parent_id = def_map.module_id(parent_id);
- if item == ItemInNs::Types(ModuleDefId::ModuleId(parent_id)) {
- Some(ModPath::from_segments(PathKind::Super(1), None))
- } else {
- None
- }
- } else {
- None
- }
-}
-
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum PrefixKind {
/// Causes paths to always start with either `self`, `super`, `crate` or a crate-name.
@@ -94,135 +66,247 @@ impl PrefixKind {
self == &PrefixKind::ByCrate
}
}
+
/// Attempts to find a path to refer to the given `item` visible from the `from` ModuleId
fn find_path_inner(
db: &dyn DefDatabase,
item: ItemInNs,
from: ModuleId,
prefixed: Option<PrefixKind>,
+ prefer_no_std: bool,
) -> Option<ModPath> {
- // FIXME: Do fast path for std/core libs?
+ // - if the item is a builtin, it's in scope
+ if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
+ return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name())));
+ }
- let mut visited_modules = FxHashSet::default();
let def_map = from.def_map(db);
- find_path_inner_(db, &def_map, from, item, MAX_PATH_LEN, prefixed, &mut visited_modules)
+ let crate_root = def_map.crate_root(db);
+ // - if the item is a module, jump straight to module search
+ if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
+ let mut visited_modules = FxHashSet::default();
+ return find_path_for_module(
+ db,
+ &def_map,
+ &mut visited_modules,
+ crate_root,
+ from,
+ module_id,
+ MAX_PATH_LEN,
+ prefixed,
+ prefer_no_std || db.crate_supports_no_std(crate_root.krate),
+ );
+ }
+
+ // - if the item is already in scope, return the name under which it is
+ let scope_name = find_in_scope(db, &def_map, from, item);
+ if prefixed.is_none() {
+ if let Some(scope_name) = scope_name {
+ return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name)));
+ }
+ }
+
+ // - if the item is in the prelude, return the name from there
+ if let Some(value) = find_in_prelude(db, &crate_root.def_map(db), item, from) {
+ return value;
+ }
+
+ if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
+ // - if the item is an enum variant, refer to it via the enum
+ if let Some(mut path) = find_path_inner(
+ db,
+ ItemInNs::Types(variant.parent.into()),
+ from,
+ prefixed,
+ prefer_no_std,
+ ) {
+ let data = db.enum_data(variant.parent);
+ path.push_segment(data.variants[variant.local_id].name.clone());
+ return Some(path);
+ }
+ // If this doesn't work, it seems we have no way of referring to the
+ // enum; that's very weird, but there might still be a reexport of the
+ // variant somewhere
+ }
+
+ let mut visited_modules = FxHashSet::default();
+
+ calculate_best_path(
+ db,
+ &def_map,
+ &mut visited_modules,
+ crate_root,
+ MAX_PATH_LEN,
+ item,
+ from,
+ prefixed,
+ prefer_no_std || db.crate_supports_no_std(crate_root.krate),
+ scope_name,
+ )
}
-fn find_path_inner_(
+fn find_path_for_module(
db: &dyn DefDatabase,
def_map: &DefMap,
+ visited_modules: &mut FxHashSet<ModuleId>,
+ crate_root: ModuleId,
from: ModuleId,
- item: ItemInNs,
+ module_id: ModuleId,
max_len: usize,
- mut prefixed: Option<PrefixKind>,
- visited_modules: &mut FxHashSet<ModuleId>,
+ prefixed: Option<PrefixKind>,
+ prefer_no_std: bool,
) -> Option<ModPath> {
if max_len == 0 {
return None;
}
// Base cases:
-
// - if the item is already in scope, return the name under which it is
- let scope_name = def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
- def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone())
- });
+ let scope_name = find_in_scope(db, def_map, from, ItemInNs::Types(module_id.into()));
if prefixed.is_none() {
if let Some(scope_name) = scope_name {
return Some(ModPath::from_segments(PathKind::Plain, Some(scope_name)));
}
}
- // - if the item is a builtin, it's in scope
- if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
- return Some(ModPath::from_segments(PathKind::Plain, Some(builtin.as_name())));
- }
-
// - if the item is the crate root, return `crate`
- let crate_root = def_map.crate_root(db);
- if item == ItemInNs::Types(ModuleDefId::ModuleId(crate_root)) {
+ if module_id == crate_root {
return Some(ModPath::from_segments(PathKind::Crate, None));
}
+ // - if relative paths are fine, check if we are searching for a parent
if prefixed.filter(PrefixKind::is_absolute).is_none() {
- if let modpath @ Some(_) = check_self_super(&def_map, item, from) {
+ if let modpath @ Some(_) = find_self_super(&def_map, module_id, from) {
return modpath;
}
}
// - if the item is the crate root of a dependency crate, return the name from the extern prelude
let root_def_map = crate_root.def_map(db);
- if let ItemInNs::Types(ModuleDefId::ModuleId(item)) = item {
- for (name, &def_id) in root_def_map.extern_prelude() {
- if item == def_id {
- let name = scope_name.unwrap_or_else(|| name.clone());
-
- let name_already_occupied_in_type_ns = def_map
- .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
- def_map[local_id]
- .scope
- .type_(&name)
- .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id))
- })
- .is_some();
- let kind = if name_already_occupied_in_type_ns {
- cov_mark::hit!(ambiguous_crate_start);
- PathKind::Abs
- } else {
- PathKind::Plain
- };
- return Some(ModPath::from_segments(kind, Some(name)));
- }
+ for (name, &def_id) in root_def_map.extern_prelude() {
+ if module_id == def_id {
+ let name = scope_name.unwrap_or_else(|| name.clone());
+
+ let name_already_occupied_in_type_ns = def_map
+ .with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
+ def_map[local_id]
+ .scope
+ .type_(&name)
+ .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id))
+ })
+ .is_some();
+ let kind = if name_already_occupied_in_type_ns {
+ cov_mark::hit!(ambiguous_crate_start);
+ PathKind::Abs
+ } else {
+ PathKind::Plain
+ };
+ return Some(ModPath::from_segments(kind, Some(name)));
}
}
- // - if the item is in the prelude, return the name from there
+ if let Some(value) = find_in_prelude(db, &root_def_map, ItemInNs::Types(module_id.into()), from)
+ {
+ return value;
+ }
+ calculate_best_path(
+ db,
+ def_map,
+ visited_modules,
+ crate_root,
+ max_len,
+ ItemInNs::Types(module_id.into()),
+ from,
+ prefixed,
+ prefer_no_std,
+ scope_name,
+ )
+}
+
+fn find_in_scope(
+ db: &dyn DefDatabase,
+ def_map: &DefMap,
+ from: ModuleId,
+ item: ItemInNs,
+) -> Option<Name> {
+ def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
+ def_map[local_id].scope.name_of(item).map(|(name, _)| name.clone())
+ })
+}
+
+fn find_in_prelude(
+ db: &dyn DefDatabase,
+ root_def_map: &DefMap,
+ item: ItemInNs,
+ from: ModuleId,
+) -> Option<Option<ModPath>> {
if let Some(prelude_module) = root_def_map.prelude() {
// Preludes in block DefMaps are ignored, only the crate DefMap is searched
let prelude_def_map = prelude_module.def_map(db);
let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
if let Some((name, vis)) = prelude_scope.name_of(item) {
if vis.is_visible_from(db, from) {
- return Some(ModPath::from_segments(PathKind::Plain, Some(name.clone())));
+ return Some(Some(ModPath::from_segments(PathKind::Plain, Some(name.clone()))));
}
}
}
+ None
+}
- // Recursive case:
- // - if the item is an enum variant, refer to it via the enum
- if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
- if let Some(mut path) = find_path(db, ItemInNs::Types(variant.parent.into()), from) {
- let data = db.enum_data(variant.parent);
- path.push_segment(data.variants[variant.local_id].name.clone());
- return Some(path);
+fn find_self_super(def_map: &DefMap, item: ModuleId, from: ModuleId) -> Option<ModPath> {
+ if item == from {
+ // - if the item is the module we're in, use `self`
+ Some(ModPath::from_segments(PathKind::Super(0), None))
+ } else if let Some(parent_id) = def_map[from.local_id].parent {
+ // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
+ let parent_id = def_map.module_id(parent_id);
+ if item == parent_id {
+ Some(ModPath::from_segments(PathKind::Super(1), None))
+ } else {
+ None
}
- // If this doesn't work, it seems we have no way of referring to the
- // enum; that's very weird, but there might still be a reexport of the
- // variant somewhere
+ } else {
+ None
}
+}
- // - otherwise, look for modules containing (reexporting) it and import it from one of those
- let prefer_no_std = db.crate_supports_no_std(crate_root.krate);
+fn calculate_best_path(
+ db: &dyn DefDatabase,
+ def_map: &DefMap,
+ visited_modules: &mut FxHashSet<ModuleId>,
+ crate_root: ModuleId,
+ max_len: usize,
+ item: ItemInNs,
+ from: ModuleId,
+ mut prefixed: Option<PrefixKind>,
+ prefer_no_std: bool,
+ scope_name: Option<Name>,
+) -> Option<ModPath> {
+ if max_len <= 1 {
+ return None;
+ }
let mut best_path = None;
- let mut best_path_len = max_len;
-
+ // Recursive case:
+ // - otherwise, look for modules containing (reexporting) it and import it from one of those
if item.krate(db) == Some(from.krate) {
+ let mut best_path_len = max_len;
// Item was defined in the same crate that wants to import it. It cannot be found in any
// dependency in this case.
- // FIXME: this should have a fast path that doesn't look through the prelude again?
for (module_id, name) in find_local_import_locations(db, item, from) {
if !visited_modules.insert(module_id) {
cov_mark::hit!(recursive_imports);
continue;
}
- if let Some(mut path) = find_path_inner_(
+ if let Some(mut path) = find_path_for_module(
db,
def_map,
+ visited_modules,
+ crate_root,
from,
- ItemInNs::Types(ModuleDefId::ModuleId(module_id)),
+ module_id,
best_path_len - 1,
prefixed,
- visited_modules,
+ prefer_no_std,
) {
path.push_segment(name);
@@ -245,14 +329,16 @@ fn find_path_inner_(
import_map.import_info_for(item).and_then(|info| {
// Determine best path for containing module and append last segment from `info`.
// FIXME: we should guide this to look up the path locally, or from the same crate again?
- let mut path = find_path_inner_(
+ let mut path = find_path_for_module(
db,
def_map,
+ visited_modules,
+ crate_root,
from,
- ItemInNs::Types(ModuleDefId::ModuleId(info.container)),
- best_path_len - 1,
+ info.container,
+ max_len - 1,
prefixed,
- visited_modules,
+ prefer_no_std,
)?;
cov_mark::hit!(partially_imported);
path.push_segment(info.path.segments.last()?.clone());
@@ -268,16 +354,12 @@ fn find_path_inner_(
best_path = Some(new_path);
}
}
-
- // If the item is declared inside a block expression, don't use a prefix, as we don't handle
- // that correctly (FIXME).
- if let Some(item_module) = item.as_module_def_id().and_then(|did| did.module(db)) {
- if item_module.def_map(db).block_id().is_some() && prefixed.is_some() {
+ if let Some(module) = item.module(db) {
+ if module.def_map(db).block_id().is_some() && prefixed.is_some() {
cov_mark::hit!(prefixed_in_block_expression);
prefixed = Some(PrefixKind::Plain);
}
}
-
match prefixed.map(PrefixKind::prefix) {
Some(prefix) => best_path.or_else(|| {
scope_name.map(|scope_name| ModPath::from_segments(prefix, Some(scope_name)))
@@ -287,29 +369,48 @@ fn find_path_inner_(
}
fn select_best_path(old_path: ModPath, new_path: ModPath, prefer_no_std: bool) -> ModPath {
- if old_path.starts_with_std() && new_path.can_start_with_std() {
- if prefer_no_std {
- cov_mark::hit!(prefer_no_std_paths);
- new_path
- } else {
- cov_mark::hit!(prefer_std_paths);
- old_path
+ const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
+ match (old_path.segments().first(), new_path.segments().first()) {
+ (Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => {
+ let rank = match prefer_no_std {
+ false => |name: &Name| match name {
+ name if name == &known::core => 0,
+ name if name == &known::alloc => 0,
+ name if name == &known::std => 1,
+ _ => unreachable!(),
+ },
+ true => |name: &Name| match name {
+ name if name == &known::core => 2,
+ name if name == &known::alloc => 1,
+ name if name == &known::std => 0,
+ _ => unreachable!(),
+ },
+ };
+ let nrank = rank(new);
+ let orank = rank(old);
+ match nrank.cmp(&orank) {
+ Ordering::Less => old_path,
+ Ordering::Equal => {
+ if new_path.len() < old_path.len() {
+ new_path
+ } else {
+ old_path
+ }
+ }
+ Ordering::Greater => new_path,
+ }
}
- } else if new_path.starts_with_std() && old_path.can_start_with_std() {
- if prefer_no_std {
- cov_mark::hit!(prefer_no_std_paths);
- old_path
- } else {
- cov_mark::hit!(prefer_std_paths);
- new_path
+ _ => {
+ if new_path.len() < old_path.len() {
+ new_path
+ } else {
+ old_path
+ }
}
- } else if new_path.len() < old_path.len() {
- new_path
- } else {
- old_path
}
}
+// FIXME: Remove allocations
/// Finds locations in `from.krate` from which `item` can be imported by `from`.
fn find_local_import_locations(
db: &dyn DefDatabase,
@@ -428,7 +529,8 @@ mod tests {
.take_types()
.unwrap();
- let found_path = find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind);
+ let found_path =
+ find_path_inner(&db, ItemInNs::Types(resolved), module, prefix_kind, false);
assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind);
}
@@ -468,8 +570,8 @@ $0
"#,
"E::A",
"E::A",
- "E::A",
- "E::A",
+ "crate::E::A",
+ "self::E::A",
);
}
@@ -788,7 +890,6 @@ pub use super::foo;
#[test]
fn prefer_std_paths_over_alloc() {
- cov_mark::check!(prefer_std_paths);
check_found_path(
r#"
//- /main.rs crate:main deps:alloc,std
@@ -813,7 +914,6 @@ pub mod sync {
#[test]
fn prefer_core_paths_over_std() {
- cov_mark::check!(prefer_no_std_paths);
check_found_path(
r#"
//- /main.rs crate:main deps:core,std
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 a11a92204..7721221c4 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
@@ -18,7 +18,7 @@ use crate::{
ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
};
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
pub(crate) enum ImportType {
Glob,
Named,
@@ -302,13 +302,13 @@ impl ItemScope {
$changed = true;
}
Entry::Occupied(mut entry)
- if $glob_imports.$field.contains(&$lookup)
- && matches!($def_import_type, ImportType::Named) =>
+ if matches!($def_import_type, ImportType::Named) =>
{
- cov_mark::hit!(import_shadowed);
- $glob_imports.$field.remove(&$lookup);
- entry.insert(fld);
- $changed = true;
+ if $glob_imports.$field.remove(&$lookup) {
+ cov_mark::hit!(import_shadowed);
+ entry.insert(fld);
+ $changed = true;
+ }
}
_ => {}
}
@@ -457,8 +457,15 @@ impl ItemInNs {
/// Returns the crate defining this item (or `None` if `self` is built-in).
pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
match self {
- ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate),
+ ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db).map(|m| m.krate),
ItemInNs::Macros(id) => Some(id.module(db).krate),
}
}
+
+ pub fn module(&self, db: &dyn DefDatabase) -> Option<ModuleId> {
+ match self {
+ ItemInNs::Types(id) | ItemInNs::Values(id) => id.module(db),
+ ItemInNs::Macros(id) => Some(id.module(db)),
+ }
+ }
}
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 3342d4db4..570344596 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
@@ -943,6 +943,7 @@ impl AssocItem {
pub struct Variant {
pub name: Name,
pub fields: Fields,
+ pub ast_id: FileAstId<ast::Variant>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -952,10 +953,17 @@ pub enum Fields {
Unit,
}
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum FieldAstId {
+ Record(FileAstId<ast::RecordField>),
+ Tuple(FileAstId<ast::TupleField>),
+}
+
/// A single field of an enum variant or struct
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Field {
pub name: Name,
pub type_ref: Interned<TypeRef>,
pub visibility: RawVisibilityId,
+ pub ast_id: FieldAstId,
}
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 7f2551e94..077a1b619 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
@@ -184,7 +184,8 @@ impl<'a> Ctx<'a> {
let name = field.name()?.as_name();
let visibility = self.lower_visibility(field);
let type_ref = self.lower_type_ref_opt(field.ty());
- let res = Field { name, type_ref, visibility };
+ let ast_id = FieldAstId::Record(self.source_ast_id_map.ast_id(field));
+ let res = Field { name, type_ref, visibility, ast_id };
Some(res)
}
@@ -203,7 +204,8 @@ impl<'a> Ctx<'a> {
let name = Name::new_tuple_field(idx);
let visibility = self.lower_visibility(field);
let type_ref = self.lower_type_ref_opt(field.ty());
- Field { name, type_ref, visibility }
+ let ast_id = FieldAstId::Tuple(self.source_ast_id_map.ast_id(field));
+ Field { name, type_ref, visibility, ast_id }
}
fn lower_union(&mut self, union: &ast::Union) -> Option<FileItemTreeId<Union>> {
@@ -247,7 +249,8 @@ impl<'a> Ctx<'a> {
fn lower_variant(&mut self, variant: &ast::Variant) -> Option<Variant> {
let name = variant.name()?.as_name();
let fields = self.lower_fields(&variant.kind());
- let res = Variant { name, fields };
+ let ast_id = self.source_ast_id_map.ast_id(variant);
+ let res = Variant { name, fields, ast_id };
Some(res)
}
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 34dd817fd..da1643152 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
@@ -115,7 +115,7 @@ impl<'a> Printer<'a> {
w!(self, "{{");
self.indented(|this| {
for field in fields.clone() {
- let Field { visibility, name, type_ref } = &this.tree[field];
+ let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
this.print_attrs_of(field);
this.print_visibility(*visibility);
w!(this, "{}: ", name);
@@ -129,7 +129,7 @@ impl<'a> Printer<'a> {
w!(self, "(");
self.indented(|this| {
for field in fields.clone() {
- let Field { visibility, name, type_ref } = &this.tree[field];
+ let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
this.print_attrs_of(field);
this.print_visibility(*visibility);
w!(this, "{}: ", name);
@@ -323,7 +323,7 @@ impl<'a> Printer<'a> {
self.print_where_clause_and_opening_brace(generic_params);
self.indented(|this| {
for variant in variants.clone() {
- let Variant { name, fields } = &this.tree[variant];
+ let Variant { name, fields, ast_id: _ } = &this.tree[variant];
this.print_attrs_of(variant);
w!(this, "{}", name);
this.print_fields(fields);
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 32ebfda4f..5c7aa7234 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -474,16 +474,24 @@ pub enum DefWithBodyId {
FunctionId(FunctionId),
StaticId(StaticId),
ConstId(ConstId),
+ VariantId(EnumVariantId),
}
impl_from!(FunctionId, ConstId, StaticId for DefWithBodyId);
+impl From<EnumVariantId> for DefWithBodyId {
+ fn from(id: EnumVariantId) -> Self {
+ DefWithBodyId::VariantId(id)
+ }
+}
+
impl DefWithBodyId {
pub fn as_generic_def_id(self) -> Option<GenericDefId> {
match self {
DefWithBodyId::FunctionId(f) => Some(f.into()),
DefWithBodyId::StaticId(_) => None,
DefWithBodyId::ConstId(c) => Some(c.into()),
+ DefWithBodyId::VariantId(c) => Some(c.into()),
}
}
}
@@ -681,6 +689,7 @@ impl HasModule for DefWithBodyId {
DefWithBodyId::FunctionId(it) => it.lookup(db).module(db),
DefWithBodyId::StaticId(it) => it.lookup(db).module(db),
DefWithBodyId::ConstId(it) => it.lookup(db).module(db),
+ DefWithBodyId::VariantId(it) => it.parent.lookup(db).container,
}
}
}
@@ -691,6 +700,7 @@ impl DefWithBodyId {
DefWithBodyId::FunctionId(it) => it.lookup(db).id.value.into(),
DefWithBodyId::StaticId(it) => it.lookup(db).id.value.into(),
DefWithBodyId::ConstId(it) => it.lookup(db).id.value.into(),
+ DefWithBodyId::VariantId(it) => it.parent.lookup(db).id.value.into(),
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
index 6819e9114..fafcde25a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
@@ -12,11 +12,11 @@ fn test_copy_expand_simple() {
#[derive(Copy)]
struct Foo;
"#,
- expect![[r##"
+ expect![[r#"
#[derive(Copy)]
struct Foo;
-impl < > core::marker::Copy for Foo< > {}"##]],
+impl < > core::marker::Copy for Foo< > {}"#]],
);
}
@@ -33,7 +33,7 @@ macro Copy {}
#[derive(Copy)]
struct Foo;
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro derive {}
#[rustc_builtin_macro]
@@ -41,7 +41,7 @@ macro Copy {}
#[derive(Copy)]
struct Foo;
-impl < > crate ::marker::Copy for Foo< > {}"##]],
+impl < > crate ::marker::Copy for Foo< > {}"#]],
);
}
@@ -53,11 +53,11 @@ fn test_copy_expand_with_type_params() {
#[derive(Copy)]
struct Foo<A, B>;
"#,
- expect![[r##"
+ expect![[r#"
#[derive(Copy)]
struct Foo<A, B>;
-impl <T0: core::marker::Copy, T1: core::marker::Copy> core::marker::Copy for Foo<T0, T1> {}"##]],
+impl <T0: core::marker::Copy, T1: core::marker::Copy, > core::marker::Copy for Foo<T0, T1, > {}"#]],
);
}
@@ -70,11 +70,11 @@ fn test_copy_expand_with_lifetimes() {
#[derive(Copy)]
struct Foo<A, B, 'a, 'b>;
"#,
- expect![[r##"
+ expect![[r#"
#[derive(Copy)]
struct Foo<A, B, 'a, 'b>;
-impl <T0: core::marker::Copy, T1: core::marker::Copy> core::marker::Copy for Foo<T0, T1> {}"##]],
+impl <T0: core::marker::Copy, T1: core::marker::Copy, > core::marker::Copy for Foo<T0, T1, > {}"#]],
);
}
@@ -86,10 +86,26 @@ fn test_clone_expand() {
#[derive(Clone)]
struct Foo<A, B>;
"#,
- expect![[r##"
+ expect![[r#"
#[derive(Clone)]
struct Foo<A, B>;
-impl <T0: core::clone::Clone, T1: core::clone::Clone> core::clone::Clone for Foo<T0, T1> {}"##]],
+impl <T0: core::clone::Clone, T1: core::clone::Clone, > core::clone::Clone for Foo<T0, T1, > {}"#]],
+ );
+}
+
+#[test]
+fn test_clone_expand_with_const_generics() {
+ check(
+ r#"
+//- minicore: derive, clone
+#[derive(Clone)]
+struct Foo<const X: usize, T>(u32);
+"#,
+ expect![[r#"
+#[derive(Clone)]
+struct Foo<const X: usize, T>(u32);
+
+impl <const T0: usize, T1: core::clone::Clone, > core::clone::Clone for Foo<T0, T1, > {}"#]],
);
}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 4f626105a..c04cd1651 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -93,12 +93,12 @@ macro_rules! option_env {() => {}}
fn main() { option_env!("TEST_ENV_VAR"); }
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! option_env {() => {}}
-fn main() { std::option::Option::None:: < &str>; }
-"##]],
+fn main() { $crate::option::Option::None:: < &str>; }
+"#]],
);
}
@@ -191,7 +191,7 @@ fn main() {
format_args!("{} {:?}", arg1(a, b, c), arg2);
}
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! format_args {
($fmt:expr) => ({ /* compiler built-in */ });
@@ -199,9 +199,9 @@ macro_rules! format_args {
}
fn main() {
- std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a, b, c)), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(arg2), std::fmt::Display::fmt), ]);
+ $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(arg1(a, b, c)), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(arg2), $crate::fmt::Display::fmt), ]);
}
-"##]],
+"#]],
);
}
@@ -219,7 +219,7 @@ fn main() {
format_args!("{} {:?}", a::<A,B>(), b);
}
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! format_args {
($fmt:expr) => ({ /* compiler built-in */ });
@@ -227,9 +227,9 @@ macro_rules! format_args {
}
fn main() {
- std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A, B>()), std::fmt::Display::fmt), std::fmt::ArgumentV1::new(&(b), std::fmt::Display::fmt), ]);
+ $crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a::<A, B>()), $crate::fmt::Display::fmt), $crate::fmt::ArgumentV1::new(&(b), $crate::fmt::Display::fmt), ]);
}
-"##]],
+"#]],
);
}
@@ -248,7 +248,7 @@ fn main() {
format_args!/*+errors*/("{} {:?}", a.);
}
"#,
- expect![[r##"
+ expect![[r#"
#[rustc_builtin_macro]
macro_rules! format_args {
($fmt:expr) => ({ /* compiler built-in */ });
@@ -258,9 +258,9 @@ macro_rules! format_args {
fn main() {
let _ =
/* parse error: expected field name or number */
-std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a.), std::fmt::Display::fmt), ]);
+$crate::fmt::Arguments::new_v1(&[], &[$crate::fmt::ArgumentV1::new(&(a.), $crate::fmt::Display::fmt), ]);
}
-"##]],
+"#]],
);
}
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 495bbe457..9ffc21881 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
@@ -534,6 +534,7 @@ impl DefCollector<'_> {
match per_ns.types {
Some((ModuleDefId::ModuleId(m), _)) => {
self.def_map.prelude = Some(m);
+ break;
}
types => {
tracing::debug!(
@@ -2121,7 +2122,7 @@ impl ModCollector<'_, '_> {
fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
let ast_id = item.ast_id(self.item_tree);
- let ast_id = InFile::new(self.file_id(), ast_id);
+ let ast_id = InFile::new(self.file_id(), ast_id.upcast());
self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id,
ast_id,
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 ed7e920fd..066142291 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
@@ -4,7 +4,7 @@ use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use hir_expand::MacroCallKind;
use la_arena::Idx;
-use syntax::ast;
+use syntax::ast::{self, AnyHasAttrs};
use crate::{
attr::AttrId,
@@ -22,7 +22,7 @@ pub enum DefDiagnosticKind {
UnresolvedImport { id: ItemTreeId<item_tree::Import>, index: Idx<ast::UseTree> },
- UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
+ UnconfiguredCode { ast: AstId<AnyHasAttrs>, cfg: CfgExpr, opts: CfgOptions },
UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
@@ -75,7 +75,7 @@ impl DefDiagnostic {
pub fn unconfigured_code(
container: LocalModuleId,
- ast: AstId<ast::Item>,
+ ast: AstId<ast::AnyHasAttrs>,
cfg: CfgExpr,
opts: CfgOptions,
) -> Self {
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 8aa5973ca..070f68371 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -839,6 +839,7 @@ impl HasResolver for DefWithBodyId {
DefWithBodyId::ConstId(c) => c.resolver(db),
DefWithBodyId::FunctionId(f) => f.resolver(db),
DefWithBodyId::StaticId(s) => s.resolver(db),
+ DefWithBodyId::VariantId(v) => v.parent.resolver(db),
}
}
}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index dfd470ffc..3359c99b3 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -15,11 +15,11 @@ tracing = "0.1.35"
either = "1.7.0"
rustc-hash = "1.1.0"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-itertools = "0.10.3"
+itertools = "0.10.5"
hashbrown = { version = "0.12.1", features = [
"inline-more",
], default-features = false }
-smallvec = { version = "1.9.0", features = ["const_new"] }
+smallvec = { version = "1.10.0", features = ["const_new"] }
stdx = { path = "../stdx", version = "0.0.0" }
base-db = { path = "../base-db", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs
index 11c0a6764..2b27db0e9 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/ast_id_map.rs
@@ -93,7 +93,12 @@ impl AstIdMap {
// trait does not change ids of top-level items, which helps caching.
bdfs(node, |it| {
let kind = it.kind();
- if ast::Item::can_cast(kind) || ast::BlockExpr::can_cast(kind) {
+ if ast::Item::can_cast(kind)
+ || ast::BlockExpr::can_cast(kind)
+ || ast::Variant::can_cast(kind)
+ || ast::RecordField::can_cast(kind)
+ || ast::TupleField::can_cast(kind)
+ {
res.alloc(&it);
true
} else {
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 79989bc2e..8966047c9 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
@@ -60,7 +60,8 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option<BuiltinDeriveExpander>
struct BasicAdtInfo {
name: tt::Ident,
- type_or_const_params: usize,
+ /// `Some(ty)` if it's a const param of type `ty`, `None` if it's a type param.
+ param_types: Vec<Option<tt::Subtree>>,
}
fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
@@ -92,50 +93,22 @@ 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 type_or_const_params =
- params.map_or(0, |type_param_list| type_param_list.type_or_const_params().count());
- Ok(BasicAdtInfo { name: name_token, type_or_const_params })
-}
-
-fn make_type_args(n: usize, bound: Vec<tt::TokenTree>) -> Vec<tt::TokenTree> {
- let mut result = Vec::<tt::TokenTree>::with_capacity(n * 2);
- result.push(
- tt::Leaf::Punct(tt::Punct {
- char: '<',
- spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
- })
- .into(),
- );
- for i in 0..n {
- if i > 0 {
- result.push(
- tt::Leaf::Punct(tt::Punct {
- char: ',',
- spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
- })
- .into(),
- );
- }
- result.push(
- tt::Leaf::Ident(tt::Ident {
- id: tt::TokenId::unspecified(),
- text: format!("T{}", i).into(),
- })
- .into(),
- );
- result.extend(bound.iter().cloned());
- }
- result.push(
- tt::Leaf::Punct(tt::Punct {
- char: '>',
- spacing: tt::Spacing::Alone,
- id: tt::TokenId::unspecified(),
+ let param_types = params
+ .into_iter()
+ .flat_map(|param_list| param_list.type_or_const_params())
+ .map(|param| {
+ if let ast::TypeOrConstParam::Const(param) = param {
+ let ty = param
+ .ty()
+ .map(|ty| mbe::syntax_node_to_token_tree(ty.syntax()).0)
+ .unwrap_or_default();
+ Some(ty)
+ } else {
+ None
+ }
})
- .into(),
- );
- result
+ .collect();
+ Ok(BasicAdtInfo { name: name_token, param_types })
}
fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResult<tt::Subtree> {
@@ -143,14 +116,27 @@ fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResu
Ok(info) => info,
Err(e) => return ExpandResult::only_err(e),
};
+ let (params, args): (Vec<_>, Vec<_>) = info
+ .param_types
+ .into_iter()
+ .enumerate()
+ .map(|(idx, param_ty)| {
+ let ident = tt::Leaf::Ident(tt::Ident {
+ id: tt::TokenId::unspecified(),
+ text: format!("T{idx}").into(),
+ });
+ let ident_ = ident.clone();
+ if let Some(ty) = param_ty {
+ (quote! { const #ident : #ty , }, quote! { #ident_ , })
+ } else {
+ let bound = trait_path.clone();
+ (quote! { #ident : #bound , }, quote! { #ident_ , })
+ }
+ })
+ .unzip();
let name = info.name;
- let trait_path_clone = trait_path.token_trees.clone();
- let bound = (quote! { : ##trait_path_clone }).token_trees;
- let type_params = make_type_args(info.type_or_const_params, bound);
- let type_args = make_type_args(info.type_or_const_params, Vec::new());
- let trait_path = trait_path.token_trees;
let expanded = quote! {
- impl ##type_params ##trait_path for #name ##type_args {}
+ impl < ##params > #trait_path for #name < ##args > {}
};
ExpandResult::ok(expanded)
}
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 8befa7f7d..7b19518e2 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
@@ -238,9 +238,9 @@ fn format_args_expand(
) -> ExpandResult<tt::Subtree> {
// We expand `format_args!("", a1, a2)` to
// ```
- // std::fmt::Arguments::new_v1(&[], &[
- // std::fmt::ArgumentV1::new(&arg1,std::fmt::Display::fmt),
- // std::fmt::ArgumentV1::new(&arg2,std::fmt::Display::fmt),
+ // $crate::fmt::Arguments::new_v1(&[], &[
+ // $crate::fmt::ArgumentV1::new(&arg1,$crate::fmt::Display::fmt),
+ // $crate::fmt::ArgumentV1::new(&arg2,$crate::fmt::Display::fmt),
// ])
// ```,
// which is still not really correct, but close enough for now
@@ -262,10 +262,10 @@ fn format_args_expand(
}
let _format_string = args.remove(0);
let arg_tts = args.into_iter().flat_map(|arg| {
- quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), }
+ quote! { #DOLLAR_CRATE::fmt::ArgumentV1::new(&(#arg), #DOLLAR_CRATE::fmt::Display::fmt), }
}.token_trees);
let expanded = quote! {
- std::fmt::Arguments::new_v1(&[], &[##arg_tts])
+ #DOLLAR_CRATE::fmt::Arguments::new_v1(&[], &[##arg_tts])
};
ExpandResult::ok(expanded)
}
@@ -675,8 +675,8 @@ fn option_env_expand(
};
let expanded = match get_env_inner(db, arg_id, &key) {
- None => quote! { std::option::Option::None::<&str> },
- Some(s) => quote! { std::option::Some(#s) },
+ None => quote! { #DOLLAR_CRATE::option::Option::None::<&str> },
+ Some(s) => quote! { #DOLLAR_CRATE::option::Some(#s) },
};
ExpandResult::ok(ExpandedEager::new(expanded))
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 bc97ee15c..87e4db039 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -221,8 +221,16 @@ pub fn expand_speculative(
fixup::reverse_fixups(&mut speculative_expansion.value, &spec_args_tmap, &fixups.undo_info);
let (node, rev_tmap) = token_tree_to_syntax_node(&speculative_expansion.value, expand_to);
- let range = rev_tmap.first_range_by_token(token_id, token_to_map.kind())?;
- let token = node.syntax_node().covering_element(range).into_token()?;
+ let syntax_node = node.syntax_node();
+ let token = rev_tmap
+ .ranges_by_token(token_id, token_to_map.kind())
+ .filter_map(|range| syntax_node.covering_element(range).into_token())
+ .min_by_key(|t| {
+ // prefer tokens of the same kind and text
+ // Note the inversion of the score here, as we want to prefer the first token in case
+ // of all tokens having the same score
+ (t.kind() != token_to_map.kind()) as u8 + (t.text() != token_to_map.text()) as u8
+ })?;
Some((node.syntax_node(), token))
}
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 fc128102f..a5b499fe8 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -811,6 +811,31 @@ impl<'a> InFile<&'a SyntaxNode> {
_ => None,
}
}
+
+ pub fn original_syntax_node(self, db: &dyn db::AstDatabase) -> Option<InFile<SyntaxNode>> {
+ // This kind of upmapping can only be achieved in attribute expanded files,
+ // as we don't have node inputs otherwise and therefor can't find an `N` node in the input
+ if !self.file_id.is_macro() {
+ return Some(self.map(Clone::clone));
+ } else if !self.file_id.is_attr_macro(db) {
+ return None;
+ }
+
+ if let Some(InFile { file_id, value: (first, last) }) = ascend_node_border_tokens(db, self)
+ {
+ if file_id.is_macro() {
+ let range = first.text_range().cover(last.text_range());
+ tracing::error!("Failed mapping out of macro file for {:?}", range);
+ return None;
+ }
+ // FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes
+ let anc = algo::least_common_ancestor(&first.parent()?, &last.parent()?)?;
+ let kind = self.value.kind();
+ let value = anc.ancestors().find(|it| it.kind() == kind)?;
+ return Some(InFile::new(file_id, value));
+ }
+ None
+ }
}
impl InFile<SyntaxToken> {
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 4ce21a579..2679a1c36 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -263,6 +263,7 @@ pub mod known {
Iterator,
IntoIterator,
Item,
+ IntoIter,
Try,
Ok,
Future,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 7f143f396..ed13275ba 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -11,18 +11,19 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.3"
+itertools = "0.10.5"
arrayvec = "0.7.2"
-smallvec = "1.9.0"
+smallvec = "1.10.0"
ena = "0.14.0"
tracing = "0.1.35"
rustc-hash = "1.1.0"
scoped-tls = "1.0.0"
-chalk-solve = { version = "0.84.0", default-features = false }
-chalk-ir = "0.84.0"
-chalk-recursive = { version = "0.84.0", default-features = false }
+chalk-solve = { version = "0.86.0", default-features = false }
+chalk-ir = "0.86.0"
+chalk-recursive = { version = "0.86.0", default-features = false }
+chalk-derive = "0.86.0"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
-once_cell = "1.12.0"
+once_cell = "1.15.0"
typed-arena = "2.0.1"
stdx = { path = "../stdx", version = "0.0.0" }
@@ -37,7 +38,7 @@ limit = { path = "../limit", version = "0.0.0" }
test-utils = { path = "../test-utils" }
expect-test = "1.4.0"
tracing = "0.1.35"
-tracing-subscriber = { version = "0.3.14", default-features = false, features = [
+tracing-subscriber = { version = "0.3.16", default-features = false, features = [
"env-filter",
"registry",
] }
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 344036dd8..78911d8dc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -1,7 +1,7 @@
//! In certain situations, rust automatically inserts derefs as necessary: for
//! example, field accesses `foo.bar` still work when `foo` is actually a
//! reference to a type with the field `bar`. This is an approximation of the
-//! logic in rustc (which lives in librustc_typeck/check/autoderef.rs).
+//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
use std::sync::Arc;
@@ -123,13 +123,14 @@ fn deref_by_trait(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
let projection = {
- let b = TyBuilder::assoc_type_projection(db, target);
+ let b = TyBuilder::subst_for_def(db, deref_trait, None);
if b.remaining() != 1 {
// the Target type + Deref trait should only have one generic parameter,
// namely Deref's Self type
return None;
}
- b.push(ty).build()
+ let deref_subst = b.push(ty).build();
+ TyBuilder::assoc_type_projection(db, target, Some(deref_subst)).build()
};
// Check that the type implements Deref at all
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 94d7806cb..9ae752556 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -6,19 +6,19 @@ use chalk_ir::{
cast::{Cast, CastTo, Caster},
fold::TypeFoldable,
interner::HasInterner,
- AdtId, BoundVar, DebruijnIndex, Scalar,
+ AdtId, DebruijnIndex, Scalar,
};
use hir_def::{
- builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, GenericDefId, TraitId,
- TypeAliasId,
+ builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
+ GenericDefId, TraitId, TypeAliasId,
};
use smallvec::SmallVec;
use crate::{
consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
- to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, CallableSig, ConstData,
- ConstValue, GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty,
- TyDefId, TyExt, TyKind, ValueTyDefId,
+ to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
+ GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
+ ValueTyDefId,
};
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -34,17 +34,32 @@ pub struct TyBuilder<D> {
data: D,
vec: SmallVec<[GenericArg; 2]>,
param_kinds: SmallVec<[ParamKind; 2]>,
+ parent_subst: Substitution,
}
impl<A> TyBuilder<A> {
fn with_data<B>(self, data: B) -> TyBuilder<B> {
- TyBuilder { data, param_kinds: self.param_kinds, vec: self.vec }
+ TyBuilder {
+ data,
+ vec: self.vec,
+ param_kinds: self.param_kinds,
+ parent_subst: self.parent_subst,
+ }
}
}
impl<D> TyBuilder<D> {
- fn new(data: D, param_kinds: SmallVec<[ParamKind; 2]>) -> TyBuilder<D> {
- TyBuilder { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds }
+ fn new(
+ data: D,
+ param_kinds: SmallVec<[ParamKind; 2]>,
+ parent_subst: Option<Substitution>,
+ ) -> Self {
+ let parent_subst = parent_subst.unwrap_or_else(|| Substitution::empty(Interner));
+ Self { data, vec: SmallVec::with_capacity(param_kinds.len()), param_kinds, parent_subst }
+ }
+
+ fn new_empty(data: D) -> Self {
+ TyBuilder::new(data, SmallVec::new(), None)
}
fn build_internal(self) -> (D, Substitution) {
@@ -52,13 +67,18 @@ impl<D> TyBuilder<D> {
for (a, e) in self.vec.iter().zip(self.param_kinds.iter()) {
self.assert_match_kind(a, e);
}
- let subst = Substitution::from_iter(Interner, self.vec);
+ let subst = Substitution::from_iter(
+ Interner,
+ self.vec.into_iter().chain(self.parent_subst.iter(Interner).cloned()),
+ );
(self.data, subst)
}
pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
+ assert!(self.remaining() > 0);
let arg = arg.cast(Interner);
let expected_kind = &self.param_kinds[self.vec.len()];
+
let arg_kind = match arg.data(Interner) {
chalk_ir::GenericArgData::Ty(_) => ParamKind::Type,
chalk_ir::GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
@@ -68,7 +88,9 @@ impl<D> TyBuilder<D> {
}
};
assert_eq!(*expected_kind, arg_kind);
+
self.vec.push(arg);
+
self
}
@@ -79,20 +101,12 @@ impl<D> TyBuilder<D> {
pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
// self.fill is inlined to make borrow checker happy
let mut this = self;
- let other = this.param_kinds.iter().skip(this.vec.len());
+ let other = &this.param_kinds[this.vec.len()..];
let filler = (starting_from..).zip(other).map(|(idx, kind)| match kind {
- ParamKind::Type => {
- GenericArgData::Ty(TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner))
- .intern(Interner)
+ ParamKind::Type => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
+ ParamKind::Const(ty) => {
+ BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
}
- ParamKind::Const(ty) => GenericArgData::Const(
- ConstData {
- value: ConstValue::BoundVar(BoundVar::new(debruijn, idx)),
- ty: ty.clone(),
- }
- .intern(Interner),
- )
- .intern(Interner),
});
this.vec.extend(filler.take(this.remaining()).casted(Interner));
assert_eq!(this.remaining(), 0);
@@ -102,8 +116,8 @@ impl<D> TyBuilder<D> {
pub fn fill_with_unknown(self) -> Self {
// self.fill is inlined to make borrow checker happy
let mut this = self;
- let filler = this.param_kinds.iter().skip(this.vec.len()).map(|x| match x {
- ParamKind::Type => GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner),
+ let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
+ ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
});
this.vec.extend(filler.casted(Interner));
@@ -113,33 +127,17 @@ impl<D> TyBuilder<D> {
pub(crate) fn fill_with_inference_vars(self, table: &mut InferenceTable<'_>) -> Self {
self.fill(|x| match x {
- ParamKind::Type => GenericArgData::Ty(table.new_type_var()).intern(Interner),
- ParamKind::Const(ty) => {
- GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
- }
+ ParamKind::Type => table.new_type_var().cast(Interner),
+ ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
})
}
pub fn fill(mut self, filler: impl FnMut(&ParamKind) -> GenericArg) -> Self {
- self.vec.extend(self.param_kinds.iter().skip(self.vec.len()).map(filler));
+ self.vec.extend(self.param_kinds[self.vec.len()..].iter().map(filler));
assert_eq!(self.remaining(), 0);
self
}
- pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
- assert!(self.vec.is_empty());
- assert!(parent_substs.len(Interner) <= self.param_kinds.len());
- self.extend(parent_substs.iter(Interner).cloned());
- self
- }
-
- fn extend(&mut self, it: impl Iterator<Item = GenericArg> + Clone) {
- for x in it.clone().zip(self.param_kinds.iter().skip(self.vec.len())) {
- self.assert_match_kind(&x.0, &x.1);
- }
- self.vec.extend(it);
- }
-
fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
match (a.data(Interner), e) {
(chalk_ir::GenericArgData::Ty(_), ParamKind::Type)
@@ -188,21 +186,42 @@ impl TyBuilder<()> {
params.placeholder_subst(db)
}
- pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
- let def = def.into();
- let params = generics(db.upcast(), def);
- TyBuilder::new(
- (),
- params
- .iter()
- .map(|(id, data)| match data {
- TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
- TypeOrConstParamData::ConstParamData(_) => {
- ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
- }
- })
- .collect(),
- )
+ pub fn subst_for_def(
+ db: &dyn HirDatabase,
+ def: impl Into<GenericDefId>,
+ parent_subst: Option<Substitution>,
+ ) -> TyBuilder<()> {
+ let generics = generics(db.upcast(), def.into());
+ assert!(generics.parent_generics().is_some() == parent_subst.is_some());
+ let params = generics
+ .iter_self()
+ .map(|(id, data)| match data {
+ TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
+ TypeOrConstParamData::ConstParamData(_) => {
+ ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
+ }
+ })
+ .collect();
+ TyBuilder::new((), params, parent_subst)
+ }
+
+ /// Creates a `TyBuilder` to build `Substitution` for a generator defined in `parent`.
+ ///
+ /// A generator's substitution consists of:
+ /// - resume type of generator
+ /// - yield type of generator ([`Generator::Yield`](std::ops::Generator::Yield))
+ /// - return type of generator ([`Generator::Return`](std::ops::Generator::Return))
+ /// - generic parameters in scope on `parent`
+ /// in this order.
+ ///
+ /// This method prepopulates the builder with placeholder substitution of `parent`, so you
+ /// should only push exactly 3 `GenericArg`s before building.
+ pub fn subst_for_generator(db: &dyn HirDatabase, parent: DefWithBodyId) -> TyBuilder<()> {
+ let parent_subst =
+ parent.as_generic_def_id().map(|p| generics(db.upcast(), p).placeholder_subst(db));
+ // These represent resume type, yield type, and return type of generator.
+ let params = std::iter::repeat(ParamKind::Type).take(3).collect();
+ TyBuilder::new((), params, parent_subst)
}
pub fn build(self) -> Substitution {
@@ -213,7 +232,7 @@ impl TyBuilder<()> {
impl TyBuilder<hir_def::AdtId> {
pub fn adt(db: &dyn HirDatabase, def: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
- TyBuilder::subst_for_def(db, def).with_data(def)
+ TyBuilder::subst_for_def(db, def, None).with_data(def)
}
pub fn fill_with_defaults(
@@ -221,16 +240,27 @@ impl TyBuilder<hir_def::AdtId> {
db: &dyn HirDatabase,
mut fallback: impl FnMut() -> Ty,
) -> Self {
+ // Note that we're building ADT, so we never have parent generic parameters.
let defaults = db.generic_defaults(self.data.into());
+ let dummy_ty = TyKind::Error.intern(Interner).cast(Interner);
for default_ty in defaults.iter().skip(self.vec.len()) {
- if let GenericArgData::Ty(x) = default_ty.skip_binders().data(Interner) {
+ // NOTE(skip_binders): we only check if the arg type is error type.
+ if let Some(x) = default_ty.skip_binders().ty(Interner) {
if x.is_unknown() {
self.vec.push(fallback().cast(Interner));
continue;
}
- };
- // each default can depend on the previous parameters
- let subst_so_far = Substitution::from_iter(Interner, self.vec.clone());
+ }
+ // Each default can only depend on the previous parameters.
+ // FIXME: we don't handle const generics here.
+ let subst_so_far = Substitution::from_iter(
+ Interner,
+ self.vec
+ .iter()
+ .cloned()
+ .chain(iter::repeat(dummy_ty.clone()))
+ .take(self.param_kinds.len()),
+ );
self.vec.push(default_ty.clone().substitute(Interner, &subst_so_far).cast(Interner));
}
self
@@ -245,7 +275,7 @@ impl TyBuilder<hir_def::AdtId> {
pub struct Tuple(usize);
impl TyBuilder<Tuple> {
pub fn tuple(size: usize) -> TyBuilder<Tuple> {
- TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect())
+ TyBuilder::new(Tuple(size), iter::repeat(ParamKind::Type).take(size).collect(), None)
}
pub fn build(self) -> Ty {
@@ -256,7 +286,7 @@ impl TyBuilder<Tuple> {
impl TyBuilder<TraitId> {
pub fn trait_ref(db: &dyn HirDatabase, def: TraitId) -> TyBuilder<TraitId> {
- TyBuilder::subst_for_def(db, def).with_data(def)
+ TyBuilder::subst_for_def(db, def, None).with_data(def)
}
pub fn build(self) -> TraitRef {
@@ -266,8 +296,12 @@ impl TyBuilder<TraitId> {
}
impl TyBuilder<TypeAliasId> {
- pub fn assoc_type_projection(db: &dyn HirDatabase, def: TypeAliasId) -> TyBuilder<TypeAliasId> {
- TyBuilder::subst_for_def(db, def).with_data(def)
+ pub fn assoc_type_projection(
+ db: &dyn HirDatabase,
+ def: TypeAliasId,
+ parent_subst: Option<Substitution>,
+ ) -> TyBuilder<TypeAliasId> {
+ TyBuilder::subst_for_def(db, def, parent_subst).with_data(def)
}
pub fn build(self) -> ProjectionTy {
@@ -277,19 +311,6 @@ impl TyBuilder<TypeAliasId> {
}
impl<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>> TyBuilder<Binders<T>> {
- fn subst_binders(b: Binders<T>) -> Self {
- let param_kinds = b
- .binders
- .iter(Interner)
- .map(|x| match x {
- chalk_ir::VariableKind::Ty(_) => ParamKind::Type,
- chalk_ir::VariableKind::Lifetime => panic!("Got lifetime parameter"),
- chalk_ir::VariableKind::Const(ty) => ParamKind::Const(ty.clone()),
- })
- .collect();
- TyBuilder::new(b, param_kinds)
- }
-
pub fn build(self) -> T {
let (b, subst) = self.build_internal();
b.substitute(Interner, &subst)
@@ -297,15 +318,41 @@ impl<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>> TyBuilder<Bin
}
impl TyBuilder<Binders<Ty>> {
- pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
- TyBuilder::subst_binders(db.ty(def))
+ pub fn def_ty(
+ db: &dyn HirDatabase,
+ def: TyDefId,
+ parent_subst: Option<Substitution>,
+ ) -> TyBuilder<Binders<Ty>> {
+ let poly_ty = db.ty(def);
+ let id: GenericDefId = match def {
+ TyDefId::BuiltinType(_) => {
+ assert!(parent_subst.is_none());
+ return TyBuilder::new_empty(poly_ty);
+ }
+ TyDefId::AdtId(id) => id.into(),
+ TyDefId::TypeAliasId(id) => id.into(),
+ };
+ TyBuilder::subst_for_def(db, id, parent_subst).with_data(poly_ty)
}
pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
- TyBuilder::subst_binders(db.impl_self_ty(def))
+ TyBuilder::subst_for_def(db, def, None).with_data(db.impl_self_ty(def))
}
- pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
- TyBuilder::subst_binders(db.value_ty(def))
+ pub fn value_ty(
+ db: &dyn HirDatabase,
+ def: ValueTyDefId,
+ parent_subst: Option<Substitution>,
+ ) -> TyBuilder<Binders<Ty>> {
+ let poly_value_ty = db.value_ty(def);
+ let id = match def.to_generic_def_id() {
+ Some(id) => id,
+ None => {
+ // static items
+ assert!(parent_subst.is_none());
+ return TyBuilder::new_empty(poly_value_ty);
+ }
+ };
+ TyBuilder::subst_for_def(db, id, parent_subst).with_data(poly_value_ty)
}
}
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 faec99c7d..43c3451ca 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
@@ -11,6 +11,7 @@ use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
use base_db::CrateId;
use hir_def::{
+ expr::Movability,
lang_item::{lang_attr, LangItemTarget},
AssocItemId, GenericDefId, HasModule, ItemContainerId, Lookup, ModuleId, TypeAliasId,
};
@@ -26,9 +27,9 @@ use crate::{
to_assoc_type_id, to_chalk_trait_id,
traits::ChalkContext,
utils::generics,
- AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy,
- ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
- TyExt, TyKind, WhereClause,
+ wrap_empty_binders, AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId,
+ Interner, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef,
+ TraitRefExt, Ty, TyBuilder, TyExt, TyKind, WhereClause,
};
pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
@@ -372,17 +373,62 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
}
fn generator_datum(
&self,
- _: chalk_ir::GeneratorId<Interner>,
+ id: chalk_ir::GeneratorId<Interner>,
) -> std::sync::Arc<chalk_solve::rust_ir::GeneratorDatum<Interner>> {
- // FIXME
- unimplemented!()
+ let (parent, expr) = self.db.lookup_intern_generator(id.into());
+
+ // We fill substitution with unknown type, because we only need to know whether the generic
+ // params are types or consts to build `Binders` and those being filled up are for
+ // `resume_type`, `yield_type`, and `return_type` of the generator in question.
+ let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build();
+
+ let input_output = rust_ir::GeneratorInputOutputDatum {
+ resume_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
+ .intern(Interner),
+ yield_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 1))
+ .intern(Interner),
+ return_type: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 2))
+ .intern(Interner),
+ // FIXME: calculate upvars
+ upvars: vec![],
+ };
+
+ let it = subst
+ .iter(Interner)
+ .map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
+ let input_output = crate::make_type_and_const_binders(it, input_output);
+
+ let movability = match self.db.body(parent)[expr] {
+ hir_def::expr::Expr::Closure {
+ closure_kind: hir_def::expr::ClosureKind::Generator(movability),
+ ..
+ } => movability,
+ _ => unreachable!("non generator expression interned as generator"),
+ };
+ let movability = match movability {
+ Movability::Static => rust_ir::Movability::Static,
+ Movability::Movable => rust_ir::Movability::Movable,
+ };
+
+ Arc::new(rust_ir::GeneratorDatum { movability, input_output })
}
fn generator_witness_datum(
&self,
- _: chalk_ir::GeneratorId<Interner>,
+ id: chalk_ir::GeneratorId<Interner>,
) -> std::sync::Arc<chalk_solve::rust_ir::GeneratorWitnessDatum<Interner>> {
- // FIXME
- unimplemented!()
+ // FIXME: calculate inner types
+ let inner_types =
+ rust_ir::GeneratorWitnessExistential { types: wrap_empty_binders(vec![]) };
+
+ let (parent, _) = self.db.lookup_intern_generator(id.into());
+ // See the comment in `generator_datum()` for unknown types.
+ let subst = TyBuilder::subst_for_generator(self.db, parent).fill_with_unknown().build();
+ let it = subst
+ .iter(Interner)
+ .map(|it| it.constant(Interner).map(|c| c.data(Interner).ty.clone()));
+ let inner_types = crate::make_type_and_const_binders(it, inner_types);
+
+ Arc::new(rust_ir::GeneratorWitnessDatum { inner_types })
}
fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
@@ -429,10 +475,15 @@ pub(crate) fn associated_ty_data_query(
let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
let ctx = crate::TyLoweringContext::new(db, &resolver)
.with_type_param_mode(crate::lower::ParamLoweringMode::Variable);
- let pro_ty = TyBuilder::assoc_type_projection(db, type_alias)
+
+ let trait_subst = TyBuilder::subst_for_def(db, trait_, None)
+ .fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, generic_params.len_self())
+ .build();
+ let pro_ty = TyBuilder::assoc_type_projection(db, type_alias, Some(trait_subst))
.fill_with_bound_vars(crate::DebruijnIndex::INNERMOST, 0)
.build();
let self_ty = TyKind::Alias(AliasTy::Projection(pro_ty)).intern(Interner);
+
let mut bounds: Vec<_> = type_alias_data
.bounds
.iter()
@@ -772,10 +823,10 @@ pub(super) fn generic_predicate_to_inline_bound(
Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
}
WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
- if projection_ty.self_type_parameter(Interner) != self_ty_shifted_in {
+ let trait_ = projection_ty.trait_(db);
+ if projection_ty.self_type_parameter(db) != self_ty_shifted_in {
return None;
}
- let trait_ = projection_ty.trait_(db);
let args_no_self = projection_ty.substitution.as_slice(Interner)[1..]
.iter()
.map(|ty| ty.clone().cast(Interner))
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 4a5533c64..e2099d7e5 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
@@ -152,7 +152,7 @@ impl TyExt for Ty {
TyKind::FnDef(def, parameters) => {
let callable_def = db.lookup_intern_callable_def((*def).into());
let sig = db.callable_item_signature(callable_def);
- Some(sig.substitute(Interner, &parameters))
+ Some(sig.substitute(Interner, parameters))
}
TyKind::Closure(.., substs) => {
let sig_param = substs.at(Interner, 0).assert_ty_ref(Interner);
@@ -166,6 +166,8 @@ impl TyExt for Ty {
let trait_ref = match self.kind(Interner) {
// The principal trait bound should be the first element of the bounds. This is an
// invariant ensured by `TyLoweringContext::lower_dyn_trait()`.
+ // FIXME: dyn types may not have principal trait and we don't want to return auto trait
+ // here.
TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
match b.skip_binders() {
WhereClause::Implemented(trait_ref) => Some(trait_ref),
@@ -260,7 +262,7 @@ impl TyExt for Ty {
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj),
ty: _,
- }) => &proj.self_type_parameter(Interner) == self,
+ }) => &proj.self_type_parameter(db) == self,
_ => false,
})
.collect::<Vec<_>>();
@@ -331,6 +333,7 @@ impl TyExt for Ty {
pub trait ProjectionTyExt {
fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
+ fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty;
}
impl ProjectionTyExt for ProjectionTy {
@@ -347,6 +350,10 @@ impl ProjectionTyExt for ProjectionTy {
_ => panic!("projection ty without parent trait"),
}
}
+
+ fn self_type_parameter(&self, db: &dyn HirDatabase) -> Ty {
+ self.trait_ref(db).self_type_parameter(Interner)
+ }
}
pub trait TraitRefExt {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index 6ecb6e6fd..2c0c6e0b8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -7,14 +7,17 @@ use std::{
use chalk_ir::{BoundVar, DebruijnIndex, GenericArgData, IntTy, Scalar};
use hir_def::{
+ builtin_type::BuiltinInt,
expr::{ArithOp, BinaryOp, Expr, ExprId, Literal, Pat, PatId},
path::ModPath,
resolver::{resolver_for_expr, ResolveValueResult, Resolver, ValueNs},
+ src::HasChildSource,
type_ref::ConstScalar,
- ConstId, DefWithBodyId,
+ ConstId, DefWithBodyId, EnumVariantId, Lookup,
};
-use la_arena::{Arena, Idx};
+use la_arena::{Arena, Idx, RawIdx};
use stdx::never;
+use syntax::ast::HasName;
use crate::{
db::HirDatabase, infer::InferenceContext, lower::ParamLoweringMode, to_placeholder_idx,
@@ -77,6 +80,7 @@ pub enum ConstEvalError {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ComputedExpr {
Literal(Literal),
+ Enum(String, EnumVariantId, Literal),
Tuple(Box<[ComputedExpr]>),
}
@@ -104,6 +108,7 @@ impl Display for ComputedExpr {
Literal::String(x) => std::fmt::Debug::fmt(x, f),
Literal::ByteString(x) => std::fmt::Debug::fmt(x, f),
},
+ ComputedExpr::Enum(name, _, _) => name.fmt(f),
ComputedExpr::Tuple(t) => {
f.write_char('(')?;
for x in &**t {
@@ -148,13 +153,51 @@ fn is_valid(scalar: &Scalar, value: i128) -> bool {
}
}
+fn get_name(ctx: &mut ConstEvalCtx<'_>, variant: EnumVariantId) -> String {
+ let loc = variant.parent.lookup(ctx.db.upcast());
+ let children = variant.parent.child_source(ctx.db.upcast());
+ let item_tree = loc.id.item_tree(ctx.db.upcast());
+
+ let variant_name = children.value[variant.local_id].name();
+ let enum_name = item_tree[loc.id.value].name.to_string();
+ enum_name + "::" + &variant_name.unwrap().to_string()
+}
+
pub fn eval_const(
expr_id: ExprId,
ctx: &mut ConstEvalCtx<'_>,
) -> Result<ComputedExpr, ConstEvalError> {
+ let u128_to_i128 = |it: u128| -> Result<i128, ConstEvalError> {
+ it.try_into().map_err(|_| ConstEvalError::NotSupported("u128 is too big"))
+ };
+
let expr = &ctx.exprs[expr_id];
match expr {
- Expr::Missing => Err(ConstEvalError::IncompleteExpr),
+ Expr::Missing => match ctx.owner {
+ // evaluate the implicit variant index of an enum variant without expression
+ // FIXME: This should return the type of the enum representation
+ DefWithBodyId::VariantId(variant) => {
+ let prev_idx: u32 = variant.local_id.into_raw().into();
+ let prev_idx = prev_idx.checked_sub(1).map(RawIdx::from).map(Idx::from_raw);
+ let value = match prev_idx {
+ Some(local_id) => {
+ let prev_variant = EnumVariantId { local_id, parent: variant.parent };
+ 1 + match ctx.db.const_eval_variant(prev_variant)? {
+ ComputedExpr::Literal(Literal::Int(v, _)) => v,
+ ComputedExpr::Literal(Literal::Uint(v, _)) => u128_to_i128(v)?,
+ _ => {
+ return Err(ConstEvalError::NotSupported(
+ "Enum can't contain this kind of value",
+ ))
+ }
+ }
+ }
+ _ => 0,
+ };
+ Ok(ComputedExpr::Literal(Literal::Int(value, Some(BuiltinInt::I128))))
+ }
+ _ => Err(ConstEvalError::IncompleteExpr),
+ },
Expr::Literal(l) => Ok(ComputedExpr::Literal(l.clone())),
&Expr::UnaryOp { expr, op } => {
let ty = &ctx.expr_ty(expr);
@@ -167,9 +210,7 @@ pub fn eval_const(
return Ok(ComputedExpr::Literal(Literal::Bool(!b)))
}
ComputedExpr::Literal(Literal::Int(v, _)) => v,
- ComputedExpr::Literal(Literal::Uint(v, _)) => v
- .try_into()
- .map_err(|_| ConstEvalError::NotSupported("too big u128"))?,
+ ComputedExpr::Literal(Literal::Uint(v, _)) => u128_to_i128(v)?,
_ => return Err(ConstEvalError::NotSupported("this kind of operator")),
};
let r = match ty.kind(Interner) {
@@ -198,9 +239,7 @@ pub fn eval_const(
hir_def::expr::UnaryOp::Neg => {
let v = match ev {
ComputedExpr::Literal(Literal::Int(v, _)) => v,
- ComputedExpr::Literal(Literal::Uint(v, _)) => v
- .try_into()
- .map_err(|_| ConstEvalError::NotSupported("too big u128"))?,
+ ComputedExpr::Literal(Literal::Uint(v, _)) => u128_to_i128(v)?,
_ => return Err(ConstEvalError::NotSupported("this kind of operator")),
};
Ok(ComputedExpr::Literal(Literal::Int(
@@ -219,16 +258,12 @@ pub fn eval_const(
let op = op.ok_or(ConstEvalError::IncompleteExpr)?;
let v1 = match lhs {
ComputedExpr::Literal(Literal::Int(v, _)) => v,
- ComputedExpr::Literal(Literal::Uint(v, _)) => {
- v.try_into().map_err(|_| ConstEvalError::NotSupported("too big u128"))?
- }
+ ComputedExpr::Literal(Literal::Uint(v, _)) => u128_to_i128(v)?,
_ => return Err(ConstEvalError::NotSupported("this kind of operator")),
};
let v2 = match rhs {
ComputedExpr::Literal(Literal::Int(v, _)) => v,
- ComputedExpr::Literal(Literal::Uint(v, _)) => {
- v.try_into().map_err(|_| ConstEvalError::NotSupported("too big u128"))?
- }
+ ComputedExpr::Literal(Literal::Uint(v, _)) => u128_to_i128(v)?,
_ => return Err(ConstEvalError::NotSupported("this kind of operator")),
};
match op {
@@ -339,9 +374,22 @@ pub fn eval_const(
ValueNs::GenericParam(_) => {
Err(ConstEvalError::NotSupported("const generic without substitution"))
}
+ ValueNs::EnumVariantId(id) => match ctx.db.const_eval_variant(id)? {
+ ComputedExpr::Literal(lit) => {
+ Ok(ComputedExpr::Enum(get_name(ctx, id), id, lit))
+ }
+ _ => Err(ConstEvalError::NotSupported(
+ "Enums can't evalute to anything but numbers",
+ )),
+ },
_ => Err(ConstEvalError::NotSupported("path that are not const or local")),
}
}
+ // FIXME: Handle the cast target
+ &Expr::Cast { expr, .. } => match eval_const(expr, ctx)? {
+ ComputedExpr::Enum(_, _, lit) => Ok(ComputedExpr::Literal(lit)),
+ _ => Err(ConstEvalError::NotSupported("Can't cast these types")),
+ },
_ => Err(ConstEvalError::NotSupported("This kind of expression")),
}
}
@@ -412,7 +460,15 @@ pub(crate) fn const_eval_recover(
Err(ConstEvalError::Loop)
}
-pub(crate) fn const_eval_query(
+pub(crate) fn const_eval_variant_recover(
+ _: &dyn HirDatabase,
+ _: &[String],
+ _: &EnumVariantId,
+) -> Result<ComputedExpr, ConstEvalError> {
+ Err(ConstEvalError::Loop)
+}
+
+pub(crate) fn const_eval_variant_query(
db: &dyn HirDatabase,
const_id: ConstId,
) -> Result<ComputedExpr, ConstEvalError> {
@@ -433,6 +489,26 @@ pub(crate) fn const_eval_query(
result
}
+pub(crate) fn const_eval_query_variant(
+ db: &dyn HirDatabase,
+ variant_id: EnumVariantId,
+) -> Result<ComputedExpr, ConstEvalError> {
+ let def = variant_id.into();
+ let body = db.body(def);
+ let infer = &db.infer(def);
+ eval_const(
+ body.body_expr,
+ &mut ConstEvalCtx {
+ db,
+ owner: def,
+ exprs: &body.exprs,
+ pats: &body.pats,
+ local_data: HashMap::default(),
+ infer,
+ },
+ )
+}
+
pub(crate) fn eval_to_const<'a>(
expr: Idx<Expr>,
mode: ParamLoweringMode,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 4a052851a..b76506f6e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -88,6 +88,49 @@ fn consts() {
}
#[test]
+fn enums() {
+ check_number(
+ r#"
+ enum E {
+ F1 = 1,
+ F2 = 2 * E::F1 as u8,
+ F3 = 3 * E::F2 as u8,
+ }
+ const GOAL: i32 = E::F3 as u8;
+ "#,
+ 6,
+ );
+ check_number(
+ r#"
+ enum E { F1 = 1, F2, }
+ const GOAL: i32 = E::F2 as u8;
+ "#,
+ 2,
+ );
+ check_number(
+ r#"
+ enum E { F1, }
+ const GOAL: i32 = E::F1 as u8;
+ "#,
+ 0,
+ );
+ let r = eval_goal(
+ r#"
+ enum E { A = 1, }
+ const GOAL: E = E::A;
+ "#,
+ )
+ .unwrap();
+ match r {
+ ComputedExpr::Enum(name, _, Literal::Uint(val, _)) => {
+ assert_eq!(name, "E::A");
+ assert_eq!(val, 1);
+ }
+ x => panic!("Expected enum but found {:?}", x),
+ }
+}
+
+#[test]
fn const_loop() {
check_fail(
r#"
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 b385b1caf..932fce835 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -6,8 +6,8 @@ use std::sync::Arc;
use arrayvec::ArrayVec;
use base_db::{impl_intern_key, salsa, CrateId, Upcast};
use hir_def::{
- db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, FunctionId,
- GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
+ db::DefDatabase, expr::ExprId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumVariantId,
+ FunctionId, GenericDefId, ImplId, LifetimeParamId, LocalFieldId, TypeOrConstParamId, VariantId,
};
use la_arena::ArenaMap;
@@ -43,10 +43,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
#[salsa::invoke(crate::lower::const_param_ty_query)]
fn const_param_ty(&self, def: ConstParamId) -> Ty;
- #[salsa::invoke(crate::consteval::const_eval_query)]
+ #[salsa::invoke(crate::consteval::const_eval_variant_query)]
#[salsa::cycle(crate::consteval::const_eval_recover)]
fn const_eval(&self, def: ConstId) -> Result<ComputedExpr, ConstEvalError>;
+ #[salsa::invoke(crate::consteval::const_eval_query_variant)]
+ #[salsa::cycle(crate::consteval::const_eval_variant_recover)]
+ fn const_eval_variant(&self, def: EnumVariantId) -> Result<ComputedExpr, ConstEvalError>;
+
#[salsa::invoke(crate::lower::impl_trait_query)]
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
@@ -116,6 +120,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
#[salsa::interned]
fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
+ #[salsa::interned]
+ fn intern_generator(&self, id: (DefWithBodyId, ExprId)) -> InternedGeneratorId;
#[salsa::invoke(chalk_db::associated_ty_data_query)]
fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc<chalk_db::AssociatedTyDatum>;
@@ -150,6 +156,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
id: chalk_db::AssociatedTyValueId,
) -> Arc<chalk_db::AssociatedTyValue>;
+ #[salsa::invoke(crate::traits::normalize_projection_query)]
+ #[salsa::transparent]
+ fn normalize_projection(
+ &self,
+ projection: crate::ProjectionTy,
+ env: Arc<crate::TraitEnvironment>,
+ ) -> Ty;
+
#[salsa::invoke(trait_solve_wait)]
#[salsa::transparent]
fn trait_solve(
@@ -180,6 +194,9 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
DefWithBodyId::ConstId(it) => {
db.const_data(it).name.clone().unwrap_or_else(Name::missing).to_string()
}
+ DefWithBodyId::VariantId(it) => {
+ db.enum_data(it.parent).variants[it.local_id].name.to_string()
+ }
});
db.infer_query(def)
}
@@ -218,6 +235,10 @@ impl_intern_key!(InternedOpaqueTyId);
pub struct InternedClosureId(salsa::InternId);
impl_intern_key!(InternedClosureId);
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct InternedGeneratorId(salsa::InternId);
+impl_intern_key!(InternedGeneratorId);
+
/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
/// we have different IDs for struct and enum variant constructors.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 161b19a73..431ab949b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -18,7 +18,9 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> Vec<ExprId> {
let is_unsafe = match def {
DefWithBodyId::FunctionId(it) => db.function_data(it).has_unsafe_kw(),
- DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
+ DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) | DefWithBodyId::VariantId(_) => {
+ false
+ }
};
if is_unsafe {
return res;
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 d2f9c2b8b..0221f922f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -20,13 +20,14 @@ use hir_def::{
};
use hir_expand::{hygiene::Hygiene, name::Name};
use itertools::Itertools;
+use smallvec::SmallVec;
use syntax::SmolStr;
use crate::{
db::HirDatabase,
from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, lt_from_placeholder_idx,
mapping::from_chalk,
- primitive, subst_prefix, to_assoc_type_id,
+ primitive, to_assoc_type_id,
utils::{self, generics},
AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Const, ConstValue, DomainGoal,
GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability,
@@ -221,6 +222,7 @@ pub enum DisplaySourceCodeError {
PathNotFound,
UnknownType,
Closure,
+ Generator,
}
pub enum HirDisplayError {
@@ -289,7 +291,7 @@ impl HirDisplay for ProjectionTy {
let trait_ = f.db.trait_data(self.trait_(f.db));
write!(f, "<")?;
- self.self_type_parameter(Interner).hir_fmt(f)?;
+ self.self_type_parameter(f.db).hir_fmt(f)?;
write!(f, " as {}", trait_.name)?;
if self.substitution.len(Interner) > 1 {
write!(f, "<")?;
@@ -504,8 +506,15 @@ impl HirDisplay for Ty {
let total_len = parent_params + self_param + type_params + const_params;
// We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
if total_len > 0 {
+ // `parameters` are in the order of fn's params (including impl traits),
+ // parent's params (those from enclosing impl or trait, if any).
+ let parameters = parameters.as_slice(Interner);
+ let fn_params_len = self_param + type_params + const_params;
+ let fn_params = parameters.get(..fn_params_len);
+ let parent_params = parameters.get(parameters.len() - parent_params..);
+ let params = parent_params.into_iter().chain(fn_params).flatten();
write!(f, "<")?;
- f.write_joined(&parameters.as_slice(Interner)[..total_len], ", ")?;
+ f.write_joined(params, ", ")?;
write!(f, ">")?;
}
}
@@ -533,6 +542,7 @@ impl HirDisplay for Ty {
f.db.upcast(),
ItemInNs::Types((*def_id).into()),
module_id,
+ false,
) {
write!(f, "{}", path)?;
} else {
@@ -576,9 +586,8 @@ impl HirDisplay for Ty {
Some(x) => x,
None => return true,
};
- let actual_default = default_parameter
- .clone()
- .substitute(Interner, &subst_prefix(parameters, i));
+ let actual_default =
+ default_parameter.clone().substitute(Interner, &parameters);
parameter != &actual_default
}
let mut default_from = 0;
@@ -722,7 +731,7 @@ impl HirDisplay for Ty {
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(proj),
ty: _,
- }) => &proj.self_type_parameter(Interner) == self,
+ }) => &proj.self_type_parameter(f.db) == self,
_ => false,
})
.collect::<Vec<_>>();
@@ -742,9 +751,19 @@ impl HirDisplay for Ty {
}
TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
TyKind::Dyn(dyn_ty) => {
+ // Reorder bounds to satisfy `write_bounds_like_dyn_trait()`'s expectation.
+ // FIXME: `Iterator::partition_in_place()` or `Vec::drain_filter()` may make it
+ // more efficient when either of them hits stable.
+ let mut bounds: SmallVec<[_; 4]> =
+ dyn_ty.bounds.skip_binders().iter(Interner).cloned().collect();
+ let (auto_traits, others): (SmallVec<[_; 4]>, _) =
+ bounds.drain(1..).partition(|b| b.skip_binders().trait_id().is_some());
+ bounds.extend(others);
+ bounds.extend(auto_traits);
+
write_bounds_like_dyn_trait_with_prefix(
"dyn",
- dyn_ty.bounds.skip_binders().interned(),
+ &bounds,
SizedByDefault::NotSized,
f,
)?;
@@ -782,7 +801,34 @@ impl HirDisplay for Ty {
write!(f, "{{unknown}}")?;
}
TyKind::InferenceVar(..) => write!(f, "_")?,
- TyKind::Generator(..) => write!(f, "{{generator}}")?,
+ TyKind::Generator(_, subst) => {
+ if f.display_target.is_source_code() {
+ return Err(HirDisplayError::DisplaySourceCodeError(
+ DisplaySourceCodeError::Generator,
+ ));
+ }
+
+ let subst = subst.as_slice(Interner);
+ let a: Option<SmallVec<[&Ty; 3]>> = subst
+ .get(subst.len() - 3..)
+ .map(|args| args.iter().map(|arg| arg.ty(Interner)).collect())
+ .flatten();
+
+ if let Some([resume_ty, yield_ty, ret_ty]) = a.as_deref() {
+ write!(f, "|")?;
+ resume_ty.hir_fmt(f)?;
+ write!(f, "|")?;
+
+ write!(f, " yields ")?;
+ yield_ty.hir_fmt(f)?;
+
+ write!(f, " -> ")?;
+ ret_ty.hir_fmt(f)?;
+ } else {
+ // This *should* be unreachable, but fallback just in case.
+ write!(f, "{{generator}}")?;
+ }
+ }
TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
}
Ok(())
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 10ffde87e..0efff651c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -2,7 +2,7 @@
//! the type of each expression and pattern.
//!
//! For type inference, compare the implementations in rustc (the various
-//! check_* methods in librustc_typeck/check/mod.rs are a good entry point) and
+//! check_* methods in rustc_hir_analysis/check/mod.rs are a good entry point) and
//! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for
//! inference here is the `infer` function, which infers the types of all
//! expressions in a given function.
@@ -19,14 +19,15 @@ use std::sync::Arc;
use chalk_ir::{cast::Cast, ConstValue, DebruijnIndex, Mutability, Safety, Scalar, TypeFlags};
use hir_def::{
body::Body,
+ builtin_type::BuiltinType,
data::{ConstData, StaticData},
expr::{BindingAnnotation, ExprId, PatId},
lang_item::LangItemTarget,
path::{path, Path},
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
type_ref::TypeRef,
- AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule, Lookup,
- TraitId, TypeAliasId, VariantId,
+ AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, FunctionId, HasModule,
+ ItemContainerId, Lookup, TraitId, TypeAliasId, VariantId,
};
use hir_expand::name::{name, Name};
use itertools::Either;
@@ -67,6 +68,12 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
DefWithBodyId::ConstId(c) => ctx.collect_const(&db.const_data(c)),
DefWithBodyId::FunctionId(f) => ctx.collect_fn(f),
DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_data(s)),
+ DefWithBodyId::VariantId(v) => {
+ ctx.return_ty = TyBuilder::builtin(match db.enum_data(v.parent).variant_body_type() {
+ Either::Left(builtin) => BuiltinType::Int(builtin),
+ Either::Right(builtin) => BuiltinType::Uint(builtin),
+ });
+ }
}
ctx.infer_body();
@@ -332,7 +339,7 @@ pub struct InferenceResult {
/// unresolved or missing subpatterns or subpatterns of mismatched types.
pub type_of_pat: ArenaMap<PatId, Ty>,
type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
- /// Interned Unknown to return references to.
+ /// Interned common types to return references to.
standard_types: InternedStandardTypes,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
pub pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
@@ -412,6 +419,8 @@ pub(crate) struct InferenceContext<'a> {
/// closures, but currently this is the only field that will change there,
/// so it doesn't make sense.
return_ty: Ty,
+ /// The resume type and the yield type, respectively, of the generator being inferred.
+ resume_yield_tys: Option<(Ty, Ty)>,
diverges: Diverges,
breakables: Vec<BreakableContext>,
}
@@ -476,6 +485,7 @@ impl<'a> InferenceContext<'a> {
table: unify::InferenceTable::new(db, trait_env.clone()),
trait_env,
return_ty: TyKind::Error.intern(Interner), // set in collect_fn_signature
+ resume_yield_tys: None,
db,
owner,
body,
@@ -673,10 +683,6 @@ impl<'a> InferenceContext<'a> {
)
}
- fn resolve_obligations_as_possible(&mut self) {
- self.table.resolve_obligations_as_possible();
- }
-
fn push_obligation(&mut self, o: DomainGoal) {
self.table.register_obligation(o.cast(Interner));
}
@@ -696,7 +702,6 @@ impl<'a> InferenceContext<'a> {
}
fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
- self.resolve_obligations_as_possible();
self.table.resolve_ty_shallow(ty)
}
@@ -708,6 +713,8 @@ impl<'a> InferenceContext<'a> {
&mut self,
inner_ty: Ty,
assoc_ty: Option<TypeAliasId>,
+ // FIXME(GATs): these are args for the trait ref, args for assoc type itself should be
+ // handled when we support them.
params: &[GenericArg],
) -> Ty {
match assoc_ty {
@@ -799,7 +806,18 @@ impl<'a> InferenceContext<'a> {
self.resolve_variant_on_alias(ty, unresolved, path)
}
TypeNs::TypeAliasId(it) => {
- let ty = TyBuilder::def_ty(self.db, it.into())
+ let container = it.lookup(self.db.upcast()).container;
+ let parent_subst = match container {
+ ItemContainerId::TraitId(id) => {
+ let subst = TyBuilder::subst_for_def(self.db, id, None)
+ .fill_with_inference_vars(&mut self.table)
+ .build();
+ Some(subst)
+ }
+ // Type aliases do not exist in impls.
+ _ => None,
+ };
+ let ty = TyBuilder::def_ty(self.db, it.into(), parent_subst)
.fill_with_inference_vars(&mut self.table)
.build();
self.resolve_variant_on_alias(ty, unresolved, path)
@@ -878,6 +896,12 @@ impl<'a> InferenceContext<'a> {
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)?;
+ 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)?;
self.db.trait_data(trait_).associated_type_by_name(&name![Item])
}
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 3ead92909..094e460db 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
@@ -12,6 +12,7 @@ use crate::{
use super::{Expectation, InferenceContext};
impl InferenceContext<'_> {
+ // This function handles both closures and generators.
pub(super) fn deduce_closure_type_from_expectations(
&mut self,
closure_expr: ExprId,
@@ -27,6 +28,11 @@ impl InferenceContext<'_> {
// Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
let _ = self.coerce(Some(closure_expr), closure_ty, &expected_ty);
+ // Generators are not Fn* so return early.
+ if matches!(closure_ty.kind(Interner), TyKind::Generator(..)) {
+ return;
+ }
+
// Deduction based on the expected `dyn Fn` is done separately.
if let TyKind::Dyn(dyn_ty) = expected_ty.kind(Interner) {
if let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty) {
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 f54440bf5..8df25c83c 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
@@ -3,7 +3,7 @@
//! like going from `&Vec<T>` to `&[T]`.
//!
//! See <https://doc.rust-lang.org/nomicon/coercions.html> and
-//! `librustc_typeck/check/coercion.rs`.
+//! `rustc_hir_analysis/check/coercion.rs`.
use std::{iter, sync::Arc};
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 2d04a864a..f56108b26 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,7 +10,10 @@ use chalk_ir::{
cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind,
};
use hir_def::{
- expr::{ArithOp, Array, BinaryOp, CmpOp, Expr, ExprId, LabelId, Literal, Statement, UnaryOp},
+ expr::{
+ ArithOp, Array, BinaryOp, ClosureKind, CmpOp, Expr, ExprId, LabelId, Literal, Statement,
+ UnaryOp,
+ },
generics::TypeOrConstParamData,
path::{GenericArg, GenericArgs},
resolver::resolver_for_expr,
@@ -204,8 +207,10 @@ impl<'a> InferenceContext<'a> {
}
&Expr::For { iterable, body, pat, label } => {
let iterable_ty = self.infer_expr(iterable, &Expectation::none());
- let pat_ty =
+ let into_iter_ty =
self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item());
+ let pat_ty =
+ self.resolve_associated_type(into_iter_ty, self.resolve_iterator_item());
self.infer_pat(pat, &pat_ty, BindingMode::default());
self.with_breakable_ctx(BreakableKind::Loop, self.err_ty(), label, |this| {
@@ -216,7 +221,7 @@ impl<'a> InferenceContext<'a> {
self.diverges = Diverges::Maybe;
TyBuilder::unit()
}
- Expr::Closure { body, args, ret_type, arg_types } => {
+ Expr::Closure { body, args, ret_type, arg_types, closure_kind } => {
assert_eq!(args.len(), arg_types.len());
let mut sig_tys = Vec::new();
@@ -244,20 +249,40 @@ impl<'a> InferenceContext<'a> {
),
})
.intern(Interner);
- let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
- let closure_ty =
- TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
- .intern(Interner);
+
+ let (ty, resume_yield_tys) = if matches!(closure_kind, ClosureKind::Generator(_)) {
+ // FIXME: report error when there are more than 1 parameter.
+ let resume_ty = match sig_tys.first() {
+ // When `sig_tys.len() == 1` the first type is the return type, not the
+ // first parameter type.
+ Some(ty) if sig_tys.len() > 1 => ty.clone(),
+ _ => self.result.standard_types.unit.clone(),
+ };
+ let yield_ty = self.table.new_type_var();
+
+ let subst = TyBuilder::subst_for_generator(self.db, self.owner)
+ .push(resume_ty.clone())
+ .push(yield_ty.clone())
+ .push(ret_ty.clone())
+ .build();
+
+ let generator_id = self.db.intern_generator((self.owner, tgt_expr)).into();
+ let generator_ty = TyKind::Generator(generator_id, subst).intern(Interner);
+
+ (generator_ty, Some((resume_ty, yield_ty)))
+ } else {
+ let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
+ let closure_ty =
+ TyKind::Closure(closure_id, Substitution::from1(Interner, sig_ty.clone()))
+ .intern(Interner);
+
+ (closure_ty, None)
+ };
// Eagerly try to relate the closure type with the expected
// type, otherwise we often won't have enough information to
// infer the body.
- self.deduce_closure_type_from_expectations(
- tgt_expr,
- &closure_ty,
- &sig_ty,
- expected,
- );
+ self.deduce_closure_type_from_expectations(tgt_expr, &ty, &sig_ty, expected);
// Now go through the argument patterns
for (arg_pat, arg_ty) in args.iter().zip(sig_tys) {
@@ -266,6 +291,8 @@ impl<'a> InferenceContext<'a> {
let prev_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let prev_ret_ty = mem::replace(&mut self.return_ty, ret_ty.clone());
+ let prev_resume_yield_tys =
+ mem::replace(&mut self.resume_yield_tys, resume_yield_tys);
self.with_breakable_ctx(BreakableKind::Border, self.err_ty(), None, |this| {
this.infer_expr_coerce(*body, &Expectation::has_type(ret_ty));
@@ -273,8 +300,9 @@ impl<'a> InferenceContext<'a> {
self.diverges = prev_diverges;
self.return_ty = prev_ret_ty;
+ self.resume_yield_tys = prev_resume_yield_tys;
- closure_ty
+ ty
}
Expr::Call { callee, args, .. } => {
let callee_ty = self.infer_expr(*callee, &Expectation::none());
@@ -423,11 +451,18 @@ impl<'a> InferenceContext<'a> {
TyKind::Never.intern(Interner)
}
Expr::Yield { expr } => {
- // FIXME: track yield type for coercion
- if let Some(expr) = expr {
- self.infer_expr(*expr, &Expectation::none());
+ if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
+ if let Some(expr) = expr {
+ self.infer_expr_coerce(*expr, &Expectation::has_type(yield_ty));
+ } else {
+ let unit = self.result.standard_types.unit.clone();
+ let _ = self.coerce(Some(tgt_expr), &unit, &yield_ty);
+ }
+ resume_ty
+ } else {
+ // FIXME: report error (yield expr in non-generator)
+ TyKind::Error.intern(Interner)
}
- TyKind::Never.intern(Interner)
}
Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
@@ -952,11 +987,13 @@ impl<'a> InferenceContext<'a> {
let lhs_ty = self.infer_expr(lhs, &lhs_expectation);
let rhs_ty = self.table.new_type_var();
- let func = lang_names_for_bin_op(op).and_then(|(name, lang_item)| {
- self.db.trait_data(self.resolve_lang_item(lang_item)?.as_trait()?).method_by_name(&name)
+ let trait_func = lang_names_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))
});
- let func = match func {
- Some(func) => func,
+ 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));
@@ -966,7 +1003,9 @@ impl<'a> InferenceContext<'a> {
}
};
- let subst = TyBuilder::subst_for_def(self.db, func)
+ // HACK: We can use this substitution for the function because the function itself doesn't
+ // have its own generic parameters.
+ let subst = TyBuilder::subst_for_def(self.db, trait_, None)
.push(lhs_ty.clone())
.push(rhs_ty.clone())
.build();
@@ -1245,19 +1284,7 @@ impl<'a> InferenceContext<'a> {
assert_eq!(self_params, 0); // method shouldn't have another Self param
let total_len = parent_params + type_params + const_params + impl_trait_params;
let mut substs = Vec::with_capacity(total_len);
- // Parent arguments are unknown
- for (id, param) in def_generics.iter_parent() {
- match param {
- TypeOrConstParamData::TypeParamData(_) => {
- substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner));
- }
- TypeOrConstParamData::ConstParamData(_) => {
- let ty = self.db.const_param_ty(ConstParamId::from_unchecked(id));
- substs
- .push(GenericArgData::Const(self.table.new_const_var(ty)).intern(Interner));
- }
- }
- }
+
// handle provided arguments
if let Some(generic_args) = generic_args {
// if args are provided, it should be all of them, but we can't rely on that
@@ -1266,7 +1293,7 @@ impl<'a> InferenceContext<'a> {
.iter()
.filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
.take(type_params + const_params)
- .zip(def_generics.iter_id().skip(parent_params))
+ .zip(def_generics.iter_id())
{
if let Some(g) = generic_arg_to_chalk(
self.db,
@@ -1290,6 +1317,9 @@ impl<'a> InferenceContext<'a> {
}
}
};
+
+ // Handle everything else as unknown. This also handles generic arguments for the method's
+ // parent (impl or trait), which should come after those for the method.
for (id, data) in def_generics.iter().skip(substs.len()) {
match data {
TypeOrConstParamData::TypeParamData(_) => {
@@ -1327,9 +1357,13 @@ impl<'a> InferenceContext<'a> {
CallableDefId::FunctionId(f) => {
if let ItemContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container {
// construct a TraitRef
- let substs = crate::subst_prefix(
- &*parameters,
- generics(self.db.upcast(), trait_.into()).len(),
+ let params_len = parameters.len(Interner);
+ let trait_params_len = generics(self.db.upcast(), trait_.into()).len();
+ let substs = Substitution::from_iter(
+ Interner,
+ // The generic parameters for the trait come after those for the
+ // function.
+ &parameters.as_slice(Interner)[params_len - trait_params_len..],
);
self.push_obligation(
TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
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 f580e09e9..7a4754cdc 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
@@ -12,8 +12,8 @@ use crate::{
builder::ParamKind,
consteval,
method_resolution::{self, VisibleFromModule},
- GenericArgData, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
- ValueTyDefId,
+ utils::generics,
+ Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId,
};
use super::{ExprOrPatId, InferenceContext, TraitRef};
@@ -96,17 +96,21 @@ impl<'a> InferenceContext<'a> {
ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)),
};
- let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(Interner));
let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
let substs = ctx.substs_from_path(path, typable, true);
- let mut it = substs.as_slice(Interner)[parent_substs.len(Interner)..].iter().cloned();
- let ty = TyBuilder::value_ty(self.db, typable)
- .use_parent_substs(&parent_substs)
+ let substs = substs.as_slice(Interner);
+ let parent_substs = self_subst.or_else(|| {
+ let generics = generics(self.db.upcast(), typable.to_generic_def_id()?);
+ let parent_params_len = generics.parent_generics()?.len();
+ let parent_args = &substs[substs.len() - parent_params_len..];
+ Some(Substitution::from_iter(Interner, parent_args))
+ });
+ let parent_substs_len = parent_substs.as_ref().map_or(0, |s| s.len(Interner));
+ let mut it = substs.iter().take(substs.len() - parent_substs_len).cloned();
+ let ty = TyBuilder::value_ty(self.db, typable, parent_substs)
.fill(|x| {
it.next().unwrap_or_else(|| match x {
- ParamKind::Type => {
- GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner)
- }
+ ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
})
})
@@ -249,7 +253,7 @@ impl<'a> InferenceContext<'a> {
};
let substs = match container {
ItemContainerId::ImplId(impl_id) => {
- let impl_substs = TyBuilder::subst_for_def(self.db, impl_id)
+ let impl_substs = TyBuilder::subst_for_def(self.db, impl_id, None)
.fill_with_inference_vars(&mut self.table)
.build();
let impl_self_ty =
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 e77b55670..b00e3216b 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
@@ -4,7 +4,7 @@ use std::{fmt, mem, sync::Arc};
use chalk_ir::{
cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy,
- IntTy, NoSolution, TyVariableKind, UniverseIndex,
+ IntTy, TyVariableKind, UniverseIndex,
};
use chalk_solve::infer::ParameterEnaVariableExt;
use ena::unify::UnifyKey;
@@ -331,7 +331,6 @@ impl<'a> InferenceTable<'a> {
&mut resolve::Resolver { table: self, var_stack, fallback },
DebruijnIndex::INNERMOST,
)
- .expect("fold failed unexpectedly")
}
pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T
@@ -452,13 +451,14 @@ impl<'a> InferenceTable<'a> {
f: impl FnOnce(&mut Self) -> T,
) -> T {
use chalk_ir::fold::TypeFolder;
+
+ #[derive(chalk_derive::FallibleTypeFolder)]
+ #[has_interner(Interner)]
struct VarFudger<'a, 'b> {
table: &'a mut InferenceTable<'b>,
highest_known_var: InferenceVar,
}
impl<'a, 'b> TypeFolder<Interner> for VarFudger<'a, 'b> {
- type Error = NoSolution;
-
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
self
}
@@ -472,24 +472,24 @@ impl<'a> InferenceTable<'a> {
var: chalk_ir::InferenceVar,
kind: TyVariableKind,
_outer_binder: chalk_ir::DebruijnIndex,
- ) -> chalk_ir::Fallible<chalk_ir::Ty<Interner>> {
- Ok(if var < self.highest_known_var {
+ ) -> chalk_ir::Ty<Interner> {
+ if var < self.highest_known_var {
var.to_ty(Interner, kind)
} else {
self.table.new_type_var()
- })
+ }
}
fn fold_inference_lifetime(
&mut self,
var: chalk_ir::InferenceVar,
_outer_binder: chalk_ir::DebruijnIndex,
- ) -> chalk_ir::Fallible<chalk_ir::Lifetime<Interner>> {
- Ok(if var < self.highest_known_var {
+ ) -> chalk_ir::Lifetime<Interner> {
+ if var < self.highest_known_var {
var.to_lifetime(Interner)
} else {
self.table.new_lifetime_var()
- })
+ }
}
fn fold_inference_const(
@@ -497,12 +497,12 @@ impl<'a> InferenceTable<'a> {
ty: chalk_ir::Ty<Interner>,
var: chalk_ir::InferenceVar,
_outer_binder: chalk_ir::DebruijnIndex,
- ) -> chalk_ir::Fallible<chalk_ir::Const<Interner>> {
- Ok(if var < self.highest_known_var {
+ ) -> chalk_ir::Const<Interner> {
+ if var < self.highest_known_var {
var.to_const(Interner, ty)
} else {
self.table.new_const_var(ty)
- })
+ }
}
}
@@ -512,7 +512,6 @@ impl<'a> InferenceTable<'a> {
self.rollback_to(snapshot);
result
.fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST)
- .expect("fold_with with VarFudger")
}
/// This checks whether any of the free variables in the `canonicalized`
@@ -598,11 +597,14 @@ impl<'a> InferenceTable<'a> {
.build();
let projection = {
- let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type);
+ let b = TyBuilder::subst_for_def(self.db, fn_once_trait, None);
if b.remaining() != 2 {
return None;
}
- b.push(ty.clone()).push(arg_ty).build()
+ let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
+
+ TyBuilder::assoc_type_projection(self.db, output_assoc_type, Some(fn_once_subst))
+ .build()
};
let trait_env = self.trait_env.env.clone();
@@ -636,21 +638,24 @@ mod resolve {
use chalk_ir::{
cast::Cast,
fold::{TypeFoldable, TypeFolder},
- Fallible, NoSolution,
};
use hir_def::type_ref::ConstScalar;
- pub(super) struct Resolver<'a, 'b, F> {
+ #[derive(chalk_derive::FallibleTypeFolder)]
+ #[has_interner(Interner)]
+ pub(super) struct Resolver<
+ 'a,
+ 'b,
+ F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
+ > {
pub(super) table: &'a mut InferenceTable<'b>,
pub(super) var_stack: &'a mut Vec<InferenceVar>,
pub(super) fallback: F,
}
- impl<'a, 'b, 'i, F> TypeFolder<Interner> for Resolver<'a, 'b, F>
+ impl<'a, 'b, F> TypeFolder<Interner> for Resolver<'a, 'b, F>
where
- F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg + 'i,
+ F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
{
- type Error = NoSolution;
-
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
self
}
@@ -664,20 +669,19 @@ mod resolve {
var: InferenceVar,
kind: TyVariableKind,
outer_binder: DebruijnIndex,
- ) -> Fallible<Ty> {
+ ) -> Ty {
let var = self.table.var_unification_table.inference_var_root(var);
if self.var_stack.contains(&var) {
// recursive type
let default = self.table.fallback_value(var, kind).cast(Interner);
- return Ok((self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
+ return (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
.assert_ty_ref(Interner)
- .clone());
+ .clone();
}
let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
// known_ty may contain other variables that are known by now
self.var_stack.push(var);
- let result =
- known_ty.fold_with(self, outer_binder).expect("fold failed unexpectedly");
+ let result = known_ty.fold_with(self, outer_binder);
self.var_stack.pop();
result.assert_ty_ref(Interner).clone()
} else {
@@ -686,7 +690,7 @@ mod resolve {
.assert_ty_ref(Interner)
.clone()
};
- Ok(result)
+ result
}
fn fold_inference_const(
@@ -694,7 +698,7 @@ mod resolve {
ty: Ty,
var: InferenceVar,
outer_binder: DebruijnIndex,
- ) -> Fallible<Const> {
+ ) -> Const {
let var = self.table.var_unification_table.inference_var_root(var);
let default = ConstData {
ty: ty.clone(),
@@ -704,35 +708,33 @@ mod resolve {
.cast(Interner);
if self.var_stack.contains(&var) {
// recursive
- return Ok((self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
+ return (self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
.assert_const_ref(Interner)
- .clone());
+ .clone();
}
- let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
+ if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
// known_ty may contain other variables that are known by now
self.var_stack.push(var);
- let result =
- known_ty.fold_with(self, outer_binder).expect("fold failed unexpectedly");
+ let result = known_ty.fold_with(self, outer_binder);
self.var_stack.pop();
result.assert_const_ref(Interner).clone()
} else {
(self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
.assert_const_ref(Interner)
.clone()
- };
- Ok(result)
+ }
}
fn fold_inference_lifetime(
&mut self,
_var: InferenceVar,
_outer_binder: DebruijnIndex,
- ) -> Fallible<Lifetime> {
+ ) -> Lifetime {
// fall back all lifetimes to 'static -- currently we don't deal
// with any lifetimes, but we can sometimes get some lifetime
// variables through Chalk's unification, and this at least makes
// sure we don't leak them outside of inference
- Ok(crate::static_lifetime())
+ crate::static_lifetime()
}
}
}
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 a82a331d4..c4b700cbc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -196,20 +196,6 @@ pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
make_binders_with_count(db, usize::MAX, generics, value)
}
-// FIXME: get rid of this
-pub fn make_canonical<T: HasInterner<Interner = Interner>>(
- value: T,
- kinds: impl IntoIterator<Item = TyVariableKind>,
-) -> Canonical<T> {
- let kinds = kinds.into_iter().map(|tk| {
- chalk_ir::CanonicalVarKind::new(
- chalk_ir::VariableKind::Ty(tk),
- chalk_ir::UniverseIndex::ROOT,
- )
- });
- Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(Interner, kinds) }
-}
-
// FIXME: get rid of this, just replace it by FnPointer
/// A function signature as seen by type inference: Several parameter types and
/// one return type.
@@ -268,13 +254,13 @@ impl CallableSig {
}
impl TypeFoldable<Interner> for CallableSig {
- fn fold_with<E>(
+ fn try_fold_with<E>(
self,
- folder: &mut dyn chalk_ir::fold::TypeFolder<Interner, Error = E>,
+ folder: &mut dyn chalk_ir::fold::FallibleTypeFolder<Interner, Error = E>,
outer_binder: DebruijnIndex,
) -> Result<Self, E> {
let vec = self.params_and_return.to_vec();
- let folded = vec.fold_with(folder, outer_binder)?;
+ let folded = vec.try_fold_with(folder, outer_binder)?;
Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
}
}
@@ -306,16 +292,19 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
for_const: impl FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
) -> T {
- use chalk_ir::{fold::TypeFolder, Fallible};
- struct FreeVarFolder<F1, F2>(F1, F2);
+ use chalk_ir::fold::TypeFolder;
+
+ #[derive(chalk_derive::FallibleTypeFolder)]
+ #[has_interner(Interner)]
+ struct FreeVarFolder<
+ F1: FnMut(BoundVar, DebruijnIndex) -> Ty,
+ F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
+ >(F1, F2);
impl<
- 'i,
- F1: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i,
- F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const + 'i,
+ F1: FnMut(BoundVar, DebruijnIndex) -> Ty,
+ F2: FnMut(Ty, BoundVar, DebruijnIndex) -> Const,
> TypeFolder<Interner> for FreeVarFolder<F1, F2>
{
- type Error = NoSolution;
-
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
self
}
@@ -324,12 +313,8 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
Interner
}
- fn fold_free_var_ty(
- &mut self,
- bound_var: BoundVar,
- outer_binder: DebruijnIndex,
- ) -> Fallible<Ty> {
- Ok(self.0(bound_var, outer_binder))
+ fn fold_free_var_ty(&mut self, bound_var: BoundVar, outer_binder: DebruijnIndex) -> Ty {
+ self.0(bound_var, outer_binder)
}
fn fold_free_var_const(
@@ -337,12 +322,11 @@ pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<
ty: Ty,
bound_var: BoundVar,
outer_binder: DebruijnIndex,
- ) -> Fallible<Const> {
- Ok(self.1(ty, bound_var, outer_binder))
+ ) -> Const {
+ self.1(ty, bound_var, outer_binder)
}
}
t.fold_with(&mut FreeVarFolder(for_ty, for_const), DebruijnIndex::INNERMOST)
- .expect("fold failed unexpectedly")
}
pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
@@ -365,16 +349,13 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
f: impl FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>,
binders: DebruijnIndex,
) -> T {
- use chalk_ir::{
- fold::{TypeFolder, TypeSuperFoldable},
- Fallible,
- };
- struct TyFolder<F>(F);
- impl<'i, F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const> + 'i>
- TypeFolder<Interner> for TyFolder<F>
+ use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
+ #[derive(chalk_derive::FallibleTypeFolder)]
+ #[has_interner(Interner)]
+ struct TyFolder<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>>(F);
+ impl<F: FnMut(Either<Ty, Const>, DebruijnIndex) -> Either<Ty, Const>> TypeFolder<Interner>
+ for TyFolder<F>
{
- type Error = NoSolution;
-
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
self
}
@@ -383,16 +364,16 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
Interner
}
- fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
- let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
- Ok(self.0(Either::Left(ty), outer_binder).left().unwrap())
+ fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
+ let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
+ self.0(Either::Left(ty), outer_binder).left().unwrap()
}
- fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Fallible<Const> {
- Ok(self.0(Either::Right(c), outer_binder).right().unwrap())
+ fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
+ self.0(Either::Right(c), outer_binder).right().unwrap()
}
}
- t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
+ t.fold_with(&mut TyFolder(f), binders)
}
/// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
@@ -404,16 +385,16 @@ where
T: HasInterner<Interner = Interner>,
{
use chalk_ir::{
- fold::{TypeFolder, TypeSuperFoldable},
+ fold::{FallibleTypeFolder, TypeSuperFoldable},
Fallible,
};
struct ErrorReplacer {
vars: usize,
}
- impl TypeFolder<Interner> for ErrorReplacer {
+ impl FallibleTypeFolder<Interner> for ErrorReplacer {
type Error = NoSolution;
- fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
+ fn as_dyn(&mut self) -> &mut dyn FallibleTypeFolder<Interner, Error = Self::Error> {
self
}
@@ -421,18 +402,17 @@ where
Interner
}
- fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
+ fn try_fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
if let TyKind::Error = ty.kind(Interner) {
let index = self.vars;
self.vars += 1;
Ok(TyKind::BoundVar(BoundVar::new(outer_binder, index)).intern(Interner))
} else {
- let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
- Ok(ty)
+ ty.try_super_fold_with(self.as_dyn(), outer_binder)
}
}
- fn fold_inference_ty(
+ fn try_fold_inference_ty(
&mut self,
_var: InferenceVar,
_kind: TyVariableKind,
@@ -447,7 +427,7 @@ where
}
}
- fn fold_free_var_ty(
+ fn try_fold_free_var_ty(
&mut self,
_bound_var: BoundVar,
_outer_binder: DebruijnIndex,
@@ -461,7 +441,7 @@ where
}
}
- fn fold_inference_const(
+ fn try_fold_inference_const(
&mut self,
ty: Ty,
_var: InferenceVar,
@@ -474,7 +454,7 @@ where
}
}
- fn fold_free_var_const(
+ fn try_fold_free_var_const(
&mut self,
ty: Ty,
_bound_var: BoundVar,
@@ -487,7 +467,7 @@ where
}
}
- fn fold_inference_lifetime(
+ fn try_fold_inference_lifetime(
&mut self,
_var: InferenceVar,
_outer_binder: DebruijnIndex,
@@ -499,7 +479,7 @@ where
}
}
- fn fold_free_var_lifetime(
+ fn try_fold_free_var_lifetime(
&mut self,
_bound_var: BoundVar,
_outer_binder: DebruijnIndex,
@@ -512,7 +492,7 @@ where
}
}
let mut error_replacer = ErrorReplacer { vars: 0 };
- let value = match t.clone().fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) {
+ let value = match t.clone().try_fold_with(&mut error_replacer, DebruijnIndex::INNERMOST) {
Ok(t) => t,
Err(_) => panic!("Encountered unbound or inference vars in {:?}", t),
};
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 532544fee..223d705b1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -306,7 +306,7 @@ impl<'a> TyLoweringContext<'a> {
// FIXME we're probably doing something wrong here
self.impl_trait_counter.set(idx + count_impl_traits(type_ref) as u16);
let (
- parent_params,
+ _parent_params,
self_params,
list_params,
const_params,
@@ -319,7 +319,7 @@ impl<'a> TyLoweringContext<'a> {
};
TyKind::BoundVar(BoundVar::new(
self.in_binders,
- idx as usize + parent_params + self_params + list_params + const_params,
+ idx as usize + self_params + list_params + const_params,
))
.intern(Interner)
}
@@ -499,14 +499,31 @@ impl<'a> TyLoweringContext<'a> {
.intern(Interner)
}
TypeNs::SelfType(impl_id) => {
- let generics = generics(self.db.upcast(), impl_id.into());
- let substs = match self.type_param_mode {
- ParamLoweringMode::Placeholder => generics.placeholder_subst(self.db),
+ let def =
+ self.resolver.generic_def().expect("impl should have generic param scope");
+ let generics = generics(self.db.upcast(), def);
+
+ match self.type_param_mode {
+ ParamLoweringMode::Placeholder => {
+ // `def` can be either impl itself or item within, and we need impl itself
+ // now.
+ let generics = generics.parent_generics().unwrap_or(&generics);
+ let subst = generics.placeholder_subst(self.db);
+ self.db.impl_self_ty(impl_id).substitute(Interner, &subst)
+ }
ParamLoweringMode::Variable => {
- generics.bound_vars_subst(self.db, self.in_binders)
+ let starting_from = match def {
+ GenericDefId::ImplId(_) => 0,
+ // `def` is an item within impl. We need to substitute `BoundVar`s but
+ // remember that they are for parent (i.e. impl) generic params so they
+ // come after our own params.
+ _ => generics.len_self(),
+ };
+ TyBuilder::impl_self_ty(self.db, impl_id)
+ .fill_with_bound_vars(self.in_binders, starting_from)
+ .build()
}
- };
- self.db.impl_self_ty(impl_id).substitute(Interner, &substs)
+ }
}
TypeNs::AdtSelfType(adt) => {
let generics = generics(self.db.upcast(), adt.into());
@@ -663,40 +680,31 @@ impl<'a> TyLoweringContext<'a> {
fn substs_from_path_segment(
&self,
segment: PathSegment<'_>,
- def_generic: Option<GenericDefId>,
+ def: Option<GenericDefId>,
infer_args: bool,
explicit_self_ty: Option<Ty>,
) -> Substitution {
+ // Remember that the item's own generic args come before its parent's.
let mut substs = Vec::new();
- let def_generics = if let Some(def) = def_generic {
- generics(self.db.upcast(), def)
+ let def = if let Some(d) = def {
+ d
} else {
return Substitution::empty(Interner);
};
+ let def_generics = generics(self.db.upcast(), def);
let (parent_params, self_params, type_params, const_params, impl_trait_params) =
def_generics.provenance_split();
- let total_len =
- parent_params + self_params + type_params + const_params + impl_trait_params;
+ let item_len = self_params + type_params + const_params + impl_trait_params;
+ let total_len = parent_params + item_len;
- let ty_error = GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner);
+ let ty_error = TyKind::Error.intern(Interner).cast(Interner);
let mut def_generic_iter = def_generics.iter_id();
- for _ in 0..parent_params {
- if let Some(eid) = def_generic_iter.next() {
- match eid {
- Either::Left(_) => substs.push(ty_error.clone()),
- Either::Right(x) => {
- substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
- }
- }
- }
- }
-
let fill_self_params = || {
for x in explicit_self_ty
.into_iter()
- .map(|x| GenericArgData::Ty(x).intern(Interner))
+ .map(|x| x.cast(Interner))
.chain(iter::repeat(ty_error.clone()))
.take(self_params)
{
@@ -757,37 +765,40 @@ impl<'a> TyLoweringContext<'a> {
fill_self_params();
}
+ // These params include those of parent.
+ let remaining_params: SmallVec<[_; 2]> = def_generic_iter
+ .map(|eid| match eid {
+ Either::Left(_) => ty_error.clone(),
+ Either::Right(x) => unknown_const_as_generic(self.db.const_param_ty(x)),
+ })
+ .collect();
+ assert_eq!(remaining_params.len() + substs.len(), total_len);
+
// handle defaults. In expression or pattern path segments without
// explicitly specified type arguments, missing type arguments are inferred
// (i.e. defaults aren't used).
if !infer_args || had_explicit_args {
- if let Some(def_generic) = def_generic {
- let defaults = self.db.generic_defaults(def_generic);
- assert_eq!(total_len, defaults.len());
-
- for default_ty in defaults.iter().skip(substs.len()) {
- // each default can depend on the previous parameters
- let substs_so_far = Substitution::from_iter(Interner, substs.clone());
- if let Some(_id) = def_generic_iter.next() {
- substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
- }
- }
+ let defaults = self.db.generic_defaults(def);
+ assert_eq!(total_len, defaults.len());
+ let parent_from = item_len - substs.len();
+
+ for (idx, default_ty) in defaults[substs.len()..item_len].iter().enumerate() {
+ // each default can depend on the previous parameters
+ let substs_so_far = Substitution::from_iter(
+ Interner,
+ substs.iter().cloned().chain(remaining_params[idx..].iter().cloned()),
+ );
+ substs.push(default_ty.clone().substitute(Interner, &substs_so_far));
}
- }
- // add placeholders for args that were not provided
- // FIXME: emit diagnostics in contexts where this is not allowed
- for eid in def_generic_iter {
- match eid {
- Either::Left(_) => substs.push(ty_error.clone()),
- Either::Right(x) => {
- substs.push(unknown_const_as_generic(self.db.const_param_ty(x)))
- }
- }
+ // Keep parent's params as unknown.
+ let mut remaining_params = remaining_params;
+ substs.extend(remaining_params.drain(parent_from..));
+ } else {
+ substs.extend(remaining_params);
}
- // If this assert fails, it means you pushed into subst but didn't call .next() of def_generic_iter
- assert_eq!(substs.len(), total_len);
+ assert_eq!(substs.len(), total_len);
Substitution::from_iter(Interner, substs)
}
@@ -981,10 +992,11 @@ impl<'a> TyLoweringContext<'a> {
fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
- // INVARIANT: The principal trait bound must come first. Others may be in any order but
- // should be in the same order for the same set but possibly different order of bounds in
- // the input.
- // This invariant is used by `TyExt::dyn_trait()` and chalk.
+ // INVARIANT: The principal trait bound, if present, must come first. Others may be in any
+ // order but should be in the same order for the same set but possibly different order of
+ // bounds in the input.
+ // INVARIANT: If this function returns `DynTy`, there should be at least one trait bound.
+ // These invariants are utilized by `TyExt::dyn_trait()` and chalk.
let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
let mut bounds: Vec<_> = bounds
.iter()
@@ -1035,6 +1047,12 @@ impl<'a> TyLoweringContext<'a> {
return None;
}
+ if bounds.first().and_then(|b| b.trait_id()).is_none() {
+ // When there's no trait bound, that's an error. This happens when the trait refs
+ // are unresolved.
+ return None;
+ }
+
// As multiple occurrences of the same auto traits *are* permitted, we dedulicate the
// bounds. We shouldn't have repeated elements besides auto traits at this point.
bounds.dedup();
@@ -1046,7 +1064,8 @@ impl<'a> TyLoweringContext<'a> {
let bounds = crate::make_single_type_binders(bounds);
TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
} else {
- // FIXME: report error (additional non-auto traits or associated type rebound)
+ // FIXME: report error
+ // (additional non-auto traits, associated type rebound, or no resolved trait)
TyKind::Error.intern(Interner)
}
}
@@ -1139,11 +1158,28 @@ fn named_associated_type_shorthand_candidates<R>(
};
match res {
- TypeNs::SelfType(impl_id) => search(
+ TypeNs::SelfType(impl_id) => {
// we're _in_ the impl -- the binders get added back later. Correct,
// but it would be nice to make this more explicit
- db.impl_trait(impl_id)?.into_value_and_skipped_binders().0,
- ),
+ let trait_ref = db.impl_trait(impl_id)?.into_value_and_skipped_binders().0;
+
+ let impl_id_as_generic_def: GenericDefId = impl_id.into();
+ if impl_id_as_generic_def != def {
+ // `trait_ref` contains `BoundVar`s bound by impl's `Binders`, but here we need
+ // `BoundVar`s from `def`'s point of view.
+ // FIXME: A `HirDatabase` query may be handy if this process is needed in more
+ // places. It'd be almost identical as `impl_trait_query` where `resolver` would be
+ // of `def` instead of `impl_id`.
+ let starting_idx = generics(db.upcast(), def).len_self();
+ let subst = TyBuilder::subst_for_def(db, impl_id, None)
+ .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
+ .build();
+ let trait_ref = subst.apply(trait_ref, Interner);
+ search(trait_ref)
+ } else {
+ search(trait_ref)
+ }
+ }
TypeNs::GenericParam(param_id) => {
let predicates = db.generic_predicates_for_param(def, param_id.into(), assoc_name);
let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
@@ -1160,10 +1196,18 @@ fn named_associated_type_shorthand_candidates<R>(
}
// Handle `Self::Type` referring to own associated type in trait definitions
if let GenericDefId::TraitId(trait_id) = param_id.parent() {
- let generics = generics(db.upcast(), trait_id.into());
- if generics.params.type_or_consts[param_id.local_id()].is_trait_self() {
+ let trait_generics = generics(db.upcast(), trait_id.into());
+ if trait_generics.params.type_or_consts[param_id.local_id()].is_trait_self() {
+ let def_generics = generics(db.upcast(), def);
+ let starting_idx = match def {
+ GenericDefId::TraitId(_) => 0,
+ // `def` is an item within trait. We need to substitute `BoundVar`s but
+ // remember that they are for parent (i.e. trait) generic params so they
+ // come after our own params.
+ _ => def_generics.len_self(),
+ };
let trait_ref = TyBuilder::trait_ref(db, trait_id)
- .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
+ .fill_with_bound_vars(DebruijnIndex::INNERMOST, starting_idx)
.build();
return search(trait_ref);
}
@@ -1405,6 +1449,7 @@ pub(crate) fn generic_defaults_query(
let ctx =
TyLoweringContext::new(db, &resolver).with_type_param_mode(ParamLoweringMode::Variable);
let generic_params = generics(db.upcast(), def);
+ let parent_start_idx = generic_params.len_self();
let defaults = generic_params
.iter()
@@ -1417,19 +1462,17 @@ pub(crate) fn generic_defaults_query(
let val = unknown_const_as_generic(
db.const_param_ty(ConstParamId::from_unchecked(id)),
);
- return crate::make_binders_with_count(db, idx, &generic_params, val);
+ return make_binders(db, &generic_params, val);
}
};
let mut ty =
p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
// Each default can only refer to previous parameters.
- // type variable default referring to parameter coming
- // after it. This is forbidden (FIXME: report
- // diagnostic)
- ty = fallback_bound_vars(ty, idx);
- let val = GenericArgData::Ty(ty).intern(Interner);
- crate::make_binders_with_count(db, idx, &generic_params, val)
+ // Type variable default referring to parameter coming
+ // after it is forbidden (FIXME: report diagnostic)
+ ty = fallback_bound_vars(ty, idx, parent_start_idx);
+ crate::make_binders(db, &generic_params, ty.cast(Interner))
})
.collect();
@@ -1446,15 +1489,14 @@ pub(crate) fn generic_defaults_recover(
// we still need one default per parameter
let defaults = generic_params
.iter_id()
- .enumerate()
- .map(|(count, id)| {
+ .map(|id| {
let val = match id {
itertools::Either::Left(_) => {
GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner)
}
itertools::Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
};
- crate::make_binders_with_count(db, count, &generic_params, val)
+ crate::make_binders(db, &generic_params, val)
})
.collect();
@@ -1633,6 +1675,19 @@ pub enum ValueTyDefId {
}
impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for ValueTyDefId);
+impl ValueTyDefId {
+ pub(crate) fn to_generic_def_id(self) -> Option<GenericDefId> {
+ match self {
+ Self::FunctionId(id) => Some(id.into()),
+ Self::StructId(id) => Some(id.into()),
+ Self::UnionId(id) => Some(id.into()),
+ Self::EnumVariantId(var) => Some(var.into()),
+ Self::ConstId(id) => Some(id.into()),
+ Self::StaticId(_) => None,
+ }
+ }
+}
+
/// Build the declared type of an item. This depends on the namespace; e.g. for
/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
/// the constructor function `(usize) -> Foo` which lives in the values
@@ -1816,26 +1871,48 @@ pub(crate) fn const_or_path_to_chalk(
}
}
-/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
-/// num_vars_to_keep) by `TyKind::Unknown`.
+/// Replaces any 'free' `BoundVar`s in `s` by `TyKind::Error` from the perspective of generic
+/// parameter whose index is `param_index`. A `BoundVar` is free when it is or (syntactically)
+/// appears after the generic parameter of `param_index`.
fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
s: T,
- num_vars_to_keep: usize,
+ param_index: usize,
+ parent_start: usize,
) -> T {
+ // Keep in mind that parent generic parameters, if any, come *after* those of the item in
+ // question. In the diagrams below, `c*` and `p*` represent generic parameters of the item and
+ // its parent respectively.
+ let is_allowed = |index| {
+ if param_index < parent_start {
+ // The parameter of `param_index` is one from the item in question. Any parent generic
+ // parameters or the item's generic parameters that come before `param_index` is
+ // allowed.
+ // [c1, .., cj, .., ck, p1, .., pl] where cj is `param_index`
+ // ^^^^^^ ^^^^^^^^^^ these are allowed
+ !(param_index..parent_start).contains(&index)
+ } else {
+ // The parameter of `param_index` is one from the parent generics. Only parent generic
+ // parameters that come before `param_index` are allowed.
+ // [c1, .., ck, p1, .., pj, .., pl] where pj is `param_index`
+ // ^^^^^^ these are allowed
+ (parent_start..param_index).contains(&index)
+ }
+ };
+
crate::fold_free_vars(
s,
|bound, binders| {
- if bound.index >= num_vars_to_keep && bound.debruijn == DebruijnIndex::INNERMOST {
- TyKind::Error.intern(Interner)
- } else {
+ if bound.index_if_innermost().map_or(true, is_allowed) {
bound.shifted_in_from(binders).to_ty(Interner)
+ } else {
+ TyKind::Error.intern(Interner)
}
},
|ty, bound, binders| {
- if bound.index >= num_vars_to_keep && bound.debruijn == DebruijnIndex::INNERMOST {
- unknown_const(ty.clone())
- } else {
+ if bound.index_if_innermost().map_or(true, is_allowed) {
bound.shifted_in_from(binders).to_const(Interner, ty)
+ } else {
+ unknown_const(ty.clone())
}
},
)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
index d765fee0e..f80fb39c1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
@@ -103,6 +103,18 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
}
}
+impl From<chalk_ir::GeneratorId<Interner>> for crate::db::InternedGeneratorId {
+ fn from(id: chalk_ir::GeneratorId<Interner>) -> Self {
+ Self::from_intern_id(id.0)
+ }
+}
+
+impl From<crate::db::InternedGeneratorId> for chalk_ir::GeneratorId<Interner> {
+ fn from(id: crate::db::InternedGeneratorId) -> Self {
+ chalk_ir::GeneratorId(id.as_intern_id())
+ }
+}
+
pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
}
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 9a63d5013..3a1a3f4fd 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
@@ -1,7 +1,7 @@
//! This module is concerned with finding methods that a given type provides.
//! For details about how this works in rustc, see the method lookup page in the
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
-//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
+//! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
use std::{iter, ops::ControlFlow, sync::Arc};
use arrayvec::ArrayVec;
@@ -654,7 +654,7 @@ fn find_matching_impl(
let r = table.run_in_snapshot(|table| {
let impl_data = db.impl_data(impl_);
let substs =
- TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build();
+ TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
let impl_ty = db.impl_self_ty(impl_).substitute(Interner, &substs);
table
@@ -914,22 +914,10 @@ fn iterate_trait_method_candidates(
let db = table.db;
let env = table.trait_env.clone();
let self_is_array = matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..));
- // if ty is `dyn Trait`, the trait doesn't need to be in scope
- let inherent_trait =
- self_ty.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
- let env_traits = matches!(self_ty.kind(Interner), TyKind::Placeholder(_))
- // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
- .then(|| {
- env.traits_in_scope_from_clauses(self_ty.clone())
- .flat_map(|t| all_super_traits(db.upcast(), t))
- })
- .into_iter()
- .flatten();
- let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
- 'traits: for t in traits {
+ 'traits: for &t in traits_in_scope {
let data = db.trait_data(t);
// Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during
@@ -979,6 +967,44 @@ fn iterate_inherent_methods(
) -> ControlFlow<()> {
let db = table.db;
let env = table.trait_env.clone();
+
+ // For trait object types and placeholder types with trait bounds, the methods of the trait and
+ // its super traits are considered inherent methods. This matters because these methods have
+ // higher priority than the other traits' methods, which would be considered in
+ // `iterate_trait_method_candidates()` only after this function.
+ match self_ty.kind(Interner) {
+ TyKind::Placeholder(_) => {
+ let env = table.trait_env.clone();
+ let traits = env
+ .traits_in_scope_from_clauses(self_ty.clone())
+ .flat_map(|t| all_super_traits(db.upcast(), t));
+ iterate_inherent_trait_methods(
+ self_ty,
+ table,
+ name,
+ receiver_ty,
+ receiver_adjustments.clone(),
+ callback,
+ traits,
+ )?;
+ }
+ TyKind::Dyn(_) => {
+ if let Some(principal_trait) = self_ty.dyn_trait() {
+ let traits = all_super_traits(db.upcast(), principal_trait);
+ iterate_inherent_trait_methods(
+ self_ty,
+ table,
+ name,
+ receiver_ty,
+ receiver_adjustments.clone(),
+ callback,
+ traits.into_iter(),
+ )?;
+ }
+ }
+ _ => {}
+ }
+
let def_crates = match def_crates(db, self_ty, env.krate) {
Some(k) => k,
None => return ControlFlow::Continue(()),
@@ -1020,6 +1046,28 @@ fn iterate_inherent_methods(
}
return ControlFlow::Continue(());
+ fn iterate_inherent_trait_methods(
+ self_ty: &Ty,
+ table: &mut InferenceTable<'_>,
+ name: Option<&Name>,
+ receiver_ty: Option<&Ty>,
+ receiver_adjustments: Option<ReceiverAdjustments>,
+ callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId) -> ControlFlow<()>,
+ traits: impl Iterator<Item = TraitId>,
+ ) -> ControlFlow<()> {
+ let db = table.db;
+ for t in traits {
+ let data = db.trait_data(t);
+ for &(_, item) in data.items.iter() {
+ // We don't pass `visible_from_module` as all trait items should be visible.
+ if is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
+ callback(receiver_adjustments.clone().unwrap_or_default(), item)?;
+ }
+ }
+ }
+ ControlFlow::Continue(())
+ }
+
fn impls_for_self_ty(
impls: &InherentImpls,
self_ty: &Ty,
@@ -1099,10 +1147,9 @@ fn is_valid_candidate(
}));
if let ItemContainerId::ImplId(impl_id) = c.lookup(db.upcast()).container {
let self_ty_matches = table.run_in_snapshot(|table| {
- let subst =
- TyBuilder::subst_for_def(db, c).fill_with_inference_vars(table).build();
- let expected_self_ty =
- subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner);
+ let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id)
+ .fill_with_inference_vars(table)
+ .build();
table.unify(&expected_self_ty, &self_ty)
});
if !self_ty_matches {
@@ -1138,31 +1185,26 @@ fn is_valid_fn_candidate(
table.run_in_snapshot(|table| {
let container = fn_id.lookup(db.upcast()).container;
- let impl_subst = match container {
+ let (impl_subst, expect_self_ty) = match container {
ItemContainerId::ImplId(it) => {
- TyBuilder::subst_for_def(db, it).fill_with_inference_vars(table).build()
+ let subst =
+ TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
+ let self_ty = db.impl_self_ty(it).substitute(Interner, &subst);
+ (subst, self_ty)
}
ItemContainerId::TraitId(it) => {
- TyBuilder::subst_for_def(db, it).fill_with_inference_vars(table).build()
+ let subst =
+ TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
+ let self_ty = subst.at(Interner, 0).assert_ty_ref(Interner).clone();
+ (subst, self_ty)
}
_ => unreachable!(),
};
- let fn_subst = TyBuilder::subst_for_def(db, fn_id)
- .use_parent_substs(&impl_subst)
+ let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
.fill_with_inference_vars(table)
.build();
- let expect_self_ty = match container {
- ItemContainerId::TraitId(_) => fn_subst.at(Interner, 0).assert_ty_ref(Interner).clone(),
- ItemContainerId::ImplId(impl_id) => {
- fn_subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner)
- }
- // We should only get called for associated items (impl/trait)
- ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
- unreachable!()
- }
- };
check_that!(table.unify(&expect_self_ty, self_ty));
if let Some(receiver_ty) = receiver_ty {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index d2f13e435..ebbc54101 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -16,7 +16,7 @@ use base_db::{fixture::WithFixture, FileRange, SourceDatabaseExt};
use expect_test::Expect;
use hir_def::{
body::{Body, BodySourceMap, SyntheticSyntax},
- db::DefDatabase,
+ db::{DefDatabase, InternDatabase},
expr::{ExprId, PatId},
item_scope::ItemScope,
nameres::DefMap,
@@ -135,6 +135,10 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start()
}
+ DefWithBodyId::VariantId(it) => {
+ let loc = db.lookup_intern_enum(it.parent);
+ loc.source(&db).value.syntax().text_range().start()
+ }
});
let mut unexpected_type_mismatches = String::new();
for def in defs {
@@ -388,6 +392,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let loc = it.lookup(&db);
loc.source(&db).value.syntax().text_range().start()
}
+ DefWithBodyId::VariantId(it) => {
+ let loc = db.lookup_intern_enum(it.parent);
+ loc.source(&db).value.syntax().text_range().start()
+ }
});
for def in defs {
let (_body, source_map) = db.body_with_source_map(def);
@@ -453,6 +461,18 @@ fn visit_module(
let body = db.body(def);
visit_body(db, &body, cb);
}
+ ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
+ db.enum_data(it)
+ .variants
+ .iter()
+ .map(|(id, _)| hir_def::EnumVariantId { parent: it, local_id: id })
+ .for_each(|it| {
+ let def = it.into();
+ cb(def);
+ let body = db.body(def);
+ visit_body(db, &body, cb);
+ });
+ }
ModuleDefId::TraitId(it) => {
let trait_data = db.trait_data(it);
for &(_, item) in trait_data.items.iter() {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
index bf59fadc2..d301595bc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/coercion.rs
@@ -295,6 +295,24 @@ fn foo() {
}
#[test]
+fn generator_yield_return_coerce() {
+ check_no_mismatches(
+ r#"
+fn test() {
+ let g = || {
+ yield &1u32;
+ yield &&1u32;
+ if true {
+ return &1u32;
+ }
+ &&1u32
+ };
+}
+ "#,
+ );
+}
+
+#[test]
fn assign_coerce() {
check_no_mismatches(
r"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
index 240942e48..8a8ff08cf 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
@@ -56,6 +56,28 @@ fn main() {
}
#[test]
+fn render_dyn_ty_independent_of_order() {
+ check_types_source_code(
+ r#"
+auto trait Send {}
+trait A {
+ type Assoc;
+}
+trait B: A {}
+
+fn test(
+ _: &(dyn A<Assoc = ()> + Send),
+ //^ &(dyn A<Assoc = ()> + Send)
+ _: &(dyn Send + A<Assoc = ()>),
+ //^ &(dyn A<Assoc = ()> + Send)
+ _: &dyn B<Assoc = ()>,
+ //^ &(dyn B<Assoc = ()>)
+) {}
+ "#,
+ );
+}
+
+#[test]
fn render_dyn_for_ty() {
// FIXME
check_types_source_code(
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 81588a7c4..ac8edb841 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
@@ -1219,6 +1219,40 @@ fn main() {
}
#[test]
+fn dyn_trait_method_priority() {
+ check_types(
+ r#"
+//- minicore: from
+trait Trait {
+ fn into(&self) -> usize { 0 }
+}
+
+fn foo(a: &dyn Trait) {
+ let _ = a.into();
+ //^usize
+}
+ "#,
+ );
+}
+
+#[test]
+fn trait_method_priority_for_placeholder_type() {
+ check_types(
+ r#"
+//- minicore: from
+trait Trait {
+ fn into(&self) -> usize { 0 }
+}
+
+fn foo<T: Trait>(a: &T) {
+ let _ = a.into();
+ //^usize
+}
+ "#,
+ );
+}
+
+#[test]
fn autoderef_visibility_field() {
check(
r#"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index eb04bf877..74de33117 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -1070,3 +1070,13 @@ fn main() {
"#,
);
}
+
+#[test]
+fn cfg_params() {
+ check_types(
+ r#"
+fn my_fn(#[cfg(feature = "feature")] u8: u8, u32: u32) {}
+ //^^^ u32
+"#,
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
index 23e51a9c1..a155adcec 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs
@@ -1488,7 +1488,6 @@ fn regression_11688_4() {
#[test]
fn gat_crash_1() {
- cov_mark::check!(ignore_gats);
check_no_mismatches(
r#"
trait ATrait {}
@@ -1527,30 +1526,22 @@ unsafe impl Storage for InlineStorage {
#[test]
fn gat_crash_3() {
- // FIXME: This test currently crashes rust analyzer in a debug build but not in a
- // release build (i.e. for the user). With the assumption that tests will always be run
- // in debug mode, we catch the unwind and expect that it panicked. See the
- // [`crate::utils::generics`] function for more information.
- cov_mark::check!(ignore_gats);
- std::panic::catch_unwind(|| {
- check_no_mismatches(
- r#"
+ check_no_mismatches(
+ r#"
trait Collection {
- type Item;
- type Member<T>: Collection<Item = T>;
- fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>;
+type Item;
+type Member<T>: Collection<Item = T>;
+fn add(&mut self, value: Self::Item) -> Result<(), Self::Error>;
}
struct ConstGen<T, const N: usize> {
- data: [T; N],
+data: [T; N],
}
impl<T, const N: usize> Collection for ConstGen<T, N> {
- type Item = T;
- type Member<U> = ConstGen<U, N>;
+type Item = T;
+type Member<U> = ConstGen<U, N>;
}
- "#,
- );
- })
- .expect_err("must panic");
+ "#,
+ );
}
#[test]
@@ -1691,3 +1682,28 @@ fn macrostmts() -> u8 {
"#,
);
}
+
+#[test]
+fn dyn_with_unresolved_trait() {
+ check_types(
+ r#"
+fn foo(a: &dyn DoesNotExist) {
+ a.bar();
+ //^&{unknown}
+}
+ "#,
+ );
+}
+
+#[test]
+fn self_assoc_with_const_generics_crash() {
+ check_no_mismatches(
+ r#"
+trait Trait { type Item; }
+impl<T, const N: usize> Trait for [T; N] {
+ type Item = ();
+ fn f<U>(_: Self::Item) {}
+}
+ "#,
+ );
+}
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 4ea103e5d..080e2ac1b 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
@@ -1693,16 +1693,16 @@ fn infer_type_param() {
fn infer_const() {
check_infer(
r#"
- struct Foo;
- impl Foo { const ASSOC_CONST: u32 = 0; }
- const GLOBAL_CONST: u32 = 101;
- fn test() {
- const LOCAL_CONST: u32 = 99;
- let x = LOCAL_CONST;
- let z = GLOBAL_CONST;
- let id = Foo::ASSOC_CONST;
- }
- "#,
+struct Foo;
+impl Foo { const ASSOC_CONST: u32 = 0; }
+const GLOBAL_CONST: u32 = 101;
+fn test() {
+ const LOCAL_CONST: u32 = 99;
+ let x = LOCAL_CONST;
+ let z = GLOBAL_CONST;
+ let id = Foo::ASSOC_CONST;
+}
+"#,
expect![[r#"
48..49 '0': u32
79..82 '101': u32
@@ -1722,17 +1722,17 @@ fn infer_const() {
fn infer_static() {
check_infer(
r#"
- static GLOBAL_STATIC: u32 = 101;
- static mut GLOBAL_STATIC_MUT: u32 = 101;
- fn test() {
- static LOCAL_STATIC: u32 = 99;
- static mut LOCAL_STATIC_MUT: u32 = 99;
- let x = LOCAL_STATIC;
- let y = LOCAL_STATIC_MUT;
- let z = GLOBAL_STATIC;
- let w = GLOBAL_STATIC_MUT;
- }
- "#,
+static GLOBAL_STATIC: u32 = 101;
+static mut GLOBAL_STATIC_MUT: u32 = 101;
+fn test() {
+ static LOCAL_STATIC: u32 = 99;
+ static mut LOCAL_STATIC_MUT: u32 = 99;
+ let x = LOCAL_STATIC;
+ let y = LOCAL_STATIC_MUT;
+ let z = GLOBAL_STATIC;
+ let w = GLOBAL_STATIC_MUT;
+}
+"#,
expect![[r#"
28..31 '101': u32
69..72 '101': u32
@@ -1752,6 +1752,41 @@ fn infer_static() {
}
#[test]
+fn infer_enum_variant() {
+ check_infer(
+ r#"
+enum Foo {
+ A = 15,
+ B = Foo::A as isize + 1
+}
+"#,
+ expect![[r#"
+ 19..21 '15': isize
+ 31..37 'Foo::A': Foo
+ 31..46 'Foo::A as isize': isize
+ 31..50 'Foo::A...ze + 1': isize
+ 49..50 '1': isize
+ "#]],
+ );
+ check_infer(
+ r#"
+#[repr(u32)]
+enum Foo {
+ A = 15,
+ B = Foo::A as u32 + 1
+}
+"#,
+ expect![[r#"
+ 32..34 '15': u32
+ 44..50 'Foo::A': Foo
+ 44..57 'Foo::A as u32': u32
+ 44..61 'Foo::A...32 + 1': u32
+ 60..61 '1': u32
+ "#]],
+ );
+}
+
+#[test]
fn shadowing_primitive() {
check_types(
r#"
@@ -1918,6 +1953,88 @@ fn closure_return_inferred() {
}
#[test]
+fn generator_types_inferred() {
+ check_infer(
+ r#"
+//- minicore: generator, deref
+use core::ops::{Generator, GeneratorState};
+use core::pin::Pin;
+
+fn f(v: i64) {}
+fn test() {
+ let mut g = |r| {
+ let a = yield 0;
+ let a = yield 1;
+ let a = yield 2;
+ "return value"
+ };
+
+ match Pin::new(&mut g).resume(0usize) {
+ GeneratorState::Yielded(y) => { f(y); }
+ GeneratorState::Complete(r) => {}
+ }
+}
+ "#,
+ expect![[r#"
+ 70..71 'v': i64
+ 78..80 '{}': ()
+ 91..362 '{ ... } }': ()
+ 101..106 'mut g': |usize| yields i64 -> &str
+ 109..218 '|r| { ... }': |usize| yields i64 -> &str
+ 110..111 'r': usize
+ 113..218 '{ ... }': &str
+ 127..128 'a': usize
+ 131..138 'yield 0': usize
+ 137..138 '0': i64
+ 152..153 'a': usize
+ 156..163 'yield 1': usize
+ 162..163 '1': i64
+ 177..178 'a': usize
+ 181..188 'yield 2': usize
+ 187..188 '2': i64
+ 198..212 '"return value"': &str
+ 225..360 'match ... }': ()
+ 231..239 'Pin::new': fn new<&mut |usize| yields i64 -> &str>(&mut |usize| yields i64 -> &str) -> Pin<&mut |usize| yields i64 -> &str>
+ 231..247 'Pin::n...mut g)': Pin<&mut |usize| yields i64 -> &str>
+ 231..262 'Pin::n...usize)': GeneratorState<i64, &str>
+ 240..246 '&mut g': &mut |usize| yields i64 -> &str
+ 245..246 'g': |usize| yields i64 -> &str
+ 255..261 '0usize': usize
+ 273..299 'Genera...ded(y)': GeneratorState<i64, &str>
+ 297..298 'y': i64
+ 303..312 '{ f(y); }': ()
+ 305..306 'f': fn f(i64)
+ 305..309 'f(y)': ()
+ 307..308 'y': i64
+ 321..348 'Genera...ete(r)': GeneratorState<i64, &str>
+ 346..347 'r': &str
+ 352..354 '{}': ()
+ "#]],
+ );
+}
+
+#[test]
+fn generator_resume_yield_return_unit() {
+ check_no_mismatches(
+ r#"
+//- minicore: generator, deref
+use core::ops::{Generator, GeneratorState};
+use core::pin::Pin;
+fn test() {
+ let mut g = || {
+ let () = yield;
+ };
+
+ match Pin::new(&mut g).resume(()) {
+ GeneratorState::Yielded(()) => {}
+ GeneratorState::Complete(()) => {}
+ }
+}
+ "#,
+ );
+}
+
+#[test]
fn fn_pointer_return() {
check_infer(
r#"
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 21a863197..555b6972f 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
@@ -279,6 +279,10 @@ fn test() {
pub mod iter {
pub trait IntoIterator {
type Item;
+ type IntoIter: Iterator<Item = Self::Item>;
+ }
+ pub trait Iterator {
+ type Item;
}
}
pub mod prelude {
@@ -297,7 +301,13 @@ pub mod collections {
}
impl<T> IntoIterator for Vec<T> {
- type Item=T;
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+ }
+
+ struct IntoIter<T> {}
+ impl<T> Iterator for IntoIter<T> {
+ type Item = T;
}
}
"#,
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 77afeb321..c425f35ac 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -1,6 +1,6 @@
//! Trait solving using Chalk.
-use std::env::var;
+use std::{env::var, sync::Arc};
use chalk_ir::GoalData;
use chalk_recursive::Cache;
@@ -12,8 +12,9 @@ use stdx::panic_context;
use syntax::SmolStr;
use crate::{
- db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Goal, Guidance, InEnvironment,
- Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
+ db::HirDatabase, infer::unify::InferenceTable, AliasEq, AliasTy, Canonical, DomainGoal, Goal,
+ Guidance, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, Solution, TraitRefExt, Ty,
+ TyKind, WhereClause,
};
/// This controls how much 'time' we give the Chalk solver before giving up.
@@ -64,6 +65,16 @@ impl TraitEnvironment {
}
}
+pub(crate) fn normalize_projection_query(
+ db: &dyn HirDatabase,
+ projection: ProjectionTy,
+ env: Arc<TraitEnvironment>,
+) -> Ty {
+ let mut table = InferenceTable::new(db, env);
+ let ty = table.normalize_projection_ty(projection);
+ table.resolve_completely(ty)
+}
+
/// Solve a trait goal using Chalk.
pub(crate) fn trait_solve_query(
db: &dyn HirDatabase,
@@ -84,7 +95,7 @@ pub(crate) fn trait_solve_query(
..
}))) = &goal.value.goal.data(Interner)
{
- if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(Interner).kind(Interner) {
+ if let TyKind::BoundVar(_) = projection_ty.self_type_parameter(db).kind(Interner) {
// Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible
return Some(Solution::Ambig(Guidance::Unknown));
}
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 d6638db02..e54bcb421 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -4,7 +4,7 @@
use std::iter;
use base_db::CrateId;
-use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
+use chalk_ir::{cast::Cast, fold::Shift, BoundVar, DebruijnIndex};
use hir_def::{
db::DefDatabase,
generics::{
@@ -24,8 +24,7 @@ use smallvec::{smallvec, SmallVec};
use syntax::SmolStr;
use crate::{
- db::HirDatabase, ChalkTraitId, ConstData, ConstValue, GenericArgData, Interner, Substitution,
- TraitRef, TraitRefExt, TyKind, WhereClause,
+ db::HirDatabase, ChalkTraitId, Interner, Substitution, TraitRef, TraitRefExt, WhereClause,
};
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<Item = TraitId> {
@@ -174,31 +173,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
- if parent_generics.is_some() && matches!(def, GenericDefId::TypeAliasId(_)) {
- let params = db.generic_params(def);
- let parent_params = &parent_generics.as_ref().unwrap().params;
- let has_consts =
- params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
- let parent_has_consts =
- parent_params.iter().any(|(_, x)| matches!(x, TypeOrConstParamData::ConstParamData(_)));
- return if has_consts || parent_has_consts {
- // XXX: treat const generic associated types as not existing to avoid crashes
- // (#11769)
- //
- // Note: Also crashes when the parent has const generics (also even if the GAT
- // doesn't use them), see `tests::regression::gat_crash_3` for an example.
- // Avoids that by disabling GATs when the parent (i.e. `impl` block) has
- // const generics (#12193).
- //
- // Chalk expects the inner associated type's parameters to come
- // *before*, not after the trait's generics as we've always done it.
- // Adapting to this requires a larger refactoring
- cov_mark::hit!(ignore_gats);
- Generics { def, params: Interned::new(Default::default()), parent_generics }
- } else {
- Generics { def, params, parent_generics }
- };
- }
Generics { def, params: db.generic_params(def), parent_generics }
}
@@ -221,23 +195,30 @@ impl Generics {
})
}
- /// Iterator over types and const params of parent, then self.
+ /// Iterator over types and const params of self, then parent.
pub(crate) fn iter<'a>(
&'a self,
) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
let to_toc_id = |it: &'a Generics| {
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
};
- self.parent_generics()
- .into_iter()
- .flat_map(move |it| it.params.iter().map(to_toc_id(it)))
- .chain(self.params.iter().map(to_toc_id(self)))
+ self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
+ }
+
+ /// Iterate over types and const params without parent params.
+ pub(crate) fn iter_self<'a>(
+ &'a self,
+ ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
+ let to_toc_id = |it: &'a Generics| {
+ move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+ };
+ self.params.iter().map(to_toc_id(self))
}
/// Iterator over types and const params of parent.
pub(crate) fn iter_parent<'a>(
&'a self,
- ) -> impl Iterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
+ ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
self.parent_generics().into_iter().flat_map(|it| {
let to_toc_id =
move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
@@ -245,12 +226,18 @@ impl Generics {
})
}
+ /// Returns total number of generic parameters in scope, including those from parent.
pub(crate) fn len(&self) -> usize {
let parent = self.parent_generics().map_or(0, Generics::len);
let child = self.params.type_or_consts.len();
parent + child
}
+ /// Returns numbers of generic parameters excluding those from parent.
+ pub(crate) fn len_self(&self) -> usize {
+ self.params.type_or_consts.len()
+ }
+
/// (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());
@@ -275,15 +262,17 @@ impl Generics {
if param.parent == self.def {
let (idx, (_local_id, data)) =
self.params.iter().enumerate().find(|(_, (idx, _))| *idx == param.local_id)?;
- let parent_len = self.parent_generics().map_or(0, Generics::len);
- Some((parent_len + idx, data))
+ Some((idx, data))
} else {
- self.parent_generics().and_then(|g| g.find_param(param))
+ self.parent_generics()
+ .and_then(|g| g.find_param(param))
+ // Remember that parent parameters come after parameters for self.
+ .map(|(idx, data)| (self.len_self() + idx, data))
}
}
- fn parent_generics(&self) -> Option<&Generics> {
- self.parent_generics.as_ref().map(|it| &**it)
+ pub(crate) fn parent_generics(&self) -> Option<&Generics> {
+ self.parent_generics.as_deref()
}
/// Returns a Substitution that replaces each parameter by a bound variable.
@@ -295,18 +284,10 @@ impl Generics {
Substitution::from_iter(
Interner,
self.iter_id().enumerate().map(|(idx, id)| match id {
- Either::Left(_) => GenericArgData::Ty(
- TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(Interner),
- )
- .intern(Interner),
- Either::Right(id) => GenericArgData::Const(
- ConstData {
- value: ConstValue::BoundVar(BoundVar::new(debruijn, idx)),
- ty: db.const_param_ty(id),
- }
- .intern(Interner),
- )
- .intern(Interner),
+ Either::Left(_) => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
+ Either::Right(id) => BoundVar::new(debruijn, idx)
+ .to_const(Interner, db.const_param_ty(id))
+ .cast(Interner),
}),
)
}
@@ -316,18 +297,12 @@ impl Generics {
Substitution::from_iter(
Interner,
self.iter_id().map(|id| match id {
- Either::Left(id) => GenericArgData::Ty(
- TyKind::Placeholder(crate::to_placeholder_idx(db, id.into())).intern(Interner),
- )
- .intern(Interner),
- Either::Right(id) => GenericArgData::Const(
- ConstData {
- value: ConstValue::Placeholder(crate::to_placeholder_idx(db, id.into())),
- ty: db.const_param_ty(id),
- }
- .intern(Interner),
- )
- .intern(Interner),
+ Either::Left(id) => {
+ crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
+ }
+ Either::Right(id) => crate::to_placeholder_idx(db, id.into())
+ .to_const(Interner, db.const_param_ty(id))
+ .cast(Interner),
}),
)
}
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index 8e6a2441b..e1418de3c 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -13,9 +13,9 @@ doctest = false
rustc-hash = "1.1.0"
either = "1.7.0"
arrayvec = "0.7.2"
-itertools = "0.10.3"
-smallvec = "1.9.0"
-once_cell = "1.12.0"
+itertools = "0.10.5"
+smallvec = "1.10.0"
+once_cell = "1.15.0"
stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index 5edc16d8b..c5dc60f1e 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -1,7 +1,7 @@
//! Re-export diagnostics such that clients of `hir` don't have to depend on
//! low-level crates.
//!
-//! This probably isn't the best way to do this -- ideally, diagnistics should
+//! This probably isn't the best way to do this -- ideally, diagnostics should
//! be expressed in terms of hir types themselves.
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 0e29c52ad..27b2f445d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -492,6 +492,9 @@ impl HirDisplay for TypeAlias {
write_visibility(self.module(f.db).id, self.visibility(f.db), f)?;
let data = f.db.type_alias_data(self.id);
write!(f, "type {}", data.name)?;
+ let def_id = GenericDefId::TypeAliasId(self.id);
+ write_generic_params(def_id, f)?;
+ write_where_clause(def_id, f)?;
if !data.bounds.is_empty() {
f.write_str(": ")?;
f.write_joined(&data.bounds, " + ")?;
diff --git a/src/tools/rust-analyzer/crates/hir/src/from_id.rs b/src/tools/rust-analyzer/crates/hir/src/from_id.rs
index 9c7558d19..f825a72c0 100644
--- a/src/tools/rust-analyzer/crates/hir/src/from_id.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/from_id.rs
@@ -140,6 +140,7 @@ impl From<DefWithBody> for DefWithBodyId {
DefWithBody::Function(it) => DefWithBodyId::FunctionId(it.id),
DefWithBody::Static(it) => DefWithBodyId::StaticId(it.id),
DefWithBody::Const(it) => DefWithBodyId::ConstId(it.id),
+ DefWithBody::Variant(it) => DefWithBodyId::VariantId(it.into()),
}
}
}
@@ -150,6 +151,7 @@ impl From<DefWithBodyId> for DefWithBody {
DefWithBodyId::FunctionId(it) => DefWithBody::Function(it.into()),
DefWithBodyId::StaticId(it) => DefWithBody::Static(it.into()),
DefWithBodyId::ConstId(it) => DefWithBody::Const(it.into()),
+ DefWithBodyId::VariantId(it) => DefWithBody::Variant(it.into()),
}
}
}
@@ -172,9 +174,7 @@ impl From<GenericDef> for GenericDefId {
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
- GenericDef::Variant(it) => {
- GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
- }
+ GenericDef::Variant(it) => GenericDefId::EnumVariantId(it.into()),
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
}
}
@@ -188,9 +188,7 @@ impl From<GenericDefId> for GenericDef {
GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
- GenericDefId::EnumVariantId(it) => {
- GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
- }
+ GenericDefId::EnumVariantId(it) => GenericDef::Variant(it.into()),
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
}
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index e4bb63a86..f5324208c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -39,7 +39,7 @@ use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
use either::Either;
use hir_def::{
- adt::{ReprKind, VariantData},
+ adt::{ReprData, VariantData},
body::{BodyDiagnostic, SyntheticSyntax},
expr::{BindingAnnotation, LabelId, Pat, PatId},
generics::{TypeOrConstParamData, TypeParamProvenance},
@@ -50,7 +50,7 @@ use hir_def::{
resolver::{HasResolver, Resolver},
src::HasSource as _,
AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
- FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
+ EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
};
@@ -61,12 +61,10 @@ use hir_ty::{
diagnostics::BodyValidationDiagnostic,
method_resolution::{self, TyFingerprint},
primitive::UintTy,
- subst_prefix,
traits::FnTrait,
- AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
- ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
- QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
- TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
+ AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
+ GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
+ TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, WhereClause,
};
use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
@@ -74,7 +72,7 @@ use once_cell::unsync::Lazy;
use rustc_hash::FxHashSet;
use stdx::{impl_from, never};
use syntax::{
- ast::{self, HasAttrs as _, HasDocComments, HasName},
+ ast::{self, Expr, HasAttrs as _, HasDocComments, HasName},
AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
};
@@ -349,7 +347,10 @@ impl ModuleDef {
ModuleDef::Module(it) => it.id.into(),
ModuleDef::Const(it) => it.id.into(),
ModuleDef::Static(it) => it.id.into(),
- _ => return Vec::new(),
+ ModuleDef::Variant(it) => {
+ EnumVariantId { parent: it.parent.into(), local_id: it.id }.into()
+ }
+ ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
};
let module = match self.module(db) {
@@ -378,10 +379,10 @@ impl ModuleDef {
ModuleDef::Function(it) => Some(it.into()),
ModuleDef::Const(it) => Some(it.into()),
ModuleDef::Static(it) => Some(it.into()),
+ ModuleDef::Variant(it) => Some(it.into()),
ModuleDef::Module(_)
| ModuleDef::Adt(_)
- | ModuleDef::Variant(_)
| ModuleDef::Trait(_)
| ModuleDef::TypeAlias(_)
| ModuleDef::Macro(_)
@@ -538,6 +539,30 @@ impl Module {
}
acc.extend(decl.diagnostics(db))
}
+ ModuleDef::Adt(adt) => {
+ match adt {
+ Adt::Struct(s) => {
+ for diag in db.struct_data_with_diagnostics(s.id).1.iter() {
+ emit_def_diagnostic(db, acc, diag);
+ }
+ }
+ Adt::Union(u) => {
+ for diag in db.union_data_with_diagnostics(u.id).1.iter() {
+ emit_def_diagnostic(db, acc, diag);
+ }
+ }
+ Adt::Enum(e) => {
+ for v in e.variants(db) {
+ acc.extend(ModuleDef::Variant(v).diagnostics(db));
+ }
+
+ for diag in db.enum_data_with_diagnostics(e.id).1.iter() {
+ emit_def_diagnostic(db, acc, diag);
+ }
+ }
+ }
+ acc.extend(decl.diagnostics(db))
+ }
_ => acc.extend(decl.diagnostics(db)),
}
}
@@ -582,8 +607,13 @@ impl Module {
/// Finds a path that can be used to refer to the given item from within
/// this module, if possible.
- pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> {
- hir_def::find_path::find_path(db, item.into().into(), self.into())
+ pub fn find_use_path(
+ self,
+ db: &dyn DefDatabase,
+ item: impl Into<ItemInNs>,
+ prefer_no_std: bool,
+ ) -> Option<ModPath> {
+ hir_def::find_path::find_path(db, item.into().into(), self.into(), prefer_no_std)
}
/// Finds a path that can be used to refer to the given item from within
@@ -593,8 +623,15 @@ impl Module {
db: &dyn DefDatabase,
item: impl Into<ItemInNs>,
prefix_kind: PrefixKind,
+ prefer_no_std: bool,
) -> Option<ModPath> {
- hir_def::find_path::find_path_prefixed(db, item.into().into(), self.into(), prefix_kind)
+ hir_def::find_path::find_path_prefixed(
+ db,
+ item.into().into(),
+ self.into(),
+ prefix_kind,
+ prefer_no_std,
+ )
}
}
@@ -863,7 +900,7 @@ impl Struct {
Type::from_def(db, self.id)
}
- pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
+ pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprData> {
db.struct_data(self.id).repr.clone()
}
@@ -941,6 +978,21 @@ impl Enum {
pub fn ty(self, db: &dyn HirDatabase) -> Type {
Type::from_def(db, self.id)
}
+
+ /// The type of the enum variant bodies.
+ pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
+ Type::new_for_crate(
+ self.id.lookup(db.upcast()).container.krate(),
+ TyBuilder::builtin(match db.enum_data(self.id).variant_body_type() {
+ Either::Left(builtin) => hir_def::builtin_type::BuiltinType::Int(builtin),
+ Either::Right(builtin) => hir_def::builtin_type::BuiltinType::Uint(builtin),
+ }),
+ )
+ }
+
+ pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
+ self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
+ }
}
impl HasVisibility for Enum {
@@ -949,6 +1001,12 @@ impl HasVisibility for Enum {
}
}
+impl From<&Variant> for DefWithBodyId {
+ fn from(&v: &Variant) -> Self {
+ DefWithBodyId::VariantId(v.into())
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Variant {
pub(crate) parent: Enum,
@@ -983,6 +1041,14 @@ impl Variant {
pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
}
+
+ pub fn value(self, db: &dyn HirDatabase) -> Option<Expr> {
+ self.source(db)?.value.expr()
+ }
+
+ pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> {
+ db.const_eval_variant(self.into())
+ }
}
/// Variants inherit visibility from the parent enum.
@@ -1023,7 +1089,7 @@ impl Adt {
pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type {
let id = AdtId::from(self);
let mut it = args.iter().map(|t| t.ty.clone());
- let ty = TyBuilder::def_ty(db, id.into())
+ let ty = TyBuilder::def_ty(db, id.into(), None)
.fill(|x| {
let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
match x {
@@ -1118,8 +1184,9 @@ pub enum DefWithBody {
Function(Function),
Static(Static),
Const(Const),
+ Variant(Variant),
}
-impl_from!(Function, Const, Static for DefWithBody);
+impl_from!(Function, Const, Static, Variant for DefWithBody);
impl DefWithBody {
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -1127,6 +1194,7 @@ impl DefWithBody {
DefWithBody::Const(c) => c.module(db),
DefWithBody::Function(f) => f.module(db),
DefWithBody::Static(s) => s.module(db),
+ DefWithBody::Variant(v) => v.module(db),
}
}
@@ -1135,6 +1203,7 @@ impl DefWithBody {
DefWithBody::Function(f) => Some(f.name(db)),
DefWithBody::Static(s) => Some(s.name(db)),
DefWithBody::Const(c) => c.name(db),
+ DefWithBody::Variant(v) => Some(v.name(db)),
}
}
@@ -1144,6 +1213,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.ret_type(db),
DefWithBody::Static(it) => it.ty(db),
DefWithBody::Const(it) => it.ty(db),
+ DefWithBody::Variant(it) => it.parent.variant_body_ty(db),
}
}
@@ -1152,6 +1222,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.id.into(),
DefWithBody::Static(it) => it.id.into(),
DefWithBody::Const(it) => it.id.into(),
+ DefWithBody::Variant(it) => it.into(),
}
}
@@ -1368,6 +1439,7 @@ impl DefWithBody {
DefWithBody::Function(it) => it.into(),
DefWithBody::Static(it) => it.into(),
DefWithBody::Const(it) => it.into(),
+ DefWithBody::Variant(it) => it.into(),
};
for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
acc.push(diag.into())
@@ -2474,7 +2546,7 @@ impl TypeParam {
let resolver = self.id.parent().resolver(db.upcast());
let ty = params.get(local_idx)?.clone();
let subst = TyBuilder::placeholder_subst(db, self.id.parent());
- let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
+ let ty = ty.substitute(Interner, &subst);
match ty.data(Interner) {
GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
_ => None,
@@ -2728,7 +2800,22 @@ impl Type {
}
fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type {
- let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
+ let ty_def = def.into();
+ let parent_subst = match ty_def {
+ TyDefId::TypeAliasId(id) => match id.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(id) => {
+ let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build();
+ Some(subst)
+ }
+ ItemContainerId::ImplId(id) => {
+ let subst = TyBuilder::subst_for_def(db, id, None).fill_with_unknown().build();
+ Some(subst)
+ }
+ _ => None,
+ },
+ _ => None,
+ };
+ let ty = TyBuilder::def_ty(db, ty_def, parent_subst).fill_with_unknown().build();
Type::new(db, def, ty)
}
@@ -2868,7 +2955,11 @@ impl Type {
alias: TypeAlias,
) -> Option<Type> {
let mut args = args.iter();
- let projection = TyBuilder::assoc_type_projection(db, alias.id)
+ let trait_id = match alias.id.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(id) => id,
+ _ => unreachable!("non assoc type alias reached in normalize_trait_assoc_type()"),
+ };
+ let parent_subst = TyBuilder::subst_for_def(db, trait_id, None)
.push(self.ty.clone())
.fill(|x| {
// FIXME: this code is not covered in tests.
@@ -2880,27 +2971,14 @@ impl Type {
}
})
.build();
- let goal = hir_ty::make_canonical(
- InEnvironment::new(
- &self.env.env,
- AliasEq {
- alias: AliasTy::Projection(projection),
- ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
- .intern(Interner),
- }
- .cast(Interner),
- ),
- [TyVariableKind::General].into_iter(),
- );
+ // FIXME: We don't handle GATs yet.
+ let projection = TyBuilder::assoc_type_projection(db, alias.id, Some(parent_subst)).build();
- match db.trait_solve(self.env.krate, goal)? {
- Solution::Unique(s) => s
- .value
- .subst
- .as_slice(Interner)
- .first()
- .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())),
- Solution::Ambig(_) => None,
+ let ty = db.normalize_projection(projection, self.env.clone());
+ if ty.is_unknown() {
+ None
+ } else {
+ Some(self.derived(ty))
}
}
@@ -2944,7 +3022,7 @@ impl Type {
let adt = adt_id.into();
match adt {
- Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
+ Adt::Struct(s) => matches!(s.repr(db), Some(ReprData { packed: true, .. })),
_ => false,
}
}
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 416b6f580..119ec3210 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -257,6 +257,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
self.imp.original_ast_node(node)
}
+ /// Attempts to map the node out of macro expanded files.
+ /// This only work for attribute expansions, as other ones do not have nodes as input.
+ pub fn original_syntax_node(&self, node: &SyntaxNode) -> Option<SyntaxNode> {
+ self.imp.original_syntax_node(node)
+ }
pub fn diagnostics_display_range(&self, diagnostics: InFile<SyntaxNodePtr>) -> FileRange {
self.imp.diagnostics_display_range(diagnostics)
@@ -956,6 +961,16 @@ impl<'db> SemanticsImpl<'db> {
)
}
+ fn original_syntax_node(&self, node: &SyntaxNode) -> Option<SyntaxNode> {
+ let InFile { file_id, .. } = self.find_file(node);
+ InFile::new(file_id, node).original_syntax_node(self.db.upcast()).map(
+ |InFile { file_id, value }| {
+ self.cache(find_root(&value), file_id);
+ value
+ },
+ )
+ }
+
fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
let root = self.parse_or_expand(src.file_id).unwrap();
let node = src.map(|it| it.to_node(&root));
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 ba9a1cfb6..fa45e3c12 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
@@ -115,7 +115,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
}
impl SourceToDefCtx<'_, '_> {
- pub(super) fn file_to_def(&mut self, file: FileId) -> SmallVec<[ModuleId; 1]> {
+ pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> {
let _p = profile::span("SourceBinder::to_module_def");
let mut mods = SmallVec::new();
for &crate_id in self.db.relevant_crates(file).iter() {
@@ -130,7 +130,7 @@ impl SourceToDefCtx<'_, '_> {
mods
}
- pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> {
+ pub(super) fn module_to_def(&self, src: InFile<ast::Module>) -> Option<ModuleId> {
let _p = profile::span("module_to_def");
let parent_declaration = src
.syntax()
@@ -151,7 +151,7 @@ impl SourceToDefCtx<'_, '_> {
Some(def_map.module_id(child_id))
}
- pub(super) fn source_file_to_def(&mut self, src: InFile<ast::SourceFile>) -> Option<ModuleId> {
+ pub(super) fn source_file_to_def(&self, src: InFile<ast::SourceFile>) -> Option<ModuleId> {
let _p = profile::span("source_file_to_def");
let file_id = src.file_id.original_file(self.db.upcast());
self.file_to_def(file_id).get(0).copied()
@@ -384,7 +384,7 @@ impl SourceToDefCtx<'_, '_> {
} else {
let it = ast::Variant::cast(container.value)?;
let def = self.enum_variant_to_def(InFile::new(container.file_id, it))?;
- VariantId::from(def).into()
+ DefWithBodyId::from(def).into()
};
Some(cont)
}
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 342912b67..07bae2b38 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -22,7 +22,7 @@ use hir_def::{
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
type_ref::Mutability,
AsMacroCall, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId,
- Lookup, ModuleDefId, VariantId,
+ Lookup, ModuleDefId, TraitId, VariantId,
};
use hir_expand::{
builtin_fn_macro::BuiltinFnLikeExpander,
@@ -302,10 +302,15 @@ 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 substs = hir_ty::TyBuilder::subst_for_def(db, poll_fn).push(ty.clone()).build();
+ // 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();
Some(self.resolve_impl_method_or_trait_def(db, poll_fn, &substs))
}
@@ -321,8 +326,10 @@ impl SourceAnalyzer {
};
let ty = self.ty_of_expr(db, &prefix_expr.expr()?.into())?;
- let op_fn = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?;
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+ let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_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();
Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
}
@@ -337,8 +344,10 @@ impl SourceAnalyzer {
let lang_item_name = name![index];
- let op_fn = self.lang_trait_fn(db, &lang_item_name, &lang_item_name)?;
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn)
+ let (op_trait, op_fn) = self.lang_trait_fn(db, &lang_item_name, &lang_item_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(base_ty.clone())
.push(index_ty.clone())
.build();
@@ -354,10 +363,14 @@ impl SourceAnalyzer {
let lhs = self.ty_of_expr(db, &binop_expr.lhs()?.into())?;
let rhs = self.ty_of_expr(db, &binop_expr.rhs()?.into())?;
- let op_fn = lang_names_for_bin_op(op)
+ 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 substs =
- hir_ty::TyBuilder::subst_for_def(db, op_fn).push(lhs.clone()).push(rhs.clone()).build();
+ // 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)
+ .push(lhs.clone())
+ .push(rhs.clone())
+ .build();
Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
}
@@ -371,7 +384,13 @@ impl SourceAnalyzer {
let op_fn =
db.lang_item(self.resolver.krate(), name![branch].to_smol_str())?.as_function()?;
- let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+ let op_trait = match op_fn.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(id) => id,
+ _ => return None,
+ };
+ // HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself
+ // doesn't have any generic parameters, so we skip building another subst for `branch()`.
+ let substs = hir_ty::TyBuilder::subst_for_def(db, op_trait, None).push(ty.clone()).build();
Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
}
@@ -799,9 +818,10 @@ impl SourceAnalyzer {
db: &dyn HirDatabase,
lang_trait: &Name,
method_name: &Name,
- ) -> Option<FunctionId> {
- db.trait_data(db.lang_item(self.resolver.krate(), lang_trait.to_smol_str())?.as_trait()?)
- .method_by_name(method_name)
+ ) -> Option<(TraitId, FunctionId)> {
+ let trait_id = db.lang_item(self.resolver.krate(), lang_trait.to_smol_str())?.as_trait()?;
+ let fn_id = db.trait_data(trait_id).method_by_name(method_name)?;
+ Some((trait_id, fn_id))
}
fn ty_of_expr(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<&Ty> {
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 616a406c7..fd78decda 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -244,6 +244,10 @@ impl<'a> SymbolCollector<'a> {
DefWithBodyId::ConstId(id) => Some(
id.lookup(self.db.upcast()).source(self.db.upcast()).value.name()?.text().into(),
),
+ DefWithBodyId::VariantId(id) => Some({
+ let db = self.db.upcast();
+ id.parent.lookup(db).source(db).value.name()?.text().into()
+ }),
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index fca09d384..57a41f3d9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.3"
+itertools = "0.10.5"
either = "1.7.0"
stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
index d4d148c77..60d1588a4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_config.rs
@@ -13,4 +13,5 @@ pub struct AssistConfig {
pub snippet_cap: Option<SnippetCap>,
pub allowed: Option<Vec<AssistKind>>,
pub insert_use: InsertUseConfig,
+ pub prefer_no_std: bool,
}
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 1a7919a5a..73f4db4e5 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
@@ -87,7 +87,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
.into_iter()
.filter_map(|variant| {
Some((
- build_pat(ctx.db(), module, variant)?,
+ build_pat(ctx.db(), module, variant, ctx.config.prefer_no_std)?,
variant.should_be_hidden(ctx.db(), module.krate()),
))
})
@@ -132,8 +132,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
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));
+ let patterns = variants.into_iter().filter_map(|variant| {
+ build_pat(ctx.db(), module, variant, ctx.config.prefer_no_std)
+ });
(ast::Pat::from(make::tuple_pat(patterns)), is_hidden)
})
@@ -349,10 +350,16 @@ fn resolve_tuple_of_enum_def(
.collect()
}
-fn build_pat(db: &RootDatabase, module: hir::Module, var: ExtendedVariant) -> Option<ast::Pat> {
+fn build_pat(
+ db: &RootDatabase,
+ module: hir::Module,
+ var: ExtendedVariant,
+ prefer_no_std: bool,
+) -> Option<ast::Pat> {
match var {
ExtendedVariant::Variant(var) => {
- let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
+ let path =
+ mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var), prefer_no_std)?);
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
let pat: ast::Pat = match var.source(db)?.value.kind() {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
index 949cf3167..678dc877d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/auto_import.rs
@@ -89,8 +89,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
// ```
pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
- let mut proposed_imports =
- import_assets.search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind);
+ let mut proposed_imports = import_assets.search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ );
if proposed_imports.is_empty() {
return None;
}
@@ -153,6 +156,8 @@ pub(super) fn find_importable_node(
{
ImportAssets::for_method_call(&method_under_caret, &ctx.sema)
.zip(Some(method_under_caret.syntax().clone().into()))
+ } else if let Some(_) = ctx.find_node_at_offset_with_descend::<ast::Param>() {
+ None
} else if let Some(pat) = ctx
.find_node_at_offset_with_descend::<ast::IdentPat>()
.filter(ast::IdentPat::is_simple_ident)
@@ -266,6 +271,20 @@ mod tests {
}
#[test]
+ fn ignore_parameter_name() {
+ check_assist_not_applicable(
+ auto_import,
+ r"
+ mod foo {
+ pub mod bar {}
+ }
+
+ fn foo(bar$0: &str) {}
+ ",
+ );
+ }
+
+ #[test]
fn prefer_shorter_paths() {
let before = r"
//- /main.rs crate:main deps:foo,bar
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
index 30f6dd41a..95d11abe8 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_into_to_from.rs
@@ -50,7 +50,7 @@ pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext<'_>) -
_ => return None,
};
- mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def)?)
+ mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def, ctx.config.prefer_no_std)?)
};
let dest_type = match &ast_trait {
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
new file mode 100644
index 000000000..8d11e0bac
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -0,0 +1,822 @@
+use either::Either;
+use ide_db::defs::Definition;
+use itertools::Itertools;
+use syntax::{
+ ast::{self, AstNode, HasGenericParams, HasVisibility},
+ match_ast, SyntaxKind, SyntaxNode,
+};
+
+use crate::{assist_context::SourceChangeBuilder, AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: convert_named_struct_to_tuple_struct
+//
+// Converts struct with named fields to tuple struct, and analogously for enum variants with named
+// fields.
+//
+// ```
+// struct Point$0 { x: f32, y: f32 }
+//
+// impl Point {
+// pub fn new(x: f32, y: f32) -> Self {
+// Point { x, y }
+// }
+//
+// pub fn x(&self) -> f32 {
+// self.x
+// }
+//
+// pub fn y(&self) -> f32 {
+// self.y
+// }
+// }
+// ```
+// ->
+// ```
+// struct Point(f32, f32);
+//
+// impl Point {
+// pub fn new(x: f32, y: f32) -> Self {
+// Point(x, y)
+// }
+//
+// pub fn x(&self) -> f32 {
+// self.0
+// }
+//
+// pub fn y(&self) -> f32 {
+// self.1
+// }
+// }
+// ```
+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 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,
+ ast::FieldList::TupleFieldList(_) => return None,
+ };
+ let strukt_def = match &strukt {
+ Either::Left(s) => Either::Left(ctx.sema.to_def(s)?),
+ Either::Right(v) => Either::Right(ctx.sema.to_def(v)?),
+ };
+ let target = strukt.as_ref().either(|s| s.syntax(), |v| v.syntax()).text_range();
+
+ acc.add(
+ AssistId("convert_named_struct_to_tuple_struct", AssistKind::RefactorRewrite),
+ "Convert to tuple struct",
+ target,
+ |edit| {
+ edit_field_references(ctx, edit, record_fields.fields());
+ edit_struct_references(ctx, edit, strukt_def);
+ edit_struct_def(ctx, edit, &strukt, record_fields);
+ },
+ )
+}
+
+fn edit_struct_def(
+ ctx: &AssistContext<'_>,
+ edit: &mut SourceChangeBuilder,
+ strukt: &Either<ast::Struct, ast::Variant>,
+ record_fields: ast::RecordFieldList,
+) {
+ let tuple_fields = record_fields
+ .fields()
+ .filter_map(|f| Some(ast::make::tuple_field(f.visibility(), f.ty()?)));
+ let tuple_fields = ast::make::tuple_field_list(tuple_fields);
+ let record_fields_text_range = record_fields.syntax().text_range();
+
+ edit.edit_file(ctx.file_id());
+ edit.replace(record_fields_text_range, tuple_fields.syntax().text());
+
+ if let Either::Left(strukt) = strukt {
+ if let Some(w) = strukt.where_clause() {
+ let mut where_clause = w.to_string();
+ if where_clause.ends_with(',') {
+ where_clause.pop();
+ }
+ where_clause.push(';');
+
+ edit.delete(w.syntax().text_range());
+ edit.insert(record_fields_text_range.end(), ast::make::tokens::single_newline().text());
+ edit.insert(record_fields_text_range.end(), where_clause);
+ edit.insert(record_fields_text_range.end(), ast::make::tokens::single_newline().text());
+
+ if let Some(tok) = strukt
+ .generic_param_list()
+ .and_then(|l| l.r_angle_token())
+ .and_then(|tok| tok.next_token())
+ .filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
+ {
+ edit.delete(tok.text_range());
+ }
+ } else {
+ edit.insert(record_fields_text_range.end(), ";");
+ }
+ }
+
+ if let Some(tok) = record_fields
+ .l_curly_token()
+ .and_then(|tok| tok.prev_token())
+ .filter(|tok| tok.kind() == SyntaxKind::WHITESPACE)
+ {
+ edit.delete(tok.text_range())
+ }
+}
+
+fn edit_struct_references(
+ ctx: &AssistContext<'_>,
+ edit: &mut SourceChangeBuilder,
+ strukt: Either<hir::Struct, hir::Variant>,
+) {
+ let strukt_def = match strukt {
+ Either::Left(s) => Definition::Adt(hir::Adt::Struct(s)),
+ Either::Right(v) => Definition::Variant(v),
+ };
+ let usages = strukt_def.usages(&ctx.sema).include_self_refs().all();
+
+ let edit_node = |edit: &mut SourceChangeBuilder, node: SyntaxNode| -> Option<()> {
+ match_ast! {
+ match node {
+ ast::RecordPat(record_struct_pat) => {
+ edit.replace(
+ record_struct_pat.syntax().text_range(),
+ ast::make::tuple_struct_pat(
+ record_struct_pat.path()?,
+ record_struct_pat
+ .record_pat_field_list()?
+ .fields()
+ .filter_map(|pat| pat.pat())
+ )
+ .to_string()
+ );
+ },
+ ast::RecordExpr(record_expr) => {
+ let path = record_expr.path()?;
+ let args = record_expr
+ .record_expr_field_list()?
+ .fields()
+ .filter_map(|f| f.expr())
+ .join(", ");
+
+ edit.replace(record_expr.syntax().text_range(), format!("{path}({args})"));
+ },
+ _ => return None,
+ }
+ }
+ Some(())
+ };
+
+ for (file_id, refs) in usages {
+ edit.edit_file(file_id);
+ for r in refs {
+ for node in r.name.syntax().ancestors() {
+ if edit_node(edit, node).is_some() {
+ break;
+ }
+ }
+ }
+ }
+}
+
+fn edit_field_references(
+ ctx: &AssistContext<'_>,
+ edit: &mut SourceChangeBuilder,
+ fields: impl Iterator<Item = ast::RecordField>,
+) {
+ for (index, field) in fields.enumerate() {
+ let field = match ctx.sema.to_def(&field) {
+ Some(it) => it,
+ None => continue,
+ };
+ let def = Definition::Field(field);
+ let usages = def.usages(&ctx.sema).all();
+ for (file_id, refs) in usages {
+ edit.edit_file(file_id);
+ for r in refs {
+ if let Some(name_ref) = r.name.as_name_ref() {
+ // Only edit the field reference if it's part of a `.field` access
+ if name_ref.syntax().parent().and_then(ast::FieldExpr::cast).is_some() {
+ edit.replace(name_ref.syntax().text_range(), index.to_string());
+ }
+ }
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_assist, check_assist_not_applicable};
+
+ use super::*;
+
+ #[test]
+ fn not_applicable_other_than_record_struct() {
+ check_assist_not_applicable(convert_named_struct_to_tuple_struct, r#"struct Foo$0(u32)"#);
+ check_assist_not_applicable(convert_named_struct_to_tuple_struct, r#"struct Foo$0;"#);
+ }
+
+ #[test]
+ fn convert_simple_struct() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Inner;
+struct A$0 { inner: Inner }
+
+impl A {
+ fn new(inner: Inner) -> A {
+ A { inner }
+ }
+
+ fn new_with_default() -> A {
+ A::new(Inner)
+ }
+
+ fn into_inner(self) -> Inner {
+ self.inner
+ }
+}"#,
+ r#"
+struct Inner;
+struct A(Inner);
+
+impl A {
+ fn new(inner: Inner) -> A {
+ A(inner)
+ }
+
+ fn new_with_default() -> A {
+ A::new(Inner)
+ }
+
+ fn into_inner(self) -> Inner {
+ self.0
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_struct_referenced_via_self_kw() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Inner;
+struct A$0 { inner: Inner }
+
+impl A {
+ fn new(inner: Inner) -> Self {
+ Self { inner }
+ }
+
+ fn new_with_default() -> Self {
+ Self::new(Inner)
+ }
+
+ fn into_inner(self) -> Inner {
+ self.inner
+ }
+}"#,
+ r#"
+struct Inner;
+struct A(Inner);
+
+impl A {
+ fn new(inner: Inner) -> Self {
+ Self(inner)
+ }
+
+ fn new_with_default() -> Self {
+ Self::new(Inner)
+ }
+
+ fn into_inner(self) -> Inner {
+ self.0
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_destructured_struct() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Inner;
+struct A$0 { inner: Inner }
+
+impl A {
+ fn into_inner(self) -> Inner {
+ let A { inner: a } = self;
+ a
+ }
+
+ fn into_inner_via_self(self) -> Inner {
+ let Self { inner } = self;
+ inner
+ }
+}"#,
+ r#"
+struct Inner;
+struct A(Inner);
+
+impl A {
+ fn into_inner(self) -> Inner {
+ let A(a) = self;
+ a
+ }
+
+ fn into_inner_via_self(self) -> Inner {
+ let Self(inner) = self;
+ inner
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_struct_with_visibility() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct A$0 {
+ pub first: u32,
+ pub(crate) second: u64
+}
+
+impl A {
+ fn new() -> A {
+ A { first: 42, second: 42 }
+ }
+
+ fn into_first(self) -> u32 {
+ self.first
+ }
+
+ fn into_second(self) -> u64 {
+ self.second
+ }
+}"#,
+ r#"
+struct A(pub u32, pub(crate) u64);
+
+impl A {
+ fn new() -> A {
+ A(42, 42)
+ }
+
+ fn into_first(self) -> u32 {
+ self.0
+ }
+
+ fn into_second(self) -> u64 {
+ self.1
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_struct_with_wrapped_references() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Inner$0 { uint: u32 }
+struct Outer { inner: Inner }
+
+impl Outer {
+ fn new() -> Self {
+ Self { inner: Inner { uint: 42 } }
+ }
+
+ fn into_inner(self) -> u32 {
+ self.inner.uint
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer { inner: Inner { uint: x } } = self;
+ x
+ }
+}"#,
+ r#"
+struct Inner(u32);
+struct Outer { inner: Inner }
+
+impl Outer {
+ fn new() -> Self {
+ Self { inner: Inner(42) }
+ }
+
+ fn into_inner(self) -> u32 {
+ self.inner.0
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer { inner: Inner(x) } = self;
+ x
+ }
+}"#,
+ );
+
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Inner { uint: u32 }
+struct Outer$0 { inner: Inner }
+
+impl Outer {
+ fn new() -> Self {
+ Self { inner: Inner { uint: 42 } }
+ }
+
+ fn into_inner(self) -> u32 {
+ self.inner.uint
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer { inner: Inner { uint: x } } = self;
+ x
+ }
+}"#,
+ r#"
+struct Inner { uint: u32 }
+struct Outer(Inner);
+
+impl Outer {
+ fn new() -> Self {
+ Self(Inner { uint: 42 })
+ }
+
+ fn into_inner(self) -> u32 {
+ self.0.uint
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer(Inner { uint: x }) = self;
+ x
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_struct_with_multi_file_references() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+//- /main.rs
+struct Inner;
+struct A$0 { inner: Inner }
+
+mod foo;
+
+//- /foo.rs
+use crate::{A, Inner};
+fn f() {
+ let a = A { inner: Inner };
+}
+"#,
+ r#"
+//- /main.rs
+struct Inner;
+struct A(Inner);
+
+mod foo;
+
+//- /foo.rs
+use crate::{A, Inner};
+fn f() {
+ let a = A(Inner);
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn convert_struct_with_where_clause() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+struct Wrap$0<T>
+where
+ T: Display,
+{ field1: T }
+"#,
+ r#"
+struct Wrap<T>(T)
+where
+ T: Display;
+
+"#,
+ );
+ }
+
+ #[test]
+ fn not_applicable_other_than_record_variant() {
+ check_assist_not_applicable(
+ convert_named_struct_to_tuple_struct,
+ r#"enum Enum { Variant$0(usize) };"#,
+ );
+ check_assist_not_applicable(
+ convert_named_struct_to_tuple_struct,
+ r#"enum Enum { Variant$0 }"#,
+ );
+ }
+
+ #[test]
+ fn convert_simple_variant() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+enum A {
+ $0Variant { field1: usize },
+}
+
+impl A {
+ fn new(value: usize) -> A {
+ A::Variant { field1: value }
+ }
+
+ fn new_with_default() -> A {
+ A::new(Default::default())
+ }
+
+ fn value(self) -> usize {
+ match self {
+ A::Variant { field1: value } => value,
+ }
+ }
+}"#,
+ r#"
+enum A {
+ Variant(usize),
+}
+
+impl A {
+ fn new(value: usize) -> A {
+ A::Variant(value)
+ }
+
+ fn new_with_default() -> A {
+ A::new(Default::default())
+ }
+
+ fn value(self) -> usize {
+ match self {
+ A::Variant(value) => value,
+ }
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_variant_referenced_via_self_kw() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+enum A {
+ $0Variant { field1: usize },
+}
+
+impl A {
+ fn new(value: usize) -> A {
+ Self::Variant { field1: value }
+ }
+
+ fn new_with_default() -> A {
+ Self::new(Default::default())
+ }
+
+ fn value(self) -> usize {
+ match self {
+ Self::Variant { field1: value } => value,
+ }
+ }
+}"#,
+ r#"
+enum A {
+ Variant(usize),
+}
+
+impl A {
+ fn new(value: usize) -> A {
+ Self::Variant(value)
+ }
+
+ fn new_with_default() -> A {
+ Self::new(Default::default())
+ }
+
+ fn value(self) -> usize {
+ match self {
+ Self::Variant(value) => value,
+ }
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_destructured_variant() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+enum A {
+ $0Variant { field1: usize },
+}
+
+impl A {
+ fn into_inner(self) -> usize {
+ let A::Variant { field1: first } = self;
+ first
+ }
+
+ fn into_inner_via_self(self) -> usize {
+ let Self::Variant { field1: first } = self;
+ first
+ }
+}"#,
+ r#"
+enum A {
+ Variant(usize),
+}
+
+impl A {
+ fn into_inner(self) -> usize {
+ let A::Variant(first) = self;
+ first
+ }
+
+ fn into_inner_via_self(self) -> usize {
+ let Self::Variant(first) = self;
+ first
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_variant_with_wrapped_references() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+enum Inner {
+ $0Variant { field1: usize },
+}
+enum Outer {
+ Variant(Inner),
+}
+
+impl Outer {
+ fn new() -> Self {
+ Self::Variant(Inner::Variant { field1: 42 })
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer::Variant(Inner::Variant { field1: x }) = self;
+ x
+ }
+}"#,
+ r#"
+enum Inner {
+ Variant(usize),
+}
+enum Outer {
+ Variant(Inner),
+}
+
+impl Outer {
+ fn new() -> Self {
+ Self::Variant(Inner::Variant(42))
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer::Variant(Inner::Variant(x)) = self;
+ x
+ }
+}"#,
+ );
+
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+enum Inner {
+ Variant(usize),
+}
+enum Outer {
+ $0Variant { field1: Inner },
+}
+
+impl Outer {
+ fn new() -> Self {
+ Self::Variant { field1: Inner::Variant(42) }
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer::Variant { field1: Inner::Variant(x) } = self;
+ x
+ }
+}"#,
+ r#"
+enum Inner {
+ Variant(usize),
+}
+enum Outer {
+ Variant(Inner),
+}
+
+impl Outer {
+ fn new() -> Self {
+ Self::Variant(Inner::Variant(42))
+ }
+
+ fn into_inner_destructed(self) -> u32 {
+ let Outer::Variant(Inner::Variant(x)) = self;
+ x
+ }
+}"#,
+ );
+ }
+
+ #[test]
+ fn convert_variant_with_multi_file_references() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+//- /main.rs
+struct Inner;
+enum A {
+ $0Variant { field1: Inner },
+}
+
+mod foo;
+
+//- /foo.rs
+use crate::{A, Inner};
+fn f() {
+ let a = A::Variant { field1: Inner };
+}
+"#,
+ r#"
+//- /main.rs
+struct Inner;
+enum A {
+ Variant(Inner),
+}
+
+mod foo;
+
+//- /foo.rs
+use crate::{A, Inner};
+fn f() {
+ let a = A::Variant(Inner);
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn convert_directly_used_variant() {
+ check_assist(
+ convert_named_struct_to_tuple_struct,
+ r#"
+//- /main.rs
+struct Inner;
+enum A {
+ $0Variant { field1: Inner },
+}
+
+mod foo;
+
+//- /foo.rs
+use crate::{A::Variant, Inner};
+fn f() {
+ let a = Variant { field1: Inner };
+}
+"#,
+ r#"
+//- /main.rs
+struct Inner;
+enum A {
+ Variant(Inner),
+}
+
+mod foo;
+
+//- /foo.rs
+use crate::{A::Variant, Inner};
+fn f() {
+ let a = Variant(Inner);
+}
+"#,
+ );
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index 52a55ead3..d6c8ea785 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -152,6 +152,7 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
ctx.sema.db,
ModuleDef::from(control_flow_enum),
ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
);
if let Some(mod_path) = mod_path {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index ddc2052e7..970e948df 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -9,7 +9,7 @@ use ide_db::{
search::FileReference,
FxHashSet, RootDatabase,
};
-use itertools::{Itertools, Position};
+use itertools::Itertools;
use syntax::{
ast::{
self, edit::IndentLevel, edit_in_place::Indent, make, AstNode, HasAttrs, HasGenericParams,
@@ -298,37 +298,7 @@ fn update_variant(variant: &ast::Variant, generics: Option<ast::GenericParamList
let name = variant.name()?;
let ty = generics
.filter(|generics| generics.generic_params().count() > 0)
- .map(|generics| {
- let mut generic_str = String::with_capacity(8);
-
- for (p, more) in generics.generic_params().with_position().map(|p| match p {
- Position::First(p) | Position::Middle(p) => (p, true),
- Position::Last(p) | Position::Only(p) => (p, false),
- }) {
- match p {
- ast::GenericParam::ConstParam(konst) => {
- if let Some(name) = konst.name() {
- generic_str.push_str(name.text().as_str());
- }
- }
- ast::GenericParam::LifetimeParam(lt) => {
- if let Some(lt) = lt.lifetime() {
- generic_str.push_str(lt.text().as_str());
- }
- }
- ast::GenericParam::TypeParam(ty) => {
- if let Some(name) = ty.name() {
- generic_str.push_str(name.text().as_str());
- }
- }
- }
- if more {
- generic_str.push_str(", ");
- }
- }
-
- make::ty(&format!("{}<{}>", &name.text(), &generic_str))
- })
+ .map(|generics| make::ty(&format!("{}{}", &name.text(), generics.to_generic_args())))
.unwrap_or_else(|| make::ty(&name.text()));
// change from a record to a tuple field list
@@ -409,6 +379,7 @@ fn process_references(
ctx.sema.db,
*enum_module_def,
ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
);
if let Some(mut mod_path) = mod_path {
mod_path.pop_segment();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
index eaa6de73e..ccdfcb0d9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
@@ -77,7 +77,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
target_data_for_generate_constant(ctx, current_module, constant_module).unwrap_or_else(
|| {
let indent = IndentLevel::from_node(statement.syntax());
- (statement.syntax().text_range().start(), indent, None, format!("\n{}", indent))
+ (statement.syntax().text_range().start(), indent, None, format!("\n{indent}"))
},
);
@@ -90,7 +90,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
if let Some(file_id) = file_id {
builder.edit_file(file_id);
}
- builder.insert(offset, format!("{}{}", text, post_string));
+ builder.insert(offset, format!("{text}{post_string}"));
},
)
}
@@ -103,13 +103,13 @@ fn get_text_for_generate_constant(
) -> Option<String> {
let constant_token = not_exist_name_ref.pop()?;
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
- let mut text = format!("{}const {}: {} = $0;", vis, constant_token, type_name);
+ let mut text = format!("{vis}const {constant_token}: {type_name} = $0;");
while let Some(name_ref) = not_exist_name_ref.pop() {
let vis = if not_exist_name_ref.len() == 0 && !outer_exists { "" } else { "\npub " };
text = text.replace("\n", "\n ");
- text = format!("{}mod {} {{{}\n}}", vis, name_ref.to_string(), text);
+ text = format!("{vis}mod {name_ref} {{{text}\n}}");
}
- Some(text.replace("\n", &format!("\n{}", indent)))
+ Some(text.replace("\n", &format!("\n{indent}")))
}
fn target_data_for_generate_constant(
@@ -134,7 +134,7 @@ fn target_data_for_generate_constant(
.find(|it| it.kind() == SyntaxKind::WHITESPACE && it.to_string().contains("\n"))
.is_some();
let post_string =
- if siblings_has_newline { format!("{}", indent) } else { format!("\n{}", indent) };
+ if siblings_has_newline { format!("{indent}") } else { format!("\n{indent}") };
Some((offset, indent + 1, Some(file_id), post_string))
}
_ => Some((TextSize::from(0), 0.into(), Some(file_id), "\n".into())),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs
index 5e9995a98..a6e3d49e0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_default_from_enum_variant.rs
@@ -55,12 +55,11 @@ pub(crate) fn generate_default_from_enum_variant(
let buf = format!(
r#"
-impl Default for {0} {{
+impl Default for {enum_name} {{
fn default() -> Self {{
- Self::{1}
+ Self::{variant_name}
}}
}}"#,
- enum_name, variant_name
);
edit.insert(start_offset, buf);
},
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 cbd33de19..49d9fd707 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
@@ -1,8 +1,7 @@
use ide_db::famous_defs::FamousDefs;
-use itertools::Itertools;
use stdx::format_to;
use syntax::{
- ast::{self, HasGenericParams, HasName, HasTypeBounds, Impl},
+ ast::{self, make, HasGenericParams, HasName, Impl},
AstNode,
};
@@ -77,45 +76,47 @@ pub(crate) fn generate_default_from_new(acc: &mut Assists, ctx: &AssistContext<'
)
}
+// FIXME: based on from utils::generate_impl_text_inner
fn generate_trait_impl_text_from_impl(impl_: &ast::Impl, trait_text: &str, code: &str) -> String {
- let generic_params = impl_.generic_param_list();
- let mut buf = String::with_capacity(code.len());
- buf.push_str("\n\n");
- buf.push_str("impl");
-
- if let Some(generic_params) = &generic_params {
- let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
- let toc_params = generic_params.type_or_const_params().map(|toc_param| match toc_param {
- ast::TypeOrConstParam::Type(type_param) => {
- let mut buf = String::new();
- if let Some(it) = type_param.name() {
- format_to!(buf, "{}", it.syntax());
- }
- if let Some(it) = type_param.colon_token() {
- format_to!(buf, "{} ", it);
+ let impl_ty = impl_.self_ty().unwrap();
+ 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| {
+ // 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))
}
- if let Some(it) = type_param.type_bound_list() {
- format_to!(buf, "{}", it.syntax());
+ ast::TypeOrConstParam::Const(param) => {
+ let param = param.clone_for_update();
+ param.remove_default();
+ Some(ast::GenericParam::ConstParam(param))
}
- buf
}
- ast::TypeOrConstParam::Const(const_param) => const_param.syntax().to_string(),
});
- let generics = lifetimes.chain(toc_params).format(", ");
- format_to!(buf, "<{}>", generics);
- }
- buf.push(' ');
- buf.push_str(trait_text);
- buf.push_str(" for ");
- buf.push_str(&impl_.self_ty().unwrap().syntax().text().to_string());
+ make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
+ });
+
+ let mut buf = String::with_capacity(code.len());
+ buf.push_str("\n\n");
+
+ // `impl{generic_params} {trait_text} for {impl_.self_ty()}`
+ buf.push_str("impl");
+ if let Some(generic_params) = &generic_params {
+ format_to!(buf, "{generic_params}")
+ }
+ format_to!(buf, " {trait_text} for {impl_ty}");
match impl_.where_clause() {
Some(where_clause) => {
- format_to!(buf, "\n{}\n{{\n{}\n}}", where_clause, code);
+ format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
}
None => {
- format_to!(buf, " {{\n{}\n}}", code);
+ format_to!(buf, " {{\n{code}\n}}");
}
}
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 85b193663..ceae80755 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
@@ -51,14 +51,14 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
Some(field) => {
let field_name = field.name()?;
let field_ty = field.ty()?;
- (format!("{}", field_name), field_ty, field.syntax().text_range())
+ (field_name.to_string(), field_ty, field.syntax().text_range())
}
None => {
let field = ctx.find_node_at_offset::<ast::TupleField>()?;
let field_list = ctx.find_node_at_offset::<ast::TupleFieldList>()?;
let field_list_index = field_list.fields().position(|it| it == field)?;
let field_ty = field.ty()?;
- (format!("{}", field_list_index), field_ty, field.syntax().text_range())
+ (field_list_index.to_string(), field_ty, field.syntax().text_range())
}
};
@@ -77,7 +77,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
for method in methods {
let adt = ast::Adt::Struct(strukt.clone());
let name = method.name(ctx.db()).to_string();
- let impl_def = find_struct_impl(ctx, &adt, &name).flatten();
+ let impl_def = find_struct_impl(ctx, &adt, &[name]).flatten();
acc.add_group(
&GroupLabel("Generate delegate methods…".to_owned()),
AssistId("generate_delegate_methods", AssistKind::Generate),
@@ -151,7 +151,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
Some(cap) => {
let offset = strukt.syntax().text_range().end();
let snippet = render_snippet(cap, impl_def.syntax(), cursor);
- let snippet = format!("\n\n{}", snippet);
+ let snippet = format!("\n\n{snippet}");
builder.insert_snippet(cap, offset, snippet);
}
None => {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
index b48463512..55b7afb3d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_deref.rs
@@ -58,14 +58,15 @@ fn generate_record_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
let module = ctx.sema.to_def(&strukt)?.module(ctx.db());
let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?;
- let trait_path = module.find_use_path(ctx.db(), ModuleDef::Trait(trait_))?;
+ let trait_path =
+ module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std)?;
let field_type = field.ty()?;
let field_name = field.name()?;
let target = field.syntax().text_range();
acc.add(
AssistId("generate_deref", AssistKind::Generate),
- format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field_name),
+ format!("Generate `{deref_type_to_generate:?}` impl using `{field_name}`"),
target,
|edit| {
generate_edit(
@@ -98,13 +99,14 @@ fn generate_tuple_deref(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
let module = ctx.sema.to_def(&strukt)?.module(ctx.db());
let trait_ = deref_type_to_generate.to_trait(&ctx.sema, module.krate())?;
- let trait_path = module.find_use_path(ctx.db(), ModuleDef::Trait(trait_))?;
+ let trait_path =
+ module.find_use_path(ctx.db(), ModuleDef::Trait(trait_), ctx.config.prefer_no_std)?;
let field_type = field.ty()?;
let target = field.syntax().text_range();
acc.add(
AssistId("generate_deref", AssistKind::Generate),
- format!("Generate `{:?}` impl using `{}`", deref_type_to_generate, field.syntax()),
+ format!("Generate `{deref_type_to_generate:?}` impl using `{field}`"),
target,
|edit| {
generate_edit(
@@ -130,18 +132,16 @@ fn generate_edit(
let start_offset = strukt.syntax().text_range().end();
let impl_code = match deref_type {
DerefType::Deref => format!(
- r#" type Target = {0};
+ r#" type Target = {field_type_syntax};
fn deref(&self) -> &Self::Target {{
- &self.{1}
+ &self.{field_name}
}}"#,
- field_type_syntax, field_name
),
DerefType::DerefMut => format!(
r#" fn deref_mut(&mut self) -> &mut Self::Target {{
- &mut self.{}
+ &mut self.{field_name}
}}"#,
- field_name
),
};
let strukt_adt = ast::Adt::Struct(strukt);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
index c91141f8e..b8415c72a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_documentation_template.rs
@@ -139,40 +139,44 @@ fn make_example_for_fn(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<St
let mut example = String::new();
+ let use_path = build_path(ast_func, ctx)?;
let is_unsafe = ast_func.unsafe_token().is_some();
let param_list = ast_func.param_list()?;
let ref_mut_params = ref_mut_params(&param_list);
let self_name = self_name(ast_func);
- format_to!(example, "use {};\n\n", build_path(ast_func, ctx)?);
+ format_to!(example, "use {use_path};\n\n");
if let Some(self_name) = &self_name {
- if let Some(mtbl) = is_ref_mut_self(ast_func) {
- let mtbl = if mtbl == true { " mut" } else { "" };
- format_to!(example, "let{} {} = ;\n", mtbl, self_name);
+ if let Some(mut_) = is_ref_mut_self(ast_func) {
+ let mut_ = if mut_ == true { "mut " } else { "" };
+ format_to!(example, "let {mut_}{self_name} = ;\n");
}
}
for param_name in &ref_mut_params {
- format_to!(example, "let mut {} = ;\n", param_name);
+ format_to!(example, "let mut {param_name} = ;\n");
}
// Call the function, check result
let function_call = function_call(ast_func, &param_list, self_name.as_deref(), is_unsafe)?;
if returns_a_value(ast_func, ctx) {
if count_parameters(&param_list) < 3 {
- format_to!(example, "assert_eq!({}, );\n", function_call);
+ format_to!(example, "assert_eq!({function_call}, );\n");
} else {
- format_to!(example, "let result = {};\n", function_call);
+ format_to!(example, "let result = {function_call};\n");
example.push_str("assert_eq!(result, );\n");
}
} else {
- format_to!(example, "{};\n", function_call);
+ format_to!(example, "{function_call};\n");
}
// Check the mutated values
- if is_ref_mut_self(ast_func) == Some(true) {
- format_to!(example, "assert_eq!({}, );", self_name?);
+ if let Some(self_name) = &self_name {
+ if is_ref_mut_self(ast_func) == Some(true) {
+ format_to!(example, "assert_eq!({self_name}, );");
+ }
}
for param_name in &ref_mut_params {
- format_to!(example, "assert_eq!({}, );", param_name);
+ format_to!(example, "assert_eq!({param_name}, );");
}
+
Some(example)
}
@@ -189,7 +193,8 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
let intro_for_new = || {
let is_new = name == "new";
if is_new && ret_ty == self_ty {
- Some(format!("Creates a new [`{}`].", linkable_self_ty?))
+ let self_ty = linkable_self_ty?;
+ Some(format!("Creates a new [`{self_ty}`]."))
} else {
None
}
@@ -214,7 +219,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
} else {
""
};
- Some(format!("Returns{reference} the {what} of this [`{}`].", linkable_self_ty?))
+
+ let self_ty = linkable_self_ty?;
+ Some(format!("Returns{reference} the {what} of this [`{self_ty}`]."))
}
_ => None,
};
@@ -228,7 +235,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<S
if what == "len" {
what = "length".into()
};
- Some(format!("Sets the {what} of this [`{}`].", linkable_self_ty?))
+
+ let self_ty = linkable_self_ty?;
+ Some(format!("Sets the {what} of this [`{self_ty}`]."))
};
if let Some(intro) = intro_for_new() {
@@ -404,7 +413,7 @@ fn arguments_from_params(param_list: &ast::ParamList) -> String {
// instance `TuplePat`) could be managed later.
Some(ast::Pat::IdentPat(ident_pat)) => match ident_pat.name() {
Some(name) => match is_a_ref_mut_param(&param) {
- true => format!("&mut {}", name),
+ true => format!("&mut {name}"),
false => name.to_string(),
},
None => "_".to_string(),
@@ -424,14 +433,15 @@ fn function_call(
let name = ast_func.name()?;
let arguments = arguments_from_params(param_list);
let function_call = if param_list.self_param().is_some() {
- format!("{}.{}({})", self_name?, name, arguments)
+ let self_ = self_name?;
+ format!("{self_}.{name}({arguments})")
} else if let Some(implementation) = self_partial_type(ast_func) {
- format!("{}::{}({})", implementation, name, arguments)
+ format!("{implementation}::{name}({arguments})")
} else {
- format!("{}({})", name, arguments)
+ format!("{name}({arguments})")
};
match is_unsafe {
- true => Some(format!("unsafe {{ {} }}", function_call)),
+ true => Some(format!("unsafe {{ {function_call} }}")),
false => Some(function_call),
}
}
@@ -469,8 +479,8 @@ fn build_path(ast_func: &ast::Fn, ctx: &AssistContext<'_>) -> Option<String> {
.unwrap_or_else(|| "*".into());
let module_def: ModuleDef = ctx.sema.to_def(ast_func)?.module(ctx.db()).into();
match module_def.canonical_path(ctx.db()) {
- Some(path) => Some(format!("{}::{}::{}", crate_name, path, leaf)),
- None => Some(format!("{}::{}", crate_name, leaf)),
+ Some(path) => Some(format!("{crate_name}::{path}::{leaf}")),
+ None => Some(format!("{crate_name}::{leaf}")),
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
index 52d27d8a7..63e91b835 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_is_method.rs
@@ -52,7 +52,7 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
let fn_name = format!("is_{}", &to_lower_snake_case(&variant_name.text()));
// Return early if we've found an existing new fn
- let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
+ let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
let target = variant.syntax().text_range();
acc.add_group(
@@ -61,21 +61,15 @@ pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext<'_>
"Generate an `is_` method for this enum variant",
target,
|builder| {
- let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
+ let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} "));
let method = format!(
- " /// Returns `true` if the {} is [`{variant}`].
+ " /// Returns `true` if the {enum_lowercase_name} is [`{variant_name}`].
///
- /// [`{variant}`]: {}::{variant}
+ /// [`{variant_name}`]: {enum_name}::{variant_name}
#[must_use]
- {}fn {}(&self) -> bool {{
- matches!(self, Self::{variant}{})
+ {vis}fn {fn_name}(&self) -> bool {{
+ matches!(self, Self::{variant_name}{pattern_suffix})
}}",
- enum_lowercase_name,
- enum_name,
- vis,
- fn_name,
- pattern_suffix,
- variant = variant_name
);
add_method_to_adt(builder, &parent_enum, impl_def, &method);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
index b19aa0f65..bdd3cf4f0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_enum_projection_method.rs
@@ -116,6 +116,14 @@ fn generate_enum_projection_method(
assist_description: &str,
props: ProjectionProps,
) -> Option<()> {
+ let ProjectionProps {
+ fn_name_prefix,
+ self_param,
+ return_prefix,
+ return_suffix,
+ happy_case,
+ sad_case,
+ } = props;
let variant = ctx.find_node_at_offset::<ast::Variant>()?;
let variant_name = variant.name()?;
let parent_enum = ast::Adt::Enum(variant.parent_enum());
@@ -125,7 +133,7 @@ fn generate_enum_projection_method(
let (field,) = record.fields().collect_tuple()?;
let name = field.name()?.to_string();
let ty = field.ty()?;
- let pattern_suffix = format!(" {{ {} }}", name);
+ let pattern_suffix = format!(" {{ {name} }}");
(pattern_suffix, ty, name)
}
ast::StructKind::Tuple(tuple) => {
@@ -136,11 +144,10 @@ fn generate_enum_projection_method(
ast::StructKind::Unit => return None,
};
- let fn_name =
- format!("{}_{}", props.fn_name_prefix, &to_lower_snake_case(&variant_name.text()));
+ let fn_name = format!("{}_{}", fn_name_prefix, &to_lower_snake_case(&variant_name.text()));
// Return early if we've found an existing new fn
- let impl_def = find_struct_impl(ctx, &parent_enum, &fn_name)?;
+ let impl_def = find_struct_impl(ctx, &parent_enum, &[fn_name.clone()])?;
let target = variant.syntax().text_range();
acc.add_group(
@@ -149,27 +156,15 @@ fn generate_enum_projection_method(
assist_description,
target,
|builder| {
- let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
+ let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{v} "));
let method = format!(
- " {0}fn {1}({2}) -> {3}{4}{5} {{
- if let Self::{6}{7} = self {{
- {8}({9})
+ " {vis}fn {fn_name}({self_param}) -> {return_prefix}{field_type}{return_suffix} {{
+ if let Self::{variant_name}{pattern_suffix} = self {{
+ {happy_case}({bound_name})
}} else {{
- {10}
+ {sad_case}
}}
- }}",
- vis,
- fn_name,
- props.self_param,
- props.return_prefix,
- field_type.syntax(),
- props.return_suffix,
- variant_name,
- pattern_suffix,
- props.happy_case,
- bound_name,
- props.sad_case,
- );
+ }}");
add_method_to_adt(builder, &parent_enum, impl_def, &method);
},
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
index 507ea012b..7c81d2c6a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs
@@ -56,23 +56,18 @@ pub(crate) fn generate_from_impl_for_enum(
target,
|edit| {
let start_offset = variant.parent_enum().syntax().text_range().end();
- let from_trait = format!("From<{}>", field_type.syntax());
+ let from_trait = format!("From<{field_type}>");
let impl_code = if let Some(name) = field_name {
format!(
- r#" fn from({0}: {1}) -> Self {{
- Self::{2} {{ {0} }}
- }}"#,
- name.text(),
- field_type.syntax(),
- variant_name,
+ r#" fn from({name}: {field_type}) -> Self {{
+ Self::{variant_name} {{ {name} }}
+ }}"#
)
} else {
format!(
- r#" fn from(v: {}) -> Self {{
- Self::{}(v)
- }}"#,
- field_type.syntax(),
- variant_name,
+ r#" fn from(v: {field_type}) -> Self {{
+ Self::{variant_name}(v)
+ }}"#
)
};
let from_impl = generate_trait_impl_text(&enum_, &from_trait, &impl_code);
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 e26c76da1..c229127e4 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,4 +1,4 @@
-use hir::{HasSource, HirDisplay, Module, Semantics, TypeInfo};
+use hir::{Adt, HasSource, HirDisplay, Module, Semantics, TypeInfo};
use ide_db::{
base_db::FileId,
defs::{Definition, NameRefClass},
@@ -145,7 +145,8 @@ fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
return None;
}
let (impl_, file) = get_adt_source(ctx, &adt, fn_name.text().as_str())?;
- let (target, insert_offset) = get_method_target(ctx, &target_module, &impl_)?;
+ 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 text_range = call.syntax().text_range();
@@ -174,10 +175,11 @@ fn add_func_to_accumulator(
label: String,
) -> Option<()> {
acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |builder| {
- let function_template = function_builder.render();
+ let indent = IndentLevel::from_node(function_builder.target.syntax());
+ 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 {
- func = format!("\nimpl {} {{\n{}\n}}", name, func);
+ func = format!("\n{indent}impl {name} {{\n{func}\n{indent}}}");
}
builder.edit_file(file);
match ctx.config.snippet_cap {
@@ -196,7 +198,7 @@ fn get_adt_source(
let file = ctx.sema.parse(range.file_id);
let adt_source =
ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
- find_struct_impl(ctx, &adt_source, fn_name).map(|impl_| (impl_, range.file_id))
+ find_struct_impl(ctx, &adt_source, &[fn_name.to_string()]).map(|impl_| (impl_, range.file_id))
}
struct FunctionTemplate {
@@ -210,23 +212,26 @@ struct FunctionTemplate {
impl FunctionTemplate {
fn to_string(&self, cap: Option<SnippetCap>) -> String {
+ let Self { leading_ws, fn_def, ret_type, should_focus_return_type, trailing_ws, tail_expr } =
+ self;
+
let f = match cap {
Some(cap) => {
- let cursor = if self.should_focus_return_type {
+ let cursor = if *should_focus_return_type {
// Focus the return type if there is one
- match self.ret_type {
- Some(ref ret_type) => ret_type.syntax(),
- None => self.tail_expr.syntax(),
+ match ret_type {
+ Some(ret_type) => ret_type.syntax(),
+ None => tail_expr.syntax(),
}
} else {
- self.tail_expr.syntax()
+ tail_expr.syntax()
};
- render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(cursor))
+ render_snippet(cap, fn_def.syntax(), Cursor::Replace(cursor))
}
- None => self.fn_def.to_string(),
+ None => fn_def.to_string(),
};
- format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
+ format!("{leading_ws}{f}{trailing_ws}")
}
}
@@ -307,7 +312,7 @@ impl FunctionBuilder {
})
}
- fn render(self) -> FunctionTemplate {
+ fn render(self, is_method: bool) -> FunctionTemplate {
let placeholder_expr = make::ext::expr_todo();
let fn_body = make::block_expr(vec![], Some(placeholder_expr));
let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
@@ -325,16 +330,23 @@ impl FunctionBuilder {
match self.target {
GeneratedFunctionTarget::BehindItem(it) => {
- let indent = IndentLevel::from_node(&it);
- leading_ws = format!("\n\n{}", indent);
+ let mut indent = IndentLevel::from_node(&it);
+ if is_method {
+ indent = indent + 1;
+ leading_ws = format!("{indent}");
+ } else {
+ leading_ws = format!("\n\n{indent}");
+ }
+
fn_def = fn_def.indent(indent);
trailing_ws = String::new();
}
GeneratedFunctionTarget::InEmptyItemList(it) => {
let indent = IndentLevel::from_node(&it);
- leading_ws = format!("\n{}", indent + 1);
- fn_def = fn_def.indent(indent + 1);
- trailing_ws = format!("\n{}", indent);
+ let leading_indent = indent + 1;
+ leading_ws = format!("\n{leading_indent}");
+ fn_def = fn_def.indent(leading_indent);
+ trailing_ws = format!("\n{indent}");
}
};
@@ -411,14 +423,13 @@ fn get_fn_target(
fn get_method_target(
ctx: &AssistContext<'_>,
- target_module: &Module,
impl_: &Option<ast::Impl>,
+ adt: &Adt,
) -> Option<(GeneratedFunctionTarget, TextSize)> {
let target = match impl_ {
Some(impl_) => next_space_for_fn_in_impl(impl_)?,
None => {
- next_space_for_fn_in_module(ctx.sema.db, &target_module.definition_source(ctx.sema.db))?
- .1
+ GeneratedFunctionTarget::BehindItem(adt.source(ctx.sema.db)?.syntax().value.clone())
}
};
Some((target.clone(), get_insert_offset(&target)))
@@ -437,7 +448,7 @@ fn assoc_fn_target_info(
return None;
}
let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
- let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
+ let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
Some(TargetInfo::new(target_module, adt_name, target, file, insert_offset))
}
@@ -1468,14 +1479,12 @@ fn foo() {S.bar$0();}
",
r"
struct S;
-fn foo() {S.bar();}
impl S {
-
-
-fn bar(&self) ${0:-> _} {
- todo!()
-}
+ fn bar(&self) ${0:-> _} {
+ todo!()
+ }
}
+fn foo() {S.bar();}
",
)
}
@@ -1516,14 +1525,12 @@ fn foo() {s::S.bar$0();}
r"
mod s {
pub struct S;
-impl S {
-
-
- pub(crate) fn bar(&self) ${0:-> _} {
- todo!()
+ impl S {
+ pub(crate) fn bar(&self) ${0:-> _} {
+ todo!()
+ }
}
}
-}
fn foo() {s::S.bar();}
",
)
@@ -1544,18 +1551,16 @@ mod s {
",
r"
struct S;
+impl S {
+ fn bar(&self) ${0:-> _} {
+ todo!()
+ }
+}
mod s {
fn foo() {
super::S.bar();
}
}
-impl S {
-
-
-fn bar(&self) ${0:-> _} {
- todo!()
-}
-}
",
)
@@ -1571,14 +1576,12 @@ fn foo() {$0S.bar();}
",
r"
struct S;
-fn foo() {S.bar();}
impl S {
-
-
-fn bar(&self) ${0:-> _} {
- todo!()
-}
+ fn bar(&self) ${0:-> _} {
+ todo!()
+ }
}
+fn foo() {S.bar();}
",
)
}
@@ -1593,14 +1596,12 @@ fn foo() {S::bar$0();}
",
r"
struct S;
-fn foo() {S::bar();}
impl S {
-
-
-fn bar() ${0:-> _} {
- todo!()
-}
+ fn bar() ${0:-> _} {
+ todo!()
+ }
}
+fn foo() {S::bar();}
",
)
}
@@ -1641,14 +1642,12 @@ fn foo() {s::S::bar$0();}
r"
mod s {
pub struct S;
-impl S {
-
-
- pub(crate) fn bar() ${0:-> _} {
- todo!()
+ impl S {
+ pub(crate) fn bar() ${0:-> _} {
+ todo!()
+ }
}
}
-}
fn foo() {s::S::bar();}
",
)
@@ -1664,14 +1663,12 @@ fn foo() {$0S::bar();}
",
r"
struct S;
-fn foo() {S::bar();}
impl S {
-
-
-fn bar() ${0:-> _} {
- todo!()
-}
+ fn bar() ${0:-> _} {
+ todo!()
+ }
}
+fn foo() {S::bar();}
",
)
}
@@ -1841,15 +1838,13 @@ fn main() {
",
r"
enum Foo {}
-fn main() {
- Foo::new();
-}
impl Foo {
-
-
-fn new() ${0:-> _} {
- todo!()
+ fn new() ${0:-> _} {
+ todo!()
+ }
}
+fn main() {
+ Foo::new();
}
",
)
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 76fcef0ca..5e7191428 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
@@ -1,6 +1,9 @@
use ide_db::famous_defs::FamousDefs;
use stdx::{format_to, to_lower_snake_case};
-use syntax::ast::{self, AstNode, HasName, HasVisibility};
+use syntax::{
+ ast::{self, AstNode, HasName, HasVisibility},
+ TextRange,
+};
use crate::{
utils::{convert_reference_type, find_impl_block_end, find_struct_impl, generate_impl_text},
@@ -72,92 +75,259 @@ pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext<'_>) ->
generate_getter_impl(acc, ctx, true)
}
+#[derive(Clone, Debug)]
+struct RecordFieldInfo {
+ field_name: syntax::ast::Name,
+ field_ty: syntax::ast::Type,
+ fn_name: String,
+ target: TextRange,
+}
+
+struct GetterInfo {
+ impl_def: Option<ast::Impl>,
+ strukt: ast::Struct,
+ mutable: bool,
+}
+
pub(crate) fn generate_getter_impl(
acc: &mut Assists,
ctx: &AssistContext<'_>,
mutable: bool,
) -> Option<()> {
- let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
- let field = ctx.find_node_at_offset::<ast::RecordField>()?;
+ // This if condition denotes two modes this assist can work in:
+ // - First is acting upon selection of record fields
+ // - Next is acting upon a single record field
+ //
+ // This is the only part where implementation diverges a bit,
+ // subsequent code is generic for both of these modes
- let field_name = field.name()?;
- let field_ty = field.ty()?;
+ let (strukt, info_of_record_fields, fn_names) = if !ctx.has_empty_selection() {
+ // Selection Mode
+ let node = ctx.covering_element();
- // Return early if we've found an existing fn
- let mut fn_name = to_lower_snake_case(&field_name.to_string());
- if mutable {
- format_to!(fn_name, "_mut");
+ let node = match node {
+ syntax::NodeOrToken::Node(n) => n,
+ syntax::NodeOrToken::Token(t) => t.parent()?,
+ };
+
+ let parent_struct = node.ancestors().find_map(ast::Struct::cast)?;
+
+ let (info_of_record_fields, field_names) =
+ extract_and_parse_record_fields(&parent_struct, ctx.selection_trimmed(), mutable)?;
+
+ (parent_struct, info_of_record_fields, field_names)
+ } else {
+ // Single Record Field mode
+ let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
+ let field = ctx.find_node_at_offset::<ast::RecordField>()?;
+
+ let record_field_info = parse_record_field(field, mutable)?;
+
+ let fn_name = record_field_info.fn_name.clone();
+
+ (strukt, vec![record_field_info], vec![fn_name])
+ };
+
+ // No record fields to do work on :(
+ if info_of_record_fields.len() == 0 {
+ return None;
}
- let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), fn_name.as_str())?;
+
+ let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &fn_names)?;
let (id, label) = if mutable {
("generate_getter_mut", "Generate a mut getter method")
} else {
("generate_getter", "Generate a getter method")
};
- let target = field.syntax().text_range();
+
+ // Computing collective text range of all record fields in selected region
+ let target: TextRange = info_of_record_fields
+ .iter()
+ .map(|record_field_info| record_field_info.target)
+ .reduce(|acc, target| acc.cover(target))?;
+
+ let getter_info = GetterInfo { impl_def, strukt, mutable };
+
acc.add_group(
&GroupLabel("Generate getter/setter".to_owned()),
AssistId(id, AssistKind::Generate),
label,
target,
|builder| {
+ let record_fields_count = info_of_record_fields.len();
+
let mut buf = String::with_capacity(512);
- if impl_def.is_some() {
- buf.push('\n');
+ // Check if an impl exists
+ if let Some(impl_def) = &getter_info.impl_def {
+ // Check if impl is empty
+ if let Some(assoc_item_list) = impl_def.assoc_item_list() {
+ if assoc_item_list.assoc_items().next().is_some() {
+ // If not empty then only insert a new line
+ buf.push('\n');
+ }
+ }
}
- let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
- let (ty, body) = if mutable {
- (format!("&mut {}", field_ty), format!("&mut self.{}", field_name))
- } else {
- (|| {
- let krate = ctx.sema.scope(field_ty.syntax())?.krate();
- let famous_defs = &FamousDefs(&ctx.sema, krate);
- ctx.sema
- .resolve_type(&field_ty)
- .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
- .map(|conversion| {
- cov_mark::hit!(convert_reference_type);
- (
- conversion.convert_type(ctx.db()),
- conversion.getter(field_name.to_string()),
- )
- })
- })()
- .unwrap_or_else(|| (format!("&{}", field_ty), format!("&self.{}", field_name)))
- };
-
- format_to!(
- buf,
- " {}fn {}(&{}self) -> {} {{
- {}
- }}",
- vis,
- fn_name,
- mutable.then(|| "mut ").unwrap_or_default(),
- ty,
- body,
- );
-
- let start_offset = impl_def
- .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
+ for (i, record_field_info) in info_of_record_fields.iter().enumerate() {
+ // this buf inserts a newline at the end of a getter
+ // automatically, if one wants to add one more newline
+ // for separating it from other assoc items, that needs
+ // to be handled spearately
+ let mut getter_buf =
+ generate_getter_from_info(ctx, &getter_info, &record_field_info);
+
+ // Insert `$0` only for last getter we generate
+ if i == record_fields_count - 1 {
+ getter_buf = getter_buf.replacen("fn ", "fn $0", 1);
+ }
+
+ // For first element we do not merge with '\n', as
+ // that can be inserted by impl_def check defined
+ // above, for other cases which are:
+ //
+ // - impl exists but it empty, here we would ideally
+ // not want to keep newline between impl <struct> {
+ // and fn <fn-name>() { line
+ //
+ // - next if impl itself does not exist, in this
+ // case we ourselves generate a new impl and that
+ // again ends up with the same reasoning as above
+ // for not keeping newline
+ if i == 0 {
+ buf = buf + &getter_buf;
+ } else {
+ buf = buf + "\n" + &getter_buf;
+ }
+
+ // We don't insert a new line at the end of
+ // last getter as it will end up in the end
+ // of an impl where we would not like to keep
+ // getter and end of impl ( i.e. `}` ) with an
+ // extra line for no reason
+ if i < record_fields_count - 1 {
+ buf = buf + "\n";
+ }
+ }
+
+ let start_offset = getter_info
+ .impl_def
+ .as_ref()
+ .and_then(|impl_def| find_impl_block_end(impl_def.to_owned(), &mut buf))
.unwrap_or_else(|| {
- buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
- strukt.syntax().text_range().end()
+ buf = generate_impl_text(&ast::Adt::Struct(getter_info.strukt.clone()), &buf);
+ getter_info.strukt.syntax().text_range().end()
});
match ctx.config.snippet_cap {
- Some(cap) => {
- builder.insert_snippet(cap, start_offset, buf.replacen("fn ", "fn $0", 1))
- }
+ Some(cap) => builder.insert_snippet(cap, start_offset, buf),
None => builder.insert(start_offset, buf),
}
},
)
}
+fn generate_getter_from_info(
+ ctx: &AssistContext<'_>,
+ info: &GetterInfo,
+ record_field_info: &RecordFieldInfo,
+) -> String {
+ let mut buf = String::with_capacity(512);
+
+ let vis = info.strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
+ let (ty, body) = if info.mutable {
+ (
+ format!("&mut {}", record_field_info.field_ty),
+ format!("&mut self.{}", record_field_info.field_name),
+ )
+ } else {
+ (|| {
+ let krate = ctx.sema.scope(record_field_info.field_ty.syntax())?.krate();
+ let famous_defs = &FamousDefs(&ctx.sema, krate);
+ ctx.sema
+ .resolve_type(&record_field_info.field_ty)
+ .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
+ .map(|conversion| {
+ cov_mark::hit!(convert_reference_type);
+ (
+ conversion.convert_type(ctx.db()),
+ conversion.getter(record_field_info.field_name.to_string()),
+ )
+ })
+ })()
+ .unwrap_or_else(|| {
+ (
+ format!("&{}", record_field_info.field_ty),
+ format!("&self.{}", record_field_info.field_name),
+ )
+ })
+ };
+
+ format_to!(
+ buf,
+ " {}fn {}(&{}self) -> {} {{
+ {}
+ }}",
+ vis,
+ record_field_info.fn_name,
+ info.mutable.then(|| "mut ").unwrap_or_default(),
+ ty,
+ body,
+ );
+
+ buf
+}
+
+fn extract_and_parse_record_fields(
+ node: &ast::Struct,
+ selection_range: TextRange,
+ mutable: bool,
+) -> Option<(Vec<RecordFieldInfo>, Vec<String>)> {
+ let mut field_names: Vec<String> = vec![];
+ let field_list = node.field_list()?;
+
+ match field_list {
+ ast::FieldList::RecordFieldList(ele) => {
+ let info_of_record_fields_in_selection = ele
+ .fields()
+ .filter_map(|record_field| {
+ if selection_range.contains_range(record_field.syntax().text_range()) {
+ let record_field_info = parse_record_field(record_field, mutable)?;
+ field_names.push(record_field_info.fn_name.clone());
+ return Some(record_field_info);
+ }
+
+ None
+ })
+ .collect::<Vec<RecordFieldInfo>>();
+
+ if info_of_record_fields_in_selection.len() == 0 {
+ return None;
+ }
+
+ Some((info_of_record_fields_in_selection, field_names))
+ }
+ ast::FieldList::TupleFieldList(_) => {
+ return None;
+ }
+ }
+}
+
+fn parse_record_field(record_field: ast::RecordField, mutable: bool) -> Option<RecordFieldInfo> {
+ let field_name = record_field.name()?;
+ let field_ty = record_field.ty()?;
+
+ let mut fn_name = to_lower_snake_case(&field_name.to_string());
+ if mutable {
+ format_to!(fn_name, "_mut");
+ }
+
+ let target = record_field.syntax().text_range();
+
+ Some(RecordFieldInfo { field_name, field_ty, fn_name, target })
+}
+
#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};
@@ -489,4 +659,53 @@ impl Context {
"#,
);
}
+
+ #[test]
+ fn test_generate_multiple_getters_from_selection() {
+ check_assist(
+ generate_getter,
+ r#"
+struct Context {
+ $0data: Data,
+ count: usize,$0
+}
+ "#,
+ r#"
+struct Context {
+ data: Data,
+ count: usize,
+}
+
+impl Context {
+ fn data(&self) -> &Data {
+ &self.data
+ }
+
+ fn $0count(&self) -> &usize {
+ &self.count
+ }
+}
+ "#,
+ );
+ }
+
+ #[test]
+ fn test_generate_multiple_getters_from_selection_one_already_exists() {
+ // As impl for one of the fields already exist, skip it
+ check_assist_not_applicable(
+ generate_getter,
+ r#"
+struct Context {
+ $0data: Data,
+ count: usize,$0
+}
+
+impl Context {
+ fn data(&self) -> &Data {
+ &self.data
+ }
+}
+ "#,
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
index 68287a20b..9af26c04e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
@@ -28,7 +28,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
acc.add(
AssistId("generate_impl", AssistKind::Generate),
- format!("Generate impl for `{}`", name),
+ format!("Generate impl for `{name}`"),
target,
|edit| {
let start_offset = nominal.syntax().text_range().end();
@@ -52,6 +52,7 @@ mod tests {
use super::*;
+ // FIXME: break up into separate test fns
#[test]
fn test_add_impl() {
check_assist(
@@ -136,6 +137,18 @@ mod tests {
check_assist(
generate_impl,
+ r#"
+ struct Defaulted<const N: i32 = 0> {}$0"#,
+ r#"
+ struct Defaulted<const N: i32 = 0> {}
+
+ impl<const N: i32> Defaulted<N> {
+ $0
+ }"#,
+ );
+
+ check_assist(
+ generate_impl,
r#"pub trait Trait {}
struct Struct<T>$0
where
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
index 6c93875e9..17fadea0e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_new.rs
@@ -39,7 +39,8 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
};
// Return early if we've found an existing new fn
- let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), "new")?;
+ let impl_def =
+ find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &[String::from("new")])?;
let current_module = ctx.sema.scope(strukt.syntax())?.module();
@@ -51,17 +52,22 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
buf.push('\n');
}
- let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
+ let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
let trivial_constructors = field_list
.fields()
.map(|f| {
+ let name = f.name()?;
+
let ty = ctx.sema.resolve_type(&f.ty()?)?;
let item_in_ns = hir::ItemInNs::from(hir::ModuleDef::from(ty.as_adt()?));
- let type_path = current_module
- .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;
+ let type_path = current_module.find_use_path(
+ ctx.sema.db,
+ item_for_path_search(ctx.sema.db, item_in_ns)?,
+ ctx.config.prefer_no_std,
+ )?;
let expr = use_trivial_constructor(
&ctx.sema.db,
@@ -69,7 +75,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
&ty,
)?;
- Some(format!("{}: {}", f.name()?.syntax(), expr))
+ Some(format!("{name}: {expr}"))
})
.collect::<Vec<_>>();
@@ -78,7 +84,10 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
.enumerate()
.filter_map(|(i, f)| {
if trivial_constructors[i].is_none() {
- Some(format!("{}: {}", f.name()?.syntax(), f.ty()?.syntax()))
+ let name = f.name()?;
+ let ty = f.ty()?;
+
+ Some(format!("{name}: {ty}"))
} else {
None
}
@@ -98,7 +107,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option
})
.format(", ");
- format_to!(buf, " {}fn new({}) -> Self {{ Self {{ {} }} }}", vis, params, fields);
+ format_to!(buf, " {vis}fn new({params}) -> Self {{ Self {{ {fields} }} }}");
let start_offset = impl_def
.and_then(|impl_def| find_impl_block_start(impl_def, &mut buf))
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs
index 2a7ad6ce3..62f72df1c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_setter.rs
@@ -36,11 +36,8 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
// Return early if we've found an existing fn
let fn_name = to_lower_snake_case(&field_name.to_string());
- let impl_def = find_struct_impl(
- ctx,
- &ast::Adt::Struct(strukt.clone()),
- format!("set_{}", fn_name).as_str(),
- )?;
+ let impl_def =
+ find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &[format!("set_{fn_name}")])?;
let target = field.syntax().text_range();
acc.add_group(
@@ -55,18 +52,12 @@ pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
buf.push('\n');
}
- let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
+ let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
format_to!(
buf,
- " {}fn set_{}(&mut self, {}: {}) {{
- self.{} = {};
- }}",
- vis,
- fn_name,
- fn_name,
- field_ty,
- fn_name,
- fn_name,
+ " {vis}fn set_{fn_name}(&mut self, {fn_name}: {field_ty}) {{
+ self.{fn_name} = {fn_name};
+ }}"
);
let start_offset = impl_def
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs
new file mode 100644
index 000000000..aa710d2ce
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_format_string_arg.rs
@@ -0,0 +1,296 @@
+use crate::{AssistContext, Assists};
+use ide_db::{
+ assists::{AssistId, AssistKind},
+ syntax_helpers::{
+ format_string::is_format_string,
+ format_string_exprs::{parse_format_exprs, Arg},
+ },
+};
+use itertools::Itertools;
+use stdx::format_to;
+use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxKind::COMMA, TextRange};
+
+// Assist: move_format_string_arg
+//
+// Move an expression out of a format string.
+//
+// ```
+// macro_rules! format_args {
+// ($lit:literal $(tt:tt)*) => { 0 },
+// }
+// macro_rules! print {
+// ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+// }
+//
+// fn main() {
+// print!("{x + 1}$0");
+// }
+// ```
+// ->
+// ```
+// macro_rules! format_args {
+// ($lit:literal $(tt:tt)*) => { 0 },
+// }
+// macro_rules! print {
+// ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+// }
+//
+// fn main() {
+// print!("{}"$0, x + 1);
+// }
+// ```
+
+pub(crate) fn move_format_string_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let fmt_string = ctx.find_token_at_offset::<ast::String>()?;
+ let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
+
+ let expanded_t = ast::String::cast(
+ ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone()),
+ )?;
+ if !is_format_string(&expanded_t) {
+ return None;
+ }
+
+ let (new_fmt, extracted_args) = parse_format_exprs(fmt_string.text()).ok()?;
+ if extracted_args.is_empty() {
+ return None;
+ }
+
+ acc.add(
+ AssistId(
+ "move_format_string_arg",
+ // if there aren't any expressions, then make the assist a RefactorExtract
+ if extracted_args.iter().filter(|f| matches!(f, Arg::Expr(_))).count() == 0 {
+ AssistKind::RefactorExtract
+ } else {
+ AssistKind::QuickFix
+ },
+ ),
+ "Extract format args",
+ tt.syntax().text_range(),
+ |edit| {
+ let fmt_range = fmt_string.syntax().text_range();
+
+ // Replace old format string with new format string whose arguments have been extracted
+ edit.replace(fmt_range, new_fmt);
+
+ // Insert cursor at end of format string
+ edit.insert(fmt_range.end(), "$0");
+
+ // Extract existing arguments in macro
+ let tokens =
+ tt.token_trees_and_tokens().collect_vec();
+
+ let mut existing_args: Vec<String> = vec![];
+
+ let mut current_arg = String::new();
+ if let [_opening_bracket, NodeOrToken::Token(format_string), _args_start_comma, tokens @ .., NodeOrToken::Token(end_bracket)] =
+ tokens.as_slice()
+ {
+ for t in tokens {
+ match t {
+ NodeOrToken::Node(n) => {
+ format_to!(current_arg, "{n}");
+ },
+ NodeOrToken::Token(t) if t.kind() == COMMA=> {
+ existing_args.push(current_arg.trim().into());
+ current_arg.clear();
+ },
+ NodeOrToken::Token(t) => {
+ current_arg.push_str(t.text());
+ },
+ }
+ }
+ existing_args.push(current_arg.trim().into());
+
+ // delete everything after the format string till end bracket
+ // we're going to insert the new arguments later
+ edit.delete(TextRange::new(
+ format_string.text_range().end(),
+ end_bracket.text_range().start(),
+ ));
+ }
+
+ // Start building the new args
+ let mut existing_args = existing_args.into_iter();
+ let mut args = String::new();
+
+ let mut placeholder_idx = 1;
+
+ for extracted_args in extracted_args {
+ // remove expr from format string
+ args.push_str(", ");
+
+ match extracted_args {
+ Arg::Ident(s) | Arg::Expr(s) => {
+ // insert arg
+ args.push_str(&s);
+ }
+ Arg::Placeholder => {
+ // try matching with existing argument
+ match existing_args.next() {
+ Some(ea) => {
+ args.push_str(&ea);
+ }
+ None => {
+ // insert placeholder
+ args.push_str(&format!("${placeholder_idx}"));
+ placeholder_idx += 1;
+ }
+ }
+ }
+ }
+ }
+
+ // Insert new args
+ edit.insert(fmt_range.end(), args);
+ },
+ );
+
+ Some(())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::tests::check_assist;
+
+ const MACRO_DECL: &'static str = r#"
+macro_rules! format_args {
+ ($lit:literal $(tt:tt)*) => { 0 },
+}
+macro_rules! print {
+ ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+}
+"#;
+
+ fn add_macro_decl(s: &'static str) -> String {
+ MACRO_DECL.to_string() + s
+ }
+
+ #[test]
+ fn multiple_middle_arg() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {x + 1:b} {}$0", y + 2, 2);
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {:b} {}"$0, y + 2, x + 1, 2);
+}
+"#,
+ ),
+ );
+ }
+
+ #[test]
+ fn single_arg() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{obj.value:b}$0",);
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{:b}"$0, obj.value);
+}
+"#,
+ ),
+ );
+ }
+
+ #[test]
+ fn multiple_middle_placeholders_arg() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {x + 1:b} {} {}$0", y + 2, 2);
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {:b} {} {}"$0, y + 2, x + 1, 2, $1);
+}
+"#,
+ ),
+ );
+ }
+
+ #[test]
+ fn multiple_trailing_args() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {x + 1:b} {Struct(1, 2)}$0", 1);
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {:b} {}"$0, 1, x + 1, Struct(1, 2));
+}
+"#,
+ ),
+ );
+ }
+
+ #[test]
+ fn improper_commas() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {x + 1:b} {Struct(1, 2)}$0", 1,);
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("{} {:b} {}"$0, 1, x + 1, Struct(1, 2));
+}
+"#,
+ ),
+ );
+ }
+
+ #[test]
+ fn nested_tt() {
+ check_assist(
+ move_format_string_arg,
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("My name is {} {x$0 + x}", stringify!(Paperino))
+}
+"#,
+ ),
+ &add_macro_decl(
+ r#"
+fn main() {
+ print!("My name is {} {}"$0, stringify!(Paperino), x + x)
+}
+"#,
+ ),
+ );
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
index 121f8b4a1..e57d1d065 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_method_call.rs
@@ -44,8 +44,11 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) ->
let current_module = ctx.sema.scope(call.syntax())?.module();
let target_module_def = ModuleDef::from(resolved_call);
let item_in_ns = ItemInNs::from(target_module_def);
- let receiver_path = current_module
- .find_use_path(ctx.sema.db, item_for_path_search(ctx.sema.db, item_in_ns)?)?;
+ let receiver_path = current_module.find_use_path(
+ ctx.sema.db,
+ item_for_path_search(ctx.sema.db, item_in_ns)?,
+ ctx.config.prefer_no_std,
+ )?;
let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
index 0c2e9da38..4b2af550b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/qualify_path.rs
@@ -37,7 +37,8 @@ use crate::{
// ```
pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
let (import_assets, syntax_under_caret) = find_importable_node(ctx)?;
- let mut proposed_imports = import_assets.search_for_relative_paths(&ctx.sema);
+ let mut proposed_imports =
+ import_assets.search_for_relative_paths(&ctx.sema, ctx.config.prefer_no_std);
if proposed_imports.is_empty() {
return None;
}
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 d139f78a6..9fd5e1886 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
@@ -85,7 +85,7 @@ pub(crate) fn replace_derive_with_manual_impl(
})
.flat_map(|trait_| {
current_module
- .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_))
+ .find_use_path(ctx.sema.db, hir::ModuleDef::Trait(trait_), ctx.config.prefer_no_std)
.as_ref()
.map(mod_path_to_ast)
.zip(Some(trait_))
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index 2419fa11c..dbbc56958 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -67,6 +67,7 @@ pub(crate) fn replace_qualified_name_with_use(
ctx.sema.db,
module,
ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
)
})
.flatten();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs
new file mode 100644
index 000000000..25c58d086
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unwrap_tuple.rs
@@ -0,0 +1,159 @@
+use syntax::{
+ ast::{self, edit::AstNodeEdit},
+ AstNode, T,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: unwrap_tuple
+//
+// Unwrap the tuple to different variables.
+//
+// ```
+// # //- minicore: result
+// fn main() {
+// $0let (foo, bar) = ("Foo", "Bar");
+// }
+// ```
+// ->
+// ```
+// fn main() {
+// let foo = "Foo";
+// let bar = "Bar";
+// }
+// ```
+pub(crate) fn unwrap_tuple(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+ let let_kw = ctx.find_token_syntax_at_offset(T![let])?;
+ let let_stmt = let_kw.parent().and_then(ast::LetStmt::cast)?;
+ let indent_level = let_stmt.indent_level().0 as usize;
+ let pat = let_stmt.pat()?;
+ let ty = let_stmt.ty();
+ let init = let_stmt.initializer()?;
+
+ // This only applies for tuple patterns, types, and initializers.
+ let tuple_pat = match pat {
+ ast::Pat::TuplePat(pat) => pat,
+ _ => return None,
+ };
+ let tuple_ty = ty.and_then(|it| match it {
+ ast::Type::TupleType(ty) => Some(ty),
+ _ => None,
+ });
+ let tuple_init = match init {
+ ast::Expr::TupleExpr(expr) => expr,
+ _ => return None,
+ };
+
+ if tuple_pat.fields().count() != tuple_init.fields().count() {
+ return None;
+ }
+ if let Some(tys) = &tuple_ty {
+ if tuple_pat.fields().count() != tys.fields().count() {
+ return None;
+ }
+ }
+
+ let parent = let_kw.parent()?;
+
+ acc.add(
+ AssistId("unwrap_tuple", AssistKind::RefactorRewrite),
+ "Unwrap tuple",
+ let_kw.text_range(),
+ |edit| {
+ let indents = " ".repeat(indent_level);
+
+ // If there is an ascribed type, insert that type for each declaration,
+ // otherwise, omit that type.
+ if let Some(tys) = tuple_ty {
+ let mut zipped_decls = String::new();
+ for (pat, ty, expr) in
+ itertools::izip!(tuple_pat.fields(), tys.fields(), tuple_init.fields())
+ {
+ zipped_decls.push_str(&format!("{}let {pat}: {ty} = {expr};\n", indents))
+ }
+ edit.replace(parent.text_range(), zipped_decls.trim());
+ } else {
+ let mut zipped_decls = String::new();
+ for (pat, expr) in itertools::izip!(tuple_pat.fields(), tuple_init.fields()) {
+ zipped_decls.push_str(&format!("{}let {pat} = {expr};\n", indents));
+ }
+ edit.replace(parent.text_range(), zipped_decls.trim());
+ }
+ },
+ )
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::check_assist;
+
+ use super::*;
+
+ #[test]
+ fn unwrap_tuples() {
+ check_assist(
+ unwrap_tuple,
+ r#"
+fn main() {
+ $0let (foo, bar) = ("Foo", "Bar");
+}
+"#,
+ r#"
+fn main() {
+ let foo = "Foo";
+ let bar = "Bar";
+}
+"#,
+ );
+
+ check_assist(
+ unwrap_tuple,
+ r#"
+fn main() {
+ $0let (foo, bar, baz) = ("Foo", "Bar", "Baz");
+}
+"#,
+ r#"
+fn main() {
+ let foo = "Foo";
+ let bar = "Bar";
+ let baz = "Baz";
+}
+"#,
+ );
+ }
+
+ #[test]
+ fn unwrap_tuple_with_types() {
+ check_assist(
+ unwrap_tuple,
+ r#"
+fn main() {
+ $0let (foo, bar): (u8, i32) = (5, 10);
+}
+"#,
+ r#"
+fn main() {
+ let foo: u8 = 5;
+ let bar: i32 = 10;
+}
+"#,
+ );
+
+ check_assist(
+ unwrap_tuple,
+ r#"
+fn main() {
+ $0let (foo, bar, baz): (u8, i32, f64) = (5, 10, 17.5);
+}
+"#,
+ r#"
+fn main() {
+ let foo: u8 = 5;
+ let bar: i32 = 10;
+ let baz: f64 = 17.5;
+}
+"#,
+ );
+ }
+}
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 e52544db5..a07318cef 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -121,6 +121,7 @@ mod handlers {
mod convert_iter_for_each_to_for;
mod convert_let_else_to_match;
mod convert_tuple_struct_to_named_struct;
+ mod convert_named_struct_to_tuple_struct;
mod convert_to_guarded_return;
mod convert_two_arm_bool_match_to_matches_macro;
mod convert_while_to_loop;
@@ -136,6 +137,7 @@ mod handlers {
mod flip_binexpr;
mod flip_comma;
mod flip_trait_bound;
+ mod move_format_string_arg;
mod generate_constant;
mod generate_default_from_enum_variant;
mod generate_default_from_new;
@@ -188,6 +190,7 @@ mod handlers {
mod replace_turbofish_with_explicit_type;
mod split_import;
mod unmerge_match_arm;
+ mod unwrap_tuple;
mod sort_items;
mod toggle_ignore;
mod unmerge_use;
@@ -216,6 +219,7 @@ mod handlers {
convert_iter_for_each_to_for::convert_iter_for_each_to_for,
convert_iter_for_each_to_for::convert_for_loop_with_for_each,
convert_let_else_to_match::convert_let_else_to_match,
+ convert_named_struct_to_tuple_struct::convert_named_struct_to_tuple_struct,
convert_to_guarded_return::convert_to_guarded_return,
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,
@@ -254,6 +258,7 @@ mod handlers {
merge_imports::merge_imports,
merge_match_arms::merge_match_arms,
move_bounds::move_bounds_to_where_clause,
+ move_format_string_arg::move_format_string_arg,
move_guard::move_arm_cond_to_match_guard,
move_guard::move_guard_to_arm_body,
move_module_to_file::move_module_to_file,
@@ -289,6 +294,7 @@ mod handlers {
unnecessary_async::unnecessary_async,
unwrap_block::unwrap_block,
unwrap_result_return_type::unwrap_result_return_type,
+ unwrap_tuple::unwrap_tuple,
wrap_return_type_in_result::wrap_return_type_in_result,
// These are manually sorted for better priorities. By default,
// priority is determined by the size of the target range (smaller
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 9cd66c6b3..f7f2417d0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
@@ -29,6 +29,7 @@ pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
group: true,
skip_glob_imports: true,
},
+ prefer_no_std: false,
};
pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
@@ -95,8 +96,10 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
});
let actual = {
- let source_change =
- assist.source_change.expect("Assist did not contain any source changes");
+ let source_change = assist
+ .source_change
+ .filter(|it| !it.source_file_edits.is_empty() || !it.file_system_edits.is_empty())
+ .expect("Assist did not contain any source changes");
let mut actual = before;
if let Some(source_file_edit) = source_change.get_source_edit(file_id) {
source_file_edit.apply(&mut actual);
@@ -139,8 +142,10 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult<'_>, assist_la
match (assist, expected) {
(Some(assist), ExpectedResult::After(after)) => {
- let source_change =
- assist.source_change.expect("Assist did not contain any source changes");
+ let source_change = assist
+ .source_change
+ .filter(|it| !it.source_file_edits.is_empty() || !it.file_system_edits.is_empty())
+ .expect("Assist did not contain any source changes");
let skip_header = source_change.source_file_edits.len() == 1
&& source_change.file_system_edits.len() == 0;
@@ -227,6 +232,7 @@ fn assist_order_field_struct() {
assert_eq!(assists.next().expect("expected assist").label, "Generate a getter method");
assert_eq!(assists.next().expect("expected assist").label, "Generate a mut getter method");
assert_eq!(assists.next().expect("expected assist").label, "Generate a setter method");
+ assert_eq!(assists.next().expect("expected assist").label, "Convert to tuple struct");
assert_eq!(assists.next().expect("expected assist").label, "Add `#[derive]`");
}
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 227e2300f..2c4000efe 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
@@ -408,6 +408,47 @@ fn main() {
}
#[test]
+fn doctest_convert_named_struct_to_tuple_struct() {
+ check_doc_test(
+ "convert_named_struct_to_tuple_struct",
+ r#####"
+struct Point$0 { x: f32, y: f32 }
+
+impl Point {
+ pub fn new(x: f32, y: f32) -> Self {
+ Point { x, y }
+ }
+
+ pub fn x(&self) -> f32 {
+ self.x
+ }
+
+ pub fn y(&self) -> f32 {
+ self.y
+ }
+}
+"#####,
+ r#####"
+struct Point(f32, f32);
+
+impl Point {
+ pub fn new(x: f32, y: f32) -> Self {
+ Point(x, y)
+ }
+
+ pub fn x(&self) -> f32 {
+ self.0
+ }
+
+ pub fn y(&self) -> f32 {
+ self.1
+ }
+}
+"#####,
+ )
+}
+
+#[test]
fn doctest_convert_to_guarded_return() {
check_doc_test(
"convert_to_guarded_return",
@@ -1592,6 +1633,37 @@ fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
}
#[test]
+fn doctest_move_format_string_arg() {
+ check_doc_test(
+ "move_format_string_arg",
+ r#####"
+macro_rules! format_args {
+ ($lit:literal $(tt:tt)*) => { 0 },
+}
+macro_rules! print {
+ ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+}
+
+fn main() {
+ print!("{x + 1}$0");
+}
+"#####,
+ r#####"
+macro_rules! format_args {
+ ($lit:literal $(tt:tt)*) => { 0 },
+}
+macro_rules! print {
+ ($($arg:tt)*) => (std::io::_print(format_args!($($arg)*)));
+}
+
+fn main() {
+ print!("{}"$0, x + 1);
+}
+"#####,
+ )
+}
+
+#[test]
fn doctest_move_from_mod_rs() {
check_doc_test(
"move_from_mod_rs",
@@ -2356,6 +2428,25 @@ fn foo() -> i32 { 42i32 }
}
#[test]
+fn doctest_unwrap_tuple() {
+ check_doc_test(
+ "unwrap_tuple",
+ r#####"
+//- minicore: result
+fn main() {
+ $0let (foo, bar) = ("Foo", "Bar");
+}
+"#####,
+ r#####"
+fn main() {
+ let foo = "Foo";
+ let bar = "Bar";
+}
+"#####,
+ )
+}
+
+#[test]
fn doctest_wrap_return_type_in_result() {
check_doc_test(
"wrap_return_type_in_result",
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 4ab6e2627..db32e7182 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -2,8 +2,6 @@
use std::ops;
-use itertools::Itertools;
-
pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
use hir::{db::HirDatabase, HirDisplay, Semantics};
use ide_db::{famous_defs::FamousDefs, path_transform::PathTransform, RootDatabase, SnippetCap};
@@ -15,7 +13,7 @@ use syntax::{
edit_in_place::{AttrsOwnerEdit, Removable},
make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
},
- ted, AstNode, AstToken, Direction, SmolStr, SourceFile,
+ ted, AstNode, AstToken, Direction, SourceFile,
SyntaxKind::*,
SyntaxNode, TextRange, TextSize, T,
};
@@ -333,10 +331,14 @@ fn calc_depth(pat: &ast::Pat, depth: usize) -> usize {
// FIXME: change the new fn checking to a more semantic approach when that's more
// viable (e.g. we process proc macros, etc)
// FIXME: this partially overlaps with `find_impl_block_*`
+
+/// `find_struct_impl` looks for impl of a struct, but this also has additional feature
+/// where it takes a list of function names and check if they exist inside impl_, if
+/// even one match is found, it returns None
pub(crate) fn find_struct_impl(
ctx: &AssistContext<'_>,
adt: &ast::Adt,
- name: &str,
+ names: &[String],
) -> Option<Option<ast::Impl>> {
let db = ctx.db();
let module = adt.syntax().parent()?;
@@ -364,7 +366,7 @@ pub(crate) fn find_struct_impl(
});
if let Some(ref impl_blk) = block {
- if has_fn(impl_blk, name) {
+ if has_any_fn(impl_blk, names) {
return None;
}
}
@@ -372,12 +374,12 @@ pub(crate) fn find_struct_impl(
Some(block)
}
-fn has_fn(imp: &ast::Impl, rhs_name: &str) -> bool {
+fn has_any_fn(imp: &ast::Impl, names: &[String]) -> bool {
if let Some(il) = imp.assoc_item_list() {
for item in il.assoc_items() {
if let ast::AssocItem::Fn(f) = item {
if let Some(name) = f.name() {
- if name.text().eq_ignore_ascii_case(rhs_name) {
+ if names.iter().any(|n| n.eq_ignore_ascii_case(&name.text())) {
return true;
}
}
@@ -424,34 +426,44 @@ pub(crate) fn generate_trait_impl_text(adt: &ast::Adt, trait_text: &str, code: &
}
fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str) -> String {
- let generic_params = adt.generic_param_list();
+ // Ensure lifetime params are before type & const params
+ let generic_params = adt.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| {
+ // 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::TypeOrConstParam::Const(param) => {
+ let param = param.clone_for_update();
+ param.remove_default();
+ Some(ast::GenericParam::ConstParam(param))
+ }
+ }
+ });
+
+ make::generic_param_list(itertools::chain(lifetime_params, ty_or_const_params))
+ });
+
+ // FIXME: use syntax::make & mutable AST apis instead
+ // `trait_text` and `code` can't be opaque blobs of text
let mut buf = String::with_capacity(code.len());
+
+ // Copy any cfg attrs from the original adt
buf.push_str("\n\n");
- adt.attrs()
- .filter(|attr| attr.as_simple_call().map(|(name, _arg)| name == "cfg").unwrap_or(false))
- .for_each(|attr| buf.push_str(format!("{}\n", attr).as_str()));
+ let cfg_attrs = adt
+ .attrs()
+ .filter(|attr| attr.as_simple_call().map(|(name, _arg)| name == "cfg").unwrap_or(false));
+ cfg_attrs.for_each(|attr| buf.push_str(&format!("{attr}\n")));
+
+ // `impl{generic_params} {trait_text} for {name}{generic_params.to_generic_args()}`
buf.push_str("impl");
if let Some(generic_params) = &generic_params {
- let lifetimes = generic_params.lifetime_params().map(|lt| format!("{}", lt.syntax()));
- let toc_params = generic_params.type_or_const_params().map(|toc_param| {
- let type_param = match toc_param {
- ast::TypeOrConstParam::Type(x) => x,
- ast::TypeOrConstParam::Const(x) => return x.syntax().to_string(),
- };
- let mut buf = String::new();
- if let Some(it) = type_param.name() {
- format_to!(buf, "{}", it.syntax());
- }
- if let Some(it) = type_param.colon_token() {
- format_to!(buf, "{} ", it);
- }
- if let Some(it) = type_param.type_bound_list() {
- format_to!(buf, "{}", it.syntax());
- }
- buf
- });
- let generics = lifetimes.chain(toc_params).format(", ");
- format_to!(buf, "<{}>", generics);
+ format_to!(buf, "{generic_params}");
}
buf.push(' ');
if let Some(trait_text) = trait_text {
@@ -460,23 +472,15 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
}
buf.push_str(&adt.name().unwrap().text());
if let Some(generic_params) = generic_params {
- let lifetime_params = generic_params
- .lifetime_params()
- .filter_map(|it| it.lifetime())
- .map(|it| SmolStr::from(it.text()));
- let toc_params = generic_params
- .type_or_const_params()
- .filter_map(|it| it.name())
- .map(|it| SmolStr::from(it.text()));
- format_to!(buf, "<{}>", lifetime_params.chain(toc_params).format(", "))
+ format_to!(buf, "{}", generic_params.to_generic_args());
}
match adt.where_clause() {
Some(where_clause) => {
- format_to!(buf, "\n{}\n{{\n{}\n}}", where_clause, code);
+ format_to!(buf, "\n{where_clause}\n{{\n{code}\n}}");
}
None => {
- format_to!(buf, " {{\n{}\n}}", code);
+ format_to!(buf, " {{\n{code}\n}}");
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 8c9d6b228..75835bce9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -11,10 +11,10 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.3"
+itertools = "0.10.5"
-once_cell = "1.12.0"
-smallvec = "1.9.0"
+once_cell = "1.15.0"
+smallvec = "1.10.0"
stdx = { path = "../stdx", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index 55c3e2839..296dfc142 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -19,6 +19,7 @@ pub(crate) mod snippet;
pub(crate) mod r#type;
pub(crate) mod use_;
pub(crate) mod vis;
+pub(crate) mod env_vars;
use std::iter;
@@ -551,7 +552,11 @@ fn enum_variants_with_paths(
}
for variant in variants {
- if let Some(path) = ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
+ if let Some(path) = ctx.module.find_use_path(
+ ctx.db,
+ hir::ModuleDef::from(variant),
+ ctx.config.prefer_no_std,
+ ) {
// Variants with trivial paths are already added by the existing completion logic,
// so we should avoid adding these twice
if path.segments().len() > 1 {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
new file mode 100644
index 000000000..09e95e53d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
@@ -0,0 +1,150 @@
+//! Completes environment variables defined by Cargo (https://doc.rust-lang.org/cargo/reference/environment-variables.html)
+use hir::Semantics;
+use ide_db::{syntax_helpers::node_ext::macro_call_for_string_token, RootDatabase};
+use syntax::ast::{self, IsString};
+
+use crate::{
+ completions::Completions, context::CompletionContext, CompletionItem, CompletionItemKind,
+};
+
+const CARGO_DEFINED_VARS: &[(&str, &str)] = &[
+ ("CARGO","Path to the cargo binary performing the build"),
+ ("CARGO_MANIFEST_DIR","The directory containing the manifest of your package"),
+ ("CARGO_PKG_VERSION","The full version of your package"),
+ ("CARGO_PKG_VERSION_MAJOR","The major version of your package"),
+ ("CARGO_PKG_VERSION_MINOR","The minor version of your package"),
+ ("CARGO_PKG_VERSION_PATCH","The patch version of your package"),
+ ("CARGO_PKG_VERSION_PRE","The pre-release version of your package"),
+ ("CARGO_PKG_AUTHORS","Colon separated list of authors from the manifest of your package"),
+ ("CARGO_PKG_NAME","The name of your package"),
+ ("CARGO_PKG_DESCRIPTION","The description from the manifest of your package"),
+ ("CARGO_PKG_HOMEPAGE","The home page from the manifest of your package"),
+ ("CARGO_PKG_REPOSITORY","The repository from the manifest of your package"),
+ ("CARGO_PKG_LICENSE","The license from the manifest of your package"),
+ ("CARGO_PKG_LICENSE_FILE","The license file from the manifest of your package"),
+ ("CARGO_PKG_RUST_VERSION","The Rust version from the manifest of your package. Note that this is the minimum Rust version supported by the package, not the current Rust version"),
+ ("CARGO_CRATE_NAME","The name of the crate that is currently being compiled"),
+ ("CARGO_BIN_NAME","The name of the binary that is currently being compiled (if it is a binary). This name does not include any file extension, such as .exe"),
+ ("CARGO_PRIMARY_PACKAGE","This environment variable will be set if the package being built is primary. Primary packages are the ones the user selected on the command-line, either with -p flags or the defaults based on the current directory and the default workspace members. This environment variable will not be set when building dependencies. This is only set when compiling the package (not when running binaries or tests)"),
+ ("CARGO_TARGET_TMPDIR","Only set when building integration test or benchmark code. This is a path to a directory inside the target directory where integration tests or benchmarks are free to put any data needed by the tests/benches. Cargo initially creates this directory but doesn't manage its content in any way, this is the responsibility of the test code")
+];
+
+pub(crate) fn complete_cargo_env_vars(
+ acc: &mut Completions,
+ ctx: &CompletionContext<'_>,
+ expanded: &ast::String,
+) -> Option<()> {
+ guard_env_macro(expanded, &ctx.sema)?;
+ let range = expanded.text_range_between_quotes()?;
+
+ CARGO_DEFINED_VARS.iter().for_each(|(var, detail)| {
+ let mut item = CompletionItem::new(CompletionItemKind::Keyword, range, var);
+ item.detail(*detail);
+ item.add_to(acc);
+ });
+
+ Some(())
+}
+
+fn guard_env_macro(string: &ast::String, semantics: &Semantics<'_, RootDatabase>) -> Option<()> {
+ let call = macro_call_for_string_token(string)?;
+ let name = call.path()?.segment()?.name_ref()?;
+ let makro = semantics.resolve_macro_call(&call)?;
+ let db = semantics.db;
+
+ match name.text().as_str() {
+ "env" | "option_env" if makro.kind(db) == hir::MacroKind::BuiltIn => Some(()),
+ _ => None,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::tests::{check_edit, completion_list};
+
+ fn check(macro_name: &str) {
+ check_edit(
+ "CARGO_BIN_NAME",
+ &format!(
+ r#"
+ #[rustc_builtin_macro]
+ macro_rules! {} {{
+ ($var:literal) => {{ 0 }}
+ }}
+
+ fn main() {{
+ let foo = {}!("CAR$0");
+ }}
+ "#,
+ macro_name, macro_name
+ ),
+ &format!(
+ r#"
+ #[rustc_builtin_macro]
+ macro_rules! {} {{
+ ($var:literal) => {{ 0 }}
+ }}
+
+ fn main() {{
+ let foo = {}!("CARGO_BIN_NAME");
+ }}
+ "#,
+ macro_name, macro_name
+ ),
+ );
+ }
+ #[test]
+ fn completes_env_variable_in_env() {
+ check("env")
+ }
+
+ #[test]
+ fn completes_env_variable_in_option_env() {
+ check("option_env");
+ }
+
+ #[test]
+ fn doesnt_complete_in_random_strings() {
+ let fixture = r#"
+ fn main() {
+ let foo = "CA$0";
+ }
+ "#;
+
+ let completions = completion_list(fixture);
+ assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
+ }
+
+ #[test]
+ fn doesnt_complete_in_random_macro() {
+ let fixture = r#"
+ macro_rules! bar {
+ ($($arg:tt)*) => { 0 }
+ }
+
+ fn main() {
+ let foo = bar!("CA$0");
+
+ }
+ "#;
+
+ let completions = completion_list(fixture);
+ assert!(completions.is_empty(), "Completions weren't empty: {}", completions);
+ }
+
+ #[test]
+ fn doesnt_complete_for_shadowed_macro() {
+ let fixture = r#"
+ macro_rules! env {
+ ($var:literal) => { 0 }
+ }
+
+ fn main() {
+ let foo = env!("CA$0");
+ }
+ "#;
+
+ let completions = completion_list(fixture);
+ assert!(completions.is_empty(), "Completions weren't empty: {}", completions)
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index 588b52cc1..3192b21cf 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -165,7 +165,11 @@ pub(crate) fn complete_expr_path(
hir::Adt::Struct(strukt) => {
let path = ctx
.module
- .find_use_path(ctx.db, hir::ModuleDef::from(strukt))
+ .find_use_path(
+ ctx.db,
+ hir::ModuleDef::from(strukt),
+ ctx.config.prefer_no_std,
+ )
.filter(|it| it.len() > 1);
acc.add_struct_literal(ctx, path_ctx, strukt, path, None);
@@ -183,7 +187,11 @@ pub(crate) fn complete_expr_path(
hir::Adt::Union(un) => {
let path = ctx
.module
- .find_use_path(ctx.db, hir::ModuleDef::from(un))
+ .find_use_path(
+ ctx.db,
+ hir::ModuleDef::from(un),
+ ctx.config.prefer_no_std,
+ )
.filter(|it| it.len() > 1);
acc.add_union_literal(ctx, un, path, None);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index f04cc15d7..364969af9 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -262,7 +262,11 @@ fn import_on_the_fly(
acc.add_all(
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
+ .search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ )
.into_iter()
.filter(ns_filter)
.filter(|import| {
@@ -306,7 +310,11 @@ fn import_on_the_fly_pat_(
acc.add_all(
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
+ .search_for_imports(
+ &ctx.sema,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ )
.into_iter()
.filter(ns_filter)
.filter(|import| {
@@ -344,7 +352,7 @@ fn import_on_the_fly_method(
let user_input_lowercased = potential_import_name.to_lowercase();
import_assets
- .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind)
+ .search_for_imports(&ctx.sema, ctx.config.insert_use.prefix_kind, ctx.config.prefer_no_std)
.into_iter()
.filter(|import| {
!ctx.is_item_hidden(&import.item_to_import)
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 785db6fde..e82cbfdcb 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
@@ -38,7 +38,7 @@ use ide_db::{
};
use syntax::{
ast::{self, edit_in_place::AttrsOwnerEdit},
- AstNode, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T,
+ AstNode, SyntaxElement, SyntaxKind, TextRange, T,
};
use text_edit::TextEdit;
@@ -85,20 +85,36 @@ fn complete_trait_impl_name(
name: &Option<ast::Name>,
kind: ImplCompletionKind,
) -> Option<()> {
- let token = ctx.token.clone();
let item = match name {
Some(name) => name.syntax().parent(),
- None => if token.kind() == SyntaxKind::WHITESPACE { token.prev_token()? } else { token }
- .parent(),
+ None => {
+ let token = &ctx.token;
+ match token.kind() {
+ SyntaxKind::WHITESPACE => token.prev_token()?,
+ _ => token.clone(),
+ }
+ .parent()
+ }
}?;
- complete_trait_impl(
- acc,
- ctx,
- kind,
- replacement_range(ctx, &item),
- // item -> ASSOC_ITEM_LIST -> IMPL
- &ast::Impl::cast(item.parent()?.parent()?)?,
- );
+ let item = ctx.sema.original_syntax_node(&item)?;
+ // item -> ASSOC_ITEM_LIST -> IMPL
+ let impl_def = ast::Impl::cast(item.parent()?.parent()?)?;
+ let replacement_range = {
+ // ctx.sema.original_ast_node(item)?;
+ let first_child = item
+ .children_with_tokens()
+ .find(|child| {
+ !matches!(
+ child.kind(),
+ SyntaxKind::COMMENT | SyntaxKind::WHITESPACE | SyntaxKind::ATTR
+ )
+ })
+ .unwrap_or_else(|| SyntaxElement::Node(item.clone()));
+
+ TextRange::new(first_child.text_range().start(), ctx.source_range().end())
+ };
+
+ complete_trait_impl(acc, ctx, kind, replacement_range, &impl_def);
Some(())
}
@@ -341,17 +357,6 @@ fn function_declaration(node: &ast::Fn, needs_whitespace: bool) -> String {
syntax.trim_end().to_owned()
}
-fn replacement_range(ctx: &CompletionContext<'_>, item: &SyntaxNode) -> TextRange {
- let first_child = item
- .children_with_tokens()
- .find(|child| {
- !matches!(child.kind(), SyntaxKind::COMMENT | SyntaxKind::WHITESPACE | SyntaxKind::ATTR)
- })
- .unwrap_or_else(|| SyntaxElement::Node(item.clone()));
-
- TextRange::new(first_child.text_range().start(), ctx.source_range().end())
-}
-
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs
index 71d2d9d43..58d5bf114 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs
@@ -145,6 +145,7 @@ pub(crate) fn complete_pattern_path(
u.ty(ctx.db)
}
hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => ty.ty(ctx.db),
+ hir::PathResolution::Def(hir::ModuleDef::TypeAlias(ty)) => ty.ty(ctx.db),
_ => return,
};
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
index b273a4cb5..b43bdb9ab 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
@@ -16,8 +16,11 @@
//
// image::https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif[]
-use ide_db::SnippetCap;
-use syntax::ast::{self, AstToken};
+use ide_db::{
+ syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders},
+ SnippetCap,
+};
+use syntax::{ast, AstToken};
use crate::{
completions::postfix::build_postfix_snippet_builder, context::CompletionContext, Completions,
@@ -43,250 +46,24 @@ pub(crate) fn add_format_like_completions(
cap: SnippetCap,
receiver_text: &ast::String,
) {
- let input = match string_literal_contents(receiver_text) {
- // It's not a string literal, do not parse input.
- Some(input) => input,
- None => return,
- };
-
let postfix_snippet = match build_postfix_snippet_builder(ctx, cap, dot_receiver) {
Some(it) => it,
None => return,
};
- let mut parser = FormatStrParser::new(input);
- if parser.parse().is_ok() {
+ if let Ok((out, exprs)) = parse_format_exprs(receiver_text.text()) {
+ let exprs = with_placeholders(exprs);
for (label, macro_name) in KINDS {
- let snippet = parser.to_suggestion(macro_name);
+ let snippet = format!(r#"{}({}, {})"#, macro_name, out, exprs.join(", "));
postfix_snippet(label, macro_name, &snippet).add_to(acc);
}
}
}
-/// Checks whether provided item is a string literal.
-fn string_literal_contents(item: &ast::String) -> Option<String> {
- let item = item.text();
- if item.len() >= 2 && item.starts_with('\"') && item.ends_with('\"') {
- return Some(item[1..item.len() - 1].to_owned());
- }
-
- None
-}
-
-/// Parser for a format-like string. It is more allowing in terms of string contents,
-/// as we expect variable placeholders to be filled with expressions.
-#[derive(Debug)]
-pub(crate) struct FormatStrParser {
- input: String,
- output: String,
- extracted_expressions: Vec<String>,
- state: State,
- parsed: bool,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq)]
-enum State {
- NotExpr,
- MaybeExpr,
- Expr,
- MaybeIncorrect,
- FormatOpts,
-}
-
-impl FormatStrParser {
- pub(crate) fn new(input: String) -> Self {
- Self {
- input,
- output: String::new(),
- extracted_expressions: Vec::new(),
- state: State::NotExpr,
- parsed: false,
- }
- }
-
- pub(crate) fn parse(&mut self) -> Result<(), ()> {
- let mut current_expr = String::new();
-
- let mut placeholder_id = 1;
-
- // Count of open braces inside of an expression.
- // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
- // "{MyStruct { val_a: 0, val_b: 1 }}".
- let mut inexpr_open_count = 0;
-
- // We need to escape '\' and '$'. See the comments on `get_receiver_text()` for detail.
- let mut chars = self.input.chars().peekable();
- while let Some(chr) = chars.next() {
- match (self.state, chr) {
- (State::NotExpr, '{') => {
- self.output.push(chr);
- self.state = State::MaybeExpr;
- }
- (State::NotExpr, '}') => {
- self.output.push(chr);
- self.state = State::MaybeIncorrect;
- }
- (State::NotExpr, _) => {
- if matches!(chr, '\\' | '$') {
- self.output.push('\\');
- }
- self.output.push(chr);
- }
- (State::MaybeIncorrect, '}') => {
- // It's okay, we met "}}".
- self.output.push(chr);
- self.state = State::NotExpr;
- }
- (State::MaybeIncorrect, _) => {
- // Error in the string.
- return Err(());
- }
- (State::MaybeExpr, '{') => {
- self.output.push(chr);
- self.state = State::NotExpr;
- }
- (State::MaybeExpr, '}') => {
- // This is an empty sequence '{}'. Replace it with placeholder.
- self.output.push(chr);
- self.extracted_expressions.push(format!("${}", placeholder_id));
- placeholder_id += 1;
- self.state = State::NotExpr;
- }
- (State::MaybeExpr, _) => {
- if matches!(chr, '\\' | '$') {
- current_expr.push('\\');
- }
- current_expr.push(chr);
- self.state = State::Expr;
- }
- (State::Expr, '}') => {
- if inexpr_open_count == 0 {
- self.output.push(chr);
- self.extracted_expressions.push(current_expr.trim().into());
- current_expr = String::new();
- self.state = State::NotExpr;
- } else {
- // We're closing one brace met before inside of the expression.
- current_expr.push(chr);
- inexpr_open_count -= 1;
- }
- }
- (State::Expr, ':') if chars.peek().copied() == Some(':') => {
- // path separator
- current_expr.push_str("::");
- chars.next();
- }
- (State::Expr, ':') => {
- if inexpr_open_count == 0 {
- // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
- self.output.push(chr);
- self.extracted_expressions.push(current_expr.trim().into());
- current_expr = String::new();
- self.state = State::FormatOpts;
- } else {
- // We're inside of braced expression, assume that it's a struct field name/value delimiter.
- current_expr.push(chr);
- }
- }
- (State::Expr, '{') => {
- current_expr.push(chr);
- inexpr_open_count += 1;
- }
- (State::Expr, _) => {
- if matches!(chr, '\\' | '$') {
- current_expr.push('\\');
- }
- current_expr.push(chr);
- }
- (State::FormatOpts, '}') => {
- self.output.push(chr);
- self.state = State::NotExpr;
- }
- (State::FormatOpts, _) => {
- if matches!(chr, '\\' | '$') {
- self.output.push('\\');
- }
- self.output.push(chr);
- }
- }
- }
-
- if self.state != State::NotExpr {
- return Err(());
- }
-
- self.parsed = true;
- Ok(())
- }
-
- pub(crate) fn to_suggestion(&self, macro_name: &str) -> String {
- assert!(self.parsed, "Attempt to get a suggestion from not parsed expression");
-
- let expressions_as_string = self.extracted_expressions.join(", ");
- format!(r#"{}("{}", {})"#, macro_name, self.output, expressions_as_string)
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
- use expect_test::{expect, Expect};
-
- fn check(input: &str, expect: &Expect) {
- let mut parser = FormatStrParser::new((*input).to_owned());
- let outcome_repr = if parser.parse().is_ok() {
- // Parsing should be OK, expected repr is "string; expr_1, expr_2".
- if parser.extracted_expressions.is_empty() {
- parser.output
- } else {
- format!("{}; {}", parser.output, parser.extracted_expressions.join(", "))
- }
- } else {
- // Parsing should fail, expected repr is "-".
- "-".to_owned()
- };
-
- expect.assert_eq(&outcome_repr);
- }
-
- #[test]
- fn format_str_parser() {
- let test_vector = &[
- ("no expressions", expect![["no expressions"]]),
- (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
- ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
- ("{expr:?}", expect![["{:?}; expr"]]),
- ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
- ("{$0}", expect![[r"{}; \$0"]]),
- ("{malformed", expect![["-"]]),
- ("malformed}", expect![["-"]]),
- ("{{correct", expect![["{{correct"]]),
- ("correct}}", expect![["correct}}"]]),
- ("{correct}}}", expect![["{}}}; correct"]]),
- ("{correct}}}}}", expect![["{}}}}}; correct"]]),
- ("{incorrect}}", expect![["-"]]),
- ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
- ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
- (
- "{SomeStruct { val_a: 0, val_b: 1 }}",
- expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
- ),
- ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
- (
- "{SomeStruct { val_a: 0, val_b: 1 }:?}",
- expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
- ),
- ("{ 2 + 2 }", expect![["{}; 2 + 2"]]),
- ("{strsim::jaro_winkle(a)}", expect![["{}; strsim::jaro_winkle(a)"]]),
- ("{foo::bar::baz()}", expect![["{}; foo::bar::baz()"]]),
- ("{foo::bar():?}", expect![["{:?}; foo::bar()"]]),
- ];
-
- for (input, output) in test_vector {
- check(input, output)
- }
- }
#[test]
fn test_into_suggestion() {
@@ -302,10 +79,10 @@ mod tests {
];
for (kind, input, output) in test_vector {
- let mut parser = FormatStrParser::new((*input).to_owned());
- parser.parse().expect("Parsing must succeed");
-
- assert_eq!(&parser.to_suggestion(*kind), output);
+ let (parsed_string, exprs) = parse_format_exprs(input).unwrap();
+ let exprs = with_placeholders(exprs);
+ let snippet = format!(r#"{}("{}", {})"#, kind, parsed_string, exprs.join(", "));
+ assert_eq!(&snippet, output);
}
}
}
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 80d6af281..a0f5e81b4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
@@ -17,6 +17,7 @@ pub struct CompletionConfig {
pub callable: Option<CallableSnippets>,
pub snippet_cap: Option<SnippetCap>,
pub insert_use: InsertUseConfig,
+ pub prefer_no_std: bool,
pub snippets: Vec<Snippet>,
}
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 a5e854b74..9850813a0 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -1,4 +1,4 @@
-//! See `CompletionContext` structure.
+//! See [`CompletionContext`] structure.
mod analysis;
#[cfg(test)]
@@ -23,7 +23,10 @@ use syntax::{
};
use text_edit::Indel;
-use crate::CompletionConfig;
+use crate::{
+ context::analysis::{expand_and_analyze, AnalysisResult},
+ CompletionConfig,
+};
const COMPLETION_MARKER: &str = "intellijRulezz";
@@ -561,15 +564,27 @@ impl<'a> CompletionContext<'a> {
let edit = Indel::insert(offset, COMPLETION_MARKER.to_string());
parse.reparse(&edit).tree()
};
- let fake_ident_token =
- file_with_fake_ident.syntax().token_at_offset(offset).right_biased()?;
+ // always pick the token to the immediate left of the cursor, as that is what we are actually
+ // completing on
let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
- let token = sema.descend_into_macros_single(original_token.clone());
+
+ let AnalysisResult {
+ analysis,
+ expected: (expected_type, expected_name),
+ qualifier_ctx,
+ token,
+ offset,
+ } = expand_and_analyze(
+ &sema,
+ original_file.syntax().clone(),
+ file_with_fake_ident.syntax().clone(),
+ offset,
+ &original_token,
+ )?;
// adjust for macro input, this still fails if there is no token written yet
- let scope_offset = if original_token == token { offset } else { token.text_range().end() };
- let scope = sema.scope_at_offset(&token.parent()?, scope_offset)?;
+ let scope = sema.scope_at_offset(&token.parent()?, offset)?;
let krate = scope.krate();
let module = scope.module();
@@ -583,7 +598,7 @@ impl<'a> CompletionContext<'a> {
let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count();
- let mut ctx = CompletionContext {
+ let ctx = CompletionContext {
sema,
scope,
db,
@@ -593,19 +608,13 @@ impl<'a> CompletionContext<'a> {
token,
krate,
module,
- expected_name: None,
- expected_type: None,
- qualifier_ctx: Default::default(),
+ expected_name,
+ expected_type,
+ qualifier_ctx,
locals,
depth_from_crate_root,
};
- let ident_ctx = ctx.expand_and_analyze(
- original_file.syntax().clone(),
- file_with_fake_ident.syntax().clone(),
- offset,
- fake_ident_token,
- )?;
- Some((ctx, ident_ctx))
+ Some((ctx, analysis))
}
}
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 01dd9a234..04111ec7e 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
@@ -11,1063 +11,1094 @@ use syntax::{
};
use crate::context::{
- AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
- ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
- NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
- PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
- COMPLETION_MARKER,
+ AttrCtx, CompletionAnalysis, DotAccess, DotAccessKind, ExprCtx, ItemListKind, LifetimeContext,
+ LifetimeKind, NameContext, NameKind, NameRefContext, NameRefKind, ParamContext, ParamKind,
+ PathCompletionCtx, PathKind, PatternContext, PatternRefutability, Qualified, QualifierCtx,
+ TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
};
-impl<'a> CompletionContext<'a> {
- /// Expand attributes and macro calls at the current cursor position for both the original file
- /// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
- /// and speculative states stay in sync.
- pub(super) fn expand_and_analyze(
- &mut self,
- mut original_file: SyntaxNode,
- mut speculative_file: SyntaxNode,
- mut offset: TextSize,
- mut fake_ident_token: SyntaxToken,
- ) -> Option<CompletionAnalysis> {
- let _p = profile::span("CompletionContext::expand_and_fill");
- let mut derive_ctx = None;
-
- 'expansion: loop {
- let parent_item =
- |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
- let ancestor_items = iter::successors(
- Option::zip(
- find_node_at_offset::<ast::Item>(&original_file, offset),
- find_node_at_offset::<ast::Item>(&speculative_file, offset),
+struct ExpansionResult {
+ original_file: SyntaxNode,
+ speculative_file: SyntaxNode,
+ offset: TextSize,
+ fake_ident_token: SyntaxToken,
+ derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
+}
+
+pub(super) struct AnalysisResult {
+ pub(super) analysis: CompletionAnalysis,
+ pub(super) expected: (Option<Type>, Option<ast::NameOrNameRef>),
+ pub(super) qualifier_ctx: QualifierCtx,
+ pub(super) token: SyntaxToken,
+ pub(super) offset: TextSize,
+}
+
+pub(super) fn expand_and_analyze(
+ sema: &Semantics<'_, RootDatabase>,
+ original_file: SyntaxNode,
+ speculative_file: SyntaxNode,
+ offset: TextSize,
+ original_token: &SyntaxToken,
+) -> Option<AnalysisResult> {
+ // as we insert after the offset, right biased will *always* pick the identifier no matter
+ // if there is an ident already typed or not
+ let fake_ident_token = speculative_file.token_at_offset(offset).right_biased()?;
+ // the relative offset between the cursor and the *identifier* token we are completing on
+ let relative_offset = offset - fake_ident_token.text_range().start();
+ // 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);
+ // 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()?;
+
+ analyze(sema, expansion, original_token, &token).map(|(analysis, expected, qualifier_ctx)| {
+ AnalysisResult { analysis, expected, qualifier_ctx, token, offset }
+ })
+}
+
+/// Expand attributes and macro calls at the current cursor position for both the original file
+/// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
+/// and speculative states stay in sync.
+fn expand(
+ sema: &Semantics<'_, RootDatabase>,
+ mut original_file: SyntaxNode,
+ mut speculative_file: SyntaxNode,
+ mut offset: TextSize,
+ mut fake_ident_token: SyntaxToken,
+) -> ExpansionResult {
+ let _p = profile::span("CompletionContext::expand");
+ let mut derive_ctx = None;
+
+ 'expansion: loop {
+ let parent_item =
+ |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
+ let ancestor_items = iter::successors(
+ Option::zip(
+ find_node_at_offset::<ast::Item>(&original_file, offset),
+ find_node_at_offset::<ast::Item>(&speculative_file, offset),
+ ),
+ |(a, b)| parent_item(a).zip(parent_item(b)),
+ );
+
+ // first try to expand attributes as these are always the outermost macro calls
+ 'ancestors: for (actual_item, item_with_fake_ident) in ancestor_items {
+ match (
+ sema.expand_attr_macro(&actual_item),
+ sema.speculative_expand_attr_macro(
+ &actual_item,
+ &item_with_fake_ident,
+ fake_ident_token.clone(),
),
- |(a, b)| parent_item(a).zip(parent_item(b)),
- );
-
- // first try to expand attributes as these are always the outermost macro calls
- 'ancestors: for (actual_item, item_with_fake_ident) in ancestor_items {
- match (
- self.sema.expand_attr_macro(&actual_item),
- self.sema.speculative_expand_attr_macro(
- &actual_item,
- &item_with_fake_ident,
- fake_ident_token.clone(),
- ),
- ) {
- // maybe parent items have attributes, so continue walking the ancestors
- (None, None) => continue 'ancestors,
- // 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() {
- // offset outside of bounds from the original expansion,
- // stop here to prevent problems from happening
- break 'expansion;
- }
- original_file = actual_expansion;
- speculative_file = fake_expansion;
- fake_ident_token = fake_mapped_token;
- offset = new_offset;
- continue 'expansion;
+ ) {
+ // maybe parent items have attributes, so continue walking the ancestors
+ (None, None) => continue 'ancestors,
+ // 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() {
+ // offset outside of bounds from the original expansion,
+ // stop here to prevent problems from happening
+ break 'expansion;
}
- // exactly one expansion failed, inconsistent state so stop expanding completely
- _ => break 'expansion,
+ original_file = actual_expansion;
+ speculative_file = fake_expansion;
+ fake_ident_token = fake_mapped_token;
+ offset = new_offset;
+ continue 'expansion;
}
+ // exactly one expansion failed, inconsistent state so stop expanding completely
+ _ => break 'expansion,
}
+ }
- // No attributes have been expanded, so look for macro_call! token trees or derive token trees
- let orig_tt = match find_node_at_offset::<ast::TokenTree>(&original_file, offset) {
- Some(it) => it,
- None => break 'expansion,
- };
- let spec_tt = match find_node_at_offset::<ast::TokenTree>(&speculative_file, offset) {
- Some(it) => it,
- None => break 'expansion,
- };
+ // No attributes have been expanded, so look for macro_call! token trees or derive token trees
+ let orig_tt = match find_node_at_offset::<ast::TokenTree>(&original_file, offset) {
+ Some(it) => it,
+ None => break 'expansion,
+ };
+ let spec_tt = match find_node_at_offset::<ast::TokenTree>(&speculative_file, offset) {
+ Some(it) => it,
+ None => break 'expansion,
+ };
- // Expand pseudo-derive expansion
- if let (Some(orig_attr), Some(spec_attr)) = (
- orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
- spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
+ // Expand pseudo-derive expansion
+ if let (Some(orig_attr), Some(spec_attr)) = (
+ orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
+ spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
+ ) {
+ if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = (
+ sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
+ sema.speculative_expand_derive_as_pseudo_attr_macro(
+ &orig_attr,
+ &spec_attr,
+ fake_ident_token.clone(),
+ ),
) {
- if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = (
- self.sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
- self.sema.speculative_expand_derive_as_pseudo_attr_macro(
- &orig_attr,
- &spec_attr,
- fake_ident_token.clone(),
- ),
- ) {
- derive_ctx = Some((
- actual_expansion,
- fake_expansion,
- fake_mapped_token.text_range().start(),
- orig_attr,
- ));
- }
- // at this point we won't have any more successful expansions, so stop
+ derive_ctx = Some((
+ actual_expansion,
+ fake_expansion,
+ fake_mapped_token.text_range().start(),
+ orig_attr,
+ ));
+ }
+ // at this point we won't have any more successful expansions, so stop
+ break 'expansion;
+ }
+
+ // Expand fn-like macro calls
+ if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = (
+ orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
+ spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
+ ) {
+ let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text());
+ let mac_call_path1 =
+ macro_call_with_fake_ident.path().as_ref().map(|s| s.syntax().text());
+
+ // inconsistent state, stop expanding
+ if mac_call_path0 != mac_call_path1 {
break 'expansion;
}
+ let speculative_args = match macro_call_with_fake_ident.token_tree() {
+ Some(tt) => tt,
+ None => break 'expansion,
+ };
- // Expand fn-like macro calls
- if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = (
- orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
- spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
+ match (
+ sema.expand(&actual_macro_call),
+ sema.speculative_expand(
+ &actual_macro_call,
+ &speculative_args,
+ fake_ident_token.clone(),
+ ),
) {
- let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text());
- let mac_call_path1 =
- macro_call_with_fake_ident.path().as_ref().map(|s| s.syntax().text());
-
- // inconsistent state, stop expanding
- if mac_call_path0 != mac_call_path1 {
- break 'expansion;
- }
- let speculative_args = match macro_call_with_fake_ident.token_tree() {
- Some(tt) => tt,
- None => break 'expansion,
- };
-
- match (
- self.sema.expand(&actual_macro_call),
- self.sema.speculative_expand(
- &actual_macro_call,
- &speculative_args,
- fake_ident_token.clone(),
- ),
- ) {
- // 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() {
- // offset outside of bounds from the original expansion,
- // stop here to prevent problems from happening
- break 'expansion;
- }
- original_file = actual_expansion;
- speculative_file = fake_expansion;
- fake_ident_token = fake_mapped_token;
- offset = new_offset;
- continue 'expansion;
+ // 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() {
+ // offset outside of bounds from the original expansion,
+ // stop here to prevent problems from happening
+ break 'expansion;
}
- // at least on expansion failed, we won't have anything to expand from this point
- // onwards so break out
- _ => break 'expansion,
+ original_file = actual_expansion;
+ speculative_file = fake_expansion;
+ fake_ident_token = fake_mapped_token;
+ offset = new_offset;
+ continue 'expansion;
}
+ // at least on expansion failed, we won't have anything to expand from this point
+ // onwards so break out
+ _ => break 'expansion,
}
-
- // none of our states have changed so stop the loop
- break 'expansion;
}
- self.analyze(&original_file, speculative_file, offset, derive_ctx)
+ // none of our states have changed so stop the loop
+ break 'expansion;
}
+ ExpansionResult { original_file, speculative_file, offset, fake_ident_token, derive_ctx }
+}
- /// Calculate the expected type and name of the cursor position.
- fn expected_type_and_name(
- &self,
- name_like: &ast::NameLike,
- ) -> (Option<Type>, Option<NameOrNameRef>) {
- let mut node = match self.token.parent() {
- Some(it) => it,
- None => return (None, None),
- };
+/// Fill the completion context, this is what does semantic reasoning about the surrounding context
+/// of the completion location.
+fn analyze(
+ sema: &Semantics<'_, RootDatabase>,
+ expansion_result: ExpansionResult,
+ original_token: &SyntaxToken,
+ self_token: &SyntaxToken,
+) -> Option<(CompletionAnalysis, (Option<Type>, Option<ast::NameOrNameRef>), QualifierCtx)> {
+ 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;
+ }
- let strip_refs = |mut ty: Type| match name_like {
- ast::NameLike::NameRef(n) => {
- let p = match n.syntax().parent() {
- Some(it) => it,
- None => return ty,
- };
- let top_syn = match_ast! {
- match p {
- ast::FieldExpr(e) => e
- .syntax()
- .ancestors()
- .map_while(ast::FieldExpr::cast)
- .last()
- .map(|it| it.syntax().clone()),
- 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()),
- _ => None
- }
+ // Overwrite the path kind for derives
+ if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
+ if let Some(ast::NameLike::NameRef(name_ref)) =
+ find_node_at_offset(&file_with_fake_ident, offset)
+ {
+ let parent = name_ref.syntax().parent()?;
+ let (mut nameref_ctx, _) = classify_name_ref(&sema, &original_file, name_ref, parent)?;
+ if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
+ path_ctx.kind = PathKind::Derive {
+ existing_derives: sema
+ .resolve_derive_macro(&origin_attr)
+ .into_iter()
+ .flatten()
+ .flatten()
+ .collect(),
};
- let top_syn = match top_syn {
- Some(it) => it,
- None => return ty,
- };
- for _ in top_syn.ancestors().skip(1).map_while(ast::RefExpr::cast) {
- cov_mark::hit!(expected_type_fn_param_ref);
- ty = ty.strip_reference();
- }
- ty
}
- _ => ty,
- };
+ return Some((
+ CompletionAnalysis::NameRef(nameref_ctx),
+ (None, None),
+ QualifierCtx::default(),
+ ));
+ }
+ return None;
+ }
- loop {
- break match_ast! {
- match node {
- ast::LetStmt(it) => {
- cov_mark::hit!(expected_type_let_with_leading_char);
- cov_mark::hit!(expected_type_let_without_leading_char);
- let ty = it.pat()
- .and_then(|pat| self.sema.type_of_pat(&pat))
- .or_else(|| it.initializer().and_then(|it| self.sema.type_of_expr(&it)))
- .map(TypeInfo::original);
- let name = match it.pat() {
- Some(ast::Pat::IdentPat(ident)) => ident.name().map(NameOrNameRef::Name),
- Some(_) | None => None,
- };
-
- (ty, name)
- },
- ast::LetExpr(it) => {
- cov_mark::hit!(expected_type_if_let_without_leading_char);
- let ty = it.pat()
- .and_then(|pat| self.sema.type_of_pat(&pat))
- .or_else(|| it.expr().and_then(|it| self.sema.type_of_expr(&it)))
- .map(TypeInfo::original);
- (ty, None)
- },
- ast::ArgList(_) => {
- cov_mark::hit!(expected_type_fn_param);
- ActiveParameter::at_token(
- &self.sema,
- self.token.clone(),
- ).map(|ap| {
- let name = ap.ident().map(NameOrNameRef::Name);
-
- let ty = strip_refs(ap.ty);
- (Some(ty), name)
- })
- .unwrap_or((None, None))
- },
- ast::RecordExprFieldList(it) => {
- // wouldn't try {} be nice...
- (|| {
- if self.token.kind() == T![..]
- || self.token.prev_token().map(|t| t.kind()) == Some(T![..])
- {
- cov_mark::hit!(expected_type_struct_func_update);
- let record_expr = it.syntax().parent().and_then(ast::RecordExpr::cast)?;
- let ty = self.sema.type_of_expr(&record_expr.into())?;
- Some((
- Some(ty.original),
- None
- ))
- } else {
- cov_mark::hit!(expected_type_struct_field_without_leading_char);
- let expr_field = self.token.prev_sibling_or_token()?
- .into_node()
- .and_then(ast::RecordExprField::cast)?;
- let (_, _, ty) = self.sema.resolve_record_field(&expr_field)?;
- Some((
- Some(ty),
- expr_field.field_name().map(NameOrNameRef::NameRef),
- ))
- }
- })().unwrap_or((None, None))
- },
- ast::RecordExprField(it) => {
- if let Some(expr) = it.expr() {
- cov_mark::hit!(expected_type_struct_field_with_leading_char);
- (
- self.sema.type_of_expr(&expr).map(TypeInfo::original),
- it.field_name().map(NameOrNameRef::NameRef),
- )
- } else {
- cov_mark::hit!(expected_type_struct_field_followed_by_comma);
- let ty = self.sema.resolve_record_field(&it)
- .map(|(_, _, ty)| ty);
- (
- ty,
- it.field_name().map(NameOrNameRef::NameRef),
- )
- }
- },
- // match foo { $0 }
- // match foo { ..., pat => $0 }
- ast::MatchExpr(it) => {
- let on_arrow = previous_non_trivia_token(self.token.clone()).map_or(false, |it| T![=>] == it.kind());
-
- let ty = if on_arrow {
- // match foo { ..., pat => $0 }
- cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
- cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
- self.sema.type_of_expr(&it.into())
- } else {
- // match foo { $0 }
- cov_mark::hit!(expected_type_match_arm_without_leading_char);
- it.expr().and_then(|e| self.sema.type_of_expr(&e))
- }.map(TypeInfo::original);
- (ty, None)
- },
- ast::IfExpr(it) => {
- let ty = it.condition()
- .and_then(|e| self.sema.type_of_expr(&e))
- .map(TypeInfo::original);
- (ty, None)
- },
- ast::IdentPat(it) => {
- cov_mark::hit!(expected_type_if_let_with_leading_char);
- cov_mark::hit!(expected_type_match_arm_with_leading_char);
- let ty = self.sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
- (ty, None)
- },
- ast::Fn(it) => {
- cov_mark::hit!(expected_type_fn_ret_with_leading_char);
- cov_mark::hit!(expected_type_fn_ret_without_leading_char);
- let def = self.sema.to_def(&it);
- (def.map(|def| def.ret_type(self.db)), None)
- },
- ast::ClosureExpr(it) => {
- let ty = self.sema.type_of_expr(&it.into());
- ty.and_then(|ty| ty.original.as_callable(self.db))
- .map(|c| (Some(c.return_type()), None))
- .unwrap_or((None, None))
- },
- ast::ParamList(_) => (None, None),
- ast::Stmt(_) => (None, None),
- ast::Item(_) => (None, None),
- _ => {
- match node.parent() {
- Some(n) => {
- node = n;
- continue;
- },
- None => (None, 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()),
+ }
+ } 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()));
}
- }
-
- /// Fill the completion context, this is what does semantic reasoning about the surrounding context
- /// of the completion location.
- fn analyze(
- &mut self,
- original_file: &SyntaxNode,
- file_with_fake_ident: SyntaxNode,
- offset: TextSize,
- derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
- ) -> Option<CompletionAnalysis> {
- let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased()?;
- 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;
+ };
+ let expected = expected_type_and_name(sema, &self_token, &name_like);
+ let mut qual_ctx = QualifierCtx::default();
+ let analysis = match name_like {
+ ast::NameLike::Lifetime(lifetime) => {
+ CompletionAnalysis::Lifetime(classify_lifetime(sema, &original_file, lifetime)?)
+ }
+ ast::NameLike::NameRef(name_ref) => {
+ let parent = name_ref.syntax().parent()?;
+ let (nameref_ctx, qualifier_ctx) =
+ classify_name_ref(sema, &original_file, name_ref, parent.clone())?;
+ qual_ctx = qualifier_ctx;
+ CompletionAnalysis::NameRef(nameref_ctx)
+ }
+ ast::NameLike::Name(name) => {
+ let name_ctx = classify_name(sema, &original_file, name)?;
+ CompletionAnalysis::Name(name_ctx)
}
+ };
+ Some((analysis, expected, qual_ctx))
+}
- // Overwrite the path kind for derives
- if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
- if let Some(ast::NameLike::NameRef(name_ref)) =
- find_node_at_offset(&file_with_fake_ident, offset)
- {
- let parent = name_ref.syntax().parent()?;
- let (mut nameref_ctx, _) =
- Self::classify_name_ref(&self.sema, &original_file, name_ref, parent)?;
- if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
- path_ctx.kind = PathKind::Derive {
- existing_derives: self
- .sema
- .resolve_derive_macro(&origin_attr)
- .into_iter()
- .flatten()
- .flatten()
- .collect(),
- };
+/// Calculate the expected type and name of the cursor position.
+fn expected_type_and_name(
+ sema: &Semantics<'_, RootDatabase>,
+ token: &SyntaxToken,
+ name_like: &ast::NameLike,
+) -> (Option<Type>, Option<NameOrNameRef>) {
+ let mut node = match token.parent() {
+ Some(it) => it,
+ None => return (None, None),
+ };
+
+ let strip_refs = |mut ty: Type| match name_like {
+ ast::NameLike::NameRef(n) => {
+ let p = match n.syntax().parent() {
+ Some(it) => it,
+ None => return ty,
+ };
+ let top_syn = match_ast! {
+ match p {
+ ast::FieldExpr(e) => e
+ .syntax()
+ .ancestors()
+ .map_while(ast::FieldExpr::cast)
+ .last()
+ .map(|it| it.syntax().clone()),
+ 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()),
+ _ => None
}
- return Some(CompletionAnalysis::NameRef(nameref_ctx));
+ };
+ let top_syn = match top_syn {
+ Some(it) => it,
+ None => return ty,
+ };
+ for _ in top_syn.ancestors().skip(1).map_while(ast::RefExpr::cast) {
+ cov_mark::hit!(expected_type_fn_param_ref);
+ ty = ty.strip_reference();
}
- return None;
+ ty
}
+ _ => ty,
+ };
- let name_like = match find_node_at_offset(&file_with_fake_ident, offset) {
- Some(it) => it,
- None => {
- let analysis =
- if let Some(original) = ast::String::cast(self.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)
+ loop {
+ break match_ast! {
+ match node {
+ ast::LetStmt(it) => {
+ cov_mark::hit!(expected_type_let_with_leading_char);
+ cov_mark::hit!(expected_type_let_without_leading_char);
+ let ty = it.pat()
+ .and_then(|pat| sema.type_of_pat(&pat))
+ .or_else(|| it.initializer().and_then(|it| sema.type_of_expr(&it)))
+ .map(TypeInfo::original);
+ let name = match it.pat() {
+ Some(ast::Pat::IdentPat(ident)) => ident.name().map(NameOrNameRef::Name),
+ Some(_) | None => None,
+ };
+
+ (ty, name)
+ },
+ ast::LetExpr(it) => {
+ cov_mark::hit!(expected_type_if_let_without_leading_char);
+ let ty = it.pat()
+ .and_then(|pat| sema.type_of_pat(&pat))
+ .or_else(|| it.expr().and_then(|it| sema.type_of_expr(&it)))
+ .map(TypeInfo::original);
+ (ty, None)
+ },
+ ast::ArgList(_) => {
+ cov_mark::hit!(expected_type_fn_param);
+ ActiveParameter::at_token(
+ &sema,
+ token.clone(),
+ ).map(|ap| {
+ let name = ap.ident().map(NameOrNameRef::Name);
+
+ let ty = strip_refs(ap.ty);
+ (Some(ty), name)
+ })
+ .unwrap_or((None, None))
+ },
+ ast::RecordExprFieldList(it) => {
+ // wouldn't try {} be nice...
+ (|| {
+ if token.kind() == T![..]
+ ||token.prev_token().map(|t| t.kind()) == Some(T![..])
{
- 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,
- }
+ cov_mark::hit!(expected_type_struct_func_update);
+ let record_expr = it.syntax().parent().and_then(ast::RecordExpr::cast)?;
+ let ty = sema.type_of_expr(&record_expr.into())?;
+ Some((
+ Some(ty.original),
+ None
+ ))
} else {
- return None;
+ cov_mark::hit!(expected_type_struct_field_without_leading_char);
+ let expr_field = token.prev_sibling_or_token()?
+ .into_node()
+ .and_then(ast::RecordExprField::cast)?;
+ let (_, _, ty) = sema.resolve_record_field(&expr_field)?;
+ Some((
+ Some(ty),
+ expr_field.field_name().map(NameOrNameRef::NameRef),
+ ))
}
- };
- return Some(analysis);
+ })().unwrap_or((None, None))
+ },
+ ast::RecordExprField(it) => {
+ if let Some(expr) = it.expr() {
+ cov_mark::hit!(expected_type_struct_field_with_leading_char);
+ (
+ sema.type_of_expr(&expr).map(TypeInfo::original),
+ it.field_name().map(NameOrNameRef::NameRef),
+ )
+ } else {
+ cov_mark::hit!(expected_type_struct_field_followed_by_comma);
+ let ty = sema.resolve_record_field(&it)
+ .map(|(_, _, ty)| ty);
+ (
+ ty,
+ it.field_name().map(NameOrNameRef::NameRef),
+ )
+ }
+ },
+ // match foo { $0 }
+ // match foo { ..., pat => $0 }
+ ast::MatchExpr(it) => {
+ let on_arrow = previous_non_trivia_token(token.clone()).map_or(false, |it| T![=>] == it.kind());
+
+ let ty = if on_arrow {
+ // match foo { ..., pat => $0 }
+ cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
+ cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
+ sema.type_of_expr(&it.into())
+ } else {
+ // match foo { $0 }
+ cov_mark::hit!(expected_type_match_arm_without_leading_char);
+ it.expr().and_then(|e| sema.type_of_expr(&e))
+ }.map(TypeInfo::original);
+ (ty, None)
+ },
+ ast::IfExpr(it) => {
+ let ty = it.condition()
+ .and_then(|e| sema.type_of_expr(&e))
+ .map(TypeInfo::original);
+ (ty, None)
+ },
+ ast::IdentPat(it) => {
+ cov_mark::hit!(expected_type_if_let_with_leading_char);
+ cov_mark::hit!(expected_type_match_arm_with_leading_char);
+ let ty = sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
+ (ty, None)
+ },
+ ast::Fn(it) => {
+ cov_mark::hit!(expected_type_fn_ret_with_leading_char);
+ cov_mark::hit!(expected_type_fn_ret_without_leading_char);
+ let def = sema.to_def(&it);
+ (def.map(|def| def.ret_type(sema.db)), None)
+ },
+ ast::ClosureExpr(it) => {
+ let ty = sema.type_of_expr(&it.into());
+ ty.and_then(|ty| ty.original.as_callable(sema.db))
+ .map(|c| (Some(c.return_type()), None))
+ .unwrap_or((None, None))
+ },
+ ast::ParamList(_) => (None, None),
+ ast::Stmt(_) => (None, None),
+ ast::Item(_) => (None, None),
+ _ => {
+ match node.parent() {
+ Some(n) => {
+ node = n;
+ continue;
+ },
+ None => (None, None),
+ }
+ },
}
};
- (self.expected_type, self.expected_name) = self.expected_type_and_name(&name_like);
- let analysis = match name_like {
- ast::NameLike::Lifetime(lifetime) => CompletionAnalysis::Lifetime(
- Self::classify_lifetime(&self.sema, original_file, lifetime)?,
- ),
- ast::NameLike::NameRef(name_ref) => {
- let parent = name_ref.syntax().parent()?;
- let (nameref_ctx, qualifier_ctx) =
- Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone())?;
+ }
+}
- self.qualifier_ctx = qualifier_ctx;
- CompletionAnalysis::NameRef(nameref_ctx)
- }
- ast::NameLike::Name(name) => {
- let name_ctx = Self::classify_name(&self.sema, original_file, name)?;
- CompletionAnalysis::Name(name_ctx)
- }
- };
- Some(analysis)
+fn classify_lifetime(
+ _sema: &Semantics<'_, RootDatabase>,
+ original_file: &SyntaxNode,
+ lifetime: ast::Lifetime,
+) -> Option<LifetimeContext> {
+ let parent = lifetime.syntax().parent()?;
+ if parent.kind() == SyntaxKind::ERROR {
+ return None;
}
- fn classify_lifetime(
- _sema: &Semantics<'_, RootDatabase>,
- original_file: &SyntaxNode,
- lifetime: ast::Lifetime,
- ) -> Option<LifetimeContext> {
- let parent = lifetime.syntax().parent()?;
- if parent.kind() == SyntaxKind::ERROR {
- return None;
+ let kind = match_ast! {
+ match parent {
+ ast::LifetimeParam(param) => LifetimeKind::LifetimeParam {
+ is_decl: param.lifetime().as_ref() == Some(&lifetime),
+ param
+ },
+ ast::BreakExpr(_) => LifetimeKind::LabelRef,
+ ast::ContinueExpr(_) => LifetimeKind::LabelRef,
+ ast::Label(_) => LifetimeKind::LabelDef,
+ _ => LifetimeKind::Lifetime,
}
+ };
+ let lifetime = find_node_at_offset(&original_file, lifetime.syntax().text_range().start());
- let kind = match_ast! {
- match parent {
- ast::LifetimeParam(param) => LifetimeKind::LifetimeParam {
- is_decl: param.lifetime().as_ref() == Some(&lifetime),
- param
- },
- ast::BreakExpr(_) => LifetimeKind::LabelRef,
- ast::ContinueExpr(_) => LifetimeKind::LabelRef,
- ast::Label(_) => LifetimeKind::LabelDef,
- _ => LifetimeKind::Lifetime,
- }
- };
- let lifetime = find_node_at_offset(&original_file, lifetime.syntax().text_range().start());
+ Some(LifetimeContext { lifetime, kind })
+}
- Some(LifetimeContext { lifetime, kind })
- }
+fn classify_name(
+ sema: &Semantics<'_, RootDatabase>,
+ original_file: &SyntaxNode,
+ name: ast::Name,
+) -> Option<NameContext> {
+ let parent = name.syntax().parent()?;
+ let kind = match_ast! {
+ match parent {
+ ast::Const(_) => NameKind::Const,
+ ast::ConstParam(_) => NameKind::ConstParam,
+ ast::Enum(_) => NameKind::Enum,
+ ast::Fn(_) => NameKind::Function,
+ ast::IdentPat(bind_pat) => {
+ let mut pat_ctx = pattern_context_for(sema, original_file, bind_pat.into());
+ if let Some(record_field) = ast::RecordPatField::for_field_name(&name) {
+ pat_ctx.record_pat = find_node_in_file_compensated(sema, original_file, &record_field.parent_record_pat());
+ }
- fn classify_name(
- sema: &Semantics<'_, RootDatabase>,
- original_file: &SyntaxNode,
- name: ast::Name,
- ) -> Option<NameContext> {
- let parent = name.syntax().parent()?;
- let kind = match_ast! {
- match parent {
- ast::Const(_) => NameKind::Const,
- ast::ConstParam(_) => NameKind::ConstParam,
- ast::Enum(_) => NameKind::Enum,
- ast::Fn(_) => NameKind::Function,
- ast::IdentPat(bind_pat) => {
- let mut pat_ctx = pattern_context_for(sema, original_file, bind_pat.into());
- if let Some(record_field) = ast::RecordPatField::for_field_name(&name) {
- pat_ctx.record_pat = find_node_in_file_compensated(sema, original_file, &record_field.parent_record_pat());
- }
+ NameKind::IdentPat(pat_ctx)
+ },
+ ast::MacroDef(_) => NameKind::MacroDef,
+ ast::MacroRules(_) => NameKind::MacroRules,
+ ast::Module(module) => NameKind::Module(module),
+ ast::RecordField(_) => NameKind::RecordField,
+ ast::Rename(_) => NameKind::Rename,
+ ast::SelfParam(_) => NameKind::SelfParam,
+ ast::Static(_) => NameKind::Static,
+ ast::Struct(_) => NameKind::Struct,
+ ast::Trait(_) => NameKind::Trait,
+ ast::TypeAlias(_) => NameKind::TypeAlias,
+ ast::TypeParam(_) => NameKind::TypeParam,
+ ast::Union(_) => NameKind::Union,
+ ast::Variant(_) => NameKind::Variant,
+ _ => return None,
+ }
+ };
+ let name = find_node_at_offset(&original_file, name.syntax().text_range().start());
+ Some(NameContext { name, kind })
+}
- NameKind::IdentPat(pat_ctx)
- },
- ast::MacroDef(_) => NameKind::MacroDef,
- ast::MacroRules(_) => NameKind::MacroRules,
- ast::Module(module) => NameKind::Module(module),
- ast::RecordField(_) => NameKind::RecordField,
- ast::Rename(_) => NameKind::Rename,
- ast::SelfParam(_) => NameKind::SelfParam,
- ast::Static(_) => NameKind::Static,
- ast::Struct(_) => NameKind::Struct,
- ast::Trait(_) => NameKind::Trait,
- ast::TypeAlias(_) => NameKind::TypeAlias,
- ast::TypeParam(_) => NameKind::TypeParam,
- ast::Union(_) => NameKind::Union,
- ast::Variant(_) => NameKind::Variant,
- _ => return None,
- }
- };
- let name = find_node_at_offset(&original_file, name.syntax().text_range().start());
- Some(NameContext { name, kind })
+fn classify_name_ref(
+ sema: &Semantics<'_, RootDatabase>,
+ original_file: &SyntaxNode,
+ name_ref: ast::NameRef,
+ parent: SyntaxNode,
+) -> Option<(NameRefContext, QualifierCtx)> {
+ let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
+
+ let make_res = |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
+
+ if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
+ let dot_prefix = previous_non_trivia_token(name_ref.syntax().clone())
+ .map_or(false, |it| T![.] == it.kind());
+
+ return find_node_in_file_compensated(
+ sema,
+ original_file,
+ &record_field.parent_record_lit(),
+ )
+ .map(|expr| NameRefKind::RecordExpr { expr, dot_prefix })
+ .map(make_res);
}
-
- fn classify_name_ref(
- sema: &Semantics<'_, RootDatabase>,
- original_file: &SyntaxNode,
- name_ref: ast::NameRef,
- parent: SyntaxNode,
- ) -> Option<(NameRefContext, QualifierCtx)> {
- let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
-
- let make_res =
- |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
-
- if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
- let dot_prefix = previous_non_trivia_token(name_ref.syntax().clone())
- .map_or(false, |it| T![.] == it.kind());
-
- return find_node_in_file_compensated(
+ if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
+ let kind = NameRefKind::Pattern(PatternContext {
+ param_ctx: None,
+ has_type_ascription: false,
+ ref_token: None,
+ mut_token: None,
+ record_pat: find_node_in_file_compensated(
sema,
original_file,
- &record_field.parent_record_lit(),
+ &record_field.parent_record_pat(),
+ ),
+ ..pattern_context_for(
+ sema,
+ original_file,
+ record_field.parent_record_pat().clone().into(),
)
- .map(|expr| NameRefKind::RecordExpr { expr, dot_prefix })
- .map(make_res);
+ });
+ return Some(make_res(kind));
+ }
+
+ let segment = match_ast! {
+ match parent {
+ ast::PathSegment(segment) => segment,
+ ast::FieldExpr(field) => {
+ let receiver = find_opt_node_in_file(original_file, field.expr());
+ let receiver_is_ambiguous_float_literal = match &receiver {
+ Some(ast::Expr::Literal(l)) => matches! {
+ l.kind(),
+ ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().map_or(false, |it| it.text().ends_with('.'))
+ },
+ _ => false,
+ };
+ 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 },
+ receiver
+ });
+ return Some(make_res(kind));
+ },
+ ast::MethodCallExpr(method) => {
+ let receiver = find_opt_node_in_file(original_file, method.receiver());
+ let kind = NameRefKind::DotAccess(DotAccess {
+ receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
+ kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
+ receiver
+ });
+ return Some(make_res(kind));
+ },
+ _ => return None,
}
- if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
- let kind = NameRefKind::Pattern(PatternContext {
- param_ctx: None,
- has_type_ascription: false,
- ref_token: None,
- mut_token: None,
- record_pat: find_node_in_file_compensated(
- sema,
- original_file,
- &record_field.parent_record_pat(),
- ),
- ..pattern_context_for(
- sema,
- original_file,
- record_field.parent_record_pat().clone().into(),
- )
- });
- return Some(make_res(kind));
+ };
+
+ let path = segment.parent_path();
+ let original_path = find_node_in_file_compensated(sema, original_file, &path);
+
+ let mut path_ctx = PathCompletionCtx {
+ has_call_parens: false,
+ has_macro_bang: false,
+ qualified: Qualified::No,
+ parent: None,
+ path: path.clone(),
+ original_path,
+ kind: PathKind::Item { kind: ItemListKind::SourceFile },
+ has_type_args: false,
+ use_tree_parent: false,
+ };
+
+ let is_in_block = |it: &SyntaxNode| {
+ it.parent()
+ .map(|node| {
+ ast::ExprStmt::can_cast(node.kind()) || ast::StmtList::can_cast(node.kind())
+ })
+ .unwrap_or(false)
+ };
+ let func_update_record = |syn: &SyntaxNode| {
+ if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) {
+ find_node_in_file_compensated(sema, original_file, &record_expr)
+ } else {
+ None
+ }
+ };
+ let after_if_expr = |node: SyntaxNode| {
+ let prev_expr = (|| {
+ let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?;
+ ast::ExprStmt::cast(prev_sibling)?.expr()
+ })();
+ matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
+ };
+
+ // We do not want to generate path completions when we are sandwiched between an item decl signature and its body.
+ // ex. trait Foo $0 {}
+ // in these cases parser recovery usually kicks in for our inserted identifier, causing it
+ // to either be parsed as an ExprStmt or a MacroCall, depending on whether it is in a block
+ // expression or an item list.
+ // The following code checks if the body is missing, if it is we either cut off the body
+ // from the item or it was missing in the first place
+ let inbetween_body_and_decl_check = |node: SyntaxNode| {
+ if let Some(NodeOrToken::Node(n)) =
+ syntax::algo::non_trivia_sibling(node.into(), syntax::Direction::Prev)
+ {
+ if let Some(item) = ast::Item::cast(n) {
+ let is_inbetween = match &item {
+ ast::Item::Const(it) => it.body().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::Impl(it) => it.assoc_item_list().is_none(),
+ ast::Item::Module(it) => it.item_list().is_none(),
+ ast::Item::Static(it) => it.body().is_none(),
+ ast::Item::Struct(it) => it.field_list().is_none(),
+ ast::Item::Trait(it) => it.assoc_item_list().is_none(),
+ ast::Item::TypeAlias(it) => it.ty().is_none(),
+ ast::Item::Union(it) => it.record_field_list().is_none(),
+ _ => false,
+ };
+ if is_inbetween {
+ return Some(item);
+ }
+ }
}
+ None
+ };
- let segment = match_ast! {
+ let type_location = |node: &SyntaxNode| {
+ let parent = node.parent()?;
+ let res = match_ast! {
match parent {
- ast::PathSegment(segment) => segment,
- ast::FieldExpr(field) => {
- let receiver = find_opt_node_in_file(original_file, field.expr());
- let receiver_is_ambiguous_float_literal = match &receiver {
- Some(ast::Expr::Literal(l)) => matches! {
- l.kind(),
- ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().map_or(false, |it| it.text().ends_with('.'))
- },
- _ => false,
+ ast::Const(it) => {
+ let name = find_opt_node_in_file(original_file, it.name())?;
+ let original = ast::Const::cast(name.syntax().parent()?)?;
+ TypeLocation::TypeAscription(TypeAscriptionTarget::Const(original.body()))
+ },
+ ast::RetType(it) => {
+ if it.thin_arrow_token().is_none() {
+ return None;
+ }
+ let parent = match ast::Fn::cast(parent.parent()?) {
+ Some(x) => x.param_list(),
+ None => ast::ClosureExpr::cast(parent.parent()?)?.param_list(),
};
- 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 },
- receiver
- });
- return Some(make_res(kind));
+
+ let parent = find_opt_node_in_file(original_file, parent)?.syntax().parent()?;
+ TypeLocation::TypeAscription(TypeAscriptionTarget::RetType(match_ast! {
+ match parent {
+ ast::ClosureExpr(it) => {
+ it.body()
+ },
+ ast::Fn(it) => {
+ it.body().map(ast::Expr::BlockExpr)
+ },
+ _ => return None,
+ }
+ }))
},
- ast::MethodCallExpr(method) => {
- let receiver = find_opt_node_in_file(original_file, method.receiver());
- let kind = NameRefKind::DotAccess(DotAccess {
- receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
- kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
- receiver
- });
- return Some(make_res(kind));
+ ast::Param(it) => {
+ if it.colon_token().is_none() {
+ return None;
+ }
+ TypeLocation::TypeAscription(TypeAscriptionTarget::FnParam(find_opt_node_in_file(original_file, it.pat())))
},
+ ast::LetStmt(it) => {
+ if it.colon_token().is_none() {
+ return None;
+ }
+ TypeLocation::TypeAscription(TypeAscriptionTarget::Let(find_opt_node_in_file(original_file, it.pat())))
+ },
+ ast::Impl(it) => {
+ match it.trait_() {
+ Some(t) if t.syntax() == node => TypeLocation::ImplTrait,
+ _ => match it.self_ty() {
+ Some(t) if t.syntax() == node => TypeLocation::ImplTarget,
+ _ => return None,
+ },
+ }
+ },
+ ast::TypeBound(_) => TypeLocation::TypeBound,
+ // is this case needed?
+ ast::TypeBoundList(_) => TypeLocation::TypeBound,
+ ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))),
+ // is this case needed?
+ ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))),
+ ast::TupleField(_) => TypeLocation::TupleField,
_ => return None,
}
};
+ Some(res)
+ };
- let path = segment.parent_path();
- let original_path = find_node_in_file_compensated(sema, original_file, &path);
-
- let mut path_ctx = PathCompletionCtx {
- has_call_parens: false,
- has_macro_bang: false,
- qualified: Qualified::No,
- parent: None,
- path: path.clone(),
- original_path,
- kind: PathKind::Item { kind: ItemListKind::SourceFile },
- has_type_args: false,
- use_tree_parent: false,
- };
-
- let is_in_block = |it: &SyntaxNode| {
- it.parent()
- .map(|node| {
- ast::ExprStmt::can_cast(node.kind()) || ast::StmtList::can_cast(node.kind())
- })
- .unwrap_or(false)
- };
- let func_update_record = |syn: &SyntaxNode| {
- if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) {
- find_node_in_file_compensated(sema, original_file, &record_expr)
+ let is_in_condition = |it: &ast::Expr| {
+ (|| {
+ let parent = it.syntax().parent()?;
+ if let Some(expr) = ast::WhileExpr::cast(parent.clone()) {
+ Some(expr.condition()? == *it)
+ } else if let Some(expr) = ast::IfExpr::cast(parent) {
+ Some(expr.condition()? == *it)
} else {
None
}
- };
- let after_if_expr = |node: SyntaxNode| {
- let prev_expr = (|| {
- let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?;
- ast::ExprStmt::cast(prev_sibling)?.expr()
- })();
- matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
- };
+ })()
+ .unwrap_or(false)
+ };
- // We do not want to generate path completions when we are sandwiched between an item decl signature and its body.
- // ex. trait Foo $0 {}
- // in these cases parser recovery usually kicks in for our inserted identifier, causing it
- // to either be parsed as an ExprStmt or a MacroCall, depending on whether it is in a block
- // expression or an item list.
- // The following code checks if the body is missing, if it is we either cut off the body
- // from the item or it was missing in the first place
- let inbetween_body_and_decl_check = |node: SyntaxNode| {
- if let Some(NodeOrToken::Node(n)) =
- syntax::algo::non_trivia_sibling(node.into(), syntax::Direction::Prev)
- {
- if let Some(item) = ast::Item::cast(n) {
- let is_inbetween = match &item {
- ast::Item::Const(it) => it.body().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::Impl(it) => it.assoc_item_list().is_none(),
- ast::Item::Module(it) => it.item_list().is_none(),
- ast::Item::Static(it) => it.body().is_none(),
- ast::Item::Struct(it) => it.field_list().is_none(),
- ast::Item::Trait(it) => it.assoc_item_list().is_none(),
- ast::Item::TypeAlias(it) => it.ty().is_none(),
- ast::Item::Union(it) => it.record_field_list().is_none(),
- _ => false,
- };
- if is_inbetween {
- return Some(item);
+ let make_path_kind_expr = |expr: ast::Expr| {
+ let it = expr.syntax();
+ let in_block_expr = is_in_block(it);
+ let in_loop_body = is_in_loop_body(it);
+ let after_if_expr = after_if_expr(it.clone());
+ let ref_expr_parent =
+ path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
+ let (innermost_ret_ty, self_param) = {
+ let find_ret_ty = |it: SyntaxNode| {
+ if let Some(item) = ast::Item::cast(it.clone()) {
+ match item {
+ ast::Item::Fn(f) => Some(sema.to_def(&f).map(|it| it.ret_type(sema.db))),
+ ast::Item::MacroCall(_) => None,
+ _ => Some(None),
}
- }
- }
- None
- };
-
- let type_location = |node: &SyntaxNode| {
- let parent = node.parent()?;
- let res = match_ast! {
- match parent {
- ast::Const(it) => {
- let name = find_opt_node_in_file(original_file, it.name())?;
- let original = ast::Const::cast(name.syntax().parent()?)?;
- TypeLocation::TypeAscription(TypeAscriptionTarget::Const(original.body()))
- },
- ast::RetType(it) => {
- if it.thin_arrow_token().is_none() {
- return None;
- }
- let parent = match ast::Fn::cast(parent.parent()?) {
- Some(x) => x.param_list(),
- None => ast::ClosureExpr::cast(parent.parent()?)?.param_list(),
- };
-
- let parent = find_opt_node_in_file(original_file, parent)?.syntax().parent()?;
- TypeLocation::TypeAscription(TypeAscriptionTarget::RetType(match_ast! {
- match parent {
- ast::ClosureExpr(it) => {
- it.body()
- },
- ast::Fn(it) => {
- it.body().map(ast::Expr::BlockExpr)
- },
- _ => return None,
- }
- }))
- },
- ast::Param(it) => {
- if it.colon_token().is_none() {
- return None;
- }
- TypeLocation::TypeAscription(TypeAscriptionTarget::FnParam(find_opt_node_in_file(original_file, it.pat())))
- },
- ast::LetStmt(it) => {
- if it.colon_token().is_none() {
- return None;
- }
- TypeLocation::TypeAscription(TypeAscriptionTarget::Let(find_opt_node_in_file(original_file, it.pat())))
- },
- ast::Impl(it) => {
- match it.trait_() {
- Some(t) if t.syntax() == node => TypeLocation::ImplTrait,
- _ => match it.self_ty() {
- Some(t) if t.syntax() == node => TypeLocation::ImplTarget,
- _ => return None,
- },
- }
- },
- ast::TypeBound(_) => TypeLocation::TypeBound,
- // is this case needed?
- ast::TypeBoundList(_) => TypeLocation::TypeBound,
- ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))),
- // is this case needed?
- ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))),
- ast::TupleField(_) => TypeLocation::TupleField,
- _ => return None,
- }
- };
- Some(res)
- };
-
- let is_in_condition = |it: &ast::Expr| {
- (|| {
- let parent = it.syntax().parent()?;
- if let Some(expr) = ast::WhileExpr::cast(parent.clone()) {
- Some(expr.condition()? == *it)
- } else if let Some(expr) = ast::IfExpr::cast(parent) {
- Some(expr.condition()? == *it)
} else {
- None
- }
- })()
- .unwrap_or(false)
- };
-
- let make_path_kind_expr = |expr: ast::Expr| {
- let it = expr.syntax();
- let in_block_expr = is_in_block(it);
- let in_loop_body = is_in_loop_body(it);
- let after_if_expr = after_if_expr(it.clone());
- let ref_expr_parent =
- path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
- let (innermost_ret_ty, self_param) = {
- let find_ret_ty = |it: SyntaxNode| {
- if let Some(item) = ast::Item::cast(it.clone()) {
- match item {
- ast::Item::Fn(f) => {
- Some(sema.to_def(&f).map(|it| it.ret_type(sema.db)))
- }
- ast::Item::MacroCall(_) => None,
- _ => Some(None),
- }
- } else {
- let expr = ast::Expr::cast(it)?;
- let callable = match expr {
- // FIXME
- // ast::Expr::BlockExpr(b) if b.async_token().is_some() || b.try_token().is_some() => sema.type_of_expr(b),
- ast::Expr::ClosureExpr(_) => sema.type_of_expr(&expr),
- _ => return None,
- };
- Some(
- callable
- .and_then(|c| c.adjusted().as_callable(sema.db))
- .map(|it| it.return_type()),
- )
- }
- };
- let find_fn_self_param = |it| match it {
- ast::Item::Fn(fn_) => {
- Some(sema.to_def(&fn_).and_then(|it| it.self_param(sema.db)))
- }
- ast::Item::MacroCall(_) => None,
- _ => Some(None),
- };
-
- match find_node_in_file_compensated(sema, original_file, &expr) {
- Some(it) => {
- let innermost_ret_ty = sema
- .ancestors_with_macros(it.syntax().clone())
- .find_map(find_ret_ty)
- .flatten();
-
- let self_param = sema
- .ancestors_with_macros(it.syntax().clone())
- .filter_map(ast::Item::cast)
- .find_map(find_fn_self_param)
- .flatten();
- (innermost_ret_ty, self_param)
- }
- None => (None, None),
+ let expr = ast::Expr::cast(it)?;
+ let callable = match expr {
+ // FIXME
+ // ast::Expr::BlockExpr(b) if b.async_token().is_some() || b.try_token().is_some() => sema.type_of_expr(b),
+ ast::Expr::ClosureExpr(_) => sema.type_of_expr(&expr),
+ _ => return None,
+ };
+ Some(
+ callable
+ .and_then(|c| c.adjusted().as_callable(sema.db))
+ .map(|it| it.return_type()),
+ )
}
};
- let is_func_update = func_update_record(it);
- let in_condition = is_in_condition(&expr);
- let incomplete_let = it
- .parent()
- .and_then(ast::LetStmt::cast)
- .map_or(false, |it| it.semicolon_token().is_none());
- let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
-
- let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) {
- Some(arm) => arm
- .fat_arrow_token()
- .map_or(true, |arrow| it.text_range().start() < arrow.text_range().start()),
- None => false,
+ let find_fn_self_param = |it| match it {
+ ast::Item::Fn(fn_) => Some(sema.to_def(&fn_).and_then(|it| it.self_param(sema.db))),
+ ast::Item::MacroCall(_) => None,
+ _ => Some(None),
};
- PathKind::Expr {
- expr_ctx: ExprCtx {
- in_block_expr,
- in_loop_body,
- after_if_expr,
- in_condition,
- ref_expr_parent,
- is_func_update,
- innermost_ret_ty,
- self_param,
- incomplete_let,
- impl_,
- in_match_guard,
- },
+ match find_node_in_file_compensated(sema, original_file, &expr) {
+ Some(it) => {
+ let innermost_ret_ty = sema
+ .ancestors_with_macros(it.syntax().clone())
+ .find_map(find_ret_ty)
+ .flatten();
+
+ let self_param = sema
+ .ancestors_with_macros(it.syntax().clone())
+ .filter_map(ast::Item::cast)
+ .find_map(find_fn_self_param)
+ .flatten();
+ (innermost_ret_ty, self_param)
+ }
+ None => (None, None),
}
};
- let make_path_kind_type = |ty: ast::Type| {
- let location = type_location(ty.syntax());
- PathKind::Type { location: location.unwrap_or(TypeLocation::Other) }
+ let is_func_update = func_update_record(it);
+ let in_condition = is_in_condition(&expr);
+ let incomplete_let = it
+ .parent()
+ .and_then(ast::LetStmt::cast)
+ .map_or(false, |it| it.semicolon_token().is_none());
+ let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
+
+ let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) {
+ Some(arm) => arm
+ .fat_arrow_token()
+ .map_or(true, |arrow| it.text_range().start() < arrow.text_range().start()),
+ None => false,
};
- let mut kind_macro_call = |it: ast::MacroCall| {
- path_ctx.has_macro_bang = it.excl_token().is_some();
- let parent = it.syntax().parent()?;
- // Any path in an item list will be treated as a macro call by the parser
- let kind = match_ast! {
- match parent {
- ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
- ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())},
- ast::MacroType(ty) => make_path_kind_type(ty.into()),
- ast::ItemList(_) => PathKind::Item { kind: ItemListKind::Module },
- ast::AssocItemList(_) => PathKind::Item { kind: match parent.parent() {
- Some(it) => match_ast! {
- match it {
- ast::Trait(_) => ItemListKind::Trait,
- ast::Impl(it) => if it.trait_().is_some() {
- ItemListKind::TraitImpl(find_node_in_file_compensated(sema, original_file, &it))
- } else {
- ItemListKind::Impl
- },
- _ => return None
- }
- },
- None => return None,
- } },
- ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
- ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
- _ => return None,
- }
- };
- Some(kind)
- };
- let make_path_kind_attr = |meta: ast::Meta| {
- let attr = meta.parent_attr()?;
- let kind = attr.kind();
- let attached = attr.syntax().parent()?;
- let is_trailing_outer_attr = kind != AttrKind::Inner
- && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next)
- .is_none();
- let annotated_item_kind =
- if is_trailing_outer_attr { None } else { Some(attached.kind()) };
- Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } })
- };
+ PathKind::Expr {
+ expr_ctx: ExprCtx {
+ in_block_expr,
+ in_loop_body,
+ after_if_expr,
+ in_condition,
+ ref_expr_parent,
+ is_func_update,
+ innermost_ret_ty,
+ self_param,
+ incomplete_let,
+ impl_,
+ in_match_guard,
+ },
+ }
+ };
+ let make_path_kind_type = |ty: ast::Type| {
+ let location = type_location(ty.syntax());
+ PathKind::Type { location: location.unwrap_or(TypeLocation::Other) }
+ };
- // Infer the path kind
- let parent = path.syntax().parent()?;
+ let mut kind_macro_call = |it: ast::MacroCall| {
+ path_ctx.has_macro_bang = it.excl_token().is_some();
+ let parent = it.syntax().parent()?;
+ // Any path in an item list will be treated as a macro call by the parser
let kind = match_ast! {
match parent {
- ast::PathType(it) => make_path_kind_type(it.into()),
- ast::PathExpr(it) => {
- if let Some(p) = it.syntax().parent() {
- if ast::ExprStmt::can_cast(p.kind()) {
- if let Some(kind) = inbetween_body_and_decl_check(p) {
- return Some(make_res(NameRefKind::Keyword(kind)));
- }
- }
- }
-
- path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
-
- make_path_kind_expr(it.into())
- },
- ast::TupleStructPat(it) => {
- path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
- },
- ast::RecordPat(it) => {
- path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
- },
- ast::PathPat(it) => {
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
- },
- ast::MacroCall(it) => {
- // A macro call in this position is usually a result of parsing recovery, so check that
- if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
- return Some(make_res(NameRefKind::Keyword(kind)));
- }
-
- kind_macro_call(it)?
- },
- ast::Meta(meta) => make_path_kind_attr(meta)?,
- ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
- ast::UseTree(_) => PathKind::Use,
- // completing inside a qualifier
- ast::Path(parent) => {
- path_ctx.parent = Some(parent.clone());
- let parent = iter::successors(Some(parent), |it| it.parent_path()).last()?.syntax().parent()?;
- match_ast! {
- match parent {
- ast::PathType(it) => make_path_kind_type(it.into()),
- ast::PathExpr(it) => {
- path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
-
- make_path_kind_expr(it.into())
- },
- ast::TupleStructPat(it) => {
- path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
- },
- ast::RecordPat(it) => {
- path_ctx.has_call_parens = true;
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
- },
- ast::PathPat(it) => {
- PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
- },
- ast::MacroCall(it) => {
- kind_macro_call(it)?
+ ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
+ ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())},
+ ast::MacroType(ty) => make_path_kind_type(ty.into()),
+ ast::ItemList(_) => PathKind::Item { kind: ItemListKind::Module },
+ ast::AssocItemList(_) => PathKind::Item { kind: match parent.parent() {
+ Some(it) => match_ast! {
+ match it {
+ ast::Trait(_) => ItemListKind::Trait,
+ ast::Impl(it) => if it.trait_().is_some() {
+ ItemListKind::TraitImpl(find_node_in_file_compensated(sema, original_file, &it))
+ } else {
+ ItemListKind::Impl
},
- ast::Meta(meta) => make_path_kind_attr(meta)?,
- ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
- ast::UseTree(_) => PathKind::Use,
- ast::RecordExpr(it) => make_path_kind_expr(it.into()),
- _ => return None,
+ _ => return None
}
- }
- },
- ast::RecordExpr(it) => make_path_kind_expr(it.into()),
+ },
+ None => return None,
+ } },
+ ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
+ ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
_ => return None,
}
};
+ Some(kind)
+ };
+ let make_path_kind_attr = |meta: ast::Meta| {
+ let attr = meta.parent_attr()?;
+ let kind = attr.kind();
+ let attached = attr.syntax().parent()?;
+ let is_trailing_outer_attr = kind != AttrKind::Inner
+ && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next).is_none();
+ let annotated_item_kind = if is_trailing_outer_attr { None } else { Some(attached.kind()) };
+ Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } })
+ };
- path_ctx.kind = kind;
- path_ctx.has_type_args = segment.generic_arg_list().is_some();
+ // Infer the path kind
+ let parent = path.syntax().parent()?;
+ let kind = match_ast! {
+ match parent {
+ ast::PathType(it) => make_path_kind_type(it.into()),
+ ast::PathExpr(it) => {
+ if let Some(p) = it.syntax().parent() {
+ if ast::ExprStmt::can_cast(p.kind()) {
+ if let Some(kind) = inbetween_body_and_decl_check(p) {
+ return Some(make_res(NameRefKind::Keyword(kind)));
+ }
+ }
+ }
- // calculate the qualifier context
- if let Some((qualifier, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
- path_ctx.use_tree_parent = use_tree_parent;
- if !use_tree_parent && segment.coloncolon_token().is_some() {
- path_ctx.qualified = Qualified::Absolute;
- } else {
- let qualifier = qualifier
- .segment()
- .and_then(|it| find_node_in_file(original_file, &it))
- .map(|it| it.parent_path());
- if let Some(qualifier) = qualifier {
- let type_anchor = match qualifier.segment().and_then(|it| it.kind()) {
- Some(ast::PathSegmentKind::Type {
- type_ref: Some(type_ref),
- trait_ref,
- }) if qualifier.qualifier().is_none() => Some((type_ref, trait_ref)),
- _ => None,
- };
+ path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
+
+ make_path_kind_expr(it.into())
+ },
+ ast::TupleStructPat(it) => {
+ path_ctx.has_call_parens = true;
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
+ },
+ ast::RecordPat(it) => {
+ path_ctx.has_call_parens = true;
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
+ },
+ ast::PathPat(it) => {
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
+ },
+ ast::MacroCall(it) => {
+ // A macro call in this position is usually a result of parsing recovery, so check that
+ if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
+ return Some(make_res(NameRefKind::Keyword(kind)));
+ }
- path_ctx.qualified = if let Some((ty, trait_ref)) = type_anchor {
- let ty = match ty {
- ast::Type::InferType(_) => None,
- ty => sema.resolve_type(&ty),
- };
- let trait_ = trait_ref.and_then(|it| sema.resolve_trait(&it.path()?));
- Qualified::TypeAnchor { ty, trait_ }
- } else {
- let res = sema.resolve_path(&qualifier);
-
- // For understanding how and why super_chain_len is calculated the way it
- // is check the documentation at it's definition
- let mut segment_count = 0;
- let super_count =
- iter::successors(Some(qualifier.clone()), |p| p.qualifier())
- .take_while(|p| {
- p.segment()
- .and_then(|s| {
- segment_count += 1;
- s.super_token()
- })
- .is_some()
- })
- .count();
+ kind_macro_call(it)?
+ },
+ ast::Meta(meta) => make_path_kind_attr(meta)?,
+ ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
+ ast::UseTree(_) => PathKind::Use,
+ // completing inside a qualifier
+ ast::Path(parent) => {
+ path_ctx.parent = Some(parent.clone());
+ let parent = iter::successors(Some(parent), |it| it.parent_path()).last()?.syntax().parent()?;
+ match_ast! {
+ match parent {
+ ast::PathType(it) => make_path_kind_type(it.into()),
+ ast::PathExpr(it) => {
+ path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
+
+ make_path_kind_expr(it.into())
+ },
+ ast::TupleStructPat(it) => {
+ path_ctx.has_call_parens = true;
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
+ },
+ ast::RecordPat(it) => {
+ path_ctx.has_call_parens = true;
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
+ },
+ ast::PathPat(it) => {
+ PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
+ },
+ ast::MacroCall(it) => {
+ kind_macro_call(it)?
+ },
+ ast::Meta(meta) => make_path_kind_attr(meta)?,
+ ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
+ ast::UseTree(_) => PathKind::Use,
+ ast::RecordExpr(it) => make_path_kind_expr(it.into()),
+ _ => return None,
+ }
+ }
+ },
+ ast::RecordExpr(it) => make_path_kind_expr(it.into()),
+ _ => return None,
+ }
+ };
- let super_chain_len =
- if segment_count > super_count { None } else { Some(super_count) };
+ path_ctx.kind = kind;
+ path_ctx.has_type_args = segment.generic_arg_list().is_some();
- Qualified::With { path: qualifier, resolution: res, super_chain_len }
+ // calculate the qualifier context
+ if let Some((qualifier, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
+ path_ctx.use_tree_parent = use_tree_parent;
+ if !use_tree_parent && segment.coloncolon_token().is_some() {
+ path_ctx.qualified = Qualified::Absolute;
+ } else {
+ let qualifier = qualifier
+ .segment()
+ .and_then(|it| find_node_in_file(original_file, &it))
+ .map(|it| it.parent_path());
+ if let Some(qualifier) = qualifier {
+ let type_anchor = match qualifier.segment().and_then(|it| it.kind()) {
+ Some(ast::PathSegmentKind::Type { type_ref: Some(type_ref), trait_ref })
+ if qualifier.qualifier().is_none() =>
+ {
+ Some((type_ref, trait_ref))
}
+ _ => None,
};
- }
- } else if let Some(segment) = path.segment() {
- if segment.coloncolon_token().is_some() {
- path_ctx.qualified = Qualified::Absolute;
- }
- }
- let mut qualifier_ctx = QualifierCtx::default();
- if path_ctx.is_trivial_path() {
- // fetch the full expression that may have qualifiers attached to it
- let top_node = match path_ctx.kind {
- PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. } } => {
- parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
- let parent = p.parent()?;
- if ast::StmtList::can_cast(parent.kind()) {
- Some(p)
- } else if ast::ExprStmt::can_cast(parent.kind()) {
- Some(parent)
- } else {
- None
- }
- })
- }
- PathKind::Item { .. } => {
- parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
+ path_ctx.qualified = if let Some((ty, trait_ref)) = type_anchor {
+ let ty = match ty {
+ ast::Type::InferType(_) => None,
+ ty => sema.resolve_type(&ty),
+ };
+ let trait_ = trait_ref.and_then(|it| sema.resolve_trait(&it.path()?));
+ Qualified::TypeAnchor { ty, trait_ }
+ } else {
+ let res = sema.resolve_path(&qualifier);
+
+ // For understanding how and why super_chain_len is calculated the way it
+ // is check the documentation at it's definition
+ let mut segment_count = 0;
+ let super_count = iter::successors(Some(qualifier.clone()), |p| p.qualifier())
+ .take_while(|p| {
+ p.segment()
+ .and_then(|s| {
+ segment_count += 1;
+ s.super_token()
+ })
+ .is_some()
+ })
+ .count();
+
+ let super_chain_len =
+ if segment_count > super_count { None } else { Some(super_count) };
+
+ Qualified::With { path: qualifier, resolution: res, super_chain_len }
}
- _ => None,
};
- if let Some(top) = top_node {
- if let Some(NodeOrToken::Node(error_node)) =
- syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
- {
- if error_node.kind() == SyntaxKind::ERROR {
- qualifier_ctx.unsafe_tok = error_node
- .children_with_tokens()
- .filter_map(NodeOrToken::into_token)
- .find(|it| it.kind() == T![unsafe]);
- qualifier_ctx.vis_node =
- error_node.children().find_map(ast::Visibility::cast);
+ }
+ } else if let Some(segment) = path.segment() {
+ if segment.coloncolon_token().is_some() {
+ path_ctx.qualified = Qualified::Absolute;
+ }
+ }
+
+ let mut qualifier_ctx = QualifierCtx::default();
+ if path_ctx.is_trivial_path() {
+ // fetch the full expression that may have qualifiers attached to it
+ let top_node = match path_ctx.kind {
+ PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. } } => {
+ parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
+ let parent = p.parent()?;
+ if ast::StmtList::can_cast(parent.kind()) {
+ Some(p)
+ } else if ast::ExprStmt::can_cast(parent.kind()) {
+ Some(parent)
+ } else {
+ None
}
+ })
+ }
+ PathKind::Item { .. } => {
+ parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
+ }
+ _ => None,
+ };
+ if let Some(top) = top_node {
+ if let Some(NodeOrToken::Node(error_node)) =
+ syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
+ {
+ if error_node.kind() == SyntaxKind::ERROR {
+ qualifier_ctx.unsafe_tok = error_node
+ .children_with_tokens()
+ .filter_map(NodeOrToken::into_token)
+ .find(|it| it.kind() == T![unsafe]);
+ qualifier_ctx.vis_node = error_node.children().find_map(ast::Visibility::cast);
}
+ }
- if let PathKind::Item { .. } = path_ctx.kind {
- if qualifier_ctx.none() {
- if let Some(t) = top.first_token() {
- if let Some(prev) = t
- .prev_token()
- .and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
- {
- if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
- // This was inferred to be an item position path, but it seems
- // to be part of some other broken node which leaked into an item
- // list
- return None;
- }
+ if let PathKind::Item { .. } = path_ctx.kind {
+ if qualifier_ctx.none() {
+ if let Some(t) = top.first_token() {
+ if let Some(prev) = t
+ .prev_token()
+ .and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
+ {
+ if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
+ // This was inferred to be an item position path, but it seems
+ // to be part of some other broken node which leaked into an item
+ // list
+ return None;
}
}
}
}
}
}
- Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
}
+ Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
}
fn pattern_context_for(
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 ae1a440d0..9d0044e55 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -183,6 +183,7 @@ pub fn completions(
CompletionAnalysis::String { original, expanded: Some(expanded) } => {
completions::extern_abi::complete_extern_abi(acc, ctx, expanded);
completions::format_string::format_string(acc, ctx, original, expanded);
+ completions::env_vars::complete_cargo_env_vars(acc, ctx, expanded);
}
CompletionAnalysis::UnexpandedAttrTT {
colon_prefix,
@@ -234,7 +235,12 @@ pub fn resolve_completion_edits(
);
let import = items_with_name
.filter_map(|candidate| {
- current_module.find_use_path_prefixed(db, candidate, config.insert_use.prefix_kind)
+ current_module.find_use_path_prefixed(
+ db,
+ candidate,
+ config.insert_use.prefix_kind,
+ config.prefer_no_std,
+ )
})
.find(|mod_path| mod_path.to_string() == full_import_path);
if let Some(import_path) = import {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
index dc1039fa6..f3b8eae4f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -174,8 +174,12 @@ fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option<V
hir::PathResolution::Def(def) => def.into(),
_ => return None,
};
- let path =
- ctx.module.find_use_path_prefixed(ctx.db, item, ctx.config.insert_use.prefix_kind)?;
+ let path = ctx.module.find_use_path_prefixed(
+ ctx.db,
+ item,
+ ctx.config.insert_use.prefix_kind,
+ ctx.config.prefer_no_std,
+ )?;
Some((path.len() > 1).then(|| LocatedImport::new(path.clone(), item, item, None)))
};
let mut res = Vec::with_capacity(requires.len());
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 cf826648d..9e2beb9ee 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -66,6 +66,7 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
enable_private_editable: false,
callable: Some(CallableSnippets::FillArguments),
snippet_cap: SnippetCap::new(true),
+ prefer_no_std: false,
insert_use: InsertUseConfig {
granularity: ImportGranularity::Crate,
prefix_kind: PrefixKind::Plain,
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
index 85c4dbd66..db8bef664 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
@@ -714,3 +714,30 @@ impl Ty {
"#]],
);
}
+
+#[test]
+fn through_alias() {
+ check_empty(
+ r#"
+enum Enum<T> {
+ Unit,
+ Tuple(T),
+}
+
+type EnumAlias<T> = Enum<T>;
+
+fn f(x: EnumAlias<u8>) {
+ match x {
+ EnumAlias::$0 => (),
+ _ => (),
+ }
+
+}
+
+"#,
+ expect![[r#"
+ bn Tuple(…) Tuple($1)$0
+ bn Unit Unit$0
+ "#]],
+ );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index a1b0bd6cb..cf0bcd5c9 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -15,11 +15,12 @@ tracing = "0.1.35"
rayon = "1.5.3"
fst = { version = "0.4.7", default-features = false }
rustc-hash = "1.1.0"
-once_cell = "1.12.0"
+once_cell = "1.15.0"
either = "1.7.0"
-itertools = "0.10.3"
+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" }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
index 26ef86155..40a6a3e89 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
@@ -212,18 +212,20 @@ impl ImportAssets {
&self,
sema: &Semantics<'_, RootDatabase>,
prefix_kind: PrefixKind,
+ prefer_no_std: bool,
) -> Vec<LocatedImport> {
let _p = profile::span("import_assets::search_for_imports");
- self.search_for(sema, Some(prefix_kind))
+ self.search_for(sema, Some(prefix_kind), prefer_no_std)
}
/// This may return non-absolute paths if a part of the returned path is already imported into scope.
pub fn search_for_relative_paths(
&self,
sema: &Semantics<'_, RootDatabase>,
+ prefer_no_std: bool,
) -> Vec<LocatedImport> {
let _p = profile::span("import_assets::search_for_relative_paths");
- self.search_for(sema, None)
+ self.search_for(sema, None, prefer_no_std)
}
pub fn path_fuzzy_name_to_exact(&mut self, case_sensitive: bool) {
@@ -242,6 +244,7 @@ impl ImportAssets {
&self,
sema: &Semantics<'_, RootDatabase>,
prefixed: Option<PrefixKind>,
+ prefer_no_std: bool,
) -> Vec<LocatedImport> {
let _p = profile::span("import_assets::search_for");
@@ -252,6 +255,7 @@ impl ImportAssets {
item_for_path_search(sema.db, item)?,
&self.module_with_candidate,
prefixed,
+ prefer_no_std,
)
};
@@ -564,11 +568,12 @@ fn get_mod_path(
item_to_search: ItemInNs,
module_with_candidate: &Module,
prefixed: Option<PrefixKind>,
+ prefer_no_std: bool,
) -> Option<ModPath> {
if let Some(prefix_kind) = prefixed {
- module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind)
+ module_with_candidate.find_use_path_prefixed(db, item_to_search, prefix_kind, prefer_no_std)
} else {
- module_with_candidate.find_use_path(db, item_to_search)
+ module_with_candidate.find_use_path(db, item_to_search, prefer_no_std)
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
index 7fb4b90e6..371d642c1 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
@@ -225,7 +225,7 @@ fn path_cmp_short(a: &ast::Path, b: &ast::Path) -> Ordering {
}
/// Compares two paths, if one ends earlier than the other the has_tl parameters decide which is
-/// greater as a a path that has a tree list should be greater, while one that just ends without
+/// greater as a path that has a tree list should be greater, while one that just ends without
/// a tree list should be considered less.
pub(super) fn use_tree_path_cmp(
a: &ast::Path,
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index 1ec62a842..e0bc0f89f 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -38,6 +38,7 @@ pub mod syntax_helpers {
pub mod node_ext;
pub mod insert_whitespace_into_node;
pub mod format_string;
+ pub mod format_string_exprs;
pub use parser::LexedStr;
}
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 40af9e6fe..12d873b4a 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
@@ -173,6 +173,7 @@ impl<'a> Ctx<'a> {
let found_path = self.target_module.find_use_path(
self.source_scope.db.upcast(),
hir::ModuleDef::Trait(trait_ref),
+ false,
)?;
match ast::make::ty_path(mod_path_to_ast(&found_path)) {
ast::Type::PathType(path_ty) => Some(path_ty),
@@ -209,7 +210,7 @@ impl<'a> Ctx<'a> {
}
let found_path =
- self.target_module.find_use_path(self.source_scope.db.upcast(), def)?;
+ self.target_module.find_use_path(self.source_scope.db.upcast(), def, false)?;
let res = mod_path_to_ast(&found_path).clone_for_update();
if let Some(args) = path.segment().and_then(|it| it.generic_arg_list()) {
if let Some(segment) = res.segment() {
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 7deffe8e0..82b85f2fa 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -8,7 +8,9 @@ use std::{mem, sync::Arc};
use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
+use memchr::memmem::Finder;
use once_cell::unsync::Lazy;
+use parser::SyntaxKind;
use stdx::hash::NoHashHashMap;
use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
@@ -67,6 +69,7 @@ pub enum ReferenceCategory {
// Create
Write,
Read,
+ Import,
// FIXME: Some day should be able to search in doc comments. Would probably
// need to switch from enum to bitflags then?
// DocComment
@@ -236,6 +239,7 @@ impl Definition {
DefWithBody::Function(f) => f.source(db).map(|src| src.syntax().cloned()),
DefWithBody::Const(c) => c.source(db).map(|src| src.syntax().cloned()),
DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
+ DefWithBody::Variant(v) => v.source(db).map(|src| src.syntax().cloned()),
};
return match def {
Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
@@ -409,14 +413,17 @@ impl<'a> FindUsages<'a> {
Some(s) => s.as_str(),
None => return,
};
+ let finder = &Finder::new(name);
+ let include_self_kw_refs =
+ self.include_self_kw_refs.as_ref().map(|ty| (ty, Finder::new("Self")));
- // these can't be closures because rust infers the lifetimes wrong ...
+ // for<'a> |text: &'a str, name: &'a str, search_range: TextRange| -> impl Iterator<Item = TextSize> + 'a { ... }
fn match_indices<'a>(
text: &'a str,
- name: &'a str,
+ finder: &'a Finder<'a>,
search_range: TextRange,
) -> impl Iterator<Item = TextSize> + 'a {
- text.match_indices(name).filter_map(move |(idx, _)| {
+ finder.find_iter(text.as_bytes()).filter_map(move |idx| {
let offset: TextSize = idx.try_into().unwrap();
if !search_range.contains_inclusive(offset) {
return None;
@@ -425,6 +432,7 @@ impl<'a> FindUsages<'a> {
})
}
+ // for<'a> |scope: &'a SearchScope| -> impl Iterator<Item = (Arc<String>, FileId, TextRange)> + 'a { ... }
fn scope_files<'a>(
sema: &'a Semantics<'_, RootDatabase>,
scope: &'a SearchScope,
@@ -448,7 +456,7 @@ impl<'a> FindUsages<'a> {
let tree = Lazy::new(move || sema.parse(file_id).syntax().clone());
// Search for occurrences of the items name
- for offset in match_indices(&text, name, search_range) {
+ for offset in match_indices(&text, finder, search_range) {
for name in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if match name {
ast::NameLike::NameRef(name_ref) => self.found_name_ref(&name_ref, sink),
@@ -460,8 +468,8 @@ impl<'a> FindUsages<'a> {
}
}
// Search for occurrences of the `Self` referring to our type
- if let Some(self_ty) = &self.include_self_kw_refs {
- for offset in match_indices(&text, "Self", search_range) {
+ if let Some((self_ty, finder)) = &include_self_kw_refs {
+ for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_self_ty_name_ref(self_ty, &name_ref, sink) {
return;
@@ -477,20 +485,22 @@ impl<'a> FindUsages<'a> {
let scope = search_scope
.intersection(&SearchScope::module_and_children(self.sema.db, module));
- let is_crate_root = module.is_crate_root(self.sema.db);
+ 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 offset in match_indices(&text, "super", search_range) {
+ for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_name_ref(&name_ref, sink) {
return;
}
}
}
- if is_crate_root {
- for offset in match_indices(&text, "crate", search_range) {
+ if let Some(finder) = &is_crate_root {
+ for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_name_ref(&name_ref, sink) {
return;
@@ -531,8 +541,9 @@ impl<'a> FindUsages<'a> {
search_range.unwrap_or_else(|| TextRange::up_to(TextSize::of(text.as_str())));
let tree = Lazy::new(|| sema.parse(file_id).syntax().clone());
+ let finder = &Finder::new("self");
- for offset in match_indices(&text, "self", search_range) {
+ for offset in match_indices(&text, finder, search_range) {
for name_ref in sema.find_nodes_at_offset_with_descend(&tree, offset) {
if self.found_self_module_name_ref(&name_ref, sink) {
return;
@@ -577,7 +588,7 @@ impl<'a> FindUsages<'a> {
let reference = FileReference {
range,
name: ast::NameLike::NameRef(name_ref.clone()),
- category: None,
+ category: is_name_ref_in_import(name_ref).then(|| ReferenceCategory::Import),
};
sink(file_id, reference)
}
@@ -756,7 +767,7 @@ impl ReferenceCategory {
fn new(def: &Definition, r: &ast::NameRef) -> Option<ReferenceCategory> {
// Only Locals and Fields have accesses for now.
if !matches!(def, Definition::Local(_) | Definition::Field(_)) {
- return None;
+ return is_name_ref_in_import(r).then(|| ReferenceCategory::Import);
}
let mode = r.syntax().ancestors().find_map(|node| {
@@ -783,3 +794,12 @@ impl ReferenceCategory {
mode.or(Some(ReferenceCategory::Read))
}
}
+
+fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool {
+ name_ref
+ .syntax()
+ .parent()
+ .and_then(ast::PathSegment::cast)
+ .and_then(|it| it.parent_path().top_path().syntax().parent())
+ .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE)
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
index f48a57008..2d6927cee 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string.rs
@@ -1,7 +1,8 @@
//! Tools to work with format string literals for the `format_args!` family of macros.
+use crate::syntax_helpers::node_ext::macro_call_for_string_token;
use syntax::{
ast::{self, IsString},
- AstNode, AstToken, TextRange, TextSize,
+ TextRange, TextSize,
};
pub fn is_format_string(string: &ast::String) -> bool {
@@ -14,8 +15,7 @@ pub fn is_format_string(string: &ast::String) -> bool {
// This setup lets us correctly highlight the components of `concat!("{}", "bla")` format
// strings. It still fails for `concat!("{", "}")`, but that is rare.
(|| {
- let macro_call = string.syntax().parent_ancestors().find_map(ast::MacroCall::cast)?;
- let name = macro_call.path()?.segment()?.name_ref()?;
+ let name = macro_call_for_string_token(string)?.path()?.segment()?.name_ref()?;
if !matches!(
name.text().as_str(),
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
new file mode 100644
index 000000000..ac6c6e8fe
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
@@ -0,0 +1,267 @@
+//! Tools to work with expressions present in format string literals for the `format_args!` family of macros.
+//! Primarily meant for assists and completions.
+
+/// Enum for represenging extraced format string args.
+/// Can either be extracted expressions (which includes identifiers),
+/// or placeholders `{}`.
+#[derive(Debug, PartialEq, Eq)]
+pub enum Arg {
+ Placeholder,
+ Ident(String),
+ Expr(String),
+}
+
+/**
+ Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
+ and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
+ ```rust
+ # use ide_db::syntax_helpers::format_string_exprs::*;
+ assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
+ ```
+*/
+
+pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
+ let mut placeholder_id = 1;
+ args.into_iter()
+ .map(move |a| match a {
+ Arg::Expr(s) | Arg::Ident(s) => s,
+ Arg::Placeholder => {
+ let s = format!("${placeholder_id}");
+ placeholder_id += 1;
+ s
+ }
+ })
+ .collect()
+}
+
+/**
+ Parser for a format-like string. It is more allowing in terms of string contents,
+ as we expect variable placeholders to be filled with expressions.
+
+ Built for completions and assists, and escapes `\` and `$` in output.
+ (See the comments on `get_receiver_text()` for detail.)
+ Splits a format string that may contain expressions
+ like
+ ```rust
+ assert_eq!(parse("{ident} {} {expr + 42} ").unwrap(), ("{} {} {}", vec![Arg::Ident("ident"), Arg::Placeholder, Arg::Expr("expr + 42")]));
+ ```
+*/
+pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
+ #[derive(Debug, Clone, Copy, PartialEq)]
+ enum State {
+ NotArg,
+ MaybeArg,
+ Expr,
+ Ident,
+ MaybeIncorrect,
+ FormatOpts,
+ }
+
+ let mut state = State::NotArg;
+ let mut current_expr = String::new();
+ let mut extracted_expressions = Vec::new();
+ let mut output = String::new();
+
+ // Count of open braces inside of an expression.
+ // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
+ // "{MyStruct { val_a: 0, val_b: 1 }}".
+ let mut inexpr_open_count = 0;
+
+ let mut chars = input.chars().peekable();
+ while let Some(chr) = chars.next() {
+ match (state, chr) {
+ (State::NotArg, '{') => {
+ output.push(chr);
+ state = State::MaybeArg;
+ }
+ (State::NotArg, '}') => {
+ output.push(chr);
+ state = State::MaybeIncorrect;
+ }
+ (State::NotArg, _) => {
+ if matches!(chr, '\\' | '$') {
+ output.push('\\');
+ }
+ output.push(chr);
+ }
+ (State::MaybeIncorrect, '}') => {
+ // It's okay, we met "}}".
+ output.push(chr);
+ state = State::NotArg;
+ }
+ (State::MaybeIncorrect, _) => {
+ // Error in the string.
+ return Err(());
+ }
+ // Escaped braces `{{`
+ (State::MaybeArg, '{') => {
+ output.push(chr);
+ state = State::NotArg;
+ }
+ (State::MaybeArg, '}') => {
+ // This is an empty sequence '{}'.
+ output.push(chr);
+ extracted_expressions.push(Arg::Placeholder);
+ state = State::NotArg;
+ }
+ (State::MaybeArg, _) => {
+ if matches!(chr, '\\' | '$') {
+ current_expr.push('\\');
+ }
+ current_expr.push(chr);
+
+ // While Rust uses the unicode sets of XID_start and XID_continue for Identifiers
+ // this is probably the best we can do to avoid a false positive
+ if chr.is_alphabetic() || chr == '_' {
+ state = State::Ident;
+ } else {
+ state = State::Expr;
+ }
+ }
+ (State::Ident | State::Expr, '}') => {
+ if inexpr_open_count == 0 {
+ output.push(chr);
+
+ if matches!(state, State::Expr) {
+ extracted_expressions.push(Arg::Expr(current_expr.trim().into()));
+ } else {
+ extracted_expressions.push(Arg::Ident(current_expr.trim().into()));
+ }
+
+ current_expr = String::new();
+ state = State::NotArg;
+ } else {
+ // We're closing one brace met before inside of the expression.
+ current_expr.push(chr);
+ inexpr_open_count -= 1;
+ }
+ }
+ (State::Ident | State::Expr, ':') if matches!(chars.peek(), Some(':')) => {
+ // path separator
+ state = State::Expr;
+ current_expr.push_str("::");
+ chars.next();
+ }
+ (State::Ident | State::Expr, ':') => {
+ if inexpr_open_count == 0 {
+ // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
+ output.push(chr);
+
+ if matches!(state, State::Expr) {
+ extracted_expressions.push(Arg::Expr(current_expr.trim().into()));
+ } else {
+ extracted_expressions.push(Arg::Ident(current_expr.trim().into()));
+ }
+
+ current_expr = String::new();
+ state = State::FormatOpts;
+ } else {
+ // We're inside of braced expression, assume that it's a struct field name/value delimiter.
+ current_expr.push(chr);
+ }
+ }
+ (State::Ident | State::Expr, '{') => {
+ state = State::Expr;
+ current_expr.push(chr);
+ inexpr_open_count += 1;
+ }
+ (State::Ident | State::Expr, _) => {
+ if !(chr.is_alphanumeric() || chr == '_' || chr == '#') {
+ state = State::Expr;
+ }
+
+ if matches!(chr, '\\' | '$') {
+ current_expr.push('\\');
+ }
+ current_expr.push(chr);
+ }
+ (State::FormatOpts, '}') => {
+ output.push(chr);
+ state = State::NotArg;
+ }
+ (State::FormatOpts, _) => {
+ if matches!(chr, '\\' | '$') {
+ output.push('\\');
+ }
+ output.push(chr);
+ }
+ }
+ }
+
+ if state != State::NotArg {
+ return Err(());
+ }
+
+ Ok((output, extracted_expressions))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use expect_test::{expect, Expect};
+
+ fn check(input: &str, expect: &Expect) {
+ let (output, exprs) = parse_format_exprs(input).unwrap_or(("-".to_string(), vec![]));
+ let outcome_repr = if !exprs.is_empty() {
+ format!("{}; {}", output, with_placeholders(exprs).join(", "))
+ } else {
+ output
+ };
+
+ expect.assert_eq(&outcome_repr);
+ }
+
+ #[test]
+ fn format_str_parser() {
+ let test_vector = &[
+ ("no expressions", expect![["no expressions"]]),
+ (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
+ ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
+ ("{expr:?}", expect![["{:?}; expr"]]),
+ ("{expr:1$}", expect![[r"{:1\$}; expr"]]),
+ ("{$0}", expect![[r"{}; \$0"]]),
+ ("{malformed", expect![["-"]]),
+ ("malformed}", expect![["-"]]),
+ ("{{correct", expect![["{{correct"]]),
+ ("correct}}", expect![["correct}}"]]),
+ ("{correct}}}", expect![["{}}}; correct"]]),
+ ("{correct}}}}}", expect![["{}}}}}; correct"]]),
+ ("{incorrect}}", expect![["-"]]),
+ ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
+ ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
+ (
+ "{SomeStruct { val_a: 0, val_b: 1 }}",
+ expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
+ ),
+ ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
+ (
+ "{SomeStruct { val_a: 0, val_b: 1 }:?}",
+ expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
+ ),
+ ("{ 2 + 2 }", expect![["{}; 2 + 2"]]),
+ ("{strsim::jaro_winkle(a)}", expect![["{}; strsim::jaro_winkle(a)"]]),
+ ("{foo::bar::baz()}", expect![["{}; foo::bar::baz()"]]),
+ ("{foo::bar():?}", expect![["{:?}; foo::bar()"]]),
+ ];
+
+ for (input, output) in test_vector {
+ check(input, output)
+ }
+ }
+
+ #[test]
+ fn arg_type() {
+ assert_eq!(
+ parse_format_exprs("{_ident} {r#raw_ident} {expr.obj} {name {thing: 42} } {}")
+ .unwrap()
+ .1,
+ vec![
+ Arg::Ident("_ident".to_owned()),
+ Arg::Ident("r#raw_ident".to_owned()),
+ Arg::Expr("expr.obj".to_owned()),
+ Arg::Expr("name {thing: 42}".to_owned()),
+ Arg::Placeholder
+ ]
+ );
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
index b890e2b58..39710b8f1 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -2,8 +2,8 @@
use itertools::Itertools;
use parser::T;
use syntax::{
- ast::{self, HasLoopBody, PathSegmentKind, VisibilityKind},
- AstNode, Preorder, RustLanguage, WalkEvent,
+ ast::{self, HasLoopBody, MacroCall, PathSegmentKind, VisibilityKind},
+ AstNode, AstToken, Preorder, RustLanguage, WalkEvent,
};
pub fn expr_as_name_ref(expr: &ast::Expr) -> Option<ast::NameRef> {
@@ -457,3 +457,8 @@ pub fn parse_tt_as_comma_sep_paths(input: ast::TokenTree) -> Option<Vec<ast::Pat
.collect();
Some(paths)
}
+
+pub fn macro_call_for_string_token(string: &ast::String) -> Option<MacroCall> {
+ let macro_call = string.syntax().parent_ancestors().find_map(ast::MacroCall::cast)?;
+ Some(macro_call)
+}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 9b9e21a4d..e1d146f4e 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -11,11 +11,9 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.3"
-
-
either = "1.7.0"
-serde_json = "1.0.82"
+itertools = "0.10.5"
+serde_json = "1.0.86"
profile = { path = "../profile", version = "0.0.0" }
stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
index 04918891b..f558b7256 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/inactive_code.rs
@@ -140,4 +140,35 @@ trait Bar {
"#,
);
}
+
+ #[test]
+ fn inactive_fields_and_variants() {
+ check(
+ r#"
+enum Foo {
+ #[cfg(a)] Bar,
+//^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+ Baz {
+ #[cfg(a)] baz: String,
+ //^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+ },
+ Qux(#[cfg(a)] String),
+ //^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+
+struct Baz {
+ #[cfg(a)] baz: String,
+//^^^^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+
+struct Qux(#[cfg(a)] String);
+ //^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+
+union FooBar {
+ #[cfg(a)] baz: u32,
+//^^^^^^^^^^^^^^^^^^ weak: code is inactive due to #[cfg] directives: a is disabled
+}
+"#,
+ );
+ }
}
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 a21db5b2c..303429519 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
@@ -137,6 +137,7 @@ pub(crate) fn json_in_items(
sema.db,
it,
config.insert_use.prefix_kind,
+ config.prefer_no_std,
) {
insert_use(
&scope,
@@ -152,6 +153,7 @@ pub(crate) fn json_in_items(
sema.db,
it,
config.insert_use.prefix_kind,
+ config.prefer_no_std,
) {
insert_use(
&scope,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index edb1fc091..7f140eb6a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -124,6 +124,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
let type_path = current_module?.find_use_path(
ctx.sema.db,
item_for_path_search(ctx.sema.db, item_in_ns)?,
+ ctx.config.prefer_no_std,
)?;
use_trivial_constructor(
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
index 6bf90e645..62c69f90b 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/type_mismatch.rs
@@ -59,9 +59,6 @@ fn add_reference(
d: &hir::TypeMismatch,
acc: &mut Vec<Assist>,
) -> Option<()> {
- let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
- let expr_node = d.expr.value.to_node(&root);
-
let range = ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range;
let (_, mutability) = d.expected.as_reference()?;
@@ -72,7 +69,7 @@ fn add_reference(
let ampersands = format!("&{}", mutability.as_keyword_for_ref());
- let edit = TextEdit::insert(expr_node.syntax().text_range().start(), ampersands);
+ let edit = TextEdit::insert(range.start(), ampersands);
let source_change =
SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
acc.push(fix("add_reference_here", "Add reference here", source_change, range));
@@ -315,6 +312,34 @@ fn main() {
}
#[test]
+ fn test_add_reference_to_macro_call() {
+ check_fix(
+ r#"
+macro_rules! thousand {
+ () => {
+ 1000_u64
+ };
+}
+fn test(foo: &u64) {}
+fn main() {
+ test($0thousand!());
+}
+ "#,
+ r#"
+macro_rules! thousand {
+ () => {
+ 1000_u64
+ };
+}
+fn test(foo: &u64) {}
+fn main() {
+ test(&thousand!());
+}
+ "#,
+ );
+ }
+
+ #[test]
fn test_add_mutable_reference_to_let_stmt() {
check_fix(
r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 61e63ea7a..ae299f058 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -150,6 +150,7 @@ pub struct DiagnosticsConfig {
pub expr_fill_default: ExprFillDefaultMode,
// FIXME: We may want to include a whole `AssistConfig` here
pub insert_use: InsertUseConfig,
+ pub prefer_no_std: bool,
}
impl DiagnosticsConfig {
@@ -170,6 +171,7 @@ impl DiagnosticsConfig {
group: false,
skip_glob_imports: false,
},
+ prefer_no_std: false,
}
}
}
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 73314e0f3..4baf786c4 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -12,8 +12,7 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-
-itertools = "0.10.3"
+itertools = "0.10.5"
text-edit = { path = "../text-edit", version = "0.0.0" }
parser = { path = "../parser", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index e3a837ddc..57b5ab6ab 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -648,9 +648,10 @@ impl Match {
.module();
for (path, resolved_path) in &template.resolved_paths {
if let hir::PathResolution::Def(module_def) = resolved_path.resolution {
- let mod_path = module.find_use_path(sema.db, module_def).ok_or_else(|| {
- match_error!("Failed to render template path `{}` at match location")
- })?;
+ let mod_path =
+ module.find_use_path(sema.db, module_def, false).ok_or_else(|| {
+ match_error!("Failed to render template path `{}` at match location")
+ })?;
self.rendered_template_paths.insert(path.clone(), mod_path);
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 0e9771cd2..712459a7e 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -13,12 +13,12 @@ doctest = false
cov-mark = "2.0.0-pre.1"
crossbeam-channel = "0.5.5"
either = "1.7.0"
-itertools = "0.10.3"
+itertools = "0.10.5"
tracing = "0.1.35"
oorandom = "11.1.3"
-pulldown-cmark-to-cmark = "10.0.1"
+pulldown-cmark-to-cmark = "10.0.4"
pulldown-cmark = { version = "0.9.1", default-features = false }
-url = "2.2.2"
+url = "2.3.1"
dot = "0.1.4"
stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index 210c5c7fa..f994c284c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -8,13 +8,15 @@ use ide_db::{
use syntax::{ast::HasName, AstNode, TextRange};
use crate::{
- fn_references::find_all_methods,
+ annotations::fn_references::find_all_methods,
goto_implementation::goto_implementation,
references::find_all_refs,
runnables::{runnables, Runnable},
NavigationTarget, RunnableKind,
};
+mod fn_references;
+
// Feature: Annotations
//
// Provides user with annotations above items for looking up references or impl blocks
@@ -30,8 +32,8 @@ pub struct Annotation {
#[derive(Debug)]
pub enum AnnotationKind {
Runnable(Runnable),
- HasImpls { file_id: FileId, data: Option<Vec<NavigationTarget>> },
- HasReferences { file_id: FileId, data: Option<Vec<FileRange>> },
+ HasImpls { pos: FilePosition, data: Option<Vec<NavigationTarget>> },
+ HasReferences { pos: FilePosition, data: Option<Vec<FileRange>> },
}
pub struct AnnotationConfig {
@@ -41,6 +43,12 @@ pub struct AnnotationConfig {
pub annotate_references: bool,
pub annotate_method_references: bool,
pub annotate_enum_variant_references: bool,
+ pub location: AnnotationLocation,
+}
+
+pub enum AnnotationLocation {
+ AboveName,
+ AboveWholeItem,
}
pub(crate) fn annotations(
@@ -62,6 +70,16 @@ pub(crate) fn annotations(
}
}
+ let mk_ranges = |(range, focus): (_, Option<_>)| {
+ let cmd_target: TextRange = focus.unwrap_or(range);
+ let annotation_range = match config.location {
+ AnnotationLocation::AboveName => cmd_target,
+ AnnotationLocation::AboveWholeItem => range,
+ };
+ let target_pos = FilePosition { file_id, offset: cmd_target.start() };
+ (annotation_range, target_pos)
+ };
+
visit_file_defs(&Semantics::new(db), file_id, &mut |def| {
let range = match def {
Definition::Const(konst) if config.annotate_references => {
@@ -81,9 +99,13 @@ pub(crate) fn annotations(
})
.flatten()
.for_each(|range| {
+ let (annotation_range, target_position) = mk_ranges(range);
annotations.push(Annotation {
- range,
- kind: AnnotationKind::HasReferences { file_id, data: None },
+ range: annotation_range,
+ kind: AnnotationKind::HasReferences {
+ pos: target_position,
+ data: None,
+ },
})
})
}
@@ -108,15 +130,18 @@ pub(crate) fn annotations(
Some(range) => range,
None => return,
};
-
+ let (annotation_range, target_pos) = mk_ranges(range);
if config.annotate_impls && !matches!(def, Definition::Const(_)) {
- annotations
- .push(Annotation { range, kind: AnnotationKind::HasImpls { file_id, data: None } });
+ annotations.push(Annotation {
+ range: annotation_range,
+ kind: AnnotationKind::HasImpls { pos: target_pos, data: None },
+ });
}
+
if config.annotate_references {
annotations.push(Annotation {
- range,
- kind: AnnotationKind::HasReferences { file_id, data: None },
+ range: annotation_range,
+ kind: AnnotationKind::HasReferences { pos: target_pos, data: None },
});
}
@@ -124,10 +149,13 @@ pub(crate) fn annotations(
db: &RootDatabase,
node: InFile<T>,
source_file_id: FileId,
- ) -> Option<TextRange> {
+ ) -> Option<(TextRange, Option<TextRange>)> {
if let Some(InFile { file_id, value }) = node.original_ast_node(db) {
if file_id == source_file_id.into() {
- return value.name().map(|it| it.syntax().text_range());
+ return Some((
+ value.syntax().text_range(),
+ value.name().map(|name| name.syntax().text_range()),
+ ));
}
}
None
@@ -135,12 +163,13 @@ pub(crate) fn annotations(
});
if config.annotate_method_references {
- annotations.extend(find_all_methods(db, file_id).into_iter().map(
- |FileRange { file_id, range }| Annotation {
- range,
- kind: AnnotationKind::HasReferences { file_id, data: None },
- },
- ));
+ annotations.extend(find_all_methods(db, file_id).into_iter().map(|range| {
+ let (annotation_range, target_range) = mk_ranges(range);
+ Annotation {
+ range: annotation_range,
+ kind: AnnotationKind::HasReferences { pos: target_range, data: None },
+ }
+ }));
}
annotations
@@ -148,18 +177,11 @@ pub(crate) fn annotations(
pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) -> Annotation {
match annotation.kind {
- AnnotationKind::HasImpls { file_id, ref mut data } => {
- *data =
- goto_implementation(db, FilePosition { file_id, offset: annotation.range.start() })
- .map(|range| range.info);
+ AnnotationKind::HasImpls { pos, ref mut data } => {
+ *data = goto_implementation(db, pos).map(|range| range.info);
}
- AnnotationKind::HasReferences { file_id, ref mut data } => {
- *data = find_all_refs(
- &Semantics::new(db),
- FilePosition { file_id, offset: annotation.range.start() },
- None,
- )
- .map(|result| {
+ AnnotationKind::HasReferences { pos, ref mut data } => {
+ *data = find_all_refs(&Semantics::new(db), pos, None).map(|result| {
result
.into_iter()
.flat_map(|res| res.references)
@@ -188,21 +210,23 @@ mod tests {
use crate::{fixture, Annotation, AnnotationConfig};
- fn check(ra_fixture: &str, expect: Expect) {
+ use super::AnnotationLocation;
+
+ const DEFAULT_CONFIG: AnnotationConfig = AnnotationConfig {
+ binary_target: true,
+ annotate_runnables: true,
+ annotate_impls: true,
+ annotate_references: true,
+ annotate_method_references: true,
+ annotate_enum_variant_references: true,
+ location: AnnotationLocation::AboveName,
+ };
+
+ fn check_with_config(ra_fixture: &str, expect: Expect, config: &AnnotationConfig) {
let (analysis, file_id) = fixture::file(ra_fixture);
let annotations: Vec<Annotation> = analysis
- .annotations(
- &AnnotationConfig {
- binary_target: true,
- annotate_runnables: true,
- annotate_impls: true,
- annotate_references: true,
- annotate_method_references: true,
- annotate_enum_variant_references: true,
- },
- file_id,
- )
+ .annotations(config, file_id)
.unwrap()
.into_iter()
.map(|annotation| analysis.resolve_annotation(annotation).unwrap())
@@ -211,6 +235,10 @@ mod tests {
expect.assert_debug_eq(&annotations);
}
+ fn check(ra_fixture: &str, expect: Expect) {
+ check_with_config(ra_fixture, expect, &DEFAULT_CONFIG);
+ }
+
#[test]
fn const_annotations() {
check(
@@ -247,9 +275,12 @@ fn main() {
Annotation {
range: 6..10,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 6,
+ },
data: Some(
[
FileRange {
@@ -265,9 +296,12 @@ fn main() {
Annotation {
range: 30..36,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 30,
+ },
data: Some(
[],
),
@@ -276,9 +310,12 @@ fn main() {
Annotation {
range: 53..57,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 53,
+ },
data: Some(
[],
),
@@ -323,9 +360,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasImpls {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[],
),
@@ -334,9 +374,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[
FileRange {
@@ -352,9 +395,12 @@ fn main() {
Annotation {
range: 17..21,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 17,
+ },
data: Some(
[],
),
@@ -403,9 +449,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasImpls {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[
NavigationTarget {
@@ -424,9 +473,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[
FileRange {
@@ -448,9 +500,12 @@ fn main() {
Annotation {
range: 20..31,
kind: HasImpls {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 20,
+ },
data: Some(
[
NavigationTarget {
@@ -469,9 +524,12 @@ fn main() {
Annotation {
range: 20..31,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 20,
+ },
data: Some(
[
FileRange {
@@ -487,9 +545,12 @@ fn main() {
Annotation {
range: 69..73,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 69,
+ },
data: Some(
[],
),
@@ -530,9 +591,12 @@ fn main() {}
Annotation {
range: 3..7,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 3,
+ },
data: Some(
[],
),
@@ -581,9 +645,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasImpls {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[
NavigationTarget {
@@ -602,9 +669,12 @@ fn main() {
Annotation {
range: 7..11,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 7,
+ },
data: Some(
[
FileRange {
@@ -626,9 +696,12 @@ fn main() {
Annotation {
range: 33..44,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 33,
+ },
data: Some(
[
FileRange {
@@ -644,9 +717,12 @@ fn main() {
Annotation {
range: 61..65,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 61,
+ },
data: Some(
[],
),
@@ -740,9 +816,12 @@ mod tests {
Annotation {
range: 3..7,
kind: HasReferences {
- file_id: FileId(
- 0,
- ),
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 3,
+ },
data: Some(
[],
),
@@ -786,4 +865,48 @@ m!();
"#]],
);
}
+
+ #[test]
+ fn test_annotations_appear_above_whole_item_when_configured_to_do_so() {
+ check_with_config(
+ r#"
+/// This is a struct named Foo, obviously.
+#[derive(Clone)]
+struct Foo;
+"#,
+ expect![[r#"
+ [
+ Annotation {
+ range: 0..71,
+ kind: HasImpls {
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 67,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ Annotation {
+ range: 0..71,
+ kind: HasReferences {
+ pos: FilePosition {
+ file_id: FileId(
+ 0,
+ ),
+ offset: 67,
+ },
+ data: Some(
+ [],
+ ),
+ },
+ },
+ ]
+ "#]],
+ &AnnotationConfig { location: AnnotationLocation::AboveWholeItem, ..DEFAULT_CONFIG },
+ );
+ }
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/fn_references.rs b/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs
index 63fb322ce..0cadf125f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/fn_references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations/fn_references.rs
@@ -4,30 +4,38 @@
use hir::Semantics;
use ide_assists::utils::test_related_attribute;
use ide_db::RootDatabase;
-use syntax::{ast, ast::HasName, AstNode, SyntaxNode};
+use syntax::{ast, ast::HasName, AstNode, SyntaxNode, TextRange};
-use crate::{FileId, FileRange};
+use crate::FileId;
-pub(crate) fn find_all_methods(db: &RootDatabase, file_id: FileId) -> Vec<FileRange> {
+pub(super) fn find_all_methods(
+ db: &RootDatabase,
+ file_id: FileId,
+) -> Vec<(TextRange, Option<TextRange>)> {
let sema = Semantics::new(db);
let source_file = sema.parse(file_id);
- source_file.syntax().descendants().filter_map(|it| method_range(it, file_id)).collect()
+ source_file.syntax().descendants().filter_map(|it| method_range(it)).collect()
}
-fn method_range(item: SyntaxNode, file_id: FileId) -> Option<FileRange> {
+fn method_range(item: SyntaxNode) -> Option<(TextRange, Option<TextRange>)> {
ast::Fn::cast(item).and_then(|fn_def| {
if test_related_attribute(&fn_def).is_some() {
None
} else {
- fn_def.name().map(|name| FileRange { file_id, range: name.syntax().text_range() })
+ Some((
+ fn_def.syntax().text_range(),
+ fn_def.name().map(|name| name.syntax().text_range()),
+ ))
}
})
}
#[cfg(test)]
mod tests {
+ use syntax::TextRange;
+
use crate::fixture;
- use crate::{FileRange, TextSize};
+ use crate::TextSize;
use std::ops::RangeInclusive;
#[test]
@@ -42,7 +50,7 @@ mod tests {
"#,
);
- let refs = analysis.find_all_methods(pos.file_id).unwrap();
+ let refs = super::find_all_methods(&analysis.db, pos.file_id);
check_result(&refs, &[3..=13, 27..=33, 47..=57]);
}
@@ -57,7 +65,7 @@ mod tests {
"#,
);
- let refs = analysis.find_all_methods(pos.file_id).unwrap();
+ let refs = super::find_all_methods(&analysis.db, pos.file_id);
check_result(&refs, &[19..=22, 35..=38]);
}
@@ -78,17 +86,18 @@ mod tests {
"#,
);
- let refs = analysis.find_all_methods(pos.file_id).unwrap();
+ let refs = super::find_all_methods(&analysis.db, pos.file_id);
check_result(&refs, &[28..=34]);
}
- fn check_result(refs: &[FileRange], expected: &[RangeInclusive<u32>]) {
+ fn check_result(refs: &[(TextRange, Option<TextRange>)], expected: &[RangeInclusive<u32>]) {
assert_eq!(refs.len(), expected.len());
- for (i, item) in refs.iter().enumerate() {
+ for (i, &(full, focus)) in refs.iter().enumerate() {
let range = &expected[i];
- assert_eq!(TextSize::from(*range.start()), item.range.start());
- assert_eq!(TextSize::from(*range.end()), item.range.end());
+ let item = focus.unwrap_or(full);
+ assert_eq!(TextSize::from(*range.start()), item.start());
+ assert_eq!(TextSize::from(*range.end()), item.end());
}
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index 92ce26b42..d96827326 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -232,8 +232,13 @@ pub(crate) fn token_as_doc_comment(doc_token: &SyntaxToken) -> Option<DocComment
(match_ast! {
match doc_token {
ast::Comment(comment) => TextSize::try_from(comment.prefix().len()).ok(),
- ast::String(string) => doc_token.parent_ancestors().find_map(ast::Attr::cast)
- .filter(|attr| attr.simple_name().as_deref() == Some("doc")).and_then(|_| string.open_quote_text_range().map(|it| it.len())),
+ ast::String(string) => {
+ doc_token.parent_ancestors().find_map(ast::Attr::cast).filter(|attr| attr.simple_name().as_deref() == Some("doc"))?;
+ if doc_token.parent_ancestors().find_map(ast::MacroCall::cast).filter(|mac| mac.path().and_then(|p| p.segment()?.name_ref()).as_ref().map(|n| n.text()).as_deref() == Some("include_str")).is_some() {
+ return None;
+ }
+ string.open_quote_text_range().map(|it| it.len())
+ },
_ => None,
}
}).map(|prefix_len| DocCommentToken { prefix_len, doc_token: doc_token.clone() })
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 36a648fe4..d0be1b3f4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -48,10 +48,14 @@ pub(crate) fn goto_definition(
_ => 1,
})?;
if let Some(doc_comment) = token_as_doc_comment(&original_token) {
- return doc_comment.get_definition_with_descend_at(sema, position.offset, |def, _, _| {
- let nav = def.try_to_nav(db)?;
- Some(RangeInfo::new(original_token.text_range(), vec![nav]))
- });
+ return doc_comment.get_definition_with_descend_at(
+ sema,
+ position.offset,
+ |def, _, link_range| {
+ let nav = def.try_to_nav(db)?;
+ Some(RangeInfo::new(link_range, vec![nav]))
+ },
+ );
}
let navs = sema
.descend_into_macros(original_token.clone())
@@ -95,6 +99,14 @@ fn try_lookup_include_path(
if !matches!(&*name.text(), "include" | "include_str" | "include_bytes") {
return None;
}
+
+ // Ignore non-built-in macros to account for shadowing
+ if let Some(it) = sema.resolve_macro_call(&macro_call) {
+ if !matches!(it.kind(sema.db), hir::MacroKind::BuiltIn) {
+ return None;
+ }
+ }
+
let file_id = sema.db.resolve_path(AnchoredPath { anchor: file_id, path: &path })?;
let size = sema.db.file_text(file_id).len().try_into().ok()?;
Some(NavigationTarget {
@@ -156,9 +168,6 @@ mod tests {
fn check(ra_fixture: &str) {
let (analysis, position, expected) = fixture::annotations(ra_fixture);
let navs = analysis.goto_definition(position).unwrap().expect("no definition found").info;
- if navs.is_empty() {
- panic!("unresolved reference")
- }
let cmp = |&FileRange { file_id, range }: &_| (file_id, range.start());
let navs = navs
@@ -1348,6 +1357,10 @@ fn f(e: Enum) {
check(
r#"
//- /main.rs
+
+#[rustc_builtin_macro]
+macro_rules! include_str {}
+
fn main() {
let str = include_str!("foo.txt$0");
}
@@ -1357,6 +1370,42 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn goto_doc_include_str() {
+ check(
+ r#"
+//- /main.rs
+#[rustc_builtin_macro]
+macro_rules! include_str {}
+
+#[doc = include_str!("docs.md$0")]
+struct Item;
+
+//- /docs.md
+// docs
+//^file
+"#,
+ );
+ }
+
+ #[test]
+ fn goto_shadow_include() {
+ check(
+ r#"
+//- /main.rs
+macro_rules! include {
+ ("included.rs") => {}
+}
+
+include!("included.rs$0");
+
+//- /included.rs
+// empty
+"#,
+ );
+ }
+
#[cfg(test)]
mod goto_impl_of_trait_fn {
use super::check;
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 f190da326..540a11583 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -377,6 +377,7 @@ mod tests {
match it {
ReferenceCategory::Read => "read",
ReferenceCategory::Write => "write",
+ ReferenceCategory::Import => "import",
}
.to_string()
}),
@@ -423,12 +424,12 @@ struct Foo;
check(
r#"
use crate$0;
- //^^^^^
+ //^^^^^ import
use self;
- //^^^^
+ //^^^^ import
mod __ {
use super;
- //^^^^^
+ //^^^^^ import
}
"#,
);
@@ -436,7 +437,7 @@ mod __ {
r#"
//- /main.rs crate:main deps:lib
use lib$0;
- //^^^
+ //^^^ import
//- /lib.rs crate:lib
"#,
);
@@ -450,7 +451,7 @@ use lib$0;
mod foo;
//- /foo.rs
use self$0;
- // ^^^^
+ // ^^^^ import
"#,
);
}
@@ -1375,4 +1376,20 @@ fn main() {
"#,
);
}
+
+ #[test]
+ fn test_assoc_type_highlighting() {
+ check(
+ r#"
+trait Trait {
+ type Output;
+ // ^^^^^^
+}
+impl Trait for () {
+ type Output$0 = ();
+ // ^^^^^^
+}
+"#,
+ );
+ }
}
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 c5c50d88d..d109c0769 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -346,7 +346,16 @@ pub(super) fn definition(
Definition::Module(it) => label_and_docs(db, it),
Definition::Function(it) => label_and_docs(db, it),
Definition::Adt(it) => label_and_docs(db, it),
- Definition::Variant(it) => label_and_docs(db, it),
+ Definition::Variant(it) => label_value_and_docs(db, it, |&it| {
+ if !it.parent_enum(db).is_data_carrying(db) {
+ match it.eval(db) {
+ Ok(x) => Some(format!("{}", x)),
+ Err(_) => it.value(db).map(|x| format!("{:?}", x)),
+ }
+ } else {
+ None
+ }
+ }),
Definition::Const(it) => label_value_and_docs(db, it, |it| {
let body = it.eval(db);
match body {
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 4b8b47783..eb997e6fe 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -698,6 +698,7 @@ fn hover_enum_variant() {
check(
r#"
enum Option<T> {
+ Some(T)
/// The None variant
Non$0e
}
@@ -3528,6 +3529,112 @@ impl<const LEN: usize> Foo<LEN$0> {}
}
#[test]
+fn hover_const_eval_variant() {
+ // show hex for <10
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ /// This is a doc
+ A$0 = 1 << 3,
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 8
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+ // show hex for >10
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ /// This is a doc
+ A$0 = (1 << 3) + (1 << 2),
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 12 (0xC)
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+ // enums in const eval
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ A = 1,
+ /// This is a doc
+ B$0 = E::A as u8 + 1,
+}
+"#,
+ expect![[r#"
+ *B*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ B = 2
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+ // unspecified variant should increment by one
+ check(
+ r#"
+#[repr(u8)]
+enum E {
+ A = 4,
+ /// This is a doc
+ B$0,
+}
+"#,
+ expect![[r#"
+ *B*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ B = 5
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
+}
+
+#[test]
fn hover_const_eval() {
// show hex for <10
check(
@@ -3823,6 +3930,35 @@ fn foo() {
This is a doc
"#]],
);
+ check(
+ r#"
+enum E {
+ /// This is a doc
+ A = 3,
+}
+fn foo(e: E) {
+ match e {
+ E::A$0 => (),
+ _ => ()
+ }
+}
+"#,
+ expect![[r#"
+ *A*
+
+ ```rust
+ test::E
+ ```
+
+ ```rust
+ A = 3
+ ```
+
+ ---
+
+ This is a doc
+ "#]],
+ );
}
#[test]
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 d1b1d2c33..34d8bf67a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -176,12 +176,6 @@ impl fmt::Debug for InlayHintLabelPart {
// * elided lifetimes
// * compiler inserted reborrows
//
-// |===
-// | Editor | Action Name
-//
-// | VS Code | **rust-analyzer: Toggle inlay hints*
-// |===
-//
// image::https://user-images.githubusercontent.com/48062697/113020660-b5f98b80-917a-11eb-8d70-3be3fd558cdd.png[]
pub(crate) fn inlay_hints(
db: &RootDatabase,
@@ -1688,6 +1682,74 @@ fn main() {
}
#[test]
+ 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 },
+ r#"
+//- minicore: iterators
+struct S<T>(T);
+impl<T> S<T> {
+ fn iter(&self) -> Iter<'_, T> { loop {} }
+}
+struct Iter<'a, T: 'a>(&'a T);
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+ fn next(&mut self) -> Option<Self::Item> { loop {} }
+}
+struct Container<'a> {
+ elements: S<&'a str>,
+}
+struct SliceIter<'a, T>(&'a T);
+impl<'a, T> Iterator for SliceIter<'a, T> {
+ type Item = &'a T;
+ fn next(&mut self) -> Option<Self::Item> { loop {} }
+}
+
+fn main(a: SliceIter<'_, Container>) {
+ a
+ .filter_map(|c| Some(c.elements.iter().filter_map(|v| Some(v))))
+ .map(|e| e);
+}
+ "#,
+ expect![[r#"
+ [
+ InlayHint {
+ range: 484..554,
+ kind: ChainingHint,
+ label: [
+ "impl Iterator<Item = impl Iterator<Item = &&str>>",
+ ],
+ tooltip: Some(
+ HoverRanged(
+ FileId(
+ 0,
+ ),
+ 484..554,
+ ),
+ ),
+ },
+ InlayHint {
+ range: 484..485,
+ kind: ChainingHint,
+ label: [
+ "SliceIter<Container>",
+ ],
+ tooltip: Some(
+ HoverRanged(
+ FileId(
+ 0,
+ ),
+ 484..485,
+ ),
+ ),
+ },
+ ]
+ "#]],
+ );
+ }
+
+ #[test]
fn infer_call_method_return_associated_types_with_generic() {
check_types(
r#"
@@ -1962,7 +2024,14 @@ impl<T> Vec<T> {
}
impl<T> IntoIterator for Vec<T> {
- type Item=T;
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+}
+
+struct IntoIter<T> {}
+
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
}
fn main() {
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 055233081..416817ca0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -31,7 +31,6 @@ mod highlight_related;
mod expand_macro;
mod extend_selection;
mod file_structure;
-mod fn_references;
mod folding_ranges;
mod goto_declaration;
mod goto_definition;
@@ -74,7 +73,7 @@ use syntax::SourceFile;
use crate::navigation_target::{ToNav, TryToNav};
pub use crate::{
- annotations::{Annotation, AnnotationConfig, AnnotationKind},
+ annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation},
call_hierarchy::CallItem,
expand_macro::ExpandedMacro,
file_structure::{StructureNode, StructureNodeKind},
@@ -236,7 +235,7 @@ impl Analysis {
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo { repo: None, name: None },
);
change.change_file(file_id, Some(Arc::new(text)));
change.set_crate_graph(crate_graph);
@@ -429,11 +428,6 @@ impl Analysis {
self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, search_scope))
}
- /// Finds all methods and free functions for the file. Does not return tests!
- pub fn find_all_methods(&self, file_id: FileId) -> Cancellable<Vec<FileRange>> {
- self.with_db(|db| fn_references::find_all_methods(db, file_id))
- }
-
/// Returns a short text describing element at position.
pub fn hover(
&self,
@@ -488,8 +482,18 @@ impl Analysis {
}
/// Returns crates this file belongs too.
- pub fn crate_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
- self.with_db(|db| parent_module::crate_for(db, file_id))
+ pub fn crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
+ self.with_db(|db| parent_module::crates_for(db, file_id))
+ }
+
+ /// Returns crates this file belongs too.
+ pub fn transitive_rev_deps(&self, crate_id: CrateId) -> Cancellable<Vec<CrateId>> {
+ self.with_db(|db| db.crate_graph().transitive_rev_deps(crate_id).collect())
+ }
+
+ /// Returns crates this file *might* belong too.
+ pub fn relevant_crates_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> {
+ self.with_db(|db| db.relevant_crates(file_id).iter().copied().collect())
}
/// Returns the edition of the given crate.
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 600a52630..852a8fd83 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -253,10 +253,14 @@ pub(crate) fn def_to_moniker(
},
kind: if krate == from_crate { MonikerKind::Export } else { MonikerKind::Import },
package_information: {
- let name = krate.display_name(db)?.to_string();
- let (repo, version) = match krate.origin(db) {
- CrateOrigin::CratesIo { repo } => (repo?, krate.version(db)?),
+ let (name, repo, version) = match krate.origin(db) {
+ CrateOrigin::CratesIo { repo, name } => (
+ name.unwrap_or(krate.display_name(db)?.canonical_name().to_string()),
+ repo?,
+ krate.version(db)?,
+ ),
CrateOrigin::Lang(lang) => (
+ krate.display_name(db)?.canonical_name().to_string(),
"https://github.com/rust-lang/rust/".to_string(),
match lang {
LangCrateOrigin::Other => {
diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
index 8f3cc8687..506f9452c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
@@ -1,6 +1,6 @@
-use hir::Semantics;
+use hir::{db::DefDatabase, Semantics};
use ide_db::{
- base_db::{CrateId, FileId, FilePosition},
+ base_db::{CrateId, FileId, FileLoader, FilePosition},
RootDatabase,
};
use itertools::Itertools;
@@ -55,9 +55,13 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
}
/// Returns `Vec` for the same reason as `parent_module`
-pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
- let sema = Semantics::new(db);
- sema.to_module_defs(file_id).map(|module| module.krate().into()).unique().collect()
+pub(crate) fn crates_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
+ db.relevant_crates(file_id)
+ .iter()
+ .copied()
+ .filter(|&crate_id| db.crate_def_map(crate_id).modules_for_file(file_id).next().is_some())
+ .sorted()
+ .collect()
}
#[cfg(test)]
@@ -147,7 +151,7 @@ $0
mod foo;
"#,
);
- assert_eq!(analysis.crate_for(file_id).unwrap().len(), 1);
+ assert_eq!(analysis.crates_for(file_id).unwrap().len(), 1);
}
#[test]
@@ -162,6 +166,6 @@ mod baz;
mod baz;
"#,
);
- assert_eq!(analysis.crate_for(file_id).unwrap().len(), 2);
+ assert_eq!(analysis.crates_for(file_id).unwrap().len(), 2);
}
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 99614b645..e942413c1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -742,7 +742,7 @@ pub struct Foo {
expect![[r#"
foo Module FileId(0) 0..8 4..7
- FileId(0) 14..17
+ FileId(0) 14..17 Import
"#]],
);
}
@@ -760,7 +760,7 @@ use self$0;
expect![[r#"
foo Module FileId(0) 0..8 4..7
- FileId(1) 4..8
+ FileId(1) 4..8 Import
"#]],
);
}
@@ -775,7 +775,7 @@ use self$0;
expect![[r#"
Module FileId(0) 0..10
- FileId(0) 4..8
+ FileId(0) 4..8 Import
"#]],
);
}
@@ -803,7 +803,7 @@ pub(super) struct Foo$0 {
expect![[r#"
Foo Struct FileId(2) 0..41 18..21
- FileId(1) 20..23
+ FileId(1) 20..23 Import
FileId(1) 47..50
"#]],
);
@@ -966,7 +966,7 @@ fn g() { f(); }
expect![[r#"
f Function FileId(0) 22..31 25..26
- FileId(1) 11..12
+ FileId(1) 11..12 Import
FileId(1) 24..25
"#]],
);
@@ -1424,9 +1424,9 @@ pub use level1::Foo;
expect![[r#"
Foo Struct FileId(0) 0..15 11..14
- FileId(1) 16..19
- FileId(2) 16..19
- FileId(3) 16..19
+ FileId(1) 16..19 Import
+ FileId(2) 16..19 Import
+ FileId(3) 16..19 Import
"#]],
);
}
@@ -1454,7 +1454,7 @@ lib::foo!();
expect![[r#"
foo Macro FileId(1) 0..61 29..32
- FileId(0) 46..49
+ FileId(0) 46..49 Import
FileId(2) 0..3
FileId(3) 5..8
"#]],
@@ -1617,7 +1617,7 @@ struct Foo;
expect![[r#"
derive_identity Derive FileId(2) 1..107 45..60
- FileId(0) 17..31
+ FileId(0) 17..31 Import
FileId(0) 56..70
"#]],
);
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 9e5eb9095..27ad1a948 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -210,9 +210,7 @@ fn get_definition(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> Opt
let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
if let Some(&[x]) = def.as_deref() {
return Some(x);
- } else {
- continue;
- };
+ }
}
None
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs
index f4d038744..20810c25b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/status.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/status.rs
@@ -45,7 +45,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
if let Some(file_id) = file_id {
format_to!(buf, "\nFile info:\n");
- let crates = crate::parent_module::crate_for(db, file_id);
+ let crates = crate::parent_module::crates_for(db, file_id);
if crates.is_empty() {
format_to!(buf, "Does not belong to any crate");
}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
index 9395e914c..e7d0a8be7 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
@@ -87,9 +87,9 @@ fn punctuation(
let parent = token.parent();
let parent_kind = parent.as_ref().map_or(EOF, SyntaxNode::kind);
match (kind, parent_kind) {
- (T![?], _) => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
+ (T![?], TRY_EXPR) => HlTag::Operator(HlOperator::Other) | HlMod::ControlFlow,
(T![&], BIN_EXPR) => HlOperator::Bitwise.into(),
- (T![&], _) => {
+ (T![&], REF_EXPR) => {
let h = HlTag::Operator(HlOperator::Other).into();
let is_unsafe = parent
.and_then(ast::RefExpr::cast)
@@ -100,7 +100,9 @@ fn punctuation(
h
}
}
- (T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.], _) => HlOperator::Other.into(),
+ (T![::] | T![->] | T![=>] | T![..] | T![..=] | T![=] | T![@] | T![.], _) => {
+ HlOperator::Other.into()
+ }
(T![!], MACRO_CALL | MACRO_RULES) => HlPunct::MacroBang.into(),
(T![!], NEVER_TYPE) => HlTag::BuiltinType.into(),
(T![!], PREFIX_EXPR) => HlOperator::Logical.into(),
@@ -129,7 +131,7 @@ fn punctuation(
(T![+=] | T![-=] | T![*=] | T![/=] | T![%=], BIN_EXPR) => {
Highlight::from(HlOperator::Arithmetic) | HlMod::Mutable
}
- (T![|] | T![&] | T![!] | T![^] | T![>>] | T![<<], BIN_EXPR) => HlOperator::Bitwise.into(),
+ (T![|] | T![&] | T![^] | T![>>] | T![<<], BIN_EXPR) => HlOperator::Bitwise.into(),
(T![|=] | T![&=] | T![^=] | T![>>=] | T![<<=], BIN_EXPR) => {
Highlight::from(HlOperator::Bitwise) | HlMod::Mutable
}
@@ -137,7 +139,6 @@ fn punctuation(
(T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=], BIN_EXPR) => {
HlOperator::Comparison.into()
}
- (_, PREFIX_EXPR | BIN_EXPR | RANGE_EXPR | RANGE_PAT | REST_PAT) => HlOperator::Other.into(),
(_, ATTR) => HlTag::AttributeBracket.into(),
(kind, _) => match kind {
T!['['] | T![']'] => HlPunct::Bracket,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index e07fd3925..9ed65fbc8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -48,15 +48,15 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public static">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
<span class="keyword">fn</span> <span class="function associated declaration static trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference trait">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference trait">t_is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public static trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference trait">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference trait">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span></code></pre> \ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index eef5baea9..18045f1f5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -125,7 +125,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="comment documentation">/// ```sh</span>
<span class="comment documentation">/// echo 1</span>
<span class="comment documentation">/// ```</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">foo</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">foo</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
<span class="bool_literal">true</span>
<span class="brace">}</span>
<span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index a97802cbb..9f2b1926b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -61,11 +61,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
<span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
<span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span>
<span class="brace">}</span>
@@ -75,11 +75,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="value_param">f</span><span class="operator">.</span><span class="function associated consuming">baz</span><span class="parenthesis">(</span><span class="self_keyword consuming mutable">self</span><span class="parenthesis">)</span>
<span class="brace">}</span>
- <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
+ <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="self_keyword mutable reference">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
<span class="brace">}</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
<span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span>
<span class="brace">}</span>
@@ -96,11 +96,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
<span class="brace">}</span>
- <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
+ <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="self_keyword mutable reference">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
<span class="brace">}</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
<span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
<span class="brace">}</span>
<span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index ced7d22f0..abcd80c28 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -42,7 +42,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
</style>
-<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="operator">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+<pre><code><span class="keyword">fn</span> <span class="function declaration">fixture</span><span class="parenthesis">(</span><span class="value_param declaration reference">ra_fixture</span><span class="colon">:</span> <span class="punctuation">&</span><span class="builtin_type">str</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
<span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
index 2d85fc8c9..f98e0b1cd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
@@ -45,8 +45,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<pre><code>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
<span class="keyword">struct</span> <span class="struct declaration">Foo</span><span class="angle">&lt;</span><span class="lifetime declaration">'a</span><span class="comma">,</span> <span class="lifetime declaration">'b</span><span class="comma">,</span> <span class="lifetime declaration">'c</span><span class="angle">&gt;</span> <span class="keyword">where</span> <span class="lifetime">'a</span><span class="colon">:</span> <span class="lifetime">'a</span><span class="comma">,</span> <span class="lifetime">'static</span><span class="colon">:</span> <span class="lifetime">'static</span> <span class="brace">{</span>
- <span class="field declaration">field</span><span class="colon">:</span> <span class="operator">&</span><span class="lifetime">'a</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
- <span class="field declaration">field2</span><span class="colon">:</span> <span class="operator">&</span><span class="lifetime">'static</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
+ <span class="field declaration">field</span><span class="colon">:</span> <span class="punctuation">&</span><span class="lifetime">'a</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
+ <span class="field declaration">field2</span><span class="colon">:</span> <span class="punctuation">&</span><span class="lifetime">'static</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
<span class="brace">}</span>
<span class="keyword">impl</span><span class="angle">&lt;</span><span class="lifetime declaration">'a</span><span class="angle">&gt;</span> <span class="struct">Foo</span><span class="angle">&lt;</span><span class="lifetime">'_</span><span class="comma">,</span> <span class="lifetime">'a</span><span class="comma">,</span> <span class="lifetime">'static</span><span class="angle">&gt;</span>
<span class="keyword">where</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index c627bc9b0..a626cda3f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -62,16 +62,16 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
<span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic<span class="parenthesis">(</span><span class="string_literal">"explicit panic"</span><span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
- <span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="colon">:</span>literal <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="operator control">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
+ <span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="colon">:</span>literal <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="punctuation">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
<span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic<span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
<span class="comment">// Use `panic_str` instead of `panic_display::&lt;&str&gt;` for non_fmt_panic lint.</span>
- <span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="colon">:</span>expr <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="operator control">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
+ <span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="colon">:</span>expr <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="punctuation">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
<span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_str<span class="parenthesis">(</span><span class="punctuation">$</span>msg<span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
<span class="comment">// Special-case the single-argument case for const_panic.</span>
- <span class="parenthesis">(</span><span class="string_literal">"{}"</span><span class="comma">,</span> <span class="punctuation">$</span>arg<span class="colon">:</span>expr <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="operator control">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
- <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_display<span class="parenthesis">(</span><span class="operator">&</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span>
+ <span class="parenthesis">(</span><span class="string_literal">"{}"</span><span class="comma">,</span> <span class="punctuation">$</span>arg<span class="colon">:</span>expr <span class="punctuation">$</span><span class="parenthesis">(</span><span class="comma">,</span><span class="parenthesis">)</span><span class="punctuation">?</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
+ <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_display<span class="parenthesis">(</span><span class="punctuation">&</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span>
<span class="parenthesis">)</span><span class="comma">,</span>
<span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="colon">:</span>expr<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span>
<span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panicking<span class="colon">:</span><span class="colon">:</span>panic_fmt<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>const_format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span>fmt<span class="comma">,</span> <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 0716bae75..1992bdc6a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -49,7 +49,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="brace">}</span>
<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
<span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
- <span class="punctuation">*</span><span class="parenthesis">(</span><span class="operator">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
+ <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
<span class="brace">}</span><span class="semicolon">;</span>
<span class="brace">}</span>
<span class="keyword">static</span> <span class="keyword">mut</span> <span class="static declaration mutable unsafe">MUT_GLOBAL</span><span class="colon">:</span> <span class="struct">Struct</span> <span class="operator">=</span> <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
@@ -63,7 +63,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">struct</span> <span class="struct declaration">Struct</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="builtin_type">i32</span> <span class="brace">}</span>
<span class="keyword">impl</span> <span class="struct">Struct</span> <span class="brace">{</span>
- <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+ <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">repr</span><span class="parenthesis attribute">(</span><span class="none attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
@@ -78,11 +78,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
<span class="keyword">fn</span> <span class="function declaration">unsafe_trait_bound</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="colon">:</span> <span class="trait">UnsafeTrait</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="type_param">T</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
<span class="brace">}</span>
<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
- <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+ <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
<span class="brace">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index 5ff3448a1..13cd89010 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
rustc-hash = "1.1.0"
-smallvec = "1.9.0"
+smallvec = "1.10.0"
tracing = "0.1.35"
syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index ac691578d..9c92bae6a 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -8,7 +8,7 @@ use syntax::{
use test_utils::{bench, bench_fixture, skip_slow_tests};
use crate::{
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
syntax_node_to_token_tree, DeclarativeMacro,
};
@@ -111,35 +111,35 @@ fn invocation_fixtures(rules: &FxHashMap<String, DeclarativeMacro>) -> Vec<(Stri
fn collect_from_op(op: &Op, parent: &mut tt::Subtree, seed: &mut usize) {
return match op {
- Op::Var { kind, .. } => match kind.as_ref().map(|it| it.as_str()) {
- Some("ident") => parent.token_trees.push(make_ident("foo")),
- Some("ty") => parent.token_trees.push(make_ident("Foo")),
- Some("tt") => parent.token_trees.push(make_ident("foo")),
- Some("vis") => parent.token_trees.push(make_ident("pub")),
- Some("pat") => parent.token_trees.push(make_ident("foo")),
- Some("path") => parent.token_trees.push(make_ident("foo")),
- Some("literal") => parent.token_trees.push(make_literal("1")),
- Some("expr") => parent.token_trees.push(make_ident("foo")),
- Some("lifetime") => {
+ Op::Var { kind, .. } => match kind.as_ref() {
+ Some(MetaVarKind::Ident) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Ty) => parent.token_trees.push(make_ident("Foo")),
+ Some(MetaVarKind::Tt) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Vis) => parent.token_trees.push(make_ident("pub")),
+ Some(MetaVarKind::Pat) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Path) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Literal) => parent.token_trees.push(make_literal("1")),
+ Some(MetaVarKind::Expr) => parent.token_trees.push(make_ident("foo")),
+ Some(MetaVarKind::Lifetime) => {
parent.token_trees.push(make_punct('\''));
parent.token_trees.push(make_ident("a"));
}
- Some("block") => {
+ Some(MetaVarKind::Block) => {
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None))
}
- Some("item") => {
+ Some(MetaVarKind::Item) => {
parent.token_trees.push(make_ident("fn"));
parent.token_trees.push(make_ident("foo"));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Brace, None));
}
- Some("meta") => {
+ Some(MetaVarKind::Meta) => {
parent.token_trees.push(make_ident("foo"));
parent.token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
}
None => (),
- Some(kind) => panic!("Unhandled kind {}", kind),
+ Some(kind) => panic!("Unhandled kind {:?}", kind),
},
Op::Leaf(leaf) => parent.token_trees.push(leaf.clone().into()),
Op::Repeat { tokens, kind, separator } => {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 1e1bfa550..100ec6bfb 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::{ExpandError, ExpandResult};
+use crate::{parser::MetaVarKind, ExpandError, ExpandResult};
pub(crate) fn expand_rules(
rules: &[crate::Rule],
@@ -104,6 +104,7 @@ enum Binding {
Fragment(Fragment),
Nested(Vec<Binding>),
Empty,
+ Missing(MetaVarKind),
}
#[derive(Debug, Clone, PartialEq, Eq)]
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 c1aa14d6b..3f656df25 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -66,7 +66,7 @@ use syntax::SmolStr;
use crate::{
expander::{Binding, Bindings, ExpandResult, Fragment},
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
tt_iter::TtIter,
ExpandError, MetaTemplate,
};
@@ -119,6 +119,7 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match {
.map(|it| match it {
Binding::Fragment(_) => 1,
Binding::Empty => 1,
+ Binding::Missing(_) => 1,
Binding::Nested(it) => count(it.iter()),
})
.sum()
@@ -130,6 +131,7 @@ enum BindingKind {
Empty(SmolStr),
Optional(SmolStr),
Fragment(SmolStr, Fragment),
+ Missing(SmolStr, MetaVarKind),
Nested(usize, usize),
}
@@ -190,6 +192,10 @@ impl BindingsBuilder {
.push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
}
+ fn push_missing(&mut self, idx: &mut BindingsIdx, var: &SmolStr, kind: MetaVarKind) {
+ self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Missing(var.clone(), kind))));
+ }
+
fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) {
let BindingsIdx(idx, nidx) = self.copy(child);
self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx))));
@@ -203,17 +209,16 @@ impl BindingsBuilder {
}
fn build(self, idx: &BindingsIdx) -> Bindings {
- let mut bindings = Bindings::default();
- self.build_inner(&mut bindings, &self.nodes[idx.0]);
- bindings
+ self.build_inner(&self.nodes[idx.0])
}
- fn build_inner(&self, bindings: &mut Bindings, link_nodes: &[LinkNode<Rc<BindingKind>>]) {
+ fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind>>]) -> Bindings {
+ let mut bindings = Bindings::default();
let mut nodes = Vec::new();
self.collect_nodes(link_nodes, &mut nodes);
for cmd in nodes {
- match &**cmd {
+ match cmd {
BindingKind::Empty(name) => {
bindings.push_empty(name);
}
@@ -223,6 +228,9 @@ impl BindingsBuilder {
BindingKind::Fragment(name, fragment) => {
bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone()));
}
+ BindingKind::Missing(name, kind) => {
+ bindings.inner.insert(name.clone(), Binding::Missing(*kind));
+ }
BindingKind::Nested(idx, nested_idx) => {
let mut nested_nodes = Vec::new();
self.collect_nested(*idx, *nested_idx, &mut nested_nodes);
@@ -246,13 +254,15 @@ impl BindingsBuilder {
}
}
}
+
+ bindings
}
fn collect_nested_ref<'a>(
&'a self,
id: usize,
len: usize,
- nested_refs: &mut Vec<&'a Vec<LinkNode<Rc<BindingKind>>>>,
+ nested_refs: &mut Vec<&'a [LinkNode<Rc<BindingKind>>]>,
) {
self.nested[id].iter().take(len).for_each(|it| match it {
LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
@@ -262,26 +272,16 @@ impl BindingsBuilder {
fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
let last = &self.nodes[idx];
- let mut nested_refs = Vec::new();
+ let mut nested_refs: Vec<&[_]> = Vec::new();
self.nested[nested_idx].iter().for_each(|it| match *it {
LinkNode::Node(idx) => nested_refs.push(&self.nodes[idx]),
LinkNode::Parent { idx, len } => self.collect_nested_ref(idx, len, &mut nested_refs),
});
nested_refs.push(last);
-
- nested_refs.into_iter().for_each(|iter| {
- let mut child_bindings = Bindings::default();
- self.build_inner(&mut child_bindings, iter);
- nested.push(child_bindings)
- })
+ nested.extend(nested_refs.into_iter().map(|iter| self.build_inner(iter)));
}
- fn collect_nodes_ref<'a>(
- &'a self,
- id: usize,
- len: usize,
- nodes: &mut Vec<&'a Rc<BindingKind>>,
- ) {
+ fn collect_nodes_ref<'a>(&'a self, id: usize, len: usize, nodes: &mut Vec<&'a BindingKind>) {
self.nodes[id].iter().take(len).for_each(|it| match it {
LinkNode::Node(it) => nodes.push(it),
LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
@@ -291,7 +291,7 @@ impl BindingsBuilder {
fn collect_nodes<'a>(
&'a self,
link_nodes: &'a [LinkNode<Rc<BindingKind>>],
- nodes: &mut Vec<&'a Rc<BindingKind>>,
+ nodes: &mut Vec<&'a BindingKind>,
) {
link_nodes.iter().for_each(|it| match it {
LinkNode::Node(it) => nodes.push(it),
@@ -386,10 +386,10 @@ fn match_loop_inner<'t>(
let op = match item.dot.peek() {
None => {
// We are at or past the end of the matcher of `item`.
- if item.up.is_some() {
+ if let Some(up) = &item.up {
if item.sep_parsed.is_none() {
// Get the `up` matcher
- let mut new_pos = *item.up.clone().unwrap();
+ let mut new_pos = (**up).clone();
new_pos.bindings = bindings_builder.copy(&new_pos.bindings);
// Add matches from this repetition to the `matches` of `up`
bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings);
@@ -402,7 +402,7 @@ fn match_loop_inner<'t>(
// Check if we need a separator.
// We check the separator one by one
- let sep_idx = *item.sep_parsed.as_ref().unwrap_or(&0);
+ let sep_idx = item.sep_parsed.unwrap_or(0);
let sep_len = item.sep.as_ref().map_or(0, Separator::tt_count);
if item.sep.is_some() && sep_idx != sep_len {
let sep = item.sep.as_ref().unwrap();
@@ -467,9 +467,9 @@ fn match_loop_inner<'t>(
}
}
OpDelimited::Op(Op::Var { kind, name, .. }) => {
- if let Some(kind) = kind {
+ if let &Some(kind) = kind {
let mut fork = src.clone();
- let match_res = match_meta_var(kind.as_str(), &mut fork);
+ let match_res = match_meta_var(kind, &mut fork);
match match_res.err {
None => {
// Some meta variables are optional (e.g. vis)
@@ -484,8 +484,15 @@ fn match_loop_inner<'t>(
}
Some(err) => {
res.add_err(err);
- if let Some(fragment) = match_res.value {
- bindings_builder.push_fragment(&mut item.bindings, name, fragment);
+ match match_res.value {
+ Some(fragment) => bindings_builder.push_fragment(
+ &mut item.bindings,
+ name,
+ fragment,
+ ),
+ None => {
+ bindings_builder.push_missing(&mut item.bindings, name, kind)
+ }
}
item.is_error = true;
error_items.push(item);
@@ -677,20 +684,20 @@ fn match_leaf(lhs: &tt::Leaf, src: &mut TtIter<'_>) -> Result<(), ExpandError> {
}
}
-fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fragment>> {
+fn match_meta_var(kind: MetaVarKind, input: &mut TtIter<'_>) -> ExpandResult<Option<Fragment>> {
let fragment = match kind {
- "path" => parser::PrefixEntryPoint::Path,
- "ty" => parser::PrefixEntryPoint::Ty,
+ MetaVarKind::Path => parser::PrefixEntryPoint::Path,
+ MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
// FIXME: These two should actually behave differently depending on the edition.
//
// https://doc.rust-lang.org/edition-guide/rust-2021/or-patterns-macro-rules.html
- "pat" | "pat_param" => parser::PrefixEntryPoint::Pat,
- "stmt" => parser::PrefixEntryPoint::Stmt,
- "block" => parser::PrefixEntryPoint::Block,
- "meta" => parser::PrefixEntryPoint::MetaItem,
- "item" => parser::PrefixEntryPoint::Item,
- "vis" => parser::PrefixEntryPoint::Vis,
- "expr" => {
+ MetaVarKind::Pat | MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
+ MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
+ MetaVarKind::Block => parser::PrefixEntryPoint::Block,
+ MetaVarKind::Meta => parser::PrefixEntryPoint::MetaItem,
+ MetaVarKind::Item => parser::PrefixEntryPoint::Item,
+ MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
+ MetaVarKind::Expr => {
// `expr` should not match underscores.
// HACK: Macro expansion should not be done using "rollback and try another alternative".
// rustc [explicitly checks the next token][0].
@@ -707,17 +714,17 @@ fn match_meta_var(kind: &str, input: &mut TtIter<'_>) -> ExpandResult<Option<Fra
}
_ => {
let tt_result = match kind {
- "ident" => input
+ MetaVarKind::Ident => input
.expect_ident()
.map(|ident| tt::Leaf::from(ident.clone()).into())
.map_err(|()| ExpandError::binding_error("expected ident")),
- "tt" => input
+ MetaVarKind::Tt => input
.expect_tt()
.map_err(|()| ExpandError::binding_error("expected token tree")),
- "lifetime" => input
+ MetaVarKind::Lifetime => input
.expect_lifetime()
.map_err(|()| ExpandError::binding_error("expected lifetime")),
- "literal" => {
+ MetaVarKind::Literal => {
let neg = input.eat_char('-');
input
.expect_literal()
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 7bcc84740..cbb59ab8e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -6,7 +6,7 @@ use tt::{Delimiter, Subtree};
use crate::{
expander::{Binding, Bindings, Fragment},
- parser::{Op, RepeatKind, Separator},
+ parser::{MetaVarKind, Op, RepeatKind, Separator},
ExpandError, ExpandResult, MetaTemplate,
};
@@ -15,7 +15,7 @@ impl Bindings {
self.inner.contains_key(name)
}
- fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> {
+ fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<Fragment, ExpandError> {
macro_rules! binding_err {
($($arg:tt)*) => { ExpandError::binding_error(format!($($arg)*)) };
}
@@ -26,6 +26,7 @@ impl Bindings {
nesting_state.hit = true;
b = match b {
Binding::Fragment(_) => break,
+ Binding::Missing(_) => break,
Binding::Nested(bs) => bs.get(nesting_state.idx).ok_or_else(|| {
nesting_state.at_end = true;
binding_err!("could not find nested binding `{name}`")
@@ -37,7 +38,55 @@ impl Bindings {
};
}
match b {
- Binding::Fragment(it) => Ok(it),
+ Binding::Fragment(it) => Ok(it.clone()),
+ // emit some reasonable default expansion for missing bindings,
+ // this gives better recovery than emitting the `$fragment-name` verbatim
+ Binding::Missing(it) => Ok(match it {
+ MetaVarKind::Stmt => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
+ id: 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(),
+ 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,
+ token_trees: vec![],
+ }))
+ }
+ MetaVarKind::Path
+ | MetaVarKind::Ty
+ | MetaVarKind::Pat
+ | MetaVarKind::PatParam
+ | MetaVarKind::Expr
+ | MetaVarKind::Ident => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("missing"),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ MetaVarKind::Lifetime => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("'missing"),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ MetaVarKind::Literal => {
+ Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+ text: SmolStr::new_inline("\"missing\""),
+ id: tt::TokenId::unspecified(),
+ })))
+ }
+ }),
Binding::Nested(_) => {
Err(binding_err!("expected simple binding, found nested binding `{name}`"))
}
@@ -157,7 +206,7 @@ fn expand_var(ctx: &mut ExpandCtx<'_>, v: &SmolStr, id: tt::TokenId) -> ExpandRe
} else {
ctx.bindings.get(v, &mut ctx.nesting).map_or_else(
|e| ExpandResult { value: Fragment::Tokens(tt::TokenTree::empty()), err: Some(e) },
- |b| ExpandResult::ok(b.clone()),
+ |it| ExpandResult::ok(it),
)
}
}
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index 79da84f4a..c4f0fa20d 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -21,7 +21,7 @@ mod token_map;
use std::fmt;
use crate::{
- parser::{MetaTemplate, Op},
+ parser::{MetaTemplate, MetaVarKind, Op},
tt_iter::TtIter,
};
@@ -291,9 +291,9 @@ fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
// Checks that no repetition which could match an empty token
// https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
let lsh_is_empty_seq = separator.is_none() && subtree.iter().all(|child_op| {
- match child_op {
+ match *child_op {
// vis is optional
- Op::Var { kind: Some(kind), .. } => kind == "vis",
+ Op::Var { kind: Some(kind), .. } => kind == MetaVarKind::Vis,
Op::Repeat {
kind: parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne,
..
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index acb4be584..351c359b7 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -50,7 +50,7 @@ impl MetaTemplate {
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum Op {
- Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
+ Var { name: SmolStr, kind: Option<MetaVarKind>, id: tt::TokenId },
Ignore { name: SmolStr, id: tt::TokenId },
Index { depth: u32 },
Repeat { tokens: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
@@ -65,6 +65,24 @@ pub(crate) enum RepeatKind {
ZeroOrOne,
}
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub(crate) enum MetaVarKind {
+ Path,
+ Ty,
+ Pat,
+ PatParam,
+ Stmt,
+ Block,
+ Meta,
+ Item,
+ Vis,
+ Expr,
+ Ident,
+ Tt,
+ Lifetime,
+ Literal,
+}
+
#[derive(Clone, Debug, Eq)]
pub(crate) enum Separator {
Literal(tt::Literal),
@@ -179,13 +197,30 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
Ok(res)
}
-fn eat_fragment_kind(src: &mut TtIter<'_>, mode: Mode) -> Result<Option<SmolStr>, ParseError> {
+fn eat_fragment_kind(src: &mut TtIter<'_>, mode: Mode) -> Result<Option<MetaVarKind>, ParseError> {
if let Mode::Pattern = mode {
src.expect_char(':').map_err(|()| ParseError::unexpected("missing fragment specifier"))?;
let ident = src
.expect_ident()
.map_err(|()| ParseError::unexpected("missing fragment specifier"))?;
- return Ok(Some(ident.text.clone()));
+ let kind = match ident.text.as_str() {
+ "path" => MetaVarKind::Path,
+ "ty" => MetaVarKind::Ty,
+ "pat" => MetaVarKind::Pat,
+ "pat_param" => MetaVarKind::PatParam,
+ "stmt" => MetaVarKind::Stmt,
+ "block" => MetaVarKind::Block,
+ "meta" => MetaVarKind::Meta,
+ "item" => MetaVarKind::Item,
+ "vis" => MetaVarKind::Vis,
+ "expr" => MetaVarKind::Expr,
+ "ident" => MetaVarKind::Ident,
+ "tt" => MetaVarKind::Tt,
+ "lifetime" => MetaVarKind::Lifetime,
+ "literal" => MetaVarKind::Literal,
+ _ => return Ok(None),
+ };
+ return Ok(Some(kind));
};
Ok(None)
}
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 85a1c13fe..54879c187 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -19,7 +19,7 @@ object = { version = "0.29.0", default-features = false, features = [
] }
serde = { version = "1.0.137", features = ["derive"] }
serde_json = { version = "1.0.81", features = ["unbounded_depth"] }
-tracing = "0.1.35"
+tracing = "0.1.37"
memmap2 = "0.5.4"
snap = "1.0.5"
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 44712f419..243972b04 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
@@ -11,6 +11,8 @@ use proc_macro_api::ProcMacroKind;
use super::PanicMessage;
+pub use ra_server::TokenStream;
+
pub(crate) struct Abi {
exported_macros: Vec<proc_macro::bridge::client::ProcMacro>,
}
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 f7d3a3091..2f854bc15 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
@@ -32,8 +32,8 @@ mod abi_sysroot;
include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
// Used by `test/utils.rs`
-#[cfg(test)]
-pub(crate) use abi_1_63::TokenStream as TestTokenStream;
+#[cfg(all(test, feature = "sysroot-abi"))]
+pub(crate) use abi_sysroot::TokenStream as TestTokenStream;
use super::dylib::LoadProcMacroDylibError;
pub(crate) use abi_1_58::Abi as Abi_1_58;
@@ -144,3 +144,10 @@ impl Abi {
}
}
}
+
+#[test]
+fn test_version_check() {
+ let path = paths::AbsPathBuf::assert(crate::proc_macro_test_dylib_path());
+ let info = proc_macro_api::read_dylib_info(&path).unwrap();
+ assert!(info.version.1 >= 50);
+}
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 3679bfc43..72a2dfe72 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
@@ -20,6 +20,8 @@
mod dylib;
mod abis;
+pub mod cli;
+
use std::{
collections::{hash_map::Entry, HashMap},
env,
@@ -149,7 +151,10 @@ impl EnvSnapshot {
}
}
-pub mod cli;
+#[cfg(all(feature = "sysroot-abi", test))]
+mod tests;
#[cfg(test)]
-mod tests;
+pub fn proc_macro_test_dylib_path() -> std::path::PathBuf {
+ proc_macro_test::PROC_MACRO_TEST_LOCATION.into()
+}
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 6339d56d0..b46cdddcf 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
@@ -2,10 +2,10 @@
#[macro_use]
mod utils;
-use expect_test::expect;
-use paths::AbsPathBuf;
use utils::*;
+use expect_test::expect;
+
#[test]
fn test_derive_empty() {
assert_expand("DeriveEmpty", r#"struct S;"#, expect![[r#"SUBTREE $"#]]);
@@ -157,10 +157,3 @@ fn list_test_macros() {
DeriveError [CustomDerive]"#]]
.assert_eq(&res);
}
-
-#[test]
-fn test_version_check() {
- let path = AbsPathBuf::assert(fixtures::proc_macro_test_dylib_path());
- let info = proc_macro_api::read_dylib_info(&path).unwrap();
- assert!(info.version.1 >= 50);
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
index f881fe868..44b1b6588 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
@@ -1,15 +1,9 @@
//! utils used in proc-macro tests
-use crate::dylib;
-use crate::ProcMacroSrv;
use expect_test::Expect;
use std::str::FromStr;
-pub mod fixtures {
- pub fn proc_macro_test_dylib_path() -> std::path::PathBuf {
- proc_macro_test::PROC_MACRO_TEST_LOCATION.into()
- }
-}
+use crate::{dylib, proc_macro_test_dylib_path, ProcMacroSrv};
fn parse_string(code: &str) -> Option<crate::abis::TestTokenStream> {
// This is a bit strange. We need to parse a string into a token stream into
@@ -30,7 +24,7 @@ pub fn assert_expand_attr(macro_name: &str, ra_fixture: &str, attr_args: &str, e
}
fn assert_expand_impl(macro_name: &str, input: &str, attr: Option<&str>, expect: Expect) {
- let path = fixtures::proc_macro_test_dylib_path();
+ let path = proc_macro_test_dylib_path();
let expander = dylib::Expander::new(&path).unwrap();
let fixture = parse_string(input).unwrap();
let attr = attr.map(|attr| parse_string(attr).unwrap().into_subtree());
@@ -40,7 +34,7 @@ fn assert_expand_impl(macro_name: &str, input: &str, attr: Option<&str>, expect:
}
pub(crate) fn list() -> Vec<String> {
- let dylib_path = fixtures::proc_macro_test_dylib_path();
+ let dylib_path = proc_macro_test_dylib_path();
let mut srv = ProcMacroSrv::default();
let res = srv.list_macros(&dylib_path).unwrap();
res.into_iter().map(|(name, kind)| format!("{} [{:?}]", name, kind)).collect()
diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml
index 0b78a45a2..5697aea96 100644
--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml
@@ -10,9 +10,9 @@ rust-version = "1.57"
doctest = false
[dependencies]
-once_cell = "1.12.0"
+once_cell = "1.15.0"
cfg-if = "1.0.0"
-libc = "0.2.126"
+libc = "0.2.135"
la-arena = { version = "0.3.0", path = "../../lib/la-arena" }
countme = { version = "3.0.1", features = ["enable"] }
jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true }
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index bc75d6faa..cf9868740 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -13,11 +13,10 @@ doctest = false
tracing = "0.1.35"
rustc-hash = "1.1.0"
cargo_metadata = "0.15.0"
-semver = "1.0.10"
+semver = "1.0.14"
serde = { version = "1.0.137", features = ["derive"] }
-serde_json = "1.0.81"
-anyhow = "1.0.57"
-expect-test = "1.4.0"
+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" }
@@ -26,3 +25,6 @@ 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" }
+
+[dev-dependencies]
+expect-test = "1.4.0"
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
index 84e772d16..a26a7c57a 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
@@ -6,7 +6,12 @@
//! This module implements this second part. We use "build script" terminology
//! here, but it covers procedural macros as well.
-use std::{cell::RefCell, io, path::PathBuf, process::Command};
+use std::{
+ cell::RefCell,
+ io, mem,
+ path::{self, PathBuf},
+ process::Command,
+};
use cargo_metadata::{camino::Utf8Path, Message};
use la_arena::ArenaMap;
@@ -15,11 +20,14 @@ use rustc_hash::FxHashMap;
use semver::Version;
use serde::Deserialize;
-use crate::{cfg_flag::CfgFlag, CargoConfig, CargoWorkspace, Package};
+use crate::{
+ cfg_flag::CfgFlag, CargoConfig, CargoFeatures, CargoWorkspace, InvocationLocation,
+ InvocationStrategy, Package,
+};
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct WorkspaceBuildScripts {
- outputs: ArenaMap<Package, Option<BuildScriptOutput>>,
+ outputs: ArenaMap<Package, BuildScriptOutput>,
error: Option<String>,
}
@@ -38,43 +46,71 @@ pub(crate) struct BuildScriptOutput {
pub(crate) proc_macro_dylib_path: Option<AbsPathBuf>,
}
+impl BuildScriptOutput {
+ fn is_unchanged(&self) -> bool {
+ self.cfgs.is_empty()
+ && self.envs.is_empty()
+ && self.out_dir.is_none()
+ && self.proc_macro_dylib_path.is_none()
+ }
+}
+
impl WorkspaceBuildScripts {
- fn build_command(config: &CargoConfig) -> Command {
- if let Some([program, args @ ..]) = config.run_build_script_command.as_deref() {
- let mut cmd = Command::new(program);
- cmd.args(args);
- return cmd;
- }
+ fn build_command(config: &CargoConfig) -> io::Result<Command> {
+ let mut cmd = match config.run_build_script_command.as_deref() {
+ Some([program, args @ ..]) => {
+ let mut cmd = Command::new(program);
+ cmd.args(args);
+ cmd
+ }
+ _ => {
+ let mut cmd = Command::new(toolchain::cargo());
- let mut cmd = Command::new(toolchain::cargo());
+ cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
- cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
+ // --all-targets includes tests, benches and examples in addition to the
+ // default lib and bins. This is an independent concept from the --targets
+ // flag below.
+ cmd.arg("--all-targets");
- // --all-targets includes tests, benches and examples in addition to the
- // default lib and bins. This is an independent concept from the --targets
- // flag below.
- cmd.arg("--all-targets");
+ if let Some(target) = &config.target {
+ cmd.args(&["--target", target]);
+ }
- if let Some(target) = &config.target {
- cmd.args(&["--target", target]);
- }
+ match &config.features {
+ CargoFeatures::All => {
+ cmd.arg("--all-features");
+ }
+ CargoFeatures::Selected { features, no_default_features } => {
+ if *no_default_features {
+ cmd.arg("--no-default-features");
+ }
+ if !features.is_empty() {
+ cmd.arg("--features");
+ cmd.arg(features.join(" "));
+ }
+ }
+ }
- if config.all_features {
- cmd.arg("--all-features");
- } else {
- if config.no_default_features {
- cmd.arg("--no-default-features");
- }
- if !config.features.is_empty() {
- cmd.arg("--features");
- cmd.arg(config.features.join(" "));
+ cmd
}
+ };
+
+ cmd.envs(&config.extra_env);
+ if config.wrap_rustc_in_build_scripts {
+ // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
+ // that to compile only proc macros and build scripts during the initial
+ // `cargo check`.
+ let myself = std::env::current_exe()?;
+ cmd.env("RUSTC_WRAPPER", myself);
+ cmd.env("RA_RUSTC_WRAPPER", "1");
}
- cmd
+ Ok(cmd)
}
- pub(crate) fn run(
+ /// Runs the build scripts for the given workspace
+ pub(crate) fn run_for_workspace(
config: &CargoConfig,
workspace: &CargoWorkspace,
progress: &dyn Fn(String),
@@ -82,15 +118,23 @@ impl WorkspaceBuildScripts {
) -> io::Result<WorkspaceBuildScripts> {
const RUST_1_62: Version = Version::new(1, 62, 0);
- match Self::run_(Self::build_command(config), config, workspace, progress) {
+ let current_dir = match &config.invocation_location {
+ InvocationLocation::Root(root) if config.run_build_script_command.is_some() => {
+ root.as_path()
+ }
+ _ => &workspace.workspace_root(),
+ }
+ .as_ref();
+
+ match Self::run_per_ws(Self::build_command(config)?, workspace, current_dir, progress) {
Ok(WorkspaceBuildScripts { error: Some(error), .. })
if toolchain.as_ref().map_or(false, |it| *it >= RUST_1_62) =>
{
// building build scripts failed, attempt to build with --keep-going so
// that we potentially get more build data
- let mut cmd = Self::build_command(config);
+ let mut cmd = Self::build_command(config)?;
cmd.args(&["-Z", "unstable-options", "--keep-going"]).env("RUSTC_BOOTSTRAP", "1");
- let mut res = Self::run_(cmd, config, workspace, progress)?;
+ let mut res = Self::run_per_ws(cmd, workspace, current_dir, progress)?;
res.error = Some(error);
Ok(res)
}
@@ -98,23 +142,90 @@ impl WorkspaceBuildScripts {
}
}
- fn run_(
- mut cmd: Command,
+ /// Runs the build scripts by invoking the configured command *once*.
+ /// This populates the outputs for all passed in workspaces.
+ pub(crate) fn run_once(
config: &CargoConfig,
- workspace: &CargoWorkspace,
+ workspaces: &[&CargoWorkspace],
progress: &dyn Fn(String),
- ) -> io::Result<WorkspaceBuildScripts> {
- if config.wrap_rustc_in_build_scripts {
- // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
- // that to compile only proc macros and build scripts during the initial
- // `cargo check`.
- let myself = std::env::current_exe()?;
- cmd.env("RUSTC_WRAPPER", myself);
- cmd.env("RA_RUSTC_WRAPPER", "1");
+ ) -> io::Result<Vec<WorkspaceBuildScripts>> {
+ assert_eq!(config.invocation_strategy, InvocationStrategy::Once);
+
+ let current_dir = match &config.invocation_location {
+ InvocationLocation::Root(root) => root,
+ InvocationLocation::Workspace => {
+ return Err(io::Error::new(
+ io::ErrorKind::Other,
+ "Cannot run build scripts from workspace with invocation strategy `once`",
+ ))
+ }
+ };
+ let cmd = Self::build_command(config)?;
+ // NB: Cargo.toml could have been modified between `cargo metadata` and
+ // `cargo check`. We shouldn't assume that package ids we see here are
+ // exactly those from `config`.
+ let mut by_id = FxHashMap::default();
+ // some workspaces might depend on the same crates, so we need to duplicate the outputs
+ // to those collisions
+ let mut collisions = Vec::new();
+ let mut res: Vec<_> = workspaces
+ .iter()
+ .enumerate()
+ .map(|(idx, workspace)| {
+ let mut res = WorkspaceBuildScripts::default();
+ for package in workspace.packages() {
+ res.outputs.insert(package, BuildScriptOutput::default());
+ if by_id.contains_key(&workspace[package].id) {
+ collisions.push((&workspace[package].id, idx, package));
+ } else {
+ by_id.insert(workspace[package].id.clone(), (package, idx));
+ }
+ }
+ res
+ })
+ .collect();
+
+ let errors = Self::run_command(
+ cmd,
+ current_dir.as_path().as_ref(),
+ |package, cb| {
+ if let Some(&(package, workspace)) = by_id.get(package) {
+ cb(&workspaces[workspace][package].name, &mut res[workspace].outputs[package]);
+ }
+ },
+ progress,
+ )?;
+ res.iter_mut().for_each(|it| it.error = errors.clone());
+ collisions.into_iter().for_each(|(id, workspace, package)| {
+ if let Some(&(p, w)) = by_id.get(id) {
+ res[workspace].outputs[package] = res[w].outputs[p].clone();
+ }
+ });
+
+ if tracing::enabled!(tracing::Level::INFO) {
+ for (idx, workspace) in workspaces.iter().enumerate() {
+ for package in workspace.packages() {
+ let package_build_data = &mut res[idx].outputs[package];
+ if !package_build_data.is_unchanged() {
+ tracing::info!(
+ "{}: {:?}",
+ workspace[package].manifest.parent().display(),
+ package_build_data,
+ );
+ }
+ }
+ }
}
- cmd.current_dir(workspace.workspace_root());
+ Ok(res)
+ }
+ fn run_per_ws(
+ cmd: Command,
+ workspace: &CargoWorkspace,
+ current_dir: &path::Path,
+ progress: &dyn Fn(String),
+ ) -> io::Result<WorkspaceBuildScripts> {
let mut res = WorkspaceBuildScripts::default();
let outputs = &mut res.outputs;
// NB: Cargo.toml could have been modified between `cargo metadata` and
@@ -122,10 +233,46 @@ impl WorkspaceBuildScripts {
// exactly those from `config`.
let mut by_id: FxHashMap<String, Package> = FxHashMap::default();
for package in workspace.packages() {
- outputs.insert(package, None);
+ outputs.insert(package, BuildScriptOutput::default());
by_id.insert(workspace[package].id.clone(), package);
}
+ res.error = Self::run_command(
+ cmd,
+ current_dir,
+ |package, cb| {
+ if let Some(&package) = by_id.get(package) {
+ cb(&workspace[package].name, &mut outputs[package]);
+ }
+ },
+ progress,
+ )?;
+
+ if tracing::enabled!(tracing::Level::INFO) {
+ for package in workspace.packages() {
+ let package_build_data = &mut outputs[package];
+ if !package_build_data.is_unchanged() {
+ tracing::info!(
+ "{}: {:?}",
+ workspace[package].manifest.parent().display(),
+ package_build_data,
+ );
+ }
+ }
+ }
+
+ Ok(res)
+ }
+
+ fn run_command(
+ mut cmd: Command,
+ current_dir: &path::Path,
+ // ideally this would be something like:
+ // with_output_for: impl FnMut(&str, dyn FnOnce(&mut BuildScriptOutput)),
+ // but owned trait objects aren't a thing
+ mut with_output_for: impl FnMut(&str, &mut dyn FnMut(&str, &mut BuildScriptOutput)),
+ progress: &dyn Fn(String),
+ ) -> io::Result<Option<String>> {
let errors = RefCell::new(String::new());
let push_err = |err: &str| {
let mut e = errors.borrow_mut();
@@ -133,7 +280,8 @@ impl WorkspaceBuildScripts {
e.push('\n');
};
- tracing::info!("Running build scripts: {:?}", cmd);
+ tracing::info!("Running build scripts in {}: {:?}", current_dir.display(), cmd);
+ cmd.current_dir(current_dir);
let output = stdx::process::spawn_with_streaming_output(
cmd,
&mut |line| {
@@ -145,59 +293,58 @@ impl WorkspaceBuildScripts {
.unwrap_or_else(|_| Message::TextLine(line.to_string()));
match message {
- Message::BuildScriptExecuted(message) => {
- let package = match by_id.get(&message.package_id.repr) {
- Some(&it) => it,
- None => return,
- };
- let cfgs = {
- let mut acc = Vec::new();
- for cfg in message.cfgs {
- match cfg.parse::<CfgFlag>() {
- Ok(it) => acc.push(it),
- Err(err) => {
- push_err(&format!(
- "invalid cfg from cargo-metadata: {}",
- err
- ));
- return;
- }
- };
+ Message::BuildScriptExecuted(mut message) => {
+ with_output_for(&message.package_id.repr, &mut |name, data| {
+ progress(format!("running build-script: {}", name));
+ let cfgs = {
+ let mut acc = Vec::new();
+ for cfg in &message.cfgs {
+ match cfg.parse::<CfgFlag>() {
+ Ok(it) => acc.push(it),
+ Err(err) => {
+ push_err(&format!(
+ "invalid cfg from cargo-metadata: {}",
+ err
+ ));
+ return;
+ }
+ };
+ }
+ acc
+ };
+ if !message.env.is_empty() {
+ data.envs = mem::take(&mut message.env);
}
- acc
- };
- // cargo_metadata crate returns default (empty) path for
- // older cargos, which is not absolute, so work around that.
- let out_dir = message.out_dir.into_os_string();
- if !out_dir.is_empty() {
- let data = outputs[package].get_or_insert_with(Default::default);
- data.out_dir = Some(AbsPathBuf::assert(PathBuf::from(out_dir)));
- data.cfgs = cfgs;
- }
- if !message.env.is_empty() {
- outputs[package].get_or_insert_with(Default::default).envs =
- message.env;
- }
+ // cargo_metadata crate returns default (empty) path for
+ // older cargos, which is not absolute, so work around that.
+ let out_dir = mem::take(&mut message.out_dir).into_os_string();
+ if !out_dir.is_empty() {
+ let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir));
+ // inject_cargo_env(package, package_build_data);
+ // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
+ if let Some(out_dir) =
+ out_dir.as_os_str().to_str().map(|s| s.to_owned())
+ {
+ data.envs.push(("OUT_DIR".to_string(), out_dir));
+ }
+ data.out_dir = Some(out_dir);
+ data.cfgs = cfgs;
+ }
+ });
}
Message::CompilerArtifact(message) => {
- let package = match by_id.get(&message.package_id.repr) {
- Some(it) => *it,
- None => return,
- };
-
- progress(format!("metadata {}", message.target.name));
-
- if message.target.kind.iter().any(|k| k == "proc-macro") {
- // Skip rmeta file
- if let Some(filename) =
- message.filenames.iter().find(|name| is_dylib(name))
- {
- let filename = AbsPathBuf::assert(PathBuf::from(&filename));
- outputs[package]
- .get_or_insert_with(Default::default)
- .proc_macro_dylib_path = Some(filename);
+ with_output_for(&message.package_id.repr, &mut |name, data| {
+ progress(format!("building proc-macros: {}", name));
+ if message.target.kind.iter().any(|k| k == "proc-macro") {
+ // Skip rmeta file
+ if let Some(filename) =
+ message.filenames.iter().find(|name| is_dylib(name))
+ {
+ let filename = AbsPathBuf::assert(PathBuf::from(&filename));
+ data.proc_macro_dylib_path = Some(filename);
+ }
}
- }
+ });
}
Message::CompilerMessage(message) => {
progress(message.target.name);
@@ -216,32 +363,13 @@ impl WorkspaceBuildScripts {
},
)?;
- for package in workspace.packages() {
- if let Some(package_build_data) = &mut outputs[package] {
- tracing::info!(
- "{}: {:?}",
- workspace[package].manifest.parent().display(),
- package_build_data,
- );
- // inject_cargo_env(package, package_build_data);
- if let Some(out_dir) = &package_build_data.out_dir {
- // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
- if let Some(out_dir) = out_dir.as_os_str().to_str().map(|s| s.to_owned()) {
- package_build_data.envs.push(("OUT_DIR".to_string(), out_dir));
- }
- }
- }
- }
-
- let mut errors = errors.into_inner();
- if !output.status.success() {
- if errors.is_empty() {
- errors = "cargo check failed".to_string();
- }
- res.error = Some(errors);
- }
-
- Ok(res)
+ let errors = if !output.status.success() {
+ let errors = errors.into_inner();
+ Some(if errors.is_empty() { "cargo check failed".to_string() } else { errors })
+ } else {
+ None
+ };
+ Ok(errors)
}
pub fn error(&self) -> Option<&str> {
@@ -249,11 +377,11 @@ impl WorkspaceBuildScripts {
}
pub(crate) fn get_output(&self, idx: Package) -> Option<&BuildScriptOutput> {
- self.outputs.get(idx)?.as_ref()
+ self.outputs.get(idx)
}
}
-// FIXME: File a better way to know if it is a dylib.
+// FIXME: Find a better way to know if it is a dylib.
fn is_dylib(path: &Utf8Path) -> bool {
match path.extension().map(|e| e.to_string().to_lowercase()) {
None => false,
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 eed955b42..b4c2ba436 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
@@ -2,6 +2,7 @@
use std::iter;
use std::path::PathBuf;
+use std::str::from_utf8;
use std::{ops, process::Command};
use anyhow::{Context, Result};
@@ -13,8 +14,8 @@ use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde_json::from_value;
-use crate::CfgOverrides;
-use crate::{utf8_stdout, ManifestPath};
+use crate::{utf8_stdout, InvocationLocation, ManifestPath};
+use crate::{CfgOverrides, InvocationStrategy};
/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
/// workspace. It pretty closely mirrors `cargo metadata` output.
@@ -70,34 +71,43 @@ impl Default for UnsetTestCrates {
}
}
-#[derive(Default, Clone, Debug, PartialEq, Eq)]
-pub struct CargoConfig {
- /// Do not activate the `default` feature.
- pub no_default_features: bool,
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum CargoFeatures {
+ All,
+ Selected {
+ /// List of features to activate.
+ features: Vec<String>,
+ /// Do not activate the `default` feature.
+ no_default_features: bool,
+ },
+}
- /// Activate all available features
- pub all_features: bool,
+impl Default for CargoFeatures {
+ fn default() -> Self {
+ CargoFeatures::Selected { features: vec![], no_default_features: false }
+ }
+}
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct CargoConfig {
/// List of features to activate.
- /// This will be ignored if `cargo_all_features` is true.
- pub features: Vec<String>,
-
+ pub features: CargoFeatures,
/// rustc target
pub target: Option<String>,
-
- /// Don't load sysroot crates (`std`, `core` & friends). Might be useful
- /// when debugging isolated issues.
- pub no_sysroot: bool,
-
+ /// Sysroot loading behavior
+ pub sysroot: Option<RustcSource>,
/// rustc private crate source
pub rustc_source: Option<RustcSource>,
-
/// crates to disable `#[cfg(test)]` on
pub unset_test_crates: UnsetTestCrates,
-
+ /// Invoke `cargo check` through the RUSTC_WRAPPER.
pub wrap_rustc_in_build_scripts: bool,
-
+ /// The command to run instead of `cargo check` for building build scripts.
pub run_build_script_command: Option<Vec<String>>,
+ /// Extra env vars to set when invoking the cargo command
+ pub extra_env: FxHashMap<String, String>,
+ pub invocation_strategy: InvocationStrategy,
+ pub invocation_location: InvocationLocation,
}
impl CargoConfig {
@@ -140,7 +150,7 @@ pub struct PackageData {
pub targets: Vec<Target>,
/// Does this package come from the local filesystem (and is editable)?
pub is_local: bool,
- // Whether this package is a member of the workspace
+ /// Whether this package is a member of the workspace
pub is_member: bool,
/// List of packages this package depends on
pub dependencies: Vec<PackageDependency>,
@@ -246,8 +256,8 @@ impl TargetKind {
}
}
+// Deserialize helper for the cargo metadata
#[derive(Deserialize, Default)]
-// Deserialise helper for the cargo metadata
struct PackageMetadata {
#[serde(rename = "rust-analyzer")]
rust_analyzer: Option<RustAnalyzerPackageMetaData>,
@@ -263,22 +273,23 @@ impl CargoWorkspace {
let target = config
.target
.clone()
- .or_else(|| cargo_config_build_target(cargo_toml))
- .or_else(|| rustc_discover_host_triple(cargo_toml));
+ .or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
+ .or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
let mut meta = MetadataCommand::new();
meta.cargo_path(toolchain::cargo());
meta.manifest_path(cargo_toml.to_path_buf());
- if config.all_features {
- meta.features(CargoOpt::AllFeatures);
- } else {
- if config.no_default_features {
- // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
- // https://github.com/oli-obk/cargo_metadata/issues/79
- meta.features(CargoOpt::NoDefaultFeatures);
+ match &config.features {
+ CargoFeatures::All => {
+ meta.features(CargoOpt::AllFeatures);
}
- if !config.features.is_empty() {
- meta.features(CargoOpt::SomeFeatures(config.features.clone()));
+ CargoFeatures::Selected { features, no_default_features } => {
+ if *no_default_features {
+ meta.features(CargoOpt::NoDefaultFeatures);
+ }
+ if !features.is_empty() {
+ meta.features(CargoOpt::SomeFeatures(features.clone()));
+ }
}
}
meta.current_dir(current_dir.as_os_str());
@@ -292,10 +303,22 @@ impl CargoWorkspace {
// unclear whether cargo itself supports it.
progress("metadata".to_string());
- let meta =
- meta.exec().with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))?;
-
- Ok(meta)
+ (|| -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
+ let mut command = meta.cargo_command();
+ command.envs(&config.extra_env);
+ let output = command.output()?;
+ if !output.status.success() {
+ return Err(cargo_metadata::Error::CargoMetadata {
+ stderr: String::from_utf8(output.stderr)?,
+ });
+ }
+ let stdout = from_utf8(&output.stdout)?
+ .lines()
+ .find(|line| line.starts_with('{'))
+ .ok_or(cargo_metadata::Error::NoJson)?;
+ cargo_metadata::MetadataCommand::parse(stdout)
+ })()
+ .with_context(|| format!("Failed to run `{:?}`", meta.cargo_command()))
}
pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
@@ -306,18 +329,21 @@ impl CargoWorkspace {
let ws_members = &meta.workspace_members;
meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
- for meta_pkg in &meta.packages {
+ for meta_pkg in meta.packages {
let cargo_metadata::Package {
- id,
- edition,
name,
- manifest_path,
version,
- metadata,
+ id,
+ source,
+ targets: meta_targets,
+ features,
+ manifest_path,
repository,
+ edition,
+ metadata,
..
} = meta_pkg;
- let meta = from_value::<PackageMetadata>(metadata.clone()).unwrap_or_default();
+ let meta = from_value::<PackageMetadata>(metadata).unwrap_or_default();
let edition = match edition {
cargo_metadata::Edition::E2015 => Edition::Edition2015,
cargo_metadata::Edition::E2018 => Edition::Edition2018,
@@ -329,67 +355,50 @@ impl CargoWorkspace {
};
// We treat packages without source as "local" packages. That includes all members of
// the current workspace, as well as any path dependency outside the workspace.
- let is_local = meta_pkg.source.is_none();
- let is_member = ws_members.contains(id);
+ let is_local = source.is_none();
+ let is_member = ws_members.contains(&id);
let pkg = packages.alloc(PackageData {
id: id.repr.clone(),
- name: name.clone(),
- version: version.clone(),
- manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)).try_into().unwrap(),
+ name,
+ version,
+ manifest: AbsPathBuf::assert(manifest_path.into()).try_into().unwrap(),
targets: Vec::new(),
is_local,
is_member,
edition,
- repository: repository.clone(),
+ repository,
dependencies: Vec::new(),
- features: meta_pkg.features.clone().into_iter().collect(),
+ features: features.into_iter().collect(),
active_features: Vec::new(),
metadata: meta.rust_analyzer.unwrap_or_default(),
});
let pkg_data = &mut packages[pkg];
pkg_by_id.insert(id, pkg);
- for meta_tgt in &meta_pkg.targets {
- let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"];
+ for meta_tgt in meta_targets {
+ let cargo_metadata::Target { name, kind, required_features, src_path, .. } =
+ meta_tgt;
let tgt = targets.alloc(TargetData {
package: pkg,
- name: meta_tgt.name.clone(),
- root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)),
- kind: TargetKind::new(meta_tgt.kind.as_slice()),
- is_proc_macro,
- required_features: meta_tgt.required_features.clone(),
+ name,
+ root: AbsPathBuf::assert(src_path.into()),
+ kind: TargetKind::new(&kind),
+ is_proc_macro: &*kind == ["proc-macro"],
+ required_features,
});
pkg_data.targets.push(tgt);
}
}
let resolve = meta.resolve.expect("metadata executed with deps");
for mut node in resolve.nodes {
- let source = match pkg_by_id.get(&node.id) {
- Some(&src) => src,
- // FIXME: replace this and a similar branch below with `.unwrap`, once
- // https://github.com/rust-lang/cargo/issues/7841
- // is fixed and hits stable (around 1.43-is probably?).
- None => {
- tracing::error!("Node id do not match in cargo metadata, ignoring {}", node.id);
- continue;
- }
- };
+ let &source = pkg_by_id.get(&node.id).unwrap();
node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg));
- for (dep_node, kind) in node
+ let dependencies = node
.deps
.iter()
- .flat_map(|dep| DepKind::iter(&dep.dep_kinds).map(move |kind| (dep, kind)))
- {
- let pkg = match pkg_by_id.get(&dep_node.pkg) {
- Some(&pkg) => pkg,
- None => {
- tracing::error!(
- "Dep node id do not match in cargo metadata, ignoring {}",
- dep_node.pkg
- );
- continue;
- }
- };
+ .flat_map(|dep| DepKind::iter(&dep.dep_kinds).map(move |kind| (dep, kind)));
+ for (dep_node, kind) in dependencies {
+ let &pkg = pkg_by_id.get(&dep_node.pkg).unwrap();
let dep = PackageDependency { name: dep_node.name.clone(), pkg, kind };
packages[source].dependencies.push(dep);
}
@@ -434,10 +443,7 @@ impl CargoWorkspace {
found = true
}
self[pkg].dependencies.iter().find_map(|dep| {
- if &self[dep.pkg].manifest == manifest_path {
- return Some(self[pkg].manifest.clone());
- }
- None
+ (&self[dep.pkg].manifest == manifest_path).then(|| self[pkg].manifest.clone())
})
})
.collect::<Vec<ManifestPath>>();
@@ -463,8 +469,12 @@ impl CargoWorkspace {
}
}
-fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
+fn rustc_discover_host_triple(
+ cargo_toml: &ManifestPath,
+ extra_env: &FxHashMap<String, String>,
+) -> Option<String> {
let mut rustc = Command::new(toolchain::rustc());
+ rustc.envs(extra_env);
rustc.current_dir(cargo_toml.parent()).arg("-vV");
tracing::debug!("Discovering host platform by {:?}", rustc);
match utf8_stdout(rustc) {
@@ -486,8 +496,12 @@ fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
}
}
-fn cargo_config_build_target(cargo_toml: &ManifestPath) -> Option<String> {
+fn cargo_config_build_target(
+ cargo_toml: &ManifestPath,
+ extra_env: &FxHashMap<String, String>,
+) -> Option<String> {
let mut cargo_config = Command::new(toolchain::cargo());
+ cargo_config.envs(extra_env);
cargo_config
.current_dir(cargo_toml.parent())
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
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 b81b7432f..575581fa5 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -42,8 +42,8 @@ use rustc_hash::FxHashSet;
pub use crate::{
build_scripts::WorkspaceBuildScripts,
cargo_workspace::{
- CargoConfig, CargoWorkspace, Package, PackageData, PackageDependency, RustcSource, Target,
- TargetData, TargetKind, UnsetTestCrates,
+ CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency,
+ RustcSource, Target, TargetData, TargetKind, UnsetTestCrates,
},
manifest_path::ManifestPath,
project_json::{ProjectJson, ProjectJsonData},
@@ -67,7 +67,7 @@ impl ProjectManifest {
if path.file_name().unwrap_or_default() == "Cargo.toml" {
return Ok(ProjectManifest::CargoToml(path));
}
- bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display())
+ bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display());
}
pub fn discover_single(path: &AbsPath) -> Result<ProjectManifest> {
@@ -78,7 +78,7 @@ impl ProjectManifest {
};
if !candidates.is_empty() {
- bail!("more than one project")
+ bail!("more than one project");
}
Ok(res)
}
@@ -157,3 +157,17 @@ fn utf8_stdout(mut cmd: Command) -> Result<String> {
let stdout = String::from_utf8(output.stdout)?;
Ok(stdout.trim().to_string())
}
+
+#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
+pub enum InvocationStrategy {
+ Once,
+ #[default]
+ PerWorkspace,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub enum InvocationLocation {
+ Root(AbsPathBuf),
+ #[default]
+ Workspace,
+}
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 63d1d0ace..5133a14d5 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
@@ -110,14 +110,17 @@ impl ProjectJson {
.collect::<Vec<_>>(),
}
}
+
/// Returns the number of crates in the project.
pub fn n_crates(&self) -> usize {
self.crates.len()
}
+
/// Returns an iterator over the crates in the project.
pub fn crates(&self) -> impl Iterator<Item = (CrateId, &Crate)> + '_ {
self.crates.iter().enumerate().map(|(idx, krate)| (CrateId(idx as u32), krate))
}
+
/// Returns the path to the project's root folder.
pub fn path(&self) -> &AbsPath {
&self.project_root
diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
index 17e244d06..323136183 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
@@ -3,10 +3,15 @@
use std::process::Command;
use anyhow::Result;
+use rustc_hash::FxHashMap;
use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath};
-pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Vec<CfgFlag> {
+pub(crate) fn get(
+ cargo_toml: Option<&ManifestPath>,
+ target: Option<&str>,
+ extra_env: &FxHashMap<String, String>,
+) -> Vec<CfgFlag> {
let _p = profile::span("rustc_cfg::get");
let mut res = Vec::with_capacity(6 * 2 + 1);
@@ -18,7 +23,7 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
}
}
- match get_rust_cfgs(cargo_toml, target) {
+ match get_rust_cfgs(cargo_toml, target, extra_env) {
Ok(rustc_cfgs) => {
tracing::debug!(
"rustc cfgs found: {:?}",
@@ -35,9 +40,14 @@ pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Ve
res
}
-fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Result<String> {
+fn get_rust_cfgs(
+ cargo_toml: Option<&ManifestPath>,
+ target: Option<&str>,
+ extra_env: &FxHashMap<String, String>,
+) -> Result<String> {
if let Some(cargo_toml) = cargo_toml {
let mut cargo_config = Command::new(toolchain::cargo());
+ cargo_config.envs(extra_env);
cargo_config
.current_dir(cargo_toml.parent())
.args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
@@ -52,6 +62,7 @@ fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Res
}
// using unstable cargo features failed, fall back to using plain rustc
let mut cmd = Command::new(toolchain::rustc());
+ cmd.envs(extra_env);
cmd.args(&["--print", "cfg", "-O"]);
if let Some(target) = target {
cmd.args(&["--target", target]);
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 362bb0f5e..fa8d76f3f 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -9,6 +9,7 @@ use std::{env, fs, iter, ops, path::PathBuf, process::Command};
use anyhow::{format_err, Result};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
+use rustc_hash::FxHashMap;
use crate::{utf8_stdout, ManifestPath};
@@ -63,22 +64,38 @@ impl Sysroot {
self.by_name("proc_macro")
}
- pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
+ pub fn crates(&self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + '_ {
self.crates.iter().map(|(id, _data)| id)
}
+}
- pub fn discover(dir: &AbsPath) -> Result<Sysroot> {
- tracing::debug!("Discovering sysroot for {}", dir.display());
- let sysroot_dir = discover_sysroot_dir(dir)?;
- let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, dir)?;
+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> {
+ tracing::debug!("discovering sysroot for {}", dir.display());
+ 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)
}
- pub fn discover_rustc(cargo_toml: &ManifestPath) -> Option<ManifestPath> {
- tracing::debug!("Discovering rustc source for {}", cargo_toml.display());
+ pub fn discover_rustc(
+ cargo_toml: &ManifestPath,
+ extra_env: &FxHashMap<String, String>,
+ ) -> Option<ManifestPath> {
+ tracing::debug!("discovering rustc source for {}", cargo_toml.display());
let current_dir = cargo_toml.parent();
- discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
+ let sysroot_dir = discover_sysroot_dir(current_dir, extra_env).ok()?;
+ get_rustc_src(&sysroot_dir)
+ }
+
+ pub fn with_sysroot_dir(sysroot_dir: AbsPathBuf) -> Result<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)
}
pub fn load(sysroot_dir: AbsPathBuf, sysroot_src_dir: AbsPathBuf) -> Result<Sysroot> {
@@ -144,33 +161,46 @@ impl Sysroot {
}
}
-fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
+fn discover_sysroot_dir(
+ current_dir: &AbsPath,
+ extra_env: &FxHashMap<String, String>,
+) -> Result<AbsPathBuf> {
let mut rustc = Command::new(toolchain::rustc());
+ rustc.envs(extra_env);
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
tracing::debug!("Discovering sysroot by {:?}", rustc);
let stdout = utf8_stdout(rustc)?;
Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
}
-fn discover_sysroot_src_dir(
- sysroot_path: &AbsPathBuf,
- current_dir: &AbsPath,
-) -> Result<AbsPathBuf> {
+fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
if let Ok(path) = env::var("RUST_SRC_PATH") {
- let path = AbsPathBuf::try_from(path.as_str())
- .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
- let core = path.join("core");
- if fs::metadata(&core).is_ok() {
- tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
- return Ok(path);
+ if let Ok(path) = AbsPathBuf::try_from(path.as_str()) {
+ let core = path.join("core");
+ if fs::metadata(&core).is_ok() {
+ tracing::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
+ return Some(path);
+ }
+ tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
+ } else {
+ tracing::debug!("RUST_SRC_PATH is set, but is invalid, ignoring");
}
- tracing::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
}
get_rust_src(sysroot_path)
+}
+
+fn discover_sysroot_src_dir_or_add_component(
+ sysroot_path: &AbsPathBuf,
+ current_dir: &AbsPath,
+ extra_env: &FxHashMap<String, String>,
+) -> Result<AbsPathBuf> {
+ discover_sysroot_src_dir(sysroot_path)
.or_else(|| {
let mut rustup = Command::new(toolchain::rustup());
+ rustup.envs(extra_env);
rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
+ tracing::info!("adding rust-src component by {:?}", rustup);
utf8_stdout(rustup).ok()?;
get_rust_src(sysroot_path)
})
@@ -189,7 +219,7 @@ try installing the Rust source the same way you installed rustc",
fn get_rustc_src(sysroot_path: &AbsPath) -> Option<ManifestPath> {
let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
let rustc_src = ManifestPath::try_from(rustc_src).ok()?;
- tracing::debug!("Checking for rustc source code: {}", rustc_src.display());
+ tracing::debug!("checking for rustc source code: {}", rustc_src.display());
if fs::metadata(&rustc_src).is_ok() {
Some(rustc_src)
} else {
@@ -199,7 +229,7 @@ fn get_rustc_src(sysroot_path: &AbsPath) -> Option<ManifestPath> {
fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
let rust_src = sysroot_path.join("lib/rustlib/src/rust/library");
- tracing::debug!("Checking sysroot: {}", rust_src.display());
+ tracing::debug!("checking sysroot library: {}", rust_src.display());
if fs::metadata(&rust_src).is_ok() {
Some(rust_src)
} else {
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 9ccb6e910..e2444e249 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -92,13 +92,17 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
}
fn to_crate_graph(project_workspace: ProjectWorkspace) -> CrateGraph {
- project_workspace.to_crate_graph(&mut |_, _| Ok(Vec::new()), &mut {
- let mut counter = 0;
- move |_path| {
- counter += 1;
- Some(FileId(counter))
- }
- })
+ project_workspace.to_crate_graph(
+ &mut |_, _| Ok(Vec::new()),
+ &mut {
+ let mut counter = 0;
+ move |_path| {
+ counter += 1;
+ Some(FileId(counter))
+ }
+ },
+ &Default::default(),
+ )
}
fn check_crate_graph(crate_graph: CrateGraph, expect: Expect) {
@@ -181,6 +185,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -256,6 +263,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -331,6 +341,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -406,6 +419,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -473,6 +489,9 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
repo: Some(
"https://github.com/rust-lang/libc",
),
+ name: Some(
+ "libc",
+ ),
},
is_proc_macro: false,
},
@@ -563,6 +582,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -640,6 +662,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -717,6 +742,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -794,6 +822,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -861,6 +892,9 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
repo: Some(
"https://github.com/rust-lang/libc",
),
+ name: Some(
+ "libc",
+ ),
},
is_proc_macro: false,
},
@@ -942,6 +976,9 @@ fn cargo_hello_world_project_model() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -1019,6 +1056,9 @@ fn cargo_hello_world_project_model() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -1096,6 +1136,9 @@ fn cargo_hello_world_project_model() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -1173,6 +1216,9 @@ fn cargo_hello_world_project_model() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello-world",
+ ),
},
is_proc_macro: false,
},
@@ -1240,6 +1286,9 @@ fn cargo_hello_world_project_model() {
repo: Some(
"https://github.com/rust-lang/libc",
),
+ name: Some(
+ "libc",
+ ),
},
is_proc_macro: false,
},
@@ -1800,6 +1849,9 @@ fn rust_project_hello_world_project_model() {
),
origin: CratesIo {
repo: None,
+ name: Some(
+ "hello_world",
+ ),
},
is_proc_macro: false,
},
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 818bbed6a..2780c62ed 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -2,7 +2,7 @@
//! metadata` or `rust-project.json`) into representation stored in the salsa
//! database -- `CrateGraph`.
-use std::{collections::VecDeque, fmt, fs, process::Command};
+use std::{collections::VecDeque, fmt, fs, process::Command, sync::Arc};
use anyhow::{format_err, Context, Result};
use base_db::{
@@ -21,8 +21,8 @@ use crate::{
cfg_flag::CfgFlag,
rustc_cfg,
sysroot::SysrootCrate,
- utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, ProjectJson, ProjectManifest, Sysroot,
- TargetKind, WorkspaceBuildScripts,
+ utf8_stdout, CargoConfig, CargoWorkspace, InvocationStrategy, ManifestPath, Package,
+ ProjectJson, ProjectManifest, Sysroot, TargetKind, WorkspaceBuildScripts,
};
/// A set of cfg-overrides per crate.
@@ -156,11 +156,16 @@ impl ProjectWorkspace {
})?;
let project_location = project_json.parent().to_path_buf();
let project_json = ProjectJson::new(&project_location, data);
- ProjectWorkspace::load_inline(project_json, config.target.as_deref())?
+ ProjectWorkspace::load_inline(
+ project_json,
+ config.target.as_deref(),
+ &config.extra_env,
+ )?
}
ProjectManifest::CargoToml(cargo_toml) => {
let cargo_version = utf8_stdout({
let mut cmd = Command::new(toolchain::cargo());
+ cmd.envs(&config.extra_env);
cmd.arg("--version");
cmd
})?;
@@ -183,22 +188,41 @@ impl ProjectWorkspace {
})?;
let cargo = CargoWorkspace::new(meta);
- let sysroot = if config.no_sysroot {
- None
- } else {
- Some(Sysroot::discover(cargo_toml.parent()).with_context(|| {
- format!(
+ let sysroot = match &config.sysroot {
+ Some(RustcSource::Path(path)) => {
+ Some(Sysroot::with_sysroot_dir(path.clone()).with_context(|| {
+ format!(
+ "Failed to find sysroot for Cargo.toml file {}.",
+ cargo_toml.display()
+ )
+ })?)
+ }
+ 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,
};
+ if let Some(sysroot) = &sysroot {
+ tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot");
+ }
let rustc_dir = match &config.rustc_source {
Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(),
- Some(RustcSource::Discover) => Sysroot::discover_rustc(&cargo_toml),
+ Some(RustcSource::Discover) => {
+ Sysroot::discover_rustc(&cargo_toml, &config.extra_env)
+ }
None => None,
};
+ if let Some(rustc_dir) = &rustc_dir {
+ tracing::info!(rustc_dir = %rustc_dir.display(), "Using rustc source");
+ }
let rustc = match rustc_dir {
Some(rustc_dir) => Some({
@@ -216,7 +240,8 @@ impl ProjectWorkspace {
None => None,
};
- let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref());
+ let rustc_cfg =
+ rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), &config.extra_env);
let cfg_overrides = config.cfg_overrides();
ProjectWorkspace::Cargo {
@@ -237,6 +262,7 @@ impl ProjectWorkspace {
pub fn load_inline(
project_json: ProjectJson,
target: Option<&str>,
+ extra_env: &FxHashMap<String, String>,
) -> Result<ProjectWorkspace> {
let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) {
(Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)?),
@@ -257,8 +283,11 @@ impl ProjectWorkspace {
}
(None, None) => None,
};
+ if let Some(sysroot) = &sysroot {
+ tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot");
+ }
- let rustc_cfg = rustc_cfg::get(None, target);
+ let rustc_cfg = rustc_cfg::get(None, target, extra_env);
Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
}
@@ -268,11 +297,13 @@ impl ProjectWorkspace {
.first()
.and_then(|it| it.parent())
.ok_or_else(|| format_err!("No detached files to load"))?,
+ &Default::default(),
)?;
- let rustc_cfg = rustc_cfg::get(None, None);
+ let rustc_cfg = rustc_cfg::get(None, None, &Default::default());
Ok(ProjectWorkspace::DetachedFiles { files: detached_files, sysroot, rustc_cfg })
}
+ /// Runs the build scripts for this [`ProjectWorkspace`].
pub fn run_build_scripts(
&self,
config: &CargoConfig,
@@ -280,9 +311,13 @@ impl ProjectWorkspace {
) -> Result<WorkspaceBuildScripts> {
match self {
ProjectWorkspace::Cargo { cargo, toolchain, .. } => {
- WorkspaceBuildScripts::run(config, cargo, progress, toolchain).with_context(|| {
- format!("Failed to run build scripts for {}", &cargo.workspace_root().display())
- })
+ WorkspaceBuildScripts::run_for_workspace(config, cargo, progress, toolchain)
+ .with_context(|| {
+ format!(
+ "Failed to run build scripts for {}",
+ &cargo.workspace_root().display()
+ )
+ })
}
ProjectWorkspace::Json { .. } | ProjectWorkspace::DetachedFiles { .. } => {
Ok(WorkspaceBuildScripts::default())
@@ -290,6 +325,49 @@ impl ProjectWorkspace {
}
}
+ /// Runs the build scripts for the given [`ProjectWorkspace`]s. Depending on the invocation
+ /// strategy this may run a single build process for all project workspaces.
+ pub fn run_all_build_scripts(
+ workspaces: &[ProjectWorkspace],
+ config: &CargoConfig,
+ progress: &dyn Fn(String),
+ ) -> Vec<Result<WorkspaceBuildScripts>> {
+ if matches!(config.invocation_strategy, InvocationStrategy::PerWorkspace)
+ || config.run_build_script_command.is_none()
+ {
+ return workspaces.iter().map(|it| it.run_build_scripts(config, progress)).collect();
+ }
+
+ let cargo_ws: Vec<_> = workspaces
+ .iter()
+ .filter_map(|it| match it {
+ ProjectWorkspace::Cargo { cargo, .. } => Some(cargo),
+ _ => None,
+ })
+ .collect();
+ let ref mut outputs = 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)),
+ };
+
+ workspaces
+ .iter()
+ .map(|it| match it {
+ ProjectWorkspace::Cargo { cargo, .. } => match outputs {
+ Ok(outputs) => Ok(outputs.next().unwrap()),
+ Err(e) => Err(e.clone()).with_context(|| {
+ format!(
+ "Failed to run build scripts for {}",
+ &cargo.workspace_root().display()
+ )
+ }),
+ },
+ _ => Ok(WorkspaceBuildScripts::default()),
+ })
+ .collect()
+ }
+
pub fn set_build_scripts(&mut self, bs: WorkspaceBuildScripts) {
match self {
ProjectWorkspace::Cargo { build_scripts, .. } => *build_scripts = bs,
@@ -303,6 +381,13 @@ 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>| {
+ sysroot.map(|sysroot| PackageRoot {
+ is_local: false,
+ include: vec![sysroot.src_root().to_path_buf()],
+ exclude: Vec::new(),
+ })
+ };
match self {
ProjectWorkspace::Json { project, sysroot, rustc_cfg: _ } => project
.crates()
@@ -313,13 +398,7 @@ impl ProjectWorkspace {
})
.collect::<FxHashSet<_>>()
.into_iter()
- .chain(sysroot.as_ref().into_iter().flat_map(|sysroot| {
- sysroot.crates().map(move |krate| PackageRoot {
- is_local: false,
- include: vec![sysroot[krate].root.parent().to_path_buf()],
- exclude: Vec::new(),
- })
- }))
+ .chain(mk_sysroot(sysroot.as_ref()))
.collect::<Vec<_>>(),
ProjectWorkspace::Cargo {
cargo,
@@ -368,11 +447,7 @@ impl ProjectWorkspace {
}
PackageRoot { is_local, include, exclude }
})
- .chain(sysroot.iter().map(|sysroot| PackageRoot {
- is_local: false,
- include: vec![sysroot.src_root().to_path_buf()],
- exclude: Vec::new(),
- }))
+ .chain(mk_sysroot(sysroot.as_ref()))
.chain(rustc.iter().flat_map(|rustc| {
rustc.packages().map(move |krate| PackageRoot {
is_local: false,
@@ -389,11 +464,7 @@ impl ProjectWorkspace {
include: vec![detached_file.clone()],
exclude: Vec::new(),
})
- .chain(sysroot.crates().map(|krate| PackageRoot {
- is_local: false,
- include: vec![sysroot[krate].root.parent().to_path_buf()],
- exclude: Vec::new(),
- }))
+ .chain(mk_sysroot(Some(sysroot)))
.collect(),
}
}
@@ -416,6 +487,7 @@ impl ProjectWorkspace {
&self,
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
+ extra_env: &FxHashMap<String, String>,
) -> CrateGraph {
let _p = profile::span("ProjectWorkspace::to_crate_graph");
@@ -426,6 +498,7 @@ impl ProjectWorkspace {
load,
project,
sysroot,
+ extra_env,
),
ProjectWorkspace::Cargo {
cargo,
@@ -464,6 +537,7 @@ fn project_json_to_crate_graph(
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
project: &ProjectJson,
sysroot: &Option<Sysroot>,
+ extra_env: &FxHashMap<String, String>,
) -> CrateGraph {
let mut crate_graph = CrateGraph::default();
let sysroot_deps = sysroot
@@ -489,9 +563,9 @@ fn project_json_to_crate_graph(
};
let target_cfgs = match krate.target.as_deref() {
- Some(target) => {
- cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(None, Some(target)))
- }
+ Some(target) => cfg_cache
+ .entry(target)
+ .or_insert_with(|| rustc_cfg::get(None, Some(target), extra_env)),
None => &rustc_cfg,
};
@@ -510,9 +584,15 @@ fn project_json_to_crate_graph(
proc_macro,
krate.is_proc_macro,
if krate.display_name.is_some() {
- CrateOrigin::CratesIo { repo: krate.repository.clone() }
+ CrateOrigin::CratesIo {
+ repo: krate.repository.clone(),
+ name: krate
+ .display_name
+ .clone()
+ .map(|n| n.canonical_name().to_string()),
+ }
} else {
- CrateOrigin::CratesIo { repo: None }
+ CrateOrigin::CratesIo { repo: None, name: None }
},
),
)
@@ -624,6 +704,8 @@ fn cargo_to_crate_graph(
lib_tgt = Some((crate_id, cargo[tgt].name.clone()));
pkg_to_lib_crate.insert(pkg, crate_id);
}
+ // Even crates that don't set proc-macro = true are allowed to depend on proc_macro
+ // (just none of the APIs work when called outside of a proc macro).
if let Some(proc_macro) = libproc_macro {
add_dep_with_prelude(
&mut crate_graph,
@@ -639,19 +721,19 @@ fn cargo_to_crate_graph(
}
// Set deps to the core, std and to the lib target of the current package
- for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
+ for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
// Add sysroot deps first so that a lib target named `core` etc. can overwrite them.
- public_deps.add(*from, &mut crate_graph);
+ public_deps.add(from, &mut crate_graph);
if let Some((to, name)) = lib_tgt.clone() {
- if to != *from && *kind != TargetKind::BuildScript {
+ if to != from && kind != TargetKind::BuildScript {
// (build script can not depend on its library target)
// For root projects with dashes in their name,
// cargo metadata does not do any normalization,
// so we do it ourselves currently
let name = CrateName::normalize_dashes(&name);
- add_dep(&mut crate_graph, *from, name, to);
+ add_dep(&mut crate_graph, from, name, to);
}
}
}
@@ -663,17 +745,17 @@ fn cargo_to_crate_graph(
for dep in cargo[pkg].dependencies.iter() {
let name = CrateName::new(&dep.name).unwrap();
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
- for (from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
- if dep.kind == DepKind::Build && *kind != TargetKind::BuildScript {
+ for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
+ if dep.kind == DepKind::Build && kind != TargetKind::BuildScript {
// Only build scripts may depend on build dependencies.
continue;
}
- if dep.kind != DepKind::Build && *kind == TargetKind::BuildScript {
+ if dep.kind != DepKind::Build && kind == TargetKind::BuildScript {
// Build scripts may only depend on build dependencies.
continue;
}
- add_dep(&mut crate_graph, *from, name.clone(), to)
+ add_dep(&mut crate_graph, from, name.clone(), to)
}
}
}
@@ -684,9 +766,9 @@ fn cargo_to_crate_graph(
// and create dependencies on them for the crates which opt-in to that
if let Some(rustc_workspace) = rustc {
handle_rustc_crates(
+ &mut crate_graph,
rustc_workspace,
load,
- &mut crate_graph,
&cfg_options,
override_cfg,
load_proc_macro,
@@ -730,14 +812,17 @@ fn detached_files_to_crate_graph(
let detached_file_crate = crate_graph.add_crate_root(
file_id,
Edition::CURRENT,
- display_name,
+ display_name.clone(),
None,
cfg_options.clone(),
cfg_options.clone(),
Env::default(),
Ok(Vec::new()),
false,
- CrateOrigin::CratesIo { repo: None },
+ CrateOrigin::CratesIo {
+ repo: None,
+ name: display_name.map(|n| n.canonical_name().to_string()),
+ },
);
public_deps.add(detached_file_crate, &mut crate_graph);
@@ -746,16 +831,16 @@ fn detached_files_to_crate_graph(
}
fn handle_rustc_crates(
+ crate_graph: &mut CrateGraph,
rustc_workspace: &CargoWorkspace,
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
- crate_graph: &mut CrateGraph,
cfg_options: &CfgOptions,
override_cfg: &CfgOverrides,
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
- pkg_to_lib_crate: &mut FxHashMap<la_arena::Idx<crate::PackageData>, CrateId>,
+ pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
public_deps: &SysrootPublicDeps,
cargo: &CargoWorkspace,
- pkg_crates: &FxHashMap<la_arena::Idx<crate::PackageData>, Vec<(CrateId, TargetKind)>>,
+ pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
build_scripts: &WorkspaceBuildScripts,
) {
let mut rustc_pkg_crates = FxHashMap::default();
@@ -769,8 +854,8 @@ fn handle_rustc_crates(
let mut queue = VecDeque::new();
queue.push_back(root_pkg);
while let Some(pkg) = queue.pop_front() {
- // Don't duplicate packages if they are dependended on a diamond pattern
- // N.B. if this line is omitted, we try to analyse over 4_800_000 crates
+ // Don't duplicate packages if they are dependent on a diamond pattern
+ // N.B. if this line is omitted, we try to analyze over 4_800_000 crates
// which is not ideal
if rustc_pkg_crates.contains_key(&pkg) {
continue;
@@ -913,7 +998,7 @@ fn add_target_crate_root(
env,
proc_macro,
is_proc_macro,
- CrateOrigin::CratesIo { repo: pkg.repository.clone() },
+ CrateOrigin::CratesIo { repo: pkg.repository.clone(), name: Some(pkg.name.clone()) },
)
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 539258918..544502853 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -18,14 +18,14 @@ name = "rust-analyzer"
path = "src/bin/main.rs"
[dependencies]
-anyhow = "1.0.57"
+anyhow = "1.0.62"
crossbeam-channel = "0.5.5"
dissimilar = "1.0.4"
-itertools = "0.10.3"
+itertools = "0.10.5"
scip = "0.1.1"
lsp-types = { version = "0.93.1", features = ["proposed"] }
parking_lot = "0.12.1"
-xflags = "0.2.4"
+xflags = "0.3.0"
oorandom = "11.1.3"
rustc-hash = "1.1.0"
serde = { version = "1.0.137", features = ["derive"] }
@@ -33,10 +33,10 @@ serde_json = { version = "1.0.81", features = ["preserve_order"] }
threadpool = "1.8.1"
rayon = "1.5.3"
num_cpus = "1.13.1"
-mimalloc = { version = "0.1.29", default-features = false, optional = true }
-lsp-server = { version = "0.6.0", path = "../../lib/lsp-server" }
+mimalloc = { version = "0.1.30", default-features = false, optional = true }
+lsp-server = { version = "0.7.0", path = "../../lib/lsp-server" }
tracing = "0.1.35"
-tracing-subscriber = { version = "0.3.14", default-features = false, features = [
+tracing-subscriber = { version = "0.3.16", default-features = false, features = [
"env-filter",
"registry",
"fmt",
@@ -87,7 +87,6 @@ jemalloc = ["jemallocator", "profile/jemalloc"]
force-always-assert = ["always-assert/force"]
in-rust-tree = [
"proc-macro-srv/sysroot-abi",
- "sourcegen/in-rust-tree",
"ide/in-rust-tree",
"syntax/in-rust-tree",
]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs
index 298814af5..ac10721d9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/logger.rs
@@ -132,7 +132,7 @@ where
let ext = span.extensions();
- // `FormattedFields` is a a formatted representation of the span's
+ // `FormattedFields` is a formatted representation of the span's
// fields, which is stored in its extensions by the `fmt` layer's
// `new_span` method. The fields will have been formatted
// by the same field formatter that's provided to the event
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 f6a680297..eabfcf194 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
@@ -37,16 +37,15 @@ fn main() {
process::exit(code);
}
- if let Err(err) = try_main() {
+ let flags = flags::RustAnalyzer::from_env_or_exit();
+ if let Err(err) = try_main(flags) {
tracing::error!("Unexpected error: {}", err);
eprintln!("{}", err);
process::exit(101);
}
}
-fn try_main() -> Result<()> {
- let flags = flags::RustAnalyzer::from_env()?;
-
+fn try_main(flags: flags::RustAnalyzer) -> Result<()> {
#[cfg(debug_assertions)]
if flags.wait_dbg || env::var("RA_WAIT_DBG").is_ok() {
#[allow(unused_mut)]
@@ -76,10 +75,6 @@ fn try_main() -> Result<()> {
println!("rust-analyzer {}", rust_analyzer::version());
return Ok(());
}
- if cmd.help {
- println!("{}", flags::RustAnalyzer::HELP);
- return Ok(());
- }
with_extra_thread("LspServer", run_server)?;
}
flags::RustAnalyzerCmd::ProcMacro(flags::ProcMacro) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
index 1c39e9391..6ede194ba 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cargo_target_spec.rs
@@ -4,7 +4,7 @@ use std::mem;
use cfg::{CfgAtom, CfgExpr};
use ide::{FileId, RunnableKind, TestId};
-use project_model::{self, ManifestPath, TargetKind};
+use project_model::{self, CargoFeatures, ManifestPath, TargetKind};
use vfs::AbsPathBuf;
use crate::{global_state::GlobalStateSnapshot, Result};
@@ -35,41 +35,41 @@ impl CargoTargetSpec {
match kind {
RunnableKind::Test { test_id, attr } => {
- args.push("test".to_string());
+ args.push("test".to_owned());
extra_args.push(test_id.to_string());
if let TestId::Path(_) = test_id {
- extra_args.push("--exact".to_string());
+ extra_args.push("--exact".to_owned());
}
- extra_args.push("--nocapture".to_string());
+ extra_args.push("--nocapture".to_owned());
if attr.ignore {
- extra_args.push("--ignored".to_string());
+ extra_args.push("--ignored".to_owned());
}
}
RunnableKind::TestMod { path } => {
- args.push("test".to_string());
- extra_args.push(path.to_string());
- extra_args.push("--nocapture".to_string());
+ args.push("test".to_owned());
+ extra_args.push(path.clone());
+ extra_args.push("--nocapture".to_owned());
}
RunnableKind::Bench { test_id } => {
- args.push("bench".to_string());
+ args.push("bench".to_owned());
extra_args.push(test_id.to_string());
if let TestId::Path(_) = test_id {
- extra_args.push("--exact".to_string());
+ extra_args.push("--exact".to_owned());
}
- extra_args.push("--nocapture".to_string());
+ extra_args.push("--nocapture".to_owned());
}
RunnableKind::DocTest { test_id } => {
- args.push("test".to_string());
- args.push("--doc".to_string());
+ args.push("test".to_owned());
+ args.push("--doc".to_owned());
extra_args.push(test_id.to_string());
- extra_args.push("--nocapture".to_string());
+ extra_args.push("--nocapture".to_owned());
}
RunnableKind::Bin => {
let subcommand = match spec {
Some(CargoTargetSpec { target_kind: TargetKind::Test, .. }) => "test",
_ => "run",
};
- args.push(subcommand.to_string());
+ args.push(subcommand.to_owned());
}
}
@@ -82,29 +82,35 @@ impl CargoTargetSpec {
};
let cargo_config = snap.config.cargo();
- if cargo_config.all_features {
- args.push("--all-features".to_string());
- for feature in target_required_features {
- args.push("--features".to_string());
- args.push(feature);
- }
- } else {
- let mut features = Vec::new();
- if let Some(cfg) = cfg.as_ref() {
- required_features(cfg, &mut features);
+ match &cargo_config.features {
+ CargoFeatures::All => {
+ args.push("--all-features".to_owned());
+ for feature in target_required_features {
+ args.push("--features".to_owned());
+ args.push(feature);
+ }
}
+ CargoFeatures::Selected { features, no_default_features } => {
+ let mut feats = Vec::new();
+ if let Some(cfg) = cfg.as_ref() {
+ required_features(cfg, &mut feats);
+ }
- features.extend(cargo_config.features);
- features.extend(target_required_features);
+ feats.extend(features.iter().cloned());
+ feats.extend(target_required_features);
- features.dedup();
- for feature in features {
- args.push("--features".to_string());
- args.push(feature);
+ feats.dedup();
+ for feature in feats {
+ args.push("--features".to_owned());
+ args.push(feature);
+ }
+
+ if *no_default_features {
+ args.push("--no-default-features".to_owned());
+ }
}
}
-
Ok((args, extra_args))
}
@@ -112,7 +118,7 @@ impl CargoTargetSpec {
global_state_snapshot: &GlobalStateSnapshot,
file_id: FileId,
) -> Result<Option<CargoTargetSpec>> {
- let crate_id = match &*global_state_snapshot.analysis.crate_for(file_id)? {
+ let crate_id = match &*global_state_snapshot.analysis.crates_for(file_id)? {
&[crate_id, ..] => crate_id,
_ => return Ok(None),
};
@@ -136,7 +142,7 @@ impl CargoTargetSpec {
}
pub(crate) fn push_to(self, buf: &mut Vec<String>, kind: &RunnableKind) {
- buf.push("--package".to_string());
+ buf.push("--package".to_owned());
buf.push(self.package);
// Can't mix --doc with other target flags
@@ -145,23 +151,23 @@ impl CargoTargetSpec {
}
match self.target_kind {
TargetKind::Bin => {
- buf.push("--bin".to_string());
+ buf.push("--bin".to_owned());
buf.push(self.target);
}
TargetKind::Test => {
- buf.push("--test".to_string());
+ buf.push("--test".to_owned());
buf.push(self.target);
}
TargetKind::Bench => {
- buf.push("--bench".to_string());
+ buf.push("--bench".to_owned());
buf.push(self.target);
}
TargetKind::Example => {
- buf.push("--example".to_string());
+ buf.push("--example".to_owned());
buf.push(self.target);
}
TargetKind::Lib => {
- buf.push("--lib".to_string());
+ buf.push("--lib".to_owned());
}
TargetKind::Other | TargetKind::BuildScript => (),
}
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 f52e1e751..01fccc83e 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
@@ -24,7 +24,7 @@ use ide_db::base_db::{
use itertools::Itertools;
use oorandom::Rand32;
use profile::{Bytes, StopWatch};
-use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
+use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource};
use rayon::prelude::*;
use rustc_hash::FxHashSet;
use stdx::format_to;
@@ -55,7 +55,10 @@ impl flags::AnalysisStats {
};
let mut cargo_config = CargoConfig::default();
- cargo_config.no_sysroot = self.no_sysroot;
+ cargo_config.sysroot = match self.no_sysroot {
+ 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,
@@ -80,7 +83,8 @@ impl flags::AnalysisStats {
Some(build_scripts_sw.elapsed())
};
- let (host, vfs, _proc_macro) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _proc_macro) =
+ load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;
let db = host.raw_database();
eprint!("{:<20} {}", "Database loaded:", db_load_sw.elapsed());
eprint!(" (metadata {}", metadata_time);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index aa32654fb..5bcc97e22 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -31,8 +31,6 @@ xflags::xflags! {
default cmd lsp-server {
/// Print version.
optional --version
- /// Print help.
- optional -h, --help
/// Dump a LSP config JSON schema.
optional --print-config-schema
@@ -54,10 +52,10 @@ xflags::xflags! {
}
/// Batch typecheck project and print summary statistics
- cmd analysis-stats
+ cmd analysis-stats {
/// Directory with Cargo.toml.
required path: PathBuf
- {
+
optional --output format: OutputFormat
/// Randomize order in which crates, modules, and items are processed.
@@ -84,38 +82,37 @@ xflags::xflags! {
optional --skip-inference
}
- cmd diagnostics
+ cmd diagnostics {
/// Directory with Cargo.toml.
required path: PathBuf
- {
+
/// Don't run build scripts or load `OUT_DIR` values by running `cargo check` before analysis.
optional --disable-build-scripts
/// Don't use expand proc macros.
optional --disable-proc-macros
}
- cmd ssr
+ cmd ssr {
/// A structured search replace rule (`$a.foo($b) ==> bar($a, $b)`)
repeated rule: SsrRule
- {}
+ }
- cmd search
+ cmd search {
/// A structured search replace pattern (`$a.foo($b)`)
repeated pattern: SsrPattern
- {
/// Prints debug information for any nodes with source exactly equal to snippet.
optional --debug snippet: String
}
cmd proc-macro {}
- cmd lsif
+ cmd lsif {
required path: PathBuf
- {}
+ }
- cmd scip
+ cmd scip {
required path: PathBuf
- {}
+ }
}
}
@@ -150,7 +147,6 @@ pub enum RustAnalyzerCmd {
#[derive(Debug)]
pub struct LspServer {
pub version: bool,
- pub help: bool,
pub print_config_schema: bool,
}
@@ -218,7 +214,10 @@ pub struct Scip {
}
impl RustAnalyzer {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
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 5d1c013c3..5dba545b8 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
@@ -6,7 +6,7 @@ use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver};
use hir::db::DefDatabase;
use ide::{AnalysisHost, Change};
-use ide_db::base_db::CrateGraph;
+use ide_db::{base_db::CrateGraph, FxHashMap};
use proc_macro_api::ProcMacroServer;
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
use vfs::{loader::Handle, AbsPath, AbsPathBuf};
@@ -38,7 +38,7 @@ pub fn load_workspace_at(
workspace.set_build_scripts(build_scripts)
}
- load_workspace(workspace, load_config)
+ load_workspace(workspace, &cargo_config.extra_env, load_config)
}
// Note: Since this function is used by external tools that use rust-analyzer as a library
@@ -48,6 +48,7 @@ pub fn load_workspace_at(
// these tools need access to `ProjectWorkspace`, too, which `load_workspace_at` hides.
pub fn load_workspace(
ws: ProjectWorkspace,
+ extra_env: &FxHashMap<String, String>,
load_config: &LoadCargoConfig,
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroServer>)> {
let (sender, receiver) = unbounded();
@@ -59,10 +60,26 @@ pub fn load_workspace(
};
let proc_macro_client = if load_config.with_proc_macro {
- let path = AbsPathBuf::assert(std::env::current_exe()?);
- Ok(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
+ let mut path = AbsPathBuf::assert(std::env::current_exe()?);
+ let mut args = vec!["proc-macro"];
+
+ if let ProjectWorkspace::Cargo { sysroot, .. } | ProjectWorkspace::Json { sysroot, .. } =
+ &ws
+ {
+ if let Some(sysroot) = sysroot.as_ref() {
+ let standalone_server_name =
+ format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
+ let server_path = sysroot.root().join("libexec").join(&standalone_server_name);
+ if std::fs::metadata(&server_path).is_ok() {
+ path = server_path;
+ args = vec![];
+ }
+ }
+ }
+
+ ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|e| e.to_string())
} else {
- Err("proc macro server not started".to_owned())
+ Err("proc macro server disabled".to_owned())
};
let crate_graph = ws.to_crate_graph(
@@ -75,6 +92,7 @@ pub fn load_workspace(
vfs.set_file_contents(path.clone(), contents);
vfs.file_id(&path)
},
+ extra_env,
);
let project_folders = ProjectFolders::new(&[ws], &[]);
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 491c55a04..748306ea5 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
@@ -299,7 +299,8 @@ impl flags::Lsif {
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
- let (host, vfs, _proc_macro) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _proc_macro) =
+ load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;
let db = host.raw_database();
let analysis = host.analysis();
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 65cc993c4..8b77ccde0 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
@@ -8,8 +8,8 @@ use std::{
use crate::line_index::{LineEndings, LineIndex, OffsetEncoding};
use hir::Name;
use ide::{
- LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile, TextRange,
- TokenId,
+ LineCol, MonikerDescriptorKind, StaticIndex, StaticIndexedFile, TextRange, TokenId,
+ TokenStaticData,
};
use ide_db::LineIndexDatabase;
use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
@@ -40,7 +40,8 @@ impl flags::Scip {
let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
- let (host, vfs, _) = load_workspace(workspace, &load_cargo_config)?;
+ let (host, vfs, _) =
+ load_workspace(workspace, &cargo_config.extra_env, &load_cargo_config)?;
let db = host.raw_database();
let analysis = host.analysis();
@@ -74,7 +75,7 @@ impl flags::Scip {
let mut symbols_emitted: HashSet<TokenId> = HashSet::default();
let mut tokens_to_symbol: HashMap<TokenId, String> = HashMap::new();
- for file in si.files {
+ for StaticIndexedFile { file_id, tokens, .. } in si.files {
let mut local_count = 0;
let mut new_local_symbol = || {
let new_symbol = scip::types::Symbol::new_local(local_count);
@@ -83,7 +84,6 @@ impl flags::Scip {
new_symbol
};
- let StaticIndexedFile { file_id, tokens, .. } = file;
let relative_path = match get_relative_filepath(&vfs, &rootpath, file_id) {
Some(relative_path) => relative_path,
None => continue,
@@ -106,28 +106,20 @@ impl flags::Scip {
let mut occurrence = scip_types::Occurrence::default();
occurrence.range = text_range_to_scip_range(&line_index, range);
- occurrence.symbol = match tokens_to_symbol.get(&id) {
- Some(symbol) => symbol.clone(),
- None => {
- let symbol = match &token.moniker {
- Some(moniker) => moniker_to_symbol(&moniker),
- None => new_local_symbol(),
- };
-
- let symbol = scip::symbol::format_symbol(symbol);
- tokens_to_symbol.insert(id, symbol.clone());
- symbol
- }
- };
+ occurrence.symbol = tokens_to_symbol
+ .entry(id)
+ .or_insert_with(|| {
+ let symbol = token_to_symbol(&token).unwrap_or_else(&mut new_local_symbol);
+ scip::symbol::format_symbol(symbol)
+ })
+ .clone();
if let Some(def) = token.definition {
if def.range == range {
occurrence.symbol_roles |= scip_types::SymbolRole::Definition as i32;
}
- if !symbols_emitted.contains(&id) {
- symbols_emitted.insert(id);
-
+ if symbols_emitted.insert(id) {
let mut symbol_info = scip_types::SymbolInformation::default();
symbol_info.symbol = occurrence.symbol.clone();
if let Some(hover) = &token.hover {
@@ -206,9 +198,11 @@ fn new_descriptor(name: Name, suffix: scip_types::descriptor::Suffix) -> scip_ty
///
/// Only returns a Symbol when it's a non-local symbol.
/// So if the visibility isn't outside of a document, then it will return None
-fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
+fn token_to_symbol(token: &TokenStaticData) -> Option<scip_types::Symbol> {
use scip_types::descriptor::Suffix::*;
+ let moniker = token.moniker.as_ref()?;
+
let package_name = moniker.package_information.name.clone();
let version = moniker.package_information.version.clone();
let descriptors = moniker
@@ -232,7 +226,7 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
})
.collect();
- scip_types::Symbol {
+ Some(scip_types::Symbol {
scheme: "rust-analyzer".into(),
package: Some(scip_types::Package {
manager: "cargo".to_string(),
@@ -243,19 +237,15 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
.into(),
descriptors,
..Default::default()
- }
+ })
}
#[cfg(test)]
mod test {
use super::*;
- use hir::Semantics;
- use ide::{AnalysisHost, FilePosition};
- use ide_db::defs::IdentClass;
- use ide_db::{base_db::fixture::ChangeFixture, helpers::pick_best_token};
+ use ide::{AnalysisHost, FilePosition, StaticIndex, TextSize};
+ use ide_db::base_db::fixture::ChangeFixture;
use scip::symbol::format_symbol;
- use syntax::SyntaxKind::*;
- use syntax::{AstNode, T};
fn position(ra_fixture: &str) -> (AnalysisHost, FilePosition) {
let mut host = AnalysisHost::default();
@@ -272,53 +262,33 @@ mod test {
fn check_symbol(ra_fixture: &str, expected: &str) {
let (host, position) = position(ra_fixture);
+ let analysis = host.analysis();
+ let si = StaticIndex::compute(&analysis);
+
let FilePosition { file_id, offset } = position;
- let db = host.raw_database();
- let sema = &Semantics::new(db);
- let file = sema.parse(file_id).syntax().clone();
- 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]
- | COMMENT => 2,
- kind if kind.is_trivia() => 0,
- _ => 1,
- })
- .expect("OK OK");
-
- let navs = sema
- .descend_into_macros(original_token.clone())
- .into_iter()
- .filter_map(|token| {
- IdentClass::classify_token(sema, &token).map(IdentClass::definitions).map(|it| {
- it.into_iter().flat_map(|def| {
- let module = def.module(db).unwrap();
- let current_crate = module.krate();
-
- match MonikerResult::from_def(sema.db, def, current_crate) {
- Some(moniker_result) => Some(moniker_to_symbol(&moniker_result)),
- None => None,
- }
- })
- })
- })
- .flatten()
- .collect::<Vec<_>>();
+ let mut found_symbol = None;
+ for file in &si.files {
+ if file.file_id != file_id {
+ continue;
+ }
+ for &(range, id) in &file.tokens {
+ if range.contains(offset - TextSize::from(1)) {
+ let token = si.tokens.get(id).unwrap();
+ found_symbol = token_to_symbol(token);
+ break;
+ }
+ }
+ }
if expected == "" {
- assert_eq!(0, navs.len(), "must have no symbols {:?}", navs);
+ assert!(found_symbol.is_none(), "must have no symbols {:?}", found_symbol);
return;
}
- assert_eq!(1, navs.len(), "must have one symbol {:?}", navs);
-
- let res = navs.get(0).unwrap();
- let formatted = format_symbol(res.clone());
+ assert!(found_symbol.is_some(), "must have one symbol {:?}", found_symbol);
+ let res = found_symbol.unwrap();
+ let formatted = format_symbol(res);
assert_eq!(formatted, expected);
}
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 54dcb42d9..85322f12a 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -7,7 +7,7 @@
//! configure the server itself, feature flags are passed into analysis, and
//! tweak things like automatic insertion of `()` in completions.
-use std::{ffi::OsString, fmt, iter, path::PathBuf};
+use std::{fmt, iter, path::PathBuf};
use flycheck::FlycheckConfig;
use ide::{
@@ -22,7 +22,8 @@ use ide_db::{
use itertools::Itertools;
use lsp_types::{ClientCapabilities, MarkupKind};
use project_model::{
- CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource, UnsetTestCrates,
+ CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource,
+ UnsetTestCrates,
};
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{de::DeserializeOwned, Deserialize};
@@ -68,6 +69,19 @@ config_data! {
cargo_autoreload: bool = "true",
/// Run build scripts (`build.rs`) for more precise code analysis.
cargo_buildScripts_enable: bool = "true",
+ /// Specifies the working directory for running build scripts.
+ /// - "workspace": run build scripts for a workspace in the workspace's root directory.
+ /// This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.
+ /// - "root": run build scripts in the project's root directory.
+ /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+ /// is set.
+ cargo_buildScripts_invocationLocation: InvocationLocation = "\"workspace\"",
+ /// Specifies the invocation strategy to use when running the build scripts command.
+ /// If `per_workspace` is set, the command will be executed for each workspace.
+ /// If `once` is set, the command will be executed once.
+ /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+ /// is set.
+ cargo_buildScripts_invocationStrategy: InvocationStrategy = "\"per_workspace\"",
/// Override the command rust-analyzer uses to run build scripts and
/// build procedural macros. The command is required to output json
/// and should therefore include `--message-format=json` or a similar
@@ -84,14 +98,22 @@ config_data! {
/// Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
/// avoid checking unnecessary things.
cargo_buildScripts_useRustcWrapper: bool = "true",
+ /// Extra environment variables that will be set when running cargo, rustc
+ /// or other commands within the workspace. Useful for setting RUSTFLAGS.
+ cargo_extraEnv: FxHashMap<String, String> = "{}",
/// List of features to activate.
///
/// Set this to `"all"` to pass `--all-features` to cargo.
- cargo_features: CargoFeatures = "[]",
+ cargo_features: CargoFeaturesDef = "[]",
/// Whether to pass `--no-default-features` to cargo.
cargo_noDefaultFeatures: bool = "false",
- /// Internal config for debugging, disables loading of sysroot crates.
- cargo_noSysroot: bool = "false",
+ /// Relative path to the sysroot, or "discover" to try to automatically find it via
+ /// "rustc --print sysroot".
+ ///
+ /// Unsetting this disables sysroot loading.
+ ///
+ /// This option does not take effect until rust-analyzer is restarted.
+ cargo_sysroot: Option<String> = "\"discover\"",
/// Compilation target override (target triple).
cargo_target: Option<String> = "null",
/// Unsets `#[cfg(test)]` for the specified crates.
@@ -105,11 +127,28 @@ config_data! {
checkOnSave_enable: bool = "true",
/// Extra arguments for `cargo check`.
checkOnSave_extraArgs: Vec<String> = "[]",
+ /// Extra environment variables that will be set when running `cargo check`.
+ /// Extends `#rust-analyzer.cargo.extraEnv#`.
+ checkOnSave_extraEnv: FxHashMap<String, String> = "{}",
/// List of features to activate. Defaults to
/// `#rust-analyzer.cargo.features#`.
///
/// Set to `"all"` to pass `--all-features` to Cargo.
- checkOnSave_features: Option<CargoFeatures> = "null",
+ checkOnSave_features: Option<CargoFeaturesDef> = "null",
+ /// Specifies the working directory for running checks.
+ /// - "workspace": run checks for workspaces in the corresponding workspaces' root directories.
+ // FIXME: Ideally we would support this in some way
+ /// This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.
+ /// - "root": run checks in the project's root directory.
+ /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+ /// is set.
+ checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"",
+ /// Specifies the invocation strategy to use when running the checkOnSave command.
+ /// If `per_workspace` is set, the command will be executed for each workspace.
+ /// If `once` is set, the command will be executed once.
+ /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+ /// is set.
+ checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"",
/// Whether to pass `--no-default-features` to Cargo. Defaults to
/// `#rust-analyzer.cargo.noDefaultFeatures#`.
checkOnSave_noDefaultFeatures: Option<bool> = "null",
@@ -219,7 +258,6 @@ config_data! {
files_excludeDirs: Vec<PathBuf> = "[]",
/// Controls file watching implementation.
files_watcher: FilesWatcherDef = "\"client\"",
-
/// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords.
highlightRelated_breakPoints_enable: bool = "true",
/// Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`).
@@ -263,6 +301,8 @@ config_data! {
imports_group_enable: bool = "true",
/// Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.
imports_merge_glob: bool = "true",
+ /// Prefer to unconditionally use imports of the core and alloc crate, over the std crate.
+ imports_prefer_no_std: bool = "false",
/// The path structure for newly inserted paths to use.
imports_prefix: ImportPrefixDef = "\"plain\"",
@@ -307,6 +347,7 @@ config_data! {
/// Join lines unwraps trivial blocks.
joinLines_unwrapTrivialBlock: bool = "true",
+
/// Whether to show `Debug` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_debug_enable: bool = "true",
@@ -318,6 +359,8 @@ config_data! {
/// Whether to show `Implementations` lens. Only applies when
/// `#rust-analyzer.lens.enable#` is set.
lens_implementations_enable: bool = "true",
+ /// Where to render annotations.
+ lens_location: AnnotationLocation = "\"above_name\"",
/// Whether to show `References` lens for Struct, Enum, and Union.
/// Only applies when `#rust-analyzer.lens.enable#` is set.
lens_references_adt_enable: bool = "false",
@@ -359,6 +402,9 @@ config_data! {
/// this is rust-analyzer itself, but we override this in tests).
procMacro_server: Option<PathBuf> = "null",
+ /// Exclude imports from find-all-references.
+ references_excludeImports: bool = "false",
+
/// Command to be executed instead of 'cargo' for runnables.
runnables_command: Option<String> = "null",
/// Additional arguments to be passed to cargo for runnables such as
@@ -494,6 +540,25 @@ pub struct LensConfig {
pub refs_adt: bool, // for Struct, Enum, Union and Trait
pub refs_trait: bool, // for Struct, Enum, Union and Trait
pub enum_variant_refs: bool,
+
+ // annotations
+ pub location: AnnotationLocation,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum AnnotationLocation {
+ AboveName,
+ AboveWholeItem,
+}
+
+impl From<AnnotationLocation> for ide::AnnotationLocation {
+ fn from(location: AnnotationLocation) -> Self {
+ match location {
+ AnnotationLocation::AboveName => ide::AnnotationLocation::AboveName,
+ AnnotationLocation::AboveWholeItem => ide::AnnotationLocation::AboveWholeItem,
+ }
+ }
}
impl LensConfig {
@@ -918,6 +983,7 @@ impl Config {
ExprFillDefaultDef::Default => ExprFillDefaultMode::Default,
},
insert_use: self.insert_use_config(),
+ prefer_no_std: self.data.imports_prefer_no_std,
}
}
@@ -929,19 +995,31 @@ impl Config {
}
}
+ pub fn extra_env(&self) -> &FxHashMap<String, String> {
+ &self.data.cargo_extraEnv
+ }
+
+ pub fn check_on_save_extra_env(&self) -> FxHashMap<String, String> {
+ let mut extra_env = self.data.cargo_extraEnv.clone();
+ extra_env.extend(self.data.checkOnSave_extraEnv.clone());
+ extra_env
+ }
+
pub fn lru_capacity(&self) -> Option<usize> {
self.data.lru_capacity
}
- pub fn proc_macro_srv(&self) -> Option<(AbsPathBuf, Vec<OsString>)> {
+ pub fn proc_macro_srv(&self) -> Option<(AbsPathBuf, /* is path explicitly set */ bool)> {
if !self.data.procMacro_enable {
return None;
}
- let path = match &self.data.procMacro_server {
- Some(it) => self.root_path.join(it),
- None => AbsPathBuf::assert(std::env::current_exe().ok()?),
- };
- Some((path, vec!["proc-macro".into()]))
+ Some(match &self.data.procMacro_server {
+ Some(it) => (
+ AbsPathBuf::try_from(it.clone()).unwrap_or_else(|path| self.root_path.join(path)),
+ true,
+ ),
+ None => (AbsPathBuf::assert(std::env::current_exe().ok()?), false),
+ })
}
pub fn dummy_replacements(&self) -> &FxHashMap<Box<str>, Box<[Box<str>]>> {
@@ -984,20 +1062,39 @@ impl Config {
RustcSource::Path(self.root_path.join(rustc_src))
}
});
+ let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| {
+ if sysroot == "discover" {
+ RustcSource::Discover
+ } else {
+ RustcSource::Path(self.root_path.join(sysroot))
+ }
+ });
CargoConfig {
- no_default_features: self.data.cargo_noDefaultFeatures,
- all_features: matches!(self.data.cargo_features, CargoFeatures::All),
features: match &self.data.cargo_features {
- CargoFeatures::All => vec![],
- CargoFeatures::Listed(it) => it.clone(),
+ CargoFeaturesDef::All => CargoFeatures::All,
+ CargoFeaturesDef::Selected(features) => CargoFeatures::Selected {
+ features: features.clone(),
+ no_default_features: self.data.cargo_noDefaultFeatures,
+ },
},
target: self.data.cargo_target.clone(),
- no_sysroot: self.data.cargo_noSysroot,
+ sysroot,
rustc_source,
unset_test_crates: UnsetTestCrates::Only(self.data.cargo_unsetTest.clone()),
wrap_rustc_in_build_scripts: self.data.cargo_buildScripts_useRustcWrapper,
+ invocation_strategy: match self.data.cargo_buildScripts_invocationStrategy {
+ InvocationStrategy::Once => project_model::InvocationStrategy::Once,
+ InvocationStrategy::PerWorkspace => project_model::InvocationStrategy::PerWorkspace,
+ },
+ invocation_location: match self.data.cargo_buildScripts_invocationLocation {
+ InvocationLocation::Root => {
+ project_model::InvocationLocation::Root(self.root_path.clone())
+ }
+ InvocationLocation::Workspace => project_model::InvocationLocation::Workspace,
+ },
run_build_script_command: self.data.cargo_buildScripts_overrideCommand.clone(),
+ extra_env: self.data.cargo_extraEnv.clone(),
}
}
@@ -1023,7 +1120,23 @@ impl Config {
Some(args) if !args.is_empty() => {
let mut args = args.clone();
let command = args.remove(0);
- FlycheckConfig::CustomCommand { command, args }
+ FlycheckConfig::CustomCommand {
+ command,
+ args,
+ extra_env: self.check_on_save_extra_env(),
+ invocation_strategy: match self.data.checkOnSave_invocationStrategy {
+ InvocationStrategy::Once => flycheck::InvocationStrategy::Once,
+ InvocationStrategy::PerWorkspace => {
+ flycheck::InvocationStrategy::PerWorkspace
+ }
+ },
+ invocation_location: match self.data.checkOnSave_invocationLocation {
+ InvocationLocation::Root => {
+ flycheck::InvocationLocation::Root(self.root_path.clone())
+ }
+ InvocationLocation::Workspace => flycheck::InvocationLocation::Workspace,
+ },
+ }
}
Some(_) | None => FlycheckConfig::CargoCommand {
command: self.data.checkOnSave_command.clone(),
@@ -1039,7 +1152,7 @@ impl Config {
.unwrap_or(self.data.cargo_noDefaultFeatures),
all_features: matches!(
self.data.checkOnSave_features.as_ref().unwrap_or(&self.data.cargo_features),
- CargoFeatures::All
+ CargoFeaturesDef::All
),
features: match self
.data
@@ -1047,10 +1160,11 @@ impl Config {
.clone()
.unwrap_or_else(|| self.data.cargo_features.clone())
{
- CargoFeatures::All => vec![],
- CargoFeatures::Listed(it) => it,
+ CargoFeaturesDef::All => vec![],
+ CargoFeaturesDef::Selected(it) => it,
},
extra_args: self.data.checkOnSave_extraArgs.clone(),
+ extra_env: self.check_on_save_extra_env(),
},
};
Some(flycheck_config)
@@ -1133,6 +1247,7 @@ impl Config {
CallableCompletionDef::None => None,
},
insert_use: self.insert_use_config(),
+ prefer_no_std: self.data.imports_prefer_no_std,
snippet_cap: SnippetCap::new(try_or_def!(
self.caps
.text_document
@@ -1147,6 +1262,10 @@ impl Config {
}
}
+ pub fn find_all_refs_exclude_imports(&self) -> bool {
+ self.data.references_excludeImports
+ }
+
pub fn snippet_cap(&self) -> bool {
self.experimental("snippetTextEdit")
}
@@ -1156,6 +1275,7 @@ impl Config {
snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")),
allowed: None,
insert_use: self.insert_use_config(),
+ prefer_no_std: self.data.imports_prefer_no_std,
}
}
@@ -1185,6 +1305,7 @@ impl Config {
refs_trait: self.data.lens_enable && self.data.lens_references_trait_enable,
enum_variant_refs: self.data.lens_enable
&& self.data.lens_references_enumVariant_enable,
+ location: self.data.lens_location,
}
}
@@ -1509,10 +1630,24 @@ enum CallableCompletionDef {
#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
-enum CargoFeatures {
+enum CargoFeaturesDef {
#[serde(deserialize_with = "de_unit_v::all")]
All,
- Listed(Vec<String>),
+ Selected(Vec<String>),
+}
+
+#[derive(Deserialize, Debug, Clone)]
+#[serde(rename_all = "snake_case")]
+enum InvocationStrategy {
+ Once,
+ PerWorkspace,
+}
+
+#[derive(Deserialize, Debug, Clone)]
+#[serde(rename_all = "snake_case")]
+enum InvocationLocation {
+ Root,
+ Workspace,
}
#[derive(Deserialize, Debug, Clone)]
@@ -1857,7 +1992,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"Only show mutable reborrow hints."
]
},
- "CargoFeatures" => set! {
+ "CargoFeaturesDef" => set! {
"anyOf": [
{
"type": "string",
@@ -1874,7 +2009,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
}
],
},
- "Option<CargoFeatures>" => set! {
+ "Option<CargoFeaturesDef>" => set! {
"anyOf": [
{
"type": "string",
@@ -1921,6 +2056,30 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
"Use server-side file watching",
],
},
+ "AnnotationLocation" => set! {
+ "type": "string",
+ "enum": ["above_name", "above_whole_item"],
+ "enumDescriptions": [
+ "Render annotations above the name of the item.",
+ "Render annotations above the whole item, including documentation comments and attributes."
+ ],
+ },
+ "InvocationStrategy" => set! {
+ "type": "string",
+ "enum": ["per_workspace", "once"],
+ "enumDescriptions": [
+ "The command will be executed for each workspace.",
+ "The command will be executed once."
+ ],
+ },
+ "InvocationLocation" => set! {
+ "type": "string",
+ "enum": ["workspace", "root"],
+ "enumDescriptions": [
+ "The command will be executed in the corresponding workspace root.",
+ "The command will be executed in the project root."
+ ],
+ },
_ => panic!("missing entry for {}: {}", ty, default),
}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs
index f16559148..57899b599 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/dispatch.rs
@@ -52,7 +52,7 @@ impl<'a> RequestDispatcher<'a> {
let _pctx = stdx::panic_context::enter(panic_context);
f(self.global_state, params)
};
- if let Ok(response) = result_to_response::<R>(req.id.clone(), result) {
+ if let Ok(response) = result_to_response::<R>(req.id, result) {
self.global_state.respond(response);
}
@@ -80,7 +80,7 @@ impl<'a> RequestDispatcher<'a> {
f(global_state_snapshot, params)
});
- if let Ok(response) = thread_result_to_response::<R>(req.id.clone(), result) {
+ if let Ok(response) = thread_result_to_response::<R>(req.id, result) {
self.global_state.respond(response);
}
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 7bdd34d1f..f2db9a273 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
@@ -95,22 +95,22 @@ pub(crate) fn annotation(
match resolve {
lsp_ext::CodeLensResolveData::Impls(params) => {
- let file_id =
- snap.url_to_file_id(&params.text_document_position_params.text_document.uri)?;
+ let pos @ FilePosition { file_id, .. } =
+ file_position(snap, params.text_document_position_params)?;
let line_index = snap.file_line_index(file_id)?;
Ok(Annotation {
range: text_range(&line_index, code_lens.range)?,
- kind: AnnotationKind::HasImpls { file_id, data: None },
+ kind: AnnotationKind::HasImpls { pos, data: None },
})
}
lsp_ext::CodeLensResolveData::References(params) => {
- let file_id = snap.url_to_file_id(&params.text_document.uri)?;
+ let pos @ FilePosition { file_id, .. } = file_position(snap, params)?;
let line_index = snap.file_line_index(file_id)?;
Ok(Annotation {
range: text_range(&line_index, code_lens.range)?,
- kind: AnnotationKind::HasReferences { file_id, data: None },
+ kind: AnnotationKind::HasReferences { pos, data: None },
})
}
}
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 92df4d70f..3fb06c31f 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
@@ -64,7 +64,7 @@ pub(crate) struct GlobalState {
pub(crate) source_root_config: SourceRootConfig,
pub(crate) proc_macro_clients: Vec<Result<ProcMacroServer, String>>,
- pub(crate) flycheck: Vec<FlycheckHandle>,
+ pub(crate) flycheck: Arc<[FlycheckHandle]>,
pub(crate) flycheck_sender: Sender<flycheck::Message>,
pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
@@ -117,6 +117,7 @@ pub(crate) struct GlobalStateSnapshot {
vfs: Arc<RwLock<(vfs::Vfs, NoHashHashMap<FileId, LineEndings>)>>,
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
pub(crate) proc_macros_loaded: bool,
+ pub(crate) flycheck: Arc<[FlycheckHandle]>,
}
impl std::panic::UnwindSafe for GlobalStateSnapshot {}
@@ -155,7 +156,7 @@ impl GlobalState {
source_root_config: SourceRootConfig::default(),
proc_macro_clients: vec![],
- flycheck: Vec::new(),
+ flycheck: Arc::new([]),
flycheck_sender,
flycheck_receiver,
@@ -185,11 +186,48 @@ impl GlobalState {
let (change, changed_files) = {
let mut change = Change::new();
let (vfs, line_endings_map) = &mut *self.vfs.write();
- let changed_files = vfs.take_changes();
+ let mut changed_files = vfs.take_changes();
if changed_files.is_empty() {
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| {
+ use vfs::ChangeKind::*;
+
+ if a.file_id != b.file_id {
+ return false;
+ }
+
+ 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,
+ }
+ });
+
for file in &changed_files {
if let Some(path) = vfs.file_path(file.file_id).as_path() {
let path = path.to_path_buf();
@@ -258,6 +296,7 @@ impl GlobalState {
mem_docs: self.mem_docs.clone(),
semantic_tokens_cache: Arc::clone(&self.semantic_tokens_cache),
proc_macros_loaded: !self.fetch_build_data_queue.last_op_result().0.is_empty(),
+ flycheck: self.flycheck.clone(),
}
}
@@ -317,6 +356,10 @@ impl GlobalState {
}
}
+ pub(crate) fn is_completed(&self, request: &lsp_server::Request) -> bool {
+ self.req_queue.incoming.is_completed(&request.id)
+ }
+
fn send(&mut self, message: lsp_server::Message) {
self.sender.send(message).unwrap()
}
@@ -357,6 +400,10 @@ impl GlobalStateSnapshot {
url_from_abs_path(path)
}
+ pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath {
+ self.vfs.read().0.file_path(file_id)
+ }
+
pub(crate) fn cargo_target_for_crate_root(
&self,
crate_id: CrateId,
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 e79cf3d3f..34795a8eb 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers.rs
@@ -10,8 +10,8 @@ use std::{
use anyhow::Context;
use ide::{
AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange,
- HoverAction, HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SingleResolve,
- SourceChange, TextEdit,
+ HoverAction, HoverGotoTypeData, Query, RangeInfo, ReferenceCategory, Runnable, RunnableKind,
+ SingleResolve, SourceChange, TextEdit,
};
use ide_db::SymbolKind;
use lsp_server::ErrorCode;
@@ -658,7 +658,7 @@ pub(crate) fn handle_parent_module(
// check if invoked at the crate root
let file_id = from_proto::file_id(&snap, &params.text_document.uri)?;
- let crate_id = match snap.analysis.crate_for(file_id)?.first() {
+ let crate_id = match snap.analysis.crates_for(file_id)?.first() {
Some(&crate_id) => crate_id,
None => return Ok(None),
};
@@ -1012,6 +1012,8 @@ pub(crate) fn handle_references(
let _p = profile::span("handle_references");
let position = from_proto::file_position(&snap, params.text_document_position)?;
+ let exclude_imports = snap.config.find_all_refs_exclude_imports();
+
let refs = match snap.analysis.find_all_refs(position, None)? {
None => return Ok(None),
Some(refs) => refs,
@@ -1032,7 +1034,11 @@ pub(crate) fn handle_references(
refs.references
.into_iter()
.flat_map(|(file_id, refs)| {
- refs.into_iter().map(move |(range, _)| FileRange { file_id, range })
+ refs.into_iter()
+ .filter(|&(_, category)| {
+ !exclude_imports || category != Some(ReferenceCategory::Import)
+ })
+ .map(move |(range, _)| FileRange { file_id, range })
})
.chain(decl)
})
@@ -1234,6 +1240,7 @@ pub(crate) fn handle_code_lens(
annotate_references: lens_config.refs_adt,
annotate_method_references: lens_config.method_refs,
annotate_enum_variant_references: lens_config.enum_variant_refs,
+ location: lens_config.location.into(),
},
file_id,
)?;
@@ -1283,7 +1290,7 @@ pub(crate) fn handle_document_highlight(
.into_iter()
.map(|ide::HighlightedRange { range, category }| lsp_types::DocumentHighlight {
range: to_proto::range(&line_index, range),
- kind: category.map(to_proto::document_highlight_kind),
+ kind: category.and_then(to_proto::document_highlight_kind),
})
.collect();
Ok(Some(res))
@@ -1775,13 +1782,22 @@ fn run_rustfmt(
) -> Result<Option<Vec<lsp_types::TextEdit>>> {
let file_id = from_proto::file_id(snap, &text_document.uri)?;
let file = snap.analysis.file_text(file_id)?;
- let crate_ids = snap.analysis.crate_for(file_id)?;
+
+ // find the edition of the package the file belongs to
+ // (if it belongs to multiple we'll just pick the first one and pray)
+ let edition = snap
+ .analysis
+ .relevant_crates_for(file_id)?
+ .into_iter()
+ .find_map(|crate_id| snap.cargo_target_for_crate_root(crate_id))
+ .map(|(ws, target)| ws[ws[target].package].edition);
let line_index = snap.file_line_index(file_id)?;
let mut command = match snap.config.rustfmt() {
RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
let mut cmd = process::Command::new(toolchain::rustfmt());
+ cmd.envs(snap.config.extra_env());
cmd.args(extra_args);
// try to chdir to the file so we can respect `rustfmt.toml`
// FIXME: use `rustfmt --config-path` once
@@ -1800,9 +1816,7 @@ fn run_rustfmt(
);
}
}
- if let Some(&crate_id) = crate_ids.first() {
- // Assume all crates are in the same edition
- let edition = snap.analysis.crate_edition(crate_id)?;
+ if let Some(edition) = edition {
cmd.arg("--edition");
cmd.arg(edition.to_string());
}
@@ -1839,6 +1853,7 @@ fn run_rustfmt(
}
RustfmtConfig::CustomCommand { command, args } => {
let mut cmd = process::Command::new(command);
+ cmd.envs(snap.config.extra_env());
cmd.args(args);
cmd
}
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 e49a98685..96b1cb6b1 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
@@ -145,6 +145,7 @@ fn integrated_completion_benchmark() {
skip_glob_imports: true,
},
snippets: Vec::new(),
+ prefer_no_std: false,
};
let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -182,6 +183,7 @@ fn integrated_completion_benchmark() {
skip_glob_imports: true,
},
snippets: Vec::new(),
+ prefer_no_std: false,
};
let position =
FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
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 5a37cbe2e..b3cea64d4 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
@@ -87,6 +87,7 @@ impl GlobalState {
state: Progress,
message: Option<String>,
fraction: Option<f64>,
+ cancel_token: Option<String>,
) {
if !self.config.work_done_progress() {
return;
@@ -95,7 +96,10 @@ impl GlobalState {
assert!((0.0..=1.0).contains(&f));
(f * 100.0) as u32
});
- let token = lsp_types::ProgressToken::String(format!("rustAnalyzer/{}", title));
+ let cancellable = Some(cancel_token.is_some());
+ let token = lsp_types::ProgressToken::String(
+ cancel_token.unwrap_or_else(|| format!("rustAnalyzer/{}", title)),
+ );
let work_done_progress = match state {
Progress::Begin => {
self.send_request::<lsp_types::request::WorkDoneProgressCreate>(
@@ -105,14 +109,14 @@ impl GlobalState {
lsp_types::WorkDoneProgress::Begin(lsp_types::WorkDoneProgressBegin {
title: title.into(),
- cancellable: None,
+ cancellable,
message,
percentage,
})
}
Progress::Report => {
lsp_types::WorkDoneProgress::Report(lsp_types::WorkDoneProgressReport {
- cancellable: None,
+ cancellable,
message,
percentage,
})
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 3cfbc2e4e..2c928a580 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
@@ -10,7 +10,7 @@ use std::{
use always_assert::always;
use crossbeam_channel::{select, Receiver};
use flycheck::FlycheckHandle;
-use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath};
+use ide_db::base_db::{SourceDatabaseExt, VfsPath};
use itertools::Itertools;
use lsp_server::{Connection, Notification, Request};
use lsp_types::notification::Notification as _;
@@ -191,7 +191,7 @@ impl GlobalState {
// NOTE: don't count blocking select! call as a loop-turn time
let _p = profile::span("GlobalState::handle_event");
- tracing::debug!("handle_event({:?})", event);
+ tracing::debug!("{:?} handle_event({:?})", loop_start, event);
let task_queue_len = self.task_pool.handle.len();
if task_queue_len > 0 {
tracing::info!("task queue len: {}", task_queue_len);
@@ -257,7 +257,7 @@ impl GlobalState {
}
};
- self.report_progress("Indexing", state, message, Some(fraction));
+ self.report_progress("Indexing", state, message, Some(fraction), None);
}
}
Event::Vfs(message) => {
@@ -425,7 +425,9 @@ impl GlobalState {
fn handle_task(&mut self, prime_caches_progress: &mut Vec<PrimeCachesProgress>, task: Task) {
match task {
Task::Response(response) => self.respond(response),
- Task::Retry(req) => self.on_request(req),
+ // Only retry requests that haven't been cancelled. Otherwise we do unnecessary work.
+ Task::Retry(req) if !self.is_completed(&req) => self.on_request(req),
+ Task::Retry(_) => (),
Task::Diagnostics(diagnostics_per_file) => {
for (file_id, diagnostics) in diagnostics_per_file {
self.diagnostics.set_native_diagnostics(file_id, diagnostics)
@@ -463,7 +465,7 @@ impl GlobalState {
}
};
- self.report_progress("Fetching", state, msg, None);
+ self.report_progress("Fetching", state, msg, None, None);
}
Task::FetchBuildData(progress) => {
let (state, msg) = match progress {
@@ -479,7 +481,7 @@ impl GlobalState {
};
if let Some(state) = state {
- self.report_progress("Loading", state, msg, None);
+ self.report_progress("Loading", state, msg, None, None);
}
}
}
@@ -516,6 +518,7 @@ impl GlobalState {
state,
Some(format!("{}/{}", n_done, n_total)),
Some(Progress::fraction(n_done, n_total)),
+ None,
)
}
}
@@ -540,7 +543,10 @@ impl GlobalState {
diag.fix,
),
Err(err) => {
- tracing::error!("File with cargo diagnostic not found in VFS: {}", err);
+ tracing::error!(
+ "flycheck {id}: File with cargo diagnostic not found in VFS: {}",
+ err
+ );
}
};
}
@@ -582,7 +588,13 @@ impl GlobalState {
} else {
format!("cargo check (#{})", id + 1)
};
- self.report_progress(&title, state, message, None);
+ self.report_progress(
+ &title,
+ state,
+ message,
+ None,
+ Some(format!("rust-analyzer/checkOnSave/{}", id)),
+ );
}
}
}
@@ -696,7 +708,16 @@ impl GlobalState {
this.cancel(id);
Ok(())
})?
- .on::<lsp_types::notification::WorkDoneProgressCancel>(|_this, _params| {
+ .on::<lsp_types::notification::WorkDoneProgressCancel>(|this, params| {
+ if let lsp_types::NumberOrString::String(s) = &params.token {
+ if let Some(id) = s.strip_prefix("rust-analyzer/checkOnSave/") {
+ if let Ok(id) = u32::from_str_radix(id, 10) {
+ if let Some(flycheck) = this.flycheck.get(id as usize) {
+ flycheck.cancel();
+ }
+ }
+ }
+ }
// Just ignore this. It is OK to continue sending progress
// notifications for this token, as the client can't know when
// we accepted notification.
@@ -709,7 +730,7 @@ impl GlobalState {
.insert(path.clone(), DocumentData::new(params.text_document.version))
.is_err();
if already_exists {
- tracing::error!("duplicate DidOpenTextDocument: {}", path)
+ tracing::error!("duplicate DidOpenTextDocument: {}", path);
}
this.vfs
.write()
@@ -756,69 +777,7 @@ impl GlobalState {
Ok(())
})?
.on::<lsp_types::notification::DidSaveTextDocument>(|this, params| {
- let mut updated = false;
if let Ok(vfs_path) = from_proto::vfs_path(&params.text_document.uri) {
- let (vfs, _) = &*this.vfs.read();
-
- // Trigger flychecks for all workspaces that depend on the saved file
- if let Some(file_id) = vfs.file_id(&vfs_path) {
- let analysis = this.analysis_host.analysis();
- // Crates containing or depending on the saved file
- let crate_ids: Vec<_> = analysis
- .crate_for(file_id)?
- .into_iter()
- .flat_map(|id| {
- this.analysis_host
- .raw_database()
- .crate_graph()
- .transitive_rev_deps(id)
- })
- .sorted()
- .unique()
- .collect();
-
- let crate_root_paths: Vec<_> = crate_ids
- .iter()
- .filter_map(|&crate_id| {
- analysis
- .crate_root(crate_id)
- .map(|file_id| {
- vfs.file_path(file_id).as_path().map(ToOwned::to_owned)
- })
- .transpose()
- })
- .collect::<ide::Cancellable<_>>()?;
- let crate_root_paths: Vec<_> =
- crate_root_paths.iter().map(Deref::deref).collect();
-
- // Find all workspaces that have at least one target containing the saved file
- let workspace_ids =
- this.workspaces.iter().enumerate().filter(|(_, ws)| match ws {
- project_model::ProjectWorkspace::Cargo { cargo, .. } => {
- cargo.packages().any(|pkg| {
- cargo[pkg].targets.iter().any(|&it| {
- crate_root_paths.contains(&cargo[it].root.as_path())
- })
- })
- }
- project_model::ProjectWorkspace::Json { project, .. } => project
- .crates()
- .any(|(c, _)| crate_ids.iter().any(|&crate_id| crate_id == c)),
- project_model::ProjectWorkspace::DetachedFiles { .. } => false,
- });
-
- // Find and trigger corresponding flychecks
- for flycheck in &this.flycheck {
- for (id, _) in workspace_ids.clone() {
- if id == flycheck.id() {
- updated = true;
- flycheck.restart();
- continue;
- }
- }
- }
- }
-
// Re-fetch workspaces if a workspace related file has changed
if let Some(abs_path) = vfs_path.as_path() {
if reload::should_refresh_for_change(&abs_path, ChangeKind::Modify) {
@@ -826,13 +785,90 @@ impl GlobalState {
.request_op(format!("DidSaveTextDocument {}", abs_path.display()));
}
}
+
+ let file_id = this.vfs.read().0.file_id(&vfs_path);
+ if let Some(file_id) = file_id {
+ let world = this.snapshot();
+ let mut updated = false;
+ let task = move || -> std::result::Result<(), ide::Cancelled> {
+ // Trigger flychecks for all workspaces that depend on the saved file
+ // Crates containing or depending on the saved file
+ let crate_ids: Vec<_> = world
+ .analysis
+ .crates_for(file_id)?
+ .into_iter()
+ .flat_map(|id| world.analysis.transitive_rev_deps(id))
+ .flatten()
+ .sorted()
+ .unique()
+ .collect();
+
+ let crate_root_paths: Vec<_> = crate_ids
+ .iter()
+ .filter_map(|&crate_id| {
+ world
+ .analysis
+ .crate_root(crate_id)
+ .map(|file_id| {
+ world
+ .file_id_to_file_path(file_id)
+ .as_path()
+ .map(ToOwned::to_owned)
+ })
+ .transpose()
+ })
+ .collect::<ide::Cancellable<_>>()?;
+ let crate_root_paths: Vec<_> =
+ crate_root_paths.iter().map(Deref::deref).collect();
+
+ // Find all workspaces that have at least one target containing the saved file
+ let workspace_ids =
+ world.workspaces.iter().enumerate().filter(|(_, ws)| match ws {
+ project_model::ProjectWorkspace::Cargo { cargo, .. } => {
+ cargo.packages().any(|pkg| {
+ cargo[pkg].targets.iter().any(|&it| {
+ crate_root_paths.contains(&cargo[it].root.as_path())
+ })
+ })
+ }
+ project_model::ProjectWorkspace::Json { project, .. } => {
+ project.crates().any(|(c, _)| {
+ crate_ids.iter().any(|&crate_id| crate_id == c)
+ })
+ }
+ project_model::ProjectWorkspace::DetachedFiles { .. } => false,
+ });
+
+ // Find and trigger corresponding flychecks
+ for flycheck in world.flycheck.iter() {
+ for (id, _) in workspace_ids.clone() {
+ if id == flycheck.id() {
+ updated = true;
+ flycheck.restart();
+ continue;
+ }
+ }
+ }
+ // No specific flycheck was triggered, so let's trigger all of them.
+ if !updated {
+ for flycheck in world.flycheck.iter() {
+ flycheck.restart();
+ }
+ }
+ Ok(())
+ };
+ this.task_pool.handle.spawn_with_sender(move |_| {
+ if let Err(e) = std::panic::catch_unwind(task) {
+ tracing::error!("DidSaveTextDocument flycheck task panicked: {e:?}")
+ }
+ });
+ return Ok(());
+ }
}
// No specific flycheck was triggered, so let's trigger all of them.
- if !updated {
- for flycheck in &this.flycheck {
- flycheck.restart();
- }
+ for flycheck in this.flycheck.iter() {
+ flycheck.restart();
}
Ok(())
})?
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 e47f70fff..e1f651786 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -143,6 +143,7 @@ impl GlobalState {
project_model::ProjectWorkspace::load_inline(
it.clone(),
cargo_config.target.as_deref(),
+ &cargo_config.extra_env,
)
}
})
@@ -174,10 +175,8 @@ impl GlobalState {
sender.send(Task::FetchBuildData(BuildDataProgress::Report(msg))).unwrap()
}
};
- let mut res = Vec::new();
- for ws in workspaces.iter() {
- res.push(ws.run_build_scripts(&config, &progress));
- }
+ let res = ProjectWorkspace::run_all_build_scripts(&workspaces, &config, &progress);
+
sender.send(Task::FetchBuildData(BuildDataProgress::End((workspaces, res)))).unwrap();
});
}
@@ -305,41 +304,50 @@ impl GlobalState {
format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
if self.proc_macro_clients.is_empty() {
- if let Some((path, args)) = self.config.proc_macro_srv() {
+ if let Some((path, path_manually_set)) = self.config.proc_macro_srv() {
tracing::info!("Spawning proc-macro servers");
self.proc_macro_clients = self
.workspaces
.iter()
.map(|ws| {
- let mut args = args.clone();
- let mut path = path.clone();
-
- if let ProjectWorkspace::Cargo { sysroot, .. }
- | ProjectWorkspace::Json { sysroot, .. } = ws
- {
- tracing::debug!("Found a cargo workspace...");
- if let Some(sysroot) = sysroot.as_ref() {
- tracing::debug!("Found a cargo workspace with a sysroot...");
- let server_path =
- sysroot.root().join("libexec").join(&standalone_server_name);
- if std::fs::metadata(&server_path).is_ok() {
- tracing::debug!(
- "And the server exists at {}",
- server_path.display()
- );
- path = server_path;
- args = vec![];
- } else {
- tracing::debug!(
- "And the server does not exist at {}",
- server_path.display()
- );
+ let (path, args) = if path_manually_set {
+ tracing::debug!(
+ "Pro-macro server path explicitly set: {}",
+ path.display()
+ );
+ (path.clone(), vec![])
+ } else {
+ let mut sysroot_server = None;
+ if let ProjectWorkspace::Cargo { sysroot, .. }
+ | ProjectWorkspace::Json { sysroot, .. } = ws
+ {
+ if let Some(sysroot) = sysroot.as_ref() {
+ let server_path = sysroot
+ .root()
+ .join("libexec")
+ .join(&standalone_server_name);
+ if std::fs::metadata(&server_path).is_ok() {
+ tracing::debug!(
+ "Sysroot proc-macro server exists at {}",
+ server_path.display()
+ );
+ sysroot_server = Some(server_path);
+ } else {
+ tracing::debug!(
+ "Sysroot proc-macro server does not exist at {}",
+ server_path.display()
+ );
+ }
}
}
- }
+ sysroot_server.map_or_else(
+ || (path.clone(), vec!["proc-macro".to_owned()]),
+ |path| (path, vec![]),
+ )
+ };
tracing::info!(?args, "Using proc-macro server at {}", path.display(),);
- ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
+ ProcMacroServer::spawn(path.clone(), args).map_err(|err| {
let error = format!(
"Failed to run proc-macro server from path {}, error: {:?}",
path.display(),
@@ -398,7 +406,11 @@ impl GlobalState {
dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
)
};
- crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
+ crate_graph.extend(ws.to_crate_graph(
+ &mut load_proc_macro,
+ &mut load,
+ &self.config.cargo().extra_env,
+ ));
}
crate_graph
};
@@ -454,39 +466,54 @@ impl GlobalState {
let config = match self.config.flycheck() {
Some(it) => it,
None => {
- self.flycheck = Vec::new();
+ self.flycheck = Arc::new([]);
self.diagnostics.clear_check_all();
return;
}
};
let sender = self.flycheck_sender.clone();
- self.flycheck = self
- .workspaces
- .iter()
- .enumerate()
- .filter_map(|(id, w)| match w {
- ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())),
- ProjectWorkspace::Json { project, .. } => {
- // Enable flychecks for json projects if a custom flycheck command was supplied
- // in the workspace configuration.
- match config {
- FlycheckConfig::CustomCommand { .. } => Some((id, project.path())),
- _ => None,
- }
- }
- ProjectWorkspace::DetachedFiles { .. } => None,
- })
- .map(|(id, root)| {
- let sender = sender.clone();
- FlycheckHandle::spawn(
- id,
- Box::new(move |msg| sender.send(msg).unwrap()),
- config.clone(),
- root.to_path_buf(),
- )
- })
- .collect();
+ let invocation_strategy = match config {
+ FlycheckConfig::CargoCommand { .. } => flycheck::InvocationStrategy::PerWorkspace,
+ FlycheckConfig::CustomCommand { invocation_strategy, .. } => invocation_strategy,
+ };
+
+ self.flycheck = match invocation_strategy {
+ flycheck::InvocationStrategy::Once => vec![FlycheckHandle::spawn(
+ 0,
+ Box::new(move |msg| sender.send(msg).unwrap()),
+ config.clone(),
+ self.config.root_path().clone(),
+ )],
+ flycheck::InvocationStrategy::PerWorkspace => {
+ self.workspaces
+ .iter()
+ .enumerate()
+ .filter_map(|(id, w)| match w {
+ ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())),
+ ProjectWorkspace::Json { project, .. } => {
+ // Enable flychecks for json projects if a custom flycheck command was supplied
+ // in the workspace configuration.
+ match config {
+ FlycheckConfig::CustomCommand { .. } => Some((id, project.path())),
+ _ => None,
+ }
+ }
+ ProjectWorkspace::DetachedFiles { .. } => None,
+ })
+ .map(|(id, root)| {
+ let sender = sender.clone();
+ FlycheckHandle::spawn(
+ id,
+ Box::new(move |msg| sender.send(msg).unwrap()),
+ config.clone(),
+ root.to_path_buf(),
+ )
+ })
+ .collect()
+ }
+ }
+ .into();
}
}
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 e083b9d0e..5936454a7 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
@@ -83,10 +83,11 @@ pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolK
pub(crate) fn document_highlight_kind(
category: ReferenceCategory,
-) -> lsp_types::DocumentHighlightKind {
+) -> Option<lsp_types::DocumentHighlightKind> {
match category {
- ReferenceCategory::Read => lsp_types::DocumentHighlightKind::READ,
- ReferenceCategory::Write => lsp_types::DocumentHighlightKind::WRITE,
+ ReferenceCategory::Read => Some(lsp_types::DocumentHighlightKind::READ),
+ ReferenceCategory::Write => Some(lsp_types::DocumentHighlightKind::WRITE),
+ ReferenceCategory::Import => None,
}
}
@@ -1176,13 +1177,13 @@ pub(crate) fn code_lens(
})
}
}
- AnnotationKind::HasImpls { file_id, data } => {
+ AnnotationKind::HasImpls { pos: file_range, data } => {
if !client_commands_config.show_reference {
return Ok(());
}
- let line_index = snap.file_line_index(file_id)?;
+ let line_index = snap.file_line_index(file_range.file_id)?;
let annotation_range = range(&line_index, annotation.range);
- let url = url(snap, file_id);
+ let url = url(snap, file_range.file_id);
let id = lsp_types::TextDocumentIdentifier { uri: url.clone() };
@@ -1220,13 +1221,13 @@ pub(crate) fn code_lens(
data: Some(to_value(lsp_ext::CodeLensResolveData::Impls(goto_params)).unwrap()),
})
}
- AnnotationKind::HasReferences { file_id, data } => {
+ AnnotationKind::HasReferences { pos: file_range, data } => {
if !client_commands_config.show_reference {
return Ok(());
}
- let line_index = snap.file_line_index(file_id)?;
+ let line_index = snap.file_line_index(file_range.file_id)?;
let annotation_range = range(&line_index, annotation.range);
- let url = url(snap, file_id);
+ let url = url(snap, file_range.file_id);
let id = lsp_types::TextDocumentIdentifier { uri: url.clone() };
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 4cc46af1b..fa55f7d90 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
@@ -18,7 +18,6 @@ mod tidy;
use std::{collections::HashMap, path::PathBuf, time::Instant};
-use expect_test::expect;
use lsp_types::{
notification::DidOpenTextDocument,
request::{
@@ -60,7 +59,7 @@ use std::collections::Spam;
"#,
)
.with_config(serde_json::json!({
- "cargo": { "noSysroot": false }
+ "cargo": { "sysroot": "discover" }
}))
.server()
.wait_until_workspace_is_loaded();
@@ -615,7 +614,7 @@ fn main() {{}}
librs, libs
))
.with_config(serde_json::json!({
- "cargo": { "noSysroot": false }
+ "cargo": { "sysroot": "discover" }
}))
.server()
.wait_until_workspace_is_loaded();
@@ -743,7 +742,7 @@ fn main() {
"buildScripts": {
"enable": true
},
- "noSysroot": true,
+ "sysroot": null,
}
}))
.server()
@@ -821,7 +820,10 @@ fn main() {
}
#[test]
+// FIXME: Re-enable once we can run proc-macro tests on rust-lang/rust-analyzer again
+#[cfg(any())]
fn resolve_proc_macro() {
+ use expect_test::expect;
if skip_slow_tests() {
return;
}
@@ -898,7 +900,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
"buildScripts": {
"enable": true
},
- "noSysroot": true,
+ "sysroot": null,
},
"procMacro": {
"enable": true,
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 4fa88c3c6..7257445da 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
@@ -34,7 +34,7 @@ impl<'a> Project<'a> {
config: serde_json::json!({
"cargo": {
// Loading standard library is costly, let's ignore it by default
- "noSysroot": true,
+ "sysroot": null,
// Can't use test binary as rustc wrapper.
"buildScripts": {
"useRustcWrapper": false
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 58099a58d..24e68eca6 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
@@ -177,6 +177,7 @@ fn check_licenses() {
let sh = &Shell::new().unwrap();
let expected = "
+(MIT OR Apache-2.0) AND Unicode-DFS-2016
0BSD OR MIT OR Apache-2.0
Apache-2.0
Apache-2.0 OR BSL-1.0
diff --git a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
index a84110d94..e75867e2d 100644
--- a/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/sourcegen/Cargo.toml
@@ -11,6 +11,3 @@ doctest = false
[dependencies]
xshell = "0.2.2"
-
-[features]
-in-rust-tree = []
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index 092b99ae5..e0657ab0f 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -10,7 +10,7 @@ rust-version = "1.57"
doctest = false
[dependencies]
-libc = "0.2.126"
+libc = "0.2.135"
backtrace = { version = "0.3.65", optional = true }
always-assert = { version = "0.1.2", features = ["log"] }
# Think twice before adding anything here
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 0e2dec386..1ef903371 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -12,11 +12,11 @@ doctest = false
[dependencies]
cov-mark = "2.0.0-pre.1"
-itertools = "0.10.3"
-rowan = "0.15.8"
+itertools = "0.10.5"
+rowan = "0.15.10"
rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" }
rustc-hash = "1.1.0"
-once_cell = "1.12.0"
+once_cell = "1.15.0"
indexmap = "1.9.1"
smol_str = "0.1.23"
@@ -28,7 +28,7 @@ profile = { path = "../profile", version = "0.0.0" }
[dev-dependencies]
rayon = "1.5.3"
expect-test = "1.4.0"
-proc-macro2 = "1.0.39"
+proc-macro2 = "1.0.47"
quote = "1.0.20"
ungrammar = "1.16.1"
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
index eadebbe8a..660c057e9 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
@@ -235,6 +235,24 @@ impl ast::GenericParamList {
}
}
}
+
+ /// Constructs a matching [`ast::GenericArgList`]
+ pub fn to_generic_args(&self) -> ast::GenericArgList {
+ let args = self.generic_params().filter_map(|param| match param {
+ ast::GenericParam::LifetimeParam(it) => {
+ Some(ast::GenericArg::LifetimeArg(make::lifetime_arg(it.lifetime()?)))
+ }
+ ast::GenericParam::TypeParam(it) => {
+ Some(ast::GenericArg::TypeArg(make::type_arg(make::ext::ty_name(it.name()?))))
+ }
+ ast::GenericParam::ConstParam(it) => {
+ // Name-only const params get parsed as `TypeArg`s
+ Some(ast::GenericArg::TypeArg(make::type_arg(make::ext::ty_name(it.name()?))))
+ }
+ });
+
+ make::generic_arg_list(args)
+ }
}
impl ast::WhereClause {
@@ -248,6 +266,42 @@ impl ast::WhereClause {
}
}
+impl ast::TypeParam {
+ pub fn remove_default(&self) {
+ if let Some((eq, last)) = self
+ .syntax()
+ .children_with_tokens()
+ .find(|it| it.kind() == T![=])
+ .zip(self.syntax().last_child_or_token())
+ {
+ ted::remove_all(eq..=last);
+
+ // remove any trailing ws
+ if let Some(last) = self.syntax().last_token().filter(|it| it.kind() == WHITESPACE) {
+ last.detach();
+ }
+ }
+ }
+}
+
+impl ast::ConstParam {
+ pub fn remove_default(&self) {
+ if let Some((eq, last)) = self
+ .syntax()
+ .children_with_tokens()
+ .find(|it| it.kind() == T![=])
+ .zip(self.syntax().last_child_or_token())
+ {
+ ted::remove_all(eq..=last);
+
+ // remove any trailing ws
+ if let Some(last) = self.syntax().last_token().filter(|it| it.kind() == WHITESPACE) {
+ last.detach();
+ }
+ }
+ }
+}
+
pub trait Removable: AstNode {
fn remove(&self);
}
@@ -264,7 +318,7 @@ impl Removable for ast::TypeBoundList {
impl ast::PathSegment {
pub fn get_or_create_generic_arg_list(&self) -> ast::GenericArgList {
if self.generic_arg_list().is_none() {
- let arg_list = make::generic_arg_list().clone_for_update();
+ let arg_list = make::generic_arg_list(empty()).clone_for_update();
ted::append_child(self.syntax(), arg_list.syntax());
}
self.generic_arg_list().unwrap()
@@ -591,7 +645,7 @@ impl ast::RecordPatFieldList {
}
fn get_or_insert_comma_after(syntax: &SyntaxNode) -> SyntaxToken {
- let comma = match syntax
+ match syntax
.siblings_with_tokens(Direction::Next)
.filter_map(|it| it.into_token())
.find(|it| it.kind() == T![,])
@@ -602,8 +656,7 @@ fn get_or_insert_comma_after(syntax: &SyntaxNode) -> SyntaxToken {
ted::insert(Position::after(syntax), &comma);
comma
}
- };
- comma
+ }
}
impl ast::StmtList {
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 83f8bbac5..4057a75e7 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -88,6 +88,9 @@ pub mod ext {
block_expr(None, None)
}
+ pub fn ty_name(name: ast::Name) -> ast::Type {
+ ty_path(ident_path(&name.to_string()))
+ }
pub fn ty_bool() -> ast::Type {
ty_path(ident_path("bool"))
}
@@ -160,6 +163,7 @@ pub fn assoc_item_list() -> ast::AssocItemList {
ast_from_text("impl C for D {}")
}
+// FIXME: `ty_params` should be `ast::GenericArgList`
pub fn impl_(
ty: ast::Path,
params: Option<ast::GenericParamList>,
@@ -185,10 +189,6 @@ pub fn impl_trait(
ast_from_text(&format!("impl{ty_params} {trait_} for {ty}{ty_params} {{}}"))
}
-pub(crate) fn generic_arg_list() -> ast::GenericArgList {
- ast_from_text("const S: T<> = ();")
-}
-
pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
ast_from_text(&format!("type __ = {name_ref};"))
}
@@ -718,6 +718,21 @@ pub fn generic_param_list(
ast_from_text(&format!("fn f<{args}>() {{ }}"))
}
+pub fn type_arg(ty: ast::Type) -> ast::TypeArg {
+ ast_from_text(&format!("const S: T<{ty}> = ();"))
+}
+
+pub fn lifetime_arg(lifetime: ast::Lifetime) -> ast::LifetimeArg {
+ ast_from_text(&format!("const S: T<{lifetime}> = ();"))
+}
+
+pub(crate) fn generic_arg_list(
+ args: impl IntoIterator<Item = ast::GenericArg>,
+) -> ast::GenericArgList {
+ let args = args.into_iter().join(", ");
+ ast_from_text(&format!("const S: T<{args}> = ();"))
+}
+
pub fn visibility_pub_crate() -> ast::Visibility {
ast_from_text("pub(crate) struct S")
}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index bb92c51e9..fe82aa907 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -873,3 +873,33 @@ impl ast::MatchGuard {
support::child(&self.syntax)
}
}
+
+impl From<ast::Item> for ast::AnyHasAttrs {
+ fn from(node: ast::Item) -> Self {
+ Self::new(node)
+ }
+}
+
+impl From<ast::AssocItem> for ast::AnyHasAttrs {
+ fn from(node: ast::AssocItem) -> Self {
+ Self::new(node)
+ }
+}
+
+impl From<ast::Variant> for ast::AnyHasAttrs {
+ fn from(node: ast::Variant) -> Self {
+ Self::new(node)
+ }
+}
+
+impl From<ast::RecordField> for ast::AnyHasAttrs {
+ fn from(node: ast::RecordField) -> Self {
+ Self::new(node)
+ }
+}
+
+impl From<ast::TupleField> for ast::AnyHasAttrs {
+ fn from(node: ast::TupleField) -> Self {
+ Self::new(node)
+ }
+}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
index 4f5e273a5..84c66b27e 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
@@ -92,7 +92,7 @@ impl<T> Parse<T> {
SyntaxNode::new_root(self.green.clone())
}
pub fn errors(&self) -> &[SyntaxError] {
- &*self.errors
+ &self.errors
}
}
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index 8c806e792..c824f5af7 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -61,6 +61,8 @@
//! "
//! ```
+use std::iter;
+
use rustc_hash::FxHashMap;
use stdx::trim_indent;
@@ -259,7 +261,7 @@ impl MiniCore {
if res.has_flag(entry) {
panic!("duplicate minicore flag: {:?}", entry);
}
- res.activated_flags.push(entry.to_string());
+ res.activated_flags.push(entry.to_owned());
}
res
@@ -273,35 +275,34 @@ impl MiniCore {
let raw_mini_core = include_str!("./minicore.rs");
let mut lines = raw_mini_core.split_inclusive('\n');
- let mut parsing_flags = false;
let mut implications = Vec::new();
// Parse `//!` preamble and extract flags and dependencies.
- for line in lines.by_ref() {
- let line = match line.strip_prefix("//!") {
- Some(it) => it,
- None => {
- assert!(line.trim().is_empty());
- break;
- }
- };
-
- if parsing_flags {
- let (flag, deps) = line.split_once(':').unwrap();
- let flag = flag.trim();
- self.valid_flags.push(flag.to_string());
- for dep in deps.split(", ") {
- let dep = dep.trim();
- if !dep.is_empty() {
- self.assert_valid_flag(dep);
- implications.push((flag, dep));
- }
- }
+ let trim_doc: fn(&str) -> Option<&str> = |line| match line.strip_prefix("//!") {
+ Some(it) => Some(it),
+ None => {
+ assert!(line.trim().is_empty(), "expected empty line after minicore header");
+ None
}
+ };
+ for line in lines
+ .by_ref()
+ .map_while(trim_doc)
+ .skip_while(|line| !line.contains("Available flags:"))
+ .skip(1)
+ {
+ let (flag, deps) = line.split_once(':').unwrap();
+ let flag = flag.trim();
+
+ self.valid_flags.push(flag.to_string());
+ implications.extend(
+ iter::repeat(flag)
+ .zip(deps.split(", ").map(str::trim).filter(|dep| !dep.is_empty())),
+ );
+ }
- if line.contains("Available flags:") {
- parsing_flags = true;
- }
+ for (_, dep) in &implications {
+ self.assert_valid_flag(dep);
}
for flag in &self.activated_flags {
@@ -332,7 +333,7 @@ impl MiniCore {
}
if let Some(region) = trimmed.strip_prefix("// endregion:") {
let prev = active_regions.pop().unwrap();
- assert_eq!(prev, region);
+ assert_eq!(prev, region, "unbalanced region pairs");
continue;
}
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 6df29db47..69d2e62b2 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -8,35 +8,36 @@
//! We then strip all the code marked with other flags.
//!
//! Available flags:
-//! sized:
-//! unsize: sized
+//! add:
+//! as_ref: sized
+//! bool_impl: option, fn
+//! clone: sized
//! coerce_unsized: unsize
-//! slice:
-//! range:
-//! deref: sized
+//! copy: clone
+//! default: sized
//! deref_mut: deref
-//! index: sized
+//! deref: sized
+//! derive:
+//! drop:
+//! eq: sized
+//! fmt: result
//! fn:
-//! try:
-//! pin:
+//! from: sized
//! future: pin
-//! option:
-//! result:
+//! generator: pin
+//! hash:
+//! index: sized
//! iterator: option
//! iterators: iterator, fn
-//! default: sized
-//! hash:
-//! clone: sized
-//! copy: clone
-//! from: sized
-//! eq: sized
+//! option:
//! ord: eq, option
-//! derive:
-//! fmt: result
-//! bool_impl: option, fn
-//! add:
-//! as_ref: sized
-//! drop:
+//! pin:
+//! range:
+//! result:
+//! sized:
+//! slice:
+//! try:
+//! unsize: sized
pub mod marker {
// region:sized
@@ -182,6 +183,19 @@ pub mod ops {
type Target: ?Sized;
fn deref(&self) -> &Self::Target;
}
+
+ impl<T: ?Sized> Deref for &T {
+ type Target = T;
+ fn deref(&self) -> &T {
+ loop {}
+ }
+ }
+ impl<T: ?Sized> Deref for &mut T {
+ type Target = T;
+ fn deref(&self) -> &T {
+ loop {}
+ }
+ }
// region:deref_mut
#[lang = "deref_mut"]
pub trait DerefMut: Deref {
@@ -347,6 +361,27 @@ pub mod ops {
fn add(self, rhs: Rhs) -> Self::Output;
}
// endregion:add
+
+ // region:generator
+ mod generator {
+ use crate::pin::Pin;
+
+ #[lang = "generator"]
+ pub trait Generator<R = ()> {
+ type Yield;
+ #[lang = "generator_return"]
+ type Return;
+ fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return>;
+ }
+
+ #[lang = "generator_state"]
+ pub enum GeneratorState<Y, R> {
+ Yielded(Y),
+ Complete(R),
+ }
+ }
+ pub use self::generator::{Generator, GeneratorState};
+ // endregion:generator
}
// region:eq
@@ -455,6 +490,19 @@ pub mod pin {
pub struct Pin<P> {
pointer: P,
}
+ impl<P> Pin<P> {
+ pub fn new(pointer: P) -> Pin<P> {
+ loop {}
+ }
+ }
+ // region:deref
+ impl<P: crate::ops::Deref> crate::ops::Deref for Pin<P> {
+ type Target = P::Target;
+ fn deref(&self) -> &P::Target {
+ loop {}
+ }
+ }
+ // endregion:deref
}
// endregion:pin
@@ -536,7 +584,7 @@ pub mod iter {
}
}
}
- pub use self::adapters::{Take, FilterMap};
+ pub use self::adapters::{FilterMap, Take};
mod sources {
mod repeat {
diff --git a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
index cf14bbd3c..7a90d64a9 100644
--- a/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/text-edit/Cargo.toml
@@ -10,5 +10,5 @@ rust-version = "1.57"
doctest = false
[dependencies]
-itertools = "0.10.3"
+itertools = "0.10.5"
text-size = "1.1.0"
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index 7d3b9e09e..3e0f31f19 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -10,4 +10,4 @@ rust-version = "1.57"
doctest = false
[dependencies]
-home = "0.5.3"
+home = "0.5.4"
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
index fcc693a7d..df5dc24e2 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
@@ -14,7 +14,7 @@ tracing = "0.1.35"
jod-thread = "0.1.2"
walkdir = "2.3.2"
crossbeam-channel = "0.5.5"
-notify = "=5.0.0-pre.16"
+notify = "5.0"
vfs = { path = "../vfs", version = "0.0.0" }
paths = { path = "../paths", version = "0.0.0" }
diff --git a/src/tools/rust-analyzer/docs/dev/README.md b/src/tools/rust-analyzer/docs/dev/README.md
index c7f152acc..4ac75b4bb 100644
--- a/src/tools/rust-analyzer/docs/dev/README.md
+++ b/src/tools/rust-analyzer/docs/dev/README.md
@@ -98,7 +98,7 @@ After I am done with the fix, I use `cargo xtask install --client` to try the ne
If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
I usually just `cargo xtask install --server` and poke changes from my live environment.
Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
-To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.noSysroot": true` in `.code/settings.json`.
+To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.sysroot": null` in `.code/settings.json`.
This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
diff --git a/src/tools/rust-analyzer/docs/dev/guide.md b/src/tools/rust-analyzer/docs/dev/guide.md
index 808eb5d10..52a13da31 100644
--- a/src/tools/rust-analyzer/docs/dev/guide.md
+++ b/src/tools/rust-analyzer/docs/dev/guide.md
@@ -40,8 +40,8 @@ terms of files and offsets, and **not** in terms of Rust concepts like structs,
traits, etc. The "typed" API with Rust specific types is slightly lower in the
stack, we'll talk about it later.
-[`AnalysisHost`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L265-L284
-[`Analysis`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ide_api/src/lib.rs#L291-L478
+[`AnalysisHost`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L265-L284
+[`Analysis`]: https://github.com/rust-lang/rust-analyzer/blob/guide-2019-01/crates/ra_ide_api/src/lib.rs#L291-L478
The reason for this separation of `Analysis` and `AnalysisHost` is that we want to apply
changes "uniquely", but we might also want to fork an `Analysis` and send it to
@@ -88,9 +88,8 @@ is lower than Cargo's model of packages: each Cargo package consists of several
targets, each of which is a separate crate (or several crates, if you try
different feature combinations).
-Procedural macros should become inputs as well, but currently they are not
-supported. Procedural macro will be a black box `Box<dyn Fn(TokenStream) -> TokenStream>`
-function, and will be inserted into the crate graph just like dependencies.
+Procedural macros are inputs as well, roughly modeled as a crate with a bunch of
+additional black box `dyn Fn(TokenStream) -> TokenStream` functions.
Soon we'll talk how we build an LSP server on top of `Analysis`, but first,
let's deal with that paths issue.
diff --git a/src/tools/rust-analyzer/docs/dev/syntax.md b/src/tools/rust-analyzer/docs/dev/syntax.md
index 30e137013..97e376787 100644
--- a/src/tools/rust-analyzer/docs/dev/syntax.md
+++ b/src/tools/rust-analyzer/docs/dev/syntax.md
@@ -8,10 +8,10 @@ This guide describes the current state of syntax trees and parsing in rust-analy
The things described are implemented in three places
-* [rowan](https://github.com/rust-analyzer/rowan/tree/v0.9.0) -- a generic library for rowan syntax trees.
-* [ra_syntax](https://github.com/rust-lang/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/ra_syntax) crate inside rust-analyzer which wraps `rowan` into rust-analyzer specific API.
+* [rowan](https://github.com/rust-analyzer/rowan/tree/v0.15.10) -- a generic library for rowan syntax trees.
+* [syntax](https://github.com/rust-lang/rust-analyzer/tree/36a70b7435c48837018c71576d7bb4e8f763f501/crates/syntax) crate inside rust-analyzer which wraps `rowan` into rust-analyzer specific API.
Nothing in rust-analyzer except this crate knows about `rowan`.
-* [parser](https://github.com/rust-lang/rust-analyzer/tree/cf5bdf464cad7ceb9a67e07985a3f4d3799ec0b6/crates/parser) crate parses input tokens into an `ra_syntax` tree
+* [parser](https://github.com/rust-lang/rust-analyzer/tree/36a70b7435c48837018c71576d7bb4e8f763f501/crates/parser) crate parses input tokens into a `syntax` tree
## Design Goals
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 72b925726..502833de7 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -24,6 +24,25 @@ Automatically refresh project info via `cargo metadata` on
--
Run build scripts (`build.rs`) for more precise code analysis.
--
+[[rust-analyzer.cargo.buildScripts.invocationLocation]]rust-analyzer.cargo.buildScripts.invocationLocation (default: `"workspace"`)::
++
+--
+Specifies the working directory for running build scripts.
+- "workspace": run build scripts for a workspace in the workspace's root directory.
+ This is incompatible with `#rust-analyzer.cargo.buildScripts.invocationStrategy#` set to `once`.
+- "root": run build scripts in the project's root directory.
+This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+is set.
+--
+[[rust-analyzer.cargo.buildScripts.invocationStrategy]]rust-analyzer.cargo.buildScripts.invocationStrategy (default: `"per_workspace"`)::
++
+--
+Specifies the invocation strategy to use when running the build scripts command.
+If `per_workspace` is set, the command will be executed for each workspace.
+If `once` is set, the command will be executed once.
+This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+is set.
+--
[[rust-analyzer.cargo.buildScripts.overrideCommand]]rust-analyzer.cargo.buildScripts.overrideCommand (default: `null`)::
+
--
@@ -46,6 +65,12 @@ cargo check --quiet --workspace --message-format=json --all-targets
Use `RUSTC_WRAPPER=rust-analyzer` when running build scripts to
avoid checking unnecessary things.
--
+[[rust-analyzer.cargo.extraEnv]]rust-analyzer.cargo.extraEnv (default: `{}`)::
++
+--
+Extra environment variables that will be set when running cargo, rustc
+or other commands within the workspace. Useful for setting RUSTFLAGS.
+--
[[rust-analyzer.cargo.features]]rust-analyzer.cargo.features (default: `[]`)::
+
--
@@ -58,10 +83,15 @@ Set this to `"all"` to pass `--all-features` to cargo.
--
Whether to pass `--no-default-features` to cargo.
--
-[[rust-analyzer.cargo.noSysroot]]rust-analyzer.cargo.noSysroot (default: `false`)::
+[[rust-analyzer.cargo.sysroot]]rust-analyzer.cargo.sysroot (default: `"discover"`)::
+
--
-Internal config for debugging, disables loading of sysroot crates.
+Relative path to the sysroot, or "discover" to try to automatically find it via
+"rustc --print sysroot".
+
+Unsetting this disables sysroot loading.
+
+This option does not take effect until rust-analyzer is restarted.
--
[[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
+
@@ -93,6 +123,12 @@ Run specified `cargo check` command for diagnostics on save.
--
Extra arguments for `cargo check`.
--
+[[rust-analyzer.checkOnSave.extraEnv]]rust-analyzer.checkOnSave.extraEnv (default: `{}`)::
++
+--
+Extra environment variables that will be set when running `cargo check`.
+Extends `#rust-analyzer.cargo.extraEnv#`.
+--
[[rust-analyzer.checkOnSave.features]]rust-analyzer.checkOnSave.features (default: `null`)::
+
--
@@ -101,6 +137,25 @@ List of features to activate. Defaults to
Set to `"all"` to pass `--all-features` to Cargo.
--
+[[rust-analyzer.checkOnSave.invocationLocation]]rust-analyzer.checkOnSave.invocationLocation (default: `"workspace"`)::
++
+--
+Specifies the working directory for running checks.
+- "workspace": run checks for workspaces in the corresponding workspaces' root directories.
+ This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.
+- "root": run checks in the project's root directory.
+This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+is set.
+--
+[[rust-analyzer.checkOnSave.invocationStrategy]]rust-analyzer.checkOnSave.invocationStrategy (default: `"per_workspace"`)::
++
+--
+Specifies the invocation strategy to use when running the checkOnSave command.
+If `per_workspace` is set, the command will be executed for each workspace.
+If `once` is set, the command will be executed once.
+This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+is set.
+--
[[rust-analyzer.checkOnSave.noDefaultFeatures]]rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`)::
+
--
@@ -353,6 +408,11 @@ Group inserted imports by the https://rust-analyzer.github.io/manual.html#auto-i
--
Whether to allow import insertion to merge new imports into single path glob imports like `use std::fmt::*;`.
--
+[[rust-analyzer.imports.prefer.no.std]]rust-analyzer.imports.prefer.no.std (default: `false`)::
++
+--
+Prefer to unconditionally use imports of the core and alloc crate, over the std crate.
+--
[[rust-analyzer.imports.prefix]]rust-analyzer.imports.prefix (default: `"plain"`)::
+
--
@@ -474,6 +534,11 @@ client doesn't set the corresponding capability.
Whether to show `Implementations` lens. Only applies when
`#rust-analyzer.lens.enable#` is set.
--
+[[rust-analyzer.lens.location]]rust-analyzer.lens.location (default: `"above_name"`)::
++
+--
+Where to render annotations.
+--
[[rust-analyzer.lens.references.adt.enable]]rust-analyzer.lens.references.adt.enable (default: `false`)::
+
--
@@ -546,6 +611,11 @@ This config takes a map of crate names with the exported proc-macro names to ign
Internal config, path to proc-macro server executable (typically,
this is rust-analyzer itself, but we override this in tests).
--
+[[rust-analyzer.references.excludeImports]]rust-analyzer.references.excludeImports (default: `false`)::
++
+--
+Exclude imports from find-all-references.
+--
[[rust-analyzer.runnables.command]]rust-analyzer.runnables.command (default: `null`)::
+
--
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index 9bd3b6a69..c30838e5f 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -174,14 +174,25 @@ On Unix, running the editor from a shell or changing the `.desktop` file to set
==== `rustup`
-`rust-analyzer` is available in `rustup`, but only in the nightly toolchain:
+`rust-analyzer` is available in `rustup`:
[source,bash]
----
-$ rustup +nightly component add rust-analyzer-preview
+$ rustup component add rust-analyzer
----
-However, in contrast to `component add clippy` or `component add rustfmt`, this does not actually place a `rust-analyzer` binary in `~/.cargo/bin`, see https://github.com/rust-lang/rustup/issues/2411[this issue].
+However, in contrast to `component add clippy` or `component add rustfmt`, this does not actually place a `rust-analyzer` binary in `~/.cargo/bin`, see https://github.com/rust-lang/rustup/issues/2411[this issue]. You can find the path to the binary using:
+[source,bash]
+----
+$ rustup which --toolchain stable rust-analyzer
+----
+You can link to there from `~/.cargo/bin` or configure your editor to use the full path.
+
+Alternatively you might be able to configure your editor to start `rust-analyzer` using the command:
+[source,bash]
+----
+$ rustup run stable rust-analyzer
+----
==== Arch Linux
diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
index 204d120d0..5922bbfdb 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "lsp-server"
-version = "0.6.0"
+version = "0.7.0"
description = "Generic LSP server scaffold."
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server"
@@ -8,9 +8,9 @@ edition = "2021"
[dependencies]
log = "0.4.17"
-serde_json = "1.0.81"
-serde = { version = "1.0.137", features = ["derive"] }
-crossbeam-channel = "0.5.5"
+serde_json = "1.0.86"
+serde = { version = "1.0.144", features = ["derive"] }
+crossbeam-channel = "0.5.6"
[dev-dependencies]
-lsp-types = "0.93.0"
+lsp-types = "0.93.1"
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
index 97e5bd35c..b241561f9 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/msg.rs
@@ -98,7 +98,7 @@ pub struct ResponseError {
}
#[derive(Clone, Copy, Debug)]
-#[allow(unused)]
+#[non_exhaustive]
pub enum ErrorCode {
// Defined by JSON RPC:
ParseError = -32700,
@@ -135,6 +135,14 @@ pub enum ErrorCode {
///
/// @since 3.17.0
ServerCancelled = -32802,
+
+ /// A request failed but it was syntactically correct, e.g the
+ /// method name was known and the parameters were valid. The error
+ /// message should contain human readable information about why
+ /// the request failed.
+ ///
+ /// @since 3.17.0
+ RequestFailed = -32803,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
index 1f3d44715..e5f19be20 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
@@ -35,6 +35,7 @@ impl<I> Incoming<I> {
pub fn register(&mut self, id: RequestId, data: I) {
self.pending.insert(id, data);
}
+
pub fn cancel(&mut self, id: RequestId) -> Option<Response> {
let _data = self.complete(id.clone())?;
let error = ResponseError {
@@ -44,9 +45,14 @@ impl<I> Incoming<I> {
};
Some(Response { id, result: None, error: Some(error) })
}
+
pub fn complete(&mut self, id: RequestId) -> Option<I> {
self.pending.remove(&id)
}
+
+ pub fn is_completed(&self, id: &RequestId) -> bool {
+ !self.pending.contains_key(id)
+ }
}
impl<O> Outgoing<O> {
@@ -56,6 +62,7 @@ impl<O> Outgoing<O> {
self.next_id += 1;
Request::new(id, method, params)
}
+
pub fn complete(&mut self, id: RequestId) -> Option<O> {
self.pending.remove(&id)
}
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 95d44e9b9..0be0bf920 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -7,9 +7,9 @@ edition = "2021"
rust-version = "1.57"
[dependencies]
-anyhow = "1.0.57"
+anyhow = "1.0.62"
flate2 = "1.0.24"
write-json = "0.1.2"
xshell = "0.2.2"
-xflags = "0.2.4"
+xflags = "0.3.0"
# Avoid adding more dependencies to this crate
diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs
index 993c64cce..0fce48898 100644
--- a/src/tools/rust-analyzer/xtask/src/flags.rs
+++ b/src/tools/rust-analyzer/xtask/src/flags.rs
@@ -7,10 +7,6 @@ xflags::xflags! {
/// Run custom build command.
cmd xtask {
- default cmd help {
- /// Print help information.
- optional -h, --help
- }
/// Install rust-analyzer server or editor plugin.
cmd install {
@@ -42,9 +38,9 @@ xflags::xflags! {
optional --dry-run
}
/// Builds a benchmark version of rust-analyzer and puts it into `./target`.
- cmd bb
+ cmd bb {
required suffix: String
- {}
+ }
}
}
@@ -58,7 +54,6 @@ pub struct Xtask {
#[derive(Debug)]
pub enum XtaskCmd {
- Help(Help),
Install(Install),
FuzzTests(FuzzTests),
Release(Release),
@@ -69,11 +64,6 @@ pub enum XtaskCmd {
}
#[derive(Debug)]
-pub struct Help {
- pub help: bool,
-}
-
-#[derive(Debug)]
pub struct Install {
pub client: bool,
pub code_bin: Option<String>,
@@ -111,7 +101,10 @@ pub struct Bb {
}
impl Xtask {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs
index 335ac324a..a37f469ad 100644
--- a/src/tools/rust-analyzer/xtask/src/main.rs
+++ b/src/tools/rust-analyzer/xtask/src/main.rs
@@ -25,15 +25,12 @@ use std::{
use xshell::{cmd, Shell};
fn main() -> anyhow::Result<()> {
+ let flags = flags::Xtask::from_env_or_exit();
+
let sh = &Shell::new()?;
sh.change_dir(project_root());
- let flags = flags::Xtask::from_env()?;
match flags.subcommand {
- flags::XtaskCmd::Help(_) => {
- println!("{}", flags::Xtask::HELP);
- Ok(())
- }
flags::XtaskCmd::Install(cmd) => cmd.run(sh),
flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
flags::XtaskCmd::Release(cmd) => cmd.run(sh),
diff --git a/src/tools/rustdoc/main.rs b/src/tools/rustdoc/main.rs
index 5b499a1fa..b81f46d12 100644
--- a/src/tools/rustdoc/main.rs
+++ b/src/tools/rustdoc/main.rs
@@ -1,3 +1,6 @@
+#![feature(unix_sigpipe)]
+
+#[unix_sigpipe = "sig_dfl"]
fn main() {
rustdoc::main()
}
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index e26e24ec5..fcc02eca4 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -145,7 +145,7 @@ impl ChainItemKind {
fn from_ast(context: &RewriteContext<'_>, expr: &ast::Expr) -> (ChainItemKind, Span) {
let (kind, span) = match expr.kind {
- ast::ExprKind::MethodCall(ref segment, ref expressions, _) => {
+ ast::ExprKind::MethodCall(ref segment, ref receiver, ref expressions, _) => {
let types = if let Some(ref generic_args) = segment.args {
if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args {
data.args
@@ -163,7 +163,7 @@ impl ChainItemKind {
} else {
vec![]
};
- let span = mk_sp(expressions[0].span.hi(), expr.span.hi());
+ let span = mk_sp(receiver.span.hi(), expr.span.hi());
let kind = ChainItemKind::MethodCall(segment.clone(), types, expressions.clone());
(kind, span)
}
@@ -253,7 +253,7 @@ impl ChainItem {
format!("::<{}>", type_list.join(", "))
};
let callee_str = format!(".{}{}", rewrite_ident(context, method_name), type_str);
- rewrite_call(context, &callee_str, &args[1..], span, shape)
+ rewrite_call(context, &callee_str, &args, span, shape)
}
}
@@ -400,8 +400,8 @@ impl Chain {
// is a try! macro, we'll convert it to shorthand when the option is set.
fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option<ast::Expr> {
match expr.kind {
- ast::ExprKind::MethodCall(_, ref expressions, _) => {
- Some(Self::convert_try(&expressions[0], context))
+ ast::ExprKind::MethodCall(_, ref receiver, _, _) => {
+ Some(Self::convert_try(&receiver, context))
}
ast::ExprKind::Field(ref subexpr, _)
| ast::ExprKind::Try(ref subexpr)
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index e37ed798c..c5e61658a 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -4,7 +4,7 @@ use crate::config::options::{IgnoreList, WidthHeuristics};
/// Trait for types that can be used in `Config`.
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>".
+ /// pipe-separated list of variants; for other types it returns `<type>`.
fn doc_hint() -> String;
}
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index 8f35068e3..a2a73f0a5 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -594,7 +594,7 @@ impl<'a> FmtVisitor<'a> {
let both_type = |l: &TyOpt, r: &TyOpt| is_type(l) && is_type(r);
let both_opaque = |l: &TyOpt, r: &TyOpt| is_opaque(l) && is_opaque(r);
let need_empty_line = |a: &ast::AssocItemKind, b: &ast::AssocItemKind| match (a, b) {
- (TyAlias(lty), TyAlias(rty))
+ (Type(lty), Type(rty))
if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
{
false
@@ -612,7 +612,7 @@ impl<'a> FmtVisitor<'a> {
}
buffer.sort_by(|(_, a), (_, b)| match (&a.kind, &b.kind) {
- (TyAlias(lty), TyAlias(rty))
+ (Type(lty), Type(rty))
if both_type(&lty.ty, &rty.ty) || both_opaque(&lty.ty, &rty.ty) =>
{
a.ident.as_str().cmp(b.ident.as_str())
@@ -621,10 +621,10 @@ impl<'a> FmtVisitor<'a> {
a.ident.as_str().cmp(b.ident.as_str())
}
(Fn(..), Fn(..)) => a.span.lo().cmp(&b.span.lo()),
- (TyAlias(ty), _) if is_type(&ty.ty) => Ordering::Less,
- (_, TyAlias(ty)) if is_type(&ty.ty) => Ordering::Greater,
- (TyAlias(..), _) => Ordering::Less,
- (_, TyAlias(..)) => Ordering::Greater,
+ (Type(ty), _) if is_type(&ty.ty) => Ordering::Less,
+ (_, Type(ty)) if is_type(&ty.ty) => Ordering::Greater,
+ (Type(..), _) => Ordering::Less,
+ (_, Type(..)) => Ordering::Greater,
(Const(..), _) => Ordering::Less,
(_, Const(..)) => Ordering::Greater,
(MacCall(..), _) => Ordering::Less,
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index 7bb745eeb..9c3cc7820 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -660,7 +660,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
self.push_rewrite(ai.span, rewrite);
}
}
- (ast::AssocItemKind::TyAlias(ref ty_alias), _) => {
+ (ast::AssocItemKind::Type(ref ty_alias), _) => {
self.visit_ty_alias_kind(ty_alias, visitor_kind, ai.span);
}
(ast::AssocItemKind::MacCall(ref mac), _) => {
diff --git a/src/tools/tidy/src/alphabetical.rs b/src/tools/tidy/src/alphabetical.rs
new file mode 100644
index 000000000..f913f6cde
--- /dev/null
+++ b/src/tools/tidy/src/alphabetical.rs
@@ -0,0 +1,111 @@
+//! Checks that a list of items is in alphabetical order
+//!
+//! To use, use the following annotation in the code:
+//! ```rust
+//! // tidy-alphabetical-start
+//! fn aaa() {}
+//! fn eee() {}
+//! fn z() {}
+//! // tidy-alphabetical-end
+//! ```
+//!
+//! The following lines are ignored:
+//! - Lines that are indented with more or less spaces than the first line
+//! - Lines starting with `//`, `#[`, `)`, `]`, `}` if the comment has the same indentation as
+//! the first line
+//!
+//! If a line ends with an opening bracket, the line is ignored and the next line will have
+//! its extra indentation ignored.
+
+use std::{fmt::Display, path::Path};
+
+use crate::walk::{filter_dirs, walk};
+
+fn indentation(line: &str) -> usize {
+ line.find(|c| c != ' ').unwrap_or(0)
+}
+
+fn is_close_bracket(c: char) -> bool {
+ matches!(c, ')' | ']' | '}')
+}
+
+// Don't let tidy check this here :D
+const START_COMMENT: &str = concat!("// tidy-alphabetical", "-start");
+const END_COMMENT: &str = "// tidy-alphabetical-end";
+
+fn check_section<'a>(
+ file: impl Display,
+ lines: impl Iterator<Item = (usize, &'a str)>,
+ bad: &mut bool,
+) {
+ let content_lines = lines.take_while(|(_, line)| !line.contains(END_COMMENT));
+
+ let mut prev_line = String::new();
+ let mut first_indent = None;
+ let mut in_split_line = None;
+
+ for (line_idx, line) in content_lines {
+ if line.contains(START_COMMENT) {
+ tidy_error!(
+ bad,
+ "{file}:{} found `{START_COMMENT}` expecting `{END_COMMENT}`",
+ line_idx
+ )
+ }
+
+ let indent = first_indent.unwrap_or_else(|| {
+ let indent = indentation(line);
+ first_indent = Some(indent);
+ indent
+ });
+
+ let line = if let Some(prev_split_line) = in_split_line {
+ in_split_line = None;
+ format!("{prev_split_line}{}", line.trim_start())
+ } else {
+ line.to_string()
+ };
+
+ if indentation(&line) != indent {
+ continue;
+ }
+
+ let trimmed_line = line.trim_start_matches(' ');
+
+ if trimmed_line.starts_with("//")
+ || trimmed_line.starts_with("#[")
+ || trimmed_line.starts_with(is_close_bracket)
+ {
+ continue;
+ }
+
+ if line.trim_end().ends_with('(') {
+ in_split_line = Some(line);
+ continue;
+ }
+
+ let prev_line_trimmed_lowercase = prev_line.trim_start_matches(' ').to_lowercase();
+
+ if trimmed_line.to_lowercase() < prev_line_trimmed_lowercase {
+ tidy_error!(bad, "{file}:{}: line not in alphabetical order", line_idx + 1,);
+ }
+
+ prev_line = line;
+ }
+}
+
+pub fn check(path: &Path, bad: &mut bool) {
+ walk(path, &mut filter_dirs, &mut |entry, contents| {
+ let file = &entry.path().display();
+
+ let mut lines = contents.lines().enumerate().peekable();
+ while let Some((_, line)) = lines.next() {
+ if line.contains(START_COMMENT) {
+ check_section(file, &mut lines, bad);
+ if lines.peek().is_none() {
+ tidy_error!(bad, "{file}: reached end of file expecting `{END_COMMENT}`")
+ }
+ }
+ }
+ });
+}
diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs
index 30903f56d..b898f20a5 100644
--- a/src/tools/tidy/src/bins.rs
+++ b/src/tools/tidy/src/bins.rs
@@ -21,6 +21,7 @@ mod os_impl {
#[cfg(unix)]
mod os_impl {
+ use crate::walk::{filter_dirs, walk_no_read};
use std::fs;
use std::os::unix::prelude::*;
use std::path::Path;
@@ -100,10 +101,10 @@ mod os_impl {
const ALLOWED: &[&str] = &["configure", "x"];
- crate::walk_no_read(
+ walk_no_read(
path,
&mut |path| {
- crate::filter_dirs(path)
+ filter_dirs(path)
|| path.ends_with("src/etc")
// This is a list of directories that we almost certainly
// don't need to walk. A future PR will likely want to
diff --git a/src/tools/tidy/src/debug_artifacts.rs b/src/tools/tidy/src/debug_artifacts.rs
index ab87230f8..9880a32ad 100644
--- a/src/tools/tidy/src/debug_artifacts.rs
+++ b/src/tools/tidy/src/debug_artifacts.rs
@@ -1,5 +1,6 @@
//! Tidy check to prevent creation of unnecessary debug artifacts while running tests.
+use crate::walk::{filter_dirs, walk};
use std::path::{Path, PathBuf};
const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
@@ -7,7 +8,7 @@ const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in t
pub fn check(path: &Path, bad: &mut bool) {
let test_dir: PathBuf = path.join("test");
- super::walk(&test_dir, &mut super::filter_dirs, &mut |entry, contents| {
+ walk(&test_dir, &mut filter_dirs, &mut |entry, contents| {
let filename = entry.path();
let is_rust = filename.extension().map_or(false, |ext| ext == "rs");
if !is_rust {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index cbd8cfa01..8a0239ece 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -18,9 +18,11 @@ const LICENSES: &[&str] = &[
"ISC",
"Unlicense/MIT",
"Unlicense OR MIT",
- "0BSD OR MIT OR Apache-2.0", // adler license
- "Zlib OR Apache-2.0 OR MIT", // tinyvec
- "MIT OR Zlib OR Apache-2.0", // miniz_oxide
+ "0BSD OR MIT OR Apache-2.0", // adler license
+ "Zlib OR Apache-2.0 OR MIT", // tinyvec
+ "MIT OR Apache-2.0 OR Zlib", // tinyvec_macros
+ "MIT OR Zlib OR Apache-2.0", // miniz_oxide
+ "(MIT OR Apache-2.0) AND Unicode-DFS-2016", // unicode_ident
];
/// These are exceptions to Rust's permissive licensing policy, and
@@ -72,14 +74,11 @@ const EXCEPTIONS_BOOTSTRAP: &[(&str, &str)] = &[
/// these and all their dependencies *must not* be in the exception list.
const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
-/// Crates whose dependencies must be explicitly permitted.
-const RESTRICTED_DEPENDENCY_CRATES: &[&str] = &["rustc_driver", "rustc_codegen_llvm"];
-
/// Crates rustc is allowed to depend on. Avoid adding to the list if possible.
///
/// This list is here to provide a speed-bump to adding a new dependency to
/// rustc. Please check with the compiler team before adding an entry.
-const PERMITTED_DEPENDENCIES: &[&str] = &[
+const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
"addr2line",
"adler",
"ahash",
@@ -218,6 +217,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
"time",
"tinystr",
"tinyvec",
+ "tinyvec_macros",
"thin-vec",
"tracing",
"tracing-attributes",
@@ -236,6 +236,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
"unic-langid-macros",
"unic-langid-macros-impl",
"unic-ucd-version",
+ "unicode-ident",
"unicode-normalization",
"unicode-script",
"unicode-security",
@@ -258,7 +259,9 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
"ahash",
"anyhow",
"ar",
+ "arrayvec",
"autocfg",
+ "bumpalo",
"bitflags",
"byteorder",
"cfg-if",
@@ -305,7 +308,7 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
];
const FORBIDDEN_TO_HAVE_DUPLICATES: &[&str] = &[
- // These two crates take quite a long time to build, so don't allow two versions of them
+ // This crate takes quite a long time to build, so don't allow two versions of them
// to accidentally sneak into our dependency graph, in order to ensure we keep our CI times
// under control.
"cargo",
@@ -322,12 +325,12 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = compute_runtime_crates(&metadata);
- check_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
- check_dependencies(
+ check_license_exceptions(&metadata, EXCEPTIONS, runtime_ids, bad);
+ check_permitted_dependencies(
&metadata,
- "main workspace",
- PERMITTED_DEPENDENCIES,
- RESTRICTED_DEPENDENCY_CRATES,
+ "rustc",
+ PERMITTED_RUSTC_DEPENDENCIES,
+ &["rustc_driver", "rustc_codegen_llvm"],
bad,
);
check_crate_duplicate(&metadata, FORBIDDEN_TO_HAVE_DUPLICATES, bad);
@@ -340,8 +343,8 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = HashSet::new();
- check_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
- check_dependencies(
+ check_license_exceptions(&metadata, EXCEPTIONS_CRANELIFT, runtime_ids, bad);
+ check_permitted_dependencies(
&metadata,
"cranelift",
PERMITTED_CRANELIFT_DEPENDENCIES,
@@ -356,13 +359,13 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
.features(cargo_metadata::CargoOpt::AllFeatures);
let metadata = t!(cmd.exec());
let runtime_ids = HashSet::new();
- check_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
+ check_license_exceptions(&metadata, EXCEPTIONS_BOOTSTRAP, runtime_ids, bad);
}
/// Check that all licenses are in the valid list in `LICENSES`.
///
-/// Packages listed in `EXCEPTIONS` are allowed for tools.
-fn check_exceptions(
+/// Packages listed in `exceptions` are allowed for tools.
+fn check_license_exceptions(
metadata: &Metadata,
exceptions: &[(&str, &str)],
runtime_ids: HashSet<&PackageId>,
@@ -432,11 +435,11 @@ fn check_exceptions(
}
}
-/// Checks the dependency of `RESTRICTED_DEPENDENCY_CRATES` at the given path. Changes `bad` to
+/// Checks the dependency of `restricted_dependency_crates` at the given path. Changes `bad` to
/// `true` if a check failed.
///
-/// Specifically, this checks that the dependencies are on the `PERMITTED_DEPENDENCIES`.
-fn check_dependencies(
+/// Specifically, this checks that the dependencies are on the `permitted_dependencies`.
+fn check_permitted_dependencies(
metadata: &Metadata,
descr: &str,
permitted_dependencies: &[&'static str],
diff --git a/src/tools/tidy/src/edition.rs b/src/tools/tidy/src/edition.rs
index b0abee459..8a7c4460d 100644
--- a/src/tools/tidy/src/edition.rs
+++ b/src/tools/tidy/src/edition.rs
@@ -1,5 +1,6 @@
//! Tidy check to ensure that crate `edition` is '2018' or '2021'.
+use crate::walk::{filter_dirs, walk};
use std::path::Path;
fn is_edition_2021(mut line: &str) -> bool {
@@ -8,9 +9,9 @@ fn is_edition_2021(mut line: &str) -> bool {
}
pub fn check(path: &Path, bad: &mut bool) {
- super::walk(
+ walk(
path,
- &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
+ &mut |path| filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap();
diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs
index 0a226443e..610e322e1 100644
--- a/src/tools/tidy/src/error_codes_check.rs
+++ b/src/tools/tidy/src/error_codes_check.rs
@@ -1,6 +1,7 @@
//! Checks that all error codes have at least one test to prevent having error
//! codes that are silently not thrown by the compiler anymore.
+use crate::walk::{filter_dirs, walk};
use std::collections::{HashMap, HashSet};
use std::ffi::OsStr;
use std::fs::read_to_string;
@@ -217,7 +218,7 @@ pub fn check(paths: &[&Path], bad: &mut bool) {
println!("Checking which error codes lack tests...");
for path in paths {
- super::walk(path, &mut super::filter_dirs, &mut |entry, contents| {
+ walk(path, &mut filter_dirs, &mut |entry, contents| {
let file_name = entry.file_name();
let entry_path = entry.path();
diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs
index dbcc9341a..fe5fd72b9 100644
--- a/src/tools/tidy/src/errors.rs
+++ b/src/tools/tidy/src/errors.rs
@@ -3,14 +3,15 @@
//! This ensures that error codes are used at most once and also prints out some
//! statistics about the error codes.
+use crate::walk::{filter_dirs, walk};
use std::collections::HashMap;
use std::path::Path;
pub fn check(path: &Path, bad: &mut bool) {
let mut map: HashMap<_, Vec<_>> = HashMap::new();
- super::walk(
+ walk(
path,
- &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
+ &mut |path| filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index b306a527a..f10ecf5f2 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -9,7 +9,8 @@
//! * All unstable lang features have tests to ensure they are actually unstable.
//! * Language features in a group are sorted by feature name.
-use std::collections::HashMap;
+use crate::walk::{filter_dirs, walk, walk_many};
+use std::collections::hash_map::{Entry, HashMap};
use std::fmt;
use std::fs;
use std::num::NonZeroU32;
@@ -92,14 +93,14 @@ pub fn check(
let lib_features = get_and_check_lib_features(lib_path, bad, &features);
assert!(!lib_features.is_empty());
- super::walk_many(
+ walk_many(
&[
&src_path.join("test/ui"),
&src_path.join("test/ui-fulldeps"),
&src_path.join("test/rustdoc-ui"),
&src_path.join("test/rustdoc"),
],
- &mut |path| super::filter_dirs(path),
+ &mut filter_dirs,
&mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
@@ -279,13 +280,14 @@ fn test_filen_gate(filen_underscore: &str, features: &mut Features) -> bool {
}
pub fn collect_lang_features(base_compiler_path: &Path, bad: &mut bool) -> Features {
- let mut all = collect_lang_features_in(base_compiler_path, "active.rs", bad);
- all.extend(collect_lang_features_in(base_compiler_path, "accepted.rs", bad));
- all.extend(collect_lang_features_in(base_compiler_path, "removed.rs", bad));
- all
+ let mut features = Features::new();
+ collect_lang_features_in(&mut features, base_compiler_path, "active.rs", bad);
+ collect_lang_features_in(&mut features, base_compiler_path, "accepted.rs", bad);
+ collect_lang_features_in(&mut features, base_compiler_path, "removed.rs", bad);
+ features
}
-fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features {
+fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, bad: &mut bool) {
let path = base.join("rustc_feature").join("src").join(file);
let contents = t!(fs::read_to_string(&path));
@@ -297,135 +299,145 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
let mut in_feature_group = false;
let mut prev_names = vec![];
- contents
- .lines()
- .zip(1..)
- .filter_map(|(line, line_number)| {
- let line = line.trim();
-
- // Within -start and -end, the tracking issue can be omitted.
- match line {
- "// no-tracking-issue-start" => {
- next_feature_omits_tracking_issue = true;
- return None;
- }
- "// no-tracking-issue-end" => {
- next_feature_omits_tracking_issue = false;
- return None;
- }
- _ => {}
+ let lines = contents.lines().zip(1..);
+ for (line, line_number) in lines {
+ let line = line.trim();
+
+ // Within -start and -end, the tracking issue can be omitted.
+ match line {
+ "// no-tracking-issue-start" => {
+ next_feature_omits_tracking_issue = true;
+ continue;
}
+ "// no-tracking-issue-end" => {
+ next_feature_omits_tracking_issue = false;
+ continue;
+ }
+ _ => {}
+ }
- if line.starts_with(FEATURE_GROUP_START_PREFIX) {
- if in_feature_group {
- tidy_error!(
- bad,
- "{}:{}: \
+ if line.starts_with(FEATURE_GROUP_START_PREFIX) {
+ if in_feature_group {
+ tidy_error!(
+ bad,
+ "{}:{}: \
new feature group is started without ending the previous one",
- path.display(),
- line_number,
- );
- }
-
- in_feature_group = true;
- prev_names = vec![];
- return None;
- } else if line.starts_with(FEATURE_GROUP_END_PREFIX) {
- in_feature_group = false;
- prev_names = vec![];
- return None;
+ path.display(),
+ line_number,
+ );
}
- let mut parts = line.split(',');
- let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
- Some("active") => Status::Unstable,
- Some("incomplete") => Status::Unstable,
- Some("removed") => Status::Removed,
- Some("accepted") => Status::Stable,
- _ => return None,
- };
- let name = parts.next().unwrap().trim();
-
- let since_str = parts.next().unwrap().trim().trim_matches('"');
- let since = match since_str.parse() {
- Ok(since) => Some(since),
- Err(err) => {
- tidy_error!(
- bad,
- "{}:{}: failed to parse since: {} ({:?})",
- path.display(),
- line_number,
- since_str,
- err,
- );
- None
- }
- };
- if in_feature_group {
- if prev_names.last() > Some(&name) {
- // This assumes the user adds the feature name at the end of the list, as we're
- // not looking ahead.
- let correct_index = match prev_names.binary_search(&name) {
- Ok(_) => {
- // This only occurs when the feature name has already been declared.
- tidy_error!(
- bad,
- "{}:{}: duplicate feature {}",
- path.display(),
- line_number,
- name,
- );
- // skip any additional checks for this line
- return None;
- }
- Err(index) => index,
- };
+ in_feature_group = true;
+ prev_names = vec![];
+ continue;
+ } else if line.starts_with(FEATURE_GROUP_END_PREFIX) {
+ in_feature_group = false;
+ prev_names = vec![];
+ continue;
+ }
- let correct_placement = if correct_index == 0 {
- "at the beginning of the feature group".to_owned()
- } else if correct_index == prev_names.len() {
- // I don't believe this is reachable given the above assumption, but it
- // doesn't hurt to be safe.
- "at the end of the feature group".to_owned()
- } else {
- format!(
- "between {} and {}",
- prev_names[correct_index - 1],
- prev_names[correct_index],
- )
- };
+ let mut parts = line.split(',');
+ let level = match parts.next().map(|l| l.trim().trim_start_matches('(')) {
+ Some("active") => Status::Unstable,
+ Some("incomplete") => Status::Unstable,
+ Some("removed") => Status::Removed,
+ Some("accepted") => Status::Stable,
+ _ => continue,
+ };
+ let name = parts.next().unwrap().trim();
+
+ let since_str = parts.next().unwrap().trim().trim_matches('"');
+ let since = match since_str.parse() {
+ Ok(since) => Some(since),
+ Err(err) => {
+ tidy_error!(
+ bad,
+ "{}:{}: failed to parse since: {} ({:?})",
+ path.display(),
+ line_number,
+ since_str,
+ err,
+ );
+ None
+ }
+ };
+ if in_feature_group {
+ if prev_names.last() > Some(&name) {
+ // This assumes the user adds the feature name at the end of the list, as we're
+ // not looking ahead.
+ let correct_index = match prev_names.binary_search(&name) {
+ Ok(_) => {
+ // This only occurs when the feature name has already been declared.
+ tidy_error!(
+ bad,
+ "{}:{}: duplicate feature {}",
+ path.display(),
+ line_number,
+ name,
+ );
+ // skip any additional checks for this line
+ continue;
+ }
+ Err(index) => index,
+ };
- tidy_error!(
- bad,
- "{}:{}: feature {} is not sorted by feature name (should be {})",
- path.display(),
- line_number,
- name,
- correct_placement,
- );
- }
- prev_names.push(name);
+ let correct_placement = if correct_index == 0 {
+ "at the beginning of the feature group".to_owned()
+ } else if correct_index == prev_names.len() {
+ // I don't believe this is reachable given the above assumption, but it
+ // doesn't hurt to be safe.
+ "at the end of the feature group".to_owned()
+ } else {
+ format!(
+ "between {} and {}",
+ prev_names[correct_index - 1],
+ prev_names[correct_index],
+ )
+ };
+
+ tidy_error!(
+ bad,
+ "{}:{}: feature {} is not sorted by feature name (should be {})",
+ path.display(),
+ line_number,
+ name,
+ correct_placement,
+ );
}
+ prev_names.push(name);
+ }
- let issue_str = parts.next().unwrap().trim();
- let tracking_issue = if issue_str.starts_with("None") {
- if level == Status::Unstable && !next_feature_omits_tracking_issue {
- tidy_error!(
- bad,
- "{}:{}: no tracking issue for feature {}",
- path.display(),
- line_number,
- name,
- );
- }
- None
- } else {
- let s = issue_str.split('(').nth(1).unwrap().split(')').next().unwrap();
- Some(s.parse().unwrap())
- };
- Some((name.to_owned(), Feature { level, since, has_gate_test: false, tracking_issue }))
- })
- .collect()
+ let issue_str = parts.next().unwrap().trim();
+ let tracking_issue = if issue_str.starts_with("None") {
+ if level == Status::Unstable && !next_feature_omits_tracking_issue {
+ tidy_error!(
+ bad,
+ "{}:{}: no tracking issue for feature {}",
+ path.display(),
+ line_number,
+ name,
+ );
+ }
+ None
+ } else {
+ let s = issue_str.split('(').nth(1).unwrap().split(')').next().unwrap();
+ Some(s.parse().unwrap())
+ };
+ match features.entry(name.to_owned()) {
+ Entry::Occupied(e) => {
+ tidy_error!(
+ bad,
+ "{}:{} feature {name} already specified with status '{}'",
+ path.display(),
+ line_number,
+ e.get().level,
+ );
+ }
+ Entry::Vacant(e) => {
+ e.insert(Feature { level, since, has_gate_test: false, tracking_issue });
+ }
+ }
+ }
}
fn get_and_check_lib_features(
@@ -466,9 +478,9 @@ fn map_lib_features(
base_src_path: &Path,
mf: &mut dyn FnMut(Result<(&str, Feature), &str>, &Path, usize),
) {
- super::walk(
+ walk(
base_src_path,
- &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
+ &mut |path| filter_dirs(path) || path.ends_with("src/test"),
&mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
@@ -537,7 +549,9 @@ fn map_lib_features(
becoming_feature = None;
if line.contains("rustc_const_unstable(") {
// `const fn` features are handled specially.
- let feature_name = match find_attr_val(line, "feature") {
+ let feature_name = match find_attr_val(line, "feature").or_else(|| {
+ iter_lines.peek().and_then(|next| find_attr_val(next.1, "feature"))
+ }) {
Some(name) => name,
None => err!("malformed stability attribute: missing `feature` key"),
};
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 12d3bdcd7..fc0bce585 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -3,8 +3,6 @@
//! This library contains the tidy lints and exposes it
//! to be used by tools.
-use walk::{filter_dirs, walk, walk_many, walk_no_read};
-
/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The expression that failed
@@ -40,6 +38,7 @@ macro_rules! tidy_error {
});
}
+pub mod alphabetical;
pub mod bins;
pub mod debug_artifacts;
pub mod deps;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index c1ce94f47..ca785042a 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -90,6 +90,10 @@ fn main() {
check!(edition, &compiler_path);
check!(edition, &library_path);
+ check!(alphabetical, &src_path);
+ check!(alphabetical, &compiler_path);
+ check!(alphabetical, &library_path);
+
let collected = {
while handles.len() >= concurrency.get() {
handles.pop_front().unwrap().join().unwrap();
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 4d86fe8be..f4592fdcf 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -30,6 +30,7 @@
//! platform-specific cfgs are allowed. Not sure yet how to deal with
//! this in the long term.
+use crate::walk::{filter_dirs, walk};
use std::iter::Iterator;
use std::path::Path;
@@ -67,7 +68,7 @@ pub fn check(path: &Path, bad: &mut bool) {
// Sanity check that the complex parsing here works.
let mut saw_target_arch = false;
let mut saw_cfg_bang = false;
- super::walk(path, &mut super::filter_dirs, &mut |entry, contents| {
+ walk(path, &mut filter_dirs, &mut |entry, contents| {
let file = entry.path();
let filestr = file.to_string_lossy().replace("\\", "/");
if !filestr.ends_with(".rs") {
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index dee58ff2f..541380ceb 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -16,6 +16,7 @@
//! A number of these checks can be opted-out of with various directives of the form:
//! `// ignore-tidy-CHECK-NAME`.
+use crate::walk::{filter_dirs, walk};
use regex::Regex;
use std::path::Path;
@@ -218,13 +219,13 @@ fn is_unexplained_ignore(extension: &str, line: &str) -> bool {
pub fn check(path: &Path, bad: &mut bool) {
fn skip(path: &Path) -> bool {
- super::filter_dirs(path) || skip_markdown_path(path)
+ filter_dirs(path) || skip_markdown_path(path)
}
let problematic_consts_strings: Vec<String> = (PROBLEMATIC_CONSTS.iter().map(u32::to_string))
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v)))
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
.collect();
- super::walk(path, &mut skip, &mut |entry, contents| {
+ walk(path, &mut skip, &mut |entry, contents| {
let file = entry.path();
let filename = file.file_name().unwrap().to_string_lossy();
let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"];
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index 723684bfa..8ba257056 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -36,7 +36,7 @@ struct RevisionInfo<'a> {
pub fn check(path: &Path, bad: &mut bool) {
let tests = path.join("test");
- super::walk(
+ crate::walk::walk(
&tests,
&mut |path| path.extension().map(|p| p == "rs") == Some(false),
&mut |entry, content| {
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 8ec5c3324..c600f99c2 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -7,8 +7,8 @@ use std::path::Path;
const ENTRY_LIMIT: usize = 1000;
// FIXME: The following limits should be reduced eventually.
-const ROOT_ENTRY_LIMIT: usize = 968;
-const ISSUES_ENTRY_LIMIT: usize = 2147;
+const ROOT_ENTRY_LIMIT: usize = 948;
+const ISSUES_ENTRY_LIMIT: usize = 2117;
fn check_entries(path: &Path, bad: &mut bool) {
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))
@@ -47,7 +47,7 @@ fn check_entries(path: &Path, bad: &mut bool) {
pub fn check(path: &Path, bad: &mut bool) {
check_entries(&path, bad);
for path in &[&path.join("test/ui"), &path.join("test/ui-fulldeps")] {
- super::walk_no_read(path, &mut |_| false, &mut |entry| {
+ crate::walk::walk_no_read(path, &mut |_| false, &mut |entry| {
let file_path = entry.path();
if let Some(ext) = file_path.extension() {
if ext == "stderr" || ext == "stdout" {
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
index f675b7865..2c23b6ebc 100644
--- a/src/tools/tidy/src/unit_tests.rs
+++ b/src/tools/tidy/src/unit_tests.rs
@@ -7,6 +7,7 @@
//! named `tests.rs` or `benches.rs`, or directories named `tests` or `benches` unconfigured
//! during normal build.
+use crate::walk::{filter_dirs, walk};
use std::path::Path;
pub fn check(root_path: &Path, bad: &mut bool) {
@@ -20,7 +21,7 @@ pub fn check(root_path: &Path, bad: &mut bool) {
let mut skip = |path: &Path| {
let file_name = path.file_name().unwrap_or_default();
if path.is_dir() {
- super::filter_dirs(path)
+ filter_dirs(path)
|| path.ends_with("src/test")
|| path.ends_with("src/doc")
|| (file_name == "tests" || file_name == "benches") && !is_core(path)
@@ -34,7 +35,7 @@ pub fn check(root_path: &Path, bad: &mut bool) {
}
};
- super::walk(root_path, &mut skip, &mut |entry, contents| {
+ walk(root_path, &mut skip, &mut |entry, contents| {
let path = entry.path();
let is_core = path.starts_with(core);
for (i, line) in contents.lines().enumerate() {
diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs
index b07e80767..4cfb70fa3 100644
--- a/src/tools/tidy/src/walk.rs
+++ b/src/tools/tidy/src/walk.rs
@@ -21,6 +21,12 @@ pub fn filter_dirs(path: &Path) -> bool {
"src/tools/rust-installer",
"src/tools/rustfmt",
"src/doc/book",
+ "src/doc/edition-guide",
+ "src/doc/embedded-book",
+ "src/doc/nomicon",
+ "src/doc/rust-by-example",
+ "src/doc/rustc-dev-guide",
+ "src/doc/reference",
// Filter RLS output directories
"target/rls",
"src/bootstrap/target",
diff --git a/src/version b/src/version
index 902c74186..b6148bc0a 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.65.0
+1.66.0
diff --git a/vendor/clap/.cargo-checksum.json b/vendor/clap-3.2.20/.cargo-checksum.json
index 22fa24875..22fa24875 100644
--- a/vendor/clap/.cargo-checksum.json
+++ b/vendor/clap-3.2.20/.cargo-checksum.json
diff --git a/vendor/clap/Cargo.lock b/vendor/clap-3.2.20/Cargo.lock
index 57d007104..57d007104 100644
--- a/vendor/clap/Cargo.lock
+++ b/vendor/clap-3.2.20/Cargo.lock
diff --git a/vendor/clap/Cargo.toml b/vendor/clap-3.2.20/Cargo.toml
index 197454c07..197454c07 100644
--- a/vendor/clap/Cargo.toml
+++ b/vendor/clap-3.2.20/Cargo.toml
diff --git a/vendor/clap/LICENSE-APACHE b/vendor/clap-3.2.20/LICENSE-APACHE
index 261eeb9e9..261eeb9e9 100644
--- a/vendor/clap/LICENSE-APACHE
+++ b/vendor/clap-3.2.20/LICENSE-APACHE
diff --git a/vendor/clap/LICENSE-MIT b/vendor/clap-3.2.20/LICENSE-MIT
index 7b05b8453..7b05b8453 100644
--- a/vendor/clap/LICENSE-MIT
+++ b/vendor/clap-3.2.20/LICENSE-MIT
diff --git a/vendor/clap/README.md b/vendor/clap-3.2.20/README.md
index eea6ba6f0..eea6ba6f0 100644
--- a/vendor/clap/README.md
+++ b/vendor/clap-3.2.20/README.md
diff --git a/vendor/clap/examples/cargo-example-derive.md b/vendor/clap-3.2.20/examples/cargo-example-derive.md
index 2c7a11b88..2c7a11b88 100644
--- a/vendor/clap/examples/cargo-example-derive.md
+++ b/vendor/clap-3.2.20/examples/cargo-example-derive.md
diff --git a/vendor/clap/examples/cargo-example-derive.rs b/vendor/clap-3.2.20/examples/cargo-example-derive.rs
index f0aad29c7..f0aad29c7 100644
--- a/vendor/clap/examples/cargo-example-derive.rs
+++ b/vendor/clap-3.2.20/examples/cargo-example-derive.rs
diff --git a/vendor/clap/examples/cargo-example.md b/vendor/clap-3.2.20/examples/cargo-example.md
index 6fb6a3c4d..6fb6a3c4d 100644
--- a/vendor/clap/examples/cargo-example.md
+++ b/vendor/clap-3.2.20/examples/cargo-example.md
diff --git a/vendor/clap/examples/cargo-example.rs b/vendor/clap-3.2.20/examples/cargo-example.rs
index d9a909f4f..d9a909f4f 100644
--- a/vendor/clap/examples/cargo-example.rs
+++ b/vendor/clap-3.2.20/examples/cargo-example.rs
diff --git a/vendor/clap/examples/demo.md b/vendor/clap-3.2.20/examples/demo.md
index 93ee49c37..93ee49c37 100644
--- a/vendor/clap/examples/demo.md
+++ b/vendor/clap-3.2.20/examples/demo.md
diff --git a/vendor/clap/examples/demo.rs b/vendor/clap-3.2.20/examples/demo.rs
index a7cecfb0c..a7cecfb0c 100644
--- a/vendor/clap/examples/demo.rs
+++ b/vendor/clap-3.2.20/examples/demo.rs
diff --git a/vendor/clap/examples/derive_ref/augment_args.rs b/vendor/clap-3.2.20/examples/derive_ref/augment_args.rs
index 310556914..310556914 100644
--- a/vendor/clap/examples/derive_ref/augment_args.rs
+++ b/vendor/clap-3.2.20/examples/derive_ref/augment_args.rs
diff --git a/vendor/clap/examples/derive_ref/augment_subcommands.rs b/vendor/clap-3.2.20/examples/derive_ref/augment_subcommands.rs
index 199da98b4..199da98b4 100644
--- a/vendor/clap/examples/derive_ref/augment_subcommands.rs
+++ b/vendor/clap-3.2.20/examples/derive_ref/augment_subcommands.rs
diff --git a/vendor/clap/examples/derive_ref/custom-bool.md b/vendor/clap-3.2.20/examples/derive_ref/custom-bool.md
index 619f9ba8e..619f9ba8e 100644
--- a/vendor/clap/examples/derive_ref/custom-bool.md
+++ b/vendor/clap-3.2.20/examples/derive_ref/custom-bool.md
diff --git a/vendor/clap/examples/derive_ref/custom-bool.rs b/vendor/clap-3.2.20/examples/derive_ref/custom-bool.rs
index d3c321e72..d3c321e72 100644
--- a/vendor/clap/examples/derive_ref/custom-bool.rs
+++ b/vendor/clap-3.2.20/examples/derive_ref/custom-bool.rs
diff --git a/vendor/clap/examples/derive_ref/flatten_hand_args.rs b/vendor/clap-3.2.20/examples/derive_ref/flatten_hand_args.rs
index c10e0b29f..c10e0b29f 100644
--- a/vendor/clap/examples/derive_ref/flatten_hand_args.rs
+++ b/vendor/clap-3.2.20/examples/derive_ref/flatten_hand_args.rs
diff --git a/vendor/clap/examples/derive_ref/hand_subcommand.rs b/vendor/clap-3.2.20/examples/derive_ref/hand_subcommand.rs
index e9423bdc0..e9423bdc0 100644
--- a/vendor/clap/examples/derive_ref/hand_subcommand.rs
+++ b/vendor/clap-3.2.20/examples/derive_ref/hand_subcommand.rs
diff --git a/vendor/clap/examples/derive_ref/interop_tests.md b/vendor/clap-3.2.20/examples/derive_ref/interop_tests.md
index 746fe1878..746fe1878 100644
--- a/vendor/clap/examples/derive_ref/interop_tests.md
+++ b/vendor/clap-3.2.20/examples/derive_ref/interop_tests.md
diff --git a/vendor/clap/examples/escaped-positional-derive.md b/vendor/clap-3.2.20/examples/escaped-positional-derive.md
index fa39a2c03..fa39a2c03 100644
--- a/vendor/clap/examples/escaped-positional-derive.md
+++ b/vendor/clap-3.2.20/examples/escaped-positional-derive.md
diff --git a/vendor/clap/examples/escaped-positional-derive.rs b/vendor/clap-3.2.20/examples/escaped-positional-derive.rs
index fd8fde4ed..fd8fde4ed 100644
--- a/vendor/clap/examples/escaped-positional-derive.rs
+++ b/vendor/clap-3.2.20/examples/escaped-positional-derive.rs
diff --git a/vendor/clap/examples/escaped-positional.md b/vendor/clap-3.2.20/examples/escaped-positional.md
index 987b26139..987b26139 100644
--- a/vendor/clap/examples/escaped-positional.md
+++ b/vendor/clap-3.2.20/examples/escaped-positional.md
diff --git a/vendor/clap/examples/escaped-positional.rs b/vendor/clap-3.2.20/examples/escaped-positional.rs
index fdcb930fb..fdcb930fb 100644
--- a/vendor/clap/examples/escaped-positional.rs
+++ b/vendor/clap-3.2.20/examples/escaped-positional.rs
diff --git a/vendor/clap/examples/git-derive.md b/vendor/clap-3.2.20/examples/git-derive.md
index aa1ca6d9d..aa1ca6d9d 100644
--- a/vendor/clap/examples/git-derive.md
+++ b/vendor/clap-3.2.20/examples/git-derive.md
diff --git a/vendor/clap/examples/git-derive.rs b/vendor/clap-3.2.20/examples/git-derive.rs
index ac500ddad..ac500ddad 100644
--- a/vendor/clap/examples/git-derive.rs
+++ b/vendor/clap-3.2.20/examples/git-derive.rs
diff --git a/vendor/clap/examples/git.md b/vendor/clap-3.2.20/examples/git.md
index 9e413415a..9e413415a 100644
--- a/vendor/clap/examples/git.md
+++ b/vendor/clap-3.2.20/examples/git.md
diff --git a/vendor/clap/examples/git.rs b/vendor/clap-3.2.20/examples/git.rs
index e56f427a6..e56f427a6 100644
--- a/vendor/clap/examples/git.rs
+++ b/vendor/clap-3.2.20/examples/git.rs
diff --git a/vendor/clap/examples/multicall-busybox.md b/vendor/clap-3.2.20/examples/multicall-busybox.md
index 5ca2cad5b..5ca2cad5b 100644
--- a/vendor/clap/examples/multicall-busybox.md
+++ b/vendor/clap-3.2.20/examples/multicall-busybox.md
diff --git a/vendor/clap/examples/multicall-busybox.rs b/vendor/clap-3.2.20/examples/multicall-busybox.rs
index 2e7f976c1..2e7f976c1 100644
--- a/vendor/clap/examples/multicall-busybox.rs
+++ b/vendor/clap-3.2.20/examples/multicall-busybox.rs
diff --git a/vendor/clap/examples/multicall-hostname.md b/vendor/clap-3.2.20/examples/multicall-hostname.md
index d22b85fba..d22b85fba 100644
--- a/vendor/clap/examples/multicall-hostname.md
+++ b/vendor/clap-3.2.20/examples/multicall-hostname.md
diff --git a/vendor/clap/examples/multicall-hostname.rs b/vendor/clap-3.2.20/examples/multicall-hostname.rs
index b57680a5c..b57680a5c 100644
--- a/vendor/clap/examples/multicall-hostname.rs
+++ b/vendor/clap-3.2.20/examples/multicall-hostname.rs
diff --git a/vendor/clap/examples/pacman.md b/vendor/clap-3.2.20/examples/pacman.md
index b8ddd09d9..b8ddd09d9 100644
--- a/vendor/clap/examples/pacman.md
+++ b/vendor/clap-3.2.20/examples/pacman.md
diff --git a/vendor/clap/examples/pacman.rs b/vendor/clap-3.2.20/examples/pacman.rs
index aee7cd892..aee7cd892 100644
--- a/vendor/clap/examples/pacman.rs
+++ b/vendor/clap-3.2.20/examples/pacman.rs
diff --git a/vendor/clap/examples/repl.rs b/vendor/clap-3.2.20/examples/repl.rs
index c509adee6..c509adee6 100644
--- a/vendor/clap/examples/repl.rs
+++ b/vendor/clap-3.2.20/examples/repl.rs
diff --git a/vendor/clap/examples/tutorial_builder/01_quick.md b/vendor/clap-3.2.20/examples/tutorial_builder/01_quick.md
index 4a9e3fca1..4a9e3fca1 100644
--- a/vendor/clap/examples/tutorial_builder/01_quick.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/01_quick.md
diff --git a/vendor/clap/examples/tutorial_builder/01_quick.rs b/vendor/clap-3.2.20/examples/tutorial_builder/01_quick.rs
index 393d6aeae..393d6aeae 100644
--- a/vendor/clap/examples/tutorial_builder/01_quick.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/01_quick.rs
diff --git a/vendor/clap/examples/tutorial_builder/02_app_settings.md b/vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.md
index 247843bcf..247843bcf 100644
--- a/vendor/clap/examples/tutorial_builder/02_app_settings.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.md
diff --git a/vendor/clap/examples/tutorial_builder/02_app_settings.rs b/vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.rs
index 5f374d7f0..5f374d7f0 100644
--- a/vendor/clap/examples/tutorial_builder/02_app_settings.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_app_settings.rs
diff --git a/vendor/clap/examples/tutorial_builder/02_apps.md b/vendor/clap-3.2.20/examples/tutorial_builder/02_apps.md
index 8504b5f52..8504b5f52 100644
--- a/vendor/clap/examples/tutorial_builder/02_apps.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_apps.md
diff --git a/vendor/clap/examples/tutorial_builder/02_apps.rs b/vendor/clap-3.2.20/examples/tutorial_builder/02_apps.rs
index db9da18f9..db9da18f9 100644
--- a/vendor/clap/examples/tutorial_builder/02_apps.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_apps.rs
diff --git a/vendor/clap/examples/tutorial_builder/02_crate.md b/vendor/clap-3.2.20/examples/tutorial_builder/02_crate.md
index f76e0d608..f76e0d608 100644
--- a/vendor/clap/examples/tutorial_builder/02_crate.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_crate.md
diff --git a/vendor/clap/examples/tutorial_builder/02_crate.rs b/vendor/clap-3.2.20/examples/tutorial_builder/02_crate.rs
index 8a1722fd3..8a1722fd3 100644
--- a/vendor/clap/examples/tutorial_builder/02_crate.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/02_crate.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_bool.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.md
index b0ee2a126..b0ee2a126 100644
--- a/vendor/clap/examples/tutorial_builder/03_01_flag_bool.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.md
diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.rs
index 03f2f1756..03f2f1756 100644
--- a/vendor/clap/examples/tutorial_builder/03_01_flag_bool.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_bool.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_count.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.md
index ca4bcd6eb..ca4bcd6eb 100644
--- a/vendor/clap/examples/tutorial_builder/03_01_flag_count.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.md
diff --git a/vendor/clap/examples/tutorial_builder/03_01_flag_count.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.rs
index 7f23649d6..7f23649d6 100644
--- a/vendor/clap/examples/tutorial_builder/03_01_flag_count.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_01_flag_count.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_02_option.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.md
index 6198bcc73..6198bcc73 100644
--- a/vendor/clap/examples/tutorial_builder/03_02_option.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.md
diff --git a/vendor/clap/examples/tutorial_builder/03_02_option.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.rs
index 188244566..188244566 100644
--- a/vendor/clap/examples/tutorial_builder/03_02_option.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_02_option.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_03_positional.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.md
index a3d7b8cf3..a3d7b8cf3 100644
--- a/vendor/clap/examples/tutorial_builder/03_03_positional.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.md
diff --git a/vendor/clap/examples/tutorial_builder/03_03_positional.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.rs
index 0c3a5f037..0c3a5f037 100644
--- a/vendor/clap/examples/tutorial_builder/03_03_positional.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_03_positional.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_04_subcommands.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.md
index 8f9efa911..8f9efa911 100644
--- a/vendor/clap/examples/tutorial_builder/03_04_subcommands.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.md
diff --git a/vendor/clap/examples/tutorial_builder/03_04_subcommands.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.rs
index fbe23809e..fbe23809e 100644
--- a/vendor/clap/examples/tutorial_builder/03_04_subcommands.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_04_subcommands.rs
diff --git a/vendor/clap/examples/tutorial_builder/03_05_default_values.md b/vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.md
index 7b6c0307d..7b6c0307d 100644
--- a/vendor/clap/examples/tutorial_builder/03_05_default_values.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.md
diff --git a/vendor/clap/examples/tutorial_builder/03_05_default_values.rs b/vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.rs
index cb3e3831f..cb3e3831f 100644
--- a/vendor/clap/examples/tutorial_builder/03_05_default_values.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/03_05_default_values.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_01_enum.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.md
index 282b1e613..282b1e613 100644
--- a/vendor/clap/examples/tutorial_builder/04_01_enum.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.md
diff --git a/vendor/clap/examples/tutorial_builder/04_01_enum.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.rs
index e8cf70f5c..e8cf70f5c 100644
--- a/vendor/clap/examples/tutorial_builder/04_01_enum.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_enum.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_01_possible.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.md
index 2909bfb17..2909bfb17 100644
--- a/vendor/clap/examples/tutorial_builder/04_01_possible.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.md
diff --git a/vendor/clap/examples/tutorial_builder/04_01_possible.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.rs
index 3da7aca74..3da7aca74 100644
--- a/vendor/clap/examples/tutorial_builder/04_01_possible.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_01_possible.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_02_parse.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.md
index 605bf4b59..605bf4b59 100644
--- a/vendor/clap/examples/tutorial_builder/04_02_parse.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.md
diff --git a/vendor/clap/examples/tutorial_builder/04_02_parse.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.rs
index 13f41a18e..13f41a18e 100644
--- a/vendor/clap/examples/tutorial_builder/04_02_parse.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_parse.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_02_validate.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.md
index a317a8eb7..a317a8eb7 100644
--- a/vendor/clap/examples/tutorial_builder/04_02_validate.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.md
diff --git a/vendor/clap/examples/tutorial_builder/04_02_validate.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.rs
index ea2f32e67..ea2f32e67 100644
--- a/vendor/clap/examples/tutorial_builder/04_02_validate.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_02_validate.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_03_relations.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.md
index 3ea336363..3ea336363 100644
--- a/vendor/clap/examples/tutorial_builder/04_03_relations.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.md
diff --git a/vendor/clap/examples/tutorial_builder/04_03_relations.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.rs
index 8e26d3ea9..8e26d3ea9 100644
--- a/vendor/clap/examples/tutorial_builder/04_03_relations.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_03_relations.rs
diff --git a/vendor/clap/examples/tutorial_builder/04_04_custom.md b/vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.md
index 26a3df1ab..26a3df1ab 100644
--- a/vendor/clap/examples/tutorial_builder/04_04_custom.md
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.md
diff --git a/vendor/clap/examples/tutorial_builder/04_04_custom.rs b/vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.rs
index fb40b2fc4..fb40b2fc4 100644
--- a/vendor/clap/examples/tutorial_builder/04_04_custom.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/04_04_custom.rs
diff --git a/vendor/clap/examples/tutorial_builder/05_01_assert.rs b/vendor/clap-3.2.20/examples/tutorial_builder/05_01_assert.rs
index 4b9254230..4b9254230 100644
--- a/vendor/clap/examples/tutorial_builder/05_01_assert.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_builder/05_01_assert.rs
diff --git a/vendor/clap/examples/tutorial_derive/01_quick.md b/vendor/clap-3.2.20/examples/tutorial_derive/01_quick.md
index 6f70d2cce..6f70d2cce 100644
--- a/vendor/clap/examples/tutorial_derive/01_quick.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/01_quick.md
diff --git a/vendor/clap/examples/tutorial_derive/01_quick.rs b/vendor/clap-3.2.20/examples/tutorial_derive/01_quick.rs
index 2c2031061..2c2031061 100644
--- a/vendor/clap/examples/tutorial_derive/01_quick.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/01_quick.rs
diff --git a/vendor/clap/examples/tutorial_derive/02_app_settings.md b/vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.md
index ee16c66df..ee16c66df 100644
--- a/vendor/clap/examples/tutorial_derive/02_app_settings.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.md
diff --git a/vendor/clap/examples/tutorial_derive/02_app_settings.rs b/vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.rs
index 6a06929bb..6a06929bb 100644
--- a/vendor/clap/examples/tutorial_derive/02_app_settings.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_app_settings.rs
diff --git a/vendor/clap/examples/tutorial_derive/02_apps.md b/vendor/clap-3.2.20/examples/tutorial_derive/02_apps.md
index 0141581c4..0141581c4 100644
--- a/vendor/clap/examples/tutorial_derive/02_apps.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_apps.md
diff --git a/vendor/clap/examples/tutorial_derive/02_apps.rs b/vendor/clap-3.2.20/examples/tutorial_derive/02_apps.rs
index b97ce1eed..b97ce1eed 100644
--- a/vendor/clap/examples/tutorial_derive/02_apps.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_apps.rs
diff --git a/vendor/clap/examples/tutorial_derive/02_crate.md b/vendor/clap-3.2.20/examples/tutorial_derive/02_crate.md
index 92c820758..92c820758 100644
--- a/vendor/clap/examples/tutorial_derive/02_crate.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_crate.md
diff --git a/vendor/clap/examples/tutorial_derive/02_crate.rs b/vendor/clap-3.2.20/examples/tutorial_derive/02_crate.rs
index 5576f998c..5576f998c 100644
--- a/vendor/clap/examples/tutorial_derive/02_crate.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/02_crate.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_01_flag_bool.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.md
index 0baaa10ca..0baaa10ca 100644
--- a/vendor/clap/examples/tutorial_derive/03_01_flag_bool.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.md
diff --git a/vendor/clap/examples/tutorial_derive/03_01_flag_bool.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.rs
index de677d8c6..de677d8c6 100644
--- a/vendor/clap/examples/tutorial_derive/03_01_flag_bool.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_bool.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_01_flag_count.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.md
index 3d5a53084..3d5a53084 100644
--- a/vendor/clap/examples/tutorial_derive/03_01_flag_count.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.md
diff --git a/vendor/clap/examples/tutorial_derive/03_01_flag_count.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.rs
index 680f7f5e5..680f7f5e5 100644
--- a/vendor/clap/examples/tutorial_derive/03_01_flag_count.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_01_flag_count.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_02_option.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.md
index 84ff7fa74..84ff7fa74 100644
--- a/vendor/clap/examples/tutorial_derive/03_02_option.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.md
diff --git a/vendor/clap/examples/tutorial_derive/03_02_option.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.rs
index 75b67afe7..75b67afe7 100644
--- a/vendor/clap/examples/tutorial_derive/03_02_option.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_02_option.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_03_positional.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.md
index 7281fe3ff..7281fe3ff 100644
--- a/vendor/clap/examples/tutorial_derive/03_03_positional.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.md
diff --git a/vendor/clap/examples/tutorial_derive/03_03_positional.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.rs
index 7478951f1..7478951f1 100644
--- a/vendor/clap/examples/tutorial_derive/03_03_positional.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_03_positional.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_04_subcommands.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.md
index 02f96e3d3..02f96e3d3 100644
--- a/vendor/clap/examples/tutorial_derive/03_04_subcommands.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.md
diff --git a/vendor/clap/examples/tutorial_derive/03_04_subcommands.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.rs
index 62a45a97e..62a45a97e 100644
--- a/vendor/clap/examples/tutorial_derive/03_04_subcommands.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_04_subcommands_alt.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands_alt.rs
index b6124936c..b6124936c 100644
--- a/vendor/clap/examples/tutorial_derive/03_04_subcommands_alt.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_04_subcommands_alt.rs
diff --git a/vendor/clap/examples/tutorial_derive/03_05_default_values.md b/vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.md
index f7315e736..f7315e736 100644
--- a/vendor/clap/examples/tutorial_derive/03_05_default_values.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.md
diff --git a/vendor/clap/examples/tutorial_derive/03_05_default_values.rs b/vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.rs
index 10a1ec808..10a1ec808 100644
--- a/vendor/clap/examples/tutorial_derive/03_05_default_values.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/03_05_default_values.rs
diff --git a/vendor/clap/examples/tutorial_derive/04_01_enum.md b/vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.md
index 2523af924..2523af924 100644
--- a/vendor/clap/examples/tutorial_derive/04_01_enum.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.md
diff --git a/vendor/clap/examples/tutorial_derive/04_01_enum.rs b/vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.rs
index 1ac984288..1ac984288 100644
--- a/vendor/clap/examples/tutorial_derive/04_01_enum.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_01_enum.rs
diff --git a/vendor/clap/examples/tutorial_derive/04_02_parse.md b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.md
index 6079ef193..6079ef193 100644
--- a/vendor/clap/examples/tutorial_derive/04_02_parse.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.md
diff --git a/vendor/clap/examples/tutorial_derive/04_02_parse.rs b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.rs
index 6336a9cf1..6336a9cf1 100644
--- a/vendor/clap/examples/tutorial_derive/04_02_parse.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_parse.rs
diff --git a/vendor/clap/examples/tutorial_derive/04_02_validate.md b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.md
index cc43440ef..cc43440ef 100644
--- a/vendor/clap/examples/tutorial_derive/04_02_validate.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.md
diff --git a/vendor/clap/examples/tutorial_derive/04_02_validate.rs b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.rs
index 7dac79c9f..7dac79c9f 100644
--- a/vendor/clap/examples/tutorial_derive/04_02_validate.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_02_validate.rs
diff --git a/vendor/clap/examples/tutorial_derive/04_03_relations.md b/vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.md
index 4f5703d82..4f5703d82 100644
--- a/vendor/clap/examples/tutorial_derive/04_03_relations.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.md
diff --git a/vendor/clap/examples/tutorial_derive/04_03_relations.rs b/vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.rs
index 37efe95e3..37efe95e3 100644
--- a/vendor/clap/examples/tutorial_derive/04_03_relations.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_03_relations.rs
diff --git a/vendor/clap/examples/tutorial_derive/04_04_custom.md b/vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.md
index 0f19bfe31..0f19bfe31 100644
--- a/vendor/clap/examples/tutorial_derive/04_04_custom.md
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.md
diff --git a/vendor/clap/examples/tutorial_derive/04_04_custom.rs b/vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.rs
index 454d489c1..454d489c1 100644
--- a/vendor/clap/examples/tutorial_derive/04_04_custom.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/04_04_custom.rs
diff --git a/vendor/clap/examples/tutorial_derive/05_01_assert.rs b/vendor/clap-3.2.20/examples/tutorial_derive/05_01_assert.rs
index 66dca727f..66dca727f 100644
--- a/vendor/clap/examples/tutorial_derive/05_01_assert.rs
+++ b/vendor/clap-3.2.20/examples/tutorial_derive/05_01_assert.rs
diff --git a/vendor/clap/examples/typed-derive.md b/vendor/clap-3.2.20/examples/typed-derive.md
index 9c7615c63..9c7615c63 100644
--- a/vendor/clap/examples/typed-derive.md
+++ b/vendor/clap-3.2.20/examples/typed-derive.md
diff --git a/vendor/clap/examples/typed-derive.rs b/vendor/clap-3.2.20/examples/typed-derive.rs
index 31084029d..31084029d 100644
--- a/vendor/clap/examples/typed-derive.rs
+++ b/vendor/clap-3.2.20/examples/typed-derive.rs
diff --git a/vendor/clap/src/_cookbook/cargo_example.rs b/vendor/clap-3.2.20/src/_cookbook/cargo_example.rs
index ec5d582db..ec5d582db 100644
--- a/vendor/clap/src/_cookbook/cargo_example.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/cargo_example.rs
diff --git a/vendor/clap/src/_cookbook/cargo_example_derive b/vendor/clap-3.2.20/src/_cookbook/cargo_example_derive
index e69de29bb..e69de29bb 100644
--- a/vendor/clap/src/_cookbook/cargo_example_derive
+++ b/vendor/clap-3.2.20/src/_cookbook/cargo_example_derive
diff --git a/vendor/clap/src/_cookbook/cargo_example_derive.rs b/vendor/clap-3.2.20/src/_cookbook/cargo_example_derive.rs
index d49f956f9..d49f956f9 100644
--- a/vendor/clap/src/_cookbook/cargo_example_derive.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/cargo_example_derive.rs
diff --git a/vendor/clap/src/_cookbook/escaped_positional.rs b/vendor/clap-3.2.20/src/_cookbook/escaped_positional.rs
index 99a3f83f3..99a3f83f3 100644
--- a/vendor/clap/src/_cookbook/escaped_positional.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/escaped_positional.rs
diff --git a/vendor/clap/src/_cookbook/escaped_positional_derive.rs b/vendor/clap-3.2.20/src/_cookbook/escaped_positional_derive.rs
index e6f99ad17..e6f99ad17 100644
--- a/vendor/clap/src/_cookbook/escaped_positional_derive.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/escaped_positional_derive.rs
diff --git a/vendor/clap/src/_cookbook/git.rs b/vendor/clap-3.2.20/src/_cookbook/git.rs
index 03a926ca8..03a926ca8 100644
--- a/vendor/clap/src/_cookbook/git.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/git.rs
diff --git a/vendor/clap/src/_cookbook/git_derive.rs b/vendor/clap-3.2.20/src/_cookbook/git_derive.rs
index d3119736d..d3119736d 100644
--- a/vendor/clap/src/_cookbook/git_derive.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/git_derive.rs
diff --git a/vendor/clap/src/_cookbook/mod.rs b/vendor/clap-3.2.20/src/_cookbook/mod.rs
index 1a78ed11b..1a78ed11b 100644
--- a/vendor/clap/src/_cookbook/mod.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/mod.rs
diff --git a/vendor/clap/src/_cookbook/multicall_busybox.rs b/vendor/clap-3.2.20/src/_cookbook/multicall_busybox.rs
index e3384d682..e3384d682 100644
--- a/vendor/clap/src/_cookbook/multicall_busybox.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/multicall_busybox.rs
diff --git a/vendor/clap/src/_cookbook/multicall_hostname.rs b/vendor/clap-3.2.20/src/_cookbook/multicall_hostname.rs
index 9777654dc..9777654dc 100644
--- a/vendor/clap/src/_cookbook/multicall_hostname.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/multicall_hostname.rs
diff --git a/vendor/clap/src/_cookbook/pacman.rs b/vendor/clap-3.2.20/src/_cookbook/pacman.rs
index 880c58158..880c58158 100644
--- a/vendor/clap/src/_cookbook/pacman.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/pacman.rs
diff --git a/vendor/clap/src/_cookbook/repl.rs b/vendor/clap-3.2.20/src/_cookbook/repl.rs
index 549ec8259..549ec8259 100644
--- a/vendor/clap/src/_cookbook/repl.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/repl.rs
diff --git a/vendor/clap/src/_cookbook/typed_derive.rs b/vendor/clap-3.2.20/src/_cookbook/typed_derive.rs
index a5fd15ff8..a5fd15ff8 100644
--- a/vendor/clap/src/_cookbook/typed_derive.rs
+++ b/vendor/clap-3.2.20/src/_cookbook/typed_derive.rs
diff --git a/vendor/clap/src/_derive/_tutorial.rs b/vendor/clap-3.2.20/src/_derive/_tutorial.rs
index abd57cef8..abd57cef8 100644
--- a/vendor/clap/src/_derive/_tutorial.rs
+++ b/vendor/clap-3.2.20/src/_derive/_tutorial.rs
diff --git a/vendor/clap/src/_derive/mod.rs b/vendor/clap-3.2.20/src/_derive/mod.rs
index fc9f35db5..fc9f35db5 100644
--- a/vendor/clap/src/_derive/mod.rs
+++ b/vendor/clap-3.2.20/src/_derive/mod.rs
diff --git a/vendor/clap/src/_faq.rs b/vendor/clap-3.2.20/src/_faq.rs
index 661a7e73d..661a7e73d 100644
--- a/vendor/clap/src/_faq.rs
+++ b/vendor/clap-3.2.20/src/_faq.rs
diff --git a/vendor/clap/src/_features.rs b/vendor/clap-3.2.20/src/_features.rs
index 923134c45..923134c45 100644
--- a/vendor/clap/src/_features.rs
+++ b/vendor/clap-3.2.20/src/_features.rs
diff --git a/vendor/clap/src/_tutorial.rs b/vendor/clap-3.2.20/src/_tutorial.rs
index 9dbfc6864..9dbfc6864 100644
--- a/vendor/clap/src/_tutorial.rs
+++ b/vendor/clap-3.2.20/src/_tutorial.rs
diff --git a/vendor/clap/src/bin/stdio-fixture.rs b/vendor/clap-3.2.20/src/bin/stdio-fixture.rs
index e3f34b41a..e3f34b41a 100644
--- a/vendor/clap/src/bin/stdio-fixture.rs
+++ b/vendor/clap-3.2.20/src/bin/stdio-fixture.rs
diff --git a/vendor/clap/src/builder/action.rs b/vendor/clap-3.2.20/src/builder/action.rs
index 71a91a8b1..71a91a8b1 100644
--- a/vendor/clap/src/builder/action.rs
+++ b/vendor/clap-3.2.20/src/builder/action.rs
diff --git a/vendor/clap/src/builder/app_settings.rs b/vendor/clap-3.2.20/src/builder/app_settings.rs
index 88bc243c4..88bc243c4 100644
--- a/vendor/clap/src/builder/app_settings.rs
+++ b/vendor/clap-3.2.20/src/builder/app_settings.rs
diff --git a/vendor/clap/src/builder/arg.rs b/vendor/clap-3.2.20/src/builder/arg.rs
index e9403d0b7..e9403d0b7 100644
--- a/vendor/clap/src/builder/arg.rs
+++ b/vendor/clap-3.2.20/src/builder/arg.rs
diff --git a/vendor/clap/src/builder/arg_group.rs b/vendor/clap-3.2.20/src/builder/arg_group.rs
index 0fe317109..0fe317109 100644
--- a/vendor/clap/src/builder/arg_group.rs
+++ b/vendor/clap-3.2.20/src/builder/arg_group.rs
diff --git a/vendor/clap/src/builder/arg_predicate.rs b/vendor/clap-3.2.20/src/builder/arg_predicate.rs
index 58eb5494c..58eb5494c 100644
--- a/vendor/clap/src/builder/arg_predicate.rs
+++ b/vendor/clap-3.2.20/src/builder/arg_predicate.rs
diff --git a/vendor/clap/src/builder/arg_settings.rs b/vendor/clap-3.2.20/src/builder/arg_settings.rs
index ecc064caa..ecc064caa 100644
--- a/vendor/clap/src/builder/arg_settings.rs
+++ b/vendor/clap-3.2.20/src/builder/arg_settings.rs
diff --git a/vendor/clap/src/builder/command.rs b/vendor/clap-3.2.20/src/builder/command.rs
index de59ad8cd..de59ad8cd 100644
--- a/vendor/clap/src/builder/command.rs
+++ b/vendor/clap-3.2.20/src/builder/command.rs
diff --git a/vendor/clap/src/builder/debug_asserts.rs b/vendor/clap-3.2.20/src/builder/debug_asserts.rs
index 864b8b479..864b8b479 100644
--- a/vendor/clap/src/builder/debug_asserts.rs
+++ b/vendor/clap-3.2.20/src/builder/debug_asserts.rs
diff --git a/vendor/clap/src/builder/macros.rs b/vendor/clap-3.2.20/src/builder/macros.rs
index 5be4d205e..5be4d205e 100644
--- a/vendor/clap/src/builder/macros.rs
+++ b/vendor/clap-3.2.20/src/builder/macros.rs
diff --git a/vendor/clap/src/builder/mod.rs b/vendor/clap-3.2.20/src/builder/mod.rs
index 4f24c74d3..4f24c74d3 100644
--- a/vendor/clap/src/builder/mod.rs
+++ b/vendor/clap-3.2.20/src/builder/mod.rs
diff --git a/vendor/clap/src/builder/possible_value.rs b/vendor/clap-3.2.20/src/builder/possible_value.rs
index 1c14217a6..1c14217a6 100644
--- a/vendor/clap/src/builder/possible_value.rs
+++ b/vendor/clap-3.2.20/src/builder/possible_value.rs
diff --git a/vendor/clap/src/builder/regex.rs b/vendor/clap-3.2.20/src/builder/regex.rs
index bf3a78e0c..bf3a78e0c 100644
--- a/vendor/clap/src/builder/regex.rs
+++ b/vendor/clap-3.2.20/src/builder/regex.rs
diff --git a/vendor/clap/src/builder/tests.rs b/vendor/clap-3.2.20/src/builder/tests.rs
index 76c8b8785..76c8b8785 100644
--- a/vendor/clap/src/builder/tests.rs
+++ b/vendor/clap-3.2.20/src/builder/tests.rs
diff --git a/vendor/clap/src/builder/usage_parser.rs b/vendor/clap-3.2.20/src/builder/usage_parser.rs
index 85d0d304e..85d0d304e 100644
--- a/vendor/clap/src/builder/usage_parser.rs
+++ b/vendor/clap-3.2.20/src/builder/usage_parser.rs
diff --git a/vendor/clap/src/builder/value_hint.rs b/vendor/clap-3.2.20/src/builder/value_hint.rs
index 7c35d1eb3..7c35d1eb3 100644
--- a/vendor/clap/src/builder/value_hint.rs
+++ b/vendor/clap-3.2.20/src/builder/value_hint.rs
diff --git a/vendor/clap/src/builder/value_parser.rs b/vendor/clap-3.2.20/src/builder/value_parser.rs
index 0492f2782..0492f2782 100644
--- a/vendor/clap/src/builder/value_parser.rs
+++ b/vendor/clap-3.2.20/src/builder/value_parser.rs
diff --git a/vendor/clap/src/derive.rs b/vendor/clap-3.2.20/src/derive.rs
index b6ac04df6..b6ac04df6 100644
--- a/vendor/clap/src/derive.rs
+++ b/vendor/clap-3.2.20/src/derive.rs
diff --git a/vendor/clap/src/error/context.rs b/vendor/clap-3.2.20/src/error/context.rs
index 985cd4d70..985cd4d70 100644
--- a/vendor/clap/src/error/context.rs
+++ b/vendor/clap-3.2.20/src/error/context.rs
diff --git a/vendor/clap/src/error/kind.rs b/vendor/clap-3.2.20/src/error/kind.rs
index 4c3dc48b0..4c3dc48b0 100644
--- a/vendor/clap/src/error/kind.rs
+++ b/vendor/clap-3.2.20/src/error/kind.rs
diff --git a/vendor/clap/src/error/mod.rs b/vendor/clap-3.2.20/src/error/mod.rs
index fbd2b30a8..fbd2b30a8 100644
--- a/vendor/clap/src/error/mod.rs
+++ b/vendor/clap-3.2.20/src/error/mod.rs
diff --git a/vendor/clap/src/lib.rs b/vendor/clap-3.2.20/src/lib.rs
index 5cefe6ec1..5cefe6ec1 100644
--- a/vendor/clap/src/lib.rs
+++ b/vendor/clap-3.2.20/src/lib.rs
diff --git a/vendor/clap/src/macros.rs b/vendor/clap-3.2.20/src/macros.rs
index 1f9167408..1f9167408 100644
--- a/vendor/clap/src/macros.rs
+++ b/vendor/clap-3.2.20/src/macros.rs
diff --git a/vendor/clap/src/mkeymap.rs b/vendor/clap-3.2.20/src/mkeymap.rs
index 97ecdda77..97ecdda77 100644
--- a/vendor/clap/src/mkeymap.rs
+++ b/vendor/clap-3.2.20/src/mkeymap.rs
diff --git a/vendor/clap/src/output/fmt.rs b/vendor/clap-3.2.20/src/output/fmt.rs
index dc1f46e08..dc1f46e08 100644
--- a/vendor/clap/src/output/fmt.rs
+++ b/vendor/clap-3.2.20/src/output/fmt.rs
diff --git a/vendor/clap/src/output/help.rs b/vendor/clap-3.2.20/src/output/help.rs
index eb53bfa54..eb53bfa54 100644
--- a/vendor/clap/src/output/help.rs
+++ b/vendor/clap-3.2.20/src/output/help.rs
diff --git a/vendor/clap/src/output/mod.rs b/vendor/clap-3.2.20/src/output/mod.rs
index e32aac26a..e32aac26a 100644
--- a/vendor/clap/src/output/mod.rs
+++ b/vendor/clap-3.2.20/src/output/mod.rs
diff --git a/vendor/clap/src/output/usage.rs b/vendor/clap-3.2.20/src/output/usage.rs
index 6f7a2cad4..6f7a2cad4 100644
--- a/vendor/clap/src/output/usage.rs
+++ b/vendor/clap-3.2.20/src/output/usage.rs
diff --git a/vendor/clap/src/parser/arg_matcher.rs b/vendor/clap-3.2.20/src/parser/arg_matcher.rs
index 22087e722..22087e722 100644
--- a/vendor/clap/src/parser/arg_matcher.rs
+++ b/vendor/clap-3.2.20/src/parser/arg_matcher.rs
diff --git a/vendor/clap/src/parser/error.rs b/vendor/clap-3.2.20/src/parser/error.rs
index caeba4b8f..caeba4b8f 100644
--- a/vendor/clap/src/parser/error.rs
+++ b/vendor/clap-3.2.20/src/parser/error.rs
diff --git a/vendor/clap/src/parser/features/mod.rs b/vendor/clap-3.2.20/src/parser/features/mod.rs
index bdeb766ec..bdeb766ec 100644
--- a/vendor/clap/src/parser/features/mod.rs
+++ b/vendor/clap-3.2.20/src/parser/features/mod.rs
diff --git a/vendor/clap/src/parser/features/suggestions.rs b/vendor/clap-3.2.20/src/parser/features/suggestions.rs
index 9e46f3c9e..9e46f3c9e 100644
--- a/vendor/clap/src/parser/features/suggestions.rs
+++ b/vendor/clap-3.2.20/src/parser/features/suggestions.rs
diff --git a/vendor/clap/src/parser/matches/any_value.rs b/vendor/clap-3.2.20/src/parser/matches/any_value.rs
index a9277e75f..a9277e75f 100644
--- a/vendor/clap/src/parser/matches/any_value.rs
+++ b/vendor/clap-3.2.20/src/parser/matches/any_value.rs
diff --git a/vendor/clap/src/parser/matches/arg_matches.rs b/vendor/clap-3.2.20/src/parser/matches/arg_matches.rs
index 2585c0219..2585c0219 100644
--- a/vendor/clap/src/parser/matches/arg_matches.rs
+++ b/vendor/clap-3.2.20/src/parser/matches/arg_matches.rs
diff --git a/vendor/clap/src/parser/matches/matched_arg.rs b/vendor/clap-3.2.20/src/parser/matches/matched_arg.rs
index fde6d37f3..fde6d37f3 100644
--- a/vendor/clap/src/parser/matches/matched_arg.rs
+++ b/vendor/clap-3.2.20/src/parser/matches/matched_arg.rs
diff --git a/vendor/clap/src/parser/matches/mod.rs b/vendor/clap-3.2.20/src/parser/matches/mod.rs
index 7b88eeca7..7b88eeca7 100644
--- a/vendor/clap/src/parser/matches/mod.rs
+++ b/vendor/clap-3.2.20/src/parser/matches/mod.rs
diff --git a/vendor/clap/src/parser/matches/value_source.rs b/vendor/clap-3.2.20/src/parser/matches/value_source.rs
index fb762d2af..fb762d2af 100644
--- a/vendor/clap/src/parser/matches/value_source.rs
+++ b/vendor/clap-3.2.20/src/parser/matches/value_source.rs
diff --git a/vendor/clap/src/parser/mod.rs b/vendor/clap-3.2.20/src/parser/mod.rs
index da81648e1..da81648e1 100644
--- a/vendor/clap/src/parser/mod.rs
+++ b/vendor/clap-3.2.20/src/parser/mod.rs
diff --git a/vendor/clap/src/parser/parser.rs b/vendor/clap-3.2.20/src/parser/parser.rs
index ad2bc6e9c..ad2bc6e9c 100644
--- a/vendor/clap/src/parser/parser.rs
+++ b/vendor/clap-3.2.20/src/parser/parser.rs
diff --git a/vendor/clap/src/parser/validator.rs b/vendor/clap-3.2.20/src/parser/validator.rs
index ebf2b234d..ebf2b234d 100644
--- a/vendor/clap/src/parser/validator.rs
+++ b/vendor/clap-3.2.20/src/parser/validator.rs
diff --git a/vendor/clap/src/util/color.rs b/vendor/clap-3.2.20/src/util/color.rs
index 15c9901a0..15c9901a0 100644
--- a/vendor/clap/src/util/color.rs
+++ b/vendor/clap-3.2.20/src/util/color.rs
diff --git a/vendor/clap/src/util/fnv.rs b/vendor/clap-3.2.20/src/util/fnv.rs
index 4602300a4..4602300a4 100644
--- a/vendor/clap/src/util/fnv.rs
+++ b/vendor/clap-3.2.20/src/util/fnv.rs
diff --git a/vendor/clap/src/util/graph.rs b/vendor/clap-3.2.20/src/util/graph.rs
index d646400b0..d646400b0 100644
--- a/vendor/clap/src/util/graph.rs
+++ b/vendor/clap-3.2.20/src/util/graph.rs
diff --git a/vendor/clap/src/util/id.rs b/vendor/clap-3.2.20/src/util/id.rs
index 63a7e003e..63a7e003e 100644
--- a/vendor/clap/src/util/id.rs
+++ b/vendor/clap-3.2.20/src/util/id.rs
diff --git a/vendor/clap/src/util/mod.rs b/vendor/clap-3.2.20/src/util/mod.rs
index 8adc8db17..8adc8db17 100644
--- a/vendor/clap/src/util/mod.rs
+++ b/vendor/clap-3.2.20/src/util/mod.rs
diff --git a/vendor/clap/src/util/str_to_bool.rs b/vendor/clap-3.2.20/src/util/str_to_bool.rs
index 1fbdc7531..1fbdc7531 100644
--- a/vendor/clap/src/util/str_to_bool.rs
+++ b/vendor/clap-3.2.20/src/util/str_to_bool.rs
diff --git a/vendor/clap_lex/.cargo-checksum.json b/vendor/clap_lex-0.2.2/.cargo-checksum.json
index d1fc5c2fe..d1fc5c2fe 100644
--- a/vendor/clap_lex/.cargo-checksum.json
+++ b/vendor/clap_lex-0.2.2/.cargo-checksum.json
diff --git a/vendor/clap_lex/Cargo.toml b/vendor/clap_lex-0.2.2/Cargo.toml
index b089dcde8..b089dcde8 100644
--- a/vendor/clap_lex/Cargo.toml
+++ b/vendor/clap_lex-0.2.2/Cargo.toml
diff --git a/vendor/clap_lex/LICENSE-APACHE b/vendor/clap_lex-0.2.2/LICENSE-APACHE
index 261eeb9e9..261eeb9e9 100644
--- a/vendor/clap_lex/LICENSE-APACHE
+++ b/vendor/clap_lex-0.2.2/LICENSE-APACHE
diff --git a/vendor/clap_lex/LICENSE-MIT b/vendor/clap_lex-0.2.2/LICENSE-MIT
index 5acedf041..5acedf041 100644
--- a/vendor/clap_lex/LICENSE-MIT
+++ b/vendor/clap_lex-0.2.2/LICENSE-MIT
diff --git a/vendor/clap_lex/README.md b/vendor/clap_lex-0.2.2/README.md
index 0c21bc819..0c21bc819 100644
--- a/vendor/clap_lex/README.md
+++ b/vendor/clap_lex-0.2.2/README.md
diff --git a/vendor/clap_lex/src/lib.rs b/vendor/clap_lex-0.2.2/src/lib.rs
index f205c3de0..f205c3de0 100644
--- a/vendor/clap_lex/src/lib.rs
+++ b/vendor/clap_lex-0.2.2/src/lib.rs
diff --git a/vendor/compiler_builtins/.cargo-checksum.json b/vendor/compiler_builtins/.cargo-checksum.json
index 3310b9b76..90052bb9e 100644
--- a/vendor/compiler_builtins/.cargo-checksum.json
+++ b/vendor/compiler_builtins/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"b0b1672fdd0af3eb8158670383772f3ce12d656d1481ec46657da2e9b26b19dd","Cargo.toml":"a49915bc5e86d21f27cfecb8465fe38a8e9cef628cca9619bfd2332cba170ac7","README.md":"5eb36fbab30693dbbe9f0de54749c95bd06fd6e42013b5b9eff3c062b9fdd34f","build.rs":"0c006642fbbe9fa5372a88cbbbb0bb4b391f635b2bde0c497de10740c1458c5e","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":"d88e01c2c2d11333dd49b61166caa036ff5f08f3a8c5973b9e3c9574bf2eb675","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":"9de65aedb36910356bc47d25b1468b40ab63faf7e319e599e478a239681bdf9c","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/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":"cb9a830e0d440ed825aa897f268e4ae067204da4ffc162ba963977a4b309007f","src/float/div.rs":"bc808a5372d041b96aa603ac814165e1e7dbd690e4ab9b026d9465c1cbc2c583","src/float/extend.rs":"180b2e791c58e0526de0a798845c580ce3222c8a15c8665e6e6a4bf5cf1a34aa","src/float/mod.rs":"48d76632575789a6ecf99213b1ed38c21c86ad5a5c3fa33ccb31f77829271b79","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":"c32a7c416f2c81d6368720053864c3e7082417bca983c329520a8e7dc8c34736","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":"d0e85291d12a57c61791257e3adefb8f2222e1ba6f9e5cd4cf7fba59d26477f4","src/macros.rs":"a3261b40b1db041fb779b32bfc2bf3cba7a7c85f10fd02997163b3396658a3d7","src/math.rs":"ac6063d7c8927e3b8fe6e41acf83261db2a57e02f7c5a30bc52dbb03c0df9c72","src/mem/impls.rs":"a8d1c28a77d9b334872abbebfcba3fd1802175bef53c0b545e85242860698780","src/mem/mod.rs":"5034543d963149c14a6823bee32a1fb9dfd950c32153d37f97e9df1dc6c23129","src/mem/x86_64.rs":"9f740891f666acf384159128eef233d9e15c6120da8016370c6f9f05cc29d653","src/probestack.rs":"ef5c07e9b95de7b2b77a937789fcfefd9846274317489ad6d623e377c9888601","src/riscv.rs":"8aa8cde1106a179e9a37724193bc5cea5defe212eb38e3049c23b254578f78d4","src/x86.rs":"117b50d6725ee0af0a7b3d197ea580655561f66a870ebc450d96af22bf7f39f6","src/x86_64.rs":"4f16bc9fad7757d48a6da3a078c715dd3a22154aadb4f1998d4c1b5d91396f9e"},"package":"4f873ce2bd3550b0b565f878b3d04ea8253f4259dc3d20223af2e1ba86f5ecca"} \ No newline at end of file
+{"files":{"Cargo.lock":"d76ea6435a58ea3155de70652b8c03e08e0c96645dcf7e2f8f3650c06cb699e2","Cargo.toml":"97342c77c2e481ff977fafc2a84d7c729f26e08dee2cf1d00b6be8ddad303797","LICENSE.txt":"0e13fed90654e0bc677d624a2d770833a09541fe0c0bdb3d051b3d081207393a","README.md":"5eb36fbab30693dbbe9f0de54749c95bd06fd6e42013b5b9eff3c062b9fdd34f","build.rs":"0c006642fbbe9fa5372a88cbbbb0bb4b391f635b2bde0c497de10740c1458c5e","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":"d88e01c2c2d11333dd49b61166caa036ff5f08f3a8c5973b9e3c9574bf2eb675","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":"9de65aedb36910356bc47d25b1468b40ab63faf7e319e599e478a239681bdf9c","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/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":"48d76632575789a6ecf99213b1ed38c21c86ad5a5c3fa33ccb31f77829271b79","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":"d0e85291d12a57c61791257e3adefb8f2222e1ba6f9e5cd4cf7fba59d26477f4","src/macros.rs":"de690dffc59a5884ed06c67d38f06c41ed02fcd6318189397a0d4aafbd375ad8","src/math.rs":"7cafdf3d65e083b31a9ceebab9510236b2c7290dbf1927f435d0f9b2d62d2a0b","src/mem/impls.rs":"a8d1c28a77d9b334872abbebfcba3fd1802175bef53c0b545e85242860698780","src/mem/mod.rs":"5034543d963149c14a6823bee32a1fb9dfd950c32153d37f97e9df1dc6c23129","src/mem/x86_64.rs":"9f740891f666acf384159128eef233d9e15c6120da8016370c6f9f05cc29d653","src/probestack.rs":"ef5c07e9b95de7b2b77a937789fcfefd9846274317489ad6d623e377c9888601","src/riscv.rs":"8aa8cde1106a179e9a37724193bc5cea5defe212eb38e3049c23b254578f78d4","src/x86.rs":"117b50d6725ee0af0a7b3d197ea580655561f66a870ebc450d96af22bf7f39f6","src/x86_64.rs":"4f16bc9fad7757d48a6da3a078c715dd3a22154aadb4f1998d4c1b5d91396f9e"},"package":"18cd7635fea7bb481ea543b392789844c1ad581299da70184c7175ce3af76603"} \ No newline at end of file
diff --git a/vendor/compiler_builtins/Cargo.lock b/vendor/compiler_builtins/Cargo.lock
index e60762217..a498ea0ea 100644
--- a/vendor/compiler_builtins/Cargo.lock
+++ b/vendor/compiler_builtins/Cargo.lock
@@ -10,7 +10,7 @@ checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "compiler_builtins"
-version = "0.1.79"
+version = "0.1.82"
dependencies = [
"cc",
"rustc-std-workspace-core",
diff --git a/vendor/compiler_builtins/Cargo.toml b/vendor/compiler_builtins/Cargo.toml
index eedf9a7b2..13ec182df 100644
--- a/vendor/compiler_builtins/Cargo.toml
+++ b/vendor/compiler_builtins/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "compiler_builtins"
-version = "0.1.79"
+version = "0.1.82"
authors = ["Jorge Aparicio <japaricious@gmail.com>"]
links = "compiler-rt"
include = [
@@ -33,7 +33,6 @@ documentation = "https://docs.rs/compiler_builtins"
readme = "README.md"
license = "MIT/Apache-2.0"
repository = "https://github.com/rust-lang/compiler-builtins"
-resolver = "1"
[profile.dev]
panic = "abort"
diff --git a/vendor/compiler_builtins/LICENSE.txt b/vendor/compiler_builtins/LICENSE.txt
new file mode 100644
index 000000000..92bbe113a
--- /dev/null
+++ b/vendor/compiler_builtins/LICENSE.txt
@@ -0,0 +1,91 @@
+==============================================================================
+compiler-builtins License
+==============================================================================
+
+The compiler-builtins crate is dual licensed under both the University of
+Illinois "BSD-Like" license and the MIT license. As a user of this code you may
+choose to use it under either license. As a contributor, you agree to allow
+your code to be used under both.
+
+Full text of the relevant licenses is included below.
+
+==============================================================================
+
+University of Illinois/NCSA
+Open Source License
+
+Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT
+
+All rights reserved.
+
+Developed by:
+
+ LLVM Team
+
+ University of Illinois at Urbana-Champaign
+
+ http://llvm.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal with
+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:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimers.
+
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimers in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the names of the LLVM Team, University of Illinois at
+ Urbana-Champaign, nor the names of its contributors may be used to
+ endorse or promote products derived from this Software without specific
+ prior written permission.
+
+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
+CONTRIBUTORS 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 WITH THE
+SOFTWARE.
+
+==============================================================================
+
+Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT
+
+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.
+
+==============================================================================
+Copyrights and Licenses for Third Party Software Distributed with LLVM:
+==============================================================================
+The LLVM software contains code written by third parties. Such software will
+have its own individual LICENSE.TXT file in the directory in which it appears.
+This file will describe the copyrights, license, and restrictions which apply
+to that code.
+
+The disclaimer of warranty in the University of Illinois Open Source License
+applies to all code in the LLVM Distribution, and nothing in any of the
+other licenses gives permission to use the names of the LLVM Team or the
+University of Illinois to endorse or promote products derived from this
+Software.
+
diff --git a/vendor/compiler_builtins/src/float/conv.rs b/vendor/compiler_builtins/src/float/conv.rs
index 68ba63408..19fdc2fdc 100644
--- a/vendor/compiler_builtins/src/float/conv.rs
+++ b/vendor/compiler_builtins/src/float/conv.rs
@@ -13,7 +13,7 @@ mod int_to_float {
let a = (i << n) >> 8; // Significant bits, with bit 24 still in tact.
let b = (i << n) << 24; // Insignificant bits, only relevant for rounding.
let m = a + ((b - (b >> 31 & !a)) >> 31); // Add one when we need to round up. Break ties to even.
- let e = 157 - n as u32; // Exponent plus 127, minus one.
+ let e = 157 - n; // Exponent plus 127, minus one.
(e << 23) + m // + not |, so the mantissa can overflow into the exponent.
}
@@ -42,8 +42,8 @@ mod int_to_float {
return 0;
}
let n = i.leading_zeros();
- let a = ((i << n) >> 11) as u64; // Significant bits, with bit 53 still in tact.
- let b = ((i << n) << 53) as u64; // Insignificant bits, only relevant for rounding.
+ let a = (i << n) >> 11; // Significant bits, with bit 53 still in tact.
+ let b = (i << n) << 53; // Insignificant bits, only relevant for rounding.
let m = a + ((b - (b >> 63 & !a)) >> 63); // Add one when we need to round up. Break ties to even.
let e = 1085 - n as u64; // Exponent plus 1023, minus one.
(e << 52) + m // + not |, so the mantissa can overflow into the exponent.
diff --git a/vendor/compiler_builtins/src/float/div.rs b/vendor/compiler_builtins/src/float/div.rs
index 528a8368d..c2d6c07e7 100644
--- a/vendor/compiler_builtins/src/float/div.rs
+++ b/vendor/compiler_builtins/src/float/div.rs
@@ -135,11 +135,11 @@ where
let mut correction: u32 =
negate_u32(((reciprocal as u64).wrapping_mul(q31b as u64) >> 32) as u32);
- reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) as u64 >> 31) as u32;
+ reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) >> 31) as u32;
correction = negate_u32(((reciprocal as u64).wrapping_mul(q31b as u64) >> 32) as u32);
- reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) as u64 >> 31) as u32;
+ reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) >> 31) as u32;
correction = negate_u32(((reciprocal as u64).wrapping_mul(q31b as u64) >> 32) as u32);
- reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) as u64 >> 31) as u32;
+ reciprocal = ((reciprocal as u64).wrapping_mul(correction as u64) >> 31) as u32;
// Exhaustive testing shows that the error in reciprocal after three steps
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
diff --git a/vendor/compiler_builtins/src/int/specialized_div_rem/mod.rs b/vendor/compiler_builtins/src/int/specialized_div_rem/mod.rs
index 6ec4675df..77034eb54 100644
--- a/vendor/compiler_builtins/src/int/specialized_div_rem/mod.rs
+++ b/vendor/compiler_builtins/src/int/specialized_div_rem/mod.rs
@@ -72,7 +72,10 @@ mod asymmetric;
/// impossible to reach by Rust users, unless `compiler-builtins` public division functions or
/// `core/std::unchecked_div/rem` are directly used without a zero check in front.
fn zero_div_fn() -> ! {
- unsafe { core::hint::unreachable_unchecked() }
+ // Calling the intrinsic directly, to avoid the `assert_unsafe_precondition` that cannot be used
+ // here because it involves non-`inline` functions
+ // (https://github.com/rust-lang/compiler-builtins/issues/491).
+ unsafe { core::intrinsics::unreachable() }
}
const USE_LZ: bool = {
diff --git a/vendor/compiler_builtins/src/macros.rs b/vendor/compiler_builtins/src/macros.rs
index 7d90b7aad..477c25684 100644
--- a/vendor/compiler_builtins/src/macros.rs
+++ b/vendor/compiler_builtins/src/macros.rs
@@ -266,6 +266,7 @@ macro_rules! intrinsics {
#[cfg(target_arch = "arm")]
pub mod $alias {
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
+ #[cfg_attr(all(not(windows), not(target_vendor="apple")), linkage = "weak")]
pub extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
super::$name($($argname),*)
}
diff --git a/vendor/compiler_builtins/src/math.rs b/vendor/compiler_builtins/src/math.rs
index fa9836186..3fc33b127 100644
--- a/vendor/compiler_builtins/src/math.rs
+++ b/vendor/compiler_builtins/src/math.rs
@@ -118,8 +118,11 @@ no_mangle! {
fn truncf(x: f32) -> f32;
}
-// only for the thumb*-none-eabi* targets
-#[cfg(all(target_arch = "arm", target_os = "none"))]
+// only for the thumb*-none-eabi* targets and riscv32*-none-elf targets that lack the floating point instruction set
+#[cfg(any(
+ all(target_arch = "arm", target_os = "none"),
+ all(target_arch = "riscv32", not(target_feature = "f"), target_os = "none")
+))]
no_mangle! {
fn fmin(x: f64, y: f64) -> f64;
fn fminf(x: f32, y: f32) -> f32;
diff --git a/vendor/compiletest_rs/.cargo-checksum.json b/vendor/compiletest_rs/.cargo-checksum.json
index 8533fd089..c7ba6752d 100644
--- a/vendor/compiletest_rs/.cargo-checksum.json
+++ b/vendor/compiletest_rs/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"e66bd0207f0ea860188e04376705d67a4658e78295bcaf579b2a89dbd9088d54","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"e0655e85239c6e887c0f35e1b97fb2574127ea61c28e3deec93c20b560f47892","build.rs":"905784fbb4a75c17279a88fd476e7221104adf00b4dd745a4a66bd41cac8d77a","src/common.rs":"df14f9c75c6a341c5bbc90c4b386c20f66164196f3b4b2ffc19b454d6b658e2b","src/errors.rs":"88a36d1726d90b11bf9272b1439dd52cd4fdf2e70e6e0cb6cfb323f76d84e3ff","src/header.rs":"04e405d100c46dd82139705e8b833e03d19c597edf3a5f7fee92ad9cbd12c201","src/json.rs":"e278c4c3c32c60e840a250b0979926e2ac333dcbbbaae5ab6fcf01ca05bef625","src/lib.rs":"ac780a6ad8d9eb84bd0c6bd7c56fab64a98ef29b9133f1b4fb2a845b58c839bc","src/raise_fd_limit.rs":"b0840fe16df9edaae0571499e105db47768050fcd62729d1e56295f2db34318e","src/read2.rs":"fb9caa84bec8c9c3d2c1ee39a4a6698c461fdc77aec086c74fd7738a6acf4155","src/runtest.rs":"9dc12384637275790ca5a030f79e7ea72be991ff8d5365193e48895a30db6454","src/uidiff.rs":"2f612bd4ed76d68c0f6b3eb8dda5adf14a3e6ceef261c88c810ac6b6857e2d34","src/util.rs":"9cda9e803ffe5e1b5d4c74cf7da7bd51e28a8d1b09bda3d31e01c0f648c3262d","tests/bless.rs":"29031f02666102ab8cde316b9206bf1e770275f9fa6e0172754dcad859a52b5b","tests/test_support/mod.rs":"21ec96cca07cf95b6e3333917a5158a6c47356940063f77d52503b97fd3d8b79"},"package":"262134ef87408da1ddfe45e33daa0ca43b75286d6b1076446e602d264cf9847e"} \ No newline at end of file
+{"files":{"Cargo.toml":"cc0342b513ff3ec9dd349398d0a851131ce10afa5b7748997fe7b66f4c75ad32","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"043fc0e7bbad6798c80b81640db2f45cea97b2cadadf8d21e08fe89119872e07","build.rs":"905784fbb4a75c17279a88fd476e7221104adf00b4dd745a4a66bd41cac8d77a","src/common.rs":"df14f9c75c6a341c5bbc90c4b386c20f66164196f3b4b2ffc19b454d6b658e2b","src/errors.rs":"88a36d1726d90b11bf9272b1439dd52cd4fdf2e70e6e0cb6cfb323f76d84e3ff","src/header.rs":"04e405d100c46dd82139705e8b833e03d19c597edf3a5f7fee92ad9cbd12c201","src/json.rs":"e278c4c3c32c60e840a250b0979926e2ac333dcbbbaae5ab6fcf01ca05bef625","src/lib.rs":"ac780a6ad8d9eb84bd0c6bd7c56fab64a98ef29b9133f1b4fb2a845b58c839bc","src/raise_fd_limit.rs":"b0840fe16df9edaae0571499e105db47768050fcd62729d1e56295f2db34318e","src/read2.rs":"fb9caa84bec8c9c3d2c1ee39a4a6698c461fdc77aec086c74fd7738a6acf4155","src/runtest.rs":"4d0d761d8f848ceda532ecc1363d5280951656c5a9ea7eff75d91475e7fcf269","src/uidiff.rs":"2f612bd4ed76d68c0f6b3eb8dda5adf14a3e6ceef261c88c810ac6b6857e2d34","src/util.rs":"9cda9e803ffe5e1b5d4c74cf7da7bd51e28a8d1b09bda3d31e01c0f648c3262d","tests/bless.rs":"29031f02666102ab8cde316b9206bf1e770275f9fa6e0172754dcad859a52b5b","tests/test_support/mod.rs":"21ec96cca07cf95b6e3333917a5158a6c47356940063f77d52503b97fd3d8b79"},"package":"70489bbb718aea4f92e5f48f2e3b5be670c2051de30e57cb6e5377b4aa08b372"} \ No newline at end of file
diff --git a/vendor/compiletest_rs/Cargo.toml b/vendor/compiletest_rs/Cargo.toml
index 9403548b8..f56e4d712 100644
--- a/vendor/compiletest_rs/Cargo.toml
+++ b/vendor/compiletest_rs/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "compiletest_rs"
-version = "0.8.0"
+version = "0.9.0"
authors = [
"The Rust Project Developers",
"Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>",
diff --git a/vendor/compiletest_rs/README.md b/vendor/compiletest_rs/README.md
index bf7cac194..c01a40c9b 100644
--- a/vendor/compiletest_rs/README.md
+++ b/vendor/compiletest_rs/README.md
@@ -14,7 +14,7 @@ To use `compiletest-rs` in your application, add the following to `Cargo.toml`
```toml
[dev-dependencies]
-compiletest_rs = "0.7"
+compiletest_rs = "0.9"
```
By default, `compiletest-rs` should be able to run on both stable, beta and
@@ -28,7 +28,7 @@ crate.
```toml
[dev-dependencies]
-compiletest_rs = { version = "0.7", features = [ "rustc" ] }
+compiletest_rs = { version = "0.9", features = [ "rustc" ] }
```
Create a `tests` folder in the root folder of your project. Create a test file
diff --git a/vendor/compiletest_rs/src/runtest.rs b/vendor/compiletest_rs/src/runtest.rs
index c52551488..47f9c4870 100644
--- a/vendor/compiletest_rs/src/runtest.rs
+++ b/vendor/compiletest_rs/src/runtest.rs
@@ -33,9 +33,28 @@ use std::io::{self, BufReader};
use std::path::{Path, PathBuf};
use std::process::{Command, Output, ExitStatus, Stdio, Child};
use std::str;
+use std::sync::{Arc, Mutex, RwLock};
use extract_gdb_version;
+fn get_or_create_coverage_file(path: &Path, create: impl FnOnce() -> File) -> Arc<Mutex<File>> {
+ lazy_static::lazy_static! {
+ static ref COVERAGE_FILE_LOCKS: RwLock<HashMap<PathBuf, Arc<Mutex<File>>>> = RwLock::new(HashMap::new());
+ }
+
+ {
+ let locks = COVERAGE_FILE_LOCKS.read().unwrap();
+ locks.get(path).map(Arc::clone)
+ }
+ .unwrap_or_else(|| {
+ let mut locks = COVERAGE_FILE_LOCKS.write().unwrap();
+ locks
+ .entry(path.to_path_buf())
+ .or_insert_with(|| Arc::new(Mutex::new(create())))
+ .clone()
+ })
+}
+
/// The name of the environment variable that holds dynamic library locations.
pub fn dylib_env_var() -> &'static str {
if cfg!(windows) {
@@ -2343,16 +2362,23 @@ actual:\n\
coverage_file_path.push("rustfix_missing_coverage.txt");
debug!("coverage_file_path: {}", coverage_file_path.display());
- let mut file = OpenOptions::new()
- .create(true)
- .append(true)
- .open(coverage_file_path.as_path())
- .expect("could not create or open file");
-
- if let Err(_) = writeln!(file, "{}", self.testpaths.file.display()) {
+ let file_ref = get_or_create_coverage_file(&coverage_file_path, || {
+ OpenOptions::new()
+ .create(true)
+ .write(true)
+ .truncate(true)
+ .open(coverage_file_path.as_path())
+ .expect("could not create or open file")
+ });
+ let mut file = file_ref.lock().unwrap();
+
+ if writeln!(file, "{}", self.testpaths.file.display())
+ .and_then(|_| file.sync_data())
+ .is_err()
+ {
panic!("couldn't write to {}", coverage_file_path.display());
}
- }
+ }
}
if self.props.run_rustfix {
@@ -2408,10 +2434,13 @@ actual:\n\
// And finally, compile the fixed code and make sure it both
// succeeds and has no diagnostics.
let mut rustc = self.make_compile_args(
- &self.testpaths.file.with_extension(UI_FIXED),
+ &expected_fixed_path,
TargetLocation::ThisFile(self.make_exe_name()),
AllowUnused::No,
);
+ // Set the crate name to avoid `file.revision.fixed` inferring the
+ // invalid name `file.revision`
+ rustc.arg("--crate-name=fixed");
rustc.arg("-L").arg(&self.aux_output_dir_name());
let res = self.compose_and_run_compiler(rustc, None);
if !res.status.success() {
diff --git a/vendor/crossbeam-epoch/.cargo-checksum.json b/vendor/crossbeam-epoch/.cargo-checksum.json
index 21e5f8500..d069e3a4b 100644
--- a/vendor/crossbeam-epoch/.cargo-checksum.json
+++ b/vendor/crossbeam-epoch/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"4a701ed7814fbde912aa7a1d15c95ed6b7ba3cd661c64f92c17b3b8bf67ecf5e","Cargo.lock":"018d954edeff6a45c6af01735239b639a83eed8258176481c6e9dae366085760","Cargo.toml":"4c1451a736e2ec0b31dfe6080140b69fdc614a0606db876308f1badf932dc1b9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"d67d0cf57751a019707dd95785345ee181a10ea80237789bc3c19bf28c0d45ca","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","build.rs":"89e236e4e22dd748720129dcd02edfc08adccf708a7f0b03e41780e5bafb39cc","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","no_atomic.rs":"916ed15218bb7b75a4e0d432430e7134efd27ca43ca8a8766e0c90e89febb602","src/atomic.rs":"1bd4275c1411852024533e8a70959dfedf72029e3253544d1fbb0cc18b6fd519","src/collector.rs":"29e5911f61510247659b0090517bd1a38d11e1ed86e35811603cb599962d9a58","src/default.rs":"9c4d3951981d47efc748674d64b22eff27ecb2e3ef16369aa423592740ce6033","src/deferred.rs":"0c87df5797212778edd3c2d5fcf0cc04e8b9ed100261ecf9522f74a90804a3d5","src/epoch.rs":"d31e66d8fe62299928e25867336d96391b26a4fe890a1cae0885dfcf36d6835b","src/guard.rs":"f4439909152d38c03b6dfb6eeba6c9f07c39962187d461c92a492c27c258670b","src/internal.rs":"ac40ce276f0ed3dfd561926b78f775592eabb90790e177edde41fe50c13b8256","src/lib.rs":"1c0765413dd66d4655e6417a69829ac5c2f4d504f66f77a87fe9c230c05e039d","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"cbc6334460d73761c3dea7f99ed2ccbf267d5da3bc76c812e94f85c9f4565c6a","src/sync/queue.rs":"06173b2255677d0d39178ceb49876fda2878f491e907c595eb65643dbb43c9ba","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"930bdf6d05b1fae72bb844f6c26e0a35cc83b810a987baaf5d279044d3b3f74d","Cargo.lock":"ce25f4d162a39d180e7369954bc512ab2ab1ab3b04f6f071cb2212bd43b3bbc3","Cargo.toml":"f2a34cbd48fff1346070f503da83c9149db91c7a098a0b486007fd6a39ba6a1b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"d67d0cf57751a019707dd95785345ee181a10ea80237789bc3c19bf28c0d45ca","benches/defer.rs":"c330b704d96b2ad1aed29f72c37a99da534adef8cb06a3976d5f93bf567abb20","benches/flush.rs":"0389ac6c473632f0e93c962f223404cc360257f6699b4ec90b9b3be16bb6d74f","benches/pin.rs":"2f649a5153745c7930efdb32a52f9dc522f7b8cf548a251c5e2c82ee25dc3fff","build.rs":"89e236e4e22dd748720129dcd02edfc08adccf708a7f0b03e41780e5bafb39cc","examples/sanitize.rs":"a39d1635fa61e643e59192d7a63becc97ff81f03c1f4e03d38cedefb1525026a","no_atomic.rs":"f58085b9d0666ccf62e0ae17fb5dae937c0a86fcc55dc0ae04ad8659e696a49c","src/atomic.rs":"1bd4275c1411852024533e8a70959dfedf72029e3253544d1fbb0cc18b6fd519","src/collector.rs":"29e5911f61510247659b0090517bd1a38d11e1ed86e35811603cb599962d9a58","src/default.rs":"62edf5e1f934eb82d8d7f010d6f25366e6851145a6f0a162372202bb63da1f3a","src/deferred.rs":"0c87df5797212778edd3c2d5fcf0cc04e8b9ed100261ecf9522f74a90804a3d5","src/epoch.rs":"d31e66d8fe62299928e25867336d96391b26a4fe890a1cae0885dfcf36d6835b","src/guard.rs":"f4439909152d38c03b6dfb6eeba6c9f07c39962187d461c92a492c27c258670b","src/internal.rs":"ac40ce276f0ed3dfd561926b78f775592eabb90790e177edde41fe50c13b8256","src/lib.rs":"a036d73230d0574011e67be11d275fe46439a1b5fc3295cb242d9179e5e0a220","src/sync/list.rs":"10aa4c59845ab9ff1d8bcb6f594b70bbe23c320fa7a2b125fdf85df88b9d61e2","src/sync/mod.rs":"326e32489d467e974c441120640a8338aa55da55c24b20276075ce9053997326","src/sync/once_lock.rs":"c03dc9c05a817e087dccf8b682f7307501542805533551da3c2bab442bc40743","src/sync/queue.rs":"06173b2255677d0d39178ceb49876fda2878f491e907c595eb65643dbb43c9ba","tests/loom.rs":"db772f4478966de6ec98774ca4093171dc942da635822a0d2d3257d31188cb9b"},"package":"f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348"} \ No newline at end of file
diff --git a/vendor/crossbeam-epoch/CHANGELOG.md b/vendor/crossbeam-epoch/CHANGELOG.md
index b05a52dfc..3aac87b7f 100644
--- a/vendor/crossbeam-epoch/CHANGELOG.md
+++ b/vendor/crossbeam-epoch/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Version 0.9.11
+
+- Removes the dependency on the `once_cell` crate to restore the MSRV. (#913)
+- Work around [rust-lang#98302](https://github.com/rust-lang/rust/issues/98302), which causes compile error on windows-gnu when LTO is enabled. (#913)
+
# Version 0.9.10
- Bump the minimum supported Rust version to 1.38. (#877)
diff --git a/vendor/crossbeam-epoch/Cargo.lock b/vendor/crossbeam-epoch/Cargo.lock
index 726980a93..3ded5c77e 100644
--- a/vendor/crossbeam-epoch/Cargo.lock
+++ b/vendor/crossbeam-epoch/Cargo.lock
@@ -31,14 +31,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.11"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"loom",
"memoffset",
- "once_cell",
"rand",
"rustversion",
"scopeguard",
@@ -46,13 +45,12 @@ dependencies = [
[[package]]
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
dependencies = [
"cfg-if",
"loom",
- "once_cell",
]
[[package]]
@@ -87,9 +85,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.126"
+version = "0.2.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
[[package]]
name = "log"
@@ -133,9 +131,9 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.13.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "pin-project-lite"
@@ -151,18 +149,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro2"
-version = "1.0.40"
+version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
+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",
]
@@ -190,9 +188,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",
]
@@ -223,9 +221,9 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustversion"
-version = "1.0.8"
+version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24c8ad4f0c00e1eb5bc7614d236a7f1300e3dbd76b68cac8e06fb00b015ad8d8"
+checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]]
name = "scoped-tls"
@@ -256,9 +254,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "syn"
-version = "1.0.98"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
+checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
dependencies = [
"proc-macro2",
"quote",
@@ -276,9 +274,9 @@ dependencies = [
[[package]]
name = "tracing"
-version = "0.1.35"
+version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
+checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
dependencies = [
"cfg-if",
"pin-project-lite",
@@ -299,9 +297,9 @@ dependencies = [
[[package]]
name = "tracing-core"
-version = "0.1.28"
+version = "0.1.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7"
+checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
dependencies = [
"once_cell",
"valuable",
@@ -338,9 +336,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 = "valuable"
diff --git a/vendor/crossbeam-epoch/Cargo.toml b/vendor/crossbeam-epoch/Cargo.toml
index 1551c3c2c..0f8e23864 100644
--- a/vendor/crossbeam-epoch/Cargo.toml
+++ b/vendor/crossbeam-epoch/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.38"
name = "crossbeam-epoch"
-version = "0.9.10"
+version = "0.9.11"
description = "Epoch-based garbage collection"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-epoch"
readme = "README.md"
@@ -41,10 +41,6 @@ default-features = false
[dependencies.memoffset]
version = "0.6"
-[dependencies.once_cell]
-version = "1"
-optional = true
-
[dependencies.scopeguard]
version = "1.1"
default-features = false
@@ -69,7 +65,6 @@ nightly = ["crossbeam-utils/nightly"]
std = [
"alloc",
"crossbeam-utils/std",
- "once_cell",
]
[target."cfg(crossbeam_loom)".dependencies.loom-crate]
diff --git a/vendor/crossbeam-epoch/no_atomic.rs b/vendor/crossbeam-epoch/no_atomic.rs
index f740aaee1..675d9a27e 100644
--- a/vendor/crossbeam-epoch/no_atomic.rs
+++ b/vendor/crossbeam-epoch/no_atomic.rs
@@ -2,6 +2,8 @@
// It is not intended for manual editing.
const NO_ATOMIC_CAS: &[&str] = &[
+ "armv4t-none-eabi",
+ "armv5te-none-eabi",
"avr-unknown-gnu-atmega328",
"bpfeb-unknown-none",
"bpfel-unknown-none",
@@ -10,6 +12,7 @@ const NO_ATOMIC_CAS: &[&str] = &[
"riscv32im-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"thumbv4t-none-eabi",
+ "thumbv5te-none-eabi",
"thumbv6m-none-eabi",
];
@@ -18,7 +21,9 @@ const NO_ATOMIC_64: &[&str] = &[
"arm-linux-androideabi",
"armebv7r-none-eabi",
"armebv7r-none-eabihf",
+ "armv4t-none-eabi",
"armv4t-unknown-linux-gnueabi",
+ "armv5te-none-eabi",
"armv5te-unknown-linux-gnueabi",
"armv5te-unknown-linux-musleabi",
"armv5te-unknown-linux-uclibceabi",
@@ -55,6 +60,7 @@ const NO_ATOMIC_64: &[&str] = &[
"riscv32imac-unknown-xous-elf",
"riscv32imc-unknown-none-elf",
"thumbv4t-none-eabi",
+ "thumbv5te-none-eabi",
"thumbv6m-none-eabi",
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
diff --git a/vendor/crossbeam-epoch/src/default.rs b/vendor/crossbeam-epoch/src/default.rs
index c2b4852a4..b42c1c7a7 100644
--- a/vendor/crossbeam-epoch/src/default.rs
+++ b/vendor/crossbeam-epoch/src/default.rs
@@ -8,22 +8,30 @@ use crate::collector::{Collector, LocalHandle};
use crate::guard::Guard;
use crate::primitive::thread_local;
#[cfg(not(crossbeam_loom))]
-use once_cell::sync::Lazy;
+use crate::sync::once_lock::OnceLock;
-/// The global data for the default garbage collector.
-#[cfg(not(crossbeam_loom))]
-static COLLECTOR: Lazy<Collector> = Lazy::new(Collector::new);
-// FIXME: loom does not currently provide the equivalent of Lazy:
-// https://github.com/tokio-rs/loom/issues/263
-#[cfg(crossbeam_loom)]
-loom::lazy_static! {
- /// The global data for the default garbage collector.
- static ref COLLECTOR: Collector = Collector::new();
+fn collector() -> &'static Collector {
+ #[cfg(not(crossbeam_loom))]
+ {
+ /// The global data for the default garbage collector.
+ static COLLECTOR: OnceLock<Collector> = OnceLock::new();
+ COLLECTOR.get_or_init(Collector::new)
+ }
+ // FIXME: loom does not currently provide the equivalent of Lazy:
+ // https://github.com/tokio-rs/loom/issues/263
+ #[cfg(crossbeam_loom)]
+ {
+ loom::lazy_static! {
+ /// The global data for the default garbage collector.
+ static ref COLLECTOR: Collector = Collector::new();
+ }
+ &COLLECTOR
+ }
}
thread_local! {
/// The per-thread participant for the default garbage collector.
- static HANDLE: LocalHandle = COLLECTOR.register();
+ static HANDLE: LocalHandle = collector().register();
}
/// Pins the current thread.
@@ -40,7 +48,7 @@ pub fn is_pinned() -> bool {
/// Returns the default global collector.
pub fn default_collector() -> &'static Collector {
- &COLLECTOR
+ collector()
}
#[inline]
@@ -50,7 +58,7 @@ where
{
HANDLE
.try_with(|h| f(h))
- .unwrap_or_else(|_| f(&COLLECTOR.register()))
+ .unwrap_or_else(|_| f(&collector().register()))
}
#[cfg(all(test, not(crossbeam_loom)))]
diff --git a/vendor/crossbeam-epoch/src/lib.rs b/vendor/crossbeam-epoch/src/lib.rs
index 4cf982b6b..b432c1f40 100644
--- a/vendor/crossbeam-epoch/src/lib.rs
+++ b/vendor/crossbeam-epoch/src/lib.rs
@@ -107,7 +107,7 @@ mod primitive {
// https://github.com/tokio-rs/loom#handling-loom-api-differences
impl<T> UnsafeCell<T> {
#[inline]
- pub(crate) fn new(data: T) -> UnsafeCell<T> {
+ pub(crate) const fn new(data: T) -> UnsafeCell<T> {
UnsafeCell(::core::cell::UnsafeCell::new(data))
}
diff --git a/vendor/crossbeam-epoch/src/sync/mod.rs b/vendor/crossbeam-epoch/src/sync/mod.rs
index 5c06e7643..08981be25 100644
--- a/vendor/crossbeam-epoch/src/sync/mod.rs
+++ b/vendor/crossbeam-epoch/src/sync/mod.rs
@@ -1,4 +1,7 @@
//! Synchronization primitives.
pub(crate) mod list;
+#[cfg(feature = "std")]
+#[cfg(not(crossbeam_loom))]
+pub(crate) mod once_lock;
pub(crate) mod queue;
diff --git a/vendor/crossbeam-epoch/src/sync/once_lock.rs b/vendor/crossbeam-epoch/src/sync/once_lock.rs
new file mode 100644
index 000000000..c1fefc96c
--- /dev/null
+++ b/vendor/crossbeam-epoch/src/sync/once_lock.rs
@@ -0,0 +1,103 @@
+// Based on unstable std::sync::OnceLock.
+//
+// Source: https://github.com/rust-lang/rust/blob/8e9c93df464b7ada3fc7a1c8ccddd9dcb24ee0a0/library/std/src/sync/once_lock.rs
+
+use core::cell::UnsafeCell;
+use core::mem::MaybeUninit;
+use core::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Once;
+
+pub(crate) struct OnceLock<T> {
+ once: Once,
+ // Once::is_completed requires Rust 1.43, so use this to track of whether they have been initialized.
+ is_initialized: AtomicBool,
+ value: UnsafeCell<MaybeUninit<T>>,
+ // Unlike std::sync::OnceLock, we don't need PhantomData here because
+ // we don't use #[may_dangle].
+}
+
+unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
+unsafe impl<T: Send> Send for OnceLock<T> {}
+
+impl<T> OnceLock<T> {
+ /// Creates a new empty cell.
+ #[must_use]
+ pub(crate) const fn new() -> Self {
+ Self {
+ once: Once::new(),
+ is_initialized: AtomicBool::new(false),
+ value: UnsafeCell::new(MaybeUninit::uninit()),
+ }
+ }
+
+ /// Gets the contents of the cell, initializing it with `f` if the cell
+ /// was empty.
+ ///
+ /// Many threads may call `get_or_init` concurrently with different
+ /// initializing functions, but it is guaranteed that only one function
+ /// will be executed.
+ ///
+ /// # Panics
+ ///
+ /// If `f` panics, the panic is propagated to the caller, and the cell
+ /// remains uninitialized.
+ ///
+ /// It is an error to reentrantly initialize the cell from `f`. The
+ /// exact outcome is unspecified. Current implementation deadlocks, but
+ /// this may be changed to a panic in the future.
+ pub(crate) fn get_or_init<F>(&self, f: F) -> &T
+ where
+ F: FnOnce() -> T,
+ {
+ // Fast path check
+ if self.is_initialized() {
+ // SAFETY: The inner value has been initialized
+ return unsafe { self.get_unchecked() };
+ }
+ self.initialize(f);
+
+ debug_assert!(self.is_initialized());
+
+ // SAFETY: The inner value has been initialized
+ unsafe { self.get_unchecked() }
+ }
+
+ #[inline]
+ fn is_initialized(&self) -> bool {
+ self.is_initialized.load(Ordering::Acquire)
+ }
+
+ #[cold]
+ fn initialize<F>(&self, f: F)
+ where
+ F: FnOnce() -> T,
+ {
+ let slot = self.value.get().cast::<T>();
+ let is_initialized = &self.is_initialized;
+
+ self.once.call_once(|| {
+ let value = f();
+ unsafe {
+ slot.write(value);
+ }
+ is_initialized.store(true, Ordering::Release);
+ });
+ }
+
+ /// # Safety
+ ///
+ /// The value must be initialized
+ unsafe fn get_unchecked(&self) -> &T {
+ debug_assert!(self.is_initialized());
+ &*self.value.get().cast::<T>()
+ }
+}
+
+impl<T> Drop for OnceLock<T> {
+ fn drop(&mut self) {
+ if self.is_initialized() {
+ // SAFETY: The inner value has been initialized
+ unsafe { self.value.get().cast::<T>().drop_in_place() };
+ }
+ }
+}
diff --git a/vendor/crossbeam-utils/.cargo-checksum.json b/vendor/crossbeam-utils/.cargo-checksum.json
index eac87698d..9c73bbda3 100644
--- a/vendor/crossbeam-utils/.cargo-checksum.json
+++ b/vendor/crossbeam-utils/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"eb2f46ecf2eee5f591c4d4e789f18735bb1ed771782a5e0f16eab3a77001e7c2","Cargo.toml":"9ce8b596c9789e65bef4c952bdcac84fc88e50ba9ecb01a818036eff4e6ecfec","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"2a19af38a52dd965c2d66bb39f90a85b430b51ee9ccb29e9e1978ee7091e5087","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build.rs":"4859f9c926c230023e861bf01c4b225b460035faf8cf6240108530efedbb747f","no_atomic.rs":"916ed15218bb7b75a4e0d432430e7134efd27ca43ca8a8766e0c90e89febb602","src/atomic/atomic_cell.rs":"0fc99463e633144c5d59d39c35b5477da1f1b90f5448cadc37454b7f4b97707e","src/atomic/consume.rs":"7a7736fcd64f6473dfea7653559ffc5e1a2a234df43835f8aa8734862145ac15","src/atomic/mod.rs":"94193895fa03cece415e8d7be700b73a9a8a7015774ca821253438607f9b0736","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"8fd5e3dcccc05860680e49c8498de8096bee9140bcfee8723d97117106a020d0","src/cache_padded.rs":"6a512698115ad0d5a5b163dbd7a83247e1f1c146c4a30f3fc74b952e3b767b59","src/lib.rs":"6f1bcf157abe06ad8458a53e865bf8efab9fad4a9424790147cee8fefb3795d8","src/sync/mod.rs":"59986f559a8f170a4b3247ab2eea2460b09809d87c8110ed88e4e7103d3519dc","src/sync/parker.rs":"91f3a7d4ee8d9e06b6558d180e8a0df08ff5c6cef612b4ce4790f9f75cb34f84","src/sync/sharded_lock.rs":"78433f55ee3defeea348d65abc78e03d63d6a304e09c568b27b403e9ad205771","src/sync/wait_group.rs":"32e946a7581c55f8aa9904527b92b177c538fa0cf7cbcfa1d1f25990582cb6ea","src/thread.rs":"21cf9b3e965529e5c0a6ff8fc1ec846bfe0006c41deb238a149be8d07384e955","tests/atomic_cell.rs":"bf8bc869c922a1cbf929c3b741bae0cae98f2157f572b5a4eb2873d20a407c22","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"314adeb8a651a28935f7a49c9a261b8fa1fd82bf6a16c865a5aced6216d7e40b","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"02661c2a820a5abe8b0c8fe15a6650aead707b57cdda0610d1b09a2680ed6969"},"package":"51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"65d3e11edf9498bdbc930c8c3878b7d3a90c1a0b1698597dc4a396a547fa0948","Cargo.toml":"1e4259a5a47271e8ae040b91e17652b5a4e0e7e45c3f22de5008db276f3a50bf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"5734ed989dfca1f625b40281ee9f4530f91b2411ec01cb748223e7eb87e201ab","README.md":"2a19af38a52dd965c2d66bb39f90a85b430b51ee9ccb29e9e1978ee7091e5087","benches/atomic_cell.rs":"c927eb3cd1e5ecc4b91adbc3bde98af15ffab4086190792ba64d5cde0e24df3d","build.rs":"4859f9c926c230023e861bf01c4b225b460035faf8cf6240108530efedbb747f","no_atomic.rs":"f58085b9d0666ccf62e0ae17fb5dae937c0a86fcc55dc0ae04ad8659e696a49c","src/atomic/atomic_cell.rs":"0fc99463e633144c5d59d39c35b5477da1f1b90f5448cadc37454b7f4b97707e","src/atomic/consume.rs":"7a7736fcd64f6473dfea7653559ffc5e1a2a234df43835f8aa8734862145ac15","src/atomic/mod.rs":"94193895fa03cece415e8d7be700b73a9a8a7015774ca821253438607f9b0736","src/atomic/seq_lock.rs":"27182e6b87a9db73c5f6831759f8625f9fcdec3c2828204c444aef04f427735a","src/atomic/seq_lock_wide.rs":"9888dd03116bb89ca36d4ab8d5a0b5032107a2983a7eb8024454263b09080088","src/backoff.rs":"8fd5e3dcccc05860680e49c8498de8096bee9140bcfee8723d97117106a020d0","src/cache_padded.rs":"8bb8925e2df44224ffa29f31a2f9c08d88d8bd3df6c1ce47003598225055fdb5","src/lib.rs":"6f1bcf157abe06ad8458a53e865bf8efab9fad4a9424790147cee8fefb3795d8","src/sync/mod.rs":"eca73c04f821859b8434d2b93db87d160dc6a3f65498ca201cd40d732ca4c134","src/sync/once_lock.rs":"c03dc9c05a817e087dccf8b682f7307501542805533551da3c2bab442bc40743","src/sync/parker.rs":"91f3a7d4ee8d9e06b6558d180e8a0df08ff5c6cef612b4ce4790f9f75cb34f84","src/sync/sharded_lock.rs":"6391b3b99b194b8e0888446c2dec340e4fb095753bcf0c1a80bc654f9c8be0e3","src/sync/wait_group.rs":"3e339aab014f50e214fea535c841755113ea058153378ed54e50a4acb403c937","src/thread.rs":"21cf9b3e965529e5c0a6ff8fc1ec846bfe0006c41deb238a149be8d07384e955","tests/atomic_cell.rs":"bf8bc869c922a1cbf929c3b741bae0cae98f2157f572b5a4eb2873d20a407c22","tests/cache_padded.rs":"1bfaff8354c8184e1ee1f902881ca9400b60effb273b0d3f752801a483d2b66d","tests/parker.rs":"6def4721287d9d70b1cfd63ebb34e1c83fbb3376edbad2bc8aac6ef69dd99d20","tests/sharded_lock.rs":"314adeb8a651a28935f7a49c9a261b8fa1fd82bf6a16c865a5aced6216d7e40b","tests/thread.rs":"9a7d7d3028c552fd834c68598b04a1cc252a816bc20ab62cec060d6cd09cab10","tests/wait_group.rs":"02661c2a820a5abe8b0c8fe15a6650aead707b57cdda0610d1b09a2680ed6969"},"package":"edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"} \ No newline at end of file
diff --git a/vendor/crossbeam-utils/CHANGELOG.md b/vendor/crossbeam-utils/CHANGELOG.md
index 28812e1d6..3a93e4659 100644
--- a/vendor/crossbeam-utils/CHANGELOG.md
+++ b/vendor/crossbeam-utils/CHANGELOG.md
@@ -1,3 +1,8 @@
+# Version 0.8.12
+
+- Removes the dependency on the `once_cell` crate to restore the MSRV. (#913)
+- Work around [rust-lang#98302](https://github.com/rust-lang/rust/issues/98302), which causes compile error on windows-gnu when LTO is enabled. (#913)
+
# Version 0.8.11
- Bump the minimum supported Rust version to 1.38. (#877)
diff --git a/vendor/crossbeam-utils/Cargo.toml b/vendor/crossbeam-utils/Cargo.toml
index 9e1b58628..5cb2b0a84 100644
--- a/vendor/crossbeam-utils/Cargo.toml
+++ b/vendor/crossbeam-utils/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.38"
name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.12"
description = "Utilities for concurrent programming"
homepage = "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils"
readme = "README.md"
@@ -35,10 +35,6 @@ repository = "https://github.com/crossbeam-rs/crossbeam"
[dependencies.cfg-if]
version = "1"
-[dependencies.once_cell]
-version = "1"
-optional = true
-
[dev-dependencies.rand]
version = "0.8"
@@ -48,7 +44,7 @@ version = "1"
[features]
default = ["std"]
nightly = []
-std = ["once_cell"]
+std = []
[target."cfg(crossbeam_loom)".dependencies.loom]
version = "0.5"
diff --git a/vendor/crossbeam-utils/no_atomic.rs b/vendor/crossbeam-utils/no_atomic.rs
index f740aaee1..675d9a27e 100644
--- a/vendor/crossbeam-utils/no_atomic.rs
+++ b/vendor/crossbeam-utils/no_atomic.rs
@@ -2,6 +2,8 @@
// It is not intended for manual editing.
const NO_ATOMIC_CAS: &[&str] = &[
+ "armv4t-none-eabi",
+ "armv5te-none-eabi",
"avr-unknown-gnu-atmega328",
"bpfeb-unknown-none",
"bpfel-unknown-none",
@@ -10,6 +12,7 @@ const NO_ATOMIC_CAS: &[&str] = &[
"riscv32im-unknown-none-elf",
"riscv32imc-unknown-none-elf",
"thumbv4t-none-eabi",
+ "thumbv5te-none-eabi",
"thumbv6m-none-eabi",
];
@@ -18,7 +21,9 @@ const NO_ATOMIC_64: &[&str] = &[
"arm-linux-androideabi",
"armebv7r-none-eabi",
"armebv7r-none-eabihf",
+ "armv4t-none-eabi",
"armv4t-unknown-linux-gnueabi",
+ "armv5te-none-eabi",
"armv5te-unknown-linux-gnueabi",
"armv5te-unknown-linux-musleabi",
"armv5te-unknown-linux-uclibceabi",
@@ -55,6 +60,7 @@ const NO_ATOMIC_64: &[&str] = &[
"riscv32imac-unknown-xous-elf",
"riscv32imc-unknown-none-elf",
"thumbv4t-none-eabi",
+ "thumbv5te-none-eabi",
"thumbv6m-none-eabi",
"thumbv7em-none-eabi",
"thumbv7em-none-eabihf",
diff --git a/vendor/crossbeam-utils/src/cache_padded.rs b/vendor/crossbeam-utils/src/cache_padded.rs
index 822e831d1..b5d5d33c9 100644
--- a/vendor/crossbeam-utils/src/cache_padded.rs
+++ b/vendor/crossbeam-utils/src/cache_padded.rs
@@ -39,9 +39,9 @@ use core::ops::{Deref, DerefMut};
/// let addr1 = &*array[0] as *const i8 as usize;
/// let addr2 = &*array[1] as *const i8 as usize;
///
-/// assert!(addr2 - addr1 >= 64);
-/// assert_eq!(addr1 % 64, 0);
-/// assert_eq!(addr2 % 64, 0);
+/// assert!(addr2 - addr1 >= 32);
+/// assert_eq!(addr1 % 32, 0);
+/// assert_eq!(addr2 % 32, 0);
/// ```
///
/// When building a concurrent queue with a head and a tail index, it is wise to place them in
diff --git a/vendor/crossbeam-utils/src/sync/mod.rs b/vendor/crossbeam-utils/src/sync/mod.rs
index eeb740c2c..f9eec71fb 100644
--- a/vendor/crossbeam-utils/src/sync/mod.rs
+++ b/vendor/crossbeam-utils/src/sync/mod.rs
@@ -4,6 +4,8 @@
//! * [`ShardedLock`], a sharded reader-writer lock with fast concurrent reads.
//! * [`WaitGroup`], for synchronizing the beginning or end of some computation.
+#[cfg(not(crossbeam_loom))]
+mod once_lock;
mod parker;
#[cfg(not(crossbeam_loom))]
mod sharded_lock;
diff --git a/vendor/crossbeam-utils/src/sync/once_lock.rs b/vendor/crossbeam-utils/src/sync/once_lock.rs
new file mode 100644
index 000000000..c1fefc96c
--- /dev/null
+++ b/vendor/crossbeam-utils/src/sync/once_lock.rs
@@ -0,0 +1,103 @@
+// Based on unstable std::sync::OnceLock.
+//
+// Source: https://github.com/rust-lang/rust/blob/8e9c93df464b7ada3fc7a1c8ccddd9dcb24ee0a0/library/std/src/sync/once_lock.rs
+
+use core::cell::UnsafeCell;
+use core::mem::MaybeUninit;
+use core::sync::atomic::{AtomicBool, Ordering};
+use std::sync::Once;
+
+pub(crate) struct OnceLock<T> {
+ once: Once,
+ // Once::is_completed requires Rust 1.43, so use this to track of whether they have been initialized.
+ is_initialized: AtomicBool,
+ value: UnsafeCell<MaybeUninit<T>>,
+ // Unlike std::sync::OnceLock, we don't need PhantomData here because
+ // we don't use #[may_dangle].
+}
+
+unsafe impl<T: Sync + Send> Sync for OnceLock<T> {}
+unsafe impl<T: Send> Send for OnceLock<T> {}
+
+impl<T> OnceLock<T> {
+ /// Creates a new empty cell.
+ #[must_use]
+ pub(crate) const fn new() -> Self {
+ Self {
+ once: Once::new(),
+ is_initialized: AtomicBool::new(false),
+ value: UnsafeCell::new(MaybeUninit::uninit()),
+ }
+ }
+
+ /// Gets the contents of the cell, initializing it with `f` if the cell
+ /// was empty.
+ ///
+ /// Many threads may call `get_or_init` concurrently with different
+ /// initializing functions, but it is guaranteed that only one function
+ /// will be executed.
+ ///
+ /// # Panics
+ ///
+ /// If `f` panics, the panic is propagated to the caller, and the cell
+ /// remains uninitialized.
+ ///
+ /// It is an error to reentrantly initialize the cell from `f`. The
+ /// exact outcome is unspecified. Current implementation deadlocks, but
+ /// this may be changed to a panic in the future.
+ pub(crate) fn get_or_init<F>(&self, f: F) -> &T
+ where
+ F: FnOnce() -> T,
+ {
+ // Fast path check
+ if self.is_initialized() {
+ // SAFETY: The inner value has been initialized
+ return unsafe { self.get_unchecked() };
+ }
+ self.initialize(f);
+
+ debug_assert!(self.is_initialized());
+
+ // SAFETY: The inner value has been initialized
+ unsafe { self.get_unchecked() }
+ }
+
+ #[inline]
+ fn is_initialized(&self) -> bool {
+ self.is_initialized.load(Ordering::Acquire)
+ }
+
+ #[cold]
+ fn initialize<F>(&self, f: F)
+ where
+ F: FnOnce() -> T,
+ {
+ let slot = self.value.get().cast::<T>();
+ let is_initialized = &self.is_initialized;
+
+ self.once.call_once(|| {
+ let value = f();
+ unsafe {
+ slot.write(value);
+ }
+ is_initialized.store(true, Ordering::Release);
+ });
+ }
+
+ /// # Safety
+ ///
+ /// The value must be initialized
+ unsafe fn get_unchecked(&self) -> &T {
+ debug_assert!(self.is_initialized());
+ &*self.value.get().cast::<T>()
+ }
+}
+
+impl<T> Drop for OnceLock<T> {
+ fn drop(&mut self) {
+ if self.is_initialized() {
+ // SAFETY: The inner value has been initialized
+ unsafe { self.value.get().cast::<T>().drop_in_place() };
+ }
+ }
+}
diff --git a/vendor/crossbeam-utils/src/sync/sharded_lock.rs b/vendor/crossbeam-utils/src/sync/sharded_lock.rs
index 692653447..b43c55ea4 100644
--- a/vendor/crossbeam-utils/src/sync/sharded_lock.rs
+++ b/vendor/crossbeam-utils/src/sync/sharded_lock.rs
@@ -9,8 +9,8 @@ use std::sync::{LockResult, PoisonError, TryLockError, TryLockResult};
use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
use std::thread::{self, ThreadId};
+use crate::sync::once_lock::OnceLock;
use crate::CachePadded;
-use once_cell::sync::Lazy;
/// The number of shards per sharded lock. Must be a power of two.
const NUM_SHARDS: usize = 8;
@@ -583,13 +583,17 @@ struct ThreadIndices {
next_index: usize,
}
-static THREAD_INDICES: Lazy<Mutex<ThreadIndices>> = Lazy::new(|| {
- Mutex::new(ThreadIndices {
- mapping: HashMap::new(),
- free_list: Vec::new(),
- next_index: 0,
- })
-});
+fn thread_indices() -> &'static Mutex<ThreadIndices> {
+ static THREAD_INDICES: OnceLock<Mutex<ThreadIndices>> = OnceLock::new();
+ fn init() -> Mutex<ThreadIndices> {
+ Mutex::new(ThreadIndices {
+ mapping: HashMap::new(),
+ free_list: Vec::new(),
+ next_index: 0,
+ })
+ }
+ THREAD_INDICES.get_or_init(init)
+}
/// A registration of a thread with an index.
///
@@ -601,7 +605,7 @@ struct Registration {
impl Drop for Registration {
fn drop(&mut self) {
- let mut indices = THREAD_INDICES.lock().unwrap();
+ let mut indices = thread_indices().lock().unwrap();
indices.mapping.remove(&self.thread_id);
indices.free_list.push(self.index);
}
@@ -610,7 +614,7 @@ impl Drop for Registration {
thread_local! {
static REGISTRATION: Registration = {
let thread_id = thread::current().id();
- let mut indices = THREAD_INDICES.lock().unwrap();
+ let mut indices = thread_indices().lock().unwrap();
let index = match indices.free_list.pop() {
Some(i) => i,
diff --git a/vendor/crossbeam-utils/src/sync/wait_group.rs b/vendor/crossbeam-utils/src/sync/wait_group.rs
index 4206ee42b..19d607415 100644
--- a/vendor/crossbeam-utils/src/sync/wait_group.rs
+++ b/vendor/crossbeam-utils/src/sync/wait_group.rs
@@ -1,6 +1,3 @@
-// Necessary for using `Mutex<usize>` for conditional variables
-#![allow(clippy::mutex_atomic)]
-
use crate::primitive::sync::{Arc, Condvar, Mutex};
use std::fmt;
@@ -42,6 +39,7 @@ use std::fmt;
///
/// // Block until all threads have finished their work.
/// wg.wait();
+/// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371
/// ```
///
/// [`Barrier`]: std::sync::Barrier
@@ -100,6 +98,7 @@ impl WaitGroup {
///
/// // Block until both threads have reached `wait()`.
/// wg.wait();
+ /// # std::thread::sleep(std::time::Duration::from_millis(500)); // wait for background threads closed: https://github.com/rust-lang/miri/issues/1371
/// ```
pub fn wait(self) {
if *self.inner.count.lock().unwrap() == 1 {
diff --git a/vendor/dashmap/.cargo-checksum.json b/vendor/dashmap/.cargo-checksum.json
index 7d0daa971..4197ac76b 100644
--- a/vendor/dashmap/.cargo-checksum.json
+++ b/vendor/dashmap/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"8f8a0060b2a6f95a4ba3f009e49a4f0a4c26ea5ba7fb02388ca5466d97c6ccfe","LICENSE":"16692e8cee4aa06e3913787497eba2d47c42002014136f5da67be6ee640e28a3","README.md":"e1114aed5dfbd2892f2d81881c46f8e17b9b4774344ad3feb55bd2c1a41384fd","rust-toolchain":"06dc4c395690e7d6ff8b92d8d265a8cf1c02cbca414e15352072e378fcb4171a","src/iter.rs":"dec9cc68374a0a176b5840e37da4e83d0493d7dca6f776dc926bf511c84e70db","src/iter_set.rs":"5327da951dc93d30b293aeb7a805666ee4b8e6364881348ab5d86b23c29a0e13","src/lib.rs":"ad0b2651810d4d286f11ce4effb800920eb4100ae6676f6141126e5488358007","src/lock.rs":"22b1013ee3cbd1598c26403552faf8e5b44fe98a8ff4c8812da15d57bdeee4b3","src/mapref/entry.rs":"ddcf788856330a4384ce987bb84ff36b494675b3b1f2460ae48376ac664491df","src/mapref/mod.rs":"15bd45cfc642a9e3e77bbfbf2d9fad9c5fac0ff6904214a3c501e262242ec8b0","src/mapref/multiple.rs":"17a87879229d78f75d71817d100aa0a210d764d6b66e4a05b17a3e092d17e306","src/mapref/one.rs":"ea46339e08c5033cf419c195e922e1ba6f606fc71c15ee31d1b3c38cfedfedcf","src/rayon/map.rs":"07315c9dd35437fd5e504a07fcbcd77f9ea19c892c32c1d60f27db5a6a26345b","src/rayon/set.rs":"21fe2ca8c58c8ff1bc753f5e2eb6131afd598211eea375f2ac7190cd0f9abcba","src/read_only.rs":"c846f8117800dbbb122bc0552021c5ac4ccfbf464bebe37f4b65e40b19baf260","src/serde.rs":"57bbf2b255de966cc9c54011429495cc5308a1f76906846b29e015f860b79559","src/set.rs":"80271aa0d8a32845afdef5a35f18e5cac6f0f5ab8d2a6b11b02cd123152c91d4","src/setref/mod.rs":"cc39e406a333dc6c04398f4b1336fb400e3a8360c387466d8a91f5d7f4ed40a7","src/setref/multiple.rs":"2270749e83f80dbb4761448f0629ecd02b0b4268f76834236d1167844e6d5e37","src/setref/one.rs":"69738583f2a160f3907e540277ccd88e0036406b3ead66b3d4015ddd938d6937","src/t.rs":"9b40ebfba22369813bf159ed60fa70e742ae72bfaec6aee91a716cba91cb8f0d","src/table.rs":"536a3b5775cbdbe436357c231e54e4e2ee4a5e1849872aa92335271b148845b4","src/try_result.rs":"81d1dd396f70b0aa2a6e1969851b706cbfdfb09c802ac9d33dcace882aa28dd1","src/util.rs":"7a8096a713cf04e60d6c9e38cd366314ed74472abab4bb8a3a9ed081a0e0301b"},"package":"3495912c9c1ccf2e18976439f4443f3fee0fd61f424ff99fde6a66b15ecb448f"} \ No newline at end of file
+{"files":{"Cargo.toml":"8181631e0224f428c3c213850ce536d9d27c82b46e3eadcd0137f78470086fc2","LICENSE":"16692e8cee4aa06e3913787497eba2d47c42002014136f5da67be6ee640e28a3","README.md":"e1114aed5dfbd2892f2d81881c46f8e17b9b4774344ad3feb55bd2c1a41384fd","rust-toolchain":"06dc4c395690e7d6ff8b92d8d265a8cf1c02cbca414e15352072e378fcb4171a","src/iter.rs":"dec9cc68374a0a176b5840e37da4e83d0493d7dca6f776dc926bf511c84e70db","src/iter_set.rs":"5327da951dc93d30b293aeb7a805666ee4b8e6364881348ab5d86b23c29a0e13","src/lib.rs":"24935d49696b2d05a83287c6a5f08d59bc206a535bfa0f8893bfeff3cfd14ea8","src/lock.rs":"22b1013ee3cbd1598c26403552faf8e5b44fe98a8ff4c8812da15d57bdeee4b3","src/mapref/entry.rs":"ddcf788856330a4384ce987bb84ff36b494675b3b1f2460ae48376ac664491df","src/mapref/mod.rs":"15bd45cfc642a9e3e77bbfbf2d9fad9c5fac0ff6904214a3c501e262242ec8b0","src/mapref/multiple.rs":"17a87879229d78f75d71817d100aa0a210d764d6b66e4a05b17a3e092d17e306","src/mapref/one.rs":"ea46339e08c5033cf419c195e922e1ba6f606fc71c15ee31d1b3c38cfedfedcf","src/rayon/map.rs":"2df5ac8241d92e1811852abd65c5b3124a14d886ae4e3a8a5cbdfdb3d7dde929","src/rayon/read_only.rs":"99dc0083f6840f59b2090bc9c5f9767a44088832e63935cb8f6bc7eca8b86102","src/rayon/set.rs":"21fe2ca8c58c8ff1bc753f5e2eb6131afd598211eea375f2ac7190cd0f9abcba","src/read_only.rs":"d872ec78201ddc272aeeabdbeaccb26e069704b85aa2f6a4d56bd0c5defe7a2b","src/serde.rs":"57bbf2b255de966cc9c54011429495cc5308a1f76906846b29e015f860b79559","src/set.rs":"80271aa0d8a32845afdef5a35f18e5cac6f0f5ab8d2a6b11b02cd123152c91d4","src/setref/mod.rs":"cc39e406a333dc6c04398f4b1336fb400e3a8360c387466d8a91f5d7f4ed40a7","src/setref/multiple.rs":"2270749e83f80dbb4761448f0629ecd02b0b4268f76834236d1167844e6d5e37","src/setref/one.rs":"69738583f2a160f3907e540277ccd88e0036406b3ead66b3d4015ddd938d6937","src/t.rs":"9b40ebfba22369813bf159ed60fa70e742ae72bfaec6aee91a716cba91cb8f0d","src/try_result.rs":"81d1dd396f70b0aa2a6e1969851b706cbfdfb09c802ac9d33dcace882aa28dd1","src/util.rs":"7a8096a713cf04e60d6c9e38cd366314ed74472abab4bb8a3a9ed081a0e0301b"},"package":"907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"} \ No newline at end of file
diff --git a/vendor/dashmap/Cargo.toml b/vendor/dashmap/Cargo.toml
index a03feb0ce..ce76bd9a7 100644
--- a/vendor/dashmap/Cargo.toml
+++ b/vendor/dashmap/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.59"
name = "dashmap"
-version = "5.3.4"
+version = "5.4.0"
authors = ["Acrimon <joel.wejdenstal@gmail.com>"]
description = "Blazing fast concurrent HashMap for Rust."
homepage = "https://github.com/xacrimon/dashmap"
@@ -29,21 +29,24 @@ features = ["rayon", "raw-api", "serde"]
version = "1.0.0"
[dependencies.hashbrown]
-version = "0.12.0"
+version = "0.12.3"
default-features = false
[dependencies.lock_api]
-version = "0.4.7"
+version = "0.4.8"
+
+[dependencies.once_cell]
+version = "1.13.1"
[dependencies.parking_lot_core]
version = "0.9.3"
[dependencies.rayon]
-version = "1.5.2"
+version = "1.5.3"
optional = true
[dependencies.serde]
-version = "1.0.136"
+version = "1.0.144"
features = ["derive"]
optional = true
diff --git a/vendor/dashmap/src/lib.rs b/vendor/dashmap/src/lib.rs
index 627b51381..bf112d570 100644
--- a/vendor/dashmap/src/lib.rs
+++ b/vendor/dashmap/src/lib.rs
@@ -16,6 +16,7 @@ mod util;
#[cfg(feature = "rayon")]
pub mod rayon {
pub mod map;
+ pub mod read_only;
pub mod set;
}
@@ -35,6 +36,7 @@ use iter::{Iter, IterMut, OwningIter};
use mapref::entry::{Entry, OccupiedEntry, VacantEntry};
use mapref::multiple::RefMulti;
use mapref::one::{Ref, RefMut};
+use once_cell::sync::OnceCell;
pub use read_only::ReadOnlyView;
pub use set::DashSet;
use std::collections::hash_map::RandomState;
@@ -51,8 +53,19 @@ cfg_if! {
pub(crate) type HashMap<K, V, S> = hashbrown::HashMap<K, SharedValue<V>, S>;
+// Temporary reimplementation of [`std::collections::TryReserveError`]
+// util [`std::collections::TryReserveError`] stabilises.
+// We cannot easily create `std::collections` error type from `hashbrown` error type
+// without access to `TryReserveError::kind` method.
+#[non_exhaustive]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct TryReserveError {}
+
fn default_shard_amount() -> usize {
- (std::thread::available_parallelism().map_or(1, usize::from) * 4).next_power_of_two()
+ static DEFAULT_SHARD_AMOUNT: OnceCell<usize> = OnceCell::new();
+ *DEFAULT_SHARD_AMOUNT.get_or_init(|| {
+ (std::thread::available_parallelism().map_or(1, usize::from) * 4).next_power_of_two()
+ })
}
fn ncb(shard_amount: usize) -> usize {
@@ -65,7 +78,7 @@ fn ncb(shard_amount: usize) -> usize {
/// with some slight changes to handle concurrency.
///
/// DashMap tries to be very simple to use and to be a direct replacement for `RwLock<HashMap<K, V, S>>`.
-/// To accomplish these all methods take `&self` instead modifying methods taking `&mut self`.
+/// To accomplish this, all methods take `&self` instead of modifying methods taking `&mut self`.
/// This allows you to put a DashMap in an `Arc<T>` and share it between threads while being able to modify it.
///
/// Documentation mentioning locking behaviour acts in the reference frame of the calling thread.
@@ -216,7 +229,7 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
/// Creates a new DashMap with a specified hasher and shard amount
///
- /// shard_amount should greater than 0 and be a power of two.
+ /// shard_amount should be greater than 0 and a power of two.
/// If a shard_amount which is not a power of two is provided, the function will panic.
///
/// # Examples
@@ -797,6 +810,24 @@ impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> DashMap<K, V, S> {
pub fn try_entry(&'a self, key: K) -> Option<Entry<'a, K, V, S>> {
self._try_entry(key)
}
+
+ /// Advanced entry API that tries to mimic `std::collections::HashMap::try_reserve`.
+ /// Tries to reserve capacity for at least `shard * additional`
+ /// and may reserve more space to avoid frequent reallocations.
+ ///
+ /// # Errors
+ ///
+ /// If the capacity overflows, or the allocator reports a failure, then an error is returned.
+ // TODO: return std::collections::TryReserveError once std::collections::TryReserveErrorKind stabilises.
+ pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+ for shard in self.shards.iter() {
+ shard
+ .write()
+ .try_reserve(additional)
+ .map_err(|_| TryReserveError {})?;
+ }
+ Ok(())
+ }
}
impl<'a, K: 'a + Eq + Hash, V: 'a, S: 'a + BuildHasher + Clone> Map<'a, K, V, S>
@@ -1367,4 +1398,26 @@ mod tests {
assert!(result2.is_locked());
}
}
+
+ #[test]
+ fn test_try_reserve() {
+ let mut map: DashMap<i32, i32> = DashMap::new();
+ // DashMap is empty and doesn't allocate memory
+ assert_eq!(map.capacity(), 0);
+
+ map.try_reserve(10).unwrap();
+
+ // And now map can hold at least 10 elements
+ assert!(map.capacity() >= 10);
+ }
+
+ #[test]
+ fn test_try_reserve_errors() {
+ let mut map: DashMap<i32, i32> = DashMap::new();
+
+ match map.try_reserve(usize::MAX) {
+ Err(_) => {}
+ _ => panic!("should have raised CapacityOverflow error"),
+ }
+ }
}
diff --git a/vendor/dashmap/src/rayon/map.rs b/vendor/dashmap/src/rayon/map.rs
index c0947cf6b..4fc0c43aa 100644
--- a/vendor/dashmap/src/rayon/map.rs
+++ b/vendor/dashmap/src/rayon/map.rs
@@ -80,7 +80,7 @@ where
}
pub struct OwningIter<K, V, S = RandomState> {
- shards: Box<[RwLock<HashMap<K, V, S>>]>,
+ pub(super) shards: Box<[RwLock<HashMap<K, V, S>>]>,
}
impl<K, V, S> ParallelIterator for OwningIter<K, V, S>
@@ -125,7 +125,7 @@ where
}
pub struct Iter<'a, K, V, S = RandomState> {
- shards: &'a [RwLock<HashMap<K, V, S>>],
+ pub(super) shards: &'a [RwLock<HashMap<K, V, S>>],
}
impl<'a, K, V, S> ParallelIterator for Iter<'a, K, V, S>
diff --git a/vendor/dashmap/src/rayon/read_only.rs b/vendor/dashmap/src/rayon/read_only.rs
new file mode 100644
index 000000000..a11448cee
--- /dev/null
+++ b/vendor/dashmap/src/rayon/read_only.rs
@@ -0,0 +1,96 @@
+use crate::mapref::multiple::RefMulti;
+use crate::rayon::map::Iter;
+use crate::ReadOnlyView;
+use core::hash::{BuildHasher, Hash};
+use rayon::iter::IntoParallelIterator;
+
+impl<K, V, S> IntoParallelIterator for ReadOnlyView<K, V, S>
+where
+ K: Send + Eq + Hash,
+ V: Send,
+ S: Send + Clone + BuildHasher,
+{
+ type Iter = super::map::OwningIter<K, V, S>;
+ type Item = (K, V);
+
+ fn into_par_iter(self) -> Self::Iter {
+ super::map::OwningIter {
+ shards: self.map.shards,
+ }
+ }
+}
+
+// This impl also enables `IntoParallelRefIterator::par_iter`
+impl<'a, K, V, S> IntoParallelIterator for &'a ReadOnlyView<K, V, S>
+where
+ K: Send + Sync + Eq + Hash,
+ V: Send + Sync,
+ S: Send + Sync + Clone + BuildHasher,
+{
+ type Iter = Iter<'a, K, V, S>;
+ type Item = RefMulti<'a, K, V, S>;
+
+ fn into_par_iter(self) -> Self::Iter {
+ Iter {
+ shards: &self.map.shards,
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::DashMap;
+ use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
+
+ fn construct_sample_map() -> DashMap<i32, String> {
+ let map = DashMap::new();
+
+ map.insert(1, "one".to_string());
+
+ map.insert(10, "ten".to_string());
+
+ map.insert(27, "twenty seven".to_string());
+
+ map.insert(45, "forty five".to_string());
+
+ map
+ }
+
+ #[test]
+ fn test_par_iter() {
+ let map = construct_sample_map();
+
+ let view = map.clone().into_read_only();
+
+ view.par_iter().for_each(|entry| {
+ let key = *entry.key();
+
+ assert!(view.contains_key(&key));
+
+ let map_entry = map.get(&key).unwrap();
+
+ assert_eq!(view.get(&key).unwrap(), map_entry.value());
+
+ let key_value: (&i32, &String) = view.get_key_value(&key).unwrap();
+
+ assert_eq!(key_value.0, map_entry.key());
+
+ assert_eq!(key_value.1, map_entry.value());
+ });
+ }
+
+ #[test]
+ fn test_into_par_iter() {
+ let map = construct_sample_map();
+
+ let view = map.clone().into_read_only();
+
+ view.into_par_iter().for_each(|(key, value)| {
+ let map_entry = map.get(&key).unwrap();
+
+ assert_eq!(&key, map_entry.key());
+
+ assert_eq!(&value, map_entry.value());
+ });
+ }
+}
diff --git a/vendor/dashmap/src/read_only.rs b/vendor/dashmap/src/read_only.rs
index c43947b2e..14582245b 100644
--- a/vendor/dashmap/src/read_only.rs
+++ b/vendor/dashmap/src/read_only.rs
@@ -7,7 +7,7 @@ use std::collections::hash_map::RandomState;
/// A read-only view into a `DashMap`. Allows to obtain raw references to the stored values.
pub struct ReadOnlyView<K, V, S = RandomState> {
- map: DashMap<K, V, S>,
+ pub(crate) map: DashMap<K, V, S>,
}
impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for ReadOnlyView<K, V, S> {
diff --git a/vendor/dashmap/src/table.rs b/vendor/dashmap/src/table.rs
deleted file mode 100644
index 03acd76e2..000000000
--- a/vendor/dashmap/src/table.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-use super::u128::AtomicU128;
-use std::borrow::Borrow;
-use std::cell::UnsafeCell;
-use std::hash::{BuildHasher, Hash, Hasher};
-use std::mem::MaybeUninit;
-use std::sync::atomic::{AtomicU64, Ordering};
-use std::sync::{Arc, Mutex};
-
-const TOMBSTONE_BIT: u64 = 1 << 63;
-const ALLOCATED_BIT: u64 = 1 << 62;
-const POINTER_MASK: u64 = 0x3FFFFFFFFFFFFFFF;
-
-fn hash<S, K>(hasher: &S, key: &K) -> u64
-where
- S: BuildHasher,
- K: Hash,
-{
- let mut hasher = hasher.build_hasher();
- key.hash(&mut hasher);
- hasher.finish()
-}
-
-struct Slot<K, V> {
- data: AtomicU64,
- pair: UnsafeCell<MaybeUninit<(K, V)>>,
-}
-
-pub struct Table<K, V, S> {
- hash: Arc<S>,
- slots: Box<[Slot<K, V>]>,
- mask: usize,
-}
-
-impl<K, V, S> Table<K, V, S>
-where
- K: Eq + Hash,
- S: BuildHasher,
-{
- pub fn new(hasher: Arc<S>, capacity: usize) -> Self {
- debug_assert!(capacity.is_power_of_two());
- let slots = (0..capacity)
- .map(|_| Slot {
- data: AtomicU64::new(0),
- pair: UnsafeCell::new(MaybeUninit::uninit()),
- })
- .collect::<Vec<_>>();
-
- Table {
- hash: hasher,
- slots: slots.into_boxed_slice(),
- mask: capacity - 1,
- }
- }
-
- pub fn get<Q>(&self, key: &Q) -> Option<*mut (K, V)>
- where
- K: Borrow<Q>,
- Q: Eq + Hash,
- {
- let hash = hash(&*self.hash, key);
- let mut idx = hash as usize & self.mask;
- let mut i = 0;
-
- loop {
- let slot = &self.slots[idx];
- let data = slot.data.load(Ordering::Relaxed);
- let ptr = (data & POINTER_MASK) as *mut (K, V);
- if !ptr.is_null() {
- let stored = unsafe { (*ptr).0.borrow() };
- if stored == key {
- return Some(ptr);
- }
- } else if data & TOMBSTONE_BIT != TOMBSTONE_BIT || i > self.mask {
- return None;
- }
-
- idx = (idx + 1) & self.mask;
- i += 1;
- }
- }
-}
diff --git a/vendor/form_urlencoded/.cargo-checksum.json b/vendor/form_urlencoded/.cargo-checksum.json
index 33e19d140..29befa62b 100644
--- a/vendor/form_urlencoded/.cargo-checksum.json
+++ b/vendor/form_urlencoded/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"aadc4e4ba33e86861d8d1d8b848ac11a27b6f87340d082b47f762387464c61ed","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","src/lib.rs":"5d30edec687843447c97e4ea87583983eb9fc06135ae718c8ecc0fa8cebef2df"},"package":"5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"} \ No newline at end of file
+{"files":{"Cargo.toml":"1771c35bc67b544a7ebc6f31168d7bc08d29ae76323e7ee10352d43b5a38afac","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","src/lib.rs":"c1a0db36086e4fd0e8bb1489f9c2bb55945dd233614bf5dc3a0c41cb49292dd3"},"package":"a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"} \ No newline at end of file
diff --git a/vendor/form_urlencoded/Cargo.toml b/vendor/form_urlencoded/Cargo.toml
index 4c9fae259..037361d31 100644
--- a/vendor/form_urlencoded/Cargo.toml
+++ b/vendor/form_urlencoded/Cargo.toml
@@ -3,26 +3,24 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
+rust-version = "1.51"
name = "form_urlencoded"
-version = "1.0.1"
+version = "1.1.0"
authors = ["The rust-url developers"]
description = "Parser and serializer for the application/x-www-form-urlencoded syntax, as used by HTML forms."
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/rust-url"
[lib]
test = false
-[dependencies.matches]
-version = "0.1"
[dependencies.percent-encoding]
-version = "2.1.0"
+version = "2.2.0"
diff --git a/vendor/form_urlencoded/src/lib.rs b/vendor/form_urlencoded/src/lib.rs
index 765ee168a..477594bf7 100644
--- a/vendor/form_urlencoded/src/lib.rs
+++ b/vendor/form_urlencoded/src/lib.rs
@@ -13,9 +13,6 @@
//! Converts between a string (such as an URL’s query string)
//! and a sequence of (name, value) pairs.
-#[macro_use]
-extern crate matches;
-
use percent_encoding::{percent_decode, percent_encode_byte};
use std::borrow::{Borrow, Cow};
use std::str;
@@ -402,8 +399,7 @@ pub(crate) fn decode_utf8_lossy(input: Cow<'_, [u8]>) -> Cow<'_, str> {
// replace invalid bytes with a placeholder.
// First we do a debug_assert to confirm our description above.
- let raw_utf8: *const [u8];
- raw_utf8 = utf8.as_bytes();
+ let raw_utf8: *const [u8] = utf8.as_bytes();
debug_assert!(raw_utf8 == &*bytes as *const [u8]);
// Given we know the original input bytes are valid UTF-8,
diff --git a/vendor/home/.cargo-checksum.json b/vendor/home/.cargo-checksum.json
index 637f4c5ce..ad8175dc3 100644
--- a/vendor/home/.cargo-checksum.json
+++ b/vendor/home/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f6ea8042d794bed2af227905011daada5eaa1eb15ba63589d2aa9c8bd5ea06e7","LICENSE-APACHE":"aefbb3792184d86e625cd877b226a00e2cf13cb546ae79e78ddb9e3f097a7156","LICENSE-MIT":"ea7c5138df175c35e89b7adc1b1b35e07786a40330cae4beb2172781bd3daad9","README.md":"13b381ff7553b3467c85b877ee0aae43ebf444deca1c85131d5f0fb3b27d5003","src/lib.rs":"bbadf2a9750a1dd204057dee19e4282d48a878bd9b1810bedf59dc4b55a992eb","src/windows.rs":"061ce6208d2a366cdbf9d094c60fa73b7e856eb1f510fa2aaf5d109bded35442"},"package":"2456aef2e6b6a9784192ae780c0f15bc57df0e918585282325e8c8ac27737654"} \ No newline at end of file
+{"files":{"Cargo.toml":"12996f8286ac1164cb7026f8e170316337a0acb2d180fbf41192ddcf534a4843","LICENSE-APACHE":"aefbb3792184d86e625cd877b226a00e2cf13cb546ae79e78ddb9e3f097a7156","LICENSE-MIT":"ea7c5138df175c35e89b7adc1b1b35e07786a40330cae4beb2172781bd3daad9","README.md":"13b381ff7553b3467c85b877ee0aae43ebf444deca1c85131d5f0fb3b27d5003","src/env.rs":"4e8bd91330f6ae948f5b825e9884720631f4fe9282fb4548915218e1c43b54a5","src/lib.rs":"cc2675a4c0d5b2e3041228554718f63f754811e9b45a3c9b423bd2f43adf38e3","src/windows.rs":"061ce6208d2a366cdbf9d094c60fa73b7e856eb1f510fa2aaf5d109bded35442"},"package":"747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"} \ No newline at end of file
diff --git a/vendor/home/Cargo.toml b/vendor/home/Cargo.toml
index 245d5e1d8..765a5f903 100644
--- a/vendor/home/Cargo.toml
+++ b/vendor/home/Cargo.toml
@@ -3,24 +3,34 @@
# 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 = "home"
-version = "0.5.3"
+version = "0.5.4"
authors = ["Brian Anderson <andersrb@gmail.com>"]
-include = ["/src", "/Cargo.toml", "/CHANGELOG", "/LICENSE-*", "/README.md"]
+include = [
+ "/src",
+ "/Cargo.toml",
+ "/CHANGELOG",
+ "/LICENSE-*",
+ "/README.md",
+]
description = "Shared definitions of home directories"
documentation = "https://docs.rs/home"
readme = "README.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/brson/home"
+
[target."cfg(windows)".dependencies.winapi]
version = "0.3"
-features = ["shlobj", "std", "winerror"]
+features = [
+ "shlobj",
+ "std",
+ "winerror",
+]
diff --git a/vendor/home/src/env.rs b/vendor/home/src/env.rs
new file mode 100644
index 000000000..e47273bc8
--- /dev/null
+++ b/vendor/home/src/env.rs
@@ -0,0 +1,106 @@
+//! Lower-level utilities for mocking the process environment.
+
+use std::{
+ ffi::OsString,
+ io,
+ path::{Path, PathBuf},
+};
+
+/// Permits parameterizing the home functions via the _from variants - used for
+/// in-process unit testing by rustup.
+pub trait Env {
+ /// Return the path to the the users home dir, or None if any error occurs:
+ /// see home_inner.
+ fn home_dir(&self) -> Option<PathBuf>;
+ /// Return the current working directory.
+ fn current_dir(&self) -> io::Result<PathBuf>;
+ /// Get an environment variable, as per std::env::var_os.
+ fn var_os(&self, key: &str) -> Option<OsString>;
+}
+
+/// Implements Env for the OS context, both Unix style and Windows.
+///
+/// This is trait permits in-process testing by providing a control point to
+/// allow in-process divergence on what is normally process wide state.
+///
+/// Implementations should be provided by whatever testing framework the caller
+/// is using. Code that is not performing in-process threaded testing requiring
+/// isolated rustup/cargo directories does not need this trait or the _from
+/// functions.
+pub struct OsEnv;
+impl Env for OsEnv {
+ fn home_dir(&self) -> Option<PathBuf> {
+ crate::home_dir_inner()
+ }
+ fn current_dir(&self) -> io::Result<PathBuf> {
+ std::env::current_dir()
+ }
+ fn var_os(&self, key: &str) -> Option<OsString> {
+ std::env::var_os(key)
+ }
+}
+
+pub const OS_ENV: OsEnv = OsEnv {};
+
+/// Returns the path of the current user's home directory from [`Env::home_dir`].
+pub fn home_dir_with_env(env: &dyn Env) -> Option<PathBuf> {
+ env.home_dir()
+}
+
+/// Variant of cargo_home where the environment source is parameterized. This is
+/// specifically to support in-process testing scenarios as environment
+/// variables and user home metadata are normally process global state. See the
+/// [`Env`] trait.
+pub fn cargo_home_with_env(env: &dyn Env) -> io::Result<PathBuf> {
+ let cwd = env.current_dir()?;
+ cargo_home_with_cwd_env(env, &cwd)
+}
+
+/// Variant of cargo_home_with_cwd where the environment source is
+/// parameterized. This is specifically to support in-process testing scenarios
+/// as environment variables and user home metadata are normally process global
+/// state. See the OsEnv trait.
+pub fn cargo_home_with_cwd_env(env: &dyn Env, cwd: &Path) -> io::Result<PathBuf> {
+ match env.var_os("CARGO_HOME").filter(|h| !h.is_empty()) {
+ Some(home) => {
+ let home = PathBuf::from(home);
+ if home.is_absolute() {
+ Ok(home)
+ } else {
+ Ok(cwd.join(&home))
+ }
+ }
+ _ => home_dir_with_env(env)
+ .map(|p| p.join(".cargo"))
+ .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not find cargo home dir")),
+ }
+}
+
+/// Variant of cargo_home_with_cwd where the environment source is
+/// parameterized. This is specifically to support in-process testing scenarios
+/// as environment variables and user home metadata are normally process global
+/// state. See the OsEnv trait.
+pub fn rustup_home_with_env(env: &dyn Env) -> io::Result<PathBuf> {
+ let cwd = env.current_dir()?;
+ rustup_home_with_cwd_env(env, &cwd)
+}
+
+/// Variant of cargo_home_with_cwd where the environment source is
+/// parameterized. This is specifically to support in-process testing scenarios
+/// as environment variables and user home metadata are normally process global
+/// state. See the OsEnv trait.
+pub fn rustup_home_with_cwd_env(env: &dyn Env, cwd: &Path) -> io::Result<PathBuf> {
+ match env.var_os("RUSTUP_HOME").filter(|h| !h.is_empty()) {
+ Some(home) => {
+ let home = PathBuf::from(home);
+ if home.is_absolute() {
+ Ok(home)
+ } else {
+ Ok(cwd.join(&home))
+ }
+ }
+ _ => home_dir_with_env(env)
+ .map(|d| d.join(".rustup"))
+ .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not find rustup home dir")),
+ }
+}
diff --git a/vendor/home/src/lib.rs b/vendor/home/src/lib.rs
index ad31d3d2e..ad254ca3b 100644
--- a/vendor/home/src/lib.rs
+++ b/vendor/home/src/lib.rs
@@ -25,13 +25,14 @@
//!
//! [discussion]: https://github.com/rust-lang/rust/pull/46799#issuecomment-361156935
-#![doc(html_root_url = "https://docs.rs/home/0.5.3")]
+#![doc(html_root_url = "https://docs.rs/home/0.5.4")]
#![deny(rust_2018_idioms)]
+pub mod env;
+
#[cfg(windows)]
mod windows;
-use std::env;
use std::io;
use std::path::{Path, PathBuf};
@@ -48,10 +49,9 @@ use std::path::{Path, PathBuf};
///
/// Returns the value of the `USERPROFILE` environment variable if it
/// is set and not equal to the empty string. If both do not exist,
-/// [`GetUserProfileDirectory`][msdn] is used to return the
-/// appropriate path.
+/// [`SHGetFolderPathW`][msdn] is used to return the appropriate path.
///
-/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/userenv/nf-userenv-getuserprofiledirectoryw
+/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetfolderpathw
///
/// # Examples
///
@@ -62,7 +62,7 @@ use std::path::{Path, PathBuf};
/// }
/// ```
pub fn home_dir() -> Option<PathBuf> {
- home_dir_inner()
+ env::home_dir_with_env(&env::OS_ENV)
}
#[cfg(windows)]
@@ -71,7 +71,7 @@ use windows::home_dir_inner;
#[cfg(any(unix, target_os = "redox"))]
fn home_dir_inner() -> Option<PathBuf> {
#[allow(deprecated)]
- env::home_dir()
+ std::env::home_dir()
}
/// Returns the storage directory used by Cargo, often knowns as
@@ -102,26 +102,13 @@ fn home_dir_inner() -> Option<PathBuf> {
/// }
/// ```
pub fn cargo_home() -> io::Result<PathBuf> {
- let cwd = env::current_dir()?;
- cargo_home_with_cwd(&cwd)
+ env::cargo_home_with_env(&env::OS_ENV)
}
/// Returns the storage directory used by Cargo within `cwd`.
/// For more details, see [`cargo_home`](fn.cargo_home.html).
pub fn cargo_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> {
- match env::var_os("CARGO_HOME").filter(|h| !h.is_empty()) {
- Some(home) => {
- let home = PathBuf::from(home);
- if home.is_absolute() {
- Ok(home)
- } else {
- Ok(cwd.join(&home))
- }
- }
- _ => home_dir()
- .map(|p| p.join(".cargo"))
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not find cargo home dir")),
- }
+ env::cargo_home_with_cwd_env(&env::OS_ENV, cwd)
}
/// Returns the storage directory used by rustup, often knowns as
@@ -152,24 +139,11 @@ pub fn cargo_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> {
/// }
/// ```
pub fn rustup_home() -> io::Result<PathBuf> {
- let cwd = env::current_dir()?;
- rustup_home_with_cwd(&cwd)
+ env::rustup_home_with_env(&env::OS_ENV)
}
/// Returns the storage directory used by rustup within `cwd`.
/// For more details, see [`rustup_home`](fn.rustup_home.html).
pub fn rustup_home_with_cwd(cwd: &Path) -> io::Result<PathBuf> {
- match env::var_os("RUSTUP_HOME").filter(|h| !h.is_empty()) {
- Some(home) => {
- let home = PathBuf::from(home);
- if home.is_absolute() {
- Ok(home)
- } else {
- Ok(cwd.join(&home))
- }
- }
- _ => home_dir()
- .map(|d| d.join(".rustup"))
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "could not find rustup home dir")),
- }
+ env::rustup_home_with_cwd_env(&env::OS_ENV, cwd)
}
diff --git a/vendor/idna/.cargo-checksum.json b/vendor/idna/.cargo-checksum.json
index 01c1655f1..edf5c94ba 100644
--- a/vendor/idna/.cargo-checksum.json
+++ b/vendor/idna/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"fa141dcb135262e5fda9f680671699045326d96779bb1acf38d48c70c712bcdf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","benches/all.rs":"e734b9c9092ed66986725f86cfe90f3756cfddb058af308b796ba494f9beefc2","src/IdnaMappingTable.txt":"87d6553a4b86bc49dcade38bf26b745cd81800eb8af295dc3fb99b4729eaea38","src/lib.rs":"d61b2bfcf4265b9a41eedd1de33ab49ea615e3c06df944321b30c57950a85342","src/make_uts46_mapping_table.py":"917055fa841f813de2bcf79cc79b595da3d5551559ee768db8660ab77cb26c34","src/punycode.rs":"07edf5293bc384a164eebb01bc18fe3d4b2d009b4565a36b74a3030978ea6e04","src/uts46.rs":"40521a01e5b8c38667252d5b1e0141c5a71f63aeae2f451b986792984e633b09","src/uts46_mapping_table.rs":"942fff78147c61da942f5f3a7ff4e90f9d7a00a29285733ac3fc3357eb2ed06f","tests/IdnaTestV2.txt":"c6f3778b0545fd150c8063286c7f5adc901e16557eddccc3751213646d07593d","tests/punycode.rs":"e6fb978f48445d1525a6b97351c41c5393a1612a35f85b9a7f45b8794fce9aba","tests/punycode_tests.json":"3d4ac0cf25984c37b9ce197f5df680a0136f728fb8ec82bc76624e42139eb3a8","tests/tests.rs":"de7425a3e4e6e871255721107803704d1431246601fa9c87105224d88dfe60d6","tests/unit.rs":"be025a7d9bab3bd1ce134c87f9d848269e157b31ca5ba0ea03426c1ac736b69e","tests/uts46.rs":"ca91d48811d366fb9e32d7aa79cfda1261b93c271b6ed7fb5535de9a2500205b"},"package":"418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"} \ No newline at end of file
+{"files":{"Cargo.toml":"e8c4cbd1a352ce9085b80ac9fcaa8468a2da84b615adf01e719a3020a0279e4c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"76e972ac0f4ddb116e86e10100132a783931a596e7b9872eaa31be15cd4d751d","benches/all.rs":"e734b9c9092ed66986725f86cfe90f3756cfddb058af308b796ba494f9beefc2","src/IdnaMappingTable.txt":"87d6553a4b86bc49dcade38bf26b745cd81800eb8af295dc3fb99b4729eaea38","src/lib.rs":"498f127759fa79bda0d264f373ab7230cc2c73ef3a7b532d619c2a513abb53ff","src/make_uts46_mapping_table.py":"917055fa841f813de2bcf79cc79b595da3d5551559ee768db8660ab77cb26c34","src/punycode.rs":"07edf5293bc384a164eebb01bc18fe3d4b2d009b4565a36b74a3030978ea6e04","src/uts46.rs":"1a5604c32cf57b50e846b58aaaba94e685ff10975e9d6d82ae953f8cefe9c028","src/uts46_mapping_table.rs":"942fff78147c61da942f5f3a7ff4e90f9d7a00a29285733ac3fc3357eb2ed06f","tests/IdnaTestV2.txt":"c6f3778b0545fd150c8063286c7f5adc901e16557eddccc3751213646d07593d","tests/punycode.rs":"7eb6215fa4c84e6710682d48dffe19e490aea223b554b97c180a7d504b9e492a","tests/punycode_tests.json":"3d4ac0cf25984c37b9ce197f5df680a0136f728fb8ec82bc76624e42139eb3a8","tests/tests.rs":"d205a2bfb29dfee73e014faebd3207a55ef0d40121e6dbd52f5d611b37ac111e","tests/unit.rs":"be025a7d9bab3bd1ce134c87f9d848269e157b31ca5ba0ea03426c1ac736b69e","tests/uts46.rs":"06c97bf7dc20f5372b542fa46922d6dd63fe15e0aa34d799d08df9e3a241aa21"},"package":"e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"} \ No newline at end of file
diff --git a/vendor/idna/Cargo.toml b/vendor/idna/Cargo.toml
index 138a27162..fa2ed42bc 100644
--- a/vendor/idna/Cargo.toml
+++ b/vendor/idna/Cargo.toml
@@ -3,21 +3,21 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
+rust-version = "1.51"
name = "idna"
-version = "0.2.3"
+version = "0.3.0"
authors = ["The rust-url developers"]
autotests = false
description = "IDNA (Internationalizing Domain Names in Applications) and Punycode."
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/rust-url/"
[lib]
@@ -33,22 +33,21 @@ name = "unit"
[[bench]]
name = "all"
harness = false
-[dependencies.matches]
-version = "0.1"
[dependencies.unicode-bidi]
version = "0.3"
[dependencies.unicode-normalization]
version = "0.1.17"
+
[dev-dependencies.assert_matches]
version = "1.3"
[dev-dependencies.bencher]
version = "0.1"
-[dev-dependencies.rustc-test]
-version = "0.3"
-
[dev-dependencies.serde_json]
version = "1.0"
+
+[dev-dependencies.tester]
+version = "0.9"
diff --git a/vendor/idna/LICENSE-MIT b/vendor/idna/LICENSE-MIT
index 24de6b418..51d5dc7eb 100644
--- a/vendor/idna/LICENSE-MIT
+++ b/vendor/idna/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2016 The rust-url developers
+Copyright (c) 2013-2022 The rust-url developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/vendor/idna/src/lib.rs b/vendor/idna/src/lib.rs
index b87d4a15e..37d638741 100644
--- a/vendor/idna/src/lib.rs
+++ b/vendor/idna/src/lib.rs
@@ -32,8 +32,9 @@
//! > that minimizes the impact of this transition for client software,
//! > allowing client software to access domains that are valid under either system.
+#[cfg(test)]
#[macro_use]
-extern crate matches;
+extern crate assert_matches;
pub mod punycode;
mod uts46;
diff --git a/vendor/idna/src/uts46.rs b/vendor/idna/src/uts46.rs
index ad798055f..ec2fd0b10 100644
--- a/vendor/idna/src/uts46.rs
+++ b/vendor/idna/src/uts46.rs
@@ -156,7 +156,7 @@ fn passes_bidi(label: &str, is_bidi_domain: bool) -> bool {
// LTR label
BidiClass::L => {
// Rule 5
- while let Some(c) = chars.next() {
+ for c in chars.by_ref() {
if !matches!(
bidi_class(c),
BidiClass::L
@@ -318,51 +318,48 @@ fn check_validity(label: &str, config: Config, errors: &mut Errors) {
// V8: Bidi rules are checked inside `processing()`
}
-/// http://www.unicode.org/reports/tr46/#Processing
-#[allow(clippy::manual_strip)] // introduced in 1.45, MSRV is 1.36
-fn processing(
- domain: &str,
- config: Config,
- normalized: &mut String,
- output: &mut String,
-) -> Errors {
- // Weed out the simple cases: only allow all lowercase ASCII characters and digits where none
- // of the labels start with PUNYCODE_PREFIX and labels don't start or end with hyphen.
- let (mut prev, mut simple, mut puny_prefix) = ('?', !domain.is_empty(), 0);
+// Detect simple cases: all lowercase ASCII characters and digits where none
+// of the labels start with PUNYCODE_PREFIX and labels don't start or end with hyphen.
+fn is_simple(domain: &str) -> bool {
+ if domain.is_empty() {
+ return false;
+ }
+ let (mut prev, mut puny_prefix) = ('?', 0);
for c in domain.chars() {
if c == '.' {
if prev == '-' {
- simple = false;
- break;
+ return false;
}
puny_prefix = 0;
continue;
} else if puny_prefix == 0 && c == '-' {
- simple = false;
- break;
+ return false;
} else if puny_prefix < 5 {
if c == ['x', 'n', '-', '-'][puny_prefix] {
puny_prefix += 1;
if puny_prefix == 4 {
- simple = false;
- break;
+ return false;
}
} else {
puny_prefix = 5;
}
}
if !c.is_ascii_lowercase() && !c.is_ascii_digit() {
- simple = false;
- break;
+ return false;
}
prev = c;
}
- if simple {
- output.push_str(domain);
- return Errors::default();
- }
+ true
+}
+/// http://www.unicode.org/reports/tr46/#Processing
+fn processing(
+ domain: &str,
+ config: Config,
+ normalized: &mut String,
+ output: &mut String,
+) -> Errors {
normalized.clear();
let mut errors = Errors::default();
let offset = output.len();
@@ -384,8 +381,8 @@ fn processing(
output.push('.');
}
first = false;
- if label.starts_with(PUNYCODE_PREFIX) {
- match decoder.decode(&label[PUNYCODE_PREFIX.len()..]) {
+ if let Some(remainder) = label.strip_prefix(PUNYCODE_PREFIX) {
+ match decoder.decode(remainder) {
Ok(decode) => {
let start = output.len();
output.extend(decode);
@@ -396,7 +393,7 @@ fn processing(
}
if !errors.is_err() {
- if !is_nfc(&decoded_label) {
+ if !is_nfc(decoded_label) {
errors.nfc = true;
} else {
check_validity(decoded_label, non_transitional, &mut errors);
@@ -448,11 +445,13 @@ impl Idna {
}
}
- /// http://www.unicode.org/reports/tr46/#ToASCII
- #[allow(clippy::wrong_self_convention)]
- pub fn to_ascii<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
- let mut errors = processing(domain, self.config, &mut self.normalized, &mut self.output);
-
+ pub fn to_ascii_inner(&mut self, domain: &str, out: &mut String) -> Errors {
+ if is_simple(domain) {
+ out.push_str(domain);
+ return Errors::default();
+ }
+ let mut errors = processing(domain, self.config, &mut self.normalized, out);
+ self.output = std::mem::replace(out, String::with_capacity(out.len()));
let mut first = true;
for label in self.output.split('.') {
if !first {
@@ -471,6 +470,13 @@ impl Idna {
}
}
}
+ errors
+ }
+
+ /// http://www.unicode.org/reports/tr46/#ToASCII
+ #[allow(clippy::wrong_self_convention)]
+ pub fn to_ascii<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
+ let mut errors = self.to_ascii_inner(domain, out);
if self.config.verify_dns_length {
let domain = if out.ends_with('.') {
@@ -492,6 +498,10 @@ impl Idna {
/// http://www.unicode.org/reports/tr46/#ToUnicode
#[allow(clippy::wrong_self_convention)]
pub fn to_unicode<'a>(&'a mut self, domain: &str, out: &mut String) -> Result<(), Errors> {
+ if is_simple(domain) {
+ out.push_str(domain);
+ return Errors::default().into();
+ }
processing(domain, self.config, &mut self.normalized, out).into()
}
}
@@ -555,7 +565,7 @@ impl Config {
/// http://www.unicode.org/reports/tr46/#ToASCII
pub fn to_ascii(self, domain: &str) -> Result<String, Errors> {
- let mut result = String::new();
+ let mut result = String::with_capacity(domain.len());
let mut codec = Idna::new(self);
codec.to_ascii(domain, &mut result).map(|()| result)
}
diff --git a/vendor/idna/tests/punycode.rs b/vendor/idna/tests/punycode.rs
index c0123c639..1a51cbc92 100644
--- a/vendor/idna/tests/punycode.rs
+++ b/vendor/idna/tests/punycode.rs
@@ -63,9 +63,9 @@ pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
};
add_test(
test_name,
- TestFn::dyn_test_fn(move || {
+ TestFn::DynTestFn(Box::new(move || {
one_test(get_string(&o, "decoded"), get_string(&o, "encoded"))
- }),
+ })),
)
}
_ => panic!(),
diff --git a/vendor/idna/tests/tests.rs b/vendor/idna/tests/tests.rs
index 5f0f8cde3..0704c81c1 100644
--- a/vendor/idna/tests/tests.rs
+++ b/vendor/idna/tests/tests.rs
@@ -1,4 +1,4 @@
-use rustc_test as test;
+use tester as test;
mod punycode;
mod uts46;
@@ -8,12 +8,18 @@ fn main() {
{
let mut add_test = |name, run| {
tests.push(test::TestDescAndFn {
- desc: test::TestDesc::new(test::DynTestName(name)),
+ desc: test::TestDesc {
+ name: test::DynTestName(name),
+ ignore: false,
+ should_panic: test::ShouldPanic::No,
+ allow_fail: false,
+ test_type: test::TestType::Unknown,
+ },
testfn: run,
})
};
punycode::collect_tests(&mut add_test);
uts46::collect_tests(&mut add_test);
}
- test::test_main(&std::env::args().collect::<Vec<_>>(), tests)
+ test::test_main(&std::env::args().collect::<Vec<_>>(), tests, None)
}
diff --git a/vendor/idna/tests/uts46.rs b/vendor/idna/tests/uts46.rs
index 72b5bcec7..bd402ce97 100644
--- a/vendor/idna/tests/uts46.rs
+++ b/vendor/idna/tests/uts46.rs
@@ -8,6 +8,7 @@
use crate::test::TestFn;
use std::char;
+use std::fmt::Write;
use idna::Errors;
@@ -25,10 +26,10 @@ pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
};
let mut pieces = line.split(';').map(|x| x.trim()).collect::<Vec<&str>>();
- let source = unescape(&pieces.remove(0));
+ let source = unescape(pieces.remove(0));
// ToUnicode
- let mut to_unicode = unescape(&pieces.remove(0));
+ let mut to_unicode = unescape(pieces.remove(0));
if to_unicode.is_empty() {
to_unicode = source.clone();
}
@@ -65,7 +66,7 @@ pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
let test_name = format!("UTS #46 line {}", i + 1);
add_test(
test_name,
- TestFn::dyn_test_fn(move || {
+ TestFn::DynTestFn(Box::new(move || {
let config = idna::Config::default()
.use_std3_ascii_rules(true)
.verify_dns_length(true)
@@ -109,7 +110,7 @@ pub fn collect_tests<F: FnMut(String, TestFn)>(add_test: &mut F) {
to_ascii_t_result,
|e| e.starts_with('C') || e == "V2",
);
- }),
+ })),
)
}
}
@@ -160,8 +161,8 @@ fn unescape(input: &str) -> String {
match char::from_u32(((c1 * 16 + c2) * 16 + c3) * 16 + c4) {
Some(c) => output.push(c),
None => {
- output
- .push_str(&format!("\\u{:X}{:X}{:X}{:X}", c1, c2, c3, c4));
+ write!(&mut output, "\\u{:X}{:X}{:X}{:X}", c1, c2, c3, c4)
+ .expect("Could not write to output");
}
};
}
diff --git a/vendor/itertools/.cargo-checksum.json b/vendor/itertools/.cargo-checksum.json
index cbed44086..a4f2873c5 100644
--- a/vendor/itertools/.cargo-checksum.json
+++ b/vendor/itertools/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"7f54a6e7b78dae273c5352ca3472c8e7d4996d42879ffbb8430df37c020c8a6a","Cargo.lock":"74a768ea98da273b20c181728d646b0e59ece19d5738f983ee8804f35a5e6af4","Cargo.toml":"3934329298921fda64203f05a3b194b3a4f009e85fdcb78b46c8a743176e1059","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"6ba6696202f5a848c40f0cdef0ae9282a8edd45b44e5d901160930534427e62d","benches/bench1.rs":"bb06f39db0544b1380cd4929139ccf521a9eecab7ca3f910b9499f965ec0a047","benches/combinations.rs":"51523ee1ca438a56f14711f0b04ee943895062d35859fbe23a2714d2fca3289d","benches/combinations_with_replacement.rs":"11f29160652a2d90ce7ca4b1c339c4457888ab6867e2456ce1c62e3adf9be737","benches/extra/mod.rs":"6ca290d72302a1945078621610b5788060b0de29639decebbdc557a80044aa97","benches/extra/zipslices.rs":"3db9764c21536c541cdf3f93ba2e34f6ab63dd12a9149aa5bd8a4524778176f1","benches/fold_specialization.rs":"5a517bbe29d366a15f6f751660e17ab1aa3e7b21552a1983048c662e34f0d69e","benches/powerset.rs":"6fd9d69a3483b37dc2411f99fb4efa6131577696f2dbdc8d1de9e4d7642fe3a3","benches/tree_fold1.rs":"539232e74f9aaea295a42069ac5af707811e90dc1c71c6e0a9064ffc731999de","benches/tuple_combinations.rs":"16366158743307a0289fc1df423a3cec45009807d410a9fe9922d5b6f8b7d002","benches/tuples.rs":"5a620783ae203e9ff9623d10d2c7fe9911d8b6c811cbad7613afa30e390c759d","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"1b465ed6a417180913104bc95a545fd9d1a3d67d121871ab737ad87e31b8be37","src/adaptors/coalesce.rs":"11d88d64fc1e3e80fc847cfbff7627e7164a1621e2e989afdd0730f2f3172dca","src/adaptors/map.rs":"241971e856e468d71323071fb4a09867fbcedb83877320be132dc03516fe60e8","src/adaptors/mod.rs":"be7eab70869f4fcf5e0e441ba7646759a39ec86952d54a3df22b60b919572ec3","src/adaptors/multi_product.rs":"742a8a42f2cc2b3840b0397639cb57d87deac8483127012c1f9a0be9c02ff1f1","src/combinations.rs":"fb25babb459389093f886721016c72bf9f00e51d02735f638d871bb3a447ffd0","src/combinations_with_replacement.rs":"3cb719c61a39af0c7e73139e0d1a94e716b69cbe6b046e3ca39150c9995ec7ff","src/concat_impl.rs":"7e14b7c1ad592a40373aec1140ed4cecc04462a9724a8ee663f3e757f457c587","src/cons_tuples_impl.rs":"c253d03b861831c01d62cacc57b49715ee62f6171e69f6886bb5a6ca0863bc3a","src/diff.rs":"a7800e9ce7a87b53ebe2338481335751fb43d44fa6a1ca719aceaaab40e5c8fe","src/duplicates_impl.rs":"663bd10f0a8f49ce0a58ba1c488a70684b61f9636232310fe8ffa2f356961e94","src/either_or_both.rs":"4f17729e9a28508cf60734355d748399c9b05d4df970b75a23e41fe462171464","src/exactly_one_err.rs":"3a72023c689a27fa9ed5e11ff2e32638d548bd327b00c642d5ee1c79e9300f75","src/flatten_ok.rs":"294f313d6e4e34c4e4d03facfd8a15ba92742ba94e609386d76e75d725d4eb14","src/format.rs":"a8192d85c0f9de8e633c202456e3cde0f3bc50f19b6bd8a4b2cfa3ef5123de1a","src/free.rs":"75189fd779017ee2c083e3e75982f1b7d4b51fae99b105a2b2d0e3d2d16dda4f","src/group_map.rs":"f7b02c964f63505d3e36280cfdc1755e05287714201efe983dacf702eee61434","src/groupbylazy.rs":"69829a5990c666cf9dfc7330a1765e0ecb6901a4572f8cda86e81f391af62283","src/grouping_map.rs":"a9f48ed6ba6bf13b16a037f8aaf608c67c6b68dc8949702a07bfeea41471e38e","src/impl_macros.rs":"f3f0865c825dfb8396e0897b9f087c6220099fade36a67e113f5af9102e1347e","src/intersperse.rs":"12c486feaec66931b62007ffd551c72d711963a15019de882d7a4aff71f1c0ae","src/k_smallest.rs":"603eb34314c01769ff7f6def2a24cf7a7b38507e6f3658b7aafc23a3b2e9b322","src/kmerge_impl.rs":"ff34c08b641276df3fcb20874925e6fe0dbf82f6db36f1de17b07b5991b373d7","src/lazy_buffer.rs":"2426f171a839eef12501086ba8da270db46b51749e68562aecc7623d56995c3f","src/lib.rs":"83d043c8af42f7b4b66c6fc5012b8399acd44de44c8d522f7cc4ae806d4462ca","src/merge_join.rs":"8a12376800eb31b124123b0590b302d08aaca71c64bcef89c1aef5d29837038a","src/minmax.rs":"96d3897c28c8c63284d4729becc9ada6855e0953cac6e1bd35cf6f38c50b0ec0","src/multipeek_impl.rs":"8e1ebb6359bd43387c7b6f65e6612845e5673418a39c7bcbdb2c52b50a2d75f5","src/pad_tail.rs":"404e611a3e3e698f7d4eef97a21c3aacd677cadb1f92a48b43bd1f83f183ab10","src/peek_nth.rs":"6a0a51f2f373ce14d3d58595c46464878a14976bf00841a7396c03f9f9ab07ac","src/peeking_take_while.rs":"34985239af5a7bef38fecb1e00f5830f1921b04e6f6e5d25456e701cc3b59e35","src/permutations.rs":"b655e43e78e98a22c3f2be2420d8aa378fc6633ee7cf8b7c6a9630ac882d68a9","src/powerset.rs":"e0ee6b1316b4dd314c1e81502b90ae8113e1cda12168322520c5a65410e584b2","src/process_results_impl.rs":"9ed7fa46c8316238272ef47577387a386c1a109b50377dd3caf4291b6587cb73","src/put_back_n_impl.rs":"821e047fecd6ca0036290029f4febe7638a3abf1faa05e1e747a3bf9d80ff464","src/rciter_impl.rs":"ed4cc5da423e001ed142ed3925a32110189d6e9f5c77606c3fa52762f111f2f6","src/repeatn.rs":"bfc8f9145c9d8a3ea651f012b7d5a8d2fbbcbefdee76eafd098d02e7c54cda90","src/size_hint.rs":"d51d0db24a30c432cb13a2b62d9afb67c3e109e75ab32232f7777803391bcc11","src/sources.rs":"61637f32c2cea2290ecfc1980c0b2d0f68463839ac09bd81006f8258ab8ecaae","src/tee.rs":"665832aa547389a420c3441470ff2494249f0ed2841be0c6a578367fe9dbd381","src/tuple_impl.rs":"039433eddafb0c5f2e4d125035304f5e5f04dd7b537e497af291e40bdb63054e","src/unique_impl.rs":"b5c30a9ca2790e7818f53680aeacee5997c09426fb4a28d2497a8f8414b19e67","src/unziptuple.rs":"ded1fd651d16c6629a49aa68386627addb4ade1ee32bc95929a16bab4f2332d5","src/with_position.rs":"c8a9b3476b3b90986b004a8877c19ff54b4c6800c5ac7ca1458d914036dacfe9","src/zip_eq_impl.rs":"4a41dc6dfe99359585d50ce648bdc85f15276c602048872b1d152e90841d8cad","src/zip_longest.rs":"f7cf5fffc3ca053ee80b410a05b27de1a475021f6de3181aea981010d7e8453f","src/ziptuple.rs":"b3606e1231ac706836cfca67b5b19a88c111a82f2b8649bec72d08b3aa81d783","tests/adaptors_no_collect.rs":"dc69691bed895e6fd3922942ccc7d424a5247b0f79dea74cf8e2f8a8af0bd491","tests/flatten_ok.rs":"b7894874132918b8229c7150b2637511d8e3e14197d8eeb9382d46b2a514efa2","tests/macros_hygiene.rs":"522afa0106e3f11a5149e9218f89c2329e405546d2ef0ea756d6a27e8a0e9ca3","tests/merge_join.rs":"b08c4ee6529d234c68d411a413b8781455d18a1eab17872d1828bb75a4fcf79b","tests/peeking_take_while.rs":"4b1c394e44a9ef9bc0de707ae080b45803db722f79834c20f15b826d7c3f1f2e","tests/quick.rs":"c975132c0a27b07494af03fa978f748c15178f9c9a8d2c647af9b47202f6dac4","tests/specializations.rs":"7a6428a0dbf826bc6adf701803e97283ca6efda9a39595642fb1070c085d52c0","tests/test_core.rs":"cc31f6623ae2e4db1efca649da554c47a60cc13ead5a7a44cfd2265a34344553","tests/test_std.rs":"53bcf0b11e853df71ad44286bff687e7d6f2040bcf800d64ff4d13448dae02c9","tests/tuples.rs":"014e4da776174bfe923270e2a359cd9c95b372fce4b952b8138909d6e2c52762","tests/zip.rs":"4f840d5cdd9021511d8e639d87152bd08b5d12f6192e88072688b0b9100ac912"},"package":"a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"ed6c781d541c40d4a19eaecd794cadebb94b3f4d51e32367803542c88f0457ee","Cargo.toml":"6dcbab25126c0cdf64f5089156de0d4346914c6d47c557d370b8e20e039ca7d3","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"3acfeb07424200ae70bf571ef63a96bae954c298bddf447c9bea0ea9394825cc","benches/bench1.rs":"bb06f39db0544b1380cd4929139ccf521a9eecab7ca3f910b9499f965ec0a047","benches/combinations.rs":"51523ee1ca438a56f14711f0b04ee943895062d35859fbe23a2714d2fca3289d","benches/combinations_with_replacement.rs":"11f29160652a2d90ce7ca4b1c339c4457888ab6867e2456ce1c62e3adf9be737","benches/extra/mod.rs":"6ca290d72302a1945078621610b5788060b0de29639decebbdc557a80044aa97","benches/extra/zipslices.rs":"40e9f68a7c00f8429193fca463caef18851fa49b33355cc136bad3ccc840d655","benches/fold_specialization.rs":"5a517bbe29d366a15f6f751660e17ab1aa3e7b21552a1983048c662e34f0d69e","benches/powerset.rs":"6fd9d69a3483b37dc2411f99fb4efa6131577696f2dbdc8d1de9e4d7642fe3a3","benches/tree_fold1.rs":"539232e74f9aaea295a42069ac5af707811e90dc1c71c6e0a9064ffc731999de","benches/tuple_combinations.rs":"16366158743307a0289fc1df423a3cec45009807d410a9fe9922d5b6f8b7d002","benches/tuples.rs":"5a620783ae203e9ff9623d10d2c7fe9911d8b6c811cbad7613afa30e390c759d","clippy.toml":"33ffb83bbddb772575b3aa565b7136a8158ee386c216ffc2588fed9e83fa3826","examples/iris.data":"596ffd580471ca4d4880f8e439c7281f3b50d8249a5960353cb200b1490f63a0","examples/iris.rs":"1b465ed6a417180913104bc95a545fd9d1a3d67d121871ab737ad87e31b8be37","src/adaptors/coalesce.rs":"a0073325d40f297d29101538d18a267aef81889a999338dc09cb43a31cb4ec8b","src/adaptors/map.rs":"241971e856e468d71323071fb4a09867fbcedb83877320be132dc03516fe60e8","src/adaptors/mod.rs":"7f3bd7d011a348ce5e4bea486ef2e6346b64c7fe27540334d56d3f147f981d59","src/adaptors/multi_product.rs":"bb43e6dce68c815c21006d5b01c56e038d54b0c3bb8ee6bb8a4de11e2952c7ad","src/combinations.rs":"fb25babb459389093f886721016c72bf9f00e51d02735f638d871bb3a447ffd0","src/combinations_with_replacement.rs":"463011a574facbdd84278386b533a90e4dd517f0417e05adb82d182049db1f50","src/concat_impl.rs":"03b1ed61cbed242c286c3c4c5c848dbd57e02ab83fcef264f3a592b58107f324","src/cons_tuples_impl.rs":"c253d03b861831c01d62cacc57b49715ee62f6171e69f6886bb5a6ca0863bc3a","src/diff.rs":"a7800e9ce7a87b53ebe2338481335751fb43d44fa6a1ca719aceaaab40e5c8fe","src/duplicates_impl.rs":"f62fe4b642f501f785721ce5a505cf622a771e457210726dd0fb8b30be7ebbbc","src/either_or_both.rs":"76b13fbfac6bc959b4c1d8b7c99ce51726e95f994ca5429477e523a3d3950e4a","src/exactly_one_err.rs":"aa50081f6a31b5109b30e3ed305e3ec2413c6908dedc8990ec5378a99cee2b39","src/extrema_set.rs":"2a25b0b86eed2fd5d05622d591a3085cab823973d450816c2c3b8cb76e9c187e","src/flatten_ok.rs":"fe209fd886ecd9cb98d99625aa0c7274af7e644eff4a10de15b4dec8bbbc934a","src/format.rs":"a8192d85c0f9de8e633c202456e3cde0f3bc50f19b6bd8a4b2cfa3ef5123de1a","src/free.rs":"dfc57b7f56a08d4986a96b679018b41346576a7a34b668e008cc01109e728750","src/group_map.rs":"f7b02c964f63505d3e36280cfdc1755e05287714201efe983dacf702eee61434","src/groupbylazy.rs":"4f2181c022a45ff8444597708861fc6863eceb6f7555ea81cf3eeba19b492971","src/grouping_map.rs":"cbc45ac563345c96f3ac50c78f73c83d870523436a7ab88c1c9a685d204461d3","src/impl_macros.rs":"4f829b458873bed556f1aff2ae4e88dbd576766e2b5bcc07ff3ac8756758e6f4","src/intersperse.rs":"b9717242495846a4a979c95d93d5681caccb7c07a0d889eab763ad3d49a46125","src/k_smallest.rs":"603eb34314c01769ff7f6def2a24cf7a7b38507e6f3658b7aafc23a3b2e9b322","src/kmerge_impl.rs":"a347b0f6fa7715afd8a54d85ce139ed5b14c9e58a16c2b3648f5b288fdb5375f","src/lazy_buffer.rs":"834f6ef7fdf9f00c8a6329beb38eaefb706847ceeec309c221dce705c2c1e05b","src/lib.rs":"fadb0045279aafe8e8cccb45fadc383c7b358197b83c9c38fba87ada4cb2f84a","src/merge_join.rs":"1016113f6c983a9498bae5dc0570190437e1357b3333f6e19ea95c88599a1225","src/minmax.rs":"96d3897c28c8c63284d4729becc9ada6855e0953cac6e1bd35cf6f38c50b0ec0","src/multipeek_impl.rs":"35162bca4456bfa20a08e8d40e4d1cc6783dc662778789fdcded60371e975122","src/pad_tail.rs":"04be2ca73abb85815b06b5524c99d6feb2919180c486a4646f9cc6c87462f67b","src/peek_nth.rs":"6a0a51f2f373ce14d3d58595c46464878a14976bf00841a7396c03f9f9ab07ac","src/peeking_take_while.rs":"2b1b77c8882be32cfd76e973d303aa62f73370efd470c60764add0cdcca524d5","src/permutations.rs":"97831e7e26904c3cae68c97e74f7c6981ceb2fb2f2217282a0e5e54083a565fc","src/powerset.rs":"e0ee6b1316b4dd314c1e81502b90ae8113e1cda12168322520c5a65410e584b2","src/process_results_impl.rs":"9ed7fa46c8316238272ef47577387a386c1a109b50377dd3caf4291b6587cb73","src/put_back_n_impl.rs":"821e047fecd6ca0036290029f4febe7638a3abf1faa05e1e747a3bf9d80ff464","src/rciter_impl.rs":"5b156082ef2d25a94a4ad01d94cba2813c4b3e72e212515a8ad0fc8588f8045d","src/repeatn.rs":"bfc8f9145c9d8a3ea651f012b7d5a8d2fbbcbefdee76eafd098d02e7c54cda90","src/size_hint.rs":"021e57aad7df8f1e70ef588e9e9b8a1695aab183b1098f1848561f96c5dc9bcb","src/sources.rs":"61637f32c2cea2290ecfc1980c0b2d0f68463839ac09bd81006f8258ab8ecaae","src/tee.rs":"665832aa547389a420c3441470ff2494249f0ed2841be0c6a578367fe9dbd381","src/tuple_impl.rs":"00a9b61942425fb477b9691c3348646c0f9f534ff94f6321027f38c61ce2478c","src/unique_impl.rs":"3b89cdd668b74cc0a0eabb1522489e2305a0d2d8da25d6a1884e8626bbdb5959","src/unziptuple.rs":"84b50e5d29b9ddbf21a46a1cc2fd7877729c7f7da9bdc8ae1966dbaf2d2f6f60","src/with_position.rs":"c8a9b3476b3b90986b004a8877c19ff54b4c6800c5ac7ca1458d914036dacfe9","src/zip_eq_impl.rs":"4a41dc6dfe99359585d50ce648bdc85f15276c602048872b1d152e90841d8cad","src/zip_longest.rs":"f7cf5fffc3ca053ee80b410a05b27de1a475021f6de3181aea981010d7e8453f","src/ziptuple.rs":"7f9df12bf6556f382bbd4ad8cf17eb8b60c1c47fadbce016141133ba0f3384a1","tests/adaptors_no_collect.rs":"f459f36d54f5d475b2b2e83f5a1c98109c15062756ae822fa379486f3eeed666","tests/flatten_ok.rs":"b7894874132918b8229c7150b2637511d8e3e14197d8eeb9382d46b2a514efa2","tests/macros_hygiene.rs":"522afa0106e3f11a5149e9218f89c2329e405546d2ef0ea756d6a27e8a0e9ca3","tests/merge_join.rs":"b08c4ee6529d234c68d411a413b8781455d18a1eab17872d1828bb75a4fcf79b","tests/peeking_take_while.rs":"4b1c394e44a9ef9bc0de707ae080b45803db722f79834c20f15b826d7c3f1f2e","tests/quick.rs":"6fcc0649b9270f024b169b1f499dd4cc7fecb0c9aec0dfc155b264916cc626e7","tests/specializations.rs":"fdd16dc663330033fedcc478609b393d4aa369dc07dc8cda31a75219fb793087","tests/test_core.rs":"32576ba90aa8e5db985b6e6ffe30e3046bc6a11d392db8f6b4bdd2ba48d9b24d","tests/test_std.rs":"f28a78a1912c950e7c37be1e82867e70dc585d60afecdebc7a97965194eee8e6","tests/tuples.rs":"014e4da776174bfe923270e2a359cd9c95b372fce4b952b8138909d6e2c52762","tests/zip.rs":"99af365fe6054ef1c6089d3e604e34da8fea66e55861ae4be9e7336ec8de4b56"},"package":"b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"} \ No newline at end of file
diff --git a/vendor/itertools/CHANGELOG.md b/vendor/itertools/CHANGELOG.md
index 5e2032c4c..d2b40b5db 100644
--- a/vendor/itertools/CHANGELOG.md
+++ b/vendor/itertools/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## 0.10.4
+ - Add `EitherOrBoth::or` and `EitherOrBoth::or_else` (#593)
+ - Add `min_set`, `max_set` et al. (#613, #323)
+ - Use `either/use_std` (#628)
+ - Documentation fixes (#612, #625, #632, #633, #634, #638)
+ - Code maintenance (#623, #624, #627, #630)
+
## 0.10.2
- Add `Itertools::multiunzip` (#362, #565)
- Add `intersperse` and `intersperse_with` free functions (#555)
diff --git a/vendor/itertools/Cargo.lock b/vendor/itertools/Cargo.lock
deleted file mode 100644
index fecfb2070..000000000
--- a/vendor/itertools/Cargo.lock
+++ /dev/null
@@ -1,726 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[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.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
-
-[[package]]
-name = "bitflags"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-
-[[package]]
-name = "bstr"
-version = "0.2.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
-dependencies = [
- "lazy_static",
- "memchr",
- "regex-automata",
- "serde",
-]
-
-[[package]]
-name = "bumpalo"
-version = "3.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
-
-[[package]]
-name = "cast"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57cdfa5d50aad6cb4d44dcab6101a7f79925bd59d82ca42f38a9856a28865374"
-dependencies = [
- "rustc_version",
-]
-
-[[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 = [
- "bitflags",
- "textwrap",
- "unicode-width",
-]
-
-[[package]]
-name = "criterion"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
-dependencies = [
- "atty",
- "cast",
- "clap",
- "criterion-plot",
- "csv",
- "itertools 0.10.0",
- "lazy_static",
- "num-traits",
- "oorandom",
- "plotters",
- "rayon",
- "regex",
- "serde",
- "serde_cbor",
- "serde_derive",
- "serde_json",
- "tinytemplate",
- "walkdir",
-]
-
-[[package]]
-name = "criterion-plot"
-version = "0.4.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d"
-dependencies = [
- "cast",
- "itertools 0.9.0",
-]
-
-[[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.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
-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-utils"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
-dependencies = [
- "cfg-if",
- "lazy_static",
-]
-
-[[package]]
-name = "csv"
-version = "1.1.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
-dependencies = [
- "bstr",
- "csv-core",
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "csv-core"
-version = "0.1.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "either"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
-
-[[package]]
-name = "getrandom"
-version = "0.1.16"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "half"
-version = "1.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "itertools"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319"
-dependencies = [
- "either",
-]
-
-[[package]]
-name = "itertools"
-version = "0.10.3"
-dependencies = [
- "criterion",
- "either",
- "paste",
- "permutohedron",
- "quickcheck",
- "rand",
-]
-
-[[package]]
-name = "itoa"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
-
-[[package]]
-name = "js-sys"
-version = "0.3.51"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062"
-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.96"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5600b4e6efc5421841a2138a6b082e07fe12f9aaa12783d50e5d13325b26b4fc"
-
-[[package]]
-name = "log"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "memchr"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
-
-[[package]]
-name = "memoffset"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
-dependencies = [
- "autocfg",
-]
-
-[[package]]
-name = "num-traits"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
-dependencies = [
- "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 = "oorandom"
-version = "11.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
-
-[[package]]
-name = "paste"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58"
-
-[[package]]
-name = "permutohedron"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b687ff7b5da449d39e418ad391e5e08da53ec334903ddbb921db208908fc372c"
-
-[[package]]
-name = "pest"
-version = "2.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
-dependencies = [
- "ucd-trie",
-]
-
-[[package]]
-name = "plotters"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
-dependencies = [
- "num-traits",
- "plotters-backend",
- "plotters-svg",
- "wasm-bindgen",
- "web-sys",
-]
-
-[[package]]
-name = "plotters-backend"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
-
-[[package]]
-name = "plotters-svg"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
-dependencies = [
- "plotters-backend",
-]
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "quickcheck"
-version = "0.9.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
-dependencies = [
- "rand",
- "rand_core",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom",
- "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
-dependencies = [
- "rand_core",
-]
-
-[[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 = [
- "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-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "rustc_version"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
-dependencies = [
- "semver",
-]
-
-[[package]]
-name = "ryu"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
-
-[[package]]
-name = "same-file"
-version = "1.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
-name = "semver"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
-dependencies = [
- "pest",
-]
-
-[[package]]
-name = "serde"
-version = "1.0.126"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
-
-[[package]]
-name = "serde_cbor"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
-dependencies = [
- "half",
- "serde",
-]
-
-[[package]]
-name = "serde_derive"
-version = "1.0.126"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "serde_json"
-version = "1.0.64"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
-dependencies = [
- "itoa",
- "ryu",
- "serde",
-]
-
-[[package]]
-name = "syn"
-version = "1.0.72"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-xid",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "tinytemplate"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
-dependencies = [
- "serde",
- "serde_json",
-]
-
-[[package]]
-name = "ucd-trie"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
-
-[[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
-
-[[package]]
-name = "walkdir"
-version = "2.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
-dependencies = [
- "same-file",
- "winapi",
- "winapi-util",
-]
-
-[[package]]
-name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasm-bindgen"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900"
-dependencies = [
- "bumpalo",
- "lazy_static",
- "log",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f"
-
-[[package]]
-name = "web-sys"
-version = "0.3.51"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582"
-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"
diff --git a/vendor/itertools/Cargo.toml b/vendor/itertools/Cargo.toml
index 525cae5f3..40be7e48f 100644
--- a/vendor/itertools/Cargo.toml
+++ b/vendor/itertools/Cargo.toml
@@ -13,7 +13,7 @@
[package]
edition = "2018"
name = "itertools"
-version = "0.10.3"
+version = "0.10.5"
authors = ["bluss"]
exclude = ["/bors.toml"]
description = "Extra iterator adaptors, iterator methods, free functions, and macros."
@@ -85,4 +85,4 @@ version = "0.7"
[features]
default = ["use_std"]
use_alloc = []
-use_std = ["use_alloc"]
+use_std = ["use_alloc", "either/use_std"]
diff --git a/vendor/itertools/README.md b/vendor/itertools/README.md
index 4cc3f8fd3..a911127f4 100644
--- a/vendor/itertools/README.md
+++ b/vendor/itertools/README.md
@@ -11,7 +11,7 @@ How to use with Cargo:
```toml
[dependencies]
-itertools = "0.10.2"
+itertools = "0.10.5"
```
How to use in your crate:
diff --git a/vendor/itertools/benches/extra/zipslices.rs b/vendor/itertools/benches/extra/zipslices.rs
index 8bf3967f5..633be5906 100644
--- a/vendor/itertools/benches/extra/zipslices.rs
+++ b/vendor/itertools/benches/extra/zipslices.rs
@@ -3,7 +3,7 @@ use std::cmp;
// Note: There are different ways to implement ZipSlices.
// This version performed the best in benchmarks.
//
-// I also implemented a version with three pointes (tptr, tend, uptr),
+// I also implemented a version with three pointers (tptr, tend, uptr),
// that mimiced slice::Iter and only checked bounds by using tptr == tend,
// but that was inferior to this solution.
diff --git a/vendor/itertools/clippy.toml b/vendor/itertools/clippy.toml
new file mode 100644
index 000000000..0a5485386
--- /dev/null
+++ b/vendor/itertools/clippy.toml
@@ -0,0 +1 @@
+msrv = "1.36.0"
diff --git a/vendor/itertools/src/adaptors/coalesce.rs b/vendor/itertools/src/adaptors/coalesce.rs
index b1aff6e27..3df7cc582 100644
--- a/vendor/itertools/src/adaptors/coalesce.rs
+++ b/vendor/itertools/src/adaptors/coalesce.rs
@@ -3,6 +3,7 @@ use std::iter::FusedIterator;
use crate::size_hint;
+#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct CoalesceBy<I, F, T>
where
I: Iterator,
@@ -86,7 +87,6 @@ impl<I: Iterator, F: CoalescePredicate<I::Item, T>, T> FusedIterator for Coalesc
/// An iterator adaptor that may join together adjacent elements.
///
/// See [`.coalesce()`](crate::Itertools::coalesce) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type Coalesce<I, F> = CoalesceBy<I, F, <I as Iterator>::Item>;
impl<F, Item, T> CoalescePredicate<Item, T> for F
@@ -113,7 +113,6 @@ where
/// An iterator adaptor that removes repeated duplicates, determining equality using a comparison function.
///
/// See [`.dedup_by()`](crate::Itertools::dedup_by) or [`.dedup()`](crate::Itertools::dedup) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type DedupBy<I, Pred> = CoalesceBy<I, DedupPred2CoalescePred<Pred>, <I as Iterator>::Item>;
#[derive(Clone)]
@@ -186,7 +185,6 @@ where
///
/// See [`.dedup_by_with_count()`](crate::Itertools::dedup_by_with_count) or
/// [`.dedup_with_count()`](crate::Itertools::dedup_with_count) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type DedupByWithCount<I, Pred> =
CoalesceBy<I, DedupPredWithCount2CoalescePred<Pred>, (usize, <I as Iterator>::Item)>;
diff --git a/vendor/itertools/src/adaptors/mod.rs b/vendor/itertools/src/adaptors/mod.rs
index 2010f535b..1695bbd65 100644
--- a/vendor/itertools/src/adaptors/mod.rs
+++ b/vendor/itertools/src/adaptors/mod.rs
@@ -35,9 +35,7 @@ pub struct Interleave<I, J> {
/// Create an iterator that interleaves elements in `i` and `j`.
///
-/// [`IntoIterator`] enabled version of `i.interleave(j)`.
-///
-/// See [`.interleave()`](crate::Itertools::interleave) for more information.
+/// [`IntoIterator`] enabled version of `[Itertools::interleave]`.
pub fn interleave<I, J>(i: I, j: J) -> Interleave<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where I: IntoIterator,
J: IntoIterator<Item = I::Item>
@@ -210,7 +208,7 @@ impl<I> PutBack<I>
/// If a value is already in the put back slot, it is overwritten.
#[inline]
pub fn put_back(&mut self, x: I::Item) {
- self.top = Some(x)
+ self.top = Some(x);
}
}
@@ -329,12 +327,7 @@ impl<I, J> Iterator for Product<I, J>
}
Some(x) => x
};
- match self.a_cur {
- None => None,
- Some(ref a) => {
- Some((a.clone(), elt_b))
- }
- }
+ self.a_cur.as_ref().map(|a| (a.clone(), elt_b))
}
fn size_hint(&self) -> (usize, Option<usize>) {
@@ -492,7 +485,6 @@ impl<T: PartialOrd> MergePredicate<T> for MergeLte {
/// Iterator element type is `I::Item`.
///
/// See [`.merge()`](crate::Itertools::merge_by) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type Merge<I, J> = MergeBy<I, J, MergeLte>;
/// Create an iterator that merges elements in `i` and `j`.
diff --git a/vendor/itertools/src/adaptors/multi_product.rs b/vendor/itertools/src/adaptors/multi_product.rs
index 30650eda6..0b3840698 100644
--- a/vendor/itertools/src/adaptors/multi_product.rs
+++ b/vendor/itertools/src/adaptors/multi_product.rs
@@ -40,7 +40,7 @@ pub fn multi_cartesian_product<H>(iters: H) -> MultiProduct<<H::Item as IntoIter
}
#[derive(Clone, Debug)]
-/// Holds the state of a single iterator within a MultiProduct.
+/// Holds the state of a single iterator within a `MultiProduct`.
struct MultiProductIter<I>
where I: Iterator + Clone,
I::Item: Clone
@@ -50,7 +50,7 @@ struct MultiProductIter<I>
iter_orig: I,
}
-/// Holds the current state during an iteration of a MultiProduct.
+/// Holds the current state during an iteration of a `MultiProduct`.
#[derive(Debug)]
enum MultiProductIterState {
StartOfIter,
diff --git a/vendor/itertools/src/combinations_with_replacement.rs b/vendor/itertools/src/combinations_with_replacement.rs
index 81b13f130..0fec9671a 100644
--- a/vendor/itertools/src/combinations_with_replacement.rs
+++ b/vendor/itertools/src/combinations_with_replacement.rs
@@ -64,7 +64,7 @@ where
// If this is the first iteration, return early
if self.first {
// In empty edge cases, stop iterating immediately
- return if self.indices.len() != 0 && !self.pool.get_next() {
+ return if !(self.indices.is_empty() || self.pool.get_next()) {
None
// Otherwise, yield the initial state
} else {
@@ -92,7 +92,7 @@ where
// We need to update the rightmost non-max value
// and all those to the right
for indices_index in increment_from..self.indices.len() {
- self.indices[indices_index] = increment_value
+ self.indices[indices_index] = increment_value;
}
Some(self.current())
}
diff --git a/vendor/itertools/src/concat_impl.rs b/vendor/itertools/src/concat_impl.rs
index 450f7fce1..f022ec90a 100644
--- a/vendor/itertools/src/concat_impl.rs
+++ b/vendor/itertools/src/concat_impl.rs
@@ -18,5 +18,6 @@ pub fn concat<I>(iterable: I) -> I::Item
where I: IntoIterator,
I::Item: Extend<<<I as IntoIterator>::Item as IntoIterator>::Item> + IntoIterator + Default
{
- iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_else(<_>::default)
+ #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce`
+ iterable.into_iter().fold1(|mut a, b| { a.extend(b); a }).unwrap_or_default()
}
diff --git a/vendor/itertools/src/duplicates_impl.rs b/vendor/itertools/src/duplicates_impl.rs
index 640d4818c..28eda44a9 100644
--- a/vendor/itertools/src/duplicates_impl.rs
+++ b/vendor/itertools/src/duplicates_impl.rs
@@ -188,7 +188,6 @@ mod private {
/// An iterator adapter to filter for duplicate elements.
///
/// See [`.duplicates_by()`](crate::Itertools::duplicates_by) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type DuplicatesBy<I, V, F> = private::DuplicatesBy<I, V, private::ByFn<F>>;
/// Create a new `DuplicatesBy` iterator.
diff --git a/vendor/itertools/src/either_or_both.rs b/vendor/itertools/src/either_or_both.rs
index 28d1df757..ef3985f75 100644
--- a/vendor/itertools/src/either_or_both.rs
+++ b/vendor/itertools/src/either_or_both.rs
@@ -165,6 +165,33 @@ impl<A, B> EitherOrBoth<A, B> {
}
/// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
+ /// Otherwise, returns the wrapped value for the present element, and the supplied
+ /// value for the other. The first (`l`) argument is used for a missing `Left`
+ /// value. The second (`r`) argument is used for a missing `Right` value.
+ ///
+ /// Arguments passed to `or` are eagerly evaluated; if you are passing
+ /// the result of a function call, it is recommended to use [`or_else`],
+ /// which is lazily evaluated.
+ ///
+ /// [`or_else`]: EitherOrBoth::or_else
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use itertools::EitherOrBoth;
+ /// assert_eq!(EitherOrBoth::Both("tree", 1).or("stone", 5), ("tree", 1));
+ /// assert_eq!(EitherOrBoth::Left("tree").or("stone", 5), ("tree", 5));
+ /// assert_eq!(EitherOrBoth::Right(1).or("stone", 5), ("stone", 1));
+ /// ```
+ pub fn or(self, l: A, r: B) -> (A, B) {
+ match self {
+ Left(inner_l) => (inner_l, r),
+ Right(inner_r) => (l, inner_r),
+ Both(inner_l, inner_r) => (inner_l, inner_r),
+ }
+ }
+
+ /// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
/// Otherwise, returns the wrapped value for the present element, and the [`default`](Default::default)
/// for the other.
pub fn or_default(self) -> (A, B)
@@ -178,6 +205,28 @@ impl<A, B> EitherOrBoth<A, B> {
EitherOrBoth::Both(l, r) => (l, r),
}
}
+
+ /// Returns a tuple consisting of the `l` and `r` in `Both(l, r)`, if present.
+ /// Otherwise, returns the wrapped value for the present element, and computes the
+ /// missing value with the supplied closure. The first argument (`l`) is used for a
+ /// missing `Left` value. The second argument (`r`) is used for a missing `Right` value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use itertools::EitherOrBoth;
+ /// let k = 10;
+ /// assert_eq!(EitherOrBoth::Both("tree", 1).or_else(|| "stone", || 2 * k), ("tree", 1));
+ /// assert_eq!(EitherOrBoth::Left("tree").or_else(|| "stone", || 2 * k), ("tree", 20));
+ /// assert_eq!(EitherOrBoth::Right(1).or_else(|| "stone", || 2 * k), ("stone", 1));
+ /// ```
+ pub fn or_else<L: FnOnce() -> A, R: FnOnce() -> B>(self, l: L, r: R) -> (A, B) {
+ match self {
+ Left(inner_l) => (inner_l, r()),
+ Right(inner_r) => (l(), inner_r),
+ Both(inner_l, inner_r) => (inner_l, inner_r),
+ }
+ }
}
impl<T> EitherOrBoth<T, T> {
diff --git a/vendor/itertools/src/exactly_one_err.rs b/vendor/itertools/src/exactly_one_err.rs
index 63485c993..c54ae77ca 100644
--- a/vendor/itertools/src/exactly_one_err.rs
+++ b/vendor/itertools/src/exactly_one_err.rs
@@ -11,10 +11,10 @@ use crate::size_hint;
/// Iterator returned for the error case of `IterTools::exactly_one()`
/// This iterator yields exactly the same elements as the input iterator.
///
-/// During the execution of exactly_one the iterator must be mutated. This wrapper
+/// During the execution of `exactly_one` the iterator must be mutated. This wrapper
/// effectively "restores" the state of the input iterator when it's handed back.
///
-/// This is very similar to PutBackN except this iterator only supports 0-2 elements and does not
+/// This is very similar to `PutBackN` except this iterator only supports 0-2 elements and does not
/// use a `Vec`.
#[derive(Clone)]
pub struct ExactlyOneError<I>
diff --git a/vendor/itertools/src/extrema_set.rs b/vendor/itertools/src/extrema_set.rs
new file mode 100644
index 000000000..ae128364c
--- /dev/null
+++ b/vendor/itertools/src/extrema_set.rs
@@ -0,0 +1,48 @@
+use std::cmp::Ordering;
+
+/// Implementation guts for `min_set`, `min_set_by`, and `min_set_by_key`.
+pub fn min_set_impl<I, K, F, Compare>(
+ mut it: I,
+ mut key_for: F,
+ mut compare: Compare,
+) -> Vec<I::Item>
+where
+ I: Iterator,
+ F: FnMut(&I::Item) -> K,
+ Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering,
+{
+ match it.next() {
+ None => Vec::new(),
+ Some(element) => {
+ let mut current_key = key_for(&element);
+ let mut result = vec![element];
+ it.for_each(|element| {
+ let key = key_for(&element);
+ match compare(&element, &result[0], &key, &current_key) {
+ Ordering::Less => {
+ result.clear();
+ result.push(element);
+ current_key = key;
+ }
+ Ordering::Equal => {
+ result.push(element);
+ }
+ Ordering::Greater => {}
+ }
+ });
+ result
+ }
+ }
+}
+
+/// Implementation guts for `ax_set`, `max_set_by`, and `max_set_by_key`.
+pub fn max_set_impl<I, K, F, Compare>(it: I, key_for: F, mut compare: Compare) -> Vec<I::Item>
+where
+ I: Iterator,
+ F: FnMut(&I::Item) -> K,
+ Compare: FnMut(&I::Item, &I::Item, &K, &K) -> Ordering,
+{
+ min_set_impl(it, key_for, |it1, it2, key1, key2| {
+ compare(it2, it1, key2, key1)
+ })
+}
diff --git a/vendor/itertools/src/flatten_ok.rs b/vendor/itertools/src/flatten_ok.rs
index d46bbde4e..21ae1f722 100644
--- a/vendor/itertools/src/flatten_ok.rs
+++ b/vendor/itertools/src/flatten_ok.rs
@@ -44,11 +44,11 @@ where
if let Some(inner) = &mut self.inner_front {
if let Some(item) = inner.next() {
return Some(Ok(item));
- } else {
- // This is necessary for the iterator to implement `FusedIterator`
- // with only the orginal iterator being fused.
- self.inner_front = None;
}
+
+ // This is necessary for the iterator to implement `FusedIterator`
+ // with only the original iterator being fused.
+ self.inner_front = None;
}
match self.iter.next() {
@@ -59,11 +59,11 @@ where
if let Some(inner) = &mut self.inner_back {
if let Some(item) = inner.next() {
return Some(Ok(item));
- } else {
- // This is necessary for the iterator to implement `FusedIterator`
- // with only the orginal iterator being fused.
- self.inner_back = None;
}
+
+ // This is necessary for the iterator to implement `FusedIterator`
+ // with only the original iterator being fused.
+ self.inner_back = None;
} else {
return None;
}
@@ -103,11 +103,11 @@ where
if let Some(inner) = &mut self.inner_back {
if let Some(item) = inner.next_back() {
return Some(Ok(item));
- } else {
- // This is necessary for the iterator to implement `FusedIterator`
- // with only the orginal iterator being fused.
- self.inner_back = None;
}
+
+ // This is necessary for the iterator to implement `FusedIterator`
+ // with only the original iterator being fused.
+ self.inner_back = None;
}
match self.iter.next_back() {
@@ -118,11 +118,11 @@ where
if let Some(inner) = &mut self.inner_front {
if let Some(item) = inner.next_back() {
return Some(Ok(item));
- } else {
- // This is necessary for the iterator to implement `FusedIterator`
- // with only the orginal iterator being fused.
- self.inner_front = None;
}
+
+ // This is necessary for the iterator to implement `FusedIterator`
+ // with only the original iterator being fused.
+ self.inner_front = None;
} else {
return None;
}
@@ -138,7 +138,6 @@ where
T: IntoIterator,
T::IntoIter: Clone,
{
- #[inline]
clone_fields!(iter, inner_front, inner_back);
}
diff --git a/vendor/itertools/src/free.rs b/vendor/itertools/src/free.rs
index 667403040..19e3e2869 100644
--- a/vendor/itertools/src/free.rs
+++ b/vendor/itertools/src/free.rs
@@ -105,18 +105,23 @@ pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
iterable.into_iter().rev()
}
-/// Iterate `i` and `j` in lock step.
+/// Converts the arguments to iterators and zips them.
///
/// [`IntoIterator`] enabled version of [`Iterator::zip`].
+///
+/// ## Example
///
/// ```
/// use itertools::zip;
///
-/// let data = [1, 2, 3, 4, 5];
-/// for (a, b) in zip(&data, &data[1..]) {
-/// /* loop body */
+/// let mut result: Vec<(i32, char)> = Vec::new();
+///
+/// for (a, b) in zip(&[1, 2, 3, 4, 5], &['a', 'b', 'c']) {
+/// result.push((*a, *b));
/// }
+/// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]);
/// ```
+#[deprecated(note="Use [std::iter::zip](https://doc.rust-lang.org/std/iter/fn.zip.html) instead", since="0.10.4")]
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
where I: IntoIterator,
J: IntoIterator
@@ -124,16 +129,21 @@ pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
i.into_iter().zip(j)
}
-/// Create an iterator that first iterates `i` and then `j`.
+
+/// Takes two iterables and creates a new iterator over both in sequence.
///
/// [`IntoIterator`] enabled version of [`Iterator::chain`].
///
+/// ## Example
/// ```
/// use itertools::chain;
+///
+/// let mut result:Vec<i32> = Vec::new();
///
-/// for elt in chain(&[1, 2, 3], &[4]) {
-/// /* loop body */
+/// for element in chain(&[1, 2, 3], &[4]) {
+/// result.push(*element);
/// }
+/// assert_eq!(result, vec![1, 2, 3, 4]);
/// ```
pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where I: IntoIterator,
@@ -239,7 +249,7 @@ pub fn min<I>(iterable: I) -> Option<I::Item>
}
-/// Combine all iterator elements into one String, seperated by `sep`.
+/// Combine all iterator elements into one String, separated by `sep`.
///
/// [`IntoIterator`] enabled version of [`Itertools::join`].
///
diff --git a/vendor/itertools/src/groupbylazy.rs b/vendor/itertools/src/groupbylazy.rs
index 91c52ea59..a5a321df4 100644
--- a/vendor/itertools/src/groupbylazy.rs
+++ b/vendor/itertools/src/groupbylazy.rs
@@ -1,13 +1,13 @@
use std::cell::{Cell, RefCell};
use alloc::vec::{self, Vec};
-/// A trait to unify FnMut for GroupBy with the chunk key in IntoChunks
+/// A trait to unify `FnMut` for `GroupBy` with the chunk key in `IntoChunks`
trait KeyFunction<A> {
type Key;
fn call_mut(&mut self, arg: A) -> Self::Key;
}
-impl<'a, A, K, F: ?Sized> KeyFunction<A> for F
+impl<A, K, F: ?Sized> KeyFunction<A> for F
where F: FnMut(A) -> K
{
type Key = K;
@@ -18,7 +18,7 @@ impl<'a, A, K, F: ?Sized> KeyFunction<A> for F
}
-/// ChunkIndex acts like the grouping key function for IntoChunks
+/// `ChunkIndex` acts like the grouping key function for `IntoChunks`
#[derive(Debug)]
struct ChunkIndex {
size: usize,
@@ -37,7 +37,7 @@ impl ChunkIndex {
}
}
-impl<'a, A> KeyFunction<A> for ChunkIndex {
+impl<A> KeyFunction<A> for ChunkIndex {
type Key = usize;
#[inline(always)]
fn call_mut(&mut self, _arg: A) -> Self::Key {
@@ -330,7 +330,7 @@ impl<K, I, F> GroupBy<K, I, F>
/// `client`: Index of group
fn drop_group(&self, client: usize) {
- self.inner.borrow_mut().drop_group(client)
+ self.inner.borrow_mut().drop_group(client);
}
}
@@ -482,7 +482,7 @@ impl<I> IntoChunks<I>
/// `client`: Index of chunk
fn drop_group(&self, client: usize) {
- self.inner.borrow_mut().drop_group(client)
+ self.inner.borrow_mut().drop_group(client);
}
}
diff --git a/vendor/itertools/src/grouping_map.rs b/vendor/itertools/src/grouping_map.rs
index be22ec849..bb5b582c9 100644
--- a/vendor/itertools/src/grouping_map.rs
+++ b/vendor/itertools/src/grouping_map.rs
@@ -39,7 +39,6 @@ pub fn new<I, K, V>(iter: I) -> GroupingMap<I>
/// `GroupingMapBy` is an intermediate struct for efficient group-and-fold operations.
///
/// See [`GroupingMap`] for more informations.
-#[must_use = "GroupingMapBy is lazy and do nothing unless consumed"]
pub type GroupingMapBy<I, F> = GroupingMap<MapForGrouping<I, F>>;
/// `GroupingMap` is an intermediate struct for efficient group-and-fold operations.
@@ -290,7 +289,7 @@ impl<I, K, V> GroupingMap<I>
where F: FnMut(&K, &V) -> CK,
CK: Ord,
{
- self.max_by(|key, v1, v2| f(key, &v1).cmp(&f(key, &v2)))
+ self.max_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and finds the minimum of each group.
@@ -368,7 +367,7 @@ impl<I, K, V> GroupingMap<I>
where F: FnMut(&K, &V) -> CK,
CK: Ord,
{
- self.min_by(|key, v1, v2| f(key, &v1).cmp(&f(key, &v2)))
+ self.min_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and find the maximum and minimum of
@@ -481,7 +480,7 @@ impl<I, K, V> GroupingMap<I>
where F: FnMut(&K, &V) -> CK,
CK: Ord,
{
- self.minmax_by(|key, v1, v2| f(key, &v1).cmp(&f(key, &v2)))
+ self.minmax_by(|key, v1, v2| f(key, v1).cmp(&f(key, v2)))
}
/// Groups elements from the `GroupingMap` source by key and sums them.
diff --git a/vendor/itertools/src/impl_macros.rs b/vendor/itertools/src/impl_macros.rs
index 5772baeb6..a029843b0 100644
--- a/vendor/itertools/src/impl_macros.rs
+++ b/vendor/itertools/src/impl_macros.rs
@@ -15,6 +15,7 @@ macro_rules! debug_fmt_fields {
macro_rules! clone_fields {
($($field:ident),*) => {
+ #[inline] // TODO is this sensible?
fn clone(&self) -> Self {
Self {
$($field: self.$field.clone(),)*
diff --git a/vendor/itertools/src/intersperse.rs b/vendor/itertools/src/intersperse.rs
index 2c660d492..10a3a5389 100644
--- a/vendor/itertools/src/intersperse.rs
+++ b/vendor/itertools/src/intersperse.rs
@@ -55,7 +55,7 @@ pub struct IntersperseWith<I, ElemF>
peek: Option<I::Item>,
}
-/// Create a new IntersperseWith iterator
+/// Create a new `IntersperseWith` iterator
pub fn intersperse_with<I, ElemF>(iter: I, elt: ElemF) -> IntersperseWith<I, ElemF>
where I: Iterator,
{
@@ -107,8 +107,7 @@ impl<I, ElemF> Iterator for IntersperseWith<I, ElemF>
self.iter.fold(accum,
|accum, x| {
let accum = f(accum, element.generate());
- let accum = f(accum, x);
- accum
+ f(accum, x)
})
}
}
diff --git a/vendor/itertools/src/kmerge_impl.rs b/vendor/itertools/src/kmerge_impl.rs
index bd56b0317..509d5fc6a 100644
--- a/vendor/itertools/src/kmerge_impl.rs
+++ b/vendor/itertools/src/kmerge_impl.rs
@@ -80,7 +80,7 @@ fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
// that wouldn't be predicted if present
while child + 1 < heap.len() {
// pick the smaller of the two children
- // use aritmethic to avoid an unpredictable branch
+ // use arithmetic to avoid an unpredictable branch
child += less_than(&heap[child+1], &heap[child]) as usize;
// sift down is done if we are already in order
@@ -104,7 +104,6 @@ fn sift_down<T, S>(heap: &mut [T], index: usize, mut less_than: S)
/// Iterator element type is `I::Item`.
///
/// See [`.kmerge()`](crate::Itertools::kmerge) for more information.
-#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub type KMerge<I> = KMergeBy<I, KMergeByLt>;
pub trait KMergePredicate<T> {
@@ -129,7 +128,7 @@ impl<T, F: FnMut(&T, &T)->bool> KMergePredicate<T> for F {
/// Create an iterator that merges elements of the contained iterators using
/// the ordering function.
///
-/// Equivalent to `iterable.into_iter().kmerge()`.
+/// [`IntoIterator`] enabled version of [`Itertools::kmerge`].
///
/// ```
/// use itertools::kmerge;
@@ -170,7 +169,7 @@ impl<I, F> fmt::Debug for KMergeBy<I, F>
/// Create an iterator that merges elements of the contained iterators.
///
-/// Equivalent to `iterable.into_iter().kmerge_by(less_than)`.
+/// [`IntoIterator`] enabled version of [`Itertools::kmerge_by`].
pub fn kmerge_by<I, F>(iterable: I, mut less_than: F)
-> KMergeBy<<I::Item as IntoIterator>::IntoIter, F>
where I: IntoIterator,
@@ -214,6 +213,7 @@ impl<I, F> Iterator for KMergeBy<I, F>
}
fn size_hint(&self) -> (usize, Option<usize>) {
+ #[allow(deprecated)] //TODO: once msrv hits 1.51. replace `fold1` with `reduce`
self.heap.iter()
.map(|i| i.size_hint())
.fold1(size_hint::add)
diff --git a/vendor/itertools/src/lazy_buffer.rs b/vendor/itertools/src/lazy_buffer.rs
index fa514ec2d..ca24062aa 100644
--- a/vendor/itertools/src/lazy_buffer.rs
+++ b/vendor/itertools/src/lazy_buffer.rs
@@ -28,16 +28,12 @@ where
if self.done {
return false;
}
- let next_item = self.it.next();
- match next_item {
- Some(x) => {
- self.buffer.push(x);
- true
- }
- None => {
- self.done = true;
- false
- }
+ if let Some(x) = self.it.next() {
+ self.buffer.push(x);
+ true
+ } else {
+ self.done = true;
+ false
}
}
@@ -61,7 +57,7 @@ where
{
type Output = <Vec<I::Item> as Index<J>>::Output;
- fn index(&self, _index: J) -> &Self::Output {
- self.buffer.index(_index)
+ fn index(&self, index: J) -> &Self::Output {
+ self.buffer.index(index)
}
}
diff --git a/vendor/itertools/src/lib.rs b/vendor/itertools/src/lib.rs
index df95e19ba..f91968870 100644
--- a/vendor/itertools/src/lib.rs
+++ b/vendor/itertools/src/lib.rs
@@ -197,6 +197,8 @@ mod combinations_with_replacement;
mod exactly_one_err;
mod diff;
mod flatten_ok;
+#[cfg(feature = "use_std")]
+mod extrema_set;
mod format;
#[cfg(feature = "use_std")]
mod grouping_map;
@@ -387,7 +389,7 @@ macro_rules! izip {
/// let with_macro: Chain<Chain<Once<_>, Take<Repeat<_>>>, slice::Iter<_>> =
/// chain![once(&0), repeat(&1).take(2), &[2, 3, 5],];
///
-/// // ...is equivalant to this:
+/// // ...is equivalent to this:
/// let with_method: Chain<Chain<Once<_>, Take<Repeat<_>>>, slice::Iter<_>> =
/// once(&0)
/// .chain(repeat(&1).take(2))
@@ -778,7 +780,7 @@ pub trait Itertools : Iterator {
/// the original iterator.
///
/// **Note:** If the iterator is clonable, prefer using that instead
- /// of using this method. It is likely to be more efficient.
+ /// of using this method. Cloning is likely to be more efficient.
///
/// Iterator element type is `Self::Item`.
///
@@ -904,7 +906,7 @@ pub trait Itertools : Iterator {
/// a series of `Result::Ok` values. `Result::Err` values are unchanged.
///
/// This is useful when you have some common error type for your crate and
- /// need to propogate it upwards, but the `Result::Ok` case needs to be flattened.
+ /// need to propagate it upwards, but the `Result::Ok` case needs to be flattened.
///
/// ```
/// use itertools::Itertools;
@@ -913,7 +915,7 @@ pub trait Itertools : Iterator {
/// let it = input.iter().cloned().flatten_ok();
/// itertools::assert_equal(it.clone(), vec![Ok(0), Ok(1), Err(false), Ok(2), Ok(3)]);
///
- /// // This can also be used to propogate errors when collecting.
+ /// // This can also be used to propagate errors when collecting.
/// let output_result: Result<Vec<i32>, bool> = it.collect();
/// assert_eq!(output_result, Err(false));
/// ```
@@ -1109,7 +1111,7 @@ pub trait Itertools : Iterator {
/// ```
#[cfg(feature = "use_alloc")]
fn multi_cartesian_product(self) -> MultiProduct<<Self::Item as IntoIterator>::IntoIter>
- where Self: Iterator + Sized,
+ where Self: Sized,
Self::Item: IntoIterator,
<Self::Item as IntoIterator>::IntoIter: Clone,
<Self::Item as IntoIterator>::Item: Clone
@@ -1746,12 +1748,10 @@ pub trait Itertools : Iterator {
fn find_position<P>(&mut self, mut pred: P) -> Option<(usize, Self::Item)>
where P: FnMut(&Self::Item) -> bool
{
- let mut index = 0usize;
- for elt in self {
+ for (index, elt) in self.enumerate() {
if pred(&elt) {
return Some((index, elt));
}
- index += 1;
}
None
}
@@ -1795,7 +1795,7 @@ pub trait Itertools : Iterator {
Some(if predicate(&first) {
first
} else {
- self.find(|x| predicate(&x)).unwrap_or(first)
+ self.find(|x| predicate(x)).unwrap_or(first)
})
}
/// Returns `true` if the given item is present in this iterator.
@@ -1953,7 +1953,7 @@ pub trait Itertools : Iterator {
where F: FnMut(Self::Item),
Self: Sized,
{
- self.for_each(f)
+ self.for_each(f);
}
/// Combine all an iterator's elements into one element by using [`Extend`].
@@ -2271,7 +2271,7 @@ pub trait Itertools : Iterator {
/// ```
///
/// Which, for non-associative functions, will typically produce a different
- /// result than the linear call tree used by `fold1`:
+ /// result than the linear call tree used by [`Iterator::reduce`]:
///
/// ```text
/// 1 2 3 4 5 6 7
@@ -2279,7 +2279,7 @@ pub trait Itertools : Iterator {
/// └─f─f─f─f─f─f
/// ```
///
- /// If `f` is associative, prefer the normal `fold1` instead.
+ /// If `f` is associative, prefer the normal [`Iterator::reduce`] instead.
///
/// ```
/// use itertools::Itertools;
@@ -2692,7 +2692,6 @@ pub trait Itertools : Iterator {
/// itertools::assert_equal(oldest_people_first,
/// vec!["Jill", "Jack", "Jane", "John"]);
/// ```
- /// ```
#[cfg(feature = "use_alloc")]
fn sorted_by_cached_key<K, F>(self, f: F) -> VecIntoIter<Self::Item>
where
@@ -2902,6 +2901,194 @@ pub trait Itertools : Iterator {
grouping_map::new(grouping_map::MapForGrouping::new(self, key_mapper))
}
+ /// Return all minimum elements of an iterator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use itertools::Itertools;
+ ///
+ /// let a: [i32; 0] = [];
+ /// assert_eq!(a.iter().min_set(), Vec::<&i32>::new());
+ ///
+ /// let a = [1];
+ /// assert_eq!(a.iter().min_set(), vec![&1]);
+ ///
+ /// let a = [1, 2, 3, 4, 5];
+ /// assert_eq!(a.iter().min_set(), vec![&1]);
+ ///
+ /// let a = [1, 1, 1, 1];
+ /// assert_eq!(a.iter().min_set(), vec![&1, &1, &1, &1]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn min_set(self) -> Vec<Self::Item>
+ where Self: Sized, Self::Item: Ord
+ {
+ extrema_set::min_set_impl(self, |_| (), |x, y, _, _| x.cmp(y))
+ }
+
+ /// Return all minimum elements of an iterator, as determined by
+ /// the specified function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::cmp::Ordering;
+ /// use itertools::Itertools;
+ ///
+ /// let a: [(i32, i32); 0] = [];
+ /// assert_eq!(a.iter().min_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new());
+ ///
+ /// let a = [(1, 2)];
+ /// assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]);
+ ///
+ /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
+ /// assert_eq!(a.iter().min_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(1, 2), &(2, 2)]);
+ ///
+ /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
+ /// assert_eq!(a.iter().min_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn min_set_by<F>(self, mut compare: F) -> Vec<Self::Item>
+ where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering
+ {
+ extrema_set::min_set_impl(
+ self,
+ |_| (),
+ |x, y, _, _| compare(x, y)
+ )
+ }
+
+ /// Return all minimum elements of an iterator, as determined by
+ /// the specified function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use itertools::Itertools;
+ ///
+ /// let a: [(i32, i32); 0] = [];
+ /// assert_eq!(a.iter().min_set_by_key(|_| ()), Vec::<&(i32, i32)>::new());
+ ///
+ /// let a = [(1, 2)];
+ /// assert_eq!(a.iter().min_set_by_key(|&&(k,_)| k), vec![&(1, 2)]);
+ ///
+ /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
+ /// assert_eq!(a.iter().min_set_by_key(|&&(_, k)| k), vec![&(1, 2), &(2, 2)]);
+ ///
+ /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
+ /// assert_eq!(a.iter().min_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn min_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
+ where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K
+ {
+ extrema_set::min_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky))
+ }
+
+ /// Return all maximum elements of an iterator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use itertools::Itertools;
+ ///
+ /// let a: [i32; 0] = [];
+ /// assert_eq!(a.iter().max_set(), Vec::<&i32>::new());
+ ///
+ /// let a = [1];
+ /// assert_eq!(a.iter().max_set(), vec![&1]);
+ ///
+ /// let a = [1, 2, 3, 4, 5];
+ /// assert_eq!(a.iter().max_set(), vec![&5]);
+ ///
+ /// let a = [1, 1, 1, 1];
+ /// assert_eq!(a.iter().max_set(), vec![&1, &1, &1, &1]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn max_set(self) -> Vec<Self::Item>
+ where Self: Sized, Self::Item: Ord
+ {
+ extrema_set::max_set_impl(self, |_| (), |x, y, _, _| x.cmp(y))
+ }
+
+ /// Return all maximum elements of an iterator, as determined by
+ /// the specified function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use std::cmp::Ordering;
+ /// use itertools::Itertools;
+ ///
+ /// let a: [(i32, i32); 0] = [];
+ /// assert_eq!(a.iter().max_set_by(|_, _| Ordering::Equal), Vec::<&(i32, i32)>::new());
+ ///
+ /// let a = [(1, 2)];
+ /// assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2)]);
+ ///
+ /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
+ /// assert_eq!(a.iter().max_set_by(|&&(_,k1), &&(_,k2)| k1.cmp(&k2)), vec![&(3, 9), &(5, 9)]);
+ ///
+ /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
+ /// assert_eq!(a.iter().max_set_by(|&&(k1,_), &&(k2, _)| k1.cmp(&k2)), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn max_set_by<F>(self, mut compare: F) -> Vec<Self::Item>
+ where Self: Sized, F: FnMut(&Self::Item, &Self::Item) -> Ordering
+ {
+ extrema_set::max_set_impl(
+ self,
+ |_| (),
+ |x, y, _, _| compare(x, y)
+ )
+ }
+
+ /// Return all minimum elements of an iterator, as determined by
+ /// the specified function.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use itertools::Itertools;
+ ///
+ /// let a: [(i32, i32); 0] = [];
+ /// assert_eq!(a.iter().max_set_by_key(|_| ()), Vec::<&(i32, i32)>::new());
+ ///
+ /// let a = [(1, 2)];
+ /// assert_eq!(a.iter().max_set_by_key(|&&(k,_)| k), vec![&(1, 2)]);
+ ///
+ /// let a = [(1, 2), (2, 2), (3, 9), (4, 8), (5, 9)];
+ /// assert_eq!(a.iter().max_set_by_key(|&&(_, k)| k), vec![&(3, 9), &(5, 9)]);
+ ///
+ /// let a = [(1, 2), (1, 3), (1, 4), (1, 5)];
+ /// assert_eq!(a.iter().max_set_by_key(|&&(k, _)| k), vec![&(1, 2), &(1, 3), &(1, 4), &(1, 5)]);
+ /// ```
+ ///
+ /// The elements can be floats but no particular result is guaranteed
+ /// if an element is NaN.
+ #[cfg(feature = "use_std")]
+ fn max_set_by_key<K, F>(self, key: F) -> Vec<Self::Item>
+ where Self: Sized, K: Ord, F: FnMut(&Self::Item) -> K
+ {
+ extrema_set::max_set_impl(self, key, |_, _, kx, ky| kx.cmp(ky))
+ }
+
/// Return the minimum and maximum elements in the iterator.
///
/// The return type `MinMaxResult` is an enum of three variants:
@@ -3157,7 +3344,7 @@ pub trait Itertools : Iterator {
/// be equal to `ypos`.
///
/// On an iterator of length `n`, `position_minmax` does `1.5 * n`
- /// comparisons, and so is faster than calling `positon_min` and
+ /// comparisons, and so is faster than calling `position_min` and
/// `position_max` separately which does `2 * n` comparisons.
///
/// For the minimum, if several elements are equally minimum, the
@@ -3478,8 +3665,7 @@ impl<T: ?Sized> Itertools for T where T: Iterator { }
/// (elements pairwise equal and sequences of the same length),
/// `false` otherwise.
///
-/// This is an [`IntoIterator`] enabled function that is similar to the standard
-/// library method [`Iterator::eq`].
+/// [`IntoIterator`] enabled version of [`Iterator::eq`].
///
/// ```
/// assert!(itertools::equal(vec![1, 2, 3], 1..4));
@@ -3490,17 +3676,7 @@ pub fn equal<I, J>(a: I, b: J) -> bool
J: IntoIterator,
I::Item: PartialEq<J::Item>
{
- let mut ia = a.into_iter();
- let mut ib = b.into_iter();
- loop {
- match ia.next() {
- Some(x) => match ib.next() {
- Some(y) => if x != y { return false; },
- None => return false,
- },
- None => return ib.next().is_none()
- }
- }
+ a.into_iter().eq(b)
}
/// Assert that two iterables produce equal sequences, with the same
diff --git a/vendor/itertools/src/merge_join.rs b/vendor/itertools/src/merge_join.rs
index 4c0048f68..f2fbdea2c 100644
--- a/vendor/itertools/src/merge_join.rs
+++ b/vendor/itertools/src/merge_join.rs
@@ -4,10 +4,12 @@ use std::fmt;
use super::adaptors::{PutBack, put_back};
use crate::either_or_both::EitherOrBoth;
+#[cfg(doc)]
+use crate::Itertools;
/// Return an iterator adaptor that merge-joins items from the two base iterators in ascending order.
///
-/// See [`.merge_join_by()`](crate::Itertools::merge_join_by) for more information.
+/// [`IntoIterator`] enabled version of [`Itertools::merge_join_by`].
pub fn merge_join_by<I, J, F>(left: I, right: J, cmp_fn: F)
-> MergeJoinBy<I::IntoIter, J::IntoIter, F>
where I: IntoIterator,
diff --git a/vendor/itertools/src/multipeek_impl.rs b/vendor/itertools/src/multipeek_impl.rs
index 5917681fc..8b49c695e 100644
--- a/vendor/itertools/src/multipeek_impl.rs
+++ b/vendor/itertools/src/multipeek_impl.rs
@@ -2,6 +2,8 @@ use std::iter::Fuse;
use alloc::collections::VecDeque;
use crate::size_hint;
use crate::PeekingNext;
+#[cfg(doc)]
+use crate::Itertools;
/// See [`multipeek()`] for more information.
#[derive(Clone, Debug)]
@@ -15,6 +17,8 @@ pub struct MultiPeek<I>
/// An iterator adaptor that allows the user to peek at multiple `.next()`
/// values without advancing the base iterator.
+///
+/// [`IntoIterator`] enabled version of [`Itertools::multipeek`].
pub fn multipeek<I>(iterable: I) -> MultiPeek<I::IntoIter>
where I: IntoIterator
{
@@ -67,10 +71,8 @@ impl<I> PeekingNext for MultiPeek<I>
if let Some(r) = self.peek() {
if !accept(r) { return None }
}
- } else {
- if let Some(r) = self.buf.get(0) {
- if !accept(r) { return None }
- }
+ } else if let Some(r) = self.buf.get(0) {
+ if !accept(r) { return None }
}
self.next()
}
diff --git a/vendor/itertools/src/pad_tail.rs b/vendor/itertools/src/pad_tail.rs
index de57ee416..248a43243 100644
--- a/vendor/itertools/src/pad_tail.rs
+++ b/vendor/itertools/src/pad_tail.rs
@@ -23,7 +23,7 @@ where
debug_fmt_fields!(PadUsing, iter, min, pos);
}
-/// Create a new **PadUsing** iterator.
+/// Create a new `PadUsing` iterator.
pub fn pad_using<I, F>(iter: I, min: usize, filler: F) -> PadUsing<I, F>
where I: Iterator,
F: FnMut(usize) -> I::Item
diff --git a/vendor/itertools/src/peeking_take_while.rs b/vendor/itertools/src/peeking_take_while.rs
index cd0945a52..b3a9c5ccb 100644
--- a/vendor/itertools/src/peeking_take_while.rs
+++ b/vendor/itertools/src/peeking_take_while.rs
@@ -90,7 +90,7 @@ where
debug_fmt_fields!(PeekingTakeWhile, iter);
}
-/// Create a PeekingTakeWhile
+/// Create a `PeekingTakeWhile`
pub fn peeking_take_while<I, F>(iter: &mut I, f: F) -> PeekingTakeWhile<I, F>
where I: Iterator,
{
diff --git a/vendor/itertools/src/permutations.rs b/vendor/itertools/src/permutations.rs
index 3080f9d5c..d03b85262 100644
--- a/vendor/itertools/src/permutations.rs
+++ b/vendor/itertools/src/permutations.rs
@@ -113,19 +113,15 @@ where
Some(indices.map(|i| vals[i].clone()).collect())
}
- PermutationState::Complete(CompleteState::Start { .. }) => None,
PermutationState::Complete(CompleteState::Ongoing { ref indices, ref cycles }) => {
let k = cycles.len();
-
Some(indices[0..k].iter().map(|&i| vals[i].clone()).collect())
},
- PermutationState::Empty => None
+ PermutationState::Complete(CompleteState::Start { .. }) | PermutationState::Empty => None
}
}
fn count(self) -> usize {
- let Permutations { vals, state } = self;
-
fn from_complete(complete_state: CompleteState) -> usize {
match complete_state.remaining() {
CompleteStateRemaining::Known(count) => count,
@@ -135,6 +131,7 @@ where
}
}
+ let Permutations { vals, state } = self;
match state {
PermutationState::StartUnknownLen { k } => {
let n = vals.len() + vals.it.count();
diff --git a/vendor/itertools/src/rciter_impl.rs b/vendor/itertools/src/rciter_impl.rs
index 782908e28..7298350a8 100644
--- a/vendor/itertools/src/rciter_impl.rs
+++ b/vendor/itertools/src/rciter_impl.rs
@@ -51,7 +51,6 @@ pub fn rciter<I>(iterable: I) -> RcIter<I::IntoIter>
}
impl<I> Clone for RcIter<I> {
- #[inline]
clone_fields!(rciter);
}
diff --git a/vendor/itertools/src/size_hint.rs b/vendor/itertools/src/size_hint.rs
index 1168ecaa3..71ea1412b 100644
--- a/vendor/itertools/src/size_hint.rs
+++ b/vendor/itertools/src/size_hint.rs
@@ -1,14 +1,14 @@
-//! Arithmetic on **Iterator** *.size_hint()* values.
+//! Arithmetic on `Iterator.size_hint()` values.
//!
use std::usize;
use std::cmp;
use std::u32;
-/// **SizeHint** is the return type of **Iterator::size_hint()**.
+/// `SizeHint` is the return type of `Iterator::size_hint()`.
pub type SizeHint = (usize, Option<usize>);
-/// Add **SizeHint** correctly.
+/// Add `SizeHint` correctly.
#[inline]
pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
let min = a.0.saturating_add(b.0);
@@ -20,7 +20,7 @@ pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
(min, max)
}
-/// Add **x** correctly to a **SizeHint**.
+/// Add `x` correctly to a `SizeHint`.
#[inline]
pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
@@ -29,7 +29,7 @@ pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
(low, hi)
}
-/// Sbb **x** correctly to a **SizeHint**.
+/// Subtract `x` correctly from a `SizeHint`.
#[inline]
#[allow(dead_code)]
pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
@@ -40,7 +40,7 @@ pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
}
-/// Multiply **SizeHint** correctly
+/// Multiply `SizeHint` correctly
///
/// ```ignore
/// use std::usize;
@@ -66,7 +66,7 @@ pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
(low, hi)
}
-/// Multiply **x** correctly with a **SizeHint**.
+/// Multiply `x` correctly with a `SizeHint`.
#[inline]
pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
let (mut low, mut hi) = sh;
@@ -75,7 +75,7 @@ pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
(low, hi)
}
-/// Raise `base` correctly by a **`SizeHint`** exponent.
+/// Raise `base` correctly by a `SizeHint` exponent.
#[inline]
pub fn pow_scalar_base(base: usize, exp: SizeHint) -> SizeHint {
let exp_low = cmp::min(exp.0, u32::MAX as usize) as u32;
diff --git a/vendor/itertools/src/tuple_impl.rs b/vendor/itertools/src/tuple_impl.rs
index d914e0323..06b5c13cb 100644
--- a/vendor/itertools/src/tuple_impl.rs
+++ b/vendor/itertools/src/tuple_impl.rs
@@ -162,8 +162,8 @@ pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
}
TupleWindows {
- last,
iter,
+ last,
}
}
diff --git a/vendor/itertools/src/unique_impl.rs b/vendor/itertools/src/unique_impl.rs
index 2240f36ed..4e81e78ec 100644
--- a/vendor/itertools/src/unique_impl.rs
+++ b/vendor/itertools/src/unique_impl.rs
@@ -1,6 +1,5 @@
-
use std::collections::HashMap;
-use std::collections::hash_map::{Entry};
+use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::fmt;
use std::iter::FusedIterator;
@@ -12,7 +11,9 @@ use std::iter::FusedIterator;
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct UniqueBy<I: Iterator, V, F> {
iter: I,
- // Use a hashmap for the entry API
+ // Use a Hashmap for the Entry API in order to prevent hashing twice.
+ // This can maybe be replaced with a HashSet once `get_or_insert_with`
+ // or a proper Entry API for Hashset is stable and meets this msrv
used: HashMap<V, ()>,
f: F,
}
diff --git a/vendor/itertools/src/unziptuple.rs b/vendor/itertools/src/unziptuple.rs
index f468f05e0..7af29ec4a 100644
--- a/vendor/itertools/src/unziptuple.rs
+++ b/vendor/itertools/src/unziptuple.rs
@@ -39,11 +39,11 @@ macro_rules! impl_unzip_iter {
#[allow(non_snake_case)]
impl<IT: Iterator<Item = ($($T,)*)>, $($T, $FromT: Default + Extend<$T>),* > MultiUnzip<($($FromT,)*)> for IT {
fn multiunzip(self) -> ($($FromT,)*) {
- // This implementation mirrors the logic of Iterator::unzip as close as possible.
- // Unfortunately a lot of the used api there is still unstable represented by
- // the commented out parts that follow.
+ // This implementation mirrors the logic of Iterator::unzip resp. Extend for (A, B) as close as possible.
+ // Unfortunately a lot of the used api there is still unstable (https://github.com/rust-lang/rust/issues/72631).
//
- // https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2816-2844
+ // Iterator::unzip: https://doc.rust-lang.org/src/core/iter/traits/iterator.rs.html#2825-2865
+ // Extend for (A, B): https://doc.rust-lang.org/src/core/iter/traits/collect.rs.html#370-411
let mut res = ($($FromT::default(),)*);
let ($($FromT,)*) = &mut res;
diff --git a/vendor/itertools/src/ziptuple.rs b/vendor/itertools/src/ziptuple.rs
index b7902ae53..6d3a584c4 100644
--- a/vendor/itertools/src/ziptuple.rs
+++ b/vendor/itertools/src/ziptuple.rs
@@ -36,6 +36,7 @@ pub struct Zip<T> {
///
/// assert_eq!(results, [0 + 3, 10 + 7, 29, 36]);
/// ```
+/// [`izip!()`]: crate::izip
pub fn multizip<T, U>(t: U) -> Zip<T>
where Zip<T>: From<U>,
Zip<T>: Iterator,
diff --git a/vendor/itertools/tests/adaptors_no_collect.rs b/vendor/itertools/tests/adaptors_no_collect.rs
index a47f906f9..103db23f1 100644
--- a/vendor/itertools/tests/adaptors_no_collect.rs
+++ b/vendor/itertools/tests/adaptors_no_collect.rs
@@ -11,12 +11,11 @@ impl Iterator for PanickingCounter {
fn next(&mut self) -> Option<Self::Item> {
self.curr += 1;
- if self.curr == self.max {
- panic!(
- "Input iterator reached maximum of {} suggesting collection by adaptor",
- self.max
- );
- }
+ assert_ne!(
+ self.curr, self.max,
+ "Input iterator reached maximum of {} suggesting collection by adaptor",
+ self.max
+ );
Some(())
}
diff --git a/vendor/itertools/tests/quick.rs b/vendor/itertools/tests/quick.rs
index 7e222a641..0adcf1ad7 100644
--- a/vendor/itertools/tests/quick.rs
+++ b/vendor/itertools/tests/quick.rs
@@ -258,12 +258,13 @@ where
let mut it = get_it();
for _ in 0..(counts.len() - 1) {
- if let None = it.next() {
+ #[allow(clippy::manual_assert)]
+ if it.next().is_none() {
panic!("Iterator shouldn't be finished, may not be deterministic");
}
}
- if let None = it.next() {
+ if it.next().is_none() {
break 'outer;
}
@@ -438,7 +439,7 @@ quickcheck! {
}
assert_eq!(answer, actual);
- assert_eq!(answer.into_iter().last(), a.clone().multi_cartesian_product().last());
+ assert_eq!(answer.into_iter().last(), a.multi_cartesian_product().last());
}
#[allow(deprecated)]
@@ -498,15 +499,13 @@ quickcheck! {
exact_size(it)
}
- fn equal_merge(a: Vec<i16>, b: Vec<i16>) -> bool {
- let mut sa = a.clone();
- let mut sb = b.clone();
- sa.sort();
- sb.sort();
- let mut merged = sa.clone();
- merged.extend(sb.iter().cloned());
+ fn equal_merge(mut a: Vec<i16>, mut b: Vec<i16>) -> bool {
+ a.sort();
+ b.sort();
+ let mut merged = a.clone();
+ merged.extend(b.iter().cloned());
merged.sort();
- itertools::equal(&merged, sa.iter().merge(&sb))
+ itertools::equal(&merged, a.iter().merge(&b))
}
fn size_merge(a: Iter<u16>, b: Iter<u16>) -> bool {
correct_size_hint(a.merge(b))
@@ -517,7 +516,7 @@ quickcheck! {
exact_size(multizip((a, b, c)))
}
fn size_zip_rc(a: Iter<i16>, b: Iter<i16>) -> bool {
- let rc = rciter(a.clone());
+ let rc = rciter(a);
correct_size_hint(multizip((&rc, &rc, b)))
}
@@ -526,19 +525,16 @@ quickcheck! {
correct_size_hint(izip!(filt, b.clone(), c.clone())) &&
exact_size(izip!(a, b, c))
}
- fn equal_kmerge(a: Vec<i16>, b: Vec<i16>, c: Vec<i16>) -> bool {
+ fn equal_kmerge(mut a: Vec<i16>, mut b: Vec<i16>, mut c: Vec<i16>) -> bool {
use itertools::free::kmerge;
- let mut sa = a.clone();
- let mut sb = b.clone();
- let mut sc = c.clone();
- sa.sort();
- sb.sort();
- sc.sort();
- let mut merged = sa.clone();
- merged.extend(sb.iter().cloned());
- merged.extend(sc.iter().cloned());
+ a.sort();
+ b.sort();
+ c.sort();
+ let mut merged = a.clone();
+ merged.extend(b.iter().cloned());
+ merged.extend(c.iter().cloned());
merged.sort();
- itertools::equal(merged.into_iter(), kmerge(vec![sa, sb, sc]))
+ itertools::equal(merged.into_iter(), kmerge(vec![a, b, c]))
}
// Any number of input iterators
@@ -610,7 +606,7 @@ quickcheck! {
fn size_2_zip_longest(a: Iter<i16>, b: Iter<i16>) -> bool {
let it = a.clone().zip_longest(b.clone());
let jt = a.clone().zip_longest(b.clone());
- itertools::equal(a.clone(),
+ itertools::equal(a,
it.filter_map(|elt| match elt {
EitherOrBoth::Both(x, _) => Some(x),
EitherOrBoth::Left(x) => Some(x),
@@ -618,7 +614,7 @@ quickcheck! {
}
))
&&
- itertools::equal(b.clone(),
+ itertools::equal(b,
jt.filter_map(|elt| match elt {
EitherOrBoth::Both(_, y) => Some(y),
EitherOrBoth::Right(y) => Some(y),
@@ -721,7 +717,7 @@ quickcheck! {
assert_eq!(expected_first, curr_perm);
- while let Some(next_perm) = perms.next() {
+ for next_perm in perms {
assert!(
next_perm > curr_perm,
"next perm isn't greater-than current; next_perm={:?} curr_perm={:?} n={}",
@@ -943,8 +939,7 @@ quickcheck! {
fn fuzz_group_by_lazy_1(it: Iter<u8>) -> bool {
let jt = it.clone();
let groups = it.group_by(|k| *k);
- let res = itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x));
- res
+ itertools::equal(jt, groups.into_iter().flat_map(|(_, x)| x))
}
}
@@ -1286,7 +1281,7 @@ quickcheck! {
.map(|i| (i % modulo, i))
.into_group_map()
.into_iter()
- .map(|(key, vals)| (key, vals.into_iter().fold(0u64, |acc, val| acc + val)))
+ .map(|(key, vals)| (key, vals.into_iter().sum()))
.collect::<HashMap<_,_>>();
assert_eq!(lookup, group_map_lookup);
@@ -1551,10 +1546,10 @@ quickcheck! {
}
quickcheck! {
- #[test]
fn counts(nums: Vec<isize>) -> TestResult {
let counts = nums.iter().counts();
for (&item, &count) in counts.iter() {
+ #[allow(clippy::absurd_extreme_comparisons)]
if count <= 0 {
return TestResult::failed();
}
@@ -1602,7 +1597,7 @@ quickcheck! {
fn is_fused<I: Iterator>(mut it: I) -> bool
{
- while let Some(_) = it.next() {}
+ for _ in it.by_ref() {}
for _ in 0..10{
if it.next().is_some(){
return false;
@@ -1693,3 +1688,62 @@ quickcheck! {
}
}
+quickcheck! {
+ fn min_set_contains_min(a: Vec<(usize, char)>) -> bool {
+ let result_set = a.iter().min_set();
+ if let Some(result_element) = a.iter().min() {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+
+ fn min_set_by_contains_min(a: Vec<(usize, char)>) -> bool {
+ let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1);
+ let result_set = a.iter().min_set_by(compare);
+ if let Some(result_element) = a.iter().min_by(compare) {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+
+ fn min_set_by_key_contains_min(a: Vec<(usize, char)>) -> bool {
+ let key = |x: &&(usize, char)| x.1;
+ let result_set = a.iter().min_set_by_key(&key);
+ if let Some(result_element) = a.iter().min_by_key(&key) {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+
+ fn max_set_contains_max(a: Vec<(usize, char)>) -> bool {
+ let result_set = a.iter().max_set();
+ if let Some(result_element) = a.iter().max() {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+
+ fn max_set_by_contains_max(a: Vec<(usize, char)>) -> bool {
+ let compare = |x: &&(usize, char), y: &&(usize, char)| x.1.cmp(&y.1);
+ let result_set = a.iter().max_set_by(compare);
+ if let Some(result_element) = a.iter().max_by(compare) {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+
+ fn max_set_by_key_contains_max(a: Vec<(usize, char)>) -> bool {
+ let key = |x: &&(usize, char)| x.1;
+ let result_set = a.iter().max_set_by_key(&key);
+ if let Some(result_element) = a.iter().max_by_key(&key) {
+ result_set.contains(&result_element)
+ } else {
+ result_set.is_empty()
+ }
+ }
+}
diff --git a/vendor/itertools/tests/specializations.rs b/vendor/itertools/tests/specializations.rs
index 199cf562a..057e11c9f 100644
--- a/vendor/itertools/tests/specializations.rs
+++ b/vendor/itertools/tests/specializations.rs
@@ -129,7 +129,7 @@ quickcheck! {
check_results_specialized!(it, |i| {
let mut parameters_from_fold = vec![];
let fold_result = i.fold(vec![], |mut acc, v| {
- parameters_from_fold.push((acc.clone(), v.clone()));
+ parameters_from_fold.push((acc.clone(), v));
acc.push(v);
acc
});
@@ -139,7 +139,7 @@ quickcheck! {
let mut parameters_from_all = vec![];
let first = i.next();
let all_result = i.all(|x| {
- parameters_from_all.push(x.clone());
+ parameters_from_all.push(x);
Some(x)==first
});
(parameters_from_all, all_result)
diff --git a/vendor/itertools/tests/test_core.rs b/vendor/itertools/tests/test_core.rs
index a7b7449d3..df94eb665 100644
--- a/vendor/itertools/tests/test_core.rs
+++ b/vendor/itertools/tests/test_core.rs
@@ -116,7 +116,7 @@ fn chain2() {
fn write_to() {
let xs = [7, 9, 8];
let mut ys = [0; 5];
- let cnt = ys.iter_mut().set_from(xs.iter().map(|x| *x));
+ let cnt = ys.iter_mut().set_from(xs.iter().copied());
assert!(cnt == xs.len());
assert!(ys == [7, 9, 8, 0, 0]);
@@ -180,15 +180,10 @@ fn batching() {
let ys = [(0, 1), (2, 1)];
// An iterator that gathers elements up in pairs
- let pit = xs.iter().cloned().batching(|it| {
- match it.next() {
- None => None,
- Some(x) => match it.next() {
- None => None,
- Some(y) => Some((x, y)),
- }
- }
- });
+ let pit = xs
+ .iter()
+ .cloned()
+ .batching(|it| it.next().and_then(|x| it.next().map(|y| (x, y))));
it::assert_equal(pit, ys.iter().cloned());
}
diff --git a/vendor/itertools/tests/test_std.rs b/vendor/itertools/tests/test_std.rs
index 2049d1597..f59034234 100644
--- a/vendor/itertools/tests/test_std.rs
+++ b/vendor/itertools/tests/test_std.rs
@@ -1,5 +1,3 @@
-use paste;
-use permutohedron;
use quickcheck as qc;
use rand::{distributions::{Distribution, Standard}, Rng, SeedableRng, rngs::StdRng};
use rand::{seq::SliceRandom, thread_rng};
@@ -123,12 +121,12 @@ fn unique() {
#[test]
fn intersperse() {
let xs = ["a", "", "b", "c"];
- let v: Vec<&str> = xs.iter().map(|x| x.clone()).intersperse(", ").collect();
+ let v: Vec<&str> = xs.iter().cloned().intersperse(", ").collect();
let text: String = v.concat();
assert_eq!(text, "a, , b, c".to_string());
let ys = [0, 1, 2, 3];
- let mut it = ys[..0].iter().map(|x| *x).intersperse(1);
+ let mut it = ys[..0].iter().copied().intersperse(1);
assert!(it.next() == None);
}
@@ -474,7 +472,7 @@ impl<T: Clone + Send, R: Clone + Rng + SeedableRng + Send> qc::Arbitrary for Ran
// Check that taking the k smallest is the same as
// sorting then taking the k first elements
-fn k_smallest_sort<I>(i: I, k: u16) -> ()
+fn k_smallest_sort<I>(i: I, k: u16)
where
I: Iterator + Clone,
I::Item: Ord + Debug,
@@ -538,10 +536,10 @@ fn sorted_by_cached_key() {
fn test_multipeek() {
let nums = vec![1u8,2,3,4,5];
- let mp = multipeek(nums.iter().map(|&x| x));
+ let mp = multipeek(nums.iter().copied());
assert_eq!(nums, mp.collect::<Vec<_>>());
- let mut mp = multipeek(nums.iter().map(|&x| x));
+ let mut mp = multipeek(nums.iter().copied());
assert_eq!(mp.peek(), Some(&1));
assert_eq!(mp.next(), Some(1));
assert_eq!(mp.peek(), Some(&2));
@@ -579,7 +577,7 @@ fn test_multipeek_peeking_next() {
use crate::it::PeekingNext;
let nums = vec![1u8,2,3,4,5,6,7];
- let mut mp = multipeek(nums.iter().map(|&x| x));
+ let mut mp = multipeek(nums.iter().copied());
assert_eq!(mp.peeking_next(|&x| x != 0), Some(1));
assert_eq!(mp.next(), Some(2));
assert_eq!(mp.peek(), Some(&3));
@@ -604,10 +602,10 @@ fn test_multipeek_peeking_next() {
fn test_peek_nth() {
let nums = vec![1u8,2,3,4,5];
- let iter = peek_nth(nums.iter().map(|&x| x));
+ let iter = peek_nth(nums.iter().copied());
assert_eq!(nums, iter.collect::<Vec<_>>());
- let mut iter = peek_nth(nums.iter().map(|&x| x));
+ let mut iter = peek_nth(nums.iter().copied());
assert_eq!(iter.peek_nth(0), Some(&1));
assert_eq!(iter.peek_nth(0), Some(&1));
@@ -638,7 +636,7 @@ fn test_peek_nth() {
fn test_peek_nth_peeking_next() {
use it::PeekingNext;
let nums = vec![1u8,2,3,4,5,6,7];
- let mut iter = peek_nth(nums.iter().map(|&x| x));
+ let mut iter = peek_nth(nums.iter().copied());
assert_eq!(iter.peeking_next(|&x| x != 0), Some(1));
assert_eq!(iter.next(), Some(2));
@@ -694,7 +692,7 @@ fn group_by() {
}
}
- let toupper = |ch: &char| ch.to_uppercase().nth(0).unwrap();
+ let toupper = |ch: &char| ch.to_uppercase().next().unwrap();
// try all possible orderings
for indices in permutohedron::Heap::new(&mut [0, 1, 2, 3]) {
@@ -993,6 +991,54 @@ fn diff_shorter() {
}
#[test]
+fn extrema_set() {
+ use std::cmp::Ordering;
+
+ // A peculiar type: Equality compares both tuple items, but ordering only the
+ // first item. Used to distinguish equal elements.
+ #[derive(Clone, Debug, PartialEq, Eq)]
+ struct Val(u32, u32);
+
+ impl PartialOrd<Val> for Val {
+ fn partial_cmp(&self, other: &Val) -> Option<Ordering> {
+ self.0.partial_cmp(&other.0)
+ }
+ }
+
+ impl Ord for Val {
+ fn cmp(&self, other: &Val) -> Ordering {
+ self.0.cmp(&other.0)
+ }
+ }
+
+ assert_eq!(None::<u32>.iter().min_set(), Vec::<&u32>::new());
+ assert_eq!(None::<u32>.iter().max_set(), Vec::<&u32>::new());
+
+ assert_eq!(Some(1u32).iter().min_set(), vec![&1]);
+ assert_eq!(Some(1u32).iter().max_set(), vec![&1]);
+
+ let data = vec![Val(0, 1), Val(2, 0), Val(0, 2), Val(1, 0), Val(2, 1)];
+
+ let min_set = data.iter().min_set();
+ assert_eq!(min_set, vec![&Val(0, 1), &Val(0, 2)]);
+
+ let min_set_by_key = data.iter().min_set_by_key(|v| v.1);
+ assert_eq!(min_set_by_key, vec![&Val(2, 0), &Val(1, 0)]);
+
+ let min_set_by = data.iter().min_set_by(|x, y| x.1.cmp(&y.1));
+ assert_eq!(min_set_by, vec![&Val(2, 0), &Val(1, 0)]);
+
+ let max_set = data.iter().max_set();
+ assert_eq!(max_set, vec![&Val(2, 0), &Val(2, 1)]);
+
+ let max_set_by_key = data.iter().max_set_by_key(|v| v.1);
+ assert_eq!(max_set_by_key, vec![&Val(0, 2)]);
+
+ let max_set_by = data.iter().max_set_by(|x, y| x.1.cmp(&y.1));
+ assert_eq!(max_set_by, vec![&Val(0, 2)]);
+}
+
+#[test]
fn minmax() {
use std::cmp::Ordering;
use crate::it::MinMaxResult;
@@ -1043,9 +1089,9 @@ fn format() {
let t2 = format!("{:?}", data.iter().format("--"));
assert_eq!(t2, ans2);
- let dataf = [1.1, 2.71828, -22.];
+ let dataf = [1.1, 5.71828, -22.];
let t3 = format!("{:.2e}", dataf.iter().format(", "));
- assert_eq!(t3, "1.10e0, 2.72e0, -2.20e1");
+ assert_eq!(t3, "1.10e0, 5.72e0, -2.20e1");
}
#[test]
@@ -1062,7 +1108,7 @@ fn fold_while() {
let vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let sum = vec.into_iter().fold_while(0, |acc, item| {
iterations += 1;
- let new_sum = acc.clone() + item;
+ let new_sum = acc + item;
if new_sum <= 20 {
FoldWhile::Continue(new_sum)
} else {
@@ -1095,7 +1141,7 @@ fn tree_fold1() {
"0 1 x 2 3 x x 4 5 x 6 7 x x x 8 9 x 10 11 x x 12 13 x 14 15 x x x x",
];
for (i, &s) in x.iter().enumerate() {
- let expected = if s == "" { None } else { Some(s.to_string()) };
+ let expected = if s.is_empty() { None } else { Some(s.to_string()) };
let num_strings = (0..i).map(|x| x.to_string());
let actual = num_strings.tree_fold1(|a, b| format!("{} {} x", a, b));
assert_eq!(actual, expected);
@@ -1119,4 +1165,4 @@ fn multiunzip() {
let (): () = [(), (), ()].iter().cloned().multiunzip();
let t: (Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>, Vec<_>) = [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)].iter().cloned().multiunzip();
assert_eq!(t, (vec![0], vec![1], vec![2], vec![3], vec![4], vec![5], vec![6], vec![7], vec![8], vec![9], vec![10], vec![11]));
-} \ No newline at end of file
+}
diff --git a/vendor/itertools/tests/zip.rs b/vendor/itertools/tests/zip.rs
index 5801b4232..75157d34f 100644
--- a/vendor/itertools/tests/zip.rs
+++ b/vendor/itertools/tests/zip.rs
@@ -29,8 +29,8 @@ fn test_zip_longest_size_hint() {
fn test_double_ended_zip_longest() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
- let a = xs.iter().map(|&x| x);
- let b = ys.iter().map(|&x| x);
+ let a = xs.iter().copied();
+ let b = ys.iter().copied();
let mut it = a.zip_longest(b);
assert_eq!(it.next(), Some(Both(1, 1)));
assert_eq!(it.next(), Some(Both(2, 2)));
@@ -45,8 +45,8 @@ fn test_double_ended_zip_longest() {
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
- let a = xs.iter().map(|&x| x);
- let b = ys.iter().map(|&x| x);
+ let a = xs.iter().copied();
+ let b = ys.iter().copied();
let mut it = multizip((a, b));
assert_eq!(it.next_back(), Some((4, 7)));
assert_eq!(it.next_back(), Some((3, 3)));
diff --git a/vendor/itoa/.cargo-checksum.json b/vendor/itoa/.cargo-checksum.json
index 4af98bbb4..5c464a6c5 100644
--- a/vendor/itoa/.cargo-checksum.json
+++ b/vendor/itoa/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"2e653183f335114876acd61d9e4eeb893b202e6842d4f128bbae40c121439432","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"4bc11375d5c1c2c7cf4988b94d44c0f1fe8cdf2d68755fef127cd5ba0d70b939","benches/bench.rs":"636f3093bd461210ad3063289d455f90669c4a1be3273bcd30898de39f02c641","src/lib.rs":"55c938bd2421bf2adc505504ecfe44dd8f537f234b3f3555bbaf6df87d35b54b","src/udiv128.rs":"16394f767854452756372d74f8025f7329fd8b61a676d81edf489681a6332ee9","tests/test.rs":"f7404fc5f7cd1bdaf74a3b64a70d5b30586241ddc1ce2c82bd1b564999fcce0e"},"package":"6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"} \ No newline at end of file
+{"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
diff --git a/vendor/itoa/Cargo.toml b/vendor/itoa/Cargo.toml
index c3a1bd601..bab03ecf7 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.3"
+version = "1.0.4"
authors = ["David Tolnay <dtolnay@gmail.com>"]
exclude = [
"performance.png",
@@ -32,3 +32,7 @@ repository = "https://github.com/dtolnay/itoa"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
+
+[dependencies.no-panic]
+version = "0.1"
+optional = true
diff --git a/vendor/itoa/src/lib.rs b/vendor/itoa/src/lib.rs
index 002156cb8..7c3616e51 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.3")]
+#![doc(html_root_url = "https://docs.rs/itoa/1.0.4")]
#![no_std]
#![allow(
clippy::cast_lossless,
@@ -43,6 +43,8 @@ mod udiv128;
use core::mem::{self, MaybeUninit};
use core::{ptr, slice, str};
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
/// A correctly sized stack allocation for the formatted integer to be written
/// into.
@@ -76,6 +78,7 @@ impl Buffer {
/// This is a cheap operation; you don't need to worry about reusing buffers
/// for efficiency.
#[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
pub fn new() -> Buffer {
let bytes = [MaybeUninit::<u8>::uninit(); I128_MAX_LEN];
Buffer { bytes }
@@ -83,6 +86,7 @@ impl Buffer {
/// Print an integer into this buffer and return a reference to its string
/// representation within the buffer.
+ #[cfg_attr(feature = "no-panic", no_panic)]
pub fn format<I: Integer>(&mut self, i: I) -> &str {
i.write(unsafe {
&mut *(&mut self.bytes as *mut [MaybeUninit<u8>; I128_MAX_LEN]
@@ -122,6 +126,7 @@ macro_rules! impl_Integer {
#[allow(unused_comparisons)]
#[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
let is_nonnegative = self >= 0;
let mut n = if is_nonnegative {
@@ -223,6 +228,7 @@ macro_rules! impl_Integer128 {
#[allow(unused_comparisons)]
#[inline]
+ #[cfg_attr(feature = "no-panic", no_panic)]
fn write(self, buf: &mut [MaybeUninit<u8>; $max_len]) -> &str {
let is_nonnegative = self >= 0;
let n = if is_nonnegative {
diff --git a/vendor/itoa/src/udiv128.rs b/vendor/itoa/src/udiv128.rs
index df53eb526..0587047a7 100644
--- a/vendor/itoa/src/udiv128.rs
+++ b/vendor/itoa/src/udiv128.rs
@@ -1,5 +1,9 @@
+#[cfg(feature = "no-panic")]
+use no_panic::no_panic;
+
/// Multiply unsigned 128 bit integers, return upper 128 bits of the result
#[inline]
+#[cfg_attr(feature = "no-panic", no_panic)]
fn u128_mulhi(x: u128, y: u128) -> u128 {
let x_lo = x as u64;
let x_hi = (x >> 64) as u64;
@@ -26,6 +30,7 @@ fn u128_mulhi(x: u128, y: u128) -> u128 {
/// Implementation, 1994, pp. 61–72
///
#[inline]
+#[cfg_attr(feature = "no-panic", no_panic)]
pub fn udivmod_1e19(n: u128) -> (u128, u64) {
let d = 10_000_000_000_000_000_000_u64; // 10^19
diff --git a/vendor/libc/.cargo-checksum.json b/vendor/libc/.cargo-checksum.json
index f16c56427..631af7226 100644
--- a/vendor/libc/.cargo-checksum.json
+++ b/vendor/libc/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"1549dc2db0ecd74316f52b2d14b15144ae970a848bf3d54c048844ed7a35df2a","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"94cbaad15021e287a1b9546a697b04c1e560f1204b52204ffaaea5975c5d03b9","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":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","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":"56dc7604509f49b274770cade97a1874c8955c3b0a445fb857707ae0ca6df41b","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"d0e8246063cae113806524a63a47c6c0628cc54a3ef03e938e89964f8b4f08b4","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"a6eee615e6ca5a6e04b526bb6b22d13b9356e87e51825cda33476c37a46cb0ef","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"755dafaf3f0945e798c34ea94c48e8552804ce60e2a15a4f0649f9d1aceaf422","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":"cc65a73b0fa95a77044a4b3ee76d6eceb9773b55aea7d73bdf070e6f66e9ea38","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":"0ed92eb93e78299cd7de0ae9daebb04a53b3c2d5e6a078e1fcd977f2a86bffc3","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"ec229cc7af2511cb510c078e87e90ee2625090bfe94f40eb35f73d79143533aa","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","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":"1e35b4773384ea143810cdce4b96f47108b37446430da30c96a0d1651656d73d","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"8f9613e50c2771b33d7cf817a735d536b389ec57f861b9486d870373c768276e","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":"228505fa48292e74b06acbed96196801595a4b822da2126a6d6c7fa773cff8bc","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":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","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":"962741303dc24a5b9653f2e9b0b4ad9eb42fc54daa0a70ca70a7ce175e75094b","src/unix/linux_like/emscripten/align.rs":"86c95cbed7a7161b1f23ee06843e7b0e2340ad92b2cb86fe2a8ef3e0e8c36216","src/unix/linux_like/emscripten/mod.rs":"c69c90606d4362f8de89b8816df0ded724ed64b53bf55d15681fde171b7bb361","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":"e20013ed91edcfb7f84f3f9f5a9ef827fd5c406e24b65989d8438da332236ef6","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":"92ea7edc0e24f79dfbf5e3efc2d7509bed230562036e6aa85ef4f2c8088ecc8f","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":"0d7849eb2435ec1f49b6774872a0518f0129c50f37c9d38b37b1535722777a22","src/unix/linux_like/linux/gnu/b32/mod.rs":"8da281da578cdee972e952b118b903b370320897a7e335342a15e1359864bef2","src/unix/linux_like/linux/gnu/b32/powerpc.rs":"049d6211ba4a9304bd4497c160bc21ae847c24e0528dd9d76263f16192e6aff5","src/unix/linux_like/linux/gnu/b32/riscv32/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs":"a4256148cec0bb672c8dfa605866930d9761af9655721de72ae41eeeb8fdbf6d","src/unix/linux_like/linux/gnu/b32/sparc/align.rs":"21adbed27df73e2d1ed934aaf733a643003d7baf2bde9c48ea440895bcca6d41","src/unix/linux_like/linux/gnu/b32/sparc/mod.rs":"525618615aa0cb80c6c90860bf579dfed8db307fffd56b97dc235fb945419434","src/unix/linux_like/linux/gnu/b32/x86/align.rs":"e4bafdc4a519a7922a81b37a62bbfd1177a2f620890eef8f1fbc47162e9eb413","src/unix/linux_like/linux/gnu/b32/x86/mod.rs":"78b4038852986436888c63be9258037cf642124daee9d5fa5cef2bf8e412bf54","src/unix/linux_like/linux/gnu/b64/aarch64/align.rs":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","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":"c72a08011c32f82919e930e0d89044d8feb65fd41bf80647436756c290344eb8","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","src/unix/linux_like/linux/gnu/b64/mips64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/mips64/mod.rs":"17aad16329431d83e1909e3a08022f6e28f4bcba7dec4a967fe1a321a6a43b99","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":"97e0ecf11ecce793a13fec39654fb513c5479edf7faa7a276fa714b61993d0fc","src/unix/linux_like/linux/gnu/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs":"b3fe290afe63d2d6e315d0cf1f775464e9c1f2a1906d243c1af74a137a4031cb","src/unix/linux_like/linux/gnu/b64/s390x.rs":"254f00266ecf9644a4b469457cb37c4dd6c055820926c1de0fb9035b6048e75c","src/unix/linux_like/linux/gnu/b64/sparc64/align.rs":"e29c4868bbecfa4a6cd8a2ad06193f3bbc78a468cc1dc9df83f002f1268130d9","src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs":"87dd7f3d5bf3c09f4064ec738e306cc9cc41ad49b4a5df62c5983301c3bbf99a","src/unix/linux_like/linux/gnu/b64/x86_64/align.rs":"62e822478356db4a73b6bbd1b36d825b893939ab4b308ec11b0578bcc4b49769","src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs":"f0db9914315d5a3d51bf5ec04a0ae6584f2e1688b9258ce132b617e67d9bd7a9","src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs":"b88ef8a1eaa9ed73bf2acb8192afb73af987a92abb94140c6376fc83f2fa5553","src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs":"79305936a60d342efdc10519ba89507d6b48e65f13f33090d3b04dc9655ceed0","src/unix/linux_like/linux/gnu/mod.rs":"fd62b48974dd2f97f6e8fa2a30624e8d69fdedc5d3b0ab2f3f09516e88a8769a","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"af94b1a6d844bed87bb4c93de0a12f160ca1f918f5234d7fe17511d4e424dedc","src/unix/linux_like/linux/musl/b32/arm/align.rs":"3e8ac052c1043764776b54c93ba4260e061df998631737a897d9d47d54f7b80c","src/unix/linux_like/linux/musl/b32/arm/mod.rs":"e5faee8efda8a225ea0b17d4d6f9e893a678e73773fa62c549a8e19c106b9f04","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":"df8f8b529a6cc6b8a7326639e83303cf1320c6c50d76517c17d42bcf45f6240a","src/unix/linux_like/linux/musl/b32/mod.rs":"7b3d9dfd8605b00bb9b5fa1439abe5ebf60199c7fa033eee555e8d181e93ffa2","src/unix/linux_like/linux/musl/b32/powerpc.rs":"c957d99a4d4371d2411a5769be8cf344516bf9ddc1011f977501a4eb57cb4e82","src/unix/linux_like/linux/musl/b32/riscv32/align.rs":"efd2accf33b87de7c7547903359a5da896edc33cd6c719552c7474b60d4a5d48","src/unix/linux_like/linux/musl/b32/riscv32/mod.rs":"698f77bfcc838f82126c54f7387881fe3e89490117e5a4f333d1b4433823a672","src/unix/linux_like/linux/musl/b32/x86/align.rs":"08e77fbd7435d7dec2ff56932433bece3f02e47ce810f89004a275a86d39cbe1","src/unix/linux_like/linux/musl/b32/x86/mod.rs":"199a91e90b454f9dc32770d5204cc4f6e5b8f144e0e34a1c91829949d6e804b3","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":"9c4878df0fea0e0affd85346e0bc191abdc5e41e74dc9199b5644ec33d29c300","src/unix/linux_like/linux/musl/b64/mips64.rs":"1fa4974fe412b22c3555d3e240dbf00cc04a5287c751035ddf08a0470d4a7c9a","src/unix/linux_like/linux/musl/b64/mod.rs":"8c10627bd582cb272514e7350ae4743a65d489356eae039d2e7e55cd533fbbc8","src/unix/linux_like/linux/musl/b64/powerpc64.rs":"36694cbdcdc33879e00502d55cb95eaa0096d213538993dd39c3da800cdd06d1","src/unix/linux_like/linux/musl/b64/riscv64/align.rs":"d321491612be8d5c61b6ec2dc0111beb3a22e58803f99cd37543efe86621b119","src/unix/linux_like/linux/musl/b64/riscv64/mod.rs":"36621aca8ecf714f8dd42662dc2997833d95b9f129ef8c220503362e21efd695","src/unix/linux_like/linux/musl/b64/s390x.rs":"c7ebabc4e1bdbbd97e5065faa3a57f41f473570920582d979f9e9d4f77448546","src/unix/linux_like/linux/musl/b64/x86_64/align.rs":"77309276ad7a42cbe59ca381f23590b7a143aded05555b34a5b307b808cbca6e","src/unix/linux_like/linux/musl/b64/x86_64/mod.rs":"238789097a26abc8b7cd578ed1a8e6cb8672083054303902781983902cd66854","src/unix/linux_like/linux/musl/mod.rs":"c3365480375bc258ffe267e7a299d7b3bb542a908bef8881f503ddc25ba8fc1f","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":"a056bbf718ddd775519058706bdb4909b56e6256985869e3c3132aa8ec5faca0","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":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","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":"bf6985e901041a61e90ccee1296b35a4c62ef90aa528d31989e1d647f072e79a","src/unix/linux_like/linux/uclibc/x86_64/other.rs":"42c3f71e58cabba373f6a55a623f3c31b85049eb64824c09c2b082b3b2d6a0a8","src/unix/linux_like/mod.rs":"09fa012e027bfcdaabee221c1b676804a9c7e0e04a4b64fdd98a50c9b5c2f674","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","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":"54633d606e4e0413274af0b5beb5e697e6c061b63feaa0704b026554cc9d9c3e","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":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"29387916ee7dc58f07478746024003215e631cd30953e8fa2a5c415f81839007","src/unix/solarish/mod.rs":"8914a68865af026c1f4fb1d5f02ba0053362ef34b813ad60cc4aa3a88aa4999e","src/unix/solarish/solaris.rs":"65b005453aefa9b9d4fc860fe77cfec80d8c97a51342b15daf55fc3e808bb384","src/unix/solarish/x86.rs":"e86e806df0caed72765040eaa2f3c883198d1aa91508540adf9b7008c77f522e","src/unix/solarish/x86_64.rs":"9074e813949f3c613afeac39d4118fb942c0b3c476232fc536489357cff5790f","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":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"} \ No newline at end of file
+{"files":{"CONTRIBUTING.md":"f480d10d2a506eecd23ae2e2dedb7a28b8bf6dae5f46f438dbb61be2003426fb","Cargo.toml":"04fa9ce26b0efcfe3dd51e3f1bbb81bb36f5d61982a11947283c7616d390549e","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"a8d47ff51ca256f56a8932dba07660672dbfe3004257ca8de708aac1415937a1","README.md":"776affa26b66843a2b4f1a1c8f88d92f6461b74568911450fea717e9db6f877b","build.rs":"1d0cbe878e98e970c3318cac0772215a9f44bd286d859d665da27872ba9d8818","rustfmt.toml":"eaa2ea84fc1ba0359b77680804903e07bb38d257ab11986b95b158e460f787b2","src/fixed_width_ints.rs":"7f986e5f5e68d25ef04d386fd2f640e8be8f15427a8d4a458ea01d26b8dca0ca","src/fuchsia/aarch64.rs":"378776a9e40766154a54c94c2a7b4675b5c302a38e6e42da99e67bfbaee60e56","src/fuchsia/align.rs":"ae1cf8f011a99737eabeb14ffff768e60f13b13363d7646744dbb0f443dab3d6","src/fuchsia/mod.rs":"cf7e0df0e655337d1c0852880817b6b514ef9599e2125232fc79cdf8eddd01ba","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":"a3f0dfff62d0f7f4f1b5f9a4e2b662acf233a46badbc5419d3cc2d735629a710","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":"bb61eec399428faee753b3df509410c51ed2ac51406d40559fcec290bb50e293","src/unix/bsd/freebsdlike/dragonfly/errno.rs":"8295b8bb0dfd38d2cdb4d9192cdeeb534cc6c3b208170e64615fa3e0edb3e578","src/unix/bsd/freebsdlike/dragonfly/mod.rs":"e4f33050d52d3e5c932da8d10e1f377e1ff609fb178ea986bfc458d31e37dc19","src/unix/bsd/freebsdlike/freebsd/aarch64.rs":"2a215bd6136b8617aacedf9be738ccee94da9d29b418e9a78101d6291c182352","src/unix/bsd/freebsdlike/freebsd/arm.rs":"59d6a670eea562fb87686e243e0a84603d29a2028a3d4b3f99ccc01bd04d2f47","src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs":"9808d152c1196aa647f1b0f0cf84dac8c930da7d7f897a44975545e3d9d17681","src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs":"23f189f188651762b38f40b4e9aba785625f6f9a52558a4a490510c3b1d08b53","src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs":"61cbe45f8499bedb168106b686d4f8239472f25c7553b069eec2afe197ff2df6","src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs":"57fee9dd251ac615ec7d32d293e0f0b6fa3bf28efbddd6d569765765aafb8b9b","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":"7df84dd6dee8b73fd4d72dd1638584d788e2a1a85f95746f7c5b330b8dc23655","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":"236ef119410d566ef94064bf13d734635eaeecb3635a5d21e8e9f91e7e3152ac","src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs":"2df36a7f122f6d6e5753cfb4d22e915cc80f6bc91c0161b3daae55a481bfd052","src/unix/bsd/freebsdlike/freebsd/mod.rs":"6a8eb9a1e35eec893de9c76a5be3ce29e4c3ca26db45fbcfa925bdd757f6352d","src/unix/bsd/freebsdlike/freebsd/powerpc.rs":"9ca3f82f88974e6db5569f2d76a5a3749b248a31747a6c0da5820492bdfeca42","src/unix/bsd/freebsdlike/freebsd/powerpc64.rs":"2dae3ecc87eac3b11657aa98915def55fc4b5c0de11fe26aae23329a54628a9a","src/unix/bsd/freebsdlike/freebsd/riscv64.rs":"8f591bd273464d684c4f64365f8ed56a8138175daa70d96008541393057a0dae","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":"a61d41f6fe01c06c6de5db2ed970522601eada133e6bac4ed2d1dfaceb576db2","src/unix/bsd/mod.rs":"817ca5719c36a74c84e52c6a56a5998b60d7f02351a405e034f08ebab079b63a","src/unix/bsd/netbsdlike/mod.rs":"b07a0e81085bd811fce7270f3b90fbfea29faf9593d9e39d9d2ebbb9a78bf25f","src/unix/bsd/netbsdlike/netbsd/aarch64.rs":"65dcb58d11e8d8028401a9d07ca3eb4cb4f053e04249cc877353449d84ccc4cb","src/unix/bsd/netbsdlike/netbsd/arm.rs":"58cdbb70b0d6f536551f0f3bb3725d2d75c4690db12c26c034e7d6ec4a924452","src/unix/bsd/netbsdlike/netbsd/mod.rs":"fa260decf53280d4fdf714af60f42d4774f8d6f2da71b0a55a6c2a85e422eb57","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":"079b11c99c6ca3cc5942c0e6d854541f8765c5058c2f024b84656697840e198b","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":"df7b6b7d8dd3441665bfe87f2abc942bddc65b8b10dfa9c83dd0422f68107891","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":"41b9d0f405cd474385acce06df0649f4eeaab3fe8fb4655f97806fa40bdf84d8","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":"e2b46404e44f7d63c26af9dbd79b4e166ef7bced2bc9c6746a26ca86e508e0d4","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":"5b32fcc0d60356c92ded4e0ba9bb32f0140a8bd75ba800486bf38294f61dbdbb","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":"c91813ee5e1bc817996c46be86d1f46802e73df2952cab576ea015490929afc5","src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs":"7169d07a9fd4716f7512719aec9fda5d8bed306dc0720ffc1b21696c9951e3c6","src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs":"387808d5398b24339e7e2bf7591150735011befc5b421fa713d7017c04a7b1da","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":"06abaca7fc85e805650ec807c4d06c888ff99e146e1ba2685f20840a86e35a2f","src/unix/linux_like/linux/gnu/no_align.rs":"9cd223135de75315840ff9c3fd5441ba1cb632b96b5c85a76f8316c86653db25","src/unix/linux_like/linux/mod.rs":"1d84f37fdfa4dfab1b758345af75e02485e2a18746830413c2afe5069a1e39ce","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":"0514b337aaa6e62be9e01e00702ef996c60319b7050ece155530147c20de9995","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":"7d8dfbd26ce958d9da17468b3c9d0b119ce7dbd59b3384551cd4423ce25db44a","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":"b84def53a49587e87f884c2bc28b21b290463b00b52e1d0309f2ba233a5b4a99","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":"3d03bd583aaf04f285f95ff8b53c9b5a891d3b64bfcda37a42648ec51c4c51e5","src/unix/mod.rs":"fbd5520d160a32a127608cd408905febe387773bbf05bfe199ef385fb5562e9c","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":"033768cb273daf2c8090d97252c2de9dba6809e6a5d2457f5727d724807695db","src/unix/solarish/compat.rs":"b07a5bfac925eb012003a459ba6bddbd3bfa9c44b3394da2ac5a602e54beae9c","src/unix/solarish/illumos.rs":"1369fb55325914654ba3ad02410b75a40c8c0008feed9704c28520be1ee49641","src/unix/solarish/mod.rs":"52a31038984e68582347f4b28fd64c01e6308ff4293628818bb279605e7b28c6","src/unix/solarish/solaris.rs":"36abcfb46fab6e7151a0c1f555b419e1267b82893f6e84d5d260308ba8eeb0c5","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":"4fae202af0327d768ed9e1b586b75816cce14fe2dc16947d2f3d381f209a54c1","src/windows/gnu/align.rs":"b2c13ec1b9f3b39a75c452c80c951dff9d0215e31d77e883b4502afb31794647","src/windows/gnu/mod.rs":"3c8c7edb7cdf5d0c44af936db2a94869585c69dfabeef30571b4f4e38375767a","src/windows/mod.rs":"090dd8fcd951d18f1905bca96188783c2e3f1433484926ecdcda144237ecec0f","src/windows/msvc/mod.rs":"c068271e00fca6b62bc4bf44bcf142cfc38caeded9b6c4e01d1ceef3ccf986f4","tests/const_fn.rs":"cb75a1f0864f926aebe79118fc34d51a0d1ade2c20a394e7774c7e545f21f1f4"},"package":"68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"} \ No newline at end of file
diff --git a/vendor/libc/Cargo.toml b/vendor/libc/Cargo.toml
index 5b54eced6..cb7c0047e 100644
--- a/vendor/libc/Cargo.toml
+++ b/vendor/libc/Cargo.toml
@@ -11,7 +11,7 @@
[package]
name = "libc"
-version = "0.2.132"
+version = "0.2.135"
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 4a18a8daa..eee82d0d8 100644
--- a/vendor/libc/src/fuchsia/mod.rs
+++ b/vendor/libc/src/fuchsia/mod.rs
@@ -3235,17 +3235,6 @@ f! {
minor as ::c_uint
}
- pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
- let major = major as ::dev_t;
- let minor = minor as ::dev_t;
- let mut dev = 0;
- dev |= (major & 0x00000fff) << 8;
- dev |= (major & 0xfffff000) << 32;
- dev |= (minor & 0x000000ff) << 0;
- dev |= (minor & 0xffffff00) << 12;
- dev
- }
-
pub fn CMSG_DATA(cmsg: *const cmsghdr) -> *mut c_uchar {
cmsg.offset(1) as *mut c_uchar
}
@@ -3322,6 +3311,17 @@ safe_f! {
pub {const} fn QCMD(cmd: ::c_int, type_: ::c_int) -> ::c_int {
(cmd << 8) | (type_ & 0x00ff)
}
+
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= (major & 0x00000fff) << 8;
+ dev |= (major & 0xfffff000) << 32;
+ dev |= (minor & 0x000000ff) << 0;
+ dev |= (minor & 0xffffff00) << 12;
+ dev
+ }
}
fn __CMSG_LEN(cmsg: *const cmsghdr) -> ::ssize_t {
@@ -4212,6 +4212,11 @@ extern "C" {
child: ::Option<unsafe extern "C" fn()>,
) -> ::c_int;
pub fn getgrgid(gid: ::gid_t) -> *mut ::group;
+
+ pub fn setgrent();
+ pub fn endgrent();
+ pub fn getgrent() -> *mut ::group;
+
pub fn getgrouplist(
user: *const ::c_char,
group: ::gid_t,
diff --git a/vendor/libc/src/unix/bsd/apple/mod.rs b/vendor/libc/src/unix/bsd/apple/mod.rs
index a831ca850..ed3028695 100644
--- a/vendor/libc/src/unix/bsd/apple/mod.rs
+++ b/vendor/libc/src/unix/bsd/apple/mod.rs
@@ -119,6 +119,15 @@ pub type thread_throughput_qos_policy_t = *mut thread_throughput_qos_policy;
pub type pthread_introspection_hook_t =
extern "C" fn(event: ::c_uint, thread: ::pthread_t, addr: *mut ::c_void, size: ::size_t);
+pub type pthread_jit_write_callback_t = ::Option<extern "C" fn(ctx: *mut ::c_void) -> ::c_int>;
+
+pub type os_unfair_lock = os_unfair_lock_s;
+pub type os_unfair_lock_t = *mut os_unfair_lock;
+
+pub type os_log_t = *mut ::c_void;
+pub type os_log_type_t = u8;
+pub type os_signpost_id_t = u64;
+pub type os_signpost_type_t = u8;
pub type vm_statistics_t = *mut vm_statistics;
pub type vm_statistics_data_t = vm_statistics;
@@ -137,6 +146,9 @@ pub type CCRNGStatus = ::CCCryptorStatus;
pub type copyfile_state_t = *mut ::c_void;
pub type copyfile_flags_t = u32;
+pub type attrgroup_t = u32;
+pub type vol_capabilities_set_t = [u32; 4];
+
deprecated_mach! {
pub type mach_timebase_info_data_t = mach_timebase_info;
}
@@ -981,6 +993,39 @@ s! {
pub uuid: ::uuid_t,
pub offset: u32,
}
+
+ pub struct attrlist {
+ pub bitmapcount: ::c_ushort,
+ pub reserved: u16,
+ pub commonattr: attrgroup_t,
+ pub volattr: attrgroup_t,
+ pub dirattr: attrgroup_t,
+ pub fileattr: attrgroup_t,
+ pub forkattr: attrgroup_t,
+ }
+
+ pub struct attrreference_t {
+ pub attr_dataoffset: i32,
+ pub attr_length: u32,
+ }
+
+ pub struct vol_capabilities_attr_t {
+ pub capabilities: vol_capabilities_set_t,
+ pub valid: vol_capabilities_set_t,
+ }
+
+ pub struct attribute_set_t {
+ pub commonattr: attrgroup_t,
+ pub volattr: attrgroup_t,
+ pub dirattr: attrgroup_t,
+ pub fileattr: attrgroup_t,
+ pub forkattr: attrgroup_t,
+ }
+
+ pub struct vol_attributes_attr_t {
+ pub validattr: attribute_set_t,
+ pub nativeattr: attribute_set_t,
+ }
}
s_no_extra_traits! {
@@ -1258,6 +1303,10 @@ s_no_extra_traits! {
pub l2p_contigbytes: ::off_t,
pub l2p_devoffset: ::off_t,
}
+
+ pub struct os_unfair_lock_s {
+ _os_unfair_lock_opaque: u32,
+ }
}
impl siginfo_t {
@@ -2539,6 +2588,27 @@ cfg_if! {
l2p_devoffset.hash(state);
}
}
+ impl PartialEq for os_unfair_lock {
+ fn eq(&self, other: &os_unfair_lock) -> bool {
+ self._os_unfair_lock_opaque == other._os_unfair_lock_opaque
+ }
+ }
+
+ impl Eq for os_unfair_lock {}
+
+ impl ::fmt::Debug for os_unfair_lock {
+ fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+ f.debug_struct("os_unfair_lock")
+ .field("_os_unfair_lock_opaque", &self._os_unfair_lock_opaque)
+ .finish()
+ }
+ }
+
+ impl ::hash::Hash for os_unfair_lock {
+ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
+ self._os_unfair_lock_opaque.hash(state);
+ }
+ }
}
}
@@ -2654,6 +2724,8 @@ 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 SEEK_HOLE: ::c_int = 3;
+pub const SEEK_DATA: ::c_int = 4;
pub const _IOFBF: ::c_int = 0;
pub const _IONBF: ::c_int = 2;
pub const _IOLBF: ::c_int = 1;
@@ -2671,11 +2743,13 @@ pub const _PC_PIPE_BUF: ::c_int = 6;
pub const _PC_CHOWN_RESTRICTED: ::c_int = 7;
pub const _PC_NO_TRUNC: ::c_int = 8;
pub const _PC_VDISABLE: ::c_int = 9;
-pub const O_DSYNC: ::c_int = 0x400000;
-pub const O_NOCTTY: ::c_int = 0x20000;
-pub const O_CLOEXEC: ::c_int = 0x1000000;
-pub const O_DIRECTORY: ::c_int = 0x100000;
-pub const O_SYMLINK: ::c_int = 0x200000;
+pub const O_EVTONLY: ::c_int = 0x00008000;
+pub const O_NOCTTY: ::c_int = 0x00020000;
+pub const O_DIRECTORY: ::c_int = 0x00100000;
+pub const O_SYMLINK: ::c_int = 0x00200000;
+pub const O_DSYNC: ::c_int = 0x00400000;
+pub const O_CLOEXEC: ::c_int = 0x01000000;
+pub const O_NOFOLLOW_ANY: ::c_int = 0x20000000;
pub const S_IFIFO: mode_t = 4096;
pub const S_IFCHR: mode_t = 8192;
pub const S_IFBLK: mode_t = 24576;
@@ -3796,6 +3870,11 @@ pub const _SC_TRACE_NAME_MAX: ::c_int = 128;
pub const _SC_TRACE_SYS_MAX: ::c_int = 129;
pub const _SC_TRACE_USER_EVENT_MAX: ::c_int = 130;
pub const _SC_PASS_MAX: ::c_int = 131;
+// `confstr` keys (only the values guaranteed by `man confstr`).
+pub const _CS_PATH: ::c_int = 1;
+pub const _CS_DARWIN_USER_DIR: ::c_int = 65536;
+pub const _CS_DARWIN_USER_TEMP_DIR: ::c_int = 65537;
+pub const _CS_DARWIN_USER_CACHE_DIR: ::c_int = 65538;
pub const PTHREAD_MUTEX_NORMAL: ::c_int = 0;
pub const PTHREAD_MUTEX_ERRORCHECK: ::c_int = 1;
@@ -3817,6 +3896,20 @@ pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
__opaque: [0; __PTHREAD_RWLOCK_SIZE__],
};
+pub const OS_UNFAIR_LOCK_INIT: os_unfair_lock = os_unfair_lock {
+ _os_unfair_lock_opaque: 0,
+};
+
+pub const OS_LOG_TYPE_DEFAULT: ::os_log_type_t = 0x00;
+pub const OS_LOG_TYPE_INFO: ::os_log_type_t = 0x01;
+pub const OS_LOG_TYPE_DEBUG: ::os_log_type_t = 0x02;
+pub const OS_LOG_TYPE_ERROR: ::os_log_type_t = 0x10;
+pub const OS_LOG_TYPE_FAULT: ::os_log_type_t = 0x11;
+
+pub const OS_SIGNPOST_EVENT: ::os_signpost_type_t = 0x00;
+pub const OS_SIGNPOST_INTERVAL_BEGIN: ::os_signpost_type_t = 0x01;
+pub const OS_SIGNPOST_INTERVAL_END: ::os_signpost_type_t = 0x02;
+
pub const MINSIGSTKSZ: ::size_t = 32768;
pub const SIGSTKSZ: ::size_t = 131072;
@@ -4678,6 +4771,145 @@ pub const COPYFILE_CONTINUE: ::c_int = 0;
pub const COPYFILE_SKIP: ::c_int = 1;
pub const COPYFILE_QUIT: ::c_int = 2;
+// <sys/attr.h>
+pub const ATTR_BIT_MAP_COUNT: ::c_ushort = 5;
+pub const FSOPT_NOFOLLOW: u32 = 0x1;
+pub const FSOPT_NOFOLLOW_ANY: u32 = 0x800;
+pub const FSOPT_REPORT_FULLSIZE: u32 = 0x4;
+pub const FSOPT_PACK_INVAL_ATTRS: u32 = 0x8;
+pub const FSOPT_ATTR_CMN_EXTENDED: u32 = 0x20;
+pub const FSOPT_RETURN_REALDEV: u32 = 0x200;
+pub const ATTR_CMN_NAME: attrgroup_t = 0x00000001;
+pub const ATTR_CMN_DEVID: attrgroup_t = 0x00000002;
+pub const ATTR_CMN_FSID: attrgroup_t = 0x00000004;
+pub const ATTR_CMN_OBJTYPE: attrgroup_t = 0x00000008;
+pub const ATTR_CMN_OBJTAG: attrgroup_t = 0x00000010;
+pub const ATTR_CMN_OBJID: attrgroup_t = 0x00000020;
+pub const ATTR_CMN_OBJPERMANENTID: attrgroup_t = 0x00000040;
+pub const ATTR_CMN_PAROBJID: attrgroup_t = 0x00000080;
+pub const ATTR_CMN_SCRIPT: attrgroup_t = 0x00000100;
+pub const ATTR_CMN_CRTIME: attrgroup_t = 0x00000200;
+pub const ATTR_CMN_MODTIME: attrgroup_t = 0x00000400;
+pub const ATTR_CMN_CHGTIME: attrgroup_t = 0x00000800;
+pub const ATTR_CMN_ACCTIME: attrgroup_t = 0x00001000;
+pub const ATTR_CMN_BKUPTIME: attrgroup_t = 0x00002000;
+pub const ATTR_CMN_FNDRINFO: attrgroup_t = 0x00004000;
+pub const ATTR_CMN_OWNERID: attrgroup_t = 0x00008000;
+pub const ATTR_CMN_GRPID: attrgroup_t = 0x00010000;
+pub const ATTR_CMN_ACCESSMASK: attrgroup_t = 0x00020000;
+pub const ATTR_CMN_FLAGS: attrgroup_t = 0x00040000;
+pub const ATTR_CMN_GEN_COUNT: attrgroup_t = 0x00080000;
+pub const ATTR_CMN_DOCUMENT_ID: attrgroup_t = 0x00100000;
+pub const ATTR_CMN_USERACCESS: attrgroup_t = 0x00200000;
+pub const ATTR_CMN_EXTENDED_SECURITY: attrgroup_t = 0x00400000;
+pub const ATTR_CMN_UUID: attrgroup_t = 0x00800000;
+pub const ATTR_CMN_GRPUUID: attrgroup_t = 0x01000000;
+pub const ATTR_CMN_FILEID: attrgroup_t = 0x02000000;
+pub const ATTR_CMN_PARENTID: attrgroup_t = 0x04000000;
+pub const ATTR_CMN_FULLPATH: attrgroup_t = 0x08000000;
+pub const ATTR_CMN_ADDEDTIME: attrgroup_t = 0x10000000;
+pub const ATTR_CMN_DATA_PROTECT_FLAGS: attrgroup_t = 0x40000000;
+pub const ATTR_CMN_RETURNED_ATTRS: attrgroup_t = 0x80000000;
+pub const ATTR_VOL_FSTYPE: attrgroup_t = 0x00000001;
+pub const ATTR_VOL_SIGNATURE: attrgroup_t = 0x00000002;
+pub const ATTR_VOL_SIZE: attrgroup_t = 0x00000004;
+pub const ATTR_VOL_SPACEFREE: attrgroup_t = 0x00000008;
+pub const ATTR_VOL_SPACEAVAIL: attrgroup_t = 0x00000010;
+pub const ATTR_VOL_MINALLOCATION: attrgroup_t = 0x00000020;
+pub const ATTR_VOL_ALLOCATIONCLUMP: attrgroup_t = 0x00000040;
+pub const ATTR_VOL_IOBLOCKSIZE: attrgroup_t = 0x00000080;
+pub const ATTR_VOL_OBJCOUNT: attrgroup_t = 0x00000100;
+pub const ATTR_VOL_FILECOUNT: attrgroup_t = 0x00000200;
+pub const ATTR_VOL_DIRCOUNT: attrgroup_t = 0x00000400;
+pub const ATTR_VOL_MAXOBJCOUNT: attrgroup_t = 0x00000800;
+pub const ATTR_VOL_MOUNTPOINT: attrgroup_t = 0x00001000;
+pub const ATTR_VOL_NAME: attrgroup_t = 0x00002000;
+pub const ATTR_VOL_MOUNTFLAGS: attrgroup_t = 0x00004000;
+pub const ATTR_VOL_MOUNTEDDEVICE: attrgroup_t = 0x00008000;
+pub const ATTR_VOL_ENCODINGSUSED: attrgroup_t = 0x00010000;
+pub const ATTR_VOL_CAPABILITIES: attrgroup_t = 0x00020000;
+pub const ATTR_VOL_UUID: attrgroup_t = 0x00040000;
+pub const ATTR_VOL_SPACEUSED: attrgroup_t = 0x00800000;
+pub const ATTR_VOL_QUOTA_SIZE: attrgroup_t = 0x10000000;
+pub const ATTR_VOL_RESERVED_SIZE: attrgroup_t = 0x20000000;
+pub const ATTR_VOL_ATTRIBUTES: attrgroup_t = 0x40000000;
+pub const ATTR_VOL_INFO: attrgroup_t = 0x80000000;
+pub const ATTR_DIR_LINKCOUNT: attrgroup_t = 0x00000001;
+pub const ATTR_DIR_ENTRYCOUNT: attrgroup_t = 0x00000002;
+pub const ATTR_DIR_MOUNTSTATUS: attrgroup_t = 0x00000004;
+pub const ATTR_DIR_ALLOCSIZE: attrgroup_t = 0x00000008;
+pub const ATTR_DIR_IOBLOCKSIZE: attrgroup_t = 0x00000010;
+pub const ATTR_DIR_DATALENGTH: attrgroup_t = 0x00000020;
+pub const ATTR_FILE_LINKCOUNT: attrgroup_t = 0x00000001;
+pub const ATTR_FILE_TOTALSIZE: attrgroup_t = 0x00000002;
+pub const ATTR_FILE_ALLOCSIZE: attrgroup_t = 0x00000004;
+pub const ATTR_FILE_IOBLOCKSIZE: attrgroup_t = 0x00000008;
+pub const ATTR_FILE_DEVTYPE: attrgroup_t = 0x00000020;
+pub const ATTR_FILE_FORKCOUNT: attrgroup_t = 0x00000080;
+pub const ATTR_FILE_FORKLIST: attrgroup_t = 0x00000100;
+pub const ATTR_FILE_DATALENGTH: attrgroup_t = 0x00000200;
+pub const ATTR_FILE_DATAALLOCSIZE: attrgroup_t = 0x00000400;
+pub const ATTR_FILE_RSRCLENGTH: attrgroup_t = 0x00001000;
+pub const ATTR_FILE_RSRCALLOCSIZE: attrgroup_t = 0x00002000;
+pub const ATTR_CMNEXT_RELPATH: attrgroup_t = 0x00000004;
+pub const ATTR_CMNEXT_PRIVATESIZE: attrgroup_t = 0x00000008;
+pub const ATTR_CMNEXT_LINKID: attrgroup_t = 0x00000010;
+pub const ATTR_CMNEXT_NOFIRMLINKPATH: attrgroup_t = 0x00000020;
+pub const ATTR_CMNEXT_REALDEVID: attrgroup_t = 0x00000040;
+pub const ATTR_CMNEXT_REALFSID: attrgroup_t = 0x00000080;
+pub const ATTR_CMNEXT_CLONEID: attrgroup_t = 0x00000100;
+pub const ATTR_CMNEXT_EXT_FLAGS: attrgroup_t = 0x00000200;
+pub const ATTR_CMNEXT_RECURSIVE_GENCOUNT: attrgroup_t = 0x00000400;
+pub const DIR_MNTSTATUS_MNTPOINT: u32 = 0x1;
+pub const VOL_CAPABILITIES_FORMAT: usize = 0;
+pub const VOL_CAPABILITIES_INTERFACES: usize = 1;
+pub const VOL_CAP_FMT_PERSISTENTOBJECTIDS: attrgroup_t = 0x00000001;
+pub const VOL_CAP_FMT_SYMBOLICLINKS: attrgroup_t = 0x00000002;
+pub const VOL_CAP_FMT_HARDLINKS: attrgroup_t = 0x00000004;
+pub const VOL_CAP_FMT_JOURNAL: attrgroup_t = 0x00000008;
+pub const VOL_CAP_FMT_JOURNAL_ACTIVE: attrgroup_t = 0x00000010;
+pub const VOL_CAP_FMT_NO_ROOT_TIMES: attrgroup_t = 0x00000020;
+pub const VOL_CAP_FMT_SPARSE_FILES: attrgroup_t = 0x00000040;
+pub const VOL_CAP_FMT_ZERO_RUNS: attrgroup_t = 0x00000080;
+pub const VOL_CAP_FMT_CASE_SENSITIVE: attrgroup_t = 0x00000100;
+pub const VOL_CAP_FMT_CASE_PRESERVING: attrgroup_t = 0x00000200;
+pub const VOL_CAP_FMT_FAST_STATFS: attrgroup_t = 0x00000400;
+pub const VOL_CAP_FMT_2TB_FILESIZE: attrgroup_t = 0x00000800;
+pub const VOL_CAP_FMT_OPENDENYMODES: attrgroup_t = 0x00001000;
+pub const VOL_CAP_FMT_HIDDEN_FILES: attrgroup_t = 0x00002000;
+pub const VOL_CAP_FMT_PATH_FROM_ID: attrgroup_t = 0x00004000;
+pub const VOL_CAP_FMT_NO_VOLUME_SIZES: attrgroup_t = 0x00008000;
+pub const VOL_CAP_FMT_DECMPFS_COMPRESSION: attrgroup_t = 0x00010000;
+pub const VOL_CAP_FMT_64BIT_OBJECT_IDS: attrgroup_t = 0x00020000;
+pub const VOL_CAP_FMT_DIR_HARDLINKS: attrgroup_t = 0x00040000;
+pub const VOL_CAP_FMT_DOCUMENT_ID: attrgroup_t = 0x00080000;
+pub const VOL_CAP_FMT_WRITE_GENERATION_COUNT: attrgroup_t = 0x00100000;
+pub const VOL_CAP_FMT_NO_IMMUTABLE_FILES: attrgroup_t = 0x00200000;
+pub const VOL_CAP_FMT_NO_PERMISSIONS: attrgroup_t = 0x00400000;
+pub const VOL_CAP_FMT_SHARED_SPACE: attrgroup_t = 0x00800000;
+pub const VOL_CAP_FMT_VOL_GROUPS: attrgroup_t = 0x01000000;
+pub const VOL_CAP_FMT_SEALED: attrgroup_t = 0x02000000;
+pub const VOL_CAP_INT_SEARCHFS: attrgroup_t = 0x00000001;
+pub const VOL_CAP_INT_ATTRLIST: attrgroup_t = 0x00000002;
+pub const VOL_CAP_INT_NFSEXPORT: attrgroup_t = 0x00000004;
+pub const VOL_CAP_INT_READDIRATTR: attrgroup_t = 0x00000008;
+pub const VOL_CAP_INT_EXCHANGEDATA: attrgroup_t = 0x00000010;
+pub const VOL_CAP_INT_COPYFILE: attrgroup_t = 0x00000020;
+pub const VOL_CAP_INT_ALLOCATE: attrgroup_t = 0x00000040;
+pub const VOL_CAP_INT_VOL_RENAME: attrgroup_t = 0x00000080;
+pub const VOL_CAP_INT_ADVLOCK: attrgroup_t = 0x00000100;
+pub const VOL_CAP_INT_FLOCK: attrgroup_t = 0x00000200;
+pub const VOL_CAP_INT_EXTENDED_SECURITY: attrgroup_t = 0x00000400;
+pub const VOL_CAP_INT_USERACCESS: attrgroup_t = 0x00000800;
+pub const VOL_CAP_INT_MANLOCK: attrgroup_t = 0x00001000;
+pub const VOL_CAP_INT_NAMEDSTREAMS: attrgroup_t = 0x00002000;
+pub const VOL_CAP_INT_EXTENDED_ATTR: attrgroup_t = 0x00004000;
+pub const VOL_CAP_INT_CLONE: attrgroup_t = 0x00010000;
+pub const VOL_CAP_INT_SNAPSHOT: attrgroup_t = 0x00020000;
+pub const VOL_CAP_INT_RENAME_SWAP: attrgroup_t = 0x00040000;
+pub const VOL_CAP_INT_RENAME_EXCL: attrgroup_t = 0x00080000;
+pub const VOL_CAP_INT_RENAME_OPENFAIL: attrgroup_t = 0x00100000;
+
cfg_if! {
if #[cfg(libc_const_extern_fn)] {
const fn __DARWIN_ALIGN32(p: usize) -> usize {
@@ -4791,6 +5023,18 @@ f! {
pub {const} fn VM_MAKE_TAG(id: u8) -> u32 {
(id as u32) << 24u32
}
+
+ pub fn major(dev: dev_t) -> i32 {
+ (dev >> 24) & 0xff
+ }
+
+ pub fn minor(dev: dev_t) -> i32 {
+ dev & 0xffffff
+ }
+
+ pub fn makedev(major: i32, minor: i32) -> dev_t {
+ (major << 24) | minor
+ }
}
safe_f! {
@@ -4846,6 +5090,11 @@ extern "C" {
pub fn fchflags(fd: ::c_int, flags: ::c_uint) -> ::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;
+ #[cfg_attr(
+ all(target_os = "macos", target_arch = "x86"),
+ link_name = "confstr$UNIX2003"
+ )]
+ pub fn confstr(name: ::c_int, buf: *mut ::c_char, len: ::size_t) -> ::size_t;
pub fn lio_listio(
mode: ::c_int,
aiocb_list: *const *mut aiocb,
@@ -5006,8 +5255,34 @@ extern "C" {
) -> *mut ::c_void;
pub fn pthread_jit_write_protect_np(enabled: ::c_int);
pub fn pthread_jit_write_protect_supported_np() -> ::c_int;
+ // An array of pthread_jit_write_with_callback_np must declare
+ // the list of callbacks e.g.
+ // #[link_section = "__DATA_CONST,__pth_jit_func"]
+ // static callbacks: [libc::pthread_jit_write_callback_t; 2] = [native_jit_write_cb,
+ // std::mem::transmute::<libc::pthread_jit_write_callback_t>(std::ptr::null())];
+ // (a handy PTHREAD_JIT_WRITE_CALLBACK_NP macro for other languages).
+ pub fn pthread_jit_write_with_callback_np(
+ callback: ::pthread_jit_write_callback_t,
+ ctx: *mut ::c_void,
+ ) -> ::c_int;
+ pub fn pthread_jit_write_freeze_callbacks_np();
pub fn pthread_cpu_number_np(cpu_number_out: *mut ::size_t) -> ::c_int;
+ pub fn os_unfair_lock_lock(lock: os_unfair_lock_t);
+ pub fn os_unfair_lock_trylock(lock: os_unfair_lock_t) -> bool;
+ pub fn os_unfair_lock_unlock(lock: os_unfair_lock_t);
+ pub fn os_unfair_lock_assert_owner(lock: os_unfair_lock_t);
+ pub fn os_unfair_lock_assert_not_owner(lock: os_unfair_lock_t);
+
+ pub fn os_log_create(subsystem: *const ::c_char, category: *const ::c_char) -> ::os_log_t;
+ pub fn os_log_type_enabled(oslog: ::os_log_t, tpe: ::os_log_type_t) -> bool;
+ pub fn os_signpost_id_make_with_pointer(
+ log: ::os_log_t,
+ ptr: *const ::c_void,
+ ) -> ::os_signpost_id_t;
+ pub fn os_signpost_id_generate(log: ::os_log_t) -> ::os_signpost_id_t;
+ pub fn os_signpost_enabled(log: ::os_log_t) -> bool;
+
pub fn thread_policy_set(
thread: thread_t,
flavor: thread_policy_flavor_t,
@@ -5536,6 +5811,61 @@ extern "C" {
) -> ::sysdir_search_path_enumeration_state;
pub static vm_page_size: vm_size_t;
+
+ pub fn getattrlist(
+ path: *const ::c_char,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u32,
+ ) -> ::c_int;
+ pub fn fgetattrlist(
+ fd: ::c_int,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u32,
+ ) -> ::c_int;
+ pub fn getattrlistat(
+ fd: ::c_int,
+ path: *const ::c_char,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: ::c_ulong,
+ ) -> ::c_int;
+ pub fn setattrlist(
+ path: *const ::c_char,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u32,
+ ) -> ::c_int;
+ pub fn fsetattrlist(
+ fd: ::c_int,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u32,
+ ) -> ::c_int;
+ pub fn setattrlistat(
+ dir_fd: ::c_int,
+ path: *const ::c_char,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u32,
+ ) -> ::c_int;
+ pub fn getattrlistbulk(
+ dirfd: ::c_int,
+ attrList: *mut ::c_void,
+ attrBuf: *mut ::c_void,
+ attrBufSize: ::size_t,
+ options: u64,
+ ) -> ::c_int;
+
+ pub fn malloc_size(ptr: *const ::c_void) -> ::size_t;
+ pub fn malloc_good_size(size: ::size_t) -> ::size_t;
}
pub unsafe fn mach_task_self() -> ::mach_port_t {
@@ -5567,7 +5897,10 @@ cfg_if! {
}
}
-#[link(name = "iconv")]
+// These require a dependency on `libiconv`, and including this when built as
+// part of `std` means every Rust program gets it. Ideally we would have a link
+// modifier to only include these if they are used, but we do not.
+#[cfg_attr(not(feature = "rustc-dep-of-std"), link(name = "iconv"))]
extern "C" {
pub fn iconv_open(tocode: *const ::c_char, fromcode: *const ::c_char) -> iconv_t;
pub fn iconv(
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
index df7719b4b..418ac3dc8 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/dragonfly/mod.rs
@@ -1066,6 +1066,8 @@ pub const CPUCTL_MSRSBIT: ::c_int = 0xc0106305;
pub const CPUCTL_MSRCBIT: ::c_int = 0xc0106306;
pub const CPUCTL_CPUID_COUNT: ::c_int = 0xc0106307;
+pub const CPU_SETSIZE: ::size_t = ::mem::size_of::<::cpumask_t>() * 8;
+
pub const EVFILT_READ: i16 = -1;
pub const EVFILT_WRITE: i16 = -2;
pub const EVFILT_AIO: i16 = -3;
@@ -1571,6 +1573,15 @@ safe_f! {
pub {const} fn WIFSIGNALED(status: ::c_int) -> bool {
(status & 0o177) != 0o177 && (status & 0o177) != 0
}
+
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= major << 8;
+ dev |= minor;
+ dev
+ }
}
extern "C" {
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
index 1af555fa3..aaa043584 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs
@@ -434,6 +434,14 @@ pub const MINCORE_SUPER: ::c_int = 0x20;
/// max length of devicename
pub const SPECNAMELEN: ::c_int = 63;
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ (major << 8) | minor
+ }
+}
+
extern "C" {
// Return type ::c_int was removed in FreeBSD 12
pub fn setgrent() -> ::c_int;
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
index 848db3399..e7f8ad780 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs
@@ -449,6 +449,19 @@ pub const KI_NSPARE_PTR: usize = 6;
pub const MINCORE_SUPER: ::c_int = 0x20;
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= ((major & 0xffffff00) as dev_t) << 32;
+ dev |= ((major & 0x000000ff) as dev_t) << 8;
+ dev |= ((minor & 0x0000ff00) as dev_t) << 24;
+ dev |= ((minor & 0xffff00ff) as dev_t) << 0;
+ dev
+ }
+}
+
extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
index a929f9d29..bcd09006b 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs
@@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;
pub const MINCORE_SUPER: ::c_int = 0x20;
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= ((major & 0xffffff00) as dev_t) << 32;
+ dev |= ((major & 0x000000ff) as dev_t) << 8;
+ dev |= ((minor & 0x0000ff00) as dev_t) << 24;
+ dev |= ((minor & 0xffff00ff) as dev_t) << 0;
+ dev
+ }
+}
+
extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
index c655d555d..9da669604 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs
@@ -468,6 +468,19 @@ pub const DOMAINSET_POLICY_INTERLEAVE: ::c_int = 4;
pub const MINCORE_SUPER: ::c_int = 0x60;
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= ((major & 0xffffff00) as dev_t) << 32;
+ dev |= ((major & 0x000000ff) as dev_t) << 8;
+ dev |= ((minor & 0x0000ff00) as dev_t) << 24;
+ dev |= ((minor & 0xffff00ff) as dev_t) << 0;
+ dev
+ }
+}
+
extern "C" {
pub fn setgrent();
pub fn mprotect(addr: *mut ::c_void, len: ::size_t, prot: ::c_int) -> ::c_int;
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
index 84e43b23e..08fd5a52d 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs
@@ -44,6 +44,8 @@ pub type fhandle_t = fhandle;
pub type au_id_t = ::uid_t;
pub type au_asid_t = ::pid_t;
+pub type cpusetid_t = ::c_int;
+
#[cfg_attr(feature = "extra_traits", derive(Debug, Hash, PartialEq, Eq))]
#[repr(u32)]
pub enum devstat_support_flags {
@@ -990,6 +992,12 @@ s! {
pub _flags: u32,
pub _clockid: u32,
}
+
+ pub struct shm_largepage_conf {
+ pub psind: ::c_int,
+ pub alloc_policy: ::c_int,
+ __pad: [::c_int; 10],
+ }
}
s_no_extra_traits! {
@@ -1890,6 +1898,9 @@ pub const LIO_READV: ::c_int = 6;
pub const DEVSTAT_N_TRANS_FLAGS: ::c_int = 4;
pub const DEVSTAT_NAME_LEN: ::c_int = 16;
+// sys/cpuset.h
+pub const CPU_SETSIZE: ::c_int = 256;
+
pub const SIGEV_THREAD_ID: ::c_int = 4;
pub const EXTATTR_NAMESPACE_EMPTY: ::c_int = 0;
@@ -2249,6 +2260,7 @@ pub const FIONWRITE: ::c_ulong = 0x40046677;
pub const FIONSPACE: ::c_ulong = 0x40046676;
pub const FIOSEEKDATA: ::c_ulong = 0xc0086661;
pub const FIOSEEKHOLE: ::c_ulong = 0xc0086662;
+pub const FIOSSHMLPGCNF: ::c_ulong = 0x80306664;
pub const JAIL_API_VERSION: u32 = 2;
pub const JAIL_CREATE: ::c_int = 0x01;
@@ -2508,6 +2520,8 @@ pub const IFCAP_TOE4: ::c_int = 0x04000;
pub const IFCAP_TOE6: ::c_int = 0x08000;
/// interface hw can filter vlan tag
pub const IFCAP_VLAN_HWFILTER: ::c_int = 0x10000;
+/// can do SIOCGIFCAPNV/SIOCSIFCAPNV
+pub const IFCAP_NV: ::c_int = 0x20000;
/// can do IFCAP_TSO on VLANs
pub const IFCAP_VLAN_HWTSO: ::c_int = 0x40000;
/// the runtime link state is dynamic
@@ -2543,7 +2557,7 @@ pub const IFCAP_TSO: ::c_int = IFCAP_TSO4 | IFCAP_TSO6;
pub const IFCAP_WOL: ::c_int = IFCAP_WOL_UCAST | IFCAP_WOL_MCAST | IFCAP_WOL_MAGIC;
pub const IFCAP_TOE: ::c_int = IFCAP_TOE4 | IFCAP_TOE6;
pub const IFCAP_TXTLS: ::c_int = IFCAP_TXTLS4 | IFCAP_TXTLS6;
-pub const IFCAP_CANTCHANGE: ::c_int = IFCAP_NETMAP;
+pub const IFCAP_CANTCHANGE: ::c_int = IFCAP_NETMAP | IFCAP_NV;
pub const IFQ_MAXLEN: ::c_int = 50;
pub const IFNET_SLOWHZ: ::c_int = 1;
@@ -3227,30 +3241,67 @@ pub const KKST_STATE_RUNNING: ::c_int = 2;
pub const PRI_MIN: ::c_int = 0;
pub const PRI_MAX: ::c_int = 255;
pub const PRI_MIN_ITHD: ::c_int = PRI_MIN;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PRI_MAX_ITHD: ::c_int = PRI_MIN_REALTIME - 1;
pub const PI_REALTIME: ::c_int = PRI_MIN_ITHD + 0;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_AV: ::c_int = PRI_MIN_ITHD + 4;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_NET: ::c_int = PRI_MIN_ITHD + 8;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_DISK: ::c_int = PRI_MIN_ITHD + 12;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_TTY: ::c_int = PRI_MIN_ITHD + 16;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_DULL: ::c_int = PRI_MIN_ITHD + 20;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PI_SOFT: ::c_int = PRI_MIN_ITHD + 24;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PRI_MIN_REALTIME: ::c_int = 48;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PRI_MAX_REALTIME: ::c_int = PRI_MIN_KERN - 1;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PRI_MIN_KERN: ::c_int = 80;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PRI_MAX_KERN: ::c_int = PRI_MIN_TIMESHARE - 1;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PSWP: ::c_int = PRI_MIN_KERN + 0;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PVM: ::c_int = PRI_MIN_KERN + 4;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PINOD: ::c_int = PRI_MIN_KERN + 8;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PRIBIO: ::c_int = PRI_MIN_KERN + 12;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PVFS: ::c_int = PRI_MIN_KERN + 16;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PZERO: ::c_int = PRI_MIN_KERN + 20;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PSOCK: ::c_int = PRI_MIN_KERN + 24;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PWAIT: ::c_int = PRI_MIN_KERN + 28;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PLOCK: ::c_int = PRI_MIN_KERN + 32;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PPAUSE: ::c_int = PRI_MIN_KERN + 36;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const PRI_MIN_TIMESHARE: ::c_int = 120;
pub const PRI_MAX_TIMESHARE: ::c_int = PRI_MIN_IDLE - 1;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
+#[allow(deprecated)]
pub const PUSER: ::c_int = PRI_MIN_TIMESHARE;
pub const PRI_MIN_IDLE: ::c_int = 224;
pub const PRI_MAX_IDLE: ::c_int = PRI_MAX;
@@ -3348,24 +3399,32 @@ pub const TDF_CANSWAP: ::c_int = 0x00000040;
pub const TDF_KTH_SUSP: ::c_int = 0x00000100;
pub const TDF_ALLPROCSUSP: ::c_int = 0x00000200;
pub const TDF_BOUNDARY: ::c_int = 0x00000400;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_ASTPENDING: ::c_int = 0x00000800;
pub const TDF_SBDRY: ::c_int = 0x00002000;
pub const TDF_UPIBLOCKED: ::c_int = 0x00004000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_NEEDSUSPCHK: ::c_int = 0x00008000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_NEEDRESCHED: ::c_int = 0x00010000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_NEEDSIGCHK: ::c_int = 0x00020000;
pub const TDF_NOLOAD: ::c_int = 0x00040000;
pub const TDF_SERESTART: ::c_int = 0x00080000;
pub const TDF_THRWAKEUP: ::c_int = 0x00100000;
pub const TDF_SEINTR: ::c_int = 0x00200000;
pub const TDF_SWAPINREQ: ::c_int = 0x00400000;
+#[deprecated(since = "0.2.133", note = "Removed in FreeBSD 14")]
pub const TDF_UNUSED23: ::c_int = 0x00800000;
pub const TDF_SCHED0: ::c_int = 0x01000000;
pub const TDF_SCHED1: ::c_int = 0x02000000;
pub const TDF_SCHED2: ::c_int = 0x04000000;
pub const TDF_SCHED3: ::c_int = 0x08000000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_ALRMPEND: ::c_int = 0x10000000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_PROFPEND: ::c_int = 0x20000000;
+#[deprecated(since = "0.2.133", note = "Not stable across OS versions")]
pub const TDF_MACPEND: ::c_int = 0x40000000;
pub const TDB_SUSPEND: ::c_int = 0x00000001;
@@ -3704,6 +3763,16 @@ pub const UMTX_OP_ROBUST_LISTS: ::c_int = 26;
pub const UMTX_ABSTIME: u32 = 1;
+pub const CPU_LEVEL_ROOT: ::c_int = 1;
+pub const CPU_LEVEL_CPUSET: ::c_int = 2;
+pub const CPU_LEVEL_WHICH: ::c_int = 3;
+
+pub const CPU_WHICH_TID: ::c_int = 1;
+pub const CPU_WHICH_PID: ::c_int = 2;
+pub const CPU_WHICH_CPUSET: ::c_int = 3;
+pub const CPU_WHICH_IRQ: ::c_int = 4;
+pub const CPU_WHICH_JAIL: ::c_int = 5;
+
const_fn! {
{const} fn _ALIGN(p: usize) -> usize {
(p + _ALIGNBYTES) & !_ALIGNBYTES
@@ -3985,6 +4054,7 @@ extern "C" {
infop: *mut ::siginfo_t,
options: ::c_int,
) -> ::c_int;
+ pub fn ptsname_r(fd: ::c_int, buf: *mut ::c_char, buflen: ::size_t) -> ::c_int;
pub fn ftok(pathname: *const ::c_char, proj_id: ::c_int) -> ::key_t;
pub fn shmget(key: ::key_t, size: ::size_t, shmflg: ::c_int) -> ::c_int;
@@ -4193,6 +4263,14 @@ extern "C" {
setsize: ::size_t,
mask: *const cpuset_t,
) -> ::c_int;
+ pub fn cpuset(setid: *mut ::cpusetid_t) -> ::c_int;
+ pub fn cpuset_getid(
+ level: cpulevel_t,
+ which: cpuwhich_t,
+ id: ::id_t,
+ setid: *mut ::cpusetid_t,
+ ) -> ::c_int;
+ pub fn cpuset_setid(which: cpuwhich_t, id: ::id_t, setid: ::cpusetid_t) -> ::c_int;
pub fn cap_enter() -> ::c_int;
pub fn cap_getmode(modep: *mut ::c_uint) -> ::c_int;
pub fn __cap_rights_init(version: ::c_int, rights: *mut cap_rights_t, ...)
diff --git a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs
index b314b6856..db21597d9 100644
--- a/vendor/libc/src/unix/bsd/freebsdlike/mod.rs
+++ b/vendor/libc/src/unix/bsd/freebsdlike/mod.rs
@@ -376,6 +376,10 @@ s! {
pub seq: ::c_ushort,
pub key: ::key_t,
}
+
+ pub struct eui64 {
+ pub octet: [u8; EUI64_LEN],
+ }
}
s_no_extra_traits! {
@@ -1329,6 +1333,8 @@ pub const ONLRET: ::tcflag_t = 0x40;
pub const CMGROUP_MAX: usize = 16;
+pub const EUI64_LEN: usize = 8;
+
// https://github.com/freebsd/freebsd/blob/master/sys/net/bpf.h
pub const BPF_ALIGNMENT: usize = SIZEOF_LONG;
@@ -1720,6 +1726,13 @@ extern "C" {
pub fn memset_s(s: *mut ::c_void, smax: ::size_t, c: ::c_int, n: ::size_t) -> ::c_int;
pub fn gethostid() -> ::c_long;
pub fn sethostid(hostid: ::c_long);
+
+ pub fn eui64_aton(a: *const ::c_char, e: *mut eui64) -> ::c_int;
+ pub fn eui64_ntoa(id: *const eui64, a: *mut ::c_char, len: ::size_t) -> ::c_int;
+ pub fn eui64_ntohost(hostname: *mut ::c_char, len: ::size_t, id: *const eui64) -> ::c_int;
+ pub fn eui64_hostton(hostname: *const ::c_char, id: *mut eui64) -> ::c_int;
+
+ pub fn eaccess(path: *const ::c_char, mode: ::c_int) -> ::c_int;
}
#[link(name = "rt")]
diff --git a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
index d12fd0730..bfe2de083 100644
--- a/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
+++ b/vendor/libc/src/unix/bsd/netbsdlike/netbsd/mod.rs
@@ -2271,6 +2271,33 @@ pub const LSZOMB: ::c_int = 5;
pub const LSONPROC: ::c_int = 7;
pub const LSSUSPENDED: ::c_int = 8;
+pub const _REG_RDI: ::c_int = 0;
+pub const _REG_RSI: ::c_int = 1;
+pub const _REG_RDX: ::c_int = 2;
+pub const _REG_RCX: ::c_int = 3;
+pub const _REG_R8: ::c_int = 4;
+pub const _REG_R9: ::c_int = 5;
+pub const _REG_R10: ::c_int = 6;
+pub const _REG_R11: ::c_int = 7;
+pub const _REG_R12: ::c_int = 8;
+pub const _REG_R13: ::c_int = 9;
+pub const _REG_R14: ::c_int = 10;
+pub const _REG_R15: ::c_int = 11;
+pub const _REG_RBP: ::c_int = 12;
+pub const _REG_RBX: ::c_int = 13;
+pub const _REG_RAX: ::c_int = 14;
+pub const _REG_GS: ::c_int = 15;
+pub const _REG_FS: ::c_int = 16;
+pub const _REG_ES: ::c_int = 17;
+pub const _REG_DS: ::c_int = 18;
+pub const _REG_TRAPNO: ::c_int = 19;
+pub const _REG_ERR: ::c_int = 20;
+pub const _REG_RIP: ::c_int = 21;
+pub const _REG_CS: ::c_int = 22;
+pub const _REG_RFLAGS: ::c_int = 23;
+pub const _REG_RSP: ::c_int = 24;
+pub const _REG_SS: ::c_int = 25;
+
const_fn! {
{const} fn _ALIGN(p: usize) -> usize {
(p + _ALIGNBYTES) & !_ALIGNBYTES
@@ -2351,6 +2378,16 @@ safe_f! {
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
status == 0xffff
}
+
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= (major << 8) & 0x000ff00;
+ dev |= (minor << 12) & 0xfff00000;
+ dev |= minor & 0xff;
+ dev
+ }
}
extern "C" {
diff --git a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs
index 1910f24a4..506306e9f 100644
--- a/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs
+++ b/vendor/libc/src/unix/bsd/netbsdlike/openbsd/mod.rs
@@ -1639,6 +1639,10 @@ pub const SF_ARCHIVED: ::c_uint = 0x00010000;
pub const SF_IMMUTABLE: ::c_uint = 0x00020000;
pub const SF_APPEND: ::c_uint = 0x00040000;
+pub const MNT_WAIT: ::c_int = 1;
+pub const MNT_NOWAIT: ::c_int = 2;
+pub const MNT_LAZY: ::c_int = 3;
+
const_fn! {
{const} fn _ALIGN(p: usize) -> usize {
(p + _ALIGNBYTES) & !_ALIGNBYTES
@@ -1695,6 +1699,16 @@ safe_f! {
pub {const} fn WIFCONTINUED(status: ::c_int) -> bool {
(status & 0o177777) == 0o177777
}
+
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= (major & 0xff) << 8;
+ dev |= minor & 0xff;
+ dev |= (minor & 0xffff00) << 8;
+ dev
+ }
}
extern "C" {
@@ -1870,6 +1884,8 @@ cfg_if! {
// these functions use statfs which uses the union mount_info:
pub fn statfs(path: *const ::c_char, buf: *mut statfs) -> ::c_int;
pub fn fstatfs(fd: ::c_int, buf: *mut statfs) -> ::c_int;
+ pub fn getmntinfo(mntbufp: *mut *mut ::statfs, flags: ::c_int) -> ::c_int;
+ pub fn getfsstat(buf: *mut statfs, bufsize: ::size_t, flags: ::c_int) -> ::c_int;
}
}
}
diff --git a/vendor/libc/src/unix/linux_like/android/mod.rs b/vendor/libc/src/unix/linux_like/android/mod.rs
index cfd229a47..67e5eb52b 100644
--- a/vendor/libc/src/unix/linux_like/android/mod.rs
+++ b/vendor/libc/src/unix/linux_like/android/mod.rs
@@ -2709,6 +2709,17 @@ pub const RTMSG_DELDEVICE: u32 = 0x12;
pub const RTMSG_NEWROUTE: u32 = 0x21;
pub const RTMSG_DELROUTE: u32 = 0x22;
+// Most `*_SUPER_MAGIC` constants are defined at the `linux_like` level; the
+// following are only available on newer Linux versions than the versions
+// currently used in CI in some configurations, so we define them here.
+cfg_if! {
+ if #[cfg(not(target_arch = "s390x"))] {
+ pub const XFS_SUPER_MAGIC: ::c_long = 0x58465342;
+ } else if #[cfg(target_arch = "s390x")] {
+ pub const XFS_SUPER_MAGIC: ::c_uint = 0x58465342;
+ }
+}
+
f! {
pub fn CMSG_NXTHDR(mhdr: *const msghdr,
cmsg: *const cmsghdr) -> *mut cmsghdr {
@@ -2781,12 +2792,6 @@ f! {
pub fn minor(dev: ::dev_t) -> ::c_int {
((dev & 0xff) | ((dev >> 12) & 0xfff00)) as ::c_int
}
- pub fn makedev(ma: ::c_int, mi: ::c_int) -> ::dev_t {
- let ma = ma as ::dev_t;
- let mi = mi as ::dev_t;
- ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
- }
-
pub fn NLA_ALIGN(len: ::c_int) -> ::c_int {
return ((len) + NLA_ALIGNTO - 1) & !(NLA_ALIGNTO - 1)
}
@@ -2796,6 +2801,15 @@ f! {
}
}
+safe_f! {
+ pub {const} fn makedev(ma: ::c_uint, mi: ::c_uint) -> ::dev_t {
+ let ma = ma as ::dev_t;
+ let mi = mi as ::dev_t;
+ ((ma & 0xfff) << 8) | (mi & 0xff) | ((mi & 0xfff00) << 12)
+ }
+
+}
+
extern "C" {
pub fn getrlimit64(resource: ::c_int, rlim: *mut rlimit64) -> ::c_int;
pub fn setrlimit64(resource: ::c_int, rlim: *const rlimit64) -> ::c_int;
diff --git a/vendor/libc/src/unix/linux_like/emscripten/mod.rs b/vendor/libc/src/unix/linux_like/emscripten/mod.rs
index 31d0ebf25..11fbb31c3 100644
--- a/vendor/libc/src/unix/linux_like/emscripten/mod.rs
+++ b/vendor/libc/src/unix/linux_like/emscripten/mod.rs
@@ -1740,8 +1740,10 @@ f! {
minor |= (dev & 0xffffff00) >> 12;
minor as ::c_uint
}
+}
- pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
let major = major as ::dev_t;
let minor = minor as ::dev_t;
let mut dev = 0;
diff --git a/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs b/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs
index 320579955..5265cdd17 100644
--- a/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/arch/generic/mod.rs
@@ -104,6 +104,13 @@ cfg_if! {
pub const SO_DETACH_REUSEPORT_BPF: ::c_int = 68;
}
}
+
+cfg_if! {
+ if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
+ pub const FICLONE: ::c_ulong = 0x40049409;
+ pub const FICLONERANGE: ::c_ulong = 0x4020940D;
+ }
+}
// pub const SO_PREFER_BUSY_POLL: ::c_int = 69;
// pub const SO_BUSY_POLL_BUDGET: ::c_int = 70;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
index 2a064974d..e0ac0dfc3 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/arm/mod.rs
@@ -835,6 +835,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
cfg_if! {
if #[cfg(libc_align)] {
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
index eb3886fbc..6a03f0ba8 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/mips/mod.rs
@@ -536,6 +536,14 @@ pub const SYS_faccessat2: ::c_long = 4000 + 439;
pub const SYS_process_madvise: ::c_long = 4000 + 440;
pub const SYS_epoll_pwait2: ::c_long = 4000 + 441;
pub const SYS_mount_setattr: ::c_long = 4000 + 442;
+pub const SYS_quotactl_fd: ::c_long = 4000 + 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 4000 + 444;
+pub const SYS_landlock_add_rule: ::c_long = 4000 + 445;
+pub const SYS_landlock_restrict_self: ::c_long = 4000 + 446;
+pub const SYS_memfd_secret: ::c_long = 4000 + 447;
+pub const SYS_process_mrelease: ::c_long = 4000 + 448;
+pub const SYS_futex_waitv: ::c_long = 4000 + 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 4000 + 450;
pub const O_DIRECT: ::c_int = 0x8000;
pub const O_DIRECTORY: ::c_int = 0x10000;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs
index ad45c607f..e70b216bf 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/powerpc.rs
@@ -814,3 +814,11 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs
index def90d6d1..827f85e86 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs
@@ -758,6 +758,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
cfg_if! {
if #[cfg(libc_align)] {
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
index 5dd2302db..57ad9fe8e 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs
@@ -839,6 +839,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
cfg_if! {
if #[cfg(libc_align)] {
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
index e42e9ebd6..93622387e 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b32/x86/mod.rs
@@ -1040,6 +1040,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
// offsets in user_regs_structs, from sys/reg.h
pub const EBX: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs
index 60a1b6932..b620cc03f 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs
@@ -885,6 +885,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn sysctl(
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs
index cac215dc4..0bf5084d5 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs
@@ -587,6 +587,14 @@ pub const SYS_faccessat2: ::c_long = 5000 + 439;
pub const SYS_process_madvise: ::c_long = 5000 + 440;
pub const SYS_epoll_pwait2: ::c_long = 5000 + 441;
pub const SYS_mount_setattr: ::c_long = 5000 + 442;
+pub const SYS_quotactl_fd: ::c_long = 5000 + 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 5000 + 444;
+pub const SYS_landlock_add_rule: ::c_long = 5000 + 445;
+pub const SYS_landlock_restrict_self: ::c_long = 5000 + 446;
+pub const SYS_memfd_secret: ::c_long = 5000 + 447;
+pub const SYS_process_mrelease: ::c_long = 5000 + 448;
+pub const SYS_futex_waitv: ::c_long = 5000 + 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 5000 + 450;
pub const SFD_CLOEXEC: ::c_int = 0x080000;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs
index b5c268706..ce8ce97bb 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs
@@ -948,6 +948,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn sysctl(
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs
index f8073902a..9d022f96e 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs
@@ -797,6 +797,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
cfg_if! {
if #[cfg(libc_align)] {
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs
index 212dc898c..c4bae089c 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/s390x.rs
@@ -935,6 +935,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs
index 8d065e6a3..9fdacfac8 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs
@@ -900,6 +900,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn sysctl(
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs
index 7e876f2d8..d515d2231 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs
@@ -265,6 +265,14 @@ s! {
pub seccomp_notif_resp: ::__u16,
pub seccomp_data: ::__u16,
}
+
+ pub struct ptrace_rseq_configuration {
+ pub rseq_abi_pointer: ::__u64,
+ pub rseq_abi_size: ::__u32,
+ pub signature: ::__u32,
+ pub flags: ::__u32,
+ pub pad: ::__u32,
+ }
}
s_no_extra_traits! {
@@ -535,6 +543,7 @@ pub const O_ASYNC: ::c_int = 0x2000;
pub const O_NDELAY: ::c_int = 0x800;
pub const PTRACE_DETACH: ::c_uint = 17;
+pub const PTRACE_GET_RSEQ_CONFIGURATION: ::c_uint = 0x420f;
pub const EFD_NONBLOCK: ::c_int = 0x800;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs
index f840f9f44..35d2714ee 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs
@@ -429,6 +429,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn sysctl(
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs
index de1a8b94b..807b948ef 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs
@@ -357,6 +357,14 @@ pub const SYS_faccessat2: ::c_long = __X32_SYSCALL_BIT + 439;
pub const SYS_process_madvise: ::c_long = __X32_SYSCALL_BIT + 440;
pub const SYS_epoll_pwait2: ::c_long = __X32_SYSCALL_BIT + 441;
pub const SYS_mount_setattr: ::c_long = __X32_SYSCALL_BIT + 442;
+pub const SYS_quotactl_fd: ::c_long = __X32_SYSCALL_BIT + 443;
+pub const SYS_landlock_create_ruleset: ::c_long = __X32_SYSCALL_BIT + 444;
+pub const SYS_landlock_add_rule: ::c_long = __X32_SYSCALL_BIT + 445;
+pub const SYS_landlock_restrict_self: ::c_long = __X32_SYSCALL_BIT + 446;
+pub const SYS_memfd_secret: ::c_long = __X32_SYSCALL_BIT + 447;
+pub const SYS_process_mrelease: ::c_long = __X32_SYSCALL_BIT + 448;
+pub const SYS_futex_waitv: ::c_long = __X32_SYSCALL_BIT + 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = __X32_SYSCALL_BIT + 450;
pub const SYS_rt_sigaction: ::c_long = __X32_SYSCALL_BIT + 512;
pub const SYS_rt_sigreturn: ::c_long = __X32_SYSCALL_BIT + 513;
pub const SYS_ioctl: ::c_long = __X32_SYSCALL_BIT + 514;
diff --git a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs
index 88bc935f6..21e7619db 100644
--- a/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/gnu/mod.rs
@@ -954,6 +954,8 @@ pub const NT_LWPSTATUS: ::c_int = 16;
pub const NT_LWPSINFO: ::c_int = 17;
pub const NT_PRFPXREG: ::c_int = 20;
+pub const ELFOSABI_ARM_AEABI: u8 = 64;
+
// linux/keyctl.h
pub const KEYCTL_DH_COMPUTE: u32 = 23;
pub const KEYCTL_PKEY_QUERY: u32 = 24;
@@ -1024,6 +1026,9 @@ pub const STATX_ATTR_APPEND: ::c_int = 0x0020;
pub const STATX_ATTR_NODUMP: ::c_int = 0x0040;
pub const STATX_ATTR_ENCRYPTED: ::c_int = 0x0800;
pub const STATX_ATTR_AUTOMOUNT: ::c_int = 0x1000;
+pub const STATX_ATTR_MOUNT_ROOT: ::c_int = 0x2000;
+pub const STATX_ATTR_VERITY: ::c_int = 0x00100000;
+pub const STATX_ATTR_DAX: ::c_int = 0x00200000;
pub const SOMAXCONN: ::c_int = 4096;
@@ -1308,11 +1313,28 @@ extern "C" {
buflen: ::size_t,
result: *mut *mut ::group,
) -> ::c_int;
+ pub fn fgetpwent_r(
+ stream: *mut ::FILE,
+ pwd: *mut ::passwd,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut ::passwd,
+ ) -> ::c_int;
+ pub fn fgetgrent_r(
+ stream: *mut ::FILE,
+ grp: *mut ::group,
+ buf: *mut ::c_char,
+ buflen: ::size_t,
+ result: *mut *mut ::group,
+ ) -> ::c_int;
pub fn sethostid(hostid: ::c_long) -> ::c_int;
pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int;
pub fn mlock2(addr: *const ::c_void, len: ::size_t, flags: ::c_uint) -> ::c_int;
+
+ pub fn euidaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int;
+ pub fn eaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int;
}
extern "C" {
diff --git a/vendor/libc/src/unix/linux_like/linux/mod.rs b/vendor/libc/src/unix/linux_like/linux/mod.rs
index aba691e5a..43f6399e4 100644
--- a/vendor/libc/src/unix/linux_like/linux/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/mod.rs
@@ -596,6 +596,13 @@ s! {
pub nla_len: u16,
pub nla_type: u16,
}
+
+ pub struct file_clone_range {
+ pub src_fd: ::__s64,
+ pub src_offset: ::__u64,
+ pub src_length: ::__u64,
+ pub dest_offset: ::__u64,
+ }
}
s_no_extra_traits! {
@@ -1299,6 +1306,181 @@ pub const _SC_THREAD_ROBUST_PRIO_PROTECT: ::c_int = 248;
pub const RLIM_SAVED_MAX: ::rlim_t = RLIM_INFINITY;
pub const RLIM_SAVED_CUR: ::rlim_t = RLIM_INFINITY;
+// elf.h - Fields in the e_ident array.
+pub const EI_NIDENT: usize = 16;
+
+pub const EI_MAG0: usize = 0;
+pub const ELFMAG0: u8 = 0x7f;
+pub const EI_MAG1: usize = 1;
+pub const ELFMAG1: u8 = b'E';
+pub const EI_MAG2: usize = 2;
+pub const ELFMAG2: u8 = b'L';
+pub const EI_MAG3: usize = 3;
+pub const ELFMAG3: u8 = b'F';
+pub const SELFMAG: usize = 4;
+
+pub const EI_CLASS: usize = 4;
+pub const ELFCLASSNONE: u8 = 0;
+pub const ELFCLASS32: u8 = 1;
+pub const ELFCLASS64: u8 = 2;
+pub const ELFCLASSNUM: usize = 3;
+
+pub const EI_DATA: usize = 5;
+pub const ELFDATANONE: u8 = 0;
+pub const ELFDATA2LSB: u8 = 1;
+pub const ELFDATA2MSB: u8 = 2;
+pub const ELFDATANUM: usize = 3;
+
+pub const EI_VERSION: usize = 6;
+
+pub const EI_OSABI: usize = 7;
+pub const ELFOSABI_NONE: u8 = 0;
+pub const ELFOSABI_SYSV: u8 = 0;
+pub const ELFOSABI_HPUX: u8 = 1;
+pub const ELFOSABI_NETBSD: u8 = 2;
+pub const ELFOSABI_GNU: u8 = 3;
+pub const ELFOSABI_LINUX: u8 = ELFOSABI_GNU;
+pub const ELFOSABI_SOLARIS: u8 = 6;
+pub const ELFOSABI_AIX: u8 = 7;
+pub const ELFOSABI_IRIX: u8 = 8;
+pub const ELFOSABI_FREEBSD: u8 = 9;
+pub const ELFOSABI_TRU64: u8 = 10;
+pub const ELFOSABI_MODESTO: u8 = 11;
+pub const ELFOSABI_OPENBSD: u8 = 12;
+pub const ELFOSABI_ARM: u8 = 97;
+pub const ELFOSABI_STANDALONE: u8 = 255;
+
+pub const EI_ABIVERSION: usize = 8;
+
+pub const EI_PAD: usize = 9;
+
+// elf.h - Legal values for e_type (object file type).
+pub const ET_NONE: u16 = 0;
+pub const ET_REL: u16 = 1;
+pub const ET_EXEC: u16 = 2;
+pub const ET_DYN: u16 = 3;
+pub const ET_CORE: u16 = 4;
+pub const ET_NUM: u16 = 5;
+pub const ET_LOOS: u16 = 0xfe00;
+pub const ET_HIOS: u16 = 0xfeff;
+pub const ET_LOPROC: u16 = 0xff00;
+pub const ET_HIPROC: u16 = 0xffff;
+
+// elf.h - Legal values for e_machine (architecture).
+pub const EM_NONE: u16 = 0;
+pub const EM_M32: u16 = 1;
+pub const EM_SPARC: u16 = 2;
+pub const EM_386: u16 = 3;
+pub const EM_68K: u16 = 4;
+pub const EM_88K: u16 = 5;
+pub const EM_860: u16 = 7;
+pub const EM_MIPS: u16 = 8;
+pub const EM_S370: u16 = 9;
+pub const EM_MIPS_RS3_LE: u16 = 10;
+pub const EM_PARISC: u16 = 15;
+pub const EM_VPP500: u16 = 17;
+pub const EM_SPARC32PLUS: u16 = 18;
+pub const EM_960: u16 = 19;
+pub const EM_PPC: u16 = 20;
+pub const EM_PPC64: u16 = 21;
+pub const EM_S390: u16 = 22;
+pub const EM_V800: u16 = 36;
+pub const EM_FR20: u16 = 37;
+pub const EM_RH32: u16 = 38;
+pub const EM_RCE: u16 = 39;
+pub const EM_ARM: u16 = 40;
+pub const EM_FAKE_ALPHA: u16 = 41;
+pub const EM_SH: u16 = 42;
+pub const EM_SPARCV9: u16 = 43;
+pub const EM_TRICORE: u16 = 44;
+pub const EM_ARC: u16 = 45;
+pub const EM_H8_300: u16 = 46;
+pub const EM_H8_300H: u16 = 47;
+pub const EM_H8S: u16 = 48;
+pub const EM_H8_500: u16 = 49;
+pub const EM_IA_64: u16 = 50;
+pub const EM_MIPS_X: u16 = 51;
+pub const EM_COLDFIRE: u16 = 52;
+pub const EM_68HC12: u16 = 53;
+pub const EM_MMA: u16 = 54;
+pub const EM_PCP: u16 = 55;
+pub const EM_NCPU: u16 = 56;
+pub const EM_NDR1: u16 = 57;
+pub const EM_STARCORE: u16 = 58;
+pub const EM_ME16: u16 = 59;
+pub const EM_ST100: u16 = 60;
+pub const EM_TINYJ: u16 = 61;
+pub const EM_X86_64: u16 = 62;
+pub const EM_PDSP: u16 = 63;
+pub const EM_FX66: u16 = 66;
+pub const EM_ST9PLUS: u16 = 67;
+pub const EM_ST7: u16 = 68;
+pub const EM_68HC16: u16 = 69;
+pub const EM_68HC11: u16 = 70;
+pub const EM_68HC08: u16 = 71;
+pub const EM_68HC05: u16 = 72;
+pub const EM_SVX: u16 = 73;
+pub const EM_ST19: u16 = 74;
+pub const EM_VAX: u16 = 75;
+pub const EM_CRIS: u16 = 76;
+pub const EM_JAVELIN: u16 = 77;
+pub const EM_FIREPATH: u16 = 78;
+pub const EM_ZSP: u16 = 79;
+pub const EM_MMIX: u16 = 80;
+pub const EM_HUANY: u16 = 81;
+pub const EM_PRISM: u16 = 82;
+pub const EM_AVR: u16 = 83;
+pub const EM_FR30: u16 = 84;
+pub const EM_D10V: u16 = 85;
+pub const EM_D30V: u16 = 86;
+pub const EM_V850: u16 = 87;
+pub const EM_M32R: u16 = 88;
+pub const EM_MN10300: u16 = 89;
+pub const EM_MN10200: u16 = 90;
+pub const EM_PJ: u16 = 91;
+pub const EM_OPENRISC: u16 = 92;
+pub const EM_ARC_A5: u16 = 93;
+pub const EM_XTENSA: u16 = 94;
+pub const EM_AARCH64: u16 = 183;
+pub const EM_TILEPRO: u16 = 188;
+pub const EM_TILEGX: u16 = 191;
+pub const EM_ALPHA: u16 = 0x9026;
+
+// elf.h - Legal values for e_version (version).
+pub const EV_NONE: u32 = 0;
+pub const EV_CURRENT: u32 = 1;
+pub const EV_NUM: u32 = 2;
+
+// elf.h - Legal values for p_type (segment type).
+pub const PT_NULL: u32 = 0;
+pub const PT_LOAD: u32 = 1;
+pub const PT_DYNAMIC: u32 = 2;
+pub const PT_INTERP: u32 = 3;
+pub const PT_NOTE: u32 = 4;
+pub const PT_SHLIB: u32 = 5;
+pub const PT_PHDR: u32 = 6;
+pub const PT_TLS: u32 = 7;
+pub const PT_NUM: u32 = 8;
+pub const PT_LOOS: u32 = 0x60000000;
+pub const PT_GNU_EH_FRAME: u32 = 0x6474e550;
+pub const PT_GNU_STACK: u32 = 0x6474e551;
+pub const PT_GNU_RELRO: u32 = 0x6474e552;
+pub const PT_LOSUNW: u32 = 0x6ffffffa;
+pub const PT_SUNWBSS: u32 = 0x6ffffffa;
+pub const PT_SUNWSTACK: u32 = 0x6ffffffb;
+pub const PT_HISUNW: u32 = 0x6fffffff;
+pub const PT_HIOS: u32 = 0x6fffffff;
+pub const PT_LOPROC: u32 = 0x70000000;
+pub const PT_HIPROC: u32 = 0x7fffffff;
+
+// Legal values for p_flags (segment flags).
+pub const PF_X: u32 = 1 << 0;
+pub const PF_W: u32 = 1 << 1;
+pub const PF_R: u32 = 1 << 2;
+pub const PF_MASKOS: u32 = 0x0ff00000;
+pub const PF_MASKPROC: u32 = 0xf0000000;
+
+// elf.h - Legal values for a_type (entry type).
pub const AT_NULL: ::c_ulong = 0;
pub const AT_IGNORE: ::c_ulong = 1;
pub const AT_EXECFD: ::c_ulong = 2;
@@ -1951,26 +2133,6 @@ pub const RESOLVE_BENEATH: ::__u64 = 0x08;
pub const RESOLVE_IN_ROOT: ::__u64 = 0x10;
pub const RESOLVE_CACHED: ::__u64 = 0x20;
-// these are used in the p_type field of Elf32_Phdr and Elf64_Phdr, which has
-// the type Elf32Word and Elf64Word respectively. Luckily, both of those are u32
-// so we can use that type here to avoid having to cast.
-pub const PT_NULL: u32 = 0;
-pub const PT_LOAD: u32 = 1;
-pub const PT_DYNAMIC: u32 = 2;
-pub const PT_INTERP: u32 = 3;
-pub const PT_NOTE: u32 = 4;
-pub const PT_SHLIB: u32 = 5;
-pub const PT_PHDR: u32 = 6;
-pub const PT_TLS: u32 = 7;
-pub const PT_NUM: u32 = 8;
-pub const PT_LOOS: u32 = 0x60000000;
-pub const PT_GNU_EH_FRAME: u32 = 0x6474e550;
-pub const PT_GNU_STACK: u32 = 0x6474e551;
-pub const PT_GNU_RELRO: u32 = 0x6474e552;
-pub const PT_HIOS: u32 = 0x6fffffff;
-pub const PT_LOPROC: u32 = 0x70000000;
-pub const PT_HIPROC: u32 = 0x7fffffff;
-
// linux/if_ether.h
pub const ETH_ALEN: ::c_int = 6;
pub const ETH_HLEN: ::c_int = 14;
@@ -2086,6 +2248,7 @@ pub const NFNLGRP_CONNTRACK_EXP_UPDATE: ::c_int = 5;
pub const NFNLGRP_CONNTRACK_EXP_DESTROY: ::c_int = 6;
pub const NFNLGRP_NFTABLES: ::c_int = 7;
pub const NFNLGRP_ACCT_QUOTA: ::c_int = 8;
+pub const NFNLGRP_NFTRACE: ::c_int = 9;
pub const NFNETLINK_V0: ::c_int = 0;
@@ -2101,15 +2264,23 @@ pub const NFNL_SUBSYS_CTNETLINK_TIMEOUT: ::c_int = 8;
pub const NFNL_SUBSYS_CTHELPER: ::c_int = 9;
pub const NFNL_SUBSYS_NFTABLES: ::c_int = 10;
pub const NFNL_SUBSYS_NFT_COMPAT: ::c_int = 11;
-pub const NFNL_SUBSYS_COUNT: ::c_int = 12;
+pub const NFNL_SUBSYS_HOOK: ::c_int = 12;
+pub const NFNL_SUBSYS_COUNT: ::c_int = 13;
pub const NFNL_MSG_BATCH_BEGIN: ::c_int = NLMSG_MIN_TYPE;
pub const NFNL_MSG_BATCH_END: ::c_int = NLMSG_MIN_TYPE + 1;
+pub const NFNL_BATCH_UNSPEC: ::c_int = 0;
+pub const NFNL_BATCH_GENID: ::c_int = 1;
+
// linux/netfilter/nfnetlink_log.h
pub const NFULNL_MSG_PACKET: ::c_int = 0;
pub const NFULNL_MSG_CONFIG: ::c_int = 1;
+pub const NFULA_VLAN_UNSPEC: ::c_int = 0;
+pub const NFULA_VLAN_PROTO: ::c_int = 1;
+pub const NFULA_VLAN_TCI: ::c_int = 2;
+
pub const NFULA_UNSPEC: ::c_int = 0;
pub const NFULA_PACKET_HDR: ::c_int = 1;
pub const NFULA_MARK: ::c_int = 2;
@@ -2130,6 +2301,8 @@ pub const NFULA_HWHEADER: ::c_int = 16;
pub const NFULA_HWLEN: ::c_int = 17;
pub const NFULA_CT: ::c_int = 18;
pub const NFULA_CT_INFO: ::c_int = 19;
+pub const NFULA_VLAN: ::c_int = 20;
+pub const NFULA_L2HDR: ::c_int = 21;
pub const NFULNL_CFG_CMD_NONE: ::c_int = 0;
pub const NFULNL_CFG_CMD_BIND: ::c_int = 1;
@@ -2153,7 +2326,7 @@ pub const NFULNL_CFG_F_SEQ: ::c_int = 0x0001;
pub const NFULNL_CFG_F_SEQ_GLOBAL: ::c_int = 0x0002;
pub const NFULNL_CFG_F_CONNTRACK: ::c_int = 0x0004;
-// linux/netfilter/nfnetlink_log.h
+// linux/netfilter/nfnetlink_queue.h
pub const NFQNL_MSG_PACKET: ::c_int = 0;
pub const NFQNL_MSG_VERDICT: ::c_int = 1;
pub const NFQNL_MSG_CONFIG: ::c_int = 2;
@@ -2178,18 +2351,13 @@ pub const NFQA_EXP: ::c_int = 15;
pub const NFQA_UID: ::c_int = 16;
pub const NFQA_GID: ::c_int = 17;
pub const NFQA_SECCTX: ::c_int = 18;
-/*
- FIXME: These are not yet available in musl sanitized kernel headers and
- make the tests fail. Enable them once musl has them.
-
- See https://github.com/rust-lang/libc/pull/1628 for more details.
pub const NFQA_VLAN: ::c_int = 19;
pub const NFQA_L2HDR: ::c_int = 20;
+pub const NFQA_PRIORITY: ::c_int = 21;
pub const NFQA_VLAN_UNSPEC: ::c_int = 0;
pub const NFQA_VLAN_PROTO: ::c_int = 1;
pub const NFQA_VLAN_TCI: ::c_int = 2;
-*/
pub const NFQNL_CFG_CMD_NONE: ::c_int = 0;
pub const NFQNL_CFG_CMD_BIND: ::c_int = 1;
@@ -2219,6 +2387,8 @@ pub const NFQA_SKB_CSUMNOTREADY: ::c_int = 0x0001;
pub const NFQA_SKB_GSO: ::c_int = 0x0002;
pub const NFQA_SKB_CSUM_NOTVERIFIED: ::c_int = 0x0004;
+// linux/genetlink.h
+
pub const GENL_NAMSIZ: ::c_int = 16;
pub const GENL_MIN_ID: ::c_int = NLMSG_MIN_TYPE;
@@ -2661,6 +2831,62 @@ pub const ARPD_LOOKUP: ::c_ushort = 0x02;
pub const ARPD_FLUSH: ::c_ushort = 0x03;
pub const ATF_MAGIC: ::c_int = 0x80;
+// userspace compat definitions for RTNLGRP_*
+pub const RTMGRP_LINK: ::c_int = 0x00001;
+pub const RTMGRP_NOTIFY: ::c_int = 0x00002;
+pub const RTMGRP_NEIGH: ::c_int = 0x00004;
+pub const RTMGRP_TC: ::c_int = 0x00008;
+pub const RTMGRP_IPV4_IFADDR: ::c_int = 0x00010;
+pub const RTMGRP_IPV4_MROUTE: ::c_int = 0x00020;
+pub const RTMGRP_IPV4_ROUTE: ::c_int = 0x00040;
+pub const RTMGRP_IPV4_RULE: ::c_int = 0x00080;
+pub const RTMGRP_IPV6_IFADDR: ::c_int = 0x00100;
+pub const RTMGRP_IPV6_MROUTE: ::c_int = 0x00200;
+pub const RTMGRP_IPV6_ROUTE: ::c_int = 0x00400;
+pub const RTMGRP_IPV6_IFINFO: ::c_int = 0x00800;
+pub const RTMGRP_DECnet_IFADDR: ::c_int = 0x01000;
+pub const RTMGRP_DECnet_ROUTE: ::c_int = 0x04000;
+pub const RTMGRP_IPV6_PREFIX: ::c_int = 0x20000;
+
+// enum rtnetlink_groups
+pub const RTNLGRP_NONE: ::c_uint = 0x00;
+pub const RTNLGRP_LINK: ::c_uint = 0x01;
+pub const RTNLGRP_NOTIFY: ::c_uint = 0x02;
+pub const RTNLGRP_NEIGH: ::c_uint = 0x03;
+pub const RTNLGRP_TC: ::c_uint = 0x04;
+pub const RTNLGRP_IPV4_IFADDR: ::c_uint = 0x05;
+pub const RTNLGRP_IPV4_MROUTE: ::c_uint = 0x06;
+pub const RTNLGRP_IPV4_ROUTE: ::c_uint = 0x07;
+pub const RTNLGRP_IPV4_RULE: ::c_uint = 0x08;
+pub const RTNLGRP_IPV6_IFADDR: ::c_uint = 0x09;
+pub const RTNLGRP_IPV6_MROUTE: ::c_uint = 0x0a;
+pub const RTNLGRP_IPV6_ROUTE: ::c_uint = 0x0b;
+pub const RTNLGRP_IPV6_IFINFO: ::c_uint = 0x0c;
+pub const RTNLGRP_DECnet_IFADDR: ::c_uint = 0x0d;
+pub const RTNLGRP_NOP2: ::c_uint = 0x0e;
+pub const RTNLGRP_DECnet_ROUTE: ::c_uint = 0x0f;
+pub const RTNLGRP_DECnet_RULE: ::c_uint = 0x10;
+pub const RTNLGRP_NOP4: ::c_uint = 0x11;
+pub const RTNLGRP_IPV6_PREFIX: ::c_uint = 0x12;
+pub const RTNLGRP_IPV6_RULE: ::c_uint = 0x13;
+pub const RTNLGRP_ND_USEROPT: ::c_uint = 0x14;
+pub const RTNLGRP_PHONET_IFADDR: ::c_uint = 0x15;
+pub const RTNLGRP_PHONET_ROUTE: ::c_uint = 0x16;
+pub const RTNLGRP_DCB: ::c_uint = 0x17;
+pub const RTNLGRP_IPV4_NETCONF: ::c_uint = 0x18;
+pub const RTNLGRP_IPV6_NETCONF: ::c_uint = 0x19;
+pub const RTNLGRP_MDB: ::c_uint = 0x1a;
+pub const RTNLGRP_MPLS_ROUTE: ::c_uint = 0x1b;
+pub const RTNLGRP_NSID: ::c_uint = 0x1c;
+pub const RTNLGRP_MPLS_NETCONF: ::c_uint = 0x1d;
+pub const RTNLGRP_IPV4_MROUTE_R: ::c_uint = 0x1e;
+pub const RTNLGRP_IPV6_MROUTE_R: ::c_uint = 0x1f;
+pub const RTNLGRP_NEXTHOP: ::c_uint = 0x20;
+pub const RTNLGRP_BRVLAN: ::c_uint = 0x21;
+pub const RTNLGRP_MCTP_IFADDR: ::c_uint = 0x22;
+pub const RTNLGRP_TUNNEL: ::c_uint = 0x23;
+pub const RTNLGRP_STATS: ::c_uint = 0x24;
+
// linux/module.h
pub const MODULE_INIT_IGNORE_MODVERSIONS: ::c_uint = 0x0001;
pub const MODULE_INIT_IGNORE_VERMAGIC: ::c_uint = 0x0002;
@@ -2673,6 +2899,14 @@ pub const SOF_TIMESTAMPING_RX_SOFTWARE: ::c_uint = 1 << 3;
pub const SOF_TIMESTAMPING_SOFTWARE: ::c_uint = 1 << 4;
pub const SOF_TIMESTAMPING_SYS_HARDWARE: ::c_uint = 1 << 5;
pub const SOF_TIMESTAMPING_RAW_HARDWARE: ::c_uint = 1 << 6;
+pub const SOF_TIMESTAMPING_OPT_ID: ::c_uint = 1 << 7;
+pub const SOF_TIMESTAMPING_TX_SCHED: ::c_uint = 1 << 8;
+pub const SOF_TIMESTAMPING_TX_ACK: ::c_uint = 1 << 9;
+pub const SOF_TIMESTAMPING_OPT_CMSG: ::c_uint = 1 << 10;
+pub const SOF_TIMESTAMPING_OPT_TSONLY: ::c_uint = 1 << 11;
+pub const SOF_TIMESTAMPING_OPT_STATS: ::c_uint = 1 << 12;
+pub const SOF_TIMESTAMPING_OPT_PKTINFO: ::c_uint = 1 << 13;
+pub const SOF_TIMESTAMPING_OPT_TX_SWHW: ::c_uint = 1 << 14;
pub const SOF_TXTIME_DEADLINE_MODE: u32 = 1 << 0;
pub const SOF_TXTIME_REPORT_ERRORS: u32 = 1 << 1;
@@ -3343,17 +3577,6 @@ f! {
minor as ::c_uint
}
- pub fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
- let major = major as ::dev_t;
- let minor = minor as ::dev_t;
- let mut dev = 0;
- dev |= (major & 0x00000fff) << 8;
- dev |= (major & 0xfffff000) << 32;
- dev |= (minor & 0x000000ff) << 0;
- dev |= (minor & 0xffffff00) << 12;
- dev
- }
-
pub fn IPTOS_TOS(tos: u8) -> u8 {
tos & IPTOS_TOS_MASK
}
@@ -3395,6 +3618,19 @@ f! {
}
}
+safe_f! {
+ pub {const} fn makedev(major: ::c_uint, minor: ::c_uint) -> ::dev_t {
+ let major = major as ::dev_t;
+ let minor = minor as ::dev_t;
+ let mut dev = 0;
+ dev |= (major & 0x00000fff) << 8;
+ dev |= (major & 0xfffff000) << 32;
+ dev |= (minor & 0x000000ff) << 0;
+ dev |= (minor & 0xffffff00) << 12;
+ dev
+ }
+}
+
cfg_if! {
if #[cfg(not(target_env = "uclibc"))] {
extern "C" {
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs
index 7e4868b85..c47fa2c4c 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/arm/mod.rs
@@ -837,6 +837,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs
index 7443a09ed..40b507bcd 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/mips/mod.rs
@@ -777,6 +777,14 @@ pub const SYS_faccessat2: ::c_long = 4000 + 439;
pub const SYS_process_madvise: ::c_long = 4000 + 440;
pub const SYS_epoll_pwait2: ::c_long = 4000 + 441;
pub const SYS_mount_setattr: ::c_long = 4000 + 442;
+pub const SYS_quotactl_fd: ::c_long = 4000 + 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 4000 + 444;
+pub const SYS_landlock_add_rule: ::c_long = 4000 + 445;
+pub const SYS_landlock_restrict_self: ::c_long = 4000 + 446;
+pub const SYS_memfd_secret: ::c_long = 4000 + 447;
+pub const SYS_process_mrelease: ::c_long = 4000 + 448;
+pub const SYS_futex_waitv: ::c_long = 4000 + 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 4000 + 450;
cfg_if! {
if #[cfg(libc_align)] {
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs
index 6d2ecf2d8..63824fbf5 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/mod.rs
@@ -3,6 +3,7 @@ pub type c_ulong = u32;
pub type nlink_t = u32;
pub type blksize_t = ::c_long;
pub type __u64 = ::c_ulonglong;
+pub type __s64 = ::c_longlong;
pub type regoff_t = ::c_int;
s! {
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs
index d7ca03813..5b1bf17ed 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/powerpc.rs
@@ -790,6 +790,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
extern "C" {
pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
index 9b68ce258..573624620 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs
@@ -271,6 +271,7 @@ pub const ENOPROTOOPT: ::c_int = 92;
pub const EPROTONOSUPPORT: ::c_int = 93;
pub const ESOCKTNOSUPPORT: ::c_int = 94;
pub const EOPNOTSUPP: ::c_int = 95;
+pub const ENOTSUP: ::c_int = EOPNOTSUPP;
pub const EPFNOSUPPORT: ::c_int = 96;
pub const EAFNOSUPPORT: ::c_int = 97;
pub const EADDRINUSE: ::c_int = 98;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs
index a6efea13b..c319b91b6 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b32/x86/mod.rs
@@ -856,6 +856,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
// offsets in user_regs_structs, from sys/reg.h
pub const EBX: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs
index 845707dcd..14b4bc6d6 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs
@@ -1,5 +1,6 @@
pub type c_char = u8;
pub type __u64 = ::c_ulonglong;
+pub type __s64 = ::c_longlong;
pub type wchar_t = u32;
pub type nlink_t = u32;
pub type blksize_t = ::c_int;
@@ -555,6 +556,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
pub const MCL_CURRENT: ::c_int = 0x0001;
pub const MCL_FUTURE: ::c_int = 0x0002;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs
index 1ed13f66b..22ac91690 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/mips64.rs
@@ -1,6 +1,7 @@
pub type c_char = i8;
pub type wchar_t = i32;
pub type __u64 = ::c_ulong;
+pub type __s64 = ::c_long;
pub type nlink_t = u64;
pub type blksize_t = i64;
@@ -444,6 +445,14 @@ pub const SYS_faccessat2: ::c_long = 5000 + 439;
pub const SYS_process_madvise: ::c_long = 5000 + 440;
pub const SYS_epoll_pwait2: ::c_long = 5000 + 441;
pub const SYS_mount_setattr: ::c_long = 5000 + 442;
+pub const SYS_quotactl_fd: ::c_long = 5000 + 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 5000 + 444;
+pub const SYS_landlock_add_rule: ::c_long = 5000 + 445;
+pub const SYS_landlock_restrict_self: ::c_long = 5000 + 446;
+pub const SYS_memfd_secret: ::c_long = 5000 + 447;
+pub const SYS_process_mrelease: ::c_long = 5000 + 448;
+pub const SYS_futex_waitv: ::c_long = 5000 + 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 5000 + 450;
pub const O_DIRECT: ::c_int = 0x8000;
pub const O_DIRECTORY: ::c_int = 0x10000;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs
index f17d72cb1..0bb4cf837 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/powerpc64.rs
@@ -1,6 +1,7 @@
pub type c_char = u8;
pub type wchar_t = i32;
pub type __u64 = ::c_ulong;
+pub type __s64 = ::c_long;
pub type nlink_t = u64;
pub type blksize_t = ::c_long;
@@ -600,6 +601,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
pub const EDEADLK: ::c_int = 58;
pub const EDEADLOCK: ::c_int = EDEADLK;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs
index fcb28c3cf..f354293e0 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs
@@ -8,6 +8,7 @@ pub type blksize_t = ::c_int;
pub type fsblkcnt64_t = ::c_ulong;
pub type fsfilcnt64_t = ::c_ulong;
pub type __u64 = ::c_ulonglong;
+pub type __s64 = ::c_longlong;
s! {
pub struct pthread_attr_t {
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs
index cb6237abc..60bfc8d3e 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/s390x.rs
@@ -4,6 +4,7 @@ pub type nlink_t = u64;
pub type wchar_t = i32;
pub type greg_t = u64;
pub type __u64 = u64;
+pub type __s64 = i64;
s! {
pub struct ipc_perm {
@@ -710,3 +711,11 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs
index 3429c2c1a..8198dc2f3 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs
@@ -3,6 +3,7 @@ pub type wchar_t = i32;
pub type nlink_t = u64;
pub type blksize_t = ::c_long;
pub type __u64 = ::c_ulonglong;
+pub type __s64 = ::c_longlong;
pub type greg_t = i64;
s! {
@@ -599,6 +600,14 @@ pub const SYS_faccessat2: ::c_long = 439;
pub const SYS_process_madvise: ::c_long = 440;
pub const SYS_epoll_pwait2: ::c_long = 441;
pub const SYS_mount_setattr: ::c_long = 442;
+pub const SYS_quotactl_fd: ::c_long = 443;
+pub const SYS_landlock_create_ruleset: ::c_long = 444;
+pub const SYS_landlock_add_rule: ::c_long = 445;
+pub const SYS_landlock_restrict_self: ::c_long = 446;
+pub const SYS_memfd_secret: ::c_long = 447;
+pub const SYS_process_mrelease: ::c_long = 448;
+pub const SYS_futex_waitv: ::c_long = 449;
+pub const SYS_set_mempolicy_home_node: ::c_long = 450;
// offsets in user_regs_structs, from sys/reg.h
pub const R15: ::c_int = 0;
diff --git a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs
index 6cdc31388..894f377ac 100644
--- a/vendor/libc/src/unix/linux_like/linux/musl/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/musl/mod.rs
@@ -754,6 +754,9 @@ extern "C" {
pub fn memfd_create(name: *const ::c_char, flags: ::c_uint) -> ::c_int;
pub fn mlock2(addr: *const ::c_void, len: ::size_t, flags: ::c_uint) -> ::c_int;
pub fn malloc_usable_size(ptr: *mut ::c_void) -> ::size_t;
+
+ pub fn euidaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int;
+ pub fn eaccess(pathname: *const ::c_char, mode: ::c_int) -> ::c_int;
}
cfg_if! {
diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs
index e0279574b..a0035b277 100644
--- a/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/uclibc/arm/mod.rs
@@ -19,6 +19,7 @@ pub type blkcnt_t = ::c_long;
pub type fsblkcnt64_t = u64;
pub type fsfilcnt64_t = u64;
pub type __u64 = ::c_ulonglong;
+pub type __s64 = ::c_longlong;
s! {
pub struct cmsghdr {
diff --git a/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs b/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs
index 529711fce..43ac79296 100644
--- a/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs
+++ b/vendor/libc/src/unix/linux_like/linux/uclibc/x86_64/mod.rs
@@ -20,6 +20,7 @@ pub type wchar_t = ::c_int;
pub type fsblkcnt64_t = u64;
pub type fsfilcnt64_t = u64;
pub type __u64 = ::c_ulong;
+pub type __s64 = ::c_long;
s! {
pub struct ipc_perm {
diff --git a/vendor/libc/src/unix/linux_like/mod.rs b/vendor/libc/src/unix/linux_like/mod.rs
index 57600f24b..46964cc17 100644
--- a/vendor/libc/src/unix/linux_like/mod.rs
+++ b/vendor/libc/src/unix/linux_like/mod.rs
@@ -1434,6 +1434,7 @@ cfg_if! {
pub const UDF_SUPER_MAGIC: ::c_long = 0x15013346;
pub const USBDEVICE_SUPER_MAGIC: ::c_long = 0x00009fa2;
pub const XENFS_SUPER_MAGIC: ::c_long = 0xabba1974;
+ pub const NSFS_MAGIC: ::c_long = 0x6e736673;
} else if #[cfg(target_arch = "s390x")] {
pub const ADFS_SUPER_MAGIC: ::c_uint = 0x0000adf5;
pub const AFFS_SUPER_MAGIC: ::c_uint = 0x0000adff;
@@ -1487,6 +1488,7 @@ cfg_if! {
pub const UDF_SUPER_MAGIC: ::c_uint = 0x15013346;
pub const USBDEVICE_SUPER_MAGIC: ::c_uint = 0x00009fa2;
pub const XENFS_SUPER_MAGIC: ::c_uint = 0xabba1974;
+ pub const NSFS_MAGIC: ::c_uint = 0x6e736673;
}
}
diff --git a/vendor/libc/src/unix/newlib/mod.rs b/vendor/libc/src/unix/newlib/mod.rs
index 34a63a81a..1a694691a 100644
--- a/vendor/libc/src/unix/newlib/mod.rs
+++ b/vendor/libc/src/unix/newlib/mod.rs
@@ -41,7 +41,7 @@ pub type tcflag_t = ::c_uint;
pub type useconds_t = u32;
cfg_if! {
- if #[cfg(target_os = "horizon")] {
+ if #[cfg(any(target_os = "horizon", all(target_os = "espidf", espidf_time64)))] {
pub type time_t = ::c_longlong;
} else {
pub type time_t = i32;
diff --git a/vendor/libc/src/unix/solarish/illumos.rs b/vendor/libc/src/unix/solarish/illumos.rs
index c86c6d69d..7d491d382 100644
--- a/vendor/libc/src/unix/solarish/illumos.rs
+++ b/vendor/libc/src/unix/solarish/illumos.rs
@@ -42,6 +42,9 @@ pub const F_OFD_SETLKW: ::c_int = 49;
pub const F_FLOCK: ::c_int = 53;
pub const F_FLOCKW: ::c_int = 54;
+pub const F_DUPFD_CLOEXEC: ::c_int = 37;
+pub const F_DUP2FD_CLOEXEC: ::c_int = 36;
+
pub const FIL_ATTACH: ::c_int = 0x1;
pub const FIL_DETACH: ::c_int = 0x2;
pub const FIL_LIST: ::c_int = 0x3;
@@ -51,6 +54,8 @@ pub const FILF_AUTO: ::c_int = 0x2;
pub const FILF_BYPASS: ::c_int = 0x4;
pub const SOL_FILTER: ::c_int = 0xfffc;
+pub const MADV_PURGE: ::c_int = 9;
+
pub const MR_HDR_AOUT: ::c_uint = 0x3;
pub const B1000000: ::speed_t = 24;
diff --git a/vendor/libc/src/unix/solarish/mod.rs b/vendor/libc/src/unix/solarish/mod.rs
index fef08d08f..c5da62be0 100644
--- a/vendor/libc/src/unix/solarish/mod.rs
+++ b/vendor/libc/src/unix/solarish/mod.rs
@@ -1327,7 +1327,6 @@ 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 F_DUPFD_CLOEXEC: ::c_int = 37;
pub const F_SETLK: ::c_int = 6;
pub const F_SETLKW: ::c_int = 7;
pub const F_GETLK: ::c_int = 14;
@@ -1441,6 +1440,7 @@ pub const MAP_RENAME: ::c_int = 0x20;
pub const MAP_ALIGN: ::c_int = 0x200;
pub const MAP_TEXT: ::c_int = 0x400;
pub const MAP_INITDATA: ::c_int = 0x800;
+pub const MAP_32BIT: ::c_int = 0x80;
pub const MAP_FAILED: *mut ::c_void = !0 as *mut ::c_void;
pub const MCL_CURRENT: ::c_int = 0x0001;
@@ -1601,7 +1601,6 @@ pub const NI_NUMERICSCOPE: ::c_uint = 0x0040;
pub const F_DUPFD: ::c_int = 0;
pub const F_DUP2FD: ::c_int = 9;
-pub const F_DUP2FD_CLOEXEC: ::c_int = 36;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
@@ -1685,6 +1684,9 @@ pub const MADV_SEQUENTIAL: ::c_int = 2;
pub const MADV_WILLNEED: ::c_int = 3;
pub const MADV_DONTNEED: ::c_int = 4;
pub const MADV_FREE: ::c_int = 5;
+pub const MADV_ACCESS_DEFAULT: ::c_int = 6;
+pub const MADV_ACCESS_LWP: ::c_int = 7;
+pub const MADV_ACCESS_MANY: ::c_int = 8;
pub const AF_UNSPEC: ::c_int = 0;
pub const AF_UNIX: ::c_int = 1;
@@ -1894,6 +1896,14 @@ pub const IPC_RMID: ::c_int = 10;
pub const IPC_SET: ::c_int = 11;
pub const IPC_SEAT: ::c_int = 12;
+// sys/shm.h
+pub const SHM_R: ::c_int = 0o400;
+pub const SHM_W: ::c_int = 0o200;
+pub const SHM_RDONLY: ::c_int = 0o10000;
+pub const SHM_RND: ::c_int = 0o20000;
+pub const SHM_SHARE_MMU: ::c_int = 0o40000;
+pub const SHM_PAGEABLE: ::c_int = 0o100000;
+
pub const SHUT_RD: ::c_int = 0;
pub const SHUT_WR: ::c_int = 1;
pub const SHUT_RDWR: ::c_int = 2;
@@ -3135,6 +3145,8 @@ extern "C" {
pub fn setpflags(flags: ::c_uint, value: ::c_uint) -> ::c_int;
pub fn sysinfo(command: ::c_int, buf: *mut ::c_char, count: ::c_long) -> ::c_int;
+
+ pub fn faccessat(fd: ::c_int, path: *const ::c_char, amode: ::c_int, flag: ::c_int) -> ::c_int;
}
#[link(name = "sendfile")]
diff --git a/vendor/libc/src/unix/solarish/solaris.rs b/vendor/libc/src/unix/solarish/solaris.rs
index 8ea070c6d..3fb166049 100644
--- a/vendor/libc/src/unix/solarish/solaris.rs
+++ b/vendor/libc/src/unix/solarish/solaris.rs
@@ -33,8 +33,13 @@ pub const AF_LOCAL: ::c_int = 0;
pub const AF_FILE: ::c_int = 0;
pub const TCP_KEEPIDLE: ::c_int = 0x1d;
-pub const TCP_KEEPCNT: ::c_int = 0x1e;
-pub const TCP_KEEPINTVL: ::c_int = 0x1f;
+pub const TCP_KEEPINTVL: ::c_int = 0x1e;
+pub const TCP_KEEPCNT: ::c_int = 0x1f;
+
+pub const F_DUPFD_CLOEXEC: ::c_int = 47;
+pub const F_DUPFD_CLOFORK: ::c_int = 49;
+pub const F_DUP2FD_CLOEXEC: ::c_int = 48;
+pub const F_DUP2FD_CLOFORK: ::c_int = 50;
extern "C" {
pub fn fexecve(
@@ -67,6 +72,8 @@ extern "C" {
pub fn fattach(fildes: ::c_int, path: *const ::c_char) -> ::c_int;
pub fn pthread_getattr_np(thread: ::pthread_t, attr: *mut ::pthread_attr_t) -> ::c_int;
+
+ pub fn euidaccess(path: *const ::c_char, amode: ::c_int) -> ::c_int;
}
s_no_extra_traits! {
diff --git a/vendor/libc/src/unix/solarish/x86_64.rs b/vendor/libc/src/unix/solarish/x86_64.rs
index 5f75bdb79..bca552f37 100644
--- a/vendor/libc/src/unix/solarish/x86_64.rs
+++ b/vendor/libc/src/unix/solarish/x86_64.rs
@@ -157,3 +157,34 @@ cfg_if! {
}
}
+
+// sys/regset.h
+
+pub const REG_GSBASE: ::c_int = 27;
+pub const REG_FSBASE: ::c_int = 26;
+pub const REG_DS: ::c_int = 25;
+pub const REG_ES: ::c_int = 24;
+pub const REG_GS: ::c_int = 23;
+pub const REG_FS: ::c_int = 22;
+pub const REG_SS: ::c_int = 21;
+pub const REG_RSP: ::c_int = 20;
+pub const REG_RFL: ::c_int = 19;
+pub const REG_CS: ::c_int = 18;
+pub const REG_RIP: ::c_int = 17;
+pub const REG_ERR: ::c_int = 16;
+pub const REG_TRAPNO: ::c_int = 15;
+pub const REG_RAX: ::c_int = 14;
+pub const REG_RCX: ::c_int = 13;
+pub const REG_RDX: ::c_int = 12;
+pub const REG_RBX: ::c_int = 11;
+pub const REG_RBP: ::c_int = 10;
+pub const REG_RSI: ::c_int = 9;
+pub const REG_RDI: ::c_int = 8;
+pub const REG_R8: ::c_int = 7;
+pub const REG_R9: ::c_int = 6;
+pub const REG_R10: ::c_int = 5;
+pub const REG_R11: ::c_int = 4;
+pub const REG_R12: ::c_int = 3;
+pub const REG_R13: ::c_int = 2;
+pub const REG_R14: ::c_int = 1;
+pub const REG_R15: ::c_int = 0;
diff --git a/vendor/lock_api/.cargo-checksum.json b/vendor/lock_api/.cargo-checksum.json
index ceb83ada3..cf8df26fa 100644
--- a/vendor/lock_api/.cargo-checksum.json
+++ b/vendor/lock_api/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"f0fb3e65549d1353e2e199977db7825c29721bbeb71dee9bb3905437dd444dce","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"af84139c71d151adead0b4398c394a7dd16087bb2db44b14a0ed970ce868a6c6","src/lib.rs":"7b67c3b69c1b5e97248afe0f6c3bc353c793ed1ce4a5d5177e63f3f05d79c63b","src/mutex.rs":"dc4131ebf73e0474948d1849934ad5156e4a3dbd55f6881e60fd6c0acb6aa861","src/remutex.rs":"659454e66fa72e678e0aa1b83151c81c90321368dc6f4c31315230b969d4936e","src/rwlock.rs":"4f35072ca1fb476089d1548c40af775564bb7e763f86ec41a2190f8c659593cc"},"package":"327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"} \ No newline at end of file
+{"files":{"Cargo.toml":"15453a84e25ac6ed84c95e11e71d9bee5b360b6dc787a433b8416b91bf8e216c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","build.rs":"af84139c71d151adead0b4398c394a7dd16087bb2db44b14a0ed970ce868a6c6","src/lib.rs":"7b67c3b69c1b5e97248afe0f6c3bc353c793ed1ce4a5d5177e63f3f05d79c63b","src/mutex.rs":"f5627b1269a9b0d116507af19b8619b9922b95b73a84ab5be3134620c97caadb","src/remutex.rs":"4fa5f0448591a32ac37f2cf9af89813f32e415d2a1ca426670a0cdaccbca66aa","src/rwlock.rs":"9160cbada7e3179bd8ec13769761437e90bfb616316947dc0cc5959f0bcdc5b9"},"package":"435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"} \ No newline at end of file
diff --git a/vendor/lock_api/Cargo.toml b/vendor/lock_api/Cargo.toml
index c1ebdb7b7..b1ff8c4db 100644
--- a/vendor/lock_api/Cargo.toml
+++ b/vendor/lock_api/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "lock_api"
-version = "0.4.7"
+version = "0.4.9"
authors = ["Amanieu d'Antras <amanieu@gmail.com>"]
description = "Wrappers to create fully-featured Mutex and RwLock types. Compatible with no_std."
keywords = [
diff --git a/vendor/lock_api/src/mutex.rs b/vendor/lock_api/src/mutex.rs
index 4e1b879e5..c97e5430b 100644
--- a/vendor/lock_api/src/mutex.rs
+++ b/vendor/lock_api/src/mutex.rs
@@ -681,15 +681,38 @@ unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'
#[must_use = "if unused the Mutex will immediately unlock"]
pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
mutex: Arc<Mutex<R, T>>,
- marker: PhantomData<R::GuardMarker>,
+ marker: PhantomData<*const ()>,
+}
+
+#[cfg(feature = "arc_lock")]
+unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where
+ R::GuardMarker: Send
+{
+}
+#[cfg(feature = "arc_lock")]
+unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where
+ R::GuardMarker: Sync
+{
}
#[cfg(feature = "arc_lock")]
impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
/// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
#[inline]
- pub fn mutex(&self) -> &Arc<Mutex<R, T>> {
- &self.mutex
+ pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
+ &s.mutex
+ }
+
+ /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
+ #[inline]
+ pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
+ // Safety: Skip our Drop impl and manually unlock the mutex.
+ let arc = unsafe { ptr::read(&s.mutex) };
+ mem::forget(s);
+ unsafe {
+ arc.raw.unlock();
+ }
+ arc
}
/// Temporarily unlocks the mutex to execute the given function.
diff --git a/vendor/lock_api/src/remutex.rs b/vendor/lock_api/src/remutex.rs
index fa0e934d1..3e2010f2b 100644
--- a/vendor/lock_api/src/remutex.rs
+++ b/vendor/lock_api/src/remutex.rs
@@ -646,7 +646,7 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGu
/// in already locked the mutex.
///
/// This is an associated function that needs to be
- /// used as `ReentrantMutexGuard::map(...)`. A method would interfere with methods of
+ /// used as `ReentrantMutexGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(
@@ -654,10 +654,10 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a> ReentrantMutexGu
f: F,
) -> Result<MappedReentrantMutexGuard<'a, R, G, U>, Self>
where
- F: FnOnce(&mut T) -> Option<&mut U>,
+ F: FnOnce(&T) -> Option<&U>,
{
let raw = &s.remutex.raw;
- let data = match f(unsafe { &mut *s.remutex.data.get() }) {
+ let data = match f(unsafe { &*s.remutex.data.get() }) {
Some(data) => data,
None => return Err(s),
};
@@ -942,7 +942,7 @@ impl<'a, R: RawMutex + 'a, G: GetThreadId + 'a, T: ?Sized + 'a>
/// in already locked the mutex.
///
/// This is an associated function that needs to be
- /// used as `MappedReentrantMutexGuard::map(...)`. A method would interfere with methods of
+ /// used as `MappedReentrantMutexGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(
diff --git a/vendor/lock_api/src/rwlock.rs b/vendor/lock_api/src/rwlock.rs
index e947f1ec0..c972fb6c6 100644
--- a/vendor/lock_api/src/rwlock.rs
+++ b/vendor/lock_api/src/rwlock.rs
@@ -1218,13 +1218,13 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockReadGuard<'a, R, T> {
}
/// Attempts to make a new `MappedRwLockReadGuard` for a component of the
- /// locked data. The original guard is return if the closure returns `None`.
+ /// locked data. Returns the original guard if the closure returns `None`.
///
/// This operation cannot fail as the `RwLockReadGuard` passed
/// in already locked the data.
///
/// This is an associated function that needs to be
- /// used as `RwLockReadGuard::map(...)`. A method would interfere with methods of
+ /// used as `RwLockReadGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
@@ -1512,7 +1512,7 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> RwLockWriteGuard<'a, R, T> {
/// in already locked the data.
///
/// This is an associated function that needs to be
- /// used as `RwLockWriteGuard::map(...)`. A method would interfere with methods of
+ /// used as `RwLockWriteGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
@@ -2374,7 +2374,7 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockReadGuard<'a, R, T> {
/// in already locked the data.
///
/// This is an associated function that needs to be
- /// used as `MappedRwLockReadGuard::map(...)`. A method would interfere with methods of
+ /// used as `MappedRwLockReadGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockReadGuard<'a, R, U>, Self>
@@ -2512,7 +2512,7 @@ impl<'a, R: RawRwLock + 'a, T: ?Sized + 'a> MappedRwLockWriteGuard<'a, R, T> {
/// in already locked the data.
///
/// This is an associated function that needs to be
- /// used as `MappedRwLockWriteGuard::map(...)`. A method would interfere with methods of
+ /// used as `MappedRwLockWriteGuard::try_map(...)`. A method would interfere with methods of
/// the same name on the contents of the locked data.
#[inline]
pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedRwLockWriteGuard<'a, R, U>, Self>
diff --git a/vendor/matches/.cargo-checksum.json b/vendor/matches/.cargo-checksum.json
deleted file mode 100644
index 65871b7ff..000000000
--- a/vendor/matches/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"Cargo.toml":"194024a82bba1c84226ac827330511fba74474a7914b1319e6700285c15f5812","LICENSE":"d7b49708075b5f43f8e108464f1970c8c66fa8b6afce4f9c944da3af77cc1460","lib.rs":"9f4187510972f5fc356ca60d19daa0e69643dd6b530edf7c928cbd75a2b990c5","tests/macro_use_one.rs":"4f599fae16f1aef369050bf0ad74cbefec06c430b29e0c9ab0811ac9592e997a","tests/use_star.rs":"39a23b8002544f65e7a896e2cefe8e0af7404151fa65d327e748f5c1101badf8"},"package":"a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"} \ No newline at end of file
diff --git a/vendor/matches/Cargo.toml b/vendor/matches/Cargo.toml
deleted file mode 100644
index 57a249a40..000000000
--- a/vendor/matches/Cargo.toml
+++ /dev/null
@@ -1,24 +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 = "matches"
-version = "0.1.9"
-authors = ["Simon Sapin <simon.sapin@exyr.org>"]
-description = "A macro to evaluate, as a boolean, whether an expression matches a pattern."
-documentation = "https://docs.rs/matches/"
-license = "MIT"
-repository = "https://github.com/SimonSapin/rust-std-candidates"
-
-[lib]
-name = "matches"
-path = "lib.rs"
diff --git a/vendor/matches/lib.rs b/vendor/matches/lib.rs
deleted file mode 100644
index 3bcd6e2fe..000000000
--- a/vendor/matches/lib.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-#![no_std]
-
-/// Check if an expression matches a refutable pattern.
-///
-/// Syntax: `matches!(` *expression* `,` *pattern* `)`
-///
-/// Return a boolean, true if the expression matches the pattern, false otherwise.
-///
-/// # Examples
-///
-/// ```
-/// #[macro_use]
-/// extern crate matches;
-///
-/// pub enum Foo<T> {
-/// A,
-/// B(T),
-/// }
-///
-/// impl<T> Foo<T> {
-/// pub fn is_a(&self) -> bool {
-/// matches!(*self, Foo::A)
-/// }
-///
-/// pub fn is_b(&self) -> bool {
-/// matches!(*self, Foo::B(_))
-/// }
-/// }
-///
-/// # fn main() { }
-/// ```
-#[macro_export]
-macro_rules! matches {
- ($expression:expr, $($pattern:tt)+) => {
- match $expression {
- $($pattern)+ => true,
- _ => false
- }
- }
-}
-
-/// Assert that an expression matches a refutable pattern.
-///
-/// Syntax: `assert_matches!(` *expression* `,` *pattern* `)`
-///
-/// Panic with a message that shows the expression if it does not match the
-/// pattern.
-///
-/// # Examples
-///
-/// ```
-/// #[macro_use]
-/// extern crate matches;
-///
-/// fn main() {
-/// let data = [1, 2, 3];
-/// assert_matches!(data.get(1), Some(_));
-/// }
-/// ```
-#[macro_export]
-macro_rules! assert_matches {
- ($expression:expr, $($pattern:tt)+) => {
- match $expression {
- $($pattern)+ => (),
- ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pattern)+)),
- }
- }
-}
-
-/// Assert that an expression matches a refutable pattern using debug assertions.
-///
-/// Syntax: `debug_assert_matches!(` *expression* `,` *pattern* `)`
-///
-/// If debug assertions are enabled, panic with a message that shows the
-/// expression if it does not match the pattern.
-///
-/// When debug assertions are not enabled, this macro does nothing.
-///
-/// # Examples
-///
-/// ```
-/// #[macro_use]
-/// extern crate matches;
-///
-/// fn main() {
-/// let data = [1, 2, 3];
-/// debug_assert_matches!(data.get(1), Some(_));
-/// }
-/// ```
-#[macro_export]
-macro_rules! debug_assert_matches {
- ($expression:expr, $($pattern:tt)+) => {
- if cfg!(debug_assertions) {
- match $expression {
- $($pattern)+ => (),
- ref e => panic!("assertion failed: `{:?}` does not match `{}`", e, stringify!($($pattern)+)),
- }
- }
- }
-}
-
-#[test]
-fn matches_works() {
- let foo = Some("-12");
- assert!(matches!(foo, Some(bar) if
- matches!(bar.as_bytes()[0], b'+' | b'-') &&
- matches!(bar.as_bytes()[1], b'0'...b'9')
- ));
-}
-
-#[test]
-fn assert_matches_works() {
- let foo = Some("-12");
- assert_matches!(foo, Some(bar) if
- matches!(bar.as_bytes()[0], b'+' | b'-') &&
- matches!(bar.as_bytes()[1], b'0'...b'9')
- );
-}
-
-#[test]
-#[should_panic(expected = "assertion failed: `Some(\"-AB\")` does not match ")]
-fn assert_matches_panics() {
- let foo = Some("-AB");
- assert_matches!(foo, Some(bar) if
- matches!(bar.as_bytes()[0], b'+' | b'-') &&
- matches!(bar.as_bytes()[1], b'0'...b'9')
- );
-}
diff --git a/vendor/matches/tests/macro_use_one.rs b/vendor/matches/tests/macro_use_one.rs
deleted file mode 100644
index a527a89ce..000000000
--- a/vendor/matches/tests/macro_use_one.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// https://github.com/SimonSapin/rust-std-candidates/issues/12
-#[macro_use(matches)] extern crate matches;
-
-#[test]
-fn matches_works() {
- let foo = Some("-12");
- assert!(matches!(foo, Some(bar) if
- matches!(bar.as_bytes()[0], b'+' | b'-') &&
- matches!(bar.as_bytes()[1], b'0'...b'9')
- ));
-}
diff --git a/vendor/matches/tests/use_star.rs b/vendor/matches/tests/use_star.rs
deleted file mode 100644
index 58a670b93..000000000
--- a/vendor/matches/tests/use_star.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//! https://github.com/SimonSapin/rust-std-candidates/issues/22
-
-extern crate matches;
-
-use matches::*;
-
-#[test]
-fn test_assert_matches() {
- assert_matches!(4, 4)
-}
diff --git a/vendor/miniz_oxide/.cargo-checksum.json b/vendor/miniz_oxide/.cargo-checksum.json
index a30f6d5ad..16e89c510 100644
--- a/vendor/miniz_oxide/.cargo-checksum.json
+++ b/vendor/miniz_oxide/.cargo-checksum.json
@@ -1 +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
+{"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
diff --git a/vendor/miniz_oxide/Cargo.toml b/vendor/miniz_oxide/Cargo.toml
index 7546128ce..7fa9d3e06 100644
--- a/vendor/miniz_oxide/Cargo.toml
+++ b/vendor/miniz_oxide/Cargo.toml
@@ -12,20 +12,32 @@
[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/*"]
+version = "0.5.4"
+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"]
+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
@@ -51,5 +63,10 @@ default-features = false
[features]
default = []
-rustc-dep-of-std = ["core", "alloc", "compiler_builtins", "adler/rustc-dep-of-std"]
+rustc-dep-of-std = [
+ "core",
+ "alloc",
+ "compiler_builtins",
+ "adler/rustc-dep-of-std",
+]
simd = ["simd-adler32"]
diff --git a/vendor/miniz_oxide/src/inflate/mod.rs b/vendor/miniz_oxide/src/inflate/mod.rs
index 535392327..03b9dc988 100644
--- a/vendor/miniz_oxide/src/inflate/mod.rs
+++ b/vendor/miniz_oxide/src/inflate/mod.rs
@@ -151,14 +151,12 @@ fn decompress_to_vec_inner(
}
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 {
+ // if the buffer has already reached the size limit, return an error
+ if ret.len() >= max_output_size {
return Err(TINFLStatus::HasMoreOutput);
- };
+ }
+ // 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);
}
diff --git a/vendor/once_cell/.cargo-checksum.json b/vendor/once_cell/.cargo-checksum.json
index 9dffae3ad..6f8adad72 100644
--- a/vendor/once_cell/.cargo-checksum.json
+++ b/vendor/once_cell/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"1638f5757551c399130656e1daab76b0322538923a791bf39e9ec247257daf79","Cargo.lock":"417a830ee5d5359f413fdf973391bf137de7ea8b075d83dcf798f1d3de36cfda","Cargo.toml":"d083a23d498e2dbf1cb3f249bdade38715b3cb237a38b733df79f20824eec4f7","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":"90541b093ed1d1cbb73f4097ff02cf80657e28264d281d6a31d96a708fdfea90","examples/reentrant_init_deadlocks.rs":"ff84929de27a848e5b155549caa96db5db5f030afca975f8ba3f3da640083001","examples/regex.rs":"4a2e0fb093c7f5bbe0fff8689fc0c670c5334344a1bfda376f5faa98a05d459f","examples/test_synchronization.rs":"88abd5c16275bb2f2d77eaecf369d97681404a77b8edd0021f24bfd377c46be3","src/imp_pl.rs":"1959494004fb0ee7443e97c4abd8be69d7173fe2b66f8fff0bca7b5c8e512525","src/imp_std.rs":"33be3a0df87e092abd68280dc72d50534d273d17eb86940e7ba2b8a45da78a70","src/lib.rs":"5320847175dc279e7abd2d98e17ab8d05b2eb7e383a4f249623b71a5209f2346","src/race.rs":"5a19afca4b5510d09ca7317b96f5642725c58b0969b2bdeb7275ed674d061e5d","tests/it.rs":"501c4ab3f4e718fa555707e9d32f3688c05e4ef8ea967e72e1c99da6bb06a0ad"},"package":"074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"f6198c1a83a8245a7b2ab062a316f3f97dfba190ac1d6bb47949e9c0cf4dac80","Cargo.lock":"e69c2663fe7efb3a4e463af446fa1367bd8e008100500137052ef15b84b02ebc","Cargo.toml":"d08e0411e5eda265a3359939f1fb646dff29ca38896222ffe0900b0af8e3ae70","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_pl.rs":"1959494004fb0ee7443e97c4abd8be69d7173fe2b66f8fff0bca7b5c8e512525","src/imp_std.rs":"33be3a0df87e092abd68280dc72d50534d273d17eb86940e7ba2b8a45da78a70","src/lib.rs":"88d2f7a63bd63f630733c86ea035b53e53f2f8d3c44f1025bc9bbe5ceaa7375f","src/race.rs":"5a19afca4b5510d09ca7317b96f5642725c58b0969b2bdeb7275ed674d061e5d","tests/it.rs":"4448a74a9898babfb943bae42ebfe3b07ec2b002ea39712127159955015d33b4"},"package":"e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"} \ No newline at end of file
diff --git a/vendor/once_cell/CHANGELOG.md b/vendor/once_cell/CHANGELOG.md
index ffb5b1df3..005ce6951 100644
--- a/vendor/once_cell/CHANGELOG.md
+++ b/vendor/once_cell/CHANGELOG.md
@@ -4,6 +4,18 @@
-
+## 1.15.0
+
+- Increase minimal supported Rust version to 1.56.0.
+- Implement `UnwindSafe` even if the `std` feature is disabled.
+
+## 1.14.0
+
+- Add extension to `unsync` and `sync` `Lazy` mut API:
+ - `force_mut`
+ - `get_mut`
+
+
## 1.13.1
- Make implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228).
diff --git a/vendor/once_cell/Cargo.lock b/vendor/once_cell/Cargo.lock
index 2e981967f..83f83681a 100644
--- a/vendor/once_cell/Cargo.lock
+++ b/vendor/once_cell/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "0.7.4"
+version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282"
+checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
@@ -34,9 +34,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "critical-section"
-version = "1.0.0"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce181dda5a65c00fcbce2b9d44ad9be001202a54fb321865ed273ac39aa8ccbe"
+checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52"
[[package]]
name = "crossbeam-utils"
@@ -45,36 +45,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
dependencies = [
"cfg-if",
- "once_cell 1.13.0",
+ "once_cell 1.14.0",
]
[[package]]
name = "lazy_static"
-version = "1.0.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.131"
+version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04c3b4822ccebfa39c02fc03d1534441b22ead323fa0f48bb7ddd8e6ba076a40"
+checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "memchr"
-version = "2.2.1"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "once_cell"
-version = "1.13.0"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
+checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "once_cell"
-version = "1.13.1"
+version = "1.15.0"
dependencies = [
"atomic-polyfill",
"crossbeam-utils",
@@ -107,25 +107,20 @@ dependencies = [
[[package]]
name = "regex"
-version = "1.2.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
- "thread_local",
- "utf8-ranges",
]
[[package]]
name = "regex-syntax"
-version = "0.6.9"
+version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfaca88e749e19dffb60f77b55e5d87a872fac7e9e48598f7cf93b2d8c047b0a"
-dependencies = [
- "ucd-util",
-]
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "smallvec"
@@ -134,27 +129,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
-name = "thread_local"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
-dependencies = [
- "lazy_static",
-]
-
-[[package]]
-name = "ucd-util"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3bf5cdf1df6b578c0947a94d4740bbb2b2afd1b898e33df1ff07b555a335e4"
-
-[[package]]
-name = "utf8-ranges"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4"
-
-[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/vendor/once_cell/Cargo.toml b/vendor/once_cell/Cargo.toml
index e8222f163..bde77ee9d 100644
--- a/vendor/once_cell/Cargo.toml
+++ b/vendor/once_cell/Cargo.toml
@@ -10,9 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.56"
name = "once_cell"
-version = "1.13.1"
+version = "1.15.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
exclude = [
"*.png",
@@ -33,6 +34,7 @@ categories = [
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/matklad/once_cell"
+resolver = "2"
[package.metadata.docs.rs]
all-features = true
diff --git a/vendor/once_cell/examples/lazy_static.rs b/vendor/once_cell/examples/lazy_static.rs
index f0505609b..3cdb19f2a 100644
--- a/vendor/once_cell/examples/lazy_static.rs
+++ b/vendor/once_cell/examples/lazy_static.rs
@@ -32,5 +32,5 @@ fn main() {
// The same works for function-style:
assert_eq!(hashmap().get(&0), Some(&"foo"));
- assert_eq!(hashmap().get(&0), Some(&"bar"));
+ assert_eq!(hashmap().get(&1), Some(&"bar"));
}
diff --git a/vendor/once_cell/src/lib.rs b/vendor/once_cell/src/lib.rs
index 70f08dea6..6de1e3eeb 100644
--- a/vendor/once_cell/src/lib.rs
+++ b/vendor/once_cell/src/lib.rs
@@ -267,7 +267,7 @@
//!
//! # Minimum Supported `rustc` Version
//!
-//! This crate's minimum supported `rustc` version is `1.36.0`.
+//! This crate's minimum supported `rustc` version is `1.56.0`.
//!
//! If only the `std` feature is enabled, MSRV will be updated conservatively.
//! When using other features, like `parking_lot`, MSRV might be updated more frequently, up to the latest stable.
@@ -348,11 +348,9 @@ pub mod unsync {
cell::{Cell, UnsafeCell},
fmt, hint, mem,
ops::{Deref, DerefMut},
+ panic::{RefUnwindSafe, UnwindSafe},
};
- #[cfg(feature = "std")]
- use std::panic::{RefUnwindSafe, UnwindSafe};
-
/// A cell which can be written to only once. It is not thread safe.
///
/// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&`
@@ -382,9 +380,7 @@ pub mod unsync {
// `&unsync::OnceCell` to sneak a `T` through `catch_unwind`,
// by initializing the cell in closure and extracting the value in the
// `Drop`.
- #[cfg(feature = "std")]
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
- #[cfg(feature = "std")]
impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
impl<T> Default for OnceCell<T> {
@@ -680,7 +676,6 @@ pub mod unsync {
init: Cell<Option<F>>,
}
- #[cfg(feature = "std")]
impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
@@ -742,6 +737,25 @@ pub mod unsync {
})
}
+ /// Forces the evaluation of this lazy value and returns a mutable reference to
+ /// the result.
+ ///
+ /// This is equivalent to the `DerefMut` impl, but is explicit.
+ ///
+ /// # Example
+ /// ```
+ /// use once_cell::unsync::Lazy;
+ ///
+ /// let mut lazy = Lazy::new(|| 92);
+ ///
+ /// assert_eq!(Lazy::force_mut(&mut lazy), &92);
+ /// assert_eq!(*lazy, 92);
+ /// ```
+ pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
+ Self::force(this);
+ Self::get_mut(this).unwrap_or_else(|| unreachable!())
+ }
+
/// Gets the reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
@@ -758,6 +772,23 @@ pub mod unsync {
pub fn get(this: &Lazy<T, F>) -> Option<&T> {
this.cell.get()
}
+
+ /// Gets the mutable reference to the result of this lazy value if
+ /// it was initialized, otherwise returns `None`.
+ ///
+ /// # Example
+ /// ```
+ /// use once_cell::unsync::Lazy;
+ ///
+ /// let mut lazy = Lazy::new(|| 92);
+ ///
+ /// assert_eq!(Lazy::get_mut(&mut lazy), None);
+ /// assert_eq!(*lazy, 92);
+ /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
+ /// ```
+ pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
+ this.cell.get_mut()
+ }
}
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
@@ -1189,7 +1220,6 @@ pub mod sync {
unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
// auto-derived `Send` impl is OK.
- #[cfg(feature = "std")]
impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
impl<T, F> Lazy<T, F> {
@@ -1232,6 +1262,23 @@ pub mod sync {
})
}
+ /// Forces the evaluation of this lazy value and
+ /// returns a mutable reference to the result. This is equivalent
+ /// to the `Deref` impl, but is explicit.
+ ///
+ /// # Example
+ /// ```
+ /// use once_cell::sync::Lazy;
+ ///
+ /// let mut lazy = Lazy::new(|| 92);
+ ///
+ /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
+ /// ```
+ pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
+ Self::force(this);
+ Self::get_mut(this).unwrap_or_else(|| unreachable!())
+ }
+
/// Gets the reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
@@ -1248,6 +1295,23 @@ pub mod sync {
pub fn get(this: &Lazy<T, F>) -> Option<&T> {
this.cell.get()
}
+
+ /// Gets the reference to the result of this lazy value if
+ /// it was initialized, otherwise returns `None`.
+ ///
+ /// # Example
+ /// ```
+ /// use once_cell::sync::Lazy;
+ ///
+ /// let mut lazy = Lazy::new(|| 92);
+ ///
+ /// assert_eq!(Lazy::get_mut(&mut lazy), None);
+ /// assert_eq!(&*lazy, &92);
+ /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
+ /// ```
+ pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
+ this.cell.get_mut()
+ }
}
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
diff --git a/vendor/once_cell/tests/it.rs b/vendor/once_cell/tests/it.rs
index 476f14bb0..410b93b64 100644
--- a/vendor/once_cell/tests/it.rs
+++ b/vendor/once_cell/tests/it.rs
@@ -138,6 +138,41 @@ mod unsync {
}
#[test]
+ fn lazy_force_mut() {
+ let called = Cell::new(0);
+ let mut x = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+ assert_eq!(called.get(), 0);
+ let v = Lazy::force_mut(&mut x);
+ assert_eq!(called.get(), 1);
+
+ *v /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+ }
+
+ #[test]
+ fn lazy_get_mut() {
+ let called = Cell::new(0);
+ let mut x: Lazy<u32, _> = Lazy::new(|| {
+ called.set(called.get() + 1);
+ 92
+ });
+
+ assert_eq!(called.get(), 0);
+ assert_eq!(*x, 92);
+
+ let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
+ assert_eq!(called.get(), 1);
+
+ *mut_ref /= 2;
+ assert_eq!(*x, 46);
+ assert_eq!(called.get(), 1);
+ }
+
+ #[test]
fn lazy_default() {
static CALLED: AtomicUsize = AtomicUsize::new(0);
diff --git a/vendor/percent-encoding/.cargo-checksum.json b/vendor/percent-encoding/.cargo-checksum.json
index 7576f0fde..e37d79346 100644
--- a/vendor/percent-encoding/.cargo-checksum.json
+++ b/vendor/percent-encoding/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"dd59f4e6c033f011625ede444aa27fc8df4be53297af238b4f76d05144de5878","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","lib.rs":"b9dd3a27fb0f56aebe3c4c411ea768a106a54e480ac08d9023c35bbba0bdcbdc"},"package":"d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"} \ No newline at end of file
+{"files":{"Cargo.toml":"7330cca9fe75c0f7cadf87d42f1af587e57d7f3e90efad7b4476d8d78580e435","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"76e972ac0f4ddb116e86e10100132a783931a596e7b9872eaa31be15cd4d751d","src/lib.rs":"5eafa40dda1d5de9770181b836c37b078f790ccdee4f461d4601fc5bc17716b8"},"package":"478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"} \ No newline at end of file
diff --git a/vendor/percent-encoding/Cargo.toml b/vendor/percent-encoding/Cargo.toml
index b51d1d449..53d0b6307 100644
--- a/vendor/percent-encoding/Cargo.toml
+++ b/vendor/percent-encoding/Cargo.toml
@@ -3,21 +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]
+edition = "2018"
+rust-version = "1.51"
name = "percent-encoding"
-version = "2.1.0"
+version = "2.2.0"
authors = ["The rust-url developers"]
description = "Percent encoding and decoding"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/rust-url/"
-[lib]
-path = "lib.rs"
-test = false
+[features]
+alloc = []
+default = ["alloc"]
diff --git a/vendor/percent-encoding/LICENSE-MIT b/vendor/percent-encoding/LICENSE-MIT
index 24de6b418..51d5dc7eb 100644
--- a/vendor/percent-encoding/LICENSE-MIT
+++ b/vendor/percent-encoding/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2016 The rust-url developers
+Copyright (c) 2013-2022 The rust-url developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/vendor/percent-encoding/lib.rs b/vendor/percent-encoding/src/lib.rs
index 27eaf6740..46a5d747c 100644
--- a/vendor/percent-encoding/lib.rs
+++ b/vendor/percent-encoding/src/lib.rs
@@ -6,7 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! URLs use special chacters to indicate the parts of the request.
+//! URLs use special characters to indicate the parts of the request.
//! For example, a `?` question mark marks the end of a path and the start of a query string.
//! In order for that character to exist inside a path, it needs to be encoded differently.
//!
@@ -21,9 +21,9 @@
//! The [`AsciiSet`] parameter of [`percent_encode`] and [`utf8_percent_encode`]
//! lets callers configure this.
//!
-//! This crate delibarately does not provide many different sets.
+//! This crate deliberately does not provide many different sets.
//! Users should consider in what context the encoded string will be used,
-//! real relevant specifications, and define their own set.
+//! read relevant specifications, and define their own set.
//! This is done by using the `add` method of an existing set.
//!
//! # Examples
@@ -37,15 +37,22 @@
//! assert_eq!(utf8_percent_encode("foo <bar>", FRAGMENT).to_string(), "foo%20%3Cbar%3E");
//! ```
-use std::borrow::Cow;
-use std::fmt;
-use std::slice;
-use std::str;
+#![no_std]
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
+#[cfg(feature = "alloc")]
+use alloc::{
+ borrow::{Cow, ToOwned},
+ string::String,
+ vec::Vec,
+};
+use core::{fmt, mem, slice, str};
/// Represents a set of characters or bytes in the ASCII range.
///
-/// This used in [`percent_encode`] and [`utf8_percent_encode`].
-/// This is simlar to [percent-encode sets](https://url.spec.whatwg.org/#percent-encoded-bytes).
+/// This is used in [`percent_encode`] and [`utf8_percent_encode`].
+/// This is similar to [percent-encode sets](https://url.spec.whatwg.org/#percent-encoded-bytes).
///
/// Use the `add` method of an existing set to define a new set. For example:
///
@@ -63,7 +70,7 @@ type Chunk = u32;
const ASCII_RANGE_LEN: usize = 0x80;
-const BITS_PER_CHUNK: usize = 8 * std::mem::size_of::<Chunk>();
+const BITS_PER_CHUNK: usize = 8 * mem::size_of::<Chunk>();
impl AsciiSet {
/// Called with UTF-8 bytes rather than code points.
@@ -109,7 +116,7 @@ macro_rules! static_assert {
($( $bool: expr, )+) => {
fn _static_assert() {
$(
- let _ = std::mem::transmute::<[u8; $bool as usize], u8>;
+ let _ = mem::transmute::<[u8; $bool as usize], u8>;
)+
}
}
@@ -252,6 +259,8 @@ impl<'a> Iterator for PercentEncode<'a> {
self.bytes = remaining;
Some(percent_encode_byte(first_byte))
} else {
+ // The unsafe blocks here are appropriate because the bytes are
+ // confirmed as a subset of UTF-8 in should_percent_encode.
for (i, &byte) in remaining.iter().enumerate() {
if self.ascii_set.should_percent_encode(byte) {
// 1 for first_byte + i for previous iterations of this loop
@@ -279,7 +288,7 @@ impl<'a> Iterator for PercentEncode<'a> {
}
impl<'a> fmt::Display for PercentEncode<'a> {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
for c in (*self).clone() {
formatter.write_str(c)?
}
@@ -287,6 +296,7 @@ impl<'a> fmt::Display for PercentEncode<'a> {
}
}
+#[cfg(feature = "alloc")]
impl<'a> From<PercentEncode<'a>> for Cow<'a, str> {
fn from(mut iter: PercentEncode<'a>) -> Self {
match iter.next() {
@@ -310,7 +320,7 @@ impl<'a> From<PercentEncode<'a>> for Cow<'a, str> {
///
/// See [`percent_decode`] regarding the return type.
#[inline]
-pub fn percent_decode_str(input: &str) -> PercentDecode {
+pub fn percent_decode_str(input: &str) -> PercentDecode<'_> {
percent_decode(input.as_bytes())
}
@@ -333,7 +343,7 @@ pub fn percent_decode_str(input: &str) -> PercentDecode {
/// assert_eq!(percent_decode(b"foo%20bar%3f").decode_utf8().unwrap(), "foo bar?");
/// ```
#[inline]
-pub fn percent_decode(input: &[u8]) -> PercentDecode {
+pub fn percent_decode(input: &[u8]) -> PercentDecode<'_> {
PercentDecode {
bytes: input.iter(),
}
@@ -345,7 +355,7 @@ pub struct PercentDecode<'a> {
bytes: slice::Iter<'a, u8>,
}
-fn after_percent_sign(iter: &mut slice::Iter<u8>) -> Option<u8> {
+fn after_percent_sign(iter: &mut slice::Iter<'_, u8>) -> Option<u8> {
let mut cloned_iter = iter.clone();
let h = char::from(*cloned_iter.next()?).to_digit(16)?;
let l = char::from(*cloned_iter.next()?).to_digit(16)?;
@@ -368,10 +378,11 @@ impl<'a> Iterator for PercentDecode<'a> {
fn size_hint(&self) -> (usize, Option<usize>) {
let bytes = self.bytes.len();
- (bytes / 3, Some(bytes))
+ ((bytes + 2) / 3, Some(bytes))
}
}
+#[cfg(feature = "alloc")]
impl<'a> From<PercentDecode<'a>> for Cow<'a, [u8]> {
fn from(iter: PercentDecode<'a>) -> Self {
match iter.if_any() {
@@ -383,6 +394,7 @@ impl<'a> From<PercentDecode<'a>> for Cow<'a, [u8]> {
impl<'a> PercentDecode<'a> {
/// If the percent-decoding is different from the input, return it as a new bytes vector.
+ #[cfg(feature = "alloc")]
fn if_any(&self) -> Option<Vec<u8>> {
let mut bytes_iter = self.bytes.clone();
while bytes_iter.any(|&b| b == b'%') {
@@ -402,6 +414,7 @@ impl<'a> PercentDecode<'a> {
/// Decode the result of percent-decoding as UTF-8.
///
/// This is return `Err` when the percent-decoded bytes are not well-formed in UTF-8.
+ #[cfg(feature = "alloc")]
pub fn decode_utf8(self) -> Result<Cow<'a, str>, str::Utf8Error> {
match self.clone().into() {
Cow::Borrowed(bytes) => match str::from_utf8(bytes) {
@@ -419,24 +432,37 @@ impl<'a> PercentDecode<'a> {
///
/// Invalid UTF-8 percent-encoded byte sequences will be replaced � U+FFFD,
/// the replacement character.
+ #[cfg(feature = "alloc")]
pub fn decode_utf8_lossy(self) -> Cow<'a, str> {
decode_utf8_lossy(self.clone().into())
}
}
-fn decode_utf8_lossy(input: Cow<[u8]>) -> Cow<str> {
+#[cfg(feature = "alloc")]
+fn decode_utf8_lossy(input: Cow<'_, [u8]>) -> Cow<'_, str> {
+ // Note: This function is duplicated in `form_urlencoded/src/query_encoding.rs`.
match input {
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
Cow::Owned(bytes) => {
- let raw_utf8: *const [u8];
match String::from_utf8_lossy(&bytes) {
- Cow::Borrowed(utf8) => raw_utf8 = utf8.as_bytes(),
- Cow::Owned(s) => return s.into(),
+ Cow::Borrowed(utf8) => {
+ // If from_utf8_lossy returns a Cow::Borrowed, then we can
+ // be sure our original bytes were valid UTF-8. This is because
+ // if the bytes were invalid UTF-8 from_utf8_lossy would have
+ // to allocate a new owned string to back the Cow so it could
+ // replace invalid bytes with a placeholder.
+
+ // First we do a debug_assert to confirm our description above.
+ let raw_utf8: *const [u8] = utf8.as_bytes();
+ debug_assert!(raw_utf8 == &*bytes as *const [u8]);
+
+ // Given we know the original input bytes are valid UTF-8,
+ // and we have ownership of those bytes, we re-use them and
+ // return a Cow::Owned here.
+ Cow::Owned(unsafe { String::from_utf8_unchecked(bytes) })
+ }
+ Cow::Owned(s) => Cow::Owned(s),
}
- // from_utf8_lossy returned a borrow of `bytes` unchanged.
- debug_assert!(raw_utf8 == &*bytes as *const [u8]);
- // Reuse the existing `Vec` allocation.
- unsafe { String::from_utf8_unchecked(bytes) }.into()
}
}
}
diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json
index 59f2a8483..b20fcaba3 100644
--- a/vendor/proc-macro2/.cargo-checksum.json
+++ b/vendor/proc-macro2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"774906eb037620dba1ef4cf6adc14ec35e7f9f81d1e2d967dfedfab8e7b603d9","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","README.md":"0c17148c1957c3f721d99fc99aedaefee5f2f1ba7e2336a289b02f91609099fb","build.rs":"2c6ddbeeb1700b8dba3689185a535c672dc43e9d61b54f835cf4f3cc163b4afc","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/fallback.rs":"5aab7b73e381dc192256a0c67c99706ae0850159fd9f805fb0c9418fc14b1e00","src/lib.rs":"8bd3da5c9f048acda3799d53eefb7fb2f8b4046612d48f34ec30102b10f4ab08","src/marker.rs":"344a8394f06a1d43355b514920e7e3c0c6dce507be767e3a590bbe3552edd110","src/parse.rs":"34fa3c2e03fa9ab3e63ea57595d1dea4edf0fcfa313a04057e4dd7dc7d7269e0","src/rcvec.rs":"49b6784c6ca5f32573cd8a83758b485d8acbfa126e5fb516ae439e429ef4c144","src/wrapper.rs":"a88d0dff9bb8317071ec205b0c2a79717cd8313041e03ef58e0645be65ab05e8","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"cb6d776eba6a238d726b0f531883adf41957e06f2717ee8a069821c81e7081d6","tests/test.rs":"2fe87d2eab135fb2417cac2876998e9314616fb68981918d7d76333c22b199a0","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0"},"package":"0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"} \ No newline at end of file
+{"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
diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml
index b8b46430d..1bda7e36d 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.43"
+version = "1.0.47"
authors = [
"David Tolnay <dtolnay@gmail.com>",
"Alex Crichton <alex@alexcrichton.com>",
diff --git a/vendor/proc-macro2/build.rs b/vendor/proc-macro2/build.rs
index 38404967d..b69d813f0 100644
--- a/vendor/proc-macro2/build.rs
+++ b/vendor/proc-macro2/build.rs
@@ -111,7 +111,10 @@ fn main() {
println!("cargo:rustc-cfg=wrap_proc_macro");
}
- if version.nightly && feature_allowed("proc_macro_span") {
+ if version.nightly
+ && feature_allowed("proc_macro_span")
+ && feature_allowed("proc_macro_span_shrink")
+ {
println!("cargo:rustc-cfg=proc_macro_span");
}
diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2/src/fallback.rs
index 378ef7e94..fe4f248d3 100644
--- a/vendor/proc-macro2/src/fallback.rs
+++ b/vendor/proc-macro2/src/fallback.rs
@@ -182,7 +182,13 @@ impl FromStr for TokenStream {
fn from_str(src: &str) -> Result<TokenStream, LexError> {
// Create a dummy file & add it to the source map
- let cursor = get_cursor(src);
+ let mut cursor = get_cursor(src);
+
+ // Strip a byte order mark if present
+ const BYTE_ORDER_MARK: &str = "\u{feff}";
+ if cursor.starts_with(BYTE_ORDER_MARK) {
+ cursor = cursor.advance(BYTE_ORDER_MARK.len());
+ }
parse::token_stream(cursor)
}
@@ -512,6 +518,26 @@ impl Span {
})
}
+ #[cfg(procmacro2_semver_exempt)]
+ pub fn before(&self) -> Span {
+ Span {
+ #[cfg(span_locations)]
+ lo: self.lo,
+ #[cfg(span_locations)]
+ hi: self.lo,
+ }
+ }
+
+ #[cfg(procmacro2_semver_exempt)]
+ pub fn after(&self) -> Span {
+ Span {
+ #[cfg(span_locations)]
+ lo: self.hi,
+ #[cfg(span_locations)]
+ hi: self.hi,
+ }
+ }
+
#[cfg(not(span_locations))]
pub fn join(&self, _other: Span) -> Option<Span> {
Some(Span {})
diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs
index be5aa5114..3fda02d5c 100644
--- a/vendor/proc-macro2/src/lib.rs
+++ b/vendor/proc-macro2/src/lib.rs
@@ -86,8 +86,11 @@
//! a different thread.
// Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.43")]
-#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.47")]
+#![cfg_attr(
+ any(proc_macro_span, super_unstable),
+ feature(proc_macro_span, proc_macro_span_shrink)
+)]
#![cfg_attr(super_unstable, feature(proc_macro_def_site))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(
@@ -509,6 +512,24 @@ impl Span {
LineColumn { line, column }
}
+ /// Creates an empty span pointing to directly before this span.
+ ///
+ /// This method is semver exempt and not exposed by default.
+ #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))]
+ #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))]
+ pub fn before(&self) -> Span {
+ Span::_new(self.inner.before())
+ }
+
+ /// Creates an empty span pointing to directly after this span.
+ ///
+ /// This method is semver exempt and not exposed by default.
+ #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))]
+ #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))]
+ pub fn after(&self) -> Span {
+ Span::_new(self.inner.after())
+ }
+
/// Create a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
diff --git a/vendor/proc-macro2/src/parse.rs b/vendor/proc-macro2/src/parse.rs
index 1c9974cfa..307e06508 100644
--- a/vendor/proc-macro2/src/parse.rs
+++ b/vendor/proc-macro2/src/parse.rs
@@ -14,7 +14,7 @@ pub(crate) struct Cursor<'a> {
}
impl<'a> Cursor<'a> {
- fn advance(&self, bytes: usize) -> Cursor<'a> {
+ pub fn advance(&self, bytes: usize) -> Cursor<'a> {
let (_front, rest) = self.rest.split_at(bytes);
Cursor {
rest,
@@ -23,7 +23,7 @@ impl<'a> Cursor<'a> {
}
}
- fn starts_with(&self, s: &str) -> bool {
+ pub fn starts_with(&self, s: &str) -> bool {
self.rest.starts_with(s)
}
@@ -116,9 +116,9 @@ fn block_comment(input: Cursor) -> PResult<&str> {
return Err(Reject);
}
- let mut depth = 0;
+ let mut depth = 0usize;
let bytes = input.as_bytes();
- let mut i = 0;
+ let mut i = 0usize;
let upper = bytes.len() - 1;
while i < upper {
@@ -283,8 +283,9 @@ fn ident_any(input: Cursor) -> PResult<crate::Ident> {
return Ok((rest, ident));
}
- if sym == "_" {
- return Err(Reject);
+ match sym {
+ "_" | "super" | "self" | "Self" | "crate" => return Err(Reject),
+ _ => {}
}
let ident = crate::Ident::_new_raw(sym, crate::Span::call_site());
diff --git a/vendor/proc-macro2/src/wrapper.rs b/vendor/proc-macro2/src/wrapper.rs
index 934440139..47d149473 100644
--- a/vendor/proc-macro2/src/wrapper.rs
+++ b/vendor/proc-macro2/src/wrapper.rs
@@ -505,6 +505,22 @@ impl Span {
}
}
+ #[cfg(super_unstable)]
+ pub fn before(&self) -> Span {
+ match self {
+ Span::Compiler(s) => Span::Compiler(s.before()),
+ Span::Fallback(s) => Span::Fallback(s.before()),
+ }
+ }
+
+ #[cfg(super_unstable)]
+ pub fn after(&self) -> Span {
+ match self {
+ Span::Compiler(s) => Span::Compiler(s.after()),
+ Span::Fallback(s) => Span::Fallback(s.after()),
+ }
+ }
+
pub fn join(&self, other: Span) -> Option<Span> {
let ret = match (self, other) {
#[cfg(proc_macro_span)]
diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2/tests/test.rs
index 16f775ed0..8f5624dbc 100644
--- a/vendor/proc-macro2/tests/test.rs
+++ b/vendor/proc-macro2/tests/test.rs
@@ -630,3 +630,16 @@ fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usi
}
}
}
+
+#[test]
+fn byte_order_mark() {
+ let string = "\u{feff}foo";
+ let tokens = string.parse::<TokenStream>().unwrap();
+ match tokens.into_iter().next().unwrap() {
+ TokenTree::Ident(ident) => assert_eq!(ident, "foo"),
+ _ => unreachable!(),
+ }
+
+ let string = "foo\u{feff}";
+ string.parse::<TokenStream>().unwrap_err();
+}
diff --git a/vendor/rowan/.cargo-checksum.json b/vendor/rowan/.cargo-checksum.json
index f2cbdfc1d..82ca4c645 100644
--- a/vendor/rowan/.cargo-checksum.json
+++ b/vendor/rowan/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"d89194369a60b64062043f52664726c5f114542c20c2fbfaafac9fad682c139b","Cargo.toml":"fbd2ff15249776d6bbc4d3646ed0a7681172aad7c7f7a42b512308b7672b43b4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"69657dd291f7b245820ee01fa7bdbfdc5dc2b47284767641ffb8f94e9f9bc522","examples/math.rs":"e7557914686973cc16c6b2736a9934708465ef996b4f0a54fdb454b524641dc9","examples/s_expressions.rs":"6d963a8c030978e2648a059f2dcd5314d9fef47f0dda45e4134caedae1429eee","src/api.rs":"b5d48c0d401014c09ef9d8ee54c849735b1235e5faa798f7291be3d6a8a335c9","src/arc.rs":"fef1aa58a57d167bf4ba99b186b7e9a9c0df8c6096c2f604fbff86430dbaa6e3","src/ast.rs":"6eeedc3fcfb7b1d3d53aa54fc68a8f3bc6381ba2433e12d82b13f51fb5a82446","src/cow_mut.rs":"c90f47a013ae8cfb00bee089b75bbc2e493424e344fb4aaeff78cb2db8558ec2","src/cursor.rs":"b150f5d016aee8b196f5c02af6e7473b32e62f39fc62242dd7adbfddb21f8b69","src/green.rs":"34d58d497d2af2bbd1533aea6b4aa91496d65275b3b6def8dd6f5b1210ec0ce0","src/green/builder.rs":"517e4f6393f8fe6deaabd288f5e5b6a670dc7deec99e5bd92df34cdb4f02db49","src/green/element.rs":"df199a8b6adefef54398f209e7316525eaf84133e952325d46641b66cb89ada9","src/green/node.rs":"02701fc84ad6fdf44bd2c9b63923b0c919ca77acdb09c40d1d2b949830eab185","src/green/node_cache.rs":"f85ca104edb7d2261fd111a6fa4165f076e802aa9414457bdb028788db8dde9d","src/green/token.rs":"a1440de773044e82686dc9173ca7732a6a415a7ba6272c8bc68b3dd896f0cd7b","src/lib.rs":"e0eb1ba73978636b577094ebb726e2e222f347587928ba3930b196b809f17f86","src/serde_impls.rs":"603a459c1e3ad6edd2915e6ef3d103bae36364e01d781a8521486d618ba7b678","src/sll.rs":"f476ecf40629de8f45f5d952a88ebd91f91c71ac635ddc7cd2eebf5a90ce07bf","src/syntax_text.rs":"e387fa481a53aa9dd220a350acabd150daa8440c07ade49ea8a2f69275c6b366","src/utility_types.rs":"ce0874ae3e2b1eccb77025322c4453ceafef983f5d41b442448fb848259edf06","tests/tidy.rs":"15f655d7022a23cea887c6ac52727811f72c7d6a0fd54cdbb0476521ab4fea7f"},"package":"e88acf7b001007e9e8c989fe7449f6601d909e5dd2c56399fc158977ad6c56e8"} \ No newline at end of file
+{"files":{"Cargo.lock":"c9b42773521ed23cc479fbacab073a4facfff8e75d2142c309503c1d4ad7fab5","Cargo.toml":"30d67cf548adf18e21fe99a8b1fe12ce8d5a78efbd1e470745d6fbab513576aa","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"69657dd291f7b245820ee01fa7bdbfdc5dc2b47284767641ffb8f94e9f9bc522","examples/math.rs":"e7557914686973cc16c6b2736a9934708465ef996b4f0a54fdb454b524641dc9","examples/s_expressions.rs":"6d963a8c030978e2648a059f2dcd5314d9fef47f0dda45e4134caedae1429eee","src/api.rs":"b5d48c0d401014c09ef9d8ee54c849735b1235e5faa798f7291be3d6a8a335c9","src/arc.rs":"fef1aa58a57d167bf4ba99b186b7e9a9c0df8c6096c2f604fbff86430dbaa6e3","src/ast.rs":"6eeedc3fcfb7b1d3d53aa54fc68a8f3bc6381ba2433e12d82b13f51fb5a82446","src/cow_mut.rs":"c90f47a013ae8cfb00bee089b75bbc2e493424e344fb4aaeff78cb2db8558ec2","src/cursor.rs":"025684328fb9138bae300e1dec9a7c016640e583ff3729a7d0a34c17854d74cc","src/green.rs":"34d58d497d2af2bbd1533aea6b4aa91496d65275b3b6def8dd6f5b1210ec0ce0","src/green/builder.rs":"517e4f6393f8fe6deaabd288f5e5b6a670dc7deec99e5bd92df34cdb4f02db49","src/green/element.rs":"df199a8b6adefef54398f209e7316525eaf84133e952325d46641b66cb89ada9","src/green/node.rs":"02701fc84ad6fdf44bd2c9b63923b0c919ca77acdb09c40d1d2b949830eab185","src/green/node_cache.rs":"f85ca104edb7d2261fd111a6fa4165f076e802aa9414457bdb028788db8dde9d","src/green/token.rs":"a1440de773044e82686dc9173ca7732a6a415a7ba6272c8bc68b3dd896f0cd7b","src/lib.rs":"e0eb1ba73978636b577094ebb726e2e222f347587928ba3930b196b809f17f86","src/serde_impls.rs":"603a459c1e3ad6edd2915e6ef3d103bae36364e01d781a8521486d618ba7b678","src/sll.rs":"f476ecf40629de8f45f5d952a88ebd91f91c71ac635ddc7cd2eebf5a90ce07bf","src/syntax_text.rs":"e387fa481a53aa9dd220a350acabd150daa8440c07ade49ea8a2f69275c6b366","src/utility_types.rs":"ce0874ae3e2b1eccb77025322c4453ceafef983f5d41b442448fb848259edf06","tests/tidy.rs":"15f655d7022a23cea887c6ac52727811f72c7d6a0fd54cdbb0476521ab4fea7f"},"package":"5811547e7ba31e903fe48c8ceab10d40d70a101f3d15523c847cce91aa71f332"} \ No newline at end of file
diff --git a/vendor/rowan/Cargo.lock b/vendor/rowan/Cargo.lock
index a53655c96..a492ecc3a 100644
--- a/vendor/rowan/Cargo.lock
+++ b/vendor/rowan/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "aho-corasick"
-version = "0.7.18"
+version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
@@ -72,7 +72,7 @@ checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rowan"
-version = "0.15.8"
+version = "0.15.10"
dependencies = [
"countme",
"hashbrown",
@@ -91,9 +91,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "serde"
-version = "1.0.140"
+version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
+checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
[[package]]
name = "text-size"
diff --git a/vendor/rowan/Cargo.toml b/vendor/rowan/Cargo.toml
index c717f55d0..44c527d42 100644
--- a/vendor/rowan/Cargo.toml
+++ b/vendor/rowan/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2021"
name = "rowan"
-version = "0.15.8"
+version = "0.15.10"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
exclude = [
".github/",
@@ -23,7 +23,6 @@ description = "Library for generic lossless syntax trees"
readme = "README.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-analyzer/rowan"
-resolver = "2"
[dependencies.countme]
version = "3.0.0"
diff --git a/vendor/rowan/src/cursor.rs b/vendor/rowan/src/cursor.rs
index 39b0c9624..671be2348 100644
--- a/vendor/rowan/src/cursor.rs
+++ b/vendor/rowan/src/cursor.rs
@@ -390,7 +390,7 @@ impl NodeData {
}
fn prev_sibling(&self) -> Option<SyntaxNode> {
let mut rev_siblings = self.green_siblings().enumerate().rev();
- let index = rev_siblings.len() - (self.index() as usize);
+ let index = rev_siblings.len().checked_sub(self.index() as usize + 1)?;
rev_siblings.nth(index);
rev_siblings.find_map(|(index, child)| {
diff --git a/vendor/rustc_tools_util/.cargo-checksum.json b/vendor/rustc_tools_util/.cargo-checksum.json
new file mode 100644
index 000000000..fa6b5aa1b
--- /dev/null
+++ b/vendor/rustc_tools_util/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"19638c267dcbea07037fae9353aafa031a81bde979a48d3333d7400cabcb0560","LICENSE-APACHE":"7ce8f5804da3116a112112a3b6ace5f58977fccf878d48dc9b108cc5e26c298c","LICENSE-MIT":"f4acf81886b4abbe3b7938d279536763774b1f061cf25881652300726ada3bda","README.md":"f90d8251e2485a4a0b3ab1b136728e429fbde3b7d6ddb222dc58fd3bae169bd1","src/lib.rs":"d2a621ad6319d586b100f796dd3d2bac9624325df4fead4edf62f6486ac8f26a"},"package":"598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366"} \ No newline at end of file
diff --git a/vendor/rustc_tools_util/Cargo.toml b/vendor/rustc_tools_util/Cargo.toml
new file mode 100644
index 000000000..44a165131
--- /dev/null
+++ b/vendor/rustc_tools_util/Cargo.toml
@@ -0,0 +1,32 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "rustc_tools_util"
+version = "0.2.1"
+description = "small helper to generate version information for git packages"
+readme = "README.md"
+keywords = [
+ "rustc",
+ "tool",
+ "git",
+ "version",
+ "hash",
+]
+categories = ["development-tools"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/rust-clippy"
+
+[dependencies]
+
+[features]
+deny-warnings = []
diff --git a/vendor/xflags/LICENSE-APACHE b/vendor/rustc_tools_util/LICENSE-APACHE
index 16fe87b06..0d62c3727 100644
--- a/vendor/xflags/LICENSE-APACHE
+++ b/vendor/rustc_tools_util/LICENSE-APACHE
@@ -186,7 +186,7 @@ APPENDIX: How to apply the Apache License to your work.
same "printed page" as the copyright notice for easier
identification within third-party archives.
-Copyright [yyyy] [name of copyright owner]
+Copyright 2014-2022 The Rust Project Developers
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/vendor/matches/LICENSE b/vendor/rustc_tools_util/LICENSE-MIT
index a7b759a49..b724b24aa 100644
--- a/vendor/matches/LICENSE
+++ b/vendor/rustc_tools_util/LICENSE-MIT
@@ -1,4 +1,6 @@
-Copyright (c) 2014-2016 Simon Sapin
+MIT License
+
+Copyright (c) 2014-2022 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/vendor/rustc_tools_util/README.md b/vendor/rustc_tools_util/README.md
new file mode 100644
index 000000000..e947f9c7e
--- /dev/null
+++ b/vendor/rustc_tools_util/README.md
@@ -0,0 +1,62 @@
+# rustc_tools_util
+
+A small tool to help you generate version information
+for packages installed from a git repo
+
+## Usage
+
+Add a `build.rs` file to your repo and list it in `Cargo.toml`
+````toml
+build = "build.rs"
+````
+
+List rustc_tools_util as regular AND build dependency.
+````toml
+[dependencies]
+rustc_tools_util = "0.2.1"
+
+[build-dependencies]
+rustc_tools_util = "0.2.1"
+````
+
+In `build.rs`, generate the data in your `main()`
+````rust
+fn main() {
+ println!(
+ "cargo:rustc-env=GIT_HASH={}",
+ rustc_tools_util::get_commit_hash().unwrap_or_default()
+ );
+ println!(
+ "cargo:rustc-env=COMMIT_DATE={}",
+ rustc_tools_util::get_commit_date().unwrap_or_default()
+ );
+ println!(
+ "cargo:rustc-env=RUSTC_RELEASE_CHANNEL={}",
+ rustc_tools_util::get_channel().unwrap_or_default()
+ );
+}
+
+````
+
+Use the version information in your main.rs
+````rust
+use rustc_tools_util::*;
+
+fn show_version() {
+ let version_info = rustc_tools_util::get_version_info!();
+ println!("{}", version_info);
+}
+````
+This gives the following output in clippy:
+`clippy 0.0.212 (a416c5e 2018-12-14)`
+
+
+## License
+
+Copyright 2014-2022 The Rust Project Developers
+
+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. All files in the project carrying such notice may not be
+copied, modified, or distributed except according to those terms.
diff --git a/vendor/rustc_tools_util/src/lib.rs b/vendor/rustc_tools_util/src/lib.rs
new file mode 100644
index 000000000..01d25c531
--- /dev/null
+++ b/vendor/rustc_tools_util/src/lib.rs
@@ -0,0 +1,162 @@
+#![cfg_attr(feature = "deny-warnings", deny(warnings))]
+
+use std::env;
+
+#[macro_export]
+macro_rules! get_version_info {
+ () => {{
+ let major = env!("CARGO_PKG_VERSION_MAJOR").parse::<u8>().unwrap();
+ let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap();
+ let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u16>().unwrap();
+ let crate_name = String::from(env!("CARGO_PKG_NAME"));
+
+ let host_compiler = option_env!("RUSTC_RELEASE_CHANNEL").map(str::to_string);
+ let commit_hash = option_env!("GIT_HASH").map(str::to_string);
+ let commit_date = option_env!("COMMIT_DATE").map(str::to_string);
+
+ VersionInfo {
+ major,
+ minor,
+ patch,
+ host_compiler,
+ commit_hash,
+ commit_date,
+ crate_name,
+ }
+ }};
+}
+
+// some code taken and adapted from RLS and cargo
+pub struct VersionInfo {
+ pub major: u8,
+ pub minor: u8,
+ pub patch: u16,
+ pub host_compiler: Option<String>,
+ pub commit_hash: Option<String>,
+ pub commit_date: Option<String>,
+ pub crate_name: String,
+}
+
+impl std::fmt::Display for VersionInfo {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let hash = self.commit_hash.clone().unwrap_or_default();
+ let hash_trimmed = hash.trim();
+
+ let date = self.commit_date.clone().unwrap_or_default();
+ let date_trimmed = date.trim();
+
+ if (hash_trimmed.len() + date_trimmed.len()) > 0 {
+ write!(
+ f,
+ "{} {}.{}.{} ({hash_trimmed} {date_trimmed})",
+ self.crate_name, self.major, self.minor, self.patch,
+ )?;
+ } else {
+ write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?;
+ }
+
+ Ok(())
+ }
+}
+
+impl std::fmt::Debug for VersionInfo {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(
+ f,
+ "VersionInfo {{ crate_name: \"{}\", major: {}, minor: {}, patch: {}",
+ self.crate_name, self.major, self.minor, self.patch,
+ )?;
+ if self.commit_hash.is_some() {
+ write!(
+ f,
+ ", commit_hash: \"{}\", commit_date: \"{}\" }}",
+ self.commit_hash.clone().unwrap_or_default().trim(),
+ self.commit_date.clone().unwrap_or_default().trim()
+ )?;
+ } else {
+ write!(f, " }}")?;
+ }
+
+ Ok(())
+ }
+}
+
+#[must_use]
+pub fn get_commit_hash() -> Option<String> {
+ std::process::Command::new("git")
+ .args(["rev-parse", "--short", "HEAD"])
+ .output()
+ .ok()
+ .and_then(|r| String::from_utf8(r.stdout).ok())
+}
+
+#[must_use]
+pub fn get_commit_date() -> Option<String> {
+ std::process::Command::new("git")
+ .args(["log", "-1", "--date=short", "--pretty=format:%cd"])
+ .output()
+ .ok()
+ .and_then(|r| String::from_utf8(r.stdout).ok())
+}
+
+#[must_use]
+pub fn get_channel() -> String {
+ match env::var("CFG_RELEASE_CHANNEL") {
+ Ok(channel) => channel,
+ Err(_) => {
+ // if that failed, try to ask rustc -V, do some parsing and find out
+ match std::process::Command::new("rustc")
+ .arg("-V")
+ .output()
+ .ok()
+ .and_then(|r| String::from_utf8(r.stdout).ok())
+ {
+ Some(rustc_output) => {
+ if rustc_output.contains("beta") {
+ String::from("beta")
+ } else if rustc_output.contains("stable") {
+ String::from("stable")
+ } else {
+ // default to nightly if we fail to parse
+ String::from("nightly")
+ }
+ },
+ // default to nightly
+ None => String::from("nightly"),
+ }
+ },
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_struct_local() {
+ let vi = get_version_info!();
+ assert_eq!(vi.major, 0);
+ assert_eq!(vi.minor, 2);
+ assert_eq!(vi.patch, 1);
+ assert_eq!(vi.crate_name, "rustc_tools_util");
+ // hard to make positive tests for these since they will always change
+ assert!(vi.commit_hash.is_none());
+ assert!(vi.commit_date.is_none());
+ }
+
+ #[test]
+ fn test_display_local() {
+ let vi = get_version_info!();
+ assert_eq!(vi.to_string(), "rustc_tools_util 0.2.1");
+ }
+
+ #[test]
+ fn test_debug_local() {
+ let vi = get_version_info!();
+ let s = format!("{vi:?}");
+ assert_eq!(
+ s,
+ "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 1 }"
+ );
+ }
+}
diff --git a/vendor/semver/.cargo-checksum.json b/vendor/semver/.cargo-checksum.json
index f9b5c853b..afd692226 100644
--- a/vendor/semver/.cargo-checksum.json
+++ b/vendor/semver/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"2841cf520fc7e71e16036c48021789cdf36182786556b2a97eb8371193e0c69c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"83e92a83348171f60d768651091803e69e4cb7ea3190cdfc45918d4637f38e1e","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"eedfc19afa205955347175916974cdad121b55cb940e40c61931e5e7629f0e65","src/backport.rs":"f8866548840434c8974f135528693f25aacc4ad03639c4e3aea3be351e13fdf8","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"3bb489f4a29f38d93370e64ae8d6e4e9b451a055cd7d392b6aeacab7eb3e1953","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"601231351ac58602b7d193cb0951b5146bd868b62aba938d5cbe52cf2b93414b","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"f59b217cd6d3e26389562710c540f0f0e1af7184ac5cbf75b2200f7ed7538f1d","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":"93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"} \ No newline at end of file
+{"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
diff --git a/vendor/semver/Cargo.toml b/vendor/semver/Cargo.toml
index e8ad37c7a..68aa0b972 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.13"
+version = "1.0.14"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Parser and evaluator for Cargo's flavor of Semantic Versioning"
documentation = "https://docs.rs/semver"
diff --git a/vendor/semver/src/backport.rs b/vendor/semver/src/backport.rs
index c7751b29f..4b67f56a5 100644
--- a/vendor/semver/src/backport.rs
+++ b/vendor/semver/src/backport.rs
@@ -22,7 +22,9 @@ pub(crate) mod alloc {
pub mod alloc {
use std::mem;
+ use std::process;
+ #[derive(Copy, Clone)]
pub struct Layout {
size: usize,
}
@@ -47,5 +49,12 @@ pub(crate) mod alloc {
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 170a4e05e..fbe1df020 100644
--- a/vendor/semver/src/identifier.rs
+++ b/vendor/semver/src/identifier.rs
@@ -66,7 +66,7 @@
// repr, leaving it available as a niche for downstream code. For example this
// allows size_of::<Version>() == size_of::<Option<Version>>().
-use crate::alloc::alloc::{alloc, dealloc, Layout};
+use crate::alloc::alloc::{alloc, dealloc, handle_alloc_error, Layout};
use core::mem;
use core::num::{NonZeroU64, NonZeroUsize};
use core::ptr::{self, NonNull};
@@ -123,6 +123,9 @@ impl Identifier {
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
// SAFETY: layout's size is nonzero.
let ptr = unsafe { alloc(layout) };
+ if ptr.is_null() {
+ handle_alloc_error(layout);
+ }
let mut write = ptr;
let mut varint_remaining = len;
while varint_remaining > 0 {
@@ -203,6 +206,9 @@ impl Clone for Identifier {
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
// SAFETY: layout's size is nonzero.
let clone = unsafe { alloc(layout) };
+ if clone.is_null() {
+ handle_alloc_error(layout);
+ }
// SAFETY: new allocation cannot overlap the previous one (this was
// not a realloc). The argument ptrs are readable/writeable
// respectively for size bytes.
diff --git a/vendor/semver/src/lib.rs b/vendor/semver/src/lib.rs
index b3c3ea286..ca4d1119c 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.13")]
+#![doc(html_root_url = "https://docs.rs/semver/1.0.14")]
#![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))]
diff --git a/vendor/serde/.cargo-checksum.json b/vendor/serde/.cargo-checksum.json
index 1149006a8..0aefd0d73 100644
--- a/vendor/serde/.cargo-checksum.json
+++ b/vendor/serde/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"a55cd52d7858718ed68b8c1aaac689aa8fb801d9194b904e3df31850c95b71f0","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":"c69d6071191c2075372218442e9e73991335c6b4be18736a7a789f04bb305525","src/de/impls.rs":"b2fea640830a690d09b453fe126034f1f3f77e553b604a7a9ac83b043315248f","src/de/mod.rs":"1ac7de9cfc47d0a8ac104c1809fd81d7febfcd01d74d6abcbf0bf31ec200f625","src/de/seed.rs":"e8cf0233afe0af5b8fb9e4c94f301c92729c5ba417280af9e2201b732e374a72","src/de/utf8.rs":"f17524ee0af98ec3abcfd7d0b812fbd1033263bd8e2ce2f57c1e1999ce153558","src/de/value.rs":"a511298691a1505955eace480afd19bfa2d5abeb06cba3b7bc92af3d0c99968c","src/integer128.rs":"ca49591abde2d8c4f582174533fee28f0fa9139e5d71bf22b25a6b175f8abccc","src/lib.rs":"ef1afaa6c1a4989102b46763c24e13d39573c8619a585ae6e9dc7c5a49efb7d9","src/macros.rs":"3d695a51f0a07f9f719dcb5620012c21a1b084c06a6283349cabf574ceba8123","src/private/de.rs":"ae9fd944944f9c2fb2eb07a622439c7ebdeab5e9d218cdaec9197cb5caa0941c","src/private/doc.rs":"e9801a43c3088fccd5f1fac76416698f948e65b647024aa9da17d673e1e8c217","src/private/mod.rs":"37b204775e572396515477b393ce793b2579de48e5971e6f596ba3723c489fd6","src/private/ser.rs":"3a90dfb5c17e81bf1d959fed60a9477713498e9d0934463627c98709132f066e","src/private/size_hint.rs":"605521227e9ba3100fbb9d5ea7fd5853385097c35015ce6908bd5f1ea20d59ad","src/ser/fmt.rs":"7827ed07fd8897e6324f75625ba0c926a4c4e7ec2914cd067391ce54d942ac7b","src/ser/impls.rs":"8b303e6231ec6d0c0ab8402d348d75229ce91d5e50a065f8209eb7d8a35c4a17","src/ser/impossible.rs":"db17913522c1c27389c5a085113911353b9813c1b116518681362e7c8b692c3a","src/ser/mod.rs":"e5008f26bd6100f52c7223184802e63f4d046651c9db56f68602752cea20745c","src/std_error.rs":"3aac687856c035517fae44ed2906dd4a1e3184bae4bf613adcdeb73f74126c57"},"package":"53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"} \ No newline at end of file
+{"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
diff --git a/vendor/serde/Cargo.toml b/vendor/serde/Cargo.toml
index 7424736c0..a319d423d 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.143"
+version = "1.0.147"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -41,7 +41,6 @@ categories = [
]
license = "MIT OR Apache-2.0"
repository = "https://github.com/serde-rs/serde"
-resolver = "1"
[package.metadata.playground]
features = [
@@ -53,7 +52,7 @@ features = [
targets = ["x86_64-unknown-linux-gnu"]
[dependencies.serde_derive]
-version = "=1.0.143"
+version = "=1.0.147"
optional = true
[dev-dependencies.serde_derive]
diff --git a/vendor/serde/src/de/ignored_any.rs b/vendor/serde/src/de/ignored_any.rs
index 1d50f5ec3..9ed438e79 100644
--- a/vendor/serde/src/de/ignored_any.rs
+++ b/vendor/serde/src/de/ignored_any.rs
@@ -228,7 +228,7 @@ impl<'de> Visitor<'de> for IgnoredAny {
where
A: EnumAccess<'de>,
{
- data.variant::<IgnoredAny>()?.1.newtype_variant()
+ try!(data.variant::<IgnoredAny>()).1.newtype_variant()
}
}
diff --git a/vendor/serde/src/de/impls.rs b/vendor/serde/src/de/impls.rs
index c2a56b4fc..c048f7145 100644
--- a/vendor/serde/src/de/impls.rs
+++ b/vendor/serde/src/de/impls.rs
@@ -2268,14 +2268,14 @@ where
where
D: Deserializer<'de>,
{
- let (start, end) = deserializer.deserialize_struct(
+ let (start, end) = try!(deserializer.deserialize_struct(
"Range",
range::FIELDS,
range::RangeVisitor {
expecting: "struct Range",
phantom: PhantomData,
},
- )?;
+ ));
Ok(start..end)
}
}
@@ -2289,14 +2289,14 @@ where
where
D: Deserializer<'de>,
{
- let (start, end) = deserializer.deserialize_struct(
+ let (start, end) = try!(deserializer.deserialize_struct(
"RangeInclusive",
range::FIELDS,
range::RangeVisitor {
expecting: "struct RangeInclusive",
phantom: PhantomData,
},
- )?;
+ ));
Ok(RangeInclusive::new(start, end))
}
}
diff --git a/vendor/serde/src/de/mod.rs b/vendor/serde/src/de/mod.rs
index e8a47cfc1..d9dafbe1e 100644
--- a/vendor/serde/src/de/mod.rs
+++ b/vendor/serde/src/de/mod.rs
@@ -565,7 +565,7 @@ pub trait Deserialize<'de>: Sized {
D: Deserializer<'de>,
{
// Default implementation just delegates to `deserialize` impl.
- *place = Deserialize::deserialize(deserializer)?;
+ *place = try!(Deserialize::deserialize(deserializer));
Ok(())
}
}
@@ -862,10 +862,10 @@ where
/// The `Deserializer` trait supports two entry point styles which enables
/// different kinds of deserialization.
///
-/// 1. The `deserialize` method. Self-describing data formats like JSON are able
-/// to look at the serialized data and tell what it represents. For example
-/// the JSON deserializer may see an opening curly brace (`{`) and know that
-/// it is seeing a map. If the data format supports
+/// 1. The `deserialize_any` method. Self-describing data formats like JSON are
+/// able to look at the serialized data and tell what it represents. For
+/// example the JSON deserializer may see an opening curly brace (`{`) and
+/// know that it is seeing a map. If the data format supports
/// `Deserializer::deserialize_any`, it will drive the Visitor using whatever
/// type it sees in the input. JSON uses this approach when deserializing
/// `serde_json::Value` which is an enum that can represent any JSON
diff --git a/vendor/serde/src/de/value.rs b/vendor/serde/src/de/value.rs
index e7afdd8d1..5d8886215 100644
--- a/vendor/serde/src/de/value.rs
+++ b/vendor/serde/src/de/value.rs
@@ -1501,7 +1501,7 @@ where
where
T: de::DeserializeSeed<'de>,
{
- match self.map.next_key_seed(seed)? {
+ match try!(self.map.next_key_seed(seed)) {
Some(key) => Ok((key, private::map_as_enum(self.map))),
None => Err(de::Error::invalid_type(de::Unexpected::Map, &"enum")),
}
@@ -1510,6 +1510,41 @@ where
////////////////////////////////////////////////////////////////////////////////
+/// A deserializer holding an `EnumAccess`.
+#[derive(Clone, Debug)]
+pub struct EnumAccessDeserializer<A> {
+ access: A,
+}
+
+impl<A> EnumAccessDeserializer<A> {
+ /// Construct a new `EnumAccessDeserializer<A>`.
+ pub fn new(access: A) -> Self {
+ EnumAccessDeserializer { access: access }
+ }
+}
+
+impl<'de, A> de::Deserializer<'de> for EnumAccessDeserializer<A>
+where
+ A: de::EnumAccess<'de>,
+{
+ type Error = A::Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
+ where
+ V: de::Visitor<'de>,
+ {
+ visitor.visit_enum(self.access)
+ }
+
+ forward_to_deserialize_any! {
+ bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+ bytes byte_buf option unit unit_struct newtype_struct seq tuple
+ tuple_struct map struct enum identifier ignored_any
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
mod private {
use lib::*;
diff --git a/vendor/serde/src/lib.rs b/vendor/serde/src/lib.rs
index f2b28d985..02c57ae9d 100644
--- a/vendor/serde/src/lib.rs
+++ b/vendor/serde/src/lib.rs
@@ -65,7 +65,7 @@
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/mongodb/bson-rust
-//! [Avro]: https://github.com/flavray/avro-rs
+//! [Avro]: https://docs.rs/apache-avro
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
@@ -81,7 +81,7 @@
////////////////////////////////////////////////////////////////////////////////
// Serde types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/serde/1.0.143")]
+#![doc(html_root_url = "https://docs.rs/serde/1.0.147")]
// 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
@@ -249,6 +249,19 @@ mod lib {
pub use self::core::time::Duration;
}
+// None of this crate's error handling needs the `From::from` error conversion
+// performed implicitly by the `?` operator or the standard library's `try!`
+// macro. This simplified macro gives a 5.5% improvement in compile time
+// compared to standard `try!`, and 9% improvement compared to `?`.
+macro_rules! try {
+ ($expr:expr) => {
+ match $expr {
+ Ok(val) => val,
+ Err(err) => return Err(err),
+ }
+ };
+}
+
////////////////////////////////////////////////////////////////////////////////
#[macro_use]
diff --git a/vendor/serde/src/private/de.rs b/vendor/serde/src/private/de.rs
index f0697d64f..01e5bf787 100644
--- a/vendor/serde/src/private/de.rs
+++ b/vendor/serde/src/private/de.rs
@@ -1262,6 +1262,17 @@ mod content {
{
match self.content {
Content::Unit => visitor.visit_unit(),
+
+ // Allow deserializing newtype variant containing unit.
+ //
+ // #[derive(Deserialize)]
+ // #[serde(tag = "result")]
+ // enum Response<T> {
+ // Success(T),
+ // }
+ //
+ // We want {"result":"Success"} to deserialize into Response<()>.
+ Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
_ => Err(self.invalid_type(&visitor)),
}
}
diff --git a/vendor/serde/src/private/ser.rs b/vendor/serde/src/private/ser.rs
index 6ee999389..293d8a865 100644
--- a/vendor/serde/src/private/ser.rs
+++ b/vendor/serde/src/private/ser.rs
@@ -51,7 +51,6 @@ enum Unsupported {
String,
ByteArray,
Optional,
- Unit,
#[cfg(any(feature = "std", feature = "alloc"))]
UnitStruct,
Sequence,
@@ -70,7 +69,6 @@ impl Display for Unsupported {
Unsupported::String => formatter.write_str("a string"),
Unsupported::ByteArray => formatter.write_str("a byte array"),
Unsupported::Optional => formatter.write_str("an optional"),
- Unsupported::Unit => formatter.write_str("unit"),
#[cfg(any(feature = "std", feature = "alloc"))]
Unsupported::UnitStruct => formatter.write_str("unit struct"),
Unsupported::Sequence => formatter.write_str("a sequence"),
@@ -184,7 +182,9 @@ where
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
- Err(self.bad_type(Unsupported::Unit))
+ let mut map = try!(self.delegate.serialize_map(Some(1)));
+ try!(map.serialize_entry(self.tag, self.variant_name));
+ map.end()
}
fn serialize_unit_struct(self, _: &'static str) -> Result<Self::Ok, Self::Error> {
diff --git a/vendor/serde/src/ser/impls.rs b/vendor/serde/src/ser/impls.rs
index 7219f51b7..8e8655582 100644
--- a/vendor/serde/src/ser/impls.rs
+++ b/vendor/serde/src/ser/impls.rs
@@ -522,7 +522,7 @@ where
}
}
-impl<T> Serialize for RefCell<T>
+impl<T: ?Sized> Serialize for RefCell<T>
where
T: Serialize,
{
@@ -538,7 +538,7 @@ where
}
#[cfg(feature = "std")]
-impl<T> Serialize for Mutex<T>
+impl<T: ?Sized> Serialize for Mutex<T>
where
T: Serialize,
{
@@ -554,7 +554,7 @@ where
}
#[cfg(feature = "std")]
-impl<T> Serialize for RwLock<T>
+impl<T: ?Sized> Serialize for RwLock<T>
where
T: Serialize,
{
@@ -614,9 +614,10 @@ impl Serialize for SystemTime {
S: Serializer,
{
use super::SerializeStruct;
- let duration_since_epoch = self
- .duration_since(UNIX_EPOCH)
- .map_err(|_| S::Error::custom("SystemTime must be later than UNIX_EPOCH"))?;
+ let duration_since_epoch = match self.duration_since(UNIX_EPOCH) {
+ Ok(duration_since_epoch) => duration_since_epoch,
+ Err(_) => return Err(S::Error::custom("SystemTime must be later than UNIX_EPOCH")),
+ };
let mut state = try!(serializer.serialize_struct("SystemTime", 2));
try!(state.serialize_field("secs_since_epoch", &duration_since_epoch.as_secs()));
try!(state.serialize_field("nanos_since_epoch", &duration_since_epoch.subsec_nanos()));
@@ -916,7 +917,7 @@ macro_rules! atomic_impl {
S: Serializer,
{
// Matches the atomic ordering used in libcore for the Debug impl
- self.load(Ordering::SeqCst).serialize(serializer)
+ self.load(Ordering::Relaxed).serialize(serializer)
}
}
)*
diff --git a/vendor/serde_derive/.cargo-checksum.json b/vendor/serde_derive/.cargo-checksum.json
index 0b2fde61e..55e1585d8 100644
--- a/vendor/serde_derive/.cargo-checksum.json
+++ b/vendor/serde_derive/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9eb295576509c448841f03d77bb2ea40d587f67ad25aa1cebc3c3e99b2369123","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":"0872481fb836d38af7f9819922a0269b3dbe27ce81a16443b905d44b3a03e349","src/pretend.rs":"4aa53bf6c1350fbcfc8c4997f720cde61a8eb3aab73bb8c101b0f0a74901892b","src/ser.rs":"0d99c841f6c7bc9751ab225fe42d1f8b7fe56e36903efcb4ff10bf6e35c390ba","src/try.rs":"b171b0088c23ebf4bfa07ba457881b41ac5e547d55dd16f737ea988d34badf61"},"package":"d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"} \ No newline at end of file
+{"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
diff --git a/vendor/serde_derive/Cargo.toml b/vendor/serde_derive/Cargo.toml
index be824e985..dc5abf1b4 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.143"
+version = "1.0.147"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
@@ -38,7 +38,6 @@ keywords = [
categories = ["no-std"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/serde-rs/serde"
-resolver = "1"
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
diff --git a/vendor/serde_derive/src/lib.rs b/vendor/serde_derive/src/lib.rs
index edf7c4157..fc8529e40 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.143")]
+#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.147")]
#![allow(unknown_lints, bare_trait_objects)]
// Ignored clippy lints
#![allow(
diff --git a/vendor/serde_json/.cargo-checksum.json b/vendor/serde_json/.cargo-checksum.json
index 8174fa507..69f778237 100644
--- a/vendor/serde_json/.cargo-checksum.json
+++ b/vendor/serde_json/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CONTRIBUTING.md":"f5270cafba66223a7b51ffc0d286075a17bb7cd88762fc80d333d3102629f4d8","Cargo.toml":"0b496503599dc9b1e962e41838c125db7d8811ad6f061ba6a865ed94ef43ffa0","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":"25ae8f37112a5628b2919619d360dfea6d238e9089fe15cb1869fb70d01bf922","src/macros.rs":"c9f23156faec8d5216d72b6a97eebd768efb3f75870a6e2beed824308587b998","src/map.rs":"54e5e8ba63cf12a24f2c0257b1ace12f1935ca6d862e7b657209ee6634bb771f","src/number.rs":"e4e2ad248acbeed5a674f8823251387a2dbc9b3730bde831a88c8c10621e7a38","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":"185539665cf3ab2fb5499a8e8e069ec75afbc2f07a2fbed0f8f9bcffd7ab729b","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":"6b0f60187c0a936dfe57686d334269863495a01446f75e1ed2e1d641861f232b","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":"e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"} \ No newline at end of file
+{"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
diff --git a/vendor/serde_json/Cargo.toml b/vendor/serde_json/Cargo.toml
index a79bb3b1c..1e1aebb8e 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.85"
+version = "1.0.86"
authors = [
"Erick Tryzelaar <erick.tryzelaar@gmail.com>",
"David Tolnay <dtolnay@gmail.com>",
diff --git a/vendor/serde_json/src/lib.rs b/vendor/serde_json/src/lib.rs
index cf4b83d19..3a1983c3f 100644
--- a/vendor/serde_json/src/lib.rs
+++ b/vendor/serde_json/src/lib.rs
@@ -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.85")]
+#![doc(html_root_url = "https://docs.rs/serde_json/1.0.86")]
// Ignored clippy lints
#![allow(
clippy::collapsible_else_if,
diff --git a/vendor/serde_json/src/number.rs b/vendor/serde_json/src/number.rs
index df8819259..3c8f6f1bf 100644
--- a/vendor/serde_json/src/number.rs
+++ b/vendor/serde_json/src/number.rs
@@ -1,20 +1,23 @@
use crate::de::ParserNumber;
use crate::error::Error;
+#[cfg(feature = "arbitrary_precision")]
+use crate::error::ErrorCode;
+#[cfg(feature = "arbitrary_precision")]
+use alloc::borrow::ToOwned;
+#[cfg(feature = "arbitrary_precision")]
+use alloc::string::{String, ToString};
use core::fmt::{self, Debug, Display};
#[cfg(not(feature = "arbitrary_precision"))]
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,
};
#[cfg(feature = "arbitrary_precision")]
-use crate::error::ErrorCode;
-#[cfg(feature = "arbitrary_precision")]
-use serde::de::{IntoDeserializer, MapAccess};
-
-#[cfg(feature = "arbitrary_precision")]
pub(crate) const TOKEN: &str = "$serde_json::private::Number";
/// Represents a JSON number, whether integer or floating point.
diff --git a/vendor/serde_json/src/value/ser.rs b/vendor/serde_json/src/value/ser.rs
index c142dacbf..37e495f65 100644
--- a/vendor/serde_json/src/value/ser.rs
+++ b/vendor/serde_json/src/value/ser.rs
@@ -195,7 +195,7 @@ impl serde::Serializer for Serializer {
T: ?Sized + Serialize,
{
let mut values = Map::new();
- values.insert(String::from(variant), tri!(to_value(&value)));
+ values.insert(String::from(variant), tri!(to_value(value)));
Ok(Value::Object(values))
}
@@ -314,7 +314,7 @@ impl serde::ser::SerializeSeq for SerializeVec {
where
T: ?Sized + Serialize,
{
- self.vec.push(tri!(to_value(&value)));
+ self.vec.push(tri!(to_value(value)));
Ok(())
}
@@ -363,7 +363,7 @@ impl serde::ser::SerializeTupleVariant for SerializeTupleVariant {
where
T: ?Sized + Serialize,
{
- self.vec.push(tri!(to_value(&value)));
+ self.vec.push(tri!(to_value(value)));
Ok(())
}
@@ -406,7 +406,7 @@ impl serde::ser::SerializeMap for SerializeMap {
// Panic because this indicates a bug in the program rather than an
// expected failure.
let key = key.expect("serialize_value called before serialize_key");
- map.insert(key, tri!(to_value(&value)));
+ map.insert(key, tri!(to_value(value)));
Ok(())
}
#[cfg(feature = "arbitrary_precision")]
@@ -663,7 +663,7 @@ impl serde::ser::SerializeStructVariant for SerializeStructVariant {
where
T: ?Sized + Serialize,
{
- self.map.insert(String::from(key), tri!(to_value(&value)));
+ self.map.insert(String::from(key), tri!(to_value(value)));
Ok(())
}
diff --git a/vendor/serde_json/tests/test.rs b/vendor/serde_json/tests/test.rs
index 0aeaff88d..aa5b5caa0 100644
--- a/vendor/serde_json/tests/test.rs
+++ b/vendor/serde_json/tests/test.rs
@@ -95,7 +95,7 @@ where
let s = to_string(value).unwrap();
assert_eq!(s, out);
- let v = to_value(&value).unwrap();
+ let v = to_value(value).unwrap();
let s = to_string(&v).unwrap();
assert_eq!(s, out);
}
@@ -111,7 +111,7 @@ where
let s = to_string_pretty(value).unwrap();
assert_eq!(s, out);
- let v = to_value(&value).unwrap();
+ let v = to_value(value).unwrap();
let s = to_string_pretty(&v).unwrap();
assert_eq!(s, out);
}
@@ -1107,7 +1107,7 @@ fn test_parse_string() {
]);
test_parse_ok(vec![
- ("\"\"", "".to_string()),
+ ("\"\"", String::new()),
("\"foo\"", "foo".to_string()),
(" \"foo\" ", "foo".to_string()),
("\"\\\"\"", "\"".to_string()),
diff --git a/vendor/smallvec/.cargo-checksum.json b/vendor/smallvec/.cargo-checksum.json
index 8f4d7bf91..e9fa9e1e6 100644
--- a/vendor/smallvec/.cargo-checksum.json
+++ b/vendor/smallvec/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"03ae7e6a133c5fd1685687aee67bc841642a4fd0deeb0d4d88b9fe27af37ba9e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"e2a235d68be20996014c00468b369887d2041ce95486625de3cef35b8f2e4acd","scripts/run_miri.sh":"0d0b8c54c73fa9da1217d29ed0984f8328dd9fb61bb5a02db44458c360cdc3c4","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"264a6e6863aeb21cd779588c2add8421ea1a5861a9bb8ef49e9dc529be8d3b20","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"2bcf69dc0597e4e8a59a92566a3dd5c82ec3a1ea563aa006ea0f4a2722cb2d17","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"} \ No newline at end of file
+{"files":{"Cargo.toml":"e8b7e22c87fa34e053c12b3751ec0c7b25b37bd1285959710321a7a00861f392","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9","README.md":"a01127c37308457e8d396b176fb790846be0978c173be3f13260b62efcef011b","benches/bench.rs":"e2a235d68be20996014c00468b369887d2041ce95486625de3cef35b8f2e4acd","debug_metadata/README.md":"dc8fbf896055359a94f7bfdfae7604e0bcfc8b10998a218d484d9fffdf83637c","debug_metadata/smallvec.natvis":"68aed2322bdc13ed6fa2021dc9625346174d73590929acbc2f95c98785c8dee4","scripts/run_miri.sh":"74a9f9adc43f986e81977b03846f7dd00122a0150bd8ec3fe4842a1a787e0f07","src/arbitrary.rs":"22e55cfbf60374945b30e6d0855129eff67cd8b878cef6fa997e1f4be67b9e3d","src/lib.rs":"35c60a9d9240853e9f6f84b7a44ff6a3197a87ab404f5ab1cd8ebeeeb72e54da","src/specialization.rs":"46433586203399251cba496d67b88d34e1be3c2b591986b77463513da1c66471","src/tests.rs":"2bcf69dc0597e4e8a59a92566a3dd5c82ec3a1ea563aa006ea0f4a2722cb2d17","tests/debugger_visualizer.rs":"87480900add8579e1285741d5a0041063b6d888328e11854ab2cdc2960d7ddb1","tests/macro.rs":"22ad4f6f104a599fdcba19cad8834105b8656b212fb6c7573a427d447f5db14f"},"package":"a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"} \ No newline at end of file
diff --git a/vendor/smallvec/Cargo.toml b/vendor/smallvec/Cargo.toml
index fd490da15..a365ca18e 100644
--- a/vendor/smallvec/Cargo.toml
+++ b/vendor/smallvec/Cargo.toml
@@ -12,18 +12,35 @@
[package]
edition = "2018"
name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
authors = ["The Servo Project Developers"]
description = "'Small vector' optimization: store up to a small number of items on the stack"
documentation = "https://docs.rs/smallvec/"
readme = "README.md"
-keywords = ["small", "vec", "vector", "stack", "no_std"]
+keywords = [
+ "small",
+ "vec",
+ "vector",
+ "stack",
+ "no_std",
+]
categories = ["data-structures"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/rust-smallvec"
+
[package.metadata.docs.rs]
all-features = true
-rustdoc-args = ["--cfg", "docsrs"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+
+[[test]]
+name = "debugger_visualizer"
+path = "tests/debugger_visualizer.rs"
+test = false
+required-features = ["debugger_visualizer"]
+
[dependencies.arbitrary]
version = "1"
optional = true
@@ -32,12 +49,20 @@ optional = true
version = "1"
optional = true
default-features = false
+
[dev-dependencies.bincode]
version = "1.0.1"
+[dev-dependencies.debugger_test]
+version = "0.1.0"
+
+[dev-dependencies.debugger_test_parser]
+version = "0.1.0"
+
[features]
const_generics = []
const_new = ["const_generics"]
+debugger_visualizer = []
may_dangle = []
specialization = []
union = []
diff --git a/vendor/smallvec/debug_metadata/README.md b/vendor/smallvec/debug_metadata/README.md
new file mode 100644
index 000000000..137500813
--- /dev/null
+++ b/vendor/smallvec/debug_metadata/README.md
@@ -0,0 +1,111 @@
+## Debugger Visualizers
+
+Many languages and debuggers enable developers to control how a type is
+displayed in a debugger. These are called "debugger visualizations" or "debugger
+views".
+
+The Windows debuggers (WinDbg\CDB) support defining custom debugger visualizations using
+the `Natvis` framework. To use Natvis, developers write XML documents using the natvis
+schema that describe how debugger types should be displayed with the `.natvis` extension.
+(See: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019)
+The Natvis files provide patterns which match type names a description of how to display
+those types.
+
+The Natvis schema can be found either online (See: https://code.visualstudio.com/docs/cpp/natvis#_schema)
+or locally at `<VS Installation Folder>\Xml\Schemas\1033\natvis.xsd`.
+
+The GNU debugger (GDB) supports defining custom debugger views using Pretty Printers.
+Pretty printers are written as python scripts that describe how a type should be displayed
+when loaded up in GDB/LLDB. (See: https://sourceware.org/gdb/onlinedocs/gdb/Pretty-Printing.html#Pretty-Printing)
+The pretty printers provide patterns, which match type names, and for matching
+types, descibe how to display those types. (For writing a pretty printer, see: https://sourceware.org/gdb/onlinedocs/gdb/Writing-a-Pretty_002dPrinter.html#Writing-a-Pretty_002dPrinter).
+
+### Embedding Visualizers
+
+Through the use of the currently unstable `#[debugger_visualizer]` attribute, the `smallvec`
+crate can embed debugger visualizers into the crate metadata.
+
+Currently the two types of visualizers supported are Natvis and Pretty printers.
+
+For Natvis files, when linking an executable with a crate that includes Natvis files,
+the MSVC linker will embed the contents of all Natvis files into the generated `PDB`.
+
+For pretty printers, the compiler will encode the contents of the pretty printer
+in the `.debug_gdb_scripts` section of the `ELF` generated.
+
+### Testing Visualizers
+
+The `smallvec` crate supports testing debugger visualizers defined for this crate. The entry point for
+these tests are `tests/debugger_visualizer.rs`. These tests are defined using the `debugger_test` and
+`debugger_test_parser` crates. The `debugger_test` crate is a proc macro crate which defines a
+single proc macro attribute, `#[debugger_test]`. For more detailed information about this crate,
+see https://crates.io/crates/debugger_test. The CI pipeline for the `smallvec` crate has been updated
+to run the debugger visualizer tests to ensure debugger visualizers do not become broken/stale.
+
+The `#[debugger_test]` proc macro attribute may only be used on test functions and will run the
+function under the debugger specified by the `debugger` meta item.
+
+This proc macro attribute has 3 required values:
+
+1. The first required meta item, `debugger`, takes a string value which specifies the debugger to launch.
+2. The second required meta item, `commands`, takes a string of new line (`\n`) separated list of debugger
+commands to run.
+3. The third required meta item, `expected_statements`, takes a string of new line (`\n`) separated list of
+statements that must exist in the debugger output. Pattern matching through regular expressions is also
+supported by using the `pattern:` prefix for each expected statement.
+
+#### Example:
+
+```rust
+#[debugger_test(
+ debugger = "cdb",
+ commands = "command1\ncommand2\ncommand3",
+ expected_statements = "statement1\nstatement2\nstatement3")]
+fn test() {
+
+}
+```
+
+Using a multiline string is also supported, with a single debugger command/expected statement per line:
+
+```rust
+#[debugger_test(
+ debugger = "cdb",
+ commands = "
+command1
+command2
+command3",
+ expected_statements = "
+statement1
+pattern:statement[0-9]+
+statement3")]
+fn test() {
+
+}
+```
+
+In the example above, the second expected statement uses pattern matching through a regular expression
+by using the `pattern:` prefix.
+
+#### Testing Locally
+
+Currently, only Natvis visualizations have been defined for the `smallvec` crate via `debug_metadata/smallvec.natvis`,
+which means the `tests/debugger_visualizer.rs` tests need to be run on Windows using the `*-pc-windows-msvc` targets.
+To run these tests locally, first ensure the debugging tools for Windows are installed or install them following
+the steps listed here, [Debugging Tools for Windows](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/).
+Once the debugging tools have been installed, the tests can be run in the same manner as they are in the CI
+pipeline.
+
+#### Note
+
+When running the debugger visualizer tests, `tests/debugger_visualizer.rs`, they need to be run consecutively
+and not in parallel. This can be achieved by passing the flag `--test-threads=1` to rustc. This is due to
+how the debugger tests are run. Each test marked with the `#[debugger_test]` attribute launches a debugger
+and attaches it to the current test process. If tests are running in parallel, the test will try to attach
+a debugger to the current process which may already have a debugger attached causing the test to fail.
+
+For example:
+
+```
+cargo test --test debugger_visualizer --features debugger_visualizer -- --test-threads=1
+```
diff --git a/vendor/smallvec/debug_metadata/smallvec.natvis b/vendor/smallvec/debug_metadata/smallvec.natvis
new file mode 100644
index 000000000..b38d47cb7
--- /dev/null
+++ b/vendor/smallvec/debug_metadata/smallvec.natvis
@@ -0,0 +1,35 @@
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+ <Type Name="smallvec::SmallVec&lt;array$&lt;*,*&gt;&gt;" Priority="Medium">
+ <Intrinsic Name="is_inline" Expression="$T2 &gt; capacity" />
+ <Intrinsic Name="len" Expression="is_inline() ? capacity : data.variant1.value.__0.__1" />
+ <Intrinsic Name="data_ptr" Expression="is_inline() ? data.variant0.value.__0.value.value : data.variant1.value.__0.__0" />
+
+ <DisplayString>{{ len={len()} }}</DisplayString>
+ <Expand>
+ <Item Name="[capacity]">is_inline() ? $T2 : capacity</Item>
+ <Item Name="[len]">len()</Item>
+
+ <ArrayItems>
+ <Size>len()</Size>
+ <ValuePointer>data_ptr()</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="smallvec::SmallVec&lt;array$&lt;*,*&gt;&gt;" Priority="MediumLow">
+ <Intrinsic Name="is_inline" Expression="$T2 &gt; capacity" />
+ <Intrinsic Name="len" Expression="is_inline() ? capacity : data.heap.__1" />
+ <Intrinsic Name="data_ptr" Expression="is_inline() ? data.inline.value.value.value : data.heap.__0" />
+
+ <DisplayString>{{ len={len()} }}</DisplayString>
+ <Expand>
+ <Item Name="[capacity]">is_inline() ? $T2 : capacity</Item>
+ <Item Name="[len]">len()</Item>
+
+ <ArrayItems>
+ <Size>len()</Size>
+ <ValuePointer>data_ptr()</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+</AutoVisualizer> \ No newline at end of file
diff --git a/vendor/smallvec/scripts/run_miri.sh b/vendor/smallvec/scripts/run_miri.sh
index 817928a09..010ceb06e 100644
--- a/vendor/smallvec/scripts/run_miri.sh
+++ b/vendor/smallvec/scripts/run_miri.sh
@@ -11,6 +11,7 @@ cargo clean
MIRI_NIGHTLY=nightly-$(curl -s https://rust-lang.github.io/rustup-components-history/x86_64-unknown-linux-gnu/miri)
echo "Installing latest nightly with Miri: $MIRI_NIGHTLY"
+rustup override unset
rustup default "$MIRI_NIGHTLY"
rustup component add miri
@@ -19,3 +20,5 @@ cargo miri setup
cargo miri test --verbose
cargo miri test --verbose --features union
cargo miri test --verbose --all-features
+
+rustup override set nightly
diff --git a/vendor/smallvec/src/lib.rs b/vendor/smallvec/src/lib.rs
index 921347af8..a335ca46c 100644
--- a/vendor/smallvec/src/lib.rs
+++ b/vendor/smallvec/src/lib.rs
@@ -81,6 +81,11 @@
#![cfg_attr(feature = "specialization", allow(incomplete_features))]
#![cfg_attr(feature = "specialization", feature(specialization))]
#![cfg_attr(feature = "may_dangle", feature(dropck_eyepatch))]
+#![cfg_attr(
+ feature = "debugger_visualizer",
+ feature(debugger_visualizer),
+ debugger_visualizer(natvis_file = "../debug_metadata/smallvec.natvis")
+)]
#![deny(missing_docs)]
#[doc(hidden)]
@@ -2084,6 +2089,7 @@ impl<T, const N: usize> SmallVec<[T; N]> {
#[cfg_attr(docsrs, doc(cfg(feature = "const_generics")))]
unsafe impl<T, const N: usize> Array for [T; N] {
type Item = T;
+ #[inline]
fn size() -> usize {
N
}
@@ -2095,6 +2101,7 @@ macro_rules! impl_array(
$(
unsafe impl<T> Array for [T; $size] {
type Item = T;
+ #[inline]
fn size() -> usize { $size }
}
)+
diff --git a/vendor/smallvec/tests/debugger_visualizer.rs b/vendor/smallvec/tests/debugger_visualizer.rs
new file mode 100644
index 000000000..210f539b6
--- /dev/null
+++ b/vendor/smallvec/tests/debugger_visualizer.rs
@@ -0,0 +1,68 @@
+use debugger_test::debugger_test;
+use smallvec::{smallvec, SmallVec};
+
+#[inline(never)]
+fn __break() {}
+
+#[debugger_test(
+ debugger = "cdb",
+ commands = r#"
+.nvlist
+dx sv
+
+g
+
+dx sv
+
+g
+
+dx sv
+"#,
+ expected_statements = r#"
+sv : { len=0x2 } [Type: smallvec::SmallVec<array$<i32,4> >]
+ [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >]
+ [capacity] : 4
+ [len] : 0x2 [Type: unsigned __int64]
+ [0] : 1 [Type: int]
+ [1] : 2 [Type: int]
+
+sv : { len=0x5 } [Type: smallvec::SmallVec<array$<i32,4> >]
+ [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >]
+ [capacity] : 0x8 [Type: unsigned __int64]
+ [len] : 0x5 [Type: unsigned __int64]
+ [0] : 5 [Type: int]
+ [1] : 2 [Type: int]
+ [2] : 3 [Type: int]
+ [3] : 4 [Type: int]
+ [4] : 5 [Type: int]
+
+sv : { len=0x5 } [Type: smallvec::SmallVec<array$<i32,4> >]
+ [<Raw View>] [Type: smallvec::SmallVec<array$<i32,4> >]
+ [capacity] : 0x8 [Type: unsigned __int64]
+ [len] : 0x5 [Type: unsigned __int64]
+ [0] : 2 [Type: int]
+ [1] : 3 [Type: int]
+ [2] : 4 [Type: int]
+ [3] : 5 [Type: int]
+ [4] : 5 [Type: int]
+"#
+)]
+#[inline(never)]
+fn test_debugger_visualizer() {
+ // This SmallVec can hold up to 4 items on the stack:
+ let mut sv: SmallVec<[i32; 4]> = smallvec![1, 2];
+ __break();
+
+ // Overfill the SmallVec to move its contents to the heap
+ for i in 3..6 {
+ sv.push(i);
+ }
+
+ // Update the contents of the first value of the SmallVec.
+ sv[0] = sv[1] + sv[2];
+ __break();
+
+ // Sort the SmallVec in place.
+ sv.sort();
+ __break();
+}
diff --git a/vendor/syn/.cargo-checksum.json b/vendor/syn/.cargo-checksum.json
index 691cc4e06..8b90dae0f 100644
--- a/vendor/syn/.cargo-checksum.json
+++ b/vendor/syn/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"598185e9190166e7f3217ced440d8b3e555ae2a6a84b51ee5ea0a5c7f55bdd0b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"b1546652aefba564455c1ebbf0f276450d4fdb19755e08bfa03c13c8bab241fc","benches/file.rs":"39e124e8ebb7f7171af29e87debbcaeb87c1eb465ef1436cfd8f218b340ef580","benches/rust.rs":"22dfbffc39f8d091ef74cca849e7e7c69e9a47f2a06f7dec91c0382401055c14","build.rs":"b815649fd2929d3debd93a58f5da2fb8eba506047a6a5ba538347305828a87b0","src/attr.rs":"234d9cebe2c5e92cd0f5e1117bf5755037e2e905788a337000a65d4bd82b63aa","src/await.rs":"8aa22e3c201cb2bdb6b4817fa00901f308ab06817607aa7b884c58c957705969","src/bigint.rs":"efc7f64959980653d73fe4f8bc2a3a2904dc05f45b02c6dc15cd316fa3d7c338","src/buffer.rs":"bd5762429e5eb3c899167e820620e7e2a66b4573c48e17326ed12d7461962536","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":"0d441100457567b7b18372fdcbbe833d7516b5a43f17f1cfc4d7f354141b8206","src/ext.rs":"1f648cff1d705a1cea64b32b77482b97a82d2fe0aaf63b40cade91e5c02dc969","src/file.rs":"f86697655222ae294215114f4eae8e6b0b5e2a935d6c479ff8f8f889c4efd2e2","src/gen/clone.rs":"c43199af10b9963476a1ef6b9e0540363a8383c611f8999463235a0939817da8","src/gen/debug.rs":"12e07500a09d1d15b7a148d9155af357c7ac9b65ac100906cf0fac604403274e","src/gen/eq.rs":"e0928a9f4e81a7ede04853d1837abccaf29dd4ffb56d864fad2f4c3a4c76f1b4","src/gen/fold.rs":"43b34e7a951c180b65c6dd97c380f067ea91776f52e70f61555bd8a4120170b1","src/gen/hash.rs":"b66425846386e2168990b3bee2461f5c01695acd8c4b6360619a07108b260f3d","src/gen/visit.rs":"d559f661ab4a4c5b058af91ef244f30f906b6be82d1dd61bf0d058236f8c6a35","src/gen/visit_mut.rs":"fe384074919cdb1a6f54b93f8a9c768da7d3751e5bbfaf8c6c7133a7ebd390ae","src/gen_helper.rs":"ea6c66388365971db6a2fc86cbb208f7eacde77e245bc8623f27a3642a3d7741","src/generics.rs":"46ed41bf116448822ddfefcb62e803fd33264ca8ba672efc0612674d85b6dd11","src/group.rs":"166f0fbb365471ffa3e4f554b72c2b460cbf7e3a1f9bec6c01ef6bbbcd751041","src/ident.rs":"2443e43561abea7eea577b141422258237a663499c839923d8a5ca6fea2470db","src/item.rs":"2745d8bc068f821fc7dc8f480aceac1d10adc578a0b8b7317eb78f5c9048c68c","src/lib.rs":"143cbfa606d88ed75d3f80a27ca582c4b5285e2e60b78991bec02393ffebf334","src/lifetime.rs":"b18862ef1e690037a4f308ea897debad7bc5038584e3b26c6d8809752ea0e3c2","src/lit.rs":"9134ff103d943cfabdbfae56e78881680f91f9902172b890884a05c58131602a","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":"88929a1a7e5e72aa2d0b3459e52d8975afea856d159047ba4ab02ecbc5878a9c","src/parse_quote.rs":"d7d996f1382c68b5fbfd4b7327ce1d389cd43c3bb3c4f382a35994d0bb79d8ab","src/pat.rs":"1e0223ca92c160e07b17a593bb93dd5d451fc9b7014012b403377a4f0f21bfce","src/path.rs":"1ad8b8335628f67a013b7ce2f662aa2feab4583ff67bc959a9dea1dcb51be8a3","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":"8115bc96090022baad91660d7e5e986664c3f1fbd2f112d1c5d1d77e5c3f227e","src/thread.rs":"815eca6bd64f4eef7c447f0809e84108f5428ff50225224b373efd8fbb696874","src/token.rs":"5e423a696f80e281c322f37c87577f9fdc28607e9c007e24896a2b12da62d5ad","src/tt.rs":"32402645b6e82ef1e882945721b59b5fb7b0ee337d1972876362ecacef643d0f","src/ty.rs":"5c05b000d4884334bed729c3345732fbbb4136a75df9dd5002c493ebb6cd091b","src/verbatim.rs":"802a97df997432f18cac6e6200ff6ea29fb2474986005e0fcdbc2b65197f87f7","src/whitespace.rs":"e63dd0aa3d34029f17766a8b09c1a6e4479e36c552c8b7023d710a399333aace","tests/.gitignore":"22e782449a3c216db3f7215d5fb8882e316768e40beeec3833aae419ad8941db","tests/common/eq.rs":"529ae94214c0666045a4c16d9beab6c71eedb40e100be8f990674d44480b5ba6","tests/common/mod.rs":"432ad35577f836a20b517d8c26ed994ac25fe73ef2f461c67688b61b99762015","tests/common/parse.rs":"81580f23583723f7a2a337c4d13ebc021057cd825562fb4e474caa7cc641fed9","tests/debug/gen.rs":"4937074a11fe8266431d05177435bad28340763d408d0a4c45bd0c0acc90a86a","tests/debug/mod.rs":"3a6bb799f478101f71c84c6f1a854a58afe2f9db43c39017909346ca20262d94","tests/macros/mod.rs":"aff805b35cfd55aef6a1359ff747e4023afcb08d69d86aff4c19465d29dda088","tests/regression.rs":"f962ebf24007f631f7e702e34e142d07581da7c9a36321ac142cafed1a0afc69","tests/regression/issue1108.rs":"f32db35244a674e22ff824ca9e5bbec2184e287b59f022db68c418b5878a2edc","tests/repo/mod.rs":"947b678f50df8716ef5c946885a3096e91ab2ec4ce2251cea83d6e6d2ab82eb5","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":"2f449a2c41a3dee6fd14bee24e1666a453cb808eda17332fd91afd127fcdd2a6","tests/test_pat.rs":"d4465f4fc3fd5d6e534ba8efabe1e0ed6da89de4ac7c96effa6bfb880c4287cf","tests/test_path.rs":"71092a5ae2c9143b92a8fe15a92d39958b3c28bd4d4275cfb2d22cbdd53ada07","tests/test_precedence.rs":"1069d979cec0e6c650bebb58be272d23080ce89e83d194dfa2718d22912e481d","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":"1aa0dd489bd844a4a9cf32a5310abd66dad1dae3ffb24fe1288b62a26bfdd8dc","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":"58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"} \ No newline at end of file
+{"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
diff --git a/vendor/syn/Cargo.toml b/vendor/syn/Cargo.toml
index d03ee2e31..7b1412593 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.99"
+version = "1.0.102"
authors = ["David Tolnay <dtolnay@gmail.com>"]
include = [
"/benches/**",
@@ -72,7 +72,7 @@ required-features = [
]
[dependencies.proc-macro2]
-version = "1.0.39"
+version = "1.0.46"
default-features = false
[dependencies.quote]
diff --git a/vendor/syn/benches/file.rs b/vendor/syn/benches/file.rs
index c500dc24a..bd4a247df 100644
--- a/vendor/syn/benches/file.rs
+++ b/vendor/syn/benches/file.rs
@@ -1,4 +1,4 @@
-// $ cargo bench --features full --bench file
+// $ cargo bench --features full,test --bench file
#![feature(rustc_private, test)]
#![recursion_limit = "1024"]
diff --git a/vendor/syn/benches/rust.rs b/vendor/syn/benches/rust.rs
index 5e4fba182..e3f8f550a 100644
--- a/vendor/syn/benches/rust.rs
+++ b/vendor/syn/benches/rust.rs
@@ -1,7 +1,7 @@
-// $ cargo bench --features full --bench rust
+// $ cargo bench --features full,test --bench rust
//
// Syn only, useful for profiling:
-// $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust
+// $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full,test --bench rust
#![cfg_attr(not(syn_only), feature(rustc_private))]
#![recursion_limit = "1024"]
@@ -46,7 +46,7 @@ mod librustc_parse {
use rustc_data_structures::sync::Lrc;
use rustc_error_messages::FluentBundle;
- use rustc_errors::{emitter::Emitter, Diagnostic, Handler};
+ use rustc_errors::{emitter::Emitter, translation::Translate, Diagnostic, Handler};
use rustc_session::parse::ParseSess;
use rustc_span::source_map::{FilePathMapping, SourceMap};
use rustc_span::{edition::Edition, FileName};
@@ -59,6 +59,9 @@ mod librustc_parse {
fn source_map(&self) -> Option<&Lrc<SourceMap>> {
None
}
+ }
+
+ impl Translate for SilentEmitter {
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
None
}
@@ -88,7 +91,7 @@ mod librustc_parse {
#[cfg(not(syn_only))]
mod read_from_disk {
pub fn bench(content: &str) -> Result<(), ()> {
- let _ = content;
+ _ = content;
Ok(())
}
}
diff --git a/vendor/syn/src/buffer.rs b/vendor/syn/src/buffer.rs
index 2c8e21bdb..161b614c8 100644
--- a/vendor/syn/src/buffer.rs
+++ b/vendor/syn/src/buffer.rs
@@ -14,23 +14,18 @@
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
-use std::hint;
use std::marker::PhantomData;
-use std::mem;
-use std::ptr;
-use std::slice;
/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
// Mimicking types from proc-macro.
- Group(Group, TokenBuffer),
+ // Group entries contain the offset to the matching End entry.
+ Group(Group, usize),
Ident(Ident),
Punct(Punct),
Literal(Literal),
- // End entries contain a raw pointer to the entry from the containing
- // token tree, or null if this is the outermost level.
- End(*const Entry),
+ End,
}
/// A buffer that can be efficiently traversed multiple times, unlike
@@ -39,102 +34,29 @@ enum Entry {
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
- // NOTE: Do not implement clone on this - there are raw pointers inside
- // these entries which will be messed up. Moving the `TokenBuffer` itself is
- // safe as the data pointed to won't be moved.
- ptr: *const Entry,
- len: usize,
-}
-
-impl Drop for TokenBuffer {
- fn drop(&mut self) {
- unsafe {
- let slice = slice::from_raw_parts_mut(self.ptr as *mut Entry, self.len);
- let _ = Box::from_raw(slice);
- }
- }
+ // NOTE: Do not implement clone on this - while the current design could be
+ // cloned, other designs which could be desirable may not be cloneable.
+ entries: Box<[Entry]>,
}
impl TokenBuffer {
- // NOTE: Do not mutate the Vec returned from this function once it returns;
- // the address of its backing memory must remain stable.
- fn inner_new(stream: TokenStream, up: *const Entry) -> TokenBuffer {
- let iterator = stream.into_iter();
- let mut entries = Vec::with_capacity(iterator.size_hint().0 + 1);
- let mut next_index_after_last_group = 0;
- for tt in iterator {
+ fn recursive_new(entries: &mut Vec<Entry>, stream: TokenStream) {
+ for tt in stream {
match tt {
- TokenTree::Ident(ident) => {
- entries.push(Entry::Ident(ident));
- }
- TokenTree::Punct(punct) => {
- entries.push(Entry::Punct(punct));
- }
- TokenTree::Literal(literal) => {
- entries.push(Entry::Literal(literal));
- }
+ TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
+ TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
+ TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
TokenTree::Group(group) => {
- // We cannot fill in a real `End` pointer until `entries` is
- // finished growing and getting potentially reallocated.
- // Instead, we temporarily coopt the spot where the end
- // pointer would go, and use it to string together an
- // intrusive linked list of all the Entry::Group entries in
- // the vector. Later after `entries` is done growing, we'll
- // traverse the linked list and fill in all the end
- // pointers with a correct value.
- let group_up =
- ptr::null::<u8>().wrapping_add(next_index_after_last_group) as *const Entry;
-
- let inner = Self::inner_new(group.stream(), group_up);
- entries.push(Entry::Group(group, inner));
- next_index_after_last_group = entries.len();
+ let group_start_index = entries.len();
+ entries.push(Entry::End); // we replace this below
+ Self::recursive_new(entries, group.stream());
+ let group_end_index = entries.len();
+ entries.push(Entry::End);
+ let group_end_offset = group_end_index - group_start_index;
+ entries[group_start_index] = Entry::Group(group, group_end_offset);
}
}
}
-
- // Add an `End` entry to the end with a reference to the enclosing token
- // stream which was passed in.
- entries.push(Entry::End(up));
-
- // NOTE: This is done to ensure that we don't accidentally modify the
- // length of the backing buffer. The backing buffer must remain at a
- // constant address after this point, as we are going to store a raw
- // pointer into it.
- let entries = entries.into_boxed_slice();
- let len = entries.len();
-
- // Convert boxed slice into a pointer to the first element early, to
- // avoid invalidating pointers into this slice when we move the Box.
- // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
- let entries = Box::into_raw(entries) as *mut Entry;
-
- // Traverse intrusive linked list of Entry::Group entries and fill in
- // correct End pointers.
- while let Some(idx) = next_index_after_last_group.checked_sub(1) {
- // We know that idx refers to one of the Entry::Group entries, and
- // that the very last entry is an Entry::End, so the next index
- // after any group entry is a valid index.
- let group_up = unsafe { entries.add(next_index_after_last_group) };
-
- // Linked list only takes us to entries which are of type Group.
- let token_buffer = match unsafe { &*entries.add(idx) } {
- Entry::Group(_group, token_buffer) => token_buffer,
- _ => unsafe { hint::unreachable_unchecked() },
- };
-
- // Last entry in any TokenBuffer is of type End.
- let buffer_ptr = token_buffer.ptr as *mut Entry;
- let last_entry = unsafe { &mut *buffer_ptr.add(token_buffer.len - 1) };
- let end_ptr_slot = match last_entry {
- Entry::End(end_ptr_slot) => end_ptr_slot,
- _ => unsafe { hint::unreachable_unchecked() },
- };
-
- // Step to next element in linked list.
- next_index_after_last_group = mem::replace(end_ptr_slot, group_up) as usize;
- }
-
- TokenBuffer { ptr: entries, len }
}
/// Creates a `TokenBuffer` containing all the tokens from the input
@@ -153,13 +75,19 @@ impl TokenBuffer {
/// Creates a `TokenBuffer` containing all the tokens from the input
/// `proc_macro2::TokenStream`.
pub fn new2(stream: TokenStream) -> Self {
- Self::inner_new(stream, ptr::null())
+ let mut entries = Vec::new();
+ Self::recursive_new(&mut entries, stream);
+ entries.push(Entry::End);
+ Self {
+ entries: entries.into_boxed_slice(),
+ }
}
/// 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 {
- unsafe { Cursor::create(self.ptr, self.ptr.add(self.len - 1)) }
+ let ptr = self.entries.as_ptr();
+ unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
}
}
@@ -179,7 +107,7 @@ impl TokenBuffer {
pub struct Cursor<'a> {
// The current entry which the `Cursor` is pointing at.
ptr: *const Entry,
- // This is the only `Entry::End(..)` object which this cursor is allowed to
+ // This is the only `Entry::End` object which this cursor is allowed to
// point at. All other `End` objects are skipped over in `Cursor::create`.
scope: *const Entry,
// Cursor is covariant in 'a. This field ensures that our pointers are still
@@ -199,7 +127,7 @@ impl<'a> Cursor<'a> {
// object in global storage.
struct UnsafeSyncEntry(Entry);
unsafe impl Sync for UnsafeSyncEntry {}
- static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End(0 as *const Entry));
+ static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);
Cursor {
ptr: &EMPTY_ENTRY.0,
@@ -212,15 +140,15 @@ impl<'a> Cursor<'a> {
/// `None`-delimited scopes when the cursor reaches the end of them,
/// allowing for them to be treated transparently.
unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
- // NOTE: If we're looking at a `End(..)`, we want to advance the cursor
+ // NOTE: If we're looking at a `End`, we want to advance the cursor
// 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(exit) = *ptr {
+ while let Entry::End = *ptr {
if ptr == scope {
break;
}
- ptr = exit;
+ ptr = ptr.add(1);
}
Cursor {
@@ -238,7 +166,10 @@ impl<'a> Cursor<'a> {
/// Bump the cursor to point at the next token after the current one. This
/// is undefined behavior if the cursor is currently looking at an
/// `Entry::End`.
- unsafe fn bump(self) -> Cursor<'a> {
+ ///
+ /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
+ /// point at the first token in the group (with the same scope end).
+ unsafe fn bump_ignore_group(self) -> Cursor<'a> {
Cursor::create(self.ptr.offset(1), self.scope)
}
@@ -248,14 +179,9 @@ impl<'a> Cursor<'a> {
///
/// WARNING: This mutates its argument.
fn ignore_none(&mut self) {
- while let Entry::Group(group, buf) = self.entry() {
+ while let Entry::Group(group, _) = self.entry() {
if group.delimiter() == Delimiter::None {
- // NOTE: We call `Cursor::create` here to make sure that
- // situations where we should immediately exit the span after
- // entering it are handled correctly.
- unsafe {
- *self = Cursor::create(buf.ptr, self.scope);
- }
+ unsafe { *self = self.bump_ignore_group() };
} else {
break;
}
@@ -279,9 +205,12 @@ impl<'a> Cursor<'a> {
self.ignore_none();
}
- if let Entry::Group(group, buf) = self.entry() {
+ if let Entry::Group(group, end_offset) = self.entry() {
if group.delimiter() == delim {
- return Some((buf.begin(), group.span(), unsafe { self.bump() }));
+ let end_of_group = unsafe { self.ptr.add(*end_offset) };
+ let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
+ let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
+ return Some((inside_of_group, group.span(), after_group));
}
}
@@ -293,7 +222,7 @@ impl<'a> Cursor<'a> {
pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
- Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump() })),
+ Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
_ => None,
}
}
@@ -304,7 +233,7 @@ impl<'a> Cursor<'a> {
self.ignore_none();
match self.entry() {
Entry::Punct(punct) if punct.as_char() != '\'' => {
- Some((punct.clone(), unsafe { self.bump() }))
+ Some((punct.clone(), unsafe { self.bump_ignore_group() }))
}
_ => None,
}
@@ -315,7 +244,7 @@ impl<'a> Cursor<'a> {
pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
self.ignore_none();
match self.entry() {
- Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump() })),
+ Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
_ => None,
}
}
@@ -326,17 +255,13 @@ impl<'a> Cursor<'a> {
self.ignore_none();
match self.entry() {
Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
- let next = unsafe { self.bump() };
- match next.ident() {
- Some((ident, rest)) => {
- let lifetime = Lifetime {
- apostrophe: punct.span(),
- ident,
- };
- Some((lifetime, rest))
- }
- None => None,
- }
+ let next = unsafe { self.bump_ignore_group() };
+ let (ident, rest) = next.ident()?;
+ let lifetime = Lifetime {
+ apostrophe: punct.span(),
+ ident,
+ };
+ Some((lifetime, rest))
}
_ => None,
}
@@ -362,15 +287,16 @@ impl<'a> Cursor<'a> {
/// This method does not treat `None`-delimited groups as transparent, and
/// will return a `Group(None, ..)` if the cursor is looking at one.
pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
- let tree = match self.entry() {
- Entry::Group(group, _) => group.clone().into(),
- Entry::Literal(literal) => literal.clone().into(),
- Entry::Ident(ident) => ident.clone().into(),
- Entry::Punct(punct) => punct.clone().into(),
- Entry::End(..) => return None,
+ let (tree, len) = match self.entry() {
+ Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
+ 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,
};
- Some((tree, unsafe { self.bump() }))
+ let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
+ Some((tree, rest))
}
/// Returns the `Span` of the current token, or `Span::call_site()` if this
@@ -381,7 +307,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(),
}
}
@@ -390,19 +316,22 @@ impl<'a> Cursor<'a> {
///
/// This method treats `'lifetimes` as a single token.
pub(crate) fn skip(self) -> Option<Cursor<'a>> {
- match self.entry() {
- Entry::End(..) => None,
+ let len = match self.entry() {
+ 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 => {
- let next = unsafe { self.bump() };
- match next.entry() {
- Entry::Ident(_) => Some(unsafe { next.bump() }),
- _ => Some(next),
+ match unsafe { &*self.ptr.add(1) } {
+ Entry::Ident(_) => 2,
+ _ => 1,
}
}
- _ => Some(unsafe { self.bump() }),
- }
+
+ Entry::Group(_, end_offset) => *end_offset,
+ _ => 1,
+ };
+
+ Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
}
}
diff --git a/vendor/syn/src/expr.rs b/vendor/syn/src/expr.rs
index cf0fa0af9..93a59b0e2 100644
--- a/vendor/syn/src/expr.rs
+++ b/vendor/syn/src/expr.rs
@@ -1371,7 +1371,9 @@ pub(crate) mod parsing {
});
} else if Precedence::Cast >= base && input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
- let ty = input.call(Type::without_plus)?;
+ let allow_plus = false;
+ let allow_group_generic = false;
+ let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
check_cast(input)?;
lhs = Expr::Cast(ExprCast {
attrs: Vec::new(),
@@ -1381,7 +1383,9 @@ pub(crate) mod parsing {
});
} else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
let colon_token: Token![:] = input.parse()?;
- let ty = input.call(Type::without_plus)?;
+ let allow_plus = false;
+ let allow_group_generic = false;
+ let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
check_cast(input)?;
lhs = Expr::Type(ExprType {
attrs: Vec::new(),
@@ -1429,7 +1433,9 @@ pub(crate) mod parsing {
});
} else if Precedence::Cast >= base && input.peek(Token![as]) {
let as_token: Token![as] = input.parse()?;
- let ty = input.call(Type::without_plus)?;
+ let allow_plus = false;
+ let allow_group_generic = false;
+ let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
check_cast(input)?;
lhs = Expr::Cast(ExprCast {
attrs: Vec::new(),
@@ -1727,7 +1733,10 @@ pub(crate) mod parsing {
|| input.peek(Token![move])
{
expr_closure(input, allow_struct).map(Expr::Closure)
- } else if input.peek(Token![for]) && input.peek2(Token![<]) && input.peek3(Lifetime) {
+ } else if input.peek(Token![for])
+ && input.peek2(Token![<])
+ && (input.peek3(Lifetime) || input.peek3(Token![>]))
+ {
let begin = input.fork();
input.parse::<BoundLifetimes>()?;
expr_closure(input, allow_struct)?;
@@ -2010,7 +2019,9 @@ pub(crate) mod parsing {
Expr::If(input.parse()?)
} else if input.peek(Token![while]) {
Expr::While(input.parse()?)
- } else if input.peek(Token![for]) {
+ } else if input.peek(Token![for])
+ && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>])))
+ {
Expr::ForLoop(input.parse()?)
} else if input.peek(Token![loop]) {
Expr::Loop(input.parse()?)
diff --git a/vendor/syn/src/gen/clone.rs b/vendor/syn/src/gen/clone.rs
index 8de1cd8c9..a413e3ec7 100644
--- a/vendor/syn/src/gen/clone.rs
+++ b/vendor/syn/src/gen/clone.rs
@@ -910,9 +910,9 @@ impl Clone for GenericArgument {
match self {
GenericArgument::Lifetime(v0) => GenericArgument::Lifetime(v0.clone()),
GenericArgument::Type(v0) => GenericArgument::Type(v0.clone()),
+ GenericArgument::Const(v0) => GenericArgument::Const(v0.clone()),
GenericArgument::Binding(v0) => GenericArgument::Binding(v0.clone()),
GenericArgument::Constraint(v0) => GenericArgument::Constraint(v0.clone()),
- GenericArgument::Const(v0) => GenericArgument::Const(v0.clone()),
}
}
}
diff --git a/vendor/syn/src/gen/debug.rs b/vendor/syn/src/gen/debug.rs
index 4adf8c593..a1f0afa79 100644
--- a/vendor/syn/src/gen/debug.rs
+++ b/vendor/syn/src/gen/debug.rs
@@ -1268,6 +1268,11 @@ impl Debug for GenericArgument {
formatter.field(v0);
formatter.finish()
}
+ GenericArgument::Const(v0) => {
+ let mut formatter = formatter.debug_tuple("Const");
+ formatter.field(v0);
+ formatter.finish()
+ }
GenericArgument::Binding(v0) => {
let mut formatter = formatter.debug_tuple("Binding");
formatter.field(v0);
@@ -1278,11 +1283,6 @@ impl Debug for GenericArgument {
formatter.field(v0);
formatter.finish()
}
- GenericArgument::Const(v0) => {
- let mut formatter = formatter.debug_tuple("Const");
- formatter.field(v0);
- formatter.finish()
- }
}
}
}
diff --git a/vendor/syn/src/gen/eq.rs b/vendor/syn/src/gen/eq.rs
index 40fed0b89..20acb809d 100644
--- a/vendor/syn/src/gen/eq.rs
+++ b/vendor/syn/src/gen/eq.rs
@@ -878,13 +878,13 @@ impl PartialEq for GenericArgument {
(GenericArgument::Type(self0), GenericArgument::Type(other0)) => {
self0 == other0
}
- (GenericArgument::Binding(self0), GenericArgument::Binding(other0)) => {
+ (GenericArgument::Const(self0), GenericArgument::Const(other0)) => {
self0 == other0
}
- (GenericArgument::Constraint(self0), GenericArgument::Constraint(other0)) => {
+ (GenericArgument::Binding(self0), GenericArgument::Binding(other0)) => {
self0 == other0
}
- (GenericArgument::Const(self0), GenericArgument::Const(other0)) => {
+ (GenericArgument::Constraint(self0), GenericArgument::Constraint(other0)) => {
self0 == other0
}
_ => false,
diff --git a/vendor/syn/src/gen/fold.rs b/vendor/syn/src/gen/fold.rs
index 6e19e6f3a..98bb5794a 100644
--- a/vendor/syn/src/gen/fold.rs
+++ b/vendor/syn/src/gen/fold.rs
@@ -1787,15 +1787,15 @@ where
GenericArgument::Type(_binding_0) => {
GenericArgument::Type(f.fold_type(_binding_0))
}
+ GenericArgument::Const(_binding_0) => {
+ GenericArgument::Const(f.fold_expr(_binding_0))
+ }
GenericArgument::Binding(_binding_0) => {
GenericArgument::Binding(f.fold_binding(_binding_0))
}
GenericArgument::Constraint(_binding_0) => {
GenericArgument::Constraint(f.fold_constraint(_binding_0))
}
- GenericArgument::Const(_binding_0) => {
- GenericArgument::Const(f.fold_expr(_binding_0))
- }
}
}
#[cfg(feature = "full")]
diff --git a/vendor/syn/src/gen/hash.rs b/vendor/syn/src/gen/hash.rs
index f68a7630e..d0400e19d 100644
--- a/vendor/syn/src/gen/hash.rs
+++ b/vendor/syn/src/gen/hash.rs
@@ -1184,15 +1184,15 @@ impl Hash for GenericArgument {
state.write_u8(1u8);
v0.hash(state);
}
- GenericArgument::Binding(v0) => {
+ GenericArgument::Const(v0) => {
state.write_u8(2u8);
v0.hash(state);
}
- GenericArgument::Constraint(v0) => {
+ GenericArgument::Binding(v0) => {
state.write_u8(3u8);
v0.hash(state);
}
- GenericArgument::Const(v0) => {
+ GenericArgument::Constraint(v0) => {
state.write_u8(4u8);
v0.hash(state);
}
diff --git a/vendor/syn/src/gen/visit.rs b/vendor/syn/src/gen/visit.rs
index 051b65936..19ddd2e72 100644
--- a/vendor/syn/src/gen/visit.rs
+++ b/vendor/syn/src/gen/visit.rs
@@ -1974,15 +1974,15 @@ where
GenericArgument::Type(_binding_0) => {
v.visit_type(_binding_0);
}
+ GenericArgument::Const(_binding_0) => {
+ v.visit_expr(_binding_0);
+ }
GenericArgument::Binding(_binding_0) => {
v.visit_binding(_binding_0);
}
GenericArgument::Constraint(_binding_0) => {
v.visit_constraint(_binding_0);
}
- GenericArgument::Const(_binding_0) => {
- v.visit_expr(_binding_0);
- }
}
}
#[cfg(feature = "full")]
diff --git a/vendor/syn/src/gen/visit_mut.rs b/vendor/syn/src/gen/visit_mut.rs
index 3ddbe9c06..239709d19 100644
--- a/vendor/syn/src/gen/visit_mut.rs
+++ b/vendor/syn/src/gen/visit_mut.rs
@@ -1975,15 +1975,15 @@ where
GenericArgument::Type(_binding_0) => {
v.visit_type_mut(_binding_0);
}
+ GenericArgument::Const(_binding_0) => {
+ v.visit_expr_mut(_binding_0);
+ }
GenericArgument::Binding(_binding_0) => {
v.visit_binding_mut(_binding_0);
}
GenericArgument::Constraint(_binding_0) => {
v.visit_constraint_mut(_binding_0);
}
- GenericArgument::Const(_binding_0) => {
- v.visit_expr_mut(_binding_0);
- }
}
}
#[cfg(feature = "full")]
diff --git a/vendor/syn/src/item.rs b/vendor/syn/src/item.rs
index 1ce970ee2..a1ef7ab43 100644
--- a/vendor/syn/src/item.rs
+++ b/vendor/syn/src/item.rs
@@ -2765,7 +2765,6 @@ mod printing {
use super::*;
use crate::attr::FilterAttrs;
use crate::print::TokensOrDefault;
- use crate::punctuated::Pair;
use proc_macro2::TokenStream;
use quote::{ToTokens, TokenStreamExt};
@@ -3283,16 +3282,9 @@ mod printing {
self.generics.to_tokens(tokens);
self.paren_token.surround(tokens, |tokens| {
let mut last_is_variadic = false;
- for input in self.inputs.pairs() {
- match input {
- Pair::Punctuated(input, comma) => {
- maybe_variadic_to_tokens(input, tokens);
- comma.to_tokens(tokens);
- }
- Pair::End(input) => {
- last_is_variadic = maybe_variadic_to_tokens(input, tokens);
- }
- }
+ for pair in self.inputs.pairs() {
+ last_is_variadic = maybe_variadic_to_tokens(pair.value(), tokens);
+ pair.punct().to_tokens(tokens);
}
if self.variadic.is_some() && !last_is_variadic {
if !self.inputs.empty_or_trailing() {
diff --git a/vendor/syn/src/lib.rs b/vendor/syn/src/lib.rs
index 09addd3a6..81f03e1b5 100644
--- a/vendor/syn/src/lib.rs
+++ b/vendor/syn/src/lib.rs
@@ -250,10 +250,11 @@
//! 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.99")]
+#![doc(html_root_url = "https://docs.rs/syn/1.0.102")]
#![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_ptr_alignment,
@@ -812,14 +813,6 @@ mod print;
////////////////////////////////////////////////////////////////////////////////
-// https://github.com/rust-lang/rust/issues/62830
-#[cfg(feature = "parsing")]
-mod rustdoc_workaround {
- pub use crate::parse::{self as parse_module};
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
mod error;
pub use crate::error::{Error, Result};
diff --git a/vendor/syn/src/lit.rs b/vendor/syn/src/lit.rs
index 2600dc801..130b40ed1 100644
--- a/vendor/syn/src/lit.rs
+++ b/vendor/syn/src/lit.rs
@@ -224,7 +224,7 @@ impl LitStr {
// Parse string literal into a token stream with every span equal to the
// original literal's span.
- let mut tokens = crate::parse_str(&self.value())?;
+ let mut tokens = TokenStream::from_str(&self.value())?;
tokens = respan_token_stream(tokens, self.span());
parser.parse2(tokens)
diff --git a/vendor/syn/src/parse_macro_input.rs b/vendor/syn/src/parse_macro_input.rs
index 8e1a5ec6b..6163cd70a 100644
--- a/vendor/syn/src/parse_macro_input.rs
+++ b/vendor/syn/src/parse_macro_input.rs
@@ -4,7 +4,7 @@
/// Refer to the [`parse` module] documentation for more details about parsing
/// in Syn.
///
-/// [`parse` module]: crate::rustdoc_workaround::parse_module
+/// [`parse` module]: mod@crate::parse
///
/// <br>
///
@@ -51,7 +51,7 @@
/// This macro can also be used with the [`Parser` trait] for types that have
/// multiple ways that they can be parsed.
///
-/// [`Parser` trait]: crate::rustdoc_workaround::parse_module::Parser
+/// [`Parser` trait]: crate::parse::Parser
///
/// ```
/// # extern crate proc_macro;
diff --git a/vendor/syn/src/pat.rs b/vendor/syn/src/pat.rs
index fa0818c16..b279186aa 100644
--- a/vendor/syn/src/pat.rs
+++ b/vendor/syn/src/pat.rs
@@ -400,11 +400,11 @@ pub mod parsing {
}
if input.peek(token::Brace) {
- let pat = pat_struct(input, path)?;
+ let pat = pat_struct(begin.fork(), input, path)?;
if qself.is_some() {
Ok(Pat::Verbatim(verbatim::between(begin, input)))
} else {
- Ok(Pat::Struct(pat))
+ Ok(pat)
}
} else if input.peek(token::Paren) {
let pat = pat_tuple_struct(input, path)?;
@@ -465,13 +465,23 @@ pub mod parsing {
})
}
- fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
+ fn pat_struct(begin: ParseBuffer, input: ParseStream, path: Path) -> Result<Pat> {
let content;
let brace_token = braced!(content in input);
let mut fields = Punctuated::new();
- while !content.is_empty() && !content.peek(Token![..]) {
- let value = content.call(field_pat)?;
+ let mut dot2_token = None;
+ while !content.is_empty() {
+ let attrs = content.call(Attribute::parse_outer)?;
+ if content.peek(Token![..]) {
+ dot2_token = Some(content.parse()?);
+ if !attrs.is_empty() {
+ return Ok(Pat::Verbatim(verbatim::between(begin, input)));
+ }
+ break;
+ }
+ let mut value = content.call(field_pat)?;
+ value.attrs = attrs;
fields.push_value(value);
if content.is_empty() {
break;
@@ -480,19 +490,13 @@ pub mod parsing {
fields.push_punct(punct);
}
- let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
- Some(content.parse()?)
- } else {
- None
- };
-
- Ok(PatStruct {
+ Ok(Pat::Struct(PatStruct {
attrs: Vec::new(),
path,
brace_token,
fields,
dot2_token,
- })
+ }))
}
impl Member {
@@ -505,7 +509,6 @@ pub mod parsing {
}
fn field_pat(input: ParseStream) -> Result<FieldPat> {
- let attrs = input.call(Attribute::parse_outer)?;
let boxed: Option<Token![box]> = input.parse()?;
let by_ref: Option<Token![ref]> = input.parse()?;
let mutability: Option<Token![mut]> = input.parse()?;
@@ -515,7 +518,7 @@ pub mod parsing {
|| member.is_unnamed()
{
return Ok(FieldPat {
- attrs,
+ attrs: Vec::new(),
member,
colon_token: input.parse()?,
pat: Box::new(multi_pat_with_leading_vert(input)?),
@@ -544,7 +547,7 @@ pub mod parsing {
}
Ok(FieldPat {
- attrs,
+ attrs: Vec::new(),
member: Member::Named(ident),
colon_token: None,
pat: Box::new(pat),
diff --git a/vendor/syn/src/path.rs b/vendor/syn/src/path.rs
index 00be352b1..742273afd 100644
--- a/vendor/syn/src/path.rs
+++ b/vendor/syn/src/path.rs
@@ -109,16 +109,16 @@ ast_enum! {
Lifetime(Lifetime),
/// A type argument.
Type(Type),
- /// A binding (equality constraint) on an associated type: the `Item =
- /// u8` in `Iterator<Item = u8>`.
- Binding(Binding),
- /// An associated type bound: `Iterator<Item: Display>`.
- Constraint(Constraint),
/// A const expression. Must be inside of a block.
///
/// NOTE: Identity expressions are represented as Type arguments, as
/// they are indistinguishable syntactically.
Const(Expr),
+ /// A binding (equality constraint) on an associated type: the `Item =
+ /// u8` in `Iterator<Item = u8>`.
+ Binding(Binding),
+ /// An associated type bound: `Iterator<Item: Display>`.
+ Constraint(Constraint),
}
}
@@ -729,8 +729,6 @@ pub(crate) mod printing {
match self {
GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
GenericArgument::Type(ty) => ty.to_tokens(tokens),
- GenericArgument::Binding(tb) => tb.to_tokens(tokens),
- GenericArgument::Constraint(tc) => tc.to_tokens(tokens),
GenericArgument::Const(e) => match *e {
Expr::Lit(_) => e.to_tokens(tokens),
@@ -746,6 +744,8 @@ pub(crate) mod printing {
e.to_tokens(tokens);
}),
},
+ GenericArgument::Binding(tb) => tb.to_tokens(tokens),
+ GenericArgument::Constraint(tc) => tc.to_tokens(tokens),
}
}
}
@@ -756,11 +756,8 @@ pub(crate) mod printing {
self.colon2_token.to_tokens(tokens);
self.lt_token.to_tokens(tokens);
- // Print lifetimes before types and consts, all before bindings,
- // regardless of their order in self.args.
- //
- // TODO: ordering rules for const arguments vs type arguments have
- // not been settled yet. https://github.com/rust-lang/rust/issues/44580
+ // Print lifetimes before types/consts/bindings, regardless of their
+ // order in self.args.
let mut trailing_or_empty = true;
for param in self.args.pairs() {
match **param.value() {
@@ -769,37 +766,24 @@ pub(crate) mod printing {
trailing_or_empty = param.punct().is_some();
}
GenericArgument::Type(_)
- | GenericArgument::Binding(_)
- | GenericArgument::Constraint(_)
- | GenericArgument::Const(_) => {}
- }
- }
- for param in self.args.pairs() {
- match **param.value() {
- GenericArgument::Type(_) | GenericArgument::Const(_) => {
- if !trailing_or_empty {
- <Token![,]>::default().to_tokens(tokens);
- }
- param.to_tokens(tokens);
- trailing_or_empty = param.punct().is_some();
- }
- GenericArgument::Lifetime(_)
+ | GenericArgument::Const(_)
| GenericArgument::Binding(_)
| GenericArgument::Constraint(_) => {}
}
}
for param in self.args.pairs() {
match **param.value() {
- GenericArgument::Binding(_) | GenericArgument::Constraint(_) => {
+ GenericArgument::Type(_)
+ | GenericArgument::Const(_)
+ | GenericArgument::Binding(_)
+ | GenericArgument::Constraint(_) => {
if !trailing_or_empty {
<Token![,]>::default().to_tokens(tokens);
}
param.to_tokens(tokens);
trailing_or_empty = param.punct().is_some();
}
- GenericArgument::Lifetime(_)
- | GenericArgument::Type(_)
- | GenericArgument::Const(_) => {}
+ GenericArgument::Lifetime(_) => {}
}
}
diff --git a/vendor/syn/src/stmt.rs b/vendor/syn/src/stmt.rs
index 3e2c71bdd..58bd013ec 100644
--- a/vendor/syn/src/stmt.rs
+++ b/vendor/syn/src/stmt.rs
@@ -175,7 +175,11 @@ pub mod parsing {
|| input.peek(Token![crate]) && !input.peek2(Token![::])
|| input.peek(Token![extern])
|| input.peek(Token![use])
- || input.peek(Token![static]) && (input.peek2(Token![mut]) || input.peek2(Ident))
+ || input.peek(Token![static])
+ && (input.peek2(Token![mut])
+ || input.peek2(Ident)
+ && !(input.peek2(Token![async])
+ && (input.peek3(Token![move]) || input.peek3(Token![|]))))
|| input.peek(Token![const]) && !input.peek2(token::Brace)
|| input.peek(Token![unsafe]) && !input.peek2(token::Brace)
|| input.peek(Token![async])
diff --git a/vendor/syn/src/ty.rs b/vendor/syn/src/ty.rs
index 0f1341fdd..4068be3c7 100644
--- a/vendor/syn/src/ty.rs
+++ b/vendor/syn/src/ty.rs
@@ -343,7 +343,8 @@ pub mod parsing {
impl Parse for Type {
fn parse(input: ParseStream) -> Result<Self> {
let allow_plus = true;
- ambig_ty(input, allow_plus)
+ let allow_group_generic = true;
+ ambig_ty(input, allow_plus, allow_group_generic)
}
}
@@ -356,11 +357,16 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
pub fn without_plus(input: ParseStream) -> Result<Self> {
let allow_plus = false;
- ambig_ty(input, allow_plus)
+ let allow_group_generic = true;
+ ambig_ty(input, allow_plus, allow_group_generic)
}
}
- fn ambig_ty(input: ParseStream, allow_plus: bool) -> Result<Type> {
+ pub(crate) fn ambig_ty(
+ input: ParseStream,
+ allow_plus: bool,
+ allow_group_generic: bool,
+ ) -> Result<Type> {
let begin = input.fork();
if input.peek(token::Group) {
@@ -381,7 +387,9 @@ pub mod parsing {
path: Path::parse_helper(input, false)?,
}));
}
- } else if input.peek(Token![<]) || input.peek(Token![::]) && input.peek3(Token![<]) {
+ } else if input.peek(Token![<]) && allow_group_generic
+ || input.peek(Token![::]) && input.peek3(Token![<])
+ {
if let Type::Path(mut ty) = *group.elem {
let arguments = &mut ty.path.segments.last_mut().unwrap().arguments;
if let PathArguments::None = arguments {
@@ -537,9 +545,15 @@ pub mod parsing {
|| lookahead.peek(Token![::])
|| lookahead.peek(Token![<])
{
- if input.peek(Token![dyn]) {
- let trait_object = TypeTraitObject::parse(input, allow_plus)?;
- return Ok(Type::TraitObject(trait_object));
+ let dyn_token: Option<Token![dyn]> = input.parse()?;
+ if dyn_token.is_some() {
+ let star_token: Option<Token![*]> = input.parse()?;
+ let bounds = TypeTraitObject::parse_bounds(input, allow_plus)?;
+ return Ok(if star_token.is_some() {
+ Type::Verbatim(verbatim::between(begin, input))
+ } else {
+ Type::TraitObject(TypeTraitObject { dyn_token, bounds })
+ });
}
let ty: TypePath = input.parse()?;
@@ -819,15 +833,28 @@ pub mod parsing {
#[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
impl Parse for TypePath {
fn parse(input: ParseStream) -> Result<Self> {
- let (qself, mut path) = path::parsing::qpath(input, false)?;
+ let expr_style = false;
+ let (qself, mut path) = path::parsing::qpath(input, expr_style)?;
- if path.segments.last().unwrap().arguments.is_empty()
+ while path.segments.last().unwrap().arguments.is_empty()
&& (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren))
{
input.parse::<Option<Token![::]>>()?;
let args: ParenthesizedGenericArguments = input.parse()?;
+ let allow_associated_type = cfg!(feature = "full")
+ && match &args.output {
+ ReturnType::Default => true,
+ ReturnType::Type(_, ty) => match **ty {
+ // TODO: probably some of the other kinds allow this too.
+ Type::Paren(_) => true,
+ _ => false,
+ },
+ };
let parenthesized = PathArguments::Parenthesized(args);
path.segments.last_mut().unwrap().arguments = parenthesized;
+ if allow_associated_type {
+ Path::parse_rest(input, &mut path, expr_style)?;
+ }
}
Ok(TypePath { qself, path })
@@ -844,7 +871,8 @@ pub mod parsing {
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
if input.peek(Token![->]) {
let arrow = input.parse()?;
- let ty = ambig_ty(input, allow_plus)?;
+ let allow_group_generic = true;
+ let ty = ambig_ty(input, allow_plus, allow_group_generic)?;
Ok(ReturnType::Type(arrow, Box::new(ty)))
} else {
Ok(ReturnType::Default)
@@ -967,7 +995,10 @@ pub mod parsing {
let content;
Ok(TypeParen {
paren_token: parenthesized!(content in input),
- elem: Box::new(ambig_ty(&content, allow_plus)?),
+ elem: Box::new({
+ let allow_group_generic = true;
+ ambig_ty(&content, allow_plus, allow_group_generic)?
+ }),
})
}
}
diff --git a/vendor/syn/tests/.gitignore b/vendor/syn/tests/.gitignore
deleted file mode 100644
index 291ed43a2..000000000
--- a/vendor/syn/tests/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/*.pending-snap
diff --git a/vendor/syn/tests/common/eq.rs b/vendor/syn/tests/common/eq.rs
index ff100aa41..a53146241 100644
--- a/vendor/syn/tests/common/eq.rs
+++ b/vendor/syn/tests/common/eq.rs
@@ -3,6 +3,7 @@
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_span;
+extern crate thin_vec;
use rustc_ast::ast::AngleBracketedArg;
use rustc_ast::ast::AngleBracketedArgs;
@@ -19,10 +20,11 @@ use rustc_ast::ast::AttrStyle;
use rustc_ast::ast::Attribute;
use rustc_ast::ast::BareFnTy;
use rustc_ast::ast::BinOpKind;
-use rustc_ast::ast::BindingMode;
+use rustc_ast::ast::BindingAnnotation;
use rustc_ast::ast::Block;
use rustc_ast::ast::BlockCheckMode;
use rustc_ast::ast::BorrowKind;
+use rustc_ast::ast::ByRef;
use rustc_ast::ast::CaptureBy;
use rustc_ast::ast::ClosureBinder;
use rustc_ast::ast::Const;
@@ -82,6 +84,7 @@ use rustc_ast::ast::Movability;
use rustc_ast::ast::MutTy;
use rustc_ast::ast::Mutability;
use rustc_ast::ast::NodeId;
+use rustc_ast::ast::NormalAttr;
use rustc_ast::ast::Param;
use rustc_ast::ast::ParenthesizedArgs;
use rustc_ast::ast::Pat;
@@ -127,14 +130,14 @@ use rustc_ast::ast::WhereRegionPredicate;
use rustc_ast::ptr::P;
use rustc_ast::token::{self, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
use rustc_ast::tokenstream::{
- AttrAnnotatedTokenStream, AttrAnnotatedTokenTree, AttributesData, DelimSpan, LazyTokenStream,
- Spacing, TokenStream, TokenTree,
+ AttrTokenStream, AttrTokenTree, AttributesData, DelimSpan, LazyAttrTokenStream, Spacing,
+ TokenStream, TokenTree,
};
use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
use rustc_span::{Span, Symbol, SyntaxContext, DUMMY_SP};
+use thin_vec::ThinVec;
pub trait SpanlessEq {
fn eq(&self, other: &Self) -> bool;
@@ -401,11 +404,12 @@ spanless_eq_struct!(AngleBracketedArgs; span args);
spanless_eq_struct!(AnonConst; id value);
spanless_eq_struct!(Arm; attrs pat guard body span id is_placeholder);
spanless_eq_struct!(AssocConstraint; id ident gen_args kind span);
-spanless_eq_struct!(AttrAnnotatedTokenStream; 0);
spanless_eq_struct!(AttrItem; path args tokens);
+spanless_eq_struct!(AttrTokenStream; 0);
spanless_eq_struct!(Attribute; kind id style span);
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!(Crate; attrs items spans id is_placeholder);
spanless_eq_struct!(EnumDef; variants);
@@ -425,13 +429,14 @@ 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 kind span);
+spanless_eq_struct!(Lit; token_lit kind span);
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!(ModSpans; !inner_span !inject_use_span);
spanless_eq_struct!(MutTy; ty mutbl);
+spanless_eq_struct!(NormalAttr; item tokens);
spanless_eq_struct!(ParenthesizedArgs; span inputs inputs_span output);
spanless_eq_struct!(Pat; id kind span tokens);
spanless_eq_struct!(PatField; ident pat is_shorthand attrs id span is_placeholder);
@@ -453,19 +458,19 @@ spanless_eq_struct!(Variant; attrs id span !vis ident data disr_expr is_placehol
spanless_eq_struct!(Visibility; kind span tokens);
spanless_eq_struct!(WhereBoundPredicate; span bound_generic_params bounded_ty bounds);
spanless_eq_struct!(WhereClause; has_where_token predicates span);
-spanless_eq_struct!(WhereEqPredicate; id span lhs_ty rhs_ty);
+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!(AssocConstraintKind; Equality(term) Bound(bounds));
spanless_eq_enum!(Async; Yes(span closure_id return_impl_trait_id) No);
-spanless_eq_enum!(AttrAnnotatedTokenTree; Token(0) Delimited(0 1 2) Attributes(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);
-spanless_eq_enum!(BindingMode; ByRef(0) ByValue(0));
spanless_eq_enum!(BlockCheckMode; Default Unsafe(0));
spanless_eq_enum!(BorrowKind; Ref Raw);
+spanless_eq_enum!(ByRef; Yes No);
spanless_eq_enum!(CaptureBy; Value Ref);
spanless_eq_enum!(ClosureBinder; NotPresent For(span generic_params));
spanless_eq_enum!(Const; Yes(0) No);
@@ -502,22 +507,23 @@ spanless_eq_enum!(StructRest; Base(0) Rest(0) None);
spanless_eq_enum!(Term; Ty(0) Const(0));
spanless_eq_enum!(TokenTree; Token(0 1) Delimited(0 1 2));
spanless_eq_enum!(TraitBoundModifier; None Maybe MaybeConst MaybeConstMaybe);
-spanless_eq_enum!(TraitObjectSyntax; Dyn None);
+spanless_eq_enum!(TraitObjectSyntax; Dyn DynStar None);
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!(VariantData; Struct(0 1) Tuple(0 1) Unit(0));
-spanless_eq_enum!(VisibilityKind; Public Restricted(path id) Inherited);
+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) 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 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);
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));
@@ -525,7 +531,7 @@ spanless_eq_enum!(ItemKind; ExternCrate(0) Use(0) Static(0 1 2) Const(0 1 2)
Fn(0) Mod(0 1) ForeignMod(0) GlobalAsm(0) TyAlias(0) Enum(0 1) Struct(0 1)
Union(0 1) Trait(0) TraitAlias(0 1) Impl(0) MacCall(0) MacroDef(0));
spanless_eq_enum!(LitKind; Str(0 1) ByteStr(0) Byte(0) Char(0) Int(0 1)
- Float(0 1) Bool(0) Err(0));
+ Float(0 1) Bool(0) Err);
spanless_eq_enum!(PatKind; Wild Ident(0 1 2) Struct(0 1 2 3) TupleStruct(0 1 2)
Or(0) Path(0 1) Tuple(0) Box(0) Ref(0 1) Lit(0) Range(0 1 2) Slice(0) Rest
Paren(0) MacCall(0));
@@ -691,7 +697,7 @@ fn is_escaped_literal_token(token: &Token, unescaped: Symbol) -> bool {
Token {
kind: TokenKind::Literal(lit),
span: _,
- } => match Lit::from_lit_token(*lit, DUMMY_SP) {
+ } => match Lit::from_token_lit(*lit, DUMMY_SP) {
Ok(lit) => is_escaped_literal(&lit, unescaped),
Err(_) => false,
},
@@ -722,7 +728,7 @@ fn is_escaped_literal_macro_arg(arg: &MacArgsEq, unescaped: Symbol) -> bool {
fn is_escaped_literal(lit: &Lit, unescaped: Symbol) -> bool {
match lit {
Lit {
- token:
+ token_lit:
token::Lit {
kind: token::LitKind::Str,
symbol: _,
@@ -735,10 +741,10 @@ fn is_escaped_literal(lit: &Lit, unescaped: Symbol) -> bool {
}
}
-impl SpanlessEq for LazyTokenStream {
+impl SpanlessEq for LazyAttrTokenStream {
fn eq(&self, other: &Self) -> bool {
- let this = self.create_token_stream();
- let other = other.create_token_stream();
+ let this = self.to_attr_token_stream();
+ let other = other.to_attr_token_stream();
SpanlessEq::eq(&this, &other)
}
}
@@ -746,26 +752,26 @@ impl SpanlessEq for LazyTokenStream {
impl SpanlessEq for AttrKind {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
- (AttrKind::Normal(item, tokens), AttrKind::Normal(item2, tokens2)) => {
- SpanlessEq::eq(item, item2) && SpanlessEq::eq(tokens, tokens2)
+ (AttrKind::Normal(normal), AttrKind::Normal(normal2)) => {
+ SpanlessEq::eq(normal, normal2)
}
(AttrKind::DocComment(kind, symbol), AttrKind::DocComment(kind2, symbol2)) => {
SpanlessEq::eq(kind, kind2) && SpanlessEq::eq(symbol, symbol2)
}
- (AttrKind::DocComment(kind, unescaped), AttrKind::Normal(item2, _tokens)) => {
+ (AttrKind::DocComment(kind, unescaped), AttrKind::Normal(normal2)) => {
match kind {
CommentKind::Line | CommentKind::Block => {}
}
let path = Path::from_ident(Ident::with_dummy_span(sym::doc));
- SpanlessEq::eq(&path, &item2.path)
- && match &item2.args {
+ 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)
}
}
}
- (AttrKind::Normal(..), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self),
+ (AttrKind::Normal(_), AttrKind::DocComment(..)) => SpanlessEq::eq(other, self),
}
}
}
diff --git a/vendor/syn/tests/debug/gen.rs b/vendor/syn/tests/debug/gen.rs
index a49ee6c92..cfd63d117 100644
--- a/vendor/syn/tests/debug/gen.rs
+++ b/vendor/syn/tests/debug/gen.rs
@@ -2215,22 +2215,22 @@ impl Debug for Lite<syn::GenericArgument> {
formatter.write_str(")")?;
Ok(())
}
- syn::GenericArgument::Binding(_val) => {
- formatter.write_str("Binding")?;
+ syn::GenericArgument::Const(_val) => {
+ formatter.write_str("Const")?;
formatter.write_str("(")?;
Debug::fmt(Lite(_val), formatter)?;
formatter.write_str(")")?;
Ok(())
}
- syn::GenericArgument::Constraint(_val) => {
- formatter.write_str("Constraint")?;
+ syn::GenericArgument::Binding(_val) => {
+ formatter.write_str("Binding")?;
formatter.write_str("(")?;
Debug::fmt(Lite(_val), formatter)?;
formatter.write_str(")")?;
Ok(())
}
- syn::GenericArgument::Const(_val) => {
- formatter.write_str("Const")?;
+ syn::GenericArgument::Constraint(_val) => {
+ formatter.write_str("Constraint")?;
formatter.write_str("(")?;
Debug::fmt(Lite(_val), formatter)?;
formatter.write_str(")")?;
diff --git a/vendor/syn/tests/regression/issue1108.rs b/vendor/syn/tests/regression/issue1108.rs
index 11a82adaa..4fd30c0c7 100644
--- a/vendor/syn/tests/regression/issue1108.rs
+++ b/vendor/syn/tests/regression/issue1108.rs
@@ -1,5 +1,5 @@
#[test]
fn issue1108() {
let data = "impl<x<>>::x for";
- let _ = syn::parse_file(data);
+ _ = syn::parse_file(data);
}
diff --git a/vendor/syn/tests/repo/mod.rs b/vendor/syn/tests/repo/mod.rs
index 0bafe6714..4c7be853b 100644
--- a/vendor/syn/tests/repo/mod.rs
+++ b/vendor/syn/tests/repo/mod.rs
@@ -10,10 +10,10 @@ use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;
-const REVISION: &str = "ee160f2f5e73b6f5954bc33f059c316d9e8582c4";
+const REVISION: &str = "98ad6a5519651af36e246c0335c964dd52c554ba";
#[rustfmt::skip]
-static EXCLUDE: &[&str] = &[
+static EXCLUDE_FILES: &[&str] = &[
// TODO: impl ~const T {}
// https://github.com/dtolnay/syn/issues/1051
"src/test/ui/rfc-2632-const-trait-impl/syntax.rs",
@@ -33,6 +33,21 @@ static EXCLUDE: &[&str] = &[
"src/tools/rustfmt/tests/source/trait.rs",
"src/tools/rustfmt/tests/target/trait.rs",
+ // Various extensions to Rust syntax made up by rust-analyzer
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0012_type_item_where_clause.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0040_crate_keyword_vis.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0131_existential_type.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0179_use_tree_abs_star.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0015_use_tree.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0029_range_forms.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0051_parameter_attrs.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0055_dot_dot_dot.rs",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/ok/0068_item_modifiers.rs",
+ "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0031_block_inner_attrs.rs",
+ "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0045_ambiguous_trait_object.rs",
+ "src/tools/rust-analyzer/crates/syntax/test_data/parser/validation/0046_mutable_const_item.rs",
+
// Placeholder syntax for "throw expressions"
"src/test/pretty/yeet-expr.rs",
"src/test/ui/try-trait/yeet-for-option.rs",
@@ -41,7 +56,9 @@ static EXCLUDE: &[&str] = &[
// Excessive nesting
"src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",
- // Testing rustfmt on invalid syntax
+ // Testing tools on invalid syntax
+ "src/test/run-make/translation/test.rs",
+ "src/test/ui/generics/issue-94432-garbage-ice.rs",
"src/tools/rustfmt/tests/coverage/target/comments.rs",
"src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
"src/tools/rustfmt/tests/parser/issue_4418.rs",
@@ -54,8 +71,8 @@ static EXCLUDE: &[&str] = &[
"src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
"src/tools/rustfmt/tests/target/type.rs",
- // Testing compiler diagnostic localization on invalid syntax
- "src/test/run-make/translation/basic-translation.rs",
+ // Generated file containing a top-level expression, used with `include!`
+ "compiler/rustc_codegen_gcc/src/intrinsic/archs.rs",
// Clippy lint lists represented as expressions
"src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
@@ -73,9 +90,6 @@ static EXCLUDE: &[&str] = &[
"src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",
// Not actually test cases
- "src/test/rustdoc-ui/test-compile-fail2.rs",
- "src/test/rustdoc-ui/test-compile-fail3.rs",
- "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
"src/test/ui/lint/expansion-time-include.rs",
"src/test/ui/macros/auxiliary/macro-comma-support.rs",
"src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
@@ -84,38 +98,52 @@ static EXCLUDE: &[&str] = &[
"src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];
+#[rustfmt::skip]
+static EXCLUDE_DIRS: &[&str] = &[
+ // Inputs that intentionally do not parse
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/err",
+ "src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err",
+
+ // Inputs that lex but do not necessarily parse
+ "src/tools/rust-analyzer/crates/parser/test_data/lexer",
+
+ // Inputs that used to crash rust-analyzer, but aren't necessarily supposed to parse
+ "src/tools/rust-analyzer/crates/syntax/test_data/parser/fuzz-failures",
+ "src/tools/rust-analyzer/crates/syntax/test_data/reparse/fuzz-failures",
+];
+
pub fn base_dir_filter(entry: &DirEntry) -> bool {
let path = entry.path();
- if path.is_dir() {
- return true; // otherwise walkdir does not visit the files
- }
- if path.extension().map_or(true, |e| e != "rs") {
- return false;
- }
let mut path_string = path.to_string_lossy();
if cfg!(windows) {
path_string = path_string.replace('\\', "/").into();
}
- let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
+ let path_string = if path_string == "tests/rust" {
+ return true;
+ } else if let Some(path) = path_string.strip_prefix("tests/rust/") {
path
} else {
panic!("unexpected path in Rust dist: {}", path_string);
};
- if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
+ if path.is_dir() {
+ return !EXCLUDE_DIRS.contains(&path_string);
+ }
+
+ if path.extension().map_or(true, |e| e != "rs") {
return false;
}
- if path.starts_with("src/test/ui") {
- let stderr_path = entry.path().with_extension("stderr");
+ if path_string.starts_with("src/test/ui") || path_string.starts_with("src/test/rustdoc-ui") {
+ let stderr_path = path.with_extension("stderr");
if stderr_path.exists() {
// Expected to fail in some way
return false;
}
}
- !EXCLUDE.contains(&path)
+ !EXCLUDE_FILES.contains(&path_string)
}
#[allow(dead_code)]
@@ -137,10 +165,17 @@ pub fn clone_rust() {
}
let mut missing = String::new();
let test_src = Path::new("tests/rust");
- for exclude in EXCLUDE {
- if !test_src.join(exclude).exists() {
+ for exclude in EXCLUDE_FILES {
+ if !test_src.join(exclude).is_file() {
+ missing += "\ntests/rust/";
+ missing += exclude;
+ }
+ }
+ for exclude in EXCLUDE_DIRS {
+ if !test_src.join(exclude).is_dir() {
missing += "\ntests/rust/";
missing += exclude;
+ missing += "/";
}
}
if !missing.is_empty() {
diff --git a/vendor/syn/tests/test_parse_stream.rs b/vendor/syn/tests/test_parse_stream.rs
index 76bd06577..cc14fa032 100644
--- a/vendor/syn/tests/test_parse_stream.rs
+++ b/vendor/syn/tests/test_parse_stream.rs
@@ -4,9 +4,9 @@ use syn::{Ident, Token};
#[test]
fn test_peek() {
- let _ = |input: ParseStream| {
- let _ = input.peek(Ident);
- let _ = input.peek(Ident::peek_any);
- let _ = input.peek(Token![::]);
+ _ = |input: ParseStream| {
+ _ = input.peek(Ident);
+ _ = input.peek(Ident::peek_any);
+ _ = input.peek(Token![::]);
};
}
diff --git a/vendor/syn/tests/test_precedence.rs b/vendor/syn/tests/test_precedence.rs
index bd273a565..dbcd74f16 100644
--- a/vendor/syn/tests/test_precedence.rs
+++ b/vendor/syn/tests/test_precedence.rs
@@ -24,6 +24,7 @@
extern crate rustc_ast;
extern crate rustc_data_structures;
extern crate rustc_span;
+extern crate thin_vec;
use crate::common::eq::SpanlessEq;
use crate::common::parse;
@@ -207,10 +208,10 @@ fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
};
use rustc_ast::mut_visit::{noop_visit_generic_arg, noop_visit_local, MutVisitor};
use rustc_data_structures::map_in_place::MapInPlace;
- use rustc_data_structures::thin_vec::ThinVec;
use rustc_span::DUMMY_SP;
use std::mem;
use std::ops::DerefMut;
+ use thin_vec::ThinVec;
struct BracketsVisitor {
failed: bool,
@@ -243,7 +244,7 @@ fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
}
fn noop_visit_expr<T: MutVisitor>(e: &mut Expr, vis: &mut T) {
- use rustc_ast::mut_visit::{noop_visit_expr, visit_thin_attrs};
+ use rustc_ast::mut_visit::{noop_visit_expr, visit_attrs};
match &mut e.kind {
ExprKind::AddrOf(BorrowKind::Raw, ..) => {}
ExprKind::Struct(expr) => {
@@ -261,7 +262,7 @@ fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
}
vis.visit_id(&mut e.id);
vis.visit_span(&mut e.span);
- visit_thin_attrs(&mut e.attrs, vis);
+ visit_attrs(&mut e.attrs, vis);
}
_ => noop_visit_expr(e, vis),
}
@@ -322,15 +323,15 @@ fn librustc_brackets(mut librustc_expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
// types yet. We'll look into comparing those in the future. For now
// focus on expressions appearing in other places.
fn visit_pat(&mut self, pat: &mut P<Pat>) {
- let _ = pat;
+ _ = pat;
}
fn visit_ty(&mut self, ty: &mut P<Ty>) {
- let _ = ty;
+ _ = ty;
}
fn visit_attribute(&mut self, attr: &mut Attribute) {
- let _ = attr;
+ _ = attr;
}
}
@@ -426,7 +427,7 @@ fn syn_brackets(syn_expr: syn::Expr) -> syn::Expr {
fn collect_exprs(file: syn::File) -> Vec<syn::Expr> {
use syn::fold::Fold;
use syn::punctuated::Punctuated;
- use syn::{token, Expr, ExprTuple, Path};
+ use syn::{token, ConstParam, Expr, ExprTuple, Path};
struct CollectExprs(Vec<Expr>);
impl Fold for CollectExprs {
@@ -447,6 +448,10 @@ fn collect_exprs(file: syn::File) -> Vec<syn::Expr> {
// Skip traversing into const generic path arguments
path
}
+
+ fn fold_const_param(&mut self, const_param: ConstParam) -> ConstParam {
+ const_param
+ }
}
let mut folder = CollectExprs(vec![]);
diff --git a/vendor/syn/tests/test_size.rs b/vendor/syn/tests/test_size.rs
index e172df2bc..02b0700f0 100644
--- a/vendor/syn/tests/test_size.rs
+++ b/vendor/syn/tests/test_size.rs
@@ -5,17 +5,17 @@ use syn::{Expr, Item, Lit, Pat, Type};
#[test]
fn test_expr_size() {
- assert_eq!(mem::size_of::<Expr>(), 280);
+ assert_eq!(mem::size_of::<Expr>(), 264);
}
#[test]
fn test_item_size() {
- assert_eq!(mem::size_of::<Item>(), 344);
+ assert_eq!(mem::size_of::<Item>(), 320);
}
#[test]
fn test_type_size() {
- assert_eq!(mem::size_of::<Type>(), 304);
+ assert_eq!(mem::size_of::<Type>(), 280);
}
#[test]
@@ -25,5 +25,5 @@ fn test_pat_size() {
#[test]
fn test_lit_size() {
- assert_eq!(mem::size_of::<Lit>(), 40);
+ assert_eq!(mem::size_of::<Lit>(), 32);
}
diff --git a/vendor/thiserror-impl/.cargo-checksum.json b/vendor/thiserror-impl/.cargo-checksum.json
index 002cf212c..e398ffbb5 100644
--- a/vendor/thiserror-impl/.cargo-checksum.json
+++ b/vendor/thiserror-impl/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3171e8d362ab2f3958292eb1862426b9206637c2941edbc482460f5e0b04c9d0","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"c7601e8394f5ee304365c520181f0dbeaa807ddaa71ce4a8618ea1a70f81b3b2","src/attr.rs":"d1fe75dde04cb8df6da4e1aaec5b38c2b0f634fa3432877993b3fec4cc08b6b5","src/expand.rs":"791000b41cc09250c04dbf2f7adc06f1254922986c86633471e934621ce31940","src/fmt.rs":"d63d39120c18712596f9f2a1715821148c2becd4d8bad5bc1b307210a84dbe98","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"7d023310cd3db670554ce108a6afd94e1ae3c55c83661d4b9fcebdf1865b9e4b","src/prop.rs":"6709932aee8f9d217f40cd644629c0ecb2f46d333ae8a1398e8d745534f4e028","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09"} \ No newline at end of file
+{"files":{"Cargo.toml":"af63bbe7a8ec50e29f44aa648a65afd05486852589b467030d28bbd7e0c878f4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","src/ast.rs":"c7601e8394f5ee304365c520181f0dbeaa807ddaa71ce4a8618ea1a70f81b3b2","src/attr.rs":"d1fe75dde04cb8df6da4e1aaec5b38c2b0f634fa3432877993b3fec4cc08b6b5","src/expand.rs":"8e2bc7ca24e8f8d9b179b792e772d3699154b750a08dcb942be298b7cc032563","src/fmt.rs":"d63d39120c18712596f9f2a1715821148c2becd4d8bad5bc1b307210a84dbe98","src/generics.rs":"2076cde22271be355a8131a77add4b93f83ab0af4317cd2df5471fffa4f95c66","src/lib.rs":"7d023310cd3db670554ce108a6afd94e1ae3c55c83661d4b9fcebdf1865b9e4b","src/prop.rs":"6709932aee8f9d217f40cd644629c0ecb2f46d333ae8a1398e8d745534f4e028","src/valid.rs":"ac95253944fd360d3578d0643a7baabb2cfa6bf9fbced7a6ce1f7b0529a3bb98"},"package":"982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"} \ No newline at end of file
diff --git a/vendor/thiserror-impl/Cargo.toml b/vendor/thiserror-impl/Cargo.toml
index c377ae01b..9f832394e 100644
--- a/vendor/thiserror-impl/Cargo.toml
+++ b/vendor/thiserror-impl/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "thiserror-impl"
-version = "1.0.33"
+version = "1.0.37"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "Implementation detail of the `thiserror` crate"
license = "MIT OR Apache-2.0"
diff --git a/vendor/thiserror-impl/src/expand.rs b/vendor/thiserror-impl/src/expand.rs
index f2f7116f2..43522096a 100644
--- a/vendor/thiserror-impl/src/expand.rs
+++ b/vendor/thiserror-impl/src/expand.rs
@@ -67,12 +67,12 @@ fn impl_struct(input: Struct) -> TokenStream {
let source_provide = if type_is_option(source_field.ty) {
quote_spanned! {source.span()=>
if let std::option::Option::Some(source) = &self.#source {
- source.as_dyn_error().provide(#demand);
+ source.thiserror_provide(#demand);
}
}
} else {
quote_spanned! {source.span()=>
- self.#source.as_dyn_error().provide(#demand);
+ self.#source.thiserror_provide(#demand);
}
};
let self_provide = if source == backtrace {
@@ -89,7 +89,7 @@ fn impl_struct(input: Struct) -> TokenStream {
})
};
quote! {
- use thiserror::__private::AsDynError;
+ use thiserror::__private::ThiserrorProvide;
#source_provide
#self_provide
}
@@ -259,12 +259,12 @@ fn impl_enum(input: Enum) -> TokenStream {
let source_provide = if type_is_option(source_field.ty) {
quote_spanned! {source.span()=>
if let std::option::Option::Some(source) = #varsource {
- source.as_dyn_error().provide(#demand);
+ source.thiserror_provide(#demand);
}
}
} else {
quote_spanned! {source.span()=>
- #varsource.as_dyn_error().provide(#demand);
+ #varsource.thiserror_provide(#demand);
}
};
let self_provide = if type_is_option(backtrace_field.ty) {
@@ -284,7 +284,7 @@ fn impl_enum(input: Enum) -> TokenStream {
#source: #varsource,
..
} => {
- use thiserror::__private::AsDynError;
+ use thiserror::__private::ThiserrorProvide;
#source_provide
#self_provide
}
@@ -298,17 +298,17 @@ fn impl_enum(input: Enum) -> TokenStream {
let source_provide = if type_is_option(source_field.ty) {
quote_spanned! {backtrace.span()=>
if let std::option::Option::Some(source) = #varsource {
- source.as_dyn_error().provide(#demand);
+ source.thiserror_provide(#demand);
}
}
} else {
quote_spanned! {backtrace.span()=>
- #varsource.as_dyn_error().provide(#demand);
+ #varsource.thiserror_provide(#demand);
}
};
quote! {
#ty::#ident {#backtrace: #varsource, ..} => {
- use thiserror::__private::AsDynError;
+ use thiserror::__private::ThiserrorProvide;
#source_provide
}
}
diff --git a/vendor/thiserror/.cargo-checksum.json b/vendor/thiserror/.cargo-checksum.json
index f62a31345..b82148e8f 100644
--- a/vendor/thiserror/.cargo-checksum.json
+++ b/vendor/thiserror/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"0de812f611be41d9b1962bdcb235479fed9d9d48eed22033fdb0c2cadbb0e602","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"f774d4cb12047fef7c65a86e00eb7299f9250e0bc1aa445d16f63162ec942551","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"3dd14cfcfe4a0ab8b1dd774e4ea0a0197989afe84e0687e73873b61cfa4347fa","src/display.rs":"63c492bfa8b8e9180ad5abcbe63c1173b4ad490c47ec33cac9a338f96c8f8e42","src/lib.rs":"62b459b2bf9b53647570511189ed4980a0aed10a9f49abec7c34cef53178a6b2","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"43323a073ca464b16e213869d3f459f07a0f9601f1516ec81371c825fb1ec8f2","tests/test_display.rs":"20fdc8903f06da3a698ef4377cccca26a71138ca6de67310c5bdb8a9fcb39d83","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"388402702a3be4ffcd0574d66733e8932bf7d5de37544a00ecb0e4f8d8246da4","tests/test_from.rs":"de1347e62069f826d8616b9e45ce6cccc3a8a8049cb51bd22d6763efe6118b0c","tests/test_generics.rs":"4f33747e3f62550d5af94687679af230ef92fbb3247ae4b41df46792a040e4dc","tests/test_lints.rs":"c17d79d77edfcdd4b8f6dcdcd1c70ad065cfbc747e1a618ac6343315d0b59ea4","tests/test_option.rs":"3a82af1ad206444b9955e3f2fda508d70f887ad0b7f7986bafc17496f63b07ab","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/from-backtrace-backtrace.rs":"1fd51c5a1f7f6b6ee676d9fc798b6276ef2ce75def33d07f0e4b7bbde3291859","tests/ui/from-backtrace-backtrace.stderr":"f9774e9dad51374501ef4a55fa2dacece4d1c70e29ca18761394bdb80a9a74da","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"40f47b286b770808a7dc5ec7970bc5cd501c9400f2e50049cf3258174929a9c1","tests/ui/source-enum-not-error.rs":"7c57c63b3ec37bc456738acea2e1038de5b0f32fe7e83984037d7ad1ed921737","tests/ui/source-enum-not-error.stderr":"44c974bf0b87431af78ccc7b4e18ebdc45135ca584a254960dff3f908ed862a8","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"8e087a059c6b69de44e149ab3b5bffc4f4c6c3cbbb13c235c9a3c7c264be3245","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57"} \ No newline at end of file
+{"files":{"Cargo.toml":"1d01528e44c86dd86ee07557c6cd89bd3cf37a2456e6f3430af299d84f304035","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"959ac4d4dc43ce39235613d853db8df4a0cfd79e262fc38aba43a98331643952","build.rs":"8b8d9cbf84b9a2fd108b49ecb4bae327da688d80b818acda9ee17170c788e193","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/aserror.rs":"c93bd9191f26a7599043b397e26822564d9bafaa339a19861182a9909e8a3811","src/display.rs":"63c492bfa8b8e9180ad5abcbe63c1173b4ad490c47ec33cac9a338f96c8f8e42","src/lib.rs":"3fcc3c1ab31a64215978b92e68c1421ec8c5fcb942e57eb35adb9cc07a865730","src/provide.rs":"b2f7a33f44f44a03e94f54cc4b79ba2dcc5fcf0fdf64b07cdd9588a6544c8d8e","tests/compiletest.rs":"022a8e400ef813d7ea1875b944549cee5125f6a995dc33e93b48cba3e1b57bd1","tests/test_backtrace.rs":"fd1f326bc23e6c1611a51bc43c1d5092b32ee18a1613abe20da0818e5729c0ed","tests/test_deprecated.rs":"7b80a10f090a3982da017556d3d71398abcead59afd8278c7b9d9b1f7b66c7b3","tests/test_display.rs":"20fdc8903f06da3a698ef4377cccca26a71138ca6de67310c5bdb8a9fcb39d83","tests/test_error.rs":"d06dca3c38f22d7ce4e27dadd6c0f78e5cefe3a2ebbc5fe44abc9ddd5ee1985f","tests/test_expr.rs":"388402702a3be4ffcd0574d66733e8932bf7d5de37544a00ecb0e4f8d8246da4","tests/test_from.rs":"de1347e62069f826d8616b9e45ce6cccc3a8a8049cb51bd22d6763efe6118b0c","tests/test_generics.rs":"4f33747e3f62550d5af94687679af230ef92fbb3247ae4b41df46792a040e4dc","tests/test_lints.rs":"c17d79d77edfcdd4b8f6dcdcd1c70ad065cfbc747e1a618ac6343315d0b59ea4","tests/test_option.rs":"3a82af1ad206444b9955e3f2fda508d70f887ad0b7f7986bafc17496f63b07ab","tests/test_path.rs":"ef5452c7e828a0179f5ace7e19f95b9762aa887caf10244adbfe36ded712c090","tests/test_source.rs":"f2f04f11bf8a709eddb1c68f113cda0c2be87e56800d6b9d991bedd545b4642f","tests/test_transparent.rs":"cd8d5be14d00d610a1782104bea6c013618501dab5c3625178ecfcf66e31f939","tests/ui/bad-field-attr.rs":"c5b567e3091969a01061843fb2d95c5e1aa3fa81edfeecdf416a84a6fba40aa8","tests/ui/bad-field-attr.stderr":"78f576d5ec66464a77f1cdf0f5bb7dcdf18f7f04f1165983a6239ec59d908ea3","tests/ui/concat-display.rs":"3995bd6b3bdd67df7bb16499775d89600c0dd20895633fe807396a64c117078d","tests/ui/concat-display.stderr":"256dfde61ee689ebe51588b135e2e030bdf95ba5adef1cb59f588c797bbdeef2","tests/ui/duplicate-enum-source.rs":"bfe28ce18042d446a76c7411aa233598211ce1157fdd3cb87bff3b3fa7c33131","tests/ui/duplicate-enum-source.stderr":"3d32fead420b27b4497be49080bc3b78f7f0ba339ead3de6c94e5dc20302c18f","tests/ui/duplicate-fmt.rs":"af53b66445bcce076a114376747f176b42c060a156563a41ccb638ae14c451fd","tests/ui/duplicate-fmt.stderr":"998bb121ce6f1595fd99529a7a1b06451b6bf476924337dce5524a83a7a5f1a1","tests/ui/duplicate-struct-source.rs":"f3d5f8e3d6fccfcdbb630db291353709583a920c6bf46f9f9de9966b67ea4c0f","tests/ui/duplicate-struct-source.stderr":"fb761d76668ac42357cf37b03c0abdbae5de0a828034990850291c9cb6ab766d","tests/ui/duplicate-transparent.rs":"41a9447e85f1a47027023442acde55c3d8610ec46d91b39bd43a42d7a004d747","tests/ui/duplicate-transparent.stderr":"4975abad43e973df158f18098d9bcb9dc39f8e75d3e733ed5d6620d1ee065c11","tests/ui/from-backtrace-backtrace.rs":"1fd51c5a1f7f6b6ee676d9fc798b6276ef2ce75def33d07f0e4b7bbde3291859","tests/ui/from-backtrace-backtrace.stderr":"f9774e9dad51374501ef4a55fa2dacece4d1c70e29ca18761394bdb80a9a74da","tests/ui/from-not-source.rs":"744a55aeffe11066830159ac023c33aaa5576e313b341fa24440ee13dfe3ac98","tests/ui/from-not-source.stderr":"525038e8b841707b927434cca4549168f73bd305faca17552a0d1fffa542ccc4","tests/ui/lifetime.rs":"e72e0391695e47fcd07edbf3819f114e468e2097086ec687781c7c8d6b4b7da7","tests/ui/lifetime.stderr":"d889a23f71324afe95dafc5f9d15337fbdbc9977cb8924f0cafe3a3becf4ced7","tests/ui/missing-fmt.rs":"bc9e2830e54c2474ff6c27a766ed3dee88d29e40f93f30e8d64d63233866c17d","tests/ui/missing-fmt.stderr":"9a20ccee9b660fe31a5b3199307b48580bb8305cb9ce33d97d3fc767a0cfc614","tests/ui/no-display.rs":"962245372272d23e9833311c15e73221b3c7da822a2ff90189613af56ffb5c2e","tests/ui/no-display.stderr":"40f47b286b770808a7dc5ec7970bc5cd501c9400f2e50049cf3258174929a9c1","tests/ui/source-enum-not-error.rs":"7c57c63b3ec37bc456738acea2e1038de5b0f32fe7e83984037d7ad1ed921737","tests/ui/source-enum-not-error.stderr":"1bb601243ff11d5de08c70edf3fd89d52b4a89fcd2a5c7775d1bc11d056ced1e","tests/ui/source-struct-not-error.rs":"09fb7713637242dca9192585a6daeb8d732dc1c1d0fa522b74f1c98618e6d949","tests/ui/source-struct-not-error.stderr":"9a1a04d606309c82eea59d1745c833189f0b4f237f0741a17dd62c11ce16642d","tests/ui/transparent-display.rs":"b3c59583eb64b0b5a246444456d03cf52d51bcdc08885023600dbb44fd87e5f2","tests/ui/transparent-display.stderr":"16d538914e0d92026bde4b4bec75660217da9ecc6b621d12d2eb81d33ed1d1da","tests/ui/transparent-enum-many.rs":"2a40a764fb4683bff57973eec61507a6c00f7d4d7a32da6e7bd0190c2e445434","tests/ui/transparent-enum-many.stderr":"f1d78c1d6d8edbef153420db4fb9ca3dc6076fa043b5b1bc0cd291daa417a3ea","tests/ui/transparent-enum-source.rs":"18f606a98ac0a53f08dc56f5f923b9cbe75d25ed34479c777b48dac305d5968c","tests/ui/transparent-enum-source.stderr":"1b2e0ac53951034575d43ec0396c4e2b3cfb272db2aef8d6baa13a7e1632cc84","tests/ui/transparent-struct-many.rs":"72c6b6c1a44c203d3bc68989b2f1ec092531ef75b745432824c3776c290326f6","tests/ui/transparent-struct-many.stderr":"7bd0536dbb54a0ce7d4a8e66ca7624a1b132d8a1d1e4fecca642ec77494ac01c","tests/ui/transparent-struct-source.rs":"863fa691ed7d27e8767da58d9ee11fd40d6642274b36338ca1074c07964ea2b3","tests/ui/transparent-struct-source.stderr":"267dab65929e67d32347fb467a00b43af931f8205d727d7671938580217fc70e","tests/ui/unexpected-field-fmt.rs":"29fba7b4d81c642ec8e47cfe053aa515acf9080a86d65e685363a48993becfe3","tests/ui/unexpected-field-fmt.stderr":"20731c4a08af04bed3ff513903adadd690b6bc532b15604557e7f25575a8338f","tests/ui/unexpected-struct-source.rs":"c6cbe882d622635c216feb8290b1bd536ce0ec4feee16bc087667a21b3641d5c","tests/ui/unexpected-struct-source.stderr":"7c8227513478f6cc09e8a28be337c8a0e758a06ca5978d774c91bd43c4a54043","tests/ui/union.rs":"331adff27cebd8b95b03b6742cc8247331fda1f961e1590ed39c8d39f50cf1d8","tests/ui/union.stderr":"5f67ad29753d6fb14bc03aef7d4a1f660ee7796e469c037efbf8b13456934ad3"},"package":"10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"} \ No newline at end of file
diff --git a/vendor/thiserror/Cargo.toml b/vendor/thiserror/Cargo.toml
index 5926572e3..2f060d6d8 100644
--- a/vendor/thiserror/Cargo.toml
+++ b/vendor/thiserror/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "thiserror"
-version = "1.0.33"
+version = "1.0.37"
authors = ["David Tolnay <dtolnay@gmail.com>"]
description = "derive(Error)"
documentation = "https://docs.rs/thiserror"
@@ -31,10 +31,10 @@ repository = "https://github.com/dtolnay/thiserror"
targets = ["x86_64-unknown-linux-gnu"]
[dependencies.thiserror-impl]
-version = "=1.0.33"
+version = "=1.0.37"
[dev-dependencies.anyhow]
-version = "1.0"
+version = "1.0.65"
[dev-dependencies.ref-cast]
version = "1.0"
diff --git a/vendor/thiserror/README.md b/vendor/thiserror/README.md
index 387a56e46..8f6b896de 100644
--- a/vendor/thiserror/README.md
+++ b/vendor/thiserror/README.md
@@ -124,8 +124,8 @@ pub enum DataStoreError {
}
```
-- The Error trait's `backtrace()` method is implemented to return whichever
- field has a type named `Backtrace`, if any.
+- The Error trait's `provide()` method is implemented to provide whichever field
+ has a type named `Backtrace`, if any, as a `std::backtrace::Backtrace`.
```rust
use std::backtrace::Backtrace;
@@ -138,8 +138,9 @@ pub enum DataStoreError {
```
- If a field is both a source (named `source`, or has `#[source]` or `#[from]`
- attribute) *and* is marked `#[backtrace]`, then the Error trait's
- `backtrace()` method is forwarded to the source's backtrace.
+ attribute) *and* is marked `#[backtrace]`, then the Error trait's `provide()`
+ method is forwarded to the source's `provide` so that both layers of the error
+ share the same backtrace.
```rust
#[derive(Error, Debug)]
@@ -165,6 +166,27 @@ pub enum DataStoreError {
}
```
+ Another use case is hiding implementation details of an error representation
+ behind an opaque error type, so that the representation is able to evolve
+ without breaking the crate's public API.
+
+ ```rust
+ // PublicError is public, but opaque and easy to keep compatible.
+ #[derive(Error, Debug)]
+ #[error(transparent)]
+ pub struct PublicError(#[from] ErrorRepr);
+
+ impl PublicError {
+ // Accessors for anything we do want to expose publicly.
+ }
+
+ // Private and free to change across minor version of the crate.
+ #[derive(Error, Debug)]
+ enum ErrorRepr {
+ ...
+ }
+ ```
+
- See also the [`anyhow`] library for a convenient single error type to use in
application code.
diff --git a/vendor/thiserror/build.rs b/vendor/thiserror/build.rs
new file mode 100644
index 000000000..004dfb015
--- /dev/null
+++ b/vendor/thiserror/build.rs
@@ -0,0 +1,66 @@
+use std::env;
+use std::fs;
+use std::path::Path;
+use std::process::{Command, ExitStatus, Stdio};
+use std::str;
+
+// This code exercises the surface area that we expect of the Provider API. If
+// the current toolchain is able to compile it, then thiserror is able to use
+// providers for backtrace support.
+const PROBE: &str = r#"
+ #![feature(provide_any)]
+
+ use std::any::{Demand, Provider};
+
+ fn _f<'a, P: Provider>(p: &'a P, demand: &mut Demand<'a>) {
+ p.provide(demand);
+ }
+"#;
+
+fn main() {
+ match compile_probe() {
+ Some(status) if status.success() => println!("cargo:rustc-cfg=provide_any"),
+ _ => {}
+ }
+}
+
+fn compile_probe() -> Option<ExitStatus> {
+ let rustc = env::var_os("RUSTC")?;
+ let out_dir = env::var_os("OUT_DIR")?;
+ let probefile = Path::new(&out_dir).join("probe.rs");
+ fs::write(&probefile, PROBE).ok()?;
+
+ // Make sure to pick up Cargo rustc configuration.
+ let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER") {
+ let mut cmd = Command::new(wrapper);
+ // The wrapper's first argument is supposed to be the path to rustc.
+ cmd.arg(rustc);
+ cmd
+ } else {
+ Command::new(rustc)
+ };
+
+ cmd.stderr(Stdio::null())
+ .arg("--edition=2018")
+ .arg("--crate-name=thiserror_build")
+ .arg("--crate-type=lib")
+ .arg("--emit=metadata")
+ .arg("--out-dir")
+ .arg(out_dir)
+ .arg(probefile);
+
+ if let Some(target) = env::var_os("TARGET") {
+ cmd.arg("--target").arg(target);
+ }
+
+ // If Cargo wants to set RUSTFLAGS, use that.
+ if let Ok(rustflags) = env::var("CARGO_ENCODED_RUSTFLAGS") {
+ if !rustflags.is_empty() {
+ for arg in rustflags.split('\x1f') {
+ cmd.arg(arg);
+ }
+ }
+ }
+
+ cmd.status().ok()
+}
diff --git a/vendor/thiserror/src/aserror.rs b/vendor/thiserror/src/aserror.rs
index c036b7b09..5fea84ef8 100644
--- a/vendor/thiserror/src/aserror.rs
+++ b/vendor/thiserror/src/aserror.rs
@@ -1,7 +1,7 @@
use std::error::Error;
use std::panic::UnwindSafe;
-pub trait AsDynError<'a> {
+pub trait AsDynError<'a>: Sealed {
fn as_dyn_error(&self) -> &(dyn Error + 'a);
}
@@ -39,3 +39,10 @@ impl<'a> AsDynError<'a> for dyn Error + Send + Sync + UnwindSafe + 'a {
self
}
}
+
+pub trait Sealed {}
+impl<'a, T: Error + 'a> Sealed for T {}
+impl<'a> Sealed for dyn Error + 'a {}
+impl<'a> Sealed for dyn Error + Send + 'a {}
+impl<'a> Sealed for dyn Error + Send + Sync + 'a {}
+impl<'a> Sealed for dyn Error + Send + Sync + UnwindSafe + 'a {}
diff --git a/vendor/thiserror/src/lib.rs b/vendor/thiserror/src/lib.rs
index 247199ffd..aae6552d0 100644
--- a/vendor/thiserror/src/lib.rs
+++ b/vendor/thiserror/src/lib.rs
@@ -146,8 +146,9 @@
//! # }
//! ```
//!
-//! - The Error trait's `backtrace()` method is implemented to return whichever
-//! field has a type named `Backtrace`, if any.
+//! - The Error trait's `provide()` method is implemented to provide whichever
+//! field has a type named `Backtrace`, if any, as a
+//! `std::backtrace::Backtrace`.
//!
//! ```rust
//! # const IGNORE: &str = stringify! {
@@ -163,7 +164,8 @@
//!
//! - If a field is both a source (named `source`, or has `#[source]` or
//! `#[from]` attribute) *and* is marked `#[backtrace]`, then the Error
-//! trait's `backtrace()` method is forwarded to the source's backtrace.
+//! trait's `provide()` method is forwarded to the source's `provide` so that
+//! both layers of the error share the same backtrace.
//!
//! ```rust
//! # const IGNORE: &str = stringify! {
@@ -196,6 +198,31 @@
//! }
//! ```
//!
+//! Another use case is hiding implementation details of an error
+//! representation behind an opaque error type, so that the representation is
+//! able to evolve without breaking the crate's public API.
+//!
+//! ```
+//! # use thiserror::Error;
+//! #
+//! // PublicError is public, but opaque and easy to keep compatible.
+//! #[derive(Error, Debug)]
+//! #[error(transparent)]
+//! pub struct PublicError(#[from] ErrorRepr);
+//!
+//! impl PublicError {
+//! // Accessors for anything we do want to expose publicly.
+//! }
+//!
+//! // Private and free to change across minor version of the crate.
+//! #[derive(Error, Debug)]
+//! enum ErrorRepr {
+//! # /*
+//! ...
+//! # */
+//! }
+//! ```
+//!
//! - See also the [`anyhow`] library for a convenient single error type to use
//! in application code.
//!
@@ -206,10 +233,14 @@
clippy::doc_markdown,
clippy::module_name_repetitions,
clippy::return_self_not_must_use,
+ clippy::wildcard_imports,
)]
+#![cfg_attr(provide_any, feature(provide_any))]
mod aserror;
mod display;
+#[cfg(provide_any)]
+mod provide;
pub use thiserror_impl::*;
@@ -218,4 +249,6 @@ pub use thiserror_impl::*;
pub mod __private {
pub use crate::aserror::AsDynError;
pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
+ #[cfg(provide_any)]
+ pub use crate::provide::ThiserrorProvide;
}
diff --git a/vendor/thiserror/src/provide.rs b/vendor/thiserror/src/provide.rs
new file mode 100644
index 000000000..524e7435d
--- /dev/null
+++ b/vendor/thiserror/src/provide.rs
@@ -0,0 +1,15 @@
+use std::any::{Demand, Provider};
+
+pub trait ThiserrorProvide: Sealed {
+ fn thiserror_provide<'a>(&'a self, demand: &mut Demand<'a>);
+}
+
+impl<T: Provider + ?Sized> ThiserrorProvide for T {
+ #[inline]
+ fn thiserror_provide<'a>(&'a self, demand: &mut Demand<'a>) {
+ self.provide(demand);
+ }
+}
+
+pub trait Sealed {}
+impl<T: Provider + ?Sized> Sealed for T {}
diff --git a/vendor/thiserror/tests/test_backtrace.rs b/vendor/thiserror/tests/test_backtrace.rs
index 052c6f481..43f68b8b7 100644
--- a/vendor/thiserror/tests/test_backtrace.rs
+++ b/vendor/thiserror/tests/test_backtrace.rs
@@ -21,6 +21,7 @@ pub mod structs {
use super::{Inner, InnerBacktrace};
use std::any;
use std::backtrace::Backtrace;
+ use std::error::Error;
use std::sync::Arc;
use thiserror::Error;
@@ -86,6 +87,20 @@ pub mod structs {
backtrace: Arc<Backtrace>,
}
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct AnyhowBacktrace {
+ #[backtrace]
+ source: anyhow::Error,
+ }
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ pub struct BoxDynErrorBacktrace {
+ #[backtrace]
+ source: Box<dyn Error>,
+ }
+
#[test]
fn test_backtrace() {
let error = PlainBacktrace {
@@ -121,6 +136,37 @@ pub mod structs {
let error = ArcBacktraceFrom::from(Inner);
assert!(any::request_ref::<Backtrace>(&error).is_some());
+
+ let error = AnyhowBacktrace {
+ source: anyhow::Error::msg("..."),
+ };
+ assert!(any::request_ref::<Backtrace>(&error).is_some());
+
+ let error = BoxDynErrorBacktrace {
+ source: Box::new(PlainBacktrace {
+ backtrace: Backtrace::capture(),
+ }),
+ };
+ assert!(any::request_ref::<Backtrace>(&error).is_some());
+ }
+
+ // https://github.com/dtolnay/thiserror/issues/185 -- std::error::Error and
+ // std::any::Provide both have a method called 'provide', so directly
+ // calling it from generated code could be ambiguous.
+ #[test]
+ fn test_provide_name_collision() {
+ use std::any::Provider;
+
+ #[derive(Error, Debug)]
+ #[error("...")]
+ struct MyError {
+ #[source]
+ #[backtrace]
+ x: std::io::Error,
+ }
+
+ let _: dyn Error;
+ let _: dyn Provider;
}
}
diff --git a/vendor/thiserror/tests/test_deprecated.rs b/vendor/thiserror/tests/test_deprecated.rs
new file mode 100644
index 000000000..5524666ab
--- /dev/null
+++ b/vendor/thiserror/tests/test_deprecated.rs
@@ -0,0 +1,10 @@
+#![deny(deprecated, clippy::all, clippy::pedantic)]
+
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum Error {
+ #[deprecated]
+ #[error("...")]
+ Deprecated,
+}
diff --git a/vendor/thiserror/tests/ui/source-enum-not-error.stderr b/vendor/thiserror/tests/ui/source-enum-not-error.stderr
index da10c6e77..29ee54600 100644
--- a/vendor/thiserror/tests/ui/source-enum-not-error.stderr
+++ b/vendor/thiserror/tests/ui/source-enum-not-error.stderr
@@ -4,7 +4,7 @@ error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but it
4 | pub struct NotError;
| -------------------
| |
- | doesn't satisfy `NotError: AsDynError`
+ | doesn't satisfy `NotError: AsDynError<'_>`
| doesn't satisfy `NotError: std::error::Error`
...
10 | source: NotError,
@@ -12,9 +12,9 @@ error[E0599]: the method `as_dyn_error` exists for reference `&NotError`, but it
|
= note: the following trait bounds were not satisfied:
`NotError: std::error::Error`
- which is required by `NotError: AsDynError`
+ which is required by `NotError: AsDynError<'_>`
`&NotError: std::error::Error`
- which is required by `&NotError: AsDynError`
+ which is required by `&NotError: AsDynError<'_>`
note: the following trait must be implemented
--> $RUST/core/src/error.rs
|
diff --git a/vendor/thiserror/tests/ui/source-struct-not-error.stderr b/vendor/thiserror/tests/ui/source-struct-not-error.stderr
index cc0e67aca..efa40281d 100644
--- a/vendor/thiserror/tests/ui/source-struct-not-error.stderr
+++ b/vendor/thiserror/tests/ui/source-struct-not-error.stderr
@@ -5,7 +5,7 @@ error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its tr
| ---------------
| |
| method `as_dyn_error` not found for this struct
- | doesn't satisfy `NotError: AsDynError`
+ | doesn't satisfy `NotError: AsDynError<'_>`
| doesn't satisfy `NotError: std::error::Error`
...
9 | source: NotError,
@@ -13,7 +13,7 @@ error[E0599]: the method `as_dyn_error` exists for struct `NotError`, but its tr
|
= note: the following trait bounds were not satisfied:
`NotError: std::error::Error`
- which is required by `NotError: AsDynError`
+ which is required by `NotError: AsDynError<'_>`
note: the following trait must be implemented
--> $RUST/core/src/error.rs
|
diff --git a/vendor/tracing-attributes/.cargo-checksum.json b/vendor/tracing-attributes/.cargo-checksum.json
index 995155f68..e29c0854b 100644
--- a/vendor/tracing-attributes/.cargo-checksum.json
+++ b/vendor/tracing-attributes/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"daa6621db253ddaaa095d297d0de2be41b03831a3992f2f9a5107749a689983e","Cargo.toml":"70c8c7dba6890f42c7830651ec9847c0e22b4c0987024d076d4abb3801f26bc8","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"7484033338a94e5ce23f1b281e1bdef1bae590c2329bd9b4d192ce66702e3a31","src/attr.rs":"4d26dad70c765fff3d4677ebe8e71b63599d67ceba5c48dbcb204d247b5394ce","src/expand.rs":"e6b81defa4ed98d71466ede6eb5a8f613cd0d33750b2e1274265467b85756362","src/lib.rs":"4400f3c00b7b4daf9cd61bec3e1f5d794c3d4b131667252a43c95a40041b6711","tests/async_fn.rs":"74126e6027bc9cb6e5e3d5d0e3b2debd5c808c737d25b90303b8e3ca878a3667","tests/destructuring.rs":"26b9800678bad09e06512a113a54556e2fac3ecb15a18dcccefe105fb8911c26","tests/err.rs":"3beb5f065e57a578825c383a56b9d64fb89794a508018bf36e16f113557909b8","tests/fields.rs":"3882bd4e744d6b492f59beac7475e8bf4ff4ca8ad85c6951c305a22c78e75fae","tests/follows_from.rs":"5bc856923e87b34e0558959149118238fe668ac621f1748cc444c21c90a86647","tests/instrument.rs":"9118eb6971d19a6b8d301bb4512b0fda909404a21e14edbef6b01db094cd8aaf","tests/levels.rs":"80ffb684163a4d28c69c40e31a82609ac02daf922086bab8247bca125aec3c69","tests/names.rs":"5afd6c4d526588bcea3141c130a45a21872956495b6868a01b44ddff57749827","tests/parents.rs":"673d3f81eed6ba433f685ec53fd007c5dd957b97d32499d7ea1537e1f289cb2e","tests/ret.rs":"083b4ca456d766c469b2fff7608b59524b422941e5c5e84f07c1ce0d7b345c7a","tests/targets.rs":"95ce1ce1e2d29794062c5b3429d91c1bfaba5813251d5d8440c12cb2db6e11bf"},"package":"11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"7c292985e41b0fd9c89d32bd15594b76bb3109ff96177af7461d1a0d3ea48574","Cargo.toml":"1c272401b940ef2fd88638a6228af02c14e3d47d4b592ee5c445f7470a0d1763","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"aae710a2c0c4ade929a84f8f3d9f98fcb9ad1c1e9e52ae0b0393db9f353f6248","src/attr.rs":"4d26dad70c765fff3d4677ebe8e71b63599d67ceba5c48dbcb204d247b5394ce","src/expand.rs":"f070e38eb3526c4c50e98cfafb2c26e50c7170f27d0bd716838a29777c1174cd","src/lib.rs":"14803c868525f6ae95b846ce2f369a47d50b2befba336335354867cf2a1b2455","tests/async_fn.rs":"6ae845ab6c508f9f2d1ea7ec3855971e8cff85afdae326593089d0a53c9c6dcf","tests/destructuring.rs":"26b9800678bad09e06512a113a54556e2fac3ecb15a18dcccefe105fb8911c26","tests/err.rs":"3beb5f065e57a578825c383a56b9d64fb89794a508018bf36e16f113557909b8","tests/fields.rs":"3882bd4e744d6b492f59beac7475e8bf4ff4ca8ad85c6951c305a22c78e75fae","tests/follows_from.rs":"5bc856923e87b34e0558959149118238fe668ac621f1748cc444c21c90a86647","tests/instrument.rs":"e3a90f2aef0d2f56c2c25018e2fbacf518e90ef6810930941f86740279252d03","tests/levels.rs":"80ffb684163a4d28c69c40e31a82609ac02daf922086bab8247bca125aec3c69","tests/names.rs":"5afd6c4d526588bcea3141c130a45a21872956495b6868a01b44ddff57749827","tests/parents.rs":"673d3f81eed6ba433f685ec53fd007c5dd957b97d32499d7ea1537e1f289cb2e","tests/ret.rs":"083b4ca456d766c469b2fff7608b59524b422941e5c5e84f07c1ce0d7b345c7a","tests/targets.rs":"95ce1ce1e2d29794062c5b3429d91c1bfaba5813251d5d8440c12cb2db6e11bf","tests/ui.rs":"c73c70fe7371998df077862092f40df7210b13496e119ab4e657a1848e42ab30","tests/ui/async_instrument.rs":"00fcde05841e8f9f6cc6f9434f8cc4baed5cf6e3ca73e8faddccbdace14e9485","tests/ui/async_instrument.stderr":"6f0457b5cd035a9bc82f5e98fb6d3a74177336ec6a19ba2e7cb9dbf3e67c3aff"},"package":"4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"} \ No newline at end of file
diff --git a/vendor/tracing-attributes/CHANGELOG.md b/vendor/tracing-attributes/CHANGELOG.md
index 4fcc81f29..42cb09b6a 100644
--- a/vendor/tracing-attributes/CHANGELOG.md
+++ b/vendor/tracing-attributes/CHANGELOG.md
@@ -1,3 +1,24 @@
+# 0.1.23 (October 6, 2022)
+
+This release of `tracing-attributes` fixes a bug where compiler diagnostic spans
+for type errors in `#[instrument]`ed `async fn`s have the location of the
+`#[instrument]` attribute rather than the location of the actual error, and a
+bug where inner attributes in `#[instrument]`ed functions would cause a compiler
+error.
+### Fixed
+
+- Fix incorrect handling of inner attributes in `#[instrument]`ed functions ([#2307])
+- Add fake return to improve spans generated for type errors in `async fn`s ([#2270])
+- Updated `syn` dependency to fix compilation with `-Z minimal-versions`
+ ([#2246])
+
+Thanks to new contributors @compiler-errors and @e-nomem, as well as @CAD97, for
+contributing to this release!
+
+[#2307]: https://github.com/tokio-rs/tracing/pull/2307
+[#2270]: https://github.com/tokio-rs/tracing/pull/2270
+[#2246]: https://github.com/tokio-rs/tracing/pull/2246
+
# 0.1.22 (July 1, 2022)
This release fixes an issue where using the `err` or `ret` arguments to
diff --git a/vendor/tracing-attributes/Cargo.toml b/vendor/tracing-attributes/Cargo.toml
index 3ecaba6fc..5639de0b3 100644
--- a/vendor/tracing-attributes/Cargo.toml
+++ b/vendor/tracing-attributes/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.49.0"
name = "tracing-attributes"
-version = "0.1.22"
+version = "0.1.23"
authors = [
"Tokio Contributors <team@tokio.rs>",
"Eliza Weisman <eliza@buoyant.io>",
@@ -49,7 +49,7 @@ version = "1"
version = "1"
[dependencies.syn]
-version = "1.0.43"
+version = "1.0.98"
features = [
"full",
"parsing",
@@ -63,21 +63,27 @@ features = [
default-features = false
[dev-dependencies.async-trait]
-version = "0.1.44"
+version = "0.1.56"
+
+[dev-dependencies.rustversion]
+version = "1.0.9"
[dev-dependencies.tokio-test]
version = "0.3.0"
[dev-dependencies.tracing]
-version = "0.1"
+version = "0.1.35"
[dev-dependencies.tracing-core]
-version = "0.1"
+version = "0.1.28"
[dev-dependencies.tracing-subscriber]
-version = "0.3"
+version = "0.3.0"
features = ["env-filter"]
+[dev-dependencies.trybuild]
+version = "1.0.64"
+
[features]
async-await = []
diff --git a/vendor/tracing-attributes/README.md b/vendor/tracing-attributes/README.md
index 636179468..356b511f2 100644
--- a/vendor/tracing-attributes/README.md
+++ b/vendor/tracing-attributes/README.md
@@ -18,7 +18,7 @@ Macro attributes for application-level tracing.
[crates-badge]: https://img.shields.io/crates/v/tracing-attributes.svg
[crates-url]: https://crates.io/crates/tracing-attributes
[docs-badge]: https://docs.rs/tracing-attributes/badge.svg
-[docs-url]: https://docs.rs/tracing-attributes/0.1.22
+[docs-url]: https://docs.rs/tracing-attributes/0.1.23
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing_attributes
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -47,7 +47,7 @@ First, add this to your `Cargo.toml`:
```toml
[dependencies]
-tracing-attributes = "0.1.22"
+tracing-attributes = "0.1.23"
```
diff --git a/vendor/tracing-attributes/src/expand.rs b/vendor/tracing-attributes/src/expand.rs
index 81ee6ed90..7005b4423 100644
--- a/vendor/tracing-attributes/src/expand.rs
+++ b/vendor/tracing-attributes/src/expand.rs
@@ -2,15 +2,16 @@ use std::iter;
use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
+use syn::visit_mut::VisitMut;
use syn::{
punctuated::Punctuated, spanned::Spanned, Block, Expr, ExprAsync, ExprCall, FieldPat, FnArg,
Ident, Item, ItemFn, Pat, PatIdent, PatReference, PatStruct, PatTuple, PatTupleStruct, PatType,
- Path, Signature, Stmt, Token, TypePath,
+ Path, ReturnType, Signature, Stmt, Token, Type, TypePath,
};
use crate::{
attr::{Field, Fields, FormatMode, InstrumentArgs},
- MaybeItemFnRef,
+ MaybeItemFn, MaybeItemFnRef,
};
/// Given an existing function, generate an instrumented version of that function
@@ -18,20 +19,21 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
input: MaybeItemFnRef<'a, B>,
args: InstrumentArgs,
instrumented_function_name: &str,
- self_type: Option<&syn::TypePath>,
+ self_type: Option<&TypePath>,
) -> proc_macro2::TokenStream {
// these are needed ahead of time, as ItemFn contains the function body _and_
// isn't representable inside a quote!/quote_spanned! macro
// (Syn's ToTokens isn't implemented for ItemFn)
let MaybeItemFnRef {
- attrs,
+ outer_attrs,
+ inner_attrs,
vis,
sig,
block,
} = input;
let Signature {
- output: return_type,
+ output,
inputs: params,
unsafety,
asyncness,
@@ -49,8 +51,35 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
let warnings = args.warnings();
+ let (return_type, return_span) = if let ReturnType::Type(_, return_type) = &output {
+ (erase_impl_trait(return_type), return_type.span())
+ } else {
+ // Point at function name if we don't have an explicit return type
+ (syn::parse_quote! { () }, ident.span())
+ };
+ // Install a fake return statement as the first thing in the function
+ // body, so that we eagerly infer that the return type is what we
+ // declared in the async fn signature.
+ // The `#[allow(..)]` is given because the return statement is
+ // unreachable, but does affect inference, so it needs to be written
+ // exactly that way for it to do its magic.
+ let fake_return_edge = quote_spanned! {return_span=>
+ #[allow(unreachable_code, clippy::diverging_sub_expression, clippy::let_unit_value)]
+ if false {
+ let __tracing_attr_fake_return: #return_type =
+ unreachable!("this is just for type inference, and is unreachable code");
+ return __tracing_attr_fake_return;
+ }
+ };
+ let block = quote! {
+ {
+ #fake_return_edge
+ #block
+ }
+ };
+
let body = gen_block(
- block,
+ &block,
params,
asyncness.is_some(),
args,
@@ -59,10 +88,11 @@ pub(crate) fn gen_function<'a, B: ToTokens + 'a>(
);
quote!(
- #(#attrs) *
- #vis #constness #unsafety #asyncness #abi fn #ident<#gen_params>(#params) #return_type
+ #(#outer_attrs) *
+ #vis #constness #unsafety #asyncness #abi fn #ident<#gen_params>(#params) #output
#where_clause
{
+ #(#inner_attrs) *
#warnings
#body
}
@@ -76,7 +106,7 @@ fn gen_block<B: ToTokens>(
async_context: bool,
mut args: InstrumentArgs,
instrumented_function_name: &str,
- self_type: Option<&syn::TypePath>,
+ self_type: Option<&TypePath>,
) -> proc_macro2::TokenStream {
// generate the span's name
let span_name = args
@@ -393,11 +423,11 @@ impl RecordType {
"Wrapping",
];
- /// Parse `RecordType` from [syn::Type] by looking up
+ /// Parse `RecordType` from [Type] by looking up
/// the [RecordType::TYPES_FOR_VALUE] array.
- fn parse_from_ty(ty: &syn::Type) -> Self {
+ fn parse_from_ty(ty: &Type) -> Self {
match ty {
- syn::Type::Path(syn::TypePath { path, .. })
+ Type::Path(TypePath { path, .. })
if path
.segments
.iter()
@@ -410,9 +440,7 @@ impl RecordType {
{
RecordType::Value
}
- syn::Type::Reference(syn::TypeReference { elem, .. }) => {
- RecordType::parse_from_ty(&*elem)
- }
+ Type::Reference(syn::TypeReference { elem, .. }) => RecordType::parse_from_ty(elem),
_ => RecordType::Debug,
}
}
@@ -471,7 +499,7 @@ pub(crate) struct AsyncInfo<'block> {
// statement that must be patched
source_stmt: &'block Stmt,
kind: AsyncKind<'block>,
- self_type: Option<syn::TypePath>,
+ self_type: Option<TypePath>,
input: &'block ItemFn,
}
@@ -606,11 +634,11 @@ impl<'block> AsyncInfo<'block> {
if ident == "_self" {
let mut ty = *ty.ty.clone();
// extract the inner type if the argument is "&self" or "&mut self"
- if let syn::Type::Reference(syn::TypeReference { elem, .. }) = ty {
+ if let Type::Reference(syn::TypeReference { elem, .. }) = ty {
ty = *elem;
}
- if let syn::Type::Path(tp) = ty {
+ if let Type::Path(tp) = ty {
self_type = Some(tp);
break;
}
@@ -631,7 +659,7 @@ impl<'block> AsyncInfo<'block> {
self,
args: InstrumentArgs,
instrumented_function_name: &str,
- ) -> proc_macro::TokenStream {
+ ) -> Result<proc_macro::TokenStream, syn::Error> {
// let's rewrite some statements!
let mut out_stmts: Vec<TokenStream> = self
.input
@@ -652,12 +680,15 @@ impl<'block> AsyncInfo<'block> {
// instrument the future by rewriting the corresponding statement
out_stmts[iter] = match self.kind {
// `Box::pin(immediately_invoked_async_fn())`
- AsyncKind::Function(fun) => gen_function(
- fun.into(),
- args,
- instrumented_function_name,
- self.self_type.as_ref(),
- ),
+ AsyncKind::Function(fun) => {
+ let fun = MaybeItemFn::from(fun.clone());
+ gen_function(
+ fun.as_ref(),
+ args,
+ instrumented_function_name,
+ self.self_type.as_ref(),
+ )
+ }
// `async move { ... }`, optionally pinned
AsyncKind::Async {
async_expr,
@@ -688,13 +719,13 @@ impl<'block> AsyncInfo<'block> {
let vis = &self.input.vis;
let sig = &self.input.sig;
let attrs = &self.input.attrs;
- quote!(
+ Ok(quote!(
#(#attrs) *
#vis #sig {
#(#out_stmts) *
}
)
- .into()
+ .into())
}
}
@@ -722,7 +753,7 @@ struct IdentAndTypesRenamer<'a> {
idents: Vec<(Ident, Ident)>,
}
-impl<'a> syn::visit_mut::VisitMut for IdentAndTypesRenamer<'a> {
+impl<'a> VisitMut for IdentAndTypesRenamer<'a> {
// we deliberately compare strings because we want to ignore the spans
// If we apply clippy's lint, the behavior changes
#[allow(clippy::cmp_owned)]
@@ -734,11 +765,11 @@ impl<'a> syn::visit_mut::VisitMut for IdentAndTypesRenamer<'a> {
}
}
- fn visit_type_mut(&mut self, ty: &mut syn::Type) {
+ fn visit_type_mut(&mut self, ty: &mut Type) {
for (type_name, new_type) in &self.types {
- if let syn::Type::Path(TypePath { path, .. }) = ty {
+ if let Type::Path(TypePath { path, .. }) = ty {
if path_to_string(path) == *type_name {
- *ty = syn::Type::Path(new_type.clone());
+ *ty = Type::Path(new_type.clone());
}
}
}
@@ -751,10 +782,33 @@ struct AsyncTraitBlockReplacer<'a> {
patched_block: Block,
}
-impl<'a> syn::visit_mut::VisitMut for AsyncTraitBlockReplacer<'a> {
+impl<'a> VisitMut for AsyncTraitBlockReplacer<'a> {
fn visit_block_mut(&mut self, i: &mut Block) {
if i == self.block {
*i = self.patched_block.clone();
}
}
}
+
+// Replaces any `impl Trait` with `_` so it can be used as the type in
+// a `let` statement's LHS.
+struct ImplTraitEraser;
+
+impl VisitMut for ImplTraitEraser {
+ fn visit_type_mut(&mut self, t: &mut Type) {
+ if let Type::ImplTrait(..) = t {
+ *t = syn::TypeInfer {
+ underscore_token: Token![_](t.span()),
+ }
+ .into();
+ } else {
+ syn::visit_mut::visit_type_mut(self, t);
+ }
+ }
+}
+
+fn erase_impl_trait(ty: &Type) -> Type {
+ let mut ty = ty.clone();
+ ImplTraitEraser.visit_type_mut(&mut ty);
+ ty
+}
diff --git a/vendor/tracing-attributes/src/lib.rs b/vendor/tracing-attributes/src/lib.rs
index 49b3c794a..f5974e4e5 100644
--- a/vendor/tracing-attributes/src/lib.rs
+++ b/vendor/tracing-attributes/src/lib.rs
@@ -16,7 +16,7 @@
//!
//! ```toml
//! [dependencies]
-//! tracing-attributes = "0.1.22"
+//! tracing-attributes = "0.1.23"
//! ```
//!
//! The [`#[instrument]`][instrument] attribute can now be added to a function
@@ -52,7 +52,7 @@
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
-#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.22")]
+#![doc(html_root_url = "https://docs.rs/tracing-attributes/0.1.23")]
#![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/"
@@ -86,7 +86,7 @@ extern crate proc_macro;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::parse::{Parse, ParseStream};
-use syn::{Attribute, Block, ItemFn, Signature, Visibility};
+use syn::{Attribute, ItemFn, Signature, Visibility};
mod attr;
mod expand;
@@ -587,11 +587,13 @@ fn instrument_precise(
// check for async_trait-like patterns in the block, and instrument
// the future instead of the wrapper
if let Some(async_like) = expand::AsyncInfo::from_fn(&input) {
- return Ok(async_like.gen_async(args, instrumented_function_name.as_str()));
+ return async_like.gen_async(args, instrumented_function_name.as_str());
}
+ let input = MaybeItemFn::from(input);
+
Ok(expand::gen_function(
- (&input).into(),
+ input.as_ref(),
args,
instrumented_function_name.as_str(),
None,
@@ -603,7 +605,8 @@ fn instrument_precise(
/// which's block is just a `TokenStream` (it may contain invalid code).
#[derive(Debug, Clone)]
struct MaybeItemFn {
- attrs: Vec<Attribute>,
+ outer_attrs: Vec<Attribute>,
+ inner_attrs: Vec<Attribute>,
vis: Visibility,
sig: Signature,
block: TokenStream,
@@ -612,7 +615,8 @@ struct MaybeItemFn {
impl MaybeItemFn {
fn as_ref(&self) -> MaybeItemFnRef<'_, TokenStream> {
MaybeItemFnRef {
- attrs: &self.attrs,
+ outer_attrs: &self.outer_attrs,
+ inner_attrs: &self.inner_attrs,
vis: &self.vis,
sig: &self.sig,
block: &self.block,
@@ -624,12 +628,14 @@ impl MaybeItemFn {
/// (just like `ItemFn`, but skips parsing the body).
impl Parse for MaybeItemFn {
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
- let attrs = input.call(syn::Attribute::parse_outer)?;
+ let outer_attrs = input.call(Attribute::parse_outer)?;
let vis: Visibility = input.parse()?;
let sig: Signature = input.parse()?;
+ let inner_attrs = input.call(Attribute::parse_inner)?;
let block: TokenStream = input.parse()?;
Ok(Self {
- attrs,
+ outer_attrs,
+ inner_attrs,
vis,
sig,
block,
@@ -637,23 +643,35 @@ impl Parse for MaybeItemFn {
}
}
+impl From<ItemFn> for MaybeItemFn {
+ fn from(
+ ItemFn {
+ attrs,
+ vis,
+ sig,
+ block,
+ }: ItemFn,
+ ) -> Self {
+ let (outer_attrs, inner_attrs) = attrs
+ .into_iter()
+ .partition(|attr| attr.style == syn::AttrStyle::Outer);
+ Self {
+ outer_attrs,
+ inner_attrs,
+ vis,
+ sig,
+ block: block.to_token_stream(),
+ }
+ }
+}
+
/// A generic reference type for `MaybeItemFn`,
/// that takes a generic block type `B` that implements `ToTokens` (eg. `TokenStream`, `Block`).
#[derive(Debug, Clone)]
struct MaybeItemFnRef<'a, B: ToTokens> {
- attrs: &'a Vec<Attribute>,
+ outer_attrs: &'a Vec<Attribute>,
+ inner_attrs: &'a Vec<Attribute>,
vis: &'a Visibility,
sig: &'a Signature,
block: &'a B,
}
-
-impl<'a> From<&'a ItemFn> for MaybeItemFnRef<'a, Box<Block>> {
- fn from(val: &'a ItemFn) -> Self {
- MaybeItemFnRef {
- attrs: &val.attrs,
- vis: &val.vis,
- sig: &val.sig,
- block: &val.block,
- }
- }
-}
diff --git a/vendor/tracing-attributes/tests/async_fn.rs b/vendor/tracing-attributes/tests/async_fn.rs
index 7e27fb5ce..c89963672 100644
--- a/vendor/tracing-attributes/tests/async_fn.rs
+++ b/vendor/tracing-attributes/tests/async_fn.rs
@@ -14,6 +14,7 @@ async fn test_async_fn(polls: usize) -> Result<(), ()> {
// Reproduces a compile error when returning an `impl Trait` from an
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
+#[allow(dead_code)] // this is just here to test whether it compiles.
#[instrument]
async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
let n = n;
@@ -22,6 +23,7 @@ async fn test_ret_impl_trait(n: i32) -> Result<impl Iterator<Item = i32>, ()> {
// Reproduces a compile error when returning an `impl Trait` from an
// instrumented async fn (see https://github.com/tokio-rs/tracing/issues/1615)
+#[allow(dead_code)] // this is just here to test whether it compiles.
#[instrument(err)]
async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'static str> {
Ok((0..10).filter(move |x| *x < n))
@@ -30,6 +32,15 @@ async fn test_ret_impl_trait_err(n: i32) -> Result<impl Iterator<Item = i32>, &'
#[instrument]
async fn test_async_fn_empty() {}
+// Reproduces a compile error when an instrumented function body contains inner
+// attributes (https://github.com/tokio-rs/tracing/issues/2294).
+#[deny(unused_variables)]
+#[instrument]
+async fn repro_async_2294() {
+ #![allow(unused_variables)]
+ let i = 42;
+}
+
// Reproduces https://github.com/tokio-rs/tracing/issues/1613
#[instrument]
// LOAD-BEARING `#[rustfmt::skip]`! This is necessary to reproduce the bug;
@@ -53,6 +64,7 @@ async fn repro_1613_2() {
}
// Reproduces https://github.com/tokio-rs/tracing/issues/1831
+#[allow(dead_code)] // this is just here to test whether it compiles.
#[instrument]
#[deny(unused_braces)]
fn repro_1831() -> Pin<Box<dyn Future<Output = ()>>> {
@@ -61,6 +73,7 @@ fn repro_1831() -> Pin<Box<dyn Future<Output = ()>>> {
// This replicates the pattern used to implement async trait methods on nightly using the
// `type_alias_impl_trait` feature
+#[allow(dead_code)] // this is just here to test whether it compiles.
#[instrument(ret, err)]
#[deny(unused_braces)]
#[allow(clippy::manual_async_fn)]
diff --git a/vendor/tracing-attributes/tests/instrument.rs b/vendor/tracing-attributes/tests/instrument.rs
index 2b2fee71e..768692748 100644
--- a/vendor/tracing-attributes/tests/instrument.rs
+++ b/vendor/tracing-attributes/tests/instrument.rs
@@ -3,6 +3,15 @@ use tracing::Level;
use tracing_attributes::instrument;
use tracing_mock::*;
+// Reproduces a compile error when an instrumented function body contains inner
+// attributes (https://github.com/tokio-rs/tracing/issues/2294).
+#[deny(unused_variables)]
+#[instrument]
+fn repro_2294() {
+ #![allow(unused_variables)]
+ let i = 42;
+}
+
#[test]
fn override_everything() {
#[instrument(target = "my_target", level = "debug")]
diff --git a/vendor/tracing-attributes/tests/ui.rs b/vendor/tracing-attributes/tests/ui.rs
new file mode 100644
index 000000000..f11cc019e
--- /dev/null
+++ b/vendor/tracing-attributes/tests/ui.rs
@@ -0,0 +1,7 @@
+// Only test on nightly, since UI tests are bound to change over time
+#[rustversion::stable]
+#[test]
+fn async_instrument() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/ui/async_instrument.rs");
+}
diff --git a/vendor/tracing-attributes/tests/ui/async_instrument.rs b/vendor/tracing-attributes/tests/ui/async_instrument.rs
new file mode 100644
index 000000000..5b245746a
--- /dev/null
+++ b/vendor/tracing-attributes/tests/ui/async_instrument.rs
@@ -0,0 +1,46 @@
+#![allow(unreachable_code)]
+
+#[tracing::instrument]
+async fn unit() {
+ ""
+}
+
+#[tracing::instrument]
+async fn simple_mismatch() -> String {
+ ""
+}
+
+// FIXME: this span is still pretty poor
+#[tracing::instrument]
+async fn opaque_unsatisfied() -> impl std::fmt::Display {
+ ("",)
+}
+
+struct Wrapper<T>(T);
+
+#[tracing::instrument]
+async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
+ ""
+}
+
+#[tracing::instrument]
+async fn early_return_unit() {
+ if true {
+ return "";
+ }
+}
+
+#[tracing::instrument]
+async fn early_return() -> String {
+ if true {
+ return "";
+ }
+ String::new()
+}
+
+#[tracing::instrument]
+async fn extra_semicolon() -> i32 {
+ 1;
+}
+
+fn main() {}
diff --git a/vendor/tracing-attributes/tests/ui/async_instrument.stderr b/vendor/tracing-attributes/tests/ui/async_instrument.stderr
new file mode 100644
index 000000000..db6f6b434
--- /dev/null
+++ b/vendor/tracing-attributes/tests/ui/async_instrument.stderr
@@ -0,0 +1,98 @@
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:5:5
+ |
+5 | ""
+ | ^^ expected `()`, found `&str`
+ |
+note: return type inferred to be `()` here
+ --> tests/ui/async_instrument.rs:4:10
+ |
+4 | async fn unit() {
+ | ^^^^
+
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:10:5
+ |
+10 | ""
+ | ^^- help: try using a conversion method: `.to_string()`
+ | |
+ | expected struct `String`, found `&str`
+ |
+note: return type inferred to be `String` here
+ --> tests/ui/async_instrument.rs:9:31
+ |
+9 | async fn simple_mismatch() -> String {
+ | ^^^^^^
+
+error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
+ --> tests/ui/async_instrument.rs:14:1
+ |
+14 | #[tracing::instrument]
+ | ^^^^^^^^^^^^^^^^^^^^^^ `(&str,)` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `(&str,)`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the attribute macro `tracing::instrument` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0277]: `(&str,)` doesn't implement `std::fmt::Display`
+ --> tests/ui/async_instrument.rs:15:34
+ |
+15 | async fn opaque_unsatisfied() -> impl std::fmt::Display {
+ | ^^^^^^^^^^^^^^^^^^^^^^ `(&str,)` cannot be formatted with the default formatter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `(&str,)`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:23:5
+ |
+23 | ""
+ | ^^ expected struct `Wrapper`, found `&str`
+ |
+ = note: expected struct `Wrapper<_>`
+ found reference `&'static str`
+note: return type inferred to be `Wrapper<_>` here
+ --> tests/ui/async_instrument.rs:22:36
+ |
+22 | async fn mismatch_with_opaque() -> Wrapper<impl std::fmt::Display> {
+ | ^^^^^^^
+help: try wrapping the expression in `Wrapper`
+ |
+23 | Wrapper("")
+ | ++++++++ +
+
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:29:16
+ |
+29 | return "";
+ | ^^ expected `()`, found `&str`
+ |
+note: return type inferred to be `()` here
+ --> tests/ui/async_instrument.rs:27:10
+ |
+27 | async fn early_return_unit() {
+ | ^^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:36:16
+ |
+36 | return "";
+ | ^^- help: try using a conversion method: `.to_string()`
+ | |
+ | expected struct `String`, found `&str`
+ |
+note: return type inferred to be `String` here
+ --> tests/ui/async_instrument.rs:34:28
+ |
+34 | async fn early_return() -> String {
+ | ^^^^^^
+
+error[E0308]: mismatched types
+ --> tests/ui/async_instrument.rs:42:35
+ |
+42 | async fn extra_semicolon() -> i32 {
+ | ___________________________________^
+43 | | 1;
+ | | - help: remove this semicolon
+44 | | }
+ | |_^ expected `i32`, found `()`
diff --git a/vendor/tracing-core/.cargo-checksum.json b/vendor/tracing-core/.cargo-checksum.json
index c51d0e671..6a9cec13f 100644
--- a/vendor/tracing-core/.cargo-checksum.json
+++ b/vendor/tracing-core/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"10eae751c81a268b6118e2dea49d0d501ea4d2a69ece6350232f3800407ab2d3","Cargo.toml":"d29fae6d4ae043c79697e4305224fb8f65279515e1db6ad1211ccd27d073287f","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"f40e479c4d837f4fec140b0f4adad7aae062d55b53708f2255b93217f19d22a9","src/callsite.rs":"f5e9cdaed7fdc75dad5da6486af0ea6e9be896ab5fc1b44c49a90b8b88b33d53","src/dispatcher.rs":"1d129a0c3af976669787733101c2ce7d2f9eca794deeb2ae5a662085e966e0cf","src/event.rs":"f2673bf5d266972e567e521c9cd92fb33f28b0c7e010937e3bc2bf9eb483087f","src/field.rs":"4ec913012ffcf05d3feba2a5ea2ba99c35e2072dabfa2db75614c0e122961b7e","src/lazy.rs":"318e3558e4446abf26294287167c0788e343044a28072f9217bd985929809087","src/lib.rs":"088b29ecce4bdb5b68df9cbe3984f4b22d7124988866d5aace0e7029ea033d58","src/metadata.rs":"1a79326aee210b9e20eb08d5baa22133390f2b1e868cf4dc72a3e9bc9a37d17f","src/parent.rs":"5d5ad733343280a64a1feb6a008e186c39305ec554f14279012b8d7915821471","src/span.rs":"dcf2135e4ca158c1be45007f0be25426c375a4081f8f3c5a4d7f7382d8a950a4","src/spin/LICENSE":"58545fed1565e42d687aecec6897d35c6d37ccb71479a137c0deb2203e125c79","src/spin/mod.rs":"c458ce5e875acb7fbfb279f23254f4924d7c6d6fee419b740800d2e8087d1524","src/spin/mutex.rs":"4d30ff2b59b18fd7909f016e1abdf9aa0c04aa11d047a46e98cffe1319e32dad","src/spin/once.rs":"3781fd4eae0db04d80c03a039906c99b1e01d1583b29ac0144e6fbbd5a0fef0b","src/stdlib.rs":"698693062b8109cace3ffea02e9c2372b7d5b5d43c0b11cb4800b0e7b1a69971","src/subscriber.rs":"916d315ca324a752f70fc3cc557089418a63779ceda54955f55f0ab3c1f3fc7b","tests/common/mod.rs":"0bbb217baa17df0f96cc1ff57dfa74ccc5a959e7f66b15bb7d25d5f43358a278","tests/dispatch.rs":"d3f000fab43734a854c82a7783142910c5e79f806cbd3f8ec5eded598c59ddb1","tests/global_dispatch.rs":"cdc05d77e448ee8b50bfb930abafa3f19b4c6f922b7bebc7797fa1dbdaa1d398","tests/macros.rs":"b1603d888b349c8d103794deceec3b1ae4538b8d3eba805f3f561899e8ad0dd2"},"package":"5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"93400b6ed3661b8f238549f19e55b0482da163a4504080785fefdcdc8b719198","Cargo.toml":"798de58e851a5cc16f76850f08ab381628c3858a438c31a3fa3e35c06e60992c","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"5f5e27d08d3c5ae5f8cc304fcd71ecc61f0c61b27e4bd983c89558805353479d","src/callsite.rs":"479f3b3809afff20ac2a4652f11ec1adc8dd59bd90c608e4e248de4a43c5a43c","src/dispatcher.rs":"16c0ceb3e9de5b7c1365d1c8cc010d12048569d3e9b1146b99b3ea3f0f582ba8","src/event.rs":"f2673bf5d266972e567e521c9cd92fb33f28b0c7e010937e3bc2bf9eb483087f","src/field.rs":"4ec913012ffcf05d3feba2a5ea2ba99c35e2072dabfa2db75614c0e122961b7e","src/lazy.rs":"318e3558e4446abf26294287167c0788e343044a28072f9217bd985929809087","src/lib.rs":"088b29ecce4bdb5b68df9cbe3984f4b22d7124988866d5aace0e7029ea033d58","src/metadata.rs":"1a79326aee210b9e20eb08d5baa22133390f2b1e868cf4dc72a3e9bc9a37d17f","src/parent.rs":"5d5ad733343280a64a1feb6a008e186c39305ec554f14279012b8d7915821471","src/span.rs":"dcf2135e4ca158c1be45007f0be25426c375a4081f8f3c5a4d7f7382d8a950a4","src/spin/LICENSE":"58545fed1565e42d687aecec6897d35c6d37ccb71479a137c0deb2203e125c79","src/spin/mod.rs":"c458ce5e875acb7fbfb279f23254f4924d7c6d6fee419b740800d2e8087d1524","src/spin/mutex.rs":"4d30ff2b59b18fd7909f016e1abdf9aa0c04aa11d047a46e98cffe1319e32dad","src/spin/once.rs":"3781fd4eae0db04d80c03a039906c99b1e01d1583b29ac0144e6fbbd5a0fef0b","src/stdlib.rs":"698693062b8109cace3ffea02e9c2372b7d5b5d43c0b11cb4800b0e7b1a69971","src/subscriber.rs":"baef1454ccf5f552b0a7ba6840eeeca19f7edf21e0303607b86e9e5ffc989a38","tests/common/mod.rs":"0bbb217baa17df0f96cc1ff57dfa74ccc5a959e7f66b15bb7d25d5f43358a278","tests/dispatch.rs":"d3f000fab43734a854c82a7783142910c5e79f806cbd3f8ec5eded598c59ddb1","tests/global_dispatch.rs":"cdc05d77e448ee8b50bfb930abafa3f19b4c6f922b7bebc7797fa1dbdaa1d398","tests/macros.rs":"b1603d888b349c8d103794deceec3b1ae4538b8d3eba805f3f561899e8ad0dd2"},"package":"24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"} \ No newline at end of file
diff --git a/vendor/tracing-core/CHANGELOG.md b/vendor/tracing-core/CHANGELOG.md
index 2db8553c9..cf0d8e3b9 100644
--- a/vendor/tracing-core/CHANGELOG.md
+++ b/vendor/tracing-core/CHANGELOG.md
@@ -1,3 +1,21 @@
+# 0.1.30 (October 6, 2022)
+
+This release of `tracing-core` adds a new `on_register_dispatch` method to the
+`Subscriber` trait to allow the `Subscriber` to perform initialization after
+being registered as a `Dispatch`, and a `WeakDispatch` type to allow a
+`Subscriber` to store its own `Dispatch` without creating reference count
+cycles.
+
+### Added
+
+- `Subscriber::on_register_dispatch` method ([#2269])
+- `WeakDispatch` type and `Dispatch::downgrade()` function ([#2293])
+
+Thanks to @jswrenn for contributing to this release!
+
+[#2269]: https://github.com/tokio-rs/tracing/pull/2269
+[#2293]: https://github.com/tokio-rs/tracing/pull/2293
+
# 0.1.29 (July 29, 2022)
This release of `tracing-core` adds `PartialEq` and `Eq` implementations for
diff --git a/vendor/tracing-core/Cargo.toml b/vendor/tracing-core/Cargo.toml
index 957194d39..806006141 100644
--- a/vendor/tracing-core/Cargo.toml
+++ b/vendor/tracing-core/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.49.0"
name = "tracing-core"
-version = "0.1.29"
+version = "0.1.30"
authors = ["Tokio Contributors <team@tokio.rs>"]
description = """
Core primitives for application-level tracing.
diff --git a/vendor/tracing-core/README.md b/vendor/tracing-core/README.md
index c6f7b0333..f06c76059 100644
--- a/vendor/tracing-core/README.md
+++ b/vendor/tracing-core/README.md
@@ -16,9 +16,9 @@ Core primitives for application-level tracing.
[Documentation][docs-url] | [Chat][discord-url]
[crates-badge]: https://img.shields.io/crates/v/tracing-core.svg
-[crates-url]: https://crates.io/crates/tracing-core/0.1.29
+[crates-url]: https://crates.io/crates/tracing-core/0.1.30
[docs-badge]: https://docs.rs/tracing-core/badge.svg
-[docs-url]: https://docs.rs/tracing-core/0.1.29
+[docs-url]: https://docs.rs/tracing-core/0.1.30
[docs-master-badge]: https://img.shields.io/badge/docs-master-blue
[docs-master-url]: https://tracing-rs.netlify.com/tracing_core
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
@@ -79,22 +79,22 @@ The following crate feature flags are available:
```toml
[dependencies]
- tracing-core = { version = "0.1.29", default-features = false }
+ tracing-core = { version = "0.1.30", default-features = false }
```
**Note**:`tracing-core`'s `no_std` support requires `liballoc`.
[`tracing`]: ../tracing
-[`span::Id`]: https://docs.rs/tracing-core/0.1.29/tracing_core/span/struct.Id.html
-[`Event`]: https://docs.rs/tracing-core/0.1.29/tracing_core/event/struct.Event.html
-[`Subscriber`]: https://docs.rs/tracing-core/0.1.29/tracing_core/subscriber/trait.Subscriber.html
-[`Metadata`]: https://docs.rs/tracing-core/0.1.29/tracing_core/metadata/struct.Metadata.html
-[`Callsite`]: https://docs.rs/tracing-core/0.1.29/tracing_core/callsite/trait.Callsite.html
-[`Field`]: https://docs.rs/tracing-core/0.1.29/tracing_core/field/struct.Field.html
-[`FieldSet`]: https://docs.rs/tracing-core/0.1.29/tracing_core/field/struct.FieldSet.html
-[`Value`]: https://docs.rs/tracing-core/0.1.29/tracing_core/field/trait.Value.html
-[`ValueSet`]: https://docs.rs/tracing-core/0.1.29/tracing_core/field/struct.ValueSet.html
-[`Dispatch`]: https://docs.rs/tracing-core/0.1.29/tracing_core/dispatcher/struct.Dispatch.html
+[`span::Id`]: https://docs.rs/tracing-core/0.1.30/tracing_core/span/struct.Id.html
+[`Event`]: https://docs.rs/tracing-core/0.1.30/tracing_core/event/struct.Event.html
+[`Subscriber`]: https://docs.rs/tracing-core/0.1.30/tracing_core/subscriber/trait.Subscriber.html
+[`Metadata`]: https://docs.rs/tracing-core/0.1.30/tracing_core/metadata/struct.Metadata.html
+[`Callsite`]: https://docs.rs/tracing-core/0.1.30/tracing_core/callsite/trait.Callsite.html
+[`Field`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.Field.html
+[`FieldSet`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.FieldSet.html
+[`Value`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/trait.Value.html
+[`ValueSet`]: https://docs.rs/tracing-core/0.1.30/tracing_core/field/struct.ValueSet.html
+[`Dispatch`]: https://docs.rs/tracing-core/0.1.30/tracing_core/dispatcher/struct.Dispatch.html
## Supported Rust Versions
diff --git a/vendor/tracing-core/src/callsite.rs b/vendor/tracing-core/src/callsite.rs
index bc7405ffa..f88713236 100644
--- a/vendor/tracing-core/src/callsite.rs
+++ b/vendor/tracing-core/src/callsite.rs
@@ -487,6 +487,7 @@ impl Callsites {
pub(crate) fn register_dispatch(dispatch: &Dispatch) {
let dispatchers = DISPATCHERS.register_dispatch(dispatch);
+ dispatch.subscriber().on_register_dispatch(dispatch);
CALLSITES.rebuild_interest(dispatchers);
}
diff --git a/vendor/tracing-core/src/dispatcher.rs b/vendor/tracing-core/src/dispatcher.rs
index a3661817c..36b3cfd85 100644
--- a/vendor/tracing-core/src/dispatcher.rs
+++ b/vendor/tracing-core/src/dispatcher.rs
@@ -134,7 +134,7 @@ use crate::stdlib::{
fmt,
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering},
- Arc,
+ Arc, Weak,
},
};
@@ -142,16 +142,50 @@ use crate::stdlib::{
use crate::stdlib::{
cell::{Cell, RefCell, RefMut},
error,
- sync::Weak,
};
+#[cfg(feature = "alloc")]
+use alloc::sync::{Arc, Weak};
+
+#[cfg(feature = "alloc")]
+use core::ops::Deref;
+
/// `Dispatch` trace data to a [`Subscriber`].
-///
#[derive(Clone)]
pub struct Dispatch {
subscriber: Arc<dyn Subscriber + Send + Sync>,
}
+/// `WeakDispatch` is a version of [`Dispatch`] that holds a non-owning reference
+/// to a [`Subscriber`].
+///
+/// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
+/// which returns an `Option<Dispatch>`. If all [`Dispatch`] clones that point
+/// at the `Subscriber` have been dropped, [`WeakDispatch::upgrade`] will return
+/// `None`. Otherwise, it will return `Some(Dispatch)`.
+///
+/// A `WeakDispatch` may be created from a [`Dispatch`] by calling the
+/// [`Dispatch::downgrade`] method. The primary use for creating a
+/// [`WeakDispatch`] is to allow a Subscriber` to hold a cyclical reference to
+/// itself without creating a memory leak. See [here] for details.
+///
+/// This type is analogous to the [`std::sync::Weak`] type, but for a
+/// [`Dispatch`] rather than an [`Arc`].
+///
+/// [`Arc`]: std::sync::Arc
+/// [here]: Subscriber#avoiding-memory-leaks
+#[derive(Clone)]
+pub struct WeakDispatch {
+ subscriber: Weak<dyn Subscriber + Send + Sync>,
+}
+
+#[cfg(feature = "alloc")]
+#[derive(Clone)]
+enum Kind<T> {
+ Global(&'static (dyn Collect + Send + Sync)),
+ Scoped(T),
+}
+
#[cfg(feature = "std")]
thread_local! {
static CURRENT_STATE: State = State {
@@ -430,8 +464,34 @@ impl Dispatch {
Registrar(Arc::downgrade(&self.subscriber))
}
- /// Registers a new callsite with this subscriber, returning whether or not
- /// the subscriber is interested in being notified about the callsite.
+ /// Creates a [`WeakDispatch`] from this `Dispatch`.
+ ///
+ /// A [`WeakDispatch`] is similar to a [`Dispatch`], but it does not prevent
+ /// the underlying [`Subscriber`] from being dropped. Instead, it only permits
+ /// access while other references to the `Subscriber` exist. This is equivalent
+ /// to the standard library's [`Arc::downgrade`] method, but for `Dispatch`
+ /// rather than `Arc`.
+ ///
+ /// The primary use for creating a [`WeakDispatch`] is to allow a `Subscriber`
+ /// to hold a cyclical reference to itself without creating a memory leak.
+ /// See [here] for details.
+ ///
+ /// [`Arc::downgrade`]: std::sync::Arc::downgrade
+ /// [here]: Subscriber#avoiding-memory-leaks
+ pub fn downgrade(&self) -> WeakDispatch {
+ WeakDispatch {
+ subscriber: Arc::downgrade(&self.subscriber),
+ }
+ }
+
+ #[inline(always)]
+ #[cfg(not(feature = "alloc"))]
+ pub(crate) fn subscriber(&self) -> &(dyn Subscriber + Send + Sync) {
+ &self.subscriber
+ }
+
+ /// Registers a new callsite with this collector, returning whether or not
+ /// the collector is interested in being notified about the callsite.
///
/// This calls the [`register_callsite`] function on the [`Subscriber`]
/// that this `Dispatch` forwards to.
@@ -631,14 +691,14 @@ impl Dispatch {
/// `T`.
#[inline]
pub fn is<T: Any>(&self) -> bool {
- <dyn Subscriber>::is::<T>(&*self.subscriber)
+ <dyn Subscriber>::is::<T>(&self.subscriber)
}
/// Returns some reference to the `Subscriber` this `Dispatch` forwards to
/// if it is of type `T`, or `None` if it isn't.
#[inline]
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
- <dyn Subscriber>::downcast_ref(&*self.subscriber)
+ <dyn Subscriber>::downcast_ref(&self.subscriber)
}
}
@@ -667,6 +727,45 @@ where
}
}
+// === impl WeakDispatch ===
+
+impl WeakDispatch {
+ /// Attempts to upgrade this `WeakDispatch` to a [`Dispatch`].
+ ///
+ /// Returns `None` if the referenced `Dispatch` has already been dropped.
+ ///
+ /// ## Examples
+ ///
+ /// ```
+ /// # use tracing_core::subscriber::NoSubscriber;
+ /// # use tracing_core::dispatcher::Dispatch;
+ /// let strong = Dispatch::new(NoSubscriber::default());
+ /// let weak = strong.downgrade();
+ ///
+ /// // The strong here keeps it alive, so we can still access the object.
+ /// assert!(weak.upgrade().is_some());
+ ///
+ /// drop(strong); // But not any more.
+ /// assert!(weak.upgrade().is_none());
+ /// ```
+ pub fn upgrade(&self) -> Option<Dispatch> {
+ self.subscriber
+ .upgrade()
+ .map(|subscriber| Dispatch { subscriber })
+ }
+}
+
+impl fmt::Debug for WeakDispatch {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut tuple = f.debug_tuple("WeakDispatch");
+ match self.subscriber.upgrade() {
+ Some(subscriber) => tuple.field(&format_args!("Some({:p})", subscriber)),
+ None => tuple.field(&format_args!("None")),
+ };
+ tuple.finish()
+ }
+}
+
#[cfg(feature = "std")]
impl Registrar {
pub(crate) fn upgrade(&self) -> Option<Dispatch> {
diff --git a/vendor/tracing-core/src/subscriber.rs b/vendor/tracing-core/src/subscriber.rs
index a6f0834e2..e8f444119 100644
--- a/vendor/tracing-core/src/subscriber.rs
+++ b/vendor/tracing-core/src/subscriber.rs
@@ -1,5 +1,5 @@
-//! Subscribers collect and record trace data.
-use crate::{span, Event, LevelFilter, Metadata};
+//! Collectors collect and record trace data.
+use crate::{span, Dispatch, Event, LevelFilter, Metadata};
use crate::stdlib::{
any::{Any, TypeId},
@@ -81,7 +81,28 @@ use crate::stdlib::{
/// [`event`]: Subscriber::event
/// [`event_enabled`]: Subscriber::event_enabled
pub trait Subscriber: 'static {
- // === Span registry methods ==============================================
+ /// Invoked when this subscriber becomes a [`Dispatch`].
+ ///
+ /// ## Avoiding Memory Leaks
+ ///
+ /// `Subscriber`s should not store their own [`Dispatch`]. 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 `Subscriber`, 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`]: crate::dispatcher::WeakDispatch
+ /// [upgraded]: crate::dispatcher::WeakDispatch::upgrade
+ fn on_register_dispatch(&self, subscriber: &Dispatch) {
+ let _ = subscriber;
+ }
/// Registers a new [callsite] with this subscriber, returning whether or not
/// the subscriber is interested in being notified about the callsite.
diff --git a/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json b/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json
new file mode 100644
index 000000000..3fd14355e
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/.cargo-checksum.json
@@ -0,0 +1 @@
+{"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/CHANGELOG.md b/vendor/tracing-subscriber-0.3.3/CHANGELOG.md
index e2ac4e7c3..c380ff3b1 100644
--- a/vendor/tracing-subscriber/CHANGELOG.md
+++ b/vendor/tracing-subscriber-0.3.3/CHANGELOG.md
@@ -1,326 +1,3 @@
-# 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/Cargo.toml b/vendor/tracing-subscriber-0.3.3/Cargo.toml
index dd432c4ac..b5e7ba7db 100644
--- a/vendor/tracing-subscriber/Cargo.toml
+++ b/vendor/tracing-subscriber-0.3.3/Cargo.toml
@@ -11,39 +11,20 @@
[package]
edition = "2018"
-rust-version = "1.49.0"
+rust-version = "1.42.0"
name = "tracing-subscriber"
-version = "0.3.15"
-authors = [
- "Eliza Weisman <eliza@buoyant.io>",
- "David Barsky <me@davidbarsky.com>",
- "Tokio Contributors <team@tokio.rs>",
-]
-description = """
-Utilities for implementing and composing `tracing` subscribers.
-"""
+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"
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"
@@ -60,21 +41,20 @@ harness = false
[[bench]]
name = "enter"
harness = false
-
[dependencies.ansi_term]
version = "0.12"
optional = true
-[dependencies.matchers]
-version = "0.1.0"
+[dependencies.lazy_static]
+version = "1"
optional = true
-[dependencies.once_cell]
-version = "1.12"
+[dependencies.matchers]
+version = "0.1.0"
optional = true
[dependencies.parking_lot]
-version = "0.12"
+version = ">= 0.7, <= 0.11"
optional = true
[dependencies.regex]
@@ -96,11 +76,11 @@ version = "0.1.0"
optional = true
[dependencies.smallvec]
-version = "1.2.0"
+version = "1"
optional = true
[dependencies.thread_local]
-version = "1.1.4"
+version = "1.0.1"
optional = true
[dependencies.time]
@@ -114,22 +94,17 @@ optional = true
default-features = false
[dependencies.tracing-core]
-version = "0.1.28"
-default-features = false
+version = "0.1.20"
[dependencies.tracing-log]
version = "0.1.2"
-features = [
- "log-tracer",
- "std",
-]
+features = ["log-tracer", "std"]
optional = true
default-features = false
[dependencies.tracing-serde]
-version = "0.1.3"
+version = "0.1.2"
optional = true
-
[dev-dependencies.criterion]
version = "0.3"
default_features = false
@@ -144,27 +119,18 @@ default-features = false
[dev-dependencies.time]
version = "0.3"
-features = [
- "formatting",
- "macros",
-]
+features = ["formatting", "macros"]
[dev-dependencies.tokio]
-version = "1"
-features = [
- "rt",
- "macros",
-]
+version = "0.2"
+features = ["rt-core", "macros"]
[dev-dependencies.tracing]
version = "0.1"
[dev-dependencies.tracing-futures]
version = "0.2"
-features = [
- "std-future",
- "std",
-]
+features = ["std-future", "std"]
default-features = false
[dev-dependencies.tracing-log]
@@ -172,61 +138,13 @@ version = "0.1.2"
[features]
alloc = []
-ansi = [
- "fmt",
- "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",
-]
+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"]
local-time = ["time/local-offset"]
-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"
-
+registry = ["sharded-slab", "thread_local", "std"]
+std = ["alloc", "tracing-core/std"]
[badges.maintenance]
status = "experimental"
diff --git a/vendor/tracing-subscriber/LICENSE b/vendor/tracing-subscriber-0.3.3/LICENSE
index cdb28b4b5..cdb28b4b5 100644
--- a/vendor/tracing-subscriber/LICENSE
+++ b/vendor/tracing-subscriber-0.3.3/LICENSE
diff --git a/vendor/tracing-subscriber/README.md b/vendor/tracing-subscriber-0.3.3/README.md
index ba2b4e1c3..75c62e8ca 100644
--- a/vendor/tracing-subscriber/README.md
+++ b/vendor/tracing-subscriber-0.3.3/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.15
+[docs-url]: https://docs.rs/tracing-subscriber/0.3.1
[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.49+][msrv]*
+*Compiler support: [requires `rustc` 1.42+][msrv]*
[msrv]: #supported-rust-versions
## Supported Rust Versions
Tracing is built against the latest stable release. The minimum supported
-version is 1.49. The current Tracing version is not guaranteed to build on Rust
+version is 1.42. 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/benches/enter.rs b/vendor/tracing-subscriber-0.3.3/benches/enter.rs
index 49c6e730a..49c6e730a 100644
--- a/vendor/tracing-subscriber/benches/enter.rs
+++ b/vendor/tracing-subscriber-0.3.3/benches/enter.rs
diff --git a/vendor/tracing-subscriber/benches/filter.rs b/vendor/tracing-subscriber-0.3.3/benches/filter.rs
index 91ab9c91d..91ab9c91d 100644
--- a/vendor/tracing-subscriber/benches/filter.rs
+++ b/vendor/tracing-subscriber-0.3.3/benches/filter.rs
diff --git a/vendor/tracing-subscriber/benches/filter_log.rs b/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs
index 4dcf3b4ec..4dcf3b4ec 100644
--- a/vendor/tracing-subscriber/benches/filter_log.rs
+++ b/vendor/tracing-subscriber-0.3.3/benches/filter_log.rs
diff --git a/vendor/tracing-subscriber/benches/fmt.rs b/vendor/tracing-subscriber-0.3.3/benches/fmt.rs
index a039e66d4..a039e66d4 100644
--- a/vendor/tracing-subscriber/benches/fmt.rs
+++ b/vendor/tracing-subscriber-0.3.3/benches/fmt.rs
diff --git a/vendor/tracing-subscriber/benches/support/mod.rs b/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs
index 25e9e7e22..25e9e7e22 100644
--- a/vendor/tracing-subscriber/benches/support/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/benches/support/mod.rs
diff --git a/vendor/tracing-subscriber/src/field/debug.rs b/vendor/tracing-subscriber-0.3.3/src/field/debug.rs
index cc67d29fe..cc67d29fe 100644
--- a/vendor/tracing-subscriber/src/field/debug.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/field/debug.rs
diff --git a/vendor/tracing-subscriber/src/field/delimited.rs b/vendor/tracing-subscriber-0.3.3/src/field/delimited.rs
index 98634cea9..8c78c4b20 100644
--- a/vendor/tracing-subscriber/src/field/delimited.rs
+++ b/vendor/tracing-subscriber-0.3.3/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`]: super::MakeVisitor
+ /// [`MakeVisitor`]: ../trait.MakeVisitor.html
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`]: tracing_core::field::Visit
+ /// [`Visit`]: https://docs.rs/tracing-core/0.1.6/tracing_core/field/trait.Visit.html
pub fn new(delimiter: D, inner: V) -> Self {
Self {
delimiter,
diff --git a/vendor/tracing-subscriber/src/field/display.rs b/vendor/tracing-subscriber-0.3.3/src/field/display.rs
index 78a039ce1..e0bbc55ed 100644
--- a/vendor/tracing-subscriber/src/field/display.rs
+++ b/vendor/tracing-subscriber-0.3.3/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`]: super::MakeVisitor
+ /// [`MakeVisitor`]: ../trait.MakeVisitor.html
pub fn new(inner: V) -> Self {
Messages(inner)
}
diff --git a/vendor/tracing-subscriber/src/field/mod.rs b/vendor/tracing-subscriber-0.3.3/src/field/mod.rs
index 5dfddb362..f7d03f2cc 100644
--- a/vendor/tracing-subscriber/src/field/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/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]: tracing_core::field::Visit
+/// [visitors]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html
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]: tracing_core::field::Visit
+/// [visitor]: https://docs.rs/tracing-core/latest/tracing_core/field/trait.Visit.html
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]: tracing_core::field::Visit
-/// [attr]: tracing_core::span::Attributes
-/// [rec]: tracing_core::span::Record
-/// [event]: tracing_core::event::Event
+/// [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
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!(self.writer, "{}={:?}", field, value).unwrap();
+ write!(&mut self.writer, "{}={:?}", field, value).unwrap();
}
}
diff --git a/vendor/tracing-subscriber/src/filter/directive.rs b/vendor/tracing-subscriber-0.3.3/src/filter/directive.rs
index 2ae3f0f24..dd6b063c4 100644
--- a/vendor/tracing-subscriber/src/filter/directive.rs
+++ b/vendor/tracing-subscriber-0.3.3/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::{Level, Metadata};
+use tracing_core::Metadata;
/// Indicates that a string could not be parsed as a filtering directive.
#[derive(Debug)]
pub struct ParseError {
@@ -142,22 +142,6 @@ 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 ===
@@ -174,22 +158,6 @@ 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/directive.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs
index f062e6ef9..66ca23dc4 100644
--- a/vendor/tracing-subscriber/src/filter/env/directive.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/directive.rs
@@ -4,14 +4,14 @@ use crate::filter::{
env::{field, FieldMap},
level::LevelFilter,
};
-use once_cell::sync::Lazy;
+use lazy_static::lazy_static;
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(Clone, Debug, Eq, PartialEq)]
+#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
pub struct Directive {
in_span: Option<String>,
@@ -107,52 +107,80 @@ impl Directive {
.collect();
(Dynamics::from_iter(dyns), statics)
}
+}
- 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,
+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;
+ }
+ }
+
+ true
}
- 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());
+ 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();
+ }
let caps = DIRECTIVE_RE.captures(from).ok_or_else(ParseError::new)?;
@@ -186,7 +214,7 @@ impl Directive {
.map(|c| {
FIELD_FILTER_RE
.find_iter(c.as_str())
- .map(|c| field::Match::parse(c.as_str(), regex))
+ .map(|c| c.as_str().parse())
.collect::<Result<Vec<_>, _>>()
})
.unwrap_or_else(|| Ok(Vec::new()));
@@ -200,7 +228,7 @@ impl Directive {
// Setting the target without the level enables every level for that target
.unwrap_or(LevelFilter::TRACE);
- Ok(Self {
+ Ok(Directive {
level,
target,
in_span,
@@ -209,48 +237,6 @@ impl 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/src/filter/env/field.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs
index 1394fd04a..970850f92 100644
--- a/vendor/tracing-subscriber/src/filter/env/field.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/field.rs
@@ -2,7 +2,7 @@ use matchers::Pattern;
use std::{
cmp::Ordering,
error::Error,
- fmt::{self, Write},
+ fmt,
str::FromStr,
sync::{
atomic::{AtomicBool, Ordering::*},
@@ -13,7 +13,7 @@ use std::{
use super::{FieldMap, LevelFilter};
use tracing_core::field::{Field, Visit};
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Debug, Eq, PartialEq)]
pub(crate) struct Match {
pub(crate) name: String, // TODO: allow match patterns for names?
pub(crate) value: Option<ValueMatch>,
@@ -38,20 +38,11 @@ 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>),
}
@@ -106,9 +97,6 @@ impl Ord for ValueMatch {
(Pat(this), Pat(that)) => this.cmp(that),
(Pat(_), _) => Ordering::Greater,
-
- (Debug(this), Debug(that)) => this.cmp(that),
- (Debug(_), _) => Ordering::Greater,
}
}
}
@@ -119,25 +107,12 @@ 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")))]
@@ -147,17 +122,9 @@ pub struct BadName {
// === impl Match ===
-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>> {
+impl FromStr for Match {
+ type Err = Box<dyn Error + Send + Sync>;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split('=');
let name = parts
.next()
@@ -166,17 +133,22 @@ impl Match {
})?
// TODO: validate field name
.to_string();
- let value = parts
- .next()
- .map(|part| match regex {
- true => ValueMatch::parse_regex(part),
- false => Ok(ValueMatch::parse_non_regex(part)),
- })
- .transpose()?;
+ let value = parts.next().map(ValueMatch::from_str).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)?;
@@ -227,14 +199,9 @@ fn value_match_f64(v: f64) -> ValueMatch {
}
}
-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> {
+impl FromStr for ValueMatch {
+ type Err = matchers::Error;
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<bool>()
.map(ValueMatch::Bool)
.or_else(|_| s.parse::<u64>().map(ValueMatch::U64))
@@ -245,21 +212,6 @@ impl 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 {
@@ -270,7 +222,6 @@ 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),
}
}
@@ -313,12 +264,6 @@ 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 {
@@ -344,102 +289,6 @@ 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 {}
@@ -552,9 +401,6 @@ 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)
- }
_ => {}
}
}
@@ -564,63 +410,7 @@ 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/src/filter/env/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs
index 81a9ae2bd..81fe0e62d 100644
--- a/vendor/tracing-subscriber/src/filter/env/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/env/mod.rs
@@ -4,8 +4,7 @@
// these are publicly re-exported, but the compiler doesn't realize
// that for some reason.
#[allow(unreachable_pub)]
-pub use self::{builder::Builder, directive::Directive, field::BadName as BadFieldName};
-mod builder;
+pub use self::{directive::Directive, field::BadName as BadFieldName};
mod directive;
mod field;
@@ -16,7 +15,6 @@ 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,
@@ -28,16 +26,6 @@ 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.
@@ -64,27 +52,10 @@ 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 matches the
-/// [`std::fmt::Debug`] output from the value.
+/// it will match _only_ on that value. Otherwise, this filter acts as a regex on
+/// 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.
@@ -101,7 +72,7 @@ use tracing_core::{
/// - A dash in a target will only appear when being specified explicitly:
/// `tracing::info!(target: "target-name", ...);`
///
-/// ## Example Syntax
+/// ## Examples
///
/// - `tokio::net=info` will enable all spans or events that:
/// - have the `tokio::net` target,
@@ -118,68 +89,10 @@ use tracing_core::{
/// - which has a field named `name` with value `bob`,
/// - at _any_ level.
///
-/// # 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.
+/// 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`].
///
/// [`Span`]: tracing_core::span
/// [fields]: tracing_core::Field
@@ -187,11 +100,6 @@ 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 {
@@ -200,8 +108,10 @@ pub struct EnvFilter {
has_dynamics: bool,
by_id: RwLock<HashMap<span::Id, directive::SpanMatcher>>,
by_cs: RwLock<HashMap<callsite::Identifier, directive::CallsiteMatcher>>,
- scope: ThreadLocal<RefCell<Vec<LevelFilter>>>,
- regex: bool,
+}
+
+thread_local! {
+ static SCOPE: RefCell<Vec<LevelFilter>> = RefCell::new(Vec::new());
}
type FieldMap<T> = HashMap<Field, T>;
@@ -224,181 +134,58 @@ 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`]: EnvFilter::from_default_env()
- /// [`EnvFilter::try_from_default_env`]: EnvFilter::try_from_default_env()
+ /// [`EnvFilter::from_default_env`]: #method.from_default_env
+ /// [`EnvFilter::try_from_default_env`]: #method.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::builder()
- .with_default_directive(LevelFilter::ERROR.into())
- .from_env_lossy()
+ Self::from_env(Self::DEFAULT_ENV)
}
/// 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 {
- Self::builder()
- .with_default_directive(LevelFilter::ERROR.into())
- .with_env_var(env.as_ref())
- .from_env_lossy()
+ env::var(env.as_ref()).map(Self::new).unwrap_or_default()
}
/// Returns a new `EnvFilter` from the directives in the given string,
/// ignoring any that are invalid.
- ///
- /// 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)
+ 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)
}
/// 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> {
- Self::builder().parse(dirs)
+ let directives = dirs
+ .as_ref()
+ .split(',')
+ .map(|s| s.parse())
+ .collect::<Result<Vec<_>, _>>()?;
+ Ok(Self::from_directives(directives))
}
/// Returns a new `EnvFilter` from the value of the `RUST_LOG` 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> {
- /// EnvFilter::builder().try_from_env()
- /// # }
- /// ```
+ /// variable, or an error if the environment variable contains any invalid
+ /// filter directives.
pub fn try_from_default_env() -> Result<Self, FromEnvError> {
- Self::builder().try_from_env()
+ Self::try_from_env(Self::DEFAULT_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> {
- Self::builder().with_env_var(env.as_ref()).try_from_env()
+ env::var(env.as_ref())?.parse().map_err(Into::into)
}
/// Add a filtering directive to this `EnvFilter`.
@@ -415,13 +202,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`]: super::LevelFilter
- /// [`Level`]: tracing_core::Level
+ /// [`LevelFilter`]: ../filter/struct.LevelFilter.html
+ /// [`Level`]: https://docs.rs/tracing-core/latest/tracing_core/struct.Level.html
///
/// # Examples
///
/// From [`LevelFilter`]:
- ///
+ ////
/// ```rust
/// use tracing_subscriber::filter::{EnvFilter, LevelFilter};
/// let mut filter = EnvFilter::from_default_env()
@@ -436,9 +223,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};
///
@@ -449,15 +236,7 @@ impl EnvFilter {
/// # Ok(())
/// # }
/// ```
- /// 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();
- }
+ pub fn add_directive(mut self, directive: Directive) -> Self {
if let Some(stat) = directive.to_static() {
self.statics.add(stat)
} else {
@@ -467,19 +246,165 @@ impl EnvFilter {
self
}
- // === filtering methods ===
+ 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
+ ));
+ }
- /// 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 (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(),
+ )
+ }
+
+ fn enabled(&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 loca'l access + iterating over the
+ // if not, we can avoid the thread local access + iterating over the
// spans in the current scope.
if self.has_dynamics && self.dynamics.max_level >= *level {
if metadata.is_span() {
@@ -495,15 +420,14 @@ impl EnvFilter {
}
}
- let enabled_by_scope = {
- let scope = self.scope.get_or_default().borrow();
- for filter in &*scope {
+ let enabled_by_scope = SCOPE.with(|scope| {
+ for filter in scope.borrow().iter() {
if filter >= level {
return true;
}
}
false
- };
+ });
if enabled_by_scope {
return true;
}
@@ -519,33 +443,7 @@ impl EnvFilter {
false
}
- /// 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>) {
+ fn on_new_span(&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);
@@ -553,37 +451,28 @@ impl EnvFilter {
}
}
- /// 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>) {
+ 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>) {
// 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) {
- self.scope.get_or_default().borrow_mut().push(span.level());
+ SCOPE.with(|scope| scope.borrow_mut().push(span.level()));
}
}
- /// 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>) {
+ fn on_exit(&self, id: &span::Id, _: Context<'_, S>) {
if self.cares_about_span(id) {
- self.scope.get_or_default().borrow_mut().pop();
+ SCOPE.with(|scope| scope.borrow_mut().pop());
}
}
- /// 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>) {
+ fn on_close(&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;
@@ -592,140 +481,6 @@ impl 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 {
@@ -747,7 +502,7 @@ where
impl Default for EnvFilter {
fn default() -> Self {
- Builder::default().from_directives(std::iter::empty())
+ Self::from_directives(std::iter::empty())
}
}
@@ -980,12 +735,4 @@ 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/src/filter/filter_fn.rs b/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs
index 332bf860a..332bf860a 100644
--- a/vendor/tracing-subscriber/src/filter/filter_fn.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/filter_fn.rs
diff --git a/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs
index 8949cfb5a..e77fd3751 100644
--- a/vendor/tracing-subscriber/src/filter/layer_filters/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/layer_filters.rs
@@ -37,7 +37,6 @@ use std::{
cell::{Cell, RefCell},
fmt,
marker::PhantomData,
- ops::Deref,
sync::Arc,
thread_local,
};
@@ -46,7 +45,6 @@ use tracing_core::{
subscriber::{Interest, Subscriber},
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.
@@ -160,231 +158,7 @@ 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.
- 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 {
@@ -405,35 +179,38 @@ impl<S> layer::Filter<S> for LevelFilter {
}
}
-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.deref().callsite_enabled(meta)
- }
+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)
+ }
- #[inline]
- fn max_level_hint(&self) -> Option<LevelFilter> {
- self.deref().max_level_hint()
- }
- };
-}
+ #[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!();
+ #[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)
+ }
+
+ #[inline]
+ fn max_level_hint(&self) -> Option<LevelFilter> {
+ (**self).max_level_hint()
+ }
}
// === impl Filtered ===
@@ -470,78 +247,6 @@ 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>
@@ -617,9 +322,7 @@ where
fn on_new_span(&self, attrs: &span::Attributes<'_>, id: &span::Id, cx: Context<'_, S>) {
self.did_enable(|| {
- let cx = cx.with_filter(self.id());
- self.filter.on_new_span(attrs, id, cx.clone());
- self.layer.on_new_span(attrs, id, cx);
+ self.layer.on_new_span(attrs, id, cx.with_filter(self.id()));
})
}
@@ -630,7 +333,6 @@ 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)
}
}
@@ -651,22 +353,19 @@ where
fn on_enter(&self, id: &span::Id, cx: Context<'_, S>) {
if let Some(cx) = cx.if_enabled_for(id, self.id()) {
- self.filter.on_enter(id, cx.clone());
- self.layer.on_enter(id, cx);
+ 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.filter.on_exit(id, cx.clone());
- self.layer.on_exit(id, cx);
+ 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.filter.on_close(id.clone(), cx.clone());
- self.layer.on_close(id, cx);
+ self.layer.on_close(id, cx)
}
}
@@ -845,10 +544,6 @@ impl fmt::Binary for FilterId {
}
}
-// === impl FilterExt ===
-
-impl<F, S> FilterExt<S> for F where F: layer::Filter<S> {}
-
// === impl FilterMap ===
impl FilterMap {
diff --git a/vendor/tracing-subscriber/src/filter/level.rs b/vendor/tracing-subscriber-0.3.3/src/filter/level.rs
index 0fa601260..0fa601260 100644
--- a/vendor/tracing-subscriber/src/filter/level.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/level.rs
diff --git a/vendor/tracing-subscriber/src/filter/mod.rs b/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs
index 000a27195..000a27195 100644
--- a/vendor/tracing-subscriber/src/filter/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/mod.rs
diff --git a/vendor/tracing-subscriber/src/filter/targets.rs b/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs
index 2a30d2db6..e0c7fcf82 100644
--- a/vendor/tracing-subscriber/src/filter/targets.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/filter/targets.rs
@@ -20,7 +20,7 @@ use core::{
slice,
str::FromStr,
};
-use tracing_core::{Interest, Level, Metadata, Subscriber};
+use tracing_core::{Interest, 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, Level, 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]:
+/// [global filter]:
///
/// ```rust
/// use tracing_subscriber::{
@@ -313,35 +313,6 @@ 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
diff --git a/vendor/tracing-subscriber/src/fmt/fmt_layer.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs
index 21992e780..0e0d5e0eb 100644
--- a/vendor/tracing-subscriber/src/fmt/fmt_layer.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/fmt_layer.rs
@@ -56,7 +56,7 @@ use tracing_core::{
/// # tracing::subscriber::set_global_default(subscriber).unwrap();
/// ```
///
-/// [`Layer`]: super::layer::Layer
+/// [`Layer`]: ../layer/trait.Layer.html
#[cfg_attr(docsrs, doc(cfg(all(feature = "fmt", feature = "std"))))]
#[derive(Debug)]
pub struct Layer<
@@ -70,11 +70,11 @@ pub struct Layer<
fmt_event: E,
fmt_span: format::FmtSpanConfig,
is_ansi: bool,
- _inner: PhantomData<fn(S)>,
+ _inner: PhantomData<S>,
}
impl<S> Layer<S> {
- /// Returns a new [`Layer`][self::Layer] with the default configuration.
+ /// Returns a new [`Layer`](struct.Layer.html) with the default configuration.
pub fn new() -> Self {
Self::default()
}
@@ -87,8 +87,8 @@ where
N: for<'writer> FormatFields<'writer> + 'static,
W: for<'writer> MakeWriter<'writer> + 'static,
{
- /// Sets the [event formatter][`FormatEvent`] that the layer being built will
- /// use to format events.
+ /// Sets the [event formatter][`FormatEvent`] that the layer 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 +108,7 @@ where
/// ```
/// [`FormatEvent`]: format::FormatEvent
/// [`Event`]: tracing::Event
- /// [`Writer`]: format::Writer
+ /// [`Writer`]: crate::format::Writer
pub fn event_format<E2>(self, e: E2) -> Layer<S, N, E2, W>
where
E2: FormatEvent<S, N> + 'static,
@@ -122,40 +122,11 @@ where
_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,
- _inner: self._inner,
- }
- }
}
// 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
///
@@ -171,6 +142,9 @@ 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,
@@ -185,57 +159,7 @@ impl<S, N, E, W> Layer<S, N, E, W> {
}
}
- /// 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
+ /// Configures the subscriber to support [`libtest`'s output capturing][capturing] when used in
/// unit tests.
///
/// See [`TestWriter`] for additional details.
@@ -256,7 +180,7 @@ 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`]: super::writer::TestWriter
+ /// [`TestWriter`]: writer/struct.TestWriter.html
pub fn with_test_writer(self) -> Layer<S, N, E, TestWriter> {
Layer {
fmt_fields: self.fmt_fields,
@@ -277,39 +201,6 @@ impl<S, N, E, W> Layer<S, N, E, W> {
..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,
- make_writer: f(self.make_writer),
- _inner: self._inner,
- }
- }
}
impl<S, N, L, T, W> Layer<S, N, format::Format<L, T>, W>
@@ -393,7 +284,7 @@ where
/// `Layer`s added to this subscriber.
///
/// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
- /// [time]: Layer::without_time()
+ /// [time]: #method.without_time
pub fn with_span_events(self, kind: FmtSpan) -> Self {
Layer {
fmt_span: self.fmt_span.with_kind(kind),
@@ -408,30 +299,6 @@ 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> {
@@ -442,9 +309,9 @@ where
}
/// Sets whether or not the [thread ID] of the current thread is displayed
- /// when formatting events.
+ /// when formatting events
///
- /// [thread ID]: std::thread::ThreadId
+ /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
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),
@@ -453,9 +320,9 @@ where
}
/// Sets whether or not the [name] of the current thread is displayed
- /// when formatting events.
+ /// when formatting events
///
- /// [name]: std::thread#naming-threads
+ /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
pub fn with_thread_names(
self,
display_thread_names: bool,
@@ -466,7 +333,7 @@ where
}
}
- /// Sets the layer being built to use a [less verbose formatter][super::format::Compact].
+ /// Sets the layer being built to use a [less verbose formatter](../fmt/format/struct.Compact.html).
pub fn compact(self) -> Layer<S, N, format::Format<format::Compact, T>, W>
where
N: for<'writer> FormatFields<'writer> + 'static,
@@ -495,7 +362,7 @@ where
}
}
- /// Sets the layer being built to use a [JSON formatter][super::format::Json].
+ /// Sets the layer being built to use a [JSON formatter](../fmt/format/struct.Json.html).
///
/// The full format includes fields from all entered spans.
///
@@ -510,7 +377,7 @@ where
/// - [`Layer::flatten_event`] can be used to enable flattening event fields into the root
/// object.
///
- /// [`Layer::flatten_event`]: Layer::flatten_event()
+ /// [`Layer::flatten_event`]: #method.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> {
@@ -531,7 +398,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`][super::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn flatten_event(
self,
flatten_event: bool,
@@ -546,7 +413,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`][super::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn with_current_span(
self,
display_current_span: bool,
@@ -561,7 +428,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`][super::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn with_span_list(
self,
display_span_list: bool,
@@ -590,36 +457,6 @@ impl<S, N, E, W> Layer<S, N, E, W> {
_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,
- _inner: self._inner,
- }
- }
}
impl<S> Default for Layer<S> {
@@ -660,7 +497,7 @@ where
/// formatters are in use, each can store its own formatted representation
/// without conflicting.
///
-/// [extensions]: crate::registry::Extensions
+/// [extensions]: ../registry/struct.Extensions.html
#[derive(Default)]
pub struct FormattedFields<E: ?Sized> {
_format_fields: PhantomData<fn(E)>,
@@ -984,7 +821,7 @@ where
/// If this returns `None`, then no span exists for that ID (either it has
/// closed or the ID is invalid).
///
- /// [stored data]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
#[inline]
pub fn span(&self, id: &Id) -> Option<SpanRef<'_, S>>
where
@@ -1007,7 +844,7 @@ where
///
/// If this returns `None`, then we are not currently within a span.
///
- /// [stored data]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
#[inline]
pub fn lookup_current(&self) -> Option<SpanRef<'_, S>>
where
diff --git a/vendor/tracing-subscriber/src/fmt/format/json.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs
index c2f4d3755..cc86f03c7 100644
--- a/vendor/tracing-subscriber/src/fmt/format/json.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/format/json.rs
@@ -23,42 +23,25 @@ use tracing_serde::AsSerde;
#[cfg(feature = "tracing-log")]
use tracing_log::NormalizeEvent;
-/// Marker for [`Format`] that indicates that the newline-delimited JSON log
-/// format should be used.
+/// Marker for `Format` that indicates that the verbose JSON log format should be used.
///
-/// 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.
+/// 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-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>
+/// ```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"}],
+/// }
+/// ```
///
/// # 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
@@ -69,23 +52,9 @@ use tracing_log::NormalizeEvent;
/// By default, event fields are not flattened, and both current span and span
/// list are logged.
///
-/// # 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
+/// [`Json::flatten_event`]: #method.flatten_event
+/// [`Json::with_current_span`]: #method.with_current_span
+/// [`Json::with_span_list`]: #method.with_span_list
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Json {
pub(crate) flatten_event: bool,
@@ -274,18 +243,6 @@ 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
@@ -341,6 +298,7 @@ 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
@@ -351,6 +309,7 @@ pub struct JsonFields {
impl JsonFields {
/// Returns a new JSON [`FormatFields`] implementation.
///
+ /// [`FormatFields`]: trait.FormatFields.html
pub fn new() -> Self {
Self { _private: () }
}
@@ -419,8 +378,9 @@ impl<'a> FormatFields<'a> for JsonFields {
/// The [visitor] produced by [`JsonFields`]'s [`MakeVisitor`] implementation.
///
-/// [visitor]: crate::field::Visit
-/// [`MakeVisitor`]: crate::field::MakeVisitor
+/// [visitor]: ../../field/trait.Visit.html
+/// [`JsonFields`]: struct.JsonFields.html
+/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
pub struct JsonVisitor<'a> {
values: BTreeMap<&'a str, serde_json::Value>,
writer: &'a mut dyn Write,
@@ -475,26 +435,6 @@ 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
@@ -548,7 +488,6 @@ mod test {
use tracing::{self, subscriber::with_default};
use std::fmt;
- use std::path::Path;
struct MockTime;
impl FormatTime for MockTime {
@@ -577,50 +516,6 @@ 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";
@@ -852,34 +747,4 @@ 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/src/fmt/format/mod.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs
index ec79ac140..9001e102e 100644
--- a/vendor/tracing-subscriber/src/fmt/format/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/format/mod.rs
@@ -1,33 +1,4 @@
//! 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},
@@ -182,7 +153,6 @@ 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
@@ -227,8 +197,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]: crate::field::RecordFields
-/// [`FmtSubscriber`]: super::Subscriber
+/// [set of fields]: ../field/trait.RecordFields.html
+/// [`FmtSubscriber`]: ../fmt/struct.Subscriber.html
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;
@@ -281,6 +251,7 @@ 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,
@@ -301,8 +272,6 @@ 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
@@ -312,76 +281,28 @@ 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]: super::super::field::Visit
-/// [`MakeVisitor`]: super::super::field::MakeVisitor
+/// [visitor]: ../../field/trait.Visit.html
+/// [`FieldFn`]: struct.FieldFn.html
+/// [`MakeVisitor`]: ../../field/trait.MakeVisitor.html
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.
-///
-/// 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
+/// Marker for `Format` that indicates that the compact log format should be used.
///
-/// <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>
+/// The compact format only includes the fields from the most recently entered span.
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Compact;
-/// 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.
+/// Marker for `Format` that indicates that the verbose log format should be used.
///
-/// # 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>
+/// The full format includes fields from all entered spans.
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
pub struct Full;
@@ -390,11 +311,8 @@ 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 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.
+/// spans. The [`Compact`] logging format includes only the fields from the most-recently-entered
+/// span.
#[derive(Debug, Clone)]
pub struct Format<F = Full, T = SystemTime> {
format: F,
@@ -405,8 +323,6 @@ 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 ===
@@ -583,8 +499,6 @@ impl Default for Format<Full, SystemTime> {
display_level: true,
display_thread_id: false,
display_thread_name: false,
- display_filename: false,
- display_line_number: false,
}
}
}
@@ -603,8 +517,6 @@ 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,
}
}
@@ -642,8 +554,6 @@ 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,
}
}
@@ -661,6 +571,8 @@ 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> {
@@ -673,8 +585,6 @@ 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,
}
}
@@ -702,8 +612,6 @@ 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,
}
}
@@ -718,8 +626,6 @@ 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,
}
}
@@ -748,9 +654,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]: std::thread::ThreadId
+ /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
pub fn with_thread_ids(self, display_thread_id: bool) -> Format<F, T> {
Format {
display_thread_id,
@@ -759,9 +665,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]: std::thread#naming-threads
+ /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
pub fn with_thread_names(self, display_thread_name: bool) -> Format<F, T> {
Format {
display_thread_name,
@@ -769,38 +675,6 @@ 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
@@ -818,24 +692,14 @@ impl<F, T> Format<F, T> {
if writer.has_ansi_escapes() {
let style = Style::new().dimmed();
write!(writer, "{}", style.prefix())?;
-
- // 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>")?;
- }
-
+ self.timer.format_time(writer)?;
write!(writer, "{} ", style.suffix())?;
return Ok(());
}
}
// Otherwise, just format the timestamp without ANSI formatting.
- // 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>")?;
- }
+ self.timer.format_time(writer)?;
writer.write_char(' ')
}
}
@@ -850,7 +714,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`][super::format::Json].
+ /// See [`Json`](../format/struct.Json.html).
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn flatten_event(mut self, flatten_event: bool) -> Format<Json, T> {
@@ -861,7 +725,7 @@ impl<T> Format<Json, T> {
/// Sets whether or not the formatter will include the current span in
/// formatted events.
///
- /// See [`format::Json`][Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn with_current_span(mut self, display_current_span: bool) -> Format<Json, T> {
@@ -872,7 +736,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`][Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn with_span_list(mut self, display_span_list: bool) -> Format<Json, T> {
@@ -976,34 +840,6 @@ 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)
}
@@ -1082,49 +918,23 @@ where
};
write!(writer, "{}", fmt_ctx)?;
- let bold = writer.bold();
- let dimmed = writer.dimmed();
-
- let mut needs_space = false;
if self.display_target {
- 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(' ')?;
+ write!(
+ writer,
+ "{}{} ",
+ writer.bold().paint(meta.target()),
+ writer.dimmed().paint(":")
+ )?;
}
ctx.format_fields(writer.by_ref(), event)?;
+ let dimmed = writer.dimmed();
for span in ctx
.event_scope()
.into_iter()
- .flat_map(crate::registry::Scope::from_root)
+ .map(crate::registry::Scope::from_root)
+ .flatten()
{
let exts = span.extensions();
if let Some(fields) = exts.get::<FormattedFields<N>>() {
@@ -1152,6 +962,7 @@ 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
@@ -1173,6 +984,7 @@ pub struct DefaultVisitor<'a> {
impl DefaultFields {
/// Returns a new default [`FormatFields`] implementation.
///
+ /// [`FormatFields`]: trait.FormatFields.html
pub fn new() -> Self {
Self { _private: () }
}
@@ -1389,14 +1201,6 @@ 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> {
@@ -1562,7 +1366,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`](super::SubscriberBuilder.html::with_span_events).
+/// See also [`with_span_events`](../struct.SubscriberBuilder.html#method.with_span_events).
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct FmtSpan(u8);
@@ -1724,9 +1528,7 @@ pub(super) mod test {
};
use super::*;
-
- use regex::Regex;
- use std::{fmt, path::Path};
+ use std::fmt;
pub(crate) struct MockTime;
impl FormatTime for MockTime {
@@ -1748,7 +1550,7 @@ pub(super) mod test {
.with_thread_names(false);
#[cfg(feature = "ansi")]
let subscriber = subscriber.with_ansi(false);
- assert_info_hello(subscriber, make_writer, "hello\n")
+ run_test(subscriber, make_writer, "hello\n")
}
fn test_ansi<T>(
@@ -1796,124 +1598,6 @@ 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>>,
@@ -1922,14 +1606,14 @@ pub(super) mod test {
T: Send + Sync + 'static,
{
let make_writer = MockMakeWriter::default();
- let subscriber = builder
+ let collector = builder
.with_writer(make_writer.clone())
.with_level(false)
.with_ansi(false)
.with_timer(MockTime)
.finish();
- with_default(subscriber, || {
+ with_default(collector, || {
let span1 = tracing::info_span!("span1", span = 1);
let span2 = tracing::info_span!(parent: &span1, "span2", span = 2);
tracing::info!(parent: &span2, "hello");
@@ -1975,21 +1659,6 @@ 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() {
@@ -2079,26 +1748,6 @@ 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 {
@@ -2146,16 +1795,4 @@ 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-0.3.3/src/fmt/format/pretty.rs
index a50d08ba7..3e47e2d93 100644
--- a/vendor/tracing-subscriber/src/fmt/format/pretty.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/format/pretty.rs
@@ -17,84 +17,6 @@ use tracing_log::NormalizeEvent;
use ansi_term::{Colour, 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,
@@ -154,10 +76,6 @@ impl Pretty {
/// 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,
@@ -166,6 +84,17 @@ impl Pretty {
}
}
+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>,
@@ -218,37 +147,12 @@ where
};
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()?;
@@ -260,21 +164,20 @@ where
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' })?;
+ 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"))?;
@@ -283,12 +186,13 @@ where
if let Some(name) = thread.name() {
write!(writer, "{}", name)?;
if self.display_thread_id {
- writer.write_char(' ')?;
+ write!(writer, " ({:?})", thread.id())?;
}
+ } else if !self.display_thread_id {
+ write!(writer, " {:?}", thread.id())?;
}
- }
- if self.display_thread_id {
- write!(writer, "{:?}", thread.id())?;
+ } else if self.display_thread_id {
+ write!(writer, " {:?}", thread.id())?;
}
writer.write_char('\n')?;
}
@@ -336,7 +240,7 @@ where
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);
+ let mut v = PrettyVisitor::new(writer, false);
fields.record(&mut v);
v.finish()
}
diff --git a/vendor/tracing-subscriber/src/fmt/mod.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs
index 3c6a6ac40..d5deb8f0c 100644
--- a/vendor/tracing-subscriber/src/fmt/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/mod.rs
@@ -13,12 +13,10 @@
//!
//! ```toml
//! [dependencies]
-//! tracing-subscriber = "0.3"
+//! tracing-subscriber = "0.2"
//! ```
//!
-//! *Compiler support: [requires `rustc` 1.49+][msrv]*
-//!
-//! [msrv]: super#supported-rust-versions
+//! *Compiler support: requires rustc 1.39+*
//!
//! Add the following to your executable to initialize the default subscriber:
//! ```rust
@@ -70,25 +68,132 @@
//!
//! * [`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. See
-//! [here](format::Full#example-output) for sample output.
+//! displayed before the formatted representation of the event.
//!
-//! * [`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.
+//! 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::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](format::Pretty#example-output)
-//! for sample output.
+//! 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>
//!
//! * [`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 is not optimized for human
-//! readability. See [here](format::Json#example-output) for sample output.
+//! 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>
//!
//! ### Customizing Formatters
//!
@@ -116,7 +221,7 @@
//! .with_thread_names(true) // include the name of the current thread
//! .compact(); // use the `Compact` formatting style.
//!
-//! // Create a `fmt` subscriber that uses our custom event format, and set it
+//! // Create a `fmt` collector that uses our custom event format, and set it
//! // as the default.
//! tracing_subscriber::fmt()
//! .event_format(format)
@@ -163,7 +268,7 @@
//!
//! ### Composing Layers
//!
-//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`][super::fmt::Layer]:
+//! Composing an [`EnvFilter`] `Layer` and a [format `Layer`](../fmt/struct.Layer.html):
//!
//! ```rust
//! use tracing_subscriber::{fmt, EnvFilter};
@@ -181,10 +286,11 @@
//! .init();
//! ```
//!
-//! [`EnvFilter`]: super::filter::EnvFilter
+//! [`EnvFilter`]: ../filter/struct.EnvFilter.html
//! [`env_logger`]: https://docs.rs/env_logger/
-//! [`filter`]: super::filter
-//! [`FmtSubscriber`]: Subscriber
+//! [`filter`]: ../filter/index.html
+//! [`SubscriberBuilder`]: ./struct.SubscriberBuilder.html
+//! [`FmtSubscriber`]: ./struct.Subscriber.html
//! [`Subscriber`]:
//! https://docs.rs/tracing/latest/tracing/trait.Subscriber.html
//! [`tracing`]: https://crates.io/crates/tracing
@@ -203,7 +309,6 @@ pub mod writer;
pub use fmt_layer::{FmtContext, FormattedFields, Layer};
use crate::layer::Layer as _;
-use crate::util::SubscriberInitExt;
use crate::{
filter::LevelFilter,
layer,
@@ -312,7 +417,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()
@@ -324,11 +429,10 @@ 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()
@@ -340,8 +444,8 @@ impl Subscriber {
///
/// This can be overridden with the [`SubscriberBuilder::with_max_level`] method.
///
- /// [verbosity level]: tracing_core::Level
- /// [`SubscriberBuilder::with_max_level`]: SubscriberBuilder::with_max_level
+ /// [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
pub const DEFAULT_MAX_LEVEL: LevelFilter = LevelFilter::INFO;
/// Returns a new `SubscriberBuilder` for configuring a format subscriber.
@@ -398,11 +502,6 @@ where
}
#[inline]
- fn event_enabled(&self, event: &Event<'_>) -> bool {
- self.inner.event_enabled(event)
- }
-
- #[inline]
fn event(&self, event: &Event<'_>) {
self.inner.event(event);
}
@@ -602,7 +701,7 @@ where
/// `Layer`s added to this subscriber.
///
/// [lifecycle]: https://docs.rs/tracing/latest/tracing/span/index.html#the-span-lifecycle
- /// [time]: SubscriberBuilder::without_time()
+ /// [time]: #method.without_time
pub fn with_span_events(self, kind: format::FmtSpan) -> Self {
SubscriberBuilder {
inner: self.inner.with_span_events(kind),
@@ -631,34 +730,6 @@ 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,
@@ -671,9 +742,9 @@ where
}
/// Sets whether or not the [name] of the current thread is displayed
- /// when formatting events.
+ /// when formatting events
///
- /// [name]: std::thread#naming-threads
+ /// [name]: https://doc.rust-lang.org/stable/std/thread/index.html#naming-threads
pub fn with_thread_names(
self,
display_thread_names: bool,
@@ -685,9 +756,9 @@ where
}
/// Sets whether or not the [thread ID] of the current thread is displayed
- /// when formatting events.
+ /// when formatting events
///
- /// [thread ID]: std::thread::ThreadId
+ /// [thread ID]: https://doc.rust-lang.org/stable/std/thread/struct.ThreadId.html
pub fn with_thread_ids(
self,
display_thread_ids: bool,
@@ -725,7 +796,7 @@ where
/// Sets the subscriber being built to use a JSON formatter.
///
- /// See [`format::Json`][super::fmt::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
#[cfg(feature = "json")]
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
pub fn json(
@@ -746,7 +817,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`][super::fmt::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn flatten_event(
self,
flatten_event: bool,
@@ -760,7 +831,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`][super::fmt::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn with_current_span(
self,
display_current_span: bool,
@@ -774,7 +845,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`][super::fmt::format::Json]
+ /// See [`format::Json`](../fmt/format/struct.Json.html)
pub fn with_span_list(
self,
display_span_list: bool,
@@ -820,7 +891,7 @@ where
}
impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
- /// Sets the field formatter that the subscriber being built will use to record
+ /// Sets the Visitor that the subscriber being built will use to record
/// fields.
///
/// For example:
@@ -896,8 +967,8 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// .try_init()?;
/// # Ok(())}
/// ```
- /// [`EnvFilter`]: super::filter::EnvFilter
- /// [`with_max_level`]: SubscriberBuilder::with_max_level()
+ /// [`EnvFilter`]: ../filter/struct.EnvFilter.html
+ /// [`with_max_level`]: #method.with_max_level
#[cfg(feature = "env-filter")]
#[cfg_attr(docsrs, doc(cfg(feature = "env-filter")))]
pub fn with_env_filter(
@@ -918,7 +989,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_env_filter`], this replaces that configuration with the new
+ /// [`with_filter`], this replaces that configuration with the new
/// maximum level.
///
/// # Examples
@@ -940,9 +1011,9 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
/// .with_max_level(LevelFilter::OFF)
/// .finish();
/// ```
- /// [verbosity level]: tracing_core::Level
- /// [`EnvFilter`]: struct@crate::filter::EnvFilter
- /// [`with_env_filter`]: fn@Self::with_env_filter
+ /// [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
pub fn with_max_level(
self,
filter: impl Into<LevelFilter>,
@@ -954,26 +1025,8 @@ impl<N, E, F, W> SubscriberBuilder<N, E, F, W> {
}
}
- /// 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
+ /// Sets the function that the subscriber being built should use to format
+ /// events that occur.
pub fn event_format<E2>(self, fmt_event: E2) -> SubscriberBuilder<N, E2, F, W>
where
E2: FormatEvent<Registry, N> + 'static,
@@ -1000,6 +1053,8 @@ 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,
@@ -1033,89 +1088,13 @@ 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::TestWriter
+ /// [`TestWriter`]: writer/struct.TestWriter.html
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
@@ -1142,44 +1121,15 @@ 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]: crate::filter::EnvFilter::DEFAULT_ENV
+/// [`RUST_LOG` environment variable]:
+/// ../filter/struct.EnvFilter.html#associatedconstant.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());
- // 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)
+ builder.try_init()
}
/// Install a global tracing subscriber that listens for events and
@@ -1198,7 +1148,8 @@ pub fn try_init() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
/// Panics if the initialization was unsuccessful, likely because a
/// global subscriber was already installed by another call to `try_init`.
///
-/// [`RUST_LOG` environment variable]: crate::filter::EnvFilter::DEFAULT_ENV
+/// [`RUST_LOG` environment variable]:
+/// ../filter/struct.EnvFilter.html#associatedconstant.DEFAULT_ENV
pub fn init() {
try_init().expect("Unable to install global subscriber")
}
diff --git a/vendor/tracing-subscriber/src/fmt/time/datetime.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs
index 531331687..531331687 100644
--- a/vendor/tracing-subscriber/src/fmt/time/datetime.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/time/datetime.rs
diff --git a/vendor/tracing-subscriber/src/fmt/time/mod.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs
index e5b7c83b0..621df16e4 100644
--- a/vendor/tracing-subscriber/src/fmt/time/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/time/mod.rs
@@ -12,13 +12,9 @@ mod time_crate;
pub use time_crate::UtcTime;
#[cfg(feature = "local-time")]
-#[cfg_attr(docsrs, doc(cfg(unsound_local_offset, feature = "local-time")))]
+#[cfg_attr(docsrs, doc(cfg(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.
@@ -30,7 +26,7 @@ pub use time_crate::OffsetTime;
///
/// The full list of provided implementations can be found in [`time`].
///
-/// [`time`]: self
+/// [`time`]: ./index.html
pub trait FormatTime {
/// Measure and write out the current time.
///
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
new file mode 100644
index 000000000..64d274365
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/time/time_crate.rs
@@ -0,0 +1,276 @@
+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/src/fmt/writer.rs b/vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs
index 4aacd6d54..0974891f7 100644
--- a/vendor/tracing-subscriber/src/fmt/writer.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/fmt/writer.rs
@@ -1,6 +1,6 @@
//! Abstractions for creating [`io::Write`] instances.
//!
-//! [`io::Write`]: std::io::Write
+//! [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
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`]: std::io::Write
- /// [`make_writer`]: MakeWriter::make_writer
+ /// [`io::Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
+ /// [`make_writer`]: #tymethod.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`]: MakeWriter::Writer
+ /// [`Writer`]: #associatedtype.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`]: super::Subscriber
-/// [`fmt::Layer`]: super::Layer
+/// [`fmt::Subscriber`]: ../struct.Subscriber.html
+/// [`fmt::Layer`]: ../struct.Layer.html
/// [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`]: std::io::stdout
-/// [`io::stderr`]: std::io::stderr
-/// [`print!`]: std::print!
+/// [`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
#[derive(Default, Debug)]
pub struct TestWriter {
_p: (),
@@ -646,9 +646,10 @@ 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`]: std::io::Write
-/// [`MutexGuard`]: std::sync::MutexGuard
-/// [`Mutex`]: std::sync::Mutex
+/// [`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
#[derive(Debug)]
pub struct MutexGuardWriter<'a, W>(MutexGuard<'a, W>);
@@ -733,6 +734,7 @@ 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,
@@ -1023,8 +1025,6 @@ 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/src/layer/context.rs b/vendor/tracing-subscriber-0.3.3/src/layer/context.rs
index 46254994f..e11959526 100644
--- a/vendor/tracing-subscriber/src/layer/context.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/layer/context.rs
@@ -25,10 +25,10 @@ use crate::{filter::FilterId, registry::Registry};
/// }
/// ```
///
-/// [`Layer`]: super::Layer
-/// [`Subscriber`]: tracing_core::Subscriber
-/// [stored data]: crate::registry::SpanRef
-/// [`LookupSpan`]: crate::registry::LookupSpan
+/// [`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
#[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]: tracing_core::subscriber::Subscriber::register_callsite()
- /// [`enabled`]: tracing_core::subscriber::Subscriber::enabled()
- /// [`Context::enabled`]: Context::enabled()
+ /// [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
#[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]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
#[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]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
#[inline]
pub fn lookup_current(&self) -> Option<registry::SpanRef<'_, S>>
where
@@ -333,7 +333,7 @@ where
/// declaration</a> for details.
/// </pre>
///
- /// [stored data]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
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]: crate::registry::SpanRef
+ /// [stored data]: ../registry/struct.SpanRef.html
pub fn event_scope(&self, event: &Event<'_>) -> Option<registry::Scope<'_, S>>
where
S: for<'lookup> LookupSpan<'lookup>,
diff --git a/vendor/tracing-subscriber/src/layer/layered.rs b/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs
index 805ec13dc..c690764ad 100644
--- a/vendor/tracing-subscriber/src/layer/layered.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/layer/layered.rs
@@ -12,17 +12,13 @@ use crate::{
};
#[cfg(all(feature = "registry", feature = "std"))]
use crate::{filter::FilterId, registry::Registry};
-use core::{
- any::{Any, TypeId},
- cmp, fmt,
- marker::PhantomData,
-};
+use core::{any::TypeId, cmp, fmt, marker::PhantomData};
/// A [`Subscriber`] composed of a `Subscriber` wrapped by one or more
/// [`Layer`]s.
///
/// [`Layer`]: crate::Layer
-/// [`Subscriber`]: tracing_core::Subscriber
+/// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html
#[derive(Clone)]
pub struct Layered<L, I, S = I> {
/// The layer.
@@ -67,30 +63,6 @@ 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>,
@@ -139,16 +111,6 @@ 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());
@@ -190,7 +152,7 @@ where
#[cfg(all(feature = "registry", feature = "std"))]
{
if let Some(g) = guard.as_mut() {
- g.set_closing()
+ g.is_closing()
};
}
@@ -289,17 +251,6 @@ 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);
@@ -435,7 +386,7 @@ where
// (rather than calling into the inner type), clear the current
// per-layer filter interest state.
#[cfg(feature = "registry")]
- filter::FilterState::take_interest();
+ drop(filter::FilterState::take_interest());
return outer;
}
diff --git a/vendor/tracing-subscriber/src/layer/mod.rs b/vendor/tracing-subscriber-0.3.3/src/layer/mod.rs
index 24b853323..f3f994490 100644
--- a/vendor/tracing-subscriber/src/layer/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/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,245 +135,9 @@
//! [`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
@@ -382,7 +146,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
@@ -394,7 +158,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
@@ -415,29 +179,7 @@
//! [`Interest::never()`] from its [`register_callsite`] method, filter
//! evaluation will short-circuit and the span or event will be disabled.
//!
-//! ### 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
+//! ### Per-Layer Filtering
//!
//! **Note**: per-layer filtering APIs currently require the [`"registry"` crate
//! feature flag][feat] to be enabled.
@@ -651,16 +393,94 @@
//! # Ok(()) }
//! ```
//!
-//! [`Subscriber`]: tracing_core::subscriber::Subscriber
-//! [span IDs]: tracing_core::span::Id
+//! ## Runtime Configuration With Layers
+//!
+//! In some cases, a particular [`Layer`] may be enabled or disabled based on
+//! runtime configuration. This can introduce challenges, because the type of a
+//! layered [`Subscriber`] depends on which layers are added to it: if an `if`
+//! or `match` expression adds some [`Layer`]s in one branch and other layers
+//! in another, the [`Subscriber`] values returned by those branches will have
+//! different types. For example, the following _will not_ work:
+//!
+//! ```compile_fail
+//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
+//! # struct Config {
+//! # is_prod: bool,
+//! # path: &'static str,
+//! # }
+//! # let cfg = Config { is_prod: false, path: "debug.log" };
+//! use std::{fs::File, sync::Arc};
+//! use tracing_subscriber::{Registry, prelude::*};
+//!
+//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
+//! let subscriber = Registry::default().with(stdout_log);
+//!
+//! // The compile error will occur here because the if and else
+//! // branches have different (and therefore incompatible) types.
+//! let subscriber = if cfg.is_prod {
+//! let file = File::create(cfg.path)?;
+//! let layer = tracing_subscriber::fmt::layer()
+//! .json()
+//! .with_writer(Arc::new(file));
+//! subscriber.with(layer)
+//! } else {
+//! subscriber
+//! };
+//!
+//! tracing::subscriber::set_global_default(subscriber)
+//! .expect("Unable to set global subscriber");
+//! # Ok(()) }
+//! ```
+//!
+//! However, a [`Layer`] wrapped in an [`Option`] [also implements the `Layer`
+//! trait][option-impl]. This allows individual layers to be enabled or disabled at
+//! runtime while always producing a [`Subscriber`] of the same type. For
+//! example:
+//!
+//! ```
+//! # fn docs() -> Result<(), Box<dyn std::error::Error + 'static>> {
+//! # struct Config {
+//! # is_prod: bool,
+//! # path: &'static str,
+//! # }
+//! # let cfg = Config { is_prod: false, path: "debug.log" };
+//! use std::{fs::File, sync::Arc};
+//! use tracing_subscriber::{Registry, prelude::*};
+//!
+//! let stdout_log = tracing_subscriber::fmt::layer().pretty();
+//! let subscriber = Registry::default().with(stdout_log);
+//!
+//! // if `cfg.is_prod` is true, also log JSON-formatted logs to a file.
+//! let json_log = if cfg.is_prod {
+//! let file = File::create(cfg.path)?;
+//! let json_log = tracing_subscriber::fmt::layer()
+//! .json()
+//! .with_writer(Arc::new(file));
+//! Some(json_log)
+//! } else {
+//! None
+//! };
+//!
+//! // If `cfg.is_prod` is false, then `json` will be `None`, and this layer
+//! // will do nothing. However, the subscriber will still have the same type
+//! // regardless of whether the `Option`'s value is `None` or `Some`.
+//! let subscriber = subscriber.with(json_log);
+//!
+//! tracing::subscriber::set_global_default(subscriber)
+//! .expect("Unable to set global subscriber");
+//! # Ok(()) }
+//! ```
+//!
+//! [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
+//! [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html
//! [the current span]: Context::current_span
//! [`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()`]: tracing_core::subscriber::Interest::never()
+//! [`Interest::never()`]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/struct.Interest.html#method.never
+//! [option-impl]: crate::layer::Layer#impl-Layer<S>-for-Option<L>
//! [`Filtered`]: crate::filter::Filtered
//! [`filter`]: crate::filter
//! [`Targets`]: crate::filter::Targets
@@ -772,15 +592,15 @@ where
/// globally enable or disable those callsites, it should always return
/// [`Interest::always()`].
///
- /// [`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()
+ /// [`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
/// [the trait-level documentation]: #filtering-with-layers
fn register_callsite(&self, metadata: &'static Metadata<'static>) -> Interest {
if self.enabled(metadata, Context::none()) {
@@ -815,12 +635,13 @@ where
/// See [the trait-level documentation] for more information on filtering
/// with `Layer`s.
///
- /// [`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()
+ /// [`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
/// [the trait-level documentation]: #filtering-with-layers
fn enabled(&self, metadata: &Metadata<'_>, ctx: Context<'_, S>) -> bool {
let _ = (metadata, ctx);
@@ -855,31 +676,6 @@ 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>) {}
@@ -1044,7 +840,7 @@ where
/// .with_subscriber(MySubscriber::new());
///```
///
- /// [`Subscriber`]: tracing_core::Subscriber
+ /// [`Subscriber`]: https://docs.rs/tracing-core/latest/tracing_core/trait.Subscriber.html
fn with_subscriber(mut self, mut inner: S) -> Layered<Self, S>
where
Self: Sized,
@@ -1061,7 +857,7 @@ where
/// per-layer filtering.
///
/// [`Filtered`]: crate::filter::Filtered
- /// [plf]: crate::layer#per-layer-filtering
+ /// [plf]: #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>
@@ -1072,131 +868,6 @@ 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>() {
@@ -1209,7 +880,6 @@ where
feature! {
#![all(feature = "registry", feature = "std")]
-
/// A per-[`Layer`] filter that determines whether a span or event is enabled
/// for an individual layer.
///
@@ -1384,51 +1054,6 @@ 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);
- }
}
}
@@ -1490,11 +1115,7 @@ where
fn max_level_hint(&self) -> Option<LevelFilter> {
match self {
Some(ref inner) => inner.max_level_hint(),
- None => {
- // There is no inner layer, so this layer will
- // never enable anything.
- Some(LevelFilter::OFF)
- }
+ None => None,
}
}
@@ -1513,14 +1134,6 @@ 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);
@@ -1568,8 +1181,6 @@ where
feature! {
#![any(feature = "std", feature = "alloc")]
- #[cfg(not(feature = "std"))]
- use alloc::vec::Vec;
macro_rules! layer_impl_body {
() => {
@@ -1609,11 +1220,6 @@ 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)
}
@@ -1660,125 +1266,6 @@ 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/src/layer/tests.rs b/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs
index d7ad61769..d7ad61769 100644
--- a/vendor/tracing-subscriber/src/layer/tests.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/layer/tests.rs
diff --git a/vendor/tracing-subscriber/src/lib.rs b/vendor/tracing-subscriber-0.3.3/src/lib.rs
index 9de70a90d..563a86dee 100644
--- a/vendor/tracing-subscriber/src/lib.rs
+++ b/vendor/tracing-subscriber-0.3.3/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.49+][msrv]*
+//! *Compiler support: [requires `rustc` 1.42+][msrv]*
//!
//! [msrv]: #supported-rust-versions
//!
@@ -60,11 +60,9 @@
//! **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`
@@ -82,7 +80,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 [`Layer`] trait, can still be used in
+//! functionality, such as the [`Subscriber`] trait, can still be used in
//! `no_std` environments.
//!
//! The dependency on the standard library is controlled by two crate feature
@@ -104,41 +102,10 @@
//! 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.49. The current Tracing version is not guaranteed to build on
+//! version is 1.42. 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
@@ -149,18 +116,17 @@
//! supported compiler version is not considered a semver breaking change as
//! long as doing so complies with this policy.
//!
-//! [`Subscriber`]: tracing_core::subscriber::Subscriber
-//! [`tracing`]: https://docs.rs/tracing/latest/tracing
-//! [`EnvFilter`]: filter::EnvFilter
-//! [`fmt`]: mod@fmt
+//! [`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
//! [`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
-//! [`libstd`]: std
-//! [`liballoc`]: alloc
-#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.15")]
+//! [`liballoc`]: https://doc.rust-lang.org/alloc/index.html
+#![doc(html_root_url = "https://docs.rs/tracing-subscriber/0.3.1")]
#![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/src/macros.rs b/vendor/tracing-subscriber-0.3.3/src/macros.rs
index 81351132f..81351132f 100644
--- a/vendor/tracing-subscriber/src/macros.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/macros.rs
diff --git a/vendor/tracing-subscriber/src/prelude.rs b/vendor/tracing-subscriber-0.3.3/src/prelude.rs
index c2230907b..c2230907b 100644
--- a/vendor/tracing-subscriber/src/prelude.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/prelude.rs
diff --git a/vendor/tracing-subscriber/src/registry/extensions.rs b/vendor/tracing-subscriber-0.3.3/src/registry/extensions.rs
index ff76fb599..899e1549f 100644
--- a/vendor/tracing-subscriber/src/registry/extensions.rs
+++ b/vendor/tracing-subscriber-0.3.3/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`](std::string::String), to avoid accidental
+ /// types like [`String`](https://doc.rust-lang.org/std/string/struct.String.html), to avoid accidental
/// cross-`Layer` clobbering.
///
/// ## Panics
diff --git a/vendor/tracing-subscriber/src/registry/mod.rs b/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs
index 38af53e8a..f3b77b6a9 100644
--- a/vendor/tracing-subscriber/src/registry/mod.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/registry/mod.rs
@@ -55,7 +55,8 @@
//! require the root subscriber to be a registry.
//!
//! [`Layer`]: crate::layer::Layer
-//! [`Subscriber`]: tracing_core::Subscriber
+//! [`Subscriber`]:
+//! https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html
//! [ctx]: crate::layer::Context
//! [lookup]: crate::layer::Context::span()
use tracing_core::{field::FieldSet, span::Id, Metadata};
@@ -86,9 +87,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`]: super::layer::Layer
-/// [`Context`]: super::layer::Context
-/// [`span()`]: super::layer::Context::span
+/// [`Layer`]: ../layer/trait.Layer.html
+/// [`Context`]: ../layer/struct.Context.html
+/// [`span()`]: ../layer/struct.Context.html#method.span
pub trait LookupSpan<'a> {
/// The type of span data stored in this registry.
type Data: SpanData<'a>;
@@ -103,6 +104,7 @@ 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.
@@ -114,7 +116,9 @@ pub trait LookupSpan<'a> {
/// rather than the [`span_data`] method; while _implementors_ of this trait
/// should only implement `span_data`.
///
- /// [`span_data`]: LookupSpan::span_data()
+ /// [`SpanRef`]: struct.SpanRef.html
+ /// [`SpanData`]: trait.SpanData.html
+ /// [`span_data`]: #method.span_data
fn span(&'a self, id: &Id) -> Option<SpanRef<'_, Self>>
where
Self: Sized,
@@ -204,8 +208,8 @@ pub trait SpanData<'a> {
/// provides additional methods for querying the registry based on values from
/// the span.
///
-/// [span data]: SpanData
-/// [registry]: LookupSpan
+/// [span data]: trait.SpanData.html
+/// [registry]: trait.LookupSpan.html
#[derive(Debug)]
pub struct SpanRef<'a, R: LookupSpan<'a>> {
registry: &'a R,
@@ -356,7 +360,7 @@ where
/// Returns a list of [fields] defined by the span.
///
- /// [fields]: tracing_core::field
+ /// [fields]: https://docs.rs/tracing-core/latest/tracing_core/field/index.html
pub fn fields(&self) -> &FieldSet {
self.data.metadata().fields()
}
diff --git a/vendor/tracing-subscriber/src/registry/sharded.rs b/vendor/tracing-subscriber-0.3.3/src/registry/sharded.rs
index b81d5fef8..a6311cb71 100644
--- a/vendor/tracing-subscriber/src/registry/sharded.rs
+++ b/vendor/tracing-subscriber-0.3.3/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]: tracing_core::span::Id
-/// [slab]: sharded_slab
+/// [span IDs]: https://docs.rs/tracing-core/latest/tracing_core/span/struct.Id.html
+/// [slab]: https://docs.rs/crate/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]: tracing_core::subscriber::Subscriber::try_close()
+/// [considered closed]: https://docs.rs/tracing-core/latest/tracing_core/subscriber/trait.Subscriber.html#method.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]: tracing_core::field
+/// [fields]: https://docs.rs/tracing-core/latest/tracing-core/field/index.html
/// [stored span data]: crate::registry::SpanData::extensions_mut
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
@@ -102,8 +102,9 @@ pub struct Registry {
/// [`Layer`s], such as formatted fields, metrics, or distributed traces should
/// be stored in the [extensions] typemap.
///
-/// [`Layer`s]: crate::layer::Layer
-/// [extensions]: Extensions
+/// [`Registry`]: struct.Registry.html
+/// [`Layer`s]: ../layer/trait.Layer.html
+/// [extensions]: struct.Extensions.html
#[cfg(feature = "registry")]
#[cfg_attr(docsrs, doc(cfg(all(feature = "registry", feature = "std"))))]
#[derive(Debug)]
@@ -114,11 +115,10 @@ 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,6 +173,7 @@ 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,
@@ -188,6 +189,7 @@ 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();
@@ -214,6 +216,7 @@ 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);
}
@@ -377,7 +380,7 @@ impl<'a> LookupSpan<'a> for Registry {
// === impl CloseGuard ===
impl<'a> CloseGuard<'a> {
- pub(crate) fn set_closing(&mut self) {
+ pub(crate) fn is_closing(&mut self) {
self.is_closing = true;
}
}
diff --git a/vendor/tracing-subscriber/src/registry/stack.rs b/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs
index 4a3f7e59d..4a3f7e59d 100644
--- a/vendor/tracing-subscriber/src/registry/stack.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/registry/stack.rs
diff --git a/vendor/tracing-subscriber/src/reload.rs b/vendor/tracing-subscriber-0.3.3/src/reload.rs
index 0c6c1c45c..b8ec67dfa 100644
--- a/vendor/tracing-subscriber/src/reload.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/reload.rs
@@ -1,69 +1,16 @@
//! 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
+//! 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 `Layer` or `Filter` functionality
+//! 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.
//!
-//! # 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
+//! [`Layer` type]: struct.Layer.html
+//! [`Layer` trait]: ../layer/trait.Layer.html
use crate::layer;
use crate::sync::RwLock;
@@ -75,10 +22,10 @@ use std::{
use tracing_core::{
callsite, span,
subscriber::{Interest, Subscriber},
- Event, LevelFilter, Metadata,
+ Event, Metadata,
};
-/// Wraps a `Layer` or `Filter`, allowing it to be reloaded dynamically at runtime.
+/// 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
@@ -89,7 +36,7 @@ pub struct Layer<L, S> {
_s: PhantomData<fn(S)>,
}
-/// Allows reloading the state of an associated [`Layer`](crate::layer::Layer).
+/// Allows reloading the state of an associated `Layer`.
#[derive(Debug)]
pub struct Handle<L, S> {
inner: Weak<RwLock<L>>,
@@ -145,11 +92,6 @@ where
}
#[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)
}
@@ -173,69 +115,15 @@ where
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()
- }
}
-// ===== 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>
+impl<L, S> Layer<L, S>
where
- L: crate::layer::Filter<S> + 'static,
+ L: crate::Layer<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
+ /// 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)),
@@ -245,10 +133,7 @@ impl<L, S> Layer<L, S> {
(this, handle)
}
- /// Returns a `Handle` that can be used to reload the wrapped [`Layer`] or [`Filter`].
- ///
- /// [`Layer`]: crate::layer::Layer
- /// [`Filter`]: crate::filter::Filter
+ /// 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),
@@ -259,27 +144,19 @@ impl<L, S> Layer<L, S> {
// ===== 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> {
+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_value.into();
+ *layer = new_layer.into();
})
}
- /// Invokes a closure with a mutable reference to the current layer or filter,
+ /// 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 {
@@ -296,7 +173,7 @@ impl<L, S> Handle<L, S> {
Ok(())
}
- /// Returns a clone of the layer or filter's current value if it still exists.
+ /// 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
@@ -305,7 +182,7 @@ impl<L, S> Handle<L, S> {
self.with_current(L::clone).ok()
}
- /// Invokes a closure with a borrowed reference to the current layer or filter,
+ /// 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 {
diff --git a/vendor/tracing-subscriber/src/sync.rs b/vendor/tracing-subscriber-0.3.3/src/sync.rs
index ec42b834a..ec42b834a 100644
--- a/vendor/tracing-subscriber/src/sync.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/sync.rs
diff --git a/vendor/tracing-subscriber/src/util.rs b/vendor/tracing-subscriber-0.3.3/src/util.rs
index 1c98aa4d2..1c98aa4d2 100644
--- a/vendor/tracing-subscriber/src/util.rs
+++ b/vendor/tracing-subscriber-0.3.3/src/util.rs
diff --git a/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs
index 00e98a994..00e98a994 100644
--- a/vendor/tracing-subscriber/tests/cached_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/cached_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber/tests/duplicate_spans.rs b/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs
index 5d4dc6a85..c4a736f74 100644
--- a/vendor/tracing-subscriber/tests/duplicate_spans.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/duplicate_spans.rs
@@ -1,4 +1,5 @@
#![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/field_filter.rs b/vendor/tracing-subscriber-0.3.3/tests/field_filter.rs
index f14a0626d..12b4053b6 100644
--- a/vendor/tracing-subscriber/tests/field_filter.rs
+++ b/vendor/tracing-subscriber-0.3.3/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.rs b/vendor/tracing-subscriber-0.3.3/tests/filter.rs
new file mode 100644
index 000000000..8386d34d2
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/tests/filter.rs
@@ -0,0 +1,187 @@
+#![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/tests/filter_log.rs b/vendor/tracing-subscriber-0.3.3/tests/filter_log.rs
index 8d57ed600..28e742501 100644
--- a/vendor/tracing-subscriber/tests/filter_log.rs
+++ b/vendor/tracing-subscriber-0.3.3/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/tests/fmt_max_level_hint.rs b/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs
index 57a0f6e3f..57a0f6e3f 100644
--- a/vendor/tracing-subscriber/tests/fmt_max_level_hint.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/fmt_max_level_hint.rs
diff --git a/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs
index 897dae282..897dae282 100644
--- a/vendor/tracing-subscriber/tests/hinted_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/hinted_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs
index d89d3bf17..d89d3bf17 100644
--- a/vendor/tracing-subscriber/tests/layer_filter_interests_are_cached.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filter_interests_are_cached.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/boxed.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs
index 0fe37188e..0fe37188e 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/boxed.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/boxed.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs
index b5f7e35ce..b5f7e35ce 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/downcast_raw.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/downcast_raw.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs
index 7fd7d843b..7fd7d843b 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/filter_scopes.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/filter_scopes.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/main.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs
index 0233f063b..2359584d7 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/main.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/main.rs
@@ -7,10 +7,9 @@ mod downcast_raw;
mod filter_scopes;
mod targets;
mod trees;
-mod vec;
use tracing::{level_filters::LevelFilter, Level};
-use tracing_subscriber::{filter, prelude::*, Layer};
+use tracing_subscriber::{filter, prelude::*};
#[test]
fn basic_layer_filters() {
diff --git a/vendor/tracing-subscriber/tests/layer_filters/targets.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs
index c8133044b..c8133044b 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/targets.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/targets.rs
diff --git a/vendor/tracing-subscriber/tests/layer_filters/trees.rs b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs
index 18cdd8ccc..18cdd8ccc 100644
--- a/vendor/tracing-subscriber/tests/layer_filters/trees.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/layer_filters/trees.rs
diff --git a/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs b/vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs
index 5c25e7f03..5c25e7f03 100644
--- a/vendor/tracing-subscriber/tests/multiple_layer_filter_interests_cached.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/multiple_layer_filter_interests_cached.rs
diff --git a/vendor/tracing-subscriber/tests/registry_max_level_hint.rs b/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs
index f94c8a1fb..f94c8a1fb 100644
--- a/vendor/tracing-subscriber/tests/registry_max_level_hint.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/registry_max_level_hint.rs
diff --git a/vendor/tracing-subscriber/tests/registry_with_subscriber.rs b/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs
index 50d2f551d..3f8d99b1d 100644
--- a/vendor/tracing-subscriber/tests/registry_with_subscriber.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/registry_with_subscriber.rs
@@ -4,7 +4,7 @@ use tracing_subscriber::prelude::*;
#[tokio::test]
async fn future_with_subscriber() {
- tracing_subscriber::registry().init();
+ let _default = 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-0.3.3/tests/reload.rs b/vendor/tracing-subscriber-0.3.3/tests/reload.rs
new file mode 100644
index 000000000..5fe422e08
--- /dev/null
+++ b/vendor/tracing-subscriber-0.3.3/tests/reload.rs
@@ -0,0 +1,81 @@
+#![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/tests/same_len_filters.rs b/vendor/tracing-subscriber-0.3.3/tests/same_len_filters.rs
index 879e578d7..b525ea6fd 100644
--- a/vendor/tracing-subscriber/tests/same_len_filters.rs
+++ b/vendor/tracing-subscriber-0.3.3/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/tests/support.rs b/vendor/tracing-subscriber-0.3.3/tests/support.rs
index 50e0e6669..848ebdc63 100644
--- a/vendor/tracing-subscriber/tests/support.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/support.rs
@@ -1,15 +1,20 @@
#![allow(missing_docs, dead_code)]
-pub use tracing_mock::{event, field, span, subscriber};
-
-use tracing_core::{
- span::{Attributes, Id, Record},
- Event, Subscriber,
-};
-use tracing_mock::{
+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},
};
+use tracing_core::{
+ span::{Attributes, Id, Record},
+ Event, Subscriber,
+};
use tracing_subscriber::{
layer::{Context, Layer},
registry::{LookupSpan, SpanRef},
diff --git a/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs b/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs
index 9fa5c6bd4..9fa5c6bd4 100644
--- a/vendor/tracing-subscriber/tests/unhinted_layer_filters_dont_break_other_layers.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/unhinted_layer_filters_dont_break_other_layers.rs
diff --git a/vendor/tracing-subscriber/tests/utils.rs b/vendor/tracing-subscriber-0.3.3/tests/utils.rs
index e95868d5e..ff025a2a2 100644
--- a/vendor/tracing-subscriber/tests/utils.rs
+++ b/vendor/tracing-subscriber-0.3.3/tests/utils.rs
@@ -1,6 +1,6 @@
#![cfg(feature = "std")]
-
-use tracing_mock::*;
+mod support;
+use self::support::*;
use tracing_subscriber::prelude::*;
#[test]
diff --git a/vendor/tracing-subscriber/.cargo-checksum.json b/vendor/tracing-subscriber/.cargo-checksum.json
deleted file mode 100644
index 6c6c14337..000000000
--- a/vendor/tracing-subscriber/.cargo-checksum.json
+++ /dev/null
@@ -1 +0,0 @@
-{"files":{"CHANGELOG.md":"299c9f1c6c293156f3d0b9cd203c676b40ae173c9b1c2ee32ad360c1c11351b7","Cargo.toml":"488b9c72556062f1b1a8eca5d98bbe369f2e54fb103e9a23a0c2885e4bb8a086","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"b34fd001abef8b8e1455ad0f1f5e8e13eb578aafc60ea877772adb4c2c9fc39a","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":"8f527b1b0e3d9c572046235e0304146a574fe114b757af90a1c07851a07ba2cf","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":"abf90b8d7a21486b28f20d4b648395b2b95a35b526bbdaba63bd2c0181ae9e87","src/filter/layer_filters/mod.rs":"2046a860b21751791dae61d20219b3d59049b84fb289ea1fca7796d214c5643c","src/filter/level.rs":"cc449757aac47caaf19dd5ba4d74c8efbcd7531fcd6c13da0c5f6fdda12cc9ca","src/filter/mod.rs":"8ebfd0dc92415ff27ec552f20919e598842a87186f13f120449053a96e1e3307","src/filter/targets.rs":"eaa11d620017269770da5b2b97302b3beb81187242912260ca98e6d60ea77780","src/fmt/fmt_layer.rs":"5042d3e2eba5f68e9041c94b52f26ab17b84f68c54d16e4c0edd9d3a3699f727","src/fmt/format/json.rs":"554985ed40f7c59787aae87626144241ca973929e33979c54f821b673b71fec9","src/fmt/format/mod.rs":"a5f6b879802d353192235cf85aa8653afa3e8ead09955e631a39415324ce42d2","src/fmt/format/pretty.rs":"30fac9a916f3b9f572efa3b650c6dab7d86a57ce903cdbba6c6c0a52064cf238","src/fmt/mod.rs":"d5274d1f8106dc7497d2be7c6d874aeca15b9ca0fd4e0c6775d3774e75b30099","src/fmt/time/datetime.rs":"778d4604d800e46b940087394e7b72750738b554e02aea523fa9820ab0768c08","src/fmt/time/mod.rs":"30c97a9d3abd099f52c4c91c7b5f0d29ed9d54d80d1718c6fb74bfd664589de1","src/fmt/time/time_crate.rs":"1bfd59516a583e396afc1770250aa8c06b52f6162a6e7b2cadb860b7eebd9d76","src/fmt/writer.rs":"1931125cf14019b66b42a9ff95e5794f344697f799c021b4a7d48fd7eb7b58f4","src/layer/context.rs":"77137d8b2810c9059ce7838c3b665748bcb9765487d6103b92596e08b0e9e84b","src/layer/layered.rs":"945e42296ce3e86aa405eb31efdef4346cdfd84111f36700cc73e473e3ce5b28","src/layer/mod.rs":"b4febff42ea5ae12b92b8c73b7c691d9486e671446da99669fc5348314721cc9","src/layer/tests.rs":"3e974d627c4bc4269cfa10c82c890e596c9d46af8e6bc03c6c117bde1237e948","src/lib.rs":"8c1a26a319318768432b1025a2d0b08544bf2698b0a278fbb07211e22b22cd73","src/macros.rs":"e184bffc6b5999c48e365ad08343dca764a5fb711b789beb26bd1d5f1d767726","src/prelude.rs":"088635def33be9a4c4b6ed934dc22540c555e27d62f7625a43aa9c0e525ca467","src/registry/extensions.rs":"0418b39287bbc06cc95b8cecd6a25aa808b8e04714d842340ff75db458cafe5b","src/registry/mod.rs":"76627b056ce39d006708a6273b6418d001b688f016f58aa546e7821d1ef7f3bb","src/registry/sharded.rs":"aaac353632b1bbb804048b40cdfce9877688efa0679ae42ab36a095fd3e3877f","src/registry/stack.rs":"9ef333d6a8a28a064e80ff1e376dbb07bc597009010ec332b2dc3ab435d737c2","src/reload.rs":"caec4e23cf879ccc7c16bccbc99e20b8a20e27565c4edc6c527e094b7d0bb097","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":"fe0ed219b79bcbb2ece4c224ee5bf05662fe3b23a224f746b273afdb1abc0fbd","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":"071af56d21e1438b112c7698790328f4797d2d4dd4c7e4857ea8d4825f1fac89","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":"60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"} \ No newline at end of file
diff --git a/vendor/tracing-subscriber/src/filter/env/builder.rs b/vendor/tracing-subscriber/src/filter/env/builder.rs
deleted file mode 100644
index 36b520543..000000000
--- a/vendor/tracing-subscriber/src/filter/env/builder.rs
+++ /dev/null
@@ -1,324 +0,0 @@
-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)]
-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 = "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 collector, 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!("{} {}", prefix, 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, 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/src/filter/layer_filters/combinator.rs b/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs
deleted file mode 100644
index e79de2087..000000000
--- a/vendor/tracing-subscriber/src/filter/layer_filters/combinator.rs
+++ /dev/null
@@ -1,469 +0,0 @@
-//! 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::or`] method. See that
-/// method's documentation for details.
-///
-/// [`Filter`]: crate::layer::Filter
-/// [`FilterExt::or`]: crate::filter::FilterExt::or
-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 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 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.
- ///
- /// [`Filter`]: crate::layer::Filter
- 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 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/src/fmt/time/time_crate.rs b/vendor/tracing-subscriber/src/fmt/time/time_crate.rs
deleted file mode 100644
index 60d57fd0b..000000000
--- a/vendor/tracing-subscriber/src/fmt/time/time_crate.rs
+++ /dev/null
@@ -1,470 +0,0 @@
-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/tests/env_filter/main.rs b/vendor/tracing-subscriber/tests/env_filter/main.rs
deleted file mode 100644
index 3c3d4868b..000000000
--- a/vendor/tracing-subscriber/tests/env_filter/main.rs
+++ /dev/null
@@ -1,547 +0,0 @@
-#![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
deleted file mode 100644
index 8bf5698a4..000000000
--- a/vendor/tracing-subscriber/tests/env_filter/per_layer.rs
+++ /dev/null
@@ -1,305 +0,0 @@
-//! 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
deleted file mode 100644
index 8f67cfcba..000000000
--- a/vendor/tracing-subscriber/tests/event_enabling.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-#![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/tests/layer_filters/combinators.rs b/vendor/tracing-subscriber/tests/layer_filters/combinators.rs
deleted file mode 100644
index 6052a2d00..000000000
--- a/vendor/tracing-subscriber/tests/layer_filters/combinators.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-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/tests/layer_filters/vec.rs b/vendor/tracing-subscriber/tests/layer_filters/vec.rs
deleted file mode 100644
index 87244e4ab..000000000
--- a/vendor/tracing-subscriber/tests/layer_filters/vec.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-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/tests/option.rs b/vendor/tracing-subscriber/tests/option.rs
deleted file mode 100644
index 738cc0a6c..000000000
--- a/vendor/tracing-subscriber/tests/option.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-#![cfg(feature = "registry")]
-use tracing::level_filters::LevelFilter;
-use tracing::Subscriber;
-use tracing_subscriber::prelude::*;
-
-// 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));
-}
-
-#[test]
-fn just_option_none_layer() {
- let subscriber = tracing_subscriber::registry().with(Some(LevelFilter::ERROR));
- assert_eq!(subscriber.max_level_hint(), Some(LevelFilter::ERROR));
-}
diff --git a/vendor/tracing-subscriber/tests/reload.rs b/vendor/tracing-subscriber/tests/reload.rs
deleted file mode 100644
index 28662e2e6..000000000
--- a/vendor/tracing-subscriber/tests/reload.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-#![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/tests/vec.rs b/vendor/tracing-subscriber/tests/vec.rs
deleted file mode 100644
index 92abf0bff..000000000
--- a/vendor/tracing-subscriber/tests/vec.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-#![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
deleted file mode 100644
index 10467cb7d..000000000
--- a/vendor/tracing-subscriber/tests/vec_subscriber_filter_interests_cached.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-#![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/.cargo-checksum.json b/vendor/tracing/.cargo-checksum.json
index 7b9d07340..8bfa395bb 100644
--- a/vendor/tracing/.cargo-checksum.json
+++ b/vendor/tracing/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"dc3017cca8de9a33d8e0c3cba87b3977b1c84e1fe16ff87bc36614572ddd5832","Cargo.toml":"e4ffa43825ed68447646e39babd364b737b1353f95a7a6baa995879ad282952d","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"2a2ff5fa337287734c28e856a185afbced4cd656791a1aaeef0b982784e601d7","benches/baseline.rs":"43a3e31b6c33dba2e6328052301b707b212487b83f0dcffc843061a9c48a2319","benches/dispatch_get_clone.rs":"866239abeb74a82440741c948a4e7e0a44e92e8cc87319ec57e3b057c9e8f5dd","benches/dispatch_get_ref.rs":"dd2803259a6784c256304e676bbce05de233e4c8451ac85863787213343e9be7","benches/empty_span.rs":"9f51cf376414ea751b2f50c357f2435a545d606118286f5b8b89f185e28aad8c","benches/enter_span.rs":"4410ec73d277e7b54e9f306c00ff3b79a150d1832966b7fc29984c8e3ad8d57c","benches/event.rs":"98de3c82ed18abe0a3cbe6eda9a4f9deec2b69bca42c3aac11dea4b608b85a67","benches/shared.rs":"2623311af7d153685064e664a5903d03e7dc3179754c324f3a76f29f060515e6","benches/span_fields.rs":"9166cd43ef2783e5419dd61ea57a02e48e8cc38aa1b357e9b79fa581929b60d8","benches/span_no_fields.rs":"79cc4befacf27d7ce728246087c4f06a6066f913e831d9043caeb7941f0193f6","benches/span_repeated.rs":"e4b3c99a7a9fc15d9042b8db399a56cf647b4eebd26f29d95325bb057b68330b","src/dispatcher.rs":"a8158e1901c50dc83d2f15b1773e6b9e31985d9af65e460be52dbf8be6874cd2","src/field.rs":"55c7a2798b9ad0269e7c738c3f15a5d0281bf34ac3a6196a3f0b15801e5278bd","src/instrument.rs":"1fe4de5c13b5ba048e9872d78d1fa4e85655f9f2ed10f79b72b5da881c9b8b45","src/level_filters.rs":"baae8e797897bae9cdd9ec64b8e9a3d71156e9c03261be17b5b18acba034e154","src/lib.rs":"c7edb1602b2e9d164bc90f9d0dff48abb2fad840c07c6283481255fbe5d321e6","src/macros.rs":"f1a83930cea322f1f2000548d91800c22a9e28d2daf3f178c7c7c3ac8da5a02d","src/span.rs":"372695b3eda8354a892316826d2598f821fcb835fb18e1e0271767bce730b7ad","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"8933d8766439f929c0a98a0863d20aff37b221314b3825edd9058be511149968","tests/enabled.rs":"1333339aace87ea9d701f2f76a1985820cc513a75013a7ed89669f7a2c635479","tests/event.rs":"7678d1cc8a29ae8b716fbddb7cc4836422732ba3dce109ff511c8bb6100da606","tests/filter_caching_is_lexically_scoped.rs":"5487a37db5fbdf3d57020ab1f01185d928c45d967d99d723ffc434540459d8dc","tests/filters_are_not_reevaluated_for_the_same_span.rs":"251abbc000dddd298448958a1f0e5be71da527ac6c1a368d57837c83a5467329","tests/filters_are_reevaluated_for_different_call_sites.rs":"e0fdd8e930c043674702831b4d96f331e63aba824576bbac50b3f53bb0241cc7","tests/filters_dont_leak.rs":"d594266818a3461886da33bfcc76937d89a433ed6980226fc428706b216c093c","tests/future_send.rs":"3e9c9193219d12e342c18bbedb2f6ec940334202feb3cffba91601d6001b8575","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"fa83397181d73d2cae09c16d9647a63d1e3bad0f2dbc5b3280f69f3d0180c488","tests/macros_incompatible_concat.rs":"5f3bcbb65e4ae39db1cfc2def62fc913c20bab0fb769c8f731504e2615585ee5","tests/macros_redefined_core.rs":"a6eac60522f71fe6c9a040b8b869d596f7eb9e907f5b49f4be4413a40c387676","tests/max_level_hint.rs":"9b366591d947ca0202fa0bdf797e1bb14534d3c896cf8b9674660cd2807c32ef","tests/multiple_max_level_hints.rs":"4d9ef0de9cccc787da8f5e3f6c233ac9db42a2a99cfe5e39997e1f4aa9df0c00","tests/no_subscriber.rs":"2f8f2ada5089d8e2e503394dfe8206598a11895907c53bf940b892f1e6afdd2f","tests/register_callsite_deadlock.rs":"c0b3142543e7a10065c7583a8ee0b6bc978ea4f3979599651101c5a28966e7c8","tests/scoped_clobbers_default.rs":"806480a74c15e4d68bb7576050662b1e53ee765fd583d003f8b349f17ea63a4b","tests/span.rs":"f84ead5b1dad9b91e5cec9d8378ab932a942936374ba928fb381e67fab52cda0","tests/subscriber.rs":"1617c098f4fa6abed174fe062111444c7b67fa0f377d2b342176998e572480e3"},"package":"2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"dc8a552611986799a0eebb56fd119ea8ae32c9b8da4be9914fe127627ad4f38a","Cargo.toml":"f8d12a05bc7ed5cfef787db206c05cc5ebcd2c165e6e629b613d1a3ff4f138de","LICENSE":"898b1ae9821e98daf8964c8d6c7f61641f5f5aa78ad500020771c0939ee0dea1","README.md":"6ff17749109fbe0855220188015846f40d3997bc2631c3163496c183c0bd50ce","benches/baseline.rs":"43a3e31b6c33dba2e6328052301b707b212487b83f0dcffc843061a9c48a2319","benches/dispatch_get_clone.rs":"866239abeb74a82440741c948a4e7e0a44e92e8cc87319ec57e3b057c9e8f5dd","benches/dispatch_get_ref.rs":"dd2803259a6784c256304e676bbce05de233e4c8451ac85863787213343e9be7","benches/empty_span.rs":"9f51cf376414ea751b2f50c357f2435a545d606118286f5b8b89f185e28aad8c","benches/enter_span.rs":"4410ec73d277e7b54e9f306c00ff3b79a150d1832966b7fc29984c8e3ad8d57c","benches/event.rs":"98de3c82ed18abe0a3cbe6eda9a4f9deec2b69bca42c3aac11dea4b608b85a67","benches/shared.rs":"2623311af7d153685064e664a5903d03e7dc3179754c324f3a76f29f060515e6","benches/span_fields.rs":"9166cd43ef2783e5419dd61ea57a02e48e8cc38aa1b357e9b79fa581929b60d8","benches/span_no_fields.rs":"79cc4befacf27d7ce728246087c4f06a6066f913e831d9043caeb7941f0193f6","benches/span_repeated.rs":"e4b3c99a7a9fc15d9042b8db399a56cf647b4eebd26f29d95325bb057b68330b","src/dispatcher.rs":"a8732392ffe56b1178f8fd3d6e6e02d40b51475c38bb4600abd9cd170df1bf6c","src/field.rs":"55c7a2798b9ad0269e7c738c3f15a5d0281bf34ac3a6196a3f0b15801e5278bd","src/instrument.rs":"1fe4de5c13b5ba048e9872d78d1fa4e85655f9f2ed10f79b72b5da881c9b8b45","src/level_filters.rs":"baae8e797897bae9cdd9ec64b8e9a3d71156e9c03261be17b5b18acba034e154","src/lib.rs":"325d0d9487ecd646a7e5e22617f5f291c4112e0e7e359e0033de1677217c5b22","src/macros.rs":"1b38906bcb32cad50b60d350c88f6f4f1fa4d46d99bf50318c44d75219760c42","src/span.rs":"372695b3eda8354a892316826d2598f821fcb835fb18e1e0271767bce730b7ad","src/stdlib.rs":"248514a9bae6106e436358aee44c92abf8e7f79022895c4a25136ddef211d198","src/subscriber.rs":"8933d8766439f929c0a98a0863d20aff37b221314b3825edd9058be511149968","tests/enabled.rs":"1333339aace87ea9d701f2f76a1985820cc513a75013a7ed89669f7a2c635479","tests/event.rs":"7678d1cc8a29ae8b716fbddb7cc4836422732ba3dce109ff511c8bb6100da606","tests/filter_caching_is_lexically_scoped.rs":"5487a37db5fbdf3d57020ab1f01185d928c45d967d99d723ffc434540459d8dc","tests/filters_are_not_reevaluated_for_the_same_span.rs":"251abbc000dddd298448958a1f0e5be71da527ac6c1a368d57837c83a5467329","tests/filters_are_reevaluated_for_different_call_sites.rs":"e0fdd8e930c043674702831b4d96f331e63aba824576bbac50b3f53bb0241cc7","tests/filters_dont_leak.rs":"d594266818a3461886da33bfcc76937d89a433ed6980226fc428706b216c093c","tests/future_send.rs":"3e9c9193219d12e342c18bbedb2f6ec940334202feb3cffba91601d6001b8575","tests/macro_imports.rs":"d5de857162185d4a2384f3cb644bfcf76c7f5c1a3b5f72bfa0d2620ac6e3873c","tests/macros.rs":"fa83397181d73d2cae09c16d9647a63d1e3bad0f2dbc5b3280f69f3d0180c488","tests/macros_incompatible_concat.rs":"5f3bcbb65e4ae39db1cfc2def62fc913c20bab0fb769c8f731504e2615585ee5","tests/macros_redefined_core.rs":"a6eac60522f71fe6c9a040b8b869d596f7eb9e907f5b49f4be4413a40c387676","tests/max_level_hint.rs":"9b366591d947ca0202fa0bdf797e1bb14534d3c896cf8b9674660cd2807c32ef","tests/multiple_max_level_hints.rs":"4d9ef0de9cccc787da8f5e3f6c233ac9db42a2a99cfe5e39997e1f4aa9df0c00","tests/no_subscriber.rs":"2f8f2ada5089d8e2e503394dfe8206598a11895907c53bf940b892f1e6afdd2f","tests/register_callsite_deadlock.rs":"c0b3142543e7a10065c7583a8ee0b6bc978ea4f3979599651101c5a28966e7c8","tests/scoped_clobbers_default.rs":"806480a74c15e4d68bb7576050662b1e53ee765fd583d003f8b349f17ea63a4b","tests/span.rs":"f84ead5b1dad9b91e5cec9d8378ab932a942936374ba928fb381e67fab52cda0","tests/subscriber.rs":"1617c098f4fa6abed174fe062111444c7b67fa0f377d2b342176998e572480e3"},"package":"8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"} \ No newline at end of file
diff --git a/vendor/tracing/CHANGELOG.md b/vendor/tracing/CHANGELOG.md
index 8b7d58808..978e0ca55 100644
--- a/vendor/tracing/CHANGELOG.md
+++ b/vendor/tracing/CHANGELOG.md
@@ -1,3 +1,55 @@
+# 0.1.37 (October 6, 2022)
+
+This release of `tracing` incorporates changes from `tracing-core`
+[v0.1.30][core-0.1.30] and `tracing-attributes` [v0.1.23][attrs-0.1.23],
+including the new `Subscriber::on_register_dispatch` method for performing late
+initialization after a `Subscriber` is registered as a `Dispatch`, and bugfixes
+for the `#[instrument]` attribute. Additionally, it fixes instances of the
+`bare_trait_objects` lint, which is now a warning on `tracing`'s MSRV and will
+become an error in the next edition.
+
+### Fixed
+
+- **attributes**: Incorrect handling of inner attributes in `#[instrument]`ed
+ functions ([#2307])
+- **attributes**: Incorrect location of compiler diagnostic spans generated for
+ type errors in `#[instrument]`ed `async fn`s ([#2270])
+- **attributes**: Updated `syn` dependency to fix compilation with `-Z
+ minimal-versions` ([#2246])
+- `bare_trait_objects` warning in `valueset!` macro expansion ([#2308])
+
+### Added
+
+- **core**: `Subscriber::on_register_dispatch` method ([#2269])
+- **core**: `WeakDispatch` type and `Dispatch::downgrade()` function ([#2293])
+
+### Changed
+
+- `tracing-core`: updated to [0.1.30][core-0.1.30]
+- `tracing-attributes`: updated to [0.1.23][attrs-0.1.23]
+
+### Documented
+
+- Added [`tracing-web`] and [`reqwest-tracing`] to related crates ([#2283],
+ [#2331])
+
+Thanks to new contributors @compiler-errors, @e-nomem, @WorldSEnder, @Xiami2012,
+and @tl-rodrigo-gryzinski, as well as @jswrenn and @CAD97, for contributing to
+this release!
+
+[core-0.1.30]: https://github.com/tokio-rs/tracing/releases/tag/tracing-core-0.1.30
+[attrs-0.1.23]: https://github.com/tokio-rs/tracing/releases/tag/tracing-attributes-0.1.23
+[`tracing-web`]: https://crates.io/crates/tracing-web/
+[`reqwest-tracing`]: https://crates.io/crates/reqwest-tracing/
+[#2246]: https://github.com/tokio-rs/tracing/pull/2246
+[#2269]: https://github.com/tokio-rs/tracing/pull/2269
+[#2283]: https://github.com/tokio-rs/tracing/pull/2283
+[#2270]: https://github.com/tokio-rs/tracing/pull/2270
+[#2293]: https://github.com/tokio-rs/tracing/pull/2293
+[#2307]: https://github.com/tokio-rs/tracing/pull/2307
+[#2308]: https://github.com/tokio-rs/tracing/pull/2308
+[#2331]: https://github.com/tokio-rs/tracing/pull/2331
+
# 0.1.36 (July 29, 2022)
This release adds support for owned values and fat pointers as arguments to the
diff --git a/vendor/tracing/Cargo.toml b/vendor/tracing/Cargo.toml
index 9b4b5fa80..90f084d8e 100644
--- a/vendor/tracing/Cargo.toml
+++ b/vendor/tracing/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.49.0"
name = "tracing"
-version = "0.1.36"
+version = "0.1.37"
authors = [
"Eliza Weisman <eliza@buoyant.io>",
"Tokio Contributors <team@tokio.rs>",
@@ -98,11 +98,11 @@ optional = true
version = "0.2.9"
[dependencies.tracing-attributes]
-version = "0.1.22"
+version = "0.1.23"
optional = true
[dependencies.tracing-core]
-version = "0.1.29"
+version = "0.1.30"
default-features = false
[dev-dependencies.criterion]
diff --git a/vendor/tracing/README.md b/vendor/tracing/README.md
index 16e671e05..694734577 100644
--- a/vendor/tracing/README.md
+++ b/vendor/tracing/README.md
@@ -250,7 +250,7 @@ my_future
is as long as the future's.
The second, and preferred, option is through the
-[`#[instrument]`](https://docs.rs/tracing/0.1.36/tracing/attr.instrument.html)
+[`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html)
attribute:
```rust
@@ -297,7 +297,7 @@ span.in_scope(|| {
// Dropping the span will close it, indicating that it has ended.
```
-The [`#[instrument]`](https://docs.rs/tracing/0.1.36/tracing/attr.instrument.html) attribute macro
+The [`#[instrument]`](https://docs.rs/tracing/0.1.37/tracing/attr.instrument.html) attribute macro
can reduce some of this boilerplate:
```rust
diff --git a/vendor/tracing/src/dispatcher.rs b/vendor/tracing/src/dispatcher.rs
index 8817ac033..a84b99f4e 100644
--- a/vendor/tracing/src/dispatcher.rs
+++ b/vendor/tracing/src/dispatcher.rs
@@ -133,7 +133,7 @@ pub use tracing_core::dispatcher::with_default;
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use tracing_core::dispatcher::DefaultGuard;
pub use tracing_core::dispatcher::{
- get_default, set_global_default, Dispatch, SetGlobalDefaultError,
+ get_default, set_global_default, Dispatch, SetGlobalDefaultError, WeakDispatch,
};
/// Private API for internal use by tracing's macros.
diff --git a/vendor/tracing/src/lib.rs b/vendor/tracing/src/lib.rs
index 7d60c7721..342e04a82 100644
--- a/vendor/tracing/src/lib.rs
+++ b/vendor/tracing/src/lib.rs
@@ -727,6 +727,8 @@
//! in [bunyan] format, enriched with timing information.
//! - [`tracing-wasm`] provides a `Subscriber`/`Layer` implementation that reports
//! events and spans via browser `console.log` and [User Timing API (`window.performance`)].
+//! - [`tracing-web`] provides a layer implementation of level-aware logging of events
+//! to web browsers' `console.*` and span events to the [User Timing API (`window.performance`)].
//! - [`tide-tracing`] provides a [tide] middleware to trace all incoming requests and responses.
//! - [`test-log`] takes care of initializing `tracing` for tests, based on
//! environment variables with an `env_logger` compatible syntax.
@@ -744,6 +746,7 @@
//! grouping together logs from the same spans during writing.
//! - [`tracing-loki`] provides a layer for shipping logs to [Grafana Loki].
//! - [`tracing-logfmt`] provides a layer that formats events and spans into the logfmt format.
+//! - [`reqwest-tracing`] provides a middleware to trace [`reqwest`] HTTP requests.
//!
//! If you're the maintainer of a `tracing` ecosystem crate not listed above,
//! please let us know! We'd love to add your project to the list!
@@ -761,6 +764,7 @@
//! [`tracing-bunyan-formatter`]: https://crates.io/crates/tracing-bunyan-formatter
//! [bunyan]: https://github.com/trentm/node-bunyan
//! [`tracing-wasm`]: https://docs.rs/tracing-wasm
+//! [`tracing-web`]: https://docs.rs/tracing-web
//! [User Timing API (`window.performance`)]: https://developer.mozilla.org/en-US/docs/Web/API/User_Timing_API
//! [`tide-tracing`]: https://crates.io/crates/tide-tracing
//! [tide]: https://crates.io/crates/tide
@@ -781,6 +785,8 @@
//! [`tracing-loki`]: https://crates.io/crates/tracing-loki
//! [Grafana Loki]: https://grafana.com/oss/loki/
//! [`tracing-logfmt`]: https://crates.io/crates/tracing-logfmt
+//! [`reqwest-tracing`]: https://crates.io/crates/reqwest-tracing
+//! [`reqwest`]: https://crates.io/crates/reqwest
//!
//! <pre class="ignore" style="white-space:normal;font:inherit;">
//! <strong>Note</strong>: Some of these ecosystem crates are currently
@@ -811,7 +817,7 @@
//!
//! ```toml
//! [dependencies]
-//! tracing = { version = "0.1.36", default-features = false }
+//! tracing = { version = "0.1.37", default-features = false }
//! ```
//!
//! <pre class="ignore" style="white-space:normal;font:inherit;">
@@ -894,7 +900,7 @@
//! [flags]: #crate-feature-flags
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg), deny(rustdoc::broken_intra_doc_links))]
-#![doc(html_root_url = "https://docs.rs/tracing/0.1.36")]
+#![doc(html_root_url = "https://docs.rs/tracing/0.1.37")]
#![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/src/macros.rs b/vendor/tracing/src/macros.rs
index b134af6e8..f3968e5c1 100644
--- a/vendor/tracing/src/macros.rs
+++ b/vendor/tracing/src/macros.rs
@@ -2193,79 +2193,79 @@ macro_rules! valueset {
// };
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = $val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$val as &Value)) },
+ @ { $($out),*, (&$next, Some(&$val as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$($k).+ as &Value)) },
+ @ { $($out),*, (&$next, Some(&$($k).+ as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$($k).+) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$($k).+) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$($k).+) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$($k).+) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = ?$val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = %$val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+ = $val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$val as &Value)) },
+ @ { $($out),*, (&$next, Some(&$val as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $($k:ident).+) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$($k).+ as &Value)) },
+ @ { $($out),*, (&$next, Some(&$($k).+ as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, ?$($k:ident).+) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$($k).+) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$($k).+) as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, %$($k:ident).+) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$($k).+) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$($k).+) as &dyn Value)) },
$next,
)
};
@@ -2273,47 +2273,47 @@ macro_rules! valueset {
// Handle literal names
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr, $($rest:tt)*) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$val as &Value)) },
+ @ { $($out),*, (&$next, Some(&$val as &dyn Value)) },
$next,
$($rest)*
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = ?$val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&debug(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&debug(&$val) as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = %$val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&display(&$val) as &Value)) },
+ @ { $($out),*, (&$next, Some(&display(&$val) as &dyn Value)) },
$next,
)
};
(@ { $(,)* $($out:expr),* }, $next:expr, $k:literal = $val:expr) => {
$crate::valueset!(
- @ { $($out),*, (&$next, Some(&$val as &Value)) },
+ @ { $($out),*, (&$next, Some(&$val as &dyn Value)) },
$next,
)
};
// Remainder is unparseable, but exists --- must be format args!
(@ { $(,)* $($out:expr),* }, $next:expr, $($rest:tt)+) => {
- $crate::valueset!(@ { (&$next, Some(&format_args!($($rest)+) as &Value)), $($out),* }, $next, )
+ $crate::valueset!(@ { (&$next, Some(&format_args!($($rest)+) as &dyn Value)), $($out),* }, $next, )
};
// === entry ===
diff --git a/vendor/unicode-ident/.cargo-checksum.json b/vendor/unicode-ident/.cargo-checksum.json
index 8066cd8bc..1fcb95c86 100644
--- a/vendor/unicode-ident/.cargo-checksum.json
+++ b/vendor/unicode-ident/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"43a169366c8f04f5c100d7b1a29fbe9f4d50ff5a019d72761be6c949f259333a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"31a16b16a84da0ccaaeb16b1a4c70d89592d12de5c139053f724dbac91bdd40c","benches/xid.rs":"a61f61ecc7d5124c759cdeb55ab74470ab69f2f3ca37613da65f16e0e5e33487","src/lib.rs":"d0030259a628125669ad6c02d3eb791526e6d6ae35d8a858a87f90245162666c","src/tables.rs":"887457a7ce0d2fff750b40134de684e86d3999e5d191544f31ee45936b7bcb72","tests/compare.rs":"89c4dc4f745064a9f734667b1d960596a10b8cb019a8ed1c5b9512678a866ad5","tests/fst/mod.rs":"69a3aaf59acd8bca962ecc6234be56be8c0934ab79b253162f10eb881523901f","tests/fst/xid_continue.fst":"6e079a81175e445461dc330f61294c9f24bdb1681b7a591999fbb4547766ea99","tests/fst/xid_start.fst":"382fc736b472d09052a53c89cc2060bd839792350c6d22638b91e9123bf14540","tests/roaring/mod.rs":"784f65a48477fab7549620c7843c7ad6da533f69a18abca1172f6acb95045e53","tests/static_size.rs":"3974f6948c06d60b63738ddf5688478144718da87ccfdc4af6918d76a0bd9f06","tests/trie/mod.rs":"d4acbb716bcbaf80660039797f45e138ed8bbd66749fa3b19b1a971574679cc9","tests/trie/trie.rs":"6780e33f74f86131aa32f321bc3c77c4d9b526b708e82db64b198dce4c86429b"},"package":"5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"} \ No newline at end of file
+{"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
diff --git a/vendor/unicode-ident/Cargo.toml b/vendor/unicode-ident/Cargo.toml
index bb1171eaa..03e1871fc 100644
--- a/vendor/unicode-ident/Cargo.toml
+++ b/vendor/unicode-ident/Cargo.toml
@@ -13,12 +13,20 @@
edition = "2018"
rust-version = "1.31"
name = "unicode-ident"
-version = "1.0.1"
+version = "1.0.5"
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"
readme = "README.md"
-license = "MIT OR Apache-2.0"
+keywords = [
+ "unicode",
+ "xid",
+]
+categories = [
+ "development-tools::procedural-macro-helpers",
+ "no-std",
+]
+license = "(MIT OR Apache-2.0) AND Unicode-DFS-2016"
repository = "https://github.com/dtolnay/unicode-ident"
[package.metadata.docs.rs]
@@ -29,7 +37,7 @@ name = "xid"
harness = false
[dev-dependencies.criterion]
-version = "0.3"
+version = "0.4"
default-features = false
[dev-dependencies.fst]
@@ -40,11 +48,11 @@ version = "0.8"
features = ["small_rng"]
[dev-dependencies.roaring]
-version = "0.9"
+version = "0.10"
[dev-dependencies.ucd-trie]
version = "0.1"
default-features = false
[dev-dependencies.unicode-xid]
-version = "0.2"
+version = "0.2.4"
diff --git a/vendor/unicode-ident/LICENSE-UNICODE b/vendor/unicode-ident/LICENSE-UNICODE
new file mode 100644
index 000000000..85d0d580d
--- /dev/null
+++ b/vendor/unicode-ident/LICENSE-UNICODE
@@ -0,0 +1,46 @@
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+See Terms of Use <https://www.unicode.org/copyright.html>
+for definitions of Unicode Inc.’s Data Files and Software.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2022 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE 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 OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
diff --git a/vendor/unicode-ident/README.md b/vendor/unicode-ident/README.md
index 4acefdb05..6c590b06c 100644
--- a/vendor/unicode-ident/README.md
+++ b/vendor/unicode-ident/README.md
@@ -41,10 +41,10 @@ different ratios of ASCII to non-ASCII codepoints in the input data.
| | static storage | 0% nonascii | 1% | 10% | 100% nonascii |
|---|---|---|---|---|---|
-| **`unicode-ident`** | 9.75 K | 0.96 ns | 0.95 ns | 1.09 ns | 1.55 ns |
-| **`unicode-xid`** | 11.34 K | 1.88 ns | 2.14 ns | 3.48 ns | 15.63 ns |
-| **`ucd-trie`** | 9.95 K | 1.29 ns | 1.28 ns | 1.36 ns | 2.15 ns |
-| **`fst`** | 133 K | 55.1 ns | 54.9 ns | 53.2 ns | 28.5 ns |
+| **`unicode-ident`** | 10.0 K | 0.96 ns | 0.95 ns | 1.09 ns | 1.55 ns |
+| **`unicode-xid`** | 11.5 K | 1.88 ns | 2.14 ns | 3.48 ns | 15.63 ns |
+| **`ucd-trie`** | 10.2 K | 1.29 ns | 1.28 ns | 1.36 ns | 2.15 ns |
+| **`fst`** | 138 K | 55.1 ns | 54.9 ns | 53.2 ns | 28.5 ns |
| **`roaring`** | 66.1 K | 2.78 ns | 3.09 ns | 3.37 ns | 4.70 ns |
Source code for the benchmark is provided in the *bench* directory of this repo
@@ -263,15 +263,21 @@ is_xid_start:
## License
-<sup>
-Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
-2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
-</sup>
+Use of the Unicode Character Database, as this crate does, is governed by the <a
+href="LICENSE-UNICODE">Unicode License Agreement &ndash; Data Files and Software
+(2016)</a>.
-<br>
+All intellectual property within this crate that is **not generated** using the
+Unicode Character Database as input is licensed under either of <a
+href="LICENSE-APACHE">Apache License, Version 2.0</a> or <a
+href="LICENSE-MIT">MIT license</a> at your option.
+
+The **generated** files incorporate tabular data derived from the Unicode
+Character Database, together with intellectual property from the original source
+code content of the crate. One must comply with the terms of both the Unicode
+License Agreement and either of the Apache license or MIT license when those
+generated files are involved.
-<sub>
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
-be dual licensed as above, without any additional terms or conditions.
-</sub>
+be licensed as just described, without any additional terms or conditions.
diff --git a/vendor/unicode-ident/src/tables.rs b/vendor/unicode-ident/src/tables.rs
index a697636b6..380c798d1 100644
--- a/vendor/unicode-ident/src/tables.rs
+++ b/vendor/unicode-ident/src/tables.rs
@@ -28,7 +28,7 @@ pub(crate) static ASCII_CONTINUE: Align64<[bool; 128]> = Align64([
pub(crate) const CHUNK: usize = 64;
-pub(crate) static TRIE_START: Align8<[u8; 394]> = Align8([
+pub(crate) static TRIE_START: Align8<[u8; 402]> = Align8([
0x04, 0x0B, 0x0F, 0x13, 0x17, 0x1B, 0x1F, 0x23, 0x27, 0x2D, 0x31, 0x34, 0x38, 0x3C, 0x40, 0x02,
0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x4D, 0x00, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
@@ -39,21 +39,22 @@ pub(crate) static TRIE_START: Align8<[u8; 394]> = Align8([
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x60, 0x64, 0x66,
0x6A, 0x6E, 0x72, 0x28, 0x76, 0x78, 0x7C, 0x80, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9E, 0xA2,
0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x05, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0xAE, 0x00, 0xB2, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xC6, 0x00, 0x00, 0x00, 0xB9,
- 0xBC, 0xCF, 0x00, 0xBF, 0xD3, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0xB1, 0x00, 0xB5, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC8, 0x00, 0x00, 0x00, 0xAF,
+ 0xCE, 0xD2, 0xD6, 0xBC, 0xDA, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0xD9, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xDC, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xDF, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE1, 0x00, 0x00,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xDD,
+ 0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE9, 0x00, 0x00,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0xE7,
]);
pub(crate) static TRIE_CONTINUE: Align8<[u8; 1793]> = Align8([
@@ -66,23 +67,23 @@ pub(crate) static TRIE_CONTINUE: Align8<[u8; 1793]> = Align8([
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62, 0x64, 0x68,
0x6C, 0x70, 0x74, 0x28, 0x76, 0x7A, 0x7E, 0x82, 0x86, 0x8A, 0x8E, 0x92, 0x96, 0x9B, 0xA0, 0xA4,
- 0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x05, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x05, 0xB0, 0x00, 0xB4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00, 0xBE, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xAC, 0xC1, 0xC4, 0xC8, 0x00, 0xCA, 0x00, 0xB9,
- 0xCD, 0xD1, 0x00, 0xBF, 0xD5, 0x00, 0x00, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0x00, 0x00,
+ 0x05, 0x2B, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x99, 0x05, 0x05, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x05, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0xB3, 0x00, 0xB7, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x32, 0x05, 0x05, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x43, 0xBB, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA9, 0xAC, 0xC4, 0xC6, 0xCA, 0x00, 0xCC, 0x00, 0xAF,
+ 0xD0, 0xD4, 0xD8, 0xBC, 0xDC, 0x00, 0x00, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0x00,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0xD9, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xDC, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xDF, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE1, 0x00, 0x00,
- 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x05, 0x05, 0xE0, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x52, 0xE3, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE6, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xE9, 0x00, 0x00,
+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xE4, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+ 0x05, 0xE7, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -169,10 +170,10 @@ pub(crate) static TRIE_CONTINUE: Align8<[u8; 1793]> = Align8([
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, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xCB,
+ 0xC2,
]);
-pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
+pub(crate) static LEAF: Align64<[u8; 7520]> = Align64([
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, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -240,7 +241,7 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xF0, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x27, 0x00, 0x40, 0x70, 0x80, 0x03, 0x00, 0x00, 0xFC,
0xE0, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xF3, 0xDF, 0x3D, 0x60, 0x27, 0xCF, 0xFF, 0x00, 0x00,
- 0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x06, 0x00,
+ 0xEF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFD, 0xEF, 0xF3, 0xDF, 0x3D, 0x60, 0x60, 0xCF, 0xFF, 0x0E, 0x00,
0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xF0, 0x80, 0xCF, 0xFF, 0x00, 0xFC,
0xEE, 0xFF, 0x7F, 0xFC, 0xFF, 0xFF, 0xFB, 0x2F, 0x7F, 0x84, 0x5F, 0xFF, 0xC0, 0xFF, 0x0C, 0x00,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -248,7 +249,7 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x3F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00,
+ 0xD6, 0xF7, 0xFF, 0xFF, 0xAF, 0xFF, 0xFF, 0x3F, 0x5F, 0x7F, 0xFF, 0xF3, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x03, 0xFF, 0x03, 0xA0, 0xC2, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0xFE, 0xFF,
0xDF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x00, 0x00, 0x3F, 0x3C, 0x62, 0xC0, 0xE1, 0xFF,
@@ -309,7 +310,7 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x00, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x07,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80,
0x00, 0x00, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -339,7 +340,7 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x80,
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
@@ -434,7 +435,7 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1B, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0,
0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00,
@@ -445,11 +446,11 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xDE, 0xFF, 0x17, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x0F, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
0xE0, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0x23, 0x00, 0x00, 0x01, 0xE0, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7F, 0xBD, 0xFF, 0xBF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x03,
0xEF, 0x9F, 0xF9, 0xFF, 0xFF, 0xFD, 0xED, 0xFB, 0x9F, 0x39, 0x81, 0xE0, 0xCF, 0x1F, 0x1F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -499,28 +500,34 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0x7F, 0xFB, 0x01, 0xFF, 0x03, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x07, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF4, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x7F, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x07, 0x00, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 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, 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,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x3F, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE3, 0x07, 0xF8,
0xE7, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 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, 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,
+ 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 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,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xE0,
@@ -545,26 +552,24 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
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, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0x7F, 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,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F,
0xFF, 0x01, 0xFF, 0x03, 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,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x3F, 0x00, 0x40, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x1F,
0xFF, 0x01, 0xFF, 0x63, 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,
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, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x6F, 0xFF, 0x7F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 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, 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, 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, 0x00, 0xFF, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xDF, 0x64, 0xDE, 0xFF, 0xEB, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xBF, 0xE7, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7B, 0x5F, 0xFC, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -581,10 +586,12 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0x10, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
- 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x80, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0xFF, 0xFF, 0xF9, 0xDB, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0x43, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -595,6 +602,14 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
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, 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, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x0F, 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, 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, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03,
+ 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, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -617,12 +632,14 @@ pub(crate) static LEAF: Align64<[u8; 7264]> = Align64([
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x3F, 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,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
diff --git a/vendor/unicode-ident/tests/fst/xid_continue.fst b/vendor/unicode-ident/tests/fst/xid_continue.fst
index 5359051cb..05e7b1aa2 100644
--- a/vendor/unicode-ident/tests/fst/xid_continue.fst
+++ b/vendor/unicode-ident/tests/fst/xid_continue.fst
Binary files differ
diff --git a/vendor/unicode-ident/tests/fst/xid_start.fst b/vendor/unicode-ident/tests/fst/xid_start.fst
index 5c2e43fac..a5975b67e 100644
--- a/vendor/unicode-ident/tests/fst/xid_start.fst
+++ b/vendor/unicode-ident/tests/fst/xid_start.fst
Binary files differ
diff --git a/vendor/unicode-ident/tests/static_size.rs b/vendor/unicode-ident/tests/static_size.rs
index f0e04d4db..df65f45dd 100644
--- a/vendor/unicode-ident/tests/static_size.rs
+++ b/vendor/unicode-ident/tests/static_size.rs
@@ -13,7 +13,7 @@ fn test_size() {
+ size_of_val(&tables::TRIE_START)
+ size_of_val(&tables::TRIE_CONTINUE)
+ size_of_val(&tables::LEAF);
- assert_eq!(9752, size);
+ assert_eq!(10016, size);
}
#[test]
@@ -24,7 +24,7 @@ fn test_xid_size() {
mod ucd;
let size = size_of_val(ucd::XID_START) + size_of_val(ucd::XID_CONTINUE);
- assert_eq!(11344, size);
+ assert_eq!(11528, size);
let _ = ucd::BY_NAME;
}
@@ -71,7 +71,7 @@ fn test_trieset_size() {
+ size_of_val(tree3_level2)
+ size_of_val(tree3_level3);
- assert_eq!(9952, start_size + continue_size);
+ assert_eq!(10208, start_size + continue_size);
let _ = trie::BY_NAME;
}
@@ -81,7 +81,7 @@ fn test_fst_size() {
let xid_start_fst = include_bytes!("fst/xid_start.fst");
let xid_continue_fst = include_bytes!("fst/xid_continue.fst");
let size = xid_start_fst.len() + xid_continue_fst.len();
- assert_eq!(132897, size);
+ assert_eq!(137749, size);
}
#[test]
diff --git a/vendor/unicode-ident/tests/trie/trie.rs b/vendor/unicode-ident/tests/trie/trie.rs
index 7f7a14f31..821e7cb0f 100644
--- a/vendor/unicode-ident/tests/trie/trie.rs
+++ b/vendor/unicode-ident/tests/trie/trie.rs
@@ -2,9 +2,9 @@
//
// ucd-generate property-bool UCD --include XID_Start,XID_Continue --trie-set
//
-// Unicode version: 14.0.0.
+// Unicode version: 15.0.0.
//
-// ucd-generate 0.2.10 is available on crates.io.
+// ucd-generate 0.2.13 is available on crates.io.
pub const BY_NAME: &'static [(&'static str, &'static ::ucd_trie::TrieSet)] = &[
("XID_Continue", XID_CONTINUE), ("XID_Start", XID_START),
@@ -77,10 +77,10 @@ pub const XID_CONTINUE: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
0xF3C5FDFFFFF99FEF, 0x5003FFCFB080799F, 0xD36DFDFFFFF987EE,
0x3FFFC05E023987, 0xF3EDFDFFFFFBBFEE, 0xFE00FFCF00013BBF,
0xF3EDFDFFFFF99FEE, 0x2FFCFB0E0399F, 0xC3FFC718D63DC7EC, 0xFFC000813DC7,
- 0xF3FFFDFFFFFDDFFF, 0xFFCF27603DDF, 0xF3EFFDFFFFFDDFEF, 0x6FFCF60603DDF,
+ 0xF3FFFDFFFFFDDFFF, 0xFFCF27603DDF, 0xF3EFFDFFFFFDDFEF, 0xEFFCF60603DDF,
0xFFFFFFFFFFFDDFFF, 0xFC00FFCF80F07DDF, 0x2FFBFFFFFC7FFFEE,
0xCFFC0FF5F847F, 0x7FFFFFFFFFFFFFE, 0x3FF7FFF, 0x3FFFFFAFFFFFF7D6,
- 0xF3FF3F5F, 0xC2A003FF03000001, 0xFFFE1FFFFFFFFEFF, 0x1FFFFFFFFEFFFFDF,
+ 0xF3FF7F5F, 0xC2A003FF03000001, 0xFFFE1FFFFFFFFEFF, 0x1FFFFFFFFEFFFFDF,
0x40, 0xFFFFFFFFFFFF03FF, 0xFFFFFFFF3FFFFFFF, 0xF7FFFFFFFFFF20BF,
0xFFFFFFFF3D7F3DFF, 0x7F3DFFFFFFFF3DFF, 0xFFFFFFFFFF7FFF3D,
0xFFFFFFFFFF3DFFFF, 0x3FE00E7FFFFFF, 0xFFFFFFFF0000FFFF,
@@ -112,78 +112,80 @@ pub const XID_CONTINUE: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
],
tree3_level1: &[
0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 10, 11, 12, 13, 14, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 15, 16, 17, 7, 18, 19, 7, 20, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 7, 15, 16, 17, 7, 18, 19, 7, 20, 21, 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, 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, 21, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 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,
],
tree3_level2: &[
0, 1, 2, 3, 4, 5, 4, 6, 4, 4, 7, 8, 9, 10, 11, 12, 2, 2, 13, 14, 15, 16,
17, 4, 2, 2, 2, 2, 18, 19, 20, 4, 21, 22, 23, 24, 25, 4, 26, 4, 27, 28,
- 29, 30, 31, 32, 33, 4, 2, 34, 35, 35, 36, 4, 4, 4, 4, 4, 37, 4, 38, 39,
- 40, 41, 2, 42, 3, 43, 44, 45, 2, 46, 47, 4, 48, 49, 50, 51, 4, 4, 2, 52,
- 2, 53, 4, 4, 54, 55, 2, 56, 57, 58, 59, 60, 4, 4, 3, 4, 61, 62, 63, 64,
- 65, 66, 67, 68, 69, 57, 4, 4, 4, 4, 70, 71, 72, 4, 73, 74, 75, 4, 4, 4, 4,
- 76, 4, 4, 77, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 78, 4, 2, 79,
- 2, 2, 2, 80, 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, 81, 82, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 79, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 29, 30, 31, 32, 33, 4, 2, 34, 35, 35, 36, 4, 4, 4, 4, 4, 37, 38, 39, 40,
+ 41, 42, 2, 43, 3, 44, 45, 46, 2, 47, 48, 49, 50, 51, 52, 53, 4, 4, 2, 54,
+ 2, 55, 4, 4, 56, 57, 2, 58, 59, 60, 61, 62, 4, 4, 3, 4, 63, 64, 65, 66,
+ 67, 68, 69, 70, 71, 59, 4, 4, 4, 4, 72, 73, 74, 4, 75, 76, 77, 4, 4, 4, 4,
+ 78, 79, 80, 81, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 82, 4, 2, 83,
+ 2, 2, 2, 84, 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, 85, 86, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 60, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 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, 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, 4, 4, 4, 4, 4, 4, 2,
- 2, 2, 2, 2, 2, 2, 2, 57, 83, 67, 84, 18, 85, 86, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 2, 4, 4, 2, 87, 88, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 59, 89, 69, 90, 18, 91, 92, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 2, 4, 4, 2, 93, 94, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 91, 34, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 96, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 88, 34, 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, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 92, 2, 2, 2, 2, 93, 94, 2, 2, 2, 2, 2, 95, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 97, 2, 2, 2, 2, 98, 99, 2, 2, 2, 2, 2, 100, 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, 2, 96, 97, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 101, 102, 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, 4, 4,
- 4, 4, 4, 4, 4, 4, 98, 60, 4, 4, 4, 4, 4, 4, 4, 99, 100, 4, 4, 101, 4, 4,
- 4, 4, 4, 4, 2, 102, 103, 104, 105, 106, 2, 2, 2, 2, 107, 108, 109, 110,
- 111, 112, 4, 4, 4, 4, 4, 4, 4, 4, 113, 114, 115, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 23, 4, 4, 4, 116, 4, 4, 4, 117, 118, 4, 4, 4,
- 4, 119, 120, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 121,
- 2, 2, 2, 122, 2, 123, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 124, 125, 126, 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, 103, 62, 4, 4, 4, 4, 4, 4, 4, 104, 105, 4, 4, 106, 4,
+ 4, 4, 4, 4, 4, 2, 107, 108, 109, 110, 111, 2, 2, 2, 2, 112, 113, 114, 115,
+ 116, 117, 4, 4, 4, 4, 4, 4, 4, 4, 118, 119, 120, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 121, 4, 4, 4, 122, 123, 124, 4, 125, 126, 4, 4,
+ 4, 4, 127, 128, 4, 4, 4, 4, 4, 4, 4, 129, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 130, 2, 2, 2, 131, 2, 132, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 133, 134, 135, 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, 127, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 128, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 136, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 137, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 57, 2, 2, 2, 11,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 2, 2, 2,
+ 11, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 138, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 129, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 130, 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, 2, 2, 2, 2, 2, 2, 2,
- 2, 131, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 132, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 139, 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, 2, 2, 2, 133,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2,
+ 2, 2, 2, 140, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 141, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 87, 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, 2, 2, 2, 87, 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,
],
tree3_level3: &[
0xB7FFFF7FFFFFEFFF, 0x3FFF3FFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF, 0,
@@ -195,32 +197,34 @@ pub const XID_CONTINUE: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
0x37FFFF00000000, 0x3FFFFFF003FFFFF, 0xC0FFFFFFFFFFFFFF,
0x873FFFFFFEEFF06F, 0x1FFFFFFF00000000, 0x1FFFFFFF, 0x7FFFFFFEFF,
0x3FFFFFFFFFFFFF, 0x7FFFF003FFFFF, 0x3FFFF, 0x1FF, 0x7FFFFFFFFFFFF,
- 0x3FF00FFFFFFFFFF, 0x31BFFFFFFFFFF, 0xFFFF00801FFFFFFF,
- 0xFFFF00000001FFFF, 0xFFFF00000000003F, 0x7FFFFF0000001F,
- 0x803FFFC00000007F, 0x3FF01FFFFFF0004, 0xFFDFFFFFFFFFFFFF,
- 0x4FFFFFFFFF00F0, 0x17FFDE1F, 0x40FFFFFFFFFBFFFF, 0xFFFF01FFBFFFBD7F,
- 0x3FF07FFFFFFFFFF, 0xFBEDFDFFFFF99FEF, 0x1F1FCFE081399F, 0x3C3FF07FF,
- 0x3FF00BF, 0xFF3FFFFFFFFFFFFF, 0x3F000001, 0x3FF0011, 0x1FFFFFFFFFFFFFF,
- 0x3FF, 0x3FF0FFFE7FFFFFF, 0x7F, 0xFFFFFFFF00000000, 0x800003FFFFFFFFFF,
- 0xF9BFFFFFFF6FF27F, 0x3FF000F, 0xFFFFFCFF00000000, 0x1BFCFFFFFF,
- 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF0080, 0xFFFF000023FFFFFF,
- 0xFF7FFFFFFFFFFDFF, 0xFFFC000003FF0001, 0x7FFEFFFFFCFFFF,
- 0xB47FFFFFFFFFFB7F, 0xFFFFFDBF03FF00FF, 0x3FF01FB7FFF, 0x7FFFFF00000000,
- 0x1000000000000, 0x3FFFFFF, 0x7FFFFFFFFFFF, 0xF, 0xFFFFFFFFFFFF0000,
- 0x1FFFFFFFFFFFF, 0xFFFF03FF7FFFFFFF, 0x1F3FFFFFFF03FF, 0xE0FFFFF803FF000F,
- 0xFFFF, 0xFFFFFFFFFFFF87FF, 0xFFFF80FF, 0x3001B00000000, 0xFFFFFFFFFFFFFF,
- 0x3FFFFF, 0x6FEF000000000000, 0x7FFFFFFFF, 0xFFFF00F000070000,
- 0xFFFFFFFFFFFFFFF, 0x1FFF07FFFFFFFFFF, 0x63FF01FF, 0xFFFF3FFFFFFFFFFF,
- 0xF807E3E000000000, 0x3C0000000FE7, 0x1C, 0xFFFFFFFFFFDFFFFF,
- 0xEBFFDE64DFFFFFFF, 0xFFFFFFFFFFFFFFEF, 0x7BFFFFFFDFDFE7BF,
- 0xFFFFFFFFFFFDFC5F, 0xFFFFFF3FFFFFFFFF, 0xF7FFFFFFF7FFFFFD,
- 0xFFDFFFFFFFDFFFFF, 0xFFFF7FFFFFFF7FFF, 0xFFFFFDFFFFFFFDFF,
- 0xFFFFFFFFFFFFCFF7, 0xF87FFFFFFFFFFFFF, 0x201FFFFFFFFFFF, 0xFFFEF8000010,
- 0x7DBF9FFFF7F, 0x3FFF1FFFFFFFFFFF, 0x43FF, 0x7FFFFFFF0000,
- 0x3FFFFFFFFFFFFFF, 0x7FFF6F7F00000000, 0x7F001F, 0x3FF0FFF,
- 0xAF7FE96FFFFFFEF, 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF,
+ 0x3FF00FFFFFFFFFF, 0x31BFFFFFFFFFF, 0xE000000000000000,
+ 0xFFFF00801FFFFFFF, 0xFFFF00000001FFFF, 0xFFFF00000000003F,
+ 0x7FFFFF0000001F, 0x803FFFC00000007F, 0x3FF01FFFFFF0004,
+ 0xFFDFFFFFFFFFFFFF, 0x4FFFFFFFFF00F0, 0x17FFDE1F, 0xC0FFFFFFFFFBFFFF, 0x3,
+ 0xFFFF01FFBFFFBD7F, 0x3FF07FFFFFFFFFF, 0xFBEDFDFFFFF99FEF,
+ 0x1F1FCFE081399F, 0x3C3FF07FF, 0x3FF00BF, 0xFF3FFFFFFFFFFFFF, 0x3F000001,
+ 0x3FF0011, 0x1FFFFFFFFFFFFFF, 0x3FF, 0x3FF0FFFE7FFFFFF, 0x7F,
+ 0xFFFFFFFF00000000, 0x800003FFFFFFFFFF, 0xF9BFFFFFFF6FF27F, 0x3FF000F,
+ 0xFFFFFCFF00000000, 0x1BFCFFFFFF, 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFF0080,
+ 0xFFFF000023FFFFFF, 0xFF7FFFFFFFFFFDFF, 0xFFFC000003FF0001,
+ 0x7FFEFFFFFCFFFF, 0xB47FFFFFFFFFFB7F, 0xFFFFFDBF03FF00FF, 0x3FF01FB7FFF,
+ 0x7FFFFF00000000, 0xC7FFFFFFFFFDFFFF, 0x3FF0007, 0x1000000000000,
+ 0x3FFFFFF, 0x7FFFFFFFFFFF, 0xF, 0xFFFFFFFFFFFF0000, 0x1FFFFFFFFFFFF,
+ 0xFFFFFFFFFFFF, 0x3FFFFF, 0xFFFF03FF7FFFFFFF, 0x1F3FFFFFFF03FF,
+ 0xE0FFFFF803FF000F, 0xFFFF, 0xFFFFFFFFFFFF87FF, 0xFFFF80FF,
+ 0x3001B00000000, 0xFFFFFFFFFFFFFF, 0x6FEF000000000000, 0x40007FFFFFFFF,
+ 0xFFFF00F000270000, 0xFFFFFFFFFFFFFFF, 0x1FFF07FFFFFFFFFF, 0x63FF01FF,
+ 0xFFFF3FFFFFFFFFFF, 0xF807E3E000000000, 0x3C0000000FE7, 0x1C,
+ 0xFFFFFFFFFFDFFFFF, 0xEBFFDE64DFFFFFFF, 0xFFFFFFFFFFFFFFEF,
+ 0x7BFFFFFFDFDFE7BF, 0xFFFFFFFFFFFDFC5F, 0xFFFFFF3FFFFFFFFF,
+ 0xF7FFFFFFF7FFFFFD, 0xFFDFFFFFFFDFFFFF, 0xFFFF7FFFFFFF7FFF,
+ 0xFFFFFDFFFFFFFDFF, 0xFFFFFFFFFFFFCFF7, 0xF87FFFFFFFFFFFFF,
+ 0x201FFFFFFFFFFF, 0xFFFEF8000010, 0x7E07FFFFFFF, 0xFFFF07DBF9FFFF7F,
+ 0x3FFFFFFFFFFF, 0x8000, 0x3FFF1FFFFFFFFFFF, 0x43FF, 0x7FFFFFFF0000,
+ 0x3FFFFFFFFFFFFFF, 0x3FFFFFFFFFF0000, 0x7FFF6F7F00000000, 0x7F001F,
+ 0x3FF0FFF, 0xAF7FE96FFFFFFEF, 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF,
0x3FF000000000000, 0xFFFFFFFF, 0xFFFF0003FFFFFFFF, 0x1FFFFFFFF,
- 0x3FFFFFFF, 0x7FF, 0xFFFFFFFFFFFF,
+ 0x3FFFFFFF, 0xFFFFFFFFFFFF07FF,
],
};
@@ -336,7 +340,7 @@ pub const XID_START: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
],
tree3_level1: &[
0, 1, 2, 3, 4, 5, 6, 7, 8, 5, 9, 10, 5, 11, 12, 5, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 13, 14, 15, 7, 16, 17, 7, 18, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 7, 7, 13, 14, 15, 7, 16, 17, 7, 18, 19, 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,
@@ -345,61 +349,63 @@ pub const XID_START: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
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,
],
tree3_level2: &[
0, 1, 2, 3, 4, 5, 4, 4, 4, 4, 6, 7, 8, 9, 10, 11, 2, 2, 12, 13, 14, 15,
16, 4, 2, 2, 2, 2, 17, 18, 19, 4, 20, 21, 22, 23, 24, 4, 25, 4, 26, 27,
28, 29, 30, 31, 32, 4, 2, 33, 34, 34, 35, 4, 4, 4, 4, 4, 36, 4, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 4, 50, 22, 51, 52, 4, 4, 5,
- 53, 54, 55, 4, 4, 56, 57, 54, 58, 59, 4, 60, 61, 4, 4, 62, 4, 63, 64, 65,
- 66, 67, 68, 69, 70, 71, 72, 4, 4, 4, 4, 73, 74, 75, 4, 76, 77, 78, 4, 4,
- 4, 4, 79, 4, 4, 80, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 81, 4, 2,
- 56, 2, 2, 2, 82, 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, 83, 84, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 56, 4, 4, 4, 4, 4, 4, 4, 4,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 22, 52, 53, 4, 4, 5,
+ 54, 55, 56, 4, 4, 57, 58, 55, 59, 60, 4, 61, 62, 4, 4, 63, 4, 64, 65, 66,
+ 67, 68, 69, 70, 71, 72, 73, 4, 4, 4, 4, 74, 75, 76, 4, 77, 78, 79, 4, 4,
+ 4, 4, 80, 81, 4, 82, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 83, 4,
+ 2, 57, 2, 2, 2, 84, 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, 85, 86,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 55, 87, 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, 2, 2, 2, 2, 2, 2, 2, 2, 2, 61, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 62, 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, 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, 4, 4, 4, 4, 4,
- 2, 2, 2, 2, 2, 2, 2, 2, 72, 85, 86, 87, 54, 88, 75, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 2, 4, 4, 2, 89, 90, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 4, 2, 2, 2, 2, 2, 2, 2, 2, 73, 88, 89, 90, 55, 91, 76, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 2, 4, 4, 2, 92, 93, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 93, 33, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 2, 2, 95, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 96, 33, 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, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 94, 2, 2, 2, 2, 95, 96, 2, 2, 2, 2, 2, 97, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 97, 2, 2, 2, 2, 98, 99, 2, 2, 2, 2, 2, 100, 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, 2, 98, 99, 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, 2, 100, 101, 102, 103, 104, 2, 2,
- 2, 2, 105, 106, 107, 108, 109, 110, 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, 22, 4, 4, 4, 4, 4, 4, 4, 111,
- 112, 4, 4, 4, 4, 87, 62, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 113, 2, 2, 2, 114, 2, 115, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 116, 117, 118, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 119, 2, 2, 2, 2, 2, 2,
+ 4, 4, 4, 4, 4, 4, 2, 101, 102, 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, 2, 103, 104, 105, 106, 107,
+ 2, 2, 2, 2, 108, 109, 110, 111, 112, 113, 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, 114, 4, 4, 4, 115, 116,
+ 4, 4, 117, 118, 4, 4, 4, 4, 90, 63, 4, 4, 4, 4, 4, 4, 4, 119, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 120, 2, 2, 2, 121, 2, 122, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 123, 124, 125, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 72, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 127, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 120, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 128, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 121, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 129, 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, 2, 2, 2, 2, 2, 2, 2, 2, 122, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 123, 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, 2, 2, 2, 2, 2, 2, 2, 2, 130, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 55,
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,
],
tree3_level3: &[
0xB7FFFF7FFFFFEFFF, 0x3FFF3FFF, 0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF, 0,
@@ -414,23 +420,25 @@ pub const XID_START: &'static ::ucd_trie::TrieSet = &::ucd_trie::TrieSet {
0x303FFFFFFFFFF, 0xFFFF00801FFFFFFF, 0xFFFF00000000003F,
0xFFFF000000000003, 0x7FFFFF0000001F, 0xFFFFFFFFFFFFF8, 0x26000000000000,
0xFFFFFFFFFFF8, 0x1FFFFFF0000, 0x7FFFFFFFF8, 0x47FFFFFFFF0090,
- 0x7FFFFFFFFFFF8, 0x1400001E, 0xFFFFFFBFFFF, 0xFFFF01FFBFFFBD7F,
+ 0x7FFFFFFFFFFF8, 0x1400001E, 0x80000FFFFFFBFFFF, 0x1, 0xFFFF01FFBFFFBD7F,
0x23EDFDFFFFF99FE0, 0x3E0010000, 0x380000780, 0xFFFFFFFFFFFF, 0xB0,
0x7FFFFFFFFFFF, 0xF000000, 0x10, 0x10007FFFFFFFFFF, 0x7FFFFFF, 0x7F,
0xFFFFFFFFFFF, 0xFFFFFFFF00000000, 0x80000000FFFFFFFF, 0x8000FFFFFF6FF27F,
0x2, 0xFFFFFCFF00000000, 0xA0001FFFF, 0x407FFFFFFFFF801,
0xFFFFFFFFF0010000, 0xFFFF0000200003FF, 0x1FFFFFFFFFFFFFF, 0x7FFFFFFFFDFF,
0xFFFC000000000001, 0xFFFF, 0x1FFFFFFFFFB7F, 0xFFFFFDBF00000040,
- 0x10003FF, 0x7FFFF00000000, 0x1000000000000, 0x3FFFFFF, 0xF,
- 0xFFFFFFFFFFFF0000, 0x1FFFFFFFFFFFF, 0xFFFF00007FFFFFFF,
+ 0x10003FF, 0x7FFFF00000000, 0xFFFFFFFFDFFF4, 0x1000000000000, 0x3FFFFFF,
+ 0xF, 0xFFFFFFFFFFFF0000, 0x1FFFFFFFFFFFF, 0x7E, 0xFFFF00007FFFFFFF,
0x7FFFFFFFFFFFFFFF, 0x3FFFFFFF0000, 0xE0FFFFF80000000F, 0x107FF,
0xFFF80000, 0xB00000000, 0xFFFFFFFFFFFFFF, 0x3FFFFF, 0x6FEF000000000000,
- 0x7FFFFFFFF, 0xFFFF00F000070000, 0xFFFFFFFFFFFFFFF, 0x1FFF07FFFFFFFFFF,
- 0x3FF01FF, 0xFFFFFFFFFFDFFFFF, 0xEBFFDE64DFFFFFFF, 0xFFFFFFFFFFFFFFEF,
- 0x7BFFFFFFDFDFE7BF, 0xFFFFFFFFFFFDFC5F, 0xFFFFFF3FFFFFFFFF,
- 0xF7FFFFFFF7FFFFFD, 0xFFDFFFFFFFDFFFFF, 0xFFFF7FFFFFFF7FFF,
- 0xFFFFFDFFFFFFFDFF, 0xFF7, 0x3F801FFFFFFFFFFF, 0x4000, 0x7FFF6F7F00000000,
- 0x1F, 0x80F, 0xAF7FE96FFFFFFEF, 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF,
- 0xFFFFFFFF, 0xFFFF0003FFFFFFFF, 0x1FFFFFFFF, 0x3FFFFFFF, 0x7FF,
+ 0x40007FFFFFFFF, 0xFFFF00F000270000, 0xFFFFFFFFFFFFFFF,
+ 0x1FFF07FFFFFFFFFF, 0x3FF01FF, 0xFFFFFFFFFFDFFFFF, 0xEBFFDE64DFFFFFFF,
+ 0xFFFFFFFFFFFFFFEF, 0x7BFFFFFFDFDFE7BF, 0xFFFFFFFFFFFDFC5F,
+ 0xFFFFFF3FFFFFFFFF, 0xF7FFFFFFF7FFFFFD, 0xFFDFFFFFFFDFFFFF,
+ 0xFFFF7FFFFFFF7FFF, 0xFFFFFDFFFFFFFDFF, 0xFF7, 0x7E07FFFFFFF,
+ 0xFFFF000000000000, 0x3FFFFFFFFFFF, 0x3F801FFFFFFFFFFF, 0x4000,
+ 0xFFFFFFF0000, 0x7FFF6F7F00000000, 0x1F, 0x80F, 0xAF7FE96FFFFFFEF,
+ 0x5EF7F796AA96EA84, 0xFFFFBEE0FFFFBFF, 0xFFFFFFFF, 0x3FFFFFFFFFFFFFF,
+ 0xFFFF0003FFFFFFFF, 0x1FFFFFFFF, 0x3FFFFFFF, 0xFFFFFFFFFFFF07FF,
],
};
diff --git a/vendor/unicode-normalization/.cargo-checksum.json b/vendor/unicode-normalization/.cargo-checksum.json
index 617f69464..7d296934d 100644
--- a/vendor/unicode-normalization/.cargo-checksum.json
+++ b/vendor/unicode-normalization/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"61d13c11053dc298bbfb471307ca7aadbd704d880154a709d03f8a7c229a5388","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"7bef9d9fba0d6241f26cc14785e9616f8a5c35ad75a2991980fe2ca0961c1d6a","benches/bench.rs":"827e5343b059a732904be29717c2797203bfd0a633edf08042afea65372a3e2c","scripts/unicode.py":"b2182eaa678e126d1b0e8d81ec1a950effe4b8827482dd729f03e6d2035e61da","src/__test_api.rs":"78e21bfa0b98894f545c8ed3e31cec20d7a48951a7f3ed69a6130c4b3d463aee","src/decompose.rs":"c0eb774843a545356e63bbcd7fb926f80d3c97ef4601ca3701fc34154f2e9905","src/lib.rs":"1983769ea083caa36b0736c87cf2a98e91c2b900f1d5dec64e327360fa862386","src/lookups.rs":"962f9909b32e02b8a2a05836135d9cd39bb1ce01f7c659de99cbd8a3a3c78574","src/no_std_prelude.rs":"602e81e67b8952b6571826f431e3b6787be3073bc10f38a0d3374278f81a6a1f","src/normalize.rs":"de2670b4437d335d42884af844a750f70e541467ecd34077dfe032103cb9b041","src/perfect_hash.rs":"400c84e2f467f61bd55d55d08672da6a9ad7a57c938ce5d0c701a6994b1b273b","src/quick_check.rs":"9756312d75fc31b67fca954e44a4812945a7e436b03ba18b9a2441f6de570f6f","src/recompose.rs":"a6228ad7561a5c7a1ef1d510159bdde1eea8a161007c80e470432e9b844d5536","src/replace.rs":"b24c904f3e00851a78820e30ddfa4ff10c795f8925fd0ee7f5870f31fdfa770b","src/stream_safe.rs":"383d71f0da401af8e735877e43855c7e16cb06deb2263539cdec2a407dbe257d","src/tables.rs":"a5dfbf4adc3b8e872b1edeaeed9a48da38648a97940c811d04e0bce9c97361d5","src/test.rs":"3af8ad8c6bd2cc1ca44660bd265ad813c88d3074b448df4d9ff376b25fb77d26"},"package":"854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"} \ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"d43bfc158330a3a780af52ff0e82d88c8b54707ddf0469e6e27749c8ded4d1b7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"60162364e07490163f7a8e199c7a0a8ace165ae5aa7e4b6f16ff1617ddef5867","benches/bench.rs":"827e5343b059a732904be29717c2797203bfd0a633edf08042afea65372a3e2c","scripts/unicode.py":"6b1d9025fa9970c23b9721c6704aa085263408d645cf9c469295978010fd7504","src/__test_api.rs":"78e21bfa0b98894f545c8ed3e31cec20d7a48951a7f3ed69a6130c4b3d463aee","src/decompose.rs":"c0eb774843a545356e63bbcd7fb926f80d3c97ef4601ca3701fc34154f2e9905","src/lib.rs":"1983769ea083caa36b0736c87cf2a98e91c2b900f1d5dec64e327360fa862386","src/lookups.rs":"962f9909b32e02b8a2a05836135d9cd39bb1ce01f7c659de99cbd8a3a3c78574","src/no_std_prelude.rs":"602e81e67b8952b6571826f431e3b6787be3073bc10f38a0d3374278f81a6a1f","src/normalize.rs":"de2670b4437d335d42884af844a750f70e541467ecd34077dfe032103cb9b041","src/perfect_hash.rs":"400c84e2f467f61bd55d55d08672da6a9ad7a57c938ce5d0c701a6994b1b273b","src/quick_check.rs":"9756312d75fc31b67fca954e44a4812945a7e436b03ba18b9a2441f6de570f6f","src/recompose.rs":"a6228ad7561a5c7a1ef1d510159bdde1eea8a161007c80e470432e9b844d5536","src/replace.rs":"b24c904f3e00851a78820e30ddfa4ff10c795f8925fd0ee7f5870f31fdfa770b","src/stream_safe.rs":"383d71f0da401af8e735877e43855c7e16cb06deb2263539cdec2a407dbe257d","src/tables.rs":"3d9983a4e24c5b1e5dc272a025cdc729b7107f9a52a1fc89eca598e69af36c3a","src/test.rs":"3af8ad8c6bd2cc1ca44660bd265ad813c88d3074b448df4d9ff376b25fb77d26"},"package":"5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"} \ No newline at end of file
diff --git a/vendor/unicode-normalization/Cargo.toml b/vendor/unicode-normalization/Cargo.toml
index 417d04ce9..1c4d1f527 100644
--- a/vendor/unicode-normalization/Cargo.toml
+++ b/vendor/unicode-normalization/Cargo.toml
@@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "unicode-normalization"
-version = "0.1.21"
+version = "0.1.22"
authors = [
"kwantam <kwantam@gmail.com>",
"Manish Goregaokar <manishsmail@gmail.com>",
diff --git a/vendor/unicode-normalization/README.md b/vendor/unicode-normalization/README.md
index cdc456f31..35030e360 100644
--- a/vendor/unicode-normalization/README.md
+++ b/vendor/unicode-normalization/README.md
@@ -31,7 +31,7 @@ to your `Cargo.toml`:
```toml
[dependencies]
-unicode-normalization = "0.1.20"
+unicode-normalization = "0.1.22"
```
## `no_std` + `alloc` support
diff --git a/vendor/unicode-normalization/scripts/unicode.py b/vendor/unicode-normalization/scripts/unicode.py
index bfe49c8b2..d32d9128a 100644
--- a/vendor/unicode-normalization/scripts/unicode.py
+++ b/vendor/unicode-normalization/scripts/unicode.py
@@ -21,7 +21,7 @@
import collections
import urllib.request
-UNICODE_VERSION = "14.0.0"
+UNICODE_VERSION = "15.0.0"
UCD_URL = "https://www.unicode.org/Public/%s/ucd/" % UNICODE_VERSION
PREAMBLE = """// Copyright 2012-2018 The Rust Project Developers. See the COPYRIGHT
diff --git a/vendor/unicode-normalization/src/tables.rs b/vendor/unicode-normalization/src/tables.rs
index 0370e2bdb..4c6885562 100644
--- a/vendor/unicode-normalization/src/tables.rs
+++ b/vendor/unicode-normalization/src/tables.rs
@@ -15,163 +15,165 @@ use crate::quick_check::IsNormalized;
use crate::quick_check::IsNormalized::*;
#[allow(unused)]
-pub const UNICODE_VERSION: (u8, u8, u8) = (14, 0, 0);
+pub const UNICODE_VERSION: (u8, u8, u8) = (15, 0, 0);
pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x0,
0x1,
- 0x5ef,
- 0x7c,
- 0xa,
- 0x0,
- 0x1f3,
- 0x7,
- 0x8b,
+ 0x224,
+ 0x197,
+ 0x4,
0x0,
+ 0x6f,
+ 0x4,
+ 0xaf,
0x0,
- 0x2,
0x0,
- 0x12,
+ 0x4,
0x0,
- 0x1,
0x0,
+ 0x88,
+ 0xa,
+ 0x8,
0x0,
0x0,
0x0,
- 0x52,
- 0xc8,
+ 0x1c,
+ 0x46,
0x1,
- 0x8a,
- 0x8e,
+ 0xd,
+ 0x1b,
0x0,
- 0x4,
- 0x83,
+ 0x15,
+ 0x12,
+ 0x45,
+ 0xec,
+ 0x36,
+ 0x10,
0x0,
- 0x5d,
- 0x42,
- 0x4,
0x0,
0x0,
- 0x65,
0x2,
0x0,
- 0x4a,
+ 0x94,
0x0,
- 0x3,
- 0x6,
- 0x4,
- 0xa,
- 0x4,
+ 0x57,
0x0,
- 0x4,
+ 0x8,
+ 0x3,
0x7,
- 0xa,
- 0x1a,
0x0,
- 0x32,
- 0x10,
- 0x36,
- 0x13,
- 0x2b,
- 0x12,
- 0x68,
+ 0x16,
+ 0x3a,
+ 0x2,
+ 0x23,
+ 0x3,
+ 0x4,
+ 0x1c,
0x1,
0x0,
- 0x19,
+ 0x47,
+ 0x11,
+ 0x17,
+ 0x4,
+ 0x1b,
0x0,
+ 0x13,
0x0,
0x0,
0x0,
- 0x5,
- 0x1,
0x0,
0x1,
- 0xa,
+ 0x7,
+ 0x7,
+ 0x4,
+ 0x2e,
0x0,
0x0,
- 0x5f,
+ 0x2c,
0x0,
0x0,
- 0x16,
+ 0x3,
+ 0xf,
0x0,
- 0x7,
0x0,
- 0x3,
+ 0x13,
0x0,
+ 0x1,
0x2,
- 0x11,
- 0x2,
- 0xd,
+ 0x1,
+ 0x9,
0x0,
0x0,
0x0,
0x1,
0x1,
0x0,
+ 0x2,
+ 0x2,
+ 0x3,
+ 0x2,
+ 0x1e,
+ 0x0,
+ 0x8,
0x11,
0x1,
- 0x17,
0x0,
- 0x15,
- 0x0,
- 0x47,
- 0x3,
- 0x27,
- 0x2c,
0x5,
0x0,
- 0x8,
- 0x0,
- 0x7,
+ 0x79,
0x0,
+ 0x4,
+ 0x13,
0x0,
0x0,
0x5,
- 0x20,
- 0x7,
- 0x15,
- 0x10,
- 0x15,
- 0x4,
- 0x3,
- 0x6,
- 0x0,
+ 0x2,
0x0,
+ 0x5,
0x1,
- 0x13,
- 0xb,
0x15,
+ 0x1,
+ 0x0,
0x3,
+ 0xc,
0x0,
+ 0x35,
+ 0x3,
0x2,
+ 0x5,
+ 0x6,
0x0,
- 0x3,
+ 0x5,
+ 0x4,
+ 0x2,
+ 0x1c,
0x0,
0x0,
0x0,
- 0xe,
+ 0x4,
0x0,
0x0,
0x0,
- 0x7,
0x9,
- 0x5,
- 0x6,
- 0x24,
- 0xa,
- 0x0,
- 0x20,
- 0x1,
+ 0x2,
+ 0x9,
+ 0x7,
0x0,
+ 0x5,
0x0,
- 0x19,
- 0x3a,
+ 0x8,
+ 0x7,
0x0,
- 0x3,
+ 0x12,
0x9,
0x0,
+ 0x39,
+ 0x2,
+ 0x9,
0x0,
0x4,
+ 0x2,
0x0,
0x0,
0x0,
@@ -179,182 +181,184 @@ pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x11,
- 0x1c,
- 0x4,
+ 0x22,
+ 0x2,
0x0,
+ 0x1b,
+ 0x13,
+ 0xc,
0x14,
- 0x21,
- 0x2,
- 0x5,
- 0xf,
+ 0x6,
0x4,
- 0x3,
+ 0x5,
+ 0x13,
0x2,
0x0,
- 0x2,
- 0x2,
+ 0x3,
+ 0x4,
0x2,
0x0,
- 0xb,
+ 0x18,
+ 0x0,
+ 0x6,
+ 0x4,
0x0,
+ 0x0,
+ 0xa,
0xa,
+ 0x0,
0x1,
0x0,
+ 0xf,
+ 0x10,
+ 0x1,
0x0,
- 0x14,
- 0x4,
0x0,
- 0x3,
0x0,
- 0x14,
0x2,
+ 0xf,
+ 0x1,
0x4,
- 0x0,
- 0x0,
- 0x0,
- 0x3,
- 0x17,
+ 0x2,
+ 0xa,
+ 0xb,
+ 0x9,
0x4,
- 0x3,
- 0x3,
- 0xe,
- 0x1c,
0x1,
- 0x2,
- 0x5,
0x0,
- 0x1,
0xb,
0x0,
- 0x0,
- 0xd,
- 0x0,
0x3,
+ 0x0,
0x6,
- 0x3,
- 0xe,
0x0,
+ 0x6,
0x0,
- 0x2,
+ 0x3,
+ 0x4,
0x0,
0x0,
- 0x5,
+ 0x3,
0x0,
- 0x10,
0x0,
+ 0x1,
+ 0x2,
+ 0x15,
0x0,
- 0x19,
0x0,
- 0x18,
0x0,
- 0x1,
+ 0x14,
+ 0x1b,
0x0,
- 0x1,
- 0x9,
- 0x5,
+ 0xc,
0x0,
0x0,
- 0x1,
- 0x4,
0x8,
+ 0x3,
+ 0xc,
0x0,
- 0x9,
- 0x11,
- 0x1b,
- 0x7,
- 0x0,
+ 0xe,
0x2,
0x0,
- 0x11,
+ 0x3,
+ 0x0,
+ 0xa,
+ 0x2,
+ 0x6,
0x1,
+ 0x0,
0x4,
- 0x4,
+ 0x0,
+ 0x1,
+ 0x6,
0x2,
- 0x11,
+ 0x3,
+ 0x2,
+ 0x10,
0x0,
0xf,
0x0,
0x0,
0x0,
0x3,
- 0xa,
- 0x0,
+ 0x3,
+ 0x4,
+ 0xd,
0x6,
- 0x8,
- 0x9,
0x0,
- 0x4,
0x0,
+ 0x2,
0x0,
0x0,
- 0xd,
- 0x2,
- 0xc,
- 0x6,
- 0x1d,
- 0x7,
0x0,
+ 0x18,
+ 0xa,
+ 0x6,
+ 0x1,
0x1,
- 0xd,
0x8,
0x0,
- 0x3,
+ 0x1,
+ 0x1,
+ 0x7,
0x0,
- 0x5,
- 0x6,
- 0x2,
0x3,
+ 0x9,
+ 0x11,
+ 0x5,
+ 0x1,
+ 0x5,
0x3,
- 0xd,
0x16,
- 0x3,
0x7,
+ 0x5,
+ 0x4,
0x0,
- 0xc,
- 0xe,
+ 0xa,
+ 0x6,
0x3,
0x0,
0x1,
0x0,
- 0x6,
- 0x0,
- 0x3,
- 0x9,
- 0x0,
0x7,
+ 0x0,
0x6,
0x0,
- 0xa,
- 0x2,
- 0x1b,
0x5,
+ 0x41,
0x9,
- 0x16,
+ 0x1,
+ 0xa,
0x0,
+ 0x5,
+ 0x2,
+ 0x11,
+ 0xb,
+ 0x3,
0x1,
0x0,
0x0,
0x1,
- 0x2,
+ 0x1,
0x0,
- 0x7,
- 0x3,
0x2,
- 0xe,
0x0,
- 0x1,
+ 0x6,
+ 0x18,
+ 0x3,
0x0,
+ 0x3,
0x0,
0x2,
- 0x1,
+ 0x0,
0x2,
0x0,
0x0,
0x0,
+ 0x0,
0x5,
- 0x3,
- 0x9,
+ 0x1,
+ 0x0,
0x0,
0x9,
0x1,
@@ -363,295 +367,298 @@ pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x2,
0x1,
0x0,
- 0x3,
- 0x3,
- 0xc,
+ 0x1,
+ 0x2,
+ 0x1,
0x0,
+ 0x3,
0x1,
0x1,
0x1,
+ 0x0,
+ 0x3,
+ 0xc,
+ 0x1,
+ 0x3,
0x1,
0x0,
- 0x5,
- 0x5,
0x2,
- 0x7,
- 0x7,
- 0x0,
- 0x1,
0x0,
0x0,
0x5,
- 0x2,
- 0xc,
+ 0x1,
+ 0x5,
0x0,
- 0x3,
- 0x12,
- 0x4,
+ 0x1,
+ 0xb,
+ 0x5,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x5,
+ 0xf,
0x0,
0x0,
- 0xd,
+ 0x2,
0x7,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x1,
- 0x0,
- 0x9,
- 0x0,
- 0xc,
- 0x0,
- 0x8,
0x0,
0x1,
- 0x5,
- 0x1,
- 0x0,
0x0,
- 0xa,
0x9,
+ 0x8,
0x0,
- 0x5,
0x0,
+ 0x3,
+ 0x3,
0x1,
0x4,
+ 0x3,
+ 0x4,
+ 0x5,
+ 0x2,
0x0,
- 0x1,
0x0,
+ 0x2,
+ 0x6,
0x1,
- 0x0,
0x5,
- 0x9,
+ 0x1,
+ 0x0,
0x3,
- 0x5,
+ 0x6,
+ 0x8,
+ 0x2,
+ 0x2,
0x6,
0x3,
- 0x4,
+ 0x0,
+ 0x10,
0x6,
+ 0x6,
+ 0x5,
0x1,
- 0x9,
- 0x1,
+ 0x7,
0x0,
0x2,
- 0x6,
+ 0x3,
0x2,
- 0x4,
- 0x0,
0x0,
- 0x8,
0x0,
0x0,
+ 0x6,
0x0,
0x0,
- 0xc,
0x0,
0x0,
+ 0x1,
0x0,
- 0x6,
- 0x6,
0x0,
- 0x6,
0x0,
0x1,
- 0x3,
- 0x4,
- 0x0,
- 0x3,
- 0x5,
+ 0x1,
+ 0x8,
+ 0x1,
0x0,
0x2,
- 0x2,
- 0x1,
- 0x4,
- 0x4,
0x0,
0x1,
+ 0xc,
+ 0x4,
0x1,
+ 0x2,
0x1,
- 0x0,
- 0x6,
- 0x3,
- 0x8,
- 0x1,
+ 0x4,
0x2,
+ 0x5,
+ 0x4,
0x0,
0x3,
+ 0x4,
0x2,
0x0,
0x1,
+ 0x3,
+ 0x7,
+ 0x6,
+ 0x8,
0x0,
+ 0x2,
0x3,
- 0xd,
0x0,
+ 0x2,
+ 0x2,
+ 0x2,
+ 0x4,
0x0,
+ 0x0,
+ 0x6,
+ 0x6,
+ 0x6,
+ 0xc,
0x5,
- 0x1,
0x0,
- 0x4,
- 0x3,
0x0,
0x0,
- 0x8,
- 0x4,
0x1,
- 0x1,
- 0xb,
+ 0x2,
0x0,
0x3,
0x0,
+ 0x9,
+ 0x3,
0x2,
0x1,
- 0x0,
- 0x16,
+ 0x1,
+ 0x9,
0x1,
0x0,
- 0x2,
0x8,
+ 0x1,
+ 0x6,
0x0,
0x3,
0x0,
- 0x0,
0x5,
0x1,
- 0x0,
- 0x0,
0x1,
- 0x4,
0x0,
0x0,
- 0x9,
0x2,
+ 0x4,
0x0,
0x2,
0x0,
- 0x9,
- 0x4,
0x2,
+ 0x6,
+ 0x6,
0x2,
+ 0x8,
+ 0x5,
+ 0x6,
+ 0x5,
0x1,
- 0x1,
- 0x3,
- 0x0,
- 0x7,
+ 0x6,
+ 0x2,
0x0,
+ 0x1,
0x0,
0x0,
0x3,
+ 0x0,
0x1,
- 0x3,
- 0x6,
- 0x2,
+ 0x9,
+ 0x5,
+ 0x5,
0xe,
0x0,
- 0x6,
+ 0x3,
0x5,
0x0,
0x0,
0x1,
+ 0x1,
0x0,
- 0x2,
0x0,
0x0,
0x0,
0x1,
- 0x2,
+ 0x4,
0x0,
- 0x1,
+ 0x2,
0x4,
+ 0x6,
0x5,
- 0x9,
- 0x1,
+ 0x6,
0x0,
- 0x9,
0x0,
0x1,
+ 0x1,
0x0,
0x0,
- 0x1,
- 0x2,
+ 0x5,
0x2,
0x8,
- 0x3,
- 0x3,
+ 0x8,
+ 0x1,
+ 0x6,
0x0,
- 0x7,
0x1,
+ 0x0,
0x1,
- 0x9,
- 0x7,
- 0x13,
+ 0x0,
+ 0x8,
0x0,
0x4,
0x7,
+ 0xa,
0x1,
0x0,
0x0,
0x2,
0x1,
- 0x3,
- 0x0,
0x1,
0x1,
+ 0x0,
+ 0x1,
0x2,
0x0,
0x2,
0x1,
- 0x0,
- 0x5,
+ 0x4,
+ 0x4,
0x0,
0x0,
0x0,
- 0x2,
+ 0x6,
0x0,
- 0x2,
+ 0x3,
+ 0x3,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x5,
- 0x3,
+ 0x2,
+ 0x1,
0x1,
0x2,
0x2,
0x0,
- 0x1,
0x4,
+ 0x2,
0x1,
0x0,
0x0,
- 0x7,
0x1,
- 0x1,
- 0x3,
- 0x0,
- 0x5,
0x0,
0x1,
+ 0x1,
+ 0x0,
0x2,
0x2,
0x2,
0x2,
0x0,
0x1,
+ 0x5,
+ 0x4,
+ 0x1,
+ 0x0,
+ 0x1,
+ 0x1,
0x0,
- 0x3,
- 0x2,
- 0x2,
0x0,
0x1,
+ 0x4,
0x1,
0x2,
- 0x2,
0x1,
0x1,
0x0,
@@ -660,93 +667,94 @@ pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x4,
- 0x3,
0x0,
- 0x0,
- 0x7,
0x1,
- 0x7,
0x0,
- 0x1,
- 0x7,
- 0x2,
- 0x1,
- 0x3,
- 0x2,
0x0,
0x4,
+ 0x1,
0x2,
- 0x3,
+ 0x0,
0x1,
+ 0xd,
+ 0x4,
0x0,
0x1,
+ 0x4,
+ 0x0,
+ 0x5,
+ 0x3,
+ 0x7,
+ 0x3,
+ 0x3,
+ 0x3,
0x2,
0x0,
- 0x4,
+ 0x2,
+ 0x2,
0x2,
0x1,
0x0,
0x1,
- 0x0,
0x3,
0x4,
- 0x3,
+ 0x1,
0x0,
+ 0x1,
0x4,
- 0x0,
0x1,
0x0,
0x0,
- 0xa,
- 0x4,
- 0x2,
- 0x1,
0x0,
+ 0x1,
+ 0x3,
+ 0x1,
0x0,
- 0x5,
0x0,
- 0x2,
- 0x2,
0x1,
+ 0x4,
+ 0x1,
+ 0x8,
0x2,
0x4,
0x1,
- 0x0,
0x1,
- 0x7,
- 0x3,
- 0x7,
+ 0x1,
0x5,
0x1,
+ 0x4,
+ 0x1,
+ 0x1,
+ 0x2,
+ 0x6,
0x0,
0x0,
0x0,
0x0,
+ 0x2,
0x0,
- 0x3,
+ 0x2,
0x0,
- 0x3,
- 0x3,
- 0x5,
- 0x5,
0x6,
- 0x0,
+ 0x3,
0x1,
+ 0x3,
+ 0x2,
+ 0x3,
0x5,
0x4,
- 0x2,
+ 0x1,
0x0,
- 0x3,
+ 0x5,
0x0,
0x0,
0x1,
0x3,
0x0,
- 0x3,
+ 0x2,
0x0,
0x1,
- 0x5,
+ 0x1,
0x0,
0x0,
0x0,
@@ -754,124 +762,126 @@ pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0xb,
- 0x3,
- 0x2,
+ 0x5,
+ 0x5,
+ 0x8,
0x0,
0x0,
0x0,
0x0,
- 0x5,
+ 0x6,
+ 0x0,
0x0,
0x0,
0x0,
0x2,
0x2,
- 0x2,
- 0x8,
+ 0x5,
0x1,
- 0x4,
0x0,
- 0x5,
+ 0x1,
+ 0x1,
0x0,
0x2,
0x2,
- 0x2,
- 0xb,
- 0x6,
+ 0x7,
+ 0x1,
+ 0x1,
0x2,
0x0,
- 0x3,
+ 0x2,
0x2,
0x1,
0x0,
0x0,
0x1,
- 0x1,
- 0x1,
0x0,
0x2,
- 0x5,
0x2,
0x2,
+ 0x4,
0x1,
+ 0x4,
0x0,
- 0x5,
- 0x3,
- 0x5,
- 0x0,
- 0x1,
0x2,
- 0x5,
- 0x1,
+ 0x2,
+ 0x4,
0x4,
+ 0x0,
0x8,
- 0x3,
+ 0x4,
+ 0x6,
+ 0x2,
+ 0x1,
0x1,
- 0x0,
0x0,
0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x3,
+ 0x6,
0x1,
+ 0x0,
+ 0x3,
0x2,
0x1,
- 0x6,
- 0x1,
0x0,
+ 0x5,
0x4,
- 0x1,
+ 0x0,
+ 0x0,
+ 0x5,
0x2,
0x0,
0x0,
0x2,
- 0x3,
0x0,
0x0,
0x4,
- 0x1,
- 0x0,
- 0x1,
- 0x1,
+ 0x3,
0x0,
+ 0x9,
+ 0x5,
0x2,
- 0x3,
- 0x1,
0x0,
0x0,
0x2,
0x0,
- 0x2,
0x1,
+ 0x7,
+ 0x0,
0x3,
0x1,
- 0x1,
- 0x1,
+ 0x2,
0x1,
0x0,
0x0,
- 0x5,
- 0x4,
+ 0x2,
+ 0x3,
0x0,
0x2,
- 0x1,
0x3,
+ 0x1,
0x2,
0x1,
0x2,
0x0,
+ 0x4,
0x2,
- 0x2,
- 0x1,
0x1,
0x1,
0x1,
0x2,
- 0xc,
0x2,
0x0,
+ 0x4,
0x2,
+ 0x1,
0x0,
0x0,
- 0x2,
+ 0x3,
+ 0x0,
0x0,
0x0,
0x0,
@@ -884,965 +894,975 @@ pub(crate) const CANONICAL_COMBINING_CLASS_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x2,
- 0x2,
0x0,
- 0x3,
- 0x2,
0x2,
+ 0x0,
0x1,
+ 0x0,
+ 0x2,
0x1,
0x1,
- 0x4,
0x0,
- 0x3,
+ 0x2,
+ 0x0,
+ 0x1,
0x0,
0x0,
- 0x2,
0x1,
0x1,
- 0x7,
- 0x2,
- 0x4,
0x0,
+ 0x1,
+ 0x0,
+ 0x2,
0x0,
- 0x4,
0x3,
- 0x6,
- 0x1,
0x0,
0x1,
- 0x2,
0x1,
0x0,
+ 0x0,
0x1,
- 0x3,
0x2,
- 0x0,
0x1,
+ 0x2,
+ 0x3,
+ 0x5,
+ 0x3,
0x1,
+ 0x0,
0x1,
- 0x9,
+ 0x3,
+ 0x7,
0x0,
0x0,
0x2,
0x0,
0x2,
+ 0x3,
0x1,
- 0x4,
];
pub(crate) const CANONICAL_COMBINING_CLASS_KV: &[u32] = &[
0x34AE6,
- 0x348DC,
- 0xA67AE6,
- 0x746DC,
- 0x65222,
+ 0x2DFAE6,
+ 0x1DFADA,
+ 0x339DC,
+ 0x1DFCE9,
0xA4D09,
- 0x20D201,
+ 0x20D0E6,
0x593E6,
0x102E0DC,
- 0x1E2EDE6,
- 0x302DDE,
+ 0x1CF4E6,
+ 0x5A2DC,
0xFE26E6,
- 0x898E6,
- 0x329DC,
+ 0x11D4509,
+ 0x5C219,
+ 0x6EADC,
0xA675E6,
0x10F4EDC,
- 0x2DF7E6,
0xA8EBE6,
- 0x310E6,
- 0x64F1F,
+ 0x332DC,
+ 0xC4D09,
0x741E6,
- 0xF8082,
- 0x1AC8E6,
- 0x322CA,
- 0x1144607,
- 0x1E023E6,
- 0x5C5DC,
+ 0x1D171D8,
+ 0xFE2DDC,
+ 0x1DF2E6,
+ 0x1DDEE6,
+ 0xA8E1E6,
+ 0x5BB14,
0x1DD5E6,
0x8CEE6,
+ 0x1A7BE6,
0xF7484,
- 0x1B6DE6,
- 0x59ADE,
+ 0xA8E6E6,
0x6191F,
- 0x82CE6,
- 0x305E6,
+ 0x114C307,
+ 0x1A79E6,
0x65DE6,
- 0x5B812,
- 0x8F6DC,
- 0x1DEEE6,
+ 0x8F11C,
+ 0x1E020E6,
+ 0xA8F1E6,
+ 0x1DFDDC,
0xFE25E6,
0x1E947E6,
- 0x486E6,
0x1A75E6,
+ 0xEBA09,
0x1E02AE6,
- 0x1D182DC,
- 0x1DE6E6,
- 0x108DDC,
+ 0x64B1B,
+ 0x6D9E6,
+ 0x116B609,
0x1DECE6,
- 0x1E015E6,
- 0x8D6E6,
+ 0xE3A09,
+ 0x954E6,
0x2DE9E6,
0x1AB3E6,
- 0x1AB0E6,
+ 0x8F3E6,
0x8F7E6,
- 0x1136CE6,
- 0xE486B,
- 0x8E1E6,
+ 0xA8E2E6,
+ 0x1E00BE6,
+ 0xFE28DC,
0x20D801,
- 0x821E6,
- 0x8FFE6,
- 0x135DE6,
+ 0xAAB0E6,
+ 0x10F4DDC,
0x825E6,
- 0xFB1E1A,
- 0x1D16DE2,
- 0x8F21D,
- 0x2DF1E6,
- 0x8E3DC,
+ 0x611E6,
+ 0xAABEE6,
+ 0x820E6,
+ 0x8E8E6,
+ 0x306E6,
0x2DE4E6,
- 0x1A18DC,
+ 0x11F4109,
0x111CA07,
+ 0x2CF0E6,
0x1CD7DC,
0x10A3ADC,
- 0x1DC4E6,
0x1E131E6,
- 0x6E4E6,
+ 0x103A09,
+ 0x73BDC,
0x358E8,
0x487E6,
0x1AB1E6,
- 0x35DEA,
- 0xFE20E6,
+ 0x11370E6,
+ 0x1CD0E6,
0xA8EEE6,
- 0x597E6,
+ 0x33CDC,
0x20D5E6,
0x819E6,
- 0x2DE5E6,
+ 0x16B30E6,
0x16AF301,
- 0x1DD0CA,
0x9BC07,
+ 0x1DE9E6,
0x1DDAE6,
- 0x1DF8E4,
+ 0x1136BE6,
0x82BE6,
- 0x1CE201,
- 0x327CA,
- 0x1A17E6,
- 0xECB7A,
- 0xA67DE6,
- 0x10F48E6,
- 0x103707,
+ 0x173409,
+ 0x1DDBE6,
+ 0x5B40E,
+ 0x1D16DE2,
+ 0x1D16901,
+ 0x34CE6,
+ 0x2DF0E6,
0x33701,
- 0x309E6,
- 0x32DDC,
- 0x1B6EE6,
- 0x34BE6,
- 0x10EABE6,
- 0x344E6,
+ 0x11373E6,
+ 0x112E907,
+ 0x1AC0DC,
+ 0x20EA01,
+ 0x33EE6,
+ 0xF7181,
0x1D16801,
0x346E6,
- 0x8DDE6,
- 0x367E6,
- 0x1E010E6,
- 0x302BE4,
- 0x5ADDE,
- 0x1CDAE6,
+ 0x1E8D6DC,
+ 0x1E8D0DC,
+ 0xFE2CDC,
+ 0x1CE0E6,
+ 0x8EAE6,
+ 0x20DBE6,
+ 0x16B31E6,
0x735E6,
- 0x5C712,
- 0x2DEEE6,
- 0x1DCED6,
- 0x598E6,
- 0x1193E09,
- 0x116B707,
+ 0x10EFDDC,
+ 0x1D17EDC,
+ 0x11A3409,
+ 0x81FE6,
+ 0x1E01CE6,
+ 0x1DDFE6,
0x20E8DC,
- 0x10F4CE6,
+ 0xABED09,
0x1DE1E6,
- 0x65BE6,
- 0x611E6,
- 0x1E008E6,
- 0x1DD9E6,
- 0x85BDC,
- 0x1A7FDC,
+ 0x316DC,
+ 0x1D182DC,
+ 0x20D7E6,
+ 0x64F1F,
+ 0x8F5E6,
0xD4D09,
- 0x2DF0E6,
- 0x8CCE6,
- 0x17D209,
- 0x596DC,
+ 0x1AC9E6,
+ 0x110B909,
+ 0x1ABCE6,
+ 0xA67AE6,
0x1D1AAE6,
- 0x5B40E,
- 0x1DE3E6,
- 0x743E6,
+ 0x1E4EEDC,
+ 0x1E130E6,
+ 0x59FE6,
+ 0x1939DE,
0x357E6,
- 0x324DC,
- 0x30BE6,
- 0x33EE6,
- 0x1CE301,
+ 0x119E009,
+ 0x16FF006,
+ 0x733E6,
+ 0xFE29DC,
0x1CF8E6,
- 0x1E003E6,
+ 0xF8409,
0x364E6,
0x317DC,
0x483E6,
- 0xEBA09,
0x36CE6,
- 0x18A9E4,
- 0x1CD9DC,
- 0x1E005E6,
+ 0x5B10B,
+ 0x1CD2E6,
+ 0x307E6,
+ 0x65121,
0x330DC,
0x319DC,
- 0x81CE6,
+ 0x656DC,
0x1DE4E6,
0x952DC,
- 0x115C007,
- 0x1E009E6,
- 0x10F49E6,
+ 0x345F0,
+ 0x2DF1E6,
+ 0x193BDC,
0x659E6,
- 0x1CDFDC,
- 0x1CDBE6,
- 0xEB876,
- 0x6D7E6,
- 0x360EA,
+ 0x5ABE6,
+ 0x1B73E6,
+ 0x2CF1E6,
+ 0xABC07,
+ 0xF7C82,
0x1136AE6,
0xA8E4E6,
0x8FBE6,
- 0xA67CE6,
0x5B20C,
- 0x333DC,
- 0x1DCADC,
- 0x1E949E6,
- 0x11371E6,
- 0x5BF17,
- 0x135FE6,
+ 0xFE21E6,
+ 0x2DFBE6,
+ 0x31AE8,
+ 0x738DC,
+ 0x20D301,
+ 0xFE2ADC,
+ 0x11369E6,
0xF7282,
- 0x1DFBE6,
+ 0x1AC2E6,
0x1D17BDC,
0xF86E6,
- 0x10F4AE6,
+ 0x327CA,
0x1DC0E6,
- 0xD3C09,
+ 0x10F48E6,
0x1104609,
- 0x5B00A,
+ 0x1B6BE6,
0x8E6DC,
0x1E134E6,
0x341E6,
0x1DF6E8,
- 0xA674E6,
+ 0xA8ECE6,
0x1D1ABE6,
0x6ECE6,
- 0x1D16FD8,
+ 0x1E2AEE6,
0x5B50F,
+ 0x1AC7E6,
0x1E002E6,
- 0x1D165D8,
- 0xF7C82,
- 0x67023,
- 0x5AADC,
- 0x1DD3E6,
- 0x10F47DC,
- 0x2DE6E6,
+ 0xFC6DC,
+ 0x1E136E6,
+ 0x8DFE6,
+ 0x64C1C,
+ 0x658E6,
+ 0x6E1E6,
0x2DE7E6,
- 0x20D6E6,
- 0x1D244E6,
- 0x1DC6E6,
- 0x20E601,
- 0x1E00AE6,
- 0x135EE6,
+ 0x8CFDC,
+ 0x302E6,
+ 0x1AC4DC,
+ 0xAABFE6,
+ 0x5B913,
+ 0x1D18BDC,
0x1172B09,
- 0xAAC1E6,
+ 0x2DF3E6,
0x739DC,
- 0x10AE5E6,
+ 0x2DE0E6,
+ 0x1CDCDC,
0x1107009,
- 0x308E6,
+ 0xA92CDC,
0x823E6,
- 0x2CF0E6,
0x1DF3E6,
+ 0xA67DE6,
0x10F46DC,
- 0x1DEBE6,
+ 0x1DCCE6,
0x6DCE6,
- 0x1D166D8,
0x11A4709,
- 0x614E6,
+ 0xEB976,
+ 0x36BE6,
0x65EE6,
0x1CF9E6,
- 0x81DE6,
- 0x6D9E6,
- 0x951E6,
- 0x2DE8E6,
+ 0x8D6E6,
+ 0x8E0E6,
+ 0x1B6EE6,
0x8D8E6,
- 0x1193D09,
- 0x328CA,
+ 0x1E026E6,
+ 0x343E6,
0x20D901,
- 0x32FDC,
- 0xA92CDC,
+ 0x1E948E6,
+ 0x5B610,
+ 0x1E011E6,
0x1DE8E6,
- 0x1E00BE6,
- 0x8F3E6,
- 0x8EEDC,
- 0xFE22E6,
- 0x8D9E6,
- 0x1D189E6,
- 0xFE28DC,
- 0xF83E6,
- 0x2DF4E6,
- 0x20F0E6,
+ 0x1DF7E4,
+ 0x2DFCE6,
+ 0x11D9709,
+ 0x486E6,
+ 0x1DC1E6,
+ 0x591DC,
+ 0x11D4409,
+ 0xA8C409,
+ 0x1BAA09,
+ 0x10EFFDC,
0x6EDDC,
- 0xFE29DC,
- 0x31EDC,
- 0x1DFCE9,
+ 0x356DC,
+ 0x1DEEE6,
+ 0x2DEDE6,
0x64D1D,
- 0x1DDDE6,
- 0x33BDC,
- 0x1D171D8,
- 0x111C009,
+ 0x17D209,
+ 0xD3C09,
+ 0x1E945E6,
+ 0x114C209,
0x303E6,
- 0xA8E0E6,
- 0xACD09,
- 0x5ACE6,
+ 0xA6F0E6,
+ 0x302FE0,
+ 0x1E01BE6,
0x11368E6,
- 0x10D24E6,
- 0x1DDEE6,
- 0x31CDC,
- 0x354DC,
- 0xF8409,
- 0x1E01EE6,
+ 0x1163F09,
+ 0x1CE301,
+ 0x5A3DC,
+ 0x8EFDC,
+ 0x596DC,
+ 0x1E028E6,
0x10F4FDC,
- 0x1E014E6,
- 0x5C219,
+ 0xA82C09,
+ 0x1D172D8,
0x2CEFE6,
- 0x326DC,
- 0x2DF8E6,
+ 0x10F49E6,
+ 0xA8EAE6,
0x32CDC,
0xD3B09,
0x1E00FE6,
- 0x1E8D2DC,
- 0x5A7DC,
+ 0x8EDDC,
+ 0x171409,
0x1ABBE6,
- 0x8DAE6,
+ 0x1E8D3DC,
0xB3C07,
- 0x1E013E6,
+ 0x59DE6,
0x10AE6DC,
- 0x1E8D5DC,
- 0x745E6,
+ 0x1DFBE6,
+ 0x16FF106,
0x82AE6,
- 0xFE23E6,
- 0x592E6,
- 0x1E8D3DC,
- 0x1AC5E6,
- 0x8D7E6,
- 0x5BC15,
- 0x33501,
- 0x1E027E6,
- 0x5B30D,
- 0xA80609,
- 0x1CD0E6,
- 0x363E6,
+ 0x20EEDC,
+ 0x1CDFDC,
+ 0x1CDDDC,
+ 0x8D2DC,
+ 0x135FE6,
+ 0xF7A82,
+ 0x610E6,
+ 0x1144209,
+ 0x2DEEE6,
+ 0x1145EE6,
+ 0x73DE6,
+ 0x35DEA,
0xFE2FE6,
+ 0xCBC07,
0x1DC7E6,
- 0xAAB2E6,
- 0x59EE6,
- 0x32ADC,
+ 0x6E7E6,
+ 0x321CA,
+ 0x5A6DC,
0xA8F0E6,
- 0x31AE8,
- 0x10A0FE6,
- 0x1123509,
- 0x1D18ADC,
+ 0x5BA13,
+ 0x2DECE6,
+ 0x8EEDC,
0x16AF201,
- 0x1DFDDC,
- 0x10376E6,
- 0x353DC,
+ 0x5C712,
+ 0x612E6,
+ 0x59CE6,
+ 0x11D4207,
0x1ABADC,
- 0x20EA01,
0x1AB4E6,
- 0x16FF106,
+ 0x1E8D2DC,
+ 0x85BDC,
0x1B72E6,
- 0x740E6,
- 0x1CDCDC,
- 0x1E130E6,
- 0x302FE0,
- 0x1E2ECE6,
+ 0x1E000E6,
+ 0x5B00A,
+ 0x5C5DC,
+ 0x10F47DC,
+ 0x1A78E6,
0x1113409,
- 0x1E006E6,
- 0x35ADC,
- 0x8CFDC,
- 0x1DCCE6,
+ 0x1144607,
+ 0x10D26E6,
+ 0x20DCE6,
+ 0x350E6,
0xF7D82,
- 0x8EAE6,
- 0x173409,
- 0x323DC,
- 0x1CDEDC,
- 0x89DE6,
+ 0x31FDC,
+ 0x103909,
+ 0x8D3DC,
+ 0x1BE607,
+ 0x731DC,
0x312E6,
- 0x34CE6,
0x829E6,
- 0x1DCFDC,
- 0x899DC,
- 0x10A3901,
- 0x114C307,
- 0x5B913,
+ 0x8FADC,
+ 0x7EBE6,
+ 0x1DDDE6,
+ 0x1D165D8,
+ 0x20E9E6,
+ 0x1E01EE6,
0x1E135E6,
0x1DEDE6,
- 0x1E001E6,
- 0x1A7CE6,
- 0xA8EDE6,
- 0x748DC,
- 0x8D3DC,
- 0x1E028E6,
- 0x8D1DC,
+ 0xC565B,
+ 0x1E012E6,
+ 0x2DE3E6,
+ 0xF7B82,
+ 0x1CDEDC,
+ 0x36DE6,
+ 0x8F4E6,
0x1E8D4DC,
0x73CDC,
- 0x1E8D6DC,
- 0xAAB7E6,
- 0x20EFDC,
+ 0x11374E6,
+ 0x5ACE6,
+ 0x1AC8E6,
0x2DEBE6,
- 0xA8E8E6,
- 0x1E01CE6,
- 0x1D1ACE6,
- 0xA8EFE6,
- 0x8E5E6,
+ 0xA92BDC,
+ 0x1117307,
+ 0x111C009,
+ 0x33601,
+ 0xF8082,
0x20D4E6,
- 0xA6F0E6,
- 0x16B32E6,
+ 0x59BDC,
+ 0x1E001E6,
0x827E6,
- 0xA3C07,
+ 0x33401,
0x31BD8,
- 0x34EDC,
- 0xFE2DDC,
- 0xDCA09,
+ 0x20D201,
+ 0x1E003E6,
+ 0x1DF0E6,
0x31DDC,
- 0x345F0,
- 0x171409,
- 0x1DFFDC,
- 0x1DC3E6,
- 0x302ADA,
- 0x1E026E6,
- 0x302CE8,
- 0x1E2AEE6,
- 0xFE21E6,
- 0x73AE6,
+ 0x2DF4E6,
+ 0x11372E6,
+ 0x314E6,
+ 0x18A9E4,
+ 0x1136CE6,
+ 0x2DE5E6,
+ 0x1113309,
+ 0x135DE6,
+ 0x1A77E6,
+ 0xE3967,
0x10D27E6,
0xCCD09,
- 0x1037AE6,
- 0x1B6CDC,
- 0xECA7A,
- 0x1D185E6,
- 0x65CDC,
- 0xE3867,
- 0x2CF1E6,
+ 0x32DDC,
+ 0x592E6,
+ 0x2DEFE6,
+ 0x8CAE6,
+ 0x2DE1E6,
+ 0x657E6,
+ 0x32BDC,
0x10EACE6,
- 0x20D301,
- 0x17DDE6,
+ 0x309E6,
+ 0x730E6,
0x65FDC,
- 0x11D4409,
- 0xF7B82,
- 0x8E0E6,
- 0x71124,
- 0x1CE401,
- 0x64E1E,
+ 0x1E014E6,
+ 0x8DEE6,
+ 0x2DFEE6,
+ 0x16B33E6,
+ 0x8CDE6,
+ 0x329DC,
+ 0x8F21D,
0x93C07,
- 0x89EE6,
- 0x1DD1E6,
+ 0x747E6,
+ 0x859DC,
0x736E6,
0x10A38E6,
- 0x20E9E6,
+ 0x81DE6,
0x1CD5DC,
- 0x10F4DDC,
- 0x1AC3DC,
- 0xFE2ADC,
- 0x306E6,
+ 0x743E6,
+ 0x746DC,
+ 0x899DC,
0x61A20,
+ 0x1CE201,
0x301E6,
- 0x738DC,
- 0x1D172D8,
+ 0x1E944E6,
+ 0x1D186E6,
0x6E0E6,
- 0x1DE0E6,
- 0x16B30E6,
+ 0x1194307,
0x355DC,
- 0x7EEE6,
- 0x11D4207,
- 0x7F1E6,
+ 0x6181E,
+ 0xA66FE6,
+ 0x8FFE6,
0x11100E6,
- 0x30CE6,
+ 0x33DE6,
0x1DC2DC,
+ 0x615E6,
0x342E6,
- 0x1CEDDC,
- 0x352E6,
- 0xE4B6B,
- 0xAAB0E6,
+ 0x1A17E6,
+ 0x11367E6,
+ 0x10EABE6,
+ 0x6EBE6,
0x1E01FE6,
- 0x5A4DC,
+ 0xE4A6B,
0x325DC,
- 0x1DE5E6,
- 0xA8F1E6,
- 0x1D17FDC,
- 0x1DF5E6,
- 0x11372E6,
- 0x484E6,
- 0x318DC,
- 0x1D16901,
- 0x1E8D0DC,
- 0xF35DC,
+ 0x349DC,
+ 0xFE23E6,
+ 0x10376E6,
+ 0x2DFFE6,
+ 0x1D16FD8,
+ 0x30FE6,
+ 0x1BAB09,
+ 0x2DE2E6,
+ 0x740E6,
+ 0x1193E09,
0xF39D8,
- 0x1E00CE6,
- 0xA8E1E6,
+ 0x20EFDC,
+ 0x2DE6E6,
0x1D187E6,
- 0x1AC0DC,
- 0x817E6,
+ 0x1DD2E6,
+ 0x10F4AE6,
0x6D8E6,
0x1B3407,
0x2DEAE6,
- 0x103A09,
- 0x1CD401,
+ 0xA679E6,
+ 0x10F84E6,
0xF87E6,
0x35FE9,
0x300E6,
- 0xA6F1E6,
+ 0x7EEE6,
0x2DF2E6,
- 0x103909,
- 0x615E6,
- 0x2DFFE6,
- 0x749E6,
- 0x309908,
- 0x81FE6,
+ 0x11F4209,
+ 0x73AE6,
+ 0x31EDC,
+ 0x1E00DE6,
+ 0x1DCED6,
+ 0x1AB7DC,
0x1D16ED8,
- 0x1E017E6,
- 0x1CD8DC,
+ 0x352E6,
+ 0x8F6DC,
0xA677E6,
- 0xEC97A,
- 0x1D186E6,
- 0x307E6,
- 0x20D7E6,
+ 0x1A7CE6,
+ 0x8E7E6,
+ 0x16B32E6,
+ 0x1DD9E6,
0x1DF9DC,
0x8E9DC,
- 0x2DF9E6,
- 0x5B610,
- 0x11A3409,
+ 0x11366E6,
+ 0x1AC6E6,
+ 0x1CE701,
0x1CD1E6,
- 0x10378E6,
- 0x656DC,
- 0x818E6,
- 0x33401,
- 0x1ABDDC,
- 0x16FF006,
+ 0x35EEA,
+ 0x16AF401,
+ 0x1AB0E6,
+ 0x34BE6,
+ 0x33BDC,
+ 0x67023,
0x366E6,
- 0x1ACCE6,
- 0x89ADC,
- 0x65020,
- 0x20E501,
- 0xAAF609,
+ 0x10D25E6,
+ 0x9FEE6,
+ 0xAAB4DC,
+ 0xBCD09,
+ 0x1DC9E6,
0x5BD16,
0x8D0DC,
- 0x1CDDDC,
- 0x7F3E6,
+ 0x816E6,
+ 0x101FDDC,
+ 0xA3C07,
0x1D17CDC,
- 0xA678E6,
+ 0x732E6,
0x826E6,
- 0xA679E6,
- 0x35CE9,
+ 0x1133B07,
+ 0x1CD9DC,
0x81EE6,
0x10F83DC,
- 0xF7181,
- 0x820E6,
- 0x1B73E6,
- 0x2DE1E6,
+ 0x313E6,
+ 0x1DFFDC,
+ 0x1D17FDC,
0x1D16701,
0x1A6009,
- 0xABC07,
+ 0x1E949E6,
+ 0x10A0DDC,
0x1183909,
- 0x1B6FE6,
- 0x321CA,
+ 0xF19DC,
0x1DE7E6,
- 0x742DC,
+ 0xB4D09,
0x89CE6,
- 0x1E018E6,
- 0x65AE6,
+ 0x2DFDE6,
+ 0x367E6,
0xA9C009,
0xA67BE6,
+ 0x333DC,
0x5A1E6,
- 0x20E7E6,
- 0x11366E6,
+ 0x8EBE6,
+ 0x1E009E6,
0x1DEFE6,
- 0x1DF4E6,
- 0x1E946E6,
+ 0x324DC,
+ 0xFE2BDC,
0xFE27DC,
- 0x8DEE6,
- 0x193AE6,
- 0x114C209,
+ 0x10D24E6,
+ 0x81BE6,
+ 0x1E008E6,
0x1E01DE6,
0xA95309,
- 0x59FE6,
+ 0x6DBE6,
0xC5554,
0x2D7F09,
- 0x1B6BE6,
- 0x610E6,
- 0x8F8E6,
+ 0x1CDAE6,
+ 0x5BC15,
+ 0x59ADE,
0xA676E6,
- 0x1D188E6,
- 0x1BAA09,
- 0xAABFE6,
+ 0x2DF8E6,
+ 0x20D6E6,
+ 0x5B30D,
0x1D181DC,
0x1ACADC,
- 0xCBC07,
- 0x115BF09,
+ 0x953E6,
+ 0x328CA,
0x5A0E6,
- 0x30FE6,
- 0x6E3DC,
- 0x82DE6,
- 0x658E6,
- 0x8FADC,
+ 0x595E6,
+ 0x8D5E6,
+ 0x308E6,
+ 0xA674E6,
+ 0x30CE6,
0x1A76E6,
- 0x1B4409,
- 0x32BDC,
- 0x313E6,
- 0x11D9709,
- 0x1AB8DC,
- 0x1E012E6,
- 0x1DC8E6,
- 0xF18DC,
- 0x613E6,
- 0x30EE6,
- 0x744DC,
- 0x8DBE6,
+ 0x1DC6E6,
+ 0x6E2E6,
+ 0x10F4CE6,
+ 0x20F0E6,
+ 0x8CBE6,
+ 0x10A0FE6,
+ 0x135EE6,
+ 0x1B6FE6,
+ 0x1AB2E6,
+ 0x1DF8E4,
+ 0x5AADC,
+ 0x10AE5E6,
0x89FE6,
- 0x1DDFE6,
- 0xE496B,
+ 0x1E00CE6,
+ 0x20E501,
0x8FCE6,
- 0x654E6,
+ 0x65020,
0x8ECE6,
- 0x8CAE6,
- 0x1CF4E6,
+ 0x898E6,
+ 0x1E2EDE6,
0x1DD7E6,
- 0x30AE6,
- 0x591DC,
- 0x730E6,
+ 0xE3867,
+ 0x89DE6,
+ 0x1B71E6,
0x85ADC,
- 0x6E8E6,
- 0x59BDC,
- 0x350E6,
- 0x171509,
- 0x16B34E6,
+ 0x1DC5E6,
+ 0x1D189E6,
+ 0xA69FE6,
+ 0x348DC,
+ 0x8DBE6,
+ 0x1DC4E6,
0x320DC,
- 0x10F85DC,
- 0x2DEDE6,
- 0x1DF2E6,
- 0x5BB14,
- 0xF82E6,
- 0x193BDC,
- 0xE3A09,
- 0x9FEE6,
- 0x1113309,
- 0xFE2EE6,
- 0xF37DC,
- 0x1DC1E6,
- 0xC4D09,
+ 0xA8E3E6,
+ 0x1E946E6,
+ 0x1D170D8,
+ 0xAAF609,
+ 0x1ACCE6,
+ 0x360EA,
+ 0x1ABFDC,
+ 0x1AC1E6,
+ 0x302CE8,
+ 0x2DF7E6,
+ 0xEB876,
+ 0x1E132E6,
0x1DFEE6,
- 0x1117307,
+ 0x33FE6,
0x20EB01,
- 0x8EFDC,
+ 0x82DE6,
0x347DC,
0x1123607,
- 0x1CE601,
- 0x316DC,
- 0x6EADC,
- 0x1E945E6,
- 0x16B36E6,
- 0xA8EAE6,
- 0x332DC,
+ 0xA6F1E6,
+ 0x749E6,
+ 0x17DDE6,
+ 0x7F1E6,
+ 0x617E6,
+ 0x1ACDE6,
+ 0x1DE6E6,
0x8E4E6,
0x351E6,
- 0x10D25E6,
- 0x2DFEE6,
- 0x6E2E6,
+ 0x89EE6,
+ 0x613E6,
+ 0x1DCDEA,
0x655DC,
- 0x2DEFE6,
- 0x1DC9E6,
+ 0x20E1E6,
+ 0x65CDC,
+ 0x1ABDDC,
0x1AB9DC,
- 0x11A9909,
- 0xF7A82,
- 0x20D1E6,
- 0x1DF7E4,
- 0xBCD09,
- 0x5B10B,
+ 0xA678E6,
+ 0x10A3F09,
+ 0x32ADC,
+ 0xA8EDE6,
+ 0x302ADA,
+ 0x20DA01,
0x30DE6,
- 0xA8C409,
- 0xA8E9E6,
- 0x953E6,
+ 0x302BE4,
+ 0x8D7E6,
+ 0x8F01B,
0x8DCE6,
0x5B711,
- 0x8F5E6,
+ 0xA80609,
0x1D1ADE6,
- 0x1E020E6,
- 0x112E907,
- 0x59CE6,
+ 0x6E4E6,
+ 0x1DE0E6,
+ 0x5ADDE,
0x1DF1E6,
- 0xAAB4DC,
- 0x595E6,
- 0x8D2DC,
+ 0x11102E6,
+ 0x1E8D5DC,
+ 0x30EE6,
0x7EFE6,
- 0x359DC,
- 0x816E6,
- 0x731DC,
- 0x8D5E6,
- 0x1E016E6,
- 0x6DBE6,
- 0x1DEAE6,
- 0xE4A6B,
+ 0x7F0E6,
+ 0x597E6,
+ 0x1E027E6,
+ 0x1E2ECE6,
+ 0x31CDC,
+ 0x315E8,
+ 0xAAB7E6,
+ 0x616E6,
0x2DF6E6,
- 0x20EEDC,
+ 0x5BF17,
+ 0x10A3901,
0x653E6,
- 0x6E7E6,
- 0x11101E6,
- 0x5BA13,
+ 0x1D166D8,
+ 0x1AC5E6,
0x361EA,
- 0x5AEE4,
- 0x1939DE,
- 0xA92BDC,
- 0x340E6,
- 0x612E6,
- 0x10F84E6,
- 0x73BDC,
+ 0x8F8E6,
+ 0x1AC3DC,
+ 0x103707,
+ 0x1123509,
+ 0x36EE6,
+ 0x1E004E6,
+ 0x1E023E6,
0x368E6,
0x1DD6E6,
- 0x1BF309,
- 0x302EE0,
+ 0x344E6,
+ 0x742DC,
0x485E6,
0x110BA07,
- 0x2DFDE6,
+ 0x1CD8DC,
+ 0x1CD401,
0x8FEE6,
- 0x331DC,
- 0xC3C07,
+ 0x2DF5E6,
0x1E00EE6,
- 0x1A7AE6,
- 0x16B33E6,
- 0x81BE6,
- 0x1E01BE6,
- 0x5A9E6,
- 0x5C118,
- 0x89BDC,
+ 0xECB7A,
+ 0x94D09,
+ 0x1DEBE6,
+ 0x1133C07,
+ 0x1E4EFE6,
+ 0x359DC,
+ 0x1E010E6,
0x304E6,
- 0x20E1E6,
+ 0x5A8E6,
+ 0x1CD6DC,
0xAAB3E6,
- 0x8E7E6,
0x1B70E6,
+ 0x6E8E6,
0xA92DDC,
- 0x1163F09,
- 0x8D4E6,
- 0x1AC6E6,
- 0xFC6DC,
+ 0x8D9E6,
+ 0x16B34E6,
+ 0xF18DC,
+ 0x30AE6,
0x20EDDC,
- 0xC565B,
+ 0x1E4ECE8,
0x1E2EFE6,
0x1D242E6,
- 0x1E132E6,
- 0x1AC7E6,
+ 0x354DC,
+ 0x16AF101,
0x35BE6,
- 0x1CE0E6,
+ 0x1DE3E6,
0x73EDC,
- 0x64C1C,
- 0x1DC5E6,
- 0x339DC,
- 0x11367E6,
- 0x1133B07,
- 0x1AC4DC,
+ 0x1E005E6,
+ 0x115BF09,
+ 0x1DC8E6,
+ 0x484E6,
+ 0x81CE6,
0x1E133E6,
- 0xFE2BDC,
- 0x737DC,
- 0x1E000E6,
+ 0x5B812,
+ 0x340E6,
+ 0x598E6,
+ 0x1BC9E01,
0x1DDCE6,
- 0x2DF5E6,
- 0x35EEA,
+ 0x115C007,
+ 0x8E3DC,
0x11C3F09,
- 0x16AF401,
- 0x116B609,
- 0x2DFBE6,
- 0x8CBE6,
- 0x64B1B,
+ 0x10F85DC,
+ 0x35CE9,
+ 0x1CDBE6,
+ 0x1D1ACE6,
+ 0x1E8D1DC,
0x1AB5DC,
- 0x1DDBE6,
- 0x1DD2E6,
+ 0xDCA09,
+ 0x322CA,
0x10F4BDC,
- 0x314E6,
- 0x1ABCE6,
+ 0x1DC3E6,
+ 0x35ADC,
0x7ECE6,
0x112EA09,
- 0x11102E6,
- 0x1A7BE6,
+ 0xE4B6B,
+ 0x7FDDC,
0x32EDC,
- 0x6DFE6,
- 0x954E6,
- 0x617E6,
- 0x1E2EEE6,
- 0x1E00DE6,
+ 0x65BE6,
+ 0xFE22E6,
+ 0x1DD3E6,
+ 0x89ADC,
+ 0xA8E8E6,
0x8F9DC,
0x36FE6,
- 0x311E6,
- 0x732E6,
+ 0x1B6DE6,
+ 0x8CCE6,
0x1134D09,
- 0x1AC2E6,
+ 0x193AE6,
0x309A08,
- 0x747E6,
+ 0xFE20E6,
0x1DE2E6,
- 0x11370E6,
- 0x110B909,
- 0x362E9,
- 0x1E944E6,
- 0x8F01B,
+ 0x1CEDDC,
+ 0x10EFEDC,
+ 0x1E013E6,
+ 0x8D4E6,
+ 0x34EDC,
0x16B35E6,
- 0x859DC,
+ 0x1037AE6,
0x1107F09,
- 0xA8E2E6,
- 0x1BAB09,
+ 0x8DDE6,
+ 0x1DD1E6,
0x33801,
- 0x8FDE6,
+ 0xA67CE6,
0x1ACEE6,
- 0x11D4509,
- 0x10A3F09,
- 0xA8E3E6,
- 0x8EDDC,
- 0x11369E6,
- 0x11373E6,
- 0xA66FE6,
- 0x20D0E6,
- 0x8EBE6,
- 0x1AB7DC,
- 0x31FDC,
- 0xEB976,
- 0x1145EE6,
- 0x1C3707,
- 0x74AE6,
+ 0x1E08FE6,
+ 0x1183A07,
+ 0x1D244E6,
+ 0x1E018E6,
+ 0xACD09,
+ 0x5A5DC,
+ 0x64E1E,
+ 0x1CE401,
+ 0xF37DC,
+ 0x745E6,
+ 0xC3C07,
+ 0x65222,
+ 0x305E6,
+ 0x33ADC,
+ 0x1DF5E6,
+ 0x1E017E6,
0x1CE801,
- 0x33CDC,
- 0x1CE701,
- 0x1DFADA,
- 0x16B31E6,
+ 0x1193D09,
+ 0x20D1E6,
+ 0x318DC,
0x822E6,
- 0x94D09,
- 0x2DE2E6,
- 0x6EBE6,
- 0x11374E6,
- 0x8F4E6,
- 0x10F82E6,
- 0x20DBE6,
- 0x733E6,
- 0x1DE9E6,
- 0x6D6E6,
- 0x2DF3E6,
- 0x2DE0E6,
+ 0x116B707,
+ 0x310E6,
+ 0x821E6,
+ 0x10378E6,
+ 0x5A4DC,
+ 0xF83E6,
+ 0xAAC1E6,
+ 0x1DD0CA,
+ 0x1D185E6,
+ 0x8D1DC,
+ 0x5AFE6,
+ 0x1DE5E6,
+ 0x309908,
0x365E6,
- 0x119E009,
- 0xABED09,
- 0x8DFE6,
- 0x5A2DC,
- 0x302E6,
+ 0x951E6,
+ 0x369E6,
+ 0x748DC,
+ 0xEC97A,
+ 0x817E6,
0x6DAE6,
- 0x5A8E6,
+ 0x1E4EDE8,
0x1CE501,
- 0xAAB8E6,
- 0x10A0DDC,
- 0x20DA01,
- 0x7FDDC,
- 0x8F11C,
- 0x1A79E6,
- 0x7F0E6,
- 0x36EE6,
- 0x1A77E6,
- 0x343E6,
+ 0x737DC,
+ 0x311E6,
+ 0x6E3DC,
+ 0x1BF309,
+ 0x89BDC,
+ 0x11101E6,
+ 0x5C118,
+ 0x2DE8E6,
+ 0x614E6,
+ 0xFE2EE6,
0x10379E6,
- 0x33601,
- 0x101FDDC,
- 0xA8ECE6,
- 0x6E1E6,
- 0x657E6,
+ 0x1DCFDC,
+ 0x82CE6,
+ 0x32FDC,
+ 0x1B4409,
+ 0x171509,
0x1ACBE6,
- 0x5AFE6,
- 0x2DFCE6,
- 0x1A78E6,
- 0x6181E,
+ 0x1B6CDC,
+ 0xECA7A,
+ 0x1E015E6,
+ 0x20E601,
0xFE24E6,
0x1D243E6,
0x1E021E6,
- 0x1ACDE6,
- 0x1CD2E6,
+ 0xE496B,
+ 0x71124,
+ 0x6DFE6,
0xA9B307,
- 0x356DC,
- 0x1D170D8,
- 0x5A3DC,
- 0xA8E6E6,
- 0x2DFAE6,
- 0xA82C09,
+ 0x65AE6,
+ 0x1A7FDC,
+ 0x8DAE6,
+ 0x8E1E6,
+ 0x11A9909,
0x1D180DC,
- 0x1AC1E6,
- 0x1ABFDC,
+ 0xA8EFE6,
+ 0x1DF4E6,
0x10377E6,
+ 0x362E9,
0x594E6,
- 0x73FE6,
- 0x1CD6DC,
+ 0x33501,
0x7F2DC,
- 0x5A5DC,
+ 0x1D18ADC,
0x1DCBE6,
- 0x1B71E6,
- 0xAABEE6,
+ 0x5A9E6,
+ 0x1CE601,
0x34DDC,
0xEC87A,
- 0x33FE6,
+ 0x6D7E6,
+ 0x108DDC,
0x5C4E6,
0x36AE6,
- 0xB4D09,
- 0x1183A07,
- 0xA69FE6,
- 0x1E8D1DC,
- 0x1DCDEA,
- 0x33DE6,
- 0x2DECE6,
+ 0x326DC,
+ 0x1E00AE6,
+ 0xA8E0E6,
+ 0x5A7DC,
+ 0x1DEAE6,
+ 0x6D6E6,
0xA8E7E6,
+ 0x30BE6,
0x16AF001,
- 0x315E8,
- 0x65121,
- 0x33ADC,
+ 0x1C3707,
+ 0x302EE0,
+ 0xE486B,
0x1DD8E6,
- 0xF19DC,
- 0x349DC,
- 0x1144209,
- 0x1DF0E6,
- 0x5A6DC,
- 0x369E6,
+ 0x1AB8DC,
+ 0x1A18DC,
+ 0x2DF9E6,
+ 0xFB1E1A,
+ 0x363E6,
+ 0x74AE6,
0x1E024E6,
0x599E6,
- 0x8E8E6,
- 0x1133C07,
- 0xE3967,
+ 0x59EE6,
+ 0x7F3E6,
0x1BF209,
- 0x1E004E6,
- 0x73DE6,
+ 0x818E6,
+ 0xA8E9E6,
+ 0x16B36E6,
0x10F50DC,
0x1DD4E6,
- 0x5ABE6,
- 0x1E011E6,
+ 0xAAB2E6,
0xA8E5E6,
- 0x1D18BDC,
- 0x36BE6,
- 0x16AF101,
- 0xFE2CDC,
- 0x1136BE6,
+ 0x744DC,
+ 0x10F82E6,
+ 0x302DDE,
+ 0x331DC,
+ 0x1D188E6,
0x7EDE6,
- 0x8CDE6,
- 0x1AC9E6,
- 0x10D26E6,
- 0x20DCE6,
- 0x616E6,
- 0x1194307,
- 0x1BC9E01,
+ 0x1E006E6,
+ 0xAAB8E6,
+ 0x353DC,
+ 0x1E016E6,
+ 0x1DCADC,
+ 0x73FE6,
+ 0xF35DC,
0xA69EE6,
- 0x1E136E6,
+ 0x323DC,
+ 0x8E5E6,
0x20ECDC,
- 0x59DE6,
- 0x1E948E6,
- 0x36DE6,
+ 0x1E2EEE6,
+ 0x5AEE4,
+ 0x11371E6,
0x1E029E6,
0x734DC,
0x1AB6DC,
- 0x7EBE6,
+ 0x20E7E6,
0x1D17DDC,
- 0x2DE3E6,
+ 0x8FDE6,
0x9CD09,
- 0x1D17EDC,
- 0x1BE607,
- 0x1AB2E6,
+ 0xF82E6,
+ 0x1A7AE6,
+ 0x654E6,
0x1E94A07,
];
@@ -16550,6 +16570,68 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_CHARS: &[char] = &[
'\u{0037}',
'\u{0038}',
'\u{0039}',
+ '\u{0430}',
+ '\u{0431}',
+ '\u{0432}',
+ '\u{0433}',
+ '\u{0434}',
+ '\u{0435}',
+ '\u{0436}',
+ '\u{0437}',
+ '\u{0438}',
+ '\u{043A}',
+ '\u{043B}',
+ '\u{043C}',
+ '\u{043E}',
+ '\u{043F}',
+ '\u{0440}',
+ '\u{0441}',
+ '\u{0442}',
+ '\u{0443}',
+ '\u{0444}',
+ '\u{0445}',
+ '\u{0446}',
+ '\u{0447}',
+ '\u{0448}',
+ '\u{044B}',
+ '\u{044D}',
+ '\u{044E}',
+ '\u{A689}',
+ '\u{04D9}',
+ '\u{0456}',
+ '\u{0458}',
+ '\u{04E9}',
+ '\u{04AF}',
+ '\u{04CF}',
+ '\u{0430}',
+ '\u{0431}',
+ '\u{0432}',
+ '\u{0433}',
+ '\u{0434}',
+ '\u{0435}',
+ '\u{0436}',
+ '\u{0437}',
+ '\u{0438}',
+ '\u{043A}',
+ '\u{043B}',
+ '\u{043E}',
+ '\u{043F}',
+ '\u{0441}',
+ '\u{0443}',
+ '\u{0444}',
+ '\u{0445}',
+ '\u{0446}',
+ '\u{0447}',
+ '\u{0448}',
+ '\u{044A}',
+ '\u{044B}',
+ '\u{0491}',
+ '\u{0456}',
+ '\u{0455}',
+ '\u{045F}',
+ '\u{04AB}',
+ '\u{A651}',
+ '\u{04B1}',
'\u{0627}',
'\u{0628}',
'\u{062C}',
@@ -16940,181 +17022,184 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_CHARS: &[char] = &[
pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
- 0xf,
+ 0x3,
0x0,
0x0,
0x0,
- 0x4,
+ 0x1,
+ 0x16c,
+ 0xe,
+ 0x4ef,
+ 0x2,
0x0,
- 0x8,
- 0x6,
- 0x5,
0x0,
0x0,
- 0x490,
- 0x1db,
- 0x16,
- 0x6,
0x2,
- 0x7a8,
- 0x24b,
0x0,
- 0x42c,
+ 0x1,
+ 0x3,
+ 0x97,
+ 0x165,
0x0,
- 0x68,
- 0x7,
- 0x266,
0x0,
+ 0x185,
0x0,
+ 0x1,
0x0,
+ 0x3f4,
0x0,
0x0,
- 0xf,
- 0x194,
- 0x376,
- 0x6,
+ 0x0,
+ 0x0,
+ 0x4,
+ 0x91,
+ 0x0,
+ 0xdd,
+ 0x1,
+ 0x26c,
+ 0x0,
0xb,
0x0,
- 0xa3,
+ 0xe0,
+ 0xbc,
+ 0x3,
+ 0x213,
+ 0x1,
0x0,
- 0x170,
- 0xfe,
+ 0xc8,
0x3,
- 0x1b2,
- 0x1dc,
+ 0x1c,
+ 0xfc,
0x0,
- 0x93,
- 0x7,
- 0x1f,
- 0x130,
0x0,
+ 0x11,
+ 0x132,
0x0,
- 0xa,
- 0x35,
0x0,
+ 0x10b,
+ 0x90,
+ 0x474,
+ 0xd6,
0x0,
- 0x35,
- 0x12c,
- 0x1b,
- 0x3d,
0x0,
+ 0x3,
+ 0xd,
+ 0x5,
0x0,
- 0x1,
+ 0x6,
+ 0x19,
0x54,
- 0x58,
- 0x0,
- 0x4,
- 0x92,
- 0x10,
- 0x1,
- 0x0,
- 0x38,
- 0x14,
- 0x11a,
- 0xe8,
+ 0x132,
+ 0x4c,
+ 0x17,
+ 0x6,
+ 0x48,
+ 0x3,
0x0,
0x0,
0x6,
- 0x7,
0xc,
+ 0x3,
0x0,
+ 0xb1,
0x1,
- 0x2c,
- 0x156,
- 0x3d,
+ 0x8c,
0x0,
- 0x9,
- 0x1,
- 0x11,
+ 0x1b,
+ 0xc0,
+ 0x7,
+ 0x2,
0x0,
- 0x18,
+ 0x12,
0x0,
0x0,
- 0xe,
- 0x5,
- 0x90,
- 0x9,
+ 0x6,
+ 0x1,
+ 0x1be,
+ 0xc8,
0x0,
- 0x9,
+ 0x7d,
0x0,
- 0x41,
+ 0xa,
0x0,
- 0x38,
- 0x1,
- 0x1a0,
- 0x3,
- 0x1a,
+ 0x0,
+ 0xb4,
+ 0x2,
+ 0x8,
0x5,
- 0x9,
+ 0x144,
+ 0xdb,
+ 0x1,
0x6,
0x0,
0x0,
- 0x53,
- 0x5,
- 0x0,
+ 0xd,
+ 0x14,
0x0,
- 0x1,
+ 0x4f,
+ 0x2,
0x0,
- 0x15,
- 0xc3,
+ 0x3,
+ 0x32,
0x0,
- 0xd,
+ 0x5,
0xe,
- 0x19,
- 0xf,
- 0x20,
+ 0x7c,
+ 0x2c,
+ 0x6,
0x0,
0x0,
- 0x4,
+ 0x7,
0x0,
0x5f,
- 0x4,
- 0x74,
- 0x24,
- 0x0,
+ 0x5,
0xf,
- 0x9b,
+ 0x67,
0x0,
+ 0x1,
+ 0x34,
0x0,
- 0x4c,
- 0x2c,
0x0,
0x0,
+ 0x90,
+ 0x12,
0x0,
- 0x4a,
- 0x1,
0x0,
- 0x45,
+ 0x1e,
+ 0x4c,
+ 0x89,
+ 0xa8,
0x0,
- 0x2,
+ 0x4,
+ 0x1f,
0x0,
0x0,
+ 0x1,
+ 0x99,
+ 0x18,
+ 0xd,
0x3,
- 0x2d,
- 0x3b,
+ 0x7,
+ 0x5,
+ 0x19,
0x2,
0x0,
- 0x5,
- 0x69,
+ 0x4,
+ 0x1,
0x3,
+ 0x90,
0xb,
- 0x0,
- 0x9,
- 0x1,
+ 0x29,
0x55,
- 0x9,
0x0,
- 0x1,
- 0x1c,
- 0x0,
- 0x9,
+ 0x51,
0x0,
0x2,
- 0x2,
- 0x7f,
- 0x42,
+ 0xd0,
+ 0x7a,
+ 0x66,
0x0,
- 0x26,
+ 0x95,
0x7,
0x0,
0x0,
@@ -17122,875 +17207,889 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x1,
0x0,
- 0x72,
- 0x30,
- 0x3c,
- 0xd9,
- 0x36,
+ 0x8d,
+ 0xf,
+ 0x21,
+ 0x56,
+ 0xa,
0x1b,
0x0,
0x0,
- 0x4,
- 0x1,
- 0x0,
- 0x3d,
- 0x0,
- 0x21,
- 0x1,
- 0x0,
- 0x2f,
+ 0x8,
+ 0x7,
+ 0x7c,
+ 0x5,
0x0,
- 0x33,
+ 0x62,
+ 0x2,
+ 0x13,
+ 0x6,
0x0,
- 0xe,
- 0x14,
- 0x19,
+ 0x4f,
0x0,
- 0x11,
- 0x3,
- 0x3,
- 0x10,
0x0,
- 0x16,
+ 0x32,
+ 0x2f,
+ 0x4,
+ 0xd,
+ 0xa0,
+ 0x4,
+ 0x8,
+ 0x24,
+ 0x1f,
0x0,
- 0x5,
0x0,
- 0x46,
- 0x6,
+ 0x82,
+ 0x45,
0x0,
+ 0x61,
0x0,
+ 0x1d,
0x1,
- 0x4,
+ 0x0,
0x1,
0x0,
+ 0x7,
+ 0x17,
+ 0xb,
0x0,
- 0x6,
- 0x13,
- 0x33,
0x0,
0x0,
- 0x16,
- 0x5c,
- 0x7,
+ 0xb,
+ 0x8,
+ 0x8,
0x0,
0x0,
- 0x2a,
+ 0x3d,
0x0,
- 0x13,
+ 0x96,
0x0,
0x0,
0x0,
- 0xb,
+ 0x8,
0x0,
0x0,
0x0,
- 0x3,
+ 0x4,
0x0,
0x3,
- 0x4c,
- 0x0,
+ 0x7,
+ 0x2c,
0x0,
0x0,
- 0x3,
+ 0x14,
+ 0x24,
0x2,
- 0x6,
0x2,
0x0,
- 0x8,
- 0x0,
- 0x55,
- 0x1,
- 0x1c,
- 0x0,
+ 0x2,
0x0,
0x12,
- 0xb,
- 0x5,
- 0xc,
- 0x3,
- 0x0,
- 0xe,
+ 0x1,
0x0,
- 0xa,
0x2,
0x0,
- 0x30,
- 0xe,
+ 0x25,
0xa,
- 0x4,
+ 0x1,
+ 0x66,
+ 0xb,
+ 0x8,
0x0,
+ 0xc,
+ 0x10,
0x2,
- 0x0,
+ 0x3,
+ 0x8,
+ 0x4,
0x6,
+ 0x1,
+ 0x4,
+ 0xe3,
+ 0x23,
+ 0x20,
+ 0x7,
0x0,
- 0x9,
- 0x47,
- 0xb,
- 0x71,
- 0x2,
+ 0xf,
+ 0x1e,
+ 0x23,
+ 0x3d,
+ 0x4,
0x0,
- 0x3,
+ 0x1,
0x0,
- 0xf,
- 0xd,
+ 0x3,
+ 0x25,
0x0,
0x1,
- 0x3b,
- 0x7,
+ 0x31,
+ 0x9d,
0x0,
0x0,
- 0x8,
+ 0x4,
0x1,
0x0,
0x0,
- 0x12,
+ 0x8,
0x0,
0x0,
- 0x13,
+ 0x26,
0x0,
0x0,
0x2,
0x0,
- 0x3,
+ 0x2,
0x0,
0x3,
- 0x12,
0x0,
0x1b,
0x0,
- 0x6,
- 0xc,
- 0x33,
- 0x5,
- 0x6,
0x2,
- 0x1,
0x0,
0x1,
+ 0xa,
0x3,
- 0x0,
- 0x7,
- 0x4,
- 0x4,
- 0x0,
- 0xb,
- 0x4,
- 0x0,
+ 0x1,
+ 0x2,
+ 0xc,
+ 0xc,
+ 0x1,
0x1,
0x0,
- 0x5,
+ 0x11,
+ 0x4,
+ 0x3d,
+ 0x2,
+ 0x1b,
+ 0x2,
0x0,
0xc,
- 0x2,
- 0x3,
- 0x69,
+ 0x6,
+ 0x6,
0x0,
- 0x7,
- 0x50,
- 0x1,
0x0,
+ 0x3,
0x0,
- 0xb,
+ 0x9,
+ 0x2c,
0x0,
+ 0x9,
+ 0x37,
+ 0x2d,
0x0,
+ 0x12,
+ 0x23,
0x0,
- 0x1b,
- 0x17,
- 0x21,
- 0x3,
- 0x4,
0x0,
- 0x12,
+ 0x1c,
0x0,
- 0x4,
- 0x2f,
- 0x1d,
- 0x4,
- 0x38,
0x26,
+ 0x10,
+ 0x15,
0x2,
0x0,
+ 0xb,
0x0,
- 0x28,
- 0x2,
- 0x2e,
- 0x1,
+ 0x4,
+ 0x14,
+ 0x5,
+ 0x13,
+ 0x7,
0x1c,
+ 0x3,
+ 0x36,
0x0,
+ 0x8,
+ 0x1,
+ 0x19,
+ 0x2,
0x0,
+ 0x1,
0x0,
- 0x3,
- 0x2,
0x0,
+ 0x4,
+ 0x1,
+ 0x8,
0x2,
+ 0xa,
0x6,
- 0x0,
- 0x38,
+ 0x13,
0x0,
0x0,
0x0,
- 0x7,
- 0x2,
+ 0x2f,
+ 0x1,
0x0,
- 0xf,
- 0x9,
- 0x4,
+ 0x16,
0x5,
- 0xb,
- 0x4,
+ 0xc,
+ 0xc,
+ 0x1,
+ 0x10,
+ 0x3,
+ 0xe,
+ 0x0,
0x1,
+ 0xd,
+ 0x28,
0x0,
- 0x27,
- 0x9,
- 0x15,
- 0x34,
0x0,
0x1,
- 0x9,
0x0,
- 0x11,
- 0x83,
+ 0x0,
+ 0x4,
+ 0x10,
0x21,
0x0,
- 0x5,
- 0xb,
+ 0x1,
0x3,
- 0x9,
0x0,
- 0x1,
+ 0x23,
0x0,
+ 0x1,
0x0,
0x0,
- 0x2d,
- 0x7,
0x0,
+ 0xd,
+ 0x1,
0x0,
- 0x7,
- 0x1c,
- 0x16,
0x0,
+ 0x6,
+ 0x6b,
0x0,
- 0x17,
- 0xb,
- 0x2b,
- 0x7,
+ 0x14,
0x0,
0x0,
0x6,
+ 0x12,
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x2a,
+ 0x1,
+ 0xb,
0x1,
- 0x7,
0x6,
- 0x3,
+ 0x9,
0x8,
- 0xb,
0x1,
- 0x5,
0x0,
- 0x38,
- 0x1,
- 0xc,
+ 0x2b,
0x0,
- 0x2,
+ 0x8,
+ 0x7,
0x0,
+ 0xf,
+ 0x16,
0x0,
- 0x11,
0x0,
+ 0x44,
0x0,
- 0x2b,
+ 0x1,
0x0,
0x0,
+ 0xc,
+ 0x19,
+ 0x25,
0x2,
- 0x10,
- 0x8,
- 0x1,
- 0x14,
- 0x4,
+ 0x1f,
+ 0xf,
+ 0xc,
0x1,
- 0xb,
- 0x0,
- 0x6,
- 0x11,
- 0x0,
- 0x7,
- 0x10,
- 0x3,
+ 0x1f,
+ 0xa,
0x0,
- 0x4,
- 0x32,
+ 0x38,
+ 0xe,
+ 0xf,
+ 0xc,
+ 0x25,
0x0,
0x6,
+ 0xe,
0x0,
- 0x1,
+ 0x8,
+ 0x0,
+ 0x2,
0x0,
0x0,
0x1,
- 0x1f,
+ 0x9,
0x1,
+ 0x16,
0x0,
0x0,
0x0,
- 0x0,
- 0xb,
- 0x7,
- 0xa,
- 0x4,
- 0x0,
+ 0x3,
0x15,
- 0xa,
- 0x0,
+ 0x62,
0x1,
0x0,
0x0,
- 0x2f,
- 0x1,
- 0x1,
- 0x6,
- 0xe,
- 0x1d,
- 0x7,
+ 0x2,
0x0,
- 0x4,
- 0xa,
- 0xa,
0x0,
+ 0x3d,
0x0,
+ 0x3,
+ 0x1,
+ 0x1,
+ 0x1,
0x0,
+ 0x1,
0x0,
0x29,
+ 0x4,
+ 0x2c,
0x1,
- 0xe,
0x0,
0x0,
- 0x18,
- 0x3,
- 0x3,
0x0,
- 0x3,
- 0x3,
0x0,
- 0x2,
+ 0x22,
0x0,
- 0xe,
+ 0x14,
+ 0x28,
0x0,
- 0x10,
+ 0x7,
+ 0x4,
+ 0x3,
+ 0x6,
0x0,
- 0x8,
- 0xc,
- 0x1b,
+ 0x1,
+ 0xd,
+ 0x2a,
0x0,
0x0,
+ 0x44,
0x0,
+ 0x8,
0x0,
+ 0x2,
0x1,
- 0x1,
- 0xd,
- 0x10,
+ 0xb,
0x0,
- 0xc,
- 0x6,
0x0,
- 0x1a,
- 0x1,
- 0x1d,
0x0,
- 0x2,
0x0,
- 0x7,
- 0x3b,
0x4,
+ 0x3,
+ 0x1c,
+ 0x5,
0x0,
+ 0x6,
0x2,
- 0xe,
- 0x10,
- 0x4,
- 0x1c,
- 0x44,
0x0,
- 0x3e,
+ 0x11,
+ 0x6,
+ 0x7,
0x0,
+ 0x2,
+ 0x28,
+ 0x7,
+ 0x1d,
+ 0xb,
0x5,
+ 0x2e,
+ 0x11,
0x0,
0x1,
- 0x17,
- 0x1,
- 0x3,
- 0x0,
+ 0xc,
0x0,
0x7,
+ 0x2f,
0x0,
- 0x3,
- 0x29,
- 0x1e,
- 0x6,
0x0,
- 0x2,
0x5,
- 0x2,
- 0x12,
+ 0xa,
0x0,
- 0xb,
+ 0x8,
+ 0x6,
0x0,
0x0,
- 0x15,
+ 0x7,
0x1,
+ 0x8,
+ 0x20,
+ 0xc,
0x0,
- 0x3,
- 0x28,
+ 0x1a,
+ 0x5,
+ 0x0,
+ 0x26,
+ 0x26,
+ 0x2,
+ 0xb,
+ 0x8,
0x0,
0x4,
+ 0x5,
+ 0x2,
+ 0x0,
+ 0x5,
+ 0x12,
+ 0x0,
+ 0x5,
0x0,
- 0xb,
0x1,
- 0x16,
+ 0x6,
+ 0x9,
+ 0x1,
0x3,
+ 0x15,
0x3,
0x0,
- 0x1d,
- 0x0,
0x0,
- 0x4,
+ 0x2,
0x0,
- 0x15,
+ 0x3,
0x0,
- 0x7,
+ 0x16,
0x0,
- 0x7,
- 0xa,
+ 0x10,
+ 0x3,
0x0,
- 0xb,
+ 0x1b,
0x2,
0x0,
- 0x28,
+ 0x9,
0x0,
- 0x1,
+ 0x9,
0x0,
- 0x13,
+ 0x9,
0x0,
0x0,
0x1,
- 0x5,
+ 0x1,
+ 0xc,
+ 0x26,
+ 0x1,
0x0,
- 0x13,
- 0x6,
0x0,
- 0x2,
+ 0x4,
0x0,
- 0x3,
+ 0xc,
+ 0x1e,
0x0,
- 0x1d,
- 0x24,
0x1,
- 0x26,
- 0x2,
- 0x19,
+ 0x36,
+ 0x6,
+ 0x3,
0x0,
- 0x4,
0x0,
- 0xf,
+ 0x1,
+ 0x0,
+ 0x6,
0x0,
0x0,
0x0,
- 0x1,
0x8,
+ 0xc,
0x0,
0x0,
0x1,
0x0,
0x0,
- 0x5,
- 0xb,
+ 0x4,
0x2,
- 0x0,
+ 0x7,
0x1,
- 0x4,
- 0x21,
- 0x5,
- 0x0,
- 0x0,
- 0x33,
- 0x3,
- 0x3,
- 0x0,
+ 0x2,
+ 0x7,
+ 0xd,
0x2,
0x0,
0x0,
- 0x1d,
0x0,
0x2,
- 0x0,
- 0x0,
- 0x1a,
- 0x1b,
0x5,
- 0x1,
0x0,
- 0x9,
- 0x2,
- 0x9,
- 0x1,
+ 0x8,
+ 0x5,
0x0,
- 0xc,
- 0x1,
0x0,
- 0x4,
+ 0x3,
+ 0x6,
0x0,
0x0,
+ 0x8,
0x1,
+ 0x5,
0x1,
0x3,
- 0x8,
+ 0x3,
+ 0x10,
+ 0xb,
+ 0x7,
0x0,
+ 0xf,
+ 0x11,
0x0,
- 0x8,
+ 0x18,
0x0,
- 0x2,
0x0,
- 0xe,
+ 0xf,
0x2,
- 0xb,
- 0xe,
- 0x3,
- 0x0,
- 0xa,
- 0x0,
- 0x4,
+ 0x7,
0x1,
- 0x3,
0x0,
0x0,
- 0x4,
- 0x2,
0x0,
0xc,
- 0x3,
- 0x11,
+ 0x18,
0x0,
- 0x1,
+ 0x17,
0x0,
- 0x7,
0x1,
- 0x3,
- 0x6,
- 0x21,
0x0,
- 0x6,
+ 0x26,
+ 0x3,
0x0,
- 0x1,
- 0xb,
+ 0x1b,
0x0,
+ 0x8,
+ 0x3,
+ 0x3,
0x0,
0x0,
+ 0x2,
+ 0x6,
0x0,
+ 0xb,
+ 0x1b,
+ 0x9,
0x0,
0x3,
0x0,
0x0,
- 0xe,
- 0x6,
0x1,
0x1,
- 0x3c,
+ 0x1,
0x5,
0x0,
- 0x0,
- 0x2,
0x6,
- 0x7,
+ 0x0,
+ 0x4,
+ 0x3,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x9,
+ 0x9,
+ 0x0,
0x2,
0x7,
0xe,
- 0x4,
- 0x4,
- 0x0,
- 0x1,
+ 0x23,
+ 0x3,
0x1,
- 0x5,
0x0,
0x0,
- 0x9,
+ 0xf,
+ 0x0,
+ 0x8,
+ 0x22,
+ 0xe,
+ 0x10,
+ 0x7,
+ 0x3,
+ 0xc,
+ 0x19,
0x1,
+ 0xa,
0x2,
- 0x17,
0x0,
- 0x4,
- 0xa,
- 0x1f,
+ 0x3,
+ 0x18,
0x1,
+ 0x16,
+ 0xa,
+ 0x0,
+ 0x2,
+ 0x8,
0x0,
+ 0x23,
0x0,
- 0x13,
- 0x5,
0x0,
- 0x3,
- 0x9,
- 0xf,
+ 0x6,
+ 0x2,
0x0,
- 0x3,
+ 0x4,
+ 0xd,
0x1b,
0x0,
+ 0x4,
+ 0x38,
0x0,
- 0x7,
- 0x3,
0x0,
+ 0x11,
+ 0xe,
0x0,
0x0,
- 0xf,
- 0xa,
0x0,
- 0x8,
- 0xa,
0x9,
- 0x1,
- 0x1f,
+ 0x0,
+ 0x21,
+ 0x13,
0x2,
- 0xc,
+ 0x18,
+ 0x4,
+ 0x1,
+ 0x10,
0x0,
- 0x9,
- 0x3,
+ 0x2,
0x0,
- 0x8,
+ 0x6,
+ 0x14,
+ 0xa,
0x0,
0x0,
0x4,
- 0x2,
+ 0xe,
+ 0x0,
0x0,
- 0xb,
0x5,
- 0xa,
- 0x15,
- 0x12,
- 0xc,
+ 0x4,
0x0,
- 0x3,
+ 0x20,
+ 0x1d,
+ 0x1,
+ 0x0,
+ 0x9,
0x0,
0x1,
0x1,
- 0x6,
+ 0x4,
0x2,
0x0,
+ 0x1,
0x0,
- 0xc,
0x0,
+ 0x24,
+ 0x1,
0x0,
- 0x2,
- 0x5,
- 0xa,
- 0x3,
+ 0x9,
+ 0x8,
0x0,
- 0xa,
0x1,
+ 0xa,
0x1,
0x0,
+ 0x4,
+ 0x0,
+ 0x13,
+ 0x5,
+ 0x0,
0x1,
0x0,
- 0x11,
- 0x1f,
+ 0x1,
0x0,
- 0xa,
0x0,
+ 0x2,
0x4,
0x0,
0x0,
+ 0x5,
0x1,
+ 0x9,
0x2,
+ 0x5,
0x0,
- 0x12,
- 0x1,
- 0x4,
0x0,
- 0xd,
- 0x13,
0x0,
0x0,
0x0,
+ 0xa,
0x0,
0x0,
- 0xb,
+ 0x10,
+ 0x1,
+ 0x4,
0x0,
0x0,
+ 0x1,
0x4,
0x0,
+ 0x1,
0x2,
+ 0x4,
+ 0x3,
0x0,
+ 0x4,
+ 0x14,
0x7,
- 0x3,
- 0x3,
- 0x3,
- 0x6,
+ 0xa,
+ 0x2,
0x6,
- 0x1,
- 0x0,
- 0x0,
- 0x1,
- 0xc,
0x0,
0x2,
- 0x0,
- 0xb,
- 0x4,
0x1,
- 0x5,
- 0x0,
0x8,
+ 0x7,
0x0,
0x0,
+ 0x0,
+ 0x14,
0x1,
- 0x1,
- 0xc,
+ 0x10,
0x0,
0x0,
0x5,
- 0x7,
- 0x2,
- 0x1c,
- 0x4,
+ 0x1,
+ 0x6,
+ 0x5,
+ 0x3,
0x0,
- 0x16,
+ 0x9,
0x2,
0x4,
- 0x9,
+ 0x2,
0x0,
0x0,
- 0x1,
- 0xf,
+ 0xc,
+ 0x19,
0x0,
0x0,
0x0,
- 0x11,
+ 0x1,
0x0,
0x0,
- 0x3,
- 0x4,
- 0x10,
- 0x0,
- 0x2,
- 0xa,
+ 0xf,
+ 0x8,
+ 0xd,
0x0,
+ 0x3,
0x1,
0x0,
- 0x2,
+ 0x9,
+ 0x14,
+ 0x17,
0x0,
0x0,
0x0,
- 0xb,
- 0x7,
- 0xb,
0x0,
0x3,
+ 0x1,
0x0,
+ 0x5,
+ 0x15,
+ 0x1,
+ 0x19,
0x1,
- 0x1a,
- 0x2,
0x1,
+ 0x1,
+ 0x1,
+ 0x3,
+ 0x0,
0x6,
- 0x4,
+ 0x3,
0x0,
- 0xd,
- 0x1,
+ 0x11,
+ 0x5,
0x0,
+ 0x4,
+ 0xc,
+ 0x3,
0x0,
- 0x2,
- 0x2,
- 0x6,
0x7,
- 0x1,
- 0x9,
- 0x16,
0x0,
0x0,
0x3,
- 0x1,
+ 0x4,
+ 0x3,
+ 0xb,
+ 0x0,
+ 0x0,
0x6,
+ 0x8,
0x3,
+ 0x1,
0x0,
0x0,
- 0xe,
0x1,
+ 0xd,
0x3,
- 0x2,
- 0x0,
- 0xa,
- 0x4,
- 0x19,
- 0x8,
0x0,
- 0x2,
+ 0x7,
0x0,
0x1,
0x0,
0x0,
0x0,
- 0x4,
+ 0x9,
0x1,
0x0,
0x2,
0x1,
- 0xb,
- 0x1,
+ 0x9,
+ 0xa,
0x8,
0x1,
- 0x2,
- 0x2,
+ 0x7,
+ 0x3,
0x0,
- 0xb,
+ 0x3,
0x0,
0x0,
- 0x2,
- 0x27,
- 0x1,
- 0x3,
+ 0x4,
0x0,
+ 0x4,
+ 0x1,
+ 0xb,
0x0,
- 0x7,
- 0x8,
+ 0x13,
0x6,
+ 0x7,
0x0,
0x0,
- 0x1,
- 0x17,
+ 0x8,
+ 0x7,
+ 0x7,
0x0,
0x3,
0x0,
- 0x1,
0x2,
+ 0x3,
0x0,
- 0x15,
- 0x9,
- 0xe,
- 0x9,
- 0xe,
- 0xc,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x1b,
+ 0x3,
+ 0x2,
0x9,
0x2,
0x1,
- 0x9,
+ 0x2,
0x0,
- 0x7,
+ 0x4,
0x1,
0x0,
- 0x1,
+ 0x6,
0x0,
0x0,
0x1,
+ 0x5,
0x0,
- 0x0,
- 0x2,
- 0x0,
- 0x1a,
+ 0xf,
0x1,
+ 0x6,
0x8,
+ 0x4,
0x0,
0x0,
- 0x8,
- 0xa,
- 0x1,
+ 0x3,
+ 0xb,
0x2,
+ 0x5,
+ 0x1,
0x2,
- 0x1d,
- 0x3,
- 0x0,
- 0x11,
+ 0x13,
+ 0x13,
0x0,
+ 0x9,
0x2,
0x0,
0x0,
@@ -18000,449 +18099,457 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x8,
- 0x8,
- 0x0,
- 0x0,
- 0x9,
- 0x2,
0x4,
- 0xd,
+ 0x2,
+ 0x21,
0x0,
- 0x7,
+ 0x6,
+ 0x3,
+ 0x1,
+ 0x1,
0x5,
- 0x4,
- 0x8,
+ 0x3,
0x0,
- 0x6,
+ 0x10,
+ 0x22,
+ 0xb,
+ 0x0,
+ 0x8,
0x0,
0x0,
0x3,
+ 0x4,
0x1,
- 0x1,
- 0x0,
+ 0x1a,
0x2,
0x0,
0x0,
0x0,
+ 0x2,
0x1,
- 0x1f,
0x0,
- 0x3,
- 0x5,
0x0,
+ 0x2,
0x0,
- 0x8,
+ 0x0,
+ 0x12,
0x1,
0x0,
- 0x15,
+ 0x2,
0x0,
0x0,
- 0x4,
- 0xf,
- 0x3,
+ 0x1,
+ 0x0,
0x2,
+ 0x21,
0x0,
0x2,
+ 0xd,
0x1,
- 0x0,
0x3,
+ 0x5,
0x1,
- 0x2,
- 0xa,
0xc,
+ 0x10,
0x0,
- 0x14,
+ 0x24,
0x0,
0x0,
- 0x4,
- 0x7,
+ 0x6,
+ 0x6,
+ 0x1b,
0x1,
- 0x1f,
+ 0xd,
0x0,
- 0x3,
+ 0x1,
0x0,
+ 0x1,
0x0,
- 0x4,
0x0,
+ 0x7,
0x2,
- 0x1,
0x0,
- 0x2f,
- 0xa,
+ 0x5,
+ 0x24,
0x6,
0x1,
- 0xb,
+ 0xe,
0x0,
- 0x8,
- 0x7,
+ 0xb,
+ 0xe,
0x7,
0x0,
0x0,
0x0,
- 0x13,
- 0x0,
- 0x0,
0x3,
- 0x2,
- 0x6,
- 0x11,
- 0x6,
0x0,
0x0,
- 0xe,
- 0x2,
0x2,
+ 0x18,
+ 0x3,
+ 0x3,
0x1,
0x0,
- 0xc,
- 0x2,
0x0,
+ 0x4,
+ 0x4,
0x0,
- 0xa,
- 0xa,
- 0x2,
+ 0x1,
0x0,
- 0x13,
+ 0x14,
+ 0x6,
+ 0xb,
0x0,
- 0x5,
+ 0x2,
+ 0x1,
+ 0x2,
+ 0x6,
+ 0x6,
0x0,
0x6,
- 0x3,
- 0x1,
+ 0x0,
0x0,
0x1,
0x2,
- 0x1,
+ 0x2,
0x1,
0x2,
- 0x5,
- 0x0,
0x0,
0x1,
- 0x14,
+ 0x8,
0x1,
- 0x3,
- 0x5,
+ 0xc,
+ 0x0,
0x7,
- 0x1,
- 0x15,
0x2,
- 0x0,
+ 0x3,
0x1,
+ 0x0,
+ 0x6,
0x1,
+ 0x7,
+ 0x11,
+ 0x3,
+ 0x0,
0x1,
- 0xb,
+ 0xa,
+ 0x2,
+ 0x2,
+ 0x8,
+ 0x6,
0x8,
0x0,
+ 0x0,
0x4,
+ 0x8,
+ 0x1,
+ 0x7,
+ 0x2,
+ 0x2,
+ 0x6,
+ 0x0,
+ 0x6,
0x0,
0x0,
+ 0x7,
0x1,
- 0x6,
+ 0xe,
0x2,
- 0x3,
0x2,
- 0x1,
- 0x1,
+ 0x32,
+ 0x7,
+ 0xb,
+ 0x4,
+ 0x4,
0x0,
- 0x9,
+ 0x6,
0x0,
- 0x26,
- 0x5,
- 0x1,
- 0x3,
- 0xa,
- 0x12,
0x8,
- 0x13,
- 0x8,
- 0x1,
- 0x14,
- 0x5,
- 0x3,
- 0x0,
- 0x9,
0x0,
0x0,
0x0,
+ 0x9,
0x2,
- 0x3,
- 0xd,
+ 0x1b,
+ 0x0,
0x0,
0x0,
- 0x21,
0x1,
+ 0xc,
0x2,
- 0x11,
- 0xe,
0x1,
+ 0x2,
+ 0xf,
0x0,
0x0,
0x0,
- 0xd,
- 0x4,
- 0x2,
- 0xb,
+ 0x3,
+ 0xc,
+ 0x5,
0x0,
0x0,
0x0,
- 0x5,
- 0x8,
+ 0xb,
+ 0x0,
+ 0x2,
0x1,
+ 0x3,
0x0,
- 0xc,
0x1,
0x6,
- 0xc,
+ 0xa,
0x1,
0x0,
- 0x5,
+ 0x8,
0x0,
- 0x1,
+ 0x4,
0x1,
0x0,
- 0x27,
+ 0x1,
0x0,
- 0xa,
- 0x10,
- 0x6,
- 0x4,
+ 0xe,
+ 0x2,
0x1,
- 0xd,
0x1,
- 0x3,
0x1,
+ 0x7,
0x1,
+ 0x3,
0x1,
0x2,
- 0x2,
- 0x2,
- 0x0,
- 0xf,
- 0x5,
0x1,
- 0x0,
- 0x0,
+ 0x3,
0x2,
- 0x4,
0x0,
- 0x3,
0x11,
+ 0x3,
+ 0x2,
+ 0x3,
0x0,
0x0,
+ 0x3,
+ 0x4,
+ 0x0,
0x0,
0x1,
+ 0x20,
0x0,
0x0,
0x1,
0x0,
0x0,
0x7,
+ 0x2,
+ 0x0,
+ 0x12,
+ 0x0,
0xa,
+ 0x1,
+ 0x2,
0x0,
- 0x3,
- 0x5,
0x0,
0x0,
0x0,
- 0x3,
- 0x8,
+ 0x2,
0x0,
- 0x5,
0x0,
- 0x8,
- 0x7,
- 0x5,
- 0x5,
+ 0x4,
+ 0xf,
0x0,
+ 0x7,
0x4,
- 0x1,
- 0xc,
- 0x1,
- 0x18,
0x2,
+ 0x12,
+ 0x0,
0x1,
- 0x8,
0x4,
0x2,
+ 0x3,
+ 0x0,
+ 0x1,
+ 0x17,
+ 0x1,
0x1,
+ 0x5,
0x0,
- 0x13,
+ 0x1,
0x0,
0x0,
- 0xc,
+ 0xb,
0x0,
- 0x3,
+ 0x1,
0x0,
0x0,
0x0,
- 0x7,
+ 0x4,
0x0,
0x0,
- 0xb,
- 0x7,
- 0x15,
+ 0x9,
0x0,
+ 0x4,
0x0,
- 0x6,
- 0x1b,
0x0,
- 0xb,
+ 0x4,
+ 0xa,
+ 0x0,
+ 0x0,
+ 0x6,
0x7,
- 0x12,
- 0x1,
- 0x9,
+ 0x2,
+ 0x3,
0x0,
0x0,
0x0,
- 0x2,
- 0x2,
+ 0x0,
+ 0x6,
0xb,
0x0,
0x0,
0x0,
0x0,
- 0x2,
- 0x5,
- 0x8,
- 0x7,
- 0x5,
- 0x8,
0x0,
0x1,
0x0,
- 0x0,
- 0x0,
+ 0xc,
+ 0x8,
0x1,
- 0x3,
- 0x9,
0xd,
+ 0xb,
+ 0x2,
+ 0x0,
+ 0x0,
0x0,
0x1,
- 0x4,
+ 0x5,
+ 0x1,
+ 0x0,
+ 0x0,
0x2,
+ 0x3,
+ 0x3,
0x0,
0x0,
- 0x9,
+ 0x8,
0x0,
- 0x2,
- 0x12,
- 0x5,
0x1,
+ 0x9,
+ 0x11,
0x1,
+ 0xc,
0x0,
0x0,
0x0,
- 0x3,
+ 0x4,
0x0,
0x0,
0x0,
- 0x4,
- 0x8,
- 0x5,
- 0x5,
- 0x6,
+ 0x1,
+ 0x1,
+ 0x17,
+ 0x1,
0x0,
- 0x3,
- 0x2,
+ 0x5,
+ 0xb,
0x1,
+ 0x4,
0x1,
- 0x3,
0x6,
- 0x15,
- 0x2,
- 0x4,
- 0x5,
+ 0x1d,
+ 0x0,
0x1,
+ 0x4,
0x2,
- 0x0,
+ 0x9,
+ 0x2,
+ 0xf,
+ 0x14,
0x2,
0x1,
- 0x4,
- 0x3,
- 0x4,
- 0xc,
+ 0x7,
0x1,
+ 0x1,
+ 0x7,
+ 0x2,
0x0,
0x0,
0x0,
0x0,
- 0x0,
+ 0x4,
+ 0x13,
0x2,
- 0x7,
0x1,
- 0x2,
- 0x6,
+ 0x1,
+ 0x3,
0x0,
0x2,
- 0x0,
0x2,
0x0,
- 0x1,
0x3,
- 0x4,
+ 0x1,
+ 0x0,
+ 0x5,
0x1,
0x1,
0x0,
- 0x12,
- 0x2,
0x1,
+ 0x1,
+ 0x2,
0x0,
0x0,
- 0xa,
+ 0x3,
0x0,
- 0x8,
- 0x8,
+ 0xa,
+ 0x6,
0x1,
- 0xc,
- 0xe,
+ 0x6,
+ 0x7,
0x1,
0x0,
- 0x5,
+ 0x0,
+ 0x2,
+ 0x7,
0x4,
- 0x1,
- 0x17,
0x0,
0x0,
- 0x11,
- 0x2,
+ 0xc,
0x2,
0x0,
+ 0xa,
0x1,
0x0,
0x0,
- 0x2,
- 0x2,
- 0x3,
- 0x2,
+ 0xa,
+ 0x0,
+ 0x6,
0x3,
- 0x4,
0x1,
+ 0x0,
+ 0xd,
+ 0x3,
0x5,
0x0,
- 0x9,
- 0x6,
0x2,
+ 0xa,
0x0,
+ 0xb,
0x1,
- 0x5,
- 0xa,
+ 0x6,
+ 0x22,
0x0,
- 0x8,
+ 0x5,
+ 0x1,
0x0,
0x2,
- 0x4,
0x0,
0x0,
+ 0x12,
+ 0x4,
+ 0x2,
0x0,
- 0xf,
- 0x3,
- 0x8,
0x0,
- 0x2,
+ 0xc,
0x0,
- 0x7,
+ 0x1,
0x0,
0x0,
0x0,
@@ -18451,455 +18558,463 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x5,
- 0x3,
- 0x3,
- 0x3,
- 0x3,
- 0x3,
0x1,
+ 0x4,
+ 0x2,
+ 0x1,
+ 0x8,
+ 0x4,
+ 0x6,
0x1,
0x0,
- 0x20,
- 0x5,
+ 0x3,
+ 0xa,
0x0,
- 0x2,
+ 0x5,
0x1,
0x0,
0x0,
- 0x9,
- 0x1,
+ 0x3,
0x0,
+ 0x6,
0x0,
- 0x8,
- 0x2,
- 0xf,
- 0x1,
+ 0x0,
+ 0x3,
+ 0x0,
+ 0x4,
0x0,
0x0,
0x0,
+ 0xe,
+ 0x1,
0x1,
- 0x4,
- 0x7,
0x0,
0x6,
- 0x4,
0x0,
+ 0x8,
0x0,
- 0x3,
- 0x5,
+ 0x0,
+ 0xa,
0x1,
- 0x7,
0x0,
+ 0x4,
+ 0x0,
+ 0x4,
0x1,
0x0,
- 0x11,
0x0,
0x0,
0x0,
0x0,
+ 0x1,
+ 0x0,
+ 0x17,
0x4,
0x0,
- 0x1,
0xb,
- 0x0,
- 0x2,
- 0x2,
0x3,
- 0x1,
+ 0x5,
+ 0x4,
0x0,
- 0x2,
+ 0x3,
+ 0xf,
+ 0x6,
0x1,
- 0xb,
0x1,
- 0x2,
0x7,
- 0x6,
- 0x6,
- 0x1,
0x4,
- 0x0,
+ 0x3,
0x1,
+ 0x3,
0x4,
- 0x0,
- 0x0,
- 0x5,
0x1,
- 0x0,
- 0x0,
- 0x1,
- 0x8,
0x1,
0x0,
0x0,
+ 0x0,
+ 0x2,
0x1,
0x0,
+ 0x5,
0x0,
0x2,
0x0,
+ 0x0,
+ 0x3,
0x1,
- 0x4,
- 0x6,
0x0,
- 0xf,
+ 0x5,
0x0,
+ 0xd,
+ 0x6,
+ 0x1,
0x0,
0x0,
- 0xd,
- 0x5,
+ 0x7,
+ 0x0,
0x0,
+ 0xa,
+ 0x3,
+ 0x2,
+ 0xa,
0x1,
+ 0x7,
+ 0x1,
+ 0x0,
0x1,
- 0x2,
0x0,
0x5,
- 0x4,
- 0x9,
0x3,
0x0,
0x5,
- 0x4,
- 0xd,
+ 0x2,
+ 0x1,
0x0,
- 0x5,
+ 0x2,
0x0,
0x1,
- 0x2,
- 0x8,
- 0x7,
- 0x11,
- 0x6,
- 0x2,
0x1,
- 0x0,
+ 0x4,
+ 0x9,
+ 0x5,
+ 0x1,
0x1,
0x6,
+ 0x0,
+ 0x9,
+ 0x1,
+ 0xa,
0x2,
0x2,
- 0x8,
0x0,
0x0,
- 0x3,
- 0x1,
- 0x4,
0x2,
- 0xf,
- 0xa,
- 0x8,
- 0xc,
- 0x0,
- 0x6,
0x2,
+ 0x7,
+ 0x9,
+ 0x0,
+ 0x10,
+ 0x1c,
+ 0x4,
+ 0x0,
+ 0x0,
0x3,
+ 0x3,
+ 0xd,
0x1,
0x3,
- 0x2,
0x0,
- 0xa,
0x0,
+ 0xc,
+ 0x7,
0x1,
- 0x6,
- 0x2,
- 0x3,
- 0x4,
- 0x1,
- 0x0,
- 0x3,
- 0x2,
0x3,
+ 0x7,
0x8,
+ 0x3,
+ 0x6,
0x0,
0x3,
- 0x2,
- 0x2,
- 0x4,
+ 0x1,
+ 0x1,
0x0,
+ 0x1,
+ 0x1,
+ 0x4,
+ 0xa,
0x5,
+ 0x0,
0x1,
+ 0x13,
0x2,
0x0,
0x0,
- 0xc,
+ 0x1,
0x2,
0x1,
- 0x3,
+ 0xe,
0x1,
+ 0xc,
0x1,
- 0x5,
0x1,
- 0x3,
+ 0x9,
0x0,
0x0,
- 0x2,
- 0x10,
+ 0x1,
+ 0xc,
0x0,
0x1,
0x0,
- 0xc,
- 0xb,
0x2,
- 0x1,
0x4,
- 0x0,
0x3,
- 0x0,
0x1,
- 0x14,
+ 0xc,
+ 0xc,
+ 0x3,
+ 0x0,
+ 0xc,
+ 0xb,
0x0,
0x1,
- 0x2,
0x1,
+ 0xa,
+ 0x1,
+ 0xb,
0x0,
- 0x7,
0x0,
- 0x2,
+ 0x1c,
0x0,
0x0,
0x0,
0x1,
0x2,
- 0x4,
- 0x0,
- 0x6,
+ 0x8,
0x3,
0x0,
- 0x11,
- 0xe,
- 0x0,
+ 0x5,
0x0,
0x3,
+ 0x3,
0x0,
- 0x1,
- 0x0,
- 0xf,
0x4,
- 0xa,
+ 0x0,
0x2,
+ 0x6,
+ 0xf,
0x0,
- 0x3,
- 0x12,
0x1,
- 0x6,
+ 0x4,
+ 0x0,
0x0,
+ 0x11,
+ 0xb,
+ 0x4,
+ 0x5,
0x4,
0x0,
- 0x2,
- 0x3,
+ 0xd,
+ 0x4,
+ 0x4,
0x3,
- 0xe,
+ 0x1,
0x0,
0x0,
- 0x7,
+ 0x2,
0x0,
0x0,
0x0,
- 0x4,
+ 0xa,
+ 0x1,
0x13,
- 0x4,
+ 0x6,
+ 0x0,
+ 0x7,
0x7,
- 0x5,
- 0x4,
- 0x2,
- 0xf,
- 0x2,
0x1,
0x1,
- 0x0,
- 0x0,
+ 0x4,
0x4,
0x0,
- 0x1,
- 0x7,
- 0xc,
0x0,
+ 0x3,
0x0,
0x7,
0x0,
0x2,
+ 0x1,
+ 0x0,
0x2,
0x0,
+ 0x2,
+ 0x2,
0x0,
0x0,
- 0x2,
- 0xc,
- 0xa,
- 0x7,
0x0,
+ 0x3,
0x4,
+ 0x5,
+ 0x10,
0x0,
- 0x4,
+ 0x7,
0x0,
+ 0xa,
+ 0x11,
0x0,
0x0,
0x1,
+ 0x1,
0x0,
0x0,
0x0,
0x0,
0x0,
+ 0x1,
0xb,
- 0xa,
- 0x3,
- 0x6,
+ 0x1,
0x0,
0x0,
- 0x4,
- 0x3,
0x0,
- 0x6,
+ 0x2,
+ 0x2,
0x0,
+ 0xa,
0x0,
+ 0x3,
0x0,
+ 0x7,
0x6,
- 0xa,
- 0x4,
+ 0x1,
0x0,
0x4,
- 0x5,
- 0x16,
+ 0x2,
+ 0x2,
0x0,
0x1,
- 0x1,
+ 0x2,
+ 0x3,
0x4,
- 0x1c,
0x0,
- 0x6,
- 0x1,
+ 0x4,
0x0,
+ 0x1,
0x0,
0x2,
- 0x2,
+ 0x10,
+ 0x5,
0x0,
0x0,
+ 0x1,
0x0,
+ 0xa,
0x4,
- 0x16,
- 0x2,
0x0,
+ 0x4,
0x0,
- 0x3,
0x0,
0x0,
- 0x3,
0x6,
0xb,
- 0x4,
+ 0xb,
+ 0x5,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x8,
+ 0x9,
0x0,
- 0x5,
- 0x5,
- 0x3,
- 0x1,
0x2,
0x4,
0x0,
- 0x4,
+ 0x5,
+ 0x2,
0x0,
+ 0x3,
0x0,
- 0x1,
0x0,
- 0x2,
- 0x8,
0x0,
0x2,
- 0xf,
- 0x9,
- 0x5,
0x0,
0x1,
- 0x1,
0x0,
+ 0x4,
0x6,
+ 0x1,
+ 0x4,
+ 0x1,
0x0,
+ 0x1,
+ 0x7,
0x0,
0x6,
- 0x4,
+ 0x0,
0x0,
0x2,
0x2,
- 0x3,
0x0,
- 0x2,
+ 0x6,
+ 0x5,
+ 0x8,
+ 0x0,
0x1,
+ 0x2,
0x1,
+ 0x0,
0x4,
- 0x1,
+ 0x7,
0x0,
- 0x5,
- 0x2,
0x1,
- 0x5,
+ 0x7,
0x0,
- 0x1,
- 0x5,
- 0x1,
0x2,
0x2,
+ 0xb,
+ 0x1,
0x2,
+ 0x6,
+ 0x1,
0x0,
0x0,
0x0,
0x0,
- 0x1,
+ 0x2,
+ 0x4,
0x0,
0x0,
- 0x2,
- 0x9,
- 0x6,
+ 0x3,
+ 0x1,
+ 0x7,
0x0,
0x1,
- 0x3,
0x1,
- 0x8,
0x0,
+ 0x1,
0x0,
- 0x2,
0x0,
+ 0xb,
0x0,
0x0,
- 0x3,
- 0x3,
- 0x1,
0x0,
- 0x2,
+ 0x6,
0x0,
+ 0x1,
+ 0x0,
+ 0x4,
+ 0xc,
0x2,
0x0,
0x1,
+ 0x1,
0x2,
- 0x3,
0x4,
- 0x1,
+ 0xe,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x1,
+ 0x2,
0x1,
0x0,
- 0xd,
- 0x1,
- 0x3,
+ 0x4,
0x3,
+ 0x18,
+ 0x0,
0x1,
+ 0x0,
+ 0x2,
0x5,
- 0x3,
- 0x1,
0x1,
0x2,
- 0x2,
0x0,
+ 0x1,
0x3,
- 0x3,
+ 0x4,
0x0,
0x0,
- 0x8,
+ 0x5,
+ 0x2,
0x0,
0x0,
0x1,
@@ -18909,12 +19024,12 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x2,
+ 0x3,
0x0,
- 0x5,
- 0xf,
- 0x4,
+ 0x1,
0x0,
- 0xb,
+ 0x0,
+ 0x1,
0x3,
0x0,
0x0,
@@ -18923,192 +19038,195 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x1,
0x0,
0x0,
- 0x3,
+ 0x14,
0x4,
- 0x6,
- 0x3,
+ 0xb,
+ 0x12,
0x0,
0x0,
- 0x1,
- 0x1,
0x2,
0x0,
+ 0x1,
+ 0x0,
0x0,
0x0,
- 0x2,
0x1,
- 0x8,
0x3,
- 0xe,
- 0x6,
- 0x2,
+ 0xb,
+ 0x3,
0x0,
0x1,
- 0x0,
0x2,
- 0x2,
- 0xa,
+ 0x0,
+ 0x10,
+ 0xd,
+ 0x1,
+ 0x1,
+ 0x7,
0x6,
0x1,
- 0x0,
- 0x8,
+ 0x1,
+ 0x2,
0x0,
0x0,
- 0xd,
0x1,
- 0x0,
+ 0x3,
0x2,
0x1,
0x3,
+ 0x1,
0x0,
0x0,
0x0,
+ 0x8,
+ 0x4,
0x2,
- 0x2,
- 0x0,
- 0x2,
- 0x0,
- 0xd,
- 0x0,
- 0x3,
+ 0x6,
0x9,
+ 0x5,
0x0,
+ 0x16,
0x1,
- 0x0,
0x4,
- 0x6,
0x0,
+ 0x3,
+ 0x3,
+ 0x4,
+ 0x1,
0x0,
- 0x5,
0x0,
- 0x1,
+ 0x2,
0x0,
0x1,
0x0,
- 0x7,
- 0x8,
0x2,
- 0x6,
- 0x1,
+ 0xd,
0x2,
0x0,
- 0x9,
- 0x0,
- 0x1,
- 0x0,
+ 0xb,
+ 0x6,
+ 0xa,
+ 0x3,
0x0,
+ 0x5,
0x0,
0x1,
- 0x1,
0x0,
- 0x3,
0x0,
- 0x2,
0x0,
+ 0x5,
0x1,
0x0,
0xa,
0x0,
- 0x7,
- 0x1,
0x2,
- 0x4,
0x0,
+ 0x2,
+ 0x2,
+ 0x5,
0x1,
+ 0x2,
0x0,
+ 0x2,
+ 0x2,
+ 0x5,
0x0,
0x1,
0x0,
0x0,
- 0xb,
+ 0x3,
+ 0x0,
+ 0x3,
0x2,
0x0,
0x0,
- 0x6,
- 0x2,
- 0x2,
- 0xf,
0x0,
0x1,
+ 0x1,
+ 0x1,
0x0,
+ 0x19,
0x0,
- 0x3,
- 0x5,
0x0,
- 0xc,
0x3,
- 0x2,
0x0,
0x1,
0x0,
+ 0x1,
0x5,
- 0x5,
+ 0x4,
0x1,
- 0x8,
+ 0x4,
0x0,
+ 0x1,
0x3,
- 0xe,
+ 0x4,
+ 0x6,
0x1,
- 0x2,
- 0x0,
0x1,
- 0x11,
- 0xa,
- 0x0,
- 0x3,
- 0x9,
+ 0x4,
0x3,
- 0x2,
- 0x0,
+ 0x4,
0x0,
+ 0x4,
+ 0x5,
+ 0x9,
0x0,
+ 0x1,
0x9,
+ 0x2,
0x1,
0x0,
0x0,
+ 0x0,
+ 0xc,
0x1,
0x0,
- 0x2,
0x0,
+ 0x3,
0x2,
- 0x0,
- 0x5,
0x3,
+ 0x2,
+ 0x1,
0x0,
- 0xb,
0x4,
0x0,
- 0x0,
- 0x3,
+ 0x4,
+ 0x7,
0x3,
- 0x0,
- 0x10,
- 0xc,
+ 0x1,
0x0,
0x1,
0x1,
- 0x9,
+ 0x0,
0x0,
0x1,
+ 0x5,
+ 0x6,
+ 0x9,
0x0,
0x2,
+ 0x1b,
+ 0x2,
0x0,
+ 0x9,
0x0,
0x0,
- 0x2,
+ 0x6,
0x0,
0x0,
+ 0x0,
+ 0x3,
+ 0x0,
+ 0x1,
0x6,
- 0xc,
0x2,
0x1,
+ 0x6,
0x1,
- 0x1,
+ 0xb,
0x3,
- 0x2,
- 0x8,
- 0x5,
- 0x2,
+ 0x6,
0x0,
0x0,
0x0,
@@ -19119,496 +19237,483 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x2,
- 0x6,
- 0x0,
+ 0x2,
0x0,
0x0,
0x0,
0x0,
- 0x5,
0x0,
0x3,
0x0,
- 0x1,
- 0x0,
- 0x0,
+ 0x3,
0x3,
0x5,
+ 0xb,
+ 0x0,
0x0,
- 0x3,
0x1,
- 0x9,
- 0x9,
- 0x4,
- 0x4,
- 0x10,
+ 0x0,
0x0,
0x2,
- 0x5,
+ 0xb,
+ 0x3,
0x2,
+ 0x13,
0x1,
0x1,
- 0x1,
+ 0x8,
+ 0x3,
+ 0x2,
+ 0x5,
0x1,
0x0,
+ 0x1,
+ 0x1,
0x5,
+ 0x0,
+ 0x1,
0x3,
- 0x8,
0x4,
- 0xb,
- 0x1,
+ 0x5,
+ 0x0,
0x2,
0x0,
- 0x4,
- 0x8,
+ 0xe,
+ 0x1,
0x0,
0x0,
0x5,
- 0x1,
+ 0x3,
+ 0x5,
0x0,
- 0x7,
0x1,
- 0x3,
+ 0x2,
0x0,
0x0,
- 0x1,
+ 0x8,
0x0,
0x1,
- 0x4,
+ 0x2,
0x0,
- 0x1,
+ 0x9,
0x0,
0x0,
0x0,
- 0x1,
+ 0x6,
0x0,
0x3,
- 0xd,
0x3,
0x9,
- 0x0,
- 0x2,
- 0x3,
0x7,
- 0xf,
- 0xa,
- 0x7,
- 0x4,
- 0x1,
- 0x1,
+ 0x0,
+ 0x8,
+ 0x0,
0x1,
+ 0x3,
0x0,
- 0x6,
+ 0x3,
0x5,
+ 0x4,
0x1,
+ 0x2,
+ 0x2,
0x0,
- 0x1,
- 0x1,
0x4,
0x3,
+ 0x0,
+ 0x7,
+ 0x5,
+ 0x3,
0x1,
- 0x1,
- 0x1,
- 0x2,
0x0,
0x4,
- 0x6,
- 0x5,
- 0x2,
+ 0x1,
0x0,
+ 0x3,
0x0,
- 0x7,
- 0x2,
0x8,
0x2,
+ 0x4,
+ 0x4,
+ 0x0,
0x9,
+ 0x1,
+ 0x4,
0x0,
+ 0x6,
+ 0x4,
0x0,
0x0,
- 0x4,
- 0x1,
0x0,
- 0x8,
- 0x2,
+ 0xa,
+ 0x1,
0x0,
0x1,
+ 0x6,
+ 0x0,
0x1,
- 0xf,
+ 0x6,
+ 0x3,
0x2,
- 0x9,
- 0x0,
- 0x9,
0x2,
- 0x7,
+ 0x0,
+ 0x1,
+ 0x1,
0x3,
+ 0x5,
0x0,
0x0,
- 0x1,
0x2,
+ 0x4,
0x1,
0x0,
0x0,
0x1,
- 0x1,
+ 0x6,
0x0,
+ 0x5,
+ 0x4,
+ 0x4,
0x1,
0x1,
- 0x1,
- 0x1,
- 0x1,
- 0x0,
+ 0x4,
0x1,
0x2,
0x0,
+ 0x2,
+ 0x2,
+ 0x5,
+ 0xd,
0x1,
- 0x1,
- 0x4,
- 0x6,
- 0xa,
0x0,
0x2,
0x0,
0x0,
- 0x4,
- 0x0,
- 0x2,
0x2,
0x0,
0x1,
0x1,
0x0,
0x0,
- 0x2,
- 0x0,
0x1,
+ 0x4,
0x0,
0x0,
+ 0x7,
0x0,
- 0x1,
0x5,
0x0,
+ 0x0,
+ 0x0,
+ 0x1,
+ 0x4,
+ 0x0,
0x9,
0x2,
- 0x2,
+ 0x4,
0x0,
0x0,
0x1,
0x0,
- 0x5,
+ 0x3,
0x0,
- 0x1,
+ 0xa,
0x0,
- 0x1,
+ 0x3,
0x1,
0x5,
- 0x3,
+ 0x1,
0x0,
0x0,
- 0x3,
0x5,
+ 0xa,
0x1,
0x2,
0x0,
0x2,
- 0x2,
- 0x2,
- 0x2,
- 0x0,
+ 0x4,
+ 0x9,
+ 0x1,
+ 0x4,
0x5,
0x0,
0x0,
0x1,
- 0x0,
- 0xc,
- 0x1,
- 0x6,
- 0x7,
+ 0x3,
+ 0x9,
+ 0x2,
+ 0x4,
+ 0x8,
0x2,
0x0,
0x0,
- 0x7,
+ 0x3,
+ 0x8,
0x0,
0x0,
0x2,
0x1,
- 0x0,
+ 0x3,
0x2,
0x1,
0x0,
0x0,
0x0,
- 0x0,
0x1,
- 0x3,
+ 0x4,
+ 0x1,
0x1,
0x0,
- 0x2,
- 0x2,
- 0x2,
+ 0x1,
0x0,
+ 0x1,
0x0,
- 0x5,
- 0x2,
- 0xe,
0x0,
0x1,
+ 0x2,
+ 0x9,
+ 0x1,
+ 0x1,
0x5,
0x2,
0x0,
0x1,
0x0,
0x0,
- 0x3,
- 0x0,
0x2,
0x0,
- 0x1,
- 0xb,
+ 0x3,
0x0,
0x1,
0x2,
- 0x1,
- 0x2,
+ 0x0,
0x4,
0x2,
+ 0x4,
0x2,
0x2,
0x0,
- 0x5,
+ 0x1,
+ 0xa,
+ 0x0,
+ 0x1,
0x0,
0x0,
0x0,
0x0,
+ 0x3,
0x0,
- 0xb,
+ 0x3,
0x2,
+ 0x5,
0x1,
- 0x0,
0x2,
- 0x3,
+ 0x1,
0x2,
0x0,
- 0x0,
+ 0x4,
+ 0x2,
0x1,
0x0,
- 0x2,
0x1,
0x0,
0x0,
0x1,
- 0x2,
0x1,
0x3,
0x0,
0x0,
0x0,
0x0,
- 0x4,
0x0,
+ 0x2,
0x0,
+ 0x2,
0x3,
- 0x5,
- 0x12,
- 0x0,
- 0x0,
0x2,
- 0xe,
0x0,
- 0x2,
- 0x6,
+ 0x0,
0x0,
0x5,
0x1,
- 0x2,
- 0x2,
0x0,
0x1,
- 0x6,
- 0x2,
- 0x0,
0x1,
- 0x3,
0x0,
+ 0x7,
0x1,
0x1,
- 0x6,
- 0x1,
0x3,
- 0x4,
0x0,
+ 0x3,
+ 0x1,
+ 0x1,
0x0,
- 0x5,
+ 0x9,
+ 0x2,
0x0,
0x1,
0x1,
- 0x3,
+ 0x7,
+ 0x6,
+ 0x2,
+ 0x0,
+ 0x6,
+ 0x0,
+ 0x4,
+ 0x0,
+ 0x2,
+ 0x7,
0x4,
0x1,
+ 0x1,
0x0,
0x0,
0x2,
+ 0x1,
+ 0x0,
+ 0x4,
0x3,
0x0,
- 0x2,
+ 0xa,
0x0,
0x0,
- 0x3,
- 0x0,
- 0x2,
0x2,
0x2,
- 0x5,
- 0x4,
0x1,
+ 0x1,
+ 0x3,
0x2,
0x1,
+ 0x1,
0x0,
- 0x2,
+ 0x3,
0x0,
0x0,
0x0,
0x1,
- 0xe,
- 0x1,
- 0x2,
+ 0x6,
0x1,
- 0x2,
+ 0x3,
+ 0xb,
+ 0xb,
0x0,
- 0x8,
0x4,
+ 0x1,
0x0,
0x0,
0x0,
0x0,
0x5,
- 0x1,
+ 0x2,
0x0,
0x0,
- 0x2,
0x1,
+ 0x4,
0x0,
0x0,
- 0x2,
+ 0x1,
0x0,
0x0,
+ 0x5,
+ 0x3,
0x2,
0x3,
- 0x0,
- 0x4,
+ 0x8,
0x1,
+ 0x6,
0x1,
0x2,
0x0,
0x1,
- 0x0,
0x4,
+ 0x5,
+ 0x2,
0x0,
+ 0x6,
+ 0x1,
0x1,
0x0,
- 0x0,
0x2,
+ 0x1,
+ 0x2,
+ 0x2,
+ 0x0,
+ 0x0,
0x4,
- 0xe,
0x0,
- 0x2,
0x1,
- 0xe,
0x2,
0x0,
- 0xa,
- 0x0,
+ 0x5,
+ 0x2,
0x2,
- 0x3,
0x6,
- 0x0,
- 0x1,
- 0x8,
0x1,
- 0x4,
- 0x0,
+ 0x5,
0x3,
0x2,
- 0x1,
+ 0x5,
0x2,
- 0x7,
- 0x3,
+ 0x1,
+ 0x1,
0x0,
0x4,
- 0x3,
+ 0x2,
0x0,
- 0x4,
+ 0x2,
0x0,
0x0,
- 0x1,
+ 0x5,
0x0,
0x0,
0x0,
0x1,
0x0,
- 0x9,
+ 0x2,
0x0,
0x0,
0x0,
- 0x1,
+ 0x15,
0x2,
0x0,
0x0,
0x1,
0x2,
0x7,
- 0x2,
- 0xa,
+ 0x3,
+ 0x3,
+ 0x3,
0x1,
- 0x0,
0x1,
+ 0x2,
+ 0x6,
0x1,
- 0xb,
0x7,
0x0,
0x0,
0x0,
0x0,
- 0x1,
- 0x1,
- 0x0,
- 0x2,
- 0x0,
- 0x0,
- 0x2,
- 0x1,
- 0xa,
0x4,
- 0x2,
- 0x7,
- 0x1,
- 0x2,
+ 0x0,
+ 0x3,
0x2,
0x0,
0x0,
- 0x2,
- 0x2,
0x1,
0x1,
+ 0x3,
0x1,
- 0x0,
0x1,
0x0,
- 0x3,
0x1,
- 0x0,
0x1,
- 0x0,
- 0x0,
- 0x0,
- 0x0,
- 0x3,
- 0x2,
- 0x2,
- 0x2,
- 0x0,
+ 0x5,
0x0,
0x1,
- 0x1,
+ 0x5,
+ 0x4,
+ 0x8,
0x2,
0x1,
0x0,
@@ -19623,154 +19728,178 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x7,
- 0x2,
- 0x3,
- 0x6,
0x3,
+ 0x1,
+ 0x1,
+ 0x0,
+ 0x0,
0x4,
+ 0x3,
0x1,
+ 0x4,
+ 0x0,
+ 0x4,
0x0,
0x2,
- 0xb,
+ 0x2,
+ 0x3,
0x0,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1,
0x5,
- 0x3,
+ 0x0,
+ 0x2,
+ 0x4,
0x2,
0x1,
+ 0x6,
0x0,
+ 0x1,
+ 0xf,
0x0,
+ 0x2,
+ 0x5,
0x0,
- 0xc,
0x2,
- 0x1,
+ 0x0,
0x3,
+ 0x4,
+ 0x2,
+ 0x4,
0x3,
+ 0x5,
0x1,
- 0x3,
- 0x0,
- 0x6,
0x1,
- 0x0,
+ 0x1,
+ 0x7,
0x0,
0x7,
+ 0x2,
0x0,
0x0,
- 0xa,
+ 0x6,
0x0,
0x0,
+ 0x2,
0x0,
0x0,
- 0x3,
0x0,
- 0x2,
0x0,
- 0x2,
0x3,
+ 0x0,
0x3,
+ 0x0,
0x1,
+ 0x2,
+ 0x7,
0x1,
- 0x3,
- 0x3,
- 0x0,
+ 0x7,
0x3,
0x1,
0x0,
- 0xa,
+ 0x2,
+ 0x2,
0x0,
- 0x1,
+ 0x5,
+ 0x0,
+ 0x3,
0x0,
0x0,
0x2,
0x1,
- 0x2,
0x1,
0x1,
0x2,
+ 0x2,
+ 0x2,
0x0,
- 0x5,
+ 0x1,
+ 0x4,
0x2,
0x1,
- 0x7,
0x2,
0x3,
0x0,
+ 0x2,
+ 0x2,
0x4,
- 0x3,
0x2,
0x1,
0x2,
- 0x1,
- 0x1,
+ 0x2,
0x0,
0x0,
0x1,
0x0,
- 0x1,
+ 0x2,
0x0,
- 0x1,
+ 0x7,
0x1,
0x0,
- 0x3,
- 0x1,
- 0x1,
0x1,
+ 0x4,
+ 0x3,
+ 0x3,
0x1,
- 0x2,
+ 0x5,
0x1,
0x0,
0x0,
- 0x6,
+ 0x3,
0x0,
0x1,
- 0x1,
+ 0x6,
0x1,
0x0,
- 0x4,
- 0x4,
+ 0x2,
0xd,
+ 0x1,
0x0,
0x0,
0x4,
0x0,
+ 0xf,
0x2,
- 0x3,
0x0,
- 0x3,
+ 0xa,
+ 0x2,
+ 0x1,
+ 0x0,
0x1,
- 0xc,
0x0,
+ 0x4,
0x2,
0x0,
0x3,
- 0x1,
- 0x3,
0x0,
0x2,
- 0x5,
- 0xb,
0x0,
+ 0x7,
+ 0x2,
0x1,
0x0,
0x0,
- 0x1,
- 0x0,
0x3,
0x0,
- 0x0,
0x4,
0x0,
0x0,
- 0x2,
- 0x2,
- 0x3,
- 0x1,
+ 0xb,
+ 0x0,
+ 0x0,
+ 0xa,
+ 0x5,
+ 0x9,
0x1,
0x0,
+ 0x3,
0x1,
0x0,
+ 0xc,
0x0,
- 0x2,
0x0,
0x0,
0x0,
@@ -19778,243 +19907,247 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x1,
0x0,
0x2,
- 0x5,
- 0x3,
- 0x0,
- 0x1,
- 0x5,
0x1,
+ 0x2,
0x0,
0x1,
+ 0x3,
+ 0x2,
0x0,
+ 0x7,
0x0,
- 0x5,
0x0,
+ 0x3,
0x0,
- 0x8,
+ 0x0,
+ 0x6,
0x2,
0x0,
0x0,
- 0x3,
+ 0x6,
0x0,
0x0,
- 0x3,
+ 0x4,
+ 0x2,
+ 0x1,
+ 0x1,
0x0,
+ 0x7,
0x2,
+ 0x4,
+ 0x1,
+ 0x5,
0x0,
0x0,
0x1,
+ 0x2,
0x0,
0x2,
+ 0x3,
+ 0x8,
0x1,
+ 0x6,
0x2,
- 0x0,
- 0x0,
0x1,
- 0x0,
- 0x0,
0x1,
0x0,
0x3,
- 0x4,
+ 0x5,
+ 0x0,
0x2,
- 0x6,
0x1,
- 0x6,
+ 0x1,
0x3,
0x0,
- 0x2,
- 0x7,
0x3,
+ 0x7,
0x1,
- 0x1,
- 0x0,
- 0x2,
0x0,
0x1,
0x0,
- 0x1,
0x0,
0x0,
+ 0x3,
0x0,
0x1,
- 0x0,
- 0x2,
- 0x7,
- 0x3,
0x1,
- 0xa,
- 0x2,
- 0x0,
0x1,
+ 0x1,
+ 0x6,
+ 0x5,
+ 0x0,
+ 0x5,
0x4,
0x0,
- 0x3,
+ 0x0,
0x3,
0x1,
0x2,
0x0,
- 0xd,
- 0x2,
0x0,
- 0x1,
+ 0x2,
0x0,
+ 0x2,
+ 0x2,
0x0,
0x2,
0x0,
- 0x1,
+ 0x4,
0x1,
0x0,
0x2,
- 0x5,
+ 0x0,
0x4,
0x1,
0x1,
- 0x0,
+ 0x4,
+ 0x2,
0x1,
0x0,
- 0x0,
+ 0x1,
0x2,
- 0x3,
0x1,
+ 0x3,
0x0,
0x0,
0x1,
- 0x1,
- 0x2,
+ 0x0,
+ 0xb,
0x2,
0x0,
0x0,
- 0x7,
- 0x4,
+ 0x3,
+ 0x3,
+ 0x5,
0x1,
0x1,
+ 0x0,
+ 0x1,
0x2,
- 0x2,
- 0x2,
- 0x4,
0x1,
0x0,
0x0,
0x0,
- 0x3,
+ 0x8,
0x1,
+ 0x4,
0x3,
- 0x2,
0x0,
- 0x2,
+ 0x7,
0x1,
+ 0x3,
0x1,
- 0x2,
0x0,
- 0x4,
- 0x4,
0x2,
+ 0x3,
+ 0x3,
0x1,
0x0,
0x1,
0x1,
- 0x3,
0x1,
0x0,
+ 0x2,
0x0,
- 0x6,
0x1,
0x1,
0x1,
+ 0x4,
+ 0x2,
+ 0x5,
+ 0x0,
0x1,
0x1,
0x0,
- 0x2,
- 0x3,
- 0x3,
- 0x2,
+ 0x1,
0x2,
0x0,
0x0,
0x0,
- 0x1,
0x0,
+ 0x3,
0x1,
0x2,
0x1,
+ 0x3,
0x1,
- 0xa,
- 0x4,
+ 0x0,
+ 0x5,
0x2,
- 0x1,
+ 0x4,
0x0,
0x3,
0x0,
0x0,
- 0x2,
- 0x5,
- 0x5,
+ 0x1,
+ 0x3,
+ 0x7,
0x0,
0x6,
0x4,
0x0,
- 0x9,
+ 0x1,
+ 0x2,
0x2,
0x3,
- 0x4,
- 0x9,
+ 0x5,
0x0,
- 0x1,
- 0x1,
+ 0x8,
+ 0x3,
0x3,
- 0x1,
0x2,
+ 0x1,
0x7,
- 0xb,
+ 0x2,
0x1,
0x1,
0x1,
0x1,
- 0x5,
- 0x2,
0x0,
- 0x2,
- 0x6,
- 0x2,
- 0x4,
+ 0x8,
0x0,
+ 0x1,
+ 0x3,
0x0,
+ 0x2,
0x1,
+ 0x0,
0x1,
+ 0x2,
0x0,
0x0,
- 0x1,
+ 0x6,
+ 0x7,
0x1,
0x0,
- 0x2,
+ 0x3,
0x0,
0x0,
0x0,
- 0x5,
+ 0x1,
0x2,
0x0,
0x0,
0x1,
- 0x0,
0x1,
- 0x4,
+ 0x1,
0x0,
0x1,
- 0x3,
+ 0x4,
+ 0x2,
0x0,
0x0,
- 0x5,
+ 0x1,
0x0,
0x0,
0x0,
- 0x4,
- 0x1,
- 0x1,
0x5,
- 0x1,
+ 0x2,
0x3,
0x1,
+ 0x2,
+ 0x0,
+ 0x6,
0x1,
0x0,
0x1,
@@ -20022,16 +20155,16 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x1,
+ 0x2,
0x0,
- 0x4,
- 0x1,
+ 0x2,
+ 0x3,
0x0,
0x2,
- 0x4,
+ 0x7,
0x1,
0x0,
- 0x2,
+ 0x0,
0x2,
0x0,
0x0,
@@ -20039,210 +20172,214 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x3,
+ 0x1,
0x0,
0x0,
- 0x3,
+ 0x2,
0x0,
0x1,
0x0,
0x4,
- 0x6,
+ 0x2,
0x0,
+ 0x11,
0x5,
- 0x1,
+ 0x4,
0x0,
+ 0x4,
+ 0x0,
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x7,
0x0,
0x1,
0x0,
0x0,
+ 0x1,
+ 0x5,
+ 0x1,
0x2,
0x2,
+ 0xe,
0x0,
- 0x2,
- 0x1,
0x0,
0x2,
- 0x2,
0x1,
- 0x2,
- 0x9,
- 0x5,
- 0x0,
0x0,
+ 0x1,
0x0,
0x3,
+ 0x1,
+ 0x2,
+ 0x1,
0x0,
+ 0xa,
0x1,
+ 0x4,
0x0,
0x5,
0x1,
- 0x8,
0x1,
- 0x0,
- 0x2,
0x1,
0x2,
- 0x0,
- 0x5,
- 0x2,
0x1,
0x1,
- 0x3,
- 0x2,
0x1,
- 0x5,
0x0,
0x0,
- 0x3,
- 0x3,
0x1,
+ 0x8,
0x1,
- 0x2,
+ 0x1,
+ 0x0,
0x1,
0x0,
0x0,
0x0,
- 0x3,
+ 0x0,
+ 0x1,
0x3,
0x1,
+ 0xf,
0x1,
- 0x3,
+ 0x2,
0x1,
0x1,
- 0x5,
0x0,
0x0,
0x2,
- 0x2,
- 0x0,
- 0x0,
- 0x0,
0x1,
- 0x2,
- 0x3,
0x0,
- 0x2,
0x0,
- 0x2,
- 0x4,
0x3,
- 0x2,
- 0x2,
- 0x0,
- 0x3,
- 0xc,
0x0,
0x1,
+ 0x0,
+ 0x0,
0x1,
0x0,
- 0x2,
0x5,
+ 0x7,
+ 0x2,
0x2,
+ 0x6,
0x0,
- 0x3,
0x1,
0x0,
+ 0x2,
0x1,
+ 0x4,
+ 0x0,
+ 0x2,
0x1,
- 0x5,
0x3,
0x2,
+ 0x2,
+ 0x1,
0x0,
0x3,
- 0x0,
- 0x4,
0x2,
- 0x0,
+ 0x4,
+ 0x3,
0x1,
+ 0x0,
0x1,
0x0,
- 0x2,
0x1,
0x1,
0x3,
0x0,
0x1,
- 0x1,
- 0x1,
- 0x0,
- 0x2,
- 0x0,
0x0,
0x2,
+ 0x6,
+ 0x5,
0x1,
+ 0x9,
0x0,
- 0x5,
- 0x2,
+ 0x3,
+ 0x1,
0x0,
+ 0x6,
0x0,
- 0x1,
- 0x1,
0x0,
0x3,
0x0,
+ 0x1,
0x0,
0x2,
0x2,
- 0x1,
- 0x3,
0x0,
0x3,
- 0x3,
- 0x2,
0x1,
+ 0x0,
0x1,
0x0,
+ 0x0,
+ 0x8,
0x1,
0x2,
- 0x3,
0x1,
0x0,
0x2,
- 0x7,
+ 0x4,
0x1,
+ 0x2,
+ 0x1,
+ 0x5,
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x2,
0x1,
0x0,
- 0x3,
0x1,
0x1,
0x2,
0x1,
0x0,
- 0xb,
+ 0x2,
+ 0x3,
0x1,
+ 0x1,
+ 0x3,
0x0,
- 0x6,
+ 0x1,
+ 0x1,
0x0,
- 0x3,
- 0xc,
0x5,
0x0,
- 0x4,
- 0xa,
0x2,
+ 0x6,
+ 0x1,
0x0,
- 0x8,
- 0x2,
+ 0x4,
+ 0x0,
+ 0x1,
0x0,
0x0,
- 0x3,
0x1,
0x2,
+ 0x0,
+ 0x3,
+ 0x0,
+ 0x1,
0x1,
0x0,
0x0,
0x2,
0x0,
0x2,
- 0x4,
+ 0x0,
0x1,
0x0,
0x0,
0x0,
- 0x4,
+ 0x2,
0x0,
- 0x9,
+ 0x0,
+ 0x1,
0x3,
0x2,
0x0,
@@ -20250,239 +20387,243 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x1,
0x0,
- 0x3,
- 0x0,
+ 0x4,
0x0,
0x0,
0x1,
- 0x0,
0x1,
0x0,
0x2,
+ 0x0,
0x2,
- 0x5,
+ 0x1,
+ 0x1,
+ 0x1,
+ 0x0,
0x0,
- 0x5,
0x0,
0x0,
0x0,
+ 0xb,
+ 0x4,
0x0,
0x1,
- 0x3,
- 0x3,
0x0,
+ 0x1,
+ 0x5,
0x0,
0x1,
0x1,
0x0,
- 0x2,
- 0x3,
- 0x0,
- 0x1,
+ 0x5,
0x1,
0x0,
+ 0x2,
0x4,
- 0x0,
- 0x1,
0x1,
0x1,
- 0x3,
0x2,
- 0x7,
+ 0x1,
+ 0x1,
+ 0x1,
0x0,
0x0,
0x0,
0x0,
- 0x2,
+ 0x0,
+ 0x6,
0x0,
0x2,
- 0x2,
- 0x2,
+ 0x3,
+ 0x0,
0x1,
0x2,
- 0x2,
- 0x5,
+ 0x3,
0x0,
+ 0x0,
+ 0x3,
+ 0x2,
0x4,
- 0x8,
0x0,
- 0x1,
0x3,
- 0x5,
0x0,
- 0x1,
0x0,
- 0x4,
+ 0x1,
0x0,
0x3,
- 0x1,
0x0,
- 0x4,
+ 0xd,
0x2,
0x0,
- 0x0,
- 0x5,
0x3,
+ 0x1,
+ 0x0,
+ 0x0,
+ 0x1,
+ 0x1,
0x3,
0x0,
0x1,
0x0,
0x4,
- 0x3,
- 0x3,
- 0x2,
+ 0xd,
+ 0x4,
0x1,
- 0x3,
+ 0x6,
+ 0x2,
0x3,
0x0,
- 0x2,
0x3,
- 0x2,
0x1,
+ 0x0,
0x2,
0x1,
+ 0x2,
0x0,
+ 0x1,
0x3,
- 0xc,
0x1,
+ 0x2,
+ 0x0,
0x1,
0x2,
0x0,
0x3,
- 0x0,
- 0x2,
+ 0x1,
0x1,
0x0,
- 0x4,
- 0x4,
0x1,
0x2,
- 0x0,
0x1,
- 0x0,
- 0x3,
0x3,
- 0x3,
- 0x1,
0x2,
0x0,
+ 0x0,
+ 0x1,
+ 0x1,
+ 0x0,
+ 0x1,
0x1,
- 0x12,
0x3,
+ 0x4,
+ 0x1,
0x2,
+ 0x3,
0x0,
0x2,
- 0xa,
- 0x5,
+ 0x3,
+ 0x2,
0x1,
0x1,
+ 0x7,
0x2,
- 0xd,
0x0,
- 0x2,
+ 0x1,
0x0,
0x0,
0x2,
0x0,
- 0x1,
0x2,
- 0x4,
- 0x3,
+ 0x5,
+ 0x1,
+ 0x1,
0x0,
0x0,
0x1,
0x1,
- 0x1,
+ 0x2,
0x0,
0x1,
- 0x1,
+ 0x3,
0x0,
0x1,
- 0x5,
+ 0x2,
0x0,
0x0,
+ 0x5,
+ 0x0,
0x2,
- 0x1,
0x0,
0x1,
- 0xb,
0x0,
0x1,
- 0x8,
+ 0x3,
0x1,
0x0,
0x0,
+ 0x3,
+ 0x5,
+ 0x5,
0x0,
0x1,
- 0x0,
- 0x0,
+ 0x3,
0x1,
0x2,
- 0x1,
0x0,
0x0,
0x3,
- 0x6,
- 0x1,
+ 0x2,
0x0,
0x0,
0x0,
- 0x4,
0x0,
0x4,
- 0x1,
0x0,
0x1,
+ 0x6,
+ 0x0,
0x1,
0x1,
+ 0x2,
0x1,
0x0,
- 0x2,
- 0x2,
0x1,
0x4,
- 0x8,
0x1,
+ 0x2,
+ 0x1,
+ 0x8,
0x1,
0x1,
0x0,
0x0,
- 0x2,
+ 0x4,
0x0,
0x0,
0x4,
0x0,
0x0,
- 0x2,
+ 0x3,
0x0,
- 0x4,
- 0x1,
- 0x2,
0x2,
+ 0x1,
+ 0x7,
+ 0x1,
0x0,
0x6,
0x0,
0x1,
0x0,
0x0,
- 0x4,
- 0x0,
0x1,
0x0,
- 0x1,
+ 0x6,
+ 0x3,
+ 0x2,
0x0,
0x0,
0x0,
0x0,
+ 0x5,
0x1,
- 0x1,
- 0x2,
0x0,
- 0x1,
+ 0x3,
0x0,
+ 0x1,
0x0,
0x1,
- 0x3,
+ 0x1,
+ 0x1,
0x1,
0x0,
0x0,
@@ -20490,3954 +20631,4019 @@ pub(crate) const COMPATIBILITY_DECOMPOSED_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x2,
+ 0x4,
+ 0x0,
+ 0x1,
0x0,
+ 0x3,
0x2,
- 0x4,
- 0x5,
0x0,
- 0x6,
0x0,
0x0,
- 0x5,
- 0x2,
0x3,
+ 0x8,
+ 0x7,
0x0,
0x0,
0x0,
0x2,
- 0x2,
+ 0x1,
+ 0x0,
0x0,
0x0,
0x0,
0x2,
- 0x3,
0x0,
0x1,
- 0x8,
- 0xa,
- 0x3,
- 0x0,
+ 0x2,
0x0,
0x1,
0x0,
+ 0x0,
0x1,
- 0x3,
0x1,
0x2,
+ 0x3,
+ 0x1,
0x1,
0x0,
- 0x4,
+ 0x2,
+ 0x7,
0x4,
0x0,
0x0,
- 0x1,
+ 0x6,
+ 0x0,
0x0,
0x0,
0x0,
0x1,
- 0x8,
+ 0x0,
+ 0x2,
0x1,
0x0,
- 0x3,
- 0x4,
- 0x3,
0x2,
0x1,
+ 0x3,
0x1,
- 0x4,
+ 0x2,
0x0,
0x1,
- 0x1,
+ 0x4,
+ 0x2,
+ 0x2,
0x1,
0x0,
- 0x1,
- 0xc,
+ 0x2,
0x0,
0x0,
0x0,
- 0x3,
- 0x3,
0x1,
- 0x7,
- 0x3,
+ 0x0,
+ 0x6,
+ 0x8,
+ 0x5,
0x1,
0x0,
- 0x3,
+ 0x8,
0x0,
0x6,
- 0x2,
- 0x0,
0x1,
0x0,
- 0x2,
+ 0xc,
+ 0x3,
+ 0x5,
0x0,
- 0x4,
- 0x4,
0x2,
0x1,
- 0x1,
0x5,
0x1,
0x1,
- 0x1,
- 0x2,
- 0x3,
- 0x0,
+ 0x4,
0x3,
0x1,
+ 0x1,
+ 0x5,
+ 0x6,
+ 0x1,
+ 0x2,
+ 0x7,
0x3,
0x2,
0x0,
- 0xf,
+ 0x0,
+ 0x1,
0x0,
0x1,
0x2,
- 0x5,
0x1,
0x1,
- 0x0,
- 0x2,
0x1,
+ 0x0,
0x1,
+ 0x2,
+ 0x2,
0x0,
- 0x4,
- 0x3,
- 0x3,
+ 0x2,
0x3,
- 0x4,
0x1,
0x1,
0x0,
0x1,
+ 0x0,
0x1,
- 0x1,
+ 0x5,
+ 0x5,
+ 0x2,
0x0,
0x0,
0x1,
- 0x1,
0x2,
+ 0x4,
0x1,
- 0x7,
0x0,
- 0x6,
- 0x6,
- 0xc,
+ 0x0,
0x1,
0x3,
- 0x3,
- 0x0,
+ 0x8,
0x1,
- 0x2,
+ 0x6,
+ 0x0,
+ 0x0,
+ 0x3,
0x1,
0x1,
0x1,
0x1,
0x2,
- 0x0,
0x1,
0x0,
- 0x6,
- 0x7,
+ 0x5,
+ 0x0,
0x1,
- 0x6,
+ 0x0,
+ 0x5,
0x1,
- 0x2,
- 0x4,
0x4,
- 0x3,
- 0x2,
- 0x0,
+ 0x1,
+ 0x8,
0x0,
+ 0x1,
0x4,
0x0,
- 0x1,
- 0x2,
0x0,
- 0x3,
0x2,
0x0,
+ 0x3,
+ 0x1,
0x0,
0x1,
+ 0x2,
+ 0x2,
0x0,
- 0x3,
+ 0x2,
0x0,
0x0,
0x1,
0x0,
0x5,
0x3,
+ 0x1,
+ 0x2,
0x3,
- 0x0,
0x1,
+ 0xc,
+ 0x3,
0x0,
- 0x2,
0x1,
0x0,
0x0,
0x0,
0x0,
- 0x2,
0x0,
+ 0x3,
0x0,
0x1,
- 0x1,
- 0x1,
+ 0x5,
+ 0x3,
+ 0x2,
0x1,
0x0,
- 0x1,
- 0x1,
+ 0x3,
+ 0x2,
0x0,
];
pub(crate) const COMPATIBILITY_DECOMPOSED_KV: &[(u32, (u16, u16))] = &[
- (0xfee5, (3971, 1)),
- (0x332a, (1837, 3)),
- (0x1d40e, (4305, 1)),
- (0xfc8f, (2976, 2)),
- (0xff18, (4032, 1)),
+ (0x1d5e5, (4752, 1)),
+ (0x1d430, (4339, 1)),
+ (0xfca0, (3015, 2)),
+ (0x1d769, (5138, 1)),
+ (0xfe55, (3808, 1)),
(0xfd72, (3438, 3)),
(0xb2, (6, 1)),
- (0x1d5c5, (4720, 1)),
- (0x1d43f, (4354, 1)),
+ (0x333b, (1909, 5)),
+ (0xfbae, (2585, 1)),
(0x1d727, (5072, 1)),
- (0x3256, (1432, 2)),
- (0x3289, (1514, 1)),
+ (0x246d, (573, 2)),
+ (0x332c, (1846, 4)),
(0x1d79a, (5187, 1)),
- (0x24e1, (830, 1)),
- (0xfc9e, (3011, 2)),
- (0x207d, (332, 1)),
- (0xff66, (4110, 1)),
- (0xff47, (4079, 1)),
+ (0xfd81, (3483, 3)),
+ (0xff07, (4015, 1)),
+ (0x1d76b, (5140, 1)),
+ (0x2fb1, (1034, 1)),
+ (0x1d4ef, (4518, 1)),
(0x3193, (1179, 1)),
(0xfbec, (2621, 3)),
(0x1d410, (4307, 1)),
(0x2177, (527, 4)),
- (0x107a1, (4266, 1)),
- (0xfd63, (3393, 3)),
- (0x330c, (1717, 4)),
+ (0xfcfa, (3200, 2)),
+ (0x1ee8e, (5451, 1)),
+ (0xfed8, (3958, 1)),
(0x32b8, (1568, 2)),
- (0x3218, (1274, 4)),
- (0x1d703, (5036, 1)),
+ (0xfb7f, (2536, 1)),
+ (0x1d5f4, (4767, 1)),
(0x33e0, (2351, 2)),
+ (0x1e055, (5324, 1)),
(0xffac, (4180, 1)),
(0x1e9a, (234, 2)),
- (0xff9b, (4163, 1)),
- (0x2101, (368, 3)),
- (0x2f93, (1004, 1)),
+ (0xfdf7, (3716, 4)),
+ (0x1d493, (4437, 1)),
+ (0x2085, (340, 1)),
(0x2148, (433, 1)),
- (0x32cc, (1611, 2)),
+ (0x1d4e9, (4512, 1)),
(0x1d73c, (5093, 1)),
(0x1da8, (210, 1)),
(0xfeba, (3928, 1)),
- (0x1f127, (5519, 3)),
(0x1d48e, (4432, 1)),
- (0x1d531, (4579, 1)),
- (0x1d623, (4814, 1)),
- (0x2492, (679, 3)),
- (0x1d798, (5185, 1)),
- (0x1db8, (226, 1)),
- (0x2fc2, (1051, 1)),
- (0x1d594, (4671, 1)),
+ (0x1ee6c, (5422, 1)),
+ (0x1d628, (4819, 1)),
+ (0x1d6d1, (4986, 1)),
+ (0x2130, (413, 1)),
+ (0xff6c, (4116, 1)),
+ (0x1d7b4, (5213, 1)),
+ (0x1da4, (206, 1)),
+ (0x1e061, (5336, 1)),
(0x3224, (1319, 3)),
- (0xffdb, (4218, 1)),
+ (0x3229, (1334, 3)),
(0x1d7ff, (5286, 1)),
- (0x1d4bd, (4469, 1)),
+ (0x1d657, (4866, 1)),
(0xfee9, (3975, 1)),
- (0x2fa2, (1019, 1)),
+ (0x32f6, (1659, 1)),
(0xfc13, (2716, 2)),
- (0xff34, (4060, 1)),
- (0xfda8, (3594, 3)),
- (0x1d560, (4619, 1)),
+ (0x1d46e, (4400, 1)),
+ (0x2472, (583, 2)),
+ (0x1d6ba, (4963, 1)),
(0xfd05, (3222, 2)),
- (0xffb4, (4188, 1)),
- (0x1d5a8, (4691, 1)),
+ (0x33d7, (2328, 2)),
+ (0xfc17, (2724, 2)),
(0x2170, (513, 1)),
- (0x1ee75, (5368, 1)),
+ (0xfd1c, (3268, 2)),
(0x3382, (2123, 2)),
- (0xff5d, (4101, 1)),
- (0x1ee95, (5396, 1)),
- (0x3325, (1824, 3)),
- (0x1d672, (4893, 1)),
- (0xfceb, (3167, 2)),
+ (0x1d764, (5133, 1)),
+ (0x1ee95, (5458, 1)),
+ (0x2f24, (893, 1)),
+ (0x32e5, (1642, 1)),
+ (0x1d409, (4300, 1)),
(0x1d43, (157, 1)),
- (0xfec2, (3936, 1)),
- (0x2f15, (878, 1)),
+ (0x1d597, (4674, 1)),
+ (0x2f81, (986, 1)),
(0xfc4a, (2826, 2)),
- (0x1d6b3, (4956, 1)),
+ (0x1d713, (5052, 1)),
(0x1d7a1, (5194, 1)),
- (0x1d47b, (4413, 1)),
+ (0xff74, (4124, 1)),
(0xff7d, (4133, 1)),
- (0x1d4fb, (4530, 1)),
- (0xfca7, (3029, 2)),
- (0x2f7d, (982, 1)),
+ (0x2483, (638, 4)),
+ (0x3323, (1817, 3)),
+ (0x1e059, (5328, 1)),
(0x1d558, (4611, 1)),
+ (0xfc37, (2788, 2)),
(0x2f64, (957, 1)),
- (0xfb78, (2529, 1)),
+ (0xfe58, (3811, 1)),
(0x32ee, (1651, 1)),
- (0x326e, (1466, 2)),
+ (0xfc6a, (2902, 2)),
(0x1d466, (4392, 1)),
- (0xfd5c, (3372, 3)),
(0x207e, (333, 1)),
- (0x1078c, (4245, 1)),
- (0x1ee37, (5335, 1)),
- (0x24d7, (820, 1)),
- (0x1eeb6, (5422, 1)),
- (0x1d576, (4641, 1)),
- (0x2f27, (896, 1)),
+ (0x1e050, (5319, 1)),
+ (0x1d5ed, (4760, 1)),
+ (0xfc97, (2992, 3)),
+ (0x1d791, (5178, 1)),
+ (0x1d7bd, (5222, 1)),
+ (0x314d, (1112, 1)),
+ (0x33aa, (2219, 3)),
(0xfc0c, (2702, 2)),
- (0x325e, (1448, 2)),
- (0xfc40, (2806, 2)),
- (0x1d772, (5147, 1)),
- (0x1d5cd, (4728, 1)),
+ (0x2f47, (928, 1)),
+ (0x3230, (1355, 3)),
+ (0xfdc6, (3684, 3)),
+ (0x1d614, (4799, 1)),
(0x3291, (1522, 1)),
- (0x2f26, (895, 1)),
- (0x2e9f, (855, 1)),
- (0x1d467, (4393, 1)),
- (0x33cf, (2309, 2)),
- (0x3251, (1422, 2)),
- (0xfb8e, (2551, 1)),
- (0x1d65e, (4873, 1)),
- (0x1db5, (223, 1)),
- (0x1d5b6, (4705, 1)),
- (0x313e, (1097, 1)),
- (0xffd4, (4213, 1)),
- (0x1d56c, (4631, 1)),
- (0xfe4d, (3801, 1)),
- (0x1d426, (4329, 1)),
+ (0xfe31, (3771, 1)),
+ (0x1d706, (5039, 1)),
+ (0xfe78, (3842, 2)),
+ (0x325a, (1440, 2)),
+ (0x2f84, (989, 1)),
+ (0xfca1, (3017, 2)),
+ (0x24bb, (792, 1)),
+ (0x2094, (354, 1)),
+ (0x1d4f8, (4527, 1)),
+ (0xfcfe, (3208, 2)),
+ (0x1d487, (4425, 1)),
+ (0x1d6fd, (5030, 1)),
+ (0x1d559, (4612, 1)),
+ (0x2074, (323, 1)),
(0x2112, (391, 1)),
- (0xfe44, (3790, 1)),
- (0x1d57a, (4645, 1)),
+ (0xfcd5, (3121, 2)),
+ (0x2f06, (863, 1)),
(0x107ba, (4290, 1)),
- (0x1dbf, (233, 1)),
- (0xfb24, (2481, 1)),
+ (0xa7f4, (2443, 1)),
+ (0x24bf, (796, 1)),
(0x1d49c, (4446, 1)),
- (0xfc34, (2782, 2)),
- (0x1d579, (4644, 1)),
- (0x1f220, (5606, 1)),
- (0xfec1, (3935, 1)),
+ (0x1d63c, (4839, 1)),
+ (0x32a2, (1539, 1)),
+ (0x1f220, (5668, 1)),
+ (0x1d60f, (4794, 1)),
(0x32d5, (1626, 1)),
(0xfcec, (3169, 2)),
- (0x2f89, (994, 1)),
- (0x33c1, (2276, 2)),
- (0xfc03, (2682, 3)),
+ (0xfc49, (2824, 2)),
+ (0xfe70, (3830, 2)),
+ (0x2f45, (926, 1)),
(0x33b8, (2258, 2)),
- (0x248a, (662, 2)),
+ (0x2e2, (85, 1)),
+ (0x2fba, (1043, 1)),
(0x32c6, (1596, 2)),
- (0x208c, (347, 1)),
- (0x1d680, (4907, 1)),
- (0x1d58c, (4663, 1)),
+ (0x1ee87, (5445, 1)),
+ (0xffb3, (4187, 1)),
(0xfb71, (2522, 1)),
- (0x3039, (1074, 1)),
- (0x2138, (420, 1)),
- (0x320c, (1228, 3)),
- (0x1d46d, (4399, 1)),
+ (0xff0b, (4019, 1)),
+ (0xfd26, (3288, 2)),
+ (0xfc63, (2881, 3)),
+ (0x3131, (1084, 1)),
+ (0xff6f, (4119, 1)),
(0x24b9, (790, 1)),
(0x32b1, (1554, 2)),
- (0x1d66a, (4885, 1)),
- (0x2475, (590, 3)),
- (0x1d403, (4294, 1)),
- (0x1db6, (224, 1)),
- (0x1d473, (4405, 1)),
+ (0xfda0, (3570, 3)),
+ (0x1d72e, (5079, 1)),
+ (0x1d64d, (4856, 1)),
+ (0xfb8f, (2552, 1)),
+ (0x1e03c, (5299, 1)),
(0xfd39, (3326, 2)),
(0xfd8b, (3513, 3)),
(0x1079a, (4259, 1)),
(0xfb95, (2558, 1)),
(0x107af, (4280, 1)),
- (0xff35, (4061, 1)),
- (0x209b, (361, 1)),
- (0x319e, (1190, 1)),
+ (0x1f16c, (5642, 2)),
+ (0x1d793, (5180, 1)),
(0x1d437, (4346, 1)),
- (0x10788, (4241, 1)),
- (0x1ee22, (5319, 1)),
+ (0x3282, (1507, 1)),
+ (0xbe, (21, 3)),
+ (0x2c7d, (853, 1)),
(0xfec8, (3942, 1)),
- (0x1d52d, (4575, 1)),
- (0xfd79, (3459, 3)),
+ (0xfc99, (2998, 3)),
+ (0x337d, (2111, 2)),
(0x3290, (1521, 1)),
- (0x32ef, (1652, 1)),
(0x2f0d, (870, 1)),
- (0x1d6a1, (4940, 1)),
- (0x1d6b8, (4961, 1)),
- (0xfc70, (2914, 2)),
- (0xfcb6, (3059, 2)),
- (0x2f11, (874, 1)),
- (0x1d781, (5162, 1)),
- (0x1d6d1, (4986, 1)),
- (0x3305, (1692, 3)),
+ (0x1d6be, (4967, 1)),
+ (0x1d5c6, (4721, 1)),
+ (0xff38, (4064, 1)),
+ (0xfda9, (3597, 3)),
+ (0x1d690, (4923, 1)),
+ (0x1d42d, (4336, 1)),
+ (0x1d524, (4566, 1)),
+ (0x3f5, (108, 1)),
+ (0x1d68f, (4922, 1)),
(0x1d5af, (4698, 1)),
- (0x1d431, (4340, 1)),
+ (0xfd5e, (3378, 3)),
(0xfef7, (3993, 3)),
(0x33e8, (2367, 2)),
- (0xfcc5, (3089, 2)),
- (0x24a9, (748, 3)),
- (0x1d38, (147, 1)),
- (0xfb9a, (2563, 1)),
- (0xfb21, (2478, 1)),
- (0x1f245, (5649, 3)),
- (0x33ee, (2384, 3)),
- (0x1d685, (4912, 1)),
+ (0x1d4cc, (4483, 1)),
+ (0x1d42f, (4338, 1)),
+ (0xfe10, (3757, 1)),
+ (0x1d57e, (4649, 1)),
+ (0x107b7, (4287, 1)),
+ (0x1d499, (4443, 1)),
+ (0x1ee0f, (5363, 1)),
+ (0xfc96, (2990, 2)),
(0x1d4d2, (4489, 1)),
- (0x328a, (1515, 1)),
- (0x1d694, (4927, 1)),
- (0x1d7b9, (5218, 1)),
+ (0xffe9, (4229, 1)),
+ (0xffa5, (4173, 1)),
+ (0x3299, (1530, 1)),
(0x1d5c4, (4719, 1)),
- (0x1d6b6, (4959, 1)),
- (0x2f4d, (934, 1)),
+ (0xfe5c, (3815, 1)),
+ (0x17f, (34, 1)),
(0x1d7ea, (5265, 1)),
- (0x33d0, (2311, 2)),
+ (0x1d4b0, (4458, 1)),
(0x1d5be, (4713, 1)),
(0x33d9, (2334, 3)),
(0x32e7, (1644, 1)),
- (0x1d4e3, (4506, 1)),
+ (0x1d6e2, (5003, 1)),
+ (0xffad, (4181, 1)),
(0xfcae, (3043, 2)),
- (0x3147, (1106, 1)),
- (0x2121, (403, 3)),
- (0x1d561, (4620, 1)),
- (0x1d41e, (4321, 1)),
+ (0xfcda, (3131, 2)),
+ (0xfc1b, (2732, 2)),
+ (0x2f62, (955, 1)),
+ (0x320a, (1222, 3)),
(0x3f9, (109, 1)),
- (0xff86, (4142, 1)),
(0xfdc1, (3669, 3)),
- (0xff20, (4040, 1)),
- (0xfedd, (3963, 1)),
- (0x1f228, (5614, 1)),
- (0x1d6ae, (4951, 1)),
- (0xff65, (4109, 1)),
- (0xfc78, (2930, 2)),
- (0xfdaf, (3615, 3)),
- (0x1f11b, (5483, 3)),
- (0xfc51, (2840, 2)),
- (0x3223, (1316, 3)),
- (0x2f3f, (920, 1)),
- (0x1d4e9, (4512, 1)),
+ (0x2f72, (971, 1)),
+ (0x316d, (1144, 1)),
+ (0x322b, (1340, 3)),
+ (0x2157, (457, 3)),
+ (0x1d659, (4868, 1)),
+ (0x1d3c, (150, 1)),
+ (0x333e, (1923, 4)),
+ (0x217e, (541, 1)),
+ (0x1f11b, (5545, 3)),
+ (0x1ee74, (5429, 1)),
+ (0x1d458, (4378, 1)),
+ (0xfbfa, (2663, 3)),
(0xfeb3, (3921, 1)),
(0xfb5f, (2504, 1)),
+ (0x2fc9, (1058, 1)),
(0x315a, (1125, 1)),
- (0xedd, (126, 2)),
- (0x2e0, (83, 1)),
+ (0x1d4a9, (4452, 1)),
+ (0xfd31, (3310, 2)),
(0x3139, (1092, 1)),
- (0x1c4, (35, 3)),
+ (0x1db0, (218, 1)),
(0x1d4f3, (4522, 1)),
- (0x24c8, (805, 1)),
- (0xfd1a, (3264, 2)),
- (0xfbdd, (2601, 2)),
- (0xfe57, (3810, 1)),
- (0x1ee94, (5395, 1)),
- (0x1d6d7, (4992, 1)),
- (0xfdf5, (3708, 4)),
- (0x1f13c, (5549, 1)),
+ (0xfccf, (3109, 2)),
+ (0xfb80, (2537, 1)),
+ (0xfc6e, (2910, 2)),
+ (0x1d768, (5137, 1)),
+ (0x2b6, (68, 1)),
+ (0x333a, (1905, 4)),
+ (0x1d7c9, (5234, 1)),
+ (0x1f13c, (5611, 1)),
(0x1d6a2, (4941, 1)),
(0x2006, (281, 1)),
(0x1d445, (4360, 1)),
- (0x2fc4, (1053, 1)),
- (0x2f0a, (867, 1)),
- (0x3180, (1163, 1)),
- (0x2f14, (877, 1)),
- (0xfe6a, (3828, 1)),
- (0x1d765, (5134, 1)),
- (0xfe59, (3812, 1)),
+ (0x1d763, (5132, 1)),
+ (0x1d5fa, (4773, 1)),
+ (0x3241, (1406, 3)),
+ (0xfe4a, (3795, 2)),
+ (0x326d, (1465, 1)),
+ (0x1d6c2, (4971, 1)),
+ (0xfd7d, (3471, 3)),
(0x3370, (2080, 3)),
- (0x1d718, (5057, 1)),
+ (0x1d6bb, (4964, 1)),
(0x1d78f, (5176, 1)),
- (0xfb00, (2451, 2)),
- (0x1d6ac, (4949, 1)),
+ (0x1d4e6, (4509, 1)),
+ (0xff12, (4026, 1)),
(0xfb05, (2463, 2)),
- (0x1ee1b, (5313, 1)),
- (0x216a, (504, 2)),
- (0x1d628, (4819, 1)),
- (0x32a3, (1540, 1)),
- (0x3366, (2050, 3)),
- (0x1d514, (4552, 1)),
+ (0x1ee1b, (5375, 1)),
+ (0x1d609, (4788, 1)),
+ (0xfe79, (3844, 2)),
+ (0xfbf6, (2651, 3)),
+ (0x1d780, (5161, 1)),
+ (0xfd38, (3324, 2)),
(0x1d4de, (4501, 1)),
(0x3182, (1165, 1)),
- (0x1d546, (4597, 1)),
- (0x1d7f0, (5271, 1)),
- (0x1d458, (4378, 1)),
- (0xfba4, (2573, 2)),
- (0x3225, (1322, 3)),
- (0x1ee15, (5307, 1)),
- (0x1d4af, (4457, 1)),
- (0xfc7e, (2942, 2)),
- (0x1d6f4, (5021, 1)),
- (0x1d7ed, (5268, 1)),
- (0x1d5fd, (4776, 1)),
- (0x3240, (1403, 3)),
- (0x3295, (1526, 1)),
- (0x2fc8, (1057, 1)),
- (0x1d4d9, (4496, 1)),
- (0x1d57c, (4647, 1)),
- (0x1ee79, (5371, 1)),
- (0xfd8c, (3516, 3)),
+ (0xfe48, (3792, 1)),
+ (0xfe5e, (3817, 1)),
+ (0x1ee1c, (5376, 1)),
+ (0x3319, (1774, 6)),
+ (0x323f, (1400, 3)),
+ (0x2f03, (860, 1)),
+ (0x1d566, (4625, 1)),
+ (0xfcf3, (3184, 3)),
+ (0x1d581, (4652, 1)),
+ (0x1d6eb, (5012, 1)),
+ (0x1e047, (5310, 1)),
+ (0x3301, (1675, 4)),
+ (0x2fa8, (1025, 1)),
+ (0x249b, (706, 3)),
+ (0xff70, (4120, 1)),
+ (0x1f219, (5661, 1)),
+ (0x1d441, (4356, 1)),
+ (0xfce9, (3163, 2)),
(0x32cd, (1613, 3)),
+ (0x1d70d, (5046, 1)),
(0xff61, (4105, 1)),
- (0x210f, (388, 1)),
+ (0x2496, (691, 3)),
(0x1d416, (4313, 1)),
- (0xff90, (4152, 1)),
+ (0x3390, (2154, 2)),
(0x1d756, (5119, 1)),
- (0x1d78b, (5172, 1)),
- (0xfd13, (3250, 2)),
+ (0x1e04a, (5313, 1)),
+ (0xfc6b, (2904, 2)),
(0xfc50, (2838, 2)),
- (0x24af, (766, 3)),
(0x1d572, (4637, 1)),
- (0xfc87, (2960, 2)),
- (0x1d629, (4820, 1)),
- (0x1d693, (4926, 1)),
- (0x24ca, (807, 1)),
- (0x1f21e, (5604, 1)),
+ (0xffce, (4209, 1)),
+ (0x2f12, (875, 1)),
+ (0xff95, (4157, 1)),
+ (0xfb99, (2562, 1)),
+ (0xff46, (4078, 1)),
+ (0xfdb7, (3639, 3)),
(0x2156, (454, 3)),
- (0x1d452, (4373, 1)),
- (0x203c, (306, 2)),
- (0x1d46a, (4396, 1)),
- (0x10781, (4235, 1)),
- (0x3226, (1325, 3)),
- (0x1d72e, (5079, 1)),
- (0x1d621, (4812, 1)),
- (0xfb8d, (2550, 1)),
- (0x1d510, (4548, 1)),
- (0x3239, (1382, 3)),
+ (0xff52, (4090, 1)),
+ (0x1f241, (5699, 3)),
+ (0x1d40f, (4306, 1)),
+ (0x1d440, (4355, 1)),
+ (0x3f1, (105, 1)),
+ (0x2078, (327, 1)),
+ (0x1d66c, (4887, 1)),
+ (0x1f13e, (5613, 1)),
+ (0xfc24, (2750, 2)),
+ (0xfe96, (3892, 1)),
(0x1d460, (4386, 1)),
(0x1d6c9, (4978, 1)),
(0x3330, (1865, 3)),
(0x2f95, (1006, 1)),
- (0x1fbf4, (5667, 1)),
- (0xff9a, (4162, 1)),
- (0x1d635, (4832, 1)),
+ (0x1d71e, (5063, 1)),
+ (0x1d51e, (4560, 1)),
+ (0x10782, (4236, 1)),
(0xfc26, (2754, 2)),
- (0x1d763, (5132, 1)),
- (0x32bf, (1582, 2)),
- (0xfd53, (3345, 3)),
- (0xfc5d, (2864, 2)),
+ (0xfd1e, (3272, 2)),
+ (0x2145, (430, 1)),
+ (0x327b, (1492, 2)),
+ (0xfcbc, (3071, 2)),
(0xff39, (4065, 1)),
(0xfc9c, (3007, 2)),
- (0x321e, (1301, 6)),
- (0xfb01, (2453, 2)),
- (0x212c, (410, 1)),
- (0x1d7b6, (5215, 1)),
- (0x1d67, (192, 1)),
- (0xfe41, (3787, 1)),
- (0x1f12a, (5528, 3)),
- (0x32b2, (1556, 2)),
+ (0xfe62, (3821, 1)),
+ (0x1d41c, (4319, 1)),
+ (0x1d691, (4924, 1)),
+ (0x1d488, (4426, 1)),
+ (0x1ee4f, (5406, 1)),
+ (0x1d5e4, (4751, 1)),
+ (0x1e03d, (5300, 1)),
+ (0xfd55, (3351, 3)),
(0xfcbd, (3073, 2)),
(0x3297, (1528, 1)),
- (0x1d5d2, (4733, 1)),
- (0x1d607, (4786, 1)),
- (0xff97, (4159, 1)),
- (0x1d53c, (4589, 1)),
- (0x32cb, (1608, 3)),
- (0x1eeaf, (5415, 1)),
- (0xfcdd, (3137, 2)),
- (0x33fa, (2420, 3)),
- (0xfd6e, (3426, 3)),
- (0x3369, (2059, 3)),
- (0x3265, (1457, 1)),
+ (0x1d5e0, (4747, 1)),
+ (0x3192, (1178, 1)),
+ (0x32d2, (1623, 1)),
+ (0x2f9e, (1015, 1)),
+ (0xfd1a, (3264, 2)),
+ (0x32e6, (1643, 1)),
+ (0x1eeaf, (5477, 1)),
+ (0x24d6, (819, 1)),
+ (0xfef4, (3986, 1)),
+ (0x1ee72, (5428, 1)),
+ (0x1d5d3, (4734, 1)),
+ (0xfd0c, (3236, 2)),
(0x1d66b, (4886, 1)),
- (0xfc07, (2692, 2)),
- (0x32eb, (1648, 1)),
- (0xfd56, (3354, 3)),
+ (0xff5a, (4098, 1)),
+ (0xfe57, (3810, 1)),
+ (0xfb6a, (2515, 1)),
(0x1d44c, (4367, 1)),
- (0x1d68c, (4919, 1)),
- (0x10787, (4240, 1)),
+ (0x2474, (587, 3)),
+ (0xfdb3, (3627, 3)),
(0xfb92, (2555, 1)),
- (0xff44, (4076, 1)),
- (0xfc23, (2748, 2)),
- (0x1d570, (4635, 1)),
- (0x1ee52, (5346, 1)),
+ (0x2098, (358, 1)),
+ (0x1d5a9, (4692, 1)),
+ (0x24b6, (787, 1)),
+ (0x1d626, (4817, 1)),
(0xab69, (2450, 1)),
- (0x3140, (1099, 1)),
- (0xfd70, (3432, 3)),
- (0xfeac, (3914, 1)),
+ (0x1d630, (4827, 1)),
+ (0xfb6c, (2517, 1)),
+ (0x1d76f, (5144, 1)),
(0x3155, (1120, 1)),
- (0xfc14, (2718, 2)),
- (0xfc2d, (2768, 2)),
+ (0xfe97, (3893, 1)),
+ (0x1dbb, (229, 1)),
(0x33bd, (2268, 2)),
(0x1d54c, (4600, 1)),
- (0xfbff, (2672, 1)),
- (0x3d0, (95, 1)),
- (0x1d574, (4639, 1)),
- (0x1f112, (5456, 3)),
- (0x1f21a, (5600, 1)),
- (0x247f, (622, 4)),
+ (0x2124, (408, 1)),
+ (0x33d2, (2315, 3)),
+ (0x3236, (1373, 3)),
+ (0x1f112, (5518, 3)),
+ (0x1d37, (146, 1)),
+ (0x132, (24, 2)),
(0x329e, (1535, 1)),
- (0x1f22f, (5621, 1)),
- (0xfeae, (3916, 1)),
- (0x107b5, (4285, 1)),
+ (0x1d65a, (4869, 1)),
+ (0xfdf8, (3720, 4)),
+ (0x385, (92, 3)),
(0x2f71, (970, 1)),
- (0x1d4c0, (4472, 1)),
- (0xfe13, (3760, 1)),
- (0x1d489, (4427, 1)),
+ (0x1ee61, (5415, 1)),
+ (0xfe3d, (3783, 1)),
+ (0x3153, (1118, 1)),
(0xfccc, (3103, 2)),
(0x3203, (1201, 3)),
- (0x1d476, (4408, 1)),
- (0x3309, (1708, 3)),
+ (0xfe3f, (3785, 1)),
+ (0x1d550, (4604, 1)),
+ (0x1d6e9, (5010, 1)),
(0x1d675, (4896, 1)),
- (0xfcf6, (3192, 2)),
- (0x1d524, (4566, 1)),
- (0xfe9f, (3901, 1)),
+ (0x3f4, (107, 1)),
+ (0x1d53e, (4591, 1)),
+ (0x315c, (1127, 1)),
(0x32ac, (1549, 1)),
(0x24cd, (810, 1)),
- (0x1d51b, (4558, 1)),
(0xffe6, (4227, 1)),
- (0xffc7, (4204, 1)),
- (0x2003, (278, 1)),
- (0xaa, (3, 1)),
+ (0x3166, (1137, 1)),
+ (0x1ee6d, (5423, 1)),
+ (0x24d3, (816, 1)),
(0xffee, (4234, 1)),
(0x1d777, (5152, 1)),
+ (0xff55, (4093, 1)),
(0x1d5de, (4745, 1)),
- (0x3324, (1820, 4)),
- (0xfba9, (2580, 1)),
- (0x215b, (469, 3)),
- (0x329c, (1533, 1)),
- (0x2fd4, (1069, 1)),
- (0x2f87, (992, 1)),
+ (0x1d593, (4670, 1)),
+ (0x1ee2b, (5386, 1)),
+ (0x1d486, (4424, 1)),
+ (0xfd71, (3435, 3)),
+ (0xfef9, (3999, 3)),
(0x326a, (1462, 1)),
+ (0x33d6, (2325, 3)),
(0x3345, (1947, 3)),
- (0x1ee5b, (5350, 1)),
- (0xfd50, (3336, 3)),
- (0x1d472, (4404, 1)),
+ (0x2d9, (73, 2)),
+ (0xfbe4, (2609, 1)),
+ (0x3149, (1108, 1)),
(0x1d40d, (4304, 1)),
- (0x2f4a, (931, 1)),
+ (0x1f235, (5689, 1)),
(0x1d6de, (4999, 1)),
- (0xfcc8, (3095, 2)),
- (0x1d7c2, (5227, 1)),
- (0x2fa3, (1020, 1)),
- (0xfd59, (3363, 3)),
+ (0x677, (116, 2)),
+ (0x1d656, (4865, 1)),
+ (0x1d3d, (151, 1)),
+ (0x1d6f0, (5017, 1)),
(0xfe34, (3774, 1)),
(0x1d69c, (4935, 1)),
- (0x1d501, (4536, 1)),
- (0x2005, (280, 1)),
+ (0xfe76, (3838, 2)),
+ (0x1daf, (217, 1)),
(0x1c5, (38, 3)),
- (0x1078b, (4244, 1)),
- (0x323d, (1394, 3)),
- (0xaf, (4, 2)),
+ (0x1d739, (5090, 1)),
+ (0x33e4, (2359, 2)),
+ (0x1d6ed, (5014, 1)),
(0x1d6d8, (4993, 1)),
- (0x1d4ac, (4455, 1)),
+ (0xfc81, (2948, 2)),
(0xfecd, (3947, 1)),
- (0x3395, (2168, 2)),
- (0x1d67a, (4901, 1)),
- (0x1d74a, (5107, 1)),
+ (0x1d726, (5071, 1)),
+ (0x1e051, (5320, 1)),
+ (0xfc2c, (2766, 2)),
(0x1d6f3, (5020, 1)),
- (0x10793, (4252, 1)),
- (0x322e, (1349, 3)),
+ (0xfc3b, (2796, 2)),
+ (0xfce7, (3159, 2)),
(0x33b1, (2244, 2)),
- (0x3154, (1119, 1)),
+ (0x2161, (484, 2)),
(0xfe89, (3875, 2)),
- (0x1d786, (5167, 1)),
+ (0x1d63f, (4842, 1)),
+ (0x1d5c9, (4724, 1)),
(0x3266, (1458, 1)),
- (0x1d4b8, (4466, 1)),
- (0x1d7b2, (5211, 1)),
- (0x1d5e2, (4749, 1)),
- (0xffdc, (4219, 1)),
- (0xffd7, (4216, 1)),
- (0x1f139, (5546, 1)),
- (0x1d49, (163, 1)),
- (0x1d7e1, (5256, 1)),
- (0xfd0a, (3232, 2)),
+ (0xfd00, (3212, 2)),
+ (0x1d4c, (166, 1)),
+ (0x1d7e3, (5258, 1)),
+ (0x1d62b, (4822, 1)),
+ (0xfdae, (3612, 3)),
+ (0x339c, (2182, 2)),
+ (0xfc8c, (2970, 2)),
+ (0x1d449, (4364, 1)),
(0xffe2, (4222, 1)),
- (0x336d, (2071, 3)),
- (0xfbda, (2598, 1)),
- (0x247d, (614, 4)),
+ (0x222f, (551, 2)),
+ (0xfc62, (2878, 3)),
+ (0x1d70a, (5043, 1)),
(0x2fb3, (1036, 1)),
- (0x1f242, (5640, 3)),
- (0x3244, (1415, 1)),
- (0xfece, (3948, 1)),
- (0x24ac, (757, 3)),
- (0xfc92, (2982, 2)),
- (0x2470, (579, 2)),
- (0x1eea3, (5405, 1)),
+ (0x1f239, (5693, 1)),
+ (0x32dc, (1633, 1)),
+ (0x1d7ad, (5206, 1)),
+ (0x3303, (1684, 3)),
+ (0x248b, (664, 2)),
+ (0x3168, (1139, 1)),
+ (0xfdf0, (3690, 3)),
(0xff8b, (4147, 1)),
- (0x1079e, (4263, 1)),
+ (0x1d5c1, (4716, 1)),
(0x320f, (1238, 4)),
- (0x1f118, (5474, 3)),
- (0x1f133, (5540, 1)),
- (0x1d78c, (5173, 1)),
- (0x1d5a5, (4688, 1)),
- (0x1d776, (5151, 1)),
- (0xfec3, (3937, 1)),
- (0xff9e, (4166, 1)),
- (0x2f92, (1003, 1)),
- (0x1d58, (177, 1)),
- (0xfda1, (3573, 3)),
- (0x3207, (1213, 3)),
+ (0x1f145, (5620, 1)),
+ (0x1f118, (5536, 3)),
+ (0xffa0, (4168, 1)),
+ (0x335a, (2022, 2)),
+ (0x1d632, (4829, 1)),
+ (0x33eb, (2375, 3)),
+ (0x2120, (401, 2)),
+ (0x24da, (823, 1)),
+ (0xff28, (4048, 1)),
+ (0xfeaa, (3912, 1)),
+ (0x2fad, (1030, 1)),
(0x20a8, (363, 2)),
- (0x1d4b2, (4460, 1)),
- (0x2c7d, (853, 1)),
- (0x3312, (1741, 4)),
- (0x1ee35, (5333, 1)),
- (0x1d486, (4424, 1)),
- (0xfdfb, (3745, 8)),
- (0xfb93, (2556, 1)),
+ (0x33f3, (2399, 3)),
+ (0x32e2, (1639, 1)),
+ (0x3318, (1770, 4)),
+ (0x1ee35, (5395, 1)),
+ (0x1d5cd, (4728, 1)),
+ (0x325f, (1450, 2)),
+ (0x3365, (2047, 3)),
(0x1d4f, (168, 1)),
- (0xff22, (4042, 1)),
- (0x1d406, (4297, 1)),
+ (0x24e7, (836, 1)),
+ (0xfc76, (2926, 2)),
+ (0xfedd, (3963, 1)),
(0xfcca, (3099, 2)),
- (0x1d7c4, (5229, 1)),
- (0x1f14e, (5571, 3)),
- (0x1ee89, (5385, 1)),
- (0x1d68d, (4920, 1)),
- (0x1d73b, (5092, 1)),
- (0x1d79f, (5192, 1)),
+ (0x208b, (346, 1)),
+ (0x1f14e, (5633, 3)),
+ (0x1ee89, (5447, 1)),
+ (0x217d, (540, 1)),
+ (0x1d770, (5145, 1)),
+ (0x1d4b8, (4466, 1)),
(0xfca5, (3025, 2)),
- (0x2084, (339, 1)),
- (0xff13, (4027, 1)),
+ (0x1d701, (5034, 1)),
+ (0x3253, (1426, 2)),
(0xfe8e, (3884, 1)),
- (0x1d6b2, (4955, 1)),
+ (0xfc56, (2850, 2)),
(0x1d469, (4395, 1)),
- (0x3284, (1509, 1)),
- (0x3343, (1940, 4)),
- (0x3322, (1814, 3)),
+ (0x3394, (2165, 3)),
+ (0xfbe2, (2607, 1)),
+ (0x2048, (312, 2)),
(0xfcf9, (3198, 2)),
- (0xfcfa, (3200, 2)),
- (0x1d6ff, (5032, 1)),
- (0x1d7f3, (5274, 1)),
+ (0xeb3, (122, 2)),
+ (0x2fc7, (1056, 1)),
+ (0x3376, (2095, 2)),
+ (0x10784, (4238, 1)),
(0x1d6ad, (4950, 1)),
- (0x2f78, (977, 1)),
(0xff80, (4136, 1)),
- (0x2486, (650, 4)),
- (0x32c2, (1588, 2)),
+ (0x1d498, (4442, 1)),
+ (0x1f141, (5616, 1)),
(0x33a5, (2205, 2)),
(0x1d683, (4910, 1)),
- (0x32d1, (1622, 1)),
- (0x1d5c9, (4724, 1)),
+ (0xfdba, (3648, 3)),
+ (0x2110, (389, 1)),
+ (0x1d6dc, (4997, 1)),
(0x1d4bf, (4471, 1)),
- (0xfc11, (2712, 2)),
- (0x32df, (1636, 1)),
- (0x1d7bd, (5222, 1)),
- (0x2f56, (943, 1)),
+ (0x1d7d6, (5245, 1)),
+ (0x1f226, (5674, 1)),
+ (0x1d60d, (4792, 1)),
(0x2025, (290, 2)),
+ (0x1f247, (5717, 3)),
(0xfe90, (3886, 1)),
- (0xfd0f, (3242, 2)),
- (0x24da, (823, 1)),
- (0x33d4, (2320, 2)),
- (0x1d648, (4851, 1)),
- (0xfc41, (2808, 2)),
- (0x328e, (1519, 1)),
+ (0x330d, (1721, 4)),
+ (0xfb5a, (2499, 1)),
+ (0x2fa7, (1024, 1)),
+ (0x33bb, (2264, 2)),
+ (0x1d70b, (5044, 1)),
+ (0x2dd, (81, 2)),
(0x1d795, (5182, 1)),
- (0xffa0, (4168, 1)),
- (0xff4a, (4082, 1)),
- (0x319c, (1188, 1)),
- (0xfd86, (3498, 3)),
- (0xfe3f, (3785, 1)),
- (0x1d582, (4653, 1)),
- (0xfc9b, (3004, 3)),
- (0x3243, (1412, 3)),
- (0xfccf, (3109, 2)),
- (0x1db9, (227, 1)),
- (0x1d7da, (5249, 1)),
- (0x3334, (1881, 6)),
- (0xfe51, (3805, 1)),
- (0x33c5, (2286, 2)),
+ (0x2488, (658, 2)),
+ (0xfc4c, (2830, 2)),
+ (0x1d599, (4676, 1)),
+ (0xfce3, (3151, 2)),
+ (0x1d5bb, (4710, 1)),
+ (0x2f8c, (997, 1)),
+ (0x1d7fe, (5285, 1)),
+ (0x1d42c, (4335, 1)),
+ (0xff78, (4128, 1)),
+ (0x1d67a, (4901, 1)),
+ (0x1d72c, (5077, 1)),
+ (0xff68, (4112, 1)),
+ (0x317a, (1157, 1)),
+ (0x1d70f, (5048, 1)),
(0x32c9, (1602, 3)),
- (0x24d5, (818, 1)),
- (0x1d7b5, (5214, 1)),
+ (0xedd, (126, 2)),
+ (0x1d5f1, (4764, 1)),
(0x1d4c2, (4474, 1)),
- (0x1d5d0, (4731, 1)),
- (0xfe49, (3793, 2)),
- (0xfed6, (3956, 1)),
+ (0xff24, (4044, 1)),
+ (0xff9a, (4162, 1)),
+ (0x1d671, (4892, 1)),
(0xffcf, (4210, 1)),
- (0x1d571, (4636, 1)),
- (0xfdf2, (3696, 4)),
- (0xfc28, (2758, 2)),
- (0x1d5ae, (4697, 1)),
+ (0x2f0b, (868, 1)),
+ (0x32cc, (1611, 2)),
+ (0x1d6fa, (5027, 1)),
+ (0x1d616, (4801, 1)),
(0xfb15, (2471, 2)),
- (0x1fc0, (242, 2)),
+ (0xfee7, (3973, 1)),
(0xff96, (4158, 1)),
+ (0x3d2, (97, 1)),
(0x1d5d9, (4740, 1)),
- (0x336f, (2077, 3)),
(0x1ffd, (271, 2)),
- (0x2f2b, (900, 1)),
- (0x1d47d, (4415, 1)),
+ (0xfbb1, (2589, 2)),
+ (0xfca3, (3021, 2)),
(0x2f7f, (984, 1)),
(0x2f42, (923, 1)),
- (0x1d647, (4850, 1)),
- (0xff6f, (4119, 1)),
- (0x334a, (1964, 6)),
- (0x331b, (1786, 4)),
- (0xfca2, (3019, 2)),
- (0xfd62, (3390, 3)),
- (0x1d57b, (4646, 1)),
- (0x107a4, (4269, 1)),
+ (0xfc27, (2756, 2)),
+ (0x1eea7, (5470, 1)),
+ (0x212d, (411, 1)),
+ (0x1d35, (144, 1)),
+ (0x1e05c, (5331, 1)),
+ (0xfcb2, (3051, 2)),
+ (0xfc7e, (2942, 2)),
+ (0x2f9d, (1014, 1)),
(0x33f9, (2417, 3)),
- (0x1f11d, (5489, 3)),
+ (0x1d606, (4785, 1)),
(0x1d55b, (4614, 1)),
(0x1d62f, (4826, 1)),
(0x2f9f, (1016, 1)),
+ (0x1dbc, (230, 1)),
(0xff3b, (4067, 1)),
- (0x1d4ff, (4534, 1)),
- (0xfe3a, (3780, 1)),
- (0xffed, (4233, 1)),
+ (0x32d8, (1629, 1)),
+ (0x1d568, (4627, 1)),
(0x33e5, (2361, 2)),
+ (0x2f82, (987, 1)),
(0xfea7, (3909, 1)),
- (0x1d4fd, (4532, 1)),
- (0x337c, (2109, 2)),
- (0xfba7, (2578, 1)),
- (0xfcb9, (3065, 2)),
+ (0x1d55d, (4616, 1)),
+ (0x1d4ac, (4455, 1)),
+ (0x24b2, (775, 3)),
+ (0xfd37, (3322, 2)),
(0x2f80, (985, 1)),
- (0xfb6c, (2517, 1)),
(0x1d4df, (4502, 1)),
- (0x1d45f, (4385, 1)),
- (0x1d7b3, (5212, 1)),
+ (0xfb73, (2524, 1)),
+ (0xfdc7, (3687, 3)),
+ (0x1d48, (162, 1)),
(0xfbb0, (2587, 2)),
- (0x2026, (292, 3)),
- (0x1ee03, (5290, 1)),
- (0xff7e, (4134, 1)),
- (0x314a, (1109, 1)),
- (0x1d625, (4816, 1)),
- (0x322d, (1346, 3)),
- (0x1ee7b, (5373, 1)),
- (0xfc0a, (2698, 2)),
- (0x314d, (1112, 1)),
+ (0x1d704, (5037, 1)),
+ (0x1d481, (4419, 1)),
+ (0x2f5b, (948, 1)),
+ (0x1e034, (5291, 1)),
+ (0x2b2, (64, 1)),
+ (0x1d41d, (4320, 1)),
+ (0xfcce, (3107, 2)),
+ (0x33a8, (2213, 4)),
(0x1d6e4, (5005, 1)),
- (0x3135, (1088, 1)),
+ (0x1d7c7, (5232, 1)),
(0x32b6, (1564, 2)),
- (0x3208, (1216, 3)),
+ (0x3218, (1274, 4)),
(0xfdf9, (3724, 3)),
- (0x1d636, (4833, 1)),
- (0xfcea, (3165, 2)),
- (0x2f60, (953, 1)),
- (0x2002, (277, 1)),
- (0x1d788, (5169, 1)),
- (0x32e5, (1642, 1)),
- (0x1079d, (4262, 1)),
- (0x1eebb, (5427, 1)),
- (0x1d4f4, (4523, 1)),
- (0x1da6, (208, 1)),
- (0x1d450, (4371, 1)),
- (0x1d670, (4891, 1)),
- (0x2dd, (81, 2)),
+ (0xfd07, (3226, 2)),
+ (0xff69, (4113, 1)),
+ (0x3196, (1182, 1)),
+ (0x1d7ec, (5267, 1)),
+ (0xfcde, (3139, 2)),
+ (0x3274, (1478, 2)),
+ (0xfd11, (3246, 2)),
+ (0xfdb9, (3645, 3)),
+ (0xfccd, (3105, 2)),
+ (0x2fa2, (1019, 1)),
+ (0xfb21, (2478, 1)),
+ (0x1d401, (4292, 1)),
+ (0x1ee0d, (5361, 1)),
+ (0x338d, (2148, 2)),
(0xfd36, (3320, 2)),
(0xfc44, (2814, 2)),
- (0x1eeb5, (5421, 1)),
- (0xfcf2, (3181, 3)),
- (0xfd10, (3244, 2)),
- (0xfc8d, (2972, 2)),
- (0xfd09, (3230, 2)),
- (0xff16, (4030, 1)),
- (0x107b9, (4289, 1)),
- (0x3384, (2127, 2)),
- (0xfc0e, (2706, 2)),
- (0x2147, (432, 1)),
- (0x335d, (2028, 2)),
+ (0x1d573, (4638, 1)),
+ (0x327c, (1494, 5)),
+ (0x1d787, (5168, 1)),
+ (0x2f1d, (886, 1)),
+ (0x1d4ca, (4481, 1)),
+ (0x2f32, (907, 1)),
+ (0x1d443, (4358, 1)),
+ (0xfec5, (3939, 1)),
+ (0x1f237, (5691, 1)),
+ (0xfb9f, (2568, 1)),
+ (0x332e, (1855, 6)),
+ (0x24cc, (809, 1)),
(0x2162, (486, 3)),
- (0xfd0e, (3240, 2)),
- (0x1d5ad, (4696, 1)),
+ (0xffb6, (4190, 1)),
(0xfb9b, (2564, 1)),
- (0xfeb9, (3927, 1)),
+ (0x1fce, (250, 3)),
(0x318e, (1177, 1)),
+ (0x32fa, (1663, 1)),
(0x32db, (1632, 1)),
- (0x1d74d, (5110, 1)),
- (0x319a, (1186, 1)),
+ (0xfee5, (3971, 1)),
+ (0xfe41, (3787, 1)),
(0x1d5df, (4746, 1)),
- (0x1f108, (5444, 2)),
- (0x1d6f5, (5022, 1)),
- (0xff8e, (4150, 1)),
- (0x1d441, (4356, 1)),
+ (0x33f6, (2408, 3)),
+ (0x1d585, (4656, 1)),
+ (0xfd92, (3528, 3)),
(0x1d5b, (180, 1)),
- (0xff10, (4024, 1)),
- (0x1d71e, (5063, 1)),
+ (0x1078a, (4243, 1)),
+ (0x337a, (2105, 2)),
+ (0xfdc3, (3675, 3)),
(0x1078e, (4247, 1)),
- (0x33cd, (2305, 2)),
(0xff63, (4107, 1)),
- (0xfdb4, (3630, 3)),
- (0x1d4d, (167, 1)),
- (0x1f22c, (5618, 1)),
- (0xfc89, (2964, 2)),
+ (0xfedf, (3965, 1)),
+ (0xfd5c, (3372, 3)),
+ (0x1e043, (5306, 1)),
+ (0x1d47b, (4413, 1)),
+ (0xfe18, (3765, 1)),
(0x1d7c5, (5230, 1)),
- (0xff5e, (4102, 1)),
- (0x1d417, (4314, 1)),
- (0xfb73, (2524, 1)),
- (0x2f13, (876, 1)),
- (0x1d783, (5164, 1)),
- (0x2155, (451, 3)),
- (0x1d6dc, (4997, 1)),
- (0x1d7a2, (5195, 1)),
- (0x33d3, (2318, 2)),
- (0x1d5c7, (4722, 1)),
- (0xfd9c, (3558, 3)),
+ (0xfbda, (2598, 1)),
+ (0x1d59d, (4680, 1)),
+ (0x1e058, (5327, 1)),
+ (0x216a, (504, 2)),
+ (0x1d798, (5185, 1)),
+ (0x1ee37, (5397, 1)),
+ (0xfc22, (2746, 2)),
+ (0x3171, (1148, 1)),
+ (0xfd66, (3402, 3)),
+ (0x1eea2, (5466, 1)),
+ (0xfb88, (2545, 1)),
(0x1d6b4, (4957, 1)),
- (0xfd1e, (3272, 2)),
+ (0x32e3, (1640, 1)),
(0x208e, (349, 1)),
- (0xfe98, (3894, 1)),
- (0x1d69f, (4938, 1)),
- (0xfe7b, (3848, 2)),
- (0x1d456, (4376, 1)),
- (0x1d6ab, (4948, 1)),
+ (0x3223, (1316, 3)),
+ (0x3137, (1090, 1)),
+ (0x222c, (546, 2)),
+ (0x2f8b, (996, 1)),
+ (0x1f11a, (5542, 3)),
(0xfc4f, (2836, 2)),
(0x1d52b, (4573, 1)),
- (0x1d50d, (4545, 1)),
- (0x1d47f, (4417, 1)),
+ (0xfba5, (2575, 2)),
+ (0x1d465, (4391, 1)),
(0xff50, (4088, 1)),
- (0x33b4, (2250, 2)),
- (0xff9f, (4167, 1)),
- (0x213c, (425, 1)),
- (0xfd75, (3447, 3)),
- (0x2f74, (973, 1)),
- (0xfc93, (2984, 2)),
- (0x1d491, (4435, 1)),
- (0xfc2c, (2766, 2)),
+ (0xff2b, (4051, 1)),
+ (0xfc60, (2872, 3)),
+ (0x326e, (1466, 2)),
+ (0xfb78, (2529, 1)),
+ (0x2080, (335, 1)),
+ (0xfe37, (3777, 1)),
+ (0x1f243, (5705, 3)),
+ (0xfb01, (2453, 2)),
(0x32a1, (1538, 1)),
(0x1d6d9, (4994, 1)),
- (0xfed2, (3952, 1)),
- (0x10794, (4253, 1)),
- (0x314c, (1111, 1)),
- (0x1d523, (4565, 1)),
- (0x1db4, (222, 1)),
- (0x1d569, (4628, 1)),
- (0x316c, (1143, 1)),
- (0x1d5dd, (4744, 1)),
- (0x2a76, (849, 3)),
+ (0x2007, (282, 1)),
+ (0x321a, (1282, 4)),
+ (0x1d730, (5081, 1)),
+ (0xfb7a, (2531, 1)),
+ (0x3175, (1152, 1)),
+ (0x2136, (418, 1)),
+ (0x3355, (2007, 2)),
+ (0x32b5, (1562, 2)),
+ (0xfe3b, (3781, 1)),
+ (0xfd2a, (3296, 2)),
(0x24ad, (760, 3)),
- (0x1d7bc, (5221, 1)),
- (0x331f, (1800, 4)),
- (0x1d4f1, (4520, 1)),
- (0x1d678, (4899, 1)),
+ (0x1d471, (4403, 1)),
+ (0x3272, (1474, 2)),
+ (0x1d77b, (5156, 1)),
+ (0xfd68, (3408, 3)),
(0x1d65d, (4872, 1)),
- (0x1f138, (5545, 1)),
- (0x33b6, (2254, 2)),
+ (0x1f138, (5607, 1)),
+ (0x1e066, (5341, 1)),
(0x217c, (539, 1)),
- (0x2f70, (969, 1)),
(0x1d586, (4657, 1)),
- (0xbd, (18, 3)),
- (0x1d4ed, (4516, 1)),
- (0x1d52f, (4577, 1)),
- (0x3299, (1530, 1)),
+ (0x1d785, (5166, 1)),
+ (0x1d73d, (5094, 1)),
+ (0xfd53, (3345, 3)),
+ (0x208c, (347, 1)),
+ (0x3326, (1827, 3)),
(0x1d517, (4554, 1)),
- (0x1ee6f, (5363, 1)),
+ (0x1ee6f, (5425, 1)),
(0xfcb0, (3047, 2)),
- (0x675, (112, 2)),
- (0x328d, (1518, 1)),
- (0x3337, (1895, 3)),
- (0x334b, (1970, 3)),
- (0xfed0, (3950, 1)),
- (0x3131, (1084, 1)),
- (0xff17, (4031, 1)),
- (0x1f22d, (5619, 1)),
- (0xfd73, (3441, 3)),
- (0x1d78a, (5171, 1)),
- (0x1d454, (4375, 1)),
+ (0xfe19, (3766, 3)),
+ (0xfb25, (2482, 1)),
+ (0xff3c, (4068, 1)),
+ (0xfc7f, (2944, 2)),
+ (0x1d680, (4907, 1)),
+ (0xff47, (4079, 1)),
+ (0x3361, (2036, 2)),
+ (0x1d5e7, (4754, 1)),
+ (0x1e031, (5288, 1)),
+ (0x10791, (4250, 1)),
+ (0x1f125, (5575, 3)),
(0x1d716, (5055, 1)),
- (0x1d5ce, (4729, 1)),
- (0xfc4b, (2828, 2)),
- (0x332b, (1840, 6)),
- (0x1f16a, (5576, 2)),
+ (0xfe11, (3758, 1)),
+ (0x1d7cb, (5236, 1)),
+ (0x316a, (1141, 1)),
+ (0x1f16a, (5638, 2)),
(0x1d7af, (5208, 1)),
- (0xff6b, (4115, 1)),
- (0x1f218, (5598, 1)),
- (0x1d4f2, (4521, 1)),
- (0xfb6d, (2518, 1)),
- (0x211d, (400, 1)),
- (0xfeaa, (3912, 1)),
- (0xfed1, (3951, 1)),
- (0xfc9d, (3009, 2)),
- (0x1d7fe, (5285, 1)),
+ (0xfc2b, (2764, 2)),
+ (0xff1e, (4038, 1)),
+ (0x2fa6, (1023, 1)),
+ (0xfd6c, (3420, 3)),
+ (0x2116, (394, 2)),
+ (0x3327, (1830, 2)),
+ (0xfc21, (2744, 2)),
+ (0x1d30, (139, 1)),
+ (0x1d6fe, (5031, 1)),
(0xfc3c, (2798, 2)),
(0xfbf7, (2654, 3)),
- (0x1d653, (4862, 1)),
+ (0x1d66e, (4889, 1)),
(0xfe36, (3776, 1)),
- (0x3205, (1207, 3)),
- (0x3220, (1307, 3)),
- (0x1d7dc, (5251, 1)),
- (0x2f00, (857, 1)),
- (0x1d658, (4867, 1)),
- (0x1d5f0, (4763, 1)),
- (0x1f201, (5586, 2)),
- (0xfd24, (3284, 2)),
- (0x1d707, (5040, 1)),
+ (0x1d600, (4779, 1)),
+ (0x32c4, (1592, 2)),
+ (0xfcee, (3173, 2)),
+ (0xfea8, (3910, 1)),
+ (0x1d7cf, (5238, 1)),
+ (0x1e05d, (5332, 1)),
+ (0x1d682, (4909, 1)),
+ (0x2498, (697, 3)),
+ (0xfedc, (3962, 1)),
(0x1d6ec, (5013, 1)),
(0x2f1e, (887, 1)),
- (0xfcba, (3067, 2)),
- (0x1d541, (4593, 1)),
- (0x33f8, (2414, 3)),
+ (0x1d69d, (4936, 1)),
+ (0xfc55, (2848, 2)),
+ (0x1ee97, (5460, 1)),
(0x1d5bf, (4714, 1)),
- (0x1fbf7, (5670, 1)),
- (0x337a, (2105, 2)),
- (0x107a5, (4270, 1)),
- (0x1d7a0, (5193, 1)),
- (0x1d71b, (5060, 1)),
- (0xfe5e, (3817, 1)),
- (0x1d519, (4556, 1)),
- (0x1fbf9, (5672, 1)),
+ (0x207f, (334, 1)),
+ (0x1eeb4, (5482, 1)),
+ (0xfc38, (2790, 2)),
+ (0x1da7, (209, 1)),
+ (0x1d705, (5038, 1)),
+ (0x1d720, (5065, 1)),
+ (0x215b, (469, 3)),
+ (0x1d4fc, (4531, 1)),
+ (0x1e03f, (5302, 1)),
(0x1d59a, (4677, 1)),
- (0xff3e, (4070, 1)),
- (0x1f143, (5556, 1)),
- (0x1d4a5, (4450, 1)),
+ (0xfcfd, (3206, 2)),
+ (0x10781, (4235, 1)),
(0x2f9c, (1013, 1)),
- (0x1d4c, (166, 1)),
- (0x1d650, (4859, 1)),
- (0xff21, (4041, 1)),
- (0x24b4, (781, 3)),
+ (0x1d5b3, (4702, 1)),
+ (0x1d7a4, (5197, 1)),
+ (0x107a7, (4272, 1)),
+ (0xfb90, (2553, 1)),
+ (0x1d490, (4434, 1)),
(0x1d543, (4595, 1)),
(0x2f6a, (963, 1)),
- (0xfeb5, (3923, 1)),
+ (0x3366, (2050, 3)),
(0x1d414, (4311, 1)),
- (0x1d6df, (5000, 1)),
- (0x13f, (28, 2)),
- (0x334d, (1978, 4)),
- (0x334e, (1982, 4)),
- (0x1d5e9, (4756, 1)),
- (0xfc7d, (2940, 2)),
- (0xfbe3, (2608, 1)),
- (0x24d2, (815, 1)),
+ (0x1d633, (4830, 1)),
+ (0x335f, (2032, 2)),
+ (0x32a8, (1545, 1)),
+ (0x33cf, (2309, 2)),
+ (0xfefc, (4007, 2)),
+ (0x1d6a3, (4942, 1)),
+ (0xffba, (4194, 1)),
+ (0x1078d, (4246, 1)),
(0x1d6c4, (4973, 1)),
- (0xfc96, (2990, 2)),
+ (0x1e044, (5307, 1)),
(0x1d4aa, (4453, 1)),
- (0x1d578, (4643, 1)),
- (0x1f104, (5436, 2)),
+ (0x1d595, (4672, 1)),
+ (0x3331, (1868, 3)),
(0x1d7f7, (5278, 1)),
- (0x3278, (1486, 2)),
- (0xfc25, (2752, 2)),
- (0x1d75b, (5124, 1)),
- (0x1dbd, (231, 1)),
- (0x1d42c, (4335, 1)),
+ (0x1d6fb, (5028, 1)),
+ (0x1d49, (163, 1)),
+ (0x1d49e, (4447, 1)),
+ (0x1d411, (4308, 1)),
+ (0x2107, (380, 1)),
(0x205f, (320, 1)),
+ (0x1e038, (5295, 1)),
(0xfb4f, (2487, 2)),
- (0xfcad, (3041, 2)),
- (0x2fba, (1043, 1)),
- (0xfb76, (2527, 1)),
+ (0x1ee9a, (5463, 1)),
+ (0x1d43c, (4351, 1)),
(0x32ad, (1550, 1)),
- (0x1eea8, (5409, 1)),
+ (0x1d468, (4394, 1)),
(0x3184, (1167, 1)),
(0x3162, (1133, 1)),
- (0x1d9f, (201, 1)),
- (0xffce, (4209, 1)),
- (0x249a, (703, 3)),
+ (0x2f69, (962, 1)),
+ (0xfe81, (3859, 2)),
+ (0x1ee05, (5353, 1)),
(0xfea5, (3907, 1)),
- (0xfe40, (3786, 1)),
+ (0x32ba, (1572, 2)),
+ (0x32f0, (1653, 1)),
(0x1d7d9, (5248, 1)),
- (0x1d3f, (153, 1)),
- (0xfe83, (3863, 2)),
+ (0x1d4c0, (4472, 1)),
(0xfea3, (3905, 1)),
- (0x3389, (2138, 4)),
- (0x1d7f6, (5277, 1)),
- (0xff98, (4160, 1)),
- (0x1ee8f, (5390, 1)),
- (0x1ee0f, (5301, 1)),
- (0x1fc1, (244, 3)),
- (0xfbe1, (2606, 1)),
+ (0x321d, (1294, 7)),
+ (0x1d6c7, (4976, 1)),
+ (0x1fcf, (253, 3)),
+ (0x33bf, (2272, 2)),
+ (0x1d718, (5057, 1)),
+ (0x10790, (4249, 1)),
+ (0x1d501, (4536, 1)),
(0x1d610, (4795, 1)),
+ (0x32e0, (1637, 1)),
(0xfd21, (3278, 2)),
- (0xfd99, (3549, 3)),
- (0x1d598, (4675, 1)),
- (0xfcf7, (3194, 2)),
- (0x1ee18, (5310, 1)),
+ (0x1d6db, (4996, 1)),
+ (0x1f13d, (5612, 1)),
+ (0x3038, (1073, 1)),
+ (0x33a7, (2210, 3)),
(0xfd25, (3286, 2)),
- (0x2024, (289, 1)),
+ (0x1d7e1, (5256, 1)),
(0xffbd, (4197, 1)),
- (0x1ee8c, (5387, 1)),
- (0x2faf, (1032, 1)),
- (0xfeb2, (3920, 1)),
- (0x1d7f1, (5272, 1)),
- (0x3232, (1361, 3)),
- (0x325c, (1444, 2)),
+ (0x1ee8c, (5449, 1)),
+ (0x1ee08, (5356, 1)),
+ (0x33c3, (2282, 2)),
+ (0x1d51a, (4557, 1)),
+ (0x32bf, (1582, 2)),
(0x249e, (715, 3)),
- (0x1f210, (5589, 1)),
- (0x1d4d5, (4492, 1)),
- (0x337d, (2111, 2)),
+ (0x33c8, (2295, 2)),
+ (0x1f210, (5651, 1)),
+ (0x2179, (533, 1)),
+ (0x3222, (1313, 3)),
(0x1d782, (5163, 1)),
(0x10789, (4242, 1)),
- (0x1d6b9, (4962, 1)),
- (0x1d43d, (4352, 1)),
+ (0x3305, (1692, 3)),
+ (0xfe3a, (3780, 1)),
(0x1d631, (4828, 1)),
(0x3199, (1185, 1)),
- (0xfe85, (3867, 2)),
- (0xfc3d, (2800, 2)),
+ (0xffd4, (4213, 1)),
+ (0x209c, (362, 1)),
(0x3247, (1418, 1)),
(0xfc88, (2962, 2)),
- (0x1d402, (4293, 1)),
- (0x1d9c, (198, 1)),
- (0x1d7dd, (5252, 1)),
+ (0xffb9, (4193, 1)),
+ (0x1d46c, (4398, 1)),
+ (0x1d636, (4833, 1)),
(0x315f, (1130, 1)),
(0xfb8b, (2548, 1)),
- (0xab5d, (2447, 1)),
- (0x1d6bf, (4968, 1)),
- (0x1d4b4, (4462, 1)),
+ (0xb5, (10, 1)),
+ (0x1d419, (4316, 1)),
+ (0xfed5, (3955, 1)),
+ (0x1d6ca, (4979, 1)),
(0x339e, (2186, 2)),
- (0x1f111, (5453, 3)),
(0x1d641, (4844, 1)),
- (0xfe63, (3822, 1)),
- (0x32fa, (1663, 1)),
- (0x1ee36, (5334, 1)),
- (0x1d49b, (4445, 1)),
- (0x2f03, (860, 1)),
- (0xa7f9, (2445, 1)),
- (0x1079c, (4261, 1)),
- (0xfdba, (3648, 3)),
+ (0x1d6af, (4952, 1)),
+ (0x3288, (1513, 1)),
+ (0x2154, (448, 3)),
+ (0xfe8d, (3883, 1)),
+ (0x1d40b, (4302, 1)),
+ (0x1d607, (4786, 1)),
+ (0xff26, (4046, 1)),
+ (0x1d758, (5121, 1)),
(0xfc4e, (2834, 2)),
(0x3364, (2044, 3)),
- (0x1d490, (4434, 1)),
- (0xffec, (4232, 1)),
- (0x33db, (2339, 2)),
- (0x2e1, (84, 1)),
- (0x1d5ec, (4759, 1)),
+ (0x1d4f5, (4524, 1)),
+ (0x2fc6, (1055, 1)),
+ (0x1d5dc, (4743, 1)),
+ (0xfc5e, (2866, 3)),
+ (0xff36, (4062, 1)),
(0x24c5, (802, 1)),
- (0x3168, (1139, 1)),
+ (0x1d587, (4658, 1)),
(0x2091, (351, 1)),
+ (0x1d750, (5113, 1)),
(0x24b0, (769, 3)),
- (0x1d568, (4627, 1)),
- (0x1f122, (5504, 3)),
- (0x1d52e, (4576, 1)),
+ (0x1f122, (5566, 3)),
+ (0x3339, (1902, 3)),
+ (0x1e054, (5323, 1)),
(0x1d511, (4549, 1)),
- (0x2fb1, (1034, 1)),
- (0x3320, (1804, 5)),
+ (0x3335, (1887, 3)),
(0xffaa, (4178, 1)),
- (0x3164, (1135, 1)),
- (0x1d5e0, (4747, 1)),
+ (0x1f240, (5696, 3)),
+ (0x1d612, (4797, 1)),
+ (0x1d553, (4606, 1)),
(0x1d5aa, (4693, 1)),
- (0x3352, (1996, 2)),
- (0x1d4ec, (4515, 1)),
+ (0xaa, (3, 1)),
+ (0xff62, (4106, 1)),
(0x24de, (827, 1)),
- (0x32a4, (1541, 1)),
- (0x24e2, (831, 1)),
- (0x1d505, (4540, 1)),
+ (0x1d7e2, (5257, 1)),
+ (0xfe6a, (3828, 1)),
(0x2f6f, (968, 1)),
- (0x2f5a, (947, 1)),
- (0xff68, (4112, 1)),
+ (0xfd59, (3363, 3)),
+ (0x1f1, (56, 2)),
+ (0x1d33, (142, 1)),
(0x1078f, (4248, 1)),
- (0x2f23, (892, 1)),
- (0xfcd0, (3111, 2)),
- (0x3298, (1529, 1)),
- (0x3287, (1512, 1)),
- (0x1d53b, (4588, 1)),
+ (0x1d536, (4584, 1)),
+ (0x2f0a, (867, 1)),
+ (0x3244, (1415, 1)),
+ (0x246e, (575, 2)),
+ (0xfc85, (2956, 2)),
(0x32f3, (1656, 1)),
- (0x1d70c, (5045, 1)),
+ (0x1fbf4, (5729, 1)),
(0x1d643, (4846, 1)),
(0xfba0, (2569, 1)),
- (0x3157, (1122, 1)),
- (0xfe3e, (3784, 1)),
+ (0x1db1, (219, 1)),
+ (0x1d457, (4377, 1)),
(0x1d7d7, (5246, 1)),
(0x3172, (1149, 1)),
- (0x1d70a, (5043, 1)),
- (0xff60, (4104, 1)),
- (0x3138, (1091, 1)),
- (0x1d5a, (179, 1)),
- (0x1d676, (4897, 1)),
- (0x2048, (312, 2)),
+ (0x33b2, (2246, 2)),
+ (0x107aa, (4275, 1)),
+ (0x2f16, (879, 1)),
+ (0x1d731, (5082, 1)),
+ (0x1d725, (5070, 1)),
+ (0xfbf4, (2645, 3)),
(0x33f5, (2405, 3)),
- (0x2466, (562, 1)),
- (0x1d43e, (4353, 1)),
+ (0x339d, (2184, 2)),
+ (0xfcc4, (3087, 2)),
(0xfc1c, (2734, 2)),
- (0x1d70d, (5046, 1)),
- (0x213f, (428, 1)),
- (0xfc39, (2792, 2)),
- (0x1d608, (4787, 1)),
- (0x335c, (2026, 2)),
+ (0xff11, (4025, 1)),
+ (0x1d76d, (5142, 1)),
+ (0x1d61c, (4807, 1)),
+ (0x1d733, (5084, 1)),
+ (0x1d5c7, (4722, 1)),
(0xff81, (4137, 1)),
(0x2122, (406, 2)),
- (0x1d61a, (4805, 1)),
- (0x1d75e, (5127, 1)),
- (0x1d493, (4437, 1)),
- (0xfb9e, (2567, 1)),
- (0x1ee72, (5366, 1)),
+ (0x1d4ae, (4456, 1)),
+ (0x1f21d, (5665, 1)),
+ (0x1d47f, (4417, 1)),
+ (0x1d757, (5120, 1)),
+ (0xbc, (15, 3)),
+ (0x1d621, (4812, 1)),
(0xffe4, (4225, 1)),
(0xfec9, (3943, 1)),
- (0xfe58, (3811, 1)),
- (0x1ee84, (5380, 1)),
+ (0x1ee84, (5442, 1)),
+ (0xfd98, (3546, 3)),
(0x3161, (1132, 1)),
- (0x1d6ba, (4963, 1)),
- (0x1d7bf, (5224, 1)),
+ (0x213f, (428, 1)),
(0x1d9e, (200, 1)),
- (0x1f236, (5628, 1)),
- (0xff6c, (4116, 1)),
- (0x2fcc, (1061, 1)),
- (0x1d4cc, (4483, 1)),
- (0x1ee0b, (5297, 1)),
- (0x1d77d, (5158, 1)),
- (0x1d5e8, (4755, 1)),
+ (0x1d619, (4804, 1)),
+ (0x1d4d6, (4493, 1)),
+ (0x1d5c0, (4715, 1)),
+ (0x2f7b, (980, 1)),
+ (0x1ee0b, (5359, 1)),
+ (0x1d746, (5103, 1)),
+ (0xfceb, (3167, 2)),
+ (0xfef3, (3985, 1)),
(0xfcf4, (3187, 3)),
- (0x1d4ce, (4485, 1)),
- (0x1ee83, (5379, 1)),
- (0x1d70b, (5044, 1)),
- (0x1d4f6, (4525, 1)),
- (0x32dd, (1634, 1)),
- (0xfe56, (3809, 1)),
- (0x3264, (1456, 1)),
- (0x1ee64, (5355, 1)),
- (0x316e, (1145, 1)),
- (0x1d790, (5177, 1)),
- (0x339b, (2180, 2)),
- (0x3281, (1506, 1)),
- (0x1d54, (173, 1)),
+ (0xfe7a, (3846, 2)),
+ (0x215c, (472, 3)),
+ (0x1d4fd, (4532, 1)),
+ (0xfba7, (2578, 1)),
+ (0xfd3c, (3332, 2)),
+ (0x1d46a, (4396, 1)),
+ (0x2163, (489, 2)),
+ (0x1ee64, (5417, 1)),
+ (0x1d692, (4925, 1)),
+ (0x1d648, (4851, 1)),
+ (0x1d482, (4420, 1)),
+ (0x1d576, (4641, 1)),
+ (0x1d717, (5056, 1)),
(0xfe30, (3769, 2)),
- (0x3211, (1246, 4)),
- (0x24ab, (754, 3)),
+ (0x1f232, (5686, 1)),
+ (0xfc77, (2928, 2)),
(0x1d668, (4883, 1)),
- (0x3271, (1472, 2)),
+ (0x2146, (431, 1)),
(0xa8, (1, 2)),
- (0x1d61, (186, 1)),
+ (0xfb93, (2556, 1)),
(0x1d5ef, (4762, 1)),
- (0xfed8, (3958, 1)),
- (0x1d5e1, (4748, 1)),
- (0x33e1, (2353, 2)),
- (0x2ef3, (856, 1)),
+ (0xfbfd, (2670, 1)),
+ (0x107ab, (4276, 1)),
+ (0x1e063, (5338, 1)),
+ (0x1d470, (4402, 1)),
(0x3356, (2009, 6)),
- (0x3331, (1868, 3)),
- (0xfd6d, (3423, 3)),
- (0xfd74, (3444, 3)),
+ (0x1d4c5, (4476, 1)),
+ (0xfbe7, (2612, 1)),
+ (0x24ea, (839, 1)),
+ (0x1d519, (4556, 1)),
(0x1d654, (4863, 1)),
- (0x107ac, (4277, 1)),
+ (0x2f6d, (966, 1)),
(0x1d518, (4555, 1)),
- (0x2f47, (928, 1)),
- (0x3230, (1355, 3)),
+ (0x1d639, (4836, 1)),
(0xfd52, (3342, 3)),
- (0x1d7a9, (5202, 1)),
+ (0x1d79f, (5192, 1)),
+ (0x1d775, (5150, 1)),
(0x3371, (2083, 3)),
- (0x1d601, (4780, 1)),
- (0xfe93, (3889, 1)),
+ (0x1e048, (5311, 1)),
(0x1d7ce, (5237, 1)),
- (0x1d6fc, (5029, 1)),
+ (0xff65, (4109, 1)),
(0x33a0, (2191, 3)),
- (0x2f4c, (933, 1)),
- (0xfc31, (2776, 2)),
+ (0x313e, (1097, 1)),
+ (0x1d60a, (4789, 1)),
(0x1d591, (4668, 1)),
- (0xfc85, (2956, 2)),
- (0xfb53, (2492, 1)),
- (0xfb55, (2494, 1)),
- (0xfebd, (3931, 1)),
- (0x2f58, (945, 1)),
+ (0x1e04d, (5316, 1)),
+ (0x1d5c5, (4720, 1)),
+ (0x327a, (1490, 2)),
+ (0x1d68, (193, 1)),
+ (0xff71, (4121, 1)),
(0x1d42e, (4337, 1)),
- (0x1d697, (4930, 1)),
- (0x1f141, (5554, 1)),
- (0x1ee2e, (5327, 1)),
+ (0x1d77a, (5155, 1)),
+ (0xfe44, (3790, 1)),
+ (0x1f132, (5601, 1)),
+ (0x1d5f6, (4769, 1)),
(0x1d77c, (5157, 1)),
- (0xfe9d, (3899, 1)),
+ (0x1d66f, (4890, 1)),
(0x1d7f5, (5276, 1)),
- (0x1eeae, (5414, 1)),
(0xfcd7, (3125, 2)),
- (0x1d480, (4418, 1)),
- (0x1d6e8, (5009, 1)),
- (0x33fe, (2432, 3)),
- (0x1d734, (5085, 1)),
- (0xfc47, (2820, 2)),
- (0xfd37, (3322, 2)),
- (0x1d57, (176, 1)),
- (0x24b7, (788, 1)),
- (0x1d612, (4797, 1)),
- (0xfe4a, (3795, 2)),
- (0x1d48, (162, 1)),
- (0x1ee70, (5364, 1)),
- (0x1fbf6, (5669, 1)),
- (0x1cc, (54, 2)),
- (0x1d599, (4676, 1)),
+ (0x3188, (1171, 1)),
+ (0x1d7a0, (5193, 1)),
+ (0xfbe5, (2610, 1)),
+ (0xff8d, (4149, 1)),
+ (0x107a1, (4266, 1)),
+ (0x1d44e, (4369, 1)),
+ (0x1d528, (4570, 1)),
+ (0x2fc4, (1053, 1)),
+ (0x2024, (289, 1)),
+ (0x10fc, (135, 1)),
+ (0xfdb0, (3618, 3)),
+ (0xfcb4, (3055, 2)),
+ (0x330c, (1717, 4)),
+ (0x316b, (1142, 1)),
+ (0x1f111, (5515, 3)),
+ (0x2fb8, (1041, 1)),
(0x3385, (2129, 2)),
- (0x1d6c3, (4972, 1)),
+ (0x1da9, (211, 1)),
(0x1d73a, (5091, 1)),
- (0x32b9, (1570, 2)),
- (0x107ae, (4279, 1)),
+ (0x3293, (1524, 1)),
+ (0x1d4cf, (4486, 1)),
(0x32d6, (1627, 1)),
- (0xffcd, (4208, 1)),
- (0xfbb1, (2589, 2)),
- (0x1f14d, (5569, 2)),
- (0x3137, (1090, 1)),
- (0xfdf8, (3720, 4)),
- (0xfcfc, (3204, 2)),
+ (0x338b, (2144, 2)),
+ (0x314a, (1109, 1)),
+ (0x1f14d, (5631, 2)),
+ (0x1e9b, (236, 2)),
+ (0x1d64a, (4853, 1)),
+ (0x1d7da, (5249, 1)),
(0xfb17, (2475, 2)),
(0x1d761, (5130, 1)),
(0x2097, (357, 1)),
- (0xfca3, (3021, 2)),
- (0x2f24, (893, 1)),
- (0x1f13f, (5552, 1)),
+ (0x1fc0, (242, 2)),
+ (0x33e3, (2357, 2)),
+ (0x1d6b3, (4956, 1)),
(0x1d5b4, (4703, 1)),
(0xfd17, (3258, 2)),
(0xfc2a, (2762, 2)),
- (0x1ee6c, (5360, 1)),
+ (0x1d76a, (5139, 1)),
(0x1d68a, (4917, 1)),
- (0x2f16, (879, 1)),
- (0x33fb, (2423, 3)),
- (0x336a, (2062, 3)),
- (0x3186, (1169, 1)),
- (0xfd1c, (3268, 2)),
+ (0x1e039, (5296, 1)),
+ (0xfbe9, (2614, 1)),
+ (0x1f107, (5504, 2)),
+ (0x107a4, (4269, 1)),
+ (0x216d, (510, 1)),
+ (0x2092, (352, 1)),
(0xff3d, (4069, 1)),
- (0x1ee92, (5393, 1)),
- (0xfea2, (3904, 1)),
- (0x1d413, (4310, 1)),
- (0x329b, (1532, 1)),
- (0xffb2, (4186, 1)),
- (0xfe12, (3759, 1)),
- (0xfbd3, (2591, 1)),
- (0xff59, (4097, 1)),
- (0x1ee91, (5392, 1)),
- (0x1fbf0, (5663, 1)),
- (0x3329, (1834, 3)),
- (0x1d6ef, (5016, 1)),
+ (0x107b3, (4283, 1)),
+ (0x2f51, (938, 1)),
+ (0xfc59, (2856, 2)),
+ (0x1d529, (4571, 1)),
+ (0x3237, (1376, 3)),
+ (0x3215, (1262, 4)),
+ (0x2465, (561, 1)),
+ (0x1d735, (5086, 1)),
+ (0x107b9, (4289, 1)),
+ (0xfed3, (3953, 1)),
+ (0x203c, (306, 2)),
(0x2f9b, (1012, 1)),
- (0x1da0, (202, 1)),
- (0xfe86, (3869, 2)),
+ (0x2f66, (959, 1)),
+ (0xfd75, (3447, 3)),
+ (0x1d634, (4831, 1)),
(0xe33, (120, 2)),
- (0x1d6d6, (4991, 1)),
+ (0x1dba, (228, 1)),
(0xfd5a, (3366, 3)),
(0x2494, (685, 3)),
- (0x1d6cb, (4980, 1)),
- (0x1d5d1, (4732, 1)),
- (0x328c, (1517, 1)),
+ (0x315d, (1128, 1)),
+ (0x1d509, (4543, 1)),
+ (0x1d797, (5184, 1)),
(0x334f, (1986, 3)),
- (0x309c, (1078, 2)),
(0x1d7fb, (5282, 1)),
- (0x33a8, (2213, 4)),
- (0x3323, (1817, 3)),
+ (0x2463, (559, 1)),
+ (0xff02, (4010, 1)),
+ (0xfb61, (2506, 1)),
(0x33ec, (2378, 3)),
- (0x1d770, (5145, 1)),
- (0x1078a, (4243, 1)),
+ (0x1d5f7, (4770, 1)),
(0x33ae, (2231, 5)),
+ (0xfc89, (2964, 2)),
(0x1d738, (5089, 1)),
- (0x2f10, (873, 1)),
- (0x1f22a, (5616, 1)),
+ (0x1e030, (5287, 1)),
+ (0x1f22a, (5678, 1)),
(0x2f4b, (932, 1)),
- (0x246b, (569, 2)),
- (0x1d67f, (4906, 1)),
- (0x3348, (1958, 4)),
- (0xff24, (4044, 1)),
+ (0x3302, (1679, 5)),
+ (0x1d4d, (167, 1)),
+ (0x1d4d7, (4494, 1)),
+ (0xfc4d, (2832, 2)),
(0x1d4e5, (4508, 1)),
(0x1d542, (4594, 1)),
- (0x248c, (666, 2)),
- (0x107a7, (4272, 1)),
- (0xfbf1, (2636, 3)),
- (0x2fa5, (1022, 1)),
- (0x1d521, (4563, 1)),
- (0xfd11, (3246, 2)),
- (0x24b5, (784, 3)),
+ (0x3336, (1890, 5)),
+ (0x2fb6, (1039, 1)),
+ (0x2fa1, (1018, 1)),
+ (0x1d71a, (5059, 1)),
+ (0xfca4, (3023, 2)),
+ (0x1d618, (4803, 1)),
+ (0xfcc2, (3083, 2)),
(0x1dac, (214, 1)),
(0xfcb8, (3063, 2)),
- (0x1d713, (5052, 1)),
+ (0xfb7c, (2533, 1)),
(0x317f, (1162, 1)),
- (0x1d5f8, (4771, 1)),
- (0xfdb2, (3624, 3)),
+ (0x1d7e0, (5255, 1)),
+ (0xffc6, (4203, 1)),
(0x3150, (1115, 1)),
- (0xfef5, (3987, 3)),
- (0xfed4, (3954, 1)),
- (0x2479, (602, 3)),
- (0x1ee5d, (5351, 1)),
+ (0x3276, (1482, 2)),
+ (0x328d, (1518, 1)),
+ (0x32bc, (1576, 2)),
+ (0x133, (26, 2)),
+ (0x1f245, (5711, 3)),
(0x213e, (427, 1)),
- (0x1d412, (4309, 1)),
- (0x2f1b, (884, 1)),
- (0xff2b, (4051, 1)),
- (0x2488, (658, 2)),
- (0xfc2f, (2772, 2)),
- (0x1d498, (4442, 1)),
- (0x2f7a, (979, 1)),
+ (0xfb66, (2511, 1)),
+ (0x2f89, (994, 1)),
+ (0x1f12e, (5597, 2)),
+ (0x1d4f1, (4520, 1)),
+ (0xfc91, (2980, 2)),
+ (0xff53, (4091, 1)),
(0x3306, (1695, 3)),
(0x2473, (585, 2)),
- (0xfc8b, (2968, 2)),
- (0xfb9f, (2568, 1)),
+ (0x1dae, (216, 1)),
+ (0xfbac, (2583, 1)),
+ (0x33b4, (2250, 2)),
(0x3214, (1258, 4)),
- (0x2230, (553, 3)),
- (0x1d651, (4860, 1)),
- (0x2f2c, (901, 1)),
- (0xfc1e, (2738, 2)),
- (0x1d64f, (4858, 1)),
+ (0x32c2, (1588, 2)),
+ (0x24ca, (807, 1)),
+ (0x1d533, (4581, 1)),
+ (0x33f8, (2414, 3)),
+ (0xff44, (4076, 1)),
(0x1d4f7, (4526, 1)),
- (0x3158, (1123, 1)),
+ (0x1078c, (4245, 1)),
(0xffca, (4205, 1)),
- (0x3000, (1071, 1)),
- (0x1db0, (218, 1)),
- (0x32ec, (1649, 1)),
- (0xfeed, (3979, 1)),
- (0x3372, (2086, 2)),
- (0x1f134, (5541, 1)),
- (0x1ee2c, (5325, 1)),
- (0xff4f, (4087, 1)),
+ (0xfe17, (3764, 1)),
+ (0xfbe1, (2606, 1)),
+ (0xfc32, (2778, 2)),
+ (0x1d625, (4816, 1)),
+ (0x140, (30, 2)),
+ (0xfeab, (3913, 1)),
+ (0x1d6d3, (4988, 1)),
+ (0x1d7a8, (5201, 1)),
(0xfb5d, (2502, 1)),
- (0x1d4eb, (4514, 1)),
- (0x1d645, (4848, 1)),
+ (0x3220, (1307, 3)),
+ (0x24a5, (736, 3)),
(0x1d4b3, (4461, 1)),
- (0x322f, (1352, 3)),
- (0x1d5fe, (4777, 1)),
+ (0x107ad, (4278, 1)),
+ (0x3399, (2176, 2)),
(0x2f36, (911, 1)),
- (0x33cb, (2301, 2)),
- (0x2f28, (897, 1)),
- (0xff26, (4046, 1)),
- (0x1d74f, (5112, 1)),
- (0xfd66, (3402, 3)),
- (0x1d5a2, (4685, 1)),
- (0x2d6f, (854, 1)),
+ (0xfc74, (2922, 2)),
+ (0x1d5a5, (4688, 1)),
+ (0x2fc3, (1052, 1)),
+ (0x1e06c, (5347, 1)),
+ (0x32d9, (1630, 1)),
+ (0x1d544, (4596, 1)),
+ (0x3221, (1310, 3)),
(0x1d512, (4550, 1)),
- (0x3379, (2102, 3)),
- (0xfcee, (3173, 2)),
- (0x1d750, (5113, 1)),
- (0xfba8, (2579, 1)),
- (0x385, (92, 3)),
+ (0xfece, (3948, 1)),
+ (0xfcf7, (3194, 2)),
+ (0xfb82, (2539, 1)),
+ (0x1d6b8, (4961, 1)),
+ (0x3194, (1180, 1)),
(0xffe5, (4226, 1)),
- (0x323c, (1391, 3)),
- (0x1fbf1, (5664, 1)),
+ (0x32e8, (1645, 1)),
+ (0x24af, (766, 3)),
+ (0x1fbf1, (5726, 1)),
(0xfbfc, (2669, 1)),
- (0x33b0, (2242, 2)),
- (0xfdb1, (3621, 3)),
- (0xfdbf, (3663, 3)),
- (0x330e, (1725, 4)),
- (0x1d5a1, (4684, 1)),
- (0x1db3, (221, 1)),
- (0x1ee4d, (5342, 1)),
+ (0xb3, (7, 1)),
+ (0x24c6, (803, 1)),
+ (0x1d749, (5106, 1)),
+ (0xfd9a, (3552, 3)),
+ (0x1d4b5, (4463, 1)),
+ (0xfede, (3964, 1)),
(0x1d6e7, (5008, 1)),
(0x2f48, (929, 1)),
- (0x1d66e, (4889, 1)),
+ (0x1d4e3, (4506, 1)),
+ (0x1eea6, (5469, 1)),
(0x2f97, (1008, 1)),
- (0x1d797, (5184, 1)),
+ (0x24a8, (745, 3)),
(0x1d562, (4621, 1)),
- (0xff52, (4090, 1)),
- (0x1d7b4, (5213, 1)),
- (0xfca9, (3033, 2)),
- (0x1d63b, (4838, 1)),
- (0x2f39, (914, 1)),
+ (0x2102, (371, 1)),
+ (0x1d61b, (4806, 1)),
+ (0x3176, (1153, 1)),
+ (0x1d60, (185, 1)),
(0x1d698, (4931, 1)),
- (0x2174, (521, 1)),
- (0xfd20, (3276, 2)),
- (0x1d69d, (4936, 1)),
- (0x24e8, (837, 1)),
- (0x213d, (426, 1)),
+ (0xfed9, (3959, 1)),
+ (0x1d61f, (4810, 1)),
+ (0x1ee6a, (5421, 1)),
+ (0xfd09, (3230, 2)),
+ (0x1d561, (4620, 1)),
+ (0x1d4e1, (4504, 1)),
(0x1d7f4, (5275, 1)),
- (0x1d779, (5154, 1)),
- (0x3215, (1262, 4)),
- (0xfb28, (2485, 1)),
- (0x33f4, (2402, 3)),
- (0x1d624, (4815, 1)),
- (0x1d577, (4642, 1)),
- (0xfbd5, (2593, 1)),
- (0xfedc, (3962, 1)),
+ (0x2f68, (961, 1)),
+ (0x1eeb3, (5481, 1)),
+ (0x1e062, (5337, 1)),
+ (0x2fbe, (1047, 1)),
+ (0x2047, (310, 2)),
+ (0xff23, (4043, 1)),
+ (0xfe77, (3840, 2)),
+ (0x1d75b, (5124, 1)),
(0x1d4b9, (4467, 1)),
(0x33ba, (2262, 2)),
- (0x2fb0, (1033, 1)),
- (0x325f, (1450, 2)),
+ (0x2482, (634, 4)),
(0xffb0, (4184, 1)),
- (0xfcef, (3175, 2)),
- (0x1f221, (5607, 1)),
- (0x1d691, (4924, 1)),
- (0x1d6dd, (4998, 1)),
- (0x2f46, (927, 1)),
+ (0x3164, (1135, 1)),
+ (0x24d1, (814, 1)),
+ (0x24db, (824, 1)),
+ (0x1d5bc, (4711, 1)),
+ (0x3396, (2170, 2)),
+ (0x1d590, (4667, 1)),
(0x1d5da, (4741, 1)),
- (0x1d5c1, (4716, 1)),
- (0x1d526, (4568, 1)),
- (0x338d, (2148, 2)),
+ (0x1d454, (4375, 1)),
+ (0x1ee24, (5382, 1)),
+ (0x2134, (416, 1)),
(0x1d7a5, (5198, 1)),
- (0xffbe, (4198, 1)),
+ (0x1e056, (5325, 1)),
(0x32f7, (1660, 1)),
- (0x1f14a, (5563, 2)),
- (0xff28, (4048, 1)),
- (0xff69, (4113, 1)),
+ (0xfe72, (3834, 2)),
+ (0x1e04c, (5315, 1)),
+ (0xfef0, (3982, 1)),
(0x2f0f, (872, 1)),
- (0x1d4d7, (4494, 1)),
+ (0x2f88, (993, 1)),
(0x1d4cd, (4484, 1)),
- (0x1ee2d, (5326, 1)),
- (0xa0, (0, 1)),
- (0x1d726, (5071, 1)),
+ (0x1d54b, (4599, 1)),
+ (0x1d7ba, (5219, 1)),
+ (0x1fbf, (240, 2)),
(0xffeb, (4231, 1)),
- (0xfdf1, (3693, 3)),
- (0xfe16, (3763, 1)),
- (0x1d754, (5117, 1)),
+ (0x1d5ee, (4761, 1)),
+ (0xff72, (4122, 1)),
+ (0x1f218, (5660, 1)),
+ (0x3234, (1367, 3)),
(0x1d7ef, (5270, 1)),
- (0x2116, (394, 2)),
- (0x33c9, (2297, 2)),
- (0x1d71d, (5062, 1)),
- (0xfea8, (3910, 1)),
+ (0x1d425, (4328, 1)),
+ (0x1d6ce, (4983, 1)),
+ (0x1ee83, (5441, 1)),
+ (0x1e04f, (5318, 1)),
(0x1d483, (4421, 1)),
- (0x1d6a0, (4939, 1)),
- (0x1d443, (4358, 1)),
+ (0xff73, (4123, 1)),
(0xff1c, (4036, 1)),
- (0x1d4c6, (4477, 1)),
- (0x2fd5, (1070, 1)),
+ (0x33f2, (2396, 3)),
+ (0x217b, (536, 3)),
+ (0x2004, (279, 1)),
(0x1d6a4, (4943, 1)),
- (0xfb6a, (2515, 1)),
- (0xfb06, (2465, 2)),
- (0xfc2b, (2764, 2)),
- (0x1f125, (5513, 3)),
- (0x2fb7, (1040, 1)),
- (0x2111, (390, 1)),
- (0x2fbe, (1047, 1)),
- (0x1d705, (5038, 1)),
+ (0x326f, (1468, 2)),
+ (0xfc57, (2852, 2)),
+ (0x32f2, (1655, 1)),
+ (0x1d646, (4849, 1)),
+ (0x1d412, (4309, 1)),
+ (0x249a, (703, 3)),
+ (0x1f127, (5581, 3)),
(0x330b, (1714, 3)),
- (0x1d463, (4389, 1)),
+ (0xfc5c, (2862, 2)),
+ (0x2f46, (927, 1)),
(0x1d40a, (4301, 1)),
- (0x1d4dc, (4499, 1)),
- (0x1d537, (4585, 1)),
+ (0x24d8, (821, 1)),
+ (0x1d77e, (5159, 1)),
(0xfd3a, (3328, 2)),
- (0x1d78, (196, 1)),
+ (0x1d64, (189, 1)),
(0x315e, (1129, 1)),
- (0xfbdf, (2604, 1)),
- (0xff01, (4009, 1)),
- (0x3216, (1266, 4)),
- (0x1d4c8, (4479, 1)),
- (0xfce5, (3155, 2)),
+ (0x319d, (1189, 1)),
+ (0x1ee3b, (5399, 1)),
+ (0xfb26, (2483, 1)),
+ (0x1d4fe, (4533, 1)),
+ (0x2480, (626, 4)),
(0x216e, (511, 1)),
- (0x2011, (286, 1)),
- (0x1d593, (4670, 1)),
- (0x1d728, (5073, 1)),
- (0x1d7d4, (5243, 1)),
- (0x1ee13, (5305, 1)),
- (0x1d48a, (4428, 1)),
+ (0x1e03b, (5298, 1)),
+ (0x1d6b6, (4959, 1)),
+ (0xbd, (18, 3)),
+ (0x1d42, (156, 1)),
+ (0x24a1, (724, 3)),
+ (0x33df, (2348, 3)),
(0xffb5, (4189, 1)),
- (0x1d77b, (5156, 1)),
- (0xffd3, (4212, 1)),
- (0x1c6, (41, 3)),
- (0x1d778, (5153, 1)),
- (0x1d690, (4923, 1)),
- (0xfefc, (4007, 2)),
- (0x1d4c3, (4475, 1)),
- (0xfd6c, (3420, 3)),
- (0x32f2, (1655, 1)),
+ (0x1e042, (5305, 1)),
+ (0xfc9a, (3001, 3)),
+ (0x1d5eb, (4758, 1)),
+ (0xfcbf, (3077, 2)),
+ (0xfd58, (3360, 3)),
+ (0x2464, (560, 1)),
+ (0xfe3c, (3782, 1)),
+ (0x3246, (1417, 1)),
+ (0x2a0c, (840, 4)),
+ (0xfdb4, (3630, 3)),
(0xfd96, (3540, 3)),
(0x1d407, (4298, 1)),
- (0x1d6eb, (5012, 1)),
(0x3257, (1434, 2)),
(0x207a, (329, 1)),
+ (0x3d5, (102, 1)),
(0x336b, (2065, 3)),
- (0x1d75c, (5125, 1)),
- (0xff0e, (4022, 1)),
- (0xffe9, (4229, 1)),
+ (0x32d0, (1621, 1)),
+ (0x1eeae, (5476, 1)),
(0x1d5d5, (4736, 1)),
- (0x1d6db, (4996, 1)),
- (0x1d451, (4372, 1)),
- (0x1d74c, (5109, 1)),
- (0x1f1, (56, 2)),
+ (0x1eead, (5475, 1)),
+ (0x2f1a, (883, 1)),
+ (0xfee0, (3966, 1)),
+ (0x2fa3, (1020, 1)),
+ (0x1eeb2, (5480, 1)),
(0xfbf5, (2648, 3)),
- (0x1d43c, (4351, 1)),
+ (0x1e067, (5342, 1)),
(0x3174, (1151, 1)),
- (0xfd68, (3408, 3)),
(0xfbe0, (2605, 1)),
- (0x1f144, (5557, 1)),
+ (0x1ee51, (5407, 1)),
+ (0xff3f, (4071, 1)),
(0x3165, (1136, 1)),
- (0x1da5, (207, 1)),
- (0xfc90, (2978, 2)),
- (0x1d55c, (4615, 1)),
- (0xfc24, (2750, 2)),
+ (0x323d, (1394, 3)),
+ (0x1d72d, (5078, 1)),
+ (0x1d79b, (5188, 1)),
+ (0x1d4b6, (4464, 1)),
(0xfc54, (2846, 2)),
- (0xfc2e, (2770, 2)),
- (0x1d634, (4831, 1)),
- (0x1d759, (5122, 1)),
+ (0x2fb0, (1033, 1)),
+ (0x3228, (1331, 3)),
+ (0x1d3a, (149, 1)),
(0x3213, (1254, 4)),
- (0x1d43b, (4350, 1)),
- (0x2f57, (944, 1)),
- (0x1d7ba, (5219, 1)),
- (0x1daf, (217, 1)),
- (0xfb96, (2559, 1)),
+ (0x1e065, (5340, 1)),
+ (0x1d4ff, (4534, 1)),
+ (0x1d734, (5085, 1)),
+ (0x1d78b, (5172, 1)),
+ (0xa69d, (2439, 1)),
(0x2f96, (1007, 1)),
- (0x317a, (1157, 1)),
- (0x1f11f, (5495, 3)),
- (0x1d6a3, (4942, 1)),
- (0x1d41, (155, 1)),
- (0x1f124, (5510, 3)),
- (0x2f17, (880, 1)),
- (0x3272, (1474, 2)),
+ (0xfc39, (2792, 2)),
+ (0x1f14c, (5629, 2)),
+ (0xfedb, (3961, 1)),
+ (0x2495, (688, 3)),
+ (0x1f124, (5572, 3)),
+ (0x1d7dc, (5251, 1)),
+ (0x1e053, (5322, 1)),
(0x2f9a, (1011, 1)),
(0xfd61, (3387, 3)),
- (0x1d5ee, (4761, 1)),
- (0x1eeab, (5411, 1)),
+ (0xfd02, (3216, 2)),
+ (0x1eeab, (5473, 1)),
(0x1079f, (4264, 1)),
- (0xf77, (129, 3)),
- (0xfd1f, (3274, 2)),
- (0x24c3, (800, 1)),
+ (0x1ee86, (5444, 1)),
+ (0xfd9b, (3555, 3)),
+ (0x1d50f, (4547, 1)),
(0xfc8e, (2974, 2)),
- (0x2499, (700, 3)),
+ (0x1d513, (4551, 1)),
(0x1d54f, (4603, 1)),
- (0x1d33, (142, 1)),
- (0xff15, (4029, 1)),
+ (0x2173, (519, 2)),
+ (0x2f5a, (947, 1)),
+ (0x1d78c, (5173, 1)),
(0x1d767, (5136, 1)),
- (0x33ce, (2307, 2)),
(0xfdab, (3603, 3)),
+ (0x2f01, (858, 1)),
(0xfc3f, (2804, 2)),
- (0x1d5e6, (4753, 1)),
- (0x33a9, (2217, 2)),
- (0x325a, (1440, 2)),
+ (0x33c6, (2288, 4)),
+ (0x1d6c0, (4969, 1)),
+ (0xfb98, (2561, 1)),
(0x3151, (1116, 1)),
- (0x3335, (1887, 3)),
- (0x1d702, (5035, 1)),
+ (0x1ee09, (5357, 1)),
+ (0xfd8a, (3510, 3)),
(0xff4d, (4085, 1)),
- (0xffe8, (4228, 1)),
- (0xba, (14, 1)),
- (0xfc12, (2714, 2)),
- (0xff03, (4011, 1)),
- (0xfe31, (3771, 1)),
- (0x1d419, (4316, 1)),
- (0x32b3, (1558, 2)),
+ (0x1d729, (5074, 1)),
+ (0xfeb4, (3922, 1)),
+ (0xfba4, (2573, 2)),
+ (0x1d6b9, (4962, 1)),
+ (0x1d6d0, (4985, 1)),
+ (0x318d, (1176, 1)),
+ (0x1f10a, (5510, 2)),
(0x2017, (287, 2)),
- (0xfee7, (3973, 1)),
- (0x24a5, (736, 3)),
- (0x132, (24, 2)),
+ (0x1f121, (5563, 3)),
+ (0x1d41f, (4322, 1)),
(0x1d415, (4312, 1)),
(0x319b, (1187, 1)),
+ (0x1d6dd, (4998, 1)),
(0x337f, (2115, 4)),
- (0x313c, (1095, 1)),
- (0x1d769, (5138, 1)),
- (0x3394, (2165, 3)),
+ (0x3260, (1452, 1)),
+ (0x1fbf6, (5731, 1)),
(0xfb7b, (2532, 1)),
- (0xff4b, (4083, 1)),
- (0x1d522, (4564, 1)),
+ (0x1d752, (5115, 1)),
+ (0x2f50, (937, 1)),
(0xfebf, (3933, 1)),
+ (0x1d658, (4867, 1)),
(0xfdfa, (3727, 18)),
- (0x1f231, (5623, 1)),
+ (0x336e, (2074, 3)),
(0xff51, (4089, 1)),
- (0x1d65a, (4869, 1)),
- (0x1d7c6, (5231, 1)),
- (0xfeb8, (3926, 1)),
- (0xfeee, (3980, 1)),
- (0x1ee61, (5353, 1)),
+ (0xfc16, (2722, 2)),
+ (0x1d5d, (182, 1)),
+ (0x24b8, (789, 1)),
+ (0xab5d, (2447, 1)),
+ (0x1d41b, (4318, 1)),
(0xfb68, (2513, 1)),
- (0x1f103, (5434, 2)),
- (0x1d45a, (4380, 1)),
- (0x1d54d, (4601, 1)),
- (0xffc5, (4202, 1)),
- (0xfcff, (3210, 2)),
+ (0x1f103, (5496, 2)),
+ (0x2f53, (940, 1)),
+ (0x3352, (1996, 2)),
+ (0x1d5f9, (4772, 1)),
+ (0x1d494, (4438, 1)),
(0x1d52c, (4574, 1)),
(0x24e6, (835, 1)),
- (0x1ee2b, (5324, 1)),
- (0x3316, (1759, 6)),
- (0x1d58b, (4662, 1)),
- (0xfdf6, (3712, 4)),
- (0xff43, (4075, 1)),
+ (0x2faf, (1032, 1)),
+ (0x32c1, (1586, 2)),
+ (0x2b3, (65, 1)),
+ (0xfec1, (3935, 1)),
+ (0x1f147, (5622, 1)),
(0x384, (90, 2)),
- (0x1d61c, (4807, 1)),
+ (0x24ba, (791, 1)),
(0xff87, (4143, 1)),
- (0x2092, (352, 1)),
- (0x2f37, (912, 1)),
- (0x1f248, (5658, 3)),
+ (0x1d669, (4884, 1)),
+ (0xff35, (4061, 1)),
+ (0xfefb, (4005, 2)),
(0x1d7fa, (5281, 1)),
- (0x215e, (478, 3)),
- (0x1d731, (5082, 1)),
- (0xfd5e, (3378, 3)),
- (0x1f219, (5599, 1)),
+ (0x1d50, (169, 1)),
+ (0xfef2, (3984, 1)),
+ (0x3245, (1416, 1)),
+ (0x1d78a, (5171, 1)),
(0xfb75, (2526, 1)),
- (0x1d5b9, (4708, 1)),
- (0x10784, (4238, 1)),
+ (0x1ee91, (5454, 1)),
+ (0x33e9, (2369, 3)),
+ (0x2139, (421, 1)),
(0x3258, (1436, 2)),
- (0x32bd, (1578, 2)),
+ (0x3287, (1512, 1)),
(0x317d, (1160, 1)),
(0x24ae, (763, 3)),
- (0x33be, (2270, 2)),
- (0xfc99, (2998, 3)),
+ (0xff98, (4160, 1)),
(0x1d596, (4673, 1)),
- (0x1d4f8, (4527, 1)),
- (0xfdb0, (3618, 3)),
- (0x3282, (1507, 1)),
+ (0x1d6b0, (4953, 1)),
+ (0x1e069, (5344, 1)),
+ (0x1f22c, (5680, 1)),
+ (0xff42, (4074, 1)),
(0xffbb, (4195, 1)),
- (0xfeec, (3978, 1)),
- (0x1d6f7, (5024, 1)),
- (0x2f82, (987, 1)),
- (0xfb04, (2460, 3)),
- (0x2f5e, (951, 1)),
- (0x1d637, (4834, 1)),
- (0x1d5ea, (4757, 1)),
- (0x1d6fd, (5030, 1)),
+ (0xff1d, (4037, 1)),
+ (0x1d503, (4538, 1)),
+ (0x1d6e1, (5002, 1)),
+ (0xfcc7, (3093, 2)),
+ (0xff60, (4104, 1)),
+ (0x1ee5d, (5413, 1)),
+ (0x1f115, (5527, 3)),
(0x1d4c9, (4480, 1)),
(0x1d567, (4626, 1)),
- (0x3d2, (97, 1)),
+ (0x1d67e, (4905, 1)),
(0x33ed, (2381, 3)),
+ (0x1e068, (5343, 1)),
(0xfda6, (3588, 3)),
- (0x24bf, (796, 1)),
+ (0x33ca, (2299, 2)),
(0x1d7f8, (5279, 1)),
(0x33ef, (2387, 3)),
- (0x1d659, (4868, 1)),
- (0x1d7c9, (5234, 1)),
+ (0xfd50, (3336, 3)),
+ (0x248e, (670, 2)),
(0xfcd4, (3119, 2)),
- (0xfb83, (2540, 1)),
- (0x2472, (583, 2)),
- (0x1d4ee, (4517, 1)),
- (0xffe0, (4220, 1)),
+ (0xfe98, (3894, 1)),
+ (0x32a7, (1544, 1)),
+ (0xffa9, (4177, 1)),
(0x2172, (516, 3)),
- (0xfe69, (3827, 1)),
- (0x2f1f, (888, 1)),
+ (0x1d5a, (179, 1)),
+ (0xff27, (4047, 1)),
+ (0x1dad, (215, 1)),
(0x1d766, (5135, 1)),
- (0x107a6, (4271, 1)),
(0x24df, (828, 1)),
+ (0xfeae, (3916, 1)),
(0xfe35, (3775, 1)),
- (0xfd7c, (3468, 3)),
- (0xffea, (4230, 1)),
+ (0x1d5a3, (4686, 1)),
+ (0x1d650, (4859, 1)),
(0x1d62a, (4821, 1)),
(0x1d4dd, (4500, 1)),
- (0x1eea5, (5406, 1)),
+ (0xff5b, (4099, 1)),
(0x1d464, (4390, 1)),
- (0x2080, (335, 1)),
- (0x33af, (2236, 6)),
+ (0xfc34, (2782, 2)),
+ (0x1d6bc, (4965, 1)),
(0x1d71c, (5061, 1)),
- (0x1ee9a, (5401, 1)),
- (0xfe5d, (3816, 1)),
- (0xff76, (4126, 1)),
- (0xff71, (4121, 1)),
+ (0x2128, (409, 1)),
+ (0xfb74, (2525, 1)),
+ (0xfced, (3171, 2)),
+ (0xa69c, (2438, 1)),
(0x2a74, (844, 3)),
- (0x1d764, (5133, 1)),
- (0xff23, (4043, 1)),
- (0x1d5ed, (4760, 1)),
- (0xfefb, (4005, 2)),
- (0x2fb6, (1039, 1)),
+ (0xfef8, (3996, 3)),
+ (0x1d63a, (4837, 1)),
+ (0xfcb5, (3057, 2)),
+ (0x1d435, (4344, 1)),
+ (0x1ee69, (5420, 1)),
(0x2036, (301, 2)),
(0x1fbd, (238, 2)),
(0x1d5fb, (4774, 1)),
+ (0x1d5b9, (4708, 1)),
(0xfd57, (3357, 3)),
- (0x1d59c, (4679, 1)),
(0x318b, (1174, 1)),
- (0x1d4a2, (4449, 1)),
- (0xfcde, (3139, 2)),
- (0x2110, (389, 1)),
+ (0xfdf5, (3708, 4)),
+ (0xfe7c, (3850, 2)),
+ (0xfc9b, (3004, 3)),
(0xfd14, (3252, 2)),
- (0x1d6e3, (5004, 1)),
- (0xfd8d, (3519, 3)),
+ (0x1d51b, (4558, 1)),
+ (0x1ee67, (5418, 1)),
+ (0x338a, (2142, 2)),
(0xff40, (4072, 1)),
- (0x2f5f, (952, 1)),
(0xfb50, (2489, 1)),
- (0xff45, (4077, 1)),
- (0x1ee17, (5309, 1)),
- (0xfe9a, (3896, 1)),
- (0x1d4cf, (4486, 1)),
- (0x1d63, (188, 1)),
+ (0x1d4c7, (4478, 1)),
+ (0x1079c, (4261, 1)),
+ (0x1ee17, (5371, 1)),
+ (0x1f190, (5644, 2)),
+ (0x1d5f0, (4763, 1)),
+ (0x32b3, (1558, 2)),
(0x1d7d5, (5244, 1)),
- (0x327d, (1499, 4)),
(0xfe64, (3823, 1)),
- (0x2f84, (989, 1)),
+ (0xfb8e, (2551, 1)),
+ (0xfc07, (2692, 2)),
(0xfb58, (2497, 1)),
- (0x1d592, (4669, 1)),
- (0x336c, (2068, 3)),
- (0x3202, (1198, 3)),
- (0x1d5e5, (4752, 1)),
- (0x1d45, (159, 1)),
- (0x1d708, (5041, 1)),
- (0xfe11, (3758, 1)),
+ (0x1d75c, (5125, 1)),
+ (0x2168, (501, 2)),
+ (0x1d745, (5102, 1)),
+ (0x1ee4e, (5405, 1)),
+ (0x2fcc, (1061, 1)),
+ (0x1d781, (5162, 1)),
+ (0x313c, (1095, 1)),
(0x1fde, (259, 3)),
(0x2fbd, (1046, 1)),
- (0xfd95, (3537, 3)),
- (0xfb67, (2512, 1)),
- (0xa69d, (2439, 1)),
+ (0x1d5d4, (4735, 1)),
+ (0x1d500, (4535, 1)),
+ (0xfc80, (2946, 2)),
(0x33a3, (2199, 3)),
(0x1d502, (4537, 1)),
- (0xfc59, (2856, 2)),
+ (0x32d1, (1622, 1)),
(0xfd97, (3543, 3)),
- (0x2fbb, (1044, 1)),
+ (0x1d489, (4427, 1)),
(0xffd6, (4215, 1)),
(0xfcc3, (3085, 2)),
(0x2493, (682, 3)),
(0x1d6c6, (4975, 1)),
- (0xfe10, (3757, 1)),
- (0x1d585, (4656, 1)),
- (0x1d75a, (5123, 1)),
- (0x1ee05, (5291, 1)),
+ (0x208d, (348, 1)),
+ (0xfb06, (2465, 2)),
+ (0x319c, (1188, 1)),
+ (0x1da1, (203, 1)),
(0xff1b, (4035, 1)),
- (0xfb99, (2562, 1)),
+ (0xfee1, (3967, 1)),
(0xfc65, (2887, 3)),
- (0x10798, (4257, 1)),
- (0x24be, (795, 1)),
+ (0xfc14, (2718, 2)),
+ (0xfea2, (3904, 1)),
(0xfb91, (2554, 1)),
- (0x1f12d, (5533, 2)),
- (0xfc63, (2881, 3)),
- (0x1c8, (46, 2)),
+ (0x3350, (1989, 3)),
+ (0x1d6c8, (4977, 1)),
+ (0x1d677, (4898, 1)),
(0x10783, (4237, 1)),
(0x1da3, (205, 1)),
(0x1d51, (170, 1)),
(0x3261, (1453, 1)),
- (0xfe72, (3834, 2)),
+ (0xfc78, (2930, 2)),
+ (0x3363, (2041, 3)),
(0x2f3c, (917, 1)),
- (0xfdf3, (3700, 4)),
- (0x1d3c, (150, 1)),
- (0xfd92, (3528, 3)),
- (0x1d5cf, (4730, 1)),
+ (0x2f27, (896, 1)),
+ (0x32a3, (1540, 1)),
+ (0x1fbf5, (5730, 1)),
(0x2b4, (66, 1)),
- (0xfd6a, (3414, 3)),
- (0xfcc2, (3083, 2)),
- (0x2149, (434, 1)),
- (0x1d655, (4864, 1)),
+ (0x3286, (1511, 1)),
+ (0x2f17, (880, 1)),
+ (0x1d5cc, (4727, 1)),
+ (0x1f230, (5684, 1)),
+ (0xfb03, (2457, 3)),
(0x24ce, (811, 1)),
- (0xfe18, (3765, 1)),
- (0xfb52, (2491, 1)),
- (0x1f123, (5507, 3)),
- (0x2460, (556, 1)),
- (0xfbf0, (2633, 3)),
- (0xfb6b, (2516, 1)),
+ (0x2f30, (905, 1)),
+ (0xfd60, (3384, 3)),
+ (0x1f123, (5569, 3)),
+ (0x1d532, (4580, 1)),
+ (0x1f21e, (5666, 1)),
(0x3353, (1998, 4)),
- (0x330f, (1729, 4)),
- (0x333e, (1923, 4)),
+ (0x1d9b, (197, 1)),
+ (0x1f104, (5498, 2)),
+ (0x1f21b, (5663, 1)),
(0xfe52, (3806, 1)),
- (0x1d557, (4610, 1)),
+ (0xfd3b, (3330, 2)),
(0x2f61, (954, 1)),
(0xfc00, (2673, 3)),
- (0x1f129, (5525, 3)),
+ (0x1ee71, (5427, 1)),
(0x3f0, (104, 1)),
- (0x1ee0d, (5299, 1)),
- (0x1d55, (174, 1)),
- (0xff6d, (4117, 1)),
- (0x1d6a8, (4945, 1)),
- (0xff5f, (4103, 1)),
- (0x1ee96, (5397, 1)),
+ (0x1d7e4, (5259, 1)),
+ (0xfc5d, (2864, 2)),
+ (0x1d670, (4891, 1)),
+ (0xfe33, (3773, 1)),
+ (0x1d57d, (4648, 1)),
+ (0xfe6b, (3829, 1)),
(0x3233, (1364, 3)),
- (0xfb23, (2480, 1)),
+ (0x2f21, (890, 1)),
(0xfc15, (2720, 2)),
(0x1d55f, (4618, 1)),
- (0x2faa, (1027, 1)),
- (0x1d7aa, (5203, 1)),
- (0x322b, (1340, 3)),
- (0x326b, (1463, 1)),
+ (0xfd64, (3396, 3)),
+ (0x1d49a, (4444, 1)),
+ (0xfe7b, (3848, 2)),
+ (0x1d762, (5131, 1)),
(0x1d6e0, (5001, 1)),
- (0x1d433, (4342, 1)),
+ (0xfeb5, (3923, 1)),
(0x1d46b, (4397, 1)),
- (0xfd22, (3280, 2)),
+ (0x1db6, (224, 1)),
(0x3141, (1100, 1)),
- (0x2124, (408, 1)),
- (0x3296, (1527, 1)),
- (0x1d60e, (4793, 1)),
- (0xfd30, (3308, 2)),
- (0x1d7e9, (5264, 1)),
+ (0xfe9c, (3898, 1)),
+ (0x1d484, (4422, 1)),
+ (0x329d, (1534, 1)),
+ (0x1d530, (4578, 1)),
+ (0xfd32, (3312, 2)),
(0xfc5f, (2869, 3)),
- (0xfd01, (3214, 2)),
+ (0x1ee7b, (5435, 1)),
(0xf0c, (128, 1)),
- (0x24ea, (839, 1)),
- (0xfebc, (3930, 1)),
+ (0x1d56f, (4634, 1)),
+ (0x1d6aa, (4947, 1)),
+ (0x33dc, (2341, 2)),
(0x24e3, (832, 1)),
- (0x1d76c, (5141, 1)),
- (0x1f22e, (5620, 1)),
- (0x1d626, (4817, 1)),
- (0x1eead, (5413, 1)),
+ (0x1f22e, (5682, 1)),
+ (0x1d4b7, (4465, 1)),
+ (0x1d5d1, (4732, 1)),
(0x1d7a6, (5199, 1)),
- (0xfe70, (3830, 2)),
- (0x1d7c7, (5232, 1)),
- (0xfd35, (3318, 2)),
+ (0x2f4e, (935, 1)),
+ (0x1d6ae, (4951, 1)),
+ (0x3f2, (106, 1)),
+ (0x3280, (1505, 1)),
(0x1d3e, (152, 1)),
- (0x1d492, (4436, 1)),
- (0xfe3b, (3781, 1)),
- (0x2088, (343, 1)),
+ (0xfbef, (2630, 3)),
+ (0x1f102, (5494, 2)),
(0xfe54, (3807, 1)),
- (0xffc4, (4201, 1)),
- (0x1d6be, (4967, 1)),
- (0xfb9d, (2566, 1)),
+ (0x3263, (1455, 1)),
+ (0xff9b, (4163, 1)),
+ (0x1d584, (4655, 1)),
+ (0x3351, (1992, 4)),
(0x3156, (1121, 1)),
- (0x3357, (2015, 3)),
(0xfbf2, (2639, 3)),
(0xfb02, (2455, 2)),
- (0x1ee1c, (5314, 1)),
- (0xfd28, (3292, 2)),
- (0xfb57, (2496, 1)),
- (0x1d67c, (4903, 1)),
- (0x676, (114, 2)),
+ (0x317b, (1158, 1)),
+ (0x314c, (1111, 1)),
+ (0x1c6, (41, 3)),
+ (0x1d73f, (5096, 1)),
+ (0x1ee4d, (5404, 1)),
(0x1d53, (172, 1)),
- (0xfc17, (2724, 2)),
- (0x1fdd, (256, 3)),
+ (0x33d1, (2313, 2)),
+ (0x1d58a, (4661, 1)),
+ (0xfd83, (3489, 3)),
(0x2178, (531, 2)),
(0x1d751, (5114, 1)),
- (0xfb7c, (2533, 1)),
+ (0xfd77, (3453, 3)),
(0x1d479, (4411, 1)),
(0x215d, (475, 3)),
- (0x1f239, (5631, 1)),
- (0x32c3, (1590, 2)),
- (0xfc38, (2790, 2)),
- (0x1d465, (4391, 1)),
+ (0xfd87, (3501, 3)),
+ (0x318a, (1173, 1)),
+ (0x1d43f, (4354, 1)),
(0x2fcd, (1062, 1)),
+ (0x1d4f0, (4519, 1)),
(0x1d59, (178, 1)),
(0x1d65f, (4874, 1)),
- (0x1d66c, (4887, 1)),
- (0x24e9, (838, 1)),
+ (0x3393, (2162, 3)),
+ (0x1ee92, (5455, 1)),
(0xa770, (2440, 1)),
- (0xfd18, (3260, 2)),
- (0xfe5a, (3813, 1)),
+ (0xfd0b, (3234, 2)),
+ (0x208a, (345, 1)),
(0xfe80, (3858, 1)),
- (0x1d603, (4782, 1)),
+ (0x1d7f3, (5274, 1)),
(0xfd0d, (3238, 2)),
(0x1d54a, (4598, 1)),
- (0xfe79, (3844, 2)),
+ (0x1d699, (4932, 1)),
(0xfe92, (3888, 1)),
- (0x217b, (536, 3)),
- (0x1d62, (187, 1)),
- (0xfb89, (2546, 1)),
- (0x2f3d, (918, 1)),
- (0x327a, (1490, 2)),
- (0xff4c, (4084, 1)),
+ (0xfe4c, (3799, 2)),
+ (0x1d653, (4862, 1)),
+ (0x1e04b, (5314, 1)),
+ (0x1d5b8, (4707, 1)),
+ (0x1d45a, (4380, 1)),
+ (0x335b, (2024, 2)),
(0x1d789, (5170, 1)),
(0xa7f2, (2441, 1)),
- (0x2497, (694, 3)),
+ (0x1eea3, (5467, 1)),
(0xff7c, (4132, 1)),
- (0xfcaa, (3035, 2)),
+ (0x2176, (524, 3)),
(0xffa6, (4174, 1)),
(0xff57, (4095, 1)),
- (0x1d581, (4652, 1)),
- (0xff2d, (4053, 1)),
- (0x1d5a6, (4689, 1)),
- (0x1d4be, (4470, 1)),
- (0x1ee7e, (5375, 1)),
- (0xffa1, (4169, 1)),
- (0x1d7de, (5253, 1)),
- (0x1d499, (4443, 1)),
- (0xffcb, (4206, 1)),
- (0x1ee54, (5347, 1)),
+ (0x1ee79, (5433, 1)),
+ (0x1d5ae, (4697, 1)),
+ (0x1d46f, (4401, 1)),
+ (0x2da, (75, 2)),
+ (0x2f4d, (934, 1)),
+ (0xfdc5, (3681, 3)),
+ (0x3384, (2127, 2)),
+ (0x24c0, (797, 1)),
+ (0x1d57c, (4647, 1)),
+ (0x1d7b0, (5209, 1)),
(0x1d5cb, (4726, 1)),
- (0xfd2f, (3306, 2)),
+ (0x1d783, (5164, 1)),
(0x1d4e8, (4511, 1)),
- (0x1f105, (5438, 2)),
+ (0x1d58e, (4665, 1)),
(0xff0d, (4021, 1)),
- (0xfe6b, (3829, 1)),
- (0x1d4b0, (4458, 1)),
- (0x1d7e8, (5263, 1)),
+ (0x1d644, (4847, 1)),
+ (0x24c4, (801, 1)),
+ (0x2f52, (939, 1)),
(0x1d68e, (4921, 1)),
- (0x1d60a, (4789, 1)),
- (0x1d5ab, (4694, 1)),
+ (0x1d50d, (4545, 1)),
+ (0xfb6b, (2516, 1)),
+ (0x2fcb, (1060, 1)),
(0xff32, (4058, 1)),
- (0x1f13e, (5551, 1)),
(0xffab, (4179, 1)),
- (0xfeca, (3944, 1)),
- (0x1d774, (5149, 1)),
- (0xfef2, (3984, 1)),
- (0xfc46, (2818, 2)),
- (0x1d408, (4299, 1)),
- (0x33bf, (2272, 2)),
- (0x1d664, (4879, 1)),
- (0x1f224, (5610, 1)),
+ (0x316c, (1143, 1)),
+ (0x2070, (321, 1)),
+ (0xfd8d, (3519, 3)),
+ (0xfe74, (3836, 2)),
+ (0x2131, (414, 1)),
+ (0xff64, (4108, 1)),
+ (0x339b, (2180, 2)),
+ (0x1e06a, (5345, 1)),
+ (0x1f224, (5672, 1)),
(0x1d405, (4296, 1)),
- (0x3277, (1484, 2)),
+ (0xff49, (4081, 1)),
(0xff37, (4063, 1)),
- (0x33e9, (2369, 3)),
- (0x2f08, (865, 1)),
+ (0x2075, (324, 1)),
+ (0xfebe, (3932, 1)),
(0xfee8, (3974, 1)),
- (0x1d7a3, (5196, 1)),
- (0xfc64, (2884, 3)),
- (0x1ee59, (5349, 1)),
- (0x33a4, (2202, 3)),
- (0x24a2, (727, 3)),
- (0xfbfa, (2663, 3)),
- (0x33a2, (2196, 3)),
- (0xfb81, (2538, 1)),
+ (0xa7f8, (2444, 1)),
+ (0x1d7be, (5223, 1)),
+ (0x1d9d, (199, 1)),
+ (0x107b6, (4286, 1)),
+ (0x2f79, (978, 1)),
+ (0x1f212, (5653, 1)),
+ (0xfcdf, (3141, 3)),
+ (0x1d5a1, (4684, 1)),
(0xfcc9, (3097, 2)),
- (0x1d51c, (4559, 1)),
- (0x1d508, (4542, 1)),
- (0x3326, (1827, 3)),
- (0x2168, (501, 2)),
- (0x32c1, (1586, 2)),
+ (0x1ee11, (5365, 1)),
+ (0x339f, (2188, 3)),
+ (0xfb83, (2540, 1)),
+ (0x1f131, (5600, 1)),
+ (0xff08, (4016, 1)),
(0xfe9e, (3900, 1)),
(0xfe39, (3779, 1)),
- (0x249d, (712, 3)),
- (0x1d743, (5100, 1)),
- (0x1ee31, (5330, 1)),
- (0xfd1d, (3270, 2)),
- (0x1d699, (4932, 1)),
+ (0x3386, (2131, 2)),
+ (0xfd6f, (3429, 3)),
+ (0x1d58b, (4662, 1)),
+ (0x1d5f3, (4766, 1)),
+ (0x1d5f, (184, 1)),
(0xfc30, (2774, 2)),
- (0x32b7, (1566, 2)),
- (0x3274, (1478, 2)),
+ (0x33fa, (2420, 3)),
+ (0x1ee5b, (5412, 1)),
+ (0x2478, (599, 3)),
(0x1d747, (5104, 1)),
- (0xfe37, (3777, 1)),
(0xfcf8, (3196, 2)),
- (0xfcda, (3131, 2)),
+ (0x1d667, (4882, 1)),
(0x1d796, (5183, 1)),
- (0x2f2a, (899, 1)),
- (0x3292, (1523, 1)),
+ (0x2011, (286, 1)),
+ (0x1f144, (5619, 1)),
(0xfd3d, (3334, 2)),
- (0xfb85, (2542, 1)),
- (0xfcb5, (3057, 2)),
- (0x1d6c2, (4971, 1)),
- (0x2098, (358, 1)),
+ (0x3270, (1470, 2)),
+ (0x326c, (1464, 1)),
+ (0x1d5c8, (4723, 1)),
+ (0x1d68c, (4919, 1)),
+ (0xfdfb, (3745, 8)),
(0xfdb6, (3636, 3)),
- (0xfe4f, (3803, 1)),
(0x2095, (355, 1)),
- (0xfd85, (3495, 3)),
- (0x2487, (654, 4)),
- (0x1ee88, (5384, 1)),
+ (0x3219, (1278, 4)),
+ (0x2499, (700, 3)),
+ (0x1ee52, (5408, 1)),
+ (0x2dc, (79, 2)),
(0x210e, (387, 1)),
- (0xfe4b, (3797, 2)),
+ (0x1d5ce, (4729, 1)),
(0x1d687, (4914, 1)),
- (0xfbeb, (2618, 3)),
- (0x2b8, (70, 1)),
+ (0x1d702, (5035, 1)),
+ (0x2093, (353, 1)),
(0x1d615, (4800, 1)),
(0x2f0c, (869, 1)),
(0x3185, (1168, 1)),
(0x1d42a, (4333, 1)),
- (0x1cb, (52, 2)),
- (0x1d428, (4331, 1)),
+ (0x247b, (608, 3)),
+ (0xfeee, (3980, 1)),
(0x10785, (4239, 1)),
- (0x3283, (1508, 1)),
(0x209a, (360, 1)),
- (0x1d47c, (4414, 1)),
- (0xff5a, (4098, 1)),
- (0x2f01, (858, 1)),
- (0x3176, (1153, 1)),
- (0xfc43, (2812, 2)),
- (0xff5c, (4100, 1)),
- (0x1d722, (5067, 1)),
+ (0xfb72, (2523, 1)),
+ (0x33e2, (2355, 2)),
+ (0xfc75, (2924, 2)),
+ (0x24d2, (815, 1)),
+ (0x1e05b, (5330, 1)),
+ (0x212c, (410, 1)),
+ (0x247f, (622, 4)),
+ (0x1d45e, (4384, 1)),
(0xfee3, (3969, 1)),
- (0x1d720, (5065, 1)),
- (0x1d600, (4779, 1)),
+ (0x2f19, (882, 1)),
+ (0x321e, (1301, 6)),
(0x2f05, (862, 1)),
- (0x1d47e, (4416, 1)),
- (0xfc80, (2946, 2)),
- (0x1ee6a, (5359, 1)),
+ (0xfb16, (2473, 2)),
+ (0x3142, (1101, 1)),
+ (0x107a5, (4270, 1)),
(0x2001, (276, 1)),
- (0x1ee34, (5332, 1)),
- (0xfd55, (3351, 3)),
- (0x1d4c1, (4473, 1)),
+ (0xfc84, (2954, 2)),
+ (0x1d55c, (4615, 1)),
+ (0x1d7c4, (5229, 1)),
(0x2fa0, (1017, 1)),
- (0x1f109, (5446, 2)),
- (0x1d5dc, (4743, 1)),
- (0x3339, (1902, 3)),
+ (0x1f143, (5618, 1)),
+ (0x2f8f, (1000, 1)),
+ (0x24c9, (806, 1)),
+ (0x32c5, (1594, 2)),
(0x248f, (672, 2)),
- (0x247a, (605, 3)),
- (0xab5e, (2448, 1)),
- (0x2a75, (847, 2)),
- (0x1d7e6, (5261, 1)),
- (0x2f12, (875, 1)),
- (0x24a4, (733, 3)),
- (0x1d62b, (4822, 1)),
- (0x2f90, (1001, 1)),
- (0x32ff, (1668, 2)),
+ (0xff84, (4140, 1)),
+ (0x3324, (1820, 4)),
+ (0xfcb7, (3061, 2)),
+ (0x1e041, (5304, 1)),
+ (0x24d9, (822, 1)),
+ (0xfd16, (3256, 2)),
+ (0x3251, (1422, 2)),
+ (0xfc92, (2982, 2)),
(0xfe8f, (3885, 1)),
- (0x1f13b, (5548, 1)),
+ (0xfdc4, (3678, 3)),
(0x2f1c, (885, 1)),
- (0xfce1, (3147, 2)),
- (0xfc6d, (2908, 2)),
+ (0x1f22b, (5679, 1)),
+ (0x1d5db, (4742, 1)),
(0x2f41, (922, 1)),
(0xfd1b, (3266, 2)),
(0x3217, (1270, 4)),
- (0xfb77, (2528, 1)),
- (0xfe87, (3871, 2)),
+ (0x1f250, (5723, 1)),
+ (0x3321, (1809, 5)),
+ (0x2f40, (921, 1)),
(0x2fca, (1059, 1)),
- (0xff8d, (4149, 1)),
- (0x33b2, (2246, 2)),
- (0x2fd1, (1066, 1)),
+ (0x107a6, (4271, 1)),
+ (0x1d589, (4660, 1)),
(0x3136, (1089, 1)),
+ (0xfc7d, (2940, 2)),
(0xfb87, (2544, 1)),
- (0x1d485, (4423, 1)),
- (0x1d6f9, (5026, 1)),
+ (0xfc0e, (2706, 2)),
+ (0x1f106, (5502, 2)),
(0x2f65, (958, 1)),
- (0xfcc4, (3087, 2)),
- (0x1d550, (4604, 1)),
- (0x3170, (1147, 1)),
- (0x1d484, (4422, 1)),
- (0x217d, (540, 1)),
- (0x1d48f, (4433, 1)),
- (0x1d45e, (4384, 1)),
- (0x1f216, (5596, 1)),
- (0x107aa, (4275, 1)),
+ (0xfe56, (3809, 1)),
+ (0xfb9c, (2565, 1)),
+ (0xfee4, (3970, 1)),
+ (0x1ee06, (5354, 1)),
+ (0x1d6d2, (4987, 1)),
+ (0x1d45d, (4383, 1)),
+ (0x1d660, (4875, 1)),
+ (0x1f216, (5658, 1)),
+ (0x1d400, (4291, 1)),
(0xfb13, (2467, 2)),
- (0x2fc1, (1050, 1)),
- (0xff7f, (4135, 1)),
- (0xfb03, (2457, 3)),
- (0x32f9, (1662, 1)),
- (0x32d8, (1629, 1)),
+ (0xfc6f, (2912, 2)),
+ (0xfca7, (3029, 2)),
+ (0xfe13, (3760, 1)),
+ (0xfe4b, (3797, 2)),
+ (0x1d78d, (5174, 1)),
(0xff2e, (4054, 1)),
- (0x1d4e6, (4509, 1)),
- (0x2161, (484, 2)),
- (0xfe5b, (3814, 1)),
- (0xfd15, (3254, 2)),
- (0xa69c, (2438, 1)),
- (0xfef6, (3990, 3)),
+ (0x2f6b, (964, 1)),
+ (0xfbe6, (2611, 1)),
+ (0x1d4f6, (4525, 1)),
+ (0x107a8, (4273, 1)),
+ (0x328b, (1516, 1)),
+ (0x1d5c, (181, 1)),
(0x246a, (567, 2)),
- (0x3314, (1751, 2)),
- (0x2f7b, (980, 1)),
+ (0xfcb9, (3065, 2)),
+ (0xfbd6, (2594, 1)),
(0x33f7, (2411, 3)),
(0xfd08, (3228, 2)),
- (0x1d7d0, (5239, 1)),
- (0x32dc, (1633, 1)),
+ (0x32c7, (1598, 2)),
+ (0x1d684, (4911, 1)),
+ (0x1eea1, (5465, 1)),
(0xfd78, (3456, 3)),
- (0x33cc, (2303, 2)),
- (0x1f225, (5611, 1)),
- (0xfcf3, (3184, 3)),
- (0x333b, (1909, 5)),
- (0x1ee0c, (5298, 1)),
- (0x1d64e, (4857, 1)),
- (0x1d73e, (5095, 1)),
- (0xfd2d, (3302, 2)),
- (0x1f11c, (5486, 3)),
- (0x1f229, (5615, 1)),
- (0xfd7b, (3465, 3)),
+ (0x1ee80, (5438, 1)),
+ (0x1f225, (5673, 1)),
+ (0x1eeb6, (5484, 1)),
+ (0x1ee0c, (5360, 1)),
+ (0xab5c, (2446, 1)),
+ (0xfb5c, (2501, 1)),
+ (0x322e, (1349, 3)),
+ (0xfc4b, (2828, 2)),
+ (0x24c7, (804, 1)),
+ (0x3360, (2034, 2)),
(0x1d737, (5088, 1)),
- (0xfc5a, (2858, 2)),
- (0x2f54, (941, 1)),
- (0x1d35, (144, 1)),
- (0x1d5d6, (4737, 1)),
- (0x2f1a, (883, 1)),
- (0x1d771, (5146, 1)),
- (0x2083, (338, 1)),
- (0x1d753, (5116, 1)),
- (0x1d516, (4553, 1)),
- (0xfdc6, (3684, 3)),
- (0x32ce, (1616, 2)),
- (0x1d69e, (4937, 1)),
- (0x339f, (2188, 3)),
- (0xfecf, (3949, 1)),
+ (0x33d0, (2311, 2)),
+ (0xfc90, (2978, 2)),
+ (0x1eeb0, (5478, 1)),
+ (0xfda1, (3573, 3)),
+ (0x3375, (2093, 2)),
+ (0x2f00, (857, 1)),
+ (0xfb9a, (2563, 1)),
+ (0x322a, (1337, 3)),
+ (0x32a9, (1546, 1)),
+ (0x1d472, (4404, 1)),
+ (0x1d4d4, (4491, 1)),
+ (0x1f221, (5669, 1)),
+ (0xff7b, (4131, 1)),
+ (0x1d46, (160, 1)),
+ (0xffb1, (4185, 1)),
(0x1d436, (4345, 1)),
- (0xb9, (13, 1)),
- (0x1f101, (5430, 2)),
- (0xfbf9, (2660, 3)),
- (0x2154, (448, 3)),
+ (0x3298, (1529, 1)),
+ (0xfc43, (2812, 2)),
+ (0xfc31, (2776, 2)),
+ (0x1d679, (4900, 1)),
(0x315b, (1126, 1)),
- (0x10791, (4250, 1)),
- (0x1d434, (4343, 1)),
+ (0x1d712, (5051, 1)),
(0xfe99, (3895, 1)),
+ (0xfed1, (3951, 1)),
(0x339a, (2178, 2)),
(0x1d4a6, (4451, 1)),
- (0x1d470, (4402, 1)),
- (0x1d6b0, (4953, 1)),
- (0xfd02, (3216, 2)),
- (0x2fc6, (1055, 1)),
- (0x2f5d, (950, 1)),
- (0x1eeb4, (5420, 1)),
- (0x3237, (1376, 3)),
- (0x1da7, (209, 1)),
- (0x1d7e3, (5258, 1)),
- (0xfb60, (2505, 1)),
+ (0xfbd5, (2593, 1)),
+ (0x210a, (383, 1)),
+ (0xfb96, (2559, 1)),
+ (0x2f8e, (999, 1)),
+ (0x1d7a9, (5202, 1)),
+ (0xfb5e, (2503, 1)),
+ (0x10793, (4252, 1)),
+ (0x2f56, (943, 1)),
+ (0x207d, (332, 1)),
+ (0x1f227, (5675, 1)),
(0xfc94, (2986, 2)),
- (0x1d63f, (4842, 1)),
+ (0x1d4d3, (4490, 1)),
(0xfd67, (3405, 3)),
- (0x1d710, (5049, 1)),
+ (0xff09, (4017, 1)),
(0x1d5a4, (4687, 1)),
- (0xfe38, (3778, 1)),
- (0x1eeb2, (5418, 1)),
- (0xfce8, (3161, 2)),
+ (0x1e06d, (5348, 1)),
+ (0x1d39, (148, 1)),
+ (0x3210, (1242, 4)),
(0x1d721, (5066, 1)),
(0xff91, (4153, 1)),
- (0x32e2, (1639, 1)),
- (0x212d, (411, 1)),
- (0x1eea7, (5408, 1)),
- (0x1f130, (5537, 1)),
+ (0x1d62d, (4824, 1)),
+ (0x1d7c0, (5225, 1)),
+ (0x1f213, (5654, 2)),
+ (0x1f130, (5599, 1)),
+ (0x1d4d5, (4492, 1)),
(0x1db2, (220, 1)),
- (0x1d730, (5081, 1)),
(0x2f98, (1009, 1)),
- (0x1d7d3, (5242, 1)),
- (0xfc27, (2756, 2)),
- (0x247b, (608, 3)),
- (0x210a, (383, 1)),
- (0x1d478, (4410, 1)),
- (0xfc97, (2992, 3)),
+ (0x1d56a, (4629, 1)),
+ (0x2477, (596, 3)),
+ (0x1d526, (4568, 1)),
+ (0x2475, (590, 3)),
+ (0x107b8, (4288, 1)),
+ (0x1f242, (5702, 3)),
(0x587, (110, 2)),
- (0xfc45, (2816, 2)),
- (0x3311, (1737, 4)),
+ (0x1d7b3, (5212, 1)),
+ (0x2076, (325, 1)),
(0x1d6f2, (5019, 1)),
- (0x314b, (1110, 1)),
- (0x2f69, (962, 1)),
+ (0xfdbc, (3654, 3)),
+ (0x24a6, (739, 3)),
+ (0x33d4, (2320, 2)),
(0x1d4d8, (4495, 1)),
- (0x1f211, (5590, 1)),
- (0x319f, (1191, 1)),
- (0x1d6c1, (4970, 1)),
- (0x1f121, (5501, 3)),
- (0x323f, (1400, 3)),
- (0x1d66d, (4888, 1)),
+ (0x320c, (1228, 3)),
+ (0x1d57b, (4646, 1)),
+ (0x1ee15, (5369, 1)),
+ (0x24a4, (733, 3)),
+ (0x2149, (434, 1)),
(0xfbf8, (2657, 3)),
(0x2f04, (861, 1)),
(0x1d5ca, (4725, 1)),
- (0x2f29, (898, 1)),
- (0x316b, (1142, 1)),
- (0xfe50, (3804, 1)),
- (0xbc, (15, 3)),
- (0x215a, (466, 3)),
+ (0x1d57, (176, 1)),
+ (0xff22, (4042, 1)),
+ (0x1d68b, (4918, 1)),
+ (0x1d7b5, (5214, 1)),
+ (0x1d4c8, (4479, 1)),
+ (0x2088, (343, 1)),
(0x3340, (1929, 5)),
- (0x33e3, (2357, 2)),
+ (0x1d507, (4541, 1)),
(0x325d, (1446, 2)),
- (0xfc74, (2922, 2)),
+ (0x1d5fe, (4777, 1)),
(0x317c, (1159, 1)),
- (0xfe68, (3826, 1)),
- (0xfcbb, (3069, 2)),
- (0x1d58a, (4661, 1)),
- (0xfc8c, (2970, 2)),
- (0x24c6, (803, 1)),
- (0x1f110, (5450, 3)),
- (0x3253, (1426, 2)),
- (0x3178, (1155, 1)),
- (0x24b8, (789, 1)),
- (0xfd9b, (3555, 3)),
+ (0x1ee47, (5401, 1)),
+ (0x33b0, (2242, 2)),
+ (0x1d786, (5167, 1)),
+ (0xfc83, (2952, 2)),
+ (0x1d444, (4359, 1)),
+ (0x32f1, (1654, 1)),
+ (0x3152, (1117, 1)),
+ (0xff13, (4027, 1)),
+ (0xfe38, (3778, 1)),
+ (0x1d4ec, (4515, 1)),
(0xfd7e, (3474, 3)),
- (0x3038, (1073, 1)),
- (0x1d76f, (5144, 1)),
- (0x1f148, (5561, 1)),
- (0x222c, (546, 2)),
- (0x1d4e7, (4510, 1)),
- (0xffad, (4181, 1)),
- (0x24bc, (793, 1)),
- (0xff5b, (4099, 1)),
- (0x1d663, (4878, 1)),
- (0x1d5b1, (4700, 1)),
- (0x1f226, (5612, 1)),
- (0x3183, (1166, 1)),
- (0x329d, (1534, 1)),
- (0xffa9, (4177, 1)),
- (0x215c, (472, 3)),
- (0x1dbc, (230, 1)),
+ (0x336f, (2077, 3)),
+ (0x3d0, (95, 1)),
+ (0x1d7f1, (5272, 1)),
+ (0x1f251, (5724, 1)),
+ (0x1db3, (221, 1)),
+ (0x1d514, (4552, 1)),
+ (0x33fb, (2423, 3)),
+ (0xfbf1, (2636, 3)),
+ (0xfd84, (3492, 3)),
+ (0x1fbf3, (5728, 1)),
+ (0x328a, (1515, 1)),
+ (0x24ab, (754, 3)),
+ (0x1d7e7, (5262, 1)),
+ (0x335c, (2026, 2)),
+ (0xff85, (4141, 1)),
+ (0x1d4bd, (4469, 1)),
(0xfdb5, (3633, 3)),
- (0x1d5f9, (4772, 1)),
- (0x2f0b, (868, 1)),
- (0x326c, (1464, 1)),
- (0x1d482, (4420, 1)),
- (0xfc20, (2742, 2)),
+ (0xfdf2, (3696, 4)),
+ (0xfe83, (3863, 2)),
+ (0x1fdd, (256, 3)),
+ (0xfc7b, (2936, 2)),
+ (0x319a, (1186, 1)),
(0x3275, (1480, 2)),
- (0x208d, (348, 1)),
- (0x2f2f, (904, 1)),
- (0x1d422, (4325, 1)),
- (0x1d6e9, (5010, 1)),
+ (0xfd20, (3276, 2)),
+ (0x1d402, (4293, 1)),
+ (0xff67, (4111, 1)),
+ (0x1d7dd, (5252, 1)),
+ (0xfc2e, (2770, 2)),
(0xff04, (4012, 1)),
- (0xfce3, (3151, 2)),
- (0x1ee02, (5289, 1)),
- (0xfe97, (3893, 1)),
+ (0x1eeb1, (5479, 1)),
+ (0x3317, (1765, 5)),
(0x3367, (2053, 3)),
+ (0x1d652, (4861, 1)),
(0x337e, (2113, 2)),
- (0xbe, (21, 3)),
- (0xfbfd, (2670, 1)),
- (0x2461, (557, 1)),
- (0x249f, (718, 3)),
+ (0x1d9c, (198, 1)),
+ (0x1079e, (4263, 1)),
+ (0x2f5f, (952, 1)),
(0xfea6, (3908, 1)),
- (0x1f21b, (5601, 1)),
- (0x1ee90, (5391, 1)),
+ (0x1d66, (191, 1)),
+ (0x1ee90, (5453, 1)),
+ (0x1d723, (5068, 1)),
(0x247e, (618, 4)),
- (0x1d6c5, (4974, 1)),
- (0x330a, (1711, 3)),
- (0x1d535, (4583, 1)),
- (0x1d46, (160, 1)),
- (0xff78, (4128, 1)),
- (0x3f2, (106, 1)),
- (0x2086, (341, 1)),
+ (0x216b, (506, 3)),
+ (0x1d74c, (5109, 1)),
+ (0x1d68d, (4920, 1)),
+ (0x3211, (1246, 4)),
+ (0x1d77f, (5160, 1)),
+ (0xff86, (4142, 1)),
+ (0x2f18, (881, 1)),
(0x3347, (1953, 5)),
- (0x1d65, (190, 1)),
- (0x1d775, (5150, 1)),
- (0x3236, (1373, 3)),
- (0xa7f4, (2443, 1)),
- (0x2fc0, (1049, 1)),
- (0x2f22, (891, 1)),
- (0x1ee09, (5295, 1)),
- (0x3197, (1183, 1)),
- (0xeb3, (122, 2)),
- (0x10790, (4249, 1)),
+ (0xfc72, (2918, 2)),
+ (0x1d496, (4440, 1)),
+ (0x1f129, (5587, 3)),
+ (0x210d, (386, 1)),
+ (0x1d40e, (4305, 1)),
+ (0x1d4e0, (4503, 1)),
+ (0x1d571, (4636, 1)),
+ (0x200a, (285, 1)),
+ (0x1d53d, (4590, 1)),
(0x2099, (359, 1)),
- (0xfb69, (2514, 1)),
- (0x1fdf, (262, 3)),
- (0x1d701, (5034, 1)),
- (0xfcf0, (3177, 2)),
- (0x1ee0a, (5296, 1)),
- (0x3360, (2034, 2)),
- (0x2f21, (890, 1)),
- (0x1d6fe, (5031, 1)),
- (0x3276, (1482, 2)),
- (0xff1e, (4038, 1)),
+ (0x2a75, (847, 2)),
+ (0xfe40, (3786, 1)),
+ (0xfebd, (3931, 1)),
+ (0x1d44b, (4366, 1)),
+ (0x32d3, (1624, 1)),
+ (0x1d666, (4881, 1)),
+ (0xfbaa, (2581, 1)),
+ (0x2f7e, (983, 1)),
+ (0xff77, (4127, 1)),
+ (0xff25, (4045, 1)),
+ (0x1d693, (4926, 1)),
(0xfeb6, (3924, 1)),
(0x1d695, (4928, 1)),
- (0x1d4f5, (4524, 1)),
- (0x1da1, (203, 1)),
+ (0xffd5, (4214, 1)),
+ (0x1d491, (4435, 1)),
(0x3359, (2020, 2)),
- (0x1d5a7, (4690, 1)),
- (0x1d504, (4539, 1)),
- (0x1ee32, (5331, 1)),
+ (0x1d57f, (4650, 1)),
+ (0xffd7, (4216, 1)),
+ (0x1ee32, (5393, 1)),
(0x3267, (1459, 1)),
+ (0xfd30, (3308, 2)),
(0xfbed, (2624, 3)),
- (0x1d536, (4584, 1)),
- (0xff38, (4064, 1)),
- (0x24b2, (775, 3)),
- (0x1d6d3, (4988, 1)),
+ (0xfd94, (3534, 3)),
+ (0x3278, (1486, 2)),
+ (0xff97, (4159, 1)),
(0x1d686, (4913, 1)),
- (0x32a5, (1542, 1)),
- (0x1d552, (4605, 1)),
- (0x2fcf, (1064, 1)),
- (0x1d6aa, (4947, 1)),
- (0x331d, (1793, 3)),
- (0xfd7f, (3477, 3)),
+ (0x1f108, (5506, 2)),
+ (0x2f2c, (901, 1)),
+ (0xfcd1, (3113, 2)),
+ (0x2468, (564, 1)),
+ (0xfe3e, (3784, 1)),
+ (0xff66, (4110, 1)),
(0xff14, (4028, 1)),
- (0x1d79c, (5189, 1)),
- (0xfe71, (3832, 2)),
- (0x248e, (670, 2)),
+ (0x1d74d, (5110, 1)),
+ (0x32f5, (1658, 1)),
+ (0x33cd, (2305, 2)),
(0x2469, (565, 2)),
- (0x1f230, (5622, 1)),
- (0x1f113, (5459, 3)),
- (0x1d481, (4419, 1)),
+ (0x32b4, (1560, 2)),
+ (0x1d65b, (4870, 1)),
+ (0x1f113, (5521, 3)),
+ (0x2155, (451, 3)),
(0x1daa, (212, 1)),
- (0x30ff, (1082, 2)),
- (0x1d7cb, (5236, 1)),
- (0xff31, (4057, 1)),
- (0x339d, (2184, 2)),
+ (0xfed6, (3956, 1)),
+ (0x1d5bd, (4712, 1)),
+ (0x1e045, (5308, 1)),
+ (0xfdf3, (3700, 4)),
(0xfb8c, (2549, 1)),
- (0x2f5b, (948, 1)),
- (0x2f62, (955, 1)),
- (0x1d44, (158, 1)),
+ (0x1d7d4, (5243, 1)),
+ (0x2b8, (70, 1)),
(0x1d565, (4624, 1)),
- (0x2071, (322, 1)),
- (0x247c, (611, 3)),
- (0x1f142, (5555, 1)),
- (0x10792, (4251, 1)),
- (0x1d544, (4596, 1)),
- (0x1d6fa, (5027, 1)),
- (0x2d9, (73, 2)),
- (0x1d573, (4638, 1)),
- (0x2f5c, (949, 1)),
- (0x1d7a7, (5200, 1)),
+ (0x2fd5, (1070, 1)),
+ (0x1d4af, (4457, 1)),
+ (0xfcf2, (3181, 3)),
+ (0x1f142, (5617, 1)),
+ (0x3195, (1181, 1)),
+ (0x1d56c, (4631, 1)),
+ (0xfd0e, (3240, 2)),
+ (0x1eeb7, (5485, 1)),
+ (0xff54, (4092, 1)),
+ (0x678, (118, 2)),
+ (0xfbee, (2627, 3)),
(0x1d540, (4592, 1)),
- (0xfdbb, (3651, 3)),
+ (0x33be, (2270, 2)),
(0xfead, (3915, 1)),
(0x1d40c, (4303, 1)),
- (0x3362, (2038, 3)),
- (0x1d61d, (4808, 1)),
- (0x33d5, (2322, 3)),
+ (0xfb23, (2480, 1)),
+ (0xfee6, (3972, 1)),
+ (0xffa1, (4169, 1)),
(0x1d674, (4895, 1)),
(0x1d36, (145, 1)),
- (0x1d5c8, (4723, 1)),
- (0x1d724, (5069, 1)),
- (0x1d400, (4291, 1)),
+ (0x2106, (377, 3)),
+ (0x3231, (1358, 3)),
+ (0x1ee59, (5411, 1)),
(0x3338, (1898, 4)),
(0x1d7c3, (5228, 1)),
- (0x2fae, (1031, 1)),
- (0x1d30, (139, 1)),
- (0x33ea, (2372, 3)),
- (0x1f234, (5626, 1)),
- (0xffe1, (4221, 1)),
+ (0x107b5, (4285, 1)),
+ (0x2b0, (62, 1)),
+ (0xfc36, (2786, 2)),
+ (0x1f234, (5688, 1)),
+ (0x1d473, (4405, 1)),
(0x313f, (1098, 1)),
- (0x1d56d, (4632, 1)),
- (0xfc0f, (2708, 2)),
+ (0xfd7b, (3465, 3)),
+ (0x3154, (1119, 1)),
+ (0x1ee31, (5392, 1)),
(0xffae, (4182, 1)),
- (0x3336, (1890, 5)),
- (0x3355, (2007, 2)),
- (0x1ee4b, (5341, 1)),
- (0xff7b, (4131, 1)),
+ (0x1d4b, (165, 1)),
+ (0x1ee4b, (5403, 1)),
+ (0x1d672, (4893, 1)),
(0x313b, (1094, 1)),
- (0xffa7, (4175, 1)),
- (0x1d6bc, (4965, 1)),
+ (0x1d7ae, (5207, 1)),
+ (0xfd35, (3318, 2)),
(0x3200, (1192, 3)),
- (0xfc0d, (2704, 2)),
- (0x1d62e, (4825, 1)),
- (0x3263, (1455, 1)),
- (0x1d72b, (5076, 1)),
- (0xfb61, (2506, 1)),
+ (0xff19, (4033, 1)),
+ (0x1d538, (4586, 1)),
+ (0x1f105, (5500, 2)),
+ (0x2f3a, (915, 1)),
+ (0xff2d, (4053, 1)),
+ (0x1ee03, (5352, 1)),
(0x2fc5, (1054, 1)),
- (0x2f19, (882, 1)),
+ (0xfc19, (2728, 2)),
(0xfb27, (2484, 1)),
- (0x1d4b1, (4459, 1)),
- (0x1d44a, (4365, 1)),
- (0x1ee2a, (5323, 1)),
- (0x1d50e, (4546, 1)),
+ (0x2f31, (906, 1)),
+ (0x2a76, (849, 3)),
+ (0x1d655, (4864, 1)),
+ (0x1d47e, (4416, 1)),
(0x246f, (577, 2)),
- (0xab5f, (2449, 1)),
- (0x1d4b7, (4465, 1)),
- (0xfccb, (3101, 2)),
- (0x321d, (1294, 7)),
- (0xfd0b, (3234, 2)),
- (0xfcab, (3037, 2)),
- (0x3175, (1152, 1)),
- (0xfeaf, (3917, 1)),
- (0xff8a, (4146, 1)),
+ (0x2f13, (876, 1)),
+ (0x1f233, (5687, 1)),
+ (0x1d59f, (4682, 1)),
+ (0x2497, (694, 3)),
+ (0x2e9f, (855, 1)),
+ (0x32dd, (1634, 1)),
+ (0xfd28, (3292, 2)),
+ (0x1d7bb, (5220, 1)),
+ (0x1d7d2, (5241, 1)),
(0x32e1, (1638, 1)),
(0x1d69b, (4934, 1)),
- (0x1f12e, (5535, 2)),
- (0x3376, (2095, 2)),
+ (0x107ac, (4277, 1)),
+ (0xfc93, (2984, 2)),
(0x2f34, (909, 1)),
(0x2490, (674, 2)),
- (0x1d439, (4348, 1)),
- (0x2471, (581, 2)),
- (0x2f30, (905, 1)),
+ (0xfb6e, (2519, 1)),
+ (0x1f12d, (5595, 2)),
+ (0xfba1, (2570, 1)),
(0x1d48d, (4431, 1)),
- (0x1d736, (5087, 1)),
- (0xfd9e, (3564, 3)),
- (0xfe88, (3873, 2)),
- (0xfc21, (2744, 2)),
- (0xfee6, (3972, 1)),
- (0x140, (30, 2)),
- (0x207f, (334, 1)),
+ (0x1f228, (5676, 1)),
+ (0x2471, (581, 2)),
+ (0xfb59, (2498, 1)),
+ (0xfec3, (3937, 1)),
+ (0x329a, (1531, 1)),
+ (0x33c9, (2297, 2)),
+ (0x1dbd, (231, 1)),
(0x1d474, (4406, 1)),
(0x1d673, (4894, 1)),
- (0x107b4, (4284, 1)),
- (0x2f72, (971, 1)),
+ (0xffe1, (4221, 1)),
+ (0x1d4c3, (4475, 1)),
(0x1d649, (4852, 1)),
- (0x1d7cf, (5238, 1)),
- (0xfcd3, (3117, 2)),
- (0x1f21c, (5602, 1)),
- (0xfcd5, (3121, 2)),
+ (0xfed2, (3952, 1)),
+ (0x3205, (1207, 3)),
+ (0x1d537, (4585, 1)),
+ (0xfcd9, (3129, 2)),
+ (0x3140, (1099, 1)),
(0x309f, (1080, 2)),
- (0x1d7be, (5223, 1)),
- (0x1f237, (5629, 1)),
- (0x33df, (2348, 3)),
- (0xff77, (4127, 1)),
- (0x2175, (522, 2)),
- (0x2107, (380, 1)),
- (0xfca4, (3023, 2)),
- (0xfc01, (2676, 3)),
- (0xfc3a, (2794, 2)),
- (0x1f2, (58, 2)),
- (0xfef4, (3986, 1)),
+ (0xff58, (4096, 1)),
+ (0x1d707, (5040, 1)),
+ (0x1d5d8, (4739, 1)),
+ (0x2f5e, (951, 1)),
+ (0x329c, (1533, 1)),
+ (0x1ee8f, (5452, 1)),
+ (0x1f21a, (5662, 1)),
+ (0x1fc1, (244, 3)),
+ (0x1d71b, (5060, 1)),
+ (0x1ee29, (5384, 1)),
+ (0x2f5d, (950, 1)),
(0x3346, (1950, 3)),
- (0x328f, (1520, 1)),
- (0x1d56, (175, 1)),
- (0x3361, (2036, 2)),
- (0x1f23a, (5632, 1)),
- (0x1ee2f, (5328, 1)),
- (0x1d5eb, (4758, 1)),
- (0xfc9a, (3001, 3)),
- (0x1d4e1, (4504, 1)),
- (0xfd58, (3360, 3)),
- (0x24c0, (797, 1)),
- (0x3254, (1428, 2)),
+ (0x33cc, (2303, 2)),
+ (0x1d676, (4897, 1)),
+ (0x2fc1, (1050, 1)),
+ (0x1d604, (4783, 1)),
+ (0x1d4ed, (4516, 1)),
+ (0x1d508, (4542, 1)),
+ (0xfd5d, (3375, 3)),
+ (0x1d5a7, (4690, 1)),
+ (0x1e033, (5290, 1)),
+ (0xb8, (11, 2)),
(0xffda, (4217, 1)),
- (0x107b6, (4286, 1)),
- (0x249c, (709, 3)),
+ (0x3273, (1476, 2)),
+ (0xff21, (4041, 1)),
(0x24cf, (812, 1)),
- (0x2153, (445, 3)),
- (0x1d5f1, (4764, 1)),
- (0x1ee8d, (5388, 1)),
- (0x1d46f, (4401, 1)),
- (0x2f8b, (996, 1)),
- (0x2fd0, (1065, 1)),
+ (0x3332, (1871, 6)),
+ (0x1d413, (4310, 1)),
+ (0x249c, (709, 3)),
+ (0xff30, (4056, 1)),
+ (0x1ee68, (5419, 1)),
+ (0x1d5b0, (4699, 1)),
+ (0xfbd7, (2595, 1)),
(0x3133, (1086, 1)),
(0xfd33, (3314, 2)),
- (0xfd87, (3501, 3)),
- (0x3187, (1170, 1)),
- (0xffba, (4194, 1)),
- (0x1d50, (169, 1)),
- (0x1d5cc, (4727, 1)),
+ (0xfc12, (2714, 2)),
+ (0x334a, (1964, 6)),
+ (0x1d48f, (4433, 1)),
+ (0xff17, (4031, 1)),
+ (0x13f, (28, 2)),
(0x32c8, (1600, 2)),
- (0xfb80, (2537, 1)),
- (0x1d68b, (4918, 1)),
- (0xfb74, (2525, 1)),
+ (0xfe63, (3822, 1)),
+ (0x1d6f7, (5024, 1)),
+ (0x33e6, (2363, 2)),
(0x1d689, (4916, 1)),
- (0x213b, (422, 3)),
- (0xfbaf, (2586, 1)),
+ (0x1d7fc, (5283, 1)),
+ (0x2167, (497, 4)),
(0x1da2, (204, 1)),
- (0x1d4b, (165, 1)),
+ (0x1eea8, (5471, 1)),
(0x3169, (1140, 1)),
- (0xfed9, (3959, 1)),
- (0x1ee97, (5398, 1)),
- (0x1d446, (4361, 1)),
- (0x1f190, (5582, 2)),
- (0x1d411, (4308, 1)),
- (0xfc61, (2875, 3)),
+ (0xaf, (4, 2)),
+ (0xfcb6, (3059, 2)),
+ (0xfbeb, (2618, 3)),
+ (0xfe61, (3820, 1)),
+ (0x1d6f5, (5022, 1)),
+ (0x3277, (1484, 2)),
(0x321b, (1286, 4)),
- (0x1d45c, (4382, 1)),
- (0xfc9f, (3013, 2)),
- (0xfb14, (2469, 2)),
- (0x1f14c, (5567, 2)),
- (0xfbee, (2627, 3)),
- (0xfbe6, (2611, 1)),
- (0x3d1, (96, 1)),
- (0x1d5f, (184, 1)),
- (0x3341, (1934, 3)),
- (0x1d5db, (4742, 1)),
- (0x1d6cf, (4984, 1)),
- (0xff41, (4073, 1)),
+ (0xfc28, (2758, 2)),
+ (0x1d51c, (4559, 1)),
+ (0xff92, (4154, 1)),
+ (0x3395, (2168, 2)),
+ (0x1d5fd, (4776, 1)),
+ (0x1d722, (5067, 1)),
+ (0x2f99, (1010, 1)),
+ (0x33a4, (2202, 3)),
+ (0x3d6, (103, 1)),
+ (0x24e8, (837, 1)),
+ (0x212f, (412, 1)),
+ (0x1f201, (5648, 2)),
(0xfec0, (3934, 1)),
- (0x3396, (2170, 2)),
+ (0x1d67d, (4904, 1)),
(0x33a1, (2194, 2)),
- (0xfda7, (3591, 3)),
+ (0xfca6, (3027, 2)),
(0x2f85, (990, 1)),
+ (0x37a, (88, 2)),
(0x32cf, (1618, 3)),
- (0xfcdc, (3135, 2)),
- (0x3259, (1438, 2)),
- (0x1d667, (4882, 1)),
- (0xfdbc, (3654, 3)),
- (0x32f0, (1653, 1)),
- (0x33ca, (2299, 2)),
+ (0x1f200, (5646, 2)),
+ (0x2e4, (87, 1)),
+ (0x1d75e, (5127, 1)),
+ (0x1d4a5, (4450, 1)),
+ (0xfed0, (3950, 1)),
+ (0x3269, (1461, 1)),
(0x1d55e, (4617, 1)),
- (0xff9d, (4165, 1)),
- (0xfc7f, (2944, 2)),
+ (0x1d439, (4348, 1)),
(0x1d5b5, (4704, 1)),
- (0xffb3, (4187, 1)),
- (0x1f10a, (5448, 2)),
- (0x1d748, (5105, 1)),
- (0x24a3, (730, 3)),
+ (0xfc64, (2884, 3)),
+ (0xfeb0, (3918, 1)),
+ (0xfbd8, (2596, 1)),
+ (0x3147, (1106, 1)),
+ (0xfbe3, (2608, 1)),
(0x2113, (392, 1)),
- (0xfee1, (3967, 1)),
- (0x1d64c, (4855, 1)),
- (0xfcfd, (3206, 2)),
+ (0x1e05f, (5334, 1)),
+ (0x3368, (2056, 3)),
(0xff4e, (4086, 1)),
(0x1d6a9, (4946, 1)),
- (0xffd5, (4214, 1)),
- (0x2fd3, (1068, 1)),
- (0x1d595, (4672, 1)),
- (0x1ee12, (5304, 1)),
- (0xfda2, (3576, 3)),
- (0xfc67, (2893, 3)),
- (0x2fb8, (1041, 1)),
+ (0xfb6d, (2518, 1)),
+ (0x332b, (1840, 6)),
+ (0x334c, (1973, 5)),
+ (0xfb52, (2491, 1)),
+ (0x1d426, (4329, 1)),
+ (0xab5f, (2449, 1)),
+ (0xfe5d, (3816, 1)),
+ (0x1d6bf, (4968, 1)),
(0x1d6b5, (4958, 1)),
- (0xfe48, (3792, 1)),
+ (0xfba6, (2577, 1)),
(0x1ffe, (273, 2)),
- (0x24bb, (792, 1)),
- (0x216d, (510, 1)),
- (0x1d6af, (4952, 1)),
- (0x2173, (519, 2)),
+ (0xfbd4, (2592, 1)),
+ (0xfc6d, (2908, 2)),
+ (0xff20, (4040, 1)),
+ (0x1d5ab, (4694, 1)),
(0x1d5f2, (4765, 1)),
- (0xfb59, (2498, 1)),
- (0x1d77e, (5159, 1)),
+ (0x325c, (1444, 2)),
+ (0xfe42, (3788, 1)),
(0x3383, (2125, 2)),
(0xfb22, (2479, 1)),
- (0x24a8, (745, 3)),
- (0x1d6c8, (4977, 1)),
+ (0x1d5ec, (4759, 1)),
+ (0x1d63e, (4841, 1)),
(0xfc7a, (2934, 2)),
- (0xfd8a, (3510, 3)),
- (0x1d773, (5148, 1)),
- (0xfc5e, (2866, 3)),
- (0x1f213, (5592, 2)),
+ (0x1d4cb, (4482, 1)),
+ (0xfd9f, (3567, 3)),
+ (0x319f, (1191, 1)),
+ (0x1d521, (4563, 1)),
(0x217f, (542, 1)),
(0x3238, (1379, 3)),
+ (0x1d438, (4347, 1)),
(0xffa4, (4172, 1)),
- (0x1ee0e, (5300, 1)),
- (0xfdb8, (3642, 3)),
- (0x3196, (1182, 1)),
+ (0x24aa, (751, 3)),
+ (0xba, (14, 1)),
(0xfc79, (2932, 2)),
- (0x1d633, (4830, 1)),
- (0x1d4d4, (4491, 1)),
+ (0xfe5b, (3814, 1)),
+ (0x1ee02, (5351, 1)),
(0x32fb, (1664, 1)),
(0x2d8, (71, 2)),
- (0x1d5ff, (4778, 1)),
- (0x3d5, (102, 1)),
- (0x2103, (372, 2)),
+ (0x32da, (1631, 1)),
+ (0x338c, (2146, 2)),
+ (0xfd2b, (3298, 2)),
(0xfd06, (3224, 2)),
- (0x1d597, (4674, 1)),
+ (0x32b0, (1553, 1)),
+ (0x1e03e, (5301, 1)),
(0x2fab, (1028, 1)),
- (0x1d67d, (4904, 1)),
- (0x322c, (1343, 3)),
- (0xfbdb, (2599, 1)),
- (0xfd12, (3248, 2)),
+ (0x210c, (385, 1)),
+ (0xfcd6, (3123, 2)),
+ (0x2164, (491, 1)),
(0xff83, (4139, 1)),
+ (0x24b4, (781, 3)),
(0x2f94, (1005, 1)),
- (0x2483, (638, 4)),
- (0x1d799, (5186, 1)),
- (0x2140, (429, 1)),
- (0xfdc4, (3678, 3)),
+ (0x32ed, (1650, 1)),
+ (0x3232, (1361, 3)),
+ (0x2f59, (946, 1)),
+ (0xff33, (4059, 1)),
(0x3262, (1454, 1)),
- (0xfda9, (3597, 3)),
- (0x1d6f0, (5017, 1)),
+ (0x330e, (1725, 4)),
+ (0x2489, (660, 2)),
(0x2fb5, (1038, 1)),
(0xfeea, (3976, 1)),
- (0x313d, (1096, 1)),
- (0x32f5, (1658, 1)),
+ (0x2fc8, (1057, 1)),
+ (0x215e, (478, 3)),
(0xff05, (4013, 1)),
- (0x1d616, (4801, 1)),
- (0x1ee1d, (5315, 1)),
- (0x3159, (1124, 1)),
- (0x1d457, (4377, 1)),
- (0xfe78, (3842, 2)),
- (0x2f31, (906, 1)),
+ (0x2f8a, (995, 1)),
+ (0x1ee1d, (5377, 1)),
+ (0xfebb, (3929, 1)),
+ (0x1d67f, (4906, 1)),
+ (0xfe93, (3889, 1)),
+ (0xfecf, (3949, 1)),
(0xfbfb, (2666, 3)),
- (0x2085, (340, 1)),
+ (0x1d6d6, (4991, 1)),
(0x2152, (441, 4)),
- (0x1d7f2, (5273, 1)),
- (0x1ee4f, (5344, 1)),
- (0xfc37, (2788, 2)),
- (0x1d459, (4379, 1)),
+ (0x1db7, (225, 1)),
+ (0x1f14a, (5625, 2)),
+ (0xfbdc, (2600, 1)),
+ (0x1d694, (4927, 1)),
(0x2158, (460, 3)),
(0x1d63d, (4840, 1)),
- (0xfee2, (3968, 1)),
- (0xfed5, (3955, 1)),
+ (0x2101, (368, 3)),
+ (0x2137, (419, 1)),
(0xfdc0, (3666, 3)),
- (0x1f238, (5630, 1)),
- (0xff9c, (4164, 1)),
- (0x1d40, (154, 1)),
+ (0x1d7a3, (5196, 1)),
+ (0x1d54, (173, 1)),
+ (0x10797, (4256, 1)),
(0x3268, (1460, 1)),
(0x10795, (4254, 1)),
(0x33b9, (2260, 2)),
+ (0xfc02, (2679, 3)),
(0x332f, (1861, 4)),
- (0x1f251, (5662, 1)),
- (0xff6e, (4118, 1)),
- (0x1d606, (4785, 1)),
- (0x32e6, (1643, 1)),
- (0xfc4c, (2830, 2)),
- (0x1d432, (4341, 1)),
- (0xfcf1, (3179, 2)),
- (0x1f13d, (5550, 1)),
- (0x32c5, (1594, 2)),
+ (0x213d, (426, 1)),
+ (0x3283, (1508, 1)),
+ (0x2f15, (878, 1)),
+ (0x1d453, (4374, 1)),
+ (0x107b0, (4281, 1)),
+ (0x2f33, (908, 1)),
+ (0xfe7f, (3856, 2)),
+ (0x1d7eb, (5266, 1)),
+ (0x32ca, (1605, 3)),
(0xedc, (124, 2)),
- (0x1fbf8, (5671, 1)),
- (0x2474, (587, 3)),
+ (0xffed, (4233, 1)),
(0x1d7ca, (5235, 1)),
- (0xfd0c, (3236, 2)),
- (0xfbef, (2630, 3)),
+ (0x3265, (1457, 1)),
+ (0x3389, (2138, 4)),
(0xfcaf, (3045, 2)),
(0xfd69, (3411, 3)),
- (0x2b7, (69, 1)),
- (0x1d57d, (4648, 1)),
- (0x24db, (824, 1)),
- (0x1d5b7, (4706, 1)),
- (0x33b3, (2248, 2)),
- (0xfb98, (2561, 1)),
- (0x1d47a, (4412, 1)),
+ (0x32a4, (1541, 1)),
+ (0x2f75, (974, 1)),
+ (0x2c7c, (852, 1)),
+ (0x2fae, (1031, 1)),
+ (0xff2c, (4052, 1)),
+ (0xfdf1, (3693, 3)),
+ (0x1d613, (4798, 1)),
+ (0xfc73, (2920, 2)),
(0x1d495, (4439, 1)),
- (0xfb7d, (2534, 1)),
- (0x2b1, (63, 1)),
+ (0x1d4ea, (4513, 1)),
(0xa7f3, (2442, 1)),
(0x1d7e5, (5260, 1)),
- (0xfeb4, (3922, 1)),
- (0xfb7f, (2536, 1)),
- (0x2f88, (993, 1)),
- (0x24c9, (806, 1)),
- (0x1f246, (5652, 3)),
- (0xfc10, (2710, 2)),
- (0x1f16b, (5578, 2)),
- (0x2074, (323, 1)),
- (0x3209, (1219, 3)),
- (0x338a, (2142, 2)),
+ (0xfe85, (3867, 2)),
+ (0x1d4f2, (4521, 1)),
+ (0x1d65e, (4873, 1)),
+ (0x1d7c6, (5231, 1)),
+ (0x2103, (372, 2)),
+ (0x2083, (338, 1)),
+ (0xfc33, (2780, 2)),
+ (0x333d, (1918, 5)),
+ (0xfcef, (3175, 2)),
+ (0xfeb8, (3926, 1)),
+ (0x32fd, (1666, 1)),
(0x1d74b, (5108, 1)),
- (0x1f21d, (5603, 1)),
- (0x1eeb1, (5417, 1)),
- (0x2157, (457, 3)),
- (0x1ee10, (5302, 1)),
- (0x1f106, (5440, 2)),
+ (0x247c, (611, 3)),
+ (0x1079d, (4262, 1)),
+ (0x1e052, (5321, 1)),
+ (0x1ee10, (5364, 1)),
+ (0x2f7d, (982, 1)),
(0xfda4, (3582, 3)),
- (0x2f91, (1002, 1)),
- (0x24a1, (724, 3)),
+ (0x323a, (1385, 3)),
+ (0x3157, (1122, 1)),
(0x33c0, (2274, 2)),
(0x1f3, (60, 2)),
- (0xff54, (4092, 1)),
+ (0xfc51, (2840, 2)),
(0xfe15, (3762, 1)),
(0x3204, (1204, 3)),
(0x3397, (2172, 2)),
- (0xff02, (4010, 1)),
- (0x32e8, (1645, 1)),
- (0x2094, (354, 1)),
- (0x1d652, (4861, 1)),
- (0x1d442, (4357, 1)),
- (0x1f135, (5542, 1)),
+ (0x1d4e2, (4505, 1)),
+ (0x32ce, (1616, 2)),
+ (0xfb69, (2514, 1)),
+ (0x1d6fc, (5029, 1)),
+ (0x32a5, (1542, 1)),
+ (0xfe9a, (3896, 1)),
(0x1dbe, (232, 1)),
- (0x1db7, (225, 1)),
- (0x1d475, (4407, 1)),
- (0xfdf0, (3690, 3)),
- (0x2133, (415, 1)),
- (0x2e4, (87, 1)),
- (0x2f0e, (871, 1)),
+ (0x2090, (350, 1)),
+ (0xfbd9, (2597, 1)),
+ (0x1d778, (5153, 1)),
+ (0x1d6d7, (4992, 1)),
+ (0x1d7bf, (5224, 1)),
+ (0xfda8, (3594, 3)),
(0x3391, (2156, 3)),
(0xfc5b, (2860, 2)),
- (0x1d41f, (4322, 1)),
- (0x1d758, (5121, 1)),
- (0x2f53, (940, 1)),
- (0x1f222, (5608, 1)),
- (0x1d671, (4892, 1)),
- (0xff07, (4015, 1)),
- (0xff19, (4033, 1)),
- (0x1d538, (4586, 1)),
+ (0x2467, (563, 1)),
+ (0x1d7f0, (5271, 1)),
+ (0x3186, (1169, 1)),
+ (0x2f10, (873, 1)),
+ (0x1d5e3, (4750, 1)),
+ (0xfce5, (3155, 2)),
+ (0x1d75a, (5123, 1)),
+ (0xa7f9, (2445, 1)),
(0x1d580, (4651, 1)),
- (0x1f247, (5655, 3)),
- (0x1fbf3, (5666, 1)),
- (0x1f23b, (5633, 1)),
- (0x2496, (691, 3)),
- (0x1d4d3, (4490, 1)),
- (0x1d44e, (4369, 1)),
+ (0x1d49b, (4445, 1)),
+ (0x2151, (438, 3)),
+ (0x1f23b, (5695, 1)),
+ (0xfcad, (3041, 2)),
+ (0x32b7, (1566, 2)),
+ (0x1d5cf, (4730, 1)),
+ (0x1d790, (5177, 1)),
(0x1d6cd, (4982, 1)),
- (0x335b, (2024, 2)),
+ (0xffcc, (4207, 1)),
(0x3307, (1698, 6)),
(0x1d7df, (5254, 1)),
- (0x1f147, (5560, 1)),
- (0x1d692, (4925, 1)),
- (0x3146, (1105, 1)),
+ (0x2f07, (864, 1)),
+ (0x24d5, (818, 1)),
(0x1d5a0, (4683, 1)),
+ (0xfb85, (2542, 1)),
(0x1d520, (4562, 1)),
- (0xfc1b, (2732, 2)),
- (0x1ee47, (5339, 1)),
- (0xfc42, (2810, 2)),
- (0x2fa4, (1021, 1)),
- (0x2f06, (863, 1)),
- (0xfe4e, (3802, 1)),
- (0x3250, (1419, 3)),
- (0x3342, (1937, 3)),
- (0x1d532, (4580, 1)),
- (0x1ee71, (5365, 1)),
+ (0x1d4d1, (4488, 1)),
+ (0x2461, (557, 1)),
+ (0x1d452, (4373, 1)),
+ (0xfb70, (2521, 1)),
+ (0x1d69f, (4938, 1)),
+ (0x1d594, (4671, 1)),
+ (0x3271, (1472, 2)),
+ (0x1e057, (5326, 1)),
+ (0x1d40, (154, 1)),
+ (0x1ee27, (5383, 1)),
(0xfd34, (3316, 2)),
- (0xfba5, (2575, 2)),
- (0xffb1, (4185, 1)),
+ (0x209b, (361, 1)),
+ (0x1d578, (4643, 1)),
(0xff56, (4094, 1)),
- (0x315c, (1127, 1)),
+ (0x2121, (403, 3)),
(0x3148, (1107, 1)),
- (0x1f233, (5625, 1)),
- (0xff1d, (4037, 1)),
- (0x3167, (1138, 1)),
- (0x2130, (413, 1)),
- (0x2f67, (960, 1)),
- (0x1d59d, (4680, 1)),
- (0x1d71a, (5059, 1)),
- (0x1d68f, (4922, 1)),
- (0x1d681, (4908, 1)),
- (0x1d46e, (4400, 1)),
- (0x1d74e, (5111, 1)),
+ (0x2f3d, (918, 1)),
+ (0x1d724, (5069, 1)),
+ (0x2166, (494, 3)),
+ (0x2f1b, (884, 1)),
+ (0x1d5ea, (4757, 1)),
+ (0xfc05, (2688, 2)),
+ (0x336a, (2062, 3)),
+ (0x24a3, (730, 3)),
+ (0x3320, (1804, 5)),
+ (0x1ee82, (5440, 1)),
+ (0x3344, (1944, 3)),
(0x210b, (384, 1)),
- (0x1d6a, (195, 1)),
- (0x1ee30, (5329, 1)),
- (0xfcb4, (3055, 2)),
- (0x1ee1a, (5312, 1)),
- (0xff2c, (4052, 1)),
- (0x2e2, (85, 1)),
+ (0x1d560, (4619, 1)),
+ (0x1ee30, (5391, 1)),
+ (0x24e5, (834, 1)),
+ (0xffea, (4230, 1)),
+ (0x1f236, (5690, 1)),
+ (0x2037, (303, 3)),
+ (0x1e05a, (5329, 1)),
(0x2000, (275, 1)),
- (0x1d7b0, (5209, 1)),
- (0xfc81, (2948, 2)),
- (0xfca0, (3015, 2)),
- (0x1d63e, (4841, 1)),
- (0xfb5b, (2500, 1)),
- (0xfbae, (2585, 1)),
- (0x1d60c, (4791, 1)),
- (0x2f33, (908, 1)),
- (0xfd3c, (3332, 2)),
- (0xfef8, (3996, 3)),
- (0x332c, (1846, 4)),
- (0xfd32, (3312, 2)),
- (0xfcbe, (3075, 2)),
+ (0x1d7e6, (5261, 1)),
+ (0xff6d, (4117, 1)),
+ (0x3036, (1072, 1)),
+ (0x1d6f4, (5021, 1)),
+ (0x1ee18, (5372, 1)),
+ (0x1ee00, (5349, 1)),
+ (0xffb4, (4188, 1)),
+ (0x1d6a8, (4945, 1)),
+ (0x3362, (2038, 3)),
+ (0xfec2, (3936, 1)),
+ (0x2f26, (895, 1)),
+ (0x33fe, (2432, 3)),
(0x2034, (298, 3)),
- (0x1ee6e, (5362, 1)),
- (0x2139, (421, 1)),
+ (0x1cc, (54, 2)),
+ (0x33e1, (2353, 2)),
+ (0xfcc0, (3079, 2)),
(0x33de, (2345, 3)),
- (0x1d34, (143, 1)),
- (0x1d5f4, (4767, 1)),
- (0x1d429, (4332, 1)),
- (0xfba3, (2572, 1)),
- (0xfc0b, (2700, 2)),
+ (0x1d5ba, (4709, 1)),
+ (0x1d47d, (4415, 1)),
+ (0xff76, (4126, 1)),
+ (0xfce2, (3149, 2)),
+ (0x217a, (534, 2)),
(0xfc29, (2760, 2)),
(0x1d6e6, (5007, 1)),
- (0xff33, (4059, 1)),
- (0xffbc, (4196, 1)),
- (0xfcac, (3039, 2)),
- (0x3344, (1944, 3)),
- (0x2087, (342, 1)),
- (0x1d73f, (5096, 1)),
+ (0x1f139, (5608, 1)),
+ (0xff2f, (4055, 1)),
+ (0x1d7a2, (5195, 1)),
+ (0x3000, (1071, 1)),
+ (0x1d6b2, (4955, 1)),
(0x107a9, (4274, 1)),
- (0x316a, (1141, 1)),
- (0xfd9a, (3552, 3)),
+ (0xfecb, (3945, 1)),
+ (0x2f09, (866, 1)),
+ (0xfe16, (3763, 1)),
(0x2100, (365, 3)),
- (0x3332, (1871, 6)),
- (0xfd89, (3507, 3)),
+ (0x3369, (2059, 3)),
+ (0x3322, (1814, 3)),
(0xfca8, (3031, 2)),
- (0x33e4, (2359, 2)),
- (0x2fc7, (1056, 1)),
- (0x321c, (1290, 4)),
- (0x107b8, (4288, 1)),
- (0x3194, (1180, 1)),
+ (0x2e0, (83, 1)),
+ (0x1d6c3, (4972, 1)),
+ (0x2147, (432, 1)),
+ (0x1d57a, (4645, 1)),
+ (0x1d6ff, (5032, 1)),
(0x1d5d7, (4738, 1)),
- (0x3198, (1184, 1)),
- (0xfed3, (3953, 1)),
- (0xfdb7, (3639, 3)),
- (0xfc49, (2824, 2)),
- (0x3351, (1992, 4)),
- (0x333a, (1905, 4)),
+ (0xff0f, (4023, 1)),
+ (0x3259, (1438, 2)),
+ (0x1d45, (159, 1)),
+ (0xfef5, (3987, 3)),
+ (0x1ee94, (5457, 1)),
+ (0x1d76c, (5141, 1)),
(0x316f, (1146, 1)),
- (0xff73, (4123, 1)),
+ (0x2f11, (874, 1)),
(0xff1f, (4039, 1)),
(0x3212, (1250, 4)),
(0x32c0, (1584, 2)),
- (0x1d46c, (4398, 1)),
- (0x1d4fa, (4529, 1)),
+ (0xffb8, (4192, 1)),
+ (0xfc0b, (2700, 2)),
(0xfc04, (2685, 3)),
- (0x1d640, (4843, 1)),
- (0x1f215, (5595, 1)),
- (0x2484, (642, 4)),
- (0x3f5, (108, 1)),
+ (0x1d651, (4860, 1)),
+ (0x1f215, (5657, 1)),
+ (0x3325, (1824, 3)),
+ (0x1d753, (5116, 1)),
(0x2fbf, (1048, 1)),
+ (0x1d73e, (5095, 1)),
(0xff06, (4014, 1)),
- (0xfcc7, (3093, 2)),
- (0xff42, (4074, 1)),
- (0xfe5c, (3815, 1)),
+ (0xfb67, (2512, 1)),
+ (0x3242, (1409, 3)),
+ (0x1d6c1, (4970, 1)),
(0xfe14, (3761, 1)),
- (0x1dae, (216, 1)),
- (0x1d409, (4300, 1)),
+ (0x1d743, (5100, 1)),
+ (0xfeca, (3944, 1)),
(0xfe43, (3789, 1)),
- (0xfc77, (2928, 2)),
(0x1d7d1, (5240, 1)),
- (0xfc19, (2728, 2)),
- (0xfb86, (2543, 1)),
- (0x1d4da, (4497, 1)),
- (0x3378, (2099, 3)),
- (0x1d661, (4876, 1)),
- (0x3252, (1424, 2)),
- (0x2f49, (930, 1)),
- (0x331a, (1780, 6)),
+ (0x1d563, (4622, 1)),
+ (0x1f21f, (5667, 1)),
+ (0xfc0d, (2704, 2)),
+ (0x2f7c, (981, 1)),
+ (0xff82, (4138, 1)),
+ (0x3250, (1419, 3)),
+ (0x1d6df, (5000, 1)),
+ (0x1d7c1, (5226, 1)),
(0xfcfb, (3202, 2)),
(0xfd51, (3339, 3)),
- (0x1ee87, (5383, 1)),
- (0x3399, (2176, 2)),
- (0xfdc5, (3681, 3)),
+ (0x3159, (1124, 1)),
+ (0x1d422, (4325, 1)),
+ (0xfb04, (2460, 3)),
+ (0x313a, (1093, 1)),
(0x1d638, (4835, 1)),
- (0x1d7a8, (5201, 1)),
- (0x1d739, (5090, 1)),
- (0x32de, (1635, 1)),
- (0xfdf7, (3716, 4)),
- (0x1f136, (5543, 1)),
+ (0x33cb, (2301, 2)),
+ (0x107a0, (4265, 1)),
+ (0x1d492, (4436, 1)),
+ (0x2460, (556, 1)),
+ (0x1d510, (4548, 1)),
(0x3374, (2090, 3)),
- (0x1d53e, (4591, 1)),
+ (0x1e032, (5289, 1)),
(0xfb29, (2486, 1)),
- (0x1ee01, (5288, 1)),
- (0x1fbf5, (5668, 1)),
- (0x1d76a, (5139, 1)),
- (0x32d9, (1630, 1)),
- (0xfd2a, (3296, 2)),
- (0x1d4a9, (4452, 1)),
- (0x24b3, (778, 3)),
- (0x2151, (438, 3)),
- (0xff95, (4157, 1)),
- (0x24aa, (751, 3)),
- (0x32a7, (1544, 1)),
- (0x1d57e, (4649, 1)),
- (0x32bc, (1576, 2)),
- (0x2482, (634, 4)),
- (0x2176, (524, 3)),
+ (0x1ee01, (5350, 1)),
+ (0x1d623, (4814, 1)),
+ (0x331d, (1793, 3)),
+ (0xffe8, (4228, 1)),
+ (0x1d531, (4579, 1)),
+ (0x1ee2a, (5385, 1)),
+ (0x2fb9, (1042, 1)),
+ (0x24e9, (838, 1)),
+ (0xfcf0, (3177, 2)),
+ (0x1d4e7, (4510, 1)),
+ (0x2fd3, (1068, 1)),
+ (0xfd62, (3390, 3)),
+ (0x1d7de, (5253, 1)),
+ (0x1ee1e, (5378, 1)),
+ (0xfdb2, (3624, 3)),
(0x2fb4, (1037, 1)),
(0xffc2, (4199, 1)),
- (0xfb5e, (2503, 1)),
- (0x1d60d, (4792, 1)),
- (0x2476, (593, 3)),
+ (0x322c, (1343, 3)),
+ (0xfe8c, (3881, 2)),
+ (0x1d6ef, (5016, 1)),
+ (0x329f, (1536, 1)),
(0x10796, (4255, 1)),
- (0x1d55d, (4616, 1)),
- (0x1d5c, (181, 1)),
- (0x107b3, (4283, 1)),
- (0x1d527, (4569, 1)),
- (0x1d768, (5137, 1)),
- (0xffa5, (4173, 1)),
- (0x2f45, (926, 1)),
- (0xfd81, (3483, 3)),
+ (0x1d38, (147, 1)),
+ (0x331e, (1796, 4)),
+ (0x1d65c, (4871, 1)),
+ (0xfb76, (2527, 1)),
+ (0x1f11d, (5551, 3)),
+ (0xfc95, (2988, 2)),
+ (0x1f12c, (5594, 1)),
(0x1d588, (4659, 1)),
- (0xfe33, (3773, 1)),
- (0x1d6c7, (4976, 1)),
- (0x2f2e, (903, 1)),
- (0x338c, (2146, 2)),
+ (0x33ee, (2384, 3)),
+ (0x24a9, (748, 3)),
+ (0x3209, (1219, 3)),
+ (0x3202, (1198, 3)),
(0x1d72a, (5075, 1)),
- (0x3221, (1310, 3)),
- (0xff11, (4025, 1)),
+ (0x2230, (553, 3)),
+ (0x1ee21, (5380, 1)),
(0x3177, (1154, 1)),
- (0xfd5b, (3369, 3)),
- (0xff88, (4144, 1)),
- (0xff08, (4016, 1)),
- (0x2fa6, (1023, 1)),
- (0xff27, (4047, 1)),
- (0x1d4ae, (4456, 1)),
- (0xfd71, (3435, 3)),
+ (0x335e, (2030, 2)),
+ (0xfeed, (3979, 1)),
+ (0x3312, (1741, 4)),
+ (0x3392, (2159, 3)),
+ (0x1d41e, (4321, 1)),
+ (0x1d5a8, (4691, 1)),
+ (0xff6b, (4115, 1)),
(0xfef1, (3983, 1)),
- (0x1d4b5, (4463, 1)),
- (0x2090, (350, 1)),
- (0x2467, (563, 1)),
- (0x1f145, (5558, 1)),
- (0x1f232, (5624, 1)),
+ (0x329b, (1532, 1)),
+ (0xfb9d, (2566, 1)),
+ (0x1d69a, (4933, 1)),
+ (0x32c3, (1590, 2)),
+ (0x32b2, (1556, 2)),
+ (0xfc8f, (2976, 2)),
(0x216c, (509, 1)),
- (0x222f, (551, 2)),
- (0xfe62, (3821, 1)),
- (0x1d4e0, (4503, 1)),
+ (0x1ee99, (5462, 1)),
+ (0xfdbe, (3660, 3)),
+ (0x2fb7, (1040, 1)),
(0x1d760, (5129, 1)),
(0x33c4, (2284, 2)),
- (0xff3a, (4066, 1)),
- (0x1d590, (4667, 1)),
- (0x1ee1f, (5317, 1)),
- (0x3375, (2093, 2)),
- (0x323e, (1397, 3)),
+ (0xfc8a, (2966, 2)),
+ (0x1d7f9, (5280, 1)),
+ (0x1d53c, (4589, 1)),
+ (0x32cb, (1608, 3)),
(0xfd29, (3294, 2)),
- (0x1d5a9, (4692, 1)),
- (0x3219, (1278, 4)),
- (0xfc6b, (2904, 2)),
+ (0x1f128, (5584, 3)),
+ (0x1da0, (202, 1)),
+ (0xfe9f, (3901, 1)),
+ (0x2171, (514, 2)),
(0x1d56b, (4630, 1)),
- (0x24d4, (817, 1)),
- (0x1d6b1, (4954, 1)),
+ (0x1d64e, (4857, 1)),
+ (0x1d432, (4341, 1)),
(0x3315, (1753, 6)),
(0xfb64, (2509, 1)),
- (0xfd98, (3546, 3)),
- (0xfd2e, (3304, 2)),
+ (0x3284, (1509, 1)),
+ (0x3357, (2015, 3)),
(0xfc35, (2784, 2)),
- (0x1d72f, (5080, 1)),
+ (0x2f92, (1003, 1)),
(0x216f, (512, 1)),
(0x33ab, (2222, 3)),
- (0xfef0, (3982, 1)),
- (0x2078, (327, 1)),
+ (0x1d434, (4343, 1)),
+ (0x1d4c1, (4473, 1)),
(0xfdbd, (3657, 3)),
- (0x3288, (1513, 1)),
- (0x32ca, (1605, 3)),
+ (0x1d6bd, (4966, 1)),
+ (0x1ee34, (5394, 1)),
(0x1d6cc, (4981, 1)),
- (0xfbdc, (2600, 1)),
- (0x1fbf2, (5665, 1)),
- (0x2004, (279, 1)),
- (0x1da9, (211, 1)),
- (0x1d5fa, (4773, 1)),
- (0xfc86, (2958, 2)),
- (0xff92, (4154, 1)),
- (0x1d48c, (4430, 1)),
- (0x326f, (1468, 2)),
- (0xfc5c, (2862, 2)),
+ (0x1f135, (5604, 1)),
+ (0xfc9f, (3013, 2)),
+ (0x1d556, (4609, 1)),
+ (0x33c7, (2292, 3)),
+ (0xfb00, (2451, 2)),
+ (0x1d765, (5134, 1)),
+ (0x1d748, (5105, 1)),
+ (0x2084, (339, 1)),
+ (0x1d44a, (4365, 1)),
+ (0x1d62, (187, 1)),
(0x318c, (1175, 1)),
- (0xfd38, (3324, 2)),
- (0x1d47, (161, 1)),
- (0x1d609, (4788, 1)),
- (0xfba1, (2570, 1)),
- (0x1eeb9, (5425, 1)),
- (0x1d4fc, (4531, 1)),
- (0x3349, (1962, 2)),
+ (0x2049, (314, 2)),
+ (0x32e4, (1641, 1)),
+ (0x1d552, (4605, 1)),
+ (0x1d546, (4597, 1)),
+ (0x1d624, (4815, 1)),
+ (0x1eeb9, (5487, 1)),
+ (0x1d4da, (4497, 1)),
(0x1ca, (50, 2)),
- (0x2f68, (961, 1)),
- (0x331c, (1790, 3)),
- (0xfd77, (3453, 3)),
- (0x1d2e, (138, 1)),
- (0x2f20, (889, 1)),
- (0x1ee3b, (5337, 1)),
+ (0x3240, (1403, 3)),
+ (0xfba8, (2579, 1)),
+ (0xffdc, (4219, 1)),
+ (0x3225, (1322, 3)),
+ (0x1d799, (5186, 1)),
+ (0x1d622, (4813, 1)),
+ (0xfb28, (2485, 1)),
(0x303a, (1075, 1)),
- (0x1ee6d, (5361, 1)),
- (0xfb8f, (2552, 1)),
- (0x332d, (1850, 5)),
- (0x1d682, (4909, 1)),
- (0xfd76, (3450, 3)),
- (0x333d, (1918, 5)),
- (0x1f217, (5597, 1)),
+ (0xffb2, (4186, 1)),
+ (0x1d592, (4669, 1)),
+ (0x207b, (330, 1)),
+ (0x1f12a, (5590, 3)),
+ (0xfd1f, (3274, 2)),
+ (0x1f217, (5659, 1)),
(0x1d575, (4640, 1)),
- (0xfe77, (3840, 2)),
+ (0xfcf1, (3179, 2)),
+ (0xfd6e, (3426, 3)),
(0x24dd, (826, 1)),
- (0x339c, (2182, 2)),
- (0x320a, (1222, 3)),
- (0x1f119, (5477, 3)),
- (0xfc57, (2852, 2)),
- (0x1f21f, (5605, 1)),
- (0x1d794, (5181, 1)),
- (0xfdb3, (3627, 3)),
- (0x107a0, (4265, 1)),
- (0x222d, (548, 3)),
- (0x2f8f, (1000, 1)),
- (0x1d553, (4606, 1)),
+ (0x1d605, (4784, 1)),
+ (0x1ee2f, (5390, 1)),
+ (0xfd27, (3290, 2)),
+ (0x1d52e, (4576, 1)),
+ (0x1d428, (4331, 1)),
+ (0x1ee36, (5396, 1)),
+ (0x32eb, (1648, 1)),
+ (0x1d678, (4899, 1)),
+ (0xfb14, (2469, 2)),
+ (0xff10, (4024, 1)),
+ (0x1d60e, (4793, 1)),
(0xfbad, (2584, 1)),
- (0x212f, (412, 1)),
- (0xfca6, (3027, 2)),
- (0x33c6, (2288, 4)),
- (0xfcd8, (3127, 2)),
- (0x1d40f, (4306, 1)),
- (0x1d423, (4326, 1)),
- (0x2f40, (921, 1)),
- (0x1d4f0, (4519, 1)),
- (0x2f75, (974, 1)),
+ (0x1d570, (4635, 1)),
+ (0x2f38, (913, 1)),
+ (0x2f4a, (931, 1)),
+ (0xff3a, (4066, 1)),
+ (0x1d741, (5098, 1)),
+ (0x1d788, (5169, 1)),
+ (0x320d, (1231, 3)),
+ (0x1d64b, (4854, 1)),
+ (0x2b1, (63, 1)),
(0x33a6, (2207, 3)),
- (0x1d425, (4328, 1)),
- (0x1d76d, (5142, 1)),
- (0x1da4, (206, 1)),
- (0x1ee57, (5348, 1)),
- (0xfea0, (3902, 1)),
- (0x1d49a, (4444, 1)),
- (0xfea1, (3903, 1)),
+ (0x1d774, (5149, 1)),
+ (0xfd2c, (3300, 2)),
+ (0x2109, (381, 2)),
+ (0x1f100, (5490, 2)),
+ (0xfc03, (2682, 3)),
+ (0x1d61, (186, 1)),
+ (0x1d7f2, (5273, 1)),
(0xfbab, (2582, 1)),
- (0x3300, (1670, 5)),
- (0x3145, (1104, 1)),
- (0x1d6c0, (4969, 1)),
- (0x1d539, (4587, 1)),
+ (0xffa7, (4175, 1)),
+ (0x1d664, (4879, 1)),
+ (0xfcdd, (3137, 2)),
+ (0x1d4be, (4470, 1)),
(0x33da, (2337, 2)),
- (0x2075, (324, 1)),
- (0x1d51e, (4560, 1)),
- (0x10782, (4236, 1)),
+ (0x1d67, (192, 1)),
+ (0x2f60, (953, 1)),
+ (0x24a0, (721, 3)),
(0xfb56, (2495, 1)),
(0x24bd, (794, 1)),
+ (0xfbdf, (2604, 1)),
(0xffb7, (4191, 1)),
- (0x1ee16, (5308, 1)),
- (0x1d6e2, (5003, 1)),
- (0xfdc7, (3687, 3)),
- (0x2fbc, (1045, 1)),
- (0xfc66, (2890, 3)),
- (0xfc6e, (2910, 2)),
- (0x1fcd, (247, 3)),
+ (0x1d77d, (5158, 1)),
+ (0x3296, (1527, 1)),
+ (0x1d5b7, (4706, 1)),
+ (0x1f23a, (5694, 1)),
+ (0x316e, (1145, 1)),
+ (0x336d, (2071, 3)),
+ (0xff7e, (4134, 1)),
(0x1d534, (4582, 1)),
(0x32a6, (1543, 1)),
- (0xfd84, (3492, 3)),
- (0x1ee7c, (5374, 1)),
- (0xfd6f, (3429, 3)),
- (0xfeef, (3981, 1)),
- (0xfd80, (3480, 3)),
+ (0x1ee7c, (5436, 1)),
+ (0x1ee2d, (5388, 1)),
+ (0xfd5b, (3369, 3)),
+ (0x331a, (1780, 6)),
+ (0x32f4, (1657, 1)),
(0x32bb, (1574, 2)),
- (0x3270, (1470, 2)),
- (0x333f, (1927, 2)),
+ (0x3343, (1940, 4)),
+ (0x2fd4, (1069, 1)),
(0xfcd2, (3115, 2)),
- (0x334c, (1973, 5)),
- (0x1d5bd, (4712, 1)),
- (0x1d7ec, (5267, 1)),
- (0x1d656, (4865, 1)),
- (0x2464, (560, 1)),
+ (0x2189, (543, 3)),
+ (0x107ae, (4279, 1)),
+ (0xffd3, (4212, 1)),
+ (0x2f2d, (902, 1)),
+ (0xfd56, (3354, 3)),
(0x2105, (374, 3)),
- (0x1d2d, (137, 1)),
- (0x1d66f, (4890, 1)),
- (0x329a, (1531, 1)),
- (0x1ee42, (5338, 1)),
- (0x208b, (346, 1)),
+ (0xfbff, (2672, 1)),
+ (0xfbea, (2615, 3)),
+ (0x1d71d, (5062, 1)),
+ (0x1ee42, (5400, 1)),
+ (0xfdfc, (3753, 4)),
(0x33d8, (2330, 4)),
- (0xfe19, (3766, 3)),
- (0x3358, (2018, 2)),
+ (0x675, (112, 2)),
+ (0x1cb, (52, 2)),
(0xfd6b, (3417, 3)),
- (0x1d711, (5050, 1)),
- (0x1ee80, (5376, 1)),
+ (0x332a, (1837, 3)),
+ (0x1d7a7, (5200, 1)),
(0xfb51, (2490, 1)),
(0x33fd, (2429, 3)),
- (0x1d729, (5074, 1)),
- (0x107a2, (4267, 1)),
- (0x1d66, (191, 1)),
- (0x1d497, (4441, 1)),
- (0x2498, (697, 3)),
+ (0x1ee57, (5410, 1)),
+ (0xa0, (0, 1)),
+ (0x2f2b, (900, 1)),
+ (0x1d404, (4295, 1)),
+ (0x2081, (336, 1)),
(0xf79, (132, 3)),
- (0x314f, (1114, 1)),
- (0x1d79b, (5188, 1)),
+ (0xfeec, (3978, 1)),
+ (0xfc2f, (2772, 2)),
(0x1d52, (171, 1)),
- (0x1d5d, (182, 1)),
- (0x246d, (573, 2)),
- (0x1d53d, (4590, 1)),
+ (0xff41, (4073, 1)),
+ (0x1d5ad, (4696, 1)),
+ (0x2133, (415, 1)),
(0x1d7ab, (5204, 1)),
- (0xfd94, (3534, 3)),
- (0xff75, (4125, 1)),
- (0x3350, (1989, 3)),
- (0x1f137, (5544, 1)),
+ (0x1d463, (4389, 1)),
+ (0xfe71, (3832, 2)),
+ (0xfbaf, (2586, 1)),
+ (0x1d736, (5087, 1)),
(0x1d5e, (183, 1)),
(0x2e3, (86, 1)),
- (0x1f244, (5646, 3)),
- (0xfb79, (2530, 1)),
- (0x2135, (417, 1)),
+ (0xfea4, (3906, 1)),
+ (0x1e035, (5292, 1)),
+ (0x3354, (2002, 5)),
(0x211a, (397, 1)),
- (0x1ee5f, (5352, 1)),
- (0xfe9b, (3897, 1)),
- (0x2fb9, (1042, 1)),
- (0x2f3b, (916, 1)),
- (0x1d54b, (4599, 1)),
- (0x1d5bb, (4710, 1)),
- (0xfd9f, (3567, 3)),
- (0xfe17, (3764, 1)),
- (0x1ee82, (5378, 1)),
- (0xfb6e, (2519, 1)),
- (0x248b, (664, 2)),
- (0x1f115, (5465, 3)),
- (0x335a, (2022, 2)),
+ (0xfe8b, (3879, 2)),
+ (0x1ee5f, (5414, 1)),
+ (0x1d74f, (5112, 1)),
+ (0x1d78, (196, 1)),
+ (0x1f13f, (5614, 1)),
+ (0xffc7, (4204, 1)),
+ (0x314b, (1110, 1)),
+ (0x1d5a6, (4689, 1)),
+ (0xfd0a, (3232, 2)),
+ (0x2476, (593, 3)),
+ (0x1e037, (5294, 1)),
+ (0x1d63, (188, 1)),
+ (0xfb62, (2507, 1)),
+ (0xfdf6, (3712, 4)),
(0xfd7a, (3462, 3)),
(0xffa2, (4170, 1)),
- (0x1d529, (4571, 1)),
- (0x3303, (1684, 3)),
- (0x1d7ad, (5206, 1)),
- (0x2f8c, (997, 1)),
- (0x10797, (4256, 1)),
- (0x2f52, (939, 1)),
- (0x3245, (1416, 1)),
- (0x336e, (2074, 3)),
- (0x1d696, (4929, 1)),
+ (0x1c4, (35, 3)),
+ (0x1d4f4, (4523, 1)),
+ (0x3388, (2135, 3)),
+ (0x1d5a2, (4685, 1)),
+ (0x2f90, (1001, 1)),
+ (0x3281, (1506, 1)),
+ (0x1d4b2, (4460, 1)),
+ (0x1d61a, (4805, 1)),
+ (0xfcc8, (3095, 2)),
(0x1d61e, (4809, 1)),
- (0xfe7a, (3846, 2)),
- (0xff85, (4141, 1)),
+ (0xfcb3, (3053, 2)),
+ (0xfd86, (3498, 3)),
(0x2096, (356, 1)),
(0x1d714, (5053, 1)),
(0xfed7, (3957, 1)),
- (0x1ee9b, (5402, 1)),
- (0x1d793, (5180, 1)),
- (0x1d494, (4438, 1)),
+ (0xff8c, (4148, 1)),
+ (0x2f77, (976, 1)),
+ (0x107b4, (4284, 1)),
(0x2089, (344, 1)),
- (0xfbd8, (2596, 1)),
- (0x1d6d2, (4987, 1)),
+ (0x3207, (1213, 3)),
+ (0xfd15, (3254, 2)),
(0x1d6b7, (4960, 1)),
- (0x1d6ed, (5014, 1)),
- (0x1d660, (4875, 1)),
+ (0x1f134, (5603, 1)),
+ (0xfe59, (3812, 1)),
(0x1d6d4, (4989, 1)),
- (0x2f6b, (964, 1)),
- (0x2f9d, (1014, 1)),
+ (0x1d708, (5041, 1)),
+ (0x1d7f6, (5277, 1)),
+ (0x1d74e, (5111, 1)),
(0x1d7db, (5250, 1)),
- (0x1ee74, (5367, 1)),
- (0x32ab, (1548, 1)),
- (0x2f50, (937, 1)),
+ (0xfcbe, (3075, 2)),
+ (0x2f86, (991, 1)),
(0x2f35, (910, 1)),
- (0xfb9c, (2565, 1)),
- (0x1ee06, (5292, 1)),
+ (0xfb81, (2538, 1)),
+ (0x1d569, (4628, 1)),
(0x3189, (1172, 1)),
- (0xfdc2, (3672, 3)),
+ (0xfc71, (2916, 2)),
(0x1d45b, (4381, 1)),
- (0x2b3, (65, 1)),
- (0x1d700, (5033, 1)),
- (0x149, (32, 2)),
- (0x3228, (1331, 3)),
- (0xfc6f, (2912, 2)),
- (0x2009, (284, 1)),
- (0x1e9b, (236, 2)),
+ (0xff4b, (4083, 1)),
+ (0xfbdb, (2599, 1)),
+ (0x3243, (1412, 3)),
+ (0x2b5, (67, 1)),
+ (0x1d564, (4623, 1)),
+ (0x3170, (1147, 1)),
+ (0xfbdd, (2601, 2)),
(0x2fce, (1063, 1)),
- (0x1d706, (5039, 1)),
- (0x1d6d0, (4985, 1)),
+ (0x215a, (466, 3)),
+ (0x2175, (522, 2)),
+ (0xfd7f, (3477, 3)),
(0x3380, (2119, 2)),
- (0x2150, (435, 3)),
- (0x1d7ae, (5207, 1)),
- (0xfc02, (2679, 3)),
- (0x24ba, (791, 1)),
- (0xfc62, (2878, 3)),
+ (0xff4c, (4084, 1)),
+ (0x1d6cb, (4980, 1)),
+ (0xfee2, (3968, 1)),
+ (0xffc5, (4202, 1)),
(0x32ae, (1551, 1)),
- (0x33c8, (2295, 2)),
+ (0xfe69, (3827, 1)),
(0x3235, (1370, 3)),
- (0x338f, (2152, 2)),
+ (0x24bc, (793, 1)),
+ (0x2fbb, (1044, 1)),
(0xffa3, (4171, 1)),
- (0x3036, (1072, 1)),
- (0x1f12b, (5531, 1)),
- (0xfdc3, (3675, 3)),
- (0x1dad, (215, 1)),
- (0xfced, (3171, 2)),
- (0x33d1, (2313, 2)),
- (0xfd88, (3504, 3)),
- (0x1d507, (4541, 1)),
- (0x1f146, (5559, 1)),
- (0x1eeb3, (5419, 1)),
- (0xfb5a, (2499, 1)),
- (0x1d404, (4295, 1)),
+ (0x3316, (1759, 6)),
+ (0x1f12b, (5593, 1)),
+ (0xfc11, (2712, 2)),
+ (0x2f44, (925, 1)),
+ (0xfbd3, (2591, 1)),
+ (0x1d63b, (4838, 1)),
+ (0xfd0f, (3242, 2)),
+ (0x1f146, (5621, 1)),
+ (0x328e, (1519, 1)),
+ (0x309c, (1078, 2)),
+ (0x1da6, (208, 1)),
+ (0x32bd, (1578, 2)),
(0xfba2, (2571, 1)),
- (0x1d4d6, (4493, 1)),
- (0x24c7, (804, 1)),
- (0x2f8e, (999, 1)),
- (0x2f07, (864, 1)),
- (0x1d435, (4344, 1)),
+ (0x1d527, (4569, 1)),
+ (0xfcc5, (3089, 2)),
+ (0x332d, (1850, 5)),
+ (0xfe5a, (3813, 1)),
+ (0x1d60c, (4791, 1)),
(0x2481, (630, 4)),
- (0x1ee69, (5358, 1)),
- (0x318d, (1176, 1)),
- (0xfc76, (2926, 2)),
- (0x1d4ea, (4513, 1)),
- (0x1d63a, (4837, 1)),
- (0x1d6e1, (5002, 1)),
- (0x1f117, (5471, 3)),
- (0x33bb, (2264, 2)),
- (0xff36, (4062, 1)),
- (0xfcb2, (3051, 2)),
- (0x1d614, (4799, 1)),
- (0xfec7, (3941, 1)),
- (0x1d59b, (4678, 1)),
- (0xfebe, (3932, 1)),
- (0x1d4f9, (4528, 1)),
- (0x1d605, (4784, 1)),
+ (0xfe4e, (3802, 1)),
+ (0xff45, (4077, 1)),
+ (0x32ef, (1652, 1)),
+ (0x1d2d, (137, 1)),
+ (0x3135, (1088, 1)),
+ (0x3342, (1937, 3)),
+ (0x1f117, (5533, 3)),
+ (0x1d72b, (5076, 1)),
+ (0x1d41, (155, 1)),
+ (0xff5d, (4101, 1)),
+ (0xfd03, (3218, 2)),
+ (0xfecc, (3946, 1)),
+ (0x1d52f, (4577, 1)),
+ (0xfc23, (2748, 2)),
+ (0x1d522, (4564, 1)),
+ (0x32f8, (1661, 1)),
(0x3143, (1102, 1)),
+ (0x1d450, (4371, 1)),
(0x2db, (77, 2)),
- (0x1ee00, (5287, 1)),
- (0x2137, (419, 1)),
- (0x1d77f, (5160, 1)),
+ (0xfccb, (3101, 2)),
+ (0x24b1, (772, 3)),
(0x1d7ee, (5269, 1)),
- (0x2166, (494, 3)),
- (0xfbd9, (2597, 1)),
+ (0x1d52d, (4575, 1)),
+ (0x1d792, (5179, 1)),
(0x2fa9, (1026, 1)),
(0x3206, (1210, 3)),
- (0xfbe2, (2607, 1)),
+ (0x2f22, (891, 1)),
+ (0x2f14, (877, 1)),
(0x309b, (1076, 2)),
- (0x1f200, (5584, 2)),
- (0x1eea9, (5410, 1)),
- (0x2037, (303, 3)),
- (0x1d559, (4612, 1)),
- (0x1d64d, (4856, 1)),
- (0x2495, (688, 3)),
- (0xfbac, (2583, 1)),
- (0x2f25, (894, 1)),
- (0x3179, (1156, 1)),
- (0xfeb0, (3918, 1)),
- (0x1d496, (4440, 1)),
+ (0x1eea9, (5472, 1)),
+ (0xfd74, (3444, 3)),
+ (0x1d6a, (195, 1)),
+ (0x1e05e, (5333, 1)),
+ (0x1d5d6, (4737, 1)),
+ (0x1d504, (4539, 1)),
+ (0xfc9e, (3011, 2)),
+ (0x2153, (445, 3)),
+ (0x1d421, (4324, 1)),
+ (0x1eea5, (5468, 1)),
+ (0x2f67, (960, 1)),
(0x3d4, (100, 2)),
(0xfc82, (2950, 2)),
- (0x1ee98, (5399, 1)),
- (0x3173, (1150, 1)),
- (0xfc16, (2722, 2)),
+ (0x1ee98, (5461, 1)),
+ (0x2f1f, (888, 1)),
+ (0x1d7d3, (5242, 1)),
(0x3313, (1745, 6)),
- (0x1d4c7, (4478, 1)),
- (0xfbd6, (2594, 1)),
- (0x1ee67, (5356, 1)),
- (0xff53, (4091, 1)),
+ (0x325e, (1448, 2)),
+ (0x2f74, (973, 1)),
+ (0x336c, (2068, 3)),
+ (0x2484, (642, 4)),
(0xfe66, (3825, 1)),
- (0x1d513, (4551, 1)),
- (0xab5c, (2446, 1)),
- (0xfbf4, (2645, 3)),
+ (0x1078b, (4244, 1)),
+ (0xfef6, (3990, 3)),
+ (0xfd85, (3495, 3)),
(0x1d48b, (4429, 1)),
- (0x24d8, (821, 1)),
- (0x1d666, (4881, 1)),
+ (0x2487, (654, 4)),
+ (0x1d64f, (4858, 1)),
(0xfe7d, (3852, 2)),
- (0x1d43a, (4349, 1)),
- (0x1ee8e, (5389, 1)),
- (0x24d3, (816, 1)),
+ (0xfd7c, (3468, 3)),
+ (0xfcc1, (3081, 2)),
+ (0x1d4a2, (4449, 1)),
(0x203e, (308, 2)),
- (0x2480, (626, 4)),
- (0x1d704, (5037, 1)),
- (0x1d762, (5131, 1)),
- (0xff0f, (4023, 1)),
- (0xfce0, (3144, 3)),
- (0x1d42, (156, 1)),
- (0xfccd, (3105, 2)),
- (0x2a0c, (840, 4)),
- (0x2189, (543, 3)),
- (0x3166, (1137, 1)),
+ (0x1d598, (4675, 1)),
+ (0x323c, (1391, 3)),
+ (0x247a, (605, 3)),
+ (0xfd12, (3248, 2)),
+ (0x1d429, (4332, 1)),
+ (0x1ee13, (5367, 1)),
+ (0xfc8d, (2972, 2)),
+ (0x2f29, (898, 1)),
+ (0x1d6a1, (4940, 1)),
+ (0x1f110, (5512, 3)),
(0x1d2c, (136, 1)),
(0x1d7b8, (5217, 1)),
- (0x1d42d, (4336, 1)),
- (0x24c2, (799, 1)),
- (0x1d79d, (5190, 1)),
- (0x2164, (491, 1)),
+ (0x32ec, (1649, 1)),
+ (0x3145, (1104, 1)),
+ (0xfdbf, (3663, 3)),
+ (0x1d54d, (4601, 1)),
(0x3181, (1164, 1)),
- (0xfd83, (3489, 3)),
- (0xb3, (7, 1)),
- (0xfc05, (2688, 2)),
- (0xfd2c, (3300, 2)),
- (0x1d6f6, (5023, 1)),
- (0x1d444, (4359, 1)),
- (0x33a7, (2210, 3)),
+ (0xfc67, (2893, 3)),
+ (0xff34, (4060, 1)),
+ (0x1d6e3, (5004, 1)),
+ (0xfd70, (3432, 3)),
+ (0x1d608, (4787, 1)),
+ (0x1d711, (5050, 1)),
+ (0xff9d, (4165, 1)),
(0x1d51f, (4561, 1)),
- (0x332e, (1855, 6)),
- (0x1d5b3, (4702, 1)),
- (0x1d488, (4426, 1)),
- (0x3393, (2162, 3)),
+ (0x1d773, (5148, 1)),
+ (0xfd95, (3537, 3)),
+ (0xff5f, (4103, 1)),
+ (0x2174, (521, 1)),
(0xfec4, (3938, 1)),
- (0x2f6c, (965, 1)),
+ (0x1d523, (4565, 1)),
(0x207c, (331, 1)),
- (0x1d65c, (4871, 1)),
+ (0x2faa, (1027, 1)),
+ (0x1d69e, (4937, 1)),
(0x2f55, (942, 1)),
- (0xfe9c, (3898, 1)),
- (0xff48, (4080, 1)),
- (0x1fce, (250, 3)),
+ (0x1d582, (4653, 1)),
+ (0x1d601, (4780, 1)),
+ (0x1d7aa, (5203, 1)),
(0x215f, (481, 2)),
- (0x1fbf, (240, 2)),
+ (0xff4a, (4082, 1)),
(0x1d477, (4409, 1)),
- (0x1d418, (4315, 1)),
(0x1d525, (4567, 1)),
- (0x2f6e, (967, 1)),
+ (0xfda2, (3576, 3)),
(0xff94, (4156, 1)),
- (0x1d744, (5101, 1)),
+ (0xff8e, (4150, 1)),
+ (0x1d43b, (4350, 1)),
(0x1d709, (5042, 1)),
- (0x1ee62, (5354, 1)),
- (0x2468, (564, 1)),
- (0x1ee77, (5370, 1)),
- (0x1eeac, (5412, 1)),
- (0x2f44, (925, 1)),
+ (0x1d56d, (4632, 1)),
+ (0x33ea, (2372, 3)),
+ (0x1ee77, (5432, 1)),
+ (0x1eeac, (5474, 1)),
+ (0x334d, (1978, 4)),
(0x1d6a5, (4944, 1)),
(0x33c2, (2278, 4)),
- (0x2f02, (859, 1)),
- (0x1d56f, (4634, 1)),
- (0x24c4, (801, 1)),
+ (0x1d661, (4876, 1)),
+ (0xfd01, (3214, 2)),
+ (0x1d5d2, (4733, 1)),
(0x2008, (283, 1)),
(0xfd8f, (3525, 3)),
(0x3227, (1328, 3)),
(0x1d447, (4362, 1)),
- (0xfc56, (2850, 2)),
- (0xfd93, (3531, 3)),
+ (0x249d, (712, 3)),
+ (0x1f14b, (5627, 2)),
(0x1d5fc, (4775, 1)),
(0x1d50a, (4544, 1)),
- (0xfe81, (3859, 2)),
+ (0xfb86, (2543, 1)),
(0x1d719, (5058, 1)),
- (0x2f3a, (915, 1)),
- (0x3319, (1774, 6)),
- (0x1d584, (4655, 1)),
+ (0x330f, (1729, 4)),
+ (0xfd6a, (3414, 3)),
+ (0xfc9d, (3009, 2)),
(0xfc3e, (2802, 2)),
- (0x323a, (1385, 3)),
- (0x2f38, (913, 1)),
+ (0x1e064, (5339, 1)),
+ (0x3d1, (96, 1)),
(0xffaf, (4183, 1)),
+ (0x1d433, (4342, 1)),
(0xfbfe, (2671, 1)),
- (0x1d59f, (4682, 1)),
- (0x1d646, (4849, 1)),
- (0x24cc, (809, 1)),
- (0xfd64, (3396, 3)),
- (0xfd3b, (3330, 2)),
+ (0x1d4dc, (4499, 1)),
+ (0xfbf0, (2633, 3)),
+ (0x33dd, (2343, 2)),
+ (0xfcf5, (3190, 2)),
(0xfce6, (3157, 2)),
(0x1d554, (4607, 1)),
- (0x1d791, (5178, 1)),
- (0x2f1d, (886, 1)),
- (0x1d5c0, (4715, 1)),
- (0xfc60, (2872, 3)),
- (0x1d60f, (4794, 1)),
+ (0x1fdf, (262, 3)),
+ (0x2082, (337, 1)),
+ (0xfeaf, (3917, 1)),
+ (0x1d43d, (4352, 1)),
+ (0x1c9, (48, 2)),
+ (0x1e060, (5335, 1)),
(0xff29, (4049, 1)),
- (0xff82, (4138, 1)),
- (0x1d7e4, (5259, 1)),
- (0x1d6ee, (5015, 1)),
- (0x327c, (1494, 5)),
- (0x3142, (1101, 1)),
- (0x2f7c, (981, 1)),
- (0x2120, (401, 2)),
- (0x32b5, (1562, 2)),
- (0x1d72c, (5077, 1)),
- (0x2f32, (907, 1)),
- (0xff25, (4045, 1)),
- (0x1ee85, (5381, 1)),
- (0xff84, (4140, 1)),
- (0x24e5, (834, 1)),
- (0x1f114, (5462, 3)),
- (0xfbf6, (2651, 3)),
+ (0x33b6, (2254, 2)),
+ (0xfb57, (2496, 1)),
+ (0xfeb2, (3920, 1)),
+ (0x1d703, (5036, 1)),
+ (0x1d5e9, (4756, 1)),
+ (0x24e1, (830, 1)),
+ (0x10794, (4253, 1)),
+ (0x328f, (1520, 1)),
+ (0x1e049, (5312, 1)),
+ (0x1d58c, (4663, 1)),
+ (0x335d, (2028, 2)),
+ (0x3039, (1074, 1)),
+ (0x1d46d, (4399, 1)),
+ (0x2f49, (930, 1)),
+ (0x1f222, (5670, 1)),
(0x32fe, (1667, 1)),
- (0xfe4c, (3799, 2)),
- (0x1f102, (5432, 2)),
- (0xfda0, (3570, 3)),
- (0x33f0, (2390, 3)),
- (0x318a, (1173, 1)),
- (0x2b2, (64, 1)),
- (0xfb90, (2553, 1)),
- (0x24d0, (813, 1)),
- (0x208a, (345, 1)),
- (0x1f132, (5539, 1)),
+ (0x1d79c, (5189, 1)),
+ (0x3179, (1156, 1)),
+ (0x1d697, (4930, 1)),
+ (0x1c8, (46, 2)),
+ (0x2138, (420, 1)),
+ (0x1d6ac, (4949, 1)),
+ (0xfc20, (2742, 2)),
+ (0x327e, (1503, 2)),
+ (0xfd24, (3284, 2)),
+ (0x32df, (1636, 1)),
(0xfc53, (2844, 2)),
+ (0xfeb9, (3927, 1)),
(0x1d76e, (5143, 1)),
- (0x1d657, (4866, 1)),
- (0x1d61f, (4810, 1)),
- (0x1f107, (5442, 2)),
- (0x2102, (371, 1)),
- (0xff2f, (4055, 1)),
+ (0x3378, (2099, 3)),
+ (0xff9f, (4167, 1)),
+ (0x1ee19, (5373, 1)),
+ (0x1f119, (5539, 3)),
+ (0x1d480, (4418, 1)),
(0xfc1d, (2736, 2)),
- (0x1d65b, (4870, 1)),
- (0x3286, (1511, 1)),
- (0x1f13a, (5547, 1)),
+ (0x30ff, (1082, 2)),
+ (0xfb63, (2508, 1)),
+ (0x1f13a, (5609, 1)),
(0x333c, (1914, 4)),
- (0xfc55, (2848, 2)),
- (0xfd26, (3288, 2)),
- (0x217a, (534, 2)),
+ (0xfc87, (2960, 2)),
+ (0x1d45c, (4382, 1)),
+ (0xfea9, (3911, 1)),
(0x1d41a, (4317, 1)),
- (0xfb70, (2521, 1)),
+ (0x1eebb, (5489, 1)),
(0x1d54e, (4602, 1)),
- (0x678, (118, 2)),
- (0x2465, (561, 1)),
- (0x1fcf, (253, 3)),
- (0x32e3, (1640, 1)),
- (0x1d5f6, (4769, 1)),
- (0x1d785, (5166, 1)),
+ (0xffc4, (4201, 1)),
+ (0x1d423, (4326, 1)),
+ (0xfcdc, (3135, 2)),
+ (0x1d58f, (4666, 1)),
+ (0x1d456, (4376, 1)),
+ (0xfd8c, (3516, 3)),
(0x1d5c2, (4717, 1)),
- (0x1d56e, (4633, 1)),
- (0x1d68, (193, 1)),
- (0x2b5, (67, 1)),
- (0xfea4, (3906, 1)),
- (0x3229, (1334, 3)),
- (0x2093, (353, 1)),
+ (0xfdbb, (3651, 3)),
+ (0x1d67c, (4903, 1)),
+ (0x1d4ab, (4454, 1)),
+ (0x1d557, (4610, 1)),
+ (0xfce4, (3153, 2)),
+ (0x322f, (1352, 3)),
+ (0x33bc, (2266, 2)),
(0xfe7e, (3854, 2)),
(0x1d44f, (4370, 1)),
- (0xfe74, (3836, 2)),
- (0xfb25, (2482, 1)),
- (0x315d, (1128, 1)),
- (0x2fa1, (1018, 1)),
- (0xfb7e, (2535, 1)),
- (0xfce7, (3159, 2)),
- (0x1d42f, (4338, 1)),
- (0x2f77, (976, 1)),
- (0x3363, (2041, 3)),
- (0x1eeb7, (5423, 1)),
- (0x2f86, (991, 1)),
- (0xfd60, (3384, 3)),
- (0x211b, (398, 1)),
+ (0x1d74a, (5107, 1)),
+ (0x3167, (1138, 1)),
+ (0xfb9e, (2567, 1)),
+ (0xff6e, (4118, 1)),
+ (0xff90, (4152, 1)),
+ (0x1d700, (5033, 1)),
+ (0x1d431, (4340, 1)),
+ (0x1d459, (4379, 1)),
+ (0x213b, (422, 3)),
+ (0x1d779, (5154, 1)),
+ (0xfc46, (2818, 2)),
+ (0x334b, (1970, 3)),
+ (0xfc41, (2808, 2)),
(0x3279, (1488, 2)),
- (0xfb7a, (2531, 1)),
(0x3294, (1525, 1)),
+ (0x1d4eb, (4514, 1)),
(0x1d71f, (5064, 1)),
- (0x2049, (314, 2)),
+ (0x2f28, (897, 1)),
(0xfbe8, (2613, 1)),
- (0x1ee39, (5336, 1)),
- (0x1d6d5, (4990, 1)),
- (0x1f131, (5538, 1)),
- (0x24a0, (721, 3)),
- (0x2f59, (946, 1)),
- (0x3301, (1675, 4)),
- (0x1d717, (5056, 1)),
- (0x2dc, (79, 2)),
- (0x1d5f3, (4766, 1)),
- (0x1d3a, (149, 1)),
+ (0x24a2, (727, 3)),
+ (0x1d759, (5122, 1)),
+ (0xfcba, (3067, 2)),
+ (0x1d2e, (138, 1)),
+ (0xfb97, (2560, 1)),
+ (0x248c, (666, 2)),
+ (0x1da5, (207, 1)),
+ (0x33d3, (2318, 2)),
+ (0xfdf4, (3704, 4)),
+ (0x107a3, (4268, 1)),
(0x2f8d, (998, 1)),
- (0x3171, (1148, 1)),
- (0xfc32, (2778, 2)),
- (0xfcf5, (3190, 2)),
+ (0x1fbf7, (5732, 1)),
+ (0x1ee7e, (5437, 1)),
+ (0xff31, (4057, 1)),
(0xfd04, (3220, 2)),
- (0x2f79, (978, 1)),
+ (0x323e, (1397, 3)),
(0x246c, (571, 2)),
- (0x1d64b, (4854, 1)),
- (0x1d589, (4660, 1)),
+ (0x1d7e9, (5264, 1)),
+ (0xfd76, (3450, 3)),
(0x3328, (1832, 2)),
- (0x1d679, (4900, 1)),
+ (0x1d602, (4781, 1)),
(0xfe60, (3819, 1)),
+ (0x1d58, (177, 1)),
(0xfd8e, (3522, 3)),
- (0x2f6d, (966, 1)),
- (0xfcb3, (3053, 2)),
- (0x33f3, (2399, 3)),
- (0x1ee86, (5382, 1)),
- (0x1d7eb, (5266, 1)),
- (0x1ee08, (5294, 1)),
+ (0x320b, (1225, 3)),
+ (0x2fa4, (1021, 1)),
+ (0xfcd8, (3127, 2)),
+ (0xfcd3, (3117, 2)),
+ (0x1d446, (4361, 1)),
(0x3310, (1733, 4)),
- (0x1d530, (4578, 1)),
- (0x2179, (533, 1)),
- (0x1d613, (4798, 1)),
- (0xfd54, (3348, 3)),
+ (0x1d66a, (4885, 1)),
+ (0x33ce, (2307, 2)),
+ (0xf77, (129, 3)),
+ (0x1d7b7, (5216, 1)),
(0xfb8a, (2547, 1)),
- (0x326d, (1465, 1)),
- (0xfbd4, (2592, 1)),
- (0xfec5, (3939, 1)),
- (0x1dbb, (229, 1)),
- (0xfc95, (2988, 2)),
- (0xfba6, (2577, 1)),
- (0x2070, (321, 1)),
- (0x33c3, (2282, 2)),
- (0x2131, (414, 1)),
- (0xfc09, (2696, 2)),
- (0x1ee8b, (5386, 1)),
- (0xfbaa, (2581, 1)),
- (0xffb9, (4193, 1)),
- (0x2109, (381, 2)),
+ (0x2f2f, (904, 1)),
+ (0x3372, (2086, 2)),
+ (0x2479, (602, 3)),
+ (0x24c8, (805, 1)),
+ (0x1d485, (4423, 1)),
+ (0x1d476, (4408, 1)),
+ (0x33c1, (2276, 2)),
+ (0x2f7a, (979, 1)),
+ (0x1d6f9, (5026, 1)),
+ (0x1d42b, (4334, 1)),
+ (0x1d475, (4407, 1)),
+ (0xfe51, (3805, 1)),
+ (0x1dbf, (233, 1)),
+ (0x3180, (1163, 1)),
(0x1d427, (4330, 1)),
- (0xfe96, (3892, 1)),
- (0x3273, (1476, 2)),
+ (0x2f08, (865, 1)),
+ (0x1e03a, (5297, 1)),
(0x3381, (2121, 2)),
- (0x1d4e4, (4507, 1)),
+ (0xff5e, (4102, 1)),
(0x1d75f, (5128, 1)),
- (0xfb16, (2473, 2)),
- (0x3246, (1417, 1)),
+ (0x1f2, (58, 2)),
+ (0x1d539, (4587, 1)),
+ (0x1d4f9, (4528, 1)),
(0x2f43, (924, 1)),
- (0x2fa7, (1024, 1)),
- (0x2f9e, (1015, 1)),
- (0xfc84, (2954, 2)),
- (0x2076, (325, 1)),
- (0x1d745, (5102, 1)),
- (0xff62, (4106, 1)),
- (0x24a6, (739, 3)),
- (0x1d6bd, (4966, 1)),
- (0xfd31, (3310, 2)),
+ (0xfd1d, (3270, 2)),
+ (0xfc1f, (2740, 2)),
+ (0x247d, (614, 4)),
+ (0xff3e, (4070, 1)),
+ (0x1d776, (5151, 1)),
+ (0x1d9f, (201, 1)),
+ (0x1ee16, (5370, 1)),
+ (0x3256, (1432, 2)),
(0xff7a, (4130, 1)),
- (0x1d5e4, (4751, 1)),
- (0x249b, (706, 3)),
- (0x3386, (2131, 2)),
- (0x1f12c, (5532, 1)),
+ (0x1d629, (4820, 1)),
+ (0x1ee54, (5409, 1)),
+ (0xff59, (4097, 1)),
+ (0x1d6cf, (4984, 1)),
+ (0x1d6f6, (5023, 1)),
(0x33b5, (2252, 2)),
- (0x24d9, (822, 1)),
+ (0x1d7b9, (5218, 1)),
(0xffd2, (4211, 1)),
- (0x1d9b, (197, 1)),
- (0x1d509, (4543, 1)),
- (0x32b0, (1553, 1)),
+ (0x3358, (2018, 2)),
+ (0x2f2a, (899, 1)),
+ (0x2e1, (84, 1)),
(0xfc68, (2896, 3)),
- (0x1f128, (5522, 3)),
- (0x1d7c1, (5226, 1)),
+ (0x3329, (1834, 3)),
+ (0xfce1, (3147, 2)),
+ (0x1d732, (5083, 1)),
(0xfb54, (2493, 1)),
- (0x1f235, (5627, 1)),
- (0xff55, (4093, 1)),
- (0xfbea, (2615, 3)),
- (0x2da, (75, 2)),
- (0x330d, (1721, 4)),
- (0x32ed, (1650, 1)),
+ (0x1d4e4, (4507, 1)),
+ (0x222d, (548, 3)),
+ (0xfdb1, (3621, 3)),
+ (0x1d794, (5181, 1)),
+ (0xfe88, (3873, 2)),
(0x1d7c8, (5233, 1)),
- (0x32b4, (1560, 2)),
- (0xfb88, (2545, 1)),
- (0x1d72d, (5078, 1)),
- (0x1d669, (4884, 1)),
- (0x3149, (1108, 1)),
- (0x1d5b0, (4699, 1)),
- (0x33e2, (2355, 2)),
- (0x1f140, (5553, 1)),
- (0xff8c, (4148, 1)),
- (0x1d55a, (4613, 1)),
+ (0xff43, (4075, 1)),
+ (0x1d420, (4323, 1)),
+ (0xfc3d, (2800, 2)),
+ (0xfd18, (3260, 2)),
+ (0xfe87, (3871, 2)),
+ (0x2fd0, (1065, 1)),
+ (0xfbf9, (2660, 3)),
+ (0x323b, (1388, 3)),
+ (0x1d685, (4912, 1)),
+ (0x2087, (342, 1)),
(0x1d75d, (5126, 1)),
- (0x107a8, (4273, 1)),
- (0x2f81, (986, 1)),
+ (0x1d47, (161, 1)),
+ (0xfc42, (2810, 2)),
+ (0x2f3f, (920, 1)),
(0xfe82, (3861, 2)),
- (0xfef9, (3999, 3)),
- (0x33f6, (2408, 3)),
- (0x1d44b, (4366, 1)),
+ (0x1d6c5, (4974, 1)),
+ (0x1ee88, (5446, 1)),
+ (0x32e9, (1646, 1)),
(0x1d44d, (4368, 1)),
- (0x327b, (1492, 2)),
- (0x1078d, (4246, 1)),
- (0xfbe4, (2609, 1)),
+ (0xfc52, (2842, 2)),
+ (0x321c, (1290, 4)),
+ (0x1fee, (268, 3)),
(0x1d448, (4363, 1)),
- (0x335e, (2030, 2)),
- (0x1d6f1, (5018, 1)),
- (0x1f214, (5594, 1)),
- (0x1d45d, (4383, 1)),
- (0x1d733, (5084, 1)),
- (0xfc33, (2780, 2)),
- (0x1f11e, (5492, 3)),
- (0x1d632, (4829, 1)),
- (0xfee4, (3970, 1)),
+ (0x3349, (1962, 2)),
+ (0x1d5e2, (4749, 1)),
+ (0x1f214, (5656, 1)),
+ (0x3239, (1382, 3)),
+ (0x2005, (280, 1)),
+ (0x1f11e, (5554, 3)),
+ (0x1f238, (5692, 1)),
+ (0x2f3b, (916, 1)),
+ (0xfdaf, (3615, 3)),
(0x1d6da, (4995, 1)),
- (0xfc8a, (2966, 2)),
- (0x1d746, (5103, 1)),
- (0x1f212, (5591, 1)),
+ (0xffec, (4232, 1)),
+ (0x1d62c, (4823, 1)),
+ (0x3226, (1325, 3)),
(0xff93, (4155, 1)),
- (0x1d7d2, (5241, 1)),
- (0x3388, (2135, 3)),
+ (0x3314, (1751, 2)),
+ (0x2079, (328, 1)),
(0xff8f, (4151, 1)),
- (0xfc1f, (2740, 2)),
+ (0x3173, (1150, 1)),
(0x1d583, (4654, 1)),
- (0x1d688, (4915, 1)),
+ (0x1fbf9, (5734, 1)),
(0xb4, (8, 2)),
- (0xfc4d, (2832, 2)),
- (0x1d7fc, (5283, 1)),
- (0x37a, (88, 2)),
- (0xfe7f, (3856, 2)),
- (0x1f240, (5634, 3)),
+ (0xfdc2, (3672, 3)),
+ (0x1d32, (141, 1)),
+ (0x1d418, (4315, 1)),
+ (0xff7f, (4135, 1)),
+ (0x1f133, (5602, 1)),
(0x32a0, (1537, 1)),
- (0x1d7c0, (5225, 1)),
- (0xfd16, (3256, 2)),
+ (0xfd63, (3393, 3)),
+ (0x1d771, (5146, 1)),
(0x33ad, (2228, 3)),
- (0x1d618, (4803, 1)),
- (0x1ee99, (5400, 1)),
- (0x1d792, (5179, 1)),
- (0x1d7a4, (5197, 1)),
+ (0x2b7, (69, 1)),
+ (0x1f211, (5652, 1)),
+ (0x1f16b, (5640, 2)),
+ (0xfb77, (2528, 1)),
(0xfefa, (4002, 3)),
- (0x32fd, (1666, 1)),
+ (0x1d461, (4387, 1)),
(0x32ea, (1647, 1)),
(0x1d555, (4608, 1)),
(0x1dab, (213, 1)),
- (0x2167, (497, 4)),
- (0x1d639, (4836, 1)),
+ (0xfebc, (3930, 1)),
+ (0x1d6b1, (4954, 1)),
(0x317e, (1161, 1)),
+ (0x1d5b1, (4700, 1)),
(0xfe95, (3891, 1)),
- (0x1d438, (4347, 1)),
- (0x3195, (1181, 1)),
- (0xfcc0, (3079, 2)),
+ (0x331f, (1800, 4)),
+ (0x1d70c, (5045, 1)),
(0x1d662, (4877, 1)),
- (0x2f4e, (935, 1)),
- (0x32a9, (1546, 1)),
+ (0x1d70e, (5047, 1)),
+ (0x1d417, (4314, 1)),
+ (0xfc10, (2710, 2)),
(0xfc1a, (2730, 2)),
(0x1d755, (5118, 1)),
(0x3134, (1087, 1)),
- (0x1d6fb, (5028, 1)),
- (0xfc69, (2899, 3)),
- (0x1d712, (5051, 1)),
- (0x1d780, (5161, 1)),
- (0xfe8a, (3877, 2)),
- (0x2c7c, (852, 1)),
- (0x1d70f, (5048, 1)),
- (0xff49, (4081, 1)),
- (0x33d2, (2315, 3)),
+ (0x3308, (1704, 4)),
+ (0x1d541, (4593, 1)),
+ (0x10787, (4240, 1)),
+ (0xfeac, (3914, 1)),
+ (0x1f229, (5677, 1)),
+ (0x1e046, (5309, 1)),
+ (0x24c3, (800, 1)),
+ (0x2026, (292, 3)),
+ (0x149, (32, 2)),
(0x33e7, (2365, 2)),
(0x211c, (399, 1)),
- (0x3377, (2097, 2)),
- (0x1d37, (146, 1)),
- (0x1d57f, (4650, 1)),
- (0x1d76b, (5140, 1)),
- (0xff09, (4017, 1)),
- (0x3392, (2159, 3)),
- (0x3152, (1117, 1)),
+ (0x2f58, (945, 1)),
+ (0x1d5ff, (4778, 1)),
+ (0xfe9b, (3897, 1)),
+ (0xfd2f, (3306, 2)),
+ (0x1d710, (5049, 1)),
+ (0x1d65, (190, 1)),
+ (0xfc1e, (2738, 2)),
(0xfd9d, (3561, 3)),
(0x2077, (326, 1)),
(0x24cb, (808, 1)),
- (0x1eeba, (5426, 1)),
- (0x3160, (1131, 1)),
- (0x677, (116, 2)),
- (0x1d56a, (4629, 1)),
+ (0x1eeba, (5488, 1)),
+ (0xff0e, (4022, 1)),
+ (0xfb7e, (2535, 1)),
+ (0x3337, (1895, 3)),
(0x248d, (668, 2)),
- (0xfd27, (3290, 2)),
+ (0xfd99, (3549, 3)),
(0xfd65, (3399, 3)),
- (0x1d566, (4625, 1)),
- (0x32da, (1631, 1)),
- (0xfcce, (3107, 2)),
- (0xff30, (4056, 1)),
- (0x1ee7a, (5372, 1)),
- (0xfe3d, (3783, 1)),
- (0x1d644, (4847, 1)),
- (0xfb5c, (2501, 1)),
+ (0x1d7ac, (5205, 1)),
+ (0x1f11c, (5548, 3)),
+ (0x32ff, (1668, 2)),
+ (0x1ee7a, (5434, 1)),
+ (0x1e06b, (5346, 1)),
+ (0xfe47, (3791, 1)),
+ (0x1d637, (4834, 1)),
+ (0x3264, (1456, 1)),
(0xfc58, (2854, 2)),
- (0xfdfc, (3753, 4)),
- (0xfee0, (3966, 1)),
- (0x1d5d4, (4735, 1)),
- (0x322a, (1337, 3)),
- (0x2f8a, (995, 1)),
- (0x1d64a, (4853, 1)),
- (0x32a2, (1539, 1)),
- (0x1ee76, (5369, 1)),
- (0xfd2b, (3298, 2)),
- (0x1f11a, (5480, 3)),
+ (0x1d603, (4782, 1)),
+ (0x1d478, (4410, 1)),
+ (0xff0a, (4018, 1)),
+ (0xfda3, (3579, 3)),
+ (0x1d44, (158, 1)),
+ (0x24d0, (813, 1)),
+ (0xab5e, (2448, 1)),
+ (0xfcfc, (3204, 2)),
+ (0xffe0, (4220, 1)),
+ (0x1ee0a, (5358, 1)),
+ (0x313d, (1096, 1)),
(0x3398, (2174, 2)),
- (0x2489, (660, 2)),
- (0x1d64, (189, 1)),
- (0x2f18, (881, 1)),
+ (0xfcd0, (3111, 2)),
+ (0x2f6e, (967, 1)),
(0x202f, (295, 1)),
- (0x1d73d, (5094, 1)),
- (0xfc36, (2786, 2)),
+ (0xfcaa, (3035, 2)),
+ (0x1d43a, (4349, 1)),
(0xfd23, (3282, 2)),
- (0x1d449, (4364, 1)),
+ (0x2ef3, (856, 1)),
(0xfe5f, (3818, 1)),
- (0xfbe7, (2612, 1)),
- (0x33aa, (2219, 3)),
- (0x107ab, (4276, 1)),
- (0x316d, (1144, 1)),
+ (0x2f93, (1004, 1)),
+ (0x2086, (341, 1)),
+ (0xfd6d, (3423, 3)),
+ (0x249f, (718, 3)),
(0x1d424, (4327, 1)),
- (0x1d677, (4898, 1)),
+ (0x1fbf8, (5733, 1)),
(0x1d462, (4388, 1)),
- (0x2079, (328, 1)),
- (0x1d7e7, (5262, 1)),
- (0x1d39, (148, 1)),
+ (0xfe4d, (3801, 1)),
+ (0x1d53b, (4588, 1)),
+ (0xfe49, (3793, 2)),
+ (0x1d6ab, (4948, 1)),
(0x3132, (1085, 1)),
- (0x3302, (1679, 5)),
- (0xfcd9, (3129, 2)),
- (0x3192, (1178, 1)),
- (0x337b, (2107, 2)),
- (0x3327, (1830, 2)),
- (0xff0c, (4020, 1)),
- (0x1eea2, (5404, 1)),
- (0x1f227, (5613, 1)),
- (0xfcfe, (3208, 2)),
+ (0x1d7c2, (5227, 1)),
+ (0xfd9c, (3558, 3)),
+ (0x2fc2, (1051, 1)),
+ (0x33f4, (2402, 3)),
+ (0x213c, (425, 1)),
+ (0x1d7e8, (5263, 1)),
+ (0xff88, (4144, 1)),
+ (0x1d79d, (5190, 1)),
(0x24c1, (798, 1)),
- (0x1eeb8, (5424, 1)),
- (0x10799, (4258, 1)),
+ (0x24e0, (829, 1)),
+ (0x1eeb8, (5486, 1)),
+ (0xfc70, (2914, 2)),
(0xfc6c, (2906, 2)),
(0x2fac, (1029, 1)),
- (0x1f202, (5588, 1)),
+ (0x1f202, (5650, 1)),
(0xfbf3, (2642, 3)),
- (0x1d430, (4339, 1)),
+ (0x2f78, (977, 1)),
(0x3255, (1430, 2)),
- (0x329f, (1536, 1)),
- (0x1c9, (48, 2)),
- (0xfef3, (3985, 1)),
+ (0x2f2e, (903, 1)),
+ (0xfb24, (2481, 1)),
+ (0x32af, (1552, 1)),
(0x1d4a, (164, 1)),
- (0x1d9d, (199, 1)),
- (0xfc3b, (2796, 2)),
- (0x2477, (596, 3)),
+ (0x2f25, (894, 1)),
+ (0x1ee6e, (5424, 1)),
+ (0xfd2d, (3302, 2)),
(0xff6a, (4114, 1)),
- (0xfcdf, (3141, 3)),
- (0x1d59e, (4681, 1)),
- (0x10fc, (135, 1)),
- (0xfea9, (3911, 1)),
+ (0x2466, (562, 1)),
+ (0x1d579, (4644, 1)),
+ (0x1f231, (5685, 1)),
+ (0xfc61, (2875, 3)),
(0x1d7fd, (5284, 1)),
(0xfd5f, (3381, 3)),
- (0xfdae, (3612, 3)),
- (0x32e9, (1646, 1)),
- (0x1d63c, (4839, 1)),
- (0x3365, (2047, 3)),
- (0xfcb7, (3061, 2)),
- (0x1d611, (4796, 1)),
- (0xfc6a, (2902, 2)),
- (0x17f, (34, 1)),
- (0x3260, (1452, 1)),
+ (0x1ee1a, (5374, 1)),
+ (0x3348, (1958, 4)),
+ (0xfba9, (2580, 1)),
+ (0x1d45f, (4385, 1)),
+ (0x1d66d, (4888, 1)),
+ (0xfce8, (3161, 2)),
+ (0xfb5b, (2500, 1)),
+ (0x1ee62, (5416, 1)),
+ (0x3146, (1105, 1)),
(0x33ac, (2225, 3)),
- (0x1f149, (5562, 1)),
+ (0x1f149, (5624, 1)),
+ (0x3295, (1526, 1)),
(0x3333, (1877, 4)),
- (0x1d60, (185, 1)),
- (0x2b6, (68, 1)),
- (0x1ee29, (5322, 1)),
+ (0xfc0f, (2708, 2)),
+ (0xff8a, (4146, 1)),
(0x3387, (2133, 2)),
- (0xfd00, (3212, 2)),
- (0x32ba, (1572, 2)),
- (0x1d742, (5099, 1)),
- (0x32c7, (1598, 2)),
- (0x216b, (506, 3)),
- (0xfc83, (2952, 2)),
- (0x24e7, (836, 1)),
- (0x3241, (1406, 3)),
+ (0x676, (114, 2)),
+ (0xffcd, (4208, 1)),
+ (0xfe86, (3869, 2)),
+ (0x1d6e8, (5009, 1)),
+ (0xfc40, (2806, 2)),
+ (0xfc0a, (2698, 2)),
+ (0x10788, (4241, 1)),
+ (0x2fc0, (1049, 1)),
+ (0x1d5b6, (4705, 1)),
(0xffa8, (4176, 1)),
- (0x3188, (1171, 1)),
- (0x1d69a, (4933, 1)),
- (0x1d62d, (4824, 1)),
- (0x3210, (1242, 4)),
- (0xff46, (4078, 1)),
- (0x1d7b7, (5216, 1)),
+ (0x3289, (1514, 1)),
+ (0xfd79, (3459, 3)),
+ (0x3300, (1670, 5)),
+ (0x1d55, (174, 1)),
+ (0x24b5, (784, 3)),
+ (0x2f4c, (933, 1)),
(0x3163, (1134, 1)),
- (0x33dd, (2343, 2)),
- (0x207b, (330, 1)),
+ (0x2002, (277, 1)),
+ (0x2f57, (944, 1)),
(0xfcdb, (3133, 2)),
(0x1d49f, (4448, 1)),
- (0xfbe9, (2614, 1)),
- (0x3144, (1103, 1)),
- (0x33c7, (2292, 3)),
- (0x1d77a, (5155, 1)),
- (0x1d58d, (4664, 1)),
- (0x1d4d1, (4488, 1)),
- (0xffb6, (4190, 1)),
- (0x1d58f, (4666, 1)),
- (0x1ee93, (5394, 1)),
- (0xffb8, (4192, 1)),
+ (0x1d688, (4915, 1)),
+ (0xff18, (4032, 1)),
+ (0x2f54, (941, 1)),
+ (0x1ee85, (5443, 1)),
+ (0x2fd1, (1066, 1)),
+ (0x33c5, (2286, 2)),
+ (0xfb53, (2492, 1)),
+ (0x3197, (1183, 1)),
+ (0x2fcf, (1064, 1)),
+ (0x1d516, (4553, 1)),
(0x3201, (1195, 3)),
(0xfd82, (3486, 3)),
- (0x1d503, (4538, 1)),
- (0x1d7d6, (5245, 1)),
- (0x210d, (386, 1)),
- (0xff3f, (4071, 1)),
- (0x1d556, (4609, 1)),
- (0x1d70e, (5047, 1)),
- (0x2f09, (866, 1)),
- (0xfbe5, (2610, 1)),
- (0xfcbc, (3071, 2)),
- (0x1d5b8, (4707, 1)),
- (0xfc7b, (2936, 2)),
- (0x3242, (1409, 3)),
- (0x1d40b, (4302, 1)),
+ (0xff16, (4030, 1)),
+ (0x2150, (435, 3)),
+ (0x1f109, (5508, 2)),
+ (0xfe9d, (3899, 1)),
+ (0x210f, (388, 1)),
+ (0x320e, (1234, 4)),
+ (0x1e040, (5303, 1)),
+ (0x330a, (1711, 3)),
+ (0x1ee0e, (5362, 1)),
+ (0xfc45, (2816, 2)),
+ (0xff48, (4080, 1)),
+ (0xfc47, (2820, 2)),
+ (0x1d505, (4540, 1)),
(0x2169, (503, 1)),
- (0x1d787, (5168, 1)),
+ (0x24dc, (825, 1)),
(0x1d7d8, (5247, 1)),
- (0x3293, (1524, 1)),
+ (0xfb55, (2494, 1)),
(0xfe84, (3865, 2)),
- (0x1f14b, (5565, 2)),
- (0x1d602, (4781, 1)),
- (0x2fc9, (1058, 1)),
- (0x107b0, (4281, 1)),
+ (0x1ee22, (5381, 1)),
+ (0x1d772, (5147, 1)),
+ (0x33f0, (2390, 3)),
+ (0x1d4b1, (4459, 1)),
(0xff99, (4161, 1)),
+ (0xfd2e, (3304, 2)),
(0x2159, (463, 3)),
- (0xfe76, (3838, 2)),
- (0x1d741, (5098, 1)),
+ (0x1d58d, (4664, 1)),
(0x1d627, (4818, 1)),
(0xfeeb, (3977, 1)),
- (0x1ee81, (5377, 1)),
- (0x2128, (409, 1)),
- (0x217e, (541, 1)),
- (0xfeab, (3913, 1)),
- (0x1f16c, (5580, 2)),
+ (0x3334, (1881, 6)),
+ (0x1f126, (5578, 3)),
+ (0x3144, (1103, 1)),
+ (0x1e036, (5293, 1)),
+ (0x1db9, (227, 1)),
(0x1d6ea, (5011, 1)),
+ (0x1d6ee, (5015, 1)),
(0xfec6, (3940, 1)),
- (0x1d51a, (4557, 1)),
- (0x107a3, (4268, 1)),
+ (0x1d64c, (4855, 1)),
+ (0xfcbb, (3069, 2)),
(0x2033, (296, 2)),
- (0xfe8c, (3881, 2)),
- (0x1d5a3, (4686, 1)),
- (0x3321, (1809, 5)),
- (0xfc22, (2746, 2)),
- (0x133, (26, 2)),
- (0x1d665, (4880, 1)),
+ (0x2009, (284, 1)),
+ (0x3377, (2097, 2)),
+ (0x3160, (1131, 1)),
+ (0x1d48c, (4430, 1)),
+ (0x24b3, (778, 3)),
(0x1d4d0, (4487, 1)),
- (0x1d7e0, (5255, 1)),
+ (0xffcb, (4206, 1)),
(0xfdad, (3609, 3)),
+ (0x1ee8b, (5448, 1)),
(0xfeb1, (3919, 1)),
- (0x1d757, (5120, 1)),
+ (0xfcea, (3165, 2)),
(0x2f76, (975, 1)),
- (0x1d7bb, (5220, 1)),
(0x32be, (1580, 2)),
- (0x2163, (489, 2)),
- (0x1d4ab, (4454, 1)),
+ (0x1d7b1, (5210, 1)),
+ (0x1d5f8, (4771, 1)),
+ (0xfd73, (3441, 3)),
(0xff1a, (4034, 1)),
- (0x2f66, (959, 1)),
- (0x1d7e2, (5257, 1)),
- (0xfebb, (3929, 1)),
- (0xb5, (10, 1)),
- (0xfdb9, (3645, 3)),
- (0xa7f8, (2444, 1)),
+ (0xfca2, (3019, 2)),
+ (0x211b, (398, 1)),
+ (0x1d5b2, (4701, 1)),
+ (0xfb60, (2505, 1)),
+ (0x1ee2e, (5389, 1)),
+ (0x2071, (322, 1)),
(0x1d4bb, (4468, 1)),
(0x33fc, (2426, 3)),
- (0x3153, (1118, 1)),
- (0x1d533, (4581, 1)),
- (0x1eea6, (5407, 1)),
- (0x2478, (599, 3)),
+ (0xfeef, (3981, 1)),
+ (0x1d4fb, (4530, 1)),
+ (0x1d728, (5073, 1)),
+ (0xfcff, (3210, 2)),
(0x1d6f8, (5025, 1)),
- (0x1d41c, (4319, 1)),
- (0x1d5bc, (4711, 1)),
+ (0x1d535, (4583, 1)),
+ (0x1d34, (143, 1)),
(0x2165, (492, 2)),
- (0x2134, (416, 1)),
- (0x3280, (1505, 1)),
- (0xff2a, (4050, 1)),
- (0x1dba, (228, 1)),
- (0xff3c, (4068, 1)),
- (0x2463, (559, 1)),
- (0xfce2, (3149, 2)),
- (0x1d7f9, (5280, 1)),
- (0x33dc, (2341, 2)),
+ (0x1ee2c, (5387, 1)),
+ (0x1d5dd, (4744, 1)),
+ (0x2140, (429, 1)),
+ (0x322d, (1346, 3)),
+ (0x1ee96, (5459, 1)),
+ (0xffbe, (4198, 1)),
+ (0x1eeb5, (5483, 1)),
+ (0x3311, (1737, 4)),
+ (0xfd89, (3507, 3)),
(0x32d7, (1628, 1)),
- (0x2146, (431, 1)),
- (0xfc72, (2918, 2)),
- (0xfb97, (2560, 1)),
- (0x107ad, (4278, 1)),
- (0xfd07, (3226, 2)),
- (0xfb62, (2507, 1)),
- (0x319d, (1189, 1)),
+ (0x2f91, (1002, 1)),
+ (0x10798, (4257, 1)),
+ (0x246b, (569, 2)),
+ (0x24c2, (799, 1)),
+ (0x1d50e, (4546, 1)),
+ (0xffbc, (4196, 1)),
+ (0xfd9e, (3564, 3)),
(0x2115, (393, 1)),
(0x1d715, (5054, 1)),
+ (0xfcac, (3039, 2)),
(0xfc98, (2995, 3)),
- (0x33bc, (2266, 2)),
- (0x1d401, (4292, 1)),
- (0xff0a, (4018, 1)),
- (0x1ee68, (5357, 1)),
- (0x1ee49, (5340, 1)),
+ (0xfc66, (2890, 3)),
+ (0x2d6f, (854, 1)),
+ (0x1d59c, (4679, 1)),
+ (0xfc01, (2676, 3)),
+ (0x1ee49, (5402, 1)),
(0x2119, (396, 1)),
- (0xfb82, (2539, 1)),
+ (0x24d7, (820, 1)),
(0x1d642, (4845, 1)),
- (0x1d5c6, (4721, 1)),
- (0x107b7, (4287, 1)),
- (0x1d42b, (4334, 1)),
- (0xffc6, (4203, 1)),
- (0x1ee24, (5320, 1)),
- (0xfd03, (3218, 2)),
- (0x1d732, (5083, 1)),
- (0x1ee07, (5293, 1)),
- (0x2082, (337, 1)),
- (0x1d5e3, (4750, 1)),
- (0x2106, (377, 3)),
- (0x1f126, (5516, 3)),
- (0x2f51, (938, 1)),
- (0x1f14f, (5574, 2)),
- (0x1d4ef, (4518, 1)),
- (0x33e6, (2363, 2)),
- (0xff0b, (4019, 1)),
- (0x33d7, (2328, 2)),
+ (0x3304, (1687, 5)),
+ (0x3198, (1184, 1)),
+ (0xfed4, (3954, 1)),
+ (0x2f6c, (965, 1)),
+ (0x1d406, (4297, 1)),
+ (0x1d61d, (4808, 1)),
+ (0x33d5, (2322, 3)),
+ (0x1ee07, (5355, 1)),
+ (0x1d4ce, (4485, 1)),
+ (0x1f101, (5492, 2)),
+ (0x10792, (4251, 1)),
+ (0x24be, (795, 1)),
+ (0x2fbc, (1045, 1)),
+ (0x1f14f, (5636, 2)),
+ (0xfe12, (3759, 1)),
+ (0xfec7, (3941, 1)),
+ (0xfc2d, (2768, 2)),
+ (0x248a, (662, 2)),
(0x1fed, (265, 3)),
- (0x32f8, (1661, 1)),
+ (0x1d6d5, (4990, 1)),
(0x2fb2, (1035, 1)),
- (0x1d7ac, (5205, 1)),
- (0x32c4, (1592, 2)),
+ (0xfc8b, (2968, 2)),
+ (0x3158, (1123, 1)),
(0xffe3, (4223, 2)),
(0xfb84, (2541, 1)),
(0xfb65, (2510, 1)),
- (0xfcd1, (3113, 2)),
- (0x3d6, (103, 1)),
+ (0x1ee93, (5456, 1)),
+ (0x3208, (1216, 3)),
(0x32fc, (1665, 1)),
(0xfe94, (3890, 1)),
(0x2f4f, (936, 1)),
- (0x1d4ca, (4481, 1)),
- (0x200a, (285, 1)),
+ (0x2f87, (992, 1)),
+ (0x1ee75, (5430, 1)),
(0x2057, (316, 4)),
(0x1d617, (4802, 1)),
- (0x2fcb, (1060, 1)),
+ (0x1d5e1, (4748, 1)),
(0xfdac, (3606, 3)),
- (0x327e, (1503, 2)),
- (0xfcbf, (3077, 2)),
- (0xfd5d, (3375, 3)),
+ (0x2f0e, (871, 1)),
+ (0x211d, (400, 1)),
+ (0x331c, (1790, 3)),
(0x2f83, (988, 1)),
- (0xfce4, (3153, 2)),
+ (0x1d5c3, (4718, 1)),
(0x3373, (2088, 2)),
- (0x24d1, (814, 1)),
- (0xfce9, (3163, 2)),
- (0x24d6, (819, 1)),
- (0x32d2, (1623, 1)),
+ (0x1f13b, (5610, 1)),
+ (0x2486, (650, 4)),
+ (0x1d665, (4880, 1)),
+ (0xfce0, (3144, 3)),
(0x3d3, (98, 2)),
- (0x32a8, (1545, 1)),
- (0x1f250, (5661, 1)),
- (0x1d723, (5068, 1)),
- (0xfc75, (2924, 2)),
- (0xfbd7, (2595, 1)),
+ (0x1d403, (4294, 1)),
+ (0x1d640, (4843, 1)),
+ (0x24ac, (757, 3)),
+ (0x2f39, (914, 1)),
+ (0x1f140, (5615, 1)),
(0xfb6f, (2520, 1)),
- (0x1d5ba, (4709, 1)),
- (0xff70, (4120, 1)),
- (0x320e, (1234, 4)),
- (0x3390, (2154, 2)),
- (0xfeda, (3960, 1)),
- (0x2fad, (1030, 1)),
- (0xfb72, (2523, 1)),
- (0xff67, (4111, 1)),
- (0x1f223, (5609, 1)),
- (0x3234, (1367, 3)),
+ (0xfd13, (3250, 2)),
+ (0x1d4c6, (4477, 1)),
+ (0x1f248, (5720, 3)),
+ (0x3183, (1166, 1)),
+ (0x1d62e, (4825, 1)),
+ (0x1f148, (5623, 1)),
+ (0xfb89, (2546, 1)),
+ (0x1ee81, (5439, 1)),
+ (0xfc25, (2752, 2)),
+ (0x1f223, (5671, 1)),
+ (0x334e, (1982, 4)),
(0x2fd2, (1067, 1)),
- (0x1f243, (5643, 3)),
- (0x1ee21, (5318, 1)),
+ (0xfd54, (3348, 3)),
+ (0xff01, (4009, 1)),
(0x1d740, (5097, 1)),
- (0x1d468, (4394, 1)),
- (0x1f100, (5428, 2)),
- (0x1f241, (5637, 3)),
- (0x1d78d, (5174, 1)),
- (0x2b0, (62, 1)),
- (0x1db1, (219, 1)),
+ (0x1d7bc, (5221, 1)),
+ (0x1db4, (222, 1)),
+ (0x1d43e, (4353, 1)),
+ (0xfca9, (3033, 2)),
+ (0xfd22, (3280, 2)),
+ (0x2f23, (892, 1)),
(0x314e, (1113, 1)),
- (0x3304, (1687, 5)),
- (0x1d420, (4323, 1)),
- (0xfd7d, (3471, 3)),
- (0x328b, (1516, 1)),
- (0x1d67b, (4902, 1)),
- (0x1d62c, (4823, 1)),
- (0x317b, (1158, 1)),
+ (0xfe8a, (3877, 2)),
+ (0xff03, (4011, 1)),
+ (0x3292, (1523, 1)),
+ (0xfcf6, (3192, 2)),
+ (0x1d3f, (153, 1)),
+ (0x1db8, (226, 1)),
+ (0xfe68, (3826, 1)),
(0x1d69, (194, 1)),
(0x1079b, (4260, 1)),
- (0x2081, (336, 1)),
- (0x1d735, (5086, 1)),
- (0xfecc, (3946, 1)),
+ (0x331b, (1786, 4)),
+ (0xfda7, (3591, 3)),
+ (0xffdb, (4218, 1)),
(0xfc7c, (2938, 2)),
(0xfda5, (3585, 3)),
- (0x1d440, (4355, 1)),
+ (0x3341, (1934, 3)),
(0x24a7, (742, 3)),
- (0x2fa8, (1025, 1)),
+ (0x3216, (1266, 4)),
(0x2f3e, (919, 1)),
- (0xfc91, (2980, 2)),
+ (0xff9c, (4164, 1)),
(0xfb20, (2477, 1)),
- (0x1f116, (5468, 3)),
+ (0x1f116, (5530, 3)),
(0x325b, (1442, 2)),
- (0x1d4fe, (4533, 1)),
+ (0x1d5e6, (4753, 1)),
(0x1d79e, (5191, 1)),
- (0x1ee14, (5306, 1)),
- (0x32d3, (1624, 1)),
+ (0x1ee14, (5368, 1)),
+ (0x333f, (1927, 2)),
(0x32d4, (1625, 1)),
- (0xb8, (11, 2)),
- (0x24b1, (772, 3)),
- (0x1d5e7, (4754, 1)),
+ (0x1f22d, (5681, 1)),
+ (0xfd88, (3504, 3)),
+ (0x1d4d9, (4496, 1)),
(0xfdaa, (3600, 3)),
(0xfcc6, (3091, 2)),
- (0x2136, (418, 1)),
- (0x210c, (385, 1)),
- (0x32af, (1552, 1)),
- (0x1d3d, (151, 1)),
- (0x1f120, (5498, 3)),
+ (0x1d56e, (4633, 1)),
+ (0x1ee39, (5398, 1)),
+ (0x1d48a, (4428, 1)),
+ (0x1d7d0, (5239, 1)),
+ (0xb9, (13, 1)),
+ (0x1f120, (5560, 3)),
(0x1d60b, (4790, 1)),
- (0x2f2d, (902, 1)),
- (0x3368, (2056, 3)),
- (0x1eea1, (5403, 1)),
- (0x32f4, (1657, 1)),
- (0xff72, (4122, 1)),
- (0x24b6, (787, 1)),
- (0x1d630, (4827, 1)),
- (0x1d4cb, (4482, 1)),
- (0xfe47, (3791, 1)),
- (0x1d684, (4911, 1)),
+ (0x2f70, (969, 1)),
+ (0x1d4fa, (4529, 1)),
+ (0x2f5c, (949, 1)),
+ (0x32ab, (1548, 1)),
+ (0xfba3, (2572, 1)),
+ (0x2f02, (859, 1)),
+ (0x1f11f, (5557, 3)),
+ (0xfc69, (2899, 3)),
+ (0x24d4, (817, 1)),
(0x2491, (676, 3)),
- (0x32d0, (1621, 1)),
+ (0x326b, (1463, 1)),
(0xfc08, (2694, 2)),
+ (0x1d7b2, (5211, 1)),
(0x33ff, (2435, 3)),
- (0xfe65, (3824, 1)),
- (0x2f99, (1010, 1)),
- (0xfede, (3964, 1)),
- (0x1d471, (4403, 1)),
+ (0xfb8d, (2550, 1)),
+ (0x1fbf0, (5725, 1)),
+ (0x3252, (1424, 2)),
(0x1d6e5, (5006, 1)),
+ (0x1d5ac, (4695, 1)),
(0xfb94, (2557, 1)),
- (0xfe61, (3820, 1)),
(0x2f63, (956, 1)),
+ (0x107a2, (4267, 1)),
(0xfc06, (2690, 2)),
- (0x1d461, (4387, 1)),
- (0x1d5d3, (4734, 1)),
- (0x246e, (575, 2)),
+ (0xfc5a, (2858, 2)),
+ (0xff75, (4125, 1)),
+ (0xfeda, (3960, 1)),
(0xff79, (4129, 1)),
(0x2462, (558, 1)),
- (0x1d5b2, (4701, 1)),
- (0xfca1, (3017, 2)),
- (0x1d61b, (4806, 1)),
- (0xff12, (4026, 1)),
- (0x1ee51, (5345, 1)),
- (0x3f1, (105, 1)),
- (0x2145, (430, 1)),
- (0xfc48, (2822, 2)),
- (0x1d619, (4804, 1)),
- (0x323b, (1388, 3)),
- (0xfcc1, (3081, 2)),
- (0x1ee19, (5311, 1)),
- (0xfb26, (2483, 1)),
- (0x1d67e, (4905, 1)),
- (0x1d749, (5106, 1)),
+ (0xfc09, (2696, 2)),
+ (0x2111, (390, 1)),
+ (0x319e, (1190, 1)),
+ (0x1d451, (4372, 1)),
+ (0x2f20, (889, 1)),
+ (0x1d6a0, (4939, 1)),
+ (0x1d577, (4642, 1)),
+ (0x1d7b6, (5215, 1)),
+ (0xff15, (4029, 1)),
+ (0x1d744, (5101, 1)),
+ (0x1f21c, (5664, 1)),
+ (0x1fbf2, (5727, 1)),
+ (0xfc3a, (2794, 2)),
+ (0x337b, (2107, 2)),
+ (0xfdb8, (3642, 3)),
(0xffc3, (4200, 1)),
- (0x1d564, (4623, 1)),
+ (0x33db, (2339, 2)),
+ (0xff0c, (4020, 1)),
(0x1d52a, (4572, 1)),
- (0x1d500, (4535, 1)),
- (0x1d5d8, (4739, 1)),
- (0x1d7b1, (5210, 1)),
- (0x1d563, (4622, 1)),
- (0x2047, (310, 2)),
- (0x33eb, (2375, 3)),
- (0xfda3, (3579, 3)),
- (0x3317, (1765, 5)),
- (0xff74, (4124, 1)),
- (0x1ee1e, (5316, 1)),
- (0x3308, (1704, 4)),
- (0x33d6, (2325, 3)),
- (0x3269, (1461, 1)),
- (0x1ee27, (5321, 1)),
- (0x1d5c3, (4718, 1)),
- (0xfe3c, (3782, 1)),
- (0x1eeb0, (5416, 1)),
- (0x335f, (2032, 2)),
- (0x338b, (2144, 2)),
- (0x3318, (1770, 4)),
- (0xfe7c, (3850, 2)),
- (0xfedf, (3965, 1)),
- (0x1d32, (141, 1)),
- (0xfb63, (2508, 1)),
- (0xfe42, (3788, 1)),
+ (0x1ee9b, (5464, 1)),
+ (0x24e2, (831, 1)),
+ (0xff9e, (4166, 1)),
+ (0x32de, (1635, 1)),
+ (0x1d574, (4639, 1)),
+ (0x1ee76, (5431, 1)),
+ (0x1d59e, (4681, 1)),
+ (0x1f244, (5708, 3)),
+ (0x1f137, (5606, 1)),
+ (0xfea0, (3902, 1)),
+ (0xff2a, (4050, 1)),
+ (0x314f, (1114, 1)),
+ (0x1d47c, (4414, 1)),
+ (0x1d467, (4393, 1)),
+ (0xff4f, (4087, 1)),
+ (0xfea1, (3903, 1)),
+ (0x33a9, (2217, 2)),
+ (0x10799, (4258, 1)),
+ (0x1ee12, (5366, 1)),
+ (0x2492, (679, 3)),
+ (0x1d696, (4929, 1)),
+ (0xfcab, (3037, 2)),
+ (0xfd19, (3262, 2)),
+ (0x1d5e8, (4755, 1)),
+ (0x1ee1f, (5379, 1)),
(0xfe91, (3887, 1)),
(0x1c7, (44, 2)),
- (0x320b, (1225, 3)),
- (0x321a, (1282, 4)),
- (0x1d4c5, (4476, 1)),
+ (0x1d681, (4908, 1)),
+ (0x24b7, (788, 1)),
(0x1d784, (5165, 1)),
- (0x320d, (1231, 3)),
- (0x1d49e, (4447, 1)),
- (0x1d604, (4783, 1)),
- (0xfc71, (2916, 2)),
- (0x1d6ce, (4983, 1)),
- (0x1d752, (5115, 1)),
+ (0x1d742, (5099, 1)),
+ (0x33a2, (2196, 3)),
+ (0x1d645, (4848, 1)),
+ (0x1ee70, (5426, 1)),
+ (0x1d611, (4796, 1)),
+ (0x337c, (2109, 2)),
+ (0x1d442, (4357, 1)),
(0xfe32, (3772, 1)),
- (0x1ee11, (5303, 1)),
(0x1d31, (140, 1)),
+ (0x3138, (1091, 1)),
(0x2485, (646, 4)),
- (0xfedb, (3961, 1)),
- (0x1d50f, (4547, 1)),
- (0x313a, (1093, 1)),
- (0xfb66, (2511, 1)),
- (0xff64, (4108, 1)),
- (0x1d5ac, (4695, 1)),
- (0x1d4e2, (4505, 1)),
- (0x3f4, (107, 1)),
- (0xfecb, (3945, 1)),
+ (0x1f114, (5524, 3)),
+ (0x1d5d0, (4731, 1)),
+ (0x1d635, (4832, 1)),
+ (0x3309, (1708, 3)),
+ (0x1d408, (4299, 1)),
+ (0xfe50, (3804, 1)),
+ (0x1ee8d, (5450, 1)),
+ (0xfd93, (3531, 3)),
+ (0x1d67b, (4902, 1)),
(0x1d4db, (4498, 1)),
- (0x2fc3, (1052, 1)),
- (0x1ee4e, (5343, 1)),
- (0xfcd6, (3123, 2)),
+ (0x1f136, (5605, 1)),
+ (0x1f22f, (5683, 1)),
+ (0x1d7ed, (5268, 1)),
+ (0x32f9, (1662, 1)),
(0x32aa, (1547, 1)),
- (0x3354, (2002, 5)),
- (0x1d5f7, (4770, 1)),
+ (0x33af, (2236, 6)),
(0x24e4, (833, 1)),
- (0x32e0, (1637, 1)),
- (0x1d421, (4324, 1)),
- (0x1d587, (4658, 1)),
+ (0x2003, (278, 1)),
+ (0xfd80, (3480, 3)),
+ (0x1e04e, (5317, 1)),
+ (0x1d59b, (4678, 1)),
(0x3285, (1510, 1)),
- (0x1fee, (268, 3)),
(0x1d78e, (5175, 1)),
- (0x2007, (282, 1)),
+ (0x3379, (2102, 3)),
(0x107b2, (4282, 1)),
(0xfeb7, (3925, 1)),
- (0x32e4, (1641, 1)),
+ (0x2470, (579, 2)),
(0x1d620, (4811, 1)),
- (0x1d6ca, (4979, 1)),
- (0x1d725, (5070, 1)),
- (0xfdbe, (3660, 3)),
+ (0x1d4b4, (4462, 1)),
+ (0x1d754, (5117, 1)),
+ (0x1f246, (5714, 3)),
(0x2160, (483, 1)),
- (0xfc52, (2842, 2)),
- (0xfc73, (2920, 2)),
- (0x2171, (514, 2)),
- (0x1d528, (4570, 1)),
+ (0x1d72f, (5080, 1)),
+ (0xfe4f, (3803, 1)),
+ (0x1d47a, (4412, 1)),
+ (0x1fcd, (247, 3)),
+ (0x327d, (1499, 4)),
(0x338e, (2150, 2)),
- (0xfdf4, (3704, 4)),
- (0x33f2, (2396, 3)),
- (0x3222, (1313, 3)),
- (0x1f22b, (5617, 1)),
- (0x1d453, (4374, 1)),
- (0x1d41b, (4318, 1)),
- (0xffcc, (4207, 1)),
- (0x1d58e, (4665, 1)),
- (0xfd19, (3262, 2)),
- (0x1d6bb, (4964, 1)),
- (0x1d41d, (4320, 1)),
- (0x2f7e, (983, 1)),
- (0xfe8d, (3883, 1)),
- (0xff58, (4096, 1)),
- (0x24dc, (825, 1)),
- (0xfe55, (3808, 1)),
- (0x3231, (1358, 3)),
+ (0x33b3, (2248, 2)),
+ (0xfd10, (3244, 2)),
+ (0x2f37, (912, 1)),
+ (0x3187, (1170, 1)),
+ (0xff5c, (4100, 1)),
+ (0x2135, (417, 1)),
+ (0x1d73b, (5092, 1)),
+ (0x3178, (1155, 1)),
+ (0xfc86, (2958, 2)),
+ (0x2fa5, (1022, 1)),
+ (0x1d6f1, (5018, 1)),
+ (0x1db5, (223, 1)),
+ (0xfb7d, (2534, 1)),
+ (0xfc48, (2822, 2)),
+ (0x1d56, (175, 1)),
+ (0x1d647, (4850, 1)),
+ (0xfe65, (3824, 1)),
(0xfc18, (2726, 2)),
(0x33f1, (2393, 3)),
- (0x32f1, (1654, 1)),
- (0x209c, (362, 1)),
- (0xfe8b, (3879, 2)),
- (0x24e0, (829, 1)),
- (0x1d4b6, (4464, 1)),
- (0x1d622, (4813, 1)),
+ (0x328c, (1517, 1)),
+ (0x32b9, (1570, 2)),
+ (0xfb79, (2530, 1)),
+ (0x1d4ee, (4517, 1)),
+ (0x338f, (2152, 2)),
+ (0x1d663, (4878, 1)),
(0x33b7, (2256, 2)),
- (0x1d487, (4425, 1)),
+ (0x1d55a, (4613, 1)),
(0xfcb1, (3049, 2)),
- (0x331e, (1796, 4)),
+ (0x3254, (1428, 2)),
(0xfbde, (2603, 1)),
(0x2f73, (972, 1)),
- (0x32f6, (1659, 1)),
+ (0x1d497, (4441, 1)),
(0xff89, (4145, 1)),
(0x1d5f5, (4768, 1)),
];
@@ -28460,403 +28666,410 @@ pub(crate) const CJK_COMPAT_VARIANTS_DECOMPOSED_KV: &[(u32, (u16, u16))] = &[
pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
+ 0xd,
+ 0x4,
+ 0xc,
+ 0x5,
+ 0x689,
+ 0x7,
+ 0x0,
0x2,
- 0x2,
- 0x6,
- 0x9,
- 0xb02,
- 0x15,
0x0,
- 0x8,
- 0x1c,
0x2,
- 0x206,
+ 0x3,
0x0,
0x0,
- 0x82,
+ 0xab,
0x0,
- 0x269,
+ 0x158,
0x0,
- 0x24,
- 0x11a,
+ 0x5a,
+ 0x1c6,
+ 0x143,
0x0,
+ 0x1,
0x0,
- 0x7,
- 0x2a,
- 0xe,
+ 0x4,
0x0,
0x0,
0x0,
- 0x1,
+ 0x6,
+ 0x4,
0x0,
- 0x235,
+ 0x92,
0x0,
0x0,
- 0x1a6,
+ 0x24d,
0x0,
- 0x5,
+ 0x7,
0x0,
- 0xa5,
+ 0x7f,
0xc,
0x0,
+ 0xc7,
0x0,
- 0xfa,
- 0x32b,
- 0x0,
+ 0x16d,
0x0,
0x0,
- 0x1b,
- 0x5c,
- 0x1,
- 0x1,
0x0,
- 0x8f,
- 0xd,
- 0x15b,
- 0x63,
+ 0xda,
+ 0x4,
0x19,
+ 0x5,
+ 0x0,
+ 0x93,
+ 0x6,
+ 0x7c,
+ 0x13,
+ 0x11b,
0x0,
0x1,
- 0x11,
- 0x43,
+ 0x8,
+ 0x58,
+ 0x0,
+ 0x5c,
+ 0xa5,
0x0,
- 0x36,
- 0x3f,
0x1,
- 0x17,
0x0,
0x0,
0x0,
0xb4,
0x1,
- 0x53,
- 0x0,
0x1,
- 0x7e,
- 0xb,
- 0x0,
- 0x73,
- 0x4b,
0x0,
- 0x4e,
- 0x1e,
- 0x9b,
- 0x3,
- 0x15,
+ 0x1,
+ 0x8,
0x0,
+ 0x79,
+ 0x7,
0x0,
+ 0xa0,
+ 0x37,
0x0,
0x7,
+ 0x36,
+ 0x5,
+ 0x39,
0x0,
0x0,
- 0x22,
0x2,
- 0x0,
- 0x89,
+ 0x9,
0x0,
0x0,
- 0x25,
+ 0x73,
0x1,
+ 0x5,
0x0,
0x0,
- 0x41,
0x0,
+ 0x3d,
0x1,
0x0,
- 0x0,
0x4,
- 0x23,
+ 0x0,
+ 0x54,
+ 0x1,
+ 0x0,
+ 0x27,
+ 0x4d,
+ 0xfa,
+ 0x4d,
0x3,
- 0x10,
0x1c,
- 0x66,
- 0xc,
- 0x7,
- 0x36,
- 0x40,
- 0x0,
+ 0xdd,
+ 0x6,
+ 0x1,
+ 0x24,
+ 0x41,
0x0,
0x0,
- 0x1d,
0x0,
- 0x12,
- 0xa,
- 0x4,
+ 0xb,
0x0,
- 0xc,
- 0x7,
- 0x4,
0x5,
+ 0x3,
+ 0xb6,
0x0,
- 0x8a,
- 0x6d,
- 0x1e,
- 0x0,
- 0x15,
+ 0xf,
0x0,
- 0x10,
- 0x3,
- 0x3b,
- 0xa3,
- 0xd,
- 0x2,
- 0x37,
- 0x25,
- 0x17,
+ 0x1,
0x16,
0x0,
- 0x6,
0x0,
+ 0x9e,
0x1,
0x0,
+ 0x21,
+ 0x0,
+ 0x25,
+ 0x4,
+ 0x10,
+ 0x4,
+ 0x15,
+ 0x2,
0x1,
- 0x47,
- 0x24,
- 0x12,
+ 0x23,
+ 0x5,
+ 0x84,
0x0,
0x0,
+ 0xf,
+ 0xa,
+ 0x2,
+ 0x37,
0x1,
0x0,
+ 0x46,
+ 0xd,
+ 0x12,
0x0,
+ 0x4,
0x0,
0x0,
- 0x1,
- 0x34,
0x0,
- 0x1,
+ 0x24,
+ 0xc,
+ 0x4a,
+ 0x2,
+ 0x4,
0x0,
- 0x1e,
+ 0x42,
0x0,
- 0x3,
+ 0x4,
0x13,
- 0x8,
- 0x28,
- 0x2b,
- 0x57,
+ 0x2,
+ 0x13,
+ 0x7b,
+ 0x3e,
0x0,
- 0x1d,
- 0x3,
0x11,
- 0x8,
+ 0x2,
+ 0x7,
+ 0x1,
0x0,
+ 0x31,
0x3,
- 0x47,
0x0,
- 0x4,
+ 0x12,
0x0,
0x0,
0x0,
+ 0x35,
+ 0x6,
0xe,
- 0x3,
- 0x5,
- 0x0,
- 0x3f,
+ 0x1e,
+ 0xc1,
0x0,
0x0,
0x0,
0x0,
- 0x1,
0x5,
+ 0x2,
+ 0x1c,
0x0,
- 0x18,
- 0x32,
- 0x1,
+ 0x8,
0x0,
- 0x14,
- 0xa,
0x9,
- 0x23,
0x3,
- 0x0,
+ 0x8d,
+ 0x70,
+ 0x54,
+ 0x23,
+ 0x11,
+ 0x1f,
+ 0x5,
+ 0x17,
+ 0x4,
0x2,
0x0,
- 0x1,
- 0x3,
- 0x0,
- 0xe,
- 0x1a,
- 0x8,
- 0xf,
+ 0x47,
+ 0x17,
+ 0xc,
+ 0x2a,
0x0,
- 0x1,
+ 0x3,
0x0,
0x0,
0x0,
- 0x4,
- 0x4e,
- 0x2,
- 0x1b,
- 0x15,
0x5,
+ 0x38,
+ 0x11,
+ 0x15,
+ 0x39,
+ 0x6,
0x0,
0x3,
+ 0x3,
0x1,
- 0xd,
0x0,
0x0,
0x0,
- 0x5,
- 0x3,
- 0x0,
- 0x2,
+ 0x53,
+ 0x4,
0x1,
- 0x1b,
- 0x0,
- 0x20,
- 0x3,
+ 0x1,
+ 0x1,
+ 0x2,
0x0,
+ 0xf,
+ 0x6,
0x0,
0x0,
- 0x9,
- 0x6,
0x0,
+ 0x4,
+ 0x28,
+ 0x4,
0x0,
0x0,
- 0x1e,
- 0x31,
+ 0x11,
+ 0x2e,
+ 0x6,
+ 0x4,
0x1,
- 0xc,
- 0xb,
0x1,
+ 0x12,
0x0,
0x0,
0x0,
+ 0x2,
0x5,
- 0x1,
- 0x4,
- 0x11,
0x0,
- 0x3a,
- 0x1,
0x15,
+ 0x2e,
0x0,
- 0x12,
+ 0x1,
0x0,
0x0,
- 0x4,
- 0x13,
- 0x14,
+ 0x6,
0x0,
0x0,
- 0x11,
- 0x2,
- 0x8,
+ 0xd,
+ 0x3,
0x0,
0x0,
+ 0x3f,
0x8,
- 0x3,
0x0,
- 0x4,
- 0x0,
- 0x3,
- 0xb,
- 0x3,
- 0xc,
+ 0x8,
0x0,
0x0,
+ 0x1a,
+ 0x2,
0x0,
- 0x9,
+ 0x7,
0x0,
- 0x6,
- 0x1,
0xa,
+ 0x0,
0x3,
+ 0xc,
+ 0x0,
+ 0x14,
+ 0x0,
0x6,
- 0x2,
+ 0x0,
+ 0x19,
0x1,
0x3,
- 0x2,
- 0x2b,
- 0x9,
0x3,
+ 0x6,
+ 0x10,
+ 0x12,
+ 0x1,
+ 0x16,
+ 0x0,
+ 0x4,
+ 0x1,
0x0,
0x0,
0x0,
- 0x8,
- 0x30,
- 0x2,
0x0,
- 0x1,
- 0x1b,
+ 0x3,
0x2,
+ 0x21,
+ 0x1,
+ 0x3,
+ 0x13,
+ 0x16,
0x0,
0x0,
- 0x29,
- 0x4,
- 0xb,
- 0x5f,
+ 0x1,
+ 0x5,
0x0,
+ 0xe,
0x0,
0x0,
+ 0x38,
+ 0x2,
+ 0x20,
0x3,
- 0xb,
- 0x1,
0x0,
- 0x9,
0xa,
+ 0xe,
0x1,
- 0x8,
- 0x4,
+ 0x3,
0x0,
- 0x8,
- 0x1,
0x0,
+ 0xa,
+ 0x6,
0x0,
- 0x1f,
+ 0x0,
+ 0x2,
0x0,
0x0,
- 0x8,
- 0x28,
+ 0x0,
+ 0x2,
0x0,
0x4,
0x18,
- 0x1e,
+ 0x1,
+ 0x0,
0x2,
0x0,
+ 0xc,
0x0,
- 0xa,
0x0,
0x1,
+ 0x1,
0x0,
0x1,
- 0x9,
+ 0x0,
0xb,
0x0,
- 0x2,
- 0x1e,
- 0x18,
+ 0x1,
0x2,
0x0,
0x0,
- 0xd,
- 0xb,
- 0x25,
+ 0x1b,
+ 0x6,
0x0,
+ 0x4,
0x0,
0x0,
- 0x4,
+ 0x5,
+ 0x20,
0x0,
- 0x1,
- 0xc,
+ 0x9,
0x0,
0x0,
0x0,
- 0x4,
0x0,
- 0x1,
+ 0x2,
0x0,
+ 0x1,
0x3,
- 0xa,
0x0,
- 0xf,
+ 0xc,
0x0,
+ 0x16,
0x0,
- 0xb,
0x0,
- 0x5,
+ 0x3,
+ 0x0,
+ 0x7,
0x0,
+ 0x8,
0x4,
- 0x3,
0x0,
0x0,
0x0,
@@ -28868,1022 +29081,1040 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x4,
+ 0x1f,
+ 0xa,
+ 0x28,
0x0,
- 0xe,
+ 0x1,
0x0,
0x0,
+ 0x8,
+ 0xd,
0x0,
0x0,
0x0,
- 0x11,
0x0,
0x0,
+ 0x1,
0x0,
+ 0x2,
0x0,
0x0,
- 0x1,
- 0x21,
+ 0x3a,
+ 0x4,
+ 0x8,
+ 0xb,
+ 0x0,
0x17,
0x0,
+ 0x2,
0x0,
- 0x1,
- 0x7,
- 0x16,
- 0xc,
- 0x1,
0x0,
0x22,
- 0x5,
0x0,
- 0x3,
- 0x0,
- 0x24,
- 0xc,
- 0x3,
0x4,
- 0x5,
- 0x1f,
- 0x7,
- 0x1,
- 0xa,
0x0,
0x1,
- 0x3a,
+ 0x2,
+ 0x6,
+ 0x17,
+ 0x7,
0x9,
+ 0x27,
0x0,
0x1,
- 0x5,
- 0x0,
- 0x0,
+ 0x11,
+ 0x7,
+ 0x23,
0x1,
0x1,
- 0x3,
- 0x27,
- 0x9,
- 0x0,
- 0xf,
- 0x18,
- 0x3,
- 0x4,
0x0,
0x0,
0x9,
- 0x5,
- 0x4,
- 0x0,
- 0xf,
- 0x1,
- 0x1,
- 0x7,
+ 0x8,
0x2,
- 0x1,
- 0x7,
- 0x1,
- 0x5,
+ 0x27,
0x8,
0x0,
- 0x3e,
- 0x2,
- 0xb,
- 0xd,
- 0x1,
- 0xf,
+ 0x17,
+ 0xc,
+ 0x3b,
+ 0x6,
0x0,
0x0,
- 0x9,
- 0x1d,
- 0x12,
+ 0xc,
+ 0x0,
+ 0x4,
0x0,
+ 0x2e,
+ 0x5,
+ 0x7,
+ 0x7,
0x0,
- 0xc,
0x3,
- 0x6,
- 0x19,
+ 0xf,
+ 0x1,
0x0,
- 0x15,
- 0x6,
- 0x14,
0x2,
0x0,
0x6,
+ 0x2,
+ 0x2,
+ 0x4,
0x0,
- 0x9,
- 0x0,
+ 0x3,
+ 0xf,
0x0,
- 0xe,
- 0x1,
0x1,
+ 0x12,
+ 0x24,
0x0,
- 0x2,
- 0x3,
0x0,
0x0,
+ 0xb,
0x1f,
- 0xa,
+ 0x15,
+ 0xd,
0x0,
- 0x8,
+ 0x1,
0x0,
- 0x3,
+ 0x1,
+ 0x2,
0x0,
0x1,
0x0,
- 0x2,
- 0x1b,
+ 0x8,
+ 0x0,
0x0,
- 0x4,
0xc,
0x1,
+ 0xe,
+ 0x0,
0x4,
+ 0x4,
+ 0x0,
0x0,
0x1,
+ 0x3,
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x2e,
+ 0x0,
+ 0x11,
+ 0x0,
+ 0x1b,
+ 0xa,
+ 0x13,
+ 0x12,
+ 0x2,
0x9,
- 0x7,
- 0x7,
+ 0x1,
+ 0xd,
0x0,
- 0x3,
0x1,
+ 0x2,
+ 0x0,
+ 0xd,
0x0,
+ 0xb,
+ 0x6,
0x0,
0x0,
+ 0xb,
0x1,
0x0,
0x0,
- 0x6,
0x2,
- 0x0,
+ 0x13,
+ 0x16,
+ 0xd,
+ 0xe,
+ 0x4,
+ 0xf,
+ 0xb,
0x2,
0x0,
- 0x1,
- 0xa,
- 0x1,
0x0,
- 0x5,
+ 0xa,
0x0,
- 0x1c,
+ 0x3,
0x0,
0xd,
- 0x6,
- 0x3,
0x2,
- 0xe,
+ 0xb,
0x0,
- 0x10,
+ 0x1d,
0x0,
- 0x1,
- 0x3d,
+ 0x2,
+ 0x7,
0x0,
0x0,
- 0x6,
+ 0x1,
0x0,
0x0,
0x0,
- 0x3,
0x7,
+ 0x6,
+ 0xe,
0x4,
- 0x20,
- 0xc,
- 0x1,
0x0,
- 0x15,
+ 0x1,
+ 0x8,
+ 0x14,
0x0,
- 0x2,
0x0,
+ 0x15,
0x0,
- 0x5,
+ 0x1,
0x0,
0x0,
0x0,
- 0xd,
+ 0x10,
0x0,
0x0,
- 0x2,
- 0x3,
+ 0x6,
+ 0x17,
0x0,
0x1,
0x0,
- 0x4,
+ 0x10,
0x0,
0x0,
0x0,
- 0xd,
+ 0xa,
0x0,
0x0,
- 0x5,
- 0x2c,
+ 0x1,
+ 0x6,
+ 0x4,
+ 0x0,
0x4,
- 0x2,
0x1,
- 0x7,
0x1,
- 0xa,
- 0xf,
+ 0x2,
+ 0x2,
0x0,
- 0x8,
+ 0x1,
+ 0x7,
0x0,
0x0,
- 0x13,
- 0x1,
- 0x19,
0x2,
- 0x1,
- 0xf,
+ 0x2,
+ 0x7,
+ 0x2,
+ 0x1f,
+ 0x9,
0x0,
0x4,
- 0x19,
+ 0x7,
0x0,
- 0xc,
+ 0x1,
0x0,
0x0,
0x0,
- 0x1,
+ 0x4,
+ 0x3,
+ 0x4,
0x0,
- 0x5,
0x0,
0x0,
- 0x1,
+ 0x4,
0x0,
0x0,
0x1,
- 0xd,
- 0x1,
- 0x5,
+ 0x9,
+ 0x17,
+ 0x6,
+ 0xf,
+ 0xc,
0x0,
- 0x2,
- 0xb,
0x0,
0x0,
+ 0x10,
0x0,
- 0x18,
- 0x6,
- 0x1,
- 0x1,
+ 0x2,
+ 0x2,
0x0,
- 0x3,
- 0x4,
0x6,
+ 0x2,
0x0,
0x3,
- 0x8,
- 0x4,
- 0x6,
0x2,
+ 0x9,
+ 0x3,
+ 0x2,
+ 0x3,
+ 0x1,
0x0,
0x0,
0x0,
+ 0x12,
+ 0x4,
0x0,
- 0x6,
- 0x0,
+ 0x8,
0x0,
- 0x2,
0x3,
- 0xb,
+ 0x18,
0x0,
0x3,
- 0x0,
0xc,
- 0x3,
- 0x17,
0x0,
+ 0x2,
+ 0x26,
0x0,
- 0x4,
- 0xa,
- 0x11,
+ 0x0,
+ 0x2,
+ 0x6,
+ 0x2,
0x0,
0x1,
- 0x3,
- 0x3,
+ 0x9,
0x8,
- 0xd,
+ 0x16,
0x1,
+ 0x3,
0x11,
0x0,
- 0x9,
+ 0x13,
0x0,
+ 0x2,
0x7,
0x0,
- 0x2,
+ 0x3,
0x0,
0x0,
0x0,
- 0x7,
- 0x2,
+ 0xc,
+ 0x1a,
0x0,
0x0,
- 0x7,
0x1,
- 0x7,
- 0x6,
+ 0x2,
0x0,
- 0x3,
- 0x5,
- 0xa,
+ 0x2,
+ 0x9,
+ 0x4,
+ 0x12,
0x0,
0x0,
- 0x3,
- 0xe,
+ 0x11,
+ 0x8,
+ 0x0,
0x0,
0x1,
- 0x8,
0x3,
- 0x2,
+ 0x0,
+ 0x3,
+ 0x6,
+ 0xf,
0x4,
- 0x5,
- 0x1d,
- 0x7,
0x1,
+ 0x3,
0x0,
- 0x4,
0x7,
+ 0x4,
0x9,
+ 0x4,
+ 0x1,
+ 0x0,
0x5,
- 0x3,
+ 0x4,
0x0,
- 0xd,
- 0x3,
+ 0x1,
0x0,
- 0x4,
0x0,
+ 0x3,
+ 0x2,
+ 0x15,
+ 0x2,
+ 0x0,
+ 0x8,
0x0,
0x2,
- 0x1,
0x0,
- 0x14,
- 0x15,
- 0x4,
0x3,
- 0x4,
- 0x0,
- 0x17,
- 0xc,
+ 0x11,
+ 0x6,
+ 0x6,
+ 0xd,
0x1,
0x0,
- 0x4,
0x1,
- 0x5,
0x3,
- 0x5,
- 0xb,
0x6,
- 0x5,
- 0x7,
- 0x3,
- 0x0,
- 0x3,
+ 0x20,
+ 0x4,
+ 0x1,
+ 0x2,
+ 0xb,
+ 0x1,
0x0,
0x0,
+ 0x1,
+ 0x1,
0x11,
- 0x21,
0x0,
- 0x10,
- 0x4,
- 0x4,
- 0x0,
- 0x4,
+ 0x1,
0x0,
- 0x15,
- 0x3,
+ 0x2,
0x1,
+ 0x0,
+ 0x0,
+ 0x7,
0x4,
+ 0x5,
+ 0x3,
0x0,
0x0,
0x0,
- 0x1,
- 0x8,
- 0x3,
- 0x2,
+ 0x5,
0x0,
+ 0x2,
0x3,
0x0,
- 0x1,
+ 0x3,
0x0,
+ 0x4,
+ 0x4,
0x2,
0x0,
- 0xc,
- 0x6,
- 0x5,
- 0x2,
- 0x1b,
- 0x2,
- 0x2,
- 0x1,
0x2,
- 0xf,
+ 0x19,
+ 0x4,
0x1,
- 0x0,
- 0x16,
- 0x0,
+ 0x13,
0x1,
+ 0x2,
0x9,
+ 0xb,
+ 0x6,
+ 0x4,
0x0,
0x1,
0x0,
+ 0x1,
+ 0x1a,
0x0,
0x2,
+ 0x5,
0x0,
0xf,
0x0,
- 0x1,
- 0x17,
- 0x4,
- 0x2,
+ 0x8,
+ 0x0,
+ 0x0,
0x2,
+ 0x4,
+ 0x10,
0x1,
0x1,
+ 0x2,
+ 0x12,
0x0,
0x0,
+ 0x9,
0x0,
- 0xc,
- 0x0,
- 0x3,
- 0x0,
+ 0x13,
0x1,
- 0x6,
- 0x5,
0x2,
- 0x0,
- 0x8,
- 0x5,
+ 0x4,
0x6,
+ 0x4,
+ 0x4,
0x0,
- 0x3,
- 0x9,
+ 0x6,
+ 0x2,
0x15,
0x0,
- 0xb,
+ 0x1,
+ 0x9,
+ 0xe,
+ 0x2,
0x3,
0x3,
+ 0x0,
+ 0x1,
0x4,
- 0x3,
0x0,
0x0,
- 0x2,
- 0xb,
+ 0x5,
+ 0xe,
+ 0x0,
+ 0x7,
0x0,
0x2,
0x0,
+ 0xb,
0x2,
- 0x8,
- 0x1,
- 0x15,
0x0,
- 0x3,
+ 0x1,
0x4,
- 0x2,
+ 0x9,
0x2,
0x0,
0x0,
- 0x4,
+ 0x0,
0x1,
0x1,
- 0xf,
- 0x8,
- 0xe,
- 0x6,
- 0x3,
0x0,
+ 0x4,
0x1,
+ 0xd,
+ 0x3,
0x0,
0x1,
- 0x1,
- 0x1,
- 0x0,
0x0,
+ 0x4,
+ 0x3,
0x1,
- 0x0,
- 0x8,
0x2,
0x0,
- 0x4,
+ 0x2,
+ 0x5,
0x0,
+ 0x3,
+ 0x2c,
+ 0xa,
+ 0x3,
0x0,
- 0x1,
+ 0x9,
0x0,
- 0x3,
0x0,
0x2,
0x0,
- 0x0,
- 0x1,
0x1,
0x0,
0x0,
+ 0x27,
+ 0x2,
0x0,
0x0,
+ 0x0,
+ 0x15,
0x1,
+ 0x2,
+ 0x4,
+ 0x0,
+ 0x2,
+ 0x0,
0x3,
0x3,
- 0x0,
0x1,
0x0,
- 0x7,
- 0x7,
+ 0x2,
+ 0x5,
+ 0xa,
0x9,
- 0x0,
- 0x1,
- 0x1,
- 0x4,
- 0x4,
0x1,
0x2,
0x3,
- 0x16,
- 0x3,
0x1,
- 0xd,
- 0x3,
- 0xb,
0x5,
- 0x4,
- 0x0,
- 0x7,
- 0x4,
- 0x0,
+ 0x1,
0x8,
- 0xc,
- 0x0,
+ 0x1,
+ 0x1,
+ 0xf,
0x0,
+ 0x3,
+ 0xa,
+ 0x3,
0x4,
- 0x7,
- 0x1,
0xd,
+ 0x3,
+ 0x1,
0x0,
+ 0xc,
+ 0x1e,
0x1,
0x1,
+ 0xa,
0x1,
- 0x6,
+ 0x3,
0x0,
- 0x4,
- 0x9,
- 0x9,
- 0x8,
- 0x1,
0x1,
+ 0x0,
0x6,
- 0x2,
- 0x1,
0x0,
+ 0x3,
0x2,
- 0x1,
+ 0x7,
+ 0x3,
+ 0xe,
+ 0x3,
+ 0x4,
+ 0xf,
+ 0x4,
0x2,
+ 0x3,
+ 0x8,
0x0,
0x2,
0x3,
0x1,
+ 0x10,
+ 0x2,
+ 0x2,
0x2,
- 0x1,
- 0x1,
- 0x4,
0x0,
0x0,
- 0x1,
- 0x3,
+ 0x5,
+ 0x2,
0x0,
- 0x4,
0x0,
+ 0x5,
0x0,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x3,
0x7,
+ 0x8,
0x0,
0x0,
0x0,
- 0x2,
+ 0x4,
0x0,
0x0,
0x0,
0x1,
- 0x8,
+ 0x3,
0x0,
0x0,
0x1,
+ 0x2,
0x1,
- 0xa,
- 0x0,
+ 0xb,
0x7,
- 0x1,
- 0x1,
- 0x0,
0x0,
+ 0x3,
+ 0x5,
0x0,
0x0,
0x0,
0x0,
- 0x7,
- 0x0,
0x0,
0x0,
0x1,
- 0x4,
+ 0x0,
0x2,
+ 0xa,
+ 0xa,
+ 0x5,
+ 0x1,
0x0,
0x0,
0x0,
- 0x4,
+ 0x2,
0x1,
- 0x4,
+ 0x9,
0x0,
0x2,
- 0x4,
- 0x5,
+ 0xb,
+ 0x2,
0x0,
0x0,
0x0,
0x0,
0x8,
0x1,
- 0x2,
- 0xe,
- 0xa,
+ 0xc,
+ 0xc,
+ 0x4,
0x0,
0x1,
- 0x1,
- 0x1,
- 0x2,
0x4,
- 0x2,
+ 0x3,
+ 0x4,
+ 0x3,
+ 0x1,
+ 0x7,
0x5,
+ 0x2,
0x4,
- 0x0,
- 0x8,
- 0x14,
+ 0x1,
0x1,
0x2,
0x0,
0x0,
- 0x5,
+ 0x8,
0x1,
0x0,
0x0,
0x0,
0x1,
+ 0x2,
0x1,
+ 0x2,
0x0,
- 0x6,
- 0x0,
- 0x4,
- 0x0,
+ 0xc,
+ 0x5,
0x1,
0x0,
0x2,
- 0xa,
- 0x17,
- 0x3,
+ 0x2,
0x6,
- 0x4,
0x0,
+ 0x1,
+ 0x2,
+ 0x2,
0x0,
0x0,
+ 0x6,
+ 0x2,
+ 0x7,
0x1,
0x0,
- 0x1,
0x0,
+ 0x5,
+ 0x1,
+ 0xa,
0x0,
- 0x8,
- 0x2,
0x2,
0x0,
0x1,
0x0,
- 0x2,
- 0x0,
0x0,
0x1,
- 0x9,
- 0x6,
+ 0x1,
+ 0xc,
0x0,
0x3,
0x2,
- 0x0,
+ 0x9,
0x0,
0x2,
- 0x2,
+ 0x3,
0x0,
0x1,
- 0x8,
- 0x6,
0x1,
- 0x7,
+ 0x5,
0x4,
- 0x2,
0x7,
- 0x5,
- 0x8,
- 0x5,
- 0x0,
- 0x8,
- 0x0,
+ 0x1,
0x1,
0x1,
0x2,
- 0x7,
0x1,
+ 0x3,
+ 0x3,
+ 0x0,
0x1,
- 0x8,
+ 0x3,
0x0,
0x2,
+ 0x2,
0x0,
+ 0x1,
0x6,
+ 0x1,
+ 0xa,
0x0,
- 0xb,
0x0,
- 0x2,
+ 0x8,
+ 0x0,
0x5,
0x0,
+ 0x1,
+ 0x2,
0x0,
0x0,
- 0x4,
0x0,
- 0x8,
+ 0x7,
+ 0x0,
+ 0x2,
0x0,
0x0,
0x0,
0x0,
0x0,
- 0x1,
- 0x14,
- 0x9,
- 0x10,
- 0xa,
0x2,
+ 0x10,
+ 0x7,
+ 0x1,
+ 0x5,
+ 0xe,
0x0,
0x0,
0x0,
- 0xc,
- 0x3,
+ 0x5,
+ 0x7,
+ 0x5,
0x1,
- 0x3,
0x0,
- 0x1,
- 0x16,
+ 0x4,
+ 0x0,
0x5,
- 0x9,
- 0x1,
- 0xa,
- 0x1,
+ 0x3,
+ 0x2,
0x0,
0x1,
0x0,
0x0,
- 0x3,
- 0x3,
- 0xd,
+ 0x9,
0x0,
+ 0x4,
+ 0x2,
+ 0x3,
0x6,
- 0x1,
+ 0x5,
0x0,
0x1,
+ 0x1,
+ 0x1,
+ 0x3,
+ 0x2,
+ 0x4,
+ 0x2,
0x2,
- 0x6,
0x2,
- 0x9,
- 0x9,
- 0xf,
- 0x0,
- 0x0,
- 0xd,
- 0x1,
0x0,
0x3,
- 0x4,
+ 0x6,
0x0,
0x1,
0x1,
0x0,
- 0x0,
- 0x1,
- 0x1,
0x1,
+ 0x2,
+ 0x14,
+ 0x0,
0x0,
0x7,
+ 0x5,
+ 0x2,
+ 0x0,
+ 0x1,
0x0,
0x0,
0x0,
0x1,
+ 0x6,
+ 0xb,
+ 0x5,
0x0,
- 0xc,
- 0x8,
+ 0xf,
+ 0x1,
0x0,
- 0x5,
+ 0x6,
+ 0x9,
+ 0x1,
+ 0x7,
0x2,
0x0,
- 0x4,
- 0x2,
0x1,
- 0x3,
- 0xb,
- 0x0,
- 0x3,
- 0x4,
+ 0x1,
0x0,
0x0,
0x1,
0x1,
+ 0x1,
0x5,
0x7,
- 0x7,
0x0,
0x0,
0x0,
- 0x3,
0x0,
- 0x5,
- 0x5,
+ 0x6,
+ 0x6,
0x0,
- 0x1,
0x7,
0x0,
- 0x0,
0x1,
+ 0x0,
+ 0x0,
0x3,
+ 0x8,
+ 0x0,
0x0,
- 0x4,
0x1,
- 0xe,
0x1,
- 0x4,
+ 0x6,
+ 0xb,
+ 0x7,
0x0,
0x0,
- 0xa,
+ 0x3,
0x0,
0x1,
- 0x2,
- 0x3,
+ 0x8,
0x1,
- 0x7,
0x1,
+ 0x5,
+ 0x2,
0x1,
- 0x4,
- 0x7,
- 0x0,
0x2,
- 0x0,
- 0x0,
- 0xc,
+ 0xa,
0x0,
0x1,
- 0x1,
0x0,
0x0,
+ 0x3,
0x0,
- 0xe,
- 0x9,
- 0x2,
- 0x6,
0x2,
0x2,
- 0x1,
- 0x1,
- 0x2,
0x0,
- 0x8,
- 0xb,
+ 0x0,
0x0,
0x0,
0x1,
- 0x2,
0x3,
- 0x1,
+ 0x6,
0x2,
0x0,
- 0x5,
- 0x6,
0x2,
0x1,
- 0x1,
0x4,
0x1,
+ 0x2,
+ 0x2,
0x0,
- 0x3,
0x0,
- 0x5,
- 0x7,
0x1,
- 0x0,
- 0x13,
+ 0x4,
+ 0x2,
0x1,
- 0x3,
- 0x9,
0x1,
0x1,
0x0,
+ 0x2,
0x4,
+ 0x3,
+ 0x2,
+ 0x3,
0x1,
0x0,
- 0x5,
0x1,
- 0x5,
- 0x10,
- 0x7,
+ 0x0,
+ 0x0,
+ 0x4,
0x0,
0x3,
- 0xc,
0x3,
+ 0x0,
+ 0x5,
0x5,
0x1,
+ 0x3,
+ 0x6,
0x0,
+ 0x1,
0x2,
- 0xd,
- 0x4,
0x0,
+ 0xa,
+ 0x3,
+ 0x1,
+ 0x1,
0x2,
- 0x6,
0x0,
0x0,
- 0x9,
+ 0x2,
+ 0x4,
0x3,
+ 0x2,
+ 0x0,
+ 0x2,
+ 0x5,
0x1,
0x0,
+ 0xb,
+ 0xa,
+ 0x0,
+ 0x0,
+ 0x1,
0x3,
0x0,
0x3,
- 0x2,
- 0x2,
0x0,
+ 0x1,
0x0,
+ 0x3,
+ 0x8,
0x2,
- 0x1,
0x0,
0x4,
0x0,
- 0x2,
0x1,
0x0,
+ 0x8,
+ 0x2,
+ 0x0,
+ 0x1,
0x1,
0x1,
0x0,
0x0,
- 0x8,
- 0x6,
+ 0x0,
+ 0x5,
0x3,
- 0x8,
- 0x7,
+ 0x6,
+ 0x2,
+ 0x14,
0x0,
0x1,
0x0,
- 0x1,
+ 0x2,
+ 0x3,
0x3,
0x1,
- 0x2,
+ 0x3,
+ 0x6,
+ 0x8,
0x1,
0x1,
- 0x2,
- 0x3,
- 0x2,
0x1,
0x1,
+ 0x3,
0x8,
- 0x1,
0x0,
0x0,
+ 0x4,
+ 0x6,
0x3,
- 0x1,
- 0x9,
0x0,
0x3,
0x0,
- 0x7,
0x0,
+ 0x9,
+ 0xa,
+ 0x3,
+ 0x3,
0x2,
+ 0x5,
+ 0x7,
0x2,
0x0,
- 0x3,
- 0x1,
- 0x1,
- 0xe,
+ 0xa,
0x1,
0x2,
0x1,
0x1,
- 0x1,
0x0,
0x2,
+ 0x2,
0x0,
- 0x5,
+ 0x1,
+ 0x6,
0x1,
0x0,
- 0xe,
+ 0x0,
+ 0xb,
+ 0x3,
0x2,
+ 0x3,
0x0,
0x0,
- 0x3,
- 0x6,
- 0x1,
- 0x6,
0x0,
+ 0x6,
0x0,
- 0x1,
- 0x1,
- 0x3,
+ 0x2,
0x12,
0x1,
0x0,
0x0,
- 0x3,
+ 0x2,
0x0,
0x0,
0x0,
@@ -29891,219 +30122,223 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x6,
- 0x6,
+ 0x1,
0x0,
0x0,
- 0x1,
+ 0x2,
+ 0x0,
0x3,
- 0x9,
- 0x1,
+ 0x4,
+ 0x0,
0x0,
0x0,
0x1,
+ 0xf,
0x3,
- 0x5,
- 0xc,
0x2,
+ 0xe,
+ 0x9,
0x0,
- 0x7,
+ 0x1,
+ 0x6,
0x0,
0x1,
- 0x3,
0x0,
- 0x4,
0x0,
+ 0x1,
+ 0x3,
0x0,
- 0x2,
- 0x5,
0x0,
+ 0x7,
+ 0x5,
0x0,
0x3,
0x0,
- 0x1,
0x0,
+ 0xc,
0x0,
+ 0x3,
0x0,
- 0x7,
- 0x8,
0x4,
- 0x9,
- 0x1,
+ 0x6,
+ 0x5,
0x1,
- 0x2,
+ 0x0,
+ 0x3,
0x0,
0x1,
+ 0x4,
+ 0x3,
0x0,
+ 0x3,
0x4,
- 0x1,
0x0,
0x3,
0x0,
- 0x12,
- 0x6,
- 0x2,
- 0xa,
0x0,
- 0x7,
+ 0x1,
0x0,
- 0x2,
+ 0x6,
0x0,
- 0x5,
+ 0x6,
0x0,
0x2,
0x0,
+ 0x2,
+ 0x3,
+ 0x3,
0x5,
- 0x7,
- 0x1,
0x1,
- 0x9,
- 0x3,
0x0,
0x5,
+ 0x5,
+ 0x3,
0x1,
0x1,
- 0x2,
- 0x6,
- 0x2,
- 0x3,
+ 0x1,
+ 0x1,
+ 0x4,
0x0,
0x0,
0x0,
+ 0x4,
0x1,
- 0x0,
0x1,
0x2,
- 0x5,
+ 0x0,
0x1,
+ 0x7,
0x0,
+ 0x2,
0x0,
- 0x12,
0x0,
0x1,
0x0,
0x0,
- 0x1,
+ 0x3,
0x0,
0x0,
0x1,
0x2,
0x0,
- 0x0,
0x1,
- 0x3,
0x1,
+ 0x3,
0x0,
- 0xb,
- 0x1,
- 0x1,
- 0x9,
+ 0x0,
+ 0x4,
0x2,
+ 0x5,
0x1,
+ 0x2,
+ 0x3,
0x0,
- 0x7,
0x3,
+ 0x1,
0x0,
0x0,
0x1,
- 0x2,
- 0x2,
- 0x3,
+ 0x6,
+ 0x1,
+ 0x1,
0x0,
0x0,
0x3,
- 0x2,
+ 0x5,
0x0,
0x0,
- 0x2,
0x0,
- 0xb,
+ 0x1,
+ 0x3,
0x0,
- 0x4,
+ 0x11,
0x0,
- 0xe,
- 0x6,
+ 0x2,
+ 0x5,
+ 0x1,
0x9,
0x1,
0x0,
- 0x0,
- 0x4,
+ 0x5,
+ 0x3,
0x2,
+ 0x1,
0x0,
- 0x5,
0x0,
+ 0x6,
0x0,
- 0x1,
+ 0x4,
0x0,
- 0x8,
- 0x1,
+ 0x2,
0x1,
- 0x5,
0x0,
0x0,
0x0,
- 0x6,
0x0,
+ 0x8,
0x0,
- 0x1,
0x0,
- 0x2,
0x1,
0x0,
- 0x2,
- 0x6,
+ 0x7,
+ 0x1,
0x0,
0x1,
+ 0x5,
0x0,
+ 0x1,
0x6,
+ 0x2,
0x3,
- 0x1,
0x5,
- 0x2,
- 0x1,
- 0x1,
0x4,
- 0x6,
0x2,
- 0xb,
0x1,
- 0x0,
- 0x2,
+ 0x1,
+ 0x7,
0x3,
0x2,
+ 0x3,
0x1,
0x0,
0x2,
- 0x9,
+ 0x8,
+ 0x4,
0x1,
0x0,
- 0x0,
0x1,
- 0x0,
- 0x0,
0x1,
- 0x0,
+ 0x2,
0x0,
0x0,
0x1,
+ 0x2,
+ 0x0,
0x1,
- 0x7,
+ 0x3,
0x0,
- 0x4,
+ 0x0,
+ 0xb,
0x2,
- 0x3,
+ 0x2,
+ 0xf,
0x0,
0x2,
+ 0x1,
0x0,
0x0,
+ 0x5,
+ 0x0,
+ 0x2,
0x1,
0x0,
0x0,
0x0,
0x1,
- 0x1,
0x2,
- 0x1,
- 0x5,
+ 0x0,
+ 0x3,
+ 0x2,
0x0,
0x0,
0x1,
@@ -30111,204 +30346,207 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x3,
- 0x0,
- 0x9,
- 0x5,
0x2,
- 0x1,
- 0x1,
0x0,
- 0x2,
- 0x1,
- 0x8,
- 0x1,
+ 0x6,
0x2,
0x2,
+ 0x3,
0x1,
+ 0xc,
0x0,
+ 0x1,
+ 0x6,
0x2,
0x3,
+ 0x2,
0x1,
- 0x0,
+ 0x2,
0x1,
0x3,
+ 0x2,
+ 0x3,
0x1,
- 0x0,
- 0x1,
+ 0x2,
0x1,
0x0,
+ 0x4,
+ 0x5,
0x0,
0x0,
- 0x3,
0x0,
0x1,
+ 0x0,
+ 0x3,
0x4,
- 0x5,
- 0x1,
- 0x4,
+ 0x2,
+ 0xb,
+ 0x0,
+ 0x2,
0x0,
0x0,
0x0,
- 0x2,
- 0x8,
0x1,
- 0x4,
0x0,
- 0x2,
+ 0x1,
+ 0x4,
0x2,
0x5,
0x2,
- 0x3,
+ 0x7,
+ 0x0,
+ 0x1,
0x0,
0x0,
0x0,
0x1,
0x0,
- 0x5,
0x6,
0x0,
- 0x2,
- 0x2,
- 0x0,
0x0,
0x1,
+ 0x4,
0x0,
0x0,
- 0x1,
0x2,
- 0x9,
0x0,
- 0x1,
- 0x2,
0x0,
- 0x3,
- 0x4,
+ 0x5,
+ 0x6,
0x1,
- 0x4,
+ 0x0,
0x1,
+ 0x5,
+ 0x0,
0x0,
0x4,
0x2,
0x3,
- 0x4,
- 0x2,
0x1,
+ 0x0,
+ 0xa,
+ 0x3,
+ 0xa,
+ 0x2,
0x2,
0x1,
0x1,
- 0x4,
- 0x5,
- 0x4,
- 0x0,
+ 0x2,
0x2,
0x3,
+ 0x4,
0x2,
- 0x0,
+ 0x1,
0x0,
0x2,
- 0x6,
+ 0x1,
+ 0x7,
0x0,
- 0x2,
+ 0x3,
+ 0x1,
0x1,
0x0,
+ 0x2,
+ 0x4,
0x1,
0x0,
0x0,
- 0x1,
- 0x9,
+ 0x2,
+ 0x6,
+ 0x3,
0x0,
0x1,
0x0,
0x3,
+ 0xa,
0x1,
- 0x0,
- 0x0,
- 0x2,
- 0x2,
+ 0x6,
0x2,
0x0,
+ 0x3,
0x0,
0x0,
- 0x4,
- 0x5,
0x0,
+ 0x6,
0x3,
+ 0x0,
0x2,
- 0x2,
+ 0x6,
+ 0x3,
0x4,
0x0,
- 0x1,
- 0x0,
- 0x3,
+ 0xa,
0x0,
- 0x5,
+ 0x2,
0x0,
+ 0x4,
0x0,
- 0x6,
- 0x1,
0x0,
+ 0x4,
0x3,
+ 0x2,
+ 0x2,
0x0,
- 0x1,
- 0x0,
- 0x6,
+ 0x8,
0x1,
0x4,
+ 0x4,
+ 0x1,
0x1,
0x1,
- 0x2,
0x1,
0x2,
+ 0x1,
0x0,
+ 0x1,
0x2,
- 0x2,
- 0x0,
+ 0x1,
0x0,
0x0,
0x3,
0x0,
- 0x5,
- 0x2,
0x0,
+ 0x5,
0x1,
+ 0x0,
+ 0xa,
+ 0x6,
0x1,
0x2,
- 0x0,
+ 0x4,
0x2,
0x1,
0x1,
+ 0x0,
+ 0x5,
0x1,
+ 0x3,
+ 0x3,
+ 0x0,
+ 0x0,
0x1,
- 0x1,
- 0x1,
- 0xa,
+ 0x6,
0x5,
- 0x1,
+ 0xc,
+ 0x0,
0x0,
+ 0xa,
+ 0x1,
0x1,
0x1,
- 0x4,
- 0x5,
0x0,
0x0,
0x2,
+ 0x0,
+ 0x4,
0x1,
0x2,
- 0x4,
- 0x0,
+ 0x3,
0x2,
+ 0x4,
0x0,
- 0x0,
- 0x3,
- 0x1,
0x1,
0x1,
- 0x1,
- 0x4,
- 0x0,
- 0x2,
- 0x0,
0x0,
0x0,
0x0,
@@ -30319,22 +30557,23 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x1,
+ 0x0,
+ 0x2,
0x0,
0x0,
0x4,
- 0x4,
+ 0x0,
0x0,
0x0,
0x0,
0x3,
0x0,
0x0,
+ 0x2,
+ 0x2,
0x7,
- 0x0,
- 0x1,
- 0x1,
0x1,
+ 0x4,
0x2,
0x1,
0x0,
@@ -30344,70 +30583,71 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x5,
0x2,
- 0x4,
+ 0x1,
+ 0x0,
+ 0x1,
+ 0xa,
0x0,
- 0x2,
- 0x5,
0x0,
0x0,
- 0x1,
- 0x1,
0x1,
0x2,
- 0x7,
+ 0x2,
+ 0x1,
0x0,
0x0,
+ 0x2,
0x1,
- 0x1,
- 0x0,
0x0,
0x0,
- 0x6,
- 0x7,
- 0x5,
- 0xf,
- 0x2,
0x0,
+ 0x4,
+ 0x4,
0x1,
- 0x1,
- 0x3,
- 0x0,
+ 0x4,
+ 0x4,
0x0,
0x1,
- 0x2,
0x1,
0x0,
0x3,
+ 0x0,
+ 0x4,
+ 0x3,
0x1,
+ 0x0,
+ 0x6,
0x1,
- 0x3,
+ 0x0,
0x1,
+ 0x0,
+ 0x2,
0x1,
0x3,
0x0,
0x0,
- 0x4,
- 0x2,
+ 0x3,
+ 0x3,
0x0,
0x1,
+ 0x2,
+ 0x2,
0x1,
- 0x1,
- 0x6,
- 0x1,
+ 0x3,
0x0,
- 0x4,
+ 0x1,
0x0,
- 0x4,
- 0x4,
+ 0xb,
+ 0x7,
0x0,
- 0x2,
0x1,
0x5,
+ 0x1,
0x0,
0x0,
- 0x2,
+ 0x9,
0x1,
- 0x2,
+ 0x3,
0x0,
0x0,
0x0,
@@ -30415,165 +30655,168 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x1,
0x0,
0x0,
- 0x3,
- 0x0,
- 0x0,
+ 0xe,
0x2,
- 0x8,
- 0x1,
+ 0x0,
+ 0x4,
0x3,
+ 0x1,
+ 0x6,
0x0,
0x0,
- 0x3,
+ 0x4,
0x0,
- 0x6,
+ 0x5,
+ 0x3,
0x1,
- 0x4,
- 0x2,
- 0x6,
+ 0x0,
0x2,
0x1,
- 0x2,
+ 0x0,
+ 0x1,
0x1,
- 0x2,
0x3,
- 0x7,
0x1,
- 0x6,
+ 0x0,
+ 0x1,
+ 0x5,
0x1,
+ 0x2,
0x1,
0x0,
+ 0x1,
0x0,
+ 0x2,
0x1,
- 0x3,
- 0x3,
0x1,
- 0x9,
+ 0x7,
0x1,
- 0x3,
- 0x8,
- 0x0,
- 0x2,
0x1,
0x2,
+ 0x6,
+ 0x4,
0x2,
+ 0x3,
+ 0x1,
0x1,
- 0x6,
- 0x0,
0x1,
0x0,
- 0x2,
0x1,
+ 0x0,
0x1,
0x2,
- 0x2,
+ 0x1,
+ 0x3,
0x0,
0x1,
+ 0x5,
0x0,
- 0x4,
0x0,
- 0x2,
0x6,
- 0x3,
+ 0x2,
+ 0x2,
+ 0x1,
0x0,
0x2,
0x1,
- 0x5,
- 0x7,
+ 0x1,
+ 0x1,
0x2,
0x4,
0x2,
0x0,
0x0,
0x0,
- 0x1,
0x0,
- 0x8,
+ 0x1,
0x3,
- 0x5,
- 0x0,
0x2,
+ 0x0,
+ 0x4,
0x1,
+ 0x4,
+ 0x2,
0x0,
0x0,
+ 0x3,
+ 0x0,
0x2,
- 0x6,
- 0x1,
- 0x1,
- 0x1,
+ 0x0,
0x3,
+ 0x0,
0x1,
0x0,
0x1,
- 0x2,
+ 0x1,
0x0,
0x0,
0x5,
+ 0x3,
0x1,
0x1,
0x1,
- 0x1,
- 0x0,
0x0,
0x1,
- 0x0,
0x2,
- 0x3,
+ 0x0,
+ 0x7,
+ 0x4,
0x0,
0x1,
0x1,
0x0,
- 0x5,
- 0x0,
- 0x4,
- 0x2,
+ 0x1,
0x0,
- 0x3,
0x5,
- 0x0,
- 0x0,
0x1,
0x0,
0x1,
- 0x1,
- 0x2,
0x0,
0x2,
- 0x1,
- 0x1,
+ 0x0,
0x1,
0x2,
- 0x0,
+ 0x2,
0x2,
0x1,
- 0x0,
- 0x4,
0x2,
- 0x0,
- 0x0,
+ 0x5,
0x2,
0x1,
0x1,
0x3,
0x0,
+ 0x3,
+ 0x1,
+ 0x0,
0x2,
+ 0x3,
+ 0x6,
+ 0x0,
+ 0x3,
0x2,
- 0x1,
0x0,
- 0x1,
0x5,
0x0,
- 0x0,
0x4,
+ 0x4,
+ 0x3,
+ 0x1,
0x0,
+ 0x2,
+ 0x8,
0x0,
+ 0x3,
0x0,
- 0x1,
0x0,
- 0x4,
- 0x2,
+ 0x0,
+ 0x0,
+ 0x3,
+ 0x0,
0x2,
0x2,
+ 0x1,
+ 0x1,
0x0,
0x3,
0x0,
@@ -30582,133 +30825,135 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x0,
- 0x5,
+ 0x1,
0x3,
- 0x8,
- 0x0,
- 0x7,
+ 0x1,
+ 0x4,
+ 0x1,
0x2,
0x2,
- 0x1,
0x2,
0x2,
+ 0x0,
+ 0x2,
0x4,
- 0x9,
0x1,
- 0x0,
- 0x0,
0x1,
0x0,
- 0x5,
0x2,
0x0,
- 0x1,
0x0,
0x2,
+ 0x4,
+ 0x4,
0x1,
+ 0x2,
0x0,
- 0x4,
+ 0x1,
0x2,
0x1,
- 0x9,
- 0x6,
+ 0x4,
0x2,
0x3,
- 0x2,
0x6,
0x0,
+ 0x1,
+ 0x5,
+ 0x0,
+ 0x0,
0x0,
0x0,
0x0,
0x2,
- 0x1,
0x2,
+ 0x1,
0x0,
0x0,
0x0,
- 0x1,
+ 0x2,
+ 0x2,
0x4,
- 0x1,
0x0,
0x0,
0x0,
0x4,
- 0xc,
- 0x0,
0x3,
- 0x2,
- 0x4,
- 0x0,
- 0x0,
0x1,
- 0x0,
- 0x0,
+ 0x1,
+ 0x9,
0x1,
0x0,
0x0,
+ 0x3,
+ 0x0,
0x0,
- 0x1,
0x2,
+ 0x1,
0x0,
- 0x8,
0x0,
0x1,
- 0x2,
0x3,
0x0,
- 0x0,
- 0x1,
- 0x4,
0x1,
+ 0x0,
0x2,
- 0x1,
0x2,
0x1,
+ 0x0,
+ 0x0,
0x1,
- 0x1,
- 0x1,
+ 0x3,
0x2,
- 0x1,
0x2,
0x0,
- 0x0,
0x1,
0x1,
0x0,
+ 0x2,
0x1,
+ 0x5,
0x2,
+ 0x4,
+ 0x1,
+ 0x0,
0x2,
+ 0x0,
0x8,
- 0x1,
+ 0x0,
0x3,
0x1,
+ 0x3,
0x1,
+ 0x2,
0x1,
0x1,
- 0x4,
- 0x3,
0x2,
- 0x0,
0x1,
0x1,
+ 0x3,
+ 0x3,
+ 0x1,
+ 0x0,
+ 0x3,
0x1,
0x2,
+ 0x2,
0x1,
0x0,
+ 0x0,
0x1,
- 0x1,
- 0x3,
+ 0x4,
+ 0x0,
+ 0x2,
0x0,
- 0x7,
0x0,
0x0,
- 0x7,
0x1,
+ 0x3,
0x1,
- 0x2,
0x0,
+ 0x1,
0x3,
- 0x0,
0x1,
0x0,
0x2,
@@ -30721,6 +30966,7 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x0,
+ 0x0,
0x1,
0x0,
0x0,
@@ -30733,18 +30979,18 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x1,
- 0x3,
+ 0x5,
0x2,
0x0,
0x0,
- 0x0,
+ 0x1,
0x2,
+ 0x8,
0x0,
- 0x3,
0x0,
0x1,
0x0,
- 0x1,
+ 0x11,
0x1,
0x0,
0x0,
@@ -30755,2523 +31001,2567 @@ pub(crate) const COMBINING_MARK_SALT: &[u16] = &[
0x0,
0x0,
0x2,
- 0x3,
- 0x0,
- 0x0,
- 0x0,
- 0x0,
0x1,
0x0,
- 0x4,
- 0x2,
0x0,
- 0x1,
- 0x8,
0x0,
0x0,
- 0x3,
- 0x7,
+ 0x1,
0x0,
0x1,
0x1,
0x0,
0x1,
0x5,
- 0x1,
- 0x4,
0x0,
0x0,
- 0x0,
- 0x3,
- 0x5,
+ 0x6,
0x3,
0x0,
0x2,
0x2,
0x1,
- 0x3,
- 0x1,
0x1,
- 0x3,
0x5,
0x3,
- 0x5,
+ 0x2,
+ 0x2,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x2,
+ 0x0,
+ 0x1,
+ 0x4,
0x1,
0x2,
+ 0x2,
0x0,
0x1,
- 0x7,
0x2,
- 0x3,
- 0xc,
- 0x8,
0x2,
0x1,
0x1,
- 0x0,
- 0x5,
- 0x3,
- 0x0,
+ 0xa,
+ 0x1,
0x1,
0x0,
0x2,
- 0x0,
- 0x3,
+ 0x2,
+ 0x1,
+ 0x4,
+ 0x6,
+ 0x1,
+ 0x1,
+ 0x1,
0x1,
0x0,
0x4,
0x1,
+ 0x0,
0x1,
0x0,
- 0x9,
0x0,
+ 0x2,
+ 0xb,
0x1,
+ 0x8,
0x1,
0x1,
- 0x2,
0x1,
0x0,
0x1,
+ 0x0,
+ 0x5,
+ 0x0,
0x3,
+ 0xf,
+ 0x1,
+ 0x1,
0x0,
0x1,
+ 0x2,
+ 0x1,
0x0,
0x1,
0x1,
0x1,
- 0x0,
0x1,
- 0x0,
+ 0x1,
+ 0x2,
+ 0x8,
0x1,
0x1,
- 0x4,
0x0,
0x1,
0x1,
0x1,
0x0,
0x0,
+ 0x0,
0x1,
0x1,
- 0x4,
+ 0x0,
0x1,
0x0,
0x2,
0x0,
0x0,
0x0,
- 0x1,
0x2,
+ 0x1,
0x0,
0x1,
- 0x2,
+ 0x3,
0x0,
];
pub(crate) const COMBINING_MARK_KV: &[u32] = &[
- 0x0f9c,
+ 0xe01cb,
0x115dd,
- 0x09fe,
- 0x0d83,
- 0x0d48,
- 0x1da10,
- 0x0ac1,
- 0x08fb,
+ 0x0e3a,
+ 0x11441,
+ 0xe0134,
+ 0x11cb1,
+ 0x115bd,
+ 0x0faf,
0xe01dc,
- 0x0368,
- 0xe018b,
- 0x0315,
- 0x1cf7,
+ 0x11181,
+ 0x11934,
+ 0x11374,
+ 0x0823,
0xa67c,
- 0x1c36,
- 0x0b42,
- 0x1da3f,
+ 0x0a4d,
+ 0xa952,
+ 0x1e003,
0x0e49,
- 0xe0119,
- 0x1c27,
- 0x0593,
- 0xa981,
+ 0x17b5,
+ 0x1074,
+ 0x2dfe,
+ 0xa8be,
+ 0x101fd,
0x102e0,
- 0xa9b5,
- 0x102f,
- 0x1e021,
- 0xaa2f,
- 0x0fa2,
- 0xe015e,
- 0x1a63,
- 0x06e3,
- 0x0308,
- 0x0f79,
- 0x1ba4,
- 0x112e7,
- 0x16f70,
- 0x1bf3,
+ 0x0fb1,
+ 0xa9ba,
+ 0x0c00,
+ 0x1daa6,
+ 0x05a2,
+ 0xfe26,
+ 0x0a41,
+ 0x07a6,
+ 0x0898,
+ 0x0b82,
+ 0x0afb,
+ 0x0fbb,
+ 0x1a7a,
+ 0x1cf1a,
0x16f6b,
- 0x1e00a,
0xa675,
- 0x1136a,
- 0xfe0e,
- 0x11ef3,
- 0x1d243,
- 0x11a97,
- 0xa806,
- 0x1daae,
- 0x11831,
+ 0x1cf45,
+ 0xe012f,
+ 0xe014f,
+ 0x11c3b,
+ 0x2df7,
+ 0xa9bf,
+ 0xa8eb,
+ 0x1bc9e,
0x1a74,
- 0x1cf10,
- 0x111b7,
- 0x1925,
+ 0x0eb8,
+ 0x302c,
+ 0x0c4d,
+ 0x064f,
0x105e,
- 0xe0112,
- 0x0656,
- 0x1e006,
+ 0x0741,
+ 0x1da44,
+ 0x0b44,
0x1924,
- 0x0f80,
+ 0x1da1d,
0x09c0,
0xfe2d,
- 0xe015c,
- 0x0a4b,
- 0x11146,
+ 0x0330,
+ 0xe01c3,
+ 0x109d,
+ 0x0322,
0x1cf18,
- 0x0c56,
- 0x0346,
- 0x1e023,
- 0xe017d,
+ 0x0c02,
+ 0xe0128,
+ 0x17cb,
0x1acb,
- 0x1da19,
+ 0xe01e3,
0xa802,
- 0x1d242,
+ 0x16f72,
+ 0x11001,
0x11634,
- 0x1da84,
+ 0x1da9b,
0x08ce,
0x0eb7,
- 0x17dd,
+ 0x11041,
0x1a7b,
- 0x0b4d,
0x1057,
+ 0xe0150,
0x1b6d,
- 0x0fa9,
+ 0x0ce2,
0xa8e6,
- 0x103b,
+ 0x1103e,
0x0619,
- 0x073a,
- 0x030d,
- 0x1daa7,
- 0x1cf04,
- 0x112df,
- 0x0f7a,
+ 0x11081,
+ 0x0fa3,
+ 0x114c3,
+ 0x11a90,
+ 0x082c,
+ 0x11173,
0x1a66,
- 0x0f78,
- 0x065d,
+ 0x1e8d4,
+ 0x1d16e,
0x111b8,
- 0x115af,
- 0xa92a,
- 0x0982,
+ 0x1934,
+ 0x1cf0c,
+ 0xe01ce,
0x1cf39,
- 0x115b5,
0x111be,
- 0xa8b6,
+ 0xe01d2,
+ 0x1da08,
0xe0141,
0x11236,
- 0x11180,
- 0x1d165,
- 0x0741,
+ 0x110c2,
+ 0xfe25,
+ 0x16b36,
0x0657,
0x0749,
- 0x0486,
- 0x114bd,
- 0x1a75,
- 0x08de,
+ 0x0311,
+ 0xe01c4,
+ 0x20d3,
+ 0x1da21,
0x1be9,
- 0x07f1,
- 0x1e02a,
+ 0x1cf0e,
+ 0x16f5d,
0x1d182,
- 0x1dea,
- 0x0822,
+ 0x1cf41,
+ 0x08fe,
0xfe05,
- 0xa8ec,
- 0x1036,
- 0x115ba,
- 0x1ba1,
- 0x116b0,
+ 0x11a59,
+ 0x1de6,
+ 0x1ac6,
+ 0xe0120,
+ 0x11a38,
0x110b7,
0x1dec,
- 0x11a8f,
- 0x1e8d1,
- 0xaa2b,
- 0x0f8e,
- 0x1cf03,
- 0x1dc7,
+ 0x0351,
+ 0x0309,
+ 0x1dcd,
+ 0x115bc,
+ 0x114b5,
+ 0x16f80,
0x11182,
- 0x2de9,
+ 0x16f6e,
0x11caa,
0xe0198,
0x0dd8,
- 0x10a39,
+ 0xa80b,
0x0eca,
- 0x0363,
+ 0x1df0,
0xa8c5,
0x0fbc,
- 0x0a4d,
+ 0x1136c,
+ 0x1064,
0x1c29,
- 0xa8e2,
- 0x0fb4,
- 0x1ab9,
+ 0x114c0,
+ 0x1030,
0x1abd,
- 0x11935,
- 0x102d,
- 0x1acc,
- 0x0654,
+ 0x0e4c,
+ 0x0a02,
+ 0x1143d,
+ 0x1e4ed,
+ 0x20d8,
0x11a04,
0x1cf26,
0xe0116,
0x0acc,
0x10f4d,
0xaaed,
- 0xe012e,
- 0x17cc,
- 0x0825,
- 0xabe4,
+ 0x07aa,
+ 0x0902,
+ 0x11442,
+ 0xe012c,
0x0ac7,
- 0xe0122,
- 0x0615,
- 0x16f72,
- 0xe01c7,
- 0x110b3,
- 0x0820,
+ 0xaabe,
+ 0x1921,
+ 0x11c9c,
+ 0x11f3e,
+ 0x11102,
+ 0x0953,
0x1da5b,
- 0x180f,
+ 0xa8e9,
0x11044,
- 0x1cf45,
+ 0x16b33,
0x08e3,
0xe0158,
0xa826,
- 0x2de4,
- 0x06d6,
- 0x1dd3,
- 0x0f37,
- 0xe0139,
- 0xe0113,
- 0x1a71,
+ 0x11f41,
+ 0x0f19,
+ 0x1058,
+ 0xe01ef,
+ 0xe011d,
+ 0x17bb,
+ 0x1171f,
0x11232,
+ 0x1cd7,
0x0364,
- 0xe016d,
- 0x0c81,
+ 0x1c35,
0x0a3f,
- 0xfe0a,
- 0xe01bf,
- 0xaab7,
- 0x11937,
- 0x1e131,
+ 0x1a5a,
+ 0x13453,
+ 0x11a55,
+ 0x1def,
+ 0x0342,
+ 0x0b4c,
0xe01ea,
- 0x05bc,
- 0xe0149,
+ 0x1cf32,
0x1082,
- 0xfe08,
- 0x11357,
+ 0x0b63,
+ 0x1ac5,
0x11635,
- 0x1da30,
+ 0x1a69,
+ 0x0487,
0xe0164,
- 0x1a67,
0x1da33,
- 0x1ab1,
- 0x11c39,
+ 0xe0107,
+ 0x0bc0,
0x11c3e,
- 0x0e3a,
- 0xabe7,
+ 0xe01c1,
+ 0x1daae,
+ 0x0fa1,
0x11c95,
- 0x11233,
- 0xa8ee,
- 0xaa2e,
+ 0xa671,
+ 0x1c36,
+ 0x1b71,
0x1b80,
- 0x11a59,
- 0xfe04,
- 0xe01c2,
- 0x1da34,
+ 0x033c,
+ 0x20d5,
+ 0x116ae,
0x1da54,
- 0x10f4b,
+ 0x0819,
+ 0x1e01f,
0x0301,
- 0x16b30,
- 0x11a91,
- 0x16af3,
+ 0x119dc,
+ 0x11726,
+ 0x031c,
0x17b8,
0xe015b,
- 0x0d63,
- 0x112e3,
+ 0x1dd0,
+ 0x0f9e,
0x0f94,
0x0f7f,
0x11d32,
0x11a8b,
0x1dda,
- 0xa9be,
- 0x1cf42,
- 0x119d7,
- 0x1ddd,
+ 0xe017a,
+ 0x116b6,
+ 0x11c9b,
+ 0x0f8e,
0x11720,
- 0x11039,
- 0x081c,
+ 0xaa7d,
+ 0x10f82,
+ 0xa9b6,
0x0744,
- 0xe0140,
- 0x09c1,
- 0x11231,
- 0x110ba,
+ 0x11f01,
+ 0x16f73,
+ 0x11632,
0x0e38,
- 0x110b4,
- 0x119da,
+ 0x0bcc,
+ 0x11f37,
+ 0x07f1,
0x0340,
- 0x0ecb,
+ 0x116b3,
0x11002,
- 0x2dff,
- 0x0331,
+ 0x1e946,
0x1cf1d,
- 0x103d,
+ 0x1da49,
0x1da2e,
- 0x1037,
- 0x1ab6,
- 0x0337,
+ 0x1b3e,
+ 0xe010a,
+ 0x09e2,
0x1cf2d,
- 0x11a90,
- 0x11d3c,
+ 0x0b03,
+ 0x094f,
0x11373,
- 0x1133e,
+ 0x13449,
+ 0x11838,
0xaa36,
- 0x20e4,
+ 0x0ccc,
0xe01b0,
0x07ad,
0x1df1,
0x17cd,
- 0x11237,
+ 0x13455,
0x0ae2,
- 0x11ca5,
- 0x07ef,
- 0x1073,
- 0x11340,
- 0x081d,
- 0xe018f,
- 0x17c7,
- 0x1aba,
- 0x1933,
+ 0x1cf3c,
+ 0x1cf27,
+ 0x16f85,
+ 0x1e00a,
+ 0x11c9f,
+ 0x1d168,
+ 0x119de,
+ 0x11932,
+ 0x1dc0,
0x110b0,
- 0x11a56,
- 0x1da03,
- 0xe01cd,
- 0x0367,
- 0x036d,
+ 0x1e948,
+ 0x1da27,
+ 0x10378,
+ 0x0310,
+ 0x0df2,
0x11038,
- 0x11830,
+ 0x114b4,
0x093a,
0x1ce0,
- 0x1c32,
- 0x0c3f,
- 0x1da50,
+ 0x094c,
+ 0x16f64,
+ 0xa8ec,
0x111bf,
- 0x2df7,
- 0x1cda,
- 0x1ba2,
- 0x0b02,
- 0x0735,
+ 0x11133,
+ 0x1bec,
+ 0x1da35,
+ 0xa94d,
+ 0x1cf00,
0x032f,
- 0xe014c,
+ 0xa928,
0x05c7,
- 0x20de,
- 0x1bee,
- 0x0599,
- 0xe0114,
- 0xa94d,
- 0x11a34,
- 0x0598,
- 0xe01d7,
- 0x081f,
+ 0x1a19,
+ 0x0354,
+ 0x11942,
+ 0x1cf34,
+ 0x07b0,
+ 0x0afa,
+ 0x1c32,
+ 0x1da0d,
+ 0x1cf25,
+ 0x11d8b,
0x116b4,
- 0x1e01c,
- 0x10ae6,
+ 0x1ac7,
0xa9bc,
+ 0x1d18a,
0xfe21,
- 0x20e8,
0xe0183,
- 0x0c62,
+ 0x07ac,
+ 0x13450,
0xe012d,
0x119d6,
- 0x07ae,
+ 0x1de1,
0x0cbe,
- 0x1da44,
- 0x1cf0c,
- 0x089e,
- 0x1a7c,
+ 0x065b,
+ 0x0316,
+ 0x1a59,
+ 0x1e004,
0xa670,
- 0x11a05,
- 0x06ed,
- 0x1cf1b,
- 0x20d7,
- 0x16f5a,
+ 0x1da4b,
+ 0x17dd,
+ 0x1e008,
+ 0xe0191,
0x0f18,
- 0x085b,
- 0x119d2,
- 0x09be,
- 0x11a38,
- 0x17c6,
- 0x0cd6,
- 0x1dee,
- 0x17d3,
- 0x1a1b,
+ 0x1143f,
+ 0xe0190,
+ 0xabe3,
+ 0x1da4d,
+ 0x0cd5,
+ 0x0dda,
+ 0x0d63,
+ 0x0e35,
+ 0x1cf1e,
+ 0x1da1e,
0xe01e8,
- 0xe01ab,
- 0x1ac6,
- 0x2de1,
- 0x17d2,
- 0x11a99,
+ 0x114bf,
+ 0x0746,
+ 0x1cd1,
+ 0x1da75,
+ 0x1e2ec,
0x0596,
- 0x08f1,
- 0x11cb3,
+ 0x1dfa,
+ 0x0334,
+ 0x16f77,
0x09e3,
- 0x0b43,
- 0x0f7c,
+ 0xe019f,
0x17ba,
- 0x1d185,
+ 0x0ac1,
0x1de3,
0x1e130,
+ 0x1ba1,
0xe01a8,
- 0xa8b9,
- 0x1939,
- 0x0f71,
- 0x11728,
- 0x116ae,
+ 0x1ac3,
+ 0x11c38,
+ 0x111b3,
+ 0x0357,
+ 0xe012a,
0x116ac,
- 0x0ce3,
- 0x1c2c,
+ 0x0f76,
0x119e0,
- 0xe0106,
- 0x1b41,
- 0x2df9,
- 0x033e,
+ 0x1a72,
+ 0x0fa2,
+ 0x1772,
+ 0x05b3,
+ 0x1df7,
0x11cb6,
- 0xfe29,
0x1da63,
- 0x1ce6,
+ 0x16f70,
0x1cf8,
- 0x2def,
- 0x1da32,
- 0x16f78,
- 0x0b4c,
- 0xa950,
- 0x0611,
+ 0x0747,
+ 0x112e4,
+ 0x1e8d3,
+ 0xaa31,
+ 0x0cc3,
+ 0xfe0d,
+ 0x11a37,
0x1dcb,
0x0317,
- 0x1928,
+ 0x1dc8,
0x1c2b,
- 0x09cc,
- 0x17c4,
- 0x0f99,
- 0x119d5,
+ 0x0eba,
+ 0x085a,
+ 0x11835,
+ 0x036c,
0x05af,
- 0x108b,
- 0xe01da,
- 0xe01d8,
+ 0x1143b,
+ 0x1da10,
+ 0x11c9e,
0xa8e1,
- 0x11832,
- 0x0591,
+ 0x035c,
+ 0x1b03,
0x0366,
0x05c4,
- 0x10f50,
- 0x1d17d,
- 0x10a05,
+ 0x1cf0d,
+ 0x11a8a,
+ 0xe01c8,
0xe01a9,
0x06e1,
- 0x0319,
- 0x0e31,
- 0x06df,
- 0x20e7,
+ 0xfe24,
+ 0xa926,
+ 0xa824,
+ 0xa92d,
0x111bc,
- 0x081e,
- 0x1072,
- 0x1da75,
+ 0xabea,
+ 0x0afc,
+ 0x1ded,
+ 0x065a,
0x0952,
- 0xe01d0,
- 0x1da27,
- 0x115c0,
- 0x1e009,
- 0x0334,
- 0x11127,
+ 0x1da5d,
+ 0x0956,
+ 0x1ce1,
+ 0x11933,
+ 0x1d167,
0xa69f,
+ 0x0d3e,
0x110b5,
- 0xe0196,
- 0x11073,
+ 0x116b2,
0x1e017,
- 0x08d2,
+ 0xe013e,
+ 0x1d180,
0x1da67,
0xaaeb,
- 0x0abe,
0x1dd1,
+ 0xaab8,
0x1cf22,
- 0x20dc,
- 0x0ae3,
+ 0x2cf1,
+ 0x06d7,
0x1930,
- 0x20e9,
+ 0x1da34,
0x0326,
0x1032,
- 0x0f76,
- 0xe01ef,
+ 0x1be7,
+ 0x09c4,
0x1da57,
- 0x108a,
- 0x0a48,
+ 0x1136a,
0x1daa1,
- 0x08f9,
- 0x0d3f,
+ 0xe0179,
+ 0x0cc1,
+ 0x11129,
0x10f83,
- 0x11ca4,
- 0x11368,
- 0x05b2,
- 0x0acd,
- 0xa67b,
- 0x11130,
- 0x1da0c,
- 0x11001,
+ 0x1034,
+ 0x0a82,
+ 0xa951,
+ 0x1344b,
+ 0x2d7f,
+ 0x09c7,
+ 0x11f39,
+ 0x11f34,
0x16f5b,
- 0x1bf2,
- 0x0f90,
+ 0x0bbe,
+ 0x031a,
0x11d8e,
- 0x1da11,
- 0xe01db,
- 0x11344,
- 0x1da4f,
- 0x1e00c,
+ 0x1e949,
+ 0x1ab6,
+ 0x1b40,
+ 0x1d16d,
+ 0x0d82,
+ 0x1134c,
0x033f,
- 0x11369,
0x11d3f,
- 0xa928,
- 0xe0142,
+ 0x0dd6,
+ 0x11445,
0x1a58,
- 0x16f65,
- 0x11d93,
- 0x11a36,
- 0x16f80,
- 0x309a,
- 0x036c,
- 0x1a73,
- 0x1112b,
- 0x1a5e,
+ 0x08de,
+ 0x1ac2,
+ 0x1b34,
+ 0x11ef4,
+ 0x11d35,
+ 0xe0195,
+ 0x1c37,
+ 0xa9e5,
+ 0xa980,
+ 0xe0185,
0xe018e,
- 0x119df,
- 0x1dc0,
+ 0xa8ba,
+ 0x193b,
0x1da3b,
- 0xe0187,
- 0x11c93,
- 0x0d4a,
+ 0x094b,
+ 0x10f48,
+ 0x0d3c,
0x1dc9,
- 0x1cf37,
0x11046,
- 0x2df1,
- 0x11633,
+ 0x1926,
+ 0x05b0,
+ 0x0c55,
0x11c3c,
- 0x0304,
0x08e6,
+ 0x0617,
0xe0109,
- 0xe0181,
0x1e134,
0xfe2c,
- 0x1cd8,
- 0x0324,
- 0x081b,
- 0x1da1b,
- 0x16af0,
- 0xaab0,
- 0x05ac,
+ 0xabe6,
+ 0xfe0f,
+ 0x1df6,
+ 0x1ac9,
+ 0x103c,
+ 0x093c,
+ 0xe0154,
+ 0x0ddb,
0x1cf13,
- 0x111cf,
+ 0x114c2,
0x20ea,
- 0x0fa1,
+ 0xe01de,
0x06ec,
- 0x1a77,
- 0x112e1,
- 0x1beb,
+ 0x105f,
+ 0x1d16f,
+ 0xfe27,
0xe01c5,
- 0xe0167,
- 0x16f77,
- 0x0afa,
- 0x1ac7,
+ 0xe0182,
+ 0x05b5,
+ 0xe0104,
+ 0xa9be,
0x1e002,
0x0cbf,
0x1886,
- 0xe0169,
- 0x0fab,
- 0x0a51,
- 0x10a3f,
+ 0x1b82,
+ 0x0fc6,
+ 0x032a,
+ 0x0670,
0x0981,
0x0595,
- 0x05aa,
- 0x06db,
+ 0x08df,
+ 0x08ca,
0x1715,
- 0xa8bc,
+ 0x0b41,
0x0658,
- 0x11a37,
+ 0x1dc2,
0x065c,
- 0x1da46,
+ 0xe0130,
0x1bac,
- 0xe011b,
+ 0x1c24,
+ 0x20de,
0x111bd,
- 0x1133c,
- 0x08f0,
- 0x08cf,
- 0x20d6,
- 0x16f52,
- 0x1ced,
- 0xe0127,
- 0x0d82,
+ 0xa8b4,
+ 0x0486,
+ 0x0302,
+ 0xe0102,
+ 0x1145e,
+ 0x1da3d,
+ 0x1cf11,
0xe0151,
- 0x05bd,
- 0x07a7,
+ 0xe01b4,
+ 0x05b7,
0x1ab4,
- 0x1712,
- 0x11d95,
- 0x0d57,
+ 0x1ba2,
+ 0x1d1ad,
+ 0x1182d,
0x1d18b,
- 0x11d3a,
- 0x0dd9,
- 0x1e014,
- 0x11ef6,
- 0x115bd,
+ 0x17bd,
+ 0x1cf1f,
+ 0x0ac9,
+ 0x11ca7,
+ 0x1deb,
0x1d17b,
- 0xa8e5,
- 0x05a0,
- 0x0fa7,
- 0x089f,
- 0x08fa,
- 0x10ae5,
+ 0x1da68,
+ 0x0ecc,
+ 0x1c30,
+ 0x116b5,
+ 0xa8e7,
+ 0x1112a,
+ 0x11a3d,
0x1136b,
- 0x11181,
- 0x11070,
- 0x16f87,
- 0x1143e,
- 0x0b01,
+ 0x05c5,
+ 0x11363,
+ 0x08f6,
+ 0x1ab0,
+ 0x1163d,
0x0c82,
- 0x1da0b,
+ 0x1cf40,
0x0f3f,
0xe0100,
0x0dd3,
- 0x0fb7,
- 0xe0182,
+ 0x1035,
+ 0x1a76,
+ 0x1daa4,
0x0314,
- 0x0d42,
- 0x08e1,
- 0x0b63,
+ 0x10f46,
+ 0x16f79,
0xe0159,
- 0xaa4d,
- 0x06dc,
- 0x1d166,
- 0xe0155,
- 0x1da26,
+ 0x0f9c,
+ 0xe013c,
+ 0x1183a,
+ 0x1e000,
+ 0x1da41,
+ 0x11a47,
0x0733,
- 0x0d4d,
- 0x16f62,
- 0x108c,
+ 0x1da60,
+ 0x11440,
0x1b72,
0x07af,
+ 0x0f73,
0xa827,
- 0x089d,
- 0x1cde,
- 0x1a79,
+ 0xe01e9,
+ 0x11a96,
0x1e012,
- 0x094f,
- 0x115be,
- 0x10f4c,
+ 0x11830,
+ 0x1da46,
+ 0x2de6,
+ 0x1cdb,
0x0616,
0xfe01,
- 0x115b8,
0x11300,
0x0951,
- 0x1b6e,
- 0x1dcd,
- 0x1e004,
- 0x08d8,
- 0x11631,
+ 0x0abc,
+ 0xaa29,
+ 0x1931,
+ 0x1da17,
+ 0x1a6d,
0x11723,
- 0x1cf16,
- 0xfe2e,
- 0x1c2f,
- 0x064f,
- 0xaaec,
- 0x08d4,
- 0x11c31,
- 0x0bc0,
- 0xe019e,
- 0x11d34,
- 0x0746,
- 0xe01d5,
- 0x11caf,
- 0x0fa8,
- 0x1b44,
- 0x1de8,
+ 0x10f4a,
+ 0xe011e,
+ 0x06e4,
+ 0x0343,
+ 0x1cd2,
+ 0x20d9,
+ 0x1163e,
+ 0x05a8,
+ 0x1122e,
+ 0x1de0,
+ 0x103e,
+ 0x102d,
+ 0x1da0b,
+ 0xaac1,
+ 0x16f7c,
+ 0x20da,
+ 0xa948,
0xa67a,
- 0x1cf2a,
- 0x11000,
- 0xe0103,
- 0x06d7,
- 0x030c,
- 0x1ddf,
- 0x11a3e,
+ 0x1cf23,
+ 0xaa35,
+ 0xa8bc,
+ 0x1da55,
+ 0xe01b3,
+ 0x16f57,
+ 0x10a05,
0x1172a,
+ 0x1a77,
0x116b1,
- 0x1de1,
- 0x11102,
- 0x1d189,
- 0xfe24,
- 0x0983,
- 0xe012a,
- 0x17ce,
+ 0x1dc1,
+ 0x1cf06,
+ 0x0a75,
+ 0x16f75,
+ 0x11d45,
+ 0x1b3c,
+ 0x1037,
0xe01be,
- 0xabea,
- 0x11c34,
- 0x082d,
- 0x1e8d4,
- 0xe0121,
- 0x1baa,
+ 0xe01a5,
+ 0x11833,
+ 0x0954,
+ 0xfe0b,
+ 0x16f6f,
+ 0x10eff,
0x064e,
- 0x1df0,
- 0x05b3,
- 0x0afb,
- 0x08ec,
+ 0x0320,
+ 0x1dcf,
+ 0xfe29,
+ 0x09be,
0x0f35,
- 0x1b35,
+ 0x0cd6,
0x0489,
- 0x08cc,
+ 0x0d4a,
0x17b7,
- 0x2df0,
0x1dfc,
- 0x111b3,
+ 0xabe8,
+ 0x1dce,
0x1b6c,
- 0x0ecc,
- 0xe019a,
- 0x0a41,
- 0x1d16e,
- 0x0d62,
- 0xe010a,
- 0x032d,
- 0x059f,
- 0x1da59,
- 0x1a56,
- 0xe0173,
+ 0x0ddf,
+ 0x16f90,
+ 0x11633,
+ 0x11a94,
+ 0xa94f,
+ 0x11837,
+ 0x0d00,
+ 0x1d171,
+ 0x108b,
+ 0x0732,
+ 0x11a99,
0x1d186,
- 0x11cb4,
+ 0x0303,
0x10377,
- 0x11a3c,
- 0x0fae,
+ 0x114b3,
+ 0x1e015,
0x0f9f,
- 0x11235,
+ 0x0acd,
0xa8c1,
- 0xabe8,
+ 0x1daa3,
0x11c98,
- 0x112e4,
+ 0x115ba,
0xe017b,
- 0x11a5b,
- 0x1dc3,
- 0x1acd,
- 0xa8c2,
- 0x16f69,
- 0x1dde,
- 0x0fb2,
- 0x11942,
+ 0x0bc7,
+ 0x11368,
+ 0x08e7,
+ 0x0ae3,
+ 0x0c4c,
+ 0x1cf37,
+ 0x1cf3d,
+ 0x112e3,
0x1bf1,
- 0x1cf21,
- 0xe0145,
+ 0x112e2,
+ 0x1d170,
+ 0xa9b3,
0x0362,
- 0x114bf,
0x0f84,
0xe013f,
0x0483,
- 0x11835,
- 0x1732,
+ 0x05b2,
+ 0xe0160,
0x11cae,
0x10f4f,
+ 0x16f61,
0xaaef,
- 0x11041,
- 0x1da0e,
+ 0xe01d8,
0x11a06,
- 0x05c2,
- 0x1143b,
- 0x2cef,
- 0x1cf0d,
+ 0x0339,
+ 0x11636,
+ 0x114b2,
+ 0x11c2f,
0x0b3e,
- 0x11ca2,
+ 0x1163a,
0x10f49,
- 0xa8e4,
- 0x0650,
- 0x0e36,
- 0xe01a4,
+ 0xa8ea,
+ 0x0c41,
+ 0x0655,
+ 0x11234,
0x032c,
- 0x11c9a,
- 0xe0172,
+ 0xe01af,
+ 0x1d17f,
0x0d3b,
- 0xa824,
+ 0x1da23,
+ 0xfb1e,
0x0ac2,
0x1bad,
- 0x0c4b,
+ 0x1163c,
0x0f95,
- 0x1714,
+ 0xa8bf,
0x1cf28,
- 0x0fb6,
+ 0xe0139,
0x10f85,
- 0xaaf6,
- 0x07b0,
+ 0x1abb,
+ 0x1da29,
0x1cf4,
- 0x1cd7,
- 0x11c33,
+ 0x06e8,
+ 0x1e8d1,
0x0b3c,
- 0xaabe,
+ 0xe011c,
0x1e013,
- 0x1cf43,
- 0x16f5d,
- 0x0ec8,
- 0x0dcf,
- 0x1b00,
- 0x1163d,
+ 0x1ace,
+ 0x05ab,
+ 0x10ae6,
+ 0x20e1,
+ 0x1cf3f,
+ 0x1dfb,
0x08cd,
- 0xe0133,
- 0x1a1a,
+ 0x11c36,
+ 0x073b,
0x082a,
- 0x1ac0,
+ 0x17b6,
+ 0x0e48,
0x20ee,
- 0x0dde,
- 0x17c5,
- 0x115bc,
- 0x0349,
+ 0x11937,
+ 0x1cdf,
+ 0xe0162,
0x1cf3a,
+ 0x08d9,
0x11637,
- 0x1cdd,
+ 0x2dfb,
0xe018c,
- 0x0fb0,
- 0x114be,
- 0x094b,
- 0x119d3,
+ 0x1df9,
+ 0x11073,
+ 0x135f,
0x08d7,
0x1773,
- 0x302b,
- 0x0f81,
+ 0x08e0,
+ 0x16af3,
0x0610,
- 0x1cf2b,
+ 0xe019c,
+ 0x0901,
0x1e018,
- 0x1171d,
+ 0x1e027,
0x1da2c,
- 0x11367,
+ 0x0b43,
0x180c,
- 0xe01a5,
+ 0x1753,
0x114b1,
0x115b2,
- 0x1daa5,
- 0x1134c,
- 0x0bd7,
- 0x1dd8,
- 0xe0189,
- 0x1cf09,
+ 0xabe7,
+ 0x031d,
+ 0x0c01,
+ 0x111b4,
+ 0xe01e2,
+ 0x08f5,
0x11cb5,
0x0cbc,
- 0x0dd6,
- 0x082b,
- 0xe0110,
+ 0x1a1a,
+ 0x1da14,
+ 0x1dc7,
0x1a18,
- 0xfb1e,
- 0x0949,
+ 0x0d62,
+ 0x0742,
0x1da58,
0x111b9,
0x11a35,
- 0x08ff,
- 0x11436,
- 0x11c36,
+ 0x115b9,
+ 0x0369,
+ 0x05a6,
0xa8f0,
+ 0xe0169,
0x116ab,
- 0x031a,
- 0x05ba,
- 0xabe3,
- 0x110b8,
- 0x0bbe,
+ 0x0ecb,
+ 0x0599,
+ 0x1da59,
+ 0x2dec,
0x11c99,
- 0x1ba9,
- 0xa983,
+ 0x0358,
+ 0x11128,
0xa8b5,
- 0x1ac9,
+ 0x1cf17,
0x16af2,
- 0x036e,
- 0x1b3d,
- 0xfe0f,
- 0x1cf30,
- 0xe014b,
+ 0x1133c,
+ 0x0711,
+ 0x11369,
+ 0x1a70,
+ 0x1062,
0xa94e,
- 0x1122d,
+ 0x1da11,
+ 0x059c,
0x0fb9,
0x11d42,
- 0x11a51,
- 0x1ac4,
+ 0xa92a,
0x11d91,
- 0x0cc8,
+ 0x1aba,
0x1a6b,
+ 0x1122c,
0xe0136,
- 0x112e9,
- 0x17c9,
- 0x16f92,
- 0x11a07,
+ 0x1086,
+ 0x1067,
+ 0xe01a2,
+ 0x0afd,
0x1da15,
- 0x1e010,
- 0xe01df,
- 0x1b04,
- 0xe0146,
- 0x11938,
- 0x116ad,
- 0x11c94,
- 0xa679,
+ 0x16f83,
+ 0x1da2a,
+ 0x1cf29,
+ 0x1da28,
+ 0x1b70,
+ 0x17b4,
+ 0x0ebb,
+ 0x0947,
0x11371,
- 0x05c5,
+ 0x1a1b,
0x0361,
- 0x10f47,
+ 0x11d34,
0x1cd4,
- 0xe0143,
- 0x1e029,
- 0x1e2ec,
+ 0x1cf3e,
+ 0x11935,
+ 0x11130,
0x1a5b,
0x11134,
- 0x05bf,
- 0x0355,
- 0x102c,
+ 0xe0149,
+ 0x11446,
+ 0x0363,
0xe0180,
- 0x1cf34,
+ 0xfe0c,
0x11c35,
+ 0x0eb6,
0x0fa4,
- 0xa825,
- 0x1dcc,
- 0x2de7,
+ 0x0fa0,
+ 0x08ff,
0x114ba,
- 0x05b9,
- 0x0f7d,
+ 0x11439,
+ 0xe0170,
0x0d40,
0xe015f,
- 0x1183a,
+ 0x06dc,
0x111c9,
0x0c48,
+ 0x1734,
0x1da43,
- 0x0323,
- 0x20d2,
+ 0xaa2c,
0x0ecd,
- 0x0333,
- 0x1b3a,
- 0x1be8,
- 0x18a9,
+ 0xe01b1,
+ 0x1e023,
+ 0x16f60,
+ 0x089d,
0x0e4d,
+ 0x07ee,
0x0312,
- 0xe01d2,
- 0x1da08,
+ 0xa8c4,
0x034c,
0x1103c,
0x0829,
- 0xe012c,
+ 0x1cf42,
0x1daa2,
0x11729,
- 0x16f81,
+ 0x0957,
0x119d1,
- 0x11ca3,
+ 0x1dc6,
0x1cf08,
- 0x0ac3,
- 0x11838,
+ 0x1abf,
+ 0x059e,
+ 0x0d81,
0xe01d3,
0x1da09,
- 0x0f7e,
+ 0x1d17d,
0x112e5,
- 0x0c02,
+ 0x11d90,
0x1e01e,
- 0x1cf9,
0x1e135,
- 0x1b42,
+ 0x030f,
0x110b2,
- 0x0659,
+ 0x111ce,
+ 0x17c6,
0xa8e3,
0x16f66,
0x0a3e,
- 0x1bef,
- 0x0732,
- 0xe011d,
+ 0x1e132,
+ 0xe0155,
+ 0x1e4ee,
0x07ab,
- 0x2de3,
- 0x05bb,
- 0xaab3,
- 0xa9b3,
+ 0x20ed,
+ 0x0963,
+ 0xe01d0,
+ 0xe01bf,
0x08d3,
- 0x16f84,
- 0x1e028,
- 0x08f6,
+ 0x1cde,
+ 0x1ba4,
+ 0x0ce3,
0x11437,
- 0x114b0,
- 0xe010d,
- 0x08e7,
- 0xe0186,
+ 0x0b02,
+ 0x0c40,
+ 0x08f4,
+ 0x11f38,
0x1088,
- 0x0d81,
- 0x0d03,
- 0x073c,
- 0x11374,
- 0x036f,
+ 0xa950,
+ 0x1bee,
+ 0xa881,
+ 0xe01a0,
+ 0x0900,
+ 0x1e8d6,
0x1171e,
- 0x0b3f,
0xe01b5,
- 0x1da2d,
+ 0x05ac,
+ 0xe0125,
0x20ef,
- 0x11c9c,
- 0x2deb,
+ 0x05b6,
+ 0xe01a7,
0x11d8d,
- 0x1063,
- 0x11c9b,
- 0x1daa6,
+ 0xe017c,
+ 0x0ccb,
0x1b3f,
+ 0x20eb,
0x0a3c,
- 0x0740,
+ 0xe0157,
0x1a57,
- 0x1d244,
+ 0x1d1ac,
0xa8ef,
- 0xe016e,
+ 0x0598,
0x112e0,
- 0x1da29,
- 0x20df,
+ 0xe012b,
+ 0x0f80,
0x1ddc,
- 0x1934,
- 0x0e4e,
+ 0x034b,
+ 0x1a68,
0xa6f0,
0x059b,
0x1b81,
- 0x11636,
+ 0x16b32,
0x0faa,
0x109c,
0x034d,
- 0x1da45,
- 0x1cf3f,
- 0x16f6e,
- 0x10a03,
+ 0xe010c,
+ 0x0319,
+ 0x1925,
+ 0x11a3b,
0x031b,
- 0xe014a,
- 0x11a03,
+ 0x1a64,
+ 0x08d4,
0xa677,
0x0b62,
- 0x1e003,
- 0x193b,
+ 0x11045,
+ 0x0acb,
0x1112f,
- 0x0dca,
- 0x1885,
- 0xa9b7,
- 0x11c30,
+ 0xe01d4,
+ 0x1da0a,
+ 0x115af,
+ 0x0613,
0xaaf5,
- 0x0c01,
- 0x0f8f,
- 0x1103e,
+ 0x08f1,
+ 0x11a56,
+ 0x0bbf,
0xaa4c,
- 0x1e947,
+ 0x1037a,
0x1dff,
- 0xe0175,
- 0x2df5,
+ 0x0abe,
+ 0x302e,
0x1b39,
- 0x1da14,
- 0x1136c,
- 0xe01de,
- 0x302a,
- 0x2de5,
- 0xe01b9,
- 0x1a6d,
- 0x1cf23,
- 0x2dfb,
+ 0x1da9d,
+ 0x1a6a,
+ 0x11ef6,
+ 0xe01aa,
+ 0x112ea,
+ 0x1e01c,
+ 0x1039,
+ 0x05b8,
+ 0x11c34,
+ 0x20db,
0x11230,
0x0c83,
- 0x0bc6,
- 0xe0150,
- 0xe016f,
- 0x193a,
- 0x0e39,
- 0x1068,
- 0xe017f,
- 0x10d27,
- 0xe01a3,
- 0x20e5,
- 0x0afc,
- 0x1cf07,
- 0x1da40,
+ 0x1036,
+ 0x0948,
+ 0x119db,
+ 0xe01ed,
+ 0x1c31,
+ 0x10a3f,
+ 0x1ab5,
+ 0x11d94,
+ 0xa983,
+ 0x0ccd,
+ 0x17c4,
+ 0x11931,
+ 0x11f42,
0x1c28,
- 0x0cc3,
- 0x0954,
- 0xabec,
+ 0x1da32,
+ 0x11145,
+ 0x302a,
0xe0135,
0x0ac8,
0x0cc7,
- 0x1ac3,
+ 0xe01ad,
0x1da00,
0x1b37,
- 0x0e35,
+ 0x036f,
0x11d43,
- 0xe01ee,
- 0x1143d,
+ 0x116ad,
+ 0x11ef5,
0xa8ff,
- 0x2cf1,
- 0x1cf3d,
- 0xa82c,
+ 0x1da19,
+ 0x030a,
+ 0x09cc,
0x10eac,
0x11d8c,
0x11a0a,
- 0x0dd0,
- 0x20d9,
+ 0xaab4,
+ 0xfe2f,
0x0ac0,
0xe0194,
0x065f,
- 0x11940,
- 0xaa31,
- 0x0ce2,
- 0xe0190,
+ 0x11a07,
+ 0xe015a,
+ 0xe0173,
+ 0x1c27,
0x17c8,
- 0x10f4a,
- 0x2dfd,
- 0x0ac9,
- 0x11080,
- 0xa671,
- 0x1193c,
+ 0x0820,
+ 0x065d,
+ 0x0bcb,
+ 0xe01dd,
+ 0x11343,
+ 0x1e009,
0x0941,
- 0x0c3c,
+ 0x1752,
+ 0x1ce4,
0x0329,
- 0x11d8a,
- 0x0fb3,
- 0x17b4,
- 0x1a5d,
+ 0x1713,
+ 0xe0118,
+ 0x119da,
+ 0x1da6a,
0x08f2,
- 0x1df6,
- 0x08d5,
+ 0x0f71,
0x16f51,
+ 0x089e,
0x2df8,
- 0x302c,
0x10a0e,
- 0xe01c0,
- 0x2cf0,
- 0x16f55,
- 0x1de7,
- 0x10f48,
+ 0x2de4,
+ 0xaa2a,
+ 0xe0192,
+ 0x0dd2,
+ 0x0c81,
+ 0xe01c7,
0x10a38,
0xe0176,
- 0x16f60,
+ 0x20e9,
0xe019d,
- 0x1cd5,
- 0x0d44,
- 0x111ce,
- 0x0bbf,
- 0x1cf44,
- 0x0345,
- 0x11a96,
- 0x1931,
- 0xe01c1,
- 0x116b5,
+ 0x20e7,
+ 0x032e,
+ 0x1e01d,
+ 0x1cf24,
+ 0x0731,
+ 0x0ac4,
+ 0xe017d,
+ 0x16f7b,
+ 0x1c34,
+ 0x115b5,
0x0306,
- 0x08ea,
+ 0x16f76,
0x0bc8,
- 0x0fba,
+ 0x061a,
0xa949,
- 0x0fa6,
- 0x0bca,
+ 0x08f0,
+ 0x11cb2,
0x1133f,
- 0x11301,
- 0x0738,
- 0x1e944,
- 0xa672,
+ 0x111b5,
+ 0x11344,
+ 0x082d,
+ 0x1dd3,
+ 0x1d172,
0xe010b,
- 0x114c1,
- 0xfe2a,
- 0x1daa9,
- 0x0fad,
- 0x11ca9,
- 0x0bc1,
- 0x1ac8,
- 0x1163a,
+ 0x2df6,
+ 0x06e0,
+ 0x1107f,
+ 0x16f74,
+ 0x11d47,
+ 0x11943,
+ 0x16b30,
0x11a01,
0x0d4b,
0xaa7b,
- 0xe012b,
- 0x0823,
- 0x0ccc,
- 0x16f56,
+ 0x1da22,
+ 0xe01ec,
+ 0x13447,
+ 0x1cf0b,
+ 0x11c9a,
0x2dfa,
- 0x030a,
+ 0xe01c2,
0x11724,
- 0x114c3,
- 0x08ed,
- 0x115b4,
- 0x0487,
- 0x0903,
- 0x1dc2,
+ 0x0485,
+ 0x11a52,
+ 0xe01cd,
+ 0x1da03,
+ 0xa8bb,
0x11722,
- 0x16f83,
- 0x11d40,
- 0x064b,
+ 0x11930,
+ 0x06ed,
+ 0x0615,
0x1daa8,
+ 0xe0132,
0x1cf33,
0x11042,
- 0x05b4,
+ 0x1cd8,
0x1a17,
- 0x0352,
- 0x11c3f,
- 0x1112a,
+ 0xe0171,
+ 0x089f,
+ 0x119dd,
0x1da5e,
- 0x11c3b,
- 0x17d1,
- 0x1ab0,
- 0x11a5a,
- 0x08e4,
+ 0x1d1aa,
+ 0x1da24,
+ 0x0b01,
+ 0x1a5e,
+ 0x11d3d,
0xe0165,
- 0x11cac,
+ 0x0367,
0x110b6,
- 0x1da49,
+ 0x11074,
0x1cf38,
- 0x1cf32,
- 0x1df9,
+ 0x11237,
+ 0x1df3,
0x1de5,
- 0xa823,
- 0x114bc,
- 0x0f75,
+ 0xe0140,
+ 0xa672,
+ 0x074a,
0x10376,
+ 0x180d,
0xe01c9,
- 0xaa2c,
0x0c63,
- 0x1056,
- 0xe019f,
- 0x0eb9,
- 0x1da9d,
- 0x0a75,
- 0xaa7d,
- 0x11c9f,
- 0x0d46,
- 0x110c2,
+ 0x064c,
+ 0x1ba8,
+ 0x0f7c,
+ 0x16f55,
+ 0xe010d,
+ 0x0484,
+ 0x11caf,
+ 0xe0106,
+ 0x0318,
+ 0x119e4,
0x032b,
- 0x0350,
- 0x1e8d0,
+ 0xe016e,
0x11438,
0x116af,
- 0xa881,
- 0x0327,
- 0x1a70,
- 0x1058,
+ 0x17cf,
+ 0x1344d,
+ 0x1e4ef,
+ 0x11f03,
+ 0x1da47,
0x106d,
- 0x103e,
- 0x0748,
- 0x06e8,
- 0xa927,
- 0x17c3,
- 0x1dce,
+ 0x1ddf,
+ 0x0d47,
+ 0x0c4a,
+ 0x0a4c,
+ 0x1cda,
+ 0x0591,
0x0b56,
0x1d187,
0x0a47,
- 0x1c35,
- 0x20e2,
+ 0x10a0c,
0x0a81,
- 0x1dd0,
- 0xfe00,
- 0xe017a,
- 0x11d97,
+ 0xa8b6,
+ 0x11d95,
+ 0x0cc0,
+ 0x0a83,
+ 0x1927,
0x06d8,
- 0x1b34,
- 0x1e8d3,
+ 0xe011b,
+ 0x06d6,
0x2dea,
- 0x0df2,
+ 0x1a61,
0xe0117,
- 0x17bd,
+ 0x20e4,
0xa9b8,
0x10f84,
0x08dd,
0xe01bb,
0x1dd2,
- 0x16f75,
- 0x1e8d6,
- 0x11c38,
- 0xe01ad,
- 0x16f73,
- 0x17bf,
- 0x1a68,
- 0x0ccd,
- 0x11074,
- 0xfe0b,
- 0x2df2,
- 0x11133,
- 0x1da4b,
+ 0x1da05,
+ 0x0f87,
+ 0x1bea,
+ 0x17d1,
+ 0x11728,
+ 0x1dc3,
+ 0x114b0,
+ 0xa8b9,
+ 0x073c,
+ 0x0a48,
+ 0x094e,
+ 0xa94b,
+ 0x0fb6,
+ 0x17c1,
0x05a7,
0x1df2,
- 0x16f86,
- 0x1c2a,
- 0x1da69,
- 0x0fa3,
+ 0x0bd7,
+ 0x0d83,
+ 0x1cf3b,
0x16fe4,
+ 0x10efd,
0x0365,
- 0x1a6a,
- 0x1086,
- 0x0a03,
- 0x3099,
- 0x119de,
+ 0x089a,
+ 0x0fa6,
+ 0x1da3c,
+ 0x11c9d,
+ 0xe0114,
0x1ab7,
- 0x1da5c,
- 0x1a59,
- 0xaa29,
- 0x0303,
- 0x0bc7,
+ 0x081f,
+ 0xa8e8,
+ 0x1193b,
+ 0x0eb1,
+ 0x032d,
0x1cf2c,
- 0xe0134,
- 0x1da0d,
- 0x0ddf,
- 0x0316,
+ 0xa8e4,
+ 0xe01d7,
+ 0x059d,
0xabed,
- 0x0fac,
- 0x0d47,
+ 0x16f78,
+ 0x1b04,
+ 0x08f3,
0x11101,
- 0x0342,
- 0x1172b,
- 0xe0177,
- 0x0743,
- 0x16b32,
- 0xe0195,
- 0x1e008,
+ 0x115be,
+ 0x11d31,
+ 0x1c33,
+ 0x1cf07,
+ 0x0307,
+ 0x0651,
+ 0x1ce5,
0x1dd9,
- 0xe01c8,
- 0x1cf14,
- 0x0f87,
- 0xa926,
+ 0x115b8,
+ 0xe01ac,
+ 0x033e,
+ 0x1920,
0x08e9,
- 0xe01e9,
- 0x08cb,
- 0x10d26,
+ 0x2df9,
+ 0x16f58,
+ 0xe01d5,
0x16f6d,
- 0x16b36,
- 0x05b6,
- 0xe0123,
+ 0xe014a,
+ 0x0d4d,
+ 0x11ca0,
0x1cf0a,
- 0x1cd1,
- 0x065a,
+ 0x1ce8,
+ 0x1060,
0x11c96,
0x035e,
- 0x16b35,
+ 0xe0186,
0x115bb,
- 0xe0137,
- 0x0ac4,
- 0x0947,
- 0x1da55,
- 0x0818,
- 0xe01ec,
- 0x1123e,
- 0xe0132,
- 0x0357,
- 0x1182f,
- 0x094e,
- 0x11c9e,
- 0x11343,
+ 0x119d7,
+ 0x16af4,
+ 0x1daa9,
+ 0x0982,
+ 0x11cb3,
+ 0x1cf2a,
+ 0x11ca4,
+ 0x033b,
+ 0x135d,
+ 0x11435,
+ 0x114b8,
+ 0x09bc,
+ 0x1e005,
+ 0x11082,
0x1d1ab,
- 0x1abf,
- 0x1cdb,
- 0x05b5,
- 0xfe0d,
- 0x111cc,
- 0x1937,
- 0x089a,
+ 0x10a03,
+ 0xa8f1,
+ 0x0e4a,
+ 0x11ca2,
+ 0xabec,
+ 0x081c,
0x1ce2,
- 0x11d96,
- 0x0948,
- 0x1b82,
- 0x0cc4,
+ 0x1da0e,
+ 0x06df,
+ 0xfe22,
+ 0x1ce6,
0x1087,
- 0x1a5a,
- 0x16f67,
- 0x1c34,
+ 0x0f8f,
+ 0x11a8f,
+ 0x09c2,
0x1da4e,
- 0x1a7f,
- 0xe0138,
- 0x20dd,
+ 0x1e006,
+ 0x08d0,
+ 0x1dd8,
+ 0x1714,
0x0a40,
- 0x1ac5,
0xe0126,
- 0x1923,
- 0x11372,
- 0x11303,
- 0x11833,
+ 0x11a53,
+ 0x13451,
+ 0x1059,
+ 0x1da61,
+ 0x1e2ed,
0x1d17c,
0xa678,
- 0x0dda,
- 0x1be7,
- 0x1bc9e,
+ 0x3099,
+ 0x16f65,
+ 0xe0131,
0x0826,
- 0x1182c,
+ 0x11c3d,
0x0df3,
- 0xaa2d,
- 0x09c4,
- 0x102b,
+ 0x180f,
+ 0x1a56,
+ 0x11d8a,
0x1cd9,
0xa8e0,
- 0x1ce7,
- 0x11933,
- 0x11a8a,
- 0xe0179,
- 0x1da24,
+ 0xe0129,
+ 0x1938,
+ 0x11f00,
+ 0x0345,
+ 0x1b02,
0xa9bd,
0x11443,
- 0xaa7c,
- 0xfe27,
+ 0xa806,
+ 0xa9b9,
+ 0x1da0c,
0xe01d6,
- 0x1b73,
0x1e00f,
- 0x11129,
- 0x07ac,
- 0x1d167,
- 0x030f,
- 0x2dee,
+ 0x1932,
+ 0x13454,
+ 0x1134b,
+ 0x192a,
+ 0x0f79,
0x1a60,
- 0xa952,
- 0x1e949,
- 0x10a0d,
+ 0x0659,
+ 0x11f3a,
+ 0x1e8d5,
0x0d01,
- 0x031d,
- 0x135f,
- 0xe01e4,
- 0x11ef4,
+ 0x0734,
+ 0x11146,
+ 0xe0108,
+ 0xe0153,
+ 0x06eb,
0xe013b,
- 0x0956,
- 0x0816,
- 0x1da65,
- 0x16f6f,
+ 0x1a73,
+ 0xe0167,
+ 0x11a98,
0x0f72,
- 0x16f79,
- 0xaab4,
- 0x105f,
- 0x1d180,
- 0x1e132,
- 0x059c,
- 0xe0185,
- 0xa9b6,
+ 0x11831,
+ 0x1dcc,
+ 0x0f81,
+ 0x119d5,
+ 0x16f68,
+ 0x0f90,
+ 0x114bb,
+ 0x2dfd,
+ 0xfe00,
0x08f7,
0x1da56,
- 0xe016a,
- 0x16f7b,
- 0x034e,
- 0x1030,
+ 0xe0187,
+ 0xa9c0,
+ 0x0f93,
+ 0xa67b,
0x0344,
- 0xe0118,
- 0x0336,
- 0x1752,
+ 0x20e2,
+ 0x08fa,
+ 0x082b,
0x05a1,
0x1ba3,
- 0x08eb,
- 0x0b4b,
+ 0x1da42,
+ 0x0313,
0x11366,
- 0x11ca6,
- 0x1d16d,
+ 0x1a6c,
+ 0xe01db,
0xa929,
- 0x16f6c,
- 0x112e8,
- 0x0dd2,
- 0xe0192,
- 0x093c,
+ 0xe01e5,
+ 0x1da1b,
+ 0x116b0,
+ 0x0324,
+ 0x17be,
0x17c0,
- 0x1cf1a,
+ 0x20dd,
0x11836,
+ 0x10f50,
0x073d,
- 0x10379,
- 0x1c26,
+ 0xe01bd,
0x0dd1,
- 0x1da0f,
- 0xe01d9,
- 0x16b31,
- 0x114c2,
+ 0x1933,
+ 0x1cf1b,
+ 0x081b,
+ 0xaa43,
+ 0xe01ee,
0x115dc,
0x1de4,
- 0x1e01d,
- 0xfe25,
+ 0x0349,
+ 0x11c32,
0xe0184,
- 0x05b0,
- 0x10378,
+ 0xa953,
+ 0x20ec,
0xe0147,
- 0x17cf,
- 0x1e01b,
- 0xe01af,
- 0x0c55,
- 0x2d7f,
+ 0x1cf31,
+ 0xaa2d,
+ 0x0b47,
+ 0x08cf,
+ 0xa92c,
0x1e024,
- 0x135d,
- 0x1da35,
- 0x0313,
- 0xa92b,
- 0xe0160,
+ 0x1e01b,
+ 0x1acd,
+ 0xe0181,
+ 0xe0124,
+ 0x1a62,
0x09bf,
0x059a,
0x0d4c,
0x11727,
- 0x1daad,
0x109b,
- 0xa947,
- 0x1e2ae,
- 0x1c2d,
+ 0x115c0,
+ 0x2def,
+ 0xe010e,
+ 0x1ced,
0xaa30,
- 0xe010c,
+ 0x1baa,
0xaabf,
- 0xe01b4,
+ 0x1da18,
0x1daaf,
0x1da1a,
0x1d181,
0x1ba6,
- 0x1dcf,
- 0x06eb,
- 0x11a3b,
- 0x0953,
+ 0x1cf02,
+ 0x11ca9,
+ 0xe01ba,
+ 0x0903,
0x1cf05,
0x0abf,
- 0x05a8,
+ 0x108c,
0x115bf,
- 0x11d8b,
+ 0x0d46,
0xe0111,
- 0xe01cf,
- 0x1da05,
- 0x1c30,
+ 0x05a0,
+ 0x11c3a,
+ 0x11725,
0x0c04,
- 0x20d0,
- 0x08df,
- 0x1b01,
- 0x0fbb,
- 0x11128,
- 0x0b41,
+ 0x08d5,
+ 0x10379,
+ 0x0308,
+ 0x1e020,
+ 0x0f9a,
+ 0x17c3,
+ 0xfe06,
0x1a55,
- 0x0d3e,
- 0x08e8,
- 0x05ab,
- 0x1d16f,
- 0x1a76,
- 0x1da0a,
- 0xaa32,
- 0xe0130,
+ 0x115b0,
+ 0x111b7,
+ 0x20d4,
+ 0x16f87,
+ 0x0a03,
+ 0xe0163,
+ 0x102b,
+ 0x06e2,
0xa9bb,
0x07a9,
- 0x0739,
- 0x1b70,
- 0x10f46,
- 0x1e000,
- 0x0a83,
- 0xe018d,
- 0x11a47,
+ 0xaa4d,
+ 0x10f4c,
+ 0x11d97,
+ 0x114bc,
+ 0x2cf0,
+ 0x1ab8,
+ 0x1a67,
0x106b,
- 0x1a61,
- 0x192b,
- 0xa8ba,
- 0x11145,
+ 0x0f75,
+ 0x11348,
+ 0x1cf9,
+ 0x11070,
0x065e,
0xe0199,
0x0f7b,
- 0xe013c,
- 0xa980,
- 0x0aff,
+ 0xa679,
+ 0x11a05,
+ 0x1ab2,
0x034a,
- 0x1df8,
- 0x030e,
- 0xa8e7,
- 0xa8c0,
+ 0xa82c,
+ 0x1e136,
+ 0x10f4b,
+ 0x20d2,
0x1cf46,
0x1da9e,
0x08db,
- 0x11363,
- 0xe0115,
- 0x0faf,
- 0x08f5,
- 0x1035,
- 0x0943,
- 0x1dc4,
- 0x114c0,
- 0x08fc,
- 0x2de6,
+ 0x0f39,
+ 0x111bb,
+ 0x1da26,
+ 0x10d26,
+ 0x1e00c,
+ 0x102c,
+ 0x16f86,
+ 0xe012e,
+ 0x1e944,
+ 0x0fb7,
0x1b36,
0x0c47,
0x180b,
- 0x0899,
- 0x302f,
- 0x1da5f,
- 0x109d,
- 0x16f90,
- 0x0fb1,
+ 0x0654,
+ 0x11cad,
+ 0x08ec,
+ 0x16f6c,
+ 0x1b44,
+ 0x0ece,
0x0ddc,
- 0xe015a,
+ 0xe01e7,
+ 0xe0177,
0x1dd7,
- 0xaa35,
+ 0xe015e,
0x0b55,
- 0xa880,
- 0x1df7,
- 0x1a5c,
+ 0x0aff,
+ 0x0cca,
0x1163b,
- 0x1074,
- 0x119d4,
- 0xe0153,
- 0xe01a6,
- 0xfe02,
- 0x035c,
- 0x1cf0f,
- 0xa8eb,
- 0x0a01,
- 0x11a08,
+ 0x1b01,
+ 0x112e7,
+ 0x10a01,
+ 0x0f99,
+ 0x11a3e,
+ 0x1da01,
+ 0x1143c,
+ 0x11a97,
+ 0xe019e,
+ 0xe019a,
0x135e,
+ 0xe018b,
0x034f,
0x1193d,
- 0x0940,
- 0x16f74,
+ 0x0368,
0xaaee,
- 0x1da13,
+ 0xaa2b,
+ 0x10f47,
0x10f4e,
- 0x114b8,
- 0xe0166,
- 0x115b3,
- 0xe01c3,
- 0x11a57,
- 0x1da3d,
- 0x0b47,
- 0x0f93,
- 0x302d,
+ 0x0f91,
+ 0xe0112,
+ 0x11640,
+ 0x08ee,
+ 0x11080,
+ 0x11c33,
+ 0x16f7f,
+ 0x1dde,
+ 0x1daab,
0xe017e,
0x0945,
- 0x1cf3c,
+ 0x0593,
0x1da5a,
- 0x11446,
- 0x1932,
- 0xa948,
- 0x033b,
- 0xe012f,
- 0x0afd,
+ 0x05bb,
+ 0x0942,
+ 0x1da30,
+ 0xaaf6,
+ 0x1da50,
+ 0x16ff0,
0xa8b7,
- 0x1dd5,
+ 0x11940,
0x0360,
- 0xe01ba,
- 0x0359,
+ 0x2df5,
+ 0x073f,
0x1a78,
- 0x11c3a,
- 0x0eb5,
- 0x0339,
- 0x1b3c,
- 0x1cf25,
+ 0x09fe,
+ 0x08e5,
+ 0x17ce,
+ 0x16f52,
+ 0xfe2e,
+ 0x1c2f,
0x1182e,
- 0x11081,
- 0x1034,
- 0x119db,
- 0x11c92,
- 0x11725,
- 0x0302,
- 0x0b44,
- 0x1d171,
+ 0xe017f,
+ 0x2df4,
+ 0xe01a3,
+ 0x11631,
+ 0x07f0,
+ 0x11ef3,
+ 0x05bd,
0x1dfe,
+ 0x1133e,
0x11a02,
- 0x114b4,
- 0x11173,
+ 0xe0110,
0x0afe,
- 0x20eb,
+ 0x2dee,
0x05a5,
- 0xe01d4,
+ 0x0594,
0x1da04,
- 0x11445,
- 0x11d33,
+ 0x08ef,
+ 0xe0145,
+ 0x030e,
0x0347,
- 0x1df4,
+ 0x0c62,
0xfe09,
- 0xe01e3,
- 0x0e4a,
- 0x0eb8,
- 0x0f83,
+ 0x1133b,
+ 0x114bd,
+ 0x111b6,
+ 0x1cf10,
0x1da3e,
- 0x0e48,
+ 0xe01b9,
0x1da48,
- 0x06ea,
- 0xe0154,
+ 0x0b4d,
+ 0x1dc5,
0x0dd4,
- 0x11348,
+ 0x1e945,
0x0618,
0x0f74,
0x11043,
- 0x1929,
+ 0x1a7f,
0x08d6,
- 0x1de6,
- 0x11a52,
+ 0x1e08f,
+ 0x11c30,
0x11a8c,
0xe01ca,
0x0332,
- 0x1daac,
- 0x082c,
+ 0x16af0,
+ 0x0dde,
0x16f7a,
- 0xa94f,
+ 0x10a0f,
+ 0x20d0,
0x11362,
- 0x1da9b,
0x1e00d,
- 0x2dfe,
+ 0x1112b,
0x05a3,
- 0x116b6,
- 0x17ca,
- 0x034b,
- 0x1083,
+ 0x0a70,
+ 0x1da65,
+ 0x11a5b,
+ 0xa9b7,
+ 0x11ca3,
0x0fb8,
- 0x1a6f,
- 0x1cd2,
+ 0x1033,
+ 0x111cf,
0xe011a,
- 0x1cf1e,
- 0x16f7e,
- 0x1936,
- 0x11d90,
- 0x16f59,
- 0x1e005,
- 0x1da42,
- 0x07ee,
+ 0x0822,
+ 0x05c2,
+ 0x1733,
+ 0xe0175,
+ 0x1ab9,
+ 0xe014e,
+ 0x1e02a,
+ 0x0f3e,
0x106c,
- 0x09c8,
0x093b,
- 0x103c,
+ 0x2de5,
+ 0x17cc,
0x20e3,
- 0xe01e5,
0x1da9f,
+ 0x11938,
0x0736,
- 0x1b6b,
- 0x07aa,
+ 0x1e029,
+ 0x0d03,
0x0bcd,
- 0x1cf01,
- 0x036b,
- 0x114b5,
- 0x111c0,
- 0x0321,
- 0x1163c,
- 0xa9e5,
- 0x1a6c,
- 0x0f73,
- 0xa8e9,
- 0x085a,
+ 0x11cab,
+ 0x11039,
+ 0x1e4ec,
+ 0x1cf03,
+ 0x030d,
+ 0x1089,
+ 0x302b,
+ 0x11301,
+ 0x11131,
+ 0xa92b,
+ 0x1d17e,
0x111ca,
- 0x0eb4,
- 0x05a6,
+ 0x1e8d0,
+ 0x0650,
0x2df3,
0x08dc,
- 0x05b7,
+ 0x102e,
0xa94c,
0x0c03,
- 0x17b6,
- 0x0819,
- 0x1143c,
- 0x1d1ad,
- 0x0b48,
- 0xfe2f,
- 0xa8ea,
+ 0xaab2,
+ 0x0eb5,
+ 0xa8e2,
+ 0x0f77,
+ 0xe0138,
+ 0x1bed,
+ 0xe01cf,
+ 0x112e9,
0xe0144,
- 0x1da20,
- 0x1de0,
- 0x1037a,
- 0x05ad,
+ 0x11d33,
+ 0x1ac0,
+ 0xe01b6,
0x17c2,
+ 0x0ac5,
0x11d44,
- 0x16f85,
- 0x0ccb,
- 0x11370,
- 0x11930,
+ 0x0739,
+ 0x11839,
+ 0x1885,
0x11100,
+ 0x064b,
0x1ba5,
- 0x1e8d5,
+ 0x110b3,
0x0e47,
- 0x1069,
- 0x1cdf,
- 0xfe20,
+ 0x08d2,
+ 0x07ef,
0x0335,
- 0x11ca7,
- 0x07f0,
- 0x10a0f,
+ 0x0f86,
+ 0x1a5d,
+ 0x030c,
0xa67d,
+ 0x1d165,
0x11cb0,
0x033d,
- 0x08d9,
+ 0x1beb,
0x16f8f,
- 0x108f,
- 0x1122e,
- 0x1b6f,
- 0xe01dd,
- 0x033a,
- 0x1dc8,
- 0x16b33,
- 0xa8bd,
- 0x11d3d,
- 0x11a55,
+ 0x11a5a,
+ 0x10ae5,
+ 0x1da13,
+ 0x103d,
+ 0x1cf12,
+ 0x0e36,
+ 0x11630,
+ 0x0944,
+ 0xaab7,
+ 0x10a3a,
0x1da31,
- 0x1daa3,
- 0x1da41,
- 0x20d8,
- 0x2df6,
+ 0x1cf30,
+ 0x07f2,
+ 0x1cf09,
+ 0xe014c,
0x1cf15,
- 0x1da4c,
+ 0x0d42,
0x0946,
- 0xe0162,
- 0x1a69,
- 0x1cf17,
+ 0x1da40,
+ 0x0cc6,
+ 0x09c1,
0x06e7,
- 0x1d17f,
+ 0x0fa9,
0x1ba7,
- 0x0369,
+ 0x0cf3,
0x0341,
- 0xe01e2,
- 0x1da18,
- 0x0c42,
- 0xfe26,
- 0x1ab2,
- 0x11d31,
- 0x033c,
- 0x0d43,
- 0xe0168,
- 0xabe5,
+ 0x05ba,
+ 0x1acc,
+ 0x0bc6,
+ 0x1ddb,
+ 0x0327,
+ 0x1da2d,
+ 0xe0178,
+ 0x2dff,
+ 0x16b34,
+ 0x0bca,
+ 0x1939,
0x1be6,
- 0x1e948,
- 0x20f0,
- 0x11943,
+ 0x0fad,
+ 0x119d3,
0xa9b4,
- 0x0b03,
+ 0x11d3a,
0x0488,
0x20e0,
- 0x0d00,
- 0x119dc,
+ 0x1cf36,
+ 0x0337,
+ 0x1abe,
0x1031,
- 0x09bc,
- 0x073b,
- 0x16f58,
- 0x10f82,
- 0x1067,
- 0x035d,
- 0x1059,
- 0x0817,
- 0x1da2b,
+ 0x1dd4,
+ 0x09d7,
+ 0x1163f,
+ 0x1cf21,
+ 0x1dc4,
+ 0xfe04,
+ 0xe0189,
+ 0x036a,
+ 0x1ddd,
0x114b6,
- 0x1a7a,
- 0x0f96,
+ 0x11180,
+ 0xe016a,
0x16f6a,
0x16ff1,
- 0x0485,
- 0xe014f,
- 0x16f63,
- 0x1734,
+ 0xe0127,
+ 0x11231,
+ 0x11241,
+ 0x0656,
0xe0161,
- 0x11d45,
- 0x0bcc,
- 0x0c40,
- 0xa6f1,
- 0x1da6a,
- 0x0310,
- 0x0ddb,
- 0x1cf27,
- 0x16f7f,
- 0x0f92,
- 0x11c97,
- 0x0859,
- 0x1cf02,
+ 0x0346,
+ 0x1143a,
+ 0x1cd6,
+ 0x0949,
+ 0x1c26,
+ 0x110b1,
+ 0x11436,
+ 0x11a03,
+ 0x11367,
+ 0x1e2ae,
+ 0xfe0a,
+ 0x1e00e,
+ 0x0325,
0x1da9c,
0x1a65,
- 0x11cab,
+ 0x0983,
+ 0x11a08,
0x17b9,
- 0x1deb,
- 0xe0191,
- 0x0f9e,
- 0x16f5e,
- 0x1abc,
+ 0x0c4b,
+ 0xe0174,
+ 0x1d244,
+ 0x1344f,
+ 0x2de7,
0x1b38,
- 0x1071,
0xe013a,
+ 0x20dc,
0xe011f,
- 0x0c4a,
- 0x1da28,
- 0xabe9,
+ 0x1cf19,
+ 0x08d1,
+ 0x1e010,
0x0955,
- 0x089b,
+ 0x16f69,
0x10eab,
- 0xa92c,
- 0x1ba8,
- 0x11721,
- 0x20e1,
- 0xa69e,
- 0xa9bf,
+ 0x17c7,
+ 0x11340,
+ 0x081d,
+ 0x0328,
+ 0x1e028,
0x17bc,
- 0x059d,
+ 0xaab3,
0xe01b7,
- 0xe013e,
- 0x0e4c,
+ 0x0e4e,
+ 0x1abc,
0x1da66,
- 0x0325,
- 0x08f4,
- 0xa92d,
- 0x1927,
- 0x111b5,
- 0x1a72,
- 0x1dc6,
+ 0x1732,
+ 0xe01ae,
+ 0x1cf43,
+ 0x1d243,
+ 0x1712,
+ 0x0c42,
+ 0x0b3f,
+ 0x302d,
0xe01e6,
0x1da1c,
- 0x16b34,
0x2ded,
- 0x0a70,
+ 0x1b41,
+ 0x11cb4,
0xe0148,
- 0x0fa0,
- 0x08e0,
- 0x20ed,
- 0x0902,
- 0xe019c,
- 0x11726,
- 0xe0193,
+ 0xe0123,
+ 0x11d93,
+ 0x1072,
+ 0x1936,
+ 0x1063,
+ 0x0c56,
+ 0x11a39,
0x1e2ef,
- 0x1bec,
+ 0xe01ab,
0x17d0,
- 0x0c4c,
- 0x1cf00,
- 0x11ca0,
- 0x16f64,
- 0x094c,
+ 0x1d242,
+ 0x0359,
+ 0x1123e,
+ 0x11639,
+ 0x1b73,
0xe0152,
- 0x08ef,
+ 0x11a8d,
0x16af1,
0x035b,
0x0bc2,
0x1da12,
- 0x1e00b,
+ 0xe01da,
+ 0x11c93,
0x094a,
- 0x1143f,
0x073e,
- 0x20d4,
- 0x064c,
- 0xfe06,
- 0x09c3,
- 0x1bf0,
- 0x17b5,
- 0x1e001,
+ 0x11372,
+ 0x0d48,
+ 0x1de9,
+ 0x114c1,
+ 0x07ae,
+ 0x11a54,
+ 0x10a39,
0x11638,
- 0x11045,
- 0x1a64,
- 0x0484,
- 0x0c00,
- 0x08fe,
- 0x0f82,
- 0x0cd5,
- 0x112e2,
+ 0x2deb,
+ 0x073a,
+ 0x1cf0f,
+ 0x0fab,
+ 0x1aca,
+ 0xa8c3,
+ 0xa981,
+ 0x1ac4,
0x1e133,
+ 0xabe5,
0x1da52,
- 0x05b8,
+ 0x0e37,
0xe0105,
- 0x1d18a,
- 0xa674,
- 0x0737,
- 0x0d41,
+ 0x11357,
+ 0x0336,
+ 0x0c3e,
+ 0xe010f,
0xe0188,
- 0x0eba,
0x111cb,
0x11444,
- 0x1d1aa,
+ 0x0940,
+ 0x11cac,
0xa8ed,
0x114b7,
- 0x2de8,
- 0x0307,
- 0x0f3e,
+ 0x11832,
+ 0x0743,
+ 0x08d8,
0x1e026,
0x1da53,
- 0xe0120,
+ 0x11c3f,
0x1da06,
- 0x16af4,
- 0x1b43,
- 0x0351,
- 0x1dc1,
+ 0xe019b,
+ 0x119d2,
+ 0xaa34,
+ 0x1b00,
0x0730,
- 0x06e4,
- 0x1163e,
- 0x1938,
+ 0x13440,
+ 0x0cc4,
+ 0xe0146,
0x1c25,
- 0xa94a,
- 0x0eb6,
- 0x1134b,
- 0xe0108,
- 0x1ab5,
- 0x11234,
- 0x1ddb,
+ 0x030b,
+ 0x11a95,
+ 0x0323,
+ 0x1e00b,
+ 0x0943,
+ 0x0f8d,
+ 0x0dca,
0x10d25,
- 0x2df4,
- 0x0322,
+ 0x2de9,
+ 0x1bab,
0x115b1,
+ 0x1da2b,
0x0ebc,
- 0x16f76,
- 0xa9b9,
+ 0x1e131,
0xe018a,
+ 0x1923,
0x05c1,
- 0x11d35,
+ 0x20df,
0x1103d,
- 0xfe0c,
- 0xa676,
+ 0xa927,
+ 0x1c2e,
0x07ec,
- 0x1cf24,
0x16f82,
- 0x112ea,
+ 0xe01e4,
0x1da25,
- 0xe014e,
- 0x11630,
+ 0x0f7a,
+ 0x1cf20,
+ 0x1171d,
0x11347,
- 0x07fd,
0x112e6,
+ 0x1d188,
0x11d41,
- 0x032e,
+ 0x1068,
0x089c,
- 0x065b,
- 0xfe22,
- 0x09c2,
- 0xe01b1,
- 0x115b9,
- 0x0354,
- 0xaab2,
+ 0x11f36,
+ 0x11341,
+ 0xaa2f,
+ 0x0356,
+ 0xe0137,
+ 0x1344c,
+ 0x0fb0,
0xe016b,
- 0xaab8,
- 0xa982,
- 0x08d0,
- 0x1926,
+ 0x1df4,
+ 0x1112d,
+ 0x1de2,
0x1103b,
- 0x1cf31,
- 0xe01ce,
- 0x0898,
- 0x11a09,
+ 0x08f9,
+ 0xe01c0,
+ 0x11f40,
+ 0x119df,
+ 0x1083,
0xaa33,
- 0x1b3e,
- 0x17be,
- 0x1dca,
- 0x16f71,
- 0x0acb,
+ 0x13448,
+ 0x0fb4,
+ 0x0ac3,
+ 0xabe4,
+ 0x11a3c,
0x1134d,
0x114b9,
0x103a,
- 0x1ac2,
- 0xe01a2,
- 0xe0129,
- 0x0309,
+ 0x1da20,
+ 0x08da,
+ 0x16f56,
+ 0x309a,
+ 0x11127,
0x11a93,
- 0x1b3b,
- 0x1cf36,
+ 0x192b,
0x0f97,
- 0x1def,
- 0x11a39,
+ 0x1cd5,
+ 0x1da5f,
0x1084,
- 0x1da22,
- 0xe01a0,
- 0x0fc6,
- 0x1cf1f,
- 0xe0157,
- 0xe0107,
- 0x0f86,
+ 0x0eb4,
+ 0x11370,
+ 0x10efe,
+ 0x1069,
+ 0x111c0,
+ 0x11834,
+ 0x119d4,
+ 0x1193c,
0x1cf1c,
- 0x1daaa,
- 0xa80b,
+ 0x1928,
+ 0x17bf,
0x1da6c,
- 0x1a62,
- 0x1da1d,
- 0x1064,
- 0xe01e7,
+ 0xe0156,
+ 0x1bf2,
+ 0x0304,
0x11ca1,
- 0x0731,
+ 0x11233,
+ 0x0859,
0x0a42,
- 0x1107f,
- 0x192a,
+ 0x1c2d,
+ 0x0738,
0x0592,
- 0x0f39,
- 0x11d47,
+ 0x1b6f,
+ 0x0355,
0x0ddd,
- 0x16f5c,
- 0x0338,
- 0x1103f,
- 0x1b40,
- 0x1182d,
- 0x1aca,
- 0x1cf0b,
- 0x1ace,
+ 0x1a71,
+ 0x0bc1,
+ 0x112df,
+ 0x1344e,
+ 0x1daac,
+ 0x1e014,
+ 0x0d44,
+ 0x1df8,
0x16f4f,
0xe01e0,
- 0xe0174,
0x1da16,
- 0x0670,
- 0x0963,
- 0x11a3d,
- 0x1921,
- 0x0320,
+ 0x11721,
+ 0x0d02,
+ 0x20e5,
+ 0x115b4,
+ 0x1b42,
+ 0x1b43,
0x0b40,
- 0xe01cb,
- 0x1da01,
+ 0xe016c,
+ 0x08ed,
0x109a,
+ 0x11303,
0x1cf35,
- 0x032a,
- 0xe013d,
- 0x11341,
- 0x0c44,
- 0x1cf11,
- 0x1ce4,
- 0x0942,
- 0xe0171,
- 0x0617,
- 0xe01b3,
- 0x1d172,
+ 0x1344a,
+ 0x17c5,
+ 0x11c39,
+ 0xa66f,
+ 0x093f,
+ 0x20d7,
+ 0x05ae,
+ 0x1cf14,
+ 0x1e016,
+ 0x08eb,
0x16f53,
0x0745,
- 0x1da36,
- 0x031f,
- 0x06e2,
+ 0x0353,
+ 0x0c3c,
+ 0x0315,
0x16f54,
- 0x180d,
- 0x09d7,
- 0xe01ae,
- 0x1da1e,
- 0x1df3,
- 0x0747,
+ 0x0eb9,
+ 0x114be,
+ 0x08cb,
+ 0x16f81,
+ 0x06db,
+ 0x07a7,
+ 0x0a4b,
0x20e6,
0x1df5,
- 0x074a,
+ 0xe01a4,
0xfe23,
- 0x1da68,
- 0x1ab8,
- 0x1ce8,
- 0x1cf0e,
+ 0x1172b,
+ 0x0dd9,
+ 0x1929,
+ 0x302f,
0x064d,
- 0x08ca,
- 0x1ded,
+ 0x0a01,
+ 0x09c8,
0x20d1,
- 0x1163f,
- 0xa953,
- 0x0318,
- 0x1a6e,
- 0x11a8e,
- 0x0a71,
- 0x116b7,
+ 0xe018f,
+ 0xa8e5,
+ 0xa8c2,
+ 0x16b31,
+ 0xa6f1,
+ 0x0f92,
+ 0x07fd,
0x094d,
0x0e4b,
0x1193e,
- 0x1143a,
+ 0xe0115,
0x093e,
0x0821,
- 0x0300,
- 0x1da47,
- 0x1cf40,
- 0xe0102,
+ 0x1cd0,
+ 0x1c2a,
+ 0x0735,
+ 0xa823,
0x05a4,
- 0x1e01f,
- 0x0311,
- 0xe01b2,
- 0x1da51,
- 0xe0178,
- 0xaac1,
- 0x0f9a,
+ 0xe0121,
+ 0xe015c,
+ 0x1a79,
+ 0x0f83,
+ 0x112e1,
+ 0xa947,
+ 0x16f5e,
0x10a06,
- 0x11cad,
- 0xa9ba,
- 0xe01b6,
- 0x1de9,
- 0x16f68,
- 0x2dec,
- 0x08d1,
- 0x0900,
+ 0x17d3,
+ 0x1d185,
+ 0x0d57,
+ 0x16f62,
+ 0x0f96,
+ 0x115b3,
+ 0x11f35,
+ 0xe0119,
0x16f7d,
- 0x11a54,
- 0xe017c,
- 0x1dd4,
- 0x1da60,
- 0xa8bb,
- 0x116b3,
+ 0xfe02,
+ 0x0c46,
+ 0x1cf44,
+ 0x2de0,
+ 0xaa2e,
+ 0x111ba,
+ 0x110b4,
0x1e8d2,
- 0x11c9d,
+ 0x11c92,
0x1d169,
- 0x1713,
- 0xa8be,
- 0x11a94,
+ 0x035f,
+ 0x0740,
0x1cdc,
- 0x1e00e,
- 0x10d24,
+ 0x1122d,
+ 0x2de8,
+ 0x0748,
0x0ec9,
- 0x05a2,
- 0x0711,
- 0xaa2a,
- 0x0e37,
+ 0x1a63,
+ 0x1da5c,
+ 0x1b35,
+ 0x0cc2,
0x1112c,
- 0x08ee,
+ 0xe0113,
0x06da,
0x1922,
- 0x10a01,
- 0x1da62,
- 0x1ce5,
- 0x1cf3b,
- 0x11435,
- 0x0cc0,
- 0x17c1,
+ 0x2de3,
+ 0x18a9,
+ 0x1ba9,
+ 0x08cc,
+ 0x11a57,
+ 0x102f,
+ 0x0737,
0x0652,
- 0x1da3c,
- 0x1daab,
- 0x0cc1,
- 0x0b82,
- 0x07a6,
- 0x11640,
- 0x1b71,
- 0x0655,
+ 0x10a0d,
+ 0x05b4,
+ 0x11000,
+ 0x0fa7,
+ 0x06e3,
+ 0x1bf3,
+ 0xe01a6,
+ 0x0352,
0x0305,
- 0x1c2e,
- 0x0cca,
- 0x1cf20,
- 0x1c31,
+ 0x0f82,
+ 0xe0172,
+ 0x11235,
+ 0x0d43,
0x106a,
- 0x08e5,
- 0x1d1ac,
- 0x1da21,
- 0xe01eb,
+ 0x20e8,
+ 0x11c94,
+ 0x1b6e,
+ 0x05b1,
0x0614,
+ 0x08fb,
0x11132,
- 0x11931,
- 0x0343,
+ 0x103b,
0x110b9,
- 0x1039,
- 0xa94b,
+ 0x112e8,
+ 0x1b6b,
0x1da6b,
- 0xa8f1,
+ 0x1c2c,
+ 0x1b3a,
0xe01bc,
- 0x0a82,
+ 0x1da64,
0x1085,
- 0x101fd,
- 0x05b1,
+ 0x1da45,
0x11d36,
- 0xa66f,
- 0x0bcb,
- 0x1060,
- 0x16f57,
+ 0x20f0,
+ 0x1da0f,
+ 0x0899,
+ 0xe01d9,
0x031e,
0x0fa5,
+ 0x1182c,
0xe01a1,
0xe01c6,
- 0x11cb1,
- 0xe010e,
+ 0x0350,
+ 0x13452,
0x1ce3,
- 0x1de2,
+ 0x2de1,
0x2dfc,
- 0xe0128,
0x1da4a,
- 0x1e015,
- 0xe019b,
- 0x20db,
+ 0x1cf04,
+ 0x16f63,
+ 0x1d189,
+ 0xe0101,
0xe014d,
0x11a92,
- 0x0eb1,
- 0xe01a7,
+ 0x0817,
+ 0x11c31,
0x11040,
- 0x11c3d,
- 0x1da4d,
+ 0xe01df,
+ 0x1e021,
0x11302,
0xe01e1,
- 0x0651,
- 0x1da17,
- 0x1920,
- 0x11cb2,
+ 0xe0166,
+ 0x11a34,
+ 0x111cc,
+ 0xaaec,
0x0962,
- 0x1abe,
- 0xe0163,
- 0x031c,
- 0x0356,
+ 0xfe07,
+ 0x1cf16,
+ 0x1bef,
+ 0x08ea,
0x1e011,
- 0x1cf06,
- 0x1d170,
- 0x07f3,
- 0x116b2,
- 0x1ce1,
+ 0x0f7e,
+ 0x1daa7,
+ 0x1937,
+ 0xe016d,
+ 0x1dee,
0xfe28,
- 0xe01c4,
- 0x08da,
- 0x20d5,
- 0x1cf12,
- 0xabe6,
+ 0x085b,
+ 0xa94a,
+ 0x1dd5,
+ 0x1dea,
+ 0x1a6f,
0xfe03,
- 0x1dfa,
- 0x11439,
- 0x11837,
- 0x093f,
- 0x1cf41,
- 0xe0131,
- 0x1145e,
- 0x1daa4,
- 0x0a02,
- 0x07a8,
- 0x0734,
- 0x1112e,
- 0x114b3,
- 0x1122c,
- 0x0594,
- 0x1e020,
- 0xe0125,
- 0x1e2ed,
- 0xe0104,
- 0x07f2,
- 0x0c4d,
- 0x1772,
- 0x1bab,
- 0x17cb,
- 0x0613,
- 0x0f91,
- 0x111ba,
- 0x1abb,
- 0x16f7c,
+ 0x1a75,
+ 0x06ea,
+ 0x16f7e,
+ 0x0f37,
+ 0x1182f,
+ 0x059f,
+ 0x1da69,
+ 0x0fac,
+ 0x0c3f,
+ 0x0d41,
+ 0x16f84,
+ 0x0fae,
+ 0xe0168,
+ 0x0c44,
+ 0x034e,
+ 0x08fc,
+ 0x05bf,
+ 0x0dd0,
+ 0x1bf0,
+ 0x2cef,
+ 0x1ab3,
+ 0x0d3f,
+ 0x1cf2b,
+ 0xa8c0,
+ 0x1a5c,
+ 0x16f67,
+ 0x1daaa,
+ 0xe016f,
+ 0x1da84,
+ 0x2df2,
0x05a9,
- 0x1d188,
+ 0xe013d,
0x0c43,
- 0xa8c3,
- 0x08f3,
+ 0x1da36,
+ 0xe0103,
0x08fd,
- 0x1193b,
- 0x0a4c,
- 0x1089,
- 0x11839,
- 0xa8e8,
+ 0x0fba,
+ 0x0ec8,
+ 0x1da1f,
+ 0xa9b5,
+ 0x1be8,
0xfe2b,
0x108d,
0x06d9,
- 0x11a95,
- 0x16f61,
- 0xe011c,
- 0x1753,
+ 0x1cdd,
+ 0x0816,
+ 0xa676,
+ 0x0818,
0x16f5f,
- 0x1133b,
+ 0x0fa8,
0x0f9b,
0x0f9d,
- 0x1bed,
- 0x0330,
- 0xe011e,
- 0x1062,
+ 0x0e31,
+ 0x11a91,
+ 0x0611,
+ 0x0b4b,
0x0b57,
- 0xa8bf,
- 0xe0156,
- 0x1da5d,
- 0x1cd0,
+ 0xe015d,
+ 0x108f,
+ 0x1e001,
+ 0x17ca,
+ 0x08e1,
0x1bc9d,
- 0xe01ed,
- 0x1da23,
- 0x035f,
- 0x11d94,
- 0x1dc5,
+ 0x2df1,
+ 0x0b42,
+ 0x081e,
+ 0x16f59,
+ 0xfe20,
0x0597,
- 0x030b,
- 0x114bb,
+ 0x1cf01,
0x1038,
0x035a,
- 0x1e027,
- 0x1c37,
- 0xaa43,
- 0x11441,
- 0x302e,
- 0x10a0c,
- 0xe015d,
- 0x1dfb,
- 0x11a53,
- 0xe01ac,
- 0x0f19,
- 0x1d168,
- 0x1b02,
+ 0xe0196,
+ 0x1a6e,
+ 0x1daa5,
+ 0x0321,
+ 0x1da51,
+ 0x17d2,
+ 0x1daad,
+ 0x033a,
+ 0x1056,
+ 0x1ab1,
+ 0x0dcf,
+ 0x1e947,
+ 0x0300,
+ 0x10d24,
0x10a02,
0x11342,
- 0x1ab3,
- 0x11442,
- 0x0c46,
+ 0x1ce7,
+ 0x031f,
+ 0x1073,
0x0653,
- 0x111bb,
+ 0x0fb2,
0x11a33,
0xe01cc,
0x1da02,
- 0x11440,
+ 0xe0133,
0x2de2,
- 0xa9c0,
- 0x11082,
- 0xe0101,
- 0x0abc,
+ 0x0333,
+ 0x0a71,
+ 0xe01eb,
+ 0x11d96,
0x0612,
0xa8b8,
- 0xe0124,
- 0xa951,
- 0x059e,
- 0x11632,
- 0x1cd6,
- 0x17bb,
- 0x119e4,
- 0x1112d,
- 0x0cc2,
+ 0x08e8,
+ 0x11ca6,
+ 0x1de8,
+ 0x1da4f,
+ 0x07a8,
+ 0x0e39,
+ 0xa982,
+ 0x036e,
+ 0x193a,
0x16f91,
- 0x20d3,
- 0x0c41,
- 0x1171f,
+ 0x10d27,
+ 0x0f78,
+ 0x035d,
0x1da2f,
- 0x1e945,
- 0x1033,
- 0x111b4,
+ 0x11a36,
+ 0xaab0,
+ 0xfe0e,
+ 0x05ad,
0x1dd6,
- 0x1733,
+ 0xe0142,
0x1dfd,
- 0x119dd,
0x1122f,
- 0x111b6,
- 0x1b03,
- 0x11c32,
- 0xa8b4,
- 0x0742,
- 0x0358,
- 0xe01bd,
- 0x036a,
- 0x0f8d,
- 0x11131,
+ 0x08e4,
+ 0xaa7c,
+ 0x1b3b,
+ 0x0b48,
+ 0x05bc,
+ 0xa8ee,
+ 0x11c97,
+ 0x110b8,
+ 0xe01b2,
+ 0xe0122,
+ 0x11a8e,
0x11a58,
- 0xfe07,
- 0x11c2f,
- 0x0ebb,
- 0x11934,
- 0x2de0,
- 0x11639,
- 0x1e946,
- 0x11ef5,
+ 0x036b,
+ 0x0331,
+ 0x16f71,
+ 0x1143e,
+ 0x110ba,
+ 0x1112e,
+ 0x089b,
0x1ac1,
+ 0xe0143,
0x07ed,
- 0x114b2,
- 0x0944,
- 0x11a98,
- 0x115b0,
- 0x1d17e,
- 0x09e2,
- 0x1da61,
- 0x0353,
- 0x1e016,
- 0xe01aa,
- 0x20da,
- 0xe0170,
+ 0xa674,
+ 0x2df0,
+ 0x1da62,
+ 0xa8bd,
+ 0x1b3d,
+ 0x11d3c,
+ 0xe014b,
+ 0xaa32,
+ 0x11a51,
+ 0x16f92,
+ 0x1d166,
+ 0x0cc8,
+ 0x1dca,
0xe01b8,
- 0x10a3a,
- 0x11a8d,
- 0x073f,
- 0x06e0,
- 0x1c33,
- 0x0328,
- 0x1da2a,
- 0xe010f,
- 0x1cf19,
- 0x16ff0,
- 0x1e136,
- 0x1da1f,
- 0x1cf29,
- 0x20ec,
- 0x0cc6,
+ 0x1ac8,
+ 0x17c9,
+ 0xfe08,
+ 0x0338,
+ 0x1de7,
+ 0xe018d,
+ 0xa69e,
+ 0x1da4c,
+ 0x07f3,
+ 0x16b35,
+ 0x0a51,
+ 0xa825,
+ 0x1071,
+ 0x11f3f,
0x0348,
- 0x0c3e,
+ 0x116b7,
+ 0x09c3,
0x1e2ee,
- 0x05ae,
0x0e34,
- 0x09c7,
- 0x1a19,
- 0x1bea,
+ 0x036d,
+ 0xabe9,
+ 0x1cf7,
0x1935,
- 0x1cf3e,
- 0x061a,
- 0x0f77,
- 0x0ac5,
- 0xa8c4,
- 0x1c24,
+ 0x05aa,
+ 0x1103f,
+ 0x11a09,
+ 0x1da3f,
+ 0x108a,
+ 0x16f5c,
+ 0x20d6,
0x07eb,
- 0x0957,
- 0x1da64,
- 0x0d02,
- 0xaa34,
- 0x0d3c,
- 0x0901,
+ 0xfe2a,
+ 0xe0193,
+ 0x11d40,
+ 0x05b9,
+ 0x0f7d,
+ 0x16f5a,
0xe0197,
0x09cd,
0x0fb5,
0x1da07,
0xe01d1,
- 0x102e,
- 0xe016c,
- 0x110b1,
+ 0xa880,
+ 0x1a7c,
+ 0x11ca5,
0x09cb,
- 0x11834,
- 0x11932,
+ 0x0fb3,
+ 0x0825,
0x1103a,
0x0827,
0x1e94a,
@@ -33403,7 +33693,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{0CDD}'..='\u{0CDE}'
| '\u{0CE0}'..='\u{0CE3}'
| '\u{0CE6}'..='\u{0CEF}'
- | '\u{0CF1}'..='\u{0CF2}'
+ | '\u{0CF1}'..='\u{0CF3}'
| '\u{0D00}'..='\u{0D0C}'
| '\u{0D0E}'..='\u{0D10}'
| '\u{0D12}'..='\u{0D44}'
@@ -33433,7 +33723,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{0EA7}'..='\u{0EBD}'
| '\u{0EC0}'..='\u{0EC4}'
| '\u{0EC6}'
- | '\u{0EC8}'..='\u{0ECD}'
+ | '\u{0EC8}'..='\u{0ECE}'
| '\u{0ED0}'..='\u{0ED9}'
| '\u{0EDC}'..='\u{0EDF}'
| '\u{0F00}'..='\u{0F47}'
@@ -33704,7 +33994,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{10E80}'..='\u{10EA9}'
| '\u{10EAB}'..='\u{10EAD}'
| '\u{10EB0}'..='\u{10EB1}'
- | '\u{10F00}'..='\u{10F27}'
+ | '\u{10EFD}'..='\u{10F27}'
| '\u{10F30}'..='\u{10F59}'
| '\u{10F70}'..='\u{10F89}'
| '\u{10FB0}'..='\u{10FCB}'
@@ -33721,7 +34011,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{11180}'..='\u{111DF}'
| '\u{111E1}'..='\u{111F4}'
| '\u{11200}'..='\u{11211}'
- | '\u{11213}'..='\u{1123E}'
+ | '\u{11213}'..='\u{11241}'
| '\u{11280}'..='\u{11286}'
| '\u{11288}'
| '\u{1128A}'..='\u{1128D}'
@@ -33774,6 +34064,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{11A00}'..='\u{11A47}'
| '\u{11A50}'..='\u{11AA2}'
| '\u{11AB0}'..='\u{11AF8}'
+ | '\u{11B00}'..='\u{11B09}'
| '\u{11C00}'..='\u{11C08}'
| '\u{11C0A}'..='\u{11C36}'
| '\u{11C38}'..='\u{11C45}'
@@ -33795,6 +34086,9 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{11D93}'..='\u{11D98}'
| '\u{11DA0}'..='\u{11DA9}'
| '\u{11EE0}'..='\u{11EF8}'
+ | '\u{11F00}'..='\u{11F10}'
+ | '\u{11F12}'..='\u{11F3A}'
+ | '\u{11F3E}'..='\u{11F59}'
| '\u{11FB0}'
| '\u{11FC0}'..='\u{11FF1}'
| '\u{11FFF}'..='\u{12399}'
@@ -33802,8 +34096,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{12470}'..='\u{12474}'
| '\u{12480}'..='\u{12543}'
| '\u{12F90}'..='\u{12FF2}'
- | '\u{13000}'..='\u{1342E}'
- | '\u{13430}'..='\u{13438}'
+ | '\u{13000}'..='\u{13455}'
| '\u{14400}'..='\u{14646}'
| '\u{16800}'..='\u{16A38}'
| '\u{16A40}'..='\u{16A5E}'
@@ -33830,7 +34123,9 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1AFF5}'..='\u{1AFFB}'
| '\u{1AFFD}'..='\u{1AFFE}'
| '\u{1B000}'..='\u{1B122}'
+ | '\u{1B132}'
| '\u{1B150}'..='\u{1B152}'
+ | '\u{1B155}'
| '\u{1B164}'..='\u{1B167}'
| '\u{1B170}'..='\u{1B2FB}'
| '\u{1BC00}'..='\u{1BC6A}'
@@ -33845,6 +34140,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1D100}'..='\u{1D126}'
| '\u{1D129}'..='\u{1D1EA}'
| '\u{1D200}'..='\u{1D245}'
+ | '\u{1D2C0}'..='\u{1D2D3}'
| '\u{1D2E0}'..='\u{1D2F3}'
| '\u{1D300}'..='\u{1D356}'
| '\u{1D360}'..='\u{1D378}'
@@ -33872,11 +34168,14 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1DA9B}'..='\u{1DA9F}'
| '\u{1DAA1}'..='\u{1DAAF}'
| '\u{1DF00}'..='\u{1DF1E}'
+ | '\u{1DF25}'..='\u{1DF2A}'
| '\u{1E000}'..='\u{1E006}'
| '\u{1E008}'..='\u{1E018}'
| '\u{1E01B}'..='\u{1E021}'
| '\u{1E023}'..='\u{1E024}'
| '\u{1E026}'..='\u{1E02A}'
+ | '\u{1E030}'..='\u{1E06D}'
+ | '\u{1E08F}'
| '\u{1E100}'..='\u{1E12C}'
| '\u{1E130}'..='\u{1E13D}'
| '\u{1E140}'..='\u{1E149}'
@@ -33884,6 +34183,7 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1E290}'..='\u{1E2AE}'
| '\u{1E2C0}'..='\u{1E2F9}'
| '\u{1E2FF}'
+ | '\u{1E4D0}'..='\u{1E4F9}'
| '\u{1E7E0}'..='\u{1E7E6}'
| '\u{1E7E8}'..='\u{1E7EB}'
| '\u{1E7ED}'..='\u{1E7EE}'
@@ -33942,10 +34242,10 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1F250}'..='\u{1F251}'
| '\u{1F260}'..='\u{1F265}'
| '\u{1F300}'..='\u{1F6D7}'
- | '\u{1F6DD}'..='\u{1F6EC}'
+ | '\u{1F6DC}'..='\u{1F6EC}'
| '\u{1F6F0}'..='\u{1F6FC}'
- | '\u{1F700}'..='\u{1F773}'
- | '\u{1F780}'..='\u{1F7D8}'
+ | '\u{1F700}'..='\u{1F776}'
+ | '\u{1F77B}'..='\u{1F7D9}'
| '\u{1F7E0}'..='\u{1F7EB}'
| '\u{1F7F0}'
| '\u{1F800}'..='\u{1F80B}'
@@ -33956,25 +34256,24 @@ pub fn is_public_assigned(c: char) -> bool {
| '\u{1F8B0}'..='\u{1F8B1}'
| '\u{1F900}'..='\u{1FA53}'
| '\u{1FA60}'..='\u{1FA6D}'
- | '\u{1FA70}'..='\u{1FA74}'
- | '\u{1FA78}'..='\u{1FA7C}'
- | '\u{1FA80}'..='\u{1FA86}'
- | '\u{1FA90}'..='\u{1FAAC}'
- | '\u{1FAB0}'..='\u{1FABA}'
- | '\u{1FAC0}'..='\u{1FAC5}'
- | '\u{1FAD0}'..='\u{1FAD9}'
- | '\u{1FAE0}'..='\u{1FAE7}'
- | '\u{1FAF0}'..='\u{1FAF6}'
+ | '\u{1FA70}'..='\u{1FA7C}'
+ | '\u{1FA80}'..='\u{1FA88}'
+ | '\u{1FA90}'..='\u{1FABD}'
+ | '\u{1FABF}'..='\u{1FAC5}'
+ | '\u{1FACE}'..='\u{1FADB}'
+ | '\u{1FAE0}'..='\u{1FAE8}'
+ | '\u{1FAF0}'..='\u{1FAF8}'
| '\u{1FB00}'..='\u{1FB92}'
| '\u{1FB94}'..='\u{1FBCA}'
| '\u{1FBF0}'..='\u{1FBF9}'
| '\u{20000}'..='\u{2A6DF}'
- | '\u{2A700}'..='\u{2B738}'
+ | '\u{2A700}'..='\u{2B739}'
| '\u{2B740}'..='\u{2B81D}'
| '\u{2B820}'..='\u{2CEA1}'
| '\u{2CEB0}'..='\u{2EBE0}'
| '\u{2F800}'..='\u{2FA1D}'
| '\u{30000}'..='\u{3134A}'
+ | '\u{31350}'..='\u{323AF}'
| '\u{E0001}'
| '\u{E0020}'..='\u{E007F}'
| '\u{E0100}'..='\u{E01EF}'
@@ -34461,6 +34760,7 @@ pub fn qc_nfkc(c: char) -> IsNormalized {
'\u{1D7C3}' => No,
'\u{1D7C4}'...'\u{1D7CB}' => No,
'\u{1D7CE}'...'\u{1D7FF}' => No,
+ '\u{1E030}'...'\u{1E06D}' => No,
'\u{1EE00}'...'\u{1EE03}' => No,
'\u{1EE05}'...'\u{1EE1F}' => No,
'\u{1EE21}'...'\u{1EE22}' => No,
@@ -35310,6 +35610,7 @@ pub fn qc_nfkd(c: char) -> IsNormalized {
'\u{1D7C3}' => No,
'\u{1D7C4}'...'\u{1D7CB}' => No,
'\u{1D7CE}'...'\u{1D7FF}' => No,
+ '\u{1E030}'...'\u{1E06D}' => No,
'\u{1EE00}'...'\u{1EE03}' => No,
'\u{1EE05}'...'\u{1EE1F}' => No,
'\u{1EE21}'...'\u{1EE22}' => No,
diff --git a/vendor/unicode-script/.cargo-checksum.json b/vendor/unicode-script/.cargo-checksum.json
index 44c6c80d2..1bd2141e0 100644
--- a/vendor/unicode-script/.cargo-checksum.json
+++ b/vendor/unicode-script/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"3b6e9ba98b2f20b8b8a13f2e961a78691a064dcd1ae0d5bcfaf26216b2bb9c68","README.md":"14f5fffdc485176a2ab2e04555231042d0f7d818dbf1a0749a1ecbd8a0d4d500","scripts/unicode.py":"53803e407327679983929fbbdaf874c44c21b6f775eb48690dd52528dd3f4a51","src/lib.rs":"1e67da407be73a423a1de030f1397864aa454925a8582e027e9a9246529bf0b6","src/tables.rs":"6303916c60cee9abfa380b345536177415f042f36df3479d35c17b3587e65479"},"package":"098ec66172ce21cd55f8bcc786ee209dd20e04eff70acfca30cb79924d173ae9"} \ No newline at end of file
+{"files":{"Cargo.toml":"dce5bd5ce9da2e852b95c7c96ef36d7e70c36bf15eff3052a3fcb9ba9f8d3af5","LICENSE-APACHE":"7cbb56d1b5d83d735056b363ab20958524120afafc4ad8206e6be98cdec5d737","LICENSE-MIT":"7ad3ea8ca3caf894db98c3f31d5d4949173ffa93c883ef19a9e529ad48960f8c","README.md":"9d922b2906be36f007f89c6f4eae8976d90a01be8181928698a121b154bbb016","scripts/unicode.py":"ce98a6f184b6d4c44c855b80d92d6d570a42535df840a44be4eecd47d6320aea","src/lib.rs":"d2476ef2fbc805c9a34110dce7415b4ba21de7da6e19470a1b856966564e905f","src/tables.rs":"e78188904a06dc06a59ad4e8c30990060f06c3d8e5871437d531389fa5aabade"},"package":"7d817255e1bed6dfd4ca47258685d14d2bdcfbc64fdc9e3819bd5848057b8ecc"} \ No newline at end of file
diff --git a/vendor/unicode-script/Cargo.toml b/vendor/unicode-script/Cargo.toml
index 6dfc01148..c2647d3ab 100644
--- a/vendor/unicode-script/Cargo.toml
+++ b/vendor/unicode-script/Cargo.toml
@@ -3,26 +3,38 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "unicode-script"
-version = "0.5.3"
+version = "0.5.5"
authors = ["Manish Goregaokar <manishsmail@gmail.com>"]
-exclude = ["target/*", "Cargo.lock", "scripts/tmp", "*.txt"]
-description = "This crate exposes the Unicode `Script` and `Script_Extension` properties from [UAX #24](http://www.unicode.org/reports/tr24/)\n"
+exclude = [
+ "target/*",
+ "Cargo.lock",
+ "scripts/tmp",
+ "*.txt",
+]
+description = """
+This crate exposes the Unicode `Script` and `Script_Extension` properties from [UAX #24](http://www.unicode.org/reports/tr24/)
+"""
homepage = "https://github.com/unicode-rs/unicode-script"
documentation = "https://docs.rs/unicode-script"
readme = "README.md"
-keywords = ["text", "unicode", "script", "language"]
+keywords = [
+ "text",
+ "unicode",
+ "script",
+ "language",
+]
license = "MIT/Apache-2.0"
repository = "https://github.com/unicode-rs/unicode-script"
+
[dependencies.compiler_builtins]
version = "0.1"
optional = true
@@ -39,4 +51,8 @@ package = "rustc-std-workspace-std"
[features]
bench = []
-rustc-dep-of-std = ["std", "core", "compiler_builtins"]
+rustc-dep-of-std = [
+ "std",
+ "core",
+ "compiler_builtins",
+]
diff --git a/vendor/unicode-script/LICENSE-APACHE b/vendor/unicode-script/LICENSE-APACHE
new file mode 100644
index 000000000..aa718b553
--- /dev/null
+++ b/vendor/unicode-script/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 2021 The Unicode-rs 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
+
+ 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/xflags/LICENSE-MIT b/vendor/unicode-script/LICENSE-MIT
index 31aa79387..20c28a2ce 100644
--- a/vendor/xflags/LICENSE-MIT
+++ b/vendor/unicode-script/LICENSE-MIT
@@ -1,23 +1,27 @@
-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.
+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/unicode-script/README.md b/vendor/unicode-script/README.md
index 85fd60b11..0afbce69b 100644
--- a/vendor/unicode-script/README.md
+++ b/vendor/unicode-script/README.md
@@ -1,7 +1,7 @@
# unicode-script
[![Build Status](https://github.com/unicode-rs/unicode-script/workflows/Tests/badge.svg)](https://github.com/unicode-rs/unicode-script/actions)
-[![Current Version](https://meritbadge.herokuapp.com/unicode-script)](https://crates.io/crates/unicode-script)
+[![Current Version](https://img.shields.io/crates/v/unicode-script.svg)](https://crates.io/crates/unicode-script)
[![License: MIT/Apache-2.0](https://img.shields.io/crates/l/unicode-script.svg)](#license)
-This crate exposes the Unicode `Script` and `Script_Extension` properties from [UAX #24](http://www.unicode.org/reports/tr24/) \ No newline at end of file
+This crate exposes the Unicode `Script` and `Script_Extension` properties from [UAX #24](http://www.unicode.org/reports/tr24/)
diff --git a/vendor/unicode-script/scripts/unicode.py b/vendor/unicode-script/scripts/unicode.py
index e40a92c6d..7b5c75c72 100644
--- a/vendor/unicode-script/scripts/unicode.py
+++ b/vendor/unicode-script/scripts/unicode.py
@@ -46,7 +46,7 @@ ending='''
}
'''
-UNICODE_VERSION = (13, 0, 0)
+UNICODE_VERSION = (15, 0, 0)
UNICODE_VERSION_NUMBER = "%s.%s.%s" %UNICODE_VERSION
@@ -59,7 +59,7 @@ def fetch(f):
os.system("curl -O https://www.unicode.org/Public/emoji/%s.%s/%s"
% (UNICODE_VERSION[0], UNICODE_VERSION[1], f))
else:
- os.system("curl -O http://www.unicode.org/Public/%s/ucd/%s"
+ os.system("curl -O https://www.unicode.org/Public/%s/ucd/%s"
% (UNICODE_VERSION_NUMBER, f))
if not os.path.exists(os.path.basename(f)):
diff --git a/vendor/unicode-script/src/lib.rs b/vendor/unicode-script/src/lib.rs
index d650ee0b2..63f129069 100644
--- a/vendor/unicode-script/src/lib.rs
+++ b/vendor/unicode-script/src/lib.rs
@@ -144,20 +144,20 @@ pub struct ScriptExtension {
// A bitset for the scripts 65-128
second: u64,
// A bitset for scripts after 128
- third: u32,
+ third: u64,
// Both Common and Inherited are represented by all used bits being set,
// this flag lets us distinguish the two.
common: bool,
}
impl ScriptExtension {
- // We don't use the complete u32 of `third`, so the "all" value is not just u32::MAX
+ // We don't use the complete u64 of `third`, so the "all" value is not just u32::MAX
// Instead, we take the number of the next (unused) script bit, subtract 128 to bring
- // it in the range of `third`, create a u32 with just that bit set, and subtract 1
+ // it in the range of `third`, create a u64 with just that bit set, and subtract 1
// to create one with all the lower bits set.
- const THIRD_MAX: u32 = ((1 << (NEXT_SCRIPT - 128)) - 1);
+ const THIRD_MAX: u64 = ((1 << (NEXT_SCRIPT - 128)) - 1);
- pub(crate) const fn new(first: u64, second: u64, third: u32) -> Self {
+ pub(crate) const fn new(first: u64, second: u64, third: u64) -> Self {
ScriptExtension {
first,
second,
diff --git a/vendor/unicode-script/src/tables.rs b/vendor/unicode-script/src/tables.rs
index e31a7229f..41035fcdc 100644
--- a/vendor/unicode-script/src/tables.rs
+++ b/vendor/unicode-script/src/tables.rs
@@ -20,7 +20,7 @@ use crate::ScriptExtension;
/// The version of [Unicode](http://www.unicode.org/)
/// that this version of unicode-script is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (13, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0);
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[non_exhaustive]
@@ -84,266 +84,280 @@ pub enum Script {
Chorasmian = 23,
/// Copt
Coptic = 24,
+ /// Cpmn
+ Cypro_Minoan = 25,
/// Cprt
- Cypriot = 25,
+ Cypriot = 26,
/// Cyrl
- Cyrillic = 26,
+ Cyrillic = 27,
/// Deva
- Devanagari = 27,
+ Devanagari = 28,
/// Diak
- Dives_Akuru = 28,
+ Dives_Akuru = 29,
/// Dogr
- Dogra = 29,
+ Dogra = 30,
/// Dsrt
- Deseret = 30,
+ Deseret = 31,
/// Dupl
- Duployan = 31,
+ Duployan = 32,
/// Egyp
- Egyptian_Hieroglyphs = 32,
+ Egyptian_Hieroglyphs = 33,
/// Elba
- Elbasan = 33,
+ Elbasan = 34,
/// Elym
- Elymaic = 34,
+ Elymaic = 35,
/// Ethi
- Ethiopic = 35,
+ Ethiopic = 36,
/// Geor
- Georgian = 36,
+ Georgian = 37,
/// Glag
- Glagolitic = 37,
+ Glagolitic = 38,
/// Gong
- Gunjala_Gondi = 38,
+ Gunjala_Gondi = 39,
/// Gonm
- Masaram_Gondi = 39,
+ Masaram_Gondi = 40,
/// Goth
- Gothic = 40,
+ Gothic = 41,
/// Gran
- Grantha = 41,
+ Grantha = 42,
/// Grek
- Greek = 42,
+ Greek = 43,
/// Gujr
- Gujarati = 43,
+ Gujarati = 44,
/// Guru
- Gurmukhi = 44,
+ Gurmukhi = 45,
/// Hang
- Hangul = 45,
+ Hangul = 46,
/// Hani
- Han = 46,
+ Han = 47,
/// Hano
- Hanunoo = 47,
+ Hanunoo = 48,
/// Hatr
- Hatran = 48,
+ Hatran = 49,
/// Hebr
- Hebrew = 49,
+ Hebrew = 50,
/// Hira
- Hiragana = 50,
+ Hiragana = 51,
/// Hluw
- Anatolian_Hieroglyphs = 51,
+ Anatolian_Hieroglyphs = 52,
/// Hmng
- Pahawh_Hmong = 52,
+ Pahawh_Hmong = 53,
/// Hmnp
- Nyiakeng_Puachue_Hmong = 53,
+ Nyiakeng_Puachue_Hmong = 54,
/// Hung
- Old_Hungarian = 54,
+ Old_Hungarian = 55,
/// Ital
- Old_Italic = 55,
+ Old_Italic = 56,
/// Java
- Javanese = 56,
+ Javanese = 57,
/// Kali
- Kayah_Li = 57,
+ Kayah_Li = 58,
/// Kana
- Katakana = 58,
+ Katakana = 59,
+ /// Kawi
+ Kawi = 60,
/// Khar
- Kharoshthi = 59,
+ Kharoshthi = 61,
/// Khmr
- Khmer = 60,
+ Khmer = 62,
/// Khoj
- Khojki = 61,
+ Khojki = 63,
/// Kits
- Khitan_Small_Script = 62,
+ Khitan_Small_Script = 64,
/// Knda
- Kannada = 63,
+ Kannada = 65,
/// Kthi
- Kaithi = 64,
+ Kaithi = 66,
/// Lana
- Tai_Tham = 65,
+ Tai_Tham = 67,
/// Laoo
- Lao = 66,
+ Lao = 68,
/// Latn
- Latin = 67,
+ Latin = 69,
/// Lepc
- Lepcha = 68,
+ Lepcha = 70,
/// Limb
- Limbu = 69,
+ Limbu = 71,
/// Lina
- Linear_A = 70,
+ Linear_A = 72,
/// Linb
- Linear_B = 71,
+ Linear_B = 73,
/// Lisu
- Lisu = 72,
+ Lisu = 74,
/// Lyci
- Lycian = 73,
+ Lycian = 75,
/// Lydi
- Lydian = 74,
+ Lydian = 76,
/// Mahj
- Mahajani = 75,
+ Mahajani = 77,
/// Maka
- Makasar = 76,
+ Makasar = 78,
/// Mand
- Mandaic = 77,
+ Mandaic = 79,
/// Mani
- Manichaean = 78,
+ Manichaean = 80,
/// Marc
- Marchen = 79,
+ Marchen = 81,
/// Medf
- Medefaidrin = 80,
+ Medefaidrin = 82,
/// Mend
- Mende_Kikakui = 81,
+ Mende_Kikakui = 83,
/// Merc
- Meroitic_Cursive = 82,
+ Meroitic_Cursive = 84,
/// Mero
- Meroitic_Hieroglyphs = 83,
+ Meroitic_Hieroglyphs = 85,
/// Mlym
- Malayalam = 84,
+ Malayalam = 86,
/// Modi
- Modi = 85,
+ Modi = 87,
/// Mong
- Mongolian = 86,
+ Mongolian = 88,
/// Mroo
- Mro = 87,
+ Mro = 89,
/// Mtei
- Meetei_Mayek = 88,
+ Meetei_Mayek = 90,
/// Mult
- Multani = 89,
+ Multani = 91,
/// Mymr
- Myanmar = 90,
+ Myanmar = 92,
+ /// Nagm
+ Nag_Mundari = 93,
/// Nand
- Nandinagari = 91,
+ Nandinagari = 94,
/// Narb
- Old_North_Arabian = 92,
+ Old_North_Arabian = 95,
/// Nbat
- Nabataean = 93,
+ Nabataean = 96,
/// Newa
- Newa = 94,
+ Newa = 97,
/// Nkoo
- Nko = 95,
+ Nko = 98,
/// Nshu
- Nushu = 96,
+ Nushu = 99,
/// Ogam
- Ogham = 97,
+ Ogham = 100,
/// Olck
- Ol_Chiki = 98,
+ Ol_Chiki = 101,
/// Orkh
- Old_Turkic = 99,
+ Old_Turkic = 102,
/// Orya
- Oriya = 100,
+ Oriya = 103,
/// Osge
- Osage = 101,
+ Osage = 104,
/// Osma
- Osmanya = 102,
+ Osmanya = 105,
+ /// Ougr
+ Old_Uyghur = 106,
/// Palm
- Palmyrene = 103,
+ Palmyrene = 107,
/// Pauc
- Pau_Cin_Hau = 104,
+ Pau_Cin_Hau = 108,
/// Perm
- Old_Permic = 105,
+ Old_Permic = 109,
/// Phag
- Phags_Pa = 106,
+ Phags_Pa = 110,
/// Phli
- Inscriptional_Pahlavi = 107,
+ Inscriptional_Pahlavi = 111,
/// Phlp
- Psalter_Pahlavi = 108,
+ Psalter_Pahlavi = 112,
/// Phnx
- Phoenician = 109,
+ Phoenician = 113,
/// Plrd
- Miao = 110,
+ Miao = 114,
/// Prti
- Inscriptional_Parthian = 111,
+ Inscriptional_Parthian = 115,
/// Rjng
- Rejang = 112,
+ Rejang = 116,
/// Rohg
- Hanifi_Rohingya = 113,
+ Hanifi_Rohingya = 117,
/// Runr
- Runic = 114,
+ Runic = 118,
/// Samr
- Samaritan = 115,
+ Samaritan = 119,
/// Sarb
- Old_South_Arabian = 116,
+ Old_South_Arabian = 120,
/// Saur
- Saurashtra = 117,
+ Saurashtra = 121,
/// Sgnw
- SignWriting = 118,
+ SignWriting = 122,
/// Shaw
- Shavian = 119,
+ Shavian = 123,
/// Shrd
- Sharada = 120,
+ Sharada = 124,
/// Sidd
- Siddham = 121,
+ Siddham = 125,
/// Sind
- Khudawadi = 122,
+ Khudawadi = 126,
/// Sinh
- Sinhala = 123,
+ Sinhala = 127,
/// Sogd
- Sogdian = 124,
+ Sogdian = 128,
/// Sogo
- Old_Sogdian = 125,
+ Old_Sogdian = 129,
/// Sora
- Sora_Sompeng = 126,
+ Sora_Sompeng = 130,
/// Soyo
- Soyombo = 127,
+ Soyombo = 131,
/// Sund
- Sundanese = 128,
+ Sundanese = 132,
/// Sylo
- Syloti_Nagri = 129,
+ Syloti_Nagri = 133,
/// Syrc
- Syriac = 130,
+ Syriac = 134,
/// Tagb
- Tagbanwa = 131,
+ Tagbanwa = 135,
/// Takr
- Takri = 132,
+ Takri = 136,
/// Tale
- Tai_Le = 133,
+ Tai_Le = 137,
/// Talu
- New_Tai_Lue = 134,
+ New_Tai_Lue = 138,
/// Taml
- Tamil = 135,
+ Tamil = 139,
/// Tang
- Tangut = 136,
+ Tangut = 140,
/// Tavt
- Tai_Viet = 137,
+ Tai_Viet = 141,
/// Telu
- Telugu = 138,
+ Telugu = 142,
/// Tfng
- Tifinagh = 139,
+ Tifinagh = 143,
/// Tglg
- Tagalog = 140,
+ Tagalog = 144,
/// Thaa
- Thaana = 141,
+ Thaana = 145,
/// Thai
- Thai = 142,
+ Thai = 146,
/// Tibt
- Tibetan = 143,
+ Tibetan = 147,
/// Tirh
- Tirhuta = 144,
+ Tirhuta = 148,
+ /// Tnsa
+ Tangsa = 149,
+ /// Toto
+ Toto = 150,
/// Ugar
- Ugaritic = 145,
+ Ugaritic = 151,
/// Vaii
- Vai = 146,
+ Vai = 152,
+ /// Vith
+ Vithkuqi = 153,
/// Wara
- Warang_Citi = 147,
+ Warang_Citi = 154,
/// Wcho
- Wancho = 148,
+ Wancho = 155,
/// Xpeo
- Old_Persian = 149,
+ Old_Persian = 156,
/// Xsux
- Cuneiform = 150,
+ Cuneiform = 157,
/// Yezi
- Yezidi = 151,
+ Yezidi = 158,
/// Yiii
- Yi = 152,
+ Yi = 159,
/// Zanb
- Zanabazar_Square = 153,
+ Zanabazar_Square = 160,
}
-pub const NEXT_SCRIPT: u8 = 154;
+pub const NEXT_SCRIPT: u8 = 161;
pub mod script_extensions {
use crate::ScriptExtension;
@@ -446,518 +460,544 @@ pub mod script_extensions {
pub const COPTIC: ScriptExtension = ScriptExtension::new(0x1000000, 0, 0);
/// Coptic
pub const COPT: ScriptExtension = COPTIC;
+ /// Cypro_Minoan
+ pub const CYPRO_MINOAN: ScriptExtension = ScriptExtension::new(0x2000000, 0, 0);
+ /// Cypro_Minoan
+ pub const CPMN: ScriptExtension = CYPRO_MINOAN;
/// Cypriot
- pub const CYPRIOT: ScriptExtension = ScriptExtension::new(0x2000000, 0, 0);
+ pub const CYPRIOT: ScriptExtension = ScriptExtension::new(0x4000000, 0, 0);
/// Cypriot
pub const CPRT: ScriptExtension = CYPRIOT;
/// Cyrillic
- pub const CYRILLIC: ScriptExtension = ScriptExtension::new(0x4000000, 0, 0);
+ pub const CYRILLIC: ScriptExtension = ScriptExtension::new(0x8000000, 0, 0);
/// Cyrillic
pub const CYRL: ScriptExtension = CYRILLIC;
/// Devanagari
- pub const DEVANAGARI: ScriptExtension = ScriptExtension::new(0x8000000, 0, 0);
+ pub const DEVANAGARI: ScriptExtension = ScriptExtension::new(0x10000000, 0, 0);
/// Devanagari
pub const DEVA: ScriptExtension = DEVANAGARI;
/// Dives_Akuru
- pub const DIVES_AKURU: ScriptExtension = ScriptExtension::new(0x10000000, 0, 0);
+ pub const DIVES_AKURU: ScriptExtension = ScriptExtension::new(0x20000000, 0, 0);
/// Dives_Akuru
pub const DIAK: ScriptExtension = DIVES_AKURU;
/// Dogra
- pub const DOGRA: ScriptExtension = ScriptExtension::new(0x20000000, 0, 0);
+ pub const DOGRA: ScriptExtension = ScriptExtension::new(0x40000000, 0, 0);
/// Dogra
pub const DOGR: ScriptExtension = DOGRA;
/// Deseret
- pub const DESERET: ScriptExtension = ScriptExtension::new(0x40000000, 0, 0);
+ pub const DESERET: ScriptExtension = ScriptExtension::new(0x80000000, 0, 0);
/// Deseret
pub const DSRT: ScriptExtension = DESERET;
/// Duployan
- pub const DUPLOYAN: ScriptExtension = ScriptExtension::new(0x80000000, 0, 0);
+ pub const DUPLOYAN: ScriptExtension = ScriptExtension::new(0x100000000, 0, 0);
/// Duployan
pub const DUPL: ScriptExtension = DUPLOYAN;
/// Egyptian_Hieroglyphs
- pub const EGYPTIAN_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0x100000000, 0, 0);
+ pub const EGYPTIAN_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0x200000000, 0, 0);
/// Egyptian_Hieroglyphs
pub const EGYP: ScriptExtension = EGYPTIAN_HIEROGLYPHS;
/// Elbasan
- pub const ELBASAN: ScriptExtension = ScriptExtension::new(0x200000000, 0, 0);
+ pub const ELBASAN: ScriptExtension = ScriptExtension::new(0x400000000, 0, 0);
/// Elbasan
pub const ELBA: ScriptExtension = ELBASAN;
/// Elymaic
- pub const ELYMAIC: ScriptExtension = ScriptExtension::new(0x400000000, 0, 0);
+ pub const ELYMAIC: ScriptExtension = ScriptExtension::new(0x800000000, 0, 0);
/// Elymaic
pub const ELYM: ScriptExtension = ELYMAIC;
/// Ethiopic
- pub const ETHIOPIC: ScriptExtension = ScriptExtension::new(0x800000000, 0, 0);
+ pub const ETHIOPIC: ScriptExtension = ScriptExtension::new(0x1000000000, 0, 0);
/// Ethiopic
pub const ETHI: ScriptExtension = ETHIOPIC;
/// Georgian
- pub const GEORGIAN: ScriptExtension = ScriptExtension::new(0x1000000000, 0, 0);
+ pub const GEORGIAN: ScriptExtension = ScriptExtension::new(0x2000000000, 0, 0);
/// Georgian
pub const GEOR: ScriptExtension = GEORGIAN;
/// Glagolitic
- pub const GLAGOLITIC: ScriptExtension = ScriptExtension::new(0x2000000000, 0, 0);
+ pub const GLAGOLITIC: ScriptExtension = ScriptExtension::new(0x4000000000, 0, 0);
/// Glagolitic
pub const GLAG: ScriptExtension = GLAGOLITIC;
/// Gunjala_Gondi
- pub const GUNJALA_GONDI: ScriptExtension = ScriptExtension::new(0x4000000000, 0, 0);
+ pub const GUNJALA_GONDI: ScriptExtension = ScriptExtension::new(0x8000000000, 0, 0);
/// Gunjala_Gondi
pub const GONG: ScriptExtension = GUNJALA_GONDI;
/// Masaram_Gondi
- pub const MASARAM_GONDI: ScriptExtension = ScriptExtension::new(0x8000000000, 0, 0);
+ pub const MASARAM_GONDI: ScriptExtension = ScriptExtension::new(0x10000000000, 0, 0);
/// Masaram_Gondi
pub const GONM: ScriptExtension = MASARAM_GONDI;
/// Gothic
- pub const GOTHIC: ScriptExtension = ScriptExtension::new(0x10000000000, 0, 0);
+ pub const GOTHIC: ScriptExtension = ScriptExtension::new(0x20000000000, 0, 0);
/// Gothic
pub const GOTH: ScriptExtension = GOTHIC;
/// Grantha
- pub const GRANTHA: ScriptExtension = ScriptExtension::new(0x20000000000, 0, 0);
+ pub const GRANTHA: ScriptExtension = ScriptExtension::new(0x40000000000, 0, 0);
/// Grantha
pub const GRAN: ScriptExtension = GRANTHA;
/// Greek
- pub const GREEK: ScriptExtension = ScriptExtension::new(0x40000000000, 0, 0);
+ pub const GREEK: ScriptExtension = ScriptExtension::new(0x80000000000, 0, 0);
/// Greek
pub const GREK: ScriptExtension = GREEK;
/// Gujarati
- pub const GUJARATI: ScriptExtension = ScriptExtension::new(0x80000000000, 0, 0);
+ pub const GUJARATI: ScriptExtension = ScriptExtension::new(0x100000000000, 0, 0);
/// Gujarati
pub const GUJR: ScriptExtension = GUJARATI;
/// Gurmukhi
- pub const GURMUKHI: ScriptExtension = ScriptExtension::new(0x100000000000, 0, 0);
+ pub const GURMUKHI: ScriptExtension = ScriptExtension::new(0x200000000000, 0, 0);
/// Gurmukhi
pub const GURU: ScriptExtension = GURMUKHI;
/// Hangul
- pub const HANGUL: ScriptExtension = ScriptExtension::new(0x200000000000, 0, 0);
+ pub const HANGUL: ScriptExtension = ScriptExtension::new(0x400000000000, 0, 0);
/// Hangul
pub const HANG: ScriptExtension = HANGUL;
/// Han
- pub const HAN: ScriptExtension = ScriptExtension::new(0x400000000000, 0, 0);
+ pub const HAN: ScriptExtension = ScriptExtension::new(0x800000000000, 0, 0);
/// Han
pub const HANI: ScriptExtension = HAN;
/// Hanunoo
- pub const HANUNOO: ScriptExtension = ScriptExtension::new(0x800000000000, 0, 0);
+ pub const HANUNOO: ScriptExtension = ScriptExtension::new(0x1000000000000, 0, 0);
/// Hanunoo
pub const HANO: ScriptExtension = HANUNOO;
/// Hatran
- pub const HATRAN: ScriptExtension = ScriptExtension::new(0x1000000000000, 0, 0);
+ pub const HATRAN: ScriptExtension = ScriptExtension::new(0x2000000000000, 0, 0);
/// Hatran
pub const HATR: ScriptExtension = HATRAN;
/// Hebrew
- pub const HEBREW: ScriptExtension = ScriptExtension::new(0x2000000000000, 0, 0);
+ pub const HEBREW: ScriptExtension = ScriptExtension::new(0x4000000000000, 0, 0);
/// Hebrew
pub const HEBR: ScriptExtension = HEBREW;
/// Hiragana
- pub const HIRAGANA: ScriptExtension = ScriptExtension::new(0x4000000000000, 0, 0);
+ pub const HIRAGANA: ScriptExtension = ScriptExtension::new(0x8000000000000, 0, 0);
/// Hiragana
pub const HIRA: ScriptExtension = HIRAGANA;
/// Anatolian_Hieroglyphs
- pub const ANATOLIAN_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0x8000000000000, 0, 0);
+ pub const ANATOLIAN_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0x10000000000000, 0, 0);
/// Anatolian_Hieroglyphs
pub const HLUW: ScriptExtension = ANATOLIAN_HIEROGLYPHS;
/// Pahawh_Hmong
- pub const PAHAWH_HMONG: ScriptExtension = ScriptExtension::new(0x10000000000000, 0, 0);
+ pub const PAHAWH_HMONG: ScriptExtension = ScriptExtension::new(0x20000000000000, 0, 0);
/// Pahawh_Hmong
pub const HMNG: ScriptExtension = PAHAWH_HMONG;
/// Nyiakeng_Puachue_Hmong
- pub const NYIAKENG_PUACHUE_HMONG: ScriptExtension = ScriptExtension::new(0x20000000000000, 0, 0);
+ pub const NYIAKENG_PUACHUE_HMONG: ScriptExtension = ScriptExtension::new(0x40000000000000, 0, 0);
/// Nyiakeng_Puachue_Hmong
pub const HMNP: ScriptExtension = NYIAKENG_PUACHUE_HMONG;
/// Old_Hungarian
- pub const OLD_HUNGARIAN: ScriptExtension = ScriptExtension::new(0x40000000000000, 0, 0);
+ pub const OLD_HUNGARIAN: ScriptExtension = ScriptExtension::new(0x80000000000000, 0, 0);
/// Old_Hungarian
pub const HUNG: ScriptExtension = OLD_HUNGARIAN;
/// Old_Italic
- pub const OLD_ITALIC: ScriptExtension = ScriptExtension::new(0x80000000000000, 0, 0);
+ pub const OLD_ITALIC: ScriptExtension = ScriptExtension::new(0x100000000000000, 0, 0);
/// Old_Italic
pub const ITAL: ScriptExtension = OLD_ITALIC;
/// Javanese
- pub const JAVANESE: ScriptExtension = ScriptExtension::new(0x100000000000000, 0, 0);
+ pub const JAVANESE: ScriptExtension = ScriptExtension::new(0x200000000000000, 0, 0);
/// Javanese
pub const JAVA: ScriptExtension = JAVANESE;
/// Kayah_Li
- pub const KAYAH_LI: ScriptExtension = ScriptExtension::new(0x200000000000000, 0, 0);
+ pub const KAYAH_LI: ScriptExtension = ScriptExtension::new(0x400000000000000, 0, 0);
/// Kayah_Li
pub const KALI: ScriptExtension = KAYAH_LI;
/// Katakana
- pub const KATAKANA: ScriptExtension = ScriptExtension::new(0x400000000000000, 0, 0);
+ pub const KATAKANA: ScriptExtension = ScriptExtension::new(0x800000000000000, 0, 0);
/// Katakana
pub const KANA: ScriptExtension = KATAKANA;
+ /// Kawi
+ pub const KAWI: ScriptExtension = ScriptExtension::new(0x1000000000000000, 0, 0);
/// Kharoshthi
- pub const KHAROSHTHI: ScriptExtension = ScriptExtension::new(0x800000000000000, 0, 0);
+ pub const KHAROSHTHI: ScriptExtension = ScriptExtension::new(0x2000000000000000, 0, 0);
/// Kharoshthi
pub const KHAR: ScriptExtension = KHAROSHTHI;
/// Khmer
- pub const KHMER: ScriptExtension = ScriptExtension::new(0x1000000000000000, 0, 0);
+ pub const KHMER: ScriptExtension = ScriptExtension::new(0x4000000000000000, 0, 0);
/// Khmer
pub const KHMR: ScriptExtension = KHMER;
/// Khojki
- pub const KHOJKI: ScriptExtension = ScriptExtension::new(0x2000000000000000, 0, 0);
+ pub const KHOJKI: ScriptExtension = ScriptExtension::new(0x8000000000000000, 0, 0);
/// Khojki
pub const KHOJ: ScriptExtension = KHOJKI;
/// Khitan_Small_Script
- pub const KHITAN_SMALL_SCRIPT: ScriptExtension = ScriptExtension::new(0x4000000000000000, 0, 0);
+ pub const KHITAN_SMALL_SCRIPT: ScriptExtension = ScriptExtension::new(0, 0x1, 0);
/// Khitan_Small_Script
pub const KITS: ScriptExtension = KHITAN_SMALL_SCRIPT;
/// Kannada
- pub const KANNADA: ScriptExtension = ScriptExtension::new(0x8000000000000000, 0, 0);
+ pub const KANNADA: ScriptExtension = ScriptExtension::new(0, 0x2, 0);
/// Kannada
pub const KNDA: ScriptExtension = KANNADA;
/// Kaithi
- pub const KAITHI: ScriptExtension = ScriptExtension::new(0, 0x1, 0);
+ pub const KAITHI: ScriptExtension = ScriptExtension::new(0, 0x4, 0);
/// Kaithi
pub const KTHI: ScriptExtension = KAITHI;
/// Tai_Tham
- pub const TAI_THAM: ScriptExtension = ScriptExtension::new(0, 0x2, 0);
+ pub const TAI_THAM: ScriptExtension = ScriptExtension::new(0, 0x8, 0);
/// Tai_Tham
pub const LANA: ScriptExtension = TAI_THAM;
/// Lao
- pub const LAO: ScriptExtension = ScriptExtension::new(0, 0x4, 0);
+ pub const LAO: ScriptExtension = ScriptExtension::new(0, 0x10, 0);
/// Lao
pub const LAOO: ScriptExtension = LAO;
/// Latin
- pub const LATIN: ScriptExtension = ScriptExtension::new(0, 0x8, 0);
+ pub const LATIN: ScriptExtension = ScriptExtension::new(0, 0x20, 0);
/// Latin
pub const LATN: ScriptExtension = LATIN;
/// Lepcha
- pub const LEPCHA: ScriptExtension = ScriptExtension::new(0, 0x10, 0);
+ pub const LEPCHA: ScriptExtension = ScriptExtension::new(0, 0x40, 0);
/// Lepcha
pub const LEPC: ScriptExtension = LEPCHA;
/// Limbu
- pub const LIMBU: ScriptExtension = ScriptExtension::new(0, 0x20, 0);
+ pub const LIMBU: ScriptExtension = ScriptExtension::new(0, 0x80, 0);
/// Limbu
pub const LIMB: ScriptExtension = LIMBU;
/// Linear_A
- pub const LINEAR_A: ScriptExtension = ScriptExtension::new(0, 0x40, 0);
+ pub const LINEAR_A: ScriptExtension = ScriptExtension::new(0, 0x100, 0);
/// Linear_A
pub const LINA: ScriptExtension = LINEAR_A;
/// Linear_B
- pub const LINEAR_B: ScriptExtension = ScriptExtension::new(0, 0x80, 0);
+ pub const LINEAR_B: ScriptExtension = ScriptExtension::new(0, 0x200, 0);
/// Linear_B
pub const LINB: ScriptExtension = LINEAR_B;
/// Lisu
- pub const LISU: ScriptExtension = ScriptExtension::new(0, 0x100, 0);
+ pub const LISU: ScriptExtension = ScriptExtension::new(0, 0x400, 0);
/// Lycian
- pub const LYCIAN: ScriptExtension = ScriptExtension::new(0, 0x200, 0);
+ pub const LYCIAN: ScriptExtension = ScriptExtension::new(0, 0x800, 0);
/// Lycian
pub const LYCI: ScriptExtension = LYCIAN;
/// Lydian
- pub const LYDIAN: ScriptExtension = ScriptExtension::new(0, 0x400, 0);
+ pub const LYDIAN: ScriptExtension = ScriptExtension::new(0, 0x1000, 0);
/// Lydian
pub const LYDI: ScriptExtension = LYDIAN;
/// Mahajani
- pub const MAHAJANI: ScriptExtension = ScriptExtension::new(0, 0x800, 0);
+ pub const MAHAJANI: ScriptExtension = ScriptExtension::new(0, 0x2000, 0);
/// Mahajani
pub const MAHJ: ScriptExtension = MAHAJANI;
/// Makasar
- pub const MAKASAR: ScriptExtension = ScriptExtension::new(0, 0x1000, 0);
+ pub const MAKASAR: ScriptExtension = ScriptExtension::new(0, 0x4000, 0);
/// Makasar
pub const MAKA: ScriptExtension = MAKASAR;
/// Mandaic
- pub const MANDAIC: ScriptExtension = ScriptExtension::new(0, 0x2000, 0);
+ pub const MANDAIC: ScriptExtension = ScriptExtension::new(0, 0x8000, 0);
/// Mandaic
pub const MAND: ScriptExtension = MANDAIC;
/// Manichaean
- pub const MANICHAEAN: ScriptExtension = ScriptExtension::new(0, 0x4000, 0);
+ pub const MANICHAEAN: ScriptExtension = ScriptExtension::new(0, 0x10000, 0);
/// Manichaean
pub const MANI: ScriptExtension = MANICHAEAN;
/// Marchen
- pub const MARCHEN: ScriptExtension = ScriptExtension::new(0, 0x8000, 0);
+ pub const MARCHEN: ScriptExtension = ScriptExtension::new(0, 0x20000, 0);
/// Marchen
pub const MARC: ScriptExtension = MARCHEN;
/// Medefaidrin
- pub const MEDEFAIDRIN: ScriptExtension = ScriptExtension::new(0, 0x10000, 0);
+ pub const MEDEFAIDRIN: ScriptExtension = ScriptExtension::new(0, 0x40000, 0);
/// Medefaidrin
pub const MEDF: ScriptExtension = MEDEFAIDRIN;
/// Mende_Kikakui
- pub const MENDE_KIKAKUI: ScriptExtension = ScriptExtension::new(0, 0x20000, 0);
+ pub const MENDE_KIKAKUI: ScriptExtension = ScriptExtension::new(0, 0x80000, 0);
/// Mende_Kikakui
pub const MEND: ScriptExtension = MENDE_KIKAKUI;
/// Meroitic_Cursive
- pub const MEROITIC_CURSIVE: ScriptExtension = ScriptExtension::new(0, 0x40000, 0);
+ pub const MEROITIC_CURSIVE: ScriptExtension = ScriptExtension::new(0, 0x100000, 0);
/// Meroitic_Cursive
pub const MERC: ScriptExtension = MEROITIC_CURSIVE;
/// Meroitic_Hieroglyphs
- pub const MEROITIC_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0, 0x80000, 0);
+ pub const MEROITIC_HIEROGLYPHS: ScriptExtension = ScriptExtension::new(0, 0x200000, 0);
/// Meroitic_Hieroglyphs
pub const MERO: ScriptExtension = MEROITIC_HIEROGLYPHS;
/// Malayalam
- pub const MALAYALAM: ScriptExtension = ScriptExtension::new(0, 0x100000, 0);
+ pub const MALAYALAM: ScriptExtension = ScriptExtension::new(0, 0x400000, 0);
/// Malayalam
pub const MLYM: ScriptExtension = MALAYALAM;
/// Modi
- pub const MODI: ScriptExtension = ScriptExtension::new(0, 0x200000, 0);
+ pub const MODI: ScriptExtension = ScriptExtension::new(0, 0x800000, 0);
/// Mongolian
- pub const MONGOLIAN: ScriptExtension = ScriptExtension::new(0, 0x400000, 0);
+ pub const MONGOLIAN: ScriptExtension = ScriptExtension::new(0, 0x1000000, 0);
/// Mongolian
pub const MONG: ScriptExtension = MONGOLIAN;
/// Mro
- pub const MRO: ScriptExtension = ScriptExtension::new(0, 0x800000, 0);
+ pub const MRO: ScriptExtension = ScriptExtension::new(0, 0x2000000, 0);
/// Mro
pub const MROO: ScriptExtension = MRO;
/// Meetei_Mayek
- pub const MEETEI_MAYEK: ScriptExtension = ScriptExtension::new(0, 0x1000000, 0);
+ pub const MEETEI_MAYEK: ScriptExtension = ScriptExtension::new(0, 0x4000000, 0);
/// Meetei_Mayek
pub const MTEI: ScriptExtension = MEETEI_MAYEK;
/// Multani
- pub const MULTANI: ScriptExtension = ScriptExtension::new(0, 0x2000000, 0);
+ pub const MULTANI: ScriptExtension = ScriptExtension::new(0, 0x8000000, 0);
/// Multani
pub const MULT: ScriptExtension = MULTANI;
/// Myanmar
- pub const MYANMAR: ScriptExtension = ScriptExtension::new(0, 0x4000000, 0);
+ pub const MYANMAR: ScriptExtension = ScriptExtension::new(0, 0x10000000, 0);
/// Myanmar
pub const MYMR: ScriptExtension = MYANMAR;
+ /// Nag_Mundari
+ pub const NAG_MUNDARI: ScriptExtension = ScriptExtension::new(0, 0x20000000, 0);
+ /// Nag_Mundari
+ pub const NAGM: ScriptExtension = NAG_MUNDARI;
/// Nandinagari
- pub const NANDINAGARI: ScriptExtension = ScriptExtension::new(0, 0x8000000, 0);
+ pub const NANDINAGARI: ScriptExtension = ScriptExtension::new(0, 0x40000000, 0);
/// Nandinagari
pub const NAND: ScriptExtension = NANDINAGARI;
/// Old_North_Arabian
- pub const OLD_NORTH_ARABIAN: ScriptExtension = ScriptExtension::new(0, 0x10000000, 0);
+ pub const OLD_NORTH_ARABIAN: ScriptExtension = ScriptExtension::new(0, 0x80000000, 0);
/// Old_North_Arabian
pub const NARB: ScriptExtension = OLD_NORTH_ARABIAN;
/// Nabataean
- pub const NABATAEAN: ScriptExtension = ScriptExtension::new(0, 0x20000000, 0);
+ pub const NABATAEAN: ScriptExtension = ScriptExtension::new(0, 0x100000000, 0);
/// Nabataean
pub const NBAT: ScriptExtension = NABATAEAN;
/// Newa
- pub const NEWA: ScriptExtension = ScriptExtension::new(0, 0x40000000, 0);
+ pub const NEWA: ScriptExtension = ScriptExtension::new(0, 0x200000000, 0);
/// Nko
- pub const NKO: ScriptExtension = ScriptExtension::new(0, 0x80000000, 0);
+ pub const NKO: ScriptExtension = ScriptExtension::new(0, 0x400000000, 0);
/// Nko
pub const NKOO: ScriptExtension = NKO;
/// Nushu
- pub const NUSHU: ScriptExtension = ScriptExtension::new(0, 0x100000000, 0);
+ pub const NUSHU: ScriptExtension = ScriptExtension::new(0, 0x800000000, 0);
/// Nushu
pub const NSHU: ScriptExtension = NUSHU;
/// Ogham
- pub const OGHAM: ScriptExtension = ScriptExtension::new(0, 0x200000000, 0);
+ pub const OGHAM: ScriptExtension = ScriptExtension::new(0, 0x1000000000, 0);
/// Ogham
pub const OGAM: ScriptExtension = OGHAM;
/// Ol_Chiki
- pub const OL_CHIKI: ScriptExtension = ScriptExtension::new(0, 0x400000000, 0);
+ pub const OL_CHIKI: ScriptExtension = ScriptExtension::new(0, 0x2000000000, 0);
/// Ol_Chiki
pub const OLCK: ScriptExtension = OL_CHIKI;
/// Old_Turkic
- pub const OLD_TURKIC: ScriptExtension = ScriptExtension::new(0, 0x800000000, 0);
+ pub const OLD_TURKIC: ScriptExtension = ScriptExtension::new(0, 0x4000000000, 0);
/// Old_Turkic
pub const ORKH: ScriptExtension = OLD_TURKIC;
/// Oriya
- pub const ORIYA: ScriptExtension = ScriptExtension::new(0, 0x1000000000, 0);
+ pub const ORIYA: ScriptExtension = ScriptExtension::new(0, 0x8000000000, 0);
/// Oriya
pub const ORYA: ScriptExtension = ORIYA;
/// Osage
- pub const OSAGE: ScriptExtension = ScriptExtension::new(0, 0x2000000000, 0);
+ pub const OSAGE: ScriptExtension = ScriptExtension::new(0, 0x10000000000, 0);
/// Osage
pub const OSGE: ScriptExtension = OSAGE;
/// Osmanya
- pub const OSMANYA: ScriptExtension = ScriptExtension::new(0, 0x4000000000, 0);
+ pub const OSMANYA: ScriptExtension = ScriptExtension::new(0, 0x20000000000, 0);
/// Osmanya
pub const OSMA: ScriptExtension = OSMANYA;
+ /// Old_Uyghur
+ pub const OLD_UYGHUR: ScriptExtension = ScriptExtension::new(0, 0x40000000000, 0);
+ /// Old_Uyghur
+ pub const OUGR: ScriptExtension = OLD_UYGHUR;
/// Palmyrene
- pub const PALMYRENE: ScriptExtension = ScriptExtension::new(0, 0x8000000000, 0);
+ pub const PALMYRENE: ScriptExtension = ScriptExtension::new(0, 0x80000000000, 0);
/// Palmyrene
pub const PALM: ScriptExtension = PALMYRENE;
/// Pau_Cin_Hau
- pub const PAU_CIN_HAU: ScriptExtension = ScriptExtension::new(0, 0x10000000000, 0);
+ pub const PAU_CIN_HAU: ScriptExtension = ScriptExtension::new(0, 0x100000000000, 0);
/// Pau_Cin_Hau
pub const PAUC: ScriptExtension = PAU_CIN_HAU;
/// Old_Permic
- pub const OLD_PERMIC: ScriptExtension = ScriptExtension::new(0, 0x20000000000, 0);
+ pub const OLD_PERMIC: ScriptExtension = ScriptExtension::new(0, 0x200000000000, 0);
/// Old_Permic
pub const PERM: ScriptExtension = OLD_PERMIC;
/// Phags_Pa
- pub const PHAGS_PA: ScriptExtension = ScriptExtension::new(0, 0x40000000000, 0);
+ pub const PHAGS_PA: ScriptExtension = ScriptExtension::new(0, 0x400000000000, 0);
/// Phags_Pa
pub const PHAG: ScriptExtension = PHAGS_PA;
/// Inscriptional_Pahlavi
- pub const INSCRIPTIONAL_PAHLAVI: ScriptExtension = ScriptExtension::new(0, 0x80000000000, 0);
+ pub const INSCRIPTIONAL_PAHLAVI: ScriptExtension = ScriptExtension::new(0, 0x800000000000, 0);
/// Inscriptional_Pahlavi
pub const PHLI: ScriptExtension = INSCRIPTIONAL_PAHLAVI;
/// Psalter_Pahlavi
- pub const PSALTER_PAHLAVI: ScriptExtension = ScriptExtension::new(0, 0x100000000000, 0);
+ pub const PSALTER_PAHLAVI: ScriptExtension = ScriptExtension::new(0, 0x1000000000000, 0);
/// Psalter_Pahlavi
pub const PHLP: ScriptExtension = PSALTER_PAHLAVI;
/// Phoenician
- pub const PHOENICIAN: ScriptExtension = ScriptExtension::new(0, 0x200000000000, 0);
+ pub const PHOENICIAN: ScriptExtension = ScriptExtension::new(0, 0x2000000000000, 0);
/// Phoenician
pub const PHNX: ScriptExtension = PHOENICIAN;
/// Miao
- pub const MIAO: ScriptExtension = ScriptExtension::new(0, 0x400000000000, 0);
+ pub const MIAO: ScriptExtension = ScriptExtension::new(0, 0x4000000000000, 0);
/// Miao
pub const PLRD: ScriptExtension = MIAO;
/// Inscriptional_Parthian
- pub const INSCRIPTIONAL_PARTHIAN: ScriptExtension = ScriptExtension::new(0, 0x800000000000, 0);
+ pub const INSCRIPTIONAL_PARTHIAN: ScriptExtension = ScriptExtension::new(0, 0x8000000000000, 0);
/// Inscriptional_Parthian
pub const PRTI: ScriptExtension = INSCRIPTIONAL_PARTHIAN;
/// Rejang
- pub const REJANG: ScriptExtension = ScriptExtension::new(0, 0x1000000000000, 0);
+ pub const REJANG: ScriptExtension = ScriptExtension::new(0, 0x10000000000000, 0);
/// Rejang
pub const RJNG: ScriptExtension = REJANG;
/// Hanifi_Rohingya
- pub const HANIFI_ROHINGYA: ScriptExtension = ScriptExtension::new(0, 0x2000000000000, 0);
+ pub const HANIFI_ROHINGYA: ScriptExtension = ScriptExtension::new(0, 0x20000000000000, 0);
/// Hanifi_Rohingya
pub const ROHG: ScriptExtension = HANIFI_ROHINGYA;
/// Runic
- pub const RUNIC: ScriptExtension = ScriptExtension::new(0, 0x4000000000000, 0);
+ pub const RUNIC: ScriptExtension = ScriptExtension::new(0, 0x40000000000000, 0);
/// Runic
pub const RUNR: ScriptExtension = RUNIC;
/// Samaritan
- pub const SAMARITAN: ScriptExtension = ScriptExtension::new(0, 0x8000000000000, 0);
+ pub const SAMARITAN: ScriptExtension = ScriptExtension::new(0, 0x80000000000000, 0);
/// Samaritan
pub const SAMR: ScriptExtension = SAMARITAN;
/// Old_South_Arabian
- pub const OLD_SOUTH_ARABIAN: ScriptExtension = ScriptExtension::new(0, 0x10000000000000, 0);
+ pub const OLD_SOUTH_ARABIAN: ScriptExtension = ScriptExtension::new(0, 0x100000000000000, 0);
/// Old_South_Arabian
pub const SARB: ScriptExtension = OLD_SOUTH_ARABIAN;
/// Saurashtra
- pub const SAURASHTRA: ScriptExtension = ScriptExtension::new(0, 0x20000000000000, 0);
+ pub const SAURASHTRA: ScriptExtension = ScriptExtension::new(0, 0x200000000000000, 0);
/// Saurashtra
pub const SAUR: ScriptExtension = SAURASHTRA;
/// SignWriting
- pub const SIGNWRITING: ScriptExtension = ScriptExtension::new(0, 0x40000000000000, 0);
+ pub const SIGNWRITING: ScriptExtension = ScriptExtension::new(0, 0x400000000000000, 0);
/// SignWriting
pub const SGNW: ScriptExtension = SIGNWRITING;
/// Shavian
- pub const SHAVIAN: ScriptExtension = ScriptExtension::new(0, 0x80000000000000, 0);
+ pub const SHAVIAN: ScriptExtension = ScriptExtension::new(0, 0x800000000000000, 0);
/// Shavian
pub const SHAW: ScriptExtension = SHAVIAN;
/// Sharada
- pub const SHARADA: ScriptExtension = ScriptExtension::new(0, 0x100000000000000, 0);
+ pub const SHARADA: ScriptExtension = ScriptExtension::new(0, 0x1000000000000000, 0);
/// Sharada
pub const SHRD: ScriptExtension = SHARADA;
/// Siddham
- pub const SIDDHAM: ScriptExtension = ScriptExtension::new(0, 0x200000000000000, 0);
+ pub const SIDDHAM: ScriptExtension = ScriptExtension::new(0, 0x2000000000000000, 0);
/// Siddham
pub const SIDD: ScriptExtension = SIDDHAM;
/// Khudawadi
- pub const KHUDAWADI: ScriptExtension = ScriptExtension::new(0, 0x400000000000000, 0);
+ pub const KHUDAWADI: ScriptExtension = ScriptExtension::new(0, 0x4000000000000000, 0);
/// Khudawadi
pub const SIND: ScriptExtension = KHUDAWADI;
/// Sinhala
- pub const SINHALA: ScriptExtension = ScriptExtension::new(0, 0x800000000000000, 0);
+ pub const SINHALA: ScriptExtension = ScriptExtension::new(0, 0x8000000000000000, 0);
/// Sinhala
pub const SINH: ScriptExtension = SINHALA;
/// Sogdian
- pub const SOGDIAN: ScriptExtension = ScriptExtension::new(0, 0x1000000000000000, 0);
+ pub const SOGDIAN: ScriptExtension = ScriptExtension::new(0, 0, 0x1);
/// Sogdian
pub const SOGD: ScriptExtension = SOGDIAN;
/// Old_Sogdian
- pub const OLD_SOGDIAN: ScriptExtension = ScriptExtension::new(0, 0x2000000000000000, 0);
+ pub const OLD_SOGDIAN: ScriptExtension = ScriptExtension::new(0, 0, 0x2);
/// Old_Sogdian
pub const SOGO: ScriptExtension = OLD_SOGDIAN;
/// Sora_Sompeng
- pub const SORA_SOMPENG: ScriptExtension = ScriptExtension::new(0, 0x4000000000000000, 0);
+ pub const SORA_SOMPENG: ScriptExtension = ScriptExtension::new(0, 0, 0x4);
/// Sora_Sompeng
pub const SORA: ScriptExtension = SORA_SOMPENG;
/// Soyombo
- pub const SOYOMBO: ScriptExtension = ScriptExtension::new(0, 0x8000000000000000, 0);
+ pub const SOYOMBO: ScriptExtension = ScriptExtension::new(0, 0, 0x8);
/// Soyombo
pub const SOYO: ScriptExtension = SOYOMBO;
/// Sundanese
- pub const SUNDANESE: ScriptExtension = ScriptExtension::new(0, 0, 0x1);
+ pub const SUNDANESE: ScriptExtension = ScriptExtension::new(0, 0, 0x10);
/// Sundanese
pub const SUND: ScriptExtension = SUNDANESE;
/// Syloti_Nagri
- pub const SYLOTI_NAGRI: ScriptExtension = ScriptExtension::new(0, 0, 0x2);
+ pub const SYLOTI_NAGRI: ScriptExtension = ScriptExtension::new(0, 0, 0x20);
/// Syloti_Nagri
pub const SYLO: ScriptExtension = SYLOTI_NAGRI;
/// Syriac
- pub const SYRIAC: ScriptExtension = ScriptExtension::new(0, 0, 0x4);
+ pub const SYRIAC: ScriptExtension = ScriptExtension::new(0, 0, 0x40);
/// Syriac
pub const SYRC: ScriptExtension = SYRIAC;
/// Tagbanwa
- pub const TAGBANWA: ScriptExtension = ScriptExtension::new(0, 0, 0x8);
+ pub const TAGBANWA: ScriptExtension = ScriptExtension::new(0, 0, 0x80);
/// Tagbanwa
pub const TAGB: ScriptExtension = TAGBANWA;
/// Takri
- pub const TAKRI: ScriptExtension = ScriptExtension::new(0, 0, 0x10);
+ pub const TAKRI: ScriptExtension = ScriptExtension::new(0, 0, 0x100);
/// Takri
pub const TAKR: ScriptExtension = TAKRI;
/// Tai_Le
- pub const TAI_LE: ScriptExtension = ScriptExtension::new(0, 0, 0x20);
+ pub const TAI_LE: ScriptExtension = ScriptExtension::new(0, 0, 0x200);
/// Tai_Le
pub const TALE: ScriptExtension = TAI_LE;
/// New_Tai_Lue
- pub const NEW_TAI_LUE: ScriptExtension = ScriptExtension::new(0, 0, 0x40);
+ pub const NEW_TAI_LUE: ScriptExtension = ScriptExtension::new(0, 0, 0x400);
/// New_Tai_Lue
pub const TALU: ScriptExtension = NEW_TAI_LUE;
/// Tamil
- pub const TAMIL: ScriptExtension = ScriptExtension::new(0, 0, 0x80);
+ pub const TAMIL: ScriptExtension = ScriptExtension::new(0, 0, 0x800);
/// Tamil
pub const TAML: ScriptExtension = TAMIL;
/// Tangut
- pub const TANGUT: ScriptExtension = ScriptExtension::new(0, 0, 0x100);
+ pub const TANGUT: ScriptExtension = ScriptExtension::new(0, 0, 0x1000);
/// Tangut
pub const TANG: ScriptExtension = TANGUT;
/// Tai_Viet
- pub const TAI_VIET: ScriptExtension = ScriptExtension::new(0, 0, 0x200);
+ pub const TAI_VIET: ScriptExtension = ScriptExtension::new(0, 0, 0x2000);
/// Tai_Viet
pub const TAVT: ScriptExtension = TAI_VIET;
/// Telugu
- pub const TELUGU: ScriptExtension = ScriptExtension::new(0, 0, 0x400);
+ pub const TELUGU: ScriptExtension = ScriptExtension::new(0, 0, 0x4000);
/// Telugu
pub const TELU: ScriptExtension = TELUGU;
/// Tifinagh
- pub const TIFINAGH: ScriptExtension = ScriptExtension::new(0, 0, 0x800);
+ pub const TIFINAGH: ScriptExtension = ScriptExtension::new(0, 0, 0x8000);
/// Tifinagh
pub const TFNG: ScriptExtension = TIFINAGH;
/// Tagalog
- pub const TAGALOG: ScriptExtension = ScriptExtension::new(0, 0, 0x1000);
+ pub const TAGALOG: ScriptExtension = ScriptExtension::new(0, 0, 0x10000);
/// Tagalog
pub const TGLG: ScriptExtension = TAGALOG;
/// Thaana
- pub const THAANA: ScriptExtension = ScriptExtension::new(0, 0, 0x2000);
+ pub const THAANA: ScriptExtension = ScriptExtension::new(0, 0, 0x20000);
/// Thaana
pub const THAA: ScriptExtension = THAANA;
/// Thai
- pub const THAI: ScriptExtension = ScriptExtension::new(0, 0, 0x4000);
+ pub const THAI: ScriptExtension = ScriptExtension::new(0, 0, 0x40000);
/// Tibetan
- pub const TIBETAN: ScriptExtension = ScriptExtension::new(0, 0, 0x8000);
+ pub const TIBETAN: ScriptExtension = ScriptExtension::new(0, 0, 0x80000);
/// Tibetan
pub const TIBT: ScriptExtension = TIBETAN;
/// Tirhuta
- pub const TIRHUTA: ScriptExtension = ScriptExtension::new(0, 0, 0x10000);
+ pub const TIRHUTA: ScriptExtension = ScriptExtension::new(0, 0, 0x100000);
/// Tirhuta
pub const TIRH: ScriptExtension = TIRHUTA;
+ /// Tangsa
+ pub const TANGSA: ScriptExtension = ScriptExtension::new(0, 0, 0x200000);
+ /// Tangsa
+ pub const TNSA: ScriptExtension = TANGSA;
+ /// Toto
+ pub const TOTO: ScriptExtension = ScriptExtension::new(0, 0, 0x400000);
/// Ugaritic
- pub const UGARITIC: ScriptExtension = ScriptExtension::new(0, 0, 0x20000);
+ pub const UGARITIC: ScriptExtension = ScriptExtension::new(0, 0, 0x800000);
/// Ugaritic
pub const UGAR: ScriptExtension = UGARITIC;
/// Vai
- pub const VAI: ScriptExtension = ScriptExtension::new(0, 0, 0x40000);
+ pub const VAI: ScriptExtension = ScriptExtension::new(0, 0, 0x1000000);
/// Vai
pub const VAII: ScriptExtension = VAI;
+ /// Vithkuqi
+ pub const VITHKUQI: ScriptExtension = ScriptExtension::new(0, 0, 0x2000000);
+ /// Vithkuqi
+ pub const VITH: ScriptExtension = VITHKUQI;
/// Warang_Citi
- pub const WARANG_CITI: ScriptExtension = ScriptExtension::new(0, 0, 0x80000);
+ pub const WARANG_CITI: ScriptExtension = ScriptExtension::new(0, 0, 0x4000000);
/// Warang_Citi
pub const WARA: ScriptExtension = WARANG_CITI;
/// Wancho
- pub const WANCHO: ScriptExtension = ScriptExtension::new(0, 0, 0x100000);
+ pub const WANCHO: ScriptExtension = ScriptExtension::new(0, 0, 0x8000000);
/// Wancho
pub const WCHO: ScriptExtension = WANCHO;
/// Old_Persian
- pub const OLD_PERSIAN: ScriptExtension = ScriptExtension::new(0, 0, 0x200000);
+ pub const OLD_PERSIAN: ScriptExtension = ScriptExtension::new(0, 0, 0x10000000);
/// Old_Persian
pub const XPEO: ScriptExtension = OLD_PERSIAN;
/// Cuneiform
- pub const CUNEIFORM: ScriptExtension = ScriptExtension::new(0, 0, 0x400000);
+ pub const CUNEIFORM: ScriptExtension = ScriptExtension::new(0, 0, 0x20000000);
/// Cuneiform
pub const XSUX: ScriptExtension = CUNEIFORM;
/// Yezidi
- pub const YEZIDI: ScriptExtension = ScriptExtension::new(0, 0, 0x800000);
+ pub const YEZIDI: ScriptExtension = ScriptExtension::new(0, 0, 0x40000000);
/// Yezidi
pub const YEZI: ScriptExtension = YEZIDI;
/// Yi
- pub const YI: ScriptExtension = ScriptExtension::new(0, 0, 0x1000000);
+ pub const YI: ScriptExtension = ScriptExtension::new(0, 0, 0x80000000);
/// Yi
pub const YIII: ScriptExtension = YI;
/// Zanabazar_Square
- pub const ZANABAZAR_SQUARE: ScriptExtension = ScriptExtension::new(0, 0, 0x2000000);
+ pub const ZANABAZAR_SQUARE: ScriptExtension = ScriptExtension::new(0, 0, 0x100000000);
/// Zanabazar_Square
pub const ZANB: ScriptExtension = ZANABAZAR_SQUARE;
/// Arabic, Coptic
pub const ARAB_COPT: ScriptExtension = ARAB.union(COPT);
/// Arabic, Hanifi_Rohingya
pub const ARAB_ROHG: ScriptExtension = ARAB.union(ROHG);
+ /// Arabic, Nko
+ pub const ARAB_NKOO: ScriptExtension = ARAB.union(NKOO);
/// Arabic, Syriac
pub const ARAB_SYRC: ScriptExtension = ARAB.union(SYRC);
/// Arabic, Thaana
@@ -1002,6 +1042,8 @@ pub mod script_extensions {
pub const KNDA_NAND: ScriptExtension = KNDA.union(NAND);
/// Latin, Mongolian
pub const LATN_MONG: ScriptExtension = LATN.union(MONG);
+ /// Manichaean, Old_Uyghur
+ pub const MANI_OUGR: ScriptExtension = MANI.union(OUGR);
/// Mongolian, Phags_Pa
pub const MONG_PHAG: ScriptExtension = MONG.union(PHAG);
/// Arabic, Syriac, Thaana
@@ -1012,6 +1054,8 @@ pub mod script_extensions {
pub const BENG_CAKM_SYLO: ScriptExtension = BENG.union(CAKM).union(SYLO);
/// Chakma, Myanmar, Tai_Le
pub const CAKM_MYMR_TALE: ScriptExtension = CAKM.union(MYMR).union(TALE);
+ /// Cypro_Minoan, Cypriot, Linear_B
+ pub const CPMN_CPRT_LINB: ScriptExtension = CPMN.union(CPRT).union(LINB);
/// Cypriot, Linear_A, Linear_B
pub const CPRT_LINA_LINB: ScriptExtension = CPRT.union(LINA).union(LINB);
/// Devanagari, Grantha, Kannada
@@ -1028,18 +1072,20 @@ pub mod script_extensions {
pub const BUHD_HANO_TAGB_TGLG: ScriptExtension = BUHD.union(HANO).union(TAGB).union(TGLG);
/// Devanagari, Dogra, Kaithi, Mahajani
pub const DEVA_DOGR_KTHI_MAHJ: ScriptExtension = DEVA.union(DOGR).union(KTHI).union(MAHJ);
- /// Arabic, Hanifi_Rohingya, Syriac, Thaana, Yezidi
- pub const ARAB_ROHG_SYRC_THAA_YEZI: ScriptExtension = ARAB.union(ROHG).union(SYRC).union(THAA).union(YEZI);
/// Bopomofo, Hangul, Han, Hiragana, Katakana
pub const BOPO_HANG_HANI_HIRA_KANA: ScriptExtension = BOPO.union(HANG).union(HANI).union(HIRA).union(KANA);
+ /// Arabic, Nko, Hanifi_Rohingya, Syriac, Thaana, Yezidi
+ pub const ARAB_NKOO_ROHG_SYRC_THAA_YEZI: ScriptExtension = ARAB.union(NKOO).union(ROHG).union(SYRC).union(THAA).union(YEZI);
/// Bopomofo, Hangul, Han, Hiragana, Katakana, Yi
pub const BOPO_HANG_HANI_HIRA_KANA_YIII: ScriptExtension = BOPO.union(HANG).union(HANI).union(HIRA).union(KANA).union(YIII);
/// Devanagari, Kannada, Malayalam, Oriya, Tamil, Telugu
pub const DEVA_KNDA_MLYM_ORYA_TAML_TELU: ScriptExtension = DEVA.union(KNDA).union(MLYM).union(ORYA).union(TAML).union(TELU);
- /// Adlam, Arabic, Mandaic, Manichaean, Psalter_Pahlavi, Hanifi_Rohingya, Sogdian, Syriac
- pub const ADLM_ARAB_MAND_MANI_PHLP_ROHG_SOGD_SYRC: ScriptExtension = ADLM.union(ARAB).union(MAND).union(MANI).union(PHLP).union(ROHG).union(SOGD).union(SYRC);
+ /// Adlam, Arabic, Nko, Hanifi_Rohingya, Syriac, Thaana, Yezidi
+ pub const ADLM_ARAB_NKOO_ROHG_SYRC_THAA_YEZI: ScriptExtension = ADLM.union(ARAB).union(NKOO).union(ROHG).union(SYRC).union(THAA).union(YEZI);
/// Bengali, Devanagari, Grantha, Kannada, Nandinagari, Oriya, Telugu, Tirhuta
pub const BENG_DEVA_GRAN_KNDA_NAND_ORYA_TELU_TIRH: ScriptExtension = BENG.union(DEVA).union(GRAN).union(KNDA).union(NAND).union(ORYA).union(TELU).union(TIRH);
+ /// Adlam, Arabic, Mandaic, Manichaean, Old_Uyghur, Psalter_Pahlavi, Hanifi_Rohingya, Sogdian, Syriac
+ pub const ADLM_ARAB_MAND_MANI_OUGR_PHLP_ROHG_SOGD_SYRC: ScriptExtension = ADLM.union(ARAB).union(MAND).union(MANI).union(OUGR).union(PHLP).union(ROHG).union(SOGD).union(SYRC);
/// Devanagari, Dogra, Gujarati, Gurmukhi, Khojki, Kaithi, Mahajani, Modi, Khudawadi, Takri, Tirhuta
pub const DEVA_DOGR_GUJR_GURU_KHOJ_KTHI_MAHJ_MODI_SIND_TAKR_TIRH: ScriptExtension = DEVA.union(DOGR).union(GUJR).union(GURU).union(KHOJ).union(KTHI).union(MAHJ).union(MODI).union(SIND).union(TAKR).union(TIRH);
/// Bengali, Devanagari, Grantha, Gujarati, Gurmukhi, Kannada, Latin, Malayalam, Oriya, Tamil, Telugu, Tirhuta
@@ -1089,6 +1135,7 @@ impl Script {
Script::Cherokee => "Cherokee",
Script::Chorasmian => "Chorasmian",
Script::Coptic => "Coptic",
+ Script::Cypro_Minoan => "Cypro_Minoan",
Script::Cypriot => "Cypriot",
Script::Cyrillic => "Cyrillic",
Script::Devanagari => "Devanagari",
@@ -1123,6 +1170,7 @@ impl Script {
Script::Javanese => "Javanese",
Script::Kayah_Li => "Kayah_Li",
Script::Katakana => "Katakana",
+ Script::Kawi => "Kawi",
Script::Kharoshthi => "Kharoshthi",
Script::Khmer => "Khmer",
Script::Khojki => "Khojki",
@@ -1155,6 +1203,7 @@ impl Script {
Script::Meetei_Mayek => "Meetei_Mayek",
Script::Multani => "Multani",
Script::Myanmar => "Myanmar",
+ Script::Nag_Mundari => "Nag_Mundari",
Script::Nandinagari => "Nandinagari",
Script::Old_North_Arabian => "Old_North_Arabian",
Script::Nabataean => "Nabataean",
@@ -1167,6 +1216,7 @@ impl Script {
Script::Oriya => "Oriya",
Script::Osage => "Osage",
Script::Osmanya => "Osmanya",
+ Script::Old_Uyghur => "Old_Uyghur",
Script::Palmyrene => "Palmyrene",
Script::Pau_Cin_Hau => "Pau_Cin_Hau",
Script::Old_Permic => "Old_Permic",
@@ -1209,8 +1259,11 @@ impl Script {
Script::Thai => "Thai",
Script::Tibetan => "Tibetan",
Script::Tirhuta => "Tirhuta",
+ Script::Tangsa => "Tangsa",
+ Script::Toto => "Toto",
Script::Ugaritic => "Ugaritic",
Script::Vai => "Vai",
+ Script::Vithkuqi => "Vithkuqi",
Script::Warang_Citi => "Warang_Citi",
Script::Wancho => "Wancho",
Script::Old_Persian => "Old_Persian",
@@ -1252,6 +1305,7 @@ impl Script {
"Cherokee" => Some(Script::Cherokee),
"Chorasmian" => Some(Script::Chorasmian),
"Coptic" => Some(Script::Coptic),
+ "Cypro_Minoan" => Some(Script::Cypro_Minoan),
"Cypriot" => Some(Script::Cypriot),
"Cyrillic" => Some(Script::Cyrillic),
"Devanagari" => Some(Script::Devanagari),
@@ -1286,6 +1340,7 @@ impl Script {
"Javanese" => Some(Script::Javanese),
"Kayah_Li" => Some(Script::Kayah_Li),
"Katakana" => Some(Script::Katakana),
+ "Kawi" => Some(Script::Kawi),
"Kharoshthi" => Some(Script::Kharoshthi),
"Khmer" => Some(Script::Khmer),
"Khojki" => Some(Script::Khojki),
@@ -1318,6 +1373,7 @@ impl Script {
"Meetei_Mayek" => Some(Script::Meetei_Mayek),
"Multani" => Some(Script::Multani),
"Myanmar" => Some(Script::Myanmar),
+ "Nag_Mundari" => Some(Script::Nag_Mundari),
"Nandinagari" => Some(Script::Nandinagari),
"Old_North_Arabian" => Some(Script::Old_North_Arabian),
"Nabataean" => Some(Script::Nabataean),
@@ -1330,6 +1386,7 @@ impl Script {
"Oriya" => Some(Script::Oriya),
"Osage" => Some(Script::Osage),
"Osmanya" => Some(Script::Osmanya),
+ "Old_Uyghur" => Some(Script::Old_Uyghur),
"Palmyrene" => Some(Script::Palmyrene),
"Pau_Cin_Hau" => Some(Script::Pau_Cin_Hau),
"Old_Permic" => Some(Script::Old_Permic),
@@ -1372,8 +1429,11 @@ impl Script {
"Thai" => Some(Script::Thai),
"Tibetan" => Some(Script::Tibetan),
"Tirhuta" => Some(Script::Tirhuta),
+ "Tangsa" => Some(Script::Tangsa),
+ "Toto" => Some(Script::Toto),
"Ugaritic" => Some(Script::Ugaritic),
"Vai" => Some(Script::Vai),
+ "Vithkuqi" => Some(Script::Vithkuqi),
"Warang_Citi" => Some(Script::Warang_Citi),
"Wancho" => Some(Script::Wancho),
"Old_Persian" => Some(Script::Old_Persian),
@@ -1416,6 +1476,7 @@ impl Script {
Script::Cherokee => "Cher",
Script::Chorasmian => "Chrs",
Script::Coptic => "Copt",
+ Script::Cypro_Minoan => "Cpmn",
Script::Cypriot => "Cprt",
Script::Cyrillic => "Cyrl",
Script::Devanagari => "Deva",
@@ -1450,6 +1511,7 @@ impl Script {
Script::Javanese => "Java",
Script::Kayah_Li => "Kali",
Script::Katakana => "Kana",
+ Script::Kawi => "Kawi",
Script::Kharoshthi => "Khar",
Script::Khmer => "Khmr",
Script::Khojki => "Khoj",
@@ -1482,6 +1544,7 @@ impl Script {
Script::Meetei_Mayek => "Mtei",
Script::Multani => "Mult",
Script::Myanmar => "Mymr",
+ Script::Nag_Mundari => "Nagm",
Script::Nandinagari => "Nand",
Script::Old_North_Arabian => "Narb",
Script::Nabataean => "Nbat",
@@ -1494,6 +1557,7 @@ impl Script {
Script::Oriya => "Orya",
Script::Osage => "Osge",
Script::Osmanya => "Osma",
+ Script::Old_Uyghur => "Ougr",
Script::Palmyrene => "Palm",
Script::Pau_Cin_Hau => "Pauc",
Script::Old_Permic => "Perm",
@@ -1536,8 +1600,11 @@ impl Script {
Script::Thai => "Thai",
Script::Tibetan => "Tibt",
Script::Tirhuta => "Tirh",
+ Script::Tangsa => "Tnsa",
+ Script::Toto => "Toto",
Script::Ugaritic => "Ugar",
Script::Vai => "Vaii",
+ Script::Vithkuqi => "Vith",
Script::Warang_Citi => "Wara",
Script::Wancho => "Wcho",
Script::Old_Persian => "Xpeo",
@@ -1578,6 +1645,7 @@ impl Script {
"Cher" => Some(Script::Cherokee),
"Chrs" => Some(Script::Chorasmian),
"Copt" => Some(Script::Coptic),
+ "Cpmn" => Some(Script::Cypro_Minoan),
"Cprt" => Some(Script::Cypriot),
"Cyrl" => Some(Script::Cyrillic),
"Deva" => Some(Script::Devanagari),
@@ -1612,6 +1680,7 @@ impl Script {
"Java" => Some(Script::Javanese),
"Kali" => Some(Script::Kayah_Li),
"Kana" => Some(Script::Katakana),
+ "Kawi" => Some(Script::Kawi),
"Khar" => Some(Script::Kharoshthi),
"Khmr" => Some(Script::Khmer),
"Khoj" => Some(Script::Khojki),
@@ -1644,6 +1713,7 @@ impl Script {
"Mtei" => Some(Script::Meetei_Mayek),
"Mult" => Some(Script::Multani),
"Mymr" => Some(Script::Myanmar),
+ "Nagm" => Some(Script::Nag_Mundari),
"Nand" => Some(Script::Nandinagari),
"Narb" => Some(Script::Old_North_Arabian),
"Nbat" => Some(Script::Nabataean),
@@ -1656,6 +1726,7 @@ impl Script {
"Orya" => Some(Script::Oriya),
"Osge" => Some(Script::Osage),
"Osma" => Some(Script::Osmanya),
+ "Ougr" => Some(Script::Old_Uyghur),
"Palm" => Some(Script::Palmyrene),
"Pauc" => Some(Script::Pau_Cin_Hau),
"Perm" => Some(Script::Old_Permic),
@@ -1698,8 +1769,11 @@ impl Script {
"Thai" => Some(Script::Thai),
"Tibt" => Some(Script::Tibetan),
"Tirh" => Some(Script::Tirhuta),
+ "Tnsa" => Some(Script::Tangsa),
+ "Toto" => Some(Script::Toto),
"Ugar" => Some(Script::Ugaritic),
"Vaii" => Some(Script::Vai),
+ "Vith" => Some(Script::Vithkuqi),
"Wara" => Some(Script::Warang_Citi),
"Wcho" => Some(Script::Wancho),
"Xpeo" => Some(Script::Old_Persian),
@@ -1739,135 +1813,142 @@ impl Script {
22 => Script::Cherokee,
23 => Script::Chorasmian,
24 => Script::Coptic,
- 25 => Script::Cypriot,
- 26 => Script::Cyrillic,
- 27 => Script::Devanagari,
- 28 => Script::Dives_Akuru,
- 29 => Script::Dogra,
- 30 => Script::Deseret,
- 31 => Script::Duployan,
- 32 => Script::Egyptian_Hieroglyphs,
- 33 => Script::Elbasan,
- 34 => Script::Elymaic,
- 35 => Script::Ethiopic,
- 36 => Script::Georgian,
- 37 => Script::Glagolitic,
- 38 => Script::Gunjala_Gondi,
- 39 => Script::Masaram_Gondi,
- 40 => Script::Gothic,
- 41 => Script::Grantha,
- 42 => Script::Greek,
- 43 => Script::Gujarati,
- 44 => Script::Gurmukhi,
- 45 => Script::Hangul,
- 46 => Script::Han,
- 47 => Script::Hanunoo,
- 48 => Script::Hatran,
- 49 => Script::Hebrew,
- 50 => Script::Hiragana,
- 51 => Script::Anatolian_Hieroglyphs,
- 52 => Script::Pahawh_Hmong,
- 53 => Script::Nyiakeng_Puachue_Hmong,
- 54 => Script::Old_Hungarian,
- 55 => Script::Old_Italic,
- 56 => Script::Javanese,
- 57 => Script::Kayah_Li,
- 58 => Script::Katakana,
- 59 => Script::Kharoshthi,
- 60 => Script::Khmer,
- 61 => Script::Khojki,
- 62 => Script::Khitan_Small_Script,
- 63 => Script::Kannada,
- 64 => Script::Kaithi,
- 65 => Script::Tai_Tham,
- 66 => Script::Lao,
- 67 => Script::Latin,
- 68 => Script::Lepcha,
- 69 => Script::Limbu,
- 70 => Script::Linear_A,
- 71 => Script::Linear_B,
- 72 => Script::Lisu,
- 73 => Script::Lycian,
- 74 => Script::Lydian,
- 75 => Script::Mahajani,
- 76 => Script::Makasar,
- 77 => Script::Mandaic,
- 78 => Script::Manichaean,
- 79 => Script::Marchen,
- 80 => Script::Medefaidrin,
- 81 => Script::Mende_Kikakui,
- 82 => Script::Meroitic_Cursive,
- 83 => Script::Meroitic_Hieroglyphs,
- 84 => Script::Malayalam,
- 85 => Script::Modi,
- 86 => Script::Mongolian,
- 87 => Script::Mro,
- 88 => Script::Meetei_Mayek,
- 89 => Script::Multani,
- 90 => Script::Myanmar,
- 91 => Script::Nandinagari,
- 92 => Script::Old_North_Arabian,
- 93 => Script::Nabataean,
- 94 => Script::Newa,
- 95 => Script::Nko,
- 96 => Script::Nushu,
- 97 => Script::Ogham,
- 98 => Script::Ol_Chiki,
- 99 => Script::Old_Turkic,
- 100 => Script::Oriya,
- 101 => Script::Osage,
- 102 => Script::Osmanya,
- 103 => Script::Palmyrene,
- 104 => Script::Pau_Cin_Hau,
- 105 => Script::Old_Permic,
- 106 => Script::Phags_Pa,
- 107 => Script::Inscriptional_Pahlavi,
- 108 => Script::Psalter_Pahlavi,
- 109 => Script::Phoenician,
- 110 => Script::Miao,
- 111 => Script::Inscriptional_Parthian,
- 112 => Script::Rejang,
- 113 => Script::Hanifi_Rohingya,
- 114 => Script::Runic,
- 115 => Script::Samaritan,
- 116 => Script::Old_South_Arabian,
- 117 => Script::Saurashtra,
- 118 => Script::SignWriting,
- 119 => Script::Shavian,
- 120 => Script::Sharada,
- 121 => Script::Siddham,
- 122 => Script::Khudawadi,
- 123 => Script::Sinhala,
- 124 => Script::Sogdian,
- 125 => Script::Old_Sogdian,
- 126 => Script::Sora_Sompeng,
- 127 => Script::Soyombo,
- 128 => Script::Sundanese,
- 129 => Script::Syloti_Nagri,
- 130 => Script::Syriac,
- 131 => Script::Tagbanwa,
- 132 => Script::Takri,
- 133 => Script::Tai_Le,
- 134 => Script::New_Tai_Lue,
- 135 => Script::Tamil,
- 136 => Script::Tangut,
- 137 => Script::Tai_Viet,
- 138 => Script::Telugu,
- 139 => Script::Tifinagh,
- 140 => Script::Tagalog,
- 141 => Script::Thaana,
- 142 => Script::Thai,
- 143 => Script::Tibetan,
- 144 => Script::Tirhuta,
- 145 => Script::Ugaritic,
- 146 => Script::Vai,
- 147 => Script::Warang_Citi,
- 148 => Script::Wancho,
- 149 => Script::Old_Persian,
- 150 => Script::Cuneiform,
- 151 => Script::Yezidi,
- 152 => Script::Yi,
- 153 => Script::Zanabazar_Square,
+ 25 => Script::Cypro_Minoan,
+ 26 => Script::Cypriot,
+ 27 => Script::Cyrillic,
+ 28 => Script::Devanagari,
+ 29 => Script::Dives_Akuru,
+ 30 => Script::Dogra,
+ 31 => Script::Deseret,
+ 32 => Script::Duployan,
+ 33 => Script::Egyptian_Hieroglyphs,
+ 34 => Script::Elbasan,
+ 35 => Script::Elymaic,
+ 36 => Script::Ethiopic,
+ 37 => Script::Georgian,
+ 38 => Script::Glagolitic,
+ 39 => Script::Gunjala_Gondi,
+ 40 => Script::Masaram_Gondi,
+ 41 => Script::Gothic,
+ 42 => Script::Grantha,
+ 43 => Script::Greek,
+ 44 => Script::Gujarati,
+ 45 => Script::Gurmukhi,
+ 46 => Script::Hangul,
+ 47 => Script::Han,
+ 48 => Script::Hanunoo,
+ 49 => Script::Hatran,
+ 50 => Script::Hebrew,
+ 51 => Script::Hiragana,
+ 52 => Script::Anatolian_Hieroglyphs,
+ 53 => Script::Pahawh_Hmong,
+ 54 => Script::Nyiakeng_Puachue_Hmong,
+ 55 => Script::Old_Hungarian,
+ 56 => Script::Old_Italic,
+ 57 => Script::Javanese,
+ 58 => Script::Kayah_Li,
+ 59 => Script::Katakana,
+ 60 => Script::Kawi,
+ 61 => Script::Kharoshthi,
+ 62 => Script::Khmer,
+ 63 => Script::Khojki,
+ 64 => Script::Khitan_Small_Script,
+ 65 => Script::Kannada,
+ 66 => Script::Kaithi,
+ 67 => Script::Tai_Tham,
+ 68 => Script::Lao,
+ 69 => Script::Latin,
+ 70 => Script::Lepcha,
+ 71 => Script::Limbu,
+ 72 => Script::Linear_A,
+ 73 => Script::Linear_B,
+ 74 => Script::Lisu,
+ 75 => Script::Lycian,
+ 76 => Script::Lydian,
+ 77 => Script::Mahajani,
+ 78 => Script::Makasar,
+ 79 => Script::Mandaic,
+ 80 => Script::Manichaean,
+ 81 => Script::Marchen,
+ 82 => Script::Medefaidrin,
+ 83 => Script::Mende_Kikakui,
+ 84 => Script::Meroitic_Cursive,
+ 85 => Script::Meroitic_Hieroglyphs,
+ 86 => Script::Malayalam,
+ 87 => Script::Modi,
+ 88 => Script::Mongolian,
+ 89 => Script::Mro,
+ 90 => Script::Meetei_Mayek,
+ 91 => Script::Multani,
+ 92 => Script::Myanmar,
+ 93 => Script::Nag_Mundari,
+ 94 => Script::Nandinagari,
+ 95 => Script::Old_North_Arabian,
+ 96 => Script::Nabataean,
+ 97 => Script::Newa,
+ 98 => Script::Nko,
+ 99 => Script::Nushu,
+ 100 => Script::Ogham,
+ 101 => Script::Ol_Chiki,
+ 102 => Script::Old_Turkic,
+ 103 => Script::Oriya,
+ 104 => Script::Osage,
+ 105 => Script::Osmanya,
+ 106 => Script::Old_Uyghur,
+ 107 => Script::Palmyrene,
+ 108 => Script::Pau_Cin_Hau,
+ 109 => Script::Old_Permic,
+ 110 => Script::Phags_Pa,
+ 111 => Script::Inscriptional_Pahlavi,
+ 112 => Script::Psalter_Pahlavi,
+ 113 => Script::Phoenician,
+ 114 => Script::Miao,
+ 115 => Script::Inscriptional_Parthian,
+ 116 => Script::Rejang,
+ 117 => Script::Hanifi_Rohingya,
+ 118 => Script::Runic,
+ 119 => Script::Samaritan,
+ 120 => Script::Old_South_Arabian,
+ 121 => Script::Saurashtra,
+ 122 => Script::SignWriting,
+ 123 => Script::Shavian,
+ 124 => Script::Sharada,
+ 125 => Script::Siddham,
+ 126 => Script::Khudawadi,
+ 127 => Script::Sinhala,
+ 128 => Script::Sogdian,
+ 129 => Script::Old_Sogdian,
+ 130 => Script::Sora_Sompeng,
+ 131 => Script::Soyombo,
+ 132 => Script::Sundanese,
+ 133 => Script::Syloti_Nagri,
+ 134 => Script::Syriac,
+ 135 => Script::Tagbanwa,
+ 136 => Script::Takri,
+ 137 => Script::Tai_Le,
+ 138 => Script::New_Tai_Lue,
+ 139 => Script::Tamil,
+ 140 => Script::Tangut,
+ 141 => Script::Tai_Viet,
+ 142 => Script::Telugu,
+ 143 => Script::Tifinagh,
+ 144 => Script::Tagalog,
+ 145 => Script::Thaana,
+ 146 => Script::Thai,
+ 147 => Script::Tibetan,
+ 148 => Script::Tirhuta,
+ 149 => Script::Tangsa,
+ 150 => Script::Toto,
+ 151 => Script::Ugaritic,
+ 152 => Script::Vai,
+ 153 => Script::Vithkuqi,
+ 154 => Script::Warang_Citi,
+ 155 => Script::Wancho,
+ 156 => Script::Old_Persian,
+ 157 => Script::Cuneiform,
+ 158 => Script::Yezidi,
+ 159 => Script::Yi,
+ 160 => Script::Zanabazar_Square,
_ => unreachable!(),
}
}
@@ -1966,7 +2047,7 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
Script::Arabic), ('\u{60b}', '\u{60b}', Script::Arabic), ('\u{60c}', '\u{60c}',
Script::Common), ('\u{60d}', '\u{60d}', Script::Arabic), ('\u{60e}', '\u{60f}',
Script::Arabic), ('\u{610}', '\u{61a}', Script::Arabic), ('\u{61b}', '\u{61b}',
- Script::Common), ('\u{61c}', '\u{61c}', Script::Arabic), ('\u{61e}', '\u{61e}',
+ Script::Common), ('\u{61c}', '\u{61c}', Script::Arabic), ('\u{61d}', '\u{61e}',
Script::Arabic), ('\u{61f}', '\u{61f}', Script::Common), ('\u{620}', '\u{63f}',
Script::Arabic), ('\u{640}', '\u{640}', Script::Common), ('\u{641}', '\u{64a}',
Script::Arabic), ('\u{64b}', '\u{655}', Script::Inherited), ('\u{656}', '\u{65f}',
@@ -1996,105 +2077,109 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
Script::Samaritan), ('\u{829}', '\u{82d}', Script::Samaritan), ('\u{830}', '\u{83e}',
Script::Samaritan), ('\u{840}', '\u{858}', Script::Mandaic), ('\u{859}', '\u{85b}',
Script::Mandaic), ('\u{85e}', '\u{85e}', Script::Mandaic), ('\u{860}', '\u{86a}',
- Script::Syriac), ('\u{8a0}', '\u{8b4}', Script::Arabic), ('\u{8b6}', '\u{8c7}',
- Script::Arabic), ('\u{8d3}', '\u{8e1}', Script::Arabic), ('\u{8e2}', '\u{8e2}',
- Script::Common), ('\u{8e3}', '\u{8ff}', Script::Arabic), ('\u{900}', '\u{902}',
- Script::Devanagari), ('\u{903}', '\u{903}', Script::Devanagari), ('\u{904}', '\u{939}',
- Script::Devanagari), ('\u{93a}', '\u{93a}', Script::Devanagari), ('\u{93b}', '\u{93b}',
- Script::Devanagari), ('\u{93c}', '\u{93c}', Script::Devanagari), ('\u{93d}', '\u{93d}',
- Script::Devanagari), ('\u{93e}', '\u{940}', Script::Devanagari), ('\u{941}', '\u{948}',
- Script::Devanagari), ('\u{949}', '\u{94c}', Script::Devanagari), ('\u{94d}', '\u{94d}',
- Script::Devanagari), ('\u{94e}', '\u{94f}', Script::Devanagari), ('\u{950}', '\u{950}',
- Script::Devanagari), ('\u{951}', '\u{954}', Script::Inherited), ('\u{955}', '\u{957}',
- Script::Devanagari), ('\u{958}', '\u{961}', Script::Devanagari), ('\u{962}', '\u{963}',
- Script::Devanagari), ('\u{964}', '\u{965}', Script::Common), ('\u{966}', '\u{96f}',
- Script::Devanagari), ('\u{970}', '\u{970}', Script::Devanagari), ('\u{971}', '\u{971}',
- Script::Devanagari), ('\u{972}', '\u{97f}', Script::Devanagari), ('\u{980}', '\u{980}',
- Script::Bengali), ('\u{981}', '\u{981}', Script::Bengali), ('\u{982}', '\u{983}',
- Script::Bengali), ('\u{985}', '\u{98c}', Script::Bengali), ('\u{98f}', '\u{990}',
- Script::Bengali), ('\u{993}', '\u{9a8}', Script::Bengali), ('\u{9aa}', '\u{9b0}',
- Script::Bengali), ('\u{9b2}', '\u{9b2}', Script::Bengali), ('\u{9b6}', '\u{9b9}',
- Script::Bengali), ('\u{9bc}', '\u{9bc}', Script::Bengali), ('\u{9bd}', '\u{9bd}',
- Script::Bengali), ('\u{9be}', '\u{9c0}', Script::Bengali), ('\u{9c1}', '\u{9c4}',
- Script::Bengali), ('\u{9c7}', '\u{9c8}', Script::Bengali), ('\u{9cb}', '\u{9cc}',
- Script::Bengali), ('\u{9cd}', '\u{9cd}', Script::Bengali), ('\u{9ce}', '\u{9ce}',
- Script::Bengali), ('\u{9d7}', '\u{9d7}', Script::Bengali), ('\u{9dc}', '\u{9dd}',
- Script::Bengali), ('\u{9df}', '\u{9e1}', Script::Bengali), ('\u{9e2}', '\u{9e3}',
- Script::Bengali), ('\u{9e6}', '\u{9ef}', Script::Bengali), ('\u{9f0}', '\u{9f1}',
- Script::Bengali), ('\u{9f2}', '\u{9f3}', Script::Bengali), ('\u{9f4}', '\u{9f9}',
- Script::Bengali), ('\u{9fa}', '\u{9fa}', Script::Bengali), ('\u{9fb}', '\u{9fb}',
- Script::Bengali), ('\u{9fc}', '\u{9fc}', Script::Bengali), ('\u{9fd}', '\u{9fd}',
- Script::Bengali), ('\u{9fe}', '\u{9fe}', Script::Bengali), ('\u{a01}', '\u{a02}',
- Script::Gurmukhi), ('\u{a03}', '\u{a03}', Script::Gurmukhi), ('\u{a05}', '\u{a0a}',
- Script::Gurmukhi), ('\u{a0f}', '\u{a10}', Script::Gurmukhi), ('\u{a13}', '\u{a28}',
- Script::Gurmukhi), ('\u{a2a}', '\u{a30}', Script::Gurmukhi), ('\u{a32}', '\u{a33}',
- Script::Gurmukhi), ('\u{a35}', '\u{a36}', Script::Gurmukhi), ('\u{a38}', '\u{a39}',
- Script::Gurmukhi), ('\u{a3c}', '\u{a3c}', Script::Gurmukhi), ('\u{a3e}', '\u{a40}',
- Script::Gurmukhi), ('\u{a41}', '\u{a42}', Script::Gurmukhi), ('\u{a47}', '\u{a48}',
- Script::Gurmukhi), ('\u{a4b}', '\u{a4d}', Script::Gurmukhi), ('\u{a51}', '\u{a51}',
- Script::Gurmukhi), ('\u{a59}', '\u{a5c}', Script::Gurmukhi), ('\u{a5e}', '\u{a5e}',
- Script::Gurmukhi), ('\u{a66}', '\u{a6f}', Script::Gurmukhi), ('\u{a70}', '\u{a71}',
- Script::Gurmukhi), ('\u{a72}', '\u{a74}', Script::Gurmukhi), ('\u{a75}', '\u{a75}',
- Script::Gurmukhi), ('\u{a76}', '\u{a76}', Script::Gurmukhi), ('\u{a81}', '\u{a82}',
- Script::Gujarati), ('\u{a83}', '\u{a83}', Script::Gujarati), ('\u{a85}', '\u{a8d}',
- Script::Gujarati), ('\u{a8f}', '\u{a91}', Script::Gujarati), ('\u{a93}', '\u{aa8}',
- Script::Gujarati), ('\u{aaa}', '\u{ab0}', Script::Gujarati), ('\u{ab2}', '\u{ab3}',
- Script::Gujarati), ('\u{ab5}', '\u{ab9}', Script::Gujarati), ('\u{abc}', '\u{abc}',
- Script::Gujarati), ('\u{abd}', '\u{abd}', Script::Gujarati), ('\u{abe}', '\u{ac0}',
- Script::Gujarati), ('\u{ac1}', '\u{ac5}', Script::Gujarati), ('\u{ac7}', '\u{ac8}',
- Script::Gujarati), ('\u{ac9}', '\u{ac9}', Script::Gujarati), ('\u{acb}', '\u{acc}',
- Script::Gujarati), ('\u{acd}', '\u{acd}', Script::Gujarati), ('\u{ad0}', '\u{ad0}',
- Script::Gujarati), ('\u{ae0}', '\u{ae1}', Script::Gujarati), ('\u{ae2}', '\u{ae3}',
- Script::Gujarati), ('\u{ae6}', '\u{aef}', Script::Gujarati), ('\u{af0}', '\u{af0}',
- Script::Gujarati), ('\u{af1}', '\u{af1}', Script::Gujarati), ('\u{af9}', '\u{af9}',
- Script::Gujarati), ('\u{afa}', '\u{aff}', Script::Gujarati), ('\u{b01}', '\u{b01}',
- Script::Oriya), ('\u{b02}', '\u{b03}', Script::Oriya), ('\u{b05}', '\u{b0c}',
- Script::Oriya), ('\u{b0f}', '\u{b10}', Script::Oriya), ('\u{b13}', '\u{b28}',
- Script::Oriya), ('\u{b2a}', '\u{b30}', Script::Oriya), ('\u{b32}', '\u{b33}',
- Script::Oriya), ('\u{b35}', '\u{b39}', Script::Oriya), ('\u{b3c}', '\u{b3c}',
- Script::Oriya), ('\u{b3d}', '\u{b3d}', Script::Oriya), ('\u{b3e}', '\u{b3e}',
- Script::Oriya), ('\u{b3f}', '\u{b3f}', Script::Oriya), ('\u{b40}', '\u{b40}',
- Script::Oriya), ('\u{b41}', '\u{b44}', Script::Oriya), ('\u{b47}', '\u{b48}',
- Script::Oriya), ('\u{b4b}', '\u{b4c}', Script::Oriya), ('\u{b4d}', '\u{b4d}',
- Script::Oriya), ('\u{b55}', '\u{b56}', Script::Oriya), ('\u{b57}', '\u{b57}',
- Script::Oriya), ('\u{b5c}', '\u{b5d}', Script::Oriya), ('\u{b5f}', '\u{b61}',
- Script::Oriya), ('\u{b62}', '\u{b63}', Script::Oriya), ('\u{b66}', '\u{b6f}',
- Script::Oriya), ('\u{b70}', '\u{b70}', Script::Oriya), ('\u{b71}', '\u{b71}',
- Script::Oriya), ('\u{b72}', '\u{b77}', Script::Oriya), ('\u{b82}', '\u{b82}',
- Script::Tamil), ('\u{b83}', '\u{b83}', Script::Tamil), ('\u{b85}', '\u{b8a}',
- Script::Tamil), ('\u{b8e}', '\u{b90}', Script::Tamil), ('\u{b92}', '\u{b95}',
- Script::Tamil), ('\u{b99}', '\u{b9a}', Script::Tamil), ('\u{b9c}', '\u{b9c}',
- Script::Tamil), ('\u{b9e}', '\u{b9f}', Script::Tamil), ('\u{ba3}', '\u{ba4}',
- Script::Tamil), ('\u{ba8}', '\u{baa}', Script::Tamil), ('\u{bae}', '\u{bb9}',
- Script::Tamil), ('\u{bbe}', '\u{bbf}', Script::Tamil), ('\u{bc0}', '\u{bc0}',
- Script::Tamil), ('\u{bc1}', '\u{bc2}', Script::Tamil), ('\u{bc6}', '\u{bc8}',
- Script::Tamil), ('\u{bca}', '\u{bcc}', Script::Tamil), ('\u{bcd}', '\u{bcd}',
- Script::Tamil), ('\u{bd0}', '\u{bd0}', Script::Tamil), ('\u{bd7}', '\u{bd7}',
- Script::Tamil), ('\u{be6}', '\u{bef}', Script::Tamil), ('\u{bf0}', '\u{bf2}',
- Script::Tamil), ('\u{bf3}', '\u{bf8}', Script::Tamil), ('\u{bf9}', '\u{bf9}',
- Script::Tamil), ('\u{bfa}', '\u{bfa}', Script::Tamil), ('\u{c00}', '\u{c00}',
- Script::Telugu), ('\u{c01}', '\u{c03}', Script::Telugu), ('\u{c04}', '\u{c04}',
- Script::Telugu), ('\u{c05}', '\u{c0c}', Script::Telugu), ('\u{c0e}', '\u{c10}',
- Script::Telugu), ('\u{c12}', '\u{c28}', Script::Telugu), ('\u{c2a}', '\u{c39}',
+ Script::Syriac), ('\u{870}', '\u{887}', Script::Arabic), ('\u{888}', '\u{888}',
+ Script::Arabic), ('\u{889}', '\u{88e}', Script::Arabic), ('\u{890}', '\u{891}',
+ Script::Arabic), ('\u{898}', '\u{89f}', Script::Arabic), ('\u{8a0}', '\u{8c8}',
+ Script::Arabic), ('\u{8c9}', '\u{8c9}', Script::Arabic), ('\u{8ca}', '\u{8e1}',
+ Script::Arabic), ('\u{8e2}', '\u{8e2}', Script::Common), ('\u{8e3}', '\u{8ff}',
+ Script::Arabic), ('\u{900}', '\u{902}', Script::Devanagari), ('\u{903}', '\u{903}',
+ Script::Devanagari), ('\u{904}', '\u{939}', Script::Devanagari), ('\u{93a}', '\u{93a}',
+ Script::Devanagari), ('\u{93b}', '\u{93b}', Script::Devanagari), ('\u{93c}', '\u{93c}',
+ Script::Devanagari), ('\u{93d}', '\u{93d}', Script::Devanagari), ('\u{93e}', '\u{940}',
+ Script::Devanagari), ('\u{941}', '\u{948}', Script::Devanagari), ('\u{949}', '\u{94c}',
+ Script::Devanagari), ('\u{94d}', '\u{94d}', Script::Devanagari), ('\u{94e}', '\u{94f}',
+ Script::Devanagari), ('\u{950}', '\u{950}', Script::Devanagari), ('\u{951}', '\u{954}',
+ Script::Inherited), ('\u{955}', '\u{957}', Script::Devanagari), ('\u{958}', '\u{961}',
+ Script::Devanagari), ('\u{962}', '\u{963}', Script::Devanagari), ('\u{964}', '\u{965}',
+ Script::Common), ('\u{966}', '\u{96f}', Script::Devanagari), ('\u{970}', '\u{970}',
+ Script::Devanagari), ('\u{971}', '\u{971}', Script::Devanagari), ('\u{972}', '\u{97f}',
+ Script::Devanagari), ('\u{980}', '\u{980}', Script::Bengali), ('\u{981}', '\u{981}',
+ Script::Bengali), ('\u{982}', '\u{983}', Script::Bengali), ('\u{985}', '\u{98c}',
+ Script::Bengali), ('\u{98f}', '\u{990}', Script::Bengali), ('\u{993}', '\u{9a8}',
+ Script::Bengali), ('\u{9aa}', '\u{9b0}', Script::Bengali), ('\u{9b2}', '\u{9b2}',
+ Script::Bengali), ('\u{9b6}', '\u{9b9}', Script::Bengali), ('\u{9bc}', '\u{9bc}',
+ Script::Bengali), ('\u{9bd}', '\u{9bd}', Script::Bengali), ('\u{9be}', '\u{9c0}',
+ Script::Bengali), ('\u{9c1}', '\u{9c4}', Script::Bengali), ('\u{9c7}', '\u{9c8}',
+ Script::Bengali), ('\u{9cb}', '\u{9cc}', Script::Bengali), ('\u{9cd}', '\u{9cd}',
+ Script::Bengali), ('\u{9ce}', '\u{9ce}', Script::Bengali), ('\u{9d7}', '\u{9d7}',
+ Script::Bengali), ('\u{9dc}', '\u{9dd}', Script::Bengali), ('\u{9df}', '\u{9e1}',
+ Script::Bengali), ('\u{9e2}', '\u{9e3}', Script::Bengali), ('\u{9e6}', '\u{9ef}',
+ Script::Bengali), ('\u{9f0}', '\u{9f1}', Script::Bengali), ('\u{9f2}', '\u{9f3}',
+ Script::Bengali), ('\u{9f4}', '\u{9f9}', Script::Bengali), ('\u{9fa}', '\u{9fa}',
+ Script::Bengali), ('\u{9fb}', '\u{9fb}', Script::Bengali), ('\u{9fc}', '\u{9fc}',
+ Script::Bengali), ('\u{9fd}', '\u{9fd}', Script::Bengali), ('\u{9fe}', '\u{9fe}',
+ Script::Bengali), ('\u{a01}', '\u{a02}', Script::Gurmukhi), ('\u{a03}', '\u{a03}',
+ Script::Gurmukhi), ('\u{a05}', '\u{a0a}', Script::Gurmukhi), ('\u{a0f}', '\u{a10}',
+ Script::Gurmukhi), ('\u{a13}', '\u{a28}', Script::Gurmukhi), ('\u{a2a}', '\u{a30}',
+ Script::Gurmukhi), ('\u{a32}', '\u{a33}', Script::Gurmukhi), ('\u{a35}', '\u{a36}',
+ Script::Gurmukhi), ('\u{a38}', '\u{a39}', Script::Gurmukhi), ('\u{a3c}', '\u{a3c}',
+ Script::Gurmukhi), ('\u{a3e}', '\u{a40}', Script::Gurmukhi), ('\u{a41}', '\u{a42}',
+ Script::Gurmukhi), ('\u{a47}', '\u{a48}', Script::Gurmukhi), ('\u{a4b}', '\u{a4d}',
+ Script::Gurmukhi), ('\u{a51}', '\u{a51}', Script::Gurmukhi), ('\u{a59}', '\u{a5c}',
+ Script::Gurmukhi), ('\u{a5e}', '\u{a5e}', Script::Gurmukhi), ('\u{a66}', '\u{a6f}',
+ Script::Gurmukhi), ('\u{a70}', '\u{a71}', Script::Gurmukhi), ('\u{a72}', '\u{a74}',
+ Script::Gurmukhi), ('\u{a75}', '\u{a75}', Script::Gurmukhi), ('\u{a76}', '\u{a76}',
+ Script::Gurmukhi), ('\u{a81}', '\u{a82}', Script::Gujarati), ('\u{a83}', '\u{a83}',
+ Script::Gujarati), ('\u{a85}', '\u{a8d}', Script::Gujarati), ('\u{a8f}', '\u{a91}',
+ Script::Gujarati), ('\u{a93}', '\u{aa8}', Script::Gujarati), ('\u{aaa}', '\u{ab0}',
+ Script::Gujarati), ('\u{ab2}', '\u{ab3}', Script::Gujarati), ('\u{ab5}', '\u{ab9}',
+ Script::Gujarati), ('\u{abc}', '\u{abc}', Script::Gujarati), ('\u{abd}', '\u{abd}',
+ Script::Gujarati), ('\u{abe}', '\u{ac0}', Script::Gujarati), ('\u{ac1}', '\u{ac5}',
+ Script::Gujarati), ('\u{ac7}', '\u{ac8}', Script::Gujarati), ('\u{ac9}', '\u{ac9}',
+ Script::Gujarati), ('\u{acb}', '\u{acc}', Script::Gujarati), ('\u{acd}', '\u{acd}',
+ Script::Gujarati), ('\u{ad0}', '\u{ad0}', Script::Gujarati), ('\u{ae0}', '\u{ae1}',
+ Script::Gujarati), ('\u{ae2}', '\u{ae3}', Script::Gujarati), ('\u{ae6}', '\u{aef}',
+ Script::Gujarati), ('\u{af0}', '\u{af0}', Script::Gujarati), ('\u{af1}', '\u{af1}',
+ Script::Gujarati), ('\u{af9}', '\u{af9}', Script::Gujarati), ('\u{afa}', '\u{aff}',
+ Script::Gujarati), ('\u{b01}', '\u{b01}', Script::Oriya), ('\u{b02}', '\u{b03}',
+ Script::Oriya), ('\u{b05}', '\u{b0c}', Script::Oriya), ('\u{b0f}', '\u{b10}',
+ Script::Oriya), ('\u{b13}', '\u{b28}', Script::Oriya), ('\u{b2a}', '\u{b30}',
+ Script::Oriya), ('\u{b32}', '\u{b33}', Script::Oriya), ('\u{b35}', '\u{b39}',
+ Script::Oriya), ('\u{b3c}', '\u{b3c}', Script::Oriya), ('\u{b3d}', '\u{b3d}',
+ Script::Oriya), ('\u{b3e}', '\u{b3e}', Script::Oriya), ('\u{b3f}', '\u{b3f}',
+ Script::Oriya), ('\u{b40}', '\u{b40}', Script::Oriya), ('\u{b41}', '\u{b44}',
+ Script::Oriya), ('\u{b47}', '\u{b48}', Script::Oriya), ('\u{b4b}', '\u{b4c}',
+ Script::Oriya), ('\u{b4d}', '\u{b4d}', Script::Oriya), ('\u{b55}', '\u{b56}',
+ Script::Oriya), ('\u{b57}', '\u{b57}', Script::Oriya), ('\u{b5c}', '\u{b5d}',
+ Script::Oriya), ('\u{b5f}', '\u{b61}', Script::Oriya), ('\u{b62}', '\u{b63}',
+ Script::Oriya), ('\u{b66}', '\u{b6f}', Script::Oriya), ('\u{b70}', '\u{b70}',
+ Script::Oriya), ('\u{b71}', '\u{b71}', Script::Oriya), ('\u{b72}', '\u{b77}',
+ Script::Oriya), ('\u{b82}', '\u{b82}', Script::Tamil), ('\u{b83}', '\u{b83}',
+ Script::Tamil), ('\u{b85}', '\u{b8a}', Script::Tamil), ('\u{b8e}', '\u{b90}',
+ Script::Tamil), ('\u{b92}', '\u{b95}', Script::Tamil), ('\u{b99}', '\u{b9a}',
+ Script::Tamil), ('\u{b9c}', '\u{b9c}', Script::Tamil), ('\u{b9e}', '\u{b9f}',
+ Script::Tamil), ('\u{ba3}', '\u{ba4}', Script::Tamil), ('\u{ba8}', '\u{baa}',
+ Script::Tamil), ('\u{bae}', '\u{bb9}', Script::Tamil), ('\u{bbe}', '\u{bbf}',
+ Script::Tamil), ('\u{bc0}', '\u{bc0}', Script::Tamil), ('\u{bc1}', '\u{bc2}',
+ Script::Tamil), ('\u{bc6}', '\u{bc8}', Script::Tamil), ('\u{bca}', '\u{bcc}',
+ Script::Tamil), ('\u{bcd}', '\u{bcd}', Script::Tamil), ('\u{bd0}', '\u{bd0}',
+ Script::Tamil), ('\u{bd7}', '\u{bd7}', Script::Tamil), ('\u{be6}', '\u{bef}',
+ Script::Tamil), ('\u{bf0}', '\u{bf2}', Script::Tamil), ('\u{bf3}', '\u{bf8}',
+ Script::Tamil), ('\u{bf9}', '\u{bf9}', Script::Tamil), ('\u{bfa}', '\u{bfa}',
+ Script::Tamil), ('\u{c00}', '\u{c00}', Script::Telugu), ('\u{c01}', '\u{c03}',
+ Script::Telugu), ('\u{c04}', '\u{c04}', Script::Telugu), ('\u{c05}', '\u{c0c}',
+ Script::Telugu), ('\u{c0e}', '\u{c10}', Script::Telugu), ('\u{c12}', '\u{c28}',
+ Script::Telugu), ('\u{c2a}', '\u{c39}', Script::Telugu), ('\u{c3c}', '\u{c3c}',
Script::Telugu), ('\u{c3d}', '\u{c3d}', Script::Telugu), ('\u{c3e}', '\u{c40}',
Script::Telugu), ('\u{c41}', '\u{c44}', Script::Telugu), ('\u{c46}', '\u{c48}',
Script::Telugu), ('\u{c4a}', '\u{c4d}', Script::Telugu), ('\u{c55}', '\u{c56}',
- Script::Telugu), ('\u{c58}', '\u{c5a}', Script::Telugu), ('\u{c60}', '\u{c61}',
- Script::Telugu), ('\u{c62}', '\u{c63}', Script::Telugu), ('\u{c66}', '\u{c6f}',
- Script::Telugu), ('\u{c77}', '\u{c77}', Script::Telugu), ('\u{c78}', '\u{c7e}',
- Script::Telugu), ('\u{c7f}', '\u{c7f}', Script::Telugu), ('\u{c80}', '\u{c80}',
- Script::Kannada), ('\u{c81}', '\u{c81}', Script::Kannada), ('\u{c82}', '\u{c83}',
- Script::Kannada), ('\u{c84}', '\u{c84}', Script::Kannada), ('\u{c85}', '\u{c8c}',
- Script::Kannada), ('\u{c8e}', '\u{c90}', Script::Kannada), ('\u{c92}', '\u{ca8}',
- Script::Kannada), ('\u{caa}', '\u{cb3}', Script::Kannada), ('\u{cb5}', '\u{cb9}',
- Script::Kannada), ('\u{cbc}', '\u{cbc}', Script::Kannada), ('\u{cbd}', '\u{cbd}',
- Script::Kannada), ('\u{cbe}', '\u{cbe}', Script::Kannada), ('\u{cbf}', '\u{cbf}',
- Script::Kannada), ('\u{cc0}', '\u{cc4}', Script::Kannada), ('\u{cc6}', '\u{cc6}',
- Script::Kannada), ('\u{cc7}', '\u{cc8}', Script::Kannada), ('\u{cca}', '\u{ccb}',
- Script::Kannada), ('\u{ccc}', '\u{ccd}', Script::Kannada), ('\u{cd5}', '\u{cd6}',
- Script::Kannada), ('\u{cde}', '\u{cde}', Script::Kannada), ('\u{ce0}', '\u{ce1}',
- Script::Kannada), ('\u{ce2}', '\u{ce3}', Script::Kannada), ('\u{ce6}', '\u{cef}',
- Script::Kannada), ('\u{cf1}', '\u{cf2}', Script::Kannada), ('\u{d00}', '\u{d01}',
+ Script::Telugu), ('\u{c58}', '\u{c5a}', Script::Telugu), ('\u{c5d}', '\u{c5d}',
+ Script::Telugu), ('\u{c60}', '\u{c61}', Script::Telugu), ('\u{c62}', '\u{c63}',
+ Script::Telugu), ('\u{c66}', '\u{c6f}', Script::Telugu), ('\u{c77}', '\u{c77}',
+ Script::Telugu), ('\u{c78}', '\u{c7e}', Script::Telugu), ('\u{c7f}', '\u{c7f}',
+ Script::Telugu), ('\u{c80}', '\u{c80}', Script::Kannada), ('\u{c81}', '\u{c81}',
+ Script::Kannada), ('\u{c82}', '\u{c83}', Script::Kannada), ('\u{c84}', '\u{c84}',
+ Script::Kannada), ('\u{c85}', '\u{c8c}', Script::Kannada), ('\u{c8e}', '\u{c90}',
+ Script::Kannada), ('\u{c92}', '\u{ca8}', Script::Kannada), ('\u{caa}', '\u{cb3}',
+ Script::Kannada), ('\u{cb5}', '\u{cb9}', Script::Kannada), ('\u{cbc}', '\u{cbc}',
+ Script::Kannada), ('\u{cbd}', '\u{cbd}', Script::Kannada), ('\u{cbe}', '\u{cbe}',
+ Script::Kannada), ('\u{cbf}', '\u{cbf}', Script::Kannada), ('\u{cc0}', '\u{cc4}',
+ Script::Kannada), ('\u{cc6}', '\u{cc6}', Script::Kannada), ('\u{cc7}', '\u{cc8}',
+ Script::Kannada), ('\u{cca}', '\u{ccb}', Script::Kannada), ('\u{ccc}', '\u{ccd}',
+ Script::Kannada), ('\u{cd5}', '\u{cd6}', Script::Kannada), ('\u{cdd}', '\u{cde}',
+ Script::Kannada), ('\u{ce0}', '\u{ce1}', Script::Kannada), ('\u{ce2}', '\u{ce3}',
+ Script::Kannada), ('\u{ce6}', '\u{cef}', Script::Kannada), ('\u{cf1}', '\u{cf2}',
+ Script::Kannada), ('\u{cf3}', '\u{cf3}', Script::Kannada), ('\u{d00}', '\u{d01}',
Script::Malayalam), ('\u{d02}', '\u{d03}', Script::Malayalam), ('\u{d04}', '\u{d0c}',
Script::Malayalam), ('\u{d0e}', '\u{d10}', Script::Malayalam), ('\u{d12}', '\u{d3a}',
Script::Malayalam), ('\u{d3b}', '\u{d3c}', Script::Malayalam), ('\u{d3d}', '\u{d3d}',
@@ -2124,7 +2209,7 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
'\u{ea5}', Script::Lao), ('\u{ea7}', '\u{eb0}', Script::Lao), ('\u{eb1}', '\u{eb1}',
Script::Lao), ('\u{eb2}', '\u{eb3}', Script::Lao), ('\u{eb4}', '\u{ebc}', Script::Lao),
('\u{ebd}', '\u{ebd}', Script::Lao), ('\u{ec0}', '\u{ec4}', Script::Lao), ('\u{ec6}',
- '\u{ec6}', Script::Lao), ('\u{ec8}', '\u{ecd}', Script::Lao), ('\u{ed0}', '\u{ed9}',
+ '\u{ec6}', Script::Lao), ('\u{ec8}', '\u{ece}', Script::Lao), ('\u{ed0}', '\u{ed9}',
Script::Lao), ('\u{edc}', '\u{edf}', Script::Lao), ('\u{f00}', '\u{f00}',
Script::Tibetan), ('\u{f01}', '\u{f03}', Script::Tibetan), ('\u{f04}', '\u{f12}',
Script::Tibetan), ('\u{f13}', '\u{f13}', Script::Tibetan), ('\u{f14}', '\u{f14}',
@@ -2185,9 +2270,10 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
('\u{169b}', '\u{169b}', Script::Ogham), ('\u{169c}', '\u{169c}', Script::Ogham),
('\u{16a0}', '\u{16ea}', Script::Runic), ('\u{16eb}', '\u{16ed}', Script::Common),
('\u{16ee}', '\u{16f0}', Script::Runic), ('\u{16f1}', '\u{16f8}', Script::Runic),
- ('\u{1700}', '\u{170c}', Script::Tagalog), ('\u{170e}', '\u{1711}', Script::Tagalog),
- ('\u{1712}', '\u{1714}', Script::Tagalog), ('\u{1720}', '\u{1731}', Script::Hanunoo),
- ('\u{1732}', '\u{1734}', Script::Hanunoo), ('\u{1735}', '\u{1736}', Script::Common),
+ ('\u{1700}', '\u{1711}', Script::Tagalog), ('\u{1712}', '\u{1714}', Script::Tagalog),
+ ('\u{1715}', '\u{1715}', Script::Tagalog), ('\u{171f}', '\u{171f}', Script::Tagalog),
+ ('\u{1720}', '\u{1731}', Script::Hanunoo), ('\u{1732}', '\u{1733}', Script::Hanunoo),
+ ('\u{1734}', '\u{1734}', Script::Hanunoo), ('\u{1735}', '\u{1736}', Script::Common),
('\u{1740}', '\u{1751}', Script::Buhid), ('\u{1752}', '\u{1753}', Script::Buhid),
('\u{1760}', '\u{176c}', Script::Tagbanwa), ('\u{176e}', '\u{1770}', Script::Tagbanwa),
('\u{1772}', '\u{1773}', Script::Tagbanwa), ('\u{1780}', '\u{17b3}', Script::Khmer),
@@ -2202,197 +2288,197 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
('\u{1802}', '\u{1803}', Script::Common), ('\u{1804}', '\u{1804}', Script::Mongolian),
('\u{1805}', '\u{1805}', Script::Common), ('\u{1806}', '\u{1806}', Script::Mongolian),
('\u{1807}', '\u{180a}', Script::Mongolian), ('\u{180b}', '\u{180d}', Script::Mongolian),
- ('\u{180e}', '\u{180e}', Script::Mongolian), ('\u{1810}', '\u{1819}', Script::Mongolian),
- ('\u{1820}', '\u{1842}', Script::Mongolian), ('\u{1843}', '\u{1843}', Script::Mongolian),
- ('\u{1844}', '\u{1878}', Script::Mongolian), ('\u{1880}', '\u{1884}', Script::Mongolian),
- ('\u{1885}', '\u{1886}', Script::Mongolian), ('\u{1887}', '\u{18a8}', Script::Mongolian),
- ('\u{18a9}', '\u{18a9}', Script::Mongolian), ('\u{18aa}', '\u{18aa}', Script::Mongolian),
- ('\u{18b0}', '\u{18f5}', Script::Canadian_Aboriginal), ('\u{1900}', '\u{191e}',
- Script::Limbu), ('\u{1920}', '\u{1922}', Script::Limbu), ('\u{1923}', '\u{1926}',
- Script::Limbu), ('\u{1927}', '\u{1928}', Script::Limbu), ('\u{1929}', '\u{192b}',
- Script::Limbu), ('\u{1930}', '\u{1931}', Script::Limbu), ('\u{1932}', '\u{1932}',
- Script::Limbu), ('\u{1933}', '\u{1938}', Script::Limbu), ('\u{1939}', '\u{193b}',
- Script::Limbu), ('\u{1940}', '\u{1940}', Script::Limbu), ('\u{1944}', '\u{1945}',
- Script::Limbu), ('\u{1946}', '\u{194f}', Script::Limbu), ('\u{1950}', '\u{196d}',
- Script::Tai_Le), ('\u{1970}', '\u{1974}', Script::Tai_Le), ('\u{1980}', '\u{19ab}',
- Script::New_Tai_Lue), ('\u{19b0}', '\u{19c9}', Script::New_Tai_Lue), ('\u{19d0}',
- '\u{19d9}', Script::New_Tai_Lue), ('\u{19da}', '\u{19da}', Script::New_Tai_Lue),
- ('\u{19de}', '\u{19df}', Script::New_Tai_Lue), ('\u{19e0}', '\u{19ff}', Script::Khmer),
- ('\u{1a00}', '\u{1a16}', Script::Buginese), ('\u{1a17}', '\u{1a18}', Script::Buginese),
- ('\u{1a19}', '\u{1a1a}', Script::Buginese), ('\u{1a1b}', '\u{1a1b}', Script::Buginese),
- ('\u{1a1e}', '\u{1a1f}', Script::Buginese), ('\u{1a20}', '\u{1a54}', Script::Tai_Tham),
- ('\u{1a55}', '\u{1a55}', Script::Tai_Tham), ('\u{1a56}', '\u{1a56}', Script::Tai_Tham),
- ('\u{1a57}', '\u{1a57}', Script::Tai_Tham), ('\u{1a58}', '\u{1a5e}', Script::Tai_Tham),
- ('\u{1a60}', '\u{1a60}', Script::Tai_Tham), ('\u{1a61}', '\u{1a61}', Script::Tai_Tham),
- ('\u{1a62}', '\u{1a62}', Script::Tai_Tham), ('\u{1a63}', '\u{1a64}', Script::Tai_Tham),
- ('\u{1a65}', '\u{1a6c}', Script::Tai_Tham), ('\u{1a6d}', '\u{1a72}', Script::Tai_Tham),
- ('\u{1a73}', '\u{1a7c}', Script::Tai_Tham), ('\u{1a7f}', '\u{1a7f}', Script::Tai_Tham),
- ('\u{1a80}', '\u{1a89}', Script::Tai_Tham), ('\u{1a90}', '\u{1a99}', Script::Tai_Tham),
- ('\u{1aa0}', '\u{1aa6}', Script::Tai_Tham), ('\u{1aa7}', '\u{1aa7}', Script::Tai_Tham),
- ('\u{1aa8}', '\u{1aad}', Script::Tai_Tham), ('\u{1ab0}', '\u{1abd}', Script::Inherited),
- ('\u{1abe}', '\u{1abe}', Script::Inherited), ('\u{1abf}', '\u{1ac0}', Script::Inherited),
- ('\u{1b00}', '\u{1b03}', Script::Balinese), ('\u{1b04}', '\u{1b04}', Script::Balinese),
- ('\u{1b05}', '\u{1b33}', Script::Balinese), ('\u{1b34}', '\u{1b34}', Script::Balinese),
- ('\u{1b35}', '\u{1b35}', Script::Balinese), ('\u{1b36}', '\u{1b3a}', Script::Balinese),
- ('\u{1b3b}', '\u{1b3b}', Script::Balinese), ('\u{1b3c}', '\u{1b3c}', Script::Balinese),
- ('\u{1b3d}', '\u{1b41}', Script::Balinese), ('\u{1b42}', '\u{1b42}', Script::Balinese),
- ('\u{1b43}', '\u{1b44}', Script::Balinese), ('\u{1b45}', '\u{1b4b}', Script::Balinese),
- ('\u{1b50}', '\u{1b59}', Script::Balinese), ('\u{1b5a}', '\u{1b60}', Script::Balinese),
- ('\u{1b61}', '\u{1b6a}', Script::Balinese), ('\u{1b6b}', '\u{1b73}', Script::Balinese),
- ('\u{1b74}', '\u{1b7c}', Script::Balinese), ('\u{1b80}', '\u{1b81}', Script::Sundanese),
- ('\u{1b82}', '\u{1b82}', Script::Sundanese), ('\u{1b83}', '\u{1ba0}', Script::Sundanese),
- ('\u{1ba1}', '\u{1ba1}', Script::Sundanese), ('\u{1ba2}', '\u{1ba5}', Script::Sundanese),
- ('\u{1ba6}', '\u{1ba7}', Script::Sundanese), ('\u{1ba8}', '\u{1ba9}', Script::Sundanese),
- ('\u{1baa}', '\u{1baa}', Script::Sundanese), ('\u{1bab}', '\u{1bad}', Script::Sundanese),
- ('\u{1bae}', '\u{1baf}', Script::Sundanese), ('\u{1bb0}', '\u{1bb9}', Script::Sundanese),
- ('\u{1bba}', '\u{1bbf}', Script::Sundanese), ('\u{1bc0}', '\u{1be5}', Script::Batak),
- ('\u{1be6}', '\u{1be6}', Script::Batak), ('\u{1be7}', '\u{1be7}', Script::Batak),
- ('\u{1be8}', '\u{1be9}', Script::Batak), ('\u{1bea}', '\u{1bec}', Script::Batak),
- ('\u{1bed}', '\u{1bed}', Script::Batak), ('\u{1bee}', '\u{1bee}', Script::Batak),
- ('\u{1bef}', '\u{1bf1}', Script::Batak), ('\u{1bf2}', '\u{1bf3}', Script::Batak),
- ('\u{1bfc}', '\u{1bff}', Script::Batak), ('\u{1c00}', '\u{1c23}', Script::Lepcha),
- ('\u{1c24}', '\u{1c2b}', Script::Lepcha), ('\u{1c2c}', '\u{1c33}', Script::Lepcha),
- ('\u{1c34}', '\u{1c35}', Script::Lepcha), ('\u{1c36}', '\u{1c37}', Script::Lepcha),
- ('\u{1c3b}', '\u{1c3f}', Script::Lepcha), ('\u{1c40}', '\u{1c49}', Script::Lepcha),
- ('\u{1c4d}', '\u{1c4f}', Script::Lepcha), ('\u{1c50}', '\u{1c59}', Script::Ol_Chiki),
- ('\u{1c5a}', '\u{1c77}', Script::Ol_Chiki), ('\u{1c78}', '\u{1c7d}', Script::Ol_Chiki),
- ('\u{1c7e}', '\u{1c7f}', Script::Ol_Chiki), ('\u{1c80}', '\u{1c88}', Script::Cyrillic),
- ('\u{1c90}', '\u{1cba}', Script::Georgian), ('\u{1cbd}', '\u{1cbf}', Script::Georgian),
- ('\u{1cc0}', '\u{1cc7}', Script::Sundanese), ('\u{1cd0}', '\u{1cd2}', Script::Inherited),
- ('\u{1cd3}', '\u{1cd3}', Script::Common), ('\u{1cd4}', '\u{1ce0}', Script::Inherited),
- ('\u{1ce1}', '\u{1ce1}', Script::Common), ('\u{1ce2}', '\u{1ce8}', Script::Inherited),
- ('\u{1ce9}', '\u{1cec}', Script::Common), ('\u{1ced}', '\u{1ced}', Script::Inherited),
- ('\u{1cee}', '\u{1cf3}', Script::Common), ('\u{1cf4}', '\u{1cf4}', Script::Inherited),
- ('\u{1cf5}', '\u{1cf6}', Script::Common), ('\u{1cf7}', '\u{1cf7}', Script::Common),
- ('\u{1cf8}', '\u{1cf9}', Script::Inherited), ('\u{1cfa}', '\u{1cfa}', Script::Common),
- ('\u{1d00}', '\u{1d25}', Script::Latin), ('\u{1d26}', '\u{1d2a}', Script::Greek),
- ('\u{1d2b}', '\u{1d2b}', Script::Cyrillic), ('\u{1d2c}', '\u{1d5c}', Script::Latin),
- ('\u{1d5d}', '\u{1d61}', Script::Greek), ('\u{1d62}', '\u{1d65}', Script::Latin),
- ('\u{1d66}', '\u{1d6a}', Script::Greek), ('\u{1d6b}', '\u{1d77}', Script::Latin),
- ('\u{1d78}', '\u{1d78}', Script::Cyrillic), ('\u{1d79}', '\u{1d9a}', Script::Latin),
- ('\u{1d9b}', '\u{1dbe}', Script::Latin), ('\u{1dbf}', '\u{1dbf}', Script::Greek),
- ('\u{1dc0}', '\u{1df9}', Script::Inherited), ('\u{1dfb}', '\u{1dff}', Script::Inherited),
- ('\u{1e00}', '\u{1eff}', Script::Latin), ('\u{1f00}', '\u{1f15}', Script::Greek),
- ('\u{1f18}', '\u{1f1d}', Script::Greek), ('\u{1f20}', '\u{1f45}', Script::Greek),
- ('\u{1f48}', '\u{1f4d}', Script::Greek), ('\u{1f50}', '\u{1f57}', Script::Greek),
- ('\u{1f59}', '\u{1f59}', Script::Greek), ('\u{1f5b}', '\u{1f5b}', Script::Greek),
- ('\u{1f5d}', '\u{1f5d}', Script::Greek), ('\u{1f5f}', '\u{1f7d}', Script::Greek),
- ('\u{1f80}', '\u{1fb4}', Script::Greek), ('\u{1fb6}', '\u{1fbc}', Script::Greek),
- ('\u{1fbd}', '\u{1fbd}', Script::Greek), ('\u{1fbe}', '\u{1fbe}', Script::Greek),
- ('\u{1fbf}', '\u{1fc1}', Script::Greek), ('\u{1fc2}', '\u{1fc4}', Script::Greek),
- ('\u{1fc6}', '\u{1fcc}', Script::Greek), ('\u{1fcd}', '\u{1fcf}', Script::Greek),
- ('\u{1fd0}', '\u{1fd3}', Script::Greek), ('\u{1fd6}', '\u{1fdb}', Script::Greek),
- ('\u{1fdd}', '\u{1fdf}', Script::Greek), ('\u{1fe0}', '\u{1fec}', Script::Greek),
- ('\u{1fed}', '\u{1fef}', Script::Greek), ('\u{1ff2}', '\u{1ff4}', Script::Greek),
- ('\u{1ff6}', '\u{1ffc}', Script::Greek), ('\u{1ffd}', '\u{1ffe}', Script::Greek),
- ('\u{2000}', '\u{200a}', Script::Common), ('\u{200b}', '\u{200b}', Script::Common),
- ('\u{200c}', '\u{200d}', Script::Inherited), ('\u{200e}', '\u{200f}', Script::Common),
- ('\u{2010}', '\u{2015}', Script::Common), ('\u{2016}', '\u{2017}', Script::Common),
- ('\u{2018}', '\u{2018}', Script::Common), ('\u{2019}', '\u{2019}', Script::Common),
- ('\u{201a}', '\u{201a}', Script::Common), ('\u{201b}', '\u{201c}', Script::Common),
- ('\u{201d}', '\u{201d}', Script::Common), ('\u{201e}', '\u{201e}', Script::Common),
- ('\u{201f}', '\u{201f}', Script::Common), ('\u{2020}', '\u{2027}', Script::Common),
- ('\u{2028}', '\u{2028}', Script::Common), ('\u{2029}', '\u{2029}', Script::Common),
- ('\u{202a}', '\u{202e}', Script::Common), ('\u{202f}', '\u{202f}', Script::Common),
- ('\u{2030}', '\u{2038}', Script::Common), ('\u{2039}', '\u{2039}', Script::Common),
- ('\u{203a}', '\u{203a}', Script::Common), ('\u{203b}', '\u{203e}', Script::Common),
- ('\u{203f}', '\u{2040}', Script::Common), ('\u{2041}', '\u{2043}', Script::Common),
- ('\u{2044}', '\u{2044}', Script::Common), ('\u{2045}', '\u{2045}', Script::Common),
- ('\u{2046}', '\u{2046}', Script::Common), ('\u{2047}', '\u{2051}', Script::Common),
- ('\u{2052}', '\u{2052}', Script::Common), ('\u{2053}', '\u{2053}', Script::Common),
- ('\u{2054}', '\u{2054}', Script::Common), ('\u{2055}', '\u{205e}', Script::Common),
- ('\u{205f}', '\u{205f}', Script::Common), ('\u{2060}', '\u{2064}', Script::Common),
- ('\u{2066}', '\u{206f}', Script::Common), ('\u{2070}', '\u{2070}', Script::Common),
- ('\u{2071}', '\u{2071}', Script::Latin), ('\u{2074}', '\u{2079}', Script::Common),
- ('\u{207a}', '\u{207c}', Script::Common), ('\u{207d}', '\u{207d}', Script::Common),
- ('\u{207e}', '\u{207e}', Script::Common), ('\u{207f}', '\u{207f}', Script::Latin),
- ('\u{2080}', '\u{2089}', Script::Common), ('\u{208a}', '\u{208c}', Script::Common),
- ('\u{208d}', '\u{208d}', Script::Common), ('\u{208e}', '\u{208e}', Script::Common),
- ('\u{2090}', '\u{209c}', Script::Latin), ('\u{20a0}', '\u{20bf}', Script::Common),
- ('\u{20d0}', '\u{20dc}', Script::Inherited), ('\u{20dd}', '\u{20e0}', Script::Inherited),
- ('\u{20e1}', '\u{20e1}', Script::Inherited), ('\u{20e2}', '\u{20e4}', Script::Inherited),
- ('\u{20e5}', '\u{20f0}', Script::Inherited), ('\u{2100}', '\u{2101}', Script::Common),
- ('\u{2102}', '\u{2102}', Script::Common), ('\u{2103}', '\u{2106}', Script::Common),
- ('\u{2107}', '\u{2107}', Script::Common), ('\u{2108}', '\u{2109}', Script::Common),
- ('\u{210a}', '\u{2113}', Script::Common), ('\u{2114}', '\u{2114}', Script::Common),
- ('\u{2115}', '\u{2115}', Script::Common), ('\u{2116}', '\u{2117}', Script::Common),
- ('\u{2118}', '\u{2118}', Script::Common), ('\u{2119}', '\u{211d}', Script::Common),
- ('\u{211e}', '\u{2123}', Script::Common), ('\u{2124}', '\u{2124}', Script::Common),
- ('\u{2125}', '\u{2125}', Script::Common), ('\u{2126}', '\u{2126}', Script::Greek),
- ('\u{2127}', '\u{2127}', Script::Common), ('\u{2128}', '\u{2128}', Script::Common),
- ('\u{2129}', '\u{2129}', Script::Common), ('\u{212a}', '\u{212b}', Script::Latin),
- ('\u{212c}', '\u{212d}', Script::Common), ('\u{212e}', '\u{212e}', Script::Common),
- ('\u{212f}', '\u{2131}', Script::Common), ('\u{2132}', '\u{2132}', Script::Latin),
- ('\u{2133}', '\u{2134}', Script::Common), ('\u{2135}', '\u{2138}', Script::Common),
- ('\u{2139}', '\u{2139}', Script::Common), ('\u{213a}', '\u{213b}', Script::Common),
- ('\u{213c}', '\u{213f}', Script::Common), ('\u{2140}', '\u{2144}', Script::Common),
- ('\u{2145}', '\u{2149}', Script::Common), ('\u{214a}', '\u{214a}', Script::Common),
- ('\u{214b}', '\u{214b}', Script::Common), ('\u{214c}', '\u{214d}', Script::Common),
- ('\u{214e}', '\u{214e}', Script::Latin), ('\u{214f}', '\u{214f}', Script::Common),
- ('\u{2150}', '\u{215f}', Script::Common), ('\u{2160}', '\u{2182}', Script::Latin),
- ('\u{2183}', '\u{2184}', Script::Latin), ('\u{2185}', '\u{2188}', Script::Latin),
- ('\u{2189}', '\u{2189}', Script::Common), ('\u{218a}', '\u{218b}', Script::Common),
- ('\u{2190}', '\u{2194}', Script::Common), ('\u{2195}', '\u{2199}', Script::Common),
- ('\u{219a}', '\u{219b}', Script::Common), ('\u{219c}', '\u{219f}', Script::Common),
- ('\u{21a0}', '\u{21a0}', Script::Common), ('\u{21a1}', '\u{21a2}', Script::Common),
- ('\u{21a3}', '\u{21a3}', Script::Common), ('\u{21a4}', '\u{21a5}', Script::Common),
- ('\u{21a6}', '\u{21a6}', Script::Common), ('\u{21a7}', '\u{21ad}', Script::Common),
- ('\u{21ae}', '\u{21ae}', Script::Common), ('\u{21af}', '\u{21cd}', Script::Common),
- ('\u{21ce}', '\u{21cf}', Script::Common), ('\u{21d0}', '\u{21d1}', Script::Common),
- ('\u{21d2}', '\u{21d2}', Script::Common), ('\u{21d3}', '\u{21d3}', Script::Common),
- ('\u{21d4}', '\u{21d4}', Script::Common), ('\u{21d5}', '\u{21f3}', Script::Common),
- ('\u{21f4}', '\u{22ff}', Script::Common), ('\u{2300}', '\u{2307}', Script::Common),
- ('\u{2308}', '\u{2308}', Script::Common), ('\u{2309}', '\u{2309}', Script::Common),
- ('\u{230a}', '\u{230a}', Script::Common), ('\u{230b}', '\u{230b}', Script::Common),
- ('\u{230c}', '\u{231f}', Script::Common), ('\u{2320}', '\u{2321}', Script::Common),
- ('\u{2322}', '\u{2328}', Script::Common), ('\u{2329}', '\u{2329}', Script::Common),
- ('\u{232a}', '\u{232a}', Script::Common), ('\u{232b}', '\u{237b}', Script::Common),
- ('\u{237c}', '\u{237c}', Script::Common), ('\u{237d}', '\u{239a}', Script::Common),
- ('\u{239b}', '\u{23b3}', Script::Common), ('\u{23b4}', '\u{23db}', Script::Common),
- ('\u{23dc}', '\u{23e1}', Script::Common), ('\u{23e2}', '\u{2426}', Script::Common),
- ('\u{2440}', '\u{244a}', Script::Common), ('\u{2460}', '\u{249b}', Script::Common),
- ('\u{249c}', '\u{24e9}', Script::Common), ('\u{24ea}', '\u{24ff}', Script::Common),
- ('\u{2500}', '\u{25b6}', Script::Common), ('\u{25b7}', '\u{25b7}', Script::Common),
- ('\u{25b8}', '\u{25c0}', Script::Common), ('\u{25c1}', '\u{25c1}', Script::Common),
- ('\u{25c2}', '\u{25f7}', Script::Common), ('\u{25f8}', '\u{25ff}', Script::Common),
- ('\u{2600}', '\u{266e}', Script::Common), ('\u{266f}', '\u{266f}', Script::Common),
- ('\u{2670}', '\u{2767}', Script::Common), ('\u{2768}', '\u{2768}', Script::Common),
- ('\u{2769}', '\u{2769}', Script::Common), ('\u{276a}', '\u{276a}', Script::Common),
- ('\u{276b}', '\u{276b}', Script::Common), ('\u{276c}', '\u{276c}', Script::Common),
- ('\u{276d}', '\u{276d}', Script::Common), ('\u{276e}', '\u{276e}', Script::Common),
- ('\u{276f}', '\u{276f}', Script::Common), ('\u{2770}', '\u{2770}', Script::Common),
- ('\u{2771}', '\u{2771}', Script::Common), ('\u{2772}', '\u{2772}', Script::Common),
- ('\u{2773}', '\u{2773}', Script::Common), ('\u{2774}', '\u{2774}', Script::Common),
- ('\u{2775}', '\u{2775}', Script::Common), ('\u{2776}', '\u{2793}', Script::Common),
- ('\u{2794}', '\u{27bf}', Script::Common), ('\u{27c0}', '\u{27c4}', Script::Common),
- ('\u{27c5}', '\u{27c5}', Script::Common), ('\u{27c6}', '\u{27c6}', Script::Common),
- ('\u{27c7}', '\u{27e5}', Script::Common), ('\u{27e6}', '\u{27e6}', Script::Common),
- ('\u{27e7}', '\u{27e7}', Script::Common), ('\u{27e8}', '\u{27e8}', Script::Common),
- ('\u{27e9}', '\u{27e9}', Script::Common), ('\u{27ea}', '\u{27ea}', Script::Common),
- ('\u{27eb}', '\u{27eb}', Script::Common), ('\u{27ec}', '\u{27ec}', Script::Common),
- ('\u{27ed}', '\u{27ed}', Script::Common), ('\u{27ee}', '\u{27ee}', Script::Common),
- ('\u{27ef}', '\u{27ef}', Script::Common), ('\u{27f0}', '\u{27ff}', Script::Common),
- ('\u{2800}', '\u{28ff}', Script::Braille), ('\u{2900}', '\u{2982}', Script::Common),
- ('\u{2983}', '\u{2983}', Script::Common), ('\u{2984}', '\u{2984}', Script::Common),
- ('\u{2985}', '\u{2985}', Script::Common), ('\u{2986}', '\u{2986}', Script::Common),
- ('\u{2987}', '\u{2987}', Script::Common), ('\u{2988}', '\u{2988}', Script::Common),
- ('\u{2989}', '\u{2989}', Script::Common), ('\u{298a}', '\u{298a}', Script::Common),
- ('\u{298b}', '\u{298b}', Script::Common), ('\u{298c}', '\u{298c}', Script::Common),
- ('\u{298d}', '\u{298d}', Script::Common), ('\u{298e}', '\u{298e}', Script::Common),
- ('\u{298f}', '\u{298f}', Script::Common), ('\u{2990}', '\u{2990}', Script::Common),
- ('\u{2991}', '\u{2991}', Script::Common), ('\u{2992}', '\u{2992}', Script::Common),
- ('\u{2993}', '\u{2993}', Script::Common), ('\u{2994}', '\u{2994}', Script::Common),
- ('\u{2995}', '\u{2995}', Script::Common), ('\u{2996}', '\u{2996}', Script::Common),
- ('\u{2997}', '\u{2997}', Script::Common), ('\u{2998}', '\u{2998}', Script::Common),
- ('\u{2999}', '\u{29d7}', Script::Common), ('\u{29d8}', '\u{29d8}', Script::Common),
- ('\u{29d9}', '\u{29d9}', Script::Common), ('\u{29da}', '\u{29da}', Script::Common),
- ('\u{29db}', '\u{29db}', Script::Common), ('\u{29dc}', '\u{29fb}', Script::Common),
- ('\u{29fc}', '\u{29fc}', Script::Common), ('\u{29fd}', '\u{29fd}', Script::Common),
- ('\u{29fe}', '\u{2aff}', Script::Common), ('\u{2b00}', '\u{2b2f}', Script::Common),
- ('\u{2b30}', '\u{2b44}', Script::Common), ('\u{2b45}', '\u{2b46}', Script::Common),
- ('\u{2b47}', '\u{2b4c}', Script::Common), ('\u{2b4d}', '\u{2b73}', Script::Common),
- ('\u{2b76}', '\u{2b95}', Script::Common), ('\u{2b97}', '\u{2bff}', Script::Common),
- ('\u{2c00}', '\u{2c2e}', Script::Glagolitic), ('\u{2c30}', '\u{2c5e}',
+ ('\u{180e}', '\u{180e}', Script::Mongolian), ('\u{180f}', '\u{180f}', Script::Mongolian),
+ ('\u{1810}', '\u{1819}', Script::Mongolian), ('\u{1820}', '\u{1842}', Script::Mongolian),
+ ('\u{1843}', '\u{1843}', Script::Mongolian), ('\u{1844}', '\u{1878}', Script::Mongolian),
+ ('\u{1880}', '\u{1884}', Script::Mongolian), ('\u{1885}', '\u{1886}', Script::Mongolian),
+ ('\u{1887}', '\u{18a8}', Script::Mongolian), ('\u{18a9}', '\u{18a9}', Script::Mongolian),
+ ('\u{18aa}', '\u{18aa}', Script::Mongolian), ('\u{18b0}', '\u{18f5}',
+ Script::Canadian_Aboriginal), ('\u{1900}', '\u{191e}', Script::Limbu), ('\u{1920}',
+ '\u{1922}', Script::Limbu), ('\u{1923}', '\u{1926}', Script::Limbu), ('\u{1927}',
+ '\u{1928}', Script::Limbu), ('\u{1929}', '\u{192b}', Script::Limbu), ('\u{1930}',
+ '\u{1931}', Script::Limbu), ('\u{1932}', '\u{1932}', Script::Limbu), ('\u{1933}',
+ '\u{1938}', Script::Limbu), ('\u{1939}', '\u{193b}', Script::Limbu), ('\u{1940}',
+ '\u{1940}', Script::Limbu), ('\u{1944}', '\u{1945}', Script::Limbu), ('\u{1946}',
+ '\u{194f}', Script::Limbu), ('\u{1950}', '\u{196d}', Script::Tai_Le), ('\u{1970}',
+ '\u{1974}', Script::Tai_Le), ('\u{1980}', '\u{19ab}', Script::New_Tai_Lue), ('\u{19b0}',
+ '\u{19c9}', Script::New_Tai_Lue), ('\u{19d0}', '\u{19d9}', Script::New_Tai_Lue),
+ ('\u{19da}', '\u{19da}', Script::New_Tai_Lue), ('\u{19de}', '\u{19df}',
+ Script::New_Tai_Lue), ('\u{19e0}', '\u{19ff}', Script::Khmer), ('\u{1a00}', '\u{1a16}',
+ Script::Buginese), ('\u{1a17}', '\u{1a18}', Script::Buginese), ('\u{1a19}', '\u{1a1a}',
+ Script::Buginese), ('\u{1a1b}', '\u{1a1b}', Script::Buginese), ('\u{1a1e}', '\u{1a1f}',
+ Script::Buginese), ('\u{1a20}', '\u{1a54}', Script::Tai_Tham), ('\u{1a55}', '\u{1a55}',
+ Script::Tai_Tham), ('\u{1a56}', '\u{1a56}', Script::Tai_Tham), ('\u{1a57}', '\u{1a57}',
+ Script::Tai_Tham), ('\u{1a58}', '\u{1a5e}', Script::Tai_Tham), ('\u{1a60}', '\u{1a60}',
+ Script::Tai_Tham), ('\u{1a61}', '\u{1a61}', Script::Tai_Tham), ('\u{1a62}', '\u{1a62}',
+ Script::Tai_Tham), ('\u{1a63}', '\u{1a64}', Script::Tai_Tham), ('\u{1a65}', '\u{1a6c}',
+ Script::Tai_Tham), ('\u{1a6d}', '\u{1a72}', Script::Tai_Tham), ('\u{1a73}', '\u{1a7c}',
+ Script::Tai_Tham), ('\u{1a7f}', '\u{1a7f}', Script::Tai_Tham), ('\u{1a80}', '\u{1a89}',
+ Script::Tai_Tham), ('\u{1a90}', '\u{1a99}', Script::Tai_Tham), ('\u{1aa0}', '\u{1aa6}',
+ Script::Tai_Tham), ('\u{1aa7}', '\u{1aa7}', Script::Tai_Tham), ('\u{1aa8}', '\u{1aad}',
+ Script::Tai_Tham), ('\u{1ab0}', '\u{1abd}', Script::Inherited), ('\u{1abe}', '\u{1abe}',
+ Script::Inherited), ('\u{1abf}', '\u{1ace}', Script::Inherited), ('\u{1b00}', '\u{1b03}',
+ Script::Balinese), ('\u{1b04}', '\u{1b04}', Script::Balinese), ('\u{1b05}', '\u{1b33}',
+ Script::Balinese), ('\u{1b34}', '\u{1b34}', Script::Balinese), ('\u{1b35}', '\u{1b35}',
+ Script::Balinese), ('\u{1b36}', '\u{1b3a}', Script::Balinese), ('\u{1b3b}', '\u{1b3b}',
+ Script::Balinese), ('\u{1b3c}', '\u{1b3c}', Script::Balinese), ('\u{1b3d}', '\u{1b41}',
+ Script::Balinese), ('\u{1b42}', '\u{1b42}', Script::Balinese), ('\u{1b43}', '\u{1b44}',
+ Script::Balinese), ('\u{1b45}', '\u{1b4c}', Script::Balinese), ('\u{1b50}', '\u{1b59}',
+ Script::Balinese), ('\u{1b5a}', '\u{1b60}', Script::Balinese), ('\u{1b61}', '\u{1b6a}',
+ Script::Balinese), ('\u{1b6b}', '\u{1b73}', Script::Balinese), ('\u{1b74}', '\u{1b7c}',
+ Script::Balinese), ('\u{1b7d}', '\u{1b7e}', Script::Balinese), ('\u{1b80}', '\u{1b81}',
+ Script::Sundanese), ('\u{1b82}', '\u{1b82}', Script::Sundanese), ('\u{1b83}', '\u{1ba0}',
+ Script::Sundanese), ('\u{1ba1}', '\u{1ba1}', Script::Sundanese), ('\u{1ba2}', '\u{1ba5}',
+ Script::Sundanese), ('\u{1ba6}', '\u{1ba7}', Script::Sundanese), ('\u{1ba8}', '\u{1ba9}',
+ Script::Sundanese), ('\u{1baa}', '\u{1baa}', Script::Sundanese), ('\u{1bab}', '\u{1bad}',
+ Script::Sundanese), ('\u{1bae}', '\u{1baf}', Script::Sundanese), ('\u{1bb0}', '\u{1bb9}',
+ Script::Sundanese), ('\u{1bba}', '\u{1bbf}', Script::Sundanese), ('\u{1bc0}', '\u{1be5}',
+ Script::Batak), ('\u{1be6}', '\u{1be6}', Script::Batak), ('\u{1be7}', '\u{1be7}',
+ Script::Batak), ('\u{1be8}', '\u{1be9}', Script::Batak), ('\u{1bea}', '\u{1bec}',
+ Script::Batak), ('\u{1bed}', '\u{1bed}', Script::Batak), ('\u{1bee}', '\u{1bee}',
+ Script::Batak), ('\u{1bef}', '\u{1bf1}', Script::Batak), ('\u{1bf2}', '\u{1bf3}',
+ Script::Batak), ('\u{1bfc}', '\u{1bff}', Script::Batak), ('\u{1c00}', '\u{1c23}',
+ Script::Lepcha), ('\u{1c24}', '\u{1c2b}', Script::Lepcha), ('\u{1c2c}', '\u{1c33}',
+ Script::Lepcha), ('\u{1c34}', '\u{1c35}', Script::Lepcha), ('\u{1c36}', '\u{1c37}',
+ Script::Lepcha), ('\u{1c3b}', '\u{1c3f}', Script::Lepcha), ('\u{1c40}', '\u{1c49}',
+ Script::Lepcha), ('\u{1c4d}', '\u{1c4f}', Script::Lepcha), ('\u{1c50}', '\u{1c59}',
+ Script::Ol_Chiki), ('\u{1c5a}', '\u{1c77}', Script::Ol_Chiki), ('\u{1c78}', '\u{1c7d}',
+ Script::Ol_Chiki), ('\u{1c7e}', '\u{1c7f}', Script::Ol_Chiki), ('\u{1c80}', '\u{1c88}',
+ Script::Cyrillic), ('\u{1c90}', '\u{1cba}', Script::Georgian), ('\u{1cbd}', '\u{1cbf}',
+ Script::Georgian), ('\u{1cc0}', '\u{1cc7}', Script::Sundanese), ('\u{1cd0}', '\u{1cd2}',
+ Script::Inherited), ('\u{1cd3}', '\u{1cd3}', Script::Common), ('\u{1cd4}', '\u{1ce0}',
+ Script::Inherited), ('\u{1ce1}', '\u{1ce1}', Script::Common), ('\u{1ce2}', '\u{1ce8}',
+ Script::Inherited), ('\u{1ce9}', '\u{1cec}', Script::Common), ('\u{1ced}', '\u{1ced}',
+ Script::Inherited), ('\u{1cee}', '\u{1cf3}', Script::Common), ('\u{1cf4}', '\u{1cf4}',
+ Script::Inherited), ('\u{1cf5}', '\u{1cf6}', Script::Common), ('\u{1cf7}', '\u{1cf7}',
+ Script::Common), ('\u{1cf8}', '\u{1cf9}', Script::Inherited), ('\u{1cfa}', '\u{1cfa}',
+ Script::Common), ('\u{1d00}', '\u{1d25}', Script::Latin), ('\u{1d26}', '\u{1d2a}',
+ Script::Greek), ('\u{1d2b}', '\u{1d2b}', Script::Cyrillic), ('\u{1d2c}', '\u{1d5c}',
+ Script::Latin), ('\u{1d5d}', '\u{1d61}', Script::Greek), ('\u{1d62}', '\u{1d65}',
+ Script::Latin), ('\u{1d66}', '\u{1d6a}', Script::Greek), ('\u{1d6b}', '\u{1d77}',
+ Script::Latin), ('\u{1d78}', '\u{1d78}', Script::Cyrillic), ('\u{1d79}', '\u{1d9a}',
+ Script::Latin), ('\u{1d9b}', '\u{1dbe}', Script::Latin), ('\u{1dbf}', '\u{1dbf}',
+ Script::Greek), ('\u{1dc0}', '\u{1dff}', Script::Inherited), ('\u{1e00}', '\u{1eff}',
+ Script::Latin), ('\u{1f00}', '\u{1f15}', Script::Greek), ('\u{1f18}', '\u{1f1d}',
+ Script::Greek), ('\u{1f20}', '\u{1f45}', Script::Greek), ('\u{1f48}', '\u{1f4d}',
+ Script::Greek), ('\u{1f50}', '\u{1f57}', Script::Greek), ('\u{1f59}', '\u{1f59}',
+ Script::Greek), ('\u{1f5b}', '\u{1f5b}', Script::Greek), ('\u{1f5d}', '\u{1f5d}',
+ Script::Greek), ('\u{1f5f}', '\u{1f7d}', Script::Greek), ('\u{1f80}', '\u{1fb4}',
+ Script::Greek), ('\u{1fb6}', '\u{1fbc}', Script::Greek), ('\u{1fbd}', '\u{1fbd}',
+ Script::Greek), ('\u{1fbe}', '\u{1fbe}', Script::Greek), ('\u{1fbf}', '\u{1fc1}',
+ Script::Greek), ('\u{1fc2}', '\u{1fc4}', Script::Greek), ('\u{1fc6}', '\u{1fcc}',
+ Script::Greek), ('\u{1fcd}', '\u{1fcf}', Script::Greek), ('\u{1fd0}', '\u{1fd3}',
+ Script::Greek), ('\u{1fd6}', '\u{1fdb}', Script::Greek), ('\u{1fdd}', '\u{1fdf}',
+ Script::Greek), ('\u{1fe0}', '\u{1fec}', Script::Greek), ('\u{1fed}', '\u{1fef}',
+ Script::Greek), ('\u{1ff2}', '\u{1ff4}', Script::Greek), ('\u{1ff6}', '\u{1ffc}',
+ Script::Greek), ('\u{1ffd}', '\u{1ffe}', Script::Greek), ('\u{2000}', '\u{200a}',
+ Script::Common), ('\u{200b}', '\u{200b}', Script::Common), ('\u{200c}', '\u{200d}',
+ Script::Inherited), ('\u{200e}', '\u{200f}', Script::Common), ('\u{2010}', '\u{2015}',
+ Script::Common), ('\u{2016}', '\u{2017}', Script::Common), ('\u{2018}', '\u{2018}',
+ Script::Common), ('\u{2019}', '\u{2019}', Script::Common), ('\u{201a}', '\u{201a}',
+ Script::Common), ('\u{201b}', '\u{201c}', Script::Common), ('\u{201d}', '\u{201d}',
+ Script::Common), ('\u{201e}', '\u{201e}', Script::Common), ('\u{201f}', '\u{201f}',
+ Script::Common), ('\u{2020}', '\u{2027}', Script::Common), ('\u{2028}', '\u{2028}',
+ Script::Common), ('\u{2029}', '\u{2029}', Script::Common), ('\u{202a}', '\u{202e}',
+ Script::Common), ('\u{202f}', '\u{202f}', Script::Common), ('\u{2030}', '\u{2038}',
+ Script::Common), ('\u{2039}', '\u{2039}', Script::Common), ('\u{203a}', '\u{203a}',
+ Script::Common), ('\u{203b}', '\u{203e}', Script::Common), ('\u{203f}', '\u{2040}',
+ Script::Common), ('\u{2041}', '\u{2043}', Script::Common), ('\u{2044}', '\u{2044}',
+ Script::Common), ('\u{2045}', '\u{2045}', Script::Common), ('\u{2046}', '\u{2046}',
+ Script::Common), ('\u{2047}', '\u{2051}', Script::Common), ('\u{2052}', '\u{2052}',
+ Script::Common), ('\u{2053}', '\u{2053}', Script::Common), ('\u{2054}', '\u{2054}',
+ Script::Common), ('\u{2055}', '\u{205e}', Script::Common), ('\u{205f}', '\u{205f}',
+ Script::Common), ('\u{2060}', '\u{2064}', Script::Common), ('\u{2066}', '\u{206f}',
+ Script::Common), ('\u{2070}', '\u{2070}', Script::Common), ('\u{2071}', '\u{2071}',
+ Script::Latin), ('\u{2074}', '\u{2079}', Script::Common), ('\u{207a}', '\u{207c}',
+ Script::Common), ('\u{207d}', '\u{207d}', Script::Common), ('\u{207e}', '\u{207e}',
+ Script::Common), ('\u{207f}', '\u{207f}', Script::Latin), ('\u{2080}', '\u{2089}',
+ Script::Common), ('\u{208a}', '\u{208c}', Script::Common), ('\u{208d}', '\u{208d}',
+ Script::Common), ('\u{208e}', '\u{208e}', Script::Common), ('\u{2090}', '\u{209c}',
+ Script::Latin), ('\u{20a0}', '\u{20c0}', Script::Common), ('\u{20d0}', '\u{20dc}',
+ Script::Inherited), ('\u{20dd}', '\u{20e0}', Script::Inherited), ('\u{20e1}', '\u{20e1}',
+ Script::Inherited), ('\u{20e2}', '\u{20e4}', Script::Inherited), ('\u{20e5}', '\u{20f0}',
+ Script::Inherited), ('\u{2100}', '\u{2101}', Script::Common), ('\u{2102}', '\u{2102}',
+ Script::Common), ('\u{2103}', '\u{2106}', Script::Common), ('\u{2107}', '\u{2107}',
+ Script::Common), ('\u{2108}', '\u{2109}', Script::Common), ('\u{210a}', '\u{2113}',
+ Script::Common), ('\u{2114}', '\u{2114}', Script::Common), ('\u{2115}', '\u{2115}',
+ Script::Common), ('\u{2116}', '\u{2117}', Script::Common), ('\u{2118}', '\u{2118}',
+ Script::Common), ('\u{2119}', '\u{211d}', Script::Common), ('\u{211e}', '\u{2123}',
+ Script::Common), ('\u{2124}', '\u{2124}', Script::Common), ('\u{2125}', '\u{2125}',
+ Script::Common), ('\u{2126}', '\u{2126}', Script::Greek), ('\u{2127}', '\u{2127}',
+ Script::Common), ('\u{2128}', '\u{2128}', Script::Common), ('\u{2129}', '\u{2129}',
+ Script::Common), ('\u{212a}', '\u{212b}', Script::Latin), ('\u{212c}', '\u{212d}',
+ Script::Common), ('\u{212e}', '\u{212e}', Script::Common), ('\u{212f}', '\u{2131}',
+ Script::Common), ('\u{2132}', '\u{2132}', Script::Latin), ('\u{2133}', '\u{2134}',
+ Script::Common), ('\u{2135}', '\u{2138}', Script::Common), ('\u{2139}', '\u{2139}',
+ Script::Common), ('\u{213a}', '\u{213b}', Script::Common), ('\u{213c}', '\u{213f}',
+ Script::Common), ('\u{2140}', '\u{2144}', Script::Common), ('\u{2145}', '\u{2149}',
+ Script::Common), ('\u{214a}', '\u{214a}', Script::Common), ('\u{214b}', '\u{214b}',
+ Script::Common), ('\u{214c}', '\u{214d}', Script::Common), ('\u{214e}', '\u{214e}',
+ Script::Latin), ('\u{214f}', '\u{214f}', Script::Common), ('\u{2150}', '\u{215f}',
+ Script::Common), ('\u{2160}', '\u{2182}', Script::Latin), ('\u{2183}', '\u{2184}',
+ Script::Latin), ('\u{2185}', '\u{2188}', Script::Latin), ('\u{2189}', '\u{2189}',
+ Script::Common), ('\u{218a}', '\u{218b}', Script::Common), ('\u{2190}', '\u{2194}',
+ Script::Common), ('\u{2195}', '\u{2199}', Script::Common), ('\u{219a}', '\u{219b}',
+ Script::Common), ('\u{219c}', '\u{219f}', Script::Common), ('\u{21a0}', '\u{21a0}',
+ Script::Common), ('\u{21a1}', '\u{21a2}', Script::Common), ('\u{21a3}', '\u{21a3}',
+ Script::Common), ('\u{21a4}', '\u{21a5}', Script::Common), ('\u{21a6}', '\u{21a6}',
+ Script::Common), ('\u{21a7}', '\u{21ad}', Script::Common), ('\u{21ae}', '\u{21ae}',
+ Script::Common), ('\u{21af}', '\u{21cd}', Script::Common), ('\u{21ce}', '\u{21cf}',
+ Script::Common), ('\u{21d0}', '\u{21d1}', Script::Common), ('\u{21d2}', '\u{21d2}',
+ Script::Common), ('\u{21d3}', '\u{21d3}', Script::Common), ('\u{21d4}', '\u{21d4}',
+ Script::Common), ('\u{21d5}', '\u{21f3}', Script::Common), ('\u{21f4}', '\u{22ff}',
+ Script::Common), ('\u{2300}', '\u{2307}', Script::Common), ('\u{2308}', '\u{2308}',
+ Script::Common), ('\u{2309}', '\u{2309}', Script::Common), ('\u{230a}', '\u{230a}',
+ Script::Common), ('\u{230b}', '\u{230b}', Script::Common), ('\u{230c}', '\u{231f}',
+ Script::Common), ('\u{2320}', '\u{2321}', Script::Common), ('\u{2322}', '\u{2328}',
+ Script::Common), ('\u{2329}', '\u{2329}', Script::Common), ('\u{232a}', '\u{232a}',
+ Script::Common), ('\u{232b}', '\u{237b}', Script::Common), ('\u{237c}', '\u{237c}',
+ Script::Common), ('\u{237d}', '\u{239a}', Script::Common), ('\u{239b}', '\u{23b3}',
+ Script::Common), ('\u{23b4}', '\u{23db}', Script::Common), ('\u{23dc}', '\u{23e1}',
+ Script::Common), ('\u{23e2}', '\u{2426}', Script::Common), ('\u{2440}', '\u{244a}',
+ Script::Common), ('\u{2460}', '\u{249b}', Script::Common), ('\u{249c}', '\u{24e9}',
+ Script::Common), ('\u{24ea}', '\u{24ff}', Script::Common), ('\u{2500}', '\u{25b6}',
+ Script::Common), ('\u{25b7}', '\u{25b7}', Script::Common), ('\u{25b8}', '\u{25c0}',
+ Script::Common), ('\u{25c1}', '\u{25c1}', Script::Common), ('\u{25c2}', '\u{25f7}',
+ Script::Common), ('\u{25f8}', '\u{25ff}', Script::Common), ('\u{2600}', '\u{266e}',
+ Script::Common), ('\u{266f}', '\u{266f}', Script::Common), ('\u{2670}', '\u{2767}',
+ Script::Common), ('\u{2768}', '\u{2768}', Script::Common), ('\u{2769}', '\u{2769}',
+ Script::Common), ('\u{276a}', '\u{276a}', Script::Common), ('\u{276b}', '\u{276b}',
+ Script::Common), ('\u{276c}', '\u{276c}', Script::Common), ('\u{276d}', '\u{276d}',
+ Script::Common), ('\u{276e}', '\u{276e}', Script::Common), ('\u{276f}', '\u{276f}',
+ Script::Common), ('\u{2770}', '\u{2770}', Script::Common), ('\u{2771}', '\u{2771}',
+ Script::Common), ('\u{2772}', '\u{2772}', Script::Common), ('\u{2773}', '\u{2773}',
+ Script::Common), ('\u{2774}', '\u{2774}', Script::Common), ('\u{2775}', '\u{2775}',
+ Script::Common), ('\u{2776}', '\u{2793}', Script::Common), ('\u{2794}', '\u{27bf}',
+ Script::Common), ('\u{27c0}', '\u{27c4}', Script::Common), ('\u{27c5}', '\u{27c5}',
+ Script::Common), ('\u{27c6}', '\u{27c6}', Script::Common), ('\u{27c7}', '\u{27e5}',
+ Script::Common), ('\u{27e6}', '\u{27e6}', Script::Common), ('\u{27e7}', '\u{27e7}',
+ Script::Common), ('\u{27e8}', '\u{27e8}', Script::Common), ('\u{27e9}', '\u{27e9}',
+ Script::Common), ('\u{27ea}', '\u{27ea}', Script::Common), ('\u{27eb}', '\u{27eb}',
+ Script::Common), ('\u{27ec}', '\u{27ec}', Script::Common), ('\u{27ed}', '\u{27ed}',
+ Script::Common), ('\u{27ee}', '\u{27ee}', Script::Common), ('\u{27ef}', '\u{27ef}',
+ Script::Common), ('\u{27f0}', '\u{27ff}', Script::Common), ('\u{2800}', '\u{28ff}',
+ Script::Braille), ('\u{2900}', '\u{2982}', Script::Common), ('\u{2983}', '\u{2983}',
+ Script::Common), ('\u{2984}', '\u{2984}', Script::Common), ('\u{2985}', '\u{2985}',
+ Script::Common), ('\u{2986}', '\u{2986}', Script::Common), ('\u{2987}', '\u{2987}',
+ Script::Common), ('\u{2988}', '\u{2988}', Script::Common), ('\u{2989}', '\u{2989}',
+ Script::Common), ('\u{298a}', '\u{298a}', Script::Common), ('\u{298b}', '\u{298b}',
+ Script::Common), ('\u{298c}', '\u{298c}', Script::Common), ('\u{298d}', '\u{298d}',
+ Script::Common), ('\u{298e}', '\u{298e}', Script::Common), ('\u{298f}', '\u{298f}',
+ Script::Common), ('\u{2990}', '\u{2990}', Script::Common), ('\u{2991}', '\u{2991}',
+ Script::Common), ('\u{2992}', '\u{2992}', Script::Common), ('\u{2993}', '\u{2993}',
+ Script::Common), ('\u{2994}', '\u{2994}', Script::Common), ('\u{2995}', '\u{2995}',
+ Script::Common), ('\u{2996}', '\u{2996}', Script::Common), ('\u{2997}', '\u{2997}',
+ Script::Common), ('\u{2998}', '\u{2998}', Script::Common), ('\u{2999}', '\u{29d7}',
+ Script::Common), ('\u{29d8}', '\u{29d8}', Script::Common), ('\u{29d9}', '\u{29d9}',
+ Script::Common), ('\u{29da}', '\u{29da}', Script::Common), ('\u{29db}', '\u{29db}',
+ Script::Common), ('\u{29dc}', '\u{29fb}', Script::Common), ('\u{29fc}', '\u{29fc}',
+ Script::Common), ('\u{29fd}', '\u{29fd}', Script::Common), ('\u{29fe}', '\u{2aff}',
+ Script::Common), ('\u{2b00}', '\u{2b2f}', Script::Common), ('\u{2b30}', '\u{2b44}',
+ Script::Common), ('\u{2b45}', '\u{2b46}', Script::Common), ('\u{2b47}', '\u{2b4c}',
+ Script::Common), ('\u{2b4d}', '\u{2b73}', Script::Common), ('\u{2b76}', '\u{2b95}',
+ Script::Common), ('\u{2b97}', '\u{2bff}', Script::Common), ('\u{2c00}', '\u{2c5f}',
Script::Glagolitic), ('\u{2c60}', '\u{2c7b}', Script::Latin), ('\u{2c7c}', '\u{2c7d}',
Script::Latin), ('\u{2c7e}', '\u{2c7f}', Script::Latin), ('\u{2c80}', '\u{2ce4}',
Script::Coptic), ('\u{2ce5}', '\u{2cea}', Script::Coptic), ('\u{2ceb}', '\u{2cee}',
@@ -2426,68 +2512,74 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
Script::Common), ('\u{2e3a}', '\u{2e3b}', Script::Common), ('\u{2e3c}', '\u{2e3f}',
Script::Common), ('\u{2e40}', '\u{2e40}', Script::Common), ('\u{2e41}', '\u{2e41}',
Script::Common), ('\u{2e42}', '\u{2e42}', Script::Common), ('\u{2e43}', '\u{2e4f}',
- Script::Common), ('\u{2e50}', '\u{2e51}', Script::Common), ('\u{2e52}', '\u{2e52}',
- Script::Common), ('\u{2e80}', '\u{2e99}', Script::Han), ('\u{2e9b}', '\u{2ef3}',
- Script::Han), ('\u{2f00}', '\u{2fd5}', Script::Han), ('\u{2ff0}', '\u{2ffb}',
- Script::Common), ('\u{3000}', '\u{3000}', Script::Common), ('\u{3001}', '\u{3003}',
- Script::Common), ('\u{3004}', '\u{3004}', Script::Common), ('\u{3005}', '\u{3005}',
- Script::Han), ('\u{3006}', '\u{3006}', Script::Common), ('\u{3007}', '\u{3007}',
- Script::Han), ('\u{3008}', '\u{3008}', Script::Common), ('\u{3009}', '\u{3009}',
- Script::Common), ('\u{300a}', '\u{300a}', Script::Common), ('\u{300b}', '\u{300b}',
- Script::Common), ('\u{300c}', '\u{300c}', Script::Common), ('\u{300d}', '\u{300d}',
- Script::Common), ('\u{300e}', '\u{300e}', Script::Common), ('\u{300f}', '\u{300f}',
- Script::Common), ('\u{3010}', '\u{3010}', Script::Common), ('\u{3011}', '\u{3011}',
- Script::Common), ('\u{3012}', '\u{3013}', Script::Common), ('\u{3014}', '\u{3014}',
- Script::Common), ('\u{3015}', '\u{3015}', Script::Common), ('\u{3016}', '\u{3016}',
- Script::Common), ('\u{3017}', '\u{3017}', Script::Common), ('\u{3018}', '\u{3018}',
- Script::Common), ('\u{3019}', '\u{3019}', Script::Common), ('\u{301a}', '\u{301a}',
- Script::Common), ('\u{301b}', '\u{301b}', Script::Common), ('\u{301c}', '\u{301c}',
- Script::Common), ('\u{301d}', '\u{301d}', Script::Common), ('\u{301e}', '\u{301f}',
- Script::Common), ('\u{3020}', '\u{3020}', Script::Common), ('\u{3021}', '\u{3029}',
- Script::Han), ('\u{302a}', '\u{302d}', Script::Inherited), ('\u{302e}', '\u{302f}',
- Script::Hangul), ('\u{3030}', '\u{3030}', Script::Common), ('\u{3031}', '\u{3035}',
- Script::Common), ('\u{3036}', '\u{3037}', Script::Common), ('\u{3038}', '\u{303a}',
- Script::Han), ('\u{303b}', '\u{303b}', Script::Han), ('\u{303c}', '\u{303c}',
- Script::Common), ('\u{303d}', '\u{303d}', Script::Common), ('\u{303e}', '\u{303f}',
- Script::Common), ('\u{3041}', '\u{3096}', Script::Hiragana), ('\u{3099}', '\u{309a}',
- Script::Inherited), ('\u{309b}', '\u{309c}', Script::Common), ('\u{309d}', '\u{309e}',
- Script::Hiragana), ('\u{309f}', '\u{309f}', Script::Hiragana), ('\u{30a0}', '\u{30a0}',
- Script::Common), ('\u{30a1}', '\u{30fa}', Script::Katakana), ('\u{30fb}', '\u{30fb}',
- Script::Common), ('\u{30fc}', '\u{30fc}', Script::Common), ('\u{30fd}', '\u{30fe}',
- Script::Katakana), ('\u{30ff}', '\u{30ff}', Script::Katakana), ('\u{3105}', '\u{312f}',
- Script::Bopomofo), ('\u{3131}', '\u{318e}', Script::Hangul), ('\u{3190}', '\u{3191}',
- Script::Common), ('\u{3192}', '\u{3195}', Script::Common), ('\u{3196}', '\u{319f}',
- Script::Common), ('\u{31a0}', '\u{31bf}', Script::Bopomofo), ('\u{31c0}', '\u{31e3}',
- Script::Common), ('\u{31f0}', '\u{31ff}', Script::Katakana), ('\u{3200}', '\u{321e}',
- Script::Hangul), ('\u{3220}', '\u{3229}', Script::Common), ('\u{322a}', '\u{3247}',
- Script::Common), ('\u{3248}', '\u{324f}', Script::Common), ('\u{3250}', '\u{3250}',
- Script::Common), ('\u{3251}', '\u{325f}', Script::Common), ('\u{3260}', '\u{327e}',
- Script::Hangul), ('\u{327f}', '\u{327f}', Script::Common), ('\u{3280}', '\u{3289}',
- Script::Common), ('\u{328a}', '\u{32b0}', Script::Common), ('\u{32b1}', '\u{32bf}',
- Script::Common), ('\u{32c0}', '\u{32cf}', Script::Common), ('\u{32d0}', '\u{32fe}',
- Script::Katakana), ('\u{32ff}', '\u{32ff}', Script::Common), ('\u{3300}', '\u{3357}',
- Script::Katakana), ('\u{3358}', '\u{33ff}', Script::Common), ('\u{3400}', '\u{4dbf}',
- Script::Han), ('\u{4dc0}', '\u{4dff}', Script::Common), ('\u{4e00}', '\u{9ffc}',
- Script::Han), ('\u{a000}', '\u{a014}', Script::Yi), ('\u{a015}', '\u{a015}', Script::Yi),
- ('\u{a016}', '\u{a48c}', Script::Yi), ('\u{a490}', '\u{a4c6}', Script::Yi), ('\u{a4d0}',
- '\u{a4f7}', Script::Lisu), ('\u{a4f8}', '\u{a4fd}', Script::Lisu), ('\u{a4fe}',
- '\u{a4ff}', Script::Lisu), ('\u{a500}', '\u{a60b}', Script::Vai), ('\u{a60c}', '\u{a60c}',
- Script::Vai), ('\u{a60d}', '\u{a60f}', Script::Vai), ('\u{a610}', '\u{a61f}',
- Script::Vai), ('\u{a620}', '\u{a629}', Script::Vai), ('\u{a62a}', '\u{a62b}',
- Script::Vai), ('\u{a640}', '\u{a66d}', Script::Cyrillic), ('\u{a66e}', '\u{a66e}',
- Script::Cyrillic), ('\u{a66f}', '\u{a66f}', Script::Cyrillic), ('\u{a670}', '\u{a672}',
- Script::Cyrillic), ('\u{a673}', '\u{a673}', Script::Cyrillic), ('\u{a674}', '\u{a67d}',
- Script::Cyrillic), ('\u{a67e}', '\u{a67e}', Script::Cyrillic), ('\u{a67f}', '\u{a67f}',
- Script::Cyrillic), ('\u{a680}', '\u{a69b}', Script::Cyrillic), ('\u{a69c}', '\u{a69d}',
- Script::Cyrillic), ('\u{a69e}', '\u{a69f}', Script::Cyrillic), ('\u{a6a0}', '\u{a6e5}',
- Script::Bamum), ('\u{a6e6}', '\u{a6ef}', Script::Bamum), ('\u{a6f0}', '\u{a6f1}',
- Script::Bamum), ('\u{a6f2}', '\u{a6f7}', Script::Bamum), ('\u{a700}', '\u{a716}',
- Script::Common), ('\u{a717}', '\u{a71f}', Script::Common), ('\u{a720}', '\u{a721}',
- Script::Common), ('\u{a722}', '\u{a76f}', Script::Latin), ('\u{a770}', '\u{a770}',
- Script::Latin), ('\u{a771}', '\u{a787}', Script::Latin), ('\u{a788}', '\u{a788}',
- Script::Common), ('\u{a789}', '\u{a78a}', Script::Common), ('\u{a78b}', '\u{a78e}',
- Script::Latin), ('\u{a78f}', '\u{a78f}', Script::Latin), ('\u{a790}', '\u{a7bf}',
- Script::Latin), ('\u{a7c2}', '\u{a7ca}', Script::Latin), ('\u{a7f5}', '\u{a7f6}',
+ Script::Common), ('\u{2e50}', '\u{2e51}', Script::Common), ('\u{2e52}', '\u{2e54}',
+ Script::Common), ('\u{2e55}', '\u{2e55}', Script::Common), ('\u{2e56}', '\u{2e56}',
+ Script::Common), ('\u{2e57}', '\u{2e57}', Script::Common), ('\u{2e58}', '\u{2e58}',
+ Script::Common), ('\u{2e59}', '\u{2e59}', Script::Common), ('\u{2e5a}', '\u{2e5a}',
+ Script::Common), ('\u{2e5b}', '\u{2e5b}', Script::Common), ('\u{2e5c}', '\u{2e5c}',
+ Script::Common), ('\u{2e5d}', '\u{2e5d}', Script::Common), ('\u{2e80}', '\u{2e99}',
+ Script::Han), ('\u{2e9b}', '\u{2ef3}', Script::Han), ('\u{2f00}', '\u{2fd5}',
+ Script::Han), ('\u{2ff0}', '\u{2ffb}', Script::Common), ('\u{3000}', '\u{3000}',
+ Script::Common), ('\u{3001}', '\u{3003}', Script::Common), ('\u{3004}', '\u{3004}',
+ Script::Common), ('\u{3005}', '\u{3005}', Script::Han), ('\u{3006}', '\u{3006}',
+ Script::Common), ('\u{3007}', '\u{3007}', Script::Han), ('\u{3008}', '\u{3008}',
+ Script::Common), ('\u{3009}', '\u{3009}', Script::Common), ('\u{300a}', '\u{300a}',
+ Script::Common), ('\u{300b}', '\u{300b}', Script::Common), ('\u{300c}', '\u{300c}',
+ Script::Common), ('\u{300d}', '\u{300d}', Script::Common), ('\u{300e}', '\u{300e}',
+ Script::Common), ('\u{300f}', '\u{300f}', Script::Common), ('\u{3010}', '\u{3010}',
+ Script::Common), ('\u{3011}', '\u{3011}', Script::Common), ('\u{3012}', '\u{3013}',
+ Script::Common), ('\u{3014}', '\u{3014}', Script::Common), ('\u{3015}', '\u{3015}',
+ Script::Common), ('\u{3016}', '\u{3016}', Script::Common), ('\u{3017}', '\u{3017}',
+ Script::Common), ('\u{3018}', '\u{3018}', Script::Common), ('\u{3019}', '\u{3019}',
+ Script::Common), ('\u{301a}', '\u{301a}', Script::Common), ('\u{301b}', '\u{301b}',
+ Script::Common), ('\u{301c}', '\u{301c}', Script::Common), ('\u{301d}', '\u{301d}',
+ Script::Common), ('\u{301e}', '\u{301f}', Script::Common), ('\u{3020}', '\u{3020}',
+ Script::Common), ('\u{3021}', '\u{3029}', Script::Han), ('\u{302a}', '\u{302d}',
+ Script::Inherited), ('\u{302e}', '\u{302f}', Script::Hangul), ('\u{3030}', '\u{3030}',
+ Script::Common), ('\u{3031}', '\u{3035}', Script::Common), ('\u{3036}', '\u{3037}',
+ Script::Common), ('\u{3038}', '\u{303a}', Script::Han), ('\u{303b}', '\u{303b}',
+ Script::Han), ('\u{303c}', '\u{303c}', Script::Common), ('\u{303d}', '\u{303d}',
+ Script::Common), ('\u{303e}', '\u{303f}', Script::Common), ('\u{3041}', '\u{3096}',
+ Script::Hiragana), ('\u{3099}', '\u{309a}', Script::Inherited), ('\u{309b}', '\u{309c}',
+ Script::Common), ('\u{309d}', '\u{309e}', Script::Hiragana), ('\u{309f}', '\u{309f}',
+ Script::Hiragana), ('\u{30a0}', '\u{30a0}', Script::Common), ('\u{30a1}', '\u{30fa}',
+ Script::Katakana), ('\u{30fb}', '\u{30fb}', Script::Common), ('\u{30fc}', '\u{30fc}',
+ Script::Common), ('\u{30fd}', '\u{30fe}', Script::Katakana), ('\u{30ff}', '\u{30ff}',
+ Script::Katakana), ('\u{3105}', '\u{312f}', Script::Bopomofo), ('\u{3131}', '\u{318e}',
+ Script::Hangul), ('\u{3190}', '\u{3191}', Script::Common), ('\u{3192}', '\u{3195}',
+ Script::Common), ('\u{3196}', '\u{319f}', Script::Common), ('\u{31a0}', '\u{31bf}',
+ Script::Bopomofo), ('\u{31c0}', '\u{31e3}', Script::Common), ('\u{31f0}', '\u{31ff}',
+ Script::Katakana), ('\u{3200}', '\u{321e}', Script::Hangul), ('\u{3220}', '\u{3229}',
+ Script::Common), ('\u{322a}', '\u{3247}', Script::Common), ('\u{3248}', '\u{324f}',
+ Script::Common), ('\u{3250}', '\u{3250}', Script::Common), ('\u{3251}', '\u{325f}',
+ Script::Common), ('\u{3260}', '\u{327e}', Script::Hangul), ('\u{327f}', '\u{327f}',
+ Script::Common), ('\u{3280}', '\u{3289}', Script::Common), ('\u{328a}', '\u{32b0}',
+ Script::Common), ('\u{32b1}', '\u{32bf}', Script::Common), ('\u{32c0}', '\u{32cf}',
+ Script::Common), ('\u{32d0}', '\u{32fe}', Script::Katakana), ('\u{32ff}', '\u{32ff}',
+ Script::Common), ('\u{3300}', '\u{3357}', Script::Katakana), ('\u{3358}', '\u{33ff}',
+ Script::Common), ('\u{3400}', '\u{4dbf}', Script::Han), ('\u{4dc0}', '\u{4dff}',
+ Script::Common), ('\u{4e00}', '\u{9fff}', Script::Han), ('\u{a000}', '\u{a014}',
+ Script::Yi), ('\u{a015}', '\u{a015}', Script::Yi), ('\u{a016}', '\u{a48c}', Script::Yi),
+ ('\u{a490}', '\u{a4c6}', Script::Yi), ('\u{a4d0}', '\u{a4f7}', Script::Lisu), ('\u{a4f8}',
+ '\u{a4fd}', Script::Lisu), ('\u{a4fe}', '\u{a4ff}', Script::Lisu), ('\u{a500}',
+ '\u{a60b}', Script::Vai), ('\u{a60c}', '\u{a60c}', Script::Vai), ('\u{a60d}', '\u{a60f}',
+ Script::Vai), ('\u{a610}', '\u{a61f}', Script::Vai), ('\u{a620}', '\u{a629}',
+ Script::Vai), ('\u{a62a}', '\u{a62b}', Script::Vai), ('\u{a640}', '\u{a66d}',
+ Script::Cyrillic), ('\u{a66e}', '\u{a66e}', Script::Cyrillic), ('\u{a66f}', '\u{a66f}',
+ Script::Cyrillic), ('\u{a670}', '\u{a672}', Script::Cyrillic), ('\u{a673}', '\u{a673}',
+ Script::Cyrillic), ('\u{a674}', '\u{a67d}', Script::Cyrillic), ('\u{a67e}', '\u{a67e}',
+ Script::Cyrillic), ('\u{a67f}', '\u{a67f}', Script::Cyrillic), ('\u{a680}', '\u{a69b}',
+ Script::Cyrillic), ('\u{a69c}', '\u{a69d}', Script::Cyrillic), ('\u{a69e}', '\u{a69f}',
+ Script::Cyrillic), ('\u{a6a0}', '\u{a6e5}', Script::Bamum), ('\u{a6e6}', '\u{a6ef}',
+ Script::Bamum), ('\u{a6f0}', '\u{a6f1}', Script::Bamum), ('\u{a6f2}', '\u{a6f7}',
+ Script::Bamum), ('\u{a700}', '\u{a716}', Script::Common), ('\u{a717}', '\u{a71f}',
+ Script::Common), ('\u{a720}', '\u{a721}', Script::Common), ('\u{a722}', '\u{a76f}',
+ Script::Latin), ('\u{a770}', '\u{a770}', Script::Latin), ('\u{a771}', '\u{a787}',
+ Script::Latin), ('\u{a788}', '\u{a788}', Script::Common), ('\u{a789}', '\u{a78a}',
+ Script::Common), ('\u{a78b}', '\u{a78e}', Script::Latin), ('\u{a78f}', '\u{a78f}',
+ Script::Latin), ('\u{a790}', '\u{a7ca}', Script::Latin), ('\u{a7d0}', '\u{a7d1}',
+ Script::Latin), ('\u{a7d3}', '\u{a7d3}', Script::Latin), ('\u{a7d5}', '\u{a7d9}',
+ Script::Latin), ('\u{a7f2}', '\u{a7f4}', Script::Latin), ('\u{a7f5}', '\u{a7f6}',
Script::Latin), ('\u{a7f7}', '\u{a7f7}', Script::Latin), ('\u{a7f8}', '\u{a7f9}',
Script::Latin), ('\u{a7fa}', '\u{a7fa}', Script::Latin), ('\u{a7fb}', '\u{a7ff}',
Script::Latin), ('\u{a800}', '\u{a801}', Script::Syloti_Nagri), ('\u{a802}', '\u{a802}',
@@ -2568,11 +2660,12 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
'\u{fb3c}', Script::Hebrew), ('\u{fb3e}', '\u{fb3e}', Script::Hebrew), ('\u{fb40}',
'\u{fb41}', Script::Hebrew), ('\u{fb43}', '\u{fb44}', Script::Hebrew), ('\u{fb46}',
'\u{fb4f}', Script::Hebrew), ('\u{fb50}', '\u{fbb1}', Script::Arabic), ('\u{fbb2}',
- '\u{fbc1}', Script::Arabic), ('\u{fbd3}', '\u{fd3d}', Script::Arabic), ('\u{fd3e}',
- '\u{fd3e}', Script::Common), ('\u{fd3f}', '\u{fd3f}', Script::Common), ('\u{fd50}',
- '\u{fd8f}', Script::Arabic), ('\u{fd92}', '\u{fdc7}', Script::Arabic), ('\u{fdf0}',
+ '\u{fbc2}', Script::Arabic), ('\u{fbd3}', '\u{fd3d}', Script::Arabic), ('\u{fd3e}',
+ '\u{fd3e}', Script::Common), ('\u{fd3f}', '\u{fd3f}', Script::Common), ('\u{fd40}',
+ '\u{fd4f}', Script::Arabic), ('\u{fd50}', '\u{fd8f}', Script::Arabic), ('\u{fd92}',
+ '\u{fdc7}', Script::Arabic), ('\u{fdcf}', '\u{fdcf}', Script::Arabic), ('\u{fdf0}',
'\u{fdfb}', Script::Arabic), ('\u{fdfc}', '\u{fdfc}', Script::Arabic), ('\u{fdfd}',
- '\u{fdfd}', Script::Arabic), ('\u{fe00}', '\u{fe0f}', Script::Inherited), ('\u{fe10}',
+ '\u{fdff}', Script::Arabic), ('\u{fe00}', '\u{fe0f}', Script::Inherited), ('\u{fe10}',
'\u{fe16}', Script::Common), ('\u{fe17}', '\u{fe17}', Script::Common), ('\u{fe18}',
'\u{fe18}', Script::Common), ('\u{fe19}', '\u{fe19}', Script::Common), ('\u{fe20}',
'\u{fe2d}', Script::Inherited), ('\u{fe2e}', '\u{fe2f}', Script::Cyrillic), ('\u{fe30}',
@@ -2648,41 +2741,48 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
Script::Osmanya), ('\u{104a0}', '\u{104a9}', Script::Osmanya), ('\u{104b0}', '\u{104d3}',
Script::Osage), ('\u{104d8}', '\u{104fb}', Script::Osage), ('\u{10500}', '\u{10527}',
Script::Elbasan), ('\u{10530}', '\u{10563}', Script::Caucasian_Albanian), ('\u{1056f}',
- '\u{1056f}', Script::Caucasian_Albanian), ('\u{10600}', '\u{10736}', Script::Linear_A),
- ('\u{10740}', '\u{10755}', Script::Linear_A), ('\u{10760}', '\u{10767}',
- Script::Linear_A), ('\u{10800}', '\u{10805}', Script::Cypriot), ('\u{10808}', '\u{10808}',
- Script::Cypriot), ('\u{1080a}', '\u{10835}', Script::Cypriot), ('\u{10837}', '\u{10838}',
- Script::Cypriot), ('\u{1083c}', '\u{1083c}', Script::Cypriot), ('\u{1083f}', '\u{1083f}',
- Script::Cypriot), ('\u{10840}', '\u{10855}', Script::Imperial_Aramaic), ('\u{10857}',
- '\u{10857}', Script::Imperial_Aramaic), ('\u{10858}', '\u{1085f}',
- Script::Imperial_Aramaic), ('\u{10860}', '\u{10876}', Script::Palmyrene), ('\u{10877}',
- '\u{10878}', Script::Palmyrene), ('\u{10879}', '\u{1087f}', Script::Palmyrene),
- ('\u{10880}', '\u{1089e}', Script::Nabataean), ('\u{108a7}', '\u{108af}',
- Script::Nabataean), ('\u{108e0}', '\u{108f2}', Script::Hatran), ('\u{108f4}', '\u{108f5}',
- Script::Hatran), ('\u{108fb}', '\u{108ff}', Script::Hatran), ('\u{10900}', '\u{10915}',
- Script::Phoenician), ('\u{10916}', '\u{1091b}', Script::Phoenician), ('\u{1091f}',
- '\u{1091f}', Script::Phoenician), ('\u{10920}', '\u{10939}', Script::Lydian),
- ('\u{1093f}', '\u{1093f}', Script::Lydian), ('\u{10980}', '\u{1099f}',
- Script::Meroitic_Hieroglyphs), ('\u{109a0}', '\u{109b7}', Script::Meroitic_Cursive),
- ('\u{109bc}', '\u{109bd}', Script::Meroitic_Cursive), ('\u{109be}', '\u{109bf}',
- Script::Meroitic_Cursive), ('\u{109c0}', '\u{109cf}', Script::Meroitic_Cursive),
- ('\u{109d2}', '\u{109ff}', Script::Meroitic_Cursive), ('\u{10a00}', '\u{10a00}',
- Script::Kharoshthi), ('\u{10a01}', '\u{10a03}', Script::Kharoshthi), ('\u{10a05}',
- '\u{10a06}', Script::Kharoshthi), ('\u{10a0c}', '\u{10a0f}', Script::Kharoshthi),
- ('\u{10a10}', '\u{10a13}', Script::Kharoshthi), ('\u{10a15}', '\u{10a17}',
- Script::Kharoshthi), ('\u{10a19}', '\u{10a35}', Script::Kharoshthi), ('\u{10a38}',
- '\u{10a3a}', Script::Kharoshthi), ('\u{10a3f}', '\u{10a3f}', Script::Kharoshthi),
- ('\u{10a40}', '\u{10a48}', Script::Kharoshthi), ('\u{10a50}', '\u{10a58}',
- Script::Kharoshthi), ('\u{10a60}', '\u{10a7c}', Script::Old_South_Arabian), ('\u{10a7d}',
- '\u{10a7e}', Script::Old_South_Arabian), ('\u{10a7f}', '\u{10a7f}',
- Script::Old_South_Arabian), ('\u{10a80}', '\u{10a9c}', Script::Old_North_Arabian),
- ('\u{10a9d}', '\u{10a9f}', Script::Old_North_Arabian), ('\u{10ac0}', '\u{10ac7}',
- Script::Manichaean), ('\u{10ac8}', '\u{10ac8}', Script::Manichaean), ('\u{10ac9}',
- '\u{10ae4}', Script::Manichaean), ('\u{10ae5}', '\u{10ae6}', Script::Manichaean),
- ('\u{10aeb}', '\u{10aef}', Script::Manichaean), ('\u{10af0}', '\u{10af6}',
- Script::Manichaean), ('\u{10b00}', '\u{10b35}', Script::Avestan), ('\u{10b39}',
- '\u{10b3f}', Script::Avestan), ('\u{10b40}', '\u{10b55}', Script::Inscriptional_Parthian),
- ('\u{10b58}', '\u{10b5f}', Script::Inscriptional_Parthian), ('\u{10b60}', '\u{10b72}',
+ '\u{1056f}', Script::Caucasian_Albanian), ('\u{10570}', '\u{1057a}', Script::Vithkuqi),
+ ('\u{1057c}', '\u{1058a}', Script::Vithkuqi), ('\u{1058c}', '\u{10592}',
+ Script::Vithkuqi), ('\u{10594}', '\u{10595}', Script::Vithkuqi), ('\u{10597}',
+ '\u{105a1}', Script::Vithkuqi), ('\u{105a3}', '\u{105b1}', Script::Vithkuqi),
+ ('\u{105b3}', '\u{105b9}', Script::Vithkuqi), ('\u{105bb}', '\u{105bc}',
+ Script::Vithkuqi), ('\u{10600}', '\u{10736}', Script::Linear_A), ('\u{10740}',
+ '\u{10755}', Script::Linear_A), ('\u{10760}', '\u{10767}', Script::Linear_A),
+ ('\u{10780}', '\u{10785}', Script::Latin), ('\u{10787}', '\u{107b0}', Script::Latin),
+ ('\u{107b2}', '\u{107ba}', Script::Latin), ('\u{10800}', '\u{10805}', Script::Cypriot),
+ ('\u{10808}', '\u{10808}', Script::Cypriot), ('\u{1080a}', '\u{10835}', Script::Cypriot),
+ ('\u{10837}', '\u{10838}', Script::Cypriot), ('\u{1083c}', '\u{1083c}', Script::Cypriot),
+ ('\u{1083f}', '\u{1083f}', Script::Cypriot), ('\u{10840}', '\u{10855}',
+ Script::Imperial_Aramaic), ('\u{10857}', '\u{10857}', Script::Imperial_Aramaic),
+ ('\u{10858}', '\u{1085f}', Script::Imperial_Aramaic), ('\u{10860}', '\u{10876}',
+ Script::Palmyrene), ('\u{10877}', '\u{10878}', Script::Palmyrene), ('\u{10879}',
+ '\u{1087f}', Script::Palmyrene), ('\u{10880}', '\u{1089e}', Script::Nabataean),
+ ('\u{108a7}', '\u{108af}', Script::Nabataean), ('\u{108e0}', '\u{108f2}', Script::Hatran),
+ ('\u{108f4}', '\u{108f5}', Script::Hatran), ('\u{108fb}', '\u{108ff}', Script::Hatran),
+ ('\u{10900}', '\u{10915}', Script::Phoenician), ('\u{10916}', '\u{1091b}',
+ Script::Phoenician), ('\u{1091f}', '\u{1091f}', Script::Phoenician), ('\u{10920}',
+ '\u{10939}', Script::Lydian), ('\u{1093f}', '\u{1093f}', Script::Lydian), ('\u{10980}',
+ '\u{1099f}', Script::Meroitic_Hieroglyphs), ('\u{109a0}', '\u{109b7}',
+ Script::Meroitic_Cursive), ('\u{109bc}', '\u{109bd}', Script::Meroitic_Cursive),
+ ('\u{109be}', '\u{109bf}', Script::Meroitic_Cursive), ('\u{109c0}', '\u{109cf}',
+ Script::Meroitic_Cursive), ('\u{109d2}', '\u{109ff}', Script::Meroitic_Cursive),
+ ('\u{10a00}', '\u{10a00}', Script::Kharoshthi), ('\u{10a01}', '\u{10a03}',
+ Script::Kharoshthi), ('\u{10a05}', '\u{10a06}', Script::Kharoshthi), ('\u{10a0c}',
+ '\u{10a0f}', Script::Kharoshthi), ('\u{10a10}', '\u{10a13}', Script::Kharoshthi),
+ ('\u{10a15}', '\u{10a17}', Script::Kharoshthi), ('\u{10a19}', '\u{10a35}',
+ Script::Kharoshthi), ('\u{10a38}', '\u{10a3a}', Script::Kharoshthi), ('\u{10a3f}',
+ '\u{10a3f}', Script::Kharoshthi), ('\u{10a40}', '\u{10a48}', Script::Kharoshthi),
+ ('\u{10a50}', '\u{10a58}', Script::Kharoshthi), ('\u{10a60}', '\u{10a7c}',
+ Script::Old_South_Arabian), ('\u{10a7d}', '\u{10a7e}', Script::Old_South_Arabian),
+ ('\u{10a7f}', '\u{10a7f}', Script::Old_South_Arabian), ('\u{10a80}', '\u{10a9c}',
+ Script::Old_North_Arabian), ('\u{10a9d}', '\u{10a9f}', Script::Old_North_Arabian),
+ ('\u{10ac0}', '\u{10ac7}', Script::Manichaean), ('\u{10ac8}', '\u{10ac8}',
+ Script::Manichaean), ('\u{10ac9}', '\u{10ae4}', Script::Manichaean), ('\u{10ae5}',
+ '\u{10ae6}', Script::Manichaean), ('\u{10aeb}', '\u{10aef}', Script::Manichaean),
+ ('\u{10af0}', '\u{10af6}', Script::Manichaean), ('\u{10b00}', '\u{10b35}',
+ Script::Avestan), ('\u{10b39}', '\u{10b3f}', Script::Avestan), ('\u{10b40}', '\u{10b55}',
+ Script::Inscriptional_Parthian), ('\u{10b58}', '\u{10b5f}',
+ Script::Inscriptional_Parthian), ('\u{10b60}', '\u{10b72}',
Script::Inscriptional_Pahlavi), ('\u{10b78}', '\u{10b7f}', Script::Inscriptional_Pahlavi),
('\u{10b80}', '\u{10b91}', Script::Psalter_Pahlavi), ('\u{10b99}', '\u{10b9c}',
Script::Psalter_Pahlavi), ('\u{10ba9}', '\u{10baf}', Script::Psalter_Pahlavi),
@@ -2692,166 +2792,186 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
('\u{10d24}', '\u{10d27}', Script::Hanifi_Rohingya), ('\u{10d30}', '\u{10d39}',
Script::Hanifi_Rohingya), ('\u{10e60}', '\u{10e7e}', Script::Arabic), ('\u{10e80}',
'\u{10ea9}', Script::Yezidi), ('\u{10eab}', '\u{10eac}', Script::Yezidi), ('\u{10ead}',
- '\u{10ead}', Script::Yezidi), ('\u{10eb0}', '\u{10eb1}', Script::Yezidi), ('\u{10f00}',
- '\u{10f1c}', Script::Old_Sogdian), ('\u{10f1d}', '\u{10f26}', Script::Old_Sogdian),
- ('\u{10f27}', '\u{10f27}', Script::Old_Sogdian), ('\u{10f30}', '\u{10f45}',
- Script::Sogdian), ('\u{10f46}', '\u{10f50}', Script::Sogdian), ('\u{10f51}', '\u{10f54}',
- Script::Sogdian), ('\u{10f55}', '\u{10f59}', Script::Sogdian), ('\u{10fb0}', '\u{10fc4}',
- Script::Chorasmian), ('\u{10fc5}', '\u{10fcb}', Script::Chorasmian), ('\u{10fe0}',
- '\u{10ff6}', Script::Elymaic), ('\u{11000}', '\u{11000}', Script::Brahmi), ('\u{11001}',
- '\u{11001}', Script::Brahmi), ('\u{11002}', '\u{11002}', Script::Brahmi), ('\u{11003}',
- '\u{11037}', Script::Brahmi), ('\u{11038}', '\u{11046}', Script::Brahmi), ('\u{11047}',
- '\u{1104d}', Script::Brahmi), ('\u{11052}', '\u{11065}', Script::Brahmi), ('\u{11066}',
- '\u{1106f}', Script::Brahmi), ('\u{1107f}', '\u{1107f}', Script::Brahmi), ('\u{11080}',
- '\u{11081}', Script::Kaithi), ('\u{11082}', '\u{11082}', Script::Kaithi), ('\u{11083}',
- '\u{110af}', Script::Kaithi), ('\u{110b0}', '\u{110b2}', Script::Kaithi), ('\u{110b3}',
- '\u{110b6}', Script::Kaithi), ('\u{110b7}', '\u{110b8}', Script::Kaithi), ('\u{110b9}',
- '\u{110ba}', Script::Kaithi), ('\u{110bb}', '\u{110bc}', Script::Kaithi), ('\u{110bd}',
- '\u{110bd}', Script::Kaithi), ('\u{110be}', '\u{110c1}', Script::Kaithi), ('\u{110cd}',
- '\u{110cd}', Script::Kaithi), ('\u{110d0}', '\u{110e8}', Script::Sora_Sompeng),
- ('\u{110f0}', '\u{110f9}', Script::Sora_Sompeng), ('\u{11100}', '\u{11102}',
- Script::Chakma), ('\u{11103}', '\u{11126}', Script::Chakma), ('\u{11127}', '\u{1112b}',
- Script::Chakma), ('\u{1112c}', '\u{1112c}', Script::Chakma), ('\u{1112d}', '\u{11134}',
- Script::Chakma), ('\u{11136}', '\u{1113f}', Script::Chakma), ('\u{11140}', '\u{11143}',
- Script::Chakma), ('\u{11144}', '\u{11144}', Script::Chakma), ('\u{11145}', '\u{11146}',
- Script::Chakma), ('\u{11147}', '\u{11147}', Script::Chakma), ('\u{11150}', '\u{11172}',
- Script::Mahajani), ('\u{11173}', '\u{11173}', Script::Mahajani), ('\u{11174}',
- '\u{11175}', Script::Mahajani), ('\u{11176}', '\u{11176}', Script::Mahajani),
- ('\u{11180}', '\u{11181}', Script::Sharada), ('\u{11182}', '\u{11182}', Script::Sharada),
- ('\u{11183}', '\u{111b2}', Script::Sharada), ('\u{111b3}', '\u{111b5}', Script::Sharada),
- ('\u{111b6}', '\u{111be}', Script::Sharada), ('\u{111bf}', '\u{111c0}', Script::Sharada),
- ('\u{111c1}', '\u{111c4}', Script::Sharada), ('\u{111c5}', '\u{111c8}', Script::Sharada),
- ('\u{111c9}', '\u{111cc}', Script::Sharada), ('\u{111cd}', '\u{111cd}', Script::Sharada),
- ('\u{111ce}', '\u{111ce}', Script::Sharada), ('\u{111cf}', '\u{111cf}', Script::Sharada),
- ('\u{111d0}', '\u{111d9}', Script::Sharada), ('\u{111da}', '\u{111da}', Script::Sharada),
- ('\u{111db}', '\u{111db}', Script::Sharada), ('\u{111dc}', '\u{111dc}', Script::Sharada),
- ('\u{111dd}', '\u{111df}', Script::Sharada), ('\u{111e1}', '\u{111f4}', Script::Sinhala),
- ('\u{11200}', '\u{11211}', Script::Khojki), ('\u{11213}', '\u{1122b}', Script::Khojki),
- ('\u{1122c}', '\u{1122e}', Script::Khojki), ('\u{1122f}', '\u{11231}', Script::Khojki),
- ('\u{11232}', '\u{11233}', Script::Khojki), ('\u{11234}', '\u{11234}', Script::Khojki),
- ('\u{11235}', '\u{11235}', Script::Khojki), ('\u{11236}', '\u{11237}', Script::Khojki),
- ('\u{11238}', '\u{1123d}', Script::Khojki), ('\u{1123e}', '\u{1123e}', Script::Khojki),
- ('\u{11280}', '\u{11286}', Script::Multani), ('\u{11288}', '\u{11288}', Script::Multani),
- ('\u{1128a}', '\u{1128d}', Script::Multani), ('\u{1128f}', '\u{1129d}', Script::Multani),
- ('\u{1129f}', '\u{112a8}', Script::Multani), ('\u{112a9}', '\u{112a9}', Script::Multani),
- ('\u{112b0}', '\u{112de}', Script::Khudawadi), ('\u{112df}', '\u{112df}',
- Script::Khudawadi), ('\u{112e0}', '\u{112e2}', Script::Khudawadi), ('\u{112e3}',
- '\u{112ea}', Script::Khudawadi), ('\u{112f0}', '\u{112f9}', Script::Khudawadi),
- ('\u{11300}', '\u{11301}', Script::Grantha), ('\u{11302}', '\u{11303}', Script::Grantha),
- ('\u{11305}', '\u{1130c}', Script::Grantha), ('\u{1130f}', '\u{11310}', Script::Grantha),
- ('\u{11313}', '\u{11328}', Script::Grantha), ('\u{1132a}', '\u{11330}', Script::Grantha),
- ('\u{11332}', '\u{11333}', Script::Grantha), ('\u{11335}', '\u{11339}', Script::Grantha),
- ('\u{1133b}', '\u{1133b}', Script::Inherited), ('\u{1133c}', '\u{1133c}',
- Script::Grantha), ('\u{1133d}', '\u{1133d}', Script::Grantha), ('\u{1133e}', '\u{1133f}',
- Script::Grantha), ('\u{11340}', '\u{11340}', Script::Grantha), ('\u{11341}', '\u{11344}',
- Script::Grantha), ('\u{11347}', '\u{11348}', Script::Grantha), ('\u{1134b}', '\u{1134d}',
- Script::Grantha), ('\u{11350}', '\u{11350}', Script::Grantha), ('\u{11357}', '\u{11357}',
- Script::Grantha), ('\u{1135d}', '\u{11361}', Script::Grantha), ('\u{11362}', '\u{11363}',
- Script::Grantha), ('\u{11366}', '\u{1136c}', Script::Grantha), ('\u{11370}', '\u{11374}',
- Script::Grantha), ('\u{11400}', '\u{11434}', Script::Newa), ('\u{11435}', '\u{11437}',
- Script::Newa), ('\u{11438}', '\u{1143f}', Script::Newa), ('\u{11440}', '\u{11441}',
- Script::Newa), ('\u{11442}', '\u{11444}', Script::Newa), ('\u{11445}', '\u{11445}',
- Script::Newa), ('\u{11446}', '\u{11446}', Script::Newa), ('\u{11447}', '\u{1144a}',
- Script::Newa), ('\u{1144b}', '\u{1144f}', Script::Newa), ('\u{11450}', '\u{11459}',
- Script::Newa), ('\u{1145a}', '\u{1145b}', Script::Newa), ('\u{1145d}', '\u{1145d}',
- Script::Newa), ('\u{1145e}', '\u{1145e}', Script::Newa), ('\u{1145f}', '\u{11461}',
- Script::Newa), ('\u{11480}', '\u{114af}', Script::Tirhuta), ('\u{114b0}', '\u{114b2}',
- Script::Tirhuta), ('\u{114b3}', '\u{114b8}', Script::Tirhuta), ('\u{114b9}', '\u{114b9}',
- Script::Tirhuta), ('\u{114ba}', '\u{114ba}', Script::Tirhuta), ('\u{114bb}', '\u{114be}',
- Script::Tirhuta), ('\u{114bf}', '\u{114c0}', Script::Tirhuta), ('\u{114c1}', '\u{114c1}',
- Script::Tirhuta), ('\u{114c2}', '\u{114c3}', Script::Tirhuta), ('\u{114c4}', '\u{114c5}',
- Script::Tirhuta), ('\u{114c6}', '\u{114c6}', Script::Tirhuta), ('\u{114c7}', '\u{114c7}',
- Script::Tirhuta), ('\u{114d0}', '\u{114d9}', Script::Tirhuta), ('\u{11580}', '\u{115ae}',
- Script::Siddham), ('\u{115af}', '\u{115b1}', Script::Siddham), ('\u{115b2}', '\u{115b5}',
- Script::Siddham), ('\u{115b8}', '\u{115bb}', Script::Siddham), ('\u{115bc}', '\u{115bd}',
- Script::Siddham), ('\u{115be}', '\u{115be}', Script::Siddham), ('\u{115bf}', '\u{115c0}',
- Script::Siddham), ('\u{115c1}', '\u{115d7}', Script::Siddham), ('\u{115d8}', '\u{115db}',
- Script::Siddham), ('\u{115dc}', '\u{115dd}', Script::Siddham), ('\u{11600}', '\u{1162f}',
- Script::Modi), ('\u{11630}', '\u{11632}', Script::Modi), ('\u{11633}', '\u{1163a}',
- Script::Modi), ('\u{1163b}', '\u{1163c}', Script::Modi), ('\u{1163d}', '\u{1163d}',
- Script::Modi), ('\u{1163e}', '\u{1163e}', Script::Modi), ('\u{1163f}', '\u{11640}',
- Script::Modi), ('\u{11641}', '\u{11643}', Script::Modi), ('\u{11644}', '\u{11644}',
- Script::Modi), ('\u{11650}', '\u{11659}', Script::Modi), ('\u{11660}', '\u{1166c}',
- Script::Mongolian), ('\u{11680}', '\u{116aa}', Script::Takri), ('\u{116ab}', '\u{116ab}',
- Script::Takri), ('\u{116ac}', '\u{116ac}', Script::Takri), ('\u{116ad}', '\u{116ad}',
- Script::Takri), ('\u{116ae}', '\u{116af}', Script::Takri), ('\u{116b0}', '\u{116b5}',
- Script::Takri), ('\u{116b6}', '\u{116b6}', Script::Takri), ('\u{116b7}', '\u{116b7}',
- Script::Takri), ('\u{116b8}', '\u{116b8}', Script::Takri), ('\u{116c0}', '\u{116c9}',
- Script::Takri), ('\u{11700}', '\u{1171a}', Script::Ahom), ('\u{1171d}', '\u{1171f}',
- Script::Ahom), ('\u{11720}', '\u{11721}', Script::Ahom), ('\u{11722}', '\u{11725}',
- Script::Ahom), ('\u{11726}', '\u{11726}', Script::Ahom), ('\u{11727}', '\u{1172b}',
- Script::Ahom), ('\u{11730}', '\u{11739}', Script::Ahom), ('\u{1173a}', '\u{1173b}',
- Script::Ahom), ('\u{1173c}', '\u{1173e}', Script::Ahom), ('\u{1173f}', '\u{1173f}',
- Script::Ahom), ('\u{11800}', '\u{1182b}', Script::Dogra), ('\u{1182c}', '\u{1182e}',
- Script::Dogra), ('\u{1182f}', '\u{11837}', Script::Dogra), ('\u{11838}', '\u{11838}',
- Script::Dogra), ('\u{11839}', '\u{1183a}', Script::Dogra), ('\u{1183b}', '\u{1183b}',
- Script::Dogra), ('\u{118a0}', '\u{118df}', Script::Warang_Citi), ('\u{118e0}',
- '\u{118e9}', Script::Warang_Citi), ('\u{118ea}', '\u{118f2}', Script::Warang_Citi),
- ('\u{118ff}', '\u{118ff}', Script::Warang_Citi), ('\u{11900}', '\u{11906}',
- Script::Dives_Akuru), ('\u{11909}', '\u{11909}', Script::Dives_Akuru), ('\u{1190c}',
- '\u{11913}', Script::Dives_Akuru), ('\u{11915}', '\u{11916}', Script::Dives_Akuru),
- ('\u{11918}', '\u{1192f}', Script::Dives_Akuru), ('\u{11930}', '\u{11935}',
- Script::Dives_Akuru), ('\u{11937}', '\u{11938}', Script::Dives_Akuru), ('\u{1193b}',
- '\u{1193c}', Script::Dives_Akuru), ('\u{1193d}', '\u{1193d}', Script::Dives_Akuru),
- ('\u{1193e}', '\u{1193e}', Script::Dives_Akuru), ('\u{1193f}', '\u{1193f}',
- Script::Dives_Akuru), ('\u{11940}', '\u{11940}', Script::Dives_Akuru), ('\u{11941}',
- '\u{11941}', Script::Dives_Akuru), ('\u{11942}', '\u{11942}', Script::Dives_Akuru),
- ('\u{11943}', '\u{11943}', Script::Dives_Akuru), ('\u{11944}', '\u{11946}',
- Script::Dives_Akuru), ('\u{11950}', '\u{11959}', Script::Dives_Akuru), ('\u{119a0}',
- '\u{119a7}', Script::Nandinagari), ('\u{119aa}', '\u{119d0}', Script::Nandinagari),
- ('\u{119d1}', '\u{119d3}', Script::Nandinagari), ('\u{119d4}', '\u{119d7}',
- Script::Nandinagari), ('\u{119da}', '\u{119db}', Script::Nandinagari), ('\u{119dc}',
- '\u{119df}', Script::Nandinagari), ('\u{119e0}', '\u{119e0}', Script::Nandinagari),
- ('\u{119e1}', '\u{119e1}', Script::Nandinagari), ('\u{119e2}', '\u{119e2}',
- Script::Nandinagari), ('\u{119e3}', '\u{119e3}', Script::Nandinagari), ('\u{119e4}',
- '\u{119e4}', Script::Nandinagari), ('\u{11a00}', '\u{11a00}', Script::Zanabazar_Square),
- ('\u{11a01}', '\u{11a0a}', Script::Zanabazar_Square), ('\u{11a0b}', '\u{11a32}',
- Script::Zanabazar_Square), ('\u{11a33}', '\u{11a38}', Script::Zanabazar_Square),
- ('\u{11a39}', '\u{11a39}', Script::Zanabazar_Square), ('\u{11a3a}', '\u{11a3a}',
- Script::Zanabazar_Square), ('\u{11a3b}', '\u{11a3e}', Script::Zanabazar_Square),
- ('\u{11a3f}', '\u{11a46}', Script::Zanabazar_Square), ('\u{11a47}', '\u{11a47}',
- Script::Zanabazar_Square), ('\u{11a50}', '\u{11a50}', Script::Soyombo), ('\u{11a51}',
- '\u{11a56}', Script::Soyombo), ('\u{11a57}', '\u{11a58}', Script::Soyombo), ('\u{11a59}',
- '\u{11a5b}', Script::Soyombo), ('\u{11a5c}', '\u{11a89}', Script::Soyombo), ('\u{11a8a}',
- '\u{11a96}', Script::Soyombo), ('\u{11a97}', '\u{11a97}', Script::Soyombo), ('\u{11a98}',
- '\u{11a99}', Script::Soyombo), ('\u{11a9a}', '\u{11a9c}', Script::Soyombo), ('\u{11a9d}',
- '\u{11a9d}', Script::Soyombo), ('\u{11a9e}', '\u{11aa2}', Script::Soyombo), ('\u{11ac0}',
- '\u{11af8}', Script::Pau_Cin_Hau), ('\u{11c00}', '\u{11c08}', Script::Bhaiksuki),
- ('\u{11c0a}', '\u{11c2e}', Script::Bhaiksuki), ('\u{11c2f}', '\u{11c2f}',
- Script::Bhaiksuki), ('\u{11c30}', '\u{11c36}', Script::Bhaiksuki), ('\u{11c38}',
- '\u{11c3d}', Script::Bhaiksuki), ('\u{11c3e}', '\u{11c3e}', Script::Bhaiksuki),
- ('\u{11c3f}', '\u{11c3f}', Script::Bhaiksuki), ('\u{11c40}', '\u{11c40}',
- Script::Bhaiksuki), ('\u{11c41}', '\u{11c45}', Script::Bhaiksuki), ('\u{11c50}',
- '\u{11c59}', Script::Bhaiksuki), ('\u{11c5a}', '\u{11c6c}', Script::Bhaiksuki),
- ('\u{11c70}', '\u{11c71}', Script::Marchen), ('\u{11c72}', '\u{11c8f}', Script::Marchen),
- ('\u{11c92}', '\u{11ca7}', Script::Marchen), ('\u{11ca9}', '\u{11ca9}', Script::Marchen),
- ('\u{11caa}', '\u{11cb0}', Script::Marchen), ('\u{11cb1}', '\u{11cb1}', Script::Marchen),
- ('\u{11cb2}', '\u{11cb3}', Script::Marchen), ('\u{11cb4}', '\u{11cb4}', Script::Marchen),
- ('\u{11cb5}', '\u{11cb6}', Script::Marchen), ('\u{11d00}', '\u{11d06}',
- Script::Masaram_Gondi), ('\u{11d08}', '\u{11d09}', Script::Masaram_Gondi), ('\u{11d0b}',
- '\u{11d30}', Script::Masaram_Gondi), ('\u{11d31}', '\u{11d36}', Script::Masaram_Gondi),
- ('\u{11d3a}', '\u{11d3a}', Script::Masaram_Gondi), ('\u{11d3c}', '\u{11d3d}',
- Script::Masaram_Gondi), ('\u{11d3f}', '\u{11d45}', Script::Masaram_Gondi), ('\u{11d46}',
- '\u{11d46}', Script::Masaram_Gondi), ('\u{11d47}', '\u{11d47}', Script::Masaram_Gondi),
- ('\u{11d50}', '\u{11d59}', Script::Masaram_Gondi), ('\u{11d60}', '\u{11d65}',
- Script::Gunjala_Gondi), ('\u{11d67}', '\u{11d68}', Script::Gunjala_Gondi), ('\u{11d6a}',
- '\u{11d89}', Script::Gunjala_Gondi), ('\u{11d8a}', '\u{11d8e}', Script::Gunjala_Gondi),
- ('\u{11d90}', '\u{11d91}', Script::Gunjala_Gondi), ('\u{11d93}', '\u{11d94}',
- Script::Gunjala_Gondi), ('\u{11d95}', '\u{11d95}', Script::Gunjala_Gondi), ('\u{11d96}',
- '\u{11d96}', Script::Gunjala_Gondi), ('\u{11d97}', '\u{11d97}', Script::Gunjala_Gondi),
- ('\u{11d98}', '\u{11d98}', Script::Gunjala_Gondi), ('\u{11da0}', '\u{11da9}',
- Script::Gunjala_Gondi), ('\u{11ee0}', '\u{11ef2}', Script::Makasar), ('\u{11ef3}',
- '\u{11ef4}', Script::Makasar), ('\u{11ef5}', '\u{11ef6}', Script::Makasar), ('\u{11ef7}',
- '\u{11ef8}', Script::Makasar), ('\u{11fb0}', '\u{11fb0}', Script::Lisu), ('\u{11fc0}',
- '\u{11fd4}', Script::Tamil), ('\u{11fd5}', '\u{11fdc}', Script::Tamil), ('\u{11fdd}',
- '\u{11fe0}', Script::Tamil), ('\u{11fe1}', '\u{11ff1}', Script::Tamil), ('\u{11fff}',
- '\u{11fff}', Script::Tamil), ('\u{12000}', '\u{12399}', Script::Cuneiform), ('\u{12400}',
- '\u{1246e}', Script::Cuneiform), ('\u{12470}', '\u{12474}', Script::Cuneiform),
- ('\u{12480}', '\u{12543}', Script::Cuneiform), ('\u{13000}', '\u{1342e}',
- Script::Egyptian_Hieroglyphs), ('\u{13430}', '\u{13438}', Script::Egyptian_Hieroglyphs),
+ '\u{10ead}', Script::Yezidi), ('\u{10eb0}', '\u{10eb1}', Script::Yezidi), ('\u{10efd}',
+ '\u{10eff}', Script::Arabic), ('\u{10f00}', '\u{10f1c}', Script::Old_Sogdian),
+ ('\u{10f1d}', '\u{10f26}', Script::Old_Sogdian), ('\u{10f27}', '\u{10f27}',
+ Script::Old_Sogdian), ('\u{10f30}', '\u{10f45}', Script::Sogdian), ('\u{10f46}',
+ '\u{10f50}', Script::Sogdian), ('\u{10f51}', '\u{10f54}', Script::Sogdian), ('\u{10f55}',
+ '\u{10f59}', Script::Sogdian), ('\u{10f70}', '\u{10f81}', Script::Old_Uyghur),
+ ('\u{10f82}', '\u{10f85}', Script::Old_Uyghur), ('\u{10f86}', '\u{10f89}',
+ Script::Old_Uyghur), ('\u{10fb0}', '\u{10fc4}', Script::Chorasmian), ('\u{10fc5}',
+ '\u{10fcb}', Script::Chorasmian), ('\u{10fe0}', '\u{10ff6}', Script::Elymaic),
+ ('\u{11000}', '\u{11000}', Script::Brahmi), ('\u{11001}', '\u{11001}', Script::Brahmi),
+ ('\u{11002}', '\u{11002}', Script::Brahmi), ('\u{11003}', '\u{11037}', Script::Brahmi),
+ ('\u{11038}', '\u{11046}', Script::Brahmi), ('\u{11047}', '\u{1104d}', Script::Brahmi),
+ ('\u{11052}', '\u{11065}', Script::Brahmi), ('\u{11066}', '\u{1106f}', Script::Brahmi),
+ ('\u{11070}', '\u{11070}', Script::Brahmi), ('\u{11071}', '\u{11072}', Script::Brahmi),
+ ('\u{11073}', '\u{11074}', Script::Brahmi), ('\u{11075}', '\u{11075}', Script::Brahmi),
+ ('\u{1107f}', '\u{1107f}', Script::Brahmi), ('\u{11080}', '\u{11081}', Script::Kaithi),
+ ('\u{11082}', '\u{11082}', Script::Kaithi), ('\u{11083}', '\u{110af}', Script::Kaithi),
+ ('\u{110b0}', '\u{110b2}', Script::Kaithi), ('\u{110b3}', '\u{110b6}', Script::Kaithi),
+ ('\u{110b7}', '\u{110b8}', Script::Kaithi), ('\u{110b9}', '\u{110ba}', Script::Kaithi),
+ ('\u{110bb}', '\u{110bc}', Script::Kaithi), ('\u{110bd}', '\u{110bd}', Script::Kaithi),
+ ('\u{110be}', '\u{110c1}', Script::Kaithi), ('\u{110c2}', '\u{110c2}', Script::Kaithi),
+ ('\u{110cd}', '\u{110cd}', Script::Kaithi), ('\u{110d0}', '\u{110e8}',
+ Script::Sora_Sompeng), ('\u{110f0}', '\u{110f9}', Script::Sora_Sompeng), ('\u{11100}',
+ '\u{11102}', Script::Chakma), ('\u{11103}', '\u{11126}', Script::Chakma), ('\u{11127}',
+ '\u{1112b}', Script::Chakma), ('\u{1112c}', '\u{1112c}', Script::Chakma), ('\u{1112d}',
+ '\u{11134}', Script::Chakma), ('\u{11136}', '\u{1113f}', Script::Chakma), ('\u{11140}',
+ '\u{11143}', Script::Chakma), ('\u{11144}', '\u{11144}', Script::Chakma), ('\u{11145}',
+ '\u{11146}', Script::Chakma), ('\u{11147}', '\u{11147}', Script::Chakma), ('\u{11150}',
+ '\u{11172}', Script::Mahajani), ('\u{11173}', '\u{11173}', Script::Mahajani),
+ ('\u{11174}', '\u{11175}', Script::Mahajani), ('\u{11176}', '\u{11176}',
+ Script::Mahajani), ('\u{11180}', '\u{11181}', Script::Sharada), ('\u{11182}', '\u{11182}',
+ Script::Sharada), ('\u{11183}', '\u{111b2}', Script::Sharada), ('\u{111b3}', '\u{111b5}',
+ Script::Sharada), ('\u{111b6}', '\u{111be}', Script::Sharada), ('\u{111bf}', '\u{111c0}',
+ Script::Sharada), ('\u{111c1}', '\u{111c4}', Script::Sharada), ('\u{111c5}', '\u{111c8}',
+ Script::Sharada), ('\u{111c9}', '\u{111cc}', Script::Sharada), ('\u{111cd}', '\u{111cd}',
+ Script::Sharada), ('\u{111ce}', '\u{111ce}', Script::Sharada), ('\u{111cf}', '\u{111cf}',
+ Script::Sharada), ('\u{111d0}', '\u{111d9}', Script::Sharada), ('\u{111da}', '\u{111da}',
+ Script::Sharada), ('\u{111db}', '\u{111db}', Script::Sharada), ('\u{111dc}', '\u{111dc}',
+ Script::Sharada), ('\u{111dd}', '\u{111df}', Script::Sharada), ('\u{111e1}', '\u{111f4}',
+ Script::Sinhala), ('\u{11200}', '\u{11211}', Script::Khojki), ('\u{11213}', '\u{1122b}',
+ Script::Khojki), ('\u{1122c}', '\u{1122e}', Script::Khojki), ('\u{1122f}', '\u{11231}',
+ Script::Khojki), ('\u{11232}', '\u{11233}', Script::Khojki), ('\u{11234}', '\u{11234}',
+ Script::Khojki), ('\u{11235}', '\u{11235}', Script::Khojki), ('\u{11236}', '\u{11237}',
+ Script::Khojki), ('\u{11238}', '\u{1123d}', Script::Khojki), ('\u{1123e}', '\u{1123e}',
+ Script::Khojki), ('\u{1123f}', '\u{11240}', Script::Khojki), ('\u{11241}', '\u{11241}',
+ Script::Khojki), ('\u{11280}', '\u{11286}', Script::Multani), ('\u{11288}', '\u{11288}',
+ Script::Multani), ('\u{1128a}', '\u{1128d}', Script::Multani), ('\u{1128f}', '\u{1129d}',
+ Script::Multani), ('\u{1129f}', '\u{112a8}', Script::Multani), ('\u{112a9}', '\u{112a9}',
+ Script::Multani), ('\u{112b0}', '\u{112de}', Script::Khudawadi), ('\u{112df}',
+ '\u{112df}', Script::Khudawadi), ('\u{112e0}', '\u{112e2}', Script::Khudawadi),
+ ('\u{112e3}', '\u{112ea}', Script::Khudawadi), ('\u{112f0}', '\u{112f9}',
+ Script::Khudawadi), ('\u{11300}', '\u{11301}', Script::Grantha), ('\u{11302}',
+ '\u{11303}', Script::Grantha), ('\u{11305}', '\u{1130c}', Script::Grantha), ('\u{1130f}',
+ '\u{11310}', Script::Grantha), ('\u{11313}', '\u{11328}', Script::Grantha), ('\u{1132a}',
+ '\u{11330}', Script::Grantha), ('\u{11332}', '\u{11333}', Script::Grantha), ('\u{11335}',
+ '\u{11339}', Script::Grantha), ('\u{1133b}', '\u{1133b}', Script::Inherited),
+ ('\u{1133c}', '\u{1133c}', Script::Grantha), ('\u{1133d}', '\u{1133d}', Script::Grantha),
+ ('\u{1133e}', '\u{1133f}', Script::Grantha), ('\u{11340}', '\u{11340}', Script::Grantha),
+ ('\u{11341}', '\u{11344}', Script::Grantha), ('\u{11347}', '\u{11348}', Script::Grantha),
+ ('\u{1134b}', '\u{1134d}', Script::Grantha), ('\u{11350}', '\u{11350}', Script::Grantha),
+ ('\u{11357}', '\u{11357}', Script::Grantha), ('\u{1135d}', '\u{11361}', Script::Grantha),
+ ('\u{11362}', '\u{11363}', Script::Grantha), ('\u{11366}', '\u{1136c}', Script::Grantha),
+ ('\u{11370}', '\u{11374}', Script::Grantha), ('\u{11400}', '\u{11434}', Script::Newa),
+ ('\u{11435}', '\u{11437}', Script::Newa), ('\u{11438}', '\u{1143f}', Script::Newa),
+ ('\u{11440}', '\u{11441}', Script::Newa), ('\u{11442}', '\u{11444}', Script::Newa),
+ ('\u{11445}', '\u{11445}', Script::Newa), ('\u{11446}', '\u{11446}', Script::Newa),
+ ('\u{11447}', '\u{1144a}', Script::Newa), ('\u{1144b}', '\u{1144f}', Script::Newa),
+ ('\u{11450}', '\u{11459}', Script::Newa), ('\u{1145a}', '\u{1145b}', Script::Newa),
+ ('\u{1145d}', '\u{1145d}', Script::Newa), ('\u{1145e}', '\u{1145e}', Script::Newa),
+ ('\u{1145f}', '\u{11461}', Script::Newa), ('\u{11480}', '\u{114af}', Script::Tirhuta),
+ ('\u{114b0}', '\u{114b2}', Script::Tirhuta), ('\u{114b3}', '\u{114b8}', Script::Tirhuta),
+ ('\u{114b9}', '\u{114b9}', Script::Tirhuta), ('\u{114ba}', '\u{114ba}', Script::Tirhuta),
+ ('\u{114bb}', '\u{114be}', Script::Tirhuta), ('\u{114bf}', '\u{114c0}', Script::Tirhuta),
+ ('\u{114c1}', '\u{114c1}', Script::Tirhuta), ('\u{114c2}', '\u{114c3}', Script::Tirhuta),
+ ('\u{114c4}', '\u{114c5}', Script::Tirhuta), ('\u{114c6}', '\u{114c6}', Script::Tirhuta),
+ ('\u{114c7}', '\u{114c7}', Script::Tirhuta), ('\u{114d0}', '\u{114d9}', Script::Tirhuta),
+ ('\u{11580}', '\u{115ae}', Script::Siddham), ('\u{115af}', '\u{115b1}', Script::Siddham),
+ ('\u{115b2}', '\u{115b5}', Script::Siddham), ('\u{115b8}', '\u{115bb}', Script::Siddham),
+ ('\u{115bc}', '\u{115bd}', Script::Siddham), ('\u{115be}', '\u{115be}', Script::Siddham),
+ ('\u{115bf}', '\u{115c0}', Script::Siddham), ('\u{115c1}', '\u{115d7}', Script::Siddham),
+ ('\u{115d8}', '\u{115db}', Script::Siddham), ('\u{115dc}', '\u{115dd}', Script::Siddham),
+ ('\u{11600}', '\u{1162f}', Script::Modi), ('\u{11630}', '\u{11632}', Script::Modi),
+ ('\u{11633}', '\u{1163a}', Script::Modi), ('\u{1163b}', '\u{1163c}', Script::Modi),
+ ('\u{1163d}', '\u{1163d}', Script::Modi), ('\u{1163e}', '\u{1163e}', Script::Modi),
+ ('\u{1163f}', '\u{11640}', Script::Modi), ('\u{11641}', '\u{11643}', Script::Modi),
+ ('\u{11644}', '\u{11644}', Script::Modi), ('\u{11650}', '\u{11659}', Script::Modi),
+ ('\u{11660}', '\u{1166c}', Script::Mongolian), ('\u{11680}', '\u{116aa}', Script::Takri),
+ ('\u{116ab}', '\u{116ab}', Script::Takri), ('\u{116ac}', '\u{116ac}', Script::Takri),
+ ('\u{116ad}', '\u{116ad}', Script::Takri), ('\u{116ae}', '\u{116af}', Script::Takri),
+ ('\u{116b0}', '\u{116b5}', Script::Takri), ('\u{116b6}', '\u{116b6}', Script::Takri),
+ ('\u{116b7}', '\u{116b7}', Script::Takri), ('\u{116b8}', '\u{116b8}', Script::Takri),
+ ('\u{116b9}', '\u{116b9}', Script::Takri), ('\u{116c0}', '\u{116c9}', Script::Takri),
+ ('\u{11700}', '\u{1171a}', Script::Ahom), ('\u{1171d}', '\u{1171f}', Script::Ahom),
+ ('\u{11720}', '\u{11721}', Script::Ahom), ('\u{11722}', '\u{11725}', Script::Ahom),
+ ('\u{11726}', '\u{11726}', Script::Ahom), ('\u{11727}', '\u{1172b}', Script::Ahom),
+ ('\u{11730}', '\u{11739}', Script::Ahom), ('\u{1173a}', '\u{1173b}', Script::Ahom),
+ ('\u{1173c}', '\u{1173e}', Script::Ahom), ('\u{1173f}', '\u{1173f}', Script::Ahom),
+ ('\u{11740}', '\u{11746}', Script::Ahom), ('\u{11800}', '\u{1182b}', Script::Dogra),
+ ('\u{1182c}', '\u{1182e}', Script::Dogra), ('\u{1182f}', '\u{11837}', Script::Dogra),
+ ('\u{11838}', '\u{11838}', Script::Dogra), ('\u{11839}', '\u{1183a}', Script::Dogra),
+ ('\u{1183b}', '\u{1183b}', Script::Dogra), ('\u{118a0}', '\u{118df}',
+ Script::Warang_Citi), ('\u{118e0}', '\u{118e9}', Script::Warang_Citi), ('\u{118ea}',
+ '\u{118f2}', Script::Warang_Citi), ('\u{118ff}', '\u{118ff}', Script::Warang_Citi),
+ ('\u{11900}', '\u{11906}', Script::Dives_Akuru), ('\u{11909}', '\u{11909}',
+ Script::Dives_Akuru), ('\u{1190c}', '\u{11913}', Script::Dives_Akuru), ('\u{11915}',
+ '\u{11916}', Script::Dives_Akuru), ('\u{11918}', '\u{1192f}', Script::Dives_Akuru),
+ ('\u{11930}', '\u{11935}', Script::Dives_Akuru), ('\u{11937}', '\u{11938}',
+ Script::Dives_Akuru), ('\u{1193b}', '\u{1193c}', Script::Dives_Akuru), ('\u{1193d}',
+ '\u{1193d}', Script::Dives_Akuru), ('\u{1193e}', '\u{1193e}', Script::Dives_Akuru),
+ ('\u{1193f}', '\u{1193f}', Script::Dives_Akuru), ('\u{11940}', '\u{11940}',
+ Script::Dives_Akuru), ('\u{11941}', '\u{11941}', Script::Dives_Akuru), ('\u{11942}',
+ '\u{11942}', Script::Dives_Akuru), ('\u{11943}', '\u{11943}', Script::Dives_Akuru),
+ ('\u{11944}', '\u{11946}', Script::Dives_Akuru), ('\u{11950}', '\u{11959}',
+ Script::Dives_Akuru), ('\u{119a0}', '\u{119a7}', Script::Nandinagari), ('\u{119aa}',
+ '\u{119d0}', Script::Nandinagari), ('\u{119d1}', '\u{119d3}', Script::Nandinagari),
+ ('\u{119d4}', '\u{119d7}', Script::Nandinagari), ('\u{119da}', '\u{119db}',
+ Script::Nandinagari), ('\u{119dc}', '\u{119df}', Script::Nandinagari), ('\u{119e0}',
+ '\u{119e0}', Script::Nandinagari), ('\u{119e1}', '\u{119e1}', Script::Nandinagari),
+ ('\u{119e2}', '\u{119e2}', Script::Nandinagari), ('\u{119e3}', '\u{119e3}',
+ Script::Nandinagari), ('\u{119e4}', '\u{119e4}', Script::Nandinagari), ('\u{11a00}',
+ '\u{11a00}', Script::Zanabazar_Square), ('\u{11a01}', '\u{11a0a}',
+ Script::Zanabazar_Square), ('\u{11a0b}', '\u{11a32}', Script::Zanabazar_Square),
+ ('\u{11a33}', '\u{11a38}', Script::Zanabazar_Square), ('\u{11a39}', '\u{11a39}',
+ Script::Zanabazar_Square), ('\u{11a3a}', '\u{11a3a}', Script::Zanabazar_Square),
+ ('\u{11a3b}', '\u{11a3e}', Script::Zanabazar_Square), ('\u{11a3f}', '\u{11a46}',
+ Script::Zanabazar_Square), ('\u{11a47}', '\u{11a47}', Script::Zanabazar_Square),
+ ('\u{11a50}', '\u{11a50}', Script::Soyombo), ('\u{11a51}', '\u{11a56}', Script::Soyombo),
+ ('\u{11a57}', '\u{11a58}', Script::Soyombo), ('\u{11a59}', '\u{11a5b}', Script::Soyombo),
+ ('\u{11a5c}', '\u{11a89}', Script::Soyombo), ('\u{11a8a}', '\u{11a96}', Script::Soyombo),
+ ('\u{11a97}', '\u{11a97}', Script::Soyombo), ('\u{11a98}', '\u{11a99}', Script::Soyombo),
+ ('\u{11a9a}', '\u{11a9c}', Script::Soyombo), ('\u{11a9d}', '\u{11a9d}', Script::Soyombo),
+ ('\u{11a9e}', '\u{11aa2}', Script::Soyombo), ('\u{11ab0}', '\u{11abf}',
+ Script::Canadian_Aboriginal), ('\u{11ac0}', '\u{11af8}', Script::Pau_Cin_Hau),
+ ('\u{11b00}', '\u{11b09}', Script::Devanagari), ('\u{11c00}', '\u{11c08}',
+ Script::Bhaiksuki), ('\u{11c0a}', '\u{11c2e}', Script::Bhaiksuki), ('\u{11c2f}',
+ '\u{11c2f}', Script::Bhaiksuki), ('\u{11c30}', '\u{11c36}', Script::Bhaiksuki),
+ ('\u{11c38}', '\u{11c3d}', Script::Bhaiksuki), ('\u{11c3e}', '\u{11c3e}',
+ Script::Bhaiksuki), ('\u{11c3f}', '\u{11c3f}', Script::Bhaiksuki), ('\u{11c40}',
+ '\u{11c40}', Script::Bhaiksuki), ('\u{11c41}', '\u{11c45}', Script::Bhaiksuki),
+ ('\u{11c50}', '\u{11c59}', Script::Bhaiksuki), ('\u{11c5a}', '\u{11c6c}',
+ Script::Bhaiksuki), ('\u{11c70}', '\u{11c71}', Script::Marchen), ('\u{11c72}',
+ '\u{11c8f}', Script::Marchen), ('\u{11c92}', '\u{11ca7}', Script::Marchen), ('\u{11ca9}',
+ '\u{11ca9}', Script::Marchen), ('\u{11caa}', '\u{11cb0}', Script::Marchen), ('\u{11cb1}',
+ '\u{11cb1}', Script::Marchen), ('\u{11cb2}', '\u{11cb3}', Script::Marchen), ('\u{11cb4}',
+ '\u{11cb4}', Script::Marchen), ('\u{11cb5}', '\u{11cb6}', Script::Marchen), ('\u{11d00}',
+ '\u{11d06}', Script::Masaram_Gondi), ('\u{11d08}', '\u{11d09}', Script::Masaram_Gondi),
+ ('\u{11d0b}', '\u{11d30}', Script::Masaram_Gondi), ('\u{11d31}', '\u{11d36}',
+ Script::Masaram_Gondi), ('\u{11d3a}', '\u{11d3a}', Script::Masaram_Gondi), ('\u{11d3c}',
+ '\u{11d3d}', Script::Masaram_Gondi), ('\u{11d3f}', '\u{11d45}', Script::Masaram_Gondi),
+ ('\u{11d46}', '\u{11d46}', Script::Masaram_Gondi), ('\u{11d47}', '\u{11d47}',
+ Script::Masaram_Gondi), ('\u{11d50}', '\u{11d59}', Script::Masaram_Gondi), ('\u{11d60}',
+ '\u{11d65}', Script::Gunjala_Gondi), ('\u{11d67}', '\u{11d68}', Script::Gunjala_Gondi),
+ ('\u{11d6a}', '\u{11d89}', Script::Gunjala_Gondi), ('\u{11d8a}', '\u{11d8e}',
+ Script::Gunjala_Gondi), ('\u{11d90}', '\u{11d91}', Script::Gunjala_Gondi), ('\u{11d93}',
+ '\u{11d94}', Script::Gunjala_Gondi), ('\u{11d95}', '\u{11d95}', Script::Gunjala_Gondi),
+ ('\u{11d96}', '\u{11d96}', Script::Gunjala_Gondi), ('\u{11d97}', '\u{11d97}',
+ Script::Gunjala_Gondi), ('\u{11d98}', '\u{11d98}', Script::Gunjala_Gondi), ('\u{11da0}',
+ '\u{11da9}', Script::Gunjala_Gondi), ('\u{11ee0}', '\u{11ef2}', Script::Makasar),
+ ('\u{11ef3}', '\u{11ef4}', Script::Makasar), ('\u{11ef5}', '\u{11ef6}', Script::Makasar),
+ ('\u{11ef7}', '\u{11ef8}', Script::Makasar), ('\u{11f00}', '\u{11f01}', Script::Kawi),
+ ('\u{11f02}', '\u{11f02}', Script::Kawi), ('\u{11f03}', '\u{11f03}', Script::Kawi),
+ ('\u{11f04}', '\u{11f10}', Script::Kawi), ('\u{11f12}', '\u{11f33}', Script::Kawi),
+ ('\u{11f34}', '\u{11f35}', Script::Kawi), ('\u{11f36}', '\u{11f3a}', Script::Kawi),
+ ('\u{11f3e}', '\u{11f3f}', Script::Kawi), ('\u{11f40}', '\u{11f40}', Script::Kawi),
+ ('\u{11f41}', '\u{11f41}', Script::Kawi), ('\u{11f42}', '\u{11f42}', Script::Kawi),
+ ('\u{11f43}', '\u{11f4f}', Script::Kawi), ('\u{11f50}', '\u{11f59}', Script::Kawi),
+ ('\u{11fb0}', '\u{11fb0}', Script::Lisu), ('\u{11fc0}', '\u{11fd4}', Script::Tamil),
+ ('\u{11fd5}', '\u{11fdc}', Script::Tamil), ('\u{11fdd}', '\u{11fe0}', Script::Tamil),
+ ('\u{11fe1}', '\u{11ff1}', Script::Tamil), ('\u{11fff}', '\u{11fff}', Script::Tamil),
+ ('\u{12000}', '\u{12399}', Script::Cuneiform), ('\u{12400}', '\u{1246e}',
+ Script::Cuneiform), ('\u{12470}', '\u{12474}', Script::Cuneiform), ('\u{12480}',
+ '\u{12543}', Script::Cuneiform), ('\u{12f90}', '\u{12ff0}', Script::Cypro_Minoan),
+ ('\u{12ff1}', '\u{12ff2}', Script::Cypro_Minoan), ('\u{13000}', '\u{1342f}',
+ Script::Egyptian_Hieroglyphs), ('\u{13430}', '\u{1343f}', Script::Egyptian_Hieroglyphs),
+ ('\u{13440}', '\u{13440}', Script::Egyptian_Hieroglyphs), ('\u{13441}', '\u{13446}',
+ Script::Egyptian_Hieroglyphs), ('\u{13447}', '\u{13455}', Script::Egyptian_Hieroglyphs),
('\u{14400}', '\u{14646}', Script::Anatolian_Hieroglyphs), ('\u{16800}', '\u{16a38}',
Script::Bamum), ('\u{16a40}', '\u{16a5e}', Script::Mro), ('\u{16a60}', '\u{16a69}',
- Script::Mro), ('\u{16a6e}', '\u{16a6f}', Script::Mro), ('\u{16ad0}', '\u{16aed}',
+ Script::Mro), ('\u{16a6e}', '\u{16a6f}', Script::Mro), ('\u{16a70}', '\u{16abe}',
+ Script::Tangsa), ('\u{16ac0}', '\u{16ac9}', Script::Tangsa), ('\u{16ad0}', '\u{16aed}',
Script::Bassa_Vah), ('\u{16af0}', '\u{16af4}', Script::Bassa_Vah), ('\u{16af5}',
'\u{16af5}', Script::Bassa_Vah), ('\u{16b00}', '\u{16b2f}', Script::Pahawh_Hmong),
('\u{16b30}', '\u{16b36}', Script::Pahawh_Hmong), ('\u{16b37}', '\u{16b3b}',
@@ -2866,118 +2986,132 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
'\u{16f50}', Script::Miao), ('\u{16f51}', '\u{16f87}', Script::Miao), ('\u{16f8f}',
'\u{16f92}', Script::Miao), ('\u{16f93}', '\u{16f9f}', Script::Miao), ('\u{16fe0}',
'\u{16fe0}', Script::Tangut), ('\u{16fe1}', '\u{16fe1}', Script::Nushu), ('\u{16fe2}',
- '\u{16fe2}', Script::Common), ('\u{16fe3}', '\u{16fe3}', Script::Common), ('\u{16fe4}',
+ '\u{16fe2}', Script::Han), ('\u{16fe3}', '\u{16fe3}', Script::Han), ('\u{16fe4}',
'\u{16fe4}', Script::Khitan_Small_Script), ('\u{16ff0}', '\u{16ff1}', Script::Han),
('\u{17000}', '\u{187f7}', Script::Tangut), ('\u{18800}', '\u{18aff}', Script::Tangut),
('\u{18b00}', '\u{18cd5}', Script::Khitan_Small_Script), ('\u{18d00}', '\u{18d08}',
- Script::Tangut), ('\u{1b000}', '\u{1b000}', Script::Katakana), ('\u{1b001}', '\u{1b11e}',
- Script::Hiragana), ('\u{1b150}', '\u{1b152}', Script::Hiragana), ('\u{1b164}',
- '\u{1b167}', Script::Katakana), ('\u{1b170}', '\u{1b2fb}', Script::Nushu), ('\u{1bc00}',
- '\u{1bc6a}', Script::Duployan), ('\u{1bc70}', '\u{1bc7c}', Script::Duployan),
- ('\u{1bc80}', '\u{1bc88}', Script::Duployan), ('\u{1bc90}', '\u{1bc99}',
- Script::Duployan), ('\u{1bc9c}', '\u{1bc9c}', Script::Duployan), ('\u{1bc9d}',
- '\u{1bc9e}', Script::Duployan), ('\u{1bc9f}', '\u{1bc9f}', Script::Duployan),
- ('\u{1bca0}', '\u{1bca3}', Script::Common), ('\u{1d000}', '\u{1d0f5}', Script::Common),
- ('\u{1d100}', '\u{1d126}', Script::Common), ('\u{1d129}', '\u{1d164}', Script::Common),
- ('\u{1d165}', '\u{1d166}', Script::Common), ('\u{1d167}', '\u{1d169}', Script::Inherited),
- ('\u{1d16a}', '\u{1d16c}', Script::Common), ('\u{1d16d}', '\u{1d172}', Script::Common),
- ('\u{1d173}', '\u{1d17a}', Script::Common), ('\u{1d17b}', '\u{1d182}', Script::Inherited),
- ('\u{1d183}', '\u{1d184}', Script::Common), ('\u{1d185}', '\u{1d18b}', Script::Inherited),
- ('\u{1d18c}', '\u{1d1a9}', Script::Common), ('\u{1d1aa}', '\u{1d1ad}', Script::Inherited),
- ('\u{1d1ae}', '\u{1d1e8}', Script::Common), ('\u{1d200}', '\u{1d241}', Script::Greek),
- ('\u{1d242}', '\u{1d244}', Script::Greek), ('\u{1d245}', '\u{1d245}', Script::Greek),
- ('\u{1d2e0}', '\u{1d2f3}', Script::Common), ('\u{1d300}', '\u{1d356}', Script::Common),
- ('\u{1d360}', '\u{1d378}', Script::Common), ('\u{1d400}', '\u{1d454}', Script::Common),
- ('\u{1d456}', '\u{1d49c}', Script::Common), ('\u{1d49e}', '\u{1d49f}', Script::Common),
- ('\u{1d4a2}', '\u{1d4a2}', Script::Common), ('\u{1d4a5}', '\u{1d4a6}', Script::Common),
- ('\u{1d4a9}', '\u{1d4ac}', Script::Common), ('\u{1d4ae}', '\u{1d4b9}', Script::Common),
- ('\u{1d4bb}', '\u{1d4bb}', Script::Common), ('\u{1d4bd}', '\u{1d4c3}', Script::Common),
- ('\u{1d4c5}', '\u{1d505}', Script::Common), ('\u{1d507}', '\u{1d50a}', Script::Common),
- ('\u{1d50d}', '\u{1d514}', Script::Common), ('\u{1d516}', '\u{1d51c}', Script::Common),
- ('\u{1d51e}', '\u{1d539}', Script::Common), ('\u{1d53b}', '\u{1d53e}', Script::Common),
- ('\u{1d540}', '\u{1d544}', Script::Common), ('\u{1d546}', '\u{1d546}', Script::Common),
- ('\u{1d54a}', '\u{1d550}', Script::Common), ('\u{1d552}', '\u{1d6a5}', Script::Common),
- ('\u{1d6a8}', '\u{1d6c0}', Script::Common), ('\u{1d6c1}', '\u{1d6c1}', Script::Common),
- ('\u{1d6c2}', '\u{1d6da}', Script::Common), ('\u{1d6db}', '\u{1d6db}', Script::Common),
- ('\u{1d6dc}', '\u{1d6fa}', Script::Common), ('\u{1d6fb}', '\u{1d6fb}', Script::Common),
- ('\u{1d6fc}', '\u{1d714}', Script::Common), ('\u{1d715}', '\u{1d715}', Script::Common),
- ('\u{1d716}', '\u{1d734}', Script::Common), ('\u{1d735}', '\u{1d735}', Script::Common),
- ('\u{1d736}', '\u{1d74e}', Script::Common), ('\u{1d74f}', '\u{1d74f}', Script::Common),
- ('\u{1d750}', '\u{1d76e}', Script::Common), ('\u{1d76f}', '\u{1d76f}', Script::Common),
- ('\u{1d770}', '\u{1d788}', Script::Common), ('\u{1d789}', '\u{1d789}', Script::Common),
- ('\u{1d78a}', '\u{1d7a8}', Script::Common), ('\u{1d7a9}', '\u{1d7a9}', Script::Common),
- ('\u{1d7aa}', '\u{1d7c2}', Script::Common), ('\u{1d7c3}', '\u{1d7c3}', Script::Common),
- ('\u{1d7c4}', '\u{1d7cb}', Script::Common), ('\u{1d7ce}', '\u{1d7ff}', Script::Common),
- ('\u{1d800}', '\u{1d9ff}', Script::SignWriting), ('\u{1da00}', '\u{1da36}',
- Script::SignWriting), ('\u{1da37}', '\u{1da3a}', Script::SignWriting), ('\u{1da3b}',
- '\u{1da6c}', Script::SignWriting), ('\u{1da6d}', '\u{1da74}', Script::SignWriting),
- ('\u{1da75}', '\u{1da75}', Script::SignWriting), ('\u{1da76}', '\u{1da83}',
- Script::SignWriting), ('\u{1da84}', '\u{1da84}', Script::SignWriting), ('\u{1da85}',
- '\u{1da86}', Script::SignWriting), ('\u{1da87}', '\u{1da8b}', Script::SignWriting),
- ('\u{1da9b}', '\u{1da9f}', Script::SignWriting), ('\u{1daa1}', '\u{1daaf}',
- Script::SignWriting), ('\u{1e000}', '\u{1e006}', Script::Glagolitic), ('\u{1e008}',
- '\u{1e018}', Script::Glagolitic), ('\u{1e01b}', '\u{1e021}', Script::Glagolitic),
- ('\u{1e023}', '\u{1e024}', Script::Glagolitic), ('\u{1e026}', '\u{1e02a}',
- Script::Glagolitic), ('\u{1e100}', '\u{1e12c}', Script::Nyiakeng_Puachue_Hmong),
- ('\u{1e130}', '\u{1e136}', Script::Nyiakeng_Puachue_Hmong), ('\u{1e137}', '\u{1e13d}',
+ Script::Tangut), ('\u{1aff0}', '\u{1aff3}', Script::Katakana), ('\u{1aff5}', '\u{1affb}',
+ Script::Katakana), ('\u{1affd}', '\u{1affe}', Script::Katakana), ('\u{1b000}',
+ '\u{1b000}', Script::Katakana), ('\u{1b001}', '\u{1b11f}', Script::Hiragana),
+ ('\u{1b120}', '\u{1b122}', Script::Katakana), ('\u{1b132}', '\u{1b132}',
+ Script::Hiragana), ('\u{1b150}', '\u{1b152}', Script::Hiragana), ('\u{1b155}',
+ '\u{1b155}', Script::Katakana), ('\u{1b164}', '\u{1b167}', Script::Katakana),
+ ('\u{1b170}', '\u{1b2fb}', Script::Nushu), ('\u{1bc00}', '\u{1bc6a}', Script::Duployan),
+ ('\u{1bc70}', '\u{1bc7c}', Script::Duployan), ('\u{1bc80}', '\u{1bc88}',
+ Script::Duployan), ('\u{1bc90}', '\u{1bc99}', Script::Duployan), ('\u{1bc9c}',
+ '\u{1bc9c}', Script::Duployan), ('\u{1bc9d}', '\u{1bc9e}', Script::Duployan),
+ ('\u{1bc9f}', '\u{1bc9f}', Script::Duployan), ('\u{1bca0}', '\u{1bca3}', Script::Common),
+ ('\u{1cf00}', '\u{1cf2d}', Script::Inherited), ('\u{1cf30}', '\u{1cf46}',
+ Script::Inherited), ('\u{1cf50}', '\u{1cfc3}', Script::Common), ('\u{1d000}', '\u{1d0f5}',
+ Script::Common), ('\u{1d100}', '\u{1d126}', Script::Common), ('\u{1d129}', '\u{1d164}',
+ Script::Common), ('\u{1d165}', '\u{1d166}', Script::Common), ('\u{1d167}', '\u{1d169}',
+ Script::Inherited), ('\u{1d16a}', '\u{1d16c}', Script::Common), ('\u{1d16d}', '\u{1d172}',
+ Script::Common), ('\u{1d173}', '\u{1d17a}', Script::Common), ('\u{1d17b}', '\u{1d182}',
+ Script::Inherited), ('\u{1d183}', '\u{1d184}', Script::Common), ('\u{1d185}', '\u{1d18b}',
+ Script::Inherited), ('\u{1d18c}', '\u{1d1a9}', Script::Common), ('\u{1d1aa}', '\u{1d1ad}',
+ Script::Inherited), ('\u{1d1ae}', '\u{1d1ea}', Script::Common), ('\u{1d200}', '\u{1d241}',
+ Script::Greek), ('\u{1d242}', '\u{1d244}', Script::Greek), ('\u{1d245}', '\u{1d245}',
+ Script::Greek), ('\u{1d2c0}', '\u{1d2d3}', Script::Common), ('\u{1d2e0}', '\u{1d2f3}',
+ Script::Common), ('\u{1d300}', '\u{1d356}', Script::Common), ('\u{1d360}', '\u{1d378}',
+ Script::Common), ('\u{1d400}', '\u{1d454}', Script::Common), ('\u{1d456}', '\u{1d49c}',
+ Script::Common), ('\u{1d49e}', '\u{1d49f}', Script::Common), ('\u{1d4a2}', '\u{1d4a2}',
+ Script::Common), ('\u{1d4a5}', '\u{1d4a6}', Script::Common), ('\u{1d4a9}', '\u{1d4ac}',
+ Script::Common), ('\u{1d4ae}', '\u{1d4b9}', Script::Common), ('\u{1d4bb}', '\u{1d4bb}',
+ Script::Common), ('\u{1d4bd}', '\u{1d4c3}', Script::Common), ('\u{1d4c5}', '\u{1d505}',
+ Script::Common), ('\u{1d507}', '\u{1d50a}', Script::Common), ('\u{1d50d}', '\u{1d514}',
+ Script::Common), ('\u{1d516}', '\u{1d51c}', Script::Common), ('\u{1d51e}', '\u{1d539}',
+ Script::Common), ('\u{1d53b}', '\u{1d53e}', Script::Common), ('\u{1d540}', '\u{1d544}',
+ Script::Common), ('\u{1d546}', '\u{1d546}', Script::Common), ('\u{1d54a}', '\u{1d550}',
+ Script::Common), ('\u{1d552}', '\u{1d6a5}', Script::Common), ('\u{1d6a8}', '\u{1d6c0}',
+ Script::Common), ('\u{1d6c1}', '\u{1d6c1}', Script::Common), ('\u{1d6c2}', '\u{1d6da}',
+ Script::Common), ('\u{1d6db}', '\u{1d6db}', Script::Common), ('\u{1d6dc}', '\u{1d6fa}',
+ Script::Common), ('\u{1d6fb}', '\u{1d6fb}', Script::Common), ('\u{1d6fc}', '\u{1d714}',
+ Script::Common), ('\u{1d715}', '\u{1d715}', Script::Common), ('\u{1d716}', '\u{1d734}',
+ Script::Common), ('\u{1d735}', '\u{1d735}', Script::Common), ('\u{1d736}', '\u{1d74e}',
+ Script::Common), ('\u{1d74f}', '\u{1d74f}', Script::Common), ('\u{1d750}', '\u{1d76e}',
+ Script::Common), ('\u{1d76f}', '\u{1d76f}', Script::Common), ('\u{1d770}', '\u{1d788}',
+ Script::Common), ('\u{1d789}', '\u{1d789}', Script::Common), ('\u{1d78a}', '\u{1d7a8}',
+ Script::Common), ('\u{1d7a9}', '\u{1d7a9}', Script::Common), ('\u{1d7aa}', '\u{1d7c2}',
+ Script::Common), ('\u{1d7c3}', '\u{1d7c3}', Script::Common), ('\u{1d7c4}', '\u{1d7cb}',
+ Script::Common), ('\u{1d7ce}', '\u{1d7ff}', Script::Common), ('\u{1d800}', '\u{1d9ff}',
+ Script::SignWriting), ('\u{1da00}', '\u{1da36}', Script::SignWriting), ('\u{1da37}',
+ '\u{1da3a}', Script::SignWriting), ('\u{1da3b}', '\u{1da6c}', Script::SignWriting),
+ ('\u{1da6d}', '\u{1da74}', Script::SignWriting), ('\u{1da75}', '\u{1da75}',
+ Script::SignWriting), ('\u{1da76}', '\u{1da83}', Script::SignWriting), ('\u{1da84}',
+ '\u{1da84}', Script::SignWriting), ('\u{1da85}', '\u{1da86}', Script::SignWriting),
+ ('\u{1da87}', '\u{1da8b}', Script::SignWriting), ('\u{1da9b}', '\u{1da9f}',
+ Script::SignWriting), ('\u{1daa1}', '\u{1daaf}', Script::SignWriting), ('\u{1df00}',
+ '\u{1df09}', Script::Latin), ('\u{1df0a}', '\u{1df0a}', Script::Latin), ('\u{1df0b}',
+ '\u{1df1e}', Script::Latin), ('\u{1df25}', '\u{1df2a}', Script::Latin), ('\u{1e000}',
+ '\u{1e006}', Script::Glagolitic), ('\u{1e008}', '\u{1e018}', Script::Glagolitic),
+ ('\u{1e01b}', '\u{1e021}', Script::Glagolitic), ('\u{1e023}', '\u{1e024}',
+ Script::Glagolitic), ('\u{1e026}', '\u{1e02a}', Script::Glagolitic), ('\u{1e030}',
+ '\u{1e06d}', Script::Cyrillic), ('\u{1e08f}', '\u{1e08f}', Script::Cyrillic),
+ ('\u{1e100}', '\u{1e12c}', Script::Nyiakeng_Puachue_Hmong), ('\u{1e130}', '\u{1e136}',
+ Script::Nyiakeng_Puachue_Hmong), ('\u{1e137}', '\u{1e13d}',
Script::Nyiakeng_Puachue_Hmong), ('\u{1e140}', '\u{1e149}',
Script::Nyiakeng_Puachue_Hmong), ('\u{1e14e}', '\u{1e14e}',
Script::Nyiakeng_Puachue_Hmong), ('\u{1e14f}', '\u{1e14f}',
- Script::Nyiakeng_Puachue_Hmong), ('\u{1e2c0}', '\u{1e2eb}', Script::Wancho), ('\u{1e2ec}',
+ Script::Nyiakeng_Puachue_Hmong), ('\u{1e290}', '\u{1e2ad}', Script::Toto), ('\u{1e2ae}',
+ '\u{1e2ae}', Script::Toto), ('\u{1e2c0}', '\u{1e2eb}', Script::Wancho), ('\u{1e2ec}',
'\u{1e2ef}', Script::Wancho), ('\u{1e2f0}', '\u{1e2f9}', Script::Wancho), ('\u{1e2ff}',
- '\u{1e2ff}', Script::Wancho), ('\u{1e800}', '\u{1e8c4}', Script::Mende_Kikakui),
- ('\u{1e8c7}', '\u{1e8cf}', Script::Mende_Kikakui), ('\u{1e8d0}', '\u{1e8d6}',
- Script::Mende_Kikakui), ('\u{1e900}', '\u{1e943}', Script::Adlam), ('\u{1e944}',
- '\u{1e94a}', Script::Adlam), ('\u{1e94b}', '\u{1e94b}', Script::Adlam), ('\u{1e950}',
- '\u{1e959}', Script::Adlam), ('\u{1e95e}', '\u{1e95f}', Script::Adlam), ('\u{1ec71}',
- '\u{1ecab}', Script::Common), ('\u{1ecac}', '\u{1ecac}', Script::Common), ('\u{1ecad}',
- '\u{1ecaf}', Script::Common), ('\u{1ecb0}', '\u{1ecb0}', Script::Common), ('\u{1ecb1}',
- '\u{1ecb4}', Script::Common), ('\u{1ed01}', '\u{1ed2d}', Script::Common), ('\u{1ed2e}',
- '\u{1ed2e}', Script::Common), ('\u{1ed2f}', '\u{1ed3d}', Script::Common), ('\u{1ee00}',
- '\u{1ee03}', Script::Arabic), ('\u{1ee05}', '\u{1ee1f}', Script::Arabic), ('\u{1ee21}',
- '\u{1ee22}', Script::Arabic), ('\u{1ee24}', '\u{1ee24}', Script::Arabic), ('\u{1ee27}',
- '\u{1ee27}', Script::Arabic), ('\u{1ee29}', '\u{1ee32}', Script::Arabic), ('\u{1ee34}',
- '\u{1ee37}', Script::Arabic), ('\u{1ee39}', '\u{1ee39}', Script::Arabic), ('\u{1ee3b}',
- '\u{1ee3b}', Script::Arabic), ('\u{1ee42}', '\u{1ee42}', Script::Arabic), ('\u{1ee47}',
- '\u{1ee47}', Script::Arabic), ('\u{1ee49}', '\u{1ee49}', Script::Arabic), ('\u{1ee4b}',
- '\u{1ee4b}', Script::Arabic), ('\u{1ee4d}', '\u{1ee4f}', Script::Arabic), ('\u{1ee51}',
- '\u{1ee52}', Script::Arabic), ('\u{1ee54}', '\u{1ee54}', Script::Arabic), ('\u{1ee57}',
- '\u{1ee57}', Script::Arabic), ('\u{1ee59}', '\u{1ee59}', Script::Arabic), ('\u{1ee5b}',
- '\u{1ee5b}', Script::Arabic), ('\u{1ee5d}', '\u{1ee5d}', Script::Arabic), ('\u{1ee5f}',
- '\u{1ee5f}', Script::Arabic), ('\u{1ee61}', '\u{1ee62}', Script::Arabic), ('\u{1ee64}',
- '\u{1ee64}', Script::Arabic), ('\u{1ee67}', '\u{1ee6a}', Script::Arabic), ('\u{1ee6c}',
- '\u{1ee72}', Script::Arabic), ('\u{1ee74}', '\u{1ee77}', Script::Arabic), ('\u{1ee79}',
- '\u{1ee7c}', Script::Arabic), ('\u{1ee7e}', '\u{1ee7e}', Script::Arabic), ('\u{1ee80}',
- '\u{1ee89}', Script::Arabic), ('\u{1ee8b}', '\u{1ee9b}', Script::Arabic), ('\u{1eea1}',
- '\u{1eea3}', Script::Arabic), ('\u{1eea5}', '\u{1eea9}', Script::Arabic), ('\u{1eeab}',
- '\u{1eebb}', Script::Arabic), ('\u{1eef0}', '\u{1eef1}', Script::Arabic), ('\u{1f000}',
- '\u{1f02b}', Script::Common), ('\u{1f030}', '\u{1f093}', Script::Common), ('\u{1f0a0}',
- '\u{1f0ae}', Script::Common), ('\u{1f0b1}', '\u{1f0bf}', Script::Common), ('\u{1f0c1}',
- '\u{1f0cf}', Script::Common), ('\u{1f0d1}', '\u{1f0f5}', Script::Common), ('\u{1f100}',
- '\u{1f10c}', Script::Common), ('\u{1f10d}', '\u{1f1ad}', Script::Common), ('\u{1f1e6}',
- '\u{1f1ff}', Script::Common), ('\u{1f200}', '\u{1f200}', Script::Hiragana), ('\u{1f201}',
- '\u{1f202}', Script::Common), ('\u{1f210}', '\u{1f23b}', Script::Common), ('\u{1f240}',
- '\u{1f248}', Script::Common), ('\u{1f250}', '\u{1f251}', Script::Common), ('\u{1f260}',
- '\u{1f265}', Script::Common), ('\u{1f300}', '\u{1f3fa}', Script::Common), ('\u{1f3fb}',
- '\u{1f3ff}', Script::Common), ('\u{1f400}', '\u{1f6d7}', Script::Common), ('\u{1f6e0}',
- '\u{1f6ec}', Script::Common), ('\u{1f6f0}', '\u{1f6fc}', Script::Common), ('\u{1f700}',
- '\u{1f773}', Script::Common), ('\u{1f780}', '\u{1f7d8}', Script::Common), ('\u{1f7e0}',
- '\u{1f7eb}', Script::Common), ('\u{1f800}', '\u{1f80b}', Script::Common), ('\u{1f810}',
- '\u{1f847}', Script::Common), ('\u{1f850}', '\u{1f859}', Script::Common), ('\u{1f860}',
- '\u{1f887}', Script::Common), ('\u{1f890}', '\u{1f8ad}', Script::Common), ('\u{1f8b0}',
- '\u{1f8b1}', Script::Common), ('\u{1f900}', '\u{1f978}', Script::Common), ('\u{1f97a}',
- '\u{1f9cb}', Script::Common), ('\u{1f9cd}', '\u{1fa53}', Script::Common), ('\u{1fa60}',
- '\u{1fa6d}', Script::Common), ('\u{1fa70}', '\u{1fa74}', Script::Common), ('\u{1fa78}',
- '\u{1fa7a}', Script::Common), ('\u{1fa80}', '\u{1fa86}', Script::Common), ('\u{1fa90}',
- '\u{1faa8}', Script::Common), ('\u{1fab0}', '\u{1fab6}', Script::Common), ('\u{1fac0}',
- '\u{1fac2}', Script::Common), ('\u{1fad0}', '\u{1fad6}', Script::Common), ('\u{1fb00}',
- '\u{1fb92}', Script::Common), ('\u{1fb94}', '\u{1fbca}', Script::Common), ('\u{1fbf0}',
- '\u{1fbf9}', Script::Common), ('\u{20000}', '\u{2a6dd}', Script::Han), ('\u{2a700}',
- '\u{2b734}', Script::Han), ('\u{2b740}', '\u{2b81d}', Script::Han), ('\u{2b820}',
- '\u{2cea1}', Script::Han), ('\u{2ceb0}', '\u{2ebe0}', Script::Han), ('\u{2f800}',
- '\u{2fa1d}', Script::Han), ('\u{30000}', '\u{3134a}', Script::Han), ('\u{e0001}',
- '\u{e0001}', Script::Common), ('\u{e0020}', '\u{e007f}', Script::Common), ('\u{e0100}',
- '\u{e01ef}', Script::Inherited)
+ '\u{1e2ff}', Script::Wancho), ('\u{1e4d0}', '\u{1e4ea}', Script::Nag_Mundari),
+ ('\u{1e4eb}', '\u{1e4eb}', Script::Nag_Mundari), ('\u{1e4ec}', '\u{1e4ef}',
+ Script::Nag_Mundari), ('\u{1e4f0}', '\u{1e4f9}', Script::Nag_Mundari), ('\u{1e7e0}',
+ '\u{1e7e6}', Script::Ethiopic), ('\u{1e7e8}', '\u{1e7eb}', Script::Ethiopic),
+ ('\u{1e7ed}', '\u{1e7ee}', Script::Ethiopic), ('\u{1e7f0}', '\u{1e7fe}',
+ Script::Ethiopic), ('\u{1e800}', '\u{1e8c4}', Script::Mende_Kikakui), ('\u{1e8c7}',
+ '\u{1e8cf}', Script::Mende_Kikakui), ('\u{1e8d0}', '\u{1e8d6}', Script::Mende_Kikakui),
+ ('\u{1e900}', '\u{1e943}', Script::Adlam), ('\u{1e944}', '\u{1e94a}', Script::Adlam),
+ ('\u{1e94b}', '\u{1e94b}', Script::Adlam), ('\u{1e950}', '\u{1e959}', Script::Adlam),
+ ('\u{1e95e}', '\u{1e95f}', Script::Adlam), ('\u{1ec71}', '\u{1ecab}', Script::Common),
+ ('\u{1ecac}', '\u{1ecac}', Script::Common), ('\u{1ecad}', '\u{1ecaf}', Script::Common),
+ ('\u{1ecb0}', '\u{1ecb0}', Script::Common), ('\u{1ecb1}', '\u{1ecb4}', Script::Common),
+ ('\u{1ed01}', '\u{1ed2d}', Script::Common), ('\u{1ed2e}', '\u{1ed2e}', Script::Common),
+ ('\u{1ed2f}', '\u{1ed3d}', Script::Common), ('\u{1ee00}', '\u{1ee03}', Script::Arabic),
+ ('\u{1ee05}', '\u{1ee1f}', Script::Arabic), ('\u{1ee21}', '\u{1ee22}', Script::Arabic),
+ ('\u{1ee24}', '\u{1ee24}', Script::Arabic), ('\u{1ee27}', '\u{1ee27}', Script::Arabic),
+ ('\u{1ee29}', '\u{1ee32}', Script::Arabic), ('\u{1ee34}', '\u{1ee37}', Script::Arabic),
+ ('\u{1ee39}', '\u{1ee39}', Script::Arabic), ('\u{1ee3b}', '\u{1ee3b}', Script::Arabic),
+ ('\u{1ee42}', '\u{1ee42}', Script::Arabic), ('\u{1ee47}', '\u{1ee47}', Script::Arabic),
+ ('\u{1ee49}', '\u{1ee49}', Script::Arabic), ('\u{1ee4b}', '\u{1ee4b}', Script::Arabic),
+ ('\u{1ee4d}', '\u{1ee4f}', Script::Arabic), ('\u{1ee51}', '\u{1ee52}', Script::Arabic),
+ ('\u{1ee54}', '\u{1ee54}', Script::Arabic), ('\u{1ee57}', '\u{1ee57}', Script::Arabic),
+ ('\u{1ee59}', '\u{1ee59}', Script::Arabic), ('\u{1ee5b}', '\u{1ee5b}', Script::Arabic),
+ ('\u{1ee5d}', '\u{1ee5d}', Script::Arabic), ('\u{1ee5f}', '\u{1ee5f}', Script::Arabic),
+ ('\u{1ee61}', '\u{1ee62}', Script::Arabic), ('\u{1ee64}', '\u{1ee64}', Script::Arabic),
+ ('\u{1ee67}', '\u{1ee6a}', Script::Arabic), ('\u{1ee6c}', '\u{1ee72}', Script::Arabic),
+ ('\u{1ee74}', '\u{1ee77}', Script::Arabic), ('\u{1ee79}', '\u{1ee7c}', Script::Arabic),
+ ('\u{1ee7e}', '\u{1ee7e}', Script::Arabic), ('\u{1ee80}', '\u{1ee89}', Script::Arabic),
+ ('\u{1ee8b}', '\u{1ee9b}', Script::Arabic), ('\u{1eea1}', '\u{1eea3}', Script::Arabic),
+ ('\u{1eea5}', '\u{1eea9}', Script::Arabic), ('\u{1eeab}', '\u{1eebb}', Script::Arabic),
+ ('\u{1eef0}', '\u{1eef1}', Script::Arabic), ('\u{1f000}', '\u{1f02b}', Script::Common),
+ ('\u{1f030}', '\u{1f093}', Script::Common), ('\u{1f0a0}', '\u{1f0ae}', Script::Common),
+ ('\u{1f0b1}', '\u{1f0bf}', Script::Common), ('\u{1f0c1}', '\u{1f0cf}', Script::Common),
+ ('\u{1f0d1}', '\u{1f0f5}', Script::Common), ('\u{1f100}', '\u{1f10c}', Script::Common),
+ ('\u{1f10d}', '\u{1f1ad}', Script::Common), ('\u{1f1e6}', '\u{1f1ff}', Script::Common),
+ ('\u{1f200}', '\u{1f200}', Script::Hiragana), ('\u{1f201}', '\u{1f202}', Script::Common),
+ ('\u{1f210}', '\u{1f23b}', Script::Common), ('\u{1f240}', '\u{1f248}', Script::Common),
+ ('\u{1f250}', '\u{1f251}', Script::Common), ('\u{1f260}', '\u{1f265}', Script::Common),
+ ('\u{1f300}', '\u{1f3fa}', Script::Common), ('\u{1f3fb}', '\u{1f3ff}', Script::Common),
+ ('\u{1f400}', '\u{1f6d7}', Script::Common), ('\u{1f6dc}', '\u{1f6ec}', Script::Common),
+ ('\u{1f6f0}', '\u{1f6fc}', Script::Common), ('\u{1f700}', '\u{1f776}', Script::Common),
+ ('\u{1f77b}', '\u{1f7d9}', Script::Common), ('\u{1f7e0}', '\u{1f7eb}', Script::Common),
+ ('\u{1f7f0}', '\u{1f7f0}', Script::Common), ('\u{1f800}', '\u{1f80b}', Script::Common),
+ ('\u{1f810}', '\u{1f847}', Script::Common), ('\u{1f850}', '\u{1f859}', Script::Common),
+ ('\u{1f860}', '\u{1f887}', Script::Common), ('\u{1f890}', '\u{1f8ad}', Script::Common),
+ ('\u{1f8b0}', '\u{1f8b1}', Script::Common), ('\u{1f900}', '\u{1fa53}', Script::Common),
+ ('\u{1fa60}', '\u{1fa6d}', Script::Common), ('\u{1fa70}', '\u{1fa7c}', Script::Common),
+ ('\u{1fa80}', '\u{1fa88}', Script::Common), ('\u{1fa90}', '\u{1fabd}', Script::Common),
+ ('\u{1fabf}', '\u{1fac5}', Script::Common), ('\u{1face}', '\u{1fadb}', Script::Common),
+ ('\u{1fae0}', '\u{1fae8}', Script::Common), ('\u{1faf0}', '\u{1faf8}', Script::Common),
+ ('\u{1fb00}', '\u{1fb92}', Script::Common), ('\u{1fb94}', '\u{1fbca}', Script::Common),
+ ('\u{1fbf0}', '\u{1fbf9}', Script::Common), ('\u{20000}', '\u{2a6df}', Script::Han),
+ ('\u{2a700}', '\u{2b739}', Script::Han), ('\u{2b740}', '\u{2b81d}', Script::Han),
+ ('\u{2b820}', '\u{2cea1}', Script::Han), ('\u{2ceb0}', '\u{2ebe0}', Script::Han),
+ ('\u{2f800}', '\u{2fa1d}', Script::Han), ('\u{30000}', '\u{3134a}', Script::Han),
+ ('\u{31350}', '\u{323af}', Script::Han), ('\u{e0001}', '\u{e0001}', Script::Common),
+ ('\u{e0020}', '\u{e007f}', Script::Common), ('\u{e0100}', '\u{e01ef}', Script::Inherited)
];
const SCRIPT_EXTENSIONS: &'static [(char, char, ScriptExtension)] = &[
@@ -2986,11 +3120,11 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
'\u{483}', script_extensions::CYRL_PERM), ('\u{484}', '\u{484}',
script_extensions::CYRL_GLAG), ('\u{485}', '\u{486}', script_extensions::CYRL_LATN),
('\u{487}', '\u{487}', script_extensions::CYRL_GLAG), ('\u{60c}', '\u{60c}',
- script_extensions::ARAB_ROHG_SYRC_THAA_YEZI), ('\u{61b}', '\u{61b}',
- script_extensions::ARAB_ROHG_SYRC_THAA_YEZI), ('\u{61c}', '\u{61c}',
+ script_extensions::ARAB_NKOO_ROHG_SYRC_THAA_YEZI), ('\u{61b}', '\u{61b}',
+ script_extensions::ARAB_NKOO_ROHG_SYRC_THAA_YEZI), ('\u{61c}', '\u{61c}',
script_extensions::ARAB_SYRC_THAA), ('\u{61f}', '\u{61f}',
- script_extensions::ARAB_ROHG_SYRC_THAA_YEZI), ('\u{640}', '\u{640}',
- script_extensions::ADLM_ARAB_MAND_MANI_PHLP_ROHG_SOGD_SYRC), ('\u{64b}', '\u{655}',
+ script_extensions::ADLM_ARAB_NKOO_ROHG_SYRC_THAA_YEZI), ('\u{640}', '\u{640}',
+ script_extensions::ADLM_ARAB_MAND_MANI_OUGR_PHLP_ROHG_SOGD_SYRC), ('\u{64b}', '\u{655}',
script_extensions::ARAB_SYRC), ('\u{660}', '\u{669}', script_extensions::ARAB_THAA_YEZI),
('\u{670}', '\u{670}', script_extensions::ARAB_SYRC), ('\u{6d4}', '\u{6d4}',
script_extensions::ARAB_ROHG), ('\u{951}', '\u{951}',
@@ -3031,10 +3165,11 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
script_extensions::BENG), ('\u{1cf8}', '\u{1cf9}', script_extensions::DEVA_GRAN),
('\u{1cfa}', '\u{1cfa}', script_extensions::NAND), ('\u{1dc0}', '\u{1dc1}',
script_extensions::GREK), ('\u{1df8}', '\u{1df8}', script_extensions::CYRL_SYRC),
- ('\u{202f}', '\u{202f}', script_extensions::LATN_MONG), ('\u{20f0}', '\u{20f0}',
- script_extensions::DEVA_GRAN_LATN), ('\u{2e43}', '\u{2e43}', script_extensions::CYRL_GLAG),
- ('\u{3001}', '\u{3002}', script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{3003}',
- '\u{3003}', script_extensions::BOPO_HANG_HANI_HIRA_KANA), ('\u{3006}', '\u{3006}',
+ ('\u{1dfa}', '\u{1dfa}', script_extensions::SYRC), ('\u{202f}', '\u{202f}',
+ script_extensions::LATN_MONG), ('\u{20f0}', '\u{20f0}', script_extensions::DEVA_GRAN_LATN),
+ ('\u{2e43}', '\u{2e43}', script_extensions::CYRL_GLAG), ('\u{3001}', '\u{3002}',
+ script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{3003}', '\u{3003}',
+ script_extensions::BOPO_HANG_HANI_HIRA_KANA), ('\u{3006}', '\u{3006}',
script_extensions::HANI), ('\u{3008}', '\u{3008}',
script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{3009}', '\u{3009}',
script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{300a}', '\u{300a}',
@@ -3088,23 +3223,27 @@ pub fn get_script_extension(c: char) -> Option<ScriptExtension> {
script_extensions::DEVA_DOGR_GUJR_GURU_KHOJ_KTHI_MAHJ_MODI_SIND_TAKR_TIRH), ('\u{a8f1}',
'\u{a8f1}', script_extensions::BENG_DEVA), ('\u{a8f3}', '\u{a8f3}',
script_extensions::DEVA_TAML), ('\u{a92e}', '\u{a92e}', script_extensions::KALI_LATN_MYMR),
- ('\u{a9cf}', '\u{a9cf}', script_extensions::BUGI_JAVA), ('\u{fdf2}', '\u{fdf2}',
- script_extensions::ARAB_THAA), ('\u{fdfd}', '\u{fdfd}', script_extensions::ARAB_THAA),
- ('\u{fe45}', '\u{fe46}', script_extensions::BOPO_HANG_HANI_HIRA_KANA), ('\u{ff61}',
- '\u{ff61}', script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{ff62}', '\u{ff62}',
+ ('\u{a9cf}', '\u{a9cf}', script_extensions::BUGI_JAVA), ('\u{fd3e}', '\u{fd3e}',
+ script_extensions::ARAB_NKOO), ('\u{fd3f}', '\u{fd3f}', script_extensions::ARAB_NKOO),
+ ('\u{fdf2}', '\u{fdf2}', script_extensions::ARAB_THAA), ('\u{fdfd}', '\u{fdfd}',
+ script_extensions::ARAB_THAA), ('\u{fe45}', '\u{fe46}',
+ script_extensions::BOPO_HANG_HANI_HIRA_KANA), ('\u{ff61}', '\u{ff61}',
+ script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{ff62}', '\u{ff62}',
script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{ff63}', '\u{ff63}',
script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{ff64}', '\u{ff65}',
script_extensions::BOPO_HANG_HANI_HIRA_KANA_YIII), ('\u{ff70}', '\u{ff70}',
script_extensions::HIRA_KANA), ('\u{ff9e}', '\u{ff9f}', script_extensions::HIRA_KANA),
- ('\u{10100}', '\u{10102}', script_extensions::CPRT_LINB), ('\u{10107}', '\u{10133}',
+ ('\u{10100}', '\u{10101}', script_extensions::CPMN_CPRT_LINB), ('\u{10102}', '\u{10102}',
+ script_extensions::CPRT_LINB), ('\u{10107}', '\u{10133}',
script_extensions::CPRT_LINA_LINB), ('\u{10137}', '\u{1013f}',
script_extensions::CPRT_LINB), ('\u{102e0}', '\u{102e0}', script_extensions::ARAB_COPT),
- ('\u{102e1}', '\u{102fb}', script_extensions::ARAB_COPT), ('\u{11301}', '\u{11301}',
- script_extensions::GRAN_TAML), ('\u{11303}', '\u{11303}', script_extensions::GRAN_TAML),
- ('\u{1133b}', '\u{1133c}', script_extensions::GRAN_TAML), ('\u{11fd0}', '\u{11fd1}',
- script_extensions::GRAN_TAML), ('\u{11fd3}', '\u{11fd3}', script_extensions::GRAN_TAML),
- ('\u{1bca0}', '\u{1bca3}', script_extensions::DUPL), ('\u{1d360}', '\u{1d371}',
- script_extensions::HANI), ('\u{1f250}', '\u{1f251}', script_extensions::HANI)
+ ('\u{102e1}', '\u{102fb}', script_extensions::ARAB_COPT), ('\u{10af2}', '\u{10af2}',
+ script_extensions::MANI_OUGR), ('\u{11301}', '\u{11301}', script_extensions::GRAN_TAML),
+ ('\u{11303}', '\u{11303}', script_extensions::GRAN_TAML), ('\u{1133b}', '\u{1133c}',
+ script_extensions::GRAN_TAML), ('\u{11fd0}', '\u{11fd1}', script_extensions::GRAN_TAML),
+ ('\u{11fd3}', '\u{11fd3}', script_extensions::GRAN_TAML), ('\u{1bca0}', '\u{1bca3}',
+ script_extensions::DUPL), ('\u{1d360}', '\u{1d371}', script_extensions::HANI), ('\u{1f250}',
+ '\u{1f251}', script_extensions::HANI)
];
diff --git a/vendor/unicode-security/.cargo-checksum.json b/vendor/unicode-security/.cargo-checksum.json
index a0a3c205d..286456775 100644
--- a/vendor/unicode-security/.cargo-checksum.json
+++ b/vendor/unicode-security/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"651b0fa8d5cbbdd756f4c54cf8f2c7ac0e2c443e3402684612babb2d0e745b5a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"cf597d1e3c462dcac6a525aab647e7b6557e03b1d6a7623ddb571cbfffc089ab","scripts/unicode.py":"44c9110535ff74c16f73276d6b15b42c8b9c5b980ca685f07d32edb068abd5ca","src/confusable_detection.rs":"c837f2ed06e9df60a7111e25471b46e5f61d86858215f548ddd43973fd2a64c4","src/general_security_profile.rs":"e7e979876f9414cec50a58301f635bb4216089f2cb2cab83487fcafb0e13c0ac","src/lib.rs":"4d0fe431eab6b50fd7293b59773f71e07f2fd4232b09d79e040bcf33a824d335","src/mixed_script.rs":"b95a3d5316c0aa6144c6ded12bb6c479df2d513e43157fb29e8dc9a3674d0d93","src/restriction_level.rs":"0e35d97c6b5ac3cf40440e80677caf6724fae7beb5d0f0bf438614a76ab920b0","src/tables.rs":"1d7886386d82b42000f9d55ba2286949da190795e75949f23640e1b25ba4a0fe","src/tests.rs":"a9d4bc171dec6dc6a440c871fa49eb14ece9ef0c248b6742f1233ea5a1d393a0"},"package":"5d87c28edc5b263377e448d6cdcb935c06b95413d8013ba6fae470558ccab18f"} \ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"b719757f69f5e8a66d65f28780173e2a7d12d30ab2d4c636eeeef7cff6dc2256","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"9266090c1c7f321793aa0775763b499eb2f7aa819eb8c8d9a607503cb9487c8e","scripts/unicode.py":"25db65759b92a2f60ca2d4a6ec401a136895eca71732d903023a80c4b6cd5a7f","src/confusable_detection.rs":"c837f2ed06e9df60a7111e25471b46e5f61d86858215f548ddd43973fd2a64c4","src/general_security_profile.rs":"e7e979876f9414cec50a58301f635bb4216089f2cb2cab83487fcafb0e13c0ac","src/lib.rs":"4d0fe431eab6b50fd7293b59773f71e07f2fd4232b09d79e040bcf33a824d335","src/mixed_script.rs":"b95a3d5316c0aa6144c6ded12bb6c479df2d513e43157fb29e8dc9a3674d0d93","src/restriction_level.rs":"1f9831385cb20fda09d608390dc56a1866929104e7d694d4a5a486c60380a002","src/tables.rs":"5459b739f3a4b60bfa1ed4704a9d3a185a8808185842bd3cd8dff1ad2f9f7a70","src/tests.rs":"a9d4bc171dec6dc6a440c871fa49eb14ece9ef0c248b6742f1233ea5a1d393a0"},"package":"9ef5756b3097992b934b06608c69f48448a0fbe804bb1e72b982f6d7983e9e63"} \ No newline at end of file
diff --git a/vendor/unicode-security/Cargo.toml b/vendor/unicode-security/Cargo.toml
index cb2022812..090882aba 100644
--- a/vendor/unicode-security/Cargo.toml
+++ b/vendor/unicode-security/Cargo.toml
@@ -3,26 +3,39 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
name = "unicode-security"
-version = "0.0.5"
-authors = ["Charles Lew <crlf0710@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
-exclude = ["target/*", "Cargo.lock"]
-description = "Detect possible security problems with Unicode usage\naccording to Unicode Technical Standard #39 rules.\n"
+version = "0.1.0"
+authors = [
+ "Charles Lew <crlf0710@gmail.com>",
+ "Manish Goregaokar <manishsmail@gmail.com>",
+]
+exclude = [
+ "target/*",
+ "Cargo.lock",
+]
+description = """
+Detect possible security problems with Unicode usage
+according to Unicode Technical Standard #39 rules.
+"""
homepage = "https://github.com/unicode-rs/unicode-security"
documentation = "https://docs.rs/unicode-security"
readme = "README.md"
-keywords = ["text", "security", "unicode"]
+keywords = [
+ "text",
+ "security",
+ "unicode",
+]
license = "MIT/Apache-2.0"
repository = "https://github.com/unicode-rs/unicode-security"
+
[dependencies.compiler_builtins]
version = "0.1"
optional = true
@@ -48,4 +61,8 @@ default-features = false
[features]
bench = []
default = []
-rustc-dep-of-std = ["std", "core", "compiler_builtins"]
+rustc-dep-of-std = [
+ "std",
+ "core",
+ "compiler_builtins",
+]
diff --git a/vendor/unicode-security/README.md b/vendor/unicode-security/README.md
index 22e8b6d35..bda8739d6 100644
--- a/vendor/unicode-security/README.md
+++ b/vendor/unicode-security/README.md
@@ -1,7 +1,7 @@
# unicode-security
[![Build Status](https://github.com/unicode-rs/unicode-security/workflows/Tests/badge.svg)](https://github.com/unicode-rs/unicode-security/actions)
-[![Current Version](https://meritbadge.herokuapp.com/unicode-security)](https://crates.io/crates/unicode-security)
+[![Current Version](https://img.shields.io/crates/v/unicode-security.svg)](https://crates.io/crates/unicode-security)
[![License: MIT/Apache-2.0](https://img.shields.io/crates/l/unicode-security.svg)](#license)
-This crate exposes various utilities from [UAX #39 Unicode Security Mechanisms](https://www.unicode.org/reports/tr39/) \ No newline at end of file
+This crate exposes various utilities from [UAX #39 Unicode Security Mechanisms](https://www.unicode.org/reports/tr39/)
diff --git a/vendor/unicode-security/scripts/unicode.py b/vendor/unicode-security/scripts/unicode.py
index 368b94c89..11ea31e53 100644
--- a/vendor/unicode-security/scripts/unicode.py
+++ b/vendor/unicode-security/scripts/unicode.py
@@ -39,14 +39,14 @@ preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRI
#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
'''
-UNICODE_VERSION = (13, 0, 0)
+UNICODE_VERSION = (15, 0, 0)
UNICODE_VERSION_NUMBER = "%s.%s.%s" %UNICODE_VERSION
# Download a Unicode security table file
def fetch(f):
if not os.path.exists(os.path.basename(f)):
- os.system("curl -O http://www.unicode.org/Public/security/%s/%s"
+ os.system("curl -O https://www.unicode.org/Public/security/%s/%s"
% (UNICODE_VERSION_NUMBER, f))
if not os.path.exists(os.path.basename(f)):
@@ -56,7 +56,7 @@ def fetch(f):
# Download a UCD table file
def fetch_unidata(f):
if not os.path.exists(os.path.basename(f)):
- os.system("curl -O http://www.unicode.org/Public/%s/ucd/%s"
+ os.system("curl -O https://www.unicode.org/Public/%s/ucd/%s"
% (UNICODE_VERSION_NUMBER, f))
if not os.path.exists(os.path.basename(f)):
diff --git a/vendor/unicode-security/src/restriction_level.rs b/vendor/unicode-security/src/restriction_level.rs
index adaf07460..b2feedbad 100644
--- a/vendor/unicode-security/src/restriction_level.rs
+++ b/vendor/unicode-security/src/restriction_level.rs
@@ -48,7 +48,7 @@ impl RestrictionLevelDetection for &'_ str {
if !GeneralSecurityProfile::identifier_allowed(ch) {
return RestrictionLevel::Unrestricted;
}
- if ch.is_ascii() {
+ if !ch.is_ascii() {
ascii_only = false;
}
let ch_set = ch.into();
diff --git a/vendor/unicode-security/src/tables.rs b/vendor/unicode-security/src/tables.rs
index 5e4bc1e03..6b72dbb0a 100644
--- a/vendor/unicode-security/src/tables.rs
+++ b/vendor/unicode-security/src/tables.rs
@@ -14,7 +14,7 @@
/// The version of [Unicode](http://www.unicode.org/)
/// that this version of unicode-security is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (13, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0);
pub mod util {
@@ -133,127 +133,135 @@ pub mod identifier {
'\u{6ce}'), ('\u{6cf}', '\u{6cf}'), ('\u{6d0}', '\u{6d3}'), ('\u{6d5}', '\u{6d5}'),
('\u{6e5}', '\u{6e6}'), ('\u{6ee}', '\u{6ef}'), ('\u{6f0}', '\u{6f9}'), ('\u{6fa}',
'\u{6fe}'), ('\u{6ff}', '\u{6ff}'), ('\u{750}', '\u{76d}'), ('\u{76e}', '\u{77f}'),
- ('\u{780}', '\u{7b0}'), ('\u{7b1}', '\u{7b1}'), ('\u{8a0}', '\u{8a0}'), ('\u{8a1}',
- '\u{8a1}'), ('\u{8a2}', '\u{8ac}'), ('\u{8b2}', '\u{8b2}'), ('\u{8b6}', '\u{8bd}'),
- ('\u{8be}', '\u{8c7}'), ('\u{901}', '\u{903}'), ('\u{904}', '\u{904}'), ('\u{905}',
- '\u{939}'), ('\u{93a}', '\u{93b}'), ('\u{93c}', '\u{94d}'), ('\u{94f}', '\u{94f}'),
- ('\u{950}', '\u{950}'), ('\u{956}', '\u{957}'), ('\u{960}', '\u{963}'), ('\u{966}',
- '\u{96f}'), ('\u{971}', '\u{972}'), ('\u{973}', '\u{977}'), ('\u{979}', '\u{97a}'),
- ('\u{97b}', '\u{97c}'), ('\u{97d}', '\u{97d}'), ('\u{97e}', '\u{97f}'), ('\u{981}',
- '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}', '\u{9a8}'),
- ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'), ('\u{9bc}',
- '\u{9bc}'), ('\u{9bd}', '\u{9bd}'), ('\u{9be}', '\u{9c4}'), ('\u{9c7}', '\u{9c8}'),
- ('\u{9cb}', '\u{9cd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'), ('\u{9e0}',
- '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{9fe}', '\u{9fe}'), ('\u{a01}', '\u{a01}'),
- ('\u{a02}', '\u{a02}'), ('\u{a03}', '\u{a03}'), ('\u{a05}', '\u{a0a}'), ('\u{a0f}',
- '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}', '\u{a32}'),
- ('\u{a35}', '\u{a35}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'), ('\u{a3e}',
- '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a5c}', '\u{a5c}'),
- ('\u{a66}', '\u{a74}'), ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8b}'), ('\u{a8c}',
- '\u{a8c}'), ('\u{a8d}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}', '\u{aa8}'),
- ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'), ('\u{abc}',
- '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}', '\u{ad0}'),
- ('\u{ae0}', '\u{ae0}'), ('\u{ae1}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'), ('\u{afa}',
- '\u{aff}'), ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}', '\u{b10}'),
- ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'), ('\u{b35}',
- '\u{b35}'), ('\u{b36}', '\u{b39}'), ('\u{b3c}', '\u{b43}'), ('\u{b47}', '\u{b48}'),
- ('\u{b4b}', '\u{b4d}'), ('\u{b55}', '\u{b55}'), ('\u{b56}', '\u{b57}'), ('\u{b5f}',
- '\u{b61}'), ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'), ('\u{b82}', '\u{b83}'),
- ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'), ('\u{b99}',
- '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'),
- ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb5}'), ('\u{bb6}', '\u{bb6}'), ('\u{bb7}',
- '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}', '\u{bcd}'),
- ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{be6}'), ('\u{be7}',
- '\u{bef}'), ('\u{c01}', '\u{c03}'), ('\u{c04}', '\u{c04}'), ('\u{c05}', '\u{c0c}'),
- ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c33}'), ('\u{c35}',
- '\u{c39}'), ('\u{c3d}', '\u{c3d}'), ('\u{c3e}', '\u{c44}'), ('\u{c46}', '\u{c48}'),
- ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'), ('\u{c60}', '\u{c61}'), ('\u{c66}',
- '\u{c6f}'), ('\u{c80}', '\u{c80}'), ('\u{c82}', '\u{c83}'), ('\u{c85}', '\u{c8c}'),
- ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}',
- '\u{cb9}'), ('\u{cbc}', '\u{cbd}'), ('\u{cbe}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'),
- ('\u{cca}', '\u{ccd}'), ('\u{cd5}', '\u{cd6}'), ('\u{ce0}', '\u{ce1}'), ('\u{ce2}',
- '\u{ce3}'), ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'), ('\u{d00}', '\u{d00}'),
- ('\u{d02}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}',
- '\u{d28}'), ('\u{d29}', '\u{d29}'), ('\u{d2a}', '\u{d39}'), ('\u{d3a}', '\u{d3a}'),
- ('\u{d3d}', '\u{d3d}'), ('\u{d3e}', '\u{d43}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}',
- '\u{d4d}'), ('\u{d4e}', '\u{d4e}'), ('\u{d54}', '\u{d56}'), ('\u{d57}', '\u{d57}'),
- ('\u{d60}', '\u{d61}'), ('\u{d66}', '\u{d6f}'), ('\u{d7a}', '\u{d7f}'), ('\u{d82}',
- '\u{d83}'), ('\u{d85}', '\u{d8e}'), ('\u{d91}', '\u{d96}'), ('\u{d9a}', '\u{da5}'),
- ('\u{da7}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}',
- '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
- ('\u{dd8}', '\u{dde}'), ('\u{df2}', '\u{df2}'), ('\u{e01}', '\u{e32}'), ('\u{e34}',
- '\u{e3a}'), ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'), ('\u{e81}', '\u{e82}'),
- ('\u{e84}', '\u{e84}'), ('\u{e86}', '\u{e86}'), ('\u{e87}', '\u{e88}'), ('\u{e89}',
- '\u{e89}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8c}', '\u{e8c}'), ('\u{e8d}', '\u{e8d}'),
- ('\u{e8e}', '\u{e93}'), ('\u{e94}', '\u{e97}'), ('\u{e98}', '\u{e98}'), ('\u{e99}',
- '\u{e9f}'), ('\u{ea0}', '\u{ea0}'), ('\u{ea1}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'),
- ('\u{ea7}', '\u{ea7}'), ('\u{ea8}', '\u{ea9}'), ('\u{eaa}', '\u{eab}'), ('\u{eac}',
- '\u{eac}'), ('\u{ead}', '\u{eb2}'), ('\u{eb4}', '\u{eb9}'), ('\u{eba}', '\u{eba}'),
- ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'), ('\u{ec8}',
- '\u{ecd}'), ('\u{ed0}', '\u{ed9}'), ('\u{ede}', '\u{edf}'), ('\u{f00}', '\u{f00}'),
- ('\u{f0b}', '\u{f0b}'), ('\u{f20}', '\u{f29}'), ('\u{f35}', '\u{f35}'), ('\u{f37}',
- '\u{f37}'), ('\u{f3e}', '\u{f42}'), ('\u{f44}', '\u{f47}'), ('\u{f49}', '\u{f4c}'),
- ('\u{f4e}', '\u{f51}'), ('\u{f53}', '\u{f56}'), ('\u{f58}', '\u{f5b}'), ('\u{f5d}',
- '\u{f68}'), ('\u{f6a}', '\u{f6a}'), ('\u{f6b}', '\u{f6c}'), ('\u{f71}', '\u{f72}'),
- ('\u{f74}', '\u{f74}'), ('\u{f7a}', '\u{f80}'), ('\u{f82}', '\u{f84}'), ('\u{f86}',
- '\u{f8b}'), ('\u{f8c}', '\u{f8f}'), ('\u{f90}', '\u{f92}'), ('\u{f94}', '\u{f95}'),
- ('\u{f96}', '\u{f96}'), ('\u{f97}', '\u{f97}'), ('\u{f99}', '\u{f9c}'), ('\u{f9e}',
- '\u{fa1}'), ('\u{fa3}', '\u{fa6}'), ('\u{fa8}', '\u{fab}'), ('\u{fad}', '\u{fad}'),
- ('\u{fae}', '\u{fb0}'), ('\u{fb1}', '\u{fb7}'), ('\u{fb8}', '\u{fb8}'), ('\u{fba}',
- '\u{fbc}'), ('\u{fc6}', '\u{fc6}'), ('\u{1000}', '\u{1021}'), ('\u{1022}', '\u{1022}'),
- ('\u{1023}', '\u{1027}'), ('\u{1028}', '\u{1028}'), ('\u{1029}', '\u{102a}'), ('\u{102b}',
- '\u{102b}'), ('\u{102c}', '\u{1032}'), ('\u{1033}', '\u{1035}'), ('\u{1036}', '\u{1039}'),
- ('\u{103a}', '\u{103f}'), ('\u{1040}', '\u{1049}'), ('\u{1050}', '\u{1059}'), ('\u{105a}',
- '\u{1099}'), ('\u{109a}', '\u{109d}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'),
- ('\u{10d0}', '\u{10f0}'), ('\u{10f7}', '\u{10f8}'), ('\u{10f9}', '\u{10fa}'), ('\u{10fd}',
- '\u{10ff}'), ('\u{1200}', '\u{1206}'), ('\u{1207}', '\u{1207}'), ('\u{1208}', '\u{1246}'),
- ('\u{1247}', '\u{1247}'), ('\u{1248}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}',
- '\u{1256}'), ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1286}'),
- ('\u{1287}', '\u{1287}'), ('\u{1288}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
- '\u{12ae}'), ('\u{12af}', '\u{12af}'), ('\u{12b0}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'),
- ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}',
- '\u{12ce}'), ('\u{12cf}', '\u{12cf}'), ('\u{12d0}', '\u{12d6}'), ('\u{12d8}', '\u{12ee}'),
- ('\u{12ef}', '\u{12ef}'), ('\u{12f0}', '\u{130e}'), ('\u{130f}', '\u{130f}'), ('\u{1310}',
- '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{131e}'), ('\u{131f}', '\u{131f}'),
- ('\u{1320}', '\u{1346}'), ('\u{1347}', '\u{1347}'), ('\u{1348}', '\u{135a}'), ('\u{135d}',
- '\u{135e}'), ('\u{135f}', '\u{135f}'), ('\u{1380}', '\u{138f}'), ('\u{1780}', '\u{17a2}'),
- ('\u{17a5}', '\u{17a7}'), ('\u{17a9}', '\u{17b3}'), ('\u{17b6}', '\u{17ca}'), ('\u{17d2}',
- '\u{17d2}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), ('\u{17e0}', '\u{17e9}'),
- ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'), ('\u{1e00}', '\u{1e99}'), ('\u{1e9e}',
- '\u{1e9e}'), ('\u{1ea0}', '\u{1ef9}'), ('\u{1f00}', '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'),
- ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}',
- '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f70}'),
- ('\u{1f72}', '\u{1f72}'), ('\u{1f74}', '\u{1f74}'), ('\u{1f76}', '\u{1f76}'), ('\u{1f78}',
- '\u{1f78}'), ('\u{1f7a}', '\u{1f7a}'), ('\u{1f7c}', '\u{1f7c}'), ('\u{1f80}', '\u{1fb4}'),
- ('\u{1fb6}', '\u{1fba}'), ('\u{1fbc}', '\u{1fbc}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}',
- '\u{1fc8}'), ('\u{1fca}', '\u{1fca}'), ('\u{1fcc}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd2}'),
- ('\u{1fd6}', '\u{1fda}'), ('\u{1fe0}', '\u{1fe2}'), ('\u{1fe4}', '\u{1fea}'), ('\u{1fec}',
- '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ff8}'), ('\u{1ffa}', '\u{1ffa}'),
- ('\u{1ffc}', '\u{1ffc}'), ('\u{200c}', '\u{200d}'), ('\u{2010}', '\u{2010}'), ('\u{2019}',
- '\u{2019}'), ('\u{2027}', '\u{2027}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'),
- ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}',
- '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'),
- ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3041}',
- '\u{3094}'), ('\u{3095}', '\u{3096}'), ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309e}'),
- ('\u{30a0}', '\u{30a0}'), ('\u{30a1}', '\u{30fe}'), ('\u{3105}', '\u{312c}'), ('\u{312d}',
- '\u{312d}'), ('\u{312f}', '\u{312f}'), ('\u{31a0}', '\u{31b7}'), ('\u{31b8}', '\u{31ba}'),
- ('\u{31bb}', '\u{31bf}'), ('\u{3400}', '\u{4db5}'), ('\u{4db6}', '\u{4dbf}'), ('\u{4e00}',
- '\u{9fa5}'), ('\u{9fa6}', '\u{9fbb}'), ('\u{9fbc}', '\u{9fc3}'), ('\u{9fc4}', '\u{9fcb}'),
- ('\u{9fcc}', '\u{9fcc}'), ('\u{9fcd}', '\u{9fd5}'), ('\u{9fd6}', '\u{9fea}'), ('\u{9feb}',
- '\u{9fef}'), ('\u{9ff0}', '\u{9ffc}'), ('\u{a67f}', '\u{a67f}'), ('\u{a717}', '\u{a71a}'),
- ('\u{a71b}', '\u{a71f}'), ('\u{a788}', '\u{a788}'), ('\u{a78d}', '\u{a78d}'), ('\u{a792}',
- '\u{a793}'), ('\u{a7aa}', '\u{a7aa}'), ('\u{a7ae}', '\u{a7ae}'), ('\u{a7b8}', '\u{a7b9}'),
- ('\u{a7c2}', '\u{a7c6}'), ('\u{a7c7}', '\u{a7ca}'), ('\u{a9e7}', '\u{a9fe}'), ('\u{aa60}',
- '\u{aa76}'), ('\u{aa7a}', '\u{aa7b}'), ('\u{aa7c}', '\u{aa7f}'), ('\u{ab01}', '\u{ab06}'),
- ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}',
- '\u{ab2e}'), ('\u{ab66}', '\u{ab67}'), ('\u{ac00}', '\u{d7a3}'), ('\u{fa0e}', '\u{fa0f}'),
- ('\u{fa11}', '\u{fa11}'), ('\u{fa13}', '\u{fa14}'), ('\u{fa1f}', '\u{fa1f}'), ('\u{fa21}',
- '\u{fa21}'), ('\u{fa23}', '\u{fa24}'), ('\u{fa27}', '\u{fa29}'), ('\u{11301}', '\u{11301}'),
- ('\u{11303}', '\u{11303}'), ('\u{1133b}', '\u{1133b}'), ('\u{1133c}', '\u{1133c}'),
- ('\u{16ff0}', '\u{16ff1}'), ('\u{1b150}', '\u{1b152}'), ('\u{1b164}', '\u{1b167}'),
- ('\u{20000}', '\u{2a6d6}'), ('\u{2a6d7}', '\u{2a6dd}'), ('\u{2a700}', '\u{2b734}'),
- ('\u{2b740}', '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2ceb0}', '\u{2ebe0}'),
- ('\u{30000}', '\u{3134a}')
+ ('\u{780}', '\u{7b0}'), ('\u{7b1}', '\u{7b1}'), ('\u{870}', '\u{887}'), ('\u{889}',
+ '\u{88e}'), ('\u{8a0}', '\u{8a0}'), ('\u{8a1}', '\u{8a1}'), ('\u{8a2}', '\u{8ac}'),
+ ('\u{8b2}', '\u{8b2}'), ('\u{8b5}', '\u{8b5}'), ('\u{8b6}', '\u{8bd}'), ('\u{8be}',
+ '\u{8c7}'), ('\u{8c8}', '\u{8c9}'), ('\u{901}', '\u{903}'), ('\u{904}', '\u{904}'),
+ ('\u{905}', '\u{939}'), ('\u{93a}', '\u{93b}'), ('\u{93c}', '\u{94d}'), ('\u{94f}',
+ '\u{94f}'), ('\u{950}', '\u{950}'), ('\u{956}', '\u{957}'), ('\u{960}', '\u{963}'),
+ ('\u{966}', '\u{96f}'), ('\u{971}', '\u{972}'), ('\u{973}', '\u{977}'), ('\u{979}',
+ '\u{97a}'), ('\u{97b}', '\u{97c}'), ('\u{97d}', '\u{97d}'), ('\u{97e}', '\u{97f}'),
+ ('\u{981}', '\u{983}'), ('\u{985}', '\u{98c}'), ('\u{98f}', '\u{990}'), ('\u{993}',
+ '\u{9a8}'), ('\u{9aa}', '\u{9b0}'), ('\u{9b2}', '\u{9b2}'), ('\u{9b6}', '\u{9b9}'),
+ ('\u{9bc}', '\u{9bc}'), ('\u{9bd}', '\u{9bd}'), ('\u{9be}', '\u{9c4}'), ('\u{9c7}',
+ '\u{9c8}'), ('\u{9cb}', '\u{9cd}'), ('\u{9ce}', '\u{9ce}'), ('\u{9d7}', '\u{9d7}'),
+ ('\u{9e0}', '\u{9e3}'), ('\u{9e6}', '\u{9f1}'), ('\u{9fe}', '\u{9fe}'), ('\u{a01}',
+ '\u{a01}'), ('\u{a02}', '\u{a02}'), ('\u{a03}', '\u{a03}'), ('\u{a05}', '\u{a0a}'),
+ ('\u{a0f}', '\u{a10}'), ('\u{a13}', '\u{a28}'), ('\u{a2a}', '\u{a30}'), ('\u{a32}',
+ '\u{a32}'), ('\u{a35}', '\u{a35}'), ('\u{a38}', '\u{a39}'), ('\u{a3c}', '\u{a3c}'),
+ ('\u{a3e}', '\u{a42}'), ('\u{a47}', '\u{a48}'), ('\u{a4b}', '\u{a4d}'), ('\u{a5c}',
+ '\u{a5c}'), ('\u{a66}', '\u{a74}'), ('\u{a81}', '\u{a83}'), ('\u{a85}', '\u{a8b}'),
+ ('\u{a8c}', '\u{a8c}'), ('\u{a8d}', '\u{a8d}'), ('\u{a8f}', '\u{a91}'), ('\u{a93}',
+ '\u{aa8}'), ('\u{aaa}', '\u{ab0}'), ('\u{ab2}', '\u{ab3}'), ('\u{ab5}', '\u{ab9}'),
+ ('\u{abc}', '\u{ac5}'), ('\u{ac7}', '\u{ac9}'), ('\u{acb}', '\u{acd}'), ('\u{ad0}',
+ '\u{ad0}'), ('\u{ae0}', '\u{ae0}'), ('\u{ae1}', '\u{ae3}'), ('\u{ae6}', '\u{aef}'),
+ ('\u{afa}', '\u{aff}'), ('\u{b01}', '\u{b03}'), ('\u{b05}', '\u{b0c}'), ('\u{b0f}',
+ '\u{b10}'), ('\u{b13}', '\u{b28}'), ('\u{b2a}', '\u{b30}'), ('\u{b32}', '\u{b33}'),
+ ('\u{b35}', '\u{b35}'), ('\u{b36}', '\u{b39}'), ('\u{b3c}', '\u{b43}'), ('\u{b47}',
+ '\u{b48}'), ('\u{b4b}', '\u{b4d}'), ('\u{b55}', '\u{b55}'), ('\u{b56}', '\u{b57}'),
+ ('\u{b5f}', '\u{b61}'), ('\u{b66}', '\u{b6f}'), ('\u{b71}', '\u{b71}'), ('\u{b82}',
+ '\u{b83}'), ('\u{b85}', '\u{b8a}'), ('\u{b8e}', '\u{b90}'), ('\u{b92}', '\u{b95}'),
+ ('\u{b99}', '\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}',
+ '\u{ba4}'), ('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb5}'), ('\u{bb6}', '\u{bb6}'),
+ ('\u{bb7}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}', '\u{bc8}'), ('\u{bca}',
+ '\u{bcd}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'), ('\u{be6}', '\u{be6}'),
+ ('\u{be7}', '\u{bef}'), ('\u{c01}', '\u{c03}'), ('\u{c04}', '\u{c04}'), ('\u{c05}',
+ '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}', '\u{c33}'),
+ ('\u{c35}', '\u{c39}'), ('\u{c3c}', '\u{c3c}'), ('\u{c3d}', '\u{c3d}'), ('\u{c3e}',
+ '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4d}'), ('\u{c55}', '\u{c56}'),
+ ('\u{c5d}', '\u{c5d}'), ('\u{c60}', '\u{c61}'), ('\u{c66}', '\u{c6f}'), ('\u{c80}',
+ '\u{c80}'), ('\u{c82}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
+ ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbc}',
+ '\u{cbd}'), ('\u{cbe}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccd}'),
+ ('\u{cd5}', '\u{cd6}'), ('\u{cdd}', '\u{cdd}'), ('\u{ce0}', '\u{ce1}'), ('\u{ce2}',
+ '\u{ce3}'), ('\u{ce6}', '\u{cef}'), ('\u{cf1}', '\u{cf2}'), ('\u{cf3}', '\u{cf3}'),
+ ('\u{d00}', '\u{d00}'), ('\u{d02}', '\u{d03}'), ('\u{d05}', '\u{d0c}'), ('\u{d0e}',
+ '\u{d10}'), ('\u{d12}', '\u{d28}'), ('\u{d29}', '\u{d29}'), ('\u{d2a}', '\u{d39}'),
+ ('\u{d3a}', '\u{d3a}'), ('\u{d3d}', '\u{d3d}'), ('\u{d3e}', '\u{d43}'), ('\u{d46}',
+ '\u{d48}'), ('\u{d4a}', '\u{d4d}'), ('\u{d4e}', '\u{d4e}'), ('\u{d54}', '\u{d56}'),
+ ('\u{d57}', '\u{d57}'), ('\u{d60}', '\u{d61}'), ('\u{d66}', '\u{d6f}'), ('\u{d7a}',
+ '\u{d7f}'), ('\u{d82}', '\u{d83}'), ('\u{d85}', '\u{d8e}'), ('\u{d91}', '\u{d96}'),
+ ('\u{d9a}', '\u{da5}'), ('\u{da7}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}',
+ '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dca}', '\u{dca}'), ('\u{dcf}', '\u{dd4}'),
+ ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{dde}'), ('\u{df2}', '\u{df2}'), ('\u{e01}',
+ '\u{e32}'), ('\u{e34}', '\u{e3a}'), ('\u{e40}', '\u{e4e}'), ('\u{e50}', '\u{e59}'),
+ ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'), ('\u{e86}', '\u{e86}'), ('\u{e87}',
+ '\u{e88}'), ('\u{e89}', '\u{e89}'), ('\u{e8a}', '\u{e8a}'), ('\u{e8c}', '\u{e8c}'),
+ ('\u{e8d}', '\u{e8d}'), ('\u{e8e}', '\u{e93}'), ('\u{e94}', '\u{e97}'), ('\u{e98}',
+ '\u{e98}'), ('\u{e99}', '\u{e9f}'), ('\u{ea0}', '\u{ea0}'), ('\u{ea1}', '\u{ea3}'),
+ ('\u{ea5}', '\u{ea5}'), ('\u{ea7}', '\u{ea7}'), ('\u{ea8}', '\u{ea9}'), ('\u{eaa}',
+ '\u{eab}'), ('\u{eac}', '\u{eac}'), ('\u{ead}', '\u{eb2}'), ('\u{eb4}', '\u{eb9}'),
+ ('\u{eba}', '\u{eba}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}',
+ '\u{ec6}'), ('\u{ec8}', '\u{ecd}'), ('\u{ece}', '\u{ece}'), ('\u{ed0}', '\u{ed9}'),
+ ('\u{ede}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f0b}', '\u{f0b}'), ('\u{f20}',
+ '\u{f29}'), ('\u{f35}', '\u{f35}'), ('\u{f37}', '\u{f37}'), ('\u{f3e}', '\u{f42}'),
+ ('\u{f44}', '\u{f47}'), ('\u{f49}', '\u{f4c}'), ('\u{f4e}', '\u{f51}'), ('\u{f53}',
+ '\u{f56}'), ('\u{f58}', '\u{f5b}'), ('\u{f5d}', '\u{f68}'), ('\u{f6a}', '\u{f6a}'),
+ ('\u{f6b}', '\u{f6c}'), ('\u{f71}', '\u{f72}'), ('\u{f74}', '\u{f74}'), ('\u{f7a}',
+ '\u{f80}'), ('\u{f82}', '\u{f84}'), ('\u{f86}', '\u{f8b}'), ('\u{f8c}', '\u{f8f}'),
+ ('\u{f90}', '\u{f92}'), ('\u{f94}', '\u{f95}'), ('\u{f96}', '\u{f96}'), ('\u{f97}',
+ '\u{f97}'), ('\u{f99}', '\u{f9c}'), ('\u{f9e}', '\u{fa1}'), ('\u{fa3}', '\u{fa6}'),
+ ('\u{fa8}', '\u{fab}'), ('\u{fad}', '\u{fad}'), ('\u{fae}', '\u{fb0}'), ('\u{fb1}',
+ '\u{fb7}'), ('\u{fb8}', '\u{fb8}'), ('\u{fba}', '\u{fbc}'), ('\u{fc6}', '\u{fc6}'),
+ ('\u{1000}', '\u{1021}'), ('\u{1022}', '\u{1022}'), ('\u{1023}', '\u{1027}'), ('\u{1028}',
+ '\u{1028}'), ('\u{1029}', '\u{102a}'), ('\u{102b}', '\u{102b}'), ('\u{102c}', '\u{1032}'),
+ ('\u{1033}', '\u{1035}'), ('\u{1036}', '\u{1039}'), ('\u{103a}', '\u{103f}'), ('\u{1040}',
+ '\u{1049}'), ('\u{1050}', '\u{1059}'), ('\u{105a}', '\u{1099}'), ('\u{109a}', '\u{109d}'),
+ ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10f0}'), ('\u{10f7}',
+ '\u{10f8}'), ('\u{10f9}', '\u{10fa}'), ('\u{10fd}', '\u{10ff}'), ('\u{1200}', '\u{1206}'),
+ ('\u{1207}', '\u{1207}'), ('\u{1208}', '\u{1246}'), ('\u{1247}', '\u{1247}'), ('\u{1248}',
+ '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'),
+ ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1286}'), ('\u{1287}', '\u{1287}'), ('\u{1288}',
+ '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}', '\u{12ae}'), ('\u{12af}', '\u{12af}'),
+ ('\u{12b0}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}',
+ '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12ce}'), ('\u{12cf}', '\u{12cf}'),
+ ('\u{12d0}', '\u{12d6}'), ('\u{12d8}', '\u{12ee}'), ('\u{12ef}', '\u{12ef}'), ('\u{12f0}',
+ '\u{130e}'), ('\u{130f}', '\u{130f}'), ('\u{1310}', '\u{1310}'), ('\u{1312}', '\u{1315}'),
+ ('\u{1318}', '\u{131e}'), ('\u{131f}', '\u{131f}'), ('\u{1320}', '\u{1346}'), ('\u{1347}',
+ '\u{1347}'), ('\u{1348}', '\u{135a}'), ('\u{135d}', '\u{135e}'), ('\u{135f}', '\u{135f}'),
+ ('\u{1380}', '\u{138f}'), ('\u{1780}', '\u{17a2}'), ('\u{17a5}', '\u{17a7}'), ('\u{17a9}',
+ '\u{17b3}'), ('\u{17b6}', '\u{17cd}'), ('\u{17d0}', '\u{17d0}'), ('\u{17d2}', '\u{17d2}'),
+ ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), ('\u{17e0}', '\u{17e9}'), ('\u{1c90}',
+ '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'), ('\u{1e00}', '\u{1e99}'), ('\u{1e9e}', '\u{1e9e}'),
+ ('\u{1ea0}', '\u{1ef9}'), ('\u{1f00}', '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}',
+ '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'),
+ ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}', '\u{1f70}'), ('\u{1f72}',
+ '\u{1f72}'), ('\u{1f74}', '\u{1f74}'), ('\u{1f76}', '\u{1f76}'), ('\u{1f78}', '\u{1f78}'),
+ ('\u{1f7a}', '\u{1f7a}'), ('\u{1f7c}', '\u{1f7c}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}',
+ '\u{1fba}'), ('\u{1fbc}', '\u{1fbc}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fc8}'),
+ ('\u{1fca}', '\u{1fca}'), ('\u{1fcc}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd2}'), ('\u{1fd6}',
+ '\u{1fda}'), ('\u{1fe0}', '\u{1fe2}'), ('\u{1fe4}', '\u{1fea}'), ('\u{1fec}', '\u{1fec}'),
+ ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ff8}'), ('\u{1ffa}', '\u{1ffa}'), ('\u{1ffc}',
+ '\u{1ffc}'), ('\u{2010}', '\u{2010}'), ('\u{2019}', '\u{2019}'), ('\u{2027}', '\u{2027}'),
+ ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}',
+ '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'),
+ ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}',
+ '\u{2dde}'), ('\u{3005}', '\u{3007}'), ('\u{3041}', '\u{3094}'), ('\u{3095}', '\u{3096}'),
+ ('\u{3099}', '\u{309a}'), ('\u{309d}', '\u{309e}'), ('\u{30a0}', '\u{30a0}'), ('\u{30a1}',
+ '\u{30fe}'), ('\u{3105}', '\u{312c}'), ('\u{312d}', '\u{312d}'), ('\u{312f}', '\u{312f}'),
+ ('\u{31a0}', '\u{31b7}'), ('\u{31b8}', '\u{31ba}'), ('\u{31bb}', '\u{31bf}'), ('\u{3400}',
+ '\u{4db5}'), ('\u{4db6}', '\u{4dbf}'), ('\u{4e00}', '\u{9fa5}'), ('\u{9fa6}', '\u{9fbb}'),
+ ('\u{9fbc}', '\u{9fc3}'), ('\u{9fc4}', '\u{9fcb}'), ('\u{9fcc}', '\u{9fcc}'), ('\u{9fcd}',
+ '\u{9fd5}'), ('\u{9fd6}', '\u{9fea}'), ('\u{9feb}', '\u{9fef}'), ('\u{9ff0}', '\u{9ffc}'),
+ ('\u{9ffd}', '\u{9fff}'), ('\u{a67f}', '\u{a67f}'), ('\u{a717}', '\u{a71a}'), ('\u{a71b}',
+ '\u{a71f}'), ('\u{a788}', '\u{a788}'), ('\u{a78d}', '\u{a78d}'), ('\u{a792}', '\u{a793}'),
+ ('\u{a7aa}', '\u{a7aa}'), ('\u{a7c0}', '\u{a7c1}'), ('\u{a7c2}', '\u{a7c6}'), ('\u{a7c7}',
+ '\u{a7ca}'), ('\u{a7d0}', '\u{a7d1}'), ('\u{a7d3}', '\u{a7d3}'), ('\u{a7d5}', '\u{a7d9}'),
+ ('\u{a9e7}', '\u{a9fe}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aa7b}'), ('\u{aa7c}',
+ '\u{aa7f}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'),
+ ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab66}', '\u{ab67}'), ('\u{ac00}',
+ '\u{d7a3}'), ('\u{fa0e}', '\u{fa0f}'), ('\u{fa11}', '\u{fa11}'), ('\u{fa13}', '\u{fa14}'),
+ ('\u{fa1f}', '\u{fa1f}'), ('\u{fa21}', '\u{fa21}'), ('\u{fa23}', '\u{fa24}'), ('\u{fa27}',
+ '\u{fa29}'), ('\u{11301}', '\u{11301}'), ('\u{11303}', '\u{11303}'), ('\u{1133b}',
+ '\u{1133b}'), ('\u{1133c}', '\u{1133c}'), ('\u{16ff0}', '\u{16ff1}'), ('\u{1b11f}',
+ '\u{1b122}'), ('\u{1b132}', '\u{1b132}'), ('\u{1b150}', '\u{1b152}'), ('\u{1b155}',
+ '\u{1b155}'), ('\u{1b164}', '\u{1b167}'), ('\u{1df00}', '\u{1df1e}'), ('\u{1df25}',
+ '\u{1df2a}'), ('\u{1e08f}', '\u{1e08f}'), ('\u{1e7e0}', '\u{1e7e6}'), ('\u{1e7e8}',
+ '\u{1e7eb}'), ('\u{1e7ed}', '\u{1e7ee}'), ('\u{1e7f0}', '\u{1e7fe}'), ('\u{20000}',
+ '\u{2a6d6}'), ('\u{2a6d7}', '\u{2a6dd}'), ('\u{2a6de}', '\u{2a6df}'), ('\u{2a700}',
+ '\u{2b734}'), ('\u{2b735}', '\u{2b738}'), ('\u{2b739}', '\u{2b739}'), ('\u{2b740}',
+ '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2ceb0}', '\u{2ebe0}'), ('\u{30000}',
+ '\u{3134a}'), ('\u{31350}', '\u{323af}')
];
const IDENTIFIER_TYPE: &'static [(char, char, IdentifierType)] = &[
@@ -438,160 +446,167 @@ pub mod identifier {
IdentifierType::Not_XID), ('\u{60d}', '\u{60f}', IdentifierType::Not_XID), ('\u{610}',
'\u{615}', IdentifierType::Uncommon_Use), ('\u{616}', '\u{61a}',
IdentifierType::Uncommon_Use), ('\u{61b}', '\u{61b}', IdentifierType::Not_XID),
- ('\u{61c}', '\u{61c}', IdentifierType::Default_Ignorable), ('\u{61e}', '\u{61e}',
- IdentifierType::Not_XID), ('\u{61f}', '\u{61f}', IdentifierType::Not_XID), ('\u{620}',
- '\u{620}', IdentifierType::Recommended), ('\u{621}', '\u{63a}',
- IdentifierType::Recommended), ('\u{63b}', '\u{63f}', IdentifierType::Recommended),
- ('\u{640}', '\u{640}', IdentifierType::Obsolete), ('\u{641}', '\u{652}',
- IdentifierType::Recommended), ('\u{653}', '\u{655}', IdentifierType::Recommended),
- ('\u{656}', '\u{658}', IdentifierType::Uncommon_Use), ('\u{659}', '\u{65e}',
- IdentifierType::Uncommon_Use), ('\u{65f}', '\u{65f}', IdentifierType::Uncommon_Use),
- ('\u{660}', '\u{669}', IdentifierType::Recommended), ('\u{66a}', '\u{66d}',
- IdentifierType::Not_XID), ('\u{66e}', '\u{66f}', IdentifierType::Obsolete), ('\u{670}',
- '\u{672}', IdentifierType::Recommended), ('\u{673}', '\u{673}',
- IdentifierType::Deprecated), ('\u{674}', '\u{674}', IdentifierType::Recommended),
- ('\u{675}', '\u{678}', IdentifierType::Not_NFKC), ('\u{679}', '\u{68d}',
- IdentifierType::Recommended), ('\u{68e}', '\u{68e}', IdentifierType::Obsolete),
- ('\u{68f}', '\u{6a0}', IdentifierType::Recommended), ('\u{6a1}', '\u{6a1}',
- IdentifierType::Obsolete), ('\u{6a2}', '\u{6b7}', IdentifierType::Recommended),
- ('\u{6b8}', '\u{6b9}', IdentifierType::Recommended), ('\u{6ba}', '\u{6be}',
- IdentifierType::Recommended), ('\u{6bf}', '\u{6bf}', IdentifierType::Recommended),
- ('\u{6c0}', '\u{6ce}', IdentifierType::Recommended), ('\u{6cf}', '\u{6cf}',
- IdentifierType::Recommended), ('\u{6d0}', '\u{6d3}', IdentifierType::Recommended),
- ('\u{6d4}', '\u{6d4}', IdentifierType::Not_XID), ('\u{6d5}', '\u{6d5}',
- IdentifierType::Recommended), ('\u{6d6}', '\u{6dc}', IdentifierType::Uncommon_Use),
- ('\u{6dd}', '\u{6dd}', IdentifierType::Not_XID), ('\u{6de}', '\u{6de}',
- IdentifierType::Not_XID), ('\u{6df}', '\u{6e4}', IdentifierType::Uncommon_Use),
- ('\u{6e5}', '\u{6e6}', IdentifierType::Recommended), ('\u{6e7}', '\u{6e8}',
- IdentifierType::Uncommon_Use), ('\u{6e9}', '\u{6e9}', IdentifierType::Not_XID),
- ('\u{6ea}', '\u{6ed}', IdentifierType::Uncommon_Use), ('\u{6ee}', '\u{6ef}',
- IdentifierType::Recommended), ('\u{6f0}', '\u{6f9}', IdentifierType::Recommended),
- ('\u{6fa}', '\u{6fc}', IdentifierType::Recommended), ('\u{6fd}', '\u{6fe}',
- IdentifierType::Inclusion), ('\u{6ff}', '\u{6ff}', IdentifierType::Recommended),
- ('\u{700}', '\u{70d}', IdentifierType::Limited_Use), ('\u{70f}', '\u{70f}',
- IdentifierType::Limited_Use), ('\u{710}', '\u{72c}', IdentifierType::Limited_Use),
- ('\u{72d}', '\u{72f}', IdentifierType::Limited_Use), ('\u{730}', '\u{73f}',
- IdentifierType::Limited_Use), ('\u{740}', '\u{74a}', IdentifierType::Limited_Use),
- ('\u{74d}', '\u{74f}', IdentifierType::Limited_Use), ('\u{750}', '\u{76d}',
- IdentifierType::Recommended), ('\u{76e}', '\u{77f}', IdentifierType::Recommended),
- ('\u{780}', '\u{7b0}', IdentifierType::Recommended), ('\u{7b1}', '\u{7b1}',
- IdentifierType::Recommended), ('\u{7c0}', '\u{7e7}', IdentifierType::Limited_Use),
- ('\u{7e8}', '\u{7ea}', IdentifierType::Limited_Use), ('\u{7eb}', '\u{7f5}',
- IdentifierType::Limited_Use), ('\u{7f6}', '\u{7f9}', IdentifierType::Limited_Use),
- ('\u{7fa}', '\u{7fa}', IdentifierType::Limited_Use), ('\u{7fd}', '\u{7fd}',
- IdentifierType::Limited_Use), ('\u{7fe}', '\u{7ff}', IdentifierType::Limited_Use),
- ('\u{800}', '\u{82d}', IdentifierType::Exclusion), ('\u{830}', '\u{83e}',
- IdentifierType::Exclusion), ('\u{840}', '\u{85b}', IdentifierType::Limited_Use),
- ('\u{85e}', '\u{85e}', IdentifierType::Limited_Use), ('\u{860}', '\u{86a}',
- IdentifierType::Limited_Use), ('\u{8a0}', '\u{8a0}', IdentifierType::Recommended),
- ('\u{8a1}', '\u{8a1}', IdentifierType::Recommended), ('\u{8a2}', '\u{8ac}',
- IdentifierType::Recommended), ('\u{8ad}', '\u{8b1}', IdentifierType::Obsolete),
- ('\u{8b2}', '\u{8b2}', IdentifierType::Recommended), ('\u{8b3}', '\u{8b4}',
- IdentifierType::Uncommon_Use), ('\u{8b6}', '\u{8bd}', IdentifierType::Recommended),
- ('\u{8be}', '\u{8c7}', IdentifierType::Recommended), ('\u{8d3}', '\u{8d3}',
- IdentifierType::Uncommon_Use), ('\u{8d4}', '\u{8e1}', IdentifierType::Uncommon_Use),
- ('\u{8e2}', '\u{8e2}', IdentifierType::Not_XID), ('\u{8e3}', '\u{8e3}',
- IdentifierType::Uncommon_Use), ('\u{8e4}', '\u{8fe}', IdentifierType::Uncommon_Use),
- ('\u{8ff}', '\u{8ff}', IdentifierType::Uncommon_Use), ('\u{900}', '\u{900}',
- IdentifierType::Uncommon_Use), ('\u{901}', '\u{903}', IdentifierType::Recommended),
- ('\u{904}', '\u{904}', IdentifierType::Recommended), ('\u{905}', '\u{939}',
- IdentifierType::Recommended), ('\u{93a}', '\u{93b}', IdentifierType::Recommended),
- ('\u{93c}', '\u{94d}', IdentifierType::Recommended), ('\u{94e}', '\u{94e}',
- IdentifierType::Obsolete), ('\u{94f}', '\u{94f}', IdentifierType::Recommended),
- ('\u{950}', '\u{950}', IdentifierType::Recommended), ('\u{951}', '\u{952}',
- IdentifierType::Obsolete), ('\u{953}', '\u{954}', IdentifierType::Technical), ('\u{955}',
- '\u{955}', IdentifierType::Uncommon_Use), ('\u{956}', '\u{957}',
- IdentifierType::Recommended), ('\u{958}', '\u{95f}', IdentifierType::Not_NFKC),
- ('\u{960}', '\u{963}', IdentifierType::Recommended), ('\u{964}', '\u{965}',
- IdentifierType::Not_XID), ('\u{966}', '\u{96f}', IdentifierType::Recommended), ('\u{970}',
- '\u{970}', IdentifierType::Not_XID), ('\u{971}', '\u{972}', IdentifierType::Recommended),
- ('\u{973}', '\u{977}', IdentifierType::Recommended), ('\u{978}', '\u{978}',
- IdentifierType::Obsolete), ('\u{979}', '\u{97a}', IdentifierType::Recommended),
- ('\u{97b}', '\u{97c}', IdentifierType::Recommended), ('\u{97d}', '\u{97d}',
- IdentifierType::Recommended), ('\u{97e}', '\u{97f}', IdentifierType::Recommended),
- ('\u{980}', '\u{980}', IdentifierType::Obsolete), ('\u{981}', '\u{983}',
- IdentifierType::Recommended), ('\u{985}', '\u{98c}', IdentifierType::Recommended),
- ('\u{98f}', '\u{990}', IdentifierType::Recommended), ('\u{993}', '\u{9a8}',
- IdentifierType::Recommended), ('\u{9aa}', '\u{9b0}', IdentifierType::Recommended),
- ('\u{9b2}', '\u{9b2}', IdentifierType::Recommended), ('\u{9b6}', '\u{9b9}',
- IdentifierType::Recommended), ('\u{9bc}', '\u{9bc}', IdentifierType::Recommended),
- ('\u{9bd}', '\u{9bd}', IdentifierType::Recommended), ('\u{9be}', '\u{9c4}',
- IdentifierType::Recommended), ('\u{9c7}', '\u{9c8}', IdentifierType::Recommended),
- ('\u{9cb}', '\u{9cd}', IdentifierType::Recommended), ('\u{9ce}', '\u{9ce}',
- IdentifierType::Recommended), ('\u{9d7}', '\u{9d7}', IdentifierType::Recommended),
- ('\u{9dc}', '\u{9dd}', IdentifierType::Not_NFKC), ('\u{9df}', '\u{9df}',
- IdentifierType::Not_NFKC), ('\u{9e0}', '\u{9e3}', IdentifierType::Recommended),
- ('\u{9e6}', '\u{9f1}', IdentifierType::Recommended), ('\u{9f2}', '\u{9fa}',
- IdentifierType::Not_XID), ('\u{9fb}', '\u{9fb}', IdentifierType::Not_XID), ('\u{9fc}',
- '\u{9fc}', IdentifierType::Obsolete), ('\u{9fd}', '\u{9fd}', IdentifierType::Not_XID),
- ('\u{9fe}', '\u{9fe}', IdentifierType::Recommended), ('\u{a01}', '\u{a01}',
- IdentifierType::Recommended), ('\u{a02}', '\u{a02}', IdentifierType::Recommended),
- ('\u{a03}', '\u{a03}', IdentifierType::Recommended), ('\u{a05}', '\u{a0a}',
- IdentifierType::Recommended), ('\u{a0f}', '\u{a10}', IdentifierType::Recommended),
- ('\u{a13}', '\u{a28}', IdentifierType::Recommended), ('\u{a2a}', '\u{a30}',
- IdentifierType::Recommended), ('\u{a32}', '\u{a32}', IdentifierType::Recommended),
- ('\u{a33}', '\u{a33}', IdentifierType::Not_NFKC), ('\u{a35}', '\u{a35}',
- IdentifierType::Recommended), ('\u{a36}', '\u{a36}', IdentifierType::Not_NFKC),
- ('\u{a38}', '\u{a39}', IdentifierType::Recommended), ('\u{a3c}', '\u{a3c}',
- IdentifierType::Recommended), ('\u{a3e}', '\u{a42}', IdentifierType::Recommended),
- ('\u{a47}', '\u{a48}', IdentifierType::Recommended), ('\u{a4b}', '\u{a4d}',
- IdentifierType::Recommended), ('\u{a51}', '\u{a51}', IdentifierType::Uncommon_Use),
- ('\u{a59}', '\u{a5b}', IdentifierType::Not_NFKC), ('\u{a5c}', '\u{a5c}',
- IdentifierType::Recommended), ('\u{a5e}', '\u{a5e}', IdentifierType::Not_NFKC),
- ('\u{a66}', '\u{a74}', IdentifierType::Recommended), ('\u{a75}', '\u{a75}',
- IdentifierType::Uncommon_Use), ('\u{a76}', '\u{a76}', IdentifierType::Not_XID),
- ('\u{a81}', '\u{a83}', IdentifierType::Recommended), ('\u{a85}', '\u{a8b}',
- IdentifierType::Recommended), ('\u{a8c}', '\u{a8c}', IdentifierType::Recommended),
- ('\u{a8d}', '\u{a8d}', IdentifierType::Recommended), ('\u{a8f}', '\u{a91}',
- IdentifierType::Recommended), ('\u{a93}', '\u{aa8}', IdentifierType::Recommended),
- ('\u{aaa}', '\u{ab0}', IdentifierType::Recommended), ('\u{ab2}', '\u{ab3}',
- IdentifierType::Recommended), ('\u{ab5}', '\u{ab9}', IdentifierType::Recommended),
- ('\u{abc}', '\u{ac5}', IdentifierType::Recommended), ('\u{ac7}', '\u{ac9}',
- IdentifierType::Recommended), ('\u{acb}', '\u{acd}', IdentifierType::Recommended),
- ('\u{ad0}', '\u{ad0}', IdentifierType::Recommended), ('\u{ae0}', '\u{ae0}',
- IdentifierType::Recommended), ('\u{ae1}', '\u{ae3}', IdentifierType::Recommended),
- ('\u{ae6}', '\u{aef}', IdentifierType::Recommended), ('\u{af0}', '\u{af0}',
- IdentifierType::Not_XID), ('\u{af1}', '\u{af1}', IdentifierType::Not_XID), ('\u{af9}',
- '\u{af9}', IdentifierType::Uncommon_Use), ('\u{afa}', '\u{aff}',
- IdentifierType::Recommended), ('\u{b01}', '\u{b03}', IdentifierType::Recommended),
- ('\u{b05}', '\u{b0c}', IdentifierType::Recommended), ('\u{b0f}', '\u{b10}',
- IdentifierType::Recommended), ('\u{b13}', '\u{b28}', IdentifierType::Recommended),
- ('\u{b2a}', '\u{b30}', IdentifierType::Recommended), ('\u{b32}', '\u{b33}',
- IdentifierType::Recommended), ('\u{b35}', '\u{b35}', IdentifierType::Recommended),
- ('\u{b36}', '\u{b39}', IdentifierType::Recommended), ('\u{b3c}', '\u{b43}',
- IdentifierType::Recommended), ('\u{b44}', '\u{b44}', IdentifierType::Uncommon_Use),
- ('\u{b47}', '\u{b48}', IdentifierType::Recommended), ('\u{b4b}', '\u{b4d}',
- IdentifierType::Recommended), ('\u{b55}', '\u{b55}', IdentifierType::Recommended),
- ('\u{b56}', '\u{b57}', IdentifierType::Recommended), ('\u{b5c}', '\u{b5d}',
- IdentifierType::Not_NFKC), ('\u{b5f}', '\u{b61}', IdentifierType::Recommended),
- ('\u{b62}', '\u{b63}', IdentifierType::Uncommon_Use), ('\u{b66}', '\u{b6f}',
- IdentifierType::Recommended), ('\u{b70}', '\u{b70}', IdentifierType::Not_XID), ('\u{b71}',
- '\u{b71}', IdentifierType::Recommended), ('\u{b72}', '\u{b77}', IdentifierType::Not_XID),
- ('\u{b82}', '\u{b83}', IdentifierType::Recommended), ('\u{b85}', '\u{b8a}',
- IdentifierType::Recommended), ('\u{b8e}', '\u{b90}', IdentifierType::Recommended),
- ('\u{b92}', '\u{b95}', IdentifierType::Recommended), ('\u{b99}', '\u{b9a}',
- IdentifierType::Recommended), ('\u{b9c}', '\u{b9c}', IdentifierType::Recommended),
- ('\u{b9e}', '\u{b9f}', IdentifierType::Recommended), ('\u{ba3}', '\u{ba4}',
- IdentifierType::Recommended), ('\u{ba8}', '\u{baa}', IdentifierType::Recommended),
- ('\u{bae}', '\u{bb5}', IdentifierType::Recommended), ('\u{bb6}', '\u{bb6}',
- IdentifierType::Recommended), ('\u{bb7}', '\u{bb9}', IdentifierType::Recommended),
- ('\u{bbe}', '\u{bc2}', IdentifierType::Recommended), ('\u{bc6}', '\u{bc8}',
- IdentifierType::Recommended), ('\u{bca}', '\u{bcd}', IdentifierType::Recommended),
- ('\u{bd0}', '\u{bd0}', IdentifierType::Recommended), ('\u{bd7}', '\u{bd7}',
- IdentifierType::Recommended), ('\u{be6}', '\u{be6}', IdentifierType::Recommended),
- ('\u{be7}', '\u{bef}', IdentifierType::Recommended), ('\u{bf0}', '\u{bf2}',
- IdentifierType::Not_XID), ('\u{bf3}', '\u{bfa}', IdentifierType::Not_XID), ('\u{c00}',
- '\u{c00}', IdentifierType::Obsolete), ('\u{c01}', '\u{c03}', IdentifierType::Recommended),
- ('\u{c04}', '\u{c04}', IdentifierType::Recommended), ('\u{c05}', '\u{c0c}',
- IdentifierType::Recommended), ('\u{c0e}', '\u{c10}', IdentifierType::Recommended),
- ('\u{c12}', '\u{c28}', IdentifierType::Recommended), ('\u{c2a}', '\u{c33}',
- IdentifierType::Recommended), ('\u{c34}', '\u{c34}', IdentifierType::Obsolete),
- ('\u{c35}', '\u{c39}', IdentifierType::Recommended), ('\u{c3d}', '\u{c3d}',
- IdentifierType::Recommended), ('\u{c3e}', '\u{c44}', IdentifierType::Recommended),
- ('\u{c46}', '\u{c48}', IdentifierType::Recommended), ('\u{c4a}', '\u{c4d}',
- IdentifierType::Recommended), ('\u{c55}', '\u{c56}', IdentifierType::Recommended),
- ('\u{c58}', '\u{c59}', IdentifierType::Obsolete), ('\u{c5a}', '\u{c5a}',
- IdentifierType::Uncommon_Use), ('\u{c60}', '\u{c61}', IdentifierType::Recommended),
+ ('\u{61c}', '\u{61c}', IdentifierType::Default_Ignorable), ('\u{61d}', '\u{61d}',
+ IdentifierType::Not_XID), ('\u{61e}', '\u{61e}', IdentifierType::Not_XID), ('\u{61f}',
+ '\u{61f}', IdentifierType::Not_XID), ('\u{620}', '\u{620}', IdentifierType::Recommended),
+ ('\u{621}', '\u{63a}', IdentifierType::Recommended), ('\u{63b}', '\u{63f}',
+ IdentifierType::Recommended), ('\u{640}', '\u{640}', IdentifierType::Obsolete),
+ ('\u{641}', '\u{652}', IdentifierType::Recommended), ('\u{653}', '\u{655}',
+ IdentifierType::Recommended), ('\u{656}', '\u{658}', IdentifierType::Uncommon_Use),
+ ('\u{659}', '\u{65e}', IdentifierType::Uncommon_Use), ('\u{65f}', '\u{65f}',
+ IdentifierType::Uncommon_Use), ('\u{660}', '\u{669}', IdentifierType::Recommended),
+ ('\u{66a}', '\u{66d}', IdentifierType::Not_XID), ('\u{66e}', '\u{66f}',
+ IdentifierType::Obsolete), ('\u{670}', '\u{672}', IdentifierType::Recommended),
+ ('\u{673}', '\u{673}', IdentifierType::Deprecated), ('\u{674}', '\u{674}',
+ IdentifierType::Recommended), ('\u{675}', '\u{678}', IdentifierType::Not_NFKC),
+ ('\u{679}', '\u{68d}', IdentifierType::Recommended), ('\u{68e}', '\u{68e}',
+ IdentifierType::Obsolete), ('\u{68f}', '\u{6a0}', IdentifierType::Recommended),
+ ('\u{6a1}', '\u{6a1}', IdentifierType::Obsolete), ('\u{6a2}', '\u{6b7}',
+ IdentifierType::Recommended), ('\u{6b8}', '\u{6b9}', IdentifierType::Recommended),
+ ('\u{6ba}', '\u{6be}', IdentifierType::Recommended), ('\u{6bf}', '\u{6bf}',
+ IdentifierType::Recommended), ('\u{6c0}', '\u{6ce}', IdentifierType::Recommended),
+ ('\u{6cf}', '\u{6cf}', IdentifierType::Recommended), ('\u{6d0}', '\u{6d3}',
+ IdentifierType::Recommended), ('\u{6d4}', '\u{6d4}', IdentifierType::Not_XID), ('\u{6d5}',
+ '\u{6d5}', IdentifierType::Recommended), ('\u{6d6}', '\u{6dc}',
+ IdentifierType::Uncommon_Use), ('\u{6dd}', '\u{6dd}', IdentifierType::Not_XID),
+ ('\u{6de}', '\u{6de}', IdentifierType::Not_XID), ('\u{6df}', '\u{6e4}',
+ IdentifierType::Uncommon_Use), ('\u{6e5}', '\u{6e6}', IdentifierType::Recommended),
+ ('\u{6e7}', '\u{6e8}', IdentifierType::Uncommon_Use), ('\u{6e9}', '\u{6e9}',
+ IdentifierType::Not_XID), ('\u{6ea}', '\u{6ed}', IdentifierType::Uncommon_Use),
+ ('\u{6ee}', '\u{6ef}', IdentifierType::Recommended), ('\u{6f0}', '\u{6f9}',
+ IdentifierType::Recommended), ('\u{6fa}', '\u{6fc}', IdentifierType::Recommended),
+ ('\u{6fd}', '\u{6fe}', IdentifierType::Inclusion), ('\u{6ff}', '\u{6ff}',
+ IdentifierType::Recommended), ('\u{700}', '\u{70d}', IdentifierType::Limited_Use),
+ ('\u{70f}', '\u{70f}', IdentifierType::Limited_Use), ('\u{710}', '\u{72c}',
+ IdentifierType::Limited_Use), ('\u{72d}', '\u{72f}', IdentifierType::Limited_Use),
+ ('\u{730}', '\u{73f}', IdentifierType::Limited_Use), ('\u{740}', '\u{74a}',
+ IdentifierType::Limited_Use), ('\u{74d}', '\u{74f}', IdentifierType::Limited_Use),
+ ('\u{750}', '\u{76d}', IdentifierType::Recommended), ('\u{76e}', '\u{77f}',
+ IdentifierType::Recommended), ('\u{780}', '\u{7b0}', IdentifierType::Recommended),
+ ('\u{7b1}', '\u{7b1}', IdentifierType::Recommended), ('\u{7c0}', '\u{7e7}',
+ IdentifierType::Limited_Use), ('\u{7e8}', '\u{7ea}', IdentifierType::Limited_Use),
+ ('\u{7eb}', '\u{7f5}', IdentifierType::Limited_Use), ('\u{7f6}', '\u{7f9}',
+ IdentifierType::Limited_Use), ('\u{7fa}', '\u{7fa}', IdentifierType::Limited_Use),
+ ('\u{7fd}', '\u{7fd}', IdentifierType::Limited_Use), ('\u{7fe}', '\u{7ff}',
+ IdentifierType::Limited_Use), ('\u{800}', '\u{82d}', IdentifierType::Exclusion),
+ ('\u{830}', '\u{83e}', IdentifierType::Exclusion), ('\u{840}', '\u{85b}',
+ IdentifierType::Limited_Use), ('\u{85e}', '\u{85e}', IdentifierType::Limited_Use),
+ ('\u{860}', '\u{86a}', IdentifierType::Limited_Use), ('\u{870}', '\u{887}',
+ IdentifierType::Recommended), ('\u{888}', '\u{888}', IdentifierType::Not_XID), ('\u{889}',
+ '\u{88e}', IdentifierType::Recommended), ('\u{890}', '\u{891}', IdentifierType::Not_XID),
+ ('\u{898}', '\u{89f}', IdentifierType::Uncommon_Use), ('\u{8a0}', '\u{8a0}',
+ IdentifierType::Recommended), ('\u{8a1}', '\u{8a1}', IdentifierType::Recommended),
+ ('\u{8a2}', '\u{8ac}', IdentifierType::Recommended), ('\u{8ad}', '\u{8b1}',
+ IdentifierType::Obsolete), ('\u{8b2}', '\u{8b2}', IdentifierType::Recommended),
+ ('\u{8b3}', '\u{8b4}', IdentifierType::Uncommon_Use), ('\u{8b5}', '\u{8b5}',
+ IdentifierType::Recommended), ('\u{8b6}', '\u{8bd}', IdentifierType::Recommended),
+ ('\u{8be}', '\u{8c7}', IdentifierType::Recommended), ('\u{8c8}', '\u{8c9}',
+ IdentifierType::Recommended), ('\u{8ca}', '\u{8d2}', IdentifierType::Uncommon_Use),
+ ('\u{8d3}', '\u{8d3}', IdentifierType::Uncommon_Use), ('\u{8d4}', '\u{8e1}',
+ IdentifierType::Uncommon_Use), ('\u{8e2}', '\u{8e2}', IdentifierType::Not_XID),
+ ('\u{8e3}', '\u{8e3}', IdentifierType::Uncommon_Use), ('\u{8e4}', '\u{8fe}',
+ IdentifierType::Uncommon_Use), ('\u{8ff}', '\u{8ff}', IdentifierType::Uncommon_Use),
+ ('\u{900}', '\u{900}', IdentifierType::Uncommon_Use), ('\u{901}', '\u{903}',
+ IdentifierType::Recommended), ('\u{904}', '\u{904}', IdentifierType::Recommended),
+ ('\u{905}', '\u{939}', IdentifierType::Recommended), ('\u{93a}', '\u{93b}',
+ IdentifierType::Recommended), ('\u{93c}', '\u{94d}', IdentifierType::Recommended),
+ ('\u{94e}', '\u{94e}', IdentifierType::Obsolete), ('\u{94f}', '\u{94f}',
+ IdentifierType::Recommended), ('\u{950}', '\u{950}', IdentifierType::Recommended),
+ ('\u{951}', '\u{952}', IdentifierType::Obsolete), ('\u{953}', '\u{954}',
+ IdentifierType::Technical), ('\u{955}', '\u{955}', IdentifierType::Uncommon_Use),
+ ('\u{956}', '\u{957}', IdentifierType::Recommended), ('\u{958}', '\u{95f}',
+ IdentifierType::Not_NFKC), ('\u{960}', '\u{963}', IdentifierType::Recommended),
+ ('\u{964}', '\u{965}', IdentifierType::Not_XID), ('\u{966}', '\u{96f}',
+ IdentifierType::Recommended), ('\u{970}', '\u{970}', IdentifierType::Not_XID), ('\u{971}',
+ '\u{972}', IdentifierType::Recommended), ('\u{973}', '\u{977}',
+ IdentifierType::Recommended), ('\u{978}', '\u{978}', IdentifierType::Obsolete),
+ ('\u{979}', '\u{97a}', IdentifierType::Recommended), ('\u{97b}', '\u{97c}',
+ IdentifierType::Recommended), ('\u{97d}', '\u{97d}', IdentifierType::Recommended),
+ ('\u{97e}', '\u{97f}', IdentifierType::Recommended), ('\u{980}', '\u{980}',
+ IdentifierType::Obsolete), ('\u{981}', '\u{983}', IdentifierType::Recommended),
+ ('\u{985}', '\u{98c}', IdentifierType::Recommended), ('\u{98f}', '\u{990}',
+ IdentifierType::Recommended), ('\u{993}', '\u{9a8}', IdentifierType::Recommended),
+ ('\u{9aa}', '\u{9b0}', IdentifierType::Recommended), ('\u{9b2}', '\u{9b2}',
+ IdentifierType::Recommended), ('\u{9b6}', '\u{9b9}', IdentifierType::Recommended),
+ ('\u{9bc}', '\u{9bc}', IdentifierType::Recommended), ('\u{9bd}', '\u{9bd}',
+ IdentifierType::Recommended), ('\u{9be}', '\u{9c4}', IdentifierType::Recommended),
+ ('\u{9c7}', '\u{9c8}', IdentifierType::Recommended), ('\u{9cb}', '\u{9cd}',
+ IdentifierType::Recommended), ('\u{9ce}', '\u{9ce}', IdentifierType::Recommended),
+ ('\u{9d7}', '\u{9d7}', IdentifierType::Recommended), ('\u{9dc}', '\u{9dd}',
+ IdentifierType::Not_NFKC), ('\u{9df}', '\u{9df}', IdentifierType::Not_NFKC), ('\u{9e0}',
+ '\u{9e3}', IdentifierType::Recommended), ('\u{9e6}', '\u{9f1}',
+ IdentifierType::Recommended), ('\u{9f2}', '\u{9fa}', IdentifierType::Not_XID), ('\u{9fb}',
+ '\u{9fb}', IdentifierType::Not_XID), ('\u{9fc}', '\u{9fc}', IdentifierType::Obsolete),
+ ('\u{9fd}', '\u{9fd}', IdentifierType::Not_XID), ('\u{9fe}', '\u{9fe}',
+ IdentifierType::Recommended), ('\u{a01}', '\u{a01}', IdentifierType::Recommended),
+ ('\u{a02}', '\u{a02}', IdentifierType::Recommended), ('\u{a03}', '\u{a03}',
+ IdentifierType::Recommended), ('\u{a05}', '\u{a0a}', IdentifierType::Recommended),
+ ('\u{a0f}', '\u{a10}', IdentifierType::Recommended), ('\u{a13}', '\u{a28}',
+ IdentifierType::Recommended), ('\u{a2a}', '\u{a30}', IdentifierType::Recommended),
+ ('\u{a32}', '\u{a32}', IdentifierType::Recommended), ('\u{a33}', '\u{a33}',
+ IdentifierType::Not_NFKC), ('\u{a35}', '\u{a35}', IdentifierType::Recommended),
+ ('\u{a36}', '\u{a36}', IdentifierType::Not_NFKC), ('\u{a38}', '\u{a39}',
+ IdentifierType::Recommended), ('\u{a3c}', '\u{a3c}', IdentifierType::Recommended),
+ ('\u{a3e}', '\u{a42}', IdentifierType::Recommended), ('\u{a47}', '\u{a48}',
+ IdentifierType::Recommended), ('\u{a4b}', '\u{a4d}', IdentifierType::Recommended),
+ ('\u{a51}', '\u{a51}', IdentifierType::Uncommon_Use), ('\u{a59}', '\u{a5b}',
+ IdentifierType::Not_NFKC), ('\u{a5c}', '\u{a5c}', IdentifierType::Recommended),
+ ('\u{a5e}', '\u{a5e}', IdentifierType::Not_NFKC), ('\u{a66}', '\u{a74}',
+ IdentifierType::Recommended), ('\u{a75}', '\u{a75}', IdentifierType::Uncommon_Use),
+ ('\u{a76}', '\u{a76}', IdentifierType::Not_XID), ('\u{a81}', '\u{a83}',
+ IdentifierType::Recommended), ('\u{a85}', '\u{a8b}', IdentifierType::Recommended),
+ ('\u{a8c}', '\u{a8c}', IdentifierType::Recommended), ('\u{a8d}', '\u{a8d}',
+ IdentifierType::Recommended), ('\u{a8f}', '\u{a91}', IdentifierType::Recommended),
+ ('\u{a93}', '\u{aa8}', IdentifierType::Recommended), ('\u{aaa}', '\u{ab0}',
+ IdentifierType::Recommended), ('\u{ab2}', '\u{ab3}', IdentifierType::Recommended),
+ ('\u{ab5}', '\u{ab9}', IdentifierType::Recommended), ('\u{abc}', '\u{ac5}',
+ IdentifierType::Recommended), ('\u{ac7}', '\u{ac9}', IdentifierType::Recommended),
+ ('\u{acb}', '\u{acd}', IdentifierType::Recommended), ('\u{ad0}', '\u{ad0}',
+ IdentifierType::Recommended), ('\u{ae0}', '\u{ae0}', IdentifierType::Recommended),
+ ('\u{ae1}', '\u{ae3}', IdentifierType::Recommended), ('\u{ae6}', '\u{aef}',
+ IdentifierType::Recommended), ('\u{af0}', '\u{af0}', IdentifierType::Not_XID), ('\u{af1}',
+ '\u{af1}', IdentifierType::Not_XID), ('\u{af9}', '\u{af9}', IdentifierType::Uncommon_Use),
+ ('\u{afa}', '\u{aff}', IdentifierType::Recommended), ('\u{b01}', '\u{b03}',
+ IdentifierType::Recommended), ('\u{b05}', '\u{b0c}', IdentifierType::Recommended),
+ ('\u{b0f}', '\u{b10}', IdentifierType::Recommended), ('\u{b13}', '\u{b28}',
+ IdentifierType::Recommended), ('\u{b2a}', '\u{b30}', IdentifierType::Recommended),
+ ('\u{b32}', '\u{b33}', IdentifierType::Recommended), ('\u{b35}', '\u{b35}',
+ IdentifierType::Recommended), ('\u{b36}', '\u{b39}', IdentifierType::Recommended),
+ ('\u{b3c}', '\u{b43}', IdentifierType::Recommended), ('\u{b44}', '\u{b44}',
+ IdentifierType::Uncommon_Use), ('\u{b47}', '\u{b48}', IdentifierType::Recommended),
+ ('\u{b4b}', '\u{b4d}', IdentifierType::Recommended), ('\u{b55}', '\u{b55}',
+ IdentifierType::Recommended), ('\u{b56}', '\u{b57}', IdentifierType::Recommended),
+ ('\u{b5c}', '\u{b5d}', IdentifierType::Not_NFKC), ('\u{b5f}', '\u{b61}',
+ IdentifierType::Recommended), ('\u{b62}', '\u{b63}', IdentifierType::Uncommon_Use),
+ ('\u{b66}', '\u{b6f}', IdentifierType::Recommended), ('\u{b70}', '\u{b70}',
+ IdentifierType::Not_XID), ('\u{b71}', '\u{b71}', IdentifierType::Recommended), ('\u{b72}',
+ '\u{b77}', IdentifierType::Not_XID), ('\u{b82}', '\u{b83}', IdentifierType::Recommended),
+ ('\u{b85}', '\u{b8a}', IdentifierType::Recommended), ('\u{b8e}', '\u{b90}',
+ IdentifierType::Recommended), ('\u{b92}', '\u{b95}', IdentifierType::Recommended),
+ ('\u{b99}', '\u{b9a}', IdentifierType::Recommended), ('\u{b9c}', '\u{b9c}',
+ IdentifierType::Recommended), ('\u{b9e}', '\u{b9f}', IdentifierType::Recommended),
+ ('\u{ba3}', '\u{ba4}', IdentifierType::Recommended), ('\u{ba8}', '\u{baa}',
+ IdentifierType::Recommended), ('\u{bae}', '\u{bb5}', IdentifierType::Recommended),
+ ('\u{bb6}', '\u{bb6}', IdentifierType::Recommended), ('\u{bb7}', '\u{bb9}',
+ IdentifierType::Recommended), ('\u{bbe}', '\u{bc2}', IdentifierType::Recommended),
+ ('\u{bc6}', '\u{bc8}', IdentifierType::Recommended), ('\u{bca}', '\u{bcd}',
+ IdentifierType::Recommended), ('\u{bd0}', '\u{bd0}', IdentifierType::Recommended),
+ ('\u{bd7}', '\u{bd7}', IdentifierType::Recommended), ('\u{be6}', '\u{be6}',
+ IdentifierType::Recommended), ('\u{be7}', '\u{bef}', IdentifierType::Recommended),
+ ('\u{bf0}', '\u{bf2}', IdentifierType::Not_XID), ('\u{bf3}', '\u{bfa}',
+ IdentifierType::Not_XID), ('\u{c00}', '\u{c00}', IdentifierType::Obsolete), ('\u{c01}',
+ '\u{c03}', IdentifierType::Recommended), ('\u{c04}', '\u{c04}',
+ IdentifierType::Recommended), ('\u{c05}', '\u{c0c}', IdentifierType::Recommended),
+ ('\u{c0e}', '\u{c10}', IdentifierType::Recommended), ('\u{c12}', '\u{c28}',
+ IdentifierType::Recommended), ('\u{c2a}', '\u{c33}', IdentifierType::Recommended),
+ ('\u{c34}', '\u{c34}', IdentifierType::Obsolete), ('\u{c35}', '\u{c39}',
+ IdentifierType::Recommended), ('\u{c3c}', '\u{c3c}', IdentifierType::Recommended),
+ ('\u{c3d}', '\u{c3d}', IdentifierType::Recommended), ('\u{c3e}', '\u{c44}',
+ IdentifierType::Recommended), ('\u{c46}', '\u{c48}', IdentifierType::Recommended),
+ ('\u{c4a}', '\u{c4d}', IdentifierType::Recommended), ('\u{c55}', '\u{c56}',
+ IdentifierType::Recommended), ('\u{c58}', '\u{c59}', IdentifierType::Obsolete),
+ ('\u{c5a}', '\u{c5a}', IdentifierType::Uncommon_Use), ('\u{c5d}', '\u{c5d}',
+ IdentifierType::Recommended), ('\u{c60}', '\u{c61}', IdentifierType::Recommended),
('\u{c62}', '\u{c63}', IdentifierType::Uncommon_Use), ('\u{c66}', '\u{c6f}',
IdentifierType::Recommended), ('\u{c77}', '\u{c77}', IdentifierType::Not_XID), ('\u{c78}',
'\u{c7f}', IdentifierType::Not_XID), ('\u{c80}', '\u{c80}', IdentifierType::Recommended),
@@ -603,44 +618,45 @@ pub mod identifier {
IdentifierType::Recommended), ('\u{cbc}', '\u{cbd}', IdentifierType::Recommended),
('\u{cbe}', '\u{cc4}', IdentifierType::Recommended), ('\u{cc6}', '\u{cc8}',
IdentifierType::Recommended), ('\u{cca}', '\u{ccd}', IdentifierType::Recommended),
- ('\u{cd5}', '\u{cd6}', IdentifierType::Recommended), ('\u{cde}', '\u{cde}',
- IdentifierType::Obsolete), ('\u{ce0}', '\u{ce1}', IdentifierType::Recommended),
- ('\u{ce2}', '\u{ce3}', IdentifierType::Recommended), ('\u{ce6}', '\u{cef}',
- IdentifierType::Recommended), ('\u{cf1}', '\u{cf2}', IdentifierType::Recommended),
- ('\u{d00}', '\u{d00}', IdentifierType::Recommended), ('\u{d01}', '\u{d01}',
- IdentifierType::Obsolete), ('\u{d02}', '\u{d03}', IdentifierType::Recommended),
- ('\u{d04}', '\u{d04}', IdentifierType::Technical), ('\u{d05}', '\u{d0c}',
- IdentifierType::Recommended), ('\u{d0e}', '\u{d10}', IdentifierType::Recommended),
- ('\u{d12}', '\u{d28}', IdentifierType::Recommended), ('\u{d29}', '\u{d29}',
- IdentifierType::Recommended), ('\u{d2a}', '\u{d39}', IdentifierType::Recommended),
- ('\u{d3a}', '\u{d3a}', IdentifierType::Recommended), ('\u{d3b}', '\u{d3c}',
- IdentifierType::Obsolete), ('\u{d3d}', '\u{d3d}', IdentifierType::Recommended),
- ('\u{d3e}', '\u{d43}', IdentifierType::Recommended), ('\u{d44}', '\u{d44}',
- IdentifierType::Uncommon_Use), ('\u{d46}', '\u{d48}', IdentifierType::Recommended),
- ('\u{d4a}', '\u{d4d}', IdentifierType::Recommended), ('\u{d4e}', '\u{d4e}',
- IdentifierType::Recommended), ('\u{d4f}', '\u{d4f}', IdentifierType::Not_XID), ('\u{d54}',
- '\u{d56}', IdentifierType::Recommended), ('\u{d57}', '\u{d57}',
- IdentifierType::Recommended), ('\u{d58}', '\u{d5e}', IdentifierType::Not_XID), ('\u{d5f}',
- '\u{d5f}', IdentifierType::Obsolete), ('\u{d60}', '\u{d61}', IdentifierType::Recommended),
- ('\u{d62}', '\u{d63}', IdentifierType::Uncommon_Use), ('\u{d66}', '\u{d6f}',
- IdentifierType::Recommended), ('\u{d70}', '\u{d75}', IdentifierType::Not_XID), ('\u{d76}',
- '\u{d78}', IdentifierType::Not_XID), ('\u{d79}', '\u{d79}', IdentifierType::Not_XID),
- ('\u{d7a}', '\u{d7f}', IdentifierType::Recommended), ('\u{d81}', '\u{d81}',
- IdentifierType::Technical), ('\u{d82}', '\u{d83}', IdentifierType::Recommended),
- ('\u{d85}', '\u{d8e}', IdentifierType::Recommended), ('\u{d8f}', '\u{d90}',
- IdentifierType::Uncommon_Use), ('\u{d91}', '\u{d96}', IdentifierType::Recommended),
- ('\u{d9a}', '\u{da5}', IdentifierType::Recommended), ('\u{da6}', '\u{da6}',
- IdentifierType::Uncommon_Use), ('\u{da7}', '\u{db1}', IdentifierType::Recommended),
- ('\u{db3}', '\u{dbb}', IdentifierType::Recommended), ('\u{dbd}', '\u{dbd}',
- IdentifierType::Recommended), ('\u{dc0}', '\u{dc6}', IdentifierType::Recommended),
- ('\u{dca}', '\u{dca}', IdentifierType::Recommended), ('\u{dcf}', '\u{dd4}',
- IdentifierType::Recommended), ('\u{dd6}', '\u{dd6}', IdentifierType::Recommended),
- ('\u{dd8}', '\u{dde}', IdentifierType::Recommended), ('\u{ddf}', '\u{ddf}',
- IdentifierType::Uncommon_Use), ('\u{de6}', '\u{def}', IdentifierType::Obsolete),
- ('\u{df2}', '\u{df2}', IdentifierType::Recommended), ('\u{df3}', '\u{df3}',
- IdentifierType::Uncommon_Use), ('\u{df4}', '\u{df4}', IdentifierType::Not_XID),
- ('\u{e01}', '\u{e32}', IdentifierType::Recommended), ('\u{e33}', '\u{e33}',
- IdentifierType::Not_NFKC), ('\u{e34}', '\u{e3a}', IdentifierType::Recommended),
+ ('\u{cd5}', '\u{cd6}', IdentifierType::Recommended), ('\u{cdd}', '\u{cdd}',
+ IdentifierType::Recommended), ('\u{cde}', '\u{cde}', IdentifierType::Obsolete),
+ ('\u{ce0}', '\u{ce1}', IdentifierType::Recommended), ('\u{ce2}', '\u{ce3}',
+ IdentifierType::Recommended), ('\u{ce6}', '\u{cef}', IdentifierType::Recommended),
+ ('\u{cf1}', '\u{cf2}', IdentifierType::Recommended), ('\u{cf3}', '\u{cf3}',
+ IdentifierType::Recommended), ('\u{d00}', '\u{d00}', IdentifierType::Recommended),
+ ('\u{d01}', '\u{d01}', IdentifierType::Obsolete), ('\u{d02}', '\u{d03}',
+ IdentifierType::Recommended), ('\u{d04}', '\u{d04}', IdentifierType::Technical),
+ ('\u{d05}', '\u{d0c}', IdentifierType::Recommended), ('\u{d0e}', '\u{d10}',
+ IdentifierType::Recommended), ('\u{d12}', '\u{d28}', IdentifierType::Recommended),
+ ('\u{d29}', '\u{d29}', IdentifierType::Recommended), ('\u{d2a}', '\u{d39}',
+ IdentifierType::Recommended), ('\u{d3a}', '\u{d3a}', IdentifierType::Recommended),
+ ('\u{d3b}', '\u{d3c}', IdentifierType::Obsolete), ('\u{d3d}', '\u{d3d}',
+ IdentifierType::Recommended), ('\u{d3e}', '\u{d43}', IdentifierType::Recommended),
+ ('\u{d44}', '\u{d44}', IdentifierType::Uncommon_Use), ('\u{d46}', '\u{d48}',
+ IdentifierType::Recommended), ('\u{d4a}', '\u{d4d}', IdentifierType::Recommended),
+ ('\u{d4e}', '\u{d4e}', IdentifierType::Recommended), ('\u{d4f}', '\u{d4f}',
+ IdentifierType::Not_XID), ('\u{d54}', '\u{d56}', IdentifierType::Recommended), ('\u{d57}',
+ '\u{d57}', IdentifierType::Recommended), ('\u{d58}', '\u{d5e}', IdentifierType::Not_XID),
+ ('\u{d5f}', '\u{d5f}', IdentifierType::Obsolete), ('\u{d60}', '\u{d61}',
+ IdentifierType::Recommended), ('\u{d62}', '\u{d63}', IdentifierType::Uncommon_Use),
+ ('\u{d66}', '\u{d6f}', IdentifierType::Recommended), ('\u{d70}', '\u{d75}',
+ IdentifierType::Not_XID), ('\u{d76}', '\u{d78}', IdentifierType::Not_XID), ('\u{d79}',
+ '\u{d79}', IdentifierType::Not_XID), ('\u{d7a}', '\u{d7f}', IdentifierType::Recommended),
+ ('\u{d81}', '\u{d81}', IdentifierType::Technical), ('\u{d82}', '\u{d83}',
+ IdentifierType::Recommended), ('\u{d85}', '\u{d8e}', IdentifierType::Recommended),
+ ('\u{d8f}', '\u{d90}', IdentifierType::Uncommon_Use), ('\u{d91}', '\u{d96}',
+ IdentifierType::Recommended), ('\u{d9a}', '\u{da5}', IdentifierType::Recommended),
+ ('\u{da6}', '\u{da6}', IdentifierType::Uncommon_Use), ('\u{da7}', '\u{db1}',
+ IdentifierType::Recommended), ('\u{db3}', '\u{dbb}', IdentifierType::Recommended),
+ ('\u{dbd}', '\u{dbd}', IdentifierType::Recommended), ('\u{dc0}', '\u{dc6}',
+ IdentifierType::Recommended), ('\u{dca}', '\u{dca}', IdentifierType::Recommended),
+ ('\u{dcf}', '\u{dd4}', IdentifierType::Recommended), ('\u{dd6}', '\u{dd6}',
+ IdentifierType::Recommended), ('\u{dd8}', '\u{dde}', IdentifierType::Recommended),
+ ('\u{ddf}', '\u{ddf}', IdentifierType::Uncommon_Use), ('\u{de6}', '\u{def}',
+ IdentifierType::Obsolete), ('\u{df2}', '\u{df2}', IdentifierType::Recommended),
+ ('\u{df3}', '\u{df3}', IdentifierType::Uncommon_Use), ('\u{df4}', '\u{df4}',
+ IdentifierType::Not_XID), ('\u{e01}', '\u{e32}', IdentifierType::Recommended), ('\u{e33}',
+ '\u{e33}', IdentifierType::Not_NFKC), ('\u{e34}', '\u{e3a}', IdentifierType::Recommended),
('\u{e3f}', '\u{e3f}', IdentifierType::Not_XID), ('\u{e40}', '\u{e4e}',
IdentifierType::Recommended), ('\u{e4f}', '\u{e4f}', IdentifierType::Not_XID), ('\u{e50}',
'\u{e59}', IdentifierType::Recommended), ('\u{e5a}', '\u{e5b}', IdentifierType::Not_XID),
@@ -662,133 +678,137 @@ pub mod identifier {
IdentifierType::Recommended), ('\u{ebb}', '\u{ebd}', IdentifierType::Recommended),
('\u{ec0}', '\u{ec4}', IdentifierType::Recommended), ('\u{ec6}', '\u{ec6}',
IdentifierType::Recommended), ('\u{ec8}', '\u{ecd}', IdentifierType::Recommended),
- ('\u{ed0}', '\u{ed9}', IdentifierType::Recommended), ('\u{edc}', '\u{edd}',
- IdentifierType::Not_NFKC), ('\u{ede}', '\u{edf}', IdentifierType::Recommended),
- ('\u{f00}', '\u{f00}', IdentifierType::Recommended), ('\u{f01}', '\u{f0a}',
- IdentifierType::Not_XID), ('\u{f0b}', '\u{f0b}', IdentifierType::Inclusion), ('\u{f0c}',
- '\u{f0c}', IdentifierType::Not_NFKC), ('\u{f0d}', '\u{f17}', IdentifierType::Not_XID),
- ('\u{f18}', '\u{f19}', IdentifierType::Technical), ('\u{f1a}', '\u{f1f}',
- IdentifierType::Not_XID), ('\u{f20}', '\u{f29}', IdentifierType::Recommended), ('\u{f2a}',
- '\u{f34}', IdentifierType::Not_XID), ('\u{f35}', '\u{f35}', IdentifierType::Recommended),
- ('\u{f36}', '\u{f36}', IdentifierType::Not_XID), ('\u{f37}', '\u{f37}',
- IdentifierType::Recommended), ('\u{f38}', '\u{f38}', IdentifierType::Not_XID), ('\u{f39}',
- '\u{f39}', IdentifierType::Uncommon_Use), ('\u{f3a}', '\u{f3d}', IdentifierType::Not_XID),
- ('\u{f3e}', '\u{f42}', IdentifierType::Recommended), ('\u{f43}', '\u{f43}',
- IdentifierType::Not_NFKC), ('\u{f44}', '\u{f47}', IdentifierType::Recommended),
- ('\u{f49}', '\u{f4c}', IdentifierType::Recommended), ('\u{f4d}', '\u{f4d}',
- IdentifierType::Not_NFKC), ('\u{f4e}', '\u{f51}', IdentifierType::Recommended),
- ('\u{f52}', '\u{f52}', IdentifierType::Not_NFKC), ('\u{f53}', '\u{f56}',
- IdentifierType::Recommended), ('\u{f57}', '\u{f57}', IdentifierType::Not_NFKC),
- ('\u{f58}', '\u{f5b}', IdentifierType::Recommended), ('\u{f5c}', '\u{f5c}',
- IdentifierType::Not_NFKC), ('\u{f5d}', '\u{f68}', IdentifierType::Recommended),
- ('\u{f69}', '\u{f69}', IdentifierType::Not_NFKC), ('\u{f6a}', '\u{f6a}',
- IdentifierType::Recommended), ('\u{f6b}', '\u{f6c}', IdentifierType::Recommended),
- ('\u{f71}', '\u{f72}', IdentifierType::Recommended), ('\u{f73}', '\u{f73}',
- IdentifierType::Not_NFKC), ('\u{f74}', '\u{f74}', IdentifierType::Recommended),
- ('\u{f75}', '\u{f76}', IdentifierType::Not_NFKC), ('\u{f77}', '\u{f77}',
- IdentifierType::Deprecated), ('\u{f78}', '\u{f78}', IdentifierType::Not_NFKC), ('\u{f79}',
- '\u{f79}', IdentifierType::Deprecated), ('\u{f7a}', '\u{f80}',
- IdentifierType::Recommended), ('\u{f81}', '\u{f81}', IdentifierType::Not_NFKC),
- ('\u{f82}', '\u{f84}', IdentifierType::Recommended), ('\u{f85}', '\u{f85}',
- IdentifierType::Not_XID), ('\u{f86}', '\u{f8b}', IdentifierType::Recommended), ('\u{f8c}',
- '\u{f8f}', IdentifierType::Recommended), ('\u{f90}', '\u{f92}',
- IdentifierType::Recommended), ('\u{f93}', '\u{f93}', IdentifierType::Not_NFKC),
- ('\u{f94}', '\u{f95}', IdentifierType::Recommended), ('\u{f96}', '\u{f96}',
- IdentifierType::Recommended), ('\u{f97}', '\u{f97}', IdentifierType::Recommended),
- ('\u{f99}', '\u{f9c}', IdentifierType::Recommended), ('\u{f9d}', '\u{f9d}',
- IdentifierType::Not_NFKC), ('\u{f9e}', '\u{fa1}', IdentifierType::Recommended),
- ('\u{fa2}', '\u{fa2}', IdentifierType::Not_NFKC), ('\u{fa3}', '\u{fa6}',
- IdentifierType::Recommended), ('\u{fa7}', '\u{fa7}', IdentifierType::Not_NFKC),
- ('\u{fa8}', '\u{fab}', IdentifierType::Recommended), ('\u{fac}', '\u{fac}',
- IdentifierType::Not_NFKC), ('\u{fad}', '\u{fad}', IdentifierType::Recommended),
- ('\u{fae}', '\u{fb0}', IdentifierType::Recommended), ('\u{fb1}', '\u{fb7}',
- IdentifierType::Recommended), ('\u{fb8}', '\u{fb8}', IdentifierType::Recommended),
- ('\u{fb9}', '\u{fb9}', IdentifierType::Not_NFKC), ('\u{fba}', '\u{fbc}',
- IdentifierType::Recommended), ('\u{fbe}', '\u{fc5}', IdentifierType::Not_XID), ('\u{fc6}',
- '\u{fc6}', IdentifierType::Recommended), ('\u{fc7}', '\u{fcc}', IdentifierType::Not_XID),
- ('\u{fce}', '\u{fce}', IdentifierType::Not_XID), ('\u{fcf}', '\u{fcf}',
- IdentifierType::Not_XID), ('\u{fd0}', '\u{fd1}', IdentifierType::Not_XID), ('\u{fd2}',
- '\u{fd4}', IdentifierType::Not_XID), ('\u{fd5}', '\u{fd8}', IdentifierType::Not_XID),
- ('\u{fd9}', '\u{fda}', IdentifierType::Not_XID), ('\u{1000}', '\u{1021}',
- IdentifierType::Recommended), ('\u{1022}', '\u{1022}', IdentifierType::Recommended),
- ('\u{1023}', '\u{1027}', IdentifierType::Recommended), ('\u{1028}', '\u{1028}',
- IdentifierType::Recommended), ('\u{1029}', '\u{102a}', IdentifierType::Recommended),
- ('\u{102b}', '\u{102b}', IdentifierType::Recommended), ('\u{102c}', '\u{1032}',
- IdentifierType::Recommended), ('\u{1033}', '\u{1035}', IdentifierType::Recommended),
- ('\u{1036}', '\u{1039}', IdentifierType::Recommended), ('\u{103a}', '\u{103f}',
- IdentifierType::Recommended), ('\u{1040}', '\u{1049}', IdentifierType::Recommended),
- ('\u{104a}', '\u{104f}', IdentifierType::Not_XID), ('\u{1050}', '\u{1059}',
- IdentifierType::Recommended), ('\u{105a}', '\u{1099}', IdentifierType::Recommended),
- ('\u{109a}', '\u{109d}', IdentifierType::Recommended), ('\u{109e}', '\u{109f}',
- IdentifierType::Not_XID), ('\u{10a0}', '\u{10c5}', IdentifierType::Obsolete), ('\u{10c7}',
- '\u{10c7}', IdentifierType::Recommended), ('\u{10cd}', '\u{10cd}',
- IdentifierType::Recommended), ('\u{10d0}', '\u{10f0}', IdentifierType::Recommended),
- ('\u{10f1}', '\u{10f6}', IdentifierType::Obsolete), ('\u{10f7}', '\u{10f8}',
- IdentifierType::Recommended), ('\u{10f9}', '\u{10fa}', IdentifierType::Recommended),
- ('\u{10fb}', '\u{10fb}', IdentifierType::Not_XID), ('\u{10fc}', '\u{10fc}',
- IdentifierType::Not_NFKC), ('\u{10fd}', '\u{10ff}', IdentifierType::Recommended),
- ('\u{1100}', '\u{1159}', IdentifierType::Obsolete), ('\u{115a}', '\u{115e}',
- IdentifierType::Obsolete), ('\u{115f}', '\u{1160}', IdentifierType::Default_Ignorable),
- ('\u{1161}', '\u{11a2}', IdentifierType::Obsolete), ('\u{11a3}', '\u{11a7}',
- IdentifierType::Obsolete), ('\u{11a8}', '\u{11f9}', IdentifierType::Obsolete),
- ('\u{11fa}', '\u{11ff}', IdentifierType::Obsolete), ('\u{1200}', '\u{1206}',
- IdentifierType::Recommended), ('\u{1207}', '\u{1207}', IdentifierType::Recommended),
- ('\u{1208}', '\u{1246}', IdentifierType::Recommended), ('\u{1247}', '\u{1247}',
- IdentifierType::Recommended), ('\u{1248}', '\u{1248}', IdentifierType::Recommended),
- ('\u{124a}', '\u{124d}', IdentifierType::Recommended), ('\u{1250}', '\u{1256}',
- IdentifierType::Recommended), ('\u{1258}', '\u{1258}', IdentifierType::Recommended),
- ('\u{125a}', '\u{125d}', IdentifierType::Recommended), ('\u{1260}', '\u{1286}',
- IdentifierType::Recommended), ('\u{1287}', '\u{1287}', IdentifierType::Recommended),
- ('\u{1288}', '\u{1288}', IdentifierType::Recommended), ('\u{128a}', '\u{128d}',
- IdentifierType::Recommended), ('\u{1290}', '\u{12ae}', IdentifierType::Recommended),
- ('\u{12af}', '\u{12af}', IdentifierType::Recommended), ('\u{12b0}', '\u{12b0}',
- IdentifierType::Recommended), ('\u{12b2}', '\u{12b5}', IdentifierType::Recommended),
- ('\u{12b8}', '\u{12be}', IdentifierType::Recommended), ('\u{12c0}', '\u{12c0}',
- IdentifierType::Recommended), ('\u{12c2}', '\u{12c5}', IdentifierType::Recommended),
- ('\u{12c8}', '\u{12ce}', IdentifierType::Recommended), ('\u{12cf}', '\u{12cf}',
- IdentifierType::Recommended), ('\u{12d0}', '\u{12d6}', IdentifierType::Recommended),
- ('\u{12d8}', '\u{12ee}', IdentifierType::Recommended), ('\u{12ef}', '\u{12ef}',
- IdentifierType::Recommended), ('\u{12f0}', '\u{130e}', IdentifierType::Recommended),
- ('\u{130f}', '\u{130f}', IdentifierType::Recommended), ('\u{1310}', '\u{1310}',
- IdentifierType::Recommended), ('\u{1312}', '\u{1315}', IdentifierType::Recommended),
- ('\u{1318}', '\u{131e}', IdentifierType::Recommended), ('\u{131f}', '\u{131f}',
- IdentifierType::Recommended), ('\u{1320}', '\u{1346}', IdentifierType::Recommended),
- ('\u{1347}', '\u{1347}', IdentifierType::Recommended), ('\u{1348}', '\u{135a}',
- IdentifierType::Recommended), ('\u{135d}', '\u{135e}', IdentifierType::Recommended),
- ('\u{135f}', '\u{135f}', IdentifierType::Recommended), ('\u{1360}', '\u{1360}',
- IdentifierType::Not_XID), ('\u{1361}', '\u{1368}', IdentifierType::Not_XID), ('\u{1369}',
- '\u{1371}', IdentifierType::Obsolete), ('\u{1372}', '\u{137c}', IdentifierType::Not_XID),
- ('\u{1380}', '\u{138f}', IdentifierType::Recommended), ('\u{1390}', '\u{1399}',
- IdentifierType::Not_XID), ('\u{13a0}', '\u{13f4}', IdentifierType::Limited_Use),
- ('\u{13f5}', '\u{13f5}', IdentifierType::Limited_Use), ('\u{13f8}', '\u{13fd}',
- IdentifierType::Limited_Use), ('\u{1400}', '\u{1400}', IdentifierType::Limited_Use),
- ('\u{1401}', '\u{166c}', IdentifierType::Limited_Use), ('\u{166d}', '\u{166e}',
- IdentifierType::Limited_Use), ('\u{166f}', '\u{1676}', IdentifierType::Limited_Use),
- ('\u{1677}', '\u{167f}', IdentifierType::Limited_Use), ('\u{1680}', '\u{1680}',
- IdentifierType::Exclusion), ('\u{1681}', '\u{169a}', IdentifierType::Exclusion),
- ('\u{169b}', '\u{169c}', IdentifierType::Exclusion), ('\u{16a0}', '\u{16ea}',
- IdentifierType::Exclusion), ('\u{16eb}', '\u{16ed}', IdentifierType::Not_XID),
- ('\u{16ee}', '\u{16f0}', IdentifierType::Exclusion), ('\u{16f1}', '\u{16f8}',
- IdentifierType::Exclusion), ('\u{1700}', '\u{170c}', IdentifierType::Exclusion),
- ('\u{170e}', '\u{1714}', IdentifierType::Exclusion), ('\u{1720}', '\u{1734}',
- IdentifierType::Exclusion), ('\u{1735}', '\u{1736}', IdentifierType::Exclusion),
- ('\u{1740}', '\u{1753}', IdentifierType::Exclusion), ('\u{1760}', '\u{176c}',
- IdentifierType::Exclusion), ('\u{176e}', '\u{1770}', IdentifierType::Exclusion),
- ('\u{1772}', '\u{1773}', IdentifierType::Exclusion), ('\u{1780}', '\u{17a2}',
- IdentifierType::Recommended), ('\u{17a3}', '\u{17a4}', IdentifierType::Deprecated),
- ('\u{17a5}', '\u{17a7}', IdentifierType::Recommended), ('\u{17a8}', '\u{17a8}',
- IdentifierType::Obsolete), ('\u{17a9}', '\u{17b3}', IdentifierType::Recommended),
- ('\u{17b4}', '\u{17b5}', IdentifierType::Default_Ignorable), ('\u{17b6}', '\u{17ca}',
- IdentifierType::Recommended), ('\u{17cb}', '\u{17d0}', IdentifierType::Technical),
- ('\u{17d1}', '\u{17d1}', IdentifierType::Technical), ('\u{17d2}', '\u{17d2}',
- IdentifierType::Recommended), ('\u{17d3}', '\u{17d3}', IdentifierType::Obsolete),
- ('\u{17d4}', '\u{17d6}', IdentifierType::Not_XID), ('\u{17d7}', '\u{17d7}',
- IdentifierType::Recommended), ('\u{17d8}', '\u{17d8}', IdentifierType::Obsolete),
- ('\u{17d9}', '\u{17db}', IdentifierType::Not_XID), ('\u{17dc}', '\u{17dc}',
- IdentifierType::Recommended), ('\u{17dd}', '\u{17dd}', IdentifierType::Technical),
- ('\u{17e0}', '\u{17e9}', IdentifierType::Recommended), ('\u{17f0}', '\u{17f9}',
- IdentifierType::Not_XID), ('\u{1800}', '\u{180a}', IdentifierType::Exclusion),
- ('\u{180b}', '\u{180d}', IdentifierType::Default_Ignorable), ('\u{180e}', '\u{180e}',
+ ('\u{ece}', '\u{ece}', IdentifierType::Recommended), ('\u{ed0}', '\u{ed9}',
+ IdentifierType::Recommended), ('\u{edc}', '\u{edd}', IdentifierType::Not_NFKC),
+ ('\u{ede}', '\u{edf}', IdentifierType::Recommended), ('\u{f00}', '\u{f00}',
+ IdentifierType::Recommended), ('\u{f01}', '\u{f0a}', IdentifierType::Not_XID), ('\u{f0b}',
+ '\u{f0b}', IdentifierType::Inclusion), ('\u{f0c}', '\u{f0c}', IdentifierType::Not_NFKC),
+ ('\u{f0d}', '\u{f17}', IdentifierType::Not_XID), ('\u{f18}', '\u{f19}',
+ IdentifierType::Technical), ('\u{f1a}', '\u{f1f}', IdentifierType::Not_XID), ('\u{f20}',
+ '\u{f29}', IdentifierType::Recommended), ('\u{f2a}', '\u{f34}', IdentifierType::Not_XID),
+ ('\u{f35}', '\u{f35}', IdentifierType::Recommended), ('\u{f36}', '\u{f36}',
+ IdentifierType::Not_XID), ('\u{f37}', '\u{f37}', IdentifierType::Recommended), ('\u{f38}',
+ '\u{f38}', IdentifierType::Not_XID), ('\u{f39}', '\u{f39}', IdentifierType::Uncommon_Use),
+ ('\u{f3a}', '\u{f3d}', IdentifierType::Not_XID), ('\u{f3e}', '\u{f42}',
+ IdentifierType::Recommended), ('\u{f43}', '\u{f43}', IdentifierType::Not_NFKC),
+ ('\u{f44}', '\u{f47}', IdentifierType::Recommended), ('\u{f49}', '\u{f4c}',
+ IdentifierType::Recommended), ('\u{f4d}', '\u{f4d}', IdentifierType::Not_NFKC),
+ ('\u{f4e}', '\u{f51}', IdentifierType::Recommended), ('\u{f52}', '\u{f52}',
+ IdentifierType::Not_NFKC), ('\u{f53}', '\u{f56}', IdentifierType::Recommended),
+ ('\u{f57}', '\u{f57}', IdentifierType::Not_NFKC), ('\u{f58}', '\u{f5b}',
+ IdentifierType::Recommended), ('\u{f5c}', '\u{f5c}', IdentifierType::Not_NFKC),
+ ('\u{f5d}', '\u{f68}', IdentifierType::Recommended), ('\u{f69}', '\u{f69}',
+ IdentifierType::Not_NFKC), ('\u{f6a}', '\u{f6a}', IdentifierType::Recommended),
+ ('\u{f6b}', '\u{f6c}', IdentifierType::Recommended), ('\u{f71}', '\u{f72}',
+ IdentifierType::Recommended), ('\u{f73}', '\u{f73}', IdentifierType::Not_NFKC),
+ ('\u{f74}', '\u{f74}', IdentifierType::Recommended), ('\u{f75}', '\u{f76}',
+ IdentifierType::Not_NFKC), ('\u{f77}', '\u{f77}', IdentifierType::Deprecated), ('\u{f78}',
+ '\u{f78}', IdentifierType::Not_NFKC), ('\u{f79}', '\u{f79}', IdentifierType::Deprecated),
+ ('\u{f7a}', '\u{f80}', IdentifierType::Recommended), ('\u{f81}', '\u{f81}',
+ IdentifierType::Not_NFKC), ('\u{f82}', '\u{f84}', IdentifierType::Recommended),
+ ('\u{f85}', '\u{f85}', IdentifierType::Not_XID), ('\u{f86}', '\u{f8b}',
+ IdentifierType::Recommended), ('\u{f8c}', '\u{f8f}', IdentifierType::Recommended),
+ ('\u{f90}', '\u{f92}', IdentifierType::Recommended), ('\u{f93}', '\u{f93}',
+ IdentifierType::Not_NFKC), ('\u{f94}', '\u{f95}', IdentifierType::Recommended),
+ ('\u{f96}', '\u{f96}', IdentifierType::Recommended), ('\u{f97}', '\u{f97}',
+ IdentifierType::Recommended), ('\u{f99}', '\u{f9c}', IdentifierType::Recommended),
+ ('\u{f9d}', '\u{f9d}', IdentifierType::Not_NFKC), ('\u{f9e}', '\u{fa1}',
+ IdentifierType::Recommended), ('\u{fa2}', '\u{fa2}', IdentifierType::Not_NFKC),
+ ('\u{fa3}', '\u{fa6}', IdentifierType::Recommended), ('\u{fa7}', '\u{fa7}',
+ IdentifierType::Not_NFKC), ('\u{fa8}', '\u{fab}', IdentifierType::Recommended),
+ ('\u{fac}', '\u{fac}', IdentifierType::Not_NFKC), ('\u{fad}', '\u{fad}',
+ IdentifierType::Recommended), ('\u{fae}', '\u{fb0}', IdentifierType::Recommended),
+ ('\u{fb1}', '\u{fb7}', IdentifierType::Recommended), ('\u{fb8}', '\u{fb8}',
+ IdentifierType::Recommended), ('\u{fb9}', '\u{fb9}', IdentifierType::Not_NFKC),
+ ('\u{fba}', '\u{fbc}', IdentifierType::Recommended), ('\u{fbe}', '\u{fc5}',
+ IdentifierType::Not_XID), ('\u{fc6}', '\u{fc6}', IdentifierType::Recommended), ('\u{fc7}',
+ '\u{fcc}', IdentifierType::Not_XID), ('\u{fce}', '\u{fce}', IdentifierType::Not_XID),
+ ('\u{fcf}', '\u{fcf}', IdentifierType::Not_XID), ('\u{fd0}', '\u{fd1}',
+ IdentifierType::Not_XID), ('\u{fd2}', '\u{fd4}', IdentifierType::Not_XID), ('\u{fd5}',
+ '\u{fd8}', IdentifierType::Not_XID), ('\u{fd9}', '\u{fda}', IdentifierType::Not_XID),
+ ('\u{1000}', '\u{1021}', IdentifierType::Recommended), ('\u{1022}', '\u{1022}',
+ IdentifierType::Recommended), ('\u{1023}', '\u{1027}', IdentifierType::Recommended),
+ ('\u{1028}', '\u{1028}', IdentifierType::Recommended), ('\u{1029}', '\u{102a}',
+ IdentifierType::Recommended), ('\u{102b}', '\u{102b}', IdentifierType::Recommended),
+ ('\u{102c}', '\u{1032}', IdentifierType::Recommended), ('\u{1033}', '\u{1035}',
+ IdentifierType::Recommended), ('\u{1036}', '\u{1039}', IdentifierType::Recommended),
+ ('\u{103a}', '\u{103f}', IdentifierType::Recommended), ('\u{1040}', '\u{1049}',
+ IdentifierType::Recommended), ('\u{104a}', '\u{104f}', IdentifierType::Not_XID),
+ ('\u{1050}', '\u{1059}', IdentifierType::Recommended), ('\u{105a}', '\u{1099}',
+ IdentifierType::Recommended), ('\u{109a}', '\u{109d}', IdentifierType::Recommended),
+ ('\u{109e}', '\u{109f}', IdentifierType::Not_XID), ('\u{10a0}', '\u{10c5}',
+ IdentifierType::Obsolete), ('\u{10c7}', '\u{10c7}', IdentifierType::Recommended),
+ ('\u{10cd}', '\u{10cd}', IdentifierType::Recommended), ('\u{10d0}', '\u{10f0}',
+ IdentifierType::Recommended), ('\u{10f1}', '\u{10f6}', IdentifierType::Obsolete),
+ ('\u{10f7}', '\u{10f8}', IdentifierType::Recommended), ('\u{10f9}', '\u{10fa}',
+ IdentifierType::Recommended), ('\u{10fb}', '\u{10fb}', IdentifierType::Not_XID),
+ ('\u{10fc}', '\u{10fc}', IdentifierType::Not_NFKC), ('\u{10fd}', '\u{10ff}',
+ IdentifierType::Recommended), ('\u{1100}', '\u{1159}', IdentifierType::Obsolete),
+ ('\u{115a}', '\u{115e}', IdentifierType::Obsolete), ('\u{115f}', '\u{1160}',
+ IdentifierType::Default_Ignorable), ('\u{1161}', '\u{11a2}', IdentifierType::Obsolete),
+ ('\u{11a3}', '\u{11a7}', IdentifierType::Obsolete), ('\u{11a8}', '\u{11f9}',
+ IdentifierType::Obsolete), ('\u{11fa}', '\u{11ff}', IdentifierType::Obsolete),
+ ('\u{1200}', '\u{1206}', IdentifierType::Recommended), ('\u{1207}', '\u{1207}',
+ IdentifierType::Recommended), ('\u{1208}', '\u{1246}', IdentifierType::Recommended),
+ ('\u{1247}', '\u{1247}', IdentifierType::Recommended), ('\u{1248}', '\u{1248}',
+ IdentifierType::Recommended), ('\u{124a}', '\u{124d}', IdentifierType::Recommended),
+ ('\u{1250}', '\u{1256}', IdentifierType::Recommended), ('\u{1258}', '\u{1258}',
+ IdentifierType::Recommended), ('\u{125a}', '\u{125d}', IdentifierType::Recommended),
+ ('\u{1260}', '\u{1286}', IdentifierType::Recommended), ('\u{1287}', '\u{1287}',
+ IdentifierType::Recommended), ('\u{1288}', '\u{1288}', IdentifierType::Recommended),
+ ('\u{128a}', '\u{128d}', IdentifierType::Recommended), ('\u{1290}', '\u{12ae}',
+ IdentifierType::Recommended), ('\u{12af}', '\u{12af}', IdentifierType::Recommended),
+ ('\u{12b0}', '\u{12b0}', IdentifierType::Recommended), ('\u{12b2}', '\u{12b5}',
+ IdentifierType::Recommended), ('\u{12b8}', '\u{12be}', IdentifierType::Recommended),
+ ('\u{12c0}', '\u{12c0}', IdentifierType::Recommended), ('\u{12c2}', '\u{12c5}',
+ IdentifierType::Recommended), ('\u{12c8}', '\u{12ce}', IdentifierType::Recommended),
+ ('\u{12cf}', '\u{12cf}', IdentifierType::Recommended), ('\u{12d0}', '\u{12d6}',
+ IdentifierType::Recommended), ('\u{12d8}', '\u{12ee}', IdentifierType::Recommended),
+ ('\u{12ef}', '\u{12ef}', IdentifierType::Recommended), ('\u{12f0}', '\u{130e}',
+ IdentifierType::Recommended), ('\u{130f}', '\u{130f}', IdentifierType::Recommended),
+ ('\u{1310}', '\u{1310}', IdentifierType::Recommended), ('\u{1312}', '\u{1315}',
+ IdentifierType::Recommended), ('\u{1318}', '\u{131e}', IdentifierType::Recommended),
+ ('\u{131f}', '\u{131f}', IdentifierType::Recommended), ('\u{1320}', '\u{1346}',
+ IdentifierType::Recommended), ('\u{1347}', '\u{1347}', IdentifierType::Recommended),
+ ('\u{1348}', '\u{135a}', IdentifierType::Recommended), ('\u{135d}', '\u{135e}',
+ IdentifierType::Recommended), ('\u{135f}', '\u{135f}', IdentifierType::Recommended),
+ ('\u{1360}', '\u{1360}', IdentifierType::Not_XID), ('\u{1361}', '\u{1368}',
+ IdentifierType::Not_XID), ('\u{1369}', '\u{1371}', IdentifierType::Obsolete), ('\u{1372}',
+ '\u{137c}', IdentifierType::Not_XID), ('\u{1380}', '\u{138f}',
+ IdentifierType::Recommended), ('\u{1390}', '\u{1399}', IdentifierType::Not_XID),
+ ('\u{13a0}', '\u{13f4}', IdentifierType::Limited_Use), ('\u{13f5}', '\u{13f5}',
+ IdentifierType::Limited_Use), ('\u{13f8}', '\u{13fd}', IdentifierType::Limited_Use),
+ ('\u{1400}', '\u{1400}', IdentifierType::Limited_Use), ('\u{1401}', '\u{166c}',
+ IdentifierType::Limited_Use), ('\u{166d}', '\u{166e}', IdentifierType::Limited_Use),
+ ('\u{166f}', '\u{1676}', IdentifierType::Limited_Use), ('\u{1677}', '\u{167f}',
+ IdentifierType::Limited_Use), ('\u{1680}', '\u{1680}', IdentifierType::Exclusion),
+ ('\u{1681}', '\u{169a}', IdentifierType::Exclusion), ('\u{169b}', '\u{169c}',
+ IdentifierType::Exclusion), ('\u{16a0}', '\u{16ea}', IdentifierType::Exclusion),
+ ('\u{16eb}', '\u{16ed}', IdentifierType::Not_XID), ('\u{16ee}', '\u{16f0}',
+ IdentifierType::Exclusion), ('\u{16f1}', '\u{16f8}', IdentifierType::Exclusion),
+ ('\u{1700}', '\u{170c}', IdentifierType::Exclusion), ('\u{170d}', '\u{170d}',
+ IdentifierType::Exclusion), ('\u{170e}', '\u{1714}', IdentifierType::Exclusion),
+ ('\u{1715}', '\u{1715}', IdentifierType::Exclusion), ('\u{171f}', '\u{171f}',
+ IdentifierType::Exclusion), ('\u{1720}', '\u{1734}', IdentifierType::Exclusion),
+ ('\u{1735}', '\u{1736}', IdentifierType::Exclusion), ('\u{1740}', '\u{1753}',
+ IdentifierType::Exclusion), ('\u{1760}', '\u{176c}', IdentifierType::Exclusion),
+ ('\u{176e}', '\u{1770}', IdentifierType::Exclusion), ('\u{1772}', '\u{1773}',
+ IdentifierType::Exclusion), ('\u{1780}', '\u{17a2}', IdentifierType::Recommended),
+ ('\u{17a3}', '\u{17a4}', IdentifierType::Deprecated), ('\u{17a5}', '\u{17a7}',
+ IdentifierType::Recommended), ('\u{17a8}', '\u{17a8}', IdentifierType::Obsolete),
+ ('\u{17a9}', '\u{17b3}', IdentifierType::Recommended), ('\u{17b4}', '\u{17b5}',
+ IdentifierType::Default_Ignorable), ('\u{17b6}', '\u{17cd}', IdentifierType::Recommended),
+ ('\u{17ce}', '\u{17cf}', IdentifierType::Technical), ('\u{17d0}', '\u{17d0}',
+ IdentifierType::Recommended), ('\u{17d1}', '\u{17d1}', IdentifierType::Technical),
+ ('\u{17d2}', '\u{17d2}', IdentifierType::Recommended), ('\u{17d3}', '\u{17d3}',
+ IdentifierType::Obsolete), ('\u{17d4}', '\u{17d6}', IdentifierType::Not_XID), ('\u{17d7}',
+ '\u{17d7}', IdentifierType::Recommended), ('\u{17d8}', '\u{17d8}',
+ IdentifierType::Obsolete), ('\u{17d9}', '\u{17db}', IdentifierType::Not_XID), ('\u{17dc}',
+ '\u{17dc}', IdentifierType::Recommended), ('\u{17dd}', '\u{17dd}',
+ IdentifierType::Technical), ('\u{17e0}', '\u{17e9}', IdentifierType::Recommended),
+ ('\u{17f0}', '\u{17f9}', IdentifierType::Not_XID), ('\u{1800}', '\u{180a}',
+ IdentifierType::Exclusion), ('\u{180b}', '\u{180d}', IdentifierType::Default_Ignorable),
+ ('\u{180e}', '\u{180e}', IdentifierType::Default_Ignorable), ('\u{180f}', '\u{180f}',
IdentifierType::Default_Ignorable), ('\u{1810}', '\u{1819}', IdentifierType::Exclusion),
('\u{1820}', '\u{1877}', IdentifierType::Exclusion), ('\u{1878}', '\u{1878}',
IdentifierType::Exclusion), ('\u{1880}', '\u{18a8}', IdentifierType::Exclusion),
@@ -812,9 +832,11 @@ pub mod identifier {
IdentifierType::Limited_Use), ('\u{1aa8}', '\u{1aad}', IdentifierType::Limited_Use),
('\u{1ab0}', '\u{1abd}', IdentifierType::Obsolete), ('\u{1abe}', '\u{1abe}',
IdentifierType::Not_XID), ('\u{1abf}', '\u{1ac0}', IdentifierType::Technical),
- ('\u{1b00}', '\u{1b4b}', IdentifierType::Limited_Use), ('\u{1b50}', '\u{1b59}',
- IdentifierType::Limited_Use), ('\u{1b5a}', '\u{1b6a}', IdentifierType::Limited_Use),
- ('\u{1b6b}', '\u{1b73}', IdentifierType::Limited_Use), ('\u{1b74}', '\u{1b7c}',
+ ('\u{1ac1}', '\u{1ace}', IdentifierType::Uncommon_Use), ('\u{1b00}', '\u{1b4b}',
+ IdentifierType::Limited_Use), ('\u{1b4c}', '\u{1b4c}', IdentifierType::Limited_Use),
+ ('\u{1b50}', '\u{1b59}', IdentifierType::Limited_Use), ('\u{1b5a}', '\u{1b6a}',
+ IdentifierType::Limited_Use), ('\u{1b6b}', '\u{1b73}', IdentifierType::Limited_Use),
+ ('\u{1b74}', '\u{1b7c}', IdentifierType::Limited_Use), ('\u{1b7d}', '\u{1b7e}',
IdentifierType::Limited_Use), ('\u{1b80}', '\u{1baa}', IdentifierType::Limited_Use),
('\u{1bab}', '\u{1bad}', IdentifierType::Limited_Use), ('\u{1bae}', '\u{1bb9}',
IdentifierType::Limited_Use), ('\u{1bba}', '\u{1bbf}', IdentifierType::Limited_Use),
@@ -844,74 +866,73 @@ pub mod identifier {
IdentifierType::Technical), ('\u{1dcf}', '\u{1dd0}', IdentifierType::Technical),
('\u{1dd1}', '\u{1de6}', IdentifierType::Technical), ('\u{1de7}', '\u{1df5}',
IdentifierType::Technical), ('\u{1df6}', '\u{1df9}', IdentifierType::Technical),
- ('\u{1dfb}', '\u{1dfb}', IdentifierType::Technical), ('\u{1dfc}', '\u{1dfc}',
- IdentifierType::Technical), ('\u{1dfd}', '\u{1dfd}', IdentifierType::Technical),
- ('\u{1dfe}', '\u{1dff}', IdentifierType::Technical), ('\u{1e00}', '\u{1e99}',
- IdentifierType::Recommended), ('\u{1e9a}', '\u{1e9a}', IdentifierType::Not_NFKC),
- ('\u{1e9b}', '\u{1e9b}', IdentifierType::Not_NFKC), ('\u{1e9c}', '\u{1e9d}',
- IdentifierType::Technical), ('\u{1e9e}', '\u{1e9e}', IdentifierType::Recommended),
- ('\u{1e9f}', '\u{1e9f}', IdentifierType::Technical), ('\u{1ea0}', '\u{1ef9}',
- IdentifierType::Recommended), ('\u{1efa}', '\u{1eff}', IdentifierType::Technical),
- ('\u{1f00}', '\u{1f15}', IdentifierType::Recommended), ('\u{1f18}', '\u{1f1d}',
- IdentifierType::Recommended), ('\u{1f20}', '\u{1f45}', IdentifierType::Recommended),
- ('\u{1f48}', '\u{1f4d}', IdentifierType::Recommended), ('\u{1f50}', '\u{1f57}',
- IdentifierType::Recommended), ('\u{1f59}', '\u{1f59}', IdentifierType::Recommended),
- ('\u{1f5b}', '\u{1f5b}', IdentifierType::Recommended), ('\u{1f5d}', '\u{1f5d}',
- IdentifierType::Recommended), ('\u{1f5f}', '\u{1f70}', IdentifierType::Recommended),
- ('\u{1f71}', '\u{1f71}', IdentifierType::Not_NFKC), ('\u{1f72}', '\u{1f72}',
- IdentifierType::Recommended), ('\u{1f73}', '\u{1f73}', IdentifierType::Not_NFKC),
- ('\u{1f74}', '\u{1f74}', IdentifierType::Recommended), ('\u{1f75}', '\u{1f75}',
- IdentifierType::Not_NFKC), ('\u{1f76}', '\u{1f76}', IdentifierType::Recommended),
- ('\u{1f77}', '\u{1f77}', IdentifierType::Not_NFKC), ('\u{1f78}', '\u{1f78}',
- IdentifierType::Recommended), ('\u{1f79}', '\u{1f79}', IdentifierType::Not_NFKC),
- ('\u{1f7a}', '\u{1f7a}', IdentifierType::Recommended), ('\u{1f7b}', '\u{1f7b}',
- IdentifierType::Not_NFKC), ('\u{1f7c}', '\u{1f7c}', IdentifierType::Recommended),
- ('\u{1f7d}', '\u{1f7d}', IdentifierType::Not_NFKC), ('\u{1f80}', '\u{1fb4}',
- IdentifierType::Recommended), ('\u{1fb6}', '\u{1fba}', IdentifierType::Recommended),
- ('\u{1fbb}', '\u{1fbb}', IdentifierType::Not_NFKC), ('\u{1fbc}', '\u{1fbc}',
- IdentifierType::Recommended), ('\u{1fbd}', '\u{1fc1}', IdentifierType::Not_NFKC),
- ('\u{1fc2}', '\u{1fc4}', IdentifierType::Recommended), ('\u{1fc6}', '\u{1fc8}',
- IdentifierType::Recommended), ('\u{1fc9}', '\u{1fc9}', IdentifierType::Not_NFKC),
- ('\u{1fca}', '\u{1fca}', IdentifierType::Recommended), ('\u{1fcb}', '\u{1fcb}',
- IdentifierType::Not_NFKC), ('\u{1fcc}', '\u{1fcc}', IdentifierType::Recommended),
- ('\u{1fcd}', '\u{1fcf}', IdentifierType::Not_NFKC), ('\u{1fd0}', '\u{1fd2}',
- IdentifierType::Recommended), ('\u{1fd3}', '\u{1fd3}', IdentifierType::Not_NFKC),
- ('\u{1fd6}', '\u{1fda}', IdentifierType::Recommended), ('\u{1fdb}', '\u{1fdb}',
- IdentifierType::Not_NFKC), ('\u{1fdd}', '\u{1fdf}', IdentifierType::Not_NFKC),
- ('\u{1fe0}', '\u{1fe2}', IdentifierType::Recommended), ('\u{1fe3}', '\u{1fe3}',
- IdentifierType::Not_NFKC), ('\u{1fe4}', '\u{1fea}', IdentifierType::Recommended),
- ('\u{1feb}', '\u{1feb}', IdentifierType::Not_NFKC), ('\u{1fec}', '\u{1fec}',
- IdentifierType::Recommended), ('\u{1fed}', '\u{1fef}', IdentifierType::Not_NFKC),
- ('\u{1ff2}', '\u{1ff4}', IdentifierType::Recommended), ('\u{1ff6}', '\u{1ff8}',
- IdentifierType::Recommended), ('\u{1ff9}', '\u{1ff9}', IdentifierType::Not_NFKC),
- ('\u{1ffa}', '\u{1ffa}', IdentifierType::Recommended), ('\u{1ffb}', '\u{1ffb}',
- IdentifierType::Not_NFKC), ('\u{1ffc}', '\u{1ffc}', IdentifierType::Recommended),
- ('\u{1ffd}', '\u{1ffe}', IdentifierType::Not_NFKC), ('\u{2000}', '\u{200a}',
- IdentifierType::Not_NFKC), ('\u{200b}', '\u{200b}', IdentifierType::Default_Ignorable),
- ('\u{200c}', '\u{200d}', IdentifierType::Inclusion), ('\u{200e}', '\u{200f}',
- IdentifierType::Default_Ignorable), ('\u{2010}', '\u{2010}', IdentifierType::Inclusion),
- ('\u{2011}', '\u{2011}', IdentifierType::Not_NFKC), ('\u{2012}', '\u{2016}',
- IdentifierType::Not_XID), ('\u{2017}', '\u{2017}', IdentifierType::Not_NFKC), ('\u{2018}',
- '\u{2018}', IdentifierType::Not_XID), ('\u{2019}', '\u{2019}', IdentifierType::Inclusion),
- ('\u{201a}', '\u{2023}', IdentifierType::Not_XID), ('\u{2024}', '\u{2026}',
- IdentifierType::Not_NFKC), ('\u{2027}', '\u{2027}', IdentifierType::Inclusion),
- ('\u{2028}', '\u{2029}', IdentifierType::Not_XID), ('\u{202a}', '\u{202e}',
- IdentifierType::Default_Ignorable), ('\u{202f}', '\u{202f}', IdentifierType::Not_NFKC),
- ('\u{2030}', '\u{2032}', IdentifierType::Not_XID), ('\u{2033}', '\u{2034}',
- IdentifierType::Not_NFKC), ('\u{2035}', '\u{2035}', IdentifierType::Not_XID), ('\u{2036}',
- '\u{2037}', IdentifierType::Not_NFKC), ('\u{2038}', '\u{203b}', IdentifierType::Not_XID),
- ('\u{203c}', '\u{203c}', IdentifierType::Not_NFKC), ('\u{203d}', '\u{203d}',
- IdentifierType::Not_XID), ('\u{203e}', '\u{203e}', IdentifierType::Not_NFKC), ('\u{203f}',
- '\u{2040}', IdentifierType::Technical), ('\u{2041}', '\u{2046}', IdentifierType::Not_XID),
- ('\u{2047}', '\u{2047}', IdentifierType::Not_NFKC), ('\u{2048}', '\u{2049}',
- IdentifierType::Not_NFKC), ('\u{204a}', '\u{204d}', IdentifierType::Not_XID), ('\u{204e}',
- '\u{2052}', IdentifierType::Not_XID), ('\u{2053}', '\u{2053}', IdentifierType::Not_XID),
- ('\u{2054}', '\u{2054}', IdentifierType::Uncommon_Use), ('\u{2055}', '\u{2055}',
- IdentifierType::Not_XID), ('\u{2056}', '\u{2056}', IdentifierType::Obsolete), ('\u{2057}',
- '\u{2057}', IdentifierType::Not_NFKC), ('\u{2058}', '\u{205e}', IdentifierType::Obsolete),
- ('\u{205f}', '\u{205f}', IdentifierType::Not_NFKC), ('\u{2060}', '\u{2063}',
- IdentifierType::Default_Ignorable), ('\u{2064}', '\u{2064}',
- IdentifierType::Default_Ignorable), ('\u{2066}', '\u{2069}',
+ ('\u{1dfa}', '\u{1dfa}', IdentifierType::Limited_Use), ('\u{1dfb}', '\u{1dfb}',
+ IdentifierType::Technical), ('\u{1dfc}', '\u{1dfc}', IdentifierType::Technical),
+ ('\u{1dfd}', '\u{1dfd}', IdentifierType::Technical), ('\u{1dfe}', '\u{1dff}',
+ IdentifierType::Technical), ('\u{1e00}', '\u{1e99}', IdentifierType::Recommended),
+ ('\u{1e9a}', '\u{1e9a}', IdentifierType::Not_NFKC), ('\u{1e9b}', '\u{1e9b}',
+ IdentifierType::Not_NFKC), ('\u{1e9c}', '\u{1e9d}', IdentifierType::Technical),
+ ('\u{1e9e}', '\u{1e9e}', IdentifierType::Recommended), ('\u{1e9f}', '\u{1e9f}',
+ IdentifierType::Technical), ('\u{1ea0}', '\u{1ef9}', IdentifierType::Recommended),
+ ('\u{1efa}', '\u{1eff}', IdentifierType::Technical), ('\u{1f00}', '\u{1f15}',
+ IdentifierType::Recommended), ('\u{1f18}', '\u{1f1d}', IdentifierType::Recommended),
+ ('\u{1f20}', '\u{1f45}', IdentifierType::Recommended), ('\u{1f48}', '\u{1f4d}',
+ IdentifierType::Recommended), ('\u{1f50}', '\u{1f57}', IdentifierType::Recommended),
+ ('\u{1f59}', '\u{1f59}', IdentifierType::Recommended), ('\u{1f5b}', '\u{1f5b}',
+ IdentifierType::Recommended), ('\u{1f5d}', '\u{1f5d}', IdentifierType::Recommended),
+ ('\u{1f5f}', '\u{1f70}', IdentifierType::Recommended), ('\u{1f71}', '\u{1f71}',
+ IdentifierType::Not_NFKC), ('\u{1f72}', '\u{1f72}', IdentifierType::Recommended),
+ ('\u{1f73}', '\u{1f73}', IdentifierType::Not_NFKC), ('\u{1f74}', '\u{1f74}',
+ IdentifierType::Recommended), ('\u{1f75}', '\u{1f75}', IdentifierType::Not_NFKC),
+ ('\u{1f76}', '\u{1f76}', IdentifierType::Recommended), ('\u{1f77}', '\u{1f77}',
+ IdentifierType::Not_NFKC), ('\u{1f78}', '\u{1f78}', IdentifierType::Recommended),
+ ('\u{1f79}', '\u{1f79}', IdentifierType::Not_NFKC), ('\u{1f7a}', '\u{1f7a}',
+ IdentifierType::Recommended), ('\u{1f7b}', '\u{1f7b}', IdentifierType::Not_NFKC),
+ ('\u{1f7c}', '\u{1f7c}', IdentifierType::Recommended), ('\u{1f7d}', '\u{1f7d}',
+ IdentifierType::Not_NFKC), ('\u{1f80}', '\u{1fb4}', IdentifierType::Recommended),
+ ('\u{1fb6}', '\u{1fba}', IdentifierType::Recommended), ('\u{1fbb}', '\u{1fbb}',
+ IdentifierType::Not_NFKC), ('\u{1fbc}', '\u{1fbc}', IdentifierType::Recommended),
+ ('\u{1fbd}', '\u{1fc1}', IdentifierType::Not_NFKC), ('\u{1fc2}', '\u{1fc4}',
+ IdentifierType::Recommended), ('\u{1fc6}', '\u{1fc8}', IdentifierType::Recommended),
+ ('\u{1fc9}', '\u{1fc9}', IdentifierType::Not_NFKC), ('\u{1fca}', '\u{1fca}',
+ IdentifierType::Recommended), ('\u{1fcb}', '\u{1fcb}', IdentifierType::Not_NFKC),
+ ('\u{1fcc}', '\u{1fcc}', IdentifierType::Recommended), ('\u{1fcd}', '\u{1fcf}',
+ IdentifierType::Not_NFKC), ('\u{1fd0}', '\u{1fd2}', IdentifierType::Recommended),
+ ('\u{1fd3}', '\u{1fd3}', IdentifierType::Not_NFKC), ('\u{1fd6}', '\u{1fda}',
+ IdentifierType::Recommended), ('\u{1fdb}', '\u{1fdb}', IdentifierType::Not_NFKC),
+ ('\u{1fdd}', '\u{1fdf}', IdentifierType::Not_NFKC), ('\u{1fe0}', '\u{1fe2}',
+ IdentifierType::Recommended), ('\u{1fe3}', '\u{1fe3}', IdentifierType::Not_NFKC),
+ ('\u{1fe4}', '\u{1fea}', IdentifierType::Recommended), ('\u{1feb}', '\u{1feb}',
+ IdentifierType::Not_NFKC), ('\u{1fec}', '\u{1fec}', IdentifierType::Recommended),
+ ('\u{1fed}', '\u{1fef}', IdentifierType::Not_NFKC), ('\u{1ff2}', '\u{1ff4}',
+ IdentifierType::Recommended), ('\u{1ff6}', '\u{1ff8}', IdentifierType::Recommended),
+ ('\u{1ff9}', '\u{1ff9}', IdentifierType::Not_NFKC), ('\u{1ffa}', '\u{1ffa}',
+ IdentifierType::Recommended), ('\u{1ffb}', '\u{1ffb}', IdentifierType::Not_NFKC),
+ ('\u{1ffc}', '\u{1ffc}', IdentifierType::Recommended), ('\u{1ffd}', '\u{1ffe}',
+ IdentifierType::Not_NFKC), ('\u{2000}', '\u{200a}', IdentifierType::Not_NFKC),
+ ('\u{200b}', '\u{200f}', IdentifierType::Default_Ignorable), ('\u{2010}', '\u{2010}',
+ IdentifierType::Inclusion), ('\u{2011}', '\u{2011}', IdentifierType::Not_NFKC),
+ ('\u{2012}', '\u{2016}', IdentifierType::Not_XID), ('\u{2017}', '\u{2017}',
+ IdentifierType::Not_NFKC), ('\u{2018}', '\u{2018}', IdentifierType::Not_XID), ('\u{2019}',
+ '\u{2019}', IdentifierType::Inclusion), ('\u{201a}', '\u{2023}', IdentifierType::Not_XID),
+ ('\u{2024}', '\u{2026}', IdentifierType::Not_NFKC), ('\u{2027}', '\u{2027}',
+ IdentifierType::Inclusion), ('\u{2028}', '\u{2029}', IdentifierType::Not_XID),
+ ('\u{202a}', '\u{202e}', IdentifierType::Default_Ignorable), ('\u{202f}', '\u{202f}',
+ IdentifierType::Not_NFKC), ('\u{2030}', '\u{2032}', IdentifierType::Not_XID), ('\u{2033}',
+ '\u{2034}', IdentifierType::Not_NFKC), ('\u{2035}', '\u{2035}', IdentifierType::Not_XID),
+ ('\u{2036}', '\u{2037}', IdentifierType::Not_NFKC), ('\u{2038}', '\u{203b}',
+ IdentifierType::Not_XID), ('\u{203c}', '\u{203c}', IdentifierType::Not_NFKC), ('\u{203d}',
+ '\u{203d}', IdentifierType::Not_XID), ('\u{203e}', '\u{203e}', IdentifierType::Not_NFKC),
+ ('\u{203f}', '\u{2040}', IdentifierType::Technical), ('\u{2041}', '\u{2046}',
+ IdentifierType::Not_XID), ('\u{2047}', '\u{2047}', IdentifierType::Not_NFKC), ('\u{2048}',
+ '\u{2049}', IdentifierType::Not_NFKC), ('\u{204a}', '\u{204d}', IdentifierType::Not_XID),
+ ('\u{204e}', '\u{2052}', IdentifierType::Not_XID), ('\u{2053}', '\u{2053}',
+ IdentifierType::Not_XID), ('\u{2054}', '\u{2054}', IdentifierType::Uncommon_Use),
+ ('\u{2055}', '\u{2055}', IdentifierType::Not_XID), ('\u{2056}', '\u{2056}',
+ IdentifierType::Obsolete), ('\u{2057}', '\u{2057}', IdentifierType::Not_NFKC),
+ ('\u{2058}', '\u{205e}', IdentifierType::Obsolete), ('\u{205f}', '\u{205f}',
+ IdentifierType::Not_NFKC), ('\u{2060}', '\u{2063}', IdentifierType::Default_Ignorable),
+ ('\u{2064}', '\u{2064}', IdentifierType::Default_Ignorable), ('\u{2066}', '\u{2069}',
IdentifierType::Default_Ignorable), ('\u{206a}', '\u{206f}', IdentifierType::Deprecated),
('\u{2070}', '\u{2070}', IdentifierType::Not_NFKC), ('\u{2071}', '\u{2071}',
IdentifierType::Not_NFKC), ('\u{2074}', '\u{208e}', IdentifierType::Not_NFKC),
@@ -924,18 +945,19 @@ pub mod identifier {
('\u{20b6}', '\u{20b8}', IdentifierType::Not_XID), ('\u{20b9}', '\u{20b9}',
IdentifierType::Not_XID), ('\u{20ba}', '\u{20ba}', IdentifierType::Not_XID), ('\u{20bb}',
'\u{20bd}', IdentifierType::Not_XID), ('\u{20be}', '\u{20be}', IdentifierType::Not_XID),
- ('\u{20bf}', '\u{20bf}', IdentifierType::Not_XID), ('\u{20d0}', '\u{20dc}',
- IdentifierType::Technical), ('\u{20dd}', '\u{20e0}', IdentifierType::Technical),
- ('\u{20e1}', '\u{20e1}', IdentifierType::Technical), ('\u{20e2}', '\u{20e3}',
- IdentifierType::Technical), ('\u{20e4}', '\u{20e4}', IdentifierType::Technical),
- ('\u{20e5}', '\u{20ea}', IdentifierType::Technical), ('\u{20eb}', '\u{20eb}',
- IdentifierType::Technical), ('\u{20ec}', '\u{20ef}', IdentifierType::Technical),
- ('\u{20f0}', '\u{20f0}', IdentifierType::Technical), ('\u{2100}', '\u{2103}',
- IdentifierType::Not_NFKC), ('\u{2104}', '\u{2104}', IdentifierType::Not_XID), ('\u{2105}',
- '\u{2107}', IdentifierType::Not_NFKC), ('\u{2108}', '\u{2108}', IdentifierType::Not_XID),
- ('\u{2109}', '\u{2113}', IdentifierType::Not_NFKC), ('\u{2114}', '\u{2114}',
- IdentifierType::Not_XID), ('\u{2115}', '\u{2116}', IdentifierType::Not_NFKC), ('\u{2117}',
- '\u{2117}', IdentifierType::Not_XID), ('\u{2118}', '\u{2118}', IdentifierType::Technical),
+ ('\u{20bf}', '\u{20bf}', IdentifierType::Not_XID), ('\u{20c0}', '\u{20c0}',
+ IdentifierType::Not_XID), ('\u{20d0}', '\u{20dc}', IdentifierType::Technical),
+ ('\u{20dd}', '\u{20e0}', IdentifierType::Technical), ('\u{20e1}', '\u{20e1}',
+ IdentifierType::Technical), ('\u{20e2}', '\u{20e3}', IdentifierType::Technical),
+ ('\u{20e4}', '\u{20e4}', IdentifierType::Technical), ('\u{20e5}', '\u{20ea}',
+ IdentifierType::Technical), ('\u{20eb}', '\u{20eb}', IdentifierType::Technical),
+ ('\u{20ec}', '\u{20ef}', IdentifierType::Technical), ('\u{20f0}', '\u{20f0}',
+ IdentifierType::Technical), ('\u{2100}', '\u{2103}', IdentifierType::Not_NFKC),
+ ('\u{2104}', '\u{2104}', IdentifierType::Not_XID), ('\u{2105}', '\u{2107}',
+ IdentifierType::Not_NFKC), ('\u{2108}', '\u{2108}', IdentifierType::Not_XID), ('\u{2109}',
+ '\u{2113}', IdentifierType::Not_NFKC), ('\u{2114}', '\u{2114}', IdentifierType::Not_XID),
+ ('\u{2115}', '\u{2116}', IdentifierType::Not_NFKC), ('\u{2117}', '\u{2117}',
+ IdentifierType::Not_XID), ('\u{2118}', '\u{2118}', IdentifierType::Technical),
('\u{2119}', '\u{211d}', IdentifierType::Not_NFKC), ('\u{211e}', '\u{211f}',
IdentifierType::Not_XID), ('\u{2120}', '\u{2122}', IdentifierType::Not_NFKC), ('\u{2123}',
'\u{2123}', IdentifierType::Not_XID), ('\u{2124}', '\u{2124}', IdentifierType::Not_NFKC),
@@ -1036,42 +1058,44 @@ pub mod identifier {
'\u{2bd2}', IdentifierType::Not_XID), ('\u{2bd3}', '\u{2beb}', IdentifierType::Not_XID),
('\u{2bec}', '\u{2bef}', IdentifierType::Uncommon_Use), ('\u{2bf0}', '\u{2bfe}',
IdentifierType::Not_XID), ('\u{2bff}', '\u{2bff}', IdentifierType::Not_XID), ('\u{2c00}',
- '\u{2c2e}', IdentifierType::Exclusion), ('\u{2c30}', '\u{2c5e}',
- IdentifierType::Exclusion), ('\u{2c60}', '\u{2c67}', IdentifierType::Technical),
- ('\u{2c68}', '\u{2c6c}', IdentifierType::Uncommon_Use), ('\u{2c6d}', '\u{2c6f}',
- IdentifierType::Obsolete), ('\u{2c70}', '\u{2c70}', IdentifierType::Obsolete),
- ('\u{2c71}', '\u{2c73}', IdentifierType::Obsolete), ('\u{2c74}', '\u{2c76}',
- IdentifierType::Obsolete), ('\u{2c77}', '\u{2c77}', IdentifierType::Technical),
- ('\u{2c78}', '\u{2c7b}', IdentifierType::Technical), ('\u{2c7c}', '\u{2c7d}',
- IdentifierType::Not_NFKC), ('\u{2c7e}', '\u{2c7f}', IdentifierType::Obsolete),
- ('\u{2c80}', '\u{2ce4}', IdentifierType::Exclusion), ('\u{2ce5}', '\u{2cea}',
- IdentifierType::Exclusion), ('\u{2ceb}', '\u{2cef}', IdentifierType::Exclusion),
- ('\u{2cf0}', '\u{2cf1}', IdentifierType::Technical), ('\u{2cf2}', '\u{2cf3}',
- IdentifierType::Exclusion), ('\u{2cf9}', '\u{2cff}', IdentifierType::Exclusion),
- ('\u{2d00}', '\u{2d25}', IdentifierType::Obsolete), ('\u{2d27}', '\u{2d27}',
- IdentifierType::Recommended), ('\u{2d2d}', '\u{2d2d}', IdentifierType::Recommended),
- ('\u{2d30}', '\u{2d65}', IdentifierType::Limited_Use), ('\u{2d66}', '\u{2d67}',
- IdentifierType::Limited_Use), ('\u{2d6f}', '\u{2d6f}', IdentifierType::Not_NFKC),
- ('\u{2d70}', '\u{2d70}', IdentifierType::Limited_Use), ('\u{2d7f}', '\u{2d7f}',
- IdentifierType::Limited_Use), ('\u{2d80}', '\u{2d96}', IdentifierType::Recommended),
- ('\u{2da0}', '\u{2da6}', IdentifierType::Recommended), ('\u{2da8}', '\u{2dae}',
- IdentifierType::Recommended), ('\u{2db0}', '\u{2db6}', IdentifierType::Recommended),
- ('\u{2db8}', '\u{2dbe}', IdentifierType::Recommended), ('\u{2dc0}', '\u{2dc6}',
- IdentifierType::Recommended), ('\u{2dc8}', '\u{2dce}', IdentifierType::Recommended),
- ('\u{2dd0}', '\u{2dd6}', IdentifierType::Recommended), ('\u{2dd8}', '\u{2dde}',
- IdentifierType::Recommended), ('\u{2de0}', '\u{2dff}', IdentifierType::Obsolete),
- ('\u{2e00}', '\u{2e0d}', IdentifierType::Technical), ('\u{2e0e}', '\u{2e16}',
- IdentifierType::Obsolete), ('\u{2e17}', '\u{2e17}', IdentifierType::Not_XID), ('\u{2e18}',
- '\u{2e1b}', IdentifierType::Not_XID), ('\u{2e1c}', '\u{2e1d}', IdentifierType::Not_XID),
- ('\u{2e1e}', '\u{2e29}', IdentifierType::Not_XID), ('\u{2e2a}', '\u{2e30}',
- IdentifierType::Obsolete), ('\u{2e31}', '\u{2e31}', IdentifierType::Obsolete),
- ('\u{2e32}', '\u{2e32}', IdentifierType::Obsolete), ('\u{2e33}', '\u{2e34}',
- IdentifierType::Not_XID), ('\u{2e35}', '\u{2e35}', IdentifierType::Obsolete), ('\u{2e36}',
- '\u{2e38}', IdentifierType::Not_XID), ('\u{2e39}', '\u{2e39}', IdentifierType::Obsolete),
- ('\u{2e3a}', '\u{2e3b}', IdentifierType::Not_XID), ('\u{2e3c}', '\u{2e42}',
- IdentifierType::Not_XID), ('\u{2e43}', '\u{2e44}', IdentifierType::Not_XID), ('\u{2e45}',
- '\u{2e49}', IdentifierType::Not_XID), ('\u{2e4a}', '\u{2e4e}', IdentifierType::Not_XID),
- ('\u{2e4f}', '\u{2e4f}', IdentifierType::Not_XID), ('\u{2e50}', '\u{2e52}',
+ '\u{2c2e}', IdentifierType::Exclusion), ('\u{2c2f}', '\u{2c2f}',
+ IdentifierType::Exclusion), ('\u{2c30}', '\u{2c5e}', IdentifierType::Exclusion),
+ ('\u{2c5f}', '\u{2c5f}', IdentifierType::Exclusion), ('\u{2c60}', '\u{2c67}',
+ IdentifierType::Technical), ('\u{2c68}', '\u{2c6c}', IdentifierType::Uncommon_Use),
+ ('\u{2c6d}', '\u{2c6f}', IdentifierType::Obsolete), ('\u{2c70}', '\u{2c70}',
+ IdentifierType::Obsolete), ('\u{2c71}', '\u{2c73}', IdentifierType::Obsolete),
+ ('\u{2c74}', '\u{2c76}', IdentifierType::Obsolete), ('\u{2c77}', '\u{2c77}',
+ IdentifierType::Technical), ('\u{2c78}', '\u{2c7b}', IdentifierType::Technical),
+ ('\u{2c7c}', '\u{2c7d}', IdentifierType::Not_NFKC), ('\u{2c7e}', '\u{2c7f}',
+ IdentifierType::Obsolete), ('\u{2c80}', '\u{2ce4}', IdentifierType::Exclusion),
+ ('\u{2ce5}', '\u{2cea}', IdentifierType::Exclusion), ('\u{2ceb}', '\u{2cef}',
+ IdentifierType::Exclusion), ('\u{2cf0}', '\u{2cf1}', IdentifierType::Technical),
+ ('\u{2cf2}', '\u{2cf3}', IdentifierType::Exclusion), ('\u{2cf9}', '\u{2cff}',
+ IdentifierType::Exclusion), ('\u{2d00}', '\u{2d25}', IdentifierType::Obsolete),
+ ('\u{2d27}', '\u{2d27}', IdentifierType::Recommended), ('\u{2d2d}', '\u{2d2d}',
+ IdentifierType::Recommended), ('\u{2d30}', '\u{2d65}', IdentifierType::Limited_Use),
+ ('\u{2d66}', '\u{2d67}', IdentifierType::Limited_Use), ('\u{2d6f}', '\u{2d6f}',
+ IdentifierType::Not_NFKC), ('\u{2d70}', '\u{2d70}', IdentifierType::Limited_Use),
+ ('\u{2d7f}', '\u{2d7f}', IdentifierType::Limited_Use), ('\u{2d80}', '\u{2d96}',
+ IdentifierType::Recommended), ('\u{2da0}', '\u{2da6}', IdentifierType::Recommended),
+ ('\u{2da8}', '\u{2dae}', IdentifierType::Recommended), ('\u{2db0}', '\u{2db6}',
+ IdentifierType::Recommended), ('\u{2db8}', '\u{2dbe}', IdentifierType::Recommended),
+ ('\u{2dc0}', '\u{2dc6}', IdentifierType::Recommended), ('\u{2dc8}', '\u{2dce}',
+ IdentifierType::Recommended), ('\u{2dd0}', '\u{2dd6}', IdentifierType::Recommended),
+ ('\u{2dd8}', '\u{2dde}', IdentifierType::Recommended), ('\u{2de0}', '\u{2dff}',
+ IdentifierType::Obsolete), ('\u{2e00}', '\u{2e0d}', IdentifierType::Technical),
+ ('\u{2e0e}', '\u{2e16}', IdentifierType::Obsolete), ('\u{2e17}', '\u{2e17}',
+ IdentifierType::Not_XID), ('\u{2e18}', '\u{2e1b}', IdentifierType::Not_XID), ('\u{2e1c}',
+ '\u{2e1d}', IdentifierType::Not_XID), ('\u{2e1e}', '\u{2e29}', IdentifierType::Not_XID),
+ ('\u{2e2a}', '\u{2e30}', IdentifierType::Obsolete), ('\u{2e31}', '\u{2e31}',
+ IdentifierType::Obsolete), ('\u{2e32}', '\u{2e32}', IdentifierType::Obsolete),
+ ('\u{2e33}', '\u{2e34}', IdentifierType::Not_XID), ('\u{2e35}', '\u{2e35}',
+ IdentifierType::Obsolete), ('\u{2e36}', '\u{2e38}', IdentifierType::Not_XID), ('\u{2e39}',
+ '\u{2e39}', IdentifierType::Obsolete), ('\u{2e3a}', '\u{2e3b}', IdentifierType::Not_XID),
+ ('\u{2e3c}', '\u{2e42}', IdentifierType::Not_XID), ('\u{2e43}', '\u{2e44}',
+ IdentifierType::Not_XID), ('\u{2e45}', '\u{2e49}', IdentifierType::Not_XID), ('\u{2e4a}',
+ '\u{2e4e}', IdentifierType::Not_XID), ('\u{2e4f}', '\u{2e4f}', IdentifierType::Not_XID),
+ ('\u{2e50}', '\u{2e52}', IdentifierType::Not_XID), ('\u{2e53}', '\u{2e5d}',
IdentifierType::Not_XID), ('\u{2e80}', '\u{2e99}', IdentifierType::Not_XID), ('\u{2e9b}',
'\u{2e9e}', IdentifierType::Not_XID), ('\u{2e9f}', '\u{2e9f}', IdentifierType::Not_NFKC),
('\u{2ea0}', '\u{2ef2}', IdentifierType::Not_XID), ('\u{2ef3}', '\u{2ef3}',
@@ -1104,11 +1128,11 @@ pub mod identifier {
IdentifierType::Recommended), ('\u{31b8}', '\u{31ba}', IdentifierType::Recommended),
('\u{31bb}', '\u{31bf}', IdentifierType::Recommended), ('\u{31c0}', '\u{31cf}',
IdentifierType::Not_XID), ('\u{31d0}', '\u{31e3}', IdentifierType::Not_XID), ('\u{31f0}',
- '\u{31ff}', IdentifierType::Technical), ('\u{3200}', '\u{321c}',
- IdentifierType::Not_NFKC), ('\u{321d}', '\u{321e}', IdentifierType::Not_NFKC),
- ('\u{3220}', '\u{3243}', IdentifierType::Not_NFKC), ('\u{3244}', '\u{3247}',
- IdentifierType::Not_NFKC), ('\u{3248}', '\u{324f}', IdentifierType::Not_XID), ('\u{3250}',
- '\u{3250}', IdentifierType::Not_NFKC), ('\u{3251}', '\u{325f}', IdentifierType::Not_NFKC),
+ '\u{31ff}', IdentifierType::Obsolete), ('\u{3200}', '\u{321c}', IdentifierType::Not_NFKC),
+ ('\u{321d}', '\u{321e}', IdentifierType::Not_NFKC), ('\u{3220}', '\u{3243}',
+ IdentifierType::Not_NFKC), ('\u{3244}', '\u{3247}', IdentifierType::Not_NFKC),
+ ('\u{3248}', '\u{324f}', IdentifierType::Not_XID), ('\u{3250}', '\u{3250}',
+ IdentifierType::Not_NFKC), ('\u{3251}', '\u{325f}', IdentifierType::Not_NFKC),
('\u{3260}', '\u{327b}', IdentifierType::Not_NFKC), ('\u{327c}', '\u{327d}',
IdentifierType::Not_NFKC), ('\u{327e}', '\u{327e}', IdentifierType::Not_NFKC),
('\u{327f}', '\u{327f}', IdentifierType::Technical), ('\u{3280}', '\u{32b0}',
@@ -1127,48 +1151,52 @@ pub mod identifier {
IdentifierType::Recommended), ('\u{9fcc}', '\u{9fcc}', IdentifierType::Recommended),
('\u{9fcd}', '\u{9fd5}', IdentifierType::Recommended), ('\u{9fd6}', '\u{9fea}',
IdentifierType::Recommended), ('\u{9feb}', '\u{9fef}', IdentifierType::Recommended),
- ('\u{9ff0}', '\u{9ffc}', IdentifierType::Recommended), ('\u{a000}', '\u{a48c}',
- IdentifierType::Limited_Use), ('\u{a490}', '\u{a4a1}', IdentifierType::Limited_Use),
- ('\u{a4a2}', '\u{a4a3}', IdentifierType::Limited_Use), ('\u{a4a4}', '\u{a4b3}',
- IdentifierType::Limited_Use), ('\u{a4b4}', '\u{a4b4}', IdentifierType::Limited_Use),
- ('\u{a4b5}', '\u{a4c0}', IdentifierType::Limited_Use), ('\u{a4c1}', '\u{a4c1}',
- IdentifierType::Limited_Use), ('\u{a4c2}', '\u{a4c4}', IdentifierType::Limited_Use),
- ('\u{a4c5}', '\u{a4c5}', IdentifierType::Limited_Use), ('\u{a4c6}', '\u{a4c6}',
- IdentifierType::Limited_Use), ('\u{a4d0}', '\u{a4fd}', IdentifierType::Limited_Use),
- ('\u{a4fe}', '\u{a4ff}', IdentifierType::Limited_Use), ('\u{a500}', '\u{a60c}',
- IdentifierType::Limited_Use), ('\u{a60d}', '\u{a60f}', IdentifierType::Limited_Use),
- ('\u{a610}', '\u{a612}', IdentifierType::Limited_Use), ('\u{a613}', '\u{a629}',
- IdentifierType::Limited_Use), ('\u{a62a}', '\u{a62b}', IdentifierType::Limited_Use),
- ('\u{a640}', '\u{a65f}', IdentifierType::Obsolete), ('\u{a660}', '\u{a661}',
- IdentifierType::Obsolete), ('\u{a662}', '\u{a66e}', IdentifierType::Obsolete),
- ('\u{a66f}', '\u{a66f}', IdentifierType::Uncommon_Use), ('\u{a670}', '\u{a673}',
- IdentifierType::Obsolete), ('\u{a674}', '\u{a67b}', IdentifierType::Obsolete),
- ('\u{a67c}', '\u{a67d}', IdentifierType::Uncommon_Use), ('\u{a67e}', '\u{a67e}',
- IdentifierType::Not_XID), ('\u{a67f}', '\u{a67f}', IdentifierType::Recommended),
- ('\u{a680}', '\u{a697}', IdentifierType::Obsolete), ('\u{a698}', '\u{a69b}',
- IdentifierType::Obsolete), ('\u{a69c}', '\u{a69d}', IdentifierType::Not_NFKC),
- ('\u{a69e}', '\u{a69e}', IdentifierType::Uncommon_Use), ('\u{a69f}', '\u{a69f}',
- IdentifierType::Obsolete), ('\u{a6a0}', '\u{a6f1}', IdentifierType::Limited_Use),
- ('\u{a6f2}', '\u{a6f7}', IdentifierType::Limited_Use), ('\u{a700}', '\u{a707}',
- IdentifierType::Obsolete), ('\u{a708}', '\u{a716}', IdentifierType::Technical),
- ('\u{a717}', '\u{a71a}', IdentifierType::Recommended), ('\u{a71b}', '\u{a71f}',
- IdentifierType::Recommended), ('\u{a720}', '\u{a721}', IdentifierType::Not_XID),
- ('\u{a722}', '\u{a72f}', IdentifierType::Technical), ('\u{a730}', '\u{a76f}',
- IdentifierType::Obsolete), ('\u{a770}', '\u{a770}', IdentifierType::Not_NFKC),
- ('\u{a771}', '\u{a787}', IdentifierType::Obsolete), ('\u{a788}', '\u{a788}',
- IdentifierType::Recommended), ('\u{a789}', '\u{a78a}', IdentifierType::Not_XID),
- ('\u{a78b}', '\u{a78c}', IdentifierType::Uncommon_Use), ('\u{a78d}', '\u{a78d}',
- IdentifierType::Recommended), ('\u{a78e}', '\u{a78e}', IdentifierType::Technical),
- ('\u{a78f}', '\u{a78f}', IdentifierType::Uncommon_Use), ('\u{a790}', '\u{a791}',
- IdentifierType::Obsolete), ('\u{a792}', '\u{a793}', IdentifierType::Recommended),
- ('\u{a794}', '\u{a79f}', IdentifierType::Obsolete), ('\u{a7a0}', '\u{a7a9}',
- IdentifierType::Obsolete), ('\u{a7aa}', '\u{a7aa}', IdentifierType::Recommended),
- ('\u{a7ab}', '\u{a7ad}', IdentifierType::Obsolete), ('\u{a7ae}', '\u{a7ae}',
- IdentifierType::Recommended), ('\u{a7af}', '\u{a7af}', IdentifierType::Technical),
- ('\u{a7b0}', '\u{a7b1}', IdentifierType::Obsolete), ('\u{a7b2}', '\u{a7b7}',
- IdentifierType::Uncommon_Use), ('\u{a7b8}', '\u{a7b9}', IdentifierType::Recommended),
- ('\u{a7ba}', '\u{a7bf}', IdentifierType::Technical), ('\u{a7c2}', '\u{a7c6}',
- IdentifierType::Recommended), ('\u{a7c7}', '\u{a7ca}', IdentifierType::Recommended),
+ ('\u{9ff0}', '\u{9ffc}', IdentifierType::Recommended), ('\u{9ffd}', '\u{9fff}',
+ IdentifierType::Recommended), ('\u{a000}', '\u{a48c}', IdentifierType::Limited_Use),
+ ('\u{a490}', '\u{a4a1}', IdentifierType::Limited_Use), ('\u{a4a2}', '\u{a4a3}',
+ IdentifierType::Limited_Use), ('\u{a4a4}', '\u{a4b3}', IdentifierType::Limited_Use),
+ ('\u{a4b4}', '\u{a4b4}', IdentifierType::Limited_Use), ('\u{a4b5}', '\u{a4c0}',
+ IdentifierType::Limited_Use), ('\u{a4c1}', '\u{a4c1}', IdentifierType::Limited_Use),
+ ('\u{a4c2}', '\u{a4c4}', IdentifierType::Limited_Use), ('\u{a4c5}', '\u{a4c5}',
+ IdentifierType::Limited_Use), ('\u{a4c6}', '\u{a4c6}', IdentifierType::Limited_Use),
+ ('\u{a4d0}', '\u{a4fd}', IdentifierType::Limited_Use), ('\u{a4fe}', '\u{a4ff}',
+ IdentifierType::Limited_Use), ('\u{a500}', '\u{a60c}', IdentifierType::Limited_Use),
+ ('\u{a60d}', '\u{a60f}', IdentifierType::Limited_Use), ('\u{a610}', '\u{a612}',
+ IdentifierType::Limited_Use), ('\u{a613}', '\u{a629}', IdentifierType::Limited_Use),
+ ('\u{a62a}', '\u{a62b}', IdentifierType::Limited_Use), ('\u{a640}', '\u{a65f}',
+ IdentifierType::Obsolete), ('\u{a660}', '\u{a661}', IdentifierType::Obsolete),
+ ('\u{a662}', '\u{a66e}', IdentifierType::Obsolete), ('\u{a66f}', '\u{a66f}',
+ IdentifierType::Uncommon_Use), ('\u{a670}', '\u{a673}', IdentifierType::Obsolete),
+ ('\u{a674}', '\u{a67b}', IdentifierType::Obsolete), ('\u{a67c}', '\u{a67d}',
+ IdentifierType::Uncommon_Use), ('\u{a67e}', '\u{a67e}', IdentifierType::Not_XID),
+ ('\u{a67f}', '\u{a67f}', IdentifierType::Recommended), ('\u{a680}', '\u{a697}',
+ IdentifierType::Obsolete), ('\u{a698}', '\u{a69b}', IdentifierType::Obsolete),
+ ('\u{a69c}', '\u{a69d}', IdentifierType::Not_NFKC), ('\u{a69e}', '\u{a69e}',
+ IdentifierType::Uncommon_Use), ('\u{a69f}', '\u{a69f}', IdentifierType::Obsolete),
+ ('\u{a6a0}', '\u{a6f1}', IdentifierType::Limited_Use), ('\u{a6f2}', '\u{a6f7}',
+ IdentifierType::Limited_Use), ('\u{a700}', '\u{a707}', IdentifierType::Obsolete),
+ ('\u{a708}', '\u{a716}', IdentifierType::Technical), ('\u{a717}', '\u{a71a}',
+ IdentifierType::Recommended), ('\u{a71b}', '\u{a71f}', IdentifierType::Recommended),
+ ('\u{a720}', '\u{a721}', IdentifierType::Not_XID), ('\u{a722}', '\u{a72f}',
+ IdentifierType::Technical), ('\u{a730}', '\u{a76f}', IdentifierType::Obsolete),
+ ('\u{a770}', '\u{a770}', IdentifierType::Not_NFKC), ('\u{a771}', '\u{a787}',
+ IdentifierType::Obsolete), ('\u{a788}', '\u{a788}', IdentifierType::Recommended),
+ ('\u{a789}', '\u{a78a}', IdentifierType::Not_XID), ('\u{a78b}', '\u{a78c}',
+ IdentifierType::Uncommon_Use), ('\u{a78d}', '\u{a78d}', IdentifierType::Recommended),
+ ('\u{a78e}', '\u{a78e}', IdentifierType::Technical), ('\u{a78f}', '\u{a78f}',
+ IdentifierType::Uncommon_Use), ('\u{a790}', '\u{a791}', IdentifierType::Obsolete),
+ ('\u{a792}', '\u{a793}', IdentifierType::Recommended), ('\u{a794}', '\u{a79f}',
+ IdentifierType::Obsolete), ('\u{a7a0}', '\u{a7a9}', IdentifierType::Obsolete),
+ ('\u{a7aa}', '\u{a7aa}', IdentifierType::Recommended), ('\u{a7ab}', '\u{a7ad}',
+ IdentifierType::Obsolete), ('\u{a7ae}', '\u{a7ae}', IdentifierType::Technical),
+ ('\u{a7af}', '\u{a7af}', IdentifierType::Technical), ('\u{a7b0}', '\u{a7b1}',
+ IdentifierType::Obsolete), ('\u{a7b2}', '\u{a7b7}', IdentifierType::Uncommon_Use),
+ ('\u{a7b8}', '\u{a7b9}', IdentifierType::Uncommon_Use), ('\u{a7ba}', '\u{a7bf}',
+ IdentifierType::Technical), ('\u{a7c0}', '\u{a7c1}', IdentifierType::Recommended),
+ ('\u{a7c2}', '\u{a7c6}', IdentifierType::Recommended), ('\u{a7c7}', '\u{a7ca}',
+ IdentifierType::Recommended), ('\u{a7d0}', '\u{a7d1}', IdentifierType::Recommended),
+ ('\u{a7d3}', '\u{a7d3}', IdentifierType::Recommended), ('\u{a7d5}', '\u{a7d9}',
+ IdentifierType::Recommended), ('\u{a7f2}', '\u{a7f4}', IdentifierType::Not_NFKC),
('\u{a7f5}', '\u{a7f6}', IdentifierType::Obsolete), ('\u{a7f7}', '\u{a7f7}',
IdentifierType::Obsolete), ('\u{a7f8}', '\u{a7f9}', IdentifierType::Not_NFKC),
('\u{a7fa}', '\u{a7fa}', IdentifierType::Technical), ('\u{a7fb}', '\u{a7ff}',
@@ -1235,119 +1263,133 @@ pub mod identifier {
IdentifierType::Not_NFKC), ('\u{fb3e}', '\u{fb3e}', IdentifierType::Not_NFKC),
('\u{fb40}', '\u{fb41}', IdentifierType::Not_NFKC), ('\u{fb43}', '\u{fb44}',
IdentifierType::Not_NFKC), ('\u{fb46}', '\u{fbb1}', IdentifierType::Not_NFKC),
- ('\u{fbb2}', '\u{fbc1}', IdentifierType::Technical), ('\u{fbd3}', '\u{fd3d}',
- IdentifierType::Not_NFKC), ('\u{fd3e}', '\u{fd3f}', IdentifierType::Technical),
- ('\u{fd50}', '\u{fd8f}', IdentifierType::Not_NFKC), ('\u{fd92}', '\u{fdc7}',
- IdentifierType::Not_NFKC), ('\u{fdf0}', '\u{fdfb}', IdentifierType::Not_NFKC),
+ ('\u{fbb2}', '\u{fbc1}', IdentifierType::Technical), ('\u{fbc2}', '\u{fbc2}',
+ IdentifierType::Technical), ('\u{fbd3}', '\u{fd3d}', IdentifierType::Not_NFKC),
+ ('\u{fd3e}', '\u{fd3f}', IdentifierType::Technical), ('\u{fd40}', '\u{fd4f}',
+ IdentifierType::Technical), ('\u{fd50}', '\u{fd8f}', IdentifierType::Not_NFKC),
+ ('\u{fd92}', '\u{fdc7}', IdentifierType::Not_NFKC), ('\u{fdcf}', '\u{fdcf}',
+ IdentifierType::Technical), ('\u{fdf0}', '\u{fdfb}', IdentifierType::Not_NFKC),
('\u{fdfc}', '\u{fdfc}', IdentifierType::Not_NFKC), ('\u{fdfd}', '\u{fdfd}',
- IdentifierType::Technical), ('\u{fe00}', '\u{fe0f}', IdentifierType::Default_Ignorable),
- ('\u{fe10}', '\u{fe19}', IdentifierType::Not_NFKC), ('\u{fe20}', '\u{fe23}',
- IdentifierType::Technical), ('\u{fe24}', '\u{fe26}', IdentifierType::Technical),
- ('\u{fe27}', '\u{fe2d}', IdentifierType::Technical), ('\u{fe2e}', '\u{fe2f}',
- IdentifierType::Uncommon_Use), ('\u{fe30}', '\u{fe44}', IdentifierType::Not_NFKC),
- ('\u{fe45}', '\u{fe46}', IdentifierType::Technical), ('\u{fe47}', '\u{fe48}',
- IdentifierType::Not_NFKC), ('\u{fe49}', '\u{fe52}', IdentifierType::Not_NFKC),
- ('\u{fe54}', '\u{fe66}', IdentifierType::Not_NFKC), ('\u{fe68}', '\u{fe6b}',
- IdentifierType::Not_NFKC), ('\u{fe70}', '\u{fe72}', IdentifierType::Not_NFKC),
- ('\u{fe73}', '\u{fe73}', IdentifierType::Technical), ('\u{fe74}', '\u{fe74}',
- IdentifierType::Not_NFKC), ('\u{fe76}', '\u{fefc}', IdentifierType::Not_NFKC),
- ('\u{feff}', '\u{feff}', IdentifierType::Default_Ignorable), ('\u{ff01}', '\u{ff5e}',
- IdentifierType::Not_NFKC), ('\u{ff5f}', '\u{ff60}', IdentifierType::Not_NFKC),
- ('\u{ff61}', '\u{ff9f}', IdentifierType::Not_NFKC), ('\u{ffa0}', '\u{ffa0}',
- IdentifierType::Default_Ignorable), ('\u{ffa1}', '\u{ffbe}', IdentifierType::Not_NFKC),
- ('\u{ffc2}', '\u{ffc7}', IdentifierType::Not_NFKC), ('\u{ffca}', '\u{ffcf}',
- IdentifierType::Not_NFKC), ('\u{ffd2}', '\u{ffd7}', IdentifierType::Not_NFKC),
- ('\u{ffda}', '\u{ffdc}', IdentifierType::Not_NFKC), ('\u{ffe0}', '\u{ffe6}',
- IdentifierType::Not_NFKC), ('\u{ffe8}', '\u{ffee}', IdentifierType::Not_NFKC),
- ('\u{fff9}', '\u{fffb}', IdentifierType::Not_XID), ('\u{fffc}', '\u{fffc}',
- IdentifierType::Not_XID), ('\u{fffd}', '\u{fffd}', IdentifierType::Not_XID), ('\u{10000}',
- '\u{1000b}', IdentifierType::Exclusion), ('\u{1000d}', '\u{10026}',
- IdentifierType::Exclusion), ('\u{10028}', '\u{1003a}', IdentifierType::Exclusion),
- ('\u{1003c}', '\u{1003d}', IdentifierType::Exclusion), ('\u{1003f}', '\u{1004d}',
- IdentifierType::Exclusion), ('\u{10050}', '\u{1005d}', IdentifierType::Exclusion),
- ('\u{10080}', '\u{100fa}', IdentifierType::Exclusion), ('\u{10100}', '\u{10102}',
- IdentifierType::Exclusion), ('\u{10107}', '\u{10133}', IdentifierType::Exclusion),
- ('\u{10137}', '\u{1013f}', IdentifierType::Exclusion), ('\u{10140}', '\u{10174}',
- IdentifierType::Obsolete), ('\u{10175}', '\u{1018a}', IdentifierType::Not_XID),
- ('\u{1018b}', '\u{1018c}', IdentifierType::Not_XID), ('\u{1018d}', '\u{1018e}',
- IdentifierType::Not_XID), ('\u{10190}', '\u{1019b}', IdentifierType::Not_XID),
- ('\u{1019c}', '\u{1019c}', IdentifierType::Not_XID), ('\u{101a0}', '\u{101a0}',
- IdentifierType::Not_XID), ('\u{101d0}', '\u{101fc}', IdentifierType::Obsolete),
- ('\u{101fd}', '\u{101fd}', IdentifierType::Obsolete), ('\u{10280}', '\u{1029c}',
- IdentifierType::Exclusion), ('\u{102a0}', '\u{102d0}', IdentifierType::Exclusion),
- ('\u{102e0}', '\u{102e0}', IdentifierType::Obsolete), ('\u{102e1}', '\u{102fb}',
- IdentifierType::Obsolete), ('\u{10300}', '\u{1031e}', IdentifierType::Exclusion),
- ('\u{1031f}', '\u{1031f}', IdentifierType::Exclusion), ('\u{10320}', '\u{10323}',
- IdentifierType::Exclusion), ('\u{1032d}', '\u{1032f}', IdentifierType::Exclusion),
- ('\u{10330}', '\u{1034a}', IdentifierType::Exclusion), ('\u{10350}', '\u{1037a}',
- IdentifierType::Exclusion), ('\u{10380}', '\u{1039d}', IdentifierType::Exclusion),
- ('\u{1039f}', '\u{1039f}', IdentifierType::Exclusion), ('\u{103a0}', '\u{103c3}',
- IdentifierType::Exclusion), ('\u{103c8}', '\u{103cf}', IdentifierType::Exclusion),
- ('\u{103d0}', '\u{103d0}', IdentifierType::Exclusion), ('\u{103d1}', '\u{103d5}',
- IdentifierType::Exclusion), ('\u{10400}', '\u{10425}', IdentifierType::Exclusion),
- ('\u{10426}', '\u{10427}', IdentifierType::Exclusion), ('\u{10428}', '\u{1044d}',
- IdentifierType::Exclusion), ('\u{1044e}', '\u{1049d}', IdentifierType::Exclusion),
- ('\u{104a0}', '\u{104a9}', IdentifierType::Exclusion), ('\u{104b0}', '\u{104d3}',
- IdentifierType::Limited_Use), ('\u{104d8}', '\u{104fb}', IdentifierType::Limited_Use),
- ('\u{10500}', '\u{10527}', IdentifierType::Exclusion), ('\u{10530}', '\u{10563}',
- IdentifierType::Exclusion), ('\u{1056f}', '\u{1056f}', IdentifierType::Exclusion),
+ IdentifierType::Technical), ('\u{fdfe}', '\u{fdff}', IdentifierType::Technical),
+ ('\u{fe00}', '\u{fe0f}', IdentifierType::Default_Ignorable), ('\u{fe10}', '\u{fe19}',
+ IdentifierType::Not_NFKC), ('\u{fe20}', '\u{fe23}', IdentifierType::Technical),
+ ('\u{fe24}', '\u{fe26}', IdentifierType::Technical), ('\u{fe27}', '\u{fe2d}',
+ IdentifierType::Technical), ('\u{fe2e}', '\u{fe2f}', IdentifierType::Uncommon_Use),
+ ('\u{fe30}', '\u{fe44}', IdentifierType::Not_NFKC), ('\u{fe45}', '\u{fe46}',
+ IdentifierType::Technical), ('\u{fe47}', '\u{fe48}', IdentifierType::Not_NFKC),
+ ('\u{fe49}', '\u{fe52}', IdentifierType::Not_NFKC), ('\u{fe54}', '\u{fe66}',
+ IdentifierType::Not_NFKC), ('\u{fe68}', '\u{fe6b}', IdentifierType::Not_NFKC),
+ ('\u{fe70}', '\u{fe72}', IdentifierType::Not_NFKC), ('\u{fe73}', '\u{fe73}',
+ IdentifierType::Technical), ('\u{fe74}', '\u{fe74}', IdentifierType::Not_NFKC),
+ ('\u{fe76}', '\u{fefc}', IdentifierType::Not_NFKC), ('\u{feff}', '\u{feff}',
+ IdentifierType::Default_Ignorable), ('\u{ff01}', '\u{ff5e}', IdentifierType::Not_NFKC),
+ ('\u{ff5f}', '\u{ff60}', IdentifierType::Not_NFKC), ('\u{ff61}', '\u{ff9f}',
+ IdentifierType::Not_NFKC), ('\u{ffa0}', '\u{ffa0}', IdentifierType::Default_Ignorable),
+ ('\u{ffa1}', '\u{ffbe}', IdentifierType::Not_NFKC), ('\u{ffc2}', '\u{ffc7}',
+ IdentifierType::Not_NFKC), ('\u{ffca}', '\u{ffcf}', IdentifierType::Not_NFKC),
+ ('\u{ffd2}', '\u{ffd7}', IdentifierType::Not_NFKC), ('\u{ffda}', '\u{ffdc}',
+ IdentifierType::Not_NFKC), ('\u{ffe0}', '\u{ffe6}', IdentifierType::Not_NFKC),
+ ('\u{ffe8}', '\u{ffee}', IdentifierType::Not_NFKC), ('\u{fff9}', '\u{fffb}',
+ IdentifierType::Not_XID), ('\u{fffc}', '\u{fffc}', IdentifierType::Not_XID), ('\u{fffd}',
+ '\u{fffd}', IdentifierType::Not_XID), ('\u{10000}', '\u{1000b}',
+ IdentifierType::Exclusion), ('\u{1000d}', '\u{10026}', IdentifierType::Exclusion),
+ ('\u{10028}', '\u{1003a}', IdentifierType::Exclusion), ('\u{1003c}', '\u{1003d}',
+ IdentifierType::Exclusion), ('\u{1003f}', '\u{1004d}', IdentifierType::Exclusion),
+ ('\u{10050}', '\u{1005d}', IdentifierType::Exclusion), ('\u{10080}', '\u{100fa}',
+ IdentifierType::Exclusion), ('\u{10100}', '\u{10102}', IdentifierType::Exclusion),
+ ('\u{10107}', '\u{10133}', IdentifierType::Exclusion), ('\u{10137}', '\u{1013f}',
+ IdentifierType::Exclusion), ('\u{10140}', '\u{10174}', IdentifierType::Obsolete),
+ ('\u{10175}', '\u{1018a}', IdentifierType::Not_XID), ('\u{1018b}', '\u{1018c}',
+ IdentifierType::Not_XID), ('\u{1018d}', '\u{1018e}', IdentifierType::Not_XID),
+ ('\u{10190}', '\u{1019b}', IdentifierType::Not_XID), ('\u{1019c}', '\u{1019c}',
+ IdentifierType::Not_XID), ('\u{101a0}', '\u{101a0}', IdentifierType::Not_XID),
+ ('\u{101d0}', '\u{101fc}', IdentifierType::Obsolete), ('\u{101fd}', '\u{101fd}',
+ IdentifierType::Obsolete), ('\u{10280}', '\u{1029c}', IdentifierType::Exclusion),
+ ('\u{102a0}', '\u{102d0}', IdentifierType::Exclusion), ('\u{102e0}', '\u{102e0}',
+ IdentifierType::Obsolete), ('\u{102e1}', '\u{102fb}', IdentifierType::Obsolete),
+ ('\u{10300}', '\u{1031e}', IdentifierType::Exclusion), ('\u{1031f}', '\u{1031f}',
+ IdentifierType::Exclusion), ('\u{10320}', '\u{10323}', IdentifierType::Exclusion),
+ ('\u{1032d}', '\u{1032f}', IdentifierType::Exclusion), ('\u{10330}', '\u{1034a}',
+ IdentifierType::Exclusion), ('\u{10350}', '\u{1037a}', IdentifierType::Exclusion),
+ ('\u{10380}', '\u{1039d}', IdentifierType::Exclusion), ('\u{1039f}', '\u{1039f}',
+ IdentifierType::Exclusion), ('\u{103a0}', '\u{103c3}', IdentifierType::Exclusion),
+ ('\u{103c8}', '\u{103cf}', IdentifierType::Exclusion), ('\u{103d0}', '\u{103d0}',
+ IdentifierType::Exclusion), ('\u{103d1}', '\u{103d5}', IdentifierType::Exclusion),
+ ('\u{10400}', '\u{10425}', IdentifierType::Exclusion), ('\u{10426}', '\u{10427}',
+ IdentifierType::Exclusion), ('\u{10428}', '\u{1044d}', IdentifierType::Exclusion),
+ ('\u{1044e}', '\u{1049d}', IdentifierType::Exclusion), ('\u{104a0}', '\u{104a9}',
+ IdentifierType::Exclusion), ('\u{104b0}', '\u{104d3}', IdentifierType::Limited_Use),
+ ('\u{104d8}', '\u{104fb}', IdentifierType::Limited_Use), ('\u{10500}', '\u{10527}',
+ IdentifierType::Exclusion), ('\u{10530}', '\u{10563}', IdentifierType::Exclusion),
+ ('\u{1056f}', '\u{1056f}', IdentifierType::Exclusion), ('\u{10570}', '\u{1057a}',
+ IdentifierType::Exclusion), ('\u{1057c}', '\u{1058a}', IdentifierType::Exclusion),
+ ('\u{1058c}', '\u{10592}', IdentifierType::Exclusion), ('\u{10594}', '\u{10595}',
+ IdentifierType::Exclusion), ('\u{10597}', '\u{105a1}', IdentifierType::Exclusion),
+ ('\u{105a3}', '\u{105b1}', IdentifierType::Exclusion), ('\u{105b3}', '\u{105b9}',
+ IdentifierType::Exclusion), ('\u{105bb}', '\u{105bc}', IdentifierType::Exclusion),
('\u{10600}', '\u{10736}', IdentifierType::Exclusion), ('\u{10740}', '\u{10755}',
IdentifierType::Exclusion), ('\u{10760}', '\u{10767}', IdentifierType::Exclusion),
- ('\u{10800}', '\u{10805}', IdentifierType::Exclusion), ('\u{10808}', '\u{10808}',
- IdentifierType::Exclusion), ('\u{1080a}', '\u{10835}', IdentifierType::Exclusion),
- ('\u{10837}', '\u{10838}', IdentifierType::Exclusion), ('\u{1083c}', '\u{1083c}',
- IdentifierType::Exclusion), ('\u{1083f}', '\u{1083f}', IdentifierType::Exclusion),
- ('\u{10840}', '\u{10855}', IdentifierType::Exclusion), ('\u{10857}', '\u{1085f}',
- IdentifierType::Exclusion), ('\u{10860}', '\u{10876}', IdentifierType::Exclusion),
- ('\u{10877}', '\u{1087f}', IdentifierType::Exclusion), ('\u{10880}', '\u{1089e}',
- IdentifierType::Exclusion), ('\u{108a7}', '\u{108af}', IdentifierType::Exclusion),
- ('\u{108e0}', '\u{108f2}', IdentifierType::Exclusion), ('\u{108f4}', '\u{108f5}',
- IdentifierType::Exclusion), ('\u{108fb}', '\u{108ff}', IdentifierType::Exclusion),
- ('\u{10900}', '\u{10915}', IdentifierType::Exclusion), ('\u{10916}', '\u{10919}',
- IdentifierType::Exclusion), ('\u{1091a}', '\u{1091b}', IdentifierType::Exclusion),
- ('\u{1091f}', '\u{1091f}', IdentifierType::Exclusion), ('\u{10920}', '\u{10939}',
- IdentifierType::Exclusion), ('\u{1093f}', '\u{1093f}', IdentifierType::Exclusion),
- ('\u{10980}', '\u{109b7}', IdentifierType::Exclusion), ('\u{109bc}', '\u{109bd}',
- IdentifierType::Exclusion), ('\u{109be}', '\u{109bf}', IdentifierType::Exclusion),
- ('\u{109c0}', '\u{109cf}', IdentifierType::Exclusion), ('\u{109d2}', '\u{109ff}',
- IdentifierType::Exclusion), ('\u{10a00}', '\u{10a03}', IdentifierType::Exclusion),
- ('\u{10a05}', '\u{10a06}', IdentifierType::Exclusion), ('\u{10a0c}', '\u{10a13}',
- IdentifierType::Exclusion), ('\u{10a15}', '\u{10a17}', IdentifierType::Exclusion),
- ('\u{10a19}', '\u{10a33}', IdentifierType::Exclusion), ('\u{10a34}', '\u{10a35}',
- IdentifierType::Exclusion), ('\u{10a38}', '\u{10a3a}', IdentifierType::Exclusion),
- ('\u{10a3f}', '\u{10a3f}', IdentifierType::Exclusion), ('\u{10a40}', '\u{10a47}',
- IdentifierType::Exclusion), ('\u{10a48}', '\u{10a48}', IdentifierType::Exclusion),
- ('\u{10a50}', '\u{10a58}', IdentifierType::Exclusion), ('\u{10a60}', '\u{10a7c}',
- IdentifierType::Exclusion), ('\u{10a7d}', '\u{10a7f}', IdentifierType::Exclusion),
- ('\u{10a80}', '\u{10a9c}', IdentifierType::Exclusion), ('\u{10a9d}', '\u{10a9f}',
- IdentifierType::Exclusion), ('\u{10ac0}', '\u{10ac7}', IdentifierType::Exclusion),
- ('\u{10ac8}', '\u{10ac8}', IdentifierType::Exclusion), ('\u{10ac9}', '\u{10ae6}',
- IdentifierType::Exclusion), ('\u{10aeb}', '\u{10af6}', IdentifierType::Exclusion),
- ('\u{10b00}', '\u{10b35}', IdentifierType::Exclusion), ('\u{10b39}', '\u{10b3f}',
- IdentifierType::Exclusion), ('\u{10b40}', '\u{10b55}', IdentifierType::Exclusion),
- ('\u{10b58}', '\u{10b5f}', IdentifierType::Exclusion), ('\u{10b60}', '\u{10b72}',
- IdentifierType::Exclusion), ('\u{10b78}', '\u{10b7f}', IdentifierType::Exclusion),
- ('\u{10b80}', '\u{10b91}', IdentifierType::Exclusion), ('\u{10b99}', '\u{10b9c}',
- IdentifierType::Exclusion), ('\u{10ba9}', '\u{10baf}', IdentifierType::Exclusion),
- ('\u{10c00}', '\u{10c48}', IdentifierType::Exclusion), ('\u{10c80}', '\u{10cb2}',
- IdentifierType::Exclusion), ('\u{10cc0}', '\u{10cf2}', IdentifierType::Exclusion),
- ('\u{10cfa}', '\u{10cff}', IdentifierType::Exclusion), ('\u{10d00}', '\u{10d27}',
- IdentifierType::Limited_Use), ('\u{10d30}', '\u{10d39}', IdentifierType::Limited_Use),
- ('\u{10e60}', '\u{10e7e}', IdentifierType::Not_XID), ('\u{10e80}', '\u{10ea9}',
- IdentifierType::Exclusion), ('\u{10eab}', '\u{10eac}', IdentifierType::Exclusion),
- ('\u{10ead}', '\u{10ead}', IdentifierType::Exclusion), ('\u{10eb0}', '\u{10eb1}',
- IdentifierType::Exclusion), ('\u{10f00}', '\u{10f1c}', IdentifierType::Exclusion),
- ('\u{10f1d}', '\u{10f26}', IdentifierType::Exclusion), ('\u{10f27}', '\u{10f27}',
- IdentifierType::Exclusion), ('\u{10f30}', '\u{10f50}', IdentifierType::Exclusion),
- ('\u{10f51}', '\u{10f59}', IdentifierType::Exclusion), ('\u{10fb0}', '\u{10fc4}',
- IdentifierType::Exclusion), ('\u{10fc5}', '\u{10fcb}', IdentifierType::Exclusion),
- ('\u{10fe0}', '\u{10ff6}', IdentifierType::Exclusion), ('\u{11000}', '\u{11046}',
- IdentifierType::Exclusion), ('\u{11047}', '\u{1104d}', IdentifierType::Exclusion),
- ('\u{11052}', '\u{11065}', IdentifierType::Exclusion), ('\u{11066}', '\u{1106f}',
- IdentifierType::Exclusion), ('\u{1107f}', '\u{1107f}', IdentifierType::Exclusion),
- ('\u{11080}', '\u{110ba}', IdentifierType::Exclusion), ('\u{110bb}', '\u{110bc}',
- IdentifierType::Exclusion), ('\u{110bd}', '\u{110bd}', IdentifierType::Exclusion),
- ('\u{110be}', '\u{110c1}', IdentifierType::Exclusion), ('\u{110cd}', '\u{110cd}',
+ ('\u{10780}', '\u{10780}', IdentifierType::Uncommon_Use), ('\u{10781}', '\u{10785}',
+ IdentifierType::Not_NFKC), ('\u{10787}', '\u{107b0}', IdentifierType::Not_NFKC),
+ ('\u{107b2}', '\u{107ba}', IdentifierType::Not_NFKC), ('\u{10800}', '\u{10805}',
+ IdentifierType::Exclusion), ('\u{10808}', '\u{10808}', IdentifierType::Exclusion),
+ ('\u{1080a}', '\u{10835}', IdentifierType::Exclusion), ('\u{10837}', '\u{10838}',
+ IdentifierType::Exclusion), ('\u{1083c}', '\u{1083c}', IdentifierType::Exclusion),
+ ('\u{1083f}', '\u{1083f}', IdentifierType::Exclusion), ('\u{10840}', '\u{10855}',
+ IdentifierType::Exclusion), ('\u{10857}', '\u{1085f}', IdentifierType::Exclusion),
+ ('\u{10860}', '\u{10876}', IdentifierType::Exclusion), ('\u{10877}', '\u{1087f}',
+ IdentifierType::Exclusion), ('\u{10880}', '\u{1089e}', IdentifierType::Exclusion),
+ ('\u{108a7}', '\u{108af}', IdentifierType::Exclusion), ('\u{108e0}', '\u{108f2}',
+ IdentifierType::Exclusion), ('\u{108f4}', '\u{108f5}', IdentifierType::Exclusion),
+ ('\u{108fb}', '\u{108ff}', IdentifierType::Exclusion), ('\u{10900}', '\u{10915}',
+ IdentifierType::Exclusion), ('\u{10916}', '\u{10919}', IdentifierType::Exclusion),
+ ('\u{1091a}', '\u{1091b}', IdentifierType::Exclusion), ('\u{1091f}', '\u{1091f}',
+ IdentifierType::Exclusion), ('\u{10920}', '\u{10939}', IdentifierType::Exclusion),
+ ('\u{1093f}', '\u{1093f}', IdentifierType::Exclusion), ('\u{10980}', '\u{109b7}',
+ IdentifierType::Exclusion), ('\u{109bc}', '\u{109bd}', IdentifierType::Exclusion),
+ ('\u{109be}', '\u{109bf}', IdentifierType::Exclusion), ('\u{109c0}', '\u{109cf}',
+ IdentifierType::Exclusion), ('\u{109d2}', '\u{109ff}', IdentifierType::Exclusion),
+ ('\u{10a00}', '\u{10a03}', IdentifierType::Exclusion), ('\u{10a05}', '\u{10a06}',
+ IdentifierType::Exclusion), ('\u{10a0c}', '\u{10a13}', IdentifierType::Exclusion),
+ ('\u{10a15}', '\u{10a17}', IdentifierType::Exclusion), ('\u{10a19}', '\u{10a33}',
+ IdentifierType::Exclusion), ('\u{10a34}', '\u{10a35}', IdentifierType::Exclusion),
+ ('\u{10a38}', '\u{10a3a}', IdentifierType::Exclusion), ('\u{10a3f}', '\u{10a3f}',
+ IdentifierType::Exclusion), ('\u{10a40}', '\u{10a47}', IdentifierType::Exclusion),
+ ('\u{10a48}', '\u{10a48}', IdentifierType::Exclusion), ('\u{10a50}', '\u{10a58}',
+ IdentifierType::Exclusion), ('\u{10a60}', '\u{10a7c}', IdentifierType::Exclusion),
+ ('\u{10a7d}', '\u{10a7f}', IdentifierType::Exclusion), ('\u{10a80}', '\u{10a9c}',
+ IdentifierType::Exclusion), ('\u{10a9d}', '\u{10a9f}', IdentifierType::Exclusion),
+ ('\u{10ac0}', '\u{10ac7}', IdentifierType::Exclusion), ('\u{10ac8}', '\u{10ac8}',
+ IdentifierType::Exclusion), ('\u{10ac9}', '\u{10ae6}', IdentifierType::Exclusion),
+ ('\u{10aeb}', '\u{10af6}', IdentifierType::Exclusion), ('\u{10b00}', '\u{10b35}',
+ IdentifierType::Exclusion), ('\u{10b39}', '\u{10b3f}', IdentifierType::Exclusion),
+ ('\u{10b40}', '\u{10b55}', IdentifierType::Exclusion), ('\u{10b58}', '\u{10b5f}',
+ IdentifierType::Exclusion), ('\u{10b60}', '\u{10b72}', IdentifierType::Exclusion),
+ ('\u{10b78}', '\u{10b7f}', IdentifierType::Exclusion), ('\u{10b80}', '\u{10b91}',
+ IdentifierType::Exclusion), ('\u{10b99}', '\u{10b9c}', IdentifierType::Exclusion),
+ ('\u{10ba9}', '\u{10baf}', IdentifierType::Exclusion), ('\u{10c00}', '\u{10c48}',
+ IdentifierType::Exclusion), ('\u{10c80}', '\u{10cb2}', IdentifierType::Exclusion),
+ ('\u{10cc0}', '\u{10cf2}', IdentifierType::Exclusion), ('\u{10cfa}', '\u{10cff}',
+ IdentifierType::Exclusion), ('\u{10d00}', '\u{10d27}', IdentifierType::Limited_Use),
+ ('\u{10d30}', '\u{10d39}', IdentifierType::Limited_Use), ('\u{10e60}', '\u{10e7e}',
+ IdentifierType::Not_XID), ('\u{10e80}', '\u{10ea9}', IdentifierType::Exclusion),
+ ('\u{10eab}', '\u{10eac}', IdentifierType::Exclusion), ('\u{10ead}', '\u{10ead}',
+ IdentifierType::Exclusion), ('\u{10eb0}', '\u{10eb1}', IdentifierType::Exclusion),
+ ('\u{10efd}', '\u{10eff}', IdentifierType::Uncommon_Use), ('\u{10f00}', '\u{10f1c}',
+ IdentifierType::Exclusion), ('\u{10f1d}', '\u{10f26}', IdentifierType::Exclusion),
+ ('\u{10f27}', '\u{10f27}', IdentifierType::Exclusion), ('\u{10f30}', '\u{10f50}',
+ IdentifierType::Exclusion), ('\u{10f51}', '\u{10f59}', IdentifierType::Exclusion),
+ ('\u{10f70}', '\u{10f85}', IdentifierType::Exclusion), ('\u{10f86}', '\u{10f89}',
+ IdentifierType::Exclusion), ('\u{10fb0}', '\u{10fc4}', IdentifierType::Exclusion),
+ ('\u{10fc5}', '\u{10fcb}', IdentifierType::Exclusion), ('\u{10fe0}', '\u{10ff6}',
+ IdentifierType::Exclusion), ('\u{11000}', '\u{11046}', IdentifierType::Exclusion),
+ ('\u{11047}', '\u{1104d}', IdentifierType::Exclusion), ('\u{11052}', '\u{11065}',
+ IdentifierType::Exclusion), ('\u{11066}', '\u{1106f}', IdentifierType::Exclusion),
+ ('\u{11070}', '\u{11075}', IdentifierType::Exclusion), ('\u{1107f}', '\u{1107f}',
+ IdentifierType::Exclusion), ('\u{11080}', '\u{110ba}', IdentifierType::Exclusion),
+ ('\u{110bb}', '\u{110bc}', IdentifierType::Exclusion), ('\u{110bd}', '\u{110bd}',
+ IdentifierType::Exclusion), ('\u{110be}', '\u{110c1}', IdentifierType::Exclusion),
+ ('\u{110c2}', '\u{110c2}', IdentifierType::Exclusion), ('\u{110cd}', '\u{110cd}',
IdentifierType::Exclusion), ('\u{110d0}', '\u{110e8}', IdentifierType::Exclusion),
('\u{110f0}', '\u{110f9}', IdentifierType::Exclusion), ('\u{11100}', '\u{11134}',
IdentifierType::Limited_Use), ('\u{11136}', '\u{1113f}', IdentifierType::Limited_Use),
@@ -1365,45 +1407,47 @@ pub mod identifier {
IdentifierType::Not_XID), ('\u{11200}', '\u{11211}', IdentifierType::Exclusion),
('\u{11213}', '\u{11237}', IdentifierType::Exclusion), ('\u{11238}', '\u{1123d}',
IdentifierType::Exclusion), ('\u{1123e}', '\u{1123e}', IdentifierType::Exclusion),
- ('\u{11280}', '\u{11286}', IdentifierType::Exclusion), ('\u{11288}', '\u{11288}',
- IdentifierType::Exclusion), ('\u{1128a}', '\u{1128d}', IdentifierType::Exclusion),
- ('\u{1128f}', '\u{1129d}', IdentifierType::Exclusion), ('\u{1129f}', '\u{112a8}',
- IdentifierType::Exclusion), ('\u{112a9}', '\u{112a9}', IdentifierType::Exclusion),
- ('\u{112b0}', '\u{112ea}', IdentifierType::Exclusion), ('\u{112f0}', '\u{112f9}',
- IdentifierType::Exclusion), ('\u{11300}', '\u{11300}', IdentifierType::Exclusion),
- ('\u{11301}', '\u{11301}', IdentifierType::Recommended), ('\u{11302}', '\u{11302}',
- IdentifierType::Exclusion), ('\u{11303}', '\u{11303}', IdentifierType::Recommended),
- ('\u{11305}', '\u{1130c}', IdentifierType::Exclusion), ('\u{1130f}', '\u{11310}',
- IdentifierType::Exclusion), ('\u{11313}', '\u{11328}', IdentifierType::Exclusion),
- ('\u{1132a}', '\u{11330}', IdentifierType::Exclusion), ('\u{11332}', '\u{11333}',
- IdentifierType::Exclusion), ('\u{11335}', '\u{11339}', IdentifierType::Exclusion),
- ('\u{1133b}', '\u{1133b}', IdentifierType::Recommended), ('\u{1133c}', '\u{1133c}',
- IdentifierType::Recommended), ('\u{1133d}', '\u{11344}', IdentifierType::Exclusion),
- ('\u{11347}', '\u{11348}', IdentifierType::Exclusion), ('\u{1134b}', '\u{1134d}',
- IdentifierType::Exclusion), ('\u{11350}', '\u{11350}', IdentifierType::Exclusion),
- ('\u{11357}', '\u{11357}', IdentifierType::Exclusion), ('\u{1135d}', '\u{11363}',
- IdentifierType::Exclusion), ('\u{11366}', '\u{1136c}', IdentifierType::Exclusion),
- ('\u{11370}', '\u{11374}', IdentifierType::Exclusion), ('\u{11400}', '\u{1144a}',
- IdentifierType::Limited_Use), ('\u{1144b}', '\u{1144f}', IdentifierType::Limited_Use),
- ('\u{11450}', '\u{11459}', IdentifierType::Limited_Use), ('\u{1145a}', '\u{1145a}',
- IdentifierType::Limited_Use), ('\u{1145b}', '\u{1145b}', IdentifierType::Limited_Use),
- ('\u{1145d}', '\u{1145d}', IdentifierType::Limited_Use), ('\u{1145e}', '\u{1145e}',
- IdentifierType::Limited_Use), ('\u{1145f}', '\u{1145f}', IdentifierType::Limited_Use),
- ('\u{11460}', '\u{11461}', IdentifierType::Limited_Use), ('\u{11480}', '\u{114c5}',
- IdentifierType::Exclusion), ('\u{114c6}', '\u{114c6}', IdentifierType::Exclusion),
- ('\u{114c7}', '\u{114c7}', IdentifierType::Exclusion), ('\u{114d0}', '\u{114d9}',
- IdentifierType::Exclusion), ('\u{11580}', '\u{115b5}', IdentifierType::Exclusion),
- ('\u{115b8}', '\u{115c0}', IdentifierType::Exclusion), ('\u{115c1}', '\u{115c9}',
- IdentifierType::Exclusion), ('\u{115ca}', '\u{115d7}', IdentifierType::Exclusion),
- ('\u{115d8}', '\u{115dd}', IdentifierType::Exclusion), ('\u{11600}', '\u{11640}',
- IdentifierType::Exclusion), ('\u{11641}', '\u{11643}', IdentifierType::Exclusion),
- ('\u{11644}', '\u{11644}', IdentifierType::Exclusion), ('\u{11650}', '\u{11659}',
- IdentifierType::Exclusion), ('\u{11660}', '\u{1166c}', IdentifierType::Exclusion),
- ('\u{11680}', '\u{116b7}', IdentifierType::Exclusion), ('\u{116b8}', '\u{116b8}',
- IdentifierType::Exclusion), ('\u{116c0}', '\u{116c9}', IdentifierType::Exclusion),
- ('\u{11700}', '\u{11719}', IdentifierType::Exclusion), ('\u{1171a}', '\u{1171a}',
- IdentifierType::Exclusion), ('\u{1171d}', '\u{1172b}', IdentifierType::Exclusion),
- ('\u{11730}', '\u{11739}', IdentifierType::Exclusion), ('\u{1173a}', '\u{1173f}',
+ ('\u{1123f}', '\u{11241}', IdentifierType::Exclusion), ('\u{11280}', '\u{11286}',
+ IdentifierType::Exclusion), ('\u{11288}', '\u{11288}', IdentifierType::Exclusion),
+ ('\u{1128a}', '\u{1128d}', IdentifierType::Exclusion), ('\u{1128f}', '\u{1129d}',
+ IdentifierType::Exclusion), ('\u{1129f}', '\u{112a8}', IdentifierType::Exclusion),
+ ('\u{112a9}', '\u{112a9}', IdentifierType::Exclusion), ('\u{112b0}', '\u{112ea}',
+ IdentifierType::Exclusion), ('\u{112f0}', '\u{112f9}', IdentifierType::Exclusion),
+ ('\u{11300}', '\u{11300}', IdentifierType::Exclusion), ('\u{11301}', '\u{11301}',
+ IdentifierType::Recommended), ('\u{11302}', '\u{11302}', IdentifierType::Exclusion),
+ ('\u{11303}', '\u{11303}', IdentifierType::Recommended), ('\u{11305}', '\u{1130c}',
+ IdentifierType::Exclusion), ('\u{1130f}', '\u{11310}', IdentifierType::Exclusion),
+ ('\u{11313}', '\u{11328}', IdentifierType::Exclusion), ('\u{1132a}', '\u{11330}',
+ IdentifierType::Exclusion), ('\u{11332}', '\u{11333}', IdentifierType::Exclusion),
+ ('\u{11335}', '\u{11339}', IdentifierType::Exclusion), ('\u{1133b}', '\u{1133b}',
+ IdentifierType::Recommended), ('\u{1133c}', '\u{1133c}', IdentifierType::Recommended),
+ ('\u{1133d}', '\u{11344}', IdentifierType::Exclusion), ('\u{11347}', '\u{11348}',
+ IdentifierType::Exclusion), ('\u{1134b}', '\u{1134d}', IdentifierType::Exclusion),
+ ('\u{11350}', '\u{11350}', IdentifierType::Exclusion), ('\u{11357}', '\u{11357}',
+ IdentifierType::Exclusion), ('\u{1135d}', '\u{11363}', IdentifierType::Exclusion),
+ ('\u{11366}', '\u{1136c}', IdentifierType::Exclusion), ('\u{11370}', '\u{11374}',
+ IdentifierType::Exclusion), ('\u{11400}', '\u{1144a}', IdentifierType::Limited_Use),
+ ('\u{1144b}', '\u{1144f}', IdentifierType::Limited_Use), ('\u{11450}', '\u{11459}',
+ IdentifierType::Limited_Use), ('\u{1145a}', '\u{1145a}', IdentifierType::Limited_Use),
+ ('\u{1145b}', '\u{1145b}', IdentifierType::Limited_Use), ('\u{1145d}', '\u{1145d}',
+ IdentifierType::Limited_Use), ('\u{1145e}', '\u{1145e}', IdentifierType::Limited_Use),
+ ('\u{1145f}', '\u{1145f}', IdentifierType::Limited_Use), ('\u{11460}', '\u{11461}',
+ IdentifierType::Limited_Use), ('\u{11480}', '\u{114c5}', IdentifierType::Exclusion),
+ ('\u{114c6}', '\u{114c6}', IdentifierType::Exclusion), ('\u{114c7}', '\u{114c7}',
+ IdentifierType::Exclusion), ('\u{114d0}', '\u{114d9}', IdentifierType::Exclusion),
+ ('\u{11580}', '\u{115b5}', IdentifierType::Exclusion), ('\u{115b8}', '\u{115c0}',
+ IdentifierType::Exclusion), ('\u{115c1}', '\u{115c9}', IdentifierType::Exclusion),
+ ('\u{115ca}', '\u{115d7}', IdentifierType::Exclusion), ('\u{115d8}', '\u{115dd}',
+ IdentifierType::Exclusion), ('\u{11600}', '\u{11640}', IdentifierType::Exclusion),
+ ('\u{11641}', '\u{11643}', IdentifierType::Exclusion), ('\u{11644}', '\u{11644}',
+ IdentifierType::Exclusion), ('\u{11650}', '\u{11659}', IdentifierType::Exclusion),
+ ('\u{11660}', '\u{1166c}', IdentifierType::Exclusion), ('\u{11680}', '\u{116b7}',
+ IdentifierType::Exclusion), ('\u{116b8}', '\u{116b8}', IdentifierType::Exclusion),
+ ('\u{116b9}', '\u{116b9}', IdentifierType::Exclusion), ('\u{116c0}', '\u{116c9}',
+ IdentifierType::Exclusion), ('\u{11700}', '\u{11719}', IdentifierType::Exclusion),
+ ('\u{1171a}', '\u{1171a}', IdentifierType::Exclusion), ('\u{1171d}', '\u{1172b}',
+ IdentifierType::Exclusion), ('\u{11730}', '\u{11739}', IdentifierType::Exclusion),
+ ('\u{1173a}', '\u{1173f}', IdentifierType::Exclusion), ('\u{11740}', '\u{11746}',
IdentifierType::Exclusion), ('\u{11800}', '\u{1183a}', IdentifierType::Exclusion),
('\u{1183b}', '\u{1183b}', IdentifierType::Exclusion), ('\u{118a0}', '\u{118e9}',
IdentifierType::Exclusion), ('\u{118ea}', '\u{118f2}', IdentifierType::Exclusion),
@@ -1423,255 +1467,283 @@ pub mod identifier {
IdentifierType::Exclusion), ('\u{11a86}', '\u{11a99}', IdentifierType::Exclusion),
('\u{11a9a}', '\u{11a9c}', IdentifierType::Exclusion), ('\u{11a9d}', '\u{11a9d}',
IdentifierType::Exclusion), ('\u{11a9e}', '\u{11aa2}', IdentifierType::Exclusion),
- ('\u{11ac0}', '\u{11af8}', IdentifierType::Exclusion), ('\u{11c00}', '\u{11c08}',
- IdentifierType::Exclusion), ('\u{11c0a}', '\u{11c36}', IdentifierType::Exclusion),
- ('\u{11c38}', '\u{11c40}', IdentifierType::Exclusion), ('\u{11c41}', '\u{11c45}',
- IdentifierType::Exclusion), ('\u{11c50}', '\u{11c59}', IdentifierType::Exclusion),
- ('\u{11c5a}', '\u{11c6c}', IdentifierType::Exclusion), ('\u{11c70}', '\u{11c71}',
- IdentifierType::Exclusion), ('\u{11c72}', '\u{11c8f}', IdentifierType::Exclusion),
- ('\u{11c92}', '\u{11ca7}', IdentifierType::Exclusion), ('\u{11ca9}', '\u{11cb6}',
- IdentifierType::Exclusion), ('\u{11d00}', '\u{11d06}', IdentifierType::Exclusion),
- ('\u{11d08}', '\u{11d09}', IdentifierType::Exclusion), ('\u{11d0b}', '\u{11d36}',
- IdentifierType::Exclusion), ('\u{11d3a}', '\u{11d3a}', IdentifierType::Exclusion),
- ('\u{11d3c}', '\u{11d3d}', IdentifierType::Exclusion), ('\u{11d3f}', '\u{11d47}',
- IdentifierType::Exclusion), ('\u{11d50}', '\u{11d59}', IdentifierType::Exclusion),
- ('\u{11d60}', '\u{11d65}', IdentifierType::Limited_Use), ('\u{11d67}', '\u{11d68}',
- IdentifierType::Limited_Use), ('\u{11d6a}', '\u{11d8e}', IdentifierType::Limited_Use),
- ('\u{11d90}', '\u{11d91}', IdentifierType::Limited_Use), ('\u{11d93}', '\u{11d98}',
- IdentifierType::Limited_Use), ('\u{11da0}', '\u{11da9}', IdentifierType::Limited_Use),
- ('\u{11ee0}', '\u{11ef6}', IdentifierType::Exclusion), ('\u{11ef7}', '\u{11ef8}',
- IdentifierType::Exclusion), ('\u{11fb0}', '\u{11fb0}', IdentifierType::Limited_Use),
- ('\u{11fc0}', '\u{11ff1}', IdentifierType::Not_XID), ('\u{11fff}', '\u{11fff}',
- IdentifierType::Not_XID), ('\u{12000}', '\u{1236e}', IdentifierType::Exclusion),
- ('\u{1236f}', '\u{12398}', IdentifierType::Exclusion), ('\u{12399}', '\u{12399}',
- IdentifierType::Exclusion), ('\u{12400}', '\u{12462}', IdentifierType::Exclusion),
- ('\u{12463}', '\u{1246e}', IdentifierType::Exclusion), ('\u{12470}', '\u{12473}',
- IdentifierType::Exclusion), ('\u{12474}', '\u{12474}', IdentifierType::Exclusion),
- ('\u{12480}', '\u{12543}', IdentifierType::Exclusion), ('\u{13000}', '\u{1342e}',
- IdentifierType::Exclusion), ('\u{13430}', '\u{13438}', IdentifierType::Exclusion),
+ ('\u{11ab0}', '\u{11abf}', IdentifierType::Limited_Use), ('\u{11ac0}', '\u{11af8}',
+ IdentifierType::Exclusion), ('\u{11b00}', '\u{11b09}', IdentifierType::Not_XID),
+ ('\u{11c00}', '\u{11c08}', IdentifierType::Exclusion), ('\u{11c0a}', '\u{11c36}',
+ IdentifierType::Exclusion), ('\u{11c38}', '\u{11c40}', IdentifierType::Exclusion),
+ ('\u{11c41}', '\u{11c45}', IdentifierType::Exclusion), ('\u{11c50}', '\u{11c59}',
+ IdentifierType::Exclusion), ('\u{11c5a}', '\u{11c6c}', IdentifierType::Exclusion),
+ ('\u{11c70}', '\u{11c71}', IdentifierType::Exclusion), ('\u{11c72}', '\u{11c8f}',
+ IdentifierType::Exclusion), ('\u{11c92}', '\u{11ca7}', IdentifierType::Exclusion),
+ ('\u{11ca9}', '\u{11cb6}', IdentifierType::Exclusion), ('\u{11d00}', '\u{11d06}',
+ IdentifierType::Exclusion), ('\u{11d08}', '\u{11d09}', IdentifierType::Exclusion),
+ ('\u{11d0b}', '\u{11d36}', IdentifierType::Exclusion), ('\u{11d3a}', '\u{11d3a}',
+ IdentifierType::Exclusion), ('\u{11d3c}', '\u{11d3d}', IdentifierType::Exclusion),
+ ('\u{11d3f}', '\u{11d47}', IdentifierType::Exclusion), ('\u{11d50}', '\u{11d59}',
+ IdentifierType::Exclusion), ('\u{11d60}', '\u{11d65}', IdentifierType::Limited_Use),
+ ('\u{11d67}', '\u{11d68}', IdentifierType::Limited_Use), ('\u{11d6a}', '\u{11d8e}',
+ IdentifierType::Limited_Use), ('\u{11d90}', '\u{11d91}', IdentifierType::Limited_Use),
+ ('\u{11d93}', '\u{11d98}', IdentifierType::Limited_Use), ('\u{11da0}', '\u{11da9}',
+ IdentifierType::Limited_Use), ('\u{11ee0}', '\u{11ef6}', IdentifierType::Exclusion),
+ ('\u{11ef7}', '\u{11ef8}', IdentifierType::Exclusion), ('\u{11f00}', '\u{11f10}',
+ IdentifierType::Exclusion), ('\u{11f12}', '\u{11f3a}', IdentifierType::Exclusion),
+ ('\u{11f3e}', '\u{11f42}', IdentifierType::Exclusion), ('\u{11f43}', '\u{11f4f}',
+ IdentifierType::Exclusion), ('\u{11f50}', '\u{11f59}', IdentifierType::Exclusion),
+ ('\u{11fb0}', '\u{11fb0}', IdentifierType::Limited_Use), ('\u{11fc0}', '\u{11ff1}',
+ IdentifierType::Not_XID), ('\u{11fff}', '\u{11fff}', IdentifierType::Not_XID),
+ ('\u{12000}', '\u{1236e}', IdentifierType::Exclusion), ('\u{1236f}', '\u{12398}',
+ IdentifierType::Exclusion), ('\u{12399}', '\u{12399}', IdentifierType::Exclusion),
+ ('\u{12400}', '\u{12462}', IdentifierType::Exclusion), ('\u{12463}', '\u{1246e}',
+ IdentifierType::Exclusion), ('\u{12470}', '\u{12473}', IdentifierType::Exclusion),
+ ('\u{12474}', '\u{12474}', IdentifierType::Exclusion), ('\u{12480}', '\u{12543}',
+ IdentifierType::Exclusion), ('\u{12f90}', '\u{12ff0}', IdentifierType::Exclusion),
+ ('\u{12ff1}', '\u{12ff2}', IdentifierType::Exclusion), ('\u{13000}', '\u{1342e}',
+ IdentifierType::Exclusion), ('\u{1342f}', '\u{1342f}', IdentifierType::Exclusion),
+ ('\u{13430}', '\u{13438}', IdentifierType::Exclusion), ('\u{13439}', '\u{1343f}',
+ IdentifierType::Exclusion), ('\u{13440}', '\u{13455}', IdentifierType::Exclusion),
('\u{14400}', '\u{14646}', IdentifierType::Exclusion), ('\u{16800}', '\u{16a38}',
IdentifierType::Limited_Use), ('\u{16a40}', '\u{16a5e}', IdentifierType::Uncommon_Use),
('\u{16a60}', '\u{16a69}', IdentifierType::Uncommon_Use), ('\u{16a6e}', '\u{16a6f}',
- IdentifierType::Exclusion), ('\u{16ad0}', '\u{16aed}', IdentifierType::Exclusion),
- ('\u{16af0}', '\u{16af4}', IdentifierType::Exclusion), ('\u{16af5}', '\u{16af5}',
- IdentifierType::Exclusion), ('\u{16b00}', '\u{16b36}', IdentifierType::Exclusion),
- ('\u{16b37}', '\u{16b3f}', IdentifierType::Exclusion), ('\u{16b40}', '\u{16b43}',
- IdentifierType::Exclusion), ('\u{16b44}', '\u{16b45}', IdentifierType::Exclusion),
- ('\u{16b50}', '\u{16b59}', IdentifierType::Exclusion), ('\u{16b5b}', '\u{16b61}',
- IdentifierType::Exclusion), ('\u{16b63}', '\u{16b77}', IdentifierType::Exclusion),
- ('\u{16b7d}', '\u{16b8f}', IdentifierType::Exclusion), ('\u{16e40}', '\u{16e7f}',
- IdentifierType::Exclusion), ('\u{16e80}', '\u{16e9a}', IdentifierType::Exclusion),
- ('\u{16f00}', '\u{16f44}', IdentifierType::Limited_Use), ('\u{16f45}', '\u{16f4a}',
- IdentifierType::Limited_Use), ('\u{16f4f}', '\u{16f4f}', IdentifierType::Limited_Use),
- ('\u{16f50}', '\u{16f7e}', IdentifierType::Limited_Use), ('\u{16f7f}', '\u{16f87}',
- IdentifierType::Limited_Use), ('\u{16f8f}', '\u{16f9f}', IdentifierType::Limited_Use),
- ('\u{16fe0}', '\u{16fe0}', IdentifierType::Exclusion), ('\u{16fe1}', '\u{16fe1}',
- IdentifierType::Exclusion), ('\u{16fe2}', '\u{16fe2}', IdentifierType::Not_XID),
- ('\u{16fe3}', '\u{16fe3}', IdentifierType::Obsolete), ('\u{16fe4}', '\u{16fe4}',
- IdentifierType::Exclusion), ('\u{16ff0}', '\u{16ff1}', IdentifierType::Recommended),
- ('\u{17000}', '\u{187ec}', IdentifierType::Exclusion), ('\u{187ed}', '\u{187f1}',
- IdentifierType::Exclusion), ('\u{187f2}', '\u{187f7}', IdentifierType::Exclusion),
- ('\u{18800}', '\u{18af2}', IdentifierType::Exclusion), ('\u{18af3}', '\u{18cd5}',
- IdentifierType::Exclusion), ('\u{18d00}', '\u{18d08}', IdentifierType::Exclusion),
- ('\u{1b000}', '\u{1b001}', IdentifierType::Obsolete), ('\u{1b002}', '\u{1b11e}',
- IdentifierType::Obsolete), ('\u{1b150}', '\u{1b152}', IdentifierType::Recommended),
- ('\u{1b164}', '\u{1b167}', IdentifierType::Recommended), ('\u{1b170}', '\u{1b2fb}',
- IdentifierType::Exclusion), ('\u{1bc00}', '\u{1bc6a}', IdentifierType::Exclusion),
- ('\u{1bc70}', '\u{1bc7c}', IdentifierType::Exclusion), ('\u{1bc80}', '\u{1bc88}',
- IdentifierType::Exclusion), ('\u{1bc90}', '\u{1bc99}', IdentifierType::Exclusion),
- ('\u{1bc9c}', '\u{1bc9c}', IdentifierType::Exclusion), ('\u{1bc9d}', '\u{1bc9e}',
- IdentifierType::Exclusion), ('\u{1bc9f}', '\u{1bc9f}', IdentifierType::Exclusion),
- ('\u{1bca0}', '\u{1bca3}', IdentifierType::Default_Ignorable), ('\u{1d000}', '\u{1d0f5}',
- IdentifierType::Technical), ('\u{1d100}', '\u{1d126}', IdentifierType::Technical),
- ('\u{1d129}', '\u{1d129}', IdentifierType::Technical), ('\u{1d12a}', '\u{1d15d}',
- IdentifierType::Technical), ('\u{1d15e}', '\u{1d164}', IdentifierType::Not_NFKC),
- ('\u{1d165}', '\u{1d169}', IdentifierType::Technical), ('\u{1d16a}', '\u{1d16c}',
- IdentifierType::Technical), ('\u{1d16d}', '\u{1d172}', IdentifierType::Technical),
- ('\u{1d173}', '\u{1d17a}', IdentifierType::Default_Ignorable), ('\u{1d17b}', '\u{1d182}',
- IdentifierType::Technical), ('\u{1d183}', '\u{1d184}', IdentifierType::Technical),
- ('\u{1d185}', '\u{1d18b}', IdentifierType::Technical), ('\u{1d18c}', '\u{1d1a9}',
- IdentifierType::Technical), ('\u{1d1aa}', '\u{1d1ad}', IdentifierType::Technical),
- ('\u{1d1ae}', '\u{1d1ba}', IdentifierType::Technical), ('\u{1d1bb}', '\u{1d1c0}',
- IdentifierType::Not_NFKC), ('\u{1d1c1}', '\u{1d1dd}', IdentifierType::Technical),
- ('\u{1d1de}', '\u{1d1e8}', IdentifierType::Uncommon_Use), ('\u{1d200}', '\u{1d241}',
+ IdentifierType::Exclusion), ('\u{16a70}', '\u{16abe}', IdentifierType::Exclusion),
+ ('\u{16ac0}', '\u{16ac9}', IdentifierType::Exclusion), ('\u{16ad0}', '\u{16aed}',
+ IdentifierType::Exclusion), ('\u{16af0}', '\u{16af4}', IdentifierType::Exclusion),
+ ('\u{16af5}', '\u{16af5}', IdentifierType::Exclusion), ('\u{16b00}', '\u{16b36}',
+ IdentifierType::Exclusion), ('\u{16b37}', '\u{16b3f}', IdentifierType::Exclusion),
+ ('\u{16b40}', '\u{16b43}', IdentifierType::Exclusion), ('\u{16b44}', '\u{16b45}',
+ IdentifierType::Exclusion), ('\u{16b50}', '\u{16b59}', IdentifierType::Exclusion),
+ ('\u{16b5b}', '\u{16b61}', IdentifierType::Exclusion), ('\u{16b63}', '\u{16b77}',
+ IdentifierType::Exclusion), ('\u{16b7d}', '\u{16b8f}', IdentifierType::Exclusion),
+ ('\u{16e40}', '\u{16e7f}', IdentifierType::Exclusion), ('\u{16e80}', '\u{16e9a}',
+ IdentifierType::Exclusion), ('\u{16f00}', '\u{16f44}', IdentifierType::Limited_Use),
+ ('\u{16f45}', '\u{16f4a}', IdentifierType::Limited_Use), ('\u{16f4f}', '\u{16f4f}',
+ IdentifierType::Limited_Use), ('\u{16f50}', '\u{16f7e}', IdentifierType::Limited_Use),
+ ('\u{16f7f}', '\u{16f87}', IdentifierType::Limited_Use), ('\u{16f8f}', '\u{16f9f}',
+ IdentifierType::Limited_Use), ('\u{16fe0}', '\u{16fe0}', IdentifierType::Exclusion),
+ ('\u{16fe1}', '\u{16fe1}', IdentifierType::Exclusion), ('\u{16fe2}', '\u{16fe2}',
+ IdentifierType::Not_XID), ('\u{16fe3}', '\u{16fe3}', IdentifierType::Obsolete),
+ ('\u{16fe4}', '\u{16fe4}', IdentifierType::Exclusion), ('\u{16ff0}', '\u{16ff1}',
+ IdentifierType::Recommended), ('\u{17000}', '\u{187ec}', IdentifierType::Exclusion),
+ ('\u{187ed}', '\u{187f1}', IdentifierType::Exclusion), ('\u{187f2}', '\u{187f7}',
+ IdentifierType::Exclusion), ('\u{18800}', '\u{18af2}', IdentifierType::Exclusion),
+ ('\u{18af3}', '\u{18cd5}', IdentifierType::Exclusion), ('\u{18d00}', '\u{18d08}',
+ IdentifierType::Exclusion), ('\u{1aff0}', '\u{1aff3}', IdentifierType::Uncommon_Use),
+ ('\u{1aff5}', '\u{1affb}', IdentifierType::Uncommon_Use), ('\u{1affd}', '\u{1affe}',
+ IdentifierType::Uncommon_Use), ('\u{1b000}', '\u{1b001}', IdentifierType::Obsolete),
+ ('\u{1b002}', '\u{1b11e}', IdentifierType::Obsolete), ('\u{1b11f}', '\u{1b122}',
+ IdentifierType::Recommended), ('\u{1b132}', '\u{1b132}', IdentifierType::Recommended),
+ ('\u{1b150}', '\u{1b152}', IdentifierType::Recommended), ('\u{1b155}', '\u{1b155}',
+ IdentifierType::Recommended), ('\u{1b164}', '\u{1b167}', IdentifierType::Recommended),
+ ('\u{1b170}', '\u{1b2fb}', IdentifierType::Exclusion), ('\u{1bc00}', '\u{1bc6a}',
+ IdentifierType::Exclusion), ('\u{1bc70}', '\u{1bc7c}', IdentifierType::Exclusion),
+ ('\u{1bc80}', '\u{1bc88}', IdentifierType::Exclusion), ('\u{1bc90}', '\u{1bc99}',
+ IdentifierType::Exclusion), ('\u{1bc9c}', '\u{1bc9c}', IdentifierType::Exclusion),
+ ('\u{1bc9d}', '\u{1bc9e}', IdentifierType::Exclusion), ('\u{1bc9f}', '\u{1bc9f}',
+ IdentifierType::Exclusion), ('\u{1bca0}', '\u{1bca3}', IdentifierType::Default_Ignorable),
+ ('\u{1cf00}', '\u{1cf2d}', IdentifierType::Technical), ('\u{1cf30}', '\u{1cf46}',
+ IdentifierType::Technical), ('\u{1cf50}', '\u{1cfc3}', IdentifierType::Technical),
+ ('\u{1d000}', '\u{1d0f5}', IdentifierType::Technical), ('\u{1d100}', '\u{1d126}',
+ IdentifierType::Technical), ('\u{1d129}', '\u{1d129}', IdentifierType::Technical),
+ ('\u{1d12a}', '\u{1d15d}', IdentifierType::Technical), ('\u{1d15e}', '\u{1d164}',
+ IdentifierType::Not_NFKC), ('\u{1d165}', '\u{1d169}', IdentifierType::Technical),
+ ('\u{1d16a}', '\u{1d16c}', IdentifierType::Technical), ('\u{1d16d}', '\u{1d172}',
+ IdentifierType::Technical), ('\u{1d173}', '\u{1d17a}', IdentifierType::Default_Ignorable),
+ ('\u{1d17b}', '\u{1d182}', IdentifierType::Technical), ('\u{1d183}', '\u{1d184}',
+ IdentifierType::Technical), ('\u{1d185}', '\u{1d18b}', IdentifierType::Technical),
+ ('\u{1d18c}', '\u{1d1a9}', IdentifierType::Technical), ('\u{1d1aa}', '\u{1d1ad}',
+ IdentifierType::Technical), ('\u{1d1ae}', '\u{1d1ba}', IdentifierType::Technical),
+ ('\u{1d1bb}', '\u{1d1c0}', IdentifierType::Not_NFKC), ('\u{1d1c1}', '\u{1d1dd}',
+ IdentifierType::Technical), ('\u{1d1de}', '\u{1d1e8}', IdentifierType::Uncommon_Use),
+ ('\u{1d1e9}', '\u{1d1ea}', IdentifierType::Technical), ('\u{1d200}', '\u{1d241}',
IdentifierType::Obsolete), ('\u{1d242}', '\u{1d244}', IdentifierType::Technical),
- ('\u{1d245}', '\u{1d245}', IdentifierType::Obsolete), ('\u{1d2e0}', '\u{1d2f3}',
- IdentifierType::Not_XID), ('\u{1d300}', '\u{1d356}', IdentifierType::Technical),
- ('\u{1d360}', '\u{1d371}', IdentifierType::Not_XID), ('\u{1d372}', '\u{1d378}',
- IdentifierType::Not_XID), ('\u{1d400}', '\u{1d454}', IdentifierType::Not_NFKC),
- ('\u{1d456}', '\u{1d49c}', IdentifierType::Not_NFKC), ('\u{1d49e}', '\u{1d49f}',
- IdentifierType::Not_NFKC), ('\u{1d4a2}', '\u{1d4a2}', IdentifierType::Not_NFKC),
- ('\u{1d4a5}', '\u{1d4a6}', IdentifierType::Not_NFKC), ('\u{1d4a9}', '\u{1d4ac}',
- IdentifierType::Not_NFKC), ('\u{1d4ae}', '\u{1d4b9}', IdentifierType::Not_NFKC),
- ('\u{1d4bb}', '\u{1d4bb}', IdentifierType::Not_NFKC), ('\u{1d4bd}', '\u{1d4c0}',
- IdentifierType::Not_NFKC), ('\u{1d4c1}', '\u{1d4c1}', IdentifierType::Not_NFKC),
- ('\u{1d4c2}', '\u{1d4c3}', IdentifierType::Not_NFKC), ('\u{1d4c5}', '\u{1d505}',
- IdentifierType::Not_NFKC), ('\u{1d507}', '\u{1d50a}', IdentifierType::Not_NFKC),
- ('\u{1d50d}', '\u{1d514}', IdentifierType::Not_NFKC), ('\u{1d516}', '\u{1d51c}',
- IdentifierType::Not_NFKC), ('\u{1d51e}', '\u{1d539}', IdentifierType::Not_NFKC),
- ('\u{1d53b}', '\u{1d53e}', IdentifierType::Not_NFKC), ('\u{1d540}', '\u{1d544}',
- IdentifierType::Not_NFKC), ('\u{1d546}', '\u{1d546}', IdentifierType::Not_NFKC),
- ('\u{1d54a}', '\u{1d550}', IdentifierType::Not_NFKC), ('\u{1d552}', '\u{1d6a3}',
- IdentifierType::Not_NFKC), ('\u{1d6a4}', '\u{1d6a5}', IdentifierType::Not_NFKC),
- ('\u{1d6a8}', '\u{1d7c9}', IdentifierType::Not_NFKC), ('\u{1d7ca}', '\u{1d7cb}',
- IdentifierType::Not_NFKC), ('\u{1d7ce}', '\u{1d7ff}', IdentifierType::Not_NFKC),
- ('\u{1d800}', '\u{1d9ff}', IdentifierType::Exclusion), ('\u{1da00}', '\u{1da36}',
- IdentifierType::Exclusion), ('\u{1da37}', '\u{1da3a}', IdentifierType::Exclusion),
- ('\u{1da3b}', '\u{1da6c}', IdentifierType::Exclusion), ('\u{1da6d}', '\u{1da74}',
- IdentifierType::Exclusion), ('\u{1da75}', '\u{1da75}', IdentifierType::Exclusion),
- ('\u{1da76}', '\u{1da83}', IdentifierType::Exclusion), ('\u{1da84}', '\u{1da84}',
- IdentifierType::Exclusion), ('\u{1da85}', '\u{1da8b}', IdentifierType::Exclusion),
- ('\u{1da9b}', '\u{1da9f}', IdentifierType::Exclusion), ('\u{1daa1}', '\u{1daaf}',
- IdentifierType::Exclusion), ('\u{1e000}', '\u{1e006}', IdentifierType::Exclusion),
+ ('\u{1d245}', '\u{1d245}', IdentifierType::Obsolete), ('\u{1d2c0}', '\u{1d2d3}',
+ IdentifierType::Not_XID), ('\u{1d2e0}', '\u{1d2f3}', IdentifierType::Not_XID),
+ ('\u{1d300}', '\u{1d356}', IdentifierType::Technical), ('\u{1d360}', '\u{1d371}',
+ IdentifierType::Not_XID), ('\u{1d372}', '\u{1d378}', IdentifierType::Not_XID),
+ ('\u{1d400}', '\u{1d454}', IdentifierType::Not_NFKC), ('\u{1d456}', '\u{1d49c}',
+ IdentifierType::Not_NFKC), ('\u{1d49e}', '\u{1d49f}', IdentifierType::Not_NFKC),
+ ('\u{1d4a2}', '\u{1d4a2}', IdentifierType::Not_NFKC), ('\u{1d4a5}', '\u{1d4a6}',
+ IdentifierType::Not_NFKC), ('\u{1d4a9}', '\u{1d4ac}', IdentifierType::Not_NFKC),
+ ('\u{1d4ae}', '\u{1d4b9}', IdentifierType::Not_NFKC), ('\u{1d4bb}', '\u{1d4bb}',
+ IdentifierType::Not_NFKC), ('\u{1d4bd}', '\u{1d4c0}', IdentifierType::Not_NFKC),
+ ('\u{1d4c1}', '\u{1d4c1}', IdentifierType::Not_NFKC), ('\u{1d4c2}', '\u{1d4c3}',
+ IdentifierType::Not_NFKC), ('\u{1d4c5}', '\u{1d505}', IdentifierType::Not_NFKC),
+ ('\u{1d507}', '\u{1d50a}', IdentifierType::Not_NFKC), ('\u{1d50d}', '\u{1d514}',
+ IdentifierType::Not_NFKC), ('\u{1d516}', '\u{1d51c}', IdentifierType::Not_NFKC),
+ ('\u{1d51e}', '\u{1d539}', IdentifierType::Not_NFKC), ('\u{1d53b}', '\u{1d53e}',
+ IdentifierType::Not_NFKC), ('\u{1d540}', '\u{1d544}', IdentifierType::Not_NFKC),
+ ('\u{1d546}', '\u{1d546}', IdentifierType::Not_NFKC), ('\u{1d54a}', '\u{1d550}',
+ IdentifierType::Not_NFKC), ('\u{1d552}', '\u{1d6a3}', IdentifierType::Not_NFKC),
+ ('\u{1d6a4}', '\u{1d6a5}', IdentifierType::Not_NFKC), ('\u{1d6a8}', '\u{1d7c9}',
+ IdentifierType::Not_NFKC), ('\u{1d7ca}', '\u{1d7cb}', IdentifierType::Not_NFKC),
+ ('\u{1d7ce}', '\u{1d7ff}', IdentifierType::Not_NFKC), ('\u{1d800}', '\u{1d9ff}',
+ IdentifierType::Exclusion), ('\u{1da00}', '\u{1da36}', IdentifierType::Exclusion),
+ ('\u{1da37}', '\u{1da3a}', IdentifierType::Exclusion), ('\u{1da3b}', '\u{1da6c}',
+ IdentifierType::Exclusion), ('\u{1da6d}', '\u{1da74}', IdentifierType::Exclusion),
+ ('\u{1da75}', '\u{1da75}', IdentifierType::Exclusion), ('\u{1da76}', '\u{1da83}',
+ IdentifierType::Exclusion), ('\u{1da84}', '\u{1da84}', IdentifierType::Exclusion),
+ ('\u{1da85}', '\u{1da8b}', IdentifierType::Exclusion), ('\u{1da9b}', '\u{1da9f}',
+ IdentifierType::Exclusion), ('\u{1daa1}', '\u{1daaf}', IdentifierType::Exclusion),
+ ('\u{1df00}', '\u{1df1e}', IdentifierType::Recommended), ('\u{1df25}', '\u{1df2a}',
+ IdentifierType::Recommended), ('\u{1e000}', '\u{1e006}', IdentifierType::Exclusion),
('\u{1e008}', '\u{1e018}', IdentifierType::Exclusion), ('\u{1e01b}', '\u{1e021}',
IdentifierType::Exclusion), ('\u{1e023}', '\u{1e024}', IdentifierType::Exclusion),
- ('\u{1e026}', '\u{1e02a}', IdentifierType::Exclusion), ('\u{1e100}', '\u{1e12c}',
- IdentifierType::Limited_Use), ('\u{1e130}', '\u{1e13d}', IdentifierType::Limited_Use),
- ('\u{1e140}', '\u{1e149}', IdentifierType::Limited_Use), ('\u{1e14e}', '\u{1e14e}',
- IdentifierType::Limited_Use), ('\u{1e14f}', '\u{1e14f}', IdentifierType::Limited_Use),
+ ('\u{1e026}', '\u{1e02a}', IdentifierType::Exclusion), ('\u{1e030}', '\u{1e06d}',
+ IdentifierType::Not_NFKC), ('\u{1e08f}', '\u{1e08f}', IdentifierType::Recommended),
+ ('\u{1e100}', '\u{1e12c}', IdentifierType::Limited_Use), ('\u{1e130}', '\u{1e13d}',
+ IdentifierType::Limited_Use), ('\u{1e140}', '\u{1e149}', IdentifierType::Limited_Use),
+ ('\u{1e14e}', '\u{1e14e}', IdentifierType::Limited_Use), ('\u{1e14f}', '\u{1e14f}',
+ IdentifierType::Limited_Use), ('\u{1e290}', '\u{1e2ae}', IdentifierType::Exclusion),
('\u{1e2c0}', '\u{1e2f9}', IdentifierType::Limited_Use), ('\u{1e2ff}', '\u{1e2ff}',
- IdentifierType::Limited_Use), ('\u{1e800}', '\u{1e8c4}', IdentifierType::Exclusion),
- ('\u{1e8c7}', '\u{1e8cf}', IdentifierType::Exclusion), ('\u{1e8d0}', '\u{1e8d6}',
- IdentifierType::Exclusion), ('\u{1e900}', '\u{1e94a}', IdentifierType::Limited_Use),
- ('\u{1e94b}', '\u{1e94b}', IdentifierType::Limited_Use), ('\u{1e950}', '\u{1e959}',
- IdentifierType::Limited_Use), ('\u{1e95e}', '\u{1e95f}', IdentifierType::Limited_Use),
- ('\u{1ec71}', '\u{1ecb4}', IdentifierType::Not_XID), ('\u{1ed01}', '\u{1ed3d}',
- IdentifierType::Not_XID), ('\u{1ee00}', '\u{1ee03}', IdentifierType::Not_NFKC),
- ('\u{1ee05}', '\u{1ee1f}', IdentifierType::Not_NFKC), ('\u{1ee21}', '\u{1ee22}',
- IdentifierType::Not_NFKC), ('\u{1ee24}', '\u{1ee24}', IdentifierType::Not_NFKC),
- ('\u{1ee27}', '\u{1ee27}', IdentifierType::Not_NFKC), ('\u{1ee29}', '\u{1ee32}',
- IdentifierType::Not_NFKC), ('\u{1ee34}', '\u{1ee37}', IdentifierType::Not_NFKC),
- ('\u{1ee39}', '\u{1ee39}', IdentifierType::Not_NFKC), ('\u{1ee3b}', '\u{1ee3b}',
- IdentifierType::Not_NFKC), ('\u{1ee42}', '\u{1ee42}', IdentifierType::Not_NFKC),
- ('\u{1ee47}', '\u{1ee47}', IdentifierType::Not_NFKC), ('\u{1ee49}', '\u{1ee49}',
- IdentifierType::Not_NFKC), ('\u{1ee4b}', '\u{1ee4b}', IdentifierType::Not_NFKC),
- ('\u{1ee4d}', '\u{1ee4f}', IdentifierType::Not_NFKC), ('\u{1ee51}', '\u{1ee52}',
- IdentifierType::Not_NFKC), ('\u{1ee54}', '\u{1ee54}', IdentifierType::Not_NFKC),
- ('\u{1ee57}', '\u{1ee57}', IdentifierType::Not_NFKC), ('\u{1ee59}', '\u{1ee59}',
- IdentifierType::Not_NFKC), ('\u{1ee5b}', '\u{1ee5b}', IdentifierType::Not_NFKC),
- ('\u{1ee5d}', '\u{1ee5d}', IdentifierType::Not_NFKC), ('\u{1ee5f}', '\u{1ee5f}',
- IdentifierType::Not_NFKC), ('\u{1ee61}', '\u{1ee62}', IdentifierType::Not_NFKC),
- ('\u{1ee64}', '\u{1ee64}', IdentifierType::Not_NFKC), ('\u{1ee67}', '\u{1ee6a}',
- IdentifierType::Not_NFKC), ('\u{1ee6c}', '\u{1ee72}', IdentifierType::Not_NFKC),
- ('\u{1ee74}', '\u{1ee77}', IdentifierType::Not_NFKC), ('\u{1ee79}', '\u{1ee7c}',
- IdentifierType::Not_NFKC), ('\u{1ee7e}', '\u{1ee7e}', IdentifierType::Not_NFKC),
- ('\u{1ee80}', '\u{1ee89}', IdentifierType::Not_NFKC), ('\u{1ee8b}', '\u{1ee9b}',
- IdentifierType::Not_NFKC), ('\u{1eea1}', '\u{1eea3}', IdentifierType::Not_NFKC),
- ('\u{1eea5}', '\u{1eea9}', IdentifierType::Not_NFKC), ('\u{1eeab}', '\u{1eebb}',
- IdentifierType::Not_NFKC), ('\u{1eef0}', '\u{1eef1}', IdentifierType::Not_XID),
- ('\u{1f000}', '\u{1f02b}', IdentifierType::Not_XID), ('\u{1f030}', '\u{1f093}',
- IdentifierType::Not_XID), ('\u{1f0a0}', '\u{1f0ae}', IdentifierType::Not_XID),
- ('\u{1f0b1}', '\u{1f0be}', IdentifierType::Not_XID), ('\u{1f0bf}', '\u{1f0bf}',
- IdentifierType::Not_XID), ('\u{1f0c1}', '\u{1f0cf}', IdentifierType::Not_XID),
- ('\u{1f0d1}', '\u{1f0df}', IdentifierType::Not_XID), ('\u{1f0e0}', '\u{1f0f5}',
- IdentifierType::Not_XID), ('\u{1f100}', '\u{1f10a}', IdentifierType::Not_NFKC),
- ('\u{1f10b}', '\u{1f10c}', IdentifierType::Not_XID), ('\u{1f10d}', '\u{1f10f}',
- IdentifierType::Not_XID), ('\u{1f110}', '\u{1f12e}', IdentifierType::Not_NFKC),
- ('\u{1f12f}', '\u{1f12f}', IdentifierType::Not_XID), ('\u{1f130}', '\u{1f130}',
- IdentifierType::Not_NFKC), ('\u{1f131}', '\u{1f131}', IdentifierType::Not_NFKC),
- ('\u{1f132}', '\u{1f13c}', IdentifierType::Not_NFKC), ('\u{1f13d}', '\u{1f13d}',
- IdentifierType::Not_NFKC), ('\u{1f13e}', '\u{1f13e}', IdentifierType::Not_NFKC),
- ('\u{1f13f}', '\u{1f13f}', IdentifierType::Not_NFKC), ('\u{1f140}', '\u{1f141}',
- IdentifierType::Not_NFKC), ('\u{1f142}', '\u{1f142}', IdentifierType::Not_NFKC),
- ('\u{1f143}', '\u{1f145}', IdentifierType::Not_NFKC), ('\u{1f146}', '\u{1f146}',
- IdentifierType::Not_NFKC), ('\u{1f147}', '\u{1f149}', IdentifierType::Not_NFKC),
- ('\u{1f14a}', '\u{1f14e}', IdentifierType::Not_NFKC), ('\u{1f14f}', '\u{1f14f}',
- IdentifierType::Not_NFKC), ('\u{1f150}', '\u{1f156}', IdentifierType::Not_XID),
- ('\u{1f157}', '\u{1f157}', IdentifierType::Not_XID), ('\u{1f158}', '\u{1f15e}',
- IdentifierType::Not_XID), ('\u{1f15f}', '\u{1f15f}', IdentifierType::Not_XID),
- ('\u{1f160}', '\u{1f169}', IdentifierType::Not_XID), ('\u{1f16a}', '\u{1f16b}',
- IdentifierType::Not_NFKC), ('\u{1f16c}', '\u{1f16c}', IdentifierType::Not_NFKC),
- ('\u{1f16d}', '\u{1f16f}', IdentifierType::Not_XID), ('\u{1f170}', '\u{1f178}',
- IdentifierType::Not_XID), ('\u{1f179}', '\u{1f179}', IdentifierType::Not_XID),
- ('\u{1f17a}', '\u{1f17a}', IdentifierType::Not_XID), ('\u{1f17b}', '\u{1f17c}',
- IdentifierType::Not_XID), ('\u{1f17d}', '\u{1f17e}', IdentifierType::Not_XID),
- ('\u{1f17f}', '\u{1f17f}', IdentifierType::Not_XID), ('\u{1f180}', '\u{1f189}',
- IdentifierType::Not_XID), ('\u{1f18a}', '\u{1f18d}', IdentifierType::Not_XID),
- ('\u{1f18e}', '\u{1f18f}', IdentifierType::Not_XID), ('\u{1f190}', '\u{1f190}',
- IdentifierType::Not_NFKC), ('\u{1f191}', '\u{1f19a}', IdentifierType::Not_XID),
- ('\u{1f19b}', '\u{1f1ac}', IdentifierType::Not_XID), ('\u{1f1ad}', '\u{1f1ad}',
- IdentifierType::Not_XID), ('\u{1f1e6}', '\u{1f1ff}', IdentifierType::Not_XID),
- ('\u{1f200}', '\u{1f200}', IdentifierType::Not_NFKC), ('\u{1f201}', '\u{1f202}',
- IdentifierType::Not_NFKC), ('\u{1f210}', '\u{1f231}', IdentifierType::Not_NFKC),
- ('\u{1f232}', '\u{1f23a}', IdentifierType::Not_NFKC), ('\u{1f23b}', '\u{1f23b}',
- IdentifierType::Not_NFKC), ('\u{1f240}', '\u{1f248}', IdentifierType::Not_NFKC),
- ('\u{1f250}', '\u{1f251}', IdentifierType::Not_NFKC), ('\u{1f260}', '\u{1f265}',
- IdentifierType::Not_XID), ('\u{1f300}', '\u{1f320}', IdentifierType::Not_XID),
- ('\u{1f321}', '\u{1f32c}', IdentifierType::Not_XID), ('\u{1f32d}', '\u{1f32f}',
- IdentifierType::Not_XID), ('\u{1f330}', '\u{1f335}', IdentifierType::Not_XID),
- ('\u{1f336}', '\u{1f336}', IdentifierType::Not_XID), ('\u{1f337}', '\u{1f37c}',
- IdentifierType::Not_XID), ('\u{1f37d}', '\u{1f37d}', IdentifierType::Not_XID),
- ('\u{1f37e}', '\u{1f37f}', IdentifierType::Not_XID), ('\u{1f380}', '\u{1f393}',
- IdentifierType::Not_XID), ('\u{1f394}', '\u{1f39f}', IdentifierType::Not_XID),
- ('\u{1f3a0}', '\u{1f3c4}', IdentifierType::Not_XID), ('\u{1f3c5}', '\u{1f3c5}',
- IdentifierType::Not_XID), ('\u{1f3c6}', '\u{1f3ca}', IdentifierType::Not_XID),
- ('\u{1f3cb}', '\u{1f3ce}', IdentifierType::Not_XID), ('\u{1f3cf}', '\u{1f3d3}',
- IdentifierType::Not_XID), ('\u{1f3d4}', '\u{1f3df}', IdentifierType::Not_XID),
- ('\u{1f3e0}', '\u{1f3f0}', IdentifierType::Not_XID), ('\u{1f3f1}', '\u{1f3f7}',
- IdentifierType::Not_XID), ('\u{1f3f8}', '\u{1f3ff}', IdentifierType::Not_XID),
- ('\u{1f400}', '\u{1f43e}', IdentifierType::Not_XID), ('\u{1f43f}', '\u{1f43f}',
- IdentifierType::Not_XID), ('\u{1f440}', '\u{1f440}', IdentifierType::Not_XID),
- ('\u{1f441}', '\u{1f441}', IdentifierType::Not_XID), ('\u{1f442}', '\u{1f4f7}',
- IdentifierType::Not_XID), ('\u{1f4f8}', '\u{1f4f8}', IdentifierType::Not_XID),
- ('\u{1f4f9}', '\u{1f4fc}', IdentifierType::Not_XID), ('\u{1f4fd}', '\u{1f4fe}',
- IdentifierType::Not_XID), ('\u{1f4ff}', '\u{1f4ff}', IdentifierType::Not_XID),
- ('\u{1f500}', '\u{1f53d}', IdentifierType::Not_XID), ('\u{1f53e}', '\u{1f53f}',
- IdentifierType::Not_XID), ('\u{1f540}', '\u{1f543}', IdentifierType::Not_XID),
- ('\u{1f544}', '\u{1f54a}', IdentifierType::Not_XID), ('\u{1f54b}', '\u{1f54e}',
- IdentifierType::Not_XID), ('\u{1f54f}', '\u{1f54f}', IdentifierType::Uncommon_Use),
- ('\u{1f550}', '\u{1f567}', IdentifierType::Not_XID), ('\u{1f568}', '\u{1f579}',
- IdentifierType::Not_XID), ('\u{1f57a}', '\u{1f57a}', IdentifierType::Not_XID),
- ('\u{1f57b}', '\u{1f5a3}', IdentifierType::Not_XID), ('\u{1f5a4}', '\u{1f5a4}',
- IdentifierType::Not_XID), ('\u{1f5a5}', '\u{1f5fa}', IdentifierType::Not_XID),
- ('\u{1f5fb}', '\u{1f5ff}', IdentifierType::Not_XID), ('\u{1f600}', '\u{1f600}',
- IdentifierType::Not_XID), ('\u{1f601}', '\u{1f610}', IdentifierType::Not_XID),
- ('\u{1f611}', '\u{1f611}', IdentifierType::Not_XID), ('\u{1f612}', '\u{1f614}',
- IdentifierType::Not_XID), ('\u{1f615}', '\u{1f615}', IdentifierType::Not_XID),
- ('\u{1f616}', '\u{1f616}', IdentifierType::Not_XID), ('\u{1f617}', '\u{1f617}',
- IdentifierType::Not_XID), ('\u{1f618}', '\u{1f618}', IdentifierType::Not_XID),
- ('\u{1f619}', '\u{1f619}', IdentifierType::Not_XID), ('\u{1f61a}', '\u{1f61a}',
- IdentifierType::Not_XID), ('\u{1f61b}', '\u{1f61b}', IdentifierType::Not_XID),
- ('\u{1f61c}', '\u{1f61e}', IdentifierType::Not_XID), ('\u{1f61f}', '\u{1f61f}',
- IdentifierType::Not_XID), ('\u{1f620}', '\u{1f625}', IdentifierType::Not_XID),
- ('\u{1f626}', '\u{1f627}', IdentifierType::Not_XID), ('\u{1f628}', '\u{1f62b}',
- IdentifierType::Not_XID), ('\u{1f62c}', '\u{1f62c}', IdentifierType::Not_XID),
- ('\u{1f62d}', '\u{1f62d}', IdentifierType::Not_XID), ('\u{1f62e}', '\u{1f62f}',
- IdentifierType::Not_XID), ('\u{1f630}', '\u{1f633}', IdentifierType::Not_XID),
- ('\u{1f634}', '\u{1f634}', IdentifierType::Not_XID), ('\u{1f635}', '\u{1f640}',
- IdentifierType::Not_XID), ('\u{1f641}', '\u{1f642}', IdentifierType::Not_XID),
- ('\u{1f643}', '\u{1f644}', IdentifierType::Not_XID), ('\u{1f645}', '\u{1f64f}',
- IdentifierType::Not_XID), ('\u{1f650}', '\u{1f67f}', IdentifierType::Not_XID),
- ('\u{1f680}', '\u{1f6c5}', IdentifierType::Not_XID), ('\u{1f6c6}', '\u{1f6cf}',
- IdentifierType::Not_XID), ('\u{1f6d0}', '\u{1f6d0}', IdentifierType::Not_XID),
- ('\u{1f6d1}', '\u{1f6d2}', IdentifierType::Not_XID), ('\u{1f6d3}', '\u{1f6d4}',
- IdentifierType::Not_XID), ('\u{1f6d5}', '\u{1f6d5}', IdentifierType::Not_XID),
- ('\u{1f6d6}', '\u{1f6d7}', IdentifierType::Not_XID), ('\u{1f6e0}', '\u{1f6ec}',
- IdentifierType::Not_XID), ('\u{1f6f0}', '\u{1f6f3}', IdentifierType::Not_XID),
- ('\u{1f6f4}', '\u{1f6f6}', IdentifierType::Not_XID), ('\u{1f6f7}', '\u{1f6f8}',
- IdentifierType::Not_XID), ('\u{1f6f9}', '\u{1f6f9}', IdentifierType::Not_XID),
- ('\u{1f6fa}', '\u{1f6fa}', IdentifierType::Not_XID), ('\u{1f6fb}', '\u{1f6fc}',
- IdentifierType::Not_XID), ('\u{1f700}', '\u{1f773}', IdentifierType::Not_XID),
+ IdentifierType::Limited_Use), ('\u{1e4d0}', '\u{1e4f9}', IdentifierType::Exclusion),
+ ('\u{1e7e0}', '\u{1e7e6}', IdentifierType::Recommended), ('\u{1e7e8}', '\u{1e7eb}',
+ IdentifierType::Recommended), ('\u{1e7ed}', '\u{1e7ee}', IdentifierType::Recommended),
+ ('\u{1e7f0}', '\u{1e7fe}', IdentifierType::Recommended), ('\u{1e800}', '\u{1e8c4}',
+ IdentifierType::Exclusion), ('\u{1e8c7}', '\u{1e8cf}', IdentifierType::Exclusion),
+ ('\u{1e8d0}', '\u{1e8d6}', IdentifierType::Exclusion), ('\u{1e900}', '\u{1e94a}',
+ IdentifierType::Limited_Use), ('\u{1e94b}', '\u{1e94b}', IdentifierType::Limited_Use),
+ ('\u{1e950}', '\u{1e959}', IdentifierType::Limited_Use), ('\u{1e95e}', '\u{1e95f}',
+ IdentifierType::Limited_Use), ('\u{1ec71}', '\u{1ecb4}', IdentifierType::Not_XID),
+ ('\u{1ed01}', '\u{1ed3d}', IdentifierType::Not_XID), ('\u{1ee00}', '\u{1ee03}',
+ IdentifierType::Not_NFKC), ('\u{1ee05}', '\u{1ee1f}', IdentifierType::Not_NFKC),
+ ('\u{1ee21}', '\u{1ee22}', IdentifierType::Not_NFKC), ('\u{1ee24}', '\u{1ee24}',
+ IdentifierType::Not_NFKC), ('\u{1ee27}', '\u{1ee27}', IdentifierType::Not_NFKC),
+ ('\u{1ee29}', '\u{1ee32}', IdentifierType::Not_NFKC), ('\u{1ee34}', '\u{1ee37}',
+ IdentifierType::Not_NFKC), ('\u{1ee39}', '\u{1ee39}', IdentifierType::Not_NFKC),
+ ('\u{1ee3b}', '\u{1ee3b}', IdentifierType::Not_NFKC), ('\u{1ee42}', '\u{1ee42}',
+ IdentifierType::Not_NFKC), ('\u{1ee47}', '\u{1ee47}', IdentifierType::Not_NFKC),
+ ('\u{1ee49}', '\u{1ee49}', IdentifierType::Not_NFKC), ('\u{1ee4b}', '\u{1ee4b}',
+ IdentifierType::Not_NFKC), ('\u{1ee4d}', '\u{1ee4f}', IdentifierType::Not_NFKC),
+ ('\u{1ee51}', '\u{1ee52}', IdentifierType::Not_NFKC), ('\u{1ee54}', '\u{1ee54}',
+ IdentifierType::Not_NFKC), ('\u{1ee57}', '\u{1ee57}', IdentifierType::Not_NFKC),
+ ('\u{1ee59}', '\u{1ee59}', IdentifierType::Not_NFKC), ('\u{1ee5b}', '\u{1ee5b}',
+ IdentifierType::Not_NFKC), ('\u{1ee5d}', '\u{1ee5d}', IdentifierType::Not_NFKC),
+ ('\u{1ee5f}', '\u{1ee5f}', IdentifierType::Not_NFKC), ('\u{1ee61}', '\u{1ee62}',
+ IdentifierType::Not_NFKC), ('\u{1ee64}', '\u{1ee64}', IdentifierType::Not_NFKC),
+ ('\u{1ee67}', '\u{1ee6a}', IdentifierType::Not_NFKC), ('\u{1ee6c}', '\u{1ee72}',
+ IdentifierType::Not_NFKC), ('\u{1ee74}', '\u{1ee77}', IdentifierType::Not_NFKC),
+ ('\u{1ee79}', '\u{1ee7c}', IdentifierType::Not_NFKC), ('\u{1ee7e}', '\u{1ee7e}',
+ IdentifierType::Not_NFKC), ('\u{1ee80}', '\u{1ee89}', IdentifierType::Not_NFKC),
+ ('\u{1ee8b}', '\u{1ee9b}', IdentifierType::Not_NFKC), ('\u{1eea1}', '\u{1eea3}',
+ IdentifierType::Not_NFKC), ('\u{1eea5}', '\u{1eea9}', IdentifierType::Not_NFKC),
+ ('\u{1eeab}', '\u{1eebb}', IdentifierType::Not_NFKC), ('\u{1eef0}', '\u{1eef1}',
+ IdentifierType::Not_XID), ('\u{1f000}', '\u{1f02b}', IdentifierType::Not_XID),
+ ('\u{1f030}', '\u{1f093}', IdentifierType::Not_XID), ('\u{1f0a0}', '\u{1f0ae}',
+ IdentifierType::Not_XID), ('\u{1f0b1}', '\u{1f0be}', IdentifierType::Not_XID),
+ ('\u{1f0bf}', '\u{1f0bf}', IdentifierType::Not_XID), ('\u{1f0c1}', '\u{1f0cf}',
+ IdentifierType::Not_XID), ('\u{1f0d1}', '\u{1f0df}', IdentifierType::Not_XID),
+ ('\u{1f0e0}', '\u{1f0f5}', IdentifierType::Not_XID), ('\u{1f100}', '\u{1f10a}',
+ IdentifierType::Not_NFKC), ('\u{1f10b}', '\u{1f10c}', IdentifierType::Not_XID),
+ ('\u{1f10d}', '\u{1f10f}', IdentifierType::Not_XID), ('\u{1f110}', '\u{1f12e}',
+ IdentifierType::Not_NFKC), ('\u{1f12f}', '\u{1f12f}', IdentifierType::Not_XID),
+ ('\u{1f130}', '\u{1f130}', IdentifierType::Not_NFKC), ('\u{1f131}', '\u{1f131}',
+ IdentifierType::Not_NFKC), ('\u{1f132}', '\u{1f13c}', IdentifierType::Not_NFKC),
+ ('\u{1f13d}', '\u{1f13d}', IdentifierType::Not_NFKC), ('\u{1f13e}', '\u{1f13e}',
+ IdentifierType::Not_NFKC), ('\u{1f13f}', '\u{1f13f}', IdentifierType::Not_NFKC),
+ ('\u{1f140}', '\u{1f141}', IdentifierType::Not_NFKC), ('\u{1f142}', '\u{1f142}',
+ IdentifierType::Not_NFKC), ('\u{1f143}', '\u{1f145}', IdentifierType::Not_NFKC),
+ ('\u{1f146}', '\u{1f146}', IdentifierType::Not_NFKC), ('\u{1f147}', '\u{1f149}',
+ IdentifierType::Not_NFKC), ('\u{1f14a}', '\u{1f14e}', IdentifierType::Not_NFKC),
+ ('\u{1f14f}', '\u{1f14f}', IdentifierType::Not_NFKC), ('\u{1f150}', '\u{1f156}',
+ IdentifierType::Not_XID), ('\u{1f157}', '\u{1f157}', IdentifierType::Not_XID),
+ ('\u{1f158}', '\u{1f15e}', IdentifierType::Not_XID), ('\u{1f15f}', '\u{1f15f}',
+ IdentifierType::Not_XID), ('\u{1f160}', '\u{1f169}', IdentifierType::Not_XID),
+ ('\u{1f16a}', '\u{1f16b}', IdentifierType::Not_NFKC), ('\u{1f16c}', '\u{1f16c}',
+ IdentifierType::Not_NFKC), ('\u{1f16d}', '\u{1f16f}', IdentifierType::Not_XID),
+ ('\u{1f170}', '\u{1f178}', IdentifierType::Not_XID), ('\u{1f179}', '\u{1f179}',
+ IdentifierType::Not_XID), ('\u{1f17a}', '\u{1f17a}', IdentifierType::Not_XID),
+ ('\u{1f17b}', '\u{1f17c}', IdentifierType::Not_XID), ('\u{1f17d}', '\u{1f17e}',
+ IdentifierType::Not_XID), ('\u{1f17f}', '\u{1f17f}', IdentifierType::Not_XID),
+ ('\u{1f180}', '\u{1f189}', IdentifierType::Not_XID), ('\u{1f18a}', '\u{1f18d}',
+ IdentifierType::Not_XID), ('\u{1f18e}', '\u{1f18f}', IdentifierType::Not_XID),
+ ('\u{1f190}', '\u{1f190}', IdentifierType::Not_NFKC), ('\u{1f191}', '\u{1f19a}',
+ IdentifierType::Not_XID), ('\u{1f19b}', '\u{1f1ac}', IdentifierType::Not_XID),
+ ('\u{1f1ad}', '\u{1f1ad}', IdentifierType::Not_XID), ('\u{1f1e6}', '\u{1f1ff}',
+ IdentifierType::Not_XID), ('\u{1f200}', '\u{1f200}', IdentifierType::Not_NFKC),
+ ('\u{1f201}', '\u{1f202}', IdentifierType::Not_NFKC), ('\u{1f210}', '\u{1f231}',
+ IdentifierType::Not_NFKC), ('\u{1f232}', '\u{1f23a}', IdentifierType::Not_NFKC),
+ ('\u{1f23b}', '\u{1f23b}', IdentifierType::Not_NFKC), ('\u{1f240}', '\u{1f248}',
+ IdentifierType::Not_NFKC), ('\u{1f250}', '\u{1f251}', IdentifierType::Not_NFKC),
+ ('\u{1f260}', '\u{1f265}', IdentifierType::Not_XID), ('\u{1f300}', '\u{1f320}',
+ IdentifierType::Not_XID), ('\u{1f321}', '\u{1f32c}', IdentifierType::Not_XID),
+ ('\u{1f32d}', '\u{1f32f}', IdentifierType::Not_XID), ('\u{1f330}', '\u{1f335}',
+ IdentifierType::Not_XID), ('\u{1f336}', '\u{1f336}', IdentifierType::Not_XID),
+ ('\u{1f337}', '\u{1f37c}', IdentifierType::Not_XID), ('\u{1f37d}', '\u{1f37d}',
+ IdentifierType::Not_XID), ('\u{1f37e}', '\u{1f37f}', IdentifierType::Not_XID),
+ ('\u{1f380}', '\u{1f393}', IdentifierType::Not_XID), ('\u{1f394}', '\u{1f39f}',
+ IdentifierType::Not_XID), ('\u{1f3a0}', '\u{1f3c4}', IdentifierType::Not_XID),
+ ('\u{1f3c5}', '\u{1f3c5}', IdentifierType::Not_XID), ('\u{1f3c6}', '\u{1f3ca}',
+ IdentifierType::Not_XID), ('\u{1f3cb}', '\u{1f3ce}', IdentifierType::Not_XID),
+ ('\u{1f3cf}', '\u{1f3d3}', IdentifierType::Not_XID), ('\u{1f3d4}', '\u{1f3df}',
+ IdentifierType::Not_XID), ('\u{1f3e0}', '\u{1f3f0}', IdentifierType::Not_XID),
+ ('\u{1f3f1}', '\u{1f3f7}', IdentifierType::Not_XID), ('\u{1f3f8}', '\u{1f3ff}',
+ IdentifierType::Not_XID), ('\u{1f400}', '\u{1f43e}', IdentifierType::Not_XID),
+ ('\u{1f43f}', '\u{1f43f}', IdentifierType::Not_XID), ('\u{1f440}', '\u{1f440}',
+ IdentifierType::Not_XID), ('\u{1f441}', '\u{1f441}', IdentifierType::Not_XID),
+ ('\u{1f442}', '\u{1f4f7}', IdentifierType::Not_XID), ('\u{1f4f8}', '\u{1f4f8}',
+ IdentifierType::Not_XID), ('\u{1f4f9}', '\u{1f4fc}', IdentifierType::Not_XID),
+ ('\u{1f4fd}', '\u{1f4fe}', IdentifierType::Not_XID), ('\u{1f4ff}', '\u{1f4ff}',
+ IdentifierType::Not_XID), ('\u{1f500}', '\u{1f53d}', IdentifierType::Not_XID),
+ ('\u{1f53e}', '\u{1f53f}', IdentifierType::Not_XID), ('\u{1f540}', '\u{1f543}',
+ IdentifierType::Not_XID), ('\u{1f544}', '\u{1f54a}', IdentifierType::Not_XID),
+ ('\u{1f54b}', '\u{1f54e}', IdentifierType::Not_XID), ('\u{1f54f}', '\u{1f54f}',
+ IdentifierType::Uncommon_Use), ('\u{1f550}', '\u{1f567}', IdentifierType::Not_XID),
+ ('\u{1f568}', '\u{1f579}', IdentifierType::Not_XID), ('\u{1f57a}', '\u{1f57a}',
+ IdentifierType::Not_XID), ('\u{1f57b}', '\u{1f5a3}', IdentifierType::Not_XID),
+ ('\u{1f5a4}', '\u{1f5a4}', IdentifierType::Not_XID), ('\u{1f5a5}', '\u{1f5fa}',
+ IdentifierType::Not_XID), ('\u{1f5fb}', '\u{1f5ff}', IdentifierType::Not_XID),
+ ('\u{1f600}', '\u{1f600}', IdentifierType::Not_XID), ('\u{1f601}', '\u{1f610}',
+ IdentifierType::Not_XID), ('\u{1f611}', '\u{1f611}', IdentifierType::Not_XID),
+ ('\u{1f612}', '\u{1f614}', IdentifierType::Not_XID), ('\u{1f615}', '\u{1f615}',
+ IdentifierType::Not_XID), ('\u{1f616}', '\u{1f616}', IdentifierType::Not_XID),
+ ('\u{1f617}', '\u{1f617}', IdentifierType::Not_XID), ('\u{1f618}', '\u{1f618}',
+ IdentifierType::Not_XID), ('\u{1f619}', '\u{1f619}', IdentifierType::Not_XID),
+ ('\u{1f61a}', '\u{1f61a}', IdentifierType::Not_XID), ('\u{1f61b}', '\u{1f61b}',
+ IdentifierType::Not_XID), ('\u{1f61c}', '\u{1f61e}', IdentifierType::Not_XID),
+ ('\u{1f61f}', '\u{1f61f}', IdentifierType::Not_XID), ('\u{1f620}', '\u{1f625}',
+ IdentifierType::Not_XID), ('\u{1f626}', '\u{1f627}', IdentifierType::Not_XID),
+ ('\u{1f628}', '\u{1f62b}', IdentifierType::Not_XID), ('\u{1f62c}', '\u{1f62c}',
+ IdentifierType::Not_XID), ('\u{1f62d}', '\u{1f62d}', IdentifierType::Not_XID),
+ ('\u{1f62e}', '\u{1f62f}', IdentifierType::Not_XID), ('\u{1f630}', '\u{1f633}',
+ IdentifierType::Not_XID), ('\u{1f634}', '\u{1f634}', IdentifierType::Not_XID),
+ ('\u{1f635}', '\u{1f640}', IdentifierType::Not_XID), ('\u{1f641}', '\u{1f642}',
+ IdentifierType::Not_XID), ('\u{1f643}', '\u{1f644}', IdentifierType::Not_XID),
+ ('\u{1f645}', '\u{1f64f}', IdentifierType::Not_XID), ('\u{1f650}', '\u{1f67f}',
+ IdentifierType::Not_XID), ('\u{1f680}', '\u{1f6c5}', IdentifierType::Not_XID),
+ ('\u{1f6c6}', '\u{1f6cf}', IdentifierType::Not_XID), ('\u{1f6d0}', '\u{1f6d0}',
+ IdentifierType::Not_XID), ('\u{1f6d1}', '\u{1f6d2}', IdentifierType::Not_XID),
+ ('\u{1f6d3}', '\u{1f6d4}', IdentifierType::Not_XID), ('\u{1f6d5}', '\u{1f6d5}',
+ IdentifierType::Not_XID), ('\u{1f6d6}', '\u{1f6d7}', IdentifierType::Not_XID),
+ ('\u{1f6dc}', '\u{1f6dc}', IdentifierType::Not_XID), ('\u{1f6dd}', '\u{1f6df}',
+ IdentifierType::Not_XID), ('\u{1f6e0}', '\u{1f6ec}', IdentifierType::Not_XID),
+ ('\u{1f6f0}', '\u{1f6f3}', IdentifierType::Not_XID), ('\u{1f6f4}', '\u{1f6f6}',
+ IdentifierType::Not_XID), ('\u{1f6f7}', '\u{1f6f8}', IdentifierType::Not_XID),
+ ('\u{1f6f9}', '\u{1f6f9}', IdentifierType::Not_XID), ('\u{1f6fa}', '\u{1f6fa}',
+ IdentifierType::Not_XID), ('\u{1f6fb}', '\u{1f6fc}', IdentifierType::Not_XID),
+ ('\u{1f700}', '\u{1f773}', IdentifierType::Not_XID), ('\u{1f774}', '\u{1f776}',
+ IdentifierType::Not_XID), ('\u{1f77b}', '\u{1f77f}', IdentifierType::Not_XID),
('\u{1f780}', '\u{1f7d4}', IdentifierType::Not_XID), ('\u{1f7d5}', '\u{1f7d8}',
- IdentifierType::Not_XID), ('\u{1f7e0}', '\u{1f7eb}', IdentifierType::Not_XID),
- ('\u{1f800}', '\u{1f80b}', IdentifierType::Not_XID), ('\u{1f810}', '\u{1f847}',
- IdentifierType::Not_XID), ('\u{1f850}', '\u{1f859}', IdentifierType::Not_XID),
- ('\u{1f860}', '\u{1f887}', IdentifierType::Not_XID), ('\u{1f890}', '\u{1f8ad}',
- IdentifierType::Not_XID), ('\u{1f8b0}', '\u{1f8b1}', IdentifierType::Not_XID),
- ('\u{1f900}', '\u{1f90b}', IdentifierType::Not_XID), ('\u{1f90c}', '\u{1f90c}',
- IdentifierType::Not_XID), ('\u{1f90d}', '\u{1f90f}', IdentifierType::Not_XID),
- ('\u{1f910}', '\u{1f918}', IdentifierType::Not_XID), ('\u{1f919}', '\u{1f91e}',
- IdentifierType::Not_XID), ('\u{1f91f}', '\u{1f91f}', IdentifierType::Not_XID),
- ('\u{1f920}', '\u{1f927}', IdentifierType::Not_XID), ('\u{1f928}', '\u{1f92f}',
- IdentifierType::Not_XID), ('\u{1f930}', '\u{1f930}', IdentifierType::Not_XID),
- ('\u{1f931}', '\u{1f932}', IdentifierType::Not_XID), ('\u{1f933}', '\u{1f93e}',
- IdentifierType::Not_XID), ('\u{1f93f}', '\u{1f93f}', IdentifierType::Not_XID),
- ('\u{1f940}', '\u{1f94b}', IdentifierType::Not_XID), ('\u{1f94c}', '\u{1f94c}',
- IdentifierType::Not_XID), ('\u{1f94d}', '\u{1f94f}', IdentifierType::Not_XID),
- ('\u{1f950}', '\u{1f95e}', IdentifierType::Not_XID), ('\u{1f95f}', '\u{1f96b}',
- IdentifierType::Not_XID), ('\u{1f96c}', '\u{1f970}', IdentifierType::Not_XID),
- ('\u{1f971}', '\u{1f971}', IdentifierType::Not_XID), ('\u{1f972}', '\u{1f972}',
- IdentifierType::Not_XID), ('\u{1f973}', '\u{1f976}', IdentifierType::Not_XID),
- ('\u{1f977}', '\u{1f978}', IdentifierType::Not_XID), ('\u{1f97a}', '\u{1f97a}',
+ IdentifierType::Not_XID), ('\u{1f7d9}', '\u{1f7d9}', IdentifierType::Not_XID),
+ ('\u{1f7e0}', '\u{1f7eb}', IdentifierType::Not_XID), ('\u{1f7f0}', '\u{1f7f0}',
+ IdentifierType::Not_XID), ('\u{1f800}', '\u{1f80b}', IdentifierType::Not_XID),
+ ('\u{1f810}', '\u{1f847}', IdentifierType::Not_XID), ('\u{1f850}', '\u{1f859}',
+ IdentifierType::Not_XID), ('\u{1f860}', '\u{1f887}', IdentifierType::Not_XID),
+ ('\u{1f890}', '\u{1f8ad}', IdentifierType::Not_XID), ('\u{1f8b0}', '\u{1f8b1}',
+ IdentifierType::Not_XID), ('\u{1f900}', '\u{1f90b}', IdentifierType::Not_XID),
+ ('\u{1f90c}', '\u{1f90c}', IdentifierType::Not_XID), ('\u{1f90d}', '\u{1f90f}',
+ IdentifierType::Not_XID), ('\u{1f910}', '\u{1f918}', IdentifierType::Not_XID),
+ ('\u{1f919}', '\u{1f91e}', IdentifierType::Not_XID), ('\u{1f91f}', '\u{1f91f}',
+ IdentifierType::Not_XID), ('\u{1f920}', '\u{1f927}', IdentifierType::Not_XID),
+ ('\u{1f928}', '\u{1f92f}', IdentifierType::Not_XID), ('\u{1f930}', '\u{1f930}',
+ IdentifierType::Not_XID), ('\u{1f931}', '\u{1f932}', IdentifierType::Not_XID),
+ ('\u{1f933}', '\u{1f93e}', IdentifierType::Not_XID), ('\u{1f93f}', '\u{1f93f}',
+ IdentifierType::Not_XID), ('\u{1f940}', '\u{1f94b}', IdentifierType::Not_XID),
+ ('\u{1f94c}', '\u{1f94c}', IdentifierType::Not_XID), ('\u{1f94d}', '\u{1f94f}',
+ IdentifierType::Not_XID), ('\u{1f950}', '\u{1f95e}', IdentifierType::Not_XID),
+ ('\u{1f95f}', '\u{1f96b}', IdentifierType::Not_XID), ('\u{1f96c}', '\u{1f970}',
+ IdentifierType::Not_XID), ('\u{1f971}', '\u{1f971}', IdentifierType::Not_XID),
+ ('\u{1f972}', '\u{1f972}', IdentifierType::Not_XID), ('\u{1f973}', '\u{1f976}',
+ IdentifierType::Not_XID), ('\u{1f977}', '\u{1f978}', IdentifierType::Not_XID),
+ ('\u{1f979}', '\u{1f979}', IdentifierType::Not_XID), ('\u{1f97a}', '\u{1f97a}',
IdentifierType::Not_XID), ('\u{1f97b}', '\u{1f97b}', IdentifierType::Not_XID),
('\u{1f97c}', '\u{1f97f}', IdentifierType::Not_XID), ('\u{1f980}', '\u{1f984}',
IdentifierType::Not_XID), ('\u{1f985}', '\u{1f991}', IdentifierType::Not_XID),
@@ -1683,23 +1755,37 @@ pub mod identifier {
IdentifierType::Not_XID), ('\u{1f9c0}', '\u{1f9c0}', IdentifierType::Not_XID),
('\u{1f9c1}', '\u{1f9c2}', IdentifierType::Not_XID), ('\u{1f9c3}', '\u{1f9ca}',
IdentifierType::Not_XID), ('\u{1f9cb}', '\u{1f9cb}', IdentifierType::Not_XID),
- ('\u{1f9cd}', '\u{1f9cf}', IdentifierType::Not_XID), ('\u{1f9d0}', '\u{1f9e6}',
- IdentifierType::Not_XID), ('\u{1f9e7}', '\u{1f9ff}', IdentifierType::Not_XID),
- ('\u{1fa00}', '\u{1fa53}', IdentifierType::Not_XID), ('\u{1fa60}', '\u{1fa6d}',
- IdentifierType::Not_XID), ('\u{1fa70}', '\u{1fa73}', IdentifierType::Not_XID),
- ('\u{1fa74}', '\u{1fa74}', IdentifierType::Not_XID), ('\u{1fa78}', '\u{1fa7a}',
+ ('\u{1f9cc}', '\u{1f9cc}', IdentifierType::Not_XID), ('\u{1f9cd}', '\u{1f9cf}',
+ IdentifierType::Not_XID), ('\u{1f9d0}', '\u{1f9e6}', IdentifierType::Not_XID),
+ ('\u{1f9e7}', '\u{1f9ff}', IdentifierType::Not_XID), ('\u{1fa00}', '\u{1fa53}',
+ IdentifierType::Not_XID), ('\u{1fa60}', '\u{1fa6d}', IdentifierType::Not_XID),
+ ('\u{1fa70}', '\u{1fa73}', IdentifierType::Not_XID), ('\u{1fa74}', '\u{1fa74}',
+ IdentifierType::Not_XID), ('\u{1fa75}', '\u{1fa77}', IdentifierType::Not_XID),
+ ('\u{1fa78}', '\u{1fa7a}', IdentifierType::Not_XID), ('\u{1fa7b}', '\u{1fa7c}',
IdentifierType::Not_XID), ('\u{1fa80}', '\u{1fa82}', IdentifierType::Not_XID),
- ('\u{1fa83}', '\u{1fa86}', IdentifierType::Not_XID), ('\u{1fa90}', '\u{1fa95}',
- IdentifierType::Not_XID), ('\u{1fa96}', '\u{1faa8}', IdentifierType::Not_XID),
- ('\u{1fab0}', '\u{1fab6}', IdentifierType::Not_XID), ('\u{1fac0}', '\u{1fac2}',
- IdentifierType::Not_XID), ('\u{1fad0}', '\u{1fad6}', IdentifierType::Not_XID),
- ('\u{1fb00}', '\u{1fb92}', IdentifierType::Not_XID), ('\u{1fb94}', '\u{1fbca}',
- IdentifierType::Not_XID), ('\u{1fbf0}', '\u{1fbf9}', IdentifierType::Not_NFKC),
- ('\u{20000}', '\u{2a6d6}', IdentifierType::Recommended), ('\u{2a6d7}', '\u{2a6dd}',
+ ('\u{1fa83}', '\u{1fa86}', IdentifierType::Not_XID), ('\u{1fa87}', '\u{1fa88}',
+ IdentifierType::Not_XID), ('\u{1fa90}', '\u{1fa95}', IdentifierType::Not_XID),
+ ('\u{1fa96}', '\u{1faa8}', IdentifierType::Not_XID), ('\u{1faa9}', '\u{1faac}',
+ IdentifierType::Not_XID), ('\u{1faad}', '\u{1faaf}', IdentifierType::Not_XID),
+ ('\u{1fab0}', '\u{1fab6}', IdentifierType::Not_XID), ('\u{1fab7}', '\u{1faba}',
+ IdentifierType::Not_XID), ('\u{1fabb}', '\u{1fabd}', IdentifierType::Not_XID),
+ ('\u{1fabf}', '\u{1fabf}', IdentifierType::Not_XID), ('\u{1fac0}', '\u{1fac2}',
+ IdentifierType::Not_XID), ('\u{1fac3}', '\u{1fac5}', IdentifierType::Not_XID),
+ ('\u{1face}', '\u{1facf}', IdentifierType::Not_XID), ('\u{1fad0}', '\u{1fad6}',
+ IdentifierType::Not_XID), ('\u{1fad7}', '\u{1fad9}', IdentifierType::Not_XID),
+ ('\u{1fada}', '\u{1fadb}', IdentifierType::Not_XID), ('\u{1fae0}', '\u{1fae7}',
+ IdentifierType::Not_XID), ('\u{1fae8}', '\u{1fae8}', IdentifierType::Not_XID),
+ ('\u{1faf0}', '\u{1faf6}', IdentifierType::Not_XID), ('\u{1faf7}', '\u{1faf8}',
+ IdentifierType::Not_XID), ('\u{1fb00}', '\u{1fb92}', IdentifierType::Not_XID),
+ ('\u{1fb94}', '\u{1fbca}', IdentifierType::Not_XID), ('\u{1fbf0}', '\u{1fbf9}',
+ IdentifierType::Not_NFKC), ('\u{20000}', '\u{2a6d6}', IdentifierType::Recommended),
+ ('\u{2a6d7}', '\u{2a6dd}', IdentifierType::Recommended), ('\u{2a6de}', '\u{2a6df}',
IdentifierType::Recommended), ('\u{2a700}', '\u{2b734}', IdentifierType::Recommended),
- ('\u{2b740}', '\u{2b81d}', IdentifierType::Recommended), ('\u{2b820}', '\u{2cea1}',
- IdentifierType::Recommended), ('\u{2ceb0}', '\u{2ebe0}', IdentifierType::Recommended),
- ('\u{2f800}', '\u{2fa1d}', IdentifierType::Not_NFKC), ('\u{30000}', '\u{3134a}',
+ ('\u{2b735}', '\u{2b738}', IdentifierType::Recommended), ('\u{2b739}', '\u{2b739}',
+ IdentifierType::Recommended), ('\u{2b740}', '\u{2b81d}', IdentifierType::Recommended),
+ ('\u{2b820}', '\u{2cea1}', IdentifierType::Recommended), ('\u{2ceb0}', '\u{2ebe0}',
+ IdentifierType::Recommended), ('\u{2f800}', '\u{2fa1d}', IdentifierType::Not_NFKC),
+ ('\u{30000}', '\u{3134a}', IdentifierType::Recommended), ('\u{31350}', '\u{323af}',
IdentifierType::Recommended), ('\u{e0001}', '\u{e0001}', IdentifierType::Deprecated),
('\u{e0020}', '\u{e007f}', IdentifierType::Default_Ignorable), ('\u{e0100}', '\u{e01ef}',
IdentifierType::Default_Ignorable)
@@ -4281,10 +4367,10 @@ pub mod potential_mixed_script_confusable {
'\u{101d}', '\u{1036}', '\u{1038}', '\u{1040}', '\u{10e7}', '\u{10ff}', '\u{1200}',
'\u{1206}', '\u{1223}', '\u{1240}', '\u{1260}', '\u{1261}', '\u{1294}', '\u{12ae}',
'\u{12d0}', '\u{1323}', '\u{17b7}', '\u{17b8}', '\u{17b9}', '\u{17ba}', '\u{17c6}',
- '\u{3007}', '\u{304f}', '\u{3078}', '\u{30a4}', '\u{30a8}', '\u{30ab}', '\u{30bf}',
- '\u{30c8}', '\u{30cb}', '\u{30ce}', '\u{30cf}', '\u{30d8}', '\u{30ed}', '\u{4e00}',
- '\u{4e3f}', '\u{4e8c}', '\u{4ebb}', '\u{516b}', '\u{529b}', '\u{535c}', '\u{53e3}',
- '\u{56d7}', '\u{5915}', '\u{5de5}', '\u{a792}', '\u{a793}', '\u{21fe8}'
+ '\u{17cb}', '\u{3007}', '\u{304f}', '\u{3078}', '\u{30a4}', '\u{30a8}', '\u{30ab}',
+ '\u{30bf}', '\u{30c8}', '\u{30cb}', '\u{30ce}', '\u{30cf}', '\u{30d8}', '\u{30ed}',
+ '\u{4e00}', '\u{4e3f}', '\u{4e8c}', '\u{4ebb}', '\u{516b}', '\u{529b}', '\u{535c}',
+ '\u{53e3}', '\u{56d7}', '\u{5915}', '\u{5de5}', '\u{a792}', '\u{a793}', '\u{21fe8}'
];
}
diff --git a/vendor/unicode-segmentation/.cargo-checksum.json b/vendor/unicode-segmentation/.cargo-checksum.json
index f9b266839..acc5d5d0e 100644
--- a/vendor/unicode-segmentation/.cargo-checksum.json
+++ b/vendor/unicode-segmentation/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"56be6b873eab00a7504dc74b43b67b94945707ad5fb008b970ee55d3bb35faca","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"efe7aa058e004e12d683039dbc4440e2fec3088364201a620703acedbeef8cb2","benches/graphemes.rs":"88a9f672ea7a03cc15fae36ce544a6e7234e532359402483978858ccda47db3d","benches/unicode_words.rs":"95c3a178ebe07c8cb2c560546ee911bfc4f1e1db81a6cd2c1cef1c99ed2a421a","benches/word_bounds.rs":"66acf40c0a4b06cdb6dd97c1759aba8dea961bb30cd7f223de3ebff8198520b2","scripts/unicode.py":"772c3aba1ae87f4cee562e824a225a7a230a710d9ca21593bc7845f1fe70e7ef","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"b5a32bdbb529e9417e8ada8d92656339b6ffb4e9bed8e6d32a0409c13a03050b","src/lib.rs":"572789173717edd0fe037ae656530663406951636c548e6793711b7d5caad910","src/sentence.rs":"aac52f69207e0b68925ab0c6c18cc36ed3da8e918006d96d724f0f19d4d9d643","src/tables.rs":"117efdcf284aaf2b456a5da6a0948a65a9b0bde498a9aad687bebb551b5b061e","src/test.rs":"f039fa285d510244672a067bdbe98ce7ff940e4f2ff82926466e012ac48ad95a","src/testdata.rs":"2429f421557d0d65c9b167a5fd29c5e61f0d197c9221053adefc2f862311752c","src/word.rs":"6eeea9351c12f0a4404606596a487e0e8aa948ba4b134c7cb827ee41557a39fe"},"package":"7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"} \ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"55e5a65c91693dd47a27409e54ad6d5ce805ce003b822e4a568bfd070725e956","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"efe7aa058e004e12d683039dbc4440e2fec3088364201a620703acedbeef8cb2","benches/graphemes.rs":"88a9f672ea7a03cc15fae36ce544a6e7234e532359402483978858ccda47db3d","benches/unicode_words.rs":"95c3a178ebe07c8cb2c560546ee911bfc4f1e1db81a6cd2c1cef1c99ed2a421a","benches/word_bounds.rs":"66acf40c0a4b06cdb6dd97c1759aba8dea961bb30cd7f223de3ebff8198520b2","scripts/unicode.py":"d4ba970a0419f33d20f3deb888be12427bfbb40aa25a5719968600d45cf4dadb","scripts/unicode_gen_breaktests.py":"ee96982d8959bec75c2382233cfca7e239f12a89a1be5fbf942601a215bb9283","src/grapheme.rs":"b5a32bdbb529e9417e8ada8d92656339b6ffb4e9bed8e6d32a0409c13a03050b","src/lib.rs":"572789173717edd0fe037ae656530663406951636c548e6793711b7d5caad910","src/sentence.rs":"aac52f69207e0b68925ab0c6c18cc36ed3da8e918006d96d724f0f19d4d9d643","src/tables.rs":"ba9fa1774b6294ed14565ec6be0f2ec316759d54e3af7c002b6848973d7b1f3c","src/test.rs":"f039fa285d510244672a067bdbe98ce7ff940e4f2ff82926466e012ac48ad95a","src/testdata.rs":"533c02ecace1bec3d46b65d101c7619bc83a2fb2c187a2c960346533c09a0e3e","src/word.rs":"6eeea9351c12f0a4404606596a487e0e8aa948ba4b134c7cb827ee41557a39fe"},"package":"0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"} \ No newline at end of file
diff --git a/vendor/unicode-segmentation/Cargo.toml b/vendor/unicode-segmentation/Cargo.toml
index 697beb38a..0da56c81e 100644
--- a/vendor/unicode-segmentation/Cargo.toml
+++ b/vendor/unicode-segmentation/Cargo.toml
@@ -12,14 +12,32 @@
[package]
edition = "2018"
name = "unicode-segmentation"
-version = "1.9.0"
-authors = ["kwantam <kwantam@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
-exclude = ["target/*", "Cargo.lock", "scripts/tmp", "benches/texts/*", "*.txt"]
-description = "This crate provides Grapheme Cluster, Word and Sentence boundaries\naccording to Unicode Standard Annex #29 rules.\n"
+version = "1.10.0"
+authors = [
+ "kwantam <kwantam@gmail.com>",
+ "Manish Goregaokar <manishsmail@gmail.com>",
+]
+exclude = [
+ "target/*",
+ "Cargo.lock",
+ "scripts/tmp",
+ "benches/texts/*",
+ "*.txt",
+]
+description = """
+This crate provides Grapheme Cluster, Word and Sentence boundaries
+according to Unicode Standard Annex #29 rules.
+"""
homepage = "https://github.com/unicode-rs/unicode-segmentation"
documentation = "https://unicode-rs.github.io/unicode-segmentation"
readme = "README.md"
-keywords = ["text", "unicode", "grapheme", "word", "boundary"]
+keywords = [
+ "text",
+ "unicode",
+ "grapheme",
+ "word",
+ "boundary",
+]
license = "MIT/Apache-2.0"
repository = "https://github.com/unicode-rs/unicode-segmentation"
@@ -34,6 +52,7 @@ harness = false
[[bench]]
name = "word_bounds"
harness = false
+
[dev-dependencies.criterion]
version = "0.3"
diff --git a/vendor/unicode-segmentation/scripts/unicode.py b/vendor/unicode-segmentation/scripts/unicode.py
index 4976d62e3..7aed85e7c 100755
--- a/vendor/unicode-segmentation/scripts/unicode.py
+++ b/vendor/unicode-segmentation/scripts/unicode.py
@@ -54,7 +54,7 @@ expanded_categories = {
# these are the surrogate codepoints, which are not valid rust characters
surrogate_codepoints = (0xd800, 0xdfff)
-UNICODE_VERSION = (14, 0, 0)
+UNICODE_VERSION = (15, 0, 0)
UNICODE_VERSION_NUMBER = "%s.%s.%s" %UNICODE_VERSION
diff --git a/vendor/unicode-segmentation/src/tables.rs b/vendor/unicode-segmentation/src/tables.rs
index b96a01d56..5a811c922 100644
--- a/vendor/unicode-segmentation/src/tables.rs
+++ b/vendor/unicode-segmentation/src/tables.rs
@@ -14,7 +14,7 @@
/// The version of [Unicode](http://www.unicode.org/)
/// that this version of unicode-segmentation is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (14, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0);
pub mod util {
#[inline]
@@ -87,11 +87,12 @@ mod general_category {
('\u{11450}', '\u{11459}'), ('\u{114d0}', '\u{114d9}'), ('\u{11650}', '\u{11659}'),
('\u{116c0}', '\u{116c9}'), ('\u{11730}', '\u{1173b}'), ('\u{118e0}', '\u{118f2}'),
('\u{11950}', '\u{11959}'), ('\u{11c50}', '\u{11c6c}'), ('\u{11d50}', '\u{11d59}'),
- ('\u{11da0}', '\u{11da9}'), ('\u{11fc0}', '\u{11fd4}'), ('\u{12400}', '\u{1246e}'),
- ('\u{16a60}', '\u{16a69}'), ('\u{16ac0}', '\u{16ac9}'), ('\u{16b50}', '\u{16b59}'),
- ('\u{16b5b}', '\u{16b61}'), ('\u{16e80}', '\u{16e96}'), ('\u{1d2e0}', '\u{1d2f3}'),
- ('\u{1d360}', '\u{1d378}'), ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1e140}', '\u{1e149}'),
- ('\u{1e2f0}', '\u{1e2f9}'), ('\u{1e8c7}', '\u{1e8cf}'), ('\u{1e950}', '\u{1e959}'),
+ ('\u{11da0}', '\u{11da9}'), ('\u{11f50}', '\u{11f59}'), ('\u{11fc0}', '\u{11fd4}'),
+ ('\u{12400}', '\u{1246e}'), ('\u{16a60}', '\u{16a69}'), ('\u{16ac0}', '\u{16ac9}'),
+ ('\u{16b50}', '\u{16b59}'), ('\u{16b5b}', '\u{16b61}'), ('\u{16e80}', '\u{16e96}'),
+ ('\u{1d2c0}', '\u{1d2d3}'), ('\u{1d2e0}', '\u{1d2f3}'), ('\u{1d360}', '\u{1d378}'),
+ ('\u{1d7ce}', '\u{1d7ff}'), ('\u{1e140}', '\u{1e149}'), ('\u{1e2f0}', '\u{1e2f9}'),
+ ('\u{1e4f0}', '\u{1e4f9}'), ('\u{1e8c7}', '\u{1e8cf}'), ('\u{1e950}', '\u{1e959}'),
('\u{1ec71}', '\u{1ecab}'), ('\u{1ecad}', '\u{1ecaf}'), ('\u{1ecb1}', '\u{1ecb4}'),
('\u{1ed01}', '\u{1ed2d}'), ('\u{1ed2f}', '\u{1ed3d}'), ('\u{1f100}', '\u{1f10c}'),
('\u{1fbf0}', '\u{1fbf9}')
@@ -144,189 +145,192 @@ mod derived_property {
'\u{b9a}'), ('\u{b9c}', '\u{b9c}'), ('\u{b9e}', '\u{b9f}'), ('\u{ba3}', '\u{ba4}'),
('\u{ba8}', '\u{baa}'), ('\u{bae}', '\u{bb9}'), ('\u{bbe}', '\u{bc2}'), ('\u{bc6}',
'\u{bc8}'), ('\u{bca}', '\u{bcc}'), ('\u{bd0}', '\u{bd0}'), ('\u{bd7}', '\u{bd7}'),
- ('\u{c00}', '\u{c03}'), ('\u{c05}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}',
- '\u{c28}'), ('\u{c2a}', '\u{c39}'), ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'),
- ('\u{c4a}', '\u{c4c}'), ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c5d}',
- '\u{c5d}'), ('\u{c60}', '\u{c63}'), ('\u{c80}', '\u{c83}'), ('\u{c85}', '\u{c8c}'),
- ('\u{c8e}', '\u{c90}'), ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}',
- '\u{cb9}'), ('\u{cbd}', '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccc}'),
- ('\u{cd5}', '\u{cd6}'), ('\u{cdd}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{cf1}',
- '\u{cf2}'), ('\u{d00}', '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'),
- ('\u{d3d}', '\u{d44}'), ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4c}'), ('\u{d4e}',
- '\u{d4e}'), ('\u{d54}', '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d7a}', '\u{d7f}'),
- ('\u{d81}', '\u{d83}'), ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}',
- '\u{dbb}'), ('\u{dbd}', '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dcf}', '\u{dd4}'),
- ('\u{dd6}', '\u{dd6}'), ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{e01}',
- '\u{e3a}'), ('\u{e40}', '\u{e46}'), ('\u{e4d}', '\u{e4d}'), ('\u{e81}', '\u{e82}'),
- ('\u{e84}', '\u{e84}'), ('\u{e86}', '\u{e8a}'), ('\u{e8c}', '\u{ea3}'), ('\u{ea5}',
- '\u{ea5}'), ('\u{ea7}', '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'),
- ('\u{ec6}', '\u{ec6}'), ('\u{ecd}', '\u{ecd}'), ('\u{edc}', '\u{edf}'), ('\u{f00}',
- '\u{f00}'), ('\u{f40}', '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f81}'),
- ('\u{f88}', '\u{f97}'), ('\u{f99}', '\u{fbc}'), ('\u{1000}', '\u{1036}'), ('\u{1038}',
- '\u{1038}'), ('\u{103b}', '\u{103f}'), ('\u{1050}', '\u{108f}'), ('\u{109a}', '\u{109d}'),
- ('\u{10a0}', '\u{10c5}'), ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}',
- '\u{10fa}'), ('\u{10fc}', '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'),
- ('\u{1258}', '\u{1258}'), ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}',
- '\u{128d}'), ('\u{1290}', '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'),
- ('\u{12c0}', '\u{12c0}'), ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}',
- '\u{1310}'), ('\u{1312}', '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'),
- ('\u{13a0}', '\u{13f5}'), ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'), ('\u{166f}',
- '\u{167f}'), ('\u{1681}', '\u{169a}'), ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}'),
- ('\u{1700}', '\u{1713}'), ('\u{171f}', '\u{1733}'), ('\u{1740}', '\u{1753}'), ('\u{1760}',
- '\u{176c}'), ('\u{176e}', '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17b3}'),
- ('\u{17b6}', '\u{17c8}'), ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), ('\u{1820}',
- '\u{1878}'), ('\u{1880}', '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}', '\u{191e}'),
- ('\u{1920}', '\u{192b}'), ('\u{1930}', '\u{1938}'), ('\u{1950}', '\u{196d}'), ('\u{1970}',
- '\u{1974}'), ('\u{1980}', '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}', '\u{1a1b}'),
- ('\u{1a20}', '\u{1a5e}'), ('\u{1a61}', '\u{1a74}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1abf}',
- '\u{1ac0}'), ('\u{1acc}', '\u{1ace}'), ('\u{1b00}', '\u{1b33}'), ('\u{1b35}', '\u{1b43}'),
- ('\u{1b45}', '\u{1b4c}'), ('\u{1b80}', '\u{1ba9}'), ('\u{1bac}', '\u{1baf}'), ('\u{1bba}',
- '\u{1be5}'), ('\u{1be7}', '\u{1bf1}'), ('\u{1c00}', '\u{1c36}'), ('\u{1c4d}', '\u{1c4f}'),
- ('\u{1c5a}', '\u{1c7d}'), ('\u{1c80}', '\u{1c88}'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}',
- '\u{1cbf}'), ('\u{1ce9}', '\u{1cec}'), ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'),
- ('\u{1cfa}', '\u{1cfa}'), ('\u{1d00}', '\u{1dbf}'), ('\u{1de7}', '\u{1df4}'), ('\u{1e00}',
- '\u{1f15}'), ('\u{1f18}', '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'),
- ('\u{1f50}', '\u{1f57}'), ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}',
- '\u{1f5d}'), ('\u{1f5f}', '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'),
- ('\u{1fbe}', '\u{1fbe}'), ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}',
- '\u{1fd3}'), ('\u{1fd6}', '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'),
- ('\u{1ff6}', '\u{1ffc}'), ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}',
- '\u{209c}'), ('\u{2102}', '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'),
- ('\u{2115}', '\u{2115}'), ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}',
- '\u{2126}'), ('\u{2128}', '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2139}'),
- ('\u{213c}', '\u{213f}'), ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}',
- '\u{2188}'), ('\u{24b6}', '\u{24e9}'), ('\u{2c00}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'),
- ('\u{2cf2}', '\u{2cf3}'), ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}',
- '\u{2d2d}'), ('\u{2d30}', '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'),
- ('\u{2da0}', '\u{2da6}'), ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}',
- '\u{2dbe}'), ('\u{2dc0}', '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'),
- ('\u{2dd8}', '\u{2dde}'), ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}',
- '\u{3007}'), ('\u{3021}', '\u{3029}'), ('\u{3031}', '\u{3035}'), ('\u{3038}', '\u{303c}'),
- ('\u{3041}', '\u{3096}'), ('\u{309d}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}',
- '\u{30ff}'), ('\u{3105}', '\u{312f}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31bf}'),
- ('\u{31f0}', '\u{31ff}'), ('\u{3400}', '\u{4dbf}'), ('\u{4e00}', '\u{a48c}'), ('\u{a4d0}',
- '\u{a4fd}'), ('\u{a500}', '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'),
- ('\u{a640}', '\u{a66e}'), ('\u{a674}', '\u{a67b}'), ('\u{a67f}', '\u{a6ef}'), ('\u{a717}',
- '\u{a71f}'), ('\u{a722}', '\u{a788}'), ('\u{a78b}', '\u{a7ca}'), ('\u{a7d0}', '\u{a7d1}'),
- ('\u{a7d3}', '\u{a7d3}'), ('\u{a7d5}', '\u{a7d9}'), ('\u{a7f2}', '\u{a805}'), ('\u{a807}',
- '\u{a827}'), ('\u{a840}', '\u{a873}'), ('\u{a880}', '\u{a8c3}'), ('\u{a8c5}', '\u{a8c5}'),
- ('\u{a8f2}', '\u{a8f7}'), ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8ff}'), ('\u{a90a}',
- '\u{a92a}'), ('\u{a930}', '\u{a952}'), ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9b2}'),
- ('\u{a9b4}', '\u{a9bf}'), ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9ef}'), ('\u{a9fa}',
- '\u{a9fe}'), ('\u{aa00}', '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), ('\u{aa60}', '\u{aa76}'),
- ('\u{aa7a}', '\u{aabe}'), ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}',
- '\u{aadd}'), ('\u{aae0}', '\u{aaef}'), ('\u{aaf2}', '\u{aaf5}'), ('\u{ab01}', '\u{ab06}'),
- ('\u{ab09}', '\u{ab0e}'), ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}',
- '\u{ab2e}'), ('\u{ab30}', '\u{ab5a}'), ('\u{ab5c}', '\u{ab69}'), ('\u{ab70}', '\u{abea}'),
- ('\u{ac00}', '\u{d7a3}'), ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}',
- '\u{fa6d}'), ('\u{fa70}', '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'),
- ('\u{fb1d}', '\u{fb28}'), ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}',
- '\u{fb3e}'), ('\u{fb40}', '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'),
- ('\u{fbd3}', '\u{fd3d}'), ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}',
- '\u{fdfb}'), ('\u{fe70}', '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'),
- ('\u{ff41}', '\u{ff5a}'), ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}',
- '\u{ffcf}'), ('\u{ffd2}', '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'),
- ('\u{1000d}', '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'),
- ('\u{1003f}', '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'),
- ('\u{10140}', '\u{10174}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'),
- ('\u{10300}', '\u{1031f}'), ('\u{1032d}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'),
- ('\u{10380}', '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'),
- ('\u{103d1}', '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{104b0}', '\u{104d3}'),
- ('\u{104d8}', '\u{104fb}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', '\u{10563}'),
- ('\u{10570}', '\u{1057a}'), ('\u{1057c}', '\u{1058a}'), ('\u{1058c}', '\u{10592}'),
- ('\u{10594}', '\u{10595}'), ('\u{10597}', '\u{105a1}'), ('\u{105a3}', '\u{105b1}'),
- ('\u{105b3}', '\u{105b9}'), ('\u{105bb}', '\u{105bc}'), ('\u{10600}', '\u{10736}'),
- ('\u{10740}', '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10780}', '\u{10785}'),
- ('\u{10787}', '\u{107b0}'), ('\u{107b2}', '\u{107ba}'), ('\u{10800}', '\u{10805}'),
- ('\u{10808}', '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'),
- ('\u{1083c}', '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'),
- ('\u{10880}', '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'),
- ('\u{10900}', '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'),
- ('\u{109be}', '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'),
- ('\u{10a0c}', '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a35}'),
- ('\u{10a60}', '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'),
- ('\u{10ac9}', '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'),
- ('\u{10b60}', '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'),
- ('\u{10c80}', '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{10d00}', '\u{10d27}'),
- ('\u{10e80}', '\u{10ea9}'), ('\u{10eab}', '\u{10eac}'), ('\u{10eb0}', '\u{10eb1}'),
- ('\u{10f00}', '\u{10f1c}'), ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'),
- ('\u{10f70}', '\u{10f81}'), ('\u{10fb0}', '\u{10fc4}'), ('\u{10fe0}', '\u{10ff6}'),
- ('\u{11000}', '\u{11045}'), ('\u{11071}', '\u{11075}'), ('\u{11082}', '\u{110b8}'),
- ('\u{110c2}', '\u{110c2}'), ('\u{110d0}', '\u{110e8}'), ('\u{11100}', '\u{11132}'),
- ('\u{11144}', '\u{11147}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'),
- ('\u{11180}', '\u{111bf}'), ('\u{111c1}', '\u{111c4}'), ('\u{111ce}', '\u{111cf}'),
- ('\u{111da}', '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'),
- ('\u{11213}', '\u{11234}'), ('\u{11237}', '\u{11237}'), ('\u{1123e}', '\u{1123e}'),
- ('\u{11280}', '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'),
- ('\u{1128f}', '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112e8}'),
- ('\u{11300}', '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'),
- ('\u{11313}', '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'),
- ('\u{11335}', '\u{11339}'), ('\u{1133d}', '\u{11344}'), ('\u{11347}', '\u{11348}'),
- ('\u{1134b}', '\u{1134c}'), ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'),
- ('\u{1135d}', '\u{11363}'), ('\u{11400}', '\u{11441}'), ('\u{11443}', '\u{11445}'),
- ('\u{11447}', '\u{1144a}'), ('\u{1145f}', '\u{11461}'), ('\u{11480}', '\u{114c1}'),
- ('\u{114c4}', '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115b5}'),
- ('\u{115b8}', '\u{115be}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{1163e}'),
- ('\u{11640}', '\u{11640}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116b5}'),
- ('\u{116b8}', '\u{116b8}'), ('\u{11700}', '\u{1171a}'), ('\u{1171d}', '\u{1172a}'),
- ('\u{11740}', '\u{11746}'), ('\u{11800}', '\u{11838}'), ('\u{118a0}', '\u{118df}'),
- ('\u{118ff}', '\u{11906}'), ('\u{11909}', '\u{11909}'), ('\u{1190c}', '\u{11913}'),
- ('\u{11915}', '\u{11916}'), ('\u{11918}', '\u{11935}'), ('\u{11937}', '\u{11938}'),
- ('\u{1193b}', '\u{1193c}'), ('\u{1193f}', '\u{11942}'), ('\u{119a0}', '\u{119a7}'),
- ('\u{119aa}', '\u{119d7}'), ('\u{119da}', '\u{119df}'), ('\u{119e1}', '\u{119e1}'),
- ('\u{119e3}', '\u{119e4}'), ('\u{11a00}', '\u{11a32}'), ('\u{11a35}', '\u{11a3e}'),
- ('\u{11a50}', '\u{11a97}'), ('\u{11a9d}', '\u{11a9d}'), ('\u{11ab0}', '\u{11af8}'),
- ('\u{11c00}', '\u{11c08}'), ('\u{11c0a}', '\u{11c36}'), ('\u{11c38}', '\u{11c3e}'),
- ('\u{11c40}', '\u{11c40}'), ('\u{11c72}', '\u{11c8f}'), ('\u{11c92}', '\u{11ca7}'),
- ('\u{11ca9}', '\u{11cb6}'), ('\u{11d00}', '\u{11d06}'), ('\u{11d08}', '\u{11d09}'),
- ('\u{11d0b}', '\u{11d36}'), ('\u{11d3a}', '\u{11d3a}'), ('\u{11d3c}', '\u{11d3d}'),
- ('\u{11d3f}', '\u{11d41}'), ('\u{11d43}', '\u{11d43}'), ('\u{11d46}', '\u{11d47}'),
- ('\u{11d60}', '\u{11d65}'), ('\u{11d67}', '\u{11d68}'), ('\u{11d6a}', '\u{11d8e}'),
- ('\u{11d90}', '\u{11d91}'), ('\u{11d93}', '\u{11d96}'), ('\u{11d98}', '\u{11d98}'),
- ('\u{11ee0}', '\u{11ef6}'), ('\u{11fb0}', '\u{11fb0}'), ('\u{12000}', '\u{12399}'),
- ('\u{12400}', '\u{1246e}'), ('\u{12480}', '\u{12543}'), ('\u{12f90}', '\u{12ff0}'),
- ('\u{13000}', '\u{1342e}'), ('\u{14400}', '\u{14646}'), ('\u{16800}', '\u{16a38}'),
- ('\u{16a40}', '\u{16a5e}'), ('\u{16a70}', '\u{16abe}'), ('\u{16ad0}', '\u{16aed}'),
- ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}', '\u{16b77}'),
- ('\u{16b7d}', '\u{16b8f}'), ('\u{16e40}', '\u{16e7f}'), ('\u{16f00}', '\u{16f4a}'),
- ('\u{16f4f}', '\u{16f87}'), ('\u{16f8f}', '\u{16f9f}'), ('\u{16fe0}', '\u{16fe1}'),
- ('\u{16fe3}', '\u{16fe3}'), ('\u{16ff0}', '\u{16ff1}'), ('\u{17000}', '\u{187f7}'),
- ('\u{18800}', '\u{18cd5}'), ('\u{18d00}', '\u{18d08}'), ('\u{1aff0}', '\u{1aff3}'),
- ('\u{1aff5}', '\u{1affb}'), ('\u{1affd}', '\u{1affe}'), ('\u{1b000}', '\u{1b122}'),
- ('\u{1b150}', '\u{1b152}'), ('\u{1b164}', '\u{1b167}'), ('\u{1b170}', '\u{1b2fb}'),
- ('\u{1bc00}', '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'),
- ('\u{1bc90}', '\u{1bc99}'), ('\u{1bc9e}', '\u{1bc9e}'), ('\u{1d400}', '\u{1d454}'),
- ('\u{1d456}', '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'),
- ('\u{1d4a5}', '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'),
- ('\u{1d4bb}', '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'),
- ('\u{1d507}', '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'),
- ('\u{1d51e}', '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'),
- ('\u{1d546}', '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'),
- ('\u{1d6a8}', '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'),
- ('\u{1d6fc}', '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'),
- ('\u{1d750}', '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'),
- ('\u{1d7aa}', '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1df00}', '\u{1df1e}'),
- ('\u{1e000}', '\u{1e006}'), ('\u{1e008}', '\u{1e018}'), ('\u{1e01b}', '\u{1e021}'),
- ('\u{1e023}', '\u{1e024}'), ('\u{1e026}', '\u{1e02a}'), ('\u{1e100}', '\u{1e12c}'),
- ('\u{1e137}', '\u{1e13d}'), ('\u{1e14e}', '\u{1e14e}'), ('\u{1e290}', '\u{1e2ad}'),
- ('\u{1e2c0}', '\u{1e2eb}'), ('\u{1e7e0}', '\u{1e7e6}'), ('\u{1e7e8}', '\u{1e7eb}'),
- ('\u{1e7ed}', '\u{1e7ee}'), ('\u{1e7f0}', '\u{1e7fe}'), ('\u{1e800}', '\u{1e8c4}'),
- ('\u{1e900}', '\u{1e943}'), ('\u{1e947}', '\u{1e947}'), ('\u{1e94b}', '\u{1e94b}'),
- ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}', '\u{1ee22}'),
- ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}', '\u{1ee32}'),
- ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}', '\u{1ee3b}'),
- ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}', '\u{1ee49}'),
- ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}', '\u{1ee52}'),
- ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}', '\u{1ee59}'),
- ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}', '\u{1ee5f}'),
- ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}', '\u{1ee6a}'),
- ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}', '\u{1ee7c}'),
- ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}', '\u{1ee9b}'),
- ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}', '\u{1eebb}'),
- ('\u{1f130}', '\u{1f149}'), ('\u{1f150}', '\u{1f169}'), ('\u{1f170}', '\u{1f189}'),
- ('\u{20000}', '\u{2a6df}'), ('\u{2a700}', '\u{2b738}'), ('\u{2b740}', '\u{2b81d}'),
- ('\u{2b820}', '\u{2cea1}'), ('\u{2ceb0}', '\u{2ebe0}'), ('\u{2f800}', '\u{2fa1d}'),
- ('\u{30000}', '\u{3134a}')
+ ('\u{c00}', '\u{c0c}'), ('\u{c0e}', '\u{c10}'), ('\u{c12}', '\u{c28}'), ('\u{c2a}',
+ '\u{c39}'), ('\u{c3d}', '\u{c44}'), ('\u{c46}', '\u{c48}'), ('\u{c4a}', '\u{c4c}'),
+ ('\u{c55}', '\u{c56}'), ('\u{c58}', '\u{c5a}'), ('\u{c5d}', '\u{c5d}'), ('\u{c60}',
+ '\u{c63}'), ('\u{c80}', '\u{c83}'), ('\u{c85}', '\u{c8c}'), ('\u{c8e}', '\u{c90}'),
+ ('\u{c92}', '\u{ca8}'), ('\u{caa}', '\u{cb3}'), ('\u{cb5}', '\u{cb9}'), ('\u{cbd}',
+ '\u{cc4}'), ('\u{cc6}', '\u{cc8}'), ('\u{cca}', '\u{ccc}'), ('\u{cd5}', '\u{cd6}'),
+ ('\u{cdd}', '\u{cde}'), ('\u{ce0}', '\u{ce3}'), ('\u{cf1}', '\u{cf3}'), ('\u{d00}',
+ '\u{d0c}'), ('\u{d0e}', '\u{d10}'), ('\u{d12}', '\u{d3a}'), ('\u{d3d}', '\u{d44}'),
+ ('\u{d46}', '\u{d48}'), ('\u{d4a}', '\u{d4c}'), ('\u{d4e}', '\u{d4e}'), ('\u{d54}',
+ '\u{d57}'), ('\u{d5f}', '\u{d63}'), ('\u{d7a}', '\u{d7f}'), ('\u{d81}', '\u{d83}'),
+ ('\u{d85}', '\u{d96}'), ('\u{d9a}', '\u{db1}'), ('\u{db3}', '\u{dbb}'), ('\u{dbd}',
+ '\u{dbd}'), ('\u{dc0}', '\u{dc6}'), ('\u{dcf}', '\u{dd4}'), ('\u{dd6}', '\u{dd6}'),
+ ('\u{dd8}', '\u{ddf}'), ('\u{df2}', '\u{df3}'), ('\u{e01}', '\u{e3a}'), ('\u{e40}',
+ '\u{e46}'), ('\u{e4d}', '\u{e4d}'), ('\u{e81}', '\u{e82}'), ('\u{e84}', '\u{e84}'),
+ ('\u{e86}', '\u{e8a}'), ('\u{e8c}', '\u{ea3}'), ('\u{ea5}', '\u{ea5}'), ('\u{ea7}',
+ '\u{eb9}'), ('\u{ebb}', '\u{ebd}'), ('\u{ec0}', '\u{ec4}'), ('\u{ec6}', '\u{ec6}'),
+ ('\u{ecd}', '\u{ecd}'), ('\u{edc}', '\u{edf}'), ('\u{f00}', '\u{f00}'), ('\u{f40}',
+ '\u{f47}'), ('\u{f49}', '\u{f6c}'), ('\u{f71}', '\u{f83}'), ('\u{f88}', '\u{f97}'),
+ ('\u{f99}', '\u{fbc}'), ('\u{1000}', '\u{1036}'), ('\u{1038}', '\u{1038}'), ('\u{103b}',
+ '\u{103f}'), ('\u{1050}', '\u{108f}'), ('\u{109a}', '\u{109d}'), ('\u{10a0}', '\u{10c5}'),
+ ('\u{10c7}', '\u{10c7}'), ('\u{10cd}', '\u{10cd}'), ('\u{10d0}', '\u{10fa}'), ('\u{10fc}',
+ '\u{1248}'), ('\u{124a}', '\u{124d}'), ('\u{1250}', '\u{1256}'), ('\u{1258}', '\u{1258}'),
+ ('\u{125a}', '\u{125d}'), ('\u{1260}', '\u{1288}'), ('\u{128a}', '\u{128d}'), ('\u{1290}',
+ '\u{12b0}'), ('\u{12b2}', '\u{12b5}'), ('\u{12b8}', '\u{12be}'), ('\u{12c0}', '\u{12c0}'),
+ ('\u{12c2}', '\u{12c5}'), ('\u{12c8}', '\u{12d6}'), ('\u{12d8}', '\u{1310}'), ('\u{1312}',
+ '\u{1315}'), ('\u{1318}', '\u{135a}'), ('\u{1380}', '\u{138f}'), ('\u{13a0}', '\u{13f5}'),
+ ('\u{13f8}', '\u{13fd}'), ('\u{1401}', '\u{166c}'), ('\u{166f}', '\u{167f}'), ('\u{1681}',
+ '\u{169a}'), ('\u{16a0}', '\u{16ea}'), ('\u{16ee}', '\u{16f8}'), ('\u{1700}', '\u{1713}'),
+ ('\u{171f}', '\u{1733}'), ('\u{1740}', '\u{1753}'), ('\u{1760}', '\u{176c}'), ('\u{176e}',
+ '\u{1770}'), ('\u{1772}', '\u{1773}'), ('\u{1780}', '\u{17b3}'), ('\u{17b6}', '\u{17c8}'),
+ ('\u{17d7}', '\u{17d7}'), ('\u{17dc}', '\u{17dc}'), ('\u{1820}', '\u{1878}'), ('\u{1880}',
+ '\u{18aa}'), ('\u{18b0}', '\u{18f5}'), ('\u{1900}', '\u{191e}'), ('\u{1920}', '\u{192b}'),
+ ('\u{1930}', '\u{1938}'), ('\u{1950}', '\u{196d}'), ('\u{1970}', '\u{1974}'), ('\u{1980}',
+ '\u{19ab}'), ('\u{19b0}', '\u{19c9}'), ('\u{1a00}', '\u{1a1b}'), ('\u{1a20}', '\u{1a5e}'),
+ ('\u{1a61}', '\u{1a74}'), ('\u{1aa7}', '\u{1aa7}'), ('\u{1abf}', '\u{1ac0}'), ('\u{1acc}',
+ '\u{1ace}'), ('\u{1b00}', '\u{1b33}'), ('\u{1b35}', '\u{1b43}'), ('\u{1b45}', '\u{1b4c}'),
+ ('\u{1b80}', '\u{1ba9}'), ('\u{1bac}', '\u{1baf}'), ('\u{1bba}', '\u{1be5}'), ('\u{1be7}',
+ '\u{1bf1}'), ('\u{1c00}', '\u{1c36}'), ('\u{1c4d}', '\u{1c4f}'), ('\u{1c5a}', '\u{1c7d}'),
+ ('\u{1c80}', '\u{1c88}'), ('\u{1c90}', '\u{1cba}'), ('\u{1cbd}', '\u{1cbf}'), ('\u{1ce9}',
+ '\u{1cec}'), ('\u{1cee}', '\u{1cf3}'), ('\u{1cf5}', '\u{1cf6}'), ('\u{1cfa}', '\u{1cfa}'),
+ ('\u{1d00}', '\u{1dbf}'), ('\u{1de7}', '\u{1df4}'), ('\u{1e00}', '\u{1f15}'), ('\u{1f18}',
+ '\u{1f1d}'), ('\u{1f20}', '\u{1f45}'), ('\u{1f48}', '\u{1f4d}'), ('\u{1f50}', '\u{1f57}'),
+ ('\u{1f59}', '\u{1f59}'), ('\u{1f5b}', '\u{1f5b}'), ('\u{1f5d}', '\u{1f5d}'), ('\u{1f5f}',
+ '\u{1f7d}'), ('\u{1f80}', '\u{1fb4}'), ('\u{1fb6}', '\u{1fbc}'), ('\u{1fbe}', '\u{1fbe}'),
+ ('\u{1fc2}', '\u{1fc4}'), ('\u{1fc6}', '\u{1fcc}'), ('\u{1fd0}', '\u{1fd3}'), ('\u{1fd6}',
+ '\u{1fdb}'), ('\u{1fe0}', '\u{1fec}'), ('\u{1ff2}', '\u{1ff4}'), ('\u{1ff6}', '\u{1ffc}'),
+ ('\u{2071}', '\u{2071}'), ('\u{207f}', '\u{207f}'), ('\u{2090}', '\u{209c}'), ('\u{2102}',
+ '\u{2102}'), ('\u{2107}', '\u{2107}'), ('\u{210a}', '\u{2113}'), ('\u{2115}', '\u{2115}'),
+ ('\u{2119}', '\u{211d}'), ('\u{2124}', '\u{2124}'), ('\u{2126}', '\u{2126}'), ('\u{2128}',
+ '\u{2128}'), ('\u{212a}', '\u{212d}'), ('\u{212f}', '\u{2139}'), ('\u{213c}', '\u{213f}'),
+ ('\u{2145}', '\u{2149}'), ('\u{214e}', '\u{214e}'), ('\u{2160}', '\u{2188}'), ('\u{24b6}',
+ '\u{24e9}'), ('\u{2c00}', '\u{2ce4}'), ('\u{2ceb}', '\u{2cee}'), ('\u{2cf2}', '\u{2cf3}'),
+ ('\u{2d00}', '\u{2d25}'), ('\u{2d27}', '\u{2d27}'), ('\u{2d2d}', '\u{2d2d}'), ('\u{2d30}',
+ '\u{2d67}'), ('\u{2d6f}', '\u{2d6f}'), ('\u{2d80}', '\u{2d96}'), ('\u{2da0}', '\u{2da6}'),
+ ('\u{2da8}', '\u{2dae}'), ('\u{2db0}', '\u{2db6}'), ('\u{2db8}', '\u{2dbe}'), ('\u{2dc0}',
+ '\u{2dc6}'), ('\u{2dc8}', '\u{2dce}'), ('\u{2dd0}', '\u{2dd6}'), ('\u{2dd8}', '\u{2dde}'),
+ ('\u{2de0}', '\u{2dff}'), ('\u{2e2f}', '\u{2e2f}'), ('\u{3005}', '\u{3007}'), ('\u{3021}',
+ '\u{3029}'), ('\u{3031}', '\u{3035}'), ('\u{3038}', '\u{303c}'), ('\u{3041}', '\u{3096}'),
+ ('\u{309d}', '\u{309f}'), ('\u{30a1}', '\u{30fa}'), ('\u{30fc}', '\u{30ff}'), ('\u{3105}',
+ '\u{312f}'), ('\u{3131}', '\u{318e}'), ('\u{31a0}', '\u{31bf}'), ('\u{31f0}', '\u{31ff}'),
+ ('\u{3400}', '\u{4dbf}'), ('\u{4e00}', '\u{a48c}'), ('\u{a4d0}', '\u{a4fd}'), ('\u{a500}',
+ '\u{a60c}'), ('\u{a610}', '\u{a61f}'), ('\u{a62a}', '\u{a62b}'), ('\u{a640}', '\u{a66e}'),
+ ('\u{a674}', '\u{a67b}'), ('\u{a67f}', '\u{a6ef}'), ('\u{a717}', '\u{a71f}'), ('\u{a722}',
+ '\u{a788}'), ('\u{a78b}', '\u{a7ca}'), ('\u{a7d0}', '\u{a7d1}'), ('\u{a7d3}', '\u{a7d3}'),
+ ('\u{a7d5}', '\u{a7d9}'), ('\u{a7f2}', '\u{a805}'), ('\u{a807}', '\u{a827}'), ('\u{a840}',
+ '\u{a873}'), ('\u{a880}', '\u{a8c3}'), ('\u{a8c5}', '\u{a8c5}'), ('\u{a8f2}', '\u{a8f7}'),
+ ('\u{a8fb}', '\u{a8fb}'), ('\u{a8fd}', '\u{a8ff}'), ('\u{a90a}', '\u{a92a}'), ('\u{a930}',
+ '\u{a952}'), ('\u{a960}', '\u{a97c}'), ('\u{a980}', '\u{a9b2}'), ('\u{a9b4}', '\u{a9bf}'),
+ ('\u{a9cf}', '\u{a9cf}'), ('\u{a9e0}', '\u{a9ef}'), ('\u{a9fa}', '\u{a9fe}'), ('\u{aa00}',
+ '\u{aa36}'), ('\u{aa40}', '\u{aa4d}'), ('\u{aa60}', '\u{aa76}'), ('\u{aa7a}', '\u{aabe}'),
+ ('\u{aac0}', '\u{aac0}'), ('\u{aac2}', '\u{aac2}'), ('\u{aadb}', '\u{aadd}'), ('\u{aae0}',
+ '\u{aaef}'), ('\u{aaf2}', '\u{aaf5}'), ('\u{ab01}', '\u{ab06}'), ('\u{ab09}', '\u{ab0e}'),
+ ('\u{ab11}', '\u{ab16}'), ('\u{ab20}', '\u{ab26}'), ('\u{ab28}', '\u{ab2e}'), ('\u{ab30}',
+ '\u{ab5a}'), ('\u{ab5c}', '\u{ab69}'), ('\u{ab70}', '\u{abea}'), ('\u{ac00}', '\u{d7a3}'),
+ ('\u{d7b0}', '\u{d7c6}'), ('\u{d7cb}', '\u{d7fb}'), ('\u{f900}', '\u{fa6d}'), ('\u{fa70}',
+ '\u{fad9}'), ('\u{fb00}', '\u{fb06}'), ('\u{fb13}', '\u{fb17}'), ('\u{fb1d}', '\u{fb28}'),
+ ('\u{fb2a}', '\u{fb36}'), ('\u{fb38}', '\u{fb3c}'), ('\u{fb3e}', '\u{fb3e}'), ('\u{fb40}',
+ '\u{fb41}'), ('\u{fb43}', '\u{fb44}'), ('\u{fb46}', '\u{fbb1}'), ('\u{fbd3}', '\u{fd3d}'),
+ ('\u{fd50}', '\u{fd8f}'), ('\u{fd92}', '\u{fdc7}'), ('\u{fdf0}', '\u{fdfb}'), ('\u{fe70}',
+ '\u{fe74}'), ('\u{fe76}', '\u{fefc}'), ('\u{ff21}', '\u{ff3a}'), ('\u{ff41}', '\u{ff5a}'),
+ ('\u{ff66}', '\u{ffbe}'), ('\u{ffc2}', '\u{ffc7}'), ('\u{ffca}', '\u{ffcf}'), ('\u{ffd2}',
+ '\u{ffd7}'), ('\u{ffda}', '\u{ffdc}'), ('\u{10000}', '\u{1000b}'), ('\u{1000d}',
+ '\u{10026}'), ('\u{10028}', '\u{1003a}'), ('\u{1003c}', '\u{1003d}'), ('\u{1003f}',
+ '\u{1004d}'), ('\u{10050}', '\u{1005d}'), ('\u{10080}', '\u{100fa}'), ('\u{10140}',
+ '\u{10174}'), ('\u{10280}', '\u{1029c}'), ('\u{102a0}', '\u{102d0}'), ('\u{10300}',
+ '\u{1031f}'), ('\u{1032d}', '\u{1034a}'), ('\u{10350}', '\u{1037a}'), ('\u{10380}',
+ '\u{1039d}'), ('\u{103a0}', '\u{103c3}'), ('\u{103c8}', '\u{103cf}'), ('\u{103d1}',
+ '\u{103d5}'), ('\u{10400}', '\u{1049d}'), ('\u{104b0}', '\u{104d3}'), ('\u{104d8}',
+ '\u{104fb}'), ('\u{10500}', '\u{10527}'), ('\u{10530}', '\u{10563}'), ('\u{10570}',
+ '\u{1057a}'), ('\u{1057c}', '\u{1058a}'), ('\u{1058c}', '\u{10592}'), ('\u{10594}',
+ '\u{10595}'), ('\u{10597}', '\u{105a1}'), ('\u{105a3}', '\u{105b1}'), ('\u{105b3}',
+ '\u{105b9}'), ('\u{105bb}', '\u{105bc}'), ('\u{10600}', '\u{10736}'), ('\u{10740}',
+ '\u{10755}'), ('\u{10760}', '\u{10767}'), ('\u{10780}', '\u{10785}'), ('\u{10787}',
+ '\u{107b0}'), ('\u{107b2}', '\u{107ba}'), ('\u{10800}', '\u{10805}'), ('\u{10808}',
+ '\u{10808}'), ('\u{1080a}', '\u{10835}'), ('\u{10837}', '\u{10838}'), ('\u{1083c}',
+ '\u{1083c}'), ('\u{1083f}', '\u{10855}'), ('\u{10860}', '\u{10876}'), ('\u{10880}',
+ '\u{1089e}'), ('\u{108e0}', '\u{108f2}'), ('\u{108f4}', '\u{108f5}'), ('\u{10900}',
+ '\u{10915}'), ('\u{10920}', '\u{10939}'), ('\u{10980}', '\u{109b7}'), ('\u{109be}',
+ '\u{109bf}'), ('\u{10a00}', '\u{10a03}'), ('\u{10a05}', '\u{10a06}'), ('\u{10a0c}',
+ '\u{10a13}'), ('\u{10a15}', '\u{10a17}'), ('\u{10a19}', '\u{10a35}'), ('\u{10a60}',
+ '\u{10a7c}'), ('\u{10a80}', '\u{10a9c}'), ('\u{10ac0}', '\u{10ac7}'), ('\u{10ac9}',
+ '\u{10ae4}'), ('\u{10b00}', '\u{10b35}'), ('\u{10b40}', '\u{10b55}'), ('\u{10b60}',
+ '\u{10b72}'), ('\u{10b80}', '\u{10b91}'), ('\u{10c00}', '\u{10c48}'), ('\u{10c80}',
+ '\u{10cb2}'), ('\u{10cc0}', '\u{10cf2}'), ('\u{10d00}', '\u{10d27}'), ('\u{10e80}',
+ '\u{10ea9}'), ('\u{10eab}', '\u{10eac}'), ('\u{10eb0}', '\u{10eb1}'), ('\u{10f00}',
+ '\u{10f1c}'), ('\u{10f27}', '\u{10f27}'), ('\u{10f30}', '\u{10f45}'), ('\u{10f70}',
+ '\u{10f81}'), ('\u{10fb0}', '\u{10fc4}'), ('\u{10fe0}', '\u{10ff6}'), ('\u{11000}',
+ '\u{11045}'), ('\u{11071}', '\u{11075}'), ('\u{11080}', '\u{110b8}'), ('\u{110c2}',
+ '\u{110c2}'), ('\u{110d0}', '\u{110e8}'), ('\u{11100}', '\u{11132}'), ('\u{11144}',
+ '\u{11147}'), ('\u{11150}', '\u{11172}'), ('\u{11176}', '\u{11176}'), ('\u{11180}',
+ '\u{111bf}'), ('\u{111c1}', '\u{111c4}'), ('\u{111ce}', '\u{111cf}'), ('\u{111da}',
+ '\u{111da}'), ('\u{111dc}', '\u{111dc}'), ('\u{11200}', '\u{11211}'), ('\u{11213}',
+ '\u{11234}'), ('\u{11237}', '\u{11237}'), ('\u{1123e}', '\u{11241}'), ('\u{11280}',
+ '\u{11286}'), ('\u{11288}', '\u{11288}'), ('\u{1128a}', '\u{1128d}'), ('\u{1128f}',
+ '\u{1129d}'), ('\u{1129f}', '\u{112a8}'), ('\u{112b0}', '\u{112e8}'), ('\u{11300}',
+ '\u{11303}'), ('\u{11305}', '\u{1130c}'), ('\u{1130f}', '\u{11310}'), ('\u{11313}',
+ '\u{11328}'), ('\u{1132a}', '\u{11330}'), ('\u{11332}', '\u{11333}'), ('\u{11335}',
+ '\u{11339}'), ('\u{1133d}', '\u{11344}'), ('\u{11347}', '\u{11348}'), ('\u{1134b}',
+ '\u{1134c}'), ('\u{11350}', '\u{11350}'), ('\u{11357}', '\u{11357}'), ('\u{1135d}',
+ '\u{11363}'), ('\u{11400}', '\u{11441}'), ('\u{11443}', '\u{11445}'), ('\u{11447}',
+ '\u{1144a}'), ('\u{1145f}', '\u{11461}'), ('\u{11480}', '\u{114c1}'), ('\u{114c4}',
+ '\u{114c5}'), ('\u{114c7}', '\u{114c7}'), ('\u{11580}', '\u{115b5}'), ('\u{115b8}',
+ '\u{115be}'), ('\u{115d8}', '\u{115dd}'), ('\u{11600}', '\u{1163e}'), ('\u{11640}',
+ '\u{11640}'), ('\u{11644}', '\u{11644}'), ('\u{11680}', '\u{116b5}'), ('\u{116b8}',
+ '\u{116b8}'), ('\u{11700}', '\u{1171a}'), ('\u{1171d}', '\u{1172a}'), ('\u{11740}',
+ '\u{11746}'), ('\u{11800}', '\u{11838}'), ('\u{118a0}', '\u{118df}'), ('\u{118ff}',
+ '\u{11906}'), ('\u{11909}', '\u{11909}'), ('\u{1190c}', '\u{11913}'), ('\u{11915}',
+ '\u{11916}'), ('\u{11918}', '\u{11935}'), ('\u{11937}', '\u{11938}'), ('\u{1193b}',
+ '\u{1193c}'), ('\u{1193f}', '\u{11942}'), ('\u{119a0}', '\u{119a7}'), ('\u{119aa}',
+ '\u{119d7}'), ('\u{119da}', '\u{119df}'), ('\u{119e1}', '\u{119e1}'), ('\u{119e3}',
+ '\u{119e4}'), ('\u{11a00}', '\u{11a32}'), ('\u{11a35}', '\u{11a3e}'), ('\u{11a50}',
+ '\u{11a97}'), ('\u{11a9d}', '\u{11a9d}'), ('\u{11ab0}', '\u{11af8}'), ('\u{11c00}',
+ '\u{11c08}'), ('\u{11c0a}', '\u{11c36}'), ('\u{11c38}', '\u{11c3e}'), ('\u{11c40}',
+ '\u{11c40}'), ('\u{11c72}', '\u{11c8f}'), ('\u{11c92}', '\u{11ca7}'), ('\u{11ca9}',
+ '\u{11cb6}'), ('\u{11d00}', '\u{11d06}'), ('\u{11d08}', '\u{11d09}'), ('\u{11d0b}',
+ '\u{11d36}'), ('\u{11d3a}', '\u{11d3a}'), ('\u{11d3c}', '\u{11d3d}'), ('\u{11d3f}',
+ '\u{11d41}'), ('\u{11d43}', '\u{11d43}'), ('\u{11d46}', '\u{11d47}'), ('\u{11d60}',
+ '\u{11d65}'), ('\u{11d67}', '\u{11d68}'), ('\u{11d6a}', '\u{11d8e}'), ('\u{11d90}',
+ '\u{11d91}'), ('\u{11d93}', '\u{11d96}'), ('\u{11d98}', '\u{11d98}'), ('\u{11ee0}',
+ '\u{11ef6}'), ('\u{11f00}', '\u{11f10}'), ('\u{11f12}', '\u{11f3a}'), ('\u{11f3e}',
+ '\u{11f40}'), ('\u{11fb0}', '\u{11fb0}'), ('\u{12000}', '\u{12399}'), ('\u{12400}',
+ '\u{1246e}'), ('\u{12480}', '\u{12543}'), ('\u{12f90}', '\u{12ff0}'), ('\u{13000}',
+ '\u{1342f}'), ('\u{13441}', '\u{13446}'), ('\u{14400}', '\u{14646}'), ('\u{16800}',
+ '\u{16a38}'), ('\u{16a40}', '\u{16a5e}'), ('\u{16a70}', '\u{16abe}'), ('\u{16ad0}',
+ '\u{16aed}'), ('\u{16b00}', '\u{16b2f}'), ('\u{16b40}', '\u{16b43}'), ('\u{16b63}',
+ '\u{16b77}'), ('\u{16b7d}', '\u{16b8f}'), ('\u{16e40}', '\u{16e7f}'), ('\u{16f00}',
+ '\u{16f4a}'), ('\u{16f4f}', '\u{16f87}'), ('\u{16f8f}', '\u{16f9f}'), ('\u{16fe0}',
+ '\u{16fe1}'), ('\u{16fe3}', '\u{16fe3}'), ('\u{16ff0}', '\u{16ff1}'), ('\u{17000}',
+ '\u{187f7}'), ('\u{18800}', '\u{18cd5}'), ('\u{18d00}', '\u{18d08}'), ('\u{1aff0}',
+ '\u{1aff3}'), ('\u{1aff5}', '\u{1affb}'), ('\u{1affd}', '\u{1affe}'), ('\u{1b000}',
+ '\u{1b122}'), ('\u{1b132}', '\u{1b132}'), ('\u{1b150}', '\u{1b152}'), ('\u{1b155}',
+ '\u{1b155}'), ('\u{1b164}', '\u{1b167}'), ('\u{1b170}', '\u{1b2fb}'), ('\u{1bc00}',
+ '\u{1bc6a}'), ('\u{1bc70}', '\u{1bc7c}'), ('\u{1bc80}', '\u{1bc88}'), ('\u{1bc90}',
+ '\u{1bc99}'), ('\u{1bc9e}', '\u{1bc9e}'), ('\u{1d400}', '\u{1d454}'), ('\u{1d456}',
+ '\u{1d49c}'), ('\u{1d49e}', '\u{1d49f}'), ('\u{1d4a2}', '\u{1d4a2}'), ('\u{1d4a5}',
+ '\u{1d4a6}'), ('\u{1d4a9}', '\u{1d4ac}'), ('\u{1d4ae}', '\u{1d4b9}'), ('\u{1d4bb}',
+ '\u{1d4bb}'), ('\u{1d4bd}', '\u{1d4c3}'), ('\u{1d4c5}', '\u{1d505}'), ('\u{1d507}',
+ '\u{1d50a}'), ('\u{1d50d}', '\u{1d514}'), ('\u{1d516}', '\u{1d51c}'), ('\u{1d51e}',
+ '\u{1d539}'), ('\u{1d53b}', '\u{1d53e}'), ('\u{1d540}', '\u{1d544}'), ('\u{1d546}',
+ '\u{1d546}'), ('\u{1d54a}', '\u{1d550}'), ('\u{1d552}', '\u{1d6a5}'), ('\u{1d6a8}',
+ '\u{1d6c0}'), ('\u{1d6c2}', '\u{1d6da}'), ('\u{1d6dc}', '\u{1d6fa}'), ('\u{1d6fc}',
+ '\u{1d714}'), ('\u{1d716}', '\u{1d734}'), ('\u{1d736}', '\u{1d74e}'), ('\u{1d750}',
+ '\u{1d76e}'), ('\u{1d770}', '\u{1d788}'), ('\u{1d78a}', '\u{1d7a8}'), ('\u{1d7aa}',
+ '\u{1d7c2}'), ('\u{1d7c4}', '\u{1d7cb}'), ('\u{1df00}', '\u{1df1e}'), ('\u{1df25}',
+ '\u{1df2a}'), ('\u{1e000}', '\u{1e006}'), ('\u{1e008}', '\u{1e018}'), ('\u{1e01b}',
+ '\u{1e021}'), ('\u{1e023}', '\u{1e024}'), ('\u{1e026}', '\u{1e02a}'), ('\u{1e030}',
+ '\u{1e06d}'), ('\u{1e08f}', '\u{1e08f}'), ('\u{1e100}', '\u{1e12c}'), ('\u{1e137}',
+ '\u{1e13d}'), ('\u{1e14e}', '\u{1e14e}'), ('\u{1e290}', '\u{1e2ad}'), ('\u{1e2c0}',
+ '\u{1e2eb}'), ('\u{1e4d0}', '\u{1e4eb}'), ('\u{1e7e0}', '\u{1e7e6}'), ('\u{1e7e8}',
+ '\u{1e7eb}'), ('\u{1e7ed}', '\u{1e7ee}'), ('\u{1e7f0}', '\u{1e7fe}'), ('\u{1e800}',
+ '\u{1e8c4}'), ('\u{1e900}', '\u{1e943}'), ('\u{1e947}', '\u{1e947}'), ('\u{1e94b}',
+ '\u{1e94b}'), ('\u{1ee00}', '\u{1ee03}'), ('\u{1ee05}', '\u{1ee1f}'), ('\u{1ee21}',
+ '\u{1ee22}'), ('\u{1ee24}', '\u{1ee24}'), ('\u{1ee27}', '\u{1ee27}'), ('\u{1ee29}',
+ '\u{1ee32}'), ('\u{1ee34}', '\u{1ee37}'), ('\u{1ee39}', '\u{1ee39}'), ('\u{1ee3b}',
+ '\u{1ee3b}'), ('\u{1ee42}', '\u{1ee42}'), ('\u{1ee47}', '\u{1ee47}'), ('\u{1ee49}',
+ '\u{1ee49}'), ('\u{1ee4b}', '\u{1ee4b}'), ('\u{1ee4d}', '\u{1ee4f}'), ('\u{1ee51}',
+ '\u{1ee52}'), ('\u{1ee54}', '\u{1ee54}'), ('\u{1ee57}', '\u{1ee57}'), ('\u{1ee59}',
+ '\u{1ee59}'), ('\u{1ee5b}', '\u{1ee5b}'), ('\u{1ee5d}', '\u{1ee5d}'), ('\u{1ee5f}',
+ '\u{1ee5f}'), ('\u{1ee61}', '\u{1ee62}'), ('\u{1ee64}', '\u{1ee64}'), ('\u{1ee67}',
+ '\u{1ee6a}'), ('\u{1ee6c}', '\u{1ee72}'), ('\u{1ee74}', '\u{1ee77}'), ('\u{1ee79}',
+ '\u{1ee7c}'), ('\u{1ee7e}', '\u{1ee7e}'), ('\u{1ee80}', '\u{1ee89}'), ('\u{1ee8b}',
+ '\u{1ee9b}'), ('\u{1eea1}', '\u{1eea3}'), ('\u{1eea5}', '\u{1eea9}'), ('\u{1eeab}',
+ '\u{1eebb}'), ('\u{1f130}', '\u{1f149}'), ('\u{1f150}', '\u{1f169}'), ('\u{1f170}',
+ '\u{1f189}'), ('\u{20000}', '\u{2a6df}'), ('\u{2a700}', '\u{2b739}'), ('\u{2b740}',
+ '\u{2b81d}'), ('\u{2b820}', '\u{2cea1}'), ('\u{2ceb0}', '\u{2ebe0}'), ('\u{2f800}',
+ '\u{2fa1d}'), ('\u{30000}', '\u{3134a}'), ('\u{31350}', '\u{323af}')
];
#[inline]
@@ -441,55 +445,56 @@ pub mod grapheme {
GC_Extend), ('\u{cc3}', '\u{cc4}', GC_SpacingMark), ('\u{cc6}', '\u{cc6}', GC_Extend),
('\u{cc7}', '\u{cc8}', GC_SpacingMark), ('\u{cca}', '\u{ccb}', GC_SpacingMark), ('\u{ccc}',
'\u{ccd}', GC_Extend), ('\u{cd5}', '\u{cd6}', GC_Extend), ('\u{ce2}', '\u{ce3}', GC_Extend),
- ('\u{d00}', '\u{d01}', GC_Extend), ('\u{d02}', '\u{d03}', GC_SpacingMark), ('\u{d3b}',
- '\u{d3c}', GC_Extend), ('\u{d3e}', '\u{d3e}', GC_Extend), ('\u{d3f}', '\u{d40}',
- GC_SpacingMark), ('\u{d41}', '\u{d44}', GC_Extend), ('\u{d46}', '\u{d48}', GC_SpacingMark),
- ('\u{d4a}', '\u{d4c}', GC_SpacingMark), ('\u{d4d}', '\u{d4d}', GC_Extend), ('\u{d4e}',
- '\u{d4e}', GC_Prepend), ('\u{d57}', '\u{d57}', GC_Extend), ('\u{d62}', '\u{d63}',
- GC_Extend), ('\u{d81}', '\u{d81}', GC_Extend), ('\u{d82}', '\u{d83}', GC_SpacingMark),
- ('\u{dca}', '\u{dca}', GC_Extend), ('\u{dcf}', '\u{dcf}', GC_Extend), ('\u{dd0}', '\u{dd1}',
- GC_SpacingMark), ('\u{dd2}', '\u{dd4}', GC_Extend), ('\u{dd6}', '\u{dd6}', GC_Extend),
- ('\u{dd8}', '\u{dde}', GC_SpacingMark), ('\u{ddf}', '\u{ddf}', GC_Extend), ('\u{df2}',
- '\u{df3}', GC_SpacingMark), ('\u{e31}', '\u{e31}', GC_Extend), ('\u{e33}', '\u{e33}',
- GC_SpacingMark), ('\u{e34}', '\u{e3a}', GC_Extend), ('\u{e47}', '\u{e4e}', GC_Extend),
- ('\u{eb1}', '\u{eb1}', GC_Extend), ('\u{eb3}', '\u{eb3}', GC_SpacingMark), ('\u{eb4}',
- '\u{ebc}', GC_Extend), ('\u{ec8}', '\u{ecd}', GC_Extend), ('\u{f18}', '\u{f19}', GC_Extend),
- ('\u{f35}', '\u{f35}', GC_Extend), ('\u{f37}', '\u{f37}', GC_Extend), ('\u{f39}', '\u{f39}',
- GC_Extend), ('\u{f3e}', '\u{f3f}', GC_SpacingMark), ('\u{f71}', '\u{f7e}', GC_Extend),
- ('\u{f7f}', '\u{f7f}', GC_SpacingMark), ('\u{f80}', '\u{f84}', GC_Extend), ('\u{f86}',
- '\u{f87}', GC_Extend), ('\u{f8d}', '\u{f97}', GC_Extend), ('\u{f99}', '\u{fbc}', GC_Extend),
- ('\u{fc6}', '\u{fc6}', GC_Extend), ('\u{102d}', '\u{1030}', GC_Extend), ('\u{1031}',
- '\u{1031}', GC_SpacingMark), ('\u{1032}', '\u{1037}', GC_Extend), ('\u{1039}', '\u{103a}',
- GC_Extend), ('\u{103b}', '\u{103c}', GC_SpacingMark), ('\u{103d}', '\u{103e}', GC_Extend),
- ('\u{1056}', '\u{1057}', GC_SpacingMark), ('\u{1058}', '\u{1059}', GC_Extend), ('\u{105e}',
- '\u{1060}', GC_Extend), ('\u{1071}', '\u{1074}', GC_Extend), ('\u{1082}', '\u{1082}',
- GC_Extend), ('\u{1084}', '\u{1084}', GC_SpacingMark), ('\u{1085}', '\u{1086}', GC_Extend),
- ('\u{108d}', '\u{108d}', GC_Extend), ('\u{109d}', '\u{109d}', GC_Extend), ('\u{1100}',
- '\u{115f}', GC_L), ('\u{1160}', '\u{11a7}', GC_V), ('\u{11a8}', '\u{11ff}', GC_T),
- ('\u{135d}', '\u{135f}', GC_Extend), ('\u{1712}', '\u{1714}', GC_Extend), ('\u{1715}',
- '\u{1715}', GC_SpacingMark), ('\u{1732}', '\u{1733}', GC_Extend), ('\u{1734}', '\u{1734}',
- GC_SpacingMark), ('\u{1752}', '\u{1753}', GC_Extend), ('\u{1772}', '\u{1773}', GC_Extend),
- ('\u{17b4}', '\u{17b5}', GC_Extend), ('\u{17b6}', '\u{17b6}', GC_SpacingMark), ('\u{17b7}',
- '\u{17bd}', GC_Extend), ('\u{17be}', '\u{17c5}', GC_SpacingMark), ('\u{17c6}', '\u{17c6}',
- GC_Extend), ('\u{17c7}', '\u{17c8}', GC_SpacingMark), ('\u{17c9}', '\u{17d3}', GC_Extend),
- ('\u{17dd}', '\u{17dd}', GC_Extend), ('\u{180b}', '\u{180d}', GC_Extend), ('\u{180e}',
- '\u{180e}', GC_Control), ('\u{180f}', '\u{180f}', GC_Extend), ('\u{1885}', '\u{1886}',
- GC_Extend), ('\u{18a9}', '\u{18a9}', GC_Extend), ('\u{1920}', '\u{1922}', GC_Extend),
- ('\u{1923}', '\u{1926}', GC_SpacingMark), ('\u{1927}', '\u{1928}', GC_Extend), ('\u{1929}',
- '\u{192b}', GC_SpacingMark), ('\u{1930}', '\u{1931}', GC_SpacingMark), ('\u{1932}',
- '\u{1932}', GC_Extend), ('\u{1933}', '\u{1938}', GC_SpacingMark), ('\u{1939}', '\u{193b}',
- GC_Extend), ('\u{1a17}', '\u{1a18}', GC_Extend), ('\u{1a19}', '\u{1a1a}', GC_SpacingMark),
- ('\u{1a1b}', '\u{1a1b}', GC_Extend), ('\u{1a55}', '\u{1a55}', GC_SpacingMark), ('\u{1a56}',
- '\u{1a56}', GC_Extend), ('\u{1a57}', '\u{1a57}', GC_SpacingMark), ('\u{1a58}', '\u{1a5e}',
- GC_Extend), ('\u{1a60}', '\u{1a60}', GC_Extend), ('\u{1a62}', '\u{1a62}', GC_Extend),
- ('\u{1a65}', '\u{1a6c}', GC_Extend), ('\u{1a6d}', '\u{1a72}', GC_SpacingMark), ('\u{1a73}',
- '\u{1a7c}', GC_Extend), ('\u{1a7f}', '\u{1a7f}', GC_Extend), ('\u{1ab0}', '\u{1ace}',
- GC_Extend), ('\u{1b00}', '\u{1b03}', GC_Extend), ('\u{1b04}', '\u{1b04}', GC_SpacingMark),
- ('\u{1b34}', '\u{1b3a}', GC_Extend), ('\u{1b3b}', '\u{1b3b}', GC_SpacingMark), ('\u{1b3c}',
- '\u{1b3c}', GC_Extend), ('\u{1b3d}', '\u{1b41}', GC_SpacingMark), ('\u{1b42}', '\u{1b42}',
- GC_Extend), ('\u{1b43}', '\u{1b44}', GC_SpacingMark), ('\u{1b6b}', '\u{1b73}', GC_Extend),
- ('\u{1b80}', '\u{1b81}', GC_Extend), ('\u{1b82}', '\u{1b82}', GC_SpacingMark), ('\u{1ba1}',
- '\u{1ba1}', GC_SpacingMark), ('\u{1ba2}', '\u{1ba5}', GC_Extend), ('\u{1ba6}', '\u{1ba7}',
+ ('\u{cf3}', '\u{cf3}', GC_SpacingMark), ('\u{d00}', '\u{d01}', GC_Extend), ('\u{d02}',
+ '\u{d03}', GC_SpacingMark), ('\u{d3b}', '\u{d3c}', GC_Extend), ('\u{d3e}', '\u{d3e}',
+ GC_Extend), ('\u{d3f}', '\u{d40}', GC_SpacingMark), ('\u{d41}', '\u{d44}', GC_Extend),
+ ('\u{d46}', '\u{d48}', GC_SpacingMark), ('\u{d4a}', '\u{d4c}', GC_SpacingMark), ('\u{d4d}',
+ '\u{d4d}', GC_Extend), ('\u{d4e}', '\u{d4e}', GC_Prepend), ('\u{d57}', '\u{d57}',
+ GC_Extend), ('\u{d62}', '\u{d63}', GC_Extend), ('\u{d81}', '\u{d81}', GC_Extend),
+ ('\u{d82}', '\u{d83}', GC_SpacingMark), ('\u{dca}', '\u{dca}', GC_Extend), ('\u{dcf}',
+ '\u{dcf}', GC_Extend), ('\u{dd0}', '\u{dd1}', GC_SpacingMark), ('\u{dd2}', '\u{dd4}',
+ GC_Extend), ('\u{dd6}', '\u{dd6}', GC_Extend), ('\u{dd8}', '\u{dde}', GC_SpacingMark),
+ ('\u{ddf}', '\u{ddf}', GC_Extend), ('\u{df2}', '\u{df3}', GC_SpacingMark), ('\u{e31}',
+ '\u{e31}', GC_Extend), ('\u{e33}', '\u{e33}', GC_SpacingMark), ('\u{e34}', '\u{e3a}',
+ GC_Extend), ('\u{e47}', '\u{e4e}', GC_Extend), ('\u{eb1}', '\u{eb1}', GC_Extend),
+ ('\u{eb3}', '\u{eb3}', GC_SpacingMark), ('\u{eb4}', '\u{ebc}', GC_Extend), ('\u{ec8}',
+ '\u{ece}', GC_Extend), ('\u{f18}', '\u{f19}', GC_Extend), ('\u{f35}', '\u{f35}', GC_Extend),
+ ('\u{f37}', '\u{f37}', GC_Extend), ('\u{f39}', '\u{f39}', GC_Extend), ('\u{f3e}', '\u{f3f}',
+ GC_SpacingMark), ('\u{f71}', '\u{f7e}', GC_Extend), ('\u{f7f}', '\u{f7f}', GC_SpacingMark),
+ ('\u{f80}', '\u{f84}', GC_Extend), ('\u{f86}', '\u{f87}', GC_Extend), ('\u{f8d}', '\u{f97}',
+ GC_Extend), ('\u{f99}', '\u{fbc}', GC_Extend), ('\u{fc6}', '\u{fc6}', GC_Extend),
+ ('\u{102d}', '\u{1030}', GC_Extend), ('\u{1031}', '\u{1031}', GC_SpacingMark), ('\u{1032}',
+ '\u{1037}', GC_Extend), ('\u{1039}', '\u{103a}', GC_Extend), ('\u{103b}', '\u{103c}',
+ GC_SpacingMark), ('\u{103d}', '\u{103e}', GC_Extend), ('\u{1056}', '\u{1057}',
+ GC_SpacingMark), ('\u{1058}', '\u{1059}', GC_Extend), ('\u{105e}', '\u{1060}', GC_Extend),
+ ('\u{1071}', '\u{1074}', GC_Extend), ('\u{1082}', '\u{1082}', GC_Extend), ('\u{1084}',
+ '\u{1084}', GC_SpacingMark), ('\u{1085}', '\u{1086}', GC_Extend), ('\u{108d}', '\u{108d}',
+ GC_Extend), ('\u{109d}', '\u{109d}', GC_Extend), ('\u{1100}', '\u{115f}', GC_L),
+ ('\u{1160}', '\u{11a7}', GC_V), ('\u{11a8}', '\u{11ff}', GC_T), ('\u{135d}', '\u{135f}',
+ GC_Extend), ('\u{1712}', '\u{1714}', GC_Extend), ('\u{1715}', '\u{1715}', GC_SpacingMark),
+ ('\u{1732}', '\u{1733}', GC_Extend), ('\u{1734}', '\u{1734}', GC_SpacingMark), ('\u{1752}',
+ '\u{1753}', GC_Extend), ('\u{1772}', '\u{1773}', GC_Extend), ('\u{17b4}', '\u{17b5}',
+ GC_Extend), ('\u{17b6}', '\u{17b6}', GC_SpacingMark), ('\u{17b7}', '\u{17bd}', GC_Extend),
+ ('\u{17be}', '\u{17c5}', GC_SpacingMark), ('\u{17c6}', '\u{17c6}', GC_Extend), ('\u{17c7}',
+ '\u{17c8}', GC_SpacingMark), ('\u{17c9}', '\u{17d3}', GC_Extend), ('\u{17dd}', '\u{17dd}',
+ GC_Extend), ('\u{180b}', '\u{180d}', GC_Extend), ('\u{180e}', '\u{180e}', GC_Control),
+ ('\u{180f}', '\u{180f}', GC_Extend), ('\u{1885}', '\u{1886}', GC_Extend), ('\u{18a9}',
+ '\u{18a9}', GC_Extend), ('\u{1920}', '\u{1922}', GC_Extend), ('\u{1923}', '\u{1926}',
+ GC_SpacingMark), ('\u{1927}', '\u{1928}', GC_Extend), ('\u{1929}', '\u{192b}',
+ GC_SpacingMark), ('\u{1930}', '\u{1931}', GC_SpacingMark), ('\u{1932}', '\u{1932}',
+ GC_Extend), ('\u{1933}', '\u{1938}', GC_SpacingMark), ('\u{1939}', '\u{193b}', GC_Extend),
+ ('\u{1a17}', '\u{1a18}', GC_Extend), ('\u{1a19}', '\u{1a1a}', GC_SpacingMark), ('\u{1a1b}',
+ '\u{1a1b}', GC_Extend), ('\u{1a55}', '\u{1a55}', GC_SpacingMark), ('\u{1a56}', '\u{1a56}',
+ GC_Extend), ('\u{1a57}', '\u{1a57}', GC_SpacingMark), ('\u{1a58}', '\u{1a5e}', GC_Extend),
+ ('\u{1a60}', '\u{1a60}', GC_Extend), ('\u{1a62}', '\u{1a62}', GC_Extend), ('\u{1a65}',
+ '\u{1a6c}', GC_Extend), ('\u{1a6d}', '\u{1a72}', GC_SpacingMark), ('\u{1a73}', '\u{1a7c}',
+ GC_Extend), ('\u{1a7f}', '\u{1a7f}', GC_Extend), ('\u{1ab0}', '\u{1ace}', GC_Extend),
+ ('\u{1b00}', '\u{1b03}', GC_Extend), ('\u{1b04}', '\u{1b04}', GC_SpacingMark), ('\u{1b34}',
+ '\u{1b3a}', GC_Extend), ('\u{1b3b}', '\u{1b3b}', GC_SpacingMark), ('\u{1b3c}', '\u{1b3c}',
+ GC_Extend), ('\u{1b3d}', '\u{1b41}', GC_SpacingMark), ('\u{1b42}', '\u{1b42}', GC_Extend),
+ ('\u{1b43}', '\u{1b44}', GC_SpacingMark), ('\u{1b6b}', '\u{1b73}', GC_Extend), ('\u{1b80}',
+ '\u{1b81}', GC_Extend), ('\u{1b82}', '\u{1b82}', GC_SpacingMark), ('\u{1ba1}', '\u{1ba1}',
+ GC_SpacingMark), ('\u{1ba2}', '\u{1ba5}', GC_Extend), ('\u{1ba6}', '\u{1ba7}',
GC_SpacingMark), ('\u{1ba8}', '\u{1ba9}', GC_Extend), ('\u{1baa}', '\u{1baa}',
GC_SpacingMark), ('\u{1bab}', '\u{1bad}', GC_Extend), ('\u{1be6}', '\u{1be6}', GC_Extend),
('\u{1be7}', '\u{1be7}', GC_SpacingMark), ('\u{1be8}', '\u{1be9}', GC_Extend), ('\u{1bea}',
@@ -866,74 +871,75 @@ pub mod grapheme {
('\u{10a01}', '\u{10a03}', GC_Extend), ('\u{10a05}', '\u{10a06}', GC_Extend), ('\u{10a0c}',
'\u{10a0f}', GC_Extend), ('\u{10a38}', '\u{10a3a}', GC_Extend), ('\u{10a3f}', '\u{10a3f}',
GC_Extend), ('\u{10ae5}', '\u{10ae6}', GC_Extend), ('\u{10d24}', '\u{10d27}', GC_Extend),
- ('\u{10eab}', '\u{10eac}', GC_Extend), ('\u{10f46}', '\u{10f50}', GC_Extend), ('\u{10f82}',
- '\u{10f85}', GC_Extend), ('\u{11000}', '\u{11000}', GC_SpacingMark), ('\u{11001}',
- '\u{11001}', GC_Extend), ('\u{11002}', '\u{11002}', GC_SpacingMark), ('\u{11038}',
- '\u{11046}', GC_Extend), ('\u{11070}', '\u{11070}', GC_Extend), ('\u{11073}', '\u{11074}',
- GC_Extend), ('\u{1107f}', '\u{11081}', GC_Extend), ('\u{11082}', '\u{11082}',
- GC_SpacingMark), ('\u{110b0}', '\u{110b2}', GC_SpacingMark), ('\u{110b3}', '\u{110b6}',
- GC_Extend), ('\u{110b7}', '\u{110b8}', GC_SpacingMark), ('\u{110b9}', '\u{110ba}',
- GC_Extend), ('\u{110bd}', '\u{110bd}', GC_Prepend), ('\u{110c2}', '\u{110c2}', GC_Extend),
- ('\u{110cd}', '\u{110cd}', GC_Prepend), ('\u{11100}', '\u{11102}', GC_Extend), ('\u{11127}',
- '\u{1112b}', GC_Extend), ('\u{1112c}', '\u{1112c}', GC_SpacingMark), ('\u{1112d}',
- '\u{11134}', GC_Extend), ('\u{11145}', '\u{11146}', GC_SpacingMark), ('\u{11173}',
- '\u{11173}', GC_Extend), ('\u{11180}', '\u{11181}', GC_Extend), ('\u{11182}', '\u{11182}',
- GC_SpacingMark), ('\u{111b3}', '\u{111b5}', GC_SpacingMark), ('\u{111b6}', '\u{111be}',
- GC_Extend), ('\u{111bf}', '\u{111c0}', GC_SpacingMark), ('\u{111c2}', '\u{111c3}',
- GC_Prepend), ('\u{111c9}', '\u{111cc}', GC_Extend), ('\u{111ce}', '\u{111ce}',
- GC_SpacingMark), ('\u{111cf}', '\u{111cf}', GC_Extend), ('\u{1122c}', '\u{1122e}',
- GC_SpacingMark), ('\u{1122f}', '\u{11231}', GC_Extend), ('\u{11232}', '\u{11233}',
- GC_SpacingMark), ('\u{11234}', '\u{11234}', GC_Extend), ('\u{11235}', '\u{11235}',
- GC_SpacingMark), ('\u{11236}', '\u{11237}', GC_Extend), ('\u{1123e}', '\u{1123e}',
- GC_Extend), ('\u{112df}', '\u{112df}', GC_Extend), ('\u{112e0}', '\u{112e2}',
- GC_SpacingMark), ('\u{112e3}', '\u{112ea}', GC_Extend), ('\u{11300}', '\u{11301}',
- GC_Extend), ('\u{11302}', '\u{11303}', GC_SpacingMark), ('\u{1133b}', '\u{1133c}',
- GC_Extend), ('\u{1133e}', '\u{1133e}', GC_Extend), ('\u{1133f}', '\u{1133f}',
- GC_SpacingMark), ('\u{11340}', '\u{11340}', GC_Extend), ('\u{11341}', '\u{11344}',
- GC_SpacingMark), ('\u{11347}', '\u{11348}', GC_SpacingMark), ('\u{1134b}', '\u{1134d}',
- GC_SpacingMark), ('\u{11357}', '\u{11357}', GC_Extend), ('\u{11362}', '\u{11363}',
- GC_SpacingMark), ('\u{11366}', '\u{1136c}', GC_Extend), ('\u{11370}', '\u{11374}',
- GC_Extend), ('\u{11435}', '\u{11437}', GC_SpacingMark), ('\u{11438}', '\u{1143f}',
- GC_Extend), ('\u{11440}', '\u{11441}', GC_SpacingMark), ('\u{11442}', '\u{11444}',
- GC_Extend), ('\u{11445}', '\u{11445}', GC_SpacingMark), ('\u{11446}', '\u{11446}',
- GC_Extend), ('\u{1145e}', '\u{1145e}', GC_Extend), ('\u{114b0}', '\u{114b0}', GC_Extend),
- ('\u{114b1}', '\u{114b2}', GC_SpacingMark), ('\u{114b3}', '\u{114b8}', GC_Extend),
- ('\u{114b9}', '\u{114b9}', GC_SpacingMark), ('\u{114ba}', '\u{114ba}', GC_Extend),
- ('\u{114bb}', '\u{114bc}', GC_SpacingMark), ('\u{114bd}', '\u{114bd}', GC_Extend),
- ('\u{114be}', '\u{114be}', GC_SpacingMark), ('\u{114bf}', '\u{114c0}', GC_Extend),
- ('\u{114c1}', '\u{114c1}', GC_SpacingMark), ('\u{114c2}', '\u{114c3}', GC_Extend),
- ('\u{115af}', '\u{115af}', GC_Extend), ('\u{115b0}', '\u{115b1}', GC_SpacingMark),
- ('\u{115b2}', '\u{115b5}', GC_Extend), ('\u{115b8}', '\u{115bb}', GC_SpacingMark),
- ('\u{115bc}', '\u{115bd}', GC_Extend), ('\u{115be}', '\u{115be}', GC_SpacingMark),
- ('\u{115bf}', '\u{115c0}', GC_Extend), ('\u{115dc}', '\u{115dd}', GC_Extend), ('\u{11630}',
- '\u{11632}', GC_SpacingMark), ('\u{11633}', '\u{1163a}', GC_Extend), ('\u{1163b}',
- '\u{1163c}', GC_SpacingMark), ('\u{1163d}', '\u{1163d}', GC_Extend), ('\u{1163e}',
- '\u{1163e}', GC_SpacingMark), ('\u{1163f}', '\u{11640}', GC_Extend), ('\u{116ab}',
- '\u{116ab}', GC_Extend), ('\u{116ac}', '\u{116ac}', GC_SpacingMark), ('\u{116ad}',
- '\u{116ad}', GC_Extend), ('\u{116ae}', '\u{116af}', GC_SpacingMark), ('\u{116b0}',
- '\u{116b5}', GC_Extend), ('\u{116b6}', '\u{116b6}', GC_SpacingMark), ('\u{116b7}',
- '\u{116b7}', GC_Extend), ('\u{1171d}', '\u{1171f}', GC_Extend), ('\u{11722}', '\u{11725}',
- GC_Extend), ('\u{11726}', '\u{11726}', GC_SpacingMark), ('\u{11727}', '\u{1172b}',
- GC_Extend), ('\u{1182c}', '\u{1182e}', GC_SpacingMark), ('\u{1182f}', '\u{11837}',
- GC_Extend), ('\u{11838}', '\u{11838}', GC_SpacingMark), ('\u{11839}', '\u{1183a}',
- GC_Extend), ('\u{11930}', '\u{11930}', GC_Extend), ('\u{11931}', '\u{11935}',
- GC_SpacingMark), ('\u{11937}', '\u{11938}', GC_SpacingMark), ('\u{1193b}', '\u{1193c}',
- GC_Extend), ('\u{1193d}', '\u{1193d}', GC_SpacingMark), ('\u{1193e}', '\u{1193e}',
- GC_Extend), ('\u{1193f}', '\u{1193f}', GC_Prepend), ('\u{11940}', '\u{11940}',
- GC_SpacingMark), ('\u{11941}', '\u{11941}', GC_Prepend), ('\u{11942}', '\u{11942}',
- GC_SpacingMark), ('\u{11943}', '\u{11943}', GC_Extend), ('\u{119d1}', '\u{119d3}',
- GC_SpacingMark), ('\u{119d4}', '\u{119d7}', GC_Extend), ('\u{119da}', '\u{119db}',
- GC_Extend), ('\u{119dc}', '\u{119df}', GC_SpacingMark), ('\u{119e0}', '\u{119e0}',
- GC_Extend), ('\u{119e4}', '\u{119e4}', GC_SpacingMark), ('\u{11a01}', '\u{11a0a}',
- GC_Extend), ('\u{11a33}', '\u{11a38}', GC_Extend), ('\u{11a39}', '\u{11a39}',
- GC_SpacingMark), ('\u{11a3a}', '\u{11a3a}', GC_Prepend), ('\u{11a3b}', '\u{11a3e}',
- GC_Extend), ('\u{11a47}', '\u{11a47}', GC_Extend), ('\u{11a51}', '\u{11a56}', GC_Extend),
- ('\u{11a57}', '\u{11a58}', GC_SpacingMark), ('\u{11a59}', '\u{11a5b}', GC_Extend),
- ('\u{11a84}', '\u{11a89}', GC_Prepend), ('\u{11a8a}', '\u{11a96}', GC_Extend), ('\u{11a97}',
- '\u{11a97}', GC_SpacingMark), ('\u{11a98}', '\u{11a99}', GC_Extend), ('\u{11c2f}',
- '\u{11c2f}', GC_SpacingMark), ('\u{11c30}', '\u{11c36}', GC_Extend), ('\u{11c38}',
- '\u{11c3d}', GC_Extend), ('\u{11c3e}', '\u{11c3e}', GC_SpacingMark), ('\u{11c3f}',
- '\u{11c3f}', GC_Extend), ('\u{11c92}', '\u{11ca7}', GC_Extend), ('\u{11ca9}', '\u{11ca9}',
+ ('\u{10eab}', '\u{10eac}', GC_Extend), ('\u{10efd}', '\u{10eff}', GC_Extend), ('\u{10f46}',
+ '\u{10f50}', GC_Extend), ('\u{10f82}', '\u{10f85}', GC_Extend), ('\u{11000}', '\u{11000}',
+ GC_SpacingMark), ('\u{11001}', '\u{11001}', GC_Extend), ('\u{11002}', '\u{11002}',
+ GC_SpacingMark), ('\u{11038}', '\u{11046}', GC_Extend), ('\u{11070}', '\u{11070}',
+ GC_Extend), ('\u{11073}', '\u{11074}', GC_Extend), ('\u{1107f}', '\u{11081}', GC_Extend),
+ ('\u{11082}', '\u{11082}', GC_SpacingMark), ('\u{110b0}', '\u{110b2}', GC_SpacingMark),
+ ('\u{110b3}', '\u{110b6}', GC_Extend), ('\u{110b7}', '\u{110b8}', GC_SpacingMark),
+ ('\u{110b9}', '\u{110ba}', GC_Extend), ('\u{110bd}', '\u{110bd}', GC_Prepend), ('\u{110c2}',
+ '\u{110c2}', GC_Extend), ('\u{110cd}', '\u{110cd}', GC_Prepend), ('\u{11100}', '\u{11102}',
+ GC_Extend), ('\u{11127}', '\u{1112b}', GC_Extend), ('\u{1112c}', '\u{1112c}',
+ GC_SpacingMark), ('\u{1112d}', '\u{11134}', GC_Extend), ('\u{11145}', '\u{11146}',
+ GC_SpacingMark), ('\u{11173}', '\u{11173}', GC_Extend), ('\u{11180}', '\u{11181}',
+ GC_Extend), ('\u{11182}', '\u{11182}', GC_SpacingMark), ('\u{111b3}', '\u{111b5}',
+ GC_SpacingMark), ('\u{111b6}', '\u{111be}', GC_Extend), ('\u{111bf}', '\u{111c0}',
+ GC_SpacingMark), ('\u{111c2}', '\u{111c3}', GC_Prepend), ('\u{111c9}', '\u{111cc}',
+ GC_Extend), ('\u{111ce}', '\u{111ce}', GC_SpacingMark), ('\u{111cf}', '\u{111cf}',
+ GC_Extend), ('\u{1122c}', '\u{1122e}', GC_SpacingMark), ('\u{1122f}', '\u{11231}',
+ GC_Extend), ('\u{11232}', '\u{11233}', GC_SpacingMark), ('\u{11234}', '\u{11234}',
+ GC_Extend), ('\u{11235}', '\u{11235}', GC_SpacingMark), ('\u{11236}', '\u{11237}',
+ GC_Extend), ('\u{1123e}', '\u{1123e}', GC_Extend), ('\u{11241}', '\u{11241}', GC_Extend),
+ ('\u{112df}', '\u{112df}', GC_Extend), ('\u{112e0}', '\u{112e2}', GC_SpacingMark),
+ ('\u{112e3}', '\u{112ea}', GC_Extend), ('\u{11300}', '\u{11301}', GC_Extend), ('\u{11302}',
+ '\u{11303}', GC_SpacingMark), ('\u{1133b}', '\u{1133c}', GC_Extend), ('\u{1133e}',
+ '\u{1133e}', GC_Extend), ('\u{1133f}', '\u{1133f}', GC_SpacingMark), ('\u{11340}',
+ '\u{11340}', GC_Extend), ('\u{11341}', '\u{11344}', GC_SpacingMark), ('\u{11347}',
+ '\u{11348}', GC_SpacingMark), ('\u{1134b}', '\u{1134d}', GC_SpacingMark), ('\u{11357}',
+ '\u{11357}', GC_Extend), ('\u{11362}', '\u{11363}', GC_SpacingMark), ('\u{11366}',
+ '\u{1136c}', GC_Extend), ('\u{11370}', '\u{11374}', GC_Extend), ('\u{11435}', '\u{11437}',
+ GC_SpacingMark), ('\u{11438}', '\u{1143f}', GC_Extend), ('\u{11440}', '\u{11441}',
+ GC_SpacingMark), ('\u{11442}', '\u{11444}', GC_Extend), ('\u{11445}', '\u{11445}',
+ GC_SpacingMark), ('\u{11446}', '\u{11446}', GC_Extend), ('\u{1145e}', '\u{1145e}',
+ GC_Extend), ('\u{114b0}', '\u{114b0}', GC_Extend), ('\u{114b1}', '\u{114b2}',
+ GC_SpacingMark), ('\u{114b3}', '\u{114b8}', GC_Extend), ('\u{114b9}', '\u{114b9}',
+ GC_SpacingMark), ('\u{114ba}', '\u{114ba}', GC_Extend), ('\u{114bb}', '\u{114bc}',
+ GC_SpacingMark), ('\u{114bd}', '\u{114bd}', GC_Extend), ('\u{114be}', '\u{114be}',
+ GC_SpacingMark), ('\u{114bf}', '\u{114c0}', GC_Extend), ('\u{114c1}', '\u{114c1}',
+ GC_SpacingMark), ('\u{114c2}', '\u{114c3}', GC_Extend), ('\u{115af}', '\u{115af}',
+ GC_Extend), ('\u{115b0}', '\u{115b1}', GC_SpacingMark), ('\u{115b2}', '\u{115b5}',
+ GC_Extend), ('\u{115b8}', '\u{115bb}', GC_SpacingMark), ('\u{115bc}', '\u{115bd}',
+ GC_Extend), ('\u{115be}', '\u{115be}', GC_SpacingMark), ('\u{115bf}', '\u{115c0}',
+ GC_Extend), ('\u{115dc}', '\u{115dd}', GC_Extend), ('\u{11630}', '\u{11632}',
+ GC_SpacingMark), ('\u{11633}', '\u{1163a}', GC_Extend), ('\u{1163b}', '\u{1163c}',
+ GC_SpacingMark), ('\u{1163d}', '\u{1163d}', GC_Extend), ('\u{1163e}', '\u{1163e}',
+ GC_SpacingMark), ('\u{1163f}', '\u{11640}', GC_Extend), ('\u{116ab}', '\u{116ab}',
+ GC_Extend), ('\u{116ac}', '\u{116ac}', GC_SpacingMark), ('\u{116ad}', '\u{116ad}',
+ GC_Extend), ('\u{116ae}', '\u{116af}', GC_SpacingMark), ('\u{116b0}', '\u{116b5}',
+ GC_Extend), ('\u{116b6}', '\u{116b6}', GC_SpacingMark), ('\u{116b7}', '\u{116b7}',
+ GC_Extend), ('\u{1171d}', '\u{1171f}', GC_Extend), ('\u{11722}', '\u{11725}', GC_Extend),
+ ('\u{11726}', '\u{11726}', GC_SpacingMark), ('\u{11727}', '\u{1172b}', GC_Extend),
+ ('\u{1182c}', '\u{1182e}', GC_SpacingMark), ('\u{1182f}', '\u{11837}', GC_Extend),
+ ('\u{11838}', '\u{11838}', GC_SpacingMark), ('\u{11839}', '\u{1183a}', GC_Extend),
+ ('\u{11930}', '\u{11930}', GC_Extend), ('\u{11931}', '\u{11935}', GC_SpacingMark),
+ ('\u{11937}', '\u{11938}', GC_SpacingMark), ('\u{1193b}', '\u{1193c}', GC_Extend),
+ ('\u{1193d}', '\u{1193d}', GC_SpacingMark), ('\u{1193e}', '\u{1193e}', GC_Extend),
+ ('\u{1193f}', '\u{1193f}', GC_Prepend), ('\u{11940}', '\u{11940}', GC_SpacingMark),
+ ('\u{11941}', '\u{11941}', GC_Prepend), ('\u{11942}', '\u{11942}', GC_SpacingMark),
+ ('\u{11943}', '\u{11943}', GC_Extend), ('\u{119d1}', '\u{119d3}', GC_SpacingMark),
+ ('\u{119d4}', '\u{119d7}', GC_Extend), ('\u{119da}', '\u{119db}', GC_Extend), ('\u{119dc}',
+ '\u{119df}', GC_SpacingMark), ('\u{119e0}', '\u{119e0}', GC_Extend), ('\u{119e4}',
+ '\u{119e4}', GC_SpacingMark), ('\u{11a01}', '\u{11a0a}', GC_Extend), ('\u{11a33}',
+ '\u{11a38}', GC_Extend), ('\u{11a39}', '\u{11a39}', GC_SpacingMark), ('\u{11a3a}',
+ '\u{11a3a}', GC_Prepend), ('\u{11a3b}', '\u{11a3e}', GC_Extend), ('\u{11a47}', '\u{11a47}',
+ GC_Extend), ('\u{11a51}', '\u{11a56}', GC_Extend), ('\u{11a57}', '\u{11a58}',
+ GC_SpacingMark), ('\u{11a59}', '\u{11a5b}', GC_Extend), ('\u{11a84}', '\u{11a89}',
+ GC_Prepend), ('\u{11a8a}', '\u{11a96}', GC_Extend), ('\u{11a97}', '\u{11a97}',
+ GC_SpacingMark), ('\u{11a98}', '\u{11a99}', GC_Extend), ('\u{11c2f}', '\u{11c2f}',
+ GC_SpacingMark), ('\u{11c30}', '\u{11c36}', GC_Extend), ('\u{11c38}', '\u{11c3d}',
+ GC_Extend), ('\u{11c3e}', '\u{11c3e}', GC_SpacingMark), ('\u{11c3f}', '\u{11c3f}',
+ GC_Extend), ('\u{11c92}', '\u{11ca7}', GC_Extend), ('\u{11ca9}', '\u{11ca9}',
GC_SpacingMark), ('\u{11caa}', '\u{11cb0}', GC_Extend), ('\u{11cb1}', '\u{11cb1}',
GC_SpacingMark), ('\u{11cb2}', '\u{11cb3}', GC_Extend), ('\u{11cb4}', '\u{11cb4}',
GC_SpacingMark), ('\u{11cb5}', '\u{11cb6}', GC_Extend), ('\u{11d31}', '\u{11d36}',
@@ -943,45 +949,52 @@ pub mod grapheme {
'\u{11d91}', GC_Extend), ('\u{11d93}', '\u{11d94}', GC_SpacingMark), ('\u{11d95}',
'\u{11d95}', GC_Extend), ('\u{11d96}', '\u{11d96}', GC_SpacingMark), ('\u{11d97}',
'\u{11d97}', GC_Extend), ('\u{11ef3}', '\u{11ef4}', GC_Extend), ('\u{11ef5}', '\u{11ef6}',
- GC_SpacingMark), ('\u{13430}', '\u{13438}', GC_Control), ('\u{16af0}', '\u{16af4}',
- GC_Extend), ('\u{16b30}', '\u{16b36}', GC_Extend), ('\u{16f4f}', '\u{16f4f}', GC_Extend),
- ('\u{16f51}', '\u{16f87}', GC_SpacingMark), ('\u{16f8f}', '\u{16f92}', GC_Extend),
- ('\u{16fe4}', '\u{16fe4}', GC_Extend), ('\u{16ff0}', '\u{16ff1}', GC_SpacingMark),
- ('\u{1bc9d}', '\u{1bc9e}', GC_Extend), ('\u{1bca0}', '\u{1bca3}', GC_Control), ('\u{1cf00}',
- '\u{1cf2d}', GC_Extend), ('\u{1cf30}', '\u{1cf46}', GC_Extend), ('\u{1d165}', '\u{1d165}',
- GC_Extend), ('\u{1d166}', '\u{1d166}', GC_SpacingMark), ('\u{1d167}', '\u{1d169}',
- GC_Extend), ('\u{1d16d}', '\u{1d16d}', GC_SpacingMark), ('\u{1d16e}', '\u{1d172}',
- GC_Extend), ('\u{1d173}', '\u{1d17a}', GC_Control), ('\u{1d17b}', '\u{1d182}', GC_Extend),
- ('\u{1d185}', '\u{1d18b}', GC_Extend), ('\u{1d1aa}', '\u{1d1ad}', GC_Extend), ('\u{1d242}',
- '\u{1d244}', GC_Extend), ('\u{1da00}', '\u{1da36}', GC_Extend), ('\u{1da3b}', '\u{1da6c}',
- GC_Extend), ('\u{1da75}', '\u{1da75}', GC_Extend), ('\u{1da84}', '\u{1da84}', GC_Extend),
- ('\u{1da9b}', '\u{1da9f}', GC_Extend), ('\u{1daa1}', '\u{1daaf}', GC_Extend), ('\u{1e000}',
- '\u{1e006}', GC_Extend), ('\u{1e008}', '\u{1e018}', GC_Extend), ('\u{1e01b}', '\u{1e021}',
- GC_Extend), ('\u{1e023}', '\u{1e024}', GC_Extend), ('\u{1e026}', '\u{1e02a}', GC_Extend),
- ('\u{1e130}', '\u{1e136}', GC_Extend), ('\u{1e2ae}', '\u{1e2ae}', GC_Extend), ('\u{1e2ec}',
- '\u{1e2ef}', GC_Extend), ('\u{1e8d0}', '\u{1e8d6}', GC_Extend), ('\u{1e944}', '\u{1e94a}',
- GC_Extend), ('\u{1f000}', '\u{1f0ff}', GC_Extended_Pictographic), ('\u{1f10d}', '\u{1f10f}',
- GC_Extended_Pictographic), ('\u{1f12f}', '\u{1f12f}', GC_Extended_Pictographic),
- ('\u{1f16c}', '\u{1f171}', GC_Extended_Pictographic), ('\u{1f17e}', '\u{1f17f}',
- GC_Extended_Pictographic), ('\u{1f18e}', '\u{1f18e}', GC_Extended_Pictographic),
- ('\u{1f191}', '\u{1f19a}', GC_Extended_Pictographic), ('\u{1f1ad}', '\u{1f1e5}',
- GC_Extended_Pictographic), ('\u{1f1e6}', '\u{1f1ff}', GC_Regional_Indicator), ('\u{1f201}',
- '\u{1f20f}', GC_Extended_Pictographic), ('\u{1f21a}', '\u{1f21a}',
- GC_Extended_Pictographic), ('\u{1f22f}', '\u{1f22f}', GC_Extended_Pictographic),
- ('\u{1f232}', '\u{1f23a}', GC_Extended_Pictographic), ('\u{1f23c}', '\u{1f23f}',
- GC_Extended_Pictographic), ('\u{1f249}', '\u{1f3fa}', GC_Extended_Pictographic),
- ('\u{1f3fb}', '\u{1f3ff}', GC_Extend), ('\u{1f400}', '\u{1f53d}', GC_Extended_Pictographic),
- ('\u{1f546}', '\u{1f64f}', GC_Extended_Pictographic), ('\u{1f680}', '\u{1f6ff}',
- GC_Extended_Pictographic), ('\u{1f774}', '\u{1f77f}', GC_Extended_Pictographic),
- ('\u{1f7d5}', '\u{1f7ff}', GC_Extended_Pictographic), ('\u{1f80c}', '\u{1f80f}',
- GC_Extended_Pictographic), ('\u{1f848}', '\u{1f84f}', GC_Extended_Pictographic),
- ('\u{1f85a}', '\u{1f85f}', GC_Extended_Pictographic), ('\u{1f888}', '\u{1f88f}',
- GC_Extended_Pictographic), ('\u{1f8ae}', '\u{1f8ff}', GC_Extended_Pictographic),
- ('\u{1f90c}', '\u{1f93a}', GC_Extended_Pictographic), ('\u{1f93c}', '\u{1f945}',
- GC_Extended_Pictographic), ('\u{1f947}', '\u{1faff}', GC_Extended_Pictographic),
- ('\u{1fc00}', '\u{1fffd}', GC_Extended_Pictographic), ('\u{e0000}', '\u{e001f}',
- GC_Control), ('\u{e0020}', '\u{e007f}', GC_Extend), ('\u{e0080}', '\u{e00ff}', GC_Control),
- ('\u{e0100}', '\u{e01ef}', GC_Extend), ('\u{e01f0}', '\u{e0fff}', GC_Control)
+ GC_SpacingMark), ('\u{11f00}', '\u{11f01}', GC_Extend), ('\u{11f02}', '\u{11f02}',
+ GC_Prepend), ('\u{11f03}', '\u{11f03}', GC_SpacingMark), ('\u{11f34}', '\u{11f35}',
+ GC_SpacingMark), ('\u{11f36}', '\u{11f3a}', GC_Extend), ('\u{11f3e}', '\u{11f3f}',
+ GC_SpacingMark), ('\u{11f40}', '\u{11f40}', GC_Extend), ('\u{11f41}', '\u{11f41}',
+ GC_SpacingMark), ('\u{11f42}', '\u{11f42}', GC_Extend), ('\u{13430}', '\u{1343f}',
+ GC_Control), ('\u{13440}', '\u{13440}', GC_Extend), ('\u{13447}', '\u{13455}', GC_Extend),
+ ('\u{16af0}', '\u{16af4}', GC_Extend), ('\u{16b30}', '\u{16b36}', GC_Extend), ('\u{16f4f}',
+ '\u{16f4f}', GC_Extend), ('\u{16f51}', '\u{16f87}', GC_SpacingMark), ('\u{16f8f}',
+ '\u{16f92}', GC_Extend), ('\u{16fe4}', '\u{16fe4}', GC_Extend), ('\u{16ff0}', '\u{16ff1}',
+ GC_SpacingMark), ('\u{1bc9d}', '\u{1bc9e}', GC_Extend), ('\u{1bca0}', '\u{1bca3}',
+ GC_Control), ('\u{1cf00}', '\u{1cf2d}', GC_Extend), ('\u{1cf30}', '\u{1cf46}', GC_Extend),
+ ('\u{1d165}', '\u{1d165}', GC_Extend), ('\u{1d166}', '\u{1d166}', GC_SpacingMark),
+ ('\u{1d167}', '\u{1d169}', GC_Extend), ('\u{1d16d}', '\u{1d16d}', GC_SpacingMark),
+ ('\u{1d16e}', '\u{1d172}', GC_Extend), ('\u{1d173}', '\u{1d17a}', GC_Control), ('\u{1d17b}',
+ '\u{1d182}', GC_Extend), ('\u{1d185}', '\u{1d18b}', GC_Extend), ('\u{1d1aa}', '\u{1d1ad}',
+ GC_Extend), ('\u{1d242}', '\u{1d244}', GC_Extend), ('\u{1da00}', '\u{1da36}', GC_Extend),
+ ('\u{1da3b}', '\u{1da6c}', GC_Extend), ('\u{1da75}', '\u{1da75}', GC_Extend), ('\u{1da84}',
+ '\u{1da84}', GC_Extend), ('\u{1da9b}', '\u{1da9f}', GC_Extend), ('\u{1daa1}', '\u{1daaf}',
+ GC_Extend), ('\u{1e000}', '\u{1e006}', GC_Extend), ('\u{1e008}', '\u{1e018}', GC_Extend),
+ ('\u{1e01b}', '\u{1e021}', GC_Extend), ('\u{1e023}', '\u{1e024}', GC_Extend), ('\u{1e026}',
+ '\u{1e02a}', GC_Extend), ('\u{1e08f}', '\u{1e08f}', GC_Extend), ('\u{1e130}', '\u{1e136}',
+ GC_Extend), ('\u{1e2ae}', '\u{1e2ae}', GC_Extend), ('\u{1e2ec}', '\u{1e2ef}', GC_Extend),
+ ('\u{1e4ec}', '\u{1e4ef}', GC_Extend), ('\u{1e8d0}', '\u{1e8d6}', GC_Extend), ('\u{1e944}',
+ '\u{1e94a}', GC_Extend), ('\u{1f000}', '\u{1f0ff}', GC_Extended_Pictographic), ('\u{1f10d}',
+ '\u{1f10f}', GC_Extended_Pictographic), ('\u{1f12f}', '\u{1f12f}',
+ GC_Extended_Pictographic), ('\u{1f16c}', '\u{1f171}', GC_Extended_Pictographic),
+ ('\u{1f17e}', '\u{1f17f}', GC_Extended_Pictographic), ('\u{1f18e}', '\u{1f18e}',
+ GC_Extended_Pictographic), ('\u{1f191}', '\u{1f19a}', GC_Extended_Pictographic),
+ ('\u{1f1ad}', '\u{1f1e5}', GC_Extended_Pictographic), ('\u{1f1e6}', '\u{1f1ff}',
+ GC_Regional_Indicator), ('\u{1f201}', '\u{1f20f}', GC_Extended_Pictographic), ('\u{1f21a}',
+ '\u{1f21a}', GC_Extended_Pictographic), ('\u{1f22f}', '\u{1f22f}',
+ GC_Extended_Pictographic), ('\u{1f232}', '\u{1f23a}', GC_Extended_Pictographic),
+ ('\u{1f23c}', '\u{1f23f}', GC_Extended_Pictographic), ('\u{1f249}', '\u{1f3fa}',
+ GC_Extended_Pictographic), ('\u{1f3fb}', '\u{1f3ff}', GC_Extend), ('\u{1f400}', '\u{1f53d}',
+ GC_Extended_Pictographic), ('\u{1f546}', '\u{1f64f}', GC_Extended_Pictographic),
+ ('\u{1f680}', '\u{1f6ff}', GC_Extended_Pictographic), ('\u{1f774}', '\u{1f77f}',
+ GC_Extended_Pictographic), ('\u{1f7d5}', '\u{1f7ff}', GC_Extended_Pictographic),
+ ('\u{1f80c}', '\u{1f80f}', GC_Extended_Pictographic), ('\u{1f848}', '\u{1f84f}',
+ GC_Extended_Pictographic), ('\u{1f85a}', '\u{1f85f}', GC_Extended_Pictographic),
+ ('\u{1f888}', '\u{1f88f}', GC_Extended_Pictographic), ('\u{1f8ae}', '\u{1f8ff}',
+ GC_Extended_Pictographic), ('\u{1f90c}', '\u{1f93a}', GC_Extended_Pictographic),
+ ('\u{1f93c}', '\u{1f945}', GC_Extended_Pictographic), ('\u{1f947}', '\u{1faff}',
+ GC_Extended_Pictographic), ('\u{1fc00}', '\u{1fffd}', GC_Extended_Pictographic),
+ ('\u{e0000}', '\u{e001f}', GC_Control), ('\u{e0020}', '\u{e007f}', GC_Extend), ('\u{e0080}',
+ '\u{e00ff}', GC_Control), ('\u{e0100}', '\u{e01ef}', GC_Extend), ('\u{e01f0}', '\u{e0fff}',
+ GC_Control)
];
}
@@ -1146,171 +1159,171 @@ pub mod word {
'\u{cc8}', WC_Extend), ('\u{cca}', '\u{ccd}', WC_Extend), ('\u{cd5}', '\u{cd6}', WC_Extend),
('\u{cdd}', '\u{cde}', WC_ALetter), ('\u{ce0}', '\u{ce1}', WC_ALetter), ('\u{ce2}',
'\u{ce3}', WC_Extend), ('\u{ce6}', '\u{cef}', WC_Numeric), ('\u{cf1}', '\u{cf2}',
- WC_ALetter), ('\u{d00}', '\u{d03}', WC_Extend), ('\u{d04}', '\u{d0c}', WC_ALetter),
- ('\u{d0e}', '\u{d10}', WC_ALetter), ('\u{d12}', '\u{d3a}', WC_ALetter), ('\u{d3b}',
- '\u{d3c}', WC_Extend), ('\u{d3d}', '\u{d3d}', WC_ALetter), ('\u{d3e}', '\u{d44}',
- WC_Extend), ('\u{d46}', '\u{d48}', WC_Extend), ('\u{d4a}', '\u{d4d}', WC_Extend),
- ('\u{d4e}', '\u{d4e}', WC_ALetter), ('\u{d54}', '\u{d56}', WC_ALetter), ('\u{d57}',
- '\u{d57}', WC_Extend), ('\u{d5f}', '\u{d61}', WC_ALetter), ('\u{d62}', '\u{d63}',
- WC_Extend), ('\u{d66}', '\u{d6f}', WC_Numeric), ('\u{d7a}', '\u{d7f}', WC_ALetter),
- ('\u{d81}', '\u{d83}', WC_Extend), ('\u{d85}', '\u{d96}', WC_ALetter), ('\u{d9a}',
- '\u{db1}', WC_ALetter), ('\u{db3}', '\u{dbb}', WC_ALetter), ('\u{dbd}', '\u{dbd}',
- WC_ALetter), ('\u{dc0}', '\u{dc6}', WC_ALetter), ('\u{dca}', '\u{dca}', WC_Extend),
- ('\u{dcf}', '\u{dd4}', WC_Extend), ('\u{dd6}', '\u{dd6}', WC_Extend), ('\u{dd8}', '\u{ddf}',
- WC_Extend), ('\u{de6}', '\u{def}', WC_Numeric), ('\u{df2}', '\u{df3}', WC_Extend),
- ('\u{e31}', '\u{e31}', WC_Extend), ('\u{e34}', '\u{e3a}', WC_Extend), ('\u{e47}', '\u{e4e}',
- WC_Extend), ('\u{e50}', '\u{e59}', WC_Numeric), ('\u{eb1}', '\u{eb1}', WC_Extend),
- ('\u{eb4}', '\u{ebc}', WC_Extend), ('\u{ec8}', '\u{ecd}', WC_Extend), ('\u{ed0}', '\u{ed9}',
- WC_Numeric), ('\u{f00}', '\u{f00}', WC_ALetter), ('\u{f18}', '\u{f19}', WC_Extend),
- ('\u{f20}', '\u{f29}', WC_Numeric), ('\u{f35}', '\u{f35}', WC_Extend), ('\u{f37}',
- '\u{f37}', WC_Extend), ('\u{f39}', '\u{f39}', WC_Extend), ('\u{f3e}', '\u{f3f}', WC_Extend),
- ('\u{f40}', '\u{f47}', WC_ALetter), ('\u{f49}', '\u{f6c}', WC_ALetter), ('\u{f71}',
- '\u{f84}', WC_Extend), ('\u{f86}', '\u{f87}', WC_Extend), ('\u{f88}', '\u{f8c}',
- WC_ALetter), ('\u{f8d}', '\u{f97}', WC_Extend), ('\u{f99}', '\u{fbc}', WC_Extend),
- ('\u{fc6}', '\u{fc6}', WC_Extend), ('\u{102b}', '\u{103e}', WC_Extend), ('\u{1040}',
- '\u{1049}', WC_Numeric), ('\u{1056}', '\u{1059}', WC_Extend), ('\u{105e}', '\u{1060}',
- WC_Extend), ('\u{1062}', '\u{1064}', WC_Extend), ('\u{1067}', '\u{106d}', WC_Extend),
- ('\u{1071}', '\u{1074}', WC_Extend), ('\u{1082}', '\u{108d}', WC_Extend), ('\u{108f}',
- '\u{108f}', WC_Extend), ('\u{1090}', '\u{1099}', WC_Numeric), ('\u{109a}', '\u{109d}',
- WC_Extend), ('\u{10a0}', '\u{10c5}', WC_ALetter), ('\u{10c7}', '\u{10c7}', WC_ALetter),
- ('\u{10cd}', '\u{10cd}', WC_ALetter), ('\u{10d0}', '\u{10fa}', WC_ALetter), ('\u{10fc}',
- '\u{1248}', WC_ALetter), ('\u{124a}', '\u{124d}', WC_ALetter), ('\u{1250}', '\u{1256}',
- WC_ALetter), ('\u{1258}', '\u{1258}', WC_ALetter), ('\u{125a}', '\u{125d}', WC_ALetter),
- ('\u{1260}', '\u{1288}', WC_ALetter), ('\u{128a}', '\u{128d}', WC_ALetter), ('\u{1290}',
- '\u{12b0}', WC_ALetter), ('\u{12b2}', '\u{12b5}', WC_ALetter), ('\u{12b8}', '\u{12be}',
- WC_ALetter), ('\u{12c0}', '\u{12c0}', WC_ALetter), ('\u{12c2}', '\u{12c5}', WC_ALetter),
- ('\u{12c8}', '\u{12d6}', WC_ALetter), ('\u{12d8}', '\u{1310}', WC_ALetter), ('\u{1312}',
- '\u{1315}', WC_ALetter), ('\u{1318}', '\u{135a}', WC_ALetter), ('\u{135d}', '\u{135f}',
- WC_Extend), ('\u{1380}', '\u{138f}', WC_ALetter), ('\u{13a0}', '\u{13f5}', WC_ALetter),
- ('\u{13f8}', '\u{13fd}', WC_ALetter), ('\u{1401}', '\u{166c}', WC_ALetter), ('\u{166f}',
- '\u{167f}', WC_ALetter), ('\u{1680}', '\u{1680}', WC_WSegSpace), ('\u{1681}', '\u{169a}',
- WC_ALetter), ('\u{16a0}', '\u{16ea}', WC_ALetter), ('\u{16ee}', '\u{16f8}', WC_ALetter),
- ('\u{1700}', '\u{1711}', WC_ALetter), ('\u{1712}', '\u{1715}', WC_Extend), ('\u{171f}',
- '\u{1731}', WC_ALetter), ('\u{1732}', '\u{1734}', WC_Extend), ('\u{1740}', '\u{1751}',
- WC_ALetter), ('\u{1752}', '\u{1753}', WC_Extend), ('\u{1760}', '\u{176c}', WC_ALetter),
- ('\u{176e}', '\u{1770}', WC_ALetter), ('\u{1772}', '\u{1773}', WC_Extend), ('\u{17b4}',
- '\u{17d3}', WC_Extend), ('\u{17dd}', '\u{17dd}', WC_Extend), ('\u{17e0}', '\u{17e9}',
- WC_Numeric), ('\u{180b}', '\u{180d}', WC_Extend), ('\u{180e}', '\u{180e}', WC_Format),
- ('\u{180f}', '\u{180f}', WC_Extend), ('\u{1810}', '\u{1819}', WC_Numeric), ('\u{1820}',
- '\u{1878}', WC_ALetter), ('\u{1880}', '\u{1884}', WC_ALetter), ('\u{1885}', '\u{1886}',
- WC_Extend), ('\u{1887}', '\u{18a8}', WC_ALetter), ('\u{18a9}', '\u{18a9}', WC_Extend),
- ('\u{18aa}', '\u{18aa}', WC_ALetter), ('\u{18b0}', '\u{18f5}', WC_ALetter), ('\u{1900}',
- '\u{191e}', WC_ALetter), ('\u{1920}', '\u{192b}', WC_Extend), ('\u{1930}', '\u{193b}',
- WC_Extend), ('\u{1946}', '\u{194f}', WC_Numeric), ('\u{19d0}', '\u{19d9}', WC_Numeric),
- ('\u{1a00}', '\u{1a16}', WC_ALetter), ('\u{1a17}', '\u{1a1b}', WC_Extend), ('\u{1a55}',
- '\u{1a5e}', WC_Extend), ('\u{1a60}', '\u{1a7c}', WC_Extend), ('\u{1a7f}', '\u{1a7f}',
- WC_Extend), ('\u{1a80}', '\u{1a89}', WC_Numeric), ('\u{1a90}', '\u{1a99}', WC_Numeric),
- ('\u{1ab0}', '\u{1ace}', WC_Extend), ('\u{1b00}', '\u{1b04}', WC_Extend), ('\u{1b05}',
- '\u{1b33}', WC_ALetter), ('\u{1b34}', '\u{1b44}', WC_Extend), ('\u{1b45}', '\u{1b4c}',
- WC_ALetter), ('\u{1b50}', '\u{1b59}', WC_Numeric), ('\u{1b6b}', '\u{1b73}', WC_Extend),
- ('\u{1b80}', '\u{1b82}', WC_Extend), ('\u{1b83}', '\u{1ba0}', WC_ALetter), ('\u{1ba1}',
- '\u{1bad}', WC_Extend), ('\u{1bae}', '\u{1baf}', WC_ALetter), ('\u{1bb0}', '\u{1bb9}',
- WC_Numeric), ('\u{1bba}', '\u{1be5}', WC_ALetter), ('\u{1be6}', '\u{1bf3}', WC_Extend),
- ('\u{1c00}', '\u{1c23}', WC_ALetter), ('\u{1c24}', '\u{1c37}', WC_Extend), ('\u{1c40}',
- '\u{1c49}', WC_Numeric), ('\u{1c4d}', '\u{1c4f}', WC_ALetter), ('\u{1c50}', '\u{1c59}',
- WC_Numeric), ('\u{1c5a}', '\u{1c7d}', WC_ALetter), ('\u{1c80}', '\u{1c88}', WC_ALetter),
- ('\u{1c90}', '\u{1cba}', WC_ALetter), ('\u{1cbd}', '\u{1cbf}', WC_ALetter), ('\u{1cd0}',
- '\u{1cd2}', WC_Extend), ('\u{1cd4}', '\u{1ce8}', WC_Extend), ('\u{1ce9}', '\u{1cec}',
- WC_ALetter), ('\u{1ced}', '\u{1ced}', WC_Extend), ('\u{1cee}', '\u{1cf3}', WC_ALetter),
- ('\u{1cf4}', '\u{1cf4}', WC_Extend), ('\u{1cf5}', '\u{1cf6}', WC_ALetter), ('\u{1cf7}',
- '\u{1cf9}', WC_Extend), ('\u{1cfa}', '\u{1cfa}', WC_ALetter), ('\u{1d00}', '\u{1dbf}',
- WC_ALetter), ('\u{1dc0}', '\u{1dff}', WC_Extend), ('\u{1e00}', '\u{1f15}', WC_ALetter),
- ('\u{1f18}', '\u{1f1d}', WC_ALetter), ('\u{1f20}', '\u{1f45}', WC_ALetter), ('\u{1f48}',
- '\u{1f4d}', WC_ALetter), ('\u{1f50}', '\u{1f57}', WC_ALetter), ('\u{1f59}', '\u{1f59}',
- WC_ALetter), ('\u{1f5b}', '\u{1f5b}', WC_ALetter), ('\u{1f5d}', '\u{1f5d}', WC_ALetter),
- ('\u{1f5f}', '\u{1f7d}', WC_ALetter), ('\u{1f80}', '\u{1fb4}', WC_ALetter), ('\u{1fb6}',
- '\u{1fbc}', WC_ALetter), ('\u{1fbe}', '\u{1fbe}', WC_ALetter), ('\u{1fc2}', '\u{1fc4}',
- WC_ALetter), ('\u{1fc6}', '\u{1fcc}', WC_ALetter), ('\u{1fd0}', '\u{1fd3}', WC_ALetter),
- ('\u{1fd6}', '\u{1fdb}', WC_ALetter), ('\u{1fe0}', '\u{1fec}', WC_ALetter), ('\u{1ff2}',
- '\u{1ff4}', WC_ALetter), ('\u{1ff6}', '\u{1ffc}', WC_ALetter), ('\u{2000}', '\u{2006}',
- WC_WSegSpace), ('\u{2008}', '\u{200a}', WC_WSegSpace), ('\u{200c}', '\u{200c}', WC_Extend),
- ('\u{200d}', '\u{200d}', WC_ZWJ), ('\u{200e}', '\u{200f}', WC_Format), ('\u{2018}',
- '\u{2019}', WC_MidNumLet), ('\u{2024}', '\u{2024}', WC_MidNumLet), ('\u{2027}', '\u{2027}',
- WC_MidLetter), ('\u{2028}', '\u{2029}', WC_Newline), ('\u{202a}', '\u{202e}', WC_Format),
- ('\u{202f}', '\u{202f}', WC_ExtendNumLet), ('\u{203f}', '\u{2040}', WC_ExtendNumLet),
- ('\u{2044}', '\u{2044}', WC_MidNum), ('\u{2054}', '\u{2054}', WC_ExtendNumLet), ('\u{205f}',
- '\u{205f}', WC_WSegSpace), ('\u{2060}', '\u{2064}', WC_Format), ('\u{2066}', '\u{206f}',
- WC_Format), ('\u{2071}', '\u{2071}', WC_ALetter), ('\u{207f}', '\u{207f}', WC_ALetter),
- ('\u{2090}', '\u{209c}', WC_ALetter), ('\u{20d0}', '\u{20f0}', WC_Extend), ('\u{2102}',
- '\u{2102}', WC_ALetter), ('\u{2107}', '\u{2107}', WC_ALetter), ('\u{210a}', '\u{2113}',
- WC_ALetter), ('\u{2115}', '\u{2115}', WC_ALetter), ('\u{2119}', '\u{211d}', WC_ALetter),
- ('\u{2124}', '\u{2124}', WC_ALetter), ('\u{2126}', '\u{2126}', WC_ALetter), ('\u{2128}',
- '\u{2128}', WC_ALetter), ('\u{212a}', '\u{212d}', WC_ALetter), ('\u{212f}', '\u{2139}',
- WC_ALetter), ('\u{213c}', '\u{213f}', WC_ALetter), ('\u{2145}', '\u{2149}', WC_ALetter),
- ('\u{214e}', '\u{214e}', WC_ALetter), ('\u{2160}', '\u{2188}', WC_ALetter), ('\u{24b6}',
- '\u{24e9}', WC_ALetter), ('\u{2c00}', '\u{2ce4}', WC_ALetter), ('\u{2ceb}', '\u{2cee}',
- WC_ALetter), ('\u{2cef}', '\u{2cf1}', WC_Extend), ('\u{2cf2}', '\u{2cf3}', WC_ALetter),
- ('\u{2d00}', '\u{2d25}', WC_ALetter), ('\u{2d27}', '\u{2d27}', WC_ALetter), ('\u{2d2d}',
- '\u{2d2d}', WC_ALetter), ('\u{2d30}', '\u{2d67}', WC_ALetter), ('\u{2d6f}', '\u{2d6f}',
- WC_ALetter), ('\u{2d7f}', '\u{2d7f}', WC_Extend), ('\u{2d80}', '\u{2d96}', WC_ALetter),
- ('\u{2da0}', '\u{2da6}', WC_ALetter), ('\u{2da8}', '\u{2dae}', WC_ALetter), ('\u{2db0}',
- '\u{2db6}', WC_ALetter), ('\u{2db8}', '\u{2dbe}', WC_ALetter), ('\u{2dc0}', '\u{2dc6}',
- WC_ALetter), ('\u{2dc8}', '\u{2dce}', WC_ALetter), ('\u{2dd0}', '\u{2dd6}', WC_ALetter),
- ('\u{2dd8}', '\u{2dde}', WC_ALetter), ('\u{2de0}', '\u{2dff}', WC_Extend), ('\u{2e2f}',
- '\u{2e2f}', WC_ALetter), ('\u{3000}', '\u{3000}', WC_WSegSpace), ('\u{3005}', '\u{3005}',
- WC_ALetter), ('\u{302a}', '\u{302f}', WC_Extend), ('\u{3031}', '\u{3035}', WC_Katakana),
- ('\u{303b}', '\u{303c}', WC_ALetter), ('\u{3099}', '\u{309a}', WC_Extend), ('\u{309b}',
- '\u{309c}', WC_Katakana), ('\u{30a0}', '\u{30fa}', WC_Katakana), ('\u{30fc}', '\u{30ff}',
- WC_Katakana), ('\u{3105}', '\u{312f}', WC_ALetter), ('\u{3131}', '\u{318e}', WC_ALetter),
- ('\u{31a0}', '\u{31bf}', WC_ALetter), ('\u{31f0}', '\u{31ff}', WC_Katakana), ('\u{32d0}',
- '\u{32fe}', WC_Katakana), ('\u{3300}', '\u{3357}', WC_Katakana), ('\u{a000}', '\u{a48c}',
- WC_ALetter), ('\u{a4d0}', '\u{a4fd}', WC_ALetter), ('\u{a500}', '\u{a60c}', WC_ALetter),
- ('\u{a610}', '\u{a61f}', WC_ALetter), ('\u{a620}', '\u{a629}', WC_Numeric), ('\u{a62a}',
- '\u{a62b}', WC_ALetter), ('\u{a640}', '\u{a66e}', WC_ALetter), ('\u{a66f}', '\u{a672}',
- WC_Extend), ('\u{a674}', '\u{a67d}', WC_Extend), ('\u{a67f}', '\u{a69d}', WC_ALetter),
- ('\u{a69e}', '\u{a69f}', WC_Extend), ('\u{a6a0}', '\u{a6ef}', WC_ALetter), ('\u{a6f0}',
- '\u{a6f1}', WC_Extend), ('\u{a708}', '\u{a7ca}', WC_ALetter), ('\u{a7d0}', '\u{a7d1}',
- WC_ALetter), ('\u{a7d3}', '\u{a7d3}', WC_ALetter), ('\u{a7d5}', '\u{a7d9}', WC_ALetter),
- ('\u{a7f2}', '\u{a801}', WC_ALetter), ('\u{a802}', '\u{a802}', WC_Extend), ('\u{a803}',
- '\u{a805}', WC_ALetter), ('\u{a806}', '\u{a806}', WC_Extend), ('\u{a807}', '\u{a80a}',
- WC_ALetter), ('\u{a80b}', '\u{a80b}', WC_Extend), ('\u{a80c}', '\u{a822}', WC_ALetter),
- ('\u{a823}', '\u{a827}', WC_Extend), ('\u{a82c}', '\u{a82c}', WC_Extend), ('\u{a840}',
- '\u{a873}', WC_ALetter), ('\u{a880}', '\u{a881}', WC_Extend), ('\u{a882}', '\u{a8b3}',
- WC_ALetter), ('\u{a8b4}', '\u{a8c5}', WC_Extend), ('\u{a8d0}', '\u{a8d9}', WC_Numeric),
- ('\u{a8e0}', '\u{a8f1}', WC_Extend), ('\u{a8f2}', '\u{a8f7}', WC_ALetter), ('\u{a8fb}',
- '\u{a8fb}', WC_ALetter), ('\u{a8fd}', '\u{a8fe}', WC_ALetter), ('\u{a8ff}', '\u{a8ff}',
- WC_Extend), ('\u{a900}', '\u{a909}', WC_Numeric), ('\u{a90a}', '\u{a925}', WC_ALetter),
- ('\u{a926}', '\u{a92d}', WC_Extend), ('\u{a930}', '\u{a946}', WC_ALetter), ('\u{a947}',
- '\u{a953}', WC_Extend), ('\u{a960}', '\u{a97c}', WC_ALetter), ('\u{a980}', '\u{a983}',
- WC_Extend), ('\u{a984}', '\u{a9b2}', WC_ALetter), ('\u{a9b3}', '\u{a9c0}', WC_Extend),
- ('\u{a9cf}', '\u{a9cf}', WC_ALetter), ('\u{a9d0}', '\u{a9d9}', WC_Numeric), ('\u{a9e5}',
- '\u{a9e5}', WC_Extend), ('\u{a9f0}', '\u{a9f9}', WC_Numeric), ('\u{aa00}', '\u{aa28}',
- WC_ALetter), ('\u{aa29}', '\u{aa36}', WC_Extend), ('\u{aa40}', '\u{aa42}', WC_ALetter),
- ('\u{aa43}', '\u{aa43}', WC_Extend), ('\u{aa44}', '\u{aa4b}', WC_ALetter), ('\u{aa4c}',
- '\u{aa4d}', WC_Extend), ('\u{aa50}', '\u{aa59}', WC_Numeric), ('\u{aa7b}', '\u{aa7d}',
- WC_Extend), ('\u{aab0}', '\u{aab0}', WC_Extend), ('\u{aab2}', '\u{aab4}', WC_Extend),
- ('\u{aab7}', '\u{aab8}', WC_Extend), ('\u{aabe}', '\u{aabf}', WC_Extend), ('\u{aac1}',
- '\u{aac1}', WC_Extend), ('\u{aae0}', '\u{aaea}', WC_ALetter), ('\u{aaeb}', '\u{aaef}',
- WC_Extend), ('\u{aaf2}', '\u{aaf4}', WC_ALetter), ('\u{aaf5}', '\u{aaf6}', WC_Extend),
- ('\u{ab01}', '\u{ab06}', WC_ALetter), ('\u{ab09}', '\u{ab0e}', WC_ALetter), ('\u{ab11}',
- '\u{ab16}', WC_ALetter), ('\u{ab20}', '\u{ab26}', WC_ALetter), ('\u{ab28}', '\u{ab2e}',
- WC_ALetter), ('\u{ab30}', '\u{ab69}', WC_ALetter), ('\u{ab70}', '\u{abe2}', WC_ALetter),
- ('\u{abe3}', '\u{abea}', WC_Extend), ('\u{abec}', '\u{abed}', WC_Extend), ('\u{abf0}',
- '\u{abf9}', WC_Numeric), ('\u{ac00}', '\u{d7a3}', WC_ALetter), ('\u{d7b0}', '\u{d7c6}',
- WC_ALetter), ('\u{d7cb}', '\u{d7fb}', WC_ALetter), ('\u{fb00}', '\u{fb06}', WC_ALetter),
- ('\u{fb13}', '\u{fb17}', WC_ALetter), ('\u{fb1d}', '\u{fb1d}', WC_Hebrew_Letter),
- ('\u{fb1e}', '\u{fb1e}', WC_Extend), ('\u{fb1f}', '\u{fb28}', WC_Hebrew_Letter),
- ('\u{fb2a}', '\u{fb36}', WC_Hebrew_Letter), ('\u{fb38}', '\u{fb3c}', WC_Hebrew_Letter),
- ('\u{fb3e}', '\u{fb3e}', WC_Hebrew_Letter), ('\u{fb40}', '\u{fb41}', WC_Hebrew_Letter),
- ('\u{fb43}', '\u{fb44}', WC_Hebrew_Letter), ('\u{fb46}', '\u{fb4f}', WC_Hebrew_Letter),
- ('\u{fb50}', '\u{fbb1}', WC_ALetter), ('\u{fbd3}', '\u{fd3d}', WC_ALetter), ('\u{fd50}',
- '\u{fd8f}', WC_ALetter), ('\u{fd92}', '\u{fdc7}', WC_ALetter), ('\u{fdf0}', '\u{fdfb}',
- WC_ALetter), ('\u{fe00}', '\u{fe0f}', WC_Extend), ('\u{fe10}', '\u{fe10}', WC_MidNum),
- ('\u{fe13}', '\u{fe13}', WC_MidLetter), ('\u{fe14}', '\u{fe14}', WC_MidNum), ('\u{fe20}',
- '\u{fe2f}', WC_Extend), ('\u{fe33}', '\u{fe34}', WC_ExtendNumLet), ('\u{fe4d}', '\u{fe4f}',
- WC_ExtendNumLet), ('\u{fe50}', '\u{fe50}', WC_MidNum), ('\u{fe52}', '\u{fe52}',
- WC_MidNumLet), ('\u{fe54}', '\u{fe54}', WC_MidNum), ('\u{fe55}', '\u{fe55}', WC_MidLetter),
- ('\u{fe70}', '\u{fe74}', WC_ALetter), ('\u{fe76}', '\u{fefc}', WC_ALetter), ('\u{feff}',
- '\u{feff}', WC_Format), ('\u{ff07}', '\u{ff07}', WC_MidNumLet), ('\u{ff0c}', '\u{ff0c}',
- WC_MidNum), ('\u{ff0e}', '\u{ff0e}', WC_MidNumLet), ('\u{ff10}', '\u{ff19}', WC_Numeric),
- ('\u{ff1a}', '\u{ff1a}', WC_MidLetter), ('\u{ff1b}', '\u{ff1b}', WC_MidNum), ('\u{ff21}',
- '\u{ff3a}', WC_ALetter), ('\u{ff3f}', '\u{ff3f}', WC_ExtendNumLet), ('\u{ff41}', '\u{ff5a}',
- WC_ALetter), ('\u{ff66}', '\u{ff9d}', WC_Katakana), ('\u{ff9e}', '\u{ff9f}', WC_Extend),
- ('\u{ffa0}', '\u{ffbe}', WC_ALetter), ('\u{ffc2}', '\u{ffc7}', WC_ALetter), ('\u{ffca}',
- '\u{ffcf}', WC_ALetter), ('\u{ffd2}', '\u{ffd7}', WC_ALetter), ('\u{ffda}', '\u{ffdc}',
- WC_ALetter), ('\u{fff9}', '\u{fffb}', WC_Format), ('\u{10000}', '\u{1000b}', WC_ALetter),
- ('\u{1000d}', '\u{10026}', WC_ALetter), ('\u{10028}', '\u{1003a}', WC_ALetter),
- ('\u{1003c}', '\u{1003d}', WC_ALetter), ('\u{1003f}', '\u{1004d}', WC_ALetter),
+ WC_ALetter), ('\u{cf3}', '\u{cf3}', WC_Extend), ('\u{d00}', '\u{d03}', WC_Extend),
+ ('\u{d04}', '\u{d0c}', WC_ALetter), ('\u{d0e}', '\u{d10}', WC_ALetter), ('\u{d12}',
+ '\u{d3a}', WC_ALetter), ('\u{d3b}', '\u{d3c}', WC_Extend), ('\u{d3d}', '\u{d3d}',
+ WC_ALetter), ('\u{d3e}', '\u{d44}', WC_Extend), ('\u{d46}', '\u{d48}', WC_Extend),
+ ('\u{d4a}', '\u{d4d}', WC_Extend), ('\u{d4e}', '\u{d4e}', WC_ALetter), ('\u{d54}',
+ '\u{d56}', WC_ALetter), ('\u{d57}', '\u{d57}', WC_Extend), ('\u{d5f}', '\u{d61}',
+ WC_ALetter), ('\u{d62}', '\u{d63}', WC_Extend), ('\u{d66}', '\u{d6f}', WC_Numeric),
+ ('\u{d7a}', '\u{d7f}', WC_ALetter), ('\u{d81}', '\u{d83}', WC_Extend), ('\u{d85}',
+ '\u{d96}', WC_ALetter), ('\u{d9a}', '\u{db1}', WC_ALetter), ('\u{db3}', '\u{dbb}',
+ WC_ALetter), ('\u{dbd}', '\u{dbd}', WC_ALetter), ('\u{dc0}', '\u{dc6}', WC_ALetter),
+ ('\u{dca}', '\u{dca}', WC_Extend), ('\u{dcf}', '\u{dd4}', WC_Extend), ('\u{dd6}', '\u{dd6}',
+ WC_Extend), ('\u{dd8}', '\u{ddf}', WC_Extend), ('\u{de6}', '\u{def}', WC_Numeric),
+ ('\u{df2}', '\u{df3}', WC_Extend), ('\u{e31}', '\u{e31}', WC_Extend), ('\u{e34}', '\u{e3a}',
+ WC_Extend), ('\u{e47}', '\u{e4e}', WC_Extend), ('\u{e50}', '\u{e59}', WC_Numeric),
+ ('\u{eb1}', '\u{eb1}', WC_Extend), ('\u{eb4}', '\u{ebc}', WC_Extend), ('\u{ec8}', '\u{ece}',
+ WC_Extend), ('\u{ed0}', '\u{ed9}', WC_Numeric), ('\u{f00}', '\u{f00}', WC_ALetter),
+ ('\u{f18}', '\u{f19}', WC_Extend), ('\u{f20}', '\u{f29}', WC_Numeric), ('\u{f35}',
+ '\u{f35}', WC_Extend), ('\u{f37}', '\u{f37}', WC_Extend), ('\u{f39}', '\u{f39}', WC_Extend),
+ ('\u{f3e}', '\u{f3f}', WC_Extend), ('\u{f40}', '\u{f47}', WC_ALetter), ('\u{f49}',
+ '\u{f6c}', WC_ALetter), ('\u{f71}', '\u{f84}', WC_Extend), ('\u{f86}', '\u{f87}',
+ WC_Extend), ('\u{f88}', '\u{f8c}', WC_ALetter), ('\u{f8d}', '\u{f97}', WC_Extend),
+ ('\u{f99}', '\u{fbc}', WC_Extend), ('\u{fc6}', '\u{fc6}', WC_Extend), ('\u{102b}',
+ '\u{103e}', WC_Extend), ('\u{1040}', '\u{1049}', WC_Numeric), ('\u{1056}', '\u{1059}',
+ WC_Extend), ('\u{105e}', '\u{1060}', WC_Extend), ('\u{1062}', '\u{1064}', WC_Extend),
+ ('\u{1067}', '\u{106d}', WC_Extend), ('\u{1071}', '\u{1074}', WC_Extend), ('\u{1082}',
+ '\u{108d}', WC_Extend), ('\u{108f}', '\u{108f}', WC_Extend), ('\u{1090}', '\u{1099}',
+ WC_Numeric), ('\u{109a}', '\u{109d}', WC_Extend), ('\u{10a0}', '\u{10c5}', WC_ALetter),
+ ('\u{10c7}', '\u{10c7}', WC_ALetter), ('\u{10cd}', '\u{10cd}', WC_ALetter), ('\u{10d0}',
+ '\u{10fa}', WC_ALetter), ('\u{10fc}', '\u{1248}', WC_ALetter), ('\u{124a}', '\u{124d}',
+ WC_ALetter), ('\u{1250}', '\u{1256}', WC_ALetter), ('\u{1258}', '\u{1258}', WC_ALetter),
+ ('\u{125a}', '\u{125d}', WC_ALetter), ('\u{1260}', '\u{1288}', WC_ALetter), ('\u{128a}',
+ '\u{128d}', WC_ALetter), ('\u{1290}', '\u{12b0}', WC_ALetter), ('\u{12b2}', '\u{12b5}',
+ WC_ALetter), ('\u{12b8}', '\u{12be}', WC_ALetter), ('\u{12c0}', '\u{12c0}', WC_ALetter),
+ ('\u{12c2}', '\u{12c5}', WC_ALetter), ('\u{12c8}', '\u{12d6}', WC_ALetter), ('\u{12d8}',
+ '\u{1310}', WC_ALetter), ('\u{1312}', '\u{1315}', WC_ALetter), ('\u{1318}', '\u{135a}',
+ WC_ALetter), ('\u{135d}', '\u{135f}', WC_Extend), ('\u{1380}', '\u{138f}', WC_ALetter),
+ ('\u{13a0}', '\u{13f5}', WC_ALetter), ('\u{13f8}', '\u{13fd}', WC_ALetter), ('\u{1401}',
+ '\u{166c}', WC_ALetter), ('\u{166f}', '\u{167f}', WC_ALetter), ('\u{1680}', '\u{1680}',
+ WC_WSegSpace), ('\u{1681}', '\u{169a}', WC_ALetter), ('\u{16a0}', '\u{16ea}', WC_ALetter),
+ ('\u{16ee}', '\u{16f8}', WC_ALetter), ('\u{1700}', '\u{1711}', WC_ALetter), ('\u{1712}',
+ '\u{1715}', WC_Extend), ('\u{171f}', '\u{1731}', WC_ALetter), ('\u{1732}', '\u{1734}',
+ WC_Extend), ('\u{1740}', '\u{1751}', WC_ALetter), ('\u{1752}', '\u{1753}', WC_Extend),
+ ('\u{1760}', '\u{176c}', WC_ALetter), ('\u{176e}', '\u{1770}', WC_ALetter), ('\u{1772}',
+ '\u{1773}', WC_Extend), ('\u{17b4}', '\u{17d3}', WC_Extend), ('\u{17dd}', '\u{17dd}',
+ WC_Extend), ('\u{17e0}', '\u{17e9}', WC_Numeric), ('\u{180b}', '\u{180d}', WC_Extend),
+ ('\u{180e}', '\u{180e}', WC_Format), ('\u{180f}', '\u{180f}', WC_Extend), ('\u{1810}',
+ '\u{1819}', WC_Numeric), ('\u{1820}', '\u{1878}', WC_ALetter), ('\u{1880}', '\u{1884}',
+ WC_ALetter), ('\u{1885}', '\u{1886}', WC_Extend), ('\u{1887}', '\u{18a8}', WC_ALetter),
+ ('\u{18a9}', '\u{18a9}', WC_Extend), ('\u{18aa}', '\u{18aa}', WC_ALetter), ('\u{18b0}',
+ '\u{18f5}', WC_ALetter), ('\u{1900}', '\u{191e}', WC_ALetter), ('\u{1920}', '\u{192b}',
+ WC_Extend), ('\u{1930}', '\u{193b}', WC_Extend), ('\u{1946}', '\u{194f}', WC_Numeric),
+ ('\u{19d0}', '\u{19d9}', WC_Numeric), ('\u{1a00}', '\u{1a16}', WC_ALetter), ('\u{1a17}',
+ '\u{1a1b}', WC_Extend), ('\u{1a55}', '\u{1a5e}', WC_Extend), ('\u{1a60}', '\u{1a7c}',
+ WC_Extend), ('\u{1a7f}', '\u{1a7f}', WC_Extend), ('\u{1a80}', '\u{1a89}', WC_Numeric),
+ ('\u{1a90}', '\u{1a99}', WC_Numeric), ('\u{1ab0}', '\u{1ace}', WC_Extend), ('\u{1b00}',
+ '\u{1b04}', WC_Extend), ('\u{1b05}', '\u{1b33}', WC_ALetter), ('\u{1b34}', '\u{1b44}',
+ WC_Extend), ('\u{1b45}', '\u{1b4c}', WC_ALetter), ('\u{1b50}', '\u{1b59}', WC_Numeric),
+ ('\u{1b6b}', '\u{1b73}', WC_Extend), ('\u{1b80}', '\u{1b82}', WC_Extend), ('\u{1b83}',
+ '\u{1ba0}', WC_ALetter), ('\u{1ba1}', '\u{1bad}', WC_Extend), ('\u{1bae}', '\u{1baf}',
+ WC_ALetter), ('\u{1bb0}', '\u{1bb9}', WC_Numeric), ('\u{1bba}', '\u{1be5}', WC_ALetter),
+ ('\u{1be6}', '\u{1bf3}', WC_Extend), ('\u{1c00}', '\u{1c23}', WC_ALetter), ('\u{1c24}',
+ '\u{1c37}', WC_Extend), ('\u{1c40}', '\u{1c49}', WC_Numeric), ('\u{1c4d}', '\u{1c4f}',
+ WC_ALetter), ('\u{1c50}', '\u{1c59}', WC_Numeric), ('\u{1c5a}', '\u{1c7d}', WC_ALetter),
+ ('\u{1c80}', '\u{1c88}', WC_ALetter), ('\u{1c90}', '\u{1cba}', WC_ALetter), ('\u{1cbd}',
+ '\u{1cbf}', WC_ALetter), ('\u{1cd0}', '\u{1cd2}', WC_Extend), ('\u{1cd4}', '\u{1ce8}',
+ WC_Extend), ('\u{1ce9}', '\u{1cec}', WC_ALetter), ('\u{1ced}', '\u{1ced}', WC_Extend),
+ ('\u{1cee}', '\u{1cf3}', WC_ALetter), ('\u{1cf4}', '\u{1cf4}', WC_Extend), ('\u{1cf5}',
+ '\u{1cf6}', WC_ALetter), ('\u{1cf7}', '\u{1cf9}', WC_Extend), ('\u{1cfa}', '\u{1cfa}',
+ WC_ALetter), ('\u{1d00}', '\u{1dbf}', WC_ALetter), ('\u{1dc0}', '\u{1dff}', WC_Extend),
+ ('\u{1e00}', '\u{1f15}', WC_ALetter), ('\u{1f18}', '\u{1f1d}', WC_ALetter), ('\u{1f20}',
+ '\u{1f45}', WC_ALetter), ('\u{1f48}', '\u{1f4d}', WC_ALetter), ('\u{1f50}', '\u{1f57}',
+ WC_ALetter), ('\u{1f59}', '\u{1f59}', WC_ALetter), ('\u{1f5b}', '\u{1f5b}', WC_ALetter),
+ ('\u{1f5d}', '\u{1f5d}', WC_ALetter), ('\u{1f5f}', '\u{1f7d}', WC_ALetter), ('\u{1f80}',
+ '\u{1fb4}', WC_ALetter), ('\u{1fb6}', '\u{1fbc}', WC_ALetter), ('\u{1fbe}', '\u{1fbe}',
+ WC_ALetter), ('\u{1fc2}', '\u{1fc4}', WC_ALetter), ('\u{1fc6}', '\u{1fcc}', WC_ALetter),
+ ('\u{1fd0}', '\u{1fd3}', WC_ALetter), ('\u{1fd6}', '\u{1fdb}', WC_ALetter), ('\u{1fe0}',
+ '\u{1fec}', WC_ALetter), ('\u{1ff2}', '\u{1ff4}', WC_ALetter), ('\u{1ff6}', '\u{1ffc}',
+ WC_ALetter), ('\u{2000}', '\u{2006}', WC_WSegSpace), ('\u{2008}', '\u{200a}', WC_WSegSpace),
+ ('\u{200c}', '\u{200c}', WC_Extend), ('\u{200d}', '\u{200d}', WC_ZWJ), ('\u{200e}',
+ '\u{200f}', WC_Format), ('\u{2018}', '\u{2019}', WC_MidNumLet), ('\u{2024}', '\u{2024}',
+ WC_MidNumLet), ('\u{2027}', '\u{2027}', WC_MidLetter), ('\u{2028}', '\u{2029}', WC_Newline),
+ ('\u{202a}', '\u{202e}', WC_Format), ('\u{202f}', '\u{202f}', WC_ExtendNumLet), ('\u{203f}',
+ '\u{2040}', WC_ExtendNumLet), ('\u{2044}', '\u{2044}', WC_MidNum), ('\u{2054}', '\u{2054}',
+ WC_ExtendNumLet), ('\u{205f}', '\u{205f}', WC_WSegSpace), ('\u{2060}', '\u{2064}',
+ WC_Format), ('\u{2066}', '\u{206f}', WC_Format), ('\u{2071}', '\u{2071}', WC_ALetter),
+ ('\u{207f}', '\u{207f}', WC_ALetter), ('\u{2090}', '\u{209c}', WC_ALetter), ('\u{20d0}',
+ '\u{20f0}', WC_Extend), ('\u{2102}', '\u{2102}', WC_ALetter), ('\u{2107}', '\u{2107}',
+ WC_ALetter), ('\u{210a}', '\u{2113}', WC_ALetter), ('\u{2115}', '\u{2115}', WC_ALetter),
+ ('\u{2119}', '\u{211d}', WC_ALetter), ('\u{2124}', '\u{2124}', WC_ALetter), ('\u{2126}',
+ '\u{2126}', WC_ALetter), ('\u{2128}', '\u{2128}', WC_ALetter), ('\u{212a}', '\u{212d}',
+ WC_ALetter), ('\u{212f}', '\u{2139}', WC_ALetter), ('\u{213c}', '\u{213f}', WC_ALetter),
+ ('\u{2145}', '\u{2149}', WC_ALetter), ('\u{214e}', '\u{214e}', WC_ALetter), ('\u{2160}',
+ '\u{2188}', WC_ALetter), ('\u{24b6}', '\u{24e9}', WC_ALetter), ('\u{2c00}', '\u{2ce4}',
+ WC_ALetter), ('\u{2ceb}', '\u{2cee}', WC_ALetter), ('\u{2cef}', '\u{2cf1}', WC_Extend),
+ ('\u{2cf2}', '\u{2cf3}', WC_ALetter), ('\u{2d00}', '\u{2d25}', WC_ALetter), ('\u{2d27}',
+ '\u{2d27}', WC_ALetter), ('\u{2d2d}', '\u{2d2d}', WC_ALetter), ('\u{2d30}', '\u{2d67}',
+ WC_ALetter), ('\u{2d6f}', '\u{2d6f}', WC_ALetter), ('\u{2d7f}', '\u{2d7f}', WC_Extend),
+ ('\u{2d80}', '\u{2d96}', WC_ALetter), ('\u{2da0}', '\u{2da6}', WC_ALetter), ('\u{2da8}',
+ '\u{2dae}', WC_ALetter), ('\u{2db0}', '\u{2db6}', WC_ALetter), ('\u{2db8}', '\u{2dbe}',
+ WC_ALetter), ('\u{2dc0}', '\u{2dc6}', WC_ALetter), ('\u{2dc8}', '\u{2dce}', WC_ALetter),
+ ('\u{2dd0}', '\u{2dd6}', WC_ALetter), ('\u{2dd8}', '\u{2dde}', WC_ALetter), ('\u{2de0}',
+ '\u{2dff}', WC_Extend), ('\u{2e2f}', '\u{2e2f}', WC_ALetter), ('\u{3000}', '\u{3000}',
+ WC_WSegSpace), ('\u{3005}', '\u{3005}', WC_ALetter), ('\u{302a}', '\u{302f}', WC_Extend),
+ ('\u{3031}', '\u{3035}', WC_Katakana), ('\u{303b}', '\u{303c}', WC_ALetter), ('\u{3099}',
+ '\u{309a}', WC_Extend), ('\u{309b}', '\u{309c}', WC_Katakana), ('\u{30a0}', '\u{30fa}',
+ WC_Katakana), ('\u{30fc}', '\u{30ff}', WC_Katakana), ('\u{3105}', '\u{312f}', WC_ALetter),
+ ('\u{3131}', '\u{318e}', WC_ALetter), ('\u{31a0}', '\u{31bf}', WC_ALetter), ('\u{31f0}',
+ '\u{31ff}', WC_Katakana), ('\u{32d0}', '\u{32fe}', WC_Katakana), ('\u{3300}', '\u{3357}',
+ WC_Katakana), ('\u{a000}', '\u{a48c}', WC_ALetter), ('\u{a4d0}', '\u{a4fd}', WC_ALetter),
+ ('\u{a500}', '\u{a60c}', WC_ALetter), ('\u{a610}', '\u{a61f}', WC_ALetter), ('\u{a620}',
+ '\u{a629}', WC_Numeric), ('\u{a62a}', '\u{a62b}', WC_ALetter), ('\u{a640}', '\u{a66e}',
+ WC_ALetter), ('\u{a66f}', '\u{a672}', WC_Extend), ('\u{a674}', '\u{a67d}', WC_Extend),
+ ('\u{a67f}', '\u{a69d}', WC_ALetter), ('\u{a69e}', '\u{a69f}', WC_Extend), ('\u{a6a0}',
+ '\u{a6ef}', WC_ALetter), ('\u{a6f0}', '\u{a6f1}', WC_Extend), ('\u{a708}', '\u{a7ca}',
+ WC_ALetter), ('\u{a7d0}', '\u{a7d1}', WC_ALetter), ('\u{a7d3}', '\u{a7d3}', WC_ALetter),
+ ('\u{a7d5}', '\u{a7d9}', WC_ALetter), ('\u{a7f2}', '\u{a801}', WC_ALetter), ('\u{a802}',
+ '\u{a802}', WC_Extend), ('\u{a803}', '\u{a805}', WC_ALetter), ('\u{a806}', '\u{a806}',
+ WC_Extend), ('\u{a807}', '\u{a80a}', WC_ALetter), ('\u{a80b}', '\u{a80b}', WC_Extend),
+ ('\u{a80c}', '\u{a822}', WC_ALetter), ('\u{a823}', '\u{a827}', WC_Extend), ('\u{a82c}',
+ '\u{a82c}', WC_Extend), ('\u{a840}', '\u{a873}', WC_ALetter), ('\u{a880}', '\u{a881}',
+ WC_Extend), ('\u{a882}', '\u{a8b3}', WC_ALetter), ('\u{a8b4}', '\u{a8c5}', WC_Extend),
+ ('\u{a8d0}', '\u{a8d9}', WC_Numeric), ('\u{a8e0}', '\u{a8f1}', WC_Extend), ('\u{a8f2}',
+ '\u{a8f7}', WC_ALetter), ('\u{a8fb}', '\u{a8fb}', WC_ALetter), ('\u{a8fd}', '\u{a8fe}',
+ WC_ALetter), ('\u{a8ff}', '\u{a8ff}', WC_Extend), ('\u{a900}', '\u{a909}', WC_Numeric),
+ ('\u{a90a}', '\u{a925}', WC_ALetter), ('\u{a926}', '\u{a92d}', WC_Extend), ('\u{a930}',
+ '\u{a946}', WC_ALetter), ('\u{a947}', '\u{a953}', WC_Extend), ('\u{a960}', '\u{a97c}',
+ WC_ALetter), ('\u{a980}', '\u{a983}', WC_Extend), ('\u{a984}', '\u{a9b2}', WC_ALetter),
+ ('\u{a9b3}', '\u{a9c0}', WC_Extend), ('\u{a9cf}', '\u{a9cf}', WC_ALetter), ('\u{a9d0}',
+ '\u{a9d9}', WC_Numeric), ('\u{a9e5}', '\u{a9e5}', WC_Extend), ('\u{a9f0}', '\u{a9f9}',
+ WC_Numeric), ('\u{aa00}', '\u{aa28}', WC_ALetter), ('\u{aa29}', '\u{aa36}', WC_Extend),
+ ('\u{aa40}', '\u{aa42}', WC_ALetter), ('\u{aa43}', '\u{aa43}', WC_Extend), ('\u{aa44}',
+ '\u{aa4b}', WC_ALetter), ('\u{aa4c}', '\u{aa4d}', WC_Extend), ('\u{aa50}', '\u{aa59}',
+ WC_Numeric), ('\u{aa7b}', '\u{aa7d}', WC_Extend), ('\u{aab0}', '\u{aab0}', WC_Extend),
+ ('\u{aab2}', '\u{aab4}', WC_Extend), ('\u{aab7}', '\u{aab8}', WC_Extend), ('\u{aabe}',
+ '\u{aabf}', WC_Extend), ('\u{aac1}', '\u{aac1}', WC_Extend), ('\u{aae0}', '\u{aaea}',
+ WC_ALetter), ('\u{aaeb}', '\u{aaef}', WC_Extend), ('\u{aaf2}', '\u{aaf4}', WC_ALetter),
+ ('\u{aaf5}', '\u{aaf6}', WC_Extend), ('\u{ab01}', '\u{ab06}', WC_ALetter), ('\u{ab09}',
+ '\u{ab0e}', WC_ALetter), ('\u{ab11}', '\u{ab16}', WC_ALetter), ('\u{ab20}', '\u{ab26}',
+ WC_ALetter), ('\u{ab28}', '\u{ab2e}', WC_ALetter), ('\u{ab30}', '\u{ab69}', WC_ALetter),
+ ('\u{ab70}', '\u{abe2}', WC_ALetter), ('\u{abe3}', '\u{abea}', WC_Extend), ('\u{abec}',
+ '\u{abed}', WC_Extend), ('\u{abf0}', '\u{abf9}', WC_Numeric), ('\u{ac00}', '\u{d7a3}',
+ WC_ALetter), ('\u{d7b0}', '\u{d7c6}', WC_ALetter), ('\u{d7cb}', '\u{d7fb}', WC_ALetter),
+ ('\u{fb00}', '\u{fb06}', WC_ALetter), ('\u{fb13}', '\u{fb17}', WC_ALetter), ('\u{fb1d}',
+ '\u{fb1d}', WC_Hebrew_Letter), ('\u{fb1e}', '\u{fb1e}', WC_Extend), ('\u{fb1f}', '\u{fb28}',
+ WC_Hebrew_Letter), ('\u{fb2a}', '\u{fb36}', WC_Hebrew_Letter), ('\u{fb38}', '\u{fb3c}',
+ WC_Hebrew_Letter), ('\u{fb3e}', '\u{fb3e}', WC_Hebrew_Letter), ('\u{fb40}', '\u{fb41}',
+ WC_Hebrew_Letter), ('\u{fb43}', '\u{fb44}', WC_Hebrew_Letter), ('\u{fb46}', '\u{fb4f}',
+ WC_Hebrew_Letter), ('\u{fb50}', '\u{fbb1}', WC_ALetter), ('\u{fbd3}', '\u{fd3d}',
+ WC_ALetter), ('\u{fd50}', '\u{fd8f}', WC_ALetter), ('\u{fd92}', '\u{fdc7}', WC_ALetter),
+ ('\u{fdf0}', '\u{fdfb}', WC_ALetter), ('\u{fe00}', '\u{fe0f}', WC_Extend), ('\u{fe10}',
+ '\u{fe10}', WC_MidNum), ('\u{fe13}', '\u{fe13}', WC_MidLetter), ('\u{fe14}', '\u{fe14}',
+ WC_MidNum), ('\u{fe20}', '\u{fe2f}', WC_Extend), ('\u{fe33}', '\u{fe34}', WC_ExtendNumLet),
+ ('\u{fe4d}', '\u{fe4f}', WC_ExtendNumLet), ('\u{fe50}', '\u{fe50}', WC_MidNum), ('\u{fe52}',
+ '\u{fe52}', WC_MidNumLet), ('\u{fe54}', '\u{fe54}', WC_MidNum), ('\u{fe55}', '\u{fe55}',
+ WC_MidLetter), ('\u{fe70}', '\u{fe74}', WC_ALetter), ('\u{fe76}', '\u{fefc}', WC_ALetter),
+ ('\u{feff}', '\u{feff}', WC_Format), ('\u{ff07}', '\u{ff07}', WC_MidNumLet), ('\u{ff0c}',
+ '\u{ff0c}', WC_MidNum), ('\u{ff0e}', '\u{ff0e}', WC_MidNumLet), ('\u{ff10}', '\u{ff19}',
+ WC_Numeric), ('\u{ff1a}', '\u{ff1a}', WC_MidLetter), ('\u{ff1b}', '\u{ff1b}', WC_MidNum),
+ ('\u{ff21}', '\u{ff3a}', WC_ALetter), ('\u{ff3f}', '\u{ff3f}', WC_ExtendNumLet),
+ ('\u{ff41}', '\u{ff5a}', WC_ALetter), ('\u{ff66}', '\u{ff9d}', WC_Katakana), ('\u{ff9e}',
+ '\u{ff9f}', WC_Extend), ('\u{ffa0}', '\u{ffbe}', WC_ALetter), ('\u{ffc2}', '\u{ffc7}',
+ WC_ALetter), ('\u{ffca}', '\u{ffcf}', WC_ALetter), ('\u{ffd2}', '\u{ffd7}', WC_ALetter),
+ ('\u{ffda}', '\u{ffdc}', WC_ALetter), ('\u{fff9}', '\u{fffb}', WC_Format), ('\u{10000}',
+ '\u{1000b}', WC_ALetter), ('\u{1000d}', '\u{10026}', WC_ALetter), ('\u{10028}', '\u{1003a}',
+ WC_ALetter), ('\u{1003c}', '\u{1003d}', WC_ALetter), ('\u{1003f}', '\u{1004d}', WC_ALetter),
('\u{10050}', '\u{1005d}', WC_ALetter), ('\u{10080}', '\u{100fa}', WC_ALetter),
('\u{10140}', '\u{10174}', WC_ALetter), ('\u{101fd}', '\u{101fd}', WC_Extend), ('\u{10280}',
'\u{1029c}', WC_ALetter), ('\u{102a0}', '\u{102d0}', WC_ALetter), ('\u{102e0}', '\u{102e0}',
@@ -1346,53 +1359,55 @@ pub mod word {
('\u{10c80}', '\u{10cb2}', WC_ALetter), ('\u{10cc0}', '\u{10cf2}', WC_ALetter),
('\u{10d00}', '\u{10d23}', WC_ALetter), ('\u{10d24}', '\u{10d27}', WC_Extend), ('\u{10d30}',
'\u{10d39}', WC_Numeric), ('\u{10e80}', '\u{10ea9}', WC_ALetter), ('\u{10eab}', '\u{10eac}',
- WC_Extend), ('\u{10eb0}', '\u{10eb1}', WC_ALetter), ('\u{10f00}', '\u{10f1c}', WC_ALetter),
- ('\u{10f27}', '\u{10f27}', WC_ALetter), ('\u{10f30}', '\u{10f45}', WC_ALetter),
- ('\u{10f46}', '\u{10f50}', WC_Extend), ('\u{10f70}', '\u{10f81}', WC_ALetter), ('\u{10f82}',
- '\u{10f85}', WC_Extend), ('\u{10fb0}', '\u{10fc4}', WC_ALetter), ('\u{10fe0}', '\u{10ff6}',
- WC_ALetter), ('\u{11000}', '\u{11002}', WC_Extend), ('\u{11003}', '\u{11037}', WC_ALetter),
- ('\u{11038}', '\u{11046}', WC_Extend), ('\u{11066}', '\u{1106f}', WC_Numeric), ('\u{11070}',
- '\u{11070}', WC_Extend), ('\u{11071}', '\u{11072}', WC_ALetter), ('\u{11073}', '\u{11074}',
- WC_Extend), ('\u{11075}', '\u{11075}', WC_ALetter), ('\u{1107f}', '\u{11082}', WC_Extend),
- ('\u{11083}', '\u{110af}', WC_ALetter), ('\u{110b0}', '\u{110ba}', WC_Extend), ('\u{110bd}',
- '\u{110bd}', WC_Format), ('\u{110c2}', '\u{110c2}', WC_Extend), ('\u{110cd}', '\u{110cd}',
- WC_Format), ('\u{110d0}', '\u{110e8}', WC_ALetter), ('\u{110f0}', '\u{110f9}', WC_Numeric),
- ('\u{11100}', '\u{11102}', WC_Extend), ('\u{11103}', '\u{11126}', WC_ALetter), ('\u{11127}',
- '\u{11134}', WC_Extend), ('\u{11136}', '\u{1113f}', WC_Numeric), ('\u{11144}', '\u{11144}',
- WC_ALetter), ('\u{11145}', '\u{11146}', WC_Extend), ('\u{11147}', '\u{11147}', WC_ALetter),
- ('\u{11150}', '\u{11172}', WC_ALetter), ('\u{11173}', '\u{11173}', WC_Extend), ('\u{11176}',
- '\u{11176}', WC_ALetter), ('\u{11180}', '\u{11182}', WC_Extend), ('\u{11183}', '\u{111b2}',
- WC_ALetter), ('\u{111b3}', '\u{111c0}', WC_Extend), ('\u{111c1}', '\u{111c4}', WC_ALetter),
- ('\u{111c9}', '\u{111cc}', WC_Extend), ('\u{111ce}', '\u{111cf}', WC_Extend), ('\u{111d0}',
- '\u{111d9}', WC_Numeric), ('\u{111da}', '\u{111da}', WC_ALetter), ('\u{111dc}', '\u{111dc}',
- WC_ALetter), ('\u{11200}', '\u{11211}', WC_ALetter), ('\u{11213}', '\u{1122b}', WC_ALetter),
- ('\u{1122c}', '\u{11237}', WC_Extend), ('\u{1123e}', '\u{1123e}', WC_Extend), ('\u{11280}',
- '\u{11286}', WC_ALetter), ('\u{11288}', '\u{11288}', WC_ALetter), ('\u{1128a}', '\u{1128d}',
- WC_ALetter), ('\u{1128f}', '\u{1129d}', WC_ALetter), ('\u{1129f}', '\u{112a8}', WC_ALetter),
- ('\u{112b0}', '\u{112de}', WC_ALetter), ('\u{112df}', '\u{112ea}', WC_Extend), ('\u{112f0}',
- '\u{112f9}', WC_Numeric), ('\u{11300}', '\u{11303}', WC_Extend), ('\u{11305}', '\u{1130c}',
- WC_ALetter), ('\u{1130f}', '\u{11310}', WC_ALetter), ('\u{11313}', '\u{11328}', WC_ALetter),
- ('\u{1132a}', '\u{11330}', WC_ALetter), ('\u{11332}', '\u{11333}', WC_ALetter),
- ('\u{11335}', '\u{11339}', WC_ALetter), ('\u{1133b}', '\u{1133c}', WC_Extend), ('\u{1133d}',
- '\u{1133d}', WC_ALetter), ('\u{1133e}', '\u{11344}', WC_Extend), ('\u{11347}', '\u{11348}',
- WC_Extend), ('\u{1134b}', '\u{1134d}', WC_Extend), ('\u{11350}', '\u{11350}', WC_ALetter),
- ('\u{11357}', '\u{11357}', WC_Extend), ('\u{1135d}', '\u{11361}', WC_ALetter), ('\u{11362}',
- '\u{11363}', WC_Extend), ('\u{11366}', '\u{1136c}', WC_Extend), ('\u{11370}', '\u{11374}',
- WC_Extend), ('\u{11400}', '\u{11434}', WC_ALetter), ('\u{11435}', '\u{11446}', WC_Extend),
- ('\u{11447}', '\u{1144a}', WC_ALetter), ('\u{11450}', '\u{11459}', WC_Numeric),
- ('\u{1145e}', '\u{1145e}', WC_Extend), ('\u{1145f}', '\u{11461}', WC_ALetter), ('\u{11480}',
- '\u{114af}', WC_ALetter), ('\u{114b0}', '\u{114c3}', WC_Extend), ('\u{114c4}', '\u{114c5}',
- WC_ALetter), ('\u{114c7}', '\u{114c7}', WC_ALetter), ('\u{114d0}', '\u{114d9}', WC_Numeric),
- ('\u{11580}', '\u{115ae}', WC_ALetter), ('\u{115af}', '\u{115b5}', WC_Extend), ('\u{115b8}',
- '\u{115c0}', WC_Extend), ('\u{115d8}', '\u{115db}', WC_ALetter), ('\u{115dc}', '\u{115dd}',
- WC_Extend), ('\u{11600}', '\u{1162f}', WC_ALetter), ('\u{11630}', '\u{11640}', WC_Extend),
- ('\u{11644}', '\u{11644}', WC_ALetter), ('\u{11650}', '\u{11659}', WC_Numeric),
- ('\u{11680}', '\u{116aa}', WC_ALetter), ('\u{116ab}', '\u{116b7}', WC_Extend), ('\u{116b8}',
- '\u{116b8}', WC_ALetter), ('\u{116c0}', '\u{116c9}', WC_Numeric), ('\u{1171d}', '\u{1172b}',
- WC_Extend), ('\u{11730}', '\u{11739}', WC_Numeric), ('\u{11800}', '\u{1182b}', WC_ALetter),
- ('\u{1182c}', '\u{1183a}', WC_Extend), ('\u{118a0}', '\u{118df}', WC_ALetter), ('\u{118e0}',
- '\u{118e9}', WC_Numeric), ('\u{118ff}', '\u{11906}', WC_ALetter), ('\u{11909}', '\u{11909}',
- WC_ALetter), ('\u{1190c}', '\u{11913}', WC_ALetter), ('\u{11915}', '\u{11916}', WC_ALetter),
+ WC_Extend), ('\u{10eb0}', '\u{10eb1}', WC_ALetter), ('\u{10efd}', '\u{10eff}', WC_Extend),
+ ('\u{10f00}', '\u{10f1c}', WC_ALetter), ('\u{10f27}', '\u{10f27}', WC_ALetter),
+ ('\u{10f30}', '\u{10f45}', WC_ALetter), ('\u{10f46}', '\u{10f50}', WC_Extend), ('\u{10f70}',
+ '\u{10f81}', WC_ALetter), ('\u{10f82}', '\u{10f85}', WC_Extend), ('\u{10fb0}', '\u{10fc4}',
+ WC_ALetter), ('\u{10fe0}', '\u{10ff6}', WC_ALetter), ('\u{11000}', '\u{11002}', WC_Extend),
+ ('\u{11003}', '\u{11037}', WC_ALetter), ('\u{11038}', '\u{11046}', WC_Extend), ('\u{11066}',
+ '\u{1106f}', WC_Numeric), ('\u{11070}', '\u{11070}', WC_Extend), ('\u{11071}', '\u{11072}',
+ WC_ALetter), ('\u{11073}', '\u{11074}', WC_Extend), ('\u{11075}', '\u{11075}', WC_ALetter),
+ ('\u{1107f}', '\u{11082}', WC_Extend), ('\u{11083}', '\u{110af}', WC_ALetter), ('\u{110b0}',
+ '\u{110ba}', WC_Extend), ('\u{110bd}', '\u{110bd}', WC_Format), ('\u{110c2}', '\u{110c2}',
+ WC_Extend), ('\u{110cd}', '\u{110cd}', WC_Format), ('\u{110d0}', '\u{110e8}', WC_ALetter),
+ ('\u{110f0}', '\u{110f9}', WC_Numeric), ('\u{11100}', '\u{11102}', WC_Extend), ('\u{11103}',
+ '\u{11126}', WC_ALetter), ('\u{11127}', '\u{11134}', WC_Extend), ('\u{11136}', '\u{1113f}',
+ WC_Numeric), ('\u{11144}', '\u{11144}', WC_ALetter), ('\u{11145}', '\u{11146}', WC_Extend),
+ ('\u{11147}', '\u{11147}', WC_ALetter), ('\u{11150}', '\u{11172}', WC_ALetter),
+ ('\u{11173}', '\u{11173}', WC_Extend), ('\u{11176}', '\u{11176}', WC_ALetter), ('\u{11180}',
+ '\u{11182}', WC_Extend), ('\u{11183}', '\u{111b2}', WC_ALetter), ('\u{111b3}', '\u{111c0}',
+ WC_Extend), ('\u{111c1}', '\u{111c4}', WC_ALetter), ('\u{111c9}', '\u{111cc}', WC_Extend),
+ ('\u{111ce}', '\u{111cf}', WC_Extend), ('\u{111d0}', '\u{111d9}', WC_Numeric), ('\u{111da}',
+ '\u{111da}', WC_ALetter), ('\u{111dc}', '\u{111dc}', WC_ALetter), ('\u{11200}', '\u{11211}',
+ WC_ALetter), ('\u{11213}', '\u{1122b}', WC_ALetter), ('\u{1122c}', '\u{11237}', WC_Extend),
+ ('\u{1123e}', '\u{1123e}', WC_Extend), ('\u{1123f}', '\u{11240}', WC_ALetter), ('\u{11241}',
+ '\u{11241}', WC_Extend), ('\u{11280}', '\u{11286}', WC_ALetter), ('\u{11288}', '\u{11288}',
+ WC_ALetter), ('\u{1128a}', '\u{1128d}', WC_ALetter), ('\u{1128f}', '\u{1129d}', WC_ALetter),
+ ('\u{1129f}', '\u{112a8}', WC_ALetter), ('\u{112b0}', '\u{112de}', WC_ALetter),
+ ('\u{112df}', '\u{112ea}', WC_Extend), ('\u{112f0}', '\u{112f9}', WC_Numeric), ('\u{11300}',
+ '\u{11303}', WC_Extend), ('\u{11305}', '\u{1130c}', WC_ALetter), ('\u{1130f}', '\u{11310}',
+ WC_ALetter), ('\u{11313}', '\u{11328}', WC_ALetter), ('\u{1132a}', '\u{11330}', WC_ALetter),
+ ('\u{11332}', '\u{11333}', WC_ALetter), ('\u{11335}', '\u{11339}', WC_ALetter),
+ ('\u{1133b}', '\u{1133c}', WC_Extend), ('\u{1133d}', '\u{1133d}', WC_ALetter), ('\u{1133e}',
+ '\u{11344}', WC_Extend), ('\u{11347}', '\u{11348}', WC_Extend), ('\u{1134b}', '\u{1134d}',
+ WC_Extend), ('\u{11350}', '\u{11350}', WC_ALetter), ('\u{11357}', '\u{11357}', WC_Extend),
+ ('\u{1135d}', '\u{11361}', WC_ALetter), ('\u{11362}', '\u{11363}', WC_Extend), ('\u{11366}',
+ '\u{1136c}', WC_Extend), ('\u{11370}', '\u{11374}', WC_Extend), ('\u{11400}', '\u{11434}',
+ WC_ALetter), ('\u{11435}', '\u{11446}', WC_Extend), ('\u{11447}', '\u{1144a}', WC_ALetter),
+ ('\u{11450}', '\u{11459}', WC_Numeric), ('\u{1145e}', '\u{1145e}', WC_Extend), ('\u{1145f}',
+ '\u{11461}', WC_ALetter), ('\u{11480}', '\u{114af}', WC_ALetter), ('\u{114b0}', '\u{114c3}',
+ WC_Extend), ('\u{114c4}', '\u{114c5}', WC_ALetter), ('\u{114c7}', '\u{114c7}', WC_ALetter),
+ ('\u{114d0}', '\u{114d9}', WC_Numeric), ('\u{11580}', '\u{115ae}', WC_ALetter),
+ ('\u{115af}', '\u{115b5}', WC_Extend), ('\u{115b8}', '\u{115c0}', WC_Extend), ('\u{115d8}',
+ '\u{115db}', WC_ALetter), ('\u{115dc}', '\u{115dd}', WC_Extend), ('\u{11600}', '\u{1162f}',
+ WC_ALetter), ('\u{11630}', '\u{11640}', WC_Extend), ('\u{11644}', '\u{11644}', WC_ALetter),
+ ('\u{11650}', '\u{11659}', WC_Numeric), ('\u{11680}', '\u{116aa}', WC_ALetter),
+ ('\u{116ab}', '\u{116b7}', WC_Extend), ('\u{116b8}', '\u{116b8}', WC_ALetter), ('\u{116c0}',
+ '\u{116c9}', WC_Numeric), ('\u{1171d}', '\u{1172b}', WC_Extend), ('\u{11730}', '\u{11739}',
+ WC_Numeric), ('\u{11800}', '\u{1182b}', WC_ALetter), ('\u{1182c}', '\u{1183a}', WC_Extend),
+ ('\u{118a0}', '\u{118df}', WC_ALetter), ('\u{118e0}', '\u{118e9}', WC_Numeric),
+ ('\u{118ff}', '\u{11906}', WC_ALetter), ('\u{11909}', '\u{11909}', WC_ALetter),
+ ('\u{1190c}', '\u{11913}', WC_ALetter), ('\u{11915}', '\u{11916}', WC_ALetter),
('\u{11918}', '\u{1192f}', WC_ALetter), ('\u{11930}', '\u{11935}', WC_Extend), ('\u{11937}',
'\u{11938}', WC_Extend), ('\u{1193b}', '\u{1193e}', WC_Extend), ('\u{1193f}', '\u{1193f}',
WC_ALetter), ('\u{11940}', '\u{11940}', WC_Extend), ('\u{11941}', '\u{11941}', WC_ALetter),
@@ -1418,12 +1433,17 @@ pub mod word {
('\u{11d8a}', '\u{11d8e}', WC_Extend), ('\u{11d90}', '\u{11d91}', WC_Extend), ('\u{11d93}',
'\u{11d97}', WC_Extend), ('\u{11d98}', '\u{11d98}', WC_ALetter), ('\u{11da0}', '\u{11da9}',
WC_Numeric), ('\u{11ee0}', '\u{11ef2}', WC_ALetter), ('\u{11ef3}', '\u{11ef6}', WC_Extend),
- ('\u{11fb0}', '\u{11fb0}', WC_ALetter), ('\u{12000}', '\u{12399}', WC_ALetter),
- ('\u{12400}', '\u{1246e}', WC_ALetter), ('\u{12480}', '\u{12543}', WC_ALetter),
- ('\u{12f90}', '\u{12ff0}', WC_ALetter), ('\u{13000}', '\u{1342e}', WC_ALetter),
- ('\u{13430}', '\u{13438}', WC_Format), ('\u{14400}', '\u{14646}', WC_ALetter), ('\u{16800}',
- '\u{16a38}', WC_ALetter), ('\u{16a40}', '\u{16a5e}', WC_ALetter), ('\u{16a60}', '\u{16a69}',
- WC_Numeric), ('\u{16a70}', '\u{16abe}', WC_ALetter), ('\u{16ac0}', '\u{16ac9}', WC_Numeric),
+ ('\u{11f00}', '\u{11f01}', WC_Extend), ('\u{11f02}', '\u{11f02}', WC_ALetter), ('\u{11f03}',
+ '\u{11f03}', WC_Extend), ('\u{11f04}', '\u{11f10}', WC_ALetter), ('\u{11f12}', '\u{11f33}',
+ WC_ALetter), ('\u{11f34}', '\u{11f3a}', WC_Extend), ('\u{11f3e}', '\u{11f42}', WC_Extend),
+ ('\u{11f50}', '\u{11f59}', WC_Numeric), ('\u{11fb0}', '\u{11fb0}', WC_ALetter),
+ ('\u{12000}', '\u{12399}', WC_ALetter), ('\u{12400}', '\u{1246e}', WC_ALetter),
+ ('\u{12480}', '\u{12543}', WC_ALetter), ('\u{12f90}', '\u{12ff0}', WC_ALetter),
+ ('\u{13000}', '\u{1342f}', WC_ALetter), ('\u{13430}', '\u{1343f}', WC_Format), ('\u{13440}',
+ '\u{13440}', WC_Extend), ('\u{13441}', '\u{13446}', WC_ALetter), ('\u{13447}', '\u{13455}',
+ WC_Extend), ('\u{14400}', '\u{14646}', WC_ALetter), ('\u{16800}', '\u{16a38}', WC_ALetter),
+ ('\u{16a40}', '\u{16a5e}', WC_ALetter), ('\u{16a60}', '\u{16a69}', WC_Numeric),
+ ('\u{16a70}', '\u{16abe}', WC_ALetter), ('\u{16ac0}', '\u{16ac9}', WC_Numeric),
('\u{16ad0}', '\u{16aed}', WC_ALetter), ('\u{16af0}', '\u{16af4}', WC_Extend), ('\u{16b00}',
'\u{16b2f}', WC_ALetter), ('\u{16b30}', '\u{16b36}', WC_Extend), ('\u{16b40}', '\u{16b43}',
WC_ALetter), ('\u{16b50}', '\u{16b59}', WC_Numeric), ('\u{16b63}', '\u{16b77}', WC_ALetter),
@@ -1434,40 +1454,43 @@ pub mod word {
('\u{16fe3}', '\u{16fe3}', WC_ALetter), ('\u{16fe4}', '\u{16fe4}', WC_Extend), ('\u{16ff0}',
'\u{16ff1}', WC_Extend), ('\u{1aff0}', '\u{1aff3}', WC_Katakana), ('\u{1aff5}', '\u{1affb}',
WC_Katakana), ('\u{1affd}', '\u{1affe}', WC_Katakana), ('\u{1b000}', '\u{1b000}',
- WC_Katakana), ('\u{1b120}', '\u{1b122}', WC_Katakana), ('\u{1b164}', '\u{1b167}',
- WC_Katakana), ('\u{1bc00}', '\u{1bc6a}', WC_ALetter), ('\u{1bc70}', '\u{1bc7c}',
- WC_ALetter), ('\u{1bc80}', '\u{1bc88}', WC_ALetter), ('\u{1bc90}', '\u{1bc99}', WC_ALetter),
- ('\u{1bc9d}', '\u{1bc9e}', WC_Extend), ('\u{1bca0}', '\u{1bca3}', WC_Format), ('\u{1cf00}',
- '\u{1cf2d}', WC_Extend), ('\u{1cf30}', '\u{1cf46}', WC_Extend), ('\u{1d165}', '\u{1d169}',
- WC_Extend), ('\u{1d16d}', '\u{1d172}', WC_Extend), ('\u{1d173}', '\u{1d17a}', WC_Format),
- ('\u{1d17b}', '\u{1d182}', WC_Extend), ('\u{1d185}', '\u{1d18b}', WC_Extend), ('\u{1d1aa}',
- '\u{1d1ad}', WC_Extend), ('\u{1d242}', '\u{1d244}', WC_Extend), ('\u{1d400}', '\u{1d454}',
- WC_ALetter), ('\u{1d456}', '\u{1d49c}', WC_ALetter), ('\u{1d49e}', '\u{1d49f}', WC_ALetter),
- ('\u{1d4a2}', '\u{1d4a2}', WC_ALetter), ('\u{1d4a5}', '\u{1d4a6}', WC_ALetter),
- ('\u{1d4a9}', '\u{1d4ac}', WC_ALetter), ('\u{1d4ae}', '\u{1d4b9}', WC_ALetter),
- ('\u{1d4bb}', '\u{1d4bb}', WC_ALetter), ('\u{1d4bd}', '\u{1d4c3}', WC_ALetter),
- ('\u{1d4c5}', '\u{1d505}', WC_ALetter), ('\u{1d507}', '\u{1d50a}', WC_ALetter),
- ('\u{1d50d}', '\u{1d514}', WC_ALetter), ('\u{1d516}', '\u{1d51c}', WC_ALetter),
- ('\u{1d51e}', '\u{1d539}', WC_ALetter), ('\u{1d53b}', '\u{1d53e}', WC_ALetter),
- ('\u{1d540}', '\u{1d544}', WC_ALetter), ('\u{1d546}', '\u{1d546}', WC_ALetter),
- ('\u{1d54a}', '\u{1d550}', WC_ALetter), ('\u{1d552}', '\u{1d6a5}', WC_ALetter),
- ('\u{1d6a8}', '\u{1d6c0}', WC_ALetter), ('\u{1d6c2}', '\u{1d6da}', WC_ALetter),
- ('\u{1d6dc}', '\u{1d6fa}', WC_ALetter), ('\u{1d6fc}', '\u{1d714}', WC_ALetter),
- ('\u{1d716}', '\u{1d734}', WC_ALetter), ('\u{1d736}', '\u{1d74e}', WC_ALetter),
- ('\u{1d750}', '\u{1d76e}', WC_ALetter), ('\u{1d770}', '\u{1d788}', WC_ALetter),
- ('\u{1d78a}', '\u{1d7a8}', WC_ALetter), ('\u{1d7aa}', '\u{1d7c2}', WC_ALetter),
- ('\u{1d7c4}', '\u{1d7cb}', WC_ALetter), ('\u{1d7ce}', '\u{1d7ff}', WC_Numeric),
- ('\u{1da00}', '\u{1da36}', WC_Extend), ('\u{1da3b}', '\u{1da6c}', WC_Extend), ('\u{1da75}',
- '\u{1da75}', WC_Extend), ('\u{1da84}', '\u{1da84}', WC_Extend), ('\u{1da9b}', '\u{1da9f}',
- WC_Extend), ('\u{1daa1}', '\u{1daaf}', WC_Extend), ('\u{1df00}', '\u{1df1e}', WC_ALetter),
+ WC_Katakana), ('\u{1b120}', '\u{1b122}', WC_Katakana), ('\u{1b155}', '\u{1b155}',
+ WC_Katakana), ('\u{1b164}', '\u{1b167}', WC_Katakana), ('\u{1bc00}', '\u{1bc6a}',
+ WC_ALetter), ('\u{1bc70}', '\u{1bc7c}', WC_ALetter), ('\u{1bc80}', '\u{1bc88}', WC_ALetter),
+ ('\u{1bc90}', '\u{1bc99}', WC_ALetter), ('\u{1bc9d}', '\u{1bc9e}', WC_Extend), ('\u{1bca0}',
+ '\u{1bca3}', WC_Format), ('\u{1cf00}', '\u{1cf2d}', WC_Extend), ('\u{1cf30}', '\u{1cf46}',
+ WC_Extend), ('\u{1d165}', '\u{1d169}', WC_Extend), ('\u{1d16d}', '\u{1d172}', WC_Extend),
+ ('\u{1d173}', '\u{1d17a}', WC_Format), ('\u{1d17b}', '\u{1d182}', WC_Extend), ('\u{1d185}',
+ '\u{1d18b}', WC_Extend), ('\u{1d1aa}', '\u{1d1ad}', WC_Extend), ('\u{1d242}', '\u{1d244}',
+ WC_Extend), ('\u{1d400}', '\u{1d454}', WC_ALetter), ('\u{1d456}', '\u{1d49c}', WC_ALetter),
+ ('\u{1d49e}', '\u{1d49f}', WC_ALetter), ('\u{1d4a2}', '\u{1d4a2}', WC_ALetter),
+ ('\u{1d4a5}', '\u{1d4a6}', WC_ALetter), ('\u{1d4a9}', '\u{1d4ac}', WC_ALetter),
+ ('\u{1d4ae}', '\u{1d4b9}', WC_ALetter), ('\u{1d4bb}', '\u{1d4bb}', WC_ALetter),
+ ('\u{1d4bd}', '\u{1d4c3}', WC_ALetter), ('\u{1d4c5}', '\u{1d505}', WC_ALetter),
+ ('\u{1d507}', '\u{1d50a}', WC_ALetter), ('\u{1d50d}', '\u{1d514}', WC_ALetter),
+ ('\u{1d516}', '\u{1d51c}', WC_ALetter), ('\u{1d51e}', '\u{1d539}', WC_ALetter),
+ ('\u{1d53b}', '\u{1d53e}', WC_ALetter), ('\u{1d540}', '\u{1d544}', WC_ALetter),
+ ('\u{1d546}', '\u{1d546}', WC_ALetter), ('\u{1d54a}', '\u{1d550}', WC_ALetter),
+ ('\u{1d552}', '\u{1d6a5}', WC_ALetter), ('\u{1d6a8}', '\u{1d6c0}', WC_ALetter),
+ ('\u{1d6c2}', '\u{1d6da}', WC_ALetter), ('\u{1d6dc}', '\u{1d6fa}', WC_ALetter),
+ ('\u{1d6fc}', '\u{1d714}', WC_ALetter), ('\u{1d716}', '\u{1d734}', WC_ALetter),
+ ('\u{1d736}', '\u{1d74e}', WC_ALetter), ('\u{1d750}', '\u{1d76e}', WC_ALetter),
+ ('\u{1d770}', '\u{1d788}', WC_ALetter), ('\u{1d78a}', '\u{1d7a8}', WC_ALetter),
+ ('\u{1d7aa}', '\u{1d7c2}', WC_ALetter), ('\u{1d7c4}', '\u{1d7cb}', WC_ALetter),
+ ('\u{1d7ce}', '\u{1d7ff}', WC_Numeric), ('\u{1da00}', '\u{1da36}', WC_Extend), ('\u{1da3b}',
+ '\u{1da6c}', WC_Extend), ('\u{1da75}', '\u{1da75}', WC_Extend), ('\u{1da84}', '\u{1da84}',
+ WC_Extend), ('\u{1da9b}', '\u{1da9f}', WC_Extend), ('\u{1daa1}', '\u{1daaf}', WC_Extend),
+ ('\u{1df00}', '\u{1df1e}', WC_ALetter), ('\u{1df25}', '\u{1df2a}', WC_ALetter),
('\u{1e000}', '\u{1e006}', WC_Extend), ('\u{1e008}', '\u{1e018}', WC_Extend), ('\u{1e01b}',
'\u{1e021}', WC_Extend), ('\u{1e023}', '\u{1e024}', WC_Extend), ('\u{1e026}', '\u{1e02a}',
- WC_Extend), ('\u{1e100}', '\u{1e12c}', WC_ALetter), ('\u{1e130}', '\u{1e136}', WC_Extend),
- ('\u{1e137}', '\u{1e13d}', WC_ALetter), ('\u{1e140}', '\u{1e149}', WC_Numeric),
- ('\u{1e14e}', '\u{1e14e}', WC_ALetter), ('\u{1e290}', '\u{1e2ad}', WC_ALetter),
- ('\u{1e2ae}', '\u{1e2ae}', WC_Extend), ('\u{1e2c0}', '\u{1e2eb}', WC_ALetter), ('\u{1e2ec}',
- '\u{1e2ef}', WC_Extend), ('\u{1e2f0}', '\u{1e2f9}', WC_Numeric), ('\u{1e7e0}', '\u{1e7e6}',
- WC_ALetter), ('\u{1e7e8}', '\u{1e7eb}', WC_ALetter), ('\u{1e7ed}', '\u{1e7ee}', WC_ALetter),
+ WC_Extend), ('\u{1e030}', '\u{1e06d}', WC_ALetter), ('\u{1e08f}', '\u{1e08f}', WC_Extend),
+ ('\u{1e100}', '\u{1e12c}', WC_ALetter), ('\u{1e130}', '\u{1e136}', WC_Extend), ('\u{1e137}',
+ '\u{1e13d}', WC_ALetter), ('\u{1e140}', '\u{1e149}', WC_Numeric), ('\u{1e14e}', '\u{1e14e}',
+ WC_ALetter), ('\u{1e290}', '\u{1e2ad}', WC_ALetter), ('\u{1e2ae}', '\u{1e2ae}', WC_Extend),
+ ('\u{1e2c0}', '\u{1e2eb}', WC_ALetter), ('\u{1e2ec}', '\u{1e2ef}', WC_Extend), ('\u{1e2f0}',
+ '\u{1e2f9}', WC_Numeric), ('\u{1e4d0}', '\u{1e4eb}', WC_ALetter), ('\u{1e4ec}', '\u{1e4ef}',
+ WC_Extend), ('\u{1e4f0}', '\u{1e4f9}', WC_Numeric), ('\u{1e7e0}', '\u{1e7e6}', WC_ALetter),
+ ('\u{1e7e8}', '\u{1e7eb}', WC_ALetter), ('\u{1e7ed}', '\u{1e7ee}', WC_ALetter),
('\u{1e7f0}', '\u{1e7fe}', WC_ALetter), ('\u{1e800}', '\u{1e8c4}', WC_ALetter),
('\u{1e8d0}', '\u{1e8d6}', WC_Extend), ('\u{1e900}', '\u{1e943}', WC_ALetter), ('\u{1e944}',
'\u{1e94a}', WC_Extend), ('\u{1e94b}', '\u{1e94b}', WC_ALetter), ('\u{1e950}', '\u{1e959}',
@@ -1941,508 +1964,509 @@ pub mod sentence {
('\u{cc6}', '\u{cc8}', SC_Extend), ('\u{cca}', '\u{ccd}', SC_Extend), ('\u{cd5}', '\u{cd6}',
SC_Extend), ('\u{cdd}', '\u{cde}', SC_OLetter), ('\u{ce0}', '\u{ce1}', SC_OLetter),
('\u{ce2}', '\u{ce3}', SC_Extend), ('\u{ce6}', '\u{cef}', SC_Numeric), ('\u{cf1}',
- '\u{cf2}', SC_OLetter), ('\u{d00}', '\u{d03}', SC_Extend), ('\u{d04}', '\u{d0c}',
- SC_OLetter), ('\u{d0e}', '\u{d10}', SC_OLetter), ('\u{d12}', '\u{d3a}', SC_OLetter),
- ('\u{d3b}', '\u{d3c}', SC_Extend), ('\u{d3d}', '\u{d3d}', SC_OLetter), ('\u{d3e}',
- '\u{d44}', SC_Extend), ('\u{d46}', '\u{d48}', SC_Extend), ('\u{d4a}', '\u{d4d}', SC_Extend),
- ('\u{d4e}', '\u{d4e}', SC_OLetter), ('\u{d54}', '\u{d56}', SC_OLetter), ('\u{d57}',
- '\u{d57}', SC_Extend), ('\u{d5f}', '\u{d61}', SC_OLetter), ('\u{d62}', '\u{d63}',
- SC_Extend), ('\u{d66}', '\u{d6f}', SC_Numeric), ('\u{d7a}', '\u{d7f}', SC_OLetter),
- ('\u{d81}', '\u{d83}', SC_Extend), ('\u{d85}', '\u{d96}', SC_OLetter), ('\u{d9a}',
- '\u{db1}', SC_OLetter), ('\u{db3}', '\u{dbb}', SC_OLetter), ('\u{dbd}', '\u{dbd}',
- SC_OLetter), ('\u{dc0}', '\u{dc6}', SC_OLetter), ('\u{dca}', '\u{dca}', SC_Extend),
- ('\u{dcf}', '\u{dd4}', SC_Extend), ('\u{dd6}', '\u{dd6}', SC_Extend), ('\u{dd8}', '\u{ddf}',
- SC_Extend), ('\u{de6}', '\u{def}', SC_Numeric), ('\u{df2}', '\u{df3}', SC_Extend),
- ('\u{e01}', '\u{e30}', SC_OLetter), ('\u{e31}', '\u{e31}', SC_Extend), ('\u{e32}',
- '\u{e33}', SC_OLetter), ('\u{e34}', '\u{e3a}', SC_Extend), ('\u{e40}', '\u{e46}',
- SC_OLetter), ('\u{e47}', '\u{e4e}', SC_Extend), ('\u{e50}', '\u{e59}', SC_Numeric),
- ('\u{e81}', '\u{e82}', SC_OLetter), ('\u{e84}', '\u{e84}', SC_OLetter), ('\u{e86}',
- '\u{e8a}', SC_OLetter), ('\u{e8c}', '\u{ea3}', SC_OLetter), ('\u{ea5}', '\u{ea5}',
- SC_OLetter), ('\u{ea7}', '\u{eb0}', SC_OLetter), ('\u{eb1}', '\u{eb1}', SC_Extend),
- ('\u{eb2}', '\u{eb3}', SC_OLetter), ('\u{eb4}', '\u{ebc}', SC_Extend), ('\u{ebd}',
- '\u{ebd}', SC_OLetter), ('\u{ec0}', '\u{ec4}', SC_OLetter), ('\u{ec6}', '\u{ec6}',
- SC_OLetter), ('\u{ec8}', '\u{ecd}', SC_Extend), ('\u{ed0}', '\u{ed9}', SC_Numeric),
- ('\u{edc}', '\u{edf}', SC_OLetter), ('\u{f00}', '\u{f00}', SC_OLetter), ('\u{f18}',
- '\u{f19}', SC_Extend), ('\u{f20}', '\u{f29}', SC_Numeric), ('\u{f35}', '\u{f35}',
- SC_Extend), ('\u{f37}', '\u{f37}', SC_Extend), ('\u{f39}', '\u{f39}', SC_Extend),
- ('\u{f3a}', '\u{f3d}', SC_Close), ('\u{f3e}', '\u{f3f}', SC_Extend), ('\u{f40}', '\u{f47}',
- SC_OLetter), ('\u{f49}', '\u{f6c}', SC_OLetter), ('\u{f71}', '\u{f84}', SC_Extend),
- ('\u{f86}', '\u{f87}', SC_Extend), ('\u{f88}', '\u{f8c}', SC_OLetter), ('\u{f8d}',
- '\u{f97}', SC_Extend), ('\u{f99}', '\u{fbc}', SC_Extend), ('\u{fc6}', '\u{fc6}', SC_Extend),
- ('\u{1000}', '\u{102a}', SC_OLetter), ('\u{102b}', '\u{103e}', SC_Extend), ('\u{103f}',
- '\u{103f}', SC_OLetter), ('\u{1040}', '\u{1049}', SC_Numeric), ('\u{104a}', '\u{104b}',
- SC_STerm), ('\u{1050}', '\u{1055}', SC_OLetter), ('\u{1056}', '\u{1059}', SC_Extend),
- ('\u{105a}', '\u{105d}', SC_OLetter), ('\u{105e}', '\u{1060}', SC_Extend), ('\u{1061}',
- '\u{1061}', SC_OLetter), ('\u{1062}', '\u{1064}', SC_Extend), ('\u{1065}', '\u{1066}',
- SC_OLetter), ('\u{1067}', '\u{106d}', SC_Extend), ('\u{106e}', '\u{1070}', SC_OLetter),
- ('\u{1071}', '\u{1074}', SC_Extend), ('\u{1075}', '\u{1081}', SC_OLetter), ('\u{1082}',
- '\u{108d}', SC_Extend), ('\u{108e}', '\u{108e}', SC_OLetter), ('\u{108f}', '\u{108f}',
- SC_Extend), ('\u{1090}', '\u{1099}', SC_Numeric), ('\u{109a}', '\u{109d}', SC_Extend),
- ('\u{10a0}', '\u{10c5}', SC_Upper), ('\u{10c7}', '\u{10c7}', SC_Upper), ('\u{10cd}',
- '\u{10cd}', SC_Upper), ('\u{10d0}', '\u{10fa}', SC_OLetter), ('\u{10fc}', '\u{1248}',
- SC_OLetter), ('\u{124a}', '\u{124d}', SC_OLetter), ('\u{1250}', '\u{1256}', SC_OLetter),
- ('\u{1258}', '\u{1258}', SC_OLetter), ('\u{125a}', '\u{125d}', SC_OLetter), ('\u{1260}',
- '\u{1288}', SC_OLetter), ('\u{128a}', '\u{128d}', SC_OLetter), ('\u{1290}', '\u{12b0}',
- SC_OLetter), ('\u{12b2}', '\u{12b5}', SC_OLetter), ('\u{12b8}', '\u{12be}', SC_OLetter),
- ('\u{12c0}', '\u{12c0}', SC_OLetter), ('\u{12c2}', '\u{12c5}', SC_OLetter), ('\u{12c8}',
- '\u{12d6}', SC_OLetter), ('\u{12d8}', '\u{1310}', SC_OLetter), ('\u{1312}', '\u{1315}',
- SC_OLetter), ('\u{1318}', '\u{135a}', SC_OLetter), ('\u{135d}', '\u{135f}', SC_Extend),
- ('\u{1362}', '\u{1362}', SC_STerm), ('\u{1367}', '\u{1368}', SC_STerm), ('\u{1380}',
- '\u{138f}', SC_OLetter), ('\u{13a0}', '\u{13f5}', SC_Upper), ('\u{13f8}', '\u{13fd}',
- SC_Lower), ('\u{1401}', '\u{166c}', SC_OLetter), ('\u{166e}', '\u{166e}', SC_STerm),
- ('\u{166f}', '\u{167f}', SC_OLetter), ('\u{1680}', '\u{1680}', SC_Sp), ('\u{1681}',
- '\u{169a}', SC_OLetter), ('\u{169b}', '\u{169c}', SC_Close), ('\u{16a0}', '\u{16ea}',
- SC_OLetter), ('\u{16ee}', '\u{16f8}', SC_OLetter), ('\u{1700}', '\u{1711}', SC_OLetter),
- ('\u{1712}', '\u{1715}', SC_Extend), ('\u{171f}', '\u{1731}', SC_OLetter), ('\u{1732}',
- '\u{1734}', SC_Extend), ('\u{1735}', '\u{1736}', SC_STerm), ('\u{1740}', '\u{1751}',
- SC_OLetter), ('\u{1752}', '\u{1753}', SC_Extend), ('\u{1760}', '\u{176c}', SC_OLetter),
- ('\u{176e}', '\u{1770}', SC_OLetter), ('\u{1772}', '\u{1773}', SC_Extend), ('\u{1780}',
- '\u{17b3}', SC_OLetter), ('\u{17b4}', '\u{17d3}', SC_Extend), ('\u{17d7}', '\u{17d7}',
- SC_OLetter), ('\u{17dc}', '\u{17dc}', SC_OLetter), ('\u{17dd}', '\u{17dd}', SC_Extend),
- ('\u{17e0}', '\u{17e9}', SC_Numeric), ('\u{1802}', '\u{1802}', SC_SContinue), ('\u{1803}',
- '\u{1803}', SC_STerm), ('\u{1808}', '\u{1808}', SC_SContinue), ('\u{1809}', '\u{1809}',
- SC_STerm), ('\u{180b}', '\u{180d}', SC_Extend), ('\u{180e}', '\u{180e}', SC_Format),
- ('\u{180f}', '\u{180f}', SC_Extend), ('\u{1810}', '\u{1819}', SC_Numeric), ('\u{1820}',
- '\u{1878}', SC_OLetter), ('\u{1880}', '\u{1884}', SC_OLetter), ('\u{1885}', '\u{1886}',
- SC_Extend), ('\u{1887}', '\u{18a8}', SC_OLetter), ('\u{18a9}', '\u{18a9}', SC_Extend),
- ('\u{18aa}', '\u{18aa}', SC_OLetter), ('\u{18b0}', '\u{18f5}', SC_OLetter), ('\u{1900}',
- '\u{191e}', SC_OLetter), ('\u{1920}', '\u{192b}', SC_Extend), ('\u{1930}', '\u{193b}',
- SC_Extend), ('\u{1944}', '\u{1945}', SC_STerm), ('\u{1946}', '\u{194f}', SC_Numeric),
- ('\u{1950}', '\u{196d}', SC_OLetter), ('\u{1970}', '\u{1974}', SC_OLetter), ('\u{1980}',
- '\u{19ab}', SC_OLetter), ('\u{19b0}', '\u{19c9}', SC_OLetter), ('\u{19d0}', '\u{19d9}',
- SC_Numeric), ('\u{1a00}', '\u{1a16}', SC_OLetter), ('\u{1a17}', '\u{1a1b}', SC_Extend),
- ('\u{1a20}', '\u{1a54}', SC_OLetter), ('\u{1a55}', '\u{1a5e}', SC_Extend), ('\u{1a60}',
- '\u{1a7c}', SC_Extend), ('\u{1a7f}', '\u{1a7f}', SC_Extend), ('\u{1a80}', '\u{1a89}',
- SC_Numeric), ('\u{1a90}', '\u{1a99}', SC_Numeric), ('\u{1aa7}', '\u{1aa7}', SC_OLetter),
- ('\u{1aa8}', '\u{1aab}', SC_STerm), ('\u{1ab0}', '\u{1ace}', SC_Extend), ('\u{1b00}',
- '\u{1b04}', SC_Extend), ('\u{1b05}', '\u{1b33}', SC_OLetter), ('\u{1b34}', '\u{1b44}',
- SC_Extend), ('\u{1b45}', '\u{1b4c}', SC_OLetter), ('\u{1b50}', '\u{1b59}', SC_Numeric),
- ('\u{1b5a}', '\u{1b5b}', SC_STerm), ('\u{1b5e}', '\u{1b5f}', SC_STerm), ('\u{1b6b}',
- '\u{1b73}', SC_Extend), ('\u{1b7d}', '\u{1b7e}', SC_STerm), ('\u{1b80}', '\u{1b82}',
- SC_Extend), ('\u{1b83}', '\u{1ba0}', SC_OLetter), ('\u{1ba1}', '\u{1bad}', SC_Extend),
- ('\u{1bae}', '\u{1baf}', SC_OLetter), ('\u{1bb0}', '\u{1bb9}', SC_Numeric), ('\u{1bba}',
- '\u{1be5}', SC_OLetter), ('\u{1be6}', '\u{1bf3}', SC_Extend), ('\u{1c00}', '\u{1c23}',
- SC_OLetter), ('\u{1c24}', '\u{1c37}', SC_Extend), ('\u{1c3b}', '\u{1c3c}', SC_STerm),
- ('\u{1c40}', '\u{1c49}', SC_Numeric), ('\u{1c4d}', '\u{1c4f}', SC_OLetter), ('\u{1c50}',
- '\u{1c59}', SC_Numeric), ('\u{1c5a}', '\u{1c7d}', SC_OLetter), ('\u{1c7e}', '\u{1c7f}',
- SC_STerm), ('\u{1c80}', '\u{1c88}', SC_Lower), ('\u{1c90}', '\u{1cba}', SC_OLetter),
- ('\u{1cbd}', '\u{1cbf}', SC_OLetter), ('\u{1cd0}', '\u{1cd2}', SC_Extend), ('\u{1cd4}',
- '\u{1ce8}', SC_Extend), ('\u{1ce9}', '\u{1cec}', SC_OLetter), ('\u{1ced}', '\u{1ced}',
- SC_Extend), ('\u{1cee}', '\u{1cf3}', SC_OLetter), ('\u{1cf4}', '\u{1cf4}', SC_Extend),
- ('\u{1cf5}', '\u{1cf6}', SC_OLetter), ('\u{1cf7}', '\u{1cf9}', SC_Extend), ('\u{1cfa}',
- '\u{1cfa}', SC_OLetter), ('\u{1d00}', '\u{1dbf}', SC_Lower), ('\u{1dc0}', '\u{1dff}',
- SC_Extend), ('\u{1e00}', '\u{1e00}', SC_Upper), ('\u{1e01}', '\u{1e01}', SC_Lower),
- ('\u{1e02}', '\u{1e02}', SC_Upper), ('\u{1e03}', '\u{1e03}', SC_Lower), ('\u{1e04}',
- '\u{1e04}', SC_Upper), ('\u{1e05}', '\u{1e05}', SC_Lower), ('\u{1e06}', '\u{1e06}',
- SC_Upper), ('\u{1e07}', '\u{1e07}', SC_Lower), ('\u{1e08}', '\u{1e08}', SC_Upper),
- ('\u{1e09}', '\u{1e09}', SC_Lower), ('\u{1e0a}', '\u{1e0a}', SC_Upper), ('\u{1e0b}',
- '\u{1e0b}', SC_Lower), ('\u{1e0c}', '\u{1e0c}', SC_Upper), ('\u{1e0d}', '\u{1e0d}',
- SC_Lower), ('\u{1e0e}', '\u{1e0e}', SC_Upper), ('\u{1e0f}', '\u{1e0f}', SC_Lower),
- ('\u{1e10}', '\u{1e10}', SC_Upper), ('\u{1e11}', '\u{1e11}', SC_Lower), ('\u{1e12}',
- '\u{1e12}', SC_Upper), ('\u{1e13}', '\u{1e13}', SC_Lower), ('\u{1e14}', '\u{1e14}',
- SC_Upper), ('\u{1e15}', '\u{1e15}', SC_Lower), ('\u{1e16}', '\u{1e16}', SC_Upper),
- ('\u{1e17}', '\u{1e17}', SC_Lower), ('\u{1e18}', '\u{1e18}', SC_Upper), ('\u{1e19}',
- '\u{1e19}', SC_Lower), ('\u{1e1a}', '\u{1e1a}', SC_Upper), ('\u{1e1b}', '\u{1e1b}',
- SC_Lower), ('\u{1e1c}', '\u{1e1c}', SC_Upper), ('\u{1e1d}', '\u{1e1d}', SC_Lower),
- ('\u{1e1e}', '\u{1e1e}', SC_Upper), ('\u{1e1f}', '\u{1e1f}', SC_Lower), ('\u{1e20}',
- '\u{1e20}', SC_Upper), ('\u{1e21}', '\u{1e21}', SC_Lower), ('\u{1e22}', '\u{1e22}',
- SC_Upper), ('\u{1e23}', '\u{1e23}', SC_Lower), ('\u{1e24}', '\u{1e24}', SC_Upper),
- ('\u{1e25}', '\u{1e25}', SC_Lower), ('\u{1e26}', '\u{1e26}', SC_Upper), ('\u{1e27}',
- '\u{1e27}', SC_Lower), ('\u{1e28}', '\u{1e28}', SC_Upper), ('\u{1e29}', '\u{1e29}',
- SC_Lower), ('\u{1e2a}', '\u{1e2a}', SC_Upper), ('\u{1e2b}', '\u{1e2b}', SC_Lower),
- ('\u{1e2c}', '\u{1e2c}', SC_Upper), ('\u{1e2d}', '\u{1e2d}', SC_Lower), ('\u{1e2e}',
- '\u{1e2e}', SC_Upper), ('\u{1e2f}', '\u{1e2f}', SC_Lower), ('\u{1e30}', '\u{1e30}',
- SC_Upper), ('\u{1e31}', '\u{1e31}', SC_Lower), ('\u{1e32}', '\u{1e32}', SC_Upper),
- ('\u{1e33}', '\u{1e33}', SC_Lower), ('\u{1e34}', '\u{1e34}', SC_Upper), ('\u{1e35}',
- '\u{1e35}', SC_Lower), ('\u{1e36}', '\u{1e36}', SC_Upper), ('\u{1e37}', '\u{1e37}',
- SC_Lower), ('\u{1e38}', '\u{1e38}', SC_Upper), ('\u{1e39}', '\u{1e39}', SC_Lower),
- ('\u{1e3a}', '\u{1e3a}', SC_Upper), ('\u{1e3b}', '\u{1e3b}', SC_Lower), ('\u{1e3c}',
- '\u{1e3c}', SC_Upper), ('\u{1e3d}', '\u{1e3d}', SC_Lower), ('\u{1e3e}', '\u{1e3e}',
- SC_Upper), ('\u{1e3f}', '\u{1e3f}', SC_Lower), ('\u{1e40}', '\u{1e40}', SC_Upper),
- ('\u{1e41}', '\u{1e41}', SC_Lower), ('\u{1e42}', '\u{1e42}', SC_Upper), ('\u{1e43}',
- '\u{1e43}', SC_Lower), ('\u{1e44}', '\u{1e44}', SC_Upper), ('\u{1e45}', '\u{1e45}',
- SC_Lower), ('\u{1e46}', '\u{1e46}', SC_Upper), ('\u{1e47}', '\u{1e47}', SC_Lower),
- ('\u{1e48}', '\u{1e48}', SC_Upper), ('\u{1e49}', '\u{1e49}', SC_Lower), ('\u{1e4a}',
- '\u{1e4a}', SC_Upper), ('\u{1e4b}', '\u{1e4b}', SC_Lower), ('\u{1e4c}', '\u{1e4c}',
- SC_Upper), ('\u{1e4d}', '\u{1e4d}', SC_Lower), ('\u{1e4e}', '\u{1e4e}', SC_Upper),
- ('\u{1e4f}', '\u{1e4f}', SC_Lower), ('\u{1e50}', '\u{1e50}', SC_Upper), ('\u{1e51}',
- '\u{1e51}', SC_Lower), ('\u{1e52}', '\u{1e52}', SC_Upper), ('\u{1e53}', '\u{1e53}',
- SC_Lower), ('\u{1e54}', '\u{1e54}', SC_Upper), ('\u{1e55}', '\u{1e55}', SC_Lower),
- ('\u{1e56}', '\u{1e56}', SC_Upper), ('\u{1e57}', '\u{1e57}', SC_Lower), ('\u{1e58}',
- '\u{1e58}', SC_Upper), ('\u{1e59}', '\u{1e59}', SC_Lower), ('\u{1e5a}', '\u{1e5a}',
- SC_Upper), ('\u{1e5b}', '\u{1e5b}', SC_Lower), ('\u{1e5c}', '\u{1e5c}', SC_Upper),
- ('\u{1e5d}', '\u{1e5d}', SC_Lower), ('\u{1e5e}', '\u{1e5e}', SC_Upper), ('\u{1e5f}',
- '\u{1e5f}', SC_Lower), ('\u{1e60}', '\u{1e60}', SC_Upper), ('\u{1e61}', '\u{1e61}',
- SC_Lower), ('\u{1e62}', '\u{1e62}', SC_Upper), ('\u{1e63}', '\u{1e63}', SC_Lower),
- ('\u{1e64}', '\u{1e64}', SC_Upper), ('\u{1e65}', '\u{1e65}', SC_Lower), ('\u{1e66}',
- '\u{1e66}', SC_Upper), ('\u{1e67}', '\u{1e67}', SC_Lower), ('\u{1e68}', '\u{1e68}',
- SC_Upper), ('\u{1e69}', '\u{1e69}', SC_Lower), ('\u{1e6a}', '\u{1e6a}', SC_Upper),
- ('\u{1e6b}', '\u{1e6b}', SC_Lower), ('\u{1e6c}', '\u{1e6c}', SC_Upper), ('\u{1e6d}',
- '\u{1e6d}', SC_Lower), ('\u{1e6e}', '\u{1e6e}', SC_Upper), ('\u{1e6f}', '\u{1e6f}',
- SC_Lower), ('\u{1e70}', '\u{1e70}', SC_Upper), ('\u{1e71}', '\u{1e71}', SC_Lower),
- ('\u{1e72}', '\u{1e72}', SC_Upper), ('\u{1e73}', '\u{1e73}', SC_Lower), ('\u{1e74}',
- '\u{1e74}', SC_Upper), ('\u{1e75}', '\u{1e75}', SC_Lower), ('\u{1e76}', '\u{1e76}',
- SC_Upper), ('\u{1e77}', '\u{1e77}', SC_Lower), ('\u{1e78}', '\u{1e78}', SC_Upper),
- ('\u{1e79}', '\u{1e79}', SC_Lower), ('\u{1e7a}', '\u{1e7a}', SC_Upper), ('\u{1e7b}',
- '\u{1e7b}', SC_Lower), ('\u{1e7c}', '\u{1e7c}', SC_Upper), ('\u{1e7d}', '\u{1e7d}',
- SC_Lower), ('\u{1e7e}', '\u{1e7e}', SC_Upper), ('\u{1e7f}', '\u{1e7f}', SC_Lower),
- ('\u{1e80}', '\u{1e80}', SC_Upper), ('\u{1e81}', '\u{1e81}', SC_Lower), ('\u{1e82}',
- '\u{1e82}', SC_Upper), ('\u{1e83}', '\u{1e83}', SC_Lower), ('\u{1e84}', '\u{1e84}',
- SC_Upper), ('\u{1e85}', '\u{1e85}', SC_Lower), ('\u{1e86}', '\u{1e86}', SC_Upper),
- ('\u{1e87}', '\u{1e87}', SC_Lower), ('\u{1e88}', '\u{1e88}', SC_Upper), ('\u{1e89}',
- '\u{1e89}', SC_Lower), ('\u{1e8a}', '\u{1e8a}', SC_Upper), ('\u{1e8b}', '\u{1e8b}',
- SC_Lower), ('\u{1e8c}', '\u{1e8c}', SC_Upper), ('\u{1e8d}', '\u{1e8d}', SC_Lower),
- ('\u{1e8e}', '\u{1e8e}', SC_Upper), ('\u{1e8f}', '\u{1e8f}', SC_Lower), ('\u{1e90}',
- '\u{1e90}', SC_Upper), ('\u{1e91}', '\u{1e91}', SC_Lower), ('\u{1e92}', '\u{1e92}',
- SC_Upper), ('\u{1e93}', '\u{1e93}', SC_Lower), ('\u{1e94}', '\u{1e94}', SC_Upper),
- ('\u{1e95}', '\u{1e9d}', SC_Lower), ('\u{1e9e}', '\u{1e9e}', SC_Upper), ('\u{1e9f}',
- '\u{1e9f}', SC_Lower), ('\u{1ea0}', '\u{1ea0}', SC_Upper), ('\u{1ea1}', '\u{1ea1}',
- SC_Lower), ('\u{1ea2}', '\u{1ea2}', SC_Upper), ('\u{1ea3}', '\u{1ea3}', SC_Lower),
- ('\u{1ea4}', '\u{1ea4}', SC_Upper), ('\u{1ea5}', '\u{1ea5}', SC_Lower), ('\u{1ea6}',
- '\u{1ea6}', SC_Upper), ('\u{1ea7}', '\u{1ea7}', SC_Lower), ('\u{1ea8}', '\u{1ea8}',
- SC_Upper), ('\u{1ea9}', '\u{1ea9}', SC_Lower), ('\u{1eaa}', '\u{1eaa}', SC_Upper),
- ('\u{1eab}', '\u{1eab}', SC_Lower), ('\u{1eac}', '\u{1eac}', SC_Upper), ('\u{1ead}',
- '\u{1ead}', SC_Lower), ('\u{1eae}', '\u{1eae}', SC_Upper), ('\u{1eaf}', '\u{1eaf}',
- SC_Lower), ('\u{1eb0}', '\u{1eb0}', SC_Upper), ('\u{1eb1}', '\u{1eb1}', SC_Lower),
- ('\u{1eb2}', '\u{1eb2}', SC_Upper), ('\u{1eb3}', '\u{1eb3}', SC_Lower), ('\u{1eb4}',
- '\u{1eb4}', SC_Upper), ('\u{1eb5}', '\u{1eb5}', SC_Lower), ('\u{1eb6}', '\u{1eb6}',
- SC_Upper), ('\u{1eb7}', '\u{1eb7}', SC_Lower), ('\u{1eb8}', '\u{1eb8}', SC_Upper),
- ('\u{1eb9}', '\u{1eb9}', SC_Lower), ('\u{1eba}', '\u{1eba}', SC_Upper), ('\u{1ebb}',
- '\u{1ebb}', SC_Lower), ('\u{1ebc}', '\u{1ebc}', SC_Upper), ('\u{1ebd}', '\u{1ebd}',
- SC_Lower), ('\u{1ebe}', '\u{1ebe}', SC_Upper), ('\u{1ebf}', '\u{1ebf}', SC_Lower),
- ('\u{1ec0}', '\u{1ec0}', SC_Upper), ('\u{1ec1}', '\u{1ec1}', SC_Lower), ('\u{1ec2}',
- '\u{1ec2}', SC_Upper), ('\u{1ec3}', '\u{1ec3}', SC_Lower), ('\u{1ec4}', '\u{1ec4}',
- SC_Upper), ('\u{1ec5}', '\u{1ec5}', SC_Lower), ('\u{1ec6}', '\u{1ec6}', SC_Upper),
- ('\u{1ec7}', '\u{1ec7}', SC_Lower), ('\u{1ec8}', '\u{1ec8}', SC_Upper), ('\u{1ec9}',
- '\u{1ec9}', SC_Lower), ('\u{1eca}', '\u{1eca}', SC_Upper), ('\u{1ecb}', '\u{1ecb}',
- SC_Lower), ('\u{1ecc}', '\u{1ecc}', SC_Upper), ('\u{1ecd}', '\u{1ecd}', SC_Lower),
- ('\u{1ece}', '\u{1ece}', SC_Upper), ('\u{1ecf}', '\u{1ecf}', SC_Lower), ('\u{1ed0}',
- '\u{1ed0}', SC_Upper), ('\u{1ed1}', '\u{1ed1}', SC_Lower), ('\u{1ed2}', '\u{1ed2}',
- SC_Upper), ('\u{1ed3}', '\u{1ed3}', SC_Lower), ('\u{1ed4}', '\u{1ed4}', SC_Upper),
- ('\u{1ed5}', '\u{1ed5}', SC_Lower), ('\u{1ed6}', '\u{1ed6}', SC_Upper), ('\u{1ed7}',
- '\u{1ed7}', SC_Lower), ('\u{1ed8}', '\u{1ed8}', SC_Upper), ('\u{1ed9}', '\u{1ed9}',
- SC_Lower), ('\u{1eda}', '\u{1eda}', SC_Upper), ('\u{1edb}', '\u{1edb}', SC_Lower),
- ('\u{1edc}', '\u{1edc}', SC_Upper), ('\u{1edd}', '\u{1edd}', SC_Lower), ('\u{1ede}',
- '\u{1ede}', SC_Upper), ('\u{1edf}', '\u{1edf}', SC_Lower), ('\u{1ee0}', '\u{1ee0}',
- SC_Upper), ('\u{1ee1}', '\u{1ee1}', SC_Lower), ('\u{1ee2}', '\u{1ee2}', SC_Upper),
- ('\u{1ee3}', '\u{1ee3}', SC_Lower), ('\u{1ee4}', '\u{1ee4}', SC_Upper), ('\u{1ee5}',
- '\u{1ee5}', SC_Lower), ('\u{1ee6}', '\u{1ee6}', SC_Upper), ('\u{1ee7}', '\u{1ee7}',
- SC_Lower), ('\u{1ee8}', '\u{1ee8}', SC_Upper), ('\u{1ee9}', '\u{1ee9}', SC_Lower),
- ('\u{1eea}', '\u{1eea}', SC_Upper), ('\u{1eeb}', '\u{1eeb}', SC_Lower), ('\u{1eec}',
- '\u{1eec}', SC_Upper), ('\u{1eed}', '\u{1eed}', SC_Lower), ('\u{1eee}', '\u{1eee}',
- SC_Upper), ('\u{1eef}', '\u{1eef}', SC_Lower), ('\u{1ef0}', '\u{1ef0}', SC_Upper),
- ('\u{1ef1}', '\u{1ef1}', SC_Lower), ('\u{1ef2}', '\u{1ef2}', SC_Upper), ('\u{1ef3}',
- '\u{1ef3}', SC_Lower), ('\u{1ef4}', '\u{1ef4}', SC_Upper), ('\u{1ef5}', '\u{1ef5}',
- SC_Lower), ('\u{1ef6}', '\u{1ef6}', SC_Upper), ('\u{1ef7}', '\u{1ef7}', SC_Lower),
- ('\u{1ef8}', '\u{1ef8}', SC_Upper), ('\u{1ef9}', '\u{1ef9}', SC_Lower), ('\u{1efa}',
- '\u{1efa}', SC_Upper), ('\u{1efb}', '\u{1efb}', SC_Lower), ('\u{1efc}', '\u{1efc}',
- SC_Upper), ('\u{1efd}', '\u{1efd}', SC_Lower), ('\u{1efe}', '\u{1efe}', SC_Upper),
- ('\u{1eff}', '\u{1f07}', SC_Lower), ('\u{1f08}', '\u{1f0f}', SC_Upper), ('\u{1f10}',
- '\u{1f15}', SC_Lower), ('\u{1f18}', '\u{1f1d}', SC_Upper), ('\u{1f20}', '\u{1f27}',
- SC_Lower), ('\u{1f28}', '\u{1f2f}', SC_Upper), ('\u{1f30}', '\u{1f37}', SC_Lower),
- ('\u{1f38}', '\u{1f3f}', SC_Upper), ('\u{1f40}', '\u{1f45}', SC_Lower), ('\u{1f48}',
- '\u{1f4d}', SC_Upper), ('\u{1f50}', '\u{1f57}', SC_Lower), ('\u{1f59}', '\u{1f59}',
- SC_Upper), ('\u{1f5b}', '\u{1f5b}', SC_Upper), ('\u{1f5d}', '\u{1f5d}', SC_Upper),
- ('\u{1f5f}', '\u{1f5f}', SC_Upper), ('\u{1f60}', '\u{1f67}', SC_Lower), ('\u{1f68}',
- '\u{1f6f}', SC_Upper), ('\u{1f70}', '\u{1f7d}', SC_Lower), ('\u{1f80}', '\u{1f87}',
- SC_Lower), ('\u{1f88}', '\u{1f8f}', SC_Upper), ('\u{1f90}', '\u{1f97}', SC_Lower),
- ('\u{1f98}', '\u{1f9f}', SC_Upper), ('\u{1fa0}', '\u{1fa7}', SC_Lower), ('\u{1fa8}',
- '\u{1faf}', SC_Upper), ('\u{1fb0}', '\u{1fb4}', SC_Lower), ('\u{1fb6}', '\u{1fb7}',
- SC_Lower), ('\u{1fb8}', '\u{1fbc}', SC_Upper), ('\u{1fbe}', '\u{1fbe}', SC_Lower),
- ('\u{1fc2}', '\u{1fc4}', SC_Lower), ('\u{1fc6}', '\u{1fc7}', SC_Lower), ('\u{1fc8}',
- '\u{1fcc}', SC_Upper), ('\u{1fd0}', '\u{1fd3}', SC_Lower), ('\u{1fd6}', '\u{1fd7}',
- SC_Lower), ('\u{1fd8}', '\u{1fdb}', SC_Upper), ('\u{1fe0}', '\u{1fe7}', SC_Lower),
- ('\u{1fe8}', '\u{1fec}', SC_Upper), ('\u{1ff2}', '\u{1ff4}', SC_Lower), ('\u{1ff6}',
- '\u{1ff7}', SC_Lower), ('\u{1ff8}', '\u{1ffc}', SC_Upper), ('\u{2000}', '\u{200a}', SC_Sp),
- ('\u{200b}', '\u{200b}', SC_Format), ('\u{200c}', '\u{200d}', SC_Extend), ('\u{200e}',
- '\u{200f}', SC_Format), ('\u{2013}', '\u{2014}', SC_SContinue), ('\u{2018}', '\u{201f}',
- SC_Close), ('\u{2024}', '\u{2024}', SC_ATerm), ('\u{2028}', '\u{2029}', SC_Sep),
- ('\u{202a}', '\u{202e}', SC_Format), ('\u{202f}', '\u{202f}', SC_Sp), ('\u{2039}',
- '\u{203a}', SC_Close), ('\u{203c}', '\u{203d}', SC_STerm), ('\u{2045}', '\u{2046}',
- SC_Close), ('\u{2047}', '\u{2049}', SC_STerm), ('\u{205f}', '\u{205f}', SC_Sp), ('\u{2060}',
- '\u{2064}', SC_Format), ('\u{2066}', '\u{206f}', SC_Format), ('\u{2071}', '\u{2071}',
- SC_Lower), ('\u{207d}', '\u{207e}', SC_Close), ('\u{207f}', '\u{207f}', SC_Lower),
- ('\u{208d}', '\u{208e}', SC_Close), ('\u{2090}', '\u{209c}', SC_Lower), ('\u{20d0}',
- '\u{20f0}', SC_Extend), ('\u{2102}', '\u{2102}', SC_Upper), ('\u{2107}', '\u{2107}',
- SC_Upper), ('\u{210a}', '\u{210a}', SC_Lower), ('\u{210b}', '\u{210d}', SC_Upper),
- ('\u{210e}', '\u{210f}', SC_Lower), ('\u{2110}', '\u{2112}', SC_Upper), ('\u{2113}',
- '\u{2113}', SC_Lower), ('\u{2115}', '\u{2115}', SC_Upper), ('\u{2119}', '\u{211d}',
- SC_Upper), ('\u{2124}', '\u{2124}', SC_Upper), ('\u{2126}', '\u{2126}', SC_Upper),
- ('\u{2128}', '\u{2128}', SC_Upper), ('\u{212a}', '\u{212d}', SC_Upper), ('\u{212f}',
- '\u{212f}', SC_Lower), ('\u{2130}', '\u{2133}', SC_Upper), ('\u{2134}', '\u{2134}',
- SC_Lower), ('\u{2135}', '\u{2138}', SC_OLetter), ('\u{2139}', '\u{2139}', SC_Lower),
- ('\u{213c}', '\u{213d}', SC_Lower), ('\u{213e}', '\u{213f}', SC_Upper), ('\u{2145}',
- '\u{2145}', SC_Upper), ('\u{2146}', '\u{2149}', SC_Lower), ('\u{214e}', '\u{214e}',
- SC_Lower), ('\u{2160}', '\u{216f}', SC_Upper), ('\u{2170}', '\u{217f}', SC_Lower),
- ('\u{2180}', '\u{2182}', SC_OLetter), ('\u{2183}', '\u{2183}', SC_Upper), ('\u{2184}',
- '\u{2184}', SC_Lower), ('\u{2185}', '\u{2188}', SC_OLetter), ('\u{2308}', '\u{230b}',
- SC_Close), ('\u{2329}', '\u{232a}', SC_Close), ('\u{24b6}', '\u{24cf}', SC_Upper),
- ('\u{24d0}', '\u{24e9}', SC_Lower), ('\u{275b}', '\u{2760}', SC_Close), ('\u{2768}',
- '\u{2775}', SC_Close), ('\u{27c5}', '\u{27c6}', SC_Close), ('\u{27e6}', '\u{27ef}',
- SC_Close), ('\u{2983}', '\u{2998}', SC_Close), ('\u{29d8}', '\u{29db}', SC_Close),
- ('\u{29fc}', '\u{29fd}', SC_Close), ('\u{2c00}', '\u{2c2f}', SC_Upper), ('\u{2c30}',
- '\u{2c5f}', SC_Lower), ('\u{2c60}', '\u{2c60}', SC_Upper), ('\u{2c61}', '\u{2c61}',
- SC_Lower), ('\u{2c62}', '\u{2c64}', SC_Upper), ('\u{2c65}', '\u{2c66}', SC_Lower),
- ('\u{2c67}', '\u{2c67}', SC_Upper), ('\u{2c68}', '\u{2c68}', SC_Lower), ('\u{2c69}',
- '\u{2c69}', SC_Upper), ('\u{2c6a}', '\u{2c6a}', SC_Lower), ('\u{2c6b}', '\u{2c6b}',
- SC_Upper), ('\u{2c6c}', '\u{2c6c}', SC_Lower), ('\u{2c6d}', '\u{2c70}', SC_Upper),
- ('\u{2c71}', '\u{2c71}', SC_Lower), ('\u{2c72}', '\u{2c72}', SC_Upper), ('\u{2c73}',
- '\u{2c74}', SC_Lower), ('\u{2c75}', '\u{2c75}', SC_Upper), ('\u{2c76}', '\u{2c7d}',
- SC_Lower), ('\u{2c7e}', '\u{2c80}', SC_Upper), ('\u{2c81}', '\u{2c81}', SC_Lower),
- ('\u{2c82}', '\u{2c82}', SC_Upper), ('\u{2c83}', '\u{2c83}', SC_Lower), ('\u{2c84}',
- '\u{2c84}', SC_Upper), ('\u{2c85}', '\u{2c85}', SC_Lower), ('\u{2c86}', '\u{2c86}',
- SC_Upper), ('\u{2c87}', '\u{2c87}', SC_Lower), ('\u{2c88}', '\u{2c88}', SC_Upper),
- ('\u{2c89}', '\u{2c89}', SC_Lower), ('\u{2c8a}', '\u{2c8a}', SC_Upper), ('\u{2c8b}',
- '\u{2c8b}', SC_Lower), ('\u{2c8c}', '\u{2c8c}', SC_Upper), ('\u{2c8d}', '\u{2c8d}',
- SC_Lower), ('\u{2c8e}', '\u{2c8e}', SC_Upper), ('\u{2c8f}', '\u{2c8f}', SC_Lower),
- ('\u{2c90}', '\u{2c90}', SC_Upper), ('\u{2c91}', '\u{2c91}', SC_Lower), ('\u{2c92}',
- '\u{2c92}', SC_Upper), ('\u{2c93}', '\u{2c93}', SC_Lower), ('\u{2c94}', '\u{2c94}',
- SC_Upper), ('\u{2c95}', '\u{2c95}', SC_Lower), ('\u{2c96}', '\u{2c96}', SC_Upper),
- ('\u{2c97}', '\u{2c97}', SC_Lower), ('\u{2c98}', '\u{2c98}', SC_Upper), ('\u{2c99}',
- '\u{2c99}', SC_Lower), ('\u{2c9a}', '\u{2c9a}', SC_Upper), ('\u{2c9b}', '\u{2c9b}',
- SC_Lower), ('\u{2c9c}', '\u{2c9c}', SC_Upper), ('\u{2c9d}', '\u{2c9d}', SC_Lower),
- ('\u{2c9e}', '\u{2c9e}', SC_Upper), ('\u{2c9f}', '\u{2c9f}', SC_Lower), ('\u{2ca0}',
- '\u{2ca0}', SC_Upper), ('\u{2ca1}', '\u{2ca1}', SC_Lower), ('\u{2ca2}', '\u{2ca2}',
- SC_Upper), ('\u{2ca3}', '\u{2ca3}', SC_Lower), ('\u{2ca4}', '\u{2ca4}', SC_Upper),
- ('\u{2ca5}', '\u{2ca5}', SC_Lower), ('\u{2ca6}', '\u{2ca6}', SC_Upper), ('\u{2ca7}',
- '\u{2ca7}', SC_Lower), ('\u{2ca8}', '\u{2ca8}', SC_Upper), ('\u{2ca9}', '\u{2ca9}',
- SC_Lower), ('\u{2caa}', '\u{2caa}', SC_Upper), ('\u{2cab}', '\u{2cab}', SC_Lower),
- ('\u{2cac}', '\u{2cac}', SC_Upper), ('\u{2cad}', '\u{2cad}', SC_Lower), ('\u{2cae}',
- '\u{2cae}', SC_Upper), ('\u{2caf}', '\u{2caf}', SC_Lower), ('\u{2cb0}', '\u{2cb0}',
- SC_Upper), ('\u{2cb1}', '\u{2cb1}', SC_Lower), ('\u{2cb2}', '\u{2cb2}', SC_Upper),
- ('\u{2cb3}', '\u{2cb3}', SC_Lower), ('\u{2cb4}', '\u{2cb4}', SC_Upper), ('\u{2cb5}',
- '\u{2cb5}', SC_Lower), ('\u{2cb6}', '\u{2cb6}', SC_Upper), ('\u{2cb7}', '\u{2cb7}',
- SC_Lower), ('\u{2cb8}', '\u{2cb8}', SC_Upper), ('\u{2cb9}', '\u{2cb9}', SC_Lower),
- ('\u{2cba}', '\u{2cba}', SC_Upper), ('\u{2cbb}', '\u{2cbb}', SC_Lower), ('\u{2cbc}',
- '\u{2cbc}', SC_Upper), ('\u{2cbd}', '\u{2cbd}', SC_Lower), ('\u{2cbe}', '\u{2cbe}',
- SC_Upper), ('\u{2cbf}', '\u{2cbf}', SC_Lower), ('\u{2cc0}', '\u{2cc0}', SC_Upper),
- ('\u{2cc1}', '\u{2cc1}', SC_Lower), ('\u{2cc2}', '\u{2cc2}', SC_Upper), ('\u{2cc3}',
- '\u{2cc3}', SC_Lower), ('\u{2cc4}', '\u{2cc4}', SC_Upper), ('\u{2cc5}', '\u{2cc5}',
- SC_Lower), ('\u{2cc6}', '\u{2cc6}', SC_Upper), ('\u{2cc7}', '\u{2cc7}', SC_Lower),
- ('\u{2cc8}', '\u{2cc8}', SC_Upper), ('\u{2cc9}', '\u{2cc9}', SC_Lower), ('\u{2cca}',
- '\u{2cca}', SC_Upper), ('\u{2ccb}', '\u{2ccb}', SC_Lower), ('\u{2ccc}', '\u{2ccc}',
- SC_Upper), ('\u{2ccd}', '\u{2ccd}', SC_Lower), ('\u{2cce}', '\u{2cce}', SC_Upper),
- ('\u{2ccf}', '\u{2ccf}', SC_Lower), ('\u{2cd0}', '\u{2cd0}', SC_Upper), ('\u{2cd1}',
- '\u{2cd1}', SC_Lower), ('\u{2cd2}', '\u{2cd2}', SC_Upper), ('\u{2cd3}', '\u{2cd3}',
- SC_Lower), ('\u{2cd4}', '\u{2cd4}', SC_Upper), ('\u{2cd5}', '\u{2cd5}', SC_Lower),
- ('\u{2cd6}', '\u{2cd6}', SC_Upper), ('\u{2cd7}', '\u{2cd7}', SC_Lower), ('\u{2cd8}',
- '\u{2cd8}', SC_Upper), ('\u{2cd9}', '\u{2cd9}', SC_Lower), ('\u{2cda}', '\u{2cda}',
- SC_Upper), ('\u{2cdb}', '\u{2cdb}', SC_Lower), ('\u{2cdc}', '\u{2cdc}', SC_Upper),
- ('\u{2cdd}', '\u{2cdd}', SC_Lower), ('\u{2cde}', '\u{2cde}', SC_Upper), ('\u{2cdf}',
- '\u{2cdf}', SC_Lower), ('\u{2ce0}', '\u{2ce0}', SC_Upper), ('\u{2ce1}', '\u{2ce1}',
- SC_Lower), ('\u{2ce2}', '\u{2ce2}', SC_Upper), ('\u{2ce3}', '\u{2ce4}', SC_Lower),
- ('\u{2ceb}', '\u{2ceb}', SC_Upper), ('\u{2cec}', '\u{2cec}', SC_Lower), ('\u{2ced}',
- '\u{2ced}', SC_Upper), ('\u{2cee}', '\u{2cee}', SC_Lower), ('\u{2cef}', '\u{2cf1}',
- SC_Extend), ('\u{2cf2}', '\u{2cf2}', SC_Upper), ('\u{2cf3}', '\u{2cf3}', SC_Lower),
- ('\u{2d00}', '\u{2d25}', SC_Lower), ('\u{2d27}', '\u{2d27}', SC_Lower), ('\u{2d2d}',
- '\u{2d2d}', SC_Lower), ('\u{2d30}', '\u{2d67}', SC_OLetter), ('\u{2d6f}', '\u{2d6f}',
- SC_OLetter), ('\u{2d7f}', '\u{2d7f}', SC_Extend), ('\u{2d80}', '\u{2d96}', SC_OLetter),
- ('\u{2da0}', '\u{2da6}', SC_OLetter), ('\u{2da8}', '\u{2dae}', SC_OLetter), ('\u{2db0}',
- '\u{2db6}', SC_OLetter), ('\u{2db8}', '\u{2dbe}', SC_OLetter), ('\u{2dc0}', '\u{2dc6}',
- SC_OLetter), ('\u{2dc8}', '\u{2dce}', SC_OLetter), ('\u{2dd0}', '\u{2dd6}', SC_OLetter),
- ('\u{2dd8}', '\u{2dde}', SC_OLetter), ('\u{2de0}', '\u{2dff}', SC_Extend), ('\u{2e00}',
- '\u{2e0d}', SC_Close), ('\u{2e1c}', '\u{2e1d}', SC_Close), ('\u{2e20}', '\u{2e29}',
- SC_Close), ('\u{2e2e}', '\u{2e2e}', SC_STerm), ('\u{2e2f}', '\u{2e2f}', SC_OLetter),
- ('\u{2e3c}', '\u{2e3c}', SC_STerm), ('\u{2e42}', '\u{2e42}', SC_Close), ('\u{2e53}',
- '\u{2e54}', SC_STerm), ('\u{2e55}', '\u{2e5c}', SC_Close), ('\u{3000}', '\u{3000}', SC_Sp),
- ('\u{3001}', '\u{3001}', SC_SContinue), ('\u{3002}', '\u{3002}', SC_STerm), ('\u{3005}',
- '\u{3007}', SC_OLetter), ('\u{3008}', '\u{3011}', SC_Close), ('\u{3014}', '\u{301b}',
- SC_Close), ('\u{301d}', '\u{301f}', SC_Close), ('\u{3021}', '\u{3029}', SC_OLetter),
- ('\u{302a}', '\u{302f}', SC_Extend), ('\u{3031}', '\u{3035}', SC_OLetter), ('\u{3038}',
- '\u{303c}', SC_OLetter), ('\u{3041}', '\u{3096}', SC_OLetter), ('\u{3099}', '\u{309a}',
- SC_Extend), ('\u{309d}', '\u{309f}', SC_OLetter), ('\u{30a1}', '\u{30fa}', SC_OLetter),
- ('\u{30fc}', '\u{30ff}', SC_OLetter), ('\u{3105}', '\u{312f}', SC_OLetter), ('\u{3131}',
- '\u{318e}', SC_OLetter), ('\u{31a0}', '\u{31bf}', SC_OLetter), ('\u{31f0}', '\u{31ff}',
- SC_OLetter), ('\u{3400}', '\u{4dbf}', SC_OLetter), ('\u{4e00}', '\u{a48c}', SC_OLetter),
- ('\u{a4d0}', '\u{a4fd}', SC_OLetter), ('\u{a4ff}', '\u{a4ff}', SC_STerm), ('\u{a500}',
- '\u{a60c}', SC_OLetter), ('\u{a60e}', '\u{a60f}', SC_STerm), ('\u{a610}', '\u{a61f}',
- SC_OLetter), ('\u{a620}', '\u{a629}', SC_Numeric), ('\u{a62a}', '\u{a62b}', SC_OLetter),
- ('\u{a640}', '\u{a640}', SC_Upper), ('\u{a641}', '\u{a641}', SC_Lower), ('\u{a642}',
- '\u{a642}', SC_Upper), ('\u{a643}', '\u{a643}', SC_Lower), ('\u{a644}', '\u{a644}',
- SC_Upper), ('\u{a645}', '\u{a645}', SC_Lower), ('\u{a646}', '\u{a646}', SC_Upper),
- ('\u{a647}', '\u{a647}', SC_Lower), ('\u{a648}', '\u{a648}', SC_Upper), ('\u{a649}',
- '\u{a649}', SC_Lower), ('\u{a64a}', '\u{a64a}', SC_Upper), ('\u{a64b}', '\u{a64b}',
- SC_Lower), ('\u{a64c}', '\u{a64c}', SC_Upper), ('\u{a64d}', '\u{a64d}', SC_Lower),
- ('\u{a64e}', '\u{a64e}', SC_Upper), ('\u{a64f}', '\u{a64f}', SC_Lower), ('\u{a650}',
- '\u{a650}', SC_Upper), ('\u{a651}', '\u{a651}', SC_Lower), ('\u{a652}', '\u{a652}',
- SC_Upper), ('\u{a653}', '\u{a653}', SC_Lower), ('\u{a654}', '\u{a654}', SC_Upper),
- ('\u{a655}', '\u{a655}', SC_Lower), ('\u{a656}', '\u{a656}', SC_Upper), ('\u{a657}',
- '\u{a657}', SC_Lower), ('\u{a658}', '\u{a658}', SC_Upper), ('\u{a659}', '\u{a659}',
- SC_Lower), ('\u{a65a}', '\u{a65a}', SC_Upper), ('\u{a65b}', '\u{a65b}', SC_Lower),
- ('\u{a65c}', '\u{a65c}', SC_Upper), ('\u{a65d}', '\u{a65d}', SC_Lower), ('\u{a65e}',
- '\u{a65e}', SC_Upper), ('\u{a65f}', '\u{a65f}', SC_Lower), ('\u{a660}', '\u{a660}',
- SC_Upper), ('\u{a661}', '\u{a661}', SC_Lower), ('\u{a662}', '\u{a662}', SC_Upper),
- ('\u{a663}', '\u{a663}', SC_Lower), ('\u{a664}', '\u{a664}', SC_Upper), ('\u{a665}',
- '\u{a665}', SC_Lower), ('\u{a666}', '\u{a666}', SC_Upper), ('\u{a667}', '\u{a667}',
- SC_Lower), ('\u{a668}', '\u{a668}', SC_Upper), ('\u{a669}', '\u{a669}', SC_Lower),
- ('\u{a66a}', '\u{a66a}', SC_Upper), ('\u{a66b}', '\u{a66b}', SC_Lower), ('\u{a66c}',
- '\u{a66c}', SC_Upper), ('\u{a66d}', '\u{a66d}', SC_Lower), ('\u{a66e}', '\u{a66e}',
- SC_OLetter), ('\u{a66f}', '\u{a672}', SC_Extend), ('\u{a674}', '\u{a67d}', SC_Extend),
- ('\u{a67f}', '\u{a67f}', SC_OLetter), ('\u{a680}', '\u{a680}', SC_Upper), ('\u{a681}',
- '\u{a681}', SC_Lower), ('\u{a682}', '\u{a682}', SC_Upper), ('\u{a683}', '\u{a683}',
- SC_Lower), ('\u{a684}', '\u{a684}', SC_Upper), ('\u{a685}', '\u{a685}', SC_Lower),
- ('\u{a686}', '\u{a686}', SC_Upper), ('\u{a687}', '\u{a687}', SC_Lower), ('\u{a688}',
- '\u{a688}', SC_Upper), ('\u{a689}', '\u{a689}', SC_Lower), ('\u{a68a}', '\u{a68a}',
- SC_Upper), ('\u{a68b}', '\u{a68b}', SC_Lower), ('\u{a68c}', '\u{a68c}', SC_Upper),
- ('\u{a68d}', '\u{a68d}', SC_Lower), ('\u{a68e}', '\u{a68e}', SC_Upper), ('\u{a68f}',
- '\u{a68f}', SC_Lower), ('\u{a690}', '\u{a690}', SC_Upper), ('\u{a691}', '\u{a691}',
- SC_Lower), ('\u{a692}', '\u{a692}', SC_Upper), ('\u{a693}', '\u{a693}', SC_Lower),
- ('\u{a694}', '\u{a694}', SC_Upper), ('\u{a695}', '\u{a695}', SC_Lower), ('\u{a696}',
- '\u{a696}', SC_Upper), ('\u{a697}', '\u{a697}', SC_Lower), ('\u{a698}', '\u{a698}',
- SC_Upper), ('\u{a699}', '\u{a699}', SC_Lower), ('\u{a69a}', '\u{a69a}', SC_Upper),
- ('\u{a69b}', '\u{a69d}', SC_Lower), ('\u{a69e}', '\u{a69f}', SC_Extend), ('\u{a6a0}',
- '\u{a6ef}', SC_OLetter), ('\u{a6f0}', '\u{a6f1}', SC_Extend), ('\u{a6f3}', '\u{a6f3}',
- SC_STerm), ('\u{a6f7}', '\u{a6f7}', SC_STerm), ('\u{a717}', '\u{a71f}', SC_OLetter),
- ('\u{a722}', '\u{a722}', SC_Upper), ('\u{a723}', '\u{a723}', SC_Lower), ('\u{a724}',
- '\u{a724}', SC_Upper), ('\u{a725}', '\u{a725}', SC_Lower), ('\u{a726}', '\u{a726}',
- SC_Upper), ('\u{a727}', '\u{a727}', SC_Lower), ('\u{a728}', '\u{a728}', SC_Upper),
- ('\u{a729}', '\u{a729}', SC_Lower), ('\u{a72a}', '\u{a72a}', SC_Upper), ('\u{a72b}',
- '\u{a72b}', SC_Lower), ('\u{a72c}', '\u{a72c}', SC_Upper), ('\u{a72d}', '\u{a72d}',
- SC_Lower), ('\u{a72e}', '\u{a72e}', SC_Upper), ('\u{a72f}', '\u{a731}', SC_Lower),
- ('\u{a732}', '\u{a732}', SC_Upper), ('\u{a733}', '\u{a733}', SC_Lower), ('\u{a734}',
- '\u{a734}', SC_Upper), ('\u{a735}', '\u{a735}', SC_Lower), ('\u{a736}', '\u{a736}',
- SC_Upper), ('\u{a737}', '\u{a737}', SC_Lower), ('\u{a738}', '\u{a738}', SC_Upper),
- ('\u{a739}', '\u{a739}', SC_Lower), ('\u{a73a}', '\u{a73a}', SC_Upper), ('\u{a73b}',
- '\u{a73b}', SC_Lower), ('\u{a73c}', '\u{a73c}', SC_Upper), ('\u{a73d}', '\u{a73d}',
- SC_Lower), ('\u{a73e}', '\u{a73e}', SC_Upper), ('\u{a73f}', '\u{a73f}', SC_Lower),
- ('\u{a740}', '\u{a740}', SC_Upper), ('\u{a741}', '\u{a741}', SC_Lower), ('\u{a742}',
- '\u{a742}', SC_Upper), ('\u{a743}', '\u{a743}', SC_Lower), ('\u{a744}', '\u{a744}',
- SC_Upper), ('\u{a745}', '\u{a745}', SC_Lower), ('\u{a746}', '\u{a746}', SC_Upper),
- ('\u{a747}', '\u{a747}', SC_Lower), ('\u{a748}', '\u{a748}', SC_Upper), ('\u{a749}',
- '\u{a749}', SC_Lower), ('\u{a74a}', '\u{a74a}', SC_Upper), ('\u{a74b}', '\u{a74b}',
- SC_Lower), ('\u{a74c}', '\u{a74c}', SC_Upper), ('\u{a74d}', '\u{a74d}', SC_Lower),
- ('\u{a74e}', '\u{a74e}', SC_Upper), ('\u{a74f}', '\u{a74f}', SC_Lower), ('\u{a750}',
- '\u{a750}', SC_Upper), ('\u{a751}', '\u{a751}', SC_Lower), ('\u{a752}', '\u{a752}',
- SC_Upper), ('\u{a753}', '\u{a753}', SC_Lower), ('\u{a754}', '\u{a754}', SC_Upper),
- ('\u{a755}', '\u{a755}', SC_Lower), ('\u{a756}', '\u{a756}', SC_Upper), ('\u{a757}',
- '\u{a757}', SC_Lower), ('\u{a758}', '\u{a758}', SC_Upper), ('\u{a759}', '\u{a759}',
- SC_Lower), ('\u{a75a}', '\u{a75a}', SC_Upper), ('\u{a75b}', '\u{a75b}', SC_Lower),
- ('\u{a75c}', '\u{a75c}', SC_Upper), ('\u{a75d}', '\u{a75d}', SC_Lower), ('\u{a75e}',
- '\u{a75e}', SC_Upper), ('\u{a75f}', '\u{a75f}', SC_Lower), ('\u{a760}', '\u{a760}',
- SC_Upper), ('\u{a761}', '\u{a761}', SC_Lower), ('\u{a762}', '\u{a762}', SC_Upper),
- ('\u{a763}', '\u{a763}', SC_Lower), ('\u{a764}', '\u{a764}', SC_Upper), ('\u{a765}',
- '\u{a765}', SC_Lower), ('\u{a766}', '\u{a766}', SC_Upper), ('\u{a767}', '\u{a767}',
- SC_Lower), ('\u{a768}', '\u{a768}', SC_Upper), ('\u{a769}', '\u{a769}', SC_Lower),
- ('\u{a76a}', '\u{a76a}', SC_Upper), ('\u{a76b}', '\u{a76b}', SC_Lower), ('\u{a76c}',
- '\u{a76c}', SC_Upper), ('\u{a76d}', '\u{a76d}', SC_Lower), ('\u{a76e}', '\u{a76e}',
- SC_Upper), ('\u{a76f}', '\u{a778}', SC_Lower), ('\u{a779}', '\u{a779}', SC_Upper),
- ('\u{a77a}', '\u{a77a}', SC_Lower), ('\u{a77b}', '\u{a77b}', SC_Upper), ('\u{a77c}',
- '\u{a77c}', SC_Lower), ('\u{a77d}', '\u{a77e}', SC_Upper), ('\u{a77f}', '\u{a77f}',
- SC_Lower), ('\u{a780}', '\u{a780}', SC_Upper), ('\u{a781}', '\u{a781}', SC_Lower),
- ('\u{a782}', '\u{a782}', SC_Upper), ('\u{a783}', '\u{a783}', SC_Lower), ('\u{a784}',
- '\u{a784}', SC_Upper), ('\u{a785}', '\u{a785}', SC_Lower), ('\u{a786}', '\u{a786}',
- SC_Upper), ('\u{a787}', '\u{a787}', SC_Lower), ('\u{a788}', '\u{a788}', SC_OLetter),
- ('\u{a78b}', '\u{a78b}', SC_Upper), ('\u{a78c}', '\u{a78c}', SC_Lower), ('\u{a78d}',
- '\u{a78d}', SC_Upper), ('\u{a78e}', '\u{a78e}', SC_Lower), ('\u{a78f}', '\u{a78f}',
- SC_OLetter), ('\u{a790}', '\u{a790}', SC_Upper), ('\u{a791}', '\u{a791}', SC_Lower),
- ('\u{a792}', '\u{a792}', SC_Upper), ('\u{a793}', '\u{a795}', SC_Lower), ('\u{a796}',
- '\u{a796}', SC_Upper), ('\u{a797}', '\u{a797}', SC_Lower), ('\u{a798}', '\u{a798}',
- SC_Upper), ('\u{a799}', '\u{a799}', SC_Lower), ('\u{a79a}', '\u{a79a}', SC_Upper),
- ('\u{a79b}', '\u{a79b}', SC_Lower), ('\u{a79c}', '\u{a79c}', SC_Upper), ('\u{a79d}',
- '\u{a79d}', SC_Lower), ('\u{a79e}', '\u{a79e}', SC_Upper), ('\u{a79f}', '\u{a79f}',
- SC_Lower), ('\u{a7a0}', '\u{a7a0}', SC_Upper), ('\u{a7a1}', '\u{a7a1}', SC_Lower),
- ('\u{a7a2}', '\u{a7a2}', SC_Upper), ('\u{a7a3}', '\u{a7a3}', SC_Lower), ('\u{a7a4}',
- '\u{a7a4}', SC_Upper), ('\u{a7a5}', '\u{a7a5}', SC_Lower), ('\u{a7a6}', '\u{a7a6}',
- SC_Upper), ('\u{a7a7}', '\u{a7a7}', SC_Lower), ('\u{a7a8}', '\u{a7a8}', SC_Upper),
- ('\u{a7a9}', '\u{a7a9}', SC_Lower), ('\u{a7aa}', '\u{a7ae}', SC_Upper), ('\u{a7af}',
- '\u{a7af}', SC_Lower), ('\u{a7b0}', '\u{a7b4}', SC_Upper), ('\u{a7b5}', '\u{a7b5}',
- SC_Lower), ('\u{a7b6}', '\u{a7b6}', SC_Upper), ('\u{a7b7}', '\u{a7b7}', SC_Lower),
- ('\u{a7b8}', '\u{a7b8}', SC_Upper), ('\u{a7b9}', '\u{a7b9}', SC_Lower), ('\u{a7ba}',
- '\u{a7ba}', SC_Upper), ('\u{a7bb}', '\u{a7bb}', SC_Lower), ('\u{a7bc}', '\u{a7bc}',
- SC_Upper), ('\u{a7bd}', '\u{a7bd}', SC_Lower), ('\u{a7be}', '\u{a7be}', SC_Upper),
- ('\u{a7bf}', '\u{a7bf}', SC_Lower), ('\u{a7c0}', '\u{a7c0}', SC_Upper), ('\u{a7c1}',
- '\u{a7c1}', SC_Lower), ('\u{a7c2}', '\u{a7c2}', SC_Upper), ('\u{a7c3}', '\u{a7c3}',
- SC_Lower), ('\u{a7c4}', '\u{a7c7}', SC_Upper), ('\u{a7c8}', '\u{a7c8}', SC_Lower),
- ('\u{a7c9}', '\u{a7c9}', SC_Upper), ('\u{a7ca}', '\u{a7ca}', SC_Lower), ('\u{a7d0}',
- '\u{a7d0}', SC_Upper), ('\u{a7d1}', '\u{a7d1}', SC_Lower), ('\u{a7d3}', '\u{a7d3}',
- SC_Lower), ('\u{a7d5}', '\u{a7d5}', SC_Lower), ('\u{a7d6}', '\u{a7d6}', SC_Upper),
- ('\u{a7d7}', '\u{a7d7}', SC_Lower), ('\u{a7d8}', '\u{a7d8}', SC_Upper), ('\u{a7d9}',
- '\u{a7d9}', SC_Lower), ('\u{a7f2}', '\u{a7f4}', SC_OLetter), ('\u{a7f5}', '\u{a7f5}',
- SC_Upper), ('\u{a7f6}', '\u{a7f6}', SC_Lower), ('\u{a7f7}', '\u{a7f7}', SC_OLetter),
- ('\u{a7f8}', '\u{a7fa}', SC_Lower), ('\u{a7fb}', '\u{a801}', SC_OLetter), ('\u{a802}',
- '\u{a802}', SC_Extend), ('\u{a803}', '\u{a805}', SC_OLetter), ('\u{a806}', '\u{a806}',
- SC_Extend), ('\u{a807}', '\u{a80a}', SC_OLetter), ('\u{a80b}', '\u{a80b}', SC_Extend),
- ('\u{a80c}', '\u{a822}', SC_OLetter), ('\u{a823}', '\u{a827}', SC_Extend), ('\u{a82c}',
- '\u{a82c}', SC_Extend), ('\u{a840}', '\u{a873}', SC_OLetter), ('\u{a876}', '\u{a877}',
- SC_STerm), ('\u{a880}', '\u{a881}', SC_Extend), ('\u{a882}', '\u{a8b3}', SC_OLetter),
- ('\u{a8b4}', '\u{a8c5}', SC_Extend), ('\u{a8ce}', '\u{a8cf}', SC_STerm), ('\u{a8d0}',
- '\u{a8d9}', SC_Numeric), ('\u{a8e0}', '\u{a8f1}', SC_Extend), ('\u{a8f2}', '\u{a8f7}',
- SC_OLetter), ('\u{a8fb}', '\u{a8fb}', SC_OLetter), ('\u{a8fd}', '\u{a8fe}', SC_OLetter),
- ('\u{a8ff}', '\u{a8ff}', SC_Extend), ('\u{a900}', '\u{a909}', SC_Numeric), ('\u{a90a}',
- '\u{a925}', SC_OLetter), ('\u{a926}', '\u{a92d}', SC_Extend), ('\u{a92f}', '\u{a92f}',
- SC_STerm), ('\u{a930}', '\u{a946}', SC_OLetter), ('\u{a947}', '\u{a953}', SC_Extend),
- ('\u{a960}', '\u{a97c}', SC_OLetter), ('\u{a980}', '\u{a983}', SC_Extend), ('\u{a984}',
- '\u{a9b2}', SC_OLetter), ('\u{a9b3}', '\u{a9c0}', SC_Extend), ('\u{a9c8}', '\u{a9c9}',
- SC_STerm), ('\u{a9cf}', '\u{a9cf}', SC_OLetter), ('\u{a9d0}', '\u{a9d9}', SC_Numeric),
- ('\u{a9e0}', '\u{a9e4}', SC_OLetter), ('\u{a9e5}', '\u{a9e5}', SC_Extend), ('\u{a9e6}',
- '\u{a9ef}', SC_OLetter), ('\u{a9f0}', '\u{a9f9}', SC_Numeric), ('\u{a9fa}', '\u{a9fe}',
- SC_OLetter), ('\u{aa00}', '\u{aa28}', SC_OLetter), ('\u{aa29}', '\u{aa36}', SC_Extend),
- ('\u{aa40}', '\u{aa42}', SC_OLetter), ('\u{aa43}', '\u{aa43}', SC_Extend), ('\u{aa44}',
- '\u{aa4b}', SC_OLetter), ('\u{aa4c}', '\u{aa4d}', SC_Extend), ('\u{aa50}', '\u{aa59}',
- SC_Numeric), ('\u{aa5d}', '\u{aa5f}', SC_STerm), ('\u{aa60}', '\u{aa76}', SC_OLetter),
- ('\u{aa7a}', '\u{aa7a}', SC_OLetter), ('\u{aa7b}', '\u{aa7d}', SC_Extend), ('\u{aa7e}',
- '\u{aaaf}', SC_OLetter), ('\u{aab0}', '\u{aab0}', SC_Extend), ('\u{aab1}', '\u{aab1}',
- SC_OLetter), ('\u{aab2}', '\u{aab4}', SC_Extend), ('\u{aab5}', '\u{aab6}', SC_OLetter),
- ('\u{aab7}', '\u{aab8}', SC_Extend), ('\u{aab9}', '\u{aabd}', SC_OLetter), ('\u{aabe}',
- '\u{aabf}', SC_Extend), ('\u{aac0}', '\u{aac0}', SC_OLetter), ('\u{aac1}', '\u{aac1}',
- SC_Extend), ('\u{aac2}', '\u{aac2}', SC_OLetter), ('\u{aadb}', '\u{aadd}', SC_OLetter),
- ('\u{aae0}', '\u{aaea}', SC_OLetter), ('\u{aaeb}', '\u{aaef}', SC_Extend), ('\u{aaf0}',
- '\u{aaf1}', SC_STerm), ('\u{aaf2}', '\u{aaf4}', SC_OLetter), ('\u{aaf5}', '\u{aaf6}',
- SC_Extend), ('\u{ab01}', '\u{ab06}', SC_OLetter), ('\u{ab09}', '\u{ab0e}', SC_OLetter),
- ('\u{ab11}', '\u{ab16}', SC_OLetter), ('\u{ab20}', '\u{ab26}', SC_OLetter), ('\u{ab28}',
- '\u{ab2e}', SC_OLetter), ('\u{ab30}', '\u{ab5a}', SC_Lower), ('\u{ab5c}', '\u{ab68}',
- SC_Lower), ('\u{ab69}', '\u{ab69}', SC_OLetter), ('\u{ab70}', '\u{abbf}', SC_Lower),
- ('\u{abc0}', '\u{abe2}', SC_OLetter), ('\u{abe3}', '\u{abea}', SC_Extend), ('\u{abeb}',
- '\u{abeb}', SC_STerm), ('\u{abec}', '\u{abed}', SC_Extend), ('\u{abf0}', '\u{abf9}',
- SC_Numeric), ('\u{ac00}', '\u{d7a3}', SC_OLetter), ('\u{d7b0}', '\u{d7c6}', SC_OLetter),
- ('\u{d7cb}', '\u{d7fb}', SC_OLetter), ('\u{f900}', '\u{fa6d}', SC_OLetter), ('\u{fa70}',
- '\u{fad9}', SC_OLetter), ('\u{fb00}', '\u{fb06}', SC_Lower), ('\u{fb13}', '\u{fb17}',
- SC_Lower), ('\u{fb1d}', '\u{fb1d}', SC_OLetter), ('\u{fb1e}', '\u{fb1e}', SC_Extend),
- ('\u{fb1f}', '\u{fb28}', SC_OLetter), ('\u{fb2a}', '\u{fb36}', SC_OLetter), ('\u{fb38}',
- '\u{fb3c}', SC_OLetter), ('\u{fb3e}', '\u{fb3e}', SC_OLetter), ('\u{fb40}', '\u{fb41}',
- SC_OLetter), ('\u{fb43}', '\u{fb44}', SC_OLetter), ('\u{fb46}', '\u{fbb1}', SC_OLetter),
- ('\u{fbd3}', '\u{fd3d}', SC_OLetter), ('\u{fd3e}', '\u{fd3f}', SC_Close), ('\u{fd50}',
- '\u{fd8f}', SC_OLetter), ('\u{fd92}', '\u{fdc7}', SC_OLetter), ('\u{fdf0}', '\u{fdfb}',
- SC_OLetter), ('\u{fe00}', '\u{fe0f}', SC_Extend), ('\u{fe10}', '\u{fe11}', SC_SContinue),
- ('\u{fe13}', '\u{fe13}', SC_SContinue), ('\u{fe17}', '\u{fe18}', SC_Close), ('\u{fe20}',
- '\u{fe2f}', SC_Extend), ('\u{fe31}', '\u{fe32}', SC_SContinue), ('\u{fe35}', '\u{fe44}',
- SC_Close), ('\u{fe47}', '\u{fe48}', SC_Close), ('\u{fe50}', '\u{fe51}', SC_SContinue),
- ('\u{fe52}', '\u{fe52}', SC_ATerm), ('\u{fe55}', '\u{fe55}', SC_SContinue), ('\u{fe56}',
- '\u{fe57}', SC_STerm), ('\u{fe58}', '\u{fe58}', SC_SContinue), ('\u{fe59}', '\u{fe5e}',
- SC_Close), ('\u{fe63}', '\u{fe63}', SC_SContinue), ('\u{fe70}', '\u{fe74}', SC_OLetter),
- ('\u{fe76}', '\u{fefc}', SC_OLetter), ('\u{feff}', '\u{feff}', SC_Format), ('\u{ff01}',
- '\u{ff01}', SC_STerm), ('\u{ff08}', '\u{ff09}', SC_Close), ('\u{ff0c}', '\u{ff0d}',
- SC_SContinue), ('\u{ff0e}', '\u{ff0e}', SC_ATerm), ('\u{ff10}', '\u{ff19}', SC_Numeric),
- ('\u{ff1a}', '\u{ff1a}', SC_SContinue), ('\u{ff1f}', '\u{ff1f}', SC_STerm), ('\u{ff21}',
- '\u{ff3a}', SC_Upper), ('\u{ff3b}', '\u{ff3b}', SC_Close), ('\u{ff3d}', '\u{ff3d}',
- SC_Close), ('\u{ff41}', '\u{ff5a}', SC_Lower), ('\u{ff5b}', '\u{ff5b}', SC_Close),
- ('\u{ff5d}', '\u{ff5d}', SC_Close), ('\u{ff5f}', '\u{ff60}', SC_Close), ('\u{ff61}',
- '\u{ff61}', SC_STerm), ('\u{ff62}', '\u{ff63}', SC_Close), ('\u{ff64}', '\u{ff64}',
- SC_SContinue), ('\u{ff66}', '\u{ff9d}', SC_OLetter), ('\u{ff9e}', '\u{ff9f}', SC_Extend),
- ('\u{ffa0}', '\u{ffbe}', SC_OLetter), ('\u{ffc2}', '\u{ffc7}', SC_OLetter), ('\u{ffca}',
- '\u{ffcf}', SC_OLetter), ('\u{ffd2}', '\u{ffd7}', SC_OLetter), ('\u{ffda}', '\u{ffdc}',
- SC_OLetter), ('\u{fff9}', '\u{fffb}', SC_Format), ('\u{10000}', '\u{1000b}', SC_OLetter),
- ('\u{1000d}', '\u{10026}', SC_OLetter), ('\u{10028}', '\u{1003a}', SC_OLetter),
- ('\u{1003c}', '\u{1003d}', SC_OLetter), ('\u{1003f}', '\u{1004d}', SC_OLetter),
- ('\u{10050}', '\u{1005d}', SC_OLetter), ('\u{10080}', '\u{100fa}', SC_OLetter),
- ('\u{10140}', '\u{10174}', SC_OLetter), ('\u{101fd}', '\u{101fd}', SC_Extend), ('\u{10280}',
- '\u{1029c}', SC_OLetter), ('\u{102a0}', '\u{102d0}', SC_OLetter), ('\u{102e0}', '\u{102e0}',
- SC_Extend), ('\u{10300}', '\u{1031f}', SC_OLetter), ('\u{1032d}', '\u{1034a}', SC_OLetter),
- ('\u{10350}', '\u{10375}', SC_OLetter), ('\u{10376}', '\u{1037a}', SC_Extend), ('\u{10380}',
- '\u{1039d}', SC_OLetter), ('\u{103a0}', '\u{103c3}', SC_OLetter), ('\u{103c8}', '\u{103cf}',
- SC_OLetter), ('\u{103d1}', '\u{103d5}', SC_OLetter), ('\u{10400}', '\u{10427}', SC_Upper),
- ('\u{10428}', '\u{1044f}', SC_Lower), ('\u{10450}', '\u{1049d}', SC_OLetter), ('\u{104a0}',
- '\u{104a9}', SC_Numeric), ('\u{104b0}', '\u{104d3}', SC_Upper), ('\u{104d8}', '\u{104fb}',
- SC_Lower), ('\u{10500}', '\u{10527}', SC_OLetter), ('\u{10530}', '\u{10563}', SC_OLetter),
- ('\u{10570}', '\u{1057a}', SC_Upper), ('\u{1057c}', '\u{1058a}', SC_Upper), ('\u{1058c}',
- '\u{10592}', SC_Upper), ('\u{10594}', '\u{10595}', SC_Upper), ('\u{10597}', '\u{105a1}',
- SC_Lower), ('\u{105a3}', '\u{105b1}', SC_Lower), ('\u{105b3}', '\u{105b9}', SC_Lower),
- ('\u{105bb}', '\u{105bc}', SC_Lower), ('\u{10600}', '\u{10736}', SC_OLetter), ('\u{10740}',
- '\u{10755}', SC_OLetter), ('\u{10760}', '\u{10767}', SC_OLetter), ('\u{10780}', '\u{10780}',
- SC_Lower), ('\u{10781}', '\u{10782}', SC_OLetter), ('\u{10783}', '\u{10785}', SC_Lower),
- ('\u{10787}', '\u{107b0}', SC_Lower), ('\u{107b2}', '\u{107ba}', SC_Lower), ('\u{10800}',
- '\u{10805}', SC_OLetter), ('\u{10808}', '\u{10808}', SC_OLetter), ('\u{1080a}', '\u{10835}',
- SC_OLetter), ('\u{10837}', '\u{10838}', SC_OLetter), ('\u{1083c}', '\u{1083c}', SC_OLetter),
+ '\u{cf2}', SC_OLetter), ('\u{cf3}', '\u{cf3}', SC_Extend), ('\u{d00}', '\u{d03}',
+ SC_Extend), ('\u{d04}', '\u{d0c}', SC_OLetter), ('\u{d0e}', '\u{d10}', SC_OLetter),
+ ('\u{d12}', '\u{d3a}', SC_OLetter), ('\u{d3b}', '\u{d3c}', SC_Extend), ('\u{d3d}',
+ '\u{d3d}', SC_OLetter), ('\u{d3e}', '\u{d44}', SC_Extend), ('\u{d46}', '\u{d48}',
+ SC_Extend), ('\u{d4a}', '\u{d4d}', SC_Extend), ('\u{d4e}', '\u{d4e}', SC_OLetter),
+ ('\u{d54}', '\u{d56}', SC_OLetter), ('\u{d57}', '\u{d57}', SC_Extend), ('\u{d5f}',
+ '\u{d61}', SC_OLetter), ('\u{d62}', '\u{d63}', SC_Extend), ('\u{d66}', '\u{d6f}',
+ SC_Numeric), ('\u{d7a}', '\u{d7f}', SC_OLetter), ('\u{d81}', '\u{d83}', SC_Extend),
+ ('\u{d85}', '\u{d96}', SC_OLetter), ('\u{d9a}', '\u{db1}', SC_OLetter), ('\u{db3}',
+ '\u{dbb}', SC_OLetter), ('\u{dbd}', '\u{dbd}', SC_OLetter), ('\u{dc0}', '\u{dc6}',
+ SC_OLetter), ('\u{dca}', '\u{dca}', SC_Extend), ('\u{dcf}', '\u{dd4}', SC_Extend),
+ ('\u{dd6}', '\u{dd6}', SC_Extend), ('\u{dd8}', '\u{ddf}', SC_Extend), ('\u{de6}', '\u{def}',
+ SC_Numeric), ('\u{df2}', '\u{df3}', SC_Extend), ('\u{e01}', '\u{e30}', SC_OLetter),
+ ('\u{e31}', '\u{e31}', SC_Extend), ('\u{e32}', '\u{e33}', SC_OLetter), ('\u{e34}',
+ '\u{e3a}', SC_Extend), ('\u{e40}', '\u{e46}', SC_OLetter), ('\u{e47}', '\u{e4e}',
+ SC_Extend), ('\u{e50}', '\u{e59}', SC_Numeric), ('\u{e81}', '\u{e82}', SC_OLetter),
+ ('\u{e84}', '\u{e84}', SC_OLetter), ('\u{e86}', '\u{e8a}', SC_OLetter), ('\u{e8c}',
+ '\u{ea3}', SC_OLetter), ('\u{ea5}', '\u{ea5}', SC_OLetter), ('\u{ea7}', '\u{eb0}',
+ SC_OLetter), ('\u{eb1}', '\u{eb1}', SC_Extend), ('\u{eb2}', '\u{eb3}', SC_OLetter),
+ ('\u{eb4}', '\u{ebc}', SC_Extend), ('\u{ebd}', '\u{ebd}', SC_OLetter), ('\u{ec0}',
+ '\u{ec4}', SC_OLetter), ('\u{ec6}', '\u{ec6}', SC_OLetter), ('\u{ec8}', '\u{ece}',
+ SC_Extend), ('\u{ed0}', '\u{ed9}', SC_Numeric), ('\u{edc}', '\u{edf}', SC_OLetter),
+ ('\u{f00}', '\u{f00}', SC_OLetter), ('\u{f18}', '\u{f19}', SC_Extend), ('\u{f20}',
+ '\u{f29}', SC_Numeric), ('\u{f35}', '\u{f35}', SC_Extend), ('\u{f37}', '\u{f37}',
+ SC_Extend), ('\u{f39}', '\u{f39}', SC_Extend), ('\u{f3a}', '\u{f3d}', SC_Close), ('\u{f3e}',
+ '\u{f3f}', SC_Extend), ('\u{f40}', '\u{f47}', SC_OLetter), ('\u{f49}', '\u{f6c}',
+ SC_OLetter), ('\u{f71}', '\u{f84}', SC_Extend), ('\u{f86}', '\u{f87}', SC_Extend),
+ ('\u{f88}', '\u{f8c}', SC_OLetter), ('\u{f8d}', '\u{f97}', SC_Extend), ('\u{f99}',
+ '\u{fbc}', SC_Extend), ('\u{fc6}', '\u{fc6}', SC_Extend), ('\u{1000}', '\u{102a}',
+ SC_OLetter), ('\u{102b}', '\u{103e}', SC_Extend), ('\u{103f}', '\u{103f}', SC_OLetter),
+ ('\u{1040}', '\u{1049}', SC_Numeric), ('\u{104a}', '\u{104b}', SC_STerm), ('\u{1050}',
+ '\u{1055}', SC_OLetter), ('\u{1056}', '\u{1059}', SC_Extend), ('\u{105a}', '\u{105d}',
+ SC_OLetter), ('\u{105e}', '\u{1060}', SC_Extend), ('\u{1061}', '\u{1061}', SC_OLetter),
+ ('\u{1062}', '\u{1064}', SC_Extend), ('\u{1065}', '\u{1066}', SC_OLetter), ('\u{1067}',
+ '\u{106d}', SC_Extend), ('\u{106e}', '\u{1070}', SC_OLetter), ('\u{1071}', '\u{1074}',
+ SC_Extend), ('\u{1075}', '\u{1081}', SC_OLetter), ('\u{1082}', '\u{108d}', SC_Extend),
+ ('\u{108e}', '\u{108e}', SC_OLetter), ('\u{108f}', '\u{108f}', SC_Extend), ('\u{1090}',
+ '\u{1099}', SC_Numeric), ('\u{109a}', '\u{109d}', SC_Extend), ('\u{10a0}', '\u{10c5}',
+ SC_Upper), ('\u{10c7}', '\u{10c7}', SC_Upper), ('\u{10cd}', '\u{10cd}', SC_Upper),
+ ('\u{10d0}', '\u{10fa}', SC_OLetter), ('\u{10fc}', '\u{10fc}', SC_Lower), ('\u{10fd}',
+ '\u{1248}', SC_OLetter), ('\u{124a}', '\u{124d}', SC_OLetter), ('\u{1250}', '\u{1256}',
+ SC_OLetter), ('\u{1258}', '\u{1258}', SC_OLetter), ('\u{125a}', '\u{125d}', SC_OLetter),
+ ('\u{1260}', '\u{1288}', SC_OLetter), ('\u{128a}', '\u{128d}', SC_OLetter), ('\u{1290}',
+ '\u{12b0}', SC_OLetter), ('\u{12b2}', '\u{12b5}', SC_OLetter), ('\u{12b8}', '\u{12be}',
+ SC_OLetter), ('\u{12c0}', '\u{12c0}', SC_OLetter), ('\u{12c2}', '\u{12c5}', SC_OLetter),
+ ('\u{12c8}', '\u{12d6}', SC_OLetter), ('\u{12d8}', '\u{1310}', SC_OLetter), ('\u{1312}',
+ '\u{1315}', SC_OLetter), ('\u{1318}', '\u{135a}', SC_OLetter), ('\u{135d}', '\u{135f}',
+ SC_Extend), ('\u{1362}', '\u{1362}', SC_STerm), ('\u{1367}', '\u{1368}', SC_STerm),
+ ('\u{1380}', '\u{138f}', SC_OLetter), ('\u{13a0}', '\u{13f5}', SC_Upper), ('\u{13f8}',
+ '\u{13fd}', SC_Lower), ('\u{1401}', '\u{166c}', SC_OLetter), ('\u{166e}', '\u{166e}',
+ SC_STerm), ('\u{166f}', '\u{167f}', SC_OLetter), ('\u{1680}', '\u{1680}', SC_Sp),
+ ('\u{1681}', '\u{169a}', SC_OLetter), ('\u{169b}', '\u{169c}', SC_Close), ('\u{16a0}',
+ '\u{16ea}', SC_OLetter), ('\u{16ee}', '\u{16f8}', SC_OLetter), ('\u{1700}', '\u{1711}',
+ SC_OLetter), ('\u{1712}', '\u{1715}', SC_Extend), ('\u{171f}', '\u{1731}', SC_OLetter),
+ ('\u{1732}', '\u{1734}', SC_Extend), ('\u{1735}', '\u{1736}', SC_STerm), ('\u{1740}',
+ '\u{1751}', SC_OLetter), ('\u{1752}', '\u{1753}', SC_Extend), ('\u{1760}', '\u{176c}',
+ SC_OLetter), ('\u{176e}', '\u{1770}', SC_OLetter), ('\u{1772}', '\u{1773}', SC_Extend),
+ ('\u{1780}', '\u{17b3}', SC_OLetter), ('\u{17b4}', '\u{17d3}', SC_Extend), ('\u{17d7}',
+ '\u{17d7}', SC_OLetter), ('\u{17dc}', '\u{17dc}', SC_OLetter), ('\u{17dd}', '\u{17dd}',
+ SC_Extend), ('\u{17e0}', '\u{17e9}', SC_Numeric), ('\u{1802}', '\u{1802}', SC_SContinue),
+ ('\u{1803}', '\u{1803}', SC_STerm), ('\u{1808}', '\u{1808}', SC_SContinue), ('\u{1809}',
+ '\u{1809}', SC_STerm), ('\u{180b}', '\u{180d}', SC_Extend), ('\u{180e}', '\u{180e}',
+ SC_Format), ('\u{180f}', '\u{180f}', SC_Extend), ('\u{1810}', '\u{1819}', SC_Numeric),
+ ('\u{1820}', '\u{1878}', SC_OLetter), ('\u{1880}', '\u{1884}', SC_OLetter), ('\u{1885}',
+ '\u{1886}', SC_Extend), ('\u{1887}', '\u{18a8}', SC_OLetter), ('\u{18a9}', '\u{18a9}',
+ SC_Extend), ('\u{18aa}', '\u{18aa}', SC_OLetter), ('\u{18b0}', '\u{18f5}', SC_OLetter),
+ ('\u{1900}', '\u{191e}', SC_OLetter), ('\u{1920}', '\u{192b}', SC_Extend), ('\u{1930}',
+ '\u{193b}', SC_Extend), ('\u{1944}', '\u{1945}', SC_STerm), ('\u{1946}', '\u{194f}',
+ SC_Numeric), ('\u{1950}', '\u{196d}', SC_OLetter), ('\u{1970}', '\u{1974}', SC_OLetter),
+ ('\u{1980}', '\u{19ab}', SC_OLetter), ('\u{19b0}', '\u{19c9}', SC_OLetter), ('\u{19d0}',
+ '\u{19d9}', SC_Numeric), ('\u{1a00}', '\u{1a16}', SC_OLetter), ('\u{1a17}', '\u{1a1b}',
+ SC_Extend), ('\u{1a20}', '\u{1a54}', SC_OLetter), ('\u{1a55}', '\u{1a5e}', SC_Extend),
+ ('\u{1a60}', '\u{1a7c}', SC_Extend), ('\u{1a7f}', '\u{1a7f}', SC_Extend), ('\u{1a80}',
+ '\u{1a89}', SC_Numeric), ('\u{1a90}', '\u{1a99}', SC_Numeric), ('\u{1aa7}', '\u{1aa7}',
+ SC_OLetter), ('\u{1aa8}', '\u{1aab}', SC_STerm), ('\u{1ab0}', '\u{1ace}', SC_Extend),
+ ('\u{1b00}', '\u{1b04}', SC_Extend), ('\u{1b05}', '\u{1b33}', SC_OLetter), ('\u{1b34}',
+ '\u{1b44}', SC_Extend), ('\u{1b45}', '\u{1b4c}', SC_OLetter), ('\u{1b50}', '\u{1b59}',
+ SC_Numeric), ('\u{1b5a}', '\u{1b5b}', SC_STerm), ('\u{1b5e}', '\u{1b5f}', SC_STerm),
+ ('\u{1b6b}', '\u{1b73}', SC_Extend), ('\u{1b7d}', '\u{1b7e}', SC_STerm), ('\u{1b80}',
+ '\u{1b82}', SC_Extend), ('\u{1b83}', '\u{1ba0}', SC_OLetter), ('\u{1ba1}', '\u{1bad}',
+ SC_Extend), ('\u{1bae}', '\u{1baf}', SC_OLetter), ('\u{1bb0}', '\u{1bb9}', SC_Numeric),
+ ('\u{1bba}', '\u{1be5}', SC_OLetter), ('\u{1be6}', '\u{1bf3}', SC_Extend), ('\u{1c00}',
+ '\u{1c23}', SC_OLetter), ('\u{1c24}', '\u{1c37}', SC_Extend), ('\u{1c3b}', '\u{1c3c}',
+ SC_STerm), ('\u{1c40}', '\u{1c49}', SC_Numeric), ('\u{1c4d}', '\u{1c4f}', SC_OLetter),
+ ('\u{1c50}', '\u{1c59}', SC_Numeric), ('\u{1c5a}', '\u{1c7d}', SC_OLetter), ('\u{1c7e}',
+ '\u{1c7f}', SC_STerm), ('\u{1c80}', '\u{1c88}', SC_Lower), ('\u{1c90}', '\u{1cba}',
+ SC_OLetter), ('\u{1cbd}', '\u{1cbf}', SC_OLetter), ('\u{1cd0}', '\u{1cd2}', SC_Extend),
+ ('\u{1cd4}', '\u{1ce8}', SC_Extend), ('\u{1ce9}', '\u{1cec}', SC_OLetter), ('\u{1ced}',
+ '\u{1ced}', SC_Extend), ('\u{1cee}', '\u{1cf3}', SC_OLetter), ('\u{1cf4}', '\u{1cf4}',
+ SC_Extend), ('\u{1cf5}', '\u{1cf6}', SC_OLetter), ('\u{1cf7}', '\u{1cf9}', SC_Extend),
+ ('\u{1cfa}', '\u{1cfa}', SC_OLetter), ('\u{1d00}', '\u{1dbf}', SC_Lower), ('\u{1dc0}',
+ '\u{1dff}', SC_Extend), ('\u{1e00}', '\u{1e00}', SC_Upper), ('\u{1e01}', '\u{1e01}',
+ SC_Lower), ('\u{1e02}', '\u{1e02}', SC_Upper), ('\u{1e03}', '\u{1e03}', SC_Lower),
+ ('\u{1e04}', '\u{1e04}', SC_Upper), ('\u{1e05}', '\u{1e05}', SC_Lower), ('\u{1e06}',
+ '\u{1e06}', SC_Upper), ('\u{1e07}', '\u{1e07}', SC_Lower), ('\u{1e08}', '\u{1e08}',
+ SC_Upper), ('\u{1e09}', '\u{1e09}', SC_Lower), ('\u{1e0a}', '\u{1e0a}', SC_Upper),
+ ('\u{1e0b}', '\u{1e0b}', SC_Lower), ('\u{1e0c}', '\u{1e0c}', SC_Upper), ('\u{1e0d}',
+ '\u{1e0d}', SC_Lower), ('\u{1e0e}', '\u{1e0e}', SC_Upper), ('\u{1e0f}', '\u{1e0f}',
+ SC_Lower), ('\u{1e10}', '\u{1e10}', SC_Upper), ('\u{1e11}', '\u{1e11}', SC_Lower),
+ ('\u{1e12}', '\u{1e12}', SC_Upper), ('\u{1e13}', '\u{1e13}', SC_Lower), ('\u{1e14}',
+ '\u{1e14}', SC_Upper), ('\u{1e15}', '\u{1e15}', SC_Lower), ('\u{1e16}', '\u{1e16}',
+ SC_Upper), ('\u{1e17}', '\u{1e17}', SC_Lower), ('\u{1e18}', '\u{1e18}', SC_Upper),
+ ('\u{1e19}', '\u{1e19}', SC_Lower), ('\u{1e1a}', '\u{1e1a}', SC_Upper), ('\u{1e1b}',
+ '\u{1e1b}', SC_Lower), ('\u{1e1c}', '\u{1e1c}', SC_Upper), ('\u{1e1d}', '\u{1e1d}',
+ SC_Lower), ('\u{1e1e}', '\u{1e1e}', SC_Upper), ('\u{1e1f}', '\u{1e1f}', SC_Lower),
+ ('\u{1e20}', '\u{1e20}', SC_Upper), ('\u{1e21}', '\u{1e21}', SC_Lower), ('\u{1e22}',
+ '\u{1e22}', SC_Upper), ('\u{1e23}', '\u{1e23}', SC_Lower), ('\u{1e24}', '\u{1e24}',
+ SC_Upper), ('\u{1e25}', '\u{1e25}', SC_Lower), ('\u{1e26}', '\u{1e26}', SC_Upper),
+ ('\u{1e27}', '\u{1e27}', SC_Lower), ('\u{1e28}', '\u{1e28}', SC_Upper), ('\u{1e29}',
+ '\u{1e29}', SC_Lower), ('\u{1e2a}', '\u{1e2a}', SC_Upper), ('\u{1e2b}', '\u{1e2b}',
+ SC_Lower), ('\u{1e2c}', '\u{1e2c}', SC_Upper), ('\u{1e2d}', '\u{1e2d}', SC_Lower),
+ ('\u{1e2e}', '\u{1e2e}', SC_Upper), ('\u{1e2f}', '\u{1e2f}', SC_Lower), ('\u{1e30}',
+ '\u{1e30}', SC_Upper), ('\u{1e31}', '\u{1e31}', SC_Lower), ('\u{1e32}', '\u{1e32}',
+ SC_Upper), ('\u{1e33}', '\u{1e33}', SC_Lower), ('\u{1e34}', '\u{1e34}', SC_Upper),
+ ('\u{1e35}', '\u{1e35}', SC_Lower), ('\u{1e36}', '\u{1e36}', SC_Upper), ('\u{1e37}',
+ '\u{1e37}', SC_Lower), ('\u{1e38}', '\u{1e38}', SC_Upper), ('\u{1e39}', '\u{1e39}',
+ SC_Lower), ('\u{1e3a}', '\u{1e3a}', SC_Upper), ('\u{1e3b}', '\u{1e3b}', SC_Lower),
+ ('\u{1e3c}', '\u{1e3c}', SC_Upper), ('\u{1e3d}', '\u{1e3d}', SC_Lower), ('\u{1e3e}',
+ '\u{1e3e}', SC_Upper), ('\u{1e3f}', '\u{1e3f}', SC_Lower), ('\u{1e40}', '\u{1e40}',
+ SC_Upper), ('\u{1e41}', '\u{1e41}', SC_Lower), ('\u{1e42}', '\u{1e42}', SC_Upper),
+ ('\u{1e43}', '\u{1e43}', SC_Lower), ('\u{1e44}', '\u{1e44}', SC_Upper), ('\u{1e45}',
+ '\u{1e45}', SC_Lower), ('\u{1e46}', '\u{1e46}', SC_Upper), ('\u{1e47}', '\u{1e47}',
+ SC_Lower), ('\u{1e48}', '\u{1e48}', SC_Upper), ('\u{1e49}', '\u{1e49}', SC_Lower),
+ ('\u{1e4a}', '\u{1e4a}', SC_Upper), ('\u{1e4b}', '\u{1e4b}', SC_Lower), ('\u{1e4c}',
+ '\u{1e4c}', SC_Upper), ('\u{1e4d}', '\u{1e4d}', SC_Lower), ('\u{1e4e}', '\u{1e4e}',
+ SC_Upper), ('\u{1e4f}', '\u{1e4f}', SC_Lower), ('\u{1e50}', '\u{1e50}', SC_Upper),
+ ('\u{1e51}', '\u{1e51}', SC_Lower), ('\u{1e52}', '\u{1e52}', SC_Upper), ('\u{1e53}',
+ '\u{1e53}', SC_Lower), ('\u{1e54}', '\u{1e54}', SC_Upper), ('\u{1e55}', '\u{1e55}',
+ SC_Lower), ('\u{1e56}', '\u{1e56}', SC_Upper), ('\u{1e57}', '\u{1e57}', SC_Lower),
+ ('\u{1e58}', '\u{1e58}', SC_Upper), ('\u{1e59}', '\u{1e59}', SC_Lower), ('\u{1e5a}',
+ '\u{1e5a}', SC_Upper), ('\u{1e5b}', '\u{1e5b}', SC_Lower), ('\u{1e5c}', '\u{1e5c}',
+ SC_Upper), ('\u{1e5d}', '\u{1e5d}', SC_Lower), ('\u{1e5e}', '\u{1e5e}', SC_Upper),
+ ('\u{1e5f}', '\u{1e5f}', SC_Lower), ('\u{1e60}', '\u{1e60}', SC_Upper), ('\u{1e61}',
+ '\u{1e61}', SC_Lower), ('\u{1e62}', '\u{1e62}', SC_Upper), ('\u{1e63}', '\u{1e63}',
+ SC_Lower), ('\u{1e64}', '\u{1e64}', SC_Upper), ('\u{1e65}', '\u{1e65}', SC_Lower),
+ ('\u{1e66}', '\u{1e66}', SC_Upper), ('\u{1e67}', '\u{1e67}', SC_Lower), ('\u{1e68}',
+ '\u{1e68}', SC_Upper), ('\u{1e69}', '\u{1e69}', SC_Lower), ('\u{1e6a}', '\u{1e6a}',
+ SC_Upper), ('\u{1e6b}', '\u{1e6b}', SC_Lower), ('\u{1e6c}', '\u{1e6c}', SC_Upper),
+ ('\u{1e6d}', '\u{1e6d}', SC_Lower), ('\u{1e6e}', '\u{1e6e}', SC_Upper), ('\u{1e6f}',
+ '\u{1e6f}', SC_Lower), ('\u{1e70}', '\u{1e70}', SC_Upper), ('\u{1e71}', '\u{1e71}',
+ SC_Lower), ('\u{1e72}', '\u{1e72}', SC_Upper), ('\u{1e73}', '\u{1e73}', SC_Lower),
+ ('\u{1e74}', '\u{1e74}', SC_Upper), ('\u{1e75}', '\u{1e75}', SC_Lower), ('\u{1e76}',
+ '\u{1e76}', SC_Upper), ('\u{1e77}', '\u{1e77}', SC_Lower), ('\u{1e78}', '\u{1e78}',
+ SC_Upper), ('\u{1e79}', '\u{1e79}', SC_Lower), ('\u{1e7a}', '\u{1e7a}', SC_Upper),
+ ('\u{1e7b}', '\u{1e7b}', SC_Lower), ('\u{1e7c}', '\u{1e7c}', SC_Upper), ('\u{1e7d}',
+ '\u{1e7d}', SC_Lower), ('\u{1e7e}', '\u{1e7e}', SC_Upper), ('\u{1e7f}', '\u{1e7f}',
+ SC_Lower), ('\u{1e80}', '\u{1e80}', SC_Upper), ('\u{1e81}', '\u{1e81}', SC_Lower),
+ ('\u{1e82}', '\u{1e82}', SC_Upper), ('\u{1e83}', '\u{1e83}', SC_Lower), ('\u{1e84}',
+ '\u{1e84}', SC_Upper), ('\u{1e85}', '\u{1e85}', SC_Lower), ('\u{1e86}', '\u{1e86}',
+ SC_Upper), ('\u{1e87}', '\u{1e87}', SC_Lower), ('\u{1e88}', '\u{1e88}', SC_Upper),
+ ('\u{1e89}', '\u{1e89}', SC_Lower), ('\u{1e8a}', '\u{1e8a}', SC_Upper), ('\u{1e8b}',
+ '\u{1e8b}', SC_Lower), ('\u{1e8c}', '\u{1e8c}', SC_Upper), ('\u{1e8d}', '\u{1e8d}',
+ SC_Lower), ('\u{1e8e}', '\u{1e8e}', SC_Upper), ('\u{1e8f}', '\u{1e8f}', SC_Lower),
+ ('\u{1e90}', '\u{1e90}', SC_Upper), ('\u{1e91}', '\u{1e91}', SC_Lower), ('\u{1e92}',
+ '\u{1e92}', SC_Upper), ('\u{1e93}', '\u{1e93}', SC_Lower), ('\u{1e94}', '\u{1e94}',
+ SC_Upper), ('\u{1e95}', '\u{1e9d}', SC_Lower), ('\u{1e9e}', '\u{1e9e}', SC_Upper),
+ ('\u{1e9f}', '\u{1e9f}', SC_Lower), ('\u{1ea0}', '\u{1ea0}', SC_Upper), ('\u{1ea1}',
+ '\u{1ea1}', SC_Lower), ('\u{1ea2}', '\u{1ea2}', SC_Upper), ('\u{1ea3}', '\u{1ea3}',
+ SC_Lower), ('\u{1ea4}', '\u{1ea4}', SC_Upper), ('\u{1ea5}', '\u{1ea5}', SC_Lower),
+ ('\u{1ea6}', '\u{1ea6}', SC_Upper), ('\u{1ea7}', '\u{1ea7}', SC_Lower), ('\u{1ea8}',
+ '\u{1ea8}', SC_Upper), ('\u{1ea9}', '\u{1ea9}', SC_Lower), ('\u{1eaa}', '\u{1eaa}',
+ SC_Upper), ('\u{1eab}', '\u{1eab}', SC_Lower), ('\u{1eac}', '\u{1eac}', SC_Upper),
+ ('\u{1ead}', '\u{1ead}', SC_Lower), ('\u{1eae}', '\u{1eae}', SC_Upper), ('\u{1eaf}',
+ '\u{1eaf}', SC_Lower), ('\u{1eb0}', '\u{1eb0}', SC_Upper), ('\u{1eb1}', '\u{1eb1}',
+ SC_Lower), ('\u{1eb2}', '\u{1eb2}', SC_Upper), ('\u{1eb3}', '\u{1eb3}', SC_Lower),
+ ('\u{1eb4}', '\u{1eb4}', SC_Upper), ('\u{1eb5}', '\u{1eb5}', SC_Lower), ('\u{1eb6}',
+ '\u{1eb6}', SC_Upper), ('\u{1eb7}', '\u{1eb7}', SC_Lower), ('\u{1eb8}', '\u{1eb8}',
+ SC_Upper), ('\u{1eb9}', '\u{1eb9}', SC_Lower), ('\u{1eba}', '\u{1eba}', SC_Upper),
+ ('\u{1ebb}', '\u{1ebb}', SC_Lower), ('\u{1ebc}', '\u{1ebc}', SC_Upper), ('\u{1ebd}',
+ '\u{1ebd}', SC_Lower), ('\u{1ebe}', '\u{1ebe}', SC_Upper), ('\u{1ebf}', '\u{1ebf}',
+ SC_Lower), ('\u{1ec0}', '\u{1ec0}', SC_Upper), ('\u{1ec1}', '\u{1ec1}', SC_Lower),
+ ('\u{1ec2}', '\u{1ec2}', SC_Upper), ('\u{1ec3}', '\u{1ec3}', SC_Lower), ('\u{1ec4}',
+ '\u{1ec4}', SC_Upper), ('\u{1ec5}', '\u{1ec5}', SC_Lower), ('\u{1ec6}', '\u{1ec6}',
+ SC_Upper), ('\u{1ec7}', '\u{1ec7}', SC_Lower), ('\u{1ec8}', '\u{1ec8}', SC_Upper),
+ ('\u{1ec9}', '\u{1ec9}', SC_Lower), ('\u{1eca}', '\u{1eca}', SC_Upper), ('\u{1ecb}',
+ '\u{1ecb}', SC_Lower), ('\u{1ecc}', '\u{1ecc}', SC_Upper), ('\u{1ecd}', '\u{1ecd}',
+ SC_Lower), ('\u{1ece}', '\u{1ece}', SC_Upper), ('\u{1ecf}', '\u{1ecf}', SC_Lower),
+ ('\u{1ed0}', '\u{1ed0}', SC_Upper), ('\u{1ed1}', '\u{1ed1}', SC_Lower), ('\u{1ed2}',
+ '\u{1ed2}', SC_Upper), ('\u{1ed3}', '\u{1ed3}', SC_Lower), ('\u{1ed4}', '\u{1ed4}',
+ SC_Upper), ('\u{1ed5}', '\u{1ed5}', SC_Lower), ('\u{1ed6}', '\u{1ed6}', SC_Upper),
+ ('\u{1ed7}', '\u{1ed7}', SC_Lower), ('\u{1ed8}', '\u{1ed8}', SC_Upper), ('\u{1ed9}',
+ '\u{1ed9}', SC_Lower), ('\u{1eda}', '\u{1eda}', SC_Upper), ('\u{1edb}', '\u{1edb}',
+ SC_Lower), ('\u{1edc}', '\u{1edc}', SC_Upper), ('\u{1edd}', '\u{1edd}', SC_Lower),
+ ('\u{1ede}', '\u{1ede}', SC_Upper), ('\u{1edf}', '\u{1edf}', SC_Lower), ('\u{1ee0}',
+ '\u{1ee0}', SC_Upper), ('\u{1ee1}', '\u{1ee1}', SC_Lower), ('\u{1ee2}', '\u{1ee2}',
+ SC_Upper), ('\u{1ee3}', '\u{1ee3}', SC_Lower), ('\u{1ee4}', '\u{1ee4}', SC_Upper),
+ ('\u{1ee5}', '\u{1ee5}', SC_Lower), ('\u{1ee6}', '\u{1ee6}', SC_Upper), ('\u{1ee7}',
+ '\u{1ee7}', SC_Lower), ('\u{1ee8}', '\u{1ee8}', SC_Upper), ('\u{1ee9}', '\u{1ee9}',
+ SC_Lower), ('\u{1eea}', '\u{1eea}', SC_Upper), ('\u{1eeb}', '\u{1eeb}', SC_Lower),
+ ('\u{1eec}', '\u{1eec}', SC_Upper), ('\u{1eed}', '\u{1eed}', SC_Lower), ('\u{1eee}',
+ '\u{1eee}', SC_Upper), ('\u{1eef}', '\u{1eef}', SC_Lower), ('\u{1ef0}', '\u{1ef0}',
+ SC_Upper), ('\u{1ef1}', '\u{1ef1}', SC_Lower), ('\u{1ef2}', '\u{1ef2}', SC_Upper),
+ ('\u{1ef3}', '\u{1ef3}', SC_Lower), ('\u{1ef4}', '\u{1ef4}', SC_Upper), ('\u{1ef5}',
+ '\u{1ef5}', SC_Lower), ('\u{1ef6}', '\u{1ef6}', SC_Upper), ('\u{1ef7}', '\u{1ef7}',
+ SC_Lower), ('\u{1ef8}', '\u{1ef8}', SC_Upper), ('\u{1ef9}', '\u{1ef9}', SC_Lower),
+ ('\u{1efa}', '\u{1efa}', SC_Upper), ('\u{1efb}', '\u{1efb}', SC_Lower), ('\u{1efc}',
+ '\u{1efc}', SC_Upper), ('\u{1efd}', '\u{1efd}', SC_Lower), ('\u{1efe}', '\u{1efe}',
+ SC_Upper), ('\u{1eff}', '\u{1f07}', SC_Lower), ('\u{1f08}', '\u{1f0f}', SC_Upper),
+ ('\u{1f10}', '\u{1f15}', SC_Lower), ('\u{1f18}', '\u{1f1d}', SC_Upper), ('\u{1f20}',
+ '\u{1f27}', SC_Lower), ('\u{1f28}', '\u{1f2f}', SC_Upper), ('\u{1f30}', '\u{1f37}',
+ SC_Lower), ('\u{1f38}', '\u{1f3f}', SC_Upper), ('\u{1f40}', '\u{1f45}', SC_Lower),
+ ('\u{1f48}', '\u{1f4d}', SC_Upper), ('\u{1f50}', '\u{1f57}', SC_Lower), ('\u{1f59}',
+ '\u{1f59}', SC_Upper), ('\u{1f5b}', '\u{1f5b}', SC_Upper), ('\u{1f5d}', '\u{1f5d}',
+ SC_Upper), ('\u{1f5f}', '\u{1f5f}', SC_Upper), ('\u{1f60}', '\u{1f67}', SC_Lower),
+ ('\u{1f68}', '\u{1f6f}', SC_Upper), ('\u{1f70}', '\u{1f7d}', SC_Lower), ('\u{1f80}',
+ '\u{1f87}', SC_Lower), ('\u{1f88}', '\u{1f8f}', SC_Upper), ('\u{1f90}', '\u{1f97}',
+ SC_Lower), ('\u{1f98}', '\u{1f9f}', SC_Upper), ('\u{1fa0}', '\u{1fa7}', SC_Lower),
+ ('\u{1fa8}', '\u{1faf}', SC_Upper), ('\u{1fb0}', '\u{1fb4}', SC_Lower), ('\u{1fb6}',
+ '\u{1fb7}', SC_Lower), ('\u{1fb8}', '\u{1fbc}', SC_Upper), ('\u{1fbe}', '\u{1fbe}',
+ SC_Lower), ('\u{1fc2}', '\u{1fc4}', SC_Lower), ('\u{1fc6}', '\u{1fc7}', SC_Lower),
+ ('\u{1fc8}', '\u{1fcc}', SC_Upper), ('\u{1fd0}', '\u{1fd3}', SC_Lower), ('\u{1fd6}',
+ '\u{1fd7}', SC_Lower), ('\u{1fd8}', '\u{1fdb}', SC_Upper), ('\u{1fe0}', '\u{1fe7}',
+ SC_Lower), ('\u{1fe8}', '\u{1fec}', SC_Upper), ('\u{1ff2}', '\u{1ff4}', SC_Lower),
+ ('\u{1ff6}', '\u{1ff7}', SC_Lower), ('\u{1ff8}', '\u{1ffc}', SC_Upper), ('\u{2000}',
+ '\u{200a}', SC_Sp), ('\u{200b}', '\u{200b}', SC_Format), ('\u{200c}', '\u{200d}',
+ SC_Extend), ('\u{200e}', '\u{200f}', SC_Format), ('\u{2013}', '\u{2014}', SC_SContinue),
+ ('\u{2018}', '\u{201f}', SC_Close), ('\u{2024}', '\u{2024}', SC_ATerm), ('\u{2028}',
+ '\u{2029}', SC_Sep), ('\u{202a}', '\u{202e}', SC_Format), ('\u{202f}', '\u{202f}', SC_Sp),
+ ('\u{2039}', '\u{203a}', SC_Close), ('\u{203c}', '\u{203d}', SC_STerm), ('\u{2045}',
+ '\u{2046}', SC_Close), ('\u{2047}', '\u{2049}', SC_STerm), ('\u{205f}', '\u{205f}', SC_Sp),
+ ('\u{2060}', '\u{2064}', SC_Format), ('\u{2066}', '\u{206f}', SC_Format), ('\u{2071}',
+ '\u{2071}', SC_Lower), ('\u{207d}', '\u{207e}', SC_Close), ('\u{207f}', '\u{207f}',
+ SC_Lower), ('\u{208d}', '\u{208e}', SC_Close), ('\u{2090}', '\u{209c}', SC_Lower),
+ ('\u{20d0}', '\u{20f0}', SC_Extend), ('\u{2102}', '\u{2102}', SC_Upper), ('\u{2107}',
+ '\u{2107}', SC_Upper), ('\u{210a}', '\u{210a}', SC_Lower), ('\u{210b}', '\u{210d}',
+ SC_Upper), ('\u{210e}', '\u{210f}', SC_Lower), ('\u{2110}', '\u{2112}', SC_Upper),
+ ('\u{2113}', '\u{2113}', SC_Lower), ('\u{2115}', '\u{2115}', SC_Upper), ('\u{2119}',
+ '\u{211d}', SC_Upper), ('\u{2124}', '\u{2124}', SC_Upper), ('\u{2126}', '\u{2126}',
+ SC_Upper), ('\u{2128}', '\u{2128}', SC_Upper), ('\u{212a}', '\u{212d}', SC_Upper),
+ ('\u{212f}', '\u{212f}', SC_Lower), ('\u{2130}', '\u{2133}', SC_Upper), ('\u{2134}',
+ '\u{2134}', SC_Lower), ('\u{2135}', '\u{2138}', SC_OLetter), ('\u{2139}', '\u{2139}',
+ SC_Lower), ('\u{213c}', '\u{213d}', SC_Lower), ('\u{213e}', '\u{213f}', SC_Upper),
+ ('\u{2145}', '\u{2145}', SC_Upper), ('\u{2146}', '\u{2149}', SC_Lower), ('\u{214e}',
+ '\u{214e}', SC_Lower), ('\u{2160}', '\u{216f}', SC_Upper), ('\u{2170}', '\u{217f}',
+ SC_Lower), ('\u{2180}', '\u{2182}', SC_OLetter), ('\u{2183}', '\u{2183}', SC_Upper),
+ ('\u{2184}', '\u{2184}', SC_Lower), ('\u{2185}', '\u{2188}', SC_OLetter), ('\u{2308}',
+ '\u{230b}', SC_Close), ('\u{2329}', '\u{232a}', SC_Close), ('\u{24b6}', '\u{24cf}',
+ SC_Upper), ('\u{24d0}', '\u{24e9}', SC_Lower), ('\u{275b}', '\u{2760}', SC_Close),
+ ('\u{2768}', '\u{2775}', SC_Close), ('\u{27c5}', '\u{27c6}', SC_Close), ('\u{27e6}',
+ '\u{27ef}', SC_Close), ('\u{2983}', '\u{2998}', SC_Close), ('\u{29d8}', '\u{29db}',
+ SC_Close), ('\u{29fc}', '\u{29fd}', SC_Close), ('\u{2c00}', '\u{2c2f}', SC_Upper),
+ ('\u{2c30}', '\u{2c5f}', SC_Lower), ('\u{2c60}', '\u{2c60}', SC_Upper), ('\u{2c61}',
+ '\u{2c61}', SC_Lower), ('\u{2c62}', '\u{2c64}', SC_Upper), ('\u{2c65}', '\u{2c66}',
+ SC_Lower), ('\u{2c67}', '\u{2c67}', SC_Upper), ('\u{2c68}', '\u{2c68}', SC_Lower),
+ ('\u{2c69}', '\u{2c69}', SC_Upper), ('\u{2c6a}', '\u{2c6a}', SC_Lower), ('\u{2c6b}',
+ '\u{2c6b}', SC_Upper), ('\u{2c6c}', '\u{2c6c}', SC_Lower), ('\u{2c6d}', '\u{2c70}',
+ SC_Upper), ('\u{2c71}', '\u{2c71}', SC_Lower), ('\u{2c72}', '\u{2c72}', SC_Upper),
+ ('\u{2c73}', '\u{2c74}', SC_Lower), ('\u{2c75}', '\u{2c75}', SC_Upper), ('\u{2c76}',
+ '\u{2c7d}', SC_Lower), ('\u{2c7e}', '\u{2c80}', SC_Upper), ('\u{2c81}', '\u{2c81}',
+ SC_Lower), ('\u{2c82}', '\u{2c82}', SC_Upper), ('\u{2c83}', '\u{2c83}', SC_Lower),
+ ('\u{2c84}', '\u{2c84}', SC_Upper), ('\u{2c85}', '\u{2c85}', SC_Lower), ('\u{2c86}',
+ '\u{2c86}', SC_Upper), ('\u{2c87}', '\u{2c87}', SC_Lower), ('\u{2c88}', '\u{2c88}',
+ SC_Upper), ('\u{2c89}', '\u{2c89}', SC_Lower), ('\u{2c8a}', '\u{2c8a}', SC_Upper),
+ ('\u{2c8b}', '\u{2c8b}', SC_Lower), ('\u{2c8c}', '\u{2c8c}', SC_Upper), ('\u{2c8d}',
+ '\u{2c8d}', SC_Lower), ('\u{2c8e}', '\u{2c8e}', SC_Upper), ('\u{2c8f}', '\u{2c8f}',
+ SC_Lower), ('\u{2c90}', '\u{2c90}', SC_Upper), ('\u{2c91}', '\u{2c91}', SC_Lower),
+ ('\u{2c92}', '\u{2c92}', SC_Upper), ('\u{2c93}', '\u{2c93}', SC_Lower), ('\u{2c94}',
+ '\u{2c94}', SC_Upper), ('\u{2c95}', '\u{2c95}', SC_Lower), ('\u{2c96}', '\u{2c96}',
+ SC_Upper), ('\u{2c97}', '\u{2c97}', SC_Lower), ('\u{2c98}', '\u{2c98}', SC_Upper),
+ ('\u{2c99}', '\u{2c99}', SC_Lower), ('\u{2c9a}', '\u{2c9a}', SC_Upper), ('\u{2c9b}',
+ '\u{2c9b}', SC_Lower), ('\u{2c9c}', '\u{2c9c}', SC_Upper), ('\u{2c9d}', '\u{2c9d}',
+ SC_Lower), ('\u{2c9e}', '\u{2c9e}', SC_Upper), ('\u{2c9f}', '\u{2c9f}', SC_Lower),
+ ('\u{2ca0}', '\u{2ca0}', SC_Upper), ('\u{2ca1}', '\u{2ca1}', SC_Lower), ('\u{2ca2}',
+ '\u{2ca2}', SC_Upper), ('\u{2ca3}', '\u{2ca3}', SC_Lower), ('\u{2ca4}', '\u{2ca4}',
+ SC_Upper), ('\u{2ca5}', '\u{2ca5}', SC_Lower), ('\u{2ca6}', '\u{2ca6}', SC_Upper),
+ ('\u{2ca7}', '\u{2ca7}', SC_Lower), ('\u{2ca8}', '\u{2ca8}', SC_Upper), ('\u{2ca9}',
+ '\u{2ca9}', SC_Lower), ('\u{2caa}', '\u{2caa}', SC_Upper), ('\u{2cab}', '\u{2cab}',
+ SC_Lower), ('\u{2cac}', '\u{2cac}', SC_Upper), ('\u{2cad}', '\u{2cad}', SC_Lower),
+ ('\u{2cae}', '\u{2cae}', SC_Upper), ('\u{2caf}', '\u{2caf}', SC_Lower), ('\u{2cb0}',
+ '\u{2cb0}', SC_Upper), ('\u{2cb1}', '\u{2cb1}', SC_Lower), ('\u{2cb2}', '\u{2cb2}',
+ SC_Upper), ('\u{2cb3}', '\u{2cb3}', SC_Lower), ('\u{2cb4}', '\u{2cb4}', SC_Upper),
+ ('\u{2cb5}', '\u{2cb5}', SC_Lower), ('\u{2cb6}', '\u{2cb6}', SC_Upper), ('\u{2cb7}',
+ '\u{2cb7}', SC_Lower), ('\u{2cb8}', '\u{2cb8}', SC_Upper), ('\u{2cb9}', '\u{2cb9}',
+ SC_Lower), ('\u{2cba}', '\u{2cba}', SC_Upper), ('\u{2cbb}', '\u{2cbb}', SC_Lower),
+ ('\u{2cbc}', '\u{2cbc}', SC_Upper), ('\u{2cbd}', '\u{2cbd}', SC_Lower), ('\u{2cbe}',
+ '\u{2cbe}', SC_Upper), ('\u{2cbf}', '\u{2cbf}', SC_Lower), ('\u{2cc0}', '\u{2cc0}',
+ SC_Upper), ('\u{2cc1}', '\u{2cc1}', SC_Lower), ('\u{2cc2}', '\u{2cc2}', SC_Upper),
+ ('\u{2cc3}', '\u{2cc3}', SC_Lower), ('\u{2cc4}', '\u{2cc4}', SC_Upper), ('\u{2cc5}',
+ '\u{2cc5}', SC_Lower), ('\u{2cc6}', '\u{2cc6}', SC_Upper), ('\u{2cc7}', '\u{2cc7}',
+ SC_Lower), ('\u{2cc8}', '\u{2cc8}', SC_Upper), ('\u{2cc9}', '\u{2cc9}', SC_Lower),
+ ('\u{2cca}', '\u{2cca}', SC_Upper), ('\u{2ccb}', '\u{2ccb}', SC_Lower), ('\u{2ccc}',
+ '\u{2ccc}', SC_Upper), ('\u{2ccd}', '\u{2ccd}', SC_Lower), ('\u{2cce}', '\u{2cce}',
+ SC_Upper), ('\u{2ccf}', '\u{2ccf}', SC_Lower), ('\u{2cd0}', '\u{2cd0}', SC_Upper),
+ ('\u{2cd1}', '\u{2cd1}', SC_Lower), ('\u{2cd2}', '\u{2cd2}', SC_Upper), ('\u{2cd3}',
+ '\u{2cd3}', SC_Lower), ('\u{2cd4}', '\u{2cd4}', SC_Upper), ('\u{2cd5}', '\u{2cd5}',
+ SC_Lower), ('\u{2cd6}', '\u{2cd6}', SC_Upper), ('\u{2cd7}', '\u{2cd7}', SC_Lower),
+ ('\u{2cd8}', '\u{2cd8}', SC_Upper), ('\u{2cd9}', '\u{2cd9}', SC_Lower), ('\u{2cda}',
+ '\u{2cda}', SC_Upper), ('\u{2cdb}', '\u{2cdb}', SC_Lower), ('\u{2cdc}', '\u{2cdc}',
+ SC_Upper), ('\u{2cdd}', '\u{2cdd}', SC_Lower), ('\u{2cde}', '\u{2cde}', SC_Upper),
+ ('\u{2cdf}', '\u{2cdf}', SC_Lower), ('\u{2ce0}', '\u{2ce0}', SC_Upper), ('\u{2ce1}',
+ '\u{2ce1}', SC_Lower), ('\u{2ce2}', '\u{2ce2}', SC_Upper), ('\u{2ce3}', '\u{2ce4}',
+ SC_Lower), ('\u{2ceb}', '\u{2ceb}', SC_Upper), ('\u{2cec}', '\u{2cec}', SC_Lower),
+ ('\u{2ced}', '\u{2ced}', SC_Upper), ('\u{2cee}', '\u{2cee}', SC_Lower), ('\u{2cef}',
+ '\u{2cf1}', SC_Extend), ('\u{2cf2}', '\u{2cf2}', SC_Upper), ('\u{2cf3}', '\u{2cf3}',
+ SC_Lower), ('\u{2d00}', '\u{2d25}', SC_Lower), ('\u{2d27}', '\u{2d27}', SC_Lower),
+ ('\u{2d2d}', '\u{2d2d}', SC_Lower), ('\u{2d30}', '\u{2d67}', SC_OLetter), ('\u{2d6f}',
+ '\u{2d6f}', SC_OLetter), ('\u{2d7f}', '\u{2d7f}', SC_Extend), ('\u{2d80}', '\u{2d96}',
+ SC_OLetter), ('\u{2da0}', '\u{2da6}', SC_OLetter), ('\u{2da8}', '\u{2dae}', SC_OLetter),
+ ('\u{2db0}', '\u{2db6}', SC_OLetter), ('\u{2db8}', '\u{2dbe}', SC_OLetter), ('\u{2dc0}',
+ '\u{2dc6}', SC_OLetter), ('\u{2dc8}', '\u{2dce}', SC_OLetter), ('\u{2dd0}', '\u{2dd6}',
+ SC_OLetter), ('\u{2dd8}', '\u{2dde}', SC_OLetter), ('\u{2de0}', '\u{2dff}', SC_Extend),
+ ('\u{2e00}', '\u{2e0d}', SC_Close), ('\u{2e1c}', '\u{2e1d}', SC_Close), ('\u{2e20}',
+ '\u{2e29}', SC_Close), ('\u{2e2e}', '\u{2e2e}', SC_STerm), ('\u{2e2f}', '\u{2e2f}',
+ SC_OLetter), ('\u{2e3c}', '\u{2e3c}', SC_STerm), ('\u{2e42}', '\u{2e42}', SC_Close),
+ ('\u{2e53}', '\u{2e54}', SC_STerm), ('\u{2e55}', '\u{2e5c}', SC_Close), ('\u{3000}',
+ '\u{3000}', SC_Sp), ('\u{3001}', '\u{3001}', SC_SContinue), ('\u{3002}', '\u{3002}',
+ SC_STerm), ('\u{3005}', '\u{3007}', SC_OLetter), ('\u{3008}', '\u{3011}', SC_Close),
+ ('\u{3014}', '\u{301b}', SC_Close), ('\u{301d}', '\u{301f}', SC_Close), ('\u{3021}',
+ '\u{3029}', SC_OLetter), ('\u{302a}', '\u{302f}', SC_Extend), ('\u{3031}', '\u{3035}',
+ SC_OLetter), ('\u{3038}', '\u{303c}', SC_OLetter), ('\u{3041}', '\u{3096}', SC_OLetter),
+ ('\u{3099}', '\u{309a}', SC_Extend), ('\u{309d}', '\u{309f}', SC_OLetter), ('\u{30a1}',
+ '\u{30fa}', SC_OLetter), ('\u{30fc}', '\u{30ff}', SC_OLetter), ('\u{3105}', '\u{312f}',
+ SC_OLetter), ('\u{3131}', '\u{318e}', SC_OLetter), ('\u{31a0}', '\u{31bf}', SC_OLetter),
+ ('\u{31f0}', '\u{31ff}', SC_OLetter), ('\u{3400}', '\u{4dbf}', SC_OLetter), ('\u{4e00}',
+ '\u{a48c}', SC_OLetter), ('\u{a4d0}', '\u{a4fd}', SC_OLetter), ('\u{a4ff}', '\u{a4ff}',
+ SC_STerm), ('\u{a500}', '\u{a60c}', SC_OLetter), ('\u{a60e}', '\u{a60f}', SC_STerm),
+ ('\u{a610}', '\u{a61f}', SC_OLetter), ('\u{a620}', '\u{a629}', SC_Numeric), ('\u{a62a}',
+ '\u{a62b}', SC_OLetter), ('\u{a640}', '\u{a640}', SC_Upper), ('\u{a641}', '\u{a641}',
+ SC_Lower), ('\u{a642}', '\u{a642}', SC_Upper), ('\u{a643}', '\u{a643}', SC_Lower),
+ ('\u{a644}', '\u{a644}', SC_Upper), ('\u{a645}', '\u{a645}', SC_Lower), ('\u{a646}',
+ '\u{a646}', SC_Upper), ('\u{a647}', '\u{a647}', SC_Lower), ('\u{a648}', '\u{a648}',
+ SC_Upper), ('\u{a649}', '\u{a649}', SC_Lower), ('\u{a64a}', '\u{a64a}', SC_Upper),
+ ('\u{a64b}', '\u{a64b}', SC_Lower), ('\u{a64c}', '\u{a64c}', SC_Upper), ('\u{a64d}',
+ '\u{a64d}', SC_Lower), ('\u{a64e}', '\u{a64e}', SC_Upper), ('\u{a64f}', '\u{a64f}',
+ SC_Lower), ('\u{a650}', '\u{a650}', SC_Upper), ('\u{a651}', '\u{a651}', SC_Lower),
+ ('\u{a652}', '\u{a652}', SC_Upper), ('\u{a653}', '\u{a653}', SC_Lower), ('\u{a654}',
+ '\u{a654}', SC_Upper), ('\u{a655}', '\u{a655}', SC_Lower), ('\u{a656}', '\u{a656}',
+ SC_Upper), ('\u{a657}', '\u{a657}', SC_Lower), ('\u{a658}', '\u{a658}', SC_Upper),
+ ('\u{a659}', '\u{a659}', SC_Lower), ('\u{a65a}', '\u{a65a}', SC_Upper), ('\u{a65b}',
+ '\u{a65b}', SC_Lower), ('\u{a65c}', '\u{a65c}', SC_Upper), ('\u{a65d}', '\u{a65d}',
+ SC_Lower), ('\u{a65e}', '\u{a65e}', SC_Upper), ('\u{a65f}', '\u{a65f}', SC_Lower),
+ ('\u{a660}', '\u{a660}', SC_Upper), ('\u{a661}', '\u{a661}', SC_Lower), ('\u{a662}',
+ '\u{a662}', SC_Upper), ('\u{a663}', '\u{a663}', SC_Lower), ('\u{a664}', '\u{a664}',
+ SC_Upper), ('\u{a665}', '\u{a665}', SC_Lower), ('\u{a666}', '\u{a666}', SC_Upper),
+ ('\u{a667}', '\u{a667}', SC_Lower), ('\u{a668}', '\u{a668}', SC_Upper), ('\u{a669}',
+ '\u{a669}', SC_Lower), ('\u{a66a}', '\u{a66a}', SC_Upper), ('\u{a66b}', '\u{a66b}',
+ SC_Lower), ('\u{a66c}', '\u{a66c}', SC_Upper), ('\u{a66d}', '\u{a66d}', SC_Lower),
+ ('\u{a66e}', '\u{a66e}', SC_OLetter), ('\u{a66f}', '\u{a672}', SC_Extend), ('\u{a674}',
+ '\u{a67d}', SC_Extend), ('\u{a67f}', '\u{a67f}', SC_OLetter), ('\u{a680}', '\u{a680}',
+ SC_Upper), ('\u{a681}', '\u{a681}', SC_Lower), ('\u{a682}', '\u{a682}', SC_Upper),
+ ('\u{a683}', '\u{a683}', SC_Lower), ('\u{a684}', '\u{a684}', SC_Upper), ('\u{a685}',
+ '\u{a685}', SC_Lower), ('\u{a686}', '\u{a686}', SC_Upper), ('\u{a687}', '\u{a687}',
+ SC_Lower), ('\u{a688}', '\u{a688}', SC_Upper), ('\u{a689}', '\u{a689}', SC_Lower),
+ ('\u{a68a}', '\u{a68a}', SC_Upper), ('\u{a68b}', '\u{a68b}', SC_Lower), ('\u{a68c}',
+ '\u{a68c}', SC_Upper), ('\u{a68d}', '\u{a68d}', SC_Lower), ('\u{a68e}', '\u{a68e}',
+ SC_Upper), ('\u{a68f}', '\u{a68f}', SC_Lower), ('\u{a690}', '\u{a690}', SC_Upper),
+ ('\u{a691}', '\u{a691}', SC_Lower), ('\u{a692}', '\u{a692}', SC_Upper), ('\u{a693}',
+ '\u{a693}', SC_Lower), ('\u{a694}', '\u{a694}', SC_Upper), ('\u{a695}', '\u{a695}',
+ SC_Lower), ('\u{a696}', '\u{a696}', SC_Upper), ('\u{a697}', '\u{a697}', SC_Lower),
+ ('\u{a698}', '\u{a698}', SC_Upper), ('\u{a699}', '\u{a699}', SC_Lower), ('\u{a69a}',
+ '\u{a69a}', SC_Upper), ('\u{a69b}', '\u{a69d}', SC_Lower), ('\u{a69e}', '\u{a69f}',
+ SC_Extend), ('\u{a6a0}', '\u{a6ef}', SC_OLetter), ('\u{a6f0}', '\u{a6f1}', SC_Extend),
+ ('\u{a6f3}', '\u{a6f3}', SC_STerm), ('\u{a6f7}', '\u{a6f7}', SC_STerm), ('\u{a717}',
+ '\u{a71f}', SC_OLetter), ('\u{a722}', '\u{a722}', SC_Upper), ('\u{a723}', '\u{a723}',
+ SC_Lower), ('\u{a724}', '\u{a724}', SC_Upper), ('\u{a725}', '\u{a725}', SC_Lower),
+ ('\u{a726}', '\u{a726}', SC_Upper), ('\u{a727}', '\u{a727}', SC_Lower), ('\u{a728}',
+ '\u{a728}', SC_Upper), ('\u{a729}', '\u{a729}', SC_Lower), ('\u{a72a}', '\u{a72a}',
+ SC_Upper), ('\u{a72b}', '\u{a72b}', SC_Lower), ('\u{a72c}', '\u{a72c}', SC_Upper),
+ ('\u{a72d}', '\u{a72d}', SC_Lower), ('\u{a72e}', '\u{a72e}', SC_Upper), ('\u{a72f}',
+ '\u{a731}', SC_Lower), ('\u{a732}', '\u{a732}', SC_Upper), ('\u{a733}', '\u{a733}',
+ SC_Lower), ('\u{a734}', '\u{a734}', SC_Upper), ('\u{a735}', '\u{a735}', SC_Lower),
+ ('\u{a736}', '\u{a736}', SC_Upper), ('\u{a737}', '\u{a737}', SC_Lower), ('\u{a738}',
+ '\u{a738}', SC_Upper), ('\u{a739}', '\u{a739}', SC_Lower), ('\u{a73a}', '\u{a73a}',
+ SC_Upper), ('\u{a73b}', '\u{a73b}', SC_Lower), ('\u{a73c}', '\u{a73c}', SC_Upper),
+ ('\u{a73d}', '\u{a73d}', SC_Lower), ('\u{a73e}', '\u{a73e}', SC_Upper), ('\u{a73f}',
+ '\u{a73f}', SC_Lower), ('\u{a740}', '\u{a740}', SC_Upper), ('\u{a741}', '\u{a741}',
+ SC_Lower), ('\u{a742}', '\u{a742}', SC_Upper), ('\u{a743}', '\u{a743}', SC_Lower),
+ ('\u{a744}', '\u{a744}', SC_Upper), ('\u{a745}', '\u{a745}', SC_Lower), ('\u{a746}',
+ '\u{a746}', SC_Upper), ('\u{a747}', '\u{a747}', SC_Lower), ('\u{a748}', '\u{a748}',
+ SC_Upper), ('\u{a749}', '\u{a749}', SC_Lower), ('\u{a74a}', '\u{a74a}', SC_Upper),
+ ('\u{a74b}', '\u{a74b}', SC_Lower), ('\u{a74c}', '\u{a74c}', SC_Upper), ('\u{a74d}',
+ '\u{a74d}', SC_Lower), ('\u{a74e}', '\u{a74e}', SC_Upper), ('\u{a74f}', '\u{a74f}',
+ SC_Lower), ('\u{a750}', '\u{a750}', SC_Upper), ('\u{a751}', '\u{a751}', SC_Lower),
+ ('\u{a752}', '\u{a752}', SC_Upper), ('\u{a753}', '\u{a753}', SC_Lower), ('\u{a754}',
+ '\u{a754}', SC_Upper), ('\u{a755}', '\u{a755}', SC_Lower), ('\u{a756}', '\u{a756}',
+ SC_Upper), ('\u{a757}', '\u{a757}', SC_Lower), ('\u{a758}', '\u{a758}', SC_Upper),
+ ('\u{a759}', '\u{a759}', SC_Lower), ('\u{a75a}', '\u{a75a}', SC_Upper), ('\u{a75b}',
+ '\u{a75b}', SC_Lower), ('\u{a75c}', '\u{a75c}', SC_Upper), ('\u{a75d}', '\u{a75d}',
+ SC_Lower), ('\u{a75e}', '\u{a75e}', SC_Upper), ('\u{a75f}', '\u{a75f}', SC_Lower),
+ ('\u{a760}', '\u{a760}', SC_Upper), ('\u{a761}', '\u{a761}', SC_Lower), ('\u{a762}',
+ '\u{a762}', SC_Upper), ('\u{a763}', '\u{a763}', SC_Lower), ('\u{a764}', '\u{a764}',
+ SC_Upper), ('\u{a765}', '\u{a765}', SC_Lower), ('\u{a766}', '\u{a766}', SC_Upper),
+ ('\u{a767}', '\u{a767}', SC_Lower), ('\u{a768}', '\u{a768}', SC_Upper), ('\u{a769}',
+ '\u{a769}', SC_Lower), ('\u{a76a}', '\u{a76a}', SC_Upper), ('\u{a76b}', '\u{a76b}',
+ SC_Lower), ('\u{a76c}', '\u{a76c}', SC_Upper), ('\u{a76d}', '\u{a76d}', SC_Lower),
+ ('\u{a76e}', '\u{a76e}', SC_Upper), ('\u{a76f}', '\u{a778}', SC_Lower), ('\u{a779}',
+ '\u{a779}', SC_Upper), ('\u{a77a}', '\u{a77a}', SC_Lower), ('\u{a77b}', '\u{a77b}',
+ SC_Upper), ('\u{a77c}', '\u{a77c}', SC_Lower), ('\u{a77d}', '\u{a77e}', SC_Upper),
+ ('\u{a77f}', '\u{a77f}', SC_Lower), ('\u{a780}', '\u{a780}', SC_Upper), ('\u{a781}',
+ '\u{a781}', SC_Lower), ('\u{a782}', '\u{a782}', SC_Upper), ('\u{a783}', '\u{a783}',
+ SC_Lower), ('\u{a784}', '\u{a784}', SC_Upper), ('\u{a785}', '\u{a785}', SC_Lower),
+ ('\u{a786}', '\u{a786}', SC_Upper), ('\u{a787}', '\u{a787}', SC_Lower), ('\u{a788}',
+ '\u{a788}', SC_OLetter), ('\u{a78b}', '\u{a78b}', SC_Upper), ('\u{a78c}', '\u{a78c}',
+ SC_Lower), ('\u{a78d}', '\u{a78d}', SC_Upper), ('\u{a78e}', '\u{a78e}', SC_Lower),
+ ('\u{a78f}', '\u{a78f}', SC_OLetter), ('\u{a790}', '\u{a790}', SC_Upper), ('\u{a791}',
+ '\u{a791}', SC_Lower), ('\u{a792}', '\u{a792}', SC_Upper), ('\u{a793}', '\u{a795}',
+ SC_Lower), ('\u{a796}', '\u{a796}', SC_Upper), ('\u{a797}', '\u{a797}', SC_Lower),
+ ('\u{a798}', '\u{a798}', SC_Upper), ('\u{a799}', '\u{a799}', SC_Lower), ('\u{a79a}',
+ '\u{a79a}', SC_Upper), ('\u{a79b}', '\u{a79b}', SC_Lower), ('\u{a79c}', '\u{a79c}',
+ SC_Upper), ('\u{a79d}', '\u{a79d}', SC_Lower), ('\u{a79e}', '\u{a79e}', SC_Upper),
+ ('\u{a79f}', '\u{a79f}', SC_Lower), ('\u{a7a0}', '\u{a7a0}', SC_Upper), ('\u{a7a1}',
+ '\u{a7a1}', SC_Lower), ('\u{a7a2}', '\u{a7a2}', SC_Upper), ('\u{a7a3}', '\u{a7a3}',
+ SC_Lower), ('\u{a7a4}', '\u{a7a4}', SC_Upper), ('\u{a7a5}', '\u{a7a5}', SC_Lower),
+ ('\u{a7a6}', '\u{a7a6}', SC_Upper), ('\u{a7a7}', '\u{a7a7}', SC_Lower), ('\u{a7a8}',
+ '\u{a7a8}', SC_Upper), ('\u{a7a9}', '\u{a7a9}', SC_Lower), ('\u{a7aa}', '\u{a7ae}',
+ SC_Upper), ('\u{a7af}', '\u{a7af}', SC_Lower), ('\u{a7b0}', '\u{a7b4}', SC_Upper),
+ ('\u{a7b5}', '\u{a7b5}', SC_Lower), ('\u{a7b6}', '\u{a7b6}', SC_Upper), ('\u{a7b7}',
+ '\u{a7b7}', SC_Lower), ('\u{a7b8}', '\u{a7b8}', SC_Upper), ('\u{a7b9}', '\u{a7b9}',
+ SC_Lower), ('\u{a7ba}', '\u{a7ba}', SC_Upper), ('\u{a7bb}', '\u{a7bb}', SC_Lower),
+ ('\u{a7bc}', '\u{a7bc}', SC_Upper), ('\u{a7bd}', '\u{a7bd}', SC_Lower), ('\u{a7be}',
+ '\u{a7be}', SC_Upper), ('\u{a7bf}', '\u{a7bf}', SC_Lower), ('\u{a7c0}', '\u{a7c0}',
+ SC_Upper), ('\u{a7c1}', '\u{a7c1}', SC_Lower), ('\u{a7c2}', '\u{a7c2}', SC_Upper),
+ ('\u{a7c3}', '\u{a7c3}', SC_Lower), ('\u{a7c4}', '\u{a7c7}', SC_Upper), ('\u{a7c8}',
+ '\u{a7c8}', SC_Lower), ('\u{a7c9}', '\u{a7c9}', SC_Upper), ('\u{a7ca}', '\u{a7ca}',
+ SC_Lower), ('\u{a7d0}', '\u{a7d0}', SC_Upper), ('\u{a7d1}', '\u{a7d1}', SC_Lower),
+ ('\u{a7d3}', '\u{a7d3}', SC_Lower), ('\u{a7d5}', '\u{a7d5}', SC_Lower), ('\u{a7d6}',
+ '\u{a7d6}', SC_Upper), ('\u{a7d7}', '\u{a7d7}', SC_Lower), ('\u{a7d8}', '\u{a7d8}',
+ SC_Upper), ('\u{a7d9}', '\u{a7d9}', SC_Lower), ('\u{a7f2}', '\u{a7f4}', SC_Lower),
+ ('\u{a7f5}', '\u{a7f5}', SC_Upper), ('\u{a7f6}', '\u{a7f6}', SC_Lower), ('\u{a7f7}',
+ '\u{a7f7}', SC_OLetter), ('\u{a7f8}', '\u{a7fa}', SC_Lower), ('\u{a7fb}', '\u{a801}',
+ SC_OLetter), ('\u{a802}', '\u{a802}', SC_Extend), ('\u{a803}', '\u{a805}', SC_OLetter),
+ ('\u{a806}', '\u{a806}', SC_Extend), ('\u{a807}', '\u{a80a}', SC_OLetter), ('\u{a80b}',
+ '\u{a80b}', SC_Extend), ('\u{a80c}', '\u{a822}', SC_OLetter), ('\u{a823}', '\u{a827}',
+ SC_Extend), ('\u{a82c}', '\u{a82c}', SC_Extend), ('\u{a840}', '\u{a873}', SC_OLetter),
+ ('\u{a876}', '\u{a877}', SC_STerm), ('\u{a880}', '\u{a881}', SC_Extend), ('\u{a882}',
+ '\u{a8b3}', SC_OLetter), ('\u{a8b4}', '\u{a8c5}', SC_Extend), ('\u{a8ce}', '\u{a8cf}',
+ SC_STerm), ('\u{a8d0}', '\u{a8d9}', SC_Numeric), ('\u{a8e0}', '\u{a8f1}', SC_Extend),
+ ('\u{a8f2}', '\u{a8f7}', SC_OLetter), ('\u{a8fb}', '\u{a8fb}', SC_OLetter), ('\u{a8fd}',
+ '\u{a8fe}', SC_OLetter), ('\u{a8ff}', '\u{a8ff}', SC_Extend), ('\u{a900}', '\u{a909}',
+ SC_Numeric), ('\u{a90a}', '\u{a925}', SC_OLetter), ('\u{a926}', '\u{a92d}', SC_Extend),
+ ('\u{a92f}', '\u{a92f}', SC_STerm), ('\u{a930}', '\u{a946}', SC_OLetter), ('\u{a947}',
+ '\u{a953}', SC_Extend), ('\u{a960}', '\u{a97c}', SC_OLetter), ('\u{a980}', '\u{a983}',
+ SC_Extend), ('\u{a984}', '\u{a9b2}', SC_OLetter), ('\u{a9b3}', '\u{a9c0}', SC_Extend),
+ ('\u{a9c8}', '\u{a9c9}', SC_STerm), ('\u{a9cf}', '\u{a9cf}', SC_OLetter), ('\u{a9d0}',
+ '\u{a9d9}', SC_Numeric), ('\u{a9e0}', '\u{a9e4}', SC_OLetter), ('\u{a9e5}', '\u{a9e5}',
+ SC_Extend), ('\u{a9e6}', '\u{a9ef}', SC_OLetter), ('\u{a9f0}', '\u{a9f9}', SC_Numeric),
+ ('\u{a9fa}', '\u{a9fe}', SC_OLetter), ('\u{aa00}', '\u{aa28}', SC_OLetter), ('\u{aa29}',
+ '\u{aa36}', SC_Extend), ('\u{aa40}', '\u{aa42}', SC_OLetter), ('\u{aa43}', '\u{aa43}',
+ SC_Extend), ('\u{aa44}', '\u{aa4b}', SC_OLetter), ('\u{aa4c}', '\u{aa4d}', SC_Extend),
+ ('\u{aa50}', '\u{aa59}', SC_Numeric), ('\u{aa5d}', '\u{aa5f}', SC_STerm), ('\u{aa60}',
+ '\u{aa76}', SC_OLetter), ('\u{aa7a}', '\u{aa7a}', SC_OLetter), ('\u{aa7b}', '\u{aa7d}',
+ SC_Extend), ('\u{aa7e}', '\u{aaaf}', SC_OLetter), ('\u{aab0}', '\u{aab0}', SC_Extend),
+ ('\u{aab1}', '\u{aab1}', SC_OLetter), ('\u{aab2}', '\u{aab4}', SC_Extend), ('\u{aab5}',
+ '\u{aab6}', SC_OLetter), ('\u{aab7}', '\u{aab8}', SC_Extend), ('\u{aab9}', '\u{aabd}',
+ SC_OLetter), ('\u{aabe}', '\u{aabf}', SC_Extend), ('\u{aac0}', '\u{aac0}', SC_OLetter),
+ ('\u{aac1}', '\u{aac1}', SC_Extend), ('\u{aac2}', '\u{aac2}', SC_OLetter), ('\u{aadb}',
+ '\u{aadd}', SC_OLetter), ('\u{aae0}', '\u{aaea}', SC_OLetter), ('\u{aaeb}', '\u{aaef}',
+ SC_Extend), ('\u{aaf0}', '\u{aaf1}', SC_STerm), ('\u{aaf2}', '\u{aaf4}', SC_OLetter),
+ ('\u{aaf5}', '\u{aaf6}', SC_Extend), ('\u{ab01}', '\u{ab06}', SC_OLetter), ('\u{ab09}',
+ '\u{ab0e}', SC_OLetter), ('\u{ab11}', '\u{ab16}', SC_OLetter), ('\u{ab20}', '\u{ab26}',
+ SC_OLetter), ('\u{ab28}', '\u{ab2e}', SC_OLetter), ('\u{ab30}', '\u{ab5a}', SC_Lower),
+ ('\u{ab5c}', '\u{ab69}', SC_Lower), ('\u{ab70}', '\u{abbf}', SC_Lower), ('\u{abc0}',
+ '\u{abe2}', SC_OLetter), ('\u{abe3}', '\u{abea}', SC_Extend), ('\u{abeb}', '\u{abeb}',
+ SC_STerm), ('\u{abec}', '\u{abed}', SC_Extend), ('\u{abf0}', '\u{abf9}', SC_Numeric),
+ ('\u{ac00}', '\u{d7a3}', SC_OLetter), ('\u{d7b0}', '\u{d7c6}', SC_OLetter), ('\u{d7cb}',
+ '\u{d7fb}', SC_OLetter), ('\u{f900}', '\u{fa6d}', SC_OLetter), ('\u{fa70}', '\u{fad9}',
+ SC_OLetter), ('\u{fb00}', '\u{fb06}', SC_Lower), ('\u{fb13}', '\u{fb17}', SC_Lower),
+ ('\u{fb1d}', '\u{fb1d}', SC_OLetter), ('\u{fb1e}', '\u{fb1e}', SC_Extend), ('\u{fb1f}',
+ '\u{fb28}', SC_OLetter), ('\u{fb2a}', '\u{fb36}', SC_OLetter), ('\u{fb38}', '\u{fb3c}',
+ SC_OLetter), ('\u{fb3e}', '\u{fb3e}', SC_OLetter), ('\u{fb40}', '\u{fb41}', SC_OLetter),
+ ('\u{fb43}', '\u{fb44}', SC_OLetter), ('\u{fb46}', '\u{fbb1}', SC_OLetter), ('\u{fbd3}',
+ '\u{fd3d}', SC_OLetter), ('\u{fd3e}', '\u{fd3f}', SC_Close), ('\u{fd50}', '\u{fd8f}',
+ SC_OLetter), ('\u{fd92}', '\u{fdc7}', SC_OLetter), ('\u{fdf0}', '\u{fdfb}', SC_OLetter),
+ ('\u{fe00}', '\u{fe0f}', SC_Extend), ('\u{fe10}', '\u{fe11}', SC_SContinue), ('\u{fe13}',
+ '\u{fe13}', SC_SContinue), ('\u{fe17}', '\u{fe18}', SC_Close), ('\u{fe20}', '\u{fe2f}',
+ SC_Extend), ('\u{fe31}', '\u{fe32}', SC_SContinue), ('\u{fe35}', '\u{fe44}', SC_Close),
+ ('\u{fe47}', '\u{fe48}', SC_Close), ('\u{fe50}', '\u{fe51}', SC_SContinue), ('\u{fe52}',
+ '\u{fe52}', SC_ATerm), ('\u{fe55}', '\u{fe55}', SC_SContinue), ('\u{fe56}', '\u{fe57}',
+ SC_STerm), ('\u{fe58}', '\u{fe58}', SC_SContinue), ('\u{fe59}', '\u{fe5e}', SC_Close),
+ ('\u{fe63}', '\u{fe63}', SC_SContinue), ('\u{fe70}', '\u{fe74}', SC_OLetter), ('\u{fe76}',
+ '\u{fefc}', SC_OLetter), ('\u{feff}', '\u{feff}', SC_Format), ('\u{ff01}', '\u{ff01}',
+ SC_STerm), ('\u{ff08}', '\u{ff09}', SC_Close), ('\u{ff0c}', '\u{ff0d}', SC_SContinue),
+ ('\u{ff0e}', '\u{ff0e}', SC_ATerm), ('\u{ff10}', '\u{ff19}', SC_Numeric), ('\u{ff1a}',
+ '\u{ff1a}', SC_SContinue), ('\u{ff1f}', '\u{ff1f}', SC_STerm), ('\u{ff21}', '\u{ff3a}',
+ SC_Upper), ('\u{ff3b}', '\u{ff3b}', SC_Close), ('\u{ff3d}', '\u{ff3d}', SC_Close),
+ ('\u{ff41}', '\u{ff5a}', SC_Lower), ('\u{ff5b}', '\u{ff5b}', SC_Close), ('\u{ff5d}',
+ '\u{ff5d}', SC_Close), ('\u{ff5f}', '\u{ff60}', SC_Close), ('\u{ff61}', '\u{ff61}',
+ SC_STerm), ('\u{ff62}', '\u{ff63}', SC_Close), ('\u{ff64}', '\u{ff64}', SC_SContinue),
+ ('\u{ff66}', '\u{ff9d}', SC_OLetter), ('\u{ff9e}', '\u{ff9f}', SC_Extend), ('\u{ffa0}',
+ '\u{ffbe}', SC_OLetter), ('\u{ffc2}', '\u{ffc7}', SC_OLetter), ('\u{ffca}', '\u{ffcf}',
+ SC_OLetter), ('\u{ffd2}', '\u{ffd7}', SC_OLetter), ('\u{ffda}', '\u{ffdc}', SC_OLetter),
+ ('\u{fff9}', '\u{fffb}', SC_Format), ('\u{10000}', '\u{1000b}', SC_OLetter), ('\u{1000d}',
+ '\u{10026}', SC_OLetter), ('\u{10028}', '\u{1003a}', SC_OLetter), ('\u{1003c}', '\u{1003d}',
+ SC_OLetter), ('\u{1003f}', '\u{1004d}', SC_OLetter), ('\u{10050}', '\u{1005d}', SC_OLetter),
+ ('\u{10080}', '\u{100fa}', SC_OLetter), ('\u{10140}', '\u{10174}', SC_OLetter),
+ ('\u{101fd}', '\u{101fd}', SC_Extend), ('\u{10280}', '\u{1029c}', SC_OLetter), ('\u{102a0}',
+ '\u{102d0}', SC_OLetter), ('\u{102e0}', '\u{102e0}', SC_Extend), ('\u{10300}', '\u{1031f}',
+ SC_OLetter), ('\u{1032d}', '\u{1034a}', SC_OLetter), ('\u{10350}', '\u{10375}', SC_OLetter),
+ ('\u{10376}', '\u{1037a}', SC_Extend), ('\u{10380}', '\u{1039d}', SC_OLetter), ('\u{103a0}',
+ '\u{103c3}', SC_OLetter), ('\u{103c8}', '\u{103cf}', SC_OLetter), ('\u{103d1}', '\u{103d5}',
+ SC_OLetter), ('\u{10400}', '\u{10427}', SC_Upper), ('\u{10428}', '\u{1044f}', SC_Lower),
+ ('\u{10450}', '\u{1049d}', SC_OLetter), ('\u{104a0}', '\u{104a9}', SC_Numeric),
+ ('\u{104b0}', '\u{104d3}', SC_Upper), ('\u{104d8}', '\u{104fb}', SC_Lower), ('\u{10500}',
+ '\u{10527}', SC_OLetter), ('\u{10530}', '\u{10563}', SC_OLetter), ('\u{10570}', '\u{1057a}',
+ SC_Upper), ('\u{1057c}', '\u{1058a}', SC_Upper), ('\u{1058c}', '\u{10592}', SC_Upper),
+ ('\u{10594}', '\u{10595}', SC_Upper), ('\u{10597}', '\u{105a1}', SC_Lower), ('\u{105a3}',
+ '\u{105b1}', SC_Lower), ('\u{105b3}', '\u{105b9}', SC_Lower), ('\u{105bb}', '\u{105bc}',
+ SC_Lower), ('\u{10600}', '\u{10736}', SC_OLetter), ('\u{10740}', '\u{10755}', SC_OLetter),
+ ('\u{10760}', '\u{10767}', SC_OLetter), ('\u{10780}', '\u{10780}', SC_Lower), ('\u{10781}',
+ '\u{10782}', SC_OLetter), ('\u{10783}', '\u{10785}', SC_Lower), ('\u{10787}', '\u{107b0}',
+ SC_Lower), ('\u{107b2}', '\u{107ba}', SC_Lower), ('\u{10800}', '\u{10805}', SC_OLetter),
+ ('\u{10808}', '\u{10808}', SC_OLetter), ('\u{1080a}', '\u{10835}', SC_OLetter),
+ ('\u{10837}', '\u{10838}', SC_OLetter), ('\u{1083c}', '\u{1083c}', SC_OLetter),
('\u{1083f}', '\u{10855}', SC_OLetter), ('\u{10860}', '\u{10876}', SC_OLetter),
('\u{10880}', '\u{1089e}', SC_OLetter), ('\u{108e0}', '\u{108f2}', SC_OLetter),
('\u{108f4}', '\u{108f5}', SC_OLetter), ('\u{10900}', '\u{10915}', SC_OLetter),
@@ -2459,33 +2483,34 @@ pub mod sentence {
('\u{10c00}', '\u{10c48}', SC_OLetter), ('\u{10c80}', '\u{10cb2}', SC_Upper), ('\u{10cc0}',
'\u{10cf2}', SC_Lower), ('\u{10d00}', '\u{10d23}', SC_OLetter), ('\u{10d24}', '\u{10d27}',
SC_Extend), ('\u{10d30}', '\u{10d39}', SC_Numeric), ('\u{10e80}', '\u{10ea9}', SC_OLetter),
- ('\u{10eab}', '\u{10eac}', SC_Extend), ('\u{10eb0}', '\u{10eb1}', SC_OLetter), ('\u{10f00}',
- '\u{10f1c}', SC_OLetter), ('\u{10f27}', '\u{10f27}', SC_OLetter), ('\u{10f30}', '\u{10f45}',
- SC_OLetter), ('\u{10f46}', '\u{10f50}', SC_Extend), ('\u{10f55}', '\u{10f59}', SC_STerm),
- ('\u{10f70}', '\u{10f81}', SC_OLetter), ('\u{10f82}', '\u{10f85}', SC_Extend), ('\u{10f86}',
- '\u{10f89}', SC_STerm), ('\u{10fb0}', '\u{10fc4}', SC_OLetter), ('\u{10fe0}', '\u{10ff6}',
- SC_OLetter), ('\u{11000}', '\u{11002}', SC_Extend), ('\u{11003}', '\u{11037}', SC_OLetter),
- ('\u{11038}', '\u{11046}', SC_Extend), ('\u{11047}', '\u{11048}', SC_STerm), ('\u{11066}',
- '\u{1106f}', SC_Numeric), ('\u{11070}', '\u{11070}', SC_Extend), ('\u{11071}', '\u{11072}',
- SC_OLetter), ('\u{11073}', '\u{11074}', SC_Extend), ('\u{11075}', '\u{11075}', SC_OLetter),
- ('\u{1107f}', '\u{11082}', SC_Extend), ('\u{11083}', '\u{110af}', SC_OLetter), ('\u{110b0}',
- '\u{110ba}', SC_Extend), ('\u{110bd}', '\u{110bd}', SC_Format), ('\u{110be}', '\u{110c1}',
- SC_STerm), ('\u{110c2}', '\u{110c2}', SC_Extend), ('\u{110cd}', '\u{110cd}', SC_Format),
- ('\u{110d0}', '\u{110e8}', SC_OLetter), ('\u{110f0}', '\u{110f9}', SC_Numeric),
- ('\u{11100}', '\u{11102}', SC_Extend), ('\u{11103}', '\u{11126}', SC_OLetter), ('\u{11127}',
- '\u{11134}', SC_Extend), ('\u{11136}', '\u{1113f}', SC_Numeric), ('\u{11141}', '\u{11143}',
- SC_STerm), ('\u{11144}', '\u{11144}', SC_OLetter), ('\u{11145}', '\u{11146}', SC_Extend),
- ('\u{11147}', '\u{11147}', SC_OLetter), ('\u{11150}', '\u{11172}', SC_OLetter),
- ('\u{11173}', '\u{11173}', SC_Extend), ('\u{11176}', '\u{11176}', SC_OLetter), ('\u{11180}',
- '\u{11182}', SC_Extend), ('\u{11183}', '\u{111b2}', SC_OLetter), ('\u{111b3}', '\u{111c0}',
- SC_Extend), ('\u{111c1}', '\u{111c4}', SC_OLetter), ('\u{111c5}', '\u{111c6}', SC_STerm),
- ('\u{111c9}', '\u{111cc}', SC_Extend), ('\u{111cd}', '\u{111cd}', SC_STerm), ('\u{111ce}',
- '\u{111cf}', SC_Extend), ('\u{111d0}', '\u{111d9}', SC_Numeric), ('\u{111da}', '\u{111da}',
- SC_OLetter), ('\u{111dc}', '\u{111dc}', SC_OLetter), ('\u{111de}', '\u{111df}', SC_STerm),
- ('\u{11200}', '\u{11211}', SC_OLetter), ('\u{11213}', '\u{1122b}', SC_OLetter),
+ ('\u{10eab}', '\u{10eac}', SC_Extend), ('\u{10eb0}', '\u{10eb1}', SC_OLetter), ('\u{10efd}',
+ '\u{10eff}', SC_Extend), ('\u{10f00}', '\u{10f1c}', SC_OLetter), ('\u{10f27}', '\u{10f27}',
+ SC_OLetter), ('\u{10f30}', '\u{10f45}', SC_OLetter), ('\u{10f46}', '\u{10f50}', SC_Extend),
+ ('\u{10f55}', '\u{10f59}', SC_STerm), ('\u{10f70}', '\u{10f81}', SC_OLetter), ('\u{10f82}',
+ '\u{10f85}', SC_Extend), ('\u{10f86}', '\u{10f89}', SC_STerm), ('\u{10fb0}', '\u{10fc4}',
+ SC_OLetter), ('\u{10fe0}', '\u{10ff6}', SC_OLetter), ('\u{11000}', '\u{11002}', SC_Extend),
+ ('\u{11003}', '\u{11037}', SC_OLetter), ('\u{11038}', '\u{11046}', SC_Extend), ('\u{11047}',
+ '\u{11048}', SC_STerm), ('\u{11066}', '\u{1106f}', SC_Numeric), ('\u{11070}', '\u{11070}',
+ SC_Extend), ('\u{11071}', '\u{11072}', SC_OLetter), ('\u{11073}', '\u{11074}', SC_Extend),
+ ('\u{11075}', '\u{11075}', SC_OLetter), ('\u{1107f}', '\u{11082}', SC_Extend), ('\u{11083}',
+ '\u{110af}', SC_OLetter), ('\u{110b0}', '\u{110ba}', SC_Extend), ('\u{110bd}', '\u{110bd}',
+ SC_Format), ('\u{110be}', '\u{110c1}', SC_STerm), ('\u{110c2}', '\u{110c2}', SC_Extend),
+ ('\u{110cd}', '\u{110cd}', SC_Format), ('\u{110d0}', '\u{110e8}', SC_OLetter), ('\u{110f0}',
+ '\u{110f9}', SC_Numeric), ('\u{11100}', '\u{11102}', SC_Extend), ('\u{11103}', '\u{11126}',
+ SC_OLetter), ('\u{11127}', '\u{11134}', SC_Extend), ('\u{11136}', '\u{1113f}', SC_Numeric),
+ ('\u{11141}', '\u{11143}', SC_STerm), ('\u{11144}', '\u{11144}', SC_OLetter), ('\u{11145}',
+ '\u{11146}', SC_Extend), ('\u{11147}', '\u{11147}', SC_OLetter), ('\u{11150}', '\u{11172}',
+ SC_OLetter), ('\u{11173}', '\u{11173}', SC_Extend), ('\u{11176}', '\u{11176}', SC_OLetter),
+ ('\u{11180}', '\u{11182}', SC_Extend), ('\u{11183}', '\u{111b2}', SC_OLetter), ('\u{111b3}',
+ '\u{111c0}', SC_Extend), ('\u{111c1}', '\u{111c4}', SC_OLetter), ('\u{111c5}', '\u{111c6}',
+ SC_STerm), ('\u{111c9}', '\u{111cc}', SC_Extend), ('\u{111cd}', '\u{111cd}', SC_STerm),
+ ('\u{111ce}', '\u{111cf}', SC_Extend), ('\u{111d0}', '\u{111d9}', SC_Numeric), ('\u{111da}',
+ '\u{111da}', SC_OLetter), ('\u{111dc}', '\u{111dc}', SC_OLetter), ('\u{111de}', '\u{111df}',
+ SC_STerm), ('\u{11200}', '\u{11211}', SC_OLetter), ('\u{11213}', '\u{1122b}', SC_OLetter),
('\u{1122c}', '\u{11237}', SC_Extend), ('\u{11238}', '\u{11239}', SC_STerm), ('\u{1123b}',
- '\u{1123c}', SC_STerm), ('\u{1123e}', '\u{1123e}', SC_Extend), ('\u{11280}', '\u{11286}',
- SC_OLetter), ('\u{11288}', '\u{11288}', SC_OLetter), ('\u{1128a}', '\u{1128d}', SC_OLetter),
+ '\u{1123c}', SC_STerm), ('\u{1123e}', '\u{1123e}', SC_Extend), ('\u{1123f}', '\u{11240}',
+ SC_OLetter), ('\u{11241}', '\u{11241}', SC_Extend), ('\u{11280}', '\u{11286}', SC_OLetter),
+ ('\u{11288}', '\u{11288}', SC_OLetter), ('\u{1128a}', '\u{1128d}', SC_OLetter),
('\u{1128f}', '\u{1129d}', SC_OLetter), ('\u{1129f}', '\u{112a8}', SC_OLetter),
('\u{112a9}', '\u{112a9}', SC_STerm), ('\u{112b0}', '\u{112de}', SC_OLetter), ('\u{112df}',
'\u{112ea}', SC_Extend), ('\u{112f0}', '\u{112f9}', SC_Numeric), ('\u{11300}', '\u{11303}',
@@ -2542,17 +2567,22 @@ pub mod sentence {
('\u{11d8a}', '\u{11d8e}', SC_Extend), ('\u{11d90}', '\u{11d91}', SC_Extend), ('\u{11d93}',
'\u{11d97}', SC_Extend), ('\u{11d98}', '\u{11d98}', SC_OLetter), ('\u{11da0}', '\u{11da9}',
SC_Numeric), ('\u{11ee0}', '\u{11ef2}', SC_OLetter), ('\u{11ef3}', '\u{11ef6}', SC_Extend),
- ('\u{11ef7}', '\u{11ef8}', SC_STerm), ('\u{11fb0}', '\u{11fb0}', SC_OLetter), ('\u{12000}',
- '\u{12399}', SC_OLetter), ('\u{12400}', '\u{1246e}', SC_OLetter), ('\u{12480}', '\u{12543}',
- SC_OLetter), ('\u{12f90}', '\u{12ff0}', SC_OLetter), ('\u{13000}', '\u{1342e}', SC_OLetter),
- ('\u{13430}', '\u{13438}', SC_Format), ('\u{14400}', '\u{14646}', SC_OLetter), ('\u{16800}',
- '\u{16a38}', SC_OLetter), ('\u{16a40}', '\u{16a5e}', SC_OLetter), ('\u{16a60}', '\u{16a69}',
- SC_Numeric), ('\u{16a6e}', '\u{16a6f}', SC_STerm), ('\u{16a70}', '\u{16abe}', SC_OLetter),
- ('\u{16ac0}', '\u{16ac9}', SC_Numeric), ('\u{16ad0}', '\u{16aed}', SC_OLetter),
- ('\u{16af0}', '\u{16af4}', SC_Extend), ('\u{16af5}', '\u{16af5}', SC_STerm), ('\u{16b00}',
- '\u{16b2f}', SC_OLetter), ('\u{16b30}', '\u{16b36}', SC_Extend), ('\u{16b37}', '\u{16b38}',
- SC_STerm), ('\u{16b40}', '\u{16b43}', SC_OLetter), ('\u{16b44}', '\u{16b44}', SC_STerm),
- ('\u{16b50}', '\u{16b59}', SC_Numeric), ('\u{16b63}', '\u{16b77}', SC_OLetter),
+ ('\u{11ef7}', '\u{11ef8}', SC_STerm), ('\u{11f00}', '\u{11f01}', SC_Extend), ('\u{11f02}',
+ '\u{11f02}', SC_OLetter), ('\u{11f03}', '\u{11f03}', SC_Extend), ('\u{11f04}', '\u{11f10}',
+ SC_OLetter), ('\u{11f12}', '\u{11f33}', SC_OLetter), ('\u{11f34}', '\u{11f3a}', SC_Extend),
+ ('\u{11f3e}', '\u{11f42}', SC_Extend), ('\u{11f43}', '\u{11f44}', SC_STerm), ('\u{11f50}',
+ '\u{11f59}', SC_Numeric), ('\u{11fb0}', '\u{11fb0}', SC_OLetter), ('\u{12000}', '\u{12399}',
+ SC_OLetter), ('\u{12400}', '\u{1246e}', SC_OLetter), ('\u{12480}', '\u{12543}', SC_OLetter),
+ ('\u{12f90}', '\u{12ff0}', SC_OLetter), ('\u{13000}', '\u{1342f}', SC_OLetter),
+ ('\u{13430}', '\u{1343f}', SC_Format), ('\u{13440}', '\u{13440}', SC_Extend), ('\u{13441}',
+ '\u{13446}', SC_OLetter), ('\u{13447}', '\u{13455}', SC_Extend), ('\u{14400}', '\u{14646}',
+ SC_OLetter), ('\u{16800}', '\u{16a38}', SC_OLetter), ('\u{16a40}', '\u{16a5e}', SC_OLetter),
+ ('\u{16a60}', '\u{16a69}', SC_Numeric), ('\u{16a6e}', '\u{16a6f}', SC_STerm), ('\u{16a70}',
+ '\u{16abe}', SC_OLetter), ('\u{16ac0}', '\u{16ac9}', SC_Numeric), ('\u{16ad0}', '\u{16aed}',
+ SC_OLetter), ('\u{16af0}', '\u{16af4}', SC_Extend), ('\u{16af5}', '\u{16af5}', SC_STerm),
+ ('\u{16b00}', '\u{16b2f}', SC_OLetter), ('\u{16b30}', '\u{16b36}', SC_Extend), ('\u{16b37}',
+ '\u{16b38}', SC_STerm), ('\u{16b40}', '\u{16b43}', SC_OLetter), ('\u{16b44}', '\u{16b44}',
+ SC_STerm), ('\u{16b50}', '\u{16b59}', SC_Numeric), ('\u{16b63}', '\u{16b77}', SC_OLetter),
('\u{16b7d}', '\u{16b8f}', SC_OLetter), ('\u{16e40}', '\u{16e5f}', SC_Upper), ('\u{16e60}',
'\u{16e7f}', SC_Lower), ('\u{16e98}', '\u{16e98}', SC_STerm), ('\u{16f00}', '\u{16f4a}',
SC_OLetter), ('\u{16f4f}', '\u{16f4f}', SC_Extend), ('\u{16f50}', '\u{16f50}', SC_OLetter),
@@ -2562,7 +2592,8 @@ pub mod sentence {
('\u{17000}', '\u{187f7}', SC_OLetter), ('\u{18800}', '\u{18cd5}', SC_OLetter),
('\u{18d00}', '\u{18d08}', SC_OLetter), ('\u{1aff0}', '\u{1aff3}', SC_OLetter),
('\u{1aff5}', '\u{1affb}', SC_OLetter), ('\u{1affd}', '\u{1affe}', SC_OLetter),
- ('\u{1b000}', '\u{1b122}', SC_OLetter), ('\u{1b150}', '\u{1b152}', SC_OLetter),
+ ('\u{1b000}', '\u{1b122}', SC_OLetter), ('\u{1b132}', '\u{1b132}', SC_OLetter),
+ ('\u{1b150}', '\u{1b152}', SC_OLetter), ('\u{1b155}', '\u{1b155}', SC_OLetter),
('\u{1b164}', '\u{1b167}', SC_OLetter), ('\u{1b170}', '\u{1b2fb}', SC_OLetter),
('\u{1bc00}', '\u{1bc6a}', SC_OLetter), ('\u{1bc70}', '\u{1bc7c}', SC_OLetter),
('\u{1bc80}', '\u{1bc88}', SC_OLetter), ('\u{1bc90}', '\u{1bc99}', SC_OLetter),
@@ -2601,40 +2632,43 @@ pub mod sentence {
SC_Extend), ('\u{1da84}', '\u{1da84}', SC_Extend), ('\u{1da88}', '\u{1da88}', SC_STerm),
('\u{1da9b}', '\u{1da9f}', SC_Extend), ('\u{1daa1}', '\u{1daaf}', SC_Extend), ('\u{1df00}',
'\u{1df09}', SC_Lower), ('\u{1df0a}', '\u{1df0a}', SC_OLetter), ('\u{1df0b}', '\u{1df1e}',
- SC_Lower), ('\u{1e000}', '\u{1e006}', SC_Extend), ('\u{1e008}', '\u{1e018}', SC_Extend),
- ('\u{1e01b}', '\u{1e021}', SC_Extend), ('\u{1e023}', '\u{1e024}', SC_Extend), ('\u{1e026}',
- '\u{1e02a}', SC_Extend), ('\u{1e100}', '\u{1e12c}', SC_OLetter), ('\u{1e130}', '\u{1e136}',
- SC_Extend), ('\u{1e137}', '\u{1e13d}', SC_OLetter), ('\u{1e140}', '\u{1e149}', SC_Numeric),
- ('\u{1e14e}', '\u{1e14e}', SC_OLetter), ('\u{1e290}', '\u{1e2ad}', SC_OLetter),
- ('\u{1e2ae}', '\u{1e2ae}', SC_Extend), ('\u{1e2c0}', '\u{1e2eb}', SC_OLetter), ('\u{1e2ec}',
- '\u{1e2ef}', SC_Extend), ('\u{1e2f0}', '\u{1e2f9}', SC_Numeric), ('\u{1e7e0}', '\u{1e7e6}',
- SC_OLetter), ('\u{1e7e8}', '\u{1e7eb}', SC_OLetter), ('\u{1e7ed}', '\u{1e7ee}', SC_OLetter),
- ('\u{1e7f0}', '\u{1e7fe}', SC_OLetter), ('\u{1e800}', '\u{1e8c4}', SC_OLetter),
- ('\u{1e8d0}', '\u{1e8d6}', SC_Extend), ('\u{1e900}', '\u{1e921}', SC_Upper), ('\u{1e922}',
- '\u{1e943}', SC_Lower), ('\u{1e944}', '\u{1e94a}', SC_Extend), ('\u{1e94b}', '\u{1e94b}',
- SC_OLetter), ('\u{1e950}', '\u{1e959}', SC_Numeric), ('\u{1ee00}', '\u{1ee03}', SC_OLetter),
- ('\u{1ee05}', '\u{1ee1f}', SC_OLetter), ('\u{1ee21}', '\u{1ee22}', SC_OLetter),
- ('\u{1ee24}', '\u{1ee24}', SC_OLetter), ('\u{1ee27}', '\u{1ee27}', SC_OLetter),
- ('\u{1ee29}', '\u{1ee32}', SC_OLetter), ('\u{1ee34}', '\u{1ee37}', SC_OLetter),
- ('\u{1ee39}', '\u{1ee39}', SC_OLetter), ('\u{1ee3b}', '\u{1ee3b}', SC_OLetter),
- ('\u{1ee42}', '\u{1ee42}', SC_OLetter), ('\u{1ee47}', '\u{1ee47}', SC_OLetter),
- ('\u{1ee49}', '\u{1ee49}', SC_OLetter), ('\u{1ee4b}', '\u{1ee4b}', SC_OLetter),
- ('\u{1ee4d}', '\u{1ee4f}', SC_OLetter), ('\u{1ee51}', '\u{1ee52}', SC_OLetter),
- ('\u{1ee54}', '\u{1ee54}', SC_OLetter), ('\u{1ee57}', '\u{1ee57}', SC_OLetter),
- ('\u{1ee59}', '\u{1ee59}', SC_OLetter), ('\u{1ee5b}', '\u{1ee5b}', SC_OLetter),
- ('\u{1ee5d}', '\u{1ee5d}', SC_OLetter), ('\u{1ee5f}', '\u{1ee5f}', SC_OLetter),
- ('\u{1ee61}', '\u{1ee62}', SC_OLetter), ('\u{1ee64}', '\u{1ee64}', SC_OLetter),
- ('\u{1ee67}', '\u{1ee6a}', SC_OLetter), ('\u{1ee6c}', '\u{1ee72}', SC_OLetter),
- ('\u{1ee74}', '\u{1ee77}', SC_OLetter), ('\u{1ee79}', '\u{1ee7c}', SC_OLetter),
- ('\u{1ee7e}', '\u{1ee7e}', SC_OLetter), ('\u{1ee80}', '\u{1ee89}', SC_OLetter),
- ('\u{1ee8b}', '\u{1ee9b}', SC_OLetter), ('\u{1eea1}', '\u{1eea3}', SC_OLetter),
- ('\u{1eea5}', '\u{1eea9}', SC_OLetter), ('\u{1eeab}', '\u{1eebb}', SC_OLetter),
- ('\u{1f130}', '\u{1f149}', SC_Upper), ('\u{1f150}', '\u{1f169}', SC_Upper), ('\u{1f170}',
- '\u{1f189}', SC_Upper), ('\u{1f676}', '\u{1f678}', SC_Close), ('\u{1fbf0}', '\u{1fbf9}',
- SC_Numeric), ('\u{20000}', '\u{2a6df}', SC_OLetter), ('\u{2a700}', '\u{2b738}', SC_OLetter),
- ('\u{2b740}', '\u{2b81d}', SC_OLetter), ('\u{2b820}', '\u{2cea1}', SC_OLetter),
- ('\u{2ceb0}', '\u{2ebe0}', SC_OLetter), ('\u{2f800}', '\u{2fa1d}', SC_OLetter),
- ('\u{30000}', '\u{3134a}', SC_OLetter), ('\u{e0001}', '\u{e0001}', SC_Format), ('\u{e0020}',
+ SC_Lower), ('\u{1df25}', '\u{1df2a}', SC_Lower), ('\u{1e000}', '\u{1e006}', SC_Extend),
+ ('\u{1e008}', '\u{1e018}', SC_Extend), ('\u{1e01b}', '\u{1e021}', SC_Extend), ('\u{1e023}',
+ '\u{1e024}', SC_Extend), ('\u{1e026}', '\u{1e02a}', SC_Extend), ('\u{1e030}', '\u{1e06d}',
+ SC_Lower), ('\u{1e08f}', '\u{1e08f}', SC_Extend), ('\u{1e100}', '\u{1e12c}', SC_OLetter),
+ ('\u{1e130}', '\u{1e136}', SC_Extend), ('\u{1e137}', '\u{1e13d}', SC_OLetter), ('\u{1e140}',
+ '\u{1e149}', SC_Numeric), ('\u{1e14e}', '\u{1e14e}', SC_OLetter), ('\u{1e290}', '\u{1e2ad}',
+ SC_OLetter), ('\u{1e2ae}', '\u{1e2ae}', SC_Extend), ('\u{1e2c0}', '\u{1e2eb}', SC_OLetter),
+ ('\u{1e2ec}', '\u{1e2ef}', SC_Extend), ('\u{1e2f0}', '\u{1e2f9}', SC_Numeric), ('\u{1e4d0}',
+ '\u{1e4eb}', SC_OLetter), ('\u{1e4ec}', '\u{1e4ef}', SC_Extend), ('\u{1e4f0}', '\u{1e4f9}',
+ SC_Numeric), ('\u{1e7e0}', '\u{1e7e6}', SC_OLetter), ('\u{1e7e8}', '\u{1e7eb}', SC_OLetter),
+ ('\u{1e7ed}', '\u{1e7ee}', SC_OLetter), ('\u{1e7f0}', '\u{1e7fe}', SC_OLetter),
+ ('\u{1e800}', '\u{1e8c4}', SC_OLetter), ('\u{1e8d0}', '\u{1e8d6}', SC_Extend), ('\u{1e900}',
+ '\u{1e921}', SC_Upper), ('\u{1e922}', '\u{1e943}', SC_Lower), ('\u{1e944}', '\u{1e94a}',
+ SC_Extend), ('\u{1e94b}', '\u{1e94b}', SC_OLetter), ('\u{1e950}', '\u{1e959}', SC_Numeric),
+ ('\u{1ee00}', '\u{1ee03}', SC_OLetter), ('\u{1ee05}', '\u{1ee1f}', SC_OLetter),
+ ('\u{1ee21}', '\u{1ee22}', SC_OLetter), ('\u{1ee24}', '\u{1ee24}', SC_OLetter),
+ ('\u{1ee27}', '\u{1ee27}', SC_OLetter), ('\u{1ee29}', '\u{1ee32}', SC_OLetter),
+ ('\u{1ee34}', '\u{1ee37}', SC_OLetter), ('\u{1ee39}', '\u{1ee39}', SC_OLetter),
+ ('\u{1ee3b}', '\u{1ee3b}', SC_OLetter), ('\u{1ee42}', '\u{1ee42}', SC_OLetter),
+ ('\u{1ee47}', '\u{1ee47}', SC_OLetter), ('\u{1ee49}', '\u{1ee49}', SC_OLetter),
+ ('\u{1ee4b}', '\u{1ee4b}', SC_OLetter), ('\u{1ee4d}', '\u{1ee4f}', SC_OLetter),
+ ('\u{1ee51}', '\u{1ee52}', SC_OLetter), ('\u{1ee54}', '\u{1ee54}', SC_OLetter),
+ ('\u{1ee57}', '\u{1ee57}', SC_OLetter), ('\u{1ee59}', '\u{1ee59}', SC_OLetter),
+ ('\u{1ee5b}', '\u{1ee5b}', SC_OLetter), ('\u{1ee5d}', '\u{1ee5d}', SC_OLetter),
+ ('\u{1ee5f}', '\u{1ee5f}', SC_OLetter), ('\u{1ee61}', '\u{1ee62}', SC_OLetter),
+ ('\u{1ee64}', '\u{1ee64}', SC_OLetter), ('\u{1ee67}', '\u{1ee6a}', SC_OLetter),
+ ('\u{1ee6c}', '\u{1ee72}', SC_OLetter), ('\u{1ee74}', '\u{1ee77}', SC_OLetter),
+ ('\u{1ee79}', '\u{1ee7c}', SC_OLetter), ('\u{1ee7e}', '\u{1ee7e}', SC_OLetter),
+ ('\u{1ee80}', '\u{1ee89}', SC_OLetter), ('\u{1ee8b}', '\u{1ee9b}', SC_OLetter),
+ ('\u{1eea1}', '\u{1eea3}', SC_OLetter), ('\u{1eea5}', '\u{1eea9}', SC_OLetter),
+ ('\u{1eeab}', '\u{1eebb}', SC_OLetter), ('\u{1f130}', '\u{1f149}', SC_Upper), ('\u{1f150}',
+ '\u{1f169}', SC_Upper), ('\u{1f170}', '\u{1f189}', SC_Upper), ('\u{1f676}', '\u{1f678}',
+ SC_Close), ('\u{1fbf0}', '\u{1fbf9}', SC_Numeric), ('\u{20000}', '\u{2a6df}', SC_OLetter),
+ ('\u{2a700}', '\u{2b739}', SC_OLetter), ('\u{2b740}', '\u{2b81d}', SC_OLetter),
+ ('\u{2b820}', '\u{2cea1}', SC_OLetter), ('\u{2ceb0}', '\u{2ebe0}', SC_OLetter),
+ ('\u{2f800}', '\u{2fa1d}', SC_OLetter), ('\u{30000}', '\u{3134a}', SC_OLetter),
+ ('\u{31350}', '\u{323af}', SC_OLetter), ('\u{e0001}', '\u{e0001}', SC_Format), ('\u{e0020}',
'\u{e007f}', SC_Extend), ('\u{e0100}', '\u{e01ef}', SC_Extend)
];
diff --git a/vendor/unicode-segmentation/src/testdata.rs b/vendor/unicode-segmentation/src/testdata.rs
index b4a1cc0c3..8a675aafe 100644
--- a/vendor/unicode-segmentation/src/testdata.rs
+++ b/vendor/unicode-segmentation/src/testdata.rs
@@ -12,7 +12,7 @@
#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
// official Unicode test data
-// http://www.unicode.org/Public/14.0.0/ucd/auxiliary/GraphemeBreakTest.txt
+// http://www.unicode.org/Public/15.0.0/ucd/auxiliary/GraphemeBreakTest.txt
pub const TEST_SAME: &'static [(&'static str, &'static [&'static str])] = &[
("\u{20}\u{20}", &["\u{20}", "\u{20}"]),
("\u{20}\u{308}\u{20}", &["\u{20}\u{308}", "\u{20}"]),
@@ -886,7 +886,7 @@ pub const TEST_DIFF: &'static [(
];
// official Unicode test data
-// http://www.unicode.org/Public/14.0.0/ucd/auxiliary/WordBreakTest.txt
+// http://www.unicode.org/Public/15.0.0/ucd/auxiliary/WordBreakTest.txt
pub const TEST_WORD: &'static [(&'static str, &'static [&'static str])] = &[
("\u{1}\u{1}", &["\u{1}", "\u{1}"]),
("\u{1}\u{308}\u{1}", &["\u{1}\u{308}", "\u{1}"]),
@@ -4917,7 +4917,7 @@ pub const TEST_WORD: &'static [(&'static str, &'static [&'static str])] = &[
];
// official Unicode test data
-// http://www.unicode.org/Public/14.0.0/ucd/auxiliary/SentenceBreakTest.txt
+// http://www.unicode.org/Public/15.0.0/ucd/auxiliary/SentenceBreakTest.txt
pub const TEST_SENTENCE: &'static [(&'static str, &'static [&'static str])] = &[
("\u{1}\u{1}", &["\u{1}\u{1}"]), ("\u{1}\u{308}\u{1}", &["\u{1}\u{308}\u{1}"]),
("\u{1}\u{d}", &["\u{1}\u{d}"]), ("\u{1}\u{308}\u{d}", &["\u{1}\u{308}\u{d}"]),
diff --git a/vendor/unicode-width/.cargo-checksum.json b/vendor/unicode-width/.cargo-checksum.json
index 0d3d03912..5c7b92228 100644
--- a/vendor/unicode-width/.cargo-checksum.json
+++ b/vendor/unicode-width/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"5c1c5fff7aaa9b6a7a2331ec2e26064e4cd519254446675196fb2eb5cc91c282","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"8a041a4305fb318f5c2cb284046f8480796521d0e829023b0441b5e8469490eb","scripts/unicode.py":"5c7d8d78b70223d9f0d6713bd5714c3a6fd4fcee4ed1b3bf749c84ed6dc7479a","src/lib.rs":"38c44436eac069bd8d11203f31ecfef8adfe92da1fce19ba00bdd25aa3fbbe20","src/tables.rs":"4026a4c18a4904edc38dff6fa6a179623091b5b6e8c434605f49d2377b4e8a01","src/tests.rs":"ca610f64b76ded8abb4b0cc5f373b40cf25cef009988fa6bd3382d0de3356bf7"},"package":"3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"} \ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"f22e31fb3559e916864820719a09ab3adbf80301440e1702acf827210bbf76df","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"8a041a4305fb318f5c2cb284046f8480796521d0e829023b0441b5e8469490eb","scripts/unicode.py":"0c53095ef99395338399f9ad218b4481cffcf63774fd61871ed32efb242419f8","src/lib.rs":"38c44436eac069bd8d11203f31ecfef8adfe92da1fce19ba00bdd25aa3fbbe20","src/tables.rs":"c6ddb420c289517bb92973199fd2987b9608f29fc10bb33b5290f39b301ce92f","src/tests.rs":"ff9f331210861ba78040f119a0f6ccfacf5b2ca1ebee430784de0858fad01860"},"package":"c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"} \ No newline at end of file
diff --git a/vendor/unicode-width/Cargo.toml b/vendor/unicode-width/Cargo.toml
index 9cb47d54c..77aded9fc 100644
--- a/vendor/unicode-width/Cargo.toml
+++ b/vendor/unicode-width/Cargo.toml
@@ -11,16 +11,30 @@
[package]
name = "unicode-width"
-version = "0.1.9"
-authors = ["kwantam <kwantam@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>"]
-exclude = ["target/*", "Cargo.lock"]
-description = "Determine displayed width of `char` and `str` types\naccording to Unicode Standard Annex #11 rules.\n"
+version = "0.1.10"
+authors = [
+ "kwantam <kwantam@gmail.com>",
+ "Manish Goregaokar <manishsmail@gmail.com>",
+]
+exclude = [
+ "target/*",
+ "Cargo.lock",
+]
+description = """
+Determine displayed width of `char` and `str` types
+according to Unicode Standard Annex #11 rules.
+"""
homepage = "https://github.com/unicode-rs/unicode-width"
documentation = "https://unicode-rs.github.io/unicode-width"
readme = "README.md"
-keywords = ["text", "width", "unicode"]
+keywords = [
+ "text",
+ "width",
+ "unicode",
+]
license = "MIT/Apache-2.0"
repository = "https://github.com/unicode-rs/unicode-width"
+
[dependencies.compiler_builtins]
version = "0.1"
optional = true
@@ -39,4 +53,8 @@ package = "rustc-std-workspace-std"
bench = []
default = []
no_std = []
-rustc-dep-of-std = ["std", "core", "compiler_builtins"]
+rustc-dep-of-std = [
+ "std",
+ "core",
+ "compiler_builtins",
+]
diff --git a/vendor/unicode-width/scripts/unicode.py b/vendor/unicode-width/scripts/unicode.py
index 7f5959d4b..2efb0b63f 100755
--- a/vendor/unicode-width/scripts/unicode.py
+++ b/vendor/unicode-width/scripts/unicode.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright 2011-2015 The Rust Project Developers. See the COPYRIGHT
+# Copyright 2011-2022 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
@@ -16,11 +16,322 @@
# - UnicodeData.txt
#
# Since this should not require frequent updates, we just store this
-# out-of-line and check the unicode.rs file into git.
-
-import fileinput, re, os, sys, operator
+# out-of-line and check the generated module into git.
+
+import enum
+import math
+import os
+import re
+import sys
+
+NUM_CODEPOINTS = 0x110000
+"""An upper bound for which `range(0, NUM_CODEPOINTS)` contains Unicode's codespace."""
+
+MAX_CODEPOINT_BITS = math.ceil(math.log2(NUM_CODEPOINTS - 1))
+"""The maximum number of bits required to represent a Unicode codepoint."""
+
+
+class OffsetType(enum.IntEnum):
+ """Represents the data type of a lookup table's offsets. Each variant's value represents the
+ number of bits required to represent that variant's type."""
+
+ U2 = 2
+ """Offsets are 2-bit unsigned integers, packed four-per-byte."""
+ U4 = 4
+ """Offsets are 4-bit unsigned integers, packed two-per-byte."""
+ U8 = 8
+ """Each offset is a single byte (u8)."""
+
+
+TABLE_CFGS = [
+ (13, MAX_CODEPOINT_BITS, OffsetType.U8),
+ (6, 13, OffsetType.U8),
+ (0, 6, OffsetType.U2),
+]
+"""Represents the format of each level of the multi-level lookup table.
+A level's entry is of the form `(low_bit, cap_bit, offset_type)`.
+This means that every sub-table in that level is indexed by bits `low_bit..cap_bit` of the
+codepoint and those tables offsets are stored according to `offset_type`.
+
+If this is edited, you must ensure that `emit_module` reflects your changes."""
+
+MODULE_FILENAME = "tables.rs"
+"""The filename of the emitted Rust module (will be created in the working directory)"""
+
+Codepoint = int
+BitPos = int
+
+
+def fetch_open(filename: str):
+ """Opens `filename` and return its corresponding file object. If `filename` isn't on disk,
+ fetches it from `http://www.unicode.org/Public/UNIDATA/`. Exits with code 1 on failure."""
+ if not os.path.exists(os.path.basename(filename)):
+ os.system(f"curl -O http://www.unicode.org/Public/UNIDATA/{filename}")
+ try:
+ return open(filename, encoding="utf-8")
+ except OSError:
+ sys.stderr.write(f"cannot load {filename}")
+ sys.exit(1)
+
+
+def load_unicode_version() -> "tuple[int, int, int]":
+ """Returns the current Unicode version by fetching and processing `ReadMe.txt`."""
+ with fetch_open("ReadMe.txt") as readme:
+ pattern = r"for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
+ return tuple(map(int, re.search(pattern, readme.read()).groups()))
+
+
+class EffectiveWidth(enum.IntEnum):
+ """Represents the width of a Unicode character. All East Asian Width classes resolve into
+ either `EffectiveWidth.NARROW`, `EffectiveWidth.WIDE`, or `EffectiveWidth.AMBIGUOUS`."""
+
+ ZERO = 0
+ """ Zero columns wide. """
+ NARROW = 1
+ """ One column wide. """
+ WIDE = 2
+ """ Two columns wide. """
+ AMBIGUOUS = 3
+ """ Two columns wide in a CJK context. One column wide in all other contexts. """
+
+
+def load_east_asian_widths() -> "list[EffectiveWidth]":
+ """Return a list of effective widths, indexed by codepoint.
+ Widths are determined by fetching and parsing `EastAsianWidth.txt`.
+
+ `Neutral`, `Narrow`, and `Halfwidth` characters are assigned `EffectiveWidth.NARROW`.
+
+ `Wide` and `Fullwidth` characters are assigned `EffectiveWidth.WIDE`.
+
+ `Ambiguous` chracters are assigned `EffectiveWidth.AMBIGUOUS`."""
+ with fetch_open("EastAsianWidth.txt") as eaw:
+ # matches a width assignment for a single codepoint, i.e. "1F336;N # ..."
+ single = re.compile(r"^([0-9A-F]+);(\w+) +# (\w+)")
+ # matches a width assignment for a range of codepoints, i.e. "3001..3003;W # ..."
+ multiple = re.compile(r"^([0-9A-F]+)\.\.([0-9A-F]+);(\w+) +# (\w+)")
+ # map between width category code and condensed width
+ width_codes = {
+ **{c: EffectiveWidth.NARROW for c in ["N", "Na", "H"]},
+ **{c: EffectiveWidth.WIDE for c in ["W", "F"]},
+ "A": EffectiveWidth.AMBIGUOUS,
+ }
-preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+ width_map = []
+ current = 0
+ for line in eaw.readlines():
+ raw_data = None # (low, high, width)
+ if match := single.match(line):
+ raw_data = (match.group(1), match.group(1), match.group(2))
+ elif match := multiple.match(line):
+ raw_data = (match.group(1), match.group(2), match.group(3))
+ else:
+ continue
+ low = int(raw_data[0], 16)
+ high = int(raw_data[1], 16)
+ width = width_codes[raw_data[2]]
+
+ assert current <= high
+ while current <= high:
+ # Some codepoints don't fall into any of the ranges in EastAsianWidth.txt.
+ # All such codepoints are implicitly given Neural width (resolves to narrow)
+ width_map.append(EffectiveWidth.NARROW if current < low else width)
+ current += 1
+
+ while len(width_map) < NUM_CODEPOINTS:
+ # Catch any leftover codepoints and assign them implicit Neutral/narrow width.
+ width_map.append(EffectiveWidth.NARROW)
+
+ return width_map
+
+
+def load_zero_widths() -> "list[bool]":
+ """Returns a list `l` where `l[c]` is true if codepoint `c` is considered a zero-width
+ character. `c` is considered a zero-width character if `c` is in general categories
+ `Cc`, `Cf`, `Mn`, or `Me` (determined by fetching and processing `UnicodeData.txt`)."""
+ with fetch_open("UnicodeData.txt") as categories:
+ zw_map = []
+ current = 0
+ for line in categories.readlines():
+ if len(raw_data := line.split(";")) != 15:
+ continue
+ [codepoint, name, cat_code] = [
+ int(raw_data[0], 16),
+ raw_data[1],
+ raw_data[2],
+ ]
+ zero_width = cat_code in ["Cc", "Cf", "Mn", "Me"]
+
+ assert current <= codepoint
+ while current <= codepoint:
+ if name.endswith(", Last>") or current == codepoint:
+ # if name ends with Last, we backfill the width value to all codepoints since
+ # the previous codepoint (aka the start of the range)
+ zw_map.append(zero_width)
+ else:
+ # unassigned characters are implicitly given Neutral width, which is nonzero
+ zw_map.append(False)
+ current += 1
+
+ while len(zw_map) < NUM_CODEPOINTS:
+ # Catch any leftover codepoints. They must be unassigned (so nonzero width)
+ zw_map.append(False)
+
+ return zw_map
+
+
+class Bucket:
+ """A bucket contains a group of codepoints and an ordered width list. If one bucket's width
+ list overlaps with another's width list, those buckets can be merged via `try_extend`."""
+
+ def __init__(self):
+ """Creates an empty bucket."""
+ self.entry_set = set()
+ self.widths = []
+
+ def append(self, codepoint: Codepoint, width: EffectiveWidth):
+ """Adds a codepoint/width pair to the bucket, and appends `width` to the width list."""
+ self.entry_set.add((codepoint, width))
+ self.widths.append(width)
+
+ def try_extend(self, attempt: "Bucket") -> bool:
+ """If either `self` or `attempt`'s width list starts with the other bucket's width list,
+ set `self`'s width list to the longer of the two, add all of `attempt`'s codepoints
+ into `self`, and return `True`. Otherwise, return `False`."""
+ (less, more) = (self.widths, attempt.widths)
+ if len(self.widths) > len(attempt.widths):
+ (less, more) = (attempt.widths, self.widths)
+ if less != more[: len(less)]:
+ return False
+ self.entry_set |= attempt.entry_set
+ self.widths = more
+ return True
+
+ def entries(self) -> "list[tuple[Codepoint, EffectiveWidth]]":
+ """Return a list of the codepoint/width pairs in this bucket, sorted by codepoint."""
+ result = list(self.entry_set)
+ result.sort()
+ return result
+
+ def width(self) -> "EffectiveWidth":
+ """If all codepoints in this bucket have the same width, return that width; otherwise,
+ return `None`."""
+ if len(self.widths) == 0:
+ return None
+ potential_width = self.widths[0]
+ for width in self.widths[1:]:
+ if potential_width != width:
+ return None
+ return potential_width
+
+
+def make_buckets(entries, low_bit: BitPos, cap_bit: BitPos) -> "list[Bucket]":
+ """Partitions the `(Codepoint, EffectiveWidth)` tuples in `entries` into `Bucket`s. All
+ codepoints with identical bits from `low_bit` to `cap_bit` (exclusive) are placed in the
+ same bucket. Returns a list of the buckets in increasing order of those bits."""
+ num_bits = cap_bit - low_bit
+ assert num_bits > 0
+ buckets = [Bucket() for _ in range(0, 2 ** num_bits)]
+ mask = (1 << num_bits) - 1
+ for (codepoint, width) in entries:
+ buckets[(codepoint >> low_bit) & mask].append(codepoint, width)
+ return buckets
+
+
+class Table:
+ """Represents a lookup table. Each table contains a certain number of subtables; each
+ subtable is indexed by a contiguous bit range of the codepoint and contains a list
+ of `2**(number of bits in bit range)` entries. (The bit range is the same for all subtables.)
+
+ Typically, tables contain a list of buckets of codepoints. Bucket `i`'s codepoints should
+ be indexed by sub-table `i` in the next-level lookup table. The entries of this table are
+ indexes into the bucket list (~= indexes into the sub-tables of the next-level table.) The
+ key to compression is that two different buckets in two different sub-tables may have the
+ same width list, which means that they can be merged into the same bucket.
+
+ If no bucket contains two codepoints with different widths, calling `indices_to_widths` will
+ discard the buckets and convert the entries into `EffectiveWidth` values."""
+
+ def __init__(
+ self, entry_groups, low_bit: BitPos, cap_bit: BitPos, offset_type: OffsetType
+ ):
+ """Create a lookup table with a sub-table for each `(Codepoint, EffectiveWidth)` iterator
+ in `entry_groups`. Each sub-table is indexed by codepoint bits in `low_bit..cap_bit`,
+ and each table entry is represented in the format specified by `offset_type`. Asserts
+ that this table is actually representable with `offset_type`."""
+ self.low_bit = low_bit
+ self.cap_bit = cap_bit
+ self.offset_type = offset_type
+ self.entries = []
+ self.indexed = []
+
+ buckets = []
+ for entries in entry_groups:
+ buckets.extend(make_buckets(entries, self.low_bit, self.cap_bit))
+
+ for bucket in buckets:
+ for (i, existing) in enumerate(self.indexed):
+ if existing.try_extend(bucket):
+ self.entries.append(i)
+ break
+ else:
+ self.entries.append(len(self.indexed))
+ self.indexed.append(bucket)
+
+ # Validate offset type
+ for index in self.entries:
+ assert index < (1 << int(self.offset_type))
+
+ def indices_to_widths(self):
+ """Destructively converts the indices in this table to the `EffectiveWidth` values of
+ their buckets. Assumes that no bucket contains codepoints with different widths."""
+ self.entries = list(map(lambda i: int(self.indexed[i].width()), self.entries))
+ del self.indexed
+
+ def buckets(self):
+ """Returns an iterator over this table's buckets."""
+ return self.indexed
+
+ def to_bytes(self) -> "list[int]":
+ """Returns this table's entries as a list of bytes. The bytes are formatted according to
+ the `OffsetType` which the table was created with, converting any `EffectiveWidth` entries
+ to their enum variant's integer value. For example, with `OffsetType.U2`, each byte will
+ contain four packed 2-bit entries."""
+ entries_per_byte = 8 // int(self.offset_type)
+ byte_array = []
+ for i in range(0, len(self.entries), entries_per_byte):
+ byte = 0
+ for j in range(0, entries_per_byte):
+ byte |= self.entries[i + j] << (j * int(self.offset_type))
+ byte_array.append(byte)
+ return byte_array
+
+
+def make_tables(
+ table_cfgs: "list[tuple[BitPos, BitPos, OffsetType]]", entries
+) -> "list[Table]":
+ """Creates a table for each configuration in `table_cfgs`, with the first config corresponding
+ to the top-level lookup table, the second config corresponding to the second-level lookup
+ table, and so forth. `entries` is an iterator over the `(Codepoint, EffectiveWidth)` pairs
+ to include in the top-level table."""
+ tables = []
+ entry_groups = [entries]
+ for (low_bit, cap_bit, offset_type) in table_cfgs:
+ table = Table(entry_groups, low_bit, cap_bit, offset_type)
+ entry_groups = map(lambda bucket: bucket.entries(), table.buckets())
+ tables.append(table)
+ return tables
+
+
+def emit_module(
+ out_name: str, unicode_version: "tuple[int, int, int]", tables: "list[Table]"
+):
+ """Outputs a Rust module to `out_name` using table data from `tables`.
+ If `TABLE_CFGS` is edited, you may need to edit the included code for `lookup_width`."""
+ if os.path.exists(out_name):
+ os.remove(out_name)
+ with open(out_name, "w", newline="\n", encoding="utf-8") as module:
+ module.write(
+ """// Copyright 2012-2022 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -31,291 +342,164 @@ preamble = '''// Copyright 2012-2015 The Rust Project Developers. See the COPYRI
// except according to those terms.
// NOTE: The following code was generated by "scripts/unicode.py", do not edit directly
-
-#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
-'''
-
-# Mapping taken from Table 12 from:
-# http://www.unicode.org/reports/tr44/#General_Category_Values
-expanded_categories = {
- 'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'],
- 'Lm': ['L'], 'Lo': ['L'],
- 'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'],
- 'Nd': ['N'], 'Nl': ['N'], 'No': ['No'],
- 'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'],
- 'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'],
- 'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'],
- 'Zs': ['Z'], 'Zl': ['Z'], 'Zp': ['Z'],
- 'Cc': ['C'], 'Cf': ['C'], 'Cs': ['C'], 'Co': ['C'], 'Cn': ['C'],
-}
-
-# these are the surrogate codepoints, which are not valid rust characters
-surrogate_codepoints = (0xd800, 0xdfff)
-
-def fetch(f):
- if not os.path.exists(os.path.basename(f)):
- os.system("curl -O http://www.unicode.org/Public/UNIDATA/%s"
- % f)
-
- if not os.path.exists(os.path.basename(f)):
- sys.stderr.write("cannot load %s" % f)
- exit(1)
-
-def is_surrogate(n):
- return surrogate_codepoints[0] <= n <= surrogate_codepoints[1]
-
-def load_unicode_data(f):
- fetch(f)
- gencats = {}
-
- udict = {}
- range_start = -1
- for line in fileinput.input(f):
- data = line.split(';')
- if len(data) != 15:
- continue
- cp = int(data[0], 16)
- if is_surrogate(cp):
- continue
- if range_start >= 0:
- for i in range(range_start, cp):
- udict[i] = data
- range_start = -1
- if data[1].endswith(", First>"):
- range_start = cp
- continue
- udict[cp] = data
-
- for code in udict:
- [code_org, name, gencat, combine, bidi,
- decomp, deci, digit, num, mirror,
- old, iso, upcase, lowcase, titlecase ] = udict[code]
-
- # place letter in categories as appropriate
- for cat in [gencat, "Assigned"] + expanded_categories.get(gencat, []):
- if cat not in gencats:
- gencats[cat] = []
- gencats[cat].append(code)
-
- gencats = group_cats(gencats)
-
- return gencats
-
-def group_cats(cats):
- cats_out = {}
- for cat in cats:
- cats_out[cat] = group_cat(cats[cat])
- return cats_out
-
-def group_cat(cat):
- cat_out = []
- letters = sorted(set(cat))
- cur_start = letters.pop(0)
- cur_end = cur_start
- for letter in letters:
- assert letter > cur_end, \
- "cur_end: %s, letter: %s" % (hex(cur_end), hex(letter))
- if letter == cur_end + 1:
- cur_end = letter
- else:
- cat_out.append((cur_start, cur_end))
- cur_start = cur_end = letter
- cat_out.append((cur_start, cur_end))
- return cat_out
-
-def format_table_content(f, content, indent):
- line = " "*indent
- first = True
- for chunk in content.split(","):
- if len(line) + len(chunk) < 98:
- if first:
- line += chunk
- else:
- line += ", " + chunk
- first = False
- else:
- f.write(line + ",\n")
- line = " "*indent + chunk
- f.write(line)
-
-# load all widths of want_widths, except those in except_cats
-def load_east_asian_width(want_widths, except_cats):
- f = "EastAsianWidth.txt"
- fetch(f)
- widths = {}
- re1 = re.compile("^([0-9A-F]+);(\w+) +# (\w+)")
- re2 = re.compile("^([0-9A-F]+)\.\.([0-9A-F]+);(\w+) +# (\w+)")
-
- for line in fileinput.input(f):
- width = None
- d_lo = 0
- d_hi = 0
- cat = None
- m = re1.match(line)
- if m:
- d_lo = m.group(1)
- d_hi = m.group(1)
- width = m.group(2)
- cat = m.group(3)
- else:
- m = re2.match(line)
- if m:
- d_lo = m.group(1)
- d_hi = m.group(2)
- width = m.group(3)
- cat = m.group(4)
- else:
- continue
- if cat in except_cats or width not in want_widths:
- continue
- d_lo = int(d_lo, 16)
- d_hi = int(d_hi, 16)
- if width not in widths:
- widths[width] = []
- widths[width].append((d_lo, d_hi))
- return widths
-
-def escape_char(c):
- return "'\\u{%x}'" % c
-
-def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True,
- pfun=lambda x: "(%s,%s)" % (escape_char(x[0]), escape_char(x[1])), is_const=True):
- pub_string = "const"
- if not is_const:
- pub_string = "let"
- if is_pub:
- pub_string = "pub " + pub_string
- f.write(" %s %s: %s = &[\n" % (pub_string, name, t_type))
- data = ""
- first = True
- for dat in t_data:
- if not first:
- data += ","
- first = False
- data += pfun(dat)
- format_table_content(f, data, 8)
- f.write("\n ];\n\n")
-
-def emit_charwidth_module(f, width_table):
- f.write("pub mod charwidth {")
- f.write("""
- use core::option::Option::{self, Some, None};
- use core::result::Result::{Ok, Err};
-
+"""
+ )
+ module.write(
+ f"""
+/// The version of [Unicode](http://www.unicode.org/)
+/// that this version of unicode-width is based on.
+pub const UNICODE_VERSION: (u8, u8, u8) = {unicode_version};
+"""
+ )
+
+ module.write(
+ """
+pub mod charwidth {
+ use core::option::Option::{self, None, Some};
+
+ /// Returns the [UAX #11](https://www.unicode.org/reports/tr11/) based width of `c` by
+ /// consulting a multi-level lookup table.
+ /// If `is_cjk == true`, ambiguous width characters are treated as double width; otherwise,
+ /// they're treated as single width.
+ ///
+ /// # Maintenance
+ /// The tables themselves are autogenerated but this function is hardcoded. You should have
+ /// nothing to worry about if you re-run `unicode.py` (for example, when updating Unicode.)
+ /// However, if you change the *actual structure* of the lookup tables (perhaps by editing the
+ /// `TABLE_CFGS` global in `unicode.py`) you must ensure that this code reflects those changes.
#[inline]
- fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
- use core::cmp::Ordering::{Equal, Less, Greater};
- match r.binary_search_by(|&(lo, hi, _, _)| {
- if lo <= c && c <= hi { Equal }
- else if hi < c { Less }
- else { Greater }
- }) {
- Ok(idx) => {
- let (_, _, r_ncjk, r_cjk) = r[idx];
- if is_cjk { r_cjk } else { r_ncjk }
+ fn lookup_width(c: char, is_cjk: bool) -> usize {
+ let cp = c as usize;
+
+ let t1_offset = TABLES_0[cp >> 13 & 0xFF];
+
+ // Each sub-table in TABLES_1 is 7 bits, and each stored entry is a byte,
+ // so each sub-table is 128 bytes in size.
+ // (Sub-tables are selected using the computed offset from the previous table.)
+ let t2_offset = TABLES_1[128 * usize::from(t1_offset) + (cp >> 6 & 0x7F)];
+
+ // Each sub-table in TABLES_2 is 6 bits, but each stored entry is 2 bits.
+ // This is accomplished by packing four stored entries into one byte.
+ // So each sub-table is 2**(6-2) == 16 bytes in size.
+ // Since this is the last table, each entry represents an encoded width.
+ let packed_widths = TABLES_2[16 * usize::from(t2_offset) + (cp >> 2 & 0xF)];
+
+ // Extract the packed width
+ let width = packed_widths >> (2 * (cp & 0b11)) & 0b11;
+
+ // A width of 3 signifies that the codepoint is ambiguous width.
+ if width == 3 {
+ if is_cjk {
+ 2
+ } else {
+ 1
}
- Err(_) => 1
+ } else {
+ width.into()
}
}
-""")
-
- f.write("""
+"""
+ )
+
+ module.write(
+ """
+ /// Returns the [UAX #11](https://www.unicode.org/reports/tr11/) based width of `c`, or
+ /// `None` if `c` is a control character other than `'\\x00'`.
+ /// If `is_cjk == true`, ambiguous width characters are treated as double width; otherwise,
+ /// they're treated as single width.
#[inline]
pub fn width(c: char, is_cjk: bool) -> Option<usize> {
- match c as usize {
- _c @ 0 => Some(0), // null is zero width
- cu if cu < 0x20 => None, // control sequences have no width
- cu if cu < 0x7F => Some(1), // ASCII
- cu if cu < 0xA0 => None, // more control sequences
- _ => Some(bsearch_range_value_table(c, is_cjk, charwidth_table) as usize)
+ if c < '\\u{7F}' {
+ if c >= '\\u{20}' {
+ // U+0020 to U+007F (exclusive) are single-width ASCII codepoints
+ Some(1)
+ } else if c == '\\0' {
+ // U+0000 *is* a control code, but it's special-cased
+ Some(0)
+ } else {
+ // U+0001 to U+0020 (exclusive) are control codes
+ None
+ }
+ } else if c >= '\\u{A0}' {
+ // No characters >= U+00A0 are control codes, so we can consult the lookup tables
+ Some(lookup_width(c, is_cjk))
+ } else {
+ // U+007F to U+00A0 (exclusive) are control codes
+ None
}
}
+"""
+ )
+
+ subtable_count = 1
+ for (i, table) in enumerate(tables):
+ new_subtable_count = len(table.buckets())
+ if i == len(tables) - 1:
+ table.indices_to_widths() # for the last table, indices == widths
+ byte_array = table.to_bytes()
+ module.write(
+ f"""
+ /// Autogenerated. {subtable_count} sub-table(s). Consult [`lookup_width`] for layout info.
+ static TABLES_{i}: [u8; {len(byte_array)}] = ["""
+ )
+ for (j, byte) in enumerate(byte_array):
+ # Add line breaks for every 15th entry (chosen to match what rustfmt does)
+ if j % 15 == 0:
+ module.write("\n ")
+ module.write(f" 0x{byte:02X},")
+ module.write("\n ];\n")
+ subtable_count = new_subtable_count
+ module.write("}\n")
+
+
+def main(module_filename: str):
+ """Obtain character data from the latest version of Unicode, transform it into a multi-level
+ lookup table for character width, and write a Rust module utilizing that table to
+ `module_filename`.
+
+ We obey the following rules in decreasing order of importance:
+ - The soft hyphen (`U+00AD`) is single-width.
+ - Hangul Jamo medial vowels & final consonants (`U+1160..=U+11FF`) are zero-width.
+ - All codepoints in general categories `Cc`, `Cf`, `Mn`, and `Me` are zero-width.
+ - All codepoints with an East Asian Width of `Ambigous` are ambiguous-width.
+ - All codepoints with an East Asian Width of `Wide` or `Fullwidth` are double-width.
+ - All other codepoints (including unassigned codepoints and codepoints with an East Asian Width
+ of `Neutral`, `Narrow`, or `Halfwidth`) are single-width.
+
+ These rules are based off of Markus Kuhn's free `wcwidth()` implementation:
+ http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c"""
+ version = load_unicode_version()
+ print(f"Generating module for Unicode {version[0]}.{version[1]}.{version[2]}")
+
+ eaw_map = load_east_asian_widths()
+ zw_map = load_zero_widths()
+
+ # Characters marked as zero-width in zw_map should be zero-width in the final map
+ width_map = list(
+ map(lambda x: EffectiveWidth.ZERO if x[1] else x[0], zip(eaw_map, zw_map))
+ )
+
+ # Override for soft hyphen
+ width_map[0x00AD] = EffectiveWidth.NARROW
+
+ # Override for Hangul Jamo medial vowels & final consonants
+ for i in range(0x1160, 0x11FF + 1):
+ width_map[i] = EffectiveWidth.ZERO
+
+ tables = make_tables(TABLE_CFGS, enumerate(width_map))
+
+ print("------------------------")
+ total_size = 0
+ for (i, table) in enumerate(tables):
+ size_bytes = len(table.to_bytes())
+ print(f"Table {i} Size: {size_bytes} bytes")
+ total_size += size_bytes
+ print("------------------------")
+ print(f" Total Size: {total_size} bytes")
+
+ emit_module(module_filename, version, tables)
+ print(f'Wrote to "{module_filename}"')
-""")
-
- f.write(" // character width table. Based on Markus Kuhn's free wcwidth() implementation,\n")
- f.write(" // http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c\n")
- emit_table(f, "charwidth_table", width_table, "&'static [(char, char, u8, u8)]", is_pub=False,
- pfun=lambda x: "(%s,%s,%s,%s)" % (escape_char(x[0]), escape_char(x[1]), x[2], x[3]))
- f.write("}\n\n")
-
-def remove_from_wtable(wtable, val):
- wtable_out = []
- while wtable:
- if wtable[0][1] < val:
- wtable_out.append(wtable.pop(0))
- elif wtable[0][0] > val:
- break
- else:
- (wt_lo, wt_hi, width, width_cjk) = wtable.pop(0)
- if wt_lo == wt_hi == val:
- continue
- elif wt_lo == val:
- wtable_out.append((wt_lo+1, wt_hi, width, width_cjk))
- elif wt_hi == val:
- wtable_out.append((wt_lo, wt_hi-1, width, width_cjk))
- else:
- wtable_out.append((wt_lo, val-1, width, width_cjk))
- wtable_out.append((val+1, wt_hi, width, width_cjk))
- if wtable:
- wtable_out.extend(wtable)
- return wtable_out
-
-
-
-def optimize_width_table(wtable):
- wtable_out = []
- w_this = wtable.pop(0)
- while wtable:
- if w_this[1] == wtable[0][0] - 1 and w_this[2:3] == wtable[0][2:3]:
- w_tmp = wtable.pop(0)
- w_this = (w_this[0], w_tmp[1], w_tmp[2], w_tmp[3])
- else:
- wtable_out.append(w_this)
- w_this = wtable.pop(0)
- wtable_out.append(w_this)
- return wtable_out
if __name__ == "__main__":
- r = "tables.rs"
- if os.path.exists(r):
- os.remove(r)
- with open(r, "w") as rf:
- # write the file's preamble
- rf.write(preamble)
-
- # download and parse all the data
- fetch("ReadMe.txt")
- with open("ReadMe.txt") as readme:
- pattern = "for Version (\d+)\.(\d+)\.(\d+) of the Unicode"
- unicode_version = re.search(pattern, readme.read()).groups()
- rf.write("""
-/// The version of [Unicode](http://www.unicode.org/)
-/// that this version of unicode-width is based on.
-pub const UNICODE_VERSION: (u8, u8, u8) = (%s, %s, %s);
-
-""" % unicode_version)
- gencats = load_unicode_data("UnicodeData.txt")
-
- ### character width module
- width_table = []
- for zwcat in ["Me", "Mn", "Cf"]:
- width_table.extend([(lo_hi[0], lo_hi[1], 0, 0) for lo_hi in gencats[zwcat]])
- width_table.append((4448, 4607, 0, 0))
-
- # get widths, except those that are explicitly marked zero-width above
- ea_widths = load_east_asian_width(["W", "F", "A"], ["Me", "Mn", "Cf"])
- # these are doublewidth
- for dwcat in ["W", "F"]:
- width_table.extend([(lo_hi1[0], lo_hi1[1], 2, 2) for lo_hi1 in ea_widths[dwcat]])
- width_table.extend([(lo_hi2[0], lo_hi2[1], 1, 2) for lo_hi2 in ea_widths["A"]])
-
- width_table.sort(key=lambda w: w[0])
-
- # soft hyphen is not zero width in preformatted text; it's used to indicate
- # a hyphen inserted to facilitate a linebreak.
- width_table = remove_from_wtable(width_table, 173)
-
- # optimize the width table by collapsing adjacent entities when possible
- width_table = optimize_width_table(width_table)
- emit_charwidth_module(rf, width_table)
+ main(MODULE_FILENAME)
diff --git a/vendor/unicode-width/src/tables.rs b/vendor/unicode-width/src/tables.rs
index c0bb77d73..439c69c80 100644
--- a/vendor/unicode-width/src/tables.rs
+++ b/vendor/unicode-width/src/tables.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2022 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@@ -10,284 +10,531 @@
// NOTE: The following code was generated by "scripts/unicode.py", do not edit directly
-#![allow(missing_docs, non_upper_case_globals, non_snake_case)]
-
/// The version of [Unicode](http://www.unicode.org/)
/// that this version of unicode-width is based on.
-pub const UNICODE_VERSION: (u8, u8, u8) = (14, 0, 0);
+pub const UNICODE_VERSION: (u8, u8, u8) = (15, 0, 0);
pub mod charwidth {
- use core::option::Option::{self, Some, None};
- use core::result::Result::{Ok, Err};
+ use core::option::Option::{self, None, Some};
+ /// Returns the [UAX #11](https://www.unicode.org/reports/tr11/) based width of `c` by
+ /// consulting a multi-level lookup table.
+ /// If `is_cjk == true`, ambiguous width characters are treated as double width; otherwise,
+ /// they're treated as single width.
+ ///
+ /// # Maintenance
+ /// The tables themselves are autogenerated but this function is hardcoded. You should have
+ /// nothing to worry about if you re-run `unicode.py` (for example, when updating Unicode.)
+ /// However, if you change the *actual structure* of the lookup tables (perhaps by editing the
+ /// `TABLE_CFGS` global in `unicode.py`) you must ensure that this code reflects those changes.
#[inline]
- fn bsearch_range_value_table(c: char, is_cjk: bool, r: &'static [(char, char, u8, u8)]) -> u8 {
- use core::cmp::Ordering::{Equal, Less, Greater};
- match r.binary_search_by(|&(lo, hi, _, _)| {
- if lo <= c && c <= hi { Equal }
- else if hi < c { Less }
- else { Greater }
- }) {
- Ok(idx) => {
- let (_, _, r_ncjk, r_cjk) = r[idx];
- if is_cjk { r_cjk } else { r_ncjk }
+ fn lookup_width(c: char, is_cjk: bool) -> usize {
+ let cp = c as usize;
+
+ let t1_offset = TABLES_0[cp >> 13 & 0xFF];
+
+ // Each sub-table in TABLES_1 is 7 bits, and each stored entry is a byte,
+ // so each sub-table is 128 bytes in size.
+ // (Sub-tables are selected using the computed offset from the previous table.)
+ let t2_offset = TABLES_1[128 * usize::from(t1_offset) + (cp >> 6 & 0x7F)];
+
+ // Each sub-table in TABLES_2 is 6 bits, but each stored entry is 2 bits.
+ // This is accomplished by packing four stored entries into one byte.
+ // So each sub-table is 2**(6-2) == 16 bytes in size.
+ // Since this is the last table, each entry represents an encoded width.
+ let packed_widths = TABLES_2[16 * usize::from(t2_offset) + (cp >> 2 & 0xF)];
+
+ // Extract the packed width
+ let width = packed_widths >> (2 * (cp & 0b11)) & 0b11;
+
+ // A width of 3 signifies that the codepoint is ambiguous width.
+ if width == 3 {
+ if is_cjk {
+ 2
+ } else {
+ 1
}
- Err(_) => 1
+ } else {
+ width.into()
}
}
+ /// Returns the [UAX #11](https://www.unicode.org/reports/tr11/) based width of `c`, or
+ /// `None` if `c` is a control character other than `'\x00'`.
+ /// If `is_cjk == true`, ambiguous width characters are treated as double width; otherwise,
+ /// they're treated as single width.
#[inline]
pub fn width(c: char, is_cjk: bool) -> Option<usize> {
- match c as usize {
- _c @ 0 => Some(0), // null is zero width
- cu if cu < 0x20 => None, // control sequences have no width
- cu if cu < 0x7F => Some(1), // ASCII
- cu if cu < 0xA0 => None, // more control sequences
- _ => Some(bsearch_range_value_table(c, is_cjk, charwidth_table) as usize)
+ if c < '\u{7F}' {
+ if c >= '\u{20}' {
+ // U+0020 to U+007F (exclusive) are single-width ASCII codepoints
+ Some(1)
+ } else if c == '\0' {
+ // U+0000 *is* a control code, but it's special-cased
+ Some(0)
+ } else {
+ // U+0001 to U+0020 (exclusive) are control codes
+ None
+ }
+ } else if c >= '\u{A0}' {
+ // No characters >= U+00A0 are control codes, so we can consult the lookup tables
+ Some(lookup_width(c, is_cjk))
+ } else {
+ // U+007F to U+00A0 (exclusive) are control codes
+ None
}
}
- // character width table. Based on Markus Kuhn's free wcwidth() implementation,
- // http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
- const charwidth_table: &'static [(char, char, u8, u8)] = &[
- ('\u{a1}', '\u{a1}', 1, 2), ('\u{a4}', '\u{a4}', 1, 2), ('\u{a7}', '\u{a8}', 1, 2),
- ('\u{aa}', '\u{aa}', 1, 2), ('\u{ae}', '\u{ae}', 1, 2), ('\u{b0}', '\u{b4}', 1, 2),
- ('\u{b6}', '\u{ba}', 1, 2), ('\u{bc}', '\u{bf}', 1, 2), ('\u{c6}', '\u{c6}', 1, 2),
- ('\u{d0}', '\u{d0}', 1, 2), ('\u{d7}', '\u{d8}', 1, 2), ('\u{de}', '\u{e1}', 1, 2),
- ('\u{e6}', '\u{e6}', 1, 2), ('\u{e8}', '\u{ea}', 1, 2), ('\u{ec}', '\u{ed}', 1, 2),
- ('\u{f0}', '\u{f0}', 1, 2), ('\u{f2}', '\u{f3}', 1, 2), ('\u{f7}', '\u{fa}', 1, 2),
- ('\u{fc}', '\u{fc}', 1, 2), ('\u{fe}', '\u{fe}', 1, 2), ('\u{101}', '\u{101}', 1, 2),
- ('\u{111}', '\u{111}', 1, 2), ('\u{113}', '\u{113}', 1, 2), ('\u{11b}', '\u{11b}', 1, 2),
- ('\u{126}', '\u{127}', 1, 2), ('\u{12b}', '\u{12b}', 1, 2), ('\u{131}', '\u{133}', 1, 2),
- ('\u{138}', '\u{138}', 1, 2), ('\u{13f}', '\u{142}', 1, 2), ('\u{144}', '\u{144}', 1, 2),
- ('\u{148}', '\u{14b}', 1, 2), ('\u{14d}', '\u{14d}', 1, 2), ('\u{152}', '\u{153}', 1, 2),
- ('\u{166}', '\u{167}', 1, 2), ('\u{16b}', '\u{16b}', 1, 2), ('\u{1ce}', '\u{1ce}', 1, 2),
- ('\u{1d0}', '\u{1d0}', 1, 2), ('\u{1d2}', '\u{1d2}', 1, 2), ('\u{1d4}', '\u{1d4}', 1, 2),
- ('\u{1d6}', '\u{1d6}', 1, 2), ('\u{1d8}', '\u{1d8}', 1, 2), ('\u{1da}', '\u{1da}', 1, 2),
- ('\u{1dc}', '\u{1dc}', 1, 2), ('\u{251}', '\u{251}', 1, 2), ('\u{261}', '\u{261}', 1, 2),
- ('\u{2c4}', '\u{2c4}', 1, 2), ('\u{2c7}', '\u{2c7}', 1, 2), ('\u{2c9}', '\u{2cb}', 1, 2),
- ('\u{2cd}', '\u{2cd}', 1, 2), ('\u{2d0}', '\u{2d0}', 1, 2), ('\u{2d8}', '\u{2db}', 1, 2),
- ('\u{2dd}', '\u{2dd}', 1, 2), ('\u{2df}', '\u{2df}', 1, 2), ('\u{300}', '\u{36f}', 0, 0),
- ('\u{391}', '\u{3a1}', 1, 2), ('\u{3a3}', '\u{3a9}', 1, 2), ('\u{3b1}', '\u{3c1}', 1, 2),
- ('\u{3c3}', '\u{3c9}', 1, 2), ('\u{401}', '\u{401}', 1, 2), ('\u{410}', '\u{44f}', 1, 2),
- ('\u{451}', '\u{451}', 1, 2), ('\u{483}', '\u{489}', 0, 0), ('\u{591}', '\u{5bd}', 0, 0),
- ('\u{5bf}', '\u{5bf}', 0, 0), ('\u{5c1}', '\u{5c2}', 0, 0), ('\u{5c4}', '\u{5c5}', 0, 0),
- ('\u{5c7}', '\u{5c7}', 0, 0), ('\u{600}', '\u{605}', 0, 0), ('\u{610}', '\u{61a}', 0, 0),
- ('\u{61c}', '\u{61c}', 0, 0), ('\u{64b}', '\u{65f}', 0, 0), ('\u{670}', '\u{670}', 0, 0),
- ('\u{6d6}', '\u{6dd}', 0, 0), ('\u{6df}', '\u{6e4}', 0, 0), ('\u{6e7}', '\u{6e8}', 0, 0),
- ('\u{6ea}', '\u{6ed}', 0, 0), ('\u{70f}', '\u{70f}', 0, 0), ('\u{711}', '\u{711}', 0, 0),
- ('\u{730}', '\u{74a}', 0, 0), ('\u{7a6}', '\u{7b0}', 0, 0), ('\u{7eb}', '\u{7f3}', 0, 0),
- ('\u{7fd}', '\u{7fd}', 0, 0), ('\u{816}', '\u{819}', 0, 0), ('\u{81b}', '\u{823}', 0, 0),
- ('\u{825}', '\u{827}', 0, 0), ('\u{829}', '\u{82d}', 0, 0), ('\u{859}', '\u{85b}', 0, 0),
- ('\u{890}', '\u{891}', 0, 0), ('\u{898}', '\u{89f}', 0, 0), ('\u{8ca}', '\u{902}', 0, 0),
- ('\u{93a}', '\u{93a}', 0, 0), ('\u{93c}', '\u{93c}', 0, 0), ('\u{941}', '\u{948}', 0, 0),
- ('\u{94d}', '\u{94d}', 0, 0), ('\u{951}', '\u{957}', 0, 0), ('\u{962}', '\u{963}', 0, 0),
- ('\u{981}', '\u{981}', 0, 0), ('\u{9bc}', '\u{9bc}', 0, 0), ('\u{9c1}', '\u{9c4}', 0, 0),
- ('\u{9cd}', '\u{9cd}', 0, 0), ('\u{9e2}', '\u{9e3}', 0, 0), ('\u{9fe}', '\u{9fe}', 0, 0),
- ('\u{a01}', '\u{a02}', 0, 0), ('\u{a3c}', '\u{a3c}', 0, 0), ('\u{a41}', '\u{a42}', 0, 0),
- ('\u{a47}', '\u{a48}', 0, 0), ('\u{a4b}', '\u{a4d}', 0, 0), ('\u{a51}', '\u{a51}', 0, 0),
- ('\u{a70}', '\u{a71}', 0, 0), ('\u{a75}', '\u{a75}', 0, 0), ('\u{a81}', '\u{a82}', 0, 0),
- ('\u{abc}', '\u{abc}', 0, 0), ('\u{ac1}', '\u{ac5}', 0, 0), ('\u{ac7}', '\u{ac8}', 0, 0),
- ('\u{acd}', '\u{acd}', 0, 0), ('\u{ae2}', '\u{ae3}', 0, 0), ('\u{afa}', '\u{aff}', 0, 0),
- ('\u{b01}', '\u{b01}', 0, 0), ('\u{b3c}', '\u{b3c}', 0, 0), ('\u{b3f}', '\u{b3f}', 0, 0),
- ('\u{b41}', '\u{b44}', 0, 0), ('\u{b4d}', '\u{b4d}', 0, 0), ('\u{b55}', '\u{b56}', 0, 0),
- ('\u{b62}', '\u{b63}', 0, 0), ('\u{b82}', '\u{b82}', 0, 0), ('\u{bc0}', '\u{bc0}', 0, 0),
- ('\u{bcd}', '\u{bcd}', 0, 0), ('\u{c00}', '\u{c00}', 0, 0), ('\u{c04}', '\u{c04}', 0, 0),
- ('\u{c3c}', '\u{c3c}', 0, 0), ('\u{c3e}', '\u{c40}', 0, 0), ('\u{c46}', '\u{c48}', 0, 0),
- ('\u{c4a}', '\u{c4d}', 0, 0), ('\u{c55}', '\u{c56}', 0, 0), ('\u{c62}', '\u{c63}', 0, 0),
- ('\u{c81}', '\u{c81}', 0, 0), ('\u{cbc}', '\u{cbc}', 0, 0), ('\u{cbf}', '\u{cbf}', 0, 0),
- ('\u{cc6}', '\u{cc6}', 0, 0), ('\u{ccc}', '\u{ccd}', 0, 0), ('\u{ce2}', '\u{ce3}', 0, 0),
- ('\u{d00}', '\u{d01}', 0, 0), ('\u{d3b}', '\u{d3c}', 0, 0), ('\u{d41}', '\u{d44}', 0, 0),
- ('\u{d4d}', '\u{d4d}', 0, 0), ('\u{d62}', '\u{d63}', 0, 0), ('\u{d81}', '\u{d81}', 0, 0),
- ('\u{dca}', '\u{dca}', 0, 0), ('\u{dd2}', '\u{dd4}', 0, 0), ('\u{dd6}', '\u{dd6}', 0, 0),
- ('\u{e31}', '\u{e31}', 0, 0), ('\u{e34}', '\u{e3a}', 0, 0), ('\u{e47}', '\u{e4e}', 0, 0),
- ('\u{eb1}', '\u{eb1}', 0, 0), ('\u{eb4}', '\u{ebc}', 0, 0), ('\u{ec8}', '\u{ecd}', 0, 0),
- ('\u{f18}', '\u{f19}', 0, 0), ('\u{f35}', '\u{f35}', 0, 0), ('\u{f37}', '\u{f37}', 0, 0),
- ('\u{f39}', '\u{f39}', 0, 0), ('\u{f71}', '\u{f7e}', 0, 0), ('\u{f80}', '\u{f84}', 0, 0),
- ('\u{f86}', '\u{f87}', 0, 0), ('\u{f8d}', '\u{f97}', 0, 0), ('\u{f99}', '\u{fbc}', 0, 0),
- ('\u{fc6}', '\u{fc6}', 0, 0), ('\u{102d}', '\u{1030}', 0, 0), ('\u{1032}', '\u{1037}', 0,
- 0), ('\u{1039}', '\u{103a}', 0, 0), ('\u{103d}', '\u{103e}', 0, 0), ('\u{1058}', '\u{1059}',
- 0, 0), ('\u{105e}', '\u{1060}', 0, 0), ('\u{1071}', '\u{1074}', 0, 0), ('\u{1082}',
- '\u{1082}', 0, 0), ('\u{1085}', '\u{1086}', 0, 0), ('\u{108d}', '\u{108d}', 0, 0),
- ('\u{109d}', '\u{109d}', 0, 0), ('\u{1100}', '\u{115f}', 2, 2), ('\u{1160}', '\u{11ff}', 0,
- 0), ('\u{135d}', '\u{135f}', 0, 0), ('\u{1712}', '\u{1714}', 0, 0), ('\u{1732}', '\u{1733}',
- 0, 0), ('\u{1752}', '\u{1753}', 0, 0), ('\u{1772}', '\u{1773}', 0, 0), ('\u{17b4}',
- '\u{17b5}', 0, 0), ('\u{17b7}', '\u{17bd}', 0, 0), ('\u{17c6}', '\u{17c6}', 0, 0),
- ('\u{17c9}', '\u{17d3}', 0, 0), ('\u{17dd}', '\u{17dd}', 0, 0), ('\u{180b}', '\u{180f}', 0,
- 0), ('\u{1885}', '\u{1886}', 0, 0), ('\u{18a9}', '\u{18a9}', 0, 0), ('\u{1920}', '\u{1922}',
- 0, 0), ('\u{1927}', '\u{1928}', 0, 0), ('\u{1932}', '\u{1932}', 0, 0), ('\u{1939}',
- '\u{193b}', 0, 0), ('\u{1a17}', '\u{1a18}', 0, 0), ('\u{1a1b}', '\u{1a1b}', 0, 0),
- ('\u{1a56}', '\u{1a56}', 0, 0), ('\u{1a58}', '\u{1a5e}', 0, 0), ('\u{1a60}', '\u{1a60}', 0,
- 0), ('\u{1a62}', '\u{1a62}', 0, 0), ('\u{1a65}', '\u{1a6c}', 0, 0), ('\u{1a73}', '\u{1a7c}',
- 0, 0), ('\u{1a7f}', '\u{1a7f}', 0, 0), ('\u{1ab0}', '\u{1ace}', 0, 0), ('\u{1b00}',
- '\u{1b03}', 0, 0), ('\u{1b34}', '\u{1b34}', 0, 0), ('\u{1b36}', '\u{1b3a}', 0, 0),
- ('\u{1b3c}', '\u{1b3c}', 0, 0), ('\u{1b42}', '\u{1b42}', 0, 0), ('\u{1b6b}', '\u{1b73}', 0,
- 0), ('\u{1b80}', '\u{1b81}', 0, 0), ('\u{1ba2}', '\u{1ba5}', 0, 0), ('\u{1ba8}', '\u{1ba9}',
- 0, 0), ('\u{1bab}', '\u{1bad}', 0, 0), ('\u{1be6}', '\u{1be6}', 0, 0), ('\u{1be8}',
- '\u{1be9}', 0, 0), ('\u{1bed}', '\u{1bed}', 0, 0), ('\u{1bef}', '\u{1bf1}', 0, 0),
- ('\u{1c2c}', '\u{1c33}', 0, 0), ('\u{1c36}', '\u{1c37}', 0, 0), ('\u{1cd0}', '\u{1cd2}', 0,
- 0), ('\u{1cd4}', '\u{1ce0}', 0, 0), ('\u{1ce2}', '\u{1ce8}', 0, 0), ('\u{1ced}', '\u{1ced}',
- 0, 0), ('\u{1cf4}', '\u{1cf4}', 0, 0), ('\u{1cf8}', '\u{1cf9}', 0, 0), ('\u{1dc0}',
- '\u{1dff}', 0, 0), ('\u{200b}', '\u{200f}', 0, 0), ('\u{2010}', '\u{2010}', 1, 2),
- ('\u{2013}', '\u{2016}', 1, 2), ('\u{2018}', '\u{2019}', 1, 2), ('\u{201c}', '\u{201d}', 1,
- 2), ('\u{2020}', '\u{2022}', 1, 2), ('\u{2024}', '\u{2027}', 1, 2), ('\u{202a}', '\u{202e}',
- 0, 0), ('\u{2030}', '\u{2030}', 1, 2), ('\u{2032}', '\u{2033}', 1, 2), ('\u{2035}',
- '\u{2035}', 1, 2), ('\u{203b}', '\u{203b}', 1, 2), ('\u{203e}', '\u{203e}', 1, 2),
- ('\u{2060}', '\u{2064}', 0, 0), ('\u{2066}', '\u{206f}', 0, 0), ('\u{2074}', '\u{2074}', 1,
- 2), ('\u{207f}', '\u{207f}', 1, 2), ('\u{2081}', '\u{2084}', 1, 2), ('\u{20ac}', '\u{20ac}',
- 1, 2), ('\u{20d0}', '\u{20f0}', 0, 0), ('\u{2103}', '\u{2103}', 1, 2), ('\u{2105}',
- '\u{2105}', 1, 2), ('\u{2109}', '\u{2109}', 1, 2), ('\u{2113}', '\u{2113}', 1, 2),
- ('\u{2116}', '\u{2116}', 1, 2), ('\u{2121}', '\u{2122}', 1, 2), ('\u{2126}', '\u{2126}', 1,
- 2), ('\u{212b}', '\u{212b}', 1, 2), ('\u{2153}', '\u{2154}', 1, 2), ('\u{215b}', '\u{215e}',
- 1, 2), ('\u{2160}', '\u{216b}', 1, 2), ('\u{2170}', '\u{2179}', 1, 2), ('\u{2189}',
- '\u{2189}', 1, 2), ('\u{2190}', '\u{2199}', 1, 2), ('\u{21b8}', '\u{21b9}', 1, 2),
- ('\u{21d2}', '\u{21d2}', 1, 2), ('\u{21d4}', '\u{21d4}', 1, 2), ('\u{21e7}', '\u{21e7}', 1,
- 2), ('\u{2200}', '\u{2200}', 1, 2), ('\u{2202}', '\u{2203}', 1, 2), ('\u{2207}', '\u{2208}',
- 1, 2), ('\u{220b}', '\u{220b}', 1, 2), ('\u{220f}', '\u{220f}', 1, 2), ('\u{2211}',
- '\u{2211}', 1, 2), ('\u{2215}', '\u{2215}', 1, 2), ('\u{221a}', '\u{221a}', 1, 2),
- ('\u{221d}', '\u{2220}', 1, 2), ('\u{2223}', '\u{2223}', 1, 2), ('\u{2225}', '\u{2225}', 1,
- 2), ('\u{2227}', '\u{222c}', 1, 2), ('\u{222e}', '\u{222e}', 1, 2), ('\u{2234}', '\u{2237}',
- 1, 2), ('\u{223c}', '\u{223d}', 1, 2), ('\u{2248}', '\u{2248}', 1, 2), ('\u{224c}',
- '\u{224c}', 1, 2), ('\u{2252}', '\u{2252}', 1, 2), ('\u{2260}', '\u{2261}', 1, 2),
- ('\u{2264}', '\u{2267}', 1, 2), ('\u{226a}', '\u{226b}', 1, 2), ('\u{226e}', '\u{226f}', 1,
- 2), ('\u{2282}', '\u{2283}', 1, 2), ('\u{2286}', '\u{2287}', 1, 2), ('\u{2295}', '\u{2295}',
- 1, 2), ('\u{2299}', '\u{2299}', 1, 2), ('\u{22a5}', '\u{22a5}', 1, 2), ('\u{22bf}',
- '\u{22bf}', 1, 2), ('\u{2312}', '\u{2312}', 1, 2), ('\u{231a}', '\u{231b}', 2, 2),
- ('\u{2329}', '\u{232a}', 2, 2), ('\u{23e9}', '\u{23ec}', 2, 2), ('\u{23f0}', '\u{23f0}', 2,
- 2), ('\u{23f3}', '\u{23f3}', 2, 2), ('\u{2460}', '\u{24e9}', 1, 2), ('\u{24eb}', '\u{254b}',
- 1, 2), ('\u{2550}', '\u{2573}', 1, 2), ('\u{2580}', '\u{258f}', 1, 2), ('\u{2592}',
- '\u{2595}', 1, 2), ('\u{25a0}', '\u{25a1}', 1, 2), ('\u{25a3}', '\u{25a9}', 1, 2),
- ('\u{25b2}', '\u{25b3}', 1, 2), ('\u{25b6}', '\u{25b7}', 1, 2), ('\u{25bc}', '\u{25bd}', 1,
- 2), ('\u{25c0}', '\u{25c1}', 1, 2), ('\u{25c6}', '\u{25c8}', 1, 2), ('\u{25cb}', '\u{25cb}',
- 1, 2), ('\u{25ce}', '\u{25d1}', 1, 2), ('\u{25e2}', '\u{25e5}', 1, 2), ('\u{25ef}',
- '\u{25ef}', 1, 2), ('\u{25fd}', '\u{25fe}', 2, 2), ('\u{2605}', '\u{2606}', 1, 2),
- ('\u{2609}', '\u{2609}', 1, 2), ('\u{260e}', '\u{260f}', 1, 2), ('\u{2614}', '\u{2615}', 2,
- 2), ('\u{261c}', '\u{261c}', 1, 2), ('\u{261e}', '\u{261e}', 1, 2), ('\u{2640}', '\u{2640}',
- 1, 2), ('\u{2642}', '\u{2642}', 1, 2), ('\u{2648}', '\u{2653}', 2, 2), ('\u{2660}',
- '\u{2661}', 1, 2), ('\u{2663}', '\u{2665}', 1, 2), ('\u{2667}', '\u{266a}', 1, 2),
- ('\u{266c}', '\u{266d}', 1, 2), ('\u{266f}', '\u{266f}', 1, 2), ('\u{267f}', '\u{267f}', 2,
- 2), ('\u{2693}', '\u{2693}', 2, 2), ('\u{269e}', '\u{269f}', 1, 2), ('\u{26a1}', '\u{26a1}',
- 2, 2), ('\u{26aa}', '\u{26ab}', 2, 2), ('\u{26bd}', '\u{26be}', 2, 2), ('\u{26bf}',
- '\u{26bf}', 1, 2), ('\u{26c4}', '\u{26c5}', 2, 2), ('\u{26c6}', '\u{26cd}', 1, 2),
- ('\u{26ce}', '\u{26ce}', 2, 2), ('\u{26cf}', '\u{26d3}', 1, 2), ('\u{26d4}', '\u{26d4}', 2,
- 2), ('\u{26d5}', '\u{26e1}', 1, 2), ('\u{26e3}', '\u{26e3}', 1, 2), ('\u{26e8}', '\u{26e9}',
- 1, 2), ('\u{26ea}', '\u{26ea}', 2, 2), ('\u{26eb}', '\u{26f1}', 1, 2), ('\u{26f2}',
- '\u{26f3}', 2, 2), ('\u{26f4}', '\u{26f4}', 1, 2), ('\u{26f5}', '\u{26f5}', 2, 2),
- ('\u{26f6}', '\u{26f9}', 1, 2), ('\u{26fa}', '\u{26fa}', 2, 2), ('\u{26fb}', '\u{26fc}', 1,
- 2), ('\u{26fd}', '\u{26fd}', 2, 2), ('\u{26fe}', '\u{26ff}', 1, 2), ('\u{2705}', '\u{2705}',
- 2, 2), ('\u{270a}', '\u{270b}', 2, 2), ('\u{2728}', '\u{2728}', 2, 2), ('\u{273d}',
- '\u{273d}', 1, 2), ('\u{274c}', '\u{274c}', 2, 2), ('\u{274e}', '\u{274e}', 2, 2),
- ('\u{2753}', '\u{2755}', 2, 2), ('\u{2757}', '\u{2757}', 2, 2), ('\u{2776}', '\u{277f}', 1,
- 2), ('\u{2795}', '\u{2797}', 2, 2), ('\u{27b0}', '\u{27b0}', 2, 2), ('\u{27bf}', '\u{27bf}',
- 2, 2), ('\u{2b1b}', '\u{2b1c}', 2, 2), ('\u{2b50}', '\u{2b50}', 2, 2), ('\u{2b55}',
- '\u{2b55}', 2, 2), ('\u{2b56}', '\u{2b59}', 1, 2), ('\u{2cef}', '\u{2cf1}', 0, 0),
- ('\u{2d7f}', '\u{2d7f}', 0, 0), ('\u{2de0}', '\u{2dff}', 0, 0), ('\u{2e80}', '\u{2e99}', 2,
- 2), ('\u{2e9b}', '\u{2ef3}', 2, 2), ('\u{2f00}', '\u{2fd5}', 2, 2), ('\u{2ff0}', '\u{2ffb}',
- 2, 2), ('\u{3000}', '\u{3029}', 2, 2), ('\u{302a}', '\u{302d}', 0, 0), ('\u{302e}',
- '\u{303e}', 2, 2), ('\u{3041}', '\u{3096}', 2, 2), ('\u{3099}', '\u{309a}', 0, 0),
- ('\u{309b}', '\u{30ff}', 2, 2), ('\u{3105}', '\u{312f}', 2, 2), ('\u{3131}', '\u{318e}', 2,
- 2), ('\u{3190}', '\u{31e3}', 2, 2), ('\u{31f0}', '\u{321e}', 2, 2), ('\u{3220}', '\u{3247}',
- 2, 2), ('\u{3248}', '\u{324f}', 1, 2), ('\u{3250}', '\u{4dbf}', 2, 2), ('\u{4e00}',
- '\u{a48c}', 2, 2), ('\u{a490}', '\u{a4c6}', 2, 2), ('\u{a66f}', '\u{a672}', 0, 0),
- ('\u{a674}', '\u{a67d}', 0, 0), ('\u{a69e}', '\u{a69f}', 0, 0), ('\u{a6f0}', '\u{a6f1}', 0,
- 0), ('\u{a802}', '\u{a802}', 0, 0), ('\u{a806}', '\u{a806}', 0, 0), ('\u{a80b}', '\u{a80b}',
- 0, 0), ('\u{a825}', '\u{a826}', 0, 0), ('\u{a82c}', '\u{a82c}', 0, 0), ('\u{a8c4}',
- '\u{a8c5}', 0, 0), ('\u{a8e0}', '\u{a8f1}', 0, 0), ('\u{a8ff}', '\u{a8ff}', 0, 0),
- ('\u{a926}', '\u{a92d}', 0, 0), ('\u{a947}', '\u{a951}', 0, 0), ('\u{a960}', '\u{a97c}', 2,
- 2), ('\u{a980}', '\u{a982}', 0, 0), ('\u{a9b3}', '\u{a9b3}', 0, 0), ('\u{a9b6}', '\u{a9b9}',
- 0, 0), ('\u{a9bc}', '\u{a9bd}', 0, 0), ('\u{a9e5}', '\u{a9e5}', 0, 0), ('\u{aa29}',
- '\u{aa2e}', 0, 0), ('\u{aa31}', '\u{aa32}', 0, 0), ('\u{aa35}', '\u{aa36}', 0, 0),
- ('\u{aa43}', '\u{aa43}', 0, 0), ('\u{aa4c}', '\u{aa4c}', 0, 0), ('\u{aa7c}', '\u{aa7c}', 0,
- 0), ('\u{aab0}', '\u{aab0}', 0, 0), ('\u{aab2}', '\u{aab4}', 0, 0), ('\u{aab7}', '\u{aab8}',
- 0, 0), ('\u{aabe}', '\u{aabf}', 0, 0), ('\u{aac1}', '\u{aac1}', 0, 0), ('\u{aaec}',
- '\u{aaed}', 0, 0), ('\u{aaf6}', '\u{aaf6}', 0, 0), ('\u{abe5}', '\u{abe5}', 0, 0),
- ('\u{abe8}', '\u{abe8}', 0, 0), ('\u{abed}', '\u{abed}', 0, 0), ('\u{ac00}', '\u{d7a3}', 2,
- 2), ('\u{e000}', '\u{f8ff}', 1, 2), ('\u{f900}', '\u{faff}', 2, 2), ('\u{fb1e}', '\u{fb1e}',
- 0, 0), ('\u{fe00}', '\u{fe0f}', 0, 0), ('\u{fe10}', '\u{fe19}', 2, 2), ('\u{fe20}',
- '\u{fe2f}', 0, 0), ('\u{fe30}', '\u{fe52}', 2, 2), ('\u{fe54}', '\u{fe66}', 2, 2),
- ('\u{fe68}', '\u{fe6b}', 2, 2), ('\u{feff}', '\u{feff}', 0, 0), ('\u{ff01}', '\u{ff60}', 2,
- 2), ('\u{ffe0}', '\u{ffe6}', 2, 2), ('\u{fff9}', '\u{fffb}', 0, 0), ('\u{fffd}', '\u{fffd}',
- 1, 2), ('\u{101fd}', '\u{101fd}', 0, 0), ('\u{102e0}', '\u{102e0}', 0, 0), ('\u{10376}',
- '\u{1037a}', 0, 0), ('\u{10a01}', '\u{10a03}', 0, 0), ('\u{10a05}', '\u{10a06}', 0, 0),
- ('\u{10a0c}', '\u{10a0f}', 0, 0), ('\u{10a38}', '\u{10a3a}', 0, 0), ('\u{10a3f}',
- '\u{10a3f}', 0, 0), ('\u{10ae5}', '\u{10ae6}', 0, 0), ('\u{10d24}', '\u{10d27}', 0, 0),
- ('\u{10eab}', '\u{10eac}', 0, 0), ('\u{10f46}', '\u{10f50}', 0, 0), ('\u{10f82}',
- '\u{10f85}', 0, 0), ('\u{11001}', '\u{11001}', 0, 0), ('\u{11038}', '\u{11046}', 0, 0),
- ('\u{11070}', '\u{11070}', 0, 0), ('\u{11073}', '\u{11074}', 0, 0), ('\u{1107f}',
- '\u{11081}', 0, 0), ('\u{110b3}', '\u{110b6}', 0, 0), ('\u{110b9}', '\u{110ba}', 0, 0),
- ('\u{110bd}', '\u{110bd}', 0, 0), ('\u{110c2}', '\u{110c2}', 0, 0), ('\u{110cd}',
- '\u{110cd}', 0, 0), ('\u{11100}', '\u{11102}', 0, 0), ('\u{11127}', '\u{1112b}', 0, 0),
- ('\u{1112d}', '\u{11134}', 0, 0), ('\u{11173}', '\u{11173}', 0, 0), ('\u{11180}',
- '\u{11181}', 0, 0), ('\u{111b6}', '\u{111be}', 0, 0), ('\u{111c9}', '\u{111cc}', 0, 0),
- ('\u{111cf}', '\u{111cf}', 0, 0), ('\u{1122f}', '\u{11231}', 0, 0), ('\u{11234}',
- '\u{11234}', 0, 0), ('\u{11236}', '\u{11237}', 0, 0), ('\u{1123e}', '\u{1123e}', 0, 0),
- ('\u{112df}', '\u{112df}', 0, 0), ('\u{112e3}', '\u{112ea}', 0, 0), ('\u{11300}',
- '\u{11301}', 0, 0), ('\u{1133b}', '\u{1133c}', 0, 0), ('\u{11340}', '\u{11340}', 0, 0),
- ('\u{11366}', '\u{1136c}', 0, 0), ('\u{11370}', '\u{11374}', 0, 0), ('\u{11438}',
- '\u{1143f}', 0, 0), ('\u{11442}', '\u{11444}', 0, 0), ('\u{11446}', '\u{11446}', 0, 0),
- ('\u{1145e}', '\u{1145e}', 0, 0), ('\u{114b3}', '\u{114b8}', 0, 0), ('\u{114ba}',
- '\u{114ba}', 0, 0), ('\u{114bf}', '\u{114c0}', 0, 0), ('\u{114c2}', '\u{114c3}', 0, 0),
- ('\u{115b2}', '\u{115b5}', 0, 0), ('\u{115bc}', '\u{115bd}', 0, 0), ('\u{115bf}',
- '\u{115c0}', 0, 0), ('\u{115dc}', '\u{115dd}', 0, 0), ('\u{11633}', '\u{1163a}', 0, 0),
- ('\u{1163d}', '\u{1163d}', 0, 0), ('\u{1163f}', '\u{11640}', 0, 0), ('\u{116ab}',
- '\u{116ab}', 0, 0), ('\u{116ad}', '\u{116ad}', 0, 0), ('\u{116b0}', '\u{116b5}', 0, 0),
- ('\u{116b7}', '\u{116b7}', 0, 0), ('\u{1171d}', '\u{1171f}', 0, 0), ('\u{11722}',
- '\u{11725}', 0, 0), ('\u{11727}', '\u{1172b}', 0, 0), ('\u{1182f}', '\u{11837}', 0, 0),
- ('\u{11839}', '\u{1183a}', 0, 0), ('\u{1193b}', '\u{1193c}', 0, 0), ('\u{1193e}',
- '\u{1193e}', 0, 0), ('\u{11943}', '\u{11943}', 0, 0), ('\u{119d4}', '\u{119d7}', 0, 0),
- ('\u{119da}', '\u{119db}', 0, 0), ('\u{119e0}', '\u{119e0}', 0, 0), ('\u{11a01}',
- '\u{11a0a}', 0, 0), ('\u{11a33}', '\u{11a38}', 0, 0), ('\u{11a3b}', '\u{11a3e}', 0, 0),
- ('\u{11a47}', '\u{11a47}', 0, 0), ('\u{11a51}', '\u{11a56}', 0, 0), ('\u{11a59}',
- '\u{11a5b}', 0, 0), ('\u{11a8a}', '\u{11a96}', 0, 0), ('\u{11a98}', '\u{11a99}', 0, 0),
- ('\u{11c30}', '\u{11c36}', 0, 0), ('\u{11c38}', '\u{11c3d}', 0, 0), ('\u{11c3f}',
- '\u{11c3f}', 0, 0), ('\u{11c92}', '\u{11ca7}', 0, 0), ('\u{11caa}', '\u{11cb0}', 0, 0),
- ('\u{11cb2}', '\u{11cb3}', 0, 0), ('\u{11cb5}', '\u{11cb6}', 0, 0), ('\u{11d31}',
- '\u{11d36}', 0, 0), ('\u{11d3a}', '\u{11d3a}', 0, 0), ('\u{11d3c}', '\u{11d3d}', 0, 0),
- ('\u{11d3f}', '\u{11d45}', 0, 0), ('\u{11d47}', '\u{11d47}', 0, 0), ('\u{11d90}',
- '\u{11d91}', 0, 0), ('\u{11d95}', '\u{11d95}', 0, 0), ('\u{11d97}', '\u{11d97}', 0, 0),
- ('\u{11ef3}', '\u{11ef4}', 0, 0), ('\u{13430}', '\u{13438}', 0, 0), ('\u{16af0}',
- '\u{16af4}', 0, 0), ('\u{16b30}', '\u{16b36}', 0, 0), ('\u{16f4f}', '\u{16f4f}', 0, 0),
- ('\u{16f8f}', '\u{16f92}', 0, 0), ('\u{16fe0}', '\u{16fe3}', 2, 2), ('\u{16fe4}',
- '\u{16fe4}', 0, 0), ('\u{16ff0}', '\u{16ff1}', 2, 2), ('\u{17000}', '\u{187f7}', 2, 2),
- ('\u{18800}', '\u{18cd5}', 2, 2), ('\u{18d00}', '\u{18d08}', 2, 2), ('\u{1aff0}',
- '\u{1aff3}', 2, 2), ('\u{1aff5}', '\u{1affb}', 2, 2), ('\u{1affd}', '\u{1affe}', 2, 2),
- ('\u{1b000}', '\u{1b122}', 2, 2), ('\u{1b150}', '\u{1b152}', 2, 2), ('\u{1b164}',
- '\u{1b167}', 2, 2), ('\u{1b170}', '\u{1b2fb}', 2, 2), ('\u{1bc9d}', '\u{1bc9e}', 0, 0),
- ('\u{1bca0}', '\u{1bca3}', 0, 0), ('\u{1cf00}', '\u{1cf2d}', 0, 0), ('\u{1cf30}',
- '\u{1cf46}', 0, 0), ('\u{1d167}', '\u{1d169}', 0, 0), ('\u{1d173}', '\u{1d182}', 0, 0),
- ('\u{1d185}', '\u{1d18b}', 0, 0), ('\u{1d1aa}', '\u{1d1ad}', 0, 0), ('\u{1d242}',
- '\u{1d244}', 0, 0), ('\u{1da00}', '\u{1da36}', 0, 0), ('\u{1da3b}', '\u{1da6c}', 0, 0),
- ('\u{1da75}', '\u{1da75}', 0, 0), ('\u{1da84}', '\u{1da84}', 0, 0), ('\u{1da9b}',
- '\u{1da9f}', 0, 0), ('\u{1daa1}', '\u{1daaf}', 0, 0), ('\u{1e000}', '\u{1e006}', 0, 0),
- ('\u{1e008}', '\u{1e018}', 0, 0), ('\u{1e01b}', '\u{1e021}', 0, 0), ('\u{1e023}',
- '\u{1e024}', 0, 0), ('\u{1e026}', '\u{1e02a}', 0, 0), ('\u{1e130}', '\u{1e136}', 0, 0),
- ('\u{1e2ae}', '\u{1e2ae}', 0, 0), ('\u{1e2ec}', '\u{1e2ef}', 0, 0), ('\u{1e8d0}',
- '\u{1e8d6}', 0, 0), ('\u{1e944}', '\u{1e94a}', 0, 0), ('\u{1f004}', '\u{1f004}', 2, 2),
- ('\u{1f0cf}', '\u{1f0cf}', 2, 2), ('\u{1f100}', '\u{1f10a}', 1, 2), ('\u{1f110}',
- '\u{1f12d}', 1, 2), ('\u{1f130}', '\u{1f169}', 1, 2), ('\u{1f170}', '\u{1f18d}', 1, 2),
- ('\u{1f18e}', '\u{1f18e}', 2, 2), ('\u{1f18f}', '\u{1f190}', 1, 2), ('\u{1f191}',
- '\u{1f19a}', 2, 2), ('\u{1f19b}', '\u{1f1ac}', 1, 2), ('\u{1f200}', '\u{1f202}', 2, 2),
- ('\u{1f210}', '\u{1f23b}', 2, 2), ('\u{1f240}', '\u{1f248}', 2, 2), ('\u{1f250}',
- '\u{1f251}', 2, 2), ('\u{1f260}', '\u{1f265}', 2, 2), ('\u{1f300}', '\u{1f320}', 2, 2),
- ('\u{1f32d}', '\u{1f335}', 2, 2), ('\u{1f337}', '\u{1f37c}', 2, 2), ('\u{1f37e}',
- '\u{1f393}', 2, 2), ('\u{1f3a0}', '\u{1f3ca}', 2, 2), ('\u{1f3cf}', '\u{1f3d3}', 2, 2),
- ('\u{1f3e0}', '\u{1f3f0}', 2, 2), ('\u{1f3f4}', '\u{1f3f4}', 2, 2), ('\u{1f3f8}',
- '\u{1f43e}', 2, 2), ('\u{1f440}', '\u{1f440}', 2, 2), ('\u{1f442}', '\u{1f4fc}', 2, 2),
- ('\u{1f4ff}', '\u{1f53d}', 2, 2), ('\u{1f54b}', '\u{1f54e}', 2, 2), ('\u{1f550}',
- '\u{1f567}', 2, 2), ('\u{1f57a}', '\u{1f57a}', 2, 2), ('\u{1f595}', '\u{1f596}', 2, 2),
- ('\u{1f5a4}', '\u{1f5a4}', 2, 2), ('\u{1f5fb}', '\u{1f64f}', 2, 2), ('\u{1f680}',
- '\u{1f6c5}', 2, 2), ('\u{1f6cc}', '\u{1f6cc}', 2, 2), ('\u{1f6d0}', '\u{1f6d2}', 2, 2),
- ('\u{1f6d5}', '\u{1f6d7}', 2, 2), ('\u{1f6dd}', '\u{1f6df}', 2, 2), ('\u{1f6eb}',
- '\u{1f6ec}', 2, 2), ('\u{1f6f4}', '\u{1f6fc}', 2, 2), ('\u{1f7e0}', '\u{1f7eb}', 2, 2),
- ('\u{1f7f0}', '\u{1f7f0}', 2, 2), ('\u{1f90c}', '\u{1f93a}', 2, 2), ('\u{1f93c}',
- '\u{1f945}', 2, 2), ('\u{1f947}', '\u{1f9ff}', 2, 2), ('\u{1fa70}', '\u{1fa74}', 2, 2),
- ('\u{1fa78}', '\u{1fa7c}', 2, 2), ('\u{1fa80}', '\u{1fa86}', 2, 2), ('\u{1fa90}',
- '\u{1faac}', 2, 2), ('\u{1fab0}', '\u{1faba}', 2, 2), ('\u{1fac0}', '\u{1fac5}', 2, 2),
- ('\u{1fad0}', '\u{1fad9}', 2, 2), ('\u{1fae0}', '\u{1fae7}', 2, 2), ('\u{1faf0}',
- '\u{1faf6}', 2, 2), ('\u{20000}', '\u{2fffd}', 2, 2), ('\u{30000}', '\u{3fffd}', 2, 2),
- ('\u{e0001}', '\u{e0001}', 0, 0), ('\u{e0020}', '\u{e007f}', 0, 0), ('\u{e0100}',
- '\u{e01ef}', 0, 0), ('\u{f0000}', '\u{ffffd}', 1, 2), ('\u{100000}', '\u{10fffd}', 1, 2)
+ /// Autogenerated. 1 sub-table(s). Consult [`lookup_width`] for layout info.
+ static TABLES_0: [u8; 256] = [
+ 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
+ 0x0E, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x0F, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x10, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x12, 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, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
];
-}
+ /// Autogenerated. 19 sub-table(s). Consult [`lookup_width`] for layout info.
+ static TABLES_1: [u8; 2432] = [
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x06, 0x08, 0x06, 0x09, 0x0A, 0x0B, 0x0C,
+ 0x0D, 0x0E, 0x0F, 0x10, 0x06, 0x06, 0x06, 0x11, 0x12, 0x13, 0x14, 0x06, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x22, 0x24, 0x25,
+ 0x26, 0x27, 0x28, 0x29, 0x2A, 0x25, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x06, 0x3B, 0x3C, 0x0A, 0x0A, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x3D, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x06, 0x43, 0x06, 0x44, 0x06, 0x06, 0x06, 0x45,
+ 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x06, 0x06, 0x4E, 0x06, 0x06, 0x06, 0x0A,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x06, 0x5A, 0x06, 0x06, 0x5B, 0x06, 0x5C, 0x5D, 0x5E, 0x5D, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x69, 0x6A, 0x06, 0x06, 0x06, 0x06, 0x06, 0x6B,
+ 0x06, 0x01, 0x06, 0x6C, 0x06, 0x06, 0x6D, 0x6E, 0x3B, 0x3B, 0x3B, 0x6F, 0x70, 0x71, 0x72,
+ 0x3B, 0x73, 0x3B, 0x74, 0x75, 0x76, 0x77, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x06, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x78, 0x79, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7A, 0x7B, 0x7C,
+ 0x06, 0x06, 0x06, 0x06, 0x7D, 0x06, 0x06, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85,
+ 0x86, 0x06, 0x06, 0x06, 0x87, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x88,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x89, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x8A, 0x8B, 0x06, 0x01, 0x71, 0x8C, 0x06, 0x8D, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x8E, 0x06, 0x06, 0x06, 0x8F, 0x06, 0x90, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x91, 0x06, 0x06, 0x92, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x93, 0x06, 0x06, 0x06, 0x06, 0x06, 0x94, 0x95, 0x06, 0x96, 0x97, 0x06,
+ 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0x2E, 0x06, 0xA1, 0x2C, 0xA2, 0x06,
+ 0x06, 0xA3, 0xA4, 0xA5, 0xA6, 0x06, 0x06, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0x06, 0xAC, 0x06,
+ 0x06, 0x06, 0xAD, 0x06, 0x06, 0x06, 0xAE, 0xAF, 0x06, 0xB0, 0xB1, 0xB2, 0xB3, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0xB4, 0x06, 0xB5, 0x06, 0xB6, 0xB7, 0xB8, 0x06, 0x06, 0x06, 0x06, 0xB9,
+ 0xBA, 0xBB, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x47, 0xBC, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0xBD, 0xBE, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xBF, 0xC0, 0xC1, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0xC2,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0xC3, 0xC4, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xC5, 0x3B, 0x3B, 0x3B, 0x3B, 0xC6,
+ 0xC7, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0xC8, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0xC9, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xCA,
+ 0xCB, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xCC, 0xCD, 0x06, 0x06, 0xCE, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xCF, 0xD0,
+ 0xD1, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xD2, 0x06, 0xBF, 0x06, 0xBE, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0xD3, 0xD4, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xD4, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xD5, 0x06, 0xD6,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xD7, 0x06, 0x06, 0xD8,
+ 0xD9, 0xDA, 0xDB, 0x06, 0xDC, 0xDD, 0x06, 0x06, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0x3B,
+ 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0x3B, 0xE9, 0x3B, 0xEA, 0x06, 0x06, 0x06, 0xEB, 0x06, 0x06,
+ 0x06, 0x06, 0xEC, 0xED, 0x3B, 0x3B, 0x06, 0xEE, 0xEF, 0xF0, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B,
+ 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0x3B, 0xE5, 0xF1, 0x0A, 0x06, 0x06, 0x0A, 0x0A, 0x0A,
+ 0x0B, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+ 0x06, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D, 0x5D,
+ 0x5D, 0xF2,
+ ];
+ /// Autogenerated. 243 sub-table(s). Consult [`lookup_width`] for layout info.
+ static TABLES_2: [u8; 3888] = [
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xD7, 0x77, 0x75, 0xFF,
+ 0xF7, 0x7F, 0xFF, 0x55, 0x75, 0x55, 0x55, 0x57, 0xD5, 0x57, 0xF5, 0x5F, 0x75, 0x7F, 0x5F,
+ 0xF7, 0xD5, 0x7F, 0x77, 0x5D, 0x55, 0x55, 0x55, 0xDD, 0x55, 0xD5, 0x55, 0x55, 0xF5, 0xD5,
+ 0x55, 0xFD, 0x55, 0x57, 0xD5, 0x7F, 0x57, 0xFF, 0x5D, 0xF5, 0x55, 0x55, 0x55, 0x55, 0xF5,
+ 0xD5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x75, 0x77, 0x77, 0x77, 0x57,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5D, 0x55, 0x55,
+ 0x55, 0x5D, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD7, 0xFD, 0x5D, 0x57, 0x55,
+ 0xFF, 0xDD, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 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, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xFD, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0x55, 0xFD, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF,
+ 0x5F, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5D,
+ 0x55, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x41, 0x10, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x00, 0x50, 0x55, 0x55, 0x00, 0x00, 0x40, 0x54, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55,
+ 0x55, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x10, 0x00,
+ 0x14, 0x04, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x51, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x05, 0x10, 0x00, 0x00, 0x01, 0x01, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x50, 0x55, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45,
+ 0x54, 0x01, 0x00, 0x54, 0x51, 0x01, 0x00, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x54, 0x01, 0x54, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x45, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x54, 0x41, 0x15, 0x14, 0x50, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x50, 0x51, 0x55, 0x55, 0x01, 0x10, 0x54, 0x51, 0x55, 0x55, 0x55, 0x55, 0x05,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x14, 0x01, 0x54, 0x55, 0x51, 0x55, 0x41, 0x55,
+ 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55, 0x51, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x54, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x04, 0x54, 0x05, 0x04,
+ 0x50, 0x55, 0x41, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45,
+ 0x55, 0x50, 0x55, 0x55, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x54,
+ 0x01, 0x54, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x45, 0x55, 0x05, 0x44, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x51, 0x00, 0x40, 0x55, 0x55, 0x15, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x51, 0x00, 0x00, 0x54, 0x55, 0x55, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x11, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x40, 0x00, 0x04, 0x55, 0x01, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x45, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x04, 0x00, 0x41, 0x41, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x50, 0x05, 0x54, 0x55, 0x55, 0x55, 0x01, 0x54, 0x55, 0x55, 0x45, 0x41,
+ 0x55, 0x51, 0x55, 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x10, 0x00, 0x50, 0x55, 0x45, 0x01, 0x00, 0x00, 0x55, 0x55, 0x51, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x40, 0x15, 0x54, 0x55, 0x45, 0x55, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15,
+ 0x14, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x45, 0x00, 0x40, 0x44, 0x01, 0x00, 0x54, 0x15, 0x00, 0x00, 0x14, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x04, 0x40, 0x54, 0x45,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x55, 0x55, 0x55,
+ 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x50, 0x10, 0x50, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45, 0x50, 0x11, 0x50, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00,
+ 0x05, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x54, 0x51,
+ 0x55, 0x54, 0x50, 0x55, 0x55, 0x55, 0x15, 0x00, 0xD7, 0x7F, 0x5F, 0x5F, 0x7F, 0xFF, 0x05,
+ 0x40, 0xF7, 0x5D, 0xD5, 0x75, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x04,
+ 0x00, 0x00, 0x55, 0x57, 0x55, 0xD5, 0xFD, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x57, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0xD5, 0x5D, 0x5D, 0x55, 0xD5, 0x75, 0x55,
+ 0x55, 0x7D, 0x75, 0xD5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5, 0x57,
+ 0xD5, 0x7F, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0x5F, 0x55, 0x55, 0x55, 0x5D, 0x55, 0xFF,
+ 0xFF, 0x5F, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x5F, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x75, 0x57, 0x55, 0x55, 0x55, 0xD5, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xF7, 0xD5, 0xD7,
+ 0xD5, 0x5D, 0x5D, 0x75, 0xFD, 0xD7, 0xDD, 0xFF, 0x77, 0x55, 0xFF, 0x55, 0x5F, 0x55, 0x55,
+ 0x57, 0x57, 0x75, 0x55, 0x55, 0x55, 0x5F, 0xFF, 0xF5, 0xF5, 0x55, 0x55, 0x55, 0x55, 0xF5,
+ 0xF5, 0x55, 0x55, 0x55, 0x5D, 0x5D, 0x55, 0x55, 0x5D, 0x55, 0x55, 0x55, 0x55, 0x55, 0xD5,
+ 0x55, 0x55, 0x55, 0x55, 0x75, 0x55, 0xA5, 0x55, 0x55, 0x55, 0x69, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xA9, 0x56, 0x96, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x5F, 0x55, 0x55, 0xDF,
+ 0xFF, 0x5F, 0x55, 0xF5, 0xF5, 0x55, 0x5F, 0x5F, 0xF5, 0xD7, 0xF5, 0x5F, 0x55, 0x55, 0x55,
+ 0xF5, 0x5F, 0x55, 0xD5, 0x55, 0x55, 0x55, 0x69, 0x55, 0x7D, 0x5D, 0xF5, 0x55, 0x5A, 0x55,
+ 0x77, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x77, 0x55, 0xAA, 0xAA, 0xAA, 0x55,
+ 0x55, 0x55, 0xDF, 0xDF, 0x7F, 0xDF, 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95,
+ 0x55, 0x55, 0xF5, 0x59, 0x55, 0xA5, 0x55, 0x55, 0x55, 0x55, 0xE9, 0x55, 0xFA, 0xFF, 0xEF,
+ 0xFF, 0xFE, 0xFF, 0xFF, 0xDF, 0x55, 0xEF, 0xFF, 0xAF, 0xFB, 0xEF, 0xFB, 0x55, 0x59, 0xA5,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0x55, 0x55, 0x55, 0x55, 0x5D, 0x55, 0x55,
+ 0x55, 0x66, 0x95, 0x9A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xF5, 0xFF, 0xFF, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0xA9, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0x55, 0x55, 0x95,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xF9, 0x5F, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x50,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x5A, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0x0A, 0xA0, 0xAA, 0xAA, 0xAA, 0x6A, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A,
+ 0x81, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0xA9, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA9, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xFF, 0xFF, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0x56, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0x6A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x40,
+ 0x00, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x50, 0x55, 0x55, 0x55, 0x45, 0x45, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x41,
+ 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x15, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x05, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x50, 0x55, 0x55,
+ 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x56, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x05, 0x50, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x40, 0x41, 0x41, 0x55, 0x55, 0x15, 0x55, 0x55,
+ 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x04, 0x14, 0x54, 0x05, 0x51,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x55, 0x45, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x51, 0x54, 0x51, 0x55, 0x55, 0x55,
+ 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0x5A, 0x55, 0x00, 0x00, 0x00, 0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0xAA,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x56, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA,
+ 0x6A, 0x55, 0x55, 0x55, 0x55, 0x01, 0x5D, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x40, 0x55, 0x01, 0x41, 0x55, 0x00, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x15, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01,
+ 0x55, 0x05, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x05, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x14, 0x54, 0x55, 0x15, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x40, 0x41, 0x51, 0x45, 0x55, 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x15, 0x00, 0x01, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x15, 0x55, 0x55, 0x55, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x40, 0x55, 0x55, 0x01, 0x14, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x50, 0x04, 0x55, 0x45, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x15, 0x15, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x54, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x05,
+ 0x44, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x44,
+ 0x15, 0x04, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05,
+ 0x50, 0x55, 0x10, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x00, 0x40, 0x11, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x15, 0x51, 0x00, 0x10, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01,
+ 0x05, 0x10, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x41, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x44, 0x15, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x00, 0x05, 0x55, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x40,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x14, 0x40, 0x55, 0x15,
+ 0x55, 0x55, 0x01, 0x40, 0x01, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x05, 0x00, 0x00, 0x40, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x40, 0x00,
+ 0x10, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x04, 0x41,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01,
+ 0x40, 0x45, 0x10, 0x00, 0x10, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x50, 0x11, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x15, 0x54, 0x55, 0x55, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x05, 0x40, 0x55, 0x44, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x54, 0x15, 0x00, 0x00, 0x00, 0x50, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x15, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0x54, 0x55, 0x55, 0x5A, 0x55, 0x55, 0x55, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x5A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA,
+ 0xA9, 0xAA, 0x69, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0x55, 0x55, 0x55,
+ 0x65, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x6A, 0x59, 0x55, 0x55, 0x55, 0xAA, 0x55,
+ 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x41, 0x00,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x15, 0x50, 0x55, 0x15, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x50, 0x55, 0x55, 0x55, 0x55, 0x05, 0x54, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x15, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x51, 0x55, 0x55, 0x55,
+ 0x54, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x10, 0x04, 0x40, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x45, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xFF, 0xFF, 0x7F, 0x55, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x5F, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xAB, 0xAA,
+ 0xEA, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x55, 0x55, 0x55, 0x55, 0x6A, 0x55, 0x55, 0x55, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0xAA, 0xAA, 0x56, 0x55,
+ 0x5A, 0x55, 0x55, 0x55, 0xAA, 0x5A, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0xA9, 0xAA, 0x9A, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA6, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0x6A, 0x95, 0xAA, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x56, 0x56, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0x6A, 0xA6, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0x96, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x5A, 0x55, 0x55, 0x95, 0x6A, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0x55, 0x55, 0x55, 0x55, 0x65, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x69, 0x55, 0x55, 0x55,
+ 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0x5A, 0x55, 0x56, 0x6A, 0xA9,
+ 0x55, 0xAA, 0x55, 0x55, 0x95, 0x56, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0x55, 0x56, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x6A, 0xAA, 0xAA, 0x9A, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0x56, 0xAA,
+ 0xAA, 0x56, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x9A,
+ 0xAA, 0x5A, 0x55, 0xA5, 0xAA, 0xAA, 0xAA, 0x55, 0xAA, 0xAA, 0x56, 0x55, 0xAA, 0xAA, 0x56,
+ 0x55, 0x51, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x5F,
+ ];
+}
diff --git a/vendor/unicode-width/src/tests.rs b/vendor/unicode-width/src/tests.rs
index 72808c64f..e49b1bfbe 100644
--- a/vendor/unicode-width/src/tests.rs
+++ b/vendor/unicode-width/src/tests.rs
@@ -13,7 +13,7 @@ use std::iter;
#[cfg(feature = "bench")]
use test::{self, Bencher};
#[cfg(feature = "bench")]
-use super::UnicodeWidthChar;
+use super::{UnicodeWidthChar, UnicodeWidthStr};
use std::prelude::v1::*;
@@ -93,7 +93,23 @@ fn simple_width_match(c: char) -> Option<usize> {
_ => UnicodeWidthChar::width(c)
}
}
-
+#[cfg(all(feature = "bench", not(feature = "no_std")))]
+#[bench]
+fn enwik8(b: &mut Bencher) {
+ // To benchmark, download & unzip `enwik8` from https://data.deepai.org/enwik8.zip
+ let data_path = "bench_data/enwik8";
+ let string = std::fs::read_to_string(data_path).unwrap_or_default();
+ b.iter(|| test::black_box(UnicodeWidthStr::width(string.as_str())));
+}
+#[cfg(all(feature = "bench", not(feature = "no_std")))]
+#[bench]
+fn jawiki(b: &mut Bencher) {
+ // To benchmark, download & extract `jawiki-20220501-pages-articles-multistream-index.txt` from
+ // https://dumps.wikimedia.org/jawiki/20220501/jawiki-20220501-pages-articles-multistream-index.txt.bz2
+ let data_path = "bench_data/jawiki-20220501-pages-articles-multistream-index.txt";
+ let string = std::fs::read_to_string(data_path).unwrap_or_default();
+ b.iter(|| test::black_box(UnicodeWidthStr::width(string.as_str())));
+}
#[test]
fn test_str() {
use super::UnicodeWidthStr;
diff --git a/vendor/unicode-xid/.cargo-checksum.json b/vendor/unicode-xid/.cargo-checksum.json
index 0f93609e5..be3630543 100644
--- a/vendor/unicode-xid/.cargo-checksum.json
+++ b/vendor/unicode-xid/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"50d9e34c8bf5a28d7e160844ed52b641c7975414e8be75166a8979710c17bcf2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"2d01a2c43c4ec10fb3b74bf84fe06995d3d53d06c968fb4e27e64682058ba9e3","benches/xid.rs":"a2986ce1df5d93bff51e73dc234bffb341d4fe5d749247296f02396dde16a72b","src/lib.rs":"3cdd204115af45e9ece70db737d711e1798eac40eaa6cc4e8280bb3342e1408e","src/tables.rs":"1c8650d5bed6c75c4071f5cac2127aaab578d887622d2fdde8808492caec5c91","src/tests.rs":"b866f890acd631e667635785c34b1723709f10a9515ca525b41de8a062c7b204","tests/exhaustive_tests.rs":"ec91e9124d61e5b3e2fbbbf37a2fd30d6c7a8fa22639d6720b416d9ebc1007c5"},"package":"957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"} \ No newline at end of file
+{"files":{"COPYRIGHT":"23860c2a7b5d96b21569afedf033469bab9fe14a1b24a35068b8641c578ce24d","Cargo.toml":"289ae8b5c1859b5556dd663b31efae72255f69e3c05408ce7a51c8ba65573677","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"7b63ecd5f1902af1b63729947373683c32745c16a10e8e6292e2e2dcd7e90ae0","README.md":"d13b0abf515d4b41b684a2255169f4340c32256c91e6a4835cafaec2161b5e5f","benches/xid.rs":"a2986ce1df5d93bff51e73dc234bffb341d4fe5d749247296f02396dde16a72b","src/lib.rs":"3cdd204115af45e9ece70db737d711e1798eac40eaa6cc4e8280bb3342e1408e","src/tables.rs":"e4c2e9b70f45d262b78fde8435a969eb2478ca6d9dacd061953f54cf344f0f4d","src/tests.rs":"b866f890acd631e667635785c34b1723709f10a9515ca525b41de8a062c7b204","tests/exhaustive_tests.rs":"ec91e9124d61e5b3e2fbbbf37a2fd30d6c7a8fa22639d6720b416d9ebc1007c5"},"package":"f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"} \ No newline at end of file
diff --git a/vendor/unicode-xid/Cargo.toml b/vendor/unicode-xid/Cargo.toml
index 04afa4c60..817a4f42f 100644
--- a/vendor/unicode-xid/Cargo.toml
+++ b/vendor/unicode-xid/Cargo.toml
@@ -12,7 +12,7 @@
[package]
rust-version = "1.17"
name = "unicode-xid"
-version = "0.2.3"
+version = "0.2.4"
authors = [
"erick.tryzelaar <erick.tryzelaar@gmail.com>",
"kwantam <kwantam@gmail.com>",
diff --git a/vendor/unicode-xid/README.md b/vendor/unicode-xid/README.md
index 325d35e95..747684303 100644
--- a/vendor/unicode-xid/README.md
+++ b/vendor/unicode-xid/README.md
@@ -26,6 +26,15 @@ on std, and instead uses equivalent functions from core.
# changelog
+## 0.2.4
+
+- Update to Unicode 15.0.0
+- Replace `const` tables with `static` tables.
+
+## 0.2.3
+
+- Update to Unicode 14.0.0
+
## 0.2.2
- Add an ASCII fast-path
diff --git a/vendor/unicode-xid/src/tables.rs b/vendor/unicode-xid/src/tables.rs
index a4a072f36..c12e76c0b 100644
--- a/vendor/unicode-xid/src/tables.rs
+++ b/vendor/unicode-xid/src/tables.rs
@@ -14,7 +14,7 @@
/// The version of [Unicode](http://www.unicode.org/)
/// that this version of unicode-xid is based on.
-pub const UNICODE_VERSION: (u64, u64, u64) = (14, 0, 0);
+pub const UNICODE_VERSION: (u64, u64, u64) = (15, 0, 0);
fn bsearch_range_table(c: char, r: &[(char, char)]) -> bool {
use core::cmp::Ordering::{Equal, Greater, Less};
@@ -37,7 +37,7 @@ fn bsearch_range_table(c: char, r: &[(char, char)]) -> bool {
}
pub mod derived_property {
- pub const XID_Continue_table: &[(char, char)] = &[
+ static XID_Continue_table: &[(char, char)] = &[
('\u{30}', '\u{39}'),
('\u{41}', '\u{5a}'),
('\u{5f}', '\u{5f}'),
@@ -196,7 +196,7 @@ pub mod derived_property {
('\u{cdd}', '\u{cde}'),
('\u{ce0}', '\u{ce3}'),
('\u{ce6}', '\u{cef}'),
- ('\u{cf1}', '\u{cf2}'),
+ ('\u{cf1}', '\u{cf3}'),
('\u{d00}', '\u{d0c}'),
('\u{d0e}', '\u{d10}'),
('\u{d12}', '\u{d44}'),
@@ -229,7 +229,7 @@ pub mod derived_property {
('\u{ea7}', '\u{ebd}'),
('\u{ec0}', '\u{ec4}'),
('\u{ec6}', '\u{ec6}'),
- ('\u{ec8}', '\u{ecd}'),
+ ('\u{ec8}', '\u{ece}'),
('\u{ed0}', '\u{ed9}'),
('\u{edc}', '\u{edf}'),
('\u{f00}', '\u{f00}'),
@@ -549,7 +549,7 @@ pub mod derived_property {
('\u{10e80}', '\u{10ea9}'),
('\u{10eab}', '\u{10eac}'),
('\u{10eb0}', '\u{10eb1}'),
- ('\u{10f00}', '\u{10f1c}'),
+ ('\u{10efd}', '\u{10f1c}'),
('\u{10f27}', '\u{10f27}'),
('\u{10f30}', '\u{10f50}'),
('\u{10f70}', '\u{10f85}'),
@@ -572,7 +572,7 @@ pub mod derived_property {
('\u{111dc}', '\u{111dc}'),
('\u{11200}', '\u{11211}'),
('\u{11213}', '\u{11237}'),
- ('\u{1123e}', '\u{1123e}'),
+ ('\u{1123e}', '\u{11241}'),
('\u{11280}', '\u{11286}'),
('\u{11288}', '\u{11288}'),
('\u{1128a}', '\u{1128d}'),
@@ -653,12 +653,17 @@ pub mod derived_property {
('\u{11d93}', '\u{11d98}'),
('\u{11da0}', '\u{11da9}'),
('\u{11ee0}', '\u{11ef6}'),
+ ('\u{11f00}', '\u{11f10}'),
+ ('\u{11f12}', '\u{11f3a}'),
+ ('\u{11f3e}', '\u{11f42}'),
+ ('\u{11f50}', '\u{11f59}'),
('\u{11fb0}', '\u{11fb0}'),
('\u{12000}', '\u{12399}'),
('\u{12400}', '\u{1246e}'),
('\u{12480}', '\u{12543}'),
('\u{12f90}', '\u{12ff0}'),
- ('\u{13000}', '\u{1342e}'),
+ ('\u{13000}', '\u{1342f}'),
+ ('\u{13440}', '\u{13455}'),
('\u{14400}', '\u{14646}'),
('\u{16800}', '\u{16a38}'),
('\u{16a40}', '\u{16a5e}'),
@@ -686,7 +691,9 @@ pub mod derived_property {
('\u{1aff5}', '\u{1affb}'),
('\u{1affd}', '\u{1affe}'),
('\u{1b000}', '\u{1b122}'),
+ ('\u{1b132}', '\u{1b132}'),
('\u{1b150}', '\u{1b152}'),
+ ('\u{1b155}', '\u{1b155}'),
('\u{1b164}', '\u{1b167}'),
('\u{1b170}', '\u{1b2fb}'),
('\u{1bc00}', '\u{1bc6a}'),
@@ -740,17 +747,21 @@ pub mod derived_property {
('\u{1da9b}', '\u{1da9f}'),
('\u{1daa1}', '\u{1daaf}'),
('\u{1df00}', '\u{1df1e}'),
+ ('\u{1df25}', '\u{1df2a}'),
('\u{1e000}', '\u{1e006}'),
('\u{1e008}', '\u{1e018}'),
('\u{1e01b}', '\u{1e021}'),
('\u{1e023}', '\u{1e024}'),
('\u{1e026}', '\u{1e02a}'),
+ ('\u{1e030}', '\u{1e06d}'),
+ ('\u{1e08f}', '\u{1e08f}'),
('\u{1e100}', '\u{1e12c}'),
('\u{1e130}', '\u{1e13d}'),
('\u{1e140}', '\u{1e149}'),
('\u{1e14e}', '\u{1e14e}'),
('\u{1e290}', '\u{1e2ae}'),
('\u{1e2c0}', '\u{1e2f9}'),
+ ('\u{1e4d0}', '\u{1e4f9}'),
('\u{1e7e0}', '\u{1e7e6}'),
('\u{1e7e8}', '\u{1e7eb}'),
('\u{1e7ed}', '\u{1e7ee}'),
@@ -794,12 +805,13 @@ pub mod derived_property {
('\u{1eeab}', '\u{1eebb}'),
('\u{1fbf0}', '\u{1fbf9}'),
('\u{20000}', '\u{2a6df}'),
- ('\u{2a700}', '\u{2b738}'),
+ ('\u{2a700}', '\u{2b739}'),
('\u{2b740}', '\u{2b81d}'),
('\u{2b820}', '\u{2cea1}'),
('\u{2ceb0}', '\u{2ebe0}'),
('\u{2f800}', '\u{2fa1d}'),
('\u{30000}', '\u{3134a}'),
+ ('\u{31350}', '\u{323af}'),
('\u{e0100}', '\u{e01ef}'),
];
@@ -807,7 +819,7 @@ pub mod derived_property {
super::bsearch_range_table(c, XID_Continue_table)
}
- pub const XID_Start_table: &[(char, char)] = &[
+ static XID_Start_table: &[(char, char)] = &[
('\u{41}', '\u{5a}'),
('\u{61}', '\u{7a}'),
('\u{aa}', '\u{aa}'),
@@ -1283,6 +1295,7 @@ pub mod derived_property {
('\u{111dc}', '\u{111dc}'),
('\u{11200}', '\u{11211}'),
('\u{11213}', '\u{1122b}'),
+ ('\u{1123f}', '\u{11240}'),
('\u{11280}', '\u{11286}'),
('\u{11288}', '\u{11288}'),
('\u{1128a}', '\u{1128d}'),
@@ -1345,12 +1358,16 @@ pub mod derived_property {
('\u{11d6a}', '\u{11d89}'),
('\u{11d98}', '\u{11d98}'),
('\u{11ee0}', '\u{11ef2}'),
+ ('\u{11f02}', '\u{11f02}'),
+ ('\u{11f04}', '\u{11f10}'),
+ ('\u{11f12}', '\u{11f33}'),
('\u{11fb0}', '\u{11fb0}'),
('\u{12000}', '\u{12399}'),
('\u{12400}', '\u{1246e}'),
('\u{12480}', '\u{12543}'),
('\u{12f90}', '\u{12ff0}'),
- ('\u{13000}', '\u{1342e}'),
+ ('\u{13000}', '\u{1342f}'),
+ ('\u{13441}', '\u{13446}'),
('\u{14400}', '\u{14646}'),
('\u{16800}', '\u{16a38}'),
('\u{16a40}', '\u{16a5e}'),
@@ -1373,7 +1390,9 @@ pub mod derived_property {
('\u{1aff5}', '\u{1affb}'),
('\u{1affd}', '\u{1affe}'),
('\u{1b000}', '\u{1b122}'),
+ ('\u{1b132}', '\u{1b132}'),
('\u{1b150}', '\u{1b152}'),
+ ('\u{1b155}', '\u{1b155}'),
('\u{1b164}', '\u{1b167}'),
('\u{1b170}', '\u{1b2fb}'),
('\u{1bc00}', '\u{1bc6a}'),
@@ -1411,11 +1430,14 @@ pub mod derived_property {
('\u{1d7aa}', '\u{1d7c2}'),
('\u{1d7c4}', '\u{1d7cb}'),
('\u{1df00}', '\u{1df1e}'),
+ ('\u{1df25}', '\u{1df2a}'),
+ ('\u{1e030}', '\u{1e06d}'),
('\u{1e100}', '\u{1e12c}'),
('\u{1e137}', '\u{1e13d}'),
('\u{1e14e}', '\u{1e14e}'),
('\u{1e290}', '\u{1e2ad}'),
('\u{1e2c0}', '\u{1e2eb}'),
+ ('\u{1e4d0}', '\u{1e4eb}'),
('\u{1e7e0}', '\u{1e7e6}'),
('\u{1e7e8}', '\u{1e7eb}'),
('\u{1e7ed}', '\u{1e7ee}'),
@@ -1457,12 +1479,13 @@ pub mod derived_property {
('\u{1eea5}', '\u{1eea9}'),
('\u{1eeab}', '\u{1eebb}'),
('\u{20000}', '\u{2a6df}'),
- ('\u{2a700}', '\u{2b738}'),
+ ('\u{2a700}', '\u{2b739}'),
('\u{2b740}', '\u{2b81d}'),
('\u{2b820}', '\u{2cea1}'),
('\u{2ceb0}', '\u{2ebe0}'),
('\u{2f800}', '\u{2fa1d}'),
('\u{30000}', '\u{3134a}'),
+ ('\u{31350}', '\u{323af}'),
];
pub fn XID_Start(c: char) -> bool {
diff --git a/vendor/url/.cargo-checksum.json b/vendor/url/.cargo-checksum.json
index 2c03fac5f..8a659101a 100644
--- a/vendor/url/.cargo-checksum.json
+++ b/vendor/url/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"9814ea7672535568bb8c84b23512fe0119f85a14a2cc84d2f7f0b3848c61a65c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"20c7855c364d57ea4c97889a5e8d98470a9952dade37bd9248b9a54431670e5e","src/host.rs":"88adbe3a8dc691a4e32d7ed664dc7f17f8a1a863ffa4cde4d618032a00ec6653","src/lib.rs":"30372556e2352f93fa56178b85174eb0c3a819e87b12c288b67a101f7535a712","src/origin.rs":"2b967dd04fa5852b4a89f13cc628f3bfd84d1432e9447b2d3cbc6fee8aba3738","src/parser.rs":"eab4f6c7bffc021e9722375447a259683b8257dc6dff784c715032c39d4b4923","src/path_segments.rs":"dd6b637245b2ad77ce96221df3f80c8b4ad858cd52aecc86b97166dec386882a","src/quirks.rs":"8a504a2eeb74429e3282f2628014f3af9a567284c2b08bd0360bfd72d3a17e43","src/slicing.rs":"25425fc5c4100a3a5da49d1e0b497f6536066afcc91c4ba4dff5ace0860acd40","tests/data.rs":"dace394aed466df0e8afea0037bb8c90306d30ce75efdaff39feb00dbd07fa79","tests/setters_tests.json":"486f6d129960d0d0d99b533caf9bef21113b31adcdb83296dfc4a59cd8431715","tests/unit.rs":"61e014d600aa558f4913ac7bc268d652eda67daead72b0b0cf288524b1d71d13","tests/urltestdata.json":"afe55dd9583d125305d31e152478de9cc19801006b413c5f4fb7d430c50b1d11"},"package":"a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"} \ No newline at end of file
+{"files":{"Cargo.toml":"c861c99782bfd4be160167bf659e87792f00d7e1eb1ee072a59546143fa980f4","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"76e972ac0f4ddb116e86e10100132a783931a596e7b9872eaa31be15cd4d751d","README.md":"71b01ec6f2f4ce47235ee430ba0c41afac563403a9dbcda23a584c3e915395ac","src/host.rs":"60cd21e0b4cbb208c36eec5d40628a8bbe1d7ef13e481479b33f89cef96277ec","src/lib.rs":"c48655bc0455efecb7f7e36dfee8b92f6d96d9a1fbc5b24890ef255fb7843956","src/origin.rs":"19a4b451e8615bfef7239d2fc719c489398fe5044edb0df7c84b54eef4ceba1b","src/parser.rs":"5c05f233722560fd21899e982b9defc828ba13fbe70e7cf157a439968716c6ae","src/path_segments.rs":"dd6b637245b2ad77ce96221df3f80c8b4ad858cd52aecc86b97166dec386882a","src/quirks.rs":"82903ff9c95604409cded330e36ebba0ede91c469d1aa40fb646186e2bef0769","src/slicing.rs":"25425fc5c4100a3a5da49d1e0b497f6536066afcc91c4ba4dff5ace0860acd40","tests/data.rs":"dbd795b25fe7869b242aeeb822c736167d5b4be1f6a867f563e23977d07c8fc5","tests/debugger_visualizer.rs":"d3a9466c636ee80ec9181817a8d30ea3e0cee699776ee4b805175981e4775448","tests/setters_tests.json":"486f6d129960d0d0d99b533caf9bef21113b31adcdb83296dfc4a59cd8431715","tests/unit.rs":"9707676cd80d7c8131b9c805f03b387a36ca2b1dda84a4d567788814c8afe59f","tests/urltestdata.json":"9dca78fbbcb6fceb0584f2fae7b3bb4e8a868750f2426c359c6694aed25f2682"},"package":"0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"} \ No newline at end of file
diff --git a/vendor/url/Cargo.toml b/vendor/url/Cargo.toml
index 108b1493e..4363ae58f 100644
--- a/vendor/url/Cargo.toml
+++ b/vendor/url/Cargo.toml
@@ -3,52 +3,81 @@
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g., crates.io) dependencies
+# to registry (e.g., crates.io) dependencies.
#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
edition = "2018"
+rust-version = "1.51"
name = "url"
-version = "2.2.2"
+version = "2.3.1"
authors = ["The rust-url developers"]
-include = ["src/**/*", "LICENSE-*", "README.md", "tests/**"]
+include = [
+ "src/**/*",
+ "LICENSE-*",
+ "README.md",
+ "tests/**",
+]
description = "URL library for Rust, based on the WHATWG URL Standard"
documentation = "https://docs.rs/url"
-readme = "../README.md"
-keywords = ["url", "parser"]
-categories = ["parser-implementations", "web-programming", "encoding"]
-license = "MIT/Apache-2.0"
+readme = "README.md"
+keywords = [
+ "url",
+ "parser",
+]
+categories = [
+ "parser-implementations",
+ "web-programming",
+ "encoding",
+]
+license = "MIT OR Apache-2.0"
repository = "https://github.com/servo/rust-url"
+[[test]]
+name = "debugger_visualizer"
+path = "tests/debugger_visualizer.rs"
+test = false
+required-features = ["debugger_visualizer"]
+
[[bench]]
name = "parse_url"
path = "benches/parse_url.rs"
harness = false
+
[dependencies.form_urlencoded]
-version = "1.0.0"
+version = "1.1.0"
[dependencies.idna]
-version = "0.2.0"
-
-[dependencies.matches]
-version = "0.1"
+version = "0.3.0"
[dependencies.percent-encoding]
-version = "2.1.0"
+version = "2.2.0"
[dependencies.serde]
version = "1.0"
features = ["derive"]
optional = true
+
[dev-dependencies.bencher]
version = "0.1"
+[dev-dependencies.debugger_test]
+version = "0.1"
+
+[dev-dependencies.debugger_test_parser]
+version = "0.1"
+
[dev-dependencies.serde_json]
version = "1.0"
+
+[features]
+debugger_visualizer = []
+default = []
+expose_internals = []
+
[badges.appveyor]
repository = "Manishearth/rust-url"
diff --git a/vendor/url/LICENSE-MIT b/vendor/url/LICENSE-MIT
index 24de6b418..51d5dc7eb 100644
--- a/vendor/url/LICENSE-MIT
+++ b/vendor/url/LICENSE-MIT
@@ -1,4 +1,4 @@
-Copyright (c) 2013-2016 The rust-url developers
+Copyright (c) 2013-2022 The rust-url developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
diff --git a/vendor/url/README.md b/vendor/url/README.md
new file mode 100644
index 000000000..ab31bffc6
--- /dev/null
+++ b/vendor/url/README.md
@@ -0,0 +1,14 @@
+rust-url
+========
+
+[![Build status](https://github.com/servo/rust-url/workflows/CI/badge.svg)](https://github.com/servo/rust-url/actions?query=workflow%3ACI)
+[![Coverage](https://codecov.io/gh/servo/rust-url/branch/master/graph/badge.svg)](https://codecov.io/gh/servo/rust-url)
+[![Chat](https://img.shields.io/badge/chat-%23rust--url:mozilla.org-%2346BC99?logo=Matrix)](https://matrix.to/#/#rust-url:mozilla.org)
+[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE-MIT)
+[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE-APACHE)
+
+URL library for Rust, based on the [URL Standard](https://url.spec.whatwg.org/).
+
+[Documentation](https://docs.rs/url/)
+
+Please see [UPGRADING.md](https://github.com/servo/rust-url/blob/master/UPGRADING.md) if you are upgrading from a previous version.
diff --git a/vendor/url/src/host.rs b/vendor/url/src/host.rs
index 953743649..f1921c654 100644
--- a/vendor/url/src/host.rs
+++ b/vendor/url/src/host.rs
@@ -82,7 +82,9 @@ impl Host<String> {
return parse_ipv6addr(&input[1..input.len() - 1]).map(Host::Ipv6);
}
let domain = percent_decode(input.as_bytes()).decode_utf8_lossy();
- let domain = idna::domain_to_ascii(&domain)?;
+
+ let domain = Self::domain_to_ascii(&domain)?;
+
if domain.is_empty() {
return Err(ParseError::EmptyHost);
}
@@ -90,9 +92,7 @@ impl Host<String> {
let is_invalid_domain_char = |c| {
matches!(
c,
- '\0' | '\t'
- | '\n'
- | '\r'
+ '\0'..='\u{001F}'
| ' '
| '#'
| '%'
@@ -106,12 +106,15 @@ impl Host<String> {
| '\\'
| ']'
| '^'
+ | '\u{007F}'
+ | '|'
)
};
if domain.find(is_invalid_domain_char).is_some() {
Err(ParseError::InvalidDomainCharacter)
- } else if let Some(address) = parse_ipv4addr(&domain)? {
+ } else if ends_in_a_number(&domain) {
+ let address = parse_ipv4addr(&domain)?;
Ok(Host::Ipv4(address))
} else {
Ok(Host::Domain(domain))
@@ -145,6 +148,7 @@ impl Host<String> {
| '\\'
| ']'
| '^'
+ | '|'
)
};
@@ -156,6 +160,11 @@ impl Host<String> {
))
}
}
+
+ /// convert domain with idna
+ fn domain_to_ascii(domain: &str) -> Result<String, ParseError> {
+ idna::domain_to_ascii(domain).map_err(Into::into)
+ }
}
impl<S: AsRef<str>> fmt::Display for Host<S> {
@@ -247,8 +256,33 @@ fn longest_zero_sequence(pieces: &[u16; 8]) -> (isize, isize) {
}
}
+/// <https://url.spec.whatwg.org/#ends-in-a-number-checker>
+fn ends_in_a_number(input: &str) -> bool {
+ let mut parts = input.rsplit('.');
+ let last = parts.next().unwrap();
+ let last = if last.is_empty() {
+ if let Some(last) = parts.next() {
+ last
+ } else {
+ return false;
+ }
+ } else {
+ last
+ };
+ if !last.is_empty() && last.chars().all(|c| ('0'..='9').contains(&c)) {
+ return true;
+ }
+
+ parse_ipv4number(last).is_ok()
+}
+
/// <https://url.spec.whatwg.org/#ipv4-number-parser>
+/// Ok(None) means the input is a valid number, but it overflows a `u32`.
fn parse_ipv4number(mut input: &str) -> Result<Option<u32>, ()> {
+ if input.is_empty() {
+ return Err(());
+ }
+
let mut r = 10;
if input.starts_with("0x") || input.starts_with("0X") {
input = &input[2..];
@@ -258,10 +292,10 @@ fn parse_ipv4number(mut input: &str) -> Result<Option<u32>, ()> {
r = 8;
}
- // At the moment we can't know the reason why from_str_radix fails
- // https://github.com/rust-lang/rust/issues/22639
- // So instead we check if the input looks like a real number and only return
- // an error when it's an overflow.
+ if input.is_empty() {
+ return Ok(Some(0));
+ }
+
let valid_number = match r {
8 => input.chars().all(|c| ('0'..='7').contains(&c)),
10 => input.chars().all(|c| ('0'..='9').contains(&c)),
@@ -270,50 +304,34 @@ fn parse_ipv4number(mut input: &str) -> Result<Option<u32>, ()> {
}),
_ => false,
};
-
if !valid_number {
- return Ok(None);
+ return Err(());
}
- if input.is_empty() {
- return Ok(Some(0));
- }
- if input.starts_with('+') {
- return Ok(None);
- }
match u32::from_str_radix(input, r) {
- Ok(number) => Ok(Some(number)),
- Err(_) => Err(()),
+ Ok(num) => Ok(Some(num)),
+ Err(_) => Ok(None), // The only possible error kind here is an integer overflow.
+ // The validity of the chars in the input is checked above.
}
}
/// <https://url.spec.whatwg.org/#concept-ipv4-parser>
-fn parse_ipv4addr(input: &str) -> ParseResult<Option<Ipv4Addr>> {
- if input.is_empty() {
- return Ok(None);
- }
+fn parse_ipv4addr(input: &str) -> ParseResult<Ipv4Addr> {
let mut parts: Vec<&str> = input.split('.').collect();
if parts.last() == Some(&"") {
parts.pop();
}
if parts.len() > 4 {
- return Ok(None);
+ return Err(ParseError::InvalidIpv4Address);
}
let mut numbers: Vec<u32> = Vec::new();
- let mut overflow = false;
for part in parts {
- if part.is_empty() {
- return Ok(None);
- }
match parse_ipv4number(part) {
Ok(Some(n)) => numbers.push(n),
- Ok(None) => return Ok(None),
- Err(()) => overflow = true,
+ Ok(None) => return Err(ParseError::InvalidIpv4Address), // u32 overflow
+ Err(()) => return Err(ParseError::InvalidIpv4Address),
};
}
- if overflow {
- return Err(ParseError::InvalidIpv4Address);
- }
let mut ipv4 = numbers.pop().expect("a non-empty list of numbers");
// Equivalent to: ipv4 >= 256 ** (4 − numbers.len())
if ipv4 > u32::max_value() >> (8 * numbers.len() as u32) {
@@ -325,7 +343,7 @@ fn parse_ipv4addr(input: &str) -> ParseResult<Option<Ipv4Addr>> {
for (counter, n) in numbers.iter().enumerate() {
ipv4 += n << (8 * (3 - counter as u32))
}
- Ok(Some(Ipv4Addr::from(ipv4)))
+ Ok(Ipv4Addr::from(ipv4))
}
/// <https://url.spec.whatwg.org/#concept-ipv6-parser>
diff --git a/vendor/url/src/lib.rs b/vendor/url/src/lib.rs
index 42793cf48..6dc09d12f 100644
--- a/vendor/url/src/lib.rs
+++ b/vendor/url/src/lib.rs
@@ -118,12 +118,16 @@ See [serde documentation](https://serde.rs) for more information.
```toml
url = { version = "2", features = ["serde"] }
```
+
*/
-#![doc(html_root_url = "https://docs.rs/url/2.2.2")]
+#![doc(html_root_url = "https://docs.rs/url/2.3.1")]
+#![cfg_attr(
+ feature = "debugger_visualizer",
+ feature(debugger_visualizer),
+ debugger_visualizer(natvis_file = "../../debug_metadata/url.natvis")
+)]
-#[macro_use]
-extern crate matches;
pub use form_urlencoded;
#[cfg(feature = "serde")]
@@ -460,7 +464,7 @@ impl Url {
}
// Add the filename if they are not the same
- if base_filename != url_filename {
+ if !relative.is_empty() || base_filename != url_filename {
// If the URIs filename is empty this means that it was a directory
// so we'll have to append a '/'.
//
@@ -1234,14 +1238,9 @@ impl Url {
/// # }
/// # run().unwrap();
/// ```
- #[allow(clippy::manual_strip)] // introduced in 1.45, MSRV is 1.36
pub fn path_segments(&self) -> Option<str::Split<'_, char>> {
let path = self.path();
- if path.starts_with('/') {
- Some(path[1..].split('/'))
- } else {
- None
- }
+ path.strip_prefix('/').map(|remainder| remainder.split('/'))
}
/// Return this URL’s query string, if any, as a percent-encoded ASCII string.
@@ -1304,7 +1303,7 @@ impl Url {
/// # Ok(())
/// # }
/// # run().unwrap();
- ///
+ /// ```
#[inline]
pub fn query_pairs(&self) -> form_urlencoded::Parse<'_> {
@@ -1351,7 +1350,7 @@ impl Url {
}
fn mutate<F: FnOnce(&mut Parser<'_>) -> R, R>(&mut self, f: F) -> R {
- let mut parser = Parser::for_setter(mem::replace(&mut self.serialization, String::new()));
+ let mut parser = Parser::for_setter(mem::take(&mut self.serialization));
let result = f(&mut parser);
self.serialization = parser.serialization;
result
@@ -1541,6 +1540,19 @@ impl Url {
/// url.set_path("data/report.csv");
/// assert_eq!(url.as_str(), "https://example.com/data/report.csv");
/// assert_eq!(url.path(), "/data/report.csv");
+ ///
+ /// // `set_path` percent-encodes the given string if it's not already percent-encoded.
+ /// let mut url = Url::parse("https://example.com")?;
+ /// url.set_path("api/some comments");
+ /// assert_eq!(url.as_str(), "https://example.com/api/some%20comments");
+ /// assert_eq!(url.path(), "/api/some%20comments");
+ ///
+ /// // `set_path` will not double percent-encode the string if it's already percent-encoded.
+ /// let mut url = Url::parse("https://example.com")?;
+ /// url.set_path("api/some%20comments");
+ /// assert_eq!(url.as_str(), "https://example.com/api/some%20comments");
+ /// assert_eq!(url.path(), "/api/some%20comments");
+ ///
/// # Ok(())
/// # }
/// # run().unwrap();
@@ -1792,8 +1804,10 @@ impl Url {
return Err(ParseError::SetHostOnCannotBeABaseUrl);
}
+ let scheme_type = SchemeType::from(self.scheme());
+
if let Some(host) = host {
- if host.is_empty() && SchemeType::from(self.scheme()).is_special() {
+ if host.is_empty() && scheme_type.is_special() && !scheme_type.is_file() {
return Err(ParseError::EmptyHost);
}
let mut host_substr = host;
@@ -1817,15 +1831,20 @@ impl Url {
self.set_host_internal(Host::parse_opaque(host_substr)?, None);
}
} else if self.has_host() {
- let scheme_type = SchemeType::from(self.scheme());
- if scheme_type.is_special() {
+ if scheme_type.is_special() && !scheme_type.is_file() {
return Err(ParseError::EmptyHost);
} else if self.serialization.len() == self.path_start as usize {
self.serialization.push('/');
}
debug_assert!(self.byte_at(self.scheme_end) == b':');
debug_assert!(self.byte_at(self.path_start) == b'/');
- let new_path_start = self.scheme_end + 1;
+
+ let new_path_start = if scheme_type.is_file() {
+ self.scheme_end + 3
+ } else {
+ self.scheme_end + 1
+ };
+
self.serialization
.drain(new_path_start as usize..self.path_start as usize);
let offset = self.path_start - new_path_start;
@@ -2127,7 +2146,7 @@ impl Url {
///
/// # Examples
///
- /// Change the URL’s scheme from `https` to `foo`:
+ /// Change the URL’s scheme from `https` to `http`:
///
/// ```
/// use url::Url;
@@ -2298,7 +2317,7 @@ impl Url {
/// # run().unwrap();
/// # }
/// ```
- #[cfg(any(unix, windows, target_os = "redox"))]
+ #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
#[allow(clippy::result_unit_err)]
pub fn from_file_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut serialization = "file://".to_owned();
@@ -2335,7 +2354,7 @@ impl Url {
///
/// Note that `std::path` does not consider trailing slashes significant
/// and usually does not include them (e.g. in `Path::parent()`).
- #[cfg(any(unix, windows, target_os = "redox"))]
+ #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
#[allow(clippy::result_unit_err)]
pub fn from_directory_path<P: AsRef<Path>>(path: P) -> Result<Url, ()> {
let mut url = Url::from_file_path(path)?;
@@ -2452,7 +2471,7 @@ impl Url {
/// (That is, if the percent-decoded path contains a NUL byte or,
/// for a Windows path, is not UTF-8.)
#[inline]
- #[cfg(any(unix, windows, target_os = "redox"))]
+ #[cfg(any(unix, windows, target_os = "redox", target_os = "wasi"))]
#[allow(clippy::result_unit_err)]
pub fn to_file_path(&self) -> Result<PathBuf, ()> {
if let Some(segments) = self.path_segments() {
@@ -2511,7 +2530,7 @@ impl fmt::Display for Url {
}
}
-/// String converstion.
+/// String conversion.
impl From<Url> for String {
fn from(value: Url) -> String {
value.serialization
@@ -2656,12 +2675,15 @@ impl<'de> serde::Deserialize<'de> for Url {
}
}
-#[cfg(any(unix, target_os = "redox"))]
+#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
fn path_to_file_url_segments(
path: &Path,
serialization: &mut String,
) -> Result<(u32, HostInternal), ()> {
+ #[cfg(any(unix, target_os = "redox"))]
use std::os::unix::prelude::OsStrExt;
+ #[cfg(target_os = "wasi")]
+ use std::os::wasi::prelude::OsStrExt;
if !path.is_absolute() {
return Err(());
}
@@ -2706,6 +2728,7 @@ fn path_to_file_url_segments_windows(
let host_start = serialization.len() + 1;
let host_end;
let host_internal;
+
match components.next() {
Some(Component::Prefix(ref p)) => match p.kind() {
Prefix::Disk(letter) | Prefix::VerbatimDisk(letter) => {
@@ -2726,7 +2749,6 @@ fn path_to_file_url_segments_windows(
}
_ => return Err(()),
},
-
_ => return Err(()),
}
@@ -2735,12 +2757,15 @@ fn path_to_file_url_segments_windows(
if component == Component::RootDir {
continue;
}
+
path_only_has_prefix = false;
// FIXME: somehow work with non-unicode?
let component = component.as_os_str().to_str().ok_or(())?;
+
serialization.push('/');
serialization.extend(percent_encode(component.as_bytes(), PATH_SEGMENT));
}
+
// A windows drive letter must end with a slash.
if serialization.len() > host_start
&& parser::is_windows_drive_letter(&serialization[host_start..])
@@ -2748,16 +2773,20 @@ fn path_to_file_url_segments_windows(
{
serialization.push('/');
}
+
Ok((host_end, host_internal))
}
-#[cfg(any(unix, target_os = "redox"))]
+#[cfg(any(unix, target_os = "redox", target_os = "wasi"))]
fn file_url_segments_to_pathbuf(
host: Option<&str>,
segments: str::Split<'_, char>,
) -> Result<PathBuf, ()> {
use std::ffi::OsStr;
+ #[cfg(any(unix, target_os = "redox"))]
use std::os::unix::prelude::OsStrExt;
+ #[cfg(target_os = "wasi")]
+ use std::os::wasi::prelude::OsStrExt;
if host.is_some() {
return Err(());
@@ -2768,10 +2797,12 @@ fn file_url_segments_to_pathbuf(
} else {
Vec::new()
};
+
for segment in segments {
bytes.push(b'/');
bytes.extend(percent_decode(segment.as_bytes()));
}
+
// A windows drive letter must end with a slash.
if bytes.len() > 2
&& matches!(bytes[bytes.len() - 2], b'a'..=b'z' | b'A'..=b'Z')
@@ -2779,12 +2810,15 @@ fn file_url_segments_to_pathbuf(
{
bytes.push(b'/');
}
+
let os_str = OsStr::from_bytes(&bytes);
let path = PathBuf::from(os_str);
+
debug_assert!(
path.is_absolute(),
"to_file_path() failed to produce an absolute Path"
);
+
Ok(path)
}
diff --git a/vendor/url/src/origin.rs b/vendor/url/src/origin.rs
index be2d948b8..81193f510 100644
--- a/vendor/url/src/origin.rs
+++ b/vendor/url/src/origin.rs
@@ -9,7 +9,6 @@
use crate::host::Host;
use crate::parser::default_port;
use crate::Url;
-use idna::domain_to_unicode;
use std::sync::atomic::{AtomicUsize, Ordering};
pub fn url_origin(url: &Url) -> Origin {
@@ -93,7 +92,7 @@ impl Origin {
Origin::Tuple(ref scheme, ref host, port) => {
let host = match *host {
Host::Domain(ref domain) => {
- let (domain, _errors) = domain_to_unicode(domain);
+ let (domain, _errors) = idna::domain_to_unicode(domain);
Host::Domain(domain)
}
_ => host.clone(),
diff --git a/vendor/url/src/parser.rs b/vendor/url/src/parser.rs
index 57be11052..f5438c505 100644
--- a/vendor/url/src/parser.rs
+++ b/vendor/url/src/parser.rs
@@ -52,15 +52,12 @@ macro_rules! simple_enum_error {
///
/// This may be extended in the future so exhaustive matching is
/// discouraged with an unused variant.
- #[allow(clippy::manual_non_exhaustive)] // introduced in 1.40, MSRV is 1.36
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+ #[non_exhaustive]
pub enum ParseError {
$(
$name,
)+
- /// Unused variant enable non-exhaustive matching
- #[doc(hidden)]
- __FutureProof,
}
impl fmt::Display for ParseError {
@@ -69,9 +66,6 @@ macro_rules! simple_enum_error {
$(
ParseError::$name => fmt.write_str($description),
)+
- ParseError::__FutureProof => {
- unreachable!("Don't abuse the FutureProof!");
- }
}
}
}
@@ -105,15 +99,12 @@ macro_rules! syntax_violation_enum {
///
/// This may be extended in the future so exhaustive matching is
/// discouraged with an unused variant.
- #[allow(clippy::manual_non_exhaustive)] // introduced in 1.40, MSRV is 1.36
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+ #[non_exhaustive]
pub enum SyntaxViolation {
$(
$name,
)+
- /// Unused variant enable non-exhaustive matching
- #[doc(hidden)]
- __FutureProof,
}
impl SyntaxViolation {
@@ -122,9 +113,6 @@ macro_rules! syntax_violation_enum {
$(
SyntaxViolation::$name => $description,
)+
- SyntaxViolation::__FutureProof => {
- unreachable!("Don't abuse the FutureProof!");
- }
}
}
}
@@ -154,7 +142,7 @@ impl fmt::Display for SyntaxViolation {
}
}
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
pub enum SchemeType {
File,
SpecialNotFile,
@@ -1227,13 +1215,11 @@ impl<'a> Parser<'a> {
}
}
}
- // Going from &str to String to &str to please the 1.33.0 borrow checker
- let before_slash_string = if ends_with_slash {
- self.serialization[segment_start..self.serialization.len() - 1].to_owned()
+ let segment_before_slash = if ends_with_slash {
+ &self.serialization[segment_start..self.serialization.len() - 1]
} else {
- self.serialization[segment_start..self.serialization.len()].to_owned()
+ &self.serialization[segment_start..self.serialization.len()]
};
- let segment_before_slash: &str = &before_slash_string;
match segment_before_slash {
// If buffer is a double-dot path segment, shorten url’s path,
".." | "%2e%2e" | "%2e%2E" | "%2E%2e" | "%2E%2E" | "%2e." | "%2E." | ".%2e"
@@ -1292,7 +1278,7 @@ impl<'a> Parser<'a> {
//FIXME: log violation
let path = self.serialization.split_off(path_start);
self.serialization.push('/');
- self.serialization.push_str(&path.trim_start_matches('/'));
+ self.serialization.push_str(path.trim_start_matches('/'));
}
input
@@ -1423,7 +1409,8 @@ impl<'a> Parser<'a> {
scheme_end: u32,
mut input: Input<'i>,
) -> Option<Input<'i>> {
- let mut query = String::new(); // FIXME: use a streaming decoder instead
+ let len = input.chars.as_str().len();
+ let mut query = String::with_capacity(len); // FIXME: use a streaming decoder instead
let mut remaining = None;
while let Some(c) = input.next() {
if c == '#' && self.context == Context::UrlParser {
@@ -1563,17 +1550,17 @@ fn is_normalized_windows_drive_letter(segment: &str) -> bool {
is_windows_drive_letter(segment) && segment.as_bytes()[1] == b':'
}
-/// Wether the scheme is file:, the path has a single segment, and that segment
+/// Whether the scheme is file:, the path has a single segment, and that segment
/// is a Windows drive letter
#[inline]
pub fn is_windows_drive_letter(segment: &str) -> bool {
segment.len() == 2 && starts_with_windows_drive_letter(segment)
}
-/// Wether path starts with a root slash
+/// Whether path starts with a root slash
/// and a windows drive letter eg: "/c:" or "/a:/"
fn path_starts_with_windows_drive_letter(s: &str) -> bool {
- if let Some(c) = s.as_bytes().get(0) {
+ if let Some(c) = s.as_bytes().first() {
matches!(c, b'/' | b'\\' | b'?' | b'#') && starts_with_windows_drive_letter(&s[1..])
} else {
false
diff --git a/vendor/url/src/quirks.rs b/vendor/url/src/quirks.rs
index 0dbc6eb44..0674ebb62 100644
--- a/vendor/url/src/quirks.rs
+++ b/vendor/url/src/quirks.rs
@@ -14,6 +14,49 @@
use crate::parser::{default_port, Context, Input, Parser, SchemeType};
use crate::{Host, ParseError, Position, Url};
+/// Internal components / offsets of a URL.
+///
+/// https://user@pass:example.com:1234/foo/bar?baz#quux
+/// | | | | ^^^^| | |
+/// | | | | | | | `----- fragment_start
+/// | | | | | | `--------- query_start
+/// | | | | | `----------------- path_start
+/// | | | | `--------------------- port
+/// | | | `----------------------- host_end
+/// | | `---------------------------------- host_start
+/// | `--------------------------------------- username_end
+/// `---------------------------------------------- scheme_end
+#[derive(Copy, Clone)]
+#[cfg(feature = "expose_internals")]
+pub struct InternalComponents {
+ pub scheme_end: u32,
+ pub username_end: u32,
+ pub host_start: u32,
+ pub host_end: u32,
+ pub port: Option<u16>,
+ pub path_start: u32,
+ pub query_start: Option<u32>,
+ pub fragment_start: Option<u32>,
+}
+
+/// Internal component / parsed offsets of the URL.
+///
+/// This can be useful for implementing efficient serialization
+/// for the URL.
+#[cfg(feature = "expose_internals")]
+pub fn internal_components(url: &Url) -> InternalComponents {
+ InternalComponents {
+ scheme_end: url.scheme_end,
+ username_end: url.username_end,
+ host_start: url.host_start,
+ host_end: url.host_end,
+ port: url.port,
+ path_start: url.path_start,
+ query_start: url.query_start,
+ fragment_start: url.fragment_start,
+ }
+}
+
/// https://url.spec.whatwg.org/#dom-url-domaintoascii
pub fn domain_to_ascii(domain: &str) -> String {
match Host::parse(domain) {
@@ -138,14 +181,10 @@ pub fn set_host(url: &mut Url, new_host: &str) -> Result<(), ()> {
}
}
// Make sure we won't set an empty host to a url with a username or a port
- if host == Host::Domain("".to_string()) {
- if !username(&url).is_empty() {
- return Err(());
- } else if let Some(Some(_)) = opt_port {
- return Err(());
- } else if url.port().is_some() {
- return Err(());
- }
+ if host == Host::Domain("".to_string())
+ && (!username(url).is_empty() || matches!(opt_port, Some(Some(_))) || url.port().is_some())
+ {
+ return Err(());
}
url.set_host_internal(host, opt_port);
Ok(())
@@ -177,10 +216,10 @@ pub fn set_hostname(url: &mut Url, new_hostname: &str) -> Result<(), ()> {
// Empty host on special not file url
if SchemeType::from(url.scheme()) == SchemeType::SpecialNotFile
// Port with an empty host
- ||!port(&url).is_empty()
+ ||!port(url).is_empty()
// Empty host that includes credentials
|| !url.username().is_empty()
- || !url.password().unwrap_or(&"").is_empty()
+ || !url.password().unwrap_or("").is_empty()
{
return Err(());
}
diff --git a/vendor/url/tests/data.rs b/vendor/url/tests/data.rs
index b72c33306..f4001ca2b 100644
--- a/vendor/url/tests/data.rs
+++ b/vendor/url/tests/data.rs
@@ -8,7 +8,6 @@
//! Data-driven tests
-use std::ops::Deref;
use std::str::FromStr;
use serde_json::Value;
@@ -16,7 +15,20 @@ use url::{quirks, Url};
#[test]
fn urltestdata() {
- // Copied form https://github.com/w3c/web-platform-tests/blob/master/url/
+ let idna_skip_inputs = [
+ "http://www.foo。bar.com",
+ "http://Go.com",
+ "http://你好你好",
+ "https://faß.ExAmPlE/",
+ "http://0Xc0.0250.01",
+ "ftp://%e2%98%83",
+ "https://%e2%98%83",
+ "file://a\u{ad}b/p",
+ "file://a%C2%ADb/p",
+ "http://GOO\u{200b}\u{2060}\u{feff}goo.com",
+ ];
+
+ // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/
let mut json = Value::from_str(include_str!("urltestdata.json"))
.expect("JSON parse error in urltestdata.json");
@@ -26,25 +38,39 @@ fn urltestdata() {
continue; // ignore comments
}
- let base = entry.take_string("base");
+ let maybe_base = entry
+ .take_key("base")
+ .expect("missing base key")
+ .maybe_string();
let input = entry.take_string("input");
let failure = entry.take_key("failure").is_some();
- let base = match Url::parse(&base) {
- Ok(base) => base,
- Err(_) if failure => continue,
- Err(message) => {
- eprint_failure(
- format!(" failed: error parsing base {:?}: {}", base, message),
- &format!("parse base for {:?}", input),
- None,
- );
- passed = false;
+ {
+ if idna_skip_inputs.contains(&input.as_str()) {
continue;
}
+ }
+
+ let res = if let Some(base) = maybe_base {
+ let base = match Url::parse(&base) {
+ Ok(base) => base,
+ Err(_) if failure => continue,
+ Err(message) => {
+ eprint_failure(
+ format!(" failed: error parsing base {:?}: {}", base, message),
+ &format!("parse base for {:?}", input),
+ None,
+ );
+ passed = false;
+ continue;
+ }
+ };
+ base.join(&input)
+ } else {
+ Url::parse(&input)
};
- let url = match (base.join(&input), failure) {
+ let url = match (res, failure) {
(Ok(url), false) => url,
(Err(_), true) => continue,
(Err(message), false) => {
@@ -91,7 +117,6 @@ fn urltestdata() {
assert!(passed)
}
-#[allow(clippy::option_as_ref_deref)] // introduced in 1.40, MSRV is 1.36
#[test]
fn setters_tests() {
let mut json = Value::from_str(include_str!("setters_tests.json"))
@@ -106,15 +131,22 @@ fn setters_tests() {
let mut tests = json.take_key(attr).unwrap();
for mut test in tests.as_array_mut().unwrap().drain(..) {
let comment = test.take_key("comment").map(|s| s.string());
+ {
+ if let Some(comment) = comment.as_ref() {
+ if comment.starts_with("IDNA Nontransitional_Processing") {
+ continue;
+ }
+ }
+ }
let href = test.take_string("href");
let new_value = test.take_string("new_value");
let name = format!("{:?}.{} = {:?}", href, attr, new_value);
let mut expected = test.take_key("expected").unwrap();
let mut url = Url::parse(&href).unwrap();
- let comment_ref = comment.as_ref().map(|s| s.deref());
+ let comment_ref = comment.as_deref();
passed &= check_invariants(&url, &name, comment_ref);
- let _ = set(&mut url, attr, &new_value);
+ set(&mut url, attr, &new_value);
for attr in ATTRIBS {
if let Some(value) = expected.take_key(attr) {
@@ -153,6 +185,7 @@ fn check_invariants(url: &Url, name: &str, comment: Option<&str>) -> bool {
trait JsonExt {
fn take_key(&mut self, key: &str) -> Option<Value>;
fn string(self) -> String;
+ fn maybe_string(self) -> Option<String>;
fn take_string(&mut self, key: &str) -> String;
}
@@ -162,10 +195,14 @@ impl JsonExt for Value {
}
fn string(self) -> String {
- if let Value::String(s) = self {
- s
- } else {
- panic!("Not a Value::String")
+ self.maybe_string().expect("")
+ }
+
+ fn maybe_string(self) -> Option<String> {
+ match self {
+ Value::String(s) => Some(s),
+ Value::Null => None,
+ _ => panic!("Not a Value::String or Value::Null"),
}
}
diff --git a/vendor/url/tests/debugger_visualizer.rs b/vendor/url/tests/debugger_visualizer.rs
new file mode 100644
index 000000000..4558e0701
--- /dev/null
+++ b/vendor/url/tests/debugger_visualizer.rs
@@ -0,0 +1,102 @@
+use debugger_test::debugger_test;
+use url::Url;
+
+#[inline(never)]
+fn __break() {}
+
+#[debugger_test(
+ debugger = "cdb",
+ commands = "
+ .nvlist
+
+ dx base_url
+
+ dx url_with_non_special_scheme
+
+ dx url_with_user_pass_port_query_fragments
+
+ dx url_blob
+
+ dx url_with_base
+
+ dx url_with_base_replaced
+
+ dx url_with_comma",
+ expected_statements = r#"
+ pattern:debugger_visualizer-.*\.exe \(embedded NatVis ".*-[0-9]+\.natvis"\)
+
+ base_url : "http://example.org/foo/bar" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "http"
+ [host] : "example.org"
+ [path] : "/foo/bar"
+
+ url_with_non_special_scheme : "non-special://test/x" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "non-special"
+ [host] : "test"
+ [path] : "/x"
+
+ url_with_user_pass_port_query_fragments : "http://user:pass@foo:21/bar;par?b#c" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "http"
+ [username] : "user"
+ [host] : "foo"
+ [port] : 21
+ [path] : "/bar;par"
+ [query] : "b"
+ [fragment] : "c"
+
+ url_blob : "blob:https://example.com:443/" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "blob"
+ [path] : "https://example.com:443/"
+
+ url_with_base : "http://example.org/a%2fc" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "http"
+ [host] : "example.org"
+ [path] : "/a%2fc"
+
+ url_with_base_replaced : "http://[::7f00:1]/" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "http"
+ [host] : "[::7f00:1]"
+ [path] : "/"
+
+ url_with_comma : "data:text/html,test#test" [Type: url::Url]
+ [<Raw View>] [Type: url::Url]
+ [scheme] : "data"
+ [path] : "text/html,test"
+ [fragment] : "test"
+ "#
+)]
+fn test_url_visualizer() {
+ // Copied from https://github.com/web-platform-tests/wpt/blob/master/url/
+ let base_url = Url::parse("http://example.org/foo/bar").unwrap();
+ assert_eq!(base_url.as_str(), "http://example.org/foo/bar");
+
+ let url_with_non_special_scheme = Url::parse("non-special://:@test/x").unwrap();
+ assert_eq!(url_with_non_special_scheme.as_str(), "non-special://test/x");
+
+ let url_with_user_pass_port_query_fragments =
+ Url::parse("http://user:pass@foo:21/bar;par?b#c").unwrap();
+ assert_eq!(
+ url_with_user_pass_port_query_fragments.as_str(),
+ "http://user:pass@foo:21/bar;par?b#c"
+ );
+
+ let url_blob = Url::parse("blob:https://example.com:443/").unwrap();
+ assert_eq!(url_blob.as_str(), "blob:https://example.com:443/");
+
+ let url_with_base = base_url.join("/a%2fc").unwrap();
+ assert_eq!(url_with_base.as_str(), "http://example.org/a%2fc");
+
+ let url_with_base_replaced = base_url.join("http://[::127.0.0.1]").unwrap();
+ assert_eq!(url_with_base_replaced.as_str(), "http://[::7f00:1]/");
+
+ let url_with_comma = base_url.join("data:text/html,test#test").unwrap();
+ assert_eq!(url_with_comma.as_str(), "data:text/html,test#test");
+
+ __break();
+}
diff --git a/vendor/url/tests/unit.rs b/vendor/url/tests/unit.rs
index 13055a473..55ff59ada 100644
--- a/vendor/url/tests/unit.rs
+++ b/vendor/url/tests/unit.rs
@@ -43,6 +43,14 @@ fn test_set_empty_host() {
assert_eq!(base.as_str(), "moz:/baz");
base.set_host(Some("servo")).unwrap();
assert_eq!(base.as_str(), "moz://servo/baz");
+
+ let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
+ base.set_host(None).unwrap();
+ assert_eq!(base.as_str(), "file:///share/foo/bar");
+
+ let mut base: Url = "file://server/share/foo/bar".parse().unwrap();
+ base.set_host(Some("foo")).unwrap();
+ assert_eq!(base.as_str(), "file://foo/share/foo/bar");
}
#[test]
@@ -256,7 +264,6 @@ fn host() {
0x2001, 0x0db8, 0x85a3, 0x08d3, 0x1319, 0x8a2e, 0x0370, 0x7344,
)),
);
- assert_host("http://1.35.+33.49", Host::Domain("1.35.+33.49"));
assert_host(
"http://[::]",
Host::Ipv6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)),
@@ -271,7 +278,8 @@ fn host() {
);
assert_host("http://0x1232131", Host::Ipv4(Ipv4Addr::new(1, 35, 33, 49)));
assert_host("http://111", Host::Ipv4(Ipv4Addr::new(0, 0, 0, 111)));
- assert_host("http://2..2.3", Host::Domain("2..2.3"));
+ assert!(Url::parse("http://1.35.+33.49").is_err());
+ assert!(Url::parse("http://2..2.3").is_err());
assert!(Url::parse("http://42.0x1232131").is_err());
assert!(Url::parse("http://192.168.0.257").is_err());
@@ -720,6 +728,34 @@ fn test_domain_encoding_quirks() {
}
}
+#[cfg(feature = "expose_internals")]
+#[test]
+fn test_expose_internals() {
+ use url::quirks::internal_components;
+ use url::quirks::InternalComponents;
+
+ let url = Url::parse("https://example.com/path/file.ext?key=val&key2=val2#fragment").unwrap();
+ let InternalComponents {
+ scheme_end,
+ username_end,
+ host_start,
+ host_end,
+ port,
+ path_start,
+ query_start,
+ fragment_start,
+ } = internal_components(&url);
+
+ assert_eq!(scheme_end, 5);
+ assert_eq!(username_end, 8);
+ assert_eq!(host_start, 8);
+ assert_eq!(host_end, 19);
+ assert_eq!(port, None);
+ assert_eq!(path_start, 19);
+ assert_eq!(query_start, Some(33));
+ assert_eq!(fragment_start, Some(51));
+}
+
#[test]
fn test_windows_unc_path() {
if !cfg!(windows) {
@@ -796,7 +832,7 @@ fn test_syntax_violation_callback_types() {
("file:/foo.txt", ExpectedFileDoubleSlash, "expected // after file:"),
("file://mozilla.org/c:/file.txt", FileWithHostAndWindowsDrive, "file: with host and Windows drive letter"),
("http://mozilla.org/^", NonUrlCodePoint, "non-URL code point"),
- ("http://mozilla.org/#\00", NullInFragment, "NULL characters are ignored in URL fragment identifiers"),
+ ("http://mozilla.org/#\x000", NullInFragment, "NULL characters are ignored in URL fragment identifiers"),
("http://mozilla.org/%1", PercentDecode, "expected 2 hex digits after %"),
("http://mozilla.org\t/foo", TabOrNewlineIgnored, "tabs or newlines are ignored in URLs"),
("http://user@:pass@mozilla.org", UnencodedAtSign, "unencoded @ sign in username or password")
@@ -1081,6 +1117,16 @@ fn test_make_relative() {
"http://127.0.0.1:8080/test/video?baz=meh#456",
"video?baz=meh#456",
),
+ (
+ "http://127.0.0.1:8080/file.txt",
+ "http://127.0.0.1:8080/test/file.txt",
+ "test/file.txt",
+ ),
+ (
+ "http://127.0.0.1:8080/not_equal.txt",
+ "http://127.0.0.1:8080/test/file.txt",
+ "test/file.txt",
+ ),
];
for (base, uri, relative) in &tests {
@@ -1093,7 +1139,7 @@ fn test_make_relative() {
base, uri, relative
);
assert_eq!(
- base_uri.join(&relative).unwrap().as_str(),
+ base_uri.join(relative).unwrap().as_str(),
*uri,
"base: {}, uri: {}, relative: {}",
base,
diff --git a/vendor/url/tests/urltestdata.json b/vendor/url/tests/urltestdata.json
index 554e61914..4265f5928 100644
--- a/vendor/url/tests/urltestdata.json
+++ b/vendor/url/tests/urltestdata.json
@@ -1,6 +1,6 @@
[
"# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js",
- "# AS OF https://github.com/jsdom/whatwg-url/commit/35f04dfd3048cf6362f4398745bb13375c5020c2",
+ "# AS OF https://github.com/web-platform-tests/wpt/commit/2a64dae4641fbd61bd4257df460e188f425b492e",
{
"input": "http://example\t.\norg",
"base": "http://example.org/foo/bar",
@@ -541,6 +541,36 @@
"hash": ""
},
{
+ "input": "\\x",
+ "base": "http://example.org/foo/bar",
+ "href": "http://example.org/x",
+ "origin": "http://example.org",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "example.org",
+ "hostname": "example.org",
+ "port": "",
+ "pathname": "/x",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "\\\\x\\hello",
+ "base": "http://example.org/foo/bar",
+ "href": "http://x/hello",
+ "origin": "http://x",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "x",
+ "hostname": "x",
+ "port": "",
+ "pathname": "/hello",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "::",
"base": "http://example.org/foo/bar",
"href": "http://example.org/foo/::",
@@ -3157,7 +3187,8 @@
{
"input": "http:/:@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http://user@/www.example.com",
@@ -3167,12 +3198,14 @@
{
"input": "http:@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http:/@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http://@/www.example.com",
@@ -3182,17 +3215,20 @@
{
"input": "https:@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http:a:b@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http:/a:b@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http://a:b@/www.example.com",
@@ -3202,7 +3238,8 @@
{
"input": "http::@/www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http:a:@www.example.com",
@@ -3267,12 +3304,14 @@
{
"input": "http:@:www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http:/@:www.example.com",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "http://@:www.example.com",
@@ -3646,6 +3685,38 @@
"search": "?%EF%BF%BD",
"hash": "#%EF%BF%BD"
},
+ "Domain is ASCII, but a label is invalid IDNA",
+ {
+ "input": "http://a.b.c.xn--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://10.0.0.xn--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
+ "IDNA labels should be matched case-insensitively",
+ {
+ "input": "http://a.b.c.XN--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a.b.c.Xn--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://10.0.0.XN--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://10.0.0.xN--pokxncvks",
+ "base": "about:blank",
+ "failure": true
+ },
"Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.",
{
"input": "http://Go.com",
@@ -3847,21 +3918,6 @@
"search": "",
"hash": ""
},
- {
- "input": "http://0..0x300/",
- "base": "about:blank",
- "href": "http://0..0x300/",
- "origin": "http://0..0x300",
- "protocol": "http:",
- "username": "",
- "password": "",
- "host": "0..0x300",
- "hostname": "0..0x300",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
"Broken IPv6",
{
"input": "http://[www.google.com]/",
@@ -4483,16 +4539,6 @@
"hash": ""
},
{
- "input": "sc://\u0000/",
- "base": "about:blank",
- "failure": true
- },
- {
- "input": "sc:// /",
- "base": "about:blank",
- "failure": true
- },
- {
"input": "sc://%/",
"base": "about:blank",
"href": "sc://%/",
@@ -4527,21 +4573,6 @@
"failure": true
},
{
- "input": "sc://[/",
- "base": "about:blank",
- "failure": true
- },
- {
- "input": "sc://\\/",
- "base": "about:blank",
- "failure": true
- },
- {
- "input": "sc://]/",
- "base": "about:blank",
- "failure": true
- },
- {
"input": "x",
"base": "sc://ñ",
"href": "sc://%C3%B1/x",
@@ -4619,7 +4650,7 @@
"search": "",
"hash": ""
},
- "# unknown scheme with non-URL characters in the path",
+ "# unknown scheme with non-URL characters",
{
"input": "wow:\uFFFF",
"base": "about:blank",
@@ -4637,6 +4668,250 @@
},
"Forbidden host code points",
{
+ "input": "sc://a\u0000b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a<b",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a>b",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a[b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a\\b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a]b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a^b",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "sc://a|b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ "Forbidden host codepoints: tabs and newlines are removed during preprocessing",
+ {
+ "input": "foo://ho\u0009st/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"foo://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "foo://ho\u000Ast/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"foo://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "foo://ho\u000Dst/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"foo://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ "Forbidden domain code-points",
+ {
+ "input": "http://a\u0000b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0001b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0002b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0003b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0004b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0005b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0006b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0007b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0008b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u000Bb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u000Cb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u000Eb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u000Fb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0010b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0011b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0012b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0013b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0014b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0015b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0016b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0017b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0018b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u0019b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Ab/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Bb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Cb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Db/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Eb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u001Fb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a%b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
"input": "http://a<b",
"base": "about:blank",
"failure": true
@@ -4647,51 +4922,330 @@
"failure": true
},
{
+ "input": "http://a[b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a]b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
"input": "http://a^b",
"base": "about:blank",
"failure": true
},
{
- "input": "non-special://a<b",
+ "input": "http://a|b/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://a\u007Fb/",
+ "base": "about:blank",
+ "failure": true
+ },
+ "Forbidden domain codepoints: tabs and newlines are removed during preprocessing",
+ {
+ "input": "http://ho\u0009st/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"http://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "http:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "http://ho\u000Ast/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"http://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "http:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "http://ho\u000Dst/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href":"http://host/",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "http:",
+ "search": "",
+ "username": ""
+ },
+ "Encoded forbidden domain codepoints in special URLs",
+ {
+ "input": "http://ho%00st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%01st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%02st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%03st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%04st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%05st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%06st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%07st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%08st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%09st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Ast/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Bst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Cst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Dst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Est/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%0Fst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%10st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%11st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%12st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%13st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%14st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%15st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%16st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%17st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%18st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%19st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Ast/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Bst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Cst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Dst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Est/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%1Fst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%20st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%23st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%25st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%2Fst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%3Ast/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%3Cst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%3Est/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%3Fst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%40st/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%5Bst/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://ho%5Cst/",
"base": "about:blank",
"failure": true
},
{
- "input": "non-special://a>b",
+ "input": "http://ho%5Dst/",
"base": "about:blank",
"failure": true
},
{
- "input": "non-special://a^b",
+ "input": "http://ho%7Cst/",
"base": "about:blank",
"failure": true
},
- "Allowed host code points",
{
- "input": "http://\u001F!\"$&'()*+,-.;=_`{|}~/",
+ "input": "http://ho%7Fst/",
"base": "about:blank",
- "href": "http://\u001F!\"$&'()*+,-.;=_`{|}~/",
- "origin": "http://\u001F!\"$&'()*+,-.;=_`{|}~",
+ "failure": true
+ },
+ "Allowed host/domain code points",
+ {
+ "input": "http://!\"$&'()*+,-.;=_`{}~/",
+ "base": "about:blank",
+ "href": "http://!\"$&'()*+,-.;=_`{}~/",
+ "origin": "http://!\"$&'()*+,-.;=_`{}~",
"protocol": "http:",
"username": "",
"password": "",
- "host": "\u001F!\"$&'()*+,-.;=_`{|}~",
- "hostname": "\u001F!\"$&'()*+,-.;=_`{|}~",
+ "host": "!\"$&'()*+,-.;=_`{}~",
+ "hostname": "!\"$&'()*+,-.;=_`{}~",
"port": "",
"pathname": "/",
"search": "",
"hash": ""
},
{
- "input": "sc://\u001F!\"$&'()*+,-.;=_`{|}~/",
+ "input": "sc://\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u000B\u000C\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F\u007F!\"$%&'()*+,-.;=_`{}~/",
"base": "about:blank",
- "href": "sc://%1F!\"$&'()*+,-.;=_`{|}~/",
+ "href": "sc://%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~/",
"origin": "null",
"protocol": "sc:",
"username": "",
"password": "",
- "host": "%1F!\"$&'()*+,-.;=_`{|}~",
- "hostname": "%1F!\"$&'()*+,-.;=_`{|}~",
+ "host": "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~",
+ "hostname": "%01%02%03%04%05%06%07%08%0B%0C%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%7F!\"$%&'()*+,-.;=_`{}~",
"port": "",
"pathname": "/",
"search": "",
@@ -4964,6 +5518,36 @@
},
"# IPv4 parsing (via https://github.com/nodejs/node/pull/10317)",
{
+ "input": "http://1.2.3.4/",
+ "base": "http://other.com/",
+ "href": "http://1.2.3.4/",
+ "origin": "http://1.2.3.4",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "1.2.3.4",
+ "hostname": "1.2.3.4",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "http://1.2.3.4./",
+ "base": "http://other.com/",
+ "href": "http://1.2.3.4/",
+ "origin": "http://1.2.3.4",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "1.2.3.4",
+ "hostname": "1.2.3.4",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "http://192.168.257",
"base": "http://other.com/",
"href": "http://192.168.1.1/",
@@ -4979,6 +5563,21 @@
"hash": ""
},
{
+ "input": "http://192.168.257.",
+ "base": "http://other.com/",
+ "href": "http://192.168.1.1/",
+ "origin": "http://192.168.1.1",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "192.168.1.1",
+ "hostname": "192.168.1.1",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "http://192.168.257.com",
"base": "http://other.com/",
"href": "http://192.168.257.com/",
@@ -5039,6 +5638,21 @@
"hash": ""
},
{
+ "input": "http://999999999.",
+ "base": "http://other.com/",
+ "href": "http://59.154.201.255/",
+ "origin": "http://59.154.201.255",
+ "protocol": "http:",
+ "username": "",
+ "password": "",
+ "host": "59.154.201.255",
+ "hostname": "59.154.201.255",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "http://999999999.com",
"base": "http://other.com/",
"href": "http://999999999.com/",
@@ -5119,21 +5733,6 @@
"failure": true
},
{
- "input": "http://256.256.256.256.256",
- "base": "http://other.com/",
- "href": "http://256.256.256.256.256/",
- "origin": "http://256.256.256.256.256",
- "protocol": "http:",
- "username": "",
- "password": "",
- "host": "256.256.256.256.256",
- "hostname": "256.256.256.256.256",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
"input": "https://0x.0x.0",
"base": "about:blank",
"href": "https://0.0.0.0/",
@@ -5188,6 +5787,56 @@
"search": "",
"hash": ""
},
+ {
+ "input": "file://%43%3A",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://%43%7C",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://%43|",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://C%7C",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "file://%43%7C/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "https://%43%7C/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "asdf://%43|/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "asdf://%43%7C/",
+ "base": "about:blank",
+ "href": "asdf://%43%7C/",
+ "origin": "null",
+ "protocol": "asdf:",
+ "username": "",
+ "password": "",
+ "host": "%43%7C",
+ "hostname": "%43%7C",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
"# file URLs relative to other file URLs (via https://github.com/jsdom/whatwg-url/pull/60)",
{
"input": "pix/submit.gif",
@@ -5247,6 +5896,20 @@
"hash": ""
},
{
+ "input": "/",
+ "base": "file://h/a/b",
+ "href": "file://h/",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "h",
+ "hostname": "h",
+ "port": "",
+ "pathname": "/",
+ "search": "",
+ "hash": ""
+ },
+ {
"input": "//d:",
"base": "file:///C:/a/b",
"href": "file:///d:",
@@ -5388,90 +6051,6 @@
},
"# File URLs and many (back)slashes",
{
- "input": "file:\\\\//",
- "base": "about:blank",
- "href": "file:///",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
- "input": "file:\\\\\\\\",
- "base": "about:blank",
- "href": "file:///",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
- "input": "file:\\\\\\\\?fox",
- "base": "about:blank",
- "href": "file:///?fox",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "?fox",
- "hash": ""
- },
- {
- "input": "file:\\\\\\\\#guppy",
- "base": "about:blank",
- "href": "file:///#guppy",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": "#guppy"
- },
- {
- "input": "file://spider///",
- "base": "about:blank",
- "href": "file://spider/",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "spider",
- "hostname": "spider",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
- "input": "file:\\\\localhost//",
- "base": "about:blank",
- "href": "file:///",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
"input": "file:///localhost//cat",
"base": "about:blank",
"href": "file:///localhost//cat",
@@ -5486,48 +6065,6 @@
"hash": ""
},
{
- "input": "file://\\/localhost//cat",
- "base": "about:blank",
- "href": "file:///localhost//cat",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/localhost//cat",
- "search": "",
- "hash": ""
- },
- {
- "input": "file://localhost//a//../..//",
- "base": "about:blank",
- "href": "file:///",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/",
- "search": "",
- "hash": ""
- },
- {
- "input": "/////mouse",
- "base": "file:///elephant",
- "href": "file:///mouse",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/mouse",
- "search": "",
- "hash": ""
- },
- {
"input": "\\//pig",
"base": "file://lion/",
"href": "file:///pig",
@@ -5542,48 +6079,6 @@
"hash": ""
},
{
- "input": "\\/localhost//pig",
- "base": "file://lion/",
- "href": "file:///pig",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/pig",
- "search": "",
- "hash": ""
- },
- {
- "input": "//localhost//pig",
- "base": "file://lion/",
- "href": "file:///pig",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/pig",
- "search": "",
- "hash": ""
- },
- {
- "input": "/..//localhost//pig",
- "base": "file://lion/",
- "href": "file://lion/localhost//pig",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "lion",
- "hostname": "lion",
- "port": "",
- "pathname": "/localhost//pig",
- "search": "",
- "hash": ""
- },
- {
"input": "file://",
"base": "file://ape/",
"href": "file:///",
@@ -5628,90 +6123,6 @@
},
"# Windows drive letter handling with the 'file:' base URL",
{
- "input": "C|",
- "base": "file://host/dir/file",
- "href": "file:///C:",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:",
- "search": "",
- "hash": ""
- },
- {
- "input": "C|#",
- "base": "file://host/dir/file",
- "href": "file:///C:#",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:",
- "search": "",
- "hash": ""
- },
- {
- "input": "C|?",
- "base": "file://host/dir/file",
- "href": "file:///C:?",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:",
- "search": "",
- "hash": ""
- },
- {
- "input": "C|/",
- "base": "file://host/dir/file",
- "href": "file:///C:/",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:/",
- "search": "",
- "hash": ""
- },
- {
- "input": "C|\n/",
- "base": "file://host/dir/file",
- "href": "file:///C:/",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:/",
- "search": "",
- "hash": ""
- },
- {
- "input": "C|\\",
- "base": "file://host/dir/file",
- "href": "file:///C:/",
- "protocol": "file:",
- "username": "",
- "password": "",
- "host": "",
- "hostname": "",
- "port": "",
- "pathname": "/C:/",
- "search": "",
- "hash": ""
- },
- {
"input": "C",
"base": "file://host/dir/file",
"href": "file://host/dir/C",
@@ -5782,24 +6193,24 @@
"search": "",
"hash": ""
},
+ "# Copy the empty host from the input in the following cases",
{
- "input": "/c:/foo/bar",
- "base": "file://host/path",
- "href": "file:///c:/foo/bar",
+ "input": "//C:/",
+ "base": "file://host/",
+ "href": "file:///C:/",
"protocol": "file:",
"username": "",
"password": "",
"host": "",
"hostname": "",
"port": "",
- "pathname": "/c:/foo/bar",
+ "pathname": "/C:/",
"search": "",
"hash": ""
},
- "# Windows drive letter quirk with not empty host",
{
- "input": "file://example.net/C:/",
- "base": "about:blank",
+ "input": "file://C:/",
+ "base": "file://host/",
"href": "file:///C:/",
"protocol": "file:",
"username": "",
@@ -5812,8 +6223,8 @@
"hash": ""
},
{
- "input": "file://1.2.3.4/C:/",
- "base": "about:blank",
+ "input": "///C:/",
+ "base": "file://host/",
"href": "file:///C:/",
"protocol": "file:",
"username": "",
@@ -5826,8 +6237,8 @@
"hash": ""
},
{
- "input": "file://[1::8]/C:/",
- "base": "about:blank",
+ "input": "file:///C:/",
+ "base": "file://host/",
"href": "file:///C:/",
"protocol": "file:",
"username": "",
@@ -5971,7 +6382,8 @@
{
"input": "\\\\\\.\\Y:",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
"# file: drive letter cases from https://crbug.com/1078698 but lowercased",
{
@@ -6033,7 +6445,51 @@
{
"input": "\\\\\\.\\y:",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
+ },
+ "# Additional file URL tests for (https://github.com/whatwg/url/issues/405)",
+ {
+ "input": "file:///one/two",
+ "base": "file:///",
+ "href": "file:///one/two",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/one/two",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "//one/two",
+ "base": "file:///",
+ "href": "file://one/two",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "one",
+ "hostname": "one",
+ "port": "",
+ "pathname": "/two",
+ "search": "",
+ "hash": ""
+ },
+ {
+ "input": "///one/two",
+ "base": "file:///",
+ "href": "file:///one/two",
+ "protocol": "file:",
+ "username": "",
+ "password": "",
+ "host": "",
+ "hostname": "",
+ "port": "",
+ "pathname": "/one/two",
+ "search": "",
+ "hash": ""
},
"# IPv6 tests",
{
@@ -6527,6 +6983,7 @@
"input": "blob:https://example.com:443/",
"base": "about:blank",
"href": "blob:https://example.com:443/",
+ "origin": "https://example.com",
"protocol": "blob:",
"username": "",
"password": "",
@@ -6541,6 +6998,7 @@
"input": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
"base": "about:blank",
"href": "blob:d3958f5c-0777-0845-9dcf-2cb28783acaf",
+ "origin": "null",
"protocol": "blob:",
"username": "",
"password": "",
@@ -6551,21 +7009,22 @@
"search": "",
"hash": ""
},
- "Invalid IPv4 radix digits",
{
- "input": "http://0177.0.0.0189",
+ "input": "blob:",
"base": "about:blank",
- "href": "http://0177.0.0.0189/",
- "protocol": "http:",
+ "href": "blob:",
+ "origin": "null",
+ "protocol": "blob:",
"username": "",
"password": "",
- "host": "0177.0.0.0189",
- "hostname": "0177.0.0.0189",
+ "host": "",
+ "hostname": "",
"port": "",
- "pathname": "/",
+ "pathname": "",
"search": "",
"hash": ""
},
+ "Invalid IPv4 radix digits",
{
"input": "http://0x7f.0.0.0x7g",
"base": "about:blank",
@@ -6760,17 +7219,20 @@
{
"input": "a",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "a/",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
{
"input": "a//",
"base": "about:blank",
- "failure": true
+ "failure": true,
+ "inputCanBeRelative": true
},
"Bases that don't fail to parse but fail to be bases",
{
@@ -6987,5 +7449,460 @@
"pathname": "/",
"search": "",
"hash": "#link"
+ },
+ "UTF-8 percent-encode of C0 control percent-encode set and supersets",
+ {
+ "input": "non-special:cannot-be-a-base-url-\u0000\u0001\u001F\u001E\u007E\u007F\u0080",
+ "base": "about:blank",
+ "hash": "",
+ "host": "",
+ "hostname": "",
+ "href": "non-special:cannot-be-a-base-url-%00%01%1F%1E~%7F%C2%80",
+ "origin": "null",
+ "password": "",
+ "pathname": "cannot-be-a-base-url-%00%01%1F%1E~%7F%C2%80",
+ "port": "",
+ "protocol": "non-special:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "https://www.example.com/path{\u007Fpath.html?query'\u007F=query#fragment<\u007Ffragment",
+ "base": "about:blank",
+ "hash": "#fragment%3C%7Ffragment",
+ "host": "www.example.com",
+ "hostname": "www.example.com",
+ "href": "https://www.example.com/path%7B%7Fpath.html?query%27%7F=query#fragment%3C%7Ffragment",
+ "origin": "https://www.example.com",
+ "password": "",
+ "pathname": "/path%7B%7Fpath.html",
+ "port": "",
+ "protocol": "https:",
+ "search": "?query%27%7F=query",
+ "username": ""
+ },
+ {
+ "input": "https://user:pass[\u007F@foo/bar",
+ "base": "http://example.org",
+ "hash": "",
+ "host": "foo",
+ "hostname": "foo",
+ "href": "https://user:pass%5B%7F@foo/bar",
+ "origin": "https://foo",
+ "password": "pass%5B%7F",
+ "pathname": "/bar",
+ "port": "",
+ "protocol": "https:",
+ "search": "",
+ "username": "user"
+ },
+ "Tests for the distinct percent-encode sets",
+ {
+ "input": "foo:// !\"$%&'()*+,-.;<=>@[\\]^_`{|}~@host/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "foo://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/",
+ "origin": "null",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": "%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~"
+ },
+ {
+ "input": "wss:// !\"$%&'()*+,-.;<=>@[]^_`{|}~@host/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "wss://%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/",
+ "origin": "wss://host",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "wss:",
+ "search": "",
+ "username": "%20!%22$%&'()*+,-.%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~"
+ },
+ {
+ "input": "foo://joe: !\"$%&'()*+,-.:;<=>@[\\]^_`{|}~@host/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "foo://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~@host/",
+ "origin": "null",
+ "password": "%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5C%5D%5E_%60%7B%7C%7D~",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": "joe"
+ },
+ {
+ "input": "wss://joe: !\"$%&'()*+,-.:;<=>@[]^_`{|}~@host/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "wss://joe:%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~@host/",
+ "origin": "wss://host",
+ "password": "%20!%22$%&'()*+,-.%3A%3B%3C%3D%3E%40%5B%5D%5E_%60%7B%7C%7D~",
+ "pathname": "/",
+ "port":"",
+ "protocol": "wss:",
+ "search": "",
+ "username": "joe"
+ },
+ {
+ "input": "foo://!\"$%&'()*+,-.;=_`{}~/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "!\"$%&'()*+,-.;=_`{}~",
+ "hostname": "!\"$%&'()*+,-.;=_`{}~",
+ "href":"foo://!\"$%&'()*+,-.;=_`{}~/",
+ "origin": "null",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "wss://!\"$&'()*+,-.;=_`{}~/",
+ "base": "about:blank",
+ "hash": "",
+ "host": "!\"$&'()*+,-.;=_`{}~",
+ "hostname": "!\"$&'()*+,-.;=_`{}~",
+ "href":"wss://!\"$&'()*+,-.;=_`{}~/",
+ "origin": "wss://!\"$&'()*+,-.;=_`{}~",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "wss:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "foo://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "foo://host/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~",
+ "origin": "null",
+ "password": "",
+ "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[\\]^_%60%7B|%7D~",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "wss://host/ !\"$%&'()*+,-./:;<=>@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "wss://host/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~",
+ "origin": "wss://host",
+ "password": "",
+ "pathname": "/%20!%22$%&'()*+,-./:;%3C=%3E@[/]^_%60%7B|%7D~",
+ "port":"",
+ "protocol": "wss:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "foo://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "foo://host/dir/?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~",
+ "origin": "null",
+ "password": "",
+ "pathname": "/dir/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "?%20!%22$%&'()*+,-./:;%3C=%3E?@[\\]^_`{|}~",
+ "username": ""
+ },
+ {
+ "input": "wss://host/dir/? !\"$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "",
+ "host": "host",
+ "hostname": "host",
+ "href": "wss://host/dir/?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~",
+ "origin": "wss://host",
+ "password": "",
+ "pathname": "/dir/",
+ "port":"",
+ "protocol": "wss:",
+ "search": "?%20!%22$%&%27()*+,-./:;%3C=%3E?@[\\]^_`{|}~",
+ "username": ""
+ },
+ {
+ "input": "foo://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
+ "host": "host",
+ "hostname": "host",
+ "href": "foo://host/dir/#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
+ "origin": "null",
+ "password": "",
+ "pathname": "/dir/",
+ "port":"",
+ "protocol": "foo:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "wss://host/dir/# !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
+ "base": "about:blank",
+ "hash": "#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
+ "host": "host",
+ "hostname": "host",
+ "href": "wss://host/dir/#%20!%22#$%&'()*+,-./:;%3C=%3E?@[\\]^_%60{|}~",
+ "origin": "wss://host",
+ "password": "",
+ "pathname": "/dir/",
+ "port":"",
+ "protocol": "wss:",
+ "search": "",
+ "username": ""
+ },
+ "Ensure that input schemes are not ignored when resolving non-special URLs",
+ {
+ "input": "abc:rootless",
+ "base": "abc://host/path",
+ "hash": "",
+ "host": "",
+ "hostname": "",
+ "href":"abc:rootless",
+ "password": "",
+ "pathname": "rootless",
+ "port":"",
+ "protocol": "abc:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "abc:rootless",
+ "base": "abc:/path",
+ "hash": "",
+ "host": "",
+ "hostname": "",
+ "href":"abc:rootless",
+ "password": "",
+ "pathname": "rootless",
+ "port":"",
+ "protocol": "abc:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "abc:rootless",
+ "base": "abc:path",
+ "hash": "",
+ "host": "",
+ "hostname": "",
+ "href":"abc:rootless",
+ "password": "",
+ "pathname": "rootless",
+ "port":"",
+ "protocol": "abc:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "abc:/rooted",
+ "base": "abc://host/path",
+ "hash": "",
+ "host": "",
+ "hostname": "",
+ "href":"abc:/rooted",
+ "password": "",
+ "pathname": "/rooted",
+ "port":"",
+ "protocol": "abc:",
+ "search": "",
+ "username": ""
+ },
+ "Empty query and fragment with blank should throw an error",
+ {
+ "input": "#",
+ "base": null,
+ "failure": true
+ },
+ {
+ "input": "?",
+ "base": null,
+ "failure": true
+ },
+ "Last component looks like a number, but not valid IPv4",
+ {
+ "input": "http://1.2.3.4.5",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://1.2.3.4.5.",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://0..0x300/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://0..0x300./",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://256.256.256.256.256",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://256.256.256.256.256.",
+ "base": "http://other.com/",
+ "failure": true
+ },
+ {
+ "input": "http://1.2.3.08",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://1.2.3.08.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://1.2.3.09",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://09.2.3.4",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://09.2.3.4.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://01.2.3.4.5",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://01.2.3.4.5.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://0x100.2.3.4",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://0x100.2.3.4.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://0x1.2.3.4.5",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://0x1.2.3.4.5.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.1.2.3.4",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.1.2.3.4.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.2.3.4",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.2.3.4.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.09",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.09.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.0x4",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.0x4.",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.09..",
+ "base": "about:blank",
+ "hash": "",
+ "host": "foo.09..",
+ "hostname": "foo.09..",
+ "href":"http://foo.09../",
+ "password": "",
+ "pathname": "/",
+ "port":"",
+ "protocol": "http:",
+ "search": "",
+ "username": ""
+ },
+ {
+ "input": "http://0999999999999999999/",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.0x",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://foo.0XFfFfFfFfFfFfFfFfFfAcE123",
+ "base": "about:blank",
+ "failure": true
+ },
+ {
+ "input": "http://💩.123/",
+ "base": "about:blank",
+ "failure": true
}
]
diff --git a/vendor/xflags-macros/.cargo-checksum.json b/vendor/xflags-macros/.cargo-checksum.json
index 98f5dfe97..fcc17d504 100644
--- a/vendor/xflags-macros/.cargo-checksum.json
+++ b/vendor/xflags-macros/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"23f3d89d0198bfa3552286396432e2ace70627773527eaaf62ed4d3ef1b37166","src/ast.rs":"bf42c4e474893d5dbd4fa3c9b392d3f837219fabb2042cfc26acc08b2ddc6f4a","src/emit.rs":"390be2d24bc21d5644c9c69624fd263bfa7dc0f3081799481177a45952168d51","src/lib.rs":"f00a5c9e671a82263d4cf4cced2895bb93ae03220112bc385553573cf9c4cd05","src/parse.rs":"2c2c9118d1f0447a946a78753edb65edd6eeb4f2a27707f5601232c8880aba85","src/update.rs":"feb2cefca834dad6550b6539be7ec9b98fedb608cd09aeddf808350c638d67b8","tests/it/help.rs":"53dbb8b5c6e09649143dc8f9e5cd690db776271a1ea778726146fc04be8583f4","tests/it/main.rs":"3cde1afb05f2470642f0f590cbed24fb553bd0ac1da0fcae93a02ffe42247d97","tests/it/repeated_pos.rs":"1b2b922beb182899504cd36440fd1547026a8a5ef4f79b483a2695227f06c4a8","tests/it/smoke.rs":"5d304f8b24716d63081965914bf4bcf9fc8bfccf30d3f49fb9d71e3405917fd2","tests/it/src/help.rs":"7430f8773b5a8dc3607fbadc04d562f015f056062d373897675140e591da4b60","tests/it/src/repeated_pos.rs":"161b39be8e543ef6dd3f019162c85b9e6d22c30dcd6297e947a2872ed1bc3c5f","tests/it/src/smoke.rs":"f17d4ffb6177fc83aa7f0ad235a487a15490a9f646e7789af8a92db4ea9552fe","tests/it/src/subcommands.rs":"1147d1a7de73cb20d5604a3e08ce43b32a89dbb9ee37aa8c595f6138a083abb9","tests/it/subcommands.rs":"dab409a1b14755122ea42a3169d4a020ce1e548e52a56211874efeb73551de08"},"package":"45d11d5fc2a97287eded8b170ca80533b3c42646dd7fa386a5eb045817921022"} \ No newline at end of file
+{"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
diff --git a/vendor/xflags-macros/Cargo.toml b/vendor/xflags-macros/Cargo.toml
index a224e51a6..70b748f0a 100644
--- a/vendor/xflags-macros/Cargo.toml
+++ b/vendor/xflags-macros/Cargo.toml
@@ -10,16 +10,18 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
name = "xflags-macros"
-version = "0.2.4"
+version = "0.3.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
description = "Private implementation details of xflags."
license = "MIT OR Apache-2.0"
repository = "https://github.com/matklad/xflags"
+resolver = "1"
[lib]
proc-macro = true
+
[dev-dependencies.expect-test]
version = "1"
diff --git a/vendor/xflags-macros/src/ast.rs b/vendor/xflags-macros/src/ast.rs
index 5ccebd951..7fb9df1e1 100644
--- a/vendor/xflags-macros/src/ast.rs
+++ b/vendor/xflags-macros/src/ast.rs
@@ -4,6 +4,12 @@ pub(crate) struct XFlags {
pub(crate) cmd: Cmd,
}
+impl XFlags {
+ pub fn is_anon(&self) -> bool {
+ self.cmd.name.is_empty()
+ }
+}
+
#[derive(Debug)]
pub(crate) struct Cmd {
pub(crate) name: String,
@@ -12,6 +18,7 @@ pub(crate) struct Cmd {
pub(crate) flags: Vec<Flag>,
pub(crate) subcommands: Vec<Cmd>,
pub(crate) default: bool,
+ pub(crate) idx: u8,
}
#[derive(Debug)]
@@ -30,6 +37,12 @@ pub(crate) struct Flag {
pub(crate) val: Option<Val>,
}
+impl Flag {
+ pub(crate) fn is_help(&self) -> bool {
+ self.name == "help"
+ }
+}
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Arity {
Optional,
diff --git a/vendor/xflags-macros/src/emit.rs b/vendor/xflags-macros/src/emit.rs
index 05d5f01dd..1f3d88ead 100644
--- a/vendor/xflags-macros/src/emit.rs
+++ b/vendor/xflags-macros/src/emit.rs
@@ -1,15 +1,25 @@
use crate::{ast, update};
-use std::{fmt::Write, path::Path};
+use std::{env, fmt::Write, path::Path};
+
+macro_rules! w {
+ ($($tt:tt)*) => {
+ drop(write!($($tt)*))
+ };
+}
pub(crate) fn emit(xflags: &ast::XFlags) -> String {
let mut buf = String::new();
+ if xflags.is_anon() {
+ w!(buf, "{{\n");
+ }
+
emit_cmd(&mut buf, &xflags.cmd);
blank_line(&mut buf);
emit_api(&mut buf, xflags);
- if std::env::var("UPDATE_XFLAGS").is_ok() {
+ if !xflags.is_anon() && env::var("UPDATE_XFLAGS").is_ok() {
if let Some(src) = &xflags.src {
update::in_place(&buf, Path::new(src.as_str()))
} else {
@@ -22,22 +32,22 @@ pub(crate) fn emit(xflags: &ast::XFlags) -> String {
}
blank_line(&mut buf);
- emit_impls(&mut buf, &xflags);
+ emit_impls(&mut buf, xflags);
emit_help(&mut buf, xflags);
- buf
-}
+ if xflags.is_anon() {
+ w!(buf, "Flags::from_env_or_exit()");
+ w!(buf, "}}\n");
+ }
-macro_rules! w {
- ($($tt:tt)*) => {
- drop(write!($($tt)*))
- };
+ buf
}
fn emit_cmd(buf: &mut String, cmd: &ast::Cmd) {
w!(buf, "#[derive(Debug)]\n");
w!(buf, "pub struct {}", cmd.ident());
- if cmd.args.is_empty() && cmd.flags.is_empty() && cmd.subcommands.is_empty() {
+ let flags = cmd.flags.iter().filter(|it| !it.is_help()).collect::<Vec<_>>();
+ if cmd.args.is_empty() && flags.is_empty() && cmd.subcommands.is_empty() {
w!(buf, ";\n");
return;
}
@@ -45,16 +55,16 @@ fn emit_cmd(buf: &mut String, cmd: &ast::Cmd) {
for arg in &cmd.args {
let ty = gen_arg_ty(arg.arity, &arg.val.ty);
- w!(buf, " pub {}: {},\n", arg.val.ident(), ty);
+ w!(buf, " pub {}: {ty},\n", arg.val.ident());
}
- if !cmd.args.is_empty() && !cmd.flags.is_empty() {
+ if !cmd.args.is_empty() && !flags.is_empty() {
blank_line(buf);
}
- for flag in &cmd.flags {
+ for flag in &flags {
let ty = gen_flag_ty(flag.arity, flag.val.as_ref().map(|it| &it.ty));
- w!(buf, " pub {}: {},\n", flag.ident(), ty);
+ w!(buf, " pub {}: {ty},\n", flag.ident());
}
if cmd.has_subcommands() {
@@ -67,8 +77,8 @@ fn emit_cmd(buf: &mut String, cmd: &ast::Cmd) {
w!(buf, "#[derive(Debug)]\n");
w!(buf, "pub enum {} {{\n", cmd.cmd_enum_ident());
for sub in &cmd.subcommands {
- let name = camel(&sub.name);
- w!(buf, " {}({}),\n", name, name);
+ let name = sub.ident();
+ w!(buf, " {name}({name}),\n");
}
w!(buf, "}}\n");
@@ -104,9 +114,12 @@ fn gen_arg_ty(arity: ast::Arity, ty: &ast::Ty) -> String {
}
fn emit_api(buf: &mut String, xflags: &ast::XFlags) {
- w!(buf, "impl {} {{\n", camel(&xflags.cmd.name));
+ w!(buf, "impl {} {{\n", xflags.cmd.ident());
- w!(buf, " pub const HELP: &'static str = Self::HELP_;\n");
+ w!(buf, " #[allow(dead_code)]\n");
+ w!(buf, " pub fn from_env_or_exit() -> Self {{\n");
+ w!(buf, " Self::from_env_or_exit_()\n");
+ w!(buf, " }}\n");
blank_line(buf);
w!(buf, " #[allow(dead_code)]\n");
@@ -123,7 +136,10 @@ fn emit_api(buf: &mut String, xflags: &ast::XFlags) {
}
fn emit_impls(buf: &mut String, xflags: &ast::XFlags) -> () {
- w!(buf, "impl {} {{\n", camel(&xflags.cmd.name));
+ w!(buf, "impl {} {{\n", xflags.cmd.ident());
+ w!(buf, " fn from_env_or_exit_() -> Self {{\n");
+ w!(buf, " Self::from_env_().unwrap_or_else(|err| err.exit())\n");
+ w!(buf, " }}\n");
w!(buf, " fn from_env_() -> xflags::Result<Self> {{\n");
w!(buf, " let mut p = xflags::rt::Parser::new_from_env();\n");
w!(buf, " Self::parse_(&mut p)\n");
@@ -134,101 +150,115 @@ fn emit_impls(buf: &mut String, xflags: &ast::XFlags) -> () {
w!(buf, " }}\n");
w!(buf, "}}\n");
blank_line(buf);
- emit_impls_rec(buf, &xflags.cmd)
-}
-
-fn emit_impls_rec(buf: &mut String, cmd: &ast::Cmd) -> () {
- emit_impl(buf, cmd);
- for sub in &cmd.subcommands {
- blank_line(buf);
- emit_impls_rec(buf, sub);
- }
+ emit_parse(buf, &xflags.cmd)
}
-fn emit_impl(buf: &mut String, cmd: &ast::Cmd) -> () {
- w!(buf, "impl {} {{\n", camel(&cmd.name));
+fn emit_parse(buf: &mut String, cmd: &ast::Cmd) {
+ w!(buf, "impl {} {{\n", cmd.ident());
w!(buf, "fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {{\n");
+ w!(buf, "#![allow(non_snake_case)]\n");
- for flag in &cmd.flags {
- w!(buf, "let mut {} = Vec::new();\n", flag.ident());
- }
+ let mut prefix = String::new();
+ emit_locals_rec(buf, &mut prefix, cmd);
blank_line(buf);
+ w!(buf, "let mut state_ = 0u8;\n");
+ w!(buf, "while let Some(arg_) = p_.pop_flag() {{\n");
+ w!(buf, "match arg_ {{\n");
+ {
+ w!(buf, "Ok(flag_) => match (state_, flag_.as_str()) {{\n");
+ emit_match_flag_rec(buf, &mut prefix, cmd);
+ w!(buf, "_ => return Err(p_.unexpected_flag(&flag_)),\n");
+ w!(buf, "}}\n");
- if !cmd.args.is_empty() {
- for arg in &cmd.args {
- w!(buf, "let mut {} = (false, Vec::new());\n", arg.val.ident());
- }
- blank_line(buf);
+ w!(buf, "Err(arg_) => match (state_, arg_.to_str().unwrap_or(\"\")) {{\n");
+ emit_match_arg_rec(buf, &mut prefix, cmd);
+ w!(buf, "_ => return Err(p_.unexpected_arg(arg_)),\n");
+ w!(buf, "}}\n");
}
+ w!(buf, "}}\n");
+ w!(buf, "}}\n");
+ emit_default_transitions(buf, cmd);
- if cmd.has_subcommands() {
- w!(buf, "let mut sub_ = None;");
- blank_line(buf);
+ w!(buf, "Ok(");
+ emit_record_rec(buf, &mut prefix, cmd);
+ w!(buf, ")");
+
+ w!(buf, "}}\n");
+ w!(buf, "}}\n");
+}
+
+fn emit_locals_rec(buf: &mut String, prefix: &mut String, cmd: &ast::Cmd) {
+ for flag in &cmd.flags {
+ if !flag.is_help() {
+ w!(buf, "let mut {prefix}{} = Vec::new();\n", flag.ident());
+ }
+ }
+ for arg in &cmd.args {
+ w!(buf, "let mut {prefix}{} = (false, Vec::new());\n", arg.val.ident());
+ }
+ for sub in &cmd.subcommands {
+ let l = sub.push_prefix(prefix);
+ emit_locals_rec(buf, prefix, sub);
+ prefix.truncate(l);
}
+}
- w!(buf, "while let Some(arg_) = p_.pop_flag() {{\n");
- w!(buf, "match arg_ {{\n");
- {
- w!(buf, "Ok(flag_) => match flag_.as_str() {{\n");
- for flag in &cmd.flags {
- w!(buf, "\"--{}\"", flag.name);
- if let Some(short) = &flag.short {
- w!(buf, "| \"-{}\"", short);
- }
- w!(buf, " => {}.push(", flag.ident());
+fn emit_match_flag_rec(buf: &mut String, prefix: &mut String, cmd: &ast::Cmd) {
+ for flag in &cmd.flags {
+ w!(buf, "(");
+ emit_all_ids_rec(buf, cmd);
+ w!(buf, ", \"--{}\"", flag.name);
+ if let Some(short) = &flag.short {
+ w!(buf, "| \"-{short}\"");
+ }
+ w!(buf, ") => ");
+ if flag.is_help() {
+ w!(buf, "return Err(p_.help(Self::HELP_)),");
+ } else {
+ w!(buf, "{prefix}{}.push(", flag.ident());
match &flag.val {
Some(val) => match &val.ty {
ast::Ty::OsString | ast::Ty::PathBuf => {
w!(buf, "p_.next_value(&flag_)?.into()")
}
ast::Ty::FromStr(ty) => {
- w!(buf, "p_.next_value_from_str::<{}>(&flag_)?", ty)
+ w!(buf, "p_.next_value_from_str::<{ty}>(&flag_)?")
}
},
None => w!(buf, "()"),
}
w!(buf, "),");
}
- if cmd.default_subcommand().is_some() {
- w!(buf, "_ => {{ p_.push_back(Ok(flag_)); break; }}");
- } else {
- w!(buf, "_ => return Err(p_.unexpected_flag(&flag_)),");
- }
- w!(buf, "}}\n");
}
- {
- w!(buf, "Err(arg_) => {{\n");
- if cmd.has_subcommands() {
- w!(buf, "match arg_.to_str().unwrap_or(\"\") {{\n");
- for sub in cmd.named_subcommands() {
- w!(buf, "\"{}\" => {{\n", sub.name);
- w!(
- buf,
- "sub_ = Some({}::{}({}::parse_(p_)?));",
- cmd.cmd_enum_ident(),
- sub.ident(),
- sub.ident()
- );
- w!(buf, "break;");
- w!(buf, "}}\n");
- }
- w!(buf, "_ => (),\n");
- w!(buf, "}}\n");
- }
+ if let Some(sub) = cmd.default_subcommand() {
+ w!(buf, "({}, _) => {{ p_.push_back(Ok(flag_)); state_ = {}; }}", cmd.idx, sub.idx);
+ }
+ for sub in &cmd.subcommands {
+ let l = sub.push_prefix(prefix);
+ emit_match_flag_rec(buf, prefix, sub);
+ prefix.truncate(l);
+ }
+}
+fn emit_match_arg_rec(buf: &mut String, prefix: &mut String, cmd: &ast::Cmd) {
+ for sub in cmd.named_subcommands() {
+ w!(buf, "({}, \"{}\") => state_ = {},\n", cmd.idx, sub.name, sub.idx);
+ }
+ if !cmd.args.is_empty() || cmd.has_subcommands() {
+ w!(buf, "({}, _) => {{\n", cmd.idx);
for arg in &cmd.args {
let done = match arg.arity {
ast::Arity::Optional | ast::Arity::Required => "done_ @ ",
ast::Arity::Repeated => "",
};
- w!(buf, "if let ({}false, buf_) = &mut {} {{\n", done, arg.val.ident());
+ w!(buf, "if let ({done}false, buf_) = &mut {prefix}{} {{\n", arg.val.ident());
w!(buf, "buf_.push(");
match &arg.val.ty {
ast::Ty::OsString | ast::Ty::PathBuf => {
w!(buf, "arg_.into()")
}
ast::Ty::FromStr(ty) => {
- w!(buf, "p_.value_from_str::<{}>(\"{}\", arg_)?", ty, arg.val.name);
+ w!(buf, "p_.value_from_str::<{ty}>(\"{}\", arg_)?", arg.val.name);
}
}
w!(buf, ");\n");
@@ -241,79 +271,110 @@ fn emit_impl(buf: &mut String, cmd: &ast::Cmd) -> () {
w!(buf, "continue;\n");
w!(buf, "}}\n");
}
- if cmd.default_subcommand().is_some() {
- w!(buf, "p_.push_back(Err(arg_)); break;");
+
+ if let Some(sub) = cmd.default_subcommand() {
+ w!(buf, "p_.push_back(Err(arg_)); state_ = {};", sub.idx);
} else {
w!(buf, "return Err(p_.unexpected_arg(arg_));");
}
w!(buf, "}}\n");
}
- w!(buf, "}}\n");
- w!(buf, "}}\n");
- if let Some(sub) = cmd.default_subcommand() {
- w!(buf, "if sub_.is_none() {{\n");
- w!(
- buf,
- "sub_ = Some({}::{}({}::parse_(p_)?));",
- cmd.cmd_enum_ident(),
- sub.ident(),
- sub.ident()
- );
- w!(buf, "}}\n");
+ for sub in &cmd.subcommands {
+ let l = sub.push_prefix(prefix);
+ emit_match_arg_rec(buf, prefix, sub);
+ prefix.truncate(l);
}
+}
- w!(buf, "Ok(Self {{\n");
- if !cmd.args.is_empty() {
- for arg in &cmd.args {
- let val = &arg.val;
- w!(buf, "{}: ", val.ident());
- match arg.arity {
- ast::Arity::Optional => {
- w!(buf, "p_.optional(\"{}\", {}.1)?", val.name, val.ident())
- }
- ast::Arity::Required => {
- w!(buf, "p_.required(\"{}\", {}.1)?", val.name, val.ident())
- }
- ast::Arity::Repeated => w!(buf, "{}.1", val.ident()),
- }
- w!(buf, ",\n");
- }
- blank_line(buf);
- }
+fn emit_record_rec(buf: &mut String, prefix: &mut String, cmd: &ast::Cmd) {
+ w!(buf, "{} {{\n", cmd.ident());
for flag in &cmd.flags {
+ if flag.is_help() {
+ continue;
+ }
w!(buf, "{}: ", flag.ident());
match &flag.val {
Some(_val) => match flag.arity {
ast::Arity::Optional => {
- w!(buf, "p_.optional(\"--{}\", {})?", flag.name, flag.ident())
+ w!(buf, "p_.optional(\"--{}\", {prefix}{})?", flag.name, flag.ident())
}
ast::Arity::Required => {
- w!(buf, "p_.required(\"--{}\", {})?", flag.name, flag.ident())
+ w!(buf, "p_.required(\"--{}\", {prefix}{})?", flag.name, flag.ident())
}
- ast::Arity::Repeated => w!(buf, "{}", flag.ident()),
+ ast::Arity::Repeated => w!(buf, "{prefix}{}", flag.ident()),
},
None => match flag.arity {
ast::Arity::Optional => {
- w!(buf, "p_.optional(\"--{}\", {})?.is_some()", flag.name, flag.ident())
+ w!(buf, "p_.optional(\"--{}\", {prefix}{})?.is_some()", flag.name, flag.ident())
}
ast::Arity::Required => {
- w!(buf, "p_.required(\"--{}\", {})?", flag.name, flag.ident())
+ w!(buf, "p_.required(\"--{}\", {prefix}{})?", flag.name, flag.ident())
}
- ast::Arity::Repeated => w!(buf, "{}.len() as u32", flag.ident()),
+ ast::Arity::Repeated => w!(buf, "{prefix}{}.len() as u32", flag.ident()),
},
}
w!(buf, ",\n");
}
+ for arg in &cmd.args {
+ let val = &arg.val;
+ w!(buf, "{}: ", val.ident());
+ match arg.arity {
+ ast::Arity::Optional => {
+ w!(buf, "p_.optional(\"{}\", {prefix}{}.1)?", val.name, val.ident())
+ }
+ ast::Arity::Required => {
+ w!(buf, "p_.required(\"{}\", {prefix}{}.1)?", val.name, val.ident())
+ }
+ ast::Arity::Repeated => w!(buf, "{prefix}{}.1", val.ident()),
+ }
+ w!(buf, ",\n");
+ }
if cmd.has_subcommands() {
- w!(buf, "subcommand: p_.subcommand(sub_)?,\n");
+ w!(buf, "subcommand: match state_ {{\n");
+ for sub in &cmd.subcommands {
+ emit_leaf_ids_rec(buf, sub);
+ w!(buf, " => {}::{}(", cmd.cmd_enum_ident(), sub.ident());
+ let l = prefix.len();
+ prefix.push_str(&snake(&sub.name));
+ prefix.push_str("__");
+ emit_record_rec(buf, prefix, sub);
+ prefix.truncate(l);
+ w!(buf, "),\n");
+ }
+ w!(buf, "_ => return Err(p_.subcommand_required()),");
+ w!(buf, "}}\n");
}
- w!(buf, "}})\n");
- w!(buf, "}}\n");
- w!(buf, "}}\n");
+ w!(buf, "}}");
+}
+
+fn emit_leaf_ids_rec(buf: &mut String, cmd: &ast::Cmd) {
+ if cmd.has_subcommands() {
+ for sub in &cmd.subcommands {
+ emit_leaf_ids_rec(buf, sub)
+ }
+ } else {
+ w!(buf, "| {}", cmd.idx)
+ }
+}
+
+fn emit_all_ids_rec(buf: &mut String, cmd: &ast::Cmd) {
+ w!(buf, "| {}", cmd.idx);
+ for sub in &cmd.subcommands {
+ emit_all_ids_rec(buf, sub)
+ }
+}
+
+fn emit_default_transitions(buf: &mut String, cmd: &ast::Cmd) {
+ if let Some(sub) = cmd.default_subcommand() {
+ w!(buf, "state_ = if state_ == {} {{ {} }} else {{ state_ }};", cmd.idx, sub.idx);
+ }
+ for sub in &cmd.subcommands {
+ emit_default_transitions(buf, sub);
+ }
}
fn emit_help(buf: &mut String, xflags: &ast::XFlags) {
@@ -327,7 +388,7 @@ fn emit_help(buf: &mut String, xflags: &ast::XFlags) {
let help = format!("{:?}", help);
let help = help.replace("\\n", "\n").replacen("\"", "\"\\\n", 1);
- w!(buf, "const HELP_: &'static str = {};", help);
+ w!(buf, "const HELP_: &'static str = {help};");
w!(buf, "}}\n");
}
@@ -336,26 +397,34 @@ fn write_lines_indented(buf: &mut String, multiline_str: &str, indent: usize) {
if line.is_empty() {
w!(buf, "\n")
} else {
- w!(buf, "{blank:indent$}{}\n", line, indent = indent, blank = "");
+ w!(buf, "{blank:indent$}{line}\n", blank = "");
}
}
}
fn help_rec(buf: &mut String, prefix: &str, cmd: &ast::Cmd) {
- w!(buf, "{}{}\n", prefix, cmd.name);
+ let mut empty_help = true;
+ if !cmd.name.is_empty() {
+ empty_help = false;
+ w!(buf, "{}{}\n", prefix, cmd.name);
+ }
if let Some(doc) = &cmd.doc {
+ empty_help = false;
write_lines_indented(buf, doc, 2);
}
let indent = if prefix.is_empty() { "" } else { " " };
let args = cmd.args_with_default();
if !args.is_empty() {
- blank_line(buf);
+ if !empty_help {
+ blank_line(buf);
+ }
+ empty_help = false;
w!(buf, "{}ARGS:\n", indent);
let mut blank = "";
for arg in &args {
- w!(buf, "{}", blank);
+ w!(buf, "{blank}");
blank = "\n";
let (l, r) = match arg.arity {
@@ -363,7 +432,7 @@ fn help_rec(buf: &mut String, prefix: &str, cmd: &ast::Cmd) {
ast::Arity::Required => ("<", ">"),
ast::Arity::Repeated => ("<", ">..."),
};
- w!(buf, " {}{}{}\n", l, arg.val.name, r);
+ w!(buf, " {l}{}{r}\n", arg.val.name);
if let Some(doc) = &arg.doc {
write_lines_indented(buf, doc, 6)
}
@@ -372,17 +441,19 @@ fn help_rec(buf: &mut String, prefix: &str, cmd: &ast::Cmd) {
let flags = cmd.flags_with_default();
if !flags.is_empty() {
- blank_line(buf);
- w!(buf, "{}OPTIONS:\n", indent);
+ if !empty_help {
+ blank_line(buf);
+ }
+ w!(buf, "{indent}OPTIONS:\n");
let mut blank = "";
for flag in &flags {
- w!(buf, "{}", blank);
+ w!(buf, "{blank}",);
blank = "\n";
- let short = flag.short.as_ref().map(|it| format!("-{}, ", it)).unwrap_or_default();
+ let short = flag.short.as_ref().map(|it| format!("-{it}, ")).unwrap_or_default();
let value = flag.val.as_ref().map(|it| format!(" <{}>", it.name)).unwrap_or_default();
- w!(buf, " {}--{}{}\n", short, flag.name, value);
+ w!(buf, " {short}--{}{value}\n", flag.name);
if let Some(doc) = &flag.doc {
write_lines_indented(buf, doc, 6);
}
@@ -407,11 +478,20 @@ fn help_rec(buf: &mut String, prefix: &str, cmd: &ast::Cmd) {
impl ast::Cmd {
fn ident(&self) -> String {
+ if self.name.is_empty() {
+ return "Flags".to_string();
+ }
camel(&self.name)
}
fn cmd_enum_ident(&self) -> String {
format!("{}Cmd", self.ident())
}
+ fn push_prefix(&self, buf: &mut String) -> usize {
+ let l = buf.len();
+ buf.push_str(&snake(&self.name));
+ buf.push_str("__");
+ l
+ }
fn has_subcommands(&self) -> bool {
!self.subcommands.is_empty()
}
@@ -510,10 +590,10 @@ mod tests {
#[test]
fn gen_it() {
- let test_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/it");
+ let test_dir = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests");
let mut did_update = false;
- for entry in fs::read_dir(test_dir.join("src")).unwrap() {
+ for entry in fs::read_dir(test_dir.join("data")).unwrap() {
let entry = entry.unwrap();
let text = fs::read_to_string(entry.path()).unwrap();
@@ -531,7 +611,7 @@ mod tests {
);
let name = entry.file_name();
- did_update |= update_on_disk_if_different(&test_dir.join(name), code);
+ did_update |= update_on_disk_if_different(&test_dir.join("it").join(name), code);
if fmt.is_none() {
panic!("syntax error");
diff --git a/vendor/xflags-macros/src/lib.rs b/vendor/xflags-macros/src/lib.rs
index 8fac00587..f1c0e0599 100644
--- a/vendor/xflags-macros/src/lib.rs
+++ b/vendor/xflags-macros/src/lib.rs
@@ -8,19 +8,39 @@ pub fn xflags(_ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
// Stub out the code, but let rust-analyzer resolve the invocation
#[cfg(not(test))]
{
- let cmd = parse::parse(_ts).unwrap();
- let text = emit::emit(&cmd);
+ let text = match parse::xflags(_ts) {
+ Ok(cmd) => emit::emit(&cmd),
+ Err(err) => format!("compile_error!(\"invalid flags syntax, {err}\");"),
+ };
text.parse().unwrap()
}
#[cfg(test)]
unimplemented!()
}
+#[proc_macro]
+pub fn parse_or_exit(_ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ // Stub out the code, but let rust-analyzer resolve the invocation
+ #[cfg(not(test))]
+ {
+ let text = match parse::parse_or_exit(_ts) {
+ Ok(cmd) => emit::emit(&cmd),
+ Err(err) => format!("compile_error!(\"invalid flags syntax, {err}\")"),
+ };
+ text.parse().unwrap()
+ }
+ #[cfg(test)]
+ {
+ let _ = parse::parse_or_exit;
+ unimplemented!();
+ }
+}
+
#[cfg(test)]
pub fn compile(src: &str) -> String {
use proc_macro2::TokenStream;
let ts = src.parse::<TokenStream>().unwrap();
- let cmd = parse::parse(ts).unwrap();
+ let cmd = parse::xflags(ts).unwrap();
emit::emit(&cmd)
}
diff --git a/vendor/xflags-macros/src/parse.rs b/vendor/xflags-macros/src/parse.rs
index e9749b141..48f9588e9 100644
--- a/vendor/xflags-macros/src/parse.rs
+++ b/vendor/xflags-macros/src/parse.rs
@@ -1,4 +1,4 @@
-use std::mem;
+use std::{fmt, mem};
#[cfg(not(test))]
use proc_macro::{Delimiter, TokenStream, TokenTree};
@@ -16,15 +16,41 @@ pub(crate) struct Error {
impl std::error::Error for Error {}
-impl std::fmt::Display for Error {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}", self.msg)
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ fmt::Display::fmt(&self.msg, f)
}
}
-pub(crate) fn parse(ts: TokenStream) -> Result<ast::XFlags> {
- let mut p = Parser::new(ts);
- xflags(&mut p)
+pub(crate) fn xflags(ts: TokenStream) -> Result<ast::XFlags> {
+ let p = &mut Parser::new(ts);
+ let src = if p.eat_keyword("src") { Some(p.expect_string()?) } else { None };
+ let doc = opt_doc(p)?;
+ let mut cmd = cmd(p)?;
+ cmd.doc = doc;
+ add_help(&mut cmd);
+ let res = ast::XFlags { src, cmd };
+ Ok(res)
+}
+
+pub(crate) fn parse_or_exit(ts: TokenStream) -> Result<ast::XFlags> {
+ let p = &mut Parser::new(ts);
+ let mut cmd = anon_cmd(p)?;
+ assert!(cmd.subcommands.is_empty());
+ add_help(&mut cmd);
+ let res = ast::XFlags { src: None, cmd };
+ Ok(res)
+}
+
+fn add_help(cmd: &mut ast::Cmd) {
+ let help = ast::Flag {
+ arity: ast::Arity::Optional,
+ name: "help".to_string(),
+ short: Some("h".to_string()),
+ doc: Some("Prints help information.".to_string()),
+ val: None,
+ };
+ cmd.flags.push(help);
}
macro_rules! format_err {
@@ -40,19 +66,25 @@ macro_rules! bail {
};
}
-fn xflags(p: &mut Parser) -> Result<ast::XFlags> {
- let src = if p.eat_keyword("src") { Some(p.expect_string()?) } else { None };
- let doc = opt_doc(p)?;
- let mut cmd = cmd(p)?;
- cmd.doc = doc;
- let res = ast::XFlags { src, cmd };
- Ok(res)
+fn anon_cmd(p: &mut Parser) -> Result<ast::Cmd> {
+ cmd_impl(p, true)
}
fn cmd(p: &mut Parser) -> Result<ast::Cmd> {
- p.expect_keyword("cmd")?;
+ cmd_impl(p, false)
+}
+
+fn cmd_impl(p: &mut Parser, anon: bool) -> Result<ast::Cmd> {
+ let name = if anon {
+ String::new()
+ } else {
+ p.expect_keyword("cmd")?;
+ cmd_name(p)?
+ };
+
+ let idx = p.idx;
+ p.idx += 1;
- let name = cmd_name(p)?;
let mut res = ast::Cmd {
name,
doc: None,
@@ -60,25 +92,16 @@ fn cmd(p: &mut Parser) -> Result<ast::Cmd> {
flags: Vec::new(),
subcommands: Vec::new(),
default: false,
+ idx,
};
- while !p.at_delim(Delimiter::Brace) {
- let doc = opt_doc(p)?;
- let arity = arity(p)?;
- match opt_val(p)? {
- Some(val) => {
- let arg = ast::Arg { arity, doc, val };
- res.args.push(arg);
- }
- None => bail!("expected ident"),
- }
+ if !anon {
+ p.enter_delim(Delimiter::Brace)?;
}
-
- p.enter_delim(Delimiter::Brace)?;
while !p.end() {
let doc = opt_doc(p)?;
- let default = p.eat_keyword("default");
- if default || p.at_keyword("cmd") {
+ let default = !anon && p.eat_keyword("default");
+ if !anon && (default || p.at_keyword("cmd")) {
let mut cmd = cmd(p)?;
cmd.doc = doc;
res.subcommands.push(cmd);
@@ -90,35 +113,56 @@ fn cmd(p: &mut Parser) -> Result<ast::Cmd> {
res.subcommands.rotate_right(1);
}
} else {
- let mut flag = flag(p)?;
- flag.doc = doc;
- res.flags.push(flag);
+ let arity = arity(p)?;
+ let is_val = p.lookahead_punct(':', 1);
+ let name = p.expect_name()?;
+ if name.starts_with('-') {
+ let mut flag = flag(p, name)?;
+ flag.doc = doc;
+ flag.arity = arity;
+ res.flags.push(flag)
+ } else if is_val {
+ p.expect_punct(':')?;
+ let ty = ty(p)?;
+ let val = ast::Val { name, ty };
+ let arg = ast::Arg { arity, doc, val };
+ res.args.push(arg);
+ } else {
+ bail!("expected `--flag` or `arg: Type`")
+ }
}
}
- p.exit_delim()?;
+ if !anon {
+ p.exit_delim()?;
+ }
Ok(res)
}
-fn flag(p: &mut Parser) -> Result<ast::Flag> {
- let arity = arity(p)?;
-
- let mut short = None;
- let mut name = flag_name(p)?;
- if !name.starts_with("--") {
+fn flag(p: &mut Parser, name: String) -> Result<ast::Flag> {
+ let short;
+ let long;
+ if name.starts_with("--") {
+ short = None;
+ long = name;
+ } else {
short = Some(name);
if !p.eat_punct(',') {
bail!("long option is required for `{}`", short.unwrap());
}
- name = flag_name(p)?;
- if !name.starts_with("--") {
- bail!("long name must begin with `--`: `{}`", name);
+ long = flag_name(p)?;
+ if !long.starts_with("--") {
+ bail!("long name must begin with `--`: `{long}`");
}
}
+ if long == "--help" {
+ bail!("`--help` flag is generated automatically")
+ }
+
let val = opt_val(p)?;
Ok(ast::Flag {
- arity,
- name: name[2..].to_string(),
+ arity: ast::Arity::Required,
+ name: long[2..].to_string(),
short: short.map(|it| it[1..].to_string()),
doc: None,
val,
@@ -148,7 +192,7 @@ fn arity(p: &mut Parser) -> Result<ast::Arity> {
return Ok(ast::Arity::Repeated);
}
if let Some(name) = p.eat_name() {
- bail!("expected one of `optional`, `required`, `repeated`, got `{}`", name)
+ bail!("expected one of `optional`, `required`, `repeated`, got `{name}`")
}
bail!("expected one of `optional`, `required`, `repeated`, got {:?}", p.ts.pop())
}
@@ -193,7 +237,7 @@ fn opt_doc(p: &mut Parser) -> Result<Option<String>> {
fn cmd_name(p: &mut Parser) -> Result<String> {
let name = p.expect_name()?;
if name.starts_with('-') {
- bail!("command name can't begin with `-`: `{}`", name);
+ bail!("command name can't begin with `-`: `{name}`");
}
Ok(name)
}
@@ -201,7 +245,7 @@ fn cmd_name(p: &mut Parser) -> Result<String> {
fn flag_name(p: &mut Parser) -> Result<String> {
let name = p.expect_name()?;
if !name.starts_with('-') {
- bail!("flag name should begin with `-`: `{}`", name);
+ bail!("flag name should begin with `-`: `{name}`");
}
Ok(name)
}
@@ -209,21 +253,16 @@ fn flag_name(p: &mut Parser) -> Result<String> {
struct Parser {
stack: Vec<Vec<TokenTree>>,
ts: Vec<TokenTree>,
+ idx: u8,
}
impl Parser {
fn new(ts: TokenStream) -> Self {
let mut ts = ts.into_iter().collect::<Vec<_>>();
ts.reverse();
- Self { stack: Vec::new(), ts }
+ Self { stack: Vec::new(), ts, idx: 0 }
}
- fn at_delim(&mut self, delimiter: Delimiter) -> bool {
- match self.ts.last() {
- Some(TokenTree::Group(g)) => g.delimiter() == delimiter,
- _ => false,
- }
- }
fn enter_delim(&mut self, delimiter: Delimiter) -> Result<()> {
match self.ts.pop() {
Some(TokenTree::Group(g)) if g.delimiter() == delimiter => {
@@ -249,7 +288,7 @@ impl Parser {
fn expect_keyword(&mut self, kw: &str) -> Result<()> {
if !self.eat_keyword(kw) {
- bail!("expected `{}`", kw)
+ bail!("expected `{kw}`")
}
Ok(())
}
@@ -271,7 +310,7 @@ impl Parser {
fn expect_name(&mut self) -> Result<String> {
self.eat_name().ok_or_else(|| {
let next = self.ts.pop().map(|it| it.to_string()).unwrap_or_default();
- format_err!("expected a name, got: `{}`", next)
+ format_err!("expected a name, got: `{next}`")
})
}
fn eat_name(&mut self) -> Option<String> {
@@ -307,7 +346,7 @@ impl Parser {
fn expect_punct(&mut self, punct: char) -> Result<()> {
if !self.eat_punct(punct) {
- bail!("expected `{}`", punct)
+ bail!("expected `{punct}`")
}
Ok(())
}
@@ -330,11 +369,18 @@ impl Parser {
fn expect_string(&mut self) -> Result<String> {
match self.ts.pop() {
Some(TokenTree::Literal(lit)) if lit.to_string().starts_with('"') => {
- let text = lit.to_string();
- let res = text.trim_matches('"').to_string();
+ let res = str_lit_value(lit.to_string());
Ok(res)
}
_ => bail!("expected a string"),
}
}
}
+
+/// "Parser" a string literal into the corresponding value.
+///
+/// Really needs support in the proc_macro library:
+/// <https://internals.rust-lang.org/t/getting-value-out-of-proc-macro-literal/14140>
+fn str_lit_value(lit: String) -> String {
+ lit.trim_matches('"').replace("\\'", "'")
+}
diff --git a/vendor/xflags-macros/src/update.rs b/vendor/xflags-macros/src/update.rs
index e476e37aa..83a404c93 100644
--- a/vendor/xflags-macros/src/update.rs
+++ b/vendor/xflags-macros/src/update.rs
@@ -6,8 +6,7 @@ pub(crate) fn in_place(api: &str, path: &Path) {
Path::new(&dir).join(path)
};
- let mut text =
- fs::read_to_string(&path).unwrap_or_else(|_| panic!("failed to read {:?}", path));
+ let mut text = fs::read_to_string(&path).unwrap_or_else(|_| panic!("failed to read {path:?}"));
let (insert_to, indent) = locate(&text);
diff --git a/vendor/xflags-macros/tests/it/src/help.rs b/vendor/xflags-macros/tests/data/help.rs
index d552c1e63..f252e34fa 100644
--- a/vendor/xflags-macros/tests/it/src/help.rs
+++ b/vendor/xflags-macros/tests/data/help.rs
@@ -2,16 +2,17 @@ xflags! {
/// Does stuff
///
/// Helpful stuff.
- cmd helpful
+ cmd helpful {
/// With an arg.
optional src: PathBuf
+
/// Another arg.
///
/// This time, we provide some extra info about the
/// arg. Maybe some caveats, or what kinds of
/// values are accepted.
optional extra: String
- {
+
/// And a switch.
required -s, --switch
diff --git a/vendor/xflags-macros/tests/it/src/repeated_pos.rs b/vendor/xflags-macros/tests/data/repeated_pos.rs
index 4106c65eb..be7c552e0 100644
--- a/vendor/xflags-macros/tests/it/src/repeated_pos.rs
+++ b/vendor/xflags-macros/tests/data/repeated_pos.rs
@@ -1,9 +1,8 @@
xflags! {
- cmd RepeatedPos
+ cmd RepeatedPos {
required a: PathBuf
optional b: u32
optional c: OsString
repeated rest: OsString
- {
}
}
diff --git a/vendor/xflags-macros/tests/it/src/smoke.rs b/vendor/xflags-macros/tests/data/smoke.rs
index ae303779e..55da2d3ef 100644
--- a/vendor/xflags-macros/tests/it/src/smoke.rs
+++ b/vendor/xflags-macros/tests/data/smoke.rs
@@ -1,10 +1,9 @@
xflags! {
/// LSP server for rust.
- cmd rust-analyzer
+ cmd rust-analyzer {
required workspace: PathBuf
/// Number of concurrent jobs.
optional jobs: u32
- {
/// Path to log file. By default, logs go to stderr.
optional --log-file path: PathBuf
repeated -v, --verbose
diff --git a/vendor/xflags-macros/tests/it/src/subcommands.rs b/vendor/xflags-macros/tests/data/subcommands.rs
index 70a0a5049..45fab8232 100644
--- a/vendor/xflags-macros/tests/it/src/subcommands.rs
+++ b/vendor/xflags-macros/tests/data/subcommands.rs
@@ -11,9 +11,8 @@ xflags! {
}
}
- cmd analysis-stats
+ cmd analysis-stats {
required path: PathBuf
- {
optional --parallel
}
}
diff --git a/vendor/xflags-macros/tests/it/help.rs b/vendor/xflags-macros/tests/it/help.rs
index 36a966485..f17062988 100644
--- a/vendor/xflags-macros/tests/it/help.rs
+++ b/vendor/xflags-macros/tests/it/help.rs
@@ -21,7 +21,10 @@ pub struct Sub {
}
impl Helpful {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
@@ -35,6 +38,9 @@ impl Helpful {
}
impl Helpful {
+ fn from_env_or_exit_() -> Self {
+ Self::from_env_().unwrap_or_else(|err| err.exit())
+ }
fn from_env_() -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new_from_env();
Self::parse_(&mut p)
@@ -47,68 +53,51 @@ impl Helpful {
impl Helpful {
fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
+ #![allow(non_snake_case)]
let mut switch = Vec::new();
-
let mut src = (false, Vec::new());
let mut extra = (false, Vec::new());
+ let mut sub__flag = Vec::new();
- let mut sub_ = None;
+ let mut state_ = 0u8;
while let Some(arg_) = p_.pop_flag() {
match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--switch" | "-s" => switch.push(()),
+ Ok(flag_) => match (state_, flag_.as_str()) {
+ (0 | 1, "--switch" | "-s") => switch.push(()),
+ (0 | 1, "--help" | "-h") => return Err(p_.help(Self::HELP_)),
+ (1, "--flag" | "-f") => sub__flag.push(()),
_ => return Err(p_.unexpected_flag(&flag_)),
},
- Err(arg_) => {
- match arg_.to_str().unwrap_or("") {
- "sub" => {
- sub_ = Some(HelpfulCmd::Sub(Sub::parse_(p_)?));
- break;
+ Err(arg_) => match (state_, arg_.to_str().unwrap_or("")) {
+ (0, "sub") => state_ = 1,
+ (0, _) => {
+ if let (done_ @ false, buf_) = &mut src {
+ buf_.push(arg_.into());
+ *done_ = true;
+ continue;
}
- _ => (),
- }
- if let (done_ @ false, buf_) = &mut src {
- buf_.push(arg_.into());
- *done_ = true;
- continue;
- }
- if let (done_ @ false, buf_) = &mut extra {
- buf_.push(p_.value_from_str::<String>("extra", arg_)?);
- *done_ = true;
- continue;
+ if let (done_ @ false, buf_) = &mut extra {
+ buf_.push(p_.value_from_str::<String>("extra", arg_)?);
+ *done_ = true;
+ continue;
+ }
+ return Err(p_.unexpected_arg(arg_));
}
- return Err(p_.unexpected_arg(arg_));
- }
+ _ => return Err(p_.unexpected_arg(arg_)),
+ },
}
}
- Ok(Self {
+ Ok(Helpful {
+ switch: p_.required("--switch", switch)?,
src: p_.optional("src", src.1)?,
extra: p_.optional("extra", extra.1)?,
-
- switch: p_.required("--switch", switch)?,
- subcommand: p_.subcommand(sub_)?,
+ subcommand: match state_ {
+ 1 => HelpfulCmd::Sub(Sub { flag: p_.optional("--flag", sub__flag)?.is_some() }),
+ _ => return Err(p_.subcommand_required()),
+ },
})
}
}
-
-impl Sub {
- fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
- let mut flag = Vec::new();
-
- while let Some(arg_) = p_.pop_flag() {
- match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--flag" | "-f" => flag.push(()),
- _ => return Err(p_.unexpected_flag(&flag_)),
- },
- Err(arg_) => {
- return Err(p_.unexpected_arg(arg_));
- }
- }
- }
- Ok(Self { flag: p_.optional("--flag", flag)?.is_some() })
- }
-}
impl Helpful {
const HELP_: &'static str = "\
helpful
@@ -131,6 +120,9 @@ OPTIONS:
-s, --switch
And a switch.
+ -h, --help
+ Prints help information.
+
SUBCOMMANDS:
helpful sub
diff --git a/vendor/xflags-macros/tests/it/main.rs b/vendor/xflags-macros/tests/it/main.rs
index 1ce058814..7d77bda36 100644
--- a/vendor/xflags-macros/tests/it/main.rs
+++ b/vendor/xflags-macros/tests/it/main.rs
@@ -67,9 +67,10 @@ fn smoke() {
"-n 92 --werbose",
expect![[r#"unexpected flag: `--werbose`"#]],
);
- check(smoke::RustAnalyzer::from_vec, "", expect![[r#"flag is required: `workspace`"#]]);
+ check(smoke::RustAnalyzer::from_vec, "", expect!["flag is required: `--number`"]);
check(smoke::RustAnalyzer::from_vec, ".", expect![[r#"flag is required: `--number`"#]]);
check(smoke::RustAnalyzer::from_vec, "-n", expect![[r#"expected a value for `-n`"#]]);
+ check(smoke::RustAnalyzer::from_vec, "-n 92", expect!["flag is required: `workspace`"]);
check(
smoke::RustAnalyzer::from_vec,
"-n lol",
@@ -196,3 +197,36 @@ fn subcommands() {
check(subcommands::RustAnalyzer::from_vec, "", expect![[r#"subcommand is required"#]]);
}
+
+#[test]
+fn subcommand_flag_inheritance() {
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "server watch --verbose --dir .",
+ expect![[r#"
+ RustAnalyzer {
+ verbose: 1,
+ subcommand: Server(
+ Server {
+ dir: Some(
+ ".",
+ ),
+ subcommand: Watch(
+ Watch,
+ ),
+ },
+ ),
+ }
+ "#]],
+ );
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "analysis-stats --verbose --dir .",
+ expect!["unexpected flag: `--dir`"],
+ );
+ check(
+ subcommands::RustAnalyzer::from_vec,
+ "--dir . server",
+ expect!["unexpected flag: `--dir`"],
+ );
+}
diff --git a/vendor/xflags-macros/tests/it/repeated_pos.rs b/vendor/xflags-macros/tests/it/repeated_pos.rs
index 334af371d..b11b90717 100644
--- a/vendor/xflags-macros/tests/it/repeated_pos.rs
+++ b/vendor/xflags-macros/tests/it/repeated_pos.rs
@@ -10,7 +10,10 @@ pub struct RepeatedPos {
}
impl RepeatedPos {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
@@ -24,6 +27,9 @@ impl RepeatedPos {
}
impl RepeatedPos {
+ fn from_env_or_exit_() -> Self {
+ Self::from_env_().unwrap_or_else(|err| err.exit())
+ }
fn from_env_() -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new_from_env();
Self::parse_(&mut p)
@@ -36,41 +42,47 @@ impl RepeatedPos {
impl RepeatedPos {
fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
+ #![allow(non_snake_case)]
let mut a = (false, Vec::new());
let mut b = (false, Vec::new());
let mut c = (false, Vec::new());
let mut rest = (false, Vec::new());
+ let mut state_ = 0u8;
while let Some(arg_) = p_.pop_flag() {
match arg_ {
- Ok(flag_) => match flag_.as_str() {
+ Ok(flag_) => match (state_, flag_.as_str()) {
+ (0, "--help" | "-h") => return Err(p_.help(Self::HELP_)),
_ => return Err(p_.unexpected_flag(&flag_)),
},
- Err(arg_) => {
- if let (done_ @ false, buf_) = &mut a {
- buf_.push(arg_.into());
- *done_ = true;
- continue;
- }
- if let (done_ @ false, buf_) = &mut b {
- buf_.push(p_.value_from_str::<u32>("b", arg_)?);
- *done_ = true;
- continue;
+ Err(arg_) => match (state_, arg_.to_str().unwrap_or("")) {
+ (0, _) => {
+ if let (done_ @ false, buf_) = &mut a {
+ buf_.push(arg_.into());
+ *done_ = true;
+ continue;
+ }
+ if let (done_ @ false, buf_) = &mut b {
+ buf_.push(p_.value_from_str::<u32>("b", arg_)?);
+ *done_ = true;
+ continue;
+ }
+ if let (done_ @ false, buf_) = &mut c {
+ buf_.push(arg_.into());
+ *done_ = true;
+ continue;
+ }
+ if let (false, buf_) = &mut rest {
+ buf_.push(arg_.into());
+ continue;
+ }
+ return Err(p_.unexpected_arg(arg_));
}
- if let (done_ @ false, buf_) = &mut c {
- buf_.push(arg_.into());
- *done_ = true;
- continue;
- }
- if let (false, buf_) = &mut rest {
- buf_.push(arg_.into());
- continue;
- }
- return Err(p_.unexpected_arg(arg_));
- }
+ _ => return Err(p_.unexpected_arg(arg_)),
+ },
}
}
- Ok(Self {
+ Ok(RepeatedPos {
a: p_.required("a", a.1)?,
b: p_.optional("b", b.1)?,
c: p_.optional("c", c.1)?,
@@ -90,5 +102,9 @@ ARGS:
[c]
<rest>...
+
+OPTIONS:
+ -h, --help
+ Prints help information.
";
}
diff --git a/vendor/xflags-macros/tests/it/smoke.rs b/vendor/xflags-macros/tests/it/smoke.rs
index e22c4f1f6..f2ebbb712 100644
--- a/vendor/xflags-macros/tests/it/smoke.rs
+++ b/vendor/xflags-macros/tests/it/smoke.rs
@@ -14,7 +14,10 @@ pub struct RustAnalyzer {
}
impl RustAnalyzer {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
@@ -28,6 +31,9 @@ impl RustAnalyzer {
}
impl RustAnalyzer {
+ fn from_env_or_exit_() -> Self {
+ Self::from_env_().unwrap_or_else(|err| err.exit())
+ }
fn from_env_() -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new_from_env();
Self::parse_(&mut p)
@@ -40,49 +46,53 @@ impl RustAnalyzer {
impl RustAnalyzer {
fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
+ #![allow(non_snake_case)]
let mut log_file = Vec::new();
let mut verbose = Vec::new();
let mut number = Vec::new();
let mut data = Vec::new();
let mut emoji = Vec::new();
-
let mut workspace = (false, Vec::new());
let mut jobs = (false, Vec::new());
+ let mut state_ = 0u8;
while let Some(arg_) = p_.pop_flag() {
match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--log-file" => log_file.push(p_.next_value(&flag_)?.into()),
- "--verbose" | "-v" => verbose.push(()),
- "--number" | "-n" => number.push(p_.next_value_from_str::<u32>(&flag_)?),
- "--data" => data.push(p_.next_value(&flag_)?.into()),
- "--emoji" => emoji.push(()),
+ Ok(flag_) => match (state_, flag_.as_str()) {
+ (0, "--log-file") => log_file.push(p_.next_value(&flag_)?.into()),
+ (0, "--verbose" | "-v") => verbose.push(()),
+ (0, "--number" | "-n") => number.push(p_.next_value_from_str::<u32>(&flag_)?),
+ (0, "--data") => data.push(p_.next_value(&flag_)?.into()),
+ (0, "--emoji") => emoji.push(()),
+ (0, "--help" | "-h") => return Err(p_.help(Self::HELP_)),
_ => return Err(p_.unexpected_flag(&flag_)),
},
- Err(arg_) => {
- if let (done_ @ false, buf_) = &mut workspace {
- buf_.push(arg_.into());
- *done_ = true;
- continue;
- }
- if let (done_ @ false, buf_) = &mut jobs {
- buf_.push(p_.value_from_str::<u32>("jobs", arg_)?);
- *done_ = true;
- continue;
+ Err(arg_) => match (state_, arg_.to_str().unwrap_or("")) {
+ (0, _) => {
+ if let (done_ @ false, buf_) = &mut workspace {
+ buf_.push(arg_.into());
+ *done_ = true;
+ continue;
+ }
+ if let (done_ @ false, buf_) = &mut jobs {
+ buf_.push(p_.value_from_str::<u32>("jobs", arg_)?);
+ *done_ = true;
+ continue;
+ }
+ return Err(p_.unexpected_arg(arg_));
}
- return Err(p_.unexpected_arg(arg_));
- }
+ _ => return Err(p_.unexpected_arg(arg_)),
+ },
}
}
- Ok(Self {
- workspace: p_.required("workspace", workspace.1)?,
- jobs: p_.optional("jobs", jobs.1)?,
-
+ Ok(RustAnalyzer {
log_file: p_.optional("--log-file", log_file)?,
verbose: verbose.len() as u32,
number: p_.required("--number", number)?,
data: data,
emoji: p_.optional("--emoji", emoji)?.is_some(),
+ workspace: p_.required("workspace", workspace.1)?,
+ jobs: p_.optional("jobs", jobs.1)?,
})
}
}
@@ -108,5 +118,8 @@ OPTIONS:
--data <value>
--emoji
+
+ -h, --help
+ Prints help information.
";
}
diff --git a/vendor/xflags-macros/tests/it/subcommands.rs b/vendor/xflags-macros/tests/it/subcommands.rs
index 7941a395d..4d0a64923 100644
--- a/vendor/xflags-macros/tests/it/subcommands.rs
+++ b/vendor/xflags-macros/tests/it/subcommands.rs
@@ -41,7 +41,10 @@ pub struct AnalysisStats {
}
impl RustAnalyzer {
- pub const HELP: &'static str = Self::HELP_;
+ #[allow(dead_code)]
+ pub fn from_env_or_exit() -> Self {
+ Self::from_env_or_exit_()
+ }
#[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
@@ -55,6 +58,9 @@ impl RustAnalyzer {
}
impl RustAnalyzer {
+ fn from_env_or_exit_() -> Self {
+ Self::from_env_().unwrap_or_else(|err| err.exit())
+ }
fn from_env_() -> xflags::Result<Self> {
let mut p = xflags::rt::Parser::new_from_env();
Self::parse_(&mut p)
@@ -67,130 +73,71 @@ impl RustAnalyzer {
impl RustAnalyzer {
fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
+ #![allow(non_snake_case)]
let mut verbose = Vec::new();
+ let mut server__dir = Vec::new();
+ let mut server__launch__log = Vec::new();
+ let mut analysis_stats__parallel = Vec::new();
+ let mut analysis_stats__path = (false, Vec::new());
- let mut sub_ = None;
+ let mut state_ = 0u8;
while let Some(arg_) = p_.pop_flag() {
match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--verbose" | "-v" => verbose.push(()),
+ Ok(flag_) => match (state_, flag_.as_str()) {
+ (0 | 1 | 2 | 3 | 4, "--verbose" | "-v") => verbose.push(()),
+ (0 | 1 | 2 | 3 | 4, "--help" | "-h") => return Err(p_.help(Self::HELP_)),
+ (1 | 2 | 3, "--dir") => server__dir.push(p_.next_value(&flag_)?.into()),
+ (1, _) => {
+ p_.push_back(Ok(flag_));
+ state_ = 2;
+ }
+ (2, "--log") => server__launch__log.push(()),
+ (4, "--parallel") => analysis_stats__parallel.push(()),
_ => return Err(p_.unexpected_flag(&flag_)),
},
- Err(arg_) => {
- match arg_.to_str().unwrap_or("") {
- "server" => {
- sub_ = Some(RustAnalyzerCmd::Server(Server::parse_(p_)?));
- break;
- }
- "analysis-stats" => {
- sub_ = Some(RustAnalyzerCmd::AnalysisStats(AnalysisStats::parse_(p_)?));
- break;
- }
- _ => (),
+ Err(arg_) => match (state_, arg_.to_str().unwrap_or("")) {
+ (0, "server") => state_ = 1,
+ (0, "analysis-stats") => state_ = 4,
+ (0, _) => {
+ return Err(p_.unexpected_arg(arg_));
}
- return Err(p_.unexpected_arg(arg_));
- }
- }
- }
- Ok(Self { verbose: verbose.len() as u32, subcommand: p_.subcommand(sub_)? })
- }
-}
-
-impl Server {
- fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
- let mut dir = Vec::new();
-
- let mut sub_ = None;
- while let Some(arg_) = p_.pop_flag() {
- match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--dir" => dir.push(p_.next_value(&flag_)?.into()),
- _ => {
- p_.push_back(Ok(flag_));
- break;
+ (1, "watch") => state_ = 3,
+ (1, _) => {
+ p_.push_back(Err(arg_));
+ state_ = 2;
}
- },
- Err(arg_) => {
- match arg_.to_str().unwrap_or("") {
- "watch" => {
- sub_ = Some(ServerCmd::Watch(Watch::parse_(p_)?));
- break;
+ (4, _) => {
+ if let (done_ @ false, buf_) = &mut analysis_stats__path {
+ buf_.push(arg_.into());
+ *done_ = true;
+ continue;
}
- _ => (),
+ return Err(p_.unexpected_arg(arg_));
}
- p_.push_back(Err(arg_));
- break;
- }
- }
- }
- if sub_.is_none() {
- sub_ = Some(ServerCmd::Launch(Launch::parse_(p_)?));
- }
- Ok(Self { dir: p_.optional("--dir", dir)?, subcommand: p_.subcommand(sub_)? })
- }
-}
-
-impl Launch {
- fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
- let mut log = Vec::new();
-
- while let Some(arg_) = p_.pop_flag() {
- match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--log" => log.push(()),
- _ => return Err(p_.unexpected_flag(&flag_)),
- },
- Err(arg_) => {
- return Err(p_.unexpected_arg(arg_));
- }
- }
- }
- Ok(Self { log: p_.optional("--log", log)?.is_some() })
- }
-}
-
-impl Watch {
- fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
- while let Some(arg_) = p_.pop_flag() {
- match arg_ {
- Ok(flag_) => match flag_.as_str() {
- _ => return Err(p_.unexpected_flag(&flag_)),
+ _ => return Err(p_.unexpected_arg(arg_)),
},
- Err(arg_) => {
- return Err(p_.unexpected_arg(arg_));
- }
}
}
- Ok(Self {})
- }
-}
-
-impl AnalysisStats {
- fn parse_(p_: &mut xflags::rt::Parser) -> xflags::Result<Self> {
- let mut parallel = Vec::new();
-
- let mut path = (false, Vec::new());
-
- while let Some(arg_) = p_.pop_flag() {
- match arg_ {
- Ok(flag_) => match flag_.as_str() {
- "--parallel" => parallel.push(()),
- _ => return Err(p_.unexpected_flag(&flag_)),
- },
- Err(arg_) => {
- if let (done_ @ false, buf_) = &mut path {
- buf_.push(arg_.into());
- *done_ = true;
- continue;
- }
- return Err(p_.unexpected_arg(arg_));
- }
- }
- }
- Ok(Self {
- path: p_.required("path", path.1)?,
-
- parallel: p_.optional("--parallel", parallel)?.is_some(),
+ state_ = if state_ == 1 { 2 } else { state_ };
+ Ok(RustAnalyzer {
+ verbose: verbose.len() as u32,
+ subcommand: match state_ {
+ 2 | 3 => RustAnalyzerCmd::Server(Server {
+ dir: p_.optional("--dir", server__dir)?,
+ subcommand: match state_ {
+ 2 => ServerCmd::Launch(Launch {
+ log: p_.optional("--log", server__launch__log)?.is_some(),
+ }),
+ 3 => ServerCmd::Watch(Watch {}),
+ _ => return Err(p_.subcommand_required()),
+ },
+ }),
+ 4 => RustAnalyzerCmd::AnalysisStats(AnalysisStats {
+ parallel: p_.optional("--parallel", analysis_stats__parallel)?.is_some(),
+ path: p_.required("path", analysis_stats__path.1)?,
+ }),
+ _ => return Err(p_.subcommand_required()),
+ },
})
}
}
@@ -201,6 +148,9 @@ rust-analyzer
OPTIONS:
-v, --verbose
+ -h, --help
+ Prints help information.
+
SUBCOMMANDS:
rust-analyzer server
diff --git a/vendor/xflags/.cargo-checksum.json b/vendor/xflags/.cargo-checksum.json
index c5fd48200..1fa4dd9e5 100644
--- a/vendor/xflags/.cargo-checksum.json
+++ b/vendor/xflags/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"76747bdf0a7c1643e62a7c8db6e65572906908415ba87daaa7444917cdf1d35b","Cargo.toml":"32dc60919f757b61d4a6602da24bdd59b77b76f284a1b55712a78e1159e2d249","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"d34d354ca65973ca9120ed16af11e188c91af2ede6894e0e842c10c874780f7b","examples/hello-generated.rs":"ac2d4864e238e664fb1b18db66aed75ac5a425877bc00729fed1135fb410b969","examples/hello.rs":"c1a5656bee529c3ef96a3afc3531e02bc9d5d309e1bcd60b76e6758fb4c2a95d","examples/longer.rs":"18ad0d00215fdf245830a581df32fbf9533f5ab47e736659e598b4ecd2d96e1a","examples/non-utf8.rs":"a9d4a03adb05c8b46c3251647b8dbf4e860277db995e14192cd8d445f3434186","src/lib.rs":"21843e64aba8010dcc877418927e5b0ad3615ff6e18020285849bbf4391f4ed0","src/rt.rs":"c3cb2d6c80ec9c0586a6e64441cee4c237d2fb420891dec2acb96d5b0c7d6937"},"package":"3f14fe1ed41a5a2b5ef3f565586c4a8a559ee55d3953faab360a771135bdee00"} \ No newline at end of file
+{"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
diff --git a/vendor/xflags/Cargo.lock b/vendor/xflags/Cargo.lock
index 37ff98bb9..e2020eb16 100644
--- a/vendor/xflags/Cargo.lock
+++ b/vendor/xflags/Cargo.lock
@@ -4,13 +4,13 @@ version = 3
[[package]]
name = "xflags"
-version = "0.2.4"
+version = "0.3.0"
dependencies = [
"xflags-macros",
]
[[package]]
name = "xflags-macros"
-version = "0.2.4"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "45d11d5fc2a97287eded8b170ca80533b3c42646dd7fa386a5eb045817921022"
+checksum = "2afbd7f2039bb6cad2dd45f0c5dff49c0d4e26118398768b7a605524d4251809"
diff --git a/vendor/xflags/Cargo.toml b/vendor/xflags/Cargo.toml
index 542701052..091002385 100644
--- a/vendor/xflags/Cargo.toml
+++ b/vendor/xflags/Cargo.toml
@@ -10,14 +10,15 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
name = "xflags"
-version = "0.2.4"
+version = "0.3.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
-exclude = [".github/", "bors.toml", "rustfmt.toml"]
description = "Moderately simple command line arguments parser."
categories = ["command-line-interface"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/matklad/xflags"
+resolver = "1"
+
[dependencies.xflags-macros]
-version = "=0.2.4"
+version = "=0.3.0"
diff --git a/vendor/xflags/README.md b/vendor/xflags/README.md
deleted file mode 100644
index bfebfb0c8..000000000
--- a/vendor/xflags/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-[![API reference](https://docs.rs/once_cell/badge.svg)](https://docs.rs/xflags/)
-
-# xflags
-
-Moderately simple command line arguments parsing:
-
-```rust
-mod flags {
- use std::path::PathBuf;
-
- xflags::xflags! {
- src "./examples/basic.rs"
-
- cmd my-command
- required path: PathBuf
- {
- optional -v, --verbose
- }
- }
-
- // generated start
- // The following code is generated by `xflags` macro.
- // Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
- #[derive(Debug)]
- pub struct MyCommand {
- pub path: PathBuf,
-
- pub verbose: bool,
- }
-
- impl MyCommand {
- pub const HELP: &'static str = Self::HELP_;
-
- pub fn from_env() -> xflags::Result<Self> {
- Self::from_env_()
- }
-
- pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
- Self::from_vec_(args)
- }
- }
- // generated end
-}
-
-fn main() {
- let flags = flags::MyCommand::from_env();
- println!("{:#?}", flags);
-}
-```
diff --git a/vendor/xflags/examples/hello-generated.rs b/vendor/xflags/examples/hello-generated.rs
index b82884859..cb74acbd7 100644
--- a/vendor/xflags/examples/hello-generated.rs
+++ b/vendor/xflags/examples/hello-generated.rs
@@ -5,10 +5,10 @@ mod flags {
src "./examples/hello-generated.rs"
/// Prints a greeting.
- cmd hello
+ cmd hello {
/// Whom to greet.
required name: String
- {
+
/// Use non-ascii symbols in the output.
optional -e, --emoji
}
@@ -25,12 +25,12 @@ mod flags {
}
impl Hello {
- pub const HELP: &'static str = Self::HELP_;
-
+ #[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
Self::from_env_()
}
+ #[allow(dead_code)]
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
Self::from_vec_(args)
}
@@ -44,9 +44,6 @@ fn main() {
let bang = if flags.emoji { "❣️" } else { "!" };
println!("Hello {}{}", flags.name, bang);
}
- Err(err) => {
- eprintln!("{}\n\n{}", err, flags::Hello::HELP);
- std::process::exit(1)
- }
+ Err(err) => err.exit(),
}
}
diff --git a/vendor/xflags/examples/hello.rs b/vendor/xflags/examples/hello.rs
index 98a19099f..91dc3fd8a 100644
--- a/vendor/xflags/examples/hello.rs
+++ b/vendor/xflags/examples/hello.rs
@@ -1,8 +1,7 @@
mod flags {
xflags::xflags! {
- cmd hello
+ cmd hello {
required name: String
- {
optional -e, --emoji
}
}
diff --git a/vendor/xflags/examples/immediate-mode.rs b/vendor/xflags/examples/immediate-mode.rs
new file mode 100644
index 000000000..ee3baa3de
--- /dev/null
+++ b/vendor/xflags/examples/immediate-mode.rs
@@ -0,0 +1,16 @@
+use std::path::PathBuf;
+
+fn main() {
+ let flags = xflags::parse_or_exit! {
+ /// Remove directories and their contents recursively.
+ optional -r,--recursive
+ /// File or directory to remove
+ required path: PathBuf
+ };
+
+ println!(
+ "removing {}{}",
+ flags.path.display(),
+ if flags.recursive { "recursively" } else { "" },
+ )
+}
diff --git a/vendor/xflags/examples/longer.rs b/vendor/xflags/examples/longer.rs
index 7ea9e18d5..199cca042 100644
--- a/vendor/xflags/examples/longer.rs
+++ b/vendor/xflags/examples/longer.rs
@@ -24,10 +24,9 @@ mod flags {
}
/// Benchmark specific analysis operation
- cmd analysis-bench
+ cmd analysis-bench {
/// Directory with Cargo.toml
optional path: PathBuf
- {
/// Compute syntax highlighting for this file
required --highlight path: PathBuf
/// Compute highlighting for this line
@@ -72,12 +71,12 @@ mod flags {
}
impl RustAnalyzer {
- pub const HELP: &'static str = Self::HELP_;
-
+ #[allow(dead_code)]
pub fn from_env() -> xflags::Result<Self> {
Self::from_env_()
}
+ #[allow(dead_code)]
pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
Self::from_vec_(args)
}
diff --git a/vendor/xflags/examples/non-utf8.rs b/vendor/xflags/examples/non-utf8.rs
index d355b24f6..28b1e98be 100644
--- a/vendor/xflags/examples/non-utf8.rs
+++ b/vendor/xflags/examples/non-utf8.rs
@@ -4,11 +4,10 @@ mod flags {
use std::{ffi::OsString, path::PathBuf};
xflags::xflags! {
- cmd Cmd
+ cmd Cmd {
required a: OsString
required b: PathBuf
required c: String
- {
}
}
}
diff --git a/vendor/xflags/src/lib.rs b/vendor/xflags/src/lib.rs
index ae347f511..0eda9dec4 100644
--- a/vendor/xflags/src/lib.rs
+++ b/vendor/xflags/src/lib.rs
@@ -1,12 +1,65 @@
-//! This crates provides a procedural macro for parsing command line arguments.
+//! `xflags` provides a procedural macro for parsing command line arguments.
//!
//! It is intended for use in development tools, so it emphasizes fast compile
//! times and convenience at the expense of features.
//!
-//! If you need something more fancy, consider using
-//! [`clap`](https://docs.rs/clap/2.33.3/clap/) instead.
+//! Rough decision tree for picking an argument parsing library:
//!
-//! ## Example
+//! * if you need all of the features and don't care about minimalism, use
+//! [clap](https://github.com/clap-rs/clap)
+//! * if you want to be maximally minimal, need only basic features (eg, no help
+//! generation), and want to be pedantically correct, use
+//! [lexopt](https://github.com/blyxxyz/lexopt)
+//! * if you want to get things done fast (eg, you want auto help, but not at
+//! the cost of waiting for syn to compile), consider this crate.
+//!
+//! The secret sauce of xflags is that it is the opposite of a derive macro.
+//! Rather than generating a command line grammar from a Rust struct, `xflags`
+//! generates Rust structs based on input grammar. The grammar definition is
+//! both shorter and simpler to write, and is lighter on compile times.
+//!
+//! Here's a complete example of `parse_or_exit!` macro which parses arguments
+//! into an "anonymous" struct:
+//!
+//! ```no_run
+//! use std::path::PathBuf;
+//!
+//! fn main() {
+//! let flags = xflags::parse_or_exit! {
+//! /// Remove directories and their contents recursively.
+//! optional -r,--recursive
+//! /// File or directory to remove
+//! required path: PathBuf
+//! };
+//!
+//! println!(
+//! "removing {}{}",
+//! flags.path.display(),
+//! if flags.recursive { "recursively" } else { "" },
+//! )
+//! }
+//! ```
+//!
+//! The above program, when run with `--help` argument, generates the following
+//! help:
+//!
+//! ```text
+//! ARGS:
+//! <path>
+//! File or directory to remove
+//!
+//! OPTIONS:
+//! -r, --recursive
+//! Remove directories and their contents recursively.
+//!
+//! -h, --help
+//! Prints help information.
+//! ```
+//!
+//! For larger programs, you'd typically want to use `xflags!` macro, which
+//! generates _named_ structs for you. Unlike a typical macro, `xflags` writes
+//! generated code into the source file, to make it easy to understand the rust
+//! types at a glance.
//!
//! ```
//! mod flags {
@@ -15,9 +68,8 @@
//! xflags::xflags! {
//! src "./examples/basic.rs"
//!
-//! cmd my-command
+//! cmd my-command {
//! required path: PathBuf
-//! {
//! optional -v, --verbose
//! }
//! }
@@ -28,17 +80,16 @@
//! #[derive(Debug)]
//! pub struct MyCommand {
//! pub path: PathBuf,
-//!
//! pub verbose: bool,
//! }
//!
//! impl MyCommand {
-//! pub const HELP: &'static str = Self::HELP_;
-//!
+//! pub fn from_env_or_exit() -> Self {
+//! Self::from_env_or_exit_()
+//! }
//! pub fn from_env() -> xflags::Result<Self> {
//! Self::from_env_()
//! }
-//!
//! pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
//! Self::from_vec_(args)
//! }
@@ -52,15 +103,15 @@
//! }
//! ```
//!
-//! To make the macro less opaque, `xflag` can generate `struct` describing the
-//! CLI in-place. To disable this behavior, omit the `src` attribute.
+//! If you'd rather use a typical proc-macro which generates hidden code, just
+//! omit the src attribute.
//!
//! xflags correctly handles non-utf8 arguments.
//!
//! ## Syntax Reference
//!
-//! The **cmd** keyword introduces a command that accepts positional arguments
-//! and switches.
+//! The `xflags!` macro uses **cmd** keyword to introduce a command or
+//! subcommand that accepts positional arguments and switches.
//!
//! ```
//! xflags::xflags! {
@@ -75,9 +126,9 @@
//! ```
//! xflags::xflags! {
//! cmd switches {
-//! optional -h, --help
-//! repeated --verbose
+//! optional -q,--quiet
//! required --pass-me
+//! repeated --verbose
//! }
//! }
//! ```
@@ -98,20 +149,21 @@
//! }
//! ```
//!
-//! Positional arguments are specified before the opening curly brace:
+//! Arguments without `--` in then are are positional.
//!
//! ```
//! use std::{path::PathBuf, ffi::OsString};
//!
//! xflags::xflags! {
-//! cmd positional-arguments
+//! cmd positional-arguments {
//! required program: PathBuf
//! repeated args: OsString
-//! { }
+//! }
//! }
//! ```
//!
-//! Nesting **cmd** is allowed:
+//! Nesting **cmd** is allowed. `xflag` automatically generates boilerplate
+//! enums for subcommands:
//!
//! ```ignore
//! xflags::xflags! {
@@ -148,12 +200,12 @@
//! }
//!
//! impl App {
-//! pub const HELP: &'static str = Self::HELP_;
-//!
+//! pub fn from_env_or_exit() -> Self {
+//! Self::from_env_or_exit_()
+//! }
//! pub fn from_env() -> xflags::Result<Self> {
//! Self::from_env_()
//! }
-//!
//! pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
//! Self::from_vec_(args)
//! }
@@ -161,6 +213,9 @@
//! // generated end
//! ```
//!
+//! Switches are always "inherited". Both `app -v foo` and `app foo -v` produce
+//! the same result.
+//!
//! To make subcommand name optional use the **default** keyword to mark a
//! subcommand to select if no subcommand name is passed. The name of the
//! default subcommand affects only the name of the generated Rust struct, it
@@ -176,8 +231,8 @@
//! }
//! ```
//!
-//! Commands, arguments, and switches can documented. Doc comments become a part
-//! of generated help:
+//! Commands, arguments, and switches can be documented. Doc comments become a
+//! part of generated help:
//!
//! ```
//! mod flags {
@@ -185,14 +240,11 @@
//!
//! xflags::xflags! {
//! /// Run basic system diagnostics.
-//! cmd healthck
+//! cmd healthck {
//! /// Optional configuration file.
//! optional config: PathBuf
-//! {
//! /// Verbosity level, can be repeated multiple times.
//! repeated -v, --verbose
-//! /// Print the help message.
-//! optional -h, --help
//! }
//! }
//! }
@@ -200,24 +252,18 @@
//! fn main() {
//! match flags::Healthck::from_env() {
//! Ok(flags) => {
-//! if flags.help {
-//! println!("{}", flags::Healthck::HELP);
-//! return;
-//! }
//! run_checks(flags.config, flags.verbose);
//! }
-//! Err(err) => {
-//! eprintln!("{}", err);
-//! }
+//! Err(err) => err.exit()
//! }
//! }
//!
//! # fn run_checks(_config: Option<std::path::PathBuf>, _verbosity: u32) {}
//! ```
//!
-//! The **src** keyword controlls how the code generation works. If it is
-//! absent, `xflags` acts as a typical procedure macro, which generates a bunch
-//! of structs and impls.
+//! The **src** keyword controls how the code generation works. If it is absent,
+//! `xflags` acts as a typical procedure macro, which generates a bunch of
+//! structs and impls.
//!
//! If the **src** keyword is present, it should specify the path to the file
//! with `xflags!` invocation. The path should be relative to the directory with
@@ -226,7 +272,7 @@
//! directly to the specified file.
//!
//! By convention, `xflag!` macro should be invoked from the `flags` submodule.
-//! The `flags::` preffix should be used to refer to command names. Additional
+//! The `flags::` prefix should be used to refer to command names. Additional
//! validation logic can go to the `flags` module:
//!
//! ```
@@ -250,21 +296,43 @@
//! }
//! }
//! ```
+//!
+//! The `parse_or_exit!` macro is a syntactic sure for `xflags!`, which
+//! immediately parses the argument, exiting the process if needed.
+//! `parse_or_exit` only supports single top-level command and doesn't need the
+//! `cmd` keyword.
+//!
+//! ## Limitations
+//!
+//! `xflags` follows
+//! [Fuchsia](https://fuchsia.dev/fuchsia-src/development/api/cli#command_line_arguments)
+//! conventions for command line arguments. GNU conventions such as grouping
+//! short-flags (`-xyz`) or gluing short flag and a value `(-fVAL)` are not
+//! supported.
+//!
+//! `xflags` requires the command line interface to be fully static. It's
+//! impossible to include additional flags at runtime.
+//!
+//! Implementation is not fully robust, there might be some residual bugs in
+//! edge cases.
use std::fmt;
/// Generates a parser for command line arguments from a DSL.
///
/// See the module-level for detailed syntax specification.
-pub use xflags_macros::xflags;
+pub use xflags_macros::{parse_or_exit, xflags};
pub type Result<T, E = Error> = std::result::Result<T, E>;
-/// This type represents an error that can occur during command line argument
-/// parsing.
+/// An error occurred when parssing command line arguments.
+///
+/// Either the command line was syntactically invalid, or `--help` was
+/// explicitly requested.
#[derive(Debug)]
pub struct Error {
msg: String,
+ help: bool,
}
impl fmt::Display for Error {
@@ -280,7 +348,23 @@ impl Error {
///
/// Use this to report custom validation errors.
pub fn new(message: impl Into<String>) -> Error {
- Error { msg: message.into() }
+ Error { msg: message.into(), help: false }
+ }
+
+ /// Error that carries `--help` message.
+ pub fn is_help(&self) -> bool {
+ self.help
+ }
+
+ /// Prints the error and exists the process.
+ pub fn exit(self) -> ! {
+ if self.is_help() {
+ println!("{self}");
+ std::process::exit(0)
+ } else {
+ eprintln!("{self}");
+ std::process::exit(2)
+ }
}
}
diff --git a/vendor/xflags/src/rt.rs b/vendor/xflags/src/rt.rs
index 3c33196af..988e6cc23 100644
--- a/vendor/xflags/src/rt.rs
+++ b/vendor/xflags/src/rt.rs
@@ -4,7 +4,7 @@ use crate::{Error, Result};
macro_rules! format_err {
($($tt:tt)*) => {
- Error { msg: format!($($tt)*) }
+ Error { msg: format!($($tt)*), help: false }
};
}
@@ -94,6 +94,14 @@ impl Parser {
format_err!("unexpected argument: {:?}", arg)
}
+ pub fn subcommand_required(&self) -> Error {
+ format_err!("subcommand is required")
+ }
+
+ pub fn help(&self, help: &'static str) -> Error {
+ Error { msg: help.to_string(), help: true }
+ }
+
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)
@@ -107,8 +115,4 @@ impl Parser {
}
vals.pop().ok_or_else(|| format_err!("flag is required: `{}`", flag))
}
-
- pub fn subcommand<T>(&self, cmd: Option<T>) -> Result<T> {
- cmd.ok_or_else(|| format_err!("subcommand is required"))
- }
}
diff --git a/version b/version
index d624c5395..28050fd47 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.65.0 (897e37553 2022-11-02) \ No newline at end of file
+1.66.0 (69f9c33d7 2022-12-12) \ No newline at end of file